From: Alex Deucher <alexander.deuc...@amd.com>

Use a dedicated copy of the current power state since
we may have to adjust it on the fly.

v2: fix up redundant state sets

Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/radeon/btc_dpm.c     |  340 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/btc_dpm.h     |    2 +
 drivers/gpu/drm/radeon/cypress_dpm.h |    1 +
 drivers/gpu/drm/radeon/radeon.h      |   13 ++
 drivers/gpu/drm/radeon/radeon_pm.c   |   43 ++++-
 drivers/gpu/drm/radeon/rv770_dpm.c   |   10 +
 6 files changed, 400 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c
index 2662ef0..989592e 100644
--- a/drivers/gpu/drm/radeon/btc_dpm.c
+++ b/drivers/gpu/drm/radeon/btc_dpm.c
@@ -1152,6 +1152,164 @@ static const u32 turks_sysls_enable[] =

 #endif

+u32 btc_valid_sclk[] =
+{
+       5000,   10000,  15000,  20000,  25000,  30000,  35000,  40000,  45000,  
50000,
+       55000,  60000,  65000,  70000,  75000,  80000,  85000,  90000,  95000,  
100000,
+       105000, 110000, 11500,  120000, 125000, 130000, 135000, 140000, 145000, 
150000,
+       155000, 160000, 165000, 170000, 175000, 180000, 185000, 190000, 195000, 
200000
+};
+
+static const struct radeon_blacklist_clocks btc_blacklist_clocks[] =
+{
+        { 10000, 30000, RADEON_SCLK_UP },
+        { 15000, 30000, RADEON_SCLK_UP },
+        { 20000, 30000, RADEON_SCLK_UP },
+        { 25000, 30000, RADEON_SCLK_UP }
+};
+
+static void btc_apply_voltage_dependency_rules(struct 
radeon_clock_voltage_dependency_table *table,
+                                              u32 clock, u16 max_voltage, u16 
*voltage)
+{
+       u32 i;
+
+       if ((table == NULL) || (table->count == 0))
+               return;
+
+       for (i= 0; i < table->count; i++) {
+               if (clock <= table->entries[i].clk) {
+                       if (*voltage < table->entries[i].v)
+                               *voltage = (u16)((table->entries[i].v < 
max_voltage) ?
+                                                 table->entries[i].v : 
max_voltage);
+                       return;
+               }
+       }
+
+       *voltage = (*voltage > max_voltage) ? *voltage : max_voltage;
+}
+
+static u32 btc_find_valid_clock(struct radeon_clock_array *clocks,
+                               u32 max_clock, u32 requested_clock)
+{
+       unsigned int i;
+
+       if ((clocks == NULL) || (clocks->count == 0))
+               return (requested_clock < max_clock) ? requested_clock : 
max_clock;
+
+       for (i = 0; i < clocks->count; i++) {
+               if (clocks->values[i] >= requested_clock)
+                       return (clocks->values[i] < max_clock) ? 
clocks->values[i] : max_clock;
+       }
+
+       return (clocks->values[clocks->count - 1] < max_clock) ?
+               clocks->values[clocks->count - 1] : max_clock;
+}
+
+static u32 btc_get_valid_mclk(struct radeon_device *rdev,
+                             u32 max_mclk, u32 requested_mclk)
+{
+       return btc_find_valid_clock(&rdev->pm.dpm.dyn_state.valid_mclk_values,
+                                   max_mclk, requested_mclk);
+}
+
+static u32 btc_get_valid_sclk(struct radeon_device *rdev,
+                             u32 max_sclk, u32 requested_sclk)
+{
+       return btc_find_valid_clock(&rdev->pm.dpm.dyn_state.valid_sclk_values,
+                                   max_sclk, requested_sclk);
+}
+
+static void btc_skip_blacklist_clocks(struct radeon_device *rdev,
+                                     const u32 max_sclk, const u32 max_mclk,
+                                     u32 *sclk, u32 *mclk)
+{
+       int i, num_blacklist_clocks;
+
+       if ((sclk == NULL) || (mclk == NULL))
+               return;
+
+       num_blacklist_clocks = ARRAY_SIZE(btc_blacklist_clocks);
+
+       for (i = 0; i < num_blacklist_clocks; i++) {
+               if ((btc_blacklist_clocks[i].sclk == *sclk) &&
+                   (btc_blacklist_clocks[i].mclk == *mclk))
+                       break;
+       }
+
+       if (i < num_blacklist_clocks) {
+               if (btc_blacklist_clocks[i].action == RADEON_SCLK_UP) {
+                       *sclk = btc_get_valid_sclk(rdev, max_sclk, *sclk + 1);
+
+                       if (*sclk < max_sclk)
+                               btc_skip_blacklist_clocks(rdev, max_sclk, 
max_mclk, sclk, mclk);
+               }
+       }
+}
+
+static void btc_adjust_clock_combinations(struct radeon_device *rdev,
+                                         const struct 
radeon_clock_and_voltage_limits *max_limits,
+                                         struct rv7xx_pl *pl)
+{
+
+       if ((pl->mclk == 0) || (pl->sclk == 0))
+               return;
+
+       if (pl->mclk == pl->sclk)
+               return;
+
+       if (pl->mclk > pl->sclk) {
+               if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > 
rdev->pm.dpm.dyn_state.mclk_sclk_ratio)
+                       pl->sclk = btc_get_valid_sclk(rdev,
+                                                     max_limits->sclk,
+                                                     (pl->mclk +
+                                                      
(rdev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) /
+                                                     
rdev->pm.dpm.dyn_state.mclk_sclk_ratio);
+       } else {
+               if ((pl->sclk - pl->mclk) > 
rdev->pm.dpm.dyn_state.sclk_mclk_delta)
+                       pl->mclk = btc_get_valid_mclk(rdev,
+                                                     max_limits->mclk,
+                                                     pl->sclk -
+                                                     
rdev->pm.dpm.dyn_state.sclk_mclk_delta);
+       }
+}
+
+static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage)
+{
+       unsigned int i;
+
+       for (i = 0; i < table->count; i++) {
+               if (voltage <= table->entries[i].value)
+                       return table->entries[i].value;
+       }
+
+       return table->entries[table->count - 1].value;
+}
+
+static void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
+                                         u16 max_vddc, u16 max_vddci,
+                                         u16 *vddc, u16 *vddci)
+{
+       struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       u16 new_voltage;
+
+       if ((0 == *vddc) || (0 == *vddci))
+               return;
+
+       if (*vddc > *vddci) {
+               if ((*vddc - *vddci) > rdev->pm.dpm.dyn_state.vddc_vddci_delta) 
{
+                       new_voltage = 
btc_find_voltage(&eg_pi->vddci_voltage_table,
+                                                      (*vddc - 
rdev->pm.dpm.dyn_state.vddc_vddci_delta));
+                       *vddci = (new_voltage < max_vddci) ? new_voltage : 
max_vddci;
+               }
+       } else {
+               if ((*vddci - *vddc) > rdev->pm.dpm.dyn_state.vddc_vddci_delta) 
{
+                       new_voltage = 
btc_find_voltage(&eg_pi->vddc_voltage_table,
+                                                      (*vddci - 
rdev->pm.dpm.dyn_state.vddc_vddci_delta));
+                       *vddc = (new_voltage < max_vddc) ? new_voltage : 
max_vddc;
+               }
+       }
+}
+
 static void btc_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
                                             bool enable)
 {
@@ -1901,6 +2059,169 @@ static void btc_init_stutter_mode(struct radeon_device 
*rdev)
        }
 }

+static void btc_apply_state_adjust_rules(struct radeon_device *rdev)
+{
+       struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
+       struct rv7xx_ps *ps = rv770_get_ps(rps);
+       struct radeon_clock_and_voltage_limits *max_limits;
+       bool disable_mclk_switching;
+       u32 mclk, sclk;
+       u16 vddc, vddci;
+
+       /* point to the hw copy since this function will modify the ps */
+       eg_pi->hw_ps = *ps;
+       rdev->pm.dpm.hw_ps.ps_priv = &eg_pi->hw_ps;
+       ps = &eg_pi->hw_ps;
+
+       if (rdev->pm.dpm.new_active_crtc_count > 1)
+               disable_mclk_switching = true;
+       else
+               disable_mclk_switching = false;
+
+       if (rdev->pm.dpm.ac_power)
+               max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
+       else
+               max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
+
+       if (rdev->pm.dpm.ac_power == false) {
+               if (ps->high.mclk > max_limits->mclk)
+                       ps->high.mclk = max_limits->mclk;
+               if (ps->high.sclk > max_limits->sclk)
+                       ps->high.sclk = max_limits->sclk;
+               if (ps->high.vddc > max_limits->vddc)
+                       ps->high.vddc = max_limits->vddc;
+               if (ps->high.vddci > max_limits->vddci)
+                       ps->high.vddci = max_limits->vddci;
+
+               if (ps->medium.mclk > max_limits->mclk)
+                       ps->medium.mclk = max_limits->mclk;
+               if (ps->medium.sclk > max_limits->sclk)
+                       ps->medium.sclk = max_limits->sclk;
+               if (ps->medium.vddc > max_limits->vddc)
+                       ps->medium.vddc = max_limits->vddc;
+               if (ps->medium.vddci > max_limits->vddci)
+                       ps->medium.vddci = max_limits->vddci;
+
+               if (ps->low.mclk > max_limits->mclk)
+                       ps->low.mclk = max_limits->mclk;
+               if (ps->low.sclk > max_limits->sclk)
+                       ps->low.sclk = max_limits->sclk;
+               if (ps->low.vddc > max_limits->vddc)
+                       ps->low.vddc = max_limits->vddc;
+               if (ps->low.vddci > max_limits->vddci)
+                       ps->low.vddci = max_limits->vddci;
+       }
+
+       /* XXX validate the min clocks required for display */
+
+       if (disable_mclk_switching) {
+               sclk = ps->low.sclk;
+               mclk = ps->high.mclk;
+               vddc = ps->low.vddc;
+               vddci = ps->high.vddci;
+       } else {
+               sclk = ps->low.sclk;
+               mclk = ps->low.mclk;
+               vddc = ps->low.vddc;
+               vddci = ps->low.vddci;
+       }
+
+       /* adjusted low state */
+       ps->low.sclk = sclk;
+       ps->low.mclk = mclk;
+       ps->low.vddc = vddc;
+       ps->low.vddci = vddci;
+
+       btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
+                                 &ps->low.sclk, &ps->low.mclk);
+
+       /* adjusted medium, high states */
+       if (ps->medium.sclk < ps->low.sclk)
+               ps->medium.sclk = ps->low.sclk;
+       if (ps->medium.vddc < ps->low.vddc)
+               ps->medium.vddc = ps->low.vddc;
+       if (ps->high.sclk < ps->medium.sclk)
+               ps->high.sclk = ps->medium.sclk;
+       if (ps->high.vddc < ps->medium.vddc)
+               ps->high.vddc = ps->medium.vddc;
+
+       if (disable_mclk_switching) {
+               mclk = ps->low.mclk;
+               if (mclk < ps->medium.mclk)
+                       mclk = ps->medium.mclk;
+               if (mclk < ps->high.mclk)
+                       mclk = ps->high.mclk;
+               ps->low.mclk = mclk;
+               ps->low.vddci = vddci;
+               ps->medium.mclk = mclk;
+               ps->medium.vddci = vddci;
+               ps->high.mclk = mclk;
+               ps->high.vddci = vddci;
+       } else {
+               if (ps->medium.mclk < ps->low.mclk)
+                       ps->medium.mclk = ps->low.mclk;
+               if (ps->medium.vddci < ps->low.vddci)
+                       ps->medium.vddci = ps->low.vddci;
+               if (ps->high.mclk < ps->medium.mclk)
+                       ps->high.mclk = ps->medium.mclk;
+               if (ps->high.vddci < ps->medium.vddci)
+                       ps->high.vddci = ps->medium.vddci;
+       }
+
+       btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
+                                 &ps->medium.sclk, &ps->medium.mclk);
+       btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
+                                 &ps->high.sclk, &ps->high.mclk);
+
+       btc_adjust_clock_combinations(rdev, max_limits, &ps->low);
+       btc_adjust_clock_combinations(rdev, max_limits, &ps->medium);
+       btc_adjust_clock_combinations(rdev, max_limits, &ps->high);
+
+       
btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+                                          ps->low.sclk, max_limits->vddc, 
&ps->low.vddc);
+       
btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+                                          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_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_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_delta_rules(rdev, max_limits->vddc, max_limits->vddci,
+                                     &ps->low.vddc, &ps->low.vddci);
+       btc_apply_voltage_delta_rules(rdev, max_limits->vddc, max_limits->vddci,
+                                     &ps->medium.vddc, &ps->medium.vddci);
+       btc_apply_voltage_delta_rules(rdev, max_limits->vddc, max_limits->vddci,
+                                     &ps->high.vddc, &ps->high.vddci);
+
+       if ((ps->high.vddc <= 
rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc) &&
+           (ps->medium.vddc <= 
rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc) &&
+           (ps->low.vddc <= 
rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc))
+               ps->dc_compatible = true;
+       else
+               ps->dc_compatible = false;
+
+       if (ps->low.vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
+               ps->low.flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
+       if (ps->medium.vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
+               ps->medium.flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
+       if (ps->high.vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
+               ps->high.flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
+}
+
 void btc_dpm_reset_asic(struct radeon_device *rdev)
 {
        rv770_restrict_performance_levels_before_switch(rdev);
@@ -1913,6 +2234,8 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
 {
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);

+       btc_apply_state_adjust_rules(rdev);
+
        btc_disable_ulv(rdev);
        btc_set_boot_state_timing(rdev);
        rv770_restrict_performance_levels_before_switch(rdev);
@@ -2121,6 +2444,9 @@ int btc_dpm_init(struct radeon_device *rdev)
        ret = rv7xx_parse_power_table(rdev);
        if (ret)
                return ret;
+       ret = r600_parse_extended_power_table(rdev);
+       if (ret)
+               return ret;

        if (rdev->pm.dpm.voltage_response_time == 0)
                rdev->pm.dpm.voltage_response_time = 
R600_VOLTAGERESPONSETIME_DFLT;
@@ -2230,6 +2556,19 @@ int btc_dpm_init(struct radeon_device *rdev)

        pi->sram_end = SMC_RAM_END;

+       rdev->pm.dpm.dyn_state.mclk_sclk_ratio = 4;
+       rdev->pm.dpm.dyn_state.vddc_vddci_delta = 200;
+       rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2 = 900;
+       rdev->pm.dpm.dyn_state.valid_sclk_values.count = 
ARRAY_SIZE(btc_valid_sclk);
+       rdev->pm.dpm.dyn_state.valid_sclk_values.values = btc_valid_sclk;
+       rdev->pm.dpm.dyn_state.valid_mclk_values.count = 0;
+       rdev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;
+
+       if (rdev->family == CHIP_TURKS)
+               rdev->pm.dpm.dyn_state.sclk_mclk_delta = 15000;
+       else
+               rdev->pm.dpm.dyn_state.sclk_mclk_delta = 10000;
+
        return 0;
 }

@@ -2242,4 +2581,5 @@ void btc_dpm_fini(struct radeon_device *rdev)
        }
        kfree(rdev->pm.dpm.ps);
        kfree(rdev->pm.dpm.priv);
+       r600_free_extended_power_table(rdev);
 }
diff --git a/drivers/gpu/drm/radeon/btc_dpm.h b/drivers/gpu/drm/radeon/btc_dpm.h
index 56b1957..807024d 100644
--- a/drivers/gpu/drm/radeon/btc_dpm.h
+++ b/drivers/gpu/drm/radeon/btc_dpm.h
@@ -33,4 +33,6 @@
 #define BTC_CGULVPARAMETER_DFLT                       0x00040035
 #define BTC_CGULVCONTROL_DFLT                         0x00001450

+extern u32 btc_valid_sclk[];
+
 #endif
diff --git a/drivers/gpu/drm/radeon/cypress_dpm.h 
b/drivers/gpu/drm/radeon/cypress_dpm.h
index 029bc9d..9e24d7a 100644
--- a/drivers/gpu/drm/radeon/cypress_dpm.h
+++ b/drivers/gpu/drm/radeon/cypress_dpm.h
@@ -88,6 +88,7 @@ struct evergreen_power_info {
        struct at ats[2];
        /* smc offsets */
        u16 mc_reg_table_start;
+       struct rv7xx_ps hw_ps;
 };

 #define CYPRESS_HASI_DFLT                               400000
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index a4d8d97..16c7d52 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1222,6 +1222,19 @@ struct radeon_dpm_thermal {
        bool               high_to_low;
 };

+enum radeon_clk_action
+{
+       RADEON_SCLK_UP = 1,
+       RADEON_SCLK_DOWN
+};
+
+struct radeon_blacklist_clocks
+{
+       u32 sclk;
+       u32 mclk;
+       enum radeon_clk_action action;
+};
+
 struct radeon_clock_and_voltage_limits {
        u32 sclk;
        u32 mclk;
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c 
b/drivers/gpu/drm/radeon/radeon_pm.c
index 7ee8cf6..2eb41be 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -722,17 +722,42 @@ static void radeon_dpm_change_power_state_locked(struct 
radeon_device *rdev)
        else
                return;

-       /* no need to reprogram if nothing changed */
+       /* no need to reprogram if nothing changed unless we are on BTC+ */
        if (rdev->pm.dpm.current_ps == rdev->pm.dpm.requested_ps) {
-               /* update display watermarks based on new power state */
-               if (rdev->pm.dpm.new_active_crtcs != 
rdev->pm.dpm.current_active_crtcs) {
-                       radeon_bandwidth_update(rdev);
-                       /* update displays */
-                       radeon_dpm_display_configuration_changed(rdev);
-                       rdev->pm.dpm.current_active_crtcs = 
rdev->pm.dpm.new_active_crtcs;
-                       rdev->pm.dpm.current_active_crtc_count = 
rdev->pm.dpm.new_active_crtc_count;
+               if ((rdev->family < CHIP_BARTS) || (rdev->flags & 
RADEON_IS_IGP)) {
+                       /* for pre-BTC and APUs if the num crtcs changed but 
state is the same,
+                        * all we need to do is update the display 
configuration.
+                        */
+                       if (rdev->pm.dpm.new_active_crtcs != 
rdev->pm.dpm.current_active_crtcs) {
+                               /* update display watermarks based on new power 
state */
+                               radeon_bandwidth_update(rdev);
+                               /* update displays */
+                               radeon_dpm_display_configuration_changed(rdev);
+                               rdev->pm.dpm.current_active_crtcs = 
rdev->pm.dpm.new_active_crtcs;
+                               rdev->pm.dpm.current_active_crtc_count = 
rdev->pm.dpm.new_active_crtc_count;
+                       }
+                       return;
+               } else {
+                       /* for BTC+ if the num crtcs hasn't changed and state 
is the same,
+                        * nothing to do, if the num crtcs is > 1 and state is 
the same,
+                        * update display configuration.
+                        */
+                       if (rdev->pm.dpm.new_active_crtcs ==
+                           rdev->pm.dpm.current_active_crtcs) {
+                               return;
+                       } else {
+                               if ((rdev->pm.dpm.current_active_crtc_count > 
1) &&
+                                   (rdev->pm.dpm.new_active_crtc_count > 1)) {
+                                       /* update display watermarks based on 
new power state */
+                                       radeon_bandwidth_update(rdev);
+                                       /* update displays */
+                                       
radeon_dpm_display_configuration_changed(rdev);
+                                       rdev->pm.dpm.current_active_crtcs = 
rdev->pm.dpm.new_active_crtcs;
+                                       rdev->pm.dpm.current_active_crtc_count 
= rdev->pm.dpm.new_active_crtc_count;
+                                       return;
+                               }
+                       }
                }
-               return;
        }

        printk("switching from power state:\n");
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c 
b/drivers/gpu/drm/radeon/rv770_dpm.c
index 55e5126..f5efa4c 100644
--- a/drivers/gpu/drm/radeon/rv770_dpm.c
+++ b/drivers/gpu/drm/radeon/rv770_dpm.c
@@ -2165,6 +2165,16 @@ static void rv7xx_parse_pplib_clock_info(struct 
radeon_device *rdev,
                pl->vddc = vddc;
                pl->vddci = vddci;
        }
+
+       if (rdev->family >= CHIP_BARTS) {
+               if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
+                   ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
+                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = 
pl->sclk;
+                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = 
pl->mclk;
+                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = 
pl->vddc;
+                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = 
pl->vddci;
+               }
+       }
 }

 int rv7xx_parse_power_table(struct radeon_device *rdev)
-- 
1.7.7.5

Reply via email to