From 7efb83f0a94cafb343140df22d7f5947d3ebf930 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Tue, 28 Jul 2026 20:59:46 -0700 Subject: [PATCH 1/5] [NOT-FOR-UPSTREAM] HID: hid-oxp: Report RGB LED under the Legion Go name This is deliberately an OGC-carried patch and must not be sent upstream. Squatting on another device's LED name is not acceptable in mainline; the real fix belongs in the Steam client, which should match the "*:rgb:joystick_rings" suffix rather than a per-device prefix. --- drivers/hid/hid-oxp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-oxp.c b/drivers/hid/hid-oxp.c index 20a54f337220d..b7427ebf6d1d2 100644 --- a/drivers/hid/hid-oxp.c +++ b/drivers/hid/hid-oxp.c @@ -1386,7 +1386,7 @@ static struct mc_subled oxp_rgb_subled_info[] = { static struct led_classdev_mc oxp_cdev_rgb = { .led_cdev = { - .name = "oxp:rgb:joystick_rings", + .name = "go:rgb:joystick_rings", .color = LED_COLOR_ID_RGB, .brightness = 0x64, .max_brightness = 0x64, From 1e91de9f5b45cdda3bcb19e026cb0fa4afd8c0e0 Mon Sep 17 00:00:00 2001 From: Jeff Hagadorn Date: Wed, 5 Aug 2026 11:31:02 -0700 Subject: [PATCH 2/5] [FROM-ML] platform/x86: oxpec: Add support for OneXPlayer X2 Mini Pro OneXPlayer X2 Mini Pro is a new Strix Halo handheld. It ships the same system board as the OneXPlayer APEX and uses the same registers as the OneXPlayer Fly devices. Add a quirk for it to the oxpec driver. Signed-off-by: Jeff Hagadorn --- drivers/platform/x86/oxpec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/oxpec.c b/drivers/platform/x86/oxpec.c index 99c0dfcf393b7..34bb17fca1481 100644 --- a/drivers/platform/x86/oxpec.c +++ b/drivers/platform/x86/oxpec.c @@ -289,6 +289,13 @@ static const struct dmi_system_id dmi_table[] = { }, .driver_data = (void *)oxp_x1, }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X2Mini PRO"), + }, + .driver_data = (void *)oxp_fly, + }, {}, }; From 9e8e8922627c339daeb85661265ca1401dcfb81b Mon Sep 17 00:00:00 2001 From: Alexander Egorov Date: Tue, 28 Jul 2026 11:35:28 +0300 Subject: [PATCH 3/5] [FROM-ML] platform/x86: oxpec: Distinguish OneXPlayer Super X board The Super X currently shares the oxp_g1_a board identifier because its existing EC functionality matches the G1 AMD. Give it a dedicated identifier so model-specific functionality can be selected without also enabling it on the G1. Preserve the existing G1 AMD behavior for the new identifier. Assisted-by: Codex:gpt-5.6 Signed-off-by: Alexander Egorov --- drivers/platform/x86/oxpec.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/oxpec.c b/drivers/platform/x86/oxpec.c index 34bb17fca1481..00a5e64b20015 100644 --- a/drivers/platform/x86/oxpec.c +++ b/drivers/platform/x86/oxpec.c @@ -50,6 +50,7 @@ enum oxp_board { oxp_x1, oxp_g1_i, oxp_g1_a, + oxp_super_x, }; static enum oxp_board board; @@ -210,7 +211,7 @@ static const struct dmi_system_id dmi_table[] = { DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER SUPER X"), }, - .driver_data = (void *)oxp_g1_a, + .driver_data = (void *)oxp_super_x, }, { .matches = { @@ -352,6 +353,7 @@ static umode_t tt_toggle_is_visible(struct kobject *kobj, case oxp_x1: case oxp_g1_i: case oxp_g1_a: + case oxp_super_x: return attr->mode; default: break; @@ -381,6 +383,7 @@ static ssize_t tt_toggle_store(struct device *dev, case oxp_fly: case oxp_mini_amd_pro: case oxp_g1_a: + case oxp_super_x: reg = OXP_TURBO_SWITCH_REG; mask = OXP_TURBO_TAKE_VAL; break; @@ -427,6 +430,7 @@ static ssize_t tt_toggle_show(struct device *dev, case oxp_fly: case oxp_mini_amd_pro: case oxp_g1_a: + case oxp_super_x: reg = OXP_TURBO_SWITCH_REG; mask = OXP_TURBO_TAKE_VAL; break; @@ -523,6 +527,7 @@ static bool oxp_psy_ext_supported(void) case oxp_x1: case oxp_g1_i: case oxp_g1_a: + case oxp_super_x: case oxp_fly: return true; default: @@ -656,6 +661,7 @@ static int oxp_pwm_enable(void) case oxp_x1: case oxp_g1_i: case oxp_g1_a: + case oxp_super_x: return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, PWM_MODE_MANUAL); default: return -EINVAL; @@ -676,6 +682,7 @@ static int oxp_pwm_disable(void) case oxp_x1: case oxp_g1_i: case oxp_g1_a: + case oxp_super_x: return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, PWM_MODE_AUTO); default: return -EINVAL; @@ -696,6 +703,7 @@ static int oxp_pwm_read(long *val) case oxp_x1: case oxp_g1_i: case oxp_g1_a: + case oxp_super_x: return read_from_ec(OXP_SENSOR_PWM_ENABLE_REG, 1, val); default: return -EOPNOTSUPP; @@ -732,6 +740,7 @@ static int oxp_pwm_fan_speed(long *val) case oxp_mini_amd_a07: case oxp_mini_amd_pro: case oxp_g1_a: + case oxp_super_x: return read_from_ec(OXP_SENSOR_FAN_REG, 2, val); default: return -EOPNOTSUPP; @@ -764,6 +773,7 @@ static int oxp_pwm_input_write(long val) case oxp_fly: case oxp_mini_amd_pro: case oxp_g1_a: + case oxp_super_x: return write_to_ec(OXP_SENSOR_PWM_REG, val); default: return -EOPNOTSUPP; @@ -803,6 +813,7 @@ static int oxp_pwm_input_read(long *val) case oxp_fly: case oxp_mini_amd_pro: case oxp_g1_a: + case oxp_super_x: default: ret = read_from_ec(OXP_SENSOR_PWM_REG, 1, val); if (ret) From 6a25dacdf28fcd69e7371a81bae185fb88846f68 Mon Sep 17 00:00:00 2001 From: Alexander Egorov Date: Tue, 28 Jul 2026 11:35:29 +0300 Subject: [PATCH 4/5] [FROM-ML] platform/x86: oxpec: Report tablet mode on OneXPlayer detachables The OneXPlayer X1 family and Super X have detachable pogo-pin keyboards. The firmware does not expose a tablet-mode input switch. The Super X keyboard enumerates as 1a86:1305. The X1 family folio keyboard enumerates as 258a:001e. Register an input device on these boards and report SW_TABLET_MODE from the model-specific pogo keyboard USB hotplug state. Other USB and Bluetooth keyboards do not affect the switch. A complete dump of the 256-byte Super X EC register map was compared with the keyboard attached, detached, and reattached. No register changed predictably with the attachment state. Tested on a OneXPlayer Super X. Mutter enables accelerometer-driven display rotation only while the pogo keyboard is absent. Assisted-by: Codex:gpt-5.6 Signed-off-by: Alexander Egorov --- drivers/platform/x86/Kconfig | 2 + drivers/platform/x86/oxpec.c | 103 +++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b54b5212b2047..960b2ae6d94d1 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1056,6 +1056,8 @@ config OXP_EC depends on ACPI_BATTERY depends on HWMON depends on X86 + depends on INPUT + depends on USB help Enables support for the platform EC of OneXPlayer and AOKZOE handheld devices. This includes fan speed, fan controls, and diff --git a/drivers/platform/x86/oxpec.c b/drivers/platform/x86/oxpec.c index 00a5e64b20015..5680c3bcd604e 100644 --- a/drivers/platform/x86/oxpec.c +++ b/drivers/platform/x86/oxpec.c @@ -18,10 +18,12 @@ #include #include #include +#include #include #include #include #include +#include #include /* Handle ACPI lock mechanism */ @@ -55,6 +57,8 @@ enum oxp_board { static enum oxp_board board; static struct device *oxp_dev; +static struct input_dev *oxp_tablet_mode_input; +static struct notifier_block oxp_usb_notifier; /* Fan reading and PWM */ #define OXP_SENSOR_FAN_REG 0x76 /* Fan reading is 2 registers long */ @@ -300,6 +304,74 @@ static const struct dmi_system_id dmi_table[] = { {}, }; +#define OXP_KEYBOARD_VID_QINHENG 0x1a86 +#define OXP_KEYBOARD_PID_K2445 0x1305 +#define OXP_KEYBOARD_VID_HAILUCK 0x258a +#define OXP_KEYBOARD_PID_HAILUCK 0x001e + +static int oxp_find_keyboard(struct usb_device *udev, void *data) +{ + bool *keyboard_attached = data; + u16 vid = le16_to_cpu(udev->descriptor.idVendor); + u16 pid = le16_to_cpu(udev->descriptor.idProduct); + + switch (board) { + case oxp_x1: + if (vid == OXP_KEYBOARD_VID_HAILUCK && + pid == OXP_KEYBOARD_PID_HAILUCK) + *keyboard_attached = true; + break; + case oxp_super_x: + if (vid == OXP_KEYBOARD_VID_QINHENG && + pid == OXP_KEYBOARD_PID_K2445) + *keyboard_attached = true; + break; + default: + break; + } + + return 0; +} + +static int oxp_usb_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct usb_device *udev = data; + u16 vid = le16_to_cpu(udev->descriptor.idVendor); + u16 pid = le16_to_cpu(udev->descriptor.idProduct); + bool keyboard = false; + + switch (board) { + case oxp_x1: + keyboard = vid == OXP_KEYBOARD_VID_HAILUCK && + pid == OXP_KEYBOARD_PID_HAILUCK; + break; + case oxp_super_x: + keyboard = vid == OXP_KEYBOARD_VID_QINHENG && + pid == OXP_KEYBOARD_PID_K2445; + break; + default: + break; + } + + if (!keyboard) + return NOTIFY_DONE; + + switch (action) { + case USB_DEVICE_ADD: + input_report_switch(oxp_tablet_mode_input, SW_TABLET_MODE, false); + break; + case USB_DEVICE_REMOVE: + input_report_switch(oxp_tablet_mode_input, SW_TABLET_MODE, true); + break; + default: + return NOTIFY_DONE; + } + + input_sync(oxp_tablet_mode_input); + return NOTIFY_OK; +} + /* Helper functions to handle EC read/write */ static int read_from_ec(u8 reg, int size, long *val) { @@ -955,6 +1027,7 @@ static const struct hwmon_chip_info oxp_ec_chip_info = { /* Initialization logic */ static int oxp_platform_probe(struct platform_device *pdev) { + bool keyboard_attached = false; struct device *dev = &pdev->dev; struct device *hwdev; int ret; @@ -972,6 +1045,33 @@ static int oxp_platform_probe(struct platform_device *pdev) return ret; } + switch (board) { + case oxp_x1: + case oxp_super_x: + oxp_tablet_mode_input = devm_input_allocate_device(dev); + if (!oxp_tablet_mode_input) + return -ENOMEM; + + oxp_tablet_mode_input->name = "OneXPlayer Tablet Mode Switch"; + oxp_tablet_mode_input->phys = "oxp-platform/input0"; + oxp_tablet_mode_input->id.bustype = BUS_HOST; + input_set_capability(oxp_tablet_mode_input, EV_SW, SW_TABLET_MODE); + + ret = input_register_device(oxp_tablet_mode_input); + if (ret) + return ret; + + oxp_usb_notifier.notifier_call = oxp_usb_notify; + usb_register_notify(&oxp_usb_notifier); + usb_for_each_dev(&keyboard_attached, oxp_find_keyboard); + input_report_switch(oxp_tablet_mode_input, SW_TABLET_MODE, + !keyboard_attached); + input_sync(oxp_tablet_mode_input); + break; + default: + break; + } + return 0; } @@ -1012,6 +1112,9 @@ static int __init oxp_platform_init(void) static void __exit oxp_platform_exit(void) { + if (board == oxp_x1 || board == oxp_super_x) + usb_unregister_notify(&oxp_usb_notifier); + platform_device_unregister(oxp_platform_device); platform_driver_unregister(&oxp_platform_driver); } From 2555f9fb097242182380867e6ec12a3672f47fbd Mon Sep 17 00:00:00 2001 From: Andrei Aldea Date: Sun, 23 Aug 2026 17:16:59 -0500 Subject: [PATCH 5/5] [FOR-UPSTREAM] platform/x86: oxpec: Add ONEXPLAYER 3 fan monitoring Match the ONEXPLAYER 3 DMI identity and read its fan tachometer through the EC register. Signed-off-by: Andrei Aldea --- drivers/platform/x86/oxpec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/platform/x86/oxpec.c b/drivers/platform/x86/oxpec.c index 5680c3bcd604e..b4e28ddccc7b4 100644 --- a/drivers/platform/x86/oxpec.c +++ b/drivers/platform/x86/oxpec.c @@ -45,6 +45,7 @@ enum oxp_board { aok_zoe_a1 = 1, orange_pi_neo, oxp_2, + oxp_3, oxp_fly, oxp_mini_amd, oxp_mini_amd_a07, @@ -154,6 +155,13 @@ static const struct dmi_system_id dmi_table[] = { }, .driver_data = (void *)oxp_2, }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER 3"), + }, + .driver_data = (void *)oxp_3, + }, { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), @@ -790,6 +798,8 @@ static umode_t oxp_ec_hwmon_is_visible(const void *drvdata, case hwmon_fan: return 0444; case hwmon_pwm: + if (board == oxp_3) + return 0; return 0644; default: return 0; @@ -803,6 +813,7 @@ static int oxp_pwm_fan_speed(long *val) case orange_pi_neo: return read_from_ec(ORANGEPI_SENSOR_FAN_REG, 2, val); case oxp_2: + case oxp_3: case oxp_x1: case oxp_g1_i: return read_from_ec(OXP_2_SENSOR_FAN_REG, 2, val);