18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for Pixcir I2C touchscreen controllers.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Pixcir, Inc.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
98c2ecf20Sopenharmony_ci#include <linux/delay.h>
108c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
118c2ecf20Sopenharmony_ci#include <linux/i2c.h>
128c2ecf20Sopenharmony_ci#include <linux/input.h>
138c2ecf20Sopenharmony_ci#include <linux/input/mt.h>
148c2ecf20Sopenharmony_ci#include <linux/input/touchscreen.h>
158c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
168c2ecf20Sopenharmony_ci#include <linux/of_device.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/*
238c2ecf20Sopenharmony_ci * Register map
248c2ecf20Sopenharmony_ci */
258c2ecf20Sopenharmony_ci#define PIXCIR_REG_POWER_MODE	51
268c2ecf20Sopenharmony_ci#define PIXCIR_REG_INT_MODE	52
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/*
298c2ecf20Sopenharmony_ci * Power modes:
308c2ecf20Sopenharmony_ci * active: max scan speed
318c2ecf20Sopenharmony_ci * idle: lower scan speed with automatic transition to active on touch
328c2ecf20Sopenharmony_ci * halt: datasheet says sleep but this is more like halt as the chip
338c2ecf20Sopenharmony_ci *       clocks are cut and it can only be brought out of this mode
348c2ecf20Sopenharmony_ci *	 using the RESET pin.
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_cienum pixcir_power_mode {
378c2ecf20Sopenharmony_ci	PIXCIR_POWER_ACTIVE,
388c2ecf20Sopenharmony_ci	PIXCIR_POWER_IDLE,
398c2ecf20Sopenharmony_ci	PIXCIR_POWER_HALT,
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#define PIXCIR_POWER_MODE_MASK	0x03
438c2ecf20Sopenharmony_ci#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/*
468c2ecf20Sopenharmony_ci * Interrupt modes:
478c2ecf20Sopenharmony_ci * periodical: interrupt is asserted periodicaly
488c2ecf20Sopenharmony_ci * diff coordinates: interrupt is asserted when coordinates change
498c2ecf20Sopenharmony_ci * level on touch: interrupt level asserted during touch
508c2ecf20Sopenharmony_ci * pulse on touch: interrupt pulse asserted during touch
518c2ecf20Sopenharmony_ci *
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_cienum pixcir_int_mode {
548c2ecf20Sopenharmony_ci	PIXCIR_INT_PERIODICAL,
558c2ecf20Sopenharmony_ci	PIXCIR_INT_DIFF_COORD,
568c2ecf20Sopenharmony_ci	PIXCIR_INT_LEVEL_TOUCH,
578c2ecf20Sopenharmony_ci	PIXCIR_INT_PULSE_TOUCH,
588c2ecf20Sopenharmony_ci};
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#define PIXCIR_INT_MODE_MASK	0x03
618c2ecf20Sopenharmony_ci#define PIXCIR_INT_ENABLE	(1UL << 3)
628c2ecf20Sopenharmony_ci#define PIXCIR_INT_POL_HIGH	(1UL << 2)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/**
658c2ecf20Sopenharmony_ci * struct pixcir_i2c_chip_data - chip related data
668c2ecf20Sopenharmony_ci * @max_fingers:	Max number of fingers reported simultaneously by h/w
678c2ecf20Sopenharmony_ci * @has_hw_ids:		Hardware supports finger tracking IDs
688c2ecf20Sopenharmony_ci *
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_cistruct pixcir_i2c_chip_data {
718c2ecf20Sopenharmony_ci	u8 max_fingers;
728c2ecf20Sopenharmony_ci	bool has_hw_ids;
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistruct pixcir_i2c_ts_data {
768c2ecf20Sopenharmony_ci	struct i2c_client *client;
778c2ecf20Sopenharmony_ci	struct input_dev *input;
788c2ecf20Sopenharmony_ci	struct gpio_desc *gpio_attb;
798c2ecf20Sopenharmony_ci	struct gpio_desc *gpio_reset;
808c2ecf20Sopenharmony_ci	struct gpio_desc *gpio_enable;
818c2ecf20Sopenharmony_ci	struct gpio_desc *gpio_wake;
828c2ecf20Sopenharmony_ci	const struct pixcir_i2c_chip_data *chip;
838c2ecf20Sopenharmony_ci	struct touchscreen_properties prop;
848c2ecf20Sopenharmony_ci	bool running;
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistruct pixcir_report_data {
888c2ecf20Sopenharmony_ci	int num_touches;
898c2ecf20Sopenharmony_ci	struct input_mt_pos pos[PIXCIR_MAX_SLOTS];
908c2ecf20Sopenharmony_ci	int ids[PIXCIR_MAX_SLOTS];
918c2ecf20Sopenharmony_ci};
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
948c2ecf20Sopenharmony_ci			    struct pixcir_report_data *report)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
978c2ecf20Sopenharmony_ci	u8 wrbuf[1] = { 0 };
988c2ecf20Sopenharmony_ci	u8 *bufptr;
998c2ecf20Sopenharmony_ci	u8 touch;
1008c2ecf20Sopenharmony_ci	int ret, i;
1018c2ecf20Sopenharmony_ci	int readsize;
1028c2ecf20Sopenharmony_ci	const struct pixcir_i2c_chip_data *chip = tsdata->chip;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	memset(report, 0, sizeof(struct pixcir_report_data));
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	i = chip->has_hw_ids ? 1 : 0;
1078c2ecf20Sopenharmony_ci	readsize = 2 + tsdata->chip->max_fingers * (4 + i);
1088c2ecf20Sopenharmony_ci	if (readsize > sizeof(rdbuf))
1098c2ecf20Sopenharmony_ci		readsize = sizeof(rdbuf);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
1128c2ecf20Sopenharmony_ci	if (ret != sizeof(wrbuf)) {
1138c2ecf20Sopenharmony_ci		dev_err(&tsdata->client->dev,
1148c2ecf20Sopenharmony_ci			"%s: i2c_master_send failed(), ret=%d\n",
1158c2ecf20Sopenharmony_ci			__func__, ret);
1168c2ecf20Sopenharmony_ci		return;
1178c2ecf20Sopenharmony_ci	}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
1208c2ecf20Sopenharmony_ci	if (ret != readsize) {
1218c2ecf20Sopenharmony_ci		dev_err(&tsdata->client->dev,
1228c2ecf20Sopenharmony_ci			"%s: i2c_master_recv failed(), ret=%d\n",
1238c2ecf20Sopenharmony_ci			__func__, ret);
1248c2ecf20Sopenharmony_ci		return;
1258c2ecf20Sopenharmony_ci	}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	touch = rdbuf[0] & 0x7;
1288c2ecf20Sopenharmony_ci	if (touch > tsdata->chip->max_fingers)
1298c2ecf20Sopenharmony_ci		touch = tsdata->chip->max_fingers;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	report->num_touches = touch;
1328c2ecf20Sopenharmony_ci	bufptr = &rdbuf[2];
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	for (i = 0; i < touch; i++) {
1358c2ecf20Sopenharmony_ci		touchscreen_set_mt_pos(&report->pos[i], &tsdata->prop,
1368c2ecf20Sopenharmony_ci				       get_unaligned_le16(bufptr),
1378c2ecf20Sopenharmony_ci				       get_unaligned_le16(bufptr + 2));
1388c2ecf20Sopenharmony_ci		if (chip->has_hw_ids) {
1398c2ecf20Sopenharmony_ci			report->ids[i] = bufptr[4];
1408c2ecf20Sopenharmony_ci			bufptr = bufptr + 5;
1418c2ecf20Sopenharmony_ci		} else {
1428c2ecf20Sopenharmony_ci			bufptr = bufptr + 4;
1438c2ecf20Sopenharmony_ci		}
1448c2ecf20Sopenharmony_ci	}
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
1488c2ecf20Sopenharmony_ci			     struct pixcir_report_data *report)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	int slots[PIXCIR_MAX_SLOTS];
1518c2ecf20Sopenharmony_ci	int n, i, slot;
1528c2ecf20Sopenharmony_ci	struct device *dev = &ts->client->dev;
1538c2ecf20Sopenharmony_ci	const struct pixcir_i2c_chip_data *chip = ts->chip;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	n = report->num_touches;
1568c2ecf20Sopenharmony_ci	if (n > PIXCIR_MAX_SLOTS)
1578c2ecf20Sopenharmony_ci		n = PIXCIR_MAX_SLOTS;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	if (!ts->chip->has_hw_ids)
1608c2ecf20Sopenharmony_ci		input_mt_assign_slots(ts->input, slots, report->pos, n, 0);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	for (i = 0; i < n; i++) {
1638c2ecf20Sopenharmony_ci		if (chip->has_hw_ids) {
1648c2ecf20Sopenharmony_ci			slot = input_mt_get_slot_by_key(ts->input,
1658c2ecf20Sopenharmony_ci							report->ids[i]);
1668c2ecf20Sopenharmony_ci			if (slot < 0) {
1678c2ecf20Sopenharmony_ci				dev_dbg(dev, "no free slot for id 0x%x\n",
1688c2ecf20Sopenharmony_ci					report->ids[i]);
1698c2ecf20Sopenharmony_ci				continue;
1708c2ecf20Sopenharmony_ci			}
1718c2ecf20Sopenharmony_ci		} else {
1728c2ecf20Sopenharmony_ci			slot = slots[i];
1738c2ecf20Sopenharmony_ci		}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		input_mt_slot(ts->input, slot);
1768c2ecf20Sopenharmony_ci		input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci		input_report_abs(ts->input, ABS_MT_POSITION_X,
1798c2ecf20Sopenharmony_ci				 report->pos[i].x);
1808c2ecf20Sopenharmony_ci		input_report_abs(ts->input, ABS_MT_POSITION_Y,
1818c2ecf20Sopenharmony_ci				 report->pos[i].y);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci		dev_dbg(dev, "%d: slot %d, x %d, y %d\n",
1848c2ecf20Sopenharmony_ci			i, slot, report->pos[i].x, report->pos[i].y);
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	input_mt_sync_frame(ts->input);
1888c2ecf20Sopenharmony_ci	input_sync(ts->input);
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	struct pixcir_i2c_ts_data *tsdata = dev_id;
1948c2ecf20Sopenharmony_ci	struct pixcir_report_data report;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	while (tsdata->running) {
1978c2ecf20Sopenharmony_ci		/* parse packet */
1988c2ecf20Sopenharmony_ci		pixcir_ts_parse(tsdata, &report);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci		/* report it */
2018c2ecf20Sopenharmony_ci		pixcir_ts_report(tsdata, &report);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci		if (gpiod_get_value_cansleep(tsdata->gpio_attb)) {
2048c2ecf20Sopenharmony_ci			if (report.num_touches) {
2058c2ecf20Sopenharmony_ci				/*
2068c2ecf20Sopenharmony_ci				 * Last report with no finger up?
2078c2ecf20Sopenharmony_ci				 * Do it now then.
2088c2ecf20Sopenharmony_ci				 */
2098c2ecf20Sopenharmony_ci				input_mt_sync_frame(tsdata->input);
2108c2ecf20Sopenharmony_ci				input_sync(tsdata->input);
2118c2ecf20Sopenharmony_ci			}
2128c2ecf20Sopenharmony_ci			break;
2138c2ecf20Sopenharmony_ci		}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci		msleep(20);
2168c2ecf20Sopenharmony_ci	}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic void pixcir_reset(struct pixcir_i2c_ts_data *tsdata)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	if (!IS_ERR_OR_NULL(tsdata->gpio_reset)) {
2248c2ecf20Sopenharmony_ci		gpiod_set_value_cansleep(tsdata->gpio_reset, 1);
2258c2ecf20Sopenharmony_ci		ndelay(100);	/* datasheet section 1.2.3 says 80ns min. */
2268c2ecf20Sopenharmony_ci		gpiod_set_value_cansleep(tsdata->gpio_reset, 0);
2278c2ecf20Sopenharmony_ci		/* wait for controller ready. 100ms guess. */
2288c2ecf20Sopenharmony_ci		msleep(100);
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
2338c2ecf20Sopenharmony_ci				 enum pixcir_power_mode mode)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	struct device *dev = &ts->client->dev;
2368c2ecf20Sopenharmony_ci	int ret;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	if (mode == PIXCIR_POWER_ACTIVE || mode == PIXCIR_POWER_IDLE) {
2398c2ecf20Sopenharmony_ci		if (ts->gpio_wake)
2408c2ecf20Sopenharmony_ci			gpiod_set_value_cansleep(ts->gpio_wake, 1);
2418c2ecf20Sopenharmony_ci	}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
2448c2ecf20Sopenharmony_ci	if (ret < 0) {
2458c2ecf20Sopenharmony_ci		dev_err(dev, "%s: can't read reg %d : %d\n",
2468c2ecf20Sopenharmony_ci			__func__, PIXCIR_REG_POWER_MODE, ret);
2478c2ecf20Sopenharmony_ci		return ret;
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	ret &= ~PIXCIR_POWER_MODE_MASK;
2518c2ecf20Sopenharmony_ci	ret |= mode;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	/* Always AUTO_IDLE */
2548c2ecf20Sopenharmony_ci	ret |= PIXCIR_POWER_ALLOW_IDLE;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
2578c2ecf20Sopenharmony_ci	if (ret < 0) {
2588c2ecf20Sopenharmony_ci		dev_err(dev, "%s: can't write reg %d : %d\n",
2598c2ecf20Sopenharmony_ci			__func__, PIXCIR_REG_POWER_MODE, ret);
2608c2ecf20Sopenharmony_ci		return ret;
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	if (mode == PIXCIR_POWER_HALT) {
2648c2ecf20Sopenharmony_ci		if (ts->gpio_wake)
2658c2ecf20Sopenharmony_ci			gpiod_set_value_cansleep(ts->gpio_wake, 0);
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	return 0;
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci/*
2728c2ecf20Sopenharmony_ci * Set the interrupt mode for the device i.e. ATTB line behaviour
2738c2ecf20Sopenharmony_ci *
2748c2ecf20Sopenharmony_ci * @polarity : 1 for active high, 0 for active low.
2758c2ecf20Sopenharmony_ci */
2768c2ecf20Sopenharmony_cistatic int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
2778c2ecf20Sopenharmony_ci			       enum pixcir_int_mode mode, bool polarity)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	struct device *dev = &ts->client->dev;
2808c2ecf20Sopenharmony_ci	int ret;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
2838c2ecf20Sopenharmony_ci	if (ret < 0) {
2848c2ecf20Sopenharmony_ci		dev_err(dev, "%s: can't read reg %d : %d\n",
2858c2ecf20Sopenharmony_ci			__func__, PIXCIR_REG_INT_MODE, ret);
2868c2ecf20Sopenharmony_ci		return ret;
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	ret &= ~PIXCIR_INT_MODE_MASK;
2908c2ecf20Sopenharmony_ci	ret |= mode;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (polarity)
2938c2ecf20Sopenharmony_ci		ret |= PIXCIR_INT_POL_HIGH;
2948c2ecf20Sopenharmony_ci	else
2958c2ecf20Sopenharmony_ci		ret &= ~PIXCIR_INT_POL_HIGH;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
2988c2ecf20Sopenharmony_ci	if (ret < 0) {
2998c2ecf20Sopenharmony_ci		dev_err(dev, "%s: can't write reg %d : %d\n",
3008c2ecf20Sopenharmony_ci			__func__, PIXCIR_REG_INT_MODE, ret);
3018c2ecf20Sopenharmony_ci		return ret;
3028c2ecf20Sopenharmony_ci	}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	return 0;
3058c2ecf20Sopenharmony_ci}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci/*
3088c2ecf20Sopenharmony_ci * Enable/disable interrupt generation
3098c2ecf20Sopenharmony_ci */
3108c2ecf20Sopenharmony_cistatic int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
3118c2ecf20Sopenharmony_ci{
3128c2ecf20Sopenharmony_ci	struct device *dev = &ts->client->dev;
3138c2ecf20Sopenharmony_ci	int ret;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
3168c2ecf20Sopenharmony_ci	if (ret < 0) {
3178c2ecf20Sopenharmony_ci		dev_err(dev, "%s: can't read reg %d : %d\n",
3188c2ecf20Sopenharmony_ci			__func__, PIXCIR_REG_INT_MODE, ret);
3198c2ecf20Sopenharmony_ci		return ret;
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if (enable)
3238c2ecf20Sopenharmony_ci		ret |= PIXCIR_INT_ENABLE;
3248c2ecf20Sopenharmony_ci	else
3258c2ecf20Sopenharmony_ci		ret &= ~PIXCIR_INT_ENABLE;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
3288c2ecf20Sopenharmony_ci	if (ret < 0) {
3298c2ecf20Sopenharmony_ci		dev_err(dev, "%s: can't write reg %d : %d\n",
3308c2ecf20Sopenharmony_ci			__func__, PIXCIR_REG_INT_MODE, ret);
3318c2ecf20Sopenharmony_ci		return ret;
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	return 0;
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic int pixcir_start(struct pixcir_i2c_ts_data *ts)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci	struct device *dev = &ts->client->dev;
3408c2ecf20Sopenharmony_ci	int error;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (ts->gpio_enable) {
3438c2ecf20Sopenharmony_ci		gpiod_set_value_cansleep(ts->gpio_enable, 1);
3448c2ecf20Sopenharmony_ci		msleep(100);
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	/* LEVEL_TOUCH interrupt with active low polarity */
3488c2ecf20Sopenharmony_ci	error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
3498c2ecf20Sopenharmony_ci	if (error) {
3508c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to set interrupt mode: %d\n", error);
3518c2ecf20Sopenharmony_ci		return error;
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	ts->running = true;
3558c2ecf20Sopenharmony_ci	mb();	/* Update status before IRQ can fire */
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	/* enable interrupt generation */
3588c2ecf20Sopenharmony_ci	error = pixcir_int_enable(ts, true);
3598c2ecf20Sopenharmony_ci	if (error) {
3608c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to enable interrupt generation: %d\n",
3618c2ecf20Sopenharmony_ci			error);
3628c2ecf20Sopenharmony_ci		return error;
3638c2ecf20Sopenharmony_ci	}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	return 0;
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cistatic int pixcir_stop(struct pixcir_i2c_ts_data *ts)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	int error;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	/* Disable interrupt generation */
3738c2ecf20Sopenharmony_ci	error = pixcir_int_enable(ts, false);
3748c2ecf20Sopenharmony_ci	if (error) {
3758c2ecf20Sopenharmony_ci		dev_err(&ts->client->dev,
3768c2ecf20Sopenharmony_ci			"Failed to disable interrupt generation: %d\n",
3778c2ecf20Sopenharmony_ci			error);
3788c2ecf20Sopenharmony_ci		return error;
3798c2ecf20Sopenharmony_ci	}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	/* Exit ISR if running, no more report parsing */
3828c2ecf20Sopenharmony_ci	ts->running = false;
3838c2ecf20Sopenharmony_ci	mb();	/* update status before we synchronize irq */
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	/* Wait till running ISR is complete */
3868c2ecf20Sopenharmony_ci	synchronize_irq(ts->client->irq);
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	if (ts->gpio_enable)
3898c2ecf20Sopenharmony_ci		gpiod_set_value_cansleep(ts->gpio_enable, 0);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	return 0;
3928c2ecf20Sopenharmony_ci}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_cistatic int pixcir_input_open(struct input_dev *dev)
3958c2ecf20Sopenharmony_ci{
3968c2ecf20Sopenharmony_ci	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	return pixcir_start(ts);
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic void pixcir_input_close(struct input_dev *dev)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	pixcir_stop(ts);
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
4118c2ecf20Sopenharmony_ci	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
4128c2ecf20Sopenharmony_ci	struct input_dev *input = ts->input;
4138c2ecf20Sopenharmony_ci	int ret = 0;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	mutex_lock(&input->mutex);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	if (device_may_wakeup(&client->dev)) {
4188c2ecf20Sopenharmony_ci		if (!input->users) {
4198c2ecf20Sopenharmony_ci			ret = pixcir_start(ts);
4208c2ecf20Sopenharmony_ci			if (ret) {
4218c2ecf20Sopenharmony_ci				dev_err(dev, "Failed to start\n");
4228c2ecf20Sopenharmony_ci				goto unlock;
4238c2ecf20Sopenharmony_ci			}
4248c2ecf20Sopenharmony_ci		}
4258c2ecf20Sopenharmony_ci	} else if (input->users) {
4268c2ecf20Sopenharmony_ci		ret = pixcir_stop(ts);
4278c2ecf20Sopenharmony_ci	}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ciunlock:
4308c2ecf20Sopenharmony_ci	mutex_unlock(&input->mutex);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	return ret;
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_cistatic int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
4388c2ecf20Sopenharmony_ci	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
4398c2ecf20Sopenharmony_ci	struct input_dev *input = ts->input;
4408c2ecf20Sopenharmony_ci	int ret = 0;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	mutex_lock(&input->mutex);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	if (device_may_wakeup(&client->dev)) {
4458c2ecf20Sopenharmony_ci		if (!input->users) {
4468c2ecf20Sopenharmony_ci			ret = pixcir_stop(ts);
4478c2ecf20Sopenharmony_ci			if (ret) {
4488c2ecf20Sopenharmony_ci				dev_err(dev, "Failed to stop\n");
4498c2ecf20Sopenharmony_ci				goto unlock;
4508c2ecf20Sopenharmony_ci			}
4518c2ecf20Sopenharmony_ci		}
4528c2ecf20Sopenharmony_ci	} else if (input->users) {
4538c2ecf20Sopenharmony_ci		ret = pixcir_start(ts);
4548c2ecf20Sopenharmony_ci	}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ciunlock:
4578c2ecf20Sopenharmony_ci	mutex_unlock(&input->mutex);
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	return ret;
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
4638c2ecf20Sopenharmony_ci			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_cistatic int pixcir_i2c_ts_probe(struct i2c_client *client,
4668c2ecf20Sopenharmony_ci			       const struct i2c_device_id *id)
4678c2ecf20Sopenharmony_ci{
4688c2ecf20Sopenharmony_ci	struct device *dev = &client->dev;
4698c2ecf20Sopenharmony_ci	struct pixcir_i2c_ts_data *tsdata;
4708c2ecf20Sopenharmony_ci	struct input_dev *input;
4718c2ecf20Sopenharmony_ci	int error;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
4748c2ecf20Sopenharmony_ci	if (!tsdata)
4758c2ecf20Sopenharmony_ci		return -ENOMEM;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	tsdata->chip = device_get_match_data(dev);
4788c2ecf20Sopenharmony_ci	if (!tsdata->chip && id)
4798c2ecf20Sopenharmony_ci		tsdata->chip = (const void *)id->driver_data;
4808c2ecf20Sopenharmony_ci	if (!tsdata->chip) {
4818c2ecf20Sopenharmony_ci		dev_err(dev, "can't locate chip data\n");
4828c2ecf20Sopenharmony_ci		return -EINVAL;
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	input = devm_input_allocate_device(dev);
4868c2ecf20Sopenharmony_ci	if (!input) {
4878c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to allocate input device\n");
4888c2ecf20Sopenharmony_ci		return -ENOMEM;
4898c2ecf20Sopenharmony_ci	}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	tsdata->client = client;
4928c2ecf20Sopenharmony_ci	tsdata->input = input;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	input->name = client->name;
4958c2ecf20Sopenharmony_ci	input->id.bustype = BUS_I2C;
4968c2ecf20Sopenharmony_ci	input->open = pixcir_input_open;
4978c2ecf20Sopenharmony_ci	input->close = pixcir_input_close;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
5008c2ecf20Sopenharmony_ci	input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
5018c2ecf20Sopenharmony_ci	touchscreen_parse_properties(input, true, &tsdata->prop);
5028c2ecf20Sopenharmony_ci	if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
5038c2ecf20Sopenharmony_ci	    !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
5048c2ecf20Sopenharmony_ci		dev_err(dev, "Touchscreen size is not specified\n");
5058c2ecf20Sopenharmony_ci		return -EINVAL;
5068c2ecf20Sopenharmony_ci	}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	error = input_mt_init_slots(input, tsdata->chip->max_fingers,
5098c2ecf20Sopenharmony_ci				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
5108c2ecf20Sopenharmony_ci	if (error) {
5118c2ecf20Sopenharmony_ci		dev_err(dev, "Error initializing Multi-Touch slots\n");
5128c2ecf20Sopenharmony_ci		return error;
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	input_set_drvdata(input, tsdata);
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN);
5188c2ecf20Sopenharmony_ci	if (IS_ERR(tsdata->gpio_attb)) {
5198c2ecf20Sopenharmony_ci		error = PTR_ERR(tsdata->gpio_attb);
5208c2ecf20Sopenharmony_ci		if (error != -EPROBE_DEFER)
5218c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to request ATTB gpio: %d\n",
5228c2ecf20Sopenharmony_ci				error);
5238c2ecf20Sopenharmony_ci		return error;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	tsdata->gpio_reset = devm_gpiod_get_optional(dev, "reset",
5278c2ecf20Sopenharmony_ci						     GPIOD_OUT_LOW);
5288c2ecf20Sopenharmony_ci	if (IS_ERR(tsdata->gpio_reset)) {
5298c2ecf20Sopenharmony_ci		error = PTR_ERR(tsdata->gpio_reset);
5308c2ecf20Sopenharmony_ci		if (error != -EPROBE_DEFER)
5318c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to request RESET gpio: %d\n",
5328c2ecf20Sopenharmony_ci				error);
5338c2ecf20Sopenharmony_ci		return error;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake",
5378c2ecf20Sopenharmony_ci						    GPIOD_OUT_HIGH);
5388c2ecf20Sopenharmony_ci	if (IS_ERR(tsdata->gpio_wake)) {
5398c2ecf20Sopenharmony_ci		error = PTR_ERR(tsdata->gpio_wake);
5408c2ecf20Sopenharmony_ci		if (error != -EPROBE_DEFER)
5418c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to get wake gpio: %d\n", error);
5428c2ecf20Sopenharmony_ci		return error;
5438c2ecf20Sopenharmony_ci	}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable",
5468c2ecf20Sopenharmony_ci						      GPIOD_OUT_HIGH);
5478c2ecf20Sopenharmony_ci	if (IS_ERR(tsdata->gpio_enable)) {
5488c2ecf20Sopenharmony_ci		error = PTR_ERR(tsdata->gpio_enable);
5498c2ecf20Sopenharmony_ci		if (error != -EPROBE_DEFER)
5508c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to get enable gpio: %d\n", error);
5518c2ecf20Sopenharmony_ci		return error;
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	if (tsdata->gpio_enable)
5558c2ecf20Sopenharmony_ci		msleep(100);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
5588c2ecf20Sopenharmony_ci					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
5598c2ecf20Sopenharmony_ci					  client->name, tsdata);
5608c2ecf20Sopenharmony_ci	if (error) {
5618c2ecf20Sopenharmony_ci		dev_err(dev, "failed to request irq %d\n", client->irq);
5628c2ecf20Sopenharmony_ci		return error;
5638c2ecf20Sopenharmony_ci	}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	pixcir_reset(tsdata);
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	/* Always be in IDLE mode to save power, device supports auto wake */
5688c2ecf20Sopenharmony_ci	error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
5698c2ecf20Sopenharmony_ci	if (error) {
5708c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to set IDLE mode\n");
5718c2ecf20Sopenharmony_ci		return error;
5728c2ecf20Sopenharmony_ci	}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	/* Stop device till opened */
5758c2ecf20Sopenharmony_ci	error = pixcir_stop(tsdata);
5768c2ecf20Sopenharmony_ci	if (error)
5778c2ecf20Sopenharmony_ci		return error;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	error = input_register_device(input);
5808c2ecf20Sopenharmony_ci	if (error)
5818c2ecf20Sopenharmony_ci		return error;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, tsdata);
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	return 0;
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_cistatic const struct pixcir_i2c_chip_data pixcir_ts_data = {
5898c2ecf20Sopenharmony_ci	.max_fingers = 2,
5908c2ecf20Sopenharmony_ci	/* no hw id support */
5918c2ecf20Sopenharmony_ci};
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_cistatic const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
5948c2ecf20Sopenharmony_ci	.max_fingers = 5,
5958c2ecf20Sopenharmony_ci	.has_hw_ids = true,
5968c2ecf20Sopenharmony_ci};
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic const struct i2c_device_id pixcir_i2c_ts_id[] = {
5998c2ecf20Sopenharmony_ci	{ "pixcir_ts", (unsigned long) &pixcir_ts_data },
6008c2ecf20Sopenharmony_ci	{ "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
6018c2ecf20Sopenharmony_ci	{ }
6028c2ecf20Sopenharmony_ci};
6038c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
6068c2ecf20Sopenharmony_cistatic const struct of_device_id pixcir_of_match[] = {
6078c2ecf20Sopenharmony_ci	{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
6088c2ecf20Sopenharmony_ci	{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
6098c2ecf20Sopenharmony_ci	{ }
6108c2ecf20Sopenharmony_ci};
6118c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, pixcir_of_match);
6128c2ecf20Sopenharmony_ci#endif
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cistatic struct i2c_driver pixcir_i2c_ts_driver = {
6158c2ecf20Sopenharmony_ci	.driver = {
6168c2ecf20Sopenharmony_ci		.name	= "pixcir_ts",
6178c2ecf20Sopenharmony_ci		.pm	= &pixcir_dev_pm_ops,
6188c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(pixcir_of_match),
6198c2ecf20Sopenharmony_ci	},
6208c2ecf20Sopenharmony_ci	.probe		= pixcir_i2c_ts_probe,
6218c2ecf20Sopenharmony_ci	.id_table	= pixcir_i2c_ts_id,
6228c2ecf20Sopenharmony_ci};
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_cimodule_i2c_driver(pixcir_i2c_ts_driver);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>");
6278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver");
6288c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
629