Skip to content

Commit 9f2975f

Browse files
author
Jiri Kosina
committed
Merge branch 'for-6.20/intel-thc' into for-linus
- support for HID output reports in the Quicki2c (Even Xu)
2 parents 05bc458 + 6761f9c commit 9f2975f

5 files changed

Lines changed: 81 additions & 43 deletions

File tree

drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,12 @@ static int quicki2c_suspend(struct device *device)
807807
if (!qcdev)
808808
return -ENODEV;
809809

810+
if (!device_may_wakeup(qcdev->dev)) {
811+
ret = quicki2c_set_power(qcdev, HIDI2C_SLEEP);
812+
if (ret)
813+
return ret;
814+
}
815+
810816
/*
811817
* As I2C is THC subsystem, no register auto save/restore support,
812818
* need driver to do that explicitly for every D3 case.
@@ -856,6 +862,9 @@ static int quicki2c_resume(struct device *device)
856862
if (ret)
857863
return ret;
858864

865+
if (!device_may_wakeup(qcdev->dev))
866+
return quicki2c_set_power(qcdev, HIDI2C_ON);
867+
859868
return 0;
860869
}
861870

@@ -913,6 +922,9 @@ static int quicki2c_poweroff(struct device *device)
913922
if (!qcdev)
914923
return -ENODEV;
915924

925+
/* Ignore the return value as platform will be poweroff soon */
926+
quicki2c_set_power(qcdev, HIDI2C_SLEEP);
927+
916928
ret = thc_interrupt_quiesce(qcdev->thc_hw, true);
917929
if (ret)
918930
return ret;
@@ -966,7 +978,7 @@ static int quicki2c_restore(struct device *device)
966978

967979
thc_change_ltr_mode(qcdev->thc_hw, THC_LTR_MODE_ACTIVE);
968980

969-
return 0;
981+
return quicki2c_set_power(qcdev, HIDI2C_ON);
970982
}
971983

972984
static int quicki2c_runtime_suspend(struct device *device)

drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ struct quicki2c_device {
213213
u8 *report_descriptor;
214214
u8 *input_buf;
215215
u8 *report_buf;
216-
u32 report_len;
216+
size_t report_len;
217217

218218
wait_queue_head_t reset_ack_wq;
219219
bool reset_ack;

drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ static int quicki2c_hid_power(struct hid_device *hid, int lvl)
8282
return 0;
8383
}
8484

85+
static int quicki2c_hid_output_report(struct hid_device *hid, u8 *buf, size_t count)
86+
{
87+
struct quicki2c_device *qcdev = hid->driver_data;
88+
89+
return quicki2c_output_report(qcdev, buf, count);
90+
}
91+
8592
static struct hid_ll_driver quicki2c_hid_ll_driver = {
8693
.parse = quicki2c_hid_parse,
8794
.start = quicki2c_hid_start,
@@ -90,6 +97,7 @@ static struct hid_ll_driver quicki2c_hid_ll_driver = {
9097
.close = quicki2c_hid_close,
9198
.power = quicki2c_hid_power,
9299
.raw_request = quicki2c_hid_raw_request,
100+
.output_report = quicki2c_hid_output_report,
93101
};
94102

95103
/**

drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
#include "quicki2c-hid.h"
1414
#include "quicki2c-protocol.h"
1515

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)
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)
1919
{
20-
int buf_len, offset = 0;
20+
size_t buf_len, offset = 0;
2121

2222
buf_len = HIDI2C_REG_LEN + cmd_len;
2323

@@ -30,31 +30,34 @@ static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int c
3030
if (buf_len > write_buf_len)
3131
return -EINVAL;
3232

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;
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;
3738

38-
if (append_data_reg) {
39-
memcpy(write_buf + offset, &qcdev->dev_desc.data_reg, HIDI2C_REG_LEN);
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);
4045
offset += HIDI2C_REG_LEN;
4146
}
4247

4348
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);
49+
put_unaligned_le16(data_len + HIDI2C_LENGTH_LEN, write_buf + offset);
4750
offset += HIDI2C_LENGTH_LEN;
4851
memcpy(write_buf + offset, data, data_len);
4952
}
5053

5154
return buf_len;
5255
}
5356

54-
static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf,
55-
u8 opcode, u8 report_type, u8 report_id)
57+
static size_t quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf,
58+
u8 opcode, u8 report_type, u8 report_id)
5659
{
57-
int cmd_len;
60+
size_t cmd_len;
5861

5962
*cmd_buf = FIELD_PREP(HIDI2C_CMD_OPCODE, opcode) |
6063
FIELD_PREP(HIDI2C_CMD_REPORT_TYPE, report_type);
@@ -72,22 +75,20 @@ static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf,
7275
}
7376

7477
static int write_cmd_to_txdma(struct quicki2c_device *qcdev, int opcode,
75-
int report_type, int report_id, u8 *buf, int buf_len)
78+
int report_type, int report_id, u8 *buf, size_t buf_len)
7679
{
77-
size_t write_buf_len;
78-
int cmd_len, ret;
80+
size_t cmd_len;
81+
ssize_t len;
7982
u32 cmd;
8083

8184
cmd_len = quicki2c_encode_cmd(qcdev, &cmd, opcode, report_type, report_id);
8285

83-
ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf,
86+
len = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf,
8487
buf_len, qcdev->report_buf, qcdev->report_len);
85-
if (ret < 0)
86-
return ret;
87-
88-
write_buf_len = ret;
88+
if (len < 0)
89+
return len;
8990

90-
return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, write_buf_len);
91+
return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, len);
9192
}
9293

9394
int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state)
@@ -126,13 +127,13 @@ int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev)
126127
}
127128

128129
int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
129-
unsigned int reportnum, void *buf, u32 buf_len)
130+
unsigned int reportnum, void *buf, size_t buf_len)
130131
{
131132
struct hidi2c_report_packet *rpt;
132-
size_t write_buf_len, read_len = 0;
133-
int cmd_len, rep_type;
133+
size_t cmd_len, read_len = 0;
134+
int rep_type, ret;
135+
ssize_t len;
134136
u32 cmd;
135-
int ret;
136137

137138
if (report_type == HID_INPUT_REPORT) {
138139
rep_type = HIDI2C_INPUT;
@@ -145,25 +146,22 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
145146

146147
cmd_len = quicki2c_encode_cmd(qcdev, &cmd, HIDI2C_GET_REPORT, rep_type, reportnum);
147148

148-
ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0,
149+
len = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0,
149150
qcdev->report_buf, qcdev->report_len);
150-
if (ret < 0)
151-
return ret;
152-
153-
write_buf_len = ret;
151+
if (len < 0)
152+
return len;
154153

155154
rpt = (struct hidi2c_report_packet *)qcdev->input_buf;
156155

157-
ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, write_buf_len,
158-
NULL, rpt, &read_len);
156+
ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, len, NULL, rpt, &read_len);
159157
if (ret) {
160-
dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %d)\n",
158+
dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %zu)\n",
161159
ret, read_len, buf_len);
162160
return ret;
163161
}
164162

165163
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",
164+
dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %zu) report id (%d vs %d)\n",
167165
le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum);
168166
return -EINVAL;
169167
}
@@ -174,7 +172,7 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
174172
}
175173

176174
int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
177-
unsigned int reportnum, void *buf, u32 buf_len)
175+
unsigned int reportnum, void *buf, size_t buf_len)
178176
{
179177
int rep_type;
180178
int ret;
@@ -197,6 +195,25 @@ int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
197195
return buf_len;
198196
}
199197

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+
200217
#define HIDI2C_RESET_TIMEOUT 5
201218

202219
int quicki2c_reset(struct quicki2c_device *qcdev)

drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ struct quicki2c_device;
1010

1111
int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state);
1212
int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
13-
unsigned int reportnum, void *buf, u32 buf_len);
13+
unsigned int reportnum, void *buf, size_t buf_len);
1414
int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
15-
unsigned int reportnum, void *buf, u32 buf_len);
15+
unsigned int reportnum, void *buf, size_t buf_len);
16+
int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len);
1617
int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev);
1718
int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev);
1819
int quicki2c_reset(struct quicki2c_device *qcdev);

0 commit comments

Comments
 (0)