All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/radeon/dpm: implement force performance levels for rs780 (v2)
@ 2013-09-01 17:34 Anthoine Bourgeois
  2013-09-02 21:02 ` Alex Deucher
  0 siblings, 1 reply; 2+ messages in thread
From: Anthoine Bourgeois @ 2013-09-01 17:34 UTC (permalink / raw)
  To: Alex Deucher, Christian König, Jerome Glisse, dri-devel

Allows you to limit the selected power levels via sysfs.

Force the feedback divider to select a power level.

v2: fix checking in rs780_force_fbdiv,
    drop a duplicate divider structure in rs780_dpm_force_performance_level,
    Force the voltage level too.

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   | 89 ++++++++++++++++++++++++++++++------
 3 files changed, 77 insertions(+), 15 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 3d61d5a..0d81dbd 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..625d6ea 100644
--- a/drivers/gpu/drm/radeon/rs780_dpm.c
+++ b/drivers/gpu/drm/radeon/rs780_dpm.c
@@ -376,9 +376,8 @@ static void rs780_disable_vbios_powersaving(struct radeon_device *rdev)
 	WREG32_P(CG_INTGFX_MISC, 0, ~0xFFF00000);
 }
 
-static void rs780_force_voltage_to_high(struct radeon_device *rdev)
+static void rs780_force_voltage(struct radeon_device *rdev, u16 voltage)
 {
-	struct igp_power_info *pi = rs780_get_pi(rdev);
 	struct igp_ps *current_state = rs780_get_ps(rdev->pm.dpm.current_ps);
 
 	if ((current_state->max_voltage == RS780_VDDC_LEVEL_HIGH) &&
@@ -390,7 +389,7 @@ static void rs780_force_voltage_to_high(struct radeon_device *rdev)
 	udelay(1);
 
 	WREG32_P(FVTHROT_PWM_CTRL_REG0,
-		 STARTING_PWM_HIGHTIME(pi->max_voltage),
+		 STARTING_PWM_HIGHTIME(voltage),
 		 ~STARTING_PWM_HIGHTIME_MASK);
 
 	WREG32_P(FVTHROT_PWM_CTRL_REG0,
@@ -404,6 +403,26 @@ 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 == current_state->sclk_high)
+		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 +451,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,
@@ -649,7 +658,7 @@ int rs780_dpm_set_power_state(struct radeon_device *rdev)
 	rs780_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 
 	if (pi->voltage_control) {
-		rs780_force_voltage_to_high(rdev);
+		rs780_force_voltage(rdev, pi->max_voltage);
 		mdelay(5);
 	}
 
@@ -986,3 +995,53 @@ 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 igp_power_info *pi = rs780_get_pi(rdev);
+	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+	struct igp_ps *ps = rs780_get_ps(rps);
+	struct atom_clock_dividers dividers;
+	int ret;
+
+	rs780_clk_scaling_enable(rdev, false);
+	rs780_voltage_scaling_enable(rdev, false);
+
+	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
+		if (pi->voltage_control)
+			rs780_force_voltage(rdev, pi->max_voltage);
+
+		ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
+						     ps->sclk_high, false, &dividers);
+		if (ret)
+			return ret;
+
+		rs780_force_fbdiv(rdev, 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, &dividers);
+		if (ret)
+			return ret;
+
+		rs780_force_fbdiv(rdev, dividers.fb_div);
+
+		if (pi->voltage_control)
+			rs780_force_voltage(rdev, pi->min_voltage);
+	} else {
+		if (pi->voltage_control)
+			rs780_force_voltage(rdev, pi->max_voltage);
+
+		WREG32_P(FVTHROT_FBDIV_REG1, 0, ~FORCE_FEEDBACK_DIV);
+		rs780_clk_scaling_enable(rdev, true);
+
+		if (pi->voltage_control) {
+			rs780_voltage_scaling_enable(rdev, true);
+			rs780_enable_voltage_scaling(rdev, rps);
+		}
+	}
+
+	rdev->pm.dpm.forced_level = level;
+
+	return 0;
+}
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] drm/radeon/dpm: implement force performance levels for rs780 (v2)
  2013-09-01 17:34 [PATCH] drm/radeon/dpm: implement force performance levels for rs780 (v2) Anthoine Bourgeois
@ 2013-09-02 21:02 ` Alex Deucher
  0 siblings, 0 replies; 2+ messages in thread
From: Alex Deucher @ 2013-09-02 21:02 UTC (permalink / raw)
  To: Anthoine Bourgeois
  Cc: Alex Deucher, Jerome Glisse, Christian König,
	Maling list - DRI developers

On Sun, Sep 1, 2013 at 1:34 PM, Anthoine Bourgeois
<anthoine.bourgeois@gmail.com> wrote:
> Allows you to limit the selected power levels via sysfs.
>
> Force the feedback divider to select a power level.
>
> v2: fix checking in rs780_force_fbdiv,
>    drop a duplicate divider structure in rs780_dpm_force_performance_level,
>    Force the voltage level too.
>
> Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>

Patch looks good.  Thanks for doing this.  I'll add it to my queue.

Alex

> ---
> drivers/gpu/drm/radeon/radeon_asic.c |  1 +
> drivers/gpu/drm/radeon/radeon_asic.h |  2 +
> drivers/gpu/drm/radeon/rs780_dpm.c   | 89
> ++++++++++++++++++++++++++++++------
> 3 files changed, 77 insertions(+), 15 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 3d61d5a..0d81dbd 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..625d6ea 100644
> --- a/drivers/gpu/drm/radeon/rs780_dpm.c
> +++ b/drivers/gpu/drm/radeon/rs780_dpm.c
> @@ -376,9 +376,8 @@ static void rs780_disable_vbios_powersaving(struct
> radeon_device *rdev)
>         WREG32_P(CG_INTGFX_MISC, 0, ~0xFFF00000);
> }
>
> -static void rs780_force_voltage_to_high(struct radeon_device *rdev)
> +static void rs780_force_voltage(struct radeon_device *rdev, u16 voltage)
> {
> -       struct igp_power_info *pi = rs780_get_pi(rdev);
>         struct igp_ps *current_state =
> rs780_get_ps(rdev->pm.dpm.current_ps);
>
>         if ((current_state->max_voltage == RS780_VDDC_LEVEL_HIGH) &&
> @@ -390,7 +389,7 @@ static void rs780_force_voltage_to_high(struct
> radeon_device *rdev)
>         udelay(1);
>
>         WREG32_P(FVTHROT_PWM_CTRL_REG0,
> -                STARTING_PWM_HIGHTIME(pi->max_voltage),
> +                STARTING_PWM_HIGHTIME(voltage),
>                  ~STARTING_PWM_HIGHTIME_MASK);
>
>         WREG32_P(FVTHROT_PWM_CTRL_REG0,
> @@ -404,6 +403,26 @@ 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 == current_state->sclk_high)
> +               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 +451,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,
> @@ -649,7 +658,7 @@ int rs780_dpm_set_power_state(struct radeon_device
> *rdev)
>         rs780_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
>
>         if (pi->voltage_control) {
> -               rs780_force_voltage_to_high(rdev);
> +               rs780_force_voltage(rdev, pi->max_voltage);
>                 mdelay(5);
>         }
>
> @@ -986,3 +995,53 @@ 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 igp_power_info *pi = rs780_get_pi(rdev);
> +       struct radeon_ps *rps = rdev->pm.dpm.current_ps;
> +       struct igp_ps *ps = rs780_get_ps(rps);
> +       struct atom_clock_dividers dividers;
> +       int ret;
> +
> +       rs780_clk_scaling_enable(rdev, false);
> +       rs780_voltage_scaling_enable(rdev, false);
> +
> +       if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
> +               if (pi->voltage_control)
> +                       rs780_force_voltage(rdev, pi->max_voltage);
> +
> +               ret = radeon_atom_get_clock_dividers(rdev,
> COMPUTE_ENGINE_PLL_PARAM,
> +                                                    ps->sclk_high, false,
> &dividers);
> +               if (ret)
> +                       return ret;
> +
> +               rs780_force_fbdiv(rdev, 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,
> &dividers);
> +               if (ret)
> +                       return ret;
> +
> +               rs780_force_fbdiv(rdev, dividers.fb_div);
> +
> +               if (pi->voltage_control)
> +                       rs780_force_voltage(rdev, pi->min_voltage);
> +       } else {
> +               if (pi->voltage_control)
> +                       rs780_force_voltage(rdev, pi->max_voltage);
> +
> +               WREG32_P(FVTHROT_FBDIV_REG1, 0, ~FORCE_FEEDBACK_DIV);
> +               rs780_clk_scaling_enable(rdev, true);
> +
> +               if (pi->voltage_control) {
> +                       rs780_voltage_scaling_enable(rdev, true);
> +                       rs780_enable_voltage_scaling(rdev, rps);
> +               }
> +       }
> +
> +       rdev->pm.dpm.forced_level = level;
> +
> +       return 0;
> +}
> --
> 1.8.1.5
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-09-02 21:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-01 17:34 [PATCH] drm/radeon/dpm: implement force performance levels for rs780 (v2) Anthoine Bourgeois
2013-09-02 21:02 ` Alex Deucher

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.