mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-01-22 17:33:19 +01:00
feat: change limits dynamically
This commit is contained in:
@@ -55,6 +55,25 @@ impl AsusArmouryAttribute {
|
|||||||
String::from(self.attr.name())
|
String::from(self.attr.name())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_i32_value(refreshed: Option<i32>, cached: &AttrValue) -> i32 {
|
||||||
|
refreshed
|
||||||
|
.or_else(|| match cached {
|
||||||
|
AttrValue::Integer(i) => Some(*i),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.unwrap_or(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
|
||||||
|
let path = dbus_path_for_attr(self.attr.name());
|
||||||
|
let signal = SignalEmitter::new(connection, path)?;
|
||||||
|
self.min_value_changed(&signal).await?;
|
||||||
|
self.max_value_changed(&signal).await?;
|
||||||
|
self.scalar_increment_changed(&signal).await?;
|
||||||
|
self.current_value_changed(&signal).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn move_to_zbus(self, connection: &Connection) -> Result<(), RogError> {
|
pub async fn move_to_zbus(self, connection: &Connection) -> Result<(), RogError> {
|
||||||
let path = dbus_path_for_attr(self.attr.name());
|
let path = dbus_path_for_attr(self.attr.name());
|
||||||
connection
|
connection
|
||||||
@@ -117,6 +136,35 @@ impl AsusArmouryAttribute {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct ArmouryAttributeRegistry {
|
||||||
|
attrs: Vec<AsusArmouryAttribute>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArmouryAttributeRegistry {
|
||||||
|
pub fn push(&mut self, attr: AsusArmouryAttribute) {
|
||||||
|
self.attrs.push(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn emit_limits(&self, connection: &Connection) -> Result<(), RogError> {
|
||||||
|
let mut last_err: Option<RogError> = None;
|
||||||
|
for attr in &self.attrs {
|
||||||
|
if let Err(e) = attr.emit_limits(connection).await {
|
||||||
|
error!(
|
||||||
|
"Failed to emit updated limits for attribute '{}': {e:?}",
|
||||||
|
attr.attribute_name()
|
||||||
|
);
|
||||||
|
last_err = Some(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(err) = last_err {
|
||||||
|
Err(err)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl crate::Reloadable for AsusArmouryAttribute {
|
impl crate::Reloadable for AsusArmouryAttribute {
|
||||||
async fn reload(&mut self) -> Result<(), RogError> {
|
async fn reload(&mut self) -> Result<(), RogError> {
|
||||||
info!("Reloading {}", self.attr.name());
|
info!("Reloading {}", self.attr.name());
|
||||||
@@ -256,26 +304,20 @@ impl AsusArmouryAttribute {
|
|||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
async fn min_value(&self) -> i32 {
|
async fn min_value(&self) -> i32 {
|
||||||
match self.attr.min_value() {
|
Self::resolve_i32_value(self.attr.refresh_min_value(), self.attr.min_value())
|
||||||
AttrValue::Integer(i) => *i,
|
|
||||||
_ => -1,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
async fn max_value(&self) -> i32 {
|
async fn max_value(&self) -> i32 {
|
||||||
match self.attr.max_value() {
|
Self::resolve_i32_value(self.attr.refresh_max_value(), self.attr.max_value())
|
||||||
AttrValue::Integer(i) => *i,
|
|
||||||
_ => -1,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
async fn scalar_increment(&self) -> i32 {
|
async fn scalar_increment(&self) -> i32 {
|
||||||
match self.attr.scalar_increment() {
|
Self::resolve_i32_value(
|
||||||
AttrValue::Integer(i) => *i,
|
self.attr.refresh_scalar_increment(),
|
||||||
_ => -1,
|
self.attr.scalar_increment(),
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[zbus(property)]
|
#[zbus(property)]
|
||||||
@@ -393,7 +435,8 @@ pub async fn start_attributes_zbus(
|
|||||||
power: AsusPower,
|
power: AsusPower,
|
||||||
attributes: FirmwareAttributes,
|
attributes: FirmwareAttributes,
|
||||||
config: Arc<Mutex<Config>>,
|
config: Arc<Mutex<Config>>,
|
||||||
) -> Result<(), RogError> {
|
) -> Result<ArmouryAttributeRegistry, RogError> {
|
||||||
|
let mut registry = ArmouryAttributeRegistry::default();
|
||||||
for attr in attributes.attributes() {
|
for attr in attributes.attributes() {
|
||||||
let mut attr = AsusArmouryAttribute::new(
|
let mut attr = AsusArmouryAttribute::new(
|
||||||
attr.clone(),
|
attr.clone(),
|
||||||
@@ -402,6 +445,8 @@ pub async fn start_attributes_zbus(
|
|||||||
config.clone(),
|
config.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let registry_attr = attr.clone();
|
||||||
|
|
||||||
if let Err(e) = attr.reload().await {
|
if let Err(e) = attr.reload().await {
|
||||||
error!(
|
error!(
|
||||||
"Skipping attribute '{}' due to reload error: {e:?}",
|
"Skipping attribute '{}' due to reload error: {e:?}",
|
||||||
@@ -430,9 +475,12 @@ pub async fn start_attributes_zbus(
|
|||||||
|
|
||||||
if let Err(e) = attr.move_to_zbus(conn).await {
|
if let Err(e) = attr.move_to_zbus(conn).await {
|
||||||
error!("Failed to register attribute '{attr_name}' on zbus: {e:?}");
|
error!("Failed to register attribute '{attr_name}' on zbus: {e:?}");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registry.push(registry_attr);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_config_or_default(
|
pub async fn set_config_or_default(
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use zbus::fdo::Error as FdoErr;
|
|||||||
use zbus::object_server::SignalEmitter;
|
use zbus::object_server::SignalEmitter;
|
||||||
use zbus::{interface, Connection};
|
use zbus::{interface, Connection};
|
||||||
|
|
||||||
use crate::asus_armoury::set_config_or_default;
|
use crate::asus_armoury::{set_config_or_default, ArmouryAttributeRegistry};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::error::RogError;
|
use crate::error::RogError;
|
||||||
use crate::{task_watch_item, CtrlTask, ReloadAndNotify};
|
use crate::{task_watch_item, CtrlTask, ReloadAndNotify};
|
||||||
@@ -46,6 +46,8 @@ pub struct CtrlPlatform {
|
|||||||
attributes: FirmwareAttributes,
|
attributes: FirmwareAttributes,
|
||||||
cpu_control: Option<CPUControl>,
|
cpu_control: Option<CPUControl>,
|
||||||
config: Arc<Mutex<Config>>,
|
config: Arc<Mutex<Config>>,
|
||||||
|
connection: Connection,
|
||||||
|
armoury_registry: ArmouryAttributeRegistry,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CtrlPlatform {
|
impl CtrlPlatform {
|
||||||
@@ -56,6 +58,8 @@ impl CtrlPlatform {
|
|||||||
config: Arc<Mutex<Config>>,
|
config: Arc<Mutex<Config>>,
|
||||||
config_path: &Path,
|
config_path: &Path,
|
||||||
signal_context: SignalEmitter<'static>,
|
signal_context: SignalEmitter<'static>,
|
||||||
|
connection: Connection,
|
||||||
|
armoury_registry: ArmouryAttributeRegistry,
|
||||||
) -> Result<Self, RogError> {
|
) -> Result<Self, RogError> {
|
||||||
let config1 = config.clone();
|
let config1 = config.clone();
|
||||||
let config_path = config_path.to_owned();
|
let config_path = config_path.to_owned();
|
||||||
@@ -68,6 +72,8 @@ impl CtrlPlatform {
|
|||||||
cpu_control: CPUControl::new()
|
cpu_control: CPUControl::new()
|
||||||
.map_err(|e| error!("Couldn't get CPU control sysfs: {e}"))
|
.map_err(|e| error!("Couldn't get CPU control sysfs: {e}"))
|
||||||
.ok(),
|
.ok(),
|
||||||
|
connection,
|
||||||
|
armoury_registry,
|
||||||
};
|
};
|
||||||
let mut inotify_self = ret_self.clone();
|
let mut inotify_self = ret_self.clone();
|
||||||
|
|
||||||
@@ -729,6 +735,31 @@ impl CtrlTask for CtrlPlatform {
|
|||||||
}
|
}
|
||||||
if !sleeping {
|
if !sleeping {
|
||||||
platform1.run_ac_or_bat_cmd(power_plugged > 0).await;
|
platform1.run_ac_or_bat_cmd(power_plugged > 0).await;
|
||||||
|
if let Ok(profile) =
|
||||||
|
platform1.platform.get_platform_profile().map(|p| p.into())
|
||||||
|
{
|
||||||
|
let attrs = FirmwareAttributes::new();
|
||||||
|
{
|
||||||
|
let mut cfg = platform1.config.lock().await;
|
||||||
|
set_config_or_default(
|
||||||
|
&attrs,
|
||||||
|
&mut *cfg,
|
||||||
|
power_plugged > 0,
|
||||||
|
profile,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
if let Err(e) = platform1
|
||||||
|
.armoury_registry
|
||||||
|
.emit_limits(&platform1.connection)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
error!(
|
||||||
|
"Failed to emit armoury updates after power change: \
|
||||||
|
{e:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
platform1.config.lock().await.last_power_plugged = power_plugged;
|
platform1.config.lock().await.last_power_plugged = power_plugged;
|
||||||
}
|
}
|
||||||
@@ -789,13 +820,17 @@ impl CtrlTask for CtrlPlatform {
|
|||||||
{
|
{
|
||||||
// TODO: manage this better, shouldn't need to create every time
|
// TODO: manage this better, shouldn't need to create every time
|
||||||
let attrs = FirmwareAttributes::new();
|
let attrs = FirmwareAttributes::new();
|
||||||
set_config_or_default(
|
{
|
||||||
&attrs,
|
let mut cfg = platform3.config.lock().await;
|
||||||
&mut *platform3.config.lock().await,
|
set_config_or_default(&attrs, &mut *cfg, power_plugged, profile).await;
|
||||||
power_plugged,
|
}
|
||||||
profile,
|
if let Err(e) = platform3
|
||||||
)
|
.armoury_registry
|
||||||
.await;
|
.emit_limits(&platform3.connection)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
error!("Failed to emit armoury updates after AC/DC toggle: {e:?}");
|
||||||
|
}
|
||||||
platform3
|
platform3
|
||||||
.enable_ppt_group_changed(&signal_ctxt_copy)
|
.enable_ppt_group_changed(&signal_ctxt_copy)
|
||||||
.await
|
.await
|
||||||
@@ -852,6 +887,9 @@ impl CtrlTask for CtrlPlatform {
|
|||||||
profile,
|
profile,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
if let Err(e) = ctrl.armoury_registry.emit_limits(&ctrl.connection).await {
|
||||||
|
error!("Failed to emit armoury updates after profile change: {e:?}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::error::Error;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ::zbus::Connection;
|
use ::zbus::Connection;
|
||||||
use asusd::asus_armoury::start_attributes_zbus;
|
use asusd::asus_armoury::{start_attributes_zbus, ArmouryAttributeRegistry};
|
||||||
use asusd::aura_manager::DeviceManager;
|
use asusd::aura_manager::DeviceManager;
|
||||||
use asusd::config::Config;
|
use asusd::config::Config;
|
||||||
use asusd::ctrl_backlight::CtrlBacklight;
|
use asusd::ctrl_backlight::CtrlBacklight;
|
||||||
@@ -74,7 +74,7 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
let platform = RogPlatform::new()?; // TODO: maybe needs async mutex?
|
let platform = RogPlatform::new()?; // TODO: maybe needs async mutex?
|
||||||
let power = AsusPower::new()?; // TODO: maybe needs async mutex?
|
let power = AsusPower::new()?; // TODO: maybe needs async mutex?
|
||||||
let attributes = FirmwareAttributes::new();
|
let attributes = FirmwareAttributes::new();
|
||||||
if let Err(e) = start_attributes_zbus(
|
let armoury_registry = match start_attributes_zbus(
|
||||||
&server,
|
&server,
|
||||||
platform.clone(),
|
platform.clone(),
|
||||||
power.clone(),
|
power.clone(),
|
||||||
@@ -83,8 +83,12 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
error!("Failed to initialize firmware attributes over zbus: {e:?}");
|
Ok(registry) => registry,
|
||||||
}
|
Err(e) => {
|
||||||
|
error!("Failed to initialize firmware attributes over zbus: {e:?}");
|
||||||
|
ArmouryAttributeRegistry::default()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match CtrlFanCurveZbus::new() {
|
match CtrlFanCurveZbus::new() {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
@@ -113,6 +117,8 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
config.clone(),
|
config.clone(),
|
||||||
&cfg_path,
|
&cfg_path,
|
||||||
CtrlPlatform::signal_context(&server)?,
|
CtrlPlatform::signal_context(&server)?,
|
||||||
|
server.clone(),
|
||||||
|
armoury_registry,
|
||||||
) {
|
) {
|
||||||
Ok(ctrl) => {
|
Ok(ctrl) => {
|
||||||
let sig_ctx = CtrlPlatform::signal_context(&server)?;
|
let sig_ctx = CtrlPlatform::signal_context(&server)?;
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SystemPageData.ppt_pl1_spl.current != -1 || SystemPageData.ppt_pl2_sppt.current != -1 || SystemPageData.ppt_pl3_fppt.current != -1 || SystemPageData.ppt_fppt.current != -1 || SystemPageData.ppt_apu_sppt.current != -1 || SystemPageData.nv_temp_target.current != -1 || SystemPageData.nv_dynamic_boost.current != -1: HorizontalLayout {
|
if (SystemPageData.ppt_pl1_spl.max > 0 && SystemPageData.ppt_pl1_spl.current != -1) || (SystemPageData.ppt_pl2_sppt.max > 0 && SystemPageData.ppt_pl2_sppt.current != -1) || (SystemPageData.ppt_pl3_fppt.max > 0 && SystemPageData.ppt_pl3_fppt.current != -1) || (SystemPageData.ppt_fppt.max > 0 && SystemPageData.ppt_fppt.current != -1) || (SystemPageData.ppt_apu_sppt.max > 0 && SystemPageData.ppt_apu_sppt.current != -1) || (SystemPageData.nv_temp_target.max > 0 && SystemPageData.nv_temp_target.current != -1) || (SystemPageData.nv_dynamic_boost.max > 0 && SystemPageData.nv_dynamic_boost.current != -1): HorizontalLayout {
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
alignment: LayoutAlignment.space-between;
|
alignment: LayoutAlignment.space-between;
|
||||||
@@ -331,7 +331,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SystemPageData.ppt_pl1_spl.current != -1: SystemSlider {
|
if SystemPageData.ppt_pl1_spl.max > 0 && SystemPageData.ppt_pl1_spl.current != -1: SystemSlider {
|
||||||
text: @tr("ppt_pl1_spl" => "CPU Sustained Power Limit");
|
text: @tr("ppt_pl1_spl" => "CPU Sustained Power Limit");
|
||||||
title: @tr("ppt_pl1_spl" => "CPU Sustained Power Limit");
|
title: @tr("ppt_pl1_spl" => "CPU Sustained Power Limit");
|
||||||
help_text: @tr("ppt_pl1_spl_help" => "Long-term CPU power limit that affects sustained workload performance. Higher values may increase heat and power consumption.");
|
help_text: @tr("ppt_pl1_spl_help" => "Long-term CPU power limit that affects sustained workload performance. Higher values may increase heat and power consumption.");
|
||||||
@@ -349,7 +349,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SystemPageData.ppt_pl2_sppt.current != -1: SystemSlider {
|
if SystemPageData.ppt_pl2_sppt.max > 0 && SystemPageData.ppt_pl2_sppt.current != -1: SystemSlider {
|
||||||
text: @tr("ppt_pl2_sppt" => "CPU Turbo Power Limit");
|
text: @tr("ppt_pl2_sppt" => "CPU Turbo Power Limit");
|
||||||
title: @tr("ppt_pl2_sppt" => "CPU Turbo Power Limit");
|
title: @tr("ppt_pl2_sppt" => "CPU Turbo Power Limit");
|
||||||
help_text: @tr("ppt_pl2_sppt_help" => "Short-term CPU power limit for boost periods. Controls maximum power during brief high-performance bursts.");
|
help_text: @tr("ppt_pl2_sppt_help" => "Short-term CPU power limit for boost periods. Controls maximum power during brief high-performance bursts.");
|
||||||
@@ -367,7 +367,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SystemPageData.ppt_pl3_fppt.current != -1: SystemSlider {
|
if SystemPageData.ppt_pl3_fppt.max > 0 && SystemPageData.ppt_pl3_fppt.current != -1: SystemSlider {
|
||||||
text: @tr("ppt_pl3_fppt" => "CPU Fast Burst Power Limit");
|
text: @tr("ppt_pl3_fppt" => "CPU Fast Burst Power Limit");
|
||||||
title: @tr("ppt_pl3_fppt" => "CPU Fast Burst Power Limit");
|
title: @tr("ppt_pl3_fppt" => "CPU Fast Burst Power Limit");
|
||||||
help_text: @tr("ppt_pl3_fppt_help" => "Ultra-short duration power limit for instantaneous CPU bursts. Affects responsiveness during sudden workload spikes.");
|
help_text: @tr("ppt_pl3_fppt_help" => "Ultra-short duration power limit for instantaneous CPU bursts. Affects responsiveness during sudden workload spikes.");
|
||||||
@@ -384,7 +384,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
SystemPageData.cb_ppt_pl3_fppt(Math.round(value));
|
SystemPageData.cb_ppt_pl3_fppt(Math.round(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if SystemPageData.ppt_fppt.current != -1: SystemSlider {
|
if SystemPageData.ppt_fppt.max > 0 && SystemPageData.ppt_fppt.current != -1: SystemSlider {
|
||||||
text: @tr("ppt_fppt" => "Fast Package Power Limit");
|
text: @tr("ppt_fppt" => "Fast Package Power Limit");
|
||||||
title: @tr("ppt_fppt" => "Fast Package Power Limit");
|
title: @tr("ppt_fppt" => "Fast Package Power Limit");
|
||||||
help_text: @tr("ppt_fppt_help" => "Ultra-short duration power limit for system package. Controls maximum power during millisecond-scale load spikes.");
|
help_text: @tr("ppt_fppt_help" => "Ultra-short duration power limit for system package. Controls maximum power during millisecond-scale load spikes.");
|
||||||
@@ -402,7 +402,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SystemPageData.ppt_apu_sppt.current != -1: SystemSlider {
|
if SystemPageData.ppt_apu_sppt.max > 0 && SystemPageData.ppt_apu_sppt.current != -1: SystemSlider {
|
||||||
text: @tr("ppt_apu_sppt" => "APU Sustained Power Limit");
|
text: @tr("ppt_apu_sppt" => "APU Sustained Power Limit");
|
||||||
title: @tr("ppt_apu_sppt" => "APU Sustained Power Limit");
|
title: @tr("ppt_apu_sppt" => "APU Sustained Power Limit");
|
||||||
help_text: @tr("ppt_apu_sppt_help" => "Long-term power limit for integrated graphics and CPU combined. Affects sustained performance of APU-based workloads.");
|
help_text: @tr("ppt_apu_sppt_help" => "Long-term power limit for integrated graphics and CPU combined. Affects sustained performance of APU-based workloads.");
|
||||||
@@ -420,7 +420,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SystemPageData.ppt_platform_sppt.current != -1: SystemSlider {
|
if SystemPageData.ppt_platform_sppt.max > 0 && SystemPageData.ppt_platform_sppt.current != -1: SystemSlider {
|
||||||
text: @tr("ppt_platform_sppt" => "Platform Sustained Power Limit");
|
text: @tr("ppt_platform_sppt" => "Platform Sustained Power Limit");
|
||||||
title: @tr("ppt_platform_sppt" => "Platform Sustained Power Limit");
|
title: @tr("ppt_platform_sppt" => "Platform Sustained Power Limit");
|
||||||
help_text: @tr("ppt_platform_sppt_help" => "Overall system power limit for sustained operations. Controls total platform power consumption over extended periods.");
|
help_text: @tr("ppt_platform_sppt_help" => "Overall system power limit for sustained operations. Controls total platform power consumption over extended periods.");
|
||||||
@@ -438,7 +438,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SystemPageData.nv_dynamic_boost.current != -1: SystemSlider {
|
if SystemPageData.nv_dynamic_boost.max > 0 && SystemPageData.nv_dynamic_boost.current != -1: SystemSlider {
|
||||||
text: @tr("nv_dynamic_boost" => "GPU Power Boost");
|
text: @tr("nv_dynamic_boost" => "GPU Power Boost");
|
||||||
title: @tr("nv_dynamic_boost" => "GPU Power Boost");
|
title: @tr("nv_dynamic_boost" => "GPU Power Boost");
|
||||||
help_text: @tr("nv_dynamic_boost_help" => "Additional power allocation for GPU dynamic boost. Higher values increase GPU performance but generate more heat.");
|
help_text: @tr("nv_dynamic_boost_help" => "Additional power allocation for GPU dynamic boost. Higher values increase GPU performance but generate more heat.");
|
||||||
@@ -456,7 +456,7 @@ export component PageSystem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SystemPageData.nv_temp_target.current != -1: SystemSlider {
|
if SystemPageData.nv_temp_target.max > 0 && SystemPageData.nv_temp_target.current != -1: SystemSlider {
|
||||||
text: @tr("nv_temp_target" => "GPU Temperature Limit");
|
text: @tr("nv_temp_target" => "GPU Temperature Limit");
|
||||||
title: @tr("nv_temp_target" => "GPU Temperature Limit");
|
title: @tr("nv_temp_target" => "GPU Temperature Limit");
|
||||||
help_text: @tr("nv_temp_target_help" => "Maximum GPU temperature threshold in Celsius. GPU will throttle to maintain temperature below this limit.");
|
help_text: @tr("nv_temp_target_help" => "Maximum GPU temperature threshold in Celsius. GPU will throttle to maintain temperature below this limit.");
|
||||||
|
|||||||
@@ -124,6 +124,22 @@ impl Attribute {
|
|||||||
&self.scalar_increment
|
&self.scalar_increment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_attr_i32(&self, name: &str) -> Option<i32> {
|
||||||
|
read_i32(&self.base_path.join(name)).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refresh_min_value(&self) -> Option<i32> {
|
||||||
|
self.read_attr_i32("min_value")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refresh_max_value(&self) -> Option<i32> {
|
||||||
|
self.read_attr_i32("max_value")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refresh_scalar_increment(&self) -> Option<i32> {
|
||||||
|
self.read_attr_i32("scalar_increment")
|
||||||
|
}
|
||||||
|
|
||||||
/// Read all the immutable values to struct data. These should *never*
|
/// Read all the immutable values to struct data. These should *never*
|
||||||
/// change, if they do then it is possibly a driver issue - although this is
|
/// change, if they do then it is possibly a driver issue - although this is
|
||||||
/// subject to `firmware_attributes` class changes in kernel.
|
/// subject to `firmware_attributes` class changes in kernel.
|
||||||
|
|||||||
Reference in New Issue
Block a user