1ca96ea86SBastien Nocera /* 2ca96ea86SBastien Nocera * Driver for Goodix Touchscreens 3ca96ea86SBastien Nocera * 4ca96ea86SBastien Nocera * Copyright (c) 2014 Red Hat Inc. 5ca96ea86SBastien Nocera * 6ca96ea86SBastien Nocera * This code is based on gt9xx.c authored by andrew@goodix.com: 7ca96ea86SBastien Nocera * 8ca96ea86SBastien Nocera * 2010 - 2012 Goodix Technology. 9ca96ea86SBastien Nocera */ 10ca96ea86SBastien Nocera 11ca96ea86SBastien Nocera /* 12ca96ea86SBastien Nocera * This program is free software; you can redistribute it and/or modify it 13ca96ea86SBastien Nocera * under the terms of the GNU General Public License as published by the Free 14ca96ea86SBastien Nocera * Software Foundation; version 2 of the License. 15ca96ea86SBastien Nocera */ 16ca96ea86SBastien Nocera 17ca96ea86SBastien Nocera #include <linux/kernel.h> 188b5a359cSBastien Nocera #include <linux/dmi.h> 19ec6e1b40SIrina Tirdea #include <linux/gpio/consumer.h> 20ca96ea86SBastien Nocera #include <linux/i2c.h> 21ca96ea86SBastien Nocera #include <linux/input.h> 22ca96ea86SBastien Nocera #include <linux/input/mt.h> 23ca96ea86SBastien Nocera #include <linux/module.h> 24ca96ea86SBastien Nocera #include <linux/delay.h> 25ca96ea86SBastien Nocera #include <linux/irq.h> 26ca96ea86SBastien Nocera #include <linux/interrupt.h> 27ca96ea86SBastien Nocera #include <linux/slab.h> 28771d8f1bSAleksei Mamlin #include <linux/acpi.h> 29771d8f1bSAleksei Mamlin #include <linux/of.h> 30ca96ea86SBastien Nocera #include <asm/unaligned.h> 31ca96ea86SBastien Nocera 32ca96ea86SBastien Nocera struct goodix_ts_data { 33ca96ea86SBastien Nocera struct i2c_client *client; 34ca96ea86SBastien Nocera struct input_dev *input_dev; 35ca96ea86SBastien Nocera int abs_x_max; 36ca96ea86SBastien Nocera int abs_y_max; 37ca96ea86SBastien Nocera unsigned int max_touch_num; 38ca96ea86SBastien Nocera unsigned int int_trigger_type; 398b5a359cSBastien Nocera bool rotated_screen; 40a779fbc6SIrina Tirdea int cfg_len; 41ec6e1b40SIrina Tirdea struct gpio_desc *gpiod_int; 42ec6e1b40SIrina Tirdea struct gpio_desc *gpiod_rst; 43ca96ea86SBastien Nocera }; 44ca96ea86SBastien Nocera 45ec6e1b40SIrina Tirdea #define GOODIX_GPIO_INT_NAME "irq" 46ec6e1b40SIrina Tirdea #define GOODIX_GPIO_RST_NAME "reset" 47ec6e1b40SIrina Tirdea 48ca96ea86SBastien Nocera #define GOODIX_MAX_HEIGHT 4096 49ca96ea86SBastien Nocera #define GOODIX_MAX_WIDTH 4096 50ca96ea86SBastien Nocera #define GOODIX_INT_TRIGGER 1 51ca96ea86SBastien Nocera #define GOODIX_CONTACT_SIZE 8 52ca96ea86SBastien Nocera #define GOODIX_MAX_CONTACTS 10 53ca96ea86SBastien Nocera 54ca96ea86SBastien Nocera #define GOODIX_CONFIG_MAX_LENGTH 240 55a779fbc6SIrina Tirdea #define GOODIX_CONFIG_911_LENGTH 186 56a779fbc6SIrina Tirdea #define GOODIX_CONFIG_967_LENGTH 228 57ca96ea86SBastien Nocera 58ca96ea86SBastien Nocera /* Register defines */ 59ca96ea86SBastien Nocera #define GOODIX_READ_COOR_ADDR 0x814E 60ca96ea86SBastien Nocera #define GOODIX_REG_CONFIG_DATA 0x8047 61e70b0307SIrina Tirdea #define GOODIX_REG_ID 0x8140 62ca96ea86SBastien Nocera 63ca96ea86SBastien Nocera #define RESOLUTION_LOC 1 64a7ac7c95SAleksei Mamlin #define MAX_CONTACTS_LOC 5 65ca96ea86SBastien Nocera #define TRIGGER_LOC 6 66ca96ea86SBastien Nocera 67ca96ea86SBastien Nocera static const unsigned long goodix_irq_flags[] = { 68ca96ea86SBastien Nocera IRQ_TYPE_EDGE_RISING, 69ca96ea86SBastien Nocera IRQ_TYPE_EDGE_FALLING, 70ca96ea86SBastien Nocera IRQ_TYPE_LEVEL_LOW, 71ca96ea86SBastien Nocera IRQ_TYPE_LEVEL_HIGH, 72ca96ea86SBastien Nocera }; 73ca96ea86SBastien Nocera 748b5a359cSBastien Nocera /* 758b5a359cSBastien Nocera * Those tablets have their coordinates origin at the bottom right 768b5a359cSBastien Nocera * of the tablet, as if rotated 180 degrees 778b5a359cSBastien Nocera */ 788b5a359cSBastien Nocera static const struct dmi_system_id rotated_screen[] = { 798b5a359cSBastien Nocera #if defined(CONFIG_DMI) && defined(CONFIG_X86) 808b5a359cSBastien Nocera { 818b5a359cSBastien Nocera .ident = "WinBook TW100", 828b5a359cSBastien Nocera .matches = { 838b5a359cSBastien Nocera DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), 848b5a359cSBastien Nocera DMI_MATCH(DMI_PRODUCT_NAME, "TW100") 858b5a359cSBastien Nocera } 868b5a359cSBastien Nocera }, 878b5a359cSBastien Nocera { 888b5a359cSBastien Nocera .ident = "WinBook TW700", 898b5a359cSBastien Nocera .matches = { 908b5a359cSBastien Nocera DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), 918b5a359cSBastien Nocera DMI_MATCH(DMI_PRODUCT_NAME, "TW700") 928b5a359cSBastien Nocera }, 938b5a359cSBastien Nocera }, 948b5a359cSBastien Nocera #endif 958b5a359cSBastien Nocera {} 968b5a359cSBastien Nocera }; 978b5a359cSBastien Nocera 98ca96ea86SBastien Nocera /** 99ca96ea86SBastien Nocera * goodix_i2c_read - read data from a register of the i2c slave device. 100ca96ea86SBastien Nocera * 101ca96ea86SBastien Nocera * @client: i2c device. 102ca96ea86SBastien Nocera * @reg: the register to read from. 103ca96ea86SBastien Nocera * @buf: raw write data buffer. 104ca96ea86SBastien Nocera * @len: length of the buffer to write 105ca96ea86SBastien Nocera */ 106ca96ea86SBastien Nocera static int goodix_i2c_read(struct i2c_client *client, 107ca96ea86SBastien Nocera u16 reg, u8 *buf, int len) 108ca96ea86SBastien Nocera { 109ca96ea86SBastien Nocera struct i2c_msg msgs[2]; 110ca96ea86SBastien Nocera u16 wbuf = cpu_to_be16(reg); 111ca96ea86SBastien Nocera int ret; 112ca96ea86SBastien Nocera 113ca96ea86SBastien Nocera msgs[0].flags = 0; 114ca96ea86SBastien Nocera msgs[0].addr = client->addr; 115ca96ea86SBastien Nocera msgs[0].len = 2; 116ca96ea86SBastien Nocera msgs[0].buf = (u8 *)&wbuf; 117ca96ea86SBastien Nocera 118ca96ea86SBastien Nocera msgs[1].flags = I2C_M_RD; 119ca96ea86SBastien Nocera msgs[1].addr = client->addr; 120ca96ea86SBastien Nocera msgs[1].len = len; 121ca96ea86SBastien Nocera msgs[1].buf = buf; 122ca96ea86SBastien Nocera 123ca96ea86SBastien Nocera ret = i2c_transfer(client->adapter, msgs, 2); 124ca96ea86SBastien Nocera return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0); 125ca96ea86SBastien Nocera } 126ca96ea86SBastien Nocera 127a779fbc6SIrina Tirdea static int goodix_get_cfg_len(u16 id) 128a779fbc6SIrina Tirdea { 129a779fbc6SIrina Tirdea switch (id) { 130a779fbc6SIrina Tirdea case 911: 131a779fbc6SIrina Tirdea case 9271: 132a779fbc6SIrina Tirdea case 9110: 133a779fbc6SIrina Tirdea case 927: 134a779fbc6SIrina Tirdea case 928: 135a779fbc6SIrina Tirdea return GOODIX_CONFIG_911_LENGTH; 136a779fbc6SIrina Tirdea 137a779fbc6SIrina Tirdea case 912: 138a779fbc6SIrina Tirdea case 967: 139a779fbc6SIrina Tirdea return GOODIX_CONFIG_967_LENGTH; 140a779fbc6SIrina Tirdea 141a779fbc6SIrina Tirdea default: 142a779fbc6SIrina Tirdea return GOODIX_CONFIG_MAX_LENGTH; 143a779fbc6SIrina Tirdea } 144a779fbc6SIrina Tirdea } 145a779fbc6SIrina Tirdea 146ca96ea86SBastien Nocera static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) 147ca96ea86SBastien Nocera { 148ca96ea86SBastien Nocera int touch_num; 149ca96ea86SBastien Nocera int error; 150ca96ea86SBastien Nocera 151ca96ea86SBastien Nocera error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data, 152ca96ea86SBastien Nocera GOODIX_CONTACT_SIZE + 1); 153ca96ea86SBastien Nocera if (error) { 154ca96ea86SBastien Nocera dev_err(&ts->client->dev, "I2C transfer error: %d\n", error); 155ca96ea86SBastien Nocera return error; 156ca96ea86SBastien Nocera } 157ca96ea86SBastien Nocera 1585f6f117cSPaul Cercueil if (!(data[0] & 0x80)) 1595f6f117cSPaul Cercueil return -EAGAIN; 1605f6f117cSPaul Cercueil 161ca96ea86SBastien Nocera touch_num = data[0] & 0x0f; 162a7ac7c95SAleksei Mamlin if (touch_num > ts->max_touch_num) 163ca96ea86SBastien Nocera return -EPROTO; 164ca96ea86SBastien Nocera 165ca96ea86SBastien Nocera if (touch_num > 1) { 166ca96ea86SBastien Nocera data += 1 + GOODIX_CONTACT_SIZE; 167ca96ea86SBastien Nocera error = goodix_i2c_read(ts->client, 168ca96ea86SBastien Nocera GOODIX_READ_COOR_ADDR + 169ca96ea86SBastien Nocera 1 + GOODIX_CONTACT_SIZE, 170ca96ea86SBastien Nocera data, 171ca96ea86SBastien Nocera GOODIX_CONTACT_SIZE * (touch_num - 1)); 172ca96ea86SBastien Nocera if (error) 173ca96ea86SBastien Nocera return error; 174ca96ea86SBastien Nocera } 175ca96ea86SBastien Nocera 176ca96ea86SBastien Nocera return touch_num; 177ca96ea86SBastien Nocera } 178ca96ea86SBastien Nocera 179ca96ea86SBastien Nocera static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) 180ca96ea86SBastien Nocera { 181ca96ea86SBastien Nocera int id = coor_data[0] & 0x0F; 182ca96ea86SBastien Nocera int input_x = get_unaligned_le16(&coor_data[1]); 183ca96ea86SBastien Nocera int input_y = get_unaligned_le16(&coor_data[3]); 184ca96ea86SBastien Nocera int input_w = get_unaligned_le16(&coor_data[5]); 185ca96ea86SBastien Nocera 1868b5a359cSBastien Nocera if (ts->rotated_screen) { 1878b5a359cSBastien Nocera input_x = ts->abs_x_max - input_x; 1888b5a359cSBastien Nocera input_y = ts->abs_y_max - input_y; 1898b5a359cSBastien Nocera } 1908b5a359cSBastien Nocera 191ca96ea86SBastien Nocera input_mt_slot(ts->input_dev, id); 192ca96ea86SBastien Nocera input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); 193ca96ea86SBastien Nocera input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x); 194ca96ea86SBastien Nocera input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y); 195ca96ea86SBastien Nocera input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w); 196ca96ea86SBastien Nocera input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w); 197ca96ea86SBastien Nocera } 198ca96ea86SBastien Nocera 199ca96ea86SBastien Nocera /** 200ca96ea86SBastien Nocera * goodix_process_events - Process incoming events 201ca96ea86SBastien Nocera * 202ca96ea86SBastien Nocera * @ts: our goodix_ts_data pointer 203ca96ea86SBastien Nocera * 204ca96ea86SBastien Nocera * Called when the IRQ is triggered. Read the current device state, and push 205ca96ea86SBastien Nocera * the input events to the user space. 206ca96ea86SBastien Nocera */ 207ca96ea86SBastien Nocera static void goodix_process_events(struct goodix_ts_data *ts) 208ca96ea86SBastien Nocera { 2090e0432f0SIrina Tirdea u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS]; 210ca96ea86SBastien Nocera int touch_num; 211ca96ea86SBastien Nocera int i; 212ca96ea86SBastien Nocera 213ca96ea86SBastien Nocera touch_num = goodix_ts_read_input_report(ts, point_data); 214ca96ea86SBastien Nocera if (touch_num < 0) 215ca96ea86SBastien Nocera return; 216ca96ea86SBastien Nocera 217ca96ea86SBastien Nocera for (i = 0; i < touch_num; i++) 218ca96ea86SBastien Nocera goodix_ts_report_touch(ts, 219ca96ea86SBastien Nocera &point_data[1 + GOODIX_CONTACT_SIZE * i]); 220ca96ea86SBastien Nocera 221ca96ea86SBastien Nocera input_mt_sync_frame(ts->input_dev); 222ca96ea86SBastien Nocera input_sync(ts->input_dev); 223ca96ea86SBastien Nocera } 224ca96ea86SBastien Nocera 225ca96ea86SBastien Nocera /** 226ca96ea86SBastien Nocera * goodix_ts_irq_handler - The IRQ handler 227ca96ea86SBastien Nocera * 228ca96ea86SBastien Nocera * @irq: interrupt number. 229ca96ea86SBastien Nocera * @dev_id: private data pointer. 230ca96ea86SBastien Nocera */ 231ca96ea86SBastien Nocera static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) 232ca96ea86SBastien Nocera { 233ca96ea86SBastien Nocera static const u8 end_cmd[] = { 234ca96ea86SBastien Nocera GOODIX_READ_COOR_ADDR >> 8, 235ca96ea86SBastien Nocera GOODIX_READ_COOR_ADDR & 0xff, 236ca96ea86SBastien Nocera 0 237ca96ea86SBastien Nocera }; 238ca96ea86SBastien Nocera struct goodix_ts_data *ts = dev_id; 239ca96ea86SBastien Nocera 240ca96ea86SBastien Nocera goodix_process_events(ts); 241ca96ea86SBastien Nocera 242ca96ea86SBastien Nocera if (i2c_master_send(ts->client, end_cmd, sizeof(end_cmd)) < 0) 243ca96ea86SBastien Nocera dev_err(&ts->client->dev, "I2C write end_cmd error\n"); 244ca96ea86SBastien Nocera 245ca96ea86SBastien Nocera return IRQ_HANDLED; 246ca96ea86SBastien Nocera } 247ca96ea86SBastien Nocera 248ec6e1b40SIrina Tirdea static int goodix_int_sync(struct goodix_ts_data *ts) 249ec6e1b40SIrina Tirdea { 250ec6e1b40SIrina Tirdea int error; 251ec6e1b40SIrina Tirdea 252ec6e1b40SIrina Tirdea error = gpiod_direction_output(ts->gpiod_int, 0); 253ec6e1b40SIrina Tirdea if (error) 254ec6e1b40SIrina Tirdea return error; 255ec6e1b40SIrina Tirdea 256ec6e1b40SIrina Tirdea msleep(50); /* T5: 50ms */ 257ec6e1b40SIrina Tirdea 258ec6e1b40SIrina Tirdea error = gpiod_direction_input(ts->gpiod_int); 259ec6e1b40SIrina Tirdea if (error) 260ec6e1b40SIrina Tirdea return error; 261ec6e1b40SIrina Tirdea 262ec6e1b40SIrina Tirdea return 0; 263ec6e1b40SIrina Tirdea } 264ec6e1b40SIrina Tirdea 265ec6e1b40SIrina Tirdea /** 266ec6e1b40SIrina Tirdea * goodix_reset - Reset device during power on 267ec6e1b40SIrina Tirdea * 268ec6e1b40SIrina Tirdea * @ts: goodix_ts_data pointer 269ec6e1b40SIrina Tirdea */ 270ec6e1b40SIrina Tirdea static int goodix_reset(struct goodix_ts_data *ts) 271ec6e1b40SIrina Tirdea { 272ec6e1b40SIrina Tirdea int error; 273ec6e1b40SIrina Tirdea 274ec6e1b40SIrina Tirdea /* begin select I2C slave addr */ 275ec6e1b40SIrina Tirdea error = gpiod_direction_output(ts->gpiod_rst, 0); 276ec6e1b40SIrina Tirdea if (error) 277ec6e1b40SIrina Tirdea return error; 278ec6e1b40SIrina Tirdea 279ec6e1b40SIrina Tirdea msleep(20); /* T2: > 10ms */ 280ec6e1b40SIrina Tirdea 281ec6e1b40SIrina Tirdea /* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */ 282ec6e1b40SIrina Tirdea error = gpiod_direction_output(ts->gpiod_int, ts->client->addr == 0x14); 283ec6e1b40SIrina Tirdea if (error) 284ec6e1b40SIrina Tirdea return error; 285ec6e1b40SIrina Tirdea 286ec6e1b40SIrina Tirdea usleep_range(100, 2000); /* T3: > 100us */ 287ec6e1b40SIrina Tirdea 288ec6e1b40SIrina Tirdea error = gpiod_direction_output(ts->gpiod_rst, 1); 289ec6e1b40SIrina Tirdea if (error) 290ec6e1b40SIrina Tirdea return error; 291ec6e1b40SIrina Tirdea 292ec6e1b40SIrina Tirdea usleep_range(6000, 10000); /* T4: > 5ms */ 293ec6e1b40SIrina Tirdea 294ec6e1b40SIrina Tirdea /* end select I2C slave addr */ 295ec6e1b40SIrina Tirdea error = gpiod_direction_input(ts->gpiod_rst); 296ec6e1b40SIrina Tirdea if (error) 297ec6e1b40SIrina Tirdea return error; 298ec6e1b40SIrina Tirdea 299ec6e1b40SIrina Tirdea error = goodix_int_sync(ts); 300ec6e1b40SIrina Tirdea if (error) 301ec6e1b40SIrina Tirdea return error; 302ec6e1b40SIrina Tirdea 303ec6e1b40SIrina Tirdea return 0; 304ec6e1b40SIrina Tirdea } 305ec6e1b40SIrina Tirdea 306ec6e1b40SIrina Tirdea /** 307ec6e1b40SIrina Tirdea * goodix_get_gpio_config - Get GPIO config from ACPI/DT 308ec6e1b40SIrina Tirdea * 309ec6e1b40SIrina Tirdea * @ts: goodix_ts_data pointer 310ec6e1b40SIrina Tirdea */ 311ec6e1b40SIrina Tirdea static int goodix_get_gpio_config(struct goodix_ts_data *ts) 312ec6e1b40SIrina Tirdea { 313ec6e1b40SIrina Tirdea int error; 314ec6e1b40SIrina Tirdea struct device *dev; 315ec6e1b40SIrina Tirdea struct gpio_desc *gpiod; 316ec6e1b40SIrina Tirdea 317ec6e1b40SIrina Tirdea if (!ts->client) 318ec6e1b40SIrina Tirdea return -EINVAL; 319ec6e1b40SIrina Tirdea dev = &ts->client->dev; 320ec6e1b40SIrina Tirdea 321ec6e1b40SIrina Tirdea /* Get the interrupt GPIO pin number */ 322ec6e1b40SIrina Tirdea gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); 323ec6e1b40SIrina Tirdea if (IS_ERR(gpiod)) { 324ec6e1b40SIrina Tirdea error = PTR_ERR(gpiod); 325ec6e1b40SIrina Tirdea if (error != -EPROBE_DEFER) 326ec6e1b40SIrina Tirdea dev_dbg(dev, "Failed to get %s GPIO: %d\n", 327ec6e1b40SIrina Tirdea GOODIX_GPIO_INT_NAME, error); 328ec6e1b40SIrina Tirdea return error; 329ec6e1b40SIrina Tirdea } 330ec6e1b40SIrina Tirdea 331ec6e1b40SIrina Tirdea ts->gpiod_int = gpiod; 332ec6e1b40SIrina Tirdea 333ec6e1b40SIrina Tirdea /* Get the reset line GPIO pin number */ 334ec6e1b40SIrina Tirdea gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, GPIOD_IN); 335ec6e1b40SIrina Tirdea if (IS_ERR(gpiod)) { 336ec6e1b40SIrina Tirdea error = PTR_ERR(gpiod); 337ec6e1b40SIrina Tirdea if (error != -EPROBE_DEFER) 338ec6e1b40SIrina Tirdea dev_dbg(dev, "Failed to get %s GPIO: %d\n", 339ec6e1b40SIrina Tirdea GOODIX_GPIO_RST_NAME, error); 340ec6e1b40SIrina Tirdea return error; 341ec6e1b40SIrina Tirdea } 342ec6e1b40SIrina Tirdea 343ec6e1b40SIrina Tirdea ts->gpiod_rst = gpiod; 344ec6e1b40SIrina Tirdea 345ec6e1b40SIrina Tirdea return 0; 346ec6e1b40SIrina Tirdea } 347ec6e1b40SIrina Tirdea 348ca96ea86SBastien Nocera /** 349ca96ea86SBastien Nocera * goodix_read_config - Read the embedded configuration of the panel 350ca96ea86SBastien Nocera * 351ca96ea86SBastien Nocera * @ts: our goodix_ts_data pointer 352ca96ea86SBastien Nocera * 353ca96ea86SBastien Nocera * Must be called during probe 354ca96ea86SBastien Nocera */ 355ca96ea86SBastien Nocera static void goodix_read_config(struct goodix_ts_data *ts) 356ca96ea86SBastien Nocera { 357ca96ea86SBastien Nocera u8 config[GOODIX_CONFIG_MAX_LENGTH]; 358ca96ea86SBastien Nocera int error; 359ca96ea86SBastien Nocera 360ca96ea86SBastien Nocera error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA, 361a779fbc6SIrina Tirdea config, ts->cfg_len); 362ca96ea86SBastien Nocera if (error) { 363ca96ea86SBastien Nocera dev_warn(&ts->client->dev, 364ca96ea86SBastien Nocera "Error reading config (%d), using defaults\n", 365ca96ea86SBastien Nocera error); 366ca96ea86SBastien Nocera ts->abs_x_max = GOODIX_MAX_WIDTH; 367ca96ea86SBastien Nocera ts->abs_y_max = GOODIX_MAX_HEIGHT; 368ca96ea86SBastien Nocera ts->int_trigger_type = GOODIX_INT_TRIGGER; 369a7ac7c95SAleksei Mamlin ts->max_touch_num = GOODIX_MAX_CONTACTS; 370ca96ea86SBastien Nocera return; 371ca96ea86SBastien Nocera } 372ca96ea86SBastien Nocera 373ca96ea86SBastien Nocera ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); 374ca96ea86SBastien Nocera ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); 375a7ac7c95SAleksei Mamlin ts->int_trigger_type = config[TRIGGER_LOC] & 0x03; 376a7ac7c95SAleksei Mamlin ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f; 377a7ac7c95SAleksei Mamlin if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) { 378ca96ea86SBastien Nocera dev_err(&ts->client->dev, 379ca96ea86SBastien Nocera "Invalid config, using defaults\n"); 380ca96ea86SBastien Nocera ts->abs_x_max = GOODIX_MAX_WIDTH; 381ca96ea86SBastien Nocera ts->abs_y_max = GOODIX_MAX_HEIGHT; 382a7ac7c95SAleksei Mamlin ts->max_touch_num = GOODIX_MAX_CONTACTS; 383ca96ea86SBastien Nocera } 3848b5a359cSBastien Nocera 3858b5a359cSBastien Nocera ts->rotated_screen = dmi_check_system(rotated_screen); 3868b5a359cSBastien Nocera if (ts->rotated_screen) 3878b5a359cSBastien Nocera dev_dbg(&ts->client->dev, 3888b5a359cSBastien Nocera "Applying '180 degrees rotated screen' quirk\n"); 389ca96ea86SBastien Nocera } 390ca96ea86SBastien Nocera 391ca96ea86SBastien Nocera /** 392ca96ea86SBastien Nocera * goodix_read_version - Read goodix touchscreen version 393ca96ea86SBastien Nocera * 394ca96ea86SBastien Nocera * @client: the i2c client 395ca96ea86SBastien Nocera * @version: output buffer containing the version on success 396e70b0307SIrina Tirdea * @id: output buffer containing the id on success 397ca96ea86SBastien Nocera */ 398e70b0307SIrina Tirdea static int goodix_read_version(struct i2c_client *client, u16 *version, u16 *id) 399ca96ea86SBastien Nocera { 400ca96ea86SBastien Nocera int error; 401ca96ea86SBastien Nocera u8 buf[6]; 402e70b0307SIrina Tirdea char id_str[5]; 403ca96ea86SBastien Nocera 404e70b0307SIrina Tirdea error = goodix_i2c_read(client, GOODIX_REG_ID, buf, sizeof(buf)); 405ca96ea86SBastien Nocera if (error) { 406ca96ea86SBastien Nocera dev_err(&client->dev, "read version failed: %d\n", error); 407ca96ea86SBastien Nocera return error; 408ca96ea86SBastien Nocera } 409ca96ea86SBastien Nocera 410e70b0307SIrina Tirdea memcpy(id_str, buf, 4); 411e70b0307SIrina Tirdea id_str[4] = 0; 412e70b0307SIrina Tirdea if (kstrtou16(id_str, 10, id)) 413e70b0307SIrina Tirdea *id = 0x1001; 414e70b0307SIrina Tirdea 415ca96ea86SBastien Nocera *version = get_unaligned_le16(&buf[4]); 416ca96ea86SBastien Nocera 417e70b0307SIrina Tirdea dev_info(&client->dev, "ID %d, version: %04x\n", *id, *version); 418ca96ea86SBastien Nocera 419ca96ea86SBastien Nocera return 0; 420ca96ea86SBastien Nocera } 421ca96ea86SBastien Nocera 422ca96ea86SBastien Nocera /** 423ca96ea86SBastien Nocera * goodix_i2c_test - I2C test function to check if the device answers. 424ca96ea86SBastien Nocera * 425ca96ea86SBastien Nocera * @client: the i2c client 426ca96ea86SBastien Nocera */ 427ca96ea86SBastien Nocera static int goodix_i2c_test(struct i2c_client *client) 428ca96ea86SBastien Nocera { 429ca96ea86SBastien Nocera int retry = 0; 430ca96ea86SBastien Nocera int error; 431ca96ea86SBastien Nocera u8 test; 432ca96ea86SBastien Nocera 433ca96ea86SBastien Nocera while (retry++ < 2) { 434ca96ea86SBastien Nocera error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA, 435ca96ea86SBastien Nocera &test, 1); 436ca96ea86SBastien Nocera if (!error) 437ca96ea86SBastien Nocera return 0; 438ca96ea86SBastien Nocera 439ca96ea86SBastien Nocera dev_err(&client->dev, "i2c test failed attempt %d: %d\n", 440ca96ea86SBastien Nocera retry, error); 441ca96ea86SBastien Nocera msleep(20); 442ca96ea86SBastien Nocera } 443ca96ea86SBastien Nocera 444ca96ea86SBastien Nocera return error; 445ca96ea86SBastien Nocera } 446ca96ea86SBastien Nocera 447ca96ea86SBastien Nocera /** 448ca96ea86SBastien Nocera * goodix_request_input_dev - Allocate, populate and register the input device 449ca96ea86SBastien Nocera * 450ca96ea86SBastien Nocera * @ts: our goodix_ts_data pointer 451e70b0307SIrina Tirdea * @version: device firmware version 452e70b0307SIrina Tirdea * @id: device ID 453ca96ea86SBastien Nocera * 454ca96ea86SBastien Nocera * Must be called during probe 455ca96ea86SBastien Nocera */ 456e70b0307SIrina Tirdea static int goodix_request_input_dev(struct goodix_ts_data *ts, u16 version, 457e70b0307SIrina Tirdea u16 id) 458ca96ea86SBastien Nocera { 459ca96ea86SBastien Nocera int error; 460ca96ea86SBastien Nocera 461ca96ea86SBastien Nocera ts->input_dev = devm_input_allocate_device(&ts->client->dev); 462ca96ea86SBastien Nocera if (!ts->input_dev) { 463ca96ea86SBastien Nocera dev_err(&ts->client->dev, "Failed to allocate input device."); 464ca96ea86SBastien Nocera return -ENOMEM; 465ca96ea86SBastien Nocera } 466ca96ea86SBastien Nocera 4670dfb35bdSIrina Tirdea input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 4680dfb35bdSIrina Tirdea 0, ts->abs_x_max, 0, 0); 4690dfb35bdSIrina Tirdea input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 4700dfb35bdSIrina Tirdea 0, ts->abs_y_max, 0, 0); 471ca96ea86SBastien Nocera input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); 472ca96ea86SBastien Nocera input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); 473ca96ea86SBastien Nocera 474a7ac7c95SAleksei Mamlin input_mt_init_slots(ts->input_dev, ts->max_touch_num, 475ca96ea86SBastien Nocera INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 476ca96ea86SBastien Nocera 477ca96ea86SBastien Nocera ts->input_dev->name = "Goodix Capacitive TouchScreen"; 478ca96ea86SBastien Nocera ts->input_dev->phys = "input/ts"; 479ca96ea86SBastien Nocera ts->input_dev->id.bustype = BUS_I2C; 480ca96ea86SBastien Nocera ts->input_dev->id.vendor = 0x0416; 481e70b0307SIrina Tirdea ts->input_dev->id.product = id; 482e70b0307SIrina Tirdea ts->input_dev->id.version = version; 483ca96ea86SBastien Nocera 484ca96ea86SBastien Nocera error = input_register_device(ts->input_dev); 485ca96ea86SBastien Nocera if (error) { 486ca96ea86SBastien Nocera dev_err(&ts->client->dev, 487ca96ea86SBastien Nocera "Failed to register input device: %d", error); 488ca96ea86SBastien Nocera return error; 489ca96ea86SBastien Nocera } 490ca96ea86SBastien Nocera 491ca96ea86SBastien Nocera return 0; 492ca96ea86SBastien Nocera } 493ca96ea86SBastien Nocera 494ca96ea86SBastien Nocera static int goodix_ts_probe(struct i2c_client *client, 495ca96ea86SBastien Nocera const struct i2c_device_id *id) 496ca96ea86SBastien Nocera { 497ca96ea86SBastien Nocera struct goodix_ts_data *ts; 498ca96ea86SBastien Nocera unsigned long irq_flags; 499ca96ea86SBastien Nocera int error; 500e70b0307SIrina Tirdea u16 version_info, id_info; 501ca96ea86SBastien Nocera 502ca96ea86SBastien Nocera dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr); 503ca96ea86SBastien Nocera 504ca96ea86SBastien Nocera if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 505ca96ea86SBastien Nocera dev_err(&client->dev, "I2C check functionality failed.\n"); 506ca96ea86SBastien Nocera return -ENXIO; 507ca96ea86SBastien Nocera } 508ca96ea86SBastien Nocera 509ca96ea86SBastien Nocera ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); 510ca96ea86SBastien Nocera if (!ts) 511ca96ea86SBastien Nocera return -ENOMEM; 512ca96ea86SBastien Nocera 513ca96ea86SBastien Nocera ts->client = client; 514ca96ea86SBastien Nocera i2c_set_clientdata(client, ts); 515ca96ea86SBastien Nocera 516ec6e1b40SIrina Tirdea error = goodix_get_gpio_config(ts); 517ec6e1b40SIrina Tirdea if (error) 518ec6e1b40SIrina Tirdea return error; 519ec6e1b40SIrina Tirdea 520ec6e1b40SIrina Tirdea if (ts->gpiod_int && ts->gpiod_rst) { 521ec6e1b40SIrina Tirdea /* reset the controller */ 522ec6e1b40SIrina Tirdea error = goodix_reset(ts); 523ec6e1b40SIrina Tirdea if (error) { 524ec6e1b40SIrina Tirdea dev_err(&client->dev, "Controller reset failed.\n"); 525ec6e1b40SIrina Tirdea return error; 526ec6e1b40SIrina Tirdea } 527ec6e1b40SIrina Tirdea } 528ec6e1b40SIrina Tirdea 529ca96ea86SBastien Nocera error = goodix_i2c_test(client); 530ca96ea86SBastien Nocera if (error) { 531ca96ea86SBastien Nocera dev_err(&client->dev, "I2C communication failure: %d\n", error); 532ca96ea86SBastien Nocera return error; 533ca96ea86SBastien Nocera } 534ca96ea86SBastien Nocera 535e70b0307SIrina Tirdea error = goodix_read_version(client, &version_info, &id_info); 536ca96ea86SBastien Nocera if (error) { 537ca96ea86SBastien Nocera dev_err(&client->dev, "Read version failed.\n"); 538ca96ea86SBastien Nocera return error; 539ca96ea86SBastien Nocera } 540ca96ea86SBastien Nocera 541a779fbc6SIrina Tirdea ts->cfg_len = goodix_get_cfg_len(id_info); 542a779fbc6SIrina Tirdea 543ca96ea86SBastien Nocera goodix_read_config(ts); 544ca96ea86SBastien Nocera 545e70b0307SIrina Tirdea error = goodix_request_input_dev(ts, version_info, id_info); 546ca96ea86SBastien Nocera if (error) 547ca96ea86SBastien Nocera return error; 548ca96ea86SBastien Nocera 549ca96ea86SBastien Nocera irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT; 550ca96ea86SBastien Nocera error = devm_request_threaded_irq(&ts->client->dev, client->irq, 551ca96ea86SBastien Nocera NULL, goodix_ts_irq_handler, 552ca96ea86SBastien Nocera irq_flags, client->name, ts); 553ca96ea86SBastien Nocera if (error) { 554ca96ea86SBastien Nocera dev_err(&client->dev, "request IRQ failed: %d\n", error); 555ca96ea86SBastien Nocera return error; 556ca96ea86SBastien Nocera } 557ca96ea86SBastien Nocera 558ca96ea86SBastien Nocera return 0; 559ca96ea86SBastien Nocera } 560ca96ea86SBastien Nocera 561ca96ea86SBastien Nocera static const struct i2c_device_id goodix_ts_id[] = { 562ca96ea86SBastien Nocera { "GDIX1001:00", 0 }, 563ca96ea86SBastien Nocera { } 564ca96ea86SBastien Nocera }; 5652e9e910eSJavier Martinez Canillas MODULE_DEVICE_TABLE(i2c, goodix_ts_id); 566ca96ea86SBastien Nocera 567771d8f1bSAleksei Mamlin #ifdef CONFIG_ACPI 568ca96ea86SBastien Nocera static const struct acpi_device_id goodix_acpi_match[] = { 569ca96ea86SBastien Nocera { "GDIX1001", 0 }, 570ca96ea86SBastien Nocera { } 571ca96ea86SBastien Nocera }; 572ca96ea86SBastien Nocera MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); 573771d8f1bSAleksei Mamlin #endif 574771d8f1bSAleksei Mamlin 575771d8f1bSAleksei Mamlin #ifdef CONFIG_OF 576771d8f1bSAleksei Mamlin static const struct of_device_id goodix_of_match[] = { 577771d8f1bSAleksei Mamlin { .compatible = "goodix,gt911" }, 578771d8f1bSAleksei Mamlin { .compatible = "goodix,gt9110" }, 579771d8f1bSAleksei Mamlin { .compatible = "goodix,gt912" }, 580771d8f1bSAleksei Mamlin { .compatible = "goodix,gt927" }, 581771d8f1bSAleksei Mamlin { .compatible = "goodix,gt9271" }, 582771d8f1bSAleksei Mamlin { .compatible = "goodix,gt928" }, 583771d8f1bSAleksei Mamlin { .compatible = "goodix,gt967" }, 584771d8f1bSAleksei Mamlin { } 585771d8f1bSAleksei Mamlin }; 586771d8f1bSAleksei Mamlin MODULE_DEVICE_TABLE(of, goodix_of_match); 587771d8f1bSAleksei Mamlin #endif 588ca96ea86SBastien Nocera 589ca96ea86SBastien Nocera static struct i2c_driver goodix_ts_driver = { 590ca96ea86SBastien Nocera .probe = goodix_ts_probe, 591ca96ea86SBastien Nocera .id_table = goodix_ts_id, 592ca96ea86SBastien Nocera .driver = { 593ca96ea86SBastien Nocera .name = "Goodix-TS", 594771d8f1bSAleksei Mamlin .acpi_match_table = ACPI_PTR(goodix_acpi_match), 595771d8f1bSAleksei Mamlin .of_match_table = of_match_ptr(goodix_of_match), 596ca96ea86SBastien Nocera }, 597ca96ea86SBastien Nocera }; 598ca96ea86SBastien Nocera module_i2c_driver(goodix_ts_driver); 599ca96ea86SBastien Nocera 600ca96ea86SBastien Nocera MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); 601ca96ea86SBastien Nocera MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>"); 602ca96ea86SBastien Nocera MODULE_DESCRIPTION("Goodix touchscreen driver"); 603ca96ea86SBastien Nocera MODULE_LICENSE("GPL v2"); 604