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,
}
impl Cpu {
/*impl Cpu {
#[inline]
pub fn index(&self) -> usize {
self.index
}
}
}*/
impl AsRef<Cpu> for Cpu {
#[inline]

View file

@ -9,10 +9,10 @@ use crate::persist::GpuJson;
#[derive(Debug, Clone)]
pub struct Gpu {
slow_memory: bool,
fast_ppt: Option<u64>,
slow_ppt: Option<u64>,
clock_limits: Option<MinMax<u64>>,
pub slow_memory: bool,
pub fast_ppt: Option<u64>,
pub slow_ppt: Option<u64>,
pub clock_limits: Option<MinMax<u64>>,
limits: GenericGpuLimit,
}
@ -101,11 +101,11 @@ impl TGpu for Gpu {
}
fn ppt(&mut self, fast: Option<u64>, slow: Option<u64>) {
if self.limits.fast_ppt.is_some() {
self.fast_ppt = fast;
if let Some(fast_lims) = &self.limits.fast_ppt {
self.fast_ppt = fast.map(|x| x.clamp(fast_lims.min, fast_lims.max));
}
if self.limits.slow_ppt.is_some() {
self.slow_ppt = slow;
if let Some(slow_lims) = &self.limits.slow_ppt {
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>>) {
if self.limits.clock_min.is_some() && self.limits.clock_max.is_some() {
self.clock_limits = limits;
if let Some(clock_min) = &self.limits.clock_min {
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()
}
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
self.generic.clock_limits(limits)
fn clock_limits(&mut self, _limits: Option<MinMax<u64>>) {
//self.generic.clock_limits(limits)
// TODO: support this
}
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::settings::MinMax;
use crate::settings::generic::Gpu as GenericGpu;
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::{OnResume, OnSet, SettingError, SettingVariant};
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)]
pub struct Gpu {
generic: GenericGpu,
implementor: Option<Mutex<RyzenAccess>>,
state: crate::state::generic::Gpu, // NOTE this is re-used for simplicity
}
impl Gpu {
pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self {
Self {
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 {
Self {
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 {
fn on_resume(&self) -> Result<(), SettingError> {
self.generic.on_resume()
// TODO
self.generic.on_resume()?;
self.resume_all()
}
}
impl OnSet for Gpu {
fn on_set(&mut self) -> Result<(), SettingError> {
self.generic.on_set()
// TODO
self.generic.on_set()?;
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 traits;
pub mod generic;
pub mod steam_deck;
pub use error::StateError;