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:
parent
0de40067da
commit
40d12e0c01
6 changed files with 76 additions and 8 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -73,3 +73,6 @@ type=sysctl
|
|||
uname_regex=aarch64
|
||||
cpuinfo_regex=${thunderx_cpuinfo_regex}
|
||||
kernel.numa_balancing=0
|
||||
|
||||
[video]
|
||||
panel_power_savings=0
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in a new issue