aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/trinity_dpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/trinity_dpm.c')
-rw-r--r--drivers/gpu/drm/radeon/trinity_dpm.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c
index a5b02c575d77..d34bfcdab9be 100644
--- a/drivers/gpu/drm/radeon/trinity_dpm.c
+++ b/drivers/gpu/drm/radeon/trinity_dpm.c
@@ -336,6 +336,7 @@ static const u32 trinity_override_mgpg_sequences[] =
336 0x00000204, 0x00000000, 336 0x00000204, 0x00000000,
337}; 337};
338 338
339extern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable);
339static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev, 340static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
340 const u32 *seq, u32 count); 341 const u32 *seq, u32 count);
341static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev); 342static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
@@ -985,6 +986,21 @@ static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev
985 trinity_setup_uvd_clocks(rdev, new_rps, old_rps); 986 trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
986} 987}
987 988
989static void trinity_set_vce_clock(struct radeon_device *rdev,
990 struct radeon_ps *new_rps,
991 struct radeon_ps *old_rps)
992{
993 if ((old_rps->evclk != new_rps->evclk) ||
994 (old_rps->ecclk != new_rps->ecclk)) {
995 /* turn the clocks on when encoding, off otherwise */
996 if (new_rps->evclk || new_rps->ecclk)
997 vce_v1_0_enable_mgcg(rdev, false);
998 else
999 vce_v1_0_enable_mgcg(rdev, true);
1000 radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
1001 }
1002}
1003
988static void trinity_program_ttt(struct radeon_device *rdev) 1004static void trinity_program_ttt(struct radeon_device *rdev)
989{ 1005{
990 struct trinity_power_info *pi = trinity_get_pi(rdev); 1006 struct trinity_power_info *pi = trinity_get_pi(rdev);
@@ -1246,6 +1262,7 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev)
1246 trinity_force_level_0(rdev); 1262 trinity_force_level_0(rdev);
1247 trinity_unforce_levels(rdev); 1263 trinity_unforce_levels(rdev);
1248 trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 1264 trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
1265 trinity_set_vce_clock(rdev, new_ps, old_ps);
1249 } 1266 }
1250 trinity_release_mutex(rdev); 1267 trinity_release_mutex(rdev);
1251 1268
@@ -1483,7 +1500,35 @@ static void trinity_adjust_uvd_state(struct radeon_device *rdev,
1483 } 1500 }
1484} 1501}
1485 1502
1503static int trinity_get_vce_clock_voltage(struct radeon_device *rdev,
1504 u32 evclk, u32 ecclk, u16 *voltage)
1505{
1506 u32 i;
1507 int ret = -EINVAL;
1508 struct radeon_vce_clock_voltage_dependency_table *table =
1509 &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
1510
1511 if (((evclk == 0) && (ecclk == 0)) ||
1512 (table && (table->count == 0))) {
1513 *voltage = 0;
1514 return 0;
1515 }
1516
1517 for (i = 0; i < table->count; i++) {
1518 if ((evclk <= table->entries[i].evclk) &&
1519 (ecclk <= table->entries[i].ecclk)) {
1520 *voltage = table->entries[i].v;
1521 ret = 0;
1522 break;
1523 }
1524 }
1525
1526 /* if no match return the highest voltage */
1527 if (ret)
1528 *voltage = table->entries[table->count - 1].v;
1486 1529
1530 return ret;
1531}
1487 1532
1488static void trinity_apply_state_adjust_rules(struct radeon_device *rdev, 1533static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1489 struct radeon_ps *new_rps, 1534 struct radeon_ps *new_rps,
@@ -1496,6 +1541,7 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1496 u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */ 1541 u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1497 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 1542 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1498 u32 i; 1543 u32 i;
1544 u16 min_vce_voltage;
1499 bool force_high; 1545 bool force_high;
1500 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count; 1546 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1501 1547
@@ -1504,6 +1550,14 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1504 1550
1505 trinity_adjust_uvd_state(rdev, new_rps); 1551 trinity_adjust_uvd_state(rdev, new_rps);
1506 1552
1553 if (new_rps->vce_active) {
1554 new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
1555 new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
1556 } else {
1557 new_rps->evclk = 0;
1558 new_rps->ecclk = 0;
1559 }
1560
1507 for (i = 0; i < ps->num_levels; i++) { 1561 for (i = 0; i < ps->num_levels; i++) {
1508 if (ps->levels[i].vddc_index < min_voltage) 1562 if (ps->levels[i].vddc_index < min_voltage)
1509 ps->levels[i].vddc_index = min_voltage; 1563 ps->levels[i].vddc_index = min_voltage;
@@ -1512,6 +1566,17 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1512 ps->levels[i].sclk = 1566 ps->levels[i].sclk =
1513 trinity_get_valid_engine_clock(rdev, min_sclk); 1567 trinity_get_valid_engine_clock(rdev, min_sclk);
1514 1568
1569 /* patch in vce limits */
1570 if (new_rps->vce_active) {
1571 /* sclk */
1572 if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
1573 ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
1574 /* vddc */
1575 trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage);
1576 if (ps->levels[i].vddc_index < min_vce_voltage)
1577 ps->levels[i].vddc_index = min_vce_voltage;
1578 }
1579
1515 ps->levels[i].ds_divider_index = 1580 ps->levels[i].ds_divider_index =
1516 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr); 1581 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1517 1582
@@ -1733,6 +1798,19 @@ static int trinity_parse_power_table(struct radeon_device *rdev)
1733 power_state_offset += 2 + power_state->v2.ucNumDPMLevels; 1798 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1734 } 1799 }
1735 rdev->pm.dpm.num_ps = state_array->ucNumEntries; 1800 rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1801
1802 /* fill in the vce power states */
1803 for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
1804 u32 sclk;
1805 clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
1806 clock_info = (union pplib_clock_info *)
1807 &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
1808 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1809 sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1810 rdev->pm.dpm.vce_states[i].sclk = sclk;
1811 rdev->pm.dpm.vce_states[i].mclk = 0;
1812 }
1813
1736 return 0; 1814 return 0;
1737} 1815}
1738 1816
@@ -1914,6 +1992,10 @@ int trinity_dpm_init(struct radeon_device *rdev)
1914 if (ret) 1992 if (ret)
1915 return ret; 1993 return ret;
1916 1994
1995 ret = r600_parse_extended_power_table(rdev);
1996 if (ret)
1997 return ret;
1998
1917 ret = trinity_parse_power_table(rdev); 1999 ret = trinity_parse_power_table(rdev);
1918 if (ret) 2000 if (ret)
1919 return ret; 2001 return ret;
@@ -2000,6 +2082,7 @@ void trinity_dpm_fini(struct radeon_device *rdev)
2000 } 2082 }
2001 kfree(rdev->pm.dpm.ps); 2083 kfree(rdev->pm.dpm.ps);
2002 kfree(rdev->pm.dpm.priv); 2084 kfree(rdev->pm.dpm.priv);
2085 r600_free_extended_power_table(rdev);
2003} 2086}
2004 2087
2005u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low) 2088u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)