| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- /*
- * Goodix GT7986U SPI Driver Code for HID.
- *
- * Copyright (C) 2024 Godix, Inc.
- */
- #include <linux/unaligned.h>
- #include <linux/delay.h>
- #include <linux/hid.h>
- #include <linux/interrupt.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/mutex.h>
- #include <linux/of.h>
- #include <linux/sizes.h>
- #include <linux/spi/spi.h>
- #define GOODIX_DEV_CONFIRM_ADDR 0x10000
- #define GOODIX_HID_DESC_ADDR 0x1058C
- #define GOODIX_HID_REPORT_DESC_ADDR 0x105AA
- #define GOODIX_HID_SIGN_ADDR 0x10D32
- #define GOODIX_HID_GET_REPORT_CMD 0x02
- #define GOODIX_HID_SET_REPORT_CMD 0x03
- #define GOODIX_HID_MAX_INBUF_SIZE 128
- #define GOODIX_HID_ACK_READY_FLAG 0x01
- #define GOODIX_HID_REPORT_READY_FLAG 0x80
- #define GOODIX_DEV_CONFIRM_VAL 0xAA
- #define GOODIX_SPI_WRITE_FLAG 0xF0
- #define GOODIX_SPI_READ_FLAG 0xF1
- #define GOODIX_SPI_TRANS_PREFIX_LEN 1
- #define GOODIX_REGISTER_WIDTH 4
- #define GOODIX_SPI_READ_DUMMY_LEN 3
- #define GOODIX_SPI_READ_PREFIX_LEN (GOODIX_SPI_TRANS_PREFIX_LEN + \
- GOODIX_REGISTER_WIDTH + \
- GOODIX_SPI_READ_DUMMY_LEN)
- #define GOODIX_SPI_WRITE_PREFIX_LEN (GOODIX_SPI_TRANS_PREFIX_LEN + \
- GOODIX_REGISTER_WIDTH)
- #define GOODIX_CHECKSUM_SIZE sizeof(u16)
- #define GOODIX_NORMAL_RESET_DELAY_MS 150
- struct goodix_hid_report_header {
- u8 flag;
- __le16 size;
- } __packed;
- #define GOODIX_HID_ACK_HEADER_SIZE sizeof(struct goodix_hid_report_header)
- struct goodix_hid_report_package {
- __le16 size;
- u8 data[];
- };
- #define GOODIX_HID_PKG_LEN_SIZE sizeof(u16)
- #define GOODIX_HID_COOR_DATA_LEN 82
- #define GOODIX_HID_COOR_PKG_LEN (GOODIX_HID_PKG_LEN_SIZE + \
- GOODIX_HID_COOR_DATA_LEN)
- /* power state */
- #define GOODIX_SPI_POWER_ON 0x00
- #define GOODIX_SPI_POWER_SLEEP 0x01
- /* flags used to record the current device operating state */
- #define GOODIX_HID_STARTED 0
- struct goodix_hid_report_event {
- struct goodix_hid_report_header hdr;
- u8 data[GOODIX_HID_COOR_PKG_LEN];
- } __packed;
- struct goodix_hid_desc {
- __le16 desc_length;
- __le16 bcd_version;
- __le16 report_desc_length;
- __le16 report_desc_register;
- __le16 input_register;
- __le16 max_input_length;
- __le16 output_register;
- __le16 max_output_length;
- __le16 cmd_register;
- __le16 data_register;
- __le16 vendor_id;
- __le16 product_id;
- __le16 version_id;
- __le32 reserved;
- } __packed;
- struct goodix_ts_data {
- struct device *dev;
- struct spi_device *spi;
- struct hid_device *hid;
- struct goodix_hid_desc hid_desc;
- struct gpio_desc *reset_gpio;
- u32 hid_report_addr;
- unsigned long flags;
- /* lock for hid raw request operation */
- struct mutex hid_request_lock;
- /* buffer used to store hid report event */
- u8 *event_buf;
- u32 hid_max_event_sz;
- /* buffer used to do spi data transfer */
- u8 xfer_buf[SZ_2K] ____cacheline_aligned;
- };
- static void *goodix_get_event_report(struct goodix_ts_data *ts, u32 addr,
- u8 *data, size_t len)
- {
- struct spi_device *spi = to_spi_device(&ts->spi->dev);
- struct spi_transfer xfers;
- struct spi_message spi_msg;
- int error;
- /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */
- data[0] = GOODIX_SPI_READ_FLAG;
- put_unaligned_be32(addr, data + GOODIX_SPI_TRANS_PREFIX_LEN);
- spi_message_init(&spi_msg);
- memset(&xfers, 0, sizeof(xfers));
- xfers.tx_buf = data;
- xfers.rx_buf = data;
- xfers.len = GOODIX_SPI_READ_PREFIX_LEN + len;
- spi_message_add_tail(&xfers, &spi_msg);
- error = spi_sync(spi, &spi_msg);
- if (error) {
- dev_err(ts->dev, "spi transfer error: %d", error);
- return NULL;
- }
- return data + GOODIX_SPI_READ_PREFIX_LEN;
- }
- static int goodix_spi_read(struct goodix_ts_data *ts, u32 addr,
- void *data, size_t len)
- {
- struct spi_device *spi = to_spi_device(&ts->spi->dev);
- struct spi_transfer xfers;
- struct spi_message spi_msg;
- int error;
- if (GOODIX_SPI_READ_PREFIX_LEN + len > sizeof(ts->xfer_buf)) {
- dev_err(ts->dev, "read data len exceed limit %zu",
- sizeof(ts->xfer_buf) - GOODIX_SPI_READ_PREFIX_LEN);
- return -EINVAL;
- }
- /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */
- ts->xfer_buf[0] = GOODIX_SPI_READ_FLAG;
- put_unaligned_be32(addr, ts->xfer_buf + GOODIX_SPI_TRANS_PREFIX_LEN);
- spi_message_init(&spi_msg);
- memset(&xfers, 0, sizeof(xfers));
- xfers.tx_buf = ts->xfer_buf;
- xfers.rx_buf = ts->xfer_buf;
- xfers.len = GOODIX_SPI_READ_PREFIX_LEN + len;
- spi_message_add_tail(&xfers, &spi_msg);
- error = spi_sync(spi, &spi_msg);
- if (error)
- dev_err(ts->dev, "spi transfer error: %d", error);
- else
- memcpy(data, ts->xfer_buf + GOODIX_SPI_READ_PREFIX_LEN, len);
- return error;
- }
- static int goodix_spi_write(struct goodix_ts_data *ts, u32 addr,
- const void *data, size_t len)
- {
- struct spi_device *spi = to_spi_device(&ts->spi->dev);
- struct spi_transfer xfers;
- struct spi_message spi_msg;
- int error;
- if (GOODIX_SPI_WRITE_PREFIX_LEN + len > sizeof(ts->xfer_buf)) {
- dev_err(ts->dev, "write data len exceed limit %zu",
- sizeof(ts->xfer_buf) - GOODIX_SPI_WRITE_PREFIX_LEN);
- return -EINVAL;
- }
- /* buffer format: 0xF0 + addr(4bytes) + data */
- ts->xfer_buf[0] = GOODIX_SPI_WRITE_FLAG;
- put_unaligned_be32(addr, ts->xfer_buf + GOODIX_SPI_TRANS_PREFIX_LEN);
- memcpy(ts->xfer_buf + GOODIX_SPI_WRITE_PREFIX_LEN, data, len);
- spi_message_init(&spi_msg);
- memset(&xfers, 0, sizeof(xfers));
- xfers.tx_buf = ts->xfer_buf;
- xfers.len = GOODIX_SPI_WRITE_PREFIX_LEN + len;
- spi_message_add_tail(&xfers, &spi_msg);
- error = spi_sync(spi, &spi_msg);
- if (error)
- dev_err(ts->dev, "spi transfer error: %d", error);
- return error;
- }
- static int goodix_dev_confirm(struct goodix_ts_data *ts)
- {
- u8 tx_buf[8], rx_buf[8];
- int retry = 3;
- int error;
- gpiod_set_value_cansleep(ts->reset_gpio, 0);
- usleep_range(4000, 4100);
- memset(tx_buf, GOODIX_DEV_CONFIRM_VAL, sizeof(tx_buf));
- while (retry--) {
- error = goodix_spi_write(ts, GOODIX_DEV_CONFIRM_ADDR,
- tx_buf, sizeof(tx_buf));
- if (error)
- return error;
- error = goodix_spi_read(ts, GOODIX_DEV_CONFIRM_ADDR,
- rx_buf, sizeof(rx_buf));
- if (error)
- return error;
- if (!memcmp(tx_buf, rx_buf, sizeof(tx_buf)))
- return 0;
- usleep_range(5000, 5100);
- }
- dev_err(ts->dev, "device confirm failed, rx_buf: %*ph", 8, rx_buf);
- return -EINVAL;
- }
- /**
- * goodix_hid_parse() - hid-core .parse() callback
- * @hid: hid device instance
- *
- * This function gets called during call to hid_add_device
- *
- * Return: 0 on success and non zero on error
- */
- static int goodix_hid_parse(struct hid_device *hid)
- {
- struct goodix_ts_data *ts = hid->driver_data;
- u16 rsize;
- int error;
- rsize = le16_to_cpu(ts->hid_desc.report_desc_length);
- if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
- dev_err(ts->dev, "invalid report desc size, %d", rsize);
- return -EINVAL;
- }
- u8 *rdesc __free(kfree) = kzalloc(rsize, GFP_KERNEL);
- if (!rdesc)
- return -ENOMEM;
- error = goodix_spi_read(ts, GOODIX_HID_REPORT_DESC_ADDR, rdesc, rsize);
- if (error) {
- dev_err(ts->dev, "failed get report desc, %d", error);
- return error;
- }
- error = hid_parse_report(hid, rdesc, rsize);
- if (error) {
- dev_err(ts->dev, "failed parse report, %d", error);
- return error;
- }
- return 0;
- }
- static int goodix_hid_get_report_length(struct hid_report *report)
- {
- return ((report->size - 1) >> 3) + 1 +
- report->device->report_enum[report->type].numbered + 2;
- }
- static void goodix_hid_find_max_report(struct hid_device *hid, unsigned int type,
- unsigned int *max)
- {
- struct hid_report *report;
- unsigned int size;
- list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
- size = goodix_hid_get_report_length(report);
- if (*max < size)
- *max = size;
- }
- }
- static int goodix_hid_start(struct hid_device *hid)
- {
- struct goodix_ts_data *ts = hid->driver_data;
- unsigned int bufsize = GOODIX_HID_COOR_PKG_LEN;
- u32 report_size;
- goodix_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize);
- goodix_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize);
- goodix_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize);
- report_size = GOODIX_SPI_READ_PREFIX_LEN +
- GOODIX_HID_ACK_HEADER_SIZE + bufsize;
- if (report_size <= ts->hid_max_event_sz)
- return 0;
- ts->event_buf = devm_krealloc(ts->dev, ts->event_buf,
- report_size, GFP_KERNEL);
- if (!ts->event_buf)
- return -ENOMEM;
- ts->hid_max_event_sz = report_size;
- return 0;
- }
- static void goodix_hid_stop(struct hid_device *hid)
- {
- hid->claimed = 0;
- }
- static int goodix_hid_open(struct hid_device *hid)
- {
- struct goodix_ts_data *ts = hid->driver_data;
- set_bit(GOODIX_HID_STARTED, &ts->flags);
- return 0;
- }
- static void goodix_hid_close(struct hid_device *hid)
- {
- struct goodix_ts_data *ts = hid->driver_data;
- clear_bit(GOODIX_HID_STARTED, &ts->flags);
- }
- /* Return date length of response data */
- static int goodix_hid_check_ack_status(struct goodix_ts_data *ts, u32 *resp_len)
- {
- struct goodix_hid_report_header hdr;
- int retry = 20;
- int error;
- int len;
- while (retry--) {
- /*
- * 3 bytes of hid request response data
- * - byte 0: Ack flag, value of 1 for data ready
- * - bytes 1-2: Response data length
- */
- error = goodix_spi_read(ts, ts->hid_report_addr,
- &hdr, sizeof(hdr));
- if (!error && (hdr.flag & GOODIX_HID_ACK_READY_FLAG)) {
- len = le16_to_cpu(hdr.size);
- if (len < GOODIX_HID_PKG_LEN_SIZE) {
- dev_err(ts->dev, "hrd.size too short: %d", len);
- return -EINVAL;
- }
- *resp_len = len;
- return 0;
- }
- /* Wait 10ms for another try */
- usleep_range(10000, 11000);
- }
- return -EINVAL;
- }
- /**
- * goodix_hid_get_raw_report() - Process hidraw GET REPORT operation
- * @hid: hid device instance
- * @reportnum: Report ID
- * @buf: Buffer for store the report date
- * @len: Length fo report data
- * @report_type: Report type
- *
- * The function for hid_ll_driver.get_raw_report to handle the HIDRAW ioctl
- * get report request. The transmitted data follows the standard i2c-hid
- * protocol with a specified header.
- *
- * Return: The length of the data in the buf on success, negative error code
- */
- static int goodix_hid_get_raw_report(struct hid_device *hid,
- unsigned char reportnum,
- u8 *buf, size_t len,
- unsigned char report_type)
- {
- struct goodix_ts_data *ts = hid->driver_data;
- u16 data_register = le16_to_cpu(ts->hid_desc.data_register);
- u16 cmd_register = le16_to_cpu(ts->hid_desc.cmd_register);
- u8 tmp_buf[GOODIX_HID_MAX_INBUF_SIZE];
- int tx_len = 0, args_len = 0;
- u32 response_data_len;
- u8 args[3];
- int error;
- if (report_type == HID_OUTPUT_REPORT)
- return -EINVAL;
- if (reportnum == 3) {
- /* Get win8 signature data */
- error = goodix_spi_read(ts, GOODIX_HID_SIGN_ADDR, buf, len);
- if (error) {
- dev_err(ts->dev, "failed get win8 sign: %d", error);
- return -EINVAL;
- }
- return len;
- }
- if (reportnum >= 0x0F)
- args[args_len++] = reportnum;
- put_unaligned_le16(data_register, args + args_len);
- args_len += sizeof(data_register);
- /* Clean 3 bytes of hid ack header data */
- memset(tmp_buf, 0, GOODIX_HID_ACK_HEADER_SIZE);
- tx_len += GOODIX_HID_ACK_HEADER_SIZE;
- put_unaligned_le16(cmd_register, tmp_buf + tx_len);
- tx_len += sizeof(cmd_register);
- tmp_buf[tx_len] = (report_type == HID_FEATURE_REPORT ? 0x03 : 0x01) << 4;
- tmp_buf[tx_len] |= reportnum >= 0x0F ? 0x0F : reportnum;
- tx_len++;
- tmp_buf[tx_len++] = GOODIX_HID_GET_REPORT_CMD;
- memcpy(tmp_buf + tx_len, args, args_len);
- tx_len += args_len;
- /* Step1: write report request info */
- error = goodix_spi_write(ts, ts->hid_report_addr, tmp_buf, tx_len);
- if (error) {
- dev_err(ts->dev, "failed send read feature cmd, %d", error);
- return error;
- }
- /* No need read response data */
- if (!len)
- return 0;
- /* Step2: check response data status */
- error = goodix_hid_check_ack_status(ts, &response_data_len);
- if (error)
- return error;
- len = min(len, response_data_len - GOODIX_HID_PKG_LEN_SIZE);
- /* Step3: read response data(skip 2bytes of hid pkg length) */
- error = goodix_spi_read(ts, ts->hid_report_addr +
- GOODIX_HID_ACK_HEADER_SIZE +
- GOODIX_HID_PKG_LEN_SIZE, buf, len);
- if (error) {
- dev_err(ts->dev, "failed read hid response data, %d", error);
- return error;
- }
- if (buf[0] != reportnum) {
- dev_err(ts->dev, "incorrect report (%d vs %d expected)",
- buf[0], reportnum);
- return -EINVAL;
- }
- return len;
- }
- /**
- * goodix_hid_set_raw_report() - process hidraw SET REPORT operation
- * @hid: HID device
- * @reportnum: Report ID
- * @buf: Buffer for communication
- * @len: Length of data in the buffer
- * @report_type: Report type
- *
- * The function for hid_ll_driver.get_raw_report to handle the HIDRAW ioctl
- * set report request. The transmitted data follows the standard i2c-hid
- * protocol with a specified header.
- *
- * Return: The length of the data sent, negative error code on failure
- */
- static int goodix_hid_set_raw_report(struct hid_device *hid,
- unsigned char reportnum,
- __u8 *buf, size_t len,
- unsigned char report_type)
- {
- struct goodix_ts_data *ts = hid->driver_data;
- u16 data_register = le16_to_cpu(ts->hid_desc.data_register);
- u16 cmd_register = le16_to_cpu(ts->hid_desc.cmd_register);
- int tx_len = 0, args_len = 0;
- u8 tmp_buf[GOODIX_HID_MAX_INBUF_SIZE];
- u8 args[5];
- int error;
- if (reportnum >= 0x0F) {
- args[args_len++] = reportnum;
- reportnum = 0x0F;
- }
- put_unaligned_le16(data_register, args + args_len);
- args_len += sizeof(data_register);
- put_unaligned_le16(GOODIX_HID_PKG_LEN_SIZE + len, args + args_len);
- args_len += GOODIX_HID_PKG_LEN_SIZE;
- /* Clean 3 bytes of hid ack header data */
- memset(tmp_buf, 0, GOODIX_HID_ACK_HEADER_SIZE);
- tx_len += GOODIX_HID_ACK_HEADER_SIZE;
- put_unaligned_le16(cmd_register, tmp_buf + tx_len);
- tx_len += sizeof(cmd_register);
- tmp_buf[tx_len++] = ((report_type == HID_FEATURE_REPORT ? 0x03 : 0x02) << 4) | reportnum;
- tmp_buf[tx_len++] = GOODIX_HID_SET_REPORT_CMD;
- memcpy(tmp_buf + tx_len, args, args_len);
- tx_len += args_len;
- memcpy(tmp_buf + tx_len, buf, len);
- tx_len += len;
- error = goodix_spi_write(ts, ts->hid_report_addr, tmp_buf, tx_len);
- if (error) {
- dev_err(ts->dev, "failed send report: %*ph", tx_len, tmp_buf);
- return error;
- }
- return len;
- }
- static int goodix_hid_raw_request(struct hid_device *hid,
- unsigned char reportnum,
- __u8 *buf, size_t len,
- unsigned char rtype, int reqtype)
- {
- struct goodix_ts_data *ts = hid->driver_data;
- int error = -EINVAL;
- guard(mutex)(&ts->hid_request_lock);
- switch (reqtype) {
- case HID_REQ_GET_REPORT:
- error = goodix_hid_get_raw_report(hid, reportnum, buf,
- len, rtype);
- break;
- case HID_REQ_SET_REPORT:
- if (buf[0] == reportnum)
- error = goodix_hid_set_raw_report(hid, reportnum,
- buf, len, rtype);
- break;
- default:
- break;
- }
- return error;
- }
- static struct hid_ll_driver goodix_hid_ll_driver = {
- .parse = goodix_hid_parse,
- .start = goodix_hid_start,
- .stop = goodix_hid_stop,
- .open = goodix_hid_open,
- .close = goodix_hid_close,
- .raw_request = goodix_hid_raw_request
- };
- static irqreturn_t goodix_hid_irq(int irq, void *data)
- {
- struct goodix_ts_data *ts = data;
- struct goodix_hid_report_event *event;
- struct goodix_hid_report_package *pkg;
- u16 report_size;
- if (!test_bit(GOODIX_HID_STARTED, &ts->flags))
- return IRQ_HANDLED;
- /*
- * First, read buffer with space for header and coordinate package:
- * - event header = 3 bytes
- * - coordinate event = GOODIX_HID_COOR_PKG_LEN bytes
- *
- * If the data size info in the event header exceeds
- * GOODIX_HID_COOR_PKG_LEN, it means that there are other packages
- * besides the coordinate package.
- */
- event = goodix_get_event_report(ts, ts->hid_report_addr, ts->event_buf,
- GOODIX_HID_ACK_HEADER_SIZE +
- GOODIX_HID_COOR_PKG_LEN);
- if (!event) {
- dev_err(ts->dev, "failed get coordinate data");
- return IRQ_HANDLED;
- }
- /* Check coordinate data valid falg */
- if (event->hdr.flag != GOODIX_HID_REPORT_READY_FLAG)
- return IRQ_HANDLED;
- pkg = (struct goodix_hid_report_package *)event->data;
- if (le16_to_cpu(pkg->size) < GOODIX_HID_PKG_LEN_SIZE) {
- dev_err(ts->dev, "invalid coordinate event package size, %d",
- le16_to_cpu(pkg->size));
- return IRQ_HANDLED;
- }
- hid_input_report(ts->hid, HID_INPUT_REPORT, pkg->data,
- le16_to_cpu(pkg->size) - GOODIX_HID_PKG_LEN_SIZE, 1);
- report_size = le16_to_cpu(event->hdr.size);
- /* Check if there are other packages */
- if (report_size <= GOODIX_HID_COOR_PKG_LEN)
- return IRQ_HANDLED;
- if (report_size >= ts->hid_max_event_sz) {
- dev_err(ts->dev, "package size exceed limit %d vs %d",
- report_size, ts->hid_max_event_sz);
- return IRQ_HANDLED;
- }
- /* Read the package behind the coordinate data */
- pkg = goodix_get_event_report(ts, ts->hid_report_addr + sizeof(*event),
- ts->event_buf,
- report_size - GOODIX_HID_COOR_PKG_LEN);
- if (!pkg) {
- dev_err(ts->dev, "failed read attachment data content");
- return IRQ_HANDLED;
- }
- hid_input_report(ts->hid, HID_INPUT_REPORT, pkg->data,
- le16_to_cpu(pkg->size) - GOODIX_HID_PKG_LEN_SIZE, 1);
- return IRQ_HANDLED;
- }
- static int goodix_hid_init(struct goodix_ts_data *ts)
- {
- struct hid_device *hid;
- int error;
- /* Get hid descriptor */
- error = goodix_spi_read(ts, GOODIX_HID_DESC_ADDR, &ts->hid_desc,
- sizeof(ts->hid_desc));
- if (error) {
- dev_err(ts->dev, "failed get hid desc, %d", error);
- return error;
- }
- hid = hid_allocate_device();
- if (IS_ERR(hid))
- return PTR_ERR(hid);
- hid->driver_data = ts;
- hid->ll_driver = &goodix_hid_ll_driver;
- hid->bus = BUS_SPI;
- hid->dev.parent = &ts->spi->dev;
- hid->version = le16_to_cpu(ts->hid_desc.bcd_version);
- hid->vendor = le16_to_cpu(ts->hid_desc.vendor_id);
- hid->product = le16_to_cpu(ts->hid_desc.product_id);
- snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-gdix",
- hid->vendor, hid->product);
- error = hid_add_device(hid);
- if (error) {
- dev_err(ts->dev, "failed add hid device, %d", error);
- hid_destroy_device(hid);
- return error;
- }
- ts->hid = hid;
- return 0;
- }
- static int goodix_spi_probe(struct spi_device *spi)
- {
- struct device *dev = &spi->dev;
- struct goodix_ts_data *ts;
- int error;
- /* init spi_device */
- spi->mode = SPI_MODE_0;
- spi->bits_per_word = 8;
- error = spi_setup(spi);
- if (error)
- return error;
- ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
- if (!ts)
- return -ENOMEM;
- mutex_init(&ts->hid_request_lock);
- spi_set_drvdata(spi, ts);
- ts->spi = spi;
- ts->dev = dev;
- ts->hid_max_event_sz = GOODIX_SPI_READ_PREFIX_LEN +
- GOODIX_HID_ACK_HEADER_SIZE + GOODIX_HID_COOR_PKG_LEN;
- ts->event_buf = devm_kmalloc(dev, ts->hid_max_event_sz, GFP_KERNEL);
- if (!ts->event_buf)
- return -ENOMEM;
- ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(ts->reset_gpio))
- return dev_err_probe(dev, PTR_ERR(ts->reset_gpio),
- "failed to request reset gpio\n");
- error = device_property_read_u32(dev, "goodix,hid-report-addr",
- &ts->hid_report_addr);
- if (error)
- return dev_err_probe(dev, error,
- "failed get hid report addr\n");
- error = goodix_dev_confirm(ts);
- if (error)
- return error;
- /* Waits 150ms for firmware to fully boot */
- msleep(GOODIX_NORMAL_RESET_DELAY_MS);
- error = goodix_hid_init(ts);
- if (error) {
- dev_err(dev, "failed init hid device");
- return error;
- }
- error = devm_request_threaded_irq(&ts->spi->dev, ts->spi->irq,
- NULL, goodix_hid_irq, IRQF_ONESHOT,
- "goodix_spi_hid", ts);
- if (error) {
- dev_err(ts->dev, "could not register interrupt, irq = %d, %d",
- ts->spi->irq, error);
- goto err_destroy_hid;
- }
- return 0;
- err_destroy_hid:
- hid_destroy_device(ts->hid);
- return error;
- }
- static void goodix_spi_remove(struct spi_device *spi)
- {
- struct goodix_ts_data *ts = spi_get_drvdata(spi);
- disable_irq(spi->irq);
- hid_destroy_device(ts->hid);
- }
- static int goodix_spi_set_power(struct goodix_ts_data *ts, int power_state)
- {
- u8 power_control_cmd[] = {0x00, 0x00, 0x00, 0x87, 0x02, 0x00, 0x08};
- int error;
- /* value 0 for power on, 1 for power sleep */
- power_control_cmd[5] = power_state;
- guard(mutex)(&ts->hid_request_lock);
- error = goodix_spi_write(ts, ts->hid_report_addr, power_control_cmd,
- sizeof(power_control_cmd));
- if (error) {
- dev_err(ts->dev, "failed set power mode: %s",
- power_state == GOODIX_SPI_POWER_ON ? "on" : "sleep");
- return error;
- }
- return 0;
- }
- static int goodix_spi_suspend(struct device *dev)
- {
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
- disable_irq(ts->spi->irq);
- return goodix_spi_set_power(ts, GOODIX_SPI_POWER_SLEEP);
- }
- static int goodix_spi_resume(struct device *dev)
- {
- struct goodix_ts_data *ts = dev_get_drvdata(dev);
- enable_irq(ts->spi->irq);
- return goodix_spi_set_power(ts, GOODIX_SPI_POWER_ON);
- }
- static DEFINE_SIMPLE_DEV_PM_OPS(goodix_spi_pm_ops,
- goodix_spi_suspend, goodix_spi_resume);
- #ifdef CONFIG_ACPI
- static const struct acpi_device_id goodix_spi_acpi_match[] = {
- { "GXTS7986" },
- { },
- };
- MODULE_DEVICE_TABLE(acpi, goodix_spi_acpi_match);
- #endif
- static const struct spi_device_id goodix_spi_ids[] = {
- { "gt7986u" },
- { },
- };
- MODULE_DEVICE_TABLE(spi, goodix_spi_ids);
- static struct spi_driver goodix_spi_driver = {
- .driver = {
- .name = "goodix-spi-hid",
- .acpi_match_table = ACPI_PTR(goodix_spi_acpi_match),
- .pm = pm_sleep_ptr(&goodix_spi_pm_ops),
- },
- .probe = goodix_spi_probe,
- .remove = goodix_spi_remove,
- .id_table = goodix_spi_ids,
- };
- module_spi_driver(goodix_spi_driver);
- MODULE_DESCRIPTION("Goodix SPI driver for HID touchscreen");
- MODULE_AUTHOR("Goodix, Inc.");
- MODULE_LICENSE("GPL");
|