u-boot-mkimage-gta01-native: re-add till uboot-utils actually works
[openembedded.git] / packages / linux / linux-ezx-2.6.21 / patches / pcap-ts.patch
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
5 @@ -164,4 +164,13 @@
6           To compile this driver as a module, choose M here: the
7           module will be called ucb1400_ts.
8  
9 +config TOUCHSCREEN_PCAP
10 +       tristate "Motorola PCAP touchscreen"
11 +       depends on EZX_PCAP
12 +       help
13 +         Say Y here if you have a Motorola EZX telephone and
14 +         want to support the built-in touchscreen.
15 +
16 +         If unsure, say N.
17 +
18  endif
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
23 @@ -0,0 +1,372 @@
24 +/*
25 + * pcap_ts.c - Touchscreen driver for Motorola PCAP2 based touchscreen as found
26 + *            in the EZX phone platform.
27 + *
28 + *  Copyright (C) 2006 Harald Welte <laforge@openezx.org>
29 + *  Copyright (C) 2007 Daniel Ribeiro <drwyrm@gmail.com>
30 + *
31 + *  Based on information found in the original Motorola 2.4.x ezx-ts.c driver.
32 + *
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.
36 + *
37 + * TODO:
38 + *     split this in a hardirq handler and a tasklet/bh
39 + */
40 +
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>
50 +
51 +#include <asm/arch/hardware.h>
52 +#include <asm/arch/pxa-regs.h>
53 +#include <asm/arch/ezx-pcap.h>
54 +
55 +#if 0
56 +#define DEBUGP(x, args ...) printk(x, ## args)
57 +#else
58 +#define DEBUGP(x, args ...)
59 +#endif
60 +
61 +#define PRESSURE 1
62 +#define COORDINATE 2
63 +#define STANDBY 3
64 +
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);
68 +
69 +struct pcap_ts {
70 +       int irq_xy;
71 +       int irq_touch;
72 +       struct input_dev *input;
73 +       struct timer_list timer;
74 +
75 +       u_int16_t x, y;
76 +       u_int16_t pressure;
77 +
78 +       u_int8_t read_state;
79 +};
80 +
81 +#define X_AXIS_MIN     0
82 +#define X_AXIS_MAX     1023
83 +
84 +#define Y_AXIS_MAX     X_AXIS_MAX
85 +#define Y_AXIS_MIN     X_AXIS_MIN
86 +
87 +#define PRESSURE_MAX   X_AXIS_MAX
88 +#define PRESSURE_MIN   X_AXIS_MIN
89 +
90 +/* if we try to read faster, pressure reading becomes unreliable */
91 +#define SAMPLE_INTERVAL                (HZ/50)
92 +
93 +
94 +static void pcap_ts_mode(u_int32_t mode)
95 +{
96 +       u_int32_t tmp;
97 +
98 +       ezx_pcap_read(SSP_PCAP_ADJ_ADC1_REGISTER, &tmp);
99 +       tmp &= ~SSP_PCAP_TOUCH_PANEL_POSITION_DETECT_MODE_MASK;
100 +       tmp |= mode;
101 +       ezx_pcap_write(SSP_PCAP_ADJ_ADC1_REGISTER, tmp);
102 +}
103 +
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)
107 +{
108 +       u_int32_t tmp;
109 +
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);
115 +}
116 +
117 +/* read the XY result from the ADC of PCAP2 */
118 +static void pcap_ts_get_xy_value(struct pcap_ts *pcap_ts)
119 +{
120 +       u_int32_t tmp;
121 +
122 +       ezx_pcap_read(SSP_PCAP_ADJ_ADC2_REGISTER, &tmp);
123 +
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;
128 +       } else {
129 +               pcap_ts->pressure = (tmp & SSP_PCAP_ADD2_VALUE_MASK)
130 +                                               >>SSP_PCAP_ADD2_VALUE_SHIFT;
131 +       }
132 +
133 +}
134 +
135 +/* PCAP2 interrupts us when ADC conversion result is available */
136 +static irqreturn_t pcap_ts_irq_xy(int irq, void *dev_id)
137 +{
138 +       struct pcap_ts *pcap_ts = dev_id;
139 +
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);
144 +
145 +       switch (pcap_ts->read_state) {
146 +       case PRESSURE:
147 +               if (pcap_ts->pressure >= PRESSURE_MAX ||
148 +                    pcap_ts->pressure <= PRESSURE_MIN ) {
149 +                       /* pen has been released (or cant read pressure - WM)*/
150 +                       DEBUGP("UP\n");
151 +                       /* do nothing */
152 +               } else {
153 +                       /* pen has been touched down */
154 +                       DEBUGP("DOWN\n");
155 +                       input_report_key(pcap_ts->input, BTN_TOUCH, 1);
156 +                       input_report_abs(pcap_ts->input, ABS_PRESSURE, pcap_ts->pressure);
157 +               }
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);
162 +               break;
163 +       case COORDINATE:
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");
168 +
169 +                       input_report_key(pcap_ts->input, BTN_TOUCH, 0);
170 +                       input_report_abs(pcap_ts->input, ABS_PRESSURE, 0);
171 +
172 +                       /* no need for timer, we'll get interrupted with
173 +                        * next touch down event */
174 +                       del_timer(&pcap_ts->timer);
175 +
176 +                       /* ask PCAP2 to interrupt us if touch event happens
177 +                        * again */
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);
181 +               } else {
182 +                       DEBUGP("DOWN\n");
183 +                       input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
184 +                       input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
185 +
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);
190 +               }
191 +               input_sync(pcap_ts->input);
192 +               break;
193 +       default:
194 +               DEBUGP("ERROR\n");
195 +               break;
196 +       }
197 +
198 +       return IRQ_HANDLED;
199 +}
200 +
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)
203 +{
204 +       struct pcap_ts *pcap_ts = dev_id;
205 +
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);
210 +
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);
215 +
216 +       return IRQ_HANDLED;
217 +}
218 +
219 +static void pcap_ts_timer_fn(unsigned long data)
220 +{
221 +       struct pcap_ts *pcap_ts = (struct pcap_ts *) data;
222 +
223 +       pcap_ts_start_xy_read(pcap_ts);
224 +}
225 +
226 +static int __init ezxts_probe(struct platform_device *pdev)
227 +{
228 +       int ret;
229 +       u_int32_t tmp;
230 +       struct pcap_ts *pcap_ts;
231 +       struct input_dev *input_dev;
232 +       int err = -ENOMEM;
233 +
234 +       pcap_ts = kzalloc(sizeof(*pcap_ts), GFP_KERNEL);
235 +       input_dev = input_allocate_device();
236 +       if (!pcap_ts || !input_dev)
237 +               goto fail;
238 +
239 +       pcap_ts->irq_xy = platform_get_irq(pdev, 0);
240 +       if (pcap_ts->irq_xy < 0) {
241 +               err = pcap_ts->irq_xy;
242 +               goto fail;
243 +       }
244 +
245 +       pcap_ts->irq_touch = platform_get_irq(pdev, 1);
246 +       if (pcap_ts->irq_touch < 0) {
247 +               err = pcap_ts->irq_touch;
248 +               goto fail;
249 +       }
250 +
251 +       // Some initialization before done in ssp_pcap_open()
252 +       ezx_pcap_bit_set( SSP_PCAP_ADJ_BIT_ADC1_TS_REFENB, 0);
253 +       // ack interrupts
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);
269 +
270 +       ret = ezx_pcap_read(SSP_PCAP_ADJ_ADC1_REGISTER, &tmp);
271 +       if (ret < 0)
272 +               return ret;
273 +
274 +       tmp &= (~SSP_PCAP_TOUCH_PANEL_POSITION_DETECT_MODE_MASK);
275 +       tmp |= PCAP_TS_STANDBY_MODE;
276 +
277 +       ret = ezx_pcap_write(SSP_PCAP_ADJ_ADC1_REGISTER, tmp);
278 +       if (ret < 0)
279 +               return ret;
280 +
281 +       err = request_irq(pcap_ts->irq_xy, pcap_ts_irq_xy, SA_INTERRUPT,
282 +                         "pcap-ts X/Y", pcap_ts);
283 +       if (err < 0) {
284 +               printk(KERN_ERR "pcap_ts: can't grab xy irq %d: %d\n",
285 +                      pcap_ts->irq_xy, err);
286 +               goto fail;
287 +       }
288 +
289 +       err = request_irq(pcap_ts->irq_touch, pcap_ts_irq_touch, SA_INTERRUPT,
290 +                         "pcap-ts touch", pcap_ts);
291 +       if (err < 0) {
292 +               printk(KERN_ERR "pcap_ts: can't grab touch irq %d: %d\n",
293 +                      pcap_ts->irq_touch, err);
294 +               goto fail_xy;
295 +       }
296 +
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;
301 +
302 +       platform_set_drvdata(pdev, pcap_ts);
303 +
304 +       pcap_ts->read_state = STANDBY;
305 +       pcap_ts_mode(PCAP_TS_STANDBY_MODE);
306 +
307 +       /* enable pressure interrupt */
308 +       ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_MSR_TSM, 0);
309 +
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;
318 +
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);
325 +
326 +       input_register_device(pcap_ts->input);
327 +
328 +       return 0;
329 +
330 +fail_xy:
331 +       free_irq(pcap_ts->irq_xy, pcap_ts);
332 +fail:
333 +       input_free_device(input_dev);
334 +       kfree(pcap_ts);
335 +
336 +       return err;
337 +}
338 +
339 +static int ezxts_remove(struct platform_device *pdev)
340 +{
341 +       struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
342 +
343 +       del_timer_sync(&pcap_ts->timer);
344 +
345 +       free_irq(pcap_ts->irq_touch, pcap_ts);
346 +       free_irq(pcap_ts->irq_xy, pcap_ts);
347 +
348 +       input_unregister_device(pcap_ts->input);
349 +       kfree(pcap_ts);
350 +
351 +       return 0;
352 +}
353 +
354 +static int ezxts_suspend(struct platform_device *dev, pm_message_t state)
355 +{
356 +       ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_ADC1_TS_REF_LOWPWR, 1);
357 +        return 0;
358 +}
359 +
360 +static int ezxts_resume(struct platform_device *dev)
361 +{
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);
365 +        return 0;
366 +}
367 +
368 +
369 +static struct platform_driver ezxts_driver = {
370 +       .probe          = ezxts_probe,
371 +       .remove         = ezxts_remove,
372 +       .suspend        = ezxts_suspend,
373 +       .resume         = ezxts_resume,
374 +       .driver         = {
375 +               .name   = "pcap-ts",
376 +               .owner  = THIS_MODULE,
377 +       },
378 +};
379 +
380 +static int __init ezxts_init(void)
381 +{
382 +       return platform_driver_register(&ezxts_driver);
383 +}
384 +
385 +static void __exit ezxts_exit(void)
386 +{
387 +       platform_driver_unregister(&ezxts_driver);
388 +}
389 +
390 +module_init(ezxts_init);
391 +module_exit(ezxts_exit);
392 +
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
400 @@ -16,3 +16,4 @@
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