aboutsummaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorNaveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>2010-10-27 15:00:52 +0530
committerSundar Iyer <sundar.iyer@stericsson.com>2010-11-10 17:46:32 +0530
commit48f16afca5fec6a8ad49d1d44998340fd5aafc9f (patch)
treef1cb2157535d4ba58ac4f51cce7c233b2460debb /drivers/input
parent27503066e00f4959acc2acab1bdc05855dcc2c02 (diff)
input:Improved the BU21013 touchscreen performance
Improved the ROHM BU21013 touchscreen driver performance. BU21013 driver performance is improved to max 82Hz from 40Hz. ST-Ericsson Id: ER 275284 Change-Id: I76ec3654664c7601efe423dc2ac8cf94b8e6dc89 Signed-off-by: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/7248 Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/Kconfig20
-rw-r--r--drivers/input/touchscreen/Makefile2
-rw-r--r--drivers/input/touchscreen/bu21013_ts.c839
3 files changed, 348 insertions, 513 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index a016fca4109..ae52ca3800a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -104,6 +104,17 @@ config TOUCHSCREEN_BU21013
depends on I2C
default y
help
+ Say Y here if you have a ROHM BU21013 and
+ want to enable support for the built-in touchscreen.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bu21013_ts.
+
+config TOUCHSCREEN_CORGI
+ tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)"
+ depends on PXA_SHARPSL
+ select CORGI_SSP_DEPRECATED
+ help
Say Y here if you have a bu21013 touchscreen connected to
your system.
@@ -112,15 +123,6 @@ 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/Makefile b/drivers/input/touchscreen/Makefile
index 3212ecc039e..2ff211c4a7a 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
+obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
@@ -50,4 +51,3 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
-obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
index efe1b01679f..7376d324f8c 100644
--- a/drivers/input/touchscreen/bu21013_ts.c
+++ b/drivers/input/touchscreen/bu21013_ts.c
@@ -5,76 +5,162 @@
*/
#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>
-#include <linux/regulator/consumer.h>
#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
#define PEN_DOWN_INTR 0
-#define PEN_UP_INTR 1
#define RESET_DELAY 30
-#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)/* 2msecs */
+#define PENUP_TIMEOUT 2 /* 2msecs */
#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 DRIVER_TP "bu21013_tp"
+#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_ts"
/**
* struct bu21013_ts_data - touch panel data 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
+ * @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
* @intr_pin: interrupt pin value
- * @x_pos: x position for two co-ordinates
- * @y_pos: y position for two co-ordinates
+ * @regulator: pointer to the Regulator used for touch screen
+ * @enable: variable to indicate the enable/disable of touch screen
* @factor_x: x scale factor
* @factor_y: y scale factor
- * @previous_press_reported: last reported flag
- * @penup_timer: timeout value
- * @regulator: pointer to the Regulator used for touch screen controller
* @tpclk: pointer to clock structure
- * @enable: variable to indicate the enable/disable of touch screen
*
- * Touch panel data structure
+ * Touch panel device data structure
*/
struct bu21013_ts_data {
struct i2c_client *client;
+ wait_queue_head_t wait;
+ bool touch_stopped;
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;
- int penup_timer;
struct regulator *regulator;
- struct clk *tpclk;
bool enable;
+ unsigned int factor_x;
+ unsigned int factor_y;
+ struct clk *tpclk;
};
static int bu21013_init_chip(struct bu21013_ts_data *data);
@@ -287,151 +373,31 @@ static struct attribute_group bu21013_attr_group = {
};
-/*
- * 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_report_pen_down() - reports the pen down event
- * @data:bu21013_ts_data structure pointer
- * @count:touch count
- *
- * This function used to report the pen down interrupt to
- * input subsystem and returns none
- */
-static void bu21013_report_pen_down(struct bu21013_ts_data *data, int count)
-{
- 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];
- }
-
- 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
+ * bu21013_read_block_data(): read the touch co-ordinates
* @data: bu21013_ts_data structure pointer
- * @x: x position
- * @y: y position
- * @count: touch count
+ * @buf: byte pointer
*
- * This function calculates the exact co-ordinates with respect to
- * display resolution and returns none
+ * Read the touch co-ordinates using i2c read block into buffer
+ * and returns integer.
*/
-static void bu21013_touch_calc
- (struct bu21013_ts_data *data, int x, int y, int count)
+static int bu21013_read_block_data(struct bu21013_ts_data *data, u8 *buf)
{
- 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;
+ int ret, i;
+
+ 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;
}
- return true;
+ return -EINVAL;
}
/**
* 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.
@@ -439,194 +405,91 @@ static bool bu21013_verify_delta(int x1, int y1, int x2, int y2)
static int bu21013_do_touch_report(struct bu21013_ts_data *data)
{
u8 buf[LENGTH_OF_BUFFER];
- 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;
+ unsigned int pos_x[2], pos_y[2];
+ bool has_x_sensors, has_y_sensors;
int finger_down_count = 0;
- int ret = 0;
- int retry_count = 5;
+ int i;
- if (data->client == NULL)
+ if (data == NULL)
return -EINVAL;
- 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;
+ if (bu21013_read_block_data(data, buf) < 0)
+ return -EINVAL;
- 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;
- }
- }
+ 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)
+ return 0;
- 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))
+ for (i = 0; i < 2; 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;
+ x = x * data->factor_x / SCALE_FACTOR;
+ y = y * data->factor_y / SCALE_FACTOR;
+ 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;
- if (finger1_valid) {
- bu21013_touch_calc(data, finger1_pos_x,
- finger1_pos_y, finger_down_count);
- finger_down_count++;
- }
- if (finger2_valid) {
- bu21013_touch_calc(data, finger2_pos_x,
- finger2_pos_y, finger_down_count);
- finger_down_count++;
- }
- }
-
- 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 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));
-}
+ for (i = 0; i < finger_down_count; i++) {
+ if (data->chip->portrait && data->chip->x_flip)
+ pos_x[i] = data->chip->x_max_res - pos_x[i];
+ if (data->chip->portrait && data->chip->y_flip)
+ pos_y[i] = data->chip->y_max_res - pos_y[i];
+ input_report_abs(data->in_dev, ABS_MT_TOUCH_MAJOR,
+ max(pos_x[i], 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);
+ }
+ } else
+ input_mt_sync(data->in_dev);
-/**
- * bu21013_timer_wq() - work queue for timer handler
- * @work:work_struct structure pointer
- *
- * This timer work queue used during polling of the co-ordinates
- * for every timeout period and returns none
- */
-static void bu21013_timer_wq(struct work_struct *work)
-{
- 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;
+ input_sync(data->in_dev);
- 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);
+ return 0;
}
-
/**
- * bu21013_gpio_int_wq() - work queue for gpio interrupt handler
- * @work:work_struct structure pointer
+ * bu21013_gpio_irq() - gpio thread function for touch interrupt
+ * @irq: irq value
+ * @device_data: void pointer
*
- * This gpio work queue used to get the co-ordinates
- * of the pen down interrupt and returns none
+ * This gpio thread function for touch interrupt
+ * and returns irqreturn_t.
*/
-static void bu21013_gpio_int_wq(struct work_struct *work)
+static irqreturn_t bu21013_gpio_irq(int irq, void *device_data)
{
- struct bu21013_ts_data *data =
- container_of(work, struct bu21013_ts_data, gpio_wq_handler);
+ struct bu21013_ts_data *data = device_data;
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);
+ do {
+ retval = bu21013_do_touch_report(data);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "bu21013_do_touch_report failed\n");
+ return IRQ_NONE;
+ }
+ 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(PENUP_TIMEOUT));
+ } while (!data->intr_pin && !data->touch_stopped);
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
*
@@ -642,33 +505,33 @@ 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");
- goto err;
+ return retval;
}
- mdelay(RESET_DELAY);
+ msleep(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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE2_REG,
(BU21013_POS_MODE2_ZERO | BU21013_POS_MODE2_AVG1 |
@@ -676,7 +539,7 @@ static int bu21013_init_chip(struct bu21013_ts_data *data)
BU21013_POS_MODE2_MULTI));
if (retval < 0) {
dev_err(&i2c->dev, "BU21013_POS_MODE2 reg write failed\n");
- goto err;
+ return retval;
}
if (data->chip->ext_clk)
retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
@@ -686,185 +549,125 @@ 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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_ON_REG,
- (BU21013_TH_ON_3 | BU21013_TH_ON_4));
+ BU21013_TH_ON_5);
if (retval < 0) {
dev_err(&i2c->dev, "BU21013_TH_ON reg write failed\n");
- goto err;
+ return retval;
}
retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG,
- BU21013_TH_OFF_4);
+ BU21013_TH_OFF_4 || BU21013_TH_OFF_3);
if (retval < 0) {
dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
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");
- goto err;
+ return retval;
}
- 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);
-
- bu21013_disable(bu21013_data);
-
- return 0;
-}
-
-/**
- * bu21013_resume() - resume the touch screen controller
- * @client: pointer to i2c client structure
- *
- * This funtion is used to resume the touch panel
- * controller and returns integer.
- */
-static int bu21013_resume(struct i2c_client *client)
-{
- struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
-
- return bu21013_enable(bu21013_data);
-}
-#endif
-
/**
* bu21013_probe() - initialzes the i2c-client touchscreen driver
- * @i2c: i2c client structure pointer
- * @id:i2c device id pointer
+ * @client: i2c client structure pointer
+ * @id: i2c device id pointer
*
* This function used to initializes the i2c-client touchscreen
* driver and returns integer.
*/
-static int bu21013_probe(struct i2c_client *i2c,
+static int __devinit bu21013_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int retval;
struct bu21013_ts_data *bu21013_data;
struct input_dev *in_dev;
- short x_max;
- short y_max;
-
- struct bu21013_platform_device *pdata = i2c->dev.platform_data;
+ struct bu21013_platform_device *pdata =
+ client->dev.platform_data;
- if (!pdata) {
- dev_err(&i2c->dev, "platform data not defined\n");
- retval = -EINVAL;
- return retval;
+ 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->tp_cntl) {
- dev_err(&i2c->dev, "controller is not enabled\n");
+ if (!pdata) {
+ dev_err(&client->dev, "platform data not defined\n");
retval = -EINVAL;
return retval;
}
bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL);
if (!bu21013_data) {
- dev_err(&i2c->dev, "device memory alloc failed\n");
+ dev_err(&client->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");
+ dev_err(&client->dev, "input device memory alloc failed\n");
retval = -ENOMEM;
goto err_alloc;
}
- bu21013_data->in_dev = in_dev;
+ bu21013_data->in_dev = in_dev;
bu21013_data->chip = pdata;
- 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);
+ bu21013_data->client = client;
+ dev_set_name(&client->dev, pdata->name);
- dev_set_name(&i2c->dev, pdata->name);
- bu21013_data->regulator = regulator_get(&i2c->dev, "v-touch");
+ bu21013_data->regulator = regulator_get(&client->dev, "v-touch");
if (IS_ERR(bu21013_data->regulator)) {
- dev_warn(&i2c->dev, "regulator_get failed\n");
+ dev_warn(&client->dev, "regulator_get failed\n");
bu21013_data->regulator = NULL;
}
if (bu21013_data->regulator)
@@ -874,19 +677,19 @@ static int bu21013_probe(struct i2c_client *i2c,
if (pdata->cs_en) {
retval = pdata->cs_en(pdata->cs_pin);
if (retval < 0) {
- dev_err(&i2c->dev, "chip init failed\n");
+ dev_err(&client->dev, "chip init failed\n");
goto err_init_cs;
}
}
- bu21013_data->tpclk = clk_get(&i2c->dev, NULL);
+ bu21013_data->tpclk = clk_get(&client->dev, NULL);
if (IS_ERR(bu21013_data->tpclk)) {
- dev_warn(&i2c->dev, "get extern clock failed\n");
+ dev_warn(&client->dev, "get extern clock failed\n");
bu21013_data->tpclk = NULL;
} else if (pdata->ext_clk) {
retval = clk_enable(bu21013_data->tpclk);
if (retval < 0) {
- dev_err(&i2c->dev, "clock enable failed\n");
+ dev_err(&client->dev, "clock enable failed\n");
goto err_ext_clk;
}
}
@@ -894,78 +697,78 @@ static int bu21013_probe(struct i2c_client *i2c,
/* configure the touch panel controller */
retval = bu21013_init_chip(bu21013_data);
if (retval < 0) {
- dev_err(&i2c->dev, "error in bu21013 config\n");
+ dev_err(&client->dev, "error in bu21013 config\n");
goto err_init_config;
}
+ init_waitqueue_head(&bu21013_data->wait);
+ bu21013_data->touch_stopped = false;
+
/* register the device to input subsystem */
- in_dev->name = DRIVER_TP;
- 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);
+ in_dev->name = pdata->name;
+ 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_abs_params(in_dev, ABS_MT_TOUCH_MAJOR, 0,
+ max(pdata->x_max_res , pdata->y_max_res), 0, 0);
+ input_set_drvdata(in_dev, bu21013_data);
retval = input_register_device(in_dev);
if (retval)
goto err_input_register;
- retval = request_irq(pdata->irq, bu21013_gpio_irq,
+ retval = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq,
(IRQF_TRIGGER_FALLING | IRQF_SHARED),
- DRIVER_TP, bu21013_data);
+ pdata->name, bu21013_data);
if (retval) {
- dev_err(&i2c->dev, "request irq %d failed\n", pdata->irq);
+ dev_err(&client->dev, "request irq %d failed\n", pdata->irq);
goto err_init_irq;
}
bu21013_data->enable = true;
+ i2c_set_clientdata(client, bu21013_data);
/* sysfs implementation for dynamic enable/disable the input event */
- retval = sysfs_create_group(&i2c->dev.kobj, &bu21013_attr_group);
+ retval = sysfs_create_group(&client->dev.kobj, &bu21013_attr_group);
if (retval) {
- dev_err(&i2c->dev, "failed to create sysfs entries\n");
- goto err_sysfs;
+ dev_err(&client->dev, "failed to create sysfs entries\n");
+ goto err_sysfs_create;
}
- dev_dbg(&i2c->dev, "init done");
-
return retval;
-err_sysfs:
+err_sysfs_create:
free_irq(pdata->irq, bu21013_data);
+ i2c_set_clientdata(client, NULL);
err_init_irq:
input_unregister_device(bu21013_data->in_dev);
bu21013_data->in_dev = NULL;
err_input_register:
+ wake_up(&bu21013_data->wait);
err_init_config:
if (bu21013_data->tpclk && pdata->ext_clk) {
clk_disable(bu21013_data->tpclk);
clk_put(bu21013_data->tpclk);
}
+ bu21013_data->tpclk = NULL;
err_ext_clk:
- pdata->cs_dis(pdata->cs_pin);
+ if (pdata->cs_dis)
+ pdata->cs_dis(pdata->cs_pin);
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);
+ if (bu21013_data->regulator) {
+ regulator_disable(bu21013_data->regulator);
+ regulator_put(bu21013_data->regulator);
+ }
input_free_device(bu21013_data->in_dev);
err_alloc:
kfree(bu21013_data);
+
return retval;
}
@@ -978,36 +781,67 @@ err_alloc:
*/
static int __devexit bu21013_remove(struct i2c_client *client)
{
- struct bu21013_ts_data *data = i2c_get_clientdata(client);
+ struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
+ bu21013_data->touch_stopped = true;
sysfs_remove_group(&client->dev.kobj, &bu21013_attr_group);
+ wake_up(&bu21013_data->wait);
+ free_irq(bu21013_data->chip->irq, bu21013_data);
+ bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin);
+ input_unregister_device(bu21013_data->in_dev);
- del_timer_sync(&data->penirq_timer);
- cancel_work_sync(&data->timer_wq_handler);
- cancel_work_sync(&data->gpio_wq_handler);
-
- if (data->chip != NULL) {
- free_irq(data->chip->irq, data);
- data->chip->cs_dis(data->chip->cs_pin);
- }
- input_unregister_device(data->in_dev);
-
- if (data->tpclk && data->chip->ext_clk) {
- clk_disable(data->tpclk);
- clk_put(data->tpclk);
+ if (bu21013_data->tpclk && bu21013_data->chip->ext_clk) {
+ clk_disable(bu21013_data->tpclk);
+ clk_put(bu21013_data->tpclk);
}
- if (data->regulator) {
- regulator_disable(data->regulator);
- regulator_put(data->regulator);
+ if (bu21013_data->regulator) {
+ regulator_disable(bu21013_data->regulator);
+ regulator_put(bu21013_data->regulator);
}
- kfree(data);
+ kfree(bu21013_data);
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);
+
+ bu21013_disable(bu21013_data);
+
+ 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);
+
+ return bu21013_enable(bu21013_data);
+}
+
+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);
@@ -1016,12 +850,11 @@ static struct i2c_driver bu21013_driver = {
.driver = {
.name = DRIVER_TP,
.owner = THIS_MODULE,
- },
- .probe = bu21013_probe,
#ifdef CONFIG_PM
- .suspend = bu21013_suspend,
- .resume = bu21013_resume,
+ .pm = &bu21013_dev_pm_ops,
#endif
+ },
+ .probe = bu21013_probe,
.remove = __devexit_p(bu21013_remove),
.id_table = bu21013_id,
};
@@ -1052,5 +885,5 @@ module_init(bu21013_init);
module_exit(bu21013_exit);
MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("NAVEEN KUMAR G");
+MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>");
MODULE_DESCRIPTION("bu21013 touch screen controller driver");