[PATCH] drm/radeon/dpm: implement force performance levels for rs780

Anthoine Bourgeois anthoine.bourgeois at gmail.com
Thu Aug 1 14:12:10 PDT 2013


2013/8/1 Deucher, Alexander <Alexander.Deucher at amd.com>

> > -----Original Message-----
> > From: Anthoine Bourgeois [mailto:anthoine.bourgeois at gmail.com]
> > Sent: Wednesday, July 31, 2013 6:34 PM
> > To: Deucher, Alexander; Koenig, Christian; Jerome Glisse; Anthoine
> > Bourgeois
> > Cc: dri-devel at 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 at 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
> >
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20130801/89e98914/attachment.html>


More information about the dri-devel mailing list