| From 7574c0db2e68c4d0bae9d415a683bdd8b2a761e9 Mon Sep 17 00:00:00 2001 |
| From: Hans de Goede <hdegoede@redhat.com> |
| Date: Wed, 13 Nov 2019 19:29:38 +0100 |
| Subject: i2c: acpi: Force bus speed to 400KHz if a Silead touchscreen is present |
| |
| From: Hans de Goede <hdegoede@redhat.com> |
| |
| commit 7574c0db2e68c4d0bae9d415a683bdd8b2a761e9 upstream. |
| |
| Many cheap devices use Silead touchscreen controllers. Testing has shown |
| repeatedly that these touchscreen controllers work fine at 400KHz, but for |
| unknown reasons do not work properly at 100KHz. This has been seen on |
| both ARM and x86 devices using totally different i2c controllers. |
| |
| On some devices the ACPI tables list another device at the same I2C-bus |
| as only being capable of 100KHz, testing has shown that these other |
| devices work fine at 400KHz (as can be expected of any recent I2C hw). |
| |
| This commit makes i2c_acpi_find_bus_speed() always return 400KHz if a |
| Silead touchscreen controller is present, fixing the touchscreen not |
| working on devices which ACPI tables' wrongly list another device on the |
| same bus as only being capable of 100KHz. |
| |
| Specifically this fixes the touchscreen on the Jumper EZpad 6 m4 not |
| working. |
| |
| Reported-by: youling 257 <youling257@gmail.com> |
| Tested-by: youling 257 <youling257@gmail.com> |
| Signed-off-by: Hans de Goede <hdegoede@redhat.com> |
| Reviewed-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> |
| Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> |
| [wsa: rewording warning a little] |
| Signed-off-by: Wolfram Sang <wsa@the-dreams.de> |
| Cc: stable@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/i2c/i2c-core-acpi.c | 28 +++++++++++++++++++++++++++- |
| 1 file changed, 27 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/i2c/i2c-core-acpi.c |
| +++ b/drivers/i2c/i2c-core-acpi.c |
| @@ -43,6 +43,7 @@ struct i2c_acpi_lookup { |
| int index; |
| u32 speed; |
| u32 min_speed; |
| + u32 force_speed; |
| }; |
| |
| static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) |
| @@ -240,6 +241,19 @@ i2c_acpi_match_device(const struct acpi_ |
| return acpi_match_device(matches, &client->dev); |
| } |
| |
| +static const struct acpi_device_id i2c_acpi_force_400khz_device_ids[] = { |
| + /* |
| + * These Silead touchscreen controllers only work at 400KHz, for |
| + * some reason they do not work at 100KHz. On some devices the ACPI |
| + * tables list another device at their bus as only being capable |
| + * of 100KHz, testing has shown that these other devices work fine |
| + * at 400KHz (as can be expected of any recent i2c hw) so we force |
| + * the speed of the bus to 400 KHz if a Silead device is present. |
| + */ |
| + { "MSSL1680", 0 }, |
| + {} |
| +}; |
| + |
| static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level, |
| void *data, void **return_value) |
| { |
| @@ -258,6 +272,9 @@ static acpi_status i2c_acpi_lookup_speed |
| if (lookup->speed <= lookup->min_speed) |
| lookup->min_speed = lookup->speed; |
| |
| + if (acpi_match_device_ids(adev, i2c_acpi_force_400khz_device_ids) == 0) |
| + lookup->force_speed = 400000; |
| + |
| return AE_OK; |
| } |
| |
| @@ -295,7 +312,16 @@ u32 i2c_acpi_find_bus_speed(struct devic |
| return 0; |
| } |
| |
| - return lookup.min_speed != UINT_MAX ? lookup.min_speed : 0; |
| + if (lookup.force_speed) { |
| + if (lookup.force_speed != lookup.min_speed) |
| + dev_warn(dev, FW_BUG "DSDT uses known not-working I2C bus speed %d, forcing it to %d\n", |
| + lookup.min_speed, lookup.force_speed); |
| + return lookup.force_speed; |
| + } else if (lookup.min_speed != UINT_MAX) { |
| + return lookup.min_speed; |
| + } else { |
| + return 0; |
| + } |
| } |
| EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed); |
| |