Message ID | 20250103051657.211966-2-rha051117@gmail.com |
---|---|
State | New |
Headers | show |
Series | [1/1] Force ELAN06FA touchpad I2C bus freq to 100KHz | expand |
On Fri, Jan 03, 2025 at 05:46:27PM -0600, R Ha wrote: > Hello, > > Thanks for reading my patch! > > On Fri, Jan 3, 2025 at 3:33 AM Mika Westerberg > <mika.westerberg@linux.intel.com> wrote: > > What are those "some devices" and "some controllers"? > > The "Some Devices" are the Lenovo V15 G4 IRU, which I use, and > potentially the Lenovo V15 G4 AMN and Lenovo Ideapad Slim 3 15IAH8 as > well (based on issue reports from other users [1]). > The "Some Controllers" are the Designware I2C controller. > > Sorry for not putting this in the commit message; I had tried to > follow the comments for the quirk I copied in Commit 7574c0db2e68c > ("i2c: acpi: Force bus speed to 400KHz if a Silead touchscreen is > present"), which left them out. In general it is good to follow the existing changelogs but in this case I would prefer to add the details of the system in question (so we know what systems the quirk is applied to). > On Fri, Jan 3, 2025 at 3:33 AM Mika Westerberg > <mika.westerberg@linux.intel.com> wrote: > > Can you add the ACPI table snippet here too for reference? > > I believe this is the correct snippet in my ACPI table (Again, V15 G4 > IRU). Tried to edit it down as much as I could, hopefully this tells > everything. Please let me know how I should attach a longer snippet or > the full ACPI table if needed. Okay thanks for sharing. I don't see the "SPED" beeing assigned in the below snipped though. I would expect this works in Windows? Have you checked if it uses 100 kHz or 400kHz there? > Scope (_SB.PC00.I2C1) > { > [...] > Device (TPD0) > { > [...] > CreateWordField (SBFB, \_SB.PC00.I2C1.TPD0._Y53._ADR, BADR) > // _ADR: Address > CreateDWordField (SBFB, \_SB.PC00.I2C1.TPD0._Y53._SPE, SPED) > // _SPE: Speed > CreateWordField (SBFG, 0x17, INT1) > CreateDWordField (SBFI, \_SB.PC00.I2C1.TPD0._Y54._INT, INT2) > // _INT: Interrupts > Method (_INI, 0, NotSerialized) // _INI: Initialize > { > If ((OSYS < 0x07DC)) > { > SRXO (0x09080011, One) > } > > INT1 = GNUM (0x09080011) > INT2 = INUM (0x09080011) > If ((TPTY == One)) > { > _HID = "ELAN06FA" > _SUB = "ELAN0001" > BADR = 0x15 > HID2 = One > Return (Zero) > } > [...] > } > > Name (_HID, "XXXX0000") // _HID: Hardware ID > Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */) // > _CID: Compatible ID > Name (_SUB, "XXXX0000") // _SUB: Subsystem ID > Name (_S0W, 0x03) // _S0W: S0 Device Wake State > Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method > { > If ((Arg0 == HIDG)) > { > Return (HIDD (Arg0, Arg1, Arg2, Arg3, HID2)) > } > > If ((Arg0 == TP7G)) > { > Return (TP7D (Arg0, Arg1, Arg2, Arg3, SBFB, SBFG)) > } > > Return (Buffer (One) > { > 0x00 // . > }) > } > [...] > Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings > { > If ((OSYS < 0x07DC)) > { > Return (SBFI) /* \_SB_.PC00.I2C1.TPD0.SBFI */ > } > > If ((TPDM == Zero)) > { > Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFG)) > } > > Return (ConcatenateResTemplate (I2CM (I2CX, BADR, SPED), SBFI)) > } > [...] > } > } > > For comparison, the properties for a device that I think did set a > proper speed was like this: > If ((TPNP == 0xD64D)) > { > _HID = "GTCH7503" > HID2 = One > BADR = 0x10 > SPED = 0x000F4240 > Return (Zero) > } > > [1]: https://bbs.archlinux.org/viewtopic.php?id=297092
On Sun, Jan 5, 2025 at 2:34 AM Mika Westerberg <mika.westerberg@linux.intel.com> wrote: > I would expect this works in Windows? Have you > checked if it uses 100 kHz or 400kHz there? The touchpad does work in Windows. I couldn't find a way to check the frequency there. I think that I need to do some more investigation into how I can find the "proper" frequency, though if anyone has any tips I would appreciate them greatly. In Windows, my touchpad does not have a vendor-provided driver, but uses the default I2C HID driver provided by Microsoft. Actually, my touchpad is registered as two devices: An "I2C HID Device" using the default "HIDI2C.inf" driver, and an "HID-compliant touch pad", using the default "input.inf" driver. Both were provided by Microsoft, so it appears there is no vendor-specific firmware here. I initially assumed that the driver would default to 100KHz (as being the lowest speed defined in drivers/i2c/busses/i2c-designware-common.c), but after reading Microsoft's documentation for I2C HID devices it appears that they recommend 400KHz or more [1]. After reading this, I tried forcing the speed to 1MHz in the kernel, which surprisingly also alleviated the laggy behavior. So it appears that the speed can be either 100KHz or 1MHz, but I think that in Windows it should be whatever the "default" defined by the Windows driver is. I tried finding the I2C frequency using the steps defined in the Microsoft guide to tracing I2C HID events using Logman [2], and this was (what I believe to be) the relevant snippet for setting up the I2C device, though it does not appear there is anything related to the controller frequency: [1]0004.0140::01/06/2025-02:34:21.359 [hidi2c][WDFDEVICE:0x000018796F20AFD8] Received WDFREQUEST 0x000018797575D918 (IOCTL_HID_READ_REPORT) on WDFQUEUE 0x000018796F20AC08 [1]0004.0140::01/06/2025-02:34:21.368 [hidi2c][WDFDEVICE:0x000018796F20AFD8] Error retrieving read WDFREQUEST 0x0000000000000000 from ReportQueue on interrupt status:0x8000001a(STATUS_NO_MORE_ENTRIES) [3]0004.3184::01/06/2025-02:34:21.369 [hidi2c][WDFDEVICE:0x000018796F20AFD8] D0Exit to target state D4 [0]0004.3184::01/06/2025-02:34:21.369 [hidi2c][WDFDEVICE:0x000018796F20AFD8] Power command (opcode:0x801) sent to device register 0x5 [0]0004.3184::01/06/2025-02:34:21.369 [hidi2c][WDFDEVICE:0x000018796F20AFD8] Successfully put device into sleep power state [0]0004.3184::01/06/2025-02:34:21.369 [hidi2c][WDFDEVICE:0x000018796F20AFD8] Deinitialized device HID state [0]0004.3184::01/06/2025-02:34:21.369 [hidi2c][WDFDEVICE:0x000018796F20AFD8] WdfObjectDelete closed and deleted SpbIoTarget [1]0004.0150::01/06/2025-02:34:23.172 [hidi2c]Created WDF driver object:0xFFFFE78696EE0E30 [3]0004.0150::01/06/2025-02:34:23.180 [hidi2c][WDFDEVICE:0x00001879716173C8] Created new device [1]0004.2364::01/06/2025-02:34:23.183 [hidi2c][WDFDEVICE:0x00001879716173C8] I2C resource found at index 0 with connection id: 0x1 [1]0004.2364::01/06/2025-02:34:23.183 [hidi2c][WDFDEVICE:0x00001879716173C8] Interrupt resource found at index 1 [1]0004.2364::01/06/2025-02:34:23.183 [hidi2c][WDFDEVICE:0x00001879716173C8] Created Spb IO Target and resources [1]0004.2364::01/06/2025-02:34:23.184 [hidi2c][WDFDEVICE:0x00001879716173C8] Found supported DSM function:1 [1]0004.2364::01/06/2025-02:34:23.184 [hidi2c][WDFDEVICE:0x00001879716173C8] HID Descriptor register address 0x1 retrieved from ACPI [1]0004.2364::01/06/2025-02:34:23.184 [hidi2c][WDFDEVICE:0x00001879716173C8] D0Entry from from previous state D4 [1]0004.2364::01/06/2025-02:34:23.185 [hidi2c][WDFDEVICE:0x00001879716173C8] HID descriptor retrieved from register 0x1 : LEN 30 VER 0x100 VID 0x4f3 PID 0x32b9 VER 0x4 RDL 679 RDA 0x2 IRA 0x3 IRML 31 ORA 0x4 ORML 0 CRA 0x5 DRA 0x6 [1]0004.2364::01/06/2025-02:34:23.185 [hidi2c][WDFDEVICE:0x00001879716173C8] Initialized device HID state [3]0004.2364::01/06/2025-02:34:23.185 [hidi2c][WDFDEVICE:0x00001879716173C8] Power command (opcode:0x800) sent to device register 0x5 [3]0004.2364::01/06/2025-02:34:23.185 [hidi2c][WDFDEVICE:0x00001879716173C8] Successfully put device into on power state [3]0004.2364::01/06/2025-02:34:23.185 [hidi2c][WDFDEVICE:0x00001879716173C8] WdfIoQueueRetrieveNextRequest failed to find idle notification request in IdleQueue WDFQUEUE 0x000018796F1CCFD8 status:0x8000001a(STATUS_NO_MORE_ENTRIES) [1]0004.2364::01/06/2025-02:34:23.186 [hidi2c][WDFDEVICE:0x00001879716173C8] Failed querying registry value for DoNotWaitForResetResponsestatus:0xc0000034(STATUS_OBJECT_NAME_NOT_FOUND) [1]0004.2364::01/06/2025-02:34:23.186 [hidi2c][WDFDEVICE:0x00001879716173C8] Starting timer for reset response - IO queue stopped [1]0004.2364::01/06/2025-02:34:23.186 [hidi2c][WDFDEVICE:0x00001879716173C8] Reset command sent to device register 0x5 [0]0004.0140::01/06/2025-02:34:23.188 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC4C48 (IOCTL_HID_GET_DEVICE_DESCRIPTOR) on WDFQUEUE 0x000018796258EA28 [0]0004.0140::01/06/2025-02:34:23.188 [hidi2c][WDFDEVICE:0x00001879716173C8] Returning device descriptor to hidclass, report descriptor length 679 [0]0004.0140::01/06/2025-02:34:23.188 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC4C48 (IOCTL_HID_GET_DEVICE_DESCRIPTOR) with STATUS_SUCCESS [0]0004.0140::01/06/2025-02:34:23.188 [hidi2c][WDFDEVICE:0x00001879716173C8] Received reset response - starting IO queue [3]0004.0150::01/06/2025-02:34:23.189 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC4C48 (IOCTL_HID_GET_DEVICE_ATTRIBUTES) on WDFQUEUE 0x000018796258EA28 [3]0004.0150::01/06/2025-02:34:23.189 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC4C48 (IOCTL_HID_GET_DEVICE_ATTRIBUTES) with STATUS_SUCCESS [3]0004.0150::01/06/2025-02:34:23.189 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC4C48 (IOCTL_HID_GET_REPORT_DESCRIPTOR) on WDFQUEUE 0x000018796258EA28 [3]0004.0150::01/06/2025-02:34:23.209 [hidi2c][WDFDEVICE:0x00001879716173C8] Report descriptor of length 679 retrieved from register 0x2 [3]0004.0150::01/06/2025-02:34:23.209 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC4C48 (IOCTL_HID_GET_REPORT_DESCRIPTOR) with STATUS_SUCCESS [3]0004.0150::01/06/2025-02:34:23.209 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC4C48 (IOCTL_HID_READ_REPORT) on WDFQUEUE 0x000018796258EA28 [3]0004.0150::01/06/2025-02:34:23.209 [hidi2c][WDFDEVICE:0x00001879716173C8] Received first ping pong read - enabling interrupt processing [3]0004.0150::01/06/2025-02:34:23.209 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC48C8 (IOCTL_HID_READ_REPORT) on WDFQUEUE 0x000018796258EA28 [2]0790.0A3C::01/06/2025-02:34:23.225 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC5A48 (IOCTL_HID_GET_STRING) on WDFQUEUE 0x000018796258EA28 [2]0790.0A3C::01/06/2025-02:34:23.225 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC5A48 (IOCTL_HID_GET_STRING) with STATUS_SUCCESS [2]0790.0A3C::01/06/2025-02:34:23.225 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC5A48 (IOCTL_HID_GET_FEATURE) on WDFQUEUE 0x000018796258EA28 [0]0790.0A3C::01/06/2025-02:34:23.233 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC5A48 (IOCTL_HID_GET_FEATURE) with STATUS_SUCCESS [0]0790.0A3C::01/06/2025-02:34:23.234 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC5A48 (IOCTL_HID_GET_FEATURE) on WDFQUEUE 0x000018796258EA28 [2]0790.0A3C::01/06/2025-02:34:23.242 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC5A48 (IOCTL_HID_GET_FEATURE) with STATUS_SUCCESS [2]0790.0A3C::01/06/2025-02:34:23.242 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC5A48 (IOCTL_HID_DEVICERESET_NOTIFICATION) on WDFQUEUE 0x000018796258EA28 [2]0790.0A3C::01/06/2025-02:34:23.242 [hidi2c][WDFDEVICE:0x00001879716173C8] Pended device reset notification WDFREQUEST 0x0000187962CC5A48 to WDFQUEUE 0x0000187967F9EB08 [8]0004.020C::01/06/2025-02:34:23.243 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC3208 (IOCTL_HID_SET_FEATURE) on WDFQUEUE 0x000018796258EA28 [0]0004.0300::01/06/2025-02:34:23.243 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC1608 (IOCTL_HID_SET_FEATURE) on WDFQUEUE 0x000018796258EA28 [2]0004.020C::01/06/2025-02:34:23.244 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC3208 (IOCTL_HID_SET_FEATURE) with STATUS_SUCCESS [2]0004.0300::01/06/2025-02:34:23.244 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC1608 (IOCTL_HID_SET_FEATURE) with STATUS_SUCCESS [2]0790.0A3C::01/06/2025-02:34:23.247 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC1608 (IOCTL_HID_SET_FEATURE) on WDFQUEUE 0x000018796258EA28 [8]0004.0300::01/06/2025-02:34:23.247 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC3208 (IOCTL_HID_SET_FEATURE) on WDFQUEUE 0x000018796258EA28 [9]0004.020C::01/06/2025-02:34:23.247 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC0F08 (IOCTL_HID_SET_FEATURE) on WDFQUEUE 0x000018796258EA28 [2]0790.0A3C::01/06/2025-02:34:23.247 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC1608 (IOCTL_HID_SET_FEATURE) with STATUS_SUCCESS [2]0004.0300::01/06/2025-02:34:23.248 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC3208 (IOCTL_HID_SET_FEATURE) with STATUS_SUCCESS [2]0004.020C::01/06/2025-02:34:23.248 [hidi2c][WDFDEVICE:0x00001879716173C8] Completing WDFREQUEST 0x0000187962CC0F08 (IOCTL_HID_SET_FEATURE) with STATUS_SUCCESS [3]0004.0140::01/06/2025-02:34:23.267 [hidi2c][WDFDEVICE:0x00001879716173C8] Received WDFREQUEST 0x0000187962CC0F08 (IOCTL_HID_READ_REPORT) on WDFQUEUE 0x000018796258EA28 [1]: https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/touchpad-device-bus-connectivity#acpi-table-entries [2]: https://learn.microsoft.com/en-us/windows-hardware/drivers/hid/event-tracing#using-logmanexe
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 14ae0cfc325e..b10f52e12fe8 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -355,6 +355,18 @@ static const struct acpi_device_id i2c_acpi_force_400khz_device_ids[] = { {} }; +static const struct acpi_device_id i2c_acpi_force_100khz_device_ids[] = { + /* + * When a 400KHz freq is used on this model of ELAN touchpad instead + * of 100Khz, excessive smoothing (similar to when there is noise in + * the signal) is intermittently applied. As some devices' ACPI + * tables do not specify the 100KHz frequency requirement, it is + * necessary to force the speed to 100KHz. + */ + { "ELAN06FA", 0 }, + {} +}; + static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level, void *data, void **return_value) { @@ -373,6 +385,9 @@ static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level, if (acpi_match_device_ids(adev, i2c_acpi_force_400khz_device_ids) == 0) lookup->force_speed = I2C_MAX_FAST_MODE_FREQ; + if (acpi_match_device_ids(adev, i2c_acpi_force_100khz_device_ids) == 0) + lookup->force_speed = I2C_MAX_STANDARD_MODE_FREQ; + return AE_OK; }
Some devices do not define valid bus frequencies for the ELAN06FA touchpad in their ACPI table, and some controllers run them at 400KHz by default. The 06FA touchpad exhibits excessive smoothing behaviors when run at 400KHz, so force the bus frequency to 100KHz. Signed-off-by: Randolph Ha <rha051117@gmail.com> --- drivers/i2c/i2c-core-acpi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)