xref: /linux/drivers/input/touchscreen/sis_i2c.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Touch Screen driver for SiS 9200 family I2C Touch panels
4  *
5  * Copyright (C) 2015 SiS, Inc.
6  * Copyright (C) 2016 Nextfour Group
7  */
8 
9 #include <linux/crc-itu-t.h>
10 #include <linux/delay.h>
11 #include <linux/i2c.h>
12 #include <linux/input.h>
13 #include <linux/input/mt.h>
14 #include <linux/interrupt.h>
15 #include <linux/gpio/consumer.h>
16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/unaligned.h>
19 
20 #define SIS_I2C_NAME		"sis_i2c_ts"
21 
22 /*
23  * The I2C packet format:
24  * le16		byte count
25  * u8		Report ID
26  * <contact data - variable length>
27  * u8		Number of contacts
28  * le16		Scan Time (optional)
29  * le16		CRC
30  *
31  * One touch point information consists of 6+ bytes, the order is:
32  * u8		contact state
33  * u8		finger id
34  * le16		x axis
35  * le16		y axis
36  * u8		contact width (optional)
37  * u8		contact height (optional)
38  * u8		pressure (optional)
39  *
40  * Maximum amount of data transmitted in one shot is 64 bytes, if controller
41  * needs to report more contacts than fit in one packet it will send true
42  * number of contacts in first packet and 0 as number of contacts in second
43  * packet.
44  */
45 
46 #define SIS_MAX_PACKET_SIZE		64
47 
48 #define SIS_PKT_LEN_OFFSET		0
49 #define SIS_PKT_REPORT_OFFSET		2 /* Report ID/type */
50 #define SIS_PKT_CONTACT_OFFSET		3 /* First contact */
51 
52 #define SIS_SCAN_TIME_LEN		2
53 
54 /* Supported report types */
55 #define SIS_ALL_IN_ONE_PACKAGE		0x10
56 #define SIS_PKT_IS_TOUCH(x)		(((x) & 0x0f) == 0x01)
57 #define SIS_PKT_IS_HIDI2C(x)		(((x) & 0x0f) == 0x06)
58 
59 /* Contact properties within report */
60 #define SIS_PKT_HAS_AREA(x)		((x) & BIT(4))
61 #define SIS_PKT_HAS_PRESSURE(x)		((x) & BIT(5))
62 #define SIS_PKT_HAS_SCANTIME(x)		((x) & BIT(6))
63 
64 /* Contact size */
65 #define SIS_BASE_LEN_PER_CONTACT	6
66 #define SIS_AREA_LEN_PER_CONTACT	2
67 #define SIS_PRESSURE_LEN_PER_CONTACT	1
68 
69 /* Offsets within contact data */
70 #define SIS_CONTACT_STATUS_OFFSET	0
71 #define SIS_CONTACT_ID_OFFSET		1 /* Contact ID */
72 #define SIS_CONTACT_X_OFFSET		2
73 #define SIS_CONTACT_Y_OFFSET		4
74 #define SIS_CONTACT_WIDTH_OFFSET	6
75 #define SIS_CONTACT_HEIGHT_OFFSET	7
76 #define SIS_CONTACT_PRESSURE_OFFSET(id)	(SIS_PKT_HAS_AREA(id) ? 8 : 6)
77 
78 /* Individual contact state */
79 #define SIS_STATUS_UP			0x0
80 #define SIS_STATUS_DOWN			0x3
81 
82 /* Touchscreen parameters */
83 #define SIS_MAX_FINGERS			10
84 #define SIS_MAX_X			4095
85 #define SIS_MAX_Y			4095
86 #define SIS_MAX_PRESSURE		255
87 
88 /* Resolution diagonal */
89 #define SIS_AREA_LENGTH_LONGER		5792
90 /*((SIS_MAX_X^2) + (SIS_MAX_Y^2))^0.5*/
91 #define SIS_AREA_LENGTH_SHORT		5792
92 #define SIS_AREA_UNIT			(5792 / 32)
93 
94 struct sis_ts_data {
95 	struct i2c_client *client;
96 	struct input_dev *input;
97 
98 	struct gpio_desc *attn_gpio;
99 	struct gpio_desc *reset_gpio;
100 
101 	u8 packet[SIS_MAX_PACKET_SIZE];
102 };
103 
104 static int sis_read_packet(struct i2c_client *client, u8 *buf,
105 			   unsigned int *num_contacts,
106 			   unsigned int *contact_size)
107 {
108 	int count_idx;
109 	int ret;
110 	u16 len;
111 	u16 crc, pkg_crc;
112 	u8 report_id;
113 
114 	ret = i2c_master_recv(client, buf, SIS_MAX_PACKET_SIZE);
115 	if (ret <= 0)
116 		return -EIO;
117 
118 	len = get_unaligned_le16(&buf[SIS_PKT_LEN_OFFSET]);
119 	if (len > SIS_MAX_PACKET_SIZE) {
120 		dev_err(&client->dev,
121 			"%s: invalid packet length (%d vs %d)\n",
122 			__func__, len, SIS_MAX_PACKET_SIZE);
123 		return -E2BIG;
124 	}
125 
126 	if (len < 10)
127 		return -EINVAL;
128 
129 	report_id = buf[SIS_PKT_REPORT_OFFSET];
130 	count_idx  = len - 1;
131 	*contact_size = SIS_BASE_LEN_PER_CONTACT;
132 
133 	if (report_id != SIS_ALL_IN_ONE_PACKAGE) {
134 		if (SIS_PKT_IS_TOUCH(report_id)) {
135 			/*
136 			 * Calculate CRC ignoring packet length
137 			 * in the beginning and CRC transmitted
138 			 * at the end of the packet.
139 			 */
140 			crc = crc_itu_t(0, buf + 2, len - 2 - 2);
141 			pkg_crc = get_unaligned_le16(&buf[len - 2]);
142 
143 			if (crc != pkg_crc) {
144 				dev_err(&client->dev,
145 					"%s: CRC Error (%d vs %d)\n",
146 					__func__, crc, pkg_crc);
147 				return -EINVAL;
148 			}
149 
150 			count_idx -= 2;
151 
152 		} else if (!SIS_PKT_IS_HIDI2C(report_id)) {
153 			dev_err(&client->dev,
154 				"%s: invalid packet ID %#02x\n",
155 				__func__, report_id);
156 			return -EINVAL;
157 		}
158 
159 		if (SIS_PKT_HAS_SCANTIME(report_id))
160 			count_idx -= SIS_SCAN_TIME_LEN;
161 
162 		if (SIS_PKT_HAS_AREA(report_id))
163 			*contact_size += SIS_AREA_LEN_PER_CONTACT;
164 		if (SIS_PKT_HAS_PRESSURE(report_id))
165 			*contact_size += SIS_PRESSURE_LEN_PER_CONTACT;
166 	}
167 
168 	*num_contacts = buf[count_idx];
169 	return 0;
170 }
171 
172 static int sis_ts_report_contact(struct sis_ts_data *ts, const u8 *data, u8 id)
173 {
174 	struct input_dev *input = ts->input;
175 	int slot;
176 	u8 status = data[SIS_CONTACT_STATUS_OFFSET];
177 	u8 pressure;
178 	u8 height, width;
179 	u16 x, y;
180 
181 	if (status != SIS_STATUS_DOWN && status != SIS_STATUS_UP) {
182 		dev_err(&ts->client->dev, "Unexpected touch status: %#02x\n",
183 			data[SIS_CONTACT_STATUS_OFFSET]);
184 		return -EINVAL;
185 	}
186 
187 	slot = input_mt_get_slot_by_key(input, data[SIS_CONTACT_ID_OFFSET]);
188 	if (slot < 0)
189 		return -ENOENT;
190 
191 	input_mt_slot(input, slot);
192 	input_mt_report_slot_state(input, MT_TOOL_FINGER,
193 				   status == SIS_STATUS_DOWN);
194 
195 	if (status == SIS_STATUS_DOWN) {
196 		pressure = height = width = 1;
197 		if (id != SIS_ALL_IN_ONE_PACKAGE) {
198 			if (SIS_PKT_HAS_AREA(id)) {
199 				width = data[SIS_CONTACT_WIDTH_OFFSET];
200 				height = data[SIS_CONTACT_HEIGHT_OFFSET];
201 			}
202 
203 			if (SIS_PKT_HAS_PRESSURE(id))
204 				pressure =
205 					data[SIS_CONTACT_PRESSURE_OFFSET(id)];
206 		}
207 
208 		x = get_unaligned_le16(&data[SIS_CONTACT_X_OFFSET]);
209 		y = get_unaligned_le16(&data[SIS_CONTACT_Y_OFFSET]);
210 
211 		input_report_abs(input, ABS_MT_TOUCH_MAJOR,
212 				 width * SIS_AREA_UNIT);
213 		input_report_abs(input, ABS_MT_TOUCH_MINOR,
214 				 height * SIS_AREA_UNIT);
215 		input_report_abs(input, ABS_MT_PRESSURE, pressure);
216 		input_report_abs(input, ABS_MT_POSITION_X, x);
217 		input_report_abs(input, ABS_MT_POSITION_Y, y);
218 	}
219 
220 	return 0;
221 }
222 
223 static void sis_ts_handle_packet(struct sis_ts_data *ts)
224 {
225 	const u8 *contact;
226 	unsigned int num_to_report = 0;
227 	unsigned int num_contacts;
228 	unsigned int num_reported;
229 	unsigned int contact_size;
230 	int error;
231 	u8 report_id;
232 
233 	do {
234 		error = sis_read_packet(ts->client, ts->packet,
235 					&num_contacts, &contact_size);
236 		if (error)
237 			break;
238 
239 		if (num_to_report == 0) {
240 			num_to_report = num_contacts;
241 		} else if (num_contacts != 0) {
242 			dev_err(&ts->client->dev,
243 				"%s: nonzero (%d) point count in tail packet\n",
244 				__func__, num_contacts);
245 			break;
246 		}
247 
248 		report_id = ts->packet[SIS_PKT_REPORT_OFFSET];
249 		contact = &ts->packet[SIS_PKT_CONTACT_OFFSET];
250 		num_reported = 0;
251 
252 		while (num_to_report > 0) {
253 			error = sis_ts_report_contact(ts, contact, report_id);
254 			if (error)
255 				break;
256 
257 			contact += contact_size;
258 			num_to_report--;
259 			num_reported++;
260 
261 			if (report_id != SIS_ALL_IN_ONE_PACKAGE &&
262 			    num_reported >= 5) {
263 				/*
264 				 * The remainder of contacts is sent
265 				 * in the 2nd packet.
266 				 */
267 				break;
268 			}
269 		}
270 	} while (num_to_report > 0);
271 
272 	input_mt_sync_frame(ts->input);
273 	input_sync(ts->input);
274 }
275 
276 static irqreturn_t sis_ts_irq_handler(int irq, void *dev_id)
277 {
278 	struct sis_ts_data *ts = dev_id;
279 
280 	do {
281 		sis_ts_handle_packet(ts);
282 	} while (ts->attn_gpio && gpiod_get_value_cansleep(ts->attn_gpio));
283 
284 	return IRQ_HANDLED;
285 }
286 
287 static void sis_ts_reset(struct sis_ts_data *ts)
288 {
289 	if (ts->reset_gpio) {
290 		/* Get out of reset */
291 		usleep_range(1000, 2000);
292 		gpiod_set_value(ts->reset_gpio, 1);
293 		usleep_range(1000, 2000);
294 		gpiod_set_value(ts->reset_gpio, 0);
295 		msleep(100);
296 	}
297 }
298 
299 static int sis_ts_probe(struct i2c_client *client)
300 {
301 	struct sis_ts_data *ts;
302 	struct input_dev *input;
303 	int error;
304 
305 	ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
306 	if (!ts)
307 		return -ENOMEM;
308 
309 	ts->client = client;
310 
311 	ts->attn_gpio = devm_gpiod_get_optional(&client->dev,
312 						"attn", GPIOD_IN);
313 	if (IS_ERR(ts->attn_gpio))
314 		return dev_err_probe(&client->dev, PTR_ERR(ts->attn_gpio),
315 				     "Failed to get attention GPIO\n");
316 
317 	ts->reset_gpio = devm_gpiod_get_optional(&client->dev,
318 						 "reset", GPIOD_OUT_LOW);
319 	if (IS_ERR(ts->reset_gpio))
320 		return dev_err_probe(&client->dev, PTR_ERR(ts->reset_gpio),
321 				     "Failed to get reset GPIO\n");
322 
323 	sis_ts_reset(ts);
324 
325 	ts->input = input = devm_input_allocate_device(&client->dev);
326 	if (!input) {
327 		dev_err(&client->dev, "Failed to allocate input device\n");
328 		return -ENOMEM;
329 	}
330 
331 	input->name = "SiS Touchscreen";
332 	input->id.bustype = BUS_I2C;
333 
334 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, SIS_MAX_X, 0, 0);
335 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, SIS_MAX_Y, 0, 0);
336 	input_set_abs_params(input, ABS_MT_PRESSURE, 0, SIS_MAX_PRESSURE, 0, 0);
337 	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
338 			     0, SIS_AREA_LENGTH_LONGER, 0, 0);
339 	input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
340 			     0, SIS_AREA_LENGTH_SHORT, 0, 0);
341 
342 	error = input_mt_init_slots(input, SIS_MAX_FINGERS, INPUT_MT_DIRECT);
343 	if (error) {
344 		dev_err(&client->dev,
345 			"Failed to initialize MT slots: %d\n", error);
346 		return error;
347 	}
348 
349 	error = devm_request_threaded_irq(&client->dev, client->irq,
350 					  NULL, sis_ts_irq_handler,
351 					  IRQF_ONESHOT,
352 					  client->name, ts);
353 	if (error) {
354 		dev_err(&client->dev, "Failed to request IRQ: %d\n", error);
355 		return error;
356 	}
357 
358 	error = input_register_device(ts->input);
359 	if (error) {
360 		dev_err(&client->dev,
361 			"Failed to register input device: %d\n", error);
362 		return error;
363 	}
364 
365 	return 0;
366 }
367 
368 #ifdef CONFIG_OF
369 static const struct of_device_id sis_ts_dt_ids[] = {
370 	{ .compatible = "sis,9200-ts" },
371 	{ /* sentinel */ }
372 };
373 MODULE_DEVICE_TABLE(of, sis_ts_dt_ids);
374 #endif
375 
376 static const struct i2c_device_id sis_ts_id[] = {
377 	{ SIS_I2C_NAME },
378 	{ "9200-ts" },
379 	{ /* sentinel */  }
380 };
381 MODULE_DEVICE_TABLE(i2c, sis_ts_id);
382 
383 static struct i2c_driver sis_ts_driver = {
384 	.driver = {
385 		.name	= SIS_I2C_NAME,
386 		.of_match_table = of_match_ptr(sis_ts_dt_ids),
387 	},
388 	.probe		= sis_ts_probe,
389 	.id_table	= sis_ts_id,
390 };
391 module_i2c_driver(sis_ts_driver);
392 
393 MODULE_DESCRIPTION("SiS 9200 Family Touchscreen Driver");
394 MODULE_LICENSE("GPL v2");
395 MODULE_AUTHOR("Mika Penttilä <mika.penttila@nextfour.com>");
396