From 0bb239c1f3a6ea14c74b6e965d5280ba83c29115 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 24 May 2007 17:45:03 -0700 Subject: [PATCH] ARM: OMAP: 2430SDP: Use ads7846 for touchscreen driver Removes the tsc2046 specific driver, and changes the 2430SDP platform code to use the ads7846 instead. Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-2430sdp.c | 33 +- drivers/input/touchscreen/Kconfig | 6 - drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/tsc2046_ts.c | 564 ------------------------- include/linux/spi/tsc2046.h | 60 --- 5 files changed, 27 insertions(+), 637 deletions(-) delete mode 100644 drivers/input/touchscreen/tsc2046_ts.c delete mode 100644 include/linux/spi/tsc2046.h diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 99195ec286c..62dd083acc4 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -45,7 +45,10 @@ #define SDP2430_FLASH_CS 0 #define SDP2430_SMC91X_CS 5 -/* TSC2046 (touchscreen) */ +/* GPIO used for TSC2046 (touchscreen) + * + * Also note that the tsc2046 is the same silicon as the ads7846, so + * that driver is used for the touchscreen. */ #define TS_GPIO 24 static struct mtd_partition sdp2430_partitions[] = { @@ -182,9 +185,25 @@ static struct platform_device *sdp2430_devices[] __initdata = { &sdp2430_kp_device, }; -static struct tsc2046_platform_data tsc2046_config = { - .dav_gpio = TS_GPIO, - .gpio_debounce = 0xa, +static void ads7846_dev_init(void) +{ + if (omap_request_gpio(TS_GPIO) < 0) + printk(KERN_ERR "can't get ads746 pen down GPIO\n"); + + omap_set_gpio_direction(TS_GPIO, 1); + + omap_set_gpio_debounce(TS_GPIO, 1); + omap_set_gpio_debounce_time(TS_GPIO, 0xa); +} + +static int ads7846_get_pendown_state(void) +{ + return !omap_get_gpio_datain(TS_GPIO); +} + +static struct ads7846_platform_data tsc2046_config __initdata = { + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, }; static struct omap2_mcspi_device_config tsc2046_mcspi_config = { @@ -198,11 +217,12 @@ static struct spi_board_info sdp2430_spi_board_info[] __initdata = { * TSC2046 operates at a max freqency of 2MHz, so * operate slightly below at 1.5MHz */ - .modalias = "tsc2046", + .modalias = "ads7846", .bus_num = 1, .chip_select = 0, .max_speed_hz = 1500000, .controller_data = &tsc2046_mcspi_config, + .irq = OMAP_GPIO_IRQ(TS_GPIO), .platform_data = &tsc2046_config, }, }; @@ -367,6 +387,7 @@ static void __init omap_2430sdp_init(void) spi_register_board_info(sdp2430_spi_board_info, ARRAY_SIZE(sdp2430_spi_board_info)); + ads7846_dev_init(); } static void __init omap_2430sdp_map_io(void) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index fe6fc0de248..f52b93c06c3 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -185,12 +185,6 @@ config TOUCHSCREEN_TSC2301 help Say Y here for if you are using the touchscreen features of TSC2301. -config TOUCHSCREEN_TSC2046 - tristate "TSC2046 touchscreen support" - default MACH_OMAP2430SDP - help - Say Y here for if you are using the touchscreen features of TSC2046 - config TOUCHSCREEN_USB_COMPOSITE tristate "USB Touchscreen Driver" depends on USB_ARCH_HAS_HCD diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 5489b7ed4c7..1f7da1e3c70 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -20,4 +20,3 @@ obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o obj-$(CONFIG_TOUCHSCREEN_TSC2102) += tsc2102_ts.o obj-$(CONFIG_TOUCHSCREEN_OMAP) += omap/ obj-$(CONFIG_TOUCHSCREEN_TSC2301) += tsc2301_ts.o -obj-$(CONFIG_TOUCHSCREEN_TSC2046) += tsc2046_ts.o diff --git a/drivers/input/touchscreen/tsc2046_ts.c b/drivers/input/touchscreen/tsc2046_ts.c deleted file mode 100644 index 80aea9fa591..00000000000 --- a/drivers/input/touchscreen/tsc2046_ts.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - * TSC2046 Touchscreen driver - * - * Author: Kevin Hilman, MontaVista Software, Inc. - * - * Communication details from original TI driver - * Copyright (C) 2004-2005 Texas Instruments, Inc. - * - * Structure based heavily on TSC2301 driver - * Copyright (C) 2005-2006 Nokia Corporation - * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - * - */ - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_ARCH_OMAP -#include -#endif - -#include - -/* TSC2046 commands */ -#define START_BYTE 0x8000 -#define X_CMDWD 0xd300 -#define Y_CMDWD 0x9300 -#define Z1_CMDWD 0xb300 -#define Z2_CMDWD 0xc300 - -#define TSC2046_TS_SCAN_TIME 1 -#define MAX_12BIT ((1 << 12) - 1) - -struct tsc2046_ts { - struct input_dev *idev; - char phys[32]; - struct timer_list timer; - spinlock_t lock; - - struct spi_transfer read_xfer[3]; - struct spi_message read_msg; - struct spi_message enable_msg; - u16 data[5]; - - u16 x; - u16 y; - u16 p; - int sample_cnt; - - int ignore_last : 1; - u16 x_plate_ohm; - int max_pressure; - int touch_pressure; - int pressure_limit; - - u16 irq_enabled:1; - u16 pen_down:1; - u16 disabled:1; - u16 pending:1; - - s16 dav_gpio; - int irq; -}; - -static const u16 tsc2046_ts_cmd_data[] = { - START_BYTE, X_CMDWD, Y_CMDWD, Z1_CMDWD, Z2_CMDWD, -}; - -static int device_suspended(struct device *dev) -{ - struct tsc2046 *tsc = dev_get_drvdata(dev); - return dev->power.power_state.event != PM_EVENT_ON || tsc->ts->disabled; -} - -static void update_pen_state(struct tsc2046 *tsc, int x, int y, int pressure) -{ - struct tsc2046_ts *ts = tsc->ts; - int sync = 0; - - if (pressure) { - input_report_abs(ts->idev, ABS_X, x); - input_report_abs(ts->idev, ABS_Y, y); - input_report_abs(ts->idev, ABS_PRESSURE, pressure); - if (!ts->pen_down) - input_report_key(ts->idev, BTN_TOUCH, 1); - sync = 1; - } else if (ts->pen_down) { - input_report_abs(ts->idev, ABS_PRESSURE, 0); - input_report_key(ts->idev, BTN_TOUCH, 0); - sync = 1; - } - - if (sync) - input_sync(ts->idev); - - ts->pen_down = pressure ? 1 : 0; - -#ifdef VERBOSE - dev_dbg(&tsc->spi->dev, "x %4d y %4d p %4d\n", x, y, pressure); -#endif -} - -#define CONV_DATA(d1, d2) \ - (((d1 & 0x7f) << 5) | ((d2 >> 11) & 0x1f)) - -/* - * This procedure is called by the SPI framework after the coordinates - * have been read from TSC2046 - */ -static void tsc2046_ts_rx(void *arg) -{ - struct tsc2046 *tsc = arg; - struct tsc2046_ts *ts = tsc->ts; - unsigned int x, y, z1, z2, pressure; - - x = CONV_DATA(ts->data[2], ts->data[3]); - y = CONV_DATA(ts->data[1], ts->data[2]); - z1 = CONV_DATA(ts->data[3], ts->data[4]); - z2 = CONV_DATA(ts->data[4], 0); - - if (z1) { - pressure = ts->x_plate_ohm * x; - pressure /= 4096; - pressure *= z2 - z1; - pressure /= z1; - } else - pressure = 0; - - /* - * If pressure value is above a preset limit (pen is barely - * touching the screen) we can't trust the coordinate values. - */ - if (pressure < ts->pressure_limit && x < MAX_12BIT && y < MAX_12BIT) { - ts->pressure_limit = ts->max_pressure; - if (ts->ignore_last) { - if (ts->sample_cnt) - update_pen_state(tsc, ts->x, ts->y, ts->p); - ts->x = x; - ts->y = y; - ts->p = pressure; - } else - update_pen_state(tsc, x, y, pressure); - ts->sample_cnt++; - } - - mod_timer(&ts->timer, - jiffies + msecs_to_jiffies(TSC2046_TS_SCAN_TIME)); -} - -static int is_pen_down(struct tsc2046_ts *ts) -{ - return ts->pen_down; -} - -/* - * Timer is called every TSC2046_TS_SCAN_TIME when the pen is down - */ -static void tsc2046_ts_timer(unsigned long arg) -{ - struct tsc2046 *tsc = (void *) arg; - struct tsc2046_ts *ts = tsc->ts; - unsigned long flags; - int ndav; - int r; - - spin_lock_irqsave(&ts->lock, flags); - ndav = omap_get_gpio_datain(ts->dav_gpio); - if (ndav || device_suspended(&tsc->spi->dev)) { - /* Pen has been lifted */ - if (!device_suspended(&tsc->spi->dev) && - !ts->irq_enabled) { - ts->irq_enabled = 1; - enable_irq(ts->irq); - } - update_pen_state(tsc, 0, 0, 0); - ts->pending = 0; - spin_unlock_irqrestore(&ts->lock, flags); - - } else { - ts->pen_down = 1; - spin_unlock_irqrestore(&ts->lock, flags); - - r = spi_async(tsc->spi, &ts->read_msg); - if (r) - dev_err(&tsc->spi->dev, "ts: spi_async() failed"); - } -} - -/* - * This interrupt is called when pen is down and first coordinates are - * available. That is indicated by a falling edge on DEV line. IRQ is - * disabled here because while the pen is down the coordinates are - * read by a timer. - */ -static irqreturn_t tsc2046_ts_irq_handler(int irq, void *dev_id) -{ - struct tsc2046 *tsc = dev_id; - struct tsc2046_ts *ts = tsc->ts; - unsigned long flags; - - spin_lock_irqsave(&ts->lock, flags); - if (ts->irq_enabled) { - ts->irq_enabled = 0; - disable_irq(ts->irq); - ts->pending = 1; - ts->pressure_limit = ts->touch_pressure; - ts->sample_cnt = 0; - mod_timer(&ts->timer, - jiffies + msecs_to_jiffies(TSC2046_TS_SCAN_TIME)); - } - spin_unlock_irqrestore(&ts->lock, flags); - - return IRQ_HANDLED; -} - -/* Must be called with ts->lock held */ -static void tsc2046_ts_disable(struct tsc2046 *tsc) -{ - struct tsc2046_ts *ts = tsc->ts; - - if (ts->disabled) - return; - - ts->disabled = 1; - if (!ts->pending) { - ts->irq_enabled = 0; - disable_irq(ts->irq); - } else { - while (ts->pending) { - spin_unlock_irq(&ts->lock); - msleep(1); - spin_lock_irq(&ts->lock); - } - } -} - -static void tsc2046_ts_enable(struct tsc2046 *tsc) -{ - struct tsc2046_ts *ts = tsc->ts; - - if (!ts->disabled) - return; - - ts->disabled = 0; - ts->irq_enabled = 1; - enable_irq(ts->irq); -} - -#ifdef CONFIG_PM -static int tsc2046_suspend(struct spi_device *spi, pm_message_t mesg) -{ - struct tsc2046 *tsc = dev_get_drvdata(&spi->dev); - struct tsc2046_ts *ts = tsc->ts; - - spin_lock_irq(&ts->lock); - tsc2046_ts_disable(tsc); - spin_unlock_irq(&ts->lock); - - return 0; -} - -static int tsc2046_resume(struct spi_device *spi) -{ - struct tsc2046 *tsc = dev_get_drvdata(&spi->dev); - struct tsc2046_ts *ts = tsc->ts; - - spin_lock_irq(&ts->lock); - tsc2046_ts_enable(tsc); - spin_unlock_irq(&ts->lock); - - return 0; -} -#endif - -static void tsc2046_ts_setup_spi_xfer(struct tsc2046 *tsc) -{ - struct tsc2046_ts *ts = tsc->ts; - struct spi_message *m = &ts->read_msg; - struct spi_transfer *x = &ts->read_xfer[1]; - - spi_message_init(m); - - /* read and write data in one transaction */ - x->tx_buf = &tsc2046_ts_cmd_data; - x->rx_buf = &ts->data; - x->len = 10; - spi_message_add_tail(x, m); - - /* send another START_BYTE to (re)enable pen interrupts */ - x++; - x->tx_buf = &tsc2046_ts_cmd_data[0]; - x->len = 2; - spi_message_add_tail(x, m); - - m->complete = tsc2046_ts_rx; - m->context = tsc; -} - -static ssize_t tsc2046_ts_pen_down_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct tsc2046 *tsc = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", is_pen_down(tsc->ts)); -} - -static DEVICE_ATTR(pen_down, S_IRUGO, tsc2046_ts_pen_down_show, NULL); - -static ssize_t tsc2046_ts_disable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct tsc2046 *tsc = dev_get_drvdata(dev); - struct tsc2046_ts *ts = tsc->ts; - - return sprintf(buf, "%u\n", ts->disabled); -} - -static ssize_t tsc2046_ts_disable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct tsc2046 *tsc = dev_get_drvdata(dev); - struct tsc2046_ts *ts = tsc->ts; - char *endp; - int i; - - i = simple_strtoul(buf, &endp, 10); - spin_lock_irq(&ts->lock); - - if (i) - tsc2046_ts_disable(tsc); - else - tsc2046_ts_enable(tsc); - - spin_unlock_irq(&ts->lock); - - return count; -} - -static DEVICE_ATTR(disable_ts, 0664, tsc2046_ts_disable_show, - tsc2046_ts_disable_store); - -int __devinit tsc2046_ts_init(struct tsc2046 *tsc, - struct tsc2046_platform_data *pdata) -{ - struct tsc2046_ts *ts; - struct input_dev *idev; - int dav_gpio, r; - - if (pdata->dav_gpio < 0) { - dev_err(&tsc->spi->dev, "need DAV GPIO"); - return -EINVAL; - } - dav_gpio = pdata->dav_gpio; - - ts = kzalloc(sizeof(*ts), GFP_KERNEL); - if (ts == NULL) - return -ENOMEM; - tsc->ts = ts; - - ts->dav_gpio = dav_gpio; -#ifdef CONFIG_ARCH_OMAP - r = omap_request_gpio(dav_gpio); - if (r < 0) { - dev_err(&tsc->spi->dev, "unable to get DAV GPIO"); - goto err1; - } - omap_set_gpio_direction(dav_gpio, 1); - if (pdata->gpio_debounce) { - omap_set_gpio_debounce(tsc->gpio, 1); - omap_set_gpio_debounce_time(tsc->gpio, pdata->gpio_debounce); - } - - ts->irq = OMAP_GPIO_IRQ(dav_gpio); -#endif - setup_timer(&ts->timer, tsc2046_ts_timer, (unsigned long)tsc); - - spin_lock_init(&ts->lock); - - ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280; - ts->max_pressure = pdata->ts_max_pressure ? : MAX_12BIT; - ts->touch_pressure = pdata->ts_touch_pressure ? : ts->max_pressure; - ts->ignore_last = pdata->ts_ignore_last; - - idev = input_allocate_device(); - if (idev == NULL) { - r = -ENOMEM; - goto err2; - } - idev->name = "TSC2046 touchscreen"; - snprintf(ts->phys, sizeof(ts->phys), - "%s/input-ts", tsc->spi->dev.bus_id); - idev->phys = ts->phys; - - idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); - idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - ts->idev = idev; - - tsc2046_ts_setup_spi_xfer(tsc); - - /* These parameters should perhaps be configurable? */ - input_set_abs_params(idev, ABS_X, 0, 4096, 0, 0); - input_set_abs_params(idev, ABS_Y, 0, 4096, 0, 0); - input_set_abs_params(idev, ABS_PRESSURE, 0, 1024, 0, 0); - - ts->irq_enabled = 1; - r = request_irq(ts->irq, tsc2046_ts_irq_handler, - IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_FALLING, - "tsc2046-ts", tsc); - if (r < 0) { - dev_err(&tsc->spi->dev, "unable to get DAV IRQ"); - goto err3; - } - set_irq_wake(ts->irq, 1); - - if (device_create_file(&tsc->spi->dev, &dev_attr_pen_down) < 0) - goto err4; - if (device_create_file(&tsc->spi->dev, &dev_attr_disable_ts) < 0) - goto err5; - - r = input_register_device(idev); - if (r < 0) { - dev_err(&tsc->spi->dev, "can't register touchscreen device\n"); - goto err6; - } - - /* kick off a transaction to enable pen interrupts */ - spi_async(tsc->spi, &ts->read_msg); - - return 0; -err6: - device_remove_file(&tsc->spi->dev, &dev_attr_disable_ts); -err5: - device_remove_file(&tsc->spi->dev, &dev_attr_pen_down); -err4: - free_irq(ts->irq, tsc); -err3: - input_free_device(idev); -err2: -#ifdef CONFIG_ARCH_OMAP - omap_free_gpio(dav_gpio); -#endif -err1: - kfree(ts); - return r; -} -EXPORT_SYMBOL(tsc2046_ts_init); - -void __devexit tsc2046_ts_exit(struct tsc2046 *tsc) -{ - struct tsc2046_ts *ts = tsc->ts; - unsigned long flags; - - spin_lock_irqsave(&ts->lock, flags); - tsc2046_ts_disable(tsc); - spin_unlock_irqrestore(&ts->lock, flags); - - device_remove_file(&tsc->spi->dev, &dev_attr_disable_ts); - device_remove_file(&tsc->spi->dev, &dev_attr_pen_down); - - free_irq(ts->irq, tsc); - input_unregister_device(ts->idev); - -#ifdef CONFIG_ARCH_OMAP - omap_free_gpio(ts->dav_gpio); -#endif - kfree(ts); -} -EXPORT_SYMBOL(tsc2046_ts_exit); - - -static int __devinit tsc2046_probe(struct spi_device *spi) -{ - struct tsc2046 *tsc; - struct tsc2046_platform_data *pdata = spi->dev.platform_data; - int r = -ENODEV; - - dev_dbg(&spi->dev, "%s\n", __FUNCTION__); - - if (!pdata) { - dev_dbg(&spi->dev, "no platform data?\n"); - return -ENODEV; - } - - tsc = kzalloc(sizeof(*tsc), GFP_KERNEL); - if (tsc == NULL) - return -ENOMEM; - - dev_set_drvdata(&spi->dev, tsc); - tsc->spi = spi; - spi->dev.power.power_state = PMSG_ON; - - spi->mode = SPI_MODE_0; - spi->bits_per_word = 16; - - /* - * The max speed might've been defined by the board-specific - * struct - */ - if (!spi->max_speed_hz) - spi->max_speed_hz = TSC2046_HZ; - spi_setup(spi); - - r = tsc2046_ts_init(tsc, pdata); - if (r) - goto err1; - - return 0; -err1: - kfree(tsc); - return r; -} - -static int __devexit tsc2046_remove(struct spi_device *spi) -{ - struct tsc2046 *tsc = dev_get_drvdata(&spi->dev); - - dev_dbg(&tsc->spi->dev, "%s\n", __FUNCTION__); - - tsc2046_ts_exit(tsc); - kfree(tsc); - - return 0; -} - -static struct spi_driver tsc2046_driver = { - .driver = { - .name = "tsc2046", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = tsc2046_probe, - .remove = __devexit_p(tsc2046_remove), -#ifdef CONFIG_PM - .suspend = tsc2046_suspend, - .resume = tsc2046_resume, -#endif -}; - -static int __init tsc2046_init(void) -{ - printk("TSC2046 driver initializing\n"); - - return spi_register_driver(&tsc2046_driver); -} -module_init(tsc2046_init); - -static void __exit tsc2046_exit(void) -{ - spi_unregister_driver(&tsc2046_driver); -} -module_exit(tsc2046_exit); - -MODULE_AUTHOR("Kevin Hilman "); -MODULE_LICENSE("GPL"); diff --git a/include/linux/spi/tsc2046.h b/include/linux/spi/tsc2046.h deleted file mode 100644 index aca712f979e..00000000000 --- a/include/linux/spi/tsc2046.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _LINUX_SPI_TSC2046_H -#define _LINUX_SPI_TSC2046_H - -#include -#include - -struct tsc2046_platform_data { - s16 dav_gpio; - s16 gpio_debounce; - u16 ts_x_plate_ohm; - u32 ts_max_pressure; /* Samples with bigger pressure value will - be ignored, since the corresponding X, Y - values are unreliable */ - u32 ts_touch_pressure;/* Pressure limit until we report a - touch event. After that we switch - to ts_max_pressure. */ - unsigned ts_ignore_last : 1; - -}; - -struct tsc2046_ts; - -struct tsc2046 { - struct spi_device *spi; - int gpio; - - struct tsc2046_ts *ts; -}; - -/* The TSC2046 operates at a maximum speed of 2MHz */ -#define TSC2046_HZ 2000000 - -#define TSC2046_DECL_MOD(module) \ -extern int tsc2046_##module##_init(struct tsc2046 *tsc, \ - struct tsc2046_platform_data *pdata); \ -extern void tsc2046_##module##_exit(struct tsc2046 *tsc); \ -extern int tsc2046_##module##_suspend(struct tsc2046 *tsc); \ -extern void tsc2046_##module##_resume(struct tsc2046 *tsc); - -#define TSC2046_DECL_EMPTY_MOD(module) \ -static inline int tsc2046_##module##_init(struct tsc2046 *tsc, \ - struct tsc2046_platform_data *pdata) \ -{ \ - return 0; \ -} \ -static inline void tsc2046_##module##_exit(struct tsc2046 *tsc) {} \ -static inline int tsc2046_##module##_suspend(struct tsc2046 *tsc) \ -{ \ - return 0; \ -} \ -static inline void tsc2046_##module##_resume(struct tsc2046 *tsc) {} - -#if defined(CONFIG_TOUCHSCREEN_TSC2046) || \ - defined(CONFIG_TOUCHSCREEN_TSC2046_MODULE) -TSC2046_DECL_MOD(ts) -#else -TSC2046_DECL_EMPTY_MOD(ts) -#endif - -#endif -- 2.41.0