diff options
author | Hans de Goede <hdegoede@redhat.com> | 2021-09-20 21:08:53 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2021-09-20 22:00:29 -0700 |
commit | 09182ed20c04d1b3a3a0d232d7748e745a438acd (patch) | |
tree | 879999c9c9f90afe7e2f6fd7a72fd2308ac2356c /drivers/input/touchscreen/goodix.c | |
parent | 20e317222eeabd74e9ff76cf4daf85f961f608dc (diff) | |
download | linux-09182ed20c04d1b3a3a0d232d7748e745a438acd.tar.gz linux-09182ed20c04d1b3a3a0d232d7748e745a438acd.tar.bz2 linux-09182ed20c04d1b3a3a0d232d7748e745a438acd.zip |
Input: goodix - add support for controllers without flash
Some Goodix touchscreen controllers, such as for example the GT912,
don't have flash-storage for their firmware.
These models require the OS to load the firmware at runtime, as well as
some other special handling. Add support for this to the goodix driver.
This patch was developed and tested on a Glavey TM800A550L tablet.
Note the "goodix,main-clk" and "firmware-name" device-properties used
by the new code are *not* documented in the
Documentation/devicetree/bindings/input/touchscreen/goodix.yaml
device-tree bindings for now.
Not documenting these is intentional. This is done because this code has
only been tested on x86/ACPI so far, where devicetree is not used.
Instead these properties are set through a software-fwnode attached to the
device by the drivers/platform/x86/touchscreen_dmi.c code. This means that
the use of this properties for now is purely a kernel-internal thing and
the name/working of the properties may still be changed for now.
Reviewed-by: Bastien Nocera <hadess@hadess.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20210920150643.155872-7-hdegoede@redhat.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/touchscreen/goodix.c')
-rw-r--r-- | drivers/input/touchscreen/goodix.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 75c53786516f..906b5a6b52d1 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -326,6 +326,11 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) return touch_num; } + if (data[0] == 0 && ts->firmware_name) { + if (goodix_handle_fw_request(ts)) + return 0; + } + usleep_range(1000, 2000); /* Poll every 1 - 2 ms */ } while (time_before(jiffies, max_timeout)); @@ -940,12 +945,19 @@ static void goodix_read_config(struct goodix_ts_data *ts) int x_max, y_max; int error; - error = goodix_i2c_read(ts->client, ts->chip->config_addr, - ts->config, ts->chip->config_len); - if (error) { - ts->int_trigger_type = GOODIX_INT_TRIGGER; - ts->max_touch_num = GOODIX_MAX_CONTACTS; - return; + /* + * On controllers where we need to upload the firmware + * (controllers without flash) ts->config already has the config + * at this point and the controller itself does not have it yet! + */ + if (!ts->firmware_name) { + error = goodix_i2c_read(ts->client, ts->chip->config_addr, + ts->config, ts->chip->config_len); + if (error) { + ts->int_trigger_type = GOODIX_INT_TRIGGER; + ts->max_touch_num = GOODIX_MAX_CONTACTS; + return; + } } ts->int_trigger_type = ts->config[TRIGGER_LOC] & 0x03; @@ -1139,7 +1151,16 @@ static void goodix_config_cb(const struct firmware *cfg, void *ctx) struct goodix_ts_data *ts = ctx; int error; - if (cfg) { + if (ts->firmware_name) { + if (!cfg) + goto err_release_cfg; + + error = goodix_check_cfg(ts, cfg->data, cfg->size); + if (error) + goto err_release_cfg; + + memcpy(ts->config, cfg->data, cfg->size); + } else if (cfg) { /* send device configuration to the firmware */ error = goodix_send_cfg(ts, cfg->data, cfg->size); if (error) @@ -1231,6 +1252,10 @@ reset: return error; } + error = goodix_firmware_check(ts); + if (error) + return error; + error = goodix_read_version(ts); if (error) return error; @@ -1297,6 +1322,9 @@ static int __maybe_unused goodix_suspend(struct device *dev) /* Free IRQ as IRQ pin is used as output in the suspend sequence */ goodix_free_irq(ts); + /* Save reference (calibration) info if necessary */ + goodix_save_bak_ref(ts); + /* Output LOW on the INT pin for 5 ms */ error = goodix_irq_direction_output(ts, 0); if (error) { |