summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authordragonn2021-08-26 13:23:08 +0200
committerdragonn2021-08-26 13:23:08 +0200
commit9d5052ad55f5ff26d1663e2b43930621c2eec291 (patch)
tree691b32f260e7cfebd999a2c01943cc912e3a8ce3
parent143e713725c0776e3bc498195a4a1b0b3af317e7 (diff)
downloadaur-9d5052ad55f5ff26d1663e2b43930621c2eec291.tar.gz
5.13.12
-rw-r--r--.SRCINFO20
-rw-r--r--PKGBUILD65
-rw-r--r--sys-kernel_arch-sources-g14_files-0045-v5-asus-wmi-Add-support-for-platform_profile.patch239
-rw-r--r--sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch788
-rw-r--r--sys-kernel_arch-sources-g14_files-9006-amd-c3-entry.patch38
5 files changed, 1100 insertions, 50 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 2b33893e101a..35786e8a1c11 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,7 +1,7 @@
pkgbase = linux-g14
pkgdesc = Linux
- pkgver = 5.13.9.arch1
- pkgrel = 1
+ pkgver = 5.13.12.arch1
+ pkgrel = 2
url = https://lab.retarded.farm/zappel/asus-rog-zephyrus-g14/
arch = x86_64
license = GPL2
@@ -16,19 +16,19 @@ pkgbase = linux-g14
makedepends = git
makedepends = gcc>=11.0
options = !strip
- source = archlinux-linux::git+https://github.com/archlinux/linux?signed#tag=v5.13.9-arch1
+ source = archlinux-linux::git+https://github.com/archlinux/linux?signed#tag=v5.13.12-arch1
source = config
source = choose-gcc-optimization.sh
source = sys-kernel_arch-sources-g14_files-0004-5.8+--more-uarches-for-kernel.patch::https://raw.githubusercontent.com/graysky2/kernel_compiler_patch/a8d200f422f4b2abeaa6cfcfa37136b308e6e33e/more-uarches-for-kernel-5.8%2B.patch
source = sys-kernel_arch-sources-g14_files-0005-lru-multi-generational.patch
- source = sys-kernel_arch-sources-g14_files-0006-fix-tigerlake-pin-mapping.patch
+ source = https://gitlab.com/asus-linux/fedora-kernel/-/archive/e087e6d70c49c685b4d7cc7364496ade3aed3609/fedora-kernel-e087e6d70c49c685b4d7cc7364496ade3aed3609.zip
source = sys-kernel_arch-sources-g14_files-0034-btusb-mediatek.patch
source = sys-kernel_arch-sources-g14_files-0039-asus-wmi-Add-panel-overdrive-functionality.patch
- source = sys-kernel_arch-sources-g14_files-0040-asus-wmi-Add-dgpu-disable-method.patch
- source = sys-kernel_arch-sources-g14_files-0041-asus-wmi-Add-egpu-enable-method.patch
source = sys-kernel_arch-sources-g14_files-0042-HID-asus-Remove-check-for-same-LED-brightness-on-set.patch
source = sys-kernel_arch-sources-g14_files-0043-ALSA-hda-realtek-Fix-speakers-not-working-on-Asus-Fl.patch
source = sys-kernel_arch-sources-g14_files-0044-claymore.patch
+ source = sys-kernel_arch-sources-g14_files-0045-v5-asus-wmi-Add-support-for-platform_profile.patch
+ source = sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch
source = sys-kernel_arch-sources-g14_files-8001-x86-amd_nb-Add-AMD-family-19h-model-50h-PCI-ids.patch
source = sys-kernel_arch-sources-g14_files-8002-hwmon-k10temp-support-Zen3-APUs.patch
source = sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Add-support-for-Lite-On-Mediatek-Chi.patch
@@ -39,6 +39,7 @@ pkgbase = linux-g14
source = sys-kernel_arch-sources-g14_files-9003-ACPI-PM-s2idle-Invert-Microsoft-UUID-entry-and-exit.patch
source = sys-kernel_arch-sources-g14_files-9004-HID-asus-Reduce-object-size-by-consolidating-calls.patch
source = sys-kernel_arch-sources-g14_files-9005-acpi-battery-Always-read-fresh-battery-state-on-update.patch
+ source = sys-kernel_arch-sources-g14_files-9006-amd-c3-entry.patch
validpgpkeys = ABAF11C65A2970B130ABE3C479BE3E4300411886
validpgpkeys = 647F28654894E3BD457199BE38DBBDC86092693E
validpgpkeys = A2FF3A36AAA56654109064AB19802F8B0D70FC30
@@ -48,14 +49,14 @@ pkgbase = linux-g14
sha256sums = 1ac18cad2578df4a70f9346f7c6fccbb62f042a0ee0594817fdef9f2704904ee
sha256sums = fa6cee9527d8e963d3398085d1862edc509a52e4540baec463edb8a9dd95bee0
sha256sums = 9327ac3edacbc60a023928147f9439789527fad62cef66945f35a9165108e30d
- sha256sums = 1e2777841f0ed2957cb9e869a150caa014fff3c32e2744fda9c950260997dcdc
+ sha256sums = 6806c034b7480245a0b9eec448bd79042ff5ff3f9f5efbf2af78227bc56004a8
sha256sums = 0c515951db1c3dfc847e9b4777249c09be520ac140feb015a39c29e0531a89e6
sha256sums = 1ab75535772c63567384eb2ac74753e4d5db2f3317cb265aedf6151b9f18c6c2
- sha256sums = 8cc771f37ee08ad5796e6db64f180c1415a5f6e03eb3045272dade30ca754b53
- sha256sums = f3461e7cc759fd4cef2ec5c4fa15b80fa6d37e16008db223f77ed88a65aa938e
sha256sums = 96bf4c0fb920a876d7ec1ed25123bab8a0a43db5f363823e83e14707083d8501
sha256sums = 32bbcde83406810f41c9ed61206a7596eb43707a912ec9d870fd94f160d247c1
sha256sums = e2d312ea95d18e91801d131a2b5d03cf2175d3088cac6f84a19410078a5b6b14
+ sha256sums = 4ef12029ea73ca924b6397e1de4911e84d9e77ddaccdab1ef579823d848524e8
+ sha256sums = d7243b89a21cdca61e753526b82cea24af0bd28bfa0158843c31226037f39d97
sha256sums = ed28a8051514f8c228717a5cdd13191b1c58181e0228d972fbe2af5ee1d013d7
sha256sums = de8c9747637768c4356c06aa65c3f157c526aa420f21fdd5edd0ed06f720a62e
sha256sums = 67ebf477b2ecbf367ea3fee1568eeb3de59de7185ef5ed66b81ae73108f6693c
@@ -66,6 +67,7 @@ pkgbase = linux-g14
sha256sums = 5b7b8f450282a15d0832b171e82fc5639de1cb7aa495efe6e6c7989ebeb8ca36
sha256sums = 544464bf0807b324120767d55867f03014a9fda4e1804768ca341be902d7ade4
sha256sums = f7a4bf6293912bfc4a20743e58a5a266be8c4dbe3c1862d196d3a3b45f2f7c90
+ sha256sums = ee8794a551e33226900654d5c806183bf3b9b2e06f64fdc322987215d233d399
pkgname = linux-g14
pkgdesc = The Linux kernel and modules
diff --git a/PKGBUILD b/PKGBUILD
index 300f41de8706..7c25bd157309 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,8 +1,8 @@
# Maintainer: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
pkgbase=linux-g14
-pkgver=5.13.9.arch1
-pkgrel=1
+pkgver=5.13.12.arch1
+pkgrel=2
pkgdesc='Linux'
_srctag=v${pkgver%.*}-${pkgver##*.}
url="https://lab.retarded.farm/zappel/asus-rog-zephyrus-g14/"
@@ -16,7 +16,7 @@ makedepends=(
)
options=('!strip')
_srcname=archlinux-linux
-_fedora_kernel_commit_id=91f97d88231152006764d3c50cc52ddbb508529f
+_fedora_kernel_commit_id=e087e6d70c49c685b4d7cc7364496ade3aed3609
source=(
"$_srcname::git+https://github.com/archlinux/linux?signed#tag=$_srctag"
config # the main kernel config file
@@ -24,18 +24,22 @@ source=(
"sys-kernel_arch-sources-g14_files-0004-5.8+--more-uarches-for-kernel.patch"::"https://raw.githubusercontent.com/graysky2/kernel_compiler_patch/a8d200f422f4b2abeaa6cfcfa37136b308e6e33e/more-uarches-for-kernel-5.8%2B.patch"
"sys-kernel_arch-sources-g14_files-0005-lru-multi-generational.patch"
- "sys-kernel_arch-sources-g14_files-0006-fix-tigerlake-pin-mapping.patch"
+ # mainlined
+ #"sys-kernel_arch-sources-g14_files-0006-fix-tigerlake-pin-mapping.patch"
- #"https://gitlab.com/asus-linux/fedora-kernel/-/archive/$_fedora_kernel_commit_id/fedora-kernel-$_fedora_kernel_commit_id.zip"
+ "https://gitlab.com/asus-linux/fedora-kernel/-/archive/$_fedora_kernel_commit_id/fedora-kernel-$_fedora_kernel_commit_id.zip"
"sys-kernel_arch-sources-g14_files-0034-btusb-mediatek.patch"
# for now let's just pull the 5 asus-linux patches we need directly and skip all of the git filtering
"sys-kernel_arch-sources-g14_files-0039-asus-wmi-Add-panel-overdrive-functionality.patch"
- "sys-kernel_arch-sources-g14_files-0040-asus-wmi-Add-dgpu-disable-method.patch"
- "sys-kernel_arch-sources-g14_files-0041-asus-wmi-Add-egpu-enable-method.patch"
+ # pull newer version from fedora repo
+ #"sys-kernel_arch-sources-g14_files-0040-asus-wmi-Add-dgpu-disable-method.patch"
+ #"sys-kernel_arch-sources-g14_files-0041-asus-wmi-Add-egpu-enable-method.patch"
"sys-kernel_arch-sources-g14_files-0042-HID-asus-Remove-check-for-same-LED-brightness-on-set.patch"
"sys-kernel_arch-sources-g14_files-0043-ALSA-hda-realtek-Fix-speakers-not-working-on-Asus-Fl.patch"
"sys-kernel_arch-sources-g14_files-0044-claymore.patch"
+ "sys-kernel_arch-sources-g14_files-0045-v5-asus-wmi-Add-support-for-platform_profile.patch"
+ "sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch"
# k10temp support for Zen3 APUs
@@ -58,6 +62,8 @@ source=(
"sys-kernel_arch-sources-g14_files-9004-HID-asus-Reduce-object-size-by-consolidating-calls.patch"
"sys-kernel_arch-sources-g14_files-9005-acpi-battery-Always-read-fresh-battery-state-on-update.patch"
+
+ "sys-kernel_arch-sources-g14_files-9006-amd-c3-entry.patch"
)
validpgpkeys=(
@@ -72,14 +78,14 @@ sha256sums=('SKIP'
'1ac18cad2578df4a70f9346f7c6fccbb62f042a0ee0594817fdef9f2704904ee'
'fa6cee9527d8e963d3398085d1862edc509a52e4540baec463edb8a9dd95bee0'
'9327ac3edacbc60a023928147f9439789527fad62cef66945f35a9165108e30d'
- '1e2777841f0ed2957cb9e869a150caa014fff3c32e2744fda9c950260997dcdc'
+ '6806c034b7480245a0b9eec448bd79042ff5ff3f9f5efbf2af78227bc56004a8'
'0c515951db1c3dfc847e9b4777249c09be520ac140feb015a39c29e0531a89e6'
'1ab75535772c63567384eb2ac74753e4d5db2f3317cb265aedf6151b9f18c6c2'
- '8cc771f37ee08ad5796e6db64f180c1415a5f6e03eb3045272dade30ca754b53'
- 'f3461e7cc759fd4cef2ec5c4fa15b80fa6d37e16008db223f77ed88a65aa938e'
'96bf4c0fb920a876d7ec1ed25123bab8a0a43db5f363823e83e14707083d8501'
'32bbcde83406810f41c9ed61206a7596eb43707a912ec9d870fd94f160d247c1'
'e2d312ea95d18e91801d131a2b5d03cf2175d3088cac6f84a19410078a5b6b14'
+ '4ef12029ea73ca924b6397e1de4911e84d9e77ddaccdab1ef579823d848524e8'
+ 'd7243b89a21cdca61e753526b82cea24af0bd28bfa0158843c31226037f39d97'
'ed28a8051514f8c228717a5cdd13191b1c58181e0228d972fbe2af5ee1d013d7'
'de8c9747637768c4356c06aa65c3f157c526aa420f21fdd5edd0ed06f720a62e'
'67ebf477b2ecbf367ea3fee1568eeb3de59de7185ef5ed66b81ae73108f6693c'
@@ -89,7 +95,8 @@ sha256sums=('SKIP'
'6e629d4a032165f39202a702ad518a050c9305f911595a43bc34ce0c1d45d36b'
'5b7b8f450282a15d0832b171e82fc5639de1cb7aa495efe6e6c7989ebeb8ca36'
'544464bf0807b324120767d55867f03014a9fda4e1804768ca341be902d7ade4'
- 'f7a4bf6293912bfc4a20743e58a5a266be8c4dbe3c1862d196d3a3b45f2f7c90')
+ 'f7a4bf6293912bfc4a20743e58a5a266be8c4dbe3c1862d196d3a3b45f2f7c90'
+ 'ee8794a551e33226900654d5c806183bf3b9b2e06f64fdc322987215d233d399')
# notable microarch levels:
#
@@ -113,36 +120,12 @@ _fedora_kernel_patch_skip_list=(
"linux-kernel-test.patch" # test patch, please ignore
patch-*-redhat.patch # wildcard match any redhat patch version
- # 00{01..12}-drm-amdgpu*.patch # upstreamed in 5.12
-
- # upstreamed
- "0001-HID-asus-Filter-keyboard-EC-for-old-ROG-keyboard.patch"
- "0001-ALSA-hda-realtek-GA503-use-same-quirks-as-GA401.patch"
- "0001-Add-jack-toggle-support-for-headphones-on-Asus-ROG-Z.patch"
- "0001-HID-asus-filter-G713-G733-key-event-to-prevent-shutd.patch"
- "0001-ACPI-video-use-native-backlight-for-GA401-GA502-GA50.patch"
- "0002-Revert-platform-x86-asus-nb-wmi-Drop-duplicate-DMI-q.patch"
- "0003-Revert-platform-x86-asus-nb-wmi-add-support-for-ASUS.patch"
-
-
- # filter out suspend patches, we'll use upstream directly
- "0001-ACPI-processor-idle-Fix-up-C-state-latency-if-not-ordered.patch"
- "0002-v5-usb-pci-quirks-disable-D3cold-on-xhci-suspend-for-s2idle-on-AMD-Renoir.diff"
- "0003-PCI-quirks-Quirk-PCI-d3hot-delay-for-AMD-xhci.diff"
- "0004-nvme-pci_look_for_StorageD3Enable_on_companion_ACPI_device_instead.patch"
- "0005-v5-1-2-acpi-PM-Move-check-for-_DSD-StorageD3Enable-property-to-acpi.diff"
- "0006-v5-2-2-acpi-PM-Add-quirks-for-AMD-Renoir-Lucienne-CPUs-to-force-the-D3-hint.diff"
- "0007-ACPI_PM_s2idle_Add_missing_LPS0_functions_for_AMD.patch"
- "0008-2-2-V2-platform-x86-force-LPS0-functions-for-AMD.diff"
-
- # filter suspend patches from 'rog' branch
- "0002-drm-amdgpu-drop-extraneous-hw_status-update.patch"
- "0013-ACPI-idle-override-and-update-c-state-latency-when-n.patch"
- "0014-usb-pci-quirks-disable-D3cold-on-AMD-xhci-suspend-fo.patch"
- "0015-PCI-quirks-Quirk-PCI-d3hot-delay-for-AMD-xhci.patch"
- "0016-nvme-put-some-AMD-PCIE-downstream-NVME-device-to-sim.patch"
- "0017-platform-x86-Add-missing-LPS0-functions-for-AMD.patch"
- "0018-platform-x86-force-LPS0-functions-for-AMD.patch"
+
+ 0001-asus-wmi-Add-support-for-platform_profile.patch
+ 0001-asus-wmi-Add-panel-overdrive-functionality.patch
+ 0004-HID-asus-Remove-check-for-same-LED-brightness-on-set.patch
+ 0001-HID-asus-Prevent-Claymore-sending-suspend-event.patch
+ 0015-PCI-quirks-Quirk-PCI-d3hot-delay-for-AMD-xhci.patch
)
export KBUILD_BUILD_HOST=archlinux
diff --git a/sys-kernel_arch-sources-g14_files-0045-v5-asus-wmi-Add-support-for-platform_profile.patch b/sys-kernel_arch-sources-g14_files-0045-v5-asus-wmi-Add-support-for-platform_profile.patch
new file mode 100644
index 000000000000..737c3bd2c15c
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-0045-v5-asus-wmi-Add-support-for-platform_profile.patch
@@ -0,0 +1,239 @@
+From ecb125585d4e69dda57647af19b8a8736b876cee Mon Sep 17 00:00:00 2001
+From: "Luke D. Jones" <luke@ljones.dev>
+Date: Fri, 13 Aug 2021 14:36:01 +1200
+Subject: [PATCH v5 1/1] asus-wmi: Add support for platform_profile
+
+Add initial support for platform_profile where the support is
+based on availability of ASUS_THROTTLE_THERMAL_POLICY.
+
+Because throttle_thermal_policy is used by platform_profile and is
+writeable separately to platform_profile any userspace changes to
+throttle_thermal_policy need to notify platform_profile.
+
+In future throttle_thermal_policy sysfs should be removed so that
+only one method controls the laptop power profile.
+
+Signed-off-by: Luke D. Jones <luke@ljones.dev>
+---
+ drivers/platform/x86/Kconfig | 1 +
+ drivers/platform/x86/asus-wmi.c | 130 +++++++++++++++++++++++++++++++-
+ 2 files changed, 127 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index d12db6c316ea..46dec48a36c1 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -281,6 +281,7 @@ config ASUS_WMI
+ select INPUT_SPARSEKMAP
+ select LEDS_CLASS
+ select NEW_LEDS
++ select ACPI_PLATFORM_PROFILE
+ help
+ Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new
+ Asus Notebooks).
+diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
+index 90a6a0d00deb..cc5811844012 100644
+--- a/drivers/platform/x86/asus-wmi.c
++++ b/drivers/platform/x86/asus-wmi.c
+@@ -26,6 +26,7 @@
+ #include <linux/rfkill.h>
+ #include <linux/pci.h>
+ #include <linux/pci_hotplug.h>
++#include <linux/platform_profile.h>
+ #include <linux/power_supply.h>
+ #include <linux/hwmon.h>
+ #include <linux/hwmon-sysfs.h>
+@@ -219,6 +220,9 @@ struct asus_wmi {
+ bool throttle_thermal_policy_available;
+ u8 throttle_thermal_policy_mode;
+
++ struct platform_profile_handler platform_profile_handler;
++ bool platform_profile_support;
++
+ // The RSOC controls the maximum charging percentage.
+ bool battery_rsoc_available;
+
+@@ -2103,12 +2107,23 @@ static int throttle_thermal_policy_set_default(struct asus_wmi *asus)
+ static int throttle_thermal_policy_switch_next(struct asus_wmi *asus)
+ {
+ u8 new_mode = asus->throttle_thermal_policy_mode + 1;
++ int err;
+
+ if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
+ new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
+
+ asus->throttle_thermal_policy_mode = new_mode;
+- return throttle_thermal_policy_write(asus);
++ err = throttle_thermal_policy_write(asus);
++ if (err)
++ return err;
++
++ /*
++ * Ensure that platform_profile updates userspace with the change to ensure
++ * that platform_profile and throttle_thermal_policy_mode are in sync.
++ */
++ platform_profile_notify();
++
++ return 0;
+ }
+
+ static ssize_t throttle_thermal_policy_show(struct device *dev,
+@@ -2124,9 +2139,10 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- int result;
+- u8 new_mode;
+ struct asus_wmi *asus = dev_get_drvdata(dev);
++ u8 new_mode;
++ int result;
++ int err;
+
+ result = kstrtou8(buf, 10, &new_mode);
+ if (result < 0)
+@@ -2136,7 +2152,15 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
+ return -EINVAL;
+
+ asus->throttle_thermal_policy_mode = new_mode;
+- throttle_thermal_policy_write(asus);
++ err = throttle_thermal_policy_write(asus);
++ if (err)
++ return err;
++
++ /*
++ * Ensure that platform_profile updates userspace with the change to ensure
++ * that platform_profile and throttle_thermal_policy_mode are in sync.
++ */
++ platform_profile_notify();
+
+ return count;
+ }
+@@ -2144,6 +2168,94 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
+ // Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent
+ static DEVICE_ATTR_RW(throttle_thermal_policy);
+
++/* Platform profile ***********************************************************/
++static int platform_profile_get(struct platform_profile_handler *pprof,
++ enum platform_profile_option *profile)
++{
++ struct asus_wmi *asus;
++ int tp;
++
++ asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
++
++ tp = asus->throttle_thermal_policy_mode;
++
++ if (tp < 0)
++ return tp;
++
++ switch (tp) {
++ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT:
++ *profile = PLATFORM_PROFILE_BALANCED;
++ break;
++ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST:
++ *profile = PLATFORM_PROFILE_PERFORMANCE;
++ break;
++ case ASUS_THROTTLE_THERMAL_POLICY_SILENT:
++ *profile = PLATFORM_PROFILE_QUIET;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int platform_profile_set(struct platform_profile_handler *pprof,
++ enum platform_profile_option profile)
++{
++ struct asus_wmi *asus;
++ int tp;
++
++ asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
++
++ switch (profile) {
++ case PLATFORM_PROFILE_PERFORMANCE:
++ tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
++ break;
++ case PLATFORM_PROFILE_BALANCED:
++ tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
++ break;
++ case PLATFORM_PROFILE_QUIET:
++ tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++
++ asus->throttle_thermal_policy_mode = tp;
++ return throttle_thermal_policy_write(asus);
++}
++
++static int platform_profile_setup(struct asus_wmi *asus)
++{
++ struct device *dev = &asus->platform_device->dev;
++ int err;
++
++ /*
++ * Not an error if a component platform_profile relies on is unavailable
++ * so early return, skipping the setup of platform_profile.
++ */
++ if (!asus->throttle_thermal_policy_available)
++ return 0;
++
++ dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
++
++ asus->platform_profile_handler.profile_get = platform_profile_get;
++ asus->platform_profile_handler.profile_set = platform_profile_set;
++
++ set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);
++ set_bit(PLATFORM_PROFILE_BALANCED,
++ asus->platform_profile_handler.choices);
++ set_bit(PLATFORM_PROFILE_PERFORMANCE,
++ asus->platform_profile_handler.choices);
++
++ err = platform_profile_register(&asus->platform_profile_handler);
++ if (err)
++ return err;
++
++ asus->platform_profile_support = true;
++ return 0;
++}
++
+ /* Backlight ******************************************************************/
+
+ static int read_backlight_power(struct asus_wmi *asus)
+@@ -2904,6 +3016,10 @@ static int asus_wmi_add(struct platform_device *pdev)
+ else
+ throttle_thermal_policy_set_default(asus);
+
++ err = platform_profile_setup(asus);
++ if (err)
++ goto fail_platform_profile_setup;
++
+ err = panel_od_check_present(asus);
+ if (err)
+ goto fail_panel_od;
+@@ -2993,6 +3109,9 @@ static int asus_wmi_add(struct platform_device *pdev)
+ asus_wmi_sysfs_exit(asus->platform_device);
+ fail_sysfs:
+ fail_throttle_thermal_policy:
++fail_platform_profile_setup:
++ if (asus->platform_profile_support)
++ platform_profile_remove();
+ fail_fan_boost_mode:
+ fail_egpu_enable:
+ fail_dgpu_disable:
+@@ -3017,6 +3136,9 @@ static int asus_wmi_remove(struct platform_device *device)
+ asus_fan_set_auto(asus);
+ asus_wmi_battery_exit(asus);
+
++ if (asus->platform_profile_support)
++ platform_profile_remove();
++
+ kfree(asus);
+ return 0;
+ }
+--
+2.31.1
+
diff --git a/sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch b/sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch
new file mode 100644
index 000000000000..d9adfc927112
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch
@@ -0,0 +1,788 @@
+From 770f400736f971ae3fe60ed83f43452eee128204 Mon Sep 17 00:00:00 2001
+From: "Luke D. Jones" <luke@ljones.dev>
+Date: Thu, 19 Aug 2021 10:42:17 +1200
+Subject: [PATCH v5 1/1] asus-wmi: Add support for custom fan curves
+
+Add support for custom fan curves found on some ASUS ROG laptops.
+
+These laptops have the ability to set a custom curve for the CPU
+and GPU fans via an ACPI method call. This patch enables this,
+additionally enabling custom fan curves per-profile, where profile
+here means each of the 3 levels of "throttle_thermal_policy".
+
+Signed-off-by: Luke D. Jones <luke@ljones.dev>
+---
+ drivers/platform/x86/asus-wmi.c | 666 +++++++++++++++++++++
+ include/linux/platform_data/x86/asus-wmi.h | 2 +
+ 2 files changed, 668 insertions(+)
+
+diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
+index cc5811844012..1b19894285e6 100644
+--- a/drivers/platform/x86/asus-wmi.c
++++ b/drivers/platform/x86/asus-wmi.c
+@@ -108,6 +108,11 @@ module_param(fnlock_default, bool, 0444);
+
+ static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
+
++static int throttle_thermal_policy_write(struct asus_wmi*);
++static ssize_t fan_curve_store(struct asus_wmi *asus, const char *buf,
++ size_t count, u32 dev, char **curve,
++ char *default_curve);
++
+ static bool ashs_present(void)
+ {
+ int i = 0;
+@@ -122,6 +127,7 @@ struct bios_args {
+ u32 arg0;
+ u32 arg1;
+ u32 arg2; /* At least TUF Gaming series uses 3 dword input buffer. */
++ u32 arg3;
+ u32 arg4;
+ u32 arg5;
+ } __packed;
+@@ -173,6 +179,21 @@ enum fan_type {
+ FAN_TYPE_SPEC83, /* starting in Spec 8.3, use CPU_FAN_CTRL */
+ };
+
++struct fan_curve {
++ char *balanced;
++ char *balanced_default;
++ char *performance;
++ char *performance_default;
++ char *quiet;
++ char *quiet_default;
++};
++
++struct enabled_fan_curves {
++ bool balanced;
++ bool performance;
++ bool quiet;
++};
++
+ struct asus_wmi {
+ int dsts_id;
+ int spec;
+@@ -220,6 +241,14 @@ struct asus_wmi {
+ bool throttle_thermal_policy_available;
+ u8 throttle_thermal_policy_mode;
+
++ bool cpu_fan_curve_available;
++ struct fan_curve cpu_fan_curve;
++
++ bool gpu_fan_curve_available;
++ struct fan_curve gpu_fan_curve;
++
++ struct enabled_fan_curves enabled_fan_curve_profiles;
++
+ struct platform_profile_handler platform_profile_handler;
+ bool platform_profile_support;
+
+@@ -285,6 +314,85 @@ int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval)
+ }
+ EXPORT_SYMBOL_GPL(asus_wmi_evaluate_method);
+
++static int asus_wmi_evaluate_method5(u32 method_id,
++ u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 *retval)
++{
++ struct bios_args args = {
++ .arg0 = arg0,
++ .arg1 = arg1,
++ .arg2 = arg2,
++ .arg3 = arg3,
++ .arg4 = arg4,
++ };
++ struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
++ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
++ acpi_status status;
++ union acpi_object *obj;
++ u32 tmp = 0;
++
++ status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,
++ &input, &output);
++
++ if (ACPI_FAILURE(status))
++ return -EIO;
++
++ obj = (union acpi_object *)output.pointer;
++ if (obj && obj->type == ACPI_TYPE_INTEGER)
++ tmp = (u32) obj->integer.value;
++
++ if (retval)
++ *retval = tmp;
++
++ kfree(obj);
++
++ if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
++ return -ENODEV;
++
++ return 0;
++}
++
++/*
++ * Returns as an error if the method output is not a buffer. Typically this
++ * means that the method called is unsupported.
++*/
++static int asus_wmi_evaluate_method_buf(u32 method_id,
++ u32 arg0, u32 arg1, u8 *ret_buffer)
++{
++ struct bios_args args = {
++ .arg0 = arg0,
++ .arg1 = arg1,
++ .arg2 = 0,
++ };
++ struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
++ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
++ acpi_status status;
++ union acpi_object *obj;
++ u32 int_tmp = 0;
++
++ status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,
++ &input, &output);
++
++ if (ACPI_FAILURE(status))
++ return -EIO;
++
++ obj = (union acpi_object *)output.pointer;
++
++ if (obj && obj->type == ACPI_TYPE_INTEGER) {
++ int_tmp = (u32) obj->integer.value;
++ if (int_tmp == ASUS_WMI_UNSUPPORTED_METHOD)
++ return -ENODEV;
++ return int_tmp;
++ }
++
++ if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length >= 16) {
++ memcpy(ret_buffer, obj->buffer.pointer, obj->buffer.length);
++ }
++
++ kfree(obj);
++
++ return 0;
++}
++
+ static int asus_wmi_evaluate_method_agfn(const struct acpi_buffer args)
+ {
+ struct acpi_buffer input;
+@@ -2043,6 +2151,455 @@ static ssize_t fan_boost_mode_store(struct device *dev,
+ // Fan boost mode: 0 - normal, 1 - overboost, 2 - silent
+ static DEVICE_ATTR_RW(fan_boost_mode);
+
++/* Custom fan curves per-profile **********************************************/
++
++static int custom_fan_check_present(struct asus_wmi *asus,
++ bool *available, u32 dev)
++{
++ struct fan_curve *curves = &asus->cpu_fan_curve;
++ u8 *b = kzalloc(16 * sizeof(u8), GFP_KERNEL);
++ /* 15 punctuation marks + 16 sets of numbers up to 3 char each */
++ int str_len = 15 + 16 * 3;
++ int err;
++
++ *available = false;
++
++ if (dev == ASUS_WMI_DEVID_GPU_FAN_CURVE)
++ curves = &asus->gpu_fan_curve;
++
++ /* Balanced default */
++ err = asus_wmi_evaluate_method_buf(asus->dsts_id, dev, 0, b);
++ if (err) {
++ if (err == -ENODEV)
++ return 0;
++ return err;
++ }
++
++ curves->balanced = kzalloc(str_len * sizeof(char), GFP_KERNEL);
++ if (!curves->balanced)
++ return -ENOMEM;
++
++ curves->balanced_default = kzalloc(str_len * sizeof(char), GFP_KERNEL);
++ if (!curves->balanced_default)
++ return -ENOMEM;
++
++ sprintf(curves->balanced, "%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d",
++ b[0], b[8], b[1], b[9], b[2], b[10], b[3], b[11],
++ b[4], b[12], b[5], b[13], b[6], b[14], b[7], b[15]);
++ sprintf(curves->balanced_default, curves->balanced);
++
++ /* Quiet default */
++ err = asus_wmi_evaluate_method_buf(asus->dsts_id, dev, 1, b);
++ if (err) {
++ if (err == -ENODEV)
++ return 0;
++ return err;
++ }
++
++ curves->quiet = kzalloc(str_len * sizeof(char), GFP_KERNEL);
++ if (!curves->quiet)
++ return -ENOMEM;
++
++ curves->quiet_default = kzalloc(str_len * sizeof(char), GFP_KERNEL);
++ if (!curves->quiet_default)
++ return -ENOMEM;
++
++ sprintf(curves->quiet, "%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d",
++ b[0], b[8], b[1], b[9], b[2], b[10], b[3], b[11],
++ b[4], b[12], b[5], b[13], b[6], b[14], b[7], b[15]);
++ sprintf(curves->quiet_default, curves->quiet);
++
++ /* Performance default */
++ err = asus_wmi_evaluate_method_buf(asus->dsts_id, dev, 2, b);
++ if (err) {
++ if (err == -ENODEV)
++ return 0;
++ return err;
++ }
++
++ curves->performance = kzalloc(str_len * sizeof(char), GFP_KERNEL);
++ if (!curves->performance)
++ return -ENOMEM;
++
++ curves->performance_default = kzalloc(str_len * sizeof(char), GFP_KERNEL);
++ if (!curves->performance_default)
++ return -ENOMEM;
++
++ sprintf(curves->performance,
++ "%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d,%d:%d",
++ b[0], b[8], b[1], b[9], b[2], b[10], b[3], b[11],
++ b[4], b[12], b[5], b[13], b[6], b[14], b[7], b[15]);
++ sprintf(curves->performance_default, curves->performance);
++
++ kfree(b);
++
++ *available = true;
++ return 0;
++}
++
++/*
++ * The expected input is of the format
++ * "30:1,49:2,59:3,69:4,79:31,89:49,99:56,109:58"
++ * where a pair is 30:1, with 30 = temperature, and 1 = percentage
++*/
++static int fan_curve_check_valid(const char *curve)
++{
++ char * buf, *set, *set_end, *pair_tmp, *pair, *pair_end;
++ int err, ret;
++
++ char *set_delimiter = ",";
++ char *pair_delimiter = ":";
++ bool pair_start = true;
++ u32 prev_percent = 0;
++ u32 prev_temp = 0;
++ u32 percent = 0;
++ u32 temp = 0;
++
++ buf = set_end = pair_end = kstrdup(curve, GFP_KERNEL);
++
++ while( (set = strsep(&set_end, set_delimiter)) != NULL ) {
++ pair_tmp = kstrdup(set, GFP_KERNEL);
++ pair_start = true;
++ while( (pair = strsep(&pair_tmp, pair_delimiter)) != NULL ) {
++ err = kstrtouint(pair, 10, &ret);
++ if (err) {
++ kfree(pair_tmp);
++ kfree(buf);
++ return err;
++ }
++
++ if (pair_start) {
++ temp = ret;
++ pair_start = false;
++ } else {
++ percent = ret;
++ }
++ }
++ kfree(pair_tmp);
++
++ if (temp < prev_temp || percent < prev_percent || percent > 100) {
++ pr_info("Fan curve invalid");
++ pr_info("A value is sequentially lower or percentage is > 100");
++ kfree(buf);
++ return -EINVAL;
++ }
++
++ prev_temp = temp;
++ prev_percent = percent;
++ }
++ kfree(buf);
++
++ return 0;
++}
++
++static int fan_curve_write(struct asus_wmi *asus, u32 dev, char *curve)
++{
++ char * buf, *set, *pair_tmp, *pair, *set_end, *pair_end;
++ int err, ret;
++
++ char *set_delimiter = ",";
++ char *pair_delimiter = ":";
++ bool half_complete = false;
++ bool pair_start = true;
++ u32 percent = 0;
++ u32 shift = 0;
++ u32 temp = 0;
++ u32 arg1 = 0;
++ u32 arg2 = 0;
++ u32 arg3 = 0;
++ u32 arg4 = 0;
++
++ buf = set_end = pair_end = kstrdup(curve, GFP_KERNEL);
++
++ while( (set = strsep(&set_end, set_delimiter)) != NULL ) {
++ pair_tmp = kstrdup(set, GFP_KERNEL);
++ pair_start = true;
++ while( (pair = strsep(&pair_tmp, pair_delimiter)) != NULL ) {
++ err = kstrtouint(pair, 10, &ret);
++ if (err) {
++ kfree(pair_tmp);
++ kfree(buf);
++ return err;
++ }
++
++ if (pair_start) {
++ temp = ret;
++ pair_start = false;
++ } else {
++ percent = ret;
++ }
++ }
++ kfree(pair_tmp);
++
++ if (!half_complete) {
++ arg1 += temp << shift;
++ arg3 += percent << shift;
++ } else {
++ arg2 += temp << shift;
++ arg4 += percent << shift;
++ }
++ shift += 8;
++
++ if (shift == 32) {
++ shift = 0;
++ half_complete = true;
++ }
++ }
++ kfree(buf);
++
++ return asus_wmi_evaluate_method5(ASUS_WMI_METHODID_DEVS, dev,
++ arg1, arg2, arg3, arg4, &ret);
++}
++
++static ssize_t fan_curve_store(struct asus_wmi *asus, const char *buf,
++ size_t count, u32 dev, char **curve,
++ char *default_curve)
++{
++ int err;
++
++ /* Allow a user to write "" or " " to erase a curve setting */
++ if (strlen(buf) <= 1 || strcmp(buf, " \n") == 0) {
++ kfree(*curve);
++ *curve = kstrdup(default_curve, GFP_KERNEL);
++ err = throttle_thermal_policy_write(asus);
++ if (err)
++ return err;
++ return count;
++ }
++
++ err = fan_curve_check_valid(buf);
++ if (err)
++ return err;
++
++ if (*curve)
++ kfree(*curve);
++
++ /* Always save fan curve if it is valid */
++ *curve = kstrdup(buf, GFP_KERNEL);
++
++ /* Maybe activate fan curve if in associated mode */
++ err = throttle_thermal_policy_write(asus);
++
++ if (err)
++ return err;
++
++ return count;
++}
++
++/*
++ * CPU Fan Curves
++*/
++
++static ssize_t cpu_fan_curve_balanced_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", asus->cpu_fan_curve.balanced);
++}
++
++static ssize_t cpu_fan_curve_balanced_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return fan_curve_store(asus, buf, count, ASUS_WMI_DEVID_CPU_FAN_CURVE,
++ &asus->cpu_fan_curve.balanced,
++ asus->cpu_fan_curve.balanced_default);
++}
++
++static DEVICE_ATTR_RW(cpu_fan_curve_balanced);
++
++static ssize_t cpu_fan_curve_performance_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", asus->cpu_fan_curve.performance);
++}
++
++static ssize_t cpu_fan_curve_performance_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return fan_curve_store(asus, buf, count, ASUS_WMI_DEVID_CPU_FAN_CURVE,
++ &asus->cpu_fan_curve.performance,
++ asus->cpu_fan_curve.performance_default);
++}
++
++static DEVICE_ATTR_RW(cpu_fan_curve_performance);
++
++static ssize_t cpu_fan_curve_quiet_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", asus->cpu_fan_curve.quiet);
++}
++
++static ssize_t cpu_fan_curve_quiet_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return fan_curve_store(asus, buf, count, ASUS_WMI_DEVID_CPU_FAN_CURVE,
++ &asus->cpu_fan_curve.quiet,
++ asus->cpu_fan_curve.quiet_default);
++}
++
++static DEVICE_ATTR_RW(cpu_fan_curve_quiet);
++
++/*
++ * GPU Fan Curves
++*/
++
++static ssize_t gpu_fan_curve_balanced_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", asus->gpu_fan_curve.balanced);
++}
++
++static ssize_t gpu_fan_curve_balanced_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return fan_curve_store(asus, buf, count, ASUS_WMI_DEVID_GPU_FAN_CURVE,
++ &asus->gpu_fan_curve.balanced,
++ asus->gpu_fan_curve.balanced_default);
++}
++
++static DEVICE_ATTR_RW(gpu_fan_curve_balanced);
++
++static ssize_t gpu_fan_curve_performance_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", asus->gpu_fan_curve.performance);
++}
++
++static ssize_t gpu_fan_curve_performance_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return fan_curve_store(asus, buf, count, ASUS_WMI_DEVID_GPU_FAN_CURVE,
++ &asus->gpu_fan_curve.performance,
++ asus->gpu_fan_curve.performance_default);
++}
++
++static DEVICE_ATTR_RW(gpu_fan_curve_performance);
++
++static ssize_t gpu_fan_curve_quiet_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", asus->gpu_fan_curve.quiet);
++}
++
++static ssize_t gpu_fan_curve_quiet_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ return fan_curve_store(asus, buf, count, ASUS_WMI_DEVID_GPU_FAN_CURVE,
++ &asus->gpu_fan_curve.quiet,
++ asus->gpu_fan_curve.quiet_default);
++}
++
++static DEVICE_ATTR_RW(gpu_fan_curve_quiet);
++
++/*
++ * Active curves per profile
++*/
++
++static int enabled_fan_curve_profiles_check_present(struct asus_wmi *asus)
++{
++ if (!asus->cpu_fan_curve_available || !asus->gpu_fan_curve_available)
++ return -ENODEV;
++
++ return 0;
++}
++
++
++static int enabled_fan_curve_profiles_write(struct asus_wmi *asus,
++ const char *names)
++{
++ char *buf, *set, *set_end;
++ int err;
++
++ buf = set_end = kstrdup(names, GFP_KERNEL);
++
++ /* Reset before checking */
++ asus->enabled_fan_curve_profiles.balanced = false;
++ asus->enabled_fan_curve_profiles.quiet = false;
++ asus->enabled_fan_curve_profiles.performance = false;
++
++ while( (set = strsep(&set_end, " ")) != NULL ) {
++ if (set == NULL)
++ set = buf;
++
++ pr_info("SET: %s", set);
++ pr_info("SET: %d", strcmp(set, "quiet"));
++ pr_info("SET: %d", strcmp(set, "quiet\n"));
++
++ if (strcmp(set, "balanced") == 0
++ || strcmp(set, "balanced\n") == 0)
++ asus->enabled_fan_curve_profiles.balanced = true;
++
++ if (strcmp(set, "quiet") == 0
++ || strcmp(set, "quiet\n") == 0)
++ asus->enabled_fan_curve_profiles.quiet = true;
++
++ if (strcmp(set, "performance") == 0
++ || strcmp(set, "performance\n") == 0)
++ asus->enabled_fan_curve_profiles.performance = true;
++ }
++
++ err = throttle_thermal_policy_write(asus);
++ if (err)
++ return err;
++
++ kfree(buf);
++
++ return 0;
++}
++
++static ssize_t enabled_fan_curve_profiles_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ int len = 0;
++
++ if (asus->enabled_fan_curve_profiles.balanced)
++ len += sysfs_emit_at(buf, len, "balanced ");
++
++ if (asus->enabled_fan_curve_profiles.performance)
++ len += sysfs_emit_at(buf, len, "performance ");
++
++ if (asus->enabled_fan_curve_profiles.quiet)
++ len += sysfs_emit_at(buf, len, "quiet ");
++
++ len += sysfs_emit_at(buf, len, "\n");
++
++ return len;
++}
++
++static ssize_t enabled_fan_curve_profiles_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ int err;
++
++ err = enabled_fan_curve_profiles_write(asus, buf);
++ if (err)
++ return err;
++
++ return count;
++}
++
++static DEVICE_ATTR_RW(enabled_fan_curve_profiles);
++
+ /* Throttle thermal policy ****************************************************/
+
+ static int throttle_thermal_policy_check_present(struct asus_wmi *asus)
+@@ -2067,6 +2624,59 @@ static int throttle_thermal_policy_check_present(struct asus_wmi *asus)
+ return 0;
+ }
+
++static int throttle_thermal_policy_write_cpu_curves(struct asus_wmi *asus)
++{
++ char *curve = NULL;
++ int err, mode;
++
++ mode = asus->throttle_thermal_policy_mode;
++
++ if (mode == ASUS_THROTTLE_THERMAL_POLICY_DEFAULT
++ && asus->enabled_fan_curve_profiles.balanced) {
++ curve = asus->cpu_fan_curve.balanced;
++ } else if (mode == ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST
++ && asus->enabled_fan_curve_profiles.performance) {
++ curve = asus->cpu_fan_curve.performance;
++ } else if (mode == ASUS_THROTTLE_THERMAL_POLICY_SILENT
++ && asus->enabled_fan_curve_profiles.quiet) {
++ curve = asus->cpu_fan_curve.quiet;
++ }
++
++ if (curve != NULL) {
++ err = fan_curve_write(asus, ASUS_WMI_DEVID_CPU_FAN_CURVE, curve);
++ if (err)
++ return err;
++ }
++ return 0;
++}
++
++
++static int throttle_thermal_policy_write_gpu_curves(struct asus_wmi *asus)
++{
++ char *curve = NULL;
++ int err, mode;
++
++ mode = asus->throttle_thermal_policy_mode;
++
++ if (mode == ASUS_THROTTLE_THERMAL_POLICY_DEFAULT
++ && asus->enabled_fan_curve_profiles.balanced) {
++ curve = asus->gpu_fan_curve.balanced;
++ } else if (mode == ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST
++ && asus->enabled_fan_curve_profiles.performance) {
++ curve = asus->gpu_fan_curve.performance;
++ } else if (mode == ASUS_THROTTLE_THERMAL_POLICY_SILENT
++ && asus->enabled_fan_curve_profiles.quiet) {
++ curve = asus->gpu_fan_curve.quiet;
++ }
++
++ if (curve != NULL) {
++ err = fan_curve_write(asus, ASUS_WMI_DEVID_GPU_FAN_CURVE, curve);
++ if (err)
++ return err;
++ }
++ return 0;
++}
++
+ static int throttle_thermal_policy_write(struct asus_wmi *asus)
+ {
+ int err;
+@@ -2092,6 +2702,26 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
+ return -EIO;
+ }
+
++ if (asus->cpu_fan_curve_available) {
++ err = throttle_thermal_policy_write_cpu_curves(asus);
++ if (err) {
++ dev_warn(&asus->platform_device->dev,
++ "Failed to set custom CPU curve for thermal policy: %d\n",
++ err);
++ return err;
++ }
++ }
++
++ if (asus->gpu_fan_curve_available) {
++ err = throttle_thermal_policy_write_gpu_curves(asus);
++ if (err) {
++ dev_warn(&asus->platform_device->dev,
++ "Failed to set custom GPU curve for thermal policy: %d\n",
++ err);
++ return err;
++ }
++ }
++
+ return 0;
+ }
+
+@@ -2711,6 +3341,13 @@ static struct attribute *platform_attributes[] = {
+ &dev_attr_als_enable.attr,
+ &dev_attr_fan_boost_mode.attr,
+ &dev_attr_throttle_thermal_policy.attr,
++ &dev_attr_cpu_fan_curve_balanced.attr,
++ &dev_attr_cpu_fan_curve_performance.attr,
++ &dev_attr_cpu_fan_curve_quiet.attr,
++ &dev_attr_gpu_fan_curve_balanced.attr,
++ &dev_attr_gpu_fan_curve_performance.attr,
++ &dev_attr_gpu_fan_curve_quiet.attr,
++ &dev_attr_enabled_fan_curve_profiles.attr,
+ &dev_attr_panel_od.attr,
+ NULL
+ };
+@@ -2741,6 +3378,20 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
+ 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_cpu_fan_curve_balanced.attr)
++ ok = asus->cpu_fan_curve_available;
++ else if (attr == &dev_attr_cpu_fan_curve_performance.attr)
++ ok = asus->cpu_fan_curve_available;
++ else if (attr == &dev_attr_cpu_fan_curve_quiet.attr)
++ ok = asus->cpu_fan_curve_available;
++ else if (attr == &dev_attr_gpu_fan_curve_balanced.attr)
++ ok = asus->gpu_fan_curve_available;
++ else if (attr == &dev_attr_gpu_fan_curve_performance.attr)
++ ok = asus->gpu_fan_curve_available;
++ else if (attr == &dev_attr_gpu_fan_curve_quiet.attr)
++ ok = asus->gpu_fan_curve_available;
++ else if (attr == &dev_attr_enabled_fan_curve_profiles.attr)
++ ok = asus->cpu_fan_curve_available || asus->gpu_fan_curve_available;
+ else if (attr == &dev_attr_panel_od.attr)
+ ok = asus->panel_overdrive_available;
+
+@@ -3016,6 +3667,20 @@ static int asus_wmi_add(struct platform_device *pdev)
+ else
+ throttle_thermal_policy_set_default(asus);
+
++ err = custom_fan_check_present(asus, &asus->cpu_fan_curve_available,
++ ASUS_WMI_DEVID_CPU_FAN_CURVE);
++ if (err)
++ goto fail_throttle_fan_curve;
++
++ err = custom_fan_check_present(asus, &asus->gpu_fan_curve_available,
++ ASUS_WMI_DEVID_GPU_FAN_CURVE);
++ if (err)
++ goto fail_throttle_fan_curve;
++
++ err = enabled_fan_curve_profiles_check_present(asus);
++ if (err)
++ goto fail_throttle_fan_curve;
++
+ err = platform_profile_setup(asus);
+ if (err)
+ goto fail_platform_profile_setup;
+@@ -3109,6 +3774,7 @@ static int asus_wmi_add(struct platform_device *pdev)
+ asus_wmi_sysfs_exit(asus->platform_device);
+ fail_sysfs:
+ fail_throttle_thermal_policy:
++fail_throttle_fan_curve:
+ fail_platform_profile_setup:
+ if (asus->platform_profile_support)
+ platform_profile_remove();
+diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
+index 17dc5cb6f3f2..a571b47ff362 100644
+--- a/include/linux/platform_data/x86/asus-wmi.h
++++ b/include/linux/platform_data/x86/asus-wmi.h
+@@ -77,6 +77,8 @@
+ #define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011
+ #define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 /* deprecated */
+ #define ASUS_WMI_DEVID_CPU_FAN_CTRL 0x00110013
++#define ASUS_WMI_DEVID_CPU_FAN_CURVE 0x00110024
++#define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025
+
+ /* Power */
+ #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
+--
+2.31.1
+
diff --git a/sys-kernel_arch-sources-g14_files-9006-amd-c3-entry.patch b/sys-kernel_arch-sources-g14_files-9006-amd-c3-entry.patch
new file mode 100644
index 000000000000..98000fd7211f
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-9006-amd-c3-entry.patch
@@ -0,0 +1,38 @@
+AMD CPU which support C3 shares cache. Its not necessary to flush the
+caches in software before entering C3. This will cause performance drop
+for the cores which share some caches. ARB_DIS is not used with current
+AMD C state implementation. So set related flags correctly.
+
+Signed-off-by: Deepak Sharma <deepak.sharma@amd.com>
+---
+ arch/x86/kernel/acpi/cstate.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
+index 7de599eba7f0..62a5986d625a 100644
+--- a/arch/x86/kernel/acpi/cstate.c
++++ b/arch/x86/kernel/acpi/cstate.c
+@@ -79,6 +79,21 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
+ */
+ flags->bm_control = 0;
+ }
++ if (c->x86_vendor == X86_VENDOR_AMD) {
++ /*
++ * For all AMD CPUs that support C3, caches should not be
++ * flushed by software while entering C3 type state. Set
++ * bm->check to 1 so that kernel doesn't need to execute
++ * cache flush operation.
++ */
++ flags->bm_check = 1;
++ /*
++ * In current AMD C state implementation ARB_DIS is no longer
++ * used. So set bm_control to zero to indicate ARB_DIS is not
++ * required while entering C3 type state.
++ */
++ flags->bm_control = 0;
++ }
+ }
+ EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
+
+--
+2.25.1 \ No newline at end of file