Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add a driver for wdt87xx touchscreen controller

This is a driver for Weida HiTech WDT87xx series touchscreen controller.

Signed-off-by: HungNien Chen <hn.chen@weidahitech.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

HungNien Chen and committed by
Dmitry Torokhov
3e30c11c eeeee40f

+1153
+12
drivers/input/touchscreen/Kconfig
··· 658 658 To compile this driver as a module, choose M here: the 659 659 module will be called pixcir_i2c_ts. 660 660 661 + config TOUCHSCREEN_WDT87XX_I2C 662 + tristate "Weida HiTech I2C touchscreen" 663 + depends on I2C 664 + help 665 + Say Y here if you have a Weida WDT87XX I2C touchscreen 666 + connected to your system. 667 + 668 + If unsure, say N. 669 + 670 + To compile this driver as a module, choose M here: the 671 + module will be called wdt87xx_i2c. 672 + 661 673 config TOUCHSCREEN_WM831X 662 674 tristate "Support for WM831x touchscreen controllers" 663 675 depends on MFD_WM831X
+1
drivers/input/touchscreen/Makefile
··· 72 72 obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o 73 73 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o 74 74 obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o 75 + obj-$(CONFIG_TOUCHSCREEN_WDT87XX_I2C) += wdt87xx_i2c.o 75 76 obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o 76 77 obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o 77 78 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
+1140
drivers/input/touchscreen/wdt87xx_i2c.c
··· 1 + /* 2 + * Weida HiTech WDT87xx TouchScreen I2C driver 3 + * 4 + * Copyright (c) 2015 Weida Hi-Tech Co., Ltd. 5 + * HN Chen <hn.chen@weidahitech.com> 6 + * 7 + * This software is licensed under the terms of the GNU General Public 8 + * License, as published by the Free Software Foundation, and 9 + * may be copied, distributed, and modified under those terms. 10 + */ 11 + 12 + #include <linux/i2c.h> 13 + #include <linux/input.h> 14 + #include <linux/interrupt.h> 15 + #include <linux/delay.h> 16 + #include <linux/irq.h> 17 + #include <linux/io.h> 18 + #include <linux/module.h> 19 + #include <linux/slab.h> 20 + #include <linux/firmware.h> 21 + #include <linux/input/mt.h> 22 + #include <linux/acpi.h> 23 + #include <asm/unaligned.h> 24 + 25 + #define WDT87XX_NAME "wdt87xx_i2c" 26 + #define WDT87XX_DRV_VER "0.9.5" 27 + #define WDT87XX_FW_NAME "wdt87xx_fw.bin" 28 + #define WDT87XX_CFG_NAME "wdt87xx_cfg.bin" 29 + 30 + #define MODE_ACTIVE 0x01 31 + #define MODE_READY 0x02 32 + #define MODE_IDLE 0x03 33 + #define MODE_SLEEP 0x04 34 + #define MODE_STOP 0xFF 35 + 36 + #define WDT_MAX_FINGER 10 37 + #define WDT_RAW_BUF_COUNT 54 38 + #define WDT_V1_RAW_BUF_COUNT 74 39 + #define WDT_FIRMWARE_ID 0xa9e368f5 40 + 41 + #define PG_SIZE 0x1000 42 + #define MAX_RETRIES 3 43 + 44 + #define MAX_UNIT_AXIS 0x7FFF 45 + 46 + #define PKT_READ_SIZE 72 47 + #define PKT_WRITE_SIZE 80 48 + 49 + /* the finger definition of the report event */ 50 + #define FINGER_EV_OFFSET_ID 0 51 + #define FINGER_EV_OFFSET_X 1 52 + #define FINGER_EV_OFFSET_Y 3 53 + #define FINGER_EV_SIZE 5 54 + 55 + #define FINGER_EV_V1_OFFSET_ID 0 56 + #define FINGER_EV_V1_OFFSET_W 1 57 + #define FINGER_EV_V1_OFFSET_P 2 58 + #define FINGER_EV_V1_OFFSET_X 3 59 + #define FINGER_EV_V1_OFFSET_Y 5 60 + #define FINGER_EV_V1_SIZE 7 61 + 62 + /* The definition of a report packet */ 63 + #define TOUCH_PK_OFFSET_REPORT_ID 0 64 + #define TOUCH_PK_OFFSET_EVENT 1 65 + #define TOUCH_PK_OFFSET_SCAN_TIME 51 66 + #define TOUCH_PK_OFFSET_FNGR_NUM 53 67 + 68 + #define TOUCH_PK_V1_OFFSET_REPORT_ID 0 69 + #define TOUCH_PK_V1_OFFSET_EVENT 1 70 + #define TOUCH_PK_V1_OFFSET_SCAN_TIME 71 71 + #define TOUCH_PK_V1_OFFSET_FNGR_NUM 73 72 + 73 + /* The definition of the controller parameters */ 74 + #define CTL_PARAM_OFFSET_FW_ID 0 75 + #define CTL_PARAM_OFFSET_PLAT_ID 2 76 + #define CTL_PARAM_OFFSET_XMLS_ID1 4 77 + #define CTL_PARAM_OFFSET_XMLS_ID2 6 78 + #define CTL_PARAM_OFFSET_PHY_CH_X 8 79 + #define CTL_PARAM_OFFSET_PHY_CH_Y 10 80 + #define CTL_PARAM_OFFSET_PHY_X0 12 81 + #define CTL_PARAM_OFFSET_PHY_X1 14 82 + #define CTL_PARAM_OFFSET_PHY_Y0 16 83 + #define CTL_PARAM_OFFSET_PHY_Y1 18 84 + #define CTL_PARAM_OFFSET_PHY_W 22 85 + #define CTL_PARAM_OFFSET_PHY_H 24 86 + 87 + /* Communication commands */ 88 + #define PACKET_SIZE 56 89 + #define VND_REQ_READ 0x06 90 + #define VND_READ_DATA 0x07 91 + #define VND_REQ_WRITE 0x08 92 + 93 + #define VND_CMD_START 0x00 94 + #define VND_CMD_STOP 0x01 95 + #define VND_CMD_RESET 0x09 96 + 97 + #define VND_CMD_ERASE 0x1A 98 + 99 + #define VND_GET_CHECKSUM 0x66 100 + 101 + #define VND_SET_DATA 0x83 102 + #define VND_SET_COMMAND_DATA 0x84 103 + #define VND_SET_CHECKSUM_CALC 0x86 104 + #define VND_SET_CHECKSUM_LENGTH 0x87 105 + 106 + #define VND_CMD_SFLCK 0xFC 107 + #define VND_CMD_SFUNL 0xFD 108 + 109 + #define CMD_SFLCK_KEY 0xC39B 110 + #define CMD_SFUNL_KEY 0x95DA 111 + 112 + #define STRIDX_PLATFORM_ID 0x80 113 + #define STRIDX_PARAMETERS 0x81 114 + 115 + #define CMD_BUF_SIZE 8 116 + #define PKT_BUF_SIZE 64 117 + 118 + /* The definition of the command packet */ 119 + #define CMD_REPORT_ID_OFFSET 0x0 120 + #define CMD_TYPE_OFFSET 0x1 121 + #define CMD_INDEX_OFFSET 0x2 122 + #define CMD_KEY_OFFSET 0x3 123 + #define CMD_LENGTH_OFFSET 0x4 124 + #define CMD_DATA_OFFSET 0x8 125 + 126 + /* The definition of firmware chunk tags */ 127 + #define FOURCC_ID_RIFF 0x46464952 128 + #define FOURCC_ID_WHIF 0x46494857 129 + #define FOURCC_ID_FRMT 0x544D5246 130 + #define FOURCC_ID_FRWR 0x52575246 131 + #define FOURCC_ID_CNFG 0x47464E43 132 + 133 + #define CHUNK_ID_FRMT FOURCC_ID_FRMT 134 + #define CHUNK_ID_FRWR FOURCC_ID_FRWR 135 + #define CHUNK_ID_CNFG FOURCC_ID_CNFG 136 + 137 + #define FW_FOURCC1_OFFSET 0 138 + #define FW_SIZE_OFFSET 4 139 + #define FW_FOURCC2_OFFSET 8 140 + #define FW_PAYLOAD_OFFSET 40 141 + 142 + #define FW_CHUNK_ID_OFFSET 0 143 + #define FW_CHUNK_SIZE_OFFSET 4 144 + #define FW_CHUNK_TGT_START_OFFSET 8 145 + #define FW_CHUNK_PAYLOAD_LEN_OFFSET 12 146 + #define FW_CHUNK_SRC_START_OFFSET 16 147 + #define FW_CHUNK_VERSION_OFFSET 20 148 + #define FW_CHUNK_ATTR_OFFSET 24 149 + #define FW_CHUNK_PAYLOAD_OFFSET 32 150 + 151 + /* Controller requires minimum 300us between commands */ 152 + #define WDT_COMMAND_DELAY_MS 2 153 + #define WDT_FLASH_WRITE_DELAY_MS 4 154 + 155 + struct wdt87xx_sys_param { 156 + u16 fw_id; 157 + u16 plat_id; 158 + u16 xmls_id1; 159 + u16 xmls_id2; 160 + u16 phy_ch_x; 161 + u16 phy_ch_y; 162 + u16 phy_w; 163 + u16 phy_h; 164 + u32 max_x; 165 + u32 max_y; 166 + }; 167 + 168 + struct wdt87xx_data { 169 + struct i2c_client *client; 170 + struct input_dev *input; 171 + /* Mutex for fw update to prevent concurrent access */ 172 + struct mutex fw_mutex; 173 + struct wdt87xx_sys_param param; 174 + u8 phys[32]; 175 + }; 176 + 177 + static int wdt87xx_i2c_xfer(struct i2c_client *client, 178 + void *txdata, size_t txlen, 179 + void *rxdata, size_t rxlen) 180 + { 181 + struct i2c_msg msgs[] = { 182 + { 183 + .addr = client->addr, 184 + .flags = 0, 185 + .len = txlen, 186 + .buf = txdata, 187 + }, 188 + { 189 + .addr = client->addr, 190 + .flags = I2C_M_RD, 191 + .len = rxlen, 192 + .buf = rxdata, 193 + }, 194 + }; 195 + int error; 196 + int ret; 197 + 198 + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 199 + if (ret != ARRAY_SIZE(msgs)) { 200 + error = ret < 0 ? ret : -EIO; 201 + dev_err(&client->dev, "%s: i2c transfer failed: %d\n", 202 + __func__, error); 203 + return error; 204 + } 205 + 206 + return 0; 207 + } 208 + 209 + static int wdt87xx_get_string(struct i2c_client *client, u8 str_idx, 210 + u8 *buf, size_t len) 211 + { 212 + u8 tx_buf[] = { 0x22, 0x00, 0x13, 0x0E, str_idx, 0x23, 0x00 }; 213 + u8 rx_buf[PKT_WRITE_SIZE]; 214 + size_t rx_len = len + 2; 215 + int error; 216 + 217 + if (rx_len > sizeof(rx_buf)) 218 + return -EINVAL; 219 + 220 + error = wdt87xx_i2c_xfer(client, tx_buf, sizeof(tx_buf), 221 + rx_buf, rx_len); 222 + if (error) { 223 + dev_err(&client->dev, "get string failed: %d\n", error); 224 + return error; 225 + } 226 + 227 + if (rx_buf[1] != 0x03) { 228 + dev_err(&client->dev, "unexpected response to get string: %d\n", 229 + rx_buf[1]); 230 + return -EINVAL; 231 + } 232 + 233 + rx_len = min_t(size_t, len, rx_buf[0]); 234 + memcpy(buf, &rx_buf[2], rx_len); 235 + 236 + mdelay(WDT_COMMAND_DELAY_MS); 237 + 238 + return 0; 239 + } 240 + 241 + static int wdt87xx_get_feature(struct i2c_client *client, 242 + u8 *buf, size_t buf_size) 243 + { 244 + u8 tx_buf[8]; 245 + u8 rx_buf[PKT_WRITE_SIZE]; 246 + size_t tx_len = 0; 247 + size_t rx_len = buf_size + 2; 248 + int error; 249 + 250 + if (rx_len > sizeof(rx_buf)) 251 + return -EINVAL; 252 + 253 + /* Get feature command packet */ 254 + tx_buf[tx_len++] = 0x22; 255 + tx_buf[tx_len++] = 0x00; 256 + if (buf[CMD_REPORT_ID_OFFSET] > 0xF) { 257 + tx_buf[tx_len++] = 0x30; 258 + tx_buf[tx_len++] = 0x02; 259 + tx_buf[tx_len++] = buf[CMD_REPORT_ID_OFFSET]; 260 + } else { 261 + tx_buf[tx_len++] = 0x30 | buf[CMD_REPORT_ID_OFFSET]; 262 + tx_buf[tx_len++] = 0x02; 263 + } 264 + tx_buf[tx_len++] = 0x23; 265 + tx_buf[tx_len++] = 0x00; 266 + 267 + error = wdt87xx_i2c_xfer(client, tx_buf, tx_len, rx_buf, rx_len); 268 + if (error) { 269 + dev_err(&client->dev, "get feature failed: %d\n", error); 270 + return error; 271 + } 272 + 273 + rx_len = min_t(size_t, buf_size, get_unaligned_le16(rx_buf)); 274 + memcpy(buf, &rx_buf[2], rx_len); 275 + 276 + mdelay(WDT_COMMAND_DELAY_MS); 277 + 278 + return 0; 279 + } 280 + 281 + static int wdt87xx_set_feature(struct i2c_client *client, 282 + const u8 *buf, size_t buf_size) 283 + { 284 + u8 tx_buf[PKT_WRITE_SIZE]; 285 + int tx_len = 0; 286 + int error; 287 + 288 + /* Set feature command packet */ 289 + tx_buf[tx_len++] = 0x22; 290 + tx_buf[tx_len++] = 0x00; 291 + if (buf[CMD_REPORT_ID_OFFSET] > 0xF) { 292 + tx_buf[tx_len++] = 0x30; 293 + tx_buf[tx_len++] = 0x03; 294 + tx_buf[tx_len++] = buf[CMD_REPORT_ID_OFFSET]; 295 + } else { 296 + tx_buf[tx_len++] = 0x30 | buf[CMD_REPORT_ID_OFFSET]; 297 + tx_buf[tx_len++] = 0x03; 298 + } 299 + tx_buf[tx_len++] = 0x23; 300 + tx_buf[tx_len++] = 0x00; 301 + tx_buf[tx_len++] = (buf_size & 0xFF); 302 + tx_buf[tx_len++] = ((buf_size & 0xFF00) >> 8); 303 + 304 + if (tx_len + buf_size > sizeof(tx_buf)) 305 + return -EINVAL; 306 + 307 + memcpy(&tx_buf[tx_len], buf, buf_size); 308 + tx_len += buf_size; 309 + 310 + error = i2c_master_send(client, tx_buf, tx_len); 311 + if (error < 0) { 312 + dev_err(&client->dev, "set feature failed: %d\n", error); 313 + return error; 314 + } 315 + 316 + mdelay(WDT_COMMAND_DELAY_MS); 317 + 318 + return 0; 319 + } 320 + 321 + static int wdt87xx_send_command(struct i2c_client *client, int cmd, int value) 322 + { 323 + u8 cmd_buf[CMD_BUF_SIZE]; 324 + 325 + /* Set the command packet */ 326 + cmd_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_WRITE; 327 + cmd_buf[CMD_TYPE_OFFSET] = VND_SET_COMMAND_DATA; 328 + put_unaligned_le16((u16)cmd, &cmd_buf[CMD_INDEX_OFFSET]); 329 + 330 + switch (cmd) { 331 + case VND_CMD_START: 332 + case VND_CMD_STOP: 333 + case VND_CMD_RESET: 334 + /* Mode selector */ 335 + put_unaligned_le32((value & 0xFF), &cmd_buf[CMD_LENGTH_OFFSET]); 336 + break; 337 + 338 + case VND_CMD_SFLCK: 339 + put_unaligned_le16(CMD_SFLCK_KEY, &cmd_buf[CMD_KEY_OFFSET]); 340 + break; 341 + 342 + case VND_CMD_SFUNL: 343 + put_unaligned_le16(CMD_SFUNL_KEY, &cmd_buf[CMD_KEY_OFFSET]); 344 + break; 345 + 346 + case VND_CMD_ERASE: 347 + case VND_SET_CHECKSUM_CALC: 348 + case VND_SET_CHECKSUM_LENGTH: 349 + put_unaligned_le32(value, &cmd_buf[CMD_KEY_OFFSET]); 350 + break; 351 + 352 + default: 353 + cmd_buf[CMD_REPORT_ID_OFFSET] = 0; 354 + dev_err(&client->dev, "Invalid command: %d\n", cmd); 355 + return -EINVAL; 356 + } 357 + 358 + return wdt87xx_set_feature(client, cmd_buf, sizeof(cmd_buf)); 359 + } 360 + 361 + static int wdt87xx_sw_reset(struct i2c_client *client) 362 + { 363 + int error; 364 + 365 + dev_dbg(&client->dev, "resetting device now\n"); 366 + 367 + error = wdt87xx_send_command(client, VND_CMD_RESET, 0); 368 + if (error) { 369 + dev_err(&client->dev, "reset failed\n"); 370 + return error; 371 + } 372 + 373 + /* Wait the device to be ready */ 374 + msleep(200); 375 + 376 + return 0; 377 + } 378 + 379 + static const void *wdt87xx_get_fw_chunk(const struct firmware *fw, u32 id) 380 + { 381 + size_t pos = FW_PAYLOAD_OFFSET; 382 + u32 chunk_id, chunk_size; 383 + 384 + while (pos < fw->size) { 385 + chunk_id = get_unaligned_le32(fw->data + 386 + pos + FW_CHUNK_ID_OFFSET); 387 + if (chunk_id == id) 388 + return fw->data + pos; 389 + 390 + chunk_size = get_unaligned_le32(fw->data + 391 + pos + FW_CHUNK_SIZE_OFFSET); 392 + pos += chunk_size + 2 * sizeof(u32); /* chunk ID + size */ 393 + } 394 + 395 + return NULL; 396 + } 397 + 398 + static int wdt87xx_get_sysparam(struct i2c_client *client, 399 + struct wdt87xx_sys_param *param) 400 + { 401 + u8 buf[PKT_READ_SIZE]; 402 + int error; 403 + 404 + error = wdt87xx_get_string(client, STRIDX_PARAMETERS, buf, 32); 405 + if (error) { 406 + dev_err(&client->dev, "failed to get parameters\n"); 407 + return error; 408 + } 409 + 410 + param->xmls_id1 = get_unaligned_le16(buf + CTL_PARAM_OFFSET_XMLS_ID1); 411 + param->xmls_id2 = get_unaligned_le16(buf + CTL_PARAM_OFFSET_XMLS_ID2); 412 + param->phy_ch_x = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_CH_X); 413 + param->phy_ch_y = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_CH_Y); 414 + param->phy_w = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_W) / 10; 415 + param->phy_h = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_H) / 10; 416 + 417 + param->max_x = MAX_UNIT_AXIS; 418 + param->max_y = DIV_ROUND_CLOSEST(MAX_UNIT_AXIS * param->phy_h, 419 + param->phy_w); 420 + 421 + error = wdt87xx_get_string(client, STRIDX_PLATFORM_ID, buf, 8); 422 + if (error) { 423 + dev_err(&client->dev, "failed to get platform id\n"); 424 + return error; 425 + } 426 + 427 + param->plat_id = buf[1]; 428 + 429 + buf[0] = 0xf2; 430 + error = wdt87xx_get_feature(client, buf, 16); 431 + if (error) { 432 + dev_err(&client->dev, "failed to get firmware id\n"); 433 + return error; 434 + } 435 + 436 + if (buf[0] != 0xf2) { 437 + dev_err(&client->dev, "wrong id of fw response: 0x%x\n", 438 + buf[0]); 439 + return -EINVAL; 440 + } 441 + 442 + param->fw_id = get_unaligned_le16(&buf[1]); 443 + 444 + dev_info(&client->dev, 445 + "fw_id: 0x%x, plat_id: 0x%x\nxml_id1: %04x, xml_id2: %04x\n", 446 + param->fw_id, param->plat_id, 447 + param->xmls_id1, param->xmls_id2); 448 + 449 + return 0; 450 + } 451 + 452 + static int wdt87xx_validate_firmware(struct wdt87xx_data *wdt, 453 + const struct firmware *fw) 454 + { 455 + const void *fw_chunk; 456 + u32 data1, data2; 457 + u32 size; 458 + u8 fw_chip_id; 459 + u8 chip_id; 460 + 461 + data1 = get_unaligned_le32(fw->data + FW_FOURCC1_OFFSET); 462 + data2 = get_unaligned_le32(fw->data + FW_FOURCC2_OFFSET); 463 + if (data1 != FOURCC_ID_RIFF || data2 != FOURCC_ID_WHIF) { 464 + dev_err(&wdt->client->dev, "check fw tag failed\n"); 465 + return -EINVAL; 466 + } 467 + 468 + size = get_unaligned_le32(fw->data + FW_SIZE_OFFSET); 469 + if (size != fw->size) { 470 + dev_err(&wdt->client->dev, 471 + "fw size mismatch: expected %d, actual %zd\n", 472 + size, fw->size); 473 + return -EINVAL; 474 + } 475 + 476 + /* 477 + * Get the chip_id from the firmware. Make sure that it is the 478 + * right controller to do the firmware and config update. 479 + */ 480 + fw_chunk = wdt87xx_get_fw_chunk(fw, CHUNK_ID_FRWR); 481 + if (!fw_chunk) { 482 + dev_err(&wdt->client->dev, 483 + "unable to locate firmware chunk\n"); 484 + return -EINVAL; 485 + } 486 + 487 + fw_chip_id = (get_unaligned_le32(fw_chunk + 488 + FW_CHUNK_VERSION_OFFSET) >> 12) & 0xF; 489 + chip_id = (wdt->param.fw_id >> 12) & 0xF; 490 + 491 + if (fw_chip_id != chip_id) { 492 + dev_err(&wdt->client->dev, 493 + "fw version mismatch: fw %d vs. chip %d\n", 494 + fw_chip_id, chip_id); 495 + return -ENODEV; 496 + } 497 + 498 + return 0; 499 + } 500 + 501 + static int wdt87xx_validate_fw_chunk(const void *data, int id) 502 + { 503 + if (id == CHUNK_ID_FRWR) { 504 + u32 fw_id; 505 + 506 + fw_id = get_unaligned_le32(data + FW_CHUNK_PAYLOAD_OFFSET); 507 + if (fw_id != WDT_FIRMWARE_ID) 508 + return -EINVAL; 509 + } 510 + 511 + return 0; 512 + } 513 + 514 + static int wdt87xx_write_data(struct i2c_client *client, const char *data, 515 + u32 address, int length) 516 + { 517 + u16 packet_size; 518 + int count = 0; 519 + int error; 520 + u8 pkt_buf[PKT_BUF_SIZE]; 521 + 522 + /* Address and length should be 4 bytes aligned */ 523 + if ((address & 0x3) != 0 || (length & 0x3) != 0) { 524 + dev_err(&client->dev, 525 + "addr & len must be 4 bytes aligned %x, %x\n", 526 + address, length); 527 + return -EINVAL; 528 + } 529 + 530 + while (length) { 531 + packet_size = min(length, PACKET_SIZE); 532 + 533 + pkt_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_WRITE; 534 + pkt_buf[CMD_TYPE_OFFSET] = VND_SET_DATA; 535 + put_unaligned_le16(packet_size, &pkt_buf[CMD_INDEX_OFFSET]); 536 + put_unaligned_le32(address, &pkt_buf[CMD_LENGTH_OFFSET]); 537 + memcpy(&pkt_buf[CMD_DATA_OFFSET], data, packet_size); 538 + 539 + error = wdt87xx_set_feature(client, pkt_buf, sizeof(pkt_buf)); 540 + if (error) 541 + return error; 542 + 543 + length -= packet_size; 544 + data += packet_size; 545 + address += packet_size; 546 + 547 + /* Wait for the controller to finish the write */ 548 + mdelay(WDT_FLASH_WRITE_DELAY_MS); 549 + 550 + if ((++count % 32) == 0) { 551 + /* Delay for fw to clear watch dog */ 552 + msleep(20); 553 + } 554 + } 555 + 556 + return 0; 557 + } 558 + 559 + static u16 misr(u16 cur_value, u8 new_value) 560 + { 561 + u32 a, b; 562 + u32 bit0; 563 + u32 y; 564 + 565 + a = cur_value; 566 + b = new_value; 567 + bit0 = a ^ (b & 1); 568 + bit0 ^= a >> 1; 569 + bit0 ^= a >> 2; 570 + bit0 ^= a >> 4; 571 + bit0 ^= a >> 5; 572 + bit0 ^= a >> 7; 573 + bit0 ^= a >> 11; 574 + bit0 ^= a >> 15; 575 + y = (a << 1) ^ b; 576 + y = (y & ~1) | (bit0 & 1); 577 + 578 + return (u16)y; 579 + } 580 + 581 + static u16 wdt87xx_calculate_checksum(const u8 *data, size_t length) 582 + { 583 + u16 checksum = 0; 584 + size_t i; 585 + 586 + for (i = 0; i < length; i++) 587 + checksum = misr(checksum, data[i]); 588 + 589 + return checksum; 590 + } 591 + 592 + static int wdt87xx_get_checksum(struct i2c_client *client, u16 *checksum, 593 + u32 address, int length) 594 + { 595 + int error; 596 + int time_delay; 597 + u8 pkt_buf[PKT_BUF_SIZE]; 598 + u8 cmd_buf[CMD_BUF_SIZE]; 599 + 600 + error = wdt87xx_send_command(client, VND_SET_CHECKSUM_LENGTH, length); 601 + if (error) { 602 + dev_err(&client->dev, "failed to set checksum length\n"); 603 + return error; 604 + } 605 + 606 + error = wdt87xx_send_command(client, VND_SET_CHECKSUM_CALC, address); 607 + if (error) { 608 + dev_err(&client->dev, "failed to set checksum address\n"); 609 + return error; 610 + } 611 + 612 + /* Wait the operation to complete */ 613 + time_delay = DIV_ROUND_UP(length, 1024); 614 + msleep(time_delay * 30); 615 + 616 + memset(cmd_buf, 0, sizeof(cmd_buf)); 617 + cmd_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_READ; 618 + cmd_buf[CMD_TYPE_OFFSET] = VND_GET_CHECKSUM; 619 + error = wdt87xx_set_feature(client, cmd_buf, sizeof(cmd_buf)); 620 + if (error) { 621 + dev_err(&client->dev, "failed to request checksum\n"); 622 + return error; 623 + } 624 + 625 + memset(pkt_buf, 0, sizeof(pkt_buf)); 626 + pkt_buf[CMD_REPORT_ID_OFFSET] = VND_READ_DATA; 627 + error = wdt87xx_get_feature(client, pkt_buf, sizeof(pkt_buf)); 628 + if (error) { 629 + dev_err(&client->dev, "failed to read checksum\n"); 630 + return error; 631 + } 632 + 633 + *checksum = get_unaligned_le16(&pkt_buf[CMD_DATA_OFFSET]); 634 + return 0; 635 + } 636 + 637 + static int wdt87xx_write_firmware(struct i2c_client *client, const void *chunk) 638 + { 639 + u32 start_addr = get_unaligned_le32(chunk + FW_CHUNK_TGT_START_OFFSET); 640 + u32 size = get_unaligned_le32(chunk + FW_CHUNK_PAYLOAD_LEN_OFFSET); 641 + const void *data = chunk + FW_CHUNK_PAYLOAD_OFFSET; 642 + int error; 643 + int err1; 644 + int page_size; 645 + int retry = 0; 646 + u16 device_checksum, firmware_checksum; 647 + 648 + dev_dbg(&client->dev, "start 4k page program\n"); 649 + 650 + error = wdt87xx_send_command(client, VND_CMD_STOP, MODE_STOP); 651 + if (error) { 652 + dev_err(&client->dev, "stop report mode failed\n"); 653 + return error; 654 + } 655 + 656 + error = wdt87xx_send_command(client, VND_CMD_SFUNL, 0); 657 + if (error) { 658 + dev_err(&client->dev, "unlock failed\n"); 659 + goto out_enable_reporting; 660 + } 661 + 662 + mdelay(10); 663 + 664 + while (size) { 665 + dev_dbg(&client->dev, "%s: %x, %x\n", __func__, 666 + start_addr, size); 667 + 668 + page_size = min_t(u32, size, PG_SIZE); 669 + size -= page_size; 670 + 671 + for (retry = 0; retry < MAX_RETRIES; retry++) { 672 + error = wdt87xx_send_command(client, VND_CMD_ERASE, 673 + start_addr); 674 + if (error) { 675 + dev_err(&client->dev, 676 + "erase failed at %#08x\n", start_addr); 677 + break; 678 + } 679 + 680 + msleep(50); 681 + 682 + error = wdt87xx_write_data(client, data, start_addr, 683 + page_size); 684 + if (error) { 685 + dev_err(&client->dev, 686 + "write failed at %#08x (%d bytes)\n", 687 + start_addr, page_size); 688 + break; 689 + } 690 + 691 + error = wdt87xx_get_checksum(client, &device_checksum, 692 + start_addr, page_size); 693 + if (error) { 694 + dev_err(&client->dev, 695 + "failed to retrieve checksum for %#08x (len: %d)\n", 696 + start_addr, page_size); 697 + break; 698 + } 699 + 700 + firmware_checksum = 701 + wdt87xx_calculate_checksum(data, page_size); 702 + 703 + if (device_checksum == firmware_checksum) 704 + break; 705 + 706 + dev_err(&client->dev, 707 + "checksum fail: %d vs %d, retry %d\n", 708 + device_checksum, firmware_checksum, retry); 709 + } 710 + 711 + if (retry == MAX_RETRIES) { 712 + dev_err(&client->dev, "page write failed\n"); 713 + error = -EIO; 714 + goto out_lock_device; 715 + } 716 + 717 + start_addr = start_addr + page_size; 718 + data = data + page_size; 719 + } 720 + 721 + out_lock_device: 722 + err1 = wdt87xx_send_command(client, VND_CMD_SFLCK, 0); 723 + if (err1) 724 + dev_err(&client->dev, "lock failed\n"); 725 + 726 + mdelay(10); 727 + 728 + out_enable_reporting: 729 + err1 = wdt87xx_send_command(client, VND_CMD_START, 0); 730 + if (err1) 731 + dev_err(&client->dev, "start to report failed\n"); 732 + 733 + return error ? error : err1; 734 + } 735 + 736 + static int wdt87xx_load_chunk(struct i2c_client *client, 737 + const struct firmware *fw, u32 ck_id) 738 + { 739 + const void *chunk; 740 + int error; 741 + 742 + chunk = wdt87xx_get_fw_chunk(fw, ck_id); 743 + if (!chunk) { 744 + dev_err(&client->dev, "unable to locate chunk (type %d)\n", 745 + ck_id); 746 + return -EINVAL; 747 + } 748 + 749 + error = wdt87xx_validate_fw_chunk(chunk, ck_id); 750 + if (error) { 751 + dev_err(&client->dev, "invalid chunk (type %d): %d\n", 752 + ck_id, error); 753 + return error; 754 + } 755 + 756 + error = wdt87xx_write_firmware(client, chunk); 757 + if (error) { 758 + dev_err(&client->dev, 759 + "failed to write fw chunk (type %d): %d\n", 760 + ck_id, error); 761 + return error; 762 + } 763 + 764 + return 0; 765 + } 766 + 767 + static int wdt87xx_do_update_firmware(struct i2c_client *client, 768 + const struct firmware *fw, 769 + unsigned int chunk_id) 770 + { 771 + struct wdt87xx_data *wdt = i2c_get_clientdata(client); 772 + int error; 773 + 774 + error = wdt87xx_validate_firmware(wdt, fw); 775 + if (error) 776 + return error; 777 + 778 + error = mutex_lock_interruptible(&wdt->fw_mutex); 779 + if (error) 780 + return error; 781 + 782 + disable_irq(client->irq); 783 + 784 + error = wdt87xx_load_chunk(client, fw, chunk_id); 785 + if (error) { 786 + dev_err(&client->dev, 787 + "firmware load failed (type: %d): %d\n", 788 + chunk_id, error); 789 + goto out; 790 + } 791 + 792 + error = wdt87xx_sw_reset(client); 793 + if (error) { 794 + dev_err(&client->dev, "soft reset failed: %d\n", error); 795 + goto out; 796 + } 797 + 798 + /* Refresh the parameters */ 799 + error = wdt87xx_get_sysparam(client, &wdt->param); 800 + if (error) 801 + dev_err(&client->dev, 802 + "failed to refresh system paramaters: %d\n", error); 803 + out: 804 + enable_irq(client->irq); 805 + mutex_unlock(&wdt->fw_mutex); 806 + 807 + return error ? error : 0; 808 + } 809 + 810 + static int wdt87xx_update_firmware(struct device *dev, 811 + const char *fw_name, unsigned int chunk_id) 812 + { 813 + struct i2c_client *client = to_i2c_client(dev); 814 + const struct firmware *fw; 815 + int error; 816 + 817 + error = request_firmware(&fw, fw_name, dev); 818 + if (error) { 819 + dev_err(&client->dev, "unable to retrieve firmware %s: %d\n", 820 + fw_name, error); 821 + return error; 822 + } 823 + 824 + error = wdt87xx_do_update_firmware(client, fw, chunk_id); 825 + 826 + release_firmware(fw); 827 + 828 + return error ? error : 0; 829 + } 830 + 831 + static ssize_t config_csum_show(struct device *dev, 832 + struct device_attribute *attr, char *buf) 833 + { 834 + struct i2c_client *client = to_i2c_client(dev); 835 + struct wdt87xx_data *wdt = i2c_get_clientdata(client); 836 + u32 cfg_csum; 837 + 838 + cfg_csum = wdt->param.xmls_id1; 839 + cfg_csum = (cfg_csum << 16) | wdt->param.xmls_id2; 840 + 841 + return scnprintf(buf, PAGE_SIZE, "%x\n", cfg_csum); 842 + } 843 + 844 + static ssize_t fw_version_show(struct device *dev, 845 + struct device_attribute *attr, char *buf) 846 + { 847 + struct i2c_client *client = to_i2c_client(dev); 848 + struct wdt87xx_data *wdt = i2c_get_clientdata(client); 849 + 850 + return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.fw_id); 851 + } 852 + 853 + static ssize_t plat_id_show(struct device *dev, 854 + struct device_attribute *attr, char *buf) 855 + { 856 + struct i2c_client *client = to_i2c_client(dev); 857 + struct wdt87xx_data *wdt = i2c_get_clientdata(client); 858 + 859 + return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.plat_id); 860 + } 861 + 862 + static ssize_t update_config_store(struct device *dev, 863 + struct device_attribute *attr, 864 + const char *buf, size_t count) 865 + { 866 + int error; 867 + 868 + error = wdt87xx_update_firmware(dev, WDT87XX_CFG_NAME, CHUNK_ID_CNFG); 869 + 870 + return error ? error : count; 871 + } 872 + 873 + static ssize_t update_fw_store(struct device *dev, 874 + struct device_attribute *attr, 875 + const char *buf, size_t count) 876 + { 877 + int error; 878 + 879 + error = wdt87xx_update_firmware(dev, WDT87XX_FW_NAME, CHUNK_ID_FRWR); 880 + 881 + return error ? error : count; 882 + } 883 + 884 + static DEVICE_ATTR_RO(config_csum); 885 + static DEVICE_ATTR_RO(fw_version); 886 + static DEVICE_ATTR_RO(plat_id); 887 + static DEVICE_ATTR_WO(update_config); 888 + static DEVICE_ATTR_WO(update_fw); 889 + 890 + static struct attribute *wdt87xx_attrs[] = { 891 + &dev_attr_config_csum.attr, 892 + &dev_attr_fw_version.attr, 893 + &dev_attr_plat_id.attr, 894 + &dev_attr_update_config.attr, 895 + &dev_attr_update_fw.attr, 896 + NULL 897 + }; 898 + 899 + static const struct attribute_group wdt87xx_attr_group = { 900 + .attrs = wdt87xx_attrs, 901 + }; 902 + 903 + static void wdt87xx_report_contact(struct input_dev *input, 904 + struct wdt87xx_sys_param *param, 905 + u8 *buf) 906 + { 907 + int finger_id; 908 + u32 x, y; 909 + u8 w, p; 910 + 911 + finger_id = (buf[FINGER_EV_V1_OFFSET_ID] >> 3) - 1; 912 + if (finger_id < 0) 913 + return; 914 + 915 + /* Check if this is an active contact */ 916 + if (!(buf[FINGER_EV_V1_OFFSET_ID] & 0x1)) 917 + return; 918 + 919 + w = buf[FINGER_EV_V1_OFFSET_W]; 920 + p = buf[FINGER_EV_V1_OFFSET_P]; 921 + 922 + x = get_unaligned_le16(buf + FINGER_EV_V1_OFFSET_X); 923 + 924 + y = get_unaligned_le16(buf + FINGER_EV_V1_OFFSET_Y); 925 + y = DIV_ROUND_CLOSEST(y * param->phy_h, param->phy_w); 926 + 927 + /* Refuse incorrect coordinates */ 928 + if (x > param->max_x || y > param->max_y) 929 + return; 930 + 931 + dev_dbg(input->dev.parent, "tip on (%d), x(%d), y(%d)\n", 932 + finger_id, x, y); 933 + 934 + input_mt_slot(input, finger_id); 935 + input_mt_report_slot_state(input, MT_TOOL_FINGER, 1); 936 + input_report_abs(input, ABS_MT_TOUCH_MAJOR, w); 937 + input_report_abs(input, ABS_MT_PRESSURE, p); 938 + input_report_abs(input, ABS_MT_POSITION_X, x); 939 + input_report_abs(input, ABS_MT_POSITION_Y, y); 940 + } 941 + 942 + static irqreturn_t wdt87xx_ts_interrupt(int irq, void *dev_id) 943 + { 944 + struct wdt87xx_data *wdt = dev_id; 945 + struct i2c_client *client = wdt->client; 946 + int i, fingers; 947 + int error; 948 + u8 raw_buf[WDT_V1_RAW_BUF_COUNT] = {0}; 949 + 950 + error = i2c_master_recv(client, raw_buf, WDT_V1_RAW_BUF_COUNT); 951 + if (error < 0) { 952 + dev_err(&client->dev, "read v1 raw data failed: %d\n", error); 953 + goto irq_exit; 954 + } 955 + 956 + fingers = raw_buf[TOUCH_PK_V1_OFFSET_FNGR_NUM]; 957 + if (!fingers) 958 + goto irq_exit; 959 + 960 + for (i = 0; i < WDT_MAX_FINGER; i++) 961 + wdt87xx_report_contact(wdt->input, 962 + &wdt->param, 963 + &raw_buf[TOUCH_PK_V1_OFFSET_EVENT + 964 + i * FINGER_EV_V1_SIZE]); 965 + 966 + input_mt_sync_frame(wdt->input); 967 + input_sync(wdt->input); 968 + 969 + irq_exit: 970 + return IRQ_HANDLED; 971 + } 972 + 973 + static int wdt87xx_ts_create_input_device(struct wdt87xx_data *wdt) 974 + { 975 + struct device *dev = &wdt->client->dev; 976 + struct input_dev *input; 977 + unsigned int res = DIV_ROUND_CLOSEST(MAX_UNIT_AXIS, wdt->param.phy_w); 978 + int error; 979 + 980 + input = devm_input_allocate_device(dev); 981 + if (!input) { 982 + dev_err(dev, "failed to allocate input device\n"); 983 + return -ENOMEM; 984 + } 985 + wdt->input = input; 986 + 987 + input->name = "WDT87xx Touchscreen"; 988 + input->id.bustype = BUS_I2C; 989 + input->phys = wdt->phys; 990 + 991 + input_set_abs_params(input, ABS_MT_POSITION_X, 0, 992 + wdt->param.max_x, 0, 0); 993 + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 994 + wdt->param.max_y, 0, 0); 995 + input_abs_set_res(input, ABS_MT_POSITION_X, res); 996 + input_abs_set_res(input, ABS_MT_POSITION_Y, res); 997 + 998 + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0); 999 + input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xFF, 0, 0); 1000 + 1001 + input_mt_init_slots(input, WDT_MAX_FINGER, 1002 + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 1003 + 1004 + error = input_register_device(input); 1005 + if (error) { 1006 + dev_err(dev, "failed to register input device: %d\n", error); 1007 + return error; 1008 + } 1009 + 1010 + return 0; 1011 + } 1012 + 1013 + static int wdt87xx_ts_probe(struct i2c_client *client, 1014 + const struct i2c_device_id *id) 1015 + { 1016 + struct wdt87xx_data *wdt; 1017 + int error; 1018 + 1019 + dev_dbg(&client->dev, "adapter=%d, client irq: %d\n", 1020 + client->adapter->nr, client->irq); 1021 + 1022 + /* Check if the I2C function is ok in this adaptor */ 1023 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 1024 + return -ENXIO; 1025 + 1026 + wdt = devm_kzalloc(&client->dev, sizeof(*wdt), GFP_KERNEL); 1027 + if (!wdt) 1028 + return -ENOMEM; 1029 + 1030 + wdt->client = client; 1031 + mutex_init(&wdt->fw_mutex); 1032 + i2c_set_clientdata(client, wdt); 1033 + 1034 + snprintf(wdt->phys, sizeof(wdt->phys), "i2c-%u-%04x/input0", 1035 + client->adapter->nr, client->addr); 1036 + 1037 + error = wdt87xx_get_sysparam(client, &wdt->param); 1038 + if (error) 1039 + return error; 1040 + 1041 + error = wdt87xx_ts_create_input_device(wdt); 1042 + if (error) 1043 + return error; 1044 + 1045 + error = devm_request_threaded_irq(&client->dev, client->irq, 1046 + NULL, wdt87xx_ts_interrupt, 1047 + IRQF_ONESHOT, 1048 + client->name, wdt); 1049 + if (error) { 1050 + dev_err(&client->dev, "request irq failed: %d\n", error); 1051 + return error; 1052 + } 1053 + 1054 + error = sysfs_create_group(&client->dev.kobj, &wdt87xx_attr_group); 1055 + if (error) { 1056 + dev_err(&client->dev, "create sysfs failed: %d\n", error); 1057 + return error; 1058 + } 1059 + 1060 + return 0; 1061 + } 1062 + 1063 + static int wdt87xx_ts_remove(struct i2c_client *client) 1064 + { 1065 + sysfs_remove_group(&client->dev.kobj, &wdt87xx_attr_group); 1066 + 1067 + return 0; 1068 + } 1069 + 1070 + static int __maybe_unused wdt87xx_suspend(struct device *dev) 1071 + { 1072 + struct i2c_client *client = to_i2c_client(dev); 1073 + int error; 1074 + 1075 + disable_irq(client->irq); 1076 + 1077 + error = wdt87xx_send_command(client, VND_CMD_STOP, MODE_IDLE); 1078 + if (error) { 1079 + enable_irq(client->irq); 1080 + dev_err(&client->dev, 1081 + "failed to stop device when suspending: %d\n", 1082 + error); 1083 + return error; 1084 + } 1085 + 1086 + return 0; 1087 + } 1088 + 1089 + static int __maybe_unused wdt87xx_resume(struct device *dev) 1090 + { 1091 + struct i2c_client *client = to_i2c_client(dev); 1092 + int error; 1093 + 1094 + /* 1095 + * The chip may have been reset while system is resuming, 1096 + * give it some time to settle. 1097 + */ 1098 + mdelay(100); 1099 + 1100 + error = wdt87xx_send_command(client, VND_CMD_START, 0); 1101 + if (error) 1102 + dev_err(&client->dev, 1103 + "failed to start device when resuming: %d\n", 1104 + error); 1105 + 1106 + enable_irq(client->irq); 1107 + 1108 + return 0; 1109 + } 1110 + 1111 + static SIMPLE_DEV_PM_OPS(wdt87xx_pm_ops, wdt87xx_suspend, wdt87xx_resume); 1112 + 1113 + static const struct i2c_device_id wdt87xx_dev_id[] = { 1114 + { WDT87XX_NAME, 0 }, 1115 + { } 1116 + }; 1117 + MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id); 1118 + 1119 + static const struct acpi_device_id wdt87xx_acpi_id[] = { 1120 + { "WDHT0001", 0 }, 1121 + { } 1122 + }; 1123 + MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id); 1124 + 1125 + static struct i2c_driver wdt87xx_driver = { 1126 + .probe = wdt87xx_ts_probe, 1127 + .remove = wdt87xx_ts_remove, 1128 + .id_table = wdt87xx_dev_id, 1129 + .driver = { 1130 + .name = WDT87XX_NAME, 1131 + .pm = &wdt87xx_pm_ops, 1132 + .acpi_match_table = ACPI_PTR(wdt87xx_acpi_id), 1133 + }, 1134 + }; 1135 + module_i2c_driver(wdt87xx_driver); 1136 + 1137 + MODULE_AUTHOR("HN Chen <hn.chen@weidahitech.com>"); 1138 + MODULE_DESCRIPTION("WeidaHiTech WDT87XX Touchscreen driver"); 1139 + MODULE_VERSION(WDT87XX_DRV_VER); 1140 + MODULE_LICENSE("GPL");