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