diff options
author | Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | 2010-10-18 17:33:52 +0200 |
---|---|---|
committer | Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | 2010-10-23 13:29:34 +0200 |
commit | b96cb51296043b2411036d807090bdefbcdcc4f5 (patch) | |
tree | 798c2cc57ebf6ee965080601e573ae34983cc86e /drivers/input | |
parent | 1c9a174eaee3c120cc4d9fb205ae7f22c731f5da (diff) |
input: update bu21013 touchscreen controller
This patch is based on the following work:
input: bu21013 touch screen hangs with Gallery application using BT
ST-Ericsson Id: ER 272266
Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
input: bu21013: various clean-ups.
ST-Ericsson Id: AP 267341
Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
bu21013:Improve the touchscreen performance
ST-Ericsson Id: ER 266784
Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
bu21013: fix to increase the touch screen performance
ST-Ericsson Id: ER 264213
Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
bu21013:Fix for html docs in dual touch controllers support
ST-Ericsson ID: WP 257134
Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
bu21013:Coverity fix for Dual touch controllers support
ST-Ericsson ID: WP 257134
Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
bu21013: Driver for new dual touch controllers support
ST-Ericsson ID: WP 257134
Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
Moreover, documentation is added to DocBook
Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 10 | ||||
-rw-r--r-- | drivers/input/touchscreen/bu21013_ts.c | 1070 |
2 files changed, 711 insertions, 369 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 4b1c7f939a9..6c0b8dabc68 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -102,6 +102,7 @@ config TOUCHSCREEN_BITSY config TOUCHSCREEN_BU21013 tristate "BU21013 based touch panel controllers" depends on I2C + default y help Say Y here if you have a bu21013 touchscreen connected to your system. @@ -111,6 +112,15 @@ config TOUCHSCREEN_BU21013 To compile this driver as a module, choose M here: the module will be called bu21013_ts. +config BU21013_TSC_CNTL1 + bool "Touch panel1 with BU21013 controller" + depends on TOUCHSCREEN_BU21013 + default y + +config BU21013_TSC_CNTL2 + bool "Touch panel2 with BU21013 controller2" + depends on TOUCHSCREEN_BU21013 + config TOUCHSCREEN_DA9034 tristate "Touchscreen support for Dialog Semiconductor DA9034" depends on PMIC_DA903X diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index ccde5860256..da9cd0ad15f 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -1,181 +1,338 @@ /* - * Copyright (C) ST-Ericsson SA 2010 + * Copyright (C) ST-Ericsson SA 2009 * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson * License terms:GNU General Public License (GPL) version 2 */ #include <linux/kernel.h> +#include <linux/init.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/workqueue.h> #include <linux/input.h> +#include <linux/types.h> +#include <linux/timer.h> #include <linux/input/bu21013.h> #include <linux/slab.h> #define PEN_DOWN_INTR 0 -#define MAX_FINGERS 2 +#define PEN_UP_INTR 1 #define RESET_DELAY 30 -#define PENUP_TIMEOUT (10) +#define POLLING_DELAY 100 +#define MAX_TOOL_WIDTH 15 +#define MAX_TOUCH_MAJOR 255 +#define MAX_TOUCH_MINOR 15 +#define MAX_PRESSURE 1 +#define PENUP_TIMEOUT (2) +#define SCALE_FACTOR 1000 #define DELTA_MIN 16 #define MASK_BITS 0x03 #define SHIFT_8 8 #define SHIFT_2 2 #define LENGTH_OF_BUFFER 11 -#define I2C_RETRY_COUNT 5 - -#define BU21013_SENSORS_BTN_0_7_REG 0x70 -#define BU21013_SENSORS_BTN_8_15_REG 0x71 -#define BU21013_SENSORS_BTN_16_23_REG 0x72 -#define BU21013_X1_POS_MSB_REG 0x73 -#define BU21013_X1_POS_LSB_REG 0x74 -#define BU21013_Y1_POS_MSB_REG 0x75 -#define BU21013_Y1_POS_LSB_REG 0x76 -#define BU21013_X2_POS_MSB_REG 0x77 -#define BU21013_X2_POS_LSB_REG 0x78 -#define BU21013_Y2_POS_MSB_REG 0x79 -#define BU21013_Y2_POS_LSB_REG 0x7A -#define BU21013_INT_CLR_REG 0xE8 -#define BU21013_INT_MODE_REG 0xE9 -#define BU21013_GAIN_REG 0xEA -#define BU21013_OFFSET_MODE_REG 0xEB -#define BU21013_XY_EDGE_REG 0xEC -#define BU21013_RESET_REG 0xED -#define BU21013_CALIB_REG 0xEE -#define BU21013_DONE_REG 0xEF -#define BU21013_SENSOR_0_7_REG 0xF0 -#define BU21013_SENSOR_8_15_REG 0xF1 -#define BU21013_SENSOR_16_23_REG 0xF2 -#define BU21013_POS_MODE1_REG 0xF3 -#define BU21013_POS_MODE2_REG 0xF4 -#define BU21013_CLK_MODE_REG 0xF5 -#define BU21013_IDLE_REG 0xFA -#define BU21013_FILTER_REG 0xFB -#define BU21013_TH_ON_REG 0xFC -#define BU21013_TH_OFF_REG 0xFD - - -#define BU21013_RESET_ENABLE 0x01 - -#define BU21013_SENSORS_EN_0_7 0x3F -#define BU21013_SENSORS_EN_8_15 0xFC -#define BU21013_SENSORS_EN_16_23 0x1F - -#define BU21013_POS_MODE1_0 0x02 -#define BU21013_POS_MODE1_1 0x04 -#define BU21013_POS_MODE1_2 0x08 - -#define BU21013_POS_MODE2_ZERO 0x01 -#define BU21013_POS_MODE2_AVG1 0x02 -#define BU21013_POS_MODE2_AVG2 0x04 -#define BU21013_POS_MODE2_EN_XY 0x08 -#define BU21013_POS_MODE2_EN_RAW 0x10 -#define BU21013_POS_MODE2_MULTI 0x80 - -#define BU21013_CLK_MODE_DIV 0x01 -#define BU21013_CLK_MODE_EXT 0x02 -#define BU21013_CLK_MODE_CALIB 0x80 - -#define BU21013_IDLET_0 0x01 -#define BU21013_IDLET_1 0x02 -#define BU21013_IDLET_2 0x04 -#define BU21013_IDLET_3 0x08 -#define BU21013_IDLE_INTERMIT_EN 0x10 - -#define BU21013_DELTA_0_6 0x7F -#define BU21013_FILTER_EN 0x80 - -#define BU21013_INT_MODE_LEVEL 0x00 -#define BU21013_INT_MODE_EDGE 0x01 - -#define BU21013_GAIN_0 0x01 -#define BU21013_GAIN_1 0x02 -#define BU21013_GAIN_2 0x04 - -#define BU21013_OFFSET_MODE_DEFAULT 0x00 -#define BU21013_OFFSET_MODE_MOVE 0x01 -#define BU21013_OFFSET_MODE_DISABLE 0x02 - -#define BU21013_TH_ON_0 0x01 -#define BU21013_TH_ON_1 0x02 -#define BU21013_TH_ON_2 0x04 -#define BU21013_TH_ON_3 0x08 -#define BU21013_TH_ON_4 0x10 -#define BU21013_TH_ON_5 0x20 -#define BU21013_TH_ON_6 0x40 -#define BU21013_TH_ON_7 0x80 -#define BU21013_TH_ON_MAX 0xFF - -#define BU21013_TH_OFF_0 0x01 -#define BU21013_TH_OFF_1 0x02 -#define BU21013_TH_OFF_2 0x04 -#define BU21013_TH_OFF_3 0x08 -#define BU21013_TH_OFF_4 0x10 -#define BU21013_TH_OFF_5 0x20 -#define BU21013_TH_OFF_6 0x40 -#define BU21013_TH_OFF_7 0x80 -#define BU21013_TH_OFF_MAX 0xFF - -#define BU21013_X_EDGE_0 0x01 -#define BU21013_X_EDGE_1 0x02 -#define BU21013_X_EDGE_2 0x04 -#define BU21013_X_EDGE_3 0x08 -#define BU21013_Y_EDGE_0 0x10 -#define BU21013_Y_EDGE_1 0x20 -#define BU21013_Y_EDGE_2 0x40 -#define BU21013_Y_EDGE_3 0x80 - -#define BU21013_DONE 0x01 -#define BU21013_NUMBER_OF_X_SENSORS (6) -#define BU21013_NUMBER_OF_Y_SENSORS (11) #define DRIVER_TP "bu21013_tp" /** * struct bu21013_ts_data - touch panel data structure - * @client: pointer to the i2c client - * @wait: variable to wait_queue_head_t structure - * @touch_stopped: touch stop flag - * @chip: pointer to the touch panel controller - * @in_dev: pointer to the input device structure + * @client: pointer to the i2c client + * @chip: pointer to the touch panel controller + * @in_dev: pointer to the input device structure + * @penirq_timer: variable to the timer list structure + * @timer_handler: variable to work structure for timer + * @gpio_handler: variable to work structure for gpio interrupt + * @board_flag: variable to indicate the href v1 board * @intr_pin: interrupt pin value + * @x_pos: x position for two co-ordinates + * @y_pos: y position for two co-ordinates + * @factor_x: x scale factor + * @factor_y: y scale factor + * @previous_press_reported: last reported flag + * @touchp_kobj: pointer to kernel object for touch panel + * @penup_timer: timeout value * - * Touch panel device data structure + * Touch panel data structure */ struct bu21013_ts_data { struct i2c_client *client; - wait_queue_head_t wait; - bool touch_stopped; - const struct bu21013_platform_device *chip; + struct bu21013_platform_device *chip; struct input_dev *in_dev; + struct timer_list penirq_timer; + struct work_struct timer_wq_handler; + struct work_struct gpio_wq_handler; unsigned int intr_pin; + signed short x_pos[2]; + signed short y_pos[2]; + int factor_x; + int factor_y; + bool previous_press_reported; + struct kobject *touchp_kobj; + int penup_timer; }; +/* Global variable to maintain the sys data for two controllers */ +struct bu21013_ts_data *tp1_sys_data, *tp2_sys_data; + +static int bu21013_init_chip(struct bu21013_ts_data *data); + +/* + * sysfs is used to change the touchpanel1 parameters + * and also enable the external clock dynamically + */ +static ssize_t touchp1_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + u8 timeout; + u8 sys_ext_clock; + + if (strcmp(attr->name, "timeout_value") == 0) { + timeout = tp1_sys_data->penup_timer; + sprintf(buf, "%d\n", timeout); + } else if (strcmp(attr->name, "ext_clk") == 0) { + sys_ext_clock = tp1_sys_data->chip->ext_clk; + sprintf(buf, "%d\n", sys_ext_clock); + } + return strlen(buf); +} +static ssize_t touchp1_attr_store(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t len) +{ + int ret = 0; + int timeout; + int sys_ext_clock; + + if (strcmp(attr->name, "timeout_value") == 0) { + ret = sscanf(buf, "%d", &timeout); + if (ret == 1) + tp1_sys_data->penup_timer = timeout; + } else if (strcmp(attr->name, "ext_clk") == 0) { + ret = sscanf(buf, "%d", &sys_ext_clock); + if ((ret == 1) && + (tp1_sys_data->chip->ext_clk != sys_ext_clock)) { + tp1_sys_data->chip->ext_clk = sys_ext_clock; + bu21013_init_chip(tp1_sys_data); + } + } + return ret == 1 ? len : -EINVAL; +} + +/* + * sysfs is used to change the touchpanel2 parameters + * and also enable the external clock dynamically + */ +static ssize_t touchp2_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + u8 timeout; + u8 sys_ext_clock; + + if (strcmp(attr->name, "timeout_value") == 0) { + timeout = tp2_sys_data->penup_timer; + sprintf(buf, "%d\n", timeout); + } else if (strcmp(attr->name, "ext_clk") == 0) { + sys_ext_clock = tp2_sys_data->chip->ext_clk; + sprintf(buf, "%d\n", sys_ext_clock); + } + return strlen(buf); +} +static ssize_t touchp2_attr_store(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t len) +{ + int ret = 0; + int timeout; + int sys_ext_clock; + + if (strcmp(attr->name, "timeout_value") == 0) { + ret = sscanf(buf, "%d", &timeout); + if (ret == 1) + tp2_sys_data->penup_timer = timeout; + } else if (strcmp(attr->name, "ext_clk") == 0) { + ret = sscanf(buf, "%d", &sys_ext_clock); + if ((ret == 1) && + (tp2_sys_data->chip->ext_clk != sys_ext_clock)) { + tp2_sys_data->chip->ext_clk = sys_ext_clock; + bu21013_init_chip(tp2_sys_data); + } + } + return ret == 1 ? len : -EINVAL; +} + + +static struct attribute touchp_timeout = {.name = "timeout_value", + .mode = 0666}; +static struct attribute touchp_ext_clk = {.name = "ext_clk", .mode = 0666}; + +static struct attribute *touchp_attribute[] = { + &touchp_timeout, + &touchp_ext_clk, + NULL +}; + +static const struct sysfs_ops touchp1_sysfs_ops = { + .show = touchp1_attr_show, + .store = touchp1_attr_store, +}; + +static const struct sysfs_ops touchp2_sysfs_ops = { + .show = touchp2_attr_show, + .store = touchp2_attr_store, +}; + +static struct kobj_type ktype_touchp1 = { + .sysfs_ops = &touchp1_sysfs_ops, + .default_attrs = touchp_attribute, +}; +static struct kobj_type ktype_touchp2 = { + .sysfs_ops = &touchp2_sysfs_ops, + .default_attrs = touchp_attribute, +}; + +/* + * bu21013_get_number_of_bits() - count the bits in given value + * @val: read bits from this value + * @range: maximum number of bits + * + * Read the number of bits from the given value + * and returns integer + */ +static inline int bu21013_get_number_of_bits(unsigned int val, int range) +{ + int i; + int num = 0; + unsigned int mask = 1; + + for (i = 0; i < range; i++) { + if (val & mask) + num++; + mask = mask << 1; + } + return num; +} /** - * bu21013_read_block_data(): read the touch co-ordinates - * @data: bu21013_ts_data structure pointer - * @buf: byte pointer + * bu21013_report_pen_down() - reports the pen down event + * @data:bu21013_ts_data structure pointer + * @count:touch count * - * Read the touch co-ordinates using i2c read block into buffer - * and returns integer. + * This function used to report the pen down interrupt to + * input subsystem and returns none */ -static int bu21013_read_block_data(struct bu21013_ts_data *data, u8 *buf) +static void bu21013_report_pen_down(struct bu21013_ts_data *data, int count) { - int ret, i; + short pt0x; + short pt0y; + short pt1x; + short pt1y; + if (data->chip->portrait) { + pt0x = data->x_pos[0]; + pt0y = data->y_pos[0]; + pt1x = data->x_pos[1]; + pt1y = data->y_pos[1]; + } else { + pt0x = data->y_pos[0]; + pt0y = data->x_pos[0]; + pt1x = data->y_pos[1]; + pt1y = data->x_pos[1]; + } - for (i = 0; i < I2C_RETRY_COUNT; i++) { - ret = i2c_smbus_read_i2c_block_data - (data->client, BU21013_SENSORS_BTN_0_7_REG, - LENGTH_OF_BUFFER, buf); - if (ret == LENGTH_OF_BUFFER) - return 0; + input_report_abs(data->in_dev, ABS_X, pt0x); + input_report_abs(data->in_dev, ABS_Y, pt0y); + input_report_abs(data->in_dev, ABS_PRESSURE, 1); + input_report_abs(data->in_dev, ABS_TOOL_WIDTH, 1); + input_report_key(data->in_dev, BTN_TOUCH, 1); + + if (count > 1) { + input_report_key(data->in_dev, BTN_2, 1); + input_report_abs(data->in_dev, ABS_HAT0X, pt1x); + input_report_abs(data->in_dev, ABS_HAT0Y, pt1y); + } + input_report_abs(data->in_dev, ABS_MT_TOUCH_MAJOR, 1); + input_report_abs(data->in_dev, ABS_MT_TOUCH_MINOR, 1); + input_report_key(data->in_dev, ABS_MT_WIDTH_MAJOR, 1); + input_report_abs(data->in_dev, ABS_MT_POSITION_X, pt0x); + input_report_abs(data->in_dev, ABS_MT_POSITION_Y, pt0y); + input_mt_sync(data->in_dev); + + if (count > 1) { + input_report_abs(data->in_dev, ABS_MT_TOUCH_MAJOR, 1); + input_report_key(data->in_dev, ABS_MT_WIDTH_MAJOR, 1); + input_report_abs(data->in_dev, ABS_MT_POSITION_X, pt1x); + input_report_abs(data->in_dev, ABS_MT_POSITION_Y, pt1y); + input_mt_sync(data->in_dev); + } + input_sync(data->in_dev); + data->previous_press_reported = count; +} +/** + * bu21013_report_pen_up() - reports the pen up event + * @data:bu21013_ts_data structure pointer + * + * This function used to report the pen up interrupt + * to input subsystem and returns none + */ +static void bu21013_report_pen_up(struct bu21013_ts_data *data) +{ + input_report_abs(data->in_dev, ABS_PRESSURE, 0); + input_report_abs(data->in_dev, ABS_TOOL_WIDTH, 0); + input_report_key(data->in_dev, BTN_TOUCH, 0); + input_report_key(data->in_dev, BTN_2, 0); + input_report_abs(data->in_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_key(data->in_dev, ABS_MT_WIDTH_MAJOR, 0); + input_mt_sync(data->in_dev); + input_sync(data->in_dev); + data->previous_press_reported = 0; +} +/** + * bu21013_touch_calc() - calculates the co-ordinates delta + * @data: bu21013_ts_data structure pointer + * @x: x position + * @y: y position + * @count: touch count + * + * This function calculates the exact co-ordinates with respect to + * display resolution and returns none + */ +static void bu21013_touch_calc + (struct bu21013_ts_data *data, int x, int y, int count) +{ + data->x_pos[count] = x * data->factor_x / SCALE_FACTOR; + data->y_pos[count] = y * data->factor_y / SCALE_FACTOR; + if ((data->chip->portrait) && (data->chip->x_flip)) + data->x_pos[count] = + data->chip->x_max_res - data->x_pos[count]; + if ((data->chip->portrait) && (data->chip->y_flip)) + data->y_pos[count] = + data->chip->y_max_res - data->y_pos[count]; +} +/** + * bu21013_verify_delta() - verify the co-ordinates delta + * @x1: x1 position + * @y1: y1 position + * @x2: x2 position + * @y2: y2 position + * + * This function verifies the delta of the + * co-ordinates and returns boolean. + */ +static bool bu21013_verify_delta(int x1, int y1, int x2, int y2) +{ + int delta_x, delta_y; + if ((x1 != 0) && (y1 != 0)) { + delta_x = x2 - x1; + if (x1 > x2) + delta_x = x1 - x2; + delta_y = y2 - y1; + if (y1 > y2) + delta_y = y1 - y2; + if ((delta_x < DELTA_MIN) || (delta_y < DELTA_MIN)) + return false; } - return -EINVAL; + return true; } /** * bu21013_do_touch_report(): Get the touch co-ordinates - * @data: bu21013_ts_data structure pointer + * @data:bu21013_ts_data structure pointer * * Get the touch co-ordinates from touch sensor registers and writes * into device structure and returns integer. @@ -183,91 +340,194 @@ static int bu21013_read_block_data(struct bu21013_ts_data *data, u8 *buf) static int bu21013_do_touch_report(struct bu21013_ts_data *data) { u8 buf[LENGTH_OF_BUFFER]; - unsigned int pos_x[2], pos_y[2]; - bool has_x_sensors, has_y_sensors; + int finger1_valid = 0; + int finger2_valid = 0; + unsigned int finger1_pos_x; + unsigned int finger1_pos_y; + unsigned int finger2_pos_x; + unsigned int finger2_pos_y; + int number_of_active_x_sensors; + int number_of_active_y_sensors; + int total_number_of_active_sensors; int finger_down_count = 0; - int i; - - if (data == NULL) - return -EINVAL; + int ret = 0; + int retry_count = 5; - if (bu21013_read_block_data(data, buf) < 0) + if (data->client == NULL) return -EINVAL; - has_x_sensors = hweight32(buf[0] & BU21013_SENSORS_EN_0_7); - has_y_sensors = hweight32(((buf[1] & BU21013_SENSORS_EN_8_15) | - ((buf[2] & BU21013_SENSORS_EN_16_23) << SHIFT_8)) >> SHIFT_2); - if (!has_x_sensors || !has_y_sensors) + do { + ret = i2c_smbus_read_i2c_block_data + (data->client, BU21013_SENSORS_BTN_0_7_REG, + LENGTH_OF_BUFFER, buf); + retry_count--; + if ((ret < LENGTH_OF_BUFFER) && (!retry_count)) + return -EINVAL; + } while (ret < LENGTH_OF_BUFFER); + + number_of_active_x_sensors = + bu21013_get_number_of_bits((buf[0] & BU21013_SENSORS_EN_0_7), + BU21013_NUMBER_OF_X_SENSORS); + + number_of_active_y_sensors = bu21013_get_number_of_bits + ((((buf[1] & BU21013_SENSORS_EN_8_15) | + ((buf[2] & BU21013_SENSORS_EN_16_23) << SHIFT_8)) >> SHIFT_2), + BU21013_NUMBER_OF_Y_SENSORS); + + if (((number_of_active_x_sensors != 0) && + (number_of_active_y_sensors == 0)) || + ((number_of_active_x_sensors == 0) && + (number_of_active_y_sensors != 0))) return 0; - for (i = 0; i < MAX_FINGERS; i++) { - const u8 *p = &buf[4 * i + 3]; - unsigned int x = p[0] << SHIFT_2 | (p[1] & MASK_BITS); - unsigned int y = p[2] << SHIFT_2 | (p[3] & MASK_BITS); - if (x == 0 || y == 0) - continue; - pos_x[finger_down_count] = x; - pos_y[finger_down_count] = y; - finger_down_count++; - } - - if (finger_down_count) { - if (finger_down_count == 2 && - (abs(pos_x[0] - pos_x[1]) < DELTA_MIN || - abs(pos_y[0] - pos_y[1]) < DELTA_MIN)) { - return 0; + total_number_of_active_sensors = + number_of_active_x_sensors + number_of_active_y_sensors; + + finger1_pos_x = buf[3] << SHIFT_2 | (buf[4] & MASK_BITS); + finger1_pos_y = buf[5] << SHIFT_2 | (buf[6] & MASK_BITS); + finger2_pos_x = buf[7] << SHIFT_2 | (buf[8] & MASK_BITS); + finger2_pos_y = buf[9] << SHIFT_2 | (buf[10] & MASK_BITS); + + if (total_number_of_active_sensors) { + if ((finger2_pos_x != 0) && (finger2_pos_y != 0)) { + if ((finger1_pos_x == 0) || (finger1_pos_y == 0)) + return 0; + ret = bu21013_verify_delta(finger1_pos_x, + finger1_pos_y, finger2_pos_x, finger2_pos_y); + if (!ret) + total_number_of_active_sensors = 0; } + } - for (i = 0; i < finger_down_count; i++) { - if (data->chip->x_flip) - pos_x[i] = data->chip->touch_x_max - pos_x[i]; - if (data->chip->y_flip) - pos_y[i] = data->chip->touch_y_max - pos_y[i]; - - input_report_abs(data->in_dev, - ABS_MT_POSITION_X, pos_x[i]); - input_report_abs(data->in_dev, - ABS_MT_POSITION_Y, pos_y[i]); - input_mt_sync(data->in_dev); + if (total_number_of_active_sensors) { + finger1_valid = 1; + if ((finger1_pos_x == 0) || (finger1_pos_y == 0) || + (finger1_pos_x >= data->chip->touch_x_max) || + (finger1_pos_y >= data->chip->touch_y_max)) + finger1_valid = 0; + finger2_valid = 1; + if ((finger2_pos_x == 0) || (finger2_pos_y == 0) || + (finger2_pos_x >= data->chip->touch_x_max) || + (finger2_pos_y >= data->chip->touch_y_max)) + finger2_valid = 0; + if ((finger1_valid == 0) && (finger2_valid == 0)) + return 0; + if (finger1_valid) { + bu21013_touch_calc(data, finger1_pos_x, + finger1_pos_y, finger_down_count); + finger_down_count++; } - } else - input_mt_sync(data->in_dev); + if (finger2_valid) { + bu21013_touch_calc(data, finger2_pos_x, + finger2_pos_y, finger_down_count); + finger_down_count++; + } + } - input_sync(data->in_dev); + if (finger_down_count > 0) + bu21013_report_pen_down(data, finger_down_count); + else { + if (data->previous_press_reported) + bu21013_report_pen_up(data); + } - return 0; + return ret; +} + +/** + * bu21013_timer_start() - start the timer + * @data:bu21013_ts_data structure pointer + * + * This funtion used to run the timer and returns none. + */ +static inline void bu21013_timer_start(struct bu21013_ts_data *data) +{ + mod_timer(&data->penirq_timer, + jiffies + msecs_to_jiffies(data->penup_timer)); } + /** - * bu21013_gpio_irq() - gpio thread function for touch interrupt - * @irq: irq value - * @device_data: void pointer + * bu21013_timer_wq() - work queue for timer handler + * @work:work_struct structure pointer * - * This gpio thread function for touch interrupt - * and returns irqreturn_t. + * This timer work queue used during polling of the co-ordinates + * for every timeout period and returns none */ -static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) +static void bu21013_timer_wq(struct work_struct *work) { - struct bu21013_ts_data *data = device_data; + struct bu21013_ts_data *data = + container_of(work, struct bu21013_ts_data, timer_wq_handler); + struct task_struct *tsk = current; struct i2c_client *i2c = data->client; int retval; - do { - retval = bu21013_do_touch_report(data); - if (retval < 0) { - dev_err(&i2c->dev, "bu21013_do_touch_report failed\n"); - return IRQ_NONE; - } + set_task_state(tsk, TASK_INTERRUPTIBLE); + retval = bu21013_do_touch_report(data); + if (retval < 0) { + dev_err(&i2c->dev, "get co-ordinates failed\n"); + return; + } + data->intr_pin = data->chip->irq_read_val(); + if (data->intr_pin == PEN_DOWN_INTR) + bu21013_timer_start(data); + else + enable_irq(data->chip->irq); +} - data->intr_pin = data->chip->irq_read_val(); - if (data->intr_pin == PEN_DOWN_INTR) - wait_event_timeout(data->wait, data->touch_stopped, - msecs_to_jiffies(2)); - } while (!data->intr_pin && !data->touch_stopped); +/** + * bu21013_gpio_int_wq() - work queue for gpio interrupt handler + * @work:work_struct structure pointer + * + * This gpio work queue used to get the co-ordinates + * of the pen down interrupt and returns none + */ +static void bu21013_gpio_int_wq(struct work_struct *work) +{ + struct bu21013_ts_data *data = + container_of(work, struct bu21013_ts_data, gpio_wq_handler); + struct i2c_client *i2c = data->client; + struct task_struct *tsk = current; + int retval; + set_task_state(tsk, TASK_INTERRUPTIBLE); + disable_irq(data->chip->irq); + retval = bu21013_do_touch_report(data); + if (retval < 0) { + dev_err(&i2c->dev, "get co-ordinates failed\n"); + return; + } + bu21013_timer_start(data); +} + +/** + * bu21013_gpio_irq() - gpio callback handler for touch interrupt + * @irq: irq value + * @device_data:void pointer + * + * This gpio callback handler for gpio interrupt + * and assigns the task and returns irqreturn_t. + */ +static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) +{ + struct bu21013_ts_data *data = (struct bu21013_ts_data *)device_data; + schedule_work(&data->gpio_wq_handler); return IRQ_HANDLED; } /** + * bu21013_timer_callback() - callback handler for timer + * @dev_data:touch screen data + * + * This timer callback handler used to schedule the work during + * polling of pen down interrupts and returns none + */ +static void bu21013_timer_callback(unsigned long dev_data) +{ + struct bu21013_ts_data *data = (struct bu21013_ts_data *)dev_data; + schedule_work(&data->timer_wq_handler); +} + +/** * bu21013_init_chip() - power on sequence for the bu21013 controller * @data: device structure pointer * @@ -283,47 +543,42 @@ static int bu21013_init_chip(struct bu21013_ts_data *data) BU21013_RESET_ENABLE); if (retval < 0) { dev_err(&i2c->dev, "BU21013_RESET reg write failed\n"); - return retval; + goto err; } - msleep(RESET_DELAY); + mdelay(RESET_DELAY); retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_0_7_REG, BU21013_SENSORS_EN_0_7); if (retval < 0) { dev_err(&i2c->dev, "BU21013_SENSOR_0_7 reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_8_15_REG, - BU21013_SENSORS_EN_8_15); + BU21013_SENSORS_EN_8_15); if (retval < 0) { dev_err(&i2c->dev, "BU21013_SENSOR_8_15 reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_16_23_REG, - BU21013_SENSORS_EN_16_23); + BU21013_SENSORS_EN_16_23); if (retval < 0) { dev_err(&i2c->dev, "BU21013_SENSOR_16_23 reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE1_REG, (BU21013_POS_MODE1_0 | BU21013_POS_MODE1_1)); if (retval < 0) { dev_err(&i2c->dev, "BU21013_POS_MODE1 reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE2_REG, (BU21013_POS_MODE2_ZERO | BU21013_POS_MODE2_AVG1 | BU21013_POS_MODE2_AVG2 | BU21013_POS_MODE2_EN_RAW | BU21013_POS_MODE2_MULTI)); if (retval < 0) { dev_err(&i2c->dev, "BU21013_POS_MODE2 reg write failed\n"); - return retval; + goto err; } - if (data->chip->ext_clk) retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG, (BU21013_CLK_MODE_EXT | BU21013_CLK_MODE_CALIB)); @@ -332,192 +587,322 @@ static int bu21013_init_chip(struct bu21013_ts_data *data) (BU21013_CLK_MODE_DIV | BU21013_CLK_MODE_CALIB)); if (retval < 0) { dev_err(&i2c->dev, "BU21013_CLK_MODE reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_IDLE_REG, (BU21013_IDLET_0 | BU21013_IDLE_INTERMIT_EN)); if (retval < 0) { dev_err(&i2c->dev, "BU21013_IDLE reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_MODE_REG, BU21013_INT_MODE_LEVEL); if (retval < 0) { dev_err(&i2c->dev, "BU21013_INT_MODE reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_FILTER_REG, (BU21013_DELTA_0_6 | BU21013_FILTER_EN)); if (retval < 0) { dev_err(&i2c->dev, "BU21013_FILTER reg write failed\n"); - return retval; + goto err; } retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_ON_REG, - BU21013_TH_ON_5); + (BU21013_TH_ON_3 | BU21013_TH_ON_4)); if (retval < 0) { dev_err(&i2c->dev, "BU21013_TH_ON reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG, - BU21013_TH_OFF_4 || BU21013_TH_OFF_3); + BU21013_TH_OFF_4); if (retval < 0) { dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_GAIN_REG, (BU21013_GAIN_0 | BU21013_GAIN_1)); if (retval < 0) { dev_err(&i2c->dev, "BU21013_GAIN reg write failed\n"); - return retval; + goto err; } retval = i2c_smbus_write_byte_data(i2c, BU21013_OFFSET_MODE_REG, BU21013_OFFSET_MODE_DEFAULT); if (retval < 0) { dev_err(&i2c->dev, "BU21013_OFFSET_MODE reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_XY_EDGE_REG, - (BU21013_X_EDGE_0 | BU21013_X_EDGE_2 | + (BU21013_X_EDGE_0 | BU21013_X_EDGE_2 | BU21013_Y_EDGE_1 | BU21013_Y_EDGE_3)); if (retval < 0) { dev_err(&i2c->dev, "BU21013_XY_EDGE reg write failed\n"); - return retval; + goto err; } - retval = i2c_smbus_write_byte_data(i2c, BU21013_DONE_REG, BU21013_DONE); if (retval < 0) { dev_err(&i2c->dev, "BU21013_REG_DONE reg write failed\n"); - return retval; + goto err; } + data->x_pos[0] = 0; + data->x_pos[1] = 0; + data->y_pos[0] = 0; + data->y_pos[1] = 0; + data->previous_press_reported = 0; + + data->factor_x = (data->chip->x_max_res * SCALE_FACTOR / + data->chip->touch_x_max); + data->factor_y = (data->chip->y_max_res * SCALE_FACTOR / + data->chip->touch_y_max); +err: + return retval; +} + +#ifdef CONFIG_PM +/** + * bu21013_suspend() - suspend the touch screen controller + * @client: pointer to i2c client structure + * @mesg: message from power manager + * + * This funtion is used to suspend the + * touch panel controller and returns integer + */ +static int bu21013_suspend(struct i2c_client *client, pm_message_t mesg) +{ + struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client); + + if (device_may_wakeup(&client->dev)) + enable_irq(bu21013_data->chip->irq); + else + disable_irq(bu21013_data->chip->irq); + return 0; } /** - * bu21013_free_irq() - frees IRQ registered for touchscreen - * @bu21013_data: device structure pointer + * bu21013_resume() - resume the touch screen controller + * @client: pointer to i2c client structure * - * This function signals interrupt thread to stop processing and - * frees interrupt. + * This funtion is used to resume the touch panel + * controller and returns integer. */ -static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data) +static int bu21013_resume(struct i2c_client *client) { - bu21013_data->touch_stopped = true; - wake_up(&bu21013_data->wait); - free_irq(bu21013_data->chip->irq, bu21013_data); + int retval; + struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client); + + retval = bu21013_init_chip(bu21013_data); + if (retval < 0) { + dev_err(&client->dev, "tsc config failed\n"); + goto err; + } + + if (device_may_wakeup(&client->dev)) + disable_irq(bu21013_data->chip->irq); + else + enable_irq(bu21013_data->chip->irq); + + return 0; +err: + kfree(bu21013_data); + return retval; } +#endif /** - * bu21013_probe() - initializes the i2c-client touchscreen driver - * @client: i2c client structure pointer - * @id: i2c device id pointer + * bu21013_sysfs() - sys fs parameters + * @tp_kobj: kernel object structure pointer + * + * This function uses to initialize the sysfs for touch panel + * based on the controller number + */ +int bu21013_sysfs(struct kobject *tp_kobj , int ctrl) +{ + int retval = 0; + + tp_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); + if (tp_kobj == NULL) { + retval = -ENOMEM; + goto err; + } + if (ctrl == 1) + tp_kobj->ktype = &ktype_touchp1; + else if (ctrl == 2) + tp_kobj->ktype = &ktype_touchp2; + kobject_init(tp_kobj, tp_kobj->ktype); + if (ctrl == 1) + retval = kobject_set_name(tp_kobj, "touchp1"); + else if (ctrl == 2) + retval = kobject_set_name(tp_kobj, "touchp2"); + if (retval) { + kfree(tp_kobj); + goto err; + } + if (ctrl == 1) + retval = kobject_add(tp_kobj, NULL, "touchp1"); + else if (ctrl == 2) + retval = kobject_add(tp_kobj, NULL, "touchp2"); + if (retval) { + kfree(tp_kobj); + goto err; + } + return 0; +err: + return retval; +} +/** + * bu21013_probe() - initialzes the i2c-client touchscreen driver + * @i2c: i2c client structure pointer + * @id:i2c device id pointer * * This function used to initializes the i2c-client touchscreen * driver and returns integer. */ -static int __devinit bu21013_probe(struct i2c_client *client, +static int bu21013_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + int retval; struct bu21013_ts_data *bu21013_data; struct input_dev *in_dev; - const struct bu21013_platform_device *pdata = - client->dev.platform_data; - int error; + short x_max; + short y_max; + struct bu21013_platform_device *pdata = i2c->dev.platform_data; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, "i2c smbus byte data not supported\n"); - return -EIO; + if (!pdata) { + dev_err(&i2c->dev, "platform data not defined\n"); + retval = -EINVAL; + return retval; } - if (!pdata) { - dev_err(&client->dev, "platform data not defined\n"); - return -EINVAL; + if (!pdata->tp_cntl) { + dev_err(&i2c->dev, "controller is not enabled\n"); + retval = -EINVAL; + return retval; } bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL); - in_dev = input_allocate_device(); - if (!bu21013_data || !in_dev) { - dev_err(&client->dev, "device memory alloc failed\n"); - error = -ENOMEM; - goto err_free_mem; + if (!bu21013_data) { + dev_err(&i2c->dev, "device memory alloc failed\n"); + retval = -ENOMEM; + return retval; } + /* allocate input device */ + in_dev = input_allocate_device(); + if (!in_dev) { + dev_err(&i2c->dev, "input device memory alloc failed\n"); + retval = -ENOMEM; + goto err_alloc; + } bu21013_data->in_dev = in_dev; + bu21013_data->chip = pdata; - bu21013_data->client = client; - bu21013_data->touch_stopped = false; - init_waitqueue_head(&bu21013_data->wait); + bu21013_data->client = i2c; + bu21013_data->penup_timer = PENUP_TIMEOUT; + + if (bu21013_data->chip->portrait) { + x_max = pdata->x_max_res; + y_max = pdata->y_max_res; + } else { + x_max = pdata->y_max_res; + y_max = pdata->x_max_res; + } + + INIT_WORK(&bu21013_data->timer_wq_handler, bu21013_timer_wq); + INIT_WORK(&bu21013_data->gpio_wq_handler, bu21013_gpio_int_wq); + + init_timer(&bu21013_data->penirq_timer); + bu21013_data->penirq_timer.data = (unsigned long)bu21013_data; + bu21013_data->penirq_timer.function = bu21013_timer_callback; + i2c_set_clientdata(i2c, bu21013_data); /* configure the gpio pins */ if (pdata->cs_en) { - error = pdata->cs_en(pdata->cs_pin); - if (error < 0) { - dev_err(&client->dev, "chip init failed\n"); - goto err_free_mem; + retval = pdata->cs_en(pdata->cs_pin); + if (retval < 0) { + dev_err(&i2c->dev, "chip init failed\n"); + goto err_init_cs; } } /* configure the touch panel controller */ - error = bu21013_init_chip(bu21013_data); - if (error) { - dev_err(&client->dev, "error in bu21013 config\n"); - goto err_cs_disable; + retval = bu21013_init_chip(bu21013_data); + if (retval < 0) { + dev_err(&i2c->dev, "error in bu21013 config\n"); + goto err_init_config; } /* register the device to input subsystem */ in_dev->name = DRIVER_TP; - in_dev->id.bustype = BUS_I2C; - in_dev->dev.parent = &client->dev; - - __set_bit(EV_SYN, in_dev->evbit); - __set_bit(EV_KEY, in_dev->evbit); - __set_bit(EV_ABS, in_dev->evbit); - - input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, - pdata->x_max_res, 0, 0); - input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, - pdata->y_max_res, 0, 0); - input_set_drvdata(in_dev, bu21013_data); - - error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq, - IRQF_TRIGGER_FALLING | IRQF_SHARED, - DRIVER_TP, bu21013_data); - if (error) { - dev_err(&client->dev, "request irq %d failed\n", pdata->irq); - goto err_cs_disable; - } - - error = input_register_device(in_dev); - if (error) { - dev_err(&client->dev, "failed to register input device\n"); - goto err_free_irq; + set_bit(EV_SYN, in_dev->evbit); + set_bit(EV_KEY, in_dev->evbit); + set_bit(EV_ABS, in_dev->evbit); + set_bit(BTN_TOUCH, in_dev->keybit); + + input_set_abs_params(in_dev, ABS_X, 0, x_max, 0, 0); + input_set_abs_params(in_dev, ABS_Y, 0, y_max, 0, 0); + input_set_abs_params(in_dev, ABS_PRESSURE, 0, MAX_PRESSURE, 0, 0); + input_set_abs_params(in_dev, ABS_TOOL_WIDTH, 0, MAX_TOOL_WIDTH, 0, 0); + + set_bit(BTN_2, in_dev->keybit); + input_set_abs_params(in_dev, ABS_HAT0X, 0, x_max, 0, 0); + input_set_abs_params(in_dev, ABS_HAT0Y, 0, y_max, 0, 0); + input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, x_max, 0, 0); + input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, y_max, 0, 0); + input_set_abs_params(in_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, + 0, 0); + input_set_abs_params + (in_dev, ABS_MT_TOUCH_MINOR, 0, MAX_TOUCH_MINOR, 0, 0); + input_set_abs_params(in_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); + input_set_abs_params(in_dev, ABS_MT_WIDTH_MAJOR, 0, MAX_TOOL_WIDTH, + 0, 0); + retval = input_register_device(in_dev); + if (retval) + goto err_input_register; + + retval = request_irq(pdata->irq, bu21013_gpio_irq, + (IRQF_TRIGGER_FALLING | IRQF_SHARED), + DRIVER_TP, bu21013_data); + if (retval) { + dev_err(&i2c->dev, "request irq %d failed\n", pdata->irq); + goto err_init_irq; } - device_init_wakeup(&client->dev, pdata->wakeup); - i2c_set_clientdata(client, bu21013_data); - - return 0; - -err_free_irq: - bu21013_free_irq(bu21013_data); -err_cs_disable: + retval = bu21013_sysfs(bu21013_data->touchp_kobj, pdata->tp_cntl); + if (retval) + goto err_init_sys; + /* + * to maintain the each device data, we are storing + * in global varaiables for tuning the touch screen + */ + if (pdata->tp_cntl == 1) + tp1_sys_data = bu21013_data; + else if (pdata->tp_cntl == 2) + tp2_sys_data = bu21013_data; + + dev_dbg(&i2c->dev, "init done"); + + return retval; +err_init_sys: + free_irq(pdata->irq, bu21013_data); +err_init_irq: + input_unregister_device(bu21013_data->in_dev); + bu21013_data->in_dev = NULL; +err_input_register: +err_init_config: pdata->cs_dis(pdata->cs_pin); -err_free_mem: +err_init_cs: + del_timer_sync(&bu21013_data->penirq_timer); + cancel_work_sync(&bu21013_data->timer_wq_handler); + cancel_work_sync(&bu21013_data->gpio_wq_handler); input_free_device(bu21013_data->in_dev); +err_alloc: kfree(bu21013_data); - - return error; + return retval; } /** * bu21013_remove() - removes the i2c-client touchscreen driver @@ -528,79 +913,25 @@ err_free_mem: */ static int __devexit bu21013_remove(struct i2c_client *client) { - struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client); + struct bu21013_ts_data *data = i2c_get_clientdata(client); - bu21013_free_irq(bu21013_data); + del_timer_sync(&data->penirq_timer); + cancel_work_sync(&data->timer_wq_handler); + cancel_work_sync(&data->gpio_wq_handler); - bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin); - - input_unregister_device(bu21013_data->in_dev); - kfree(bu21013_data); - - device_init_wakeup(&client->dev, false); - - return 0; -} - -#ifdef CONFIG_PM -/** - * bu21013_suspend() - suspend the touch screen controller - * @dev: pointer to device structure - * - * This function is used to suspend the - * touch panel controller and returns integer - */ -static int bu21013_suspend(struct device *dev) -{ - struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev); - struct i2c_client *client = bu21013_data->client; - - bu21013_data->touch_stopped = true; - if (device_may_wakeup(&client->dev)) - enable_irq_wake(bu21013_data->chip->irq); - else - disable_irq(bu21013_data->chip->irq); - - return 0; -} - -/** - * bu21013_resume() - resume the touch screen controller - * @dev: pointer to device structure - * - * This function is used to resume the touch panel - * controller and returns integer. - */ -static int bu21013_resume(struct device *dev) -{ - struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev); - struct i2c_client *client = bu21013_data->client; - int retval; - - retval = bu21013_init_chip(bu21013_data); - if (retval < 0) { - dev_err(&client->dev, "bu21013 controller config failed\n"); - return retval; + if (data->chip != NULL) { + free_irq(data->chip->irq, data); + data->chip->cs_dis(data->chip->cs_pin); } - - bu21013_data->touch_stopped = false; - - if (device_may_wakeup(&client->dev)) - disable_irq_wake(bu21013_data->chip->irq); - else - enable_irq(bu21013_data->chip->irq); + input_unregister_device(data->in_dev); + kfree(data); return 0; } -static const struct dev_pm_ops bu21013_dev_pm_ops = { - .suspend = bu21013_suspend, - .resume = bu21013_resume, -}; -#endif - static const struct i2c_device_id bu21013_id[] = { { DRIVER_TP, 0 }, + { DRIVER_TP, 0 }, { } }; MODULE_DEVICE_TABLE(i2c, bu21013_id); @@ -609,11 +940,12 @@ static struct i2c_driver bu21013_driver = { .driver = { .name = DRIVER_TP, .owner = THIS_MODULE, -#ifdef CONFIG_PM - .pm = &bu21013_dev_pm_ops, -#endif }, .probe = bu21013_probe, +#ifdef CONFIG_PM + .suspend = bu21013_suspend, + .resume = bu21013_resume, +#endif .remove = __devexit_p(bu21013_remove), .id_table = bu21013_id, }; @@ -644,5 +976,5 @@ module_init(bu21013_init); module_exit(bu21013_exit); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>"); +MODULE_AUTHOR("NAVEEN KUMAR G"); MODULE_DESCRIPTION("bu21013 touch screen controller driver"); |