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>
1612e7425aSFabio Estevam #include <linux/module.h>
17*dbce1a7dSRob Herring #include <linux/of.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 
pixcir_ts_parse(struct pixcir_i2c_ts_data * tsdata,struct pixcir_report_data * report)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 
pixcir_ts_report(struct pixcir_i2c_ts_data * ts,struct pixcir_report_data * report)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 
pixcir_ts_isr(int irq,void * dev_id)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 
pixcir_reset(struct pixcir_i2c_ts_data * tsdata)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 
pixcir_set_power_mode(struct pixcir_i2c_ts_data * ts,enum pixcir_power_mode mode)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  */
pixcir_set_int_mode(struct pixcir_i2c_ts_data * ts,enum pixcir_int_mode mode,bool polarity)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  */
pixcir_int_enable(struct pixcir_i2c_ts_data * ts,bool enable)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 
pixcir_start(struct pixcir_i2c_ts_data * ts)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 
pixcir_stop(struct pixcir_i2c_ts_data * ts)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 
pixcir_input_open(struct input_dev * dev)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 
pixcir_input_close(struct input_dev * dev)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 
pixcir_i2c_ts_suspend(struct device * dev)408add8bbd2SJonathan Cameron static int 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)) {
418d69f0a43SAndrzej Pietrasiewicz 		if (!input_device_enabled(input)) {
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 		}
425d69f0a43SAndrzej Pietrasiewicz 	} else if (input_device_enabled(input)) {
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 
pixcir_i2c_ts_resume(struct device * dev)435add8bbd2SJonathan Cameron static int 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)) {
445d69f0a43SAndrzej Pietrasiewicz 		if (!input_device_enabled(input)) {
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 		}
452d69f0a43SAndrzej Pietrasiewicz 	} else if (input_device_enabled(input)) {
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 
462add8bbd2SJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
46336a281e2SJianchun Bian 				pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
46436a281e2SJianchun Bian 
pixcir_i2c_ts_probe(struct i2c_client * client)465211ab70dSUwe Kleine-König static int pixcir_i2c_ts_probe(struct i2c_client *client)
46636a281e2SJianchun Bian {
467211ab70dSUwe Kleine-König 	const struct i2c_device_id *id = i2c_client_get_device_id(client);
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);
518e32825c4SKrzysztof Kozlowski 	if (IS_ERR(tsdata->gpio_attb))
519e32825c4SKrzysztof Kozlowski 		return dev_err_probe(dev, PTR_ERR(tsdata->gpio_attb),
520e32825c4SKrzysztof Kozlowski 				     "Failed to request ATTB gpio\n");
5210dfc8d41SRoger Quadros 
52240929167SRoger Quadros 	tsdata->gpio_reset = devm_gpiod_get_optional(dev, "reset",
52340929167SRoger Quadros 						     GPIOD_OUT_LOW);
524e32825c4SKrzysztof Kozlowski 	if (IS_ERR(tsdata->gpio_reset))
525e32825c4SKrzysztof Kozlowski 		return dev_err_probe(dev, PTR_ERR(tsdata->gpio_reset),
526e32825c4SKrzysztof Kozlowski 				     "Failed to request RESET gpio\n");
52740929167SRoger Quadros 
528bcf5b3deSSander Vermin 	tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake",
529bcf5b3deSSander Vermin 						    GPIOD_OUT_HIGH);
530e32825c4SKrzysztof Kozlowski 	if (IS_ERR(tsdata->gpio_wake))
531e32825c4SKrzysztof Kozlowski 		return dev_err_probe(dev, PTR_ERR(tsdata->gpio_wake),
532e32825c4SKrzysztof Kozlowski 				     "Failed to get wake gpio\n");
533bcf5b3deSSander Vermin 
534bcf5b3deSSander Vermin 	tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable",
535bcf5b3deSSander Vermin 						      GPIOD_OUT_HIGH);
536e32825c4SKrzysztof Kozlowski 	if (IS_ERR(tsdata->gpio_enable))
537e32825c4SKrzysztof Kozlowski 		return dev_err_probe(dev, PTR_ERR(tsdata->gpio_enable),
538e32825c4SKrzysztof Kozlowski 				     "Failed to get enable gpio\n");
539bcf5b3deSSander Vermin 
540bcf5b3deSSander Vermin 	if (tsdata->gpio_enable)
541bcf5b3deSSander Vermin 		msleep(100);
542bcf5b3deSSander Vermin 
543e9d4718dSRoger Quadros 	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
5449b7e31bbSLars-Peter Clausen 					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
54536a281e2SJianchun Bian 					  client->name, tsdata);
54636a281e2SJianchun Bian 	if (error) {
547e9d4718dSRoger Quadros 		dev_err(dev, "failed to request irq %d\n", client->irq);
548e9d4718dSRoger Quadros 		return error;
54936a281e2SJianchun Bian 	}
55036a281e2SJianchun Bian 
55140929167SRoger Quadros 	pixcir_reset(tsdata);
55240929167SRoger Quadros 
5533b36fbb0SRoger Quadros 	/* Always be in IDLE mode to save power, device supports auto wake */
5543b36fbb0SRoger Quadros 	error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
5553b36fbb0SRoger Quadros 	if (error) {
5563b36fbb0SRoger Quadros 		dev_err(dev, "Failed to set IDLE mode\n");
5573b36fbb0SRoger Quadros 		return error;
5583b36fbb0SRoger Quadros 	}
5593b36fbb0SRoger Quadros 
5603b36fbb0SRoger Quadros 	/* Stop device till opened */
5613b36fbb0SRoger Quadros 	error = pixcir_stop(tsdata);
5623b36fbb0SRoger Quadros 	if (error)
5633b36fbb0SRoger Quadros 		return error;
5643b36fbb0SRoger Quadros 
56536a281e2SJianchun Bian 	error = input_register_device(input);
56636a281e2SJianchun Bian 	if (error)
567e9d4718dSRoger Quadros 		return error;
56836a281e2SJianchun Bian 
5697cdcb8d1SRoger Quadros 	i2c_set_clientdata(client, tsdata);
57036a281e2SJianchun Bian 
57136a281e2SJianchun Bian 	return 0;
57236a281e2SJianchun Bian }
57336a281e2SJianchun Bian 
574a4054596SRoger Quadros static const struct pixcir_i2c_chip_data pixcir_ts_data = {
575a4054596SRoger Quadros 	.max_fingers = 2,
576a4054596SRoger Quadros 	/* no hw id support */
577a4054596SRoger Quadros };
578a4054596SRoger Quadros 
579a4054596SRoger Quadros static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
580a4054596SRoger Quadros 	.max_fingers = 5,
581a4054596SRoger Quadros 	.has_hw_ids = true,
582a4054596SRoger Quadros };
583a4054596SRoger Quadros 
584792e154cSDmitry Torokhov static const struct i2c_device_id pixcir_i2c_ts_id[] = {
585792e154cSDmitry Torokhov 	{ "pixcir_ts", (unsigned long) &pixcir_ts_data },
586792e154cSDmitry Torokhov 	{ "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
587792e154cSDmitry Torokhov 	{ }
588792e154cSDmitry Torokhov };
589792e154cSDmitry Torokhov MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
590792e154cSDmitry Torokhov 
591792e154cSDmitry Torokhov #ifdef CONFIG_OF
592a4054596SRoger Quadros static const struct of_device_id pixcir_of_match[] = {
593a4054596SRoger Quadros 	{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
594a4054596SRoger Quadros 	{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
595a4054596SRoger Quadros 	{ }
596a4054596SRoger Quadros };
597a4054596SRoger Quadros MODULE_DEVICE_TABLE(of, pixcir_of_match);
598a4054596SRoger Quadros #endif
599a4054596SRoger Quadros 
60036a281e2SJianchun Bian static struct i2c_driver pixcir_i2c_ts_driver = {
60136a281e2SJianchun Bian 	.driver = {
60236a281e2SJianchun Bian 		.name	= "pixcir_ts",
603add8bbd2SJonathan Cameron 		.pm	= pm_sleep_ptr(&pixcir_dev_pm_ops),
604a4054596SRoger Quadros 		.of_match_table = of_match_ptr(pixcir_of_match),
60536a281e2SJianchun Bian 	},
606d8bde56dSUwe Kleine-König 	.probe		= pixcir_i2c_ts_probe,
60736a281e2SJianchun Bian 	.id_table	= pixcir_i2c_ts_id,
60836a281e2SJianchun Bian };
60936a281e2SJianchun Bian 
6104a533835SDmitry Torokhov module_i2c_driver(pixcir_i2c_ts_driver);
61136a281e2SJianchun Bian 
61236a281e2SJianchun Bian MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>");
61336a281e2SJianchun Bian MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver");
61436a281e2SJianchun Bian MODULE_LICENSE("GPL");
615