summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input')
-rwxr-xr-xdrivers/input/touchscreen/Kconfig12
-rwxr-xr-xdrivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/elan_ts.c387
-rwxr-xr-xdrivers/input/touchscreen/max11801_ts.c283
4 files changed, 621 insertions, 62 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index bf8d1797589c..bf002d471b1f 100755
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -187,6 +187,18 @@ config TOUCHSCREEN_EGALAX
To compile this driver as a module, choose M here: the
module will be called egalax_ts.
+config TOUCHSCREEN_ELAN
+ tristate "ELAN touchscreen input driver"
+ depends on I2C
+ help
+ Say Y here if you have an I2C ELAN touchscreen
+ attached.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called elan-touch.
+
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index f61dfe88bc62..28ac2d2c81bd 100755
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -66,3 +66,4 @@ obj-$(CONFIG_TOUCHSCREEN_P1003) += p1003_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
+obj-$(CONFIG_TOUCHSCREEN_ELAN) += elan_ts.o
diff --git a/drivers/input/touchscreen/elan_ts.c b/drivers/input/touchscreen/elan_ts.c
new file mode 100644
index 000000000000..7edd87d6cd1b
--- /dev/null
+++ b/drivers/input/touchscreen/elan_ts.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2007-2008 HTC Corporation.
+ *
+ * This driver is adapted from elan8232_i2c.c written by Shan-Fu Chiou
+ * <sfchiou@gmail.com> and Jay Tu <jay_tu@htc.com>.
+ * This driver is also adapted from the ELAN Touch Screen driver
+ * written by Stanley Zeng <stanley.zeng@emc.com.tw>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/hrtimer.h>
+#include <linux/gpio.h>
+
+static const char ELAN_TS_NAME[] = "elan-touch";
+
+#define ELAN_TS_X_MAX 1088
+#define ELAN_TS_Y_MAX 768
+#define ELAN_USER_X_MAX 800
+#define ELAN_USER_Y_MAX 600
+#define IDX_PACKET_SIZE 8
+
+enum {
+ hello_packet = 0x55,
+ idx_coordinate_packet = 0x5a,
+};
+
+enum {
+ idx_finger_state = 7,
+};
+
+static struct workqueue_struct *elan_wq;
+
+static struct elan_data {
+ int intr_gpio;
+ int use_irq;
+ struct hrtimer timer;
+ struct work_struct work;
+ struct i2c_client *client;
+ struct input_dev *input;
+ wait_queue_head_t wait;
+} elan_touch_data;
+
+/*--------------------------------------------------------------*/
+static int elan_touch_detect_int_level(void)
+{
+ unsigned v;
+ v = gpio_get_value(elan_touch_data.intr_gpio);
+
+ return v;
+}
+
+static int __elan_touch_poll(struct i2c_client *client)
+{
+ int status = 0, retry = 20;
+
+ do {
+ status = elan_touch_detect_int_level();
+ retry--;
+ mdelay(20);
+ } while (status == 1 && retry > 0);
+
+ return (status == 0 ? 0 : -ETIMEDOUT);
+}
+
+static int elan_touch_poll(struct i2c_client *client)
+{
+ return __elan_touch_poll(client);
+}
+
+static int __hello_packet_handler(struct i2c_client *client)
+{
+ int rc;
+ uint8_t buf_recv[4] = { 0 };
+
+ rc = elan_touch_poll(client);
+
+ if (rc < 0) {
+ return -EINVAL;
+ }
+
+ rc = i2c_master_recv(client, buf_recv, 4);
+
+ if (rc != 4) {
+ return rc;
+ } else {
+ int i;
+ printk("hello packet: [0x%02x 0x%02x 0x%02x 0x%02x]\n",
+ buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]);
+
+ for (i = 0; i < 4; i++)
+ if (buf_recv[i] != hello_packet)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline int elan_touch_parse_xy(uint8_t *data, uint16_t *x,
+ uint16_t *y)
+{
+ *x = (data[0] & 0xf0);
+ *x <<= 4;
+ *x |= data[1];
+ if (*x >= ELAN_TS_X_MAX)
+ *x = ELAN_TS_X_MAX;
+ *x = ((((ELAN_TS_X_MAX -
+ *x) * 1000) / ELAN_TS_X_MAX) * ELAN_USER_X_MAX) / 1000;
+
+ *y = (data[0] & 0x0f);
+ *y <<= 8;
+ *y |= data[2];
+ if (*y >= ELAN_TS_Y_MAX)
+ *y = ELAN_TS_Y_MAX;
+ *y = ((((ELAN_TS_Y_MAX -
+ *y) * 1000) / ELAN_TS_Y_MAX) * ELAN_USER_Y_MAX) / 1000;
+
+ return 0;
+}
+
+/* __elan_touch_init -- hand shaking with touch panel
+ *
+ * 1.recv hello packet
+ */
+static int __elan_touch_init(struct i2c_client *client)
+{
+ int rc;
+ rc = __hello_packet_handler(client);
+ if (rc < 0)
+ goto hand_shake_failed;
+
+hand_shake_failed:
+ return rc;
+}
+
+static int elan_touch_recv_data(struct i2c_client *client, uint8_t * buf)
+{
+ int rc, bytes_to_recv = IDX_PACKET_SIZE;
+
+ if (buf == NULL)
+ return -EINVAL;
+
+ memset(buf, 0, bytes_to_recv);
+ rc = i2c_master_recv(client, buf, bytes_to_recv);
+ if (rc != bytes_to_recv) {
+ return -EINVAL;
+ }
+
+ return rc;
+}
+
+static void elan_touch_report_data(struct i2c_client *client, uint8_t * buf)
+{
+ switch (buf[0]) {
+ case idx_coordinate_packet:
+ {
+ uint16_t x1, x2, y1, y2;
+ uint8_t finger_stat;
+
+ finger_stat = (buf[idx_finger_state] & 0x06) >> 1;
+
+ if (finger_stat == 0) {
+ input_report_key(elan_touch_data.input, BTN_TOUCH, 0);
+ input_report_key(elan_touch_data.input, BTN_2, 0);
+ } else if (finger_stat == 1) {
+ elan_touch_parse_xy(&buf[1], &x1, &y1);
+ input_report_abs(elan_touch_data.input, ABS_X, x1);
+ input_report_abs(elan_touch_data.input, ABS_Y, y1);
+ input_report_key(elan_touch_data.input, BTN_TOUCH, 1);
+ input_report_key(elan_touch_data.input, BTN_2, 0);
+ } else if (finger_stat == 2) {
+ elan_touch_parse_xy(&buf[1], &x1, &y1);
+ input_report_abs(elan_touch_data.input, ABS_X, x1);
+ input_report_abs(elan_touch_data.input, ABS_Y, y1);
+ input_report_key(elan_touch_data.input, BTN_TOUCH, 1);
+ elan_touch_parse_xy(&buf[4], &x2, &y2);
+ input_report_abs(elan_touch_data.input, ABS_HAT0X, x2);
+ input_report_abs(elan_touch_data.input, ABS_HAT0Y, y2);
+ input_report_key(elan_touch_data.input, BTN_2, 1);
+ }
+ input_sync(elan_touch_data.input);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+static void elan_touch_work_func(struct work_struct *work)
+{
+ int rc;
+ uint8_t buf[IDX_PACKET_SIZE] = { 0 };
+ struct i2c_client *client = elan_touch_data.client;
+
+ if (elan_touch_detect_int_level())
+ return;
+
+ rc = elan_touch_recv_data(client, buf);
+ if (rc < 0)
+ return;
+
+ elan_touch_report_data(client, buf);
+}
+
+static irqreturn_t elan_touch_ts_interrupt(int irq, void *dev_id)
+{
+ queue_work(elan_wq, &elan_touch_data.work);
+
+ return IRQ_HANDLED;
+}
+
+static enum hrtimer_restart elan_touch_timer_func(struct hrtimer *timer)
+{
+ queue_work(elan_wq, &elan_touch_data.work);
+ hrtimer_start(&elan_touch_data.timer, ktime_set(0, 12500000),
+ HRTIMER_MODE_REL);
+
+ return HRTIMER_NORESTART;
+}
+
+static int elan_touch_register_interrupt(struct i2c_client *client)
+{
+ int err = 0;
+
+ if (client->irq) {
+ elan_touch_data.use_irq = 1;
+ err =
+ request_irq(client->irq, elan_touch_ts_interrupt,
+ IRQF_TRIGGER_FALLING, ELAN_TS_NAME,
+ &elan_touch_data);
+
+ if (err < 0) {
+ printk("%s(%s): Can't allocate irq %d\n", __FILE__,
+ __func__, client->irq);
+ elan_touch_data.use_irq = 0;
+ }
+ }
+
+ if (!elan_touch_data.use_irq) {
+ hrtimer_init(&elan_touch_data.timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ elan_touch_data.timer.function = elan_touch_timer_func;
+ hrtimer_start(&elan_touch_data.timer, ktime_set(1, 0),
+ HRTIMER_MODE_REL);
+ }
+
+ printk("elan ts starts in %s mode.\n",
+ elan_touch_data.use_irq == 1 ? "interrupt" : "polling");
+
+ return 0;
+}
+
+static int elan_touch_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+
+ elan_wq = create_singlethread_workqueue("elan_wq");
+ if (!elan_wq) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ elan_touch_data.client = client;
+ strlcpy(client->name, ELAN_TS_NAME, I2C_NAME_SIZE);
+
+ INIT_WORK(&elan_touch_data.work, elan_touch_work_func);
+
+ elan_touch_data.intr_gpio = irq_to_gpio(client->irq);
+ pr_debug("irq_to_gpio irq %d, gpio %d\n", client->irq,
+ elan_touch_data.intr_gpio);
+
+ elan_touch_data.input = input_allocate_device();
+ if (elan_touch_data.input == NULL) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ err = __elan_touch_init(client);
+ if (err < 0) {
+ printk("elan - Read Hello Packet Failed\n");
+ goto fail;
+ }
+
+ elan_touch_data.input->name = ELAN_TS_NAME;
+ elan_touch_data.input->id.bustype = BUS_I2C;
+
+ set_bit(EV_SYN, elan_touch_data.input->evbit);
+
+ set_bit(EV_KEY, elan_touch_data.input->evbit);
+ set_bit(BTN_TOUCH, elan_touch_data.input->keybit);
+ set_bit(BTN_2, elan_touch_data.input->keybit);
+
+ set_bit(EV_ABS, elan_touch_data.input->evbit);
+ set_bit(ABS_X, elan_touch_data.input->absbit);
+ set_bit(ABS_Y, elan_touch_data.input->absbit);
+ set_bit(ABS_HAT0X, elan_touch_data.input->absbit);
+ set_bit(ABS_HAT0Y, elan_touch_data.input->absbit);
+
+ input_set_abs_params(elan_touch_data.input, ABS_X, 0, ELAN_USER_X_MAX,
+ 0, 0);
+ input_set_abs_params(elan_touch_data.input, ABS_Y, 0, ELAN_USER_Y_MAX,
+ 0, 0);
+ input_set_abs_params(elan_touch_data.input, ABS_HAT0X, 0,
+ ELAN_USER_X_MAX, 0, 0);
+ input_set_abs_params(elan_touch_data.input, ABS_HAT0Y, 0,
+ ELAN_USER_Y_MAX, 0, 0);
+
+ err = input_register_device(elan_touch_data.input);
+ if (err < 0) {
+ goto fail;
+ }
+
+ elan_touch_register_interrupt(elan_touch_data.client);
+
+ return 0;
+
+fail:
+ input_free_device(elan_touch_data.input);
+ if (elan_wq)
+ destroy_workqueue(elan_wq);
+ return err;
+}
+
+static int elan_touch_remove(struct i2c_client *client)
+{
+ if (elan_wq)
+ destroy_workqueue(elan_wq);
+
+ input_unregister_device(elan_touch_data.input);
+
+ if (elan_touch_data.use_irq)
+ free_irq(client->irq, client);
+ else
+ hrtimer_cancel(&elan_touch_data.timer);
+ return 0;
+}
+
+/* -------------------------------------------------------------------- */
+static const struct i2c_device_id elan_touch_id[] = {
+ {"elan-touch", 0},
+ {}
+};
+
+static struct i2c_driver elan_touch_driver = {
+ .probe = elan_touch_probe,
+ .remove = elan_touch_remove,
+ .id_table = elan_touch_id,
+ .driver = {
+ .name = "elan-touch",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init elan_touch_init(void)
+{
+ return i2c_add_driver(&elan_touch_driver);
+}
+
+static void __exit elan_touch_exit(void)
+{
+ i2c_del_driver(&elan_touch_driver);
+}
+
+module_init(elan_touch_init);
+module_exit(elan_touch_exit);
+
+MODULE_AUTHOR("Stanley Zeng <stanley.zeng@emc.com.tw>");
+MODULE_DESCRIPTION("ELAN Touch Screen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
index ca88d6823a98..48ee3600a03b 100755
--- a/drivers/input/touchscreen/max11801_ts.c
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -2,7 +2,7 @@
* Driver for MAXI MAX11801 - A Resistive touch screen controller with
* i2c interface
*
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
* Author: Zhang Jiejing <jiejing.zhang@freescale.com>
*
* Based on mcs5000_ts.c
@@ -38,6 +38,8 @@
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
+
/* Register Address define */
#define GENERNAL_STATUS_REG 0x00
@@ -53,13 +55,32 @@
#define AUX_MESURE_CONF_REG 0x0a
#define OP_MODE_CONF_REG 0x0b
+#define Panel_Setup_X (0x69 << 1)
+#define Panel_Setup_Y (0x6b << 1)
+
+#define XY_combined_measurement (0x70 << 1)
+#define X_measurement (0x78 << 1)
+#define Y_measurement (0x7a << 1)
+#define AUX_measurement (0x76 << 1)
+
/* FIFO is found only in max11800 and max11801 */
#define FIFO_RD_CMD (0x50 << 1)
#define MAX11801_FIFO_INT (1 << 2)
#define MAX11801_FIFO_OVERFLOW (1 << 3)
+#define MAX11801_EDGE_INT (1 << 1)
+
+#define FIFO_RD_X_MSB (0x52 << 1)
+#define FIFO_RD_X_LSB (0x53 << 1)
+#define FIFO_RD_Y_MSB (0x54 << 1)
+#define FIFO_RD_Y_LSB (0x55 << 1)
+#define FIFO_RD_AUX_MSB (0x5a << 1)
+#define FIFO_RD_AUX_LSB (0x5b << 1)
#define XY_BUFSIZE 4
#define XY_BUF_OFFSET 4
+#define X_BUFSIZE 2
+#define Y_BUFSIZE 2
+#define AUX_BUFSIZE 2
#define MAX11801_MAX_X 0xfff
#define MAX11801_MAX_Y 0xfff
@@ -83,6 +104,54 @@ struct max11801_data {
struct i2c_client *client;
struct input_dev *input_dev;
};
+struct i2c_client *max11801_client;
+unsigned int max11801_workmode;
+
+static int max11801_dcm_write_command(struct i2c_client *client, int command)
+{
+ return i2c_smbus_write_byte(client, command);
+}
+
+static u32 max11801_dcm_sample_aux(struct i2c_client *client)
+{
+ u8 temp_buf;
+ u8 aux_buf[AUX_BUFSIZE];
+ int ret;
+ int aux = 0;
+ u32 sample_data = 0;
+ /* AUX_measurement*/
+ max11801_dcm_write_command(client, AUX_measurement);
+ mdelay(5);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_MSB,
+ 1, &temp_buf);
+ aux_buf[0] = temp_buf;
+ if (ret < 1)
+ printk(KERN_DEBUG "FIFO_RD_AUX_MSB read fails\n");
+ mdelay(5);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_LSB,
+ 1, &temp_buf);
+ aux_buf[1] = temp_buf;
+ if (ret < 1)
+ printk(KERN_DEBUG "FIFO_RD_AUX_LSB read fails\n");
+ aux = (aux_buf[0] << 4) +
+ (aux_buf[1] >> 4);
+ /*
+ voltage = (9170*aux)/7371;
+ voltage is (26.2*3150*aux)/(16.2*0xFFF)
+ V(aux)=3150*sample/0xFFF,V(battery)=212*V(aux)/81
+ sample_data = (14840*aux)/7371-1541;
+ */
+ sample_data = (14840*aux)/7371;
+ return sample_data;
+}
+
+u32 max11801_read_adc(void)
+{
+ u32 adc_data;
+ adc_data = max11801_dcm_sample_aux(max11801_client);
+ return adc_data;
+}
+EXPORT_SYMBOL_GPL(max11801_read_adc);
static u8 read_register(struct i2c_client *client, int addr)
{
@@ -109,76 +178,166 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
struct i2c_client *client = data->client;
int status, i, ret;
u8 buf[XY_BUFSIZE];
+ u8 x_buf[X_BUFSIZE];
+ u8 y_buf[Y_BUFSIZE];
+ u8 temp_buf[1];
int x = -1;
int y = -1;
status = read_register(data->client, GENERNAL_STATUS_REG);
-
- if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) {
- status = read_register(data->client, GENERNAL_STATUS_REG);
-
- ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
- XY_BUFSIZE, buf);
-
- /*
- * We should get 4 bytes buffer that contains X,Y
- * and event tag
- */
- if (ret < XY_BUFSIZE)
- goto out;
-
- for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) {
- if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
- x = (buf[i] << XY_BUF_OFFSET) +
- (buf[i + 1] >> XY_BUF_OFFSET);
- else if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
- y = (buf[i] << XY_BUF_OFFSET) +
- (buf[i + 1] >> XY_BUF_OFFSET);
- }
-
- if ((buf[1] & EVENT_TAG_MASK) != (buf[3] & EVENT_TAG_MASK))
- goto out;
-
- switch (buf[1] & EVENT_TAG_MASK) {
- case EVENT_INIT:
- /* fall through */
- case EVENT_MIDDLE:
- calibration_pointer(&x, &y);
- input_report_abs(data->input_dev, ABS_X, x);
- input_report_abs(data->input_dev, ABS_Y, y);
- input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
- input_sync(data->input_dev);
- break;
-
- case EVENT_RELEASE:
- input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
- input_sync(data->input_dev);
- break;
-
- case EVENT_FIFO_END:
- break;
- }
- }
+ if (max11801_workmode == 0) {
+ if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) {
+ status = read_register(data->client, GENERNAL_STATUS_REG);
+
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
+ XY_BUFSIZE, buf);
+
+ /*
+ * We should get 4 bytes buffer that contains X,Y
+ * and event tag
+ */
+ if (ret < XY_BUFSIZE)
+ goto out;
+
+ for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) {
+ if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
+ x = (buf[i] << XY_BUF_OFFSET) +
+ (buf[i + 1] >> XY_BUF_OFFSET);
+ else if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
+ y = (buf[i] << XY_BUF_OFFSET) +
+ (buf[i + 1] >> XY_BUF_OFFSET);
+ }
+
+ if ((buf[1] & EVENT_TAG_MASK) != (buf[3] & EVENT_TAG_MASK))
+ goto out;
+
+ switch (buf[1] & EVENT_TAG_MASK) {
+ case EVENT_INIT:
+ /* fall through */
+ case EVENT_MIDDLE:
+ calibration_pointer(&x, &y);
+ input_report_abs(data->input_dev, ABS_X, x);
+ input_report_abs(data->input_dev, ABS_Y, y);
+ input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
+ input_sync(data->input_dev);
+ break;
+
+ case EVENT_RELEASE:
+ input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
+ input_sync(data->input_dev);
+ break;
+
+ case EVENT_FIFO_END:
+ break;
+ }
+ }
out:
- return IRQ_HANDLED;
+return IRQ_HANDLED;
+ }
+ else if (max11801_workmode == 1) {
+ if (status & (MAX11801_EDGE_INT)) {
+ status = read_register(data->client, GENERNAL_STATUS_REG);
+
+ /* X = panel setup*/
+ max11801_dcm_write_command(client, Panel_Setup_X);
+ /* X_measurement*/
+ max11801_dcm_write_command(client, X_measurement);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_X_MSB,
+ 1, temp_buf);
+ x_buf[0] = temp_buf[0];
+ if (ret < 1)
+ goto out2;
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_X_LSB,
+ 1, temp_buf);
+ x_buf[1] = temp_buf[0];
+ if (ret < 1)
+ goto out2;
+ /* Y = panel setup*/
+ max11801_dcm_write_command(client, Panel_Setup_Y);
+ /* Y_measurement*/
+ max11801_dcm_write_command(client, Y_measurement);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_Y_MSB,
+ 1, temp_buf);
+ y_buf[0] = temp_buf[0];
+ if (ret < 1)
+ goto out2;
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_Y_LSB,
+ 1, temp_buf);
+ y_buf[1] = temp_buf[0];
+ if (ret < 1)
+ goto out2;
+
+ if ((x_buf[1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
+ x = (x_buf[0] << XY_BUF_OFFSET) +
+ (x_buf[1] >> XY_BUF_OFFSET);
+ if ((y_buf[1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
+ y = (y_buf[0] << XY_BUF_OFFSET) +
+ (y_buf[1] >> XY_BUF_OFFSET);
+
+ if ((x_buf[1] & EVENT_TAG_MASK) != (y_buf[1] & EVENT_TAG_MASK))
+ goto out2;
+
+ switch (x_buf[1] & EVENT_TAG_MASK) {
+ case EVENT_INIT:
+ /* fall through */
+ case EVENT_MIDDLE:
+ calibration_pointer(&x, &y);
+ input_report_abs(data->input_dev, ABS_X, x);
+ input_report_abs(data->input_dev, ABS_Y, y);
+ input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
+ input_sync(data->input_dev);
+ break;
+
+ case EVENT_RELEASE:
+ input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
+ input_sync(data->input_dev);
+ break;
+
+ case EVENT_FIFO_END:
+ break;
+ }
+ }
+ }
+out2:
+return IRQ_HANDLED;
}
static void __devinit max11801_ts_phy_init(struct max11801_data *data)
{
struct i2c_client *client = data->client;
-
- /* Average X,Y, take 16 samples, average eight media sample */
- max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
- /* X,Y panel setup time set to 20us */
- max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
- /* Rough pullup time (2uS), Fine pullup time (10us) */
- max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
- /* Auto mode init period = 5ms , scan period = 5ms*/
- max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
- /* Aperture X,Y set to +- 4LSB */
- max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
- /* Enable Power, enable Automode, enable Aperture, enable Average X,Y */
- max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
+ max11801_client = client;
+ if (max11801_workmode == 0) {
+ /* Average X,Y, take 16 samples, average eight media sample */
+ max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
+ /* X,Y panel setup time set to 20us */
+ max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
+ /* Rough pullup time (2uS), Fine pullup time (10us) */
+ max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
+ /* Auto mode init period = 5ms , scan period = 5ms*/
+ max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
+ /* Aperture X,Y set to +- 4LSB */
+ max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
+ /* Enable Power, enable Automode, enable Aperture, enable Average X,Y */
+ max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
+ }
+ if (max11801_workmode == 1) {
+ /* Average X,Y, take 16 samples, average eight media sample */
+ max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
+ /* X,Y panel setup time set to 20us */
+ max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
+ /* Rough pullup time (2uS), Fine pullup time (10us) */
+ max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
+ /* Auto mode init period = 5ms , scan period = 5ms*/
+ max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
+ /* Aperture X,Y set to +- 4LSB */
+ max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
+ /* Enable Power, enable Direct conversion mode , enable Aperture, enable Average X,Y */
+ max11801_write_reg(client, OP_MODE_CONF_REG, 0x16);
+ /* Delay initial=1ms, Sampling time 2us ,Averaging sample depth 2 samples, Resolution 12bit */
+ max11801_write_reg(client, AUX_MESURE_CONF_REG, 0x76);
+ /* Use edge interrupt with direct conversion mode */
+ max11801_write_reg(client, GENERNAL_CONF_REG, 0xf3);
+ }
}
static int __devinit max11801_ts_probe(struct i2c_client *client,
@@ -195,7 +354,7 @@ static int __devinit max11801_ts_probe(struct i2c_client *client,
error = -ENOMEM;
goto err_free_mem;
}
-
+ max11801_workmode = *(int *)(client->dev).platform_data;
data->client = client;
data->input_dev = input_dev;