From: Felipe Balbi <felipe.balbi@xxxxxxxxx> Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx> --- drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/omap/Makefile | 10 + drivers/input/touchscreen/omap/omap_ts.c | 267 ++++++++++++++++++++++++++++++ drivers/input/touchscreen/omap/omap_ts.h | 57 +++++++ drivers/input/touchscreen/omap/ts_hx.c | 184 ++++++++++++++++++++ 5 files changed, 519 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/omap/Makefile create mode 100644 drivers/input/touchscreen/omap/omap_ts.c create mode 100644 drivers/input/touchscreen/omap/omap_ts.h create mode 100644 drivers/input/touchscreen/omap/ts_hx.c diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 0342389..e0bc8fb 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o +obj-$(CONFIG_TOUCHSCREEN_OMAP) += omap/ obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o diff --git a/drivers/input/touchscreen/omap/Makefile b/drivers/input/touchscreen/omap/Makefile new file mode 100644 index 0000000..af6344e --- /dev/null +++ b/drivers/input/touchscreen/omap/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the OMAP touchscreen input driver +# + +obj-$(CONFIG_TOUCHSCREEN_OMAP) += omapts.o + +objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H2) += ts_hx.o +objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H3) += ts_hx.o + +omapts-objs := omap_ts.o $(objs-yy) diff --git a/drivers/input/touchscreen/omap/omap_ts.c b/drivers/input/touchscreen/omap/omap_ts.c new file mode 100644 index 0000000..ee85755 --- /dev/null +++ b/drivers/input/touchscreen/omap/omap_ts.c @@ -0,0 +1,267 @@ +/* + * input/touchscreen/omap/omap_ts.c + * + * touchscreen input device driver for various TI OMAP boards + * Copyright (c) 2002 MontaVista Software Inc. + * Copyright (c) 2004 Texas Instruments, Inc. + * Cleanup and modularization 2004 by Dirk Behme <dirk.behme@xxxxxxxxxxxx> + * + * Assembled using driver code copyright the companies above. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * History: + * 12/12/2004 Srinath Modified and intergrated code for H2 and H3 + * + */ + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/init.h> +#include <linux/wait.h> +#include <linux/interrupt.h> +#include <linux/suspend.h> +#include <linux/platform_device.h> + +#include <asm/mach-types.h> + +//#define DEBUG + +#include "omap_ts.h" + +#define OMAP_TS_NAME "omap_ts" + +static struct ts_device *__initdata ts_devs[] = { +#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) + &hx_ts, +#endif +}; + +static struct omap_ts_t ts_omap; + +static int omap_ts_read(void) +{ + u16 data[4] = { 0, 0, 0, 0 }; + + ts_omap.dev->read(data); + + input_report_abs(ts_omap.inputdevice, ABS_X, data[0]); + input_report_abs(ts_omap.inputdevice, ABS_Y, data[1]); + input_report_abs(ts_omap.inputdevice, ABS_PRESSURE, data[2]); + input_sync(ts_omap.inputdevice); + + DEBUG_TS("omap_ts_read: read x=%d,y=%d,p=%d\n", data[0], data[1], + data[2]); + + return 0; +} + +static void omap_ts_timer(unsigned long data) +{ + unsigned long flags; + + spin_lock_irqsave(&ts_omap.lock, flags); + + if (!ts_omap.dev->penup()) { + if (!ts_omap.touched) { + DEBUG_TS("omap_ts_timer: pen down\n"); + input_report_key(ts_omap.inputdevice, BTN_TOUCH, 1); + } + ts_omap.touched = 1; + omap_ts_read(); + ts_omap.ts_timer.expires = jiffies + HZ / 100; + add_timer(&(ts_omap.ts_timer)); + } else { + if (ts_omap.touched) { + DEBUG_TS("omap_ts_timer: pen up\n"); + ts_omap.touched = 0; + input_report_abs(ts_omap.inputdevice, ABS_X, 0); + input_report_abs(ts_omap.inputdevice, ABS_Y, 0); + input_report_abs(ts_omap.inputdevice, ABS_PRESSURE, + 0); + input_sync(ts_omap.inputdevice); + input_report_key(ts_omap.inputdevice, BTN_TOUCH, 0); + } + if (!ts_omap.irq_enabled) { + ts_omap.irq_enabled = 1; + enable_irq(ts_omap.irq); + } + } + + spin_unlock_irqrestore(&ts_omap.lock, flags); +} + +static irqreturn_t omap_ts_handler(int irq, void *dev_id) +{ + spin_lock(&ts_omap.lock); + + if (ts_omap.irq_enabled) { + ts_omap.irq_enabled = 0; + disable_irq(irq); + } + // restart acquire + mod_timer(&ts_omap.ts_timer, jiffies + HZ / 100); + + spin_unlock(&ts_omap.lock); + + return IRQ_HANDLED; +} + +static int __init omap_ts_probe(struct platform_device *pdev) +{ + int i; + int status = -ENODEV; + + memset(&ts_omap, 0, sizeof(ts_omap)); + + ts_omap.inputdevice = input_allocate_device(); + if (!ts_omap.inputdevice) { + return -ENOMEM; + } + + spin_lock_init(&ts_omap.lock); + + for (i = 0; i < ARRAY_SIZE(ts_devs); i++) { + if (!ts_devs[i] || !ts_devs[i]->probe) + continue; + status = ts_devs[i]->probe(&ts_omap); + if (status == 0) { + ts_omap.dev = ts_devs[i]; + break; + } + } + + if (status != 0) { + input_free_device(ts_omap.inputdevice); + return status; + } + + // Init acquisition timer function + init_timer(&ts_omap.ts_timer); + ts_omap.ts_timer.function = omap_ts_timer; + + /* request irq */ + if (ts_omap.irq != -1) { + if (request_irq(ts_omap.irq, omap_ts_handler, + IRQF_SAMPLE_RANDOM | ts_omap.irq_type, + OMAP_TS_NAME, &ts_omap)) { + printk(KERN_ERR + "omap_ts.c: Could not allocate touchscreen IRQ!\n"); + ts_omap.irq = -1; + ts_omap.dev->remove(); + input_free_device(ts_omap.inputdevice); + return -EINVAL; + } + ts_omap.irq_enabled = 1; + } else { + printk(KERN_ERR "omap_ts.c: No touchscreen IRQ assigned!\n"); + ts_omap.dev->remove(); + input_free_device(ts_omap.inputdevice); + return -EINVAL; + } + + ts_omap.inputdevice->name = OMAP_TS_NAME; + ts_omap.inputdevice->dev = &pdev->dev; + ts_omap.inputdevice->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + ts_omap.inputdevice->keybit[BIT_WORD(BTN_TOUCH)] |= BIT(BTN_TOUCH); + ts_omap.inputdevice->absbit[0] = + BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); + input_register_device(ts_omap.inputdevice); + + ts_omap.dev->enable(); + + printk("OMAP touchscreen driver initialized\n"); + + return 0; +} + +static int omap_ts_remove(struct platform_device *pdev) +{ + ts_omap.dev->disable(); + input_unregister_device(ts_omap.inputdevice); + if (ts_omap.irq != -1) + free_irq(ts_omap.irq, &ts_omap); + + ts_omap.dev->remove(); + + return 0; +} + +static int omap_ts_suspend(struct platform_device *pdev, pm_message_t state) +{ + ts_omap.dev->disable(); + return 0; +} + +static int omap_ts_resume(struct platform_device *pdev) +{ + ts_omap.dev->enable(); + return 0; +} + +static void omap_ts_device_release(struct device *dev) +{ + /* Nothing */ +} +static struct platform_driver omap_ts_driver = { + .probe = omap_ts_probe, + .remove = omap_ts_remove, + .suspend = omap_ts_suspend, + .resume = omap_ts_resume, + .driver = { + .name = OMAP_TS_NAME, + }, +}; + +static struct platform_device omap_ts_device = { + .name = OMAP_TS_NAME, + .id = -1, + .dev = { + .release = omap_ts_device_release, + }, +}; + +static int __init omap_ts_init(void) +{ + int ret; + + if (machine_is_omap_osk() || machine_is_omap_innovator()) + return -ENODEV; + + ret = platform_device_register(&omap_ts_device); + if (ret != 0) + return -ENODEV; + + ret = platform_driver_register(&omap_ts_driver); + if (ret != 0) { + platform_device_unregister(&omap_ts_device); + return -ENODEV; + } + + return 0; +} + +static void __exit omap_ts_exit(void) +{ + platform_driver_unregister(&omap_ts_driver); + platform_device_unregister(&omap_ts_device); +} + +module_init(omap_ts_init); +module_exit(omap_ts_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/omap/omap_ts.h b/drivers/input/touchscreen/omap/omap_ts.h new file mode 100644 index 0000000..bef8e17 --- /dev/null +++ b/drivers/input/touchscreen/omap/omap_ts.h @@ -0,0 +1,57 @@ +/* + * omap_ts.h - header file for OMAP touchscreen support + * + * Copyright (c) 2002 MontaVista Software Inc. + * Copyright (c) 2004 Texas Instruments, Inc. + * + * Assembled using driver code copyright the companies above. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __OMAP_TS_H +#define __OMAP_TS_H + +#ifdef DEBUG +#define DEBUG_TS(fmt...) printk(fmt) +#else +#define DEBUG_TS(fmt...) do { } while (0) +#endif + +struct omap_ts_t; + +struct ts_device { + int (*probe) (struct omap_ts_t *); + void (*read) (u16 *); + void (*enable) (void); + void (*disable) (void); + void (*remove) (void); + int (*penup) (void); +}; + +struct omap_ts_t{ + struct input_dev * inputdevice; + struct timer_list ts_timer; // Timer for triggering acquisitions + int touched; + int irq; + int irq_type; + int irq_enabled; + struct ts_device *dev; + spinlock_t lock; +}; + +extern struct ts_device hx_ts; + +#endif /* __OMAP_TS_H */ diff --git a/drivers/input/touchscreen/omap/ts_hx.c b/drivers/input/touchscreen/omap/ts_hx.c new file mode 100644 index 0000000..9f82f5a --- /dev/null +++ b/drivers/input/touchscreen/omap/ts_hx.c @@ -0,0 +1,184 @@ +/* + * input/touchscreen/omap/ts_hx.c + * touchscreen support for OMAP H3 and H2 boards + * + * Copyright (c) 2002 MontaVista Software Inc. + * Copyright (c) 2004 Texas Instruments, Inc. + * + * Assembled using driver code copyright the companies above. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * History: + * 9/12/2004 Srinath Modified and integrated H2 and H3 code + * + */ + +#include <linux/input.h> +#include <linux/device.h> +#include <asm/mach-types.h> +#include <asm/arch/gpio.h> +#include <asm/arch/mux.h> +#include <asm/arch/hardware.h> +#include <asm/hardware/tsc2101.h> + +#include "../drivers/ssi/omap-tsc2101.h" +#include "omap_ts.h" + +#define H2_GPIO_NUM 4 +#define H3_GPIO_NUM 48 + +#define OMAP_TSC2101_XRES 500 +#define TOUCHSCREEN_DATA_REGISTERS_PAGE 0x0 +#define TOUCHSCREEN_CONTROL_REGISTERS_PAGE 0x1 +#define OMAP_TSC2101_READ_MAX 0x4 +#define TSC2101_GETSTATUS(ret) (((ret) >> 11) & 0x1) +#define TSC2101_MASKVAL 0xFFF +#define TSC2101_PRESSUREVAL(x) ((x) << 12) + +static int hx_ts_penup(void); +static int hx_ts_probe(struct omap_ts_t *ts); +static void hx_ts_read(u16 * data); +static void hx_ts_enable(void); +static void hx_ts_disable(void); +#ifdef MODULE +static void hx_ts_remove(void); +#endif + +struct ts_device hx_ts = { + .probe = hx_ts_probe, + .read = hx_ts_read, + .enable = hx_ts_enable, + .disable = hx_ts_disable, + .remove = __exit_p(hx_ts_remove), + .penup = hx_ts_penup, +}; + +static int hx_ts_penup(void) +{ + int ret = 0; + /* Read the status register */ + ret = omap_tsc2101_read(TOUCHSCREEN_CONTROL_REGISTERS_PAGE, + TSC2101_TS_STATUS); + /* Check for availability of data in status register */ + ret = TSC2101_GETSTATUS(ret); + return !ret; + +} + +static int __init hx_ts_probe(struct omap_ts_t *ts) +{ + unsigned gpio; + + if (machine_is_omap_h2()) { + gpio = H2_GPIO_NUM; + omap_cfg_reg(P20_1610_GPIO4); + } else if (machine_is_omap_h3()) { + gpio = H3_GPIO_NUM; + omap_cfg_reg(W19_1610_GPIO48); + } else + return -ENODEV; + + ts->irq = OMAP_GPIO_IRQ(gpio); + if (omap_request_gpio(gpio) != 0) { + printk(KERN_ERR "hX_ts_init.c: Could not reserve GPIO!\n"); + return -EINVAL; + }; + + omap_set_gpio_direction(gpio, 1); + ts->irq_type = IRQF_TRIGGER_FALLING; + return 0; +} + +static void hx_ts_read(u16 * values) +{ + s32 t, p = 0; + int i; + + /* Read X, Y, Z1 and Z2 */ + omap_tsc2101_reads(TOUCHSCREEN_DATA_REGISTERS_PAGE, TSC2101_TS_X, + values, OMAP_TSC2101_READ_MAX); + + for (i = 0; i < OMAP_TSC2101_READ_MAX; i++) + values[i] &= TSC2101_MASKVAL; + + /* Calculate Pressure */ + if (values[TSC2101_TS_Z1] != 0) { + t = ((OMAP_TSC2101_XRES * values[TSC2101_TS_X]) * + (values[TSC2101_TS_Z2] - values[TSC2101_TS_Z1])); + p = t / (u32) (TSC2101_PRESSUREVAL(values[TSC2101_TS_Z1])); + if (p < 0) + p = 0; + } + + values[TSC2101_TS_Z1] = p; +} + +static void hx_ts_enable(void) +{ + int ret = omap_tsc2101_enable(); + if (ret) { + printk(KERN_ERR "FAILED TO INITIALIZE TSC CODEC\n"); + return; + } + + /* PINTDAV is data available only */ + omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE, + TSC2101_TS_STATUS, TSC2101_DATA_AVAILABLE); + /* disable buffer mode */ + omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE, + TSC2101_TS_BUFFER_CTRL, TSC2101_BUFFERMODE_DISABLE); + /* use internal reference, 100 usec power-up delay, + * * power down between conversions, 1.25V internal reference */ + omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE, + TSC2101_TS_REF_CTRL, TSC2101_REF_POWERUP); + /* enable touch detection, 84usec precharge time, 32 usec sense time */ + omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE, + TSC2101_TS_CONFIG_CTRL, TSC2101_ENABLE_TOUCHDETECT); + /* 3 msec conversion delays */ + omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE, + TSC2101_TS_PROG_DELAY, TSC2101_PRG_DELAY); + /* + * TSC2101-controlled conversions + * 12-bit samples + * continuous X,Y,Z1,Z2 scan mode + * average (mean) 4 samples per coordinate + * 1 MHz internal conversion clock + * 500 usec panel voltage stabilization delay + */ + omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE, + TSC2101_TS_ADC_CTRL, TSC2101_ADC_CONTROL); + + return; + +} + +static void hx_ts_disable(void) +{ + /* stop conversions and power down */ + omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE, + TSC2101_TS_ADC_CTRL, TSC2101_ADC_POWERDOWN); + omap_tsc2101_disable(); +} + +#ifdef MODULE +static void __exit hx_ts_remove(void) +{ + if (machine_is_omap_h2()) + omap_free_gpio(H2_GPIO_NUM); + else if (machine_is_omap_h3()) + omap_free_gpio(H3_GPIO_NUM); +} +#endif -- 1.6.0.1.141.g445ca -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html