Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/radeon/dpm: add debugfs support for RS780/RS880 (v3)

This allows you to look at the current DPM state via
debugfs.

Due to the way the hardware works on these asics, there's
no way to look up exactly what power state we are in, so
we make the best guess we can based on the current sclk.

v2: Anthoine's version
v3: fix ref div

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

+31
+1
drivers/gpu/drm/radeon/radeon_asic.c
··· 1270 1270 .get_sclk = &rs780_dpm_get_sclk, 1271 1271 .get_mclk = &rs780_dpm_get_mclk, 1272 1272 .print_power_state = &rs780_dpm_print_power_state, 1273 + .debugfs_print_current_performance_level = &rs780_dpm_debugfs_print_current_performance_level, 1273 1274 }, 1274 1275 .pflip = { 1275 1276 .pre_page_flip = &rs600_pre_page_flip,
+2
drivers/gpu/drm/radeon/radeon_asic.h
··· 433 433 u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low); 434 434 void rs780_dpm_print_power_state(struct radeon_device *rdev, 435 435 struct radeon_ps *ps); 436 + void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 437 + struct seq_file *m); 436 438 437 439 /* uvd */ 438 440 int r600_uvd_init(struct radeon_device *rdev);
+25
drivers/gpu/drm/radeon/rs780_dpm.c
··· 28 28 #include "r600_dpm.h" 29 29 #include "rs780_dpm.h" 30 30 #include "atom.h" 31 + #include <linux/seq_file.h> 31 32 32 33 static struct igp_ps *rs780_get_ps(struct radeon_ps *rps) 33 34 { ··· 961 960 struct igp_power_info *pi = rs780_get_pi(rdev); 962 961 963 962 return pi->bootup_uma_clk; 963 + } 964 + 965 + void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 966 + struct seq_file *m) 967 + { 968 + struct radeon_ps *rps = rdev->pm.dpm.current_ps; 969 + struct igp_ps *ps = rs780_get_ps(rps); 970 + u32 current_fb_div = RREG32(FVTHROT_STATUS_REG0) & CURRENT_FEEDBACK_DIV_MASK; 971 + u32 func_cntl = RREG32(CG_SPLL_FUNC_CNTL); 972 + u32 ref_div = ((func_cntl & SPLL_REF_DIV_MASK) >> SPLL_REF_DIV_SHIFT) + 1; 973 + u32 post_div = ((func_cntl & SPLL_SW_HILEN_MASK) >> SPLL_SW_HILEN_SHIFT) + 1 + 974 + ((func_cntl & SPLL_SW_LOLEN_MASK) >> SPLL_SW_LOLEN_SHIFT) + 1; 975 + u32 sclk = (rdev->clock.spll.reference_freq * current_fb_div) / 976 + (post_div * ref_div); 977 + 978 + seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 979 + 980 + /* guess based on the current sclk */ 981 + if (sclk < (ps->sclk_low + 500)) 982 + seq_printf(m, "power level 0 sclk: %u vddc_index: %d\n", 983 + ps->sclk_low, ps->min_voltage); 984 + else 985 + seq_printf(m, "power level 1 sclk: %u vddc_index: %d\n", 986 + ps->sclk_high, ps->max_voltage); 964 987 }
+3
drivers/gpu/drm/radeon/rs780d.h
··· 28 28 # define SPLL_SLEEP (1 << 1) 29 29 # define SPLL_REF_DIV(x) ((x) << 2) 30 30 # define SPLL_REF_DIV_MASK (7 << 2) 31 + # define SPLL_REF_DIV_SHIFT 2 31 32 # define SPLL_FB_DIV(x) ((x) << 5) 32 33 # define SPLL_FB_DIV_MASK (0xff << 2) 33 34 # define SPLL_FB_DIV_SHIFT 2 ··· 37 36 # define SPLL_PULSENUM_MASK (3 << 14) 38 37 # define SPLL_SW_HILEN(x) ((x) << 16) 39 38 # define SPLL_SW_HILEN_MASK (0xf << 16) 39 + # define SPLL_SW_HILEN_SHIFT 16 40 40 # define SPLL_SW_LOLEN(x) ((x) << 20) 41 41 # define SPLL_SW_LOLEN_MASK (0xf << 20) 42 + # define SPLL_SW_LOLEN_SHIFT 20 42 43 # define SPLL_DIVEN (1 << 24) 43 44 # define SPLL_BYPASS_EN (1 << 25) 44 45 # define SPLL_CHG_STATUS (1 << 29)