linuxs-_smdk2440_2.6.19 : add missed touchscreen patch.
[openembedded.git] / packages / linux / linux-smdk2440 / smdk2440-touchscreen-r3.patch
1 Index: linux-2.6.19/arch/arm/mach-s3c2410/devs.c
2 ===================================================================
3 --- linux-2.6.19.orig/arch/arm/mach-s3c2410/devs.c
4 +++ linux-2.6.19/arch/arm/mach-s3c2410/devs.c
5 @@ -26,6 +26,7 @@
6  #include <asm/hardware.h>
7  #include <asm/io.h>
8  #include <asm/irq.h>
9 +#include <asm/arch/ts.h>
10  
11  #include <asm/arch/regs-serial.h>
12  
13 @@ -204,6 +205,23 @@ struct platform_device s3c_device_nand =
14  
15  EXPORT_SYMBOL(s3c_device_nand);
16  
17 +/* Touchscreen */
18 +struct platform_device s3c_device_ts = {
19 +       .name             = "s3c2410-ts",
20 +       .id               = -1,
21 +};
22 +
23 +EXPORT_SYMBOL(s3c_device_ts);
24 +
25 +static struct s3c2410_ts_mach_info s3c2410ts_info;
26 +
27 +void __init set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
28 +{
29 +       memcpy(&s3c2410ts_info,hard_s3c2410ts_info,sizeof(struct s3c2410_ts_mach_info));
30 +       s3c_device_ts.dev.platform_data = &s3c2410ts_info;
31 +}
32 +EXPORT_SYMBOL(set_s3c2410ts_info);
33 +
34  /* USB Device (Gadget)*/
35  
36  static struct resource s3c_usbgadget_resource[] = {
37 Index: linux-2.6.19/arch/arm/mach-s3c2410/devs.h
38 ===================================================================
39 --- linux-2.6.19.orig/arch/arm/mach-s3c2410/devs.h
40 +++ linux-2.6.19/arch/arm/mach-s3c2410/devs.h
41 @@ -41,6 +41,7 @@ extern struct platform_device s3c_device
42  extern struct platform_device s3c_device_timer3;
43  
44  extern struct platform_device s3c_device_usbgadget;
45 +extern struct platform_device s3c_device_ts;
46  
47  /* s3c2440 specific devices */
48  
49 Index: linux-2.6.19/drivers/input/touchscreen/Kconfig
50 ===================================================================
51 --- linux-2.6.19.orig/drivers/input/touchscreen/Kconfig
52 +++ linux-2.6.19/drivers/input/touchscreen/Kconfig
53 @@ -49,6 +49,24 @@ config TOUCHSCREEN_CORGI
54           To compile this driver as a module, choose M here: the
55           module will be called corgi_ts.
56  
57 +config TOUCHSCREEN_S3C2410
58 +       tristate "Samsung S3C2410 touchscreen input driver"
59 +       depends on ARCH_S3C2410 && INPUT && INPUT_TOUCHSCREEN
60 +       select SERIO
61 +       help
62 +         Say Y here if you have the s3c2410 touchscreen.
63 +
64 +         If unsure, say N.
65 +
66 +         To compile this driver as a module, choose M here: the
67 +         module will be called s3c2410_ts.
68 +
69 +config TOUCHSCREEN_S3C2410_DEBUG
70 +       boolean "Samsung S3C2410 touchscreen debug messages"
71 +       depends on TOUCHSCREEN_S3C2410
72 +       help
73 +         Select this if you want debug messages
74 +
75  config TOUCHSCREEN_GUNZE
76         tristate "Gunze AHL-51S touchscreen"
77         select SERIO
78 Index: linux-2.6.19/drivers/input/touchscreen/Makefile
79 ===================================================================
80 --- linux-2.6.19.orig/drivers/input/touchscreen/Makefile
81 +++ linux-2.6.19/drivers/input/touchscreen/Makefile
82 @@ -15,3 +15,5 @@ obj-$(CONFIG_TOUCHSCREEN_HP600)       += hp680
83  obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)     += penmount.o
84  obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)   += touchright.o
85  obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)     += touchwin.o
86 +obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
87 +
88 Index: linux-2.6.19/drivers/input/touchscreen/s3c2410_ts.c
89 ===================================================================
90 --- /dev/null
91 +++ linux-2.6.19/drivers/input/touchscreen/s3c2410_ts.c
92 @@ -0,0 +1,350 @@
93 +/*
94 + * This program is free software; you can redistribute it and/or modify
95 + * it under the terms of the GNU General Public License as published by
96 + * the Free Software Foundation; either version 2 of the License, or
97 + * (at your option) any later version.
98 + *
99 + * This program is distributed in the hope that it will be useful,
100 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
101 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
102 + * GNU General Public License for more details.
103 + *
104 + * You should have received a copy of the GNU General Public License
105 + * along with this program; if not, write to the Free Software
106 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
107 + *
108 + * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
109 + * iPAQ H1940 touchscreen support
110 + *
111 + * ChangeLog
112 + *
113 + * 2004-09-05: Herbert Pƶtzl <herbert@13thfloor.at>
114 + *     - added clock (de-)allocation code
115 + *
116 + * 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>
117 + *      - h1940_ -> s3c2410 (this driver is now also used on the n30
118 + *        machines :P)
119 + *      - Debug messages are now enabled with the config option
120 + *        TOUCHSCREEN_S3C2410_DEBUG
121 + *      - Changed the way the value are read
122 + *      - Input subsystem should now work
123 + *      - Use ioremap and readl/writel
124 + *
125 + * 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>
126 + *      - Make use of some undocumented features of the touchscreen
127 + *        controller
128 + *
129 + */
130 +
131 +#include <linux/errno.h>
132 +#include <linux/kernel.h>
133 +#include <linux/module.h>
134 +#include <linux/slab.h>
135 +#include <linux/input.h>
136 +#include <linux/init.h>
137 +#include <linux/serio.h>
138 +#include <linux/delay.h>
139 +#include <linux/platform_device.h>
140 +#include <linux/clk.h>
141 +#include <asm/io.h>
142 +#include <asm/irq.h>
143 +
144 +#include <asm/arch/regs-adc.h>
145 +#include <asm/arch/regs-gpio.h>
146 +#include <asm/arch/ts.h>
147 +
148 +/* For ts.dev.id.version */
149 +#define S3C2410TSVERSION       0x0101
150 +
151 +#define WAIT4INT(x)  (((x)<<8) | \
152 +                    S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
153 +                    S3C2410_ADCTSC_XY_PST(3))
154 +
155 +#define AUTOPST             (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
156 +                    S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
157 +
158 +#define DEBUG_LVL    KERN_DEBUG
159 +
160 +MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
161 +MODULE_DESCRIPTION("s3c2410 touchscreen driver");
162 +MODULE_LICENSE("GPL");
163 +
164 +/*
165 + * Definitions & global arrays.
166 + */
167 +
168 +
169 +static char *s3c2410ts_name = "s3c2410 TouchScreen";
170 +
171 +/*
172 + * Per-touchscreen data.
173 + */
174 +
175 +struct s3c2410ts {
176 +       struct input_dev *dev;
177 +       long xp;
178 +       long yp;
179 +       int count;
180 +       int shift;
181 +};
182 +
183 +static struct s3c2410ts ts;
184 +static void __iomem *base_addr;
185 +
186 +static inline void s3c2410_ts_connect(void)
187 +{
188 +       s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
189 +       s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
190 +       s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
191 +       s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
192 +}
193 +
194 +static void touch_timer_fire(unsigned long data)
195 +{
196 +       unsigned long data0;
197 +       unsigned long data1;
198 +       int updown;
199 +
200 +       data0 = readl(base_addr+S3C2410_ADCDAT0);
201 +       data1 = readl(base_addr+S3C2410_ADCDAT1);
202 +
203 +       updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
204 +
205 +       if (updown) {
206 +               if (ts.count != 0) {
207 +                       ts.xp >>= ts.shift;
208 +                       ts.yp >>= ts.shift;
209 +
210 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
211 +                       {
212 +                               struct timeval tv;
213 +                               do_gettimeofday(&tv);
214 +                               printk(DEBUG_LVL "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts.xp, ts.yp);
215 +                       }
216 +#endif
217 +
218 +                       input_report_abs(ts.dev, ABS_X, ts.xp);
219 +                       input_report_abs(ts.dev, ABS_Y, ts.yp);
220 +
221 +                       input_report_key(ts.dev, BTN_TOUCH, 1);
222 +                       input_report_abs(ts.dev, ABS_PRESSURE, 1);
223 +                       input_sync(ts.dev);
224 +               }
225 +
226 +               ts.xp = 0;
227 +               ts.yp = 0;
228 +               ts.count = 0;
229 +
230 +               writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
231 +               writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
232 +       } else {
233 +               ts.count = 0;
234 +
235 +               input_report_key(ts.dev, BTN_TOUCH, 0);
236 +               input_report_abs(ts.dev, ABS_PRESSURE, 0);
237 +               input_sync(ts.dev);
238 +
239 +               writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
240 +       }
241 +}
242 +
243 +static struct timer_list touch_timer =
244 +               TIMER_INITIALIZER(touch_timer_fire, 0, 0);
245 +
246 +static irqreturn_t stylus_updown(int irq, void *dev_id, struct pt_regs *regs)
247 +{
248 +       unsigned long data0;
249 +       unsigned long data1;
250 +       int updown;
251 +
252 +       data0 = readl(base_addr+S3C2410_ADCDAT0);
253 +       data1 = readl(base_addr+S3C2410_ADCDAT1);
254 +
255 +       updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
256 +
257 +       /* TODO we should never get an interrupt with updown set while
258 +        * the timer is running, but maybe we ought to verify that the
259 +        * timer isn't running anyways. */
260 +
261 +       if (updown)
262 +               touch_timer_fire(0);
263 +
264 +       return IRQ_HANDLED;
265 +}
266 +
267 +
268 +static irqreturn_t stylus_action(int irq, void *dev_id, struct pt_regs *regs)
269 +{
270 +       unsigned long data0;
271 +       unsigned long data1;
272 +
273 +       data0 = readl(base_addr+S3C2410_ADCDAT0);
274 +       data1 = readl(base_addr+S3C2410_ADCDAT1);
275 +
276 +       ts.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
277 +       ts.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
278 +       ts.count++;
279 +
280 +        if (ts.count < (1<<ts.shift)) {
281 +               writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
282 +               writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
283 +       } else {
284 +               mod_timer(&touch_timer, jiffies+1);
285 +               writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
286 +       }
287 +
288 +       return IRQ_HANDLED;
289 +}
290 +
291 +static struct clk      *adc_clock;
292 +
293 +/*
294 + * The functions for inserting/removing us as a module.
295 + */
296 +
297 +static int __init s3c2410ts_probe(struct platform_device *pdev)
298 +{
299 +       struct s3c2410_ts_mach_info *info;
300 +       struct input_dev *input_dev;
301 +
302 +       info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
303 +
304 +       if (!info)
305 +       {
306 +               printk(KERN_ERR "Hm... too bad : no platform data for ts\n");
307 +               return -EINVAL;
308 +       }
309 +
310 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
311 +       printk(DEBUG_LVL "Entering s3c2410ts_init\n");
312 +#endif
313 +
314 +       adc_clock = clk_get(NULL, "adc");
315 +       if (!adc_clock) {
316 +               printk(KERN_ERR "failed to get adc clock source\n");
317 +               return -ENOENT;
318 +       }
319 +       clk_enable(adc_clock);
320 +
321 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
322 +       printk(DEBUG_LVL "got and enabled clock\n");
323 +#endif
324 +
325 +       base_addr=ioremap(S3C2410_PA_ADC,0x20);
326 +       if (base_addr == NULL) {
327 +               printk(KERN_ERR "Failed to remap register block\n");
328 +               return -ENOMEM;
329 +       }
330 +
331 +
332 +       /* Configure GPIOs */
333 +       s3c2410_ts_connect();
334 +
335 +       if ((info->presc&0xff) > 0)
336 +               writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
337 +                            base_addr+S3C2410_ADCCON);
338 +       else
339 +               writel(0,base_addr+S3C2410_ADCCON);
340 +
341 +
342 +       /* Initialise registers */
343 +       if ((info->delay&0xffff) > 0)
344 +               writel(info->delay & 0xffff,  base_addr+S3C2410_ADCDLY);
345 +
346 +       writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
347 +
348 +       /* Initialise input stuff */
349 +       memset(&ts, 0, sizeof(struct s3c2410ts));
350 +       input_dev = input_allocate_device();
351 +
352 +       if (!input_dev) {
353 +               printk(KERN_ERR "Unable to allocate the input device !!\n");
354 +               return -ENOMEM;
355 +       }
356 +
357 +       ts.dev = input_dev;
358 +       ts.dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
359 +       ts.dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
360 +       input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);
361 +       input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
362 +       input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
363 +
364 +       ts.dev->private = &ts;
365 +       ts.dev->name = s3c2410ts_name;
366 +       ts.dev->id.bustype = BUS_RS232;
367 +       ts.dev->id.vendor = 0xDEAD;
368 +       ts.dev->id.product = 0xBEEF;
369 +       ts.dev->id.version = S3C2410TSVERSION;
370 +
371 +       ts.shift = info->oversampling_shift;
372 +
373 +       /* Get irqs */
374 +       if (request_irq(IRQ_ADC, stylus_action, SA_SAMPLE_RANDOM,
375 +               "s3c2410_action", ts.dev)) {
376 +               printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");
377 +               iounmap(base_addr);
378 +               return -EIO;
379 +       }
380 +       if (request_irq(IRQ_TC, stylus_updown, SA_SAMPLE_RANDOM,
381 +                       "s3c2410_action", ts.dev)) {
382 +               printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
383 +               iounmap(base_addr);
384 +               return -EIO;
385 +       }
386 +
387 +       printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);
388 +
389 +       /* All went ok, so register to the input system */
390 +       input_register_device(ts.dev);
391 +
392 +       return 0;
393 +}
394 +
395 +static int s3c2410ts_remove(struct platform_device *pdev)
396 +{
397 +       disable_irq(IRQ_ADC);
398 +       disable_irq(IRQ_TC);
399 +       free_irq(IRQ_TC,ts.dev);
400 +       free_irq(IRQ_ADC,ts.dev);
401 +
402 +       if (adc_clock) {
403 +               clk_disable(adc_clock);
404 +               clk_put(adc_clock);
405 +               adc_clock = NULL;
406 +       }
407 +
408 +       input_unregister_device(ts.dev);
409 +       iounmap(base_addr);
410 +
411 +       return 0;
412 +}
413 +
414 +static struct platform_driver s3c2410ts_driver = {
415 +       .driver         = {
416 +              .name   = "s3c2410-ts",
417 +              .owner  = THIS_MODULE,
418 +       },
419 +       .probe          = s3c2410ts_probe,
420 +       .remove         = s3c2410ts_remove,
421 +};
422 +
423 +
424 +static int __init s3c2410ts_init(void)
425 +{
426 +       return platform_driver_register(&s3c2410ts_driver);
427 +}
428 +
429 +static void __exit s3c2410ts_exit(void)
430 +{
431 +       platform_driver_unregister(&s3c2410ts_driver);
432 +}
433 +
434 +module_init(s3c2410ts_init);
435 +module_exit(s3c2410ts_exit);
436 +
437 +/*
438 +    Local variables:
439 +        compile-command: "make ARCH=arm CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux- -k -C ../../.."
440 +        c-basic-offset: 8
441 +    End:
442 +*/
443 Index: linux-2.6.19/include/asm-arm/arch-s3c2410/regs-adc.h
444 ===================================================================
445 --- linux-2.6.19.orig/include/asm-arm/arch-s3c2410/regs-adc.h
446 +++ linux-2.6.19/include/asm-arm/arch-s3c2410/regs-adc.h
447 @@ -41,7 +41,7 @@
448  #define S3C2410_ADCTSC_XP_SEN          (1<<4)
449  #define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
450  #define S3C2410_ADCTSC_AUTO_PST                (1<<2)
451 -#define S3C2410_ADCTSC_XY_PST          (0x3<<0)
452 +#define S3C2410_ADCTSC_XY_PST(x)       (((x)&0x3)<<0)
453  
454  /* ADCDAT0 Bits */
455  #define S3C2410_ADCDAT0_UPDOWN         (1<<15)
456 Index: linux-2.6.19/include/asm-arm/arch-s3c2410/ts.h
457 ===================================================================
458 --- /dev/null
459 +++ linux-2.6.19/include/asm-arm/arch-s3c2410/ts.h
460 @@ -0,0 +1,28 @@
461 +/* linux/include/asm/arch-s3c2410/ts.h
462 + *
463 + * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
464 + *
465 + *
466 + * This program is free software; you can redistribute it and/or modify
467 + * it under the terms of the GNU General Public License version 2 as
468 + * published by the Free Software Foundation.
469 + *
470 + *
471 + *  Changelog:
472 + *     24-Mar-2005     RTP     Created file
473 + *     03-Aug-2005     RTP     Renamed to ts.h
474 + */
475 +
476 +#ifndef __ASM_ARM_TS_H
477 +#define __ASM_ARM_TS_H
478 +
479 +struct s3c2410_ts_mach_info {
480 +       int             delay;
481 +       int             presc;
482 +       int             oversampling_shift;
483 +};
484 +
485 +void __init set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info);
486 +
487 +#endif /* __ASM_ARM_TS_H */
488 +
489 Index: linux-2.6.19/arch/arm/mach-s3c2410/mach-smdk2440.c
490 ===================================================================
491 --- linux-2.6.19.orig/arch/arm/mach-s3c2410/mach-smdk2440.c
492 +++ linux-2.6.19/arch/arm/mach-s3c2410/mach-smdk2440.c
493 @@ -35,6 +35,7 @@
494  #include <asm/arch/regs-serial.h>
495  #include <asm/arch/regs-gpio.h>
496  #include <asm/arch/regs-lcd.h>
497 +#include <asm/arch/ts.h>
498  
499  #include <asm/arch/idle.h>
500  #include <asm/arch/fb.h>
501 @@ -177,6 +178,7 @@ static struct platform_device *smdk2440_
502         &s3c_device_wdt,
503         &s3c_device_i2c,
504         &s3c_device_iis,
505 +       &s3c_device_ts,
506  };
507  
508  static struct s3c24xx_board smdk2440_board __initdata = {
509 @@ -184,6 +186,12 @@ static struct s3c24xx_board smdk2440_boa
510         .devices_count = ARRAY_SIZE(smdk2440_devices)
511  };
512  
513 +static struct s3c2410_ts_mach_info qt2410_ts_cfg = {
514 +       .delay = 10000,
515 +       .presc = 49,
516 +       .oversampling_shift = 2,
517 +};
518 +
519  static void __init smdk2440_map_io(void)
520  {
521         s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
522 @@ -195,6 +203,7 @@ static void __init smdk2440_map_io(void)
523  static void __init smdk2440_machine_init(void)
524  {
525         s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
526 +       set_s3c2410ts_info(&qt2410_ts_cfg);
527  
528         smdk_machine_init();
529  }