162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Driver for Pixcir I2C touchscreen controllers.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2010-2011 Pixcir, Inc.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <asm/unaligned.h>
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1162306a36Sopenharmony_ci#include <linux/i2c.h>
1262306a36Sopenharmony_ci#include <linux/input.h>
1362306a36Sopenharmony_ci#include <linux/input/mt.h>
1462306a36Sopenharmony_ci#include <linux/input/touchscreen.h>
1562306a36Sopenharmony_ci#include <linux/interrupt.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/of.h>
1862306a36Sopenharmony_ci#include <linux/slab.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/*
2362306a36Sopenharmony_ci * Register map
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci#define PIXCIR_REG_POWER_MODE	51
2662306a36Sopenharmony_ci#define PIXCIR_REG_INT_MODE	52
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * Power modes:
3062306a36Sopenharmony_ci * active: max scan speed
3162306a36Sopenharmony_ci * idle: lower scan speed with automatic transition to active on touch
3262306a36Sopenharmony_ci * halt: datasheet says sleep but this is more like halt as the chip
3362306a36Sopenharmony_ci *       clocks are cut and it can only be brought out of this mode
3462306a36Sopenharmony_ci *	 using the RESET pin.
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_cienum pixcir_power_mode {
3762306a36Sopenharmony_ci	PIXCIR_POWER_ACTIVE,
3862306a36Sopenharmony_ci	PIXCIR_POWER_IDLE,
3962306a36Sopenharmony_ci	PIXCIR_POWER_HALT,
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define PIXCIR_POWER_MODE_MASK	0x03
4362306a36Sopenharmony_ci#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/*
4662306a36Sopenharmony_ci * Interrupt modes:
4762306a36Sopenharmony_ci * periodical: interrupt is asserted periodicaly
4862306a36Sopenharmony_ci * diff coordinates: interrupt is asserted when coordinates change
4962306a36Sopenharmony_ci * level on touch: interrupt level asserted during touch
5062306a36Sopenharmony_ci * pulse on touch: interrupt pulse asserted during touch
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci */
5362306a36Sopenharmony_cienum pixcir_int_mode {
5462306a36Sopenharmony_ci	PIXCIR_INT_PERIODICAL,
5562306a36Sopenharmony_ci	PIXCIR_INT_DIFF_COORD,
5662306a36Sopenharmony_ci	PIXCIR_INT_LEVEL_TOUCH,
5762306a36Sopenharmony_ci	PIXCIR_INT_PULSE_TOUCH,
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define PIXCIR_INT_MODE_MASK	0x03
6162306a36Sopenharmony_ci#define PIXCIR_INT_ENABLE	(1UL << 3)
6262306a36Sopenharmony_ci#define PIXCIR_INT_POL_HIGH	(1UL << 2)
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/**
6562306a36Sopenharmony_ci * struct pixcir_i2c_chip_data - chip related data
6662306a36Sopenharmony_ci * @max_fingers:	Max number of fingers reported simultaneously by h/w
6762306a36Sopenharmony_ci * @has_hw_ids:		Hardware supports finger tracking IDs
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_cistruct pixcir_i2c_chip_data {
7162306a36Sopenharmony_ci	u8 max_fingers;
7262306a36Sopenharmony_ci	bool has_hw_ids;
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistruct pixcir_i2c_ts_data {
7662306a36Sopenharmony_ci	struct i2c_client *client;
7762306a36Sopenharmony_ci	struct input_dev *input;
7862306a36Sopenharmony_ci	struct gpio_desc *gpio_attb;
7962306a36Sopenharmony_ci	struct gpio_desc *gpio_reset;
8062306a36Sopenharmony_ci	struct gpio_desc *gpio_enable;
8162306a36Sopenharmony_ci	struct gpio_desc *gpio_wake;
8262306a36Sopenharmony_ci	const struct pixcir_i2c_chip_data *chip;
8362306a36Sopenharmony_ci	struct touchscreen_properties prop;
8462306a36Sopenharmony_ci	bool running;
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistruct pixcir_report_data {
8862306a36Sopenharmony_ci	int num_touches;
8962306a36Sopenharmony_ci	struct input_mt_pos pos[PIXCIR_MAX_SLOTS];
9062306a36Sopenharmony_ci	int ids[PIXCIR_MAX_SLOTS];
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
9462306a36Sopenharmony_ci			    struct pixcir_report_data *report)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
9762306a36Sopenharmony_ci	u8 wrbuf[1] = { 0 };
9862306a36Sopenharmony_ci	u8 *bufptr;
9962306a36Sopenharmony_ci	u8 touch;
10062306a36Sopenharmony_ci	int ret, i;
10162306a36Sopenharmony_ci	int readsize;
10262306a36Sopenharmony_ci	const struct pixcir_i2c_chip_data *chip = tsdata->chip;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	memset(report, 0, sizeof(struct pixcir_report_data));
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	i = chip->has_hw_ids ? 1 : 0;
10762306a36Sopenharmony_ci	readsize = 2 + tsdata->chip->max_fingers * (4 + i);
10862306a36Sopenharmony_ci	if (readsize > sizeof(rdbuf))
10962306a36Sopenharmony_ci		readsize = sizeof(rdbuf);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
11262306a36Sopenharmony_ci	if (ret != sizeof(wrbuf)) {
11362306a36Sopenharmony_ci		dev_err(&tsdata->client->dev,
11462306a36Sopenharmony_ci			"%s: i2c_master_send failed(), ret=%d\n",
11562306a36Sopenharmony_ci			__func__, ret);
11662306a36Sopenharmony_ci		return;
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
12062306a36Sopenharmony_ci	if (ret != readsize) {
12162306a36Sopenharmony_ci		dev_err(&tsdata->client->dev,
12262306a36Sopenharmony_ci			"%s: i2c_master_recv failed(), ret=%d\n",
12362306a36Sopenharmony_ci			__func__, ret);
12462306a36Sopenharmony_ci		return;
12562306a36Sopenharmony_ci	}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	touch = rdbuf[0] & 0x7;
12862306a36Sopenharmony_ci	if (touch > tsdata->chip->max_fingers)
12962306a36Sopenharmony_ci		touch = tsdata->chip->max_fingers;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	report->num_touches = touch;
13262306a36Sopenharmony_ci	bufptr = &rdbuf[2];
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	for (i = 0; i < touch; i++) {
13562306a36Sopenharmony_ci		touchscreen_set_mt_pos(&report->pos[i], &tsdata->prop,
13662306a36Sopenharmony_ci				       get_unaligned_le16(bufptr),
13762306a36Sopenharmony_ci				       get_unaligned_le16(bufptr + 2));
13862306a36Sopenharmony_ci		if (chip->has_hw_ids) {
13962306a36Sopenharmony_ci			report->ids[i] = bufptr[4];
14062306a36Sopenharmony_ci			bufptr = bufptr + 5;
14162306a36Sopenharmony_ci		} else {
14262306a36Sopenharmony_ci			bufptr = bufptr + 4;
14362306a36Sopenharmony_ci		}
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
14862306a36Sopenharmony_ci			     struct pixcir_report_data *report)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	int slots[PIXCIR_MAX_SLOTS];
15162306a36Sopenharmony_ci	int n, i, slot;
15262306a36Sopenharmony_ci	struct device *dev = &ts->client->dev;
15362306a36Sopenharmony_ci	const struct pixcir_i2c_chip_data *chip = ts->chip;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	n = report->num_touches;
15662306a36Sopenharmony_ci	if (n > PIXCIR_MAX_SLOTS)
15762306a36Sopenharmony_ci		n = PIXCIR_MAX_SLOTS;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	if (!ts->chip->has_hw_ids)
16062306a36Sopenharmony_ci		input_mt_assign_slots(ts->input, slots, report->pos, n, 0);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	for (i = 0; i < n; i++) {
16362306a36Sopenharmony_ci		if (chip->has_hw_ids) {
16462306a36Sopenharmony_ci			slot = input_mt_get_slot_by_key(ts->input,
16562306a36Sopenharmony_ci							report->ids[i]);
16662306a36Sopenharmony_ci			if (slot < 0) {
16762306a36Sopenharmony_ci				dev_dbg(dev, "no free slot for id 0x%x\n",
16862306a36Sopenharmony_ci					report->ids[i]);
16962306a36Sopenharmony_ci				continue;
17062306a36Sopenharmony_ci			}
17162306a36Sopenharmony_ci		} else {
17262306a36Sopenharmony_ci			slot = slots[i];
17362306a36Sopenharmony_ci		}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci		input_mt_slot(ts->input, slot);
17662306a36Sopenharmony_ci		input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci		input_report_abs(ts->input, ABS_MT_POSITION_X,
17962306a36Sopenharmony_ci				 report->pos[i].x);
18062306a36Sopenharmony_ci		input_report_abs(ts->input, ABS_MT_POSITION_Y,
18162306a36Sopenharmony_ci				 report->pos[i].y);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci		dev_dbg(dev, "%d: slot %d, x %d, y %d\n",
18462306a36Sopenharmony_ci			i, slot, report->pos[i].x, report->pos[i].y);
18562306a36Sopenharmony_ci	}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	input_mt_sync_frame(ts->input);
18862306a36Sopenharmony_ci	input_sync(ts->input);
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	struct pixcir_i2c_ts_data *tsdata = dev_id;
19462306a36Sopenharmony_ci	struct pixcir_report_data report;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	while (tsdata->running) {
19762306a36Sopenharmony_ci		/* parse packet */
19862306a36Sopenharmony_ci		pixcir_ts_parse(tsdata, &report);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci		/* report it */
20162306a36Sopenharmony_ci		pixcir_ts_report(tsdata, &report);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci		if (gpiod_get_value_cansleep(tsdata->gpio_attb)) {
20462306a36Sopenharmony_ci			if (report.num_touches) {
20562306a36Sopenharmony_ci				/*
20662306a36Sopenharmony_ci				 * Last report with no finger up?
20762306a36Sopenharmony_ci				 * Do it now then.
20862306a36Sopenharmony_ci				 */
20962306a36Sopenharmony_ci				input_mt_sync_frame(tsdata->input);
21062306a36Sopenharmony_ci				input_sync(tsdata->input);
21162306a36Sopenharmony_ci			}
21262306a36Sopenharmony_ci			break;
21362306a36Sopenharmony_ci		}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci		msleep(20);
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	return IRQ_HANDLED;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic void pixcir_reset(struct pixcir_i2c_ts_data *tsdata)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	if (!IS_ERR_OR_NULL(tsdata->gpio_reset)) {
22462306a36Sopenharmony_ci		gpiod_set_value_cansleep(tsdata->gpio_reset, 1);
22562306a36Sopenharmony_ci		ndelay(100);	/* datasheet section 1.2.3 says 80ns min. */
22662306a36Sopenharmony_ci		gpiod_set_value_cansleep(tsdata->gpio_reset, 0);
22762306a36Sopenharmony_ci		/* wait for controller ready. 100ms guess. */
22862306a36Sopenharmony_ci		msleep(100);
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
23362306a36Sopenharmony_ci				 enum pixcir_power_mode mode)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct device *dev = &ts->client->dev;
23662306a36Sopenharmony_ci	int ret;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	if (mode == PIXCIR_POWER_ACTIVE || mode == PIXCIR_POWER_IDLE) {
23962306a36Sopenharmony_ci		if (ts->gpio_wake)
24062306a36Sopenharmony_ci			gpiod_set_value_cansleep(ts->gpio_wake, 1);
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
24462306a36Sopenharmony_ci	if (ret < 0) {
24562306a36Sopenharmony_ci		dev_err(dev, "%s: can't read reg %d : %d\n",
24662306a36Sopenharmony_ci			__func__, PIXCIR_REG_POWER_MODE, ret);
24762306a36Sopenharmony_ci		return ret;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	ret &= ~PIXCIR_POWER_MODE_MASK;
25162306a36Sopenharmony_ci	ret |= mode;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Always AUTO_IDLE */
25462306a36Sopenharmony_ci	ret |= PIXCIR_POWER_ALLOW_IDLE;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
25762306a36Sopenharmony_ci	if (ret < 0) {
25862306a36Sopenharmony_ci		dev_err(dev, "%s: can't write reg %d : %d\n",
25962306a36Sopenharmony_ci			__func__, PIXCIR_REG_POWER_MODE, ret);
26062306a36Sopenharmony_ci		return ret;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	if (mode == PIXCIR_POWER_HALT) {
26462306a36Sopenharmony_ci		if (ts->gpio_wake)
26562306a36Sopenharmony_ci			gpiod_set_value_cansleep(ts->gpio_wake, 0);
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	return 0;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/*
27262306a36Sopenharmony_ci * Set the interrupt mode for the device i.e. ATTB line behaviour
27362306a36Sopenharmony_ci *
27462306a36Sopenharmony_ci * @polarity : 1 for active high, 0 for active low.
27562306a36Sopenharmony_ci */
27662306a36Sopenharmony_cistatic int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
27762306a36Sopenharmony_ci			       enum pixcir_int_mode mode, bool polarity)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	struct device *dev = &ts->client->dev;
28062306a36Sopenharmony_ci	int ret;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
28362306a36Sopenharmony_ci	if (ret < 0) {
28462306a36Sopenharmony_ci		dev_err(dev, "%s: can't read reg %d : %d\n",
28562306a36Sopenharmony_ci			__func__, PIXCIR_REG_INT_MODE, ret);
28662306a36Sopenharmony_ci		return ret;
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	ret &= ~PIXCIR_INT_MODE_MASK;
29062306a36Sopenharmony_ci	ret |= mode;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	if (polarity)
29362306a36Sopenharmony_ci		ret |= PIXCIR_INT_POL_HIGH;
29462306a36Sopenharmony_ci	else
29562306a36Sopenharmony_ci		ret &= ~PIXCIR_INT_POL_HIGH;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
29862306a36Sopenharmony_ci	if (ret < 0) {
29962306a36Sopenharmony_ci		dev_err(dev, "%s: can't write reg %d : %d\n",
30062306a36Sopenharmony_ci			__func__, PIXCIR_REG_INT_MODE, ret);
30162306a36Sopenharmony_ci		return ret;
30262306a36Sopenharmony_ci	}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	return 0;
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci/*
30862306a36Sopenharmony_ci * Enable/disable interrupt generation
30962306a36Sopenharmony_ci */
31062306a36Sopenharmony_cistatic int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	struct device *dev = &ts->client->dev;
31362306a36Sopenharmony_ci	int ret;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
31662306a36Sopenharmony_ci	if (ret < 0) {
31762306a36Sopenharmony_ci		dev_err(dev, "%s: can't read reg %d : %d\n",
31862306a36Sopenharmony_ci			__func__, PIXCIR_REG_INT_MODE, ret);
31962306a36Sopenharmony_ci		return ret;
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	if (enable)
32362306a36Sopenharmony_ci		ret |= PIXCIR_INT_ENABLE;
32462306a36Sopenharmony_ci	else
32562306a36Sopenharmony_ci		ret &= ~PIXCIR_INT_ENABLE;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
32862306a36Sopenharmony_ci	if (ret < 0) {
32962306a36Sopenharmony_ci		dev_err(dev, "%s: can't write reg %d : %d\n",
33062306a36Sopenharmony_ci			__func__, PIXCIR_REG_INT_MODE, ret);
33162306a36Sopenharmony_ci		return ret;
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	return 0;
33562306a36Sopenharmony_ci}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_cistatic int pixcir_start(struct pixcir_i2c_ts_data *ts)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	struct device *dev = &ts->client->dev;
34062306a36Sopenharmony_ci	int error;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	if (ts->gpio_enable) {
34362306a36Sopenharmony_ci		gpiod_set_value_cansleep(ts->gpio_enable, 1);
34462306a36Sopenharmony_ci		msleep(100);
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	/* LEVEL_TOUCH interrupt with active low polarity */
34862306a36Sopenharmony_ci	error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
34962306a36Sopenharmony_ci	if (error) {
35062306a36Sopenharmony_ci		dev_err(dev, "Failed to set interrupt mode: %d\n", error);
35162306a36Sopenharmony_ci		return error;
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	ts->running = true;
35562306a36Sopenharmony_ci	mb();	/* Update status before IRQ can fire */
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	/* enable interrupt generation */
35862306a36Sopenharmony_ci	error = pixcir_int_enable(ts, true);
35962306a36Sopenharmony_ci	if (error) {
36062306a36Sopenharmony_ci		dev_err(dev, "Failed to enable interrupt generation: %d\n",
36162306a36Sopenharmony_ci			error);
36262306a36Sopenharmony_ci		return error;
36362306a36Sopenharmony_ci	}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	return 0;
36662306a36Sopenharmony_ci}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_cistatic int pixcir_stop(struct pixcir_i2c_ts_data *ts)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	int error;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	/* Disable interrupt generation */
37362306a36Sopenharmony_ci	error = pixcir_int_enable(ts, false);
37462306a36Sopenharmony_ci	if (error) {
37562306a36Sopenharmony_ci		dev_err(&ts->client->dev,
37662306a36Sopenharmony_ci			"Failed to disable interrupt generation: %d\n",
37762306a36Sopenharmony_ci			error);
37862306a36Sopenharmony_ci		return error;
37962306a36Sopenharmony_ci	}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	/* Exit ISR if running, no more report parsing */
38262306a36Sopenharmony_ci	ts->running = false;
38362306a36Sopenharmony_ci	mb();	/* update status before we synchronize irq */
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	/* Wait till running ISR is complete */
38662306a36Sopenharmony_ci	synchronize_irq(ts->client->irq);
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	if (ts->gpio_enable)
38962306a36Sopenharmony_ci		gpiod_set_value_cansleep(ts->gpio_enable, 0);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	return 0;
39262306a36Sopenharmony_ci}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_cistatic int pixcir_input_open(struct input_dev *dev)
39562306a36Sopenharmony_ci{
39662306a36Sopenharmony_ci	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	return pixcir_start(ts);
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic void pixcir_input_close(struct input_dev *dev)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	pixcir_stop(ts);
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_cistatic int pixcir_i2c_ts_suspend(struct device *dev)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
41162306a36Sopenharmony_ci	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
41262306a36Sopenharmony_ci	struct input_dev *input = ts->input;
41362306a36Sopenharmony_ci	int ret = 0;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	mutex_lock(&input->mutex);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	if (device_may_wakeup(&client->dev)) {
41862306a36Sopenharmony_ci		if (!input_device_enabled(input)) {
41962306a36Sopenharmony_ci			ret = pixcir_start(ts);
42062306a36Sopenharmony_ci			if (ret) {
42162306a36Sopenharmony_ci				dev_err(dev, "Failed to start\n");
42262306a36Sopenharmony_ci				goto unlock;
42362306a36Sopenharmony_ci			}
42462306a36Sopenharmony_ci		}
42562306a36Sopenharmony_ci	} else if (input_device_enabled(input)) {
42662306a36Sopenharmony_ci		ret = pixcir_stop(ts);
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ciunlock:
43062306a36Sopenharmony_ci	mutex_unlock(&input->mutex);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	return ret;
43362306a36Sopenharmony_ci}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_cistatic int pixcir_i2c_ts_resume(struct device *dev)
43662306a36Sopenharmony_ci{
43762306a36Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
43862306a36Sopenharmony_ci	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
43962306a36Sopenharmony_ci	struct input_dev *input = ts->input;
44062306a36Sopenharmony_ci	int ret = 0;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	mutex_lock(&input->mutex);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	if (device_may_wakeup(&client->dev)) {
44562306a36Sopenharmony_ci		if (!input_device_enabled(input)) {
44662306a36Sopenharmony_ci			ret = pixcir_stop(ts);
44762306a36Sopenharmony_ci			if (ret) {
44862306a36Sopenharmony_ci				dev_err(dev, "Failed to stop\n");
44962306a36Sopenharmony_ci				goto unlock;
45062306a36Sopenharmony_ci			}
45162306a36Sopenharmony_ci		}
45262306a36Sopenharmony_ci	} else if (input_device_enabled(input)) {
45362306a36Sopenharmony_ci		ret = pixcir_start(ts);
45462306a36Sopenharmony_ci	}
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ciunlock:
45762306a36Sopenharmony_ci	mutex_unlock(&input->mutex);
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return ret;
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic DEFINE_SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
46362306a36Sopenharmony_ci				pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cistatic int pixcir_i2c_ts_probe(struct i2c_client *client)
46662306a36Sopenharmony_ci{
46762306a36Sopenharmony_ci	const struct i2c_device_id *id = i2c_client_get_device_id(client);
46862306a36Sopenharmony_ci	struct device *dev = &client->dev;
46962306a36Sopenharmony_ci	struct pixcir_i2c_ts_data *tsdata;
47062306a36Sopenharmony_ci	struct input_dev *input;
47162306a36Sopenharmony_ci	int error;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
47462306a36Sopenharmony_ci	if (!tsdata)
47562306a36Sopenharmony_ci		return -ENOMEM;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	tsdata->chip = device_get_match_data(dev);
47862306a36Sopenharmony_ci	if (!tsdata->chip && id)
47962306a36Sopenharmony_ci		tsdata->chip = (const void *)id->driver_data;
48062306a36Sopenharmony_ci	if (!tsdata->chip) {
48162306a36Sopenharmony_ci		dev_err(dev, "can't locate chip data\n");
48262306a36Sopenharmony_ci		return -EINVAL;
48362306a36Sopenharmony_ci	}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	input = devm_input_allocate_device(dev);
48662306a36Sopenharmony_ci	if (!input) {
48762306a36Sopenharmony_ci		dev_err(dev, "Failed to allocate input device\n");
48862306a36Sopenharmony_ci		return -ENOMEM;
48962306a36Sopenharmony_ci	}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	tsdata->client = client;
49262306a36Sopenharmony_ci	tsdata->input = input;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	input->name = client->name;
49562306a36Sopenharmony_ci	input->id.bustype = BUS_I2C;
49662306a36Sopenharmony_ci	input->open = pixcir_input_open;
49762306a36Sopenharmony_ci	input->close = pixcir_input_close;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
50062306a36Sopenharmony_ci	input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
50162306a36Sopenharmony_ci	touchscreen_parse_properties(input, true, &tsdata->prop);
50262306a36Sopenharmony_ci	if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
50362306a36Sopenharmony_ci	    !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
50462306a36Sopenharmony_ci		dev_err(dev, "Touchscreen size is not specified\n");
50562306a36Sopenharmony_ci		return -EINVAL;
50662306a36Sopenharmony_ci	}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	error = input_mt_init_slots(input, tsdata->chip->max_fingers,
50962306a36Sopenharmony_ci				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
51062306a36Sopenharmony_ci	if (error) {
51162306a36Sopenharmony_ci		dev_err(dev, "Error initializing Multi-Touch slots\n");
51262306a36Sopenharmony_ci		return error;
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	input_set_drvdata(input, tsdata);
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN);
51862306a36Sopenharmony_ci	if (IS_ERR(tsdata->gpio_attb))
51962306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(tsdata->gpio_attb),
52062306a36Sopenharmony_ci				     "Failed to request ATTB gpio\n");
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	tsdata->gpio_reset = devm_gpiod_get_optional(dev, "reset",
52362306a36Sopenharmony_ci						     GPIOD_OUT_LOW);
52462306a36Sopenharmony_ci	if (IS_ERR(tsdata->gpio_reset))
52562306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(tsdata->gpio_reset),
52662306a36Sopenharmony_ci				     "Failed to request RESET gpio\n");
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake",
52962306a36Sopenharmony_ci						    GPIOD_OUT_HIGH);
53062306a36Sopenharmony_ci	if (IS_ERR(tsdata->gpio_wake))
53162306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(tsdata->gpio_wake),
53262306a36Sopenharmony_ci				     "Failed to get wake gpio\n");
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable",
53562306a36Sopenharmony_ci						      GPIOD_OUT_HIGH);
53662306a36Sopenharmony_ci	if (IS_ERR(tsdata->gpio_enable))
53762306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(tsdata->gpio_enable),
53862306a36Sopenharmony_ci				     "Failed to get enable gpio\n");
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	if (tsdata->gpio_enable)
54162306a36Sopenharmony_ci		msleep(100);
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
54462306a36Sopenharmony_ci					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
54562306a36Sopenharmony_ci					  client->name, tsdata);
54662306a36Sopenharmony_ci	if (error) {
54762306a36Sopenharmony_ci		dev_err(dev, "failed to request irq %d\n", client->irq);
54862306a36Sopenharmony_ci		return error;
54962306a36Sopenharmony_ci	}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	pixcir_reset(tsdata);
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	/* Always be in IDLE mode to save power, device supports auto wake */
55462306a36Sopenharmony_ci	error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
55562306a36Sopenharmony_ci	if (error) {
55662306a36Sopenharmony_ci		dev_err(dev, "Failed to set IDLE mode\n");
55762306a36Sopenharmony_ci		return error;
55862306a36Sopenharmony_ci	}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	/* Stop device till opened */
56162306a36Sopenharmony_ci	error = pixcir_stop(tsdata);
56262306a36Sopenharmony_ci	if (error)
56362306a36Sopenharmony_ci		return error;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	error = input_register_device(input);
56662306a36Sopenharmony_ci	if (error)
56762306a36Sopenharmony_ci		return error;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	i2c_set_clientdata(client, tsdata);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	return 0;
57262306a36Sopenharmony_ci}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_cistatic const struct pixcir_i2c_chip_data pixcir_ts_data = {
57562306a36Sopenharmony_ci	.max_fingers = 2,
57662306a36Sopenharmony_ci	/* no hw id support */
57762306a36Sopenharmony_ci};
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_cistatic const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
58062306a36Sopenharmony_ci	.max_fingers = 5,
58162306a36Sopenharmony_ci	.has_hw_ids = true,
58262306a36Sopenharmony_ci};
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_cistatic const struct i2c_device_id pixcir_i2c_ts_id[] = {
58562306a36Sopenharmony_ci	{ "pixcir_ts", (unsigned long) &pixcir_ts_data },
58662306a36Sopenharmony_ci	{ "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
58762306a36Sopenharmony_ci	{ }
58862306a36Sopenharmony_ci};
58962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci#ifdef CONFIG_OF
59262306a36Sopenharmony_cistatic const struct of_device_id pixcir_of_match[] = {
59362306a36Sopenharmony_ci	{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
59462306a36Sopenharmony_ci	{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
59562306a36Sopenharmony_ci	{ }
59662306a36Sopenharmony_ci};
59762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, pixcir_of_match);
59862306a36Sopenharmony_ci#endif
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_cistatic struct i2c_driver pixcir_i2c_ts_driver = {
60162306a36Sopenharmony_ci	.driver = {
60262306a36Sopenharmony_ci		.name	= "pixcir_ts",
60362306a36Sopenharmony_ci		.pm	= pm_sleep_ptr(&pixcir_dev_pm_ops),
60462306a36Sopenharmony_ci		.of_match_table = of_match_ptr(pixcir_of_match),
60562306a36Sopenharmony_ci	},
60662306a36Sopenharmony_ci	.probe		= pixcir_i2c_ts_probe,
60762306a36Sopenharmony_ci	.id_table	= pixcir_i2c_ts_id,
60862306a36Sopenharmony_ci};
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_cimodule_i2c_driver(pixcir_i2c_ts_driver);
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ciMODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>");
61362306a36Sopenharmony_ciMODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver");
61462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
615