Re: [PATCH] PCAP touchscreen driver (for 2.6.32)
Hi Daniel, On Sat, Jun 27, 2009 at 02:02:18PM -0300, Daniel Ribeiro wrote: Touchscreen driver for PCAP2 PMIC. Signed-off-by: Daniel Ribeiro drw...@gmail.com --- drivers/input/touchscreen/Kconfig |9 ++ drivers/input/touchscreen/Makefile |1 + drivers/input/touchscreen/pcap_ts.c | 235 +++ 3 files changed, 245 insertions(+), 0 deletions(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 72e2712..8e6fa8b 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -498,4 +498,13 @@ config TOUCHSCREEN_W90X900 To compile this driver as a module, choose M here: the module will be called w90p910_ts. +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 3e1c5e0..4599bf7 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -40,3 +40,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)+= zylonite-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_W90X900)+= w90p910_ts.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 000..7877fdf --- /dev/null +++ b/drivers/input/touchscreen/pcap_ts.c @@ -0,0 +1,235 @@ +/* + * Driver for Motorola PCAP2 touchscreen as found in the EZX phone platform. + * + * Copyright (C) 2006 Harald Welte lafo...@openezx.org + * Copyright (C) 2009 Daniel Ribeiro drw...@gmail.com + * + * 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 pcap_chip *pcap; + struct input_dev *input; + struct delayed_work work; + u16 x, y; + u16 pressure; + u8 read_state; +}; + +#define SAMPLE_DELAY 20 /* msecs */ + +#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 + +static void pcap_ts_read_xy(void *data, u16 res[2]) +{ + struct pcap_ts *pcap_ts = data; + + switch (pcap_ts-read_state) { + case PCAP_ADC_TS_M_PRESSURE: + /* pressure reading is unreliable */ + if (res[0] PRESSURE_MIN res[0] PRESSURE_MAX) + pcap_ts-pressure = res[0]; + pcap_ts-read_state = PCAP_ADC_TS_M_XY; + schedule_delayed_work(pcap_ts-work, 0); + 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) { + /* pen has been released */ + input_report_abs(pcap_ts-input, ABS_PRESSURE, 0); + input_report_key(pcap_ts-input, BTN_TOUCH, 0); + + pcap_ts-read_state = PCAP_ADC_TS_M_STANDBY; + schedule_delayed_work(pcap_ts-work, 0); It looks like the only thing the work will do is: + pcap_set_ts_bits(pcap_ts-pcap, + pcap_ts-read_state PCAP_ADC_TS_M_SHIFT); So why not do that directly here instead of scheduling work again? + } 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; + schedule_delayed_work(pcap_ts-work, + msecs_to_jiffies(SAMPLE_DELAY)); + } + input_sync(pcap_ts-input); + break; + default: Maybe add some angry words here? + break; + }
Re: [PATCH] PCAP touchscreen driver (for 2.6.32)
Hi Daniel, 2009/6/27 Daniel Ribeiro drw...@gmail.com: Touchscreen driver for PCAP2 PMIC. Some more description in commit text really helps. +static irqreturn_t pcap_ts_event_touch(int pirq, void *data) +{ + struct pcap_ts *pcap_ts = data; + + if (pcap_ts-read_state == PCAP_ADC_TS_M_STANDBY) { + pcap_ts-read_state = PCAP_ADC_TS_M_PRESSURE; + schedule_delayed_work(pcap_ts-work, 0); + } + return IRQ_HANDLED; +} + +static int __devinit pcap_ts_probe(struct platform_device *pdev) +{ + struct input_dev *input_dev; + struct pcap_ts *pcap_ts; + int err = -ENOMEM; + + pcap_ts = kzalloc(sizeof(*pcap_ts), GFP_KERNEL); + if (!pcap_ts) + return err; + + pcap_ts-pcap = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, pcap_ts); + + input_dev = input_allocate_device(); + if (!pcap_ts || !input_dev) + goto fail; + + INIT_DELAYED_WORK(pcap_ts-work, pcap_ts_work); + + pcap_ts-read_state = PCAP_ADC_TS_M_STANDBY; + + 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); + + err = request_irq(pcap_to_irq(pcap_ts-pcap, PCAP_IRQ_TS), + pcap_ts_event_touch, 0, Touch Screen, pcap_ts); + if (err) + goto fail; + + err = input_register_device(pcap_ts-input); + if (err) + goto fail_touch; Please move request_irq after input_register_device, as IRQ can get fired before input device gets available, right? Overall driver is nice and clean. -- ---Trilok Soni http://triloksoni.wordpress.com http://www.linkedin.com/in/triloksoni
Re: [PATCH] PCAP touchscreen driver (for 2.6.32)
Daniel, some trivial comments, I can do the changes if you want. On Sat, 27 Jun 2009 14:02:18 -0300 Daniel Ribeiro drw...@gmail.com wrote: Touchscreen driver for PCAP2 PMIC. Signed-off-by: Daniel Ribeiro drw...@gmail.com --- drivers/input/touchscreen/Kconfig |9 ++ drivers/input/touchscreen/Makefile |1 + drivers/input/touchscreen/pcap_ts.c | 235 +++ 3 files changed, 245 insertions(+), 0 deletions(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 72e2712..8e6fa8b 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -498,4 +498,13 @@ config TOUCHSCREEN_W90X900 To compile this driver as a module, choose M here: the module will be called w90p910_ts. +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 3e1c5e0..4599bf7 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -40,3 +40,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)+= zylonite-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_W90X900)+= w90p910_ts.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 000..7877fdf --- /dev/null +++ b/drivers/input/touchscreen/pcap_ts.c @@ -0,0 +1,235 @@ +/* + * Driver for Motorola PCAP2 touchscreen as found in the EZX phone platform. + * + * Copyright (C) 2006 Harald Welte lafo...@openezx.org + * Copyright (C) 2009 Daniel Ribeiro drw...@gmail.com + * + * 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 pcap_chip *pcap; + struct input_dev *input; + struct delayed_work work; + u16 x, y; + u16 pressure; + u8 read_state; +}; + +#define SAMPLE_DELAY 20 /* msecs */ + +#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 + +static void pcap_ts_read_xy(void *data, u16 res[2]) +{ + struct pcap_ts *pcap_ts = data; + + switch (pcap_ts-read_state) { + case PCAP_ADC_TS_M_PRESSURE: + /* pressure reading is unreliable */ + if (res[0] PRESSURE_MIN res[0] PRESSURE_MAX) + pcap_ts-pressure = res[0]; + pcap_ts-read_state = PCAP_ADC_TS_M_XY; + schedule_delayed_work(pcap_ts-work, 0); + 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) { + /* pen has been released */ + input_report_abs(pcap_ts-input, ABS_PRESSURE, 0); + input_report_key(pcap_ts-input, BTN_TOUCH, 0); + + pcap_ts-read_state = PCAP_ADC_TS_M_STANDBY; + schedule_delayed_work(pcap_ts-work, 0); + } 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; + schedule_delayed_work(pcap_ts-work, + msecs_to_jiffies(SAMPLE_DELAY)); + } + input_sync(pcap_ts-input); + break; + default: + break; + } +} + +static void pcap_ts_work(struct work_struct *work) +{ + struct delayed_work *dw = container_of(work, struct delayed_work, work); + struct pcap_ts *pcap_ts = container_of(dw,
Re: [PATCH] PCAP touchscreen driver (for 2.6.32)
Em Dom, 2009-06-28 às 16:35 +0200, Antonio Ospite escreveu: + pcap_ts-pcap = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, pcap_ts); + + input_dev = input_allocate_device(); + if (!pcap_ts || !input_dev) Can pcap_ts be ever NULL here? This test can be simplified. Right, it really can't be NULL. I will fix it. +#ifdef CONFIG_PM +static int pcap_ts_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct pcap_ts *pcap_ts = platform_get_drvdata(pdev); + + pcap_set_ts_bits(pcap_ts-pcap, PCAP_ADC_TS_REF_LOWPWR); + return 0; +} + +static int pcap_ts_resume(struct platform_device *pdev) +{ + struct pcap_ts *pcap_ts = platform_get_drvdata(pdev); + + pcap_set_ts_bits(pcap_ts-pcap, + pcap_ts-read_state PCAP_ADC_TS_M_SHIFT); + return 0; +} +#endif + define the suspend/resume callbacks as NULL in a #else here and remove the #ifdef CONFIG_PM below? That seems to be the most used style. +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, + }, +}; Ok. Thanks for the review! :) -- Daniel Ribeiro signature.asc Description: Esta é uma parte de mensagem assinada digitalmente