Driver for AUO In-Cell touchscreens using pixcir ICs
Subsystems (2)
PATCH v2 1/1 Driver for AUO In-Cell touchscreens using pixcir ICs
Some displays from AUO have a so called in-cell touchscreen, meaning it is built directly into the display unit.
Touchdata is gathered through PIXCIR Tango-ICs and processed in an Atmel ATmega168P with custom firmware. Communication between the host system and ATmega is done via I2C.
Devices using this touch solution include the Dell Streak5 and the family of Qisda ebook readers.
The driver reports single- and multi-touch events including touch area values.
---
changes since v1: address comments from Christoph Fritz (wrong type for error checks, wrong call to input_free_device)
drivers/input/touchscreen/Kconfig | 14 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/auo-pixcir-ts.c | 656 +++++++++++++++++++++++++++++ include/linux/input/auo-pixcir-ts.h | 57 +++ 4 files changed, 728 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/auo-pixcir-ts.c create mode 100644 include/linux/input/auo-pixcir-ts.h
drivers/input/touchscreen/Kconfig +14 -0
@@ -98,6 +98,20 @@ 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 + default n + 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
drivers/input/touchscreen/Makefile +1 -0
@@ -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
drivers/input/touchscreen/auo-pixcir-ts.c new file +656 -0
656 lines not on this page · raw message
include/linux/input/auo-pixcir-ts.h new file +57 -0
57 lines not on this page · raw message
Signature · 1 line
1.7.5.4
Dmitry Torokhov
maintainerHi Heiko,
Quoted 31 lines · Heiko Stübner
Some displays from AUO have a so called in-cell touchscreen, meaning it is built directly into the display unit.
Touchdata is gathered through PIXCIR Tango-ICs and processed in an Atmel ATmega168P with custom firmware. Communication between the host system and ATmega is done via I2C.
Devices using this touch solution include the Dell Streak5 and the family of Qisda ebook readers.
The driver reports single- and multi-touch events including touch area values.
Signed-off-by Heiko Stuebner <[email protected]>---
changes since v1: address comments from Christoph Fritz (wrong type for error checks, wrong call toinput_free_device)drivers/input/touchscreen/Kconfig | 14 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/auo-pixcir-ts.c | 656 +++++++++++++++++++++++++++++ include/linux/input/auo-pixcir-ts.h | 57 +++ 4 files changed, 728 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/auo-pixcir-ts.c create mode 100644 include/linux/input/auo-pixcir-ts.hdrivers/input/touchscreen/Kconfig +0
-0
drivers/input/touchscreen/Kconfig config TOUCHSCREEN_ATMEL_MXT · line 105
Quoted 8 lines
drivers/input/touchscreen/Kconfig +5
-0@@ -98,6 +98,20 @@ 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 + default n
No need for "default n"
Quoted 30 lines
drivers/input/touchscreen/Kconfig +9
-0+ 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_BITSYdrivers/input/touchscreen/Makefile +1
-0@@ -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.odrivers/input/touchscreen/auo-pixcir-ts.c new file +0
-0
drivers/input/touchscreen/auo-pixcir-ts.c line 1
Quoted 1 line
drivers/input/touchscreen/auo-pixcir-ts.c new file +1
-0@@ -0,0 +1,656 @@ +/* drivers/input/touchscreen/auo-pixcir-ts.c
Please no file names in files - this way you don't need to change it here if you rename it later.
Quoted 19 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +19
-0+* +* Copyright (c) 2011 Heiko Stuebner <[email protected]> +* +* 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. +* +*/
drivers/input/touchscreen/auo-pixcir-ts.c line 30
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/jiffies.h> +#include <linux/io.h> +#include <linux/uaccess.h>
Do you need this?
drivers/input/touchscreen/auo-pixcir-ts.c line 31
Quoted 1 line
drivers/input/touchscreen/auo-pixcir-ts.c new file +1
-0+#include <linux/miscdevice.h>
And this?
drivers/input/touchscreen/auo-pixcir-ts.c line 33
Quoted 2 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +2
-0+#include <linux/i2c.h> +#include <linux/semaphore.h>
I think you want mutex.h instead.
Quoted 183 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +183
-0+#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; +bool is_open; +}; + +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; +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; +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,
drivers/input/touchscreen/auo-pixcir-ts.c line 226
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+ 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);
Is there a way to track the contacts and switch to protocol B by any chance?
Quoted 55 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +55
-0+ +/* 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);
drivers/input/touchscreen/auo-pixcir-ts.c line 291
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+if (ret) { +dev_err (&client->dev,"unable to write reg %Xh, %d\n" , +AUO_PIXCIR_REG_POWER_MODE , ret); +return ret; + } + +return 0 ; +} + +static int auo_pixcir_int_config (struct auo_pixcir_ts *ts,int int_setting)
__devinit?
Quoted 18 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +18
-0+{ +struct i2c_client *client = ts->client; +struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; +int ret; + + ret =i2c_smbus_read_byte_data (client,AUO_PIXCIR_REG_INT_SETTING ); +if (ret <0 ) { +dev_err (&client->dev,"unable to read reg %Xh, %d\n" , +AUO_PIXCIR_REG_INT_SETTING , ret); +return ret; + } + + ret &= (~AUO_PIXCIR_INT_MODE_MASK ); + ret |= int_setting; + ret |=AUO_PIXCIR_INT_POL_HIGH ;/* always use high for interrupts */ + + ret =i2c_smbus_write_byte_data (client,AUO_PIXCIR_REG_INT_SETTING , + ret);
drivers/input/touchscreen/auo-pixcir-ts.c line 319
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+if (ret <0 ) { +dev_err (&client->dev,"unable to write reg %Xh, %d\n" , +AUO_PIXCIR_REG_INT_SETTING , ret); +return ret; + } + +if (pdata->int_setting ==AUO_PIXCIR_INT_TOUCH_IND ) + ts->touch_ind_mode =1 ; +else + ts->touch_ind_mode =0 ;
ts->touch_ind_mode = pdata->int_setting == AUO_PIXCIR_INT_TOUCH_IND;
drivers/input/touchscreen/auo-pixcir-ts.c line 324
Quoted 5 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +5
-0+ +return 0 ; +} + +/* controll the generation of interrupts on the device side */
Typo: control
drivers/input/touchscreen/auo-pixcir-ts.c line 325
Quoted 1 line
drivers/input/touchscreen/auo-pixcir-ts.c new file +1
-0+static int auo_pixcir_int_enable (struct auo_pixcir_ts *ts,int enable)
bool enable
Probably call it "auo_pixcir_int_toggle".
drivers/input/touchscreen/auo-pixcir-ts.c line 334
Quoted 9 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +9
-0+{ +struct i2c_client *client = ts->client; +int ret; + + ret =i2c_smbus_read_byte_data (client,AUO_PIXCIR_REG_INT_SETTING ); +if (ret <0 ) { +dev_err (&client->dev,"unable to read reg %Xh, %d\n" , +AUO_PIXCIR_REG_INT_SETTING , ret); +disable_irq (client->irq);
This looks like wrong place for disable_irq(). Caller should do it IMO.
Quoted 87 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +87
-0+return ret; + } + +if (enable) + ret |=AUO_PIXCIR_INT_ENABLE ; +else + ret &= ~AUO_PIXCIR_INT_ENABLE ; + + ret =i2c_smbus_write_byte_data (client,AUO_PIXCIR_REG_INT_SETTING , + ret); +if (ret <0 ) { +dev_err (&client->dev,"unable to write reg %Xh, %d\n" , +AUO_PIXCIR_REG_INT_SETTING , ret); +disable_irq (client->irq); +return ret; + } + +return 0 ; +} + +static int auo_pixcir_start (struct auo_pixcir_ts *ts) +{ +struct i2c_client *client = ts->client; +int ret; + + ret =auo_pixcir_power_mode (ts,AUO_PIXCIR_POWER_ACTIVE ); +if (ret <0 ) { +dev_err (&client->dev,"could not set power mode, %d\n" , + ret); +return ret; + } + + ts->stopped = false; +mb (); +enable_irq (client->irq); + + ret =auo_pixcir_int_enable (ts,1 ); +if (ret <0 ) { +dev_err (&client->dev,"could not enable interrupt, %d\n" , + ret); +return ret; + } + +return 0 ; +} + +static int auo_pixcir_stop (struct auo_pixcir_ts *ts) +{ +struct i2c_client *client = ts->client; +int ret; + + ret =auo_pixcir_int_enable (ts,0 ); +if (ret <0 ) { +dev_err (&client->dev,"could not disable interrupt, %d\n" , + ret); +return ret; + } + +/* disable receiving of interrupts */ +disable_irq (client->irq); + ts->stopped = true; +mb (); +wake_up (&ts->wait); + +return auo_pixcir_power_mode (ts,AUO_PIXCIR_POWER_DEEP_SLEEP ); +} + +static int auo_pixcir_input_open (struct input_dev *dev) +{ +struct auo_pixcir_ts *ts =input_get_drvdata (dev); +int ret; + + ret =auo_pixcir_start (ts); +if (ret) +return ret; + + ts->is_open = true; + +return 0 ; +} + +static void auo_pixcir_input_close (struct input_dev *dev) +{ +struct auo_pixcir_ts *ts =input_get_drvdata (dev); + + ts->is_open = false; +
drivers/input/touchscreen/auo-pixcir-ts.c line 431
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+auo_pixcir_stop (ts); + +return ; +} + +#ifdef CONFIG_PM_SLEEP +static int auo_pixcir_suspend (struct device *dev) +{ +struct i2c_client *client =to_i2c_client (dev); + struct auo_pixcir_ts *ts = (struct auo_pixcir_ts *)
The cast is not needed.
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+i2c_get_clientdata (client); + +/* if device isn't open it's stopped already */ +if (ts->is_open) { +if (device_may_wakeup (&client->dev)) { +enable_irq_wake (client->irq); +return auo_pixcir_power_mode (ts, +AUO_PIXCIR_POWER_SLEEP ); + }else { +auo_pixcir_stop (ts);
drivers/input/touchscreen/auo-pixcir-ts.c line 451
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+ } + } + +return 0 ; +} + +static int auo_pixcir_resume (struct device *dev) +{ +struct i2c_client *client =to_i2c_client (dev); + struct auo_pixcir_ts *ts = (struct auo_pixcir_ts *)
The cast is not needed.
drivers/input/touchscreen/auo-pixcir-ts.c line 454
Quoted 3 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +3
-0+i2c_get_clientdata (client); + +/* if device isn't open it was stopped and should stay that way */
If it is configured as wakeup source it should still wake up the system.
drivers/input/touchscreen/auo-pixcir-ts.c line 459
Quoted 5 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +5
-0+if (ts->is_open) { +if (device_may_wakeup (&client->dev)) { +disable_irq_wake (client->irq); +/* automatic wakeup on first-touch */ + }else if (ts->is_open) {
This needs locking WRT open/close. You can use input->users and input->mutex instead of ts->is_open.
drivers/input/touchscreen/auo-pixcir-ts.c line 467
Quoted 8 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +8
-0+return auo_pixcir_start (ts); + } + } + +return 0 ; +} + +SIMPLE_DEV_PM_OPS (auo_pixcir_pm_ops, auo_pixcir_suspend, auo_pixcir_resume);
static and pull it out of #ifdef and you can drop #ifdef in driver definition as well.
Quoted 20 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +20
-0+#endif + +static int __devinit auo_pixcir_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ +struct auo_pixcir_ts *ts; +struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; +struct input_dev *input_dev; +int ret; + +if (!pdata) +return -EINVAL ; + + ts =kzalloc (sizeof (struct auo_pixcir_ts ),GFP_KERNEL ); +if (!ts) +return -ENOMEM ; + + ret =gpio_request (pdata->gpio_int,"auo_pixcir_ts_int" ); +if (ret) { + dev_err(&client->dev, "request of gpio %d failed, %d\n",
drivers/input/touchscreen/auo-pixcir-ts.c line 497
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+ pdata->gpio_int, ret); + goto err_gpio_int; + } + + ret =gpio_request (pdata->gpio_rst,"auo_pixcir_ts_rst" ); +if (ret) { +dev_err (&client->dev,"request of gpio %d failed, %d\n" , + pdata->gpio_int, ret); + goto err_gpio_rst; + }
I do not see it actually being used?
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+ +if (pdata->init_hw) + pdata->init_hw (); + + ts->client = client; + ts->touch_ind_mode =0 ; +init_waitqueue_head (&ts->wait); + +snprintf (ts->phys,sizeof (ts->phys), +"%s/input0" ,dev_name (&client->dev));
drivers/input/touchscreen/auo-pixcir-ts.c line 517
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+ + input_dev =input_allocate_device (); +if (!input_dev) { +dev_err (&client->dev,"could not allocate input device\n" ); + goto err_input_alloc; + } + + ts->input = input_dev; + + input_dev->name ="auo_pixcir_ts" ;
Could do with a better name I think. It does not need to resemble file name.
Quoted 51 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +51
-0+ input_dev->phys = ts->phys; + input_dev->id.bustype =BUS_I2C ; + input_dev->dev.parent = &client->dev; + + input_dev->open = auo_pixcir_input_open; + input_dev->close = auo_pixcir_input_close; + +__set_bit (EV_ABS , input_dev->evbit); +__set_bit (EV_KEY , input_dev->evbit); + +__set_bit (BTN_TOUCH , input_dev->keybit); + +/* For single touch */ +input_set_abs_params (input_dev,ABS_X ,0 , pdata->x_max,0 ,0 ); +input_set_abs_params (input_dev,ABS_Y ,0 , pdata->y_max,0 ,0 ); + +/* For multi touch */ +input_set_abs_params (input_dev,ABS_MT_POSITION_X ,0 , + pdata->x_max,0 ,0 ); +input_set_abs_params (input_dev,ABS_MT_POSITION_Y ,0 , + pdata->y_max,0 ,0 ); +input_set_abs_params (input_dev,ABS_MT_TOUCH_MAJOR ,0 , +AUO_PIXCIR_MAX_AREA ,0 ,0 ); +input_set_abs_params (input_dev,ABS_MT_TOUCH_MINOR ,0 , +AUO_PIXCIR_MAX_AREA ,0 ,0 ); +input_set_abs_params (input_dev,ABS_MT_ORIENTATION ,0 ,1 ,0 ,0 ); + + ret =i2c_smbus_read_byte_data (client,AUO_PIXCIR_REG_VERSION ); +if (ret <0 ) + goto err_fw_vers; +dev_info (&client->dev,"firmware version 0x%X\n" , ret); + + ret =auo_pixcir_int_config (ts, pdata->int_setting); +if (ret) + goto err_fw_vers; + +/* disable irqs on the device side before irq-request */ +auo_pixcir_int_enable (ts,0 ); + ts->stopped = true; + ts->is_open = false; + + ret =request_threaded_irq (client->irq,NULL , auo_pixcir_interrupt, +IRQF_TRIGGER_RISING |IRQF_ONESHOT , + input_dev->name, ts); +if (ret) { +dev_err (&client->dev,"irq %d requested failed\n" , client->irq); + goto err_fw_vers; + } + +/* stop device and put it into deep sleep until it is opened */ + ret =auo_pixcir_stop (ts);
drivers/input/touchscreen/auo-pixcir-ts.c line 578
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+if (ret <0 ) + goto err_input_register; + + ret =input_register_device (input_dev); +if (ret) { +dev_err (&client->dev,"could not register input device\n" ); + goto err_input_register; + } + +input_set_drvdata (ts->input, ts);
Just do this earlier and then auo_pixcir_stop() is enough, you won't need to call auo_pixcir_int_enable() before registering IRQ.
Quoted 14 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +14
-0+ +i2c_set_clientdata (client, ts); + +return 0 ; + +err_input_register: +free_irq (client->irq, ts); +err_fw_vers: +input_free_device (input_dev); +err_input_alloc: +if (pdata->exit_hw) + pdata->exit_hw (); +gpio_free (pdata->gpio_rst); +err_gpio_rst:
drivers/input/touchscreen/auo-pixcir-ts.c line 602
Quoted 10 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +10
-0+gpio_free (pdata->gpio_int); +err_gpio_int: +kfree (ts); + +return ret; +} + +static int __devexit auo_pixcir_remove(struct i2c_client *client) +{ + struct auo_pixcir_ts *ts = (struct auo_pixcir_ts *)
No need to cast.
drivers/input/touchscreen/auo-pixcir-ts.c line 604
Quoted 2 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +2
-0+i2c_get_clientdata (client); +struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
const.
drivers/input/touchscreen/auo-pixcir-ts.c line 606
Quoted 2 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +2
-0+ +auo_pixcir_stop (ts);
This should not be needed as the device should be closed at this point.
Quoted 83 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +50
-0+ +free_irq (client->irq, ts); + +input_unregister_device (ts->input); + +if (pdata->exit_hw) + pdata->exit_hw (); + +gpio_free (pdata->gpio_int); +gpio_free (pdata->gpio_rst); + +kfree (ts); + +return 0 ; +} + +static const struct i2c_device_id auo_pixcir_idtable[] = { + {"auo_pixcir_ts" ,0 }, + { } +}; +MODULE_DEVICE_TABLE (i2c, auo_pixcir_idtable); + +static struct i2c_driver auo_pixcir_driver = { + .driver = { + .owner =THIS_MODULE , + .name ="auo_pixcir_ts" , +#ifdef CONFIG_PM + .pm = &auo_pixcir_pm_ops, +#endif + }, + .probe = auo_pixcir_probe, + .remove =__devexit_p (auo_pixcir_remove), + .id_table = auo_pixcir_idtable, +}; + +static int __init auo_pixcir_init (void ) +{ +return i2c_add_driver (&auo_pixcir_driver); +} +module_init (auo_pixcir_init); + +static void __exit auo_pixcir_exit(void) +{ +i2c_del_driver (&auo_pixcir_driver); +} +module_exit (auo_pixcir_exit); + +MODULE_DESCRIPTION ("AUO-PIXCIR touchscreen driver" ); +MODULE_LICENSE ("GPL v2" ); +MODULE_AUTHOR ("Heiko Stuebner <[email protected]>" );include/linux/input/auo-pixcir-ts.h new file +27
-0@@ -0,0 +1,57 @@ +/* drivers/input/touchscreen/auo-pixcir-ts.h +* +* Copyright (c) 2011 Heiko Stuebner <[email protected]> +* +* based on auo_touch.h from Dell Streak 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. +* +*/ + +#ifndef __AUO_PIXCIR_TS_H__ +#define __AUO_PIXCIR_TS_H__ + +/* +* Interrupt modes: +* periodical: interrupt is asserted periodicaly
include/linux/input/auo-pixcir-ts.h line 37
Quoted 10 lines
include/linux/input/auo-pixcir-ts.h new file +10
-0+* compare coordinates: interrupt is asserted when coordinates change +* indicate touch: interrupt is asserted during touch +*/ +#define AUO_PIXCIR_INT_PERIODICAL 0x00 +#define AUO_PIXCIR_INT_COMP_COORD 0x01 +#define AUO_PIXCIR_INT_TOUCH_IND 0x02 + +/* +* @gpio_int interrupt gpio +* @gpio_rst reset gpio, used in init_hw and exit_hw
OK, if it is used by platform code only then it should not be here.
include/linux/input/auo-pixcir-ts.h line 50
Quoted 13 lines
include/linux/input/auo-pixcir-ts.h new file +13
-0+* @int_setting one of AUO_PIXCIR_INT_* +* @init_hw hardwarespecific init +* @exit_hw hardwarespecific shutdown +* @x_max x-resolution +* @y_max y-resolution +*/ +struct auo_pixcir_ts_platdata { +int gpio_int; +int gpio_rst; + +int int_setting; + +void (*init_hw)(void );
Maybe pass client or device so that we could theoretically handle multiple devices?
Quoted 10 lines
include/linux/input/auo-pixcir-ts.h new file +7
-0+void (*exit_hw)(void ); + +unsigned int x_max; + unsigned int y_max; +}; + +#endif Signature · 1 line
1.7.5.4
Thanks.
Signature · 5 lines
Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Dmitry,
thanks for the review
Am Dienstag, 6. Dezember 2011, 06:56:37 schrieb Dmitry Torokhov:
Quoted 19 lines · Heiko Stübner
Quoted 18 lines
Some displays from AUO have a so called in-cell touchscreen, meaning it is built directly into the display unit.
Touchdata is gathered through PIXCIR Tango-ICs and processed in an Atmel ATmega168P with custom firmware. Communication between the host system and ATmega is done via I2C.
Devices using this touch solution include the Dell Streak5 and the family of Qisda ebook readers.
The driver reports single- and multi-touch events including touch area values.
Signed-off-by Heiko Stuebner <[email protected]>---
changes since v1: address comments from Christoph Fritz (wrong type for error checks, wrong call toinput_free_device)
Quoted 9 lines
Quoted 9 lines
drivers/input/touchscreen/Kconfig | 14 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/auo-pixcir-ts.c | 656 +++++++++++++++++++++++++++++ include/linux/input/auo-pixcir-ts.h | 57 +++ 4 files changed, 728 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/auo-pixcir-ts.c create mode 100644 include/linux/input/auo-pixcir-ts.h
[ ... small corrections, thanks for finding them ... ]
Quoted 9 lines
Quoted 9 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +9
-0+ +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);
Quoted 8 lines
drivers/input/touchscreen/auo-pixcir-ts.c line 226
Quoted 5 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +5
-0+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);Is there a way to track the contacts and switch to protocol B by any chance?
I'm not sure, but will check how the device handles changing the number of touching fingers and if it would be possible to switch.
Quoted 11 lines
drivers/input/touchscreen/auo-pixcir-ts.c line 237
Quoted 11 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +11
-0+ +/* 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++; + } + }
[ ... more small stuff for me to fix ... ]
Quoted 11 lines
drivers/input/touchscreen/auo-pixcir-ts.c line 578
Quoted 8 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +8
-0+ + ret =input_register_device (input_dev); +if (ret) { +dev_err (&client->dev,"could not register input device\n" ); + goto err_input_register; + } + +input_set_drvdata (ts->input, ts);Just do this earlier and then
auo_pixcir_stop()is enough, you won't need to callauo_pixcir_int_enable()before registering IRQ.
Just to be sure, you mean moving the input_set_drvdata before the irq- registration?
Quoted 5 lines
drivers/input/touchscreen/auo-pixcir-ts.c line 583
Quoted 5 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +5
-0+ +i2c_set_clientdata (client, ts); + +return 0 ; +
[ ... and still more small stuff ]
Thanks
Heiko
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Am Mittwoch 07 Dezember 2011, 15:31:20 schrieb Heiko Stübner:
Quoted 55 lines
Hi Dmitry,
thanks for the review
Am Dienstag, 6. Dezember 2011, 06:56:37 schrieb Dmitry Torokhov:
Quoted 24 lines · Heiko Stübner
Quoted 23 lines
Some displays from AUO have a so called in-cell touchscreen, meaning it is built directly into the display unit.
Touchdata is gathered through PIXCIR Tango-ICs and processed in an Atmel ATmega168P with custom firmware. Communication between the host system and ATmega is done via I2C.
Devices using this touch solution include the Dell Streak5 and the family of Qisda ebook readers.
The driver reports single- and multi-touch events including touch area values.
Signed-off-by Heiko Stuebner <[email protected]>---
changes since v1: address comments from Christoph Fritz (wrong type for error checks, wrong call toinput_free_device)drivers/input/touchscreen/Kconfig | 14 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/auo-pixcir-ts.c | 656+++++++++++++++++++++++++++++
include/linux/input/auo-pixcir-ts.hQuoted 5 lines
Quoted 5 lines
| 57 +++
4 files changed, 728 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/auo-pixcir-ts.c create mode 100644 include/linux/input/auo-pixcir-ts.h[ ... small corrections, thanks for finding them ... ]
Quoted 9 lines
Quoted 9 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +9
-0+ +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);Quoted 8 lines
drivers/input/touchscreen/auo-pixcir-ts.c line 226
Quoted 5 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +5
-0+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);Is there a way to track the contacts and switch to protocol B by any chance?
Quoted 2 lines
I'm not sure, but will check how the device handles changing the number of touching fingers and if it would be possible to switch.
Sadly, the device does not seem capable of really tracking the contacts individually.
My testcase:
- p0 <-> finger0, p1 <-> finger1
- finger0 is lifted
in todays test: new mapping finger1 <-> p0
some time ago during another test sometimes it did this switch and sometimes not, so the mapping reported point <-> finger is probably not stable.
Quoted 26 lines
Quoted 11 lines
drivers/input/touchscreen/auo-pixcir-ts.c line 237
Quoted 11 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +11
-0+ +/* 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++; + } + }[ ... more small stuff for me to fix ... ]
Quoted 11 lines
drivers/input/touchscreen/auo-pixcir-ts.c line 578
Quoted 8 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +8
-0+ + ret =input_register_device (input_dev); +if (ret) { +dev_err (&client->dev,"could not register input device\n" ); + goto err_input_register; + } + +input_set_drvdata (ts->input, ts);Just do this earlier and then
auo_pixcir_stop()is enough, you won't need to callauo_pixcir_int_enable()before registering IRQ.
Quoted 2 lines
Just to be sure, you mean moving the
input_set_drvdatabefore the irq- registration?
seems to work
Quoted 10 lines
Quoted 5 lines
drivers/input/touchscreen/auo-pixcir-ts.c line 583
Quoted 5 lines
drivers/input/touchscreen/auo-pixcir-ts.c new file +5
-0+ +i2c_set_clientdata (client, ts); + +return 0 ; +[ ... and still more small stuff ]
Thanks
Heiko
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html