adjustor 3.7.6__tar.gz → 3.8.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. {adjustor-3.7.6/src/adjustor.egg-info → adjustor-3.8.0}/PKG-INFO +1 -1
  2. {adjustor-3.7.6 → adjustor-3.8.0}/pyproject.toml +1 -1
  3. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/const.py +46 -31
  4. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/amd/ppd.py +37 -15
  5. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/asus/__init__.py +8 -45
  6. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/asus/settings.yml +0 -15
  7. adjustor-3.8.0/src/adjustor/drivers/battery/__init__.py +173 -0
  8. adjustor-3.8.0/src/adjustor/drivers/battery/battery.yml +28 -0
  9. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/smu/__init__.py +26 -33
  10. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/hhd.py +11 -11
  11. {adjustor-3.7.6 → adjustor-3.8.0/src/adjustor.egg-info}/PKG-INFO +1 -1
  12. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor.egg-info/SOURCES.txt +2 -0
  13. {adjustor-3.7.6 → adjustor-3.8.0}/LICENSE +0 -0
  14. {adjustor-3.7.6 → adjustor-3.8.0}/MANIFEST.in +0 -0
  15. {adjustor-3.7.6 → adjustor-3.8.0}/readme.md +0 -0
  16. {adjustor-3.7.6 → adjustor-3.8.0}/setup.cfg +0 -0
  17. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/__init__.py +0 -0
  18. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/__main__.py +0 -0
  19. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/__init__.py +0 -0
  20. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/acpi.py +0 -0
  21. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/alib.py +0 -0
  22. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/fan/__init__.py +0 -0
  23. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/fan/__main__.py +0 -0
  24. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/fan/alg.py +0 -0
  25. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/fan/core.py +0 -0
  26. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/fan/utils.py +0 -0
  27. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/lenovo.py +0 -0
  28. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/core/platform.py +0 -0
  29. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/__init__.py +0 -0
  30. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/amd/__init__.py +0 -0
  31. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/amd/power-profiles-daemon.dbus.xml.in +0 -0
  32. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/amd/settings.yml +0 -0
  33. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/general/__init__.py +0 -0
  34. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/general/settings.yml +0 -0
  35. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/lenovo/__init__.py +0 -0
  36. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/lenovo/settings.yml +0 -0
  37. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/smu/qam.yml +0 -0
  38. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/drivers/smu/smu.yml +0 -0
  39. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/events.py +0 -0
  40. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/fuse/__init__.py +0 -0
  41. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/fuse/driver.py +0 -0
  42. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/fuse/gpu.py +0 -0
  43. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/fuse/utils.py +0 -0
  44. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/i18n.py +0 -0
  45. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor/settings.yml +0 -0
  46. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor.egg-info/dependency_links.txt +0 -0
  47. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor.egg-info/entry_points.txt +0 -0
  48. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor.egg-info/requires.txt +0 -0
  49. {adjustor-3.7.6 → adjustor-3.8.0}/src/adjustor.egg-info/top_level.txt +0 -0
  50. {adjustor-3.7.6 → adjustor-3.8.0}/usr/share/dbus-1/system.d/hhd-net.hadess.PowerProfiles.conf +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: adjustor
3
- Version: 3.7.6
3
+ Version: 3.8.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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "adjustor"
3
- version = "3.7.6"
3
+ version = "3.8.0"
4
4
  authors = [
5
5
  { name="Kapenekakis Antheas", email="pypi@antheas.dev" },
6
6
  ]
@@ -27,17 +27,17 @@ class DevideProfile(TypedDict):
27
27
  alib: dict[str, AlibParams]
28
28
  dev: dict[str, DeviceParams]
29
29
 
30
-
31
- PLATFORM_PROFILE_MAP = [
32
- ("low-power", 0),
33
- ("quiet", 0),
34
- ("balanced", 13),
35
- ("performance", 20),
36
- ]
30
+ # internal name for ppd, platform_profile choices, min TDP for
31
+ # profile to apply, tdp target to apply when selecting profile
37
32
  ENERGY_MAP = [
38
- ("power", 0),
39
- ("balanced", 13),
40
- ("performance", 20),
33
+ ("power", ["low-power", "quiet"], 0, 8),
34
+ ("balanced", ["balanced"], 13, 15),
35
+ ("performance", ["performance"], 20, 25),
36
+ ]
37
+ ENERGY_MAP_18W = [
38
+ ("low-power", ["low-power", "quiet"], 0, 5),
39
+ ("balanced", ["balanced"], 8, 12),
40
+ ("performance", ["performance"], 13, 18),
41
41
  ]
42
42
 
43
43
  ALIB_PARAMS = {
@@ -112,33 +112,48 @@ DEV_PARAMS_8040: dict[str, DeviceParams] = DEV_PARAMS_30W
112
112
  DEV_PARAMS_HX370: dict[str, DeviceParams] = DEV_PARAMS_30W
113
113
  DEV_PARAMS_LEGO = DEV_PARAMS_30W
114
114
 
115
- DEV_DATA: dict[str, tuple[dict[str, DeviceParams], dict[str, AlibParams], bool]] = {
116
- "NEO-01": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False),
117
- "V3": (DEV_PARAMS_28W, ALIB_PARAMS_8040, False),
118
- "83E1": (DEV_PARAMS_LEGO, ALIB_PARAMS_7040, False),
119
- "ONEXPLAYER F1Pro": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370, False),
120
- "ONEXPLAYER F1 EVA-02": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370, False),
115
+ DEV_DATA: dict[
116
+ str,
117
+ tuple[
118
+ dict[str, DeviceParams],
119
+ dict[str, AlibParams],
120
+ bool,
121
+ list[tuple[str, list[str], int, int]],
122
+ ],
123
+ ] = {
124
+ "NEO-01": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False, ENERGY_MAP),
125
+ "V3": (DEV_PARAMS_28W, ALIB_PARAMS_8040, False, ENERGY_MAP),
126
+ "83E1": (DEV_PARAMS_LEGO, ALIB_PARAMS_7040, False, ENERGY_MAP),
127
+ "ONEXPLAYER F1Pro": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370, False, ENERGY_MAP),
128
+ "ONEXPLAYER F1 EVA-02": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370, False, ENERGY_MAP),
121
129
  # GPD Devices are 28W max
122
- "G1618-04": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False),
123
- "G1617-01": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False),
124
- "G1619-04": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False),
125
- "G1619-05": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False),
130
+ "G1618-04": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False, ENERGY_MAP),
131
+ "G1617-01": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False, ENERGY_MAP),
132
+ "G1619-04": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False, ENERGY_MAP),
133
+ "G1619-05": (DEV_PARAMS_28W, ALIB_PARAMS_7040, False, ENERGY_MAP),
126
134
  }
127
135
 
128
- CPU_DATA: dict[str, tuple[dict[str, DeviceParams], dict[str, AlibParams]]] = {
129
- "AMD Ryzen Z1 Extreme": (DEV_PARAMS_7040, ALIB_PARAMS_7040),
130
- "AMD Ryzen Z1": (DEV_PARAMS_7040, ALIB_PARAMS_7040),
136
+ CPU_DATA: dict[
137
+ str,
138
+ tuple[
139
+ dict[str, DeviceParams],
140
+ dict[str, AlibParams],
141
+ list[tuple[str, list[str], int, int]],
142
+ ],
143
+ ] = {
144
+ "AMD Ryzen Z1 Extreme": (DEV_PARAMS_7040, ALIB_PARAMS_7040, ENERGY_MAP),
145
+ "AMD Ryzen Z1": (DEV_PARAMS_7040, ALIB_PARAMS_7040, ENERGY_MAP),
131
146
  # Ayaneo AIR Pro, max is 18W
132
- "AMD Ryzen 5 5560U": (DEV_PARAMS_18W, ALIB_PARAMS_5040),
147
+ "AMD Ryzen 5 5560U": (DEV_PARAMS_18W, ALIB_PARAMS_5040, ENERGY_MAP_18W),
133
148
  # 28W works fine, 30W is pushing it
134
- "AMD Ryzen 7 5700U": (DEV_PARAMS_5000, ALIB_PARAMS_5040),
135
- "AMD Ryzen 7 5800U": (DEV_PARAMS_5000, ALIB_PARAMS_5040),
149
+ "AMD Ryzen 7 5700U": (DEV_PARAMS_5000, ALIB_PARAMS_5040, ENERGY_MAP),
150
+ "AMD Ryzen 7 5800U": (DEV_PARAMS_5000, ALIB_PARAMS_5040, ENERGY_MAP),
136
151
  # GPD Win 4
137
152
  # model name : AMD Ryzen 7 6800U with Radeon Graphics
138
- "AMD Ryzen 7 6800U": (DEV_PARAMS_6000, ALIB_PARAMS_6040),
139
- "AMD Ryzen 7 7840U": (DEV_PARAMS_7040, ALIB_PARAMS_7040),
140
- "AMD Ryzen 7 8840U": (DEV_PARAMS_8040, ALIB_PARAMS_8040),
153
+ "AMD Ryzen 7 6800U": (DEV_PARAMS_6000, ALIB_PARAMS_6040, ENERGY_MAP),
154
+ "AMD Ryzen 7 7840U": (DEV_PARAMS_7040, ALIB_PARAMS_7040, ENERGY_MAP),
155
+ "AMD Ryzen 7 8840U": (DEV_PARAMS_8040, ALIB_PARAMS_8040, ENERGY_MAP),
141
156
  # AMD Athlon Silver 3050e (Win600, will it support tdp?)
142
- "AMD Ryzen AI 9 HX 370": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370),
143
- "AMD Ryzen AI HX 360": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370),
157
+ "AMD Ryzen AI 9 HX 370": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370, ENERGY_MAP),
158
+ "AMD Ryzen AI HX 360": (DEV_PARAMS_HX370, ALIB_PARAMS_HX370, ENERGY_MAP),
144
159
  }
@@ -138,22 +138,24 @@ def create_interface(legacy: bool):
138
138
  # TODO
139
139
  return handle
140
140
 
141
- def update_profile(self):
142
- for line in sys.stdin:
143
- if not line:
144
- break
145
- profile = line.strip()
146
- if profile not in SUPPORTED_PROFILES_REVERSE:
147
- continue
141
+ def set_profile(self, profile):
142
+ if profile not in SUPPORTED_PROFILES_REVERSE:
143
+ return
148
144
 
149
- self.profile = profile
150
- self.PropertiesChanged(
151
- iface(legacy), {"ActiveProfile": self.profile}, []
152
- )
153
- return True
145
+ self.profile = SUPPORTED_PROFILES_REVERSE[profile]
146
+ self.PropertiesChanged(iface(legacy), {"ActiveProfile": self.profile}, [])
154
147
 
155
148
  return HhdPpd
156
149
 
150
+ def update_profile(services):
151
+ for line in sys.stdin:
152
+ if not line:
153
+ break
154
+ profile = line.strip()
155
+
156
+ for s in services:
157
+ s.set_profile(profile)
158
+ return True
157
159
 
158
160
  if __name__ == "__main__":
159
161
  mainloop = None
@@ -166,10 +168,30 @@ if __name__ == "__main__":
166
168
 
167
169
  legacy = False
168
170
  session_bus = dbus.SystemBus()
169
- name = dbus.service.BusName(iface(legacy), session_bus)
170
- object = create_interface(legacy)(session_bus)
171
+
172
+ claimed = False
173
+ try:
174
+ name1 = dbus.service.BusName(iface(False), session_bus)
175
+ claimed = True
176
+ except Exception:
177
+ pass
178
+
179
+ try:
180
+ name2 = dbus.service.BusName(iface(True), session_bus)
181
+ claimed = True
182
+ except Exception:
183
+ pass
184
+
185
+ if not claimed:
186
+ sys.exit(1)
187
+
188
+ services = [
189
+ create_interface(False)(session_bus),
190
+ create_interface(True)(session_bus),
191
+ ]
192
+
193
+ GLib.timeout_add(100, lambda: update_profile(services))
171
194
 
172
- GLib.timeout_add(100, object.update_profile)
173
195
  mainloop = GLib.MainLoop()
174
196
  mainloop.run()
175
197
  except KeyboardInterrupt:
@@ -51,20 +51,6 @@ MIN_CURVE = [2, 5, 17, 17, 17, 17, 17, 17]
51
51
  DEFAULT_CURVE = [5, 10, 20, 35, 55, 75, 75, 75]
52
52
 
53
53
 
54
- def set_charge_limit(lim: int):
55
- try:
56
- # FIXME: Hardcoded path, should match using another characteristic
57
- logger.info(f"Setting charge limit to {lim:d} %.")
58
- with open(
59
- "/sys/class/power_supply/BAT0/charge_control_end_threshold", "w"
60
- ) as f:
61
- f.write(f"{lim}\n")
62
- return True
63
- except Exception as e:
64
- logger.error(f"Failed to write battery limit with error:\n{e}")
65
- return False
66
-
67
-
68
54
  def set_tdp(pretty: str, fn: str, val: int):
69
55
  logger.info(f"Setting tdp value '{pretty}' to {val} by writing to:\n{fn}")
70
56
  try:
@@ -147,7 +133,6 @@ class AsusDriverPlugin(HHDPlugin):
147
133
 
148
134
  self.queue_fan = None
149
135
  self.queue_tdp = None
150
- self.queue_charge_limit = None
151
136
  self.queue_extreme = time.perf_counter() + EXTREME_STARTUP_DELAY
152
137
  self.new_tdp = None
153
138
  self.new_mode = None
@@ -225,34 +210,6 @@ class AsusDriverPlugin(HHDPlugin):
225
210
 
226
211
  curr = time.perf_counter()
227
212
 
228
- # Charge limit
229
- lim = conf["tdp.asus.charge_limit"].to(str)
230
- if (self.startup and lim != "disabled") or (
231
- lim != self.old_conf["charge_limit"].to(str)
232
- ):
233
- self.queue_charge_limit = curr + APPLY_DELAY
234
-
235
- if self.queue_charge_limit and self.queue_charge_limit < curr:
236
- self.queue_charge_limit = None
237
- match lim:
238
- case "p65":
239
- set_charge_limit(65)
240
- case "p70":
241
- set_charge_limit(70)
242
- case "p80":
243
- set_charge_limit(80)
244
- case "p85":
245
- set_charge_limit(85)
246
- case "p90":
247
- set_charge_limit(90)
248
- case "p95":
249
- set_charge_limit(95)
250
- case "disabled":
251
- # Avoid writing charge limit on startup if
252
- # disabled
253
- if not self.startup:
254
- set_charge_limit(100)
255
-
256
213
  #
257
214
  # TDP
258
215
  #
@@ -508,8 +465,14 @@ class AsusDriverPlugin(HHDPlugin):
508
465
  f"Waking up from sleep, resetting TDP after {SLEEP_DELAY} seconds."
509
466
  )
510
467
  self.queue_tdp = time.time() + SLEEP_DELAY
511
- elif ev["type"] == "acpi" and ev["event"] in ("ac", "dc") and not self.queue_tdp:
512
- logger.info(f"Power adapter status switched to '{ev['event']}', resetting TDP.")
468
+ elif (
469
+ ev["type"] == "acpi"
470
+ and ev["event"] in ("ac", "dc")
471
+ and not self.queue_tdp
472
+ ):
473
+ logger.info(
474
+ f"Power adapter status switched to '{ev['event']}', resetting TDP."
475
+ )
513
476
  self.queue_tdp = time.time() + APPLY_DELAY
514
477
  elif self.cycle_tdp and ev["type"] == "special" and ev["event"] == "xbox_y":
515
478
  match self.mode:
@@ -129,21 +129,6 @@ children:
129
129
  default: >-
130
130
  Asus hardware limits the minimum fan curve depending on TDP mode.
131
131
 
132
- charge_limit:
133
- type: multiple
134
- title: Charge Limit (%)
135
- tags: [ non-essential, ordinal ]
136
- hint: >-
137
- Applies a charge limit to the battery, 75% and up.
138
- options:
139
- p70: 70%
140
- p80: 80%
141
- p85: 85%
142
- p90: 90%
143
- p95: 95%
144
- disabled: Unset
145
- default: disabled
146
-
147
132
  extreme_standby:
148
133
  type: multiple
149
134
  title: Extreme Standby Mode
@@ -0,0 +1,173 @@
1
+ import logging
2
+ import time
3
+ from threading import Event as TEvent, Lock, Thread
4
+ from typing import Sequence
5
+ import os
6
+
7
+ from hhd.plugins import Context, Event, HHDPlugin, load_relative_yaml
8
+ from hhd.plugins.conf import Config
9
+
10
+ from adjustor.core.alib import AlibParams, DeviceParams, alib
11
+ from adjustor.core.fan import fan_worker, get_fan_info
12
+ from adjustor.core.platform import get_platform_choices, set_platform_profile
13
+ from adjustor.i18n import _
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ APPLY_DELAY = 0.7
18
+
19
+
20
+ def set_charge_limit(bat: str, lim: int):
21
+ try:
22
+ logger.info(f"Setting charge limit to {lim:d} %.")
23
+ with open(bat, "w") as f:
24
+ f.write(f"{lim}\n")
25
+ return True
26
+ except Exception as e:
27
+ logger.error(f"Failed to write battery limit with error:\n{e}")
28
+ return False
29
+
30
+
31
+ def set_charge_bypass(bat: str, type: str):
32
+ match type:
33
+ case "disabled":
34
+ val = "Standard"
35
+ case "awake":
36
+ val = "BypassS0"
37
+ case "always":
38
+ val = "Bypass"
39
+ case _:
40
+ logger.error(f"Invalid charge bypass type: {type}")
41
+ return
42
+
43
+ try:
44
+ logger.info(f"Setting charge type to '{val}' (for bypass '{type}').")
45
+ with open(bat, "w") as f:
46
+ f.write(f"{val}\n")
47
+ return True
48
+ except Exception as e:
49
+ logger.error(f"Failed to write battery bypass with error:\n{e}")
50
+ return False
51
+
52
+
53
+ class BatteryPlugin(HHDPlugin):
54
+
55
+ def __init__(
56
+ self,
57
+ ) -> None:
58
+ self.name = f"adjustor_battery"
59
+ self.priority = 9
60
+ self.log = "batt"
61
+ self.enabled = False
62
+ self.initialized = False
63
+ self.startup = False
64
+
65
+ self.queue_charge_limit = None
66
+ self.charge_bypass_fn = None
67
+ self.charge_limit_fn = None
68
+ self.charge_bypass_prev = None
69
+ self.charge_limit_prev = None
70
+
71
+ def settings(self):
72
+ if not self.enabled:
73
+ self.initialized = False
74
+ return {}
75
+
76
+ self.initialized = True
77
+ out = {"tdp": {"battery": load_relative_yaml("battery.yml")}}
78
+
79
+ if not self.charge_limit_fn:
80
+ del out["tdp"]["battery"]["children"]["charge_limit"]
81
+ if not self.charge_bypass_fn:
82
+ del out["tdp"]["battery"]["children"]["charge_bypass"]
83
+
84
+ return out
85
+
86
+ def open(
87
+ self,
88
+ emit,
89
+ context: Context,
90
+ ):
91
+ self.emit = emit
92
+ self.startup = True
93
+
94
+ for bat in os.listdir("/sys/class/power_supply"):
95
+ if not bat.startswith("BAT"):
96
+ continue
97
+
98
+ with open(f"/sys/class/power_supply/{bat}/type") as f:
99
+ if "Battery" not in f.read():
100
+ continue
101
+
102
+ base = f"/sys/class/power_supply/{bat}"
103
+ if os.path.exists(f"{base}/charge_control_end_threshold"):
104
+ self.charge_limit_fn = f"{base}/charge_control_end_threshold"
105
+ if os.path.exists(f"{base}/charge_type"):
106
+ try:
107
+ with open("/sys/devices/virtual/dmi/id/sys_vendor") as f:
108
+ supports = "ONE-NETBOOK" in f.read()
109
+ except Exception:
110
+ supports = False
111
+
112
+ if supports:
113
+ self.charge_bypass_fn = f"{base}/charge_type"
114
+ else:
115
+ logger.warning(
116
+ "Found charge type, but charge bypass is only supported on OneXPlayer currently."
117
+ )
118
+ if self.charge_bypass_fn or self.charge_limit_fn:
119
+ logger.info(
120
+ f"Found battery '{bat}' with:\nBattery Bypass:\n{self.charge_bypass_fn}\nBattery Limit:\n{self.charge_limit_fn}."
121
+ )
122
+ break
123
+
124
+ def update(self, conf: Config):
125
+ self.enabled = conf["hhd.settings.tdp_enable"].to(bool)
126
+
127
+ if not self.initialized:
128
+ return
129
+
130
+ curr = time.time()
131
+
132
+ if self.charge_bypass_fn:
133
+ bypass = conf["tdp.battery.charge_bypass"].to(str)
134
+ if self.charge_bypass_prev != bypass:
135
+ self.charge_bypass_prev = bypass
136
+
137
+ if bypass != "disabled" or not self.startup:
138
+ set_charge_bypass(self.charge_bypass_fn, bypass)
139
+
140
+ # Charge limit
141
+ if self.charge_limit_fn:
142
+ lim = conf["tdp.battery.charge_limit"].to(str)
143
+ if lim != self.charge_limit_prev:
144
+ self.queue_charge_limit = curr + APPLY_DELAY
145
+ self.charge_limit_prev = lim
146
+
147
+ if self.startup or (
148
+ self.queue_charge_limit and self.queue_charge_limit < curr
149
+ ):
150
+ self.queue_charge_limit = None
151
+ self.charge_limit_prev = lim
152
+
153
+ match lim:
154
+ case "p65":
155
+ set_charge_limit(self.charge_limit_fn, 65)
156
+ case "p70":
157
+ set_charge_limit(self.charge_limit_fn, 70)
158
+ case "p80":
159
+ set_charge_limit(self.charge_limit_fn, 80)
160
+ case "p85":
161
+ set_charge_limit(self.charge_limit_fn, 85)
162
+ case "p90":
163
+ set_charge_limit(self.charge_limit_fn, 90)
164
+ case "p95":
165
+ set_charge_limit(self.charge_limit_fn, 95)
166
+ case "disabled":
167
+ # Avoid writing charge limit on startup if
168
+ # disabled, so that if user does not use us
169
+ # we do not overwrite their setting.
170
+ if not self.startup:
171
+ set_charge_limit(self.charge_limit_fn, 100)
172
+
173
+ self.startup = False
@@ -0,0 +1,28 @@
1
+ title: Battery Settings
2
+ type: container
3
+ tags: [ hide-title ]
4
+ children:
5
+ charge_limit:
6
+ type: multiple
7
+ title: Charge Limit (%)
8
+ tags: [ non-essential, ordinal ]
9
+ hint: >-
10
+ Applies a charge limit to the battery, 75% and up.
11
+ options:
12
+ p70: 70%
13
+ p80: 80%
14
+ p85: 85%
15
+ p90: 90%
16
+ p95: 95%
17
+ disabled: Unset
18
+ default: disabled
19
+
20
+ charge_bypass:
21
+ type: multiple
22
+ title: Charge Bypass
23
+ tags: [ non-essential, ordinal ]
24
+ options:
25
+ disabled: Unset
26
+ awake: While On
27
+ always: Always
28
+ default: Unset
@@ -44,8 +44,8 @@ class SmuQamPlugin(HHDPlugin):
44
44
  def __init__(
45
45
  self,
46
46
  dev: dict[str, DeviceParams],
47
- pp_map: list[tuple[str, int]] | None,
48
- energy_map: list[tuple[str, int]] | None,
47
+ pp_map: list[tuple[str, list[str], int, int]] | None,
48
+ pp_enable: bool = True,
49
49
  init_tdp: bool = True,
50
50
  ) -> None:
51
51
  self.name = f"adjustor_smu_qam"
@@ -80,19 +80,15 @@ class SmuQamPlugin(HHDPlugin):
80
80
  # startup
81
81
  self.init_tdp = init_tdp
82
82
 
83
- self.energy_map = energy_map
84
- if pp_map:
83
+ self.pp_map = pp_map
84
+ if pp_enable and pp_map:
85
85
  self.pps = get_platform_choices() or []
86
- if self.pps:
87
- self.pp_map = pp_map
88
- else:
86
+ if not self.pps:
89
87
  logger.warning(
90
88
  f"Platform profile map was provided but device does not have platform profiles."
91
89
  )
92
- self.pp_map = None
93
90
  else:
94
91
  self.pps = []
95
- self.pp_map = None
96
92
 
97
93
  def settings(self):
98
94
  if not self.enabled:
@@ -205,18 +201,16 @@ class SmuQamPlugin(HHDPlugin):
205
201
  conf["tdp.smu.std.skin_limit"] = new_tdp
206
202
  conf["tdp.smu.std.stapm_limit"] = new_tdp
207
203
 
208
- if self.pp_map and conf["tdp.smu.platform_profile"].to(str) != "disabled":
209
- pp = self.pp_map[0][0]
210
- for npp, tdp in self.pp_map:
211
- if tdp < new_tdp and npp in self.pps:
212
- pp = npp
213
- conf["tdp.smu.platform_profile"] = pp
214
-
215
- if self.energy_map:
216
- ep = self.energy_map[0][0]
217
- for nep, tdp in self.energy_map:
204
+ if self.pp_map:
205
+ pp = ep = self.pp_map[0][0]
206
+ for nep, npps, tdp, target in self.pp_map:
218
207
  if tdp < new_tdp:
219
208
  ep = nep
209
+ for npp in npps:
210
+ if npp in self.pps:
211
+ pp = npp
212
+ if self.pps and conf.get("tdp.smu.platform_profile", "disabled") != "disabled":
213
+ conf["tdp.smu.platform_profile"] = pp
220
214
  conf["tdp.smu.energy_policy"] = ep
221
215
 
222
216
  if new_boost:
@@ -310,15 +304,13 @@ class SmuQamPlugin(HHDPlugin):
310
304
  self.new_tdp = ev["tdp"]
311
305
  self.sys_tdp = ev["tdp"] is not None
312
306
 
313
- if ev["type"] == "ppd":
314
- # TODO: Make tunable per device
315
- match ev["status"]:
316
- case "power":
317
- self.new_tdp = 8
318
- case "balanced":
319
- self.new_tdp = 15
320
- case "performance":
321
- self.new_tdp = 25
307
+ if ev["type"] == "ppd" and self.pp_map:
308
+ for ep, pps, tdp, target in self.pp_map:
309
+ if ep == ev["status"]:
310
+ self.new_tdp = target
311
+ break
312
+ else:
313
+ logger.warning(f"Energy profile '{ev['status']}' not found in map.")
322
314
 
323
315
  if ev["type"] == "special" and ev.get("event", None) == "wakeup":
324
316
  logger.info(
@@ -462,6 +454,12 @@ class SmuDriverPlugin(HHDPlugin):
462
454
  self.is_set = False
463
455
  self.old_pp = new_pp
464
456
 
457
+ # Inform ppd instantly to avoid lag in slider
458
+ new_target = conf["tdp.smu.energy_policy"].to(str)
459
+ if new_target != self.old_target:
460
+ self.old_target = new_target
461
+ self.emit({"type": "energy", "status": new_target}) # type: ignore
462
+
465
463
  if conf["tdp.smu.apply"].to(bool):
466
464
  conf["tdp.smu.apply"] = False
467
465
 
@@ -471,11 +469,6 @@ class SmuDriverPlugin(HHDPlugin):
471
469
  set_platform_profile(cpp)
472
470
  time.sleep(PP_DELAY)
473
471
 
474
- new_target = conf["tdp.smu.energy_policy"].to(str)
475
- if new_target != self.old_target:
476
- self.old_target = new_target
477
- self.emit({"type": "energy", "status": new_target}) # type: ignore
478
-
479
472
  alib(
480
473
  new_vals,
481
474
  self.cpu,
@@ -10,7 +10,7 @@ from hhd.plugins.plugin import Emitter
10
10
  from hhd.utils import expanduser
11
11
 
12
12
  from adjustor.core.acpi import check_perms, initialize
13
- from adjustor.core.const import CPU_DATA, DEV_DATA, PLATFORM_PROFILE_MAP, ENERGY_MAP
13
+ from adjustor.core.const import CPU_DATA, DEV_DATA
14
14
 
15
15
  from .i18n import _
16
16
 
@@ -243,6 +243,7 @@ def autodetect(existing: Sequence[HHDPlugin]) -> Sequence[HHDPlugin]:
243
243
  from .drivers.lenovo import LenovoDriverPlugin
244
244
  from .drivers.smu import SmuDriverPlugin, SmuQamPlugin
245
245
  from .drivers.amd import AmdGPUPlugin
246
+ from .drivers.battery import BatteryPlugin
246
247
 
247
248
  drivers = []
248
249
  with open("/sys/devices/virtual/dmi/id/product_name") as f:
@@ -261,9 +262,7 @@ def autodetect(existing: Sequence[HHDPlugin]) -> Sequence[HHDPlugin]:
261
262
  max_tdp = 30
262
263
 
263
264
  legion_s = prod in LEGION_GO_S_DMIS
264
- if (prod == LEGION_GO_DMI or legion_s) and not bool(
265
- os.environ.get("HHD_ADJ_ALLY")
266
- ):
265
+ if (prod == LEGION_GO_DMI or legion_s) and not bool(os.environ.get("HHD_ADJ_ALLY")):
267
266
  drivers.append(LenovoDriverPlugin(legion_s=legion_s))
268
267
  drivers_matched = True
269
268
  use_acpi_call = True
@@ -284,7 +283,7 @@ def autodetect(existing: Sequence[HHDPlugin]) -> Sequence[HHDPlugin]:
284
283
  drivers_matched = False
285
284
 
286
285
  if not drivers_matched and prod in DEV_DATA:
287
- dev, cpu, pp_enable = DEV_DATA[prod]
286
+ dev, cpu, pp_enable, energy_map = DEV_DATA[prod]
288
287
 
289
288
  try:
290
289
  # Set values for the steam slider
@@ -308,8 +307,8 @@ def autodetect(existing: Sequence[HHDPlugin]) -> Sequence[HHDPlugin]:
308
307
  drivers.append(
309
308
  SmuQamPlugin(
310
309
  dev,
311
- PLATFORM_PROFILE_MAP if pp_enable else None,
312
- ENERGY_MAP,
310
+ energy_map,
311
+ pp_enable=pp_enable,
313
312
  init_tdp=not prod == "83E1",
314
313
  ),
315
314
  )
@@ -317,7 +316,7 @@ def autodetect(existing: Sequence[HHDPlugin]) -> Sequence[HHDPlugin]:
317
316
  use_acpi_call = True
318
317
 
319
318
  if not drivers_matched:
320
- for name, (dev, cpu) in CPU_DATA.items():
319
+ for name, (dev, cpu, energy_map) in CPU_DATA.items():
321
320
  if name in cpuinfo:
322
321
  drivers.append(
323
322
  SmuDriverPlugin(
@@ -327,7 +326,7 @@ def autodetect(existing: Sequence[HHDPlugin]) -> Sequence[HHDPlugin]:
327
326
  )
328
327
  )
329
328
  drivers.append(
330
- SmuQamPlugin(dev, PLATFORM_PROFILE_MAP, ENERGY_MAP),
329
+ SmuQamPlugin(dev, energy_map),
331
330
  )
332
331
  use_acpi_call = True
333
332
  break
@@ -336,13 +335,14 @@ def autodetect(existing: Sequence[HHDPlugin]) -> Sequence[HHDPlugin]:
336
335
  from .drivers.general import GeneralPowerPlugin
337
336
 
338
337
  logger.info(f"No tdp drivers found for this device, using generic plugin.")
339
-
338
+
340
339
  is_steamdeck = "Jupiter" in prod or "Galileo" in prod
341
- return [GeneralPowerPlugin(is_steamdeck=is_steamdeck)]
340
+ return [GeneralPowerPlugin(is_steamdeck=is_steamdeck), BatteryPlugin()]
342
341
 
343
342
  return [
344
343
  *drivers,
345
344
  AdjustorInitPlugin(use_acpi_call=use_acpi_call),
346
345
  AdjustorPlugin(min_tdp, default_tdp, max_tdp),
346
+ BatteryPlugin(),
347
347
  AmdGPUPlugin(),
348
348
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: adjustor
3
- Version: 3.7.6
3
+ Version: 3.8.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
@@ -32,6 +32,8 @@ src/adjustor/drivers/amd/ppd.py
32
32
  src/adjustor/drivers/amd/settings.yml
33
33
  src/adjustor/drivers/asus/__init__.py
34
34
  src/adjustor/drivers/asus/settings.yml
35
+ src/adjustor/drivers/battery/__init__.py
36
+ src/adjustor/drivers/battery/battery.yml
35
37
  src/adjustor/drivers/general/__init__.py
36
38
  src/adjustor/drivers/general/settings.yml
37
39
  src/adjustor/drivers/lenovo/__init__.py
File without changes
File without changes
File without changes
File without changes
File without changes