The T5 object may have various sizes depending on the objects used on the
particular maXTouch chip and firmware version, therefore it can't be hardcoded
in the driver. Allocate a buffer on probe instead.

Signed-off-by: Nick Dyer <nick.d...@itdev.co.uk>
Acked-by: Benson Leung <ble...@chromium.org>
---
 drivers/input/touchscreen/atmel_mxt_ts.c |  108 +++++++++++++++++-------------
 1 file changed, 61 insertions(+), 47 deletions(-)

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c 
b/drivers/input/touchscreen/atmel_mxt_ts.c
index ae9ea93..76ad308 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -228,11 +228,6 @@ struct mxt_object {
        u8 num_report_ids;
 } __packed;
 
-struct mxt_message {
-       u8 reportid;
-       u8 message[7];
-};
-
 /* Each client has this additional data */
 struct mxt_data {
        struct i2c_client *client;
@@ -252,8 +247,10 @@ struct mxt_data {
        u32 info_crc;
        u8 bootloader_addr;
        struct t7_config t7_cfg;
+       u8 *msg_buf;
 
        /* Cached parameters from object table */
+       u8 T5_msg_size;
        u8 T6_reportid;
        u16 T6_address;
        u16 T7_address;
@@ -317,10 +314,10 @@ static bool mxt_object_readable(unsigned int type)
        }
 }
 
-static void mxt_dump_message(struct device *dev, struct mxt_message *message)
+static void mxt_dump_message(struct mxt_data *data, u8 *message)
 {
-       dev_dbg(dev, "MXT MSG: %*ph\n",
-                      sizeof(struct mxt_message), message);
+       dev_dbg(&data->client->dev, "MXT MSG: %*ph\n",
+                      data->T5_msg_size, message);
 }
 
 static int mxt_wait_for_completion(struct mxt_data *data,
@@ -634,8 +631,7 @@ mxt_get_object(struct mxt_data *data, u8 type)
        return NULL;
 }
 
-static int mxt_read_message(struct mxt_data *data,
-                                struct mxt_message *message)
+static int mxt_read_message(struct mxt_data *data, u8 *message)
 {
        struct mxt_object *object;
        u16 reg;
@@ -646,10 +642,10 @@ static int mxt_read_message(struct mxt_data *data,
 
        reg = object->start_address;
        return __mxt_read_reg(data->client, reg,
-                       sizeof(struct mxt_message), message);
+                       data->T5_msg_size, message);
 }
 
-static void mxt_input_button(struct mxt_data *data, struct mxt_message 
*message)
+static void mxt_input_button(struct mxt_data *data, u8 *message)
 {
        struct input_dev *input = data->input_dev;
        const struct mxt_platform_data *pdata = data->pdata;
@@ -664,7 +660,7 @@ static void mxt_input_button(struct mxt_data *data, struct 
mxt_message *message)
        for (i = 0; i < pdata->t19_num_keys; i++) {
                if (pdata->t19_keymap[i] == KEY_RESERVED)
                        continue;
-               button = !(message->message[0] & (1 << i));
+               button = !(message[1] & (1 << i));
                input_report_key(input, pdata->t19_keymap[i], button);
        }
 }
@@ -675,12 +671,12 @@ static void mxt_input_sync(struct input_dev *input_dev)
        input_sync(input_dev);
 }
 
-static void mxt_input_touchevent(struct mxt_data *data,
-                                     struct mxt_message *message, int id)
+static void mxt_input_touchevent(struct mxt_data *data, u8 *message)
 {
        struct device *dev = &data->client->dev;
-       u8 status = message->message[0];
        struct input_dev *input_dev = data->input_dev;
+       int id;
+       u8 status;
        int x;
        int y;
        int area;
@@ -690,8 +686,10 @@ static void mxt_input_touchevent(struct mxt_data *data,
        if (!data->enable_reporting)
                return;
 
-       x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
-       y = (message->message[2] << 4) | ((message->message[3] & 0xf));
+       id = message[0] - data->T9_reportid_min;
+       status = message[1];
+       x = (message[2] << 4) | ((message[4] >> 4) & 0xf);
+       y = (message[3] << 4) | ((message[4] & 0xf));
 
        /* Handle 10/12 bit switching */
        if (data->max_x < 1024)
@@ -699,8 +697,8 @@ static void mxt_input_touchevent(struct mxt_data *data,
        if (data->max_y < 1024)
                y >>= 2;
 
-       area = message->message[4];
-       amplitude = message->message[5];
+       area = message[5];
+       amplitude = message[6];
 
        dev_dbg(dev,
                "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n",
@@ -744,16 +742,16 @@ static u16 mxt_extract_T6_csum(const u8 *csum)
        return csum[0] | (csum[1] << 8) | (csum[2] << 16);
 }
 
-static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg)
+static bool mxt_is_T9_message(struct mxt_data *data, u8 *msg)
 {
-       u8 id = msg->reportid;
+       u8 id = msg[0];
        return (id >= data->T9_reportid_min && id <= data->T9_reportid_max);
 }
 
 static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data)
 {
-       struct mxt_message message;
-       const u8 *payload = &message.message[0];
+       u8 *message = &data->msg_buf[0];
+       const u8 *payload = &data->msg_buf[1];
        struct device *dev = &data->client->dev;
        u8 reportid;
        bool update_input = false;
@@ -761,12 +759,12 @@ static irqreturn_t 
mxt_process_messages_until_invalid(struct mxt_data *data)
        u32 crc;
 
        do {
-               if (mxt_read_message(data, &message)) {
+               if (mxt_read_message(data, message)) {
                        dev_err(dev, "Failed to read message\n");
                        return IRQ_NONE;
                }
 
-               reportid = message.reportid;
+               reportid = message[0];
                dump = data->debug_enabled;
 
                if (reportid == data->T6_reportid) {
@@ -783,19 +781,18 @@ static irqreturn_t 
mxt_process_messages_until_invalid(struct mxt_data *data)
 
                        if (status & MXT_T6_STATUS_RESET)
                                complete(&data->reset_completion);
-               } else if (mxt_is_T9_message(data, &message)) {
-                       int id = reportid - data->T9_reportid_min;
-                       mxt_input_touchevent(data, &message, id);
+               } else if (mxt_is_T9_message(data, message)) {
+                       mxt_input_touchevent(data, message);
                        update_input = true;
-               } else if (message.reportid == data->T19_reportid) {
-                       mxt_input_button(data, &message);
+               } else if (reportid == data->T19_reportid) {
+                       mxt_input_button(data, message);
                        update_input = true;
                } else {
                        dump = true;
                }
 
                if (dump)
-                       mxt_dump_message(dev, &message);
+                       mxt_dump_message(data, message);
        } while (reportid != MXT_RPTID_NOMSG);
 
        if (data->enable_reporting && update_input)
@@ -1245,16 +1242,15 @@ recheck:
 static int mxt_make_highchg(struct mxt_data *data)
 {
        struct device *dev = &data->client->dev;
-       struct mxt_message message;
        int count = 10;
        int error;
 
        /* Read dummy message to make high CHG pin */
        do {
-               error = mxt_read_message(data, &message);
+               error = mxt_read_message(data, data->msg_buf);
                if (error)
                        return error;
-       } while (message.reportid != MXT_RPTID_NOMSG && --count);
+       } while (data->msg_buf[0] != MXT_RPTID_NOMSG && --count);
 
        if (!count) {
                dev_err(dev, "CHG pin isn't cleared\n");
@@ -1291,6 +1287,21 @@ static int mxt_get_info(struct mxt_data *data)
        return 0;
 }
 
+static void mxt_free_object_table(struct mxt_data *data)
+{
+       kfree(data->object_table);
+       data->object_table = NULL;
+       kfree(data->msg_buf);
+       data->msg_buf = NULL;
+       data->enable_reporting = false;
+       data->T5_msg_size = 0;
+       data->T6_reportid = 0;
+       data->T7_address = 0;
+       data->T9_reportid_min = 0;
+       data->T9_reportid_max = 0;
+       data->T19_reportid = 0;
+}
+
 static int mxt_get_object_table(struct mxt_data *data)
 {
        struct i2c_client *client = data->client;
@@ -1332,6 +1343,9 @@ static int mxt_get_object_table(struct mxt_data *data)
                        min_id, max_id);
 
                switch (object->type) {
+               case MXT_GEN_MESSAGE_T5:
+                       /* CRC not enabled, therefore don't read last byte */
+                       data->T5_msg_size = mxt_obj_size(object) - 1;
                case MXT_GEN_COMMAND_T6:
                        data->T6_reportid = min_id;
                        data->T6_address = object->start_address;
@@ -1355,18 +1369,18 @@ static int mxt_get_object_table(struct mxt_data *data)
                        data->mem_size = end_address + 1;
        }
 
+       data->msg_buf = kzalloc(data->T5_msg_size, GFP_KERNEL);
+       if (!data->msg_buf) {
+               dev_err(&client->dev, "Failed to allocate message buffer\n");
+               error = -ENOMEM;
+               goto free_object_table;
+       }
+
        return 0;
-}
 
-static void mxt_free_object_table(struct mxt_data *data)
-{
-       kfree(data->object_table);
-       data->object_table = NULL;
-       data->enable_reporting = false;
-       data->T6_reportid = 0;
-       data->T9_reportid_min = 0;
-       data->T9_reportid_max = 0;
-       data->T19_reportid = 0;
+free_object_table:
+       mxt_free_object_table(data);
+       return error;
 }
 
 static int mxt_read_t9_resolution(struct mxt_data *data)
@@ -2064,7 +2078,7 @@ err_unregister_device:
        input_unregister_device(data->input_dev);
        data->input_dev = NULL;
 err_free_object:
-       kfree(data->object_table);
+       mxt_free_object_table(data);
 err_free_irq:
        free_irq(data->irq, data);
 err_free_pdata:
@@ -2086,7 +2100,7 @@ static int mxt_remove(struct i2c_client *client)
        sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
        free_irq(data->irq, data);
        input_unregister_device(data->input_dev);
-       kfree(data->object_table);
+       mxt_free_object_table(data);
        if (!dev_get_platdata(&data->client->dev))
                kfree(data->pdata);
        kfree(data);
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to