linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 08/14] input: PCAP2 based touchscreen driver
       [not found] <20081121160403.073751031@dodger.lab.datenfreihafen.org>
@ 2008-11-21 16:04 ` stefan
  2008-11-21 17:05   ` Dmitry Torokhov
  0 siblings, 1 reply; 5+ messages in thread
From: stefan @ 2008-11-21 16:04 UTC (permalink / raw)
  To: eric.y.miao, dmitry.torokhov
  Cc: linux-arm-kernel, linux-input, linux-kernel, Daniel Ribeiro

[-- Attachment #1: ezx/pcap_ts.diff --]
[-- Type: text/plain, Size: 8641 bytes --]

Touchscreen driver based on the PCAP2 multi function device.

Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com>

---
 drivers/input/touchscreen/Kconfig   |    9 ++
 drivers/input/touchscreen/Makefile  |    1 +
 drivers/input/touchscreen/pcap_ts.c |  258 +++++++++++++++++++++++++++++++++++
 3 files changed, 268 insertions(+), 0 deletions(-)

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3d1ab8f..a1bd364 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -376,4 +376,13 @@ config TOUCHSCREEN_TOUCHIT213
 	  To compile this driver as a module, choose M here: the
 	  module will be called touchit213.
 
+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
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 15cf290..97d8931 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -31,3 +31,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)	+= wm9705.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)	+= wm9712.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713)	+= wm9713.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
new file mode 100644
index 0000000..ea18aff
--- /dev/null
+++ b/drivers/input/touchscreen/pcap_ts.c
@@ -0,0 +1,258 @@
+/*
+ * 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-2008 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.
+ *
+ */
+
+#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 <linux/mfd/ezx-pcap.h>
+
+struct pcap_ts {
+	struct input_dev *input;
+	struct timer_list timer;
+	struct work_struct work;
+	u16 x, y;
+	u16 pressure;
+	u8 read_state;
+};
+
+struct pcap_ts *pcap_ts;
+
+#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_read_xy(void)
+{
+	u32 res[2];
+
+	ezx_pcap_get_adc_channel_result(PCAP_ADC_CH_TS_X1, PCAP_ADC_CH_TS_Y1,
+									res);
+	ezx_pcap_disable_adc();
+
+	switch (pcap_ts->read_state) {
+	case PCAP_ADC_TS_M_PRESSURE:
+		/* save pressure, start xy read */
+		pcap_ts->pressure = res[0];
+		pcap_ts->read_state = PCAP_ADC_TS_M_XY;
+		schedule_work(&pcap_ts->work);
+		break;
+	case PCAP_ADC_TS_M_XY:
+		pcap_ts->y = res[0];
+		pcap_ts->x = res[1];
+		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 ||
+		    pcap_ts->pressure <= PRESSURE_MIN ||
+		    pcap_ts->pressure >= PRESSURE_MAX) {
+			/* pen has been released */
+			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->read_state = PCAP_ADC_TS_M_STANDBY;
+			ezx_pcap_unmask_event(PCAP_IRQ_TS);
+			schedule_work(&pcap_ts->work);
+		} else {
+			/* pen is touching the screen*/
+			input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
+			input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
+			input_report_key(pcap_ts->input, BTN_TOUCH, 1);
+			input_report_abs(pcap_ts->input, ABS_PRESSURE,
+						pcap_ts->pressure);
+
+			/* switch back to pressure read mode */
+			pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
+			mod_timer(&pcap_ts->timer,
+					jiffies + SAMPLE_INTERVAL);
+		}
+		input_sync(pcap_ts->input);
+		break;
+	default:
+		break;
+	}
+}
+
+static void pcap_ts_work(struct work_struct *unused)
+{
+	u32 tmp;
+
+	switch (pcap_ts->read_state) {
+	case PCAP_ADC_TS_M_STANDBY:
+		/* set TS to standby */
+		ezx_pcap_read(PCAP_REG_ADC, &tmp);
+		tmp &= ~PCAP_ADC_TS_M_MASK;
+		tmp |= (PCAP_ADC_TS_M_STANDBY << PCAP_ADC_TS_M_SHIFT);
+		ezx_pcap_write(PCAP_REG_ADC, tmp);
+		break;
+	case PCAP_ADC_TS_M_PRESSURE:
+	case PCAP_ADC_TS_M_XY:
+		/* start adc conversion */
+		ezx_pcap_start_adc(PCAP_ADC_BANK_1, PCAP_ADC_T_NOW,
+			(pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT),
+						pcap_ts_read_xy, NULL);
+		break;
+	}
+}
+
+static void pcap_ts_event_touch(u32 events)
+{
+	/* pen touch down, mask touch event and start reading pressure */
+	ezx_pcap_mask_event(PCAP_IRQ_TS);
+	pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
+	schedule_work(&pcap_ts->work);
+}
+
+static void pcap_ts_timer_fn(unsigned long data)
+{
+	schedule_work(&pcap_ts->work);
+}
+
+static int __devinit pcap_ts_probe(struct platform_device *pdev)
+{
+	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;
+
+	INIT_WORK(&pcap_ts->work, pcap_ts_work);
+
+	pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
+
+	init_timer(&pcap_ts->timer);
+	pcap_ts->timer.data = (unsigned long) pcap_ts;
+	pcap_ts->timer.function = &pcap_ts_timer_fn;
+
+	pcap_ts->input = input_dev;
+
+	input_dev->name = "pcap-touchscreen";
+	input_dev->phys = "pcap_ts/input0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0002;
+	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &pdev->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(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);
+
+	ezx_pcap_register_event(PCAP_IRQ_TS, pcap_ts_event_touch,
+							"Touch Screen");
+
+	err = input_register_device(pcap_ts->input);
+	if (err)
+		goto fail_touch;
+
+	schedule_work(&pcap_ts->work);
+
+	return 0;
+
+fail_touch:
+	ezx_pcap_unregister_event(PCAP_IRQ_TS);
+fail:
+	input_free_device(input_dev);
+	kfree(pcap_ts);
+
+	return err;
+}
+
+static int __devexit pcap_ts_remove(struct platform_device *pdev)
+{
+	ezx_pcap_unregister_event(PCAP_IRQ_TS);
+
+	del_timer_sync(&pcap_ts->timer);
+
+	input_unregister_device(pcap_ts->input);
+	kfree(pcap_ts);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int pcap_ts_suspend(struct platform_device *dev, pm_message_t state)
+{
+	u32 tmp;
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp |= PCAP_ADC_TS_REF_LOWPWR;
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+	return 0;
+}
+
+static int pcap_ts_resume(struct platform_device *dev)
+{
+	u32 tmp;
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp &= ~PCAP_ADC_TS_REF_LOWPWR;
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+	return 0;
+}
+#else
+
+#define pcap_ts_suspend NULL
+#define pcap_ts_resume  NULL
+
+#endif
+
+static struct platform_driver pcap_ts_driver = {
+	.probe		= pcap_ts_probe,
+	.remove		= __devexit_p(pcap_ts_remove),
+	.suspend	= pcap_ts_suspend,
+	.resume		= pcap_ts_resume,
+	.driver		= {
+		.name	= "pcap-ts",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init pcap_ts_init(void)
+{
+	return platform_driver_register(&pcap_ts_driver);
+}
+
+static void __exit pcap_ts_exit(void)
+{
+	platform_driver_unregister(&pcap_ts_driver);
+}
+
+module_init(pcap_ts_init);
+module_exit(pcap_ts_exit);
+
+MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver");
+MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
+MODULE_LICENSE("GPL");
-- 
tg: (fc25aca..) ezx/pcap_ts (depends on: ezx/local/pcap)

-- 

-------------------------------------------------------------------
List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [patch 08/14] input: PCAP2 based touchscreen driver
  2008-11-21 16:04 ` [patch 08/14] input: PCAP2 based touchscreen driver stefan
@ 2008-11-21 17:05   ` Dmitry Torokhov
  2008-11-22  0:00     ` Stefan Schmidt
  0 siblings, 1 reply; 5+ messages in thread
From: Dmitry Torokhov @ 2008-11-21 17:05 UTC (permalink / raw)
  To: stefan
  Cc: eric.y.miao, linux-arm-kernel, linux-input, linux-kernel,
	Daniel Ribeiro

On Fri, Nov 21, 2008 at 05:04:11PM +0100, stefan@datenfreihafen.org wrote:
> Touchscreen driver based on the PCAP2 multi function device.
> 
> Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com>
> 
> +
> +static int __devexit pcap_ts_remove(struct platform_device *pdev)
> +{
> +	ezx_pcap_unregister_event(PCAP_IRQ_TS);
> +
> +	del_timer_sync(&pcap_ts->timer);
> +
> +	input_unregister_device(pcap_ts->input);
> +	kfree(pcap_ts);
> +

Could pcap_ts->work be still running at this point?

> +	return 0;
> +}
> +
> +}
> +#else
> +
> +#define pcap_ts_suspend NULL
> +#define pcap_ts_resume  NULL
> +
> +#endif
> +
> +static struct platform_driver pcap_ts_driver = {
> +	.probe		= pcap_ts_probe,
> +	.remove		= __devexit_p(pcap_ts_remove),
> +	.suspend	= pcap_ts_suspend,
> +	.resume		= pcap_ts_resume,

I think it is preferred that .suspend and .resume assigments are
guarded by #ifdef CONFIG_PM, not creating NULL stubs as this will
(theoretically) allow removing .suspend and .resume pointers from
driver stucture when compiling without PM support.

Also try running through checkpatch.pl - there are a few warnings I'd
like to be fixed as well. Otherwise looks pretty good.

Oh, and you need to add your sign-off please. Thanks!

-- 
Dmitry

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch 08/14] input: PCAP2 based touchscreen driver
  2008-11-21 17:05   ` Dmitry Torokhov
@ 2008-11-22  0:00     ` Stefan Schmidt
  2009-04-21  2:18       ` Dmitry Torokhov
  0 siblings, 1 reply; 5+ messages in thread
From: Stefan Schmidt @ 2008-11-22  0:00 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: stefan, eric.y.miao, linux-arm-kernel, linux-input, linux-kernel,
	Daniel Ribeiro, ao2

Hello.

Thanks for the fast review. I hope we could address all your points with a new
patch below.

On Fri, 2008-11-21 at 12:05, Dmitry Torokhov wrote:
> On Fri, Nov 21, 2008 at 05:04:11PM +0100, stefan@datenfreihafen.org wrote:
> > Touchscreen driver based on the PCAP2 multi function device.
> > 
> > Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com>
> > 
> > +
> > +static int __devexit pcap_ts_remove(struct platform_device *pdev)
> > +{
> > +	ezx_pcap_unregister_event(PCAP_IRQ_TS);
> > +
> > +	del_timer_sync(&pcap_ts->timer);
> > +
> > +	input_unregister_device(pcap_ts->input);
> > +	kfree(pcap_ts);
> > +
> 
> Could pcap_ts->work be still running at this point?

Good point. Adding a cancel_work_sync()
 
> > +static struct platform_driver pcap_ts_driver = {
> > +	.probe		= pcap_ts_probe,
> > +	.remove		= __devexit_p(pcap_ts_remove),
> > +	.suspend	= pcap_ts_suspend,
> > +	.resume		= pcap_ts_resume,
> 
> I think it is preferred that .suspend and .resume assigments are
> guarded by #ifdef CONFIG_PM, not creating NULL stubs as this will
> (theoretically) allow removing .suspend and .resume pointers from
> driver stucture when compiling without PM support.

Change to #ifdef

> Also try running through checkpatch.pl - there are a few warnings I'd
> like to be fixed as well.

Can you elaborate on this? I tested with checkpatch.pl here, but did not get
anny warning.

> Otherwise looks pretty good.

Thanks. Let's hope the PCAP2 driver goes in this time so we can merge this one
as well.

> Oh, and you need to add your sign-off please. Thanks!

Added.


From: Daniel Ribeiro <drwyrm@gmail.com>
Subject: input: PCAP2 based touchscreen driver
To: dmitry.torokhov@gmail.com
Cc: eric.y.miao@gmail.com, linux-arm-kernel@lists.arm.linux.org.uk, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org

Touchscreen driver based on the PCAP2 multi function device.

Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com>
Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>

---
 drivers/input/touchscreen/Kconfig   |    9 ++
 drivers/input/touchscreen/Makefile  |    1 +
 drivers/input/touchscreen/pcap_ts.c |  256 +++++++++++++++++++++++++++++++++++
 3 files changed, 266 insertions(+), 0 deletions(-)

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3d1ab8f..a1bd364 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -376,4 +376,13 @@ config TOUCHSCREEN_TOUCHIT213
 	  To compile this driver as a module, choose M here: the
 	  module will be called touchit213.
 
+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
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 15cf290..97d8931 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -31,3 +31,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)	+= wm9705.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)	+= wm9712.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713)	+= wm9713.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
new file mode 100644
index 0000000..a7ff2e2
--- /dev/null
+++ b/drivers/input/touchscreen/pcap_ts.c
@@ -0,0 +1,256 @@
+/*
+ * 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-2008 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.
+ *
+ */
+
+#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 <linux/mfd/ezx-pcap.h>
+
+struct pcap_ts {
+	struct input_dev *input;
+	struct timer_list timer;
+	struct work_struct work;
+	u16 x, y;
+	u16 pressure;
+	u8 read_state;
+};
+
+struct pcap_ts *pcap_ts;
+
+#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_read_xy(void)
+{
+	u32 res[2];
+
+	ezx_pcap_get_adc_channel_result(PCAP_ADC_CH_TS_X1, PCAP_ADC_CH_TS_Y1,
+									res);
+	ezx_pcap_disable_adc();
+
+	switch (pcap_ts->read_state) {
+	case PCAP_ADC_TS_M_PRESSURE:
+		/* save pressure, start xy read */
+		pcap_ts->pressure = res[0];
+		pcap_ts->read_state = PCAP_ADC_TS_M_XY;
+		schedule_work(&pcap_ts->work);
+		break;
+	case PCAP_ADC_TS_M_XY:
+		pcap_ts->y = res[0];
+		pcap_ts->x = res[1];
+		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 ||
+		    pcap_ts->pressure <= PRESSURE_MIN ||
+		    pcap_ts->pressure >= PRESSURE_MAX) {
+			/* pen has been released */
+			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->read_state = PCAP_ADC_TS_M_STANDBY;
+			ezx_pcap_unmask_event(PCAP_IRQ_TS);
+			schedule_work(&pcap_ts->work);
+		} else {
+			/* pen is touching the screen*/
+			input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
+			input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
+			input_report_key(pcap_ts->input, BTN_TOUCH, 1);
+			input_report_abs(pcap_ts->input, ABS_PRESSURE,
+						pcap_ts->pressure);
+
+			/* switch back to pressure read mode */
+			pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
+			mod_timer(&pcap_ts->timer,
+					jiffies + SAMPLE_INTERVAL);
+		}
+		input_sync(pcap_ts->input);
+		break;
+	default:
+		break;
+	}
+}
+
+static void pcap_ts_work(struct work_struct *unused)
+{
+	u32 tmp;
+
+	switch (pcap_ts->read_state) {
+	case PCAP_ADC_TS_M_STANDBY:
+		/* set TS to standby */
+		ezx_pcap_read(PCAP_REG_ADC, &tmp);
+		tmp &= ~PCAP_ADC_TS_M_MASK;
+		tmp |= (PCAP_ADC_TS_M_STANDBY << PCAP_ADC_TS_M_SHIFT);
+		ezx_pcap_write(PCAP_REG_ADC, tmp);
+		break;
+	case PCAP_ADC_TS_M_PRESSURE:
+	case PCAP_ADC_TS_M_XY:
+		/* start adc conversion */
+		ezx_pcap_start_adc(PCAP_ADC_BANK_1, PCAP_ADC_T_NOW,
+			(pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT),
+						pcap_ts_read_xy, NULL);
+		break;
+	}
+}
+
+static void pcap_ts_event_touch(u32 events, void *unused)
+{
+	/* pen touch down, mask touch event and start reading pressure */
+	ezx_pcap_mask_event(PCAP_IRQ_TS);
+	pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
+	schedule_work(&pcap_ts->work);
+}
+
+static void pcap_ts_timer_fn(unsigned long data)
+{
+	schedule_work(&pcap_ts->work);
+}
+
+static int __devinit pcap_ts_probe(struct platform_device *pdev)
+{
+	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;
+
+	INIT_WORK(&pcap_ts->work, pcap_ts_work);
+
+	pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
+
+	init_timer(&pcap_ts->timer);
+	pcap_ts->timer.data = (unsigned long) pcap_ts;
+	pcap_ts->timer.function = &pcap_ts_timer_fn;
+
+	pcap_ts->input = input_dev;
+
+	input_dev->name = "pcap-touchscreen";
+	input_dev->phys = "pcap_ts/input0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0002;
+	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &pdev->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(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);
+
+	ezx_pcap_register_event(PCAP_IRQ_TS, pcap_ts_event_touch,
+							NULL, "Touch Screen");
+
+	err = input_register_device(pcap_ts->input);
+	if (err)
+		goto fail_touch;
+
+	schedule_work(&pcap_ts->work);
+
+	return 0;
+
+fail_touch:
+	ezx_pcap_unregister_event(PCAP_IRQ_TS);
+fail:
+	input_free_device(input_dev);
+	kfree(pcap_ts);
+
+	return err;
+}
+
+static int __devexit pcap_ts_remove(struct platform_device *pdev)
+{
+	ezx_pcap_unregister_event(PCAP_IRQ_TS);
+
+	del_timer_sync(&pcap_ts->timer);
+
+	input_unregister_device(pcap_ts->input);
+	cancel_work_sync(&pcap_ts->work);
+	kfree(pcap_ts);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int pcap_ts_suspend(struct platform_device *dev, pm_message_t state)
+{
+	u32 tmp;
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp |= PCAP_ADC_TS_REF_LOWPWR;
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+	return 0;
+}
+
+static int pcap_ts_resume(struct platform_device *dev)
+{
+	u32 tmp;
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp &= ~PCAP_ADC_TS_REF_LOWPWR;
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+	return 0;
+}
+#endif
+
+static struct platform_driver pcap_ts_driver = {
+	.probe		= pcap_ts_probe,
+	.remove		= __devexit_p(pcap_ts_remove),
+#ifdef CONFIG_PM
+	.suspend	= pcap_ts_suspend,
+	.resume		= pcap_ts_resume,
+#endif
+	.driver		= {
+		.name	= "pcap-ts",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init pcap_ts_init(void)
+{
+	return platform_driver_register(&pcap_ts_driver);
+}
+
+static void __exit pcap_ts_exit(void)
+{
+	platform_driver_unregister(&pcap_ts_driver);
+}
+
+module_init(pcap_ts_init);
+module_exit(pcap_ts_exit);
+
+MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver");
+MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
+MODULE_LICENSE("GPL");
-- 
tg: (8e9f66c..) ezx/pcap_ts (depends on: ezx/local/pcap)

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [patch 08/14] input: PCAP2 based touchscreen driver
  2008-11-22  0:00     ` Stefan Schmidt
@ 2009-04-21  2:18       ` Dmitry Torokhov
  2009-04-21  2:38         ` Daniel Ribeiro
  0 siblings, 1 reply; 5+ messages in thread
From: Dmitry Torokhov @ 2009-04-21  2:18 UTC (permalink / raw)
  To: Stefan Schmidt
  Cc: eric.y.miao, linux-arm-kernel, linux-input, linux-kernel,
	Daniel Ribeiro, ao2

Hi Stephen,

On Friday 21 November 2008 16:00:47 Stefan Schmidt wrote:
> Hello.
>
> Thanks for the fast review. I hope we could address all your points with a
> new patch below.

What is the status of PCAP support? Is it going to be merged in
mainline? I am holding the touchscreen driver in my queue because
it requires linux/mfd/ezx-pcap.h which is not in mainline yet...

Should I drop the driver? Is it going to be merged through some
other tree?

Thanks!

-- 
Dmitry

P.S. Just in case here is what I have in my tree at the moment:

Input: add PCAP2 based touchscreen driver

From: Daniel Ribeiro <drwyrm@gmail.com>

This is touchscreen driver based on the PCAP2 multi function device.

Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com>
Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/input/touchscreen/Kconfig   |    9 +
 drivers/input/touchscreen/Makefile  |    1 
 drivers/input/touchscreen/pcap_ts.c |  264 +++++++++++++++++++++++++++++++++++
 3 files changed, 274 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/touchscreen/pcap_ts.c


diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 82c388e..761e256 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -481,4 +481,13 @@ config TOUCHSCREEN_TSC2007
 	  To compile this driver as a module, choose M here: the
 	  module will be called tsc2007.
 
+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
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index bef7415..20b009f 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
 obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
+obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
new file mode 100644
index 0000000..122cd09
--- /dev/null
+++ b/drivers/input/touchscreen/pcap_ts.c
@@ -0,0 +1,264 @@
+/*
+ * 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-2008 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.
+ *
+ */
+
+#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 <linux/mfd/ezx-pcap.h>
+
+struct pcap_ts {
+	struct input_dev *input;
+	struct timer_list timer;
+	struct work_struct work;
+	u16 x, y;
+	u16 pressure;
+	u8 read_state;
+};
+
+struct pcap_ts *pcap_ts;
+
+#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_read_xy(void)
+{
+	u32 res[2];
+
+	ezx_pcap_get_adc_channel_result(PCAP_ADC_CH_TS_X1,
+					PCAP_ADC_CH_TS_Y1,
+					res);
+	ezx_pcap_disable_adc();
+
+	switch (pcap_ts->read_state) {
+	case PCAP_ADC_TS_M_PRESSURE:
+		/* save pressure, start xy read */
+		pcap_ts->pressure = res[0];
+		pcap_ts->read_state = PCAP_ADC_TS_M_XY;
+		schedule_work(&pcap_ts->work);
+		break;
+
+	case PCAP_ADC_TS_M_XY:
+		pcap_ts->y = res[0];
+		pcap_ts->x = res[1];
+		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 ||
+		    pcap_ts->pressure <= PRESSURE_MIN ||
+		    pcap_ts->pressure >= PRESSURE_MAX) {
+			/* pen has been released */
+			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->read_state = PCAP_ADC_TS_M_STANDBY;
+			ezx_pcap_unmask_event(PCAP_IRQ_TS);
+			schedule_work(&pcap_ts->work);
+		} else {
+			/* pen is touching the screen*/
+			input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
+			input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
+			input_report_key(pcap_ts->input, BTN_TOUCH, 1);
+			input_report_abs(pcap_ts->input, ABS_PRESSURE,
+						pcap_ts->pressure);
+
+			/* switch back to pressure read mode */
+			pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
+			mod_timer(&pcap_ts->timer,
+					jiffies + SAMPLE_INTERVAL);
+		}
+		input_sync(pcap_ts->input);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void pcap_ts_work(struct work_struct *unused)
+{
+	u32 tmp;
+
+	switch (pcap_ts->read_state) {
+	case PCAP_ADC_TS_M_STANDBY:
+		/* set TS to standby */
+		ezx_pcap_read(PCAP_REG_ADC, &tmp);
+		tmp &= ~PCAP_ADC_TS_M_MASK;
+		tmp |= (PCAP_ADC_TS_M_STANDBY << PCAP_ADC_TS_M_SHIFT);
+		ezx_pcap_write(PCAP_REG_ADC, tmp);
+		break;
+
+	case PCAP_ADC_TS_M_PRESSURE:
+	case PCAP_ADC_TS_M_XY:
+		/* start adc conversion */
+		ezx_pcap_start_adc(PCAP_ADC_BANK_1, PCAP_ADC_T_NOW,
+			(pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT),
+						pcap_ts_read_xy, NULL);
+		break;
+	}
+}
+
+static void pcap_ts_event_touch(u32 events, void *unused)
+{
+	/* pen touch down, mask touch event and start reading pressure */
+	ezx_pcap_mask_event(PCAP_IRQ_TS);
+	pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
+	schedule_work(&pcap_ts->work);
+}
+
+static void pcap_ts_timer_fn(unsigned long data)
+{
+	schedule_work(&pcap_ts->work);
+}
+
+static int __devinit pcap_ts_probe(struct platform_device *pdev)
+{
+	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;
+
+	INIT_WORK(&pcap_ts->work, pcap_ts_work);
+
+	pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
+
+	init_timer(&pcap_ts->timer);
+	pcap_ts->timer.data = (unsigned long) pcap_ts;
+	pcap_ts->timer.function = &pcap_ts_timer_fn;
+
+	pcap_ts->input = input_dev;
+
+	input_dev->name = "pcap-touchscreen";
+	input_dev->phys = "pcap_ts/input0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0002;
+	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &pdev->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(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);
+
+	ezx_pcap_register_event(PCAP_IRQ_TS, pcap_ts_event_touch,
+				NULL, "Touch Screen");
+
+	err = input_register_device(pcap_ts->input);
+	if (err)
+		goto fail_touch;
+
+	schedule_work(&pcap_ts->work);
+
+	return 0;
+
+fail_touch:
+	ezx_pcap_unregister_event(PCAP_IRQ_TS);
+fail:
+	input_free_device(input_dev);
+	kfree(pcap_ts);
+
+	return err;
+}
+
+static int __devexit pcap_ts_remove(struct platform_device *pdev)
+{
+	ezx_pcap_unregister_event(PCAP_IRQ_TS);
+
+	del_timer_sync(&pcap_ts->timer);
+	cancel_work_sync(&pcap_ts->work);
+
+	input_unregister_device(pcap_ts->input);
+	kfree(pcap_ts);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int pcap_ts_suspend(struct platform_device *dev, pm_message_t state)
+{
+	u32 tmp;
+
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp |= PCAP_ADC_TS_REF_LOWPWR;
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+
+	return 0;
+}
+
+static int pcap_ts_resume(struct platform_device *dev)
+{
+	u32 tmp;
+
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp &= ~PCAP_ADC_TS_REF_LOWPWR;
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+
+	return 0;
+}
+#endif
+
+static struct platform_driver pcap_ts_driver = {
+	.probe		= pcap_ts_probe,
+	.remove		= __devexit_p(pcap_ts_remove),
+#ifdef CONFIG_PM
+	.suspend	= pcap_ts_suspend,
+	.resume		= pcap_ts_resume,
+#endif
+	.driver		= {
+		.name	= "pcap-ts",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init pcap_ts_init(void)
+{
+	return platform_driver_register(&pcap_ts_driver);
+}
+
+static void __exit pcap_ts_exit(void)
+{
+	platform_driver_unregister(&pcap_ts_driver);
+}
+
+module_init(pcap_ts_init);
+module_exit(pcap_ts_exit);
+
+MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver");
+MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
+MODULE_LICENSE("GPL");

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [patch 08/14] input: PCAP2 based touchscreen driver
  2009-04-21  2:18       ` Dmitry Torokhov
@ 2009-04-21  2:38         ` Daniel Ribeiro
  0 siblings, 0 replies; 5+ messages in thread
From: Daniel Ribeiro @ 2009-04-21  2:38 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Stefan Schmidt, eric.y.miao, linux-arm-kernel, linux-input,
	linux-kernel, ao2

Em Seg, 2009-04-20 às 19:18 -0700, Dmitry Torokhov escreveu:
> What is the status of PCAP support? Is it going to be merged in
> mainline? I am holding the touchscreen driver in my queue because
> it requires linux/mfd/ezx-pcap.h which is not in mainline yet...
> 
> Should I drop the driver? Is it going to be merged through some
> other tree?

Hi Dmitry,

Please drop it. There is still a lot of work needed to get our core PCAP
driver in shape for mainline.

Thanks!

-- 
Daniel Ribeiro

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-04-21  2:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20081121160403.073751031@dodger.lab.datenfreihafen.org>
2008-11-21 16:04 ` [patch 08/14] input: PCAP2 based touchscreen driver stefan
2008-11-21 17:05   ` Dmitry Torokhov
2008-11-22  0:00     ` Stefan Schmidt
2009-04-21  2:18       ` Dmitry Torokhov
2009-04-21  2:38         ` Daniel Ribeiro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).