Add Steam Deck max clock detection since OC can now be reported correctly
version 2.0.0-alpha3
This commit is contained in:
parent
1a4bfb9669
commit
3e3e9a68f4
9 changed files with 536 additions and 125 deletions
2
backend/Cargo.lock
generated
2
backend/Cargo.lock
generated
|
@ -1170,7 +1170,7 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
|||
|
||||
[[package]]
|
||||
name = "powertools"
|
||||
version = "2.0.0-alpha2"
|
||||
version = "2.0.0-alpha3"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "powertools"
|
||||
version = "2.0.0-alpha2"
|
||||
version = "2.0.0-alpha3"
|
||||
edition = "2021"
|
||||
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
|
||||
description = "Backend (superuser) functionality for PowerTools"
|
||||
|
|
|
@ -77,16 +77,16 @@ impl Default for Base {
|
|||
},
|
||||
limits: super::Limits {
|
||||
cpu: super::Limit {
|
||||
provider: super::CpuLimitType::SteamDeck,
|
||||
limits: super::GenericCpusLimit::default_for(super::CpuLimitType::SteamDeck),
|
||||
provider: super::CpuLimitType::SteamDeckOLED,
|
||||
limits: super::GenericCpusLimit::default_for(super::CpuLimitType::SteamDeckOLED),
|
||||
},
|
||||
gpu: super::Limit {
|
||||
provider: super::GpuLimitType::SteamDeck,
|
||||
provider: super::GpuLimitType::SteamDeckOLED,
|
||||
limits: super::GenericGpuLimit::default_for(super::GpuLimitType::SteamDeckOLED),
|
||||
},
|
||||
battery: super::Limit {
|
||||
provider: super::BatteryLimitType::SteamDeck,
|
||||
limits: super::GenericBatteryLimit::default_for(super::BatteryLimitType::SteamDeck),
|
||||
provider: super::BatteryLimitType::SteamDeckOLED,
|
||||
limits: super::GenericBatteryLimit::default_for(super::BatteryLimitType::SteamDeckOLED),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -93,13 +93,14 @@ pub struct GenericCpuLimit {
|
|||
pub tdp_divisor: Option<u64>,
|
||||
pub tdp_step: Option<u64>,
|
||||
pub skip_resume_reclock: bool,
|
||||
pub experiments: bool,
|
||||
pub extras: super::LimitExtras,
|
||||
}
|
||||
|
||||
impl GenericCpuLimit {
|
||||
pub fn default_for(t: &CpuLimitType, _index: usize) -> Self {
|
||||
match t {
|
||||
CpuLimitType::SteamDeck | CpuLimitType::SteamDeckOLED => Self::default_steam_deck(),
|
||||
CpuLimitType::SteamDeck => Self::default_steam_deck(),
|
||||
CpuLimitType::SteamDeckOLED => Self::default_steam_deck_oled(),
|
||||
CpuLimitType::DevMode => Self {
|
||||
clock_min: Some(RangeLimit { min: Some(100), max: Some(5000) }),
|
||||
clock_max: Some(RangeLimit { min: Some(100), max: Some(4800) }),
|
||||
|
@ -109,7 +110,7 @@ impl GenericCpuLimit {
|
|||
tdp_divisor: Some(1_000_000),
|
||||
tdp_step: Some(1),
|
||||
skip_resume_reclock: false,
|
||||
experiments: true,
|
||||
extras: Default::default(),
|
||||
},
|
||||
_ => Self {
|
||||
clock_min: None,
|
||||
|
@ -120,7 +121,7 @@ impl GenericCpuLimit {
|
|||
tdp_divisor: None,
|
||||
tdp_step: None,
|
||||
skip_resume_reclock: false,
|
||||
experiments: false,
|
||||
extras: Default::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +142,32 @@ impl GenericCpuLimit {
|
|||
tdp_divisor: None,
|
||||
tdp_step: None,
|
||||
skip_resume_reclock: false,
|
||||
experiments: false,
|
||||
extras: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_steam_deck_oled() -> Self {
|
||||
Self {
|
||||
clock_min: Some(RangeLimit {
|
||||
min: Some(1400),
|
||||
max: Some(3500),
|
||||
}),
|
||||
clock_max: Some(RangeLimit {
|
||||
min: Some(400),
|
||||
max: Some(3500),
|
||||
}),
|
||||
clock_step: Some(100),
|
||||
tdp: None,
|
||||
tdp_boost: None,
|
||||
tdp_divisor: None,
|
||||
tdp_step: None,
|
||||
skip_resume_reclock: false,
|
||||
extras: super::LimitExtras {
|
||||
experiments: false,
|
||||
quirks: vec![
|
||||
"clock-autodetect".to_owned(),
|
||||
].into_iter().collect()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,6 +191,6 @@ impl GenericCpuLimit {
|
|||
}
|
||||
self.clock_step = limit_override.clock_step;
|
||||
self.skip_resume_reclock = limit_override.skip_resume_reclock;
|
||||
self.experiments = limit_override.experiments;
|
||||
self.extras = limit_override.extras;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ impl GenericGpuLimit {
|
|||
fn default_steam_deck_oled() -> Self {
|
||||
let mut sd = Self::default_steam_deck();
|
||||
sd.memory_clock_step = Some(200);
|
||||
sd.extras.quirks.insert("clock-autodetect".to_owned());
|
||||
sd
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -102,6 +102,9 @@ impl Cpus {
|
|||
|
||||
pub fn variant(mut self, model: super::Model) -> Self {
|
||||
self.variant = model;
|
||||
for cpu in self.cpus.iter_mut() {
|
||||
cpu.variant(model)
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +128,12 @@ impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
|||
}
|
||||
}
|
||||
let new_cpu = if let Some(cpu_limit) = limits.cpus.get(i) {
|
||||
Cpu::from_json_and_limits(cpu, version, i, cpu_limit.to_owned())
|
||||
let mut cpu_limit_clone = cpu_limit.to_owned();
|
||||
for item in &limits.extras.quirks {
|
||||
cpu_limit_clone.extras.quirks.insert(item.to_owned());
|
||||
}
|
||||
cpu_limit_clone.extras.experiments |= limits.extras.experiments;
|
||||
Cpu::from_json_and_limits(cpu, version, i, cpu_limit_clone)
|
||||
} else {
|
||||
Cpu::from_json(cpu, version, i)
|
||||
};
|
||||
|
@ -262,6 +270,7 @@ pub struct Cpu {
|
|||
index: usize,
|
||||
state: crate::state::steam_deck::Cpu,
|
||||
sysfs: BasicEntityPath,
|
||||
variant: super::Model,
|
||||
}
|
||||
|
||||
//const CPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage";
|
||||
|
@ -289,6 +298,7 @@ impl Cpu {
|
|||
index: i,
|
||||
state: crate::state::steam_deck::Cpu::default(),
|
||||
sysfs: Self::find_card_sysfs(other.root),
|
||||
variant: super::Model::LCD,
|
||||
},
|
||||
_ => Self {
|
||||
online: other.online,
|
||||
|
@ -298,6 +308,7 @@ impl Cpu {
|
|||
index: i,
|
||||
state: crate::state::steam_deck::Cpu::default(),
|
||||
sysfs: Self::find_card_sysfs(other.root),
|
||||
variant: super::Model::LCD,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -341,6 +352,19 @@ impl Cpu {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_max_cpu_clock(&self) -> u64 {
|
||||
if !(self.limits.extras.experiments || self.limits.extras.quirks.contains("clock-autodetect")) {
|
||||
return MAX_CLOCK;
|
||||
}
|
||||
if let super::Model::OLED = self.variant {
|
||||
if let Ok(freq_khz) = usdpl_back::api::files::read_single::<_, u64, _>(cpu_max_clock_path(self.index)) {
|
||||
log::debug!("Detected CPU max clock of {}KHz", freq_khz);
|
||||
return freq_khz / 1000
|
||||
}
|
||||
}
|
||||
MAX_CLOCK
|
||||
}
|
||||
|
||||
fn set_clock_limit(
|
||||
&self,
|
||||
index: usize,
|
||||
|
@ -591,6 +615,7 @@ impl Cpu {
|
|||
index: cpu_index,
|
||||
state: crate::state::steam_deck::Cpu::default(),
|
||||
sysfs: Self::find_card_sysfs(None::<&'static str>),
|
||||
variant: super::Model::LCD,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,14 +627,15 @@ impl Cpu {
|
|||
}
|
||||
|
||||
fn limits(&self) -> crate::api::CpuLimits {
|
||||
let max_cpu_clock = self.read_max_cpu_clock();
|
||||
crate::api::CpuLimits {
|
||||
clock_min_limits: Some(RangeLimit {
|
||||
min: range_min_or_fallback(&self.limits.clock_max, MIN_MAX_CLOCK), // allows min to be set by max (it's weird, blame the kernel)
|
||||
max: range_max_or_fallback(&self.limits.clock_min, MAX_CLOCK),
|
||||
max: range_max_or_fallback(&self.limits.clock_min, max_cpu_clock),
|
||||
}),
|
||||
clock_max_limits: Some(RangeLimit {
|
||||
min: range_min_or_fallback(&self.limits.clock_max, MIN_MAX_CLOCK),
|
||||
max: range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK),
|
||||
max: range_max_or_fallback(&self.limits.clock_max, max_cpu_clock),
|
||||
}),
|
||||
clock_step: self.limits.clock_step.unwrap_or(CLOCK_STEP),
|
||||
governors: self.governors(),
|
||||
|
@ -628,6 +654,10 @@ impl Cpu {
|
|||
};
|
||||
gov_str.split(' ').map(|s| s.to_owned()).collect()
|
||||
}
|
||||
|
||||
pub fn variant(&mut self, model: super::Model) {
|
||||
self.variant = model;
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<CpuJson> for Cpu {
|
||||
|
@ -714,3 +744,8 @@ fn cpu_available_governors_path(index: usize) -> String {
|
|||
index
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cpu_max_clock_path(index: usize) -> String {
|
||||
format!("/sys/devices/system/cpu/cpufreq/policy{}/cpuinfo_max_freq", index)
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ pub struct Gpu {
|
|||
|
||||
const GPU_CLOCK_LIMITS_ATTRIBUTE: &str = "device/pp_od_clk_voltage";
|
||||
const GPU_MEMORY_DOWNCLOCK_ATTRIBUTE: &str = "device/pp_dpm_fclk";
|
||||
const GPU_CLOCK_READOUT_ATTRIBUTE: &str = "device/pp_dpm_sclk";
|
||||
|
||||
const CARD_EXTENSIONS: &[&'static str] = &[
|
||||
GPU_CLOCK_LIMITS_ATTRIBUTE,
|
||||
|
@ -141,6 +142,29 @@ impl Gpu {
|
|||
})
|
||||
}
|
||||
|
||||
fn read_max_gpu_clock(&self) -> u64 {
|
||||
if !(self.limits.extras.experiments || self.limits.extras.quirks.contains("clock-autodetect")) {
|
||||
return MAX_CLOCK;
|
||||
}
|
||||
if let super::Model::OLED = self.variant {
|
||||
if let Ok(f) = self
|
||||
.sysfs_card
|
||||
.read_value(GPU_CLOCK_READOUT_ATTRIBUTE.to_owned())
|
||||
{
|
||||
let options = parse_pp_dpm_sclk(&String::from_utf8_lossy(&f));
|
||||
return options.get(options.len() - 1)
|
||||
.map(|x| {
|
||||
let x = x.1 as u64;
|
||||
log::debug!("Detected GPU max clock of {}MHz", x);
|
||||
x
|
||||
|
||||
})
|
||||
.unwrap_or(MAX_CLOCK);
|
||||
}
|
||||
}
|
||||
MAX_CLOCK
|
||||
}
|
||||
|
||||
fn is_memory_clock_maxed(&self) -> bool {
|
||||
if let Some(clock) = &self.memory_clock {
|
||||
if let Some(limit) = &self.limits.memory_clock {
|
||||
|
@ -611,6 +635,7 @@ impl crate::settings::OnUnload for Gpu {
|
|||
|
||||
impl TGpu for Gpu {
|
||||
fn limits(&self) -> crate::api::GpuLimits {
|
||||
let max_gpu_clock = self.read_max_gpu_clock();
|
||||
crate::api::GpuLimits {
|
||||
fast_ppt_limits: Some(RangeLimit {
|
||||
min: super::util::range_min_or_fallback(&self.limits.fast_ppt, MIN_FAST_PPT)
|
||||
|
@ -630,11 +655,11 @@ impl TGpu for Gpu {
|
|||
tdp_step: 42,
|
||||
clock_min_limits: Some(RangeLimit {
|
||||
min: super::util::range_min_or_fallback(&self.limits.clock_min, MIN_CLOCK),
|
||||
max: super::util::range_max_or_fallback(&self.limits.clock_min, MAX_CLOCK),
|
||||
max: super::util::range_max_or_fallback(&self.limits.clock_min, max_gpu_clock),
|
||||
}),
|
||||
clock_max_limits: Some(RangeLimit {
|
||||
min: super::util::range_min_or_fallback(&self.limits.clock_max, MIN_CLOCK),
|
||||
max: super::util::range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK),
|
||||
max: super::util::range_max_or_fallback(&self.limits.clock_max, max_gpu_clock),
|
||||
}),
|
||||
clock_step: self.limits.clock_step.unwrap_or(100),
|
||||
memory_control: Some(RangeLimit {
|
||||
|
@ -693,7 +718,7 @@ impl TGpu for Gpu {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_pp_dpm_fclk(s: &str) -> Vec<(usize, usize)> {
|
||||
fn parse_sysfs_clk_selector_str(s: &str) -> Vec<(usize, usize)> {
|
||||
// (value, MHz)
|
||||
let mut result = Vec::new();
|
||||
for line in s.split('\n') {
|
||||
|
@ -715,3 +740,13 @@ fn parse_pp_dpm_fclk(s: &str) -> Vec<(usize, usize)> {
|
|||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_pp_dpm_fclk(s: &str) -> Vec<(usize, usize)> {
|
||||
parse_sysfs_clk_selector_str(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_pp_dpm_sclk(s: &str) -> Vec<(usize, usize)> {
|
||||
parse_sysfs_clk_selector_str(s)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "PowerTools",
|
||||
"version": "2.0.0-alpha2",
|
||||
"version": "2.0.0-alpha3",
|
||||
"description": "Power tweaks for power users",
|
||||
"scripts": {
|
||||
"build": "shx rm -rf dist && rollup -c",
|
||||
|
|
Loading…
Reference in a new issue