Commit cef9dd85 authored by Hans de Goede's avatar Hans de Goede Committed by Andy Shevchenko

platform/x86: add support for devices with Silead touchscreens

On ACPI based tablets, the ACPI touchscreen node only contains info on
the gpio and the irq, and is missing any info on the axis. This info is
expected to be built into the tablet model specific version of the driver
shipped with the os-image for the device.

Add support for getting the missing info from a table built into the
driver, using dmi data to identify which entry of the table to use and
add info for the CUBE iwork8 Air and Jumper EZpad mini3 tablets on which
this code was tested / developed.

BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=187531Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
[dmitry.torokhov@gmail.com: Move to platform/x86]
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
[andy: fixed merge conflict]
Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
parent 1cfd3ba0
...@@ -11271,6 +11271,14 @@ F: drivers/media/usb/siano/ ...@@ -11271,6 +11271,14 @@ F: drivers/media/usb/siano/
F: drivers/media/usb/siano/ F: drivers/media/usb/siano/
F: drivers/media/mmc/siano/ F: drivers/media/mmc/siano/
SILEAD TOUCHSCREEN DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/input/touchscreen/silead.c
F: drivers/platform/x86/silead_dmi.c
SIMPLEFB FB DRIVER SIMPLEFB FB DRIVER
M: Hans de Goede <hdegoede@redhat.com> M: Hans de Goede <hdegoede@redhat.com>
L: linux-fbdev@vger.kernel.org L: linux-fbdev@vger.kernel.org
......
...@@ -1084,4 +1084,15 @@ config INTEL_TURBO_MAX_3 ...@@ -1084,4 +1084,15 @@ config INTEL_TURBO_MAX_3
This driver is only required when the system is not using Hardware This driver is only required when the system is not using Hardware
P-States (HWP). In HWP mode, priority can be read from ACPI tables. P-States (HWP). In HWP mode, priority can be read from ACPI tables.
config SILEAD_DMI
bool "Tablets with Silead touchscreens"
depends on ACPI && DMI && I2C && INPUT
---help---
Certain ACPI based tablets with Silead touchscreens do not have
enough data in ACPI tables for the touchscreen driver to handle
the touchscreen properly, as OEMs expected the data to be baked
into the tablet model specific version of the driver shipped
with the OS-image for the device. This option supplies the missing
information. Enable this for x86 tablets with Silead touchscreens.
endif # X86_PLATFORM_DEVICES endif # X86_PLATFORM_DEVICES
...@@ -66,6 +66,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o ...@@ -66,6 +66,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o
obj-$(CONFIG_SILEAD_DMI) += silead_dmi.o
obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o
obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
......
/*
* Silead touchscreen driver DMI based configuration code
*
* Copyright (c) 2017 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Red Hat authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/notifier.h>
#include <linux/property.h>
#include <linux/string.h>
struct silead_ts_dmi_data {
const char *acpi_name;
struct property_entry *properties;
};
static struct property_entry cube_iwork8_air_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
{ }
};
static const struct silead_ts_dmi_data cube_iwork8_air_data = {
.acpi_name = "MSSL1680:00",
.properties = cube_iwork8_air_props,
};
static struct property_entry jumper_ezpad_mini3_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
{ }
};
static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = {
.acpi_name = "MSSL1680:00",
.properties = jumper_ezpad_mini3_props,
};
static const struct dmi_system_id silead_ts_dmi_table[] = {
{
/* CUBE iwork8 Air */
.driver_data = (void *)&cube_iwork8_air_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "cube"),
DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"),
DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
},
},
{
/* Jumper EZpad mini3 */
.driver_data = (void *)&jumper_ezpad_mini3_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
/* jumperx.T87.KFBNEEA02 with the version-nr dropped */
DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
},
},
{ },
};
static void silead_ts_dmi_add_props(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
const struct dmi_system_id *dmi_id;
const struct silead_ts_dmi_data *ts_data;
int error;
dmi_id = dmi_first_match(silead_ts_dmi_table);
if (!dmi_id)
return;
ts_data = dmi_id->driver_data;
if (has_acpi_companion(dev) &&
!strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
error = device_add_properties(dev, ts_data->properties);
if (error)
dev_err(dev, "failed to add properties: %d\n", error);
}
}
static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
switch (action) {
case BUS_NOTIFY_ADD_DEVICE:
silead_ts_dmi_add_props(dev);
break;
default:
break;
}
return 0;
}
static struct notifier_block silead_ts_dmi_notifier = {
.notifier_call = silead_ts_dmi_notifier_call,
};
static int __init silead_ts_dmi_init(void)
{
int error;
error = bus_register_notifier(&i2c_bus_type, &silead_ts_dmi_notifier);
if (error)
pr_err("%s: failed to register i2c bus notifier: %d\n",
__func__, error);
return error;
}
/*
* We are registering out notifier after i2c core is initialized and i2c bus
* itself is ready (which happens at postcore initcall level), but before
* ACPI starts enumerating devices (at subsys initcall level).
*/
arch_initcall(silead_ts_dmi_init);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment