diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 10:55:52 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 10:55:52 -0800 |
| commit | dbe950f201a8edd353b0bd9079e8d536ee4ce37c (patch) | |
| tree | dffbada6b3d33cc67383758570de22b4f45693b6 /drivers/input/touchscreen | |
| parent | f62f61917d72c1fb0101ad405664f6fc868d676b (diff) | |
| parent | da733563be5a9da26fe81d9f007262d00b846e22 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (64 commits)
Input: tc3589x-keypad - add missing kerneldoc
Input: ucb1400-ts - switch to using dev_xxx() for diagnostic messages
Input: ucb1400_ts - convert to threaded IRQ
Input: ucb1400_ts - drop inline annotations
Input: usb1400_ts - add __devinit/__devexit section annotations
Input: ucb1400_ts - set driver owner
Input: ucb1400_ts - convert to use dev_pm_ops
Input: psmouse - make sure we do not use stale methods
Input: evdev - do not block waiting for an event if fd is nonblock
Input: evdev - if no events and non-block, return EAGAIN not 0
Input: evdev - only allow reading events if a full packet is present
Input: add driver for pixcir i2c touchscreens
Input: samsung-keypad - implement runtime power management support
Input: tegra-kbc - report wakeup key for some platforms
Input: tegra-kbc - add device tree bindings
Input: add driver for AUO In-Cell touchscreens using pixcir ICs
Input: mpu3050 - configure the sampling method
Input: mpu3050 - ensure we enable interrupts
Input: mpu3050 - add of_match table for device-tree probing
Input: sentelic - document the latest hardware
...
Fix up fairly trivial conflicts (device tree matching conflicting with
some independent cleanups) in drivers/input/keyboard/samsung-keypad.c
Diffstat (limited to 'drivers/input/touchscreen')
32 files changed, 1508 insertions, 520 deletions
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index b3aebc2166ba..05f30b73c3c3 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -217,18 +217,7 @@ static struct platform_driver pm860x_touch_driver = { .probe = pm860x_touch_probe, .remove = __devexit_p(pm860x_touch_remove), }; - -static int __init pm860x_touch_init(void) -{ - return platform_driver_register(&pm860x_touch_driver); -} -module_init(pm860x_touch_init); - -static void __exit pm860x_touch_exit(void) -{ - platform_driver_unregister(&pm860x_touch_driver); -} -module_exit(pm860x_touch_exit); +module_platform_driver(pm860x_touch_driver); MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x"); MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 3488ffe1fa0a..4af2a18eb3ba 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -98,6 +98,19 @@ config TOUCHSCREEN_ATMEL_MXT To compile this driver as a module, choose M here: the module will be called atmel_mxt_ts. +config TOUCHSCREEN_AUO_PIXCIR + tristate "AUO in-cell touchscreen using Pixcir ICs" + depends on I2C + depends on GPIOLIB + help + Say Y here if you have a AUO display with in-cell touchscreen + using Pixcir ICs. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called auo-pixcir-ts. + config TOUCHSCREEN_BITSY tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" depends on SA1100_BITSY @@ -177,6 +190,16 @@ config TOUCHSCREEN_EETI To compile this driver as a module, choose M here: the module will be called eeti_ts. +config TOUCHSCREEN_EGALAX + tristate "EETI eGalax multi-touch panel support" + depends on I2C + help + Say Y here to enable support for I2C connected EETI + eGalax multi-touch panels. + + To compile this driver as a module, choose M here: the + module will be called egalax_ts. + config TOUCHSCREEN_FUJITSU tristate "Fujitsu serial touchscreen" select SERIO @@ -435,6 +458,18 @@ config TOUCHSCREEN_UCB1400 To compile this driver as a module, choose M here: the module will be called ucb1400_ts. +config TOUCHSCREEN_PIXCIR + tristate "PIXCIR I2C touchscreens" + depends on I2C + help + Say Y here if you have a pixcir i2c touchscreen + controller. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called pixcir_i2c_ts. + config TOUCHSCREEN_WM831X tristate "Support for WM831x touchscreen controllers" depends on MFD_WM831X @@ -541,6 +576,7 @@ config TOUCHSCREEN_USB_COMPOSITE - GoTop Super_Q2/GogoPen/PenPower tablets - JASTEC USB Touch Controller/DigiTech DTR-02U - Zytronic controllers + - Elo TouchSystems 2700 IntelliTouch Have a look at <http://linux.chapter7.ch/touchkit/> for a usage description and the required user-space stuff. @@ -620,6 +656,11 @@ config TOUCHSCREEN_USB_JASTEC bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EXPERT depends on TOUCHSCREEN_USB_COMPOSITE +config TOUCHSCREEN_USB_ELO + default y + bool "Elo TouchSystems 2700 IntelliTouch controller device support" if EXPERT + depends on TOUCHSCREEN_USB_COMPOSITE + config TOUCHSCREEN_USB_E2I default y bool "e2i Touchscreen controller (e.g. from Mimo 740)" diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index f957676035a4..496091e88460 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o +obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o @@ -23,6 +24,7 @@ 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 +obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o @@ -39,6 +41,7 @@ obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o +obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index baa43df6502d..49a36df0b752 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -488,10 +488,10 @@ static ssize_t ad7877_disable_store(struct device *dev, const char *buf, size_t count) { struct ad7877 *ts = dev_get_drvdata(dev); - unsigned long val; + unsigned int val; int error; - error = strict_strtoul(buf, 10, &val); + error = kstrtouint(buf, 10, &val); if (error) return error; @@ -518,10 +518,10 @@ static ssize_t ad7877_dac_store(struct device *dev, const char *buf, size_t count) { struct ad7877 *ts = dev_get_drvdata(dev); - unsigned long val; + unsigned int val; int error; - error = strict_strtoul(buf, 10, &val); + error = kstrtouint(buf, 10, &val); if (error) return error; @@ -548,10 +548,10 @@ static ssize_t ad7877_gpio3_store(struct device *dev, const char *buf, size_t count) { struct ad7877 *ts = dev_get_drvdata(dev); - unsigned long val; + unsigned int val; int error; - error = strict_strtoul(buf, 10, &val); + error = kstrtouint(buf, 10, &val); if (error) return error; @@ -579,10 +579,10 @@ static ssize_t ad7877_gpio4_store(struct device *dev, const char *buf, size_t count) { struct ad7877 *ts = dev_get_drvdata(dev); - unsigned long val; + unsigned int val; int error; - error = strict_strtoul(buf, 10, &val); + error = kstrtouint(buf, 10, &val); if (error) return error; @@ -853,7 +853,6 @@ static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume); static struct spi_driver ad7877_driver = { .driver = { .name = "ad7877", - .bus = &spi_bus_type, .owner = THIS_MODULE, .pm = &ad7877_pm, }, diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index c789b974c795..0dac6712f42b 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c @@ -16,30 +16,6 @@ #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ -#ifdef CONFIG_PM_SLEEP -static int ad7879_i2c_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ad7879 *ts = i2c_get_clientdata(client); - - ad7879_suspend(ts); - - return 0; -} - -static int ad7879_i2c_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ad7879 *ts = i2c_get_clientdata(client); - - ad7879_resume(ts); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume); - /* All registers are word-sized. * AD7879 uses a high-byte first convention. */ @@ -47,7 +23,7 @@ static int ad7879_i2c_read(struct device *dev, u8 reg) { struct i2c_client *client = to_i2c_client(dev); - return swab16(i2c_smbus_read_word_data(client, reg)); + return i2c_smbus_read_word_swapped(client, reg); } static int ad7879_i2c_multi_read(struct device *dev, @@ -68,7 +44,7 @@ static int ad7879_i2c_write(struct device *dev, u8 reg, u16 val) { struct i2c_client *client = to_i2c_client(dev); - return i2c_smbus_write_word_data(client, reg, swab16(val)); + return i2c_smbus_write_word_swapped(client, reg, val); } static const struct ad7879_bus_ops ad7879_i2c_bus_ops = { @@ -119,7 +95,7 @@ static struct i2c_driver ad7879_i2c_driver = { .driver = { .name = "ad7879", .owner = THIS_MODULE, - .pm = &ad7879_i2c_pm, + .pm = &ad7879_pm_ops, }, .probe = ad7879_i2c_probe, .remove = __devexit_p(ad7879_i2c_remove), @@ -141,4 +117,3 @@ module_exit(ad7879_i2c_exit); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("i2c:ad7879"); diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index b1643c8fa7c9..9b2e1c2b1971 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c @@ -22,30 +22,6 @@ #define AD7879_WRITECMD(reg) (AD7879_CMD(reg)) #define AD7879_READCMD(reg) (AD7879_CMD(reg) | AD7879_CMD_READ) -#ifdef CONFIG_PM_SLEEP -static int ad7879_spi_suspend(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - struct ad7879 *ts = spi_get_drvdata(spi); - - ad7879_suspend(ts); - - return 0; -} - -static int ad7879_spi_resume(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - struct ad7879 *ts = spi_get_drvdata(spi); - - ad7879_resume(ts); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(ad7879_spi_pm, ad7879_spi_suspend, ad7879_spi_resume); - /* * ad7879_read/write are only used for initial setup and for sysfs controls. * The main traffic is done in ad7879_collect(). @@ -174,9 +150,8 @@ static int __devexit ad7879_spi_remove(struct spi_device *spi) static struct spi_driver ad7879_spi_driver = { .driver = { .name = "ad7879", - .bus = &spi_bus_type, .owner = THIS_MODULE, - .pm = &ad7879_spi_pm, + .pm = &ad7879_pm_ops, }, .probe = ad7879_spi_probe, .remove = __devexit_p(ad7879_spi_remove), diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 3b2e9ed2aeec..e2482b40da51 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -281,8 +281,11 @@ static void ad7879_close(struct input_dev* input) __ad7879_disable(ts); } -void ad7879_suspend(struct ad7879 *ts) +#ifdef CONFIG_PM_SLEEP +static int ad7879_suspend(struct device *dev) { + struct ad7879 *ts = dev_get_drvdata(dev); + mutex_lock(&ts->input->mutex); if (!ts->suspended && !ts->disabled && ts->input->users) @@ -291,11 +294,14 @@ void ad7879_suspend(struct ad7879 *ts) ts->suspended = true; mutex_unlock(&ts->input->mutex); + + return 0; } -EXPORT_SYMBOL(ad7879_suspend); -void ad7879_resume(struct ad7879 *ts) +static int ad7879_resume(struct device *dev) { + struct ad7879 *ts = dev_get_drvdata(dev); + mutex_lock(&ts->input->mutex); if (ts->suspended && !ts->disabled && ts->input->users) @@ -304,8 +310,13 @@ void ad7879_resume(struct ad7879 *ts) ts->suspended = false; mutex_unlock(&ts->input->mutex); + + return 0; } -EXPORT_SYMBOL(ad7879_resume); +#endif + +SIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume); +EXPORT_SYMBOL(ad7879_pm_ops); static void ad7879_toggle(struct ad7879 *ts, bool disable) { @@ -340,10 +351,10 @@ static ssize_t ad7879_disable_store(struct device *dev, const char *buf, size_t count) { struct ad7879 *ts = dev_get_drvdata(dev); - unsigned long val; + unsigned int val; int error; - error = strict_strtoul(buf, 10, &val); + error = kstrtouint(buf, 10, &val); if (error) return error; diff --git a/drivers/input/touchscreen/ad7879.h b/drivers/input/touchscreen/ad7879.h index 6b45a27236c7..6fd13c48d373 100644 --- a/drivers/input/touchscreen/ad7879.h +++ b/drivers/input/touchscreen/ad7879.h @@ -21,8 +21,8 @@ struct ad7879_bus_ops { int (*write)(struct device *dev, u8 reg, u16 val); }; -void ad7879_suspend(struct ad7879 *); -void ad7879_resume(struct ad7879 *); +extern const struct dev_pm_ops ad7879_pm_ops; + struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq, const struct ad7879_bus_ops *bops); void ad7879_remove(struct ad7879 *); diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index de31ec6fe9e4..23fd90185659 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -602,10 +602,12 @@ static ssize_t ads7846_disable_store(struct device *dev, const char *buf, size_t count) { struct ads7846 *ts = dev_get_drvdata(dev); - unsigned long i; + unsigned int i; + int err; - if (strict_strtoul(buf, 10, &i)) - return -EINVAL; + err = kstrtouint(buf, 10, &i); + if (err) + return err; if (i) ads7846_disable(ts); @@ -1424,7 +1426,6 @@ static int __devexit ads7846_remove(struct spi_device *spi) static struct spi_driver ads7846_driver = { .driver = { .name = "ads7846", - .bus = &spi_bus_type, .owner = THIS_MODULE, .pm = &ads7846_pm, }, diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index 8034cbb20f74..d016cb26d125 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c @@ -429,18 +429,7 @@ static struct platform_driver atmel_wm97xx_driver = { .suspend = atmel_wm97xx_suspend, .resume = atmel_wm97xx_resume, }; - -static int __init atmel_wm97xx_init(void) -{ - return platform_driver_probe(&atmel_wm97xx_driver, atmel_wm97xx_probe); -} -module_init(atmel_wm97xx_init); - -static void __exit atmel_wm97xx_exit(void) -{ - platform_driver_unregister(&atmel_wm97xx_driver); -} -module_exit(atmel_wm97xx_exit); +module_platform_driver(atmel_wm97xx_driver); MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32"); diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 122a87883659..201b2d2ec1b3 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -351,20 +351,7 @@ static struct platform_driver atmel_tsadcc_driver = { .name = "atmel_tsadcc", }, }; - -static int __init atmel_tsadcc_init(void) -{ - return platform_driver_register(&atmel_tsadcc_driver); -} - -static void __exit atmel_tsadcc_exit(void) -{ - platform_driver_unregister(&atmel_tsadcc_driver); -} - -module_init(atmel_tsadcc_init); -module_exit(atmel_tsadcc_exit); - +module_platform_driver(atmel_tsadcc_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Atmel TouchScreen Driver"); diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c new file mode 100644 index 000000000000..94fb9fbb08a9 --- /dev/null +++ b/drivers/input/touchscreen/auo-pixcir-ts.c @@ -0,0 +1,652 @@ +/* + * Driver for AUO in-cell touchscreens + * + * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de> + * + * loosely based on auo_touch.c from Dell Streak vendor-kernel + * + * Copyright (c) 2008 QUALCOMM Incorporated. + * Copyright (c) 2008 QUALCOMM USA, INC. + * + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/jiffies.h> +#include <linux/i2c.h> +#include <linux/mutex.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/input/auo-pixcir-ts.h> + +/* + * Coordinate calculation: + * X1 = X1_LSB + X1_MSB*256 + * Y1 = Y1_LSB + Y1_MSB*256 + * X2 = X2_LSB + X2_MSB*256 + * Y2 = Y2_LSB + Y2_MSB*256 + */ +#define AUO_PIXCIR_REG_X1_LSB 0x00 +#define AUO_PIXCIR_REG_X1_MSB 0x01 +#define AUO_PIXCIR_REG_Y1_LSB 0x02 +#define AUO_PIXCIR_REG_Y1_MSB 0x03 +#define AUO_PIXCIR_REG_X2_LSB 0x04 +#define AUO_PIXCIR_REG_X2_MSB 0x05 +#define AUO_PIXCIR_REG_Y2_LSB 0x06 +#define AUO_PIXCIR_REG_Y2_MSB 0x07 + +#define AUO_PIXCIR_REG_STRENGTH 0x0d +#define AUO_PIXCIR_REG_STRENGTH_X1_LSB 0x0e +#define AUO_PIXCIR_REG_STRENGTH_X1_MSB 0x0f + +#define AUO_PIXCIR_REG_RAW_DATA_X 0x2b +#define AUO_PIXCIR_REG_RAW_DATA_Y 0x4f + +#define AUO_PIXCIR_REG_X_SENSITIVITY 0x6f +#define AUO_PIXCIR_REG_Y_SENSITIVITY 0x70 +#define AUO_PIXCIR_REG_INT_SETTING 0x71 +#define AUO_PIXCIR_REG_INT_WIDTH 0x72 +#define AUO_PIXCIR_REG_POWER_MODE 0x73 + +#define AUO_PIXCIR_REG_VERSION 0x77 +#define AUO_PIXCIR_REG_CALIBRATE 0x78 + +#define AUO_PIXCIR_REG_TOUCHAREA_X1 0x1e +#define AUO_PIXCIR_REG_TOUCHAREA_Y1 0x1f +#define AUO_PIXCIR_REG_TOUCHAREA_X2 0x20 +#define AUO_PIXCIR_REG_TOUCHAREA_Y2 0x21 + +#define AUO_PIXCIR_REG_EEPROM_CALIB_X 0x42 +#define AUO_PIXCIR_REG_EEPROM_CALIB_Y 0xad + +#define AUO_PIXCIR_INT_TPNUM_MASK 0xe0 +#define AUO_PIXCIR_INT_TPNUM_SHIFT 5 +#define AUO_PIXCIR_INT_RELEASE (1 << 4) +#define AUO_PIXCIR_INT_ENABLE (1 << 3) +#define AUO_PIXCIR_INT_POL_HIGH (1 << 2) +#define AUO_PIXCIR_INT_MODE_MASK 0x03 + +/* + * Power modes: + * active: scan speed 60Hz + * sleep: scan speed 10Hz can be auto-activated, wakeup on 1st touch + * deep sleep: scan speed 1Hz can only be entered or left manually. + */ +#define AUO_PIXCIR_POWER_ACTIVE 0x00 +#define AUO_PIXCIR_POWER_SLEEP 0x01 +#define AUO_PIXCIR_POWER_DEEP_SLEEP 0x02 +#define AUO_PIXCIR_POWER_MASK 0x03 + +#define AUO_PIXCIR_POWER_ALLOW_SLEEP (1 << 2) +#define AUO_PIXCIR_POWER_IDLE_TIME(ms) ((ms & 0xf) << 4) + +#define AUO_PIXCIR_CALIBRATE 0x03 + +#define AUO_PIXCIR_EEPROM_CALIB_X_LEN 62 +#define AUO_PIXCIR_EEPROM_CALIB_Y_LEN 36 + +#define AUO_PIXCIR_RAW_DATA_X_LEN 18 +#define AUO_PIXCIR_RAW_DATA_Y_LEN 11 + +#define AUO_PIXCIR_STRENGTH_ENABLE (1 << 0) + +/* Touchscreen absolute values */ +#define AUO_PIXCIR_REPORT_POINTS 2 +#define AUO_PIXCIR_MAX_AREA 0xff +#define AUO_PIXCIR_PENUP_TIMEOUT_MS 10 + +struct auo_pixcir_ts { + struct i2c_client *client; + struct input_dev *input; + char phys[32]; + + /* special handling for touch_indicate interupt mode */ + bool touch_ind_mode; + + wait_queue_head_t wait; + bool stopped; +}; + +struct auo_point_t { + int coord_x; + int coord_y; + int area_major; + int area_minor; + int orientation; +}; + +static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts, + struct auo_point_t *point) +{ + struct i2c_client *client = ts->client; + const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; + uint8_t raw_coord[8]; + uint8_t raw_area[4]; + int i, ret; + + /* touch coordinates */ + ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_X1_LSB, + 8, raw_coord); + if (ret < 0) { + dev_err(&client->dev, "failed to read coordinate, %d\n", ret); + return ret; + } + + /* touch area */ + ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_TOUCHAREA_X1, + 4, raw_area); + if (ret < 0) { + dev_err(&client->dev, "could not read touch area, %d\n", ret); + return ret; + } + + for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) { + point[i].coord_x = + raw_coord[4 * i + 1] << 8 | raw_coord[4 * i]; + point[i].coord_y = + raw_coord[4 * i + 3] << 8 | raw_coord[4 * i + 2]; + + if (point[i].coord_x > pdata->x_max || + point[i].coord_y > pdata->y_max) { + dev_warn(&client->dev, "coordinates (%d,%d) invalid\n", + point[i].coord_x, point[i].coord_y); + point[i].coord_x = point[i].coord_y = 0; + } + + /* determine touch major, minor and orientation */ + point[i].area_major = max(raw_area[2 * i], raw_area[2 * i + 1]); + point[i].area_minor = min(raw_area[2 * i], raw_area[2 * i + 1]); + point[i].orientation = raw_area[2 * i] > raw_area[2 * i + 1]; + } + + return 0; +} + +static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id) +{ + struct auo_pixcir_ts *ts = dev_id; + struct i2c_client *client = ts->client; + const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; + struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS]; + int i; + int ret; + int fingers = 0; + int abs = -1; + + while (!ts->stopped) { + + /* check for up event in touch touch_ind_mode */ + if (ts->touch_ind_mode) { + if (gpio_get_value(pdata->gpio_int) == 0) { + input_mt_sync(ts->input); + input_report_key(ts->input, BTN_TOUCH, 0); + input_sync(ts->input); + break; + } + } + + ret = auo_pixcir_collect_data(ts, point); + if (ret < 0) { + /* we want to loop only in touch_ind_mode */ + if (!ts->touch_ind_mode) + break; + + wait_event_timeout(ts->wait, ts->stopped, + msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS)); + continue; + } + + for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) { + if (point[i].coord_x > 0 || point[i].coord_y > 0) { + input_report_abs(ts->input, ABS_MT_POSITION_X, + point[i].coord_x); + input_report_abs(ts->input, ABS_MT_POSITION_Y, + point[i].coord_y); + input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, + point[i].area_major); + input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, + point[i].area_minor); + input_report_abs(ts->input, ABS_MT_ORIENTATION, + point[i].orientation); + input_mt_sync(ts->input); + + /* use first finger as source for singletouch */ + if (fingers == 0) + abs = i; + + /* number of touch points could also be queried + * via i2c but would require an additional call + */ + fingers++; + } + } + + input_report_key(ts->input, BTN_TOUCH, fingers > 0); + + if (abs > -1) { + input_report_abs(ts->input, ABS_X, point[abs].coord_x); + input_report_abs(ts->input, ABS_Y, point[abs].coord_y); + } + + input_sync(ts->input); + + /* we want to loop only in touch_ind_mode */ + if (!ts->touch_ind_mode) + break; + + wait_event_timeout(ts->wait, ts->stopped, + msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS)); + } + + return IRQ_HANDLED; +} + +/* + * Set the power mode of the device. + * Valid modes are + * - AUO_PIXCIR_POWER_ACTIVE + * - AUO_PIXCIR_POWER_SLEEP - automatically left on first touch + * - AUO_PIXCIR_POWER_DEEP_SLEEP + */ +static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode) +{ + struct i2c_client *client = ts->client; + int ret; + + ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_POWER_MODE); + if (ret < 0) { + dev_err(&client->dev, "unable to read reg %Xh, %d\n", + AUO_PIXCIR_REG_POWER_MODE, ret); + return ret; + } + + ret &= ~AUO_PIXCIR_POWER_MASK; + ret |= mode; + + ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_POWER_MODE, ret); + if (ret) { + dev_err(&client->dev, "unable to write reg %Xh, %d\n", + AUO_PIXCIR_REG_POWER_MODE, ret); + return ret; + } + + return 0; +} + +static __devinit int auo_pixcir_int_con |
