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