Skip to content

Commit 3e78a6c

Browse files
committed
Merge tag 'hid-for-linus-2024031301' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - support for the following Bluetooth devices from Samsung: Samsung wireless {Keyboard, GamePad, Action Mouse, Book Cover, Universal Keyboard, HOGP Keyboard} (Sandeep C S) - second version of code for applying proper quirk depending on firmware version for lenovo/cptkbd (Mikhail Khvainitski) - lenovo/cptkbd firmware-dependent quirk (Mikhail Khvainitski) - assorted fixes and optimizations for amd-sfh (Basavaraj Natikar) - dead code and dead data structures removal (Jiri Slaby, Jiapeng Chong) * tag 'hid-for-linus-2024031301' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (25 commits) HID: amd_sfh: Set the AMD SFH driver to depend on x86 HID: input: avoid polling stylus battery on Chromebook Pompom HID: amd_sfh: Extend MP2 register access to SFH HID: amd_sfh: Improve boot time when SFH is available HID: amd_sfh: Avoid disabling the interrupt HID: amd_sfh: Update HPD sensor structure elements HID: amd_sfh: Increase sensor command timeout HID: intel-ish-hid: ipc: Add Arrow Lake PCI device ID HID: nintendo: Remove some unused functions HID: hid-prodikeys: remove struct pk_device HID: hid-prodikeys: remove unused struct pcmidi_snd members HID: hid-multitouch: remove unused mt_application::dev_time HID: hid-lg3ff: remove unused struct lg3ff_device HID: protect hid_device::bpf by CONFIG_HID_BPF HID: wacom: remove unused hid_data::pressure HID: apple: remove unused members from struct apple_sc_backlight HID: wacom: Clean up use of struct->wacom_wac HID: samsung: Add Samsung wireless bookcover and universal keyboard support HID: samsung: Add Samsung wireless action mouse support HID: samsung: Add Samsung wireless gamepad support ...
2 parents b345ff6 + 0db18cd commit 3e78a6c

21 files changed

+623
-196
lines changed

drivers/hid/amd-sfh-hid/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ menu "AMD SFH HID Support"
66
config AMD_SFH_HID
77
tristate "AMD Sensor Fusion Hub"
88
depends on HID
9+
depends on X86
910
help
1011
If you say yes to this option, support will be included for the
1112
AMD Sensor Fusion Hub.

drivers/hid/amd-sfh-hid/amd_sfh_common.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
2020
#define AMD_P2C_MSG(regno) (0x10680 + ((regno) * 4))
2121

22+
#define AMD_C2P_MSG_V1(regno) (0x10900 + ((regno) * 4))
23+
#define AMD_P2C_MSG_V1(regno) (0x10500 + ((regno) * 4))
24+
2225
#define SENSOR_ENABLED 4
2326
#define SENSOR_DISABLED 5
2427

@@ -53,6 +56,9 @@ struct amd_mp2_dev {
5356
/* mp2 active control status */
5457
u32 mp2_acs;
5558
struct sfh_dev_status dev_en;
59+
struct work_struct work;
60+
u8 init_done;
61+
u8 rver;
5662
};
5763

5864
struct amd_mp2_ops {
@@ -79,4 +85,14 @@ void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata);
7985
int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata);
8086
void amd_sfh_clear_intr(struct amd_mp2_dev *privdata);
8187
int amd_sfh_irq_init(struct amd_mp2_dev *privdata);
88+
89+
static inline u64 amd_get_c2p_val(struct amd_mp2_dev *mp2, u32 idx)
90+
{
91+
return mp2->rver == 1 ? AMD_C2P_MSG_V1(idx) : AMD_C2P_MSG(idx);
92+
}
93+
94+
static inline u64 amd_get_p2c_val(struct amd_mp2_dev *mp2, u32 idx)
95+
{
96+
return mp2->rver == 1 ? AMD_P2C_MSG_V1(idx) : AMD_P2C_MSG(idx);
97+
}
8298
#endif

drivers/hid/amd-sfh-hid/amd_sfh_pcie.c

Lines changed: 97 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <linux/bitops.h>
1212
#include <linux/delay.h>
13+
#include <linux/devm-helpers.h>
1314
#include <linux/dma-mapping.h>
1415
#include <linux/dmi.h>
1516
#include <linux/interrupt.h>
@@ -35,15 +36,17 @@ static int sensor_mask_override = -1;
3536
module_param_named(sensor_mask, sensor_mask_override, int, 0444);
3637
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");
3738

39+
static bool intr_disable = true;
40+
3841
static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
3942
{
4043
union cmd_response cmd_resp;
4144

42-
/* Get response with status within a max of 1600 ms timeout */
45+
/* Get response with status within a max of 10 seconds timeout */
4346
if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
4447
(cmd_resp.response_v2.response == sensor_sts &&
4548
cmd_resp.response_v2.status == 0 && (sid == 0xff ||
46-
cmd_resp.response_v2.sensor_id == sid)), 500, 1600000))
49+
cmd_resp.response_v2.sensor_id == sid)), 500, 10000000))
4750
return cmd_resp.response_v2.response;
4851

4952
return SENSOR_DISABLED;
@@ -55,7 +58,7 @@ static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sen
5558

5659
cmd_base.ul = 0;
5760
cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR;
58-
cmd_base.cmd_v2.intr_disable = 1;
61+
cmd_base.cmd_v2.intr_disable = intr_disable;
5962
cmd_base.cmd_v2.period = info.period;
6063
cmd_base.cmd_v2.sensor_id = info.sensor_idx;
6164
cmd_base.cmd_v2.length = 16;
@@ -73,7 +76,7 @@ static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx)
7376

7477
cmd_base.ul = 0;
7578
cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR;
76-
cmd_base.cmd_v2.intr_disable = 1;
79+
cmd_base.cmd_v2.intr_disable = intr_disable;
7780
cmd_base.cmd_v2.period = 0;
7881
cmd_base.cmd_v2.sensor_id = sensor_idx;
7982
cmd_base.cmd_v2.length = 16;
@@ -87,7 +90,7 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
8790
union sfh_cmd_base cmd_base;
8891

8992
cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS;
90-
cmd_base.cmd_v2.intr_disable = 1;
93+
cmd_base.cmd_v2.intr_disable = intr_disable;
9194
cmd_base.cmd_v2.period = 0;
9295
cmd_base.cmd_v2.sensor_id = 0;
9396

@@ -96,9 +99,9 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
9699

97100
void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
98101
{
99-
if (readl(privdata->mmio + AMD_P2C_MSG(4))) {
100-
writel(0, privdata->mmio + AMD_P2C_MSG(4));
101-
writel(0xf, privdata->mmio + AMD_P2C_MSG(5));
102+
if (readl(privdata->mmio + amd_get_p2c_val(privdata, 4))) {
103+
writel(0, privdata->mmio + amd_get_p2c_val(privdata, 4));
104+
writel(0xf, privdata->mmio + amd_get_p2c_val(privdata, 5));
102105
}
103106
}
104107

@@ -292,6 +295,26 @@ int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
292295
return 0;
293296
}
294297

298+
static int mp2_disable_intr(const struct dmi_system_id *id)
299+
{
300+
intr_disable = false;
301+
return 0;
302+
}
303+
304+
static const struct dmi_system_id dmi_sfh_table[] = {
305+
{
306+
/*
307+
* https://bugzilla.kernel.org/show_bug.cgi?id=218104
308+
*/
309+
.callback = mp2_disable_intr,
310+
.matches = {
311+
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
312+
DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook x360 435 G7"),
313+
},
314+
},
315+
{}
316+
};
317+
295318
static const struct dmi_system_id dmi_nodevs[] = {
296319
{
297320
/*
@@ -307,6 +330,48 @@ static const struct dmi_system_id dmi_nodevs[] = {
307330
{ }
308331
};
309332

333+
static void sfh1_1_init_work(struct work_struct *work)
334+
{
335+
struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work);
336+
struct pci_dev *pdev = mp2->pdev;
337+
int rc;
338+
339+
rc = mp2->sfh1_1_ops->init(mp2);
340+
if (rc) {
341+
dev_err(&pdev->dev, "sfh1_1_init failed err %d\n", rc);
342+
return;
343+
}
344+
345+
amd_sfh_clear_intr(mp2);
346+
mp2->init_done = 1;
347+
}
348+
349+
static void sfh_init_work(struct work_struct *work)
350+
{
351+
struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work);
352+
struct pci_dev *pdev = mp2->pdev;
353+
int rc;
354+
355+
rc = amd_sfh_hid_client_init(mp2);
356+
if (rc) {
357+
amd_sfh_clear_intr(mp2);
358+
dev_err(&pdev->dev, "amd_sfh_hid_client_init failed err %d\n", rc);
359+
return;
360+
}
361+
362+
amd_sfh_clear_intr(mp2);
363+
mp2->init_done = 1;
364+
}
365+
366+
static void amd_sfh_remove(struct pci_dev *pdev)
367+
{
368+
struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
369+
370+
flush_work(&mp2->work);
371+
if (mp2->init_done)
372+
mp2->mp2_ops->remove(mp2);
373+
}
374+
310375
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
311376
{
312377
struct amd_mp2_dev *privdata;
@@ -315,6 +380,8 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
315380
if (dmi_first_match(dmi_nodevs))
316381
return -ENODEV;
317382

383+
dmi_check_system(dmi_sfh_table);
384+
318385
privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL);
319386
if (!privdata)
320387
return -ENOMEM;
@@ -343,10 +410,15 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
343410

344411
privdata->sfh1_1_ops = (const struct amd_sfh1_1_ops *)id->driver_data;
345412
if (privdata->sfh1_1_ops) {
346-
rc = privdata->sfh1_1_ops->init(privdata);
413+
if (boot_cpu_data.x86 >= 0x1A)
414+
privdata->rver = 1;
415+
416+
rc = devm_work_autocancel(&pdev->dev, &privdata->work, sfh1_1_init_work);
347417
if (rc)
348418
return rc;
349-
goto init_done;
419+
420+
schedule_work(&privdata->work);
421+
return 0;
350422
}
351423

352424
mp2_select_ops(privdata);
@@ -357,33 +429,34 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
357429
return rc;
358430
}
359431

360-
rc = amd_sfh_hid_client_init(privdata);
432+
rc = devm_work_autocancel(&pdev->dev, &privdata->work, sfh_init_work);
361433
if (rc) {
362434
amd_sfh_clear_intr(privdata);
363-
if (rc != -EOPNOTSUPP)
364-
dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n");
365435
return rc;
366436
}
367437

368-
init_done:
369-
amd_sfh_clear_intr(privdata);
370-
371-
return devm_add_action_or_reset(&pdev->dev, privdata->mp2_ops->remove, privdata);
438+
schedule_work(&privdata->work);
439+
return 0;
372440
}
373441

374442
static void amd_sfh_shutdown(struct pci_dev *pdev)
375443
{
376444
struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
377445

378-
if (mp2 && mp2->mp2_ops)
379-
mp2->mp2_ops->stop_all(mp2);
446+
if (mp2) {
447+
flush_work(&mp2->work);
448+
if (mp2->init_done)
449+
mp2->mp2_ops->stop_all(mp2);
450+
}
380451
}
381452

382453
static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
383454
{
384455
struct amd_mp2_dev *mp2 = dev_get_drvdata(dev);
385456

386-
mp2->mp2_ops->resume(mp2);
457+
flush_work(&mp2->work);
458+
if (mp2->init_done)
459+
mp2->mp2_ops->resume(mp2);
387460

388461
return 0;
389462
}
@@ -392,7 +465,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
392465
{
393466
struct amd_mp2_dev *mp2 = dev_get_drvdata(dev);
394467

395-
mp2->mp2_ops->suspend(mp2);
468+
flush_work(&mp2->work);
469+
if (mp2->init_done)
470+
mp2->mp2_ops->suspend(mp2);
396471

397472
return 0;
398473
}
@@ -414,6 +489,7 @@ static struct pci_driver amd_mp2_pci_driver = {
414489
.probe = amd_mp2_pci_probe,
415490
.driver.pm = &amd_mp2_pm_ops,
416491
.shutdown = amd_sfh_shutdown,
492+
.remove = amd_sfh_remove,
417493
};
418494
module_pci_driver(amd_mp2_pci_driver);
419495

drivers/hid/amd-sfh-hid/amd_sfh_pcie.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ enum mem_use_type {
9090
struct hpd_status {
9191
union {
9292
struct {
93-
u32 human_presence_report : 4;
94-
u32 human_presence_actual : 4;
95-
u32 probablity : 8;
9693
u32 object_distance : 16;
94+
u32 probablity : 8;
95+
u32 human_presence_actual : 4;
96+
u32 human_presence_report : 4;
9797
} shpd;
9898
u32 val;
9999
};

drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
251251
break;
252252
case HPD_IDX:
253253
get_common_inputs(&hpd_input.common_property, report_id);
254-
hpdstatus.val = readl(mp2->mmio + AMD_C2P_MSG(4));
254+
hpdstatus.val = readl(mp2->mmio + amd_get_c2p_val(mp2, 4));
255255
hpd_input.human_presence = hpdstatus.shpd.presence;
256256
report_size = sizeof(hpd_input);
257257
memcpy(input_report, &hpd_input, sizeof(hpd_input));

drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
172172
if (rc)
173173
goto cleanup;
174174

175-
writel(0, privdata->mmio + AMD_P2C_MSG(0));
175+
writel(0, privdata->mmio + amd_get_p2c_val(privdata, 0));
176176
mp2_ops->start(privdata, info);
177177
status = amd_sfh_wait_for_response
178178
(privdata, cl_data->sensor_idx[i], ENABLE_SENSOR);
@@ -298,7 +298,7 @@ static void amd_sfh_set_ops(struct amd_mp2_dev *mp2)
298298

299299
int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
300300
{
301-
u32 phy_base = readl(mp2->mmio + AMD_C2P_MSG(22));
301+
u32 phy_base = readl(mp2->mmio + amd_get_c2p_val(mp2, 22));
302302
struct device *dev = &mp2->pdev->dev;
303303
struct sfh_base_info binfo;
304304
int rc;

drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
2020
struct sfh_cmd_response cmd_resp;
2121

2222
/* Get response with status within a max of 10000 ms timeout */
23-
if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
23+
if (!readl_poll_timeout(mp2->mmio + amd_get_p2c_val(mp2, 0), cmd_resp.resp,
2424
(cmd_resp.response.response == 0 &&
2525
cmd_resp.response.cmd_id == cmd_id && (sid == 0xff ||
2626
cmd_resp.response.sensor_id == sid)), 500, 10000000))
@@ -39,7 +39,7 @@ static void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor
3939
cmd_base.cmd.sub_cmd_value = 1;
4040
cmd_base.cmd.sensor_id = info.sensor_idx;
4141

42-
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
42+
writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));
4343
}
4444

4545
static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
@@ -52,8 +52,8 @@ static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
5252
cmd_base.cmd.sub_cmd_value = 1;
5353
cmd_base.cmd.sensor_id = sensor_idx;
5454

55-
writeq(0x0, privdata->mmio + AMD_C2P_MSG(1));
56-
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
55+
writeq(0x0, privdata->mmio + amd_get_c2p_val(privdata, 1));
56+
writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));
5757
}
5858

5959
static void amd_stop_all_sensor(struct amd_mp2_dev *privdata)
@@ -66,7 +66,7 @@ static void amd_stop_all_sensor(struct amd_mp2_dev *privdata)
6666
/* 0xf indicates all sensors */
6767
cmd_base.cmd.sensor_id = 0xf;
6868

69-
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
69+
writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));
7070
}
7171

7272
static struct amd_mp2_ops amd_sfh_ops = {

drivers/hid/hid-apple.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ struct apple_non_apple_keyboard {
7979
struct apple_sc_backlight {
8080
struct led_classdev cdev;
8181
struct hid_device *hdev;
82-
unsigned short backlight_off, backlight_on_min, backlight_on_max;
8382
};
8483

8584
struct apple_sc {

drivers/hid/hid-ids.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@
430430
#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1 0x2BED
431431
#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2 0x2BEE
432432
#define I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG 0x2D02
433+
#define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81
433434

434435
#define USB_VENDOR_ID_ELECOM 0x056e
435436
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
@@ -1146,8 +1147,15 @@
11461147
#define USB_DEVICE_ID_SAITEK_X65 0x0b6a
11471148

11481149
#define USB_VENDOR_ID_SAMSUNG 0x0419
1150+
#define USB_VENDOR_ID_SAMSUNG_ELECTRONICS 0x04e8
11491151
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
11501152
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600
1153+
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD 0x7021
1154+
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_GAMEPAD 0xa000
1155+
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_ACTIONMOUSE 0xa004
1156+
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_BOOKCOVER 0xa005
1157+
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_UNIVERSAL_KBD 0xa006
1158+
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_MULTI_HOGP_KBD 0xa064
11511159

11521160
#define USB_VENDOR_ID_SEMICO 0x1a2c
11531161
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023

drivers/hid/hid-input.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
411411
HID_BATTERY_QUIRK_IGNORE },
412412
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG),
413413
HID_BATTERY_QUIRK_IGNORE },
414+
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM),
415+
HID_BATTERY_QUIRK_AVOID_QUERY },
414416
{}
415417
};
416418

0 commit comments

Comments
 (0)