xref: /linux/drivers/input/touchscreen/pixcir_i2c_ts.c (revision 9c92ab61914157664a2fbdf926df0eb937838e45)
1*9c92ab61SThomas 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 
836a281e2SJianchun Bian #include <linux/delay.h>
936a281e2SJianchun Bian #include <linux/module.h>
1036a281e2SJianchun Bian #include <linux/interrupt.h>
1136a281e2SJianchun Bian #include <linux/slab.h>
1236a281e2SJianchun Bian #include <linux/i2c.h>
1336a281e2SJianchun Bian #include <linux/input.h>
1462e65b7eSRoger Quadros #include <linux/input/mt.h>
15d48259a0SDmitry Torokhov #include <linux/input/touchscreen.h>
160dfc8d41SRoger Quadros #include <linux/gpio.h>
17cb4a5f06SDmitry Torokhov #include <linux/gpio/consumer.h>
18a4054596SRoger Quadros #include <linux/of_device.h>
1928a74c05SDmitry Torokhov #include <linux/platform_data/pixcir_i2c_ts.h>
200bb11e96SHans de Goede #include <asm/unaligned.h>
2136a281e2SJianchun Bian 
2236874c7eSRoger Quadros #define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
2362e65b7eSRoger Quadros 
2436a281e2SJianchun Bian struct pixcir_i2c_ts_data {
2536a281e2SJianchun Bian 	struct i2c_client *client;
2636a281e2SJianchun Bian 	struct input_dev *input;
27cb4a5f06SDmitry Torokhov 	struct gpio_desc *gpio_attb;
2840929167SRoger Quadros 	struct gpio_desc *gpio_reset;
29bcf5b3deSSander Vermin 	struct gpio_desc *gpio_enable;
30bcf5b3deSSander Vermin 	struct gpio_desc *gpio_wake;
31d48259a0SDmitry Torokhov 	const struct pixcir_i2c_chip_data *chip;
320bb11e96SHans de Goede 	struct touchscreen_properties prop;
3336874c7eSRoger Quadros 	int max_fingers;	/* Max fingers supported in this instance */
34d48259a0SDmitry Torokhov 	bool running;
3536a281e2SJianchun Bian };
3636a281e2SJianchun Bian 
3762e65b7eSRoger Quadros struct pixcir_report_data {
3862e65b7eSRoger Quadros 	int num_touches;
390bb11e96SHans de Goede 	struct input_mt_pos pos[PIXCIR_MAX_SLOTS];
400bb11e96SHans de Goede 	int ids[PIXCIR_MAX_SLOTS];
4162e65b7eSRoger Quadros };
4262e65b7eSRoger Quadros 
4362e65b7eSRoger Quadros static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
4462e65b7eSRoger Quadros 			    struct pixcir_report_data *report)
4536a281e2SJianchun Bian {
4636874c7eSRoger Quadros 	u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
4736874c7eSRoger Quadros 	u8 wrbuf[1] = { 0 };
4862e65b7eSRoger Quadros 	u8 *bufptr;
4936a281e2SJianchun Bian 	u8 touch;
5062e65b7eSRoger Quadros 	int ret, i;
5136874c7eSRoger Quadros 	int readsize;
52d48259a0SDmitry Torokhov 	const struct pixcir_i2c_chip_data *chip = tsdata->chip;
5362e65b7eSRoger Quadros 
5462e65b7eSRoger Quadros 	memset(report, 0, sizeof(struct pixcir_report_data));
5536a281e2SJianchun Bian 
5636874c7eSRoger Quadros 	i = chip->has_hw_ids ? 1 : 0;
5736874c7eSRoger Quadros 	readsize = 2 + tsdata->max_fingers * (4 + i);
5836874c7eSRoger Quadros 	if (readsize > sizeof(rdbuf))
5936874c7eSRoger Quadros 		readsize = sizeof(rdbuf);
6036874c7eSRoger Quadros 
6136a281e2SJianchun Bian 	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
6236a281e2SJianchun Bian 	if (ret != sizeof(wrbuf)) {
6336a281e2SJianchun Bian 		dev_err(&tsdata->client->dev,
6436a281e2SJianchun Bian 			"%s: i2c_master_send failed(), ret=%d\n",
6536a281e2SJianchun Bian 			__func__, ret);
6636a281e2SJianchun Bian 		return;
6736a281e2SJianchun Bian 	}
6836a281e2SJianchun Bian 
6936874c7eSRoger Quadros 	ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
70469d7d22SFrodo Lai 	if (ret != readsize) {
7136a281e2SJianchun Bian 		dev_err(&tsdata->client->dev,
7236a281e2SJianchun Bian 			"%s: i2c_master_recv failed(), ret=%d\n",
7336a281e2SJianchun Bian 			__func__, ret);
7436a281e2SJianchun Bian 		return;
7536a281e2SJianchun Bian 	}
7636a281e2SJianchun Bian 
7762e65b7eSRoger Quadros 	touch = rdbuf[0] & 0x7;
7836874c7eSRoger Quadros 	if (touch > tsdata->max_fingers)
7936874c7eSRoger Quadros 		touch = tsdata->max_fingers;
8036a281e2SJianchun Bian 
8162e65b7eSRoger Quadros 	report->num_touches = touch;
8262e65b7eSRoger Quadros 	bufptr = &rdbuf[2];
8336a281e2SJianchun Bian 
8462e65b7eSRoger Quadros 	for (i = 0; i < touch; i++) {
850bb11e96SHans de Goede 		touchscreen_set_mt_pos(&report->pos[i], &tsdata->prop,
860bb11e96SHans de Goede 				       get_unaligned_le16(bufptr),
870bb11e96SHans de Goede 				       get_unaligned_le16(bufptr + 2));
8836874c7eSRoger Quadros 		if (chip->has_hw_ids) {
890bb11e96SHans de Goede 			report->ids[i] = bufptr[4];
9036874c7eSRoger Quadros 			bufptr = bufptr + 5;
9136874c7eSRoger Quadros 		} else {
9262e65b7eSRoger Quadros 			bufptr = bufptr + 4;
9336a281e2SJianchun Bian 		}
9436a281e2SJianchun Bian 	}
9536874c7eSRoger Quadros }
9636a281e2SJianchun Bian 
9762e65b7eSRoger Quadros static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
9862e65b7eSRoger Quadros 			     struct pixcir_report_data *report)
9962e65b7eSRoger Quadros {
10062e65b7eSRoger Quadros 	int slots[PIXCIR_MAX_SLOTS];
10162e65b7eSRoger Quadros 	int n, i, slot;
10262e65b7eSRoger Quadros 	struct device *dev = &ts->client->dev;
103d48259a0SDmitry Torokhov 	const struct pixcir_i2c_chip_data *chip = ts->chip;
10462e65b7eSRoger Quadros 
10562e65b7eSRoger Quadros 	n = report->num_touches;
10662e65b7eSRoger Quadros 	if (n > PIXCIR_MAX_SLOTS)
10762e65b7eSRoger Quadros 		n = PIXCIR_MAX_SLOTS;
10862e65b7eSRoger Quadros 
1090bb11e96SHans de Goede 	if (!ts->chip->has_hw_ids)
1100bb11e96SHans de Goede 		input_mt_assign_slots(ts->input, slots, report->pos, n, 0);
11162e65b7eSRoger Quadros 
11262e65b7eSRoger Quadros 	for (i = 0; i < n; i++) {
11336874c7eSRoger Quadros 		if (chip->has_hw_ids) {
1140bb11e96SHans de Goede 			slot = input_mt_get_slot_by_key(ts->input,
1150bb11e96SHans de Goede 							report->ids[i]);
11636874c7eSRoger Quadros 			if (slot < 0) {
11736874c7eSRoger Quadros 				dev_dbg(dev, "no free slot for id 0x%x\n",
1180bb11e96SHans de Goede 					report->ids[i]);
11936874c7eSRoger Quadros 				continue;
12036874c7eSRoger Quadros 			}
12136874c7eSRoger Quadros 		} else {
12262e65b7eSRoger Quadros 			slot = slots[i];
12336874c7eSRoger Quadros 		}
12462e65b7eSRoger Quadros 
12562e65b7eSRoger Quadros 		input_mt_slot(ts->input, slot);
1260bb11e96SHans de Goede 		input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
12762e65b7eSRoger Quadros 
1280bb11e96SHans de Goede 		input_report_abs(ts->input, ABS_MT_POSITION_X,
1290bb11e96SHans de Goede 				 report->pos[i].x);
1300bb11e96SHans de Goede 		input_report_abs(ts->input, ABS_MT_POSITION_Y,
1310bb11e96SHans de Goede 				 report->pos[i].y);
13262e65b7eSRoger Quadros 
13362e65b7eSRoger Quadros 		dev_dbg(dev, "%d: slot %d, x %d, y %d\n",
1340bb11e96SHans de Goede 			i, slot, report->pos[i].x, report->pos[i].y);
13562e65b7eSRoger Quadros 	}
13662e65b7eSRoger Quadros 
13762e65b7eSRoger Quadros 	input_mt_sync_frame(ts->input);
13862e65b7eSRoger Quadros 	input_sync(ts->input);
13936a281e2SJianchun Bian }
14036a281e2SJianchun Bian 
14136a281e2SJianchun Bian static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
14236a281e2SJianchun Bian {
14336a281e2SJianchun Bian 	struct pixcir_i2c_ts_data *tsdata = dev_id;
14462e65b7eSRoger Quadros 	struct pixcir_report_data report;
14536a281e2SJianchun Bian 
1463b36fbb0SRoger Quadros 	while (tsdata->running) {
14762e65b7eSRoger Quadros 		/* parse packet */
14862e65b7eSRoger Quadros 		pixcir_ts_parse(tsdata, &report);
14936a281e2SJianchun Bian 
15062e65b7eSRoger Quadros 		/* report it */
15162e65b7eSRoger Quadros 		pixcir_ts_report(tsdata, &report);
15262e65b7eSRoger Quadros 
153127520caSDmitry Torokhov 		if (gpiod_get_value_cansleep(tsdata->gpio_attb)) {
15462e65b7eSRoger Quadros 			if (report.num_touches) {
15562e65b7eSRoger Quadros 				/*
15662e65b7eSRoger Quadros 				 * Last report with no finger up?
15762e65b7eSRoger Quadros 				 * Do it now then.
15862e65b7eSRoger Quadros 				 */
15962e65b7eSRoger Quadros 				input_mt_sync_frame(tsdata->input);
16062e65b7eSRoger Quadros 				input_sync(tsdata->input);
16162e65b7eSRoger Quadros 			}
16236a281e2SJianchun Bian 			break;
16362e65b7eSRoger Quadros 		}
16436a281e2SJianchun Bian 
16536a281e2SJianchun Bian 		msleep(20);
16636a281e2SJianchun Bian 	}
16736a281e2SJianchun Bian 
16836a281e2SJianchun Bian 	return IRQ_HANDLED;
16936a281e2SJianchun Bian }
17036a281e2SJianchun Bian 
17140929167SRoger Quadros static void pixcir_reset(struct pixcir_i2c_ts_data *tsdata)
17240929167SRoger Quadros {
17340929167SRoger Quadros 	if (!IS_ERR_OR_NULL(tsdata->gpio_reset)) {
17440929167SRoger Quadros 		gpiod_set_value_cansleep(tsdata->gpio_reset, 1);
17540929167SRoger Quadros 		ndelay(100);	/* datasheet section 1.2.3 says 80ns min. */
17640929167SRoger Quadros 		gpiod_set_value_cansleep(tsdata->gpio_reset, 0);
17740929167SRoger Quadros 		/* wait for controller ready. 100ms guess. */
17840929167SRoger Quadros 		msleep(100);
17940929167SRoger Quadros 	}
18040929167SRoger Quadros }
18140929167SRoger Quadros 
1823b36fbb0SRoger Quadros static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
1833b36fbb0SRoger Quadros 				 enum pixcir_power_mode mode)
1843b36fbb0SRoger Quadros {
1853b36fbb0SRoger Quadros 	struct device *dev = &ts->client->dev;
1863b36fbb0SRoger Quadros 	int ret;
1873b36fbb0SRoger Quadros 
188bcf5b3deSSander Vermin 	if (mode == PIXCIR_POWER_ACTIVE || mode == PIXCIR_POWER_IDLE) {
189bcf5b3deSSander Vermin 		if (ts->gpio_wake)
190bcf5b3deSSander Vermin 			gpiod_set_value_cansleep(ts->gpio_wake, 1);
191bcf5b3deSSander Vermin 	}
192bcf5b3deSSander Vermin 
1933b36fbb0SRoger Quadros 	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
1943b36fbb0SRoger Quadros 	if (ret < 0) {
1953b36fbb0SRoger Quadros 		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
1963b36fbb0SRoger Quadros 			__func__, PIXCIR_REG_POWER_MODE, ret);
1973b36fbb0SRoger Quadros 		return ret;
1983b36fbb0SRoger Quadros 	}
1993b36fbb0SRoger Quadros 
2003b36fbb0SRoger Quadros 	ret &= ~PIXCIR_POWER_MODE_MASK;
2013b36fbb0SRoger Quadros 	ret |= mode;
2023b36fbb0SRoger Quadros 
2033b36fbb0SRoger Quadros 	/* Always AUTO_IDLE */
2043b36fbb0SRoger Quadros 	ret |= PIXCIR_POWER_ALLOW_IDLE;
2053b36fbb0SRoger Quadros 
2063b36fbb0SRoger Quadros 	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
2073b36fbb0SRoger Quadros 	if (ret < 0) {
2083b36fbb0SRoger Quadros 		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
2093b36fbb0SRoger Quadros 			__func__, PIXCIR_REG_POWER_MODE, ret);
2103b36fbb0SRoger Quadros 		return ret;
2113b36fbb0SRoger Quadros 	}
2123b36fbb0SRoger Quadros 
213bcf5b3deSSander Vermin 	if (mode == PIXCIR_POWER_HALT) {
214bcf5b3deSSander Vermin 		if (ts->gpio_wake)
215bcf5b3deSSander Vermin 			gpiod_set_value_cansleep(ts->gpio_wake, 0);
216bcf5b3deSSander Vermin 	}
217bcf5b3deSSander Vermin 
2183b36fbb0SRoger Quadros 	return 0;
2193b36fbb0SRoger Quadros }
2203b36fbb0SRoger Quadros 
2213b36fbb0SRoger Quadros /*
2223b36fbb0SRoger Quadros  * Set the interrupt mode for the device i.e. ATTB line behaviour
2233b36fbb0SRoger Quadros  *
2243b36fbb0SRoger Quadros  * @polarity : 1 for active high, 0 for active low.
2253b36fbb0SRoger Quadros  */
2263b36fbb0SRoger Quadros static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
2273b36fbb0SRoger Quadros 			       enum pixcir_int_mode mode, bool polarity)
2283b36fbb0SRoger Quadros {
2293b36fbb0SRoger Quadros 	struct device *dev = &ts->client->dev;
2303b36fbb0SRoger Quadros 	int ret;
2313b36fbb0SRoger Quadros 
2323b36fbb0SRoger Quadros 	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
2333b36fbb0SRoger Quadros 	if (ret < 0) {
2343b36fbb0SRoger Quadros 		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
2353b36fbb0SRoger Quadros 			__func__, PIXCIR_REG_INT_MODE, ret);
2363b36fbb0SRoger Quadros 		return ret;
2373b36fbb0SRoger Quadros 	}
2383b36fbb0SRoger Quadros 
2393b36fbb0SRoger Quadros 	ret &= ~PIXCIR_INT_MODE_MASK;
2403b36fbb0SRoger Quadros 	ret |= mode;
2413b36fbb0SRoger Quadros 
2423b36fbb0SRoger Quadros 	if (polarity)
2433b36fbb0SRoger Quadros 		ret |= PIXCIR_INT_POL_HIGH;
2443b36fbb0SRoger Quadros 	else
2453b36fbb0SRoger Quadros 		ret &= ~PIXCIR_INT_POL_HIGH;
2463b36fbb0SRoger Quadros 
2473b36fbb0SRoger Quadros 	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
2483b36fbb0SRoger Quadros 	if (ret < 0) {
2493b36fbb0SRoger Quadros 		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
2503b36fbb0SRoger Quadros 			__func__, PIXCIR_REG_INT_MODE, ret);
2513b36fbb0SRoger Quadros 		return ret;
2523b36fbb0SRoger Quadros 	}
2533b36fbb0SRoger Quadros 
2543b36fbb0SRoger Quadros 	return 0;
2553b36fbb0SRoger Quadros }
2563b36fbb0SRoger Quadros 
2573b36fbb0SRoger Quadros /*
2583b36fbb0SRoger Quadros  * Enable/disable interrupt generation
2593b36fbb0SRoger Quadros  */
2603b36fbb0SRoger Quadros static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
2613b36fbb0SRoger Quadros {
2623b36fbb0SRoger Quadros 	struct device *dev = &ts->client->dev;
2633b36fbb0SRoger Quadros 	int ret;
2643b36fbb0SRoger Quadros 
2653b36fbb0SRoger Quadros 	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
2663b36fbb0SRoger Quadros 	if (ret < 0) {
2673b36fbb0SRoger Quadros 		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
2683b36fbb0SRoger Quadros 			__func__, PIXCIR_REG_INT_MODE, ret);
2693b36fbb0SRoger Quadros 		return ret;
2703b36fbb0SRoger Quadros 	}
2713b36fbb0SRoger Quadros 
2723b36fbb0SRoger Quadros 	if (enable)
2733b36fbb0SRoger Quadros 		ret |= PIXCIR_INT_ENABLE;
2743b36fbb0SRoger Quadros 	else
2753b36fbb0SRoger Quadros 		ret &= ~PIXCIR_INT_ENABLE;
2763b36fbb0SRoger Quadros 
2773b36fbb0SRoger Quadros 	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
2783b36fbb0SRoger Quadros 	if (ret < 0) {
2793b36fbb0SRoger Quadros 		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
2803b36fbb0SRoger Quadros 			__func__, PIXCIR_REG_INT_MODE, ret);
2813b36fbb0SRoger Quadros 		return ret;
2823b36fbb0SRoger Quadros 	}
2833b36fbb0SRoger Quadros 
2843b36fbb0SRoger Quadros 	return 0;
2853b36fbb0SRoger Quadros }
2863b36fbb0SRoger Quadros 
2873b36fbb0SRoger Quadros static int pixcir_start(struct pixcir_i2c_ts_data *ts)
2883b36fbb0SRoger Quadros {
2893b36fbb0SRoger Quadros 	struct device *dev = &ts->client->dev;
2903b36fbb0SRoger Quadros 	int error;
2913b36fbb0SRoger Quadros 
292bcf5b3deSSander Vermin 	if (ts->gpio_enable) {
293bcf5b3deSSander Vermin 		gpiod_set_value_cansleep(ts->gpio_enable, 1);
294bcf5b3deSSander Vermin 		msleep(100);
295bcf5b3deSSander Vermin 	}
296bcf5b3deSSander Vermin 
2973b36fbb0SRoger Quadros 	/* LEVEL_TOUCH interrupt with active low polarity */
2983b36fbb0SRoger Quadros 	error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
2993b36fbb0SRoger Quadros 	if (error) {
3003b36fbb0SRoger Quadros 		dev_err(dev, "Failed to set interrupt mode: %d\n", error);
3013b36fbb0SRoger Quadros 		return error;
3023b36fbb0SRoger Quadros 	}
3033b36fbb0SRoger Quadros 
3043b36fbb0SRoger Quadros 	ts->running = true;
3053b36fbb0SRoger Quadros 	mb();	/* Update status before IRQ can fire */
3063b36fbb0SRoger Quadros 
3073b36fbb0SRoger Quadros 	/* enable interrupt generation */
3083b36fbb0SRoger Quadros 	error = pixcir_int_enable(ts, true);
3093b36fbb0SRoger Quadros 	if (error) {
3103b36fbb0SRoger Quadros 		dev_err(dev, "Failed to enable interrupt generation: %d\n",
3113b36fbb0SRoger Quadros 			error);
3123b36fbb0SRoger Quadros 		return error;
3133b36fbb0SRoger Quadros 	}
3143b36fbb0SRoger Quadros 
3153b36fbb0SRoger Quadros 	return 0;
3163b36fbb0SRoger Quadros }
3173b36fbb0SRoger Quadros 
3183b36fbb0SRoger Quadros static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
3193b36fbb0SRoger Quadros {
3203b36fbb0SRoger Quadros 	int error;
3213b36fbb0SRoger Quadros 
3223b36fbb0SRoger Quadros 	/* Disable interrupt generation */
3233b36fbb0SRoger Quadros 	error = pixcir_int_enable(ts, false);
3243b36fbb0SRoger Quadros 	if (error) {
3253b36fbb0SRoger Quadros 		dev_err(&ts->client->dev,
3263b36fbb0SRoger Quadros 			"Failed to disable interrupt generation: %d\n",
3273b36fbb0SRoger Quadros 			error);
3283b36fbb0SRoger Quadros 		return error;
3293b36fbb0SRoger Quadros 	}
3303b36fbb0SRoger Quadros 
3313b36fbb0SRoger Quadros 	/* Exit ISR if running, no more report parsing */
3323b36fbb0SRoger Quadros 	ts->running = false;
3333b36fbb0SRoger Quadros 	mb();	/* update status before we synchronize irq */
3343b36fbb0SRoger Quadros 
3353b36fbb0SRoger Quadros 	/* Wait till running ISR is complete */
3363b36fbb0SRoger Quadros 	synchronize_irq(ts->client->irq);
3373b36fbb0SRoger Quadros 
338bcf5b3deSSander Vermin 	if (ts->gpio_enable)
339bcf5b3deSSander Vermin 		gpiod_set_value_cansleep(ts->gpio_enable, 0);
340bcf5b3deSSander Vermin 
3413b36fbb0SRoger Quadros 	return 0;
3423b36fbb0SRoger Quadros }
3433b36fbb0SRoger Quadros 
3443b36fbb0SRoger Quadros static int pixcir_input_open(struct input_dev *dev)
3453b36fbb0SRoger Quadros {
3463b36fbb0SRoger Quadros 	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
3473b36fbb0SRoger Quadros 
3483b36fbb0SRoger Quadros 	return pixcir_start(ts);
3493b36fbb0SRoger Quadros }
3503b36fbb0SRoger Quadros 
3513b36fbb0SRoger Quadros static void pixcir_input_close(struct input_dev *dev)
3523b36fbb0SRoger Quadros {
3533b36fbb0SRoger Quadros 	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
3543b36fbb0SRoger Quadros 
3553b36fbb0SRoger Quadros 	pixcir_stop(ts);
3563b36fbb0SRoger Quadros }
3573b36fbb0SRoger Quadros 
35802b6a58bSJingoo Han static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
35936a281e2SJianchun Bian {
36036a281e2SJianchun Bian 	struct i2c_client *client = to_i2c_client(dev);
3617cdcb8d1SRoger Quadros 	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
3627cdcb8d1SRoger Quadros 	struct input_dev *input = ts->input;
3637cdcb8d1SRoger Quadros 	int ret = 0;
36436a281e2SJianchun Bian 
3657cdcb8d1SRoger Quadros 	mutex_lock(&input->mutex);
3667cdcb8d1SRoger Quadros 
3677cdcb8d1SRoger Quadros 	if (device_may_wakeup(&client->dev)) {
3687cdcb8d1SRoger Quadros 		if (!input->users) {
3697cdcb8d1SRoger Quadros 			ret = pixcir_start(ts);
3707cdcb8d1SRoger Quadros 			if (ret) {
3717cdcb8d1SRoger Quadros 				dev_err(dev, "Failed to start\n");
3727cdcb8d1SRoger Quadros 				goto unlock;
3737cdcb8d1SRoger Quadros 			}
3747cdcb8d1SRoger Quadros 		}
3757cdcb8d1SRoger Quadros 	} else if (input->users) {
3767cdcb8d1SRoger Quadros 		ret = pixcir_stop(ts);
3777cdcb8d1SRoger Quadros 	}
37836a281e2SJianchun Bian 
3797cdcb8d1SRoger Quadros unlock:
3807cdcb8d1SRoger Quadros 	mutex_unlock(&input->mutex);
3817cdcb8d1SRoger Quadros 
3827cdcb8d1SRoger Quadros 	return ret;
38336a281e2SJianchun Bian }
38436a281e2SJianchun Bian 
38502b6a58bSJingoo Han static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
38636a281e2SJianchun Bian {
38736a281e2SJianchun Bian 	struct i2c_client *client = to_i2c_client(dev);
3887cdcb8d1SRoger Quadros 	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
3897cdcb8d1SRoger Quadros 	struct input_dev *input = ts->input;
3907cdcb8d1SRoger Quadros 	int ret = 0;
39136a281e2SJianchun Bian 
3927cdcb8d1SRoger Quadros 	mutex_lock(&input->mutex);
3937cdcb8d1SRoger Quadros 
3947cdcb8d1SRoger Quadros 	if (device_may_wakeup(&client->dev)) {
3957cdcb8d1SRoger Quadros 		if (!input->users) {
3967cdcb8d1SRoger Quadros 			ret = pixcir_stop(ts);
3977cdcb8d1SRoger Quadros 			if (ret) {
3987cdcb8d1SRoger Quadros 				dev_err(dev, "Failed to stop\n");
3997cdcb8d1SRoger Quadros 				goto unlock;
4007cdcb8d1SRoger Quadros 			}
4017cdcb8d1SRoger Quadros 		}
4027cdcb8d1SRoger Quadros 	} else if (input->users) {
4037cdcb8d1SRoger Quadros 		ret = pixcir_start(ts);
4047cdcb8d1SRoger Quadros 	}
4057cdcb8d1SRoger Quadros 
4067cdcb8d1SRoger Quadros unlock:
4077cdcb8d1SRoger Quadros 	mutex_unlock(&input->mutex);
4087cdcb8d1SRoger Quadros 
4097cdcb8d1SRoger Quadros 	return ret;
41036a281e2SJianchun Bian }
41136a281e2SJianchun Bian 
41236a281e2SJianchun Bian static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
41336a281e2SJianchun Bian 			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
41436a281e2SJianchun Bian 
415a4054596SRoger Quadros #ifdef CONFIG_OF
416a4054596SRoger Quadros static const struct of_device_id pixcir_of_match[];
417a4054596SRoger Quadros 
418d48259a0SDmitry Torokhov static int pixcir_parse_dt(struct device *dev,
419d48259a0SDmitry Torokhov 			   struct pixcir_i2c_ts_data *tsdata)
420a4054596SRoger Quadros {
4218ffef3ccSLABBE Corentin 	tsdata->chip = of_device_get_match_data(dev);
422d48259a0SDmitry Torokhov 	if (!tsdata->chip)
423d48259a0SDmitry Torokhov 		return -EINVAL;
424a4054596SRoger Quadros 
425d48259a0SDmitry Torokhov 	return 0;
426a4054596SRoger Quadros }
427a4054596SRoger Quadros #else
428d48259a0SDmitry Torokhov static int pixcir_parse_dt(struct device *dev,
429d48259a0SDmitry Torokhov 			   struct pixcir_i2c_ts_data *tsdata)
430a4054596SRoger Quadros {
431d48259a0SDmitry Torokhov 	return -EINVAL;
432a4054596SRoger Quadros }
433a4054596SRoger Quadros #endif
434a4054596SRoger Quadros 
4355298cc4cSBill Pemberton static int pixcir_i2c_ts_probe(struct i2c_client *client,
43636a281e2SJianchun Bian 			       const struct i2c_device_id *id)
43736a281e2SJianchun Bian {
438c838cb3dSJingoo Han 	const struct pixcir_ts_platform_data *pdata =
439c838cb3dSJingoo Han 			dev_get_platdata(&client->dev);
440e9d4718dSRoger Quadros 	struct device *dev = &client->dev;
44136a281e2SJianchun Bian 	struct pixcir_i2c_ts_data *tsdata;
44236a281e2SJianchun Bian 	struct input_dev *input;
44336a281e2SJianchun Bian 	int error;
44436a281e2SJianchun Bian 
445d48259a0SDmitry Torokhov 	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
446d48259a0SDmitry Torokhov 	if (!tsdata)
447d48259a0SDmitry Torokhov 		return -ENOMEM;
448a4054596SRoger Quadros 
449d48259a0SDmitry Torokhov 	if (pdata) {
450d48259a0SDmitry Torokhov 		tsdata->chip = &pdata->chip;
451d48259a0SDmitry Torokhov 	} else if (dev->of_node) {
452d48259a0SDmitry Torokhov 		error = pixcir_parse_dt(dev, tsdata);
453d48259a0SDmitry Torokhov 		if (error)
454d48259a0SDmitry Torokhov 			return error;
455d48259a0SDmitry Torokhov 	} else {
456d7ddf154SGuenter Roeck 		dev_err(dev, "platform data not defined\n");
45736a281e2SJianchun Bian 		return -EINVAL;
45836a281e2SJianchun Bian 	}
45936a281e2SJianchun Bian 
460d48259a0SDmitry Torokhov 	if (!tsdata->chip->max_fingers) {
461d48259a0SDmitry Torokhov 		dev_err(dev, "Invalid max_fingers in chip data\n");
46236874c7eSRoger Quadros 		return -EINVAL;
46336874c7eSRoger Quadros 	}
46436874c7eSRoger Quadros 
465e9d4718dSRoger Quadros 	input = devm_input_allocate_device(dev);
466e9d4718dSRoger Quadros 	if (!input) {
467e9d4718dSRoger Quadros 		dev_err(dev, "Failed to allocate input device\n");
468e9d4718dSRoger Quadros 		return -ENOMEM;
46936a281e2SJianchun Bian 	}
47036a281e2SJianchun Bian 
47136a281e2SJianchun Bian 	tsdata->client = client;
47236a281e2SJianchun Bian 	tsdata->input = input;
47336a281e2SJianchun Bian 
47436a281e2SJianchun Bian 	input->name = client->name;
47536a281e2SJianchun Bian 	input->id.bustype = BUS_I2C;
4763b36fbb0SRoger Quadros 	input->open = pixcir_input_open;
4773b36fbb0SRoger Quadros 	input->close = pixcir_input_close;
478d7ddf154SGuenter Roeck 	input->dev.parent = dev;
47936a281e2SJianchun Bian 
480d48259a0SDmitry Torokhov 	if (pdata) {
48136a281e2SJianchun Bian 		input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
48236a281e2SJianchun Bian 		input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
483d48259a0SDmitry Torokhov 	} else {
484d48259a0SDmitry Torokhov 		input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
485d48259a0SDmitry Torokhov 		input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
4860bb11e96SHans de Goede 		touchscreen_parse_properties(input, true, &tsdata->prop);
487d48259a0SDmitry Torokhov 		if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
488d48259a0SDmitry Torokhov 		    !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
489d48259a0SDmitry Torokhov 			dev_err(dev, "Touchscreen size is not specified\n");
490d48259a0SDmitry Torokhov 			return -EINVAL;
491d48259a0SDmitry Torokhov 		}
492d48259a0SDmitry Torokhov 	}
49336a281e2SJianchun Bian 
494d48259a0SDmitry Torokhov 	tsdata->max_fingers = tsdata->chip->max_fingers;
49536874c7eSRoger Quadros 	if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
49636874c7eSRoger Quadros 		tsdata->max_fingers = PIXCIR_MAX_SLOTS;
49736874c7eSRoger Quadros 		dev_info(dev, "Limiting maximum fingers to %d\n",
49836874c7eSRoger Quadros 			 tsdata->max_fingers);
49936874c7eSRoger Quadros 	}
50036874c7eSRoger Quadros 
50136874c7eSRoger Quadros 	error = input_mt_init_slots(input, tsdata->max_fingers,
50262e65b7eSRoger Quadros 				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
50362e65b7eSRoger Quadros 	if (error) {
50462e65b7eSRoger Quadros 		dev_err(dev, "Error initializing Multi-Touch slots\n");
50562e65b7eSRoger Quadros 		return error;
50662e65b7eSRoger Quadros 	}
50762e65b7eSRoger Quadros 
50836a281e2SJianchun Bian 	input_set_drvdata(input, tsdata);
50936a281e2SJianchun Bian 
510cb4a5f06SDmitry Torokhov 	tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN);
511cb4a5f06SDmitry Torokhov 	if (IS_ERR(tsdata->gpio_attb)) {
512cb4a5f06SDmitry Torokhov 		error = PTR_ERR(tsdata->gpio_attb);
513cb4a5f06SDmitry Torokhov 		dev_err(dev, "Failed to request ATTB gpio: %d\n", error);
5140dfc8d41SRoger Quadros 		return error;
5150dfc8d41SRoger Quadros 	}
5160dfc8d41SRoger Quadros 
51740929167SRoger Quadros 	tsdata->gpio_reset = devm_gpiod_get_optional(dev, "reset",
51840929167SRoger Quadros 						     GPIOD_OUT_LOW);
51940929167SRoger Quadros 	if (IS_ERR(tsdata->gpio_reset)) {
52040929167SRoger Quadros 		error = PTR_ERR(tsdata->gpio_reset);
52140929167SRoger Quadros 		dev_err(dev, "Failed to request RESET gpio: %d\n", error);
52240929167SRoger Quadros 		return error;
52340929167SRoger Quadros 	}
52440929167SRoger Quadros 
525bcf5b3deSSander Vermin 	tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake",
526bcf5b3deSSander Vermin 						    GPIOD_OUT_HIGH);
527bcf5b3deSSander Vermin 	if (IS_ERR(tsdata->gpio_wake)) {
528bcf5b3deSSander Vermin 		error = PTR_ERR(tsdata->gpio_wake);
529bcf5b3deSSander Vermin 		if (error != -EPROBE_DEFER)
530bcf5b3deSSander Vermin 			dev_err(dev, "Failed to get wake gpio: %d\n", error);
531bcf5b3deSSander Vermin 		return error;
532bcf5b3deSSander Vermin 	}
533bcf5b3deSSander Vermin 
534bcf5b3deSSander Vermin 	tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable",
535bcf5b3deSSander Vermin 						      GPIOD_OUT_HIGH);
536bcf5b3deSSander Vermin 	if (IS_ERR(tsdata->gpio_enable)) {
537bcf5b3deSSander Vermin 		error = PTR_ERR(tsdata->gpio_enable);
538bcf5b3deSSander Vermin 		if (error != -EPROBE_DEFER)
539bcf5b3deSSander Vermin 			dev_err(dev, "Failed to get enable gpio: %d\n", error);
540bcf5b3deSSander Vermin 		return error;
541bcf5b3deSSander Vermin 	}
542bcf5b3deSSander Vermin 
543bcf5b3deSSander Vermin 	if (tsdata->gpio_enable)
544bcf5b3deSSander Vermin 		msleep(100);
545bcf5b3deSSander Vermin 
546e9d4718dSRoger Quadros 	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
5479b7e31bbSLars-Peter Clausen 					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
54836a281e2SJianchun Bian 					  client->name, tsdata);
54936a281e2SJianchun Bian 	if (error) {
550e9d4718dSRoger Quadros 		dev_err(dev, "failed to request irq %d\n", client->irq);
551e9d4718dSRoger Quadros 		return error;
55236a281e2SJianchun Bian 	}
55336a281e2SJianchun Bian 
55440929167SRoger Quadros 	pixcir_reset(tsdata);
55540929167SRoger Quadros 
5563b36fbb0SRoger Quadros 	/* Always be in IDLE mode to save power, device supports auto wake */
5573b36fbb0SRoger Quadros 	error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
5583b36fbb0SRoger Quadros 	if (error) {
5593b36fbb0SRoger Quadros 		dev_err(dev, "Failed to set IDLE mode\n");
5603b36fbb0SRoger Quadros 		return error;
5613b36fbb0SRoger Quadros 	}
5623b36fbb0SRoger Quadros 
5633b36fbb0SRoger Quadros 	/* Stop device till opened */
5643b36fbb0SRoger Quadros 	error = pixcir_stop(tsdata);
5653b36fbb0SRoger Quadros 	if (error)
5663b36fbb0SRoger Quadros 		return error;
5673b36fbb0SRoger Quadros 
56836a281e2SJianchun Bian 	error = input_register_device(input);
56936a281e2SJianchun Bian 	if (error)
570e9d4718dSRoger Quadros 		return error;
57136a281e2SJianchun Bian 
5727cdcb8d1SRoger Quadros 	i2c_set_clientdata(client, tsdata);
57336a281e2SJianchun Bian 
57436a281e2SJianchun Bian 	return 0;
57536a281e2SJianchun Bian }
57636a281e2SJianchun Bian 
57736a281e2SJianchun Bian static const struct i2c_device_id pixcir_i2c_ts_id[] = {
57836a281e2SJianchun Bian 	{ "pixcir_ts", 0 },
579a4054596SRoger Quadros 	{ "pixcir_tangoc", 0 },
58036a281e2SJianchun Bian 	{ }
58136a281e2SJianchun Bian };
58236a281e2SJianchun Bian MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
58336a281e2SJianchun Bian 
584a4054596SRoger Quadros #ifdef CONFIG_OF
585a4054596SRoger Quadros static const struct pixcir_i2c_chip_data pixcir_ts_data = {
586a4054596SRoger Quadros 	.max_fingers = 2,
587a4054596SRoger Quadros 	/* no hw id support */
588a4054596SRoger Quadros };
589a4054596SRoger Quadros 
590a4054596SRoger Quadros static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
591a4054596SRoger Quadros 	.max_fingers = 5,
592a4054596SRoger Quadros 	.has_hw_ids = true,
593a4054596SRoger Quadros };
594a4054596SRoger Quadros 
595a4054596SRoger Quadros static const struct of_device_id pixcir_of_match[] = {
596a4054596SRoger Quadros 	{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
597a4054596SRoger Quadros 	{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
598a4054596SRoger Quadros 	{ }
599a4054596SRoger Quadros };
600a4054596SRoger Quadros MODULE_DEVICE_TABLE(of, pixcir_of_match);
601a4054596SRoger Quadros #endif
602a4054596SRoger Quadros 
60336a281e2SJianchun Bian static struct i2c_driver pixcir_i2c_ts_driver = {
60436a281e2SJianchun Bian 	.driver = {
60536a281e2SJianchun Bian 		.name	= "pixcir_ts",
60636a281e2SJianchun Bian 		.pm	= &pixcir_dev_pm_ops,
607a4054596SRoger Quadros 		.of_match_table = of_match_ptr(pixcir_of_match),
60836a281e2SJianchun Bian 	},
60936a281e2SJianchun Bian 	.probe		= pixcir_i2c_ts_probe,
61036a281e2SJianchun Bian 	.id_table	= pixcir_i2c_ts_id,
61136a281e2SJianchun Bian };
61236a281e2SJianchun Bian 
6134a533835SDmitry Torokhov module_i2c_driver(pixcir_i2c_ts_driver);
61436a281e2SJianchun Bian 
61536a281e2SJianchun Bian MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>");
61636a281e2SJianchun Bian MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver");
61736a281e2SJianchun Bian MODULE_LICENSE("GPL");
618