aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
authorZhang Jiejing <jiejing.zhang@freescale.com>2011-04-12 02:48:23 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-04-12 02:53:51 -0400
commit4203306506ebe4eaaa84a2cbd7c1eb2fc0128faa (patch)
tree7d271bdabbda899504860bbb7b4ada4053089164 /drivers/input/touchscreen
parent467112777c462a592c27338eeea5d1a320e82b5f (diff)
Input: add driver for Maxim max11801 touchscreen controller
Add MAXI max11801 resistive touchscreen controller driver. This driver uses Auto Mode and Aperture Mode. Support for other max1180x devices can be added to this driver as well, as they use almost the same register addresses and codes. You can find data sheet here: http://www.maxim-ic.com/datasheet/index.mvp/id/5943 Signed-off-by: Zhang Jiejing <jiejing.zhang@freescale.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/max11801_ts.c272
3 files changed, 285 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 112ec55f293..6b2d441a7dd 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -248,6 +248,18 @@ config TOUCHSCREEN_LPC32XX
248 To compile this driver as a module, choose M here: the 248 To compile this driver as a module, choose M here: the
249 module will be called lpc32xx_ts. 249 module will be called lpc32xx_ts.
250 250
251config TOUCHSCREEN_MAX11801
252 tristate "MAX11801 based touchscreens"
253 depends on I2C
254 help
255 Say Y here if you have a MAX11801 based touchscreen
256 controller.
257
258 If unsure, say N.
259
260 To compile this driver as a module, choose M here: the
261 module will be called max11801_ts.
262
251config TOUCHSCREEN_MCS5000 263config TOUCHSCREEN_MCS5000
252 tristate "MELFAS MCS-5000 touchscreen" 264 tristate "MELFAS MCS-5000 touchscreen"
253 depends on I2C 265 depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index ca94098d4c9..282d6f76ae2 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
27obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o 27obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
28obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o 28obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
29obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o 29obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
30obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
30obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o 31obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
31obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o 32obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
32obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o 33obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
new file mode 100644
index 00000000000..4f2713d9279
--- /dev/null
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -0,0 +1,272 @@
1/*
2 * Driver for MAXI MAX11801 - A Resistive touch screen controller with
3 * i2c interface
4 *
5 * Copyright (C) 2011 Freescale Semiconductor, Inc.
6 * Author: Zhang Jiejing <jiejing.zhang@freescale.com>
7 *
8 * Based on mcs5000_ts.c
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License.
13 */
14
15/*
16 * This driver aims to support the series of MAXI touch chips max11801
17 * through max11803. The main difference between these 4 chips can be
18 * found in the table below:
19 * -----------------------------------------------------
20 * | CHIP | AUTO MODE SUPPORT(FIFO) | INTERFACE |
21 * |----------------------------------------------------|
22 * | max11800 | YES | SPI |
23 * | max11801 | YES | I2C |
24 * | max11802 | NO | SPI |
25 * | max11803 | NO | I2C |
26 * ------------------------------------------------------
27 *
28 * Currently, this driver only supports max11801.
29 *
30 * Data Sheet:
31 * http://www.maxim-ic.com/datasheet/index.mvp/id/5943
32 */
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/i2c.h>
37#include <linux/interrupt.h>
38#include <linux/input.h>
39#include <linux/slab.h>
40#include <linux/bitops.h>
41
42/* Register Address define */
43#define GENERNAL_STATUS_REG 0x00
44#define GENERNAL_CONF_REG 0x01
45#define MESURE_RES_CONF_REG 0x02
46#define MESURE_AVER_CONF_REG 0x03
47#define ADC_SAMPLE_TIME_CONF_REG 0x04
48#define PANEL_SETUPTIME_CONF_REG 0x05
49#define DELAY_CONVERSION_CONF_REG 0x06
50#define TOUCH_DETECT_PULLUP_CONF_REG 0x07
51#define AUTO_MODE_TIME_CONF_REG 0x08 /* only for max11800/max11801 */
52#define APERTURE_CONF_REG 0x09 /* only for max11800/max11801 */
53#define AUX_MESURE_CONF_REG 0x0a
54#define OP_MODE_CONF_REG 0x0b
55
56/* FIFO is found only in max11800 and max11801 */
57#define FIFO_RD_CMD (0x50 << 1)
58#define MAX11801_FIFO_INT (1 << 2)
59#define MAX11801_FIFO_OVERFLOW (1 << 3)
60
61#define XY_BUFSIZE 4
62#define XY_BUF_OFFSET 4
63
64#define MAX11801_MAX_X 0xfff
65#define MAX11801_MAX_Y 0xfff
66
67#define MEASURE_TAG_OFFSET 2
68#define MEASURE_TAG_MASK (3 << MEASURE_TAG_OFFSET)
69#define EVENT_TAG_OFFSET 0
70#define EVENT_TAG_MASK (3 << EVENT_TAG_OFFSET)
71#define MEASURE_X_TAG (0 << MEASURE_TAG_OFFSET)
72#define MEASURE_Y_TAG (1 << MEASURE_TAG_OFFSET)
73
74/* These are the state of touch event state machine */
75enum {
76 EVENT_INIT,
77 EVENT_MIDDLE,
78 EVENT_RELEASE,
79 EVENT_FIFO_END
80};
81
82struct max11801_data {
83 struct i2c_client *client;
84 struct input_dev *input_dev;
85};
86
87static u8 read_register(struct i2c_client *client, int addr)
88{
89 /* XXX: The chip ignores LSB of register address */
90 return i2c_smbus_read_byte_data(client, addr << 1);
91}
92
93static int max11801_write_reg(struct i2c_client *client, int addr, int data)
94{
95 /* XXX: The chip ignores LSB of register address */
96 return i2c_smbus_write_byte_data(client, addr << 1, data);
97}
98
99static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
100{
101 struct max11801_data *data = dev_id;
102 struct i2c_client *client = data->client;
103 int status, i, ret;
104 u8 buf[XY_BUFSIZE];
105 int x = -1;
106 int y = -1;
107
108 status = read_register(data->client, GENERNAL_STATUS_REG);
109
110 if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) {
111 status = read_register(data->client, GENERNAL_STATUS_REG);
112
113 ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
114 XY_BUFSIZE, buf);
115
116 /*
117 * We should get 4 bytes buffer that contains X,Y
118 * and event tag
119 */
120 if (ret < XY_BUFSIZE)
121 goto out;
122
123 for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) {
124 if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
125 x = (buf[i] << XY_BUF_OFFSET) +
126 (buf[i + 1] >> XY_BUF_OFFSET);
127 else if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
128 y = (buf[i] << XY_BUF_OFFSET) +
129 (buf[i + 1] >> XY_BUF_OFFSET);
130 }
131
132 if ((buf[1] & EVENT_TAG_MASK) != (buf[3] & EVENT_TAG_MASK))
133 goto out;
134
135 switch (buf[1] & EVENT_TAG_MASK) {
136 case EVENT_INIT:
137 /* fall through */
138 case EVENT_MIDDLE:
139 input_report_abs(data->input_dev, ABS_X, x);
140 input_report_abs(data->input_dev, ABS_Y, y);
141 input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
142 input_sync(data->input_dev);
143 break;
144
145 case EVENT_RELEASE:
146 input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
147 input_sync(data->input_dev);
148 break;
149
150 case EVENT_FIFO_END:
151 break;
152 }
153 }
154out:
155 return IRQ_HANDLED;
156}
157
158static void __devinit max11801_ts_phy_init(struct max11801_data *data)
159{
160 struct i2c_client *client = data->client;
161
162 /* Average X,Y, take 16 samples, average eight media sample */
163 max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
164 /* X,Y panel setup time set to 20us */
165 max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
166 /* Rough pullup time (2uS), Fine pullup time (10us) */
167 max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
168 /* Auto mode init period = 5ms , scan period = 5ms*/
169 max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
170 /* Aperture X,Y set to +- 4LSB */
171 max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
172 /* Enable Power, enable Automode, enable Aperture, enable Average X,Y */
173 max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
174}
175
176static int __devinit max11801_ts_probe(struct i2c_client *client,
177 const struct i2c_device_id *id)
178{
179 struct max11801_data *data;
180 struct input_dev *input_dev;
181 int error;
182
183 data = kzalloc(sizeof(struct max11801_data), GFP_KERNEL);
184 input_dev = input_allocate_device();
185 if (!data || !input_dev) {
186 dev_err(&client->dev, "Failed to allocate memory\n");
187 error = -ENOMEM;
188 goto err_free_mem;
189 }
190
191 data->client = client;
192 data->input_dev = input_dev;
193
194 input_dev->name = "max11801_ts";
195 input_dev->id.bustype = BUS_I2C;
196 input_dev->dev.parent = &client->dev;
197
198 __set_bit(EV_ABS, input_dev->evbit);
199 __set_bit(EV_KEY, input_dev->evbit);
200 __set_bit(BTN_TOUCH, input_dev->keybit);
201 input_set_abs_params(input_dev, ABS_X, 0, MAX11801_MAX_X, 0, 0);
202 input_set_abs_params(input_dev, ABS_Y, 0, MAX11801_MAX_Y, 0, 0);
203 input_set_drvdata(input_dev, data);
204
205 max11801_ts_phy_init(data);
206
207 error = request_threaded_irq(client->irq, NULL, max11801_ts_interrupt,
208 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
209 "max11801_ts", data);
210 if (error) {
211 dev_err(&client->dev, "Failed to register interrupt\n");
212 goto err_free_mem;
213 }
214
215 error = input_register_device(data->input_dev);
216 if (error)
217 goto err_free_irq;
218
219 i2c_set_clientdata(client, data);
220 return 0;
221
222err_free_irq:
223 free_irq(client->irq, data);
224err_free_mem:
225 input_free_device(input_dev);
226 kfree(data);
227 return error;
228}
229
230static __devexit int max11801_ts_remove(struct i2c_client *client)
231{
232 struct max11801_data *data = i2c_get_clientdata(client);
233
234 free_irq(client->irq, data);
235 input_unregister_device(data->input_dev);
236 kfree(data);
237
238 return 0;
239}
240
241static const struct i2c_device_id max11801_ts_id[] = {
242 {"max11801", 0},
243 { }
244};
245MODULE_DEVICE_TABLE(i2c, max11801_ts_id);
246
247static struct i2c_driver max11801_ts_driver = {
248 .driver = {
249 .name = "max11801_ts",
250 .owner = THIS_MODULE,
251 },
252 .id_table = max11801_ts_id,
253 .probe = max11801_ts_probe,
254 .remove = __devexit_p(max11801_ts_remove),
255};
256
257static int __init max11801_ts_init(void)
258{
259 return i2c_add_driver(&max11801_ts_driver);
260}
261
262static void __exit max11801_ts_exit(void)
263{
264 i2c_del_driver(&max11801_ts_driver);
265}
266
267module_init(max11801_ts_init);
268module_exit(max11801_ts_exit);
269
270MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>");
271MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller");
272MODULE_LICENSE("GPL");