1
0
Fork 0

Modify the video plugin for tuning of the amdgpu panel_power_savings attribute

This attribute accepts a range from 0 through 4 where larger values
will also have larger panel power savings.

Using this has a trade off for color accuracy, and it is only applied
when the system is currently operating on battery.

Intentionally the plugin will check what values are already programmed
to the sysfs file to avoid unnecessary writes.  Writing the sysfs file
will cause a modeset which isn't necessary if writing the same value twice.

The default values are applied to the profiles that are used in
power-profiles-daemon compatbility.  They also match the values used in
that software.

Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
This commit is contained in:
Mario Limonciello 2024-02-22 14:55:48 -06:00
parent 0de40067da
commit 40d12e0c01
6 changed files with 76 additions and 8 deletions

View file

@ -62,3 +62,6 @@ sched_min_granularity_ns = 10000000
# and reduces their over-scheduling. Synchronous workloads will still
# have immediate wakeup/sleep latencies.
sched_wakeup_granularity_ns = 15000000
[video]
panel_power_savings=0

View file

@ -22,6 +22,7 @@ timeout=10
[video]
radeon_powersave=dpm-balanced, auto
panel_power_savings=0
[disk]
# Comma separated list of devices, all devices if commented out.

View file

@ -35,3 +35,6 @@ vm.dirty_background_ratio=3
# 100 tells the kernel to aggressively swap processes out of physical memory
# and move them to swap cache
vm.swappiness=10
[video]
panel_power_savings=0

View file

@ -22,6 +22,7 @@ timeout=10
[video]
radeon_powersave=dpm-battery, auto
panel_power_savings=3
[disk]
# Comma separated list of devices, all devices if commented out.

View file

@ -73,3 +73,6 @@ type=sysctl
uname_regex=aarch64
cpuinfo_regex=${thunderx_cpuinfo_regex}
kernel.numa_balancing=0
[video]
panel_power_savings=0

View file

@ -11,9 +11,10 @@ log = tuned.logs.get()
class VideoPlugin(base.Plugin):
"""
`video`::
Sets various powersave levels on video cards. Currently, only the
Radeon cards are supported. The powersave level can be specified
Sets various power saving features on video cards.
Radeon cards are supported.
The powersave level can be specified
by using the [option]`radeon_powersave` option. Supported values are:
+
--
@ -40,17 +41,27 @@ class VideoPlugin(base.Plugin):
radeon_powersave=high
----
====
Mobile hardware with amdgpu driven eDP panels can be configured
with the [option]`panel_power_savings` option.
This accepts a value range from 0 to 4, where 4 is the highest power savings
but will trade off color accuracy.
"""
def __init__(self, *args, **kwargs):
super(VideoPlugin, self).__init__(*args, **kwargs)
def _init_devices(self):
self._devices_supported = True
self._free_devices = set()
self._assigned_devices = set()
# FIXME: this is a blind shot, needs testing
for device in self._hardware_inventory.get_devices("drm").match_sys_name("card*").match_property("DEVTYPE", "drm_minor"):
self._free_devices.add(device.sys_name)
# Add any radeon and amdgpu hardware with /any/ supported attributes present
for device in self._hardware_inventory.get_devices("drm").match_sys_name("card*-*"):
attrs = self._files(device.sys_name)
for attr in attrs:
if os.path.exists(attrs[attr]):
self._free_devices.add(device.sys_name)
self._cmd = commands()
def _get_device_objects(self, devices):
@ -60,6 +71,7 @@ class VideoPlugin(base.Plugin):
def _get_config_options(self):
return {
"radeon_powersave" : None,
"panel_power_savings": None,
}
def _instance_init(self, instance):
@ -73,9 +85,31 @@ class VideoPlugin(base.Plugin):
return {
"method" : "/sys/class/drm/%s/device/power_method" % device,
"profile": "/sys/class/drm/%s/device/power_profile" % device,
"dpm_state": "/sys/class/drm/%s/device/power_dpm_state" % device
"dpm_state": "/sys/class/drm/%s/device/power_dpm_state" % device,
"panel_power_savings": "/sys/class/drm/%s/amdgpu/panel_power_savings" % device,
}
def apply_panel_power_saving_target(self, device, target, sim=False):
"""Apply the target value to the panel_power_savings file if it doesn't already have it"""
# if we don't have the file, we might be radeon not amdgpu
if not os.path.exists(self._files(device)["panel_power_savings"]):
return None
# make sure the value is different (avoids unnecessary kernel modeset)
current = int(self._get_panel_power_savings(device))
if current == target:
log.info(
"panel_power_savings for %s already %s" % (device, target)
)
return target
# flush it out
log.info("%s panel_power_savings -> %s" % (device, target))
if sim or self._cmd.write_to_file(self._files(device)["panel_power_savings"], target):
return target
return None
@command_set("radeon_powersave", per_device=True)
def _set_radeon_powersave(self, value, device, sim, remove):
sys_files = self._files(device)
@ -127,3 +161,26 @@ class VideoPlugin(base.Plugin):
return "dpm-" + self._cmd.read_file(sys_files["dpm_state"]).strip()
else:
return None
@command_set("panel_power_savings", per_device=True)
def _set_panel_power_savings(self, value, device, sim, remove):
"""Set the panel_power_savings value"""
try:
value = int(value, 10)
except ValueError:
log.warn("Invalid value %s for panel_power_savings" % value)
return None
if value in range(0, 5):
return self.apply_panel_power_saving_target(device, value, sim)
else:
log.warn("Invalid value %s for panel_power_savings" % value)
return None
@command_get("panel_power_savings")
def _get_panel_power_savings(self, device, ignore_missing=False):
"""Get the current panel_power_savings value"""
if not os.path.exists(self._files(device)["panel_power_savings"]):
log.debug("panel_power_savings is not supported on '%s'" % device)
return None
fname = self._files(device)["panel_power_savings"]
return self._cmd.read_file(fname, no_error=ignore_missing).strip()