aboutsummaryrefslogtreecommitdiffstats
path: root/packages/linux/linux-ezx-2.6.23/patches/pcap-ts.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-ezx-2.6.23/patches/pcap-ts.patch')
-rw-r--r--packages/linux/linux-ezx-2.6.23/patches/pcap-ts.patch363
1 files changed, 363 insertions, 0 deletions
diff --git a/packages/linux/linux-ezx-2.6.23/patches/pcap-ts.patch b/packages/linux/linux-ezx-2.6.23/patches/pcap-ts.patch
new file mode 100644
index 0000000000..5891ccb837
--- /dev/null
+++ b/packages/linux/linux-ezx-2.6.23/patches/pcap-ts.patch
@@ -0,0 +1,363 @@
+Index: linux-2.6.23/drivers/input/touchscreen/Kconfig
+===================================================================
+--- linux-2.6.23.orig/drivers/input/touchscreen/Kconfig 2007-10-10 09:38:44.000000000 +0200
++++ linux-2.6.23/drivers/input/touchscreen/Kconfig 2007-10-22 22:25:02.000000000 +0200
+@@ -238,4 +238,13 @@
+ bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
+ depends on TOUCHSCREEN_USB_COMPOSITE
+
++config TOUCHSCREEN_PCAP
++ tristate "Motorola PCAP touchscreen"
++ depends on EZX_PCAP
++ help
++ Say Y here if you have a Motorola EZX telephone and
++ want to support the built-in touchscreen.
++
++ If unsure, say N.
++
+ endif
+Index: linux-2.6.23/drivers/input/touchscreen/pcap_ts.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23/drivers/input/touchscreen/pcap_ts.c 2007-10-22 22:25:02.000000000 +0200
+@@ -0,0 +1,331 @@
++/*
++ * pcap_ts.c - Touchscreen driver for Motorola PCAP2 based touchscreen as found
++ * in the EZX phone platform.
++ *
++ * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
++ * Copyright (C) 2007 Daniel Ribeiro <drwyrm@gmail.com>
++ *
++ * Based on information found in the original Motorola 2.4.x ezx-ts.c driver.
++ *
++ * 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.
++ *
++ * TODO:
++ * split this in a hardirq handler and a tasklet/bh
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/string.h>
++#include <linux/pm.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/input.h>
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/ezx-pcap.h>
++
++#if 0
++#define DEBUGP(x, args ...) printk(x, ## args)
++#else
++#define DEBUGP(x, args ...)
++#endif
++
++#define POSITION_X_MEASUREMENT 0
++#define POSITION_XY_MEASUREMENT 1
++#define PRESSURE_MEASUREMENT 2
++#define PLATE_X_MEASUREMENT 3
++#define PLATE_Y_MEASUREMENT 4
++#define STANDBY_MODE 5
++#define NONTS_MODE 6
++
++struct pcap_ts {
++ int irq_xy;
++ int irq_touch;
++ struct input_dev *input;
++ struct timer_list timer;
++ u_int16_t x, y;
++ u_int16_t pressure;
++ u_int8_t read_state;
++};
++
++#define X_AXIS_MIN 0
++#define X_AXIS_MAX 1023
++
++#define Y_AXIS_MAX X_AXIS_MAX
++#define Y_AXIS_MIN X_AXIS_MIN
++
++#define PRESSURE_MAX X_AXIS_MAX
++#define PRESSURE_MIN X_AXIS_MIN
++
++/* if we try to read faster, pressure reading becomes unreliable */
++#define SAMPLE_INTERVAL (HZ/50)
++
++
++static void pcap_ts_mode(struct pcap_ts *pcap_ts, u_int32_t mode)
++{
++ u_int32_t tmp;
++
++ pcap_ts->read_state = mode;
++ ezx_pcap_read(PCAP_REG_ADC1, &tmp);
++ tmp &= ~PCAP_ADC1_TS_M_MASK;
++ tmp |= ((mode << PCAP_ADC1_TS_M_SHIFT) & PCAP_ADC1_TS_M_MASK);
++ ezx_pcap_write(PCAP_REG_ADC1, tmp);
++}
++
++/* issue a XY read command to the ADC of PCAP2. Well get an ADCDONE interrupt
++ * once the result of the conversion is available */
++static void pcap_ts_start_xy_read(struct pcap_ts *pcap_ts)
++{
++ u_int32_t tmp;
++
++ ezx_pcap_read(PCAP_REG_ADC1, &tmp);
++ tmp &= ~(PCAP_BIT_ADC1_RAND | PCAP_ADC1_ADA1_MASK |
++ PCAP_ADC1_ADA2_MASK);
++ tmp |= (PCAP_BIT_ADC1_ADEN | PCAP_BIT_ADC1_AD_SEL1 |
++ PCAP_BIT_ADC1_AD_SEL2 | (5 << PCAP_ADC1_ADA1_SHIFT) |
++ (3 << PCAP_ADC1_ADA2_SHIFT));
++ ezx_pcap_write(PCAP_REG_ADC1, tmp);
++ ezx_pcap_bit_set(PCAP_BIT_ADC2_ASC, 1);
++}
++
++/* read the XY result from the ADC of PCAP2 */
++static void pcap_ts_get_xy_value(struct pcap_ts *pcap_ts)
++{
++ u_int32_t tmp;
++
++ ezx_pcap_read(PCAP_REG_ADC2, &tmp);
++
++ if (pcap_ts->read_state == POSITION_XY_MEASUREMENT) {
++ pcap_ts->x = (tmp & PCAP_ADC2_ADD1_MASK) >>
++ PCAP_ADC2_ADD1_SHIFT;
++ pcap_ts->y = (tmp & PCAP_ADC2_ADD2_MASK) >>
++ PCAP_ADC2_ADD2_SHIFT;
++ } else {
++ pcap_ts->pressure = (tmp & PCAP_ADC2_ADD2_MASK) >>
++ PCAP_ADC2_ADD2_SHIFT;
++ }
++}
++
++/* PCAP2 interrupts us when ADC conversion result is available */
++static irqreturn_t pcap_ts_irq_xy(int irq, void *dev_id)
++{
++ struct pcap_ts *pcap_ts = dev_id;
++
++ pcap_ts_get_xy_value(pcap_ts);
++ DEBUGP(KERN_DEBUG "%s X=%4d, Y=%4d Z=%4d ",
++ pcap_ts->read_state == POSITION_XY_MEASUREMENT ? "COORD" :
++ "PRESS", pcap_ts->x, pcap_ts->y, pcap_ts->pressure);
++ switch (pcap_ts->read_state) {
++ case PRESSURE_MEASUREMENT:
++ if (pcap_ts->pressure >= PRESSURE_MAX ||
++ pcap_ts->pressure <= PRESSURE_MIN ) {
++ /* pen has been released (or cant read pressure - WM)*/
++ DEBUGP("UP\n");
++ /* do nothing */
++ } else {
++ /* pen has been touched down */
++ DEBUGP("DOWN\n");
++ input_report_key(pcap_ts->input, BTN_TOUCH, 1);
++ input_report_abs(pcap_ts->input, ABS_PRESSURE, pcap_ts->pressure);
++ }
++ /* switch state machine into coordinate read mode */
++ pcap_ts_mode(pcap_ts, POSITION_XY_MEASUREMENT);
++ pcap_ts_start_xy_read(pcap_ts);
++ break;
++ case POSITION_XY_MEASUREMENT:
++ if (pcap_ts->x <= X_AXIS_MIN || pcap_ts->x >= X_AXIS_MAX ||
++ pcap_ts->y <= Y_AXIS_MIN || pcap_ts->y >= Y_AXIS_MAX) {
++ /* pen has been released */
++ DEBUGP("UP END\n");
++
++ input_report_key(pcap_ts->input, BTN_TOUCH, 0);
++ input_report_abs(pcap_ts->input, ABS_PRESSURE, 0);
++
++ /* no need for timer, we'll get interrupted with
++ * next touch down event */
++ del_timer(&pcap_ts->timer);
++
++ /* ask PCAP2 to interrupt us if touch event happens
++ * again */
++ pcap_ts_mode(pcap_ts, STANDBY_MODE);
++ enable_irq(pcap_ts->irq_touch);
++ } else {
++ DEBUGP("DOWN\n");
++ input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
++ input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
++
++ /* switch back to pressure read mode */
++ pcap_ts_mode(pcap_ts, PRESSURE_MEASUREMENT);
++ mod_timer(&pcap_ts->timer, jiffies + SAMPLE_INTERVAL);
++ }
++ input_sync(pcap_ts->input);
++ break;
++ default:
++ DEBUGP("ERROR\n");
++ break;
++ }
++ return IRQ_HANDLED;
++}
++
++/* PCAP2 interrupts us if the pen touches down (interrupts also on pen up - WM)*/
++static irqreturn_t pcap_ts_irq_touch(int irq, void *dev_id)
++{
++ struct pcap_ts *pcap_ts = dev_id;
++ /* mask Touchscreen interrupt bit, prevents further touch events
++ * from being reported to us until we're finished with reading
++ * both pressure and x/y from ADC */
++ disable_irq(pcap_ts->irq_touch);
++
++ DEBUGP("touched!!\n");
++ pcap_ts_mode(pcap_ts, PRESSURE_MEASUREMENT);
++ pcap_ts_start_xy_read(pcap_ts);
++ return IRQ_HANDLED;
++}
++
++static void pcap_ts_timer_fn(unsigned long data)
++{
++ struct pcap_ts *pcap_ts = (struct pcap_ts *) data;
++
++ pcap_ts_start_xy_read(pcap_ts);
++}
++
++static int __init ezxts_probe(struct platform_device *pdev)
++{
++ struct pcap_ts *pcap_ts;
++ struct input_dev *input_dev;
++ int err = -ENOMEM;
++
++ pcap_ts = kzalloc(sizeof(*pcap_ts), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!pcap_ts || !input_dev)
++ goto fail;
++
++ pcap_ts->irq_xy = platform_get_irq(pdev, 0);
++ if (pcap_ts->irq_xy < 0) {
++ err = pcap_ts->irq_xy;
++ goto fail;
++ }
++
++ pcap_ts->irq_touch = platform_get_irq(pdev, 1);
++ if (pcap_ts->irq_touch < 0) {
++ err = pcap_ts->irq_touch;
++ goto fail;
++ }
++
++ ezx_pcap_bit_set(PCAP_BIT_ADC1_TS_REFENB, 0);
++ pcap_ts_mode(pcap_ts, STANDBY_MODE);
++
++ err = request_irq(pcap_ts->irq_xy, pcap_ts_irq_xy, IRQF_DISABLED,
++ "pcap-ts X/Y", pcap_ts);
++ if (err < 0) {
++ printk(KERN_ERR "pcap_ts: can't grab xy irq %d: %d\n",
++ pcap_ts->irq_xy, err);
++ goto fail;
++ }
++
++ err = request_irq(pcap_ts->irq_touch, pcap_ts_irq_touch, IRQF_DISABLED,
++ "pcap-ts touch", pcap_ts);
++ if (err < 0) {
++ printk(KERN_ERR "pcap_ts: can't grab touch irq %d: %d\n",
++ pcap_ts->irq_touch, err);
++ goto fail_xy;
++ }
++
++ pcap_ts->input = input_dev;
++ init_timer(&pcap_ts->timer);
++ pcap_ts->timer.data = (unsigned long) pcap_ts;
++ pcap_ts->timer.function = &pcap_ts_timer_fn;
++
++ platform_set_drvdata(pdev, pcap_ts);
++
++ input_dev->name = "pcap-touchscreen";
++ input_dev->phys = "ezxts/input0";
++ input_dev->id.bustype = BUS_HOST;
++ input_dev->id.vendor = 0x0001;
++ input_dev->id.product = 0x0002;
++ input_dev->id.version = 0x0100;
++ input_dev->cdev.dev = &pdev->dev;
++ input_dev->private = pcap_ts;
++
++ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
++ input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
++ input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
++ input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN,
++ PRESSURE_MAX, 0, 0);
++
++ input_register_device(pcap_ts->input);
++
++ return 0;
++
++fail_xy:
++ free_irq(pcap_ts->irq_xy, pcap_ts);
++fail:
++ input_free_device(input_dev);
++ kfree(pcap_ts);
++
++ return err;
++}
++
++static int ezxts_remove(struct platform_device *pdev)
++{
++ struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
++
++ del_timer_sync(&pcap_ts->timer);
++
++ free_irq(pcap_ts->irq_touch, pcap_ts);
++ free_irq(pcap_ts->irq_xy, pcap_ts);
++
++ input_unregister_device(pcap_ts->input);
++ kfree(pcap_ts);
++
++ return 0;
++}
++
++static int ezxts_suspend(struct platform_device *dev, pm_message_t state)
++{
++ ezx_pcap_bit_set(PCAP_BIT_ADC1_TS_REF_LOWPWR, 1);
++ return 0;
++}
++
++static int ezxts_resume(struct platform_device *dev)
++{
++ ezx_pcap_bit_set(PCAP_BIT_ADC1_TS_REF_LOWPWR, 0);
++ /* just in case we suspend with TSI masked. */
++// ezx_pcap_bit_set(PCAP_BIT_MSR_TSM, 0);
++ return 0;
++}
++
++
++static struct platform_driver ezxts_driver = {
++ .probe = ezxts_probe,
++ .remove = ezxts_remove,
++ .suspend = ezxts_suspend,
++ .resume = ezxts_resume,
++ .driver = {
++ .name = "pcap-ts",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ezxts_init(void)
++{
++ return platform_driver_register(&ezxts_driver);
++}
++
++static void __exit ezxts_exit(void)
++{
++ platform_driver_unregister(&ezxts_driver);
++}
++
++module_init(ezxts_init);
++module_exit(ezxts_exit);
++
++MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver");
++MODULE_AUTHOR("Harald Welte <laforge@openezx.org>");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.23/drivers/input/touchscreen/Makefile
+===================================================================
+--- linux-2.6.23.orig/drivers/input/touchscreen/Makefile 2007-10-10 09:38:44.000000000 +0200
++++ linux-2.6.23/drivers/input/touchscreen/Makefile 2007-10-22 22:25:02.000000000 +0200
+@@ -18,3 +18,4 @@
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
+ obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
++obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o