drm/radeon/dpm: implement force performance levels for rs780
Subsystems (2)
PATCH 1/1 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.
---
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(-)
drivers/gpu/drm/radeon/radeon_asic.c +0 -0
@@ -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,drivers/gpu/drm/radeon/radeon_asic.h +0 -0
@@ -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);
drivers/gpu/drm/radeon/rs780_dpm.c +0 -0
@@ -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;
+}
Signature · 1 line
1.8.1.5
Deucher, Alexander
maintainerQuoted 9 lines
-----Original Message-----
From: Anthoine Bourgeois [mailto:[email protected]]
Sent: Wednesday, July 31, 2013 6:34 PM
To: Deucher, Alexander; Koenig, Christian; Jerome Glisse; Anthoine Bourgeois
Cc: [email protected]
Subject: [PATCH] drm/radeon/dpm: implement force performance levels for rs780
Quoted 3 lines
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
Quoted 48 lines
Signed-off-by Anthoine Bourgeois <[email protected]>--- 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(-)drivers/gpu/drm/radeon/radeon_asic.c +1
-0@@ -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, },drivers/gpu/drm/radeon/radeon_asic.c +0
-0.pflip = { .pre_page_flip = &rs600_pre_page_flip,drivers/gpu/drm/radeon/radeon_asic.h +2
-0@@ -437,6 +437,8 @@ void rs780_dpm_print_power_state(structradeon_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 */
intr600_uvd_init(struct radeon_device *rdev);drivers/gpu/drm/radeon/rs780_dpm.c +0
-0@@ -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);
drivers/gpu/drm/radeon/rs780_dpm.c static void rs780_force_voltage_to_high(struct · line 415
Quoted 10 lines
drivers/gpu/drm/radeon/rs780_dpm.c +7
-0} +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.
Quoted 48 lines
drivers/gpu/drm/radeon/rs780_dpm.c +4
-0+ +WREG32_P (GFX_MACRO_BYPASS_CNTL ,SPLL_BYPASS_CNTL , ~SPLL_BYPASS_CNTL ); + + WREG32_P(FVTHROT_FBDIV_REG2,
FORCED_FEEDBACK_DIV(fb_div),drivers/gpu/drm/radeon/rs780_dpm.c +2
-0+ ~FORCED_FEEDBACK_DIV_MASK); + WREG32_P(FVTHROT_FBDIV_REG1,
STARTING_FEEDBACK_DIV(fb_div),drivers/gpu/drm/radeon/rs780_dpm.c +2
-0+ ~STARTING_FEEDBACK_DIV_MASK); + WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV,~FORCE_FEEDBACK_DIV);
drivers/gpu/drm/radeon/rs780_dpm.c +6
-7+ +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);
drivers/gpu/drm/radeon/rs780_dpm.c +1
-4- -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 @@ voidrs780_dpm_debugfs_print_current_performance_level(struct
radeon_device*rde
drivers/gpu/drm/radeon/rs780_dpm.c
Quoted 10 lines
drivers/gpu/drm/radeon/rs780_dpm.c +7
-0seq_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.
Quoted 35 lines
drivers/gpu/drm/radeon/rs780_dpm.c +6
-0+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,drivers/gpu/drm/radeon/rs780_dpm.c +1
-0+ ps->sclk_high, false,
&max_dividers);drivers/gpu/drm/radeon/rs780_dpm.c +6
-0+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,drivers/gpu/drm/radeon/rs780_dpm.c +1
-0+ ps->sclk_low, false,
&min_dividers);drivers/gpu/drm/radeon/rs780_dpm.c +6
-0+if (ret) +return ret; + +rs780_force_fbdiv (rdev, min_dividers.fb_div); + }else { + WREG32_P(FVTHROT_FBDIV_REG1, 0,~FORCE_FEEDBACK_DIV);
drivers/gpu/drm/radeon/rs780_dpm.c +7
-1+rs780_clk_scaling_enable (rdev, true); + } + + rdev->pm.dpm.forced_level = level; + +return 0 ; +} --1.8.1.5
2013/8/1 Deucher, Alexander <[email protected]>
Quoted 70 lines
Quoted 9 lines
-----Original Message-----
From: Anthoine Bourgeois [mailto:[email protected]]
Sent: Wednesday, July 31, 2013 6:34 PM
To: Deucher, Alexander; Koenig, Christian; Jerome Glisse; Anthoine Bourgeois
Cc: [email protected]
Subject: [PATCH] drm/radeon/dpm: implement force performance levels for rs780Quoted 3 lines
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
Quoted 53 lines
Signed-off-by Anthoine Bourgeois <[email protected]>--- 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(-)drivers/gpu/drm/radeon/radeon_asic.c +1
-0@@ -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,drivers/gpu/drm/radeon/radeon_asic.h +2
-0@@ -437,6 +437,8 @@ void rs780_dpm_print_power_state(structradeon_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 */
intr600_uvd_init(struct radeon_device *rdev);drivers/gpu/drm/radeon/rs780_dpm.c +3
-0@@ -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-
Quoted 8 lines
drivers/gpu/drm/radeon/rs780_dpm.c static void rs780_force_voltage_to_high(struct · line 415
Quoted 5 lines
drivers/gpu/drm/radeon/rs780_dpm.c +4
-0>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.
Quoted 54 lines
Quoted 54 lines
drivers/gpu/drm/radeon/rs780_dpm.c +4
-0+ +WREG32_P (GFX_MACRO_BYPASS_CNTL ,SPLL_BYPASS_CNTL , ~SPLL_BYPASS_CNTL ); + + WREG32_P(FVTHROT_FBDIV_REG2,
FORCED_FEEDBACK_DIV(fb_div),drivers/gpu/drm/radeon/rs780_dpm.c +2
-0+ ~FORCED_FEEDBACK_DIV_MASK); + WREG32_P(FVTHROT_FBDIV_REG1,
STARTING_FEEDBACK_DIV(fb_div),drivers/gpu/drm/radeon/rs780_dpm.c +2
-0+ ~STARTING_FEEDBACK_DIV_MASK); + WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV,~FORCE_FEEDBACK_DIV);
drivers/gpu/drm/radeon/rs780_dpm.c +6
-7+ +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);
drivers/gpu/drm/radeon/rs780_dpm.c +1
-4- -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 @@ voidrs780_dpm_debugfs_print_current_performance_level(struct
radeon_device*rde
seq_printf(m, "power level 1 sclk: %uvddc_index: %d\n",
ps->sclk_high,ps->max_voltage);
}drivers/gpu/drm/radeon/rs780_dpm.c +2
-0+ +int rs780_dpm_force_performance_level(struct radeon_device *rdev,
Quoted 8 lines
drivers/gpu/drm/radeon/rs780_dpm.c
Quoted 5 lines
drivers/gpu/drm/radeon/rs780_dpm.c +5
-0+ 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.
Quoted 4 lines
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
Quoted 28 lines
Quoted 28 lines
drivers/gpu/drm/radeon/rs780_dpm.c +6
-0+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);drivers/gpu/drm/radeon/rs780_dpm.c +6
-0+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);drivers/gpu/drm/radeon/rs780_dpm.c +6
-0+if (ret) +return ret; + +rs780_force_fbdiv (rdev, min_dividers.fb_div); + }else { + WREG32_P(FVTHROT_FBDIV_REG1, 0,~FORCE_FEEDBACK_DIV);
drivers/gpu/drm/radeon/rs780_dpm.c +2
-0+rs780_clk_scaling_enable (rdev, true); + }
Quoted 11 lines
Quoted 8 lines
drivers/gpu/drm/radeon/rs780_dpm.c +5
-1+ + rdev->pm.dpm.forced_level = level; + +return 0 ; +} --1.8.1.5
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel