12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29ca5bf50SSiebren Vroegindeweij /* 39ca5bf50SSiebren Vroegindeweij * Driver for ELAN eKTF2127 i2c touchscreen controller 49ca5bf50SSiebren Vroegindeweij * 59ca5bf50SSiebren Vroegindeweij * For this driver the layout of the Chipone icn8318 i2c 69ca5bf50SSiebren Vroegindeweij * touchscreencontroller is used. 79ca5bf50SSiebren Vroegindeweij * 89ca5bf50SSiebren Vroegindeweij * Author: 99ca5bf50SSiebren Vroegindeweij * Michel Verlaan <michel.verl@gmail.com> 109ca5bf50SSiebren Vroegindeweij * Siebren Vroegindeweij <siebren.vroegindeweij@hotmail.com> 119ca5bf50SSiebren Vroegindeweij * 129ca5bf50SSiebren Vroegindeweij * Original chipone_icn8318 driver: 139ca5bf50SSiebren Vroegindeweij * Hans de Goede <hdegoede@redhat.com> 149ca5bf50SSiebren Vroegindeweij */ 159ca5bf50SSiebren Vroegindeweij 169ca5bf50SSiebren Vroegindeweij #include <linux/gpio/consumer.h> 179ca5bf50SSiebren Vroegindeweij #include <linux/interrupt.h> 189ca5bf50SSiebren Vroegindeweij #include <linux/i2c.h> 199ca5bf50SSiebren Vroegindeweij #include <linux/input.h> 209ca5bf50SSiebren Vroegindeweij #include <linux/input/mt.h> 219ca5bf50SSiebren Vroegindeweij #include <linux/input/touchscreen.h> 229ca5bf50SSiebren Vroegindeweij #include <linux/module.h> 239ca5bf50SSiebren Vroegindeweij #include <linux/of.h> 249ca5bf50SSiebren Vroegindeweij #include <linux/delay.h> 259ca5bf50SSiebren Vroegindeweij 269ca5bf50SSiebren Vroegindeweij /* Packet header defines (first byte of data send / received) */ 279ca5bf50SSiebren Vroegindeweij #define EKTF2127_NOISE 0x40 289ca5bf50SSiebren Vroegindeweij #define EKTF2127_RESPONSE 0x52 299ca5bf50SSiebren Vroegindeweij #define EKTF2127_REQUEST 0x53 309ca5bf50SSiebren Vroegindeweij #define EKTF2127_HELLO 0x55 31af5689fbSJonathan Neuschäfer #define EKTF2127_REPORT2 0x5a 329ca5bf50SSiebren Vroegindeweij #define EKTF2127_REPORT 0x5d 339ca5bf50SSiebren Vroegindeweij #define EKTF2127_CALIB_DONE 0x66 349ca5bf50SSiebren Vroegindeweij 359ca5bf50SSiebren Vroegindeweij /* Register defines (second byte of data send / received) */ 369ca5bf50SSiebren Vroegindeweij #define EKTF2127_ENV_NOISY 0x41 379ca5bf50SSiebren Vroegindeweij #define EKTF2127_HEIGHT 0x60 389ca5bf50SSiebren Vroegindeweij #define EKTF2127_WIDTH 0x63 399ca5bf50SSiebren Vroegindeweij 409ca5bf50SSiebren Vroegindeweij /* 2 bytes header + 5 * 3 bytes coordinates + 3 bytes pressure info + footer */ 419ca5bf50SSiebren Vroegindeweij #define EKTF2127_TOUCH_REPORT_SIZE 21 429ca5bf50SSiebren Vroegindeweij #define EKTF2127_MAX_TOUCHES 5 439ca5bf50SSiebren Vroegindeweij 449ca5bf50SSiebren Vroegindeweij struct ektf2127_ts { 459ca5bf50SSiebren Vroegindeweij struct i2c_client *client; 469ca5bf50SSiebren Vroegindeweij struct input_dev *input; 479ca5bf50SSiebren Vroegindeweij struct gpio_desc *power_gpios; 489ca5bf50SSiebren Vroegindeweij struct touchscreen_properties prop; 499ca5bf50SSiebren Vroegindeweij }; 509ca5bf50SSiebren Vroegindeweij 519ca5bf50SSiebren Vroegindeweij static void ektf2127_parse_coordinates(const u8 *buf, unsigned int touch_count, 529ca5bf50SSiebren Vroegindeweij struct input_mt_pos *touches) 539ca5bf50SSiebren Vroegindeweij { 549ca5bf50SSiebren Vroegindeweij int index = 0; 559ca5bf50SSiebren Vroegindeweij int i; 569ca5bf50SSiebren Vroegindeweij 579ca5bf50SSiebren Vroegindeweij for (i = 0; i < touch_count; i++) { 589ca5bf50SSiebren Vroegindeweij index = 2 + i * 3; 599ca5bf50SSiebren Vroegindeweij 609ca5bf50SSiebren Vroegindeweij touches[i].x = (buf[index] & 0x0f); 619ca5bf50SSiebren Vroegindeweij touches[i].x <<= 8; 629ca5bf50SSiebren Vroegindeweij touches[i].x |= buf[index + 2]; 639ca5bf50SSiebren Vroegindeweij 649ca5bf50SSiebren Vroegindeweij touches[i].y = (buf[index] & 0xf0); 659ca5bf50SSiebren Vroegindeweij touches[i].y <<= 4; 669ca5bf50SSiebren Vroegindeweij touches[i].y |= buf[index + 1]; 679ca5bf50SSiebren Vroegindeweij } 689ca5bf50SSiebren Vroegindeweij } 699ca5bf50SSiebren Vroegindeweij 709ca5bf50SSiebren Vroegindeweij static void ektf2127_report_event(struct ektf2127_ts *ts, const u8 *buf) 719ca5bf50SSiebren Vroegindeweij { 729ca5bf50SSiebren Vroegindeweij struct input_mt_pos touches[EKTF2127_MAX_TOUCHES]; 739ca5bf50SSiebren Vroegindeweij int slots[EKTF2127_MAX_TOUCHES]; 749ca5bf50SSiebren Vroegindeweij unsigned int touch_count, i; 759ca5bf50SSiebren Vroegindeweij 769ca5bf50SSiebren Vroegindeweij touch_count = buf[1] & 0x07; 779ca5bf50SSiebren Vroegindeweij if (touch_count > EKTF2127_MAX_TOUCHES) { 789ca5bf50SSiebren Vroegindeweij dev_err(&ts->client->dev, 799ca5bf50SSiebren Vroegindeweij "Too many touches %d > %d\n", 809ca5bf50SSiebren Vroegindeweij touch_count, EKTF2127_MAX_TOUCHES); 819ca5bf50SSiebren Vroegindeweij touch_count = EKTF2127_MAX_TOUCHES; 829ca5bf50SSiebren Vroegindeweij } 839ca5bf50SSiebren Vroegindeweij 849ca5bf50SSiebren Vroegindeweij ektf2127_parse_coordinates(buf, touch_count, touches); 859ca5bf50SSiebren Vroegindeweij input_mt_assign_slots(ts->input, slots, touches, 869ca5bf50SSiebren Vroegindeweij touch_count, 0); 879ca5bf50SSiebren Vroegindeweij 889ca5bf50SSiebren Vroegindeweij for (i = 0; i < touch_count; i++) { 899ca5bf50SSiebren Vroegindeweij input_mt_slot(ts->input, slots[i]); 909ca5bf50SSiebren Vroegindeweij input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); 919ca5bf50SSiebren Vroegindeweij touchscreen_report_pos(ts->input, &ts->prop, 929ca5bf50SSiebren Vroegindeweij touches[i].x, touches[i].y, true); 939ca5bf50SSiebren Vroegindeweij } 949ca5bf50SSiebren Vroegindeweij 959ca5bf50SSiebren Vroegindeweij input_mt_sync_frame(ts->input); 969ca5bf50SSiebren Vroegindeweij input_sync(ts->input); 979ca5bf50SSiebren Vroegindeweij } 989ca5bf50SSiebren Vroegindeweij 99af5689fbSJonathan Neuschäfer static void ektf2127_report2_contact(struct ektf2127_ts *ts, int slot, 100af5689fbSJonathan Neuschäfer const u8 *buf, bool active) 101af5689fbSJonathan Neuschäfer { 102af5689fbSJonathan Neuschäfer input_mt_slot(ts->input, slot); 103af5689fbSJonathan Neuschäfer input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, active); 104af5689fbSJonathan Neuschäfer 105af5689fbSJonathan Neuschäfer if (active) { 106af5689fbSJonathan Neuschäfer int x = (buf[0] & 0xf0) << 4 | buf[1]; 107af5689fbSJonathan Neuschäfer int y = (buf[0] & 0x0f) << 8 | buf[2]; 108af5689fbSJonathan Neuschäfer 109af5689fbSJonathan Neuschäfer touchscreen_report_pos(ts->input, &ts->prop, x, y, true); 110af5689fbSJonathan Neuschäfer } 111af5689fbSJonathan Neuschäfer } 112af5689fbSJonathan Neuschäfer 113af5689fbSJonathan Neuschäfer static void ektf2127_report2_event(struct ektf2127_ts *ts, const u8 *buf) 114af5689fbSJonathan Neuschäfer { 115af5689fbSJonathan Neuschäfer ektf2127_report2_contact(ts, 0, &buf[1], !!(buf[7] & 2)); 116af5689fbSJonathan Neuschäfer ektf2127_report2_contact(ts, 1, &buf[4], !!(buf[7] & 4)); 117af5689fbSJonathan Neuschäfer 118af5689fbSJonathan Neuschäfer input_mt_sync_frame(ts->input); 119af5689fbSJonathan Neuschäfer input_sync(ts->input); 120af5689fbSJonathan Neuschäfer } 121af5689fbSJonathan Neuschäfer 1229ca5bf50SSiebren Vroegindeweij static irqreturn_t ektf2127_irq(int irq, void *dev_id) 1239ca5bf50SSiebren Vroegindeweij { 1249ca5bf50SSiebren Vroegindeweij struct ektf2127_ts *ts = dev_id; 1259ca5bf50SSiebren Vroegindeweij struct device *dev = &ts->client->dev; 1269ca5bf50SSiebren Vroegindeweij char buf[EKTF2127_TOUCH_REPORT_SIZE]; 1279ca5bf50SSiebren Vroegindeweij int ret; 1289ca5bf50SSiebren Vroegindeweij 1299ca5bf50SSiebren Vroegindeweij ret = i2c_master_recv(ts->client, buf, EKTF2127_TOUCH_REPORT_SIZE); 1309ca5bf50SSiebren Vroegindeweij if (ret != EKTF2127_TOUCH_REPORT_SIZE) { 1319ca5bf50SSiebren Vroegindeweij dev_err(dev, "Error reading touch data: %d\n", ret); 1329ca5bf50SSiebren Vroegindeweij goto out; 1339ca5bf50SSiebren Vroegindeweij } 1349ca5bf50SSiebren Vroegindeweij 1359ca5bf50SSiebren Vroegindeweij switch (buf[0]) { 1369ca5bf50SSiebren Vroegindeweij case EKTF2127_REPORT: 1379ca5bf50SSiebren Vroegindeweij ektf2127_report_event(ts, buf); 1389ca5bf50SSiebren Vroegindeweij break; 1399ca5bf50SSiebren Vroegindeweij 140af5689fbSJonathan Neuschäfer case EKTF2127_REPORT2: 141af5689fbSJonathan Neuschäfer ektf2127_report2_event(ts, buf); 142af5689fbSJonathan Neuschäfer break; 143af5689fbSJonathan Neuschäfer 1449ca5bf50SSiebren Vroegindeweij case EKTF2127_NOISE: 1459ca5bf50SSiebren Vroegindeweij if (buf[1] == EKTF2127_ENV_NOISY) 1469ca5bf50SSiebren Vroegindeweij dev_dbg(dev, "Environment is electrically noisy\n"); 1479ca5bf50SSiebren Vroegindeweij break; 1489ca5bf50SSiebren Vroegindeweij 1499ca5bf50SSiebren Vroegindeweij case EKTF2127_HELLO: 1509ca5bf50SSiebren Vroegindeweij case EKTF2127_CALIB_DONE: 1519ca5bf50SSiebren Vroegindeweij break; 1529ca5bf50SSiebren Vroegindeweij 1539ca5bf50SSiebren Vroegindeweij default: 1549ca5bf50SSiebren Vroegindeweij dev_err(dev, "Unexpected packet header byte %#02x\n", buf[0]); 1559ca5bf50SSiebren Vroegindeweij break; 1569ca5bf50SSiebren Vroegindeweij } 1579ca5bf50SSiebren Vroegindeweij 1589ca5bf50SSiebren Vroegindeweij out: 1599ca5bf50SSiebren Vroegindeweij return IRQ_HANDLED; 1609ca5bf50SSiebren Vroegindeweij } 1619ca5bf50SSiebren Vroegindeweij 1629ca5bf50SSiebren Vroegindeweij static int ektf2127_start(struct input_dev *dev) 1639ca5bf50SSiebren Vroegindeweij { 1649ca5bf50SSiebren Vroegindeweij struct ektf2127_ts *ts = input_get_drvdata(dev); 1659ca5bf50SSiebren Vroegindeweij 1669ca5bf50SSiebren Vroegindeweij enable_irq(ts->client->irq); 1679ca5bf50SSiebren Vroegindeweij gpiod_set_value_cansleep(ts->power_gpios, 1); 1689ca5bf50SSiebren Vroegindeweij 1699ca5bf50SSiebren Vroegindeweij return 0; 1709ca5bf50SSiebren Vroegindeweij } 1719ca5bf50SSiebren Vroegindeweij 1729ca5bf50SSiebren Vroegindeweij static void ektf2127_stop(struct input_dev *dev) 1739ca5bf50SSiebren Vroegindeweij { 1749ca5bf50SSiebren Vroegindeweij struct ektf2127_ts *ts = input_get_drvdata(dev); 1759ca5bf50SSiebren Vroegindeweij 1769ca5bf50SSiebren Vroegindeweij disable_irq(ts->client->irq); 1779ca5bf50SSiebren Vroegindeweij gpiod_set_value_cansleep(ts->power_gpios, 0); 1789ca5bf50SSiebren Vroegindeweij } 1799ca5bf50SSiebren Vroegindeweij 180979987deSArnd Bergmann static int __maybe_unused ektf2127_suspend(struct device *dev) 1819ca5bf50SSiebren Vroegindeweij { 1829ca5bf50SSiebren Vroegindeweij struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev)); 1839ca5bf50SSiebren Vroegindeweij 1849ca5bf50SSiebren Vroegindeweij mutex_lock(&ts->input->mutex); 185*d69f0a43SAndrzej Pietrasiewicz if (input_device_enabled(ts->input)) 1869ca5bf50SSiebren Vroegindeweij ektf2127_stop(ts->input); 1879ca5bf50SSiebren Vroegindeweij mutex_unlock(&ts->input->mutex); 1889ca5bf50SSiebren Vroegindeweij 1899ca5bf50SSiebren Vroegindeweij return 0; 1909ca5bf50SSiebren Vroegindeweij } 1919ca5bf50SSiebren Vroegindeweij 192979987deSArnd Bergmann static int __maybe_unused ektf2127_resume(struct device *dev) 1939ca5bf50SSiebren Vroegindeweij { 1949ca5bf50SSiebren Vroegindeweij struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev)); 1959ca5bf50SSiebren Vroegindeweij 1969ca5bf50SSiebren Vroegindeweij mutex_lock(&ts->input->mutex); 197*d69f0a43SAndrzej Pietrasiewicz if (input_device_enabled(ts->input)) 1989ca5bf50SSiebren Vroegindeweij ektf2127_start(ts->input); 1999ca5bf50SSiebren Vroegindeweij mutex_unlock(&ts->input->mutex); 2009ca5bf50SSiebren Vroegindeweij 2019ca5bf50SSiebren Vroegindeweij return 0; 2029ca5bf50SSiebren Vroegindeweij } 2039ca5bf50SSiebren Vroegindeweij 2049ca5bf50SSiebren Vroegindeweij static SIMPLE_DEV_PM_OPS(ektf2127_pm_ops, ektf2127_suspend, 2059ca5bf50SSiebren Vroegindeweij ektf2127_resume); 2069ca5bf50SSiebren Vroegindeweij 2079ca5bf50SSiebren Vroegindeweij static int ektf2127_query_dimension(struct i2c_client *client, bool width) 2089ca5bf50SSiebren Vroegindeweij { 2099ca5bf50SSiebren Vroegindeweij struct device *dev = &client->dev; 2109ca5bf50SSiebren Vroegindeweij const char *what = width ? "width" : "height"; 2119ca5bf50SSiebren Vroegindeweij u8 what_code = width ? EKTF2127_WIDTH : EKTF2127_HEIGHT; 2129ca5bf50SSiebren Vroegindeweij u8 buf[4]; 2139ca5bf50SSiebren Vroegindeweij int ret; 2149ca5bf50SSiebren Vroegindeweij int error; 2159ca5bf50SSiebren Vroegindeweij 2169ca5bf50SSiebren Vroegindeweij /* Request dimension */ 2179ca5bf50SSiebren Vroegindeweij buf[0] = EKTF2127_REQUEST; 2189ca5bf50SSiebren Vroegindeweij buf[1] = width ? EKTF2127_WIDTH : EKTF2127_HEIGHT; 2199ca5bf50SSiebren Vroegindeweij buf[2] = 0x00; 2209ca5bf50SSiebren Vroegindeweij buf[3] = 0x00; 2219ca5bf50SSiebren Vroegindeweij ret = i2c_master_send(client, buf, sizeof(buf)); 2229ca5bf50SSiebren Vroegindeweij if (ret != sizeof(buf)) { 2239ca5bf50SSiebren Vroegindeweij error = ret < 0 ? ret : -EIO; 2249ca5bf50SSiebren Vroegindeweij dev_err(dev, "Failed to request %s: %d\n", what, error); 2259ca5bf50SSiebren Vroegindeweij return error; 2269ca5bf50SSiebren Vroegindeweij } 2279ca5bf50SSiebren Vroegindeweij 2289ca5bf50SSiebren Vroegindeweij msleep(20); 2299ca5bf50SSiebren Vroegindeweij 2309ca5bf50SSiebren Vroegindeweij /* Read response */ 2319ca5bf50SSiebren Vroegindeweij ret = i2c_master_recv(client, buf, sizeof(buf)); 2329ca5bf50SSiebren Vroegindeweij if (ret != sizeof(buf)) { 2339ca5bf50SSiebren Vroegindeweij error = ret < 0 ? ret : -EIO; 2349ca5bf50SSiebren Vroegindeweij dev_err(dev, "Failed to receive %s data: %d\n", what, error); 2359ca5bf50SSiebren Vroegindeweij return error; 2369ca5bf50SSiebren Vroegindeweij } 2379ca5bf50SSiebren Vroegindeweij 2389ca5bf50SSiebren Vroegindeweij if (buf[0] != EKTF2127_RESPONSE || buf[1] != what_code) { 2399ca5bf50SSiebren Vroegindeweij dev_err(dev, "Unexpected %s data: %#02x %#02x\n", 2409ca5bf50SSiebren Vroegindeweij what, buf[0], buf[1]); 2419ca5bf50SSiebren Vroegindeweij return -EIO; 2429ca5bf50SSiebren Vroegindeweij } 2439ca5bf50SSiebren Vroegindeweij 2449ca5bf50SSiebren Vroegindeweij return (((buf[3] & 0xf0) << 4) | buf[2]) - 1; 2459ca5bf50SSiebren Vroegindeweij } 2469ca5bf50SSiebren Vroegindeweij 2479ca5bf50SSiebren Vroegindeweij static int ektf2127_probe(struct i2c_client *client, 2489ca5bf50SSiebren Vroegindeweij const struct i2c_device_id *id) 2499ca5bf50SSiebren Vroegindeweij { 2509ca5bf50SSiebren Vroegindeweij struct device *dev = &client->dev; 2519ca5bf50SSiebren Vroegindeweij struct ektf2127_ts *ts; 2529ca5bf50SSiebren Vroegindeweij struct input_dev *input; 2539ca5bf50SSiebren Vroegindeweij u8 buf[4]; 2549ca5bf50SSiebren Vroegindeweij int max_x, max_y; 2559ca5bf50SSiebren Vroegindeweij int error; 2569ca5bf50SSiebren Vroegindeweij 2579ca5bf50SSiebren Vroegindeweij if (!client->irq) { 2589ca5bf50SSiebren Vroegindeweij dev_err(dev, "Error no irq specified\n"); 2599ca5bf50SSiebren Vroegindeweij return -EINVAL; 2609ca5bf50SSiebren Vroegindeweij } 2619ca5bf50SSiebren Vroegindeweij 2629ca5bf50SSiebren Vroegindeweij ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); 2639ca5bf50SSiebren Vroegindeweij if (!ts) 2649ca5bf50SSiebren Vroegindeweij return -ENOMEM; 2659ca5bf50SSiebren Vroegindeweij 2669ca5bf50SSiebren Vroegindeweij /* This requests the gpio *and* turns on the touchscreen controller */ 2679ca5bf50SSiebren Vroegindeweij ts->power_gpios = devm_gpiod_get(dev, "power", GPIOD_OUT_HIGH); 2689ca5bf50SSiebren Vroegindeweij if (IS_ERR(ts->power_gpios)) { 2699ca5bf50SSiebren Vroegindeweij error = PTR_ERR(ts->power_gpios); 2709ca5bf50SSiebren Vroegindeweij if (error != -EPROBE_DEFER) 2719ca5bf50SSiebren Vroegindeweij dev_err(dev, "Error getting power gpio: %d\n", error); 2729ca5bf50SSiebren Vroegindeweij return error; 2739ca5bf50SSiebren Vroegindeweij } 2749ca5bf50SSiebren Vroegindeweij 2759ca5bf50SSiebren Vroegindeweij input = devm_input_allocate_device(dev); 2769ca5bf50SSiebren Vroegindeweij if (!input) 2779ca5bf50SSiebren Vroegindeweij return -ENOMEM; 2789ca5bf50SSiebren Vroegindeweij 2799ca5bf50SSiebren Vroegindeweij input->name = client->name; 2809ca5bf50SSiebren Vroegindeweij input->id.bustype = BUS_I2C; 2819ca5bf50SSiebren Vroegindeweij input->open = ektf2127_start; 2829ca5bf50SSiebren Vroegindeweij input->close = ektf2127_stop; 2839ca5bf50SSiebren Vroegindeweij 2849ca5bf50SSiebren Vroegindeweij ts->client = client; 2859ca5bf50SSiebren Vroegindeweij 2869ca5bf50SSiebren Vroegindeweij /* Read hello (ignore result, depends on initial power state) */ 2879ca5bf50SSiebren Vroegindeweij msleep(20); 2889ca5bf50SSiebren Vroegindeweij i2c_master_recv(ts->client, buf, sizeof(buf)); 2899ca5bf50SSiebren Vroegindeweij 2909ca5bf50SSiebren Vroegindeweij /* Read resolution from chip */ 2919ca5bf50SSiebren Vroegindeweij max_x = ektf2127_query_dimension(client, true); 2929ca5bf50SSiebren Vroegindeweij if (max_x < 0) 2939ca5bf50SSiebren Vroegindeweij return max_x; 2949ca5bf50SSiebren Vroegindeweij 2959ca5bf50SSiebren Vroegindeweij max_y = ektf2127_query_dimension(client, false); 2969ca5bf50SSiebren Vroegindeweij if (max_y < 0) 2979ca5bf50SSiebren Vroegindeweij return max_y; 2989ca5bf50SSiebren Vroegindeweij 2999ca5bf50SSiebren Vroegindeweij input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_x, 0, 0); 3009ca5bf50SSiebren Vroegindeweij input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_y, 0, 0); 3019ca5bf50SSiebren Vroegindeweij touchscreen_parse_properties(input, true, &ts->prop); 3029ca5bf50SSiebren Vroegindeweij 3039ca5bf50SSiebren Vroegindeweij error = input_mt_init_slots(input, EKTF2127_MAX_TOUCHES, 3049ca5bf50SSiebren Vroegindeweij INPUT_MT_DIRECT | 3059ca5bf50SSiebren Vroegindeweij INPUT_MT_DROP_UNUSED | 3069ca5bf50SSiebren Vroegindeweij INPUT_MT_TRACK); 3079ca5bf50SSiebren Vroegindeweij if (error) 3089ca5bf50SSiebren Vroegindeweij return error; 3099ca5bf50SSiebren Vroegindeweij 3109ca5bf50SSiebren Vroegindeweij ts->input = input; 3119ca5bf50SSiebren Vroegindeweij input_set_drvdata(input, ts); 3129ca5bf50SSiebren Vroegindeweij 3139ca5bf50SSiebren Vroegindeweij error = devm_request_threaded_irq(dev, client->irq, 3149ca5bf50SSiebren Vroegindeweij NULL, ektf2127_irq, 3159ca5bf50SSiebren Vroegindeweij IRQF_ONESHOT, client->name, ts); 3169ca5bf50SSiebren Vroegindeweij if (error) { 3179ca5bf50SSiebren Vroegindeweij dev_err(dev, "Error requesting irq: %d\n", error); 3189ca5bf50SSiebren Vroegindeweij return error; 3199ca5bf50SSiebren Vroegindeweij } 3209ca5bf50SSiebren Vroegindeweij 3219ca5bf50SSiebren Vroegindeweij /* Stop device till opened */ 3229ca5bf50SSiebren Vroegindeweij ektf2127_stop(ts->input); 3239ca5bf50SSiebren Vroegindeweij 3249ca5bf50SSiebren Vroegindeweij error = input_register_device(input); 3259ca5bf50SSiebren Vroegindeweij if (error) 3269ca5bf50SSiebren Vroegindeweij return error; 3279ca5bf50SSiebren Vroegindeweij 3289ca5bf50SSiebren Vroegindeweij i2c_set_clientdata(client, ts); 3299ca5bf50SSiebren Vroegindeweij 3309ca5bf50SSiebren Vroegindeweij return 0; 3319ca5bf50SSiebren Vroegindeweij } 3329ca5bf50SSiebren Vroegindeweij 3339ca5bf50SSiebren Vroegindeweij #ifdef CONFIG_OF 3349ca5bf50SSiebren Vroegindeweij static const struct of_device_id ektf2127_of_match[] = { 3359ca5bf50SSiebren Vroegindeweij { .compatible = "elan,ektf2127" }, 336af5689fbSJonathan Neuschäfer { .compatible = "elan,ektf2132" }, 3379ca5bf50SSiebren Vroegindeweij {} 3389ca5bf50SSiebren Vroegindeweij }; 3399ca5bf50SSiebren Vroegindeweij MODULE_DEVICE_TABLE(of, ektf2127_of_match); 3409ca5bf50SSiebren Vroegindeweij #endif 3419ca5bf50SSiebren Vroegindeweij 3429ca5bf50SSiebren Vroegindeweij static const struct i2c_device_id ektf2127_i2c_id[] = { 3439ca5bf50SSiebren Vroegindeweij { "ektf2127", 0 }, 344af5689fbSJonathan Neuschäfer { "ektf2132", 0 }, 3459ca5bf50SSiebren Vroegindeweij {} 3469ca5bf50SSiebren Vroegindeweij }; 3479ca5bf50SSiebren Vroegindeweij MODULE_DEVICE_TABLE(i2c, ektf2127_i2c_id); 3489ca5bf50SSiebren Vroegindeweij 3499ca5bf50SSiebren Vroegindeweij static struct i2c_driver ektf2127_driver = { 3509ca5bf50SSiebren Vroegindeweij .driver = { 3519ca5bf50SSiebren Vroegindeweij .name = "elan_ektf2127", 3529ca5bf50SSiebren Vroegindeweij .pm = &ektf2127_pm_ops, 3539ca5bf50SSiebren Vroegindeweij .of_match_table = of_match_ptr(ektf2127_of_match), 3549ca5bf50SSiebren Vroegindeweij }, 3559ca5bf50SSiebren Vroegindeweij .probe = ektf2127_probe, 3569ca5bf50SSiebren Vroegindeweij .id_table = ektf2127_i2c_id, 3579ca5bf50SSiebren Vroegindeweij }; 3589ca5bf50SSiebren Vroegindeweij module_i2c_driver(ektf2127_driver); 3599ca5bf50SSiebren Vroegindeweij 360af5689fbSJonathan Neuschäfer MODULE_DESCRIPTION("ELAN eKTF2127/eKTF2132 I2C Touchscreen Driver"); 3619ca5bf50SSiebren Vroegindeweij MODULE_AUTHOR("Michel Verlaan, Siebren Vroegindeweij"); 3629ca5bf50SSiebren Vroegindeweij MODULE_LICENSE("GPL"); 363