1 Index: linux-2.6.21/drivers/input/touchscreen/Kconfig
2 ===================================================================
3 --- linux-2.6.21.orig/drivers/input/touchscreen/Kconfig 2007-06-02 20:17:58.000000000 -0300
4 +++ linux-2.6.21/drivers/input/touchscreen/Kconfig 2007-06-02 20:18:40.000000000 -0300
6 To compile this driver as a module, choose M here: the
7 module will be called ucb1400_ts.
9 +config TOUCHSCREEN_PCAP
10 + tristate "Motorola PCAP touchscreen"
13 + Say Y here if you have a Motorola EZX telephone and
14 + want to support the built-in touchscreen.
19 Index: linux-2.6.21/drivers/input/touchscreen/pcap_ts.c
20 ===================================================================
21 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
22 +++ linux-2.6.21/drivers/input/touchscreen/pcap_ts.c 2007-06-02 20:19:39.000000000 -0300
25 + * pcap_ts.c - Touchscreen driver for Motorola PCAP2 based touchscreen as found
26 + * in the EZX phone platform.
28 + * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
29 + * Copyright (C) 2007 Daniel Ribeiro <drwyrm@gmail.com>
31 + * Based on information found in the original Motorola 2.4.x ezx-ts.c driver.
33 + * This program is free software; you can redistribute it and/or modify
34 + * it under the terms of the GNU General Public License version 2 as
35 + * published by the Free Software Foundation.
38 + * split this in a hardirq handler and a tasklet/bh
41 +#include <linux/module.h>
42 +#include <linux/init.h>
43 +#include <linux/fs.h>
44 +#include <linux/string.h>
45 +#include <linux/pm.h>
46 +#include <linux/timer.h>
47 +#include <linux/interrupt.h>
48 +#include <linux/platform_device.h>
49 +#include <linux/input.h>
51 +#include <asm/arch/hardware.h>
52 +#include <asm/arch/pxa-regs.h>
53 +#include <asm/arch/ezx-pcap.h>
56 +#define DEBUGP(x, args ...) printk(x, ## args)
58 +#define DEBUGP(x, args ...)
65 +extern int ezx_pcap_read(u_int8_t, u_int32_t *);
66 +extern int ezx_pcap_write(u_int8_t, u_int32_t);
67 +extern int ezx_pcap_bit_set(u_int32_t, u_int8_t);
72 + struct input_dev *input;
73 + struct timer_list timer;
78 + u_int8_t read_state;
82 +#define X_AXIS_MAX 1023
84 +#define Y_AXIS_MAX X_AXIS_MAX
85 +#define Y_AXIS_MIN X_AXIS_MIN
87 +#define PRESSURE_MAX X_AXIS_MAX
88 +#define PRESSURE_MIN X_AXIS_MIN
90 +/* if we try to read faster, pressure reading becomes unreliable */
91 +#define SAMPLE_INTERVAL (HZ/50)
94 +static void pcap_ts_mode(u_int32_t mode)
98 + ezx_pcap_read(SSP_PCAP_ADJ_ADC1_REGISTER, &tmp);
99 + tmp &= ~SSP_PCAP_TOUCH_PANEL_POSITION_DETECT_MODE_MASK;
101 + ezx_pcap_write(SSP_PCAP_ADJ_ADC1_REGISTER, tmp);
104 +/* issue a XY read command to the ADC of PCAP2. Well get an ADCDONE2 interrupt
105 + * once the result of the conversion is available */
106 +static void pcap_ts_start_xy_read(struct pcap_ts *pcap_ts)
110 + ezx_pcap_read(SSP_PCAP_ADJ_ADC1_REGISTER, &tmp);
111 + tmp &= SSP_PCAP_ADC_START_VALUE_SET_MASK;
112 + tmp |= SSP_PCAP_ADC_START_VALUE;
113 + ezx_pcap_write(SSP_PCAP_ADJ_ADC1_REGISTER, tmp);
114 + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_ADC2_ASC, 1);
117 +/* read the XY result from the ADC of PCAP2 */
118 +static void pcap_ts_get_xy_value(struct pcap_ts *pcap_ts)
122 + ezx_pcap_read(SSP_PCAP_ADJ_ADC2_REGISTER, &tmp);
124 + if (pcap_ts->read_state == COORDINATE && !(tmp & 0x00400000)) {
125 + pcap_ts->x = (tmp & SSP_PCAP_ADD1_VALUE_MASK);
126 + pcap_ts->y = (tmp & SSP_PCAP_ADD2_VALUE_MASK)
127 + >>SSP_PCAP_ADD2_VALUE_SHIFT;
129 + pcap_ts->pressure = (tmp & SSP_PCAP_ADD2_VALUE_MASK)
130 + >>SSP_PCAP_ADD2_VALUE_SHIFT;
135 +/* PCAP2 interrupts us when ADC conversion result is available */
136 +static irqreturn_t pcap_ts_irq_xy(int irq, void *dev_id)
138 + struct pcap_ts *pcap_ts = dev_id;
140 + pcap_ts_get_xy_value(pcap_ts);
141 + DEBUGP(KERN_DEBUG "%s X=%4d, Y=%4d Z=%4d ",
142 + pcap_ts->read_state == COORDINATE ? "COORD" : "PRESS",
143 + pcap_ts->x, pcap_ts->y, pcap_ts->pressure);
145 + switch (pcap_ts->read_state) {
147 + if (pcap_ts->pressure >= PRESSURE_MAX ||
148 + pcap_ts->pressure <= PRESSURE_MIN ) {
149 + /* pen has been released (or cant read pressure - WM)*/
153 + /* pen has been touched down */
155 + input_report_key(pcap_ts->input, BTN_TOUCH, 1);
156 + input_report_abs(pcap_ts->input, ABS_PRESSURE, pcap_ts->pressure);
158 + /* switch state machine into coordinate read mode */
159 + pcap_ts->read_state = COORDINATE;
160 + pcap_ts_mode(PCAP_TS_POSITION_XY_MEASUREMENT);
161 + pcap_ts_start_xy_read(pcap_ts);
164 + if (pcap_ts->x <= X_AXIS_MIN || pcap_ts->x >= X_AXIS_MAX ||
165 + pcap_ts->y <= Y_AXIS_MIN || pcap_ts->y >= Y_AXIS_MAX) {
166 + /* pen has been released */
167 + DEBUGP("UP END\n");
169 + input_report_key(pcap_ts->input, BTN_TOUCH, 0);
170 + input_report_abs(pcap_ts->input, ABS_PRESSURE, 0);
172 + /* no need for timer, we'll get interrupted with
173 + * next touch down event */
174 + del_timer(&pcap_ts->timer);
176 + /* ask PCAP2 to interrupt us if touch event happens
178 + pcap_ts->read_state = STANDBY;
179 + pcap_ts_mode(PCAP_TS_STANDBY_MODE);
180 + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_MSR_TSM, 0);
183 + input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
184 + input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
186 + /* switch back to pressure read mode */
187 + pcap_ts->read_state = PRESSURE;
188 + pcap_ts_mode(PCAP_TS_PRESSURE_MEASUREMENT);
189 + mod_timer(&pcap_ts->timer, jiffies + SAMPLE_INTERVAL);
191 + input_sync(pcap_ts->input);
198 + return IRQ_HANDLED;
201 +/* PCAP2 interrupts us if the pen touches down (interrupts also on pen up - WM)*/
202 +static irqreturn_t pcap_ts_irq_touch(int irq, void *dev_id)
204 + struct pcap_ts *pcap_ts = dev_id;
206 + /* mask Touchscreen interrupt bit, prevents further touch events
207 + * from being reported to us until we're finished with reading
208 + * both pressure and x/y from ADC */
209 + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_MSR_TSM, 1);
211 + DEBUGP("touched!!\n");
212 + pcap_ts_mode(PCAP_TS_PRESSURE_MEASUREMENT);
213 + pcap_ts->read_state = PRESSURE;
214 + pcap_ts_start_xy_read(pcap_ts);
216 + return IRQ_HANDLED;
219 +static void pcap_ts_timer_fn(unsigned long data)
221 + struct pcap_ts *pcap_ts = (struct pcap_ts *) data;
223 + pcap_ts_start_xy_read(pcap_ts);
226 +static int __init ezxts_probe(struct platform_device *pdev)
230 + struct pcap_ts *pcap_ts;
231 + struct input_dev *input_dev;
234 + pcap_ts = kzalloc(sizeof(*pcap_ts), GFP_KERNEL);
235 + input_dev = input_allocate_device();
236 + if (!pcap_ts || !input_dev)
239 + pcap_ts->irq_xy = platform_get_irq(pdev, 0);
240 + if (pcap_ts->irq_xy < 0) {
241 + err = pcap_ts->irq_xy;
245 + pcap_ts->irq_touch = platform_get_irq(pdev, 1);
246 + if (pcap_ts->irq_touch < 0) {
247 + err = pcap_ts->irq_touch;
251 + // Some initialization before done in ssp_pcap_open()
252 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_TS_REFENB, 0);
254 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ISR_ADCDONE2I, 1);
255 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ISR_TSI, 1);
256 + // unmask interrupts
257 + // ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_MSR_TSM, 0);
258 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_MSR_ADCDONE2M, 0);
259 + // set adc bits? FIXME I dont think its necessary - WM
260 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC2_ADINC1, 0);
261 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC2_ADINC2, 0);
262 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_ATO0, 0);
263 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_ATO1, 0);
264 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_ATO2, 0);
265 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_ATO3, 0);
266 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_ATOX, 0);
267 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_MTR1, 0);
268 + ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_MTR2, 0);
270 + ret = ezx_pcap_read(SSP_PCAP_ADJ_ADC1_REGISTER, &tmp);
274 + tmp &= (~SSP_PCAP_TOUCH_PANEL_POSITION_DETECT_MODE_MASK);
275 + tmp |= PCAP_TS_STANDBY_MODE;
277 + ret = ezx_pcap_write(SSP_PCAP_ADJ_ADC1_REGISTER, tmp);
281 + err = request_irq(pcap_ts->irq_xy, pcap_ts_irq_xy, SA_INTERRUPT,
282 + "pcap-ts X/Y", pcap_ts);
284 + printk(KERN_ERR "pcap_ts: can't grab xy irq %d: %d\n",
285 + pcap_ts->irq_xy, err);
289 + err = request_irq(pcap_ts->irq_touch, pcap_ts_irq_touch, SA_INTERRUPT,
290 + "pcap-ts touch", pcap_ts);
292 + printk(KERN_ERR "pcap_ts: can't grab touch irq %d: %d\n",
293 + pcap_ts->irq_touch, err);
297 + pcap_ts->input = input_dev;
298 + init_timer(&pcap_ts->timer);
299 + pcap_ts->timer.data = (unsigned long) pcap_ts;
300 + pcap_ts->timer.function = &pcap_ts_timer_fn;
302 + platform_set_drvdata(pdev, pcap_ts);
304 + pcap_ts->read_state = STANDBY;
305 + pcap_ts_mode(PCAP_TS_STANDBY_MODE);
307 + /* enable pressure interrupt */
308 + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_MSR_TSM, 0);
310 + input_dev->name = "pcap-touchscreen";
311 + input_dev->phys = "ezxts/input0";
312 + input_dev->id.bustype = BUS_HOST;
313 + input_dev->id.vendor = 0x0001;
314 + input_dev->id.product = 0x0002;
315 + input_dev->id.version = 0x0100;
316 + input_dev->cdev.dev = &pdev->dev;
317 + input_dev->private = pcap_ts;
319 + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
320 + input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
321 + input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
322 + input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
323 + input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN,
324 + PRESSURE_MAX, 0, 0);
326 + input_register_device(pcap_ts->input);
331 + free_irq(pcap_ts->irq_xy, pcap_ts);
333 + input_free_device(input_dev);
339 +static int ezxts_remove(struct platform_device *pdev)
341 + struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
343 + del_timer_sync(&pcap_ts->timer);
345 + free_irq(pcap_ts->irq_touch, pcap_ts);
346 + free_irq(pcap_ts->irq_xy, pcap_ts);
348 + input_unregister_device(pcap_ts->input);
354 +static int ezxts_suspend(struct platform_device *dev, pm_message_t state)
356 + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_ADC1_TS_REF_LOWPWR, 1);
360 +static int ezxts_resume(struct platform_device *dev)
362 + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_ADC1_TS_REF_LOWPWR, 0);
363 + /* just in case we suspend with TSI masked. */
364 + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_MSR_TSM, 0);
369 +static struct platform_driver ezxts_driver = {
370 + .probe = ezxts_probe,
371 + .remove = ezxts_remove,
372 + .suspend = ezxts_suspend,
373 + .resume = ezxts_resume,
376 + .owner = THIS_MODULE,
380 +static int __init ezxts_init(void)
382 + return platform_driver_register(&ezxts_driver);
385 +static void __exit ezxts_exit(void)
387 + platform_driver_unregister(&ezxts_driver);
390 +module_init(ezxts_init);
391 +module_exit(ezxts_exit);
393 +MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver");
394 +MODULE_AUTHOR("Harald Welte <laforge@openezx.org>");
395 +MODULE_LICENSE("GPL");
396 Index: linux-2.6.21/drivers/input/touchscreen/Makefile
397 ===================================================================
398 --- linux-2.6.21.orig/drivers/input/touchscreen/Makefile 2007-06-02 20:17:58.000000000 -0300
399 +++ linux-2.6.21/drivers/input/touchscreen/Makefile 2007-06-02 20:18:40.000000000 -0300
401 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
402 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
403 obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
404 +obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o