aboutsummaryrefslogtreecommitdiff
path: root/SOURCES
diff options
context:
space:
mode:
authorJan200101 <sentrycraft123@gmail.com>2024-09-08 01:51:44 +0200
committerJan200101 <sentrycraft123@gmail.com>2024-09-08 01:51:44 +0200
commit047e589c8b3afbe92382f9c3072d100bcc590d72 (patch)
tree3b9c36516a2ad24317d5ae5c1a21e1d8287e12e3 /SOURCES
parent56d04f7e49da925d17785eaad94acb4cbd27004f (diff)
downloadkernel-fsync-047e589c8b3afbe92382f9c3072d100bcc590d72.tar.gz
kernel-fsync-047e589c8b3afbe92382f9c3072d100bcc590d72.zip
kernel 6.10.7
Diffstat (limited to 'SOURCES')
-rw-r--r--SOURCES/0001-add-ally-x-dmi-quirk-for-controller-suspend.patch28
-rw-r--r--SOURCES/0001-patch_realtek-Fix-ROG-ALLY-X-audio.patch50
-rw-r--r--SOURCES/Patchlist.changelog24
-rw-r--r--SOURCES/asus-linux.patch4733
-rw-r--r--SOURCES/dcn32-dcn301-dcn321-mpo-reverts.patch4
-rw-r--r--SOURCES/kernel-aarch64-16k-debug-fedora.config2
-rw-r--r--SOURCES/kernel-aarch64-16k-fedora.config2
-rw-r--r--SOURCES/kernel-aarch64-64k-debug-rhel.config2
-rw-r--r--SOURCES/kernel-aarch64-64k-rhel.config2
-rw-r--r--SOURCES/kernel-aarch64-debug-fedora.config2
-rw-r--r--SOURCES/kernel-aarch64-debug-rhel.config2
-rw-r--r--SOURCES/kernel-aarch64-fedora.config2
-rw-r--r--SOURCES/kernel-aarch64-rhel.config2
-rw-r--r--SOURCES/kernel-aarch64-rt-debug-rhel.config2
-rw-r--r--SOURCES/kernel-aarch64-rt-rhel.config2
-rw-r--r--SOURCES/kernel-ppc64le-debug-fedora.config2
-rw-r--r--SOURCES/kernel-ppc64le-debug-rhel.config2
-rw-r--r--SOURCES/kernel-ppc64le-fedora.config2
-rw-r--r--SOURCES/kernel-ppc64le-rhel.config2
-rw-r--r--SOURCES/kernel-s390x-debug-fedora.config2
-rw-r--r--SOURCES/kernel-s390x-debug-rhel.config2
-rw-r--r--SOURCES/kernel-s390x-fedora.config2
-rw-r--r--SOURCES/kernel-s390x-rhel.config2
-rw-r--r--SOURCES/kernel-s390x-zfcpdump-rhel.config2
-rw-r--r--SOURCES/kernel-x86_64-debug-fedora.config2
-rw-r--r--SOURCES/kernel-x86_64-debug-rhel.config2
-rw-r--r--SOURCES/kernel-x86_64-fedora.config2
-rw-r--r--SOURCES/kernel-x86_64-rhel.config2
-rw-r--r--SOURCES/kernel-x86_64-rt-debug-rhel.config2
-rw-r--r--SOURCES/kernel-x86_64-rt-rhel.config2
-rw-r--r--SOURCES/kernel.changelog14
-rw-r--r--SOURCES/linux-surface.patch223
-rw-r--r--SOURCES/patch-6.10-redhat.patch191
-rw-r--r--SOURCES/t2linux.patch4
-rw-r--r--SOURCES/v14.8-0004-HID-asus-add-ROG-Ally-xpad-settings.patch2320
35 files changed, 3900 insertions, 3741 deletions
diff --git a/SOURCES/0001-add-ally-x-dmi-quirk-for-controller-suspend.patch b/SOURCES/0001-add-ally-x-dmi-quirk-for-controller-suspend.patch
deleted file mode 100644
index bffa8c5..0000000
--- a/SOURCES/0001-add-ally-x-dmi-quirk-for-controller-suspend.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 79d958eccfa4a1cfbb552032e9542f03333005e7 Mon Sep 17 00:00:00 2001
-From: antheas <antheas@users.noreply.github.com>
-Date: Mon, 15 Jul 2024 00:00:45 +0300
-Subject: [PATCH] add ally x dmi quirk for controller suspend
-
----
- drivers/platform/x86/asus-wmi.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
-index 3f9b6285c9a6..8e362726b703 100644
---- a/drivers/platform/x86/asus-wmi.c
-+++ b/drivers/platform/x86/asus-wmi.c
-@@ -4645,8 +4645,10 @@ static int asus_wmi_add(struct platform_device *pdev)
- asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU);
- asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU);
- asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE);
-- asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE)
-- && dmi_match(DMI_BOARD_NAME, "RC71L");
-+ asus->ally_mcu_usb_switch =
-+ acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) &&
-+ (dmi_match(DMI_BOARD_NAME, "RC71L") ||
-+ dmi_match(DMI_BOARD_NAME, "RC72LA"));
-
- if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE))
- asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;
---
-2.45.2
diff --git a/SOURCES/0001-patch_realtek-Fix-ROG-ALLY-X-audio.patch b/SOURCES/0001-patch_realtek-Fix-ROG-ALLY-X-audio.patch
deleted file mode 100644
index bcb222a..0000000
--- a/SOURCES/0001-patch_realtek-Fix-ROG-ALLY-X-audio.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From ac9fa29b679959fc58c9180942a74e6687a63584 Mon Sep 17 00:00:00 2001
-From: Jonathan LoBue <jlobue10@gmail.com>
-Date: Thu, 25 Jul 2024 08:22:38 -0700
-Subject: [PATCH] ALSA: hda/realtek: tas2781: Fix ROG ALLY X audio
-
-Fix the loading of the proper TI TAS2781 amplifier
-for the ROG ALLY X, while keeping the other Realtek
-codec and pin portions from original ROG ALLY.
-
-Add proper credit and tag lines before submitting...
-This patch is for sharing and testing (6.10.1)
----
- sound/pci/hda/patch_realtek.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
-index 766f0b1..8d118df 100644
---- a/sound/pci/hda/patch_realtek.c
-+++ b/sound/pci/hda/patch_realtek.c
-@@ -7409,6 +7409,7 @@ enum {
- ALC285_FIXUP_THINKPAD_X1_GEN7,
- ALC285_FIXUP_THINKPAD_HEADSET_JACK,
- ALC294_FIXUP_ASUS_ALLY,
-+ ALC294_FIXUP_ASUS_ALLY_X,
- ALC294_FIXUP_ASUS_ALLY_PINS,
- ALC294_FIXUP_ASUS_ALLY_VERBS,
- ALC294_FIXUP_ASUS_ALLY_SPEAKER,
-@@ -8875,6 +8876,12 @@ static const struct hda_fixup alc269_fixups[] = {
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_ALLY_PINS
- },
-+ [ALC294_FIXUP_ASUS_ALLY_X] = {
-+ .type = HDA_FIXUP_FUNC,
-+ .v.func = tas2781_fixup_i2c,
-+ .chained = true,
-+ .chain_id = ALC294_FIXUP_ASUS_ALLY_PINS
-+ },
- [ALC294_FIXUP_ASUS_ALLY_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
-@@ -10306,6 +10313,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
- SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
- SND_PCI_QUIRK(0x1043, 0x17f3, "ROG Ally NR2301L/X", ALC294_FIXUP_ASUS_ALLY),
-+ SND_PCI_QUIRK(0x1043, 0x1eb3, "ROG Ally X RC72LA", ALC294_FIXUP_ASUS_ALLY_X),
- SND_PCI_QUIRK(0x1043, 0x1863, "ASUS UX6404VI/VV", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
- SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
---
-2.45.2
diff --git a/SOURCES/Patchlist.changelog b/SOURCES/Patchlist.changelog
index b93cf59..f1b9625 100644
--- a/SOURCES/Patchlist.changelog
+++ b/SOURCES/Patchlist.changelog
@@ -1,3 +1,27 @@
+https://gitlab.com/cki-project/kernel-ark/-/commit/378f837843ce9ccefbf401f707cda2c10c03b258
+ 378f837843ce9ccefbf401f707cda2c10c03b258 Revert the F39 commits which should not have pushed
+
+https://gitlab.com/cki-project/kernel-ark/-/commit/617f0465246a2629c0ce735529f0addaacba0604
+ 617f0465246a2629c0ce735529f0addaacba0604 KVM: PPC: Book3S HV nestedv2: Keep nested guest HASHPKEYR in sync
+
+https://gitlab.com/cki-project/kernel-ark/-/commit/713ce2b8136985b1a7ff2ec6dc3c75ebbf4e3ddd
+ 713ce2b8136985b1a7ff2ec6dc3c75ebbf4e3ddd KVM: PPC: Book3S HV: Add one-reg interface for HASHPKEYR register
+
+https://gitlab.com/cki-project/kernel-ark/-/commit/3a7a0b70797b9e19312547345f0fd84595458302
+ 3a7a0b70797b9e19312547345f0fd84595458302 KVM: PPC: Book3S HV nestedv2: Keep nested guest HASHKEYR in sync
+
+https://gitlab.com/cki-project/kernel-ark/-/commit/aab7db47edcfacd592b7483fa0371bf8d23e8b6f
+ aab7db47edcfacd592b7483fa0371bf8d23e8b6f KVM: PPC: Book3S HV: Add one-reg interface for HASHKEYR register
+
+https://gitlab.com/cki-project/kernel-ark/-/commit/1d5f5405eb8b0023aefe21d56558d742e2b558ea
+ 1d5f5405eb8b0023aefe21d56558d742e2b558ea KVM: PPC: Book3S HV nestedv2: Keep nested guest DEXCR in sync
+
+https://gitlab.com/cki-project/kernel-ark/-/commit/3eec751027838fde380aee0676b2bb9806a01a75
+ 3eec751027838fde380aee0676b2bb9806a01a75 KVM: PPC: Book3S HV: Add one-reg interface for DEXCR register
+
+https://gitlab.com/cki-project/kernel-ark/-/commit/c3be1c8ba3dc3a70fb65546e836193ce584de02b
+ c3be1c8ba3dc3a70fb65546e836193ce584de02b Revert "cpupower: Bump soname version"
+
https://gitlab.com/cki-project/kernel-ark/-/commit/d42657488c703c24d1fffaecced0b3b82d30b393
d42657488c703c24d1fffaecced0b3b82d30b393 selinux: revert our use of vma_is_initial_heap()
diff --git a/SOURCES/asus-linux.patch b/SOURCES/asus-linux.patch
index d7817b7..e22d980 100644
--- a/SOURCES/asus-linux.patch
+++ b/SOURCES/asus-linux.patch
@@ -1,104 +1,2928 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: "Luke D. Jones" <luke@ljones.dev>
-Date: Sun, 10 Mar 2024 15:14:37 +1300
-Subject: [PATCH] asus-linux
+From: Jan200101 <sentrycraft123@gmail.com>
+Date: Sun, 8 Sep 2024 01:49:57 +0200
+Subject: [PATCH] asus-linux 6.10.6
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
---
- .../ABI/testing/sysfs-platform-asus-wmi | 23 +-
- drivers/hid/hid-asus.c | 7 +
- drivers/hid/hid-ids.h | 1 +
- drivers/platform/x86/Kconfig | 14 +
- drivers/platform/x86/Makefile | 1 +
- drivers/platform/x86/asus-bios.c | 983 ++++++++++++++++++
- drivers/platform/x86/asus-bios.h | 288 +++++
- drivers/platform/x86/asus-wmi.c | 754 +++++++-------
- include/linux/platform_data/x86/asus-wmi.h | 65 ++
- 9 files changed, 1735 insertions(+), 401 deletions(-)
- create mode 100644 drivers/platform/x86/asus-bios.c
- create mode 100644 drivers/platform/x86/asus-bios.h
+ drivers/hid/Kconfig | 9 +
+ drivers/hid/Makefile | 1 +
+ drivers/hid/hid-asus-ally.c | 2284 +++++++++++++++++++
+ drivers/hid/hid-asus-ally.h | 544 +++++
+ drivers/hid/hid-asus.c | 29 +
+ drivers/hid/hid-ids.h | 3 +
+ drivers/platform/x86/Kconfig | 14 +
+ drivers/platform/x86/Makefile | 1 +
+ drivers/platform/x86/amd/pmf/pmf-quirks.c | 9 +-
+ drivers/platform/x86/asus-armoury.c | 1049 +++++++++
+ drivers/platform/x86/asus-armoury.h | 259 +++
+ drivers/platform/x86/asus-wmi.c | 254 ++-
+ drivers/platform/x86/intel/int3472/Makefile | 9 +-
+ drivers/platform/x86/intel/int3472/common.c | 7 +
+ include/linux/platform_data/x86/asus-wmi.h | 56 +
+ sound/pci/hda/patch_realtek.c | 8 +
+ 16 files changed, 4466 insertions(+), 70 deletions(-)
+ create mode 100644 drivers/hid/hid-asus-ally.c
+ create mode 100644 drivers/hid/hid-asus-ally.h
+ create mode 100644 drivers/platform/x86/asus-armoury.c
+ create mode 100644 drivers/platform/x86/asus-armoury.h
-diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi
-index 28144371a0f1..984a04f32fd0 100644
---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi
-+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi
-@@ -142,8 +142,8 @@ Contact: "Luke Jones" <luke@ljones.dev>
- Description:
- Set the Package Power Target total of CPU: PL1 on Intel, SPL on AMD.
- Shown on Intel+Nvidia or AMD+Nvidia based systems:
--
-- * min=5, max=250
-+ * min/max varies, read *_min/*_max sysfs entries
-+ * -1 resets to default
-
- What: /sys/devices/platform/<platform>/ppt_pl2_sppt
- Date: Jun 2023
-@@ -152,8 +152,8 @@ Contact: "Luke Jones" <luke@ljones.dev>
- Description:
- Set the Slow Package Power Tracking Limit of CPU: PL2 on Intel, SPPT,
- on AMD. Shown on Intel+Nvidia or AMD+Nvidia based systems:
--
-- * min=5, max=250
-+ * min/max varies, read *_min/*_max sysfs entries
-+ * -1 resets to default
-
- What: /sys/devices/platform/<platform>/ppt_fppt
- Date: Jun 2023
-@@ -161,7 +161,8 @@ KernelVersion: 6.5
- Contact: "Luke Jones" <luke@ljones.dev>
- Description:
- Set the Fast Package Power Tracking Limit of CPU. AMD+Nvidia only:
-- * min=5, max=250
-+ * min/max varies, read *_min/*_max sysfs entries
-+ * -1 resets to default
-
- What: /sys/devices/platform/<platform>/ppt_apu_sppt
- Date: Jun 2023
-@@ -169,7 +170,8 @@ KernelVersion: 6.5
- Contact: "Luke Jones" <luke@ljones.dev>
- Description:
- Set the APU SPPT limit. Shown on full AMD systems only:
-- * min=5, max=130
-+ * min/max varies, read *_min/*_max sysfs entries
-+ * -1 resets to default
-
- What: /sys/devices/platform/<platform>/ppt_platform_sppt
- Date: Jun 2023
-@@ -177,7 +179,8 @@ KernelVersion: 6.5
- Contact: "Luke Jones" <luke@ljones.dev>
- Description:
- Set the platform SPPT limit. Shown on full AMD systems only:
-- * min=5, max=130
-+ * min/max varies, read *_min/*_max sysfs entries
-+ * -1 resets to default
-
- What: /sys/devices/platform/<platform>/nv_dynamic_boost
- Date: Jun 2023
-@@ -185,7 +188,8 @@ KernelVersion: 6.5
- Contact: "Luke Jones" <luke@ljones.dev>
- Description:
- Set the dynamic boost limit of the Nvidia dGPU:
-- * min=5, max=25
-+ * min/max varies, read *_min/*_max sysfs entries
-+ * -1 resets to default
-
- What: /sys/devices/platform/<platform>/nv_temp_target
- Date: Jun 2023
-@@ -193,7 +197,8 @@ KernelVersion: 6.5
- Contact: "Luke Jones" <luke@ljones.dev>
- Description:
- Set the target temperature limit of the Nvidia dGPU:
-- * min=75, max=87
-+ * min/max varies, read *_min/*_max sysfs entries
-+ * -1 resets to default
-
- What: /sys/devices/platform/<platform>/boot_sound
- Date: Apr 2024
+diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
+index 08446c89eff6..ea0dbe9111c4 100644
+--- a/drivers/hid/Kconfig
++++ b/drivers/hid/Kconfig
+@@ -164,6 +164,15 @@ config HID_ASUS
+ - GL553V series
+ - GL753V series
+
++config HID_ASUS_ALLY
++ tristate "Asus Ally gamepad configuration support"
++ depends on USB_HID
++ depends on LEDS_CLASS
++ depends on LEDS_CLASS_MULTICOLOR
++ select POWER_SUPPLY
++ help
++ Support for configuring the Asus ROG Ally gamepad using attributes.
++
+ config HID_AUREAL
+ tristate "Aureal"
+ help
+diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
+index ce71b53ea6c5..98b346d8f783 100644
+--- a/drivers/hid/Makefile
++++ b/drivers/hid/Makefile
+@@ -31,6 +31,7 @@ obj-$(CONFIG_HID_APPLE) += hid-apple.o
+ obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o
+ obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
+ obj-$(CONFIG_HID_ASUS) += hid-asus.o
++obj-$(CONFIG_HID_ASUS_ALLY) += hid-asus-ally.o
+ obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
+ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
+ obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o
+diff --git a/drivers/hid/hid-asus-ally.c b/drivers/hid/hid-asus-ally.c
+new file mode 100644
+index 000000000000..fd3d23b2c284
+--- /dev/null
++++ b/drivers/hid/hid-asus-ally.c
+@@ -0,0 +1,2284 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * HID driver for Asus ROG laptops and Ally
++ *
++ * Copyright (c) 2023 Luke Jones <luke@ljones.dev>
++ */
++
++#include "linux/delay.h"
++#include "linux/device.h"
++#include "linux/err.h"
++#include "linux/input-event-codes.h"
++#include "linux/kstrtox.h"
++#include "linux/printk.h"
++#include "linux/slab.h"
++#include "linux/stddef.h"
++#include "linux/sysfs.h"
++#include <linux/hid.h>
++#include <linux/types.h>
++#include <linux/usb.h>
++#include <linux/leds.h>
++#include <linux/led-class-multicolor.h>
++
++#include "hid-ids.h"
++#include "hid-asus-ally.h"
++
++#define READY_MAX_TRIES 3
++#define FEATURE_REPORT_ID 0x0d
++#define FEATURE_ROG_ALLY_REPORT_ID 0x5a
++#define FEATURE_ROG_ALLY_CODE_PAGE 0xD1
++#define FEATURE_ROG_ALLY_REPORT_SIZE 64
++#define ALLY_X_INPUT_REPORT_USB 0x0B
++#define ALLY_X_INPUT_REPORT_USB_SIZE 16
++
++#define ALLY_CFG_INTF_IN_ADDRESS 0x83
++#define ALLY_CFG_INTF_OUT_ADDRESS 0x04
++#define ALLY_X_INTERFACE_ADDRESS 0x87
++
++#define FEATURE_KBD_LED_REPORT_ID1 0x5d
++#define FEATURE_KBD_LED_REPORT_ID2 0x5e
++
++enum ROG_ALLY_TYPE {
++ ROG_ALLY_TYPE,
++ ROG_ALLY_TYPE_X,
++};
++
++static const struct hid_device_id rog_ally_devices[] = {
++ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY),
++ .driver_data = ROG_ALLY_TYPE },
++ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X),
++ .driver_data = ROG_ALLY_TYPE_X },
++ {}
++};
++
++struct KeyCode {
++ const char *label;
++ u8 code;
++};
++
++static const struct KeyCode gamepad_codes[] = {
++ { "PAD_A", 0x01 }, { "PAD_B", 0x02 }, { "PAD_X", 0x03 },
++ { "PAD_Y", 0x04 }, { "PAD_LB", 0x05 }, { "PAD_RB", 0x06 },
++ { "PAD_LS", 0x07 }, { "PAD_RS", 0x08 }, { "PAD_DPAD_UP", 0x09 },
++ { "PAD_DPAD_DOWN", 0x0a }, { "PAD_DPAD_LEFT", 0x0b }, { "PAD_DPAD_RIGHT", 0x0c },
++ { "PAD_VIEW", 0x11 }, { "PAD_MENU", 0x12 }, { "PAD_XBOX", 0x13 }
++};
++
++static const struct KeyCode keyboard_codes[] = { { "KB_M1", 0x8f },
++ { "KB_M2", 0x8e },
++ { "KB_ESC", 0x76 },
++ { "KB_F1", 0x50 },
++ { "KB_F2", 0x60 },
++ { "KB_F3", 0x40 },
++ { "KB_F4", 0x0c },
++ { "KB_F5", 0x03 },
++ { "KB_F6", 0x0b },
++ { "KB_F7", 0x80 },
++ { "KB_F8", 0x0a },
++ { "KB_F9", 0x01 },
++ { "KB_F10", 0x09 },
++ { "KB_F11", 0x78 },
++ { "KB_F12", 0x07 },
++ { "KB_F14", 0x10 },
++ { "KB_F15", 0x18 },
++ { "KB_BACKTICK", 0x0e },
++ { "KB_1", 0x16 },
++ { "KB_2", 0x1e },
++ { "KB_3", 0x26 },
++ { "KB_4", 0x25 },
++ { "KB_5", 0x2e },
++ { "KB_6", 0x36 },
++ { "KB_7", 0x3d },
++ { "KB_8", 0x3e },
++ { "KB_9", 0x46 },
++ { "KB_0", 0x45 },
++ { "KB_HYPHEN", 0x4e },
++ { "KB_EQUALS", 0x55 },
++ { "KB_BACKSPACE", 0x66 },
++ { "KB_TAB", 0x0d },
++ { "KB_Q", 0x15 },
++ { "KB_W", 0x1d },
++ { "KB_E", 0x24 },
++ { "KB_R", 0x2d },
++ { "KB_T", 0x2d },
++ { "KB_Y", 0x35 },
++ { "KB_U", 0x3c },
++ { "KB_I", 0x43 },
++ { "KB_O", 0x44 },
++ { "KB_P", 0x4d },
++ { "KB_LBRACKET", 0x54 },
++ { "KB_RBRACKET", 0x5b },
++ { "KB_BACKSLASH", 0x5d },
++ { "KB_CAPS", 0x58 },
++ { "KB_A", 0x1c },
++ { "KB_S", 0x1b },
++ { "KB_D", 0x23 },
++ { "KB_F", 0x2b },
++ { "KB_G", 0x34 },
++ { "KB_H", 0x33 },
++ { "KB_J", 0x3b },
++ { "KB_K", 0x42 },
++ { "KB_L", 0x4b },
++ { "KB_SEMI", 0x4c },
++ { "KB_QUOTE", 0x52 },
++ { "KB_RET", 0x5a },
++ { "KB_LSHIFT", 0x88 },
++ { "KB_Z", 0x1a },
++ { "KB_X", 0x22 },
++ { "KB_C", 0x21 },
++ { "KB_V", 0x2a },
++ { "KB_B", 0x32 },
++ { "KB_N", 0x31 },
++ { "KB_M", 0x3a },
++ { "KB_COMMA", 0x41 },
++ { "KB_PERIOD", 0x49 },
++ { "KB_FWDSLASH", 0x4a },
++ { "KB_RSHIFT", 0x89 },
++ { "KB_LCTL", 0x8c },
++ { "KB_META", 0x82 },
++ { "KB_LALT", 0xba },
++ { "KB_SPACE", 0x29 },
++ { "KB_RALT", 0x8b },
++ { "KB_MENU", 0x84 },
++ { "KB_RCTL", 0x8d },
++ { "KB_PRNTSCN", 0xc3 },
++ { "KB_SCRLCK", 0x7e },
++ { "KB_PAUSE", 0x91 },
++ { "KB_INS", 0xc2 },
++ { "KB_HOME", 0x94 },
++ { "KB_PGUP", 0x96 },
++ { "KB_DEL", 0xc0 },
++ { "KB_END", 0x95 },
++ { "KB_PGDWN", 0x97 },
++ { "KB_UP_ARROW", 0x99 },
++ { "KB_DOWN_ARROW", 0x98 },
++ { "KB_LEFT_ARROW", 0x91 },
++ { "KB_RIGHT_ARROW", 0x9b },
++ { "NUMPAD_LOCK", 0x77 },
++ { "NUMPAD_FWDSLASH", 0x90 },
++ { "NUMPAD_ASTERISK", 0x7c },
++ { "NUMPAD_HYPHEN", 0x7b },
++ { "NUMPAD_0", 0x70 },
++ { "NUMPAD_1", 0x69 },
++ { "NUMPAD_2", 0x72 },
++ { "NUMPAD_3", 0x7a },
++ { "NUMPAD_4", 0x6b },
++ { "NUMPAD_5", 0x73 },
++ { "NUMPAD_6", 0x74 },
++ { "NUMPAD_7", 0x6c },
++ { "NUMPAD_8", 0x75 },
++ { "NUMPAD_9", 0x7d },
++ { "NUMPAD_PLUS", 0x79 },
++ { "NUMPAD_ENTER", 0x81 },
++ { "NUMPAD_PERIOD", 0x71 } };
++
++static const struct KeyCode mouse_codes[] = { { "MOUSE_LCLICK", 0x01 },
++ { "MOUSE_RCLICK", 0x02 },
++ { "MOUSE_MCLICK", 0x03 },
++ { "MOUSE_WHEEL_UP", 0x04 },
++ { "MOUSE_WHEEL_DOWN", 0x05 } };
++
++static const struct KeyCode media_codes[] = {
++ { "MEDIA_SCREENSHOT", 0x16 }, { "MEDIA_SHOW_KEYBOARD", 0x19 },
++ { "MEDIA_SHOW_DESKTOP", 0x1c }, { "MEDIA_START_RECORDING", 0x1e },
++ { "MEDIA_MIC_OFF", 0x01 }, { "MEDIA_VOL_DOWN", 0x02 },
++ { "MEDIA_VOL_UP", 0x03 }
++};
++
++/* The hatswitch outputs integers, we use them to index this X|Y pair */
++static const int hat_values[][2] = {
++ { 0, 0 }, { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 },
++ { 0, 1 }, { -1, 1 }, { -1, 0 }, { -1, -1 },
++};
++
++/* rumble packet structure */
++struct ff_data {
++ u8 enable;
++ u8 magnitude_left;
++ u8 magnitude_right;
++ u8 magnitude_strong;
++ u8 magnitude_weak;
++ u8 pulse_sustain_10ms;
++ u8 pulse_release_10ms;
++ u8 loop_count;
++} __packed;
++
++struct ff_report {
++ u8 report_id;
++ struct ff_data ff;
++} __packed;
++
++struct ally_x_input_report {
++ uint16_t x, y;
++ uint16_t rx, ry;
++ uint16_t z, rz;
++ uint8_t buttons[4];
++} __packed;
++
++struct ally_x_device {
++ struct input_dev *input;
++ struct hid_device *hdev;
++ spinlock_t lock;
++
++ struct ff_report *ff_packet;
++ struct work_struct output_worker;
++ bool output_worker_initialized;
++ /* Prevent multiple queued event due to the enforced delay in worker */
++ bool update_qam_btn;
++ /* Set if the QAM and AC buttons emit Xbox and Xbox+A */
++ bool qam_btns_steam_mode;
++ bool update_ff;
++};
++
++struct ally_rgb_leds {
++ struct hid_device *hdev;
++ /* Need two dev here to enable the 3 step brightness */
++ struct led_classdev led_bright_dev;
++ struct led_classdev_mc led_rgb_dev;
++ struct work_struct work;
++ spinlock_t lock;
++
++ bool removed;
++
++ /* Update the main brightness 0-2 using a single raw write */
++ bool update_bright;
++ unsigned int brightness;
++
++ /* Update the RGB only to keep write efficient */
++ bool update_rgb;
++ uint8_t gamepad_red;
++ uint8_t gamepad_green;
++ uint8_t gamepad_blue;
++};
++
++/* ROG Ally has many settings related to the gamepad, all using the same n-key endpoint */
++struct ally_gamepad_cfg {
++ struct hid_device *hdev;
++ struct input_dev *input;
++
++ enum xpad_mode mode;
++ /*
++ * index: [joysticks/triggers][left(2 bytes), right(2 bytes)]
++ * joysticks: 2 bytes: inner, outer
++ * triggers: 2 bytes: lower, upper
++ * min/max: 0-64
++ */
++ u8 deadzones[xpad_mode_mouse][2][4];
++ /*
++ * index: left, right
++ * max: 64
++ */
++ u8 vibration_intensity[xpad_mode_mouse][2];
++ /*
++ * index: [joysticks][2 byte stepping per point]
++ * - 4 points of 2 bytes each
++ * - byte 0 of pair = stick move %
++ * - byte 1 of pair = stick response %
++ * - min/max: 1-63
++ */
++ bool supports_response_curves;
++ u8 response_curve[xpad_mode_mouse][2][8];
++ /*
++ * left = byte 0, right = byte 1
++ */
++ bool supports_anti_deadzones;
++ u8 anti_deadzones[xpad_mode_mouse][2];
++ /*
++ * index: [mode][phys pair][b1, b1 secondary, b2, b2 secondary, blocks of 11]
++ */
++ u8 key_mapping[xpad_mode_mouse][btn_pair_lt_rt][MAPPING_BLOCK_LEN];
++ /*
++ * index: [mode][button index]
++ */
++ u8 turbo_btns[xpad_mode_mouse][TURBO_BLOCK_LEN];
++ /*
++ * index: [joystick side][Y-stable, Y-min, Y-max, X-stable, X-min, X-max]
++ */
++ u32 js_calibrations[2][6];
++ /*
++ * index: [trigger side][stable, max]
++ */
++ u32 tr_calibrations[2][2];
++};
++
++static struct ally_drvdata {
++ struct hid_device *hdev;
++ struct ally_x_device *ally_x;
++ struct ally_gamepad_cfg *gamepad_cfg;
++ struct ally_rgb_leds *led_rgb;
++} drvdata;
++
++static int asus_dev_get_report(struct hid_device *hdev, u8 *out_buf, size_t out_buf_size)
++{
++ return hid_hw_raw_request(hdev, FEATURE_REPORT_ID, out_buf, out_buf_size,
++ HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
++}
++
++static int asus_dev_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size)
++{
++ unsigned char *dmabuf;
++ int ret;
++
++ dmabuf = kmemdup(buf, buf_size, GFP_KERNEL);
++ if (!dmabuf)
++ return -ENOMEM;
++
++ ret = hid_hw_raw_request(hdev, buf[0], dmabuf, buf_size, HID_FEATURE_REPORT,
++ HID_REQ_SET_REPORT);
++ kfree(dmabuf);
++
++ return ret;
++}
++
++/**************************************************************************************************/
++/* ROG Ally gamepad i/o and force-feedback */
++/**************************************************************************************************/
++static int ally_x_raw_event(struct ally_x_device *ally_x, struct hid_report *report, u8 *data,
++ int size)
++{
++ struct ally_x_input_report *in_report;
++ unsigned long flags;
++ u8 byte;
++
++ if (data[0] == 0x0B) {
++ in_report = (struct ally_x_input_report *)&data[1];
++
++ input_report_abs(ally_x->input, ABS_X, in_report->x);
++ input_report_abs(ally_x->input, ABS_Y, in_report->y);
++ input_report_abs(ally_x->input, ABS_RX, in_report->rx);
++ input_report_abs(ally_x->input, ABS_RY, in_report->ry);
++ input_report_abs(ally_x->input, ABS_Z, in_report->z);
++ input_report_abs(ally_x->input, ABS_RZ, in_report->rz);
++
++ byte = in_report->buttons[0];
++ input_report_key(ally_x->input, BTN_A, byte & BIT(0));
++ input_report_key(ally_x->input, BTN_B, byte & BIT(1));
++ input_report_key(ally_x->input, BTN_X, byte & BIT(2));
++ input_report_key(ally_x->input, BTN_Y, byte & BIT(3));
++ input_report_key(ally_x->input, BTN_TL, byte & BIT(4));
++ input_report_key(ally_x->input, BTN_TR, byte & BIT(5));
++ input_report_key(ally_x->input, BTN_SELECT, byte & BIT(6));
++ input_report_key(ally_x->input, BTN_START, byte & BIT(7));
++
++ byte = in_report->buttons[1];
++ input_report_key(ally_x->input, BTN_THUMBL, byte & BIT(0));
++ input_report_key(ally_x->input, BTN_THUMBR, byte & BIT(1));
++ input_report_key(ally_x->input, BTN_MODE, byte & BIT(2));
++
++ byte = in_report->buttons[2];
++ input_report_abs(ally_x->input, ABS_HAT0X, hat_values[byte][0]);
++ input_report_abs(ally_x->input, ABS_HAT0Y, hat_values[byte][1]);
++ }
++ /*
++ * The MCU used on Ally provides many devices: gamepad, keyboord, mouse, other.
++ * The AC and QAM buttons route through another interface making it difficult to
++ * use the events unless we grab those and use them here. Only works for Ally X.
++ */
++ else if (data[0] == 0x5A) {
++ if (ally_x->qam_btns_steam_mode) {
++ spin_lock_irqsave(&ally_x->lock, flags);
++ if (data[1] == 0x38 && !ally_x->update_qam_btn) {
++ ally_x->update_qam_btn = true;
++ if (ally_x->output_worker_initialized)
++ schedule_work(&ally_x->output_worker);
++ }
++ spin_unlock_irqrestore(&ally_x->lock, flags);
++ /* Left/XBox button. Long press does ctrl+alt+del which we can't catch */
++ input_report_key(ally_x->input, BTN_MODE, data[1] == 0xA6);
++ } else {
++ input_report_key(ally_x->input, KEY_F16, data[1] == 0xA6);
++ input_report_key(ally_x->input, KEY_PROG1, data[1] == 0x38);
++ }
++ /* QAM long press */
++ input_report_key(ally_x->input, KEY_F17, data[1] == 0xA7);
++ /* QAM long press released */
++ input_report_key(ally_x->input, KEY_F18, data[1] == 0xA8);
++ }
++
++ input_sync(ally_x->input);
++
++ return 0;
++}
++
++static struct input_dev *ally_x_alloc_input_dev(struct hid_device *hdev,
++ const char *name_suffix)
++{
++ struct input_dev *input_dev;
++
++ input_dev = devm_input_allocate_device(&hdev->dev);
++ if (!input_dev)
++ return ERR_PTR(-ENOMEM);
++
++ input_dev->id.bustype = hdev->bus;
++ input_dev->id.vendor = hdev->vendor;
++ input_dev->id.product = hdev->product;
++ input_dev->id.version = hdev->version;
++ input_dev->uniq = hdev->uniq;
++ input_dev->name = "ASUS ROG Ally X Gamepad";
++
++ input_set_drvdata(input_dev, hdev);
++
++ return input_dev;
++}
++
++static int ally_x_play_effect(struct input_dev *idev, void *data, struct ff_effect *effect)
++{
++ struct ally_x_device *ally_x = drvdata.ally_x;
++ unsigned long flags;
++
++ if (effect->type != FF_RUMBLE)
++ return 0;
++
++ spin_lock_irqsave(&ally_x->lock, flags);
++ ally_x->ff_packet->ff.magnitude_strong = effect->u.rumble.strong_magnitude / 512;
++ ally_x->ff_packet->ff.magnitude_weak = effect->u.rumble.weak_magnitude / 512;
++ ally_x->update_ff = true;
++ spin_unlock_irqrestore(&ally_x->lock, flags);
++
++ if (ally_x->output_worker_initialized)
++ schedule_work(&ally_x->output_worker);
++
++ return 0;
++}
++
++static void ally_x_work(struct work_struct *work)
++{
++ struct ally_x_device *ally_x = container_of(work, struct ally_x_device, output_worker);
++ struct ff_report *ff_report = NULL;
++ bool update_qam = false;
++ bool update_ff = false;
++ unsigned long flags;
++
++ spin_lock_irqsave(&ally_x->lock, flags);
++ update_ff = ally_x->update_ff;
++ if (ally_x->update_ff) {
++ ff_report = kmemdup(ally_x->ff_packet, sizeof(*ally_x->ff_packet), GFP_KERNEL);
++ ally_x->update_ff = false;
++ }
++ update_qam = ally_x->update_qam_btn;
++ spin_unlock_irqrestore(&ally_x->lock, flags);
++
++ if (update_ff && ff_report) {
++ ff_report->ff.magnitude_left = ff_report->ff.magnitude_strong;
++ ff_report->ff.magnitude_right = ff_report->ff.magnitude_weak;
++ asus_dev_set_report(ally_x->hdev, (u8 *)ff_report, sizeof(*ff_report));
++ }
++ kfree(ff_report);
++
++ if (update_qam) {
++ /*
++ * The sleeps here are required to allow steam to register the button combo.
++ */
++ usleep_range(1000, 2000);
++ input_report_key(ally_x->input, BTN_MODE, 1);
++ input_sync(ally_x->input);
++
++ msleep(80);
++ input_report_key(ally_x->input, BTN_A, 1);
++ input_sync(ally_x->input);
++
++ msleep(80);
++ input_report_key(ally_x->input, BTN_A, 0);
++ input_sync(ally_x->input);
++
++ msleep(80);
++ input_report_key(ally_x->input, BTN_MODE, 0);
++ input_sync(ally_x->input);
++
++ spin_lock_irqsave(&ally_x->lock, flags);
++ ally_x->update_qam_btn = false;
++ spin_unlock_irqrestore(&ally_x->lock, flags);
++ }
++}
++
++static struct input_dev *ally_x_setup_input(struct hid_device *hdev)
++{
++ int ret, abs_min = 0, js_abs_max = 65535, tr_abs_max = 1023;
++ struct input_dev *input;
++
++ input = ally_x_alloc_input_dev(hdev, NULL);
++ if (IS_ERR(input))
++ return ERR_CAST(input);
++
++ input_set_abs_params(input, ABS_X, abs_min, js_abs_max, 0, 0);
++ input_set_abs_params(input, ABS_Y, abs_min, js_abs_max, 0, 0);
++ input_set_abs_params(input, ABS_RX, abs_min, js_abs_max, 0, 0);
++ input_set_abs_params(input, ABS_RY, abs_min, js_abs_max, 0, 0);
++ input_set_abs_params(input, ABS_Z, abs_min, tr_abs_max, 0, 0);
++ input_set_abs_params(input, ABS_RZ, abs_min, tr_abs_max, 0, 0);
++ input_set_abs_params(input, ABS_HAT0X, -1, 1, 0, 0);
++ input_set_abs_params(input, ABS_HAT0Y, -1, 1, 0, 0);
++ input_set_capability(input, EV_KEY, BTN_A);
++ input_set_capability(input, EV_KEY, BTN_B);
++ input_set_capability(input, EV_KEY, BTN_X);
++ input_set_capability(input, EV_KEY, BTN_Y);
++ input_set_capability(input, EV_KEY, BTN_TL);
++ input_set_capability(input, EV_KEY, BTN_TR);
++ input_set_capability(input, EV_KEY, BTN_SELECT);
++ input_set_capability(input, EV_KEY, BTN_START);
++ input_set_capability(input, EV_KEY, BTN_MODE);
++ input_set_capability(input, EV_KEY, BTN_THUMBL);
++ input_set_capability(input, EV_KEY, BTN_THUMBR);
++
++ input_set_capability(input, EV_KEY, KEY_PROG1);
++ input_set_capability(input, EV_KEY, KEY_F16);
++ input_set_capability(input, EV_KEY, KEY_F17);
++ input_set_capability(input, EV_KEY, KEY_F18);
++
++ input_set_capability(input, EV_FF, FF_RUMBLE);
++ input_ff_create_memless(input, NULL, ally_x_play_effect);
++
++ ret = input_register_device(input);
++ if (ret)
++ return ERR_PTR(ret);
++
++ return input;
++}
++
++static ssize_t ally_x_qam_mode_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ally_x_device *ally_x = drvdata.ally_x;
++
++ return sysfs_emit(buf, "%d\n", ally_x->qam_btns_steam_mode);
++}
++
++static ssize_t ally_x_qam_mode_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct ally_x_device *ally_x = drvdata.ally_x;
++ bool val;
++ int ret;
++
++ ret = kstrtobool(buf, &val);
++ if (ret < 0)
++ return ret;
++
++ ally_x->qam_btns_steam_mode = val;
++
++ return count;
++}
++ALLY_DEVICE_ATTR_RW(ally_x_qam_mode, qam_mode);
++
++static struct ally_x_device *ally_x_create(struct hid_device *hdev)
++{
++ uint8_t max_output_report_size;
++ struct ally_x_device *ally_x;
++ struct ff_report *report;
++ int ret;
++
++ ally_x = devm_kzalloc(&hdev->dev, sizeof(*ally_x), GFP_KERNEL);
++ if (!ally_x)
++ return ERR_PTR(-ENOMEM);
++
++ ally_x->hdev = hdev;
++ INIT_WORK(&ally_x->output_worker, ally_x_work);
++ spin_lock_init(&ally_x->lock);
++ ally_x->output_worker_initialized = true;
++ ally_x->qam_btns_steam_mode =
++ true; /* Always default to steam mode, it can be changed by userspace attr */
++
++ max_output_report_size = sizeof(struct ally_x_input_report);
++ report = devm_kzalloc(&hdev->dev, sizeof(*report), GFP_KERNEL);
++ if (!report) {
++ ret = -ENOMEM;
++ goto free_ally_x;
++ }
++
++ /* None of these bytes will change for the FF command for now */
++ report->report_id = 0x0D;
++ report->ff.enable = 0x0F; /* Enable all by default */
++ report->ff.pulse_sustain_10ms = 0xFF; /* Duration */
++ report->ff.pulse_release_10ms = 0x00; /* Start Delay */
++ report->ff.loop_count = 0xEB; /* Loop Count */
++ ally_x->ff_packet = report;
++
++ ally_x->input = ally_x_setup_input(hdev);
++ if (IS_ERR(ally_x->input)) {
++ ret = PTR_ERR(ally_x->input);
++ goto free_ff_packet;
++ }
++
++ if (sysfs_create_file(&hdev->dev.kobj, &dev_attr_ally_x_qam_mode.attr)) {
++ ret = -ENODEV;
++ goto unregister_input;
++ }
++
++ ally_x->update_ff = true;
++ if (ally_x->output_worker_initialized)
++ schedule_work(&ally_x->output_worker);
++
++ hid_info(hdev, "Registered Ally X controller using %s\n",
++ dev_name(&ally_x->input->dev));
++ return ally_x;
++
++unregister_input:
++ input_unregister_device(ally_x->input);
++free_ff_packet:
++ kfree(ally_x->ff_packet);
++free_ally_x:
++ kfree(ally_x);
++ return ERR_PTR(ret);
++}
++
++static void ally_x_remove(struct hid_device *hdev)
++{
++ struct ally_x_device *ally_x = drvdata.ally_x;
++ unsigned long flags;
++
++ spin_lock_irqsave(&ally_x->lock, flags);
++ ally_x->output_worker_initialized = false;
++ spin_unlock_irqrestore(&ally_x->lock, flags);
++ cancel_work_sync(&ally_x->output_worker);
++ sysfs_remove_file(&hdev->dev.kobj, &dev_attr_ally_x_qam_mode.attr);
++}
++
++/**************************************************************************************************/
++/* ROG Ally configuration */
++/**************************************************************************************************/
++static int __gamepad_write_all_to_mcu(struct hid_device *hdev,
++ struct ally_gamepad_cfg *ally_cfg);
++
++static int process_key_code(const struct KeyCode *codes, int code_count, const char *buf_copy,
++ u8 *out, int out_idx)
++{
++ for (int i = 0; i < code_count; i++) {
++ if (strcmp(buf_copy, codes[i].label) == 0) {
++ out[out_idx] = codes[i].code;
++ return 0; // Found
++ }
++ }
++ return -EINVAL; // Not found
++}
++
++static int __string_to_key_code(const char *buf, u8 *out, int out_len)
++{
++ char buf_copy[32];
++ u8 *save_buf;
++
++ if (out_len != BTN_CODE_LEN)
++ return -EINVAL;
++
++ save_buf = kzalloc(out_len, GFP_KERNEL);
++ if (!save_buf)
++ return -ENOMEM;
++ memcpy(save_buf, out, out_len);
++ memset(out, 0, out_len); /* always clear before adjusting */
++
++ strscpy(buf_copy, buf);
++ buf_copy[strcspn(buf_copy, "\n")] = 0;
++
++ /* Gamepad group */
++ out[0] = 0x01;
++ if (process_key_code(gamepad_codes, ARRAY_SIZE(gamepad_codes), buf_copy, out, 1) == 0)
++ goto success;
++
++ /* Keyboard group */
++ out[0] = 0x02;
++ if (process_key_code(keyboard_codes, ARRAY_SIZE(keyboard_codes), buf_copy, out, 2) == 0)
++ goto success;
++
++ /* Mouse group */
++ out[0] = 0x03;
++ if (process_key_code(mouse_codes, ARRAY_SIZE(mouse_codes), buf_copy, out, 4) == 0)
++ goto success;
++
++ /* Media group */
++ out[0] = 0x05;
++ if (process_key_code(media_codes, ARRAY_SIZE(media_codes), buf_copy, out, 3) == 0)
++ goto success;
++
++ /* Restore bytes if invalid input */
++ memcpy(out, save_buf, out_len);
++ kfree(save_buf);
++ return -EINVAL;
++
++success:
++ kfree(save_buf);
++ return 0;
++}
++
++static const char *key_code_to_string(const struct KeyCode *codes, int code_count, u8 code)
++{
++ for (int i = 0; i < code_count; i++) {
++ if (codes[i].code == code)
++ return codes[i].label;
++ }
++ return "";
++}
++
++static u8 *__get_btn_block(struct ally_gamepad_cfg *ally_cfg, enum btn_pair pair,
++ enum btn_pair_side side, bool secondary)
++{
++ int offs;
++
++ offs = side ? MAPPING_BLOCK_LEN / 2 : 0;
++ offs = secondary ? offs + BTN_CODE_LEN : offs;
++ return ally_cfg->key_mapping[ally_cfg->mode - 1][pair - 1] + offs;
++}
++
++static const char *__btn_map_to_string(struct ally_gamepad_cfg *ally_cfg, enum btn_pair pair,
++ enum btn_pair_side side, bool secondary)
++{
++ u8 *out_arg = __get_btn_block(ally_cfg, pair, side, secondary);
++
++ switch (out_arg[0]) {
++ case 0x01: // Gamepad buttons
++ return key_code_to_string(gamepad_codes, ARRAY_SIZE(gamepad_codes), out_arg[1]);
++ case 0x02: // Keyboard keys
++ return key_code_to_string(keyboard_codes, ARRAY_SIZE(keyboard_codes),
++ out_arg[2]);
++ case 0x03: // Mouse buttons
++ return key_code_to_string(mouse_codes, ARRAY_SIZE(mouse_codes), out_arg[4]);
++ case 0x05: // Media controls
++ return key_code_to_string(media_codes, ARRAY_SIZE(media_codes), out_arg[3]);
++ default:
++ return "";
++ }
++}
++
++/* ASUS ROG Ally device specific attributes */
++
++/* This should be called before any attempts to set device functions */
++static int __gamepad_check_ready(struct hid_device *hdev)
++{
++ int ret, count;
++ u8 *hidbuf;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ ret = 0;
++ for (count = 0; count < READY_MAX_TRIES; count++) {
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_check_ready;
++ hidbuf[3] = 01;
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ hid_warn(hdev, "ROG Ally check failed set report: %d\n", ret);
++
++ hidbuf[0] = hidbuf[1] = hidbuf[2] = hidbuf[3] = 0;
++ ret = asus_dev_get_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ hid_warn(hdev, "ROG Ally check failed get report: %d\n", ret);
++
++ ret = hidbuf[2] == xpad_cmd_check_ready;
++ if (ret)
++ break;
++ usleep_range(
++ 1000,
++ 2000); /* don't spam the entire loop in less than USB response time */
++ }
++
++ if (count == READY_MAX_TRIES)
++ hid_warn(hdev, "ROG Ally never responded with a ready\n");
++
++ kfree(hidbuf);
++ return ret;
++}
++
++/* BUTTON REMAPPING *******************************************************************************/
++static void __btn_pair_to_pkt(struct ally_gamepad_cfg *ally_cfg, enum btn_pair pair, u8 *out,
++ int out_len)
++{
++ out[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ out[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ out[2] = xpad_cmd_set_mapping;
++ out[3] = pair;
++ out[4] = xpad_cmd_len_mapping;
++ memcpy(&out[5], &ally_cfg->key_mapping[ally_cfg->mode - 1][pair - 1],
++ MAPPING_BLOCK_LEN);
++}
++
++/* Store the button setting in driver data. Does not apply to device until __gamepad_set_mapping */
++static int __gamepad_mapping_store(struct ally_gamepad_cfg *ally_cfg, const char *buf,
++ enum btn_pair pair, int side, bool secondary)
++{
++ u8 *out_arg;
++
++ out_arg = __get_btn_block(ally_cfg, pair, side, secondary);
++
++ return __string_to_key_code(buf, out_arg, BTN_CODE_LEN);
++}
++
++/* Apply the mapping pair to the device */
++static int __gamepad_set_mapping(struct hid_device *hdev, struct ally_gamepad_cfg *ally_cfg,
++ enum btn_pair pair)
++{
++ u8 *hidbuf;
++ int ret;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ __btn_pair_to_pkt(ally_cfg, pair, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++
++ kfree(hidbuf);
++
++ return ret;
++}
++
++static ssize_t btn_mapping_apply_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ struct hid_device *hdev = to_hid_device(dev);
++ int ret;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ ret = __gamepad_write_all_to_mcu(hdev, ally_cfg);
++ if (ret < 0)
++ return ret;
++
++ return count;
++}
++ALLY_DEVICE_ATTR_WO(btn_mapping_apply, apply_all);
++
++/* BUTTON TURBO ***********************************************************************************/
++static int __btn_turbo_index(enum btn_pair pair, int side)
++{
++ return (pair - 1) * (2 * TURBO_BLOCK_STEP) + (side * TURBO_BLOCK_STEP);
++};
++
++static int __gamepad_turbo_show(struct device *dev, enum btn_pair pair, int side)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ return ally_cfg->turbo_btns[ally_cfg->mode - 1][__btn_turbo_index(pair, side)];
++};
++
++static int __gamepad_turbo_store(struct device *dev, const char *buf, enum btn_pair pair,
++ int side)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ int ret, val;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ ret = kstrtoint(buf, 0, &val);
++ if (ret)
++ return ret;
++ if (val < 0 || val > 16)
++ return -EINVAL;
++
++ ally_cfg->turbo_btns[ally_cfg->mode - 1][__btn_turbo_index(pair, side)] = val;
++
++ return 0;
++};
++
++/* button map attributes, regular and macro*/
++ALLY_BTN_MAPPING(m2, btn_pair_m1_m2, btn_pair_side_left);
++ALLY_BTN_MAPPING(m1, btn_pair_m1_m2, btn_pair_side_right);
++ALLY_BTN_MAPPING(a, btn_pair_a_b, btn_pair_side_left);
++ALLY_BTN_MAPPING(b, btn_pair_a_b, btn_pair_side_right);
++ALLY_BTN_MAPPING(x, btn_pair_x_y, btn_pair_side_left);
++ALLY_BTN_MAPPING(y, btn_pair_x_y, btn_pair_side_right);
++ALLY_BTN_MAPPING(lb, btn_pair_lb_rb, btn_pair_side_left);
++ALLY_BTN_MAPPING(rb, btn_pair_lb_rb, btn_pair_side_right);
++ALLY_BTN_MAPPING(ls, btn_pair_ls_rs, btn_pair_side_left);
++ALLY_BTN_MAPPING(rs, btn_pair_ls_rs, btn_pair_side_right);
++ALLY_BTN_MAPPING(lt, btn_pair_lt_rt, btn_pair_side_left);
++ALLY_BTN_MAPPING(rt, btn_pair_lt_rt, btn_pair_side_right);
++ALLY_BTN_MAPPING(dpad_u, btn_pair_dpad_u_d, btn_pair_side_left);
++ALLY_BTN_MAPPING(dpad_d, btn_pair_dpad_u_d, btn_pair_side_right);
++ALLY_BTN_MAPPING(dpad_l, btn_pair_dpad_l_r, btn_pair_side_left);
++ALLY_BTN_MAPPING(dpad_r, btn_pair_dpad_l_r, btn_pair_side_right);
++ALLY_BTN_MAPPING(view, btn_pair_view_menu, btn_pair_side_left);
++ALLY_BTN_MAPPING(menu, btn_pair_view_menu, btn_pair_side_right);
++
++static void __gamepad_mapping_xpad_default(struct ally_gamepad_cfg *ally_cfg)
++{
++ memcpy(&ally_cfg->key_mapping[0][0], &XPAD_DEF1, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[0][1], &XPAD_DEF2, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[0][2], &XPAD_DEF3, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[0][3], &XPAD_DEF4, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[0][4], &XPAD_DEF5, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[0][5], &XPAD_DEF6, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[0][6], &XPAD_DEF7, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[0][7], &XPAD_DEF8, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[0][8], &XPAD_DEF9, MAPPING_BLOCK_LEN);
++}
++
++static void __gamepad_mapping_wasd_default(struct ally_gamepad_cfg *ally_cfg)
++{
++ memcpy(&ally_cfg->key_mapping[1][0], &WASD_DEF1, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[1][1], &WASD_DEF2, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[1][2], &WASD_DEF3, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[1][3], &WASD_DEF4, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[1][4], &WASD_DEF5, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[1][5], &WASD_DEF6, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[1][6], &WASD_DEF7, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[1][7], &WASD_DEF8, MAPPING_BLOCK_LEN);
++ memcpy(&ally_cfg->key_mapping[1][8], &WASD_DEF9, MAPPING_BLOCK_LEN);
++}
++
++static ssize_t btn_mapping_reset_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ switch (ally_cfg->mode) {
++ case xpad_mode_game:
++ __gamepad_mapping_xpad_default(ally_cfg);
++ break;
++ case xpad_mode_wasd:
++ __gamepad_mapping_wasd_default(ally_cfg);
++ break;
++ default:
++ __gamepad_mapping_xpad_default(ally_cfg);
++ break;
++ }
++
++ return count;
++}
++
++ALLY_DEVICE_ATTR_WO(btn_mapping_reset, reset_btn_mapping);
++
++/* GAMEPAD MODE ***********************************************************************************/
++static ssize_t __gamepad_set_mode(struct hid_device *hdev, struct ally_gamepad_cfg *ally_cfg,
++ int val)
++{
++ u8 *hidbuf;
++ int ret;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_mode;
++ hidbuf[3] = xpad_cmd_len_mode;
++ hidbuf[4] = val;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ goto report_fail;
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ goto report_fail;
++
++ ret = __gamepad_write_all_to_mcu(hdev, ally_cfg);
++ if (ret < 0)
++ goto report_fail;
++
++report_fail:
++ kfree(hidbuf);
++ return ret;
++}
++
++static ssize_t gamepad_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ return sysfs_emit(buf, "%d\n", ally_cfg->mode);
++}
++
++static ssize_t gamepad_mode_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct hid_device *hdev = to_hid_device(dev);
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ int ret, val;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ ret = kstrtoint(buf, 0, &val);
++ if (ret)
++ return ret;
++
++ if (val < xpad_mode_game || val > xpad_mode_mouse)
++ return -EINVAL;
++
++ ally_cfg->mode = val;
++
++ ret = __gamepad_set_mode(hdev, ally_cfg, val);
++ if (ret < 0)
++ return ret;
++
++ return count;
++}
++
++DEVICE_ATTR_RW(gamepad_mode);
++
++/* VIBRATION INTENSITY ****************************************************************************/
++static ssize_t gamepad_vibration_intensity_index_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return sysfs_emit(buf, "left right\n");
++}
++
++ALLY_DEVICE_ATTR_RO(gamepad_vibration_intensity_index, vibration_intensity_index);
++
++static ssize_t __gamepad_write_vibe_intensity_to_mcu(struct hid_device *hdev,
++ struct ally_gamepad_cfg *ally_cfg)
++{
++ u8 *hidbuf;
++ int ret;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_vibe_intensity;
++ hidbuf[3] = xpad_cmd_len_vibe_intensity;
++ hidbuf[4] = ally_cfg->vibration_intensity[ally_cfg->mode - 1][btn_pair_side_left];
++ hidbuf[5] = ally_cfg->vibration_intensity[ally_cfg->mode - 1][btn_pair_side_right];
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ goto report_fail;
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ goto report_fail;
++
++report_fail:
++ kfree(hidbuf);
++ return ret;
++}
++
++static ssize_t gamepad_vibration_intensity_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ return sysfs_emit(
++ buf, "%d %d\n",
++ ally_cfg->vibration_intensity[ally_cfg->mode - 1][btn_pair_side_left],
++ ally_cfg->vibration_intensity[ally_cfg->mode - 1][btn_pair_side_right]);
++}
++
++static ssize_t gamepad_vibration_intensity_store(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
++{
++ struct hid_device *hdev = to_hid_device(dev);
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ u32 left, right;
++ int ret;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ if (sscanf(buf, "%d %d", &left, &right) != 2)
++ return -EINVAL;
++
++ if (left > 64 || right > 64)
++ return -EINVAL;
++
++ ally_cfg->vibration_intensity[ally_cfg->mode - 1][btn_pair_side_left] = left;
++ ally_cfg->vibration_intensity[ally_cfg->mode - 1][btn_pair_side_right] = right;
++
++ ret = __gamepad_write_vibe_intensity_to_mcu(hdev, ally_cfg);
++ if (ret < 0)
++ return ret;
++
++ return count;
++}
++
++ALLY_DEVICE_ATTR_RW(gamepad_vibration_intensity, vibration_intensity);
++
++/* ROOT LEVEL ATTRS *******************************************************************************/
++static struct attribute *gamepad_device_attrs[] = {
++ &dev_attr_gamepad_mode.attr,
++ &dev_attr_btn_mapping_reset.attr,
++ &dev_attr_btn_mapping_apply.attr,
++ &dev_attr_gamepad_vibration_intensity.attr,
++ &dev_attr_gamepad_vibration_intensity_index.attr,
++ NULL
++};
++
++static const struct attribute_group ally_controller_attr_group = {
++ .attrs = gamepad_device_attrs,
++};
++
++/* ANALOGUE DEADZONES *****************************************************************************/
++static ssize_t __gamepad_set_deadzones(struct hid_device *hdev,
++ struct ally_gamepad_cfg *ally_cfg)
++{
++ u8 *hidbuf;
++ int ret;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_js_dz;
++ hidbuf[3] = xpad_cmd_len_deadzone;
++ hidbuf[4] = ally_cfg->deadzones[ally_cfg->mode - 1][0][0];
++ hidbuf[5] = ally_cfg->deadzones[ally_cfg->mode - 1][0][1];
++ hidbuf[6] = ally_cfg->deadzones[ally_cfg->mode - 1][0][2];
++ hidbuf[7] = ally_cfg->deadzones[ally_cfg->mode - 1][0][3];
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ goto end;
++
++ hidbuf[2] = xpad_cmd_set_tr_dz;
++ hidbuf[4] = ally_cfg->deadzones[ally_cfg->mode - 1][1][0];
++ hidbuf[5] = ally_cfg->deadzones[ally_cfg->mode - 1][1][1];
++ hidbuf[6] = ally_cfg->deadzones[ally_cfg->mode - 1][1][2];
++ hidbuf[7] = ally_cfg->deadzones[ally_cfg->mode - 1][1][3];
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ goto end;
++
++end:
++ kfree(hidbuf);
++ return ret;
++}
++
++static ssize_t __gamepad_store_deadzones(struct ally_gamepad_cfg *ally_cfg, enum xpad_axis axis,
++ const char *buf)
++{
++ int cmd, side, is_tr;
++ u32 inner, outer;
++
++ if (sscanf(buf, "%d %d", &inner, &outer) != 2)
++ return -EINVAL;
++
++ if (inner > 64 || outer > 64 || inner > outer)
++ return -EINVAL;
++
++ is_tr = axis > xpad_axis_xy_right;
++ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 2 : 0;
++ cmd = is_tr ? xpad_cmd_set_js_dz : xpad_cmd_set_tr_dz;
++
++ ally_cfg->deadzones[ally_cfg->mode - 1][is_tr][side] = inner;
++ ally_cfg->deadzones[ally_cfg->mode - 1][is_tr][side + 1] = outer;
++
++ return 0;
++}
++
++static ssize_t axis_xyz_deadzone_index_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return sysfs_emit(buf, "inner outer\n");
++}
++
++ALLY_DEVICE_ATTR_RO(axis_xyz_deadzone_index, deadzone_index);
++
++ALLY_AXIS_DEADZONE(xpad_axis_xy_left, deadzone);
++ALLY_AXIS_DEADZONE(xpad_axis_xy_right, deadzone);
++ALLY_AXIS_DEADZONE(xpad_axis_z_left, deadzone);
++ALLY_AXIS_DEADZONE(xpad_axis_z_right, deadzone);
++
++/* ANTI-DEADZONES *********************************************************************************/
++static ssize_t __gamepad_write_js_ADZ_to_mcu(struct hid_device *hdev,
++ struct ally_gamepad_cfg *ally_cfg)
++{
++ u8 *hidbuf;
++ int ret;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_adz;
++ hidbuf[3] = xpad_cmd_len_adz;
++ hidbuf[4] = ally_cfg->anti_deadzones[ally_cfg->mode - 1][btn_pair_side_left];
++ hidbuf[5] = ally_cfg->anti_deadzones[ally_cfg->mode - 1][btn_pair_side_right];
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ goto report_fail;
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ goto report_fail;
++
++report_fail:
++ kfree(hidbuf);
++ return ret;
++}
++
++static ssize_t __gamepad_js_ADZ_store(struct device *dev, const char *buf,
++ enum btn_pair_side side)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ int ret, val;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ ret = kstrtoint(buf, 0, &val);
++ if (ret)
++ return ret;
++
++ if (val < 0 || val > 32)
++ return -EINVAL;
++
++ ally_cfg->anti_deadzones[ally_cfg->mode - 1][side] = val;
++
++ return ret;
++}
++
++static ssize_t xpad_axis_xy_left_ADZ_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ return sysfs_emit(buf, "%d\n",
++ ally_cfg->anti_deadzones[ally_cfg->mode - 1][btn_pair_side_left]);
++}
++
++static ssize_t xpad_axis_xy_left_ADZ_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int ret = __gamepad_js_ADZ_store(dev, buf, btn_pair_side_left);
++
++ if (ret)
++ return ret;
++
++ return count;
++}
++
++ALLY_DEVICE_ATTR_RW(xpad_axis_xy_left_ADZ, anti_deadzone);
++
++static ssize_t xpad_axis_xy_right_ADZ_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ return sysfs_emit(buf, "%d\n",
++ ally_cfg->anti_deadzones[ally_cfg->mode - 1][btn_pair_side_right]);
++}
++
++static ssize_t xpad_axis_xy_right_ADZ_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int ret = __gamepad_js_ADZ_store(dev, buf, btn_pair_side_right);
++
++ if (ret)
++ return ret;
++
++ return count;
++}
++
++ALLY_DEVICE_ATTR_RW(xpad_axis_xy_right_ADZ, anti_deadzone);
++
++/* JS RESPONSE CURVES *****************************************************************************/
++static ssize_t rc_point_index_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ return sysfs_emit(buf, "move response\n");
++}
++
++ALLY_DEVICE_ATTR_RO(rc_point_index, rc_point_index);
++
++static ssize_t __gamepad_write_response_curves_to_mcu(struct hid_device *hdev,
++ struct ally_gamepad_cfg *ally_cfg)
++{
++ u8 *hidbuf;
++ int ret;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_response_curve;
++ hidbuf[3] = xpad_cmd_len_response_curve;
++ hidbuf[4] = 0x01;
++ memcpy(&hidbuf[5], &ally_cfg->response_curve[ally_cfg->mode - 1][btn_pair_side_left],
++ 8);
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ goto report_fail;
++
++ hidbuf[4] = 0x02;
++ memcpy(&hidbuf[5], &ally_cfg->response_curve[ally_cfg->mode - 1][btn_pair_side_right],
++ 8);
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ goto report_fail;
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ goto report_fail;
++
++report_fail:
++ kfree(hidbuf);
++ return ret;
++}
++
++static ssize_t __gamepad_store_response_curve(struct device *dev, const char *buf,
++ enum btn_pair_side side, int point)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ u32 move, response;
++ int idx;
++
++ idx = (point - 1) * 2;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ if (sscanf(buf, "%d %d", &move, &response) != 2)
++ return -EINVAL;
++
++ if (move > 64 || response > 64)
++ return -EINVAL;
++
++ ally_cfg->response_curve[ally_cfg->mode - 1][side][idx] = move;
++ ally_cfg->response_curve[ally_cfg->mode - 1][side][idx + 1] = response;
++
++ return 0;
++}
++
++ALLY_JS_RC_POINT(left, 1, rc_point_);
++ALLY_JS_RC_POINT(left, 2, rc_point_);
++ALLY_JS_RC_POINT(left, 3, rc_point_);
++ALLY_JS_RC_POINT(left, 4, rc_point_);
++
++ALLY_JS_RC_POINT(right, 1, rc_point_);
++ALLY_JS_RC_POINT(right, 2, rc_point_);
++ALLY_JS_RC_POINT(right, 3, rc_point_);
++ALLY_JS_RC_POINT(right, 4, rc_point_);
++
++/* CALIBRATIONS ***********************************************************************************/
++static int __gamepad_get_calibration(struct hid_device *hdev)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ u8 *hidbuf;
++ int ret, i;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ for (i = 0; i < 2; i++) {
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = 0xD0;
++ hidbuf[2] = 0x03;
++ hidbuf[3] = i + 1; // 0x01 JS, 0x02 TR
++ hidbuf[4] = 0x20;
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0) {
++ hid_warn(hdev, "ROG Ally check failed set report: %d\n", ret);
++ goto cleanup;
++ }
++
++ memset(hidbuf, 0, FEATURE_ROG_ALLY_REPORT_SIZE);
++ ret = asus_dev_get_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0 || hidbuf[5] != 1) {
++ hid_warn(hdev, "ROG Ally check failed get report: %d\n", ret);
++ goto cleanup;
++ }
++
++ if (i == 0) {
++ /* Joystick calibration */
++ /* [left][index] is Y: stable, min, max. X: stable, min, max */
++ ally_cfg->js_calibrations[0][3] = (hidbuf[6] << 8) | hidbuf[7];
++ ally_cfg->js_calibrations[0][4] = (hidbuf[8] << 8) | hidbuf[9];
++ ally_cfg->js_calibrations[0][5] = (hidbuf[10] << 8) | hidbuf[11];
++ ally_cfg->js_calibrations[0][0] = (hidbuf[12] << 8) | hidbuf[13];
++ ally_cfg->js_calibrations[0][1] = (hidbuf[14] << 8) | hidbuf[15];
++ ally_cfg->js_calibrations[0][2] = (hidbuf[16] << 8) | hidbuf[17];
++ /* [right][index] is Y: stable, min, max. X: stable, min, max */
++ ally_cfg->js_calibrations[1][0] = (hidbuf[24] << 8) | hidbuf[25];
++ ally_cfg->js_calibrations[1][1] = (hidbuf[26] << 8) | hidbuf[27];
++ ally_cfg->js_calibrations[1][2] = (hidbuf[28] << 8) | hidbuf[29];
++ ally_cfg->js_calibrations[1][3] = (hidbuf[18] << 8) | hidbuf[19];
++ ally_cfg->js_calibrations[1][4] = (hidbuf[20] << 8) | hidbuf[21];
++ ally_cfg->js_calibrations[1][5] = (hidbuf[22] << 8) | hidbuf[23];
++ } else {
++ /* Trigger calibration */
++ /* [left/right][stable/max] */
++ ally_cfg->tr_calibrations[0][0] = (hidbuf[6] << 8) | hidbuf[7];
++ ally_cfg->tr_calibrations[0][1] = (hidbuf[8] << 8) | hidbuf[9];
++ ally_cfg->tr_calibrations[1][0] = (hidbuf[10] << 8) | hidbuf[11];
++ ally_cfg->tr_calibrations[1][1] = (hidbuf[12] << 8) | hidbuf[13];
++ }
++ }
++
++cleanup:
++ kfree(hidbuf);
++ return ret;
++}
++
++static ssize_t __gamepad_write_cal_to_mcu(struct device *dev, enum xpad_axis axis)
++{
++ struct hid_device *hdev = to_hid_device(dev);
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ u8 *c, side, pkt_len, data_len;
++ int ret, cal, checksum = 0;
++ u8 *hidbuf;
++ int *head;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
++ pkt_len = axis > xpad_axis_xy_right ? 0x06 : 0x0E;
++ data_len = axis > xpad_axis_xy_right ? 2 : 6;
++ head = axis > xpad_axis_xy_right ? ally_cfg->tr_calibrations[side] :
++ ally_cfg->js_calibrations[side];
++
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_calibration;
++ hidbuf[3] = pkt_len;
++ hidbuf[4] = 0x01; /* second command (write calibration) */
++ hidbuf[5] = axis;
++ c = &hidbuf[6]; /* pointer to data start */
++
++ for (size_t i = 0; i < data_len; i++) {
++ cal = head[i];
++ *c = (u8)((cal & 0xff00) >> 8);
++ checksum += *c;
++ c += 1;
++ *c = (u8)(cal & 0xff);
++ checksum += *c;
++ c += 1;
++ }
++
++ hidbuf[6 + data_len * 2] = checksum;
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ goto report_fail;
++
++ memset(hidbuf, 0, FEATURE_ROG_ALLY_REPORT_SIZE);
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_calibration;
++ hidbuf[3] = xpad_cmd_len_calibration3;
++ hidbuf[4] = 0x03; /* second command (apply the calibration that was written) */
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ goto report_fail;
++
++report_fail:
++ kfree(hidbuf);
++ return ret;
++}
++
++static ssize_t __gamepad_cal_store(struct device *dev, const char *buf, enum xpad_axis axis)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ u32 x_stable, x_min, x_max, y_stable, y_min, y_max, side;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ if (axis == xpad_axis_xy_left || axis == xpad_axis_xy_right) {
++ if (sscanf(buf, "%d %d %d %d %d %d", &x_stable, &x_min, &x_max, &y_stable,
++ &y_min, &y_max) != 6)
++ return -EINVAL;
++
++ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
++ /* stored in reverse order for easy copy to packet */
++ ally_cfg->js_calibrations[side][0] = y_stable;
++ ally_cfg->js_calibrations[side][1] = y_min;
++ ally_cfg->js_calibrations[side][2] = y_max;
++ ally_cfg->js_calibrations[side][3] = x_stable;
++ ally_cfg->js_calibrations[side][4] = x_min;
++ ally_cfg->js_calibrations[side][5] = x_max;
++
++ return __gamepad_write_cal_to_mcu(dev, axis);
++ }
++ if (sscanf(buf, "%d %d", &x_stable, &x_max) != 2)
++ return -EINVAL;
++
++ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
++ /* stored in reverse order for easy copy to packet */
++ ally_cfg->tr_calibrations[side][0] = x_stable;
++ ally_cfg->tr_calibrations[side][1] = x_max;
++
++ return __gamepad_write_cal_to_mcu(dev, axis);
++}
++
++static ssize_t __gamepad_cal_show(struct device *dev, char *buf, enum xpad_axis axis)
++{
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg;
++ int side = (axis == xpad_axis_xy_right || axis == xpad_axis_z_right) ? 1 : 0;
++
++ if (!drvdata.gamepad_cfg)
++ return -ENODEV;
++
++ if (axis == xpad_axis_xy_left || axis == xpad_axis_xy_right) {
++ return sysfs_emit(
++ buf, "%d %d %d %d %d %d\n", ally_cfg->js_calibrations[side][3],
++ ally_cfg->js_calibrations[side][4], ally_cfg->js_calibrations[side][5],
++ ally_cfg->js_calibrations[side][0], ally_cfg->js_calibrations[side][1],
++ ally_cfg->js_calibrations[side][2]);
++ }
++
++ return sysfs_emit(buf, "%d %d\n", ally_cfg->tr_calibrations[side][0],
++ ally_cfg->tr_calibrations[side][1]);
++}
++
++ALLY_CAL_ATTR(xpad_axis_xy_left_cal, xpad_axis_xy_left, calibration);
++ALLY_CAL_ATTR(xpad_axis_xy_right_cal, xpad_axis_xy_right, calibration);
++ALLY_CAL_ATTR(xpad_axis_z_left_cal, xpad_axis_z_left, calibration);
++ALLY_CAL_ATTR(xpad_axis_z_right_cal, xpad_axis_z_right, calibration);
++
++static ssize_t xpad_axis_xy_cal_index_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return sysfs_emit(buf, "x_stable x_min x_max y_stable y_min y_max\n");
++}
++
++ALLY_DEVICE_ATTR_RO(xpad_axis_xy_cal_index, calibration_index);
++
++static ssize_t xpad_axis_z_cal_index_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return sysfs_emit(buf, "z_stable z_max\n");
++}
++
++ALLY_DEVICE_ATTR_RO(xpad_axis_z_cal_index, calibration_index);
++
++static ssize_t __gamepad_cal_reset(struct device *dev, const char *buf, enum xpad_axis axis)
++{
++ struct hid_device *hdev = to_hid_device(dev);
++ u8 *hidbuf;
++ int ret;
++
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++
++ /* Write the reset value, then apply it */
++ for (u8 cmd = 0x02; cmd <= 0x03; cmd++) {
++ memset(hidbuf, 0, FEATURE_ROG_ALLY_REPORT_SIZE);
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_calibration;
++ hidbuf[3] = (cmd == 0x02) ? xpad_cmd_len_calibration2 :
++ xpad_cmd_len_calibration3;
++ hidbuf[4] = cmd;
++ hidbuf[5] = axis;
++
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ break;
++ }
++
++ __gamepad_get_calibration(hdev);
++
++ kfree(hidbuf);
++ return ret;
++}
++
++ALLY_CAL_RESET_ATTR(xpad_axis_xy_left_cal_reset, xpad_axis_xy_left, calibration_reset);
++ALLY_CAL_RESET_ATTR(xpad_axis_xy_right_cal_reset, xpad_axis_xy_right, calibration_reset);
++ALLY_CAL_RESET_ATTR(xpad_axis_z_left_cal_reset, xpad_axis_z_left, calibration_reset);
++ALLY_CAL_RESET_ATTR(xpad_axis_z_right_cal_reset, xpad_axis_z_right, calibration_reset);
++
++static struct attribute *gamepad_axis_xy_left_attrs[] = {
++ &dev_attr_xpad_axis_xy_left_deadzone.attr,
++ &dev_attr_axis_xyz_deadzone_index.attr,
++ &dev_attr_xpad_axis_xy_left_ADZ.attr,
++ &dev_attr_xpad_axis_xy_left_cal_reset.attr,
++ &dev_attr_xpad_axis_xy_left_cal.attr,
++ &dev_attr_xpad_axis_xy_cal_index.attr,
++ &dev_attr_rc_point_left_1.attr,
++ &dev_attr_rc_point_left_2.attr,
++ &dev_attr_rc_point_left_3.attr,
++ &dev_attr_rc_point_left_4.attr,
++ &dev_attr_rc_point_index.attr,
++ NULL
++};
++static const struct attribute_group ally_controller_axis_xy_left_attr_group = {
++ .name = "axis_xy_left",
++ .attrs = gamepad_axis_xy_left_attrs,
++};
++
++static struct attribute *gamepad_axis_xy_right_attrs[] = {
++ &dev_attr_xpad_axis_xy_right_deadzone.attr,
++ &dev_attr_axis_xyz_deadzone_index.attr,
++ &dev_attr_xpad_axis_xy_right_ADZ.attr,
++ &dev_attr_xpad_axis_xy_right_cal_reset.attr,
++ &dev_attr_xpad_axis_xy_right_cal.attr,
++ &dev_attr_xpad_axis_xy_cal_index.attr,
++ &dev_attr_rc_point_right_1.attr,
++ &dev_attr_rc_point_right_2.attr,
++ &dev_attr_rc_point_right_3.attr,
++ &dev_attr_rc_point_right_4.attr,
++ &dev_attr_rc_point_index.attr,
++ NULL
++};
++static const struct attribute_group ally_controller_axis_xy_right_attr_group = {
++ .name = "axis_xy_right",
++ .attrs = gamepad_axis_xy_right_attrs,
++};
++
++static struct attribute *gamepad_axis_z_left_attrs[] = {
++ &dev_attr_xpad_axis_z_left_deadzone.attr, &dev_attr_axis_xyz_deadzone_index.attr,
++ &dev_attr_xpad_axis_z_left_cal.attr, &dev_attr_xpad_axis_z_cal_index.attr,
++ &dev_attr_xpad_axis_z_left_cal_reset.attr, NULL
++};
++static const struct attribute_group ally_controller_axis_z_left_attr_group = {
++ .name = "axis_z_left",
++ .attrs = gamepad_axis_z_left_attrs,
++};
++
++static struct attribute *gamepad_axis_z_right_attrs[] = {
++ &dev_attr_xpad_axis_z_right_deadzone.attr, &dev_attr_axis_xyz_deadzone_index.attr,
++ &dev_attr_xpad_axis_z_right_cal.attr, &dev_attr_xpad_axis_z_cal_index.attr,
++ &dev_attr_xpad_axis_z_right_cal_reset.attr, NULL
++};
++static const struct attribute_group ally_controller_axis_z_right_attr_group = {
++ .name = "axis_z_right",
++ .attrs = gamepad_axis_z_right_attrs,
++};
++
++static const struct attribute_group *gamepad_device_attr_groups[] = {
++ &ally_controller_attr_group,
++ &ally_controller_axis_xy_left_attr_group,
++ &ally_controller_axis_xy_right_attr_group,
++ &ally_controller_axis_z_left_attr_group,
++ &ally_controller_axis_z_right_attr_group,
++ &btn_mapping_m1_attr_group,
++ &btn_mapping_m2_attr_group,
++ &btn_mapping_a_attr_group,
++ &btn_mapping_b_attr_group,
++ &btn_mapping_x_attr_group,
++ &btn_mapping_y_attr_group,
++ &btn_mapping_lb_attr_group,
++ &btn_mapping_rb_attr_group,
++ &btn_mapping_ls_attr_group,
++ &btn_mapping_rs_attr_group,
++ &btn_mapping_dpad_u_attr_group,
++ &btn_mapping_dpad_d_attr_group,
++ &btn_mapping_dpad_l_attr_group,
++ &btn_mapping_dpad_r_attr_group,
++ &btn_mapping_view_attr_group,
++ &btn_mapping_menu_attr_group,
++ NULL
++};
++
++static int __gamepad_write_all_to_mcu(struct hid_device *hdev,
++ struct ally_gamepad_cfg *ally_cfg)
++{
++ u8 *hidbuf;
++ int ret;
++
++ ret = __gamepad_set_mapping(hdev, ally_cfg, btn_pair_dpad_u_d);
++ if (ret < 0)
++ return ret;
++ ret = __gamepad_set_mapping(hdev, ally_cfg, btn_pair_dpad_l_r);
++ if (ret < 0)
++ return ret;
++ ret = __gamepad_set_mapping(hdev, ally_cfg, btn_pair_ls_rs);
++ if (ret < 0)
++ return ret;
++ ret = __gamepad_set_mapping(hdev, ally_cfg, btn_pair_lb_rb);
++ if (ret < 0)
++ return ret;
++ ret = __gamepad_set_mapping(hdev, ally_cfg, btn_pair_a_b);
++ if (ret < 0)
++ return ret;
++ ret = __gamepad_set_mapping(hdev, ally_cfg, btn_pair_x_y);
++ if (ret < 0)
++ return ret;
++ ret = __gamepad_set_mapping(hdev, ally_cfg, btn_pair_view_menu);
++ if (ret < 0)
++ return ret;
++ ret = __gamepad_set_mapping(hdev, ally_cfg, btn_pair_m1_m2);
++ if (ret < 0)
++ return ret;
++ __gamepad_set_mapping(hdev, ally_cfg, btn_pair_lt_rt);
++ if (ret < 0)
++ return ret;
++ __gamepad_set_deadzones(hdev, ally_cfg);
++ if (ret < 0)
++ return ret;
++ __gamepad_write_js_ADZ_to_mcu(hdev, ally_cfg);
++ if (ret < 0)
++ return ret;
++ __gamepad_write_vibe_intensity_to_mcu(hdev, ally_cfg);
++ if (ret < 0)
++ return ret;
++ __gamepad_write_response_curves_to_mcu(hdev, ally_cfg);
++ if (ret < 0)
++ return ret;
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ return ret;
++
++ /* set turbo */
++ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
++ if (!hidbuf)
++ return -ENOMEM;
++ hidbuf[0] = FEATURE_ROG_ALLY_REPORT_ID;
++ hidbuf[1] = FEATURE_ROG_ALLY_CODE_PAGE;
++ hidbuf[2] = xpad_cmd_set_turbo;
++ hidbuf[3] = xpad_cmd_len_turbo;
++ memcpy(&hidbuf[4], ally_cfg->turbo_btns[ally_cfg->mode - 1], TURBO_BLOCK_LEN);
++ ret = asus_dev_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++
++ kfree(hidbuf);
++ return ret;
++}
++
++static struct ally_gamepad_cfg *ally_gamepad_cfg_create(struct hid_device *hdev)
++{
++ struct ally_gamepad_cfg *ally_cfg;
++ struct input_dev *input_dev;
++ int i, err;
++
++ ally_cfg = devm_kzalloc(&hdev->dev, sizeof(*ally_cfg), GFP_KERNEL);
++ if (!ally_cfg)
++ return ERR_PTR(-ENOMEM);
++ ally_cfg->hdev = hdev;
++
++ input_dev = devm_input_allocate_device(&hdev->dev);
++ if (!input_dev) {
++ err = -ENOMEM;
++ goto free_ally_cfg;
++ }
++ ally_cfg->input = input_dev;
++
++ input_dev->id.bustype = hdev->bus;
++ input_dev->id.vendor = hdev->vendor;
++ input_dev->id.product = hdev->product;
++ input_dev->id.version = hdev->version;
++ input_dev->uniq = hdev->uniq;
++ input_dev->name = "ASUS ROG Ally Config";
++ input_set_capability(input_dev, EV_KEY, KEY_PROG1);
++ input_set_capability(input_dev, EV_KEY, KEY_F16);
++ input_set_capability(input_dev, EV_KEY, KEY_F17);
++ input_set_capability(input_dev, EV_KEY, KEY_F18);
++
++ input_set_drvdata(input_dev, hdev);
++
++ err = input_register_device(input_dev);
++ if (err)
++ goto free_input_dev;
++
++ ally_cfg->mode = xpad_mode_game;
++ for (i = 0; i < xpad_mode_mouse; i++) {
++ ally_cfg->deadzones[i][0][1] = 64;
++ ally_cfg->deadzones[i][0][3] = 64;
++ ally_cfg->deadzones[i][1][1] = 64;
++ ally_cfg->deadzones[i][1][3] = 64;
++ ally_cfg->response_curve[i][0][0] = 0x14;
++ ally_cfg->response_curve[i][0][1] = 0x14;
++ ally_cfg->response_curve[i][0][2] = 0x28;
++ ally_cfg->response_curve[i][0][3] = 0x28;
++ ally_cfg->response_curve[i][0][4] = 0x3c;
++ ally_cfg->response_curve[i][0][5] = 0x3c;
++ ally_cfg->response_curve[i][0][6] = 0x63;
++ ally_cfg->response_curve[i][0][7] = 0x63;
++ ally_cfg->response_curve[i][1][0] = 0x14;
++ ally_cfg->response_curve[i][1][1] = 0x14;
++ ally_cfg->response_curve[i][1][2] = 0x28;
++ ally_cfg->response_curve[i][1][3] = 0x28;
++ ally_cfg->response_curve[i][1][4] = 0x3c;
++ ally_cfg->response_curve[i][1][5] = 0x3c;
++ ally_cfg->response_curve[i][1][6] = 0x63;
++ ally_cfg->response_curve[i][1][7] = 0x63;
++ ally_cfg->vibration_intensity[i][0] = 64;
++ ally_cfg->vibration_intensity[i][1] = 64;
++ }
++ drvdata.gamepad_cfg = ally_cfg;
++
++ /* ignore all errors for this as they are related to USB HID I/O */
++ __gamepad_mapping_xpad_default(ally_cfg);
++ __gamepad_mapping_wasd_default(ally_cfg);
++ /* these calls will never error so ignore the return */
++ __gamepad_mapping_store(ally_cfg, KB_M2, btn_pair_m1_m2, btn_pair_side_left, false);
++ __gamepad_mapping_store(ally_cfg, KB_M1, btn_pair_m1_m2, btn_pair_side_right, false);
++ __gamepad_set_mode(hdev, ally_cfg, xpad_mode_game);
++ __gamepad_set_mapping(hdev, ally_cfg, btn_pair_m1_m2);
++ /* ensure we have data for users to start from */
++ __gamepad_get_calibration(hdev);
++
++ if (sysfs_create_groups(&hdev->dev.kobj, gamepad_device_attr_groups)) {
++ err = -ENODEV;
++ goto unregister_input_dev;
++ }
++
++ return ally_cfg;
++
++unregister_input_dev:
++ input_unregister_device(input_dev);
++ ally_cfg->input = NULL; // Prevent double free when kfree(ally_cfg) happens
++
++free_input_dev:
++ devm_kfree(&hdev->dev, input_dev);
++
++free_ally_cfg:
++ devm_kfree(&hdev->dev, ally_cfg);
++ return ERR_PTR(err);
++}
++
++static void ally_cfg_remove(struct hid_device *hdev)
++{
++ __gamepad_set_mode(hdev, drvdata.gamepad_cfg, xpad_mode_mouse);
++ sysfs_remove_groups(&hdev->dev.kobj, gamepad_device_attr_groups);
++}
++
++/**************************************************************************************************/
++/* ROG Ally LED control */
++/**************************************************************************************************/
++static void ally_schedule_work(struct ally_rgb_leds *led)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&led->lock, flags);
++ if (!led->removed)
++ schedule_work(&led->work);
++ spin_unlock_irqrestore(&led->lock, flags);
++ pr_warn("5");
++}
++
++static void ally_led_do_brightness(struct work_struct *work)
++{
++ struct ally_rgb_leds *led = container_of(work, struct ally_rgb_leds, work);
++ u8 buf1[] = { FEATURE_ROG_ALLY_REPORT_ID, 0xb4, 0x00, 0x00, 0x00 };
++ u8 buf[] = { FEATURE_ROG_ALLY_REPORT_ID, 0xba, 0xc5, 0xc4, 0x00 };
++ unsigned long flags;
++
++ spin_lock_irqsave(&led->lock, flags);
++ if (!led->update_bright) {
++ spin_unlock_irqrestore(&led->lock, flags);
++ return;
++ }
++ led->update_bright = false;
++ buf[4] = led->brightness;
++ spin_unlock_irqrestore(&led->lock, flags);
++
++ if (asus_dev_set_report(led->hdev, buf, sizeof(buf)) < 0)
++ hid_err(led->hdev, "Ally failed to set backlight\n");
++ if (asus_dev_set_report(led->hdev, buf1, sizeof(buf1)) < 0)
++ hid_err(led->hdev, "Ally failed to set backlight\n");
++}
++
++static void ally_led_do_rgb(struct work_struct *work)
++{
++ struct ally_rgb_leds *led = container_of(work, struct ally_rgb_leds, work);
++ unsigned long flags;
++ int ret;
++
++ u8 buf[16] = { [0] = FEATURE_ROG_ALLY_REPORT_ID,
++ [1] = FEATURE_ROG_ALLY_CODE_PAGE,
++ [2] = xpad_cmd_set_leds,
++ [3] = xpad_cmd_len_leds };
++
++ spin_lock_irqsave(&led->lock, flags);
++ if (!led->update_rgb) {
++ spin_unlock_irqrestore(&led->lock, flags);
++ return;
++ }
++ for (int i = 0; i < 4; i++) {
++ buf[4 + i * 3] = led->gamepad_red;
++ buf[5 + i * 3] = led->gamepad_green;
++ buf[6 + i * 3] = led->gamepad_blue;
++ }
++ led->update_rgb = false;
++ spin_unlock_irqrestore(&led->lock, flags);
++
++ ret = asus_dev_set_report(led->hdev, buf, sizeof(buf));
++ if (ret < 0)
++ hid_err(led->hdev, "Ally failed to set gamepad backlight: %d\n", ret);
++}
++
++static void ally_led_work(struct work_struct *work)
++{
++ ally_led_do_brightness(work);
++ ally_led_do_rgb(work);
++}
++
++static void ally_backlight_set(struct led_classdev *led_cdev, enum led_brightness brightness)
++{
++ struct ally_rgb_leds *led =
++ container_of(led_cdev, struct ally_rgb_leds, led_bright_dev);
++ unsigned long flags;
++
++ spin_lock_irqsave(&led->lock, flags);
++ led->update_bright = true;
++ led->brightness = brightness;
++ spin_unlock_irqrestore(&led->lock, flags);
++
++ ally_schedule_work(led);
++}
++
++static enum led_brightness ally_backlight_get(struct led_classdev *led_cdev)
++{
++ struct ally_rgb_leds *led =
++ container_of(led_cdev, struct ally_rgb_leds, led_bright_dev);
++ enum led_brightness brightness;
++ unsigned long flags;
++
++ spin_lock_irqsave(&led->lock, flags);
++ brightness = led->brightness;
++ spin_unlock_irqrestore(&led->lock, flags);
++
++ return brightness;
++}
++
++static void ally_set_rgb_brightness(struct led_classdev *cdev, enum led_brightness brightness)
++{
++ struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
++ struct ally_rgb_leds *led = container_of(mc_cdev, struct ally_rgb_leds, led_rgb_dev);
++ unsigned long flags;
++
++ led_mc_calc_color_components(mc_cdev, brightness);
++ spin_lock_irqsave(&led->lock, flags);
++ led->update_rgb = true;
++ led->gamepad_red = mc_cdev->subled_info[0].brightness;
++ led->gamepad_green = mc_cdev->subled_info[1].brightness;
++ led->gamepad_blue = mc_cdev->subled_info[2].brightness;
++ spin_unlock_irqrestore(&led->lock, flags);
++
++ ally_schedule_work(led);
++}
++
++static int ally_gamepad_register_brightness(struct hid_device *hdev,
++ struct ally_rgb_leds *led_rgb)
++{
++ struct led_classdev *led_cdev;
++
++ led_cdev = &led_rgb->led_bright_dev;
++ led_cdev->name = "ally:kbd_backlight"; /* Let a desktop control it also */
++ led_cdev->max_brightness = 3;
++ led_cdev->brightness_set = ally_backlight_set;
++ led_cdev->brightness_get = ally_backlight_get;
++
++ return devm_led_classdev_register(&hdev->dev, &led_rgb->led_bright_dev);
++}
++
++static int ally_gamepad_register_rgb_leds(struct hid_device *hdev,
++ struct ally_rgb_leds *led_rgb)
++{
++ struct mc_subled *mc_led_info;
++ struct led_classdev *led_cdev;
++
++ mc_led_info = devm_kmalloc_array(&hdev->dev, 3, sizeof(*mc_led_info),
++ GFP_KERNEL | __GFP_ZERO);
++ if (!mc_led_info)
++ return -ENOMEM;
++
++ mc_led_info[0].color_index = LED_COLOR_ID_RED;
++ mc_led_info[1].color_index = LED_COLOR_ID_GREEN;
++ mc_led_info[2].color_index = LED_COLOR_ID_BLUE;
++
++ led_rgb->led_rgb_dev.subled_info = mc_led_info;
++ led_rgb->led_rgb_dev.num_colors = 3;
++
++ led_cdev = &led_rgb->led_rgb_dev.led_cdev;
++ led_cdev->name = "ally:rgb:gamepad";
++ led_cdev->brightness = 128;
++ led_cdev->max_brightness = 255;
++ led_cdev->brightness_set = ally_set_rgb_brightness;
++
++ return devm_led_classdev_multicolor_register(&hdev->dev, &led_rgb->led_rgb_dev);
++}
++
++static struct ally_rgb_leds *ally_gamepad_rgb_create(struct hid_device *hdev)
++{
++ struct ally_rgb_leds *led_rgb;
++ int ret;
++
++ led_rgb = devm_kzalloc(&hdev->dev, sizeof(struct ally_rgb_leds), GFP_KERNEL);
++ if (!led_rgb)
++ return ERR_PTR(-ENOMEM);
++
++ ret = ally_gamepad_register_rgb_leds(hdev, led_rgb);
++ if (ret < 0) {
++ cancel_work_sync(&led_rgb->work);
++ devm_kfree(&hdev->dev, led_rgb);
++ return ERR_PTR(ret);
++ }
++
++ ret = ally_gamepad_register_brightness(hdev, led_rgb);
++ if (ret < 0) {
++ cancel_work_sync(&led_rgb->work);
++ devm_kfree(&hdev->dev, led_rgb);
++ return ERR_PTR(ret);
++ }
++
++ led_rgb->hdev = hdev;
++ led_rgb->brightness = 3;
++ led_rgb->removed = false;
++
++ INIT_WORK(&led_rgb->work, ally_led_work);
++ spin_lock_init(&led_rgb->lock);
++
++ return led_rgb;
++}
++
++static void ally_rgb_remove(struct hid_device *hdev)
++{
++ struct ally_rgb_leds *led_rgb = drvdata.led_rgb;
++ unsigned long flags;
++
++ spin_lock_irqsave(&led_rgb->lock, flags);
++ led_rgb->removed = true;
++ spin_unlock_irqrestore(&led_rgb->lock, flags);
++ cancel_work_sync(&led_rgb->work);
++}
++
++/**************************************************************************************************/
++/* ROG Ally driver init */
++/**************************************************************************************************/
++static int ally_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data,
++ int size)
++{
++ struct ally_gamepad_cfg *cfg = drvdata.gamepad_cfg;
++ struct ally_x_device *ally_x = drvdata.ally_x;
++
++ if (ally_x) {
++ if ((hdev->bus == BUS_USB && report->id == ALLY_X_INPUT_REPORT_USB &&
++ size == ALLY_X_INPUT_REPORT_USB_SIZE) ||
++ (cfg && data[0] == 0x5A)) {
++ ally_x_raw_event(ally_x, report, data, size);
++ } else {
++ return -1;
++ }
++ }
++ if (cfg && !ally_x) {
++ input_report_key(cfg->input, KEY_PROG1, data[1] == 0x38);
++ input_report_key(cfg->input, KEY_F16, data[1] == 0xA6);
++ input_report_key(cfg->input, KEY_F17, data[1] == 0xA7);
++ input_report_key(cfg->input, KEY_F18, data[1] == 0xA8);
++ input_sync(cfg->input);
++ }
++
++ return 0;
++}
++
++static int ally_gamepad_init(struct hid_device *hdev, u8 report_id)
++{
++ const u8 buf[] = { report_id, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54, 0x65,
++ 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
++ int ret;
++
++ ret = asus_dev_set_report(hdev, buf, sizeof(buf));
++ if (ret < 0)
++ hid_err(hdev, "Ally failed to send init command: %d\n", ret);
++
++ return ret;
++}
++
++static int ally_probe(struct hid_device *hdev, const struct hid_device_id *id)
++{
++ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
++ struct usb_host_endpoint *ep = intf->cur_altsetting->endpoint;
++ int ret;
++
++ if (ep->desc.bEndpointAddress != ALLY_CFG_INTF_IN_ADDRESS &&
++ ep->desc.bEndpointAddress != ALLY_X_INTERFACE_ADDRESS)
++ return -ENODEV;
++
++ ret = hid_parse(hdev);
++ if (ret) {
++ hid_err(hdev, "Parse failed\n");
++ return ret;
++ }
++
++ ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
++ if (ret) {
++ hid_err(hdev, "Failed to start HID device\n");
++ return ret;
++ }
++
++ ret = hid_hw_open(hdev);
++ if (ret) {
++ hid_err(hdev, "Failed to open HID device\n");
++ goto err_stop;
++ }
++
++ /* Initialize MCU even before alloc */
++ ret = ally_gamepad_init(hdev, FEATURE_REPORT_ID);
++ if (ret < 0)
++ return ret;
++
++ ret = ally_gamepad_init(hdev, FEATURE_KBD_LED_REPORT_ID1);
++ if (ret < 0)
++ return ret;
++
++ ret = ally_gamepad_init(hdev, FEATURE_KBD_LED_REPORT_ID2);
++ if (ret < 0)
++ return ret;
++
++ drvdata.hdev = hdev;
++ hid_set_drvdata(hdev, &drvdata);
++
++ /* This should almost always exist */
++ if (ep->desc.bEndpointAddress == ALLY_CFG_INTF_IN_ADDRESS) {
++ drvdata.led_rgb = ally_gamepad_rgb_create(hdev);
++ if (IS_ERR(drvdata.led_rgb))
++ hid_err(hdev, "Failed to create Ally gamepad LEDs.\n");
++ else
++ hid_info(hdev, "Created Ally RGB LED controls.\n");
++
++ ally_gamepad_cfg_create(hdev); // assigns self
++ if (IS_ERR(drvdata.gamepad_cfg))
++ hid_err(hdev, "Failed to create Ally gamepad attributes.\n");
++ else
++ hid_info(hdev, "Created Ally gamepad attributes.\n");
++
++ if (IS_ERR(drvdata.led_rgb) && IS_ERR(drvdata.gamepad_cfg))
++ goto err_close;
++ }
++
++ /* May or may not exist */
++ if (ep->desc.bEndpointAddress == ALLY_X_INTERFACE_ADDRESS) {
++ drvdata.ally_x = ally_x_create(hdev);
++ if (IS_ERR(drvdata.ally_x)) {
++ hid_err(hdev, "Failed to create Ally X gamepad.\n");
++ drvdata.ally_x = NULL;
++ goto err_close;
++ }
++ hid_info(hdev, "Created Ally X controller.\n");
++
++ // Not required since we send this inputs ep through the gamepad input dev
++ if (drvdata.gamepad_cfg && drvdata.gamepad_cfg->input) {
++ input_unregister_device(drvdata.gamepad_cfg->input);
++ hid_info(hdev, "Ally X removed unrequired input dev.\n");
++ }
++ }
++
++ return 0;
++
++err_close:
++ hid_hw_close(hdev);
++err_stop:
++ hid_hw_stop(hdev);
++ return ret;
++}
++
++static void ally_remove(struct hid_device *hdev)
++{
++ if (drvdata.ally_x)
++ ally_x_remove(hdev);
++ if (drvdata.led_rgb)
++ ally_rgb_remove(hdev);
++ if (drvdata.gamepad_cfg)
++ ally_cfg_remove(hdev);
++ hid_hw_close(hdev);
++ hid_hw_stop(hdev);
++}
++
++static int ally_resume(struct hid_device *hdev)
++{
++ int ret;
++
++ ret = ally_gamepad_init(hdev, FEATURE_REPORT_ID);
++ if (ret < 0)
++ return ret;
++
++ ret = ally_gamepad_init(hdev, FEATURE_KBD_LED_REPORT_ID1);
++ if (ret < 0)
++ return ret;
++
++ ret = ally_gamepad_init(hdev, FEATURE_KBD_LED_REPORT_ID2);
++ if (ret < 0)
++ return ret;
++
++ if (drvdata.ally_x && drvdata.ally_x->output_worker_initialized)
++ schedule_work(&drvdata.ally_x->output_worker);
++
++ return ret;
++}
++
++MODULE_DEVICE_TABLE(hid, rog_ally_devices);
++
++static struct hid_driver rog_ally_cfg = {
++ .name = "asus_rog_ally",
++ .id_table = rog_ally_devices,
++ .probe = ally_probe,
++ .remove = ally_remove,
++ .raw_event = ally_raw_event,
++ .resume = ally_resume,
++};
++
++static int __init rog_ally_cfg_init(void)
++{
++ return hid_register_driver(&rog_ally_cfg);
++}
++
++static void __exit rog_ally_cfg_exit(void)
++{
++ hid_unregister_driver(&rog_ally_cfg);
++}
++
++module_init(rog_ally_cfg_init);
++module_exit(rog_ally_cfg_exit);
++
++MODULE_AUTHOR("Luke D. Jones");
++MODULE_DESCRIPTION("HID Driver for ASUS ROG Ally gamepad configuration.");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hid/hid-asus-ally.h b/drivers/hid/hid-asus-ally.h
+new file mode 100644
+index 000000000000..252d9f126e32
+--- /dev/null
++++ b/drivers/hid/hid-asus-ally.h
+@@ -0,0 +1,544 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later
++ *
++ * HID driver for Asus ROG laptops and Ally
++ *
++ * Copyright (c) 2023 Luke Jones <luke@ljones.dev>
++ */
++
++#include <linux/hid.h>
++#include <linux/types.h>
++
++#define ALLY_X_INTERFACE_ADDRESS 0x87
++
++#define BTN_CODE_LEN 11
++#define MAPPING_BLOCK_LEN 44
++
++#define TURBO_BLOCK_LEN 32
++#define TURBO_BLOCK_STEP 2
++
++#define PAD_A "pad_a"
++#define PAD_B "pad_b"
++#define PAD_X "pad_x"
++#define PAD_Y "pad_y"
++#define PAD_LB "pad_lb"
++#define PAD_RB "pad_rb"
++#define PAD_LS "pad_ls"
++#define PAD_RS "pad_rs"
++#define PAD_DPAD_UP "pad_dpad_up"
++#define PAD_DPAD_DOWN "pad_dpad_down"
++#define PAD_DPAD_LEFT "pad_dpad_left"
++#define PAD_DPAD_RIGHT "pad_dpad_right"
++#define PAD_VIEW "pad_view"
++#define PAD_MENU "pad_menu"
++#define PAD_XBOX "pad_xbox"
++
++#define KB_M1 "kb_m1"
++#define KB_M2 "kb_m2"
++#define KB_ESC "kb_esc"
++#define KB_F1 "kb_f1"
++#define KB_F2 "kb_f2"
++#define KB_F3 "kb_f3"
++#define KB_F4 "kb_f4"
++#define KB_F5 "kb_f5"
++#define KB_F6 "kb_f6"
++#define KB_F7 "kb_f7"
++#define KB_F8 "kb_f8"
++#define KB_F9 "kb_f9"
++#define KB_F10 "kb_f10"
++#define KB_F11 "kb_f11"
++#define KB_F12 "kb_f12"
++#define KB_F14 "kb_f14"
++#define KB_F15 "kb_f15"
++
++#define KB_BACKTICK "kb_backtick"
++#define KB_1 "kb_1"
++#define KB_2 "kb_2"
++#define KB_3 "kb_3"
++#define KB_4 "kb_4"
++#define KB_5 "kb_5"
++#define KB_6 "kb_6"
++#define KB_7 "kb_7"
++#define KB_8 "kb_8"
++#define KB_9 "kb_9"
++#define KB_0 "kb_0"
++#define KB_HYPHEN "kb_hyphen"
++#define KB_EQUALS "kb_equals"
++#define KB_BACKSPACE "kb_backspace"
++
++#define KB_TAB "kb_tab"
++#define KB_Q "kb_q"
++#define KB_W "kb_w"
++#define KB_E "kb_e"
++#define KB_R "kb_r"
++#define KB_T "kb_t"
++#define KB_Y "kb_y"
++#define KB_U "kb_u"
++#define KB_I "kb_i"
++#define KB_O "kb_o"
++#define KB_P "kb_p"
++#define KB_LBRACKET "kb_lbracket"
++#define KB_RBRACKET "kb_rbracket"
++#define KB_BACKSLASH "kb_bkslash"
++
++#define KB_CAPS "kb_caps"
++#define KB_A "kb_a"
++#define KB_S "kb_s"
++#define KB_D "kb_d"
++#define KB_F "kb_f"
++#define KB_G "kb_g"
++#define KB_H "kb_h"
++#define KB_J "kb_j"
++#define KB_K "kb_k"
++#define KB_L "kb_l"
++#define KB_SEMI "kb_semicolon"
++#define KB_QUOTE "kb_quote"
++#define KB_RET "kb_enter"
++
++#define KB_LSHIFT "kb_lshift"
++#define KB_Z "kb_z"
++#define KB_X "kb_x"
++#define KB_C "kb_c"
++#define KB_V "kb_v"
++#define KB_B "kb_b"
++#define KB_N "kb_n"
++#define KB_M "kb_m"
++#define KB_COMMA "kb_comma"
++#define KB_PERIOD "kb_period"
++#define KB_FWDSLASH "kb_fwdslash"
++#define KB_RSHIFT "kb_rshift"
++
++#define KB_LCTL "kb_lctl"
++#define KB_META "kb_meta"
++#define KB_LALT "kb_lalt"
++#define KB_SPACE "kb_space"
++#define KB_RALT "kb_ralt"
++#define KB_MENU "kb_menu"
++#define KB_RCTL "kb_rctl"
++
++#define KB_PRNTSCN "kb_prntscn"
++#define KB_SCRLCK "kb_scrlck"
++#define KB_PAUSE "kb_pause"
++#define KB_INS "kb_ins"
++#define KB_HOME "kb_home"
++#define KB_PGUP "kb_pgup"
++#define KB_DEL "kb_del"
++#define KB_END "kb_end"
++#define KB_PGDWN "kb_pgdwn"
++
++#define KB_UP_ARROW "kb_up_arrow"
++#define KB_DOWN_ARROW "kb_down_arrow"
++#define KB_LEFT_ARROW "kb_left_arrow"
++#define KB_RIGHT_ARROW "kb_right_arrow"
++
++#define NUMPAD_LOCK "numpad_lock"
++#define NUMPAD_FWDSLASH "numpad_fwdslash"
++#define NUMPAD_ASTERISK "numpad_asterisk"
++#define NUMPAD_HYPHEN "numpad_hyphen"
++#define NUMPAD_0 "numpad_0"
++#define NUMPAD_1 "numpad_1"
++#define NUMPAD_2 "numpad_2"
++#define NUMPAD_3 "numpad_3"
++#define NUMPAD_4 "numpad_4"
++#define NUMPAD_5 "numpad_5"
++#define NUMPAD_6 "numpad_6"
++#define NUMPAD_7 "numpad_7"
++#define NUMPAD_8 "numpad_8"
++#define NUMPAD_9 "numpad_9"
++#define NUMPAD_PLUS "numpad_plus"
++#define NUMPAD_ENTER "numpad_enter"
++#define NUMPAD_PERIOD "numpad_."
++
++#define MOUSE_LCLICK "rat_lclick"
++#define MOUSE_RCLICK "rat_rclick"
++#define MOUSE_MCLICK "rat_mclick"
++#define MOUSE_WHEEL_UP "rat_wheel_up"
++#define MOUSE_WHEEL_DOWN "rat_wheel_down"
++
++#define MEDIA_SCREENSHOT "media_screenshot"
++#define MEDIA_SHOW_KEYBOARD "media_show_keyboard"
++#define MEDIA_SHOW_DESKTOP "media_show_desktop"
++#define MEDIA_START_RECORDING "media_start_recording"
++#define MEDIA_MIC_OFF "media_mic_off"
++#define MEDIA_VOL_DOWN "media_vol_down"
++#define MEDIA_VOL_UP "media_vol_up"
++
++/* required so we can have nested attributes with same name but different functions */
++#define ALLY_DEVICE_ATTR_RW(_name, _sysfs_name) \
++ struct device_attribute dev_attr_##_name = \
++ __ATTR(_sysfs_name, 0644, _name##_show, _name##_store)
++
++#define ALLY_DEVICE_ATTR_RO(_name, _sysfs_name) \
++ struct device_attribute dev_attr_##_name = \
++ __ATTR(_sysfs_name, 0444, _name##_show, NULL)
++
++#define ALLY_DEVICE_ATTR_WO(_name, _sysfs_name) \
++ struct device_attribute dev_attr_##_name = \
++ __ATTR(_sysfs_name, 0200, NULL, _name##_store)
++
++/* response curve macros */
++#define ALLY_RESP_CURVE_SHOW(_name, _point_n) \
++ static ssize_t _name##_show(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
++ { \
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg; \
++ int idx = (_point_n - 1) * 2; \
++ if (!drvdata.gamepad_cfg) \
++ return -ENODEV; \
++ return sysfs_emit( \
++ buf, "%d %d\n", \
++ ally_cfg->response_curve[ally_cfg->mode] \
++ [btn_pair_side_left][idx], \
++ ally_cfg->response_curve[ally_cfg->mode] \
++ [btn_pair_side_right] \
++ [idx + 1]); \
++ }
++
++#define ALLY_RESP_CURVE_STORE(_name, _side, _point_n) \
++ static ssize_t _name##_store(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++ { \
++ int ret = __gamepad_store_response_curve( \
++ dev, buf, btn_pair_side_##_side, _point_n); \
++ if (ret < 0) \
++ return ret; \
++ return count; \
++ }
++
++/* _point_n must start at 1 */
++#define ALLY_JS_RC_POINT(_side, _point_n, _sysfs_label) \
++ ALLY_RESP_CURVE_SHOW(rc_point_##_side##_##_point_n, _point_n); \
++ ALLY_RESP_CURVE_STORE(rc_point_##_side##_##_point_n, _side, _point_n); \
++ ALLY_DEVICE_ATTR_RW(rc_point_##_side##_##_point_n, \
++ _sysfs_label##_point_n)
++
++/* deadzone macros */
++#define ALLY_AXIS_DEADZONE_SHOW(_axis) \
++ static ssize_t _axis##_deadzone_show( \
++ struct device *dev, struct device_attribute *attr, char *buf) \
++ { \
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg; \
++ int side, is_tr; \
++ if (!drvdata.gamepad_cfg) \
++ return -ENODEV; \
++ is_tr = _axis > xpad_axis_xy_right; \
++ side = _axis == xpad_axis_xy_right || \
++ _axis == xpad_axis_z_right ? \
++ 2 : \
++ 0; \
++ return sysfs_emit( \
++ buf, "%d %d\n", \
++ ally_cfg->deadzones[ally_cfg->mode][is_tr][side], \
++ ally_cfg->deadzones[ally_cfg->mode][is_tr][side + 1]); \
++ }
++
++#define ALLY_AXIS_DEADZONE_STORE(_axis) \
++ static ssize_t _axis##_deadzone_store(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++ { \
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg; \
++ if (!drvdata.gamepad_cfg) \
++ return -ENODEV; \
++ int ret = __gamepad_store_deadzones(ally_cfg, _axis, buf); \
++ if (ret < 0) \
++ return ret; \
++ return count; \
++ }
++
++#define ALLY_AXIS_DEADZONE(_axis, _sysfs_label) \
++ ALLY_AXIS_DEADZONE_SHOW(_axis); \
++ ALLY_AXIS_DEADZONE_STORE(_axis); \
++ ALLY_DEVICE_ATTR_RW(_axis##_deadzone, _sysfs_label)
++
++/* button specific macros */
++#define ALLY_BTN_SHOW(_fname, _pair, _side, _secondary) \
++ static ssize_t _fname##_show(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
++ { \
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg; \
++ if (!drvdata.gamepad_cfg) \
++ return -ENODEV; \
++ return sysfs_emit(buf, "%s\n", \
++ __btn_map_to_string(ally_cfg, _pair, _side, \
++ _secondary)); \
++ }
++
++#define ALLY_BTN_STORE(_fname, _pair, _side, _secondary) \
++ static ssize_t _fname##_store(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++ { \
++ struct ally_gamepad_cfg *ally_cfg = drvdata.gamepad_cfg; \
++ if (!drvdata.gamepad_cfg) \
++ return -ENODEV; \
++ int ret = __gamepad_mapping_store(ally_cfg, buf, _pair, _side, \
++ _secondary); \
++ if (ret < 0) \
++ return ret; \
++ return count; \
++ }
++
++#define ALLY_BTN_TURBO_SHOW(_fname, _pair, _side) \
++ static ssize_t _fname##_turbo_show( \
++ struct device *dev, struct device_attribute *attr, char *buf) \
++ { \
++ return sysfs_emit(buf, "%d\n", \
++ __gamepad_turbo_show(dev, _pair, _side)); \
++ }
++
++#define ALLY_BTN_TURBO_STORE(_fname, _pair, _side) \
++ static ssize_t _fname##_turbo_store(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++ { \
++ int ret = __gamepad_turbo_store(dev, buf, _pair, _side); \
++ if (ret < 0) \
++ return ret; \
++ return count; \
++ }
++
++#define ALLY_BTN_ATTRS_GROUP(_name, _fname) \
++ static struct attribute *_fname##_attrs[] = { \
++ &dev_attr_##_fname.attr, &dev_attr_##_fname##_macro.attr, \
++ &dev_attr_##_fname##_turbo.attr, NULL \
++ }; \
++ static const struct attribute_group _fname##_attr_group = { \
++ .name = __stringify(_name), \
++ .attrs = _fname##_attrs, \
++ }
++
++#define ALLY_BTN_MAPPING(_fname, _pair, _side) \
++ ALLY_BTN_SHOW(btn_mapping_##_fname, _pair, _side, false); \
++ ALLY_BTN_STORE(btn_mapping_##_fname, _pair, _side, false); \
++ ALLY_BTN_SHOW(btn_mapping_##_fname##_macro, _pair, _side, true); \
++ ALLY_BTN_STORE(btn_mapping_##_fname##_macro, _pair, _side, true); \
++ ALLY_BTN_TURBO_SHOW(btn_mapping_##_fname, _pair, _side); \
++ ALLY_BTN_TURBO_STORE(btn_mapping_##_fname, _pair, _side); \
++ ALLY_DEVICE_ATTR_RW(btn_mapping_##_fname, remap); \
++ ALLY_DEVICE_ATTR_RW(btn_mapping_##_fname##_macro, macro_remap); \
++ ALLY_DEVICE_ATTR_RW(btn_mapping_##_fname##_turbo, turbo); \
++ ALLY_BTN_ATTRS_GROUP(btn_##_fname, btn_mapping_##_fname)
++
++/* calibration macros */
++#define ALLY_CAL_STORE(_fname, _axis) \
++ static ssize_t _fname##_store(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++ { \
++ int ret = __gamepad_cal_store(dev, buf, _axis); \
++ if (ret < 0) \
++ return ret; \
++ return count; \
++ }
++
++#define ALLY_CAL_SHOW(_fname, _axis) \
++ static ssize_t _fname##_show(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
++ { \
++ return __gamepad_cal_show(dev, buf, _axis); \
++ }
++
++#define ALLY_CAL_ATTR(_fname, _axis, _sysfs_label) \
++ ALLY_CAL_STORE(_fname, _axis); \
++ ALLY_CAL_SHOW(_fname, _axis); \
++ ALLY_DEVICE_ATTR_RW(_fname, _sysfs_label)
++
++#define ALLY_CAL_RESET_STORE(_fname, _axis) \
++ static ssize_t _fname##_store(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++ { \
++ int ret = __gamepad_cal_reset(dev, buf, _axis); \
++ if (ret < 0) \
++ return ret; \
++ return count; \
++ }
++
++#define ALLY_CAL_RESET_ATTR(_fname, _axis, _sysfs_label) \
++ ALLY_CAL_RESET_STORE(_fname, _axis); \
++ ALLY_DEVICE_ATTR_WO(_fname, _sysfs_label)
++
++/*
++ * The following blocks of packets exist to make setting a default boot config
++ * easier. They were directly captured from setting the gamepad up.
++ */
++
++/* Default blocks for the xpad mode */
++static const u8 XPAD_DEF1[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x05, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8c, 0x88, 0x76, 0x00, 0x00
++};
++static const u8 XPAD_DEF2[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00,
++ 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0d, 0x00, 0x00, 0x00
++};
++static const u8 XPAD_DEF3[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 XPAD_DEF4[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 XPAD_DEF5[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00, 0x00
++};
++static const u8 XPAD_DEF6[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x4d, 0x00, 0x00, 0x00,
++ 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x05, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 XPAD_DEF7[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 XPAD_DEF8[MAPPING_BLOCK_LEN] = {
++ 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 XPAD_DEF9[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++
++/* default blocks for the wasd mode */
++static const u8 WASD_DEF1[MAPPING_BLOCK_LEN] = {
++ 0x02, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x05, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8c, 0x88, 0x76, 0x00, 0x00
++};
++static const u8 WASD_DEF2[MAPPING_BLOCK_LEN] = {
++ 0x02, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0d, 0x00, 0x00, 0x00
++};
++static const u8 WASD_DEF3[MAPPING_BLOCK_LEN] = {
++ 0x02, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 WASD_DEF4[MAPPING_BLOCK_LEN] = {
++ 0x02, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 WASD_DEF5[MAPPING_BLOCK_LEN] = {
++ 0x02, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00, 0x00
++};
++static const u8 WASD_DEF6[MAPPING_BLOCK_LEN] = {
++ 0x02, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x4d, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x05, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 WASD_DEF7[MAPPING_BLOCK_LEN] = {
++ 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 WASD_DEF8[MAPPING_BLOCK_LEN] = {
++ 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++static const u8 WASD_DEF9[MAPPING_BLOCK_LEN] = {
++ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, 0x0d, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++
++/*
++ * the xpad_mode is used inside the mode setting packet and is used
++ * for indexing (xpad_mode - 1)
++ */
++enum xpad_mode {
++ xpad_mode_game = 0x01,
++ xpad_mode_wasd = 0x02,
++ xpad_mode_mouse = 0x03,
++};
++
++/* the xpad_cmd determines which feature is set or queried */
++enum xpad_cmd {
++ xpad_cmd_set_mode = 0x01,
++ xpad_cmd_set_mapping = 0x02,
++ xpad_cmd_set_js_dz = 0x04, /* deadzones */
++ xpad_cmd_set_tr_dz = 0x05, /* deadzones */
++ xpad_cmd_set_vibe_intensity = 0x06,
++ xpad_cmd_set_leds = 0x08,
++ xpad_cmd_check_ready = 0x0A,
++ xpad_cmd_set_calibration = 0x0D,
++ xpad_cmd_set_turbo = 0x0F,
++ xpad_cmd_set_response_curve = 0x13,
++ xpad_cmd_set_adz = 0x18,
++};
++
++/* the xpad_cmd determines which feature is set or queried */
++enum xpad_cmd_len {
++ xpad_cmd_len_mode = 0x01,
++ xpad_cmd_len_mapping = 0x2c,
++ xpad_cmd_len_deadzone = 0x04,
++ xpad_cmd_len_vibe_intensity = 0x02,
++ xpad_cmd_len_leds = 0x0C,
++ xpad_cmd_len_calibration2 = 0x01,
++ xpad_cmd_len_calibration3 = 0x01,
++ xpad_cmd_len_turbo = 0x20,
++ xpad_cmd_len_response_curve = 0x09,
++ xpad_cmd_len_adz = 0x02,
++};
++
++/*
++ * the xpad_mode is used in various set and query HID packets and is
++ * used for indexing (xpad_axis - 1)
++ */
++enum xpad_axis {
++ xpad_axis_xy_left = 0x01,
++ xpad_axis_xy_right = 0x02,
++ xpad_axis_z_left = 0x03,
++ xpad_axis_z_right = 0x04,
++};
++
++enum btn_pair {
++ btn_pair_dpad_u_d = 0x01,
++ btn_pair_dpad_l_r = 0x02,
++ btn_pair_ls_rs = 0x03,
++ btn_pair_lb_rb = 0x04,
++ btn_pair_a_b = 0x05,
++ btn_pair_x_y = 0x06,
++ btn_pair_view_menu = 0x07,
++ btn_pair_m1_m2 = 0x08,
++ btn_pair_lt_rt = 0x09,
++};
++
++enum btn_pair_side {
++ btn_pair_side_left = 0x00,
++ btn_pair_side_right = 0x01,
++};
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
-index 37e6d25593c2..af57a5f03193 100644
+index 37e6d25593c2..9f83a770de8d 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
-@@ -492,12 +492,19 @@ static void asus_kbd_backlight_work(struct work_struct *work)
+@@ -52,6 +52,10 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
+ #define FEATURE_KBD_LED_REPORT_ID1 0x5d
+ #define FEATURE_KBD_LED_REPORT_ID2 0x5e
+
++#define ALLY_CFG_INTF_IN_ADDRESS 0x83
++#define ALLY_CFG_INTF_OUT_ADDRESS 0x04
++#define ALLY_X_INTERFACE_ADDRESS 0x87
++
+ #define SUPPORT_KBD_BACKLIGHT BIT(0)
+
+ #define MAX_TOUCH_MAJOR 8
+@@ -84,6 +88,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
+ #define QUIRK_MEDION_E1239T BIT(10)
+ #define QUIRK_ROG_NKEY_KEYBOARD BIT(11)
+ #define QUIRK_ROG_CLAYMORE_II_KEYBOARD BIT(12)
++#define QUIRK_ROG_ALLY_XPAD BIT(13)
+
+ #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
+ QUIRK_NO_INIT_REPORTS | \
+@@ -492,12 +497,19 @@ static void asus_kbd_backlight_work(struct work_struct *work)
*/
static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev)
{
@@ -118,71 +2942,133 @@ index 37e6d25593c2..af57a5f03193 100644
ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS,
ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value);
hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value);
+@@ -996,6 +1008,17 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
+
+ drvdata->quirks = id->driver_data;
+
++ /* Ignore these endpoints as they will be used by other drivers */
++ if (drvdata->quirks & QUIRK_ROG_ALLY_XPAD) {
++ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
++ struct usb_host_endpoint *ep = intf->cur_altsetting->endpoint;
++
++ if (ep->desc.bEndpointAddress == ALLY_X_INTERFACE_ADDRESS ||
++ ep->desc.bEndpointAddress == ALLY_CFG_INTF_IN_ADDRESS ||
++ ep->desc.bEndpointAddress == ALLY_CFG_INTF_OUT_ADDRESS)
++ return -ENODEV;
++ }
++
+ /*
+ * T90CHI's keyboard dock returns same ID values as T100CHI's dock.
+ * Thus, identify T90CHI dock with product name string.
+@@ -1247,6 +1270,12 @@ static const struct hid_device_id asus_devices[] = {
+ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY),
++ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD},
++ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
++ USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X),
++ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD },
++ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
++ USB_DEVICE_ID_ASUSTEK_ROG_AZOTH_KEYBOARD),
+ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD),
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
-index 72d56ee7ce1b..8291699ec56c 100644
+index 72d56ee7ce1b..57f1f1bc5eb6 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
-@@ -209,6 +209,7 @@
+@@ -209,7 +209,10 @@
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 0x19b6
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3 0x1a30
#define USB_DEVICE_ID_ASUSTEK_ROG_Z13_LIGHTBAR 0x18c6
+#define USB_DEVICE_ID_ASUSTEK_ROG_RAIKIRI_PAD 0x1abb
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY 0x1abe
++#define USB_DEVICE_ID_ASUSTEK_ROG_AZOTH_KEYBOARD 0x1a83
++#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c
#define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b
#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869
+
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
-index 665fa9524986..b4a5a5bec7f3 100644
+index ddfccc226751..d13c4085c228 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
-@@ -265,6 +265,18 @@ config ASUS_WIRELESS
+@@ -265,6 +265,19 @@ config ASUS_WIRELESS
If you choose to compile this driver as a module the module will be
called asus-wireless.
-+config ASUS_BIOS
-+ tristate "ASUS BIOS Driver"
++config ASUS_ARMOURY
++ tristate "ASUS Armoury (firmware) Driver"
+ depends on ACPI_WMI
+ depends on ASUS_WMI
+ select FW_ATTR_CLASS
+ help
+ Say Y here if you have a WMI aware Asus laptop and would like to use the
-+ firmware_attributes API.
++ firmware_attributes API to control various settings typically exposed in
++ the ASUS Armoury Crate application available on Windows.
+
+ To compile this driver as a module, choose M here: the module will
-+ be called asus-bios.
++ be called asus-armoury.
+
config ASUS_WMI
tristate "ASUS WMI Driver"
depends on ACPI_WMI
-@@ -276,6 +288,8 @@ config ASUS_WMI
+@@ -276,6 +289,7 @@ config ASUS_WMI
depends on HOTPLUG_PCI
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on SERIO_I8042 || SERIO_I8042 = n
-+ select ASUS_BIOS
-+ select ASUS_WMI_BIOS
++ select ASUS_ARMOURY
select INPUT_SPARSEKMAP
select LEDS_CLASS
select NEW_LEDS
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
-index e1b142947067..d9b5b3f3b241 100644
+index e1b142947067..fe3e7e7dede8 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o
# ASUS
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
obj-$(CONFIG_ASUS_WIRELESS) += asus-wireless.o
-+obj-$(CONFIG_ASUS_BIOS) += asus-bios.o
++obj-$(CONFIG_ASUS_ARMOURY) += asus-armoury.o
obj-$(CONFIG_ASUS_WMI) += asus-wmi.o
obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o
obj-$(CONFIG_ASUS_TF103C_DOCK) += asus-tf103c-dock.o
-diff --git a/drivers/platform/x86/asus-bios.c b/drivers/platform/x86/asus-bios.c
+diff --git a/drivers/platform/x86/amd/pmf/pmf-quirks.c b/drivers/platform/x86/amd/pmf/pmf-quirks.c
+index 0b2eb0ae85fe..460444cda1b2 100644
+--- a/drivers/platform/x86/amd/pmf/pmf-quirks.c
++++ b/drivers/platform/x86/amd/pmf/pmf-quirks.c
+@@ -29,6 +29,14 @@ static const struct dmi_system_id fwbug_list[] = {
+ },
+ .driver_data = &quirk_no_sps_bug,
+ },
++ {
++ .ident = "ROG Ally X",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "RC72LA"),
++ },
++ .driver_data = &quirk_no_sps_bug,
++ },
+ {}
+ };
+
+@@ -48,4 +56,3 @@ void amd_pmf_quirks_init(struct amd_pmf_dev *dev)
+ dmi_id->ident);
+ }
+ }
+-
+diff --git a/drivers/platform/x86/asus-armoury.c b/drivers/platform/x86/asus-armoury.c
new file mode 100644
-index 000000000000..bd4c408fd062
+index 000000000000..aa784b6b9483
--- /dev/null
-+++ b/drivers/platform/x86/asus-bios.c
-@@ -0,0 +1,983 @@
++++ b/drivers/platform/x86/asus-armoury.c
+@@ -0,0 +1,1049 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
-+ * Asus BIOS attributes driver
++ * Asus Armoury (WMI) attributes driver. This driver uses the fw_attributes
++ * class to expose the various WMI functions that many gaming and some
++ * non-gaming ASUS laptops have available.
++ * These typically don't fit anywhere else in the sysfs such as under LED class,
++ * hwmon or other, and are set in Windows using the ASUS Armoury Crate tool.
+ *
+ * Copyright(C) 2010 Intel Corporation.
+ * Copyright(C) 2024-2024 Luke Jones <luke@ljones.dev>
@@ -201,18 +3087,11 @@ index 000000000000..bd4c408fd062
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/kernel.h>
-+#include "asus-bios.h"
-+#include "asus-wmi.h"
++#include "asus-armoury.h"
+#include "firmware_attributes_class.h"
+
-+MODULE_AUTHOR("Luke Jones <luke@ljones.dev>");
-+MODULE_DESCRIPTION("ASUS BIOS Configuration Driver");
-+MODULE_LICENSE("GPL");
-+
+#define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
+
-+MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
-+
+#define ASUS_MINI_LED_MODE_MASK 0x03
+/* Standard modes for devices with only on/off */
+#define ASUS_MINI_LED_OFF 0x00
@@ -247,14 +3126,18 @@ index 000000000000..bd4c408fd062
+#define NVIDIA_BOOST_MAX 25
+#define NVIDIA_TEMP_MIN 75
+#define NVIDIA_TEMP_MAX 87
-+#define NVIDIA_GPU_POWER_MAX 70
++#define NVIDIA_POWER_MIN 0
++#define NVIDIA_POWER_MAX 70
++#define NVIDIA_POWER_DEFAULT 70
+
+/* Tunables provided by ASUS for gaming laptops */
+struct rog_tunables {
+ u32 cpu_default;
++ u32 cpu_min;
+ u32 cpu_max;
+
+ u32 platform_default;
++ u32 platform_min;
+ u32 platform_max;
+
+ u32 ppt_pl1_spl; // cpu
@@ -264,13 +3147,20 @@ index 000000000000..bd4c408fd062
+ u32 ppt_fppt; // cpu
+
+ u32 nv_boost_default;
++ u32 nv_boost_min;
+ u32 nv_boost_max;
+ u32 nv_dynamic_boost;
+
+ u32 nv_temp_default;
++ u32 nv_temp_min;
+ u32 nv_temp_max;
+ u32 nv_temp_target;
+
++ u32 dgpu_tgp_default;
++ u32 dgpu_tgp_min;
++ u32 dgpu_tgp_max;
++ u32 dgpu_tgp;
++
+ u32 min_perf_cores;
+ u32 max_perf_cores;
+ u32 max_power_cores;
@@ -278,32 +3168,46 @@ index 000000000000..bd4c408fd062
+
+static const struct class *fw_attr_class;
+
-+struct asus_bios_priv {
++struct asus_armoury_priv {
+ struct device *fw_attr_dev;
+ struct kset *fw_attr_kset;
+
+ struct rog_tunables *rog_tunables;
+ u32 mini_led_dev_id;
+ u32 gpu_mux_dev_id;
-+ bool dgpu_disable_available;
-+ bool egpu_enable_available;
+
+ struct mutex mutex;
-+} asus_bios = {
-+ .mutex = __MUTEX_INITIALIZER(asus_bios.mutex),
+};
+
-+static struct fw_attrs_group {
++static struct asus_armoury_priv asus_armoury = {
++ .mutex = __MUTEX_INITIALIZER(asus_armoury.mutex)
++};
++
++struct fw_attrs_group {
+ u32 pending_reboot;
-+} fw_attrs = {
++};
++
++static struct fw_attrs_group fw_attrs = {
+ .pending_reboot = 0,
+};
+
-+/* WMI helper methods */
++struct asus_attr_group {
++ const struct attribute_group *attr_group;
++ u32 wmi_devid;
++};
++
++/**
++ * asus_wmi_is_present() - determine if a WMI interface is available.
++ * @dev_id: The WMI function ID to use.
++ *
++ * Returns: Boolean state. Note that an error will also return false.
++ */
+static bool asus_wmi_is_present(u32 dev_id)
+{
+ u32 retval;
-+ int status = asus_wmi_get_devstate_dsts(dev_id, &retval);
++ int status;
++
++ status = asus_wmi_get_devstate_dsts(dev_id, &retval);
+ pr_debug("%s called (0x%08x), retval: 0x%08x\n", __func__, dev_id, retval);
+
+ return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT);
@@ -312,47 +3216,66 @@ index 000000000000..bd4c408fd062
+static void asus_set_reboot_and_signal_event(void)
+{
+ fw_attrs.pending_reboot = 1;
-+ kobject_uevent(&asus_bios.fw_attr_dev->kobj, KOBJ_CHANGE);
++ kobject_uevent(&asus_armoury.fw_attr_dev->kobj, KOBJ_CHANGE);
+}
+
+static ssize_t pending_reboot_show(struct kobject *kobj,
-+ struct kobj_attribute *attr,
-+ char *buf)
++ struct kobj_attribute *attr,
++ char *buf)
+{
-+ return sysfs_emit(buf, "%d\n", fw_attrs.pending_reboot);
++ return sysfs_emit(buf, "%u\n", fw_attrs.pending_reboot);
+}
+
+static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
+
-+static bool asus_bios_requires_reboot(struct kobj_attribute *attr) {
++static bool asus_bios_requires_reboot(struct kobj_attribute *attr)
++{
+ return !strcmp(attr->attr.name, "gpu_mux_mode") ||
++ !strcmp(attr->attr.name, "cores_performance") ||
++ !strcmp(attr->attr.name, "cores_efficiency") ||
+ !strcmp(attr->attr.name, "panel_hd_mode");
+}
+
-+/*
-+ * Generic store function for use with many ROG tunables
++/**
++ * attr_int_store() - Generic store function for use with most WMI functions.
++ * @kobj: Pointer to the driver object.
++ * @kobj_attribute: Pointer the the attribute calling this function.
++ * @buf: The buffer to read from, this is parsed to `int` type.
++ * @count:
++ * @min: Minimum accepted value. Below this returns -EINVAL.
++ * @max: Maximum accepted value. Above this returns -EINVAL.
++ * @store_value: Pointer to where the parsed value should be stored.
++ * @wmi_dev: The WMI function ID to use.
++ *
++ * The WMI functions available on most ASUS laptops return a 1 as "success", and
++ * a 0 as failed. However some functions can return n > 1 for additional errors.
++ * attr_int_store() currently treats all values which are not 1 as errors, ignoring
++ * the possible differences in WMI error returns.
++ *
++ * Returns: Either count, or an error.
+ */
+static ssize_t attr_int_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count,
+ u32 min, u32 max, u32 *store_value, u32 wmi_dev)
+{
-+ int result, value;
++ u32 result, value;
++ int err;
+
-+ result = kstrtoint(buf, 10, &value);
-+ if (result)
-+ return result;
++ err = kstrtouint(buf, 10, &value);
++ if (err)
++ return err;
+
+ if (value < min || value > max)
+ return -EINVAL;
+
-+ asus_wmi_set_devstate(wmi_dev, value, &result);
-+ if (result) {
-+ pr_err("Failed to set %s: %d\n", attr->attr.name, result);
-+ return result;
++ err = asus_wmi_set_devstate(wmi_dev, value, &result);
++ if (err) {
++ pr_err("Failed to set %s: %d\n", attr->attr.name, err);
++ return err;
+ }
+
-+ if (result > 1) {
++ if (result != 1) {
+ pr_err("Failed to set %s (result): 0x%x\n", attr->attr.name, result);
+ return -EIO;
+ }
@@ -374,7 +3297,7 @@ index 000000000000..bd4c408fd062
+ u32 value;
+ int err;
+
-+ err = asus_wmi_get_devstate_dsts(asus_bios.mini_led_dev_id, &value);
++ err = asus_wmi_get_devstate_dsts(asus_armoury.mini_led_dev_id, &value);
+ if (err)
+ return err;
+
@@ -384,7 +3307,7 @@ index 000000000000..bd4c408fd062
+ * Remap the mode values to match previous generation mini-led. The last gen
+ * WMI 0 == off, while on this version WMI 2 ==off (flipped).
+ */
-+ if (asus_bios.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) {
++ if (asus_armoury.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) {
+ switch (value) {
+ case ASUS_MINI_LED_2024_WEAK:
+ value = ASUS_MINI_LED_ON;
@@ -398,7 +3321,7 @@ index 000000000000..bd4c408fd062
+ }
+ }
+
-+ return sysfs_emit(buf, "%d\n", value);
++ return sysfs_emit(buf, "%u\n", value);
+}
+
+static ssize_t mini_led_mode_current_value_store(struct kobject *kobj,
@@ -408,14 +3331,14 @@ index 000000000000..bd4c408fd062
+ int result, err;
+ u32 mode;
+
-+ result = kstrtou32(buf, 10, &mode);
-+ if (result)
-+ return result;
++ err = kstrtou32(buf, 10, &mode);
++ if (err)
++ return err;
+
-+ if (asus_bios.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE &&
++ if (asus_armoury.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE &&
+ mode > ASUS_MINI_LED_ON)
+ return -EINVAL;
-+ if (asus_bios.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 &&
++ if (asus_armoury.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 &&
+ mode > ASUS_MINI_LED_STRONG_MODE)
+ return -EINVAL;
+
@@ -423,7 +3346,7 @@ index 000000000000..bd4c408fd062
+ * Remap the mode values so expected behaviour is the same as the last
+ * generation of mini-LED with 0 == off, 1 == on.
+ */
-+ if (asus_bios.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) {
++ if (asus_armoury.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) {
+ switch (mode) {
+ case ASUS_MINI_LED_OFF:
+ mode = ASUS_MINI_LED_2024_OFF;
@@ -437,13 +3360,13 @@ index 000000000000..bd4c408fd062
+ }
+ }
+
-+ err = asus_wmi_set_devstate(asus_bios.mini_led_dev_id, mode, &result);
++ err = asus_wmi_set_devstate(asus_armoury.mini_led_dev_id, mode, &result);
+ if (err) {
+ pr_warn("Failed to set mini-LED: %d\n", err);
+ return err;
+ }
+
-+ if (result > 1) {
++ if (result != 1) {
+ pr_warn("Failed to set mini-LED mode (result): 0x%x\n", result);
+ return -EIO;
+ }
@@ -456,7 +3379,7 @@ index 000000000000..bd4c408fd062
+static ssize_t mini_led_mode_possible_values_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
-+ switch (asus_bios.mini_led_dev_id) {
++ switch (asus_armoury.mini_led_dev_id) {
+ case ASUS_WMI_DEVID_MINI_LED_MODE:
+ return sysfs_emit(buf, "0;1\n");
+ case ASUS_WMI_DEVID_MINI_LED_MODE2:
@@ -482,18 +3405,18 @@ index 000000000000..bd4c408fd062
+ if (optimus > 1)
+ return -EINVAL;
+
-+ if (asus_bios.dgpu_disable_available) {
++ if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU)) {
+ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_DGPU, &result);
+ if (err)
+ return err;
-+ if (err && !optimus) {
++ if (result && !optimus) {
+ err = -ENODEV;
+ pr_warn("Can not switch MUX to dGPU mode when dGPU is disabled: %d\n", err);
+ return err;
+ }
+ }
+
-+ if (asus_bios.egpu_enable_available) {
++ if (asus_wmi_is_present(ASUS_WMI_DEVID_EGPU)) {
+ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_EGPU, &result);
+ if (err)
+ return err;
@@ -504,14 +3427,14 @@ index 000000000000..bd4c408fd062
+ }
+ }
+
-+ err = asus_wmi_set_devstate(asus_bios.gpu_mux_dev_id, optimus, &result);
++ err = asus_wmi_set_devstate(asus_armoury.gpu_mux_dev_id, optimus, &result);
+ if (err) {
-+ pr_err("%s Failed to set GPU MUX mode: %d\nn", __func__, err);
++ pr_err("Failed to set GPU MUX mode: %d\nn", err);
+ return err;
+ }
+ /* !1 is considered a fail by ASUS */
+ if (result != 1) {
-+ pr_warn("%s Failed to set GPU MUX mode (result): 0x%x\n", __func__, result);
++ pr_warn("Failed to set GPU MUX mode (result): 0x%x\n", result);
+ return -EIO;
+ }
+
@@ -519,7 +3442,7 @@ index 000000000000..bd4c408fd062
+
+ return count;
+}
-+WMI_SHOW_INT(gpu_mux_mode_current_value, "%d\n", asus_bios.gpu_mux_dev_id);
++WMI_SHOW_INT(gpu_mux_mode_current_value, "%d\n", asus_armoury.gpu_mux_dev_id);
+ATTR_GROUP_BOOL_CUSTOM(gpu_mux_mode, "gpu_mux_mode", "Set the GPU display MUX mode");
+
+/*
@@ -535,15 +3458,15 @@ index 000000000000..bd4c408fd062
+ int result, err;
+ u32 disable;
+
-+ result = kstrtou32(buf, 10, &disable);
-+ if (result)
-+ return result;
++ err = kstrtou32(buf, 10, &disable);
++ if (err)
++ return err;
+
+ if (disable > 1)
+ return -EINVAL;
+
-+ if (asus_bios.gpu_mux_dev_id) {
-+ err = asus_wmi_get_devstate_dsts(asus_bios.gpu_mux_dev_id, &result);
++ if (asus_armoury.gpu_mux_dev_id) {
++ err = asus_wmi_get_devstate_dsts(asus_armoury.gpu_mux_dev_id, &result);
+ if (err)
+ return err;
+ if (!result && disable) {
@@ -559,7 +3482,7 @@ index 000000000000..bd4c408fd062
+ return err;
+ }
+
-+ if (result > 1) {
++ if (result != 1) {
+ pr_warn("Failed to set dgpu disable (result): 0x%x\n", result);
+ return -EIO;
+ }
@@ -592,8 +3515,8 @@ index 000000000000..bd4c408fd062
+ return err;
+ }
+
-+ if (asus_bios.gpu_mux_dev_id) {
-+ err = asus_wmi_get_devstate_dsts(asus_bios.gpu_mux_dev_id, &result);
++ if (asus_armoury.gpu_mux_dev_id) {
++ err = asus_wmi_get_devstate_dsts(asus_armoury.gpu_mux_dev_id, &result);
+ if (err) {
+ pr_warn("Failed to get gpu mux status: %d\n", result);
+ return result;
@@ -611,7 +3534,7 @@ index 000000000000..bd4c408fd062
+ return err;
+ }
+
-+ if (result > 1) {
++ if (result != 1) {
+ pr_warn("Failed to set egpu state (retval): 0x%x\n", result);
+ return -EIO;
+ }
@@ -737,22 +3660,22 @@ index 000000000000..bd4c408fd062
+}
+ATTR_GROUP_ENUM_CUSTOM(apu_mem, "apu_mem", "Set the available system memory for the APU to use");
+
-+static int asus_bios_set_max_cores(void)
++static int init_max_cpu_cores(void)
+{
+ u32 cores;
+ int err;
+
-+ asus_bios.rog_tunables->min_perf_cores = 4;
-+ asus_bios.rog_tunables->max_perf_cores = 4;
-+ asus_bios.rog_tunables->max_power_cores = 8;
++ asus_armoury.rog_tunables->min_perf_cores = 4;
++ asus_armoury.rog_tunables->max_perf_cores = 4;
++ asus_armoury.rog_tunables->max_power_cores = 8;
+
+ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES_MAX, &cores);
+ if (err)
+ return err;
+
+ cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT;
-+ asus_bios.rog_tunables->max_power_cores = (cores & 0xff00) >> 8;
-+ asus_bios.rog_tunables->max_perf_cores = cores & 0xff;
++ asus_armoury.rog_tunables->max_power_cores = (cores & 0xff00) >> 8;
++ asus_armoury.rog_tunables->max_perf_cores = cores & 0xff;
+
+ return 0;
+}
@@ -769,12 +3692,12 @@ index 000000000000..bd4c408fd062
+ case CPU_CORE_DEFAULT:
+ case CPU_CORE_MAX:
+ if (core_type == CPU_CORE_PERF)
-+ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->max_perf_cores);
++ return sysfs_emit(buf, "%d\n", asus_armoury.rog_tunables->max_perf_cores);
+ else
-+ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->max_power_cores);
++ return sysfs_emit(buf, "%d\n", asus_armoury.rog_tunables->max_power_cores);
+ case CPU_CORE_MIN:
+ if (core_type == CPU_CORE_PERF)
-+ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->min_perf_cores);
++ return sysfs_emit(buf, "%d\n", asus_armoury.rog_tunables->min_perf_cores);
+ else
+ return sysfs_emit(buf, "%d\n", 0);
+ default:
@@ -805,11 +3728,11 @@ index 000000000000..bd4c408fd062
+ return result;
+
+ if (core_type == CPU_CORE_PERF) {
-+ min = asus_bios.rog_tunables->min_perf_cores;
-+ max = asus_bios.rog_tunables->max_perf_cores;
++ min = asus_armoury.rog_tunables->min_perf_cores;
++ max = asus_armoury.rog_tunables->max_perf_cores;
+ } else {
+ min = 0;
-+ max = asus_bios.rog_tunables->max_power_cores;
++ max = asus_armoury.rog_tunables->max_power_cores;
+ }
+ if (cores < min || cores > max)
+ return -EINVAL;
@@ -828,12 +3751,12 @@ index 000000000000..bd4c408fd062
+
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_CORES, cores, &result);
+ if (err) {
-+ pr_warn("Failed to set perfromance core count: %d\n", err);
++ pr_warn("Failed to set CPU core count: %d\n", err);
+ return err;
+ }
+
+ if (result > 1) {
-+ pr_warn("Failed to set performance core count (result): 0x%x\n", result);
++ pr_warn("Failed to set CPU core count (result): 0x%x\n", result);
+ return -EIO;
+ }
+
@@ -872,13 +3795,16 @@ index 000000000000..bd4c408fd062
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
-+ int err = cores_current_value_store(kobj, attr, buf, CPU_CORE_PERF);
++ int err;
++
++ err = cores_current_value_store(kobj, attr, buf, CPU_CORE_PERF);
+ if (err)
+ return err;
+
+ return count;
+}
-+ATTR_GROUP_CORES_RW(cores_performance, "cores_performance", ASUS_WMI_DEVID_CORES, "Set the max available performance cores");
++ATTR_GROUP_CORES_RW(cores_performance, "cores_performance",
++ "Set the max available performance cores");
+
+static ssize_t cores_efficiency_min_value_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
@@ -908,142 +3834,147 @@ index 000000000000..bd4c408fd062
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
-+ int err = cores_current_value_store(kobj, attr, buf, CPU_CORE_POWER);
++ int err;
++
++ err = cores_current_value_store(kobj, attr, buf, CPU_CORE_POWER);
+ if (err)
+ return err;
+
+ return count;
+}
-+ATTR_GROUP_CORES_RW(cores_efficiency, "cores_efficiency", ASUS_WMI_DEVID_CORES, "Set the max available efficiency cores");
++ATTR_GROUP_CORES_RW(cores_efficiency, "cores_efficiency",
++ "Set the max available efficiency cores");
+
+/* Simple attribute creation */
-+ATTR_GROUP_ENUM_INT_RW(thermal_policy, "thermal_policy", ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, 0, 3, "0;1;2", "Fan stuff todo");
-+ATTR_GROUP_PPT_RW(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL,
-+ cpu_default, 5, cpu_max, 1, "Set the CPU slow package limit");
-+ATTR_GROUP_PPT_RW(ppt_pl2_sppt, "ppt_pl2_sppt", ASUS_WMI_DEVID_PPT_PL2_SPPT,
-+ cpu_default, 5, cpu_max, 1, "Set the CPU fast package limit");
-+ATTR_GROUP_PPT_RW(ppt_apu_sppt, "ppt_apu_sppt", ASUS_WMI_DEVID_PPT_APU_SPPT,
-+ platform_default, 5, platform_max, 1, "Set the CPU slow package limit");
-+ATTR_GROUP_PPT_RW(ppt_platform_sppt, "ppt_platform_sppt", ASUS_WMI_DEVID_PPT_PLAT_SPPT,
-+ platform_default, 5, platform_max, 1, "Set the CPU slow package limit");
-+ATTR_GROUP_PPT_RW(ppt_fppt, "ppt_fppt", ASUS_WMI_DEVID_PPT_FPPT,
-+ cpu_default, 5, cpu_max, 1, "Set the CPU slow package limit");
-+
-+ATTR_GROUP_PPT_RW(nv_dynamic_boost, "nv_dynamic_boost", ASUS_WMI_DEVID_NV_DYN_BOOST,
-+ nv_boost_default, 5, nv_boost_max, 1, "Set the Nvidia dynamic boost limit");
-+ATTR_GROUP_PPT_RW(nv_temp_target, "nv_temp_target", ASUS_WMI_DEVID_NV_THERM_TARGET,
-+ nv_temp_default, 75, nv_temp_max, 1, "Set the Nvidia max thermal limit");
-+ATTR_GROUP_INT_VALUE_ONLY_RO(dgpu_base_tgp, "dgpu_base_tgp", ASUS_WMI_DEVID_DGPU_BASE_TGP, "Read the base TGP value")
-+ATTR_GROUP_INT_RW(dgpu_tgp, "dgpu_tgp", ASUS_WMI_DEVID_DGPU_SET_TGP,
-+ 70, 0, NVIDIA_GPU_POWER_MAX, 1, "Set the additional TGP on top of the base TGP");
-+
-+ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE, 0, 0, "0;1;2", "Show the current mode of charging");
-+ATTR_GROUP_BOOL_RW(boot_sound, "boot_sound", ASUS_WMI_DEVID_BOOT_SOUND, "Set the boot POST sound");
-+ATTR_GROUP_BOOL_RW(mcu_powersave, "mcu_powersave", ASUS_WMI_DEVID_MCU_POWERSAVE, "Set MCU powersaving mode");
-+ATTR_GROUP_BOOL_RW(panel_od, "panel_overdrive", ASUS_WMI_DEVID_PANEL_OD, "Set the panel refresh overdrive");
-+ATTR_GROUP_BOOL_RW(panel_hd_mode, "panel_hd_mode", ASUS_WMI_DEVID_PANEL_HD, "Set the panel HD mode to UHD<0> or FHD<1>");
-+ATTR_GROUP_BOOL_RO(egpu_connected, "egpu_connected", ASUS_WMI_DEVID_EGPU_CONNECTED, "Show the eGPU connection status");
++ATTR_GROUP_ROG_TUNABLE(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL,
++ cpu_default, cpu_min, cpu_max, 1, "Set the CPU slow package limit");
++ATTR_GROUP_ROG_TUNABLE(ppt_pl2_sppt, "ppt_pl2_sppt", ASUS_WMI_DEVID_PPT_PL2_SPPT,
++ cpu_default, cpu_min, cpu_max, 1, "Set the CPU fast package limit");
++ATTR_GROUP_ROG_TUNABLE(ppt_apu_sppt, "ppt_apu_sppt", ASUS_WMI_DEVID_PPT_APU_SPPT,
++ platform_default, platform_min, platform_max, 1, "Set the CPU slow package limit");
++ATTR_GROUP_ROG_TUNABLE(ppt_platform_sppt, "ppt_platform_sppt", ASUS_WMI_DEVID_PPT_PLAT_SPPT,
++ platform_default, platform_min, platform_max, 1, "Set the CPU slow package limit");
++ATTR_GROUP_ROG_TUNABLE(ppt_fppt, "ppt_fppt", ASUS_WMI_DEVID_PPT_FPPT,
++ cpu_default, cpu_min, cpu_max, 1, "Set the CPU slow package limit");
++
++ATTR_GROUP_ROG_TUNABLE(nv_dynamic_boost, "nv_dynamic_boost", ASUS_WMI_DEVID_NV_DYN_BOOST,
++ nv_boost_default, nv_boost_min, nv_boost_max, 1, "Set the Nvidia dynamic boost limit");
++ATTR_GROUP_ROG_TUNABLE(nv_temp_target, "nv_temp_target", ASUS_WMI_DEVID_NV_THERM_TARGET,
++ nv_temp_default, nv_boost_min, nv_temp_max, 1, "Set the Nvidia max thermal limit");
++ATTR_GROUP_INT_VALUE_ONLY_RO(dgpu_base_tgp, "dgpu_base_tgp", ASUS_WMI_DEVID_DGPU_BASE_TGP,
++ "Read the base TGP value");
++ATTR_GROUP_ROG_TUNABLE(dgpu_tgp, "dgpu_tgp", ASUS_WMI_DEVID_DGPU_SET_TGP,
++ dgpu_tgp_default, dgpu_tgp_min, dgpu_tgp_max, 1,
++ "Set the additional TGP on top of the base TGP");
++
++ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE,
++ "0;1;2", "Show the current mode of charging");
++ATTR_GROUP_BOOL_RW(boot_sound, "boot_sound", ASUS_WMI_DEVID_BOOT_SOUND,
++ "Set the boot POST sound");
++ATTR_GROUP_BOOL_RW(mcu_powersave, "mcu_powersave", ASUS_WMI_DEVID_MCU_POWERSAVE,
++ "Set MCU powersaving mode");
++ATTR_GROUP_BOOL_RW(panel_od, "panel_overdrive", ASUS_WMI_DEVID_PANEL_OD,
++ "Set the panel refresh overdrive");
++ATTR_GROUP_BOOL_RW(panel_hd_mode, "panel_hd_mode", ASUS_WMI_DEVID_PANEL_HD,
++ "Set the panel HD mode to UHD<0> or FHD<1>");
++ATTR_GROUP_BOOL_RO(egpu_connected, "egpu_connected", ASUS_WMI_DEVID_EGPU_CONNECTED,
++ "Show the eGPU connection status");
++
++/* If an attribute does not require any special case handling add it here */
++static const struct asus_attr_group armoury_attr_groups[] = {
++ { &egpu_connected_attr_group, ASUS_WMI_DEVID_EGPU_CONNECTED },
++ { &egpu_enable_attr_group, ASUS_WMI_DEVID_EGPU },
++ { &dgpu_disable_attr_group, ASUS_WMI_DEVID_DGPU },
++
++ { &ppt_pl1_spl_attr_group, ASUS_WMI_DEVID_PPT_PL1_SPL },
++ { &ppt_pl2_sppt_attr_group, ASUS_WMI_DEVID_PPT_PL2_SPPT },
++ { &ppt_apu_sppt_attr_group, ASUS_WMI_DEVID_PPT_APU_SPPT },
++ { &ppt_platform_sppt_attr_group, ASUS_WMI_DEVID_PPT_PLAT_SPPT },
++ { &ppt_fppt_attr_group, ASUS_WMI_DEVID_PPT_FPPT },
++ { &nv_dynamic_boost_attr_group, ASUS_WMI_DEVID_NV_DYN_BOOST },
++ { &nv_temp_target_attr_group, ASUS_WMI_DEVID_NV_THERM_TARGET },
++ { &dgpu_base_tgp_attr_group, ASUS_WMI_DEVID_DGPU_BASE_TGP },
++ { &dgpu_tgp_attr_group, ASUS_WMI_DEVID_DGPU_SET_TGP },
++ { &apu_mem_attr_group, ASUS_WMI_DEVID_APU_MEM },
++ { &cores_efficiency_attr_group, ASUS_WMI_DEVID_CORES_MAX },
++ { &cores_performance_attr_group, ASUS_WMI_DEVID_CORES_MAX },
++
++ { &charge_mode_attr_group, ASUS_WMI_DEVID_CHARGE_MODE },
++ { &boot_sound_attr_group, ASUS_WMI_DEVID_BOOT_SOUND },
++ { &mcu_powersave_attr_group, ASUS_WMI_DEVID_MCU_POWERSAVE },
++ { &panel_od_attr_group, ASUS_WMI_DEVID_PANEL_OD },
++ { &panel_hd_mode_attr_group, ASUS_WMI_DEVID_PANEL_HD },
++};
+
+static int asus_fw_attr_add(void)
+{
-+ int ret;
-+ ret = fw_attributes_class_get(&fw_attr_class);
-+ if (ret)
++ int err;
++
++ err = fw_attributes_class_get(&fw_attr_class);
++ if (err)
+ goto fail_class_created;
-+ else
-+ asus_bios.fw_attr_dev = device_create(fw_attr_class, NULL,
-+ MKDEV(0, 0), NULL, "%s", DRIVER_NAME);
+
-+ if (IS_ERR(asus_bios.fw_attr_dev)) {
-+ ret = PTR_ERR(asus_bios.fw_attr_dev);
++ asus_armoury.fw_attr_dev = device_create(fw_attr_class, NULL,
++ MKDEV(0, 0), NULL, "%s", DRIVER_NAME);
++
++ if (IS_ERR(asus_armoury.fw_attr_dev)) {
++ err = PTR_ERR(asus_armoury.fw_attr_dev);
+ goto fail_class_created;
+ }
+
-+ asus_bios.fw_attr_kset = kset_create_and_add("attributes", NULL,
-+ &asus_bios.fw_attr_dev->kobj);
-+ if (!asus_bios.fw_attr_dev) {
-+ ret = -ENOMEM;
++ asus_armoury.fw_attr_kset = kset_create_and_add("attributes", NULL,
++ &asus_armoury.fw_attr_dev->kobj);
++ if (!asus_armoury.fw_attr_dev) {
++ err = -ENOMEM;
+ pr_debug("Failed to create and add attributes\n");
+ goto err_destroy_classdev;
+ }
+
-+ /* Add any firmware_attributes required */
-+ ret = sysfs_create_file(&asus_bios.fw_attr_kset->kobj, &pending_reboot.attr);
-+ if (ret) {
++ err = sysfs_create_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr);
++ if (err) {
+ pr_warn("Failed to create sysfs level attributes\n");
+ goto fail_class_created;
+ }
+
-+ // TODO: logging
-+ asus_bios.mini_led_dev_id = 0;
++ err = 0;
++ asus_armoury.mini_led_dev_id = 0;
+ if (asus_wmi_is_present(ASUS_WMI_DEVID_MINI_LED_MODE)) {
-+ asus_bios.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &mini_led_mode_attr_group);
-+ }
-+ else if (asus_wmi_is_present(ASUS_WMI_DEVID_MINI_LED_MODE2)) {
-+ asus_bios.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2;
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &mini_led_mode_attr_group);
++ asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;
++ err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj,
++ &mini_led_mode_attr_group);
++ } else if (asus_wmi_is_present(ASUS_WMI_DEVID_MINI_LED_MODE2)) {
++ asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2;
++ err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj,
++ &mini_led_mode_attr_group);
+ }
++ if (err)
++ pr_warn("Failed to create sysfs-group for mini_led\n");
+
++ err = 0;
++ asus_armoury.gpu_mux_dev_id = 0;
+ if (asus_wmi_is_present(ASUS_WMI_DEVID_GPU_MUX)) {
-+ asus_bios.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX;
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &gpu_mux_mode_attr_group);
++ asus_armoury.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX;
++ err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, &gpu_mux_mode_attr_group);
+ } else if (asus_wmi_is_present(ASUS_WMI_DEVID_GPU_MUX_VIVO)) {
-+ asus_bios.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX_VIVO;
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &gpu_mux_mode_attr_group);
++ asus_armoury.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX_VIVO;
++ err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, &gpu_mux_mode_attr_group);
+ }
++ if (err)
++ pr_warn("Failed to create sysfs-group for gpu_mux\n");
+
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU)) {
-+ asus_bios.dgpu_disable_available = true;
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &dgpu_disable_attr_group);
-+ }
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_EGPU)) {
-+ asus_bios.egpu_enable_available = true;
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &egpu_enable_attr_group);
-+ }
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_EGPU_CONNECTED))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &egpu_connected_attr_group);
-+
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_CORES_MAX) && !asus_bios_set_max_cores()){
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &cores_performance_attr_group);
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &cores_efficiency_attr_group);
-+ }
++ for (int i = 0; i < ARRAY_SIZE(armoury_attr_groups); i++) {
++ if (!asus_wmi_is_present(armoury_attr_groups[i].wmi_devid))
++ continue;
+
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &thermal_policy_attr_group);
-+
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PL1_SPL))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_pl1_spl_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PL2_SPPT))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_pl2_sppt_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_APU_SPPT))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_apu_sppt_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PLAT_SPPT))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_platform_sppt_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_FPPT))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_fppt_attr_group);
-+
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_NV_DYN_BOOST))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &nv_dynamic_boost_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_NV_THERM_TARGET))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &nv_temp_target_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU_BASE_TGP))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &dgpu_base_tgp_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU_SET_TGP))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &dgpu_tgp_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_APU_MEM))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &apu_mem_attr_group);
-+
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_CHARGE_MODE))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &charge_mode_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_BOOT_SOUND))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &boot_sound_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_MCU_POWERSAVE))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &mcu_powersave_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_PANEL_OD))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &panel_od_attr_group);
-+ if (asus_wmi_is_present(ASUS_WMI_DEVID_PANEL_HD))
-+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &panel_hd_mode_attr_group);
++ err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj,
++ armoury_attr_groups[i].attr_group);
++ if (err)
++ pr_warn("Failed to create sysfs-group for %s\n",
++ armoury_attr_groups[i].attr_group->name);
++ else
++ pr_debug("Created sysfs-group for %s\n",
++ armoury_attr_groups[i].attr_group->name);
++ }
+
+ return 0;
+
@@ -1052,7 +3983,7 @@ index 000000000000..bd4c408fd062
+
+fail_class_created:
+ fw_attributes_class_put();
-+ return ret;
++ return err;
+}
+
+/* Init / exit ****************************************************************/
@@ -1106,9 +4037,11 @@ index 000000000000..bd4c408fd062
+
+ /* ensure defaults for tunables */
+ rog->cpu_default = cpu_default;
++ rog->cpu_min = PPT_CPU_LIMIT_MIN;
+ rog->cpu_max = cpu_max;
+
+ rog->platform_default = platform_default;
++ rog->platform_max = PPT_PLATFORM_MIN;
+ rog->platform_max = platform_max;
+
+ rog->ppt_pl1_spl = cpu_default;
@@ -1119,30 +4052,40 @@ index 000000000000..bd4c408fd062
+ rog->ppt_fppt = platform_default;
+
+ rog->nv_boost_default = NVIDIA_BOOST_MAX;
++ rog->nv_boost_max = NVIDIA_BOOST_MIN;
+ rog->nv_boost_max = max_boost;
+ rog->nv_dynamic_boost = NVIDIA_BOOST_MIN;
+
+ rog->nv_temp_default = NVIDIA_TEMP_MAX;
++ rog->nv_temp_max = NVIDIA_TEMP_MIN;
+ rog->nv_temp_max = NVIDIA_TEMP_MAX;
+ rog->nv_temp_target = NVIDIA_TEMP_MIN;
+
++ rog->dgpu_tgp_default = NVIDIA_POWER_DEFAULT;
++ rog->dgpu_tgp_min = NVIDIA_POWER_MIN;
++ rog->dgpu_tgp_max = NVIDIA_POWER_MAX;
++ rog->dgpu_tgp = NVIDIA_POWER_MAX;
++
+}
+
+static int __init asus_fw_init(void)
+{
+ int err;
+
-+ mutex_lock(&asus_bios.mutex);
++ fw_attrs.pending_reboot = 0;
++
++ mutex_lock(&asus_armoury.mutex);
+
-+ asus_bios.rog_tunables = kzalloc(sizeof(struct rog_tunables), GFP_KERNEL);
-+ if (!asus_bios.rog_tunables) {
-+ mutex_unlock(&asus_bios.mutex);
++ asus_armoury.rog_tunables = kzalloc(sizeof(struct rog_tunables), GFP_KERNEL);
++ if (!asus_armoury.rog_tunables) {
++ mutex_unlock(&asus_armoury.mutex);
+ return -ENOMEM;
+ }
-+ init_rog_tunables(asus_bios.rog_tunables);
++ init_rog_tunables(asus_armoury.rog_tunables);
++ init_max_cpu_cores();
+
+ err = asus_fw_attr_add();
-+ mutex_unlock(&asus_bios.mutex);
++ mutex_unlock(&asus_armoury.mutex);
+ if (err)
+ return err;
+
@@ -1151,27 +4094,32 @@ index 000000000000..bd4c408fd062
+
+static void __exit asus_fw_exit(void)
+{
-+ mutex_lock(&asus_bios.mutex);
++ mutex_lock(&asus_armoury.mutex);
+
-+ sysfs_remove_file(&asus_bios.fw_attr_kset->kobj, &pending_reboot.attr);
-+ kset_unregister(asus_bios.fw_attr_kset);
++ sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr);
++ kset_unregister(asus_armoury.fw_attr_kset);
+ device_destroy(fw_attr_class, MKDEV(0, 0));
+ fw_attributes_class_put();
+
-+ mutex_unlock(&asus_bios.mutex);
++ mutex_unlock(&asus_armoury.mutex);
+}
+
+module_init(asus_fw_init);
+module_exit(asus_fw_exit);
-diff --git a/drivers/platform/x86/asus-bios.h b/drivers/platform/x86/asus-bios.h
++
++MODULE_AUTHOR("Luke Jones <luke@ljones.dev>");
++MODULE_DESCRIPTION("ASUS BIOS Configuration Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
+diff --git a/drivers/platform/x86/asus-armoury.h b/drivers/platform/x86/asus-armoury.h
new file mode 100644
-index 000000000000..7016ec14efc1
+index 000000000000..25b2c055930e
--- /dev/null
-+++ b/drivers/platform/x86/asus-bios.h
-@@ -0,0 +1,288 @@
++++ b/drivers/platform/x86/asus-armoury.h
+@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
-+ * Definitions for kernel modules using asus-bios driver
++ * Definitions for kernel modules using asus-armoury driver
+ *
+ * Copyright (c) 2024 Luke Jones <luke@ljones.dev>
+ */
@@ -1182,7 +4130,7 @@ index 000000000000..7016ec14efc1
+#include "firmware_attributes_class.h"
+#include <linux/types.h>
+
-+#define DRIVER_NAME "asus-bioscfg"
++#define DRIVER_NAME "asus-armoury"
+
+static ssize_t attr_int_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count,
@@ -1211,7 +4159,8 @@ index 000000000000..7016ec14efc1
+ .show = _show, \
+}
+
-+#define __ASUS_ATTR_RW(_func, _name) __ATTR(_name, 0644, _func##_##_name##_show, _func##_##_name##_store)
++#define __ASUS_ATTR_RW(_func, _name) __ATTR(_name, 0644, \
++ _func##_##_name##_show, _func##_##_name##_store)
+
+#define __WMI_STORE_INT(_attr, _min, _max, _wmi) \
+static ssize_t _attr##_store(struct kobject *kobj, \
@@ -1236,42 +4185,16 @@ index 000000000000..7016ec14efc1
+
+/* Create functions and attributes for use in other macros or on their own */
+
-+#define __ROG_TUNABLE_RW(_attr, _min, _max, _wmi) \
-+static ssize_t _attr##_current_value_store(struct kobject *kobj, \
-+ struct kobj_attribute *attr, \
-+ const char *buf, size_t count) \
-+{ \
-+ return attr_int_store(kobj, attr, buf, count, \
-+ _min, asus_bios.rog_tunables->_max, \
-+ &asus_bios.rog_tunables->_attr, _wmi); \
-+} \
-+static ssize_t _attr##_current_value_show(struct kobject *kobj, \
-+ struct kobj_attribute *attr, char *buf) \
-+{ \
-+ return sysfs_emit(buf, "%u\n", asus_bios.rog_tunables->_attr); \
-+} \
-+static struct kobj_attribute attr_##_attr##_current_value = \
-+ __ASUS_ATTR_RW(_attr, current_value);
-+
-+#define __ROG_TUNABLE_SHOW(_prop, _attrname, _val) \
-+static ssize_t _attrname##_##_prop##_show(struct kobject *kobj, \
-+ struct kobj_attribute *attr, char *buf) \
-+{ \
-+ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->_val); \
-+} \
-+static struct kobj_attribute attr_##_attrname##_##_prop = \
-+ __ASUS_ATTR_RO(_attrname, _prop);
-+
+#define __ATTR_CURRENT_INT_RO(_attr, _wmi) \
+WMI_SHOW_INT(_attr##_current_value, "%d\n", _wmi); \
+static struct kobj_attribute attr_##_attr##_current_value = \
-+ __ASUS_ATTR_RO(_attr, current_value);
++ __ASUS_ATTR_RO(_attr, current_value)
+
+#define __ATTR_CURRENT_INT_RW(_attr, _minv, _maxv, _wmi) \
+__WMI_STORE_INT(_attr##_current_value, _minv, _maxv, _wmi); \
+WMI_SHOW_INT(_attr##_current_value, "%d\n", _wmi); \
-+static struct kobj_attribute attr_##_attr##_current_value = \
-+ __ASUS_ATTR_RW(_attr, current_value);
++static struct kobj_attribute attr_##_attr##_current_value = \
++ __ASUS_ATTR_RW(_attr, current_value)
+
+/* Shows a formatted static variable */
+#define __ATTR_SHOW_FMT(_prop, _attrname, _fmt, _val) \
@@ -1280,13 +4203,13 @@ index 000000000000..7016ec14efc1
+{ \
+ return sysfs_emit(buf, _fmt, _val); \
+} \
-+static struct kobj_attribute attr_##_attrname##_##_prop = \
-+ __ASUS_ATTR_RO(_attrname, _prop);
++static struct kobj_attribute attr_##_attrname##_##_prop = \
++ __ASUS_ATTR_RO(_attrname, _prop)
+
+/* Requires current_value show&|store */
+#define __ATTR_GROUP_INT_VALUE_ONLY(_attrname, _fsname, _dispname) \
-+__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
-+static struct kobj_attribute attr_##_attrname##_type = \
++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
++static struct kobj_attribute attr_##_attrname##_type = \
+ __ASUS_ATTR_RO_AS(type, int_type_show); \
+static struct attribute *_attrname##_attrs[] = { \
+ &attr_##_attrname##_current_value.attr, \
@@ -1297,38 +4220,13 @@ index 000000000000..7016ec14efc1
+static const struct attribute_group _attrname##_attr_group = { \
+ .name = _fsname, \
+ .attrs = _attrname##_attrs \
-+};
-+
-+/* Int style min/max range, base macro. Requires current_value show&|store */
-+#define __ATTR_GROUP_INT(_attrname, _fsname, _default, \
-+ _min, _max, _incstep, _dispname)\
-+__ATTR_SHOW_FMT(default_value, _attrname, "%d\n", _default); \
-+__ATTR_SHOW_FMT(min_value, _attrname, "%d\n", _min); \
-+__ATTR_SHOW_FMT(max_value, _attrname, "%d\n", _max); \
-+__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", _incstep); \
-+__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
-+static struct kobj_attribute attr_##_attrname##_type = \
-+ __ASUS_ATTR_RO_AS(type, int_type_show); \
-+static struct attribute *_attrname##_attrs[] = { \
-+ &attr_##_attrname##_current_value.attr, \
-+ &attr_##_attrname##_default_value.attr, \
-+ &attr_##_attrname##_min_value.attr, \
-+ &attr_##_attrname##_max_value.attr, \
-+ &attr_##_attrname##_scalar_increment.attr, \
-+ &attr_##_attrname##_display_name.attr, \
-+ &attr_##_attrname##_type.attr, \
-+ NULL \
-+}; \
-+static const struct attribute_group _attrname##_attr_group = { \
-+ .name = _fsname, \
-+ .attrs = _attrname##_attrs \
-+};
++}
+
+/* Boolean style enumeration, base macro. Requires adding show/store */
+#define __ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname) \
-+__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
+__ATTR_SHOW_FMT(possible_values, _attrname, "%s\n", _possible); \
-+static struct kobj_attribute attr_##_attrname##_type = \
++static struct kobj_attribute attr_##_attrname##_type = \
+ __ASUS_ATTR_RO_AS(type, enum_type_show); \
+static struct attribute *_attrname##_attrs[] = { \
+ &attr_##_attrname##_current_value.attr, \
@@ -1340,24 +4238,19 @@ index 000000000000..7016ec14efc1
+static const struct attribute_group _attrname##_attr_group = { \
+ .name = _fsname, \
+ .attrs = _attrname##_attrs \
-+};
++}
+
+#define ATTR_GROUP_INT_VALUE_ONLY_RO(_attrname, _fsname, _wmi, _dispname) \
-+__ATTR_CURRENT_INT_RO(_attrname, _wmi); \
-+__ATTR_GROUP_INT_VALUE_ONLY(_attrname, _fsname, _dispname);
-+
-+#define ATTR_GROUP_INT_RW(_attrname, _fsname, _wmi, _default, _min, \
-+ _max, _incstep, _dispname) \
-+__ATTR_CURRENT_INT_RW(_attrname, _min, _max, _wmi); \
-+__ATTR_GROUP_INT(_attrname, _fsname, _default, _min, _max, _incstep, _dispname);
++ __ATTR_CURRENT_INT_RO(_attrname, _wmi); \
++ __ATTR_GROUP_INT_VALUE_ONLY(_attrname, _fsname, _dispname)
+
+#define ATTR_GROUP_BOOL_RO(_attrname, _fsname, _wmi, _dispname) \
-+__ATTR_CURRENT_INT_RO(_attrname, _wmi); \
-+__ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname);
++ __ATTR_CURRENT_INT_RO(_attrname, _wmi); \
++ __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname)
+
+#define ATTR_GROUP_BOOL_RW(_attrname, _fsname, _wmi, _dispname) \
-+__ATTR_CURRENT_INT_RW(_attrname, 0, 1, _wmi); \
-+__ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname);
++ __ATTR_CURRENT_INT_RW(_attrname, 0, 1, _wmi); \
++ __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname)
+
+/*
+ * Requires <name>_current_value_show(), <name>_current_value_show()
@@ -1365,29 +4258,24 @@ index 000000000000..7016ec14efc1
+#define ATTR_GROUP_BOOL_CUSTOM(_attrname, _fsname, _dispname) \
+static struct kobj_attribute attr_##_attrname##_current_value = \
+ __ASUS_ATTR_RW(_attrname, current_value); \
-+__ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname);
++ __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname)
+
-+#define ATTR_GROUP_ENUM_INT_RO(_attrname, _fsname, _wmi, _min, \
-+ _max, _possible, _dispname) \
-+__ATTR_CURRENT_INT_RO(_attrname, _wmi); \
-+__ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname);
-+
-+#define ATTR_GROUP_ENUM_INT_RW(_attrname, _fsname, _wmi, _min, \
-+ _max, _possible, _dispname) \
-+__ATTR_CURRENT_INT_RW(_attrname, _min, _max, _wmi); \
-+__ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname);
++#define ATTR_GROUP_ENUM_INT_RO(_attrname, _fsname, _wmi, \
++ _possible, _dispname) \
++ __ATTR_CURRENT_INT_RO(_attrname, _wmi); \
++ __ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname)
+
+/*
+ * Requires <name>_current_value_show(), <name>_current_value_show()
+ * and <name>_possible_values_show()
+ */
+#define ATTR_GROUP_ENUM_CUSTOM(_attrname, _fsname, _dispname) \
-+__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
-+static struct kobj_attribute attr_##_attrname##_current_value = \
++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
++static struct kobj_attribute attr_##_attrname##_current_value = \
+ __ASUS_ATTR_RW(_attrname, current_value); \
-+static struct kobj_attribute attr_##_attrname##_possible_values = \
++static struct kobj_attribute attr_##_attrname##_possible_values = \
+ __ASUS_ATTR_RO(_attrname, possible_values); \
-+static struct kobj_attribute attr_##_attrname##_type = \
++static struct kobj_attribute attr_##_attrname##_type = \
+ __ASUS_ATTR_RO_AS(type, enum_type_show); \
+static struct attribute *_attrname##_attrs[] = { \
+ &attr_##_attrname##_current_value.attr, \
@@ -1399,21 +4287,21 @@ index 000000000000..7016ec14efc1
+static const struct attribute_group _attrname##_attr_group = { \
+ .name = _fsname, \
+ .attrs = _attrname##_attrs \
-+};
++}
+
+/* CPU core attributes need a little different in setup */
-+#define ATTR_GROUP_CORES_RW(_attrname, _fsname, _wmi, _dispname)\
++#define ATTR_GROUP_CORES_RW(_attrname, _fsname, _dispname) \
+__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", 1); \
-+__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
+static struct kobj_attribute attr_##_attrname##_current_value = \
+ __ASUS_ATTR_RW(_attrname, current_value); \
+static struct kobj_attribute attr_##_attrname##_default_value = \
+ __ASUS_ATTR_RO(_attrname, default_value); \
-+static struct kobj_attribute attr_##_attrname##_min_value = \
++static struct kobj_attribute attr_##_attrname##_min_value = \
+ __ASUS_ATTR_RO(_attrname, min_value); \
-+static struct kobj_attribute attr_##_attrname##_max_value = \
++static struct kobj_attribute attr_##_attrname##_max_value = \
+ __ASUS_ATTR_RO(_attrname, max_value); \
-+static struct kobj_attribute attr_##_attrname##_type = \
++static struct kobj_attribute attr_##_attrname##_type = \
+ __ASUS_ATTR_RO_AS(type, int_type_show); \
+static struct attribute *_attrname##_attrs[] = { \
+ &attr_##_attrname##_current_value.attr, \
@@ -1428,114 +4316,105 @@ index 000000000000..7016ec14efc1
+static const struct attribute_group _attrname##_attr_group = { \
+ .name = _fsname, \
+ .attrs = _attrname##_attrs \
-+};
++}
+
-+/* ROG PPT attributes need a little different in setup */
-+#define ATTR_GROUP_PPT_RW(_attrname, _fsname, _wmi, _default, \
-+ _min, _max, _incstep, _dispname) \
-+__ROG_TUNABLE_RW(_attrname, _min, _max, _wmi); \
-+__ROG_TUNABLE_SHOW(default_value, _attrname, _default); \
-+__ATTR_SHOW_FMT(min_value, _attrname, "%d\n", _min); \
-+__ROG_TUNABLE_SHOW(max_value, _attrname, _max); \
-+__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", _incstep); \
-+__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
-+static struct kobj_attribute attr_##_attrname##_type = \
-+ __ASUS_ATTR_RO_AS(type, int_type_show); \
-+static struct attribute *_attrname##_attrs[] = { \
-+ &attr_##_attrname##_current_value.attr, \
-+ &attr_##_attrname##_default_value.attr, \
-+ &attr_##_attrname##_min_value.attr, \
-+ &attr_##_attrname##_max_value.attr, \
-+ &attr_##_attrname##_scalar_increment.attr, \
-+ &attr_##_attrname##_display_name.attr, \
-+ &attr_##_attrname##_type.attr, \
-+ NULL \
-+}; \
-+static const struct attribute_group _attrname##_attr_group = { \
-+ .name = _fsname, \
-+ .attrs = _attrname##_attrs \
-+};
++/*
++ * ROG PPT attributes need a little different in setup as they
++ * require rog_tunables members.
++ */
++
++#define __ROG_TUNABLE_RW(_attr, _min, _max, _wmi) \
++static ssize_t _attr##_current_value_store(struct kobject *kobj, \
++ struct kobj_attribute *attr, \
++ const char *buf, size_t count) \
++{ \
++ return attr_int_store(kobj, attr, buf, count, \
++ asus_armoury.rog_tunables->_min, \
++ asus_armoury.rog_tunables->_max, \
++ &asus_armoury.rog_tunables->_attr, _wmi); \
++} \
++static ssize_t _attr##_current_value_show(struct kobject *kobj, \
++ struct kobj_attribute *attr, char *buf) \
++{ \
++ return sysfs_emit(buf, "%u\n", asus_armoury.rog_tunables->_attr);\
++} \
++static struct kobj_attribute attr_##_attr##_current_value = \
++ __ASUS_ATTR_RW(_attr, current_value)
++
++#define __ROG_TUNABLE_SHOW(_prop, _attrname, _val) \
++static ssize_t _attrname##_##_prop##_show(struct kobject *kobj, \
++ struct kobj_attribute *attr, char *buf) \
++{ \
++ return sysfs_emit(buf, "%d\n", asus_armoury.rog_tunables->_val);\
++} \
++static struct kobj_attribute attr_##_attrname##_##_prop = \
++ __ASUS_ATTR_RO(_attrname, _prop)
++
++#define ATTR_GROUP_ROG_TUNABLE(_attrname, _fsname, _wmi, _default, \
++ _min, _max, _incstep, _dispname) \
++__ROG_TUNABLE_SHOW(default_value, _attrname, _default); \
++__ROG_TUNABLE_RW(_attrname, _min, _max, _wmi); \
++__ROG_TUNABLE_SHOW(min_value, _attrname, _min); \
++__ROG_TUNABLE_SHOW(max_value, _attrname, _max); \
++__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", _incstep); \
++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \
++static struct kobj_attribute attr_##_attrname##_type = \
++ __ASUS_ATTR_RO_AS(type, int_type_show); \
++static struct attribute *_attrname##_attrs[] = { \
++ &attr_##_attrname##_current_value.attr, \
++ &attr_##_attrname##_default_value.attr, \
++ &attr_##_attrname##_min_value.attr, \
++ &attr_##_attrname##_max_value.attr, \
++ &attr_##_attrname##_scalar_increment.attr, \
++ &attr_##_attrname##_display_name.attr, \
++ &attr_##_attrname##_type.attr, \
++ NULL \
++}; \
++static const struct attribute_group _attrname##_attr_group = { \
++ .name = _fsname, \
++ .attrs = _attrname##_attrs \
++}
+
+#endif /* _ASUS_BIOSCFG_H_ */
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
-index bc9c5db38324..9c80aa073758 100644
+index bc9c5db38324..9faebd12bd49 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
-@@ -97,6 +97,11 @@ module_param(fnlock_default, bool, 0444);
+@@ -97,6 +97,12 @@ module_param(fnlock_default, bool, 0444);
#define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST 1
#define ASUS_THROTTLE_THERMAL_POLICY_SILENT 2
+#define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO 0
++#define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1
+#define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO 2
-+#define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1
-+#define ASUS_THROTTLE_THERMAL_POLICY_FULLSPEED 3
++
++#define PLATFORM_PROFILE_MAX 2
+
#define USB_INTEL_XUSB2PR 0xD0
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
-@@ -112,11 +117,13 @@ module_param(fnlock_default, bool, 0444);
- /* Mask to determine if setting temperature or percentage */
- #define FAN_CURVE_PWM_MASK 0x04
+@@ -146,6 +152,20 @@ static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
--/* Limits for tunables available on ASUS ROG laptops */
--#define PPT_TOTAL_MIN 5
--#define PPT_TOTAL_MAX 250
--#define PPT_CPU_MIN 5
--#define PPT_CPU_MAX 130
-+/* Default limits for tunables available on ASUS ROG laptops */
-+#define PPT_CPU_LIMIT_MIN 5
-+#define PPT_CPU_LIMIT_MAX 150
-+#define PPT_CPU_LIMIT_DEFAULT 80
-+#define PPT_PLATFORM_MIN 5
-+#define PPT_PLATFORM_MAX 100
-+#define PPT_PLATFORM_DEFAULT 80
- #define NVIDIA_BOOST_MIN 5
- #define NVIDIA_BOOST_MAX 25
- #define NVIDIA_TEMP_MIN 75
-@@ -219,6 +226,29 @@ struct fan_curve_data {
- u8 percents[FAN_CURVE_POINTS];
- };
+ static int throttle_thermal_policy_write(struct asus_wmi *);
-+/* Tunables provided by ASUS for gaming laptops */
-+struct rog_tunables {
-+ u32 cpu_default;
-+ u32 cpu_max;
-+
-+ u32 platform_default;
-+ u32 platform_max;
-+
-+ u32 ppt_pl1_spl; // total
-+ u32 ppt_pl2_sppt; // total
-+ u32 ppt_apu_sppt; // cpu
-+ u32 ppt_platform_sppt; // cpu
-+ u32 ppt_fppt; // total
-+
-+ u32 nv_boost_default;
-+ u32 nv_boost_max;
-+ u32 nv_dynamic_boost;
-+
-+ u32 nv_temp_default;
-+ u32 nv_temp_max;
-+ u32 nv_temp_target;
++static const struct dmi_system_id asus_ally_mcu_quirk[] = {
++ {
++ .matches = {
++ DMI_MATCH(DMI_BOARD_NAME, "RC71L"),
++ },
++ },
++ {
++ .matches = {
++ DMI_MATCH(DMI_BOARD_NAME, "RC72L"),
++ },
++ },
++ { },
+};
+
- struct asus_wmi {
- int dsts_id;
- int spec;
-@@ -273,20 +303,13 @@ struct asus_wmi {
- bool dgpu_disable_available;
- u32 gpu_mux_dev;
-
-- /* Tunables provided by ASUS for gaming laptops */
-- u32 ppt_pl2_sppt;
-- u32 ppt_pl1_spl;
-- u32 ppt_apu_sppt;
-- u32 ppt_platform_sppt;
-- u32 ppt_fppt;
-- u32 nv_dynamic_boost;
-- u32 nv_temp_target;
-+ struct rog_tunables rog_tunables;
-
+ static bool ashs_present(void)
+ {
+ int i = 0;
+@@ -285,8 +305,8 @@ struct asus_wmi {
u32 kbd_rgb_dev;
bool kbd_rgb_state_available;
@@ -1545,7 +4424,7 @@ index bc9c5db38324..9c80aa073758 100644
bool cpu_fan_curve_available;
bool gpu_fan_curve_available;
-@@ -334,20 +357,29 @@ static int asus_wmi_evaluate_method3(u32 method_id,
+@@ -334,20 +354,29 @@ static int asus_wmi_evaluate_method3(u32 method_id,
status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,
&input, &output);
@@ -1577,7 +4456,7 @@ index bc9c5db38324..9c80aa073758 100644
return 0;
}
-@@ -377,20 +409,29 @@ static int asus_wmi_evaluate_method5(u32 method_id,
+@@ -377,20 +406,29 @@ static int asus_wmi_evaluate_method5(u32 method_id,
status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,
&input, &output);
@@ -1609,7 +4488,7 @@ index bc9c5db38324..9c80aa073758 100644
return 0;
}
-@@ -416,8 +457,13 @@ static int asus_wmi_evaluate_method_buf(u32 method_id,
+@@ -416,8 +454,13 @@ static int asus_wmi_evaluate_method_buf(u32 method_id,
status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,
&input, &output);
@@ -1624,7 +4503,7 @@ index bc9c5db38324..9c80aa073758 100644
obj = (union acpi_object *)output.pointer;
-@@ -453,8 +499,11 @@ static int asus_wmi_evaluate_method_buf(u32 method_id,
+@@ -453,8 +496,11 @@ static int asus_wmi_evaluate_method_buf(u32 method_id,
kfree(obj);
@@ -1637,11 +4516,27 @@ index bc9c5db38324..9c80aa073758 100644
return 0;
}
-@@ -503,12 +552,28 @@ static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
+@@ -503,12 +549,56 @@ static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
return 0;
}
-static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
+- u32 *retval)
++/**
++ * asus_wmi_get_devstate_dsts() - Get the WMI function state.
++ * @dev_id: The WMI function to call.
++ * @retval: A pointer to where to store the value returned from WMI.
++ *
++ * The returned WMI function state can also be used to determine if the WMI
++ * function is supported by checking if the asus_wmi_get_devstate_dsts()
++ * returns an error.
++ *
++ * On success the return value is 0, and the retval is a valid value returned
++ * by the successful WMI function call. An error value is returned only if the
++ * WMI function failed, or if it returns "unsupported" which is typically a 0
++ * (no return, and no 'supported' bit set), or a 0xFFFFFFFE (~1) which if not
++ * caught here can result in unexpected behaviour later.
++ */
+int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval)
+{
+ int err;
@@ -1649,16 +4544,29 @@ index bc9c5db38324..9c80aa073758 100644
+ err = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, dev_id, 0, retval);
+ if (err)
+ return err;
-+
-+ if (*retval == ~0)
++ /* Be explicit about retval */
++ if (*retval == 0xFFFFFFFE || *retval == 0)
+ return -ENODEV;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(asus_wmi_get_devstate_dsts);
+
-+int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
- u32 *retval)
++/**
++ * asus_wmi_set_devstate() - Set the WMI function state.
++ * @dev_id: The WMI function to call.
++ * @ctrl_param: The argument to be used for this WMI function.
++ * @retval: A pointer to where to store the value returned from WMI.
++ *
++ * The returned WMI function state if not checked here for error as
++ * asus_wmi_set_devstate() is not called unless first paired with a call to
++ * asus_wmi_get_devstate_dsts() to check that the WMI function is supported.
++ *
++ * On success the return value is 0, and the retval is a valid value returned
++ * by the successful WMI function call. An error value is returned only if the
++ * WMI function failed.
++ */
++int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval)
{
return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
ctrl_param, retval);
@@ -1667,7 +4575,7 @@ index bc9c5db38324..9c80aa073758 100644
/* Helper for special devices with magic return codes */
static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
-@@ -542,6 +607,7 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id)
+@@ -542,6 +632,7 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id)
{
u32 retval;
int status = asus_wmi_get_devstate(asus, dev_id, &retval);
@@ -1675,413 +4583,7 @@ index bc9c5db38324..9c80aa073758 100644
return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT);
}
-@@ -625,6 +691,98 @@ static void asus_wmi_input_exit(struct asus_wmi *asus)
- asus->inputdev = NULL;
- }
-
-+/* Helper macros for generalised WMI calls */
-+
-+/* Generic store function for use with many ROG tunables */
-+static ssize_t rog_tunable_store(struct asus_wmi *asus,
-+ struct attribute *attr,
-+ const char *buf, size_t count,
-+ u32 min, u32 max, u32 defaultv,
-+ u32 *store_value, u32 wmi_dev)
-+{
-+ int result, err, value;
-+
-+ result = kstrtoint(buf, 10, &value);
-+ if (result)
-+ return result;
-+
-+ if (value == -1 )
-+ value = defaultv;
-+ if (value < min || value > max)
-+ return -EINVAL;
-+
-+ err = asus_wmi_set_devstate(wmi_dev, value, &result);
-+ if (err) {
-+ pr_err("Failed to set %s: %d\n", attr->name, err);
-+ return err;
-+ }
-+
-+ if (result > 1) {
-+ pr_err("Failed to set %s (result): 0x%x\n", attr->name, result);
-+ return -EIO;
-+ }
-+
-+ if (store_value != NULL)
-+ *store_value = value;
-+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, attr->name);
-+
-+ return count;
-+}
-+
-+#define ROG_TUNABLE_STORE(_fname, _min, _max, _default, _wmi) \
-+static ssize_t _fname##_store(struct device *dev, \
-+ struct device_attribute *attr, const char *buf, size_t count) \
-+{ \
-+ struct asus_wmi *asus = dev_get_drvdata(dev); \
-+ return rog_tunable_store(asus, &attr->attr, buf, count, \
-+ _min, asus->rog_tunables._max, asus->rog_tunables._default, \
-+ &asus->rog_tunables._fname, _wmi); \
-+}
-+
-+#define ROG_TUNABLE_SHOW(_fname) \
-+static ssize_t _fname##_show(struct device *dev, struct device_attribute *attr, char *buf) \
-+{ \
-+ struct asus_wmi *asus = dev_get_drvdata(dev); \
-+ return sysfs_emit(buf, "%u\n", asus->rog_tunables._fname); \
-+}
-+
-+#define ROG_TUNABLE_MIN_SHOW(_fname, _minv) \
-+static ssize_t _fname##_min_show(struct device *dev, struct device_attribute *attr, char *buf) \
-+{ \
-+ return sysfs_emit(buf, "%u\n", _minv); \
-+}
-+
-+#define ROG_TUNABLE_MAX_SHOW(_fname, _maxv) \
-+static ssize_t _fname##_max_show(struct device *dev, struct device_attribute *attr, char *buf) \
-+{ \
-+ struct asus_wmi *asus = dev_get_drvdata(dev); \
-+ return sysfs_emit(buf, "%u\n", asus->rog_tunables._maxv); \
-+}
-+
-+#define ROG_ATTR_RW(_fname, _minv, _maxv, _defaultv, _wmi) \
-+ROG_TUNABLE_MIN_SHOW(_fname, _minv); \
-+ROG_TUNABLE_MAX_SHOW(_fname, _maxv); \
-+ROG_TUNABLE_STORE(_fname, _minv, _maxv, _defaultv, _wmi);\
-+ROG_TUNABLE_SHOW(_fname); \
-+static DEVICE_ATTR_RO(_fname##_min); \
-+static DEVICE_ATTR_RO(_fname##_max); \
-+static DEVICE_ATTR_RW(_fname)
-+
-+ROG_ATTR_RW(ppt_platform_sppt,
-+ PPT_PLATFORM_MIN, platform_max, platform_default, ASUS_WMI_DEVID_PPT_PLAT_SPPT);
-+ROG_ATTR_RW(ppt_pl2_sppt,
-+ PPT_CPU_LIMIT_MIN, cpu_max, cpu_default, ASUS_WMI_DEVID_PPT_PL2_SPPT);
-+ROG_ATTR_RW(ppt_apu_sppt,
-+ PPT_PLATFORM_MIN, platform_max, platform_default, ASUS_WMI_DEVID_PPT_APU_SPPT);
-+ROG_ATTR_RW(ppt_pl1_spl,
-+ PPT_CPU_LIMIT_MIN, cpu_max, cpu_default, ASUS_WMI_DEVID_PPT_PL1_SPL);
-+ROG_ATTR_RW(ppt_fppt,
-+ PPT_CPU_LIMIT_MIN, cpu_max, cpu_default, ASUS_WMI_DEVID_PPT_FPPT);
-+ROG_ATTR_RW(nv_dynamic_boost,
-+ NVIDIA_BOOST_MIN, nv_boost_max, nv_boost_default, ASUS_WMI_DEVID_NV_DYN_BOOST);
-+ROG_ATTR_RW(nv_temp_target,
-+ NVIDIA_TEMP_MIN, nv_temp_max, nv_temp_default, ASUS_WMI_DEVID_NV_THERM_TARGET);
-+
- /* Tablet mode ****************************************************************/
-
- static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus)
-@@ -995,306 +1153,6 @@ static const struct attribute_group *kbd_rgb_mode_groups[] = {
- NULL,
- };
-
--/* Tunable: PPT: Intel=PL1, AMD=SPPT *****************************************/
--static ssize_t ppt_pl2_sppt_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-- int result, err;
-- u32 value;
--
-- result = kstrtou32(buf, 10, &value);
-- if (result)
-- return result;
--
-- if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)
-- return -EINVAL;
--
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL2_SPPT, value, &result);
-- if (err) {
-- pr_warn("Failed to set ppt_pl2_sppt: %d\n", err);
-- return err;
-- }
--
-- if (result > 1) {
-- pr_warn("Failed to set ppt_pl2_sppt (result): 0x%x\n", result);
-- return -EIO;
-- }
--
-- asus->ppt_pl2_sppt = value;
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl2_sppt");
--
-- return count;
--}
--
--static ssize_t ppt_pl2_sppt_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%u\n", asus->ppt_pl2_sppt);
--}
--static DEVICE_ATTR_RW(ppt_pl2_sppt);
--
--/* Tunable: PPT, Intel=PL1, AMD=SPL ******************************************/
--static ssize_t ppt_pl1_spl_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-- int result, err;
-- u32 value;
--
-- result = kstrtou32(buf, 10, &value);
-- if (result)
-- return result;
--
-- if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)
-- return -EINVAL;
--
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL1_SPL, value, &result);
-- if (err) {
-- pr_warn("Failed to set ppt_pl1_spl: %d\n", err);
-- return err;
-- }
--
-- if (result > 1) {
-- pr_warn("Failed to set ppt_pl1_spl (result): 0x%x\n", result);
-- return -EIO;
-- }
--
-- asus->ppt_pl1_spl = value;
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl1_spl");
--
-- return count;
--}
--static ssize_t ppt_pl1_spl_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%u\n", asus->ppt_pl1_spl);
--}
--static DEVICE_ATTR_RW(ppt_pl1_spl);
--
--/* Tunable: PPT APU FPPT ******************************************************/
--static ssize_t ppt_fppt_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-- int result, err;
-- u32 value;
--
-- result = kstrtou32(buf, 10, &value);
-- if (result)
-- return result;
--
-- if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)
-- return -EINVAL;
--
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_FPPT, value, &result);
-- if (err) {
-- pr_warn("Failed to set ppt_fppt: %d\n", err);
-- return err;
-- }
--
-- if (result > 1) {
-- pr_warn("Failed to set ppt_fppt (result): 0x%x\n", result);
-- return -EIO;
-- }
--
-- asus->ppt_fppt = value;
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_fpu_sppt");
--
-- return count;
--}
--
--static ssize_t ppt_fppt_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%u\n", asus->ppt_fppt);
--}
--static DEVICE_ATTR_RW(ppt_fppt);
--
--/* Tunable: PPT APU SPPT *****************************************************/
--static ssize_t ppt_apu_sppt_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-- int result, err;
-- u32 value;
--
-- result = kstrtou32(buf, 10, &value);
-- if (result)
-- return result;
--
-- if (value < PPT_CPU_MIN || value > PPT_CPU_MAX)
-- return -EINVAL;
--
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_APU_SPPT, value, &result);
-- if (err) {
-- pr_warn("Failed to set ppt_apu_sppt: %d\n", err);
-- return err;
-- }
--
-- if (result > 1) {
-- pr_warn("Failed to set ppt_apu_sppt (result): 0x%x\n", result);
-- return -EIO;
-- }
--
-- asus->ppt_apu_sppt = value;
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_apu_sppt");
--
-- return count;
--}
--
--static ssize_t ppt_apu_sppt_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%u\n", asus->ppt_apu_sppt);
--}
--static DEVICE_ATTR_RW(ppt_apu_sppt);
--
--/* Tunable: PPT platform SPPT ************************************************/
--static ssize_t ppt_platform_sppt_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-- int result, err;
-- u32 value;
--
-- result = kstrtou32(buf, 10, &value);
-- if (result)
-- return result;
--
-- if (value < PPT_CPU_MIN || value > PPT_CPU_MAX)
-- return -EINVAL;
--
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PLAT_SPPT, value, &result);
-- if (err) {
-- pr_warn("Failed to set ppt_platform_sppt: %d\n", err);
-- return err;
-- }
--
-- if (result > 1) {
-- pr_warn("Failed to set ppt_platform_sppt (result): 0x%x\n", result);
-- return -EIO;
-- }
--
-- asus->ppt_platform_sppt = value;
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_platform_sppt");
--
-- return count;
--}
--
--static ssize_t ppt_platform_sppt_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%u\n", asus->ppt_platform_sppt);
--}
--static DEVICE_ATTR_RW(ppt_platform_sppt);
--
--/* Tunable: NVIDIA dynamic boost *********************************************/
--static ssize_t nv_dynamic_boost_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-- int result, err;
-- u32 value;
--
-- result = kstrtou32(buf, 10, &value);
-- if (result)
-- return result;
--
-- if (value < NVIDIA_BOOST_MIN || value > NVIDIA_BOOST_MAX)
-- return -EINVAL;
--
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_DYN_BOOST, value, &result);
-- if (err) {
-- pr_warn("Failed to set nv_dynamic_boost: %d\n", err);
-- return err;
-- }
--
-- if (result > 1) {
-- pr_warn("Failed to set nv_dynamic_boost (result): 0x%x\n", result);
-- return -EIO;
-- }
--
-- asus->nv_dynamic_boost = value;
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_dynamic_boost");
--
-- return count;
--}
--
--static ssize_t nv_dynamic_boost_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%u\n", asus->nv_dynamic_boost);
--}
--static DEVICE_ATTR_RW(nv_dynamic_boost);
--
--/* Tunable: NVIDIA temperature target ****************************************/
--static ssize_t nv_temp_target_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
-- int result, err;
-- u32 value;
--
-- result = kstrtou32(buf, 10, &value);
-- if (result)
-- return result;
--
-- if (value < NVIDIA_TEMP_MIN || value > NVIDIA_TEMP_MAX)
-- return -EINVAL;
--
-- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_THERM_TARGET, value, &result);
-- if (err) {
-- pr_warn("Failed to set nv_temp_target: %d\n", err);
-- return err;
-- }
--
-- if (result > 1) {
-- pr_warn("Failed to set nv_temp_target (result): 0x%x\n", result);
-- return -EIO;
-- }
--
-- asus->nv_temp_target = value;
-- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_temp_target");
--
-- return count;
--}
--
--static ssize_t nv_temp_target_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct asus_wmi *asus = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%u\n", asus->nv_temp_target);
--}
--static DEVICE_ATTR_RW(nv_temp_target);
--
- /* Ally MCU Powersave ********************************************************/
- static ssize_t mcu_powersave_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-@@ -1685,7 +1544,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
+@@ -1685,7 +1776,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
goto error;
}
@@ -2091,20 +4593,7 @@ index bc9c5db38324..9c80aa073758 100644
asus->kbd_led_wk = led_val;
asus->kbd_led.name = "asus::kbd_backlight";
asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
-@@ -2312,10 +2172,10 @@ static ssize_t mini_led_mode_store(struct device *dev,
- return result;
-
- if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE &&
-- mode > ASUS_MINI_LED_ON)
-+ mode > ASUS_MINI_LED_ON)
- return -EINVAL;
- if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 &&
-- mode > ASUS_MINI_LED_STRONG_MODE)
-+ mode > ASUS_MINI_LED_STRONG_MODE)
- return -EINVAL;
-
- /*
-@@ -3127,7 +2987,7 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev)
+@@ -3127,7 +3219,7 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev)
int err, fan_idx;
u8 mode = 0;
@@ -2113,7 +4602,7 @@ index bc9c5db38324..9c80aa073758 100644
mode = asus->throttle_thermal_policy_mode;
/* DEVID_<C/G>PU_FAN_CURVE is switched for OVERBOOST vs SILENT */
if (mode == 2)
-@@ -3334,7 +3194,7 @@ static ssize_t fan_curve_enable_store(struct device *dev,
+@@ -3334,7 +3426,7 @@ static ssize_t fan_curve_enable_store(struct device *dev,
* For machines with throttle this is the only way to reset fans
* to default mode of operation (does not erase curve data).
*/
@@ -2122,7 +4611,7 @@ index bc9c5db38324..9c80aa073758 100644
err = throttle_thermal_policy_write(asus);
if (err)
return err;
-@@ -3551,8 +3411,8 @@ static const struct attribute_group asus_fan_curve_attr_group = {
+@@ -3551,8 +3643,8 @@ static const struct attribute_group asus_fan_curve_attr_group = {
__ATTRIBUTE_GROUPS(asus_fan_curve_attr);
/*
@@ -2133,7 +4622,7 @@ index bc9c5db38324..9c80aa073758 100644
*/
static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
{
-@@ -3562,18 +3422,27 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
+@@ -3562,18 +3654,27 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
err = fan_curve_check_present(asus, &asus->cpu_fan_curve_available,
ASUS_WMI_DEVID_CPU_FAN_CURVE);
@@ -2164,7 +4653,7 @@ index bc9c5db38324..9c80aa073758 100644
if (!asus->cpu_fan_curve_available
&& !asus->gpu_fan_curve_available
-@@ -3593,38 +3462,31 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
+@@ -3593,38 +3694,13 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
}
/* Throttle thermal policy ****************************************************/
@@ -2197,33 +4686,16 @@ index bc9c5db38324..9c80aa073758 100644
- u8 value;
+ u8 value = asus->throttle_thermal_policy_mode;
u32 retval;
-+ bool vivo;
+ int err;
- value = asus->throttle_thermal_policy_mode;
-+ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO;
-+ if (vivo) {
-+ switch (value) {
-+ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT:
-+ value = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO;
-+ break;
-+ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST:
-+ value = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO;
-+ break;
-+ case ASUS_THROTTLE_THERMAL_POLICY_SILENT:
-+ value = ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-
+-
- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY,
+ err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev,
value, &retval);
sysfs_notify(&asus->platform_device->dev.kobj, NULL,
-@@ -3654,7 +3516,7 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
+@@ -3654,7 +3730,7 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
static int throttle_thermal_policy_set_default(struct asus_wmi *asus)
{
@@ -2232,54 +4704,100 @@ index bc9c5db38324..9c80aa073758 100644
return 0;
asus->throttle_thermal_policy_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
-@@ -3664,9 +3526,14 @@ static int throttle_thermal_policy_set_default(struct asus_wmi *asus)
- static int throttle_thermal_policy_switch_next(struct asus_wmi *asus)
- {
+@@ -3666,7 +3742,7 @@ static int throttle_thermal_policy_switch_next(struct asus_wmi *asus)
u8 new_mode = asus->throttle_thermal_policy_mode + 1;
-+ bool vivo;
int err;
- if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
-+ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO;
-+ if (!vivo && new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
-+ new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
-+
-+ if (vivo && new_mode > ASUS_THROTTLE_THERMAL_POLICY_FULLSPEED)
++ if (new_mode > PLATFORM_PROFILE_MAX)
new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
asus->throttle_thermal_policy_mode = new_mode;
-@@ -3699,13 +3566,17 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
- struct asus_wmi *asus = dev_get_drvdata(dev);
- u8 new_mode;
- int result;
-+ bool vivo;
- int err;
-
- result = kstrtou8(buf, 10, &new_mode);
+@@ -3705,7 +3781,7 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
if (result < 0)
return result;
- if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
-+ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO;
-+ if (vivo && new_mode > ASUS_THROTTLE_THERMAL_POLICY_FULLSPEED)
-+ return -EINVAL;
-+ else if (!vivo && new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
++ if (new_mode > PLATFORM_PROFILE_MAX)
return -EINVAL;
asus->throttle_thermal_policy_mode = new_mode;
-@@ -3722,7 +3593,10 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
+@@ -3722,10 +3798,52 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
return count;
}
-// Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent
+/*
+ * Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent
-+ * VIVOBOOK: 3 - fans full speed
+ */
static DEVICE_ATTR_RW(throttle_thermal_policy);
/* Platform profile ***********************************************************/
-@@ -3788,7 +3662,7 @@ static int platform_profile_setup(struct asus_wmi *asus)
++static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode)
++{
++ bool vivo;
++
++ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO;
++
++ if (vivo) {
++ switch (mode) {
++ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT:
++ return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO;
++ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST:
++ return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO;
++ case ASUS_THROTTLE_THERMAL_POLICY_SILENT:
++ return ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO;
++ }
++ }
++
++ return mode;
++}
++
++static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int mode)
++{
++ bool vivo;
++
++ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO;
++
++ if (vivo) {
++ switch (mode) {
++ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO:
++ return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
++ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO:
++ return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
++ case ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO:
++ return ASUS_THROTTLE_THERMAL_POLICY_SILENT;
++ }
++ }
++
++ return mode;
++}
++
+ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+ {
+@@ -3733,10 +3851,9 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
+ int tp;
+
+ asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
+-
+ tp = asus->throttle_thermal_policy_mode;
+
+- switch (tp) {
++ switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {
+ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+@@ -3775,7 +3892,7 @@ static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
+ return -EOPNOTSUPP;
+ }
+
+- asus->throttle_thermal_policy_mode = tp;
++ asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp);
+ return throttle_thermal_policy_write(asus);
+ }
+
+@@ -3788,7 +3905,7 @@ static int platform_profile_setup(struct asus_wmi *asus)
* Not an error if a component platform_profile relies on is unavailable
* so early return, skipping the setup of platform_profile.
*/
@@ -2288,7 +4806,7 @@ index bc9c5db38324..9c80aa073758 100644
return 0;
dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
-@@ -3803,8 +3677,13 @@ static int platform_profile_setup(struct asus_wmi *asus)
+@@ -3803,8 +3920,13 @@ static int platform_profile_setup(struct asus_wmi *asus)
asus->platform_profile_handler.choices);
err = platform_profile_register(&asus->platform_profile_handler);
@@ -2303,7 +4821,7 @@ index bc9c5db38324..9c80aa073758 100644
asus->platform_profile_support = true;
return 0;
-@@ -4203,7 +4082,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
+@@ -4203,7 +4325,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
if (code == NOTIFY_KBD_FBM || code == NOTIFY_KBD_TTP) {
if (asus->fan_boost_mode_available)
fan_boost_mode_switch_next(asus);
@@ -2312,79 +4830,16 @@ index bc9c5db38324..9c80aa073758 100644
throttle_thermal_policy_switch_next(asus);
return;
-@@ -4329,13 +4208,27 @@ static struct attribute *platform_attributes[] = {
- &dev_attr_als_enable.attr,
- &dev_attr_fan_boost_mode.attr,
- &dev_attr_throttle_thermal_policy.attr,
-- &dev_attr_ppt_pl2_sppt.attr,
- &dev_attr_ppt_pl1_spl.attr,
-+ &dev_attr_ppt_pl1_spl_min.attr,
-+ &dev_attr_ppt_pl1_spl_max.attr,
-+ &dev_attr_ppt_pl2_sppt.attr,
-+ &dev_attr_ppt_pl2_sppt_min.attr,
-+ &dev_attr_ppt_pl2_sppt_max.attr,
- &dev_attr_ppt_fppt.attr,
-+ &dev_attr_ppt_fppt_min.attr,
-+ &dev_attr_ppt_fppt_max.attr,
- &dev_attr_ppt_apu_sppt.attr,
-+ &dev_attr_ppt_apu_sppt_min.attr,
-+ &dev_attr_ppt_apu_sppt_max.attr,
- &dev_attr_ppt_platform_sppt.attr,
-+ &dev_attr_ppt_platform_sppt_min.attr,
-+ &dev_attr_ppt_platform_sppt_max.attr,
- &dev_attr_nv_dynamic_boost.attr,
-+ &dev_attr_nv_dynamic_boost_min.attr,
-+ &dev_attr_nv_dynamic_boost_max.attr,
- &dev_attr_nv_temp_target.attr,
-+ &dev_attr_nv_temp_target_min.attr,
-+ &dev_attr_nv_temp_target_max.attr,
- &dev_attr_mcu_powersave.attr,
- &dev_attr_boot_sound.attr,
- &dev_attr_panel_od.attr,
-@@ -4375,20 +4268,34 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
+@@ -4375,7 +4497,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
else if (attr == &dev_attr_fan_boost_mode.attr)
ok = asus->fan_boost_mode_available;
else if (attr == &dev_attr_throttle_thermal_policy.attr)
- ok = asus->throttle_thermal_policy_available;
-- else if (attr == &dev_attr_ppt_pl2_sppt.attr)
+ ok = asus->throttle_thermal_policy_dev != 0;
-+ else if (attr == &dev_attr_ppt_pl2_sppt.attr
-+ || attr == &dev_attr_ppt_pl2_sppt_min.attr
-+ || attr == &dev_attr_ppt_pl2_sppt_max.attr)
+ else if (attr == &dev_attr_ppt_pl2_sppt.attr)
devid = ASUS_WMI_DEVID_PPT_PL2_SPPT;
-- else if (attr == &dev_attr_ppt_pl1_spl.attr)
-+ else if (attr == &dev_attr_ppt_pl1_spl.attr
-+ || attr == &dev_attr_ppt_pl1_spl_min.attr
-+ || attr == &dev_attr_ppt_pl1_spl_max.attr)
- devid = ASUS_WMI_DEVID_PPT_PL1_SPL;
-- else if (attr == &dev_attr_ppt_fppt.attr)
-+ else if (attr == &dev_attr_ppt_fppt.attr
-+ || attr == &dev_attr_ppt_fppt_min.attr
-+ || attr == &dev_attr_ppt_fppt_max.attr)
- devid = ASUS_WMI_DEVID_PPT_FPPT;
-- else if (attr == &dev_attr_ppt_apu_sppt.attr)
-+ else if (attr == &dev_attr_ppt_apu_sppt.attr
-+ || attr == &dev_attr_ppt_apu_sppt_min.attr
-+ || attr == &dev_attr_ppt_apu_sppt_max.attr)
- devid = ASUS_WMI_DEVID_PPT_APU_SPPT;
-- else if (attr == &dev_attr_ppt_platform_sppt.attr)
-+ else if (attr == &dev_attr_ppt_platform_sppt.attr
-+ || attr == &dev_attr_ppt_platform_sppt_min.attr
-+ || attr == &dev_attr_ppt_platform_sppt_max.attr)
- devid = ASUS_WMI_DEVID_PPT_PLAT_SPPT;
-- else if (attr == &dev_attr_nv_dynamic_boost.attr)
-+ else if (attr == &dev_attr_nv_dynamic_boost.attr
-+ || attr == &dev_attr_nv_dynamic_boost_min.attr
-+ || attr == &dev_attr_nv_dynamic_boost_max.attr)
- devid = ASUS_WMI_DEVID_NV_DYN_BOOST;
-- else if (attr == &dev_attr_nv_temp_target.attr)
-+ else if (attr == &dev_attr_nv_temp_target.attr
-+ || attr == &dev_attr_nv_temp_target_min.attr
-+ || attr == &dev_attr_nv_temp_target_max.attr)
- devid = ASUS_WMI_DEVID_NV_THERM_TARGET;
- else if (attr == &dev_attr_mcu_powersave.attr)
- devid = ASUS_WMI_DEVID_MCU_POWERSAVE;
-@@ -4401,8 +4308,10 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
+ else if (attr == &dev_attr_ppt_pl1_spl.attr)
+@@ -4401,8 +4523,10 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
else if (attr == &dev_attr_available_mini_led_mode.attr)
ok = asus->mini_led_dev_id != 0;
@@ -2396,102 +4851,16 @@ index bc9c5db38324..9c80aa073758 100644
return ok ? attr->mode : 0;
}
-@@ -4612,6 +4521,77 @@ static void asus_wmi_debugfs_init(struct asus_wmi *asus)
-
- /* Init / exit ****************************************************************/
-
-+/* Set up the min/max and defaults for ROG tunables */
-+static void init_rog_tunables(struct asus_wmi *asus)
-+{
-+ const char *product;
-+ u32 max_boost = NVIDIA_BOOST_MAX;
-+ u32 cpu_default = PPT_CPU_LIMIT_DEFAULT;
-+ u32 cpu_max = PPT_CPU_LIMIT_MAX;
-+ u32 platform_default = PPT_PLATFORM_DEFAULT;
-+ u32 platform_max = PPT_PLATFORM_MAX;
-+
-+ /*
-+ * ASUS product_name contains everything required, e.g,
-+ * "ROG Flow X16 GV601VV_GV601VV_00185149B"
-+ */
-+ product = dmi_get_system_info(DMI_PRODUCT_NAME);
-+
-+ if (strstr(product, "GA402R")) {
-+ cpu_default = 125;
-+ } else if (strstr(product, "13QY")) {
-+ cpu_max = 250;
-+ } else if (strstr(product, "X13")) {
-+ cpu_max = 75;
-+ cpu_default = 50;
-+ } else if (strstr(product, "RC71")) {
-+ cpu_max = 50;
-+ cpu_default = 30;
-+ } else if (strstr(product, "G814")
-+ || strstr(product, "G614")
-+ || strstr(product, "G834")
-+ || strstr(product, "G634")) {
-+ cpu_max = 175;
-+ } else if (strstr(product, "GA402X")
-+ || strstr(product, "GA403")
-+ || strstr(product, "FA507N")
-+ || strstr(product, "FA507X")
-+ || strstr(product, "FA707N")
-+ || strstr(product, "FA707X")) {
-+ cpu_max = 90;
-+ }
-+
-+ if (strstr(product, "GZ301ZE"))
-+ max_boost = 5;
-+ else if (strstr(product, "FX507ZC4"))
-+ max_boost = 15;
-+ else if (strstr(product, "GU605"))
-+ max_boost = 20;
-+
-+ /* ensure defaults for tunables */
-+ asus->rog_tunables.cpu_default = cpu_default;
-+ asus->rog_tunables.cpu_max = cpu_max;
-+
-+ asus->rog_tunables.platform_default = platform_default;
-+ asus->rog_tunables.platform_max = platform_max;
-+
-+ asus->rog_tunables.ppt_pl1_spl = cpu_default;
-+ asus->rog_tunables.ppt_pl2_sppt = cpu_default;
-+ asus->rog_tunables.ppt_apu_sppt = cpu_default;
-+
-+ asus->rog_tunables.ppt_platform_sppt = platform_default;
-+ asus->rog_tunables.ppt_fppt = platform_default;
-+
-+ asus->rog_tunables.nv_boost_default = NVIDIA_BOOST_MAX;
-+ asus->rog_tunables.nv_boost_max = max_boost;
-+ asus->rog_tunables.nv_dynamic_boost = NVIDIA_BOOST_MIN;
-+
-+ asus->rog_tunables.nv_temp_default = NVIDIA_TEMP_MAX;
-+ asus->rog_tunables.nv_temp_max = NVIDIA_TEMP_MAX;
-+ asus->rog_tunables.nv_temp_target = NVIDIA_TEMP_MIN;
-+
-+}
-+
- static int asus_wmi_add(struct platform_device *pdev)
- {
- struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
-@@ -4637,15 +4617,7 @@ static int asus_wmi_add(struct platform_device *pdev)
- if (err)
- goto fail_platform;
-
-- /* ensure defaults for tunables */
-- asus->ppt_pl2_sppt = 5;
-- asus->ppt_pl1_spl = 5;
-- asus->ppt_apu_sppt = 5;
-- asus->ppt_platform_sppt = 5;
-- asus->ppt_fppt = 5;
-- asus->nv_dynamic_boost = 5;
-- asus->nv_temp_target = 75;
--
-+ init_rog_tunables(asus);
- asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU);
+@@ -4650,7 +4774,7 @@ static int asus_wmi_add(struct platform_device *pdev)
asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU);
asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE);
-@@ -4667,18 +4639,17 @@ static int asus_wmi_add(struct platform_device *pdev)
+ asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE)
+- && dmi_match(DMI_BOARD_NAME, "RC71L");
++ && dmi_check_system(asus_ally_mcu_quirk);
+
+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE))
+ asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;
+@@ -4667,18 +4791,17 @@ static int asus_wmi_add(struct platform_device *pdev)
else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE2))
asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE2;
@@ -2516,7 +4885,7 @@ index bc9c5db38324..9c80aa073758 100644
goto fail_platform_profile_setup;
err = asus_wmi_sysfs_init(asus->platform_device);
-@@ -4771,7 +4742,6 @@ static int asus_wmi_add(struct platform_device *pdev)
+@@ -4771,7 +4894,6 @@ static int asus_wmi_add(struct platform_device *pdev)
fail_input:
asus_wmi_sysfs_exit(asus->platform_device);
fail_sysfs:
@@ -2524,8 +4893,52 @@ index bc9c5db38324..9c80aa073758 100644
fail_custom_fan_curve:
fail_platform_profile_setup:
if (asus->platform_profile_support)
+diff --git a/drivers/platform/x86/intel/int3472/Makefile b/drivers/platform/x86/intel/int3472/Makefile
+index 9f16cb514397..a8aba07bf1dc 100644
+--- a/drivers/platform/x86/intel/int3472/Makefile
++++ b/drivers/platform/x86/intel/int3472/Makefile
+@@ -1,4 +1,7 @@
+ obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \
+- intel_skl_int3472_tps68470.o
+-intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o led.o common.o
+-intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o common.o
++ intel_skl_int3472_tps68470.o \
++ intel_skl_int3472_common.o
++intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o led.o
++intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o
++
++intel_skl_int3472_common-y += common.o
+diff --git a/drivers/platform/x86/intel/int3472/common.c b/drivers/platform/x86/intel/int3472/common.c
+index 9db2bb0bbba4..b3a2578e06c1 100644
+--- a/drivers/platform/x86/intel/int3472/common.c
++++ b/drivers/platform/x86/intel/int3472/common.c
+@@ -29,6 +29,7 @@ union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *i
+
+ return obj;
+ }
++EXPORT_SYMBOL_GPL(skl_int3472_get_acpi_buffer);
+
+ int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
+ {
+@@ -52,6 +53,7 @@ int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
+ kfree(obj);
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(skl_int3472_fill_cldb);
+
+ /* sensor_adev_ret may be NULL, name_ret must not be NULL */
+ int skl_int3472_get_sensor_adev_and_name(struct device *dev,
+@@ -80,3 +82,8 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev,
+
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(skl_int3472_get_sensor_adev_and_name);
++
++MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Device Driver library");
++MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
++MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
-index 3eb5cd6773ad..870f4bb57100 100644
+index 3eb5cd6773ad..a23cc8624218 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -4,6 +4,7 @@
@@ -2581,20 +4994,11 @@ index 3eb5cd6773ad..870f4bb57100 100644
static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
u32 *retval)
{
-@@ -160,4 +181,48 @@ static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
+@@ -160,4 +181,39 @@ static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
}
#endif
+/* To be used by both hid-asus and asus-wmi to determine which controls kbd_brightness */
-+#if IS_ENABLED(CONFIG_ASUS_WMI)
-+bool asus_use_hid_led(void);
-+#else
-+static inline bool asus_use_hid_led(void)
-+{
-+ return true;
-+}
-+#endif
-+
+static const struct dmi_system_id asus_use_hid_led_dmi_ids[] = {
+ {
+ .matches = {
@@ -2626,7 +5030,40 @@ index 3eb5cd6773ad..870f4bb57100 100644
+ DMI_MATCH(DMI_BOARD_NAME, "RC71L"),
+ },
+ },
-+ NULL,
++ { },
+};
+
#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 3840565ef8b0..5641b40b9cdc 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -7409,6 +7409,7 @@ enum {
+ ALC285_FIXUP_THINKPAD_X1_GEN7,
+ ALC285_FIXUP_THINKPAD_HEADSET_JACK,
+ ALC294_FIXUP_ASUS_ALLY,
++ ALC294_FIXUP_ASUS_ALLY_X,
+ ALC294_FIXUP_ASUS_ALLY_PINS,
+ ALC294_FIXUP_ASUS_ALLY_VERBS,
+ ALC294_FIXUP_ASUS_ALLY_SPEAKER,
+@@ -8875,6 +8876,12 @@ static const struct hda_fixup alc269_fixups[] = {
+ .chained = true,
+ .chain_id = ALC294_FIXUP_ASUS_ALLY_PINS
+ },
++ [ALC294_FIXUP_ASUS_ALLY_X] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = tas2781_fixup_i2c,
++ .chained = true,
++ .chain_id = ALC294_FIXUP_ASUS_ALLY_PINS
++ },
+ [ALC294_FIXUP_ASUS_ALLY_PINS] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+@@ -10307,6 +10314,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
+ SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
+ SND_PCI_QUIRK(0x1043, 0x17f3, "ROG Ally NR2301L/X", ALC294_FIXUP_ASUS_ALLY),
++ SND_PCI_QUIRK(0x1043, 0x1eb3, "ROG Ally X RC72LA", ALC294_FIXUP_ASUS_ALLY_X),
+ SND_PCI_QUIRK(0x1043, 0x1863, "ASUS UX6404VI/VV", ALC245_FIXUP_CS35L41_SPI_2),
+ SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
+ SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
diff --git a/SOURCES/dcn32-dcn301-dcn321-mpo-reverts.patch b/SOURCES/dcn32-dcn301-dcn321-mpo-reverts.patch
index 0899cdb..35084b7 100644
--- a/SOURCES/dcn32-dcn301-dcn321-mpo-reverts.patch
+++ b/SOURCES/dcn32-dcn301-dcn321-mpo-reverts.patch
@@ -91,8 +91,8 @@ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/
index 9a3cc0514a36..adde6c7b09f6 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
-@@ -1779,7 +1779,7 @@ static bool dcn321_resource_construct(
- dc->caps.color.mpc.ocsc = 1;
+@@ -1782,7 +1782,7 @@
+ dc->config.use_pipe_ctx_sync_logic = true;
dc->config.dc_mode_clk_limit_support = true;
- dc->config.enable_windowed_mpo_odm = true;
diff --git a/SOURCES/kernel-aarch64-16k-debug-fedora.config b/SOURCES/kernel-aarch64-16k-debug-fedora.config
index b46564f..1ce8390 100644
--- a/SOURCES/kernel-aarch64-16k-debug-fedora.config
+++ b/SOURCES/kernel-aarch64-16k-debug-fedora.config
@@ -10185,3 +10185,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-16k-fedora.config b/SOURCES/kernel-aarch64-16k-fedora.config
index 9fbc21c..24594e0 100644
--- a/SOURCES/kernel-aarch64-16k-fedora.config
+++ b/SOURCES/kernel-aarch64-16k-fedora.config
@@ -10156,3 +10156,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-64k-debug-rhel.config b/SOURCES/kernel-aarch64-64k-debug-rhel.config
index 4060a6b..a404466 100644
--- a/SOURCES/kernel-aarch64-64k-debug-rhel.config
+++ b/SOURCES/kernel-aarch64-64k-debug-rhel.config
@@ -8206,3 +8206,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-64k-rhel.config b/SOURCES/kernel-aarch64-64k-rhel.config
index 058a619..abb7ae0 100644
--- a/SOURCES/kernel-aarch64-64k-rhel.config
+++ b/SOURCES/kernel-aarch64-64k-rhel.config
@@ -8181,3 +8181,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-debug-fedora.config b/SOURCES/kernel-aarch64-debug-fedora.config
index 30d1b95..4ba469b 100644
--- a/SOURCES/kernel-aarch64-debug-fedora.config
+++ b/SOURCES/kernel-aarch64-debug-fedora.config
@@ -10184,3 +10184,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-debug-rhel.config b/SOURCES/kernel-aarch64-debug-rhel.config
index c5845c6..7dba0fe 100644
--- a/SOURCES/kernel-aarch64-debug-rhel.config
+++ b/SOURCES/kernel-aarch64-debug-rhel.config
@@ -8202,3 +8202,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-fedora.config b/SOURCES/kernel-aarch64-fedora.config
index c05da35..3c67f6a 100644
--- a/SOURCES/kernel-aarch64-fedora.config
+++ b/SOURCES/kernel-aarch64-fedora.config
@@ -10155,3 +10155,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-rhel.config b/SOURCES/kernel-aarch64-rhel.config
index 8277598..4450f4a 100644
--- a/SOURCES/kernel-aarch64-rhel.config
+++ b/SOURCES/kernel-aarch64-rhel.config
@@ -8177,3 +8177,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-rt-debug-rhel.config b/SOURCES/kernel-aarch64-rt-debug-rhel.config
index cb2f7f9..673311a 100644
--- a/SOURCES/kernel-aarch64-rt-debug-rhel.config
+++ b/SOURCES/kernel-aarch64-rt-debug-rhel.config
@@ -8262,3 +8262,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-aarch64-rt-rhel.config b/SOURCES/kernel-aarch64-rt-rhel.config
index 378957a..a932510 100644
--- a/SOURCES/kernel-aarch64-rt-rhel.config
+++ b/SOURCES/kernel-aarch64-rt-rhel.config
@@ -8237,3 +8237,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-ppc64le-debug-fedora.config b/SOURCES/kernel-ppc64le-debug-fedora.config
index 75b508c..0cd84a4 100644
--- a/SOURCES/kernel-ppc64le-debug-fedora.config
+++ b/SOURCES/kernel-ppc64le-debug-fedora.config
@@ -8416,3 +8416,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-ppc64le-debug-rhel.config b/SOURCES/kernel-ppc64le-debug-rhel.config
index cf747f1..f1fd5f1 100644
--- a/SOURCES/kernel-ppc64le-debug-rhel.config
+++ b/SOURCES/kernel-ppc64le-debug-rhel.config
@@ -7664,3 +7664,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-ppc64le-fedora.config b/SOURCES/kernel-ppc64le-fedora.config
index 415aa28..d0470d8 100644
--- a/SOURCES/kernel-ppc64le-fedora.config
+++ b/SOURCES/kernel-ppc64le-fedora.config
@@ -8385,3 +8385,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-ppc64le-rhel.config b/SOURCES/kernel-ppc64le-rhel.config
index 25ac725..5fd266b 100644
--- a/SOURCES/kernel-ppc64le-rhel.config
+++ b/SOURCES/kernel-ppc64le-rhel.config
@@ -7641,3 +7641,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-s390x-debug-fedora.config b/SOURCES/kernel-s390x-debug-fedora.config
index 091dc10..59ccfe6 100644
--- a/SOURCES/kernel-s390x-debug-fedora.config
+++ b/SOURCES/kernel-s390x-debug-fedora.config
@@ -8354,3 +8354,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-s390x-debug-rhel.config b/SOURCES/kernel-s390x-debug-rhel.config
index 88a84d0..f47ccc6 100644
--- a/SOURCES/kernel-s390x-debug-rhel.config
+++ b/SOURCES/kernel-s390x-debug-rhel.config
@@ -7646,3 +7646,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-s390x-fedora.config b/SOURCES/kernel-s390x-fedora.config
index 2479547..dd3adc9 100644
--- a/SOURCES/kernel-s390x-fedora.config
+++ b/SOURCES/kernel-s390x-fedora.config
@@ -8323,3 +8323,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-s390x-rhel.config b/SOURCES/kernel-s390x-rhel.config
index c9435cd..20d1a61 100644
--- a/SOURCES/kernel-s390x-rhel.config
+++ b/SOURCES/kernel-s390x-rhel.config
@@ -7623,3 +7623,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-s390x-zfcpdump-rhel.config b/SOURCES/kernel-s390x-zfcpdump-rhel.config
index cab9fb5..582dc9b 100644
--- a/SOURCES/kernel-s390x-zfcpdump-rhel.config
+++ b/SOURCES/kernel-s390x-zfcpdump-rhel.config
@@ -7645,3 +7645,5 @@ CONFIG_HID_APPLETB_BL=m
CONFIG_HID_APPLETB_KBD=m
CONFIG_HID_APPLE_MAGIC_BACKLIGHT=m
CONFIG_APPLE_BCE=m
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-x86_64-debug-fedora.config b/SOURCES/kernel-x86_64-debug-fedora.config
index 94664db..b691f1b 100644
--- a/SOURCES/kernel-x86_64-debug-fedora.config
+++ b/SOURCES/kernel-x86_64-debug-fedora.config
@@ -9093,3 +9093,5 @@ CONFIG_SND_SOC_SOF_IPC3=y
CONFIG_SND_SOC_SOF_INTEL_IPC4=y
CONFIG_SND_SOC_SOF_AMD_COMMON=m
CONFIG_SND_SOC_TOPOLOGY=y
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-x86_64-debug-rhel.config b/SOURCES/kernel-x86_64-debug-rhel.config
index 41c2975..210dddd 100644
--- a/SOURCES/kernel-x86_64-debug-rhel.config
+++ b/SOURCES/kernel-x86_64-debug-rhel.config
@@ -8087,3 +8087,5 @@ CONFIG_SND_SOC_SOF_AMD_ACP63=m
# CONFIG_SND_AMD_ASOC_REMBRANDT is not set
# CONFIG_SND_SOC_AMD_LEGACY_MACH is not set
CONFIG_SND_SOC_TOPOLOGY=y
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-x86_64-fedora.config b/SOURCES/kernel-x86_64-fedora.config
index 44b4660..713987a 100644
--- a/SOURCES/kernel-x86_64-fedora.config
+++ b/SOURCES/kernel-x86_64-fedora.config
@@ -9063,3 +9063,5 @@ CONFIG_SND_SOC_SOF_IPC3=y
CONFIG_SND_SOC_SOF_INTEL_IPC4=y
CONFIG_SND_SOC_SOF_AMD_COMMON=m
CONFIG_SND_SOC_TOPOLOGY=y
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-x86_64-rhel.config b/SOURCES/kernel-x86_64-rhel.config
index d9c818d..1a5ab05 100644
--- a/SOURCES/kernel-x86_64-rhel.config
+++ b/SOURCES/kernel-x86_64-rhel.config
@@ -8063,3 +8063,5 @@ CONFIG_SND_SOC_SOF_AMD_ACP63=m
# CONFIG_SND_AMD_ASOC_REMBRANDT is not set
# CONFIG_SND_SOC_AMD_LEGACY_MACH is not set
CONFIG_SND_SOC_TOPOLOGY=y
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-x86_64-rt-debug-rhel.config b/SOURCES/kernel-x86_64-rt-debug-rhel.config
index b606b47..1cb0a7f 100644
--- a/SOURCES/kernel-x86_64-rt-debug-rhel.config
+++ b/SOURCES/kernel-x86_64-rt-debug-rhel.config
@@ -8148,3 +8148,5 @@ CONFIG_SND_SOC_SOF_AMD_ACP63=m
# CONFIG_SND_AMD_ASOC_REMBRANDT is not set
# CONFIG_SND_SOC_AMD_LEGACY_MACH is not set
CONFIG_SND_SOC_TOPOLOGY=y
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel-x86_64-rt-rhel.config b/SOURCES/kernel-x86_64-rt-rhel.config
index 6084234..b75bb3f 100644
--- a/SOURCES/kernel-x86_64-rt-rhel.config
+++ b/SOURCES/kernel-x86_64-rt-rhel.config
@@ -8124,3 +8124,5 @@ CONFIG_SND_SOC_SOF_AMD_ACP63=m
# CONFIG_SND_AMD_ASOC_REMBRANDT is not set
# CONFIG_SND_SOC_AMD_LEGACY_MACH is not set
CONFIG_SND_SOC_TOPOLOGY=y
+CONFIG_HID_ASUS_ALLY=m
+CONFIG_ASUS_ARMOURY=m
diff --git a/SOURCES/kernel.changelog b/SOURCES/kernel.changelog
index 0a0213f..f665727 100644
--- a/SOURCES/kernel.changelog
+++ b/SOURCES/kernel.changelog
@@ -1,3 +1,17 @@
+* Thu Aug 29 2024 Augusto Caringi <acaringi@redhat.com> [6.10.7-0]
+- KVM: PPC: Book3S HV nestedv2: Keep nested guest HASHPKEYR in sync (Shivaprasad G Bhat)
+- KVM: PPC: Book3S HV: Add one-reg interface for HASHPKEYR register (Shivaprasad G Bhat)
+- KVM: PPC: Book3S HV nestedv2: Keep nested guest HASHKEYR in sync (Shivaprasad G Bhat)
+- KVM: PPC: Book3S HV: Add one-reg interface for HASHKEYR register (Shivaprasad G Bhat)
+- KVM: PPC: Book3S HV nestedv2: Keep nested guest DEXCR in sync (Shivaprasad G Bhat)
+- KVM: PPC: Book3S HV: Add one-reg interface for DEXCR register (Shivaprasad G Bhat)
+- Revert the F39 commits which should not have pushed (Justin M. Forbes)
+- Turn off libbpf dynamic for perf on F39 (Justin M. Forbes)
+- Revert "cpupower: Bump soname version" (Justin M. Forbes)
+- Drop soname for libcpupower.so since we reverted the bump (Justin M. Forbes)
+- Linux v6.10.7
+Resolves:
+
* Mon Aug 19 2024 Justin M. Forbes <jforbes@fedoraproject.org> [6.10.6-0]
- Add to BugsFixed (Justin M. Forbes)
- selinux: revert our use of vma_is_initial_heap() (Paul Moore)
diff --git a/SOURCES/linux-surface.patch b/SOURCES/linux-surface.patch
index dd4d3b6..303c347 100644
--- a/SOURCES/linux-surface.patch
+++ b/SOURCES/linux-surface.patch
@@ -1,4 +1,4 @@
-From fa4500c4ae1546dba5d5e4fbada8e6d0406adab0 Mon Sep 17 00:00:00 2001
+From 252c5b2e65865a2a3aa6a5400f204c47d22490ee Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 9 Jun 2024 19:48:58 +0200
Subject: [PATCH] Revert "efi/x86: Set the PE/COFF header's NX compat flag
@@ -33,9 +33,9 @@ index b5c79f43359b..a1bbedd989e4 100644
.long 0 # SizeOfStackReserve
.long 0 # SizeOfStackCommit
--
-2.45.2
+2.46.0
-From b161e7d8c1f16ef72ed5195aa97e6357e06bdc4e Mon Sep 17 00:00:00 2001
+From 1146270e92aee0b612dfe695bcf8f7131a19bcf3 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Sun, 18 Oct 2020 16:42:44 +0900
Subject: [PATCH] (surface3-oemb) add DMI matches for Surface 3 with broken DMI
@@ -134,9 +134,9 @@ index 5e2ec60e2954..207868c699f2 100644
};
--
-2.45.2
+2.46.0
-From 2497b1ba9fa349ddf764c38c46160a785a5f3475 Mon Sep 17 00:00:00 2001
+From 800e9cfe84a3eadd4dc9ae700940068e77fa8a12 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 3 Nov 2020 13:28:04 +0100
Subject: [PATCH] mwifiex: Add quirk resetting the PCI bridge on MS Surface
@@ -301,9 +301,9 @@ index d6ff964aec5b..5d30ae39d65e 100644
void mwifiex_initialize_quirks(struct pcie_service_card *card);
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
--
-2.45.2
+2.46.0
-From 52c3a74193a1e37e241dc8a8cef0a71e843a29b5 Mon Sep 17 00:00:00 2001
+From d51c5a356fee57c99a8d181825f8f941f34749d7 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Sun, 4 Oct 2020 00:11:49 +0900
Subject: [PATCH] mwifiex: pcie: disable bridge_d3 for Surface gen4+
@@ -456,9 +456,9 @@ index 5d30ae39d65e..c14eb56eb911 100644
void mwifiex_initialize_quirks(struct pcie_service_card *card);
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
--
-2.45.2
+2.46.0
-From 338d5143d47a9de3d5a25f1fa203f6b6a95864ef Mon Sep 17 00:00:00 2001
+From 317cde3654592dcb3e072d0d2fe7b4e5598cc078 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Thu, 25 Mar 2021 11:33:02 +0100
Subject: [PATCH] Bluetooth: btusb: Lower passive lescan interval on Marvell
@@ -534,9 +534,9 @@ index 789c492df6fa..1e766b6c1f9a 100644
(id->driver_info & BTUSB_MEDIATEK)) {
hdev->setup = btusb_mtk_setup;
--
-2.45.2
+2.46.0
-From 5030f889081c8676ae652623ad86b797b05d7221 Mon Sep 17 00:00:00 2001
+From 268a79fb66862ef22294397a425fd074fc336c34 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 27 Feb 2021 00:45:52 +0100
Subject: [PATCH] ath10k: Add module parameters to override board files
@@ -654,9 +654,9 @@ index bdf0552cd1c3..e062cc687689 100644
snprintf(filename, sizeof(filename), "%s/%s/%s",
dir, ar->board_name, file);
--
-2.45.2
+2.46.0
-From 318ef833ea6bf3a2ef7566bad79931b216bd7423 Mon Sep 17 00:00:00 2001
+From 9904c59dbdd422b811974893bab69fc5b4bc9a03 Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Thu, 30 Jul 2020 13:21:53 +0200
Subject: [PATCH] mei: me: Add Icelake device ID for iTouch
@@ -693,9 +693,9 @@ index 6589635f8ba3..a1df48a434e2 100644
{MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)},
--
-2.45.2
+2.46.0
-From ddcd34d797494f38ba7be0d9e46a919fda557576 Mon Sep 17 00:00:00 2001
+From b0d9ceae2f95a4e4093b07580bedc10821374555 Mon Sep 17 00:00:00 2001
From: Liban Hannan <liban.p@gmail.com>
Date: Tue, 12 Apr 2022 23:31:12 +0100
Subject: [PATCH] iommu: Use IOMMU passthrough mode for IPTS
@@ -800,9 +800,9 @@ index f55ec1fd7942..8d95579436a9 100644
{
if (risky_device(dev))
--
-2.45.2
+2.46.0
-From 6ff2cce19a707fb565e9aebf9fb2b00fe845a46a Mon Sep 17 00:00:00 2001
+From ee1ebc3f9ec7a8418f418902817b5c5f4b51c21d Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Sun, 11 Dec 2022 12:00:59 +0100
Subject: [PATCH] hid: Add support for Intel Precise Touch and Stylus
@@ -3895,9 +3895,9 @@ index 000000000000..1f966b8b32c4
+
+#endif /* IPTS_THREAD_H */
--
-2.45.2
+2.46.0
-From 52e90ab224f06fd648ca85cd43a91670a9a4e683 Mon Sep 17 00:00:00 2001
+From 0d0e07366b425e953d6dab698d62dbe9a7546994 Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Sun, 11 Dec 2022 12:03:38 +0100
Subject: [PATCH] iommu: intel: Disable source id verification for ITHC
@@ -3936,9 +3936,9 @@ index e4a70886678c..961a33b87c24 100644
* DMA alias provides us with a PCI device and alias. The only case
* where the it will return an alias on a different bus than the
--
-2.45.2
+2.46.0
-From a5da515376d209ea8610fed94888f48d9b64387f Mon Sep 17 00:00:00 2001
+From 19a947aa5cc417bd43656cf9d8bf010abdc6bc3f Mon Sep 17 00:00:00 2001
From: quo <tuple@list.ru>
Date: Sun, 11 Dec 2022 12:10:54 +0100
Subject: [PATCH] hid: Add support for Intel Touch Host Controller
@@ -6666,64 +6666,9 @@ index 000000000000..aec320d4e945
+int ithc_reset(struct ithc *ithc);
+
--
-2.45.2
+2.46.0
-From 5180e4810b868e0d3da85577b776a929cecf1d65 Mon Sep 17 00:00:00 2001
-From: Maximilian Luz <luzmaximilian@gmail.com>
-Date: Fri, 19 Apr 2024 20:41:47 +0200
-Subject: [PATCH] platform/surface: aggregator: Fix warning when controller is
- destroyed in probe
-
-There is a small window in ssam_serial_hub_probe() where the controller
-is initialized but has not been started yet. Specifically, between
-ssam_controller_init() and ssam_controller_start(). Any failure in this
-window, for example caused by a failure of serdev_device_open(),
-currently results in an incorrect warning being emitted.
-
-In particular, any failure in this window results in the controller
-being destroyed via ssam_controller_destroy(). This function checks the
-state of the controller and, in an attempt to validate that the
-controller has been cleanly shut down before we try and deallocate any
-resources, emits a warning if that state is not SSAM_CONTROLLER_STOPPED.
-
-However, since we have only just initialized the controller and have not
-yet started it, its state is SSAM_CONTROLLER_INITIALIZED. Note that this
-is the only point at which the controller has this state, as it will
-change after we start the controller with ssam_controller_start() and
-never revert back. Further, at this point no communication has taken
-place and the sender and receiver threads have not been started yet (and
-we may not even have an open serdev device either).
-
-Therefore, it is perfectly safe to call ssam_controller_destroy() with a
-state of SSAM_CONTROLLER_INITIALIZED. This, however, means that the
-warning currently being emitted is incorrect. Fix it by extending the
-check.
-
-Fixes: c167b9c7e3d6 ("platform/surface: Add Surface Aggregator subsystem")
-Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
-Patchset: surface-sam
----
- drivers/platform/surface/aggregator/controller.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
-index 7fc602e01487..7e89f547999b 100644
---- a/drivers/platform/surface/aggregator/controller.c
-+++ b/drivers/platform/surface/aggregator/controller.c
-@@ -1354,7 +1354,8 @@ void ssam_controller_destroy(struct ssam_controller *ctrl)
- if (ctrl->state == SSAM_CONTROLLER_UNINITIALIZED)
- return;
-
-- WARN_ON(ctrl->state != SSAM_CONTROLLER_STOPPED);
-+ WARN_ON(ctrl->state != SSAM_CONTROLLER_STOPPED &&
-+ ctrl->state != SSAM_CONTROLLER_INITIALIZED);
-
- /*
- * Note: New events could still have been received after the previous
---
-2.45.2
-
-From 144dbc865c07df0290009d509b31635aac53a907 Mon Sep 17 00:00:00 2001
+From 00b833401e8060eb50db269e0681383454a74848 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 22 Oct 2023 14:57:11 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Add support for
@@ -6754,9 +6699,9 @@ index 1c4d74db08c9..f826489dc69d 100644
{ "MSHW0123", (unsigned long)ssam_node_group_sls },
--
-2.45.2
+2.46.0
-From 7b906ae84a56322a5098c77a774f5fb00b4318a5 Mon Sep 17 00:00:00 2001
+From 9e13165394bf1898d05c7d5a4a5adb1767d2307e Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Mon, 20 Nov 2023 19:47:00 +0100
Subject: [PATCH] platform/surface: aggregator_registry: Add support for
@@ -6824,9 +6769,9 @@ index f826489dc69d..ef59a7b66667 100644
{ },
};
--
-2.45.2
+2.46.0
-From d602c3714f0cc654b90de7800f844d6201eaa66b Mon Sep 17 00:00:00 2001
+From 83719d2cd70ad6ac1df993782e757ded15e881cc Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 9 Jun 2024 20:05:57 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Add support for
@@ -6881,9 +6826,9 @@ index ef59a7b66667..70a2ea5a1957 100644
{ "MSHW0118", (unsigned long)ssam_node_group_slg1 },
--
-2.45.2
+2.46.0
-From 4bde7be038c7dced1b596c7d41e6f0bb3043d301 Mon Sep 17 00:00:00 2001
+From c188646846cc6e9db1134eb62208d088ce615312 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 30 Dec 2023 18:07:54 +0100
Subject: [PATCH] hwmon: Add thermal sensor driver for Surface Aggregator
@@ -7109,9 +7054,9 @@ index 000000000000..48c3e826713f
+MODULE_DESCRIPTION("Thermal sensor subsystem driver for Surface System Aggregator Module");
+MODULE_LICENSE("GPL");
--
-2.45.2
+2.46.0
-From ae82a35c632785771ebe2ad7f48006a1eb8f6a91 Mon Sep 17 00:00:00 2001
+From 31d334453ebc65b7868bf33b1963553586e64fa3 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 30 Dec 2023 18:12:23 +0100
Subject: [PATCH] hwmon: surface_temp: Add support for sensor names
@@ -7304,9 +7249,9 @@ index 48c3e826713f..4c08926139db 100644
"surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info,
NULL);
--
-2.45.2
+2.46.0
-From 6a80e0b93ce1d8cf9d1b7e383b4b951fb4908294 Mon Sep 17 00:00:00 2001
+From 36174000616d130e9b4655d69eb3bd5b07adbecb Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Mon, 10 Jun 2024 21:47:47 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Add fan and thermal
@@ -7333,9 +7278,9 @@ index 70a2ea5a1957..6b568804f70b 100644
&ssam_node_hid_main_touchpad,
&ssam_node_hid_main_iid5,
--
-2.45.2
+2.46.0
-From 3175ecd829a778ffef35956d8785877bb76fe4b0 Mon Sep 17 00:00:00 2001
+From e32f317be4ad620fb6683b62ad9e883f37e17f57 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Mon, 10 Jun 2024 21:48:02 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Add fan and thermal
@@ -7362,9 +7307,9 @@ index 6b568804f70b..9046df95c043 100644
&ssam_node_hid_sam_keyboard,
&ssam_node_hid_sam_penstash,
--
-2.45.2
+2.46.0
-From aeef49471d7ec17f243c685b85c0c870c99e9e3d Mon Sep 17 00:00:00 2001
+From ebf64f6dcf1bdf0dbe80b5ec5e3d4b8a6cfab41e Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Fri, 28 Jun 2024 22:31:37 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Add Support for
@@ -7416,9 +7361,9 @@ index 9046df95c043..058f4edd8b66 100644
{ "MSHW0107", (unsigned long)ssam_node_group_gen5 },
--
-2.45.2
+2.46.0
-From 56def3328ab5c84c33a87c062448f1f97e545282 Mon Sep 17 00:00:00 2001
+From 8dac7a369f2f1c461750a3c3f6d93caae9566ace Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 25 Jul 2020 17:19:53 +0200
Subject: [PATCH] i2c: acpi: Implement RawBytes read access
@@ -7528,9 +7473,9 @@ index 14ae0cfc325e..a3a9f81fb47f 100644
dev_warn(&adapter->dev, "protocol 0x%02x not supported for client 0x%02x\n",
accessor_type, client->addr);
--
-2.45.2
+2.46.0
-From 99ca5a4092ea27b42c256940694e13a8f2abd457 Mon Sep 17 00:00:00 2001
+From fe964119c511036a560d1dfcbec1196ae4ed1621 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 13 Feb 2021 16:41:18 +0100
Subject: [PATCH] platform/surface: Add driver for Surface Book 1 dGPU switch
@@ -7751,9 +7696,9 @@ index 000000000000..8b816ed8f35c
+MODULE_DESCRIPTION("Discrete GPU Power-Switch for Surface Book 1");
+MODULE_LICENSE("GPL");
--
-2.45.2
+2.46.0
-From 1afbbb29ce7bd15bbf4f812cbc034514bb667b43 Mon Sep 17 00:00:00 2001
+From d811fb8e32e1327baf131c85522aee281f4281af Mon Sep 17 00:00:00 2001
From: Sachi King <nakato@nakato.io>
Date: Tue, 5 Oct 2021 00:05:09 +1100
Subject: [PATCH] Input: soc_button_array - support AMD variant Surface devices
@@ -7828,9 +7773,9 @@ index f6d060377d18..b8603f74eb28 100644
/*
--
-2.45.2
+2.46.0
-From 888fc8298e984f1cb23ac66e91a02d2e7f174919 Mon Sep 17 00:00:00 2001
+From e21138766921f4a22e710b4858f75f98e308c61d Mon Sep 17 00:00:00 2001
From: Sachi King <nakato@nakato.io>
Date: Tue, 5 Oct 2021 00:22:57 +1100
Subject: [PATCH] platform/surface: surfacepro3_button: don't load on amd
@@ -7900,9 +7845,9 @@ index 2755601f979c..4240c98ca226 100644
--
-2.45.2
+2.46.0
-From 201768f64dd2128028bed46940ecd9ea85483973 Mon Sep 17 00:00:00 2001
+From a19b7328ccb6c090354593fa039e5283140a5e69 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 18 Feb 2023 01:02:49 +0100
Subject: [PATCH] USB: quirks: Add USB_QUIRK_DELAY_INIT for Surface Go 3
@@ -7941,9 +7886,9 @@ index 13171454f959..a83beefd25f3 100644
{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
--
-2.45.2
+2.46.0
-From 9ae353f19e719e680d93710ec61aef6edefab6f1 Mon Sep 17 00:00:00 2001
+From 99fb371b3a11e3c3d67d29673508911b81a1408c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Thu, 5 Nov 2020 13:09:45 +0100
Subject: [PATCH] hid/multitouch: Turn off Type Cover keyboard backlight when
@@ -8174,9 +8119,9 @@ index 56fc78841f24..a266449065a0 100644
{ .driver_data = MT_CLS_GOOGLE,
HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
--
-2.45.2
+2.46.0
-From 922102cc310758a2655f9bb3eb9a413bc551b1a7 Mon Sep 17 00:00:00 2001
+From 7b797164a3f2ecf402b8f24d5123e74914b09064 Mon Sep 17 00:00:00 2001
From: PJungkamp <p.jungkamp@gmail.com>
Date: Fri, 25 Feb 2022 12:04:25 +0100
Subject: [PATCH] hid/multitouch: Add support for surface pro type cover tablet
@@ -8473,9 +8418,9 @@ index a266449065a0..060c706e936a 100644
unregister_pm_notifier(&td->pm_notifier);
del_timer_sync(&td->release_timer);
--
-2.45.2
+2.46.0
-From dc75889e49675c868d33320a996c33d183fee94a Mon Sep 17 00:00:00 2001
+From e26e0570db9e2dbb37e075ef7a88270fe793fb94 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 19 Feb 2023 22:12:24 +0100
Subject: [PATCH] PCI: Add quirk to prevent calling shutdown mehtod
@@ -8570,9 +8515,9 @@ index cafc5ab1cbcb..64bb5aca2c13 100644
atomic_t enable_cnt; /* pci_enable_device has been called */
--
-2.45.2
+2.46.0
-From 41732ed4458eb3b08b4a658f1cd617d83c90cec6 Mon Sep 17 00:00:00 2001
+From bed56a2a67db8c5934008ed83fa0bbd71360ab02 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 12 Mar 2023 01:41:57 +0100
Subject: [PATCH] platform/surface: gpe: Add support for Surface Pro 9
@@ -8621,9 +8566,9 @@ index 62fd4004db31..103fc4468262 100644
.ident = "Surface Book 1",
.matches = {
--
-2.45.2
+2.46.0
-From 2d145df171e42d90ac54b0bdc42e77337e99679a Mon Sep 17 00:00:00 2001
+From 0a70aafbfa7ad39054c0974e428935c9d9e48cf1 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 10 Oct 2021 20:56:57 +0200
Subject: [PATCH] ACPI: delay enumeration of devices with a _DEP pointing to an
@@ -8697,9 +8642,9 @@ index 503773707e01..a292a20c4315 100644
* Do not enumerate devices with enumeration_by_parent flag set as
* they will be enumerated by their respective parents.
--
-2.45.2
+2.46.0
-From f0e749b5b8f19dca95eaf7b24c925f7684669993 Mon Sep 17 00:00:00 2001
+From bdae5b6a0e462398fa6035a2f0de8efae144abe4 Mon Sep 17 00:00:00 2001
From: zouxiaoh <xiaohong.zou@intel.com>
Date: Fri, 25 Jun 2021 08:52:59 +0800
Subject: [PATCH] iommu: intel-ipu: use IOMMU passthrough mode for Intel IPUs
@@ -8807,9 +8752,9 @@ index 8d95579436a9..cbfb59ed5985 100644
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9D3E, quirk_iommu_ipts);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x34E4, quirk_iommu_ipts);
--
-2.45.2
+2.46.0
-From 197059f84ca0575efb65a4667023e9e14c53fe87 Mon Sep 17 00:00:00 2001
+From aa044fab288ddf51ad963effe090d0b548d83243 Mon Sep 17 00:00:00 2001
From: Daniel Scally <djrscally@gmail.com>
Date: Sun, 10 Oct 2021 20:57:02 +0200
Subject: [PATCH] platform/x86: int3472: Enable I2c daisy chain
@@ -8844,9 +8789,9 @@ index 1e107fd49f82..e3e1696e7f0e 100644
return 0;
--
-2.45.2
+2.46.0
-From cff4d571011727ee47c29f21c9b1d255ca4efe8e Mon Sep 17 00:00:00 2001
+From 12da0a015e6d71071561668950a4fb5e33220af8 Mon Sep 17 00:00:00 2001
From: Daniel Scally <dan.scally@ideasonboard.com>
Date: Thu, 2 Mar 2023 12:59:39 +0000
Subject: [PATCH] platform/x86: int3472: Remap reset GPIO for INT347E
@@ -8899,9 +8844,9 @@ index 07b302e09340..1d3097bc7e48 100644
agpio, func, polarity);
if (ret)
--
-2.45.2
+2.46.0
-From 31cab2b99a833eab39602f61e3f3f801884f8980 Mon Sep 17 00:00:00 2001
+From ddc65d1014592b1fe4d6e16c9badcc928e577b3b Mon Sep 17 00:00:00 2001
From: Daniel Scally <dan.scally@ideasonboard.com>
Date: Tue, 21 Mar 2023 13:45:26 +0000
Subject: [PATCH] media: i2c: Clarify that gain is Analogue gain in OV7251
@@ -8938,9 +8883,9 @@ index 30f61e04ecaf..9c1292ca8552 100644
V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(ov7251_test_pattern_menu) - 1,
--
-2.45.2
+2.46.0
-From b17d182f347660c7c2e873d0a2e21b57ce44858c Mon Sep 17 00:00:00 2001
+From ea560c5a7e55695438ac99fbd363352991fe62af Mon Sep 17 00:00:00 2001
From: Daniel Scally <dan.scally@ideasonboard.com>
Date: Wed, 22 Mar 2023 11:01:42 +0000
Subject: [PATCH] media: v4l2-core: Acquire privacy led in
@@ -8989,9 +8934,9 @@ index 89c7192148df..44eca113e772 100644
if (ret < 0)
goto out_cleanup;
--
-2.45.2
+2.46.0
-From c51c33aa1cdbea15c1b493b300f66408d8306bd9 Mon Sep 17 00:00:00 2001
+From 0c59f9eee1c8dc8ea4d99f8b1a07b342ef5e425d Mon Sep 17 00:00:00 2001
From: Kate Hsuan <hpa@redhat.com>
Date: Tue, 21 Mar 2023 23:37:16 +0800
Subject: [PATCH] platform: x86: int3472: Add MFD cell for tps68470 LED
@@ -9030,9 +8975,9 @@ index e3e1696e7f0e..423dc555093f 100644
for (i = 0; i < board_data->n_gpiod_lookups; i++)
gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
--
-2.45.2
+2.46.0
-From b37b24f5e18fd586452ec4a7cc978c3360074e42 Mon Sep 17 00:00:00 2001
+From 8f69fe36b3d6052c7f41182041fc59ea84515066 Mon Sep 17 00:00:00 2001
From: Kate Hsuan <hpa@redhat.com>
Date: Tue, 21 Mar 2023 23:37:17 +0800
Subject: [PATCH] include: mfd: tps68470: Add masks for LEDA and LEDB
@@ -9071,9 +9016,9 @@ index 7807fa329db0..2d2abb25b944 100644
+
#endif /* __LINUX_MFD_TPS68470_H */
--
-2.45.2
+2.46.0
-From 8ef5b1010e49d11964f2dd7da3c3271f5f9bf503 Mon Sep 17 00:00:00 2001
+From 457ccb4dad651a58bc24e4c49fcc95a81e3762bb Mon Sep 17 00:00:00 2001
From: Kate Hsuan <hpa@redhat.com>
Date: Tue, 21 Mar 2023 23:37:18 +0800
Subject: [PATCH] leds: tps68470: Add LED control for tps68470
@@ -9322,9 +9267,9 @@ index 000000000000..35aeb5db89c8
+MODULE_DESCRIPTION("LED driver for TPS68470 PMIC");
+MODULE_LICENSE("GPL v2");
--
-2.45.2
+2.46.0
-From ca688e057ec8149ccd01d2c7876b707aa33bdbc8 Mon Sep 17 00:00:00 2001
+From 281dcaef04abcc6a75b34c6f69f8f608b68912cf Mon Sep 17 00:00:00 2001
From: mojyack <mojyack@gmail.com>
Date: Sat, 3 Feb 2024 12:59:53 +0900
Subject: [PATCH] media: staging: ipu3-imgu: Fix multiple calls of s_stream on
@@ -9369,9 +9314,9 @@ index 3df58eb3e882..81aff2d5d898 100644
r = imgu_s_stream(imgu, false);
if (!r)
--
-2.45.2
+2.46.0
-From d267b727836905eaefc1541eb743479338827db5 Mon Sep 17 00:00:00 2001
+From f1d09776b3c5026bfd4d035bbca5be3f8e41b247 Mon Sep 17 00:00:00 2001
From: mojyack <mojyack@gmail.com>
Date: Tue, 26 Mar 2024 05:55:44 +0900
Subject: [PATCH] media: i2c: dw9719: fix probe error on surface go 2
@@ -9401,9 +9346,9 @@ index c626ed845928..0094cfda57ea 100644
cci_write(dw9719->regmap, DW9719_CONTROL, 1, &ret);
--
-2.45.2
+2.46.0
-From 68bfb06084548d1f7d23fc2c5e7c4b70262078b3 Mon Sep 17 00:00:00 2001
+From 29121bd1e5b235572d56645abdb8f54a31bf476e Mon Sep 17 00:00:00 2001
From: Sachi King <nakato@nakato.io>
Date: Sat, 29 May 2021 17:47:38 +1000
Subject: [PATCH] ACPI: Add quirk for Surface Laptop 4 AMD missing irq 7
@@ -9468,9 +9413,9 @@ index 4bf82dbd2a6b..7a8cb090c656 100644
mp_config_acpi_legacy_irqs();
--
-2.45.2
+2.46.0
-From f72f4d6bc2d6e1f1ec68422cffaed5e77820c6c5 Mon Sep 17 00:00:00 2001
+From f8d58835a76ce8ea016c0fcd75ddb93a95ca14c6 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Thu, 3 Jun 2021 14:04:26 +0200
Subject: [PATCH] ACPI: Add AMD 13" Surface Laptop 4 model to irq 7 override
@@ -9510,9 +9455,9 @@ index 7a8cb090c656..0faafc323e67 100644
};
--
-2.45.2
+2.46.0
-From ca8843e551ab3528c958bc8efaa51356dbdc23de Mon Sep 17 00:00:00 2001
+From 5c662b210790b2b297457de3e84274cc062b215e Mon Sep 17 00:00:00 2001
From: "Bart Groeneveld | GPX Solutions B.V" <bart@gpxbv.nl>
Date: Mon, 5 Dec 2022 16:08:46 +0100
Subject: [PATCH] acpi: allow usage of acpi_tad on HW-reduced platforms
@@ -9620,5 +9565,5 @@ index 1d670dbe4d1d..71c9e375ca1c 100644
ret = sysfs_create_group(&dev->kobj, &acpi_tad_dc_attr_group);
if (ret)
--
-2.45.2
+2.46.0
diff --git a/SOURCES/patch-6.10-redhat.patch b/SOURCES/patch-6.10-redhat.patch
index 01f9da9..3ef3fe6 100644
--- a/SOURCES/patch-6.10-redhat.patch
+++ b/SOURCES/patch-6.10-redhat.patch
@@ -1,6 +1,12 @@
+ Documentation/virt/kvm/api.rst | 3 +
Makefile | 12 ++
arch/arm/Kconfig | 4 +-
arch/arm64/Kconfig | 2 +-
+ arch/powerpc/include/asm/kvm_host.h | 3 +
+ arch/powerpc/include/uapi/asm/kvm.h | 3 +
+ arch/powerpc/kvm/book3s_hv.c | 18 +++
+ arch/powerpc/kvm/book3s_hv.h | 3 +
+ arch/powerpc/kvm/book3s_hv_nestedv2.c | 18 +++
arch/s390/include/asm/ipl.h | 1 +
arch/s390/kernel/ipl.c | 5 +
arch/s390/kernel/setup.c | 4 +
@@ -23,7 +29,6 @@
drivers/input/rmi4/rmi_driver.c | 124 ++++++++++-------
drivers/iommu/iommu.c | 22 +++
drivers/media/pci/intel/ipu-bridge.c | 40 ++++--
- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 13 +-
drivers/pci/quirks.c | 24 ++++
drivers/scsi/sd.c | 10 ++
drivers/usb/core/hub.c | 7 +
@@ -40,11 +45,26 @@
security/lockdown/Kconfig | 13 ++
security/lockdown/lockdown.c | 1 +
security/security.c | 12 ++
- security/selinux/hooks.c | 12 +-
- 43 files changed, 800 insertions(+), 260 deletions(-)
+ 47 files changed, 827 insertions(+), 256 deletions(-)
+diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
+index eec8df1dde06..88f49dd10cd0 100644
+--- a/Documentation/virt/kvm/api.rst
++++ b/Documentation/virt/kvm/api.rst
+@@ -2445,8 +2445,11 @@ registers, find a list below:
+ PPC KVM_REG_PPC_PSSCR 64
+ PPC KVM_REG_PPC_DEC_EXPIRY 64
+ PPC KVM_REG_PPC_PTCR 64
++ PPC KVM_REG_PPC_HASHKEYR 64
++ PPC KVM_REG_PPC_HASHPKEYR 64
+ PPC KVM_REG_PPC_DAWR1 64
+ PPC KVM_REG_PPC_DAWRX1 64
++ PPC KVM_REG_PPC_DEXCR 64
+ PPC KVM_REG_PPC_TM_GPR0 64
+ ...
+ PPC KVM_REG_PPC_TM_GPR31 64
diff --git a/Makefile b/Makefile
-index 361a70264e1f..eaf69484d4ce 100644
+index ab77d171e268..c46aa8337181 100644
--- a/Makefile
+++ b/Makefile
@@ -22,6 +22,18 @@ $(if $(filter __%, $(MAKECMDGOALS)), \
@@ -95,6 +115,120 @@ index 11bbdc15c6e5..9cecc1448e3c 100644
help
For systems with 52-bit userspace VAs enabled, the kernel will attempt
to maintain compatibility with older software by providing 48-bit VAs
+diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
+index 8abac532146e..6a0c771d3ce8 100644
+--- a/arch/powerpc/include/asm/kvm_host.h
++++ b/arch/powerpc/include/asm/kvm_host.h
+@@ -599,6 +599,9 @@ struct kvm_vcpu_arch {
+ ulong dawrx0;
+ ulong dawr1;
+ ulong dawrx1;
++ ulong dexcr;
++ ulong hashkeyr;
++ ulong hashpkeyr;
+ ulong ciabr;
+ ulong cfar;
+ ulong ppr;
+diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
+index 1691297a766a..eaeda001784e 100644
+--- a/arch/powerpc/include/uapi/asm/kvm.h
++++ b/arch/powerpc/include/uapi/asm/kvm.h
+@@ -645,6 +645,9 @@ struct kvm_ppc_cpu_char {
+ #define KVM_REG_PPC_SIER3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc3)
+ #define KVM_REG_PPC_DAWR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc4)
+ #define KVM_REG_PPC_DAWRX1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc5)
++#define KVM_REG_PPC_DEXCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc6)
++#define KVM_REG_PPC_HASHKEYR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc7)
++#define KVM_REG_PPC_HASHPKEYR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc8)
+
+ /* Transactional Memory checkpointed state:
+ * This is all GPRs, all VSX regs and a subset of SPRs
+diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
+index d8352e4d9cdc..36068c3ed8a7 100644
+--- a/arch/powerpc/kvm/book3s_hv.c
++++ b/arch/powerpc/kvm/book3s_hv.c
+@@ -2349,6 +2349,15 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
+ case KVM_REG_PPC_DAWRX1:
+ *val = get_reg_val(id, kvmppc_get_dawrx1_hv(vcpu));
+ break;
++ case KVM_REG_PPC_DEXCR:
++ *val = get_reg_val(id, kvmppc_get_dexcr_hv(vcpu));
++ break;
++ case KVM_REG_PPC_HASHKEYR:
++ *val = get_reg_val(id, kvmppc_get_hashkeyr_hv(vcpu));
++ break;
++ case KVM_REG_PPC_HASHPKEYR:
++ *val = get_reg_val(id, kvmppc_get_hashpkeyr_hv(vcpu));
++ break;
+ case KVM_REG_PPC_CIABR:
+ *val = get_reg_val(id, kvmppc_get_ciabr_hv(vcpu));
+ break;
+@@ -2592,6 +2601,15 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
+ case KVM_REG_PPC_DAWRX1:
+ kvmppc_set_dawrx1_hv(vcpu, set_reg_val(id, *val) & ~DAWRX_HYP);
+ break;
++ case KVM_REG_PPC_DEXCR:
++ kvmppc_set_dexcr_hv(vcpu, set_reg_val(id, *val));
++ break;
++ case KVM_REG_PPC_HASHKEYR:
++ kvmppc_set_hashkeyr_hv(vcpu, set_reg_val(id, *val));
++ break;
++ case KVM_REG_PPC_HASHPKEYR:
++ kvmppc_set_hashpkeyr_hv(vcpu, set_reg_val(id, *val));
++ break;
+ case KVM_REG_PPC_CIABR:
+ kvmppc_set_ciabr_hv(vcpu, set_reg_val(id, *val));
+ /* Don't allow setting breakpoints in hypervisor code */
+diff --git a/arch/powerpc/kvm/book3s_hv.h b/arch/powerpc/kvm/book3s_hv.h
+index 47b2c815641e..a404c9b221c1 100644
+--- a/arch/powerpc/kvm/book3s_hv.h
++++ b/arch/powerpc/kvm/book3s_hv.h
+@@ -116,6 +116,9 @@ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawr0, 64, KVMPPC_GSID_DAWR0)
+ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawr1, 64, KVMPPC_GSID_DAWR1)
+ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawrx0, 64, KVMPPC_GSID_DAWRX0)
+ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawrx1, 64, KVMPPC_GSID_DAWRX1)
++KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dexcr, 64, KVMPPC_GSID_DEXCR)
++KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(hashkeyr, 64, KVMPPC_GSID_HASHKEYR)
++KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(hashpkeyr, 64, KVMPPC_GSID_HASHPKEYR)
+ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(ciabr, 64, KVMPPC_GSID_CIABR)
+ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(wort, 64, KVMPPC_GSID_WORT)
+ KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(ppr, 64, KVMPPC_GSID_PPR)
+diff --git a/arch/powerpc/kvm/book3s_hv_nestedv2.c b/arch/powerpc/kvm/book3s_hv_nestedv2.c
+index 342f58314770..eeecea8f202b 100644
+--- a/arch/powerpc/kvm/book3s_hv_nestedv2.c
++++ b/arch/powerpc/kvm/book3s_hv_nestedv2.c
+@@ -193,6 +193,15 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb,
+ case KVMPPC_GSID_DAWRX1:
+ rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx1);
+ break;
++ case KVMPPC_GSID_DEXCR:
++ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dexcr);
++ break;
++ case KVMPPC_GSID_HASHKEYR:
++ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hashkeyr);
++ break;
++ case KVMPPC_GSID_HASHPKEYR:
++ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hashpkeyr);
++ break;
+ case KVMPPC_GSID_CIABR:
+ rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ciabr);
+ break;
+@@ -445,6 +454,15 @@ static int gs_msg_ops_vcpu_refresh_info(struct kvmppc_gs_msg *gsm,
+ case KVMPPC_GSID_DAWRX1:
+ vcpu->arch.dawrx1 = kvmppc_gse_get_u32(gse);
+ break;
++ case KVMPPC_GSID_DEXCR:
++ vcpu->arch.dexcr = kvmppc_gse_get_u64(gse);
++ break;
++ case KVMPPC_GSID_HASHKEYR:
++ vcpu->arch.hashkeyr = kvmppc_gse_get_u64(gse);
++ break;
++ case KVMPPC_GSID_HASHPKEYR:
++ vcpu->arch.hashpkeyr = kvmppc_gse_get_u64(gse);
++ break;
+ case KVMPPC_GSID_CIABR:
+ vcpu->arch.ciabr = kvmppc_gse_get_u64(gse);
+ break;
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h
index b0d00032479d..afb9544fb007 100644
--- a/arch/s390/include/asm/ipl.h
@@ -569,7 +703,7 @@ index 1687483ff319..390b67f19181 100644
return ctx.rc;
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
-index 503773707e01..2fead21fcb07 100644
+index cdc5a74092c7..45679565878f 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1793,6 +1793,15 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
@@ -1523,30 +1657,6 @@ index 61750cc98d70..a0e9a71580b5 100644
};
static const struct ipu_property_names prop_names = {
-diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-index 5fe0e671ecb3..826b768196e2 100644
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -4320,9 +4320,16 @@ brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa,
- /* Single PMK operation */
- pmk_op->count = cpu_to_le16(1);
- length += sizeof(struct brcmf_pmksa_v3);
-- memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN);
-- memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
-- pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN;
-+ if (pmksa->bssid)
-+ memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN);
-+ if (pmksa->pmkid) {
-+ memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
-+ pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN;
-+ }
-+ if (pmksa->ssid && pmksa->ssid_len) {
-+ memcpy(pmk_op->pmk[0].ssid.SSID, pmksa->ssid, pmksa->ssid_len);
-+ pmk_op->pmk[0].ssid.SSID_len = pmksa->ssid_len;
-+ }
- pmk_op->pmk[0].time_left = cpu_to_le32(alive ? BRCMF_PMKSA_NO_EXPIRY : 0);
- }
-
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 568410e64ce6..6afbaee83950 100644
--- a/drivers/pci/quirks.c
@@ -1957,26 +2067,3 @@ index 8cee5b6c6e6d..489e25946bf9 100644
#ifdef CONFIG_PERF_EVENTS
/**
* security_perf_event_open() - Check if a perf event open is allowed
-diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index 55c78c318ccd..bfa61e005aac 100644
---- a/security/selinux/hooks.c
-+++ b/security/selinux/hooks.c
-@@ -3852,7 +3852,17 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
- if (default_noexec &&
- (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
- int rc = 0;
-- if (vma_is_initial_heap(vma)) {
-+ /*
-+ * We don't use the vma_is_initial_heap() helper as it has
-+ * a history of problems and is currently broken on systems
-+ * where there is no heap, e.g. brk == start_brk. Before
-+ * replacing the conditional below with vma_is_initial_heap(),
-+ * or something similar, please ensure that the logic is the
-+ * same as what we have below or you have tested every possible
-+ * corner case you can think to test.
-+ */
-+ if (vma->vm_start >= vma->vm_mm->start_brk &&
-+ vma->vm_end <= vma->vm_mm->brk) {
- rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
- PROCESS__EXECHEAP, NULL);
- } else if (!vma->vm_file && (vma_is_initial_stack(vma) ||
diff --git a/SOURCES/t2linux.patch b/SOURCES/t2linux.patch
index 566de6c..46faa57 100644
--- a/SOURCES/t2linux.patch
+++ b/SOURCES/t2linux.patch
@@ -1477,7 +1477,7 @@ diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index ce71b53ea6c5..fecec1d61393 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
-@@ -29,6 +29,8 @@ obj-$(CONFIG_HID_ALPS) += hid-alps.o
+@@ -29,6 +29,8 @@
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o
obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o
@@ -1485,7 +1485,7 @@ index ce71b53ea6c5..fecec1d61393 100644
+obj-$(CONFIG_HID_APPLETB_KBD) += hid-appletb-kbd.o
obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
obj-$(CONFIG_HID_ASUS) += hid-asus.o
- obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
+ obj-$(CONFIG_HID_ASUS_ALLY) += hid-asus-ally.o
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index bd022e004356..6dedb84d7cc3 100644
--- a/drivers/hid/hid-apple.c
diff --git a/SOURCES/v14.8-0004-HID-asus-add-ROG-Ally-xpad-settings.patch b/SOURCES/v14.8-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
deleted file mode 100644
index 2a21e86..0000000
--- a/SOURCES/v14.8-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
+++ /dev/null
@@ -1,2320 +0,0 @@
-From 9fd3de7abd22d7e67a8757e3f67410302359fec7 Mon Sep 17 00:00:00 2001
-From: "Luke D. Jones" <luke@ljones.dev>
-Date: Fri, 1 Dec 2023 16:57:19 +1300
-Subject: [PATCH v14.7 4/4] HID: asus: add ROG Ally xpad settings
-
-- move ROG specific stuff to new .c
-- add a header for common parts
-- add xpad mode
-- add deadzones
-- add anti-deadzones
-- add gamepad button remapping
-- add gamepad mapping reset for xpad and wasd modes
-- add turbo mode for individual buttons
-- add joystick response curves
-- add vibration intensity settings
-- add calibration setting
----
- .../ABI/testing/sysfs-driver-hid-asus | 85 +
- drivers/hid/Makefile | 2 +
- drivers/hid/{hid-asus.c => hid-asus-core.c} | 71 +-
- drivers/hid/hid-asus-rog.c | 1469 +++++++++++++++++
- drivers/hid/hid-asus-rog.h | 482 ++++++
- drivers/hid/hid-asus.h | 58 +
- 6 files changed, 2126 insertions(+), 41 deletions(-)
- create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-asus
- rename drivers/hid/{hid-asus.c => hid-asus-core.c} (96%)
- create mode 100644 drivers/hid/hid-asus-rog.c
- create mode 100644 drivers/hid/hid-asus-rog.h
- create mode 100644 drivers/hid/hid-asus.h
-
-diff --git a/Documentation/ABI/testing/sysfs-driver-hid-asus b/Documentation/ABI/testing/sysfs-driver-hid-asus
-new file mode 100644
-index 000000000000..df5b0c5b0702
---- /dev/null
-+++ b/Documentation/ABI/testing/sysfs-driver-hid-asus
-@@ -0,0 +1,85 @@
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/gamepad_mode
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Set the mode the ROG Ally xpad operates in:
-+ - 1 = Game mode
-+ - 2 = WASD mode
-+ - 3 = Mouse mode
-+ This setting applies instantly and applies settings that were previously changed
-+ under that mode which are:
-+ - deadzones
-+ - anti-deadzones
-+ - button mapping
-+ - button turbo settings
-+ - response curves
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/apply
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Apply the settings that have been stored in attributes so far. Because there are
-+ many individual settings across a dozen packets this separation is required to
-+ prevent spamming the MCU when userspace applications apply many changes at once.
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/reset_btn_mapping
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Reset a gamepad mode to its default button mapping.
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y/z>_<left/right>/deadzone
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Set the inner and outer deadzones of joysticks and triggers. These settings are not
-+ written to the MCU until `apply` is set.
-+ - range 0-64 (corresponds to 0-100%)
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y/z>_<left/right>/deadzone_index
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Descriptive labels for joystick deadzone array.
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y>_<left/right>/anti-deadzone
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Set the joystick anti-deadzone feature:
-+ - range 0-32 (corresponds to 0-50%)
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y/z>_<left/right>/calibration
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Calibration values for the joysticks and trigger analogues. There are no default
-+ values as the calibration is determined in userspace.
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y/z>_<left/right>/calibration_index
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Descriptive labels for joystick and triggers calibration array.
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y>_<left/right>/rc_point<n>
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Set the joystick response curve. There are 4 points available with 1 being the lowest
-+ point and 4 being the highest point.
-+ - range 0-64 (corresponds to 0-100%)
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y>_<left/right>/rc_point_index
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Descriptive labels for joystick response curve points.
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/btn_<label>/turbo
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Set the turbo mode of the button:
-+ - 0 = no turbo, a separate press and release is registered on press and release
-+ - 1-16 = interval between presses if button held down in steps of 1000ms/16
-+ These settings are not written to the MCU until `apply` is set.
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/vibration_intensity
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Set the vibration intensity for left and right haptics. Applies instantly.
-+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/vibration_intensity_index
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Descriptive labels for index points of vibration_intensity.
-\ No newline at end of file
-diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
-index 8a06d0f840bc..7c2436ed05d6 100644
---- a/drivers/hid/Makefile
-+++ b/drivers/hid/Makefile
-@@ -23,6 +23,8 @@ hid-logitech-$(CONFIG_LOGIWHEELS_FF) += hid-lg4ff.o
- hid-wiimote-y := hid-wiimote-core.o hid-wiimote-modules.o
- hid-wiimote-$(CONFIG_DEBUG_FS) += hid-wiimote-debug.o
-
-+hid-asus-y := hid-asus-core.o hid-asus-rog.o
-+
- obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
- obj-$(CONFIG_HID_ACCUTOUCH) += hid-accutouch.o
- obj-$(CONFIG_HID_ALPS) += hid-alps.o
-diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus-core.c
-similarity index 96%
-rename from drivers/hid/hid-asus.c
-rename to drivers/hid/hid-asus-core.c
-index 3a1a6024d299..026705c43ee1 100644
---- a/drivers/hid/hid-asus.c
-+++ b/drivers/hid/hid-asus-core.c
-@@ -20,9 +20,8 @@
- * Copyright (c) 2016 Frederik Wenigwieser <frederik.wenigwieser@gmail.com>
- */
-
--/*
-- */
--
-+#include <asm-generic/errno-base.h>
-+#include <asm-generic/errno.h>
- #include <linux/dmi.h>
- #include <linux/hid.h>
- #include <linux/module.h>
-@@ -32,6 +31,7 @@
- #include <linux/power_supply.h>
- #include <linux/leds.h>
-
-+#include "hid-asus.h"
- #include "hid-ids.h"
-
- MODULE_AUTHOR("Yusuke Fujimaki <usk.fujimaki@gmail.com>");
-@@ -47,10 +47,6 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
- #define T100CHI_MOUSE_REPORT_ID 0x06
- #define FEATURE_REPORT_ID 0x0d
- #define INPUT_REPORT_ID 0x5d
--#define FEATURE_KBD_REPORT_ID 0x5a
--#define FEATURE_KBD_REPORT_SIZE 16
--#define FEATURE_KBD_LED_REPORT_ID1 0x5d
--#define FEATURE_KBD_LED_REPORT_ID2 0x5e
-
- #define SUPPORT_KBD_BACKLIGHT BIT(0)
-
-@@ -71,20 +67,6 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
- #define BATTERY_STAT_CHARGING (1)
- #define BATTERY_STAT_FULL (2)
-
--#define QUIRK_FIX_NOTEBOOK_REPORT BIT(0)
--#define QUIRK_NO_INIT_REPORTS BIT(1)
--#define QUIRK_SKIP_INPUT_MAPPING BIT(2)
--#define QUIRK_IS_MULTITOUCH BIT(3)
--#define QUIRK_NO_CONSUMER_USAGES BIT(4)
--#define QUIRK_USE_KBD_BACKLIGHT BIT(5)
--#define QUIRK_T100_KEYBOARD BIT(6)
--#define QUIRK_T100CHI BIT(7)
--#define QUIRK_G752_KEYBOARD BIT(8)
--#define QUIRK_T90CHI BIT(9)
--#define QUIRK_MEDION_E1239T BIT(10)
--#define QUIRK_ROG_NKEY_KEYBOARD BIT(11)
--#define QUIRK_ROG_CLAYMORE_II_KEYBOARD BIT(12)
--
- #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
- QUIRK_NO_INIT_REPORTS | \
- QUIRK_NO_CONSUMER_USAGES)
-@@ -113,22 +95,6 @@ struct asus_touchpad_info {
- int report_size;
- };
-
--struct asus_drvdata {
-- unsigned long quirks;
-- struct hid_device *hdev;
-- struct input_dev *input;
-- struct input_dev *tp_kbd_input;
-- struct asus_kbd_leds *kbd_backlight;
-- const struct asus_touchpad_info *tp;
-- bool enable_backlight;
-- struct power_supply *battery;
-- struct power_supply_desc battery_desc;
-- int battery_capacity;
-- int battery_stat;
-- bool battery_in_query;
-- unsigned long battery_next_query;
--};
--
- static int asus_report_battery(struct asus_drvdata *, u8 *, int);
-
- static const struct asus_touchpad_info asus_i2c_tp = {
-@@ -329,6 +295,16 @@ static int asus_raw_event(struct hid_device *hdev,
- if (drvdata->battery && data[0] == BATTERY_REPORT_ID)
- return asus_report_battery(drvdata, data, size);
-
-+ // TODO: remove after debugging
-+ // if (data[0] == 0x5a || data[0] == 0x5d || data[0] == 0x5e){
-+ // for (int i = 0; i < size; i++) {
-+ // if (i == 0)
-+ // printk(KERN_INFO "GOT: %02x,", data[i]);
-+ // else
-+ // printk(KERN_CONT "%02x,", data[i]);
-+ // }
-+ // }
-+
- if (drvdata->tp && data[0] == INPUT_REPORT_ID)
- return asus_report_input(drvdata, data, size);
-
-@@ -365,7 +341,7 @@ static int asus_raw_event(struct hid_device *hdev,
- return 0;
- }
-
--static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size)
-+int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size)
- {
- unsigned char *dmabuf;
- int ret;
-@@ -386,6 +362,13 @@ static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t bu
- return ret;
- }
-
-+int asus_kbd_get_report(struct hid_device *hdev, u8 *out_buf, size_t out_buf_size)
-+{
-+ return hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, out_buf,
-+ out_buf_size, HID_FEATURE_REPORT,
-+ HID_REQ_GET_REPORT);
-+}
-+
- static int asus_kbd_init(struct hid_device *hdev, u8 report_id)
- {
- const u8 buf[] = { report_id, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
-@@ -846,8 +829,8 @@ static int asus_input_mapping(struct hid_device *hdev,
- case 0xb2: asus_map_key_clear(KEY_PROG2); break; /* Fn+Left previous aura */
- case 0xb3: asus_map_key_clear(KEY_PROG3); break; /* Fn+Left next aura */
- case 0x6a: asus_map_key_clear(KEY_F13); break; /* Screenpad toggle */
-- case 0x4b: asus_map_key_clear(KEY_F14); break; /* Arrows/Pg-Up/Dn toggle */
-- case 0xa5: asus_map_key_clear(KEY_F15); break; /* ROG Ally left back */
-+ case 0x4b: asus_map_key_clear(KEY_F14); break; /* Arrows/Pg-Up/Dn toggle, Ally M1 */
-+ case 0xa5: asus_map_key_clear(KEY_F15); break; /* ROG Ally M2 */
- case 0xa6: asus_map_key_clear(KEY_F16); break; /* ROG Ally QAM button */
- case 0xa7: asus_map_key_clear(KEY_F17); break; /* ROG Ally ROG long-press */
- case 0xa8: asus_map_key_clear(KEY_F18); break; /* ROG Ally ROG long-press-release */
-@@ -1063,6 +1046,10 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
- }
- }
-
-+ /* all ROG devices have this HID interface but we will focus on Ally for now */
-+ if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD && hid_is_usb(hdev))
-+ rog_ally.probe(hdev, &rog_ally);
-+
- ret = hid_parse(hdev);
- if (ret) {
- hid_err(hdev, "Asus hid parse failed: %d\n", ret);
-@@ -1112,6 +1099,8 @@ static void asus_remove(struct hid_device *hdev)
- cancel_work_sync(&drvdata->kbd_backlight->work);
- }
-
-+ rog_ally.remove(hdev, &rog_ally);
-+
- hid_hw_stop(hdev);
- }
-
-diff --git a/drivers/hid/hid-asus-rog.c b/drivers/hid/hid-asus-rog.c
-new file mode 100644
-index 000000000000..94b7c986576c
---- /dev/null
-+++ b/drivers/hid/hid-asus-rog.c
-@@ -0,0 +1,1469 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * HID driver for Asus ROG laptops and Ally
-+ *
-+ * Copyright (c) 2023 Luke Jones <luke@ljones.dev>
-+ */
-+
-+#include <linux/hid.h>
-+#include <linux/types.h>
-+#include <linux/usb.h>
-+
-+#include "hid-asus.h"
-+#include "hid-asus-rog.h"
-+
-+/* ROG Ally has many settings related to the gamepad, all using the same n-key endpoint */
-+struct asus_rog_ally {
-+ enum xpad_mode mode;
-+ /*
-+ * index: [joysticks/triggers][left(2 bytes), right(2 bytes)]
-+ * joysticks: 2 bytes: inner, outer
-+ * triggers: 2 bytes: lower, upper
-+ * min/max: 0-64
-+ */
-+ u8 deadzones[xpad_mode_mouse][2][4];
-+ /*
-+ * index: left, right
-+ * max: 64
-+ */
-+ u8 vibration_intensity[xpad_mode_mouse][2];
-+ /*
-+ * index: [joysticks][2 byte stepping per point]
-+ * - 4 points of 2 bytes each
-+ * - byte 0 of pair = stick move %
-+ * - byte 1 of pair = stick response %
-+ * - min/max: 1-63
-+ */
-+ bool supports_response_curves;
-+ u8 response_curve[xpad_mode_mouse][2][8];
-+ /*
-+ * left = byte 0, right = byte 1
-+ */
-+ bool supports_anti_deadzones;
-+ u8 anti_deadzones[xpad_mode_mouse][2];
-+ /*
-+ * index: [mode][phys pair][b1, b1 secondary, b2, b2 secondary, blocks of 11]
-+ */
-+ u8 key_mapping[xpad_mode_mouse][btn_pair_lt_rt][MAPPING_BLOCK_LEN];
-+ /*
-+ *
-+ */
-+ u8 turbo_btns[xpad_mode_mouse][TURBO_BLOCK_LEN];
-+ /*
-+ */
-+ u32 js_calibrations[2][6];
-+ u32 tr_calibrations[2][2];
-+};
-+
-+static struct asus_rog_ally *__rog_ally_data(struct device *raw_dev)
-+{
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ return ((struct asus_drvdata *)hid_get_drvdata(hdev))->rog_ally_data;
-+}
-+
-+#define STR_TO_CODE_IF(_idx, _code, _label) \
-+ if (!strcmp(buf, _label)) \
-+ out[_idx] = _code;
-+
-+#define STR_TO_CODE_ELIF(_idx, _code, _label) else if (!strcmp(buf, _label)) out[_idx] = _code;
-+
-+/* writes the bytes for a requested key/function in to the out buffer */
-+const static int __string_to_key_code(const char *buf, u8 *out, int out_len)
-+{
-+ u8 *save_buf;
-+
-+ if (out_len != BTN_CODE_LEN)
-+ return -EINVAL;
-+
-+ save_buf = kzalloc(out_len, GFP_KERNEL);
-+ if (!save_buf)
-+ return -ENOMEM;
-+ memcpy(save_buf, out, out_len);
-+ memset(out, 0, out_len); // always clear before adjusting
-+
-+ // Allow clearing
-+ if (!strcmp(buf, " ") || !strcmp(buf, "\n"))
-+ goto success;
-+
-+ // set group xpad
-+ out[0] = 0x01;
-+ STR_TO_CODE_IF(1, 0x01, PAD_A)
-+ STR_TO_CODE_ELIF(1, 0x02, PAD_B)
-+ STR_TO_CODE_ELIF(1, 0x03, PAD_X)
-+ STR_TO_CODE_ELIF(1, 0x04, PAD_Y)
-+ STR_TO_CODE_ELIF(1, 0x05, PAD_LB)
-+ STR_TO_CODE_ELIF(1, 0x06, PAD_RB)
-+ STR_TO_CODE_ELIF(1, 0x07, PAD_LS)
-+ STR_TO_CODE_ELIF(1, 0x08, PAD_RS)
-+ STR_TO_CODE_ELIF(1, 0x09, PAD_DPAD_UP)
-+ STR_TO_CODE_ELIF(1, 0x0a, PAD_DPAD_DOWN)
-+ STR_TO_CODE_ELIF(1, 0x0b, PAD_DPAD_LEFT)
-+ STR_TO_CODE_ELIF(1, 0x0c, PAD_DPAD_RIGHT)
-+ STR_TO_CODE_ELIF(1, 0x11, PAD_VIEW)
-+ STR_TO_CODE_ELIF(1, 0x12, PAD_MENU)
-+ STR_TO_CODE_ELIF(1, 0x13, PAD_XBOX)
-+ if (out[1])
-+ goto success;
-+
-+ // set group keyboard
-+ out[0] = 0x02;
-+ STR_TO_CODE_IF(2, 0x8f, KB_M1)
-+ STR_TO_CODE_ELIF(2, 0x8e, KB_M2)
-+
-+ STR_TO_CODE_ELIF(2, 0x76, KB_ESC)
-+ STR_TO_CODE_ELIF(2, 0x50, KB_F1)
-+ STR_TO_CODE_ELIF(2, 0x60, KB_F2)
-+ STR_TO_CODE_ELIF(2, 0x40, KB_F3)
-+ STR_TO_CODE_ELIF(2, 0x0c, KB_F4)
-+ STR_TO_CODE_ELIF(2, 0x03, KB_F5)
-+ STR_TO_CODE_ELIF(2, 0x0b, KB_F6)
-+ STR_TO_CODE_ELIF(2, 0x80, KB_F7)
-+ STR_TO_CODE_ELIF(2, 0x0a, KB_F8)
-+ STR_TO_CODE_ELIF(2, 0x01, KB_F9)
-+ STR_TO_CODE_ELIF(2, 0x09, KB_F10)
-+ STR_TO_CODE_ELIF(2, 0x78, KB_F11)
-+ STR_TO_CODE_ELIF(2, 0x07, KB_F12)
-+ STR_TO_CODE_ELIF(2, 0x10, KB_F14)
-+ STR_TO_CODE_ELIF(2, 0x18, KB_F15)
-+
-+ STR_TO_CODE_ELIF(2, 0x0e, KB_BACKTICK)
-+ STR_TO_CODE_ELIF(2, 0x16, KB_1)
-+ STR_TO_CODE_ELIF(2, 0x1e, KB_2)
-+ STR_TO_CODE_ELIF(2, 0x26, KB_3)
-+ STR_TO_CODE_ELIF(2, 0x25, KB_4)
-+ STR_TO_CODE_ELIF(2, 0x2e, KB_5)
-+ STR_TO_CODE_ELIF(2, 0x36, KB_6)
-+ STR_TO_CODE_ELIF(2, 0x3d, KB_7)
-+ STR_TO_CODE_ELIF(2, 0x3e, KB_8)
-+ STR_TO_CODE_ELIF(2, 0x46, KB_9)
-+ STR_TO_CODE_ELIF(2, 0x45, KB_0)
-+ STR_TO_CODE_ELIF(2, 0x4e, KB_HYPHEN)
-+ STR_TO_CODE_ELIF(2, 0x55, KB_EQUALS)
-+ STR_TO_CODE_ELIF(2, 0x66, KB_BACKSPACE)
-+
-+ STR_TO_CODE_ELIF(2, 0x0d, KB_TAB)
-+ STR_TO_CODE_ELIF(2, 0x15, KB_Q)
-+ STR_TO_CODE_ELIF(2, 0x1d, KB_W)
-+ STR_TO_CODE_ELIF(2, 0x24, KB_E)
-+ STR_TO_CODE_ELIF(2, 0x2d, KB_R)
-+ STR_TO_CODE_ELIF(2, 0x2d, KB_T)
-+ STR_TO_CODE_ELIF(2, 0x35, KB_Y)
-+ STR_TO_CODE_ELIF(2, 0x3c, KB_U)
-+ STR_TO_CODE_ELIF(2, 0x43, KB_I)
-+ STR_TO_CODE_ELIF(2, 0x44, KB_O)
-+ STR_TO_CODE_ELIF(2, 0x4d, KB_P)
-+ STR_TO_CODE_ELIF(2, 0x54, KB_LBRACKET)
-+ STR_TO_CODE_ELIF(2, 0x5b, KB_RBRACKET)
-+ STR_TO_CODE_ELIF(2, 0x5d, KB_BACKSLASH)
-+
-+ STR_TO_CODE_ELIF(2, 0x58, KB_CAPS)
-+ STR_TO_CODE_ELIF(2, 0x1c, KB_A)
-+ STR_TO_CODE_ELIF(2, 0x1b, KB_S)
-+ STR_TO_CODE_ELIF(2, 0x23, KB_D)
-+ STR_TO_CODE_ELIF(2, 0x2b, KB_F)
-+ STR_TO_CODE_ELIF(2, 0x34, KB_G)
-+ STR_TO_CODE_ELIF(2, 0x33, KB_H)
-+ STR_TO_CODE_ELIF(2, 0x3b, KB_J)
-+ STR_TO_CODE_ELIF(2, 0x42, KB_K)
-+ STR_TO_CODE_ELIF(2, 0x4b, KB_L)
-+ STR_TO_CODE_ELIF(2, 0x4c, KB_SEMI)
-+ STR_TO_CODE_ELIF(2, 0x52, KB_QUOTE)
-+ STR_TO_CODE_ELIF(2, 0x5a, KB_RET)
-+
-+ STR_TO_CODE_ELIF(2, 0x88, KB_LSHIFT)
-+ STR_TO_CODE_ELIF(2, 0x1a, KB_Z)
-+ STR_TO_CODE_ELIF(2, 0x22, KB_X)
-+ STR_TO_CODE_ELIF(2, 0x21, KB_C)
-+ STR_TO_CODE_ELIF(2, 0x2a, KB_V)
-+ STR_TO_CODE_ELIF(2, 0x32, KB_B)
-+ STR_TO_CODE_ELIF(2, 0x31, KB_N)
-+ STR_TO_CODE_ELIF(2, 0x3a, KB_M)
-+ STR_TO_CODE_ELIF(2, 0x41, KB_COMMA)
-+ STR_TO_CODE_ELIF(2, 0x49, KB_PERIOD)
-+ STR_TO_CODE_ELIF(2, 0x4a, KB_FWDSLASH)
-+ STR_TO_CODE_ELIF(2, 0x89, KB_RSHIFT)
-+
-+ STR_TO_CODE_ELIF(2, 0x8c, KB_LCTL)
-+ STR_TO_CODE_ELIF(2, 0x82, KB_META)
-+ STR_TO_CODE_ELIF(2, 0xba, KB_LALT)
-+ STR_TO_CODE_ELIF(2, 0x29, KB_SPACE)
-+ STR_TO_CODE_ELIF(2, 0x8b, KB_RALT)
-+ STR_TO_CODE_ELIF(2, 0x84, KB_MENU)
-+ STR_TO_CODE_ELIF(2, 0x8d, KB_RCTL)
-+
-+ STR_TO_CODE_ELIF(2, 0xc3, KB_PRNTSCN)
-+ STR_TO_CODE_ELIF(2, 0x7e, KB_SCRLCK)
-+ STR_TO_CODE_ELIF(2, 0x91, KB_PAUSE)
-+ STR_TO_CODE_ELIF(2, 0xc2, KB_INS)
-+ STR_TO_CODE_ELIF(2, 0x94, KB_HOME)
-+ STR_TO_CODE_ELIF(2, 0x96, KB_PGUP)
-+ STR_TO_CODE_ELIF(2, 0xc0, KB_DEL)
-+ STR_TO_CODE_ELIF(2, 0x95, KB_END)
-+ STR_TO_CODE_ELIF(2, 0x97, KB_PGDWN)
-+
-+ STR_TO_CODE_ELIF(2, 0x99, KB_UP_ARROW)
-+ STR_TO_CODE_ELIF(2, 0x98, KB_DOWN_ARROW)
-+ STR_TO_CODE_ELIF(2, 0x91, KB_LEFT_ARROW)
-+ STR_TO_CODE_ELIF(2, 0x9b, KB_RIGHT_ARROW)
-+
-+ STR_TO_CODE_ELIF(2, 0x77, NUMPAD_LOCK)
-+ STR_TO_CODE_ELIF(2, 0x90, NUMPAD_FWDSLASH)
-+ STR_TO_CODE_ELIF(2, 0x7c, NUMPAD_ASTERISK)
-+ STR_TO_CODE_ELIF(2, 0x7b, NUMPAD_HYPHEN)
-+ STR_TO_CODE_ELIF(2, 0x70, NUMPAD_0)
-+ STR_TO_CODE_ELIF(2, 0x69, NUMPAD_1)
-+ STR_TO_CODE_ELIF(2, 0x72, NUMPAD_2)
-+ STR_TO_CODE_ELIF(2, 0x7a, NUMPAD_3)
-+ STR_TO_CODE_ELIF(2, 0x6b, NUMPAD_4)
-+ STR_TO_CODE_ELIF(2, 0x73, NUMPAD_5)
-+ STR_TO_CODE_ELIF(2, 0x74, NUMPAD_6)
-+ STR_TO_CODE_ELIF(2, 0x6c, NUMPAD_7)
-+ STR_TO_CODE_ELIF(2, 0x75, NUMPAD_8)
-+ STR_TO_CODE_ELIF(2, 0x7d, NUMPAD_9)
-+ STR_TO_CODE_ELIF(2, 0x79, NUMPAD_PLUS)
-+ STR_TO_CODE_ELIF(2, 0x81, NUMPAD_ENTER)
-+ STR_TO_CODE_ELIF(2, 0x71, NUMPAD_PERIOD)
-+ if (out[2])
-+ goto success;
-+
-+ out[0] = 0x03;
-+ STR_TO_CODE_IF(4, 0x01, RAT_LCLICK)
-+ STR_TO_CODE_ELIF(4, 0x02, RAT_RCLICK)
-+ STR_TO_CODE_ELIF(4, 0x03, RAT_MCLICK)
-+ STR_TO_CODE_ELIF(4, 0x04, RAT_WHEEL_UP)
-+ STR_TO_CODE_ELIF(4, 0x05, RAT_WHEEL_DOWN)
-+ if (out[4] != 0)
-+ goto success;
-+
-+ out[0] = 0x05;
-+ STR_TO_CODE_IF(3, 0x16, MEDIA_SCREENSHOT)
-+ STR_TO_CODE_ELIF(3, 0x19, MEDIA_SHOW_KEYBOARD)
-+ STR_TO_CODE_ELIF(3, 0x1c, MEDIA_SHOW_DESKTOP)
-+ STR_TO_CODE_ELIF(3, 0x1e, MEDIA_START_RECORDING)
-+ STR_TO_CODE_ELIF(3, 0x01, MEDIA_MIC_OFF)
-+ STR_TO_CODE_ELIF(3, 0x02, MEDIA_VOL_DOWN)
-+ STR_TO_CODE_ELIF(3, 0x03, MEDIA_VOL_UP)
-+ if (out[3])
-+ goto success;
-+
-+ // restore bytes if invalid input
-+ memcpy(out, save_buf, out_len);
-+ kfree(save_buf);
-+ return -EINVAL;
-+
-+success:
-+ kfree(save_buf);
-+ return 0;
-+}
-+
-+#define CODE_TO_STR_IF(_idx, _code, _label) \
-+ if (btn_block[_idx] == _code) \
-+ return _label;
-+
-+const static char *__btn_map_to_string(struct device *raw_dev, enum btn_pair pair,
-+ enum btn_pair_side side, bool secondary)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ u8 *btn_block;
-+ int offs;
-+
-+ // TODO: this little block is common
-+ offs = side ? MAPPING_BLOCK_LEN / 2 : 0;
-+ offs = secondary ? offs + BTN_CODE_LEN : offs;
-+ btn_block = rog_ally->key_mapping[rog_ally->mode - 1][pair - 1] + offs;
-+
-+ if (btn_block[0] == 0x01) {
-+ CODE_TO_STR_IF(1, 0x01, PAD_A)
-+ CODE_TO_STR_IF(1, 0x02, PAD_B)
-+ CODE_TO_STR_IF(1, 0x03, PAD_X)
-+ CODE_TO_STR_IF(1, 0x04, PAD_Y)
-+ CODE_TO_STR_IF(1, 0x05, PAD_LB)
-+ CODE_TO_STR_IF(1, 0x06, PAD_RB)
-+ CODE_TO_STR_IF(1, 0x07, PAD_LS)
-+ CODE_TO_STR_IF(1, 0x08, PAD_RS)
-+ CODE_TO_STR_IF(1, 0x09, PAD_DPAD_UP)
-+ CODE_TO_STR_IF(1, 0x0a, PAD_DPAD_DOWN)
-+ CODE_TO_STR_IF(1, 0x0b, PAD_DPAD_LEFT)
-+ CODE_TO_STR_IF(1, 0x0c, PAD_DPAD_RIGHT)
-+ CODE_TO_STR_IF(1, 0x11, PAD_VIEW)
-+ CODE_TO_STR_IF(1, 0x12, PAD_MENU)
-+ CODE_TO_STR_IF(1, 0x13, PAD_XBOX)
-+ }
-+
-+ if (btn_block[0] == 0x02) {
-+ CODE_TO_STR_IF(2, 0x8f, KB_M1)
-+ CODE_TO_STR_IF(2, 0x8e, KB_M2)
-+ CODE_TO_STR_IF(2, 0x76, KB_ESC)
-+ CODE_TO_STR_IF(2, 0x50, KB_F1)
-+ CODE_TO_STR_IF(2, 0x60, KB_F2)
-+ CODE_TO_STR_IF(2, 0x40, KB_F3)
-+ CODE_TO_STR_IF(2, 0x0c, KB_F4)
-+ CODE_TO_STR_IF(2, 0x03, KB_F5)
-+ CODE_TO_STR_IF(2, 0x0b, KB_F6)
-+ CODE_TO_STR_IF(2, 0x80, KB_F7)
-+ CODE_TO_STR_IF(2, 0x0a, KB_F8)
-+ CODE_TO_STR_IF(2, 0x01, KB_F9)
-+ CODE_TO_STR_IF(2, 0x09, KB_F10)
-+ CODE_TO_STR_IF(2, 0x78, KB_F11)
-+ CODE_TO_STR_IF(2, 0x07, KB_F12)
-+ CODE_TO_STR_IF(2, 0x10, KB_F14)
-+ CODE_TO_STR_IF(2, 0x18, KB_F15)
-+
-+ CODE_TO_STR_IF(2, 0x0e, KB_BACKTICK)
-+ CODE_TO_STR_IF(2, 0x16, KB_1)
-+ CODE_TO_STR_IF(2, 0x1e, KB_2)
-+ CODE_TO_STR_IF(2, 0x26, KB_3)
-+ CODE_TO_STR_IF(2, 0x25, KB_4)
-+ CODE_TO_STR_IF(2, 0x2e, KB_5)
-+ CODE_TO_STR_IF(2, 0x36, KB_6)
-+ CODE_TO_STR_IF(2, 0x3d, KB_7)
-+ CODE_TO_STR_IF(2, 0x3e, KB_8)
-+ CODE_TO_STR_IF(2, 0x46, KB_9)
-+ CODE_TO_STR_IF(2, 0x45, KB_0)
-+ CODE_TO_STR_IF(2, 0x4e, KB_HYPHEN)
-+ CODE_TO_STR_IF(2, 0x55, KB_EQUALS)
-+ CODE_TO_STR_IF(2, 0x66, KB_BACKSPACE)
-+
-+ CODE_TO_STR_IF(2, 0x0d, KB_TAB)
-+ CODE_TO_STR_IF(2, 0x15, KB_Q)
-+ CODE_TO_STR_IF(2, 0x1d, KB_W)
-+ CODE_TO_STR_IF(2, 0x24, KB_E)
-+ CODE_TO_STR_IF(2, 0x2d, KB_R)
-+ CODE_TO_STR_IF(2, 0x2d, KB_T)
-+ CODE_TO_STR_IF(2, 0x35, KB_Y)
-+ CODE_TO_STR_IF(2, 0x3c, KB_U)
-+ CODE_TO_STR_IF(2, 0x43, KB_I)
-+ CODE_TO_STR_IF(2, 0x44, KB_O)
-+ CODE_TO_STR_IF(2, 0x4d, KB_P)
-+ CODE_TO_STR_IF(2, 0x54, KB_LBRACKET)
-+ CODE_TO_STR_IF(2, 0x5b, KB_RBRACKET)
-+ CODE_TO_STR_IF(2, 0x5d, KB_BACKSLASH)
-+
-+ CODE_TO_STR_IF(2, 0x58, KB_CAPS)
-+ CODE_TO_STR_IF(2, 0x1c, KB_A)
-+ CODE_TO_STR_IF(2, 0x1b, KB_S)
-+ CODE_TO_STR_IF(2, 0x23, KB_D)
-+ CODE_TO_STR_IF(2, 0x2b, KB_F)
-+ CODE_TO_STR_IF(2, 0x34, KB_G)
-+ CODE_TO_STR_IF(2, 0x33, KB_H)
-+ CODE_TO_STR_IF(2, 0x3b, KB_J)
-+ CODE_TO_STR_IF(2, 0x42, KB_K)
-+ CODE_TO_STR_IF(2, 0x4b, KB_L)
-+ CODE_TO_STR_IF(2, 0x4c, KB_SEMI)
-+ CODE_TO_STR_IF(2, 0x52, KB_QUOTE)
-+ CODE_TO_STR_IF(2, 0x5a, KB_RET)
-+
-+ CODE_TO_STR_IF(2, 0x88, KB_LSHIFT)
-+ CODE_TO_STR_IF(2, 0x1a, KB_Z)
-+ CODE_TO_STR_IF(2, 0x22, KB_X)
-+ CODE_TO_STR_IF(2, 0x21, KB_C)
-+ CODE_TO_STR_IF(2, 0x2a, KB_V)
-+ CODE_TO_STR_IF(2, 0x32, KB_B)
-+ CODE_TO_STR_IF(2, 0x31, KB_N)
-+ CODE_TO_STR_IF(2, 0x3a, KB_M)
-+ CODE_TO_STR_IF(2, 0x41, KB_COMMA)
-+ CODE_TO_STR_IF(2, 0x49, KB_PERIOD)
-+ CODE_TO_STR_IF(2, 0x4a, KB_FWDSLASH)
-+ CODE_TO_STR_IF(2, 0x89, KB_RSHIFT)
-+
-+ CODE_TO_STR_IF(2, 0x8c, KB_LCTL)
-+ CODE_TO_STR_IF(2, 0x82, KB_META)
-+ CODE_TO_STR_IF(2, 0xba, KB_LALT)
-+ CODE_TO_STR_IF(2, 0x29, KB_SPACE)
-+ CODE_TO_STR_IF(2, 0x8b, KB_RALT)
-+ CODE_TO_STR_IF(2, 0x84, KB_MENU)
-+ CODE_TO_STR_IF(2, 0x8d, KB_RCTL)
-+
-+ CODE_TO_STR_IF(2, 0xc3, KB_PRNTSCN)
-+ CODE_TO_STR_IF(2, 0x7e, KB_SCRLCK)
-+ CODE_TO_STR_IF(2, 0x91, KB_PAUSE)
-+ CODE_TO_STR_IF(2, 0xc2, KB_INS)
-+ CODE_TO_STR_IF(2, 0x94, KB_HOME)
-+ CODE_TO_STR_IF(2, 0x96, KB_PGUP)
-+ CODE_TO_STR_IF(2, 0xc0, KB_DEL)
-+ CODE_TO_STR_IF(2, 0x95, KB_END)
-+ CODE_TO_STR_IF(2, 0x97, KB_PGDWN)
-+
-+ CODE_TO_STR_IF(2, 0x99, KB_UP_ARROW)
-+ CODE_TO_STR_IF(2, 0x98, KB_DOWN_ARROW)
-+ CODE_TO_STR_IF(2, 0x91, KB_LEFT_ARROW)
-+ CODE_TO_STR_IF(2, 0x9b, KB_RIGHT_ARROW)
-+
-+ CODE_TO_STR_IF(2, 0x77, NUMPAD_LOCK)
-+ CODE_TO_STR_IF(2, 0x90, NUMPAD_FWDSLASH)
-+ CODE_TO_STR_IF(2, 0x7c, NUMPAD_ASTERISK)
-+ CODE_TO_STR_IF(2, 0x7b, NUMPAD_HYPHEN)
-+ CODE_TO_STR_IF(2, 0x70, NUMPAD_0)
-+ CODE_TO_STR_IF(2, 0x69, NUMPAD_1)
-+ CODE_TO_STR_IF(2, 0x72, NUMPAD_2)
-+ CODE_TO_STR_IF(2, 0x7a, NUMPAD_3)
-+ CODE_TO_STR_IF(2, 0x6b, NUMPAD_4)
-+ CODE_TO_STR_IF(2, 0x73, NUMPAD_5)
-+ CODE_TO_STR_IF(2, 0x74, NUMPAD_6)
-+ CODE_TO_STR_IF(2, 0x6c, NUMPAD_7)
-+ CODE_TO_STR_IF(2, 0x75, NUMPAD_8)
-+ CODE_TO_STR_IF(2, 0x7d, NUMPAD_9)
-+ CODE_TO_STR_IF(2, 0x79, NUMPAD_PLUS)
-+ CODE_TO_STR_IF(2, 0x81, NUMPAD_ENTER)
-+ CODE_TO_STR_IF(2, 0x71, NUMPAD_PERIOD)
-+ }
-+
-+ if (btn_block[0] == 0x03) {
-+ CODE_TO_STR_IF(4, 0x01, RAT_LCLICK)
-+ CODE_TO_STR_IF(4, 0x02, RAT_RCLICK)
-+ CODE_TO_STR_IF(4, 0x03, RAT_MCLICK)
-+ CODE_TO_STR_IF(4, 0x04, RAT_WHEEL_UP)
-+ CODE_TO_STR_IF(4, 0x05, RAT_WHEEL_DOWN)
-+ }
-+
-+ if (btn_block[0] == 0x05) {
-+ CODE_TO_STR_IF(3, 0x16, MEDIA_SCREENSHOT)
-+ CODE_TO_STR_IF(3, 0x19, MEDIA_SHOW_KEYBOARD)
-+ CODE_TO_STR_IF(3, 0x1c, MEDIA_SHOW_DESKTOP)
-+ CODE_TO_STR_IF(3, 0x1e, MEDIA_START_RECORDING)
-+ CODE_TO_STR_IF(3, 0x01, MEDIA_MIC_OFF)
-+ CODE_TO_STR_IF(3, 0x02, MEDIA_VOL_DOWN)
-+ CODE_TO_STR_IF(3, 0x03, MEDIA_VOL_UP)
-+ }
-+
-+ return "";
-+}
-+
-+/* ASUS ROG Ally device specific attributes */
-+
-+/* This should be called before any attempts to set device functions */
-+static int __gamepad_check_ready(struct hid_device *hdev)
-+{
-+ u8 *hidbuf;
-+ int ret, count;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ for (count = 0; count < 3; count++) {
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_check_ready;
-+ hidbuf[3] = 01;
-+ ret = asus_kbd_set_report(hdev, hidbuf,
-+ FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ hid_warn(hdev, "ROG Ally check failed set report: %d\n", ret);
-+
-+ hidbuf[0] = hidbuf[1] = hidbuf[2] = hidbuf[3] = 0;
-+ ret = asus_kbd_get_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ hid_warn(hdev, "ROG Ally check failed get report: %d\n", ret);
-+
-+ ret = hidbuf[2] == xpad_cmd_check_ready;
-+ if (!ret)
-+ hid_warn(hdev, "ROG Ally not ready, retry %d\n", count);
-+ else
-+ break;
-+ msleep(2); // don't spam the entire loop in less than USB response time
-+ }
-+
-+ if (count == 3)
-+ hid_err(hdev, "ROG Ally never responded with a ready\n");
-+
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+/********** BUTTON REMAPPING *********************************************************************/
-+static void __btn_pair_to_pkt(struct device *raw_dev, enum btn_pair pair, u8 *out, int out_len)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+
-+ out[0] = FEATURE_KBD_REPORT_ID;
-+ out[1] = 0xD1;
-+ out[2] = xpad_cmd_set_mapping;
-+ out[3] = pair;
-+ out[4] = 0x2c; //length
-+ memcpy(&out[5], &rog_ally->key_mapping[rog_ally->mode - 1][pair - 1], MAPPING_BLOCK_LEN);
-+}
-+
-+/* Store the button setting in driver data. Does not apply to device until __gamepad_set_mapping */
-+static int __gamepad_mapping_store(struct device *raw_dev, const char *buf, enum btn_pair pair,
-+ int side, bool secondary)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ u8 *key_code;
-+ int offs;
-+
-+ offs = side ? MAPPING_BLOCK_LEN / 2 : 0;
-+ offs = secondary ? offs + BTN_CODE_LEN : offs;
-+ key_code = rog_ally->key_mapping[rog_ally->mode - 1][pair - 1] + offs;
-+
-+ return __string_to_key_code(buf, key_code, BTN_CODE_LEN);
-+}
-+
-+/* Apply the mapping pair to the device */
-+static int __gamepad_set_mapping(struct device *raw_dev, enum btn_pair pair)
-+{
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ int ret;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ __btn_pair_to_pkt(raw_dev, pair, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ kfree(hidbuf);
-+
-+ return ret;
-+}
-+
-+static ssize_t btn_mapping_apply_store(struct device *raw_dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ int ret = __gamepad_write_all_to_mcu(raw_dev);
-+ if (ret < 0)
-+ return ret;
-+ return count;
-+}
-+ALLY_DEVICE_ATTR_WO(btn_mapping_apply, apply);
-+
-+/********** BUTTON TURBO *************************************************************************/
-+static int __gamepad_turbo_index(enum btn_pair pair, int side)
-+{
-+ return (pair - 1) * (2 * TURBO_BLOCK_STEP) + (side * TURBO_BLOCK_STEP);
-+};
-+
-+static int __gamepad_turbo_show(struct device *raw_dev, enum btn_pair pair, int side)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ return rog_ally->turbo_btns[rog_ally->mode - 1][__gamepad_turbo_index(pair, side)];
-+};
-+
-+static int __gamepad_turbo_store(struct device *raw_dev, const char *buf, enum btn_pair pair,
-+ int side)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ int ret, val;
-+
-+ ret = kstrtoint(buf, 0, &val);
-+ if (ret)
-+ return ret;
-+ if (val < 0 || val > 16)
-+ return -EINVAL;
-+
-+ rog_ally->turbo_btns[rog_ally->mode - 1][__gamepad_turbo_index(pair, side)] = val;
-+
-+ return 0;
-+};
-+
-+/* button map attributes, regular and macro*/
-+ALLY_BTN_MAPPING(m2, btn_pair_m1_m2, btn_pair_side_left);
-+ALLY_BTN_MAPPING(m1, btn_pair_m1_m2, btn_pair_side_right);
-+ALLY_BTN_MAPPING(a, btn_pair_a_b, btn_pair_side_left);
-+ALLY_BTN_MAPPING(b, btn_pair_a_b, btn_pair_side_right);
-+ALLY_BTN_MAPPING(x, btn_pair_x_y, btn_pair_side_left);
-+ALLY_BTN_MAPPING(y, btn_pair_x_y, btn_pair_side_right);
-+ALLY_BTN_MAPPING(lb, btn_pair_lb_rb, btn_pair_side_left);
-+ALLY_BTN_MAPPING(rb, btn_pair_lb_rb, btn_pair_side_right);
-+ALLY_BTN_MAPPING(ls, btn_pair_ls_rs, btn_pair_side_left);
-+ALLY_BTN_MAPPING(rs, btn_pair_ls_rs, btn_pair_side_right);
-+ALLY_BTN_MAPPING(lt, btn_pair_lt_rt, btn_pair_side_left);
-+ALLY_BTN_MAPPING(rt, btn_pair_lt_rt, btn_pair_side_right);
-+ALLY_BTN_MAPPING(dpad_u, btn_pair_dpad_u_d, btn_pair_side_left);
-+ALLY_BTN_MAPPING(dpad_d, btn_pair_dpad_u_d, btn_pair_side_right);
-+ALLY_BTN_MAPPING(dpad_l, btn_pair_dpad_l_r, btn_pair_side_left);
-+ALLY_BTN_MAPPING(dpad_r, btn_pair_dpad_l_r, btn_pair_side_right);
-+ALLY_BTN_MAPPING(view, btn_pair_view_menu, btn_pair_side_left);
-+ALLY_BTN_MAPPING(menu, btn_pair_view_menu, btn_pair_side_right);
-+
-+static void __gamepad_mapping_xpad_default(struct asus_rog_ally *rog_ally)
-+{
-+ memcpy(&rog_ally->key_mapping[0][0], &XPAD_DEF1, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[0][1], &XPAD_DEF2, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[0][2], &XPAD_DEF3, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[0][3], &XPAD_DEF4, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[0][4], &XPAD_DEF5, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[0][5], &XPAD_DEF6, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[0][6], &XPAD_DEF7, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[0][7], &XPAD_DEF8, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[0][8], &XPAD_DEF9, MAPPING_BLOCK_LEN);
-+}
-+
-+static void __gamepad_mapping_wasd_default(struct asus_rog_ally *rog_ally)
-+{
-+ memcpy(&rog_ally->key_mapping[1][0], &WASD_DEF1, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[1][1], &WASD_DEF2, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[1][2], &WASD_DEF3, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[1][3], &WASD_DEF4, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[1][4], &WASD_DEF5, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[1][5], &WASD_DEF6, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[1][6], &WASD_DEF7, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[1][7], &WASD_DEF8, MAPPING_BLOCK_LEN);
-+ memcpy(&rog_ally->key_mapping[1][8], &WASD_DEF9, MAPPING_BLOCK_LEN);
-+}
-+
-+static ssize_t btn_mapping_reset_store(struct device *raw_dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ switch (rog_ally->mode) {
-+ case xpad_mode_game:
-+ __gamepad_mapping_xpad_default(rog_ally);
-+ break;
-+ case xpad_mode_wasd:
-+ __gamepad_mapping_wasd_default(rog_ally);
-+ break;
-+ default:
-+ __gamepad_mapping_xpad_default(rog_ally);
-+ break;
-+ }
-+
-+ return count;
-+}
-+
-+ALLY_DEVICE_ATTR_WO(btn_mapping_reset, reset_btn_mapping);
-+
-+/********** GAMEPAD MODE *************************************************************************/
-+static ssize_t __gamepad_set_mode(struct device *raw_dev, int val)
-+{
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ int ret;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_mode;
-+ hidbuf[3] = 0x01;
-+ hidbuf[4] = val;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ ret = __gamepad_write_all_to_mcu(raw_dev);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+report_fail:
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+static ssize_t gamepad_mode_show(struct device *raw_dev, struct device_attribute *attr, char *buf)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ return sysfs_emit(buf, "%d\n", rog_ally->mode);
-+}
-+
-+static ssize_t gamepad_mode_store(struct device *raw_dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ int ret, val;
-+
-+ ret = kstrtoint(buf, 0, &val);
-+ if (ret)
-+ return ret;
-+
-+ if (val < xpad_mode_game || val > xpad_mode_mouse)
-+ return -EINVAL;
-+
-+ rog_ally->mode = val;
-+
-+ ret = __gamepad_set_mode(raw_dev, val);
-+ if (ret < 0)
-+ return ret;
-+
-+ return count;
-+}
-+
-+DEVICE_ATTR_RW(gamepad_mode);
-+
-+/********** VIBRATION INTENSITY ******************************************************************/
-+static ssize_t gamepad_vibration_intensity_index_show(struct device *raw_dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ return sysfs_emit(buf, "left right\n");
-+}
-+
-+ALLY_DEVICE_ATTR_RO(gamepad_vibration_intensity_index, vibration_intensity_index);
-+
-+static ssize_t __gamepad_write_vibe_intensity_to_mcu(struct device *raw_dev)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ int ret;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_vibe_intensity;
-+ hidbuf[3] = 0x02; // length
-+ hidbuf[4] = rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_left];
-+ hidbuf[5] = rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_right];
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+report_fail:
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+static ssize_t gamepad_vibration_intensity_show(struct device *raw_dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ return sysfs_emit(buf, "%d %d\n",
-+ rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_left],
-+ rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_right]);
-+}
-+
-+static ssize_t gamepad_vibration_intensity_store(struct device *raw_dev,
-+ struct device_attribute *attr, const char *buf,
-+ size_t count)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ u32 left, right;
-+ int ret;
-+
-+ if (sscanf(buf, "%d %d", &left, &right) != 2)
-+ return -EINVAL;
-+
-+ if (left > 64 || right > 64)
-+ return -EINVAL;
-+
-+ rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_left] = left;
-+ rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_right] = right;
-+
-+ ret = __gamepad_write_vibe_intensity_to_mcu(raw_dev);
-+ if (ret < 0)
-+ return ret;
-+
-+ return count;
-+}
-+
-+ALLY_DEVICE_ATTR_RW(gamepad_vibration_intensity, vibration_intensity);
-+
-+/********** ROOT LEVEL ATTRS **********************************************************************/
-+static struct attribute *gamepad_device_attrs[] = { &dev_attr_gamepad_mode.attr,
-+ &dev_attr_btn_mapping_reset.attr,
-+ &dev_attr_btn_mapping_apply.attr,
-+ &dev_attr_gamepad_vibration_intensity.attr,
-+ &dev_attr_gamepad_vibration_intensity_index.attr,
-+ NULL };
-+
-+static const struct attribute_group ally_controller_attr_group = {
-+ .attrs = gamepad_device_attrs,
-+};
-+
-+/********** ANALOGUE DEADZONES ********************************************************************/
-+static ssize_t __gamepad_set_deadzones(struct device *raw_dev)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ int ret;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_js_dz;
-+ hidbuf[3] = 0x04; // length
-+ hidbuf[4] = rog_ally->deadzones[rog_ally->mode - 1][0][0];
-+ hidbuf[5] = rog_ally->deadzones[rog_ally->mode - 1][0][1];
-+ hidbuf[6] = rog_ally->deadzones[rog_ally->mode - 1][0][2];
-+ hidbuf[7] = rog_ally->deadzones[rog_ally->mode - 1][0][3];
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto end;
-+
-+ hidbuf[2] = xpad_cmd_set_tr_dz;
-+ hidbuf[4] = rog_ally->deadzones[rog_ally->mode - 1][1][0];
-+ hidbuf[5] = rog_ally->deadzones[rog_ally->mode - 1][1][1];
-+ hidbuf[6] = rog_ally->deadzones[rog_ally->mode - 1][1][2];
-+ hidbuf[7] = rog_ally->deadzones[rog_ally->mode - 1][1][3];
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto end;
-+
-+end:
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+static ssize_t __gamepad_store_deadzones(struct device *raw_dev, enum xpad_axis axis,
-+ const char *buf)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ int cmd, side, is_tr;
-+ u32 inner, outer;
-+
-+ if (sscanf(buf, "%d %d", &inner, &outer) != 2)
-+ return -EINVAL;
-+
-+ if (inner > 64 || outer > 64 || inner > outer)
-+ return -EINVAL;
-+
-+ is_tr = axis > xpad_axis_xy_right;
-+ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 2 : 0;
-+ cmd = is_tr ? xpad_cmd_set_js_dz : xpad_cmd_set_tr_dz;
-+
-+ rog_ally->deadzones[rog_ally->mode - 1][is_tr][side] = inner;
-+ rog_ally->deadzones[rog_ally->mode - 1][is_tr][side + 1] = outer;
-+
-+ return 0;
-+}
-+
-+static ssize_t axis_xyz_deadzone_index_show(struct device *raw_dev, struct device_attribute *attr,
-+ char *buf)
-+{
-+ return sysfs_emit(buf, "inner outer\n");
-+}
-+
-+ALLY_DEVICE_ATTR_RO(axis_xyz_deadzone_index, deadzone_index);
-+
-+ALLY_AXIS_DEADZONE(xpad_axis_xy_left, deadzone);
-+ALLY_AXIS_DEADZONE(xpad_axis_xy_right, deadzone);
-+ALLY_AXIS_DEADZONE(xpad_axis_z_left, deadzone);
-+ALLY_AXIS_DEADZONE(xpad_axis_z_right, deadzone);
-+
-+/********** ANTI-DEADZONES ***********************************************************************/
-+static ssize_t __gamepad_write_js_ADZ_to_mcu(struct device *raw_dev)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ int ret;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_adz;
-+ hidbuf[3] = 0x02; // length
-+ hidbuf[4] = rog_ally->anti_deadzones[rog_ally->mode - 1][btn_pair_side_left];
-+ hidbuf[5] = rog_ally->anti_deadzones[rog_ally->mode - 1][btn_pair_side_right];
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+report_fail:
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+static ssize_t __gamepad_js_ADZ_store(struct device *raw_dev, const char *buf,
-+ enum btn_pair_side side)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ int ret, val;
-+
-+ ret = kstrtoint(buf, 0, &val);
-+ if (ret)
-+ return ret;
-+
-+ if (val < 0 || val > 32)
-+ return -EINVAL;
-+
-+ rog_ally->anti_deadzones[rog_ally->mode - 1][side] = val;
-+
-+ return ret;
-+}
-+
-+static ssize_t xpad_axis_xy_left_ADZ_show(struct device *raw_dev, struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ return sysfs_emit(buf, "%d\n",
-+ rog_ally->anti_deadzones[rog_ally->mode - 1][btn_pair_side_left]);
-+}
-+
-+static ssize_t xpad_axis_xy_left_ADZ_store(struct device *raw_dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ int ret = __gamepad_js_ADZ_store(raw_dev, buf, btn_pair_side_left);
-+ if (ret)
-+ return ret;
-+
-+ return count;
-+}
-+
-+ALLY_DEVICE_ATTR_RW(xpad_axis_xy_left_ADZ, anti_deadzone);
-+
-+static ssize_t xpad_axis_xy_right_ADZ_show(struct device *raw_dev, struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ return sysfs_emit(buf, "%d\n",
-+ rog_ally->anti_deadzones[rog_ally->mode - 1][btn_pair_side_right]);
-+}
-+
-+static ssize_t xpad_axis_xy_right_ADZ_store(struct device *raw_dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ int ret = __gamepad_js_ADZ_store(raw_dev, buf, btn_pair_side_right);
-+ if (ret)
-+ return ret;
-+
-+ return count;
-+}
-+
-+ALLY_DEVICE_ATTR_RW(xpad_axis_xy_right_ADZ, anti_deadzone);
-+
-+/********** JS RESPONSE CURVES *******************************************************************/
-+static ssize_t rc_point_index_show(struct device *raw_dev, struct device_attribute *attr, char *buf)
-+{
-+ return sysfs_emit(buf, "move response\n");
-+}
-+
-+ALLY_DEVICE_ATTR_RO(rc_point_index, rc_point_index);
-+
-+static ssize_t __gamepad_write_response_curves_to_mcu(struct device *raw_dev)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ int ret;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_response_curve;
-+ hidbuf[3] = 0x09; // length
-+ hidbuf[4] = 0x01;
-+ memcpy(&hidbuf[5], &rog_ally->response_curve[rog_ally->mode - 1][btn_pair_side_left], 8);
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ hidbuf[4] = 0x02;
-+ memcpy(&hidbuf[5], &rog_ally->response_curve[rog_ally->mode - 1][btn_pair_side_right], 8);
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+report_fail:
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+static ssize_t __gamepad_store_response_curve(struct device *raw_dev, const char *buf,
-+ enum btn_pair_side side, int point)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ int idx = (point - 1) * 2;
-+ u32 move, response;
-+
-+ if (sscanf(buf, "%d %d", &move, &response) != 2)
-+ return -EINVAL;
-+
-+ if (move > 64 || response > 64)
-+ return -EINVAL;
-+
-+ rog_ally->response_curve[rog_ally->mode - 1][side][idx] = move;
-+ rog_ally->response_curve[rog_ally->mode - 1][side][idx + 1] = response;
-+
-+ return 0;
-+}
-+
-+ALLY_JS_RC_POINT(left, 1, rc_point_);
-+ALLY_JS_RC_POINT(left, 2, rc_point_);
-+ALLY_JS_RC_POINT(left, 3, rc_point_);
-+ALLY_JS_RC_POINT(left, 4, rc_point_);
-+
-+ALLY_JS_RC_POINT(right, 1, rc_point_);
-+ALLY_JS_RC_POINT(right, 2, rc_point_);
-+ALLY_JS_RC_POINT(right, 3, rc_point_);
-+ALLY_JS_RC_POINT(right, 4, rc_point_);
-+
-+/********** CALIBRATIONS *************************************************************************/
-+static ssize_t __gamepad_write_cal_to_mcu(struct device *raw_dev, enum xpad_axis axis)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ u8 *c, side, pkt_len, data_len;
-+ int ret, cal, checksum = 0;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
-+ pkt_len = axis > xpad_axis_xy_right ? 0x06 : 0x0E;
-+ data_len = axis > xpad_axis_xy_right ? 2 : 6;
-+
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_calibration;
-+ hidbuf[3] = pkt_len;
-+ hidbuf[4] = 0x01; // second command (set)
-+ hidbuf[5] = axis;
-+ c = &hidbuf[6]; // pointer
-+
-+ for (size_t i = 0; i < data_len; i++) {
-+ cal = rog_ally->js_calibrations[side][i];
-+ *c = (u8)((cal & 0xff00) >> 8);
-+ checksum += *c;
-+ c += 1;
-+ *c = (u8)(cal & 0xff);
-+ checksum += *c;
-+ c += 1;
-+ }
-+
-+ hidbuf[6 + data_len * 2] = checksum;
-+
-+ // TODO: debug if
-+ printk("CAL: ");
-+ for (size_t i = 0; i < 19; i++) {
-+ printk(KERN_CONT "%02x,", hidbuf[i]);
-+ }
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ memset(hidbuf, 0, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_calibration;
-+ hidbuf[3] = 0x01; // pkt len
-+ hidbuf[4] = 0x03; // second command (set)
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+report_fail:
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+static ssize_t __gamepad_cal_store(struct device *raw_dev, const char *buf, enum xpad_axis axis)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ u32 x_stable, x_min, x_max, y_stable, y_min, y_max, side;
-+
-+ if (axis == xpad_axis_xy_left || axis == xpad_axis_xy_right) {
-+ if (sscanf(buf, "%d %d %d %d %d %d", &x_stable, &x_min, &x_max, &y_stable, &y_min,
-+ &y_max) != 6)
-+ return -EINVAL;
-+ //TODO: validate input
-+
-+ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
-+ /* stored in reverse order for easy copy to packet */
-+ rog_ally->js_calibrations[side][0] = y_stable;
-+ rog_ally->js_calibrations[side][1] = y_min;
-+ rog_ally->js_calibrations[side][2] = y_max;
-+ rog_ally->js_calibrations[side][3] = x_stable;
-+ rog_ally->js_calibrations[side][4] = x_min;
-+ rog_ally->js_calibrations[side][5] = x_max;
-+
-+ return __gamepad_write_cal_to_mcu(raw_dev, axis);
-+ } else {
-+ if (sscanf(buf, "%d %d", &x_stable, &x_max) != 2)
-+ return -EINVAL;
-+ //TODO: validate input
-+
-+ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
-+ /* stored in reverse order for easy copy to packet */
-+ rog_ally->tr_calibrations[side][0] = x_stable;
-+ rog_ally->tr_calibrations[side][1] = x_max;
-+
-+ return __gamepad_write_cal_to_mcu(raw_dev, axis);
-+ }
-+}
-+
-+static ssize_t __gamepad_cal_show(struct device *raw_dev, char *buf, enum xpad_axis axis)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ int side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
-+
-+ if (axis == xpad_axis_xy_left || axis == xpad_axis_xy_right) {
-+ return sysfs_emit(buf, "%d %d %d %d %d %d\n", rog_ally->js_calibrations[side][3],
-+ rog_ally->js_calibrations[side][4],
-+ rog_ally->js_calibrations[side][5],
-+ rog_ally->js_calibrations[side][0],
-+ rog_ally->js_calibrations[side][1],
-+ rog_ally->js_calibrations[side][2]);
-+ } else {
-+ return sysfs_emit(buf, "%d %d\n", rog_ally->tr_calibrations[side][0],
-+ rog_ally->tr_calibrations[side][1]);
-+ }
-+}
-+
-+ALLY_CAL_ATTR(xpad_axis_xy_left_cal, xpad_axis_xy_left, calibration);
-+ALLY_CAL_ATTR(xpad_axis_xy_right_cal, xpad_axis_xy_right, calibration);
-+ALLY_CAL_ATTR(xpad_axis_z_left_cal, xpad_axis_z_left, calibration);
-+ALLY_CAL_ATTR(xpad_axis_z_right_cal, xpad_axis_z_right, calibration);
-+
-+static ssize_t xpad_axis_xy_cal_index_show(struct device *raw_dev, struct device_attribute *attr,
-+ char *buf)
-+{
-+ return sysfs_emit(buf, "x_stable x_min x_max y_stable y_min y_max\n");
-+}
-+
-+ALLY_DEVICE_ATTR_RO(xpad_axis_xy_cal_index, calibration_index);
-+
-+static ssize_t xpad_axis_z_cal_index_show(struct device *raw_dev, struct device_attribute *attr,
-+ char *buf)
-+{
-+ return sysfs_emit(buf, "z_stable z_max\n");
-+}
-+
-+ALLY_DEVICE_ATTR_RO(xpad_axis_z_cal_index, calibration_index);
-+
-+static ssize_t __gamepad_cal_reset(struct device *raw_dev, const char *buf, enum xpad_axis axis)
-+{
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ u8 side;
-+ int ret;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+
-+ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
-+
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_calibration;
-+ hidbuf[3] = 0x02; // pkt len
-+ hidbuf[4] = 0x02; // second command (reset)
-+ hidbuf[5] = axis;
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ memset(hidbuf, 0, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_calibration;
-+ hidbuf[3] = 0x01; // pkt len
-+ hidbuf[4] = 0x03; // second command (set)
-+
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+report_fail:
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+ALLY_CAL_RESET_ATTR(xpad_axis_xy_left_cal_reset, xpad_axis_xy_left, calibration_reset);
-+ALLY_CAL_RESET_ATTR(xpad_axis_xy_right_cal_reset, xpad_axis_xy_right, calibration_reset);
-+ALLY_CAL_RESET_ATTR(xpad_axis_z_left_cal_reset, xpad_axis_z_left, calibration_reset);
-+ALLY_CAL_RESET_ATTR(xpad_axis_z_right_cal_reset, xpad_axis_z_right, calibration_reset);
-+
-+static struct attribute *gamepad_axis_xy_left_attrs[] = { &dev_attr_xpad_axis_xy_left_deadzone.attr,
-+ &dev_attr_axis_xyz_deadzone_index.attr,
-+ &dev_attr_xpad_axis_xy_left_ADZ.attr,
-+ &dev_attr_xpad_axis_xy_left_cal_reset.attr,
-+ &dev_attr_xpad_axis_xy_left_cal.attr,
-+ &dev_attr_xpad_axis_xy_cal_index.attr,
-+ &dev_attr_rc_point_left_1.attr,
-+ &dev_attr_rc_point_left_2.attr,
-+ &dev_attr_rc_point_left_3.attr,
-+ &dev_attr_rc_point_left_4.attr,
-+ &dev_attr_rc_point_index.attr,
-+ NULL };
-+static const struct attribute_group ally_controller_axis_xy_left_attr_group = {
-+ .name = "axis_xy_left",
-+ .attrs = gamepad_axis_xy_left_attrs,
-+};
-+
-+static struct attribute *gamepad_axis_xy_right_attrs[] = {
-+ &dev_attr_xpad_axis_xy_right_deadzone.attr,
-+ &dev_attr_axis_xyz_deadzone_index.attr,
-+ &dev_attr_xpad_axis_xy_right_ADZ.attr,
-+ &dev_attr_xpad_axis_xy_right_cal_reset.attr,
-+ &dev_attr_xpad_axis_xy_right_cal.attr,
-+ &dev_attr_xpad_axis_xy_cal_index.attr,
-+ &dev_attr_rc_point_right_1.attr,
-+ &dev_attr_rc_point_right_2.attr,
-+ &dev_attr_rc_point_right_3.attr,
-+ &dev_attr_rc_point_right_4.attr,
-+ &dev_attr_rc_point_index.attr,
-+ NULL
-+};
-+static const struct attribute_group ally_controller_axis_xy_right_attr_group = {
-+ .name = "axis_xy_right",
-+ .attrs = gamepad_axis_xy_right_attrs,
-+};
-+
-+static struct attribute *gamepad_axis_z_left_attrs[] = {
-+ &dev_attr_xpad_axis_z_left_deadzone.attr, &dev_attr_axis_xyz_deadzone_index.attr,
-+ &dev_attr_xpad_axis_z_left_cal.attr, &dev_attr_xpad_axis_z_cal_index.attr,
-+ &dev_attr_xpad_axis_z_left_cal_reset.attr, NULL
-+};
-+static const struct attribute_group ally_controller_axis_z_left_attr_group = {
-+ .name = "axis_z_left",
-+ .attrs = gamepad_axis_z_left_attrs,
-+};
-+
-+static struct attribute *gamepad_axis_z_right_attrs[] = {
-+ &dev_attr_xpad_axis_z_right_deadzone.attr, &dev_attr_axis_xyz_deadzone_index.attr,
-+ &dev_attr_xpad_axis_z_right_cal.attr, &dev_attr_xpad_axis_z_cal_index.attr,
-+ &dev_attr_xpad_axis_z_right_cal_reset.attr, NULL
-+};
-+static const struct attribute_group ally_controller_axis_z_right_attr_group = {
-+ .name = "axis_z_right",
-+ .attrs = gamepad_axis_z_right_attrs,
-+};
-+
-+static const struct attribute_group *gamepad_device_attr_groups[] = {
-+ &ally_controller_attr_group,
-+ &ally_controller_axis_xy_left_attr_group,
-+ &ally_controller_axis_xy_right_attr_group,
-+ &ally_controller_axis_z_left_attr_group,
-+ &ally_controller_axis_z_right_attr_group,
-+ &btn_mapping_m1_attr_group,
-+ &btn_mapping_m2_attr_group,
-+ &btn_mapping_a_attr_group,
-+ &btn_mapping_b_attr_group,
-+ &btn_mapping_x_attr_group,
-+ &btn_mapping_y_attr_group,
-+ &btn_mapping_lb_attr_group,
-+ &btn_mapping_rb_attr_group,
-+ &btn_mapping_ls_attr_group,
-+ &btn_mapping_rs_attr_group,
-+ &btn_mapping_dpad_u_attr_group,
-+ &btn_mapping_dpad_d_attr_group,
-+ &btn_mapping_dpad_l_attr_group,
-+ &btn_mapping_dpad_r_attr_group,
-+ &btn_mapping_view_attr_group,
-+ &btn_mapping_menu_attr_group,
-+ NULL
-+};
-+
-+static int __gamepad_write_all_to_mcu(struct device *raw_dev)
-+{
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ struct hid_device *hdev = to_hid_device(raw_dev);
-+ u8 *hidbuf;
-+ int ret = 0;
-+
-+ ret = __gamepad_set_mapping(&hdev->dev, btn_pair_dpad_u_d);
-+ if (ret < 0)
-+ return ret;
-+ ret = __gamepad_set_mapping(&hdev->dev, btn_pair_dpad_l_r);
-+ if (ret < 0)
-+ return ret;
-+ ret = __gamepad_set_mapping(&hdev->dev, btn_pair_ls_rs);
-+ if (ret < 0)
-+ return ret;
-+ ret = __gamepad_set_mapping(&hdev->dev, btn_pair_lb_rb);
-+ if (ret < 0)
-+ return ret;
-+ ret = __gamepad_set_mapping(&hdev->dev, btn_pair_a_b);
-+ if (ret < 0)
-+ return ret;
-+ ret = __gamepad_set_mapping(&hdev->dev, btn_pair_x_y);
-+ if (ret < 0)
-+ return ret;
-+ ret = __gamepad_set_mapping(&hdev->dev, btn_pair_view_menu);
-+ if (ret < 0)
-+ return ret;
-+ ret = __gamepad_set_mapping(&hdev->dev, btn_pair_m1_m2);
-+ if (ret < 0)
-+ return ret;
-+ __gamepad_set_mapping(&hdev->dev, btn_pair_lt_rt);
-+ if (ret < 0)
-+ return ret;
-+ __gamepad_set_deadzones(raw_dev);
-+ if (ret < 0)
-+ return ret;
-+ __gamepad_write_js_ADZ_to_mcu(raw_dev);
-+ if (ret < 0)
-+ return ret;
-+ __gamepad_write_vibe_intensity_to_mcu(raw_dev);
-+ if (ret < 0)
-+ return ret;
-+ __gamepad_write_response_curves_to_mcu(raw_dev);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = __gamepad_check_ready(hdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ /* set turbo */
-+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
-+ if (!hidbuf)
-+ return -ENOMEM;
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_set_turbo;
-+ hidbuf[3] = 0x20; // length
-+ memcpy(&hidbuf[4], rog_ally->turbo_btns[rog_ally->mode - 1], TURBO_BLOCK_LEN);
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+
-+ kfree(hidbuf);
-+ return ret;
-+}
-+
-+static int asus_rog_ally_probe(struct hid_device *hdev, const struct rog_ops *ops)
-+{
-+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
-+ int ret = 0;
-+
-+ /* all ROG devices have this HID interface but we will focus on Ally for now */
-+ if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD && hid_is_usb(hdev)) {
-+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-+
-+ if (intf->altsetting->desc.bInterfaceNumber == 0) {
-+ hid_info(hdev, "Setting up ROG USB interface\n");
-+ /* initialise and set up USB, common to ROG */
-+ // TODO:
-+
-+ /* initialise the Ally data */
-+ if (drvdata->quirks & QUIRK_ROG_ALLY_XPAD) {
-+ hid_info(hdev, "Setting up ROG Ally interface\n");
-+
-+ drvdata->rog_ally_data = devm_kzalloc(
-+ &hdev->dev, sizeof(*drvdata->rog_ally_data), GFP_KERNEL);
-+ if (!drvdata->rog_ally_data) {
-+ hid_err(hdev, "Can't alloc Asus ROG USB interface\n");
-+ ret = -ENOMEM;
-+ goto err_stop_hw;
-+ }
-+ // TODO: move these to functions
-+ drvdata->rog_ally_data->mode = xpad_mode_game;
-+ for (int i = 0; i < xpad_mode_mouse; i++) {
-+ drvdata->rog_ally_data->deadzones[i][0][1] = 64;
-+ drvdata->rog_ally_data->deadzones[i][0][3] = 64;
-+ drvdata->rog_ally_data->deadzones[i][1][1] = 64;
-+ drvdata->rog_ally_data->deadzones[i][1][3] = 64;
-+
-+ drvdata->rog_ally_data->response_curve[i][0][0] = 0x14;
-+ drvdata->rog_ally_data->response_curve[i][0][1] = 0x14;
-+ drvdata->rog_ally_data->response_curve[i][0][2] = 0x28;
-+ drvdata->rog_ally_data->response_curve[i][0][3] = 0x28;
-+ drvdata->rog_ally_data->response_curve[i][0][4] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[i][0][5] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[i][0][6] = 0x50;
-+ drvdata->rog_ally_data->response_curve[i][0][7] = 0x50;
-+
-+ drvdata->rog_ally_data->response_curve[i][1][0] = 0x14;
-+ drvdata->rog_ally_data->response_curve[i][1][1] = 0x14;
-+ drvdata->rog_ally_data->response_curve[i][1][2] = 0x28;
-+ drvdata->rog_ally_data->response_curve[i][1][3] = 0x28;
-+ drvdata->rog_ally_data->response_curve[i][1][4] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[i][1][5] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[i][1][6] = 0x50;
-+ drvdata->rog_ally_data->response_curve[i][1][7] = 0x50;
-+
-+ drvdata->rog_ally_data->vibration_intensity[i][0] = 64;
-+ drvdata->rog_ally_data->vibration_intensity[i][1] = 64;
-+ }
-+
-+ /* ignore all errors for this as they are related to USB HID I/O */
-+ __gamepad_mapping_xpad_default(drvdata->rog_ally_data);
-+ __gamepad_mapping_wasd_default(drvdata->rog_ally_data);
-+ // these calls will never error so ignore the return
-+ __gamepad_mapping_store(&hdev->dev, "kb_f14", btn_pair_m1_m2,
-+ btn_pair_side_left, false); // M2
-+ __gamepad_mapping_store(&hdev->dev, "kb_f15", btn_pair_m1_m2,
-+ btn_pair_side_right, false); // M1
-+ __gamepad_set_mapping(&hdev->dev, btn_pair_m1_m2);
-+ __gamepad_set_mode(&hdev->dev, xpad_mode_game);
-+ }
-+
-+ if (sysfs_create_groups(&hdev->dev.kobj, gamepad_device_attr_groups))
-+ goto err_stop_hw;
-+ }
-+ }
-+
-+ return 0;
-+err_stop_hw:
-+ hid_hw_stop(hdev);
-+ return ret;
-+}
-+
-+void asus_rog_ally_remove(struct hid_device *hdev, const struct rog_ops *ops)
-+{
-+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
-+ if (drvdata->rog_ally_data) {
-+ __gamepad_set_mode(&hdev->dev, xpad_mode_mouse);
-+ sysfs_remove_groups(&hdev->dev.kobj, gamepad_device_attr_groups);
-+ }
-+}
-+
-+const struct rog_ops rog_ally = {
-+ .probe = asus_rog_ally_probe,
-+ .remove = asus_rog_ally_remove,
-+};
-diff --git a/drivers/hid/hid-asus-rog.h b/drivers/hid/hid-asus-rog.h
-new file mode 100644
-index 000000000000..efad0b041d5d
---- /dev/null
-+++ b/drivers/hid/hid-asus-rog.h
-@@ -0,0 +1,482 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * HID driver for Asus ROG laptops and Ally
-+ *
-+ * Copyright (c) 2023 Luke Jones <luke@ljones.dev>
-+ */
-+
-+/* data that is private to the hid-asus-rog module */
-+
-+#include <linux/hid.h>
-+#include <linux/types.h>
-+
-+#define BTN_CODE_LEN 11
-+#define MAPPING_BLOCK_LEN 44
-+
-+#define TURBO_BLOCK_LEN 32
-+#define TURBO_BLOCK_STEP 2
-+
-+#define PAD_A "pad_a"
-+#define PAD_B "pad_b"
-+#define PAD_X "pad_x"
-+#define PAD_Y "pad_y"
-+#define PAD_LB "pad_lb"
-+#define PAD_RB "pad_rb"
-+#define PAD_LS "pad_ls"
-+#define PAD_RS "pad_rs"
-+#define PAD_DPAD_UP "pad_dpad_up"
-+#define PAD_DPAD_DOWN "pad_dpad_down"
-+#define PAD_DPAD_LEFT "pad_dpad_left"
-+#define PAD_DPAD_RIGHT "pad_dpad_right"
-+#define PAD_VIEW "pad_view"
-+#define PAD_MENU "pad_menu"
-+#define PAD_XBOX "pad_xbox"
-+
-+#define KB_M1 "kb_m1"
-+#define KB_M2 "kb_m2"
-+#define KB_ESC "kb_esc"
-+#define KB_F1 "kb_f1"
-+#define KB_F2 "kb_f2"
-+#define KB_F3 "kb_f3"
-+#define KB_F4 "kb_f4"
-+#define KB_F5 "kb_f5"
-+#define KB_F6 "kb_f6"
-+#define KB_F7 "kb_f7"
-+#define KB_F8 "kb_f8"
-+#define KB_F9 "kb_f9"
-+#define KB_F10 "kb_f10"
-+#define KB_F11 "kb_f11"
-+#define KB_F12 "kb_f12"
-+#define KB_F14 "kb_f14"
-+#define KB_F15 "kb_f15"
-+
-+#define KB_BACKTICK "kb_backtick"
-+#define KB_1 "kb_1"
-+#define KB_2 "kb_2"
-+#define KB_3 "kb_3"
-+#define KB_4 "kb_4"
-+#define KB_5 "kb_5"
-+#define KB_6 "kb_6"
-+#define KB_7 "kb_7"
-+#define KB_8 "kb_8"
-+#define KB_9 "kb_9"
-+#define KB_0 "kb_0"
-+#define KB_HYPHEN "kb_hyphen"
-+#define KB_EQUALS "kb_equals"
-+#define KB_BACKSPACE "kb_backspace"
-+
-+#define KB_TAB "kb_tab"
-+#define KB_Q "kb_q"
-+#define KB_W "kb_w"
-+#define KB_E "kb_e"
-+#define KB_R "kb_r"
-+#define KB_T "kb_t"
-+#define KB_Y "kb_y"
-+#define KB_U "kb_u"
-+#define KB_I "kb_i"
-+#define KB_O "kb_o"
-+#define KB_P "kb_p"
-+#define KB_LBRACKET "kb_lbracket"
-+#define KB_RBRACKET "kb_rbracket"
-+#define KB_BACKSLASH "kb_bkslash"
-+
-+#define KB_CAPS "kb_caps"
-+#define KB_A "kb_a"
-+#define KB_S "kb_s"
-+#define KB_D "kb_d"
-+#define KB_F "kb_f"
-+#define KB_G "kb_g"
-+#define KB_H "kb_h"
-+#define KB_J "kb_j"
-+#define KB_K "kb_k"
-+#define KB_L "kb_l"
-+#define KB_SEMI "kb_semicolon"
-+#define KB_QUOTE "kb_quote"
-+#define KB_RET "kb_enter"
-+
-+#define KB_LSHIFT "kb_lshift"
-+#define KB_Z "kb_z"
-+#define KB_X "kb_x"
-+#define KB_C "kb_c"
-+#define KB_V "kb_v"
-+#define KB_B "kb_b"
-+#define KB_N "kb_n"
-+#define KB_M "kb_m"
-+#define KB_COMMA "kb_comma"
-+#define KB_PERIOD "kb_period"
-+#define KB_FWDSLASH "kb_fwdslash"
-+#define KB_RSHIFT "kb_rshift"
-+
-+#define KB_LCTL "kb_lctl"
-+#define KB_META "kb_meta"
-+#define KB_LALT "kb_lalt"
-+#define KB_SPACE "kb_space"
-+#define KB_RALT "kb_ralt"
-+#define KB_MENU "kb_menu"
-+#define KB_RCTL "kb_rctl"
-+
-+#define KB_PRNTSCN "kb_prntscn"
-+#define KB_SCRLCK "kb_scrlck"
-+#define KB_PAUSE "kb_pause"
-+#define KB_INS "kb_ins"
-+#define KB_HOME "kb_home"
-+#define KB_PGUP "kb_pgup"
-+#define KB_DEL "kb_del"
-+#define KB_END "kb_end"
-+#define KB_PGDWN "kb_pgdwn"
-+
-+#define KB_UP_ARROW "kb_up_arrow"
-+#define KB_DOWN_ARROW "kb_down_arrow"
-+#define KB_LEFT_ARROW "kb_left_arrow"
-+#define KB_RIGHT_ARROW "kb_right_arrow"
-+
-+#define NUMPAD_LOCK "numpad_lock"
-+#define NUMPAD_FWDSLASH "numpad_fwdslash"
-+#define NUMPAD_ASTERISK "numpad_asterisk"
-+#define NUMPAD_HYPHEN "numpad_hyphen"
-+#define NUMPAD_0 "numpad_0"
-+#define NUMPAD_1 "numpad_1"
-+#define NUMPAD_2 "numpad_2"
-+#define NUMPAD_3 "numpad_3"
-+#define NUMPAD_4 "numpad_4"
-+#define NUMPAD_5 "numpad_5"
-+#define NUMPAD_6 "numpad_6"
-+#define NUMPAD_7 "numpad_7"
-+#define NUMPAD_8 "numpad_8"
-+#define NUMPAD_9 "numpad_9"
-+#define NUMPAD_PLUS "numpad_plus"
-+#define NUMPAD_ENTER "numpad_enter"
-+#define NUMPAD_PERIOD "numpad_."
-+
-+#define RAT_LCLICK "rat_lclick"
-+#define RAT_RCLICK "rat_rclick"
-+#define RAT_MCLICK "rat_mclick"
-+#define RAT_WHEEL_UP "rat_wheel_up"
-+#define RAT_WHEEL_DOWN "rat_wheel_down"
-+
-+#define MEDIA_SCREENSHOT "media_screenshot"
-+#define MEDIA_SHOW_KEYBOARD "media_show_keyboard"
-+#define MEDIA_SHOW_DESKTOP "media_show_desktop"
-+#define MEDIA_START_RECORDING "media_start_recording"
-+#define MEDIA_MIC_OFF "media_mic_off"
-+#define MEDIA_VOL_DOWN "media_vol_down"
-+#define MEDIA_VOL_UP "media_vol_up"
-+
-+/* required so we can have nested attributes with same name but different functions */
-+#define ALLY_DEVICE_ATTR_RW(_name, _sysfs_name) \
-+ struct device_attribute dev_attr_##_name = \
-+ __ATTR(_sysfs_name, 0644, _name##_show, _name##_store)
-+
-+#define ALLY_DEVICE_ATTR_RO(_name, _sysfs_name) \
-+ struct device_attribute dev_attr_##_name = __ATTR(_sysfs_name, 0444, _name##_show, NULL)
-+
-+#define ALLY_DEVICE_ATTR_WO(_name, _sysfs_name) \
-+ struct device_attribute dev_attr_##_name = __ATTR(_sysfs_name, 0200, NULL, _name##_store)
-+
-+/* response curve macros */
-+#define ALLY_RESP_CURVE_SHOW(_name, _point_n) \
-+ static ssize_t _name##_show(struct device *raw_dev, struct device_attribute *attr, \
-+ char *buf) \
-+ { \
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev); \
-+ int idx = (_point_n - 1) * 2; \
-+ return sysfs_emit( \
-+ buf, "%d %d\n", \
-+ rog_ally->response_curve[rog_ally->mode][btn_pair_side_left][idx], \
-+ rog_ally->response_curve[rog_ally->mode][btn_pair_side_right][idx + 1]); \
-+ }
-+
-+#define ALLY_RESP_CURVE_STORE(_name, _side, _point_n) \
-+ static ssize_t _name##_store(struct device *raw_dev, struct device_attribute *attr, \
-+ const char *buf, size_t count) \
-+ { \
-+ int ret = __gamepad_store_response_curve(raw_dev, buf, btn_pair_side_##_side, \
-+ _point_n); \
-+ if (ret < 0) \
-+ return ret; \
-+ return count; \
-+ }
-+
-+/* _point_n must start at 1 */
-+#define ALLY_JS_RC_POINT(_side, _point_n, _sysfs_label) \
-+ ALLY_RESP_CURVE_SHOW(rc_point_##_side##_##_point_n, _point_n); \
-+ ALLY_RESP_CURVE_STORE(rc_point_##_side##_##_point_n, _side, _point_n); \
-+ ALLY_DEVICE_ATTR_RW(rc_point_##_side##_##_point_n, _sysfs_label##_point_n);
-+
-+/* deadzone macros */
-+#define ALLY_AXIS_DEADZONE_SHOW(_axis) \
-+ static ssize_t _axis##_deadzone_show(struct device *raw_dev, \
-+ struct device_attribute *attr, char *buf) \
-+ { \
-+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev); \
-+ int side, is_tr; \
-+ \
-+ is_tr = _axis > xpad_axis_xy_right; \
-+ side = _axis == xpad_axis_xy_right || _axis == xpad_axis_z_right ? 2 : 0; \
-+ \
-+ return sysfs_emit(buf, "%d %d\n", \
-+ rog_ally->deadzones[rog_ally->mode][is_tr][side], \
-+ rog_ally->deadzones[rog_ally->mode][is_tr][side + 1]); \
-+ }
-+
-+#define ALLY_AXIS_DEADZONE_STORE(_axis) \
-+ static ssize_t _axis##_deadzone_store(struct device *raw_dev, \
-+ struct device_attribute *attr, const char *buf, \
-+ size_t count) \
-+ { \
-+ int ret = __gamepad_store_deadzones(raw_dev, _axis, buf); \
-+ if (ret < 0) \
-+ return ret; \
-+ return count; \
-+ }
-+
-+#define ALLY_AXIS_DEADZONE(_axis, _sysfs_label) \
-+ ALLY_AXIS_DEADZONE_SHOW(_axis); \
-+ ALLY_AXIS_DEADZONE_STORE(_axis); \
-+ ALLY_DEVICE_ATTR_RW(_axis##_deadzone, _sysfs_label);
-+
-+/* button specific macros */
-+#define ALLY_BTN_SHOW(_fname, _pair, _side, _secondary) \
-+ static ssize_t _fname##_show(struct device *raw_dev, struct device_attribute *attr, \
-+ char *buf) \
-+ { \
-+ return sysfs_emit(buf, "%s\n", \
-+ __btn_map_to_string(raw_dev, _pair, _side, _secondary)); \
-+ }
-+
-+#define ALLY_BTN_STORE(_fname, _pair, _side, _secondary) \
-+ static ssize_t _fname##_store(struct device *raw_dev, struct device_attribute *attr, \
-+ const char *buf, size_t count) \
-+ { \
-+ int ret = __gamepad_mapping_store(raw_dev, buf, _pair, _side, _secondary); \
-+ if (ret < 0) \
-+ return ret; \
-+ return count; \
-+ }
-+
-+#define ALLY_BTN_TURBO_SHOW(_fname, _pair, _side) \
-+ static ssize_t _fname##_turbo_show(struct device *raw_dev, struct device_attribute *attr, \
-+ char *buf) \
-+ { \
-+ return sysfs_emit(buf, "%d\n", __gamepad_turbo_show(raw_dev, _pair, _side)); \
-+ }
-+
-+#define ALLY_BTN_TURBO_STORE(_fname, _pair, _side) \
-+ static ssize_t _fname##_turbo_store(struct device *raw_dev, struct device_attribute *attr, \
-+ const char *buf, size_t count) \
-+ { \
-+ int ret = __gamepad_turbo_store(raw_dev, buf, _pair, _side); \
-+ if (ret < 0) \
-+ return ret; \
-+ return count; \
-+ }
-+
-+#define ALLY_BTN_ATTRS_GROUP(_name, _fname) \
-+ static struct attribute *_fname##_attrs[] = { &dev_attr_##_fname.attr, \
-+ &dev_attr_##_fname##_macro.attr, \
-+ &dev_attr_##_fname##_turbo.attr, NULL }; \
-+ static const struct attribute_group _fname##_attr_group = { \
-+ .name = __stringify(_name), \
-+ .attrs = _fname##_attrs, \
-+ };
-+
-+#define ALLY_BTN_MAPPING(_fname, _pair, _side) \
-+ ALLY_BTN_SHOW(btn_mapping_##_fname, _pair, _side, false); \
-+ ALLY_BTN_STORE(btn_mapping_##_fname, _pair, _side, false); \
-+ \
-+ ALLY_BTN_SHOW(btn_mapping_##_fname##_macro, _pair, _side, true); \
-+ ALLY_BTN_STORE(btn_mapping_##_fname##_macro, _pair, _side, true); \
-+ \
-+ ALLY_BTN_TURBO_SHOW(btn_mapping_##_fname, _pair, _side); \
-+ ALLY_BTN_TURBO_STORE(btn_mapping_##_fname, _pair, _side); \
-+ \
-+ ALLY_DEVICE_ATTR_RW(btn_mapping_##_fname, remap); \
-+ ALLY_DEVICE_ATTR_RW(btn_mapping_##_fname##_macro, macro_remap); \
-+ ALLY_DEVICE_ATTR_RW(btn_mapping_##_fname##_turbo, turbo); \
-+ \
-+ ALLY_BTN_ATTRS_GROUP(btn_##_fname, btn_mapping_##_fname);
-+
-+/* calibration macros */
-+#define ALLY_CAL_STORE(_fname, _axis) \
-+ static ssize_t _fname##_store(struct device *raw_dev, struct device_attribute *attr, \
-+ const char *buf, size_t count) \
-+ { \
-+ int ret = __gamepad_cal_store(raw_dev, buf, _axis); \
-+ if (ret < 0) \
-+ return ret; \
-+ return count; \
-+ };
-+
-+#define ALLY_CAL_SHOW(_fname, _axis) \
-+ static ssize_t _fname##_show(struct device *raw_dev, struct device_attribute *attr, \
-+ char *buf) \
-+ { \
-+ return __gamepad_cal_show(raw_dev, buf, _axis); \
-+ }
-+
-+#define ALLY_CAL_ATTR(_fname, _axis, _sysfs_label) \
-+ ALLY_CAL_STORE(_fname, _axis); \
-+ ALLY_CAL_SHOW(_fname, _axis); \
-+ ALLY_DEVICE_ATTR_RW(_fname, _sysfs_label);
-+
-+#define ALLY_CAL_RESET_STORE(_fname, _axis) \
-+ static ssize_t _fname##_store(struct device *raw_dev, struct device_attribute *attr, \
-+ const char *buf, size_t count) \
-+ { \
-+ int ret = __gamepad_cal_reset(raw_dev, buf, _axis); \
-+ if (ret < 0) \
-+ return ret; \
-+ return count; \
-+ };
-+
-+#define ALLY_CAL_RESET_ATTR(_fname, _axis, _sysfs_label) \
-+ ALLY_CAL_RESET_STORE(_fname, _axis); \
-+ ALLY_DEVICE_ATTR_WO(_fname, _sysfs_label);
-+
-+/* Default blocks for the xpad mode */
-+static const u8 XPAD_DEF1[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x19,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8c, 0x88, 0x76, 0x00, 0x00
-+};
-+static const u8 XPAD_DEF2[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-+ 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0d, 0x00, 0x00, 0x00
-+};
-+static const u8 XPAD_DEF3[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 XPAD_DEF4[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 XPAD_DEF5[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x16,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00, 0x00
-+};
-+static const u8 XPAD_DEF6[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-+ 0x00, 0x02, 0x82, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 XPAD_DEF7[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 XPAD_DEF8[MAPPING_BLOCK_LEN] = {
-+ 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8e, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 XPAD_DEF9[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+
-+/* default blocks for the wasd mode */
-+static const u8 WASD_DEF1[MAPPING_BLOCK_LEN] = {
-+ 0x02, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x19,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8c, 0x88, 0x76, 0x00, 0x00
-+};
-+static const u8 WASD_DEF2[MAPPING_BLOCK_LEN] = {
-+ 0x02, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-+ 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0d, 0x00, 0x00, 0x00
-+};
-+static const u8 WASD_DEF3[MAPPING_BLOCK_LEN] = {
-+ 0x02, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 WASD_DEF4[MAPPING_BLOCK_LEN] = {
-+ 0x02, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 WASD_DEF5[MAPPING_BLOCK_LEN] = {
-+ 0x02, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x16,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00, 0x00
-+};
-+static const u8 WASD_DEF6[MAPPING_BLOCK_LEN] = {
-+ 0x02, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-+ 0x00, 0x02, 0x82, 0x4d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 WASD_DEF7[MAPPING_BLOCK_LEN] = {
-+ 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 WASD_DEF8[MAPPING_BLOCK_LEN] = {
-+ 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8e, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+static const u8 WASD_DEF9[MAPPING_BLOCK_LEN] = {
-+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+
-+/*
-+ * the xpad_mode is used inside the mode setting packet and is used
-+ * for indexing (xpad_mode - 1)
-+ */
-+enum xpad_mode {
-+ xpad_mode_game = 0x01,
-+ xpad_mode_wasd = 0x02,
-+ xpad_mode_mouse = 0x03,
-+};
-+
-+/* the xpad_cmd determines which feature is set or queried */
-+enum xpad_cmd {
-+ xpad_cmd_set_mode = 0x01,
-+ xpad_cmd_set_mapping = 0x02,
-+ xpad_cmd_set_js_dz = 0x04, /* deadzones */
-+ xpad_cmd_set_tr_dz = 0x05, /* deadzones */
-+ xpad_cmd_set_vibe_intensity = 0x06,
-+ xpad_cmd_check_ready = 0x0A,
-+ xpad_cmd_set_calibration = 0x0D,
-+ xpad_cmd_set_turbo = 0x0F,
-+ xpad_cmd_set_response_curve = 0x13,
-+ xpad_cmd_set_adz = 0x18,
-+};
-+
-+/*
-+ * the xpad_mode is used in various set and query HID packets and is
-+ * used for indexing (xpad_axis - 1)
-+ */
-+enum xpad_axis {
-+ xpad_axis_xy_left = 0x01,
-+ xpad_axis_xy_right = 0x02,
-+ xpad_axis_z_left = 0x03,
-+ xpad_axis_z_right = 0x04,
-+};
-+
-+enum btn_pair {
-+ btn_pair_dpad_u_d = 0x01,
-+ btn_pair_dpad_l_r = 0x02,
-+ btn_pair_ls_rs = 0x03,
-+ btn_pair_lb_rb = 0x04,
-+ btn_pair_a_b = 0x05,
-+ btn_pair_x_y = 0x06,
-+ btn_pair_view_menu = 0x07,
-+ btn_pair_m1_m2 = 0x08,
-+ btn_pair_lt_rt = 0x09,
-+};
-+
-+enum btn_pair_side {
-+ btn_pair_side_left = 0x00,
-+ btn_pair_side_right = 0x01,
-+};
-+
-+static int __gamepad_write_all_to_mcu(struct device *raw_dev);
-\ No newline at end of file
-diff --git a/drivers/hid/hid-asus.h b/drivers/hid/hid-asus.h
-new file mode 100644
-index 000000000000..18317cad7110
---- /dev/null
-+++ b/drivers/hid/hid-asus.h
-@@ -0,0 +1,58 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * HID driver for Asus ROG laptops and Ally
-+ *
-+ * Copyright (c) 2023 Luke Jones <luke@ljones.dev>
-+ */
-+
-+#include <linux/hid.h>
-+#include <linux/types.h>
-+
-+#define FEATURE_KBD_REPORT_ID 0x5a
-+#define FEATURE_KBD_REPORT_SIZE 16
-+#define FEATURE_KBD_LED_REPORT_ID1 0x5d
-+#define FEATURE_KBD_LED_REPORT_ID2 0x5e
-+#define FEATURE_ROG_ALLY_REPORT_SIZE 64
-+
-+#define QUIRK_FIX_NOTEBOOK_REPORT BIT(0)
-+#define QUIRK_NO_INIT_REPORTS BIT(1)
-+#define QUIRK_SKIP_INPUT_MAPPING BIT(2)
-+#define QUIRK_IS_MULTITOUCH BIT(3)
-+#define QUIRK_NO_CONSUMER_USAGES BIT(4)
-+#define QUIRK_USE_KBD_BACKLIGHT BIT(5)
-+#define QUIRK_T100_KEYBOARD BIT(6)
-+#define QUIRK_T100CHI BIT(7)
-+#define QUIRK_G752_KEYBOARD BIT(8)
-+#define QUIRK_T90CHI BIT(9)
-+#define QUIRK_MEDION_E1239T BIT(10)
-+#define QUIRK_ROG_NKEY_KEYBOARD BIT(11)
-+#define QUIRK_ROG_CLAYMORE_II_KEYBOARD BIT(12)
-+#define QUIRK_ROG_ALLY_XPAD BIT(13)
-+
-+struct asus_drvdata {
-+ unsigned long quirks;
-+ struct hid_device *hdev;
-+ struct input_dev *input;
-+ struct input_dev *tp_kbd_input;
-+ struct asus_kbd_leds *kbd_backlight;
-+ const struct asus_touchpad_info *tp;
-+ bool enable_backlight;
-+ struct power_supply *battery;
-+ struct power_supply_desc battery_desc;
-+ int battery_capacity;
-+ int battery_stat;
-+ bool battery_in_query;
-+ unsigned long battery_next_query;
-+ struct asus_rog_ally *rog_ally_data;
-+};
-+
-+extern int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size);
-+
-+extern int asus_kbd_get_report(struct hid_device *hdev, u8 *out_buf, size_t out_buf_size);
-+
-+struct rog_ops {
-+ int (*probe) (struct hid_device *hdev, const struct rog_ops *ops);
-+ void (*remove) (struct hid_device *hdev, const struct rog_ops *ops);
-+};
-+
-+extern const struct rog_ops rog_ally;
-\ No newline at end of file
---
-2.43.0
-