adjustor 3.5.4__tar.gz → 3.6.1__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {adjustor-3.5.4/src/adjustor.egg-info → adjustor-3.6.1}/PKG-INFO +1 -1
- {adjustor-3.5.4 → adjustor-3.6.1}/pyproject.toml +1 -1
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/const.py +1 -0
- adjustor-3.6.1/src/adjustor/core/fan/__init__.py +1 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/fan/alg.py +2 -3
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/fan/core.py +45 -6
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/asus/__init__.py +22 -13
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/general/__init__.py +8 -5
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/smu/__init__.py +123 -5
- adjustor-3.6.1/src/adjustor/drivers/smu/qam.yml +80 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/settings.yml +1 -4
- {adjustor-3.5.4 → adjustor-3.6.1/src/adjustor.egg-info}/PKG-INFO +1 -1
- adjustor-3.5.4/src/adjustor/drivers/__init__.py +0 -0
- adjustor-3.5.4/src/adjustor/drivers/smu/qam.yml +0 -21
- {adjustor-3.5.4 → adjustor-3.6.1}/LICENSE +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/MANIFEST.in +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/readme.md +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/setup.cfg +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/__init__.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/__main__.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/__init__.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/acpi.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/alib.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/fan/__main__.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/fan/utils.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/lenovo.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/core/platform.py +0 -0
- {adjustor-3.5.4/src/adjustor/core/fan → adjustor-3.6.1/src/adjustor/drivers}/__init__.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/amd/__init__.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/amd/power-profiles-daemon.dbus.xml.in +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/amd/ppd.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/amd/settings.yml +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/asus/settings.yml +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/general/settings.yml +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/lenovo/__init__.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/lenovo/settings.yml +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/smu/smu.yml +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/events.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/fuse/__init__.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/fuse/driver.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/fuse/gpu.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/fuse/utils.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/hhd.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/i18n.py +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor.egg-info/SOURCES.txt +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor.egg-info/dependency_links.txt +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor.egg-info/entry_points.txt +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor.egg-info/requires.txt +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor.egg-info/top_level.txt +0 -0
- {adjustor-3.5.4 → adjustor-3.6.1}/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
|
+
Version: 3.6.1
|
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
|
@@ -120,4 +120,5 @@ CPU_DATA: dict[str, tuple[dict[str, DeviceParams], dict[str, AlibParams]]] = {
|
|
120
120
|
"AMD Ryzen 7 8840U": (DEV_PARAMS_8040, ALIB_PARAMS_8040),
|
121
121
|
# AMD Athlon Silver 3050e (Win600, will it support tdp?)
|
122
122
|
"AMD Ryzen AI 9 HX 370": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370),
|
123
|
+
"AMD Ryzen AI HX 360": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370),
|
123
124
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
from .core import get_fan_info, fan_worker
|
@@ -34,7 +34,6 @@ UPDATE_FREQUENCY = 5
|
|
34
34
|
UPDATE_T = 1 / UPDATE_FREQUENCY
|
35
35
|
SETPOINT_UPDATE_FREQUENCY = 1
|
36
36
|
SETPOINT_UPDATE_T = 1 / SETPOINT_UPDATE_FREQUENCY
|
37
|
-
HYSTERESIS_RATIO = 0.25
|
38
37
|
|
39
38
|
|
40
39
|
def _calculate_jerk(speed_span, decel_ratio, freq, time):
|
@@ -133,12 +132,12 @@ def update_setpoint(temp: float, curr: int, fan_curve: dict[int, float]):
|
|
133
132
|
# Add some hysterisis to avoid dithering
|
134
133
|
if idx > 0:
|
135
134
|
prev = targets[idx - 1]
|
136
|
-
if temp < prev
|
135
|
+
if temp < prev:
|
137
136
|
return prev
|
138
137
|
|
139
138
|
if idx < len(targets) - 1:
|
140
139
|
next = targets[idx + 1]
|
141
|
-
if temp > next
|
140
|
+
if temp > next:
|
142
141
|
return next
|
143
142
|
|
144
143
|
return curr
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
import time
|
3
3
|
from typing import TypedDict
|
4
|
+
from threading import Lock, Event
|
4
5
|
|
5
6
|
from .alg import (
|
6
7
|
SETPOINT_UPDATE_T,
|
@@ -40,10 +41,12 @@ class FanState(TypedDict):
|
|
40
41
|
v_curr: float
|
41
42
|
v_target: float
|
42
43
|
v_target_pwm: int
|
44
|
+
t_target: int
|
43
45
|
v_rpm: list[int]
|
44
46
|
t_junction: float
|
45
47
|
t_edge: float
|
46
48
|
fan_data: FanData
|
49
|
+
in_setpoint: bool
|
47
50
|
|
48
51
|
|
49
52
|
def get_fan_info() -> FanInfo | None:
|
@@ -131,11 +134,37 @@ def update_fan_speed(
|
|
131
134
|
"v_rpm": fan_speeds,
|
132
135
|
"t_junction": t_junction,
|
133
136
|
"t_edge": t_edge,
|
137
|
+
"t_target": data["t_target"],
|
134
138
|
"fan_data": data,
|
139
|
+
"in_setpoint": in_setpoint,
|
135
140
|
},
|
136
141
|
)
|
137
142
|
|
138
143
|
|
144
|
+
def fan_worker(
|
145
|
+
info: FanInfo,
|
146
|
+
should_exit: Event,
|
147
|
+
lock: Lock,
|
148
|
+
fan_curve: dict[int, float],
|
149
|
+
state: FanState,
|
150
|
+
junction: Event,
|
151
|
+
):
|
152
|
+
try:
|
153
|
+
set_fans_to_pwm(True, info)
|
154
|
+
while not should_exit.is_set():
|
155
|
+
with lock:
|
156
|
+
state_tmp = state or None # First time state will be empty
|
157
|
+
in_setpoint, state_tmp = update_fan_speed(
|
158
|
+
state_tmp, info, fan_curve, junction.is_set()
|
159
|
+
)
|
160
|
+
state.update(state_tmp)
|
161
|
+
time.sleep(SETPOINT_UPDATE_T if in_setpoint else UPDATE_T)
|
162
|
+
except Exception as e:
|
163
|
+
logger.error(f"Fan worker failed:\n{e}")
|
164
|
+
finally:
|
165
|
+
set_fans_to_pwm(False, info)
|
166
|
+
|
167
|
+
|
139
168
|
def fan_pwm_tester(normal_curve: bool = True, observe_only: bool = False):
|
140
169
|
fan_info = get_fan_info()
|
141
170
|
if fan_info is None:
|
@@ -181,12 +210,22 @@ def fan_pwm_tester(normal_curve: bool = True, observe_only: bool = False):
|
|
181
210
|
|
182
211
|
state = None
|
183
212
|
for i in range(10000000):
|
184
|
-
in_setpoint, state = update_fan_speed(
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
print(
|
189
|
-
|
213
|
+
in_setpoint, state = update_fan_speed(
|
214
|
+
state, fan_info, fan_curve, False, observe_only=observe_only
|
215
|
+
)
|
216
|
+
|
217
|
+
print(
|
218
|
+
f"\n> {i:05d}: {'in setpoint' if in_setpoint else 'updating'}{' (observe)' if observe_only else ''}"
|
219
|
+
)
|
220
|
+
print(
|
221
|
+
f" Junction: {state['t_junction']:.2f}C, Edge: {state['t_edge']:.2f}C"
|
222
|
+
)
|
223
|
+
print(
|
224
|
+
f" Current: {state['v_curr']*100:.1f}%, Target: {state['v_target']*100:.1f}%"
|
225
|
+
)
|
226
|
+
print(
|
227
|
+
f" Fan speeds: {' '.join(map(lambda rpm: f"{rpm:4d}rpm/{MAX_FAN}rpm ({100*rpm/MAX_FAN:.1f}%)", state['v_rpm']))}"
|
228
|
+
)
|
190
229
|
time.sleep(SETPOINT_UPDATE_T if in_setpoint else UPDATE_T)
|
191
230
|
except KeyboardInterrupt:
|
192
231
|
print("Exiting fan test.")
|
@@ -169,7 +169,9 @@ class AsusDriverPlugin(HHDPlugin):
|
|
169
169
|
path_exists = os.path.exists(EXTREME_FN)
|
170
170
|
extreme_supported = EXTREME_ENABLE and path_exists
|
171
171
|
if self.extreme_supported is None:
|
172
|
-
logger.info(
|
172
|
+
logger.info(
|
173
|
+
f"Extreme standby enabled: {EXTREME_ENABLE}, file exists: {extreme_supported}. Enabled: {extreme_supported}"
|
174
|
+
)
|
173
175
|
self.extreme_supported = extreme_supported
|
174
176
|
if not self.extreme_supported:
|
175
177
|
del out["tdp"]["asus"]["children"]["extreme_standby"]
|
@@ -177,21 +179,25 @@ class AsusDriverPlugin(HHDPlugin):
|
|
177
179
|
# Set units
|
178
180
|
if self.allyx:
|
179
181
|
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["quiet"]["unit"] = "13W"
|
180
|
-
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["balanced"][
|
182
|
+
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["balanced"][
|
183
|
+
"unit"
|
184
|
+
] = "17W"
|
181
185
|
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["performance"][
|
182
186
|
"unit"
|
183
187
|
] = "25/30W"
|
184
188
|
else:
|
185
189
|
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["quiet"]["unit"] = "10W"
|
186
|
-
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["balanced"][
|
190
|
+
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["balanced"][
|
191
|
+
"unit"
|
192
|
+
] = "15W"
|
187
193
|
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["performance"][
|
188
194
|
"unit"
|
189
195
|
] = "25/30W"
|
190
196
|
|
191
197
|
if not self.enforce_limits:
|
192
|
-
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["custom"]["children"][
|
193
|
-
"
|
194
|
-
] = 50
|
198
|
+
out["tdp"]["asus"]["children"]["tdp_v2"]["modes"]["custom"]["children"][
|
199
|
+
"tdp"
|
200
|
+
]["max"] = 50
|
195
201
|
return out
|
196
202
|
|
197
203
|
def open(
|
@@ -298,6 +304,7 @@ class AsusDriverPlugin(HHDPlugin):
|
|
298
304
|
new_target = "performance"
|
299
305
|
|
300
306
|
# In custom mode, re-apply settings with debounce
|
307
|
+
tdp_set = False
|
301
308
|
if mode == "custom":
|
302
309
|
# Check user changed values
|
303
310
|
if new_tdp:
|
@@ -410,7 +417,7 @@ class AsusDriverPlugin(HHDPlugin):
|
|
410
417
|
|
411
418
|
# Check if fan curve has changed
|
412
419
|
# Use debounce logic on these changes
|
413
|
-
if tdp_reset and manual_fan_curve:
|
420
|
+
if ((tdp_reset and mode != "custom") or tdp_set) and manual_fan_curve:
|
414
421
|
self.queue_fan = curr + APPLY_DELAY
|
415
422
|
|
416
423
|
for i in POINTS:
|
@@ -431,7 +438,7 @@ class AsusDriverPlugin(HHDPlugin):
|
|
431
438
|
self.queue_tdp = curr + APPLY_DELAY
|
432
439
|
|
433
440
|
apply_curve = self.queue_fan and self.queue_fan < curr
|
434
|
-
if apply_curve:
|
441
|
+
if apply_curve or tdp_set:
|
435
442
|
try:
|
436
443
|
if conf["tdp.asus.fan.mode"].to(str) == "manual":
|
437
444
|
set_fan_curve(
|
@@ -475,7 +482,7 @@ class AsusDriverPlugin(HHDPlugin):
|
|
475
482
|
with open(EXTREME_FN, "r") as f:
|
476
483
|
cval = f.read().strip() == "1"
|
477
484
|
if nval != cval:
|
478
|
-
logger.info
|
485
|
+
logger.info(f"Setting extreme standby to '{standby}'")
|
479
486
|
with open(EXTREME_FN, "w") as f:
|
480
487
|
f.write("1" if standby == "enabled" else "0")
|
481
488
|
else:
|
@@ -487,7 +494,7 @@ class AsusDriverPlugin(HHDPlugin):
|
|
487
494
|
for ev in events:
|
488
495
|
if ev["type"] == "tdp":
|
489
496
|
self.new_tdp = ev["tdp"]
|
490
|
-
self.sys_tdp = ev[
|
497
|
+
self.sys_tdp = ev["tdp"] is not None
|
491
498
|
elif ev["type"] == "ppd":
|
492
499
|
match ev["status"]:
|
493
500
|
case "power":
|
@@ -496,10 +503,12 @@ class AsusDriverPlugin(HHDPlugin):
|
|
496
503
|
self.new_mode = "balanced"
|
497
504
|
case "performance":
|
498
505
|
self.new_mode = "performance"
|
499
|
-
elif ev[
|
500
|
-
logger.info(
|
506
|
+
elif ev["type"] == "special" and ev.get("event", None) == "wakeup":
|
507
|
+
logger.info(
|
508
|
+
f"Waking up from sleep, resetting TDP after {SLEEP_DELAY} seconds."
|
509
|
+
)
|
501
510
|
self.queue_tdp = time.time() + SLEEP_DELAY
|
502
|
-
elif self.cycle_tdp and ev[
|
511
|
+
elif self.cycle_tdp and ev["type"] == "special" and ev["event"] == "xbox_y":
|
503
512
|
match self.mode:
|
504
513
|
case "quiet":
|
505
514
|
self.new_mode = "balanced"
|
@@ -32,6 +32,7 @@ class GeneralPowerPlugin(HHDPlugin):
|
|
32
32
|
self.ovr_enabled = False
|
33
33
|
self.should_exit = Event()
|
34
34
|
self.t_sys = None
|
35
|
+
self.currentTarget = None
|
35
36
|
|
36
37
|
def settings(self):
|
37
38
|
sets = load_relative_yaml("./settings.yml")
|
@@ -151,10 +152,11 @@ class GeneralPowerPlugin(HHDPlugin):
|
|
151
152
|
"balanced": "balanced",
|
152
153
|
"performance": "throughput-performance"
|
153
154
|
}
|
155
|
+
|
154
156
|
new_profile = ppd_tuned_mapping.get(conf.get("tdp.general.profile", self.target))
|
155
|
-
if new_profile != self.
|
156
|
-
logger.info(f"Setting TuneD profile to '{new_profile}'")
|
157
|
-
self.
|
157
|
+
if new_profile != self.currentTarget and new_profile and self.currentTarget:
|
158
|
+
logger.info(f"Setting TuneD profile to '{new_profile}' from '{self.target}'")
|
159
|
+
self.currentTarget = new_profile
|
158
160
|
try:
|
159
161
|
subprocess.run(
|
160
162
|
[shutil.which('tuned-adm'), "profile", new_profile],
|
@@ -162,6 +164,7 @@ class GeneralPowerPlugin(HHDPlugin):
|
|
162
164
|
stdout=subprocess.PIPE,
|
163
165
|
stderr=subprocess.PIPE,
|
164
166
|
)
|
167
|
+
|
165
168
|
except Exception as e:
|
166
169
|
self.tuned_supported = False
|
167
170
|
logger.warning(f"tuned-adm returned with error:\n{e}")
|
@@ -176,13 +179,13 @@ class GeneralPowerPlugin(HHDPlugin):
|
|
176
179
|
stdout=subprocess.PIPE,
|
177
180
|
stderr=subprocess.PIPE,
|
178
181
|
)
|
179
|
-
|
180
182
|
tuned_ppd_mapping = {
|
181
183
|
"powersave": "power-saver",
|
182
184
|
"balanced": "balanced",
|
183
185
|
"throughput-performance": "performance"
|
184
186
|
}
|
185
|
-
self.
|
187
|
+
self.currentTarget = res.stdout.decode().split(":")[1].strip()
|
188
|
+
self.target = tuned_ppd_mapping.get(self.currentTarget) # type: ignore
|
186
189
|
|
187
190
|
if self.target != conf["tdp.general.profile"].to(str):
|
188
191
|
conf["tdp.general.profile"] = self.target
|
@@ -1,11 +1,13 @@
|
|
1
1
|
import logging
|
2
2
|
import time
|
3
|
+
from threading import Event as TEvent, Lock, Thread
|
3
4
|
from typing import Sequence
|
4
5
|
|
5
6
|
from hhd.plugins import Context, Event, HHDPlugin, load_relative_yaml
|
6
7
|
from hhd.plugins.conf import Config
|
7
8
|
|
8
9
|
from adjustor.core.alib import AlibParams, DeviceParams, alib
|
10
|
+
from adjustor.core.fan import fan_worker, get_fan_info
|
9
11
|
from adjustor.core.platform import get_platform_choices, set_platform_profile
|
10
12
|
from adjustor.i18n import _
|
11
13
|
|
@@ -15,6 +17,27 @@ PP_DELAY = 0.2
|
|
15
17
|
APPLY_DELAY = 1
|
16
18
|
SLEEP_DELAY = 4
|
17
19
|
|
20
|
+
DEFAULT_EDGE = {
|
21
|
+
40: 25,
|
22
|
+
45: 25,
|
23
|
+
50: 40,
|
24
|
+
55: 45,
|
25
|
+
60: 50,
|
26
|
+
65: 55,
|
27
|
+
70: 70,
|
28
|
+
80: 85,
|
29
|
+
90: 100,
|
30
|
+
}
|
31
|
+
DEFAULT_TCTL = {
|
32
|
+
40: 40,
|
33
|
+
50: 45,
|
34
|
+
60: 50,
|
35
|
+
70: 80,
|
36
|
+
80: 90,
|
37
|
+
90: 100,
|
38
|
+
100: 100,
|
39
|
+
}
|
40
|
+
|
18
41
|
|
19
42
|
class SmuQamPlugin(HHDPlugin):
|
20
43
|
|
@@ -44,6 +67,14 @@ class SmuQamPlugin(HHDPlugin):
|
|
44
67
|
self.is_set = False
|
45
68
|
self.lims = self.dev.get("skin_limit", self.dev.get("stapm_limit", None))
|
46
69
|
|
70
|
+
self.fan_info = None
|
71
|
+
self.fan_t = None
|
72
|
+
self.fan_should_exit = TEvent()
|
73
|
+
self.fan_junction = TEvent()
|
74
|
+
self.fan_lock = Lock()
|
75
|
+
self.fan_curve = {}
|
76
|
+
self.fan_state = {}
|
77
|
+
|
47
78
|
# Workaround for debugging on the legion go
|
48
79
|
# Avoids sending SMU commands that will conflict with Lenovo TDP on
|
49
80
|
# startup
|
@@ -87,6 +118,33 @@ class SmuQamPlugin(HHDPlugin):
|
|
87
118
|
{"min": dmin, "max": dmax, "default": default}
|
88
119
|
)
|
89
120
|
|
121
|
+
if not self.fan_info:
|
122
|
+
del out["tdp"]["qam"]["children"]["fan"]
|
123
|
+
else:
|
124
|
+
base = out["tdp"]["qam"]["children"]["fan"]["modes"]["manual_edge"][
|
125
|
+
"children"
|
126
|
+
]["st40"]
|
127
|
+
reset = out["tdp"]["qam"]["children"]["fan"]["modes"]["manual_edge"][
|
128
|
+
"children"
|
129
|
+
].pop("reset")
|
130
|
+
for k, v in DEFAULT_EDGE.items():
|
131
|
+
out["tdp"]["qam"]["children"]["fan"]["modes"]["manual_edge"][
|
132
|
+
"children"
|
133
|
+
][f"st{k}"] = {**base, "title": f"{k}C", "default": v}
|
134
|
+
out["tdp"]["qam"]["children"]["fan"]["modes"]["manual_edge"]["children"][
|
135
|
+
"reset"
|
136
|
+
] = reset
|
137
|
+
reset = out["tdp"]["qam"]["children"]["fan"]["modes"]["manual_junction"][
|
138
|
+
"children"
|
139
|
+
].pop("reset")
|
140
|
+
for k, v in DEFAULT_TCTL.items():
|
141
|
+
out["tdp"]["qam"]["children"]["fan"]["modes"]["manual_junction"][
|
142
|
+
"children"
|
143
|
+
][f"st{k}"] = {**base, "title": f"{k}C", "default": v}
|
144
|
+
out["tdp"]["qam"]["children"]["fan"]["modes"]["manual_junction"][
|
145
|
+
"children"
|
146
|
+
]["reset"] = reset
|
147
|
+
|
90
148
|
return out
|
91
149
|
|
92
150
|
def open(
|
@@ -95,6 +153,7 @@ class SmuQamPlugin(HHDPlugin):
|
|
95
153
|
context: Context,
|
96
154
|
):
|
97
155
|
self.emit = emit
|
156
|
+
self.fan_info = get_fan_info()
|
98
157
|
|
99
158
|
def update(self, conf: Config):
|
100
159
|
self.enabled = conf["hhd.settings.tdp_enable"].to(bool)
|
@@ -191,12 +250,65 @@ class SmuQamPlugin(HHDPlugin):
|
|
191
250
|
self.old_tdp = new_tdp
|
192
251
|
self.old_boost = new_boost
|
193
252
|
|
253
|
+
if self.fan_info:
|
254
|
+
mode = conf["tdp.qam.fan.mode"].to(str)
|
255
|
+
if mode != "disabled":
|
256
|
+
with self.fan_lock:
|
257
|
+
if conf[f"tdp.qam.fan.{mode}.reset"].to(bool):
|
258
|
+
conf[f"tdp.qam.fan.{mode}.reset"] = False
|
259
|
+
curve = DEFAULT_EDGE if "edge" in mode else DEFAULT_TCTL
|
260
|
+
for k, v in curve.items():
|
261
|
+
if f"tdp.qam.fan.{mode}.st{k}" in conf:
|
262
|
+
conf[f"tdp.qam.fan.{mode}.st{k}"] = v
|
263
|
+
|
264
|
+
for k, v in conf[f"tdp.qam.fan.{mode}"].to(dict).items():
|
265
|
+
if not k.startswith("st"):
|
266
|
+
continue
|
267
|
+
self.fan_curve[int(k[2:])] = v / 100
|
268
|
+
if self.fan_state:
|
269
|
+
s = self.fan_state
|
270
|
+
fan_speed = (
|
271
|
+
f"{s['v_curr']*100:.1f}% @ {s['t_target']}C"
|
272
|
+
if s["in_setpoint"]
|
273
|
+
else f"{s['v_curr']*100:.1f}% → {s['v_target']*100:.1f}%"
|
274
|
+
)
|
275
|
+
conf[f"tdp.qam.fan.{mode}.info"] = (
|
276
|
+
f"{fan_speed} ({', '.join(map(str, s['v_rpm']))} RPM)\n"
|
277
|
+
+ f"Tctl: {s['t_junction']:.2f}C, "
|
278
|
+
+ f"Edge: {s['t_edge']:.2f}C\n"
|
279
|
+
)
|
280
|
+
if "junction" in mode:
|
281
|
+
self.fan_junction.set()
|
282
|
+
else:
|
283
|
+
self.fan_junction.clear()
|
284
|
+
|
285
|
+
if not self.fan_t:
|
286
|
+
self.fan_should_exit.clear()
|
287
|
+
self.fan_t = Thread(
|
288
|
+
target=fan_worker,
|
289
|
+
args=(
|
290
|
+
self.fan_info,
|
291
|
+
self.fan_should_exit,
|
292
|
+
self.fan_lock,
|
293
|
+
self.fan_curve,
|
294
|
+
self.fan_state,
|
295
|
+
self.fan_junction,
|
296
|
+
),
|
297
|
+
)
|
298
|
+
self.fan_t.start()
|
299
|
+
else:
|
300
|
+
if self.fan_t:
|
301
|
+
self.fan_should_exit.set()
|
302
|
+
self.fan_t.join()
|
303
|
+
self.fan_t = None
|
304
|
+
self.fan_state = {}
|
305
|
+
|
194
306
|
def notify(self, events: Sequence[Event]):
|
195
307
|
for ev in events:
|
196
308
|
if ev["type"] == "tdp":
|
197
309
|
self.sys_tdp = True
|
198
310
|
self.new_tdp = ev["tdp"]
|
199
|
-
self.sys_tdp = ev[
|
311
|
+
self.sys_tdp = ev["tdp"] is not None
|
200
312
|
|
201
313
|
if ev["type"] == "ppd":
|
202
314
|
# TODO: Make tunable per device
|
@@ -207,13 +319,19 @@ class SmuQamPlugin(HHDPlugin):
|
|
207
319
|
self.new_tdp = 15
|
208
320
|
case "performance":
|
209
321
|
self.new_tdp = 25
|
210
|
-
|
211
|
-
if ev[
|
212
|
-
logger.info(
|
322
|
+
|
323
|
+
if ev["type"] == "special" and ev.get("event", None) == "wakeup":
|
324
|
+
logger.info(
|
325
|
+
f"Waking up from sleep, resetting TDP after {SLEEP_DELAY} seconds."
|
326
|
+
)
|
213
327
|
self.queued = time.time() + SLEEP_DELAY
|
214
328
|
|
215
329
|
def close(self):
|
216
|
-
|
330
|
+
if self.fan_t:
|
331
|
+
self.fan_should_exit.set()
|
332
|
+
self.fan_t.join()
|
333
|
+
self.fan_t = None
|
334
|
+
self.fan_state = {}
|
217
335
|
|
218
336
|
|
219
337
|
class SmuDriverPlugin(HHDPlugin):
|
@@ -0,0 +1,80 @@
|
|
1
|
+
title: TDP Settings
|
2
|
+
type: container
|
3
|
+
tags: [ hide-title ]
|
4
|
+
children:
|
5
|
+
tdp:
|
6
|
+
title: TDP
|
7
|
+
hint: >-
|
8
|
+
Controls all Ryzen SMU settings through preset curves.
|
9
|
+
type: int
|
10
|
+
step: 1
|
11
|
+
unit: W
|
12
|
+
|
13
|
+
boost:
|
14
|
+
title: TDP Boost
|
15
|
+
type: bool
|
16
|
+
default: True
|
17
|
+
|
18
|
+
sys_tdp:
|
19
|
+
type: display
|
20
|
+
title: " "
|
21
|
+
tags: []
|
22
|
+
|
23
|
+
fan:
|
24
|
+
type: mode
|
25
|
+
title: Custom Fan Curve
|
26
|
+
hint: >-
|
27
|
+
Allows you to set a custom fan curve and to choose the temperature
|
28
|
+
probe (Edge or Junction). Junction is the peak temperature of the
|
29
|
+
chip: responds faster and prevents throttling. Edge is the temperature
|
30
|
+
of the chip: responds slower and prevents overheating.
|
31
|
+
|
32
|
+
default: disabled
|
33
|
+
modes:
|
34
|
+
disabled:
|
35
|
+
type: container
|
36
|
+
title: Disabled
|
37
|
+
|
38
|
+
manual_edge:
|
39
|
+
type: container
|
40
|
+
title: Manual (Edge, Smooth)
|
41
|
+
tags: [ non-essential ]
|
42
|
+
children:
|
43
|
+
|
44
|
+
info:
|
45
|
+
title: ""
|
46
|
+
type: display
|
47
|
+
|
48
|
+
st40: &speed_template
|
49
|
+
hint: Sets the speed at the named temperature.
|
50
|
+
tags: [slim]
|
51
|
+
type: int
|
52
|
+
min: 0
|
53
|
+
max: 100
|
54
|
+
step: 2
|
55
|
+
unit: "%"
|
56
|
+
title: 40C
|
57
|
+
default: 25
|
58
|
+
|
59
|
+
reset:
|
60
|
+
type: action
|
61
|
+
title: Reset to Default
|
62
|
+
|
63
|
+
manual_junction:
|
64
|
+
type: container
|
65
|
+
title: Manual (Tctl, Fast)
|
66
|
+
tags: [ non-essential ]
|
67
|
+
children:
|
68
|
+
|
69
|
+
info:
|
70
|
+
title: ""
|
71
|
+
type: display
|
72
|
+
|
73
|
+
st40:
|
74
|
+
<<: *speed_template
|
75
|
+
title: 40C
|
76
|
+
default: 40
|
77
|
+
|
78
|
+
reset:
|
79
|
+
type: action
|
80
|
+
title: Reset to Default
|
@@ -25,10 +25,7 @@ tdp:
|
|
25
25
|
tags: [ non-essential ]
|
26
26
|
default: >
|
27
27
|
Handheld Daemon supports the TDP slider in Steam and can use its per
|
28
|
-
game profiles
|
29
|
-
fan curves and battery limits.
|
30
|
-
Consider it, unless you prefer Decky.
|
31
|
-
(Powercontrol supports fan curves for GPD and Ayaneo devices)
|
28
|
+
game profiles. It also supports custom fan curves and battery limits.
|
32
29
|
|
33
30
|
decky_remove:
|
34
31
|
title: Disable Decky TDP Plugins
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: adjustor
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.6.1
|
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
|
File without changes
|
@@ -1,21 +0,0 @@
|
|
1
|
-
title: TDP Settings
|
2
|
-
type: container
|
3
|
-
tags: [ hide-title ]
|
4
|
-
children:
|
5
|
-
tdp:
|
6
|
-
title: TDP
|
7
|
-
hint: >-
|
8
|
-
Controls all Ryzen SMU settings through preset curves.
|
9
|
-
type: int
|
10
|
-
step: 1
|
11
|
-
unit: W
|
12
|
-
|
13
|
-
boost:
|
14
|
-
title: TDP Boost
|
15
|
-
type: bool
|
16
|
-
default: True
|
17
|
-
|
18
|
-
sys_tdp:
|
19
|
-
type: display
|
20
|
-
title: " "
|
21
|
-
tags: []
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{adjustor-3.5.4 → adjustor-3.6.1}/src/adjustor/drivers/amd/power-profiles-daemon.dbus.xml.in
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{adjustor-3.5.4 → adjustor-3.6.1}/usr/share/dbus-1/system.d/hhd-net.hadess.PowerProfiles.conf
RENAMED
File without changes
|