Merge "input: atmel_mxt_ts: Add support for keyarray object" into msm-3.0
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 3c98a75..2453b6b 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -306,6 +306,12 @@
u8 t7_data[T7_DATA_SIZE];
u16 t7_start_addr;
u8 t9_ctrl;
+ u32 keyarray_old;
+ u32 keyarray_new;
+ u8 t9_max_reportid;
+ u8 t9_min_reportid;
+ u8 t15_max_reportid;
+ u8 t15_min_reportid;
};
static bool mxt_object_readable(unsigned int type)
@@ -670,16 +676,48 @@
mxt_input_report(data, id);
}
+static void mxt_handle_key_array(struct mxt_data *data,
+ struct mxt_message *message)
+{
+ u32 keys_changed;
+ int i;
+
+ if (!data->pdata->key_codes) {
+ dev_err(&data->client->dev, "keyarray is not supported\n");
+ return;
+ }
+
+ data->keyarray_new = message->message[1] |
+ (message->message[2] << 8) |
+ (message->message[3] << 16) |
+ (message->message[4] << 24);
+
+ keys_changed = data->keyarray_old ^ data->keyarray_new;
+
+ if (!keys_changed) {
+ dev_dbg(&data->client->dev, "no keys changed\n");
+ return;
+ }
+
+ for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
+ if (!(keys_changed & (1 << i)))
+ continue;
+
+ input_report_key(data->input_dev, data->pdata->key_codes[i],
+ (data->keyarray_new & (1 << i)));
+ input_sync(data->input_dev);
+ }
+
+ data->keyarray_old = data->keyarray_new;
+}
+
static irqreturn_t mxt_interrupt(int irq, void *dev_id)
{
struct mxt_data *data = dev_id;
struct mxt_message message;
- struct mxt_object *object;
struct device *dev = &data->client->dev;
int id;
u8 reportid;
- u8 max_reportid;
- u8 min_reportid;
do {
if (mxt_read_message(data, &message)) {
@@ -688,16 +726,20 @@
}
reportid = message.reportid;
- /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */
- object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
- if (!object)
- goto end;
- max_reportid = object->max_reportid;
- min_reportid = max_reportid - object->num_report_ids + 1;
- id = reportid - min_reportid;
+ if (!reportid) {
+ dev_dbg(dev, "Report id 0 is reserved\n");
+ continue;
+ }
- if (reportid >= min_reportid && reportid <= max_reportid)
+ /* check whether report id is part of T9 or T15 */
+ id = reportid - data->t9_min_reportid;
+
+ if (reportid >= data->t9_min_reportid &&
+ reportid <= data->t9_max_reportid)
mxt_input_touchevent(data, &message, id);
+ else if (reportid >= data->t15_min_reportid &&
+ reportid <= data->t15_max_reportid)
+ mxt_handle_key_array(data, &message);
else
mxt_dump_message(dev, &message);
} while (reportid != 0xff);
@@ -857,6 +899,8 @@
u8 val;
u8 command_register;
struct mxt_object *t7_object;
+ struct mxt_object *t9_object;
+ struct mxt_object *t15_object;
error = mxt_get_info(data);
if (error)
@@ -903,6 +947,28 @@
goto free_object_table;
}
+ /* Store T9, T15's min and max report ids */
+ t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
+ if (!t9_object) {
+ dev_err(&client->dev, "Failed to get T9 object\n");
+ error = -EINVAL;
+ goto free_object_table;
+ }
+ data->t9_max_reportid = t9_object->max_reportid;
+ data->t9_min_reportid = t9_object->max_reportid -
+ t9_object->num_report_ids + 1;
+
+ if (data->pdata->key_codes) {
+ t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
+ if (!t15_object)
+ dev_dbg(&client->dev, "T15 object is not available\n");
+ else {
+ data->t15_max_reportid = t15_object->max_reportid;
+ data->t15_min_reportid = t15_object->max_reportid -
+ t15_object->num_report_ids + 1;
+ }
+ }
+
/* Backup to memory */
mxt_write_object(data, MXT_GEN_COMMAND_T6,
MXT_COMMAND_BACKUPNV,
@@ -1562,7 +1628,7 @@
const struct mxt_platform_data *pdata = client->dev.platform_data;
struct mxt_data *data;
struct input_dev *input_dev;
- int error;
+ int error, i;
if (!pdata)
return -EINVAL;
@@ -1608,6 +1674,15 @@
input_set_abs_params(input_dev, ABS_MT_PRESSURE,
0, 255, 0, 0);
+ /* set key array supported keys */
+ if (pdata->key_codes) {
+ for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
+ if (pdata->key_codes[i])
+ input_set_capability(input_dev, EV_KEY,
+ pdata->key_codes[i]);
+ }
+ }
+
input_set_drvdata(input_dev, data);
i2c_set_clientdata(client, data);
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index d61b934..9aa557a 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -26,6 +26,9 @@
#define MXT_ROTATED_180 0x6
#define MXT_DIAGONAL_COUNTER 0x7
+/* MXT_TOUCH_KEYARRAY_T15 */
+#define MXT_KEYARRAY_MAX_KEYS 32
+
/* The platform data for the Atmel maXTouch touchscreen driver */
struct mxt_platform_data {
const u8 *config;
@@ -38,6 +41,7 @@
bool digital_pwr_regulator;
int reset_gpio;
int irq_gpio;
+ int *key_codes;
u8(*read_chg) (void);
int (*init_hw) (bool);