projects/linux·blob master · refs

81 lines · 1.8 KiB

1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * AMD SFH tablet-mode switch driver
4 *
5 * Copyright (c) 2026, Advanced Micro Devices, Inc.
6 * All Rights Reserved.
7 *
8 * Author: Basavaraj Natikar <[email protected]>
9 */
10
11#include <linux/amd-pmf-io.h>
12#include <linux/auxiliary_bus.h>
13#include <linux/input.h>
14#include <linux/module.h>
15#include <linux/pci_ids.h>
16
17#define POLL_INTERVAL_MS 200
18
19static void sfh_tm_poll(struct input_dev *input)
20{
21 struct amd_sfh_info info = {};
22
23 if (amd_get_sfh_info(&info, MT_OP_MODE))
24 return;
25
26 input_report_switch(input, SW_TABLET_MODE,
27 info.op_mode == SFH_MODE_TABLET);
28 input_sync(input);
29}
30
31static int sfh_tm_probe(struct auxiliary_device *auxdev,
32 const struct auxiliary_device_id *id)
33{
34 struct device *dev = &auxdev->dev;
35 struct amd_sfh_info info = {};
36 struct input_dev *input;
37 int error;
38
39 error = amd_get_sfh_info(&info, MT_OP_MODE);
40 if (error)
41 return error == -EINVAL ? -ENODEV : error;
42
43 input = devm_input_allocate_device(dev);
44 if (!input)
45 return -ENOMEM;
46
47 input->name = "AMD SFH tablet mode switch";
48 input->phys = "amd-sfh/tabletmode";
49 input->id.bustype = BUS_HOST;
50 input->id.vendor = PCI_VENDOR_ID_AMD;
51 input_set_capability(input, EV_SW, SW_TABLET_MODE);
52
53 error = input_setup_polling(input, sfh_tm_poll);
54 if (error)
55 return error;
56 input_set_poll_interval(input, POLL_INTERVAL_MS);
57
58 sfh_tm_poll(input);
59
60 error = input_register_device(input);
61 if (error)
62 return error;
63
64 return 0;
65}
66
67static const struct auxiliary_device_id sfh_tm_id_table[] = {
68 { .name = "amd_sfh.tabletmode" },
69 {}
70};
71MODULE_DEVICE_TABLE(auxiliary, sfh_tm_id_table);
72
73static struct auxiliary_driver sfh_tm_driver = {
74 .name = "tabletmode",
75 .id_table = sfh_tm_id_table,
76 .probe = sfh_tm_probe,
77};
78module_auxiliary_driver(sfh_tm_driver);
79
80MODULE_DESCRIPTION("AMD SFH tablet mode switch");
81MODULE_LICENSE("GPL");