0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/i2c.h>
0013 #include <linux/input.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/delay.h>
0016 #include <linux/irq.h>
0017 #include <linux/io.h>
0018 #include <linux/module.h>
0019 #include <linux/slab.h>
0020 #include <linux/firmware.h>
0021 #include <linux/input/mt.h>
0022 #include <linux/acpi.h>
0023 #include <asm/unaligned.h>
0024
0025 #define WDT87XX_NAME "wdt87xx_i2c"
0026 #define WDT87XX_FW_NAME "wdt87xx_fw.bin"
0027 #define WDT87XX_CFG_NAME "wdt87xx_cfg.bin"
0028
0029 #define MODE_ACTIVE 0x01
0030 #define MODE_READY 0x02
0031 #define MODE_IDLE 0x03
0032 #define MODE_SLEEP 0x04
0033 #define MODE_STOP 0xFF
0034
0035 #define WDT_MAX_FINGER 10
0036 #define WDT_RAW_BUF_COUNT 54
0037 #define WDT_V1_RAW_BUF_COUNT 74
0038 #define WDT_FIRMWARE_ID 0xa9e368f5
0039
0040 #define PG_SIZE 0x1000
0041 #define MAX_RETRIES 3
0042
0043 #define MAX_UNIT_AXIS 0x7FFF
0044
0045 #define PKT_READ_SIZE 72
0046 #define PKT_WRITE_SIZE 80
0047
0048
0049 #define FINGER_EV_OFFSET_ID 0
0050 #define FINGER_EV_OFFSET_X 1
0051 #define FINGER_EV_OFFSET_Y 3
0052 #define FINGER_EV_SIZE 5
0053
0054 #define FINGER_EV_V1_OFFSET_ID 0
0055 #define FINGER_EV_V1_OFFSET_W 1
0056 #define FINGER_EV_V1_OFFSET_P 2
0057 #define FINGER_EV_V1_OFFSET_X 3
0058 #define FINGER_EV_V1_OFFSET_Y 5
0059 #define FINGER_EV_V1_SIZE 7
0060
0061
0062 #define TOUCH_PK_OFFSET_REPORT_ID 0
0063 #define TOUCH_PK_OFFSET_EVENT 1
0064 #define TOUCH_PK_OFFSET_SCAN_TIME 51
0065 #define TOUCH_PK_OFFSET_FNGR_NUM 53
0066
0067 #define TOUCH_PK_V1_OFFSET_REPORT_ID 0
0068 #define TOUCH_PK_V1_OFFSET_EVENT 1
0069 #define TOUCH_PK_V1_OFFSET_SCAN_TIME 71
0070 #define TOUCH_PK_V1_OFFSET_FNGR_NUM 73
0071
0072
0073 #define CTL_PARAM_OFFSET_FW_ID 0
0074 #define CTL_PARAM_OFFSET_PLAT_ID 2
0075 #define CTL_PARAM_OFFSET_XMLS_ID1 4
0076 #define CTL_PARAM_OFFSET_XMLS_ID2 6
0077 #define CTL_PARAM_OFFSET_PHY_CH_X 8
0078 #define CTL_PARAM_OFFSET_PHY_CH_Y 10
0079 #define CTL_PARAM_OFFSET_PHY_X0 12
0080 #define CTL_PARAM_OFFSET_PHY_X1 14
0081 #define CTL_PARAM_OFFSET_PHY_Y0 16
0082 #define CTL_PARAM_OFFSET_PHY_Y1 18
0083 #define CTL_PARAM_OFFSET_PHY_W 22
0084 #define CTL_PARAM_OFFSET_PHY_H 24
0085 #define CTL_PARAM_OFFSET_FACTOR 32
0086
0087
0088 #define WDT_GD_DEVICE 1
0089 #define DEV_DESC_OFFSET_VID 8
0090 #define DEV_DESC_OFFSET_PID 10
0091
0092
0093 #define PACKET_SIZE 56
0094 #define VND_REQ_READ 0x06
0095 #define VND_READ_DATA 0x07
0096 #define VND_REQ_WRITE 0x08
0097
0098 #define VND_CMD_START 0x00
0099 #define VND_CMD_STOP 0x01
0100 #define VND_CMD_RESET 0x09
0101
0102 #define VND_CMD_ERASE 0x1A
0103
0104 #define VND_GET_CHECKSUM 0x66
0105
0106 #define VND_SET_DATA 0x83
0107 #define VND_SET_COMMAND_DATA 0x84
0108 #define VND_SET_CHECKSUM_CALC 0x86
0109 #define VND_SET_CHECKSUM_LENGTH 0x87
0110
0111 #define VND_CMD_SFLCK 0xFC
0112 #define VND_CMD_SFUNL 0xFD
0113
0114 #define CMD_SFLCK_KEY 0xC39B
0115 #define CMD_SFUNL_KEY 0x95DA
0116
0117 #define STRIDX_PLATFORM_ID 0x80
0118 #define STRIDX_PARAMETERS 0x81
0119
0120 #define CMD_BUF_SIZE 8
0121 #define PKT_BUF_SIZE 64
0122
0123
0124 #define CMD_REPORT_ID_OFFSET 0x0
0125 #define CMD_TYPE_OFFSET 0x1
0126 #define CMD_INDEX_OFFSET 0x2
0127 #define CMD_KEY_OFFSET 0x3
0128 #define CMD_LENGTH_OFFSET 0x4
0129 #define CMD_DATA_OFFSET 0x8
0130
0131
0132 #define FOURCC_ID_RIFF 0x46464952
0133 #define FOURCC_ID_WHIF 0x46494857
0134 #define FOURCC_ID_FRMT 0x544D5246
0135 #define FOURCC_ID_FRWR 0x52575246
0136 #define FOURCC_ID_CNFG 0x47464E43
0137
0138 #define CHUNK_ID_FRMT FOURCC_ID_FRMT
0139 #define CHUNK_ID_FRWR FOURCC_ID_FRWR
0140 #define CHUNK_ID_CNFG FOURCC_ID_CNFG
0141
0142 #define FW_FOURCC1_OFFSET 0
0143 #define FW_SIZE_OFFSET 4
0144 #define FW_FOURCC2_OFFSET 8
0145 #define FW_PAYLOAD_OFFSET 40
0146
0147 #define FW_CHUNK_ID_OFFSET 0
0148 #define FW_CHUNK_SIZE_OFFSET 4
0149 #define FW_CHUNK_TGT_START_OFFSET 8
0150 #define FW_CHUNK_PAYLOAD_LEN_OFFSET 12
0151 #define FW_CHUNK_SRC_START_OFFSET 16
0152 #define FW_CHUNK_VERSION_OFFSET 20
0153 #define FW_CHUNK_ATTR_OFFSET 24
0154 #define FW_CHUNK_PAYLOAD_OFFSET 32
0155
0156
0157 #define WDT_COMMAND_DELAY_MS 2
0158 #define WDT_FLASH_WRITE_DELAY_MS 4
0159 #define WDT_FLASH_ERASE_DELAY_MS 200
0160 #define WDT_FW_RESET_TIME 2500
0161
0162 struct wdt87xx_sys_param {
0163 u16 fw_id;
0164 u16 plat_id;
0165 u16 xmls_id1;
0166 u16 xmls_id2;
0167 u16 phy_ch_x;
0168 u16 phy_ch_y;
0169 u16 phy_w;
0170 u16 phy_h;
0171 u16 scaling_factor;
0172 u32 max_x;
0173 u32 max_y;
0174 u16 vendor_id;
0175 u16 product_id;
0176 };
0177
0178 struct wdt87xx_data {
0179 struct i2c_client *client;
0180 struct input_dev *input;
0181
0182 struct mutex fw_mutex;
0183 struct wdt87xx_sys_param param;
0184 u8 phys[32];
0185 };
0186
0187 static int wdt87xx_i2c_xfer(struct i2c_client *client,
0188 void *txdata, size_t txlen,
0189 void *rxdata, size_t rxlen)
0190 {
0191 struct i2c_msg msgs[] = {
0192 {
0193 .addr = client->addr,
0194 .flags = 0,
0195 .len = txlen,
0196 .buf = txdata,
0197 },
0198 {
0199 .addr = client->addr,
0200 .flags = I2C_M_RD,
0201 .len = rxlen,
0202 .buf = rxdata,
0203 },
0204 };
0205 int error;
0206 int ret;
0207
0208 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
0209 if (ret != ARRAY_SIZE(msgs)) {
0210 error = ret < 0 ? ret : -EIO;
0211 dev_err(&client->dev, "%s: i2c transfer failed: %d\n",
0212 __func__, error);
0213 return error;
0214 }
0215
0216 return 0;
0217 }
0218
0219 static int wdt87xx_get_desc(struct i2c_client *client, u8 desc_idx,
0220 u8 *buf, size_t len)
0221 {
0222 u8 tx_buf[] = { 0x22, 0x00, 0x10, 0x0E, 0x23, 0x00 };
0223 int error;
0224
0225 tx_buf[2] |= desc_idx & 0xF;
0226
0227 error = wdt87xx_i2c_xfer(client, tx_buf, sizeof(tx_buf),
0228 buf, len);
0229 if (error) {
0230 dev_err(&client->dev, "get desc failed: %d\n", error);
0231 return error;
0232 }
0233
0234 if (buf[0] != len) {
0235 dev_err(&client->dev, "unexpected response to get desc: %d\n",
0236 buf[0]);
0237 return -EINVAL;
0238 }
0239
0240 mdelay(WDT_COMMAND_DELAY_MS);
0241
0242 return 0;
0243 }
0244
0245 static int wdt87xx_get_string(struct i2c_client *client, u8 str_idx,
0246 u8 *buf, size_t len)
0247 {
0248 u8 tx_buf[] = { 0x22, 0x00, 0x13, 0x0E, str_idx, 0x23, 0x00 };
0249 u8 rx_buf[PKT_WRITE_SIZE];
0250 size_t rx_len = len + 2;
0251 int error;
0252
0253 if (rx_len > sizeof(rx_buf))
0254 return -EINVAL;
0255
0256 error = wdt87xx_i2c_xfer(client, tx_buf, sizeof(tx_buf),
0257 rx_buf, rx_len);
0258 if (error) {
0259 dev_err(&client->dev, "get string failed: %d\n", error);
0260 return error;
0261 }
0262
0263 if (rx_buf[1] != 0x03) {
0264 dev_err(&client->dev, "unexpected response to get string: %d\n",
0265 rx_buf[1]);
0266 return -EINVAL;
0267 }
0268
0269 rx_len = min_t(size_t, len, rx_buf[0]);
0270 memcpy(buf, &rx_buf[2], rx_len);
0271
0272 mdelay(WDT_COMMAND_DELAY_MS);
0273
0274 return 0;
0275 }
0276
0277 static int wdt87xx_get_feature(struct i2c_client *client,
0278 u8 *buf, size_t buf_size)
0279 {
0280 u8 tx_buf[8];
0281 u8 rx_buf[PKT_WRITE_SIZE];
0282 size_t tx_len = 0;
0283 size_t rx_len = buf_size + 2;
0284 int error;
0285
0286 if (rx_len > sizeof(rx_buf))
0287 return -EINVAL;
0288
0289
0290 tx_buf[tx_len++] = 0x22;
0291 tx_buf[tx_len++] = 0x00;
0292 if (buf[CMD_REPORT_ID_OFFSET] > 0xF) {
0293 tx_buf[tx_len++] = 0x30;
0294 tx_buf[tx_len++] = 0x02;
0295 tx_buf[tx_len++] = buf[CMD_REPORT_ID_OFFSET];
0296 } else {
0297 tx_buf[tx_len++] = 0x30 | buf[CMD_REPORT_ID_OFFSET];
0298 tx_buf[tx_len++] = 0x02;
0299 }
0300 tx_buf[tx_len++] = 0x23;
0301 tx_buf[tx_len++] = 0x00;
0302
0303 error = wdt87xx_i2c_xfer(client, tx_buf, tx_len, rx_buf, rx_len);
0304 if (error) {
0305 dev_err(&client->dev, "get feature failed: %d\n", error);
0306 return error;
0307 }
0308
0309 rx_len = min_t(size_t, buf_size, get_unaligned_le16(rx_buf));
0310 memcpy(buf, &rx_buf[2], rx_len);
0311
0312 mdelay(WDT_COMMAND_DELAY_MS);
0313
0314 return 0;
0315 }
0316
0317 static int wdt87xx_set_feature(struct i2c_client *client,
0318 const u8 *buf, size_t buf_size)
0319 {
0320 u8 tx_buf[PKT_WRITE_SIZE];
0321 int tx_len = 0;
0322 int error;
0323
0324
0325 tx_buf[tx_len++] = 0x22;
0326 tx_buf[tx_len++] = 0x00;
0327 if (buf[CMD_REPORT_ID_OFFSET] > 0xF) {
0328 tx_buf[tx_len++] = 0x30;
0329 tx_buf[tx_len++] = 0x03;
0330 tx_buf[tx_len++] = buf[CMD_REPORT_ID_OFFSET];
0331 } else {
0332 tx_buf[tx_len++] = 0x30 | buf[CMD_REPORT_ID_OFFSET];
0333 tx_buf[tx_len++] = 0x03;
0334 }
0335 tx_buf[tx_len++] = 0x23;
0336 tx_buf[tx_len++] = 0x00;
0337 tx_buf[tx_len++] = (buf_size & 0xFF);
0338 tx_buf[tx_len++] = ((buf_size & 0xFF00) >> 8);
0339
0340 if (tx_len + buf_size > sizeof(tx_buf))
0341 return -EINVAL;
0342
0343 memcpy(&tx_buf[tx_len], buf, buf_size);
0344 tx_len += buf_size;
0345
0346 error = i2c_master_send(client, tx_buf, tx_len);
0347 if (error < 0) {
0348 dev_err(&client->dev, "set feature failed: %d\n", error);
0349 return error;
0350 }
0351
0352 mdelay(WDT_COMMAND_DELAY_MS);
0353
0354 return 0;
0355 }
0356
0357 static int wdt87xx_send_command(struct i2c_client *client, int cmd, int value)
0358 {
0359 u8 cmd_buf[CMD_BUF_SIZE];
0360
0361
0362 cmd_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_WRITE;
0363 cmd_buf[CMD_TYPE_OFFSET] = VND_SET_COMMAND_DATA;
0364 put_unaligned_le16((u16)cmd, &cmd_buf[CMD_INDEX_OFFSET]);
0365
0366 switch (cmd) {
0367 case VND_CMD_START:
0368 case VND_CMD_STOP:
0369 case VND_CMD_RESET:
0370
0371 put_unaligned_le32((value & 0xFF), &cmd_buf[CMD_LENGTH_OFFSET]);
0372 break;
0373
0374 case VND_CMD_SFLCK:
0375 put_unaligned_le16(CMD_SFLCK_KEY, &cmd_buf[CMD_KEY_OFFSET]);
0376 break;
0377
0378 case VND_CMD_SFUNL:
0379 put_unaligned_le16(CMD_SFUNL_KEY, &cmd_buf[CMD_KEY_OFFSET]);
0380 break;
0381
0382 case VND_CMD_ERASE:
0383 case VND_SET_CHECKSUM_CALC:
0384 case VND_SET_CHECKSUM_LENGTH:
0385 put_unaligned_le32(value, &cmd_buf[CMD_KEY_OFFSET]);
0386 break;
0387
0388 default:
0389 cmd_buf[CMD_REPORT_ID_OFFSET] = 0;
0390 dev_err(&client->dev, "Invalid command: %d\n", cmd);
0391 return -EINVAL;
0392 }
0393
0394 return wdt87xx_set_feature(client, cmd_buf, sizeof(cmd_buf));
0395 }
0396
0397 static int wdt87xx_sw_reset(struct i2c_client *client)
0398 {
0399 int error;
0400
0401 dev_dbg(&client->dev, "resetting device now\n");
0402
0403 error = wdt87xx_send_command(client, VND_CMD_RESET, 0);
0404 if (error) {
0405 dev_err(&client->dev, "reset failed\n");
0406 return error;
0407 }
0408
0409
0410 msleep(WDT_FW_RESET_TIME);
0411
0412 return 0;
0413 }
0414
0415 static const void *wdt87xx_get_fw_chunk(const struct firmware *fw, u32 id)
0416 {
0417 size_t pos = FW_PAYLOAD_OFFSET;
0418 u32 chunk_id, chunk_size;
0419
0420 while (pos < fw->size) {
0421 chunk_id = get_unaligned_le32(fw->data +
0422 pos + FW_CHUNK_ID_OFFSET);
0423 if (chunk_id == id)
0424 return fw->data + pos;
0425
0426 chunk_size = get_unaligned_le32(fw->data +
0427 pos + FW_CHUNK_SIZE_OFFSET);
0428 pos += chunk_size + 2 * sizeof(u32);
0429 }
0430
0431 return NULL;
0432 }
0433
0434 static int wdt87xx_get_sysparam(struct i2c_client *client,
0435 struct wdt87xx_sys_param *param)
0436 {
0437 u8 buf[PKT_READ_SIZE];
0438 int error;
0439
0440 error = wdt87xx_get_desc(client, WDT_GD_DEVICE, buf, 18);
0441 if (error) {
0442 dev_err(&client->dev, "failed to get device desc\n");
0443 return error;
0444 }
0445
0446 param->vendor_id = get_unaligned_le16(buf + DEV_DESC_OFFSET_VID);
0447 param->product_id = get_unaligned_le16(buf + DEV_DESC_OFFSET_PID);
0448
0449 error = wdt87xx_get_string(client, STRIDX_PARAMETERS, buf, 34);
0450 if (error) {
0451 dev_err(&client->dev, "failed to get parameters\n");
0452 return error;
0453 }
0454
0455 param->xmls_id1 = get_unaligned_le16(buf + CTL_PARAM_OFFSET_XMLS_ID1);
0456 param->xmls_id2 = get_unaligned_le16(buf + CTL_PARAM_OFFSET_XMLS_ID2);
0457 param->phy_ch_x = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_CH_X);
0458 param->phy_ch_y = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_CH_Y);
0459 param->phy_w = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_W) / 10;
0460 param->phy_h = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_H) / 10;
0461
0462
0463 param->scaling_factor =
0464 get_unaligned_le16(buf + CTL_PARAM_OFFSET_FACTOR);
0465
0466 param->max_x = MAX_UNIT_AXIS;
0467 param->max_y = DIV_ROUND_CLOSEST(MAX_UNIT_AXIS * param->phy_h,
0468 param->phy_w);
0469
0470 error = wdt87xx_get_string(client, STRIDX_PLATFORM_ID, buf, 8);
0471 if (error) {
0472 dev_err(&client->dev, "failed to get platform id\n");
0473 return error;
0474 }
0475
0476 param->plat_id = buf[1];
0477
0478 buf[0] = 0xf2;
0479 error = wdt87xx_get_feature(client, buf, 16);
0480 if (error) {
0481 dev_err(&client->dev, "failed to get firmware id\n");
0482 return error;
0483 }
0484
0485 if (buf[0] != 0xf2) {
0486 dev_err(&client->dev, "wrong id of fw response: 0x%x\n",
0487 buf[0]);
0488 return -EINVAL;
0489 }
0490
0491 param->fw_id = get_unaligned_le16(&buf[1]);
0492
0493 dev_info(&client->dev,
0494 "fw_id: 0x%x, plat_id: 0x%x, xml_id1: %04x, xml_id2: %04x\n",
0495 param->fw_id, param->plat_id,
0496 param->xmls_id1, param->xmls_id2);
0497
0498 return 0;
0499 }
0500
0501 static int wdt87xx_validate_firmware(struct wdt87xx_data *wdt,
0502 const struct firmware *fw)
0503 {
0504 const void *fw_chunk;
0505 u32 data1, data2;
0506 u32 size;
0507 u8 fw_chip_id;
0508 u8 chip_id;
0509
0510 data1 = get_unaligned_le32(fw->data + FW_FOURCC1_OFFSET);
0511 data2 = get_unaligned_le32(fw->data + FW_FOURCC2_OFFSET);
0512 if (data1 != FOURCC_ID_RIFF || data2 != FOURCC_ID_WHIF) {
0513 dev_err(&wdt->client->dev, "check fw tag failed\n");
0514 return -EINVAL;
0515 }
0516
0517 size = get_unaligned_le32(fw->data + FW_SIZE_OFFSET);
0518 if (size != fw->size) {
0519 dev_err(&wdt->client->dev,
0520 "fw size mismatch: expected %d, actual %zu\n",
0521 size, fw->size);
0522 return -EINVAL;
0523 }
0524
0525
0526
0527
0528
0529 fw_chunk = wdt87xx_get_fw_chunk(fw, CHUNK_ID_FRWR);
0530 if (!fw_chunk) {
0531 dev_err(&wdt->client->dev,
0532 "unable to locate firmware chunk\n");
0533 return -EINVAL;
0534 }
0535
0536 fw_chip_id = (get_unaligned_le32(fw_chunk +
0537 FW_CHUNK_VERSION_OFFSET) >> 12) & 0xF;
0538 chip_id = (wdt->param.fw_id >> 12) & 0xF;
0539
0540 if (fw_chip_id != chip_id) {
0541 dev_err(&wdt->client->dev,
0542 "fw version mismatch: fw %d vs. chip %d\n",
0543 fw_chip_id, chip_id);
0544 return -ENODEV;
0545 }
0546
0547 return 0;
0548 }
0549
0550 static int wdt87xx_validate_fw_chunk(const void *data, int id)
0551 {
0552 if (id == CHUNK_ID_FRWR) {
0553 u32 fw_id;
0554
0555 fw_id = get_unaligned_le32(data + FW_CHUNK_PAYLOAD_OFFSET);
0556 if (fw_id != WDT_FIRMWARE_ID)
0557 return -EINVAL;
0558 }
0559
0560 return 0;
0561 }
0562
0563 static int wdt87xx_write_data(struct i2c_client *client, const char *data,
0564 u32 address, int length)
0565 {
0566 u16 packet_size;
0567 int count = 0;
0568 int error;
0569 u8 pkt_buf[PKT_BUF_SIZE];
0570
0571
0572 if ((address & 0x3) != 0 || (length & 0x3) != 0) {
0573 dev_err(&client->dev,
0574 "addr & len must be 4 bytes aligned %x, %x\n",
0575 address, length);
0576 return -EINVAL;
0577 }
0578
0579 while (length) {
0580 packet_size = min(length, PACKET_SIZE);
0581
0582 pkt_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_WRITE;
0583 pkt_buf[CMD_TYPE_OFFSET] = VND_SET_DATA;
0584 put_unaligned_le16(packet_size, &pkt_buf[CMD_INDEX_OFFSET]);
0585 put_unaligned_le32(address, &pkt_buf[CMD_LENGTH_OFFSET]);
0586 memcpy(&pkt_buf[CMD_DATA_OFFSET], data, packet_size);
0587
0588 error = wdt87xx_set_feature(client, pkt_buf, sizeof(pkt_buf));
0589 if (error)
0590 return error;
0591
0592 length -= packet_size;
0593 data += packet_size;
0594 address += packet_size;
0595
0596
0597 mdelay(WDT_FLASH_WRITE_DELAY_MS);
0598
0599 if ((++count % 32) == 0) {
0600
0601 msleep(20);
0602 }
0603 }
0604
0605 return 0;
0606 }
0607
0608 static u16 misr(u16 cur_value, u8 new_value)
0609 {
0610 u32 a, b;
0611 u32 bit0;
0612 u32 y;
0613
0614 a = cur_value;
0615 b = new_value;
0616 bit0 = a ^ (b & 1);
0617 bit0 ^= a >> 1;
0618 bit0 ^= a >> 2;
0619 bit0 ^= a >> 4;
0620 bit0 ^= a >> 5;
0621 bit0 ^= a >> 7;
0622 bit0 ^= a >> 11;
0623 bit0 ^= a >> 15;
0624 y = (a << 1) ^ b;
0625 y = (y & ~1) | (bit0 & 1);
0626
0627 return (u16)y;
0628 }
0629
0630 static u16 wdt87xx_calculate_checksum(const u8 *data, size_t length)
0631 {
0632 u16 checksum = 0;
0633 size_t i;
0634
0635 for (i = 0; i < length; i++)
0636 checksum = misr(checksum, data[i]);
0637
0638 return checksum;
0639 }
0640
0641 static int wdt87xx_get_checksum(struct i2c_client *client, u16 *checksum,
0642 u32 address, int length)
0643 {
0644 int error;
0645 int time_delay;
0646 u8 pkt_buf[PKT_BUF_SIZE];
0647 u8 cmd_buf[CMD_BUF_SIZE];
0648
0649 error = wdt87xx_send_command(client, VND_SET_CHECKSUM_LENGTH, length);
0650 if (error) {
0651 dev_err(&client->dev, "failed to set checksum length\n");
0652 return error;
0653 }
0654
0655 error = wdt87xx_send_command(client, VND_SET_CHECKSUM_CALC, address);
0656 if (error) {
0657 dev_err(&client->dev, "failed to set checksum address\n");
0658 return error;
0659 }
0660
0661
0662 time_delay = DIV_ROUND_UP(length, 1024);
0663 msleep(time_delay * 30);
0664
0665 memset(cmd_buf, 0, sizeof(cmd_buf));
0666 cmd_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_READ;
0667 cmd_buf[CMD_TYPE_OFFSET] = VND_GET_CHECKSUM;
0668 error = wdt87xx_set_feature(client, cmd_buf, sizeof(cmd_buf));
0669 if (error) {
0670 dev_err(&client->dev, "failed to request checksum\n");
0671 return error;
0672 }
0673
0674 memset(pkt_buf, 0, sizeof(pkt_buf));
0675 pkt_buf[CMD_REPORT_ID_OFFSET] = VND_READ_DATA;
0676 error = wdt87xx_get_feature(client, pkt_buf, sizeof(pkt_buf));
0677 if (error) {
0678 dev_err(&client->dev, "failed to read checksum\n");
0679 return error;
0680 }
0681
0682 *checksum = get_unaligned_le16(&pkt_buf[CMD_DATA_OFFSET]);
0683 return 0;
0684 }
0685
0686 static int wdt87xx_write_firmware(struct i2c_client *client, const void *chunk)
0687 {
0688 u32 start_addr = get_unaligned_le32(chunk + FW_CHUNK_TGT_START_OFFSET);
0689 u32 size = get_unaligned_le32(chunk + FW_CHUNK_PAYLOAD_LEN_OFFSET);
0690 const void *data = chunk + FW_CHUNK_PAYLOAD_OFFSET;
0691 int error;
0692 int err1;
0693 int page_size;
0694 int retry = 0;
0695 u16 device_checksum, firmware_checksum;
0696
0697 dev_dbg(&client->dev, "start 4k page program\n");
0698
0699 error = wdt87xx_send_command(client, VND_CMD_STOP, MODE_STOP);
0700 if (error) {
0701 dev_err(&client->dev, "stop report mode failed\n");
0702 return error;
0703 }
0704
0705 error = wdt87xx_send_command(client, VND_CMD_SFUNL, 0);
0706 if (error) {
0707 dev_err(&client->dev, "unlock failed\n");
0708 goto out_enable_reporting;
0709 }
0710
0711 mdelay(10);
0712
0713 while (size) {
0714 dev_dbg(&client->dev, "%s: %x, %x\n", __func__,
0715 start_addr, size);
0716
0717 page_size = min_t(u32, size, PG_SIZE);
0718 size -= page_size;
0719
0720 for (retry = 0; retry < MAX_RETRIES; retry++) {
0721 error = wdt87xx_send_command(client, VND_CMD_ERASE,
0722 start_addr);
0723 if (error) {
0724 dev_err(&client->dev,
0725 "erase failed at %#08x\n", start_addr);
0726 break;
0727 }
0728
0729 msleep(WDT_FLASH_ERASE_DELAY_MS);
0730
0731 error = wdt87xx_write_data(client, data, start_addr,
0732 page_size);
0733 if (error) {
0734 dev_err(&client->dev,
0735 "write failed at %#08x (%d bytes)\n",
0736 start_addr, page_size);
0737 break;
0738 }
0739
0740 error = wdt87xx_get_checksum(client, &device_checksum,
0741 start_addr, page_size);
0742 if (error) {
0743 dev_err(&client->dev,
0744 "failed to retrieve checksum for %#08x (len: %d)\n",
0745 start_addr, page_size);
0746 break;
0747 }
0748
0749 firmware_checksum =
0750 wdt87xx_calculate_checksum(data, page_size);
0751
0752 if (device_checksum == firmware_checksum)
0753 break;
0754
0755 dev_err(&client->dev,
0756 "checksum fail: %d vs %d, retry %d\n",
0757 device_checksum, firmware_checksum, retry);
0758 }
0759
0760 if (retry == MAX_RETRIES) {
0761 dev_err(&client->dev, "page write failed\n");
0762 error = -EIO;
0763 goto out_lock_device;
0764 }
0765
0766 start_addr = start_addr + page_size;
0767 data = data + page_size;
0768 }
0769
0770 out_lock_device:
0771 err1 = wdt87xx_send_command(client, VND_CMD_SFLCK, 0);
0772 if (err1)
0773 dev_err(&client->dev, "lock failed\n");
0774
0775 mdelay(10);
0776
0777 out_enable_reporting:
0778 err1 = wdt87xx_send_command(client, VND_CMD_START, 0);
0779 if (err1)
0780 dev_err(&client->dev, "start to report failed\n");
0781
0782 return error ? error : err1;
0783 }
0784
0785 static int wdt87xx_load_chunk(struct i2c_client *client,
0786 const struct firmware *fw, u32 ck_id)
0787 {
0788 const void *chunk;
0789 int error;
0790
0791 chunk = wdt87xx_get_fw_chunk(fw, ck_id);
0792 if (!chunk) {
0793 dev_err(&client->dev, "unable to locate chunk (type %d)\n",
0794 ck_id);
0795 return -EINVAL;
0796 }
0797
0798 error = wdt87xx_validate_fw_chunk(chunk, ck_id);
0799 if (error) {
0800 dev_err(&client->dev, "invalid chunk (type %d): %d\n",
0801 ck_id, error);
0802 return error;
0803 }
0804
0805 error = wdt87xx_write_firmware(client, chunk);
0806 if (error) {
0807 dev_err(&client->dev,
0808 "failed to write fw chunk (type %d): %d\n",
0809 ck_id, error);
0810 return error;
0811 }
0812
0813 return 0;
0814 }
0815
0816 static int wdt87xx_do_update_firmware(struct i2c_client *client,
0817 const struct firmware *fw,
0818 unsigned int chunk_id)
0819 {
0820 struct wdt87xx_data *wdt = i2c_get_clientdata(client);
0821 int error;
0822
0823 error = wdt87xx_validate_firmware(wdt, fw);
0824 if (error)
0825 return error;
0826
0827 error = mutex_lock_interruptible(&wdt->fw_mutex);
0828 if (error)
0829 return error;
0830
0831 disable_irq(client->irq);
0832
0833 error = wdt87xx_load_chunk(client, fw, chunk_id);
0834 if (error) {
0835 dev_err(&client->dev,
0836 "firmware load failed (type: %d): %d\n",
0837 chunk_id, error);
0838 goto out;
0839 }
0840
0841 error = wdt87xx_sw_reset(client);
0842 if (error) {
0843 dev_err(&client->dev, "soft reset failed: %d\n", error);
0844 goto out;
0845 }
0846
0847
0848 error = wdt87xx_get_sysparam(client, &wdt->param);
0849 if (error)
0850 dev_err(&client->dev,
0851 "failed to refresh system parameters: %d\n", error);
0852 out:
0853 enable_irq(client->irq);
0854 mutex_unlock(&wdt->fw_mutex);
0855
0856 return error ? error : 0;
0857 }
0858
0859 static int wdt87xx_update_firmware(struct device *dev,
0860 const char *fw_name, unsigned int chunk_id)
0861 {
0862 struct i2c_client *client = to_i2c_client(dev);
0863 const struct firmware *fw;
0864 int error;
0865
0866 error = request_firmware(&fw, fw_name, dev);
0867 if (error) {
0868 dev_err(&client->dev, "unable to retrieve firmware %s: %d\n",
0869 fw_name, error);
0870 return error;
0871 }
0872
0873 error = wdt87xx_do_update_firmware(client, fw, chunk_id);
0874
0875 release_firmware(fw);
0876
0877 return error ? error : 0;
0878 }
0879
0880 static ssize_t config_csum_show(struct device *dev,
0881 struct device_attribute *attr, char *buf)
0882 {
0883 struct i2c_client *client = to_i2c_client(dev);
0884 struct wdt87xx_data *wdt = i2c_get_clientdata(client);
0885 u32 cfg_csum;
0886
0887 cfg_csum = wdt->param.xmls_id1;
0888 cfg_csum = (cfg_csum << 16) | wdt->param.xmls_id2;
0889
0890 return scnprintf(buf, PAGE_SIZE, "%x\n", cfg_csum);
0891 }
0892
0893 static ssize_t fw_version_show(struct device *dev,
0894 struct device_attribute *attr, char *buf)
0895 {
0896 struct i2c_client *client = to_i2c_client(dev);
0897 struct wdt87xx_data *wdt = i2c_get_clientdata(client);
0898
0899 return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.fw_id);
0900 }
0901
0902 static ssize_t plat_id_show(struct device *dev,
0903 struct device_attribute *attr, char *buf)
0904 {
0905 struct i2c_client *client = to_i2c_client(dev);
0906 struct wdt87xx_data *wdt = i2c_get_clientdata(client);
0907
0908 return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.plat_id);
0909 }
0910
0911 static ssize_t update_config_store(struct device *dev,
0912 struct device_attribute *attr,
0913 const char *buf, size_t count)
0914 {
0915 int error;
0916
0917 error = wdt87xx_update_firmware(dev, WDT87XX_CFG_NAME, CHUNK_ID_CNFG);
0918
0919 return error ? error : count;
0920 }
0921
0922 static ssize_t update_fw_store(struct device *dev,
0923 struct device_attribute *attr,
0924 const char *buf, size_t count)
0925 {
0926 int error;
0927
0928 error = wdt87xx_update_firmware(dev, WDT87XX_FW_NAME, CHUNK_ID_FRWR);
0929
0930 return error ? error : count;
0931 }
0932
0933 static DEVICE_ATTR_RO(config_csum);
0934 static DEVICE_ATTR_RO(fw_version);
0935 static DEVICE_ATTR_RO(plat_id);
0936 static DEVICE_ATTR_WO(update_config);
0937 static DEVICE_ATTR_WO(update_fw);
0938
0939 static struct attribute *wdt87xx_attrs[] = {
0940 &dev_attr_config_csum.attr,
0941 &dev_attr_fw_version.attr,
0942 &dev_attr_plat_id.attr,
0943 &dev_attr_update_config.attr,
0944 &dev_attr_update_fw.attr,
0945 NULL
0946 };
0947
0948 static const struct attribute_group wdt87xx_attr_group = {
0949 .attrs = wdt87xx_attrs,
0950 };
0951
0952 static void wdt87xx_report_contact(struct input_dev *input,
0953 struct wdt87xx_sys_param *param,
0954 u8 *buf)
0955 {
0956 int finger_id;
0957 u32 x, y, w;
0958 u8 p;
0959
0960 finger_id = (buf[FINGER_EV_V1_OFFSET_ID] >> 3) - 1;
0961 if (finger_id < 0)
0962 return;
0963
0964
0965 if (!(buf[FINGER_EV_V1_OFFSET_ID] & 0x1))
0966 return;
0967
0968 w = buf[FINGER_EV_V1_OFFSET_W];
0969 w *= param->scaling_factor;
0970
0971 p = buf[FINGER_EV_V1_OFFSET_P];
0972
0973 x = get_unaligned_le16(buf + FINGER_EV_V1_OFFSET_X);
0974
0975 y = get_unaligned_le16(buf + FINGER_EV_V1_OFFSET_Y);
0976 y = DIV_ROUND_CLOSEST(y * param->phy_h, param->phy_w);
0977
0978
0979 if (x > param->max_x || y > param->max_y)
0980 return;
0981
0982 dev_dbg(input->dev.parent, "tip on (%d), x(%d), y(%d)\n",
0983 finger_id, x, y);
0984
0985 input_mt_slot(input, finger_id);
0986 input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
0987 input_report_abs(input, ABS_MT_TOUCH_MAJOR, w);
0988 input_report_abs(input, ABS_MT_PRESSURE, p);
0989 input_report_abs(input, ABS_MT_POSITION_X, x);
0990 input_report_abs(input, ABS_MT_POSITION_Y, y);
0991 }
0992
0993 static irqreturn_t wdt87xx_ts_interrupt(int irq, void *dev_id)
0994 {
0995 struct wdt87xx_data *wdt = dev_id;
0996 struct i2c_client *client = wdt->client;
0997 int i, fingers;
0998 int error;
0999 u8 raw_buf[WDT_V1_RAW_BUF_COUNT] = {0};
1000
1001 error = i2c_master_recv(client, raw_buf, WDT_V1_RAW_BUF_COUNT);
1002 if (error < 0) {
1003 dev_err(&client->dev, "read v1 raw data failed: %d\n", error);
1004 goto irq_exit;
1005 }
1006
1007 fingers = raw_buf[TOUCH_PK_V1_OFFSET_FNGR_NUM];
1008 if (!fingers)
1009 goto irq_exit;
1010
1011 for (i = 0; i < WDT_MAX_FINGER; i++)
1012 wdt87xx_report_contact(wdt->input,
1013 &wdt->param,
1014 &raw_buf[TOUCH_PK_V1_OFFSET_EVENT +
1015 i * FINGER_EV_V1_SIZE]);
1016
1017 input_mt_sync_frame(wdt->input);
1018 input_sync(wdt->input);
1019
1020 irq_exit:
1021 return IRQ_HANDLED;
1022 }
1023
1024 static int wdt87xx_ts_create_input_device(struct wdt87xx_data *wdt)
1025 {
1026 struct device *dev = &wdt->client->dev;
1027 struct input_dev *input;
1028 unsigned int res = DIV_ROUND_CLOSEST(MAX_UNIT_AXIS, wdt->param.phy_w);
1029 int error;
1030
1031 input = devm_input_allocate_device(dev);
1032 if (!input) {
1033 dev_err(dev, "failed to allocate input device\n");
1034 return -ENOMEM;
1035 }
1036 wdt->input = input;
1037
1038 input->name = "WDT87xx Touchscreen";
1039 input->id.bustype = BUS_I2C;
1040 input->id.vendor = wdt->param.vendor_id;
1041 input->id.product = wdt->param.product_id;
1042 input->phys = wdt->phys;
1043
1044 input_set_abs_params(input, ABS_MT_POSITION_X, 0,
1045 wdt->param.max_x, 0, 0);
1046 input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
1047 wdt->param.max_y, 0, 0);
1048 input_abs_set_res(input, ABS_MT_POSITION_X, res);
1049 input_abs_set_res(input, ABS_MT_POSITION_Y, res);
1050
1051 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
1052 0, wdt->param.max_x, 0, 0);
1053 input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
1054
1055 input_mt_init_slots(input, WDT_MAX_FINGER,
1056 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
1057
1058 error = input_register_device(input);
1059 if (error) {
1060 dev_err(dev, "failed to register input device: %d\n", error);
1061 return error;
1062 }
1063
1064 return 0;
1065 }
1066
1067 static int wdt87xx_ts_probe(struct i2c_client *client,
1068 const struct i2c_device_id *id)
1069 {
1070 struct wdt87xx_data *wdt;
1071 int error;
1072
1073 dev_dbg(&client->dev, "adapter=%d, client irq: %d\n",
1074 client->adapter->nr, client->irq);
1075
1076
1077 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
1078 return -ENXIO;
1079
1080 wdt = devm_kzalloc(&client->dev, sizeof(*wdt), GFP_KERNEL);
1081 if (!wdt)
1082 return -ENOMEM;
1083
1084 wdt->client = client;
1085 mutex_init(&wdt->fw_mutex);
1086 i2c_set_clientdata(client, wdt);
1087
1088 snprintf(wdt->phys, sizeof(wdt->phys), "i2c-%u-%04x/input0",
1089 client->adapter->nr, client->addr);
1090
1091 error = wdt87xx_get_sysparam(client, &wdt->param);
1092 if (error)
1093 return error;
1094
1095 error = wdt87xx_ts_create_input_device(wdt);
1096 if (error)
1097 return error;
1098
1099 error = devm_request_threaded_irq(&client->dev, client->irq,
1100 NULL, wdt87xx_ts_interrupt,
1101 IRQF_ONESHOT,
1102 client->name, wdt);
1103 if (error) {
1104 dev_err(&client->dev, "request irq failed: %d\n", error);
1105 return error;
1106 }
1107
1108 error = devm_device_add_group(&client->dev, &wdt87xx_attr_group);
1109 if (error) {
1110 dev_err(&client->dev, "create sysfs failed: %d\n", error);
1111 return error;
1112 }
1113
1114 return 0;
1115 }
1116
1117 static int __maybe_unused wdt87xx_suspend(struct device *dev)
1118 {
1119 struct i2c_client *client = to_i2c_client(dev);
1120 int error;
1121
1122 disable_irq(client->irq);
1123
1124 error = wdt87xx_send_command(client, VND_CMD_STOP, MODE_IDLE);
1125 if (error) {
1126 enable_irq(client->irq);
1127 dev_err(&client->dev,
1128 "failed to stop device when suspending: %d\n",
1129 error);
1130 return error;
1131 }
1132
1133 return 0;
1134 }
1135
1136 static int __maybe_unused wdt87xx_resume(struct device *dev)
1137 {
1138 struct i2c_client *client = to_i2c_client(dev);
1139 int error;
1140
1141
1142
1143
1144
1145 msleep(100);
1146
1147 error = wdt87xx_send_command(client, VND_CMD_START, 0);
1148 if (error)
1149 dev_err(&client->dev,
1150 "failed to start device when resuming: %d\n",
1151 error);
1152
1153 enable_irq(client->irq);
1154
1155 return 0;
1156 }
1157
1158 static SIMPLE_DEV_PM_OPS(wdt87xx_pm_ops, wdt87xx_suspend, wdt87xx_resume);
1159
1160 static const struct i2c_device_id wdt87xx_dev_id[] = {
1161 { WDT87XX_NAME, 0 },
1162 { }
1163 };
1164 MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id);
1165
1166 static const struct acpi_device_id wdt87xx_acpi_id[] = {
1167 { "WDHT0001", 0 },
1168 { }
1169 };
1170 MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id);
1171
1172 static struct i2c_driver wdt87xx_driver = {
1173 .probe = wdt87xx_ts_probe,
1174 .id_table = wdt87xx_dev_id,
1175 .driver = {
1176 .name = WDT87XX_NAME,
1177 .pm = &wdt87xx_pm_ops,
1178 .acpi_match_table = ACPI_PTR(wdt87xx_acpi_id),
1179 },
1180 };
1181 module_i2c_driver(wdt87xx_driver);
1182
1183 MODULE_AUTHOR("HN Chen <hn.chen@weidahitech.com>");
1184 MODULE_DESCRIPTION("WeidaHiTech WDT87XX Touchscreen driver");
1185 MODULE_LICENSE("GPL");