aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Dyer <nick.dyer@itdev.co.uk>2014-05-19 02:04:46 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-05-19 02:27:26 -0400
commitc3f78043d5aea39205a14c580babd87fbdcfa148 (patch)
treea04d28b1eae6a4da2d528c9f9e2f343e88ba88f9
parent7bed6805615a215c3e23d5819ec3003b2fd8b98c (diff)
Input: atmel_mxt_ts - implement CRC check for configuration data
The configuration is stored in NVRAM on the maXTouch chip. When the device is reset it reports a CRC of the stored configuration values. Therefore it isn't necessary to send the configuration on each probe - we can check the CRC matches and avoid a timeconsuming backup/reset cycle. Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk> Acked-by: Benson Leung <bleung@chromium.org> Acked-by: Yufeng Shen <miletus@chromium.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c60
-rw-r--r--include/linux/i2c/atmel_mxt_ts.h1
2 files changed, 53 insertions, 8 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 278f364ec6e1..61f9ef221d12 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -188,6 +188,7 @@
188#define MXT_BACKUP_TIME 50 /* msec */ 188#define MXT_BACKUP_TIME 50 /* msec */
189#define MXT_RESET_TIME 200 /* msec */ 189#define MXT_RESET_TIME 200 /* msec */
190#define MXT_RESET_TIMEOUT 3000 /* msec */ 190#define MXT_RESET_TIMEOUT 3000 /* msec */
191#define MXT_CRC_TIMEOUT 1000 /* msec */
191#define MXT_FW_RESET_TIME 3000 /* msec */ 192#define MXT_FW_RESET_TIME 3000 /* msec */
192#define MXT_FW_CHG_TIMEOUT 300 /* msec */ 193#define MXT_FW_CHG_TIMEOUT 300 /* msec */
193 194
@@ -259,6 +260,7 @@ struct mxt_data {
259 unsigned int max_x; 260 unsigned int max_x;
260 unsigned int max_y; 261 unsigned int max_y;
261 bool in_bootloader; 262 bool in_bootloader;
263 u32 config_crc;
262 264
263 /* Cached parameters from object table */ 265 /* Cached parameters from object table */
264 u8 T6_reportid; 266 u8 T6_reportid;
@@ -272,6 +274,9 @@ struct mxt_data {
272 274
273 /* for reset handling */ 275 /* for reset handling */
274 struct completion reset_completion; 276 struct completion reset_completion;
277
278 /* for config update handling */
279 struct completion crc_completion;
275}; 280};
276 281
277static size_t mxt_obj_size(const struct mxt_object *obj) 282static size_t mxt_obj_size(const struct mxt_object *obj)
@@ -636,7 +641,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
636 } 641 }
637} 642}
638 643
639static unsigned mxt_extract_T6_csum(const u8 *csum) 644static u16 mxt_extract_T6_csum(const u8 *csum)
640{ 645{
641 return csum[0] | (csum[1] << 8) | (csum[2] << 16); 646 return csum[0] | (csum[1] << 8) | (csum[2] << 16);
642} 647}
@@ -654,6 +659,7 @@ static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data)
654 struct device *dev = &data->client->dev; 659 struct device *dev = &data->client->dev;
655 u8 reportid; 660 u8 reportid;
656 bool update_input = false; 661 bool update_input = false;
662 u32 crc;
657 663
658 do { 664 do {
659 if (mxt_read_message(data, &message)) { 665 if (mxt_read_message(data, &message)) {
@@ -665,9 +671,15 @@ static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data)
665 671
666 if (reportid == data->T6_reportid) { 672 if (reportid == data->T6_reportid) {
667 u8 status = payload[0]; 673 u8 status = payload[0];
668 unsigned csum = mxt_extract_T6_csum(&payload[1]); 674
675 crc = mxt_extract_T6_csum(&payload[1]);
676 if (crc != data->config_crc) {
677 data->config_crc = crc;
678 complete(&data->crc_completion);
679 }
680
669 dev_dbg(dev, "Status: %02x Config Checksum: %06x\n", 681 dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
670 status, csum); 682 status, data->config_crc);
671 683
672 if (status & MXT_T6_STATUS_RESET) 684 if (status & MXT_T6_STATUS_RESET)
673 complete(&data->reset_completion); 685 complete(&data->reset_completion);
@@ -757,6 +769,24 @@ static int mxt_soft_reset(struct mxt_data *data)
757 return 0; 769 return 0;
758} 770}
759 771
772static void mxt_update_crc(struct mxt_data *data, u8 cmd, u8 value)
773{
774 /*
775 * On failure, CRC is set to 0 and config will always be
776 * downloaded.
777 */
778 data->config_crc = 0;
779 reinit_completion(&data->crc_completion);
780
781 mxt_t6_command(data, cmd, value, true);
782
783 /*
784 * Wait for crc message. On failure, CRC is set to 0 and config will
785 * always be downloaded.
786 */
787 mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT);
788}
789
760static int mxt_check_reg_init(struct mxt_data *data) 790static int mxt_check_reg_init(struct mxt_data *data)
761{ 791{
762 const struct mxt_platform_data *pdata = data->pdata; 792 const struct mxt_platform_data *pdata = data->pdata;
@@ -771,6 +801,16 @@ static int mxt_check_reg_init(struct mxt_data *data)
771 return 0; 801 return 0;
772 } 802 }
773 803
804 mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
805
806 if (data->config_crc == pdata->config_crc) {
807 dev_info(dev, "Config CRC 0x%06X: OK\n", data->config_crc);
808 return 0;
809 }
810
811 dev_info(dev, "Config CRC 0x%06X: does not match 0x%06X\n",
812 data->config_crc, pdata->config_crc);
813
774 for (i = 0; i < data->info.object_num; i++) { 814 for (i = 0; i < data->info.object_num; i++) {
775 object = data->object_table + i; 815 object = data->object_table + i;
776 816
@@ -790,6 +830,14 @@ static int mxt_check_reg_init(struct mxt_data *data)
790 index += size; 830 index += size;
791 } 831 }
792 832
833 mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
834
835 ret = mxt_soft_reset(data);
836 if (ret)
837 return ret;
838
839 dev_info(dev, "Config successfully updated\n");
840
793 return 0; 841 return 0;
794} 842}
795 843
@@ -929,11 +977,6 @@ static int mxt_initialize(struct mxt_data *data)
929 goto err_free_object_table; 977 goto err_free_object_table;
930 } 978 }
931 979
932 error = mxt_t6_command(data, MXT_COMMAND_BACKUPNV,
933 MXT_BACKUP_VALUE, false);
934 if (!error)
935 mxt_soft_reset(data);
936
937 /* Update matrix size at info struct */ 980 /* Update matrix size at info struct */
938 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); 981 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
939 if (error) 982 if (error)
@@ -1263,6 +1306,7 @@ static int mxt_probe(struct i2c_client *client,
1263 1306
1264 init_completion(&data->bl_completion); 1307 init_completion(&data->bl_completion);
1265 init_completion(&data->reset_completion); 1308 init_completion(&data->reset_completion);
1309 init_completion(&data->crc_completion);
1266 1310
1267 mxt_calc_resolution(data); 1311 mxt_calc_resolution(data);
1268 1312
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index d26080dc606c..9f92135b6620 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -29,6 +29,7 @@
29struct mxt_platform_data { 29struct mxt_platform_data {
30 const u8 *config; 30 const u8 *config;
31 size_t config_length; 31 size_t config_length;
32 u32 config_crc;
32 33
33 unsigned int x_size; 34 unsigned int x_size;
34 unsigned int y_size; 35 unsigned int y_size;