Skip to main content

libamdgpu_top/
ppfeaturemask.rs

1use std::fmt;
2
3#[allow(non_snake_case)]
4mod MaskValue {
5    pub const PP_SCLK_DPM_MASK: u32 = 0x1;
6    pub const PP_MCLK_DPM_MASK: u32 = 0x2;
7    pub const PP_PCIE_DPM_MASK: u32 = 0x4;
8    pub const PP_SCLK_DEEP_SLEEP_MASK: u32 = 0x8;
9    pub const PP_POWER_CONTAINMENT_MASK: u32 = 0x10;
10    pub const PP_UVD_HANDSHAKE_MASK: u32 = 0x20;
11    pub const PP_SMC_VOLTAGE_CONTROL_MASK: u32 = 0x40;
12    pub const PP_VBI_TIME_SUPPORT_MASK: u32 = 0x80;
13    pub const PP_ULV_MASK: u32 = 0x100;
14    pub const PP_ENABLE_GFX_CG_THRU_SMU: u32 = 0x200;
15    pub const PP_CLOCK_STRETCH_MASK: u32 = 0x400;
16    pub const PP_OD_FUZZY_FAN_CONTROL_MASK: u32 = 0x800;
17    pub const PP_SOCCLK_DPM_MASK: u32 = 0x1000;
18    pub const PP_DCEFCLK_DPM_MASK: u32 = 0x2000;
19    pub const PP_OVERDRIVE_MASK: u32 = 0x4000;
20    pub const PP_GFXOFF_MASK: u32 = 0x8000;
21    pub const PP_ACG_MASK: u32 = 0x10000;
22    pub const PP_STUTTER_MODE: u32 = 0x20000;
23    pub const PP_AVFS_MASK: u32 = 0x40000;
24    pub const PP_GFX_DCS_MASK: u32 = 0x80000;
25}
26
27#[allow(non_camel_case_types)]
28#[derive(Debug, Clone)]
29#[repr(u32)]
30pub enum PpFeatureMask {
31    PP_SCLK_DPM_MASK = MaskValue::PP_SCLK_DPM_MASK,
32    PP_MCLK_DPM_MASK = MaskValue::PP_MCLK_DPM_MASK,
33    PP_PCIE_DPM_MASK = MaskValue::PP_PCIE_DPM_MASK,
34    PP_SCLK_DEEP_SLEEP_MASK = MaskValue::PP_SCLK_DEEP_SLEEP_MASK,
35    PP_POWER_CONTAINMENT_MASK = MaskValue::PP_POWER_CONTAINMENT_MASK,
36    PP_UVD_HANDSHAKE_MASK = MaskValue::PP_UVD_HANDSHAKE_MASK,
37    PP_SMC_VOLTAGE_CONTROL_MASK = MaskValue::PP_SMC_VOLTAGE_CONTROL_MASK,
38    PP_VBI_TIME_SUPPORT_MASK = MaskValue::PP_VBI_TIME_SUPPORT_MASK,
39    PP_ULV_MASK = MaskValue::PP_ULV_MASK,
40    PP_ENABLE_GFX_CG_THRU_SMU = MaskValue::PP_ENABLE_GFX_CG_THRU_SMU,
41    PP_CLOCK_STRETCH_MASK = MaskValue::PP_CLOCK_STRETCH_MASK,
42    PP_OD_FUZZY_FAN_CONTROL_MASK = MaskValue::PP_OD_FUZZY_FAN_CONTROL_MASK,
43    PP_SOCCLK_DPM_MASK = MaskValue::PP_SOCCLK_DPM_MASK,
44    PP_DCEFCLK_DPM_MASK = MaskValue::PP_DCEFCLK_DPM_MASK,
45    PP_OVERDRIVE_MASK = MaskValue::PP_OVERDRIVE_MASK, // disabled by default
46    PP_GFXOFF_MASK = MaskValue::PP_GFXOFF_MASK,
47    PP_ACG_MASK = MaskValue::PP_ACG_MASK,
48    PP_STUTTER_MODE = MaskValue::PP_STUTTER_MODE,
49    PP_AVFS_MASK = MaskValue::PP_AVFS_MASK,
50    PP_GFX_DCS_MASK = MaskValue::PP_GFX_DCS_MASK, // disabled by default
51}
52
53#[derive(Debug, Clone)]
54pub struct UnknownMaskValue;
55
56impl TryFrom<u32> for PpFeatureMask {
57    type Error = UnknownMaskValue;
58
59    fn try_from(value: u32) -> Result<Self, Self::Error> {
60        let v = match value {
61            MaskValue::PP_SCLK_DPM_MASK => Self::PP_SCLK_DPM_MASK,
62            MaskValue::PP_MCLK_DPM_MASK => Self::PP_MCLK_DPM_MASK,
63            MaskValue::PP_PCIE_DPM_MASK => Self::PP_PCIE_DPM_MASK,
64            MaskValue::PP_SCLK_DEEP_SLEEP_MASK => Self::PP_SCLK_DEEP_SLEEP_MASK,
65            MaskValue::PP_POWER_CONTAINMENT_MASK => Self::PP_POWER_CONTAINMENT_MASK,
66            MaskValue::PP_UVD_HANDSHAKE_MASK => Self::PP_UVD_HANDSHAKE_MASK,
67            MaskValue::PP_SMC_VOLTAGE_CONTROL_MASK => Self::PP_SMC_VOLTAGE_CONTROL_MASK,
68            MaskValue::PP_VBI_TIME_SUPPORT_MASK => Self::PP_VBI_TIME_SUPPORT_MASK,
69            MaskValue::PP_ULV_MASK => Self::PP_ULV_MASK,
70            MaskValue::PP_ENABLE_GFX_CG_THRU_SMU => Self::PP_ENABLE_GFX_CG_THRU_SMU,
71            MaskValue::PP_CLOCK_STRETCH_MASK => Self::PP_CLOCK_STRETCH_MASK,
72            MaskValue::PP_OD_FUZZY_FAN_CONTROL_MASK => Self::PP_OD_FUZZY_FAN_CONTROL_MASK,
73            MaskValue::PP_SOCCLK_DPM_MASK => Self::PP_SOCCLK_DPM_MASK,
74            MaskValue::PP_DCEFCLK_DPM_MASK => Self::PP_DCEFCLK_DPM_MASK,
75            MaskValue::PP_OVERDRIVE_MASK => Self::PP_OVERDRIVE_MASK,
76            MaskValue::PP_GFXOFF_MASK => Self::PP_GFXOFF_MASK,
77            MaskValue::PP_ACG_MASK => Self::PP_ACG_MASK,
78            MaskValue::PP_STUTTER_MODE => Self::PP_STUTTER_MODE,
79            MaskValue::PP_AVFS_MASK => Self::PP_AVFS_MASK,
80            MaskValue::PP_GFX_DCS_MASK => Self::PP_GFX_DCS_MASK,
81            _ => return Err(UnknownMaskValue),
82        };
83
84        Ok(v)
85    }
86}
87
88impl fmt::Display for PpFeatureMask {
89    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90        write!(f, "{:?}", self)
91    }
92}
93
94impl PpFeatureMask {
95    pub fn get_param_u32() -> Option<u32> {
96        let s = std::fs::read_to_string("/sys/module/amdgpu/parameters/ppfeaturemask").ok()?;
97        let len = s.len();
98
99        s.get(if s.starts_with("0x") {
100            2..len-1
101        } else {
102            0..len-1
103        }).and_then(|param| u32::from_str_radix(param, 16).ok())
104    }
105
106    pub fn get_all_enabled_feature() -> Vec<Self> {
107        let Some(mut n) = Self::get_param_u32() else { return Vec::new() };
108        let mut vec: Vec<Self> = Vec::with_capacity(32);
109        let mut i = 0;
110
111        while n != 0 {
112            if (n & 0b1) == 1 && let Ok(ftr) = PpFeatureMask::try_from(1 << i) {
113                vec.push(ftr);
114            }
115            n >>= 0b1;
116            i += 1;
117        }
118
119        vec
120    }
121}