19c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 236a281e2SJianchun Bian /* 336a281e2SJianchun Bian * Driver for Pixcir I2C touchscreen controllers. 436a281e2SJianchun Bian * 536a281e2SJianchun Bian * Copyright (C) 2010-2011 Pixcir, Inc. 636a281e2SJianchun Bian */ 736a281e2SJianchun Bian 812e7425aSFabio Estevam #include <asm/unaligned.h> 936a281e2SJianchun Bian #include <linux/delay.h> 1012e7425aSFabio Estevam #include <linux/gpio/consumer.h> 1136a281e2SJianchun Bian #include <linux/i2c.h> 1236a281e2SJianchun Bian #include <linux/input.h> 1362e65b7eSRoger Quadros #include <linux/input/mt.h> 14d48259a0SDmitry Torokhov #include <linux/input/touchscreen.h> 1512e7425aSFabio Estevam #include <linux/interrupt.h> 16a4054596SRoger Quadros #include <linux/of_device.h> 1712e7425aSFabio Estevam #include <linux/module.h> 1812e7425aSFabio Estevam #include <linux/slab.h> 1936a281e2SJianchun Bian 2036874c7eSRoger Quadros #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ 2162e65b7eSRoger Quadros 220d3c8501SFabio Estevam /* 230d3c8501SFabio Estevam * Register map 240d3c8501SFabio Estevam */ 250d3c8501SFabio Estevam #define PIXCIR_REG_POWER_MODE 51 260d3c8501SFabio Estevam #define PIXCIR_REG_INT_MODE 52 270d3c8501SFabio Estevam 280d3c8501SFabio Estevam /* 290d3c8501SFabio Estevam * Power modes: 300d3c8501SFabio Estevam * active: max scan speed 310d3c8501SFabio Estevam * idle: lower scan speed with automatic transition to active on touch 320d3c8501SFabio Estevam * halt: datasheet says sleep but this is more like halt as the chip 330d3c8501SFabio Estevam * clocks are cut and it can only be brought out of this mode 340d3c8501SFabio Estevam * using the RESET pin. 350d3c8501SFabio Estevam */ 360d3c8501SFabio Estevam enum pixcir_power_mode { 370d3c8501SFabio Estevam PIXCIR_POWER_ACTIVE, 380d3c8501SFabio Estevam PIXCIR_POWER_IDLE, 390d3c8501SFabio Estevam PIXCIR_POWER_HALT, 400d3c8501SFabio Estevam }; 410d3c8501SFabio Estevam 420d3c8501SFabio Estevam #define PIXCIR_POWER_MODE_MASK 0x03 430d3c8501SFabio Estevam #define PIXCIR_POWER_ALLOW_IDLE (1UL << 2) 440d3c8501SFabio Estevam 450d3c8501SFabio Estevam /* 460d3c8501SFabio Estevam * Interrupt modes: 470d3c8501SFabio Estevam * periodical: interrupt is asserted periodicaly 480d3c8501SFabio Estevam * diff coordinates: interrupt is asserted when coordinates change 490d3c8501SFabio Estevam * level on touch: interrupt level asserted during touch 500d3c8501SFabio Estevam * pulse on touch: interrupt pulse asserted during touch 510d3c8501SFabio Estevam * 520d3c8501SFabio Estevam */ 530d3c8501SFabio Estevam enum pixcir_int_mode { 540d3c8501SFabio Estevam PIXCIR_INT_PERIODICAL, 550d3c8501SFabio Estevam PIXCIR_INT_DIFF_COORD, 560d3c8501SFabio Estevam PIXCIR_INT_LEVEL_TOUCH, 570d3c8501SFabio Estevam PIXCIR_INT_PULSE_TOUCH, 580d3c8501SFabio Estevam }; 590d3c8501SFabio Estevam 600d3c8501SFabio Estevam #define PIXCIR_INT_MODE_MASK 0x03 610d3c8501SFabio Estevam #define PIXCIR_INT_ENABLE (1UL << 3) 620d3c8501SFabio Estevam #define PIXCIR_INT_POL_HIGH (1UL << 2) 630d3c8501SFabio Estevam 640d3c8501SFabio Estevam /** 65792e154cSDmitry Torokhov * struct pixcir_i2c_chip_data - chip related data 660d3c8501SFabio Estevam * @max_fingers: Max number of fingers reported simultaneously by h/w 670d3c8501SFabio Estevam * @has_hw_ids: Hardware supports finger tracking IDs 680d3c8501SFabio Estevam * 690d3c8501SFabio Estevam */ 700d3c8501SFabio Estevam struct pixcir_i2c_chip_data { 710d3c8501SFabio Estevam u8 max_fingers; 720d3c8501SFabio Estevam bool has_hw_ids; 730d3c8501SFabio Estevam }; 740d3c8501SFabio Estevam 7536a281e2SJianchun Bian struct pixcir_i2c_ts_data { 7636a281e2SJianchun Bian struct i2c_client *client; 7736a281e2SJianchun Bian struct input_dev *input; 78cb4a5f06SDmitry Torokhov struct gpio_desc *gpio_attb; 7940929167SRoger Quadros struct gpio_desc *gpio_reset; 80bcf5b3deSSander Vermin struct gpio_desc *gpio_enable; 81bcf5b3deSSander Vermin struct gpio_desc *gpio_wake; 82d48259a0SDmitry Torokhov const struct pixcir_i2c_chip_data *chip; 830bb11e96SHans de Goede struct touchscreen_properties prop; 84d48259a0SDmitry Torokhov bool running; 8536a281e2SJianchun Bian }; 8636a281e2SJianchun Bian 8762e65b7eSRoger Quadros struct pixcir_report_data { 8862e65b7eSRoger Quadros int num_touches; 890bb11e96SHans de Goede struct input_mt_pos pos[PIXCIR_MAX_SLOTS]; 900bb11e96SHans de Goede int ids[PIXCIR_MAX_SLOTS]; 9162e65b7eSRoger Quadros }; 9262e65b7eSRoger Quadros 9362e65b7eSRoger Quadros static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, 9462e65b7eSRoger Quadros struct pixcir_report_data *report) 9536a281e2SJianchun Bian { 9636874c7eSRoger Quadros u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5]; 9736874c7eSRoger Quadros u8 wrbuf[1] = { 0 }; 9862e65b7eSRoger Quadros u8 *bufptr; 9936a281e2SJianchun Bian u8 touch; 10062e65b7eSRoger Quadros int ret, i; 10136874c7eSRoger Quadros int readsize; 102d48259a0SDmitry Torokhov const struct pixcir_i2c_chip_data *chip = tsdata->chip; 10362e65b7eSRoger Quadros 10462e65b7eSRoger Quadros memset(report, 0, sizeof(struct pixcir_report_data)); 10536a281e2SJianchun Bian 10636874c7eSRoger Quadros i = chip->has_hw_ids ? 1 : 0; 107792e154cSDmitry Torokhov readsize = 2 + tsdata->chip->max_fingers * (4 + i); 10836874c7eSRoger Quadros if (readsize > sizeof(rdbuf)) 10936874c7eSRoger Quadros readsize = sizeof(rdbuf); 11036874c7eSRoger Quadros 11136a281e2SJianchun Bian ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); 11236a281e2SJianchun Bian if (ret != sizeof(wrbuf)) { 11336a281e2SJianchun Bian dev_err(&tsdata->client->dev, 11436a281e2SJianchun Bian "%s: i2c_master_send failed(), ret=%d\n", 11536a281e2SJianchun Bian __func__, ret); 11636a281e2SJianchun Bian return; 11736a281e2SJianchun Bian } 11836a281e2SJianchun Bian 11936874c7eSRoger Quadros ret = i2c_master_recv(tsdata->client, rdbuf, readsize); 120469d7d22SFrodo Lai if (ret != readsize) { 12136a281e2SJianchun Bian dev_err(&tsdata->client->dev, 12236a281e2SJianchun Bian "%s: i2c_master_recv failed(), ret=%d\n", 12336a281e2SJianchun Bian __func__, ret); 12436a281e2SJianchun Bian return; 12536a281e2SJianchun Bian } 12636a281e2SJianchun Bian 12762e65b7eSRoger Quadros touch = rdbuf[0] & 0x7; 128792e154cSDmitry Torokhov if (touch > tsdata->chip->max_fingers) 129792e154cSDmitry Torokhov touch = tsdata->chip->max_fingers; 13036a281e2SJianchun Bian 13162e65b7eSRoger Quadros report->num_touches = touch; 13262e65b7eSRoger Quadros bufptr = &rdbuf[2]; 13336a281e2SJianchun Bian 13462e65b7eSRoger Quadros for (i = 0; i < touch; i++) { 1350bb11e96SHans de Goede touchscreen_set_mt_pos(&report->pos[i], &tsdata->prop, 1360bb11e96SHans de Goede get_unaligned_le16(bufptr), 1370bb11e96SHans de Goede get_unaligned_le16(bufptr + 2)); 13836874c7eSRoger Quadros if (chip->has_hw_ids) { 1390bb11e96SHans de Goede report->ids[i] = bufptr[4]; 14036874c7eSRoger Quadros bufptr = bufptr + 5; 14136874c7eSRoger Quadros } else { 14262e65b7eSRoger Quadros bufptr = bufptr + 4; 14336a281e2SJianchun Bian } 14436a281e2SJianchun Bian } 14536874c7eSRoger Quadros } 14636a281e2SJianchun Bian 14762e65b7eSRoger Quadros static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, 14862e65b7eSRoger Quadros struct pixcir_report_data *report) 14962e65b7eSRoger Quadros { 15062e65b7eSRoger Quadros int slots[PIXCIR_MAX_SLOTS]; 15162e65b7eSRoger Quadros int n, i, slot; 15262e65b7eSRoger Quadros struct device *dev = &ts->client->dev; 153d48259a0SDmitry Torokhov const struct pixcir_i2c_chip_data *chip = ts->chip; 15462e65b7eSRoger Quadros 15562e65b7eSRoger Quadros n = report->num_touches; 15662e65b7eSRoger Quadros if (n > PIXCIR_MAX_SLOTS) 15762e65b7eSRoger Quadros n = PIXCIR_MAX_SLOTS; 15862e65b7eSRoger Quadros 1590bb11e96SHans de Goede if (!ts->chip->has_hw_ids) 1600bb11e96SHans de Goede input_mt_assign_slots(ts->input, slots, report->pos, n, 0); 16162e65b7eSRoger Quadros 16262e65b7eSRoger Quadros for (i = 0; i < n; i++) { 16336874c7eSRoger Quadros if (chip->has_hw_ids) { 1640bb11e96SHans de Goede slot = input_mt_get_slot_by_key(ts->input, 1650bb11e96SHans de Goede report->ids[i]); 16636874c7eSRoger Quadros if (slot < 0) { 16736874c7eSRoger Quadros dev_dbg(dev, "no free slot for id 0x%x\n", 1680bb11e96SHans de Goede report->ids[i]); 16936874c7eSRoger Quadros continue; 17036874c7eSRoger Quadros } 17136874c7eSRoger Quadros } else { 17262e65b7eSRoger Quadros slot = slots[i]; 17336874c7eSRoger Quadros } 17462e65b7eSRoger Quadros 17562e65b7eSRoger Quadros input_mt_slot(ts->input, slot); 1760bb11e96SHans de Goede input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); 17762e65b7eSRoger Quadros 1780bb11e96SHans de Goede input_report_abs(ts->input, ABS_MT_POSITION_X, 1790bb11e96SHans de Goede report->pos[i].x); 1800bb11e96SHans de Goede input_report_abs(ts->input, ABS_MT_POSITION_Y, 1810bb11e96SHans de Goede report->pos[i].y); 18262e65b7eSRoger Quadros 18362e65b7eSRoger Quadros dev_dbg(dev, "%d: slot %d, x %d, y %d\n", 1840bb11e96SHans de Goede i, slot, report->pos[i].x, report->pos[i].y); 18562e65b7eSRoger Quadros } 18662e65b7eSRoger Quadros 18762e65b7eSRoger Quadros input_mt_sync_frame(ts->input); 18862e65b7eSRoger Quadros input_sync(ts->input); 18936a281e2SJianchun Bian } 19036a281e2SJianchun Bian 19136a281e2SJianchun Bian static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) 19236a281e2SJianchun Bian { 19336a281e2SJianchun Bian struct pixcir_i2c_ts_data *tsdata = dev_id; 19462e65b7eSRoger Quadros struct pixcir_report_data report; 19536a281e2SJianchun Bian 1963b36fbb0SRoger Quadros while (tsdata->running) { 19762e65b7eSRoger Quadros /* parse packet */ 19862e65b7eSRoger Quadros pixcir_ts_parse(tsdata, &report); 19936a281e2SJianchun Bian 20062e65b7eSRoger Quadros /* report it */ 20162e65b7eSRoger Quadros pixcir_ts_report(tsdata, &report); 20262e65b7eSRoger Quadros 203127520caSDmitry Torokhov if (gpiod_get_value_cansleep(tsdata->gpio_attb)) { 20462e65b7eSRoger Quadros if (report.num_touches) { 20562e65b7eSRoger Quadros /* 20662e65b7eSRoger Quadros * Last report with no finger up? 20762e65b7eSRoger Quadros * Do it now then. 20862e65b7eSRoger Quadros */ 20962e65b7eSRoger Quadros input_mt_sync_frame(tsdata->input); 21062e65b7eSRoger Quadros input_sync(tsdata->input); 21162e65b7eSRoger Quadros } 21236a281e2SJianchun Bian break; 21362e65b7eSRoger Quadros } 21436a281e2SJianchun Bian 21536a281e2SJianchun Bian msleep(20); 21636a281e2SJianchun Bian } 21736a281e2SJianchun Bian 21836a281e2SJianchun Bian return IRQ_HANDLED; 21936a281e2SJianchun Bian } 22036a281e2SJianchun Bian 22140929167SRoger Quadros static void pixcir_reset(struct pixcir_i2c_ts_data *tsdata) 22240929167SRoger Quadros { 22340929167SRoger Quadros if (!IS_ERR_OR_NULL(tsdata->gpio_reset)) { 22440929167SRoger Quadros gpiod_set_value_cansleep(tsdata->gpio_reset, 1); 22540929167SRoger Quadros ndelay(100); /* datasheet section 1.2.3 says 80ns min. */ 22640929167SRoger Quadros gpiod_set_value_cansleep(tsdata->gpio_reset, 0); 22740929167SRoger Quadros /* wait for controller ready. 100ms guess. */ 22840929167SRoger Quadros msleep(100); 22940929167SRoger Quadros } 23040929167SRoger Quadros } 23140929167SRoger Quadros 2323b36fbb0SRoger Quadros static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts, 2333b36fbb0SRoger Quadros enum pixcir_power_mode mode) 2343b36fbb0SRoger Quadros { 2353b36fbb0SRoger Quadros struct device *dev = &ts->client->dev; 2363b36fbb0SRoger Quadros int ret; 2373b36fbb0SRoger Quadros 238bcf5b3deSSander Vermin if (mode == PIXCIR_POWER_ACTIVE || mode == PIXCIR_POWER_IDLE) { 239bcf5b3deSSander Vermin if (ts->gpio_wake) 240bcf5b3deSSander Vermin gpiod_set_value_cansleep(ts->gpio_wake, 1); 241bcf5b3deSSander Vermin } 242bcf5b3deSSander Vermin 2433b36fbb0SRoger Quadros ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE); 2443b36fbb0SRoger Quadros if (ret < 0) { 24513fb9cf5SFabio Estevam dev_err(dev, "%s: can't read reg %d : %d\n", 2463b36fbb0SRoger Quadros __func__, PIXCIR_REG_POWER_MODE, ret); 2473b36fbb0SRoger Quadros return ret; 2483b36fbb0SRoger Quadros } 2493b36fbb0SRoger Quadros 2503b36fbb0SRoger Quadros ret &= ~PIXCIR_POWER_MODE_MASK; 2513b36fbb0SRoger Quadros ret |= mode; 2523b36fbb0SRoger Quadros 2533b36fbb0SRoger Quadros /* Always AUTO_IDLE */ 2543b36fbb0SRoger Quadros ret |= PIXCIR_POWER_ALLOW_IDLE; 2553b36fbb0SRoger Quadros 2563b36fbb0SRoger Quadros ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret); 2573b36fbb0SRoger Quadros if (ret < 0) { 25813fb9cf5SFabio Estevam dev_err(dev, "%s: can't write reg %d : %d\n", 2593b36fbb0SRoger Quadros __func__, PIXCIR_REG_POWER_MODE, ret); 2603b36fbb0SRoger Quadros return ret; 2613b36fbb0SRoger Quadros } 2623b36fbb0SRoger Quadros 263bcf5b3deSSander Vermin if (mode == PIXCIR_POWER_HALT) { 264bcf5b3deSSander Vermin if (ts->gpio_wake) 265bcf5b3deSSander Vermin gpiod_set_value_cansleep(ts->gpio_wake, 0); 266bcf5b3deSSander Vermin } 267bcf5b3deSSander Vermin 2683b36fbb0SRoger Quadros return 0; 2693b36fbb0SRoger Quadros } 2703b36fbb0SRoger Quadros 2713b36fbb0SRoger Quadros /* 2723b36fbb0SRoger Quadros * Set the interrupt mode for the device i.e. ATTB line behaviour 2733b36fbb0SRoger Quadros * 2743b36fbb0SRoger Quadros * @polarity : 1 for active high, 0 for active low. 2753b36fbb0SRoger Quadros */ 2763b36fbb0SRoger Quadros static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts, 2773b36fbb0SRoger Quadros enum pixcir_int_mode mode, bool polarity) 2783b36fbb0SRoger Quadros { 2793b36fbb0SRoger Quadros struct device *dev = &ts->client->dev; 2803b36fbb0SRoger Quadros int ret; 2813b36fbb0SRoger Quadros 2823b36fbb0SRoger Quadros ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); 2833b36fbb0SRoger Quadros if (ret < 0) { 28413fb9cf5SFabio Estevam dev_err(dev, "%s: can't read reg %d : %d\n", 2853b36fbb0SRoger Quadros __func__, PIXCIR_REG_INT_MODE, ret); 2863b36fbb0SRoger Quadros return ret; 2873b36fbb0SRoger Quadros } 2883b36fbb0SRoger Quadros 2893b36fbb0SRoger Quadros ret &= ~PIXCIR_INT_MODE_MASK; 2903b36fbb0SRoger Quadros ret |= mode; 2913b36fbb0SRoger Quadros 2923b36fbb0SRoger Quadros if (polarity) 2933b36fbb0SRoger Quadros ret |= PIXCIR_INT_POL_HIGH; 2943b36fbb0SRoger Quadros else 2953b36fbb0SRoger Quadros ret &= ~PIXCIR_INT_POL_HIGH; 2963b36fbb0SRoger Quadros 2973b36fbb0SRoger Quadros ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); 2983b36fbb0SRoger Quadros if (ret < 0) { 29913fb9cf5SFabio Estevam dev_err(dev, "%s: can't write reg %d : %d\n", 3003b36fbb0SRoger Quadros __func__, PIXCIR_REG_INT_MODE, ret); 3013b36fbb0SRoger Quadros return ret; 3023b36fbb0SRoger Quadros } 3033b36fbb0SRoger Quadros 3043b36fbb0SRoger Quadros return 0; 3053b36fbb0SRoger Quadros } 3063b36fbb0SRoger Quadros 3073b36fbb0SRoger Quadros /* 3083b36fbb0SRoger Quadros * Enable/disable interrupt generation 3093b36fbb0SRoger Quadros */ 3103b36fbb0SRoger Quadros static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable) 3113b36fbb0SRoger Quadros { 3123b36fbb0SRoger Quadros struct device *dev = &ts->client->dev; 3133b36fbb0SRoger Quadros int ret; 3143b36fbb0SRoger Quadros 3153b36fbb0SRoger Quadros ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); 3163b36fbb0SRoger Quadros if (ret < 0) { 31713fb9cf5SFabio Estevam dev_err(dev, "%s: can't read reg %d : %d\n", 3183b36fbb0SRoger Quadros __func__, PIXCIR_REG_INT_MODE, ret); 3193b36fbb0SRoger Quadros return ret; 3203b36fbb0SRoger Quadros } 3213b36fbb0SRoger Quadros 3223b36fbb0SRoger Quadros if (enable) 3233b36fbb0SRoger Quadros ret |= PIXCIR_INT_ENABLE; 3243b36fbb0SRoger Quadros else 3253b36fbb0SRoger Quadros ret &= ~PIXCIR_INT_ENABLE; 3263b36fbb0SRoger Quadros 3273b36fbb0SRoger Quadros ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); 3283b36fbb0SRoger Quadros if (ret < 0) { 32913fb9cf5SFabio Estevam dev_err(dev, "%s: can't write reg %d : %d\n", 3303b36fbb0SRoger Quadros __func__, PIXCIR_REG_INT_MODE, ret); 3313b36fbb0SRoger Quadros return ret; 3323b36fbb0SRoger Quadros } 3333b36fbb0SRoger Quadros 3343b36fbb0SRoger Quadros return 0; 3353b36fbb0SRoger Quadros } 3363b36fbb0SRoger Quadros 3373b36fbb0SRoger Quadros static int pixcir_start(struct pixcir_i2c_ts_data *ts) 3383b36fbb0SRoger Quadros { 3393b36fbb0SRoger Quadros struct device *dev = &ts->client->dev; 3403b36fbb0SRoger Quadros int error; 3413b36fbb0SRoger Quadros 342bcf5b3deSSander Vermin if (ts->gpio_enable) { 343bcf5b3deSSander Vermin gpiod_set_value_cansleep(ts->gpio_enable, 1); 344bcf5b3deSSander Vermin msleep(100); 345bcf5b3deSSander Vermin } 346bcf5b3deSSander Vermin 3473b36fbb0SRoger Quadros /* LEVEL_TOUCH interrupt with active low polarity */ 3483b36fbb0SRoger Quadros error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0); 3493b36fbb0SRoger Quadros if (error) { 3503b36fbb0SRoger Quadros dev_err(dev, "Failed to set interrupt mode: %d\n", error); 3513b36fbb0SRoger Quadros return error; 3523b36fbb0SRoger Quadros } 3533b36fbb0SRoger Quadros 3543b36fbb0SRoger Quadros ts->running = true; 3553b36fbb0SRoger Quadros mb(); /* Update status before IRQ can fire */ 3563b36fbb0SRoger Quadros 3573b36fbb0SRoger Quadros /* enable interrupt generation */ 3583b36fbb0SRoger Quadros error = pixcir_int_enable(ts, true); 3593b36fbb0SRoger Quadros if (error) { 3603b36fbb0SRoger Quadros dev_err(dev, "Failed to enable interrupt generation: %d\n", 3613b36fbb0SRoger Quadros error); 3623b36fbb0SRoger Quadros return error; 3633b36fbb0SRoger Quadros } 3643b36fbb0SRoger Quadros 3653b36fbb0SRoger Quadros return 0; 3663b36fbb0SRoger Quadros } 3673b36fbb0SRoger Quadros 3683b36fbb0SRoger Quadros static int pixcir_stop(struct pixcir_i2c_ts_data *ts) 3693b36fbb0SRoger Quadros { 3703b36fbb0SRoger Quadros int error; 3713b36fbb0SRoger Quadros 3723b36fbb0SRoger Quadros /* Disable interrupt generation */ 3733b36fbb0SRoger Quadros error = pixcir_int_enable(ts, false); 3743b36fbb0SRoger Quadros if (error) { 3753b36fbb0SRoger Quadros dev_err(&ts->client->dev, 3763b36fbb0SRoger Quadros "Failed to disable interrupt generation: %d\n", 3773b36fbb0SRoger Quadros error); 3783b36fbb0SRoger Quadros return error; 3793b36fbb0SRoger Quadros } 3803b36fbb0SRoger Quadros 3813b36fbb0SRoger Quadros /* Exit ISR if running, no more report parsing */ 3823b36fbb0SRoger Quadros ts->running = false; 3833b36fbb0SRoger Quadros mb(); /* update status before we synchronize irq */ 3843b36fbb0SRoger Quadros 3853b36fbb0SRoger Quadros /* Wait till running ISR is complete */ 3863b36fbb0SRoger Quadros synchronize_irq(ts->client->irq); 3873b36fbb0SRoger Quadros 388bcf5b3deSSander Vermin if (ts->gpio_enable) 389bcf5b3deSSander Vermin gpiod_set_value_cansleep(ts->gpio_enable, 0); 390bcf5b3deSSander Vermin 3913b36fbb0SRoger Quadros return 0; 3923b36fbb0SRoger Quadros } 3933b36fbb0SRoger Quadros 3943b36fbb0SRoger Quadros static int pixcir_input_open(struct input_dev *dev) 3953b36fbb0SRoger Quadros { 3963b36fbb0SRoger Quadros struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev); 3973b36fbb0SRoger Quadros 3983b36fbb0SRoger Quadros return pixcir_start(ts); 3993b36fbb0SRoger Quadros } 4003b36fbb0SRoger Quadros 4013b36fbb0SRoger Quadros static void pixcir_input_close(struct input_dev *dev) 4023b36fbb0SRoger Quadros { 4033b36fbb0SRoger Quadros struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev); 4043b36fbb0SRoger Quadros 4053b36fbb0SRoger Quadros pixcir_stop(ts); 4063b36fbb0SRoger Quadros } 4073b36fbb0SRoger Quadros 40802b6a58bSJingoo Han static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev) 40936a281e2SJianchun Bian { 41036a281e2SJianchun Bian struct i2c_client *client = to_i2c_client(dev); 4117cdcb8d1SRoger Quadros struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client); 4127cdcb8d1SRoger Quadros struct input_dev *input = ts->input; 4137cdcb8d1SRoger Quadros int ret = 0; 41436a281e2SJianchun Bian 4157cdcb8d1SRoger Quadros mutex_lock(&input->mutex); 4167cdcb8d1SRoger Quadros 4177cdcb8d1SRoger Quadros if (device_may_wakeup(&client->dev)) { 4187cdcb8d1SRoger Quadros if (!input->users) { 4197cdcb8d1SRoger Quadros ret = pixcir_start(ts); 4207cdcb8d1SRoger Quadros if (ret) { 4217cdcb8d1SRoger Quadros dev_err(dev, "Failed to start\n"); 4227cdcb8d1SRoger Quadros goto unlock; 4237cdcb8d1SRoger Quadros } 4247cdcb8d1SRoger Quadros } 4257cdcb8d1SRoger Quadros } else if (input->users) { 4267cdcb8d1SRoger Quadros ret = pixcir_stop(ts); 4277cdcb8d1SRoger Quadros } 42836a281e2SJianchun Bian 4297cdcb8d1SRoger Quadros unlock: 4307cdcb8d1SRoger Quadros mutex_unlock(&input->mutex); 4317cdcb8d1SRoger Quadros 4327cdcb8d1SRoger Quadros return ret; 43336a281e2SJianchun Bian } 43436a281e2SJianchun Bian 43502b6a58bSJingoo Han static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev) 43636a281e2SJianchun Bian { 43736a281e2SJianchun Bian struct i2c_client *client = to_i2c_client(dev); 4387cdcb8d1SRoger Quadros struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client); 4397cdcb8d1SRoger Quadros struct input_dev *input = ts->input; 4407cdcb8d1SRoger Quadros int ret = 0; 44136a281e2SJianchun Bian 4427cdcb8d1SRoger Quadros mutex_lock(&input->mutex); 4437cdcb8d1SRoger Quadros 4447cdcb8d1SRoger Quadros if (device_may_wakeup(&client->dev)) { 4457cdcb8d1SRoger Quadros if (!input->users) { 4467cdcb8d1SRoger Quadros ret = pixcir_stop(ts); 4477cdcb8d1SRoger Quadros if (ret) { 4487cdcb8d1SRoger Quadros dev_err(dev, "Failed to stop\n"); 4497cdcb8d1SRoger Quadros goto unlock; 4507cdcb8d1SRoger Quadros } 4517cdcb8d1SRoger Quadros } 4527cdcb8d1SRoger Quadros } else if (input->users) { 4537cdcb8d1SRoger Quadros ret = pixcir_start(ts); 4547cdcb8d1SRoger Quadros } 4557cdcb8d1SRoger Quadros 4567cdcb8d1SRoger Quadros unlock: 4577cdcb8d1SRoger Quadros mutex_unlock(&input->mutex); 4587cdcb8d1SRoger Quadros 4597cdcb8d1SRoger Quadros return ret; 46036a281e2SJianchun Bian } 46136a281e2SJianchun Bian 46236a281e2SJianchun Bian static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, 46336a281e2SJianchun Bian pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); 46436a281e2SJianchun Bian 4655298cc4cSBill Pemberton static int pixcir_i2c_ts_probe(struct i2c_client *client, 46636a281e2SJianchun Bian const struct i2c_device_id *id) 46736a281e2SJianchun Bian { 468e9d4718dSRoger Quadros struct device *dev = &client->dev; 46936a281e2SJianchun Bian struct pixcir_i2c_ts_data *tsdata; 47036a281e2SJianchun Bian struct input_dev *input; 47136a281e2SJianchun Bian int error; 47236a281e2SJianchun Bian 473d48259a0SDmitry Torokhov tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL); 474d48259a0SDmitry Torokhov if (!tsdata) 475d48259a0SDmitry Torokhov return -ENOMEM; 476a4054596SRoger Quadros 477792e154cSDmitry Torokhov tsdata->chip = device_get_match_data(dev); 478792e154cSDmitry Torokhov if (!tsdata->chip && id) 479792e154cSDmitry Torokhov tsdata->chip = (const void *)id->driver_data; 480792e154cSDmitry Torokhov if (!tsdata->chip) { 481792e154cSDmitry Torokhov dev_err(dev, "can't locate chip data\n"); 48236874c7eSRoger Quadros return -EINVAL; 48336874c7eSRoger Quadros } 48436874c7eSRoger Quadros 485e9d4718dSRoger Quadros input = devm_input_allocate_device(dev); 486e9d4718dSRoger Quadros if (!input) { 487e9d4718dSRoger Quadros dev_err(dev, "Failed to allocate input device\n"); 488e9d4718dSRoger Quadros return -ENOMEM; 48936a281e2SJianchun Bian } 49036a281e2SJianchun Bian 49136a281e2SJianchun Bian tsdata->client = client; 49236a281e2SJianchun Bian tsdata->input = input; 49336a281e2SJianchun Bian 49436a281e2SJianchun Bian input->name = client->name; 49536a281e2SJianchun Bian input->id.bustype = BUS_I2C; 4963b36fbb0SRoger Quadros input->open = pixcir_input_open; 4973b36fbb0SRoger Quadros input->close = pixcir_input_close; 49836a281e2SJianchun Bian 499d48259a0SDmitry Torokhov input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); 500d48259a0SDmitry Torokhov input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); 5010bb11e96SHans de Goede touchscreen_parse_properties(input, true, &tsdata->prop); 502d48259a0SDmitry Torokhov if (!input_abs_get_max(input, ABS_MT_POSITION_X) || 503d48259a0SDmitry Torokhov !input_abs_get_max(input, ABS_MT_POSITION_Y)) { 504d48259a0SDmitry Torokhov dev_err(dev, "Touchscreen size is not specified\n"); 505d48259a0SDmitry Torokhov return -EINVAL; 506d48259a0SDmitry Torokhov } 50736a281e2SJianchun Bian 508792e154cSDmitry Torokhov error = input_mt_init_slots(input, tsdata->chip->max_fingers, 50962e65b7eSRoger Quadros INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 51062e65b7eSRoger Quadros if (error) { 51162e65b7eSRoger Quadros dev_err(dev, "Error initializing Multi-Touch slots\n"); 51262e65b7eSRoger Quadros return error; 51362e65b7eSRoger Quadros } 51462e65b7eSRoger Quadros 51536a281e2SJianchun Bian input_set_drvdata(input, tsdata); 51636a281e2SJianchun Bian 517cb4a5f06SDmitry Torokhov tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN); 518cb4a5f06SDmitry Torokhov if (IS_ERR(tsdata->gpio_attb)) { 519cb4a5f06SDmitry Torokhov error = PTR_ERR(tsdata->gpio_attb); 52071a8f345SFabio Estevam if (error != -EPROBE_DEFER) 52171a8f345SFabio Estevam dev_err(dev, "Failed to request ATTB gpio: %d\n", 52271a8f345SFabio Estevam error); 5230dfc8d41SRoger Quadros return error; 5240dfc8d41SRoger Quadros } 5250dfc8d41SRoger Quadros 52640929167SRoger Quadros tsdata->gpio_reset = devm_gpiod_get_optional(dev, "reset", 52740929167SRoger Quadros GPIOD_OUT_LOW); 52840929167SRoger Quadros if (IS_ERR(tsdata->gpio_reset)) { 52940929167SRoger Quadros error = PTR_ERR(tsdata->gpio_reset); 53071a8f345SFabio Estevam if (error != -EPROBE_DEFER) 53171a8f345SFabio Estevam dev_err(dev, "Failed to request RESET gpio: %d\n", 53271a8f345SFabio Estevam error); 53340929167SRoger Quadros return error; 53440929167SRoger Quadros } 53540929167SRoger Quadros 536bcf5b3deSSander Vermin tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake", 537bcf5b3deSSander Vermin GPIOD_OUT_HIGH); 538bcf5b3deSSander Vermin if (IS_ERR(tsdata->gpio_wake)) { 539bcf5b3deSSander Vermin error = PTR_ERR(tsdata->gpio_wake); 540bcf5b3deSSander Vermin if (error != -EPROBE_DEFER) 541bcf5b3deSSander Vermin dev_err(dev, "Failed to get wake gpio: %d\n", error); 542bcf5b3deSSander Vermin return error; 543bcf5b3deSSander Vermin } 544bcf5b3deSSander Vermin 545bcf5b3deSSander Vermin tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable", 546bcf5b3deSSander Vermin GPIOD_OUT_HIGH); 547bcf5b3deSSander Vermin if (IS_ERR(tsdata->gpio_enable)) { 548bcf5b3deSSander Vermin error = PTR_ERR(tsdata->gpio_enable); 549bcf5b3deSSander Vermin if (error != -EPROBE_DEFER) 550bcf5b3deSSander Vermin dev_err(dev, "Failed to get enable gpio: %d\n", error); 551bcf5b3deSSander Vermin return error; 552bcf5b3deSSander Vermin } 553bcf5b3deSSander Vermin 554bcf5b3deSSander Vermin if (tsdata->gpio_enable) 555bcf5b3deSSander Vermin msleep(100); 556bcf5b3deSSander Vermin 557e9d4718dSRoger Quadros error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr, 5589b7e31bbSLars-Peter Clausen IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 55936a281e2SJianchun Bian client->name, tsdata); 56036a281e2SJianchun Bian if (error) { 561e9d4718dSRoger Quadros dev_err(dev, "failed to request irq %d\n", client->irq); 562e9d4718dSRoger Quadros return error; 56336a281e2SJianchun Bian } 56436a281e2SJianchun Bian 56540929167SRoger Quadros pixcir_reset(tsdata); 56640929167SRoger Quadros 5673b36fbb0SRoger Quadros /* Always be in IDLE mode to save power, device supports auto wake */ 5683b36fbb0SRoger Quadros error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE); 5693b36fbb0SRoger Quadros if (error) { 5703b36fbb0SRoger Quadros dev_err(dev, "Failed to set IDLE mode\n"); 5713b36fbb0SRoger Quadros return error; 5723b36fbb0SRoger Quadros } 5733b36fbb0SRoger Quadros 5743b36fbb0SRoger Quadros /* Stop device till opened */ 5753b36fbb0SRoger Quadros error = pixcir_stop(tsdata); 5763b36fbb0SRoger Quadros if (error) 5773b36fbb0SRoger Quadros return error; 5783b36fbb0SRoger Quadros 57936a281e2SJianchun Bian error = input_register_device(input); 58036a281e2SJianchun Bian if (error) 581e9d4718dSRoger Quadros return error; 58236a281e2SJianchun Bian 5837cdcb8d1SRoger Quadros i2c_set_clientdata(client, tsdata); 58436a281e2SJianchun Bian 58536a281e2SJianchun Bian return 0; 58636a281e2SJianchun Bian } 58736a281e2SJianchun Bian 588a4054596SRoger Quadros static const struct pixcir_i2c_chip_data pixcir_ts_data = { 589a4054596SRoger Quadros .max_fingers = 2, 590a4054596SRoger Quadros /* no hw id support */ 591a4054596SRoger Quadros }; 592a4054596SRoger Quadros 593a4054596SRoger Quadros static const struct pixcir_i2c_chip_data pixcir_tangoc_data = { 594a4054596SRoger Quadros .max_fingers = 5, 595a4054596SRoger Quadros .has_hw_ids = true, 596a4054596SRoger Quadros }; 597a4054596SRoger Quadros 598792e154cSDmitry Torokhov static const struct i2c_device_id pixcir_i2c_ts_id[] = { 599792e154cSDmitry Torokhov { "pixcir_ts", (unsigned long) &pixcir_ts_data }, 600792e154cSDmitry Torokhov { "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data }, 601792e154cSDmitry Torokhov { } 602792e154cSDmitry Torokhov }; 603792e154cSDmitry Torokhov MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id); 604792e154cSDmitry Torokhov 605792e154cSDmitry Torokhov #ifdef CONFIG_OF 606a4054596SRoger Quadros static const struct of_device_id pixcir_of_match[] = { 607a4054596SRoger Quadros { .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data }, 608a4054596SRoger Quadros { .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data }, 609a4054596SRoger Quadros { } 610a4054596SRoger Quadros }; 611a4054596SRoger Quadros MODULE_DEVICE_TABLE(of, pixcir_of_match); 612a4054596SRoger Quadros #endif 613a4054596SRoger Quadros 61436a281e2SJianchun Bian static struct i2c_driver pixcir_i2c_ts_driver = { 61536a281e2SJianchun Bian .driver = { 61636a281e2SJianchun Bian .name = "pixcir_ts", 61736a281e2SJianchun Bian .pm = &pixcir_dev_pm_ops, 618a4054596SRoger Quadros .of_match_table = of_match_ptr(pixcir_of_match), 61936a281e2SJianchun Bian }, 62036a281e2SJianchun Bian .probe = pixcir_i2c_ts_probe, 62136a281e2SJianchun Bian .id_table = pixcir_i2c_ts_id, 62236a281e2SJianchun Bian }; 62336a281e2SJianchun Bian 6244a533835SDmitry Torokhov module_i2c_driver(pixcir_i2c_ts_driver); 62536a281e2SJianchun Bian 62636a281e2SJianchun Bian MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>"); 62736a281e2SJianchun Bian MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver"); 62836a281e2SJianchun Bian MODULE_LICENSE("GPL"); 629