Message ID | 20130717204236.GA2380@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Jul 17, 2013 at 08:54:33PM +0000, Deucher, Alexander wrote: >Good catch, I screwed up the ref divider calculation. How about the attached patch? It works too. But here was my logic, tell me if I'm wrong: The output frequency of the PLL is equal to the VCO frequency (FVCO) divided by the post-scale counter (C). Fout = FVCO / C And VCO frequency is equal to feedback (M) times the reference frequency (FREF). FVCO = FREF x M Where reference clock (FREF) is equal to the input clock (Fin) divided by the pre-scale counter (N) FREF = Fin / N then FVCO = Fin x M / N and Fout = (Fin x M) / (N x C) = FREF x M / C where: FVCO = VCO frequency Fin = input frequency Fout = output frequency FREF = reference frequency (rdev->clock.spll.reference_freq in the code) M = counter (multiplier), part of the clock feedback path (current_fb_div) N = counter (divider), part of the clock reference path (ref_div) C = post-scale counter (divider) (post_div) No need to ref_div. Or reference_freq == Fin and the varname confuses me ? In my test: # cat /sys/kernel/debug/dri/0/radeon_pm_info uvd vclk: 0 dclk: 0 power level 0 sclk: 20000 vddc_index: 2 when my system is idle and sclk == 19690 and: # cat /sys/kernel/debug/dri/0/radeon_pm_info uvd vclk: 0 dclk: 0 power level 1 sclk: 50000 vddc_index: 2 when I play supertuxkart with sclk == 49762. Thanks for yesturday, I was in a wrong way, Anthoine > >Alex > >> -----Original Message----- >> From: Anthoine Bourgeois [mailto:anthoine.bourgeois@gmail.com] >> Sent: Wednesday, July 17, 2013 4:43 PM >> To: Deucher, Alexander; Koenig, Christian; Jerome Glisse; Anthoine >> Bourgeois >> Cc: dri-devel@lists.freedesktop.org >> Subject: [PATCH] drm/radeon/dpm: add debugfs support for RS780/RS880 >> (v2) >> >> 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: fix sclk equation >> >> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >> Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com> >> --- >> drivers/gpu/drm/radeon/radeon_asic.c | 1 + >> drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ >> drivers/gpu/drm/radeon/rs780_dpm.c | 23 +++++++++++++++++++++++ >> drivers/gpu/drm/radeon/rs780d.h | 3 +++ >> 4 files changed, 29 insertions(+) >> >> diff --git a/drivers/gpu/drm/radeon/radeon_asic.c >> b/drivers/gpu/drm/radeon/radeon_asic.c >> index fea997e..78bec1a 100644 >> --- a/drivers/gpu/drm/radeon/radeon_asic.c >> +++ b/drivers/gpu/drm/radeon/radeon_asic.c >> @@ -1270,6 +1270,7 @@ static struct radeon_asic rs780_asic = { >> .get_sclk = &rs780_dpm_get_sclk, >> .get_mclk = &rs780_dpm_get_mclk, >> .print_power_state = &rs780_dpm_print_power_state, >> + .debugfs_print_current_performance_level = >> &rs780_dpm_debugfs_print_current_performance_level, >> }, >> .pflip = { >> .pre_page_flip = &rs600_pre_page_flip, >> diff --git a/drivers/gpu/drm/radeon/radeon_asic.h >> b/drivers/gpu/drm/radeon/radeon_asic.h >> index b04b578..ca18957 100644 >> --- a/drivers/gpu/drm/radeon/radeon_asic.h >> +++ b/drivers/gpu/drm/radeon/radeon_asic.h >> @@ -433,6 +433,8 @@ u32 rs780_dpm_get_sclk(struct radeon_device *rdev, >> bool low); >> u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low); >> void rs780_dpm_print_power_state(struct radeon_device *rdev, >> struct radeon_ps *ps); >> +void rs780_dpm_debugfs_print_current_performance_level(struct >> radeon_device *rdev, >> + struct seq_file *m); >> >> /* uvd */ >> int r600_uvd_init(struct radeon_device *rdev); >> diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c >> b/drivers/gpu/drm/radeon/rs780_dpm.c >> index bef832a..7f128c2 100644 >> --- a/drivers/gpu/drm/radeon/rs780_dpm.c >> +++ b/drivers/gpu/drm/radeon/rs780_dpm.c >> @@ -28,6 +28,7 @@ >> #include "r600_dpm.h" >> #include "rs780_dpm.h" >> #include "atom.h" >> +#include <linux/seq_file.h> >> >> static struct igp_ps *rs780_get_ps(struct radeon_ps *rps) >> { >> @@ -961,3 +962,25 @@ u32 rs780_dpm_get_mclk(struct radeon_device >> *rdev, bool low) >> >> return pi->bootup_uma_clk; >> } >> + >> +void rs780_dpm_debugfs_print_current_performance_level(struct >> radeon_device *rdev, >> + struct seq_file *m) >> +{ >> + struct radeon_ps *rps = rdev->pm.dpm.current_ps; >> + struct igp_ps *ps = rs780_get_ps(rps); >> + u32 current_fb_div = RREG32(FVTHROT_STATUS_REG0) & >> CURRENT_FEEDBACK_DIV_MASK; >> + u32 func_cntl = RREG32(CG_SPLL_FUNC_CNTL); >> + u32 post_div = ((func_cntl & SPLL_SW_HILEN_MASK) >> >> SPLL_SW_HILEN_SHIFT) + 1 + >> + ((func_cntl & SPLL_SW_LOLEN_MASK) >> >> SPLL_SW_LOLEN_SHIFT) + 1; >> + u32 sclk = (rdev->clock.spll.reference_freq * current_fb_div) / >> post_div; >> + >> + seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); >> + >> + /* guess based on the current sclk */ >> + if (sclk < (ps->sclk_low + 500)) >> + seq_printf(m, "power level 0 sclk: %u vddc_index: %d\n", >> + ps->sclk_low, ps->min_voltage); >> + else >> + seq_printf(m, "power level 1 sclk: %u vddc_index: %d\n", >> + ps->sclk_high, ps->max_voltage); >> +} >> diff --git a/drivers/gpu/drm/radeon/rs780d.h >> b/drivers/gpu/drm/radeon/rs780d.h >> index b1142ed..cfbe9a4 100644 >> --- a/drivers/gpu/drm/radeon/rs780d.h >> +++ b/drivers/gpu/drm/radeon/rs780d.h >> @@ -28,6 +28,7 @@ >> # define SPLL_SLEEP (1 << 1) >> # define SPLL_REF_DIV(x) ((x) << 2) >> # define SPLL_REF_DIV_MASK (7 << 2) >> +# define SPLL_REF_DIV_SHIFT 2 >> # define SPLL_FB_DIV(x) ((x) << 5) >> # define SPLL_FB_DIV_MASK (0xff << 2) >> # define SPLL_FB_DIV_SHIFT 2 >> @@ -36,8 +37,10 @@ >> # define SPLL_PULSENUM_MASK (3 << 14) >> # define SPLL_SW_HILEN(x) ((x) << 16) >> # define SPLL_SW_HILEN_MASK (0xf << 16) >> +# define SPLL_SW_HILEN_SHIFT 16 >> # define SPLL_SW_LOLEN(x) ((x) << 20) >> # define SPLL_SW_LOLEN_MASK (0xf << 20) >> +# define SPLL_SW_LOLEN_SHIFT 20 >> # define SPLL_DIVEN (1 << 24) >> # define SPLL_BYPASS_EN (1 << 25) >> # define SPLL_CHG_STATUS (1 << 29) >> -- >> 1.8.1.5 >> >
On Wed, Jul 17, 2013 at 09:44:00PM +0000, Deucher, Alexander wrote: >> -----Original Message----- >> From: Anthoine Bourgeois [mailto:anthoine.bourgeois@gmail.com] >> Sent: Wednesday, July 17, 2013 5:23 PM >> To: Deucher, Alexander; Koenig, Christian; Jerome Glisse >> Cc: dri-devel@lists.freedesktop.org >> Subject: Re: [PATCH] drm/radeon/dpm: add debugfs support for >> RS780/RS880 (v2) >> >> On Wed, Jul 17, 2013 at 08:54:33PM +0000, Deucher, Alexander wrote: >> >Good catch, I screwed up the ref divider calculation. How about the >> attached patch? >> >> It works too. But here was my logic, tell me if I'm wrong: > >Ok. > >> >> The output frequency of the PLL is equal to the VCO frequency (FVCO) >> divided by the post-scale counter (C). >> Fout = FVCO / C >> And VCO frequency is equal to feedback (M) times the reference frequency >> (FREF). >> FVCO = FREF x M >> Where reference clock (FREF) is equal to the input clock (Fin) divided >> by the pre-scale counter (N) >> FREF = Fin / N >> then >> FVCO = Fin x M / N >> and >> Fout = (Fin x M) / (N x C) = FREF x M / C >> >> where: >> FVCO = VCO frequency >> Fin = input frequency >> Fout = output frequency >> FREF = reference frequency (rdev->clock.spll.reference_freq in the code) >> M = counter (multiplier), part of the clock feedback path (current_fb_div) >> N = counter (divider), part of the clock reference path (ref_div) >> C = post-scale counter (divider) (post_div) >> >> No need to ref_div. Or reference_freq == Fin and the varname confuses me >> ? > >I'm not sure exactly how the PLL is set up. The calculation looks like so: > >Output frequency = (reference freq * feedback divider) / (reference divider * post divider); > >I think FVCO = (FREF * M) / N to use your terms, but I'm not really a hw expert. Neither me. I trust you, then : Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com> on v3. Anthoine > >Alex > >> >> In my test: >> # cat /sys/kernel/debug/dri/0/radeon_pm_info >> uvd vclk: 0 dclk: 0 >> power level 0 sclk: 20000 vddc_index: 2 >> >> when my system is idle and sclk == 19690 and: >> # cat /sys/kernel/debug/dri/0/radeon_pm_info >> uvd vclk: 0 dclk: 0 >> power level 1 sclk: 50000 vddc_index: 2 >> >> when I play supertuxkart with sclk == 49762. >> >> Thanks for yesturday, I was in a wrong way, >> Anthoine >> >> > >> >Alex >> > >> >> -----Original Message----- >> >> From: Anthoine Bourgeois [mailto:anthoine.bourgeois@gmail.com] >> >> Sent: Wednesday, July 17, 2013 4:43 PM >> >> To: Deucher, Alexander; Koenig, Christian; Jerome Glisse; Anthoine >> >> Bourgeois >> >> Cc: dri-devel@lists.freedesktop.org >> >> Subject: [PATCH] drm/radeon/dpm: add debugfs support for >> RS780/RS880 >> >> (v2) >> >> >> >> 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: fix sclk equation >> >> >> >> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >> >> Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com> >> >> --- >> >> drivers/gpu/drm/radeon/radeon_asic.c | 1 + >> >> drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ >> >> drivers/gpu/drm/radeon/rs780_dpm.c | 23 >> +++++++++++++++++++++++ >> >> drivers/gpu/drm/radeon/rs780d.h | 3 +++ >> >> 4 files changed, 29 insertions(+) >> >> >> >> diff --git a/drivers/gpu/drm/radeon/radeon_asic.c >> >> b/drivers/gpu/drm/radeon/radeon_asic.c >> >> index fea997e..78bec1a 100644 >> >> --- a/drivers/gpu/drm/radeon/radeon_asic.c >> >> +++ b/drivers/gpu/drm/radeon/radeon_asic.c >> >> @@ -1270,6 +1270,7 @@ static struct radeon_asic rs780_asic = { >> >> .get_sclk = &rs780_dpm_get_sclk, >> >> .get_mclk = &rs780_dpm_get_mclk, >> >> .print_power_state = &rs780_dpm_print_power_state, >> >> + .debugfs_print_current_performance_level = >> >> &rs780_dpm_debugfs_print_current_performance_level, >> >> }, >> >> .pflip = { >> >> .pre_page_flip = &rs600_pre_page_flip, >> >> diff --git a/drivers/gpu/drm/radeon/radeon_asic.h >> >> b/drivers/gpu/drm/radeon/radeon_asic.h >> >> index b04b578..ca18957 100644 >> >> --- a/drivers/gpu/drm/radeon/radeon_asic.h >> >> +++ b/drivers/gpu/drm/radeon/radeon_asic.h >> >> @@ -433,6 +433,8 @@ u32 rs780_dpm_get_sclk(struct radeon_device >> *rdev, >> >> bool low); >> >> u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low); >> >> void rs780_dpm_print_power_state(struct radeon_device *rdev, >> >> struct radeon_ps *ps); >> >> +void rs780_dpm_debugfs_print_current_performance_level(struct >> >> radeon_device *rdev, >> >> + struct seq_file *m); >> >> >> >> /* uvd */ >> >> int r600_uvd_init(struct radeon_device *rdev); >> >> diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c >> >> b/drivers/gpu/drm/radeon/rs780_dpm.c >> >> index bef832a..7f128c2 100644 >> >> --- a/drivers/gpu/drm/radeon/rs780_dpm.c >> >> +++ b/drivers/gpu/drm/radeon/rs780_dpm.c >> >> @@ -28,6 +28,7 @@ >> >> #include "r600_dpm.h" >> >> #include "rs780_dpm.h" >> >> #include "atom.h" >> >> +#include <linux/seq_file.h> >> >> >> >> static struct igp_ps *rs780_get_ps(struct radeon_ps *rps) >> >> { >> >> @@ -961,3 +962,25 @@ u32 rs780_dpm_get_mclk(struct radeon_device >> >> *rdev, bool low) >> >> >> >> return pi->bootup_uma_clk; >> >> } >> >> + >> >> +void rs780_dpm_debugfs_print_current_performance_level(struct >> >> radeon_device *rdev, >> >> + struct seq_file *m) >> >> +{ >> >> + struct radeon_ps *rps = rdev->pm.dpm.current_ps; >> >> + struct igp_ps *ps = rs780_get_ps(rps); >> >> + u32 current_fb_div = RREG32(FVTHROT_STATUS_REG0) & >> >> CURRENT_FEEDBACK_DIV_MASK; >> >> + u32 func_cntl = RREG32(CG_SPLL_FUNC_CNTL); >> >> + u32 post_div = ((func_cntl & SPLL_SW_HILEN_MASK) >> >> >> SPLL_SW_HILEN_SHIFT) + 1 + >> >> + ((func_cntl & SPLL_SW_LOLEN_MASK) >> >> >> SPLL_SW_LOLEN_SHIFT) + 1; >> >> + u32 sclk = (rdev->clock.spll.reference_freq * current_fb_div) / >> >> post_div; >> >> + >> >> + seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); >> >> + >> >> + /* guess based on the current sclk */ >> >> + if (sclk < (ps->sclk_low + 500)) >> >> + seq_printf(m, "power level 0 sclk: %u vddc_index: %d\n", >> >> + ps->sclk_low, ps->min_voltage); >> >> + else >> >> + seq_printf(m, "power level 1 sclk: %u vddc_index: %d\n", >> >> + ps->sclk_high, ps->max_voltage); >> >> +} >> >> diff --git a/drivers/gpu/drm/radeon/rs780d.h >> >> b/drivers/gpu/drm/radeon/rs780d.h >> >> index b1142ed..cfbe9a4 100644 >> >> --- a/drivers/gpu/drm/radeon/rs780d.h >> >> +++ b/drivers/gpu/drm/radeon/rs780d.h >> >> @@ -28,6 +28,7 @@ >> >> # define SPLL_SLEEP (1 << 1) >> >> # define SPLL_REF_DIV(x) ((x) << 2) >> >> # define SPLL_REF_DIV_MASK (7 << 2) >> >> +# define SPLL_REF_DIV_SHIFT 2 >> >> # define SPLL_FB_DIV(x) ((x) << 5) >> >> # define SPLL_FB_DIV_MASK (0xff << 2) >> >> # define SPLL_FB_DIV_SHIFT 2 >> >> @@ -36,8 +37,10 @@ >> >> # define SPLL_PULSENUM_MASK (3 << 14) >> >> # define SPLL_SW_HILEN(x) ((x) << 16) >> >> # define SPLL_SW_HILEN_MASK (0xf << 16) >> >> +# define SPLL_SW_HILEN_SHIFT 16 >> >> # define SPLL_SW_LOLEN(x) ((x) << 20) >> >> # define SPLL_SW_LOLEN_MASK (0xf << 20) >> >> +# define SPLL_SW_LOLEN_SHIFT 20 >> >> # define SPLL_DIVEN (1 << 24) >> >> # define SPLL_BYPASS_EN (1 << 25) >> >> # define SPLL_CHG_STATUS (1 << 29) >> >> -- >> >> 1.8.1.5 >> >> >> > >> >> > >
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index fea997e..78bec1a 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -1270,6 +1270,7 @@ static struct radeon_asic rs780_asic = { .get_sclk = &rs780_dpm_get_sclk, .get_mclk = &rs780_dpm_get_mclk, .print_power_state = &rs780_dpm_print_power_state, + .debugfs_print_current_performance_level = &rs780_dpm_debugfs_print_current_performance_level, }, .pflip = { .pre_page_flip = &rs600_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index b04b578..ca18957 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -433,6 +433,8 @@ u32 rs780_dpm_get_sclk(struct radeon_device *rdev, bool low); u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low); void rs780_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *ps); +void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m); /* uvd */ int r600_uvd_init(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c index bef832a..7f128c2 100644 --- a/drivers/gpu/drm/radeon/rs780_dpm.c +++ b/drivers/gpu/drm/radeon/rs780_dpm.c @@ -28,6 +28,7 @@ #include "r600_dpm.h" #include "rs780_dpm.h" #include "atom.h" +#include <linux/seq_file.h> static struct igp_ps *rs780_get_ps(struct radeon_ps *rps) { @@ -961,3 +962,25 @@ u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low) return pi->bootup_uma_clk; } + +void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m) +{ + struct radeon_ps *rps = rdev->pm.dpm.current_ps; + struct igp_ps *ps = rs780_get_ps(rps); + u32 current_fb_div = RREG32(FVTHROT_STATUS_REG0) & CURRENT_FEEDBACK_DIV_MASK; + u32 func_cntl = RREG32(CG_SPLL_FUNC_CNTL); + u32 post_div = ((func_cntl & SPLL_SW_HILEN_MASK) >> SPLL_SW_HILEN_SHIFT) + 1 + + ((func_cntl & SPLL_SW_LOLEN_MASK) >> SPLL_SW_LOLEN_SHIFT) + 1; + u32 sclk = (rdev->clock.spll.reference_freq * current_fb_div) / post_div; + + seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + + /* guess based on the current sclk */ + if (sclk < (ps->sclk_low + 500)) + seq_printf(m, "power level 0 sclk: %u vddc_index: %d\n", + ps->sclk_low, ps->min_voltage); + else + seq_printf(m, "power level 1 sclk: %u vddc_index: %d\n", + ps->sclk_high, ps->max_voltage); +} diff --git a/drivers/gpu/drm/radeon/rs780d.h b/drivers/gpu/drm/radeon/rs780d.h index b1142ed..cfbe9a4 100644 --- a/drivers/gpu/drm/radeon/rs780d.h +++ b/drivers/gpu/drm/radeon/rs780d.h @@ -28,6 +28,7 @@ # define SPLL_SLEEP (1 << 1) # define SPLL_REF_DIV(x) ((x) << 2) # define SPLL_REF_DIV_MASK (7 << 2) +# define SPLL_REF_DIV_SHIFT 2 # define SPLL_FB_DIV(x) ((x) << 5) # define SPLL_FB_DIV_MASK (0xff << 2) # define SPLL_FB_DIV_SHIFT 2 @@ -36,8 +37,10 @@ # define SPLL_PULSENUM_MASK (3 << 14) # define SPLL_SW_HILEN(x) ((x) << 16) # define SPLL_SW_HILEN_MASK (0xf << 16) +# define SPLL_SW_HILEN_SHIFT 16 # define SPLL_SW_LOLEN(x) ((x) << 20) # define SPLL_SW_LOLEN_MASK (0xf << 20) +# define SPLL_SW_LOLEN_SHIFT 20 # define SPLL_DIVEN (1 << 24) # define SPLL_BYPASS_EN (1 << 25) # define SPLL_CHG_STATUS (1 << 29)