1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* Copyright (c) 2024 Intel Corporation */ 3 4 #include <linux/bitfield.h> 5 #include <linux/hid.h> 6 #include <linux/hid-over-i2c.h> 7 #include <linux/unaligned.h> 8 9 #include "intel-thc-dev.h" 10 #include "intel-thc-dma.h" 11 12 #include "quicki2c-dev.h" 13 #include "quicki2c-hid.h" 14 #include "quicki2c-protocol.h" 15 16 static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int cmd_len, 17 bool append_data_reg, u8 *data, int data_len, 18 u8 *write_buf, int write_buf_len) 19 { 20 int buf_len, offset = 0; 21 22 buf_len = HIDI2C_REG_LEN + cmd_len; 23 24 if (append_data_reg) 25 buf_len += HIDI2C_REG_LEN; 26 27 if (data && data_len) 28 buf_len += data_len + HIDI2C_LENGTH_LEN; 29 30 if (buf_len > write_buf_len) 31 return -EINVAL; 32 33 memcpy(write_buf, &qcdev->dev_desc.cmd_reg, HIDI2C_REG_LEN); 34 offset += HIDI2C_REG_LEN; 35 memcpy(write_buf + offset, &cmd, cmd_len); 36 offset += cmd_len; 37 38 if (append_data_reg) { 39 memcpy(write_buf + offset, &qcdev->dev_desc.data_reg, HIDI2C_REG_LEN); 40 offset += HIDI2C_REG_LEN; 41 } 42 43 if (data && data_len) { 44 __le16 len = cpu_to_le16(data_len + HIDI2C_LENGTH_LEN); 45 46 memcpy(write_buf + offset, &len, HIDI2C_LENGTH_LEN); 47 offset += HIDI2C_LENGTH_LEN; 48 memcpy(write_buf + offset, data, data_len); 49 } 50 51 return buf_len; 52 } 53 54 static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf, 55 u8 opcode, u8 report_type, u8 report_id) 56 { 57 int cmd_len; 58 59 *cmd_buf = FIELD_PREP(HIDI2C_CMD_OPCODE, opcode) | 60 FIELD_PREP(HIDI2C_CMD_REPORT_TYPE, report_type); 61 62 if (report_id < HIDI2C_CMD_MAX_RI) { 63 *cmd_buf |= FIELD_PREP(HIDI2C_CMD_REPORT_ID, report_id); 64 cmd_len = HIDI2C_CMD_LEN; 65 } else { 66 *cmd_buf |= FIELD_PREP(HIDI2C_CMD_REPORT_ID, HIDI2C_CMD_MAX_RI) | 67 FIELD_PREP(HIDI2C_CMD_3RD_BYTE, report_id); 68 cmd_len = HIDI2C_CMD_LEN_OPT; 69 } 70 71 return cmd_len; 72 } 73 74 static int write_cmd_to_txdma(struct quicki2c_device *qcdev, int opcode, 75 int report_type, int report_id, u8 *buf, int buf_len) 76 { 77 size_t write_buf_len; 78 int cmd_len, ret; 79 u32 cmd; 80 81 cmd_len = quicki2c_encode_cmd(qcdev, &cmd, opcode, report_type, report_id); 82 83 ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf, 84 buf_len, qcdev->report_buf, qcdev->report_len); 85 if (ret < 0) 86 return ret; 87 88 write_buf_len = ret; 89 90 return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, write_buf_len); 91 } 92 93 int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state) 94 { 95 return write_cmd_to_txdma(qcdev, HIDI2C_SET_POWER, HIDI2C_RESERVED, power_state, NULL, 0); 96 } 97 98 int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev) 99 { 100 u32 read_len = 0; 101 int ret; 102 103 ret = thc_tic_pio_write_and_read(qcdev->thc_hw, qcdev->hid_desc_addr, 104 HIDI2C_REG_LEN, NULL, HIDI2C_DEV_DESC_LEN, 105 &read_len, (u32 *)&qcdev->dev_desc); 106 if (ret || HIDI2C_DEV_DESC_LEN != read_len) { 107 dev_err_once(qcdev->dev, "Get device descriptor failed, ret %d, read len %u\n", 108 ret, read_len); 109 return -EIO; 110 } 111 112 if (le16_to_cpu(qcdev->dev_desc.bcd_ver) != HIDI2C_HID_DESC_BCDVERSION) 113 return -EOPNOTSUPP; 114 115 return 0; 116 } 117 118 int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev) 119 { 120 u16 desc_reg = le16_to_cpu(qcdev->dev_desc.report_desc_reg); 121 size_t read_len = le16_to_cpu(qcdev->dev_desc.report_desc_len); 122 u32 prd_len = read_len; 123 124 return thc_swdma_read(qcdev->thc_hw, (u8 *)&desc_reg, HIDI2C_REG_LEN, 125 &prd_len, qcdev->report_descriptor, &read_len); 126 } 127 128 int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, 129 unsigned int reportnum, void *buf, u32 buf_len) 130 { 131 struct hidi2c_report_packet *rpt; 132 size_t write_buf_len, read_len = 0; 133 int cmd_len, rep_type; 134 u32 cmd; 135 int ret; 136 137 if (report_type == HID_INPUT_REPORT) { 138 rep_type = HIDI2C_INPUT; 139 } else if (report_type == HID_FEATURE_REPORT) { 140 rep_type = HIDI2C_FEATURE; 141 } else { 142 dev_err(qcdev->dev, "Unsupported report type for GET REPORT: %d\n", report_type); 143 return -EINVAL; 144 } 145 146 cmd_len = quicki2c_encode_cmd(qcdev, &cmd, HIDI2C_GET_REPORT, rep_type, reportnum); 147 148 ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0, 149 qcdev->report_buf, qcdev->report_len); 150 if (ret < 0) 151 return ret; 152 153 write_buf_len = ret; 154 155 rpt = (struct hidi2c_report_packet *)qcdev->input_buf; 156 157 ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, write_buf_len, 158 NULL, rpt, &read_len); 159 if (ret) { 160 dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %d)\n", 161 ret, read_len, buf_len); 162 return ret; 163 } 164 165 if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len || rpt->data[0] != reportnum) { 166 dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %d) report id (%d vs %d)\n", 167 le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum); 168 return -EINVAL; 169 } 170 171 memcpy(buf, rpt->data, buf_len); 172 173 return buf_len; 174 } 175 176 int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, 177 unsigned int reportnum, void *buf, u32 buf_len) 178 { 179 int rep_type; 180 int ret; 181 182 if (report_type == HID_OUTPUT_REPORT) { 183 rep_type = HIDI2C_OUTPUT; 184 } else if (report_type == HID_FEATURE_REPORT) { 185 rep_type = HIDI2C_FEATURE; 186 } else { 187 dev_err(qcdev->dev, "Unsupported report type for SET REPORT: %d\n", report_type); 188 return -EINVAL; 189 } 190 191 ret = write_cmd_to_txdma(qcdev, HIDI2C_SET_REPORT, rep_type, reportnum, buf, buf_len); 192 if (ret) { 193 dev_err_once(qcdev->dev, "Set Report failed, ret %d\n", ret); 194 return ret; 195 } 196 197 return buf_len; 198 } 199 200 #define HIDI2C_RESET_TIMEOUT 5 201 202 int quicki2c_reset(struct quicki2c_device *qcdev) 203 { 204 u16 input_reg = le16_to_cpu(qcdev->dev_desc.input_reg); 205 size_t read_len = HIDI2C_LENGTH_LEN; 206 u32 prd_len = read_len; 207 int ret; 208 209 qcdev->reset_ack = false; 210 qcdev->state = QUICKI2C_RESETING; 211 212 ret = write_cmd_to_txdma(qcdev, HIDI2C_RESET, HIDI2C_RESERVED, 0, NULL, 0); 213 if (ret) { 214 dev_err_once(qcdev->dev, "Send reset command failed, ret %d\n", ret); 215 return ret; 216 } 217 218 ret = wait_event_interruptible_timeout(qcdev->reset_ack_wq, qcdev->reset_ack, 219 HIDI2C_RESET_TIMEOUT * HZ); 220 if (qcdev->reset_ack) 221 return 0; 222 223 /* 224 * Manually read reset response if it wasn't received, in case reset interrupt 225 * was missed by touch device or THC hardware. 226 */ 227 ret = thc_tic_pio_read(qcdev->thc_hw, input_reg, read_len, &prd_len, 228 (u32 *)qcdev->input_buf); 229 if (ret) { 230 dev_err_once(qcdev->dev, "Read Reset Response failed, ret %d\n", ret); 231 return ret; 232 } 233 234 /* 235 * Check response packet length, it's first 16 bits of packet. 236 * If response packet length is zero, it's reset response, otherwise not. 237 */ 238 if (get_unaligned_le16(qcdev->input_buf)) { 239 dev_err_once(qcdev->dev, 240 "Wait reset response timed out ret:%d timeout:%ds\n", 241 ret, HIDI2C_RESET_TIMEOUT); 242 return -ETIMEDOUT; 243 } 244 245 qcdev->reset_ack = true; 246 247 return 0; 248 } 249