15245db49SHeiko Stübner /* 25245db49SHeiko Stübner * Driver for AUO in-cell touchscreens 35245db49SHeiko Stübner * 45245db49SHeiko Stübner * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de> 55245db49SHeiko Stübner * 65245db49SHeiko Stübner * loosely based on auo_touch.c from Dell Streak vendor-kernel 75245db49SHeiko Stübner * 85245db49SHeiko Stübner * Copyright (c) 2008 QUALCOMM Incorporated. 95245db49SHeiko Stübner * Copyright (c) 2008 QUALCOMM USA, INC. 105245db49SHeiko Stübner * 115245db49SHeiko Stübner * 125245db49SHeiko Stübner * This software is licensed under the terms of the GNU General Public 135245db49SHeiko Stübner * License version 2, as published by the Free Software Foundation, and 145245db49SHeiko Stübner * may be copied, distributed, and modified under those terms. 155245db49SHeiko Stübner * 165245db49SHeiko Stübner * This program is distributed in the hope that it will be useful, 175245db49SHeiko Stübner * but WITHOUT ANY WARRANTY; without even the implied warranty of 185245db49SHeiko Stübner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 195245db49SHeiko Stübner * GNU General Public License for more details. 205245db49SHeiko Stübner * 215245db49SHeiko Stübner */ 225245db49SHeiko Stübner 235245db49SHeiko Stübner #include <linux/kernel.h> 245245db49SHeiko Stübner #include <linux/module.h> 255245db49SHeiko Stübner #include <linux/interrupt.h> 265245db49SHeiko Stübner #include <linux/slab.h> 275245db49SHeiko Stübner #include <linux/input.h> 285245db49SHeiko Stübner #include <linux/jiffies.h> 295245db49SHeiko Stübner #include <linux/i2c.h> 305245db49SHeiko Stübner #include <linux/mutex.h> 315245db49SHeiko Stübner #include <linux/delay.h> 325245db49SHeiko Stübner #include <linux/gpio.h> 335245db49SHeiko Stübner #include <linux/input/auo-pixcir-ts.h> 345245db49SHeiko Stübner 355245db49SHeiko Stübner /* 365245db49SHeiko Stübner * Coordinate calculation: 375245db49SHeiko Stübner * X1 = X1_LSB + X1_MSB*256 385245db49SHeiko Stübner * Y1 = Y1_LSB + Y1_MSB*256 395245db49SHeiko Stübner * X2 = X2_LSB + X2_MSB*256 405245db49SHeiko Stübner * Y2 = Y2_LSB + Y2_MSB*256 415245db49SHeiko Stübner */ 425245db49SHeiko Stübner #define AUO_PIXCIR_REG_X1_LSB 0x00 435245db49SHeiko Stübner #define AUO_PIXCIR_REG_X1_MSB 0x01 445245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y1_LSB 0x02 455245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y1_MSB 0x03 465245db49SHeiko Stübner #define AUO_PIXCIR_REG_X2_LSB 0x04 475245db49SHeiko Stübner #define AUO_PIXCIR_REG_X2_MSB 0x05 485245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y2_LSB 0x06 495245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y2_MSB 0x07 505245db49SHeiko Stübner 515245db49SHeiko Stübner #define AUO_PIXCIR_REG_STRENGTH 0x0d 525245db49SHeiko Stübner #define AUO_PIXCIR_REG_STRENGTH_X1_LSB 0x0e 535245db49SHeiko Stübner #define AUO_PIXCIR_REG_STRENGTH_X1_MSB 0x0f 545245db49SHeiko Stübner 555245db49SHeiko Stübner #define AUO_PIXCIR_REG_RAW_DATA_X 0x2b 565245db49SHeiko Stübner #define AUO_PIXCIR_REG_RAW_DATA_Y 0x4f 575245db49SHeiko Stübner 585245db49SHeiko Stübner #define AUO_PIXCIR_REG_X_SENSITIVITY 0x6f 595245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y_SENSITIVITY 0x70 605245db49SHeiko Stübner #define AUO_PIXCIR_REG_INT_SETTING 0x71 615245db49SHeiko Stübner #define AUO_PIXCIR_REG_INT_WIDTH 0x72 625245db49SHeiko Stübner #define AUO_PIXCIR_REG_POWER_MODE 0x73 635245db49SHeiko Stübner 645245db49SHeiko Stübner #define AUO_PIXCIR_REG_VERSION 0x77 655245db49SHeiko Stübner #define AUO_PIXCIR_REG_CALIBRATE 0x78 665245db49SHeiko Stübner 675245db49SHeiko Stübner #define AUO_PIXCIR_REG_TOUCHAREA_X1 0x1e 685245db49SHeiko Stübner #define AUO_PIXCIR_REG_TOUCHAREA_Y1 0x1f 695245db49SHeiko Stübner #define AUO_PIXCIR_REG_TOUCHAREA_X2 0x20 705245db49SHeiko Stübner #define AUO_PIXCIR_REG_TOUCHAREA_Y2 0x21 715245db49SHeiko Stübner 725245db49SHeiko Stübner #define AUO_PIXCIR_REG_EEPROM_CALIB_X 0x42 735245db49SHeiko Stübner #define AUO_PIXCIR_REG_EEPROM_CALIB_Y 0xad 745245db49SHeiko Stübner 755245db49SHeiko Stübner #define AUO_PIXCIR_INT_TPNUM_MASK 0xe0 765245db49SHeiko Stübner #define AUO_PIXCIR_INT_TPNUM_SHIFT 5 775245db49SHeiko Stübner #define AUO_PIXCIR_INT_RELEASE (1 << 4) 785245db49SHeiko Stübner #define AUO_PIXCIR_INT_ENABLE (1 << 3) 795245db49SHeiko Stübner #define AUO_PIXCIR_INT_POL_HIGH (1 << 2) 805245db49SHeiko Stübner #define AUO_PIXCIR_INT_MODE_MASK 0x03 815245db49SHeiko Stübner 825245db49SHeiko Stübner /* 835245db49SHeiko Stübner * Power modes: 845245db49SHeiko Stübner * active: scan speed 60Hz 855245db49SHeiko Stübner * sleep: scan speed 10Hz can be auto-activated, wakeup on 1st touch 865245db49SHeiko Stübner * deep sleep: scan speed 1Hz can only be entered or left manually. 875245db49SHeiko Stübner */ 885245db49SHeiko Stübner #define AUO_PIXCIR_POWER_ACTIVE 0x00 895245db49SHeiko Stübner #define AUO_PIXCIR_POWER_SLEEP 0x01 905245db49SHeiko Stübner #define AUO_PIXCIR_POWER_DEEP_SLEEP 0x02 915245db49SHeiko Stübner #define AUO_PIXCIR_POWER_MASK 0x03 925245db49SHeiko Stübner 935245db49SHeiko Stübner #define AUO_PIXCIR_POWER_ALLOW_SLEEP (1 << 2) 945245db49SHeiko Stübner #define AUO_PIXCIR_POWER_IDLE_TIME(ms) ((ms & 0xf) << 4) 955245db49SHeiko Stübner 965245db49SHeiko Stübner #define AUO_PIXCIR_CALIBRATE 0x03 975245db49SHeiko Stübner 985245db49SHeiko Stübner #define AUO_PIXCIR_EEPROM_CALIB_X_LEN 62 995245db49SHeiko Stübner #define AUO_PIXCIR_EEPROM_CALIB_Y_LEN 36 1005245db49SHeiko Stübner 1015245db49SHeiko Stübner #define AUO_PIXCIR_RAW_DATA_X_LEN 18 1025245db49SHeiko Stübner #define AUO_PIXCIR_RAW_DATA_Y_LEN 11 1035245db49SHeiko Stübner 1045245db49SHeiko Stübner #define AUO_PIXCIR_STRENGTH_ENABLE (1 << 0) 1055245db49SHeiko Stübner 1065245db49SHeiko Stübner /* Touchscreen absolute values */ 1075245db49SHeiko Stübner #define AUO_PIXCIR_REPORT_POINTS 2 1085245db49SHeiko Stübner #define AUO_PIXCIR_MAX_AREA 0xff 1095245db49SHeiko Stübner #define AUO_PIXCIR_PENUP_TIMEOUT_MS 10 1105245db49SHeiko Stübner 1115245db49SHeiko Stübner struct auo_pixcir_ts { 1125245db49SHeiko Stübner struct i2c_client *client; 1135245db49SHeiko Stübner struct input_dev *input; 1145245db49SHeiko Stübner char phys[32]; 1155245db49SHeiko Stübner 1165245db49SHeiko Stübner /* special handling for touch_indicate interupt mode */ 1175245db49SHeiko Stübner bool touch_ind_mode; 1185245db49SHeiko Stübner 1195245db49SHeiko Stübner wait_queue_head_t wait; 1205245db49SHeiko Stübner bool stopped; 1215245db49SHeiko Stübner }; 1225245db49SHeiko Stübner 1235245db49SHeiko Stübner struct auo_point_t { 1245245db49SHeiko Stübner int coord_x; 1255245db49SHeiko Stübner int coord_y; 1265245db49SHeiko Stübner int area_major; 1275245db49SHeiko Stübner int area_minor; 1285245db49SHeiko Stübner int orientation; 1295245db49SHeiko Stübner }; 1305245db49SHeiko Stübner 1315245db49SHeiko Stübner static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts, 1325245db49SHeiko Stübner struct auo_point_t *point) 1335245db49SHeiko Stübner { 1345245db49SHeiko Stübner struct i2c_client *client = ts->client; 1355245db49SHeiko Stübner const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; 1365245db49SHeiko Stübner uint8_t raw_coord[8]; 1375245db49SHeiko Stübner uint8_t raw_area[4]; 1385245db49SHeiko Stübner int i, ret; 1395245db49SHeiko Stübner 1405245db49SHeiko Stübner /* touch coordinates */ 1415245db49SHeiko Stübner ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_X1_LSB, 1425245db49SHeiko Stübner 8, raw_coord); 1435245db49SHeiko Stübner if (ret < 0) { 1445245db49SHeiko Stübner dev_err(&client->dev, "failed to read coordinate, %d\n", ret); 1455245db49SHeiko Stübner return ret; 1465245db49SHeiko Stübner } 1475245db49SHeiko Stübner 1485245db49SHeiko Stübner /* touch area */ 1495245db49SHeiko Stübner ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_TOUCHAREA_X1, 1505245db49SHeiko Stübner 4, raw_area); 1515245db49SHeiko Stübner if (ret < 0) { 1525245db49SHeiko Stübner dev_err(&client->dev, "could not read touch area, %d\n", ret); 1535245db49SHeiko Stübner return ret; 1545245db49SHeiko Stübner } 1555245db49SHeiko Stübner 1565245db49SHeiko Stübner for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) { 1575245db49SHeiko Stübner point[i].coord_x = 1585245db49SHeiko Stübner raw_coord[4 * i + 1] << 8 | raw_coord[4 * i]; 1595245db49SHeiko Stübner point[i].coord_y = 1605245db49SHeiko Stübner raw_coord[4 * i + 3] << 8 | raw_coord[4 * i + 2]; 1615245db49SHeiko Stübner 1625245db49SHeiko Stübner if (point[i].coord_x > pdata->x_max || 1635245db49SHeiko Stübner point[i].coord_y > pdata->y_max) { 1645245db49SHeiko Stübner dev_warn(&client->dev, "coordinates (%d,%d) invalid\n", 1655245db49SHeiko Stübner point[i].coord_x, point[i].coord_y); 1665245db49SHeiko Stübner point[i].coord_x = point[i].coord_y = 0; 1675245db49SHeiko Stübner } 1685245db49SHeiko Stübner 1695245db49SHeiko Stübner /* determine touch major, minor and orientation */ 1705245db49SHeiko Stübner point[i].area_major = max(raw_area[2 * i], raw_area[2 * i + 1]); 1715245db49SHeiko Stübner point[i].area_minor = min(raw_area[2 * i], raw_area[2 * i + 1]); 1725245db49SHeiko Stübner point[i].orientation = raw_area[2 * i] > raw_area[2 * i + 1]; 1735245db49SHeiko Stübner } 1745245db49SHeiko Stübner 1755245db49SHeiko Stübner return 0; 1765245db49SHeiko Stübner } 1775245db49SHeiko Stübner 1785245db49SHeiko Stübner static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id) 1795245db49SHeiko Stübner { 1805245db49SHeiko Stübner struct auo_pixcir_ts *ts = dev_id; 1815245db49SHeiko Stübner struct i2c_client *client = ts->client; 1825245db49SHeiko Stübner const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; 1835245db49SHeiko Stübner struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS]; 1845245db49SHeiko Stübner int i; 1855245db49SHeiko Stübner int ret; 1865245db49SHeiko Stübner int fingers = 0; 1875245db49SHeiko Stübner int abs = -1; 1885245db49SHeiko Stübner 1895245db49SHeiko Stübner while (!ts->stopped) { 1905245db49SHeiko Stübner 1915245db49SHeiko Stübner /* check for up event in touch touch_ind_mode */ 1925245db49SHeiko Stübner if (ts->touch_ind_mode) { 1935245db49SHeiko Stübner if (gpio_get_value(pdata->gpio_int) == 0) { 1945245db49SHeiko Stübner input_mt_sync(ts->input); 1955245db49SHeiko Stübner input_report_key(ts->input, BTN_TOUCH, 0); 1965245db49SHeiko Stübner input_sync(ts->input); 1975245db49SHeiko Stübner break; 1985245db49SHeiko Stübner } 1995245db49SHeiko Stübner } 2005245db49SHeiko Stübner 2015245db49SHeiko Stübner ret = auo_pixcir_collect_data(ts, point); 2025245db49SHeiko Stübner if (ret < 0) { 2035245db49SHeiko Stübner /* we want to loop only in touch_ind_mode */ 2045245db49SHeiko Stübner if (!ts->touch_ind_mode) 2055245db49SHeiko Stübner break; 2065245db49SHeiko Stübner 2075245db49SHeiko Stübner wait_event_timeout(ts->wait, ts->stopped, 2085245db49SHeiko Stübner msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS)); 2095245db49SHeiko Stübner continue; 2105245db49SHeiko Stübner } 2115245db49SHeiko Stübner 2125245db49SHeiko Stübner for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) { 2135245db49SHeiko Stübner if (point[i].coord_x > 0 || point[i].coord_y > 0) { 2145245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_POSITION_X, 2155245db49SHeiko Stübner point[i].coord_x); 2165245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_POSITION_Y, 2175245db49SHeiko Stübner point[i].coord_y); 2185245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 2195245db49SHeiko Stübner point[i].area_major); 2205245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, 2215245db49SHeiko Stübner point[i].area_minor); 2225245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_ORIENTATION, 2235245db49SHeiko Stübner point[i].orientation); 2245245db49SHeiko Stübner input_mt_sync(ts->input); 2255245db49SHeiko Stübner 2265245db49SHeiko Stübner /* use first finger as source for singletouch */ 2275245db49SHeiko Stübner if (fingers == 0) 2285245db49SHeiko Stübner abs = i; 2295245db49SHeiko Stübner 2305245db49SHeiko Stübner /* number of touch points could also be queried 2315245db49SHeiko Stübner * via i2c but would require an additional call 2325245db49SHeiko Stübner */ 2335245db49SHeiko Stübner fingers++; 2345245db49SHeiko Stübner } 2355245db49SHeiko Stübner } 2365245db49SHeiko Stübner 2375245db49SHeiko Stübner input_report_key(ts->input, BTN_TOUCH, fingers > 0); 2385245db49SHeiko Stübner 2395245db49SHeiko Stübner if (abs > -1) { 2405245db49SHeiko Stübner input_report_abs(ts->input, ABS_X, point[abs].coord_x); 2415245db49SHeiko Stübner input_report_abs(ts->input, ABS_Y, point[abs].coord_y); 2425245db49SHeiko Stübner } 2435245db49SHeiko Stübner 2445245db49SHeiko Stübner input_sync(ts->input); 2455245db49SHeiko Stübner 2465245db49SHeiko Stübner /* we want to loop only in touch_ind_mode */ 2475245db49SHeiko Stübner if (!ts->touch_ind_mode) 2485245db49SHeiko Stübner break; 2495245db49SHeiko Stübner 2505245db49SHeiko Stübner wait_event_timeout(ts->wait, ts->stopped, 2515245db49SHeiko Stübner msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS)); 2525245db49SHeiko Stübner } 2535245db49SHeiko Stübner 2545245db49SHeiko Stübner return IRQ_HANDLED; 2555245db49SHeiko Stübner } 2565245db49SHeiko Stübner 2575245db49SHeiko Stübner /* 2585245db49SHeiko Stübner * Set the power mode of the device. 2595245db49SHeiko Stübner * Valid modes are 2605245db49SHeiko Stübner * - AUO_PIXCIR_POWER_ACTIVE 2615245db49SHeiko Stübner * - AUO_PIXCIR_POWER_SLEEP - automatically left on first touch 2625245db49SHeiko Stübner * - AUO_PIXCIR_POWER_DEEP_SLEEP 2635245db49SHeiko Stübner */ 2645245db49SHeiko Stübner static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode) 2655245db49SHeiko Stübner { 2665245db49SHeiko Stübner struct i2c_client *client = ts->client; 2675245db49SHeiko Stübner int ret; 2685245db49SHeiko Stübner 2695245db49SHeiko Stübner ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_POWER_MODE); 2705245db49SHeiko Stübner if (ret < 0) { 2715245db49SHeiko Stübner dev_err(&client->dev, "unable to read reg %Xh, %d\n", 2725245db49SHeiko Stübner AUO_PIXCIR_REG_POWER_MODE, ret); 2735245db49SHeiko Stübner return ret; 2745245db49SHeiko Stübner } 2755245db49SHeiko Stübner 2765245db49SHeiko Stübner ret &= ~AUO_PIXCIR_POWER_MASK; 2775245db49SHeiko Stübner ret |= mode; 2785245db49SHeiko Stübner 2795245db49SHeiko Stübner ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_POWER_MODE, ret); 2805245db49SHeiko Stübner if (ret) { 2815245db49SHeiko Stübner dev_err(&client->dev, "unable to write reg %Xh, %d\n", 2825245db49SHeiko Stübner AUO_PIXCIR_REG_POWER_MODE, ret); 2835245db49SHeiko Stübner return ret; 2845245db49SHeiko Stübner } 2855245db49SHeiko Stübner 2865245db49SHeiko Stübner return 0; 2875245db49SHeiko Stübner } 2885245db49SHeiko Stübner 2895298cc4cSBill Pemberton static int auo_pixcir_int_config(struct auo_pixcir_ts *ts, 2905245db49SHeiko Stübner int int_setting) 2915245db49SHeiko Stübner { 2925245db49SHeiko Stübner struct i2c_client *client = ts->client; 2935245db49SHeiko Stübner struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; 2945245db49SHeiko Stübner int ret; 2955245db49SHeiko Stübner 2965245db49SHeiko Stübner ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); 2975245db49SHeiko Stübner if (ret < 0) { 2985245db49SHeiko Stübner dev_err(&client->dev, "unable to read reg %Xh, %d\n", 2995245db49SHeiko Stübner AUO_PIXCIR_REG_INT_SETTING, ret); 3005245db49SHeiko Stübner return ret; 3015245db49SHeiko Stübner } 3025245db49SHeiko Stübner 3035245db49SHeiko Stübner ret &= ~AUO_PIXCIR_INT_MODE_MASK; 3045245db49SHeiko Stübner ret |= int_setting; 3055245db49SHeiko Stübner ret |= AUO_PIXCIR_INT_POL_HIGH; /* always use high for interrupts */ 3065245db49SHeiko Stübner 3075245db49SHeiko Stübner ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING, 3085245db49SHeiko Stübner ret); 3095245db49SHeiko Stübner if (ret < 0) { 3105245db49SHeiko Stübner dev_err(&client->dev, "unable to write reg %Xh, %d\n", 3115245db49SHeiko Stübner AUO_PIXCIR_REG_INT_SETTING, ret); 3125245db49SHeiko Stübner return ret; 3135245db49SHeiko Stübner } 3145245db49SHeiko Stübner 3155245db49SHeiko Stübner ts->touch_ind_mode = pdata->int_setting == AUO_PIXCIR_INT_TOUCH_IND; 3165245db49SHeiko Stübner 3175245db49SHeiko Stübner return 0; 3185245db49SHeiko Stübner } 3195245db49SHeiko Stübner 3205245db49SHeiko Stübner /* control the generation of interrupts on the device side */ 3215245db49SHeiko Stübner static int auo_pixcir_int_toggle(struct auo_pixcir_ts *ts, bool enable) 3225245db49SHeiko Stübner { 3235245db49SHeiko Stübner struct i2c_client *client = ts->client; 3245245db49SHeiko Stübner int ret; 3255245db49SHeiko Stübner 3265245db49SHeiko Stübner ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); 3275245db49SHeiko Stübner if (ret < 0) { 3285245db49SHeiko Stübner dev_err(&client->dev, "unable to read reg %Xh, %d\n", 3295245db49SHeiko Stübner AUO_PIXCIR_REG_INT_SETTING, ret); 3305245db49SHeiko Stübner return ret; 3315245db49SHeiko Stübner } 3325245db49SHeiko Stübner 3335245db49SHeiko Stübner if (enable) 3345245db49SHeiko Stübner ret |= AUO_PIXCIR_INT_ENABLE; 3355245db49SHeiko Stübner else 3365245db49SHeiko Stübner ret &= ~AUO_PIXCIR_INT_ENABLE; 3375245db49SHeiko Stübner 3385245db49SHeiko Stübner ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING, 3395245db49SHeiko Stübner ret); 3405245db49SHeiko Stübner if (ret < 0) { 3415245db49SHeiko Stübner dev_err(&client->dev, "unable to write reg %Xh, %d\n", 3425245db49SHeiko Stübner AUO_PIXCIR_REG_INT_SETTING, ret); 3435245db49SHeiko Stübner return ret; 3445245db49SHeiko Stübner } 3455245db49SHeiko Stübner 3465245db49SHeiko Stübner return 0; 3475245db49SHeiko Stübner } 3485245db49SHeiko Stübner 3495245db49SHeiko Stübner static int auo_pixcir_start(struct auo_pixcir_ts *ts) 3505245db49SHeiko Stübner { 3515245db49SHeiko Stübner struct i2c_client *client = ts->client; 3525245db49SHeiko Stübner int ret; 3535245db49SHeiko Stübner 3545245db49SHeiko Stübner ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_ACTIVE); 3555245db49SHeiko Stübner if (ret < 0) { 3565245db49SHeiko Stübner dev_err(&client->dev, "could not set power mode, %d\n", 3575245db49SHeiko Stübner ret); 3585245db49SHeiko Stübner return ret; 3595245db49SHeiko Stübner } 3605245db49SHeiko Stübner 3615245db49SHeiko Stübner ts->stopped = false; 3625245db49SHeiko Stübner mb(); 3635245db49SHeiko Stübner enable_irq(client->irq); 3645245db49SHeiko Stübner 3655245db49SHeiko Stübner ret = auo_pixcir_int_toggle(ts, 1); 3665245db49SHeiko Stübner if (ret < 0) { 3675245db49SHeiko Stübner dev_err(&client->dev, "could not enable interrupt, %d\n", 3685245db49SHeiko Stübner ret); 3695245db49SHeiko Stübner disable_irq(client->irq); 3705245db49SHeiko Stübner return ret; 3715245db49SHeiko Stübner } 3725245db49SHeiko Stübner 3735245db49SHeiko Stübner return 0; 3745245db49SHeiko Stübner } 3755245db49SHeiko Stübner 3765245db49SHeiko Stübner static int auo_pixcir_stop(struct auo_pixcir_ts *ts) 3775245db49SHeiko Stübner { 3785245db49SHeiko Stübner struct i2c_client *client = ts->client; 3795245db49SHeiko Stübner int ret; 3805245db49SHeiko Stübner 3815245db49SHeiko Stübner ret = auo_pixcir_int_toggle(ts, 0); 3825245db49SHeiko Stübner if (ret < 0) { 3835245db49SHeiko Stübner dev_err(&client->dev, "could not disable interrupt, %d\n", 3845245db49SHeiko Stübner ret); 3855245db49SHeiko Stübner return ret; 3865245db49SHeiko Stübner } 3875245db49SHeiko Stübner 3885245db49SHeiko Stübner /* disable receiving of interrupts */ 3895245db49SHeiko Stübner disable_irq(client->irq); 3905245db49SHeiko Stübner ts->stopped = true; 3915245db49SHeiko Stübner mb(); 3925245db49SHeiko Stübner wake_up(&ts->wait); 3935245db49SHeiko Stübner 3945245db49SHeiko Stübner return auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_DEEP_SLEEP); 3955245db49SHeiko Stübner } 3965245db49SHeiko Stübner 3975245db49SHeiko Stübner static int auo_pixcir_input_open(struct input_dev *dev) 3985245db49SHeiko Stübner { 3995245db49SHeiko Stübner struct auo_pixcir_ts *ts = input_get_drvdata(dev); 4005245db49SHeiko Stübner int ret; 4015245db49SHeiko Stübner 4025245db49SHeiko Stübner ret = auo_pixcir_start(ts); 4035245db49SHeiko Stübner if (ret) 4045245db49SHeiko Stübner return ret; 4055245db49SHeiko Stübner 4065245db49SHeiko Stübner return 0; 4075245db49SHeiko Stübner } 4085245db49SHeiko Stübner 4095245db49SHeiko Stübner static void auo_pixcir_input_close(struct input_dev *dev) 4105245db49SHeiko Stübner { 4115245db49SHeiko Stübner struct auo_pixcir_ts *ts = input_get_drvdata(dev); 4125245db49SHeiko Stübner 4135245db49SHeiko Stübner auo_pixcir_stop(ts); 4145245db49SHeiko Stübner 4155245db49SHeiko Stübner return; 4165245db49SHeiko Stübner } 4175245db49SHeiko Stübner 4185245db49SHeiko Stübner #ifdef CONFIG_PM_SLEEP 4195245db49SHeiko Stübner static int auo_pixcir_suspend(struct device *dev) 4205245db49SHeiko Stübner { 4215245db49SHeiko Stübner struct i2c_client *client = to_i2c_client(dev); 4225245db49SHeiko Stübner struct auo_pixcir_ts *ts = i2c_get_clientdata(client); 4235245db49SHeiko Stübner struct input_dev *input = ts->input; 4245245db49SHeiko Stübner int ret = 0; 4255245db49SHeiko Stübner 4265245db49SHeiko Stübner mutex_lock(&input->mutex); 4275245db49SHeiko Stübner 4285245db49SHeiko Stübner /* when configured as wakeup source, device should always wake system 4295245db49SHeiko Stübner * therefore start device if necessary 4305245db49SHeiko Stübner */ 4315245db49SHeiko Stübner if (device_may_wakeup(&client->dev)) { 4325245db49SHeiko Stübner /* need to start device if not open, to be wakeup source */ 4335245db49SHeiko Stübner if (!input->users) { 4345245db49SHeiko Stübner ret = auo_pixcir_start(ts); 4355245db49SHeiko Stübner if (ret) 4365245db49SHeiko Stübner goto unlock; 4375245db49SHeiko Stübner } 4385245db49SHeiko Stübner 4395245db49SHeiko Stübner enable_irq_wake(client->irq); 4405245db49SHeiko Stübner ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP); 4415245db49SHeiko Stübner } else if (input->users) { 4425245db49SHeiko Stübner ret = auo_pixcir_stop(ts); 4435245db49SHeiko Stübner } 4445245db49SHeiko Stübner 4455245db49SHeiko Stübner unlock: 4465245db49SHeiko Stübner mutex_unlock(&input->mutex); 4475245db49SHeiko Stübner 4485245db49SHeiko Stübner return ret; 4495245db49SHeiko Stübner } 4505245db49SHeiko Stübner 4515245db49SHeiko Stübner static int auo_pixcir_resume(struct device *dev) 4525245db49SHeiko Stübner { 4535245db49SHeiko Stübner struct i2c_client *client = to_i2c_client(dev); 4545245db49SHeiko Stübner struct auo_pixcir_ts *ts = i2c_get_clientdata(client); 4555245db49SHeiko Stübner struct input_dev *input = ts->input; 4565245db49SHeiko Stübner int ret = 0; 4575245db49SHeiko Stübner 4585245db49SHeiko Stübner mutex_lock(&input->mutex); 4595245db49SHeiko Stübner 4605245db49SHeiko Stübner if (device_may_wakeup(&client->dev)) { 4615245db49SHeiko Stübner disable_irq_wake(client->irq); 4625245db49SHeiko Stübner 4635245db49SHeiko Stübner /* need to stop device if it was not open on suspend */ 4645245db49SHeiko Stübner if (!input->users) { 4655245db49SHeiko Stübner ret = auo_pixcir_stop(ts); 4665245db49SHeiko Stübner if (ret) 4675245db49SHeiko Stübner goto unlock; 4685245db49SHeiko Stübner } 4695245db49SHeiko Stübner 4705245db49SHeiko Stübner /* device wakes automatically from SLEEP */ 4715245db49SHeiko Stübner } else if (input->users) { 4725245db49SHeiko Stübner ret = auo_pixcir_start(ts); 4735245db49SHeiko Stübner } 4745245db49SHeiko Stübner 4755245db49SHeiko Stübner unlock: 4765245db49SHeiko Stübner mutex_unlock(&input->mutex); 4775245db49SHeiko Stübner 4785245db49SHeiko Stübner return ret; 4795245db49SHeiko Stübner } 4805245db49SHeiko Stübner #endif 4815245db49SHeiko Stübner 4825245db49SHeiko Stübner static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend, 4835245db49SHeiko Stübner auo_pixcir_resume); 4845245db49SHeiko Stübner 4855298cc4cSBill Pemberton static int auo_pixcir_probe(struct i2c_client *client, 4865245db49SHeiko Stübner const struct i2c_device_id *id) 4875245db49SHeiko Stübner { 4885245db49SHeiko Stübner const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; 4895245db49SHeiko Stübner struct auo_pixcir_ts *ts; 4905245db49SHeiko Stübner struct input_dev *input_dev; 4915245db49SHeiko Stübner int ret; 4925245db49SHeiko Stübner 4935245db49SHeiko Stübner if (!pdata) 4945245db49SHeiko Stübner return -EINVAL; 4955245db49SHeiko Stübner 4965245db49SHeiko Stübner ts = kzalloc(sizeof(struct auo_pixcir_ts), GFP_KERNEL); 4975245db49SHeiko Stübner if (!ts) 4985245db49SHeiko Stübner return -ENOMEM; 4995245db49SHeiko Stübner 5005245db49SHeiko Stübner ret = gpio_request(pdata->gpio_int, "auo_pixcir_ts_int"); 5015245db49SHeiko Stübner if (ret) { 5025245db49SHeiko Stübner dev_err(&client->dev, "request of gpio %d failed, %d\n", 5035245db49SHeiko Stübner pdata->gpio_int, ret); 5045245db49SHeiko Stübner goto err_gpio_int; 5055245db49SHeiko Stübner } 5065245db49SHeiko Stübner 5075245db49SHeiko Stübner if (pdata->init_hw) 5085245db49SHeiko Stübner pdata->init_hw(client); 5095245db49SHeiko Stübner 5105245db49SHeiko Stübner ts->client = client; 5115245db49SHeiko Stübner ts->touch_ind_mode = 0; 5125245db49SHeiko Stübner init_waitqueue_head(&ts->wait); 5135245db49SHeiko Stübner 5145245db49SHeiko Stübner snprintf(ts->phys, sizeof(ts->phys), 5155245db49SHeiko Stübner "%s/input0", dev_name(&client->dev)); 5165245db49SHeiko Stübner 5175245db49SHeiko Stübner input_dev = input_allocate_device(); 5185245db49SHeiko Stübner if (!input_dev) { 5195245db49SHeiko Stübner dev_err(&client->dev, "could not allocate input device\n"); 5205245db49SHeiko Stübner goto err_input_alloc; 5215245db49SHeiko Stübner } 5225245db49SHeiko Stübner 5235245db49SHeiko Stübner ts->input = input_dev; 5245245db49SHeiko Stübner 5255245db49SHeiko Stübner input_dev->name = "AUO-Pixcir touchscreen"; 5265245db49SHeiko Stübner input_dev->phys = ts->phys; 5275245db49SHeiko Stübner input_dev->id.bustype = BUS_I2C; 5285245db49SHeiko Stübner input_dev->dev.parent = &client->dev; 5295245db49SHeiko Stübner 5305245db49SHeiko Stübner input_dev->open = auo_pixcir_input_open; 5315245db49SHeiko Stübner input_dev->close = auo_pixcir_input_close; 5325245db49SHeiko Stübner 5335245db49SHeiko Stübner __set_bit(EV_ABS, input_dev->evbit); 5345245db49SHeiko Stübner __set_bit(EV_KEY, input_dev->evbit); 5355245db49SHeiko Stübner 5365245db49SHeiko Stübner __set_bit(BTN_TOUCH, input_dev->keybit); 5375245db49SHeiko Stübner 5385245db49SHeiko Stübner /* For single touch */ 5395245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_X, 0, pdata->x_max, 0, 0); 5405245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_Y, 0, pdata->y_max, 0, 0); 5415245db49SHeiko Stübner 5425245db49SHeiko Stübner /* For multi touch */ 5435245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 5445245db49SHeiko Stübner pdata->x_max, 0, 0); 5455245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 5465245db49SHeiko Stübner pdata->y_max, 0, 0); 5475245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 5485245db49SHeiko Stübner AUO_PIXCIR_MAX_AREA, 0, 0); 5495245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, 5505245db49SHeiko Stübner AUO_PIXCIR_MAX_AREA, 0, 0); 5515245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); 5525245db49SHeiko Stübner 5535245db49SHeiko Stübner ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION); 5545245db49SHeiko Stübner if (ret < 0) 5555245db49SHeiko Stübner goto err_fw_vers; 5565245db49SHeiko Stübner dev_info(&client->dev, "firmware version 0x%X\n", ret); 5575245db49SHeiko Stübner 5585245db49SHeiko Stübner ret = auo_pixcir_int_config(ts, pdata->int_setting); 5595245db49SHeiko Stübner if (ret) 5605245db49SHeiko Stübner goto err_fw_vers; 5615245db49SHeiko Stübner 5625245db49SHeiko Stübner input_set_drvdata(ts->input, ts); 5635245db49SHeiko Stübner ts->stopped = true; 5645245db49SHeiko Stübner 5655245db49SHeiko Stübner ret = request_threaded_irq(client->irq, NULL, auo_pixcir_interrupt, 5665245db49SHeiko Stübner IRQF_TRIGGER_RISING | IRQF_ONESHOT, 5675245db49SHeiko Stübner input_dev->name, ts); 5685245db49SHeiko Stübner if (ret) { 5695245db49SHeiko Stübner dev_err(&client->dev, "irq %d requested failed\n", client->irq); 5705245db49SHeiko Stübner goto err_fw_vers; 5715245db49SHeiko Stübner } 5725245db49SHeiko Stübner 5735245db49SHeiko Stübner /* stop device and put it into deep sleep until it is opened */ 5745245db49SHeiko Stübner ret = auo_pixcir_stop(ts); 5755245db49SHeiko Stübner if (ret < 0) 5765245db49SHeiko Stübner goto err_input_register; 5775245db49SHeiko Stübner 5785245db49SHeiko Stübner ret = input_register_device(input_dev); 5795245db49SHeiko Stübner if (ret) { 5805245db49SHeiko Stübner dev_err(&client->dev, "could not register input device\n"); 5815245db49SHeiko Stübner goto err_input_register; 5825245db49SHeiko Stübner } 5835245db49SHeiko Stübner 5845245db49SHeiko Stübner i2c_set_clientdata(client, ts); 5855245db49SHeiko Stübner 5865245db49SHeiko Stübner return 0; 5875245db49SHeiko Stübner 5885245db49SHeiko Stübner err_input_register: 5895245db49SHeiko Stübner free_irq(client->irq, ts); 5905245db49SHeiko Stübner err_fw_vers: 5915245db49SHeiko Stübner input_free_device(input_dev); 5925245db49SHeiko Stübner err_input_alloc: 5935245db49SHeiko Stübner if (pdata->exit_hw) 5945245db49SHeiko Stübner pdata->exit_hw(client); 5955245db49SHeiko Stübner gpio_free(pdata->gpio_int); 5965245db49SHeiko Stübner err_gpio_int: 5975245db49SHeiko Stübner kfree(ts); 5985245db49SHeiko Stübner 5995245db49SHeiko Stübner return ret; 6005245db49SHeiko Stübner } 6015245db49SHeiko Stübner 6025245db49SHeiko Stübner static int __devexit auo_pixcir_remove(struct i2c_client *client) 6035245db49SHeiko Stübner { 6045245db49SHeiko Stübner struct auo_pixcir_ts *ts = i2c_get_clientdata(client); 6055245db49SHeiko Stübner const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; 6065245db49SHeiko Stübner 6075245db49SHeiko Stübner free_irq(client->irq, ts); 6085245db49SHeiko Stübner 6095245db49SHeiko Stübner input_unregister_device(ts->input); 6105245db49SHeiko Stübner 6115245db49SHeiko Stübner if (pdata->exit_hw) 6125245db49SHeiko Stübner pdata->exit_hw(client); 6135245db49SHeiko Stübner 6145245db49SHeiko Stübner gpio_free(pdata->gpio_int); 6155245db49SHeiko Stübner 6165245db49SHeiko Stübner kfree(ts); 6175245db49SHeiko Stübner 6185245db49SHeiko Stübner return 0; 6195245db49SHeiko Stübner } 6205245db49SHeiko Stübner 6215245db49SHeiko Stübner static const struct i2c_device_id auo_pixcir_idtable[] = { 6225245db49SHeiko Stübner { "auo_pixcir_ts", 0 }, 6235245db49SHeiko Stübner { } 6245245db49SHeiko Stübner }; 6255245db49SHeiko Stübner MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable); 6265245db49SHeiko Stübner 6275245db49SHeiko Stübner static struct i2c_driver auo_pixcir_driver = { 6285245db49SHeiko Stübner .driver = { 6295245db49SHeiko Stübner .owner = THIS_MODULE, 6305245db49SHeiko Stübner .name = "auo_pixcir_ts", 6315245db49SHeiko Stübner .pm = &auo_pixcir_pm_ops, 6325245db49SHeiko Stübner }, 6335245db49SHeiko Stübner .probe = auo_pixcir_probe, 6341cb0aa88SBill Pemberton .remove = auo_pixcir_remove, 6355245db49SHeiko Stübner .id_table = auo_pixcir_idtable, 6365245db49SHeiko Stübner }; 6375245db49SHeiko Stübner 6384a533835SDmitry Torokhov module_i2c_driver(auo_pixcir_driver); 6395245db49SHeiko Stübner 6405245db49SHeiko Stübner MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver"); 6415245db49SHeiko Stübner MODULE_LICENSE("GPL v2"); 6425245db49SHeiko Stübner MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 643