1// SPDX-License-Identifier: GPL-2.0-or-later
2/*-
3 * Finger Sensing Pad PS/2 mouse driver.
4 *
5 * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
6 * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation.
7 */
8
9#include <linux/module.h>
10#include <linux/input.h>
11#include <linux/input/mt.h>
12#include <linux/ctype.h>
13#include <linux/libps2.h>
14#include <linux/serio.h>
15#include <linux/jiffies.h>
16#include <linux/slab.h>
17
18#include "psmouse.h"
19#include "sentelic.h"
20
21/*
22 * Timeout for FSP PS/2 command only (in milliseconds).
23 */
24#define	FSP_CMD_TIMEOUT		200
25#define	FSP_CMD_TIMEOUT2	30
26
27#define	GET_ABS_X(packet)	((packet[1] << 2) | ((packet[3] >> 2) & 0x03))
28#define	GET_ABS_Y(packet)	((packet[2] << 2) | (packet[3] & 0x03))
29
30/** Driver version. */
31static const char fsp_drv_ver[] = "1.1.0-K";
32
33/*
34 * Make sure that the value being sent to FSP will not conflict with
35 * possible sample rate values.
36 */
37static unsigned char fsp_test_swap_cmd(unsigned char reg_val)
38{
39	switch (reg_val) {
40	case 10: case 20: case 40: case 60: case 80: case 100: case 200:
41		/*
42		 * The requested value being sent to FSP matched to possible
43		 * sample rates, swap the given value such that the hardware
44		 * wouldn't get confused.
45		 */
46		return (reg_val >> 4) | (reg_val << 4);
47	default:
48		return reg_val;	/* swap isn't necessary */
49	}
50}
51
52/*
53 * Make sure that the value being sent to FSP will not conflict with certain
54 * commands.
55 */
56static unsigned char fsp_test_invert_cmd(unsigned char reg_val)
57{
58	switch (reg_val) {
59	case 0xe9: case 0xee: case 0xf2: case 0xff:
60		/*
61		 * The requested value being sent to FSP matched to certain
62		 * commands, inverse the given value such that the hardware
63		 * wouldn't get confused.
64		 */
65		return ~reg_val;
66	default:
67		return reg_val;	/* inversion isn't necessary */
68	}
69}
70
71static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val)
72{
73	struct ps2dev *ps2dev = &psmouse->ps2dev;
74	unsigned char param[3];
75	unsigned char addr;
76	int rc = -1;
77
78	/*
79	 * We need to shut off the device and switch it into command
80	 * mode so we don't confuse our protocol handler. We don't need
81	 * to do that for writes because sysfs set helper does this for
82	 * us.
83	 */
84	psmouse_deactivate(psmouse);
85
86	ps2_begin_command(ps2dev);
87
88	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
89		goto out;
90
91	/* should return 0xfe(request for resending) */
92	ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
93	/* should return 0xfc(failed) */
94	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
95
96	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
97		goto out;
98
99	if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) {
100		ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2);
101	} else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) {
102		/* swapping is required */
103		ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2);
104		/* expect 0xfe */
105	} else {
106		/* swapping isn't necessary */
107		ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
108		/* expect 0xfe */
109	}
110	/* should return 0xfc(failed) */
111	ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT);
112
113	if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0)
114		goto out;
115
116	*reg_val = param[2];
117	rc = 0;
118
119 out:
120	ps2_end_command(ps2dev);
121	psmouse_activate(psmouse);
122	psmouse_dbg(psmouse,
123		    "READ REG: 0x%02x is 0x%02x (rc = %d)\n",
124		    reg_addr, *reg_val, rc);
125	return rc;
126}
127
128static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val)
129{
130	struct ps2dev *ps2dev = &psmouse->ps2dev;
131	unsigned char v;
132	int rc = -1;
133
134	ps2_begin_command(ps2dev);
135
136	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
137		goto out;
138
139	if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) {
140		/* inversion is required */
141		ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2);
142	} else {
143		if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) {
144			/* swapping is required */
145			ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2);
146		} else {
147			/* swapping isn't necessary */
148			ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2);
149		}
150	}
151	/* write the register address in correct order */
152	ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
153
154	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
155		goto out;
156
157	if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
158		/* inversion is required */
159		ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
160	} else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) {
161		/* swapping is required */
162		ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2);
163	} else {
164		/* swapping isn't necessary */
165		ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2);
166	}
167
168	/* write the register value in correct order */
169	ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
170	rc = 0;
171
172 out:
173	ps2_end_command(ps2dev);
174	psmouse_dbg(psmouse,
175		    "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n",
176		    reg_addr, reg_val, rc);
177	return rc;
178}
179
180/* Enable register clock gating for writing certain registers */
181static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable)
182{
183	int v, nv;
184
185	if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1)
186		return -1;
187
188	if (enable)
189		nv = v | FSP_BIT_EN_REG_CLK;
190	else
191		nv = v & ~FSP_BIT_EN_REG_CLK;
192
193	/* only write if necessary */
194	if (nv != v)
195		if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1)
196			return -1;
197
198	return 0;
199}
200
201static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val)
202{
203	struct ps2dev *ps2dev = &psmouse->ps2dev;
204	unsigned char param[3];
205	int rc = -1;
206
207	psmouse_deactivate(psmouse);
208
209	ps2_begin_command(ps2dev);
210
211	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
212		goto out;
213
214	ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
215	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
216
217	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
218		goto out;
219
220	ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2);
221	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
222
223	/* get the returned result */
224	if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
225		goto out;
226
227	*reg_val = param[2];
228	rc = 0;
229
230 out:
231	ps2_end_command(ps2dev);
232	psmouse_activate(psmouse);
233	psmouse_dbg(psmouse,
234		    "READ PAGE REG: 0x%02x (rc = %d)\n",
235		    *reg_val, rc);
236	return rc;
237}
238
239static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val)
240{
241	struct ps2dev *ps2dev = &psmouse->ps2dev;
242	unsigned char v;
243	int rc = -1;
244
245	ps2_begin_command(ps2dev);
246
247	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
248		goto out;
249
250	ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2);
251	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
252
253	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
254		goto out;
255
256	if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
257		ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
258	} else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) {
259		/* swapping is required */
260		ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2);
261	} else {
262		/* swapping isn't necessary */
263		ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2);
264	}
265
266	ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
267	rc = 0;
268
269 out:
270	ps2_end_command(ps2dev);
271	psmouse_dbg(psmouse,
272		    "WRITE PAGE REG: to 0x%02x (rc = %d)\n",
273		    reg_val, rc);
274	return rc;
275}
276
277static int fsp_get_version(struct psmouse *psmouse, int *version)
278{
279	if (fsp_reg_read(psmouse, FSP_REG_VERSION, version))
280		return -EIO;
281
282	return 0;
283}
284
285static int fsp_get_revision(struct psmouse *psmouse, int *rev)
286{
287	if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev))
288		return -EIO;
289
290	return 0;
291}
292
293static int fsp_get_sn(struct psmouse *psmouse, int *sn)
294{
295	int v0, v1, v2;
296	int rc = -EIO;
297
298	/* production number since Cx is available at: 0x0b40 ~ 0x0b42 */
299	if (fsp_page_reg_write(psmouse, FSP_PAGE_0B))
300		goto out;
301	if (fsp_reg_read(psmouse, FSP_REG_SN0, &v0))
302		goto out;
303	if (fsp_reg_read(psmouse, FSP_REG_SN1, &v1))
304		goto out;
305	if (fsp_reg_read(psmouse, FSP_REG_SN2, &v2))
306		goto out;
307	*sn = (v0 << 16) | (v1 << 8) | v2;
308	rc = 0;
309out:
310	fsp_page_reg_write(psmouse, FSP_PAGE_DEFAULT);
311	return rc;
312}
313
314static int fsp_get_buttons(struct psmouse *psmouse, int *btn)
315{
316	static const int buttons[] = {
317		0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */
318		0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */
319		0x04, /* Left/Middle/Right & Scroll Up/Down */
320		0x02, /* Left/Middle/Right */
321	};
322	int val;
323
324	if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS, &val) == -1)
325		return -EIO;
326
327	*btn = buttons[(val & 0x30) >> 4];
328	return 0;
329}
330
331/* Enable on-pad command tag output */
332static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable)
333{
334	int v, nv;
335	int res = 0;
336
337	if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) {
338		psmouse_err(psmouse, "Unable get OPC state.\n");
339		return -EIO;
340	}
341
342	if (enable)
343		nv = v | FSP_BIT_EN_OPC_TAG;
344	else
345		nv = v & ~FSP_BIT_EN_OPC_TAG;
346
347	/* only write if necessary */
348	if (nv != v) {
349		fsp_reg_write_enable(psmouse, true);
350		res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv);
351		fsp_reg_write_enable(psmouse, false);
352	}
353
354	if (res != 0) {
355		psmouse_err(psmouse, "Unable to enable OPC tag.\n");
356		res = -EIO;
357	}
358
359	return res;
360}
361
362static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable)
363{
364	struct fsp_data *pad = psmouse->private;
365	int val;
366
367	if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val))
368		return -EIO;
369
370	pad->vscroll = enable;
371
372	if (enable)
373		val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE);
374	else
375		val &= ~FSP_BIT_FIX_VSCR;
376
377	if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val))
378		return -EIO;
379
380	return 0;
381}
382
383static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable)
384{
385	struct fsp_data *pad = psmouse->private;
386	int val, v2;
387
388	if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val))
389		return -EIO;
390
391	if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2))
392		return -EIO;
393
394	pad->hscroll = enable;
395
396	if (enable) {
397		val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE);
398		v2 |= FSP_BIT_EN_MSID6;
399	} else {
400		val &= ~FSP_BIT_FIX_HSCR;
401		v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8);
402	}
403
404	if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val))
405		return -EIO;
406
407	/* reconfigure horizontal scrolling packet output */
408	if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2))
409		return -EIO;
410
411	return 0;
412}
413
414/*
415 * Write device specific initial parameters.
416 *
417 * ex: 0xab 0xcd - write oxcd into register 0xab
418 */
419static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data,
420				   const char *buf, size_t count)
421{
422	unsigned int reg, val;
423	char *rest;
424	ssize_t retval;
425
426	reg = simple_strtoul(buf, &rest, 16);
427	if (rest == buf || *rest != ' ' || reg > 0xff)
428		return -EINVAL;
429
430	retval = kstrtouint(rest + 1, 16, &val);
431	if (retval)
432		return retval;
433
434	if (val > 0xff)
435		return -EINVAL;
436
437	if (fsp_reg_write_enable(psmouse, true))
438		return -EIO;
439
440	retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count;
441
442	fsp_reg_write_enable(psmouse, false);
443
444	return retval;
445}
446
447PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg);
448
449static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse,
450					void *data, char *buf)
451{
452	struct fsp_data *pad = psmouse->private;
453
454	return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val);
455}
456
457/*
458 * Read a register from device.
459 *
460 * ex: 0xab -- read content from register 0xab
461 */
462static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data,
463					const char *buf, size_t count)
464{
465	struct fsp_data *pad = psmouse->private;
466	unsigned int reg, val;
467	int err;
468
469	err = kstrtouint(buf, 16, &reg);
470	if (err)
471		return err;
472
473	if (reg > 0xff)
474		return -EINVAL;
475
476	if (fsp_reg_read(psmouse, reg, &val))
477		return -EIO;
478
479	pad->last_reg = reg;
480	pad->last_val = val;
481
482	return count;
483}
484
485PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL,
486			fsp_attr_show_getreg, fsp_attr_set_getreg);
487
488static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse,
489					void *data, char *buf)
490{
491	int val = 0;
492
493	if (fsp_page_reg_read(psmouse, &val))
494		return -EIO;
495
496	return sprintf(buf, "%02x\n", val);
497}
498
499static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data,
500					const char *buf, size_t count)
501{
502	unsigned int val;
503	int err;
504
505	err = kstrtouint(buf, 16, &val);
506	if (err)
507		return err;
508
509	if (val > 0xff)
510		return -EINVAL;
511
512	if (fsp_page_reg_write(psmouse, val))
513		return -EIO;
514
515	return count;
516}
517
518PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL,
519			fsp_attr_show_pagereg, fsp_attr_set_pagereg);
520
521static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse,
522					void *data, char *buf)
523{
524	struct fsp_data *pad = psmouse->private;
525
526	return sprintf(buf, "%d\n", pad->vscroll);
527}
528
529static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data,
530					const char *buf, size_t count)
531{
532	unsigned int val;
533	int err;
534
535	err = kstrtouint(buf, 10, &val);
536	if (err)
537		return err;
538
539	if (val > 1)
540		return -EINVAL;
541
542	fsp_onpad_vscr(psmouse, val);
543
544	return count;
545}
546
547PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL,
548			fsp_attr_show_vscroll, fsp_attr_set_vscroll);
549
550static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse,
551					void *data, char *buf)
552{
553	struct fsp_data *pad = psmouse->private;
554
555	return sprintf(buf, "%d\n", pad->hscroll);
556}
557
558static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data,
559					const char *buf, size_t count)
560{
561	unsigned int val;
562	int err;
563
564	err = kstrtouint(buf, 10, &val);
565	if (err)
566		return err;
567
568	if (val > 1)
569		return -EINVAL;
570
571	fsp_onpad_hscr(psmouse, val);
572
573	return count;
574}
575
576PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL,
577			fsp_attr_show_hscroll, fsp_attr_set_hscroll);
578
579static ssize_t fsp_attr_show_flags(struct psmouse *psmouse,
580					void *data, char *buf)
581{
582	struct fsp_data *pad = psmouse->private;
583
584	return sprintf(buf, "%c\n",
585			pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c');
586}
587
588static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data,
589					const char *buf, size_t count)
590{
591	struct fsp_data *pad = psmouse->private;
592	size_t i;
593
594	for (i = 0; i < count; i++) {
595		switch (buf[i]) {
596		case 'C':
597			pad->flags |= FSPDRV_FLAG_EN_OPC;
598			break;
599		case 'c':
600			pad->flags &= ~FSPDRV_FLAG_EN_OPC;
601			break;
602		default:
603			return -EINVAL;
604		}
605	}
606	return count;
607}
608
609PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL,
610			fsp_attr_show_flags, fsp_attr_set_flags);
611
612static ssize_t fsp_attr_show_ver(struct psmouse *psmouse,
613					void *data, char *buf)
614{
615	return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver);
616}
617
618PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver);
619
620static struct attribute *fsp_attributes[] = {
621	&psmouse_attr_setreg.dattr.attr,
622	&psmouse_attr_getreg.dattr.attr,
623	&psmouse_attr_page.dattr.attr,
624	&psmouse_attr_vscroll.dattr.attr,
625	&psmouse_attr_hscroll.dattr.attr,
626	&psmouse_attr_flags.dattr.attr,
627	&psmouse_attr_ver.dattr.attr,
628	NULL
629};
630
631static struct attribute_group fsp_attribute_group = {
632	.attrs = fsp_attributes,
633};
634
635#ifdef	FSP_DEBUG
636static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[])
637{
638	static unsigned int ps2_packet_cnt;
639	static unsigned int ps2_last_second;
640	unsigned int jiffies_msec;
641	const char *packet_type = "UNKNOWN";
642	unsigned short abs_x = 0, abs_y = 0;
643
644	/* Interpret & dump the packet data. */
645	switch (packet[0] >> FSP_PKT_TYPE_SHIFT) {
646	case FSP_PKT_TYPE_ABS:
647		packet_type = "Absolute";
648		abs_x = GET_ABS_X(packet);
649		abs_y = GET_ABS_Y(packet);
650		break;
651	case FSP_PKT_TYPE_NORMAL:
652		packet_type = "Normal";
653		break;
654	case FSP_PKT_TYPE_NOTIFY:
655		packet_type = "Notify";
656		break;
657	case FSP_PKT_TYPE_NORMAL_OPC:
658		packet_type = "Normal-OPC";
659		break;
660	}
661
662	ps2_packet_cnt++;
663	jiffies_msec = jiffies_to_msecs(jiffies);
664	psmouse_dbg(psmouse,
665		    "%08dms %s packets: %02x, %02x, %02x, %02x; "
666		    "abs_x: %d, abs_y: %d\n",
667		    jiffies_msec, packet_type,
668		    packet[0], packet[1], packet[2], packet[3], abs_x, abs_y);
669
670	if (jiffies_msec - ps2_last_second > 1000) {
671		psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt);
672		ps2_packet_cnt = 0;
673		ps2_last_second = jiffies_msec;
674	}
675}
676#else
677static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[])
678{
679}
680#endif
681
682static void fsp_set_slot(struct input_dev *dev, int slot, bool active,
683			 unsigned int x, unsigned int y)
684{
685	input_mt_slot(dev, slot);
686	input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
687	if (active) {
688		input_report_abs(dev, ABS_MT_POSITION_X, x);
689		input_report_abs(dev, ABS_MT_POSITION_Y, y);
690	}
691}
692
693static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
694{
695	struct input_dev *dev = psmouse->dev;
696	struct fsp_data *ad = psmouse->private;
697	unsigned char *packet = psmouse->packet;
698	unsigned char button_status = 0, lscroll = 0, rscroll = 0;
699	unsigned short abs_x, abs_y, fgrs = 0;
700
701	if (psmouse->pktcnt < 4)
702		return PSMOUSE_GOOD_DATA;
703
704	/*
705	 * Full packet accumulated, process it
706	 */
707
708	fsp_packet_debug(psmouse, packet);
709
710	switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
711	case FSP_PKT_TYPE_ABS:
712
713		if ((packet[0] == 0x48 || packet[0] == 0x49) &&
714		    packet[1] == 0 && packet[2] == 0) {
715			/*
716			 * Ignore coordinate noise when finger leaving the
717			 * surface, otherwise cursor may jump to upper-left
718			 * corner.
719			 */
720			packet[3] &= 0xf0;
721		}
722
723		abs_x = GET_ABS_X(packet);
724		abs_y = GET_ABS_Y(packet);
725
726		if (packet[0] & FSP_PB0_MFMC) {
727			/*
728			 * MFMC packet: assume that there are two fingers on
729			 * pad
730			 */
731			fgrs = 2;
732
733			/* MFMC packet */
734			if (packet[0] & FSP_PB0_MFMC_FGR2) {
735				/* 2nd finger */
736				if (ad->last_mt_fgr == 2) {
737					/*
738					 * workaround for buggy firmware
739					 * which doesn't clear MFMC bit if
740					 * the 1st finger is up
741					 */
742					fgrs = 1;
743					fsp_set_slot(dev, 0, false, 0, 0);
744				}
745				ad->last_mt_fgr = 2;
746
747				fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y);
748			} else {
749				/* 1st finger */
750				if (ad->last_mt_fgr == 1) {
751					/*
752					 * workaround for buggy firmware
753					 * which doesn't clear MFMC bit if
754					 * the 2nd finger is up
755					 */
756					fgrs = 1;
757					fsp_set_slot(dev, 1, false, 0, 0);
758				}
759				ad->last_mt_fgr = 1;
760				fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y);
761			}
762		} else {
763			/* SFAC packet */
764			if ((packet[0] & (FSP_PB0_LBTN|FSP_PB0_PHY_BTN)) ==
765				FSP_PB0_LBTN) {
766				/* On-pad click in SFAC mode should be handled
767				 * by userspace.  On-pad clicks in MFMC mode
768				 * are real clickpad clicks, and not ignored.
769				 */
770				packet[0] &= ~FSP_PB0_LBTN;
771			}
772
773			/* no multi-finger information */
774			ad->last_mt_fgr = 0;
775
776			if (abs_x != 0 && abs_y != 0)
777				fgrs = 1;
778
779			fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y);
780			fsp_set_slot(dev, 1, false, 0, 0);
781		}
782		if (fgrs == 1 || (fgrs == 2 && !(packet[0] & FSP_PB0_MFMC_FGR2))) {
783			input_report_abs(dev, ABS_X, abs_x);
784			input_report_abs(dev, ABS_Y, abs_y);
785		}
786		input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
787		input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
788		input_report_key(dev, BTN_TOUCH, fgrs);
789		input_report_key(dev, BTN_TOOL_FINGER, fgrs == 1);
790		input_report_key(dev, BTN_TOOL_DOUBLETAP, fgrs == 2);
791		break;
792
793	case FSP_PKT_TYPE_NORMAL_OPC:
794		/* on-pad click, filter it if necessary */
795		if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC)
796			packet[0] &= ~FSP_PB0_LBTN;
797		fallthrough;
798
799	case FSP_PKT_TYPE_NORMAL:
800		/* normal packet */
801		/* special packet data translation from on-pad packets */
802		if (packet[3] != 0) {
803			if (packet[3] & BIT(0))
804				button_status |= 0x01;	/* wheel down */
805			if (packet[3] & BIT(1))
806				button_status |= 0x0f;	/* wheel up */
807			if (packet[3] & BIT(2))
808				button_status |= BIT(4);/* horizontal left */
809			if (packet[3] & BIT(3))
810				button_status |= BIT(5);/* horizontal right */
811			/* push back to packet queue */
812			if (button_status != 0)
813				packet[3] = button_status;
814			rscroll = (packet[3] >> 4) & 1;
815			lscroll = (packet[3] >> 5) & 1;
816		}
817		/*
818		 * Processing wheel up/down and extra button events
819		 */
820		input_report_rel(dev, REL_WHEEL,
821				 (int)(packet[3] & 8) - (int)(packet[3] & 7));
822		input_report_rel(dev, REL_HWHEEL, lscroll - rscroll);
823		input_report_key(dev, BTN_BACK, lscroll);
824		input_report_key(dev, BTN_FORWARD, rscroll);
825
826		/*
827		 * Standard PS/2 Mouse
828		 */
829		psmouse_report_standard_packet(dev, packet);
830		break;
831	}
832
833	input_sync(dev);
834
835	return PSMOUSE_FULL_PACKET;
836}
837
838static int fsp_activate_protocol(struct psmouse *psmouse)
839{
840	struct fsp_data *pad = psmouse->private;
841	struct ps2dev *ps2dev = &psmouse->ps2dev;
842	unsigned char param[2];
843	int val;
844
845	/*
846	 * Standard procedure to enter FSP Intellimouse mode
847	 * (scrolling wheel, 4th and 5th buttons)
848	 */
849	param[0] = 200;
850	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
851	param[0] = 200;
852	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
853	param[0] =  80;
854	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
855
856	ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
857	if (param[0] != 0x04) {
858		psmouse_err(psmouse,
859			    "Unable to enable 4 bytes packet format.\n");
860		return -EIO;
861	}
862
863	if (pad->ver < FSP_VER_STL3888_C0) {
864		/* Preparing relative coordinates output for older hardware */
865		if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) {
866			psmouse_err(psmouse,
867				    "Unable to read SYSCTL5 register.\n");
868			return -EIO;
869		}
870
871		if (fsp_get_buttons(psmouse, &pad->buttons)) {
872			psmouse_err(psmouse,
873				    "Unable to retrieve number of buttons.\n");
874			return -EIO;
875		}
876
877		val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8);
878		/* Ensure we are not in absolute mode */
879		val &= ~FSP_BIT_EN_PKT_G0;
880		if (pad->buttons == 0x06) {
881			/* Left/Middle/Right & Scroll Up/Down/Right/Left */
882			val |= FSP_BIT_EN_MSID6;
883		}
884
885		if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) {
886			psmouse_err(psmouse,
887				    "Unable to set up required mode bits.\n");
888			return -EIO;
889		}
890
891		/*
892		 * Enable OPC tags such that driver can tell the difference
893		 * between on-pad and real button click
894		 */
895		if (fsp_opc_tag_enable(psmouse, true))
896			psmouse_warn(psmouse,
897				     "Failed to enable OPC tag mode.\n");
898		/* enable on-pad click by default */
899		pad->flags |= FSPDRV_FLAG_EN_OPC;
900
901		/* Enable on-pad vertical and horizontal scrolling */
902		fsp_onpad_vscr(psmouse, true);
903		fsp_onpad_hscr(psmouse, true);
904	} else {
905		/* Enable absolute coordinates output for Cx/Dx hardware */
906		if (fsp_reg_write(psmouse, FSP_REG_SWC1,
907				  FSP_BIT_SWC1_EN_ABS_1F |
908				  FSP_BIT_SWC1_EN_ABS_2F |
909				  FSP_BIT_SWC1_EN_FUP_OUT |
910				  FSP_BIT_SWC1_EN_ABS_CON)) {
911			psmouse_err(psmouse,
912				    "Unable to enable absolute coordinates output.\n");
913			return -EIO;
914		}
915	}
916
917	return 0;
918}
919
920static int fsp_set_input_params(struct psmouse *psmouse)
921{
922	struct input_dev *dev = psmouse->dev;
923	struct fsp_data *pad = psmouse->private;
924
925	if (pad->ver < FSP_VER_STL3888_C0) {
926		__set_bit(BTN_MIDDLE, dev->keybit);
927		__set_bit(BTN_BACK, dev->keybit);
928		__set_bit(BTN_FORWARD, dev->keybit);
929		__set_bit(REL_WHEEL, dev->relbit);
930		__set_bit(REL_HWHEEL, dev->relbit);
931	} else {
932		/*
933		 * Hardware prior to Cx performs much better in relative mode;
934		 * hence, only enable absolute coordinates output as well as
935		 * multi-touch output for the newer hardware.
936		 *
937		 * Maximum coordinates can be computed as:
938		 *
939		 *	number of scanlines * 64 - 57
940		 *
941		 * where number of X/Y scanline lines are 16/12.
942		 */
943		int abs_x = 967, abs_y = 711;
944
945		__set_bit(EV_ABS, dev->evbit);
946		__clear_bit(EV_REL, dev->evbit);
947		__set_bit(BTN_TOUCH, dev->keybit);
948		__set_bit(BTN_TOOL_FINGER, dev->keybit);
949		__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
950		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
951
952		input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0);
953		input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0);
954		input_mt_init_slots(dev, 2, 0);
955		input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0);
956		input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0);
957	}
958
959	return 0;
960}
961
962int fsp_detect(struct psmouse *psmouse, bool set_properties)
963{
964	int id;
965
966	if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id))
967		return -EIO;
968
969	if (id != 0x01)
970		return -ENODEV;
971
972	if (set_properties) {
973		psmouse->vendor = "Sentelic";
974		psmouse->name = "FingerSensingPad";
975	}
976
977	return 0;
978}
979
980static void fsp_reset(struct psmouse *psmouse)
981{
982	fsp_opc_tag_enable(psmouse, false);
983	fsp_onpad_vscr(psmouse, false);
984	fsp_onpad_hscr(psmouse, false);
985}
986
987static void fsp_disconnect(struct psmouse *psmouse)
988{
989	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
990			   &fsp_attribute_group);
991
992	fsp_reset(psmouse);
993	kfree(psmouse->private);
994}
995
996static int fsp_reconnect(struct psmouse *psmouse)
997{
998	int version;
999
1000	if (fsp_detect(psmouse, 0))
1001		return -ENODEV;
1002
1003	if (fsp_get_version(psmouse, &version))
1004		return -ENODEV;
1005
1006	if (fsp_activate_protocol(psmouse))
1007		return -EIO;
1008
1009	return 0;
1010}
1011
1012int fsp_init(struct psmouse *psmouse)
1013{
1014	struct fsp_data *priv;
1015	int ver, rev, sn = 0;
1016	int error;
1017
1018	if (fsp_get_version(psmouse, &ver) ||
1019	    fsp_get_revision(psmouse, &rev)) {
1020		return -ENODEV;
1021	}
1022	if (ver >= FSP_VER_STL3888_C0) {
1023		/* firmware information is only available since C0 */
1024		fsp_get_sn(psmouse, &sn);
1025	}
1026
1027	psmouse_info(psmouse,
1028		     "Finger Sensing Pad, hw: %d.%d.%d, sn: %x, sw: %s\n",
1029		     ver >> 4, ver & 0x0F, rev, sn, fsp_drv_ver);
1030
1031	psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
1032	if (!priv)
1033		return -ENOMEM;
1034
1035	priv->ver = ver;
1036	priv->rev = rev;
1037
1038	psmouse->protocol_handler = fsp_process_byte;
1039	psmouse->disconnect = fsp_disconnect;
1040	psmouse->reconnect = fsp_reconnect;
1041	psmouse->cleanup = fsp_reset;
1042	psmouse->pktsize = 4;
1043
1044	error = fsp_activate_protocol(psmouse);
1045	if (error)
1046		goto err_out;
1047
1048	/* Set up various supported input event bits */
1049	error = fsp_set_input_params(psmouse);
1050	if (error)
1051		goto err_out;
1052
1053	error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
1054				   &fsp_attribute_group);
1055	if (error) {
1056		psmouse_err(psmouse,
1057			    "Failed to create sysfs attributes (%d)", error);
1058		goto err_out;
1059	}
1060
1061	return 0;
1062
1063 err_out:
1064	kfree(psmouse->private);
1065	psmouse->private = NULL;
1066	return error;
1067}
1068