adjustor 3.3.0__tar.gz → 3.4.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. {adjustor-3.3.0/src/adjustor.egg-info → adjustor-3.4.0}/PKG-INFO +51 -8
  2. {adjustor-3.3.0 → adjustor-3.4.0}/pyproject.toml +1 -1
  3. {adjustor-3.3.0 → adjustor-3.4.0}/readme.md +50 -7
  4. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/core/const.py +3 -2
  5. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/core/lenovo.py +38 -2
  6. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/amd/__init__.py +18 -3
  7. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/amd/settings.yml +6 -2
  8. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/asus/__init__.py +179 -79
  9. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/asus/settings.yml +47 -33
  10. adjustor-3.4.0/src/adjustor/drivers/general/__init__.py +146 -0
  11. adjustor-3.4.0/src/adjustor/drivers/general/settings.yml +27 -0
  12. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/lenovo/__init__.py +27 -2
  13. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/lenovo/settings.yml +21 -6
  14. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/hhd.py +7 -4
  15. {adjustor-3.3.0 → adjustor-3.4.0/src/adjustor.egg-info}/PKG-INFO +51 -8
  16. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor.egg-info/SOURCES.txt +2 -0
  17. {adjustor-3.3.0 → adjustor-3.4.0}/LICENSE +0 -0
  18. {adjustor-3.3.0 → adjustor-3.4.0}/MANIFEST.in +0 -0
  19. {adjustor-3.3.0 → adjustor-3.4.0}/setup.cfg +0 -0
  20. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/__init__.py +0 -0
  21. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/__main__.py +0 -0
  22. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/core/__init__.py +0 -0
  23. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/core/acpi.py +0 -0
  24. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/core/alib.py +0 -0
  25. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/core/platform.py +0 -0
  26. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/__init__.py +0 -0
  27. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/amd/power-profiles-daemon.dbus.xml.in +0 -0
  28. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/amd/ppd.py +0 -0
  29. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/smu/__init__.py +0 -0
  30. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/smu/qam.yml +0 -0
  31. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/drivers/smu/smu.yml +0 -0
  32. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/events.py +0 -0
  33. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/fuse/__init__.py +0 -0
  34. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/fuse/driver.py +0 -0
  35. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/fuse/gpu.py +0 -0
  36. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/fuse/utils.py +0 -0
  37. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/i18n.py +0 -0
  38. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor/settings.yml +0 -0
  39. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor.egg-info/dependency_links.txt +0 -0
  40. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor.egg-info/entry_points.txt +0 -0
  41. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor.egg-info/requires.txt +0 -0
  42. {adjustor-3.3.0 → adjustor-3.4.0}/src/adjustor.egg-info/top_level.txt +0 -0
  43. {adjustor-3.3.0 → adjustor-3.4.0}/usr/share/dbus-1/system.d/hhd-net.hadess.PowerProfiles.conf +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: adjustor
3
- Version: 3.3.0
3
+ Version: 3.4.0
4
4
  Summary: Adjustor, a userspace program for managing the TDP of handheld devices.
5
5
  Author-email: Kapenekakis Antheas <pypi@antheas.dev>
6
6
  Project-URL: Homepage, https://github.com/hhd-dev/adjustor
@@ -38,7 +38,7 @@ except intel handhelds and older prior to 6XXX AMD handhelds.
38
38
  ## TDP Control
39
39
  For the ROG Ally, Ally X and Legion Go that have an ACPI/EC implementation for
40
40
  bios and fan curves,
41
- Adjustor uses the manufactuer functions for setting TDP.
41
+ Adjustor uses the manufacturer functions for setting TDP.
42
42
  For the Allys, the asus-wmi kernel driver is used to set the tdp and manage the
43
43
  fan curves.
44
44
  For the Go, Lenovo's WMI methods are called through `acpi_call`, which will hopefully
@@ -53,14 +53,14 @@ For more, see [AMD TDP Control Details](#amd-tdp).
53
53
  In all cases, there are checks to ensure that the TDP is within the safe range
54
54
  of the processors.
55
55
 
56
- ## Energy Management
57
- Adjustor can also manage the energy profile of the processor, by setting EPP
56
+ ## Energy Management in Handhelds
57
+ Adjustor can also manage the energy profile of the processor in handhelds, by setting EPP
58
58
  and proper frequency values.
59
59
  After we transitioned people away from Decky plugins (which had some governor controls)
60
60
  to using Handheld Daemon for TDP, we found that Power Profiles Daemon (PPD)
61
61
  would use aggressive CPU values.
62
62
  These values are optimized for devices that have a dedicated power budget for the CPU
63
- (e.g., laptops, desktops), which caused issues with handhelds.
63
+ (e.g., laptops, desktops), which causes undesirable behavior handhelds.
64
64
 
65
65
  For example, the balanced PPD profile would set EPP to balance_performance and
66
66
  enable CPU boost, which would increase the draw of the CPU during gaming by 2W
@@ -91,6 +91,48 @@ TDP range instead of CPU values (which is the user's expectation).
91
91
  Of course, depending on TDP and user preference, the CPU governor values will be set
92
92
  accordingly.
93
93
 
94
+ ## Energy Management in other computers
95
+ As we design Handheld Daemon to be enabled in more Deck style devices (e.g., HTPCs),
96
+ these devices have different power requirements and processors (e.g., Intel), which
97
+ are better managed with Power Profiles Daemon.
98
+ It is the aim of the Handheld Daemon project to become a general Deck style session
99
+ manager for anything gamescope related, with useful features for all devices.
100
+
101
+ In these cases, starting with 3.4, for devices that are not in the CPU/device
102
+ whitelist (includes only AMD U series APUs and handhelds), Adjustor contains a
103
+ general energy management plugin that allows for switching the PPD power profile
104
+ from game mode.
105
+ In addition, it supports [sched_ext schedulers](#sched_ext).
106
+
107
+ This means that for general devices, Handheld Daemon uses PPD, and for handhelds,
108
+ Handheld Daemon becomes PPD.
109
+ This can be confusing for distribution maintainers and users, as they can and
110
+ should install both (e.g., Adjustor uses the Power Profile Daemon polkits).
111
+
112
+ In any case, Adjustor will never break/conflict with PPD and contains helpful
113
+ messages about disabling PPD in case the optimized handheld plugin is loaded.
114
+ For distribution maintainers that ship both and want Handheld Daemon to work
115
+ without user intervention, the environment variable `HHD_PPD_MASK` is provided.
116
+ If and only if it is set e.g., by using a systemd service extension, Handheld Daemon
117
+ will mask and disable PPD if optimized energy management is supported and enabled (e.g., for handhelds).
118
+ If the general plugin is loaded, it will unmask PPD during startup.
119
+ This means that Power Management will work properly for all devices without manual
120
+ intervention or whitelisting by distribution maintainers.
121
+
122
+ ## Sched_ext<a name="sched-ext"></a>
123
+ Starting with version 3.3, Adjustor can attach sched_ext schedulers to the
124
+ kernel if those are supported and installed.
125
+ Adjustor manages the lifetime of the scheduler, including launching and attaching
126
+ it, without using a systemd service, and is fully responsive to quirk scheduler
127
+ switches.
128
+
129
+ Schedulers are whitelisted in a case by case basis, with LAVD, rusty, and bpfland
130
+ being supported in the current version (the `scx_` namespace is crowded with e.g.,
131
+ test schedulers).
132
+ Of course, only installed schedulers are shown if and only if the kernel supports
133
+ them.
134
+ Get in touch to add your favorite scheduler, as it is a single line change.
135
+
94
136
  ## AMD TDP Control Details<a name="amd-tdp"></a>
95
137
  Adjustor controls TDP through the Dynamic Power and Thermal Configuration Interface
96
138
  of AMD, which exposes a superset of the parameters that can be currently found in
@@ -99,7 +141,7 @@ This vendor interface is part of the ACPI ASL library, and provided through the
99
141
  ALIB method 0x0C.
100
142
  The underlying implementation of the interface is SMU calls.
101
143
  This means that as long as the kernel module `acpi_call` is loaded, Adjustor
102
- can control TDP in an equivalent way to [RyzenAdj](https://github.dev/FlyGoat/RyzenAdj/).
144
+ can control TDP in a similar way to [RyzenAdj](https://github.dev/FlyGoat/RyzenAdj/).
103
145
 
104
146
  The ABI of this vendor function (as it is provided to manufacturers) can be
105
147
  considered mostly stable, so little work is needed between subsequent
@@ -109,8 +151,9 @@ Of course, support for processors is only added after the ACPI bindings have
109
151
  been reviewed, to avoid surprises.
110
152
  Both the Ally and Legion Go use this function, in the exact same way, so setting
111
153
  TDP with it is very stable, and we have had no reported crashes.
112
- It should not be used (and is not used) with those devices, however, as the
113
- manufacturer functions will interfere.
154
+ It can not be used and is not used with those devices, however, as the
155
+ manufacturer functions would interfere and provide a better user experience,
156
+ such as setting appropriate fan curves and changing the power light color on the Legion Go.
114
157
 
115
158
  Unfortunately for devices that do have an ACPI/EC implementation for TDP, there
116
159
  is no official way of setting TDP on demand, either on Linux or Windows, with
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "adjustor"
3
- version = "3.3.0"
3
+ version = "3.4.0"
4
4
  authors = [
5
5
  { name="Kapenekakis Antheas", email="pypi@antheas.dev" },
6
6
  ]
@@ -17,7 +17,7 @@ except intel handhelds and older prior to 6XXX AMD handhelds.
17
17
  ## TDP Control
18
18
  For the ROG Ally, Ally X and Legion Go that have an ACPI/EC implementation for
19
19
  bios and fan curves,
20
- Adjustor uses the manufactuer functions for setting TDP.
20
+ Adjustor uses the manufacturer functions for setting TDP.
21
21
  For the Allys, the asus-wmi kernel driver is used to set the tdp and manage the
22
22
  fan curves.
23
23
  For the Go, Lenovo's WMI methods are called through `acpi_call`, which will hopefully
@@ -32,14 +32,14 @@ For more, see [AMD TDP Control Details](#amd-tdp).
32
32
  In all cases, there are checks to ensure that the TDP is within the safe range
33
33
  of the processors.
34
34
 
35
- ## Energy Management
36
- Adjustor can also manage the energy profile of the processor, by setting EPP
35
+ ## Energy Management in Handhelds
36
+ Adjustor can also manage the energy profile of the processor in handhelds, by setting EPP
37
37
  and proper frequency values.
38
38
  After we transitioned people away from Decky plugins (which had some governor controls)
39
39
  to using Handheld Daemon for TDP, we found that Power Profiles Daemon (PPD)
40
40
  would use aggressive CPU values.
41
41
  These values are optimized for devices that have a dedicated power budget for the CPU
42
- (e.g., laptops, desktops), which caused issues with handhelds.
42
+ (e.g., laptops, desktops), which causes undesirable behavior handhelds.
43
43
 
44
44
  For example, the balanced PPD profile would set EPP to balance_performance and
45
45
  enable CPU boost, which would increase the draw of the CPU during gaming by 2W
@@ -70,6 +70,48 @@ TDP range instead of CPU values (which is the user's expectation).
70
70
  Of course, depending on TDP and user preference, the CPU governor values will be set
71
71
  accordingly.
72
72
 
73
+ ## Energy Management in other computers
74
+ As we design Handheld Daemon to be enabled in more Deck style devices (e.g., HTPCs),
75
+ these devices have different power requirements and processors (e.g., Intel), which
76
+ are better managed with Power Profiles Daemon.
77
+ It is the aim of the Handheld Daemon project to become a general Deck style session
78
+ manager for anything gamescope related, with useful features for all devices.
79
+
80
+ In these cases, starting with 3.4, for devices that are not in the CPU/device
81
+ whitelist (includes only AMD U series APUs and handhelds), Adjustor contains a
82
+ general energy management plugin that allows for switching the PPD power profile
83
+ from game mode.
84
+ In addition, it supports [sched_ext schedulers](#sched_ext).
85
+
86
+ This means that for general devices, Handheld Daemon uses PPD, and for handhelds,
87
+ Handheld Daemon becomes PPD.
88
+ This can be confusing for distribution maintainers and users, as they can and
89
+ should install both (e.g., Adjustor uses the Power Profile Daemon polkits).
90
+
91
+ In any case, Adjustor will never break/conflict with PPD and contains helpful
92
+ messages about disabling PPD in case the optimized handheld plugin is loaded.
93
+ For distribution maintainers that ship both and want Handheld Daemon to work
94
+ without user intervention, the environment variable `HHD_PPD_MASK` is provided.
95
+ If and only if it is set e.g., by using a systemd service extension, Handheld Daemon
96
+ will mask and disable PPD if optimized energy management is supported and enabled (e.g., for handhelds).
97
+ If the general plugin is loaded, it will unmask PPD during startup.
98
+ This means that Power Management will work properly for all devices without manual
99
+ intervention or whitelisting by distribution maintainers.
100
+
101
+ ## Sched_ext<a name="sched-ext"></a>
102
+ Starting with version 3.3, Adjustor can attach sched_ext schedulers to the
103
+ kernel if those are supported and installed.
104
+ Adjustor manages the lifetime of the scheduler, including launching and attaching
105
+ it, without using a systemd service, and is fully responsive to quirk scheduler
106
+ switches.
107
+
108
+ Schedulers are whitelisted in a case by case basis, with LAVD, rusty, and bpfland
109
+ being supported in the current version (the `scx_` namespace is crowded with e.g.,
110
+ test schedulers).
111
+ Of course, only installed schedulers are shown if and only if the kernel supports
112
+ them.
113
+ Get in touch to add your favorite scheduler, as it is a single line change.
114
+
73
115
  ## AMD TDP Control Details<a name="amd-tdp"></a>
74
116
  Adjustor controls TDP through the Dynamic Power and Thermal Configuration Interface
75
117
  of AMD, which exposes a superset of the parameters that can be currently found in
@@ -78,7 +120,7 @@ This vendor interface is part of the ACPI ASL library, and provided through the
78
120
  ALIB method 0x0C.
79
121
  The underlying implementation of the interface is SMU calls.
80
122
  This means that as long as the kernel module `acpi_call` is loaded, Adjustor
81
- can control TDP in an equivalent way to [RyzenAdj](https://github.dev/FlyGoat/RyzenAdj/).
123
+ can control TDP in a similar way to [RyzenAdj](https://github.dev/FlyGoat/RyzenAdj/).
82
124
 
83
125
  The ABI of this vendor function (as it is provided to manufacturers) can be
84
126
  considered mostly stable, so little work is needed between subsequent
@@ -88,8 +130,9 @@ Of course, support for processors is only added after the ACPI bindings have
88
130
  been reviewed, to avoid surprises.
89
131
  Both the Ally and Legion Go use this function, in the exact same way, so setting
90
132
  TDP with it is very stable, and we have had no reported crashes.
91
- It should not be used (and is not used) with those devices, however, as the
92
- manufacturer functions will interfere.
133
+ It can not be used and is not used with those devices, however, as the
134
+ manufacturer functions would interfere and provide a better user experience,
135
+ such as setting appropriate fan curves and changing the power light color on the Legion Go.
93
136
 
94
137
  Unfortunately for devices that do have an ACPI/EC implementation for TDP, there
95
138
  is no official way of setting TDP on demand, either on Linux or Windows, with
@@ -41,7 +41,7 @@ DEV_PARAMS_7040: dict[str, DeviceParams] = {
41
41
  "temp_target": D(60, 70, 85, 90, 100),
42
42
  }
43
43
 
44
- DEV_PARAMS_NEO: dict[str, DeviceParams] = {
44
+ DEV_PARAMS_28W: dict[str, DeviceParams] = {
45
45
  "stapm_limit": D(0, 4, 15, 28, 35),
46
46
  "skin_limit": D(0, 4, 15, 28, 35),
47
47
  "slow_limit": D(0, 4, 20, 32, 37),
@@ -58,7 +58,8 @@ DEV_PARAMS_8040: dict[str, DeviceParams] = DEV_PARAMS_7040
58
58
  DEV_PARAMS_LEGO = DEV_PARAMS_7040
59
59
 
60
60
  DEV_DATA: dict[str, tuple[dict[str, DeviceParams], dict[str, AlibParams], bool]] = {
61
- "NEO-01": (DEV_PARAMS_NEO, ALIB_PARAMS_7040, False),
61
+ "NEO-01": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False),
62
+ "V3": (DEV_PARAMS_28W, ALIB_PARAMS_8040, False),
62
63
  "83E1": (DEV_PARAMS_LEGO, ALIB_PARAMS_7040, False),
63
64
  }
64
65
 
@@ -104,12 +104,12 @@ def set_fan_curve(arr: Sequence[int], lim: Sequence[int] | None = None):
104
104
  )
105
105
 
106
106
 
107
- def set_power_light(enabled: bool):
107
+ def set_power_light_v1(enabled: bool):
108
108
  logger.debug(f"Setting power light status.")
109
109
  return call(r"\_SB.GZFD.WMAF", [0, 0x02, bytes([0x03, int(enabled), 0x00])])
110
110
 
111
111
 
112
- def get_power_light():
112
+ def get_power_light_v1():
113
113
  logger.debug(f"Getting power light status.")
114
114
  if not call(r"\_SB.GZFD.WMAF", [0, 0x01, 0x03], risky=False):
115
115
  return None
@@ -119,6 +119,42 @@ def get_power_light():
119
119
  return None
120
120
 
121
121
 
122
+ def set_power_light(enabled: bool, suspend: bool = False):
123
+ logger.debug(f"Setting power light status.")
124
+ if enabled:
125
+ if suspend:
126
+ cb = 0x03
127
+ else:
128
+ cb = 0x02
129
+ else:
130
+ cb = 0x01
131
+ return call(
132
+ r"\_SB.GZFD.WMAF",
133
+ [0, 0x02, bytes([0x024 if suspend else 0x04, 0x00, cb])],
134
+ )
135
+
136
+
137
+ def get_power_light(suspend: bool = False):
138
+ logger.debug(f"Getting power light status.")
139
+ if not call(r"\_SB.GZFD.WMAF", [0, 0x01, 0x024 if suspend else 0x04], risky=False):
140
+ return None
141
+ o = read()
142
+ if isinstance(o, bytes) and len(o) == 2:
143
+ return o[1] == (0x03 if suspend else 0x02)
144
+ return None
145
+
146
+
147
+ def get_bios_version():
148
+ raw = None
149
+ try:
150
+ with open("/sys/class/dmi/id/bios_version") as f:
151
+ raw = f.read()
152
+ return int(raw.replace("N3CN", "").split("WW")[0].strip())
153
+ except Exception as e:
154
+ logger.error(f"Failed to get BIOS version from '{raw}' with error:\n{e}")
155
+ return 1
156
+
157
+
122
158
  def get_feature(id: int):
123
159
  if not call(
124
160
  r"\_SB.GZFD.WMAE",
@@ -24,7 +24,7 @@ from adjustor.fuse.gpu import (
24
24
 
25
25
  logger = logging.getLogger(__name__)
26
26
 
27
- APPLY_DELAY = 0.5
27
+ APPLY_DELAY = 0.2
28
28
 
29
29
 
30
30
  def _ppd_client(emit, proc):
@@ -126,14 +126,29 @@ class AmdGPUPlugin(HHDPlugin):
126
126
  ]
127
127
  )
128
128
  for line in out.decode().splitlines():
129
- if "not-found" in line.lower():
129
+ line = line.lower()
130
+ if "masked" in line:
130
131
  continue
131
- if "power-profiles-daemon" in line or "tuned" in line.lower():
132
+ if "not-found" in line:
133
+ continue
134
+ if "inactive" in line:
135
+ continue
136
+ if "power-profiles-daemon" in line or "tuned" in line:
132
137
  self.ppd_conflict = True
133
138
  break
134
139
  except Exception as e:
135
140
  logger.error(f"Failed to check for PPD conflict:\n{e}")
136
141
 
142
+ if self.ppd_conflict and os.environ.get("HHD_PPD_MASK", None):
143
+ logger.warning(
144
+ "PPD conflict detected but HHD_PPD_MASK is set. Masking PPD."
145
+ )
146
+ # Mask and disable
147
+ os.system("systemctl mask power-profiles-daemon.service")
148
+ os.system("systemctl disable --now power-profiles-daemon.service")
149
+ # Keep going without check to avoid obscure errors
150
+ self.ppd_conflict = False
151
+
137
152
  if self.ppd_conflict:
138
153
  self.initialized = False
139
154
  return {
@@ -46,6 +46,11 @@ enabled:
46
46
  options:
47
47
  min: 400MHz
48
48
  nonlinear: 1GHz
49
+ hint: >-
50
+ Sets the minimum frequency for the CPU.
51
+ Using 400MHz will save battery in light games.
52
+ However, the delay of increasing the frequency
53
+ may cause minor stutters, especially in VRR displays.
49
54
  cpu_boost:
50
55
  type: multiple
51
56
  title: CPU Boost
@@ -92,8 +97,7 @@ enabled:
92
97
  title: Custom Scheduler
93
98
  hint: >-
94
99
  Allows attaching a scheduler to the kernel sched_ext.
95
- Schedulers need to be installed.
96
- "Kernel" .
100
+ Schedulers need to be installed and kernel needs to support sched_ext.
97
101
  options:
98
102
  disabled: Disabled
99
103
  scx_lavd: LAVD