Touch: DA9052 touchscreen driver
Subsystems (2)
PATCH 8/11 Touch: DA9052 touchscreen driver
This driver add support for DA9052 4-wire resistive ADC interfaced touchscreen controller.
DA9052 is a MFD therefore this driver depends on DA9052 core driver for core functionalities.
--- drivers/input/touchscreen/Kconfig | 7 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/da9052_tsi.c | 489 ++++++++++++++++++++++++++++++++ 3 files changed, 497 insertions(+), 0 deletions(-) create mode 100755 drivers/input/touchscreen/da9052_tsi.c
drivers/input/touchscreen/Kconfig +7 -0
@@ -144,6 +144,13 @@ config TOUCHSCREEN_DA9034 Say Y here to enable the support for the touchscreen found on Dialog Semiconductor DA9034 PMIC. +config TOUCHSCREEN_DA9052 + tristate "Dialog DA9052 TSI" + depends on PMIC_DA9052 + help + Say y here to support the touchscreen found on + Dialog Semiconductor DA9052 PMIC + config TOUCHSCREEN_DYNAPRO tristate "Dynapro serial touchscreen" select SERIO
drivers/input/touchscreen/Makefile +1 -0
@@ -18,6 +18,7 @@ obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o +obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
drivers/input/touchscreen/da9052_tsi.c new file +489 -0
489 lines not on this page · raw message
Quoted 9 lines · On Thu, 2011-07-14 at 14:28 +0530, ashishj3 wrote:
This driver add support for DA9052 4-wire resistive ADC interfaced touchscreen controller.
DA9052 is a MFD therefore this driver depends on DA9052 core driver for core functionalities.
Signed-off-by David Dajun Chen <[email protected]>Signed-off-by Ashish Jangam <[email protected]>---
If there are no comments then can this patch get ACK?
Quoted 9 lines · On Thu, 2011-07-14 at 14:28 +0530, ashishj3 wrote:
This driver add support for DA9052 4-wire resistive ADC interfaced touchscreen controller.
DA9052 is a MFD therefore this driver depends on DA9052 core driver for core functionalities.
Signed-off-by David Dajun Chen <[email protected]>Signed-off-by Ashish Jangam <[email protected]>---
If there are no comments then can this patch get ACK?
Dmitry Torokhov
maintainerHi Ashish,
Quoted 19 lines · On Thu, Jul 14, 2011 at 02:28:10PM +0530, ashishj3 wrote:
This driver add support for DA9052 4-wire resistive ADC interfaced touchscreen controller.
DA9052 is a MFD therefore this driver depends on DA9052 core driver for core functionalities.
Signed-off-by David Dajun Chen <[email protected]>Signed-off-by Ashish Jangam <[email protected]>--- drivers/input/touchscreen/Kconfig | 7 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/da9052_tsi.c | 489 ++++++++++++++++++++++++++++++++ 3 files changed, 497 insertions(+), 0 deletions(-) create mode 100755 drivers/input/touchscreen/da9052_tsi.cdrivers/input/touchscreen/Kconfig +0
-0
drivers/input/touchscreen/Kconfig config TOUCHSCREEN_DA9034 · line 153
Quoted 10 lines
drivers/input/touchscreen/Kconfig +7
-0@@ -144,6 +144,13 @@ config TOUCHSCREEN_DA9034 Say Y here to enable the support for the touchscreen found on Dialog Semiconductor DA9034 PMIC. +config TOUCHSCREEN_DA9052 + tristate "Dialog DA9052 TSI" + depends on PMIC_DA9052 + help + Say y here to support the touchscreen found on + Dialog Semiconductor DA9052 PMIC +
To compile this driver as a module...
Quoted 57 lines
drivers/input/touchscreen/Kconfig +0
-0config TOUCHSCREEN_DYNAPRO tristate "Dynapro serial touchscreen" select SERIOdrivers/input/touchscreen/Makefile +1
-0@@ -18,6 +18,7 @@ obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o +obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.odrivers/input/touchscreen/da9052_tsi.c new file +36
-0@@ -0,0 +1,489 @@ +/* +* TSI driver for Dialog DA9052 +* +* Copyright(c) 2011 Dialog Semiconductor Ltd. +* +* Author: David Dajun Chen <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +*/ +#include <linux/module.h> +#include <linux/input.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/freezer.h> +#include <linux/kthread.h> +#include <linux/kfifo.h> + +#include <linux/mfd/da9052/reg.h> +#include <linux/mfd/da9052/da9052.h> + +#define DA9052_ACTIVE 1 +#define DA9052_INACTIVE 0 + +#define DA9052_TSI_FIFOSIZE 640 + +enum { +DA9052_PEN_IDLE , +DA9052_PEN_DOWN , +DA9052_PEN_UP +}; + +struct da9052_tsi_reg {
drivers/input/touchscreen/da9052_tsi.c line 46
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+u16 x; +u16 y; +}; + +struct tsi_thread_type { +u8 pid; +u8 state; +struct completion notifier; +struct task_struct *thread_task; +};
What is the reason for rolling out your own kernel thread implementation? From what I understand you just need periodically to check for "pen up" and that's it, so simply use standard workqueue to schedule checks.
Quoted 7 lines
drivers/input/touchscreen/da9052_tsi.c new file +7
-0+ +struct da9052_tsi { +struct da9052 *da9052; +struct input_dev *dev; +struct tsi_thread_type tsi_pen_state_thread; +struct tsi_thread_type tsi_filter_thread; +struct kfifo fifo;
drivers/input/touchscreen/da9052_tsi.c line 63
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+struct kfifo fifo_buf; +u8 pen_up_detect_interval; +u32 zero_data_cnt; +u32 valid_penup_count; +u8 pen_state; +int irq_pendwn; +int irq_datardy; +}; + +static inline int da9052_ts_start (struct da9052_tsi *tsi)
Drop inline, let compiler figure out if the function needs to be inlined.
Normally only fucntions in header files should be marked as static inline.
Quoted 48 lines
drivers/input/touchscreen/da9052_tsi.c new file +48
-0+{ +return da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG , +1 <<0 ,1 <<0 ); +} + +static inline int da9052_ts_stop (struct da9052_tsi *tsi) +{ +return da9052_clear_bits (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<0 ); +} + +static irqreturn_t da9052_ts_pendwn_irq (int irq,void *data) +{ +struct da9052_tsi *tsi = (struct da9052_tsi *)data; +struct da9052 *da9052 = tsi->da9052; +int ret; + + da9052->events_mask |=DA9052_E_PEN_DOWN ; + da9052->events_mask &= ~DA9052_E_TSI_READY ; + +/* Mask PEN_DOWN event and unmask TSI_READY event*/ + ret =da9052_reg_update (da9052,DA9052_IRQ_MASK_B_REG ,0x80 ,0x40 ); +if (ret <0 ) +return IRQ_NONE ; + +da9052_ts_start (tsi); + tsi->pen_state =DA9052_PEN_DOWN ; + +return IRQ_HANDLED ; +} + +static int da9052_ts_read (struct da9052_tsi *tsi) +{ +struct da9052_tsi_reg co_ord = {0 ,0 }; +int ret; +uint8_t _x, _y, _v; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_X_MSB_REG ); +if (ret <0 ) +return ret; + + _x = (uint8_t ) ret; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_Y_MSB_REG ); +if (ret <0 ) +return ret; + + _y = (uint8_t ) ret; +
drivers/input/touchscreen/da9052_tsi.c line 121
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+ ret =da9052_reg_read (tsi->da9052,DA9052_TSI_LSB_REG ); +if (ret <0 ) +return ret; + + _v = (uint8_t ) ret; + + co_ord.x = ((_x <<2 ) &0x3fc ) | (_v &0x3 ); + co_ord.y = ((_y <<2 ) &0x3fc ) | ((_v &0xc ) >>2 ); + + ret =kfifo_in (&tsi->fifo, &co_ord,sizeof (struct da9052_tsi_reg ));
You have data, you know the pen state, why mess with 2! kfifos? Just report the events right here.
Quoted 212 lines
drivers/input/touchscreen/da9052_tsi.c new file +212
-0+ +return 0 ; +} + +static irqreturn_t da9052_ts_datardy_irq (int irq,void *data) +{ +struct da9052_tsi *tsi = (struct da9052_tsi *)data; +int ret; + + ret =da9052_ts_read (tsi); +if (ret) { +dev_err (tsi->da9052->dev, +"Failed to read TSI co-ordinate, %d\n" , ret); +return IRQ_NONE ; + } + +return IRQ_HANDLED ; +} + +/* +* Two FIFO are been used. FIFO1 is used for detecting pen up and +* FIFO2 for reporting pen down co-ordinate. +*/ +void da9052_ts_process_reg_data (struct da9052_tsi *tsi) +{ +struct da9052_tsi_reg tmp_raw_data; +u32 reg_data_cnt; +int ret; + + reg_data_cnt =kfifo_len (&tsi->fifo); + +while (reg_data_cnt-- >0 ) { + ret =kfifo_out (&tsi->fifo, &tmp_raw_data, +sizeof (struct da9052_tsi_reg )); +if (ret <0 ) +continue ; +kfifo_in (&tsi->fifo_buf, &tmp_raw_data, +sizeof (struct da9052_tsi_reg )); + } +return ; +} + +static void da9052_ts_report_penup (struct da9052_tsi *tsi) +{ +struct input_dev *ip_dev = tsi->dev; +struct da9052 *da9052 = tsi->da9052; +ssize_t ret; + + ret =da9052_ts_stop (tsi); +if (ret <0 ) +return ; + + da9052->events_mask |=DA9052_E_TSI_READY ; + da9052->events_mask &= ~DA9052_E_PEN_DOWN ; + +/* Mask TSI_READY event and unmask PEN_DOWN event*/ + ret =da9052_reg_update (da9052,DA9052_IRQ_MASK_B_REG ,0x40 ,0x80 ); +if (ret <0 ) +return ; + +input_report_abs (ip_dev,BTN_TOUCH ,0 ); +input_sync (ip_dev); + + tsi->zero_data_cnt =0 ; +} + +/* +* This function detects the pen up state using the kfifo len. +* If kfifo len is zero for some interval then pen up is reported. +* Else pen co-ordinate are reported. +*/ +static int da9052_ts_monitor_pen_state (void *data) +{ +struct da9052_tsi *tsi = (struct da9052_tsi *) data; +u32 data_cnt; + +set_freezable (); + +while (tsi->tsi_pen_state_thread.state ==DA9052_ACTIVE ) { +try_to_freeze (); + +set_current_state (TASK_INTERRUPTIBLE ); +schedule_timeout (msecs_to_jiffies (10 )); + +if (tsi->pen_state !=DA9052_PEN_DOWN ) +continue ; + + data_cnt =kfifo_len (&tsi->fifo); +if (data_cnt <0 ) +continue ; + +da9052_ts_process_reg_data (tsi); + +if (data_cnt) + tsi->zero_data_cnt =0 ; +else { +if ((++(tsi->zero_data_cnt)) > + tsi->valid_penup_count) { + tsi->pen_state =DA9052_PEN_UP ; +da9052_ts_report_penup (tsi); + } + } + } + +complete_and_exit (&tsi->tsi_pen_state_thread.notifier,0 ); +return 0 ; +} + +static int da9052_ts_process_thread (void *ptr) +{ +struct da9052_tsi_reg co_ord; +int cnt =0 , ret; +struct da9052_tsi *tsi = (struct da9052_tsi *)ptr; + +set_freezable (); + +while (tsi->tsi_filter_thread.state ==DA9052_ACTIVE ) { + +try_to_freeze (); + +set_current_state (TASK_INTERRUPTIBLE ); +schedule_timeout (msecs_to_jiffies (10 )); + cnt =kfifo_len (&tsi->fifo_buf); +if (cnt <=0 ) +continue ; + + ret =kfifo_out (&tsi->fifo_buf, &co_ord, +sizeof (struct da9052_tsi_reg )); +if (ret <0 ) +continue ; + +input_report_abs (tsi->dev,BTN_TOUCH ,1 ); +input_report_abs (tsi->dev,ABS_X , co_ord.x); +input_report_abs (tsi->dev,ABS_Y , co_ord.y); +input_sync (tsi->dev); + } + + tsi->tsi_filter_thread.thread_task =NULL ; +complete_and_exit (&tsi->tsi_filter_thread.notifier,0 ); + +return 0 ; +} + +static int da9052_ts_configure_gpio (struct da9052 *da9052) +{ +int ret; + + ret =da9052_clear_bits (da9052,DA9052_GPIO_2_3_REG ,0x30 ); +if (ret <0 ) +return -EIO ; + + ret =da9052_clear_bits (da9052,DA9052_GPIO_4_5_REG ,0x33 ); +if (ret <0 ) +return -EIO ; + + ret =da9052_clear_bits (da9052,DA9052_GPIO_6_7_REG ,0x33 ); +if (ret <0 ) +return -EIO ; + +return ret; +} + +static int __init da9052_ts_enable_device (struct da9052_tsi *tsi) +{ +ssize_t ret; +struct da9052 *da9052 = tsi->da9052; + + ret =da9052_ts_configure_gpio (tsi->da9052); +if (ret <0 ) +return ret; + + ret =da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG ,0xFC ,0xC0 ); +if (ret <0 ) +return ret; + + tsi->valid_penup_count =5 ; + +init_completion (&tsi->tsi_pen_state_thread.notifier); + tsi->tsi_pen_state_thread.state =DA9052_ACTIVE ; + tsi->tsi_pen_state_thread.pid =kernel_thread (da9052_ts_monitor_pen_state, tsi, +CLONE_KERNEL |SIGCHLD ); + +init_completion (&tsi->tsi_filter_thread.notifier); + tsi->tsi_filter_thread.state =DA9052_ACTIVE ; + tsi->tsi_filter_thread.pid =kernel_thread (da9052_ts_process_thread, tsi, +CLONE_KERNEL |SIGCHLD ); + + tsi->zero_data_cnt =0 ; + +/* Measure TSI sample every 1ms */ + ret =da9052_reg_update (tsi->da9052,DA9052_ADC_CONT_REG , +1 <<6 ,1 <<6 ); +if (ret <0 ) +return ret; + +/* TSI_DELAY: 4 slots, TSI_SKIP: 0 slots, TSI_MODE: XYZP */ + ret =da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG , +1 <<1 ,1 <<1 ); +if (ret <0 ) +return ret; + + da9052->events_mask |=DA9052_E_TSI_READY ; + +/* Mask TSI_READY event*/ + ret =da9052_reg_update (da9052,DA9052_IRQ_MASK_B_REG ,0 ,0x80 ); +if (ret <0 ) +return ret; + +/*Supply TSIRef thru LD09 */ + ret =da9052_reg_write (tsi->da9052,DA9052_LDO9_REG ,0x59 ); + +return ret;
drivers/input/touchscreen/da9052_tsi.c line 343
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+} + +static s32 __devinit da9052_ts_probe (struct platform_device *pdev) +{ +struct da9052_tsi *tsi; +struct input_dev *input_dev; +struct da9052 *da9052; +int ret; + + da9052 =dev_get_drvdata (pdev->dev.parent);
Check for NULL?
Quoted 14 lines
drivers/input/touchscreen/da9052_tsi.c new file +14
-0+ + tsi =kzalloc (sizeof (struct da9052_tsi ),GFP_KERNEL ); +if (!tsi) +return -ENOMEM ; + + input_dev =input_allocate_device (); +if (!input_dev) { +dev_err (tsi->da9052->dev, +"failed to allocate input device\n" ); + ret = -ENOMEM ; + goto err_mem; + } + + ret =kfifo_alloc (&tsi->fifo,DA9052_TSI_FIFOSIZE ,GFP_KERNEL );
drivers/input/touchscreen/da9052_tsi.c line 367
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+if (ret <0 ) + goto err_input; + + ret =kfifo_alloc (&tsi->fifo_buf,DA9052_TSI_FIFOSIZE ,GFP_KERNEL ); +if (ret <0 ) + goto err_fifo; + + tsi->da9052 = da9052; + tsi->pen_up_detect_interval =5 ; +platform_set_drvdata (pdev, tsi);
Can probably be moved right before "return 0;" statement.
drivers/input/touchscreen/da9052_tsi.c line 372
Quoted 5 lines
drivers/input/touchscreen/da9052_tsi.c new file +5
-0+ + input_dev->id.version =0x0101 ; + input_dev->id.vendor =0x15B6 ; + input_dev->id.product =0x9052 ; + input_dev->id.bustype =BUS_RS232 ;
Is it really RS232? BUS_HOST or leave it 0.
Quoted 4 lines
drivers/input/touchscreen/da9052_tsi.c new file +4
-0+ input_dev->name ="Dialog DA9052 TouchScreen Driver" ; + input_dev->dev.parent = &pdev->dev; +__set_bit (EV_ABS , input_dev->evbit); +__set_bit (EV_KEY , input_dev->evbit);
drivers/input/touchscreen/da9052_tsi.c line 386
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+__set_bit (BTN_TOUCH , input_dev->keybit); +__set_bit (ABS_X , input_dev->absbit); +__set_bit (ABS_Y , input_dev->absbit); + +input_set_abs_params (input_dev,ABS_X ,0 ,1023 ,0 ,0 ); +input_set_abs_params (input_dev,ABS_Y ,0 ,1023 ,0 ,0 ); +input_set_abs_params (input_dev,ABS_PRESSURE ,0 ,1023 ,0 ,0 ); + + tsi->dev = input_dev; +input_set_drvdata (input_dev, tsi);
I do not think you are using input_get_drvdata() enywhere...
drivers/input/touchscreen/da9052_tsi.c line 391
Quoted 5 lines
drivers/input/touchscreen/da9052_tsi.c new file +5
-0+ ret =input_register_device (tsi->dev); +if (ret) + goto err_mem; + + tsi->irq_pendwn =platform_get_irq_byname (pdev,"PENDWN" );
What if call fails?
Quoted 20 lines
drivers/input/touchscreen/da9052_tsi.c new file +20
-0+ ret =request_threaded_irq (tsi->da9052->irq_base + tsi->irq_pendwn, +NULL , da9052_ts_pendwn_irq, +IRQF_TRIGGER_LOW |IRQF_ONESHOT , +"PENDWN" , tsi); +if (ret <0 ) { +dev_err (tsi->da9052->dev, +"Failed to register %s IRQ %d, error = %d\n" ,"PENDWN" , + tsi->da9052->irq_base + tsi->irq_pendwn, ret); + goto err_fifo_buf; + } + + tsi->irq_datardy =platform_get_irq_byname (pdev,"TSIRDY" ); + ret =request_threaded_irq (tsi->da9052->irq_base + tsi->irq_datardy, +NULL , da9052_ts_datardy_irq, +IRQF_TRIGGER_LOW |IRQF_ONESHOT , +"TSIRDY" , tsi); +if (ret <0 ) { +dev_err (tsi->da9052->dev, +"Failed to register %s IRQ %d, error = %d\n" ,"TSIRDY" , + tsi->da9052->irq_base + tsi->irq_datardy, ret);
drivers/input/touchscreen/da9052_tsi.c line 421
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+ goto err_fifo_buf; + } + + ret =da9052_ts_enable_device (tsi); +if (ret <0 ) + goto err_fifo_buf; + +return 0 ; + +err_fifo_buf:
Error handling is busted, you forgetting to free IRQs.
drivers/input/touchscreen/da9052_tsi.c line 425
Quoted 4 lines
drivers/input/touchscreen/da9052_tsi.c new file +4
-0+kfifo_free (&tsi->fifo_buf); +err_fifo: +kfifo_free (&tsi->fifo); +err_input:
Sometimes device is already registered here, you need to call input_unregister_device() in such cases. The easiest way to handle this case it to register input device as the very last action.
Quoted 11 lines
drivers/input/touchscreen/da9052_tsi.c new file +11
-0+input_free_device (input_dev); +err_mem: +kfree (tsi); +return ret; +} + +static int __devexit da9052_ts_remove(struct platform_device *pdev) +{ +struct da9052_tsi *tsi =platform_get_drvdata (pdev); +s32 ret; +
drivers/input/touchscreen/da9052_tsi.c line 446
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+ ret =da9052_clear_bits (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<0 ); +if (ret <0 ) +return ret; + + ret =da9052_reg_write (tsi->da9052,DA9052_LDO9_REG ,0x19 ); +if (ret <0 ) +return ret; + +free_irq (tsi->da9052->irq_base + tsi->irq_pendwn,NULL ); +free_irq (tsi->da9052->irq_base + tsi->irq_datardy,NULL );
You passed 'tsi' to request_irq(), here you are passing NULL thus leaking IRQs.
Quoted 35 lines
drivers/input/touchscreen/da9052_tsi.c new file +33
-0+ + tsi->tsi_pen_state_thread.state =DA9052_INACTIVE ; +wait_for_completion (&tsi->tsi_pen_state_thread.notifier); + + tsi->tsi_filter_thread.state =DA9052_INACTIVE ; +wait_for_completion (&tsi->tsi_filter_thread.notifier); + +input_unregister_device (tsi->dev); + +platform_set_drvdata (pdev,NULL ); + +kfifo_free (&tsi->fifo); +kfifo_free (&tsi->fifo_buf); +kfree (tsi); + +return 0 ; +} + +static struct platform_driver da9052_tsi_driver = { + .probe = da9052_ts_probe, + .remove =__devexit_p (da9052_ts_remove), + .driver = { + .name ="da9052-tsi" , + .owner =THIS_MODULE , + }, +}; + +static int __init da9052_ts_init (void ) +{ +return platform_driver_register (&da9052_tsi_driver); +} +module_init (da9052_ts_init); +
drivers/input/touchscreen/da9052_tsi.c line 489
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c new file +10
-0+static void __exit da9052_ts_exit(void) +{ +platform_driver_unregister (&da9052_tsi_driver); +} +module_exit (da9052_ts_exit); + +MODULE_DESCRIPTION ("Touchscreen driver for Dialog Semiconductor DA9052" ); +MODULE_AUTHOR ("David Dajun Chen <[email protected]>" ); +MODULE_LICENSE ("GPL" ); +MODULE_ALIAS ("platform:da9052-tsi" );
Thanks.
Signature · 1 line
Dmitry
Hi Ashish,
Quoted 14 lines · On Thu, Jul 14, 2011 at 02:28:10PM +0530, ashishj3 wrote:
This driver add support for DA9052 4-wire resistive ADC interfaced touchscreen controller.
DA9052 is a MFD therefore this driver depends on DA9052 core driver for core functionalities.
Signed-off-by David Dajun Chen <[email protected]>Signed-off-by Ashish Jangam <[email protected]>--- drivers/input/touchscreen/Kconfig | 7 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/da9052_tsi.c | 489 ++++++++++++++++++++++++++++++++ 3 files changed, 497 insertions(+), 0 deletions(-) create mode 100755 drivers/input/touchscreen/da9052_tsi.c
[snip]
drivers/input/touchscreen/da9052_tsi.c line 277
Quoted 5 lines
drivers/input/touchscreen/da9052_tsi.c new file +5
-0+ ret =da9052_clear_bits (da9052,DA9052_GPIO_4_5_REG ,0x33 ); +if (ret <0 ) +return -EIO ; + + ret =da9052_clear_bits (da9052,DA9052_GPIO_6_7_REG ,0x33 );
Those two register defines are missing in your posted MFD driver headerfile "reg.h".
Regards,
Michael
Signature · 4 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
RFC PATCH 1/1 da9052_tsi: remove fifo and use delayed work
In reply to ashishj3Remove the coordinate fifo and check for penup with a delayed work, instead of a watching kernel thread.
Issues:
Sometimes there are well defined jitter values on the x-axys this must be more investigated. Hint: DA9052_TSI_CONT_A_REG holds some time Adjust values for TSI_SKIP and TSI_DELAY, which might have to be properly aligned to the touch events.
--- drivers/input/touchscreen/da9052_tsi.c | 245 ++++++++------------------------ 1 files changed, 61 insertions(+), 184 deletions(-)
drivers/input/touchscreen/da9052_tsi.c +61 -184
@@ -15,47 +15,24 @@#include <linux/input.h> #include <linux/delay.h> #include <linux/platform_device.h> -#include <linux/freezer.h> +#include <linux/sched.h> #include <linux/kthread.h> -#include <linux/kfifo.h> #include <linux/mfd/da9052/reg.h> #include <linux/mfd/da9052/da9052.h> -#define DA9052_ACTIVE 1 -#define DA9052_INACTIVE 0 - -#define DA9052_TSI_FIFOSIZE 640 - -enum { -DA9052_PEN_IDLE , -DA9052_PEN_DOWN , -DA9052_PEN_UP -}; -struct da9052_tsi_reg {u16 x;u16 y; }; -struct tsi_thread_type { -u8 pid; -u8 state; -struct completion notifier; -struct task_struct *thread_task; -}; -struct da9052_tsi {struct da9052 *da9052;struct input_dev *dev; -struct tsi_thread_type tsi_pen_state_thread; -struct tsi_thread_type tsi_filter_thread; -struct kfifo fifo; -struct kfifo fifo_buf;u8 pen_up_detect_interval;u32 zero_data_cnt;u32 valid_penup_count; -u8 pen_state; +struct delayed_work work;int irq_pendwn;int irq_datardy; };
@@ -71,6 +48,48 @@ static inline int da9052_ts_stop(struct da9052_tsi *tsi)return da9052_clear_bits (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<0 ); } +static void da9052_work (struct work_struct *work) +{ + struct da9052_tsi *tsi = container_of(work, struct da9052_tsi, work.work); +struct da9052 *da9052 = tsi->da9052; +int ret; +uint8_t _v; +u16 down; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_LSB_REG ); +if (ret <0 ) +return ; + + _v = (uint8_t ) ret; + down = ((_v &0x40 ) >>6 ); + +if (!down) { + tsi->da9052->events_mask |=DA9052_E_TSI_READY ; + tsi->da9052->events_mask &= ~DA9052_E_PEN_DOWN ; + +/* Mask TSI_READY event and unmask PEN_DOWN event*/ + ret =da9052_reg_update (tsi->da9052,DA9052_IRQ_MASK_B_REG ,0x40 ,0x80 ); +if (ret <0 ) +return ; + +input_report_abs (tsi->dev,ABS_PRESSURE ,0 ); +input_report_key (tsi->dev,BTN_TOUCH ,1 ); +input_sync (tsi->dev); + }else { + da9052->events_mask |=DA9052_E_PEN_DOWN ; + da9052->events_mask &= ~DA9052_E_TSI_READY ; + +/* Mask PEN_DOWN event and unmask TSI_READY event*/ + ret =da9052_reg_update (da9052,DA9052_IRQ_MASK_B_REG ,0x80 ,0x40 ); +if (ret <0 ) +return ; + +/* start polling for touch_det to detect release */ +schedule_delayed_work (&tsi->work,HZ /50 ); + } + +} +static irqreturn_t da9052_ts_pendwn_irq (int irq,void *data) {struct da9052_tsi *tsi = (struct da9052_tsi *)data;
@@ -86,7 +105,10 @@ static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data)return IRQ_NONE ;da9052_ts_start (tsi); - tsi->pen_state =DA9052_PEN_DOWN ; + +input_report_abs (tsi->dev,ABS_PRESSURE ,1023 ); +input_report_key (tsi->dev,BTN_TOUCH ,0 ); +input_sync (tsi->dev);return IRQ_HANDLED ; }
@@ -118,7 +140,10 @@ static int da9052_ts_read(struct da9052_tsi *tsi) co_ord.x = ((_x <<2 ) &0x3fc ) | (_v &0x3 ); co_ord.y = ((_y <<2 ) &0x3fc ) | ((_v &0xc ) >>2 ); - ret =kfifo_in (&tsi->fifo, &co_ord,sizeof (struct da9052_tsi_reg )); +input_report_abs (tsi->dev,ABS_X , co_ord.x); +input_report_abs (tsi->dev,ABS_Y , co_ord.y); +input_report_abs (tsi->dev,ABS_PRESSURE ,1023 ); +input_sync (tsi->dev);return 0 ; }
@@ -135,131 +160,10 @@ static irqreturn_t da9052_ts_datardy_irq(int irq, void *data)return IRQ_NONE ; } -return IRQ_HANDLED ; -} - -/* -* Two FIFO are been used. FIFO1 is used for detecting pen up and -* FIFO2 for reporting pen down co-ordinate. -*/ -void da9052_ts_process_reg_data (struct da9052_tsi *tsi) -{ -struct da9052_tsi_reg tmp_raw_data; -u32 reg_data_cnt; -int ret; - - reg_data_cnt =kfifo_len (&tsi->fifo); - -while (reg_data_cnt-- >0 ) { - ret =kfifo_out (&tsi->fifo, &tmp_raw_data, -sizeof (struct da9052_tsi_reg )); -if (ret <0 ) -continue ; -kfifo_in (&tsi->fifo_buf, &tmp_raw_data, -sizeof (struct da9052_tsi_reg )); - } -return ; -} - -static void da9052_ts_report_penup (struct da9052_tsi *tsi) -{ -struct input_dev *ip_dev = tsi->dev; -struct da9052 *da9052 = tsi->da9052; -ssize_t ret; - - ret =da9052_ts_stop (tsi); -if (ret <0 ) -return ; - - da9052->events_mask |=DA9052_E_TSI_READY ; - da9052->events_mask &= ~DA9052_E_PEN_DOWN ; - -/* Mask TSI_READY event and unmask PEN_DOWN event*/ - ret =da9052_reg_update (da9052,DA9052_IRQ_MASK_B_REG ,0x40 ,0x80 ); -if (ret <0 ) -return ; - -input_report_abs (ip_dev,BTN_TOUCH ,0 ); -input_sync (ip_dev); - - tsi->zero_data_cnt =0 ; -} - -/* -* This function detects the pen up state using the kfifo len. -* If kfifo len is zero for some interval then pen up is reported. -* Else pen co-ordinate are reported. -*/ -static int da9052_ts_monitor_pen_state (void *data) -{ -struct da9052_tsi *tsi = (struct da9052_tsi *) data; -u32 data_cnt; - -set_freezable (); - -while (tsi->tsi_pen_state_thread.state ==DA9052_ACTIVE ) { -try_to_freeze (); - -set_current_state (TASK_INTERRUPTIBLE ); -schedule_timeout (msecs_to_jiffies (10 )); - -if (tsi->pen_state !=DA9052_PEN_DOWN ) -continue ; - - data_cnt =kfifo_len (&tsi->fifo); -if (data_cnt <0 ) -continue ; - -da9052_ts_process_reg_data (tsi); - -if (data_cnt) - tsi->zero_data_cnt =0 ; -else { -if ((++(tsi->zero_data_cnt)) > - tsi->valid_penup_count) { - tsi->pen_state =DA9052_PEN_UP ; -da9052_ts_report_penup (tsi); - } - } - } - -complete_and_exit (&tsi->tsi_pen_state_thread.notifier,0 ); -return 0 ; -} - -static int da9052_ts_process_thread (void *ptr) -{ -struct da9052_tsi_reg co_ord; -int cnt =0 , ret; -struct da9052_tsi *tsi = (struct da9052_tsi *)ptr; - -set_freezable (); - -while (tsi->tsi_filter_thread.state ==DA9052_ACTIVE ) { - -try_to_freeze (); - -set_current_state (TASK_INTERRUPTIBLE ); -schedule_timeout (msecs_to_jiffies (10 )); - cnt =kfifo_len (&tsi->fifo_buf); -if (cnt <=0 ) -continue ; - - ret =kfifo_out (&tsi->fifo_buf, &co_ord, -sizeof (struct da9052_tsi_reg )); -if (ret <0 ) -continue ; - -input_report_abs (tsi->dev,BTN_TOUCH ,1 ); -input_report_abs (tsi->dev,ABS_X , co_ord.x); -input_report_abs (tsi->dev,ABS_Y , co_ord.y); -input_sync (tsi->dev); - } - - tsi->tsi_filter_thread.thread_task =NULL ; -complete_and_exit (&tsi->tsi_filter_thread.notifier,0 ); +/* start polling for touch_det to detect release */ +schedule_delayed_work (&tsi->work,HZ /50 ); -return 0 ; +return IRQ_HANDLED ; }static int da9052_ts_configure_gpio (struct da9052 *da9052)
@@ -296,16 +200,6 @@ static int __init da9052_ts_enable_device(struct da9052_tsi *tsi) tsi->valid_penup_count =5 ; -init_completion (&tsi->tsi_pen_state_thread.notifier); - tsi->tsi_pen_state_thread.state =DA9052_ACTIVE ; - tsi->tsi_pen_state_thread.pid =kernel_thread (da9052_ts_monitor_pen_state, tsi, -CLONE_KERNEL |SIGCHLD ); - -init_completion (&tsi->tsi_filter_thread.notifier); - tsi->tsi_filter_thread.state =DA9052_ACTIVE ; - tsi->tsi_filter_thread.pid =kernel_thread (da9052_ts_process_thread, tsi, -CLONE_KERNEL |SIGCHLD ); - tsi->zero_data_cnt =0 ;/* Measure TSI sample every 1ms */
@@ -354,14 +248,6 @@ static s32 __devinit da9052_ts_probe(struct platform_device *pdev) goto err_mem; } - ret =kfifo_alloc (&tsi->fifo,DA9052_TSI_FIFOSIZE ,GFP_KERNEL ); -if (ret <0 ) - goto err_input; - - ret =kfifo_alloc (&tsi->fifo_buf,DA9052_TSI_FIFOSIZE ,GFP_KERNEL ); -if (ret <0 ) - goto err_fifo; - tsi->da9052 = da9052; tsi->pen_up_detect_interval =5 ;platform_set_drvdata (pdev, tsi);
@@ -388,6 +274,8 @@ static s32 __devinit da9052_ts_probe(struct platform_device *pdev)if (ret) goto err_mem; +INIT_DELAYED_WORK (&tsi->work, da9052_work); + tsi->irq_pendwn =platform_get_irq_byname (pdev,"PENDWN" ); ret = request_threaded_irq(tsi->da9052->irq_base + tsi->irq_pendwn, NULL, da9052_ts_pendwn_irq,
@@ -397,7 +285,7 @@ static s32 __devinit da9052_ts_probe(struct platform_device *pdev)dev_err (tsi->da9052->dev,"Failed to register %s IRQ %d, error = %d\n" ,"PENDWN" , tsi->da9052->irq_base + tsi->irq_pendwn, ret); - goto err_fifo_buf; + goto err_input; } tsi->irq_datardy =platform_get_irq_byname (pdev,"TSIRDY" );
@@ -409,19 +297,15 @@ static s32 __devinit da9052_ts_probe(struct platform_device *pdev)dev_err (tsi->da9052->dev,"Failed to register %s IRQ %d, error = %d\n" ,"TSIRDY" , tsi->da9052->irq_base + tsi->irq_datardy, ret); - goto err_fifo_buf; + goto err_input; } ret =da9052_ts_enable_device (tsi);if (ret <0 ) - goto err_fifo_buf; + goto err_input;return 0 ; -err_fifo_buf: -kfifo_free (&tsi->fifo_buf); -err_fifo: -kfifo_free (&tsi->fifo); err_input:input_free_device (input_dev); err_mem:
@@ -445,18 +329,11 @@ static int __devexit da9052_ts_remove(struct platform_device *pdev)free_irq (tsi->da9052->irq_base + tsi->irq_pendwn,NULL );free_irq (tsi->da9052->irq_base + tsi->irq_datardy,NULL ); - tsi->tsi_pen_state_thread.state =DA9052_INACTIVE ; -wait_for_completion (&tsi->tsi_pen_state_thread.notifier); - - tsi->tsi_filter_thread.state =DA9052_INACTIVE ; -wait_for_completion (&tsi->tsi_filter_thread.notifier); - +cancel_delayed_work (&tsi->work);input_unregister_device (tsi->dev);platform_set_drvdata (pdev,NULL ); -kfifo_free (&tsi->fifo); -kfifo_free (&tsi->fifo_buf);kfree (tsi);return 0 ;
Signature · 1 line
1.7.5.4
Dmitry Torokhov
maintainerRe: [RFC PATCH] da9052_tsi: remove fifo and use delayed work
Hi Michael,
Quoted 3 lines · Michael Grzeschik
Remove the coordinate fifo and check for penup with a delayed work, instead of a watching kernel thread.
Yes, this looks much better. A few comments below.
Quoted 16 lines
Issues:
Sometimes there are well defined jitter values on the x-axys this must be more investigated. Hint:DA9052_TSI_CONT_A_REGholds some time Adjust values forTSI_SKIPandTSI_DELAY, which might have to be properly aligned to the touch events.Signed-off-by Michael Grzeschik <[email protected]>--- drivers/input/touchscreen/da9052_tsi.c | 245 ++++++++------------------------ 1 files changed, 61 insertions(+), 184 deletions(-)drivers/input/touchscreen/da9052_tsi.c +0
-0
drivers/input/touchscreen/da9052_tsi.c line 19
Quoted 6 lines
drivers/input/touchscreen/da9052_tsi.c +1
-1@@ -15,47 +15,24 @@#include <linux/input.h> #include <linux/delay.h> #include <linux/platform_device.h> -#include <linux/freezer.h> +#include <linux/sched.h> #include <linux/kthread.h>
That can be dropped too I think.
Quoted 28 lines
drivers/input/touchscreen/da9052_tsi.c +0
-19-#include <linux/kfifo.h> #include <linux/mfd/da9052/reg.h> #include <linux/mfd/da9052/da9052.h> -#define DA9052_ACTIVE 1 -#define DA9052_INACTIVE 0 - -#define DA9052_TSI_FIFOSIZE 640 - -enum { -DA9052_PEN_IDLE , -DA9052_PEN_DOWN , -DA9052_PEN_UP -}; -struct da9052_tsi_reg {u16 x;u16 y; }; -struct tsi_thread_type { -u8 pid; -u8 state; -struct completion notifier; -struct task_struct *thread_task; -}; -
drivers/input/touchscreen/da9052_tsi.c line 34
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c +0
-4struct da9052_tsi {struct da9052 *da9052;struct input_dev *dev; -struct tsi_thread_type tsi_pen_state_thread; -struct tsi_thread_type tsi_filter_thread; -struct kfifo fifo; -struct kfifo fifo_buf;u8 pen_up_detect_interval;u32 zero_data_cnt;u32 valid_penup_count;
Above 2 are not used.
Quoted 22 lines
drivers/input/touchscreen/da9052_tsi.c +14
-1-u8 pen_state; +struct delayed_work work;int irq_pendwn;int irq_datardy; };@@ -71,6 +48,48 @@ static inline int da9052_ts_stop(struct da9052_tsi *tsi)return da9052_clear_bits (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<0 ); } +static void da9052_work (struct work_struct *work) +{ + struct da9052_tsi *tsi = container_of(work, struct da9052_tsi, work.work); +struct da9052 *da9052 = tsi->da9052; +int ret; +uint8_t _v; +u16 down; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_LSB_REG ); +if (ret <0 ) +return ; + + _v = (uint8_t ) ret;
drivers/input/touchscreen/da9052_tsi.c static inline int da9052_ts_stop(struct da9052_tsi *tsi) · line 73
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c +10
-0+ down = ((_v &0x40 ) >>6 ); + +if (!down) { + tsi->da9052->events_mask |=DA9052_E_TSI_READY ; + tsi->da9052->events_mask &= ~DA9052_E_PEN_DOWN ; + +/* Mask TSI_READY event and unmask PEN_DOWN event*/ + ret =da9052_reg_update (tsi->da9052,DA9052_IRQ_MASK_B_REG ,0x40 ,0x80 ); +if (ret <0 ) +return ;
There is no good way to handle da9052_reg_update() failure so don't.
drivers/input/touchscreen/da9052_tsi.c static inline int da9052_ts_stop(struct da9052_tsi *tsi) · line 75
Quoted 2 lines
drivers/input/touchscreen/da9052_tsi.c +2
-0+ +input_report_abs (tsi->dev,ABS_PRESSURE ,0 );
No fake pressure events please.
drivers/input/touchscreen/da9052_tsi.c static inline int da9052_ts_stop(struct da9052_tsi *tsi) · line 85
Quoted 10 lines
drivers/input/touchscreen/da9052_tsi.c +10
-0+input_report_key (tsi->dev,BTN_TOUCH ,1 ); +input_sync (tsi->dev); + }else { + da9052->events_mask |=DA9052_E_PEN_DOWN ; + da9052->events_mask &= ~DA9052_E_TSI_READY ; + +/* Mask PEN_DOWN event and unmask TSI_READY event*/ + ret =da9052_reg_update (da9052,DA9052_IRQ_MASK_B_REG ,0x80 ,0x40 ); +if (ret <0 ) +return ;
Why do we need to do the masking again? Just re-schedule the work.
Quoted 35 lines
drivers/input/touchscreen/da9052_tsi.c +15
-2+ +/* start polling for touch_det to detect release */ +schedule_delayed_work (&tsi->work,HZ /50 ); + } + +} +static irqreturn_t da9052_ts_pendwn_irq (int irq,void *data) {struct da9052_tsi *tsi = (struct da9052_tsi *)data;@@ -86,7 +105,10 @@ static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data)return IRQ_NONE ;da9052_ts_start (tsi); - tsi->pen_state =DA9052_PEN_DOWN ; + +input_report_abs (tsi->dev,ABS_PRESSURE ,1023 ); +input_report_key (tsi->dev,BTN_TOUCH ,0 ); +input_sync (tsi->dev);return IRQ_HANDLED ; }@@ -118,7 +140,10 @@ static int da9052_ts_read(struct da9052_tsi *tsi) co_ord.x = ((_x <<2 ) &0x3fc ) | (_v &0x3 ); co_ord.y = ((_y <<2 ) &0x3fc ) | ((_v &0xc ) >>2 ); - ret =kfifo_in (&tsi->fifo, &co_ord,sizeof (struct da9052_tsi_reg )); +input_report_abs (tsi->dev,ABS_X , co_ord.x); +input_report_abs (tsi->dev,ABS_Y , co_ord.y); +input_report_abs (tsi->dev,ABS_PRESSURE ,1023 ); +input_sync (tsi->dev);return 0 ; }
drivers/input/touchscreen/da9052_tsi.c static irqreturn_t da9052_ts_datardy_irq(int irq, void *data) · line 162
Quoted 3 lines
drivers/input/touchscreen/da9052_tsi.c +0
-0@@ -135,131 +160,10 @@ static irqreturn_t da9052_ts_datardy_irq(int irq, void *data)return IRQ_NONE ; }
[skip[
drivers/input/touchscreen/da9052_tsi.c static irqreturn_t da9052_ts_datardy_irq(int irq, void *data) · line 165
Quoted 3 lines
drivers/input/touchscreen/da9052_tsi.c +2
-0+/* start polling for touch_det to detect release */ +schedule_delayed_work (&tsi->work,HZ /50 );
What if da9052_ts_datardy_irq() never comes? You should schedule from pendown IRQ handler.
Quoted 4 lines
drivers/input/touchscreen/da9052_tsi.c +1
-1-return 0 ; +return IRQ_HANDLED ; }
...
drivers/input/touchscreen/da9052_tsi.c
Quoted 2 lines
drivers/input/touchscreen/da9052_tsi.c +1
-1- +cancel_delayed_work (&tsi->work);
cancel_delayed_work_sync()
There are a few other changes in the patch below, however I can't compile it since the rest of the MFD code is not in mainline nor in linux-next.
Thanks.
Signature · 12 lines
Dmitry Input: da9052 - misc fixes From: Dmitry Torokhov <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]> --- drivers/input/touchscreen/da9052_tsi.c | 210 +++++++++++++++----------------- 1 files changed, 96 insertions(+), 114 deletions(-)
drivers/input/touchscreen/da9052_tsi.c +96 -114
@@ -15,7 +15,6 @@#include <linux/delay.h> #include <linux/platform_device.h> #include <linux/sched.h> -#include <linux/kthread.h> #include <linux/mfd/da9052/reg.h> #include <linux/mfd/da9052/da9052.h>
@@ -26,23 +25,20 @@ struct da9052_tsi_reg { };struct da9052_tsi { -struct da9052 *da9052; +struct da9052 *da9052;struct input_dev *dev; -u8 pen_up_detect_interval; -u32 zero_data_cnt; -u32 valid_penup_count;struct delayed_work work;int irq_pendwn;int irq_datardy; }; -static inline int da9052_ts_start (struct da9052_tsi *tsi) +static int da9052_ts_start (struct da9052_tsi *tsi) {return da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<0 ,1 <<0 ); } -static inline int da9052_ts_stop (struct da9052_tsi *tsi) +static int da9052_ts_stop (struct da9052_tsi *tsi) {return da9052_clear_bits (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<0 ); }
@@ -63,51 +59,43 @@ static void da9052_work(struct work_struct *work) down = ((_v &0x40 ) >>6 );if (!down) { +input_report_key (tsi->dev,BTN_TOUCH ,0 ); +input_sync (tsi->dev); + +da9052_ts_stop (tsi); + tsi->da9052->events_mask |=DA9052_E_TSI_READY ; tsi->da9052->events_mask &= ~DA9052_E_PEN_DOWN ;/* Mask TSI_READY event and unmask PEN_DOWN event*/ - ret =da9052_reg_update (tsi->da9052,DA9052_IRQ_MASK_B_REG ,0x40 ,0x80 ); -if (ret <0 ) -return ; - -input_report_abs (tsi->dev,ABS_PRESSURE ,0 ); -input_report_key (tsi->dev,BTN_TOUCH ,1 ); -input_sync (tsi->dev); +da9052_reg_update (tsi->da9052,DA9052_IRQ_MASK_B_REG ,0x40 ,0x80 ); }else { - da9052->events_mask |=DA9052_E_PEN_DOWN ; - da9052->events_mask &= ~DA9052_E_TSI_READY ; - -/* Mask PEN_DOWN event and unmask TSI_READY event*/ - ret =da9052_reg_update (da9052,DA9052_IRQ_MASK_B_REG ,0x80 ,0x40 ); -if (ret <0 ) -return ; - -/* start polling for touch_det to detect release */ +/* keep polling to detect release */ schedule_delayed_work (&tsi->work,HZ /50 ); } - }static irqreturn_t da9052_ts_pendwn_irq (int irq,void *data) { -struct da9052_tsi *tsi = (struct da9052_tsi *)data; +struct da9052_tsi *tsi = data;struct da9052 *da9052 = tsi->da9052;int ret; +input_report_key (tsi->dev,BTN_TOUCH ,1 ); +input_sync (tsi->dev); + da9052->events_mask |=DA9052_E_PEN_DOWN ; da9052->events_mask &= ~DA9052_E_TSI_READY ; -/* Mask PEN_DOWN event and unmask TSI_READY event*/ +/* Mask PEN_DOWN event and unmask TSI_READY event */ ret =da9052_reg_update (da9052,DA9052_IRQ_MASK_B_REG ,0x80 ,0x40 );if (ret <0 )return IRQ_NONE ;da9052_ts_start (tsi); -input_report_abs (tsi->dev,ABS_PRESSURE ,1023 ); -input_report_key (tsi->dev,BTN_TOUCH ,0 ); -input_sync (tsi->dev); +/* start polling for touch_det to detect release */ +schedule_delayed_work (&tsi->work,HZ /50 );return IRQ_HANDLED ; }
@@ -141,7 +129,6 @@ static int da9052_ts_read(struct da9052_tsi *tsi)input_report_abs (tsi->dev,ABS_X , co_ord.x);input_report_abs (tsi->dev,ABS_Y , co_ord.y); -input_report_abs (tsi->dev,ABS_PRESSURE ,1023 );input_sync (tsi->dev);return 0 ;
@@ -149,23 +136,20 @@ static int da9052_ts_read(struct da9052_tsi *tsi)static irqreturn_t da9052_ts_datardy_irq (int irq,void *data) { -struct da9052_tsi *tsi = (struct da9052_tsi *)data; -int ret; +struct da9052_tsi *tsi = data; +int error; - ret =da9052_ts_read (tsi); -if (ret) { + error =da9052_ts_read (tsi); +if (error) {dev_err (tsi->da9052->dev, -"Failed to read TSI co-ordinate, %d\n" , ret); +"Failed to read TSI co-ordinate, error: %d\n" , error);return IRQ_NONE ; } -/* start polling for touch_det to detect release */ -schedule_delayed_work (&tsi->work,HZ /50 ); -return IRQ_HANDLED ; } -static int da9052_ts_configure_gpio (struct da9052 *da9052) +static int __devinit da9052_ts_configure_gpio (struct da9052 *da9052) {int ret;
@@ -181,26 +165,22 @@ static int da9052_ts_configure_gpio(struct da9052 *da9052)if (ret <0 )return -EIO ; -return ret; +return 0 ; } -static int __init da9052_ts_enable_device (struct da9052_tsi *tsi) +static int __devinit da9052_ts_enable_device (struct da9052_tsi *tsi) { -ssize_t ret;struct da9052 *da9052 = tsi->da9052; +int error; - ret =da9052_ts_configure_gpio (tsi->da9052); -if (ret <0 ) -return ret; + error =da9052_ts_configure_gpio (tsi->da9052); +if (error) +return error; ret =da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG ,0xFC ,0xC0 );if (ret <0 )return ret; - tsi->valid_penup_count =5 ; - - tsi->zero_data_cnt =0 ; -/* Measure TSI sample every 1ms */ ret =da9052_reg_update (tsi->da9052,DA9052_ADC_CONT_REG ,1 <<6 ,1 <<6 );
@@ -220,43 +200,49 @@ static int __init da9052_ts_enable_device(struct da9052_tsi *tsi)if (ret <0 )return ret; -/*Supply TSIRef thru LD09 */ +/* Supply TSIRef thru LD09 */ ret =da9052_reg_write (tsi->da9052,DA9052_LDO9_REG ,0x59 ); +if (ret <0 ) +return ret; -return ret; +return 0 ; } -static s32 __devinit da9052_ts_probe (struct platform_device *pdev) +static int __devinit da9052_ts_probe (struct platform_device *pdev) { +struct da9052 *da9052 =platform_get_drvdata (pdev->dev.parent);struct da9052_tsi *tsi;struct input_dev *input_dev; -struct da9052 *da9052; -int ret; - - da9052 =dev_get_drvdata (pdev->dev.parent); +int irq_pendown, irq_datardy; +int error; + + irq_pendwn =platform_get_irq_byname (pdev,"PENDWN" ); + irq_datardy =platform_get_irq_byname (pdev,"TSIRDY" ); +if (irq_pendown <0 || irq_datardy <0 ) { +dev_err (da9052->dev,"Unable to determine device interrupts\n" ); +return -ENXIO ; + } tsi =kzalloc (sizeof (struct da9052_tsi ),GFP_KERNEL ); -if (!tsi) -return -ENOMEM ; - input_dev =input_allocate_device (); -if (!input_dev) { -dev_err (tsi->da9052->dev, -"failed to allocate input device\n" ); +if (!tsi || !input_dev) { +dev_err (da9052->dev,"failed to allocate memory\n" ); ret = -ENOMEM ; - goto err_mem; + goto err_free_mem; } tsi->da9052 = da9052; - tsi->pen_up_detect_interval =5 ; -platform_set_drvdata (pdev, tsi); + tsi->dev = input_dev; + tsi->irq_pendown = irq_pendwn; + tsi->irq_datadry = irq_datardy; +INIT_DELAYED_WORK (&tsi->work, da9052_work); + input_dev->name ="Dialog DA9052 TouchScreen Driver" ; input_dev->id.version =0x0101 ; input_dev->id.vendor =0x15B6 ; input_dev->id.product =0x9052 ; input_dev->id.bustype =BUS_RS232 ; - input_dev->name ="Dialog DA9052 TouchScreen Driver" ; - input_dev->dev.parent = &pdev->dev; + input_dev->dev.parent = &pdev->dev;__set_bit (EV_ABS , input_dev->evbit);__set_bit (EV_KEY , input_dev->evbit);__set_bit (BTN_TOUCH , input_dev->keybit);
@@ -265,85 +251,81 @@ static s32 __devinit da9052_ts_probe(struct platform_device *pdev)input_set_abs_params (input_dev,ABS_X ,0 ,1023 ,0 ,0 );input_set_abs_params (input_dev,ABS_Y ,0 ,1023 ,0 ,0 ); -input_set_abs_params (input_dev,ABS_PRESSURE ,0 ,1023 ,0 ,0 ); - tsi->dev = input_dev;input_set_drvdata (input_dev, tsi); - ret =input_register_device (tsi->dev); -if (ret) - goto err_mem; -INIT_DELAYED_WORK (&tsi->work, da9052_work); - - tsi->irq_pendwn =platform_get_irq_byname (pdev,"PENDWN" ); - ret =request_threaded_irq (tsi->da9052->irq_base + tsi->irq_pendwn, -NULL , da9052_ts_pendwn_irq, -IRQF_TRIGGER_LOW |IRQF_ONESHOT , -"PENDWN" , tsi); -if (ret <0 ) { -dev_err (tsi->da9052->dev, + error =request_threaded_irq (tsi->da9052->irq_base + tsi->irq_pendwn, +NULL , da9052_ts_pendwn_irq, +IRQF_TRIGGER_LOW |IRQF_ONESHOT , +"PENDWN" , tsi); +if (error) { +dev_err (da9052->dev,"Failed to register %s IRQ %d, error = %d\n" ,"PENDWN" , - tsi->da9052->irq_base + tsi->irq_pendwn, ret); + tsi->da9052->irq_base + tsi->irq_pendwn, error); goto err_input; } - tsi->irq_datardy =platform_get_irq_byname (pdev,"TSIRDY" ); - ret =request_threaded_irq (tsi->da9052->irq_base + tsi->irq_datardy, -NULL , da9052_ts_datardy_irq, -IRQF_TRIGGER_LOW |IRQF_ONESHOT , -"TSIRDY" , tsi); -if (ret <0 ) { -dev_err (tsi->da9052->dev, + error =request_threaded_irq (tsi->da9052->irq_base + tsi->irq_datardy, +NULL , da9052_ts_datardy_irq, +IRQF_TRIGGER_LOW |IRQF_ONESHOT , +"TSIRDY" , tsi); +if (error) { +dev_err (da9052->dev,"Failed to register %s IRQ %d, error = %d\n" ,"TSIRDY" , - tsi->da9052->irq_base + tsi->irq_datardy, ret); - goto err_input; + tsi->da9052->irq_base + tsi->irq_datardy, error); + goto err_free_pendown; } - ret =da9052_ts_enable_device (tsi); -if (ret <0 ) - goto err_input; + error =da9052_ts_enable_device (tsi); +if (error) { +dev_err (da9052->dev, +"Failed to enable device, error: %d\n" , error); + goto err_free_datardy; + } + error =input_register_device (tsi->dev); +if (error) + goto err_free_datardy; + +platform_set_drvdata (pdev, tsi);return 0 ; -err_input: +err_free_pendown: +free_irq (tsi->da9052->irq_base + tsi->irq_pendwn, tsi); +err_free_datardy: +free_irq (tsi->da9052->irq_base + tsi->irq_datardy, tsi); +err_free_mem:input_free_device (input_dev); -err_mem:kfree (tsi); -return ret; +return error; } static int __devexit da9052_ts_remove(struct platform_device *pdev) {struct da9052_tsi *tsi =platform_get_drvdata (pdev); -s32 ret; - ret =da9052_clear_bits (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<0 ); -if (ret <0 ) -return ret; +da9052_ts_stop (tsi); +da9052_reg_write (tsi->da9052,DA9052_LDO9_REG ,0x19 ); - ret =da9052_reg_write (tsi->da9052,DA9052_LDO9_REG ,0x19 ); -if (ret <0 ) -return ret; +free_irq (tsi->da9052->irq_base + tsi->irq_pendwn, tsi); +free_irq (tsi->da9052->irq_base + tsi->irq_datardy, tsi); -free_irq (tsi->da9052->irq_base + tsi->irq_pendwn,NULL ); -free_irq (tsi->da9052->irq_base + tsi->irq_datardy,NULL ); +cancel_delayed_work_sync (&tsi->work); -cancel_delayed_work (&tsi->work);input_unregister_device (tsi->dev); +kfree (tsi);platform_set_drvdata (pdev,NULL ); -kfree (tsi); -return 0 ; }static struct platform_driver da9052_tsi_driver = { - .probe = da9052_ts_probe, - .remove =__devexit_p (da9052_ts_remove), - .driver = { - .name ="da9052-tsi" , - .owner =THIS_MODULE , + .probe = da9052_ts_probe, + .remove =__devexit_p (da9052_ts_remove), + .driver = { + .name ="da9052-tsi" , + .owner =THIS_MODULE , }, };