summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabby Lee <galee@nvidia.com>2013-07-31 20:04:36 -0700
committerGabby Lee <galee@nvidia.com>2013-07-31 20:05:10 -0700
commit916fd65a2e0a18fe7ee58a61b2cfe08955a86920 (patch)
treeae63e9e20f4af9856070653b4c8fa0762e0b6485
parent5fb6ff9111d9e0c141116838635ba97f43891de7 (diff)
Revert "Revert "input: touch: maxim_sti: Update to version 1.3.0, v17""
This reverts commit 1d3379677dc7c4c9f3304b5ac5c1d97463fe5c45 Change-Id: I2dadbc5dee06a92073ee7fdcfb5ba5d2f037aa6f Reviewed-on: http://git-master/r/256610 Reviewed-by: Gabby Lee <galee@nvidia.com> Tested-by: Gabby Lee <galee@nvidia.com>
-rw-r--r--drivers/input/touchscreen/maxim_sti.c210
-rw-r--r--include/linux/maxim_sti.h4
2 files changed, 131 insertions, 83 deletions
diff --git a/drivers/input/touchscreen/maxim_sti.c b/drivers/input/touchscreen/maxim_sti.c
index f334d42a11c8..65b419cd49e9 100644
--- a/drivers/input/touchscreen/maxim_sti.c
+++ b/drivers/input/touchscreen/maxim_sti.c
@@ -35,7 +35,9 @@
* Custom features *
\****************************************************************************/
+#define INPUT_DEVICES 1
#define INPUT_ENABLE_DISABLE 1
+#define SUSPEND_POWER_OFF 1
#define NV_ENABLE_CPU_BOOST 1
#ifdef NV_ENABLE_CPU_BOOST
@@ -67,7 +69,7 @@ struct dev_data {
bool irq_registered;
u16 irq_param[MAX_IRQ_PARAMS];
char input_phys[128];
- struct input_dev *input_dev;
+ struct input_dev *input_dev[INPUT_DEVICES];
struct completion suspend_resume;
struct chip_access_method chip;
struct spi_device *spi;
@@ -81,10 +83,10 @@ struct dev_data {
struct list_head dev_list;
struct regulator *reg_avdd;
struct regulator *reg_dvdd;
+ void (*service_irq)(struct dev_data *dd);
#ifdef NV_ENABLE_CPU_BOOST
unsigned long last_irq_jiffies;
#endif
- void (*service_irq)(struct dev_data *dd);
};
static struct list_head dev_list;
@@ -208,24 +210,34 @@ spi_write_1(struct dev_data *dd, u16 address, u8 *buf, u16 len)
static inline int
stop_legacy_acceleration(struct dev_data *dd)
{
- u16 value = 0xDEAD;
- int ret;
+ u16 value = 0xDEAD, status, i;
+ int ret;
ret = spi_write_123(dd, 0x0003, (u8 *)&value,
sizeof(value), false);
+ if (ret < 0)
+ return -1;
usleep_range(100, 120);
- return ret;
+ for (i = 0; i < 200; i++) {
+ ret = spi_read_123(dd, 0x0003, (u8 *)&status, sizeof(status),
+ false);
+ if (ret < 0)
+ return -1;
+ if (status == 0xABCD)
+ return 0;
+ }
+
+ return -2;
}
static inline int
start_legacy_acceleration(struct dev_data *dd)
{
- u16 value = 0xBEEF;
- int ret;
+ u16 value = 0xBEEF;
+ int ret;
- ret = spi_write_123(dd, 0x0003, (u8 *)&value,
- sizeof(value), false);
+ ret = spi_write_123(dd, 0x0003, (u8 *)&value, sizeof(value), false);
usleep_range(100, 120);
return ret;
@@ -374,27 +386,19 @@ set_chip_access_method(struct dev_data *dd, u8 method)
static inline int
stop_legacy_acceleration_canned(struct dev_data *dd)
{
- u16 value = dd->irq_param[18];
- int ret;
+ u16 value = dd->irq_param[18];
- ret = stop_legacy_acceleration(dd);
- ret |= dd->chip.write(dd, dd->irq_param[16], (u8 *)&value,
+ return dd->chip.write(dd, dd->irq_param[16], (u8 *)&value,
sizeof(value));
- return ret;
}
static inline int
start_legacy_acceleration_canned(struct dev_data *dd)
{
- u16 value = dd->irq_param[17];
- int ret;
+ u16 value = dd->irq_param[17];
- ret = stop_legacy_acceleration(dd);
- ret |= dd->chip.write(dd, dd->irq_param[16], (u8 *)&value,
+ return dd->chip.write(dd, dd->irq_param[16], (u8 *)&value,
sizeof(value));
- ret |= start_legacy_acceleration(dd);
-
- return ret;
}
/* ======================================================================== */
@@ -738,6 +742,7 @@ static int suspend(struct device *dev)
wake_up_process(dd->thread);
wait_for_completion(&dd->suspend_resume);
+#if SUSPEND_POWER_OFF
/* reset-low and power-down */
pdata->reset(pdata, 0);
usleep_range(100, 120);
@@ -746,6 +751,7 @@ static int suspend(struct device *dev)
pdata->reset(pdata, 1);
return ret;
}
+#endif
return 0;
}
@@ -759,6 +765,7 @@ static int resume(struct device *dev)
if (!dd->suspend_in_progress)
return 0;
+#if SUSPEND_POWER_OFF
/* power-up and reset-high */
ret = regulator_control(dd, true);
if (ret < 0)
@@ -766,6 +773,7 @@ static int resume(struct device *dev)
usleep_range(300, 400);
pdata->reset(pdata, 1);
+#endif
dd->resume_in_progress = true;
wake_up_process(dd->thread);
@@ -835,7 +843,7 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
struct dr_config_input *config_input_msg;
struct dr_input *input_msg;
struct dr_legacy_acceleration *legacy_acceleration_msg;
- u8 i;
+ u8 i, inp;
int ret;
switch (msg_id) {
@@ -940,56 +948,68 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
return false;
case DR_CONFIG_INPUT:
config_input_msg = msg;
- dd->input_dev = input_allocate_device();
- if (dd->input_dev == NULL) {
- ERROR("failed to allocate input device");
- } else {
+ for (i = 0; i < INPUT_DEVICES; i++) {
+ dd->input_dev[i] = input_allocate_device();
+ if (dd->input_dev[i] == NULL) {
+ ERROR("failed to allocate input device");
+ continue;
+ }
snprintf(dd->input_phys, sizeof(dd->input_phys),
- "%s/input0", dev_name(&dd->spi->dev));
- dd->input_dev->name = pdata->nl_family;
- dd->input_dev->phys = dd->input_phys;
- dd->input_dev->id.bustype = BUS_SPI;
+ "%s/input%d", dev_name(&dd->spi->dev), i);
+ dd->input_dev[i]->name = pdata->nl_family;
+ dd->input_dev[i]->phys = dd->input_phys;
+ dd->input_dev[i]->id.bustype = BUS_SPI;
#if defined(CONFIG_PM_SLEEP) && INPUT_ENABLE_DISABLE
- dd->input_dev->enable = input_enable;
- dd->input_dev->disable = input_disable;
- dd->input_dev->enabled = true;
- input_set_drvdata(dd->input_dev, dd);
+ if (i == 0) {
+ dd->input_dev[i]->enable = input_enable;
+ dd->input_dev[i]->disable = input_disable;
+ dd->input_dev[i]->enabled = true;
+ input_set_drvdata(dd->input_dev[i], dd);
+ }
#endif
- __set_bit(EV_SYN, dd->input_dev->evbit);
- __set_bit(EV_ABS, dd->input_dev->evbit);
- __set_bit(EV_KEY, dd->input_dev->evbit);
- __set_bit(BTN_TOOL_RUBBER, dd->input_dev->keybit);
- input_set_abs_params(dd->input_dev, ABS_MT_POSITION_X,
- 0, config_input_msg->x_range, 0,
- 0);
- input_set_abs_params(dd->input_dev, ABS_MT_POSITION_Y,
- 0, config_input_msg->y_range, 0,
- 0);
- input_set_abs_params(dd->input_dev, ABS_MT_PRESSURE,
- 0, 0xFF, 0, 0);
- input_set_abs_params(dd->input_dev,
- ABS_MT_TRACKING_ID, 0,
- MAX_INPUT_EVENTS, 0, 0);
- input_set_abs_params(dd->input_dev, ABS_MT_TOOL_TYPE,
- 0, MT_TOOL_MAX, 0, 0);
-
#ifdef NV_ENABLE_CPU_BOOST
- input_set_capability(dd->input_dev, EV_MSC, MSC_ACTIVITY);
+ if (i == 0)
+ input_set_capability(dd->input_dev[i], EV_MSC,
+ MSC_ACTIVITY);
#endif
+ __set_bit(EV_SYN, dd->input_dev[i]->evbit);
+ __set_bit(EV_ABS, dd->input_dev[i]->evbit);
+ if (i == (INPUT_DEVICES - 1)) {
+ __set_bit(EV_KEY, dd->input_dev[i]->evbit);
+ __set_bit(BTN_TOOL_RUBBER,
+ dd->input_dev[i]->keybit);
+ }
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_POSITION_X, 0,
+ config_input_msg->x_range, 0, 0);
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_POSITION_Y, 0,
+ config_input_msg->y_range, 0, 0);
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_TRACKING_ID, 0,
+ MAX_INPUT_EVENTS, 0, 0);
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX,
+ 0, 0);
- ret = input_register_device(dd->input_dev);
+ ret = input_register_device(dd->input_dev[i]);
if (ret < 0) {
- input_free_device(dd->input_dev);
- dd->input_dev = NULL;
+ input_free_device(dd->input_dev[i]);
+ dd->input_dev[i] = NULL;
ERROR("failed to register input device");
}
}
return false;
case DR_DECONFIG:
- if (dd->input_dev != NULL) {
- input_unregister_device(dd->input_dev);
- dd->input_dev = NULL;
+ for (i = 0; i < INPUT_DEVICES; i++) {
+ if (dd->input_dev[i] == NULL)
+ continue;
+ input_unregister_device(dd->input_dev[i]);
+ dd->input_dev[i] = NULL;
}
+ dd->eraser_active = false;
if (dd->irq_registered) {
free_irq(dd->spi->irq, dd);
dd->irq_registered = false;
@@ -1002,28 +1022,33 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
input_msg = msg;
if (input_msg->events == 0) {
if (dd->eraser_active) {
- input_report_key(dd->input_dev,
+ input_report_key(
+ dd->input_dev[INPUT_DEVICES - 1],
BTN_TOOL_RUBBER, 0);
dd->eraser_active = false;
}
-
- input_mt_sync(dd->input_dev);
- input_sync(dd->input_dev);
+ for (i = 0; i < INPUT_DEVICES; i++) {
+ input_mt_sync(dd->input_dev[i]);
+ input_sync(dd->input_dev[i]);
+ }
} else {
for (i = 0; i < input_msg->events; i++) {
switch (input_msg->event[i].tool_type) {
case DR_INPUT_FINGER:
- input_report_abs(dd->input_dev,
+ inp = 0;
+ input_report_abs(dd->input_dev[inp],
ABS_MT_TOOL_TYPE,
MT_TOOL_FINGER);
break;
case DR_INPUT_STYLUS:
- input_report_abs(dd->input_dev,
+ inp = INPUT_DEVICES - 1;
+ input_report_abs(dd->input_dev[inp],
ABS_MT_TOOL_TYPE,
MT_TOOL_PEN);
break;
case DR_INPUT_ERASER:
- input_report_key(dd->input_dev,
+ inp = INPUT_DEVICES - 1;
+ input_report_key(dd->input_dev[inp],
BTN_TOOL_RUBBER, 1);
dd->eraser_active = true;
break;
@@ -1032,21 +1057,22 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
input_msg->event[i].tool_type);
break;
}
- input_report_abs(dd->input_dev,
+ input_report_abs(dd->input_dev[inp],
ABS_MT_TRACKING_ID,
input_msg->event[i].id);
- input_report_abs(dd->input_dev,
+ input_report_abs(dd->input_dev[inp],
ABS_MT_POSITION_X,
input_msg->event[i].x);
- input_report_abs(dd->input_dev,
+ input_report_abs(dd->input_dev[inp],
ABS_MT_POSITION_Y,
input_msg->event[i].y);
- input_report_abs(dd->input_dev,
+ input_report_abs(dd->input_dev[inp],
ABS_MT_PRESSURE,
input_msg->event[i].z);
- input_mt_sync(dd->input_dev);
+ input_mt_sync(dd->input_dev[inp]);
}
- input_sync(dd->input_dev);
+ for (i = 0; i < INPUT_DEVICES; i++)
+ input_sync(dd->input_dev[i]);
}
return false;
case DR_LEGACY_FWDL:
@@ -1182,7 +1208,7 @@ static irqreturn_t irq_handler(int irq, void *context)
#ifdef NV_ENABLE_CPU_BOOST
if (time_after(jiffies, dd->last_irq_jiffies + INPUT_IDLE_PERIOD))
- input_event(dd->input_dev, EV_MSC, MSC_ACTIVITY, 1);
+ input_event(dd->input_dev[0], EV_MSC, MSC_ACTIVITY, 1);
dd->last_irq_jiffies = jiffies;
#endif
@@ -1195,8 +1221,7 @@ static void service_irq_legacy_acceleration(struct dev_data *dd)
struct fu_async_data *async_data;
u16 len, rx_len, offset = 0;
u16 buf[255], rx_limit = 250 * sizeof(u16);
- int ret = 0;
- int counter = 0;
+ int ret = 0, counter = 0;
async_data = nl_alloc_attr(dd->outgoing_skb->data, FU_ASYNC_DATA,
sizeof(*async_data) + dd->irq_param[4] +
@@ -1214,7 +1239,15 @@ static void service_irq_legacy_acceleration(struct dev_data *dd)
ret = spi_read_123(dd, 0x0000, (u8 *)&buf,
rx_len + 4 * sizeof(u16), false);
if (ret < 0)
+ break;
+
+ if (buf[3] == 0xBABE) {
+ dd->legacy_acceleration = false;
+ dd->service_irq = service_irq;
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
return;
+ }
if (rx_limit == rx_len)
usleep_range(200, 300);
@@ -1242,17 +1275,22 @@ static void service_irq_legacy_acceleration(struct dev_data *dd)
offset += rx_len;
len -= rx_len;
}
+ async_data->status = *(buf + rx_len / sizeof(u16) + 2);
if (ret < 0) {
ERROR("can't read IRQ buffer (%d)", ret);
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
} else {
(void)skb_put(dd->outgoing_skb,
NL_SIZE(dd->outgoing_skb->data));
ret = genlmsg_multicast(dd->outgoing_skb, 0,
dd->nl_mc_groups[MC_FUSION].id,
GFP_KERNEL);
- if (ret < 0)
+ if (ret < 0) {
ERROR("can't send IRQ buffer %d", ret);
+ msleep(300);
+ }
ret = nl_msg_new(dd, MC_FUSION);
if (ret < 0)
ERROR("could not allocate outgoing skb (%d)", ret);
@@ -1325,21 +1363,23 @@ static void service_irq(struct dev_data *dd)
return;
}
+ async_data->status = status;
if (read_buf[0]) {
async_data->address = address[0];
async_data->length = dd->irq_param[4];
- async_data->status = status;
ret = dd->chip.read(dd, address[0], async_data->data,
dd->irq_param[4]);
}
- if (read_buf[1]) {
+ if (read_buf[1] && ret == 0) {
async_data = nl_alloc_attr(dd->outgoing_skb->data,
FU_ASYNC_DATA,
sizeof(*async_data) +
dd->irq_param[4]);
if (async_data == NULL) {
ERROR("can't add data to async IRQ buffer 2");
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
return;
}
async_data->address = address[1];
@@ -1356,14 +1396,18 @@ static void service_irq(struct dev_data *dd)
if (ret < 0) {
ERROR("can't read IRQ buffer (%d)", ret);
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
} else {
(void)skb_put(dd->outgoing_skb,
NL_SIZE(dd->outgoing_skb->data));
ret = genlmsg_multicast(dd->outgoing_skb, 0,
dd->nl_mc_groups[MC_FUSION].id,
GFP_KERNEL);
- if (ret < 0)
+ if (ret < 0) {
ERROR("can't send IRQ buffer %d", ret);
+ msleep(300);
+ }
ret = nl_msg_new(dd, MC_FUSION);
if (ret < 0)
ERROR("could not allocate outgoing skb (%d)", ret);
@@ -1439,7 +1483,9 @@ static int processing_thread(void *arg)
set_current_state(TASK_INTERRUPTIBLE);
schedule();
}
+#if !SUSPEND_POWER_OFF
start_scan_canned(dd);
+#endif
if (dd->irq_registered)
enable_irq(dd->spi->irq);
dd->resume_in_progress = false;
@@ -1618,6 +1664,7 @@ static int remove(struct spi_device *spi)
struct maxim_sti_pdata *pdata = spi->dev.platform_data;
struct dev_data *dd = spi_get_drvdata(spi);
unsigned long flags;
+ u8 i;
/* BEWARE: tear-down sequence below is carefully staged: */
/* 1) first the feeder of Netlink messages to the processing thread */
@@ -1634,8 +1681,9 @@ static int remove(struct spi_device *spi)
kfree_skb(dd->outgoing_skb);
skb_queue_purge(&dd->incoming_skb_queue);
- if (dd->input_dev)
- input_unregister_device(dd->input_dev);
+ for (i = 0; i < INPUT_DEVICES; i++)
+ if (dd->input_dev[i])
+ input_unregister_device(dd->input_dev[i]);
if (dd->irq_registered)
free_irq(dd->spi->irq, dd);
diff --git a/include/linux/maxim_sti.h b/include/linux/maxim_sti.h
index 220d57bf117f..1830ed0aa61e 100644
--- a/include/linux/maxim_sti.h
+++ b/include/linux/maxim_sti.h
@@ -27,8 +27,8 @@
#include "genetlink.h"
#endif
-#define DRIVER_VERSION "1.2.0"
-#define DRIVER_RELEASE "May 22, 2013"
+#define DRIVER_VERSION "1.3.0"
+#define DRIVER_RELEASE "July 24, 2013"
/****************************************************************************\
* Netlink: common kernel/user space macros *