xref: /linux/drivers/input/misc/amd_sfh_tabletmode.c (revision a93f3bf4e1d60777b1659b812c9e818cfc53b449)
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 <Basavaraj.Natikar@amd.com>
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 
19 static 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 
31 static 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 
67 static const struct auxiliary_device_id sfh_tm_id_table[] = {
68 	{ .name = "amd_sfh.tabletmode" },
69 	{}
70 };
71 MODULE_DEVICE_TABLE(auxiliary, sfh_tm_id_table);
72 
73 static struct auxiliary_driver sfh_tm_driver = {
74 	.name		= "tabletmode",
75 	.id_table	= sfh_tm_id_table,
76 	.probe		= sfh_tm_probe,
77 };
78 module_auxiliary_driver(sfh_tm_driver);
79 
80 MODULE_DESCRIPTION("AMD SFH tablet mode switch");
81 MODULE_LICENSE("GPL");
82