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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 






2013/8/1 Deucher, Alexander <Alexander.Deucher@xxxxxxx>
> -----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.

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
>



_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel

[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux