diff options
author | Daniel Kurtz <djkurtz@chromium.org> | 2012-06-28 09:08:20 -0400 |
---|---|---|
committer | Henrik Rydberg <rydberg@euromail.se> | 2012-06-29 09:58:06 -0400 |
commit | 333e5a9a99b8bba14f1a8631218d2d1e55fd58b1 (patch) | |
tree | 5ef107a17e2bcba86dfc8f7238a50d854be7f5f9 /drivers/input | |
parent | 7d4fa100b0cc069b2d788e1d9fe086e9e057958e (diff) |
Input: atmel_mxt_ts - cache T9 reportid range when reading object table
Streamline interrupt processing by caching the T9 reportid range when
first reading the object table.
In the process, refactor reading the object descriptor table.
First, since the object_table entries are now exactly the same layout
in device memory and in the driver, allocate an appropriately sized
array and fetch the entire table directly into it in a single i2c
transaction. Since a 6 byte table object requires 10 bytes to read,
doing this dramatically reduces overhead.
Note: The cached T9 reportid's are initialized to 0, which is an invalid
reportid. Thus, the checks in the interrupt handler will always fail for
devices that do not support the T9 object. Therefore, after doing a
firmware update, the old object table is destroyed and all cached object
values are reset to 0, before reading the new object table, in case
the new firmware does not have the old objects.
This patch tested on an MXT224E.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 76 |
1 files changed, 41 insertions, 35 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 488e3e88c3fc..48f3637aecaa 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -227,13 +227,10 @@ struct mxt_info { | |||
227 | struct mxt_object { | 227 | struct mxt_object { |
228 | u8 type; | 228 | u8 type; |
229 | u16 start_address; | 229 | u16 start_address; |
230 | u8 size; | 230 | u8 size; /* Size of each instance - 1 */ |
231 | u8 instances; | 231 | u8 instances; /* Number of instances - 1 */ |
232 | u8 num_report_ids; | 232 | u8 num_report_ids; |
233 | 233 | } __packed; | |
234 | /* to map object and message */ | ||
235 | u8 max_reportid; | ||
236 | }; | ||
237 | 234 | ||
238 | struct mxt_message { | 235 | struct mxt_message { |
239 | u8 reportid; | 236 | u8 reportid; |
@@ -251,6 +248,10 @@ struct mxt_data { | |||
251 | unsigned int irq; | 248 | unsigned int irq; |
252 | unsigned int max_x; | 249 | unsigned int max_x; |
253 | unsigned int max_y; | 250 | unsigned int max_y; |
251 | |||
252 | /* Cached parameters from object table */ | ||
253 | u8 T9_reportid_min; | ||
254 | u8 T9_reportid_max; | ||
254 | }; | 255 | }; |
255 | 256 | ||
256 | static bool mxt_object_readable(unsigned int type) | 257 | static bool mxt_object_readable(unsigned int type) |
@@ -459,13 +460,6 @@ static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val) | |||
459 | return __mxt_write_reg(client, reg, 1, &val); | 460 | return __mxt_write_reg(client, reg, 1, &val); |
460 | } | 461 | } |
461 | 462 | ||
462 | static int mxt_read_object_table(struct i2c_client *client, | ||
463 | u16 reg, u8 *object_buf) | ||
464 | { | ||
465 | return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE, | ||
466 | object_buf); | ||
467 | } | ||
468 | |||
469 | static struct mxt_object * | 463 | static struct mxt_object * |
470 | mxt_get_object(struct mxt_data *data, u8 type) | 464 | mxt_get_object(struct mxt_data *data, u8 type) |
471 | { | 465 | { |
@@ -564,7 +558,6 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) | |||
564 | { | 558 | { |
565 | struct mxt_data *data = dev_id; | 559 | struct mxt_data *data = dev_id; |
566 | struct mxt_message message; | 560 | struct mxt_message message; |
567 | struct mxt_object *object; | ||
568 | struct device *dev = &data->client->dev; | 561 | struct device *dev = &data->client->dev; |
569 | int id; | 562 | int id; |
570 | u8 reportid; | 563 | u8 reportid; |
@@ -579,13 +572,8 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) | |||
579 | 572 | ||
580 | reportid = message.reportid; | 573 | reportid = message.reportid; |
581 | 574 | ||
582 | /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */ | 575 | max_reportid = data->T9_reportid_max; |
583 | object = mxt_get_object(data, MXT_TOUCH_MULTI_T9); | 576 | min_reportid = data->T9_reportid_min; |
584 | if (!object) | ||
585 | goto end; | ||
586 | |||
587 | max_reportid = object->max_reportid; | ||
588 | min_reportid = max_reportid - object->num_report_ids + 1; | ||
589 | id = reportid - min_reportid; | 577 | id = reportid - min_reportid; |
590 | 578 | ||
591 | if (reportid >= min_reportid && reportid <= max_reportid) | 579 | if (reportid >= min_reportid && reportid <= max_reportid) |
@@ -720,30 +708,46 @@ static int mxt_get_info(struct mxt_data *data) | |||
720 | 708 | ||
721 | static int mxt_get_object_table(struct mxt_data *data) | 709 | static int mxt_get_object_table(struct mxt_data *data) |
722 | { | 710 | { |
711 | struct i2c_client *client = data->client; | ||
712 | size_t table_size; | ||
723 | int error; | 713 | int error; |
724 | int i; | 714 | int i; |
725 | u16 reg; | 715 | u8 reportid; |
726 | u8 reportid = 0; | 716 | |
727 | u8 buf[MXT_OBJECT_SIZE]; | 717 | table_size = data->info.object_num * sizeof(struct mxt_object); |
718 | error = __mxt_read_reg(client, MXT_OBJECT_START, table_size, | ||
719 | data->object_table); | ||
720 | if (error) | ||
721 | return error; | ||
728 | 722 | ||
723 | /* Valid Report IDs start counting from 1 */ | ||
724 | reportid = 1; | ||
729 | for (i = 0; i < data->info.object_num; i++) { | 725 | for (i = 0; i < data->info.object_num; i++) { |
730 | struct mxt_object *object = data->object_table + i; | 726 | struct mxt_object *object = data->object_table + i; |
727 | u8 min_id, max_id; | ||
731 | 728 | ||
732 | reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i; | 729 | le16_to_cpus(&object->start_address); |
733 | error = mxt_read_object_table(data->client, reg, buf); | ||
734 | if (error) | ||
735 | return error; | ||
736 | |||
737 | object->type = buf[0]; | ||
738 | object->start_address = (buf[2] << 8) | buf[1]; | ||
739 | object->size = buf[3]; | ||
740 | object->instances = buf[4]; | ||
741 | object->num_report_ids = buf[5]; | ||
742 | 730 | ||
743 | if (object->num_report_ids) { | 731 | if (object->num_report_ids) { |
732 | min_id = reportid; | ||
744 | reportid += object->num_report_ids * | 733 | reportid += object->num_report_ids * |
745 | (object->instances + 1); | 734 | (object->instances + 1); |
746 | object->max_reportid = reportid; | 735 | max_id = reportid - 1; |
736 | } else { | ||
737 | min_id = 0; | ||
738 | max_id = 0; | ||
739 | } | ||
740 | |||
741 | dev_dbg(&data->client->dev, | ||
742 | "Type %2d Start %3d Size %3d Instances %2d ReportIDs %3u : %3u\n", | ||
743 | object->type, object->start_address, object->size + 1, | ||
744 | object->instances + 1, min_id, max_id); | ||
745 | |||
746 | switch (object->type) { | ||
747 | case MXT_TOUCH_MULTI_T9: | ||
748 | data->T9_reportid_min = min_id; | ||
749 | data->T9_reportid_max = max_id; | ||
750 | break; | ||
747 | } | 751 | } |
748 | } | 752 | } |
749 | 753 | ||
@@ -754,6 +758,8 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
754 | { | 758 | { |
755 | kfree(data->object_table); | 759 | kfree(data->object_table); |
756 | data->object_table = NULL; | 760 | data->object_table = NULL; |
761 | data->T9_reportid_min = 0; | ||
762 | data->T9_reportid_max = 0; | ||
757 | } | 763 | } |
758 | 764 | ||
759 | static int mxt_initialize(struct mxt_data *data) | 765 | static int mxt_initialize(struct mxt_data *data) |