14780c8dfSNaveen Kumar Gaddipati /*
24780c8dfSNaveen Kumar Gaddipati  * Copyright (C) ST-Ericsson SA 2010
34780c8dfSNaveen Kumar Gaddipati  * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
44780c8dfSNaveen Kumar Gaddipati  * License terms:GNU General Public License (GPL) version 2
54780c8dfSNaveen Kumar Gaddipati  */
64780c8dfSNaveen Kumar Gaddipati 
74780c8dfSNaveen Kumar Gaddipati #include <linux/kernel.h>
84780c8dfSNaveen Kumar Gaddipati #include <linux/delay.h>
94780c8dfSNaveen Kumar Gaddipati #include <linux/interrupt.h>
104780c8dfSNaveen Kumar Gaddipati #include <linux/i2c.h>
114780c8dfSNaveen Kumar Gaddipati #include <linux/workqueue.h>
124780c8dfSNaveen Kumar Gaddipati #include <linux/input.h>
134780c8dfSNaveen Kumar Gaddipati #include <linux/input/bu21013.h>
144780c8dfSNaveen Kumar Gaddipati #include <linux/slab.h>
154780c8dfSNaveen Kumar Gaddipati 
164780c8dfSNaveen Kumar Gaddipati #define PEN_DOWN_INTR	0
174780c8dfSNaveen Kumar Gaddipati #define MAX_FINGERS	2
184780c8dfSNaveen Kumar Gaddipati #define RESET_DELAY	30
194780c8dfSNaveen Kumar Gaddipati #define PENUP_TIMEOUT	(10)
204780c8dfSNaveen Kumar Gaddipati #define DELTA_MIN	16
214780c8dfSNaveen Kumar Gaddipati #define MASK_BITS	0x03
224780c8dfSNaveen Kumar Gaddipati #define SHIFT_8		8
234780c8dfSNaveen Kumar Gaddipati #define SHIFT_2		2
244780c8dfSNaveen Kumar Gaddipati #define LENGTH_OF_BUFFER	11
254780c8dfSNaveen Kumar Gaddipati #define I2C_RETRY_COUNT	5
264780c8dfSNaveen Kumar Gaddipati 
274780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSORS_BTN_0_7_REG	0x70
284780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSORS_BTN_8_15_REG	0x71
294780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSORS_BTN_16_23_REG	0x72
304780c8dfSNaveen Kumar Gaddipati #define BU21013_X1_POS_MSB_REG		0x73
314780c8dfSNaveen Kumar Gaddipati #define BU21013_X1_POS_LSB_REG		0x74
324780c8dfSNaveen Kumar Gaddipati #define BU21013_Y1_POS_MSB_REG		0x75
334780c8dfSNaveen Kumar Gaddipati #define BU21013_Y1_POS_LSB_REG		0x76
344780c8dfSNaveen Kumar Gaddipati #define BU21013_X2_POS_MSB_REG		0x77
354780c8dfSNaveen Kumar Gaddipati #define BU21013_X2_POS_LSB_REG		0x78
364780c8dfSNaveen Kumar Gaddipati #define BU21013_Y2_POS_MSB_REG		0x79
374780c8dfSNaveen Kumar Gaddipati #define BU21013_Y2_POS_LSB_REG		0x7A
384780c8dfSNaveen Kumar Gaddipati #define BU21013_INT_CLR_REG		0xE8
394780c8dfSNaveen Kumar Gaddipati #define BU21013_INT_MODE_REG		0xE9
404780c8dfSNaveen Kumar Gaddipati #define BU21013_GAIN_REG		0xEA
414780c8dfSNaveen Kumar Gaddipati #define BU21013_OFFSET_MODE_REG		0xEB
424780c8dfSNaveen Kumar Gaddipati #define BU21013_XY_EDGE_REG		0xEC
434780c8dfSNaveen Kumar Gaddipati #define BU21013_RESET_REG		0xED
444780c8dfSNaveen Kumar Gaddipati #define BU21013_CALIB_REG		0xEE
454780c8dfSNaveen Kumar Gaddipati #define BU21013_DONE_REG		0xEF
464780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSOR_0_7_REG		0xF0
474780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSOR_8_15_REG		0xF1
484780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSOR_16_23_REG	0xF2
494780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE1_REG		0xF3
504780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE2_REG		0xF4
514780c8dfSNaveen Kumar Gaddipati #define BU21013_CLK_MODE_REG		0xF5
524780c8dfSNaveen Kumar Gaddipati #define BU21013_IDLE_REG		0xFA
534780c8dfSNaveen Kumar Gaddipati #define BU21013_FILTER_REG		0xFB
544780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_REG		0xFC
554780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_REG		0xFD
564780c8dfSNaveen Kumar Gaddipati 
574780c8dfSNaveen Kumar Gaddipati 
584780c8dfSNaveen Kumar Gaddipati #define BU21013_RESET_ENABLE		0x01
594780c8dfSNaveen Kumar Gaddipati 
604780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSORS_EN_0_7		0x3F
614780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSORS_EN_8_15		0xFC
624780c8dfSNaveen Kumar Gaddipati #define BU21013_SENSORS_EN_16_23	0x1F
634780c8dfSNaveen Kumar Gaddipati 
644780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE1_0		0x02
654780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE1_1		0x04
664780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE1_2		0x08
674780c8dfSNaveen Kumar Gaddipati 
684780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE2_ZERO		0x01
694780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE2_AVG1		0x02
704780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE2_AVG2		0x04
714780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE2_EN_XY		0x08
724780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE2_EN_RAW	0x10
734780c8dfSNaveen Kumar Gaddipati #define BU21013_POS_MODE2_MULTI		0x80
744780c8dfSNaveen Kumar Gaddipati 
754780c8dfSNaveen Kumar Gaddipati #define BU21013_CLK_MODE_DIV		0x01
764780c8dfSNaveen Kumar Gaddipati #define BU21013_CLK_MODE_EXT		0x02
774780c8dfSNaveen Kumar Gaddipati #define BU21013_CLK_MODE_CALIB		0x80
784780c8dfSNaveen Kumar Gaddipati 
794780c8dfSNaveen Kumar Gaddipati #define BU21013_IDLET_0			0x01
804780c8dfSNaveen Kumar Gaddipati #define BU21013_IDLET_1			0x02
814780c8dfSNaveen Kumar Gaddipati #define BU21013_IDLET_2			0x04
824780c8dfSNaveen Kumar Gaddipati #define BU21013_IDLET_3			0x08
834780c8dfSNaveen Kumar Gaddipati #define BU21013_IDLE_INTERMIT_EN	0x10
844780c8dfSNaveen Kumar Gaddipati 
854780c8dfSNaveen Kumar Gaddipati #define BU21013_DELTA_0_6	0x7F
864780c8dfSNaveen Kumar Gaddipati #define BU21013_FILTER_EN	0x80
874780c8dfSNaveen Kumar Gaddipati 
884780c8dfSNaveen Kumar Gaddipati #define BU21013_INT_MODE_LEVEL	0x00
894780c8dfSNaveen Kumar Gaddipati #define BU21013_INT_MODE_EDGE	0x01
904780c8dfSNaveen Kumar Gaddipati 
914780c8dfSNaveen Kumar Gaddipati #define BU21013_GAIN_0		0x01
924780c8dfSNaveen Kumar Gaddipati #define BU21013_GAIN_1		0x02
934780c8dfSNaveen Kumar Gaddipati #define BU21013_GAIN_2		0x04
944780c8dfSNaveen Kumar Gaddipati 
954780c8dfSNaveen Kumar Gaddipati #define BU21013_OFFSET_MODE_DEFAULT	0x00
964780c8dfSNaveen Kumar Gaddipati #define BU21013_OFFSET_MODE_MOVE	0x01
974780c8dfSNaveen Kumar Gaddipati #define BU21013_OFFSET_MODE_DISABLE	0x02
984780c8dfSNaveen Kumar Gaddipati 
994780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_0		0x01
1004780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_1		0x02
1014780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_2		0x04
1024780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_3		0x08
1034780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_4		0x10
1044780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_5		0x20
1054780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_6		0x40
1064780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_7		0x80
1074780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_ON_MAX	0xFF
1084780c8dfSNaveen Kumar Gaddipati 
1094780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_0	0x01
1104780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_1	0x02
1114780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_2	0x04
1124780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_3	0x08
1134780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_4	0x10
1144780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_5	0x20
1154780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_6	0x40
1164780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_7	0x80
1174780c8dfSNaveen Kumar Gaddipati #define BU21013_TH_OFF_MAX	0xFF
1184780c8dfSNaveen Kumar Gaddipati 
1194780c8dfSNaveen Kumar Gaddipati #define BU21013_X_EDGE_0	0x01
1204780c8dfSNaveen Kumar Gaddipati #define BU21013_X_EDGE_1	0x02
1214780c8dfSNaveen Kumar Gaddipati #define BU21013_X_EDGE_2	0x04
1224780c8dfSNaveen Kumar Gaddipati #define BU21013_X_EDGE_3	0x08
1234780c8dfSNaveen Kumar Gaddipati #define BU21013_Y_EDGE_0	0x10
1244780c8dfSNaveen Kumar Gaddipati #define BU21013_Y_EDGE_1	0x20
1254780c8dfSNaveen Kumar Gaddipati #define BU21013_Y_EDGE_2	0x40
1264780c8dfSNaveen Kumar Gaddipati #define BU21013_Y_EDGE_3	0x80
1274780c8dfSNaveen Kumar Gaddipati 
1284780c8dfSNaveen Kumar Gaddipati #define BU21013_DONE	0x01
1294780c8dfSNaveen Kumar Gaddipati #define BU21013_NUMBER_OF_X_SENSORS	(6)
1304780c8dfSNaveen Kumar Gaddipati #define BU21013_NUMBER_OF_Y_SENSORS	(11)
1314780c8dfSNaveen Kumar Gaddipati 
1324780c8dfSNaveen Kumar Gaddipati #define DRIVER_TP	"bu21013_tp"
1334780c8dfSNaveen Kumar Gaddipati 
1344780c8dfSNaveen Kumar Gaddipati /**
1354780c8dfSNaveen Kumar Gaddipati  * struct bu21013_ts_data - touch panel data structure
1364780c8dfSNaveen Kumar Gaddipati  * @client: pointer to the i2c client
1374780c8dfSNaveen Kumar Gaddipati  * @wait: variable to wait_queue_head_t structure
1384780c8dfSNaveen Kumar Gaddipati  * @touch_stopped: touch stop flag
1394780c8dfSNaveen Kumar Gaddipati  * @chip: pointer to the touch panel controller
1404780c8dfSNaveen Kumar Gaddipati  * @in_dev: pointer to the input device structure
1414780c8dfSNaveen Kumar Gaddipati  * @intr_pin: interrupt pin value
1424780c8dfSNaveen Kumar Gaddipati  *
1434780c8dfSNaveen Kumar Gaddipati  * Touch panel device data structure
1444780c8dfSNaveen Kumar Gaddipati  */
1454780c8dfSNaveen Kumar Gaddipati struct bu21013_ts_data {
1464780c8dfSNaveen Kumar Gaddipati 	struct i2c_client *client;
1474780c8dfSNaveen Kumar Gaddipati 	wait_queue_head_t wait;
1484780c8dfSNaveen Kumar Gaddipati 	bool touch_stopped;
1494780c8dfSNaveen Kumar Gaddipati 	const struct bu21013_platform_device *chip;
1504780c8dfSNaveen Kumar Gaddipati 	struct input_dev *in_dev;
1514780c8dfSNaveen Kumar Gaddipati 	unsigned int intr_pin;
1524780c8dfSNaveen Kumar Gaddipati };
1534780c8dfSNaveen Kumar Gaddipati 
1544780c8dfSNaveen Kumar Gaddipati /**
1554780c8dfSNaveen Kumar Gaddipati  * bu21013_read_block_data(): read the touch co-ordinates
1564780c8dfSNaveen Kumar Gaddipati  * @data: bu21013_ts_data structure pointer
1574780c8dfSNaveen Kumar Gaddipati  * @buf: byte pointer
1584780c8dfSNaveen Kumar Gaddipati  *
1594780c8dfSNaveen Kumar Gaddipati  * Read the touch co-ordinates using i2c read block into buffer
1604780c8dfSNaveen Kumar Gaddipati  * and returns integer.
1614780c8dfSNaveen Kumar Gaddipati  */
1624780c8dfSNaveen Kumar Gaddipati static int bu21013_read_block_data(struct bu21013_ts_data *data, u8 *buf)
1634780c8dfSNaveen Kumar Gaddipati {
1644780c8dfSNaveen Kumar Gaddipati 	int ret, i;
1654780c8dfSNaveen Kumar Gaddipati 
1664780c8dfSNaveen Kumar Gaddipati 	for (i = 0; i < I2C_RETRY_COUNT; i++) {
1674780c8dfSNaveen Kumar Gaddipati 		ret = i2c_smbus_read_i2c_block_data
1684780c8dfSNaveen Kumar Gaddipati 			(data->client, BU21013_SENSORS_BTN_0_7_REG,
1694780c8dfSNaveen Kumar Gaddipati 				LENGTH_OF_BUFFER, buf);
1704780c8dfSNaveen Kumar Gaddipati 		if (ret == LENGTH_OF_BUFFER)
1714780c8dfSNaveen Kumar Gaddipati 			return 0;
1724780c8dfSNaveen Kumar Gaddipati 	}
1734780c8dfSNaveen Kumar Gaddipati 	return -EINVAL;
1744780c8dfSNaveen Kumar Gaddipati }
1754780c8dfSNaveen Kumar Gaddipati 
1764780c8dfSNaveen Kumar Gaddipati /**
1774780c8dfSNaveen Kumar Gaddipati  * bu21013_do_touch_report(): Get the touch co-ordinates
1784780c8dfSNaveen Kumar Gaddipati  * @data: bu21013_ts_data structure pointer
1794780c8dfSNaveen Kumar Gaddipati  *
1804780c8dfSNaveen Kumar Gaddipati  * Get the touch co-ordinates from touch sensor registers and writes
1814780c8dfSNaveen Kumar Gaddipati  * into device structure and returns integer.
1824780c8dfSNaveen Kumar Gaddipati  */
1834780c8dfSNaveen Kumar Gaddipati static int bu21013_do_touch_report(struct bu21013_ts_data *data)
1844780c8dfSNaveen Kumar Gaddipati {
1854780c8dfSNaveen Kumar Gaddipati 	u8	buf[LENGTH_OF_BUFFER];
1864780c8dfSNaveen Kumar Gaddipati 	unsigned int pos_x[2], pos_y[2];
1874780c8dfSNaveen Kumar Gaddipati 	bool	has_x_sensors, has_y_sensors;
1884780c8dfSNaveen Kumar Gaddipati 	int	finger_down_count = 0;
1894780c8dfSNaveen Kumar Gaddipati 	int	i;
1904780c8dfSNaveen Kumar Gaddipati 
1914780c8dfSNaveen Kumar Gaddipati 	if (data == NULL)
1924780c8dfSNaveen Kumar Gaddipati 		return -EINVAL;
1934780c8dfSNaveen Kumar Gaddipati 
1944780c8dfSNaveen Kumar Gaddipati 	if (bu21013_read_block_data(data, buf) < 0)
1954780c8dfSNaveen Kumar Gaddipati 		return -EINVAL;
1964780c8dfSNaveen Kumar Gaddipati 
1974780c8dfSNaveen Kumar Gaddipati 	has_x_sensors = hweight32(buf[0] & BU21013_SENSORS_EN_0_7);
1984780c8dfSNaveen Kumar Gaddipati 	has_y_sensors = hweight32(((buf[1] & BU21013_SENSORS_EN_8_15) |
1994780c8dfSNaveen Kumar Gaddipati 		((buf[2] & BU21013_SENSORS_EN_16_23) << SHIFT_8)) >> SHIFT_2);
2004780c8dfSNaveen Kumar Gaddipati 	if (!has_x_sensors || !has_y_sensors)
2014780c8dfSNaveen Kumar Gaddipati 		return 0;
2024780c8dfSNaveen Kumar Gaddipati 
2034780c8dfSNaveen Kumar Gaddipati 	for (i = 0; i < MAX_FINGERS; i++) {
2044780c8dfSNaveen Kumar Gaddipati 		const u8 *p = &buf[4 * i + 3];
2054780c8dfSNaveen Kumar Gaddipati 		unsigned int x = p[0] << SHIFT_2 | (p[1] & MASK_BITS);
2064780c8dfSNaveen Kumar Gaddipati 		unsigned int y = p[2] << SHIFT_2 | (p[3] & MASK_BITS);
2074780c8dfSNaveen Kumar Gaddipati 		if (x == 0 || y == 0)
2084780c8dfSNaveen Kumar Gaddipati 			continue;
2094780c8dfSNaveen Kumar Gaddipati 		pos_x[finger_down_count] = x;
2104780c8dfSNaveen Kumar Gaddipati 		pos_y[finger_down_count] = y;
2114780c8dfSNaveen Kumar Gaddipati 		finger_down_count++;
2124780c8dfSNaveen Kumar Gaddipati 	}
2134780c8dfSNaveen Kumar Gaddipati 
2144780c8dfSNaveen Kumar Gaddipati 	if (finger_down_count) {
2154780c8dfSNaveen Kumar Gaddipati 		if (finger_down_count == 2 &&
2164780c8dfSNaveen Kumar Gaddipati 		    (abs(pos_x[0] - pos_x[1]) < DELTA_MIN ||
2174780c8dfSNaveen Kumar Gaddipati 		     abs(pos_y[0] - pos_y[1]) < DELTA_MIN)) {
2184780c8dfSNaveen Kumar Gaddipati 			return 0;
2194780c8dfSNaveen Kumar Gaddipati 		}
2204780c8dfSNaveen Kumar Gaddipati 
2214780c8dfSNaveen Kumar Gaddipati 		for (i = 0; i < finger_down_count; i++) {
2224780c8dfSNaveen Kumar Gaddipati 			if (data->chip->x_flip)
2234780c8dfSNaveen Kumar Gaddipati 				pos_x[i] = data->chip->touch_x_max - pos_x[i];
2244780c8dfSNaveen Kumar Gaddipati 			if (data->chip->y_flip)
2254780c8dfSNaveen Kumar Gaddipati 				pos_y[i] = data->chip->touch_y_max - pos_y[i];
2264780c8dfSNaveen Kumar Gaddipati 
2274780c8dfSNaveen Kumar Gaddipati 			input_report_abs(data->in_dev,
2284780c8dfSNaveen Kumar Gaddipati 					 ABS_MT_POSITION_X, pos_x[i]);
2294780c8dfSNaveen Kumar Gaddipati 			input_report_abs(data->in_dev,
2304780c8dfSNaveen Kumar Gaddipati 					 ABS_MT_POSITION_Y, pos_y[i]);
2314780c8dfSNaveen Kumar Gaddipati 			input_mt_sync(data->in_dev);
2324780c8dfSNaveen Kumar Gaddipati 		}
2334780c8dfSNaveen Kumar Gaddipati 	} else
2344780c8dfSNaveen Kumar Gaddipati 		input_mt_sync(data->in_dev);
2354780c8dfSNaveen Kumar Gaddipati 
2364780c8dfSNaveen Kumar Gaddipati 	input_sync(data->in_dev);
2374780c8dfSNaveen Kumar Gaddipati 
2384780c8dfSNaveen Kumar Gaddipati 	return 0;
2394780c8dfSNaveen Kumar Gaddipati }
2404780c8dfSNaveen Kumar Gaddipati /**
2414780c8dfSNaveen Kumar Gaddipati  * bu21013_gpio_irq() - gpio thread function for touch interrupt
2424780c8dfSNaveen Kumar Gaddipati  * @irq: irq value
2434780c8dfSNaveen Kumar Gaddipati  * @device_data: void pointer
2444780c8dfSNaveen Kumar Gaddipati  *
2454780c8dfSNaveen Kumar Gaddipati  * This gpio thread function for touch interrupt
2464780c8dfSNaveen Kumar Gaddipati  * and returns irqreturn_t.
2474780c8dfSNaveen Kumar Gaddipati  */
2484780c8dfSNaveen Kumar Gaddipati static irqreturn_t bu21013_gpio_irq(int irq, void *device_data)
2494780c8dfSNaveen Kumar Gaddipati {
2504780c8dfSNaveen Kumar Gaddipati 	struct bu21013_ts_data *data = device_data;
2514780c8dfSNaveen Kumar Gaddipati 	struct i2c_client *i2c = data->client;
2524780c8dfSNaveen Kumar Gaddipati 	int retval;
2534780c8dfSNaveen Kumar Gaddipati 
2544780c8dfSNaveen Kumar Gaddipati 	do {
2554780c8dfSNaveen Kumar Gaddipati 		retval = bu21013_do_touch_report(data);
2564780c8dfSNaveen Kumar Gaddipati 		if (retval < 0) {
2574780c8dfSNaveen Kumar Gaddipati 			dev_err(&i2c->dev, "bu21013_do_touch_report failed\n");
2584780c8dfSNaveen Kumar Gaddipati 			return IRQ_NONE;
2594780c8dfSNaveen Kumar Gaddipati 		}
2604780c8dfSNaveen Kumar Gaddipati 
2614780c8dfSNaveen Kumar Gaddipati 		data->intr_pin = data->chip->irq_read_val();
2624780c8dfSNaveen Kumar Gaddipati 		if (data->intr_pin == PEN_DOWN_INTR)
2634780c8dfSNaveen Kumar Gaddipati 			wait_event_timeout(data->wait, data->touch_stopped,
2644780c8dfSNaveen Kumar Gaddipati 					   msecs_to_jiffies(2));
2654780c8dfSNaveen Kumar Gaddipati 	} while (!data->intr_pin && !data->touch_stopped);
2664780c8dfSNaveen Kumar Gaddipati 
2674780c8dfSNaveen Kumar Gaddipati 	return IRQ_HANDLED;
2684780c8dfSNaveen Kumar Gaddipati }
2694780c8dfSNaveen Kumar Gaddipati 
2704780c8dfSNaveen Kumar Gaddipati /**
2714780c8dfSNaveen Kumar Gaddipati  * bu21013_init_chip() - power on sequence for the bu21013 controller
2724780c8dfSNaveen Kumar Gaddipati  * @data: device structure pointer
2734780c8dfSNaveen Kumar Gaddipati  *
2744780c8dfSNaveen Kumar Gaddipati  * This function is used to power on
2754780c8dfSNaveen Kumar Gaddipati  * the bu21013 controller and returns integer.
2764780c8dfSNaveen Kumar Gaddipati  */
2774780c8dfSNaveen Kumar Gaddipati static int bu21013_init_chip(struct bu21013_ts_data *data)
2784780c8dfSNaveen Kumar Gaddipati {
2794780c8dfSNaveen Kumar Gaddipati 	int retval;
2804780c8dfSNaveen Kumar Gaddipati 	struct i2c_client *i2c = data->client;
2814780c8dfSNaveen Kumar Gaddipati 
2824780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_RESET_REG,
2834780c8dfSNaveen Kumar Gaddipati 					BU21013_RESET_ENABLE);
2844780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
2854780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_RESET reg write failed\n");
2864780c8dfSNaveen Kumar Gaddipati 		return retval;
2874780c8dfSNaveen Kumar Gaddipati 	}
2884780c8dfSNaveen Kumar Gaddipati 	msleep(RESET_DELAY);
2894780c8dfSNaveen Kumar Gaddipati 
2904780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_0_7_REG,
2914780c8dfSNaveen Kumar Gaddipati 					BU21013_SENSORS_EN_0_7);
2924780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
2934780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_SENSOR_0_7 reg write failed\n");
2944780c8dfSNaveen Kumar Gaddipati 		return retval;
2954780c8dfSNaveen Kumar Gaddipati 	}
2964780c8dfSNaveen Kumar Gaddipati 
2974780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_8_15_REG,
2984780c8dfSNaveen Kumar Gaddipati 						BU21013_SENSORS_EN_8_15);
2994780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3004780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_SENSOR_8_15 reg write failed\n");
3014780c8dfSNaveen Kumar Gaddipati 		return retval;
3024780c8dfSNaveen Kumar Gaddipati 	}
3034780c8dfSNaveen Kumar Gaddipati 
3044780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_16_23_REG,
3054780c8dfSNaveen Kumar Gaddipati 						BU21013_SENSORS_EN_16_23);
3064780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3074780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_SENSOR_16_23 reg write failed\n");
3084780c8dfSNaveen Kumar Gaddipati 		return retval;
3094780c8dfSNaveen Kumar Gaddipati 	}
3104780c8dfSNaveen Kumar Gaddipati 
3114780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE1_REG,
3124780c8dfSNaveen Kumar Gaddipati 				(BU21013_POS_MODE1_0 | BU21013_POS_MODE1_1));
3134780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3144780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_POS_MODE1 reg write failed\n");
3154780c8dfSNaveen Kumar Gaddipati 		return retval;
3164780c8dfSNaveen Kumar Gaddipati 	}
3174780c8dfSNaveen Kumar Gaddipati 
3184780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE2_REG,
3194780c8dfSNaveen Kumar Gaddipati 			(BU21013_POS_MODE2_ZERO | BU21013_POS_MODE2_AVG1 |
3204780c8dfSNaveen Kumar Gaddipati 			BU21013_POS_MODE2_AVG2 | BU21013_POS_MODE2_EN_RAW |
3214780c8dfSNaveen Kumar Gaddipati 			BU21013_POS_MODE2_MULTI));
3224780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3234780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_POS_MODE2 reg write failed\n");
3244780c8dfSNaveen Kumar Gaddipati 		return retval;
3254780c8dfSNaveen Kumar Gaddipati 	}
3264780c8dfSNaveen Kumar Gaddipati 
3274780c8dfSNaveen Kumar Gaddipati 	if (data->chip->ext_clk)
3284780c8dfSNaveen Kumar Gaddipati 		retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
3294780c8dfSNaveen Kumar Gaddipati 			(BU21013_CLK_MODE_EXT | BU21013_CLK_MODE_CALIB));
3304780c8dfSNaveen Kumar Gaddipati 	else
3314780c8dfSNaveen Kumar Gaddipati 		retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
3324780c8dfSNaveen Kumar Gaddipati 			(BU21013_CLK_MODE_DIV | BU21013_CLK_MODE_CALIB));
3334780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3344780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_CLK_MODE reg write failed\n");
3354780c8dfSNaveen Kumar Gaddipati 		return retval;
3364780c8dfSNaveen Kumar Gaddipati 	}
3374780c8dfSNaveen Kumar Gaddipati 
3384780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_IDLE_REG,
3394780c8dfSNaveen Kumar Gaddipati 				(BU21013_IDLET_0 | BU21013_IDLE_INTERMIT_EN));
3404780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3414780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_IDLE reg write failed\n");
3424780c8dfSNaveen Kumar Gaddipati 		return retval;
3434780c8dfSNaveen Kumar Gaddipati 	}
3444780c8dfSNaveen Kumar Gaddipati 
3454780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_MODE_REG,
3464780c8dfSNaveen Kumar Gaddipati 						BU21013_INT_MODE_LEVEL);
3474780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3484780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_INT_MODE reg write failed\n");
3494780c8dfSNaveen Kumar Gaddipati 		return retval;
3504780c8dfSNaveen Kumar Gaddipati 	}
3514780c8dfSNaveen Kumar Gaddipati 
3524780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_FILTER_REG,
3534780c8dfSNaveen Kumar Gaddipati 						(BU21013_DELTA_0_6 |
3544780c8dfSNaveen Kumar Gaddipati 							BU21013_FILTER_EN));
3554780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3564780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_FILTER reg write failed\n");
3574780c8dfSNaveen Kumar Gaddipati 		return retval;
3584780c8dfSNaveen Kumar Gaddipati 	}
3594780c8dfSNaveen Kumar Gaddipati 
3604780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_ON_REG,
3614780c8dfSNaveen Kumar Gaddipati 					BU21013_TH_ON_5);
3624780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3634780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_TH_ON reg write failed\n");
3644780c8dfSNaveen Kumar Gaddipati 		return retval;
3654780c8dfSNaveen Kumar Gaddipati 	}
3664780c8dfSNaveen Kumar Gaddipati 
3674780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG,
3684780c8dfSNaveen Kumar Gaddipati 				BU21013_TH_OFF_4 || BU21013_TH_OFF_3);
3694780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3704780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n");
3714780c8dfSNaveen Kumar Gaddipati 		return retval;
3724780c8dfSNaveen Kumar Gaddipati 	}
3734780c8dfSNaveen Kumar Gaddipati 
3744780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_GAIN_REG,
3754780c8dfSNaveen Kumar Gaddipati 					(BU21013_GAIN_0 | BU21013_GAIN_1));
3764780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3774780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_GAIN reg write failed\n");
3784780c8dfSNaveen Kumar Gaddipati 		return retval;
3794780c8dfSNaveen Kumar Gaddipati 	}
3804780c8dfSNaveen Kumar Gaddipati 
3814780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_OFFSET_MODE_REG,
3824780c8dfSNaveen Kumar Gaddipati 					BU21013_OFFSET_MODE_DEFAULT);
3834780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3844780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_OFFSET_MODE reg write failed\n");
3854780c8dfSNaveen Kumar Gaddipati 		return retval;
3864780c8dfSNaveen Kumar Gaddipati 	}
3874780c8dfSNaveen Kumar Gaddipati 
3884780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_XY_EDGE_REG,
3894780c8dfSNaveen Kumar Gaddipati 				(BU21013_X_EDGE_0 | BU21013_X_EDGE_2 |
3904780c8dfSNaveen Kumar Gaddipati 				BU21013_Y_EDGE_1 | BU21013_Y_EDGE_3));
3914780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3924780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_XY_EDGE reg write failed\n");
3934780c8dfSNaveen Kumar Gaddipati 		return retval;
3944780c8dfSNaveen Kumar Gaddipati 	}
3954780c8dfSNaveen Kumar Gaddipati 
3964780c8dfSNaveen Kumar Gaddipati 	retval = i2c_smbus_write_byte_data(i2c, BU21013_DONE_REG,
3974780c8dfSNaveen Kumar Gaddipati 							BU21013_DONE);
3984780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
3994780c8dfSNaveen Kumar Gaddipati 		dev_err(&i2c->dev, "BU21013_REG_DONE reg write failed\n");
4004780c8dfSNaveen Kumar Gaddipati 		return retval;
4014780c8dfSNaveen Kumar Gaddipati 	}
4024780c8dfSNaveen Kumar Gaddipati 
4034780c8dfSNaveen Kumar Gaddipati 	return 0;
4044780c8dfSNaveen Kumar Gaddipati }
4054780c8dfSNaveen Kumar Gaddipati 
4064780c8dfSNaveen Kumar Gaddipati /**
4074780c8dfSNaveen Kumar Gaddipati  * bu21013_free_irq() - frees IRQ registered for touchscreen
4084780c8dfSNaveen Kumar Gaddipati  * @bu21013_data: device structure pointer
4094780c8dfSNaveen Kumar Gaddipati  *
4104780c8dfSNaveen Kumar Gaddipati  * This function signals interrupt thread to stop processing and
4114780c8dfSNaveen Kumar Gaddipati  * frees interrupt.
4124780c8dfSNaveen Kumar Gaddipati  */
4134780c8dfSNaveen Kumar Gaddipati static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)
4144780c8dfSNaveen Kumar Gaddipati {
4154780c8dfSNaveen Kumar Gaddipati 	bu21013_data->touch_stopped = true;
4164780c8dfSNaveen Kumar Gaddipati 	wake_up(&bu21013_data->wait);
4174780c8dfSNaveen Kumar Gaddipati 	free_irq(bu21013_data->chip->irq, bu21013_data);
4184780c8dfSNaveen Kumar Gaddipati }
4194780c8dfSNaveen Kumar Gaddipati 
4204780c8dfSNaveen Kumar Gaddipati /**
4214780c8dfSNaveen Kumar Gaddipati  * bu21013_probe() - initializes the i2c-client touchscreen driver
4224780c8dfSNaveen Kumar Gaddipati  * @client: i2c client structure pointer
4234780c8dfSNaveen Kumar Gaddipati  * @id: i2c device id pointer
4244780c8dfSNaveen Kumar Gaddipati  *
4254780c8dfSNaveen Kumar Gaddipati  * This function used to initializes the i2c-client touchscreen
4264780c8dfSNaveen Kumar Gaddipati  * driver and returns integer.
4274780c8dfSNaveen Kumar Gaddipati  */
4284780c8dfSNaveen Kumar Gaddipati static int __devinit bu21013_probe(struct i2c_client *client,
4294780c8dfSNaveen Kumar Gaddipati 					const struct i2c_device_id *id)
4304780c8dfSNaveen Kumar Gaddipati {
4314780c8dfSNaveen Kumar Gaddipati 	struct bu21013_ts_data *bu21013_data;
4324780c8dfSNaveen Kumar Gaddipati 	struct input_dev *in_dev;
4334780c8dfSNaveen Kumar Gaddipati 	const struct bu21013_platform_device *pdata =
4344780c8dfSNaveen Kumar Gaddipati 					client->dev.platform_data;
4354780c8dfSNaveen Kumar Gaddipati 	int error;
4364780c8dfSNaveen Kumar Gaddipati 
4374780c8dfSNaveen Kumar Gaddipati 	if (!i2c_check_functionality(client->adapter,
4384780c8dfSNaveen Kumar Gaddipati 					I2C_FUNC_SMBUS_BYTE_DATA)) {
4394780c8dfSNaveen Kumar Gaddipati 		dev_err(&client->dev, "i2c smbus byte data not supported\n");
4404780c8dfSNaveen Kumar Gaddipati 		return -EIO;
4414780c8dfSNaveen Kumar Gaddipati 	}
4424780c8dfSNaveen Kumar Gaddipati 
4434780c8dfSNaveen Kumar Gaddipati 	if (!pdata) {
4444780c8dfSNaveen Kumar Gaddipati 		dev_err(&client->dev, "platform data not defined\n");
4454780c8dfSNaveen Kumar Gaddipati 		return -EINVAL;
4464780c8dfSNaveen Kumar Gaddipati 	}
4474780c8dfSNaveen Kumar Gaddipati 
4484780c8dfSNaveen Kumar Gaddipati 	bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL);
4494780c8dfSNaveen Kumar Gaddipati 	in_dev = input_allocate_device();
4504780c8dfSNaveen Kumar Gaddipati 	if (!bu21013_data || !in_dev) {
4514780c8dfSNaveen Kumar Gaddipati 		dev_err(&client->dev, "device memory alloc failed\n");
4524780c8dfSNaveen Kumar Gaddipati 		error = -ENOMEM;
4534780c8dfSNaveen Kumar Gaddipati 		goto err_free_mem;
4544780c8dfSNaveen Kumar Gaddipati 	}
4554780c8dfSNaveen Kumar Gaddipati 
4564780c8dfSNaveen Kumar Gaddipati 	bu21013_data->in_dev = in_dev;
4574780c8dfSNaveen Kumar Gaddipati 	bu21013_data->chip = pdata;
4584780c8dfSNaveen Kumar Gaddipati 	bu21013_data->client = client;
4594780c8dfSNaveen Kumar Gaddipati 	bu21013_data->touch_stopped = false;
4604780c8dfSNaveen Kumar Gaddipati 	init_waitqueue_head(&bu21013_data->wait);
4614780c8dfSNaveen Kumar Gaddipati 
4624780c8dfSNaveen Kumar Gaddipati 	/* configure the gpio pins */
4634780c8dfSNaveen Kumar Gaddipati 	if (pdata->cs_en) {
4644780c8dfSNaveen Kumar Gaddipati 		error = pdata->cs_en(pdata->cs_pin);
4654780c8dfSNaveen Kumar Gaddipati 		if (error < 0) {
4664780c8dfSNaveen Kumar Gaddipati 			dev_err(&client->dev, "chip init failed\n");
4674780c8dfSNaveen Kumar Gaddipati 			goto err_free_mem;
4684780c8dfSNaveen Kumar Gaddipati 		}
4694780c8dfSNaveen Kumar Gaddipati 	}
4704780c8dfSNaveen Kumar Gaddipati 
4714780c8dfSNaveen Kumar Gaddipati 	/* configure the touch panel controller */
4724780c8dfSNaveen Kumar Gaddipati 	error = bu21013_init_chip(bu21013_data);
4734780c8dfSNaveen Kumar Gaddipati 	if (error) {
4744780c8dfSNaveen Kumar Gaddipati 		dev_err(&client->dev, "error in bu21013 config\n");
4754780c8dfSNaveen Kumar Gaddipati 		goto err_cs_disable;
4764780c8dfSNaveen Kumar Gaddipati 	}
4774780c8dfSNaveen Kumar Gaddipati 
4784780c8dfSNaveen Kumar Gaddipati 	/* register the device to input subsystem */
4794780c8dfSNaveen Kumar Gaddipati 	in_dev->name = DRIVER_TP;
4804780c8dfSNaveen Kumar Gaddipati 	in_dev->id.bustype = BUS_I2C;
4814780c8dfSNaveen Kumar Gaddipati 	in_dev->dev.parent = &client->dev;
4824780c8dfSNaveen Kumar Gaddipati 
4834780c8dfSNaveen Kumar Gaddipati 	__set_bit(EV_SYN, in_dev->evbit);
4844780c8dfSNaveen Kumar Gaddipati 	__set_bit(EV_KEY, in_dev->evbit);
4854780c8dfSNaveen Kumar Gaddipati 	__set_bit(EV_ABS, in_dev->evbit);
4864780c8dfSNaveen Kumar Gaddipati 
4874780c8dfSNaveen Kumar Gaddipati 	input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0,
4884780c8dfSNaveen Kumar Gaddipati 						pdata->x_max_res, 0, 0);
4894780c8dfSNaveen Kumar Gaddipati 	input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0,
4904780c8dfSNaveen Kumar Gaddipati 						pdata->y_max_res, 0, 0);
4914780c8dfSNaveen Kumar Gaddipati 	input_set_drvdata(in_dev, bu21013_data);
4924780c8dfSNaveen Kumar Gaddipati 
4934780c8dfSNaveen Kumar Gaddipati 	error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq,
4944780c8dfSNaveen Kumar Gaddipati 				     IRQF_TRIGGER_FALLING | IRQF_SHARED,
4954780c8dfSNaveen Kumar Gaddipati 				     DRIVER_TP, bu21013_data);
4964780c8dfSNaveen Kumar Gaddipati 	if (error) {
4974780c8dfSNaveen Kumar Gaddipati 		dev_err(&client->dev, "request irq %d failed\n", pdata->irq);
4984780c8dfSNaveen Kumar Gaddipati 		goto err_cs_disable;
4994780c8dfSNaveen Kumar Gaddipati 	}
5004780c8dfSNaveen Kumar Gaddipati 
5014780c8dfSNaveen Kumar Gaddipati 	error = input_register_device(in_dev);
5024780c8dfSNaveen Kumar Gaddipati 	if (error) {
5034780c8dfSNaveen Kumar Gaddipati 		dev_err(&client->dev, "failed to register input device\n");
5044780c8dfSNaveen Kumar Gaddipati 		goto err_free_irq;
5054780c8dfSNaveen Kumar Gaddipati 	}
5064780c8dfSNaveen Kumar Gaddipati 
5074780c8dfSNaveen Kumar Gaddipati 	device_init_wakeup(&client->dev, pdata->wakeup);
5084780c8dfSNaveen Kumar Gaddipati 	i2c_set_clientdata(client, bu21013_data);
5094780c8dfSNaveen Kumar Gaddipati 
5104780c8dfSNaveen Kumar Gaddipati 	return 0;
5114780c8dfSNaveen Kumar Gaddipati 
5124780c8dfSNaveen Kumar Gaddipati err_free_irq:
5134780c8dfSNaveen Kumar Gaddipati 	bu21013_free_irq(bu21013_data);
5144780c8dfSNaveen Kumar Gaddipati err_cs_disable:
5154780c8dfSNaveen Kumar Gaddipati 	pdata->cs_dis(pdata->cs_pin);
5164780c8dfSNaveen Kumar Gaddipati err_free_mem:
5174780c8dfSNaveen Kumar Gaddipati 	input_free_device(bu21013_data->in_dev);
5184780c8dfSNaveen Kumar Gaddipati 	kfree(bu21013_data);
5194780c8dfSNaveen Kumar Gaddipati 
5204780c8dfSNaveen Kumar Gaddipati 	return error;
5214780c8dfSNaveen Kumar Gaddipati }
5224780c8dfSNaveen Kumar Gaddipati /**
5234780c8dfSNaveen Kumar Gaddipati  * bu21013_remove() - removes the i2c-client touchscreen driver
5244780c8dfSNaveen Kumar Gaddipati  * @client: i2c client structure pointer
5254780c8dfSNaveen Kumar Gaddipati  *
5264780c8dfSNaveen Kumar Gaddipati  * This function uses to remove the i2c-client
5274780c8dfSNaveen Kumar Gaddipati  * touchscreen driver and returns integer.
5284780c8dfSNaveen Kumar Gaddipati  */
5294780c8dfSNaveen Kumar Gaddipati static int __devexit bu21013_remove(struct i2c_client *client)
5304780c8dfSNaveen Kumar Gaddipati {
5314780c8dfSNaveen Kumar Gaddipati 	struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
5324780c8dfSNaveen Kumar Gaddipati 
5334780c8dfSNaveen Kumar Gaddipati 	bu21013_free_irq(bu21013_data);
5344780c8dfSNaveen Kumar Gaddipati 
5354780c8dfSNaveen Kumar Gaddipati 	bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin);
5364780c8dfSNaveen Kumar Gaddipati 
5374780c8dfSNaveen Kumar Gaddipati 	input_unregister_device(bu21013_data->in_dev);
5384780c8dfSNaveen Kumar Gaddipati 	kfree(bu21013_data);
5394780c8dfSNaveen Kumar Gaddipati 
5404780c8dfSNaveen Kumar Gaddipati 	device_init_wakeup(&client->dev, false);
5414780c8dfSNaveen Kumar Gaddipati 
5424780c8dfSNaveen Kumar Gaddipati 	return 0;
5434780c8dfSNaveen Kumar Gaddipati }
5444780c8dfSNaveen Kumar Gaddipati 
5454780c8dfSNaveen Kumar Gaddipati #ifdef CONFIG_PM
5464780c8dfSNaveen Kumar Gaddipati /**
5474780c8dfSNaveen Kumar Gaddipati  * bu21013_suspend() - suspend the touch screen controller
5484780c8dfSNaveen Kumar Gaddipati  * @dev: pointer to device structure
5494780c8dfSNaveen Kumar Gaddipati  *
5504780c8dfSNaveen Kumar Gaddipati  * This function is used to suspend the
5514780c8dfSNaveen Kumar Gaddipati  * touch panel controller and returns integer
5524780c8dfSNaveen Kumar Gaddipati  */
5534780c8dfSNaveen Kumar Gaddipati static int bu21013_suspend(struct device *dev)
5544780c8dfSNaveen Kumar Gaddipati {
5554780c8dfSNaveen Kumar Gaddipati 	struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
5564780c8dfSNaveen Kumar Gaddipati 	struct i2c_client *client = bu21013_data->client;
5574780c8dfSNaveen Kumar Gaddipati 
5584780c8dfSNaveen Kumar Gaddipati 	bu21013_data->touch_stopped = true;
5594780c8dfSNaveen Kumar Gaddipati 	if (device_may_wakeup(&client->dev))
5604780c8dfSNaveen Kumar Gaddipati 		enable_irq_wake(bu21013_data->chip->irq);
5614780c8dfSNaveen Kumar Gaddipati 	else
5624780c8dfSNaveen Kumar Gaddipati 		disable_irq(bu21013_data->chip->irq);
5634780c8dfSNaveen Kumar Gaddipati 
5644780c8dfSNaveen Kumar Gaddipati 	return 0;
5654780c8dfSNaveen Kumar Gaddipati }
5664780c8dfSNaveen Kumar Gaddipati 
5674780c8dfSNaveen Kumar Gaddipati /**
5684780c8dfSNaveen Kumar Gaddipati  * bu21013_resume() - resume the touch screen controller
5694780c8dfSNaveen Kumar Gaddipati  * @dev: pointer to device structure
5704780c8dfSNaveen Kumar Gaddipati  *
5714780c8dfSNaveen Kumar Gaddipati  * This function is used to resume the touch panel
5724780c8dfSNaveen Kumar Gaddipati  * controller and returns integer.
5734780c8dfSNaveen Kumar Gaddipati  */
5744780c8dfSNaveen Kumar Gaddipati static int bu21013_resume(struct device *dev)
5754780c8dfSNaveen Kumar Gaddipati {
5764780c8dfSNaveen Kumar Gaddipati 	struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
5774780c8dfSNaveen Kumar Gaddipati 	struct i2c_client *client = bu21013_data->client;
5784780c8dfSNaveen Kumar Gaddipati 	int retval;
5794780c8dfSNaveen Kumar Gaddipati 
5804780c8dfSNaveen Kumar Gaddipati 	retval = bu21013_init_chip(bu21013_data);
5814780c8dfSNaveen Kumar Gaddipati 	if (retval < 0) {
5824780c8dfSNaveen Kumar Gaddipati 		dev_err(&client->dev, "bu21013 controller config failed\n");
5834780c8dfSNaveen Kumar Gaddipati 		return retval;
5844780c8dfSNaveen Kumar Gaddipati 	}
5854780c8dfSNaveen Kumar Gaddipati 
5864780c8dfSNaveen Kumar Gaddipati 	bu21013_data->touch_stopped = false;
5874780c8dfSNaveen Kumar Gaddipati 
5884780c8dfSNaveen Kumar Gaddipati 	if (device_may_wakeup(&client->dev))
5894780c8dfSNaveen Kumar Gaddipati 		disable_irq_wake(bu21013_data->chip->irq);
5904780c8dfSNaveen Kumar Gaddipati 	else
5914780c8dfSNaveen Kumar Gaddipati 		enable_irq(bu21013_data->chip->irq);
5924780c8dfSNaveen Kumar Gaddipati 
5934780c8dfSNaveen Kumar Gaddipati 	return 0;
5944780c8dfSNaveen Kumar Gaddipati }
5954780c8dfSNaveen Kumar Gaddipati 
5964780c8dfSNaveen Kumar Gaddipati static const struct dev_pm_ops bu21013_dev_pm_ops = {
5974780c8dfSNaveen Kumar Gaddipati 	.suspend = bu21013_suspend,
5984780c8dfSNaveen Kumar Gaddipati 	.resume  = bu21013_resume,
5994780c8dfSNaveen Kumar Gaddipati };
6004780c8dfSNaveen Kumar Gaddipati #endif
6014780c8dfSNaveen Kumar Gaddipati 
6024780c8dfSNaveen Kumar Gaddipati static const struct i2c_device_id bu21013_id[] = {
6034780c8dfSNaveen Kumar Gaddipati 	{ DRIVER_TP, 0 },
6044780c8dfSNaveen Kumar Gaddipati 	{ }
6054780c8dfSNaveen Kumar Gaddipati };
6064780c8dfSNaveen Kumar Gaddipati MODULE_DEVICE_TABLE(i2c, bu21013_id);
6074780c8dfSNaveen Kumar Gaddipati 
6084780c8dfSNaveen Kumar Gaddipati static struct i2c_driver bu21013_driver = {
6094780c8dfSNaveen Kumar Gaddipati 	.driver	= {
6104780c8dfSNaveen Kumar Gaddipati 		.name	=	DRIVER_TP,
6114780c8dfSNaveen Kumar Gaddipati 		.owner	=	THIS_MODULE,
6124780c8dfSNaveen Kumar Gaddipati #ifdef CONFIG_PM
6134780c8dfSNaveen Kumar Gaddipati 		.pm	=	&bu21013_dev_pm_ops,
6144780c8dfSNaveen Kumar Gaddipati #endif
6154780c8dfSNaveen Kumar Gaddipati 	},
6164780c8dfSNaveen Kumar Gaddipati 	.probe		=	bu21013_probe,
6174780c8dfSNaveen Kumar Gaddipati 	.remove		=	__devexit_p(bu21013_remove),
6184780c8dfSNaveen Kumar Gaddipati 	.id_table	=	bu21013_id,
6194780c8dfSNaveen Kumar Gaddipati };
6204780c8dfSNaveen Kumar Gaddipati 
6214780c8dfSNaveen Kumar Gaddipati /**
6224780c8dfSNaveen Kumar Gaddipati  * bu21013_init() - initializes the bu21013 touchscreen driver
6234780c8dfSNaveen Kumar Gaddipati  *
6244780c8dfSNaveen Kumar Gaddipati  * This function used to initializes the bu21013
6254780c8dfSNaveen Kumar Gaddipati  * touchscreen driver and returns integer.
6264780c8dfSNaveen Kumar Gaddipati  */
6274780c8dfSNaveen Kumar Gaddipati static int __init bu21013_init(void)
6284780c8dfSNaveen Kumar Gaddipati {
6294780c8dfSNaveen Kumar Gaddipati 	return i2c_add_driver(&bu21013_driver);
6304780c8dfSNaveen Kumar Gaddipati }
6314780c8dfSNaveen Kumar Gaddipati 
6324780c8dfSNaveen Kumar Gaddipati /**
6334780c8dfSNaveen Kumar Gaddipati  * bu21013_exit() - de-initializes the bu21013 touchscreen driver
6344780c8dfSNaveen Kumar Gaddipati  *
6354780c8dfSNaveen Kumar Gaddipati  * This function uses to de-initializes the bu21013
6364780c8dfSNaveen Kumar Gaddipati  * touchscreen driver and returns none.
6374780c8dfSNaveen Kumar Gaddipati  */
6384780c8dfSNaveen Kumar Gaddipati static void __exit bu21013_exit(void)
6394780c8dfSNaveen Kumar Gaddipati {
6404780c8dfSNaveen Kumar Gaddipati 	i2c_del_driver(&bu21013_driver);
6414780c8dfSNaveen Kumar Gaddipati }
6424780c8dfSNaveen Kumar Gaddipati 
6434780c8dfSNaveen Kumar Gaddipati module_init(bu21013_init);
6444780c8dfSNaveen Kumar Gaddipati module_exit(bu21013_exit);
6454780c8dfSNaveen Kumar Gaddipati 
6464780c8dfSNaveen Kumar Gaddipati MODULE_LICENSE("GPL v2");
6474780c8dfSNaveen Kumar Gaddipati MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>");
6484780c8dfSNaveen Kumar Gaddipati MODULE_DESCRIPTION("bu21013 touch screen controller driver");
649