diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/kv_dpm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/kv_dpm.c | 164 |
1 files changed, 129 insertions, 35 deletions
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index ecd60809db4e..71399065db04 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c | |||
@@ -40,6 +40,7 @@ static int kv_calculate_dpm_settings(struct radeon_device *rdev); | |||
40 | static void kv_enable_new_levels(struct radeon_device *rdev); | 40 | static void kv_enable_new_levels(struct radeon_device *rdev); |
41 | static void kv_program_nbps_index_settings(struct radeon_device *rdev, | 41 | static void kv_program_nbps_index_settings(struct radeon_device *rdev, |
42 | struct radeon_ps *new_rps); | 42 | struct radeon_ps *new_rps); |
43 | static int kv_set_enabled_level(struct radeon_device *rdev, u32 level); | ||
43 | static int kv_set_enabled_levels(struct radeon_device *rdev); | 44 | static int kv_set_enabled_levels(struct radeon_device *rdev); |
44 | static int kv_force_dpm_highest(struct radeon_device *rdev); | 45 | static int kv_force_dpm_highest(struct radeon_device *rdev); |
45 | static int kv_force_dpm_lowest(struct radeon_device *rdev); | 46 | static int kv_force_dpm_lowest(struct radeon_device *rdev); |
@@ -519,7 +520,7 @@ static int kv_set_dpm_boot_state(struct radeon_device *rdev) | |||
519 | 520 | ||
520 | static void kv_program_vc(struct radeon_device *rdev) | 521 | static void kv_program_vc(struct radeon_device *rdev) |
521 | { | 522 | { |
522 | WREG32_SMC(CG_FTV_0, 0x3FFFC000); | 523 | WREG32_SMC(CG_FTV_0, 0x3FFFC100); |
523 | } | 524 | } |
524 | 525 | ||
525 | static void kv_clear_vc(struct radeon_device *rdev) | 526 | static void kv_clear_vc(struct radeon_device *rdev) |
@@ -638,7 +639,10 @@ static int kv_force_lowest_valid(struct radeon_device *rdev) | |||
638 | 639 | ||
639 | static int kv_unforce_levels(struct radeon_device *rdev) | 640 | static int kv_unforce_levels(struct radeon_device *rdev) |
640 | { | 641 | { |
641 | return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel); | 642 | if (rdev->family == CHIP_KABINI) |
643 | return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel); | ||
644 | else | ||
645 | return kv_set_enabled_levels(rdev); | ||
642 | } | 646 | } |
643 | 647 | ||
644 | static int kv_update_sclk_t(struct radeon_device *rdev) | 648 | static int kv_update_sclk_t(struct radeon_device *rdev) |
@@ -667,9 +671,8 @@ static int kv_program_bootup_state(struct radeon_device *rdev) | |||
667 | &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; | 671 | &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; |
668 | 672 | ||
669 | if (table && table->count) { | 673 | if (table && table->count) { |
670 | for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) { | 674 | for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { |
671 | if ((table->entries[i].clk == pi->boot_pl.sclk) || | 675 | if (table->entries[i].clk == pi->boot_pl.sclk) |
672 | (i == 0)) | ||
673 | break; | 676 | break; |
674 | } | 677 | } |
675 | 678 | ||
@@ -682,9 +685,8 @@ static int kv_program_bootup_state(struct radeon_device *rdev) | |||
682 | if (table->num_max_dpm_entries == 0) | 685 | if (table->num_max_dpm_entries == 0) |
683 | return -EINVAL; | 686 | return -EINVAL; |
684 | 687 | ||
685 | for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) { | 688 | for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { |
686 | if ((table->entries[i].sclk_frequency == pi->boot_pl.sclk) || | 689 | if (table->entries[i].sclk_frequency == pi->boot_pl.sclk) |
687 | (i == 0)) | ||
688 | break; | 690 | break; |
689 | } | 691 | } |
690 | 692 | ||
@@ -1078,6 +1080,13 @@ static int kv_enable_ulv(struct radeon_device *rdev, bool enable) | |||
1078 | PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV); | 1080 | PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV); |
1079 | } | 1081 | } |
1080 | 1082 | ||
1083 | static void kv_reset_acp_boot_level(struct radeon_device *rdev) | ||
1084 | { | ||
1085 | struct kv_power_info *pi = kv_get_pi(rdev); | ||
1086 | |||
1087 | pi->acp_boot_level = 0xff; | ||
1088 | } | ||
1089 | |||
1081 | static void kv_update_current_ps(struct radeon_device *rdev, | 1090 | static void kv_update_current_ps(struct radeon_device *rdev, |
1082 | struct radeon_ps *rps) | 1091 | struct radeon_ps *rps) |
1083 | { | 1092 | { |
@@ -1100,6 +1109,18 @@ static void kv_update_requested_ps(struct radeon_device *rdev, | |||
1100 | pi->requested_rps.ps_priv = &pi->requested_ps; | 1109 | pi->requested_rps.ps_priv = &pi->requested_ps; |
1101 | } | 1110 | } |
1102 | 1111 | ||
1112 | void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable) | ||
1113 | { | ||
1114 | struct kv_power_info *pi = kv_get_pi(rdev); | ||
1115 | int ret; | ||
1116 | |||
1117 | if (pi->bapm_enable) { | ||
1118 | ret = kv_smc_bapm_enable(rdev, enable); | ||
1119 | if (ret) | ||
1120 | DRM_ERROR("kv_smc_bapm_enable failed\n"); | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1103 | int kv_dpm_enable(struct radeon_device *rdev) | 1124 | int kv_dpm_enable(struct radeon_device *rdev) |
1104 | { | 1125 | { |
1105 | struct kv_power_info *pi = kv_get_pi(rdev); | 1126 | struct kv_power_info *pi = kv_get_pi(rdev); |
@@ -1192,6 +1213,8 @@ int kv_dpm_enable(struct radeon_device *rdev) | |||
1192 | return ret; | 1213 | return ret; |
1193 | } | 1214 | } |
1194 | 1215 | ||
1216 | kv_reset_acp_boot_level(rdev); | ||
1217 | |||
1195 | if (rdev->irq.installed && | 1218 | if (rdev->irq.installed && |
1196 | r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { | 1219 | r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { |
1197 | ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); | 1220 | ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); |
@@ -1203,6 +1226,12 @@ int kv_dpm_enable(struct radeon_device *rdev) | |||
1203 | radeon_irq_set(rdev); | 1226 | radeon_irq_set(rdev); |
1204 | } | 1227 | } |
1205 | 1228 | ||
1229 | ret = kv_smc_bapm_enable(rdev, false); | ||
1230 | if (ret) { | ||
1231 | DRM_ERROR("kv_smc_bapm_enable failed\n"); | ||
1232 | return ret; | ||
1233 | } | ||
1234 | |||
1206 | /* powerdown unused blocks for now */ | 1235 | /* powerdown unused blocks for now */ |
1207 | kv_dpm_powergate_acp(rdev, true); | 1236 | kv_dpm_powergate_acp(rdev, true); |
1208 | kv_dpm_powergate_samu(rdev, true); | 1237 | kv_dpm_powergate_samu(rdev, true); |
@@ -1226,6 +1255,8 @@ void kv_dpm_disable(struct radeon_device *rdev) | |||
1226 | RADEON_CG_BLOCK_BIF | | 1255 | RADEON_CG_BLOCK_BIF | |
1227 | RADEON_CG_BLOCK_HDP), false); | 1256 | RADEON_CG_BLOCK_HDP), false); |
1228 | 1257 | ||
1258 | kv_smc_bapm_enable(rdev, false); | ||
1259 | |||
1229 | /* powerup blocks */ | 1260 | /* powerup blocks */ |
1230 | kv_dpm_powergate_acp(rdev, false); | 1261 | kv_dpm_powergate_acp(rdev, false); |
1231 | kv_dpm_powergate_samu(rdev, false); | 1262 | kv_dpm_powergate_samu(rdev, false); |
@@ -1450,6 +1481,39 @@ static int kv_update_samu_dpm(struct radeon_device *rdev, bool gate) | |||
1450 | return kv_enable_samu_dpm(rdev, !gate); | 1481 | return kv_enable_samu_dpm(rdev, !gate); |
1451 | } | 1482 | } |
1452 | 1483 | ||
1484 | static u8 kv_get_acp_boot_level(struct radeon_device *rdev) | ||
1485 | { | ||
1486 | u8 i; | ||
1487 | struct radeon_clock_voltage_dependency_table *table = | ||
1488 | &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; | ||
1489 | |||
1490 | for (i = 0; i < table->count; i++) { | ||
1491 | if (table->entries[i].clk >= 0) /* XXX */ | ||
1492 | break; | ||
1493 | } | ||
1494 | |||
1495 | if (i >= table->count) | ||
1496 | i = table->count - 1; | ||
1497 | |||
1498 | return i; | ||
1499 | } | ||
1500 | |||
1501 | static void kv_update_acp_boot_level(struct radeon_device *rdev) | ||
1502 | { | ||
1503 | struct kv_power_info *pi = kv_get_pi(rdev); | ||
1504 | u8 acp_boot_level; | ||
1505 | |||
1506 | if (!pi->caps_stable_p_state) { | ||
1507 | acp_boot_level = kv_get_acp_boot_level(rdev); | ||
1508 | if (acp_boot_level != pi->acp_boot_level) { | ||
1509 | pi->acp_boot_level = acp_boot_level; | ||
1510 | kv_send_msg_to_smc_with_parameter(rdev, | ||
1511 | PPSMC_MSG_ACPDPM_SetEnabledMask, | ||
1512 | (1 << pi->acp_boot_level)); | ||
1513 | } | ||
1514 | } | ||
1515 | } | ||
1516 | |||
1453 | static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate) | 1517 | static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate) |
1454 | { | 1518 | { |
1455 | struct kv_power_info *pi = kv_get_pi(rdev); | 1519 | struct kv_power_info *pi = kv_get_pi(rdev); |
@@ -1461,7 +1525,7 @@ static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate) | |||
1461 | if (pi->caps_stable_p_state) | 1525 | if (pi->caps_stable_p_state) |
1462 | pi->acp_boot_level = table->count - 1; | 1526 | pi->acp_boot_level = table->count - 1; |
1463 | else | 1527 | else |
1464 | pi->acp_boot_level = 0; | 1528 | pi->acp_boot_level = kv_get_acp_boot_level(rdev); |
1465 | 1529 | ||
1466 | ret = kv_copy_bytes_to_smc(rdev, | 1530 | ret = kv_copy_bytes_to_smc(rdev, |
1467 | pi->dpm_table_start + | 1531 | pi->dpm_table_start + |
@@ -1588,13 +1652,11 @@ static void kv_set_valid_clock_range(struct radeon_device *rdev, | |||
1588 | } | 1652 | } |
1589 | } | 1653 | } |
1590 | 1654 | ||
1591 | for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) { | 1655 | for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { |
1592 | if ((table->entries[i].clk <= new_ps->levels[new_ps->num_levels -1].sclk) || | 1656 | if (table->entries[i].clk <= new_ps->levels[new_ps->num_levels - 1].sclk) |
1593 | (i == 0)) { | ||
1594 | pi->highest_valid = i; | ||
1595 | break; | 1657 | break; |
1596 | } | ||
1597 | } | 1658 | } |
1659 | pi->highest_valid = i; | ||
1598 | 1660 | ||
1599 | if (pi->lowest_valid > pi->highest_valid) { | 1661 | if (pi->lowest_valid > pi->highest_valid) { |
1600 | if ((new_ps->levels[0].sclk - table->entries[pi->highest_valid].clk) > | 1662 | if ((new_ps->levels[0].sclk - table->entries[pi->highest_valid].clk) > |
@@ -1615,14 +1677,12 @@ static void kv_set_valid_clock_range(struct radeon_device *rdev, | |||
1615 | } | 1677 | } |
1616 | } | 1678 | } |
1617 | 1679 | ||
1618 | for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) { | 1680 | for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { |
1619 | if (table->entries[i].sclk_frequency <= | 1681 | if (table->entries[i].sclk_frequency <= |
1620 | new_ps->levels[new_ps->num_levels - 1].sclk || | 1682 | new_ps->levels[new_ps->num_levels - 1].sclk) |
1621 | i == 0) { | ||
1622 | pi->highest_valid = i; | ||
1623 | break; | 1683 | break; |
1624 | } | ||
1625 | } | 1684 | } |
1685 | pi->highest_valid = i; | ||
1626 | 1686 | ||
1627 | if (pi->lowest_valid > pi->highest_valid) { | 1687 | if (pi->lowest_valid > pi->highest_valid) { |
1628 | if ((new_ps->levels[0].sclk - | 1688 | if ((new_ps->levels[0].sclk - |
@@ -1724,6 +1784,14 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) | |||
1724 | RADEON_CG_BLOCK_BIF | | 1784 | RADEON_CG_BLOCK_BIF | |
1725 | RADEON_CG_BLOCK_HDP), false); | 1785 | RADEON_CG_BLOCK_HDP), false); |
1726 | 1786 | ||
1787 | if (pi->bapm_enable) { | ||
1788 | ret = kv_smc_bapm_enable(rdev, rdev->pm.dpm.ac_power); | ||
1789 | if (ret) { | ||
1790 | DRM_ERROR("kv_smc_bapm_enable failed\n"); | ||
1791 | return ret; | ||
1792 | } | ||
1793 | } | ||
1794 | |||
1727 | if (rdev->family == CHIP_KABINI) { | 1795 | if (rdev->family == CHIP_KABINI) { |
1728 | if (pi->enable_dpm) { | 1796 | if (pi->enable_dpm) { |
1729 | kv_set_valid_clock_range(rdev, new_ps); | 1797 | kv_set_valid_clock_range(rdev, new_ps); |
@@ -1775,6 +1843,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) | |||
1775 | return ret; | 1843 | return ret; |
1776 | } | 1844 | } |
1777 | #endif | 1845 | #endif |
1846 | kv_update_acp_boot_level(rdev); | ||
1778 | kv_update_sclk_t(rdev); | 1847 | kv_update_sclk_t(rdev); |
1779 | kv_enable_nb_dpm(rdev); | 1848 | kv_enable_nb_dpm(rdev); |
1780 | } | 1849 | } |
@@ -1785,7 +1854,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) | |||
1785 | RADEON_CG_BLOCK_BIF | | 1854 | RADEON_CG_BLOCK_BIF | |
1786 | RADEON_CG_BLOCK_HDP), true); | 1855 | RADEON_CG_BLOCK_HDP), true); |
1787 | 1856 | ||
1788 | rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; | ||
1789 | return 0; | 1857 | return 0; |
1790 | } | 1858 | } |
1791 | 1859 | ||
@@ -1806,12 +1874,23 @@ void kv_dpm_setup_asic(struct radeon_device *rdev) | |||
1806 | 1874 | ||
1807 | void kv_dpm_reset_asic(struct radeon_device *rdev) | 1875 | void kv_dpm_reset_asic(struct radeon_device *rdev) |
1808 | { | 1876 | { |
1809 | kv_force_lowest_valid(rdev); | 1877 | struct kv_power_info *pi = kv_get_pi(rdev); |
1810 | kv_init_graphics_levels(rdev); | 1878 | |
1811 | kv_program_bootup_state(rdev); | 1879 | if (rdev->family == CHIP_KABINI) { |
1812 | kv_upload_dpm_settings(rdev); | 1880 | kv_force_lowest_valid(rdev); |
1813 | kv_force_lowest_valid(rdev); | 1881 | kv_init_graphics_levels(rdev); |
1814 | kv_unforce_levels(rdev); | 1882 | kv_program_bootup_state(rdev); |
1883 | kv_upload_dpm_settings(rdev); | ||
1884 | kv_force_lowest_valid(rdev); | ||
1885 | kv_unforce_levels(rdev); | ||
1886 | } else { | ||
1887 | kv_init_graphics_levels(rdev); | ||
1888 | kv_program_bootup_state(rdev); | ||
1889 | kv_freeze_sclk_dpm(rdev, true); | ||
1890 | kv_upload_dpm_settings(rdev); | ||
1891 | kv_freeze_sclk_dpm(rdev, false); | ||
1892 | kv_set_enabled_level(rdev, pi->graphics_boot_level); | ||
1893 | } | ||
1815 | } | 1894 | } |
1816 | 1895 | ||
1817 | //XXX use sumo_dpm_display_configuration_changed | 1896 | //XXX use sumo_dpm_display_configuration_changed |
@@ -1871,12 +1950,15 @@ static int kv_force_dpm_highest(struct radeon_device *rdev) | |||
1871 | if (ret) | 1950 | if (ret) |
1872 | return ret; | 1951 | return ret; |
1873 | 1952 | ||
1874 | for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i >= 0; i--) { | 1953 | for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i > 0; i--) { |
1875 | if (enable_mask & (1 << i)) | 1954 | if (enable_mask & (1 << i)) |
1876 | break; | 1955 | break; |
1877 | } | 1956 | } |
1878 | 1957 | ||
1879 | return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); | 1958 | if (rdev->family == CHIP_KABINI) |
1959 | return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); | ||
1960 | else | ||
1961 | return kv_set_enabled_level(rdev, i); | ||
1880 | } | 1962 | } |
1881 | 1963 | ||
1882 | static int kv_force_dpm_lowest(struct radeon_device *rdev) | 1964 | static int kv_force_dpm_lowest(struct radeon_device *rdev) |
@@ -1893,7 +1975,10 @@ static int kv_force_dpm_lowest(struct radeon_device *rdev) | |||
1893 | break; | 1975 | break; |
1894 | } | 1976 | } |
1895 | 1977 | ||
1896 | return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); | 1978 | if (rdev->family == CHIP_KABINI) |
1979 | return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); | ||
1980 | else | ||
1981 | return kv_set_enabled_level(rdev, i); | ||
1897 | } | 1982 | } |
1898 | 1983 | ||
1899 | static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev, | 1984 | static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev, |
@@ -1911,9 +1996,9 @@ static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev, | |||
1911 | if (!pi->caps_sclk_ds) | 1996 | if (!pi->caps_sclk_ds) |
1912 | return 0; | 1997 | return 0; |
1913 | 1998 | ||
1914 | for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i <= 0; i--) { | 1999 | for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i > 0; i--) { |
1915 | temp = sclk / sumo_get_sleep_divider_from_id(i); | 2000 | temp = sclk / sumo_get_sleep_divider_from_id(i); |
1916 | if ((temp >= min) || (i == 0)) | 2001 | if (temp >= min) |
1917 | break; | 2002 | break; |
1918 | } | 2003 | } |
1919 | 2004 | ||
@@ -2039,12 +2124,12 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev, | |||
2039 | ps->dpmx_nb_ps_lo = 0x1; | 2124 | ps->dpmx_nb_ps_lo = 0x1; |
2040 | ps->dpmx_nb_ps_hi = 0x0; | 2125 | ps->dpmx_nb_ps_hi = 0x0; |
2041 | } else { | 2126 | } else { |
2042 | ps->dpm0_pg_nb_ps_lo = 0x1; | 2127 | ps->dpm0_pg_nb_ps_lo = 0x3; |
2043 | ps->dpm0_pg_nb_ps_hi = 0x0; | 2128 | ps->dpm0_pg_nb_ps_hi = 0x0; |
2044 | ps->dpmx_nb_ps_lo = 0x2; | 2129 | ps->dpmx_nb_ps_lo = 0x3; |
2045 | ps->dpmx_nb_ps_hi = 0x1; | 2130 | ps->dpmx_nb_ps_hi = 0x0; |
2046 | 2131 | ||
2047 | if (pi->sys_info.nb_dpm_enable && pi->battery_state) { | 2132 | if (pi->sys_info.nb_dpm_enable) { |
2048 | force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) || | 2133 | force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) || |
2049 | pi->video_start || (rdev->pm.dpm.new_active_crtc_count >= 3) || | 2134 | pi->video_start || (rdev->pm.dpm.new_active_crtc_count >= 3) || |
2050 | pi->disable_nb_ps3_in_battery; | 2135 | pi->disable_nb_ps3_in_battery; |
@@ -2210,6 +2295,15 @@ static void kv_enable_new_levels(struct radeon_device *rdev) | |||
2210 | } | 2295 | } |
2211 | } | 2296 | } |
2212 | 2297 | ||
2298 | static int kv_set_enabled_level(struct radeon_device *rdev, u32 level) | ||
2299 | { | ||
2300 | u32 new_mask = (1 << level); | ||
2301 | |||
2302 | return kv_send_msg_to_smc_with_parameter(rdev, | ||
2303 | PPSMC_MSG_SCLKDPM_SetEnabledMask, | ||
2304 | new_mask); | ||
2305 | } | ||
2306 | |||
2213 | static int kv_set_enabled_levels(struct radeon_device *rdev) | 2307 | static int kv_set_enabled_levels(struct radeon_device *rdev) |
2214 | { | 2308 | { |
2215 | struct kv_power_info *pi = kv_get_pi(rdev); | 2309 | struct kv_power_info *pi = kv_get_pi(rdev); |