Lines Matching +full:edt +full:- +full:ft5x06
1 // SPDX-License-Identifier: GPL-2.0
5 * Lothar Waßmann <LW@KARO-electronics.de> (DT support)
10 * This is a driver for the EDT "Polytouch" family of touch controllers
11 * based on the FocalTech FT5x06 line of chips.
167 for (i = 0; i < buflen - 1; i++) in edt_ft5x06_ts_check_crc()
170 if (crc != buf[buflen - 1]) { in edt_ft5x06_ts_check_crc()
171 tsdata->crc_errors++; in edt_ft5x06_ts_check_crc()
172 dev_err_ratelimited(&tsdata->client->dev, in edt_ft5x06_ts_check_crc()
174 crc, buf[buflen - 1]); in edt_ft5x06_ts_check_crc()
209 wbuf[0] = M06_REG_CMD(tsdata->factory_mode); in edt_M06_i2c_read()
210 wbuf[1] = M06_REG_ADDR(tsdata->factory_mode, addr); in edt_M06_i2c_read()
211 wbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; in edt_M06_i2c_read()
214 xfer[0].addr = i2c->addr; in edt_M06_i2c_read()
219 xfer[1].addr = i2c->addr; in edt_M06_i2c_read()
224 ret = i2c_transfer(i2c->adapter, xfer, 2); in edt_M06_i2c_read()
229 return -EIO; in edt_M06_i2c_read()
237 tsdata->header_errors++; in edt_M06_i2c_read()
241 return -EIO; in edt_M06_i2c_read()
245 return -EIO; in edt_M06_i2c_read()
250 return -EIO; in edt_M06_i2c_read()
271 wbuf[0] = M06_REG_CMD(tsdata->factory_mode); in edt_M06_i2c_write()
272 wbuf[1] = M06_REG_ADDR(tsdata->factory_mode, addr); in edt_M06_i2c_write()
276 xfer.addr = i2c->addr; in edt_M06_i2c_write()
281 ret = i2c_transfer(i2c->adapter, &xfer, 1); in edt_M06_i2c_write()
286 return -EIO; in edt_M06_i2c_write()
302 struct device *dev = &tsdata->client->dev; in edt_ft5x06_ts_isr()
308 error = regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd, rdbuf, in edt_ft5x06_ts_isr()
309 tsdata->tdata_len); in edt_ft5x06_ts_isr()
316 for (i = 0; i < tsdata->max_support_points; i++) { in edt_ft5x06_ts_isr()
317 u8 *buf = &rdbuf[i * tsdata->point_len + tsdata->tdata_offset]; in edt_ft5x06_ts_isr()
325 if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN) in edt_ft5x06_ts_isr()
331 if (tsdata->version == EV_FT) in edt_ft5x06_ts_isr()
336 input_mt_slot(tsdata->input, id); in edt_ft5x06_ts_isr()
337 if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, in edt_ft5x06_ts_isr()
339 touchscreen_report_pos(tsdata->input, &tsdata->prop, in edt_ft5x06_ts_isr()
343 input_mt_report_pointer_emulation(tsdata->input, true); in edt_ft5x06_ts_isr()
344 input_sync(tsdata->input); in edt_ft5x06_ts_isr()
382 u8 *field = (u8 *)tsdata + attr->field_offset; in edt_ft5x06_setting_show()
388 mutex_lock(&tsdata->mutex); in edt_ft5x06_setting_show()
390 if (tsdata->factory_mode) { in edt_ft5x06_setting_show()
391 error = -EIO; in edt_ft5x06_setting_show()
395 switch (tsdata->version) { in edt_ft5x06_setting_show()
397 addr = attr->addr_m06; in edt_ft5x06_setting_show()
403 addr = attr->addr_m09; in edt_ft5x06_setting_show()
407 addr = attr->addr_ev; in edt_ft5x06_setting_show()
411 error = -ENODEV; in edt_ft5x06_setting_show()
416 error = regmap_read(tsdata->regmap, addr, &val); in edt_ft5x06_setting_show()
418 dev_err(&tsdata->client->dev, in edt_ft5x06_setting_show()
420 dattr->attr.name, error); in edt_ft5x06_setting_show()
428 dev_warn(&tsdata->client->dev, in edt_ft5x06_setting_show()
430 dattr->attr.name, val, *field); in edt_ft5x06_setting_show()
436 mutex_unlock(&tsdata->mutex); in edt_ft5x06_setting_show()
448 u8 *field = (u8 *)tsdata + attr->field_offset; in edt_ft5x06_setting_store()
453 mutex_lock(&tsdata->mutex); in edt_ft5x06_setting_store()
455 if (tsdata->factory_mode) { in edt_ft5x06_setting_store()
456 error = -EIO; in edt_ft5x06_setting_store()
464 if (val < attr->limit_low || val > attr->limit_high) { in edt_ft5x06_setting_store()
465 error = -ERANGE; in edt_ft5x06_setting_store()
469 switch (tsdata->version) { in edt_ft5x06_setting_store()
471 addr = attr->addr_m06; in edt_ft5x06_setting_store()
477 addr = attr->addr_m09; in edt_ft5x06_setting_store()
481 addr = attr->addr_ev; in edt_ft5x06_setting_store()
485 error = -ENODEV; in edt_ft5x06_setting_store()
490 error = regmap_write(tsdata->regmap, addr, val); in edt_ft5x06_setting_store()
492 dev_err(&tsdata->client->dev, in edt_ft5x06_setting_store()
494 dattr->attr.name, error); in edt_ft5x06_setting_store()
501 mutex_unlock(&tsdata->mutex); in edt_ft5x06_setting_store()
505 /* m06, m09: range 0-31, m12: range 0-5 */
508 /* m06, m09: range 0-31, m12: range 0-16 */
511 /* m06, m09, m12: no supported, ev_ft: range 0-80 */
514 /* m06, m09, m12: no supported, ev_ft: range 0-80 */
530 return sysfs_emit(buf, "%s\n", tsdata->name); in model_show()
541 return sysfs_emit(buf, "%s\n", tsdata->fw_version); in fw_version_show()
553 return sysfs_emit(buf, "%d\n", tsdata->header_errors); in header_errors_show()
565 return sysfs_emit(buf, "%d\n", tsdata->crc_errors); in crc_errors_show()
587 struct edt_reg_addr *reg_addr = &tsdata->reg_addr; in edt_ft5x06_restore_reg_parameters()
588 struct regmap *regmap = tsdata->regmap; in edt_ft5x06_restore_reg_parameters()
590 regmap_write(regmap, reg_addr->reg_threshold, tsdata->threshold); in edt_ft5x06_restore_reg_parameters()
591 regmap_write(regmap, reg_addr->reg_gain, tsdata->gain); in edt_ft5x06_restore_reg_parameters()
592 if (reg_addr->reg_offset != NO_REGISTER) in edt_ft5x06_restore_reg_parameters()
593 regmap_write(regmap, reg_addr->reg_offset, tsdata->offset); in edt_ft5x06_restore_reg_parameters()
594 if (reg_addr->reg_offset_x != NO_REGISTER) in edt_ft5x06_restore_reg_parameters()
595 regmap_write(regmap, reg_addr->reg_offset_x, tsdata->offset_x); in edt_ft5x06_restore_reg_parameters()
596 if (reg_addr->reg_offset_y != NO_REGISTER) in edt_ft5x06_restore_reg_parameters()
597 regmap_write(regmap, reg_addr->reg_offset_y, tsdata->offset_y); in edt_ft5x06_restore_reg_parameters()
598 if (reg_addr->reg_report_rate != NO_REGISTER) in edt_ft5x06_restore_reg_parameters()
599 regmap_write(regmap, reg_addr->reg_report_rate, in edt_ft5x06_restore_reg_parameters()
600 tsdata->report_rate); in edt_ft5x06_restore_reg_parameters()
606 struct i2c_client *client = tsdata->client; in edt_ft5x06_factory_mode()
611 if (tsdata->version != EDT_M06) { in edt_ft5x06_factory_mode()
612 dev_err(&client->dev, in edt_ft5x06_factory_mode()
613 "No factory mode support for non-M06 devices\n"); in edt_ft5x06_factory_mode()
614 return -EINVAL; in edt_ft5x06_factory_mode()
617 disable_irq(client->irq); in edt_ft5x06_factory_mode()
619 if (!tsdata->raw_buffer) { in edt_ft5x06_factory_mode()
620 tsdata->raw_bufsize = tsdata->num_x * tsdata->num_y * in edt_ft5x06_factory_mode()
622 tsdata->raw_buffer = kzalloc(tsdata->raw_bufsize, GFP_KERNEL); in edt_ft5x06_factory_mode()
623 if (!tsdata->raw_buffer) { in edt_ft5x06_factory_mode()
624 error = -ENOMEM; in edt_ft5x06_factory_mode()
630 error = regmap_write(tsdata->regmap, WORK_REGISTER_OPMODE, 0x03); in edt_ft5x06_factory_mode()
632 dev_err(&client->dev, in edt_ft5x06_factory_mode()
637 tsdata->factory_mode = true; in edt_ft5x06_factory_mode()
641 error = regmap_read(tsdata->regmap, FACTORY_REGISTER_OPMODE, in edt_ft5x06_factory_mode()
645 } while (--retries > 0); in edt_ft5x06_factory_mode()
648 dev_err(&client->dev, "not in factory mode after %dms.\n", in edt_ft5x06_factory_mode()
650 error = -EIO; in edt_ft5x06_factory_mode()
657 kfree(tsdata->raw_buffer); in edt_ft5x06_factory_mode()
658 tsdata->raw_buffer = NULL; in edt_ft5x06_factory_mode()
659 tsdata->factory_mode = false; in edt_ft5x06_factory_mode()
660 enable_irq(client->irq); in edt_ft5x06_factory_mode()
667 struct i2c_client *client = tsdata->client; in edt_ft5x06_work_mode()
673 error = regmap_write(tsdata->regmap, FACTORY_REGISTER_OPMODE, 0x1); in edt_ft5x06_work_mode()
675 dev_err(&client->dev, in edt_ft5x06_work_mode()
680 tsdata->factory_mode = false; in edt_ft5x06_work_mode()
685 error = regmap_read(tsdata->regmap, WORK_REGISTER_OPMODE, &val); in edt_ft5x06_work_mode()
688 } while (--retries > 0); in edt_ft5x06_work_mode()
691 dev_err(&client->dev, "not in work mode after %dms.\n", in edt_ft5x06_work_mode()
693 tsdata->factory_mode = true; in edt_ft5x06_work_mode()
694 return -EIO; in edt_ft5x06_work_mode()
697 kfree(tsdata->raw_buffer); in edt_ft5x06_work_mode()
698 tsdata->raw_buffer = NULL; in edt_ft5x06_work_mode()
701 enable_irq(client->irq); in edt_ft5x06_work_mode()
710 *mode = tsdata->factory_mode; in edt_ft5x06_debugfs_mode_get()
721 return -ERANGE; in edt_ft5x06_debugfs_mode_set()
723 mutex_lock(&tsdata->mutex); in edt_ft5x06_debugfs_mode_set()
725 if (mode != tsdata->factory_mode) { in edt_ft5x06_debugfs_mode_set()
730 mutex_unlock(&tsdata->mutex); in edt_ft5x06_debugfs_mode_set()
742 struct edt_ft5x06_ts_data *tsdata = file->private_data; in edt_ft5x06_debugfs_raw_data_read()
743 struct i2c_client *client = tsdata->client; in edt_ft5x06_debugfs_raw_data_read()
751 if (*off < 0 || *off >= tsdata->raw_bufsize) in edt_ft5x06_debugfs_raw_data_read()
754 mutex_lock(&tsdata->mutex); in edt_ft5x06_debugfs_raw_data_read()
756 if (!tsdata->factory_mode || !tsdata->raw_buffer) { in edt_ft5x06_debugfs_raw_data_read()
757 error = -EIO; in edt_ft5x06_debugfs_raw_data_read()
761 error = regmap_write(tsdata->regmap, 0x08, 0x01); in edt_ft5x06_debugfs_raw_data_read()
763 dev_err(&client->dev, in edt_ft5x06_debugfs_raw_data_read()
770 error = regmap_read(tsdata->regmap, 0x08, &val); in edt_ft5x06_debugfs_raw_data_read()
772 dev_err(&client->dev, in edt_ft5x06_debugfs_raw_data_read()
780 } while (--retries > 0); in edt_ft5x06_debugfs_raw_data_read()
783 dev_err(&client->dev, in edt_ft5x06_debugfs_raw_data_read()
785 error = -ETIMEDOUT; in edt_ft5x06_debugfs_raw_data_read()
789 rdbuf = tsdata->raw_buffer; in edt_ft5x06_debugfs_raw_data_read()
790 colbytes = tsdata->num_y * sizeof(u16); in edt_ft5x06_debugfs_raw_data_read()
792 for (i = 0; i < tsdata->num_x; i++) { in edt_ft5x06_debugfs_raw_data_read()
794 error = regmap_bulk_read(tsdata->regmap, 0xf5, rdbuf, colbytes); in edt_ft5x06_debugfs_raw_data_read()
801 read = min_t(size_t, count, tsdata->raw_bufsize - *off); in edt_ft5x06_debugfs_raw_data_read()
802 if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) { in edt_ft5x06_debugfs_raw_data_read()
803 error = -EFAULT; in edt_ft5x06_debugfs_raw_data_read()
809 mutex_unlock(&tsdata->mutex); in edt_ft5x06_debugfs_raw_data_read()
821 tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL); in edt_ft5x06_ts_prepare_debugfs()
823 debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x); in edt_ft5x06_ts_prepare_debugfs()
824 debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y); in edt_ft5x06_ts_prepare_debugfs()
827 tsdata->debug_dir, tsdata, &debugfs_mode_fops); in edt_ft5x06_ts_prepare_debugfs()
829 tsdata->debug_dir, tsdata, &debugfs_raw_data_fops); in edt_ft5x06_ts_prepare_debugfs()
834 debugfs_remove_recursive(tsdata->debug_dir); in edt_ft5x06_ts_teardown_debugfs()
835 kfree(tsdata->raw_buffer); in edt_ft5x06_ts_teardown_debugfs()
842 return -ENOSYS; in edt_ft5x06_factory_mode()
862 char *model_name = tsdata->name; in edt_ft5x06_ts_identify()
863 char *fw_version = tsdata->fw_version; in edt_ft5x06_ts_identify()
870 error = regmap_bulk_read(tsdata->regmap, 0xBB, rdbuf, EDT_NAME_LEN - 1); in edt_ft5x06_ts_identify()
879 tsdata->version = EDT_M06; in edt_ft5x06_ts_identify()
882 rdbuf[EDT_NAME_LEN - 1] = '\0'; in edt_ft5x06_ts_identify()
883 if (rdbuf[EDT_NAME_LEN - 2] == '$') in edt_ft5x06_ts_identify()
884 rdbuf[EDT_NAME_LEN - 2] = '\0'; in edt_ft5x06_ts_identify()
893 regmap_exit(tsdata->regmap); in edt_ft5x06_ts_identify()
894 tsdata->regmap = regmap_init_i2c(client, in edt_ft5x06_ts_identify()
896 if (IS_ERR(tsdata->regmap)) { in edt_ft5x06_ts_identify()
897 dev_err(&client->dev, "regmap allocation failed\n"); in edt_ft5x06_ts_identify()
898 return PTR_ERR(tsdata->regmap); in edt_ft5x06_ts_identify()
901 tsdata->version = EDT_M12; in edt_ft5x06_ts_identify()
904 rdbuf[EDT_NAME_LEN - 2] = '\0'; in edt_ft5x06_ts_identify()
905 if (rdbuf[EDT_NAME_LEN - 3] == '$') in edt_ft5x06_ts_identify()
906 rdbuf[EDT_NAME_LEN - 3] = '\0'; in edt_ft5x06_ts_identify()
915 /* If it is not an EDT M06/M12 touchscreen, then the model in edt_ft5x06_ts_identify()
916 * detection is a bit hairy. The different ft5x06 in edt_ft5x06_ts_identify()
921 * touches and EDT M09 is that we know how to retrieve in edt_ft5x06_ts_identify()
924 tsdata->version = GENERIC_FT; in edt_ft5x06_ts_identify()
926 error = regmap_bulk_read(tsdata->regmap, 0xA6, rdbuf, 2); in edt_ft5x06_ts_identify()
932 error = regmap_bulk_read(tsdata->regmap, 0xA8, rdbuf, 1); in edt_ft5x06_ts_identify()
937 * not all firmwares for the ft5x06 put useful values in in edt_ft5x06_ts_identify()
941 case 0x11: /* EDT EP0110M09 */ in edt_ft5x06_ts_identify()
942 case 0x35: /* EDT EP0350M09 */ in edt_ft5x06_ts_identify()
943 case 0x43: /* EDT EP0430M09 */ in edt_ft5x06_ts_identify()
944 case 0x50: /* EDT EP0500M09 */ in edt_ft5x06_ts_identify()
945 case 0x57: /* EDT EP0570M09 */ in edt_ft5x06_ts_identify()
946 case 0x70: /* EDT EP0700M09 */ in edt_ft5x06_ts_identify()
947 tsdata->version = EDT_M09; in edt_ft5x06_ts_identify()
951 case 0xa1: /* EDT EP1010ML00 */ in edt_ft5x06_ts_identify()
952 tsdata->version = EDT_M09; in edt_ft5x06_ts_identify()
960 tsdata->version = EV_FT; in edt_ft5x06_ts_identify()
961 error = regmap_bulk_read(tsdata->regmap, 0x53, rdbuf, 1); in edt_ft5x06_ts_identify()
966 "EVERVISION-FT5726NEi"); in edt_ft5x06_ts_identify()
970 "generic ft5x06 (%02x)", in edt_ft5x06_ts_identify()
982 struct edt_reg_addr *reg_addr = &tsdata->reg_addr; in edt_ft5x06_ts_get_defaults()
983 struct regmap *regmap = tsdata->regmap; in edt_ft5x06_ts_get_defaults()
989 regmap_write(regmap, reg_addr->reg_threshold, val); in edt_ft5x06_ts_get_defaults()
990 tsdata->threshold = val; in edt_ft5x06_ts_get_defaults()
995 regmap_write(regmap, reg_addr->reg_gain, val); in edt_ft5x06_ts_get_defaults()
996 tsdata->gain = val; in edt_ft5x06_ts_get_defaults()
1001 if (reg_addr->reg_offset != NO_REGISTER) in edt_ft5x06_ts_get_defaults()
1002 regmap_write(regmap, reg_addr->reg_offset, val); in edt_ft5x06_ts_get_defaults()
1003 tsdata->offset = val; in edt_ft5x06_ts_get_defaults()
1006 error = device_property_read_u32(dev, "offset-x", &val); in edt_ft5x06_ts_get_defaults()
1008 if (reg_addr->reg_offset_x != NO_REGISTER) in edt_ft5x06_ts_get_defaults()
1009 regmap_write(regmap, reg_addr->reg_offset_x, val); in edt_ft5x06_ts_get_defaults()
1010 tsdata->offset_x = val; in edt_ft5x06_ts_get_defaults()
1013 error = device_property_read_u32(dev, "offset-y", &val); in edt_ft5x06_ts_get_defaults()
1015 if (reg_addr->reg_offset_y != NO_REGISTER) in edt_ft5x06_ts_get_defaults()
1016 regmap_write(regmap, reg_addr->reg_offset_y, val); in edt_ft5x06_ts_get_defaults()
1017 tsdata->offset_y = val; in edt_ft5x06_ts_get_defaults()
1023 struct edt_reg_addr *reg_addr = &tsdata->reg_addr; in edt_ft5x06_ts_get_parameters()
1024 struct regmap *regmap = tsdata->regmap; in edt_ft5x06_ts_get_parameters()
1027 regmap_read(regmap, reg_addr->reg_threshold, &tsdata->threshold); in edt_ft5x06_ts_get_parameters()
1028 regmap_read(regmap, reg_addr->reg_gain, &tsdata->gain); in edt_ft5x06_ts_get_parameters()
1029 if (reg_addr->reg_offset != NO_REGISTER) in edt_ft5x06_ts_get_parameters()
1030 regmap_read(regmap, reg_addr->reg_offset, &tsdata->offset); in edt_ft5x06_ts_get_parameters()
1031 if (reg_addr->reg_offset_x != NO_REGISTER) in edt_ft5x06_ts_get_parameters()
1032 regmap_read(regmap, reg_addr->reg_offset_x, &tsdata->offset_x); in edt_ft5x06_ts_get_parameters()
1033 if (reg_addr->reg_offset_y != NO_REGISTER) in edt_ft5x06_ts_get_parameters()
1034 regmap_read(regmap, reg_addr->reg_offset_y, &tsdata->offset_y); in edt_ft5x06_ts_get_parameters()
1035 if (reg_addr->reg_report_rate != NO_REGISTER) in edt_ft5x06_ts_get_parameters()
1036 regmap_read(regmap, reg_addr->reg_report_rate, in edt_ft5x06_ts_get_parameters()
1037 &tsdata->report_rate); in edt_ft5x06_ts_get_parameters()
1038 tsdata->num_x = EDT_DEFAULT_NUM_X; in edt_ft5x06_ts_get_parameters()
1039 if (reg_addr->reg_num_x != NO_REGISTER) { in edt_ft5x06_ts_get_parameters()
1040 if (!regmap_read(regmap, reg_addr->reg_num_x, &val)) in edt_ft5x06_ts_get_parameters()
1041 tsdata->num_x = val; in edt_ft5x06_ts_get_parameters()
1043 tsdata->num_y = EDT_DEFAULT_NUM_Y; in edt_ft5x06_ts_get_parameters()
1044 if (reg_addr->reg_num_y != NO_REGISTER) { in edt_ft5x06_ts_get_parameters()
1045 if (!regmap_read(regmap, reg_addr->reg_num_y, &val)) in edt_ft5x06_ts_get_parameters()
1046 tsdata->num_y = val; in edt_ft5x06_ts_get_parameters()
1054 if (tsdata->version == EDT_M06) { in edt_ft5x06_ts_set_tdata_parameters()
1055 tsdata->tdata_cmd = 0xf9; in edt_ft5x06_ts_set_tdata_parameters()
1056 tsdata->tdata_offset = 5; in edt_ft5x06_ts_set_tdata_parameters()
1057 tsdata->point_len = 4; in edt_ft5x06_ts_set_tdata_parameters()
1060 tsdata->tdata_cmd = 0x0; in edt_ft5x06_ts_set_tdata_parameters()
1061 tsdata->tdata_offset = 3; in edt_ft5x06_ts_set_tdata_parameters()
1062 tsdata->point_len = 6; in edt_ft5x06_ts_set_tdata_parameters()
1066 tsdata->tdata_len = tsdata->point_len * tsdata->max_support_points + in edt_ft5x06_ts_set_tdata_parameters()
1067 tsdata->tdata_offset + crclen; in edt_ft5x06_ts_set_tdata_parameters()
1072 struct edt_reg_addr *reg_addr = &tsdata->reg_addr; in edt_ft5x06_ts_set_regs()
1074 switch (tsdata->version) { in edt_ft5x06_ts_set_regs()
1076 reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD; in edt_ft5x06_ts_set_regs()
1077 reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE; in edt_ft5x06_ts_set_regs()
1078 reg_addr->reg_gain = WORK_REGISTER_GAIN; in edt_ft5x06_ts_set_regs()
1079 reg_addr->reg_offset = WORK_REGISTER_OFFSET; in edt_ft5x06_ts_set_regs()
1080 reg_addr->reg_offset_x = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1081 reg_addr->reg_offset_y = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1082 reg_addr->reg_num_x = WORK_REGISTER_NUM_X; in edt_ft5x06_ts_set_regs()
1083 reg_addr->reg_num_y = WORK_REGISTER_NUM_Y; in edt_ft5x06_ts_set_regs()
1088 reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; in edt_ft5x06_ts_set_regs()
1089 reg_addr->reg_report_rate = tsdata->version == EDT_M12 ? in edt_ft5x06_ts_set_regs()
1091 reg_addr->reg_gain = M09_REGISTER_GAIN; in edt_ft5x06_ts_set_regs()
1092 reg_addr->reg_offset = M09_REGISTER_OFFSET; in edt_ft5x06_ts_set_regs()
1093 reg_addr->reg_offset_x = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1094 reg_addr->reg_offset_y = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1095 reg_addr->reg_num_x = M09_REGISTER_NUM_X; in edt_ft5x06_ts_set_regs()
1096 reg_addr->reg_num_y = M09_REGISTER_NUM_Y; in edt_ft5x06_ts_set_regs()
1100 reg_addr->reg_threshold = EV_REGISTER_THRESHOLD; in edt_ft5x06_ts_set_regs()
1101 reg_addr->reg_report_rate = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1102 reg_addr->reg_gain = EV_REGISTER_GAIN; in edt_ft5x06_ts_set_regs()
1103 reg_addr->reg_offset = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1104 reg_addr->reg_offset_x = EV_REGISTER_OFFSET_X; in edt_ft5x06_ts_set_regs()
1105 reg_addr->reg_offset_y = EV_REGISTER_OFFSET_Y; in edt_ft5x06_ts_set_regs()
1106 reg_addr->reg_num_x = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1107 reg_addr->reg_num_y = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1112 reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; in edt_ft5x06_ts_set_regs()
1113 reg_addr->reg_report_rate = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1114 reg_addr->reg_gain = M09_REGISTER_GAIN; in edt_ft5x06_ts_set_regs()
1115 reg_addr->reg_offset = M09_REGISTER_OFFSET; in edt_ft5x06_ts_set_regs()
1116 reg_addr->reg_offset_x = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1117 reg_addr->reg_offset_y = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1118 reg_addr->reg_num_x = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1119 reg_addr->reg_num_y = NO_REGISTER; in edt_ft5x06_ts_set_regs()
1128 if (!IS_ERR_OR_NULL(data->regmap)) in edt_ft5x06_exit_regmap()
1129 regmap_exit(data->regmap); in edt_ft5x06_exit_regmap()
1136 regulator_disable(data->vcc); in edt_ft5x06_disable_regulators()
1137 regulator_disable(data->iovcc); in edt_ft5x06_disable_regulators()
1151 dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n"); in edt_ft5x06_ts_probe()
1153 tsdata = devm_kzalloc(&client->dev, sizeof(*tsdata), GFP_KERNEL); in edt_ft5x06_ts_probe()
1155 dev_err(&client->dev, "failed to allocate driver data.\n"); in edt_ft5x06_ts_probe()
1156 return -ENOMEM; in edt_ft5x06_ts_probe()
1159 tsdata->regmap = regmap_init_i2c(client, &edt_ft5x06_i2c_regmap_config); in edt_ft5x06_ts_probe()
1160 if (IS_ERR(tsdata->regmap)) { in edt_ft5x06_ts_probe()
1161 dev_err(&client->dev, "regmap allocation failed\n"); in edt_ft5x06_ts_probe()
1162 return PTR_ERR(tsdata->regmap); in edt_ft5x06_ts_probe()
1167 * custom action because we may replace regmap with M06-specific one in edt_ft5x06_ts_probe()
1170 error = devm_add_action_or_reset(&client->dev, edt_ft5x06_exit_regmap, in edt_ft5x06_ts_probe()
1175 chip_data = device_get_match_data(&client->dev); in edt_ft5x06_ts_probe()
1177 chip_data = (const struct edt_i2c_chip_data *)id->driver_data; in edt_ft5x06_ts_probe()
1178 if (!chip_data || !chip_data->max_support_points) { in edt_ft5x06_ts_probe()
1179 dev_err(&client->dev, "invalid or missing chip data\n"); in edt_ft5x06_ts_probe()
1180 return -EINVAL; in edt_ft5x06_ts_probe()
1183 tsdata->max_support_points = chip_data->max_support_points; in edt_ft5x06_ts_probe()
1185 tsdata->vcc = devm_regulator_get(&client->dev, "vcc"); in edt_ft5x06_ts_probe()
1186 if (IS_ERR(tsdata->vcc)) in edt_ft5x06_ts_probe()
1187 return dev_err_probe(&client->dev, PTR_ERR(tsdata->vcc), in edt_ft5x06_ts_probe()
1190 tsdata->iovcc = devm_regulator_get(&client->dev, "iovcc"); in edt_ft5x06_ts_probe()
1191 if (IS_ERR(tsdata->iovcc)) { in edt_ft5x06_ts_probe()
1192 error = PTR_ERR(tsdata->iovcc); in edt_ft5x06_ts_probe()
1193 if (error != -EPROBE_DEFER) in edt_ft5x06_ts_probe()
1194 dev_err(&client->dev, in edt_ft5x06_ts_probe()
1199 error = regulator_enable(tsdata->iovcc); in edt_ft5x06_ts_probe()
1201 dev_err(&client->dev, "failed to enable iovcc: %d\n", error); in edt_ft5x06_ts_probe()
1208 error = regulator_enable(tsdata->vcc); in edt_ft5x06_ts_probe()
1210 dev_err(&client->dev, "failed to enable vcc: %d\n", error); in edt_ft5x06_ts_probe()
1211 regulator_disable(tsdata->iovcc); in edt_ft5x06_ts_probe()
1215 error = devm_add_action_or_reset(&client->dev, in edt_ft5x06_ts_probe()
1221 tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev, in edt_ft5x06_ts_probe()
1223 if (IS_ERR(tsdata->reset_gpio)) { in edt_ft5x06_ts_probe()
1224 error = PTR_ERR(tsdata->reset_gpio); in edt_ft5x06_ts_probe()
1225 dev_err(&client->dev, in edt_ft5x06_ts_probe()
1230 tsdata->wake_gpio = devm_gpiod_get_optional(&client->dev, in edt_ft5x06_ts_probe()
1232 if (IS_ERR(tsdata->wake_gpio)) { in edt_ft5x06_ts_probe()
1233 error = PTR_ERR(tsdata->wake_gpio); in edt_ft5x06_ts_probe()
1234 dev_err(&client->dev, in edt_ft5x06_ts_probe()
1240 * Check which sleep modes we can support. Power-off requieres the in edt_ft5x06_ts_probe()
1241 * reset-pin to ensure correct power-down/power-up behaviour. Start with in edt_ft5x06_ts_probe()
1245 if (tsdata->reset_gpio) in edt_ft5x06_ts_probe()
1246 tsdata->suspend_mode = EDT_PMODE_POWEROFF; in edt_ft5x06_ts_probe()
1247 else if (tsdata->wake_gpio) in edt_ft5x06_ts_probe()
1248 tsdata->suspend_mode = EDT_PMODE_HIBERNATE; in edt_ft5x06_ts_probe()
1250 tsdata->suspend_mode = EDT_PMODE_NOT_SUPPORTED; in edt_ft5x06_ts_probe()
1252 if (tsdata->wake_gpio) { in edt_ft5x06_ts_probe()
1254 gpiod_set_value_cansleep(tsdata->wake_gpio, 1); in edt_ft5x06_ts_probe()
1258 if (tsdata->reset_gpio) { in edt_ft5x06_ts_probe()
1260 gpiod_set_value_cansleep(tsdata->reset_gpio, 0); in edt_ft5x06_ts_probe()
1264 input = devm_input_allocate_device(&client->dev); in edt_ft5x06_ts_probe()
1266 dev_err(&client->dev, "failed to allocate input device.\n"); in edt_ft5x06_ts_probe()
1267 return -ENOMEM; in edt_ft5x06_ts_probe()
1270 mutex_init(&tsdata->mutex); in edt_ft5x06_ts_probe()
1271 tsdata->client = client; in edt_ft5x06_ts_probe()
1272 tsdata->input = input; in edt_ft5x06_ts_probe()
1273 tsdata->factory_mode = false; in edt_ft5x06_ts_probe()
1278 dev_err(&client->dev, "touchscreen probe failed\n"); in edt_ft5x06_ts_probe()
1286 regmap_read(tsdata->regmap, 0x00, &val); in edt_ft5x06_ts_probe()
1290 edt_ft5x06_ts_get_defaults(&client->dev, tsdata); in edt_ft5x06_ts_probe()
1293 if (tsdata->reg_addr.reg_report_rate != NO_REGISTER && in edt_ft5x06_ts_probe()
1294 !device_property_read_u32(&client->dev, in edt_ft5x06_ts_probe()
1295 "report-rate-hz", &report_rate)) { in edt_ft5x06_ts_probe()
1296 if (tsdata->version == EDT_M06) in edt_ft5x06_ts_probe()
1297 tsdata->report_rate = clamp_val(report_rate, 30, 140); in edt_ft5x06_ts_probe()
1299 tsdata->report_rate = clamp_val(report_rate, 1, 255); in edt_ft5x06_ts_probe()
1301 if (report_rate != tsdata->report_rate) in edt_ft5x06_ts_probe()
1302 dev_warn(&client->dev, in edt_ft5x06_ts_probe()
1303 "report-rate %dHz is unsupported, use %dHz\n", in edt_ft5x06_ts_probe()
1304 report_rate, tsdata->report_rate); in edt_ft5x06_ts_probe()
1306 if (tsdata->version == EDT_M06) in edt_ft5x06_ts_probe()
1307 tsdata->report_rate /= 10; in edt_ft5x06_ts_probe()
1309 regmap_write(tsdata->regmap, tsdata->reg_addr.reg_report_rate, in edt_ft5x06_ts_probe()
1310 tsdata->report_rate); in edt_ft5x06_ts_probe()
1313 dev_dbg(&client->dev, in edt_ft5x06_ts_probe()
1315 tsdata->name, tsdata->fw_version, tsdata->num_x, tsdata->num_y); in edt_ft5x06_ts_probe()
1317 input->name = tsdata->name; in edt_ft5x06_ts_probe()
1318 input->id.bustype = BUS_I2C; in edt_ft5x06_ts_probe()
1319 input->dev.parent = &client->dev; in edt_ft5x06_ts_probe()
1322 0, tsdata->num_x * 64 - 1, 0, 0); in edt_ft5x06_ts_probe()
1324 0, tsdata->num_y * 64 - 1, 0, 0); in edt_ft5x06_ts_probe()
1326 touchscreen_parse_properties(input, true, &tsdata->prop); in edt_ft5x06_ts_probe()
1328 error = input_mt_init_slots(input, tsdata->max_support_points, in edt_ft5x06_ts_probe()
1331 dev_err(&client->dev, "Unable to init MT slots.\n"); in edt_ft5x06_ts_probe()
1335 irq_flags = irq_get_trigger_type(client->irq); in edt_ft5x06_ts_probe()
1340 error = devm_request_threaded_irq(&client->dev, client->irq, in edt_ft5x06_ts_probe()
1342 client->name, tsdata); in edt_ft5x06_ts_probe()
1344 dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); in edt_ft5x06_ts_probe()
1352 edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); in edt_ft5x06_ts_probe()
1354 dev_dbg(&client->dev, in edt_ft5x06_ts_probe()
1355 "EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n", in edt_ft5x06_ts_probe()
1356 client->irq, in edt_ft5x06_ts_probe()
1357 tsdata->wake_gpio ? desc_to_gpio(tsdata->wake_gpio) : -1, in edt_ft5x06_ts_probe()
1358 tsdata->reset_gpio ? desc_to_gpio(tsdata->reset_gpio) : -1); in edt_ft5x06_ts_probe()
1374 struct gpio_desc *reset_gpio = tsdata->reset_gpio; in edt_ft5x06_ts_suspend()
1380 if (tsdata->suspend_mode == EDT_PMODE_NOT_SUPPORTED) in edt_ft5x06_ts_suspend()
1384 ret = regmap_write(tsdata->regmap, PMOD_REGISTER_OPMODE, in edt_ft5x06_ts_suspend()
1389 if (tsdata->suspend_mode == EDT_PMODE_HIBERNATE) in edt_ft5x06_ts_suspend()
1393 * Power-off according the datasheet. Cut the power may leaf the irq in edt_ft5x06_ts_suspend()
1398 disable_irq(tsdata->client->irq); in edt_ft5x06_ts_suspend()
1403 ret = regulator_disable(tsdata->vcc); in edt_ft5x06_ts_suspend()
1406 ret = regulator_disable(tsdata->iovcc); in edt_ft5x06_ts_suspend()
1422 if (tsdata->suspend_mode == EDT_PMODE_NOT_SUPPORTED) in edt_ft5x06_ts_resume()
1425 if (tsdata->suspend_mode == EDT_PMODE_POWEROFF) { in edt_ft5x06_ts_resume()
1426 struct gpio_desc *reset_gpio = tsdata->reset_gpio; in edt_ft5x06_ts_resume()
1439 ret = regulator_enable(tsdata->iovcc); in edt_ft5x06_ts_resume()
1448 ret = regulator_enable(tsdata->vcc); in edt_ft5x06_ts_resume()
1451 regulator_disable(tsdata->iovcc); in edt_ft5x06_ts_resume()
1460 enable_irq(tsdata->client->irq); in edt_ft5x06_ts_resume()
1462 if (tsdata->factory_mode) in edt_ft5x06_ts_resume()
1465 struct gpio_desc *wake_gpio = tsdata->wake_gpio; in edt_ft5x06_ts_resume()
1503 { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
1504 { .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
1505 { .name = "ev-ft5726", .driver_data = (long)&edt_ft5506_data },
1507 /* Note no edt- prefix for compatibility with the ft6236.c driver */
1516 { .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data },
1517 { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data },
1518 { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data },
1519 { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
1520 { .compatible = "evervision,ev-ft5726", .data = &edt_ft5506_data },
1547 MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver");