Touch: DA9052/53 touch screen driver v1
Subsystems (2)
PATCH 7/7 Touch: DA9052/53 touch screen driver v1
This driver adds support for DA9052/53 4-wire resistive ADC interfaced touchscreen controller.
DA9052/53 is a MFD therefore this driver depends on DA9052/53 core driver for core functionalities.
This patch is functionally tested on Samsung SMDKV6410.
--- drivers/input/touchscreen/Kconfig | 7 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/da9052_tsi.c | 353 ++++++++++++++++++++++++++++++++ 3 files changed, 361 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/da9052_tsi.c
drivers/input/touchscreen/Kconfig +7 -0
@@ -187,6 +187,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/DA9053 TSI" + depends on PMIC_DA9052 + help + Say y here to support the touchscreen found on Dialog Semiconductor + DA9052-BC and DA9053-AA/Bx PMICs. + config TOUCHSCREEN_DYNAPRO tristate "Dynapro serial touchscreen" select SERIO
drivers/input/touchscreen/Makefile +1 -0
@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.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 +353 -0
353 lines not on this page · raw message
Any update on the below patch
Quoted 407 lines · Ashish Jangam
This driver adds support for DA9052/53 4-wire resistive ADC interfaced touchscreen controller.
DA9052/53 is a MFD therefore this driver depends on DA9052/53 core driver for core functionalities.
This patch is functionally tested on Samsung SMDKV6410.
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 | 353 ++++++++++++++++++++++++++++++++ 3 files changed, 361 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/da9052_tsi.cdrivers/input/touchscreen/Kconfig +7
-0@@ -187,6 +187,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/DA9053 TSI" + depends on PMIC_DA9052 + help + Say y here to support the touchscreen found on Dialog Semiconductor + DA9052-BC and DA9053-AA/Bx PMICs. + config TOUCHSCREEN_DYNAPRO tristate "Dynapro serial touchscreen" select SERIOdrivers/input/touchscreen/Makefile +1
-0@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.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 +353
-0@@ -0,0 +1,353 @@ +/* +* TSI driver for Dialog DA9052 +* +* Copyright(c) 2012 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/interrupt.h> + +#include <linux/mfd/da9052/reg.h> +#include <linux/mfd/da9052/da9052.h> + +#define TSI_PEN_DOWN_STATUS 0x40 + +struct da9052_tsi { +struct da9052 *da9052; +struct input_dev *dev; +struct delayed_work ts_pen_work; +int irq_pendwn; +int irq_datardy; +}; + +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 int da9052_ts_stop (struct da9052_tsi *tsi) +{ +return da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<0 ,0 ); +} + +static irqreturn_t da9052_ts_pendwn_irq (int irq,void *data) +{ +struct da9052_tsi *tsi = data; + +/* Mask PEN_DOWN event and unmask TSI_READY event */ +disable_irq_nosync (tsi->irq_pendwn); +enable_irq (tsi->irq_datardy); + +da9052_ts_start (tsi); + +input_report_key (tsi->dev,BTN_TOUCH ,1 ); +input_sync (tsi->dev); + +schedule_delayed_work (&tsi->ts_pen_work,HZ /50 ); + +return IRQ_HANDLED ; +} + +static int da9052_ts_read (struct da9052_tsi *tsi) +{ +int ret =0 ; +u16 x, y, z; +u8 v; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_X_MSB_REG ); +if (ret <0 ) + goto exit; + + x = (u16 ) ret; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_Y_MSB_REG ); +if (ret <0 ) + goto exit; + + y = (u16 ) ret; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_Z_MSB_REG ); +if (ret <0 ) + goto exit; + + z = (u16 ) ret; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_LSB_REG ); +if (ret <0 ) + goto exit; + + v = (u8 ) ret; + + x = ((x <<2 ) &0x3fc ) | (v &0x3 ); + y = ((y <<2 ) &0x3fc ) | ((v &0xc ) >>2 ); + z = ((z <<2 ) &0x3fc ) | ((v &0x30 ) >>4 ); + +input_report_abs (tsi->dev,ABS_X , x); +input_report_abs (tsi->dev,ABS_Y , y); +input_report_abs (tsi->dev,ABS_PRESSURE , z); +input_report_key (tsi->dev,BTN_TOUCH ,1 ); +input_sync (tsi->dev); + +exit: +return ret; +} + +static irqreturn_t da9052_ts_datardy_irq (int irq,void *data) +{ +struct da9052_tsi *tsi = data; + +da9052_ts_read (tsi); +return IRQ_HANDLED ; +} + +static void da9052_ts_pen_work (struct work_struct *work) +{ + struct da9052_tsi *tsi = container_of(work, struct da9052_tsi, + ts_pen_work.work); +struct input_dev *ip_dev = tsi->dev; +int ret; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_LSB_REG ); +if (ret <0 ) +return ; + +if (ret &TSI_PEN_DOWN_STATUS )/* Pen Down */ +schedule_delayed_work (&tsi->ts_pen_work,HZ /50 ); +else { +/* Pen UP */ +da9052_ts_stop (tsi); + +/* Mask TSI_READY event and unmask PEN_DOWN event */ +disable_irq (tsi->irq_datardy); +enable_irq (tsi->irq_pendwn); + +/* Report Pen UP */ +input_report_abs (ip_dev,ABS_PRESSURE ,0 ); +input_report_key (ip_dev,BTN_TOUCH ,0 ); +input_sync (ip_dev); + } +} + +static int __devinit da9052_ts_configure_gpio (struct da9052 *da9052) +{ +int ret; + + ret =da9052_reg_update (da9052,DA9052_GPIO_2_3_REG ,0x30 ,0 ); +if (ret <0 ) +return ret; + + ret =da9052_reg_update (da9052,DA9052_GPIO_4_5_REG ,0x33 ,0 ); +if (ret <0 ) +return ret; + + ret =da9052_reg_update (da9052,DA9052_GPIO_6_7_REG ,0x33 ,0 ); + +return ret; +} + +static int __devinit da9052_configure_tsi (struct da9052_tsi *tsi) +{ +ssize_t ret; + + ret =da9052_ts_configure_gpio (tsi->da9052); +if (ret <0 ) +return ret; + +/* 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: 3 slots, TSI_SKIP: 0 slots, TSI_MODE: XYZP */ + ret =da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG ,0xFC ,0xC0 ); +if (ret <0 ) +return ret; + +/* Mask PEN_DOWN and TSI_READY events */ +disable_irq (tsi->irq_pendwn); +disable_irq (tsi->irq_datardy); + +/*Supply TSIRef through LD09 */ + ret =da9052_reg_write (tsi->da9052,DA9052_LDO9_REG ,0x59 ); + +return ret; +} + +static int da9052_ts_input_open (struct input_dev *input_dev) +{ +struct da9052_tsi *tsi =input_get_drvdata (input_dev); + +/* Unmask PEN_DOWN event */ +enable_irq (tsi->irq_pendwn); + +/* Enable Pen Detect Circuit */ +return da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG , +1 <<1 ,1 <<1 ); +} + +static void da9052_ts_input_close (struct input_dev *input_dev) +{ +struct da9052_tsi *tsi =input_get_drvdata (input_dev); +int ret; + + ret =da9052_reg_read (tsi->da9052,DA9052_TSI_LSB_REG ); + +if (ret &TSI_PEN_DOWN_STATUS )/* Pen Down */ +disable_irq (tsi->irq_datardy); +else +disable_irq (tsi->irq_pendwn); + +cancel_delayed_work_sync (&tsi->ts_pen_work); + +da9052_ts_stop (tsi); + +/* Disable Pen Detect Circuit */ +da9052_reg_update (tsi->da9052,DA9052_TSI_CONT_A_REG ,1 <<1 ,0 ); +} + +static int __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); +if (da9052 ==NULL ) +return -EINVAL ; + + tsi =devm_kzalloc (&pdev->dev,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; + } + +INIT_DELAYED_WORK (&tsi->ts_pen_work, da9052_ts_pen_work); + + tsi->da9052 = da9052; + + input_dev->id.version =0x0101 ; + input_dev->id.vendor =0x15B6 ; + input_dev->id.product =0x9052 ; + input_dev->name ="Dialog DA9052 TouchScreen Driver" ; + input_dev->dev.parent = &pdev->dev; + input_dev->open = da9052_ts_input_open; + input_dev->close = da9052_ts_input_close; +__set_bit (EV_ABS , input_dev->evbit); +__set_bit (EV_KEY , input_dev->evbit); +__set_bit (BTN_TOUCH , input_dev->keybit); + +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); + + tsi->irq_pendwn =platform_get_irq_byname (pdev,"PENDWN" ); +if (tsi->irq_pendwn <0 ) { + ret = tsi->irq_pendwn; + goto err_input; + } + + ret =request_threaded_irq (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->irq_pendwn, ret); + goto err_input; + } + + tsi->irq_datardy =platform_get_irq_byname (pdev,"TSIRDY" ); +if (tsi->irq_datardy <0 ) { + ret = tsi->irq_datardy; + goto err_pendwn_irq; + } + + ret =request_threaded_irq (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->irq_datardy, ret); + goto err_pendwn_irq; + } + + ret =da9052_configure_tsi (tsi); +if (ret <0 ) + goto err_datardy_irq; + + ret =input_register_device (tsi->dev); +if (ret <0 ) + goto err_datardy_irq; + +platform_set_drvdata (pdev, tsi); + +return 0 ; + +err_datardy_irq: +free_irq (tsi->irq_datardy, tsi); +err_pendwn_irq: +free_irq (tsi->irq_pendwn, tsi); +err_input: +input_free_device (input_dev); +err_mem: +devm_kfree (&pdev->dev, tsi); +return ret; +} + +static int __devexit da9052_ts_remove(struct platform_device *pdev) +{ +struct da9052_tsi *tsi =platform_get_drvdata (pdev); + +da9052_reg_write (tsi->da9052,DA9052_LDO9_REG ,0x19 ); + +free_irq (tsi->irq_pendwn, tsi); +free_irq (tsi->irq_datardy, tsi); + +input_unregister_device (tsi->dev); + +platform_set_drvdata (pdev,NULL ); + +devm_kfree (&pdev->dev, 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 , + }, +}; + +module_platform_driver (da9052_tsi_driver); + +MODULE_DESCRIPTION ("Touchscreen driver for Dialog Semiconductor DA9052" ); +MODULE_AUTHOR ("David Dajun Chen <[email protected]>" ); +MODULE_LICENSE ("GPL" ); +MODULE_ALIAS ("platform:da9052-tsi" );
Dmitry Torokhov
maintainerHi Ashish,
Quoted 1 line · Ashish Jangam
Any update on the below patch
I looked the patch over and I think that the disabling of the IRQs in da9052_ts_input_close() is racy. You can't read device status and disable one IRQ or another as pendwn IRQ may fire right after you read the register and you will disable the wrong one.
I tried correcting this problem and also did some more cosmetic changes, could you please try the patch below and let me know if it works for you?
Thanks!
Signature · 23 lines
Dmitry Input: add support for DA9052/53 touch screen controller From: Ashish Jangam <[email protected]> This driver adds support for DA9052/53 4-wire resistive ADC interfaced touchscreen controller. DA9052/53 is a multi-function device, therefore this driver depends on DA9052/53 core. This patch is functionally tested on Samsung SMDKV6410. Signed-off-by: David Dajun Chen <[email protected]> Signed-off-by: Ashish Jangam <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]> --- drivers/input/touchscreen/Kconfig | 17 ++ drivers/input/touchscreen/Makefile | 1 drivers/input/touchscreen/da9052_tsi.c | 361 ++++++++++++++++++++++++++++++++ 3 files changed, 379 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/da9052_tsi.c
drivers/input/touchscreen/Kconfig +17 -0
@@ -187,6 +187,23 @@ config TOUCHSCREEN_DA9034 Say Y here to enable the support for the touchscreen found on Dialog Semiconductor DA9034 PMIC. + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called da9034-ts. + +config TOUCHSCREEN_DA9052 + tristate "Dialog DA9052/DA9053 TSI" + depends on PMIC_DA9052 + help + Say Y here to support the touchscreen found on Dialog Semiconductor + DA9052-BC and DA9053-AA/Bx PMICs. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called da9052_tsi. + config TOUCHSCREEN_DYNAPRO tristate "Dynapro serial touchscreen" select SERIO
drivers/input/touchscreen/Makefile +1 -0
@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.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 +361 -0
361 lines not on this page · raw message