OSDN Git Service

Input: goodix - save a copy of the config from goodix_read_config()
authorHans de Goede <hdegoede@redhat.com>
Tue, 24 Mar 2020 18:29:26 +0000 (11:29 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 24 Mar 2020 22:07:54 +0000 (15:07 -0700)
Save a copy of the config in goodix_read_config(), this is a preparation
patch for restoring the config if it was lost after a supend/resume cycle.

BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1786317
BugLink: https://github.com/nexus511/gpd-ubuntu-packages/issues/10
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199207
Reviewed-by: Bastien Nocera <hadess@hadess.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20200307121505.3707-8-hdegoede@redhat.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/touchscreen/goodix.c

index e03ecaf..7e31893 100644 (file)
@@ -72,6 +72,7 @@ struct goodix_chip_data {
        u16 config_addr;
        int config_len;
        int (*check_config)(struct goodix_ts_data *, const struct firmware *);
+       void (*calc_config_checksum)(struct goodix_ts_data *ts);
 };
 
 struct goodix_ts_data {
@@ -96,35 +97,42 @@ struct goodix_ts_data {
        unsigned long irq_flags;
        enum goodix_irq_pin_access_method irq_pin_access_method;
        unsigned int contact_size;
+       u8 config[GOODIX_CONFIG_MAX_LENGTH];
 };
 
 static int goodix_check_cfg_8(struct goodix_ts_data *ts,
                        const struct firmware *cfg);
 static int goodix_check_cfg_16(struct goodix_ts_data *ts,
                        const struct firmware *cfg);
+static void goodix_calc_cfg_checksum_8(struct goodix_ts_data *ts);
+static void goodix_calc_cfg_checksum_16(struct goodix_ts_data *ts);
 
 static const struct goodix_chip_data gt1x_chip_data = {
        .config_addr            = GOODIX_GT1X_REG_CONFIG_DATA,
        .config_len             = GOODIX_CONFIG_MAX_LENGTH,
        .check_config           = goodix_check_cfg_16,
+       .calc_config_checksum   = goodix_calc_cfg_checksum_16,
 };
 
 static const struct goodix_chip_data gt911_chip_data = {
        .config_addr            = GOODIX_GT9X_REG_CONFIG_DATA,
        .config_len             = GOODIX_CONFIG_911_LENGTH,
        .check_config           = goodix_check_cfg_8,
+       .calc_config_checksum   = goodix_calc_cfg_checksum_8,
 };
 
 static const struct goodix_chip_data gt967_chip_data = {
        .config_addr            = GOODIX_GT9X_REG_CONFIG_DATA,
        .config_len             = GOODIX_CONFIG_967_LENGTH,
        .check_config           = goodix_check_cfg_8,
+       .calc_config_checksum   = goodix_calc_cfg_checksum_8,
 };
 
 static const struct goodix_chip_data gt9x_chip_data = {
        .config_addr            = GOODIX_GT9X_REG_CONFIG_DATA,
        .config_len             = GOODIX_CONFIG_MAX_LENGTH,
        .check_config           = goodix_check_cfg_8,
+       .calc_config_checksum   = goodix_calc_cfg_checksum_8,
 };
 
 static const unsigned long goodix_irq_flags[] = {
@@ -458,6 +466,19 @@ static int goodix_check_cfg_8(struct goodix_ts_data *ts,
        return 0;
 }
 
+static void goodix_calc_cfg_checksum_8(struct goodix_ts_data *ts)
+{
+       int i, raw_cfg_len = ts->chip->config_len - 2;
+       u8 check_sum = 0;
+
+       for (i = 0; i < raw_cfg_len; i++)
+               check_sum += ts->config[i];
+       check_sum = (~check_sum) + 1;
+
+       ts->config[raw_cfg_len] = check_sum;
+       ts->config[raw_cfg_len + 1] = 1; /* Set "config_fresh" bit */
+}
+
 static int goodix_check_cfg_16(struct goodix_ts_data *ts,
                        const struct firmware *cfg)
 {
@@ -482,6 +503,19 @@ static int goodix_check_cfg_16(struct goodix_ts_data *ts,
        return 0;
 }
 
+static void goodix_calc_cfg_checksum_16(struct goodix_ts_data *ts)
+{
+       int i, raw_cfg_len = ts->chip->config_len - 3;
+       u16 check_sum = 0;
+
+       for (i = 0; i < raw_cfg_len; i += 2)
+               check_sum += get_unaligned_be16(&ts->config[i]);
+       check_sum = (~check_sum) + 1;
+
+       put_unaligned_be16(check_sum, &ts->config[raw_cfg_len]);
+       ts->config[raw_cfg_len + 2] = 1; /* Set "config_fresh" bit */
+}
+
 /**
  * goodix_check_cfg - Checks if config fw is valid
  *
@@ -859,12 +893,11 @@ retry_get_irq_gpio:
  */
 static void goodix_read_config(struct goodix_ts_data *ts)
 {
-       u8 config[GOODIX_CONFIG_MAX_LENGTH];
        int x_max, y_max;
        int error;
 
        error = goodix_i2c_read(ts->client, ts->chip->config_addr,
-                               config, ts->chip->config_len);
+                               ts->config, ts->chip->config_len);
        if (error) {
                dev_warn(&ts->client->dev, "Error reading config: %d\n",
                         error);
@@ -873,15 +906,17 @@ static void goodix_read_config(struct goodix_ts_data *ts)
                return;
        }
 
-       ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
-       ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
+       ts->int_trigger_type = ts->config[TRIGGER_LOC] & 0x03;
+       ts->max_touch_num = ts->config[MAX_CONTACTS_LOC] & 0x0f;
 
-       x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
-       y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
+       x_max = get_unaligned_le16(&ts->config[RESOLUTION_LOC]);
+       y_max = get_unaligned_le16(&ts->config[RESOLUTION_LOC + 2]);
        if (x_max && y_max) {
                input_abs_set_max(ts->input_dev, ABS_MT_POSITION_X, x_max - 1);
                input_abs_set_max(ts->input_dev, ABS_MT_POSITION_Y, y_max - 1);
        }
+
+       ts->chip->calc_config_checksum(ts);
 }
 
 /**