> -----Original Message----- > From: Anthoine Bourgeois [mailto:anthoine.bourgeois@xxxxxxxxx] > Sent: Wednesday, July 31, 2013 6:34 PM > To: Deucher, Alexander; Koenig, Christian; Jerome Glisse; Anthoine > Bourgeois > Cc: dri-devel@xxxxxxxxxxxxxxxxxxxxx > Subject: [PATCH] drm/radeon/dpm: implement force performance levels for > rs780 > > Allows you to limit the selected power levels via sysfs. > > Force the feedback divider to select a power level. Nice work. A few comments below. Alex > > Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@xxxxxxxxx> > --- > drivers/gpu/drm/radeon/radeon_asic.c | 1 + > drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ > drivers/gpu/drm/radeon/rs780_dpm.c | 67 > ++++++++++++++++++++++++++++++------ > 3 files changed, 59 insertions(+), 11 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon_asic.c > b/drivers/gpu/drm/radeon/radeon_asic.c > index f8f8b31..437d357 100644 > --- a/drivers/gpu/drm/radeon/radeon_asic.c > +++ b/drivers/gpu/drm/radeon/radeon_asic.c > @@ -1272,6 +1272,7 @@ static struct radeon_asic rs780_asic = { > .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, > + .force_performance_level = > &rs780_dpm_force_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 902479f..09841fc 100644 > --- a/drivers/gpu/drm/radeon/radeon_asic.h > +++ b/drivers/gpu/drm/radeon/radeon_asic.h > @@ -437,6 +437,8 @@ 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); > +int rs780_dpm_force_performance_level(struct radeon_device *rdev, > + enum radeon_dpm_forced_level level); > > /* 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 d1a1ce7..df58e34 100644 > --- a/drivers/gpu/drm/radeon/rs780_dpm.c > +++ b/drivers/gpu/drm/radeon/rs780_dpm.c > @@ -404,6 +404,27 @@ static void rs780_force_voltage_to_high(struct > radeon_device *rdev) > WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); > } > > +static void rs780_force_fbdiv(struct radeon_device *rdev, u32 fb_div) > +{ > + struct igp_ps *current_state = rs780_get_ps(rdev- > >pm.dpm.current_ps); > + > + if ((current_state->sclk_low == fb_div) && > + (current_state->sclk_high == fb_div)) > + return; I'm not quite sure what you are checking here. > + > + WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, > ~SPLL_BYPASS_CNTL); > + > + WREG32_P(FVTHROT_FBDIV_REG2, > FORCED_FEEDBACK_DIV(fb_div), > + ~FORCED_FEEDBACK_DIV_MASK); > + WREG32_P(FVTHROT_FBDIV_REG1, > STARTING_FEEDBACK_DIV(fb_div), > + ~STARTING_FEEDBACK_DIV_MASK); > + WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, > ~FORCE_FEEDBACK_DIV); > + > + udelay(100); > + > + WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); > +} > + > static int rs780_set_engine_clock_scaling(struct radeon_device *rdev, > struct radeon_ps *new_ps, > struct radeon_ps *old_ps) > @@ -432,17 +453,7 @@ static int rs780_set_engine_clock_scaling(struct > radeon_device *rdev, > if (ret) > return ret; > > - WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, > ~SPLL_BYPASS_CNTL); > - > - WREG32_P(FVTHROT_FBDIV_REG2, > FORCED_FEEDBACK_DIV(max_dividers.fb_div), > - ~FORCED_FEEDBACK_DIV_MASK); > - WREG32_P(FVTHROT_FBDIV_REG1, > STARTING_FEEDBACK_DIV(max_dividers.fb_div), > - ~STARTING_FEEDBACK_DIV_MASK); > - WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, > ~FORCE_FEEDBACK_DIV); > - > - udelay(100); > - > - WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); > + rs780_force_fbdiv(rdev, max_dividers.fb_div); > > if (max_dividers.fb_div > min_dividers.fb_div) { > WREG32_P(FVTHROT_FBDIV_REG0, > @@ -986,3 +997,37 @@ void > rs780_dpm_debugfs_print_current_performance_level(struct > radeon_device *rde > seq_printf(m, "power level 1 sclk: %u vddc_index: %d\n", > ps->sclk_high, ps->max_voltage); > } > + > +int rs780_dpm_force_performance_level(struct radeon_device *rdev, > + enum radeon_dpm_forced_level level) > +{ > + struct radeon_ps *rps = rdev->pm.dpm.current_ps; > + struct igp_ps *ps = rs780_get_ps(rps); > + struct atom_clock_dividers min_dividers, max_dividers; You can drop the separate min and max and just use a single dividers struct. Also, You are only forcing the sclk. It would probably also be a good idea to force the voltage levels. > + int ret; > + > + rs780_clk_scaling_enable(rdev, false); > + > + if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { > + ret = radeon_atom_get_clock_dividers(rdev, > COMPUTE_ENGINE_PLL_PARAM, > + ps->sclk_high, false, > &max_dividers); > + if (ret) > + return ret; > + > + rs780_force_fbdiv(rdev, max_dividers.fb_div); > + } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { > + ret = radeon_atom_get_clock_dividers(rdev, > COMPUTE_ENGINE_PLL_PARAM, > + ps->sclk_low, false, > &min_dividers); > + if (ret) > + return ret; > + > + rs780_force_fbdiv(rdev, min_dividers.fb_div); > + } else { > + WREG32_P(FVTHROT_FBDIV_REG1, 0, > ~FORCE_FEEDBACK_DIV); > + rs780_clk_scaling_enable(rdev, true); > + } > + > + rdev->pm.dpm.forced_level = level; > + > + return 0; > +} > -- > 1.8.1.5 > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel