* [PATCH] drm/radeon/dpm: implement force performance levels for rs780 @ 2013-07-31 22:33 Anthoine Bourgeois 2013-08-01 13:42 ` Deucher, Alexander 0 siblings, 1 reply; 3+ messages in thread From: Anthoine Bourgeois @ 2013-07-31 22:33 UTC (permalink / raw) To: Alex Deucher, Christian König, Jerome Glisse, Anthoine Bourgeois Cc: dri-devel Allows you to limit the selected power levels via sysfs. Force the feedback divider to select a power level. 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 | 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; + + 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; + 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 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* RE: [PATCH] drm/radeon/dpm: implement force performance levels for rs780 2013-07-31 22:33 [PATCH] drm/radeon/dpm: implement force performance levels for rs780 Anthoine Bourgeois @ 2013-08-01 13:42 ` Deucher, Alexander 2013-08-01 21:12 ` Anthoine Bourgeois 0 siblings, 1 reply; 3+ messages in thread From: Deucher, Alexander @ 2013-08-01 13:42 UTC (permalink / raw) To: Anthoine Bourgeois, Koenig, Christian, Jerome Glisse Cc: dri-devel@lists.freedesktop.org > -----Original Message----- > From: Anthoine Bourgeois [mailto:anthoine.bourgeois@gmail.com] > Sent: Wednesday, July 31, 2013 6:34 PM > To: Deucher, Alexander; Koenig, Christian; Jerome Glisse; Anthoine > Bourgeois > Cc: dri-devel@lists.freedesktop.org > 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@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 | 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 > ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] drm/radeon/dpm: implement force performance levels for rs780 2013-08-01 13:42 ` Deucher, Alexander @ 2013-08-01 21:12 ` Anthoine Bourgeois 0 siblings, 0 replies; 3+ messages in thread From: Anthoine Bourgeois @ 2013-08-01 21:12 UTC (permalink / raw) To: Deucher, Alexander Cc: Jerome Glisse, Koenig, Christian, dri-devel@lists.freedesktop.org [-- Attachment #1.1: Type: text/plain, Size: 6996 bytes --] 2013/8/1 Deucher, Alexander <Alexander.Deucher@amd.com> > > -----Original Message----- > > From: Anthoine Bourgeois [mailto:anthoine.bourgeois@gmail.com] > > Sent: Wednesday, July 31, 2013 6:34 PM > > To: Deucher, Alexander; Koenig, Christian; Jerome Glisse; Anthoine > > Bourgeois > > Cc: dri-devel@lists.freedesktop.org > > 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@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 | 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. > Oh yes, my mistake, fb_div shouldn't be in that condition. In my memory, I just wanted to check that sclk_low is equal to sclk_high. In that case, no need to force the fbdiv because there are the same. > > > + > > + 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. OK. > Also, > You are only forcing the sclk. It would probably also be a good idea to > force the voltage levels. > OK, I'm working on it but I can't test it, my board (RS880) doesn't seem to support the voltage scaling. I'll do my best. Anthoine > > > + 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 > > > > > [-- Attachment #1.2: Type: text/html, Size: 9201 bytes --] [-- Attachment #2: Type: text/plain, Size: 159 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2013-08-01 21:12 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-07-31 22:33 [PATCH] drm/radeon/dpm: implement force performance levels for rs780 Anthoine Bourgeois 2013-08-01 13:42 ` Deucher, Alexander 2013-08-01 21:12 ` Anthoine Bourgeois
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.