2017-01-23 20:35:30 +03:00
/*
* 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 ;
2017-03-22 18:55:53 +03:00
const struct property_entry * properties ;
2017-01-23 20:35:30 +03:00
} ;
2017-03-22 18:55:53 +03:00
static const struct property_entry cube_iwork8_air_props [ ] = {
2017-01-23 20:35:30 +03:00
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 ,
} ;
2017-03-22 18:55:53 +03:00
static const struct property_entry jumper_ezpad_mini3_props [ ] = {
2017-01-23 20:35:30 +03:00
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 ,
} ;
2017-03-22 18:55:54 +03:00
static const struct property_entry dexp_ursus_7w_props [ ] = {
PROPERTY_ENTRY_U32 ( " touchscreen-size-x " , 890 ) ,
PROPERTY_ENTRY_U32 ( " touchscreen-size-y " , 630 ) ,
PROPERTY_ENTRY_STRING ( " firmware-name " , " gsl1686-dexp-ursus-7w.fw " ) ,
PROPERTY_ENTRY_U32 ( " silead,max-fingers " , 10 ) ,
{ }
} ;
static const struct silead_ts_dmi_data dexp_ursus_7w_data = {
. acpi_name = " MSSL1680:00 " ,
. properties = dexp_ursus_7w_props ,
} ;
2017-01-23 20:35:30 +03:00
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 " ) ,
} ,
} ,
2017-03-22 18:55:54 +03:00
{
/* DEXP Ursus 7W */
. driver_data = ( void * ) & dexp_ursus_7w_data ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Insyde " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " 7W " ) ,
} ,
} ,
2017-01-23 20:35:30 +03:00
{ } ,
} ;
2017-04-04 06:25:13 +03:00
static void silead_ts_dmi_add_props ( struct i2c_client * client )
2017-01-23 20:35:30 +03:00
{
2017-04-04 06:25:13 +03:00
struct device * dev = & client - > dev ;
2017-01-23 20:35:30 +03:00
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 ;
2017-04-04 06:25:13 +03:00
struct i2c_client * client ;
2017-01-23 20:35:30 +03:00
switch ( action ) {
case BUS_NOTIFY_ADD_DEVICE :
2017-04-04 06:25:13 +03:00
client = i2c_verify_client ( dev ) ;
if ( client )
silead_ts_dmi_add_props ( client ) ;
2017-01-23 20:35:30 +03:00
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 ) ;