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