Skip to content

Commit 0b178b0

Browse files
committed
platform/x86: touchscreen_dmi: Add support for setting touchscreen properties from cmdline
On x86/ACPI platforms touchscreens mostly just work without needing any device/model specific configuration. But in some cases (mostly with Silead and Goodix touchscreens) it is still necessary to manually specify various touchscreen-properties on a per model basis. touchscreen_dmi is a special place for DMI quirks for this, but it can be challenging for users to figure out the right property values, especially for Silead touchscreens where non of these can be read back from the touchscreen-controller. ATM users can only test touchscreen properties by editing touchscreen_dmi.c and then building a completely new kernel which makes it unnecessary difficult for users to test and submit properties when necessary for their laptop / tablet model. Add support for specifying properties on the kernel commandline to allow users to easily figure out the right settings. See the added documentation in kernel-parameters.txt for the commandline syntax. Cc: Gregor Riepl <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 5d059bf commit 0b178b0

File tree

2 files changed

+98
-3
lines changed

2 files changed

+98
-3
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,28 @@
19211921
Format:
19221922
<bus_id>,<clkrate>
19231923

1924+
i2c_touchscreen_props= [HW,ACPI,X86]
1925+
Set device-properties for ACPI-enumerated I2C-attached
1926+
touchscreen, to e.g. fix coordinates of upside-down
1927+
mounted touchscreens. If you need this option please
1928+
submit a drivers/platform/x86/touchscreen_dmi.c patch
1929+
adding a DMI quirk for this.
1930+
1931+
Format:
1932+
<ACPI_HW_ID>:<prop_name>=<val>[:prop_name=val][:...]
1933+
Where <val> is one of:
1934+
Omit "=<val>" entirely Set a boolean device-property
1935+
Unsigned number Set a u32 device-property
1936+
Anything else Set a string device-property
1937+
1938+
Examples (split over multiple lines):
1939+
i2c_touchscreen_props=GDIX1001:touchscreen-inverted-x:
1940+
touchscreen-inverted-y
1941+
1942+
i2c_touchscreen_props=MSSL1680:touchscreen-size-x=1920:
1943+
touchscreen-size-y=1080:touchscreen-inverted-y:
1944+
firmware-name=gsl1680-vendor-model.fw:silead,home-button
1945+
19241946
i8042.debug [HW] Toggle i8042 debug mode
19251947
i8042.unmask_kbd_data
19261948
[HW] Enable printing of interrupt data from the KBD port

drivers/platform/x86/touchscreen_dmi.c

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
*/
1010

1111
#include <linux/acpi.h>
12+
#include <linux/ctype.h>
1213
#include <linux/device.h>
1314
#include <linux/dmi.h>
1415
#include <linux/efi_embedded_fw.h>
1516
#include <linux/i2c.h>
17+
#include <linux/init.h>
18+
#include <linux/kstrtox.h>
1619
#include <linux/notifier.h>
1720
#include <linux/property.h>
1821
#include <linux/string.h>
@@ -1817,7 +1820,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
18171820
{ }
18181821
};
18191822

1820-
static const struct ts_dmi_data *ts_data;
1823+
static struct ts_dmi_data *ts_data;
18211824

18221825
static void ts_dmi_add_props(struct i2c_client *client)
18231826
{
@@ -1852,20 +1855,90 @@ static int ts_dmi_notifier_call(struct notifier_block *nb,
18521855
return 0;
18531856
}
18541857

1858+
#define MAX_CMDLINE_PROPS 16
1859+
1860+
static struct property_entry ts_cmdline_props[MAX_CMDLINE_PROPS + 1];
1861+
1862+
static struct ts_dmi_data ts_cmdline_data = {
1863+
.properties = ts_cmdline_props,
1864+
};
1865+
1866+
static int __init ts_parse_props(char *str)
1867+
{
1868+
/* Save the original str to show it on syntax errors */
1869+
char orig_str[256];
1870+
char *name, *value;
1871+
u32 u32val;
1872+
int i, ret;
1873+
1874+
strscpy(orig_str, str, sizeof(orig_str));
1875+
1876+
/*
1877+
* str is part of the static_command_line from init/main.c and poking
1878+
* holes in that by writing 0 to it is allowed, as is taking long
1879+
* lasting references to it.
1880+
*/
1881+
ts_cmdline_data.acpi_name = strsep(&str, ":");
1882+
1883+
for (i = 0; i < MAX_CMDLINE_PROPS; i++) {
1884+
name = strsep(&str, ":");
1885+
if (!name || !name[0])
1886+
break;
1887+
1888+
/* Replace '=' with 0 and make value point past '=' or NULL */
1889+
value = name;
1890+
strsep(&value, "=");
1891+
if (!value) {
1892+
ts_cmdline_props[i] = PROPERTY_ENTRY_BOOL(name);
1893+
} else if (isdigit(value[0])) {
1894+
ret = kstrtou32(value, 0, &u32val);
1895+
if (ret)
1896+
goto syntax_error;
1897+
1898+
ts_cmdline_props[i] = PROPERTY_ENTRY_U32(name, u32val);
1899+
} else {
1900+
ts_cmdline_props[i] = PROPERTY_ENTRY_STRING(name, value);
1901+
}
1902+
}
1903+
1904+
if (!i || str)
1905+
goto syntax_error;
1906+
1907+
ts_data = &ts_cmdline_data;
1908+
return 1;
1909+
1910+
syntax_error:
1911+
pr_err("Invalid '%s' value for 'i2c_touchscreen_props='\n", orig_str);
1912+
return 1; /* "i2c_touchscreen_props=" is still a known parameter */
1913+
}
1914+
__setup("i2c_touchscreen_props=", ts_parse_props);
1915+
18551916
static struct notifier_block ts_dmi_notifier = {
18561917
.notifier_call = ts_dmi_notifier_call,
18571918
};
18581919

18591920
static int __init ts_dmi_init(void)
18601921
{
18611922
const struct dmi_system_id *dmi_id;
1923+
struct ts_dmi_data *ts_data_dmi;
18621924
int error;
18631925

18641926
dmi_id = dmi_first_match(touchscreen_dmi_table);
1865-
if (!dmi_id)
1927+
ts_data_dmi = dmi_id ? dmi_id->driver_data : NULL;
1928+
1929+
if (ts_data) {
1930+
/*
1931+
* Kernel cmdline provided data takes precedence, copy over
1932+
* DMI efi_embedded_fw info if available.
1933+
*/
1934+
if (ts_data_dmi)
1935+
ts_data->embedded_fw = ts_data_dmi->embedded_fw;
1936+
} else if (ts_data_dmi) {
1937+
ts_data = ts_data_dmi;
1938+
} else {
18661939
return 0; /* Not an error */
1940+
}
18671941

1868-
ts_data = dmi_id->driver_data;
18691942
/* Some dmi table entries only provide an efi_embedded_fw_desc */
18701943
if (!ts_data->properties)
18711944
return 0;

0 commit comments

Comments
 (0)