1 From 9e0d71c4a6247d88d3b772f6b05bcaa39711a937 Mon Sep 17 00:00:00 2001
2 From: Thomas Kunze <thommycheck@gmx.de>
3 Date: Tue, 10 Feb 2009 19:31:25 +0100
4 Subject: [PATCH 12/23] move ucb1200-ts driver
6 Move the touchscreen driver to drivers/input/touchscreen
7 where touchscreen drivers belong.
11 drivers/input/touchscreen/Makefile
20 drivers/input/touchscreen/Kconfig | 7 +
21 drivers/input/touchscreen/Makefile | 1 +
22 drivers/input/touchscreen/ucb1x00-ts.c | 438 ++++++++++++++++++++++++++++++++
23 drivers/mfd/Kconfig | 3 -
24 drivers/mfd/Makefile | 3 +-
25 drivers/mfd/ucb1x00-ts.c | 438 --------------------------------
26 6 files changed, 447 insertions(+), 443 deletions(-)
27 create mode 100644 drivers/input/touchscreen/ucb1x00-ts.c
28 delete mode 100644 drivers/mfd/ucb1x00-ts.c
30 diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
31 index 3d1ab8f..3ac8cd6 100644
32 --- a/drivers/input/touchscreen/Kconfig
33 +++ b/drivers/input/touchscreen/Kconfig
34 @@ -221,6 +221,13 @@ config TOUCHSCREEN_ATMEL_TSADCC
35 To compile this driver as a module, choose M here: the
36 module will be called atmel_tsadcc.
38 +config TOUCHSCREEN_UCB1200_TS
39 + tristate "Philips UCB1200 touchscreen"
40 + depends on MCP_UCB1200
42 + This enabled support for the Pilips UCB1200 touchscreen interface
45 config TOUCHSCREEN_UCB1400
46 tristate "Philips UCB1400 touchscreen"
48 diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
49 index 15cf290..77ba930 100644
50 --- a/drivers/input/touchscreen/Makefile
51 +++ b/drivers/input/touchscreen/Makefile
52 @@ -25,6 +25,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
53 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
54 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
55 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
56 +obj-$(CONFIG_TOUCHSCREEN_UCB1200_TS) += ucb1x00-ts.o
57 obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
58 obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
59 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
60 diff --git a/drivers/input/touchscreen/ucb1x00-ts.c b/drivers/input/touchscreen/ucb1x00-ts.c
62 index 0000000..b5feae9
64 +++ b/drivers/input/touchscreen/ucb1x00-ts.c
67 + * Touchscreen driver for UCB1x00-based touchscreens
69 + * Copyright (C) 2001 Russell King, All Rights Reserved.
70 + * Copyright (C) 2005 Pavel Machek
72 + * This program is free software; you can redistribute it and/or modify
73 + * it under the terms of the GNU General Public License version 2 as
74 + * published by the Free Software Foundation.
76 + * 21-Jan-2002 <jco@ict.es> :
78 + * Added support for synchronous A/D mode. This mode is useful to
79 + * avoid noise induced in the touchpanel by the LCD, provided that
80 + * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
81 + * It is important to note that the signal connected to the ADCSYNC
82 + * pin should provide pulses even when the LCD is blanked, otherwise
83 + * a pen touch needed to unblank the LCD will never be read.
85 +#include <linux/module.h>
86 +#include <linux/moduleparam.h>
87 +#include <linux/init.h>
88 +#include <linux/smp.h>
89 +#include <linux/sched.h>
90 +#include <linux/completion.h>
91 +#include <linux/delay.h>
92 +#include <linux/string.h>
93 +#include <linux/input.h>
94 +#include <linux/device.h>
95 +#include <linux/freezer.h>
96 +#include <linux/slab.h>
97 +#include <linux/kthread.h>
98 +#include <linux/mfd/ucb1x00.h>
100 +#include <asm/dma.h>
101 +#include <mach/collie.h>
102 +#include <asm/mach-types.h>
107 + struct input_dev *idev;
108 + struct ucb1x00 *ucb;
110 + wait_queue_head_t irq_wait;
111 + struct task_struct *rtask;
115 + unsigned int restart:1;
116 + unsigned int adcsync:1;
121 +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
123 + struct input_dev *idev = ts->idev;
125 + input_report_abs(idev, ABS_X, x);
126 + input_report_abs(idev, ABS_Y, y);
127 + input_report_abs(idev, ABS_PRESSURE, pressure);
131 +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
133 + struct input_dev *idev = ts->idev;
135 + input_report_abs(idev, ABS_PRESSURE, 0);
140 + * Switch to interrupt mode.
142 +static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
144 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
145 + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
146 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
147 + UCB_TS_CR_MODE_INT);
151 + * Switch to pressure mode, and read pressure. We don't need to wait
152 + * here, since both plates are being driven.
154 +static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
156 + if (machine_is_collie()) {
157 + ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0);
158 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
159 + UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW |
160 + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
164 + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync);
166 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
167 + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
168 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
169 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
171 + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
176 + * Switch to X position mode and measure Y plate. We switch the plate
177 + * configuration in pressure mode, then switch to position mode. This
178 + * gives a faster response time. Even so, we need to wait about 55us
179 + * for things to stabilise.
181 +static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
183 + if (machine_is_collie())
184 + ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
186 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
187 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
188 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
189 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
190 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
191 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
193 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
194 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
195 + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
199 + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
203 + * Switch to Y position mode and measure X plate. We switch the plate
204 + * configuration in pressure mode, then switch to position mode. This
205 + * gives a faster response time. Even so, we need to wait about 55us
206 + * for things to stabilise.
208 +static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
210 + if (machine_is_collie())
211 + ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
213 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
214 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
215 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
216 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
217 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
218 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
221 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
222 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
223 + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
227 + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
231 + * Switch to X plate resistance mode. Set MX to ground, PX to
232 + * supply. Measure current.
234 +static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
236 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
237 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
238 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
239 + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
243 + * Switch to Y plate resistance mode. Set MY to ground, PY to
244 + * supply. Measure current.
246 +static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
248 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
249 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
250 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
251 + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
254 +static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
256 + unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
258 + if (machine_is_collie())
259 + return (!(val & (UCB_TS_CR_TSPX_LOW)));
261 + return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
265 + * This is a RT kernel thread that handles the ADC accesses
266 + * (mainly so we can use semaphores in the UCB1200 core code
267 + * to serialise accesses to the ADC).
269 +static int ucb1x00_thread(void *_ts)
271 + struct ucb1x00_ts *ts = _ts;
272 + DECLARE_WAITQUEUE(wait, current);
276 + add_wait_queue(&ts->irq_wait, &wait);
277 + while (!kthread_should_stop()) {
278 + unsigned int x, y, p;
279 + signed long timeout;
283 + ucb1x00_adc_enable(ts->ucb);
285 + x = ucb1x00_ts_read_xpos(ts);
286 + y = ucb1x00_ts_read_ypos(ts);
287 + p = ucb1x00_ts_read_pressure(ts);
290 + * Switch back to interrupt mode.
292 + ucb1x00_ts_mode_int(ts);
293 + ucb1x00_adc_disable(ts->ucb);
297 + ucb1x00_enable(ts->ucb);
300 + if (ucb1x00_ts_pen_down(ts)) {
301 + set_current_state(TASK_INTERRUPTIBLE);
303 + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
304 + ucb1x00_disable(ts->ucb);
307 + * If we spat out a valid sample set last time,
308 + * spit out a "pen off" sample here.
311 + ucb1x00_ts_event_release(ts);
315 + timeout = MAX_SCHEDULE_TIMEOUT;
317 + ucb1x00_disable(ts->ucb);
320 + * Filtering is policy. Policy belongs in user
321 + * space. We therefore leave it to user space
322 + * to do any filtering they please.
324 + if (!ts->restart) {
325 + ucb1x00_ts_evt_add(ts, p, x, y);
329 + set_current_state(TASK_INTERRUPTIBLE);
330 + timeout = HZ / 100;
335 + schedule_timeout(timeout);
338 + remove_wait_queue(&ts->irq_wait, &wait);
345 + * We only detect touch screen _touches_ with this interrupt
346 + * handler, and even then we just schedule our task.
348 +static void ucb1x00_ts_irq(int idx, void *id)
350 + struct ucb1x00_ts *ts = id;
352 + ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
353 + wake_up(&ts->irq_wait);
356 +static int ucb1x00_ts_open(struct input_dev *idev)
358 + struct ucb1x00_ts *ts = input_get_drvdata(idev);
363 + init_waitqueue_head(&ts->irq_wait);
364 + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
369 + * If we do this at all, we should allow the user to
370 + * measure and read the X and Y resistance at any time.
372 + ucb1x00_adc_enable(ts->ucb);
373 + ts->x_res = ucb1x00_ts_read_xres(ts);
374 + ts->y_res = ucb1x00_ts_read_yres(ts);
375 + ucb1x00_adc_disable(ts->ucb);
377 + ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
378 + if (!IS_ERR(ts->rtask)) {
381 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
391 + * Release touchscreen resources. Disable IRQs.
393 +static void ucb1x00_ts_close(struct input_dev *idev)
395 + struct ucb1x00_ts *ts = input_get_drvdata(idev);
398 + kthread_stop(ts->rtask);
400 + ucb1x00_enable(ts->ucb);
401 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
402 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
403 + ucb1x00_disable(ts->ucb);
407 +static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
409 + struct ucb1x00_ts *ts = dev->priv;
411 + if (ts->rtask != NULL) {
413 + * Restart the TS thread to ensure the
414 + * TS interrupt mode is set up again
418 + wake_up(&ts->irq_wait);
423 +#define ucb1x00_ts_resume NULL
430 +static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
432 + struct ucb1x00_ts *ts;
433 + struct input_dev *idev;
436 + ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
437 + idev = input_allocate_device();
438 + if (!ts || !idev) {
443 + ts->ucb = dev->ucb;
445 + ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
447 + idev->name = "Touchscreen panel";
448 + idev->id.product = ts->ucb->id;
449 + idev->open = ucb1x00_ts_open;
450 + idev->close = ucb1x00_ts_close;
452 + __set_bit(EV_ABS, idev->evbit);
453 + __set_bit(ABS_X, idev->absbit);
454 + __set_bit(ABS_Y, idev->absbit);
455 + __set_bit(ABS_PRESSURE, idev->absbit);
457 + input_set_drvdata(idev, ts);
459 + err = input_register_device(idev);
468 + input_free_device(idev);
473 +static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
475 + struct ucb1x00_ts *ts = dev->priv;
477 + input_unregister_device(ts->idev);
481 +static struct ucb1x00_driver ucb1x00_ts_driver = {
482 + .add = ucb1x00_ts_add,
483 + .remove = ucb1x00_ts_remove,
484 + .resume = ucb1x00_ts_resume,
487 +static int __init ucb1x00_ts_init(void)
489 + return ucb1x00_register_driver(&ucb1x00_ts_driver);
492 +static void __exit ucb1x00_ts_exit(void)
494 + ucb1x00_unregister_driver(&ucb1x00_ts_driver);
497 +module_param(adcsync, int, 0444);
498 +module_init(ucb1x00_ts_init);
499 +module_exit(ucb1x00_ts_exit);
501 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
502 +MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
503 +MODULE_LICENSE("GPL");
504 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
505 index 2572773..bbc137d 100644
506 --- a/drivers/mfd/Kconfig
507 +++ b/drivers/mfd/Kconfig
508 @@ -172,8 +172,5 @@ config MCP_UCB1200
509 tristate "Support for UCB1200 / UCB1300"
512 -config MCP_UCB1200_TS
513 - tristate "Touchscreen interface support"
514 - depends on MCP_UCB1200 && INPUT
517 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
518 index 9a5ad8a..4981aff 100644
519 --- a/drivers/mfd/Makefile
520 +++ b/drivers/mfd/Makefile
521 @@ -24,11 +24,10 @@ obj-$(CONFIG_MFD_CORE) += mfd-core.o
522 obj-$(CONFIG_MCP) += mcp-core.o
523 obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
524 obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
525 -obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
527 ifeq ($(CONFIG_SA1100_ASSABET),y)
528 obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
530 obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
532 -obj-$(CONFIG_PMIC_DA903X) += da903x.o
533 \ No newline at end of file
534 +obj-$(CONFIG_PMIC_DA903X) += da903x.o
535 diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
536 deleted file mode 100644
537 index b5feae9..0000000
538 --- a/drivers/mfd/ucb1x00-ts.c
542 - * Touchscreen driver for UCB1x00-based touchscreens
544 - * Copyright (C) 2001 Russell King, All Rights Reserved.
545 - * Copyright (C) 2005 Pavel Machek
547 - * This program is free software; you can redistribute it and/or modify
548 - * it under the terms of the GNU General Public License version 2 as
549 - * published by the Free Software Foundation.
551 - * 21-Jan-2002 <jco@ict.es> :
553 - * Added support for synchronous A/D mode. This mode is useful to
554 - * avoid noise induced in the touchpanel by the LCD, provided that
555 - * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
556 - * It is important to note that the signal connected to the ADCSYNC
557 - * pin should provide pulses even when the LCD is blanked, otherwise
558 - * a pen touch needed to unblank the LCD will never be read.
560 -#include <linux/module.h>
561 -#include <linux/moduleparam.h>
562 -#include <linux/init.h>
563 -#include <linux/smp.h>
564 -#include <linux/sched.h>
565 -#include <linux/completion.h>
566 -#include <linux/delay.h>
567 -#include <linux/string.h>
568 -#include <linux/input.h>
569 -#include <linux/device.h>
570 -#include <linux/freezer.h>
571 -#include <linux/slab.h>
572 -#include <linux/kthread.h>
573 -#include <linux/mfd/ucb1x00.h>
575 -#include <asm/dma.h>
576 -#include <mach/collie.h>
577 -#include <asm/mach-types.h>
582 - struct input_dev *idev;
583 - struct ucb1x00 *ucb;
585 - wait_queue_head_t irq_wait;
586 - struct task_struct *rtask;
590 - unsigned int restart:1;
591 - unsigned int adcsync:1;
596 -static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
598 - struct input_dev *idev = ts->idev;
600 - input_report_abs(idev, ABS_X, x);
601 - input_report_abs(idev, ABS_Y, y);
602 - input_report_abs(idev, ABS_PRESSURE, pressure);
606 -static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
608 - struct input_dev *idev = ts->idev;
610 - input_report_abs(idev, ABS_PRESSURE, 0);
615 - * Switch to interrupt mode.
617 -static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
619 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
620 - UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
621 - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
622 - UCB_TS_CR_MODE_INT);
626 - * Switch to pressure mode, and read pressure. We don't need to wait
627 - * here, since both plates are being driven.
629 -static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
631 - if (machine_is_collie()) {
632 - ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0);
633 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
634 - UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW |
635 - UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
639 - return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync);
641 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
642 - UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
643 - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
644 - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
646 - return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
651 - * Switch to X position mode and measure Y plate. We switch the plate
652 - * configuration in pressure mode, then switch to position mode. This
653 - * gives a faster response time. Even so, we need to wait about 55us
654 - * for things to stabilise.
656 -static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
658 - if (machine_is_collie())
659 - ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
661 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
662 - UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
663 - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
664 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
665 - UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
666 - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
668 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
669 - UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
670 - UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
674 - return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
678 - * Switch to Y position mode and measure X plate. We switch the plate
679 - * configuration in pressure mode, then switch to position mode. This
680 - * gives a faster response time. Even so, we need to wait about 55us
681 - * for things to stabilise.
683 -static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
685 - if (machine_is_collie())
686 - ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
688 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
689 - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
690 - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
691 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
692 - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
693 - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
696 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
697 - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
698 - UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
702 - return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
706 - * Switch to X plate resistance mode. Set MX to ground, PX to
707 - * supply. Measure current.
709 -static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
711 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
712 - UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
713 - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
714 - return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
718 - * Switch to Y plate resistance mode. Set MY to ground, PY to
719 - * supply. Measure current.
721 -static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
723 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
724 - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
725 - UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
726 - return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
729 -static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
731 - unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
733 - if (machine_is_collie())
734 - return (!(val & (UCB_TS_CR_TSPX_LOW)));
736 - return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
740 - * This is a RT kernel thread that handles the ADC accesses
741 - * (mainly so we can use semaphores in the UCB1200 core code
742 - * to serialise accesses to the ADC).
744 -static int ucb1x00_thread(void *_ts)
746 - struct ucb1x00_ts *ts = _ts;
747 - DECLARE_WAITQUEUE(wait, current);
751 - add_wait_queue(&ts->irq_wait, &wait);
752 - while (!kthread_should_stop()) {
753 - unsigned int x, y, p;
754 - signed long timeout;
758 - ucb1x00_adc_enable(ts->ucb);
760 - x = ucb1x00_ts_read_xpos(ts);
761 - y = ucb1x00_ts_read_ypos(ts);
762 - p = ucb1x00_ts_read_pressure(ts);
765 - * Switch back to interrupt mode.
767 - ucb1x00_ts_mode_int(ts);
768 - ucb1x00_adc_disable(ts->ucb);
772 - ucb1x00_enable(ts->ucb);
775 - if (ucb1x00_ts_pen_down(ts)) {
776 - set_current_state(TASK_INTERRUPTIBLE);
778 - ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
779 - ucb1x00_disable(ts->ucb);
782 - * If we spat out a valid sample set last time,
783 - * spit out a "pen off" sample here.
786 - ucb1x00_ts_event_release(ts);
790 - timeout = MAX_SCHEDULE_TIMEOUT;
792 - ucb1x00_disable(ts->ucb);
795 - * Filtering is policy. Policy belongs in user
796 - * space. We therefore leave it to user space
797 - * to do any filtering they please.
799 - if (!ts->restart) {
800 - ucb1x00_ts_evt_add(ts, p, x, y);
804 - set_current_state(TASK_INTERRUPTIBLE);
805 - timeout = HZ / 100;
810 - schedule_timeout(timeout);
813 - remove_wait_queue(&ts->irq_wait, &wait);
820 - * We only detect touch screen _touches_ with this interrupt
821 - * handler, and even then we just schedule our task.
823 -static void ucb1x00_ts_irq(int idx, void *id)
825 - struct ucb1x00_ts *ts = id;
827 - ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
828 - wake_up(&ts->irq_wait);
831 -static int ucb1x00_ts_open(struct input_dev *idev)
833 - struct ucb1x00_ts *ts = input_get_drvdata(idev);
838 - init_waitqueue_head(&ts->irq_wait);
839 - ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
844 - * If we do this at all, we should allow the user to
845 - * measure and read the X and Y resistance at any time.
847 - ucb1x00_adc_enable(ts->ucb);
848 - ts->x_res = ucb1x00_ts_read_xres(ts);
849 - ts->y_res = ucb1x00_ts_read_yres(ts);
850 - ucb1x00_adc_disable(ts->ucb);
852 - ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
853 - if (!IS_ERR(ts->rtask)) {
856 - ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
866 - * Release touchscreen resources. Disable IRQs.
868 -static void ucb1x00_ts_close(struct input_dev *idev)
870 - struct ucb1x00_ts *ts = input_get_drvdata(idev);
873 - kthread_stop(ts->rtask);
875 - ucb1x00_enable(ts->ucb);
876 - ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
877 - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
878 - ucb1x00_disable(ts->ucb);
882 -static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
884 - struct ucb1x00_ts *ts = dev->priv;
886 - if (ts->rtask != NULL) {
888 - * Restart the TS thread to ensure the
889 - * TS interrupt mode is set up again
893 - wake_up(&ts->irq_wait);
898 -#define ucb1x00_ts_resume NULL
905 -static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
907 - struct ucb1x00_ts *ts;
908 - struct input_dev *idev;
911 - ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
912 - idev = input_allocate_device();
913 - if (!ts || !idev) {
918 - ts->ucb = dev->ucb;
920 - ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
922 - idev->name = "Touchscreen panel";
923 - idev->id.product = ts->ucb->id;
924 - idev->open = ucb1x00_ts_open;
925 - idev->close = ucb1x00_ts_close;
927 - __set_bit(EV_ABS, idev->evbit);
928 - __set_bit(ABS_X, idev->absbit);
929 - __set_bit(ABS_Y, idev->absbit);
930 - __set_bit(ABS_PRESSURE, idev->absbit);
932 - input_set_drvdata(idev, ts);
934 - err = input_register_device(idev);
943 - input_free_device(idev);
948 -static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
950 - struct ucb1x00_ts *ts = dev->priv;
952 - input_unregister_device(ts->idev);
956 -static struct ucb1x00_driver ucb1x00_ts_driver = {
957 - .add = ucb1x00_ts_add,
958 - .remove = ucb1x00_ts_remove,
959 - .resume = ucb1x00_ts_resume,
962 -static int __init ucb1x00_ts_init(void)
964 - return ucb1x00_register_driver(&ucb1x00_ts_driver);
967 -static void __exit ucb1x00_ts_exit(void)
969 - ucb1x00_unregister_driver(&ucb1x00_ts_driver);
972 -module_param(adcsync, int, 0444);
973 -module_init(ucb1x00_ts_init);
974 -module_exit(ucb1x00_ts_exit);
976 -MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
977 -MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
978 -MODULE_LICENSE("GPL");