diff options
Diffstat (limited to 'drivers/platform/x86/touchscreen_dmi.c')
| -rw-r--r-- | drivers/platform/x86/touchscreen_dmi.c | 115 | 
1 files changed, 112 insertions, 3 deletions
diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index c6a10ec2c83f..2d9ca2292ea1 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -9,10 +9,13 @@   */  #include <linux/acpi.h> +#include <linux/ctype.h>  #include <linux/device.h>  #include <linux/dmi.h>  #include <linux/efi_embedded_fw.h>  #include <linux/i2c.h> +#include <linux/init.h> +#include <linux/kstrtox.h>  #include <linux/notifier.h>  #include <linux/property.h>  #include <linux/string.h> @@ -897,6 +900,22 @@ static const struct ts_dmi_data schneider_sct101ctm_data = {  	.properties	= schneider_sct101ctm_props,  }; +static const struct property_entry globalspace_solt_ivw116_props[] = { +	PROPERTY_ENTRY_U32("touchscreen-min-x", 7), +	PROPERTY_ENTRY_U32("touchscreen-min-y", 22), +	PROPERTY_ENTRY_U32("touchscreen-size-x", 1723), +	PROPERTY_ENTRY_U32("touchscreen-size-y", 1077), +	PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-globalspace-solt-ivw116.fw"), +	PROPERTY_ENTRY_U32("silead,max-fingers", 10), +	PROPERTY_ENTRY_BOOL("silead,home-button"), +	{ } +}; + +static const struct ts_dmi_data globalspace_solt_ivw116_data = { +	.acpi_name	= "MSSL1680:00", +	.properties	= globalspace_solt_ivw116_props, +}; +  static const struct property_entry techbite_arc_11_6_props[] = {  	PROPERTY_ENTRY_U32("touchscreen-min-x", 5),  	PROPERTY_ENTRY_U32("touchscreen-min-y", 7), @@ -1386,6 +1405,17 @@ const struct dmi_system_id touchscreen_dmi_table[] = {  		},  	},  	{ +		/* Jumper EZpad 6s Pro */ +		.driver_data = (void *)&jumper_ezpad_6_pro_b_data, +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Jumper"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Ezpad"), +			/* Above matches are too generic, add bios match */ +			DMI_MATCH(DMI_BIOS_VERSION, "E.WSA116_8.E1.042.bin"), +			DMI_MATCH(DMI_BIOS_DATE, "01/08/2020"), +		}, +	}, +	{  		/* Jumper EZpad 6 m4 */  		.driver_data = (void *)&jumper_ezpad_6_m4_data,  		.matches = { @@ -1625,6 +1655,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {  		},  	},  	{ +		/* GlobalSpace SoLT IVW 11.6" */ +		.driver_data = (void *)&globalspace_solt_ivw116_data, +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Globalspace Tech Pvt Ltd"), +			DMI_MATCH(DMI_PRODUCT_NAME, "SolTIVW"), +			DMI_MATCH(DMI_PRODUCT_SKU, "PN20170413488"), +		}, +	}, +	{  		/* Techbite Arc 11.6 */  		.driver_data = (void *)&techbite_arc_11_6_data,  		.matches = { @@ -1817,7 +1856,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {  	{ }  }; -static const struct ts_dmi_data *ts_data; +static struct ts_dmi_data *ts_data;  static void ts_dmi_add_props(struct i2c_client *client)  { @@ -1852,6 +1891,64 @@ static int ts_dmi_notifier_call(struct notifier_block *nb,  	return 0;  } +#define MAX_CMDLINE_PROPS 16 + +static struct property_entry ts_cmdline_props[MAX_CMDLINE_PROPS + 1]; + +static struct ts_dmi_data ts_cmdline_data = { +	.properties = ts_cmdline_props, +}; + +static int __init ts_parse_props(char *str) +{ +	/* Save the original str to show it on syntax errors */ +	char orig_str[256]; +	char *name, *value; +	u32 u32val; +	int i, ret; + +	strscpy(orig_str, str, sizeof(orig_str)); + +	/* +	 * str is part of the static_command_line from init/main.c and poking +	 * holes in that by writing 0 to it is allowed, as is taking long +	 * lasting references to it. +	 */ +	ts_cmdline_data.acpi_name = strsep(&str, ":"); + +	for (i = 0; i < MAX_CMDLINE_PROPS; i++) { +		name = strsep(&str, ":"); +		if (!name || !name[0]) +			break; + +		/* Replace '=' with 0 and make value point past '=' or NULL */ +		value = name; +		strsep(&value, "="); +		if (!value) { +			ts_cmdline_props[i] = PROPERTY_ENTRY_BOOL(name); +		} else if (isdigit(value[0])) { +			ret = kstrtou32(value, 0, &u32val); +			if (ret) +				goto syntax_error; + +			ts_cmdline_props[i] = PROPERTY_ENTRY_U32(name, u32val); +		} else { +			ts_cmdline_props[i] = PROPERTY_ENTRY_STRING(name, value); +		} +	} + +	if (!i || str) +		goto syntax_error; + +	ts_data = &ts_cmdline_data; +	return 1; + +syntax_error: +	pr_err("Invalid '%s' value for 'i2c_touchscreen_props='\n", orig_str); +	return 1; /* "i2c_touchscreen_props=" is still a known parameter */ +} +__setup("i2c_touchscreen_props=", ts_parse_props); +  static struct notifier_block ts_dmi_notifier = {  	.notifier_call = ts_dmi_notifier_call,  }; @@ -1859,13 +1956,25 @@ static struct notifier_block ts_dmi_notifier = {  static int __init ts_dmi_init(void)  {  	const struct dmi_system_id *dmi_id; +	struct ts_dmi_data *ts_data_dmi;  	int error;  	dmi_id = dmi_first_match(touchscreen_dmi_table); -	if (!dmi_id) +	ts_data_dmi = dmi_id ? dmi_id->driver_data : NULL; + +	if (ts_data) { +		/* +		 * Kernel cmdline provided data takes precedence, copy over +		 * DMI efi_embedded_fw info if available. +		 */ +		if (ts_data_dmi) +			ts_data->embedded_fw = ts_data_dmi->embedded_fw; +	} else if (ts_data_dmi) { +		ts_data = ts_data_dmi; +	} else {  		return 0; /* Not an error */ +	} -	ts_data = dmi_id->driver_data;  	/* Some dmi table entries only provide an efi_embedded_fw_desc */  	if (!ts_data->properties)  		return 0;  | 
