Implement RyzenAdj driver for AMD
This commit is contained in:
parent
5614937012
commit
500fde964c
7 changed files with 189 additions and 19 deletions
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>> {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
backend/src/state/generic/gpu.rs
Normal file
16
backend/src/state/generic/gpu.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
backend/src/state/generic/mod.rs
Normal file
3
backend/src/state/generic/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
mod gpu;
|
||||||
|
|
||||||
|
pub use gpu::Gpu;
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue