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: 13+ 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-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.