drivers/intel/touch: Enhance Intel touch driver for new devices
Enhancements have been made to the Intel touch driver, including support for Google touchscreen devices, ELAN9006 and ELAN6918. The update also includes device-specific configuration changes for both I2C and SPI interfaces. Key improvements include: - Google Touchscreen support integration for ELAN9006 (SPI) and ELAN6918 (I2C). - Specification of recommended connection speeds for supported devices. - Removal of an unnecessary 100ms delay in the SPI _RST method. - Addition of a function to map the System on Chip's (SoC) I2C speed frequency. - Improved device-specific connection speed settings for both I2C and SPI interfaces. These changes aim to improve the driver’s compatibility and efficiency when interacting with the newly supported devices. BUG=none TEST=Test the updated driver on devices using ELAN9006 and ELAN6918 to verify improved responsiveness and correct device initialization. Confirm that connection speeds are set as recommended and check the absence of the previously unnecessary delay in SPI operations from the SSDT. Change-Id: Ie35de90ece44101aea008d13d19e12873cdc09bf Signed-off-by: Cliff Huang <cliff.huang@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/89180 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com>
This commit is contained in:
parent
55bf4ea07e
commit
f1708cf21a
4 changed files with 82 additions and 13 deletions
|
|
@ -4,6 +4,8 @@
|
|||
#define __DRIVERS_INTEL_TOUCH_CHIP_H__
|
||||
|
||||
#include <acpi/acpi_device.h>
|
||||
#include <commonlib/bsd/helpers.h>
|
||||
#include <device/i2c.h>
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue