Linux Audio

Check our new training course

Yocto / OpenEmbedded training

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