Lines Matching +full:i2c +full:- +full:hid

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Goodix GT7986U SPI Driver Code for HID.
9 #include <linux/hid.h>
96 struct hid_device *hid; member
103 /* lock for hid raw request operation */
105 /* buffer used to store hid report event */
115 struct spi_device *spi = to_spi_device(&ts->spi->dev); in goodix_get_event_report()
133 dev_err(ts->dev, "spi transfer error: %d", error); in goodix_get_event_report()
143 struct spi_device *spi = to_spi_device(&ts->spi->dev); in goodix_spi_read()
148 if (GOODIX_SPI_READ_PREFIX_LEN + len > sizeof(ts->xfer_buf)) { in goodix_spi_read()
149 dev_err(ts->dev, "read data len exceed limit %zu", in goodix_spi_read()
150 sizeof(ts->xfer_buf) - GOODIX_SPI_READ_PREFIX_LEN); in goodix_spi_read()
151 return -EINVAL; in goodix_spi_read()
155 ts->xfer_buf[0] = GOODIX_SPI_READ_FLAG; in goodix_spi_read()
156 put_unaligned_be32(addr, ts->xfer_buf + GOODIX_SPI_TRANS_PREFIX_LEN); in goodix_spi_read()
160 xfers.tx_buf = ts->xfer_buf; in goodix_spi_read()
161 xfers.rx_buf = ts->xfer_buf; in goodix_spi_read()
167 dev_err(ts->dev, "spi transfer error: %d", error); in goodix_spi_read()
169 memcpy(data, ts->xfer_buf + GOODIX_SPI_READ_PREFIX_LEN, len); in goodix_spi_read()
177 struct spi_device *spi = to_spi_device(&ts->spi->dev); in goodix_spi_write()
182 if (GOODIX_SPI_WRITE_PREFIX_LEN + len > sizeof(ts->xfer_buf)) { in goodix_spi_write()
183 dev_err(ts->dev, "write data len exceed limit %zu", in goodix_spi_write()
184 sizeof(ts->xfer_buf) - GOODIX_SPI_WRITE_PREFIX_LEN); in goodix_spi_write()
185 return -EINVAL; in goodix_spi_write()
189 ts->xfer_buf[0] = GOODIX_SPI_WRITE_FLAG; in goodix_spi_write()
190 put_unaligned_be32(addr, ts->xfer_buf + GOODIX_SPI_TRANS_PREFIX_LEN); in goodix_spi_write()
191 memcpy(ts->xfer_buf + GOODIX_SPI_WRITE_PREFIX_LEN, data, len); in goodix_spi_write()
195 xfers.tx_buf = ts->xfer_buf; in goodix_spi_write()
201 dev_err(ts->dev, "spi transfer error: %d", error); in goodix_spi_write()
212 gpiod_set_value_cansleep(ts->reset_gpio, 0); in goodix_dev_confirm()
216 while (retry--) { in goodix_dev_confirm()
233 dev_err(ts->dev, "device confirm failed, rx_buf: %*ph", 8, rx_buf); in goodix_dev_confirm()
234 return -EINVAL; in goodix_dev_confirm()
238 * goodix_hid_parse() - hid-core .parse() callback
239 * @hid: hid device instance
245 static int goodix_hid_parse(struct hid_device *hid) in goodix_hid_parse() argument
247 struct goodix_ts_data *ts = hid->driver_data; in goodix_hid_parse()
251 rsize = le16_to_cpu(ts->hid_desc.report_desc_length); in goodix_hid_parse()
253 dev_err(ts->dev, "invalid report desc size, %d", rsize); in goodix_hid_parse()
254 return -EINVAL; in goodix_hid_parse()
259 return -ENOMEM; in goodix_hid_parse()
263 dev_err(ts->dev, "failed get report desc, %d", error); in goodix_hid_parse()
267 error = hid_parse_report(hid, rdesc, rsize); in goodix_hid_parse()
269 dev_err(ts->dev, "failed parse report, %d", error); in goodix_hid_parse()
278 return ((report->size - 1) >> 3) + 1 + in goodix_hid_get_report_length()
279 report->device->report_enum[report->type].numbered + 2; in goodix_hid_get_report_length()
282 static void goodix_hid_find_max_report(struct hid_device *hid, unsigned int type, in goodix_hid_find_max_report() argument
288 list_for_each_entry(report, &hid->report_enum[type].report_list, list) { in goodix_hid_find_max_report()
295 static int goodix_hid_start(struct hid_device *hid) in goodix_hid_start() argument
297 struct goodix_ts_data *ts = hid->driver_data; in goodix_hid_start()
301 goodix_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize); in goodix_hid_start()
302 goodix_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize); in goodix_hid_start()
303 goodix_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); in goodix_hid_start()
307 if (report_size <= ts->hid_max_event_sz) in goodix_hid_start()
310 ts->event_buf = devm_krealloc(ts->dev, ts->event_buf, in goodix_hid_start()
312 if (!ts->event_buf) in goodix_hid_start()
313 return -ENOMEM; in goodix_hid_start()
315 ts->hid_max_event_sz = report_size; in goodix_hid_start()
319 static void goodix_hid_stop(struct hid_device *hid) in goodix_hid_stop() argument
321 hid->claimed = 0; in goodix_hid_stop()
324 static int goodix_hid_open(struct hid_device *hid) in goodix_hid_open() argument
326 struct goodix_ts_data *ts = hid->driver_data; in goodix_hid_open()
328 set_bit(GOODIX_HID_STARTED, &ts->flags); in goodix_hid_open()
332 static void goodix_hid_close(struct hid_device *hid) in goodix_hid_close() argument
334 struct goodix_ts_data *ts = hid->driver_data; in goodix_hid_close()
336 clear_bit(GOODIX_HID_STARTED, &ts->flags); in goodix_hid_close()
347 while (retry--) { in goodix_hid_check_ack_status()
349 * 3 bytes of hid request response data in goodix_hid_check_ack_status()
350 * - byte 0: Ack flag, value of 1 for data ready in goodix_hid_check_ack_status()
351 * - bytes 1-2: Response data length in goodix_hid_check_ack_status()
358 dev_err(ts->dev, "hrd.size too short: %d", len); in goodix_hid_check_ack_status()
359 return -EINVAL; in goodix_hid_check_ack_status()
361 *resp_len = len - GOODIX_HID_PKG_LEN_SIZE; in goodix_hid_check_ack_status()
369 return -EINVAL; in goodix_hid_check_ack_status()
373 * goodix_hid_get_raw_report() - Process hidraw GET REPORT operation
374 * @hid: hid device instance
381 * get report request. The transmitted data follows the standard i2c-hid
386 static int goodix_hid_get_raw_report(struct hid_device *hid, in goodix_hid_get_raw_report() argument
391 struct goodix_ts_data *ts = hid->driver_data; in goodix_hid_get_raw_report()
392 u16 data_register = le16_to_cpu(ts->hid_desc.data_register); in goodix_hid_get_raw_report()
393 u16 cmd_register = le16_to_cpu(ts->hid_desc.cmd_register); in goodix_hid_get_raw_report()
401 return -EINVAL; in goodix_hid_get_raw_report()
407 dev_err(ts->dev, "failed get win8 sign: %d", error); in goodix_hid_get_raw_report()
408 return -EINVAL; in goodix_hid_get_raw_report()
419 /* Clean 3 bytes of hid ack header data */ in goodix_hid_get_raw_report()
438 dev_err(ts->dev, "failed send read feature cmd, %d", error); in goodix_hid_get_raw_report()
455 /* Step3: read response data(skip 2bytes of hid pkg length) */ in goodix_hid_get_raw_report()
460 dev_err(ts->dev, "failed read hid response data, %d", error); in goodix_hid_get_raw_report()
465 dev_err(ts->dev, "incorrect report (%d vs %d expected)", in goodix_hid_get_raw_report()
467 return -EINVAL; in goodix_hid_get_raw_report()
473 * goodix_hid_set_raw_report() - process hidraw SET REPORT operation
474 * @hid: HID device
481 * set report request. The transmitted data follows the standard i2c-hid
486 static int goodix_hid_set_raw_report(struct hid_device *hid, in goodix_hid_set_raw_report() argument
491 struct goodix_ts_data *ts = hid->driver_data; in goodix_hid_set_raw_report()
492 u16 data_register = le16_to_cpu(ts->hid_desc.data_register); in goodix_hid_set_raw_report()
493 u16 cmd_register = le16_to_cpu(ts->hid_desc.cmd_register); in goodix_hid_set_raw_report()
510 /* Clean 3 bytes of hid ack header data */ in goodix_hid_set_raw_report()
528 dev_err(ts->dev, "failed send report: %*ph", tx_len, tmp_buf); in goodix_hid_set_raw_report()
534 static int goodix_hid_raw_request(struct hid_device *hid, in goodix_hid_raw_request() argument
539 struct goodix_ts_data *ts = hid->driver_data; in goodix_hid_raw_request()
540 int error = -EINVAL; in goodix_hid_raw_request()
542 guard(mutex)(&ts->hid_request_lock); in goodix_hid_raw_request()
545 error = goodix_hid_get_raw_report(hid, reportnum, buf, in goodix_hid_raw_request()
550 error = goodix_hid_set_raw_report(hid, reportnum, in goodix_hid_raw_request()
576 if (!test_bit(GOODIX_HID_STARTED, &ts->flags)) in goodix_hid_irq()
580 * - event header = 3 bytes in goodix_hid_irq()
581 * - coordinate event = GOODIX_HID_COOR_PKG_LEN bytes in goodix_hid_irq()
587 event = goodix_get_event_report(ts, ts->hid_report_addr, ts->event_buf, in goodix_hid_irq()
591 dev_err(ts->dev, "failed get coordinate data"); in goodix_hid_irq()
596 if (event->hdr.flag != GOODIX_HID_REPORT_READY_FLAG) in goodix_hid_irq()
599 pkg = (struct goodix_hid_report_package *)event->data; in goodix_hid_irq()
600 if (le16_to_cpu(pkg->size) < GOODIX_HID_PKG_LEN_SIZE) { in goodix_hid_irq()
601 dev_err(ts->dev, "invalid coordinate event package size, %d", in goodix_hid_irq()
602 le16_to_cpu(pkg->size)); in goodix_hid_irq()
605 hid_input_report(ts->hid, HID_INPUT_REPORT, pkg->data, in goodix_hid_irq()
606 le16_to_cpu(pkg->size) - GOODIX_HID_PKG_LEN_SIZE, 1); in goodix_hid_irq()
608 report_size = le16_to_cpu(event->hdr.size); in goodix_hid_irq()
613 if (report_size >= ts->hid_max_event_sz) { in goodix_hid_irq()
614 dev_err(ts->dev, "package size exceed limit %d vs %d", in goodix_hid_irq()
615 report_size, ts->hid_max_event_sz); in goodix_hid_irq()
620 pkg = goodix_get_event_report(ts, ts->hid_report_addr + sizeof(*event), in goodix_hid_irq()
621 ts->event_buf, in goodix_hid_irq()
622 report_size - GOODIX_HID_COOR_PKG_LEN); in goodix_hid_irq()
624 dev_err(ts->dev, "failed read attachment data content"); in goodix_hid_irq()
628 hid_input_report(ts->hid, HID_INPUT_REPORT, pkg->data, in goodix_hid_irq()
629 le16_to_cpu(pkg->size) - GOODIX_HID_PKG_LEN_SIZE, 1); in goodix_hid_irq()
636 struct hid_device *hid; in goodix_hid_init() local
639 /* Get hid descriptor */ in goodix_hid_init()
640 error = goodix_spi_read(ts, GOODIX_HID_DESC_ADDR, &ts->hid_desc, in goodix_hid_init()
641 sizeof(ts->hid_desc)); in goodix_hid_init()
643 dev_err(ts->dev, "failed get hid desc, %d", error); in goodix_hid_init()
647 hid = hid_allocate_device(); in goodix_hid_init()
648 if (IS_ERR(hid)) in goodix_hid_init()
649 return PTR_ERR(hid); in goodix_hid_init()
651 hid->driver_data = ts; in goodix_hid_init()
652 hid->ll_driver = &goodix_hid_ll_driver; in goodix_hid_init()
653 hid->bus = BUS_SPI; in goodix_hid_init()
654 hid->dev.parent = &ts->spi->dev; in goodix_hid_init()
656 hid->version = le16_to_cpu(ts->hid_desc.bcd_version); in goodix_hid_init()
657 hid->vendor = le16_to_cpu(ts->hid_desc.vendor_id); in goodix_hid_init()
658 hid->product = le16_to_cpu(ts->hid_desc.product_id); in goodix_hid_init()
659 snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-gdix", in goodix_hid_init()
660 hid->vendor, hid->product); in goodix_hid_init()
662 error = hid_add_device(hid); in goodix_hid_init()
664 dev_err(ts->dev, "failed add hid device, %d", error); in goodix_hid_init()
665 hid_destroy_device(hid); in goodix_hid_init()
669 ts->hid = hid; in goodix_hid_init()
675 struct device *dev = &spi->dev; in goodix_spi_probe()
680 spi->mode = SPI_MODE_0; in goodix_spi_probe()
681 spi->bits_per_word = 8; in goodix_spi_probe()
688 return -ENOMEM; in goodix_spi_probe()
690 mutex_init(&ts->hid_request_lock); in goodix_spi_probe()
692 ts->spi = spi; in goodix_spi_probe()
693 ts->dev = dev; in goodix_spi_probe()
694 ts->hid_max_event_sz = GOODIX_SPI_READ_PREFIX_LEN + in goodix_spi_probe()
696 ts->event_buf = devm_kmalloc(dev, ts->hid_max_event_sz, GFP_KERNEL); in goodix_spi_probe()
697 if (!ts->event_buf) in goodix_spi_probe()
698 return -ENOMEM; in goodix_spi_probe()
700 ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); in goodix_spi_probe()
701 if (IS_ERR(ts->reset_gpio)) in goodix_spi_probe()
702 return dev_err_probe(dev, PTR_ERR(ts->reset_gpio), in goodix_spi_probe()
705 ts->hid_report_addr = GOODIX_HID_REPORT_ADDR; in goodix_spi_probe()
715 dev_err(dev, "failed init hid device"); in goodix_spi_probe()
719 error = devm_request_threaded_irq(&ts->spi->dev, ts->spi->irq, in goodix_spi_probe()
723 dev_err(ts->dev, "could not register interrupt, irq = %d, %d", in goodix_spi_probe()
724 ts->spi->irq, error); in goodix_spi_probe()
731 hid_destroy_device(ts->hid); in goodix_spi_probe()
739 disable_irq(spi->irq); in goodix_spi_remove()
740 hid_destroy_device(ts->hid); in goodix_spi_remove()
751 guard(mutex)(&ts->hid_request_lock); in goodix_spi_set_power()
755 dev_err(ts->dev, "failed set power mode: %s", in goodix_spi_set_power()
766 disable_irq(ts->spi->irq); in goodix_spi_suspend()
774 enable_irq(ts->spi->irq); in goodix_spi_resume()
791 { .compatible = "goodix,gt7986u-spifw", },
805 .name = "goodix-spi-hid",
816 MODULE_DESCRIPTION("Goodix SPI driver for HID touchscreen");