Lines Matching +full:cmd +full:- +full:max +full:- +full:name
1 // SPDX-License-Identifier: GPL-2.0
6 * Copyright (C) 2012-2015 Cypress Semiconductor
13 #include <linux/crc-itu-t.h>
32 #define CY_NUM_BTN_EVENT_ID GENMASK(CY_BITS_PER_BTN - 1, 0)
161 size_t max; /* max value */ member
219 static int cyttsp5_read(struct cyttsp5 *ts, u8 *buf, u32 max) in cyttsp5_read() argument
226 error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, temp, sizeof(temp)); in cyttsp5_read()
234 if (size > max) in cyttsp5_read()
235 return -EINVAL; in cyttsp5_read()
238 return regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, size); in cyttsp5_read()
244 u8 cmd[HID_OUTPUT_MAX_CMD_SIZE]; in cyttsp5_write() local
247 return -E2BIG; in cyttsp5_write()
249 /* High bytes of register address needed as first byte of cmd */ in cyttsp5_write()
250 cmd[0] = (reg >> 8) & 0xFF; in cyttsp5_write()
254 memcpy(&cmd[1], data, size); in cyttsp5_write()
261 * data byte is the high register + left of the cmd to send in cyttsp5_write()
263 return regmap_bulk_write(ts->regmap, reg & 0xFF, cmd, size + 1); in cyttsp5_write()
266 static void cyttsp5_get_touch_axis(int *axis, int size, int max, u8 *xy_data, in cyttsp5_get_touch_axis() argument
274 *axis &= max - 1; in cyttsp5_get_touch_axis()
280 struct cyttsp5_sysinfo *si = &ts->sysinfo; in cyttsp5_get_touch_record()
284 cyttsp5_get_touch_axis(&touch->abs[abs], in cyttsp5_get_touch_record()
285 si->tch_abs[abs].size, in cyttsp5_get_touch_record()
286 si->tch_abs[abs].max, in cyttsp5_get_touch_record()
287 xy_data + si->tch_abs[abs].ofs, in cyttsp5_get_touch_record()
288 si->tch_abs[abs].bofs); in cyttsp5_get_touch_record()
294 struct cyttsp5_sysinfo *si = &ts->sysinfo; in cyttsp5_get_mt_touches()
301 memset(tch->abs, 0, sizeof(tch->abs)); in cyttsp5_get_mt_touches()
303 switch (ts->input_buf[2]) { in cyttsp5_get_mt_touches()
313 tch_addr = ts->input_buf + offset + (i * TOUCH_REPORT_SIZE); in cyttsp5_get_mt_touches()
317 tmp = tch->abs[CY_TCH_MAJ] * 100 * si->sensing_conf_data.res_x; in cyttsp5_get_mt_touches()
318 tch->abs[CY_TCH_MAJ] = tmp / si->sensing_conf_data.len_x; in cyttsp5_get_mt_touches()
319 tmp = tch->abs[CY_TCH_MIN] * 100 * si->sensing_conf_data.res_x; in cyttsp5_get_mt_touches()
320 tch->abs[CY_TCH_MIN] = tmp / si->sensing_conf_data.len_x; in cyttsp5_get_mt_touches()
322 t = tch->abs[CY_TCH_T]; in cyttsp5_get_mt_touches()
323 input_mt_slot(ts->input, t); in cyttsp5_get_mt_touches()
324 input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); in cyttsp5_get_mt_touches()
328 touchscreen_report_pos(ts->input, &ts->prop, in cyttsp5_get_mt_touches()
329 tch->abs[CY_TCH_X], tch->abs[CY_TCH_Y], in cyttsp5_get_mt_touches()
331 input_report_abs(ts->input, ABS_MT_PRESSURE, in cyttsp5_get_mt_touches()
332 tch->abs[CY_TCH_P]); in cyttsp5_get_mt_touches()
335 input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, in cyttsp5_get_mt_touches()
336 tch->abs[CY_TCH_MAJ]); in cyttsp5_get_mt_touches()
337 input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, in cyttsp5_get_mt_touches()
338 tch->abs[CY_TCH_MIN]); in cyttsp5_get_mt_touches()
341 ts->num_prv_rec = num_cur_tch; in cyttsp5_get_mt_touches()
347 struct cyttsp5_sysinfo *si = &ts->sysinfo; in cyttsp5_mt_attention()
348 int max_tch = si->sensing_conf_data.max_tch; in cyttsp5_mt_attention()
352 cyttsp5_get_touch_axis(&num_cur_tch, si->tch_hdr.size, in cyttsp5_mt_attention()
353 si->tch_hdr.max, in cyttsp5_mt_attention()
354 ts->input_buf + 3 + si->tch_hdr.ofs, in cyttsp5_mt_attention()
355 si->tch_hdr.bofs); in cyttsp5_mt_attention()
362 if (num_cur_tch == 0 && ts->num_prv_rec == 0) in cyttsp5_mt_attention()
369 input_mt_sync_frame(ts->input); in cyttsp5_mt_attention()
370 input_sync(ts->input); in cyttsp5_mt_attention()
378 struct cyttsp5_sysinfo *si = &ts->sysinfo; in cyttsp5_setup_input_device()
383 max_x_tmp = si->sensing_conf_data.res_x; in cyttsp5_setup_input_device()
384 max_y_tmp = si->sensing_conf_data.res_y; in cyttsp5_setup_input_device()
385 max_x = max_x_tmp - 1; in cyttsp5_setup_input_device()
386 max_y = max_y_tmp - 1; in cyttsp5_setup_input_device()
387 max_p = si->sensing_conf_data.max_z; in cyttsp5_setup_input_device()
389 input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, max_x, 0, 0); in cyttsp5_setup_input_device()
390 input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, max_y, 0, 0); in cyttsp5_setup_input_device()
391 input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, max_p, 0, 0); in cyttsp5_setup_input_device()
393 input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0); in cyttsp5_setup_input_device()
394 input_set_abs_params(ts->input, ABS_MT_TOUCH_MINOR, 0, MAX_AREA, 0, 0); in cyttsp5_setup_input_device()
396 error = input_mt_init_slots(ts->input, si->tch_abs[CY_TCH_T].max, in cyttsp5_setup_input_device()
401 error = input_register_device(ts->input); in cyttsp5_setup_input_device()
413 struct cyttsp5_sysinfo *si = &ts->sysinfo; in cyttsp5_parse_dt_key_code()
415 if (!si->num_btns) in cyttsp5_parse_dt_key_code()
419 memset32(si->key_code, KEY_RESERVED, si->num_btns); in cyttsp5_parse_dt_key_code()
422 si->key_code, si->num_btns); in cyttsp5_parse_dt_key_code()
428 struct cyttsp5_sysinfo *si = &ts->sysinfo; in cyttsp5_btn_attention()
432 switch (ts->input_buf[2]) { in cyttsp5_btn_attention()
441 if (ts->input_buf[2] != HID_BTN_REPORT_ID) in cyttsp5_btn_attention()
445 for (cur_btn = 0; cur_btn < si->num_btns; cur_btn++) { in cyttsp5_btn_attention()
447 cur_btn_state = (ts->input_buf[offset] >> (cur_btn * CY_BITS_PER_BTN)) in cyttsp5_btn_attention()
450 input_report_key(ts->input, si->key_code[cur_btn], in cyttsp5_btn_attention()
452 input_sync(ts->input); in cyttsp5_btn_attention()
464 size = get_unaligned_le16(&ts->response_buf[0]); in cyttsp5_validate_cmd_response()
468 report_id = ts->response_buf[HID_OUTPUT_RESPONSE_REPORT_OFFSET]; in cyttsp5_validate_cmd_response()
472 if (ts->response_buf[4] != HID_OUTPUT_BL_SOP) { in cyttsp5_validate_cmd_response()
473 dev_err(ts->dev, "HID output response, wrong SOP\n"); in cyttsp5_validate_cmd_response()
474 return -EPROTO; in cyttsp5_validate_cmd_response()
477 if (ts->response_buf[size - 1] != HID_OUTPUT_BL_EOP) { in cyttsp5_validate_cmd_response()
478 dev_err(ts->dev, "HID output response, wrong EOP\n"); in cyttsp5_validate_cmd_response()
479 return -EPROTO; in cyttsp5_validate_cmd_response()
482 crc = crc_itu_t(0xFFFF, &ts->response_buf[4], size - 7); in cyttsp5_validate_cmd_response()
483 if (get_unaligned_le16(&ts->response_buf[size - 3]) != crc) { in cyttsp5_validate_cmd_response()
484 dev_err(ts->dev, in cyttsp5_validate_cmd_response()
487 return -EPROTO; in cyttsp5_validate_cmd_response()
490 status = ts->response_buf[5]; in cyttsp5_validate_cmd_response()
492 dev_err(ts->dev, "HID output response, ERROR:%d\n", in cyttsp5_validate_cmd_response()
494 return -EPROTO; in cyttsp5_validate_cmd_response()
499 command_code = ts->response_buf[HID_OUTPUT_RESPONSE_CMD_OFFSET] in cyttsp5_validate_cmd_response()
502 dev_err(ts->dev, in cyttsp5_validate_cmd_response()
505 return -EPROTO; in cyttsp5_validate_cmd_response()
515 struct cyttsp5_sysinfo *si = &ts->sysinfo; in cyttsp5_si_get_btn_data()
516 unsigned int btns = ts->response_buf[HID_SYSINFO_BTN_OFFSET] & in cyttsp5_si_get_btn_data()
519 si->num_btns = hweight8(btns); in cyttsp5_si_get_btn_data()
524 struct cyttsp5_sensing_conf_data *scd = &ts->sysinfo.sensing_conf_data; in cyttsp5_get_sysinfo_regs()
527 &ts->response_buf[HID_SYSINFO_SENSING_OFFSET]; in cyttsp5_get_sysinfo_regs()
531 scd->max_tch = scd_dev->max_num_of_tch_per_refresh_cycle; in cyttsp5_get_sysinfo_regs()
532 scd->res_x = get_unaligned_le16(&scd_dev->res_x); in cyttsp5_get_sysinfo_regs()
533 scd->res_y = get_unaligned_le16(&scd_dev->res_y); in cyttsp5_get_sysinfo_regs()
534 scd->max_z = get_unaligned_le16(&scd_dev->max_z); in cyttsp5_get_sysinfo_regs()
535 scd->len_x = get_unaligned_le16(&scd_dev->len_x); in cyttsp5_get_sysinfo_regs()
536 scd->len_y = get_unaligned_le16(&scd_dev->len_y); in cyttsp5_get_sysinfo_regs()
544 u8 cmd[HID_OUTPUT_GET_SYSINFO_SIZE]; in cyttsp5_hid_output_get_sysinfo() local
547 put_unaligned_le16(HID_OUTPUT_GET_SYSINFO_SIZE, cmd); in cyttsp5_hid_output_get_sysinfo()
548 cmd[2] = HID_APP_OUTPUT_REPORT_ID; in cyttsp5_hid_output_get_sysinfo()
549 cmd[3] = 0x0; /* Reserved */ in cyttsp5_hid_output_get_sysinfo()
550 cmd[4] = HID_OUTPUT_GET_SYSINFO; in cyttsp5_hid_output_get_sysinfo()
552 rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd, in cyttsp5_hid_output_get_sysinfo()
555 dev_err(ts->dev, "Failed to write command %d", rc); in cyttsp5_hid_output_get_sysinfo()
559 rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, in cyttsp5_hid_output_get_sysinfo()
562 dev_err(ts->dev, "HID output cmd execution timed out\n"); in cyttsp5_hid_output_get_sysinfo()
563 rc = -ETIMEDOUT; in cyttsp5_hid_output_get_sysinfo()
569 dev_err(ts->dev, "Validation of the response failed\n"); in cyttsp5_hid_output_get_sysinfo()
579 u8 cmd[2] = { 0 }; in cyttsp5_power_control() local
582 SET_CMD_REPORT_TYPE(cmd[0], 0); in cyttsp5_power_control()
583 SET_CMD_REPORT_ID(cmd[0], HID_POWER_SLEEP); in cyttsp5_power_control()
584 SET_CMD_OPCODE(cmd[1], HID_CMD_SET_POWER); in cyttsp5_power_control()
586 rc = cyttsp5_write(ts, HID_COMMAND_REG, cmd, sizeof(cmd)); in cyttsp5_power_control()
588 dev_err(ts->dev, "Failed to write power command %d", rc); in cyttsp5_power_control()
592 rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, in cyttsp5_power_control()
595 dev_err(ts->dev, "HID power cmd execution timed out\n"); in cyttsp5_power_control()
596 return -ETIMEDOUT; in cyttsp5_power_control()
599 if (ts->response_buf[2] != HID_RESPONSE_REPORT_ID || in cyttsp5_power_control()
600 (ts->response_buf[3] & 0x03) != state || in cyttsp5_power_control()
601 (ts->response_buf[4] & 0x0f) != HID_CMD_SET_POWER) { in cyttsp5_power_control()
602 dev_err(ts->dev, "Validation of the %s response failed\n", in cyttsp5_power_control()
604 return -EINVAL; in cyttsp5_power_control()
613 u8 cmd[HID_OUTPUT_BL_LAUNCH_APP_SIZE]; in cyttsp5_hid_output_bl_launch_app() local
616 put_unaligned_le16(HID_OUTPUT_BL_LAUNCH_APP_SIZE, cmd); in cyttsp5_hid_output_bl_launch_app()
617 cmd[2] = HID_BL_OUTPUT_REPORT_ID; in cyttsp5_hid_output_bl_launch_app()
618 cmd[3] = 0x0; /* Reserved */ in cyttsp5_hid_output_bl_launch_app()
619 cmd[4] = HID_OUTPUT_BL_SOP; in cyttsp5_hid_output_bl_launch_app()
620 cmd[5] = HID_OUTPUT_BL_LAUNCH_APP; in cyttsp5_hid_output_bl_launch_app()
621 put_unaligned_le16(0x00, &cmd[6]); in cyttsp5_hid_output_bl_launch_app()
622 crc = crc_itu_t(0xFFFF, &cmd[4], 4); in cyttsp5_hid_output_bl_launch_app()
623 put_unaligned_le16(crc, &cmd[8]); in cyttsp5_hid_output_bl_launch_app()
624 cmd[10] = HID_OUTPUT_BL_EOP; in cyttsp5_hid_output_bl_launch_app()
626 rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd, in cyttsp5_hid_output_bl_launch_app()
629 dev_err(ts->dev, "Failed to write command %d", rc); in cyttsp5_hid_output_bl_launch_app()
633 rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, in cyttsp5_hid_output_bl_launch_app()
636 dev_err(ts->dev, "HID output cmd execution timed out\n"); in cyttsp5_hid_output_bl_launch_app()
637 rc = -ETIMEDOUT; in cyttsp5_hid_output_bl_launch_app()
643 dev_err(ts->dev, "Validation of the response failed\n"); in cyttsp5_hid_output_bl_launch_app()
653 struct device *dev = ts->dev; in cyttsp5_get_hid_descriptor()
662 rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, in cyttsp5_get_hid_descriptor()
665 dev_err(ts->dev, "HID get descriptor timed out\n"); in cyttsp5_get_hid_descriptor()
666 rc = -ETIMEDOUT; in cyttsp5_get_hid_descriptor()
670 memcpy(desc, ts->response_buf, sizeof(*desc)); in cyttsp5_get_hid_descriptor()
673 if (le16_to_cpu(desc->hid_desc_len) != sizeof(*desc) || in cyttsp5_get_hid_descriptor()
674 le16_to_cpu(desc->bcd_version) != HID_VERSION) { in cyttsp5_get_hid_descriptor()
676 return -ENODEV; in cyttsp5_get_hid_descriptor()
685 tch_abs->ofs = offset / 8; in fill_tch_abs()
686 tch_abs->size = report_size / 8; in fill_tch_abs()
688 tch_abs->size += 1; in fill_tch_abs()
689 tch_abs->min = 0; in fill_tch_abs()
690 tch_abs->max = 1 << report_size; in fill_tch_abs()
691 tch_abs->bofs = offset - (tch_abs->ofs << 3); in fill_tch_abs()
703 error = cyttsp5_read(ts, ts->input_buf, CY_MAX_INPUT); in cyttsp5_handle_irq()
707 size = get_unaligned_le16(&ts->input_buf[0]); in cyttsp5_handle_irq()
713 report_id = ts->input_buf[2]; in cyttsp5_handle_irq()
718 cyttsp5_mt_attention(ts->dev); in cyttsp5_handle_irq()
721 cyttsp5_btn_attention(ts->dev); in cyttsp5_handle_irq()
724 memcpy(ts->response_buf, ts->input_buf, size); in cyttsp5_handle_irq()
725 complete(&ts->cmd_done); in cyttsp5_handle_irq()
729 memcpy(ts->response_buf, ts->input_buf, size); in cyttsp5_handle_irq()
730 complete(&ts->cmd_done); in cyttsp5_handle_irq()
742 error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, sizeof(buf)); in cyttsp5_deassert_int()
750 return -EINVAL; in cyttsp5_deassert_int()
755 struct cyttsp5_sysinfo *si = &ts->sysinfo; in cyttsp5_fill_all_touch()
757 fill_tch_abs(&si->tch_abs[CY_TCH_X], REPORT_SIZE_16, in cyttsp5_fill_all_touch()
759 fill_tch_abs(&si->tch_abs[CY_TCH_Y], REPORT_SIZE_16, in cyttsp5_fill_all_touch()
761 fill_tch_abs(&si->tch_abs[CY_TCH_P], REPORT_SIZE_8, in cyttsp5_fill_all_touch()
763 fill_tch_abs(&si->tch_abs[CY_TCH_T], REPORT_SIZE_5, in cyttsp5_fill_all_touch()
765 fill_tch_abs(&si->tch_hdr, REPORT_SIZE_5, in cyttsp5_fill_all_touch()
767 fill_tch_abs(&si->tch_abs[CY_TCH_MAJ], REPORT_SIZE_8, in cyttsp5_fill_all_touch()
769 fill_tch_abs(&si->tch_abs[CY_TCH_MIN], REPORT_SIZE_8, in cyttsp5_fill_all_touch()
781 dev_err(ts->dev, "Error on deassert int r=%d\n", error); in cyttsp5_startup()
782 return -ENODEV; in cyttsp5_startup()
787 * because of a power-on-reset in cyttsp5_startup()
791 dev_err(ts->dev, "Error on launch app r=%d\n", error); in cyttsp5_startup()
795 error = cyttsp5_get_hid_descriptor(ts, &ts->hid_desc); in cyttsp5_startup()
797 dev_err(ts->dev, "Error on getting HID descriptor r=%d\n", error); in cyttsp5_startup()
803 dev_err(ts->dev, "Error on report descriptor r=%d\n", error); in cyttsp5_startup()
809 dev_err(ts->dev, "Error on getting sysinfo r=%d\n", error); in cyttsp5_startup()
820 regulator_bulk_disable(ARRAY_SIZE(ts->supplies), ts->supplies); in cyttsp5_cleanup()
824 const char *name) in cyttsp5_probe() argument
832 return -ENOMEM; in cyttsp5_probe()
835 ts->regmap = regmap; in cyttsp5_probe()
836 ts->dev = dev; in cyttsp5_probe()
837 si = &ts->sysinfo; in cyttsp5_probe()
840 init_completion(&ts->cmd_done); in cyttsp5_probe()
843 ts->supplies[0].supply = "vdd"; in cyttsp5_probe()
844 ts->supplies[1].supply = "vddio"; in cyttsp5_probe()
845 error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->supplies), in cyttsp5_probe()
846 ts->supplies); in cyttsp5_probe()
848 dev_err(ts->dev, "Failed to get regulators, error %d\n", error); in cyttsp5_probe()
856 error = regulator_bulk_enable(ARRAY_SIZE(ts->supplies), ts->supplies); in cyttsp5_probe()
858 dev_err(ts->dev, "Failed to enable regulators, error %d\n", error); in cyttsp5_probe()
862 ts->input = devm_input_allocate_device(dev); in cyttsp5_probe()
863 if (!ts->input) { in cyttsp5_probe()
865 return -ENODEV; in cyttsp5_probe()
868 ts->input->name = "cyttsp5"; in cyttsp5_probe()
869 scnprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); in cyttsp5_probe()
870 ts->input->phys = ts->phys; in cyttsp5_probe()
871 input_set_drvdata(ts->input, ts); in cyttsp5_probe()
874 ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); in cyttsp5_probe()
875 if (IS_ERR(ts->reset_gpio)) { in cyttsp5_probe()
876 error = PTR_ERR(ts->reset_gpio); in cyttsp5_probe()
880 gpiod_set_value_cansleep(ts->reset_gpio, 0); in cyttsp5_probe()
886 IRQF_ONESHOT, name, ts); in cyttsp5_probe()
894 dev_err(ts->dev, "Fail initial startup r=%d\n", error); in cyttsp5_probe()
900 dev_err(ts->dev, "Error while parsing dts %d\n", error); in cyttsp5_probe()
904 touchscreen_parse_properties(ts->input, true, &ts->prop); in cyttsp5_probe()
906 __set_bit(EV_KEY, ts->input->evbit); in cyttsp5_probe()
907 for (i = 0; i < si->num_btns; i++) in cyttsp5_probe()
908 __set_bit(si->key_code[i], ts->input->keybit); in cyttsp5_probe()
923 dev_err(&client->dev, "regmap allocation failed: %ld\n", in cyttsp5_i2c_probe()
928 return cyttsp5_probe(&client->dev, regmap, client->irq, client->name); in cyttsp5_i2c_probe()
967 .name = CYTTSP5_NAME,