From: Helge Bahmann <hcb@chaoticmind.net>
To: Jiri Kosina <jikos@kernel.org>,
linux-input@vger.kernel.org, Basavaraj Natikar <bnatikar@amd.com>
Cc: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
Subject: [PATCH 1/2] amd-sfh-hid: tablet mode hid report and asus quirk
Date: Tue, 21 Jul 2026 16:29:05 +0200 [thread overview]
Message-ID: <2108873.tdWV9SEqCh@zephyr> (raw)
In-Reply-To: <ecadaac8-e222-420a-ac5b-4d529fb3317e@amd.com>
Add an input driver that interprets the "operation mode" sensor offered
by the amd sfh as a hid driver to generate a custom hid report (tablet
mode switch).
Add a quirk to restore compatibility of the driver with the Asus
VivoBook (turn off the "disable interrupts flag). Expose the
intr_disable flag as a module parameter in case it turns out to be
needed on further laptop models.
Signed-off-by: Helge Bahmann <hcb@chaoticmind.net>
---
drivers/hid/amd-sfh-hid/amd_sfh_client.c | 19 ------------
drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 1 +
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 9 ++++++
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h | 3 ++
.../hid_descriptor/amd_sfh_hid_desc.c | 31 +++++++++++++++++++
.../hid_descriptor/amd_sfh_hid_desc.h | 9 ++++++
.../hid_descriptor/amd_sfh_hid_report_desc.h | 18 +++++++++++
7 files changed, 71 insertions(+), 19 deletions(-)
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index 7017bfa59093..57ff708ca39b 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -254,19 +254,6 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
goto cleanup;
}
- if (cl_data->sensor_idx[i] == op_idx) {
- info.period = AMD_SFH_IDLE_LOOP;
- info.sensor_idx = cl_data->sensor_idx[i];
- info.dma_address = cl_data->sensor_dma_addr[i];
- mp2_ops->start(privdata, info);
- cl_data->sensor_sts[i] = amd_sfh_wait_for_response(privdata,
- cl_data->sensor_idx[i],
- SENSOR_ENABLED);
- if (cl_data->sensor_sts[i] == SENSOR_ENABLED)
- cl_data->is_any_sensor_enabled = true;
- continue;
- }
-
cl_data->sensor_sts[i] = SENSOR_DISABLED;
cl_data->sensor_requested_cnt[i] = 0;
cl_data->cur_hid_dev = i;
@@ -327,12 +314,6 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
for (i = 0; i < cl_data->num_hid_devices; i++) {
cl_data->cur_hid_dev = i;
- if (cl_data->sensor_idx[i] == op_idx) {
- dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
- cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
- cl_data->sensor_sts[i]);
- continue;
- }
if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
rc = amdtp_hid_probe(i, cl_data);
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
index 7452b0302953..c1b62e5df2ff 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
@@ -78,4 +78,5 @@ void amdtp_hid_remove(struct amdtp_cl_data *cli_data);
int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type);
void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type);
void amdtp_hid_wakeup(struct hid_device *hid);
+
#endif
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index 1d9f955573aa..cd9cff75f114 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -39,6 +39,8 @@ module_param_named(sensor_mask, sensor_mask_override, int, 0444);
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");
static bool intr_disable = true;
+module_param_named(intr_disable, intr_disable, bool, 0444);
+MODULE_PARM_DESC(intr_disable, "override the interrupt disable sensor bit");
static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
{
@@ -317,6 +319,13 @@ static const struct dmi_system_id dmi_sfh_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook x360 435 G7"),
},
},
+ {
+ .callback = mp2_disable_intr,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VivoBook_ASUSLaptop TP420UA_TM420UA"),
+ }
+ },
{}
};
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
index 2eb61f4e8434..5e968894ebe4 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
@@ -83,6 +83,9 @@ enum sensor_idx {
als_idx = 19
};
+#define AMD_SFH_OP_IDX_MODE_LAPTOP 1
+#define AMD_SFH_OP_IDX_MODE_TABLET 3
+
enum mem_use_type {
USE_DRAM,
USE_C2P_REG,
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
index ef1f9be8b893..7e807b92d296 100644
--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
@@ -42,6 +42,11 @@ static int get_report_descriptor(int sensor_idx, u8 *rep_desc)
memcpy(rep_desc, gyro3_report_descriptor,
sizeof(gyro3_report_descriptor));
break;
+ case op_idx: /* op */
+ memset(rep_desc, 0, sizeof(tablet_mode_report_descriptor));
+ memcpy(rep_desc, tablet_mode_report_descriptor,
+ sizeof(tablet_mode_report_descriptor));
+ break;
case mag_idx: /* Magnetometer */
memset(rep_desc, 0, sizeof(comp3_report_descriptor));
memcpy(rep_desc, comp3_report_descriptor,
@@ -87,6 +92,16 @@ static u32 get_descr_sz(int sensor_idx, int descriptor_name)
return sizeof(struct gyro_feature_report);
}
break;
+ case op_idx:
+ switch (descriptor_name) {
+ case descr_size:
+ return sizeof(tablet_mode_report_descriptor);
+ case input_size:
+ return sizeof(struct tablet_mode_input_report);
+ case feature_size:
+ return sizeof(struct tablet_mode_feature_report);
+ }
+ break;
case mag_idx:
switch (descriptor_name) {
case descr_size:
@@ -139,6 +154,7 @@ static u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
{
struct accel3_feature_report acc_feature;
struct gyro_feature_report gyro_feature;
+ struct tablet_mode_feature_report tablet_mode_feature;
struct magno_feature_report magno_feature;
struct hpd_feature_report hpd_feature;
struct als_feature_report als_feature;
@@ -164,6 +180,11 @@ static u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));
report_size = sizeof(gyro_feature);
break;
+ case op_idx: /* op */
+ get_common_features(&tablet_mode_feature.common_property, report_id);
+ memcpy(feature_report, &tablet_mode_feature, sizeof(tablet_mode_feature));
+ report_size = sizeof(tablet_mode_feature);
+ break;
case mag_idx: /* Magnetometer */
get_common_features(&magno_feature.common_property, report_id);
magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;
@@ -212,6 +233,7 @@ static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
u8 supported_input = privdata->mp2_acs & GENMASK(3, 0);
struct magno_input_report magno_input;
struct accel3_input_report acc_input;
+ struct tablet_mode_input_report tablet_mode_input;
struct gyro_input_report gyro_input;
struct hpd_input_report hpd_input;
struct als_input_report als_input;
@@ -238,6 +260,15 @@ static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
memcpy(input_report, &gyro_input, sizeof(gyro_input));
report_size = sizeof(gyro_input);
break;
+ case op_idx: /* op */
+ tablet_mode_input.report_id = 0x11;
+ if (sensor_virt_addr[0] == 3)
+ tablet_mode_input.tablet_state = 1;
+ else
+ tablet_mode_input.tablet_state = 0;
+ memcpy(input_report, &tablet_mode_input, sizeof(tablet_mode_input));
+ report_size = sizeof(tablet_mode_input);
+ break;
case mag_idx: /* Magnetometer */
get_common_inputs(&magno_input.common_property, report_id);
magno_input.in_magno_x = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
index 882434b1501f..ff82e47eb3ca 100644
--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
@@ -114,4 +114,13 @@ struct hpd_input_report {
u8 human_presence;
} __packed;
+struct tablet_mode_feature_report {
+ struct common_feature_property common_property;
+} __packed;
+
+struct tablet_mode_input_report {
+ u8 report_id; /* Muss 0x11 (17) sein */
+ u8 tablet_state; /* Bit 0: Status, Bits 1-7: Padding */
+} __packed;
+
#endif
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
index 67ec2d6a417d..f95368534fc6 100644
--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
@@ -776,4 +776,22 @@ static const u8 hpd_report_descriptor[] = {
0X81, 0x02, /* HID Input (Data_Var_Abs) */
0xC0 /* HID end collection */
};
+
+/* tablet mode switch */
+static const u8 tablet_mode_report_descriptor[] = {
+0x05, 0x0C, /* HID usage consumer electronics */
+0x09, 0x01, /* HID usage */
+0xA1, 0x00, /* HID collection (Physical) */
+0x85, 0x11, /* HID report id */
+0x0A, 0xFF, 0x02, /* HID usage (unallocated -- (ab)used for tablet mode) */
+0x15, 0x00, /* HID logical Min_8(0) */
+0x25, 0x01, /* HID logical Max_8(1) */
+0x75, 0x01, /* HID report size(1) */
+0x95, 0x01, /* HID report count (1) */
+0X81, 0x02, /* HID input (Data_Var_Abs) */
+0x75, 0x01, /* HID report size (1) */
+0x95, 0x07, /* HID report count (7) */
+0x81, 0x03, /* HID input (Data_Var_Abs) */
+0xC0 /* HID end collection */
+};
#endif
--
2.47.3
next prev parent reply other threads:[~2026-07-21 14:29 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-27 6:22 [PATCH] amd-sfh-hid: tablet mode switch and asus quirk Helge Bahmann
2026-05-12 16:06 ` Jiri Kosina
2026-05-12 17:09 ` Basavaraj Natikar
2026-05-14 7:59 ` Helge Bahmann
2026-06-10 17:12 ` Basavaraj Natikar
2026-06-12 4:22 ` Helge Bahmann
2026-07-21 14:28 ` [PATCH 0/2] asus vivobook tablet mode Helge Bahmann
2026-07-21 17:52 ` Basavaraj Natikar
2026-07-21 14:29 ` Helge Bahmann [this message]
2026-07-21 14:47 ` [PATCH 1/2] amd-sfh-hid: tablet mode hid report and asus quirk sashiko-bot
2026-07-21 14:29 ` [PATCH 2/2] amd-sfh-tabletmode: interpret sfh tablet mode hid report Helge Bahmann
2026-07-21 14:41 ` sashiko-bot
2026-08-03 17:33 ` Jiri Kosina
2026-08-03 17:42 ` Basavaraj Natikar
2026-08-03 18:23 ` Jiri Kosina
2026-06-10 16:33 ` [PATCH] amd-sfh-hid: tablet mode switch and asus quirk Jiri Kosina
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2108873.tdWV9SEqCh@zephyr \
--to=hcb@chaoticmind.net \
--cc=Basavaraj.Natikar@amd.com \
--cc=bnatikar@amd.com \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).