mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-01-22 09:23:19 +01:00
Merge branch 'devel'
This commit is contained in:
@@ -55,6 +55,25 @@ impl AsusArmouryAttribute {
|
||||
String::from(self.attr.name())
|
||||
}
|
||||
|
||||
fn resolve_i32_value(refreshed: Option<i32>, cached: &AttrValue) -> i32 {
|
||||
refreshed
|
||||
.or(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> {
|
||||
let path = dbus_path_for_attr(self.attr.name());
|
||||
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 {
|
||||
async fn reload(&mut self) -> Result<(), RogError> {
|
||||
info!("Reloading {}", self.attr.name());
|
||||
@@ -131,25 +179,31 @@ impl crate::Reloadable for AsusArmouryAttribute {
|
||||
error!("Could not get power status: {e:?}");
|
||||
e
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let config = if power_plugged == 1 {
|
||||
&self.config.lock().await.ac_profile_tunings
|
||||
} else {
|
||||
&self.config.lock().await.dc_profile_tunings
|
||||
.unwrap_or_default()
|
||||
== 1;
|
||||
|
||||
let apply_value = {
|
||||
let config = self.config.lock().await;
|
||||
config
|
||||
.select_tunings_ref(power_plugged, profile)
|
||||
.and_then(|tuning| {
|
||||
if tuning.enabled {
|
||||
tuning.group.get(&self.name()).copied()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
};
|
||||
if let Some(tuning) = config.get(&profile) {
|
||||
if tuning.enabled {
|
||||
if let Some(tune) = tuning.group.get(&self.name()) {
|
||||
self.attr
|
||||
.set_current_value(&AttrValue::Integer(*tune))
|
||||
.map_err(|e| {
|
||||
error!("Could not set {} value: {e:?}", self.attr.name());
|
||||
self.attr.base_path_exists();
|
||||
e
|
||||
})?;
|
||||
info!("Set {} to {:?}", self.attr.name(), tune);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(tune) = apply_value {
|
||||
self.attr
|
||||
.set_current_value(&AttrValue::Integer(tune))
|
||||
.map_err(|e| {
|
||||
error!("Could not set {} value: {e:?}", self.attr.name());
|
||||
self.attr.base_path_exists();
|
||||
e
|
||||
})?;
|
||||
info!("Set {} to {:?}", self.attr.name(), tune);
|
||||
}
|
||||
} else {
|
||||
// Handle non-PPT attributes (boolean and other settings)
|
||||
@@ -256,26 +310,20 @@ impl AsusArmouryAttribute {
|
||||
|
||||
#[zbus(property)]
|
||||
async fn min_value(&self) -> i32 {
|
||||
match self.attr.min_value() {
|
||||
AttrValue::Integer(i) => *i,
|
||||
_ => -1,
|
||||
}
|
||||
Self::resolve_i32_value(self.attr.refresh_min_value(), self.attr.min_value())
|
||||
}
|
||||
|
||||
#[zbus(property)]
|
||||
async fn max_value(&self) -> i32 {
|
||||
match self.attr.max_value() {
|
||||
AttrValue::Integer(i) => *i,
|
||||
_ => -1,
|
||||
}
|
||||
Self::resolve_i32_value(self.attr.refresh_max_value(), self.attr.max_value())
|
||||
}
|
||||
|
||||
#[zbus(property)]
|
||||
async fn scalar_increment(&self) -> i32 {
|
||||
match self.attr.scalar_increment() {
|
||||
AttrValue::Integer(i) => *i,
|
||||
_ => -1,
|
||||
}
|
||||
Self::resolve_i32_value(
|
||||
self.attr.refresh_scalar_increment(),
|
||||
self.attr.scalar_increment(),
|
||||
)
|
||||
}
|
||||
|
||||
#[zbus(property)]
|
||||
@@ -297,12 +345,15 @@ impl AsusArmouryAttribute {
|
||||
error!("Could not get power status: {e:?}");
|
||||
e
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let mut config = self.config.lock().await;
|
||||
let tuning = config.select_tunings(power_plugged == 1, profile);
|
||||
if let Some(tune) = tuning.group.get(&self.name()) {
|
||||
return Ok(*tune);
|
||||
} else if let AttrValue::Integer(i) = self.attr.default_value() {
|
||||
.unwrap_or_default()
|
||||
== 1;
|
||||
let config = self.config.lock().await;
|
||||
if let Some(tuning) = config.select_tunings_ref(power_plugged, profile) {
|
||||
if let Some(tune) = tuning.group.get(&self.name()) {
|
||||
return Ok(*tune);
|
||||
}
|
||||
}
|
||||
if let AttrValue::Integer(i) = self.attr.default_value() {
|
||||
return Ok(*i);
|
||||
}
|
||||
return Err(fdo::Error::Failed(
|
||||
@@ -318,6 +369,83 @@ impl AsusArmouryAttribute {
|
||||
))
|
||||
}
|
||||
|
||||
async fn stored_value_for_power(&self, on_ac: bool) -> fdo::Result<i32> {
|
||||
if !self.name().is_ppt() {
|
||||
return Err(fdo::Error::NotSupported(
|
||||
"Stored values are only available for PPT attributes".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||
let config = self.config.lock().await;
|
||||
if let Some(tuning) = config.select_tunings_ref(on_ac, profile) {
|
||||
if let Some(tune) = tuning.group.get(&self.name()) {
|
||||
return Ok(*tune);
|
||||
}
|
||||
}
|
||||
|
||||
if let AttrValue::Integer(i) = self.attr.default_value() {
|
||||
return Ok(*i);
|
||||
}
|
||||
Err(fdo::Error::Failed(
|
||||
"Could not read stored value".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
async fn set_value_for_power(&mut self, on_ac: bool, value: i32) -> fdo::Result<()> {
|
||||
if !self.name().is_ppt() {
|
||||
return Err(fdo::Error::NotSupported(
|
||||
"Setting stored values is only supported for PPT attributes".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let profile: PlatformProfile = self.platform.get_platform_profile()?.into();
|
||||
let apply_now;
|
||||
|
||||
{
|
||||
let mut config = self.config.lock().await;
|
||||
let tuning = config.select_tunings(on_ac, profile);
|
||||
|
||||
if let Some(tune) = tuning.group.get_mut(&self.name()) {
|
||||
*tune = value;
|
||||
} else {
|
||||
tuning.group.insert(self.name(), value);
|
||||
debug!(
|
||||
"Store {} value for {} power = {}",
|
||||
self.attr.name(),
|
||||
if on_ac { "AC" } else { "DC" },
|
||||
value
|
||||
);
|
||||
}
|
||||
|
||||
apply_now = tuning.enabled;
|
||||
config.write();
|
||||
}
|
||||
|
||||
if apply_now {
|
||||
let power_plugged = self
|
||||
.power
|
||||
.get_online()
|
||||
.map_err(|e| {
|
||||
error!("Could not get power status: {e:?}");
|
||||
e
|
||||
})
|
||||
.unwrap_or_default()
|
||||
!= 0;
|
||||
|
||||
if power_plugged == on_ac {
|
||||
self.attr
|
||||
.set_current_value(&AttrValue::Integer(value))
|
||||
.map_err(|e| {
|
||||
error!("Could not set value: {e:?}");
|
||||
e
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[zbus(property)]
|
||||
async fn set_current_value(&mut self, value: i32) -> fdo::Result<()> {
|
||||
if self.name().is_ppt() {
|
||||
@@ -393,7 +521,8 @@ pub async fn start_attributes_zbus(
|
||||
power: AsusPower,
|
||||
attributes: FirmwareAttributes,
|
||||
config: Arc<Mutex<Config>>,
|
||||
) -> Result<(), RogError> {
|
||||
) -> Result<ArmouryAttributeRegistry, RogError> {
|
||||
let mut registry = ArmouryAttributeRegistry::default();
|
||||
for attr in attributes.attributes() {
|
||||
let mut attr = AsusArmouryAttribute::new(
|
||||
attr.clone(),
|
||||
@@ -402,6 +531,8 @@ pub async fn start_attributes_zbus(
|
||||
config.clone(),
|
||||
);
|
||||
|
||||
let registry_attr = attr.clone();
|
||||
|
||||
if let Err(e) = attr.reload().await {
|
||||
error!(
|
||||
"Skipping attribute '{}' due to reload error: {e:?}",
|
||||
@@ -430,9 +561,12 @@ pub async fn start_attributes_zbus(
|
||||
|
||||
if let Err(e) = attr.move_to_zbus(conn).await {
|
||||
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(
|
||||
|
||||
@@ -67,6 +67,19 @@ impl Config {
|
||||
};
|
||||
config.entry(profile).or_insert_with(Tuning::default)
|
||||
}
|
||||
|
||||
pub fn select_tunings_ref(
|
||||
&self,
|
||||
power_plugged: bool,
|
||||
profile: PlatformProfile,
|
||||
) -> Option<&Tuning> {
|
||||
let config = if power_plugged {
|
||||
&self.ac_profile_tunings
|
||||
} else {
|
||||
&self.dc_profile_tunings
|
||||
};
|
||||
config.get(&profile)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@@ -146,7 +159,7 @@ pub struct Config611 {
|
||||
|
||||
impl From<Config611> for Config {
|
||||
fn from(c: Config611) -> Self {
|
||||
Self {
|
||||
let mut config = Self {
|
||||
// Restore the base charge limit
|
||||
charge_control_end_threshold: c.charge_control_end_threshold,
|
||||
base_charge_control_end_threshold: c.charge_control_end_threshold,
|
||||
@@ -168,7 +181,12 @@ impl From<Config611> for Config {
|
||||
armoury_settings: HashMap::default(),
|
||||
screenpad_gamma: None,
|
||||
screenpad_sync_primary: Default::default(),
|
||||
}
|
||||
};
|
||||
|
||||
config.ac_profile_tunings = c.ac_profile_tunings;
|
||||
config.dc_profile_tunings = c.dc_profile_tunings;
|
||||
config.armoury_settings = c.armoury_settings;
|
||||
config
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use zbus::fdo::Error as FdoErr;
|
||||
use zbus::object_server::SignalEmitter;
|
||||
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::error::RogError;
|
||||
use crate::{task_watch_item, CtrlTask, ReloadAndNotify};
|
||||
@@ -46,6 +46,8 @@ pub struct CtrlPlatform {
|
||||
attributes: FirmwareAttributes,
|
||||
cpu_control: Option<CPUControl>,
|
||||
config: Arc<Mutex<Config>>,
|
||||
connection: Connection,
|
||||
armoury_registry: ArmouryAttributeRegistry,
|
||||
}
|
||||
|
||||
impl CtrlPlatform {
|
||||
@@ -56,6 +58,8 @@ impl CtrlPlatform {
|
||||
config: Arc<Mutex<Config>>,
|
||||
config_path: &Path,
|
||||
signal_context: SignalEmitter<'static>,
|
||||
connection: Connection,
|
||||
armoury_registry: ArmouryAttributeRegistry,
|
||||
) -> Result<Self, RogError> {
|
||||
let config1 = config.clone();
|
||||
let config_path = config_path.to_owned();
|
||||
@@ -68,6 +72,8 @@ impl CtrlPlatform {
|
||||
cpu_control: CPUControl::new()
|
||||
.map_err(|e| error!("Couldn't get CPU control sysfs: {e}"))
|
||||
.ok(),
|
||||
connection,
|
||||
armoury_registry,
|
||||
};
|
||||
let mut inotify_self = ret_self.clone();
|
||||
|
||||
@@ -729,6 +735,31 @@ impl CtrlTask for CtrlPlatform {
|
||||
}
|
||||
if !sleeping {
|
||||
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;
|
||||
}
|
||||
@@ -789,13 +820,17 @@ impl CtrlTask for CtrlPlatform {
|
||||
{
|
||||
// TODO: manage this better, shouldn't need to create every time
|
||||
let attrs = FirmwareAttributes::new();
|
||||
set_config_or_default(
|
||||
&attrs,
|
||||
&mut *platform3.config.lock().await,
|
||||
power_plugged,
|
||||
profile,
|
||||
)
|
||||
.await;
|
||||
{
|
||||
let mut cfg = platform3.config.lock().await;
|
||||
set_config_or_default(&attrs, &mut cfg, power_plugged, profile).await;
|
||||
}
|
||||
if let Err(e) = platform3
|
||||
.armoury_registry
|
||||
.emit_limits(&platform3.connection)
|
||||
.await
|
||||
{
|
||||
error!("Failed to emit armoury updates after AC/DC toggle: {e:?}");
|
||||
}
|
||||
platform3
|
||||
.enable_ppt_group_changed(&signal_ctxt_copy)
|
||||
.await
|
||||
@@ -852,6 +887,9 @@ impl CtrlTask for CtrlPlatform {
|
||||
profile,
|
||||
)
|
||||
.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 ::zbus::Connection;
|
||||
use asusd::asus_armoury::start_attributes_zbus;
|
||||
use asusd::asus_armoury::{start_attributes_zbus, ArmouryAttributeRegistry};
|
||||
use asusd::aura_manager::DeviceManager;
|
||||
use asusd::config::Config;
|
||||
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 power = AsusPower::new()?; // TODO: maybe needs async mutex?
|
||||
let attributes = FirmwareAttributes::new();
|
||||
if let Err(e) = start_attributes_zbus(
|
||||
let armoury_registry = match start_attributes_zbus(
|
||||
&server,
|
||||
platform.clone(),
|
||||
power.clone(),
|
||||
@@ -83,8 +83,12 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
)
|
||||
.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() {
|
||||
Ok(ctrl) => {
|
||||
@@ -113,6 +117,8 @@ async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||
config.clone(),
|
||||
&cfg_path,
|
||||
CtrlPlatform::signal_context(&server)?,
|
||||
server.clone(),
|
||||
armoury_registry,
|
||||
) {
|
||||
Ok(ctrl) => {
|
||||
let sig_ctx = CtrlPlatform::signal_context(&server)?;
|
||||
|
||||
@@ -169,7 +169,7 @@ impl AnimeImage {
|
||||
// first 5 rows for GA401 are always at X = 0
|
||||
return 0;
|
||||
}
|
||||
(y + 1) / 2 - 3
|
||||
y.div_ceil(2) - 3
|
||||
}
|
||||
AnimeType::GU604 => {
|
||||
// first 9 rows start at zero
|
||||
@@ -185,7 +185,7 @@ impl AnimeImage {
|
||||
return 0;
|
||||
}
|
||||
// and then their offset grows by one every two rows
|
||||
(y + 1) / 2 - 5
|
||||
y.div_ceil(2) - 5
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ impl AnimeImage {
|
||||
// First 5 rows for GA401 are always 33 physical LEDs long
|
||||
return 33;
|
||||
}
|
||||
36 - (y + 1) / 2
|
||||
36 - y.div_ceil(2)
|
||||
}
|
||||
AnimeType::GU604 => {
|
||||
if y <= 9 {
|
||||
|
||||
@@ -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-left: 10px;
|
||||
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");
|
||||
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.");
|
||||
@@ -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");
|
||||
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.");
|
||||
@@ -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");
|
||||
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.");
|
||||
@@ -384,7 +384,7 @@ export component PageSystem inherits Rectangle {
|
||||
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");
|
||||
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.");
|
||||
@@ -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");
|
||||
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.");
|
||||
@@ -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");
|
||||
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.");
|
||||
@@ -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");
|
||||
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.");
|
||||
@@ -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");
|
||||
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.");
|
||||
|
||||
@@ -124,6 +124,22 @@ impl Attribute {
|
||||
&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*
|
||||
/// change, if they do then it is possibly a driver issue - although this is
|
||||
/// subject to `firmware_attributes` class changes in kernel.
|
||||
|
||||
@@ -37,8 +37,9 @@ pub fn find_fan_curve_node() -> Result<Device, ProfileError> {
|
||||
derive(Type, Value, OwnedValue),
|
||||
zvariant(signature = "s")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize, Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
#[derive(Default, Deserialize, Serialize, Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum FanCurvePU {
|
||||
#[default]
|
||||
CPU = 0,
|
||||
GPU = 1,
|
||||
MID = 2,
|
||||
@@ -100,12 +101,6 @@ impl std::str::FromStr for FanCurvePU {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FanCurvePU {
|
||||
fn default() -> Self {
|
||||
Self::CPU
|
||||
}
|
||||
}
|
||||
|
||||
/// Main purpose of `FanCurves` is to enable restoring state on system boot
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||
|
||||
@@ -158,7 +158,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
canvas.set_draw_color(Color::RGB(*b, *b, *b));
|
||||
|
||||
let x: i32 = w + x_count as i32 * w
|
||||
- if (y_count + y_offset as usize) % 2 != 0 {
|
||||
- if !(y_count + y_offset as usize).is_multiple_of(2) {
|
||||
0
|
||||
} else {
|
||||
w / 2
|
||||
|
||||
Reference in New Issue
Block a user