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> 347241443fSHeiko Stübner #include <linux/of.h> 357241443fSHeiko Stübner #include <linux/of_gpio.h> 365245db49SHeiko Stübner 375245db49SHeiko Stübner /* 385245db49SHeiko Stübner * Coordinate calculation: 395245db49SHeiko Stübner * X1 = X1_LSB + X1_MSB*256 405245db49SHeiko Stübner * Y1 = Y1_LSB + Y1_MSB*256 415245db49SHeiko Stübner * X2 = X2_LSB + X2_MSB*256 425245db49SHeiko Stübner * Y2 = Y2_LSB + Y2_MSB*256 435245db49SHeiko Stübner */ 445245db49SHeiko Stübner #define AUO_PIXCIR_REG_X1_LSB 0x00 455245db49SHeiko Stübner #define AUO_PIXCIR_REG_X1_MSB 0x01 465245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y1_LSB 0x02 475245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y1_MSB 0x03 485245db49SHeiko Stübner #define AUO_PIXCIR_REG_X2_LSB 0x04 495245db49SHeiko Stübner #define AUO_PIXCIR_REG_X2_MSB 0x05 505245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y2_LSB 0x06 515245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y2_MSB 0x07 525245db49SHeiko Stübner 535245db49SHeiko Stübner #define AUO_PIXCIR_REG_STRENGTH 0x0d 545245db49SHeiko Stübner #define AUO_PIXCIR_REG_STRENGTH_X1_LSB 0x0e 555245db49SHeiko Stübner #define AUO_PIXCIR_REG_STRENGTH_X1_MSB 0x0f 565245db49SHeiko Stübner 575245db49SHeiko Stübner #define AUO_PIXCIR_REG_RAW_DATA_X 0x2b 585245db49SHeiko Stübner #define AUO_PIXCIR_REG_RAW_DATA_Y 0x4f 595245db49SHeiko Stübner 605245db49SHeiko Stübner #define AUO_PIXCIR_REG_X_SENSITIVITY 0x6f 615245db49SHeiko Stübner #define AUO_PIXCIR_REG_Y_SENSITIVITY 0x70 625245db49SHeiko Stübner #define AUO_PIXCIR_REG_INT_SETTING 0x71 635245db49SHeiko Stübner #define AUO_PIXCIR_REG_INT_WIDTH 0x72 645245db49SHeiko Stübner #define AUO_PIXCIR_REG_POWER_MODE 0x73 655245db49SHeiko Stübner 665245db49SHeiko Stübner #define AUO_PIXCIR_REG_VERSION 0x77 675245db49SHeiko Stübner #define AUO_PIXCIR_REG_CALIBRATE 0x78 685245db49SHeiko Stübner 695245db49SHeiko Stübner #define AUO_PIXCIR_REG_TOUCHAREA_X1 0x1e 705245db49SHeiko Stübner #define AUO_PIXCIR_REG_TOUCHAREA_Y1 0x1f 715245db49SHeiko Stübner #define AUO_PIXCIR_REG_TOUCHAREA_X2 0x20 725245db49SHeiko Stübner #define AUO_PIXCIR_REG_TOUCHAREA_Y2 0x21 735245db49SHeiko Stübner 745245db49SHeiko Stübner #define AUO_PIXCIR_REG_EEPROM_CALIB_X 0x42 755245db49SHeiko Stübner #define AUO_PIXCIR_REG_EEPROM_CALIB_Y 0xad 765245db49SHeiko Stübner 775245db49SHeiko Stübner #define AUO_PIXCIR_INT_TPNUM_MASK 0xe0 785245db49SHeiko Stübner #define AUO_PIXCIR_INT_TPNUM_SHIFT 5 795245db49SHeiko Stübner #define AUO_PIXCIR_INT_RELEASE (1 << 4) 805245db49SHeiko Stübner #define AUO_PIXCIR_INT_ENABLE (1 << 3) 815245db49SHeiko Stübner #define AUO_PIXCIR_INT_POL_HIGH (1 << 2) 825245db49SHeiko Stübner #define AUO_PIXCIR_INT_MODE_MASK 0x03 835245db49SHeiko Stübner 845245db49SHeiko Stübner /* 855245db49SHeiko Stübner * Power modes: 865245db49SHeiko Stübner * active: scan speed 60Hz 875245db49SHeiko Stübner * sleep: scan speed 10Hz can be auto-activated, wakeup on 1st touch 885245db49SHeiko Stübner * deep sleep: scan speed 1Hz can only be entered or left manually. 895245db49SHeiko Stübner */ 905245db49SHeiko Stübner #define AUO_PIXCIR_POWER_ACTIVE 0x00 915245db49SHeiko Stübner #define AUO_PIXCIR_POWER_SLEEP 0x01 925245db49SHeiko Stübner #define AUO_PIXCIR_POWER_DEEP_SLEEP 0x02 935245db49SHeiko Stübner #define AUO_PIXCIR_POWER_MASK 0x03 945245db49SHeiko Stübner 955245db49SHeiko Stübner #define AUO_PIXCIR_POWER_ALLOW_SLEEP (1 << 2) 965245db49SHeiko Stübner #define AUO_PIXCIR_POWER_IDLE_TIME(ms) ((ms & 0xf) << 4) 975245db49SHeiko Stübner 985245db49SHeiko Stübner #define AUO_PIXCIR_CALIBRATE 0x03 995245db49SHeiko Stübner 1005245db49SHeiko Stübner #define AUO_PIXCIR_EEPROM_CALIB_X_LEN 62 1015245db49SHeiko Stübner #define AUO_PIXCIR_EEPROM_CALIB_Y_LEN 36 1025245db49SHeiko Stübner 1035245db49SHeiko Stübner #define AUO_PIXCIR_RAW_DATA_X_LEN 18 1045245db49SHeiko Stübner #define AUO_PIXCIR_RAW_DATA_Y_LEN 11 1055245db49SHeiko Stübner 1065245db49SHeiko Stübner #define AUO_PIXCIR_STRENGTH_ENABLE (1 << 0) 1075245db49SHeiko Stübner 1085245db49SHeiko Stübner /* Touchscreen absolute values */ 1095245db49SHeiko Stübner #define AUO_PIXCIR_REPORT_POINTS 2 1105245db49SHeiko Stübner #define AUO_PIXCIR_MAX_AREA 0xff 1115245db49SHeiko Stübner #define AUO_PIXCIR_PENUP_TIMEOUT_MS 10 1125245db49SHeiko Stübner 1135245db49SHeiko Stübner struct auo_pixcir_ts { 1145245db49SHeiko Stübner struct i2c_client *client; 1155245db49SHeiko Stübner struct input_dev *input; 11638e83f7fSHeiko Stübner const struct auo_pixcir_ts_platdata *pdata; 1175245db49SHeiko Stübner char phys[32]; 1185245db49SHeiko Stübner 1195245db49SHeiko Stübner /* special handling for touch_indicate interupt mode */ 1205245db49SHeiko Stübner bool touch_ind_mode; 1215245db49SHeiko Stübner 1225245db49SHeiko Stübner wait_queue_head_t wait; 1235245db49SHeiko Stübner bool stopped; 1245245db49SHeiko Stübner }; 1255245db49SHeiko Stübner 1265245db49SHeiko Stübner struct auo_point_t { 1275245db49SHeiko Stübner int coord_x; 1285245db49SHeiko Stübner int coord_y; 1295245db49SHeiko Stübner int area_major; 1305245db49SHeiko Stübner int area_minor; 1315245db49SHeiko Stübner int orientation; 1325245db49SHeiko Stübner }; 1335245db49SHeiko Stübner 1345245db49SHeiko Stübner static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts, 1355245db49SHeiko Stübner struct auo_point_t *point) 1365245db49SHeiko Stübner { 1375245db49SHeiko Stübner struct i2c_client *client = ts->client; 13838e83f7fSHeiko Stübner const struct auo_pixcir_ts_platdata *pdata = ts->pdata; 1395245db49SHeiko Stübner uint8_t raw_coord[8]; 1405245db49SHeiko Stübner uint8_t raw_area[4]; 1415245db49SHeiko Stübner int i, ret; 1425245db49SHeiko Stübner 1435245db49SHeiko Stübner /* touch coordinates */ 1445245db49SHeiko Stübner ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_X1_LSB, 1455245db49SHeiko Stübner 8, raw_coord); 1465245db49SHeiko Stübner if (ret < 0) { 1475245db49SHeiko Stübner dev_err(&client->dev, "failed to read coordinate, %d\n", ret); 1485245db49SHeiko Stübner return ret; 1495245db49SHeiko Stübner } 1505245db49SHeiko Stübner 1515245db49SHeiko Stübner /* touch area */ 1525245db49SHeiko Stübner ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_TOUCHAREA_X1, 1535245db49SHeiko Stübner 4, raw_area); 1545245db49SHeiko Stübner if (ret < 0) { 1555245db49SHeiko Stübner dev_err(&client->dev, "could not read touch area, %d\n", ret); 1565245db49SHeiko Stübner return ret; 1575245db49SHeiko Stübner } 1585245db49SHeiko Stübner 1595245db49SHeiko Stübner for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) { 1605245db49SHeiko Stübner point[i].coord_x = 1615245db49SHeiko Stübner raw_coord[4 * i + 1] << 8 | raw_coord[4 * i]; 1625245db49SHeiko Stübner point[i].coord_y = 1635245db49SHeiko Stübner raw_coord[4 * i + 3] << 8 | raw_coord[4 * i + 2]; 1645245db49SHeiko Stübner 1655245db49SHeiko Stübner if (point[i].coord_x > pdata->x_max || 1665245db49SHeiko Stübner point[i].coord_y > pdata->y_max) { 1675245db49SHeiko Stübner dev_warn(&client->dev, "coordinates (%d,%d) invalid\n", 1685245db49SHeiko Stübner point[i].coord_x, point[i].coord_y); 1695245db49SHeiko Stübner point[i].coord_x = point[i].coord_y = 0; 1705245db49SHeiko Stübner } 1715245db49SHeiko Stübner 1725245db49SHeiko Stübner /* determine touch major, minor and orientation */ 1735245db49SHeiko Stübner point[i].area_major = max(raw_area[2 * i], raw_area[2 * i + 1]); 1745245db49SHeiko Stübner point[i].area_minor = min(raw_area[2 * i], raw_area[2 * i + 1]); 1755245db49SHeiko Stübner point[i].orientation = raw_area[2 * i] > raw_area[2 * i + 1]; 1765245db49SHeiko Stübner } 1775245db49SHeiko Stübner 1785245db49SHeiko Stübner return 0; 1795245db49SHeiko Stübner } 1805245db49SHeiko Stübner 1815245db49SHeiko Stübner static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id) 1825245db49SHeiko Stübner { 1835245db49SHeiko Stübner struct auo_pixcir_ts *ts = dev_id; 18438e83f7fSHeiko Stübner const struct auo_pixcir_ts_platdata *pdata = ts->pdata; 1855245db49SHeiko Stübner struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS]; 1865245db49SHeiko Stübner int i; 1875245db49SHeiko Stübner int ret; 1885245db49SHeiko Stübner int fingers = 0; 1895245db49SHeiko Stübner int abs = -1; 1905245db49SHeiko Stübner 1915245db49SHeiko Stübner while (!ts->stopped) { 1925245db49SHeiko Stübner 1935245db49SHeiko Stübner /* check for up event in touch touch_ind_mode */ 1945245db49SHeiko Stübner if (ts->touch_ind_mode) { 1955245db49SHeiko Stübner if (gpio_get_value(pdata->gpio_int) == 0) { 1965245db49SHeiko Stübner input_mt_sync(ts->input); 1975245db49SHeiko Stübner input_report_key(ts->input, BTN_TOUCH, 0); 1985245db49SHeiko Stübner input_sync(ts->input); 1995245db49SHeiko Stübner break; 2005245db49SHeiko Stübner } 2015245db49SHeiko Stübner } 2025245db49SHeiko Stübner 2035245db49SHeiko Stübner ret = auo_pixcir_collect_data(ts, point); 2045245db49SHeiko Stübner if (ret < 0) { 2055245db49SHeiko Stübner /* we want to loop only in touch_ind_mode */ 2065245db49SHeiko Stübner if (!ts->touch_ind_mode) 2075245db49SHeiko Stübner break; 2085245db49SHeiko Stübner 2095245db49SHeiko Stübner wait_event_timeout(ts->wait, ts->stopped, 2105245db49SHeiko Stübner msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS)); 2115245db49SHeiko Stübner continue; 2125245db49SHeiko Stübner } 2135245db49SHeiko Stübner 2145245db49SHeiko Stübner for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) { 2155245db49SHeiko Stübner if (point[i].coord_x > 0 || point[i].coord_y > 0) { 2165245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_POSITION_X, 2175245db49SHeiko Stübner point[i].coord_x); 2185245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_POSITION_Y, 2195245db49SHeiko Stübner point[i].coord_y); 2205245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 2215245db49SHeiko Stübner point[i].area_major); 2225245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, 2235245db49SHeiko Stübner point[i].area_minor); 2245245db49SHeiko Stübner input_report_abs(ts->input, ABS_MT_ORIENTATION, 2255245db49SHeiko Stübner point[i].orientation); 2265245db49SHeiko Stübner input_mt_sync(ts->input); 2275245db49SHeiko Stübner 2285245db49SHeiko Stübner /* use first finger as source for singletouch */ 2295245db49SHeiko Stübner if (fingers == 0) 2305245db49SHeiko Stübner abs = i; 2315245db49SHeiko Stübner 2325245db49SHeiko Stübner /* number of touch points could also be queried 2335245db49SHeiko Stübner * via i2c but would require an additional call 2345245db49SHeiko Stübner */ 2355245db49SHeiko Stübner fingers++; 2365245db49SHeiko Stübner } 2375245db49SHeiko Stübner } 2385245db49SHeiko Stübner 2395245db49SHeiko Stübner input_report_key(ts->input, BTN_TOUCH, fingers > 0); 2405245db49SHeiko Stübner 2415245db49SHeiko Stübner if (abs > -1) { 2425245db49SHeiko Stübner input_report_abs(ts->input, ABS_X, point[abs].coord_x); 2435245db49SHeiko Stübner input_report_abs(ts->input, ABS_Y, point[abs].coord_y); 2445245db49SHeiko Stübner } 2455245db49SHeiko Stübner 2465245db49SHeiko Stübner input_sync(ts->input); 2475245db49SHeiko Stübner 2485245db49SHeiko Stübner /* we want to loop only in touch_ind_mode */ 2495245db49SHeiko Stübner if (!ts->touch_ind_mode) 2505245db49SHeiko Stübner break; 2515245db49SHeiko Stübner 2525245db49SHeiko Stübner wait_event_timeout(ts->wait, ts->stopped, 2535245db49SHeiko Stübner msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS)); 2545245db49SHeiko Stübner } 2555245db49SHeiko Stübner 2565245db49SHeiko Stübner return IRQ_HANDLED; 2575245db49SHeiko Stübner } 2585245db49SHeiko Stübner 2595245db49SHeiko Stübner /* 2605245db49SHeiko Stübner * Set the power mode of the device. 2615245db49SHeiko Stübner * Valid modes are 2625245db49SHeiko Stübner * - AUO_PIXCIR_POWER_ACTIVE 2635245db49SHeiko Stübner * - AUO_PIXCIR_POWER_SLEEP - automatically left on first touch 2645245db49SHeiko Stübner * - AUO_PIXCIR_POWER_DEEP_SLEEP 2655245db49SHeiko Stübner */ 2665245db49SHeiko Stübner static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode) 2675245db49SHeiko Stübner { 2685245db49SHeiko Stübner struct i2c_client *client = ts->client; 2695245db49SHeiko Stübner int ret; 2705245db49SHeiko Stübner 2715245db49SHeiko Stübner ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_POWER_MODE); 2725245db49SHeiko Stübner if (ret < 0) { 2735245db49SHeiko Stübner dev_err(&client->dev, "unable to read reg %Xh, %d\n", 2745245db49SHeiko Stübner AUO_PIXCIR_REG_POWER_MODE, ret); 2755245db49SHeiko Stübner return ret; 2765245db49SHeiko Stübner } 2775245db49SHeiko Stübner 2785245db49SHeiko Stübner ret &= ~AUO_PIXCIR_POWER_MASK; 2795245db49SHeiko Stübner ret |= mode; 2805245db49SHeiko Stübner 2815245db49SHeiko Stübner ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_POWER_MODE, ret); 2825245db49SHeiko Stübner if (ret) { 2835245db49SHeiko Stübner dev_err(&client->dev, "unable to write reg %Xh, %d\n", 2845245db49SHeiko Stübner AUO_PIXCIR_REG_POWER_MODE, ret); 2855245db49SHeiko Stübner return ret; 2865245db49SHeiko Stübner } 2875245db49SHeiko Stübner 2885245db49SHeiko Stübner return 0; 2895245db49SHeiko Stübner } 2905245db49SHeiko Stübner 2915298cc4cSBill Pemberton static int auo_pixcir_int_config(struct auo_pixcir_ts *ts, 2925245db49SHeiko Stübner int int_setting) 2935245db49SHeiko Stübner { 2945245db49SHeiko Stübner struct i2c_client *client = ts->client; 29538e83f7fSHeiko Stübner const struct auo_pixcir_ts_platdata *pdata = ts->pdata; 2965245db49SHeiko Stübner int ret; 2975245db49SHeiko Stübner 2985245db49SHeiko Stübner ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); 2995245db49SHeiko Stübner if (ret < 0) { 3005245db49SHeiko Stübner dev_err(&client->dev, "unable to read reg %Xh, %d\n", 3015245db49SHeiko Stübner AUO_PIXCIR_REG_INT_SETTING, ret); 3025245db49SHeiko Stübner return ret; 3035245db49SHeiko Stübner } 3045245db49SHeiko Stübner 3055245db49SHeiko Stübner ret &= ~AUO_PIXCIR_INT_MODE_MASK; 3065245db49SHeiko Stübner ret |= int_setting; 3075245db49SHeiko Stübner ret |= AUO_PIXCIR_INT_POL_HIGH; /* always use high for interrupts */ 3085245db49SHeiko Stübner 3095245db49SHeiko Stübner ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING, 3105245db49SHeiko Stübner ret); 3115245db49SHeiko Stübner if (ret < 0) { 3125245db49SHeiko Stübner dev_err(&client->dev, "unable to write reg %Xh, %d\n", 3135245db49SHeiko Stübner AUO_PIXCIR_REG_INT_SETTING, ret); 3145245db49SHeiko Stübner return ret; 3155245db49SHeiko Stübner } 3165245db49SHeiko Stübner 3175245db49SHeiko Stübner ts->touch_ind_mode = pdata->int_setting == AUO_PIXCIR_INT_TOUCH_IND; 3185245db49SHeiko Stübner 3195245db49SHeiko Stübner return 0; 3205245db49SHeiko Stübner } 3215245db49SHeiko Stübner 3225245db49SHeiko Stübner /* control the generation of interrupts on the device side */ 3235245db49SHeiko Stübner static int auo_pixcir_int_toggle(struct auo_pixcir_ts *ts, bool enable) 3245245db49SHeiko Stübner { 3255245db49SHeiko Stübner struct i2c_client *client = ts->client; 3265245db49SHeiko Stübner int ret; 3275245db49SHeiko Stübner 3285245db49SHeiko Stübner ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); 3295245db49SHeiko Stübner if (ret < 0) { 3305245db49SHeiko Stübner dev_err(&client->dev, "unable to read reg %Xh, %d\n", 3315245db49SHeiko Stübner AUO_PIXCIR_REG_INT_SETTING, ret); 3325245db49SHeiko Stübner return ret; 3335245db49SHeiko Stübner } 3345245db49SHeiko Stübner 3355245db49SHeiko Stübner if (enable) 3365245db49SHeiko Stübner ret |= AUO_PIXCIR_INT_ENABLE; 3375245db49SHeiko Stübner else 3385245db49SHeiko Stübner ret &= ~AUO_PIXCIR_INT_ENABLE; 3395245db49SHeiko Stübner 3405245db49SHeiko Stübner ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING, 3415245db49SHeiko Stübner ret); 3425245db49SHeiko Stübner if (ret < 0) { 3435245db49SHeiko Stübner dev_err(&client->dev, "unable to write reg %Xh, %d\n", 3445245db49SHeiko Stübner AUO_PIXCIR_REG_INT_SETTING, ret); 3455245db49SHeiko Stübner return ret; 3465245db49SHeiko Stübner } 3475245db49SHeiko Stübner 3485245db49SHeiko Stübner return 0; 3495245db49SHeiko Stübner } 3505245db49SHeiko Stübner 3515245db49SHeiko Stübner static int auo_pixcir_start(struct auo_pixcir_ts *ts) 3525245db49SHeiko Stübner { 3535245db49SHeiko Stübner struct i2c_client *client = ts->client; 3545245db49SHeiko Stübner int ret; 3555245db49SHeiko Stübner 3565245db49SHeiko Stübner ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_ACTIVE); 3575245db49SHeiko Stübner if (ret < 0) { 3585245db49SHeiko Stübner dev_err(&client->dev, "could not set power mode, %d\n", 3595245db49SHeiko Stübner ret); 3605245db49SHeiko Stübner return ret; 3615245db49SHeiko Stübner } 3625245db49SHeiko Stübner 3635245db49SHeiko Stübner ts->stopped = false; 3645245db49SHeiko Stübner mb(); 3655245db49SHeiko Stübner enable_irq(client->irq); 3665245db49SHeiko Stübner 3675245db49SHeiko Stübner ret = auo_pixcir_int_toggle(ts, 1); 3685245db49SHeiko Stübner if (ret < 0) { 3695245db49SHeiko Stübner dev_err(&client->dev, "could not enable interrupt, %d\n", 3705245db49SHeiko Stübner ret); 3715245db49SHeiko Stübner disable_irq(client->irq); 3725245db49SHeiko Stübner return ret; 3735245db49SHeiko Stübner } 3745245db49SHeiko Stübner 3755245db49SHeiko Stübner return 0; 3765245db49SHeiko Stübner } 3775245db49SHeiko Stübner 3785245db49SHeiko Stübner static int auo_pixcir_stop(struct auo_pixcir_ts *ts) 3795245db49SHeiko Stübner { 3805245db49SHeiko Stübner struct i2c_client *client = ts->client; 3815245db49SHeiko Stübner int ret; 3825245db49SHeiko Stübner 3835245db49SHeiko Stübner ret = auo_pixcir_int_toggle(ts, 0); 3845245db49SHeiko Stübner if (ret < 0) { 3855245db49SHeiko Stübner dev_err(&client->dev, "could not disable interrupt, %d\n", 3865245db49SHeiko Stübner ret); 3875245db49SHeiko Stübner return ret; 3885245db49SHeiko Stübner } 3895245db49SHeiko Stübner 3905245db49SHeiko Stübner /* disable receiving of interrupts */ 3915245db49SHeiko Stübner disable_irq(client->irq); 3925245db49SHeiko Stübner ts->stopped = true; 3935245db49SHeiko Stübner mb(); 3945245db49SHeiko Stübner wake_up(&ts->wait); 3955245db49SHeiko Stübner 3965245db49SHeiko Stübner return auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_DEEP_SLEEP); 3975245db49SHeiko Stübner } 3985245db49SHeiko Stübner 3995245db49SHeiko Stübner static int auo_pixcir_input_open(struct input_dev *dev) 4005245db49SHeiko Stübner { 4015245db49SHeiko Stübner struct auo_pixcir_ts *ts = input_get_drvdata(dev); 4025245db49SHeiko Stübner int ret; 4035245db49SHeiko Stübner 4045245db49SHeiko Stübner ret = auo_pixcir_start(ts); 4055245db49SHeiko Stübner if (ret) 4065245db49SHeiko Stübner return ret; 4075245db49SHeiko Stübner 4085245db49SHeiko Stübner return 0; 4095245db49SHeiko Stübner } 4105245db49SHeiko Stübner 4115245db49SHeiko Stübner static void auo_pixcir_input_close(struct input_dev *dev) 4125245db49SHeiko Stübner { 4135245db49SHeiko Stübner struct auo_pixcir_ts *ts = input_get_drvdata(dev); 4145245db49SHeiko Stübner 4155245db49SHeiko Stübner auo_pixcir_stop(ts); 4165245db49SHeiko Stübner 4175245db49SHeiko Stübner return; 4185245db49SHeiko Stübner } 4195245db49SHeiko Stübner 4205245db49SHeiko Stübner #ifdef CONFIG_PM_SLEEP 4215245db49SHeiko Stübner static int auo_pixcir_suspend(struct device *dev) 4225245db49SHeiko Stübner { 4235245db49SHeiko Stübner struct i2c_client *client = to_i2c_client(dev); 4245245db49SHeiko Stübner struct auo_pixcir_ts *ts = i2c_get_clientdata(client); 4255245db49SHeiko Stübner struct input_dev *input = ts->input; 4265245db49SHeiko Stübner int ret = 0; 4275245db49SHeiko Stübner 4285245db49SHeiko Stübner mutex_lock(&input->mutex); 4295245db49SHeiko Stübner 4305245db49SHeiko Stübner /* when configured as wakeup source, device should always wake system 4315245db49SHeiko Stübner * therefore start device if necessary 4325245db49SHeiko Stübner */ 4335245db49SHeiko Stübner if (device_may_wakeup(&client->dev)) { 4345245db49SHeiko Stübner /* need to start device if not open, to be wakeup source */ 4355245db49SHeiko Stübner if (!input->users) { 4365245db49SHeiko Stübner ret = auo_pixcir_start(ts); 4375245db49SHeiko Stübner if (ret) 4385245db49SHeiko Stübner goto unlock; 4395245db49SHeiko Stübner } 4405245db49SHeiko Stübner 4415245db49SHeiko Stübner enable_irq_wake(client->irq); 4425245db49SHeiko Stübner ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP); 4435245db49SHeiko Stübner } else if (input->users) { 4445245db49SHeiko Stübner ret = auo_pixcir_stop(ts); 4455245db49SHeiko Stübner } 4465245db49SHeiko Stübner 4475245db49SHeiko Stübner unlock: 4485245db49SHeiko Stübner mutex_unlock(&input->mutex); 4495245db49SHeiko Stübner 4505245db49SHeiko Stübner return ret; 4515245db49SHeiko Stübner } 4525245db49SHeiko Stübner 4535245db49SHeiko Stübner static int auo_pixcir_resume(struct device *dev) 4545245db49SHeiko Stübner { 4555245db49SHeiko Stübner struct i2c_client *client = to_i2c_client(dev); 4565245db49SHeiko Stübner struct auo_pixcir_ts *ts = i2c_get_clientdata(client); 4575245db49SHeiko Stübner struct input_dev *input = ts->input; 4585245db49SHeiko Stübner int ret = 0; 4595245db49SHeiko Stübner 4605245db49SHeiko Stübner mutex_lock(&input->mutex); 4615245db49SHeiko Stübner 4625245db49SHeiko Stübner if (device_may_wakeup(&client->dev)) { 4635245db49SHeiko Stübner disable_irq_wake(client->irq); 4645245db49SHeiko Stübner 4655245db49SHeiko Stübner /* need to stop device if it was not open on suspend */ 4665245db49SHeiko Stübner if (!input->users) { 4675245db49SHeiko Stübner ret = auo_pixcir_stop(ts); 4685245db49SHeiko Stübner if (ret) 4695245db49SHeiko Stübner goto unlock; 4705245db49SHeiko Stübner } 4715245db49SHeiko Stübner 4725245db49SHeiko Stübner /* device wakes automatically from SLEEP */ 4735245db49SHeiko Stübner } else if (input->users) { 4745245db49SHeiko Stübner ret = auo_pixcir_start(ts); 4755245db49SHeiko Stübner } 4765245db49SHeiko Stübner 4775245db49SHeiko Stübner unlock: 4785245db49SHeiko Stübner mutex_unlock(&input->mutex); 4795245db49SHeiko Stübner 4805245db49SHeiko Stübner return ret; 4815245db49SHeiko Stübner } 4825245db49SHeiko Stübner #endif 4835245db49SHeiko Stübner 4847241443fSHeiko Stübner static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, 4857241443fSHeiko Stübner auo_pixcir_suspend, auo_pixcir_resume); 4867241443fSHeiko Stübner 4877241443fSHeiko Stübner #ifdef CONFIG_OF 4887241443fSHeiko Stübner static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev) 4897241443fSHeiko Stübner { 4907241443fSHeiko Stübner struct auo_pixcir_ts_platdata *pdata; 4917241443fSHeiko Stübner struct device_node *np = dev->of_node; 4927241443fSHeiko Stübner 4937241443fSHeiko Stübner if (!np) 4947241443fSHeiko Stübner return ERR_PTR(-ENOENT); 4957241443fSHeiko Stübner 4967241443fSHeiko Stübner pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 4977241443fSHeiko Stübner if (!pdata) { 4987241443fSHeiko Stübner dev_err(dev, "failed to allocate platform data\n"); 4997241443fSHeiko Stübner return ERR_PTR(-ENOMEM); 5007241443fSHeiko Stübner } 5017241443fSHeiko Stübner 5027241443fSHeiko Stübner pdata->gpio_int = of_get_gpio(np, 0); 5037241443fSHeiko Stübner if (!gpio_is_valid(pdata->gpio_int)) { 5047241443fSHeiko Stübner dev_err(dev, "failed to get interrupt gpio\n"); 5057241443fSHeiko Stübner return ERR_PTR(-EINVAL); 5067241443fSHeiko Stübner } 5077241443fSHeiko Stübner 5087241443fSHeiko Stübner pdata->gpio_rst = of_get_gpio(np, 1); 5097241443fSHeiko Stübner if (!gpio_is_valid(pdata->gpio_rst)) { 5107241443fSHeiko Stübner dev_err(dev, "failed to get reset gpio\n"); 5117241443fSHeiko Stübner return ERR_PTR(-EINVAL); 5127241443fSHeiko Stübner } 5137241443fSHeiko Stübner 5147241443fSHeiko Stübner if (of_property_read_u32(np, "x-size", &pdata->x_max)) { 5157241443fSHeiko Stübner dev_err(dev, "failed to get x-size property\n"); 5167241443fSHeiko Stübner return ERR_PTR(-EINVAL); 5177241443fSHeiko Stübner } 5187241443fSHeiko Stübner 5197241443fSHeiko Stübner if (of_property_read_u32(np, "y-size", &pdata->y_max)) { 5207241443fSHeiko Stübner dev_err(dev, "failed to get y-size property\n"); 5217241443fSHeiko Stübner return ERR_PTR(-EINVAL); 5227241443fSHeiko Stübner } 5237241443fSHeiko Stübner 5247241443fSHeiko Stübner /* default to asserting the interrupt when the screen is touched */ 5257241443fSHeiko Stübner pdata->int_setting = AUO_PIXCIR_INT_TOUCH_IND; 5267241443fSHeiko Stübner 5277241443fSHeiko Stübner return pdata; 5287241443fSHeiko Stübner } 5297241443fSHeiko Stübner #else 5307241443fSHeiko Stübner static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev) 5317241443fSHeiko Stübner { 5327241443fSHeiko Stübner return ERR_PTR(-EINVAL); 5337241443fSHeiko Stübner } 5347241443fSHeiko Stübner #endif 5355245db49SHeiko Stübner 5365298cc4cSBill Pemberton static int auo_pixcir_probe(struct i2c_client *client, 5375245db49SHeiko Stübner const struct i2c_device_id *id) 5385245db49SHeiko Stübner { 5397241443fSHeiko Stübner const struct auo_pixcir_ts_platdata *pdata; 5405245db49SHeiko Stübner struct auo_pixcir_ts *ts; 5415245db49SHeiko Stübner struct input_dev *input_dev; 5425245db49SHeiko Stübner int ret; 5435245db49SHeiko Stübner 5447241443fSHeiko Stübner pdata = dev_get_platdata(&client->dev); 5457241443fSHeiko Stübner if (!pdata) { 5467241443fSHeiko Stübner pdata = auo_pixcir_parse_dt(&client->dev); 5477241443fSHeiko Stübner if (IS_ERR(pdata)) 5487241443fSHeiko Stübner return PTR_ERR(pdata); 5497241443fSHeiko Stübner } 5505245db49SHeiko Stübner 5515245db49SHeiko Stübner ts = kzalloc(sizeof(struct auo_pixcir_ts), GFP_KERNEL); 5525245db49SHeiko Stübner if (!ts) 5535245db49SHeiko Stübner return -ENOMEM; 5545245db49SHeiko Stübner 5555245db49SHeiko Stübner ret = gpio_request(pdata->gpio_int, "auo_pixcir_ts_int"); 5565245db49SHeiko Stübner if (ret) { 5575245db49SHeiko Stübner dev_err(&client->dev, "request of gpio %d failed, %d\n", 5585245db49SHeiko Stübner pdata->gpio_int, ret); 5595245db49SHeiko Stübner goto err_gpio_int; 5605245db49SHeiko Stübner } 5615245db49SHeiko Stübner 562fa656308SHeiko Stübner ret = gpio_direction_input(pdata->gpio_int); 563fa656308SHeiko Stübner if (ret) { 564fa656308SHeiko Stübner dev_err(&client->dev, "setting direction of gpio %d failed %d\n", 565fa656308SHeiko Stübner pdata->gpio_int, ret); 566fa656308SHeiko Stübner goto err_gpio_dir; 567fa656308SHeiko Stübner } 568fa656308SHeiko Stübner 56927cef8b4SHeiko Stübner ret = gpio_request(pdata->gpio_rst, "auo_pixcir_ts_rst"); 57027cef8b4SHeiko Stübner if (ret) { 57127cef8b4SHeiko Stübner dev_err(&client->dev, "request of gpio %d failed, %d\n", 57227cef8b4SHeiko Stübner pdata->gpio_rst, ret); 57327cef8b4SHeiko Stübner goto err_gpio_dir; 57427cef8b4SHeiko Stübner } 57527cef8b4SHeiko Stübner 57627cef8b4SHeiko Stübner ret = gpio_direction_output(pdata->gpio_rst, 1); 57727cef8b4SHeiko Stübner if (ret) { 57827cef8b4SHeiko Stübner dev_err(&client->dev, "setting direction of gpio %d failed %d\n", 57927cef8b4SHeiko Stübner pdata->gpio_rst, ret); 58027cef8b4SHeiko Stübner goto err_gpio_rst; 58127cef8b4SHeiko Stübner } 58227cef8b4SHeiko Stübner 58327cef8b4SHeiko Stübner msleep(200); 5845245db49SHeiko Stübner 58538e83f7fSHeiko Stübner ts->pdata = pdata; 5865245db49SHeiko Stübner ts->client = client; 5875245db49SHeiko Stübner ts->touch_ind_mode = 0; 5885245db49SHeiko Stübner init_waitqueue_head(&ts->wait); 5895245db49SHeiko Stübner 5905245db49SHeiko Stübner snprintf(ts->phys, sizeof(ts->phys), 5915245db49SHeiko Stübner "%s/input0", dev_name(&client->dev)); 5925245db49SHeiko Stübner 5935245db49SHeiko Stübner input_dev = input_allocate_device(); 5945245db49SHeiko Stübner if (!input_dev) { 5955245db49SHeiko Stübner dev_err(&client->dev, "could not allocate input device\n"); 5965245db49SHeiko Stübner goto err_input_alloc; 5975245db49SHeiko Stübner } 5985245db49SHeiko Stübner 5995245db49SHeiko Stübner ts->input = input_dev; 6005245db49SHeiko Stübner 6015245db49SHeiko Stübner input_dev->name = "AUO-Pixcir touchscreen"; 6025245db49SHeiko Stübner input_dev->phys = ts->phys; 6035245db49SHeiko Stübner input_dev->id.bustype = BUS_I2C; 6045245db49SHeiko Stübner input_dev->dev.parent = &client->dev; 6055245db49SHeiko Stübner 6065245db49SHeiko Stübner input_dev->open = auo_pixcir_input_open; 6075245db49SHeiko Stübner input_dev->close = auo_pixcir_input_close; 6085245db49SHeiko Stübner 6095245db49SHeiko Stübner __set_bit(EV_ABS, input_dev->evbit); 6105245db49SHeiko Stübner __set_bit(EV_KEY, input_dev->evbit); 6115245db49SHeiko Stübner 6125245db49SHeiko Stübner __set_bit(BTN_TOUCH, input_dev->keybit); 6135245db49SHeiko Stübner 6145245db49SHeiko Stübner /* For single touch */ 6155245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_X, 0, pdata->x_max, 0, 0); 6165245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_Y, 0, pdata->y_max, 0, 0); 6175245db49SHeiko Stübner 6185245db49SHeiko Stübner /* For multi touch */ 6195245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 6205245db49SHeiko Stübner pdata->x_max, 0, 0); 6215245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 6225245db49SHeiko Stübner pdata->y_max, 0, 0); 6235245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 6245245db49SHeiko Stübner AUO_PIXCIR_MAX_AREA, 0, 0); 6255245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, 6265245db49SHeiko Stübner AUO_PIXCIR_MAX_AREA, 0, 0); 6275245db49SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); 6285245db49SHeiko Stübner 6295245db49SHeiko Stübner ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION); 6305245db49SHeiko Stübner if (ret < 0) 6315245db49SHeiko Stübner goto err_fw_vers; 6325245db49SHeiko Stübner dev_info(&client->dev, "firmware version 0x%X\n", ret); 6335245db49SHeiko Stübner 6345245db49SHeiko Stübner ret = auo_pixcir_int_config(ts, pdata->int_setting); 6355245db49SHeiko Stübner if (ret) 6365245db49SHeiko Stübner goto err_fw_vers; 6375245db49SHeiko Stübner 6385245db49SHeiko Stübner input_set_drvdata(ts->input, ts); 6395245db49SHeiko Stübner ts->stopped = true; 6405245db49SHeiko Stübner 6415245db49SHeiko Stübner ret = request_threaded_irq(client->irq, NULL, auo_pixcir_interrupt, 6425245db49SHeiko Stübner IRQF_TRIGGER_RISING | IRQF_ONESHOT, 6435245db49SHeiko Stübner input_dev->name, ts); 6445245db49SHeiko Stübner if (ret) { 6455245db49SHeiko Stübner dev_err(&client->dev, "irq %d requested failed\n", client->irq); 6465245db49SHeiko Stübner goto err_fw_vers; 6475245db49SHeiko Stübner } 6485245db49SHeiko Stübner 6495245db49SHeiko Stübner /* stop device and put it into deep sleep until it is opened */ 6505245db49SHeiko Stübner ret = auo_pixcir_stop(ts); 6515245db49SHeiko Stübner if (ret < 0) 6525245db49SHeiko Stübner goto err_input_register; 6535245db49SHeiko Stübner 6545245db49SHeiko Stübner ret = input_register_device(input_dev); 6555245db49SHeiko Stübner if (ret) { 6565245db49SHeiko Stübner dev_err(&client->dev, "could not register input device\n"); 6575245db49SHeiko Stübner goto err_input_register; 6585245db49SHeiko Stübner } 6595245db49SHeiko Stübner 6605245db49SHeiko Stübner i2c_set_clientdata(client, ts); 6615245db49SHeiko Stübner 6625245db49SHeiko Stübner return 0; 6635245db49SHeiko Stübner 6645245db49SHeiko Stübner err_input_register: 6655245db49SHeiko Stübner free_irq(client->irq, ts); 6665245db49SHeiko Stübner err_fw_vers: 6675245db49SHeiko Stübner input_free_device(input_dev); 6685245db49SHeiko Stübner err_input_alloc: 66927cef8b4SHeiko Stübner gpio_set_value(pdata->gpio_rst, 0); 67027cef8b4SHeiko Stübner err_gpio_rst: 67127cef8b4SHeiko Stübner gpio_free(pdata->gpio_rst); 672fa656308SHeiko Stübner err_gpio_dir: 6735245db49SHeiko Stübner gpio_free(pdata->gpio_int); 6745245db49SHeiko Stübner err_gpio_int: 6755245db49SHeiko Stübner kfree(ts); 6765245db49SHeiko Stübner 6775245db49SHeiko Stübner return ret; 6785245db49SHeiko Stübner } 6795245db49SHeiko Stübner 680e2619cf7SBill Pemberton static int auo_pixcir_remove(struct i2c_client *client) 6815245db49SHeiko Stübner { 6825245db49SHeiko Stübner struct auo_pixcir_ts *ts = i2c_get_clientdata(client); 68338e83f7fSHeiko Stübner const struct auo_pixcir_ts_platdata *pdata = ts->pdata; 6845245db49SHeiko Stübner 6855245db49SHeiko Stübner free_irq(client->irq, ts); 6865245db49SHeiko Stübner 6875245db49SHeiko Stübner input_unregister_device(ts->input); 6885245db49SHeiko Stübner 68927cef8b4SHeiko Stübner gpio_set_value(pdata->gpio_rst, 0); 69027cef8b4SHeiko Stübner gpio_free(pdata->gpio_rst); 6915245db49SHeiko Stübner 6925245db49SHeiko Stübner gpio_free(pdata->gpio_int); 6935245db49SHeiko Stübner 6945245db49SHeiko Stübner kfree(ts); 6955245db49SHeiko Stübner 6965245db49SHeiko Stübner return 0; 6975245db49SHeiko Stübner } 6985245db49SHeiko Stübner 6995245db49SHeiko Stübner static const struct i2c_device_id auo_pixcir_idtable[] = { 7005245db49SHeiko Stübner { "auo_pixcir_ts", 0 }, 7015245db49SHeiko Stübner { } 7025245db49SHeiko Stübner }; 7035245db49SHeiko Stübner MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable); 7045245db49SHeiko Stübner 7057241443fSHeiko Stübner #ifdef CONFIG_OF 7067241443fSHeiko Stübner static struct of_device_id auo_pixcir_ts_dt_idtable[] = { 7077241443fSHeiko Stübner { .compatible = "auo,auo_pixcir_ts" }, 7087241443fSHeiko Stübner {}, 7097241443fSHeiko Stübner }; 7107241443fSHeiko Stübner MODULE_DEVICE_TABLE(of, auo_pixcir_ts_dt_idtable); 7117241443fSHeiko Stübner #endif 7127241443fSHeiko Stübner 7135245db49SHeiko Stübner static struct i2c_driver auo_pixcir_driver = { 7145245db49SHeiko Stübner .driver = { 7155245db49SHeiko Stübner .owner = THIS_MODULE, 7165245db49SHeiko Stübner .name = "auo_pixcir_ts", 7175245db49SHeiko Stübner .pm = &auo_pixcir_pm_ops, 7187241443fSHeiko Stübner .of_match_table = of_match_ptr(auo_pixcir_ts_dt_idtable), 7195245db49SHeiko Stübner }, 7205245db49SHeiko Stübner .probe = auo_pixcir_probe, 7211cb0aa88SBill Pemberton .remove = auo_pixcir_remove, 7225245db49SHeiko Stübner .id_table = auo_pixcir_idtable, 7235245db49SHeiko Stübner }; 7245245db49SHeiko Stübner 7254a533835SDmitry Torokhov module_i2c_driver(auo_pixcir_driver); 7265245db49SHeiko Stübner 7275245db49SHeiko Stübner MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver"); 7285245db49SHeiko Stübner MODULE_LICENSE("GPL v2"); 7295245db49SHeiko Stübner MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 730