aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.28/collie/0012-move-ucb1200-ts-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.28/collie/0012-move-ucb1200-ts-driver.patch')
-rw-r--r--recipes/linux/linux-2.6.28/collie/0012-move-ucb1200-ts-driver.patch981
1 files changed, 0 insertions, 981 deletions
diff --git a/recipes/linux/linux-2.6.28/collie/0012-move-ucb1200-ts-driver.patch b/recipes/linux/linux-2.6.28/collie/0012-move-ucb1200-ts-driver.patch
deleted file mode 100644
index c1aafef5e2..0000000000
--- a/recipes/linux/linux-2.6.28/collie/0012-move-ucb1200-ts-driver.patch
+++ /dev/null
@@ -1,981 +0,0 @@
-From 9e0d71c4a6247d88d3b772f6b05bcaa39711a937 Mon Sep 17 00:00:00 2001
-From: Thomas Kunze <thommycheck@gmx.de>
-Date: Tue, 10 Feb 2009 19:31:25 +0100
-Subject: [PATCH 12/23] move ucb1200-ts driver
-
-Move the touchscreen driver to drivers/input/touchscreen
-where touchscreen drivers belong.
-
-Conflicts:
-
- drivers/input/touchscreen/Makefile
- drivers/mfd/Kconfig
- drivers/mfd/Makefile
-
-Conflicts:
-
- drivers/mfd/Kconfig
- drivers/mfd/Makefile
----
- drivers/input/touchscreen/Kconfig | 7 +
- drivers/input/touchscreen/Makefile | 1 +
- drivers/input/touchscreen/ucb1x00-ts.c | 438 ++++++++++++++++++++++++++++++++
- drivers/mfd/Kconfig | 3 -
- drivers/mfd/Makefile | 3 +-
- drivers/mfd/ucb1x00-ts.c | 438 --------------------------------
- 6 files changed, 447 insertions(+), 443 deletions(-)
- create mode 100644 drivers/input/touchscreen/ucb1x00-ts.c
- delete mode 100644 drivers/mfd/ucb1x00-ts.c
-
-diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
-index 3d1ab8f..3ac8cd6 100644
---- a/drivers/input/touchscreen/Kconfig
-+++ b/drivers/input/touchscreen/Kconfig
-@@ -221,6 +221,13 @@ config TOUCHSCREEN_ATMEL_TSADCC
- To compile this driver as a module, choose M here: the
- module will be called atmel_tsadcc.
-
-+config TOUCHSCREEN_UCB1200_TS
-+ tristate "Philips UCB1200 touchscreen"
-+ depends on MCP_UCB1200
-+ help
-+ This enabled support for the Pilips UCB1200 touchscreen interface
-+ and compatible.
-+
- config TOUCHSCREEN_UCB1400
- tristate "Philips UCB1400 touchscreen"
- depends on AC97_BUS
-diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
-index 15cf290..77ba930 100644
---- a/drivers/input/touchscreen/Makefile
-+++ b/drivers/input/touchscreen/Makefile
-@@ -25,6 +25,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
- obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
- obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
- obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
-+obj-$(CONFIG_TOUCHSCREEN_UCB1200_TS) += ucb1x00-ts.o
- obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
- obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
- wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
-diff --git a/drivers/input/touchscreen/ucb1x00-ts.c b/drivers/input/touchscreen/ucb1x00-ts.c
-new file mode 100644
-index 0000000..b5feae9
---- /dev/null
-+++ b/drivers/input/touchscreen/ucb1x00-ts.c
-@@ -0,0 +1,438 @@
-+/*
-+ * Touchscreen driver for UCB1x00-based touchscreens
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ * Copyright (C) 2005 Pavel Machek
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 21-Jan-2002 <jco@ict.es> :
-+ *
-+ * Added support for synchronous A/D mode. This mode is useful to
-+ * avoid noise induced in the touchpanel by the LCD, provided that
-+ * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
-+ * It is important to note that the signal connected to the ADCSYNC
-+ * pin should provide pulses even when the LCD is blanked, otherwise
-+ * a pen touch needed to unblank the LCD will never be read.
-+ */
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/init.h>
-+#include <linux/smp.h>
-+#include <linux/sched.h>
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/string.h>
-+#include <linux/input.h>
-+#include <linux/device.h>
-+#include <linux/freezer.h>
-+#include <linux/slab.h>
-+#include <linux/kthread.h>
-+#include <linux/mfd/ucb1x00.h>
-+
-+#include <asm/dma.h>
-+#include <mach/collie.h>
-+#include <asm/mach-types.h>
-+
-+
-+
-+struct ucb1x00_ts {
-+ struct input_dev *idev;
-+ struct ucb1x00 *ucb;
-+
-+ wait_queue_head_t irq_wait;
-+ struct task_struct *rtask;
-+ u16 x_res;
-+ u16 y_res;
-+
-+ unsigned int restart:1;
-+ unsigned int adcsync:1;
-+};
-+
-+static int adcsync;
-+
-+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
-+{
-+ struct input_dev *idev = ts->idev;
-+
-+ input_report_abs(idev, ABS_X, x);
-+ input_report_abs(idev, ABS_Y, y);
-+ input_report_abs(idev, ABS_PRESSURE, pressure);
-+ input_sync(idev);
-+}
-+
-+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
-+{
-+ struct input_dev *idev = ts->idev;
-+
-+ input_report_abs(idev, ABS_PRESSURE, 0);
-+ input_sync(idev);
-+}
-+
-+/*
-+ * Switch to interrupt mode.
-+ */
-+static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_INT);
-+}
-+
-+/*
-+ * Switch to pressure mode, and read pressure. We don't need to wait
-+ * here, since both plates are being driven.
-+ */
-+static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
-+{
-+ if (machine_is_collie()) {
-+ ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW |
-+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-+
-+ udelay(55);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync);
-+ } else {
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
-+ }
-+}
-+
-+/*
-+ * Switch to X position mode and measure Y plate. We switch the plate
-+ * configuration in pressure mode, then switch to position mode. This
-+ * gives a faster response time. Even so, we need to wait about 55us
-+ * for things to stabilise.
-+ */
-+static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
-+{
-+ if (machine_is_collie())
-+ ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
-+ else {
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ }
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-+
-+ udelay(55);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to Y position mode and measure X plate. We switch the plate
-+ * configuration in pressure mode, then switch to position mode. This
-+ * gives a faster response time. Even so, we need to wait about 55us
-+ * for things to stabilise.
-+ */
-+static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
-+{
-+ if (machine_is_collie())
-+ ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
-+ else {
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ }
-+
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-+
-+ udelay(55);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to X plate resistance mode. Set MX to ground, PX to
-+ * supply. Measure current.
-+ */
-+static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to Y plate resistance mode. Set MY to ground, PY to
-+ * supply. Measure current.
-+ */
-+static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
-+}
-+
-+static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
-+{
-+ unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
-+
-+ if (machine_is_collie())
-+ return (!(val & (UCB_TS_CR_TSPX_LOW)));
-+ else
-+ return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
-+}
-+
-+/*
-+ * This is a RT kernel thread that handles the ADC accesses
-+ * (mainly so we can use semaphores in the UCB1200 core code
-+ * to serialise accesses to the ADC).
-+ */
-+static int ucb1x00_thread(void *_ts)
-+{
-+ struct ucb1x00_ts *ts = _ts;
-+ DECLARE_WAITQUEUE(wait, current);
-+ int valid = 0;
-+
-+ set_freezable();
-+ add_wait_queue(&ts->irq_wait, &wait);
-+ while (!kthread_should_stop()) {
-+ unsigned int x, y, p;
-+ signed long timeout;
-+
-+ ts->restart = 0;
-+
-+ ucb1x00_adc_enable(ts->ucb);
-+
-+ x = ucb1x00_ts_read_xpos(ts);
-+ y = ucb1x00_ts_read_ypos(ts);
-+ p = ucb1x00_ts_read_pressure(ts);
-+
-+ /*
-+ * Switch back to interrupt mode.
-+ */
-+ ucb1x00_ts_mode_int(ts);
-+ ucb1x00_adc_disable(ts->ucb);
-+
-+ msleep(10);
-+
-+ ucb1x00_enable(ts->ucb);
-+
-+
-+ if (ucb1x00_ts_pen_down(ts)) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
-+ ucb1x00_disable(ts->ucb);
-+
-+ /*
-+ * If we spat out a valid sample set last time,
-+ * spit out a "pen off" sample here.
-+ */
-+ if (valid) {
-+ ucb1x00_ts_event_release(ts);
-+ valid = 0;
-+ }
-+
-+ timeout = MAX_SCHEDULE_TIMEOUT;
-+ } else {
-+ ucb1x00_disable(ts->ucb);
-+
-+ /*
-+ * Filtering is policy. Policy belongs in user
-+ * space. We therefore leave it to user space
-+ * to do any filtering they please.
-+ */
-+ if (!ts->restart) {
-+ ucb1x00_ts_evt_add(ts, p, x, y);
-+ valid = 1;
-+ }
-+
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ timeout = HZ / 100;
-+ }
-+
-+ try_to_freeze();
-+
-+ schedule_timeout(timeout);
-+ }
-+
-+ remove_wait_queue(&ts->irq_wait, &wait);
-+
-+ ts->rtask = NULL;
-+ return 0;
-+}
-+
-+/*
-+ * We only detect touch screen _touches_ with this interrupt
-+ * handler, and even then we just schedule our task.
-+ */
-+static void ucb1x00_ts_irq(int idx, void *id)
-+{
-+ struct ucb1x00_ts *ts = id;
-+
-+ ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-+ wake_up(&ts->irq_wait);
-+}
-+
-+static int ucb1x00_ts_open(struct input_dev *idev)
-+{
-+ struct ucb1x00_ts *ts = input_get_drvdata(idev);
-+ int ret = 0;
-+
-+ BUG_ON(ts->rtask);
-+
-+ init_waitqueue_head(&ts->irq_wait);
-+ ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
-+ if (ret < 0)
-+ goto out;
-+
-+ /*
-+ * If we do this at all, we should allow the user to
-+ * measure and read the X and Y resistance at any time.
-+ */
-+ ucb1x00_adc_enable(ts->ucb);
-+ ts->x_res = ucb1x00_ts_read_xres(ts);
-+ ts->y_res = ucb1x00_ts_read_yres(ts);
-+ ucb1x00_adc_disable(ts->ucb);
-+
-+ ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
-+ if (!IS_ERR(ts->rtask)) {
-+ ret = 0;
-+ } else {
-+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
-+ ts->rtask = NULL;
-+ ret = -EFAULT;
-+ }
-+
-+ out:
-+ return ret;
-+}
-+
-+/*
-+ * Release touchscreen resources. Disable IRQs.
-+ */
-+static void ucb1x00_ts_close(struct input_dev *idev)
-+{
-+ struct ucb1x00_ts *ts = input_get_drvdata(idev);
-+
-+ if (ts->rtask)
-+ kthread_stop(ts->rtask);
-+
-+ ucb1x00_enable(ts->ucb);
-+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
-+ ucb1x00_disable(ts->ucb);
-+}
-+
-+#ifdef CONFIG_PM
-+static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
-+{
-+ struct ucb1x00_ts *ts = dev->priv;
-+
-+ if (ts->rtask != NULL) {
-+ /*
-+ * Restart the TS thread to ensure the
-+ * TS interrupt mode is set up again
-+ * after sleep.
-+ */
-+ ts->restart = 1;
-+ wake_up(&ts->irq_wait);
-+ }
-+ return 0;
-+}
-+#else
-+#define ucb1x00_ts_resume NULL
-+#endif
-+
-+
-+/*
-+ * Initialisation.
-+ */
-+static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
-+{
-+ struct ucb1x00_ts *ts;
-+ struct input_dev *idev;
-+ int err;
-+
-+ ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
-+ idev = input_allocate_device();
-+ if (!ts || !idev) {
-+ err = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ ts->ucb = dev->ucb;
-+ ts->idev = idev;
-+ ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
-+
-+ idev->name = "Touchscreen panel";
-+ idev->id.product = ts->ucb->id;
-+ idev->open = ucb1x00_ts_open;
-+ idev->close = ucb1x00_ts_close;
-+
-+ __set_bit(EV_ABS, idev->evbit);
-+ __set_bit(ABS_X, idev->absbit);
-+ __set_bit(ABS_Y, idev->absbit);
-+ __set_bit(ABS_PRESSURE, idev->absbit);
-+
-+ input_set_drvdata(idev, ts);
-+
-+ err = input_register_device(idev);
-+ if (err)
-+ goto fail;
-+
-+ dev->priv = ts;
-+
-+ return 0;
-+
-+ fail:
-+ input_free_device(idev);
-+ kfree(ts);
-+ return err;
-+}
-+
-+static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
-+{
-+ struct ucb1x00_ts *ts = dev->priv;
-+
-+ input_unregister_device(ts->idev);
-+ kfree(ts);
-+}
-+
-+static struct ucb1x00_driver ucb1x00_ts_driver = {
-+ .add = ucb1x00_ts_add,
-+ .remove = ucb1x00_ts_remove,
-+ .resume = ucb1x00_ts_resume,
-+};
-+
-+static int __init ucb1x00_ts_init(void)
-+{
-+ return ucb1x00_register_driver(&ucb1x00_ts_driver);
-+}
-+
-+static void __exit ucb1x00_ts_exit(void)
-+{
-+ ucb1x00_unregister_driver(&ucb1x00_ts_driver);
-+}
-+
-+module_param(adcsync, int, 0444);
-+module_init(ucb1x00_ts_init);
-+module_exit(ucb1x00_ts_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
-index 2572773..bbc137d 100644
---- a/drivers/mfd/Kconfig
-+++ b/drivers/mfd/Kconfig
-@@ -172,8 +172,5 @@ config MCP_UCB1200
- tristate "Support for UCB1200 / UCB1300"
- depends on MCP
-
--config MCP_UCB1200_TS
-- tristate "Touchscreen interface support"
-- depends on MCP_UCB1200 && INPUT
-
- endmenu
-diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
-index 9a5ad8a..4981aff 100644
---- a/drivers/mfd/Makefile
-+++ b/drivers/mfd/Makefile
-@@ -24,11 +24,10 @@ obj-$(CONFIG_MFD_CORE) += mfd-core.o
- obj-$(CONFIG_MCP) += mcp-core.o
- obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
- obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
--obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
-
- ifeq ($(CONFIG_SA1100_ASSABET),y)
- obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
- endif
- obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
-
--obj-$(CONFIG_PMIC_DA903X) += da903x.o
-\ No newline at end of file
-+obj-$(CONFIG_PMIC_DA903X) += da903x.o
-diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
-deleted file mode 100644
-index b5feae9..0000000
---- a/drivers/mfd/ucb1x00-ts.c
-+++ /dev/null
-@@ -1,438 +0,0 @@
--/*
-- * Touchscreen driver for UCB1x00-based touchscreens
-- *
-- * Copyright (C) 2001 Russell King, All Rights Reserved.
-- * Copyright (C) 2005 Pavel Machek
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- *
-- * 21-Jan-2002 <jco@ict.es> :
-- *
-- * Added support for synchronous A/D mode. This mode is useful to
-- * avoid noise induced in the touchpanel by the LCD, provided that
-- * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
-- * It is important to note that the signal connected to the ADCSYNC
-- * pin should provide pulses even when the LCD is blanked, otherwise
-- * a pen touch needed to unblank the LCD will never be read.
-- */
--#include <linux/module.h>
--#include <linux/moduleparam.h>
--#include <linux/init.h>
--#include <linux/smp.h>
--#include <linux/sched.h>
--#include <linux/completion.h>
--#include <linux/delay.h>
--#include <linux/string.h>
--#include <linux/input.h>
--#include <linux/device.h>
--#include <linux/freezer.h>
--#include <linux/slab.h>
--#include <linux/kthread.h>
--#include <linux/mfd/ucb1x00.h>
--
--#include <asm/dma.h>
--#include <mach/collie.h>
--#include <asm/mach-types.h>
--
--
--
--struct ucb1x00_ts {
-- struct input_dev *idev;
-- struct ucb1x00 *ucb;
--
-- wait_queue_head_t irq_wait;
-- struct task_struct *rtask;
-- u16 x_res;
-- u16 y_res;
--
-- unsigned int restart:1;
-- unsigned int adcsync:1;
--};
--
--static int adcsync;
--
--static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
--{
-- struct input_dev *idev = ts->idev;
--
-- input_report_abs(idev, ABS_X, x);
-- input_report_abs(idev, ABS_Y, y);
-- input_report_abs(idev, ABS_PRESSURE, pressure);
-- input_sync(idev);
--}
--
--static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
--{
-- struct input_dev *idev = ts->idev;
--
-- input_report_abs(idev, ABS_PRESSURE, 0);
-- input_sync(idev);
--}
--
--/*
-- * Switch to interrupt mode.
-- */
--static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
--{
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-- UCB_TS_CR_MODE_INT);
--}
--
--/*
-- * Switch to pressure mode, and read pressure. We don't need to wait
-- * here, since both plates are being driven.
-- */
--static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
--{
-- if (machine_is_collie()) {
-- ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0);
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW |
-- UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
--
-- udelay(55);
--
-- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync);
-- } else {
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
--
-- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
-- }
--}
--
--/*
-- * Switch to X position mode and measure Y plate. We switch the plate
-- * configuration in pressure mode, then switch to position mode. This
-- * gives a faster response time. Even so, we need to wait about 55us
-- * for things to stabilise.
-- */
--static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
--{
-- if (machine_is_collie())
-- ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
-- else {
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-- }
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-- UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
--
-- udelay(55);
--
-- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
--}
--
--/*
-- * Switch to Y position mode and measure X plate. We switch the plate
-- * configuration in pressure mode, then switch to position mode. This
-- * gives a faster response time. Even so, we need to wait about 55us
-- * for things to stabilise.
-- */
--static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
--{
-- if (machine_is_collie())
-- ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
-- else {
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-- }
--
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-- UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
--
-- udelay(55);
--
-- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
--}
--
--/*
-- * Switch to X plate resistance mode. Set MX to ground, PX to
-- * supply. Measure current.
-- */
--static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
--{
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-- return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
--}
--
--/*
-- * Switch to Y plate resistance mode. Set MY to ground, PY to
-- * supply. Measure current.
-- */
--static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
--{
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-- UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-- return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
--}
--
--static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
--{
-- unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
--
-- if (machine_is_collie())
-- return (!(val & (UCB_TS_CR_TSPX_LOW)));
-- else
-- return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
--}
--
--/*
-- * This is a RT kernel thread that handles the ADC accesses
-- * (mainly so we can use semaphores in the UCB1200 core code
-- * to serialise accesses to the ADC).
-- */
--static int ucb1x00_thread(void *_ts)
--{
-- struct ucb1x00_ts *ts = _ts;
-- DECLARE_WAITQUEUE(wait, current);
-- int valid = 0;
--
-- set_freezable();
-- add_wait_queue(&ts->irq_wait, &wait);
-- while (!kthread_should_stop()) {
-- unsigned int x, y, p;
-- signed long timeout;
--
-- ts->restart = 0;
--
-- ucb1x00_adc_enable(ts->ucb);
--
-- x = ucb1x00_ts_read_xpos(ts);
-- y = ucb1x00_ts_read_ypos(ts);
-- p = ucb1x00_ts_read_pressure(ts);
--
-- /*
-- * Switch back to interrupt mode.
-- */
-- ucb1x00_ts_mode_int(ts);
-- ucb1x00_adc_disable(ts->ucb);
--
-- msleep(10);
--
-- ucb1x00_enable(ts->ucb);
--
--
-- if (ucb1x00_ts_pen_down(ts)) {
-- set_current_state(TASK_INTERRUPTIBLE);
--
-- ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
-- ucb1x00_disable(ts->ucb);
--
-- /*
-- * If we spat out a valid sample set last time,
-- * spit out a "pen off" sample here.
-- */
-- if (valid) {
-- ucb1x00_ts_event_release(ts);
-- valid = 0;
-- }
--
-- timeout = MAX_SCHEDULE_TIMEOUT;
-- } else {
-- ucb1x00_disable(ts->ucb);
--
-- /*
-- * Filtering is policy. Policy belongs in user
-- * space. We therefore leave it to user space
-- * to do any filtering they please.
-- */
-- if (!ts->restart) {
-- ucb1x00_ts_evt_add(ts, p, x, y);
-- valid = 1;
-- }
--
-- set_current_state(TASK_INTERRUPTIBLE);
-- timeout = HZ / 100;
-- }
--
-- try_to_freeze();
--
-- schedule_timeout(timeout);
-- }
--
-- remove_wait_queue(&ts->irq_wait, &wait);
--
-- ts->rtask = NULL;
-- return 0;
--}
--
--/*
-- * We only detect touch screen _touches_ with this interrupt
-- * handler, and even then we just schedule our task.
-- */
--static void ucb1x00_ts_irq(int idx, void *id)
--{
-- struct ucb1x00_ts *ts = id;
--
-- ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-- wake_up(&ts->irq_wait);
--}
--
--static int ucb1x00_ts_open(struct input_dev *idev)
--{
-- struct ucb1x00_ts *ts = input_get_drvdata(idev);
-- int ret = 0;
--
-- BUG_ON(ts->rtask);
--
-- init_waitqueue_head(&ts->irq_wait);
-- ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
-- if (ret < 0)
-- goto out;
--
-- /*
-- * If we do this at all, we should allow the user to
-- * measure and read the X and Y resistance at any time.
-- */
-- ucb1x00_adc_enable(ts->ucb);
-- ts->x_res = ucb1x00_ts_read_xres(ts);
-- ts->y_res = ucb1x00_ts_read_yres(ts);
-- ucb1x00_adc_disable(ts->ucb);
--
-- ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
-- if (!IS_ERR(ts->rtask)) {
-- ret = 0;
-- } else {
-- ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
-- ts->rtask = NULL;
-- ret = -EFAULT;
-- }
--
-- out:
-- return ret;
--}
--
--/*
-- * Release touchscreen resources. Disable IRQs.
-- */
--static void ucb1x00_ts_close(struct input_dev *idev)
--{
-- struct ucb1x00_ts *ts = input_get_drvdata(idev);
--
-- if (ts->rtask)
-- kthread_stop(ts->rtask);
--
-- ucb1x00_enable(ts->ucb);
-- ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
-- ucb1x00_disable(ts->ucb);
--}
--
--#ifdef CONFIG_PM
--static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
--{
-- struct ucb1x00_ts *ts = dev->priv;
--
-- if (ts->rtask != NULL) {
-- /*
-- * Restart the TS thread to ensure the
-- * TS interrupt mode is set up again
-- * after sleep.
-- */
-- ts->restart = 1;
-- wake_up(&ts->irq_wait);
-- }
-- return 0;
--}
--#else
--#define ucb1x00_ts_resume NULL
--#endif
--
--
--/*
-- * Initialisation.
-- */
--static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
--{
-- struct ucb1x00_ts *ts;
-- struct input_dev *idev;
-- int err;
--
-- ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
-- idev = input_allocate_device();
-- if (!ts || !idev) {
-- err = -ENOMEM;
-- goto fail;
-- }
--
-- ts->ucb = dev->ucb;
-- ts->idev = idev;
-- ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
--
-- idev->name = "Touchscreen panel";
-- idev->id.product = ts->ucb->id;
-- idev->open = ucb1x00_ts_open;
-- idev->close = ucb1x00_ts_close;
--
-- __set_bit(EV_ABS, idev->evbit);
-- __set_bit(ABS_X, idev->absbit);
-- __set_bit(ABS_Y, idev->absbit);
-- __set_bit(ABS_PRESSURE, idev->absbit);
--
-- input_set_drvdata(idev, ts);
--
-- err = input_register_device(idev);
-- if (err)
-- goto fail;
--
-- dev->priv = ts;
--
-- return 0;
--
-- fail:
-- input_free_device(idev);
-- kfree(ts);
-- return err;
--}
--
--static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
--{
-- struct ucb1x00_ts *ts = dev->priv;
--
-- input_unregister_device(ts->idev);
-- kfree(ts);
--}
--
--static struct ucb1x00_driver ucb1x00_ts_driver = {
-- .add = ucb1x00_ts_add,
-- .remove = ucb1x00_ts_remove,
-- .resume = ucb1x00_ts_resume,
--};
--
--static int __init ucb1x00_ts_init(void)
--{
-- return ucb1x00_register_driver(&ucb1x00_ts_driver);
--}
--
--static void __exit ucb1x00_ts_exit(void)
--{
-- ucb1x00_unregister_driver(&ucb1x00_ts_driver);
--}
--
--module_param(adcsync, int, 0444);
--module_init(ucb1x00_ts_init);
--module_exit(ucb1x00_ts_exit);
--
--MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
--MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
--MODULE_LICENSE("GPL");
---
-1.5.6.5
-