Loading drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c +13 −1 Original line number Diff line number Diff line Loading @@ -807,6 +807,12 @@ static int quicki2c_suspend(struct device *device) if (!qcdev) return -ENODEV; if (!device_may_wakeup(qcdev->dev)) { ret = quicki2c_set_power(qcdev, HIDI2C_SLEEP); if (ret) return ret; } /* * As I2C is THC subsystem, no register auto save/restore support, * need driver to do that explicitly for every D3 case. Loading Loading @@ -856,6 +862,9 @@ static int quicki2c_resume(struct device *device) if (ret) return ret; if (!device_may_wakeup(qcdev->dev)) return quicki2c_set_power(qcdev, HIDI2C_ON); return 0; } Loading Loading @@ -913,6 +922,9 @@ static int quicki2c_poweroff(struct device *device) if (!qcdev) return -ENODEV; /* Ignore the return value as platform will be poweroff soon */ quicki2c_set_power(qcdev, HIDI2C_SLEEP); ret = thc_interrupt_quiesce(qcdev->thc_hw, true); if (ret) return ret; Loading Loading @@ -966,7 +978,7 @@ static int quicki2c_restore(struct device *device) thc_change_ltr_mode(qcdev->thc_hw, THC_LTR_MODE_ACTIVE); return 0; return quicki2c_set_power(qcdev, HIDI2C_ON); } static int quicki2c_runtime_suspend(struct device *device) Loading drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h +1 −1 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ struct quicki2c_device { u8 *report_descriptor; u8 *input_buf; u8 *report_buf; u32 report_len; size_t report_len; wait_queue_head_t reset_ack_wq; bool reset_ack; Loading drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c +8 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,13 @@ static int quicki2c_hid_power(struct hid_device *hid, int lvl) return 0; } static int quicki2c_hid_output_report(struct hid_device *hid, u8 *buf, size_t count) { struct quicki2c_device *qcdev = hid->driver_data; return quicki2c_output_report(qcdev, buf, count); } static struct hid_ll_driver quicki2c_hid_ll_driver = { .parse = quicki2c_hid_parse, .start = quicki2c_hid_start, Loading @@ -90,6 +97,7 @@ static struct hid_ll_driver quicki2c_hid_ll_driver = { .close = quicki2c_hid_close, .power = quicki2c_hid_power, .raw_request = quicki2c_hid_raw_request, .output_report = quicki2c_hid_output_report, }; /** Loading drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c +56 −39 Original line number Diff line number Diff line Loading @@ -13,11 +13,11 @@ #include "quicki2c-hid.h" #include "quicki2c-protocol.h" static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int cmd_len, bool append_data_reg, u8 *data, int data_len, u8 *write_buf, int write_buf_len) static ssize_t quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, size_t cmd_len, bool append_data_reg, u8 *data, size_t data_len, u8 *write_buf, size_t write_buf_len) { int buf_len, offset = 0; size_t buf_len, offset = 0; buf_len = HIDI2C_REG_LEN + cmd_len; Loading @@ -30,6 +30,7 @@ static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int c if (buf_len > write_buf_len) return -EINVAL; if (cmd_len) { memcpy(write_buf, &qcdev->dev_desc.cmd_reg, HIDI2C_REG_LEN); offset += HIDI2C_REG_LEN; memcpy(write_buf + offset, &cmd, cmd_len); Loading @@ -39,11 +40,13 @@ static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int c memcpy(write_buf + offset, &qcdev->dev_desc.data_reg, HIDI2C_REG_LEN); offset += HIDI2C_REG_LEN; } } else { memcpy(write_buf, &qcdev->dev_desc.output_reg, HIDI2C_REG_LEN); offset += HIDI2C_REG_LEN; } if (data && data_len) { __le16 len = cpu_to_le16(data_len + HIDI2C_LENGTH_LEN); memcpy(write_buf + offset, &len, HIDI2C_LENGTH_LEN); put_unaligned_le16(data_len + HIDI2C_LENGTH_LEN, write_buf + offset); offset += HIDI2C_LENGTH_LEN; memcpy(write_buf + offset, data, data_len); } Loading @@ -51,10 +54,10 @@ static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int c return buf_len; } static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf, static size_t quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf, u8 opcode, u8 report_type, u8 report_id) { int cmd_len; size_t cmd_len; *cmd_buf = FIELD_PREP(HIDI2C_CMD_OPCODE, opcode) | FIELD_PREP(HIDI2C_CMD_REPORT_TYPE, report_type); Loading @@ -72,22 +75,20 @@ static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf, } static int write_cmd_to_txdma(struct quicki2c_device *qcdev, int opcode, int report_type, int report_id, u8 *buf, int buf_len) int report_type, int report_id, u8 *buf, size_t buf_len) { size_t write_buf_len; int cmd_len, ret; size_t cmd_len; ssize_t len; u32 cmd; cmd_len = quicki2c_encode_cmd(qcdev, &cmd, opcode, report_type, report_id); ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf, len = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf, buf_len, qcdev->report_buf, qcdev->report_len); if (ret < 0) return ret; write_buf_len = ret; if (len < 0) return len; return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, write_buf_len); return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, len); } int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state) Loading Loading @@ -126,13 +127,13 @@ int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev) } int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, unsigned int reportnum, void *buf, u32 buf_len) unsigned int reportnum, void *buf, size_t buf_len) { struct hidi2c_report_packet *rpt; size_t write_buf_len, read_len = 0; int cmd_len, rep_type; size_t cmd_len, read_len = 0; int rep_type, ret; ssize_t len; u32 cmd; int ret; if (report_type == HID_INPUT_REPORT) { rep_type = HIDI2C_INPUT; Loading @@ -145,25 +146,22 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, cmd_len = quicki2c_encode_cmd(qcdev, &cmd, HIDI2C_GET_REPORT, rep_type, reportnum); ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0, len = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0, qcdev->report_buf, qcdev->report_len); if (ret < 0) return ret; write_buf_len = ret; if (len < 0) return len; rpt = (struct hidi2c_report_packet *)qcdev->input_buf; ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, write_buf_len, NULL, rpt, &read_len); ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, len, NULL, rpt, &read_len); if (ret) { dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %d)\n", dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %zu)\n", ret, read_len, buf_len); return ret; } if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len || rpt->data[0] != reportnum) { dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %d) report id (%d vs %d)\n", dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %zu) report id (%d vs %d)\n", le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum); return -EINVAL; } Loading @@ -174,7 +172,7 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, } int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, unsigned int reportnum, void *buf, u32 buf_len) unsigned int reportnum, void *buf, size_t buf_len) { int rep_type; int ret; Loading @@ -197,6 +195,25 @@ int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, return buf_len; } int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len) { ssize_t len; int ret; len = quicki2c_init_write_buf(qcdev, 0, 0, false, buf, buf_len, qcdev->report_buf, qcdev->report_len); if (len < 0) return -EINVAL; ret = thc_dma_write(qcdev->thc_hw, qcdev->report_buf, len); if (ret) { dev_err(qcdev->dev, "Output Report failed, ret %d\n", ret); return ret; } return buf_len; } #define HIDI2C_RESET_TIMEOUT 5 int quicki2c_reset(struct quicki2c_device *qcdev) Loading drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.h +3 −2 Original line number Diff line number Diff line Loading @@ -10,9 +10,10 @@ struct quicki2c_device; int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state); int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, unsigned int reportnum, void *buf, u32 buf_len); unsigned int reportnum, void *buf, size_t buf_len); int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, unsigned int reportnum, void *buf, u32 buf_len); unsigned int reportnum, void *buf, size_t buf_len); int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len); int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev); int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev); int quicki2c_reset(struct quicki2c_device *qcdev); Loading Loading
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c +13 −1 Original line number Diff line number Diff line Loading @@ -807,6 +807,12 @@ static int quicki2c_suspend(struct device *device) if (!qcdev) return -ENODEV; if (!device_may_wakeup(qcdev->dev)) { ret = quicki2c_set_power(qcdev, HIDI2C_SLEEP); if (ret) return ret; } /* * As I2C is THC subsystem, no register auto save/restore support, * need driver to do that explicitly for every D3 case. Loading Loading @@ -856,6 +862,9 @@ static int quicki2c_resume(struct device *device) if (ret) return ret; if (!device_may_wakeup(qcdev->dev)) return quicki2c_set_power(qcdev, HIDI2C_ON); return 0; } Loading Loading @@ -913,6 +922,9 @@ static int quicki2c_poweroff(struct device *device) if (!qcdev) return -ENODEV; /* Ignore the return value as platform will be poweroff soon */ quicki2c_set_power(qcdev, HIDI2C_SLEEP); ret = thc_interrupt_quiesce(qcdev->thc_hw, true); if (ret) return ret; Loading Loading @@ -966,7 +978,7 @@ static int quicki2c_restore(struct device *device) thc_change_ltr_mode(qcdev->thc_hw, THC_LTR_MODE_ACTIVE); return 0; return quicki2c_set_power(qcdev, HIDI2C_ON); } static int quicki2c_runtime_suspend(struct device *device) Loading
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h +1 −1 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ struct quicki2c_device { u8 *report_descriptor; u8 *input_buf; u8 *report_buf; u32 report_len; size_t report_len; wait_queue_head_t reset_ack_wq; bool reset_ack; Loading
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c +8 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,13 @@ static int quicki2c_hid_power(struct hid_device *hid, int lvl) return 0; } static int quicki2c_hid_output_report(struct hid_device *hid, u8 *buf, size_t count) { struct quicki2c_device *qcdev = hid->driver_data; return quicki2c_output_report(qcdev, buf, count); } static struct hid_ll_driver quicki2c_hid_ll_driver = { .parse = quicki2c_hid_parse, .start = quicki2c_hid_start, Loading @@ -90,6 +97,7 @@ static struct hid_ll_driver quicki2c_hid_ll_driver = { .close = quicki2c_hid_close, .power = quicki2c_hid_power, .raw_request = quicki2c_hid_raw_request, .output_report = quicki2c_hid_output_report, }; /** Loading
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c +56 −39 Original line number Diff line number Diff line Loading @@ -13,11 +13,11 @@ #include "quicki2c-hid.h" #include "quicki2c-protocol.h" static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int cmd_len, bool append_data_reg, u8 *data, int data_len, u8 *write_buf, int write_buf_len) static ssize_t quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, size_t cmd_len, bool append_data_reg, u8 *data, size_t data_len, u8 *write_buf, size_t write_buf_len) { int buf_len, offset = 0; size_t buf_len, offset = 0; buf_len = HIDI2C_REG_LEN + cmd_len; Loading @@ -30,6 +30,7 @@ static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int c if (buf_len > write_buf_len) return -EINVAL; if (cmd_len) { memcpy(write_buf, &qcdev->dev_desc.cmd_reg, HIDI2C_REG_LEN); offset += HIDI2C_REG_LEN; memcpy(write_buf + offset, &cmd, cmd_len); Loading @@ -39,11 +40,13 @@ static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int c memcpy(write_buf + offset, &qcdev->dev_desc.data_reg, HIDI2C_REG_LEN); offset += HIDI2C_REG_LEN; } } else { memcpy(write_buf, &qcdev->dev_desc.output_reg, HIDI2C_REG_LEN); offset += HIDI2C_REG_LEN; } if (data && data_len) { __le16 len = cpu_to_le16(data_len + HIDI2C_LENGTH_LEN); memcpy(write_buf + offset, &len, HIDI2C_LENGTH_LEN); put_unaligned_le16(data_len + HIDI2C_LENGTH_LEN, write_buf + offset); offset += HIDI2C_LENGTH_LEN; memcpy(write_buf + offset, data, data_len); } Loading @@ -51,10 +54,10 @@ static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int c return buf_len; } static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf, static size_t quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf, u8 opcode, u8 report_type, u8 report_id) { int cmd_len; size_t cmd_len; *cmd_buf = FIELD_PREP(HIDI2C_CMD_OPCODE, opcode) | FIELD_PREP(HIDI2C_CMD_REPORT_TYPE, report_type); Loading @@ -72,22 +75,20 @@ static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf, } static int write_cmd_to_txdma(struct quicki2c_device *qcdev, int opcode, int report_type, int report_id, u8 *buf, int buf_len) int report_type, int report_id, u8 *buf, size_t buf_len) { size_t write_buf_len; int cmd_len, ret; size_t cmd_len; ssize_t len; u32 cmd; cmd_len = quicki2c_encode_cmd(qcdev, &cmd, opcode, report_type, report_id); ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf, len = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf, buf_len, qcdev->report_buf, qcdev->report_len); if (ret < 0) return ret; write_buf_len = ret; if (len < 0) return len; return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, write_buf_len); return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, len); } int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state) Loading Loading @@ -126,13 +127,13 @@ int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev) } int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, unsigned int reportnum, void *buf, u32 buf_len) unsigned int reportnum, void *buf, size_t buf_len) { struct hidi2c_report_packet *rpt; size_t write_buf_len, read_len = 0; int cmd_len, rep_type; size_t cmd_len, read_len = 0; int rep_type, ret; ssize_t len; u32 cmd; int ret; if (report_type == HID_INPUT_REPORT) { rep_type = HIDI2C_INPUT; Loading @@ -145,25 +146,22 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, cmd_len = quicki2c_encode_cmd(qcdev, &cmd, HIDI2C_GET_REPORT, rep_type, reportnum); ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0, len = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0, qcdev->report_buf, qcdev->report_len); if (ret < 0) return ret; write_buf_len = ret; if (len < 0) return len; rpt = (struct hidi2c_report_packet *)qcdev->input_buf; ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, write_buf_len, NULL, rpt, &read_len); ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, len, NULL, rpt, &read_len); if (ret) { dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %d)\n", dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %zu)\n", ret, read_len, buf_len); return ret; } if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len || rpt->data[0] != reportnum) { dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %d) report id (%d vs %d)\n", dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %zu) report id (%d vs %d)\n", le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum); return -EINVAL; } Loading @@ -174,7 +172,7 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, } int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, unsigned int reportnum, void *buf, u32 buf_len) unsigned int reportnum, void *buf, size_t buf_len) { int rep_type; int ret; Loading @@ -197,6 +195,25 @@ int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, return buf_len; } int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len) { ssize_t len; int ret; len = quicki2c_init_write_buf(qcdev, 0, 0, false, buf, buf_len, qcdev->report_buf, qcdev->report_len); if (len < 0) return -EINVAL; ret = thc_dma_write(qcdev->thc_hw, qcdev->report_buf, len); if (ret) { dev_err(qcdev->dev, "Output Report failed, ret %d\n", ret); return ret; } return buf_len; } #define HIDI2C_RESET_TIMEOUT 5 int quicki2c_reset(struct quicki2c_device *qcdev) Loading
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.h +3 −2 Original line number Diff line number Diff line Loading @@ -10,9 +10,10 @@ struct quicki2c_device; int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state); int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, unsigned int reportnum, void *buf, u32 buf_len); unsigned int reportnum, void *buf, size_t buf_len); int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, unsigned int reportnum, void *buf, u32 buf_len); unsigned int reportnum, void *buf, size_t buf_len); int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len); int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev); int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev); int quicki2c_reset(struct quicki2c_device *qcdev); Loading