drm/radeon/dpm: validate voltages against dispclk requirements
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 22 Mar 2013 19:59:10 +0000 (15:59 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 27 Jun 2013 23:16:39 +0000 (19:16 -0400)
Validate the voltages against the voltage requirements of the
dispclk.  We currently don't adjust the disp clock so it never
changes, but we need to filter out voltage levels that are too
low none the less.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/btc_dpm.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atombios.c

index e0d315e..a55b23d 100644 (file)
@@ -2178,21 +2178,26 @@ static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
                                           ps->low.mclk, max_limits->vddci, &ps->low.vddci);
        btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
                                           ps->low.mclk, max_limits->vddc, &ps->low.vddc);
-       /* XXX validate the voltage required for display */
+       btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
+                                          rdev->clock.current_dispclk, max_limits->vddc, &ps->low.vddc);
+
        btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
                                           ps->medium.sclk, max_limits->vddc, &ps->medium.vddc);
        btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
                                           ps->medium.mclk, max_limits->vddci, &ps->medium.vddci);
        btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
                                           ps->medium.mclk, max_limits->vddc, &ps->medium.vddc);
-       /* XXX validate the voltage required for display */
+       btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
+                                          rdev->clock.current_dispclk, max_limits->vddc, &ps->medium.vddc);
+
        btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
                                           ps->high.sclk, max_limits->vddc, &ps->high.vddc);
        btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
                                           ps->high.mclk, max_limits->vddci, &ps->high.vddci);
        btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
                                           ps->high.mclk, max_limits->vddc, &ps->high.vddc);
-       /* XXX validate the voltage required for display */
+       btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
+                                          rdev->clock.current_dispclk, max_limits->vddc, &ps->high.vddc);
 
        btc_apply_voltage_delta_rules(rdev, max_limits->vddc, max_limits->vddci,
                                      &ps->low.vddc, &ps->low.vddci);
@@ -2495,6 +2500,22 @@ int btc_dpm_init(struct radeon_device *rdev)
        if (ret)
                return ret;
 
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
+               kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL);
+       if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
+               r600_free_extended_power_table(rdev);
+               return -ENOMEM;
+       }
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 800;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 800;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 800;
+
        if (rdev->pm.dpm.voltage_response_time == 0)
                rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
        if (rdev->pm.dpm.backbias_response_time == 0)
@@ -2628,6 +2649,7 @@ void btc_dpm_fini(struct radeon_device *rdev)
        }
        kfree(rdev->pm.dpm.ps);
        kfree(rdev->pm.dpm.priv);
+       kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries);
        r600_free_extended_power_table(rdev);
 }
 
index af05965..21c064b 100644 (file)
@@ -866,7 +866,9 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
                btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
                                                   ps->performance_levels[i].mclk,
                                                   max_limits->vddc,  &ps->performance_levels[i].vddc);
-               /* XXX validate the voltage required for display */
+               btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
+                                                  rdev->clock.current_dispclk,
+                                                  max_limits->vddc,  &ps->performance_levels[i].vddc);
        }
 
        for (i = 0; i < ps->performance_level_count; i++) {
@@ -3910,6 +3912,22 @@ int ni_dpm_init(struct radeon_device *rdev)
        if (ret)
                return ret;
 
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
+               kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL);
+       if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
+               r600_free_extended_power_table(rdev);
+               return -ENOMEM;
+       }
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000;
+       rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900;
+
        ni_patch_dependency_tables_based_on_leakage(rdev);
 
        if (rdev->pm.dpm.voltage_response_time == 0)
@@ -4094,6 +4112,7 @@ void ni_dpm_fini(struct radeon_device *rdev)
        }
        kfree(rdev->pm.dpm.ps);
        kfree(rdev->pm.dpm.priv);
+       kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries);
        r600_free_extended_power_table(rdev);
 }
 
index e6ded6f..9de8ae2 100644 (file)
@@ -200,6 +200,7 @@ struct radeon_clock {
        uint32_t default_mclk;
        uint32_t default_sclk;
        uint32_t default_dispclk;
+       uint32_t current_dispclk;
        uint32_t dp_extclk;
        uint32_t max_pixel_clock;
 };
@@ -1298,6 +1299,7 @@ struct radeon_dpm_dynamic_state {
        struct radeon_clock_voltage_dependency_table vddc_dependency_on_sclk;
        struct radeon_clock_voltage_dependency_table vddci_dependency_on_mclk;
        struct radeon_clock_voltage_dependency_table vddc_dependency_on_mclk;
+       struct radeon_clock_voltage_dependency_table vddc_dependency_on_dispclk;
        struct radeon_clock_array valid_sclk_values;
        struct radeon_clock_array valid_mclk_values;
        struct radeon_clock_and_voltage_limits max_clock_voltage_on_dc;
index 0ac7294..c707ed0 100644 (file)
@@ -1243,6 +1243,7 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
                        }
                        rdev->clock.dp_extclk =
                                le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
+                       rdev->clock.current_dispclk = rdev->clock.default_dispclk;
                }
                *dcpll = *p1pll;