diff options
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 45 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 3 | ||||
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/corgi_ts.c | 385 | ||||
-rw-r--r-- | drivers/input/touchscreen/hampshire.c | 205 | ||||
-rw-r--r-- | drivers/input/touchscreen/s3c2410_ts.c | 40 | ||||
-rw-r--r-- | drivers/input/touchscreen/tps6507x-ts.c | 400 | ||||
-rw-r--r-- | drivers/input/touchscreen/tsc2007.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/usbtouchscreen.c | 20 | ||||
-rw-r--r-- | drivers/input/touchscreen/wm97xx-core.c | 2 |
10 files changed, 668 insertions, 438 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8a8fa4d2d6a..6703c6b9800 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -99,22 +99,6 @@ config TOUCHSCREEN_BITSY To compile this driver as a module, choose M here: the module will be called h3600_ts_input. -config TOUCHSCREEN_CORGI - tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" - depends on PXA_SHARPSL - select CORGI_SSP_DEPRECATED - help - Say Y here to enable the driver for the touchscreen on the - Sharp SL-C7xx and SL-Cxx00 series of PDAs. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called corgi_ts. - - NOTE: this driver is deprecated, try enable SPI and generic - ADS7846-based touchscreen driver. - config TOUCHSCREEN_DA9034 tristate "Touchscreen support for Dialog Semiconductor DA9034" depends on PMIC_DA903X @@ -135,6 +119,18 @@ config TOUCHSCREEN_DYNAPRO To compile this driver as a module, choose M here: the module will be called dynapro. +config TOUCHSCREEN_HAMPSHIRE + tristate "Hampshire serial touchscreen" + select SERIO + help + Say Y here if you have a Hampshire serial touchscreen connected to + your system. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called hampshire. + config TOUCHSCREEN_EETI tristate "EETI touchscreen panel support" depends on I2C @@ -158,8 +154,8 @@ config TOUCHSCREEN_FUJITSU module will be called fujitsu-ts. config TOUCHSCREEN_S3C2410 - tristate "Samsung S3C2410 touchscreen input driver" - depends on ARCH_S3C2410 + tristate "Samsung S3C2410/generic touchscreen input driver" + depends on ARCH_S3C2410 || SAMSUNG_DEV_TS select S3C24XX_ADC help Say Y here if you have the s3c2410 touchscreen. @@ -594,4 +590,17 @@ config TOUCHSCREEN_PCAP To compile this driver as a module, choose M here: the module will be called pcap_ts. + +config TOUCHSCREEN_TPS6507X + tristate "TPS6507x based touchscreens" + depends on I2C + help + Say Y here if you have a TPS6507x based touchscreen + controller. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called tps6507x_ts. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7fef7d5cca2..497964a7a21 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -12,8 +12,8 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o -obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o +obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o @@ -46,3 +46,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_TPS6507X) += tps6507x-ts.o diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 532279cda0e..634f6f6b9b1 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -1163,8 +1163,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->reg = regulator_get(&spi->dev, "vcc"); if (IS_ERR(ts->reg)) { - dev_err(&spi->dev, "unable to get regulator: %ld\n", - PTR_ERR(ts->reg)); + err = PTR_ERR(ts->reg); + dev_err(&spi->dev, "unable to get regulator: %ld\n", err); goto err_free_gpio; } diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c deleted file mode 100644 index 94a1919d439..00000000000 --- a/drivers/input/touchscreen/corgi_ts.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models - * - * Copyright (c) 2004-2005 Richard Purdie - * - * 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/delay.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/input.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/irq.h> - -#include <mach/sharpsl.h> -#include <mach/hardware.h> -#include <mach/pxa2xx-gpio.h> - - -#define PWR_MODE_ACTIVE 0 -#define PWR_MODE_SUSPEND 1 - -#define X_AXIS_MAX 3830 -#define X_AXIS_MIN 150 -#define Y_AXIS_MAX 3830 -#define Y_AXIS_MIN 190 -#define PRESSURE_MIN 0 -#define PRESSURE_MAX 15000 - -struct ts_event { - short pressure; - short x; - short y; -}; - -struct corgi_ts { - struct input_dev *input; - struct timer_list timer; - struct ts_event tc; - int pendown; - int power_mode; - int irq_gpio; - struct corgits_machinfo *machinfo; -}; - -#ifdef CONFIG_PXA25x -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) -#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) -#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) -#endif -#ifdef CONFIG_PXA27x -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) -#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x)) -#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x)) -#endif - -/* ADS7846 Touch Screen Controller bit definitions */ -#define ADSCTRL_PD0 (1u << 0) /* PD0 */ -#define ADSCTRL_PD1 (1u << 1) /* PD1 */ -#define ADSCTRL_DFR (1u << 2) /* SER/DFR */ -#define ADSCTRL_MOD (1u << 3) /* Mode */ -#define ADSCTRL_ADR_SH 4 /* Address setting */ -#define ADSCTRL_STS (1u << 7) /* Start Bit */ - -/* External Functions */ -extern unsigned int get_clk_frequency_khz(int info); - -static unsigned long calc_waittime(struct corgi_ts *corgi_ts) -{ - unsigned long hsync_invperiod = corgi_ts->machinfo->get_hsync_invperiod(); - - if (hsync_invperiod) - return get_clk_frequency_khz(0)*1000/hsync_invperiod; - else - return 0; -} - -static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend, - unsigned int address, unsigned long wait_time) -{ - unsigned long timer1 = 0, timer2, pmnc = 0; - int pos = 0; - - if (wait_time && doSend) { - PMNC_GET(pmnc); - if (!(pmnc & 0x01)) - PMNC_SET(0x01); - - /* polling HSync */ - corgi_ts->machinfo->wait_hsync(); - /* get CCNT */ - CCNT(timer1); - } - - if (doRecive) - pos = corgi_ssp_ads7846_get(); - - if (doSend) { - int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS; - /* dummy command */ - corgi_ssp_ads7846_put(cmd); - corgi_ssp_ads7846_get(); - - if (wait_time) { - /* Wait after HSync */ - CCNT(timer2); - if (timer2-timer1 > wait_time) { - /* too slow - timeout, try again */ - corgi_ts->machinfo->wait_hsync(); - /* get CCNT */ - CCNT(timer1); - /* Wait after HSync */ - CCNT(timer2); - } - while (timer2 - timer1 < wait_time) - CCNT(timer2); - } - corgi_ssp_ads7846_put(cmd); - if (wait_time && !(pmnc & 0x01)) - PMNC_SET(pmnc); - } - return pos; -} - -static int read_xydata(struct corgi_ts *corgi_ts) -{ - unsigned int x, y, z1, z2; - unsigned long flags, wait_time; - - /* critical section */ - local_irq_save(flags); - corgi_ssp_ads7846_lock(); - wait_time = calc_waittime(corgi_ts); - - /* Y-axis */ - sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time); - - /* Y-axis */ - sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time); - - /* X-axis */ - y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time); - - /* Z1 */ - x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time); - - /* Z2 */ - z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time); - z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time); - - /* Power-Down Enable */ - corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - corgi_ssp_ads7846_get(); - - corgi_ssp_ads7846_unlock(); - local_irq_restore(flags); - - if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) { - corgi_ts->tc.pressure = 0; - return 0; - } - - corgi_ts->tc.x = x; - corgi_ts->tc.y = y; - corgi_ts->tc.pressure = (x * (z2 - z1)) / z1; - return 1; -} - -static void new_data(struct corgi_ts *corgi_ts) -{ - struct input_dev *dev = corgi_ts->input; - - if (corgi_ts->power_mode != PWR_MODE_ACTIVE) - return; - - if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) - return; - - input_report_abs(dev, ABS_X, corgi_ts->tc.x); - input_report_abs(dev, ABS_Y, corgi_ts->tc.y); - input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); - input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); - input_sync(dev); -} - -static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) -{ - if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) { - /* Disable Interrupt */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_NONE); - if (read_xydata(corgi_ts)) { - corgi_ts->pendown = 1; - new_data(corgi_ts); - } - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - } else { - if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) { - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - corgi_ts->pendown++; - return; - } - - if (corgi_ts->pendown) { - corgi_ts->tc.pressure = 0; - new_data(corgi_ts); - } - - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - corgi_ts->pendown = 0; - } -} - -static void corgi_ts_timer(unsigned long data) -{ - struct corgi_ts *corgits_data = (struct corgi_ts *) data; - - ts_interrupt_main(corgits_data, 1); -} - -static irqreturn_t ts_interrupt(int irq, void *dev_id) -{ - struct corgi_ts *corgits_data = dev_id; - - ts_interrupt_main(corgits_data, 0); - return IRQ_HANDLED; -} - -#ifdef CONFIG_PM -static int corgits_suspend(struct platform_device *dev, pm_message_t state) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(dev); - - if (corgi_ts->pendown) { - del_timer_sync(&corgi_ts->timer); - corgi_ts->tc.pressure = 0; - new_data(corgi_ts); - corgi_ts->pendown = 0; - } - corgi_ts->power_mode = PWR_MODE_SUSPEND; - - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - - return 0; -} - -static int corgits_resume(struct platform_device *dev) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(dev); - - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - return 0; -} -#else -#define corgits_suspend NULL -#define corgits_resume NULL -#endif - -static int __devinit corgits_probe(struct platform_device *pdev) -{ - struct corgi_ts *corgi_ts; - struct input_dev *input_dev; - int err = -ENOMEM; - - corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!corgi_ts || !input_dev) - goto fail1; - - platform_set_drvdata(pdev, corgi_ts); - - corgi_ts->machinfo = pdev->dev.platform_data; - corgi_ts->irq_gpio = platform_get_irq(pdev, 0); - - if (corgi_ts->irq_gpio < 0) { - err = -ENODEV; - goto fail1; - } - - corgi_ts->input = input_dev; - - init_timer(&corgi_ts->timer); - corgi_ts->timer.data = (unsigned long) corgi_ts; - corgi_ts->timer.function = corgi_ts_timer; - - input_dev->name = "Corgi Touchscreen"; - input_dev->phys = "corgits/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); - - pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN); - - /* Initiaize ADS7846 Difference Reference mode */ - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - - if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { - err = -EBUSY; - goto fail1; - } - - err = input_register_device(corgi_ts->input); - if (err) - goto fail2; - - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - - return 0; - - fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); - fail1: input_free_device(input_dev); - kfree(corgi_ts); - return err; -} - -static int __devexit corgits_remove(struct platform_device *pdev) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); - - free_irq(corgi_ts->irq_gpio, corgi_ts); - del_timer_sync(&corgi_ts->timer); - corgi_ts->machinfo->put_hsync(); - input_unregister_device(corgi_ts->input); - kfree(corgi_ts); - - return 0; -} - -static struct platform_driver corgits_driver = { - .probe = corgits_probe, - .remove = __devexit_p(corgits_remove), - .suspend = corgits_suspend, - .resume = corgits_resume, - .driver = { - .name = "corgi-ts", - .owner = THIS_MODULE, - }, -}; - -static int __init corgits_init(void) -{ - return platform_driver_register(&corgits_driver); -} - -static void __exit corgits_exit(void) -{ - platform_driver_unregister(&corgits_driver); -} - -module_init(corgits_init); -module_exit(corgits_exit); - -MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); -MODULE_DESCRIPTION("Corgi TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:corgi-ts"); diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c new file mode 100644 index 00000000000..2da6cc31bb2 --- /dev/null +++ b/drivers/input/touchscreen/hampshire.c @@ -0,0 +1,205 @@ +/* + * Hampshire serial touchscreen driver + * + * Copyright (c) 2010 Adam Bennett + * Based on the dynapro driver (c) Tias Guns + * + */ + +/* + * 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. + */ + +/* + * 2010/04/08 Adam Bennett <abennett72@gmail.com> + * Copied dynapro.c and edited for Hampshire 4-byte protocol + */ + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/serio.h> +#include <linux/init.h> + +#define DRIVER_DESC "Hampshire serial touchscreen driver" + +MODULE_AUTHOR("Adam Bennett <abennett72@gmail.com>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +/* + * Definitions & global arrays. + */ + +#define HAMPSHIRE_FORMAT_TOUCH_BIT 0x40 +#define HAMPSHIRE_FORMAT_LENGTH 4 +#define HAMPSHIRE_RESPONSE_BEGIN_BYTE 0x80 + +#define HAMPSHIRE_MIN_XC 0 +#define HAMPSHIRE_MAX_XC 0x1000 +#define HAMPSHIRE_MIN_YC 0 +#define HAMPSHIRE_MAX_YC 0x1000 + +#define HAMPSHIRE_GET_XC(data) (((data[3] & 0x0c) >> 2) | (data[1] << 2) | ((data[0] & 0x38) << 6)) +#define HAMPSHIRE_GET_YC(data) ((data[3] & 0x03) | (data[2] << 2) | ((data[0] & 0x07) << 9)) +#define HAMPSHIRE_GET_TOUCHED(data) (HAMPSHIRE_FORMAT_TOUCH_BIT & data[0]) + +/* + * Per-touchscreen data. + */ + +struct hampshire { + struct input_dev *dev; + struct serio *serio; + int idx; + unsigned char data[HAMPSHIRE_FORMAT_LENGTH]; + char phys[32]; +}; + +static void hampshire_process_data(struct hampshire *phampshire) +{ + struct input_dev *dev = phampshire->dev; + + if (HAMPSHIRE_FORMAT_LENGTH == ++phampshire->idx) { + input_report_abs(dev, ABS_X, HAMPSHIRE_GET_XC(phampshire->data)); + input_report_abs(dev, ABS_Y, HAMPSHIRE_GET_YC(phampshire->data)); + input_report_key(dev, BTN_TOUCH, + HAMPSHIRE_GET_TOUCHED(phampshire->data)); + input_sync(dev); + + phampshire->idx = 0; + } +} + +static irqreturn_t hampshire_interrupt(struct serio *serio, + unsigned char data, unsigned int flags) +{ + struct hampshire *phampshire = serio_get_drvdata(serio); + + phampshire->data[phampshire->idx] = data; + + if (HAMPSHIRE_RESPONSE_BEGIN_BYTE & phampshire->data[0]) + hampshire_process_data(phampshire); + else + dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n", + phampshire->data[0]); + + return IRQ_HANDLED; +} + +static void hampshire_disconnect(struct serio *serio) +{ + struct hampshire *phampshire = serio_get_drvdata(serio); + + input_get_device(phampshire->dev); + input_unregister_device(phampshire->dev); + serio_close(serio); + serio_set_drvdata(serio, NULL); + input_put_device(phampshire->dev); + kfree(phampshire); +} + +/* + * hampshire_connect() is the routine that is called when someone adds a + * new serio device that supports hampshire protocol and registers it as + * an input device. This is usually accomplished using inputattach. + */ + +static int hampshire_connect(struct serio *serio, struct serio_driver *drv) +{ + struct hampshire *phampshire; + struct input_dev *input_dev; + int err; + + phampshire = kzalloc(sizeof(struct hampshire), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!phampshire || !input_dev) { + err = -ENOMEM; + goto fail1; + } + + phampshire->serio = serio; + phampshire->dev = input_dev; + snprintf(phampshire->phys, sizeof(phampshire->phys), + "%s/input0", serio->phys); + + input_dev->name = "Hampshire Serial TouchScreen"; + input_dev->phys = phampshire->phys; + input_dev->id.bustype = BUS_RS232; + input_dev->id.vendor = SERIO_HAMPSHIRE; + input_dev->id.product = 0; + input_dev->id.version = 0x0001; + input_dev->dev.parent = &serio->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(phampshire->dev, ABS_X, + HAMPSHIRE_MIN_XC, HAMPSHIRE_MAX_XC, 0, 0); + input_set_abs_params(phampshire->dev, ABS_Y, + HAMPSHIRE_MIN_YC, HAMPSHIRE_MAX_YC, 0, 0); + + serio_set_drvdata(serio, phampshire); + + err = serio_open(serio, drv); + if (err) + goto fail2; + + err = input_register_device(phampshire->dev); + if (err) + goto fail3; + + return 0; + + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); + kfree(phampshire); + return err; +} + +/* + * The serio driver structure. + */ + +static struct serio_device_id hampshire_serio_ids[] = { + { + .type = SERIO_RS232, + .proto = SERIO_HAMPSHIRE, + .id = SERIO_ANY, + .extra = SERIO_ANY, + }, + { 0 } +}; + +MODULE_DEVICE_TABLE(serio, hampshire_serio_ids); + +static struct serio_driver hampshire_drv = { + .driver = { + .name = "hampshire", + }, + .description = DRIVER_DESC, + .id_table = hampshire_serio_ids, + .interrupt = hampshire_interrupt, + .connect = hampshire_connect, + .disconnect = hampshire_disconnect, +}; + +/* + * The functions for inserting/removing us as a module. + */ + +static int __init hampshire_init(void) +{ + return serio_register_driver(&hampshire_drv); +} + +static void __exit hampshire_exit(void) +{ + serio_unregister_driver(&hampshire_drv); +} + +module_init(hampshire_init); +module_exit(hampshire_exit); diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 98a7d127948..ac5d0f9b0cb 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -37,9 +37,7 @@ #include <plat/adc.h> #include <plat/regs-adc.h> - -#include <mach/regs-gpio.h> -#include <mach/ts.h> +#include <plat/ts.h> #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) @@ -57,6 +55,8 @@ S3C2410_ADCTSC_AUTO_PST | \ S3C2410_ADCTSC_XY_PST(0)) +#define FEAT_PEN_IRQ (1 << 0) /* HAS ADCCLRINTPNDNUP */ + /* Per-touchscreen data. */ /** @@ -71,6 +71,7 @@ * @irq_tc: The interrupt number for pen up/down interrupt * @count: The number of samples collected. * @shift: The log2 of the maximum count to read in one go. + * @features: The features supported by the TSADC MOdule. */ struct s3c2410ts { struct s3c_adc_client *client; @@ -83,26 +84,12 @@ struct s3c2410ts { int irq_tc; int count; int shift; + int features; }; static struct s3c2410ts ts; /** - * s3c2410_ts_connect - configure gpio for s3c2410 systems - * - * Configure the GPIO for the S3C2410 system, where we have external FETs - * connected to the device (later systems such as the S3C2440 integrate - * these into the device). -*/ -static inline void s3c2410_ts_connect(void) -{ - s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON); - s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON); - s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON); - s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON); -} - -/** * get_down - return the down state of the pen * @data0: The data read from ADCDAT0 register. * @data1: The data read from ADCDAT1 register. @@ -188,6 +175,11 @@ static irqreturn_t stylus_irq(int irq, void *dev_id) else dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count); + if (ts.features & FEAT_PEN_IRQ) { + /* Clear pen down/up interrupt */ + writel(0x0, ts.io + S3C64XX_ADCCLRINTPNDNUP); + } + return IRQ_HANDLED; } @@ -296,9 +288,9 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) goto err_clk; } - /* Configure the touchscreen external FETs on the S3C2410 */ - if (!platform_get_device_id(pdev)->driver_data) - s3c2410_ts_connect(); + /* inititalise the gpio */ + if (info->cfg_gpio) + info->cfg_gpio(to_platform_device(ts.dev)); ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, s3c24xx_ts_conversion, 1); @@ -334,6 +326,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) ts.input->id.version = 0x0102; ts.shift = info->oversampling_shift; + ts.features = platform_get_device_id(pdev)->driver_data; ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, "s3c2410_ts_pen", ts.input); @@ -421,14 +414,15 @@ static struct dev_pm_ops s3c_ts_pmops = { static struct platform_device_id s3cts_driver_ids[] = { { "s3c2410-ts", 0 }, - { "s3c2440-ts", 1 }, + { "s3c2440-ts", 0 }, + { "s3c64xx-ts", FEAT_PEN_IRQ }, { } }; MODULE_DEVICE_TABLE(platform, s3cts_driver_ids); static struct platform_driver s3c_ts_driver = { .driver = { - .name = "s3c24xx-ts", + .name = "samsung-ts", .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &s3c_ts_pmops, diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c new file mode 100644 index 00000000000..5de80a1a730 --- /dev/null +++ b/drivers/input/touchscreen/tps6507x-ts.c @@ -0,0 +1,400 @@ +/* + * drivers/input/touchscreen/tps6507x_ts.c + * + * Touchscreen driver for the tps6507x chip. + * + * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com) + * + * Credits: + * + * Using code from tsc2007, MtekVision Co., Ltd. + * + * For licencing details see kernel-base/COPYING + * + * TPS65070, TPS65073, TPS650731, and TPS650732 support + * 10 bit touch screen interface. + */ + +#include <linux/module.h> +#include <linux/workqueue.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/mfd/tps6507x.h> +#include <linux/input/tps6507x-ts.h> +#include <linux/delay.h> + +#define TSC_DEFAULT_POLL_PERIOD 30 /* ms */ +#define TPS_DEFAULT_MIN_PRESSURE 0x30 +#define MAX_10BIT ((1 << 10) - 1) + +#define TPS6507X_ADCONFIG_CONVERT_TS (TPS6507X_ADCONFIG_AD_ENABLE | \ + TPS6507X_ADCONFIG_START_CONVERSION | \ + TPS6507X_ADCONFIG_INPUT_REAL_TSC) +#define TPS6507X_ADCONFIG_POWER_DOWN_TS (TPS6507X_ADCONFIG_INPUT_REAL_TSC) + +struct ts_event { + u16 x; + u16 y; + u16 pressure; +}; + +struct tps6507x_ts { + struct input_dev *input_dev; + struct device *dev; + char phys[32]; + struct workqueue_struct *wq; + struct delayed_work work; + unsigned polling; /* polling is active */ + struct ts_event tc; + struct tps6507x_dev *mfd; + u16 model; + unsigned pendown; + int irq; + void (*clear_penirq)(void); + unsigned long poll_period; /* ms */ + u16 min_pressure; + int vref; /* non-zero to leave vref on */ +}; + +static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data) +{ + int err; + + err = tsc->mfd->read_dev(tsc->mfd, reg, 1, data); + + if (err) + return err; + + return 0; +} + +static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data) +{ + return tsc->mfd->write_dev(tsc->mfd, reg, 1, &data); +} + +static s32 tps6507x_adc_conversion(struct tps6507x_ts *tsc, + u8 tsc_mode, u16 *value) +{ + s32 ret; + u8 adc_status; + u8 result; + + /* Route input signal to A/D converter */ + + ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, tsc_mode); + if (ret) { + dev_err(tsc->dev, "TSC mode read failed\n"); + goto err; + } + + /* Start A/D conversion */ + + ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG, + TPS6507X_ADCONFIG_CONVERT_TS); + if (ret) { + dev_err(tsc->dev, "ADC config write failed\n"); + return ret; + } + + do { + ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADCONFIG, + &adc_status); + if (ret) { + dev_err(tsc->dev, "ADC config read failed\n"); + goto err; + } + } while (adc_status & TPS6507X_ADCONFIG_START_CONVERSION); + + ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_2, &result); + if (ret) { + dev_err(tsc->dev, "ADC result 2 read failed\n"); + goto err; + } + + *value = (result & TPS6507X_REG_ADRESULT_2_MASK) << 8; + + ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_1, &result); + if (ret) { + dev_err(tsc->dev, "ADC result 1 read failed\n"); + goto err; + } + + *value |= result; + + dev_dbg(tsc->dev, "TSC channel %d = 0x%X\n", tsc_mode, *value); + +err: + return ret; +} + +/* Need to call tps6507x_adc_standby() after using A/D converter for the + * touch screen interrupt to work properly. + */ + +static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc) +{ + s32 ret; + s32 loops = 0; + u8 val; + + ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG, + TPS6507X_ADCONFIG_INPUT_TSC); + if (ret) + return ret; + + ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, + TPS6507X_TSCMODE_STANDBY); + if (ret) + return ret; + + ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val); + if (ret) + return ret; + + while (val & TPS6507X_REG_TSC_INT) { + mdelay(10); + ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val); + if (ret) + return ret; + loops++; + } + + return ret; +} + +static void tps6507x_ts_handler(struct work_struct *work) +{ + struct tps6507x_ts *tsc = container_of(work, + struct tps6507x_ts, work.work); + struct input_dev *input_dev = tsc->input_dev; + int pendown; + int schd; + int poll = 0; + s32 ret; + + ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE, + &tsc->tc.pressure); + if (ret) + goto done; + + pendown = tsc->tc.pressure > tsc->min_pressure; + + if (unlikely(!pendown && tsc->pendown)) { + dev_dbg(tsc->dev, "UP\n"); + input_report_key(input_dev, BTN_TOUCH, 0); + input_report_abs(input_dev, ABS_PRESSURE, 0); + input_sync(input_dev); + tsc->pendown = 0; + } + + if (pendown) { + + if (!tsc->pendown) { + dev_dbg(tsc->dev, "DOWN\n"); + input_report_key(input_dev, BTN_TOUCH, 1); + } else + dev_dbg(tsc->dev, "still down\n"); + + ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_X_POSITION, + &tsc->tc.x); + if (ret) + goto done; + + ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_Y_POSITION, + &tsc->tc.y); + if (ret) + goto done; + + input_report_abs(input_dev, ABS_X, tsc->tc.x); + input_report_abs(input_dev, ABS_Y, tsc->tc.y); + input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure); + input_sync(input_dev); + tsc->pendown = 1; + poll = 1; + } + +done: + /* always poll if not using interrupts */ + poll = 1; + + if (poll) { + schd = queue_delayed_work(tsc->wq, &tsc->work, + tsc->poll_period * HZ / 1000); + if (schd) + tsc->polling = 1; + else { + tsc->polling = 0; + dev_err(tsc->dev, "re-schedule failed"); + } + } else + tsc->polling = 0; + + ret = tps6507x_adc_standby(tsc); +} + +static int tps6507x_ts_probe(struct platform_device *pdev) +{ + int error; + struct tps6507x_ts *tsc; + struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); + struct touchscreen_init_data *init_data; + struct input_dev *input_dev; + struct tps6507x_board *tps_board; + int schd; + + /** + * tps_board points to pmic related constants + * coming from the board-evm file. + */ + + tps_board = (struct tps6507x_board *)tps6507x_dev->dev->platform_data; + + if (!tps_board) { + dev_err(tps6507x_dev->dev, + "Could not find tps6507x platform data\n"); + return -EIO; + } + + /** + * init_data points to array of regulator_init structures + * coming from the board-evm file. + */ + + init_data = tps_board->tps6507x_ts_init_data; + + tsc = kzalloc(sizeof(struct tps6507x_ts), GFP_KERNEL); + if (!tsc) { + dev_err(tps6507x_dev->dev, "failed to allocate driver data\n"); + error = -ENOMEM; + goto err0; + } + + tps6507x_dev->ts = tsc; + tsc->mfd = tps6507x_dev; + tsc->dev = tps6507x_dev->dev; + input_dev = input_allocate_device(); + if (!input_dev) { + dev_err(tsc->dev, "Failed to allocate input device.\n"); + error = -ENOMEM; + goto err1; + } + + 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, 0, MAX_10BIT, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0); + + input_dev->name = "TPS6507x Touchscreen"; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = tsc->dev; + + snprintf(tsc->phys, sizeof(tsc->phys), + "%s/input0", dev_name(tsc->dev)); + input_dev->phys = tsc->phys; + + dev_dbg(tsc->dev, "device: %s\n", input_dev->phys); + + input_set_drvdata(input_dev, tsc); + + tsc->input_dev = input_dev; + + INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler); + tsc->wq = create_workqueue("TPS6507x Touchscreen"); + + if (init_data) { + tsc->poll_period = init_data->poll_period; + tsc->vref = init_data->vref; + tsc->min_pressure = init_data->min_pressure; + input_dev->id.vendor = init_data->vendor; + input_dev->id.product = init_data->product; + input_dev->id.version = init_data->version; + } else { + tsc->poll_period = TSC_DEFAULT_POLL_PERIOD; + tsc->min_pressure = TPS_DEFAULT_MIN_PRESSURE; + } + + error = tps6507x_adc_standby(tsc); + if (error) + goto err2; + + error = input_register_device(input_dev); + if (error) + goto err2; + + schd = queue_delayed_work(tsc->wq, &tsc->work, + tsc->poll_period * HZ / 1000); + + if (schd) + tsc->polling = 1; + else { + tsc->polling = 0; + dev_err(tsc->dev, "schedule failed"); + goto err2; + } + + return 0; + +err2: + cancel_delayed_work(&tsc->work); + flush_workqueue(tsc->wq); + destroy_workqueue(tsc->wq); + tsc->wq = 0; + input_free_device(input_dev); +err1: + kfree(tsc); + tps6507x_dev->ts = NULL; +err0: + return error; +} + +static int __devexit tps6507x_ts_remove(struct platform_device *pdev) +{ + struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); + struct tps6507x_ts *tsc = tps6507x_dev->ts; + struct input_dev *input_dev = tsc->input_dev; + + if (!tsc) + return 0; + + cancel_delayed_work(&tsc->work); + flush_workqueue(tsc->wq); + destroy_workqueue(tsc->wq); + tsc->wq = 0; + + input_free_device(input_dev); + + tps6507x_dev->ts = NULL; + kfree(tsc); + + return 0; +} + +static struct platform_driver tps6507x_ts_driver = { + .driver = { + .name = "tps6507x-ts", + .owner = THIS_MODULE, + }, + .probe = tps6507x_ts_probe, + .remove = __devexit_p(tps6507x_ts_remove), +}; + +static int __init tps6507x_ts_init(void) +{ + return platform_driver_register(&tps6507x_ts_driver); +} +module_init(tps6507x_ts_init); + +static void __exit tps6507x_ts_exit(void) +{ + platform_driver_unregister(&tps6507x_ts_driver); +} +module_exit(tps6507x_ts_exit); + +MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>"); +MODULE_DESCRIPTION("TPS6507x - TouchScreen driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:tps6507x-tsc"); diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index be23780e8a3..769b479fcaa 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -347,6 +347,8 @@ static int __devexit tsc2007_remove(struct i2c_client *client) struct tsc2007 *ts = i2c_get_clientdata(client); struct tsc2007_platform_data *pdata = client->dev.platform_data; + i2c_set_clientdata(client, NULL); + tsc2007_free_irq(ts); if (pdata->exit_platform_hw) diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 99330bbdbac..567d57215c2 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -811,12 +811,11 @@ static int nexio_init(struct usbtouch_usb *usbtouch) priv = usbtouch->priv; - priv->ack_buf = kmalloc(sizeof(nexio_ack_pkt), GFP_KERNEL); + priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), + GFP_KERNEL); if (!priv->ack_buf) goto err_priv; - memcpy(priv->ack_buf, nexio_ack_pkt, sizeof(nexio_ack_pkt)); - priv->ack = usb_alloc_urb(0, GFP_KERNEL); if (!priv->ack) { dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); @@ -858,6 +857,11 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) if ((pkt[0] & 0xe0) != 0xe0) return 0; + if (be16_to_cpu(packet->data_len) > 0xff) + packet->data_len = cpu_to_be16(be16_to_cpu(packet->data_len) - 0x100); + if (be16_to_cpu(packet->x_len) > 0xff) + packet->x_len = cpu_to_be16(be16_to_cpu(packet->x_len) - 0x80); + /* send ACK */ ret = usb_submit_urb(priv->ack, GFP_ATOMIC); @@ -1113,7 +1117,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO [DEVTYPE_NEXIO] = { - .rept_size = 128, + .rept_size = 1024, .irq_always = true, .read_data = nexio_read_data, .init = nexio_init, @@ -1291,8 +1295,8 @@ static void usbtouch_close(struct input_dev *input) static void usbtouch_free_buffers(struct usb_device *udev, struct usbtouch_usb *usbtouch) { - usb_buffer_free(udev, usbtouch->type->rept_size, - usbtouch->data, usbtouch->data_dma); + usb_free_coherent(udev, usbtouch->type->rept_size, + usbtouch->data, usbtouch->data_dma); kfree(usbtouch->buffer); } @@ -1336,8 +1340,8 @@ static int usbtouch_probe(struct usb_interface *intf, if (!type->process_pkt) type->process_pkt = usbtouch_process_pkt; - usbtouch->data = usb_buffer_alloc(udev, type->rept_size, - GFP_KERNEL, &usbtouch->data_dma); + usbtouch->data = usb_alloc_coherent(udev, type->rept_size, + GFP_KERNEL, &usbtouch->data_dma); if (!usbtouch->data) goto out_free; diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 5109bf3dd85..cbfef1ea7e3 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -200,7 +200,7 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, mutex_lock(&wm->codec_mutex); reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS); - if (status & WM97XX_GPIO_HIGH) + if (status == WM97XX_GPIO_HIGH) reg |= gpio; else reg &= ~gpio; |