diff --git a/src/drivers/intel/touch/chip.h b/src/drivers/intel/touch/chip.h index e0c78648ba..90bee4a814 100644 --- a/src/drivers/intel/touch/chip.h +++ b/src/drivers/intel/touch/chip.h @@ -4,6 +4,8 @@ #define __DRIVERS_INTEL_TOUCH_CHIP_H__ #include +#include +#include #define INTEL_THC0_NAME "THC0" #define INTEL_THC1_NAME "THC1" @@ -13,6 +15,11 @@ struct intel_thc_hidi2c_dev_info { uint64_t addr; /* Used in THC_HID_I2C mode */ uint32_t descriptor_address; + /* + * connection_speed: Indicates a recommended speed for this device; + * Otherwise, if not specified, use the speed setting from the platform. + */ + enum i2c_speed connection_speed; }; struct intel_thc_hidspi_dev_info { @@ -31,6 +38,11 @@ struct intel_thc_hidspi_dev_info { /* Touch Host Controller HID Over SPI Write Opcode */ uint32_t write_opcode; + /* + * connection_speed: indicates a recommended speed for this device; + * otherwise 0 = use speed setting from the platform. unit = Hz. + */ + uint64_t connection_speed; }; union intel_thc_dev_intf_info { @@ -48,7 +60,12 @@ struct intel_thc_dev_info { struct intel_thc_hidi2c_info { /* Device connection speed in Hz */ - uint64_t connection_speed; + enum i2c_speed connection_speed; + /* + * This maps SoC specific function for converting speed in Hz to the actual + * value for the configuration register. + */ + uint64_t (*get_soc_i2c_bus_speed_val_func)(uint32_t speed); /* Device address mode */ uint64_t addr_mode; /* Standard Mode (100 kbit/s) Serial Clock Line HIGH Period */ @@ -97,7 +114,7 @@ struct intel_thc_hidspi_info { /* * Touch Host Controller HID Over SPI Connection Speed * - * HID Over SPI Connection Speed - SPI Frequency + * HID Over SPI Connection Speed - SPI Frequency; unit = Hz */ uint32_t connection_speed; @@ -158,6 +175,7 @@ enum intel_touch_device { TH_SENSOR_NONE, TH_SENSOR_WACOM, /* BOM22 for SPI only */ TH_SENSOR_ELAN, /* BOM36 for SPI and BOM37 for I2C */ + TH_SENSOR_GOOGLE, /* ELAN9006 for SPI and ELAN6918 for I2C */ TH_SENSOR_HYNITRON, /* NYITRON for I2C only */ TH_SENSOR_GENERIC, /* for device properity thru devicetree */ TH_SENSOR_MAX diff --git a/src/drivers/intel/touch/elan.h b/src/drivers/intel/touch/elan.h index b1f3ea615d..4f7b2a1ee0 100644 --- a/src/drivers/intel/touch/elan.h +++ b/src/drivers/intel/touch/elan.h @@ -16,7 +16,8 @@ static const struct drivers_intel_touch_config elan_touch_config = { .hid = "ELAN9048", .cid = "PNP0C50", .intf.hidi2c.addr = 0x16, - .intf.hidi2c.descriptor_address = 0x1 + .intf.hidi2c.descriptor_address = 0x1, + .intf.hidi2c.connection_speed = I2C_SPEED_FAST, /* fast mode */ }, .dev_hidspi = { /* BOM36 */ .hid = "ELAN904A", @@ -29,4 +30,30 @@ static const struct drivers_intel_touch_config elan_touch_config = { }, }; +/* + * ELAN9006 is used for HID-SPI interface, while ELAN6918 is used for HID-I2C + * interface. + */ + +static const struct drivers_intel_touch_config google_touch_config = { + .sensor_dev_name = "ELAN Touch Sensor Device", + .dev_hidi2c = { /* Google's I2C-based touch */ + .hid = "ELAN6918", + .cid = "PNP0C50", + .intf.hidi2c.addr = 0x10, + .intf.hidi2c.descriptor_address = 0x1, + .intf.hidi2c.connection_speed = I2C_SPEED_FAST, /* fast mode */ + }, + .dev_hidspi = { /* Google's SPI-based touch */ + .hid = "ELAN9006", + .cid = "PNP0C51", + .intf.hidspi.connection_speed = (32 * MHz), /* unit: Hz */ + .intf.hidspi.input_report_header_address = 0x1000, + .intf.hidspi.input_report_body_address = 0x1100, + .intf.hidspi.output_report_address = 0x2000, + .intf.hidspi.read_opcode = 0xb, + .intf.hidspi.write_opcode = 0x2, + }, +}; + #endif /* __DRIVERS_TOUCH_DEV_ELAN_H__ */ diff --git a/src/drivers/intel/touch/hynitron.h b/src/drivers/intel/touch/hynitron.h index 6e34d712f2..9932bbeb65 100644 --- a/src/drivers/intel/touch/hynitron.h +++ b/src/drivers/intel/touch/hynitron.h @@ -11,7 +11,8 @@ static const struct drivers_intel_touch_config hynitron_touch_config = { .hid = "HFW68H", .cid = "PNP0C50", .intf.hidi2c.addr = 0x2c, - .intf.hidi2c.descriptor_address = 0x20 + .intf.hidi2c.descriptor_address = 0x20, + .intf.hidi2c.connection_speed = I2C_SPEED_FAST, /* fast mode */ }, }; diff --git a/src/drivers/intel/touch/touch.c b/src/drivers/intel/touch/touch.c index d0723d5dce..2310773dd3 100644 --- a/src/drivers/intel/touch/touch.c +++ b/src/drivers/intel/touch/touch.c @@ -45,6 +45,7 @@ static const struct drivers_intel_touch_config *get_driver_config(const struct d [TH_SENSOR_NONE] = &none_driver_config, [TH_SENSOR_WACOM] = &wacom_touch_config, [TH_SENSOR_ELAN] = &elan_touch_config, + [TH_SENSOR_GOOGLE] = &google_touch_config, [TH_SENSOR_HYNITRON] = &hynitron_touch_config, [TH_SENSOR_GENERIC] = config }; @@ -67,6 +68,16 @@ static const struct drivers_intel_touch_config *get_driver_config(const struct d (((const struct drivers_intel_touch_config *)(device)->chip_info)->soc_## intf .field) : \ (_soc_## intf ##_info->field)) +/* + * Device-tree definition takes precedence over static drivers device-specific over static + * drivers SoC-specific definition. + */ +#define touch_dev_soc_get(device, interface, field) \ + ((((const struct drivers_intel_touch_config *)(device)->chip_info)->dev_## interface .intf.interface.field) ? : \ + (get_driver_config(device)->dev_## interface .intf.interface.field) ? : \ + ((((const struct drivers_intel_touch_config *)(device)->chip_info)->soc_## interface .field) ? : \ + (_soc_## interface ##_info->field))) + static const char *touch_acpi_name(const struct device *dev) { return touch_get(dev, name) ? : INTEL_THC0_NAME; @@ -104,7 +115,16 @@ static const char *touch_acpi_name(const struct device *dev) acpigen_write_return_ ## type(value); \ } -touch_soc_acpigen(connection_speed, hidspi, integer, "%s: connection speed = %d\n"); +#define touch_dev_soc_acpigen(field, intf, type, fmt) \ + static void touch_acpigen_## intf ## _ ## field(void *arg) \ + { \ + const struct device *dev = (const struct device *)arg; \ + uint32_t value = touch_dev_soc_get(dev, intf, field); \ + acpigen_write_debug_sprintf(fmt, touch_acpi_name(dev), value); \ + acpigen_write_return_ ## type(value); \ + } + +touch_dev_soc_acpigen(connection_speed, hidspi, integer, "%s: connection speed = %d\n"); touch_soc_acpigen(limit_packet_size, hidspi, integer, "%s: limit packet size = %d\n"); touch_soc_acpigen(performance_limit, hidspi, integer, "%s: performance limit = %d\n"); @@ -212,11 +232,12 @@ static void touch_generate_acpi_crs(const struct drivers_intel_touch_config *con static void touch_generate_acpi_i2cdev_dsd(const struct device *dev) { int dsd_pkg_cnt; + uint64_t connection_speed_val; acpigen_write_name("ICRS"); acpigen_emit_byte(BUFFER_OP); acpigen_write_len_f(); - acpigen_write_integer(12); + acpigen_write_integer(12); /* total size of ICRS + 1 */ acpigen_pop_len(); /* Name */ acpigen_write_create_buffer_word_field("ICRS", 0x00, "DADR"); acpigen_write_create_buffer_qword_field("ICRS", 0x02, "DSPD"); @@ -225,7 +246,7 @@ static void touch_generate_acpi_i2cdev_dsd(const struct device *dev) acpigen_write_name("ISUB"); acpigen_emit_byte(BUFFER_OP); acpigen_write_len_f(); - acpigen_write_integer(145); + acpigen_write_integer(145); /* total size of ISUB + 1 */ acpigen_pop_len(); acpigen_write_create_buffer_qword_field("ISUB", 0x00, "SMHX"); acpigen_write_create_buffer_qword_field("ISUB", 0x08, "SMLX"); @@ -247,7 +268,9 @@ static void touch_generate_acpi_i2cdev_dsd(const struct device *dev) acpigen_write_create_buffer_qword_field("ISUB", 0x88, "HMSL"); acpigen_write_store_int_to_namestr(touch_get(dev, dev_hidi2c.intf.hidi2c.addr), "DADR"); - acpigen_write_store_int_to_namestr(touch_soc_get(dev, hidi2c, connection_speed), "DSPD"); + connection_speed_val = _soc_hidi2c_info->get_soc_i2c_bus_speed_val_func( + touch_dev_soc_get(dev, hidi2c, connection_speed)); + acpigen_write_store_int_to_namestr(connection_speed_val, "DSPD"); acpigen_write_store_int_to_namestr(touch_soc_get(dev, hidi2c, addr_mode), "DADM"); acpigen_write_store_int_to_namestr(touch_soc_get(dev, hidi2c, sm_scl_high_period), "SMHX"); acpigen_write_store_int_to_namestr(touch_soc_get(dev, hidi2c, sm_scl_low_period), "SMLX"); @@ -451,7 +474,6 @@ static void touch_generate_acpi_spidev_rst(const struct drivers_intel_touch_conf acpigen_write_sleep(touch_soc_get(dev, hidspi, reset_sequencing_delay)); /* De-assert RESET# GPIO. */ acpigen_disable_tx_gpio(&config->soc_hidspi.reset_gpio); - acpigen_write_sleep(100); /* Note: use 100 for now */ acpigen_write_release(TOUCH_MUTEX); } else acpigen_write_debug_sprintf("%s: _RST() empty method\n", @@ -510,10 +532,11 @@ static void touch_dev_fill_ssdt_generator(const struct device *dev) touch_generate_acpi_ini(dev); touch_generate_acpi_dsm(config, dev); /* When only THC1 is used, both THC0/1 need to be enabled since THC0's - device function is '0'. In this case, THC0 should set - connected_device to TH_SENSOR_NONE so that when the driver detects - THC0, the _DSM will be available for it to check and exit without - error. */ + * device function is '0'. In this case, THC0 should set + * connected_device to TH_SENSOR_NONE so that when the driver detects + * THC0, the _DSM will be available for it to check and exit without + * error. + */ if (config->connected_device == TH_SENSOR_NONE) return;