Implement RyzenAdj driver for AMD

This commit is contained in:
NGnius (Graham) 2023-01-02 18:47:14 -05:00
parent 5614937012
commit 500fde964c
7 changed files with 189 additions and 19 deletions

View file

@ -169,12 +169,12 @@ pub struct Cpu {
state: crate::state::steam_deck::Cpu, state: crate::state::steam_deck::Cpu,
} }
impl Cpu { /*impl Cpu {
#[inline] #[inline]
pub fn index(&self) -> usize { pub fn index(&self) -> usize {
self.index self.index
} }
} }*/
impl AsRef<Cpu> for Cpu { impl AsRef<Cpu> for Cpu {
#[inline] #[inline]

View file

@ -9,10 +9,10 @@ use crate::persist::GpuJson;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Gpu { pub struct Gpu {
slow_memory: bool, pub slow_memory: bool,
fast_ppt: Option<u64>, pub fast_ppt: Option<u64>,
slow_ppt: Option<u64>, pub slow_ppt: Option<u64>,
clock_limits: Option<MinMax<u64>>, pub clock_limits: Option<MinMax<u64>>,
limits: GenericGpuLimit, limits: GenericGpuLimit,
} }
@ -101,11 +101,11 @@ impl TGpu for Gpu {
} }
fn ppt(&mut self, fast: Option<u64>, slow: Option<u64>) { fn ppt(&mut self, fast: Option<u64>, slow: Option<u64>) {
if self.limits.fast_ppt.is_some() { if let Some(fast_lims) = &self.limits.fast_ppt {
self.fast_ppt = fast; self.fast_ppt = fast.map(|x| x.clamp(fast_lims.min, fast_lims.max));
} }
if self.limits.slow_ppt.is_some() { if let Some(slow_lims) = &self.limits.slow_ppt {
self.slow_ppt = slow; self.slow_ppt = slow.map(|x| x.clamp(slow_lims.min, slow_lims.max));
} }
} }
@ -114,8 +114,14 @@ impl TGpu for Gpu {
} }
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) { fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
if self.limits.clock_min.is_some() && self.limits.clock_max.is_some() { if let Some(clock_min) = &self.limits.clock_min {
self.clock_limits = limits; if let Some(clock_max) = &self.limits.clock_max {
self.clock_limits = limits.map(|mut x| {
x.min = x.min.clamp(clock_min.min, clock_min.max);
x.max = x.max.clamp(clock_max.max, clock_max.max);
x
});
}
} }
} }

View file

@ -123,8 +123,9 @@ impl TCpu for Cpu {
self.generic.get_governor() self.generic.get_governor()
} }
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) { fn clock_limits(&mut self, _limits: Option<MinMax<u64>>) {
self.generic.clock_limits(limits) //self.generic.clock_limits(limits)
// TODO: support this
} }
fn get_clock_limits(&self) -> Option<&MinMax<u64>> { fn get_clock_limits(&self) -> Option<&MinMax<u64>> {

View file

@ -1,39 +1,182 @@
use std::sync::Mutex;
use ryzenadj_rs::RyzenAccess;
use crate::persist::GpuJson; use crate::persist::GpuJson;
use crate::settings::MinMax; use crate::settings::MinMax;
use crate::settings::generic::Gpu as GenericGpu; use crate::settings::generic::Gpu as GenericGpu;
use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{OnResume, OnSet, SettingError, SettingVariant};
use crate::settings::TGpu; use crate::settings::TGpu;
fn ryzen_adj_or_log() -> Option<Mutex<RyzenAccess>> {
match RyzenAccess::new() {
Ok(x) => Some(Mutex::new(x)),
Err(e) => {
log::error!("RyzenAdj init error: {}", e);
None
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Gpu { pub struct Gpu {
generic: GenericGpu, generic: GenericGpu,
implementor: Option<Mutex<RyzenAccess>>,
state: crate::state::generic::Gpu, // NOTE this is re-used for simplicity
} }
impl Gpu { impl Gpu {
pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self { pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self {
Self { Self {
generic: GenericGpu::from_limits(limits), generic: GenericGpu::from_limits(limits),
implementor: ryzen_adj_or_log(),
state: Default::default(),
} }
} }
pub fn from_json_and_limits(other: GpuJson, version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { pub fn from_json_and_limits(other: GpuJson, version: u64, limits: limits_core::json::GenericGpuLimit) -> Self {
Self { Self {
generic: GenericGpu::from_json_and_limits(other, version, limits), generic: GenericGpu::from_json_and_limits(other, version, limits),
implementor: ryzen_adj_or_log(),
state: Default::default(),
} }
} }
fn set_all(&mut self) -> Result<(), SettingError> {
let mutex = match &self.implementor {
Some(x) => x,
None => {
return Err(SettingError {
msg: "RyzenAdj unavailable".to_owned(),
setting: SettingVariant::Gpu,
});
}
};
let lock = match mutex.lock() {
Ok(x) => x,
Err(e) => {
return Err(SettingError {
msg: format!("RyzenAdj lock acquire failed: {}", e),
setting: SettingVariant::Gpu,
});
}
};
if let Some(fast_ppt) = &self.generic.fast_ppt {
if self.state.old_fast_ppt.is_none() {
self.state.old_fast_ppt = Some(lock.get_fast_value() as _);
}
lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e),
setting: SettingVariant::Gpu,
})?;
} else if let Some(fast_ppt) = &self.state.old_fast_ppt {
lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e),
setting: SettingVariant::Gpu,
})?;
self.state.old_fast_ppt = None;
}
if let Some(slow_ppt) = &self.generic.slow_ppt {
if self.state.old_slow_ppt.is_none() {
self.state.old_slow_ppt = Some(lock.get_slow_value() as _);
}
lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e),
setting: SettingVariant::Gpu,
})?;
} else if let Some(slow_ppt) = &self.state.old_slow_ppt {
lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e),
setting: SettingVariant::Gpu,
})?;
self.state.old_slow_ppt = None;
}
if let Some(clock_limits) = &self.generic.clock_limits {
self.state.clock_limits_set = true;
lock.set_max_gfxclk_freq(clock_limits.max as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", clock_limits.max, e),
setting: SettingVariant::Gpu,
})?;
lock.set_min_gfxclk_freq(clock_limits.min as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", clock_limits.min, e),
setting: SettingVariant::Gpu,
})?;
} else if self.state.clock_limits_set {
self.state.clock_limits_set = false;
let limits = self.generic.limits();
if let Some(min_limits) = limits.clock_min_limits {
if let Some(max_limits) = limits.clock_max_limits {
lock.set_max_gfxclk_freq(max_limits.max as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", max_limits.max, e),
setting: SettingVariant::Gpu,
})?;
lock.set_min_gfxclk_freq(min_limits.min as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", min_limits.min, e),
setting: SettingVariant::Gpu,
})?;
}
}
}
Ok(())
}
fn resume_all(&self) -> Result<(), SettingError> {
// like set_all() but without updating state
// -- assumption: state is already up to date
let mutex = match &self.implementor {
Some(x) => x,
None => {
return Err(SettingError {
msg: "RyzenAdj unavailable".to_owned(),
setting: SettingVariant::Gpu,
});
}
};
let lock = match mutex.lock() {
Ok(x) => x,
Err(e) => {
return Err(SettingError {
msg: format!("RyzenAdj lock acquire failed: {}", e),
setting: SettingVariant::Gpu,
});
}
};
if let Some(fast_ppt) = &self.generic.fast_ppt {
lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e),
setting: SettingVariant::Gpu,
})?;
}
if let Some(slow_ppt) = &self.generic.slow_ppt {
lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e),
setting: SettingVariant::Gpu,
})?;
}
if let Some(clock_limits) = &self.generic.clock_limits {
lock.set_max_gfxclk_freq(clock_limits.max as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", clock_limits.max, e),
setting: SettingVariant::Gpu,
})?;
lock.set_min_gfxclk_freq(clock_limits.min as _).map_err(|e| SettingError {
msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", clock_limits.min, e),
setting: SettingVariant::Gpu,
})?;
}
Ok(())
}
} }
impl OnResume for Gpu { impl OnResume for Gpu {
fn on_resume(&self) -> Result<(), SettingError> { fn on_resume(&self) -> Result<(), SettingError> {
self.generic.on_resume() self.generic.on_resume()?;
// TODO self.resume_all()
} }
} }
impl OnSet for Gpu { impl OnSet for Gpu {
fn on_set(&mut self) -> Result<(), SettingError> { fn on_set(&mut self) -> Result<(), SettingError> {
self.generic.on_set() self.generic.on_set()?;
// TODO self.set_all()
} }
} }

View file

@ -0,0 +1,16 @@
#[derive(Debug, Clone)]
pub struct Gpu {
pub clock_limits_set: bool,
pub old_fast_ppt: Option<u64>,
pub old_slow_ppt: Option<u64>,
}
impl std::default::Default for Gpu {
fn default() -> Self {
Self {
clock_limits_set: false,
old_fast_ppt: None,
old_slow_ppt: None,
}
}
}

View file

@ -0,0 +1,3 @@
mod gpu;
pub use gpu::Gpu;

View file

@ -1,6 +1,7 @@
mod error; mod error;
mod traits; mod traits;
pub mod generic;
pub mod steam_deck; pub mod steam_deck;
pub use error::StateError; pub use error::StateError;