18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2011 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 128c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 158c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 178c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 188c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 198c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 208c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Authors: Alex Deucher 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "radeon.h" 268c2ecf20Sopenharmony_ci#include "radeon_asic.h" 278c2ecf20Sopenharmony_ci#include "r600d.h" 288c2ecf20Sopenharmony_ci#include "r600_dpm.h" 298c2ecf20Sopenharmony_ci#include "atom.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ciconst u32 r600_utc[R600_PM_NUMBER_OF_TC] = 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci R600_UTC_DFLT_00, 348c2ecf20Sopenharmony_ci R600_UTC_DFLT_01, 358c2ecf20Sopenharmony_ci R600_UTC_DFLT_02, 368c2ecf20Sopenharmony_ci R600_UTC_DFLT_03, 378c2ecf20Sopenharmony_ci R600_UTC_DFLT_04, 388c2ecf20Sopenharmony_ci R600_UTC_DFLT_05, 398c2ecf20Sopenharmony_ci R600_UTC_DFLT_06, 408c2ecf20Sopenharmony_ci R600_UTC_DFLT_07, 418c2ecf20Sopenharmony_ci R600_UTC_DFLT_08, 428c2ecf20Sopenharmony_ci R600_UTC_DFLT_09, 438c2ecf20Sopenharmony_ci R600_UTC_DFLT_10, 448c2ecf20Sopenharmony_ci R600_UTC_DFLT_11, 458c2ecf20Sopenharmony_ci R600_UTC_DFLT_12, 468c2ecf20Sopenharmony_ci R600_UTC_DFLT_13, 478c2ecf20Sopenharmony_ci R600_UTC_DFLT_14, 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ciconst u32 r600_dtc[R600_PM_NUMBER_OF_TC] = 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci R600_DTC_DFLT_00, 538c2ecf20Sopenharmony_ci R600_DTC_DFLT_01, 548c2ecf20Sopenharmony_ci R600_DTC_DFLT_02, 558c2ecf20Sopenharmony_ci R600_DTC_DFLT_03, 568c2ecf20Sopenharmony_ci R600_DTC_DFLT_04, 578c2ecf20Sopenharmony_ci R600_DTC_DFLT_05, 588c2ecf20Sopenharmony_ci R600_DTC_DFLT_06, 598c2ecf20Sopenharmony_ci R600_DTC_DFLT_07, 608c2ecf20Sopenharmony_ci R600_DTC_DFLT_08, 618c2ecf20Sopenharmony_ci R600_DTC_DFLT_09, 628c2ecf20Sopenharmony_ci R600_DTC_DFLT_10, 638c2ecf20Sopenharmony_ci R600_DTC_DFLT_11, 648c2ecf20Sopenharmony_ci R600_DTC_DFLT_12, 658c2ecf20Sopenharmony_ci R600_DTC_DFLT_13, 668c2ecf20Sopenharmony_ci R600_DTC_DFLT_14, 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_civoid r600_dpm_print_class_info(u32 class, u32 class2) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci const char *s; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { 748c2ecf20Sopenharmony_ci case ATOM_PPLIB_CLASSIFICATION_UI_NONE: 758c2ecf20Sopenharmony_ci default: 768c2ecf20Sopenharmony_ci s = "none"; 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: 798c2ecf20Sopenharmony_ci s = "battery"; 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: 828c2ecf20Sopenharmony_ci s = "balanced"; 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: 858c2ecf20Sopenharmony_ci s = "performance"; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci printk("\tui class: %s\n", s); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci printk("\tinternal class:"); 918c2ecf20Sopenharmony_ci if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && 928c2ecf20Sopenharmony_ci (class2 == 0)) 938c2ecf20Sopenharmony_ci pr_cont(" none"); 948c2ecf20Sopenharmony_ci else { 958c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) 968c2ecf20Sopenharmony_ci pr_cont(" boot"); 978c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 988c2ecf20Sopenharmony_ci pr_cont(" thermal"); 998c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 1008c2ecf20Sopenharmony_ci pr_cont(" limited_pwr"); 1018c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_REST) 1028c2ecf20Sopenharmony_ci pr_cont(" rest"); 1038c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) 1048c2ecf20Sopenharmony_ci pr_cont(" forced"); 1058c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 1068c2ecf20Sopenharmony_ci pr_cont(" 3d_perf"); 1078c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) 1088c2ecf20Sopenharmony_ci pr_cont(" ovrdrv"); 1098c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 1108c2ecf20Sopenharmony_ci pr_cont(" uvd"); 1118c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) 1128c2ecf20Sopenharmony_ci pr_cont(" 3d_low"); 1138c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) 1148c2ecf20Sopenharmony_ci pr_cont(" acpi"); 1158c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 1168c2ecf20Sopenharmony_ci pr_cont(" uvd_hd2"); 1178c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 1188c2ecf20Sopenharmony_ci pr_cont(" uvd_hd"); 1198c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 1208c2ecf20Sopenharmony_ci pr_cont(" uvd_sd"); 1218c2ecf20Sopenharmony_ci if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 1228c2ecf20Sopenharmony_ci pr_cont(" limited_pwr2"); 1238c2ecf20Sopenharmony_ci if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 1248c2ecf20Sopenharmony_ci pr_cont(" ulv"); 1258c2ecf20Sopenharmony_ci if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 1268c2ecf20Sopenharmony_ci pr_cont(" uvd_mvc"); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci pr_cont("\n"); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_civoid r600_dpm_print_cap_info(u32 caps) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci printk("\tcaps:"); 1348c2ecf20Sopenharmony_ci if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) 1358c2ecf20Sopenharmony_ci pr_cont(" single_disp"); 1368c2ecf20Sopenharmony_ci if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) 1378c2ecf20Sopenharmony_ci pr_cont(" video"); 1388c2ecf20Sopenharmony_ci if (caps & ATOM_PPLIB_DISALLOW_ON_DC) 1398c2ecf20Sopenharmony_ci pr_cont(" no_dc"); 1408c2ecf20Sopenharmony_ci pr_cont("\n"); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_civoid r600_dpm_print_ps_status(struct radeon_device *rdev, 1448c2ecf20Sopenharmony_ci struct radeon_ps *rps) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci printk("\tstatus:"); 1478c2ecf20Sopenharmony_ci if (rps == rdev->pm.dpm.current_ps) 1488c2ecf20Sopenharmony_ci pr_cont(" c"); 1498c2ecf20Sopenharmony_ci if (rps == rdev->pm.dpm.requested_ps) 1508c2ecf20Sopenharmony_ci pr_cont(" r"); 1518c2ecf20Sopenharmony_ci if (rps == rdev->pm.dpm.boot_ps) 1528c2ecf20Sopenharmony_ci pr_cont(" b"); 1538c2ecf20Sopenharmony_ci pr_cont("\n"); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ciu32 r600_dpm_get_vblank_time(struct radeon_device *rdev) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci struct drm_device *dev = rdev->ddev; 1598c2ecf20Sopenharmony_ci struct drm_crtc *crtc; 1608c2ecf20Sopenharmony_ci struct radeon_crtc *radeon_crtc; 1618c2ecf20Sopenharmony_ci u32 vblank_in_pixels; 1628c2ecf20Sopenharmony_ci u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { 1658c2ecf20Sopenharmony_ci list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1668c2ecf20Sopenharmony_ci radeon_crtc = to_radeon_crtc(crtc); 1678c2ecf20Sopenharmony_ci if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { 1688c2ecf20Sopenharmony_ci vblank_in_pixels = 1698c2ecf20Sopenharmony_ci radeon_crtc->hw_mode.crtc_htotal * 1708c2ecf20Sopenharmony_ci (radeon_crtc->hw_mode.crtc_vblank_end - 1718c2ecf20Sopenharmony_ci radeon_crtc->hw_mode.crtc_vdisplay + 1728c2ecf20Sopenharmony_ci (radeon_crtc->v_border * 2)); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci vblank_time_us = vblank_in_pixels * 1000 / radeon_crtc->hw_mode.clock; 1758c2ecf20Sopenharmony_ci break; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci return vblank_time_us; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciu32 r600_dpm_get_vrefresh(struct radeon_device *rdev) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct drm_device *dev = rdev->ddev; 1868c2ecf20Sopenharmony_ci struct drm_crtc *crtc; 1878c2ecf20Sopenharmony_ci struct radeon_crtc *radeon_crtc; 1888c2ecf20Sopenharmony_ci u32 vrefresh = 0; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { 1918c2ecf20Sopenharmony_ci list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1928c2ecf20Sopenharmony_ci radeon_crtc = to_radeon_crtc(crtc); 1938c2ecf20Sopenharmony_ci if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { 1948c2ecf20Sopenharmony_ci vrefresh = drm_mode_vrefresh(&radeon_crtc->hw_mode); 1958c2ecf20Sopenharmony_ci break; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci return vrefresh; 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_civoid r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, 2038c2ecf20Sopenharmony_ci u32 *p, u32 *u) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci u32 b_c = 0; 2068c2ecf20Sopenharmony_ci u32 i_c; 2078c2ecf20Sopenharmony_ci u32 tmp; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci i_c = (i * r_c) / 100; 2108c2ecf20Sopenharmony_ci tmp = i_c >> p_b; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci while (tmp) { 2138c2ecf20Sopenharmony_ci b_c++; 2148c2ecf20Sopenharmony_ci tmp >>= 1; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci *u = (b_c + 1) / 2; 2188c2ecf20Sopenharmony_ci *p = i_c / (1 << (2 * (*u))); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ciint r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci u32 k, a, ah, al; 2248c2ecf20Sopenharmony_ci u32 t1; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if ((fl == 0) || (fh == 0) || (fl > fh)) 2278c2ecf20Sopenharmony_ci return -EINVAL; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci k = (100 * fh) / fl; 2308c2ecf20Sopenharmony_ci t1 = (t * (k - 100)); 2318c2ecf20Sopenharmony_ci a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100)); 2328c2ecf20Sopenharmony_ci a = (a + 5) / 10; 2338c2ecf20Sopenharmony_ci ah = ((a * t) + 5000) / 10000; 2348c2ecf20Sopenharmony_ci al = a - ah; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci *th = t - ah; 2378c2ecf20Sopenharmony_ci *tl = t + al; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci return 0; 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_civoid r600_gfx_clockgating_enable(struct radeon_device *rdev, bool enable) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci int i; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if (enable) { 2478c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); 2488c2ecf20Sopenharmony_ci } else { 2498c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci WREG32(CG_RLC_REQ_AND_RSP, 0x2); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 2548c2ecf20Sopenharmony_ci if (((RREG32(CG_RLC_REQ_AND_RSP) & CG_RLC_RSP_TYPE_MASK) >> CG_RLC_RSP_TYPE_SHIFT) == 1) 2558c2ecf20Sopenharmony_ci break; 2568c2ecf20Sopenharmony_ci udelay(1); 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci WREG32(CG_RLC_REQ_AND_RSP, 0x0); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci WREG32(GRBM_PWR_CNTL, 0x1); 2628c2ecf20Sopenharmony_ci RREG32(GRBM_PWR_CNTL); 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_civoid r600_dynamicpm_enable(struct radeon_device *rdev, bool enable) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci if (enable) 2698c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); 2708c2ecf20Sopenharmony_ci else 2718c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_civoid r600_enable_thermal_protection(struct radeon_device *rdev, bool enable) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci if (enable) 2778c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); 2788c2ecf20Sopenharmony_ci else 2798c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_civoid r600_enable_acpi_pm(struct radeon_device *rdev) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_civoid r600_enable_dynamic_pcie_gen2(struct radeon_device *rdev, bool enable) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci if (enable) 2908c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE); 2918c2ecf20Sopenharmony_ci else 2928c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE); 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cibool r600_dynamicpm_enabled(struct radeon_device *rdev) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN) 2988c2ecf20Sopenharmony_ci return true; 2998c2ecf20Sopenharmony_ci else 3008c2ecf20Sopenharmony_ci return false; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_civoid r600_enable_sclk_control(struct radeon_device *rdev, bool enable) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci if (enable) 3068c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); 3078c2ecf20Sopenharmony_ci else 3088c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_civoid r600_enable_mclk_control(struct radeon_device *rdev, bool enable) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci if (enable) 3148c2ecf20Sopenharmony_ci WREG32_P(MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF); 3158c2ecf20Sopenharmony_ci else 3168c2ecf20Sopenharmony_ci WREG32_P(MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF); 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_civoid r600_enable_spll_bypass(struct radeon_device *rdev, bool enable) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci if (enable) 3228c2ecf20Sopenharmony_ci WREG32_P(CG_SPLL_FUNC_CNTL, SPLL_BYPASS_EN, ~SPLL_BYPASS_EN); 3238c2ecf20Sopenharmony_ci else 3248c2ecf20Sopenharmony_ci WREG32_P(CG_SPLL_FUNC_CNTL, 0, ~SPLL_BYPASS_EN); 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_civoid r600_wait_for_spll_change(struct radeon_device *rdev) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci int i; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 3328c2ecf20Sopenharmony_ci if (RREG32(CG_SPLL_FUNC_CNTL) & SPLL_CHG_STATUS) 3338c2ecf20Sopenharmony_ci break; 3348c2ecf20Sopenharmony_ci udelay(1); 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_civoid r600_set_bsp(struct radeon_device *rdev, u32 u, u32 p) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci WREG32(CG_BSP, BSP(p) | BSU(u)); 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_civoid r600_set_at(struct radeon_device *rdev, 3448c2ecf20Sopenharmony_ci u32 l_to_m, u32 m_to_h, 3458c2ecf20Sopenharmony_ci u32 h_to_m, u32 m_to_l) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci WREG32(CG_RT, FLS(l_to_m) | FMS(m_to_h)); 3488c2ecf20Sopenharmony_ci WREG32(CG_LT, FHS(h_to_m) | FMS(m_to_l)); 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_civoid r600_set_tc(struct radeon_device *rdev, 3528c2ecf20Sopenharmony_ci u32 index, u32 u_t, u32 d_t) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci WREG32(CG_FFCT_0 + (index * 4), UTC_0(u_t) | DTC_0(d_t)); 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_civoid r600_select_td(struct radeon_device *rdev, 3588c2ecf20Sopenharmony_ci enum r600_td td) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci if (td == R600_TD_AUTO) 3618c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL); 3628c2ecf20Sopenharmony_ci else 3638c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL); 3648c2ecf20Sopenharmony_ci if (td == R600_TD_UP) 3658c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE); 3668c2ecf20Sopenharmony_ci if (td == R600_TD_DOWN) 3678c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE); 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_civoid r600_set_vrc(struct radeon_device *rdev, u32 vrv) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci WREG32(CG_FTV, vrv); 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_civoid r600_set_tpu(struct radeon_device *rdev, u32 u) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci WREG32_P(CG_TPC, TPU(u), ~TPU_MASK); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_civoid r600_set_tpc(struct radeon_device *rdev, u32 c) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci WREG32_P(CG_TPC, TPCC(c), ~TPCC_MASK); 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_civoid r600_set_sstu(struct radeon_device *rdev, u32 u) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci WREG32_P(CG_SSP, CG_SSTU(u), ~CG_SSTU_MASK); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_civoid r600_set_sst(struct radeon_device *rdev, u32 t) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci WREG32_P(CG_SSP, CG_SST(t), ~CG_SST_MASK); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_civoid r600_set_git(struct radeon_device *rdev, u32 t) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci WREG32_P(CG_GIT, CG_GICST(t), ~CG_GICST_MASK); 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_civoid r600_set_fctu(struct radeon_device *rdev, u32 u) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci WREG32_P(CG_FC_T, FC_TU(u), ~FC_TU_MASK); 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_civoid r600_set_fct(struct radeon_device *rdev, u32 t) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci WREG32_P(CG_FC_T, FC_T(t), ~FC_T_MASK); 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_civoid r600_set_ctxcgtt3d_rphc(struct radeon_device *rdev, u32 p) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci WREG32_P(CG_CTX_CGTT3D_R, PHC(p), ~PHC_MASK); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_civoid r600_set_ctxcgtt3d_rsdc(struct radeon_device *rdev, u32 s) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci WREG32_P(CG_CTX_CGTT3D_R, SDC(s), ~SDC_MASK); 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_civoid r600_set_vddc3d_oorsu(struct radeon_device *rdev, u32 u) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci WREG32_P(CG_VDDC3D_OOR, SU(u), ~SU_MASK); 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_civoid r600_set_vddc3d_oorphc(struct radeon_device *rdev, u32 p) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci WREG32_P(CG_VDDC3D_OOR, PHC(p), ~PHC_MASK); 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_civoid r600_set_vddc3d_oorsdc(struct radeon_device *rdev, u32 s) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci WREG32_P(CG_VDDC3D_OOR, SDC(s), ~SDC_MASK); 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_civoid r600_set_mpll_lock_time(struct radeon_device *rdev, u32 lock_time) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci WREG32_P(MPLL_TIME, MPLL_LOCK_TIME(lock_time), ~MPLL_LOCK_TIME_MASK); 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_civoid r600_set_mpll_reset_time(struct radeon_device *rdev, u32 reset_time) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci WREG32_P(MPLL_TIME, MPLL_RESET_TIME(reset_time), ~MPLL_RESET_TIME_MASK); 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_civoid r600_engine_clock_entry_enable(struct radeon_device *rdev, 4468c2ecf20Sopenharmony_ci u32 index, bool enable) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci if (enable) 4498c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4508c2ecf20Sopenharmony_ci STEP_0_SPLL_ENTRY_VALID, ~STEP_0_SPLL_ENTRY_VALID); 4518c2ecf20Sopenharmony_ci else 4528c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4538c2ecf20Sopenharmony_ci 0, ~STEP_0_SPLL_ENTRY_VALID); 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_civoid r600_engine_clock_entry_enable_pulse_skipping(struct radeon_device *rdev, 4578c2ecf20Sopenharmony_ci u32 index, bool enable) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci if (enable) 4608c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4618c2ecf20Sopenharmony_ci STEP_0_SPLL_STEP_ENABLE, ~STEP_0_SPLL_STEP_ENABLE); 4628c2ecf20Sopenharmony_ci else 4638c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4648c2ecf20Sopenharmony_ci 0, ~STEP_0_SPLL_STEP_ENABLE); 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_civoid r600_engine_clock_entry_enable_post_divider(struct radeon_device *rdev, 4688c2ecf20Sopenharmony_ci u32 index, bool enable) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci if (enable) 4718c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4728c2ecf20Sopenharmony_ci STEP_0_POST_DIV_EN, ~STEP_0_POST_DIV_EN); 4738c2ecf20Sopenharmony_ci else 4748c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4758c2ecf20Sopenharmony_ci 0, ~STEP_0_POST_DIV_EN); 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_civoid r600_engine_clock_entry_set_post_divider(struct radeon_device *rdev, 4798c2ecf20Sopenharmony_ci u32 index, u32 divider) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2), 4828c2ecf20Sopenharmony_ci STEP_0_SPLL_POST_DIV(divider), ~STEP_0_SPLL_POST_DIV_MASK); 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_civoid r600_engine_clock_entry_set_reference_divider(struct radeon_device *rdev, 4868c2ecf20Sopenharmony_ci u32 index, u32 divider) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2), 4898c2ecf20Sopenharmony_ci STEP_0_SPLL_REF_DIV(divider), ~STEP_0_SPLL_REF_DIV_MASK); 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_civoid r600_engine_clock_entry_set_feedback_divider(struct radeon_device *rdev, 4938c2ecf20Sopenharmony_ci u32 index, u32 divider) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2), 4968c2ecf20Sopenharmony_ci STEP_0_SPLL_FB_DIV(divider), ~STEP_0_SPLL_FB_DIV_MASK); 4978c2ecf20Sopenharmony_ci} 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_civoid r600_engine_clock_entry_set_step_time(struct radeon_device *rdev, 5008c2ecf20Sopenharmony_ci u32 index, u32 step_time) 5018c2ecf20Sopenharmony_ci{ 5028c2ecf20Sopenharmony_ci WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2), 5038c2ecf20Sopenharmony_ci STEP_0_SPLL_STEP_TIME(step_time), ~STEP_0_SPLL_STEP_TIME_MASK); 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_civoid r600_vid_rt_set_ssu(struct radeon_device *rdev, u32 u) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci WREG32_P(VID_RT, SSTU(u), ~SSTU_MASK); 5098c2ecf20Sopenharmony_ci} 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_civoid r600_vid_rt_set_vru(struct radeon_device *rdev, u32 u) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci WREG32_P(VID_RT, VID_CRTU(u), ~VID_CRTU_MASK); 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_civoid r600_vid_rt_set_vrt(struct radeon_device *rdev, u32 rt) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci WREG32_P(VID_RT, VID_CRT(rt), ~VID_CRT_MASK); 5198c2ecf20Sopenharmony_ci} 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_civoid r600_voltage_control_enable_pins(struct radeon_device *rdev, 5228c2ecf20Sopenharmony_ci u64 mask) 5238c2ecf20Sopenharmony_ci{ 5248c2ecf20Sopenharmony_ci WREG32(LOWER_GPIO_ENABLE, mask & 0xffffffff); 5258c2ecf20Sopenharmony_ci WREG32(UPPER_GPIO_ENABLE, upper_32_bits(mask)); 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_civoid r600_voltage_control_program_voltages(struct radeon_device *rdev, 5308c2ecf20Sopenharmony_ci enum r600_power_level index, u64 pins) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci u32 tmp, mask; 5338c2ecf20Sopenharmony_ci u32 ix = 3 - (3 & index); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci WREG32(CTXSW_VID_LOWER_GPIO_CNTL + (ix * 4), pins & 0xffffffff); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci mask = 7 << (3 * ix); 5388c2ecf20Sopenharmony_ci tmp = RREG32(VID_UPPER_GPIO_CNTL); 5398c2ecf20Sopenharmony_ci tmp = (tmp & ~mask) | ((pins >> (32 - (3 * ix))) & mask); 5408c2ecf20Sopenharmony_ci WREG32(VID_UPPER_GPIO_CNTL, tmp); 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_civoid r600_voltage_control_deactivate_static_control(struct radeon_device *rdev, 5448c2ecf20Sopenharmony_ci u64 mask) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci u32 gpio; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci gpio = RREG32(GPIOPAD_MASK); 5498c2ecf20Sopenharmony_ci gpio &= ~mask; 5508c2ecf20Sopenharmony_ci WREG32(GPIOPAD_MASK, gpio); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci gpio = RREG32(GPIOPAD_EN); 5538c2ecf20Sopenharmony_ci gpio &= ~mask; 5548c2ecf20Sopenharmony_ci WREG32(GPIOPAD_EN, gpio); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci gpio = RREG32(GPIOPAD_A); 5578c2ecf20Sopenharmony_ci gpio &= ~mask; 5588c2ecf20Sopenharmony_ci WREG32(GPIOPAD_A, gpio); 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_civoid r600_power_level_enable(struct radeon_device *rdev, 5628c2ecf20Sopenharmony_ci enum r600_power_level index, bool enable) 5638c2ecf20Sopenharmony_ci{ 5648c2ecf20Sopenharmony_ci u32 ix = 3 - (3 & index); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if (enable) 5678c2ecf20Sopenharmony_ci WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), CTXSW_FREQ_STATE_ENABLE, 5688c2ecf20Sopenharmony_ci ~CTXSW_FREQ_STATE_ENABLE); 5698c2ecf20Sopenharmony_ci else 5708c2ecf20Sopenharmony_ci WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 0, 5718c2ecf20Sopenharmony_ci ~CTXSW_FREQ_STATE_ENABLE); 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_civoid r600_power_level_set_voltage_index(struct radeon_device *rdev, 5758c2ecf20Sopenharmony_ci enum r600_power_level index, u32 voltage_index) 5768c2ecf20Sopenharmony_ci{ 5778c2ecf20Sopenharmony_ci u32 ix = 3 - (3 & index); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 5808c2ecf20Sopenharmony_ci CTXSW_FREQ_VIDS_CFG_INDEX(voltage_index), ~CTXSW_FREQ_VIDS_CFG_INDEX_MASK); 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_civoid r600_power_level_set_mem_clock_index(struct radeon_device *rdev, 5848c2ecf20Sopenharmony_ci enum r600_power_level index, u32 mem_clock_index) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci u32 ix = 3 - (3 & index); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 5898c2ecf20Sopenharmony_ci CTXSW_FREQ_MCLK_CFG_INDEX(mem_clock_index), ~CTXSW_FREQ_MCLK_CFG_INDEX_MASK); 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_civoid r600_power_level_set_eng_clock_index(struct radeon_device *rdev, 5938c2ecf20Sopenharmony_ci enum r600_power_level index, u32 eng_clock_index) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci u32 ix = 3 - (3 & index); 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 5988c2ecf20Sopenharmony_ci CTXSW_FREQ_SCLK_CFG_INDEX(eng_clock_index), ~CTXSW_FREQ_SCLK_CFG_INDEX_MASK); 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_civoid r600_power_level_set_watermark_id(struct radeon_device *rdev, 6028c2ecf20Sopenharmony_ci enum r600_power_level index, 6038c2ecf20Sopenharmony_ci enum r600_display_watermark watermark_id) 6048c2ecf20Sopenharmony_ci{ 6058c2ecf20Sopenharmony_ci u32 ix = 3 - (3 & index); 6068c2ecf20Sopenharmony_ci u32 tmp = 0; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (watermark_id == R600_DISPLAY_WATERMARK_HIGH) 6098c2ecf20Sopenharmony_ci tmp = CTXSW_FREQ_DISPLAY_WATERMARK; 6108c2ecf20Sopenharmony_ci WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), tmp, ~CTXSW_FREQ_DISPLAY_WATERMARK); 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_civoid r600_power_level_set_pcie_gen2(struct radeon_device *rdev, 6148c2ecf20Sopenharmony_ci enum r600_power_level index, bool compatible) 6158c2ecf20Sopenharmony_ci{ 6168c2ecf20Sopenharmony_ci u32 ix = 3 - (3 & index); 6178c2ecf20Sopenharmony_ci u32 tmp = 0; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci if (compatible) 6208c2ecf20Sopenharmony_ci tmp = CTXSW_FREQ_GEN2PCIE_VOLT; 6218c2ecf20Sopenharmony_ci WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), tmp, ~CTXSW_FREQ_GEN2PCIE_VOLT); 6228c2ecf20Sopenharmony_ci} 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_cienum r600_power_level r600_power_level_get_current_index(struct radeon_device *rdev) 6258c2ecf20Sopenharmony_ci{ 6268c2ecf20Sopenharmony_ci u32 tmp; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci tmp = RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK; 6298c2ecf20Sopenharmony_ci tmp >>= CURRENT_PROFILE_INDEX_SHIFT; 6308c2ecf20Sopenharmony_ci return tmp; 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cienum r600_power_level r600_power_level_get_target_index(struct radeon_device *rdev) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci u32 tmp; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci tmp = RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_PROFILE_INDEX_MASK; 6388c2ecf20Sopenharmony_ci tmp >>= TARGET_PROFILE_INDEX_SHIFT; 6398c2ecf20Sopenharmony_ci return tmp; 6408c2ecf20Sopenharmony_ci} 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_civoid r600_power_level_set_enter_index(struct radeon_device *rdev, 6438c2ecf20Sopenharmony_ci enum r600_power_level index) 6448c2ecf20Sopenharmony_ci{ 6458c2ecf20Sopenharmony_ci WREG32_P(TARGET_AND_CURRENT_PROFILE_INDEX, DYN_PWR_ENTER_INDEX(index), 6468c2ecf20Sopenharmony_ci ~DYN_PWR_ENTER_INDEX_MASK); 6478c2ecf20Sopenharmony_ci} 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_civoid r600_wait_for_power_level_unequal(struct radeon_device *rdev, 6508c2ecf20Sopenharmony_ci enum r600_power_level index) 6518c2ecf20Sopenharmony_ci{ 6528c2ecf20Sopenharmony_ci int i; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 6558c2ecf20Sopenharmony_ci if (r600_power_level_get_target_index(rdev) != index) 6568c2ecf20Sopenharmony_ci break; 6578c2ecf20Sopenharmony_ci udelay(1); 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 6618c2ecf20Sopenharmony_ci if (r600_power_level_get_current_index(rdev) != index) 6628c2ecf20Sopenharmony_ci break; 6638c2ecf20Sopenharmony_ci udelay(1); 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci} 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_civoid r600_wait_for_power_level(struct radeon_device *rdev, 6688c2ecf20Sopenharmony_ci enum r600_power_level index) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci int i; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 6738c2ecf20Sopenharmony_ci if (r600_power_level_get_target_index(rdev) == index) 6748c2ecf20Sopenharmony_ci break; 6758c2ecf20Sopenharmony_ci udelay(1); 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 6798c2ecf20Sopenharmony_ci if (r600_power_level_get_current_index(rdev) == index) 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci udelay(1); 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_civoid r600_start_dpm(struct radeon_device *rdev) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci r600_enable_sclk_control(rdev, false); 6888c2ecf20Sopenharmony_ci r600_enable_mclk_control(rdev, false); 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci r600_dynamicpm_enable(rdev, true); 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci radeon_wait_for_vblank(rdev, 0); 6938c2ecf20Sopenharmony_ci radeon_wait_for_vblank(rdev, 1); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci r600_enable_spll_bypass(rdev, true); 6968c2ecf20Sopenharmony_ci r600_wait_for_spll_change(rdev); 6978c2ecf20Sopenharmony_ci r600_enable_spll_bypass(rdev, false); 6988c2ecf20Sopenharmony_ci r600_wait_for_spll_change(rdev); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci r600_enable_spll_bypass(rdev, true); 7018c2ecf20Sopenharmony_ci r600_wait_for_spll_change(rdev); 7028c2ecf20Sopenharmony_ci r600_enable_spll_bypass(rdev, false); 7038c2ecf20Sopenharmony_ci r600_wait_for_spll_change(rdev); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci r600_enable_sclk_control(rdev, true); 7068c2ecf20Sopenharmony_ci r600_enable_mclk_control(rdev, true); 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_civoid r600_stop_dpm(struct radeon_device *rdev) 7108c2ecf20Sopenharmony_ci{ 7118c2ecf20Sopenharmony_ci r600_dynamicpm_enable(rdev, false); 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ciint r600_dpm_pre_set_power_state(struct radeon_device *rdev) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci return 0; 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_civoid r600_dpm_post_set_power_state(struct radeon_device *rdev) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_cibool r600_is_uvd_state(u32 class, u32 class2) 7258c2ecf20Sopenharmony_ci{ 7268c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 7278c2ecf20Sopenharmony_ci return true; 7288c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 7298c2ecf20Sopenharmony_ci return true; 7308c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 7318c2ecf20Sopenharmony_ci return true; 7328c2ecf20Sopenharmony_ci if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 7338c2ecf20Sopenharmony_ci return true; 7348c2ecf20Sopenharmony_ci if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 7358c2ecf20Sopenharmony_ci return true; 7368c2ecf20Sopenharmony_ci return false; 7378c2ecf20Sopenharmony_ci} 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_cistatic int r600_set_thermal_temperature_range(struct radeon_device *rdev, 7408c2ecf20Sopenharmony_ci int min_temp, int max_temp) 7418c2ecf20Sopenharmony_ci{ 7428c2ecf20Sopenharmony_ci int low_temp = 0 * 1000; 7438c2ecf20Sopenharmony_ci int high_temp = 255 * 1000; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci if (low_temp < min_temp) 7468c2ecf20Sopenharmony_ci low_temp = min_temp; 7478c2ecf20Sopenharmony_ci if (high_temp > max_temp) 7488c2ecf20Sopenharmony_ci high_temp = max_temp; 7498c2ecf20Sopenharmony_ci if (high_temp < low_temp) { 7508c2ecf20Sopenharmony_ci DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); 7518c2ecf20Sopenharmony_ci return -EINVAL; 7528c2ecf20Sopenharmony_ci } 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK); 7558c2ecf20Sopenharmony_ci WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK); 7568c2ecf20Sopenharmony_ci WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.min_temp = low_temp; 7598c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.max_temp = high_temp; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci return 0; 7628c2ecf20Sopenharmony_ci} 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_cibool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor) 7658c2ecf20Sopenharmony_ci{ 7668c2ecf20Sopenharmony_ci switch (sensor) { 7678c2ecf20Sopenharmony_ci case THERMAL_TYPE_RV6XX: 7688c2ecf20Sopenharmony_ci case THERMAL_TYPE_RV770: 7698c2ecf20Sopenharmony_ci case THERMAL_TYPE_EVERGREEN: 7708c2ecf20Sopenharmony_ci case THERMAL_TYPE_SUMO: 7718c2ecf20Sopenharmony_ci case THERMAL_TYPE_NI: 7728c2ecf20Sopenharmony_ci case THERMAL_TYPE_SI: 7738c2ecf20Sopenharmony_ci case THERMAL_TYPE_CI: 7748c2ecf20Sopenharmony_ci case THERMAL_TYPE_KV: 7758c2ecf20Sopenharmony_ci return true; 7768c2ecf20Sopenharmony_ci case THERMAL_TYPE_ADT7473_WITH_INTERNAL: 7778c2ecf20Sopenharmony_ci case THERMAL_TYPE_EMC2103_WITH_INTERNAL: 7788c2ecf20Sopenharmony_ci return false; /* need special handling */ 7798c2ecf20Sopenharmony_ci case THERMAL_TYPE_NONE: 7808c2ecf20Sopenharmony_ci case THERMAL_TYPE_EXTERNAL: 7818c2ecf20Sopenharmony_ci case THERMAL_TYPE_EXTERNAL_GPIO: 7828c2ecf20Sopenharmony_ci default: 7838c2ecf20Sopenharmony_ci return false; 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci} 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ciint r600_dpm_late_enable(struct radeon_device *rdev) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci int ret; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci if (rdev->irq.installed && 7928c2ecf20Sopenharmony_ci r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 7938c2ecf20Sopenharmony_ci ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); 7948c2ecf20Sopenharmony_ci if (ret) 7958c2ecf20Sopenharmony_ci return ret; 7968c2ecf20Sopenharmony_ci rdev->irq.dpm_thermal = true; 7978c2ecf20Sopenharmony_ci radeon_irq_set(rdev); 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci return 0; 8018c2ecf20Sopenharmony_ci} 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ciunion power_info { 8048c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO info; 8058c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V2 info_2; 8068c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V3 info_3; 8078c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 8088c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 8098c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 8108c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; 8118c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; 8128c2ecf20Sopenharmony_ci}; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ciunion fan_info { 8158c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_FANTABLE fan; 8168c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_FANTABLE2 fan2; 8178c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_FANTABLE3 fan3; 8188c2ecf20Sopenharmony_ci}; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependency_table *radeon_table, 8218c2ecf20Sopenharmony_ci ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) 8228c2ecf20Sopenharmony_ci{ 8238c2ecf20Sopenharmony_ci u32 size = atom_table->ucNumEntries * 8248c2ecf20Sopenharmony_ci sizeof(struct radeon_clock_voltage_dependency_entry); 8258c2ecf20Sopenharmony_ci int i; 8268c2ecf20Sopenharmony_ci ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci radeon_table->entries = kzalloc(size, GFP_KERNEL); 8298c2ecf20Sopenharmony_ci if (!radeon_table->entries) 8308c2ecf20Sopenharmony_ci return -ENOMEM; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci entry = &atom_table->entries[0]; 8338c2ecf20Sopenharmony_ci for (i = 0; i < atom_table->ucNumEntries; i++) { 8348c2ecf20Sopenharmony_ci radeon_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | 8358c2ecf20Sopenharmony_ci (entry->ucClockHigh << 16); 8368c2ecf20Sopenharmony_ci radeon_table->entries[i].v = le16_to_cpu(entry->usVoltage); 8378c2ecf20Sopenharmony_ci entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) 8388c2ecf20Sopenharmony_ci ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); 8398c2ecf20Sopenharmony_ci } 8408c2ecf20Sopenharmony_ci radeon_table->count = atom_table->ucNumEntries; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci return 0; 8438c2ecf20Sopenharmony_ci} 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ciint r600_get_platform_caps(struct radeon_device *rdev) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 8488c2ecf20Sopenharmony_ci union power_info *power_info; 8498c2ecf20Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 8508c2ecf20Sopenharmony_ci u16 data_offset; 8518c2ecf20Sopenharmony_ci u8 frev, crev; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 8548c2ecf20Sopenharmony_ci &frev, &crev, &data_offset)) 8558c2ecf20Sopenharmony_ci return -EINVAL; 8568c2ecf20Sopenharmony_ci power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); 8598c2ecf20Sopenharmony_ci rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); 8608c2ecf20Sopenharmony_ci rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci return 0; 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ 8668c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 8678c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 8688c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 8698c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 8708c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 8718c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ciint r600_parse_extended_power_table(struct radeon_device *rdev) 8748c2ecf20Sopenharmony_ci{ 8758c2ecf20Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 8768c2ecf20Sopenharmony_ci union power_info *power_info; 8778c2ecf20Sopenharmony_ci union fan_info *fan_info; 8788c2ecf20Sopenharmony_ci ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; 8798c2ecf20Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 8808c2ecf20Sopenharmony_ci u16 data_offset; 8818c2ecf20Sopenharmony_ci u8 frev, crev; 8828c2ecf20Sopenharmony_ci int ret, i; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 8858c2ecf20Sopenharmony_ci &frev, &crev, &data_offset)) 8868c2ecf20Sopenharmony_ci return -EINVAL; 8878c2ecf20Sopenharmony_ci power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci /* fan table */ 8908c2ecf20Sopenharmony_ci if (le16_to_cpu(power_info->pplib.usTableSize) >= 8918c2ecf20Sopenharmony_ci sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 8928c2ecf20Sopenharmony_ci if (power_info->pplib3.usFanTableOffset) { 8938c2ecf20Sopenharmony_ci fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + 8948c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib3.usFanTableOffset)); 8958c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; 8968c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); 8978c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); 8988c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); 8998c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); 9008c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); 9018c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); 9028c2ecf20Sopenharmony_ci if (fan_info->fan.ucFanTableFormat >= 2) 9038c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); 9048c2ecf20Sopenharmony_ci else 9058c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.t_max = 10900; 9068c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.cycle_delay = 100000; 9078c2ecf20Sopenharmony_ci if (fan_info->fan.ucFanTableFormat >= 3) { 9088c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; 9098c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.default_max_fan_pwm = 9108c2ecf20Sopenharmony_ci le16_to_cpu(fan_info->fan3.usFanPWMMax); 9118c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.default_fan_output_sensitivity = 4836; 9128c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.fan_output_sensitivity = 9138c2ecf20Sopenharmony_ci le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci rdev->pm.dpm.fan.ucode_fan_control = true; 9168c2ecf20Sopenharmony_ci } 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci /* clock dependancy tables, shedding tables */ 9208c2ecf20Sopenharmony_ci if (le16_to_cpu(power_info->pplib.usTableSize) >= 9218c2ecf20Sopenharmony_ci sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { 9228c2ecf20Sopenharmony_ci if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { 9238c2ecf20Sopenharmony_ci dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 9248c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 9258c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); 9268c2ecf20Sopenharmony_ci ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, 9278c2ecf20Sopenharmony_ci dep_table); 9288c2ecf20Sopenharmony_ci if (ret) 9298c2ecf20Sopenharmony_ci return ret; 9308c2ecf20Sopenharmony_ci } 9318c2ecf20Sopenharmony_ci if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { 9328c2ecf20Sopenharmony_ci dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 9338c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 9348c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); 9358c2ecf20Sopenharmony_ci ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk, 9368c2ecf20Sopenharmony_ci dep_table); 9378c2ecf20Sopenharmony_ci if (ret) { 9388c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); 9398c2ecf20Sopenharmony_ci return ret; 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci } 9428c2ecf20Sopenharmony_ci if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { 9438c2ecf20Sopenharmony_ci dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 9448c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 9458c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); 9468c2ecf20Sopenharmony_ci ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, 9478c2ecf20Sopenharmony_ci dep_table); 9488c2ecf20Sopenharmony_ci if (ret) { 9498c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); 9508c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); 9518c2ecf20Sopenharmony_ci return ret; 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci } 9548c2ecf20Sopenharmony_ci if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { 9558c2ecf20Sopenharmony_ci dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 9568c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 9578c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); 9588c2ecf20Sopenharmony_ci ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, 9598c2ecf20Sopenharmony_ci dep_table); 9608c2ecf20Sopenharmony_ci if (ret) { 9618c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); 9628c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); 9638c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); 9648c2ecf20Sopenharmony_ci return ret; 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci } 9678c2ecf20Sopenharmony_ci if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { 9688c2ecf20Sopenharmony_ci ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = 9698c2ecf20Sopenharmony_ci (ATOM_PPLIB_Clock_Voltage_Limit_Table *) 9708c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 9718c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); 9728c2ecf20Sopenharmony_ci if (clk_v->ucNumEntries) { 9738c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = 9748c2ecf20Sopenharmony_ci le16_to_cpu(clk_v->entries[0].usSclkLow) | 9758c2ecf20Sopenharmony_ci (clk_v->entries[0].ucSclkHigh << 16); 9768c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = 9778c2ecf20Sopenharmony_ci le16_to_cpu(clk_v->entries[0].usMclkLow) | 9788c2ecf20Sopenharmony_ci (clk_v->entries[0].ucMclkHigh << 16); 9798c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = 9808c2ecf20Sopenharmony_ci le16_to_cpu(clk_v->entries[0].usVddc); 9818c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = 9828c2ecf20Sopenharmony_ci le16_to_cpu(clk_v->entries[0].usVddci); 9838c2ecf20Sopenharmony_ci } 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { 9868c2ecf20Sopenharmony_ci ATOM_PPLIB_PhaseSheddingLimits_Table *psl = 9878c2ecf20Sopenharmony_ci (ATOM_PPLIB_PhaseSheddingLimits_Table *) 9888c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 9898c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); 9908c2ecf20Sopenharmony_ci ATOM_PPLIB_PhaseSheddingLimits_Record *entry; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = 9938c2ecf20Sopenharmony_ci kcalloc(psl->ucNumEntries, 9948c2ecf20Sopenharmony_ci sizeof(struct radeon_phase_shedding_limits_entry), 9958c2ecf20Sopenharmony_ci GFP_KERNEL); 9968c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { 9978c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 9988c2ecf20Sopenharmony_ci return -ENOMEM; 9998c2ecf20Sopenharmony_ci } 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci entry = &psl->entries[0]; 10028c2ecf20Sopenharmony_ci for (i = 0; i < psl->ucNumEntries; i++) { 10038c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = 10048c2ecf20Sopenharmony_ci le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); 10058c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = 10068c2ecf20Sopenharmony_ci le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); 10078c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = 10088c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVoltage); 10098c2ecf20Sopenharmony_ci entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) 10108c2ecf20Sopenharmony_ci ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.phase_shedding_limits_table.count = 10138c2ecf20Sopenharmony_ci psl->ucNumEntries; 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci /* cac data */ 10188c2ecf20Sopenharmony_ci if (le16_to_cpu(power_info->pplib.usTableSize) >= 10198c2ecf20Sopenharmony_ci sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { 10208c2ecf20Sopenharmony_ci rdev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); 10218c2ecf20Sopenharmony_ci rdev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); 10228c2ecf20Sopenharmony_ci rdev->pm.dpm.near_tdp_limit_adjusted = rdev->pm.dpm.near_tdp_limit; 10238c2ecf20Sopenharmony_ci rdev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); 10248c2ecf20Sopenharmony_ci if (rdev->pm.dpm.tdp_od_limit) 10258c2ecf20Sopenharmony_ci rdev->pm.dpm.power_control = true; 10268c2ecf20Sopenharmony_ci else 10278c2ecf20Sopenharmony_ci rdev->pm.dpm.power_control = false; 10288c2ecf20Sopenharmony_ci rdev->pm.dpm.tdp_adjustment = 0; 10298c2ecf20Sopenharmony_ci rdev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); 10308c2ecf20Sopenharmony_ci rdev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); 10318c2ecf20Sopenharmony_ci rdev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); 10328c2ecf20Sopenharmony_ci if (power_info->pplib5.usCACLeakageTableOffset) { 10338c2ecf20Sopenharmony_ci ATOM_PPLIB_CAC_Leakage_Table *cac_table = 10348c2ecf20Sopenharmony_ci (ATOM_PPLIB_CAC_Leakage_Table *) 10358c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 10368c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); 10378c2ecf20Sopenharmony_ci ATOM_PPLIB_CAC_Leakage_Record *entry; 10388c2ecf20Sopenharmony_ci u32 size = cac_table->ucNumEntries * sizeof(struct radeon_cac_leakage_table); 10398c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); 10408c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.dyn_state.cac_leakage_table.entries) { 10418c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 10428c2ecf20Sopenharmony_ci return -ENOMEM; 10438c2ecf20Sopenharmony_ci } 10448c2ecf20Sopenharmony_ci entry = &cac_table->entries[0]; 10458c2ecf20Sopenharmony_ci for (i = 0; i < cac_table->ucNumEntries; i++) { 10468c2ecf20Sopenharmony_ci if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { 10478c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = 10488c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVddc1); 10498c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = 10508c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVddc2); 10518c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = 10528c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVddc3); 10538c2ecf20Sopenharmony_ci } else { 10548c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = 10558c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVddc); 10568c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = 10578c2ecf20Sopenharmony_ci le32_to_cpu(entry->ulLeakageValue); 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci entry = (ATOM_PPLIB_CAC_Leakage_Record *) 10608c2ecf20Sopenharmony_ci ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci } 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci /* ext tables */ 10678c2ecf20Sopenharmony_ci if (le16_to_cpu(power_info->pplib.usTableSize) >= 10688c2ecf20Sopenharmony_ci sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 10698c2ecf20Sopenharmony_ci ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) 10708c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 10718c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); 10728c2ecf20Sopenharmony_ci if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && 10738c2ecf20Sopenharmony_ci ext_hdr->usVCETableOffset) { 10748c2ecf20Sopenharmony_ci VCEClockInfoArray *array = (VCEClockInfoArray *) 10758c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 10768c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usVCETableOffset) + 1); 10778c2ecf20Sopenharmony_ci ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = 10788c2ecf20Sopenharmony_ci (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) 10798c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 10808c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 10818c2ecf20Sopenharmony_ci 1 + array->ucNumEntries * sizeof(VCEClockInfo)); 10828c2ecf20Sopenharmony_ci ATOM_PPLIB_VCE_State_Table *states = 10838c2ecf20Sopenharmony_ci (ATOM_PPLIB_VCE_State_Table *) 10848c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 10858c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 10868c2ecf20Sopenharmony_ci 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + 10878c2ecf20Sopenharmony_ci 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); 10888c2ecf20Sopenharmony_ci ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; 10898c2ecf20Sopenharmony_ci ATOM_PPLIB_VCE_State_Record *state_entry; 10908c2ecf20Sopenharmony_ci VCEClockInfo *vce_clk; 10918c2ecf20Sopenharmony_ci u32 size = limits->numEntries * 10928c2ecf20Sopenharmony_ci sizeof(struct radeon_vce_clock_voltage_dependency_entry); 10938c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = 10948c2ecf20Sopenharmony_ci kzalloc(size, GFP_KERNEL); 10958c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { 10968c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 10978c2ecf20Sopenharmony_ci return -ENOMEM; 10988c2ecf20Sopenharmony_ci } 10998c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = 11008c2ecf20Sopenharmony_ci limits->numEntries; 11018c2ecf20Sopenharmony_ci entry = &limits->entries[0]; 11028c2ecf20Sopenharmony_ci state_entry = &states->entries[0]; 11038c2ecf20Sopenharmony_ci for (i = 0; i < limits->numEntries; i++) { 11048c2ecf20Sopenharmony_ci vce_clk = (VCEClockInfo *) 11058c2ecf20Sopenharmony_ci ((u8 *)&array->entries[0] + 11068c2ecf20Sopenharmony_ci (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 11078c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = 11088c2ecf20Sopenharmony_ci le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 11098c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = 11108c2ecf20Sopenharmony_ci le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 11118c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = 11128c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVoltage); 11138c2ecf20Sopenharmony_ci entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) 11148c2ecf20Sopenharmony_ci ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci for (i = 0; i < states->numEntries; i++) { 11178c2ecf20Sopenharmony_ci if (i >= RADEON_MAX_VCE_LEVELS) 11188c2ecf20Sopenharmony_ci break; 11198c2ecf20Sopenharmony_ci vce_clk = (VCEClockInfo *) 11208c2ecf20Sopenharmony_ci ((u8 *)&array->entries[0] + 11218c2ecf20Sopenharmony_ci (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 11228c2ecf20Sopenharmony_ci rdev->pm.dpm.vce_states[i].evclk = 11238c2ecf20Sopenharmony_ci le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 11248c2ecf20Sopenharmony_ci rdev->pm.dpm.vce_states[i].ecclk = 11258c2ecf20Sopenharmony_ci le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 11268c2ecf20Sopenharmony_ci rdev->pm.dpm.vce_states[i].clk_idx = 11278c2ecf20Sopenharmony_ci state_entry->ucClockInfoIndex & 0x3f; 11288c2ecf20Sopenharmony_ci rdev->pm.dpm.vce_states[i].pstate = 11298c2ecf20Sopenharmony_ci (state_entry->ucClockInfoIndex & 0xc0) >> 6; 11308c2ecf20Sopenharmony_ci state_entry = (ATOM_PPLIB_VCE_State_Record *) 11318c2ecf20Sopenharmony_ci ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); 11328c2ecf20Sopenharmony_ci } 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && 11358c2ecf20Sopenharmony_ci ext_hdr->usUVDTableOffset) { 11368c2ecf20Sopenharmony_ci UVDClockInfoArray *array = (UVDClockInfoArray *) 11378c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 11388c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); 11398c2ecf20Sopenharmony_ci ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = 11408c2ecf20Sopenharmony_ci (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) 11418c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 11428c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + 11438c2ecf20Sopenharmony_ci 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); 11448c2ecf20Sopenharmony_ci ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; 11458c2ecf20Sopenharmony_ci u32 size = limits->numEntries * 11468c2ecf20Sopenharmony_ci sizeof(struct radeon_uvd_clock_voltage_dependency_entry); 11478c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = 11488c2ecf20Sopenharmony_ci kzalloc(size, GFP_KERNEL); 11498c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { 11508c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 11518c2ecf20Sopenharmony_ci return -ENOMEM; 11528c2ecf20Sopenharmony_ci } 11538c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = 11548c2ecf20Sopenharmony_ci limits->numEntries; 11558c2ecf20Sopenharmony_ci entry = &limits->entries[0]; 11568c2ecf20Sopenharmony_ci for (i = 0; i < limits->numEntries; i++) { 11578c2ecf20Sopenharmony_ci UVDClockInfo *uvd_clk = (UVDClockInfo *) 11588c2ecf20Sopenharmony_ci ((u8 *)&array->entries[0] + 11598c2ecf20Sopenharmony_ci (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); 11608c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = 11618c2ecf20Sopenharmony_ci le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); 11628c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = 11638c2ecf20Sopenharmony_ci le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); 11648c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = 11658c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVoltage); 11668c2ecf20Sopenharmony_ci entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) 11678c2ecf20Sopenharmony_ci ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); 11688c2ecf20Sopenharmony_ci } 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && 11718c2ecf20Sopenharmony_ci ext_hdr->usSAMUTableOffset) { 11728c2ecf20Sopenharmony_ci ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = 11738c2ecf20Sopenharmony_ci (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) 11748c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 11758c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); 11768c2ecf20Sopenharmony_ci ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; 11778c2ecf20Sopenharmony_ci u32 size = limits->numEntries * 11788c2ecf20Sopenharmony_ci sizeof(struct radeon_clock_voltage_dependency_entry); 11798c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = 11808c2ecf20Sopenharmony_ci kzalloc(size, GFP_KERNEL); 11818c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { 11828c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 11838c2ecf20Sopenharmony_ci return -ENOMEM; 11848c2ecf20Sopenharmony_ci } 11858c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = 11868c2ecf20Sopenharmony_ci limits->numEntries; 11878c2ecf20Sopenharmony_ci entry = &limits->entries[0]; 11888c2ecf20Sopenharmony_ci for (i = 0; i < limits->numEntries; i++) { 11898c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = 11908c2ecf20Sopenharmony_ci le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); 11918c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = 11928c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVoltage); 11938c2ecf20Sopenharmony_ci entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) 11948c2ecf20Sopenharmony_ci ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); 11958c2ecf20Sopenharmony_ci } 11968c2ecf20Sopenharmony_ci } 11978c2ecf20Sopenharmony_ci if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && 11988c2ecf20Sopenharmony_ci ext_hdr->usPPMTableOffset) { 11998c2ecf20Sopenharmony_ci ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) 12008c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 12018c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usPPMTableOffset)); 12028c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table = 12038c2ecf20Sopenharmony_ci kzalloc(sizeof(struct radeon_ppm_table), GFP_KERNEL); 12048c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.dyn_state.ppm_table) { 12058c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 12068c2ecf20Sopenharmony_ci return -ENOMEM; 12078c2ecf20Sopenharmony_ci } 12088c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; 12098c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->cpu_core_number = 12108c2ecf20Sopenharmony_ci le16_to_cpu(ppm->usCpuCoreNumber); 12118c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->platform_tdp = 12128c2ecf20Sopenharmony_ci le32_to_cpu(ppm->ulPlatformTDP); 12138c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = 12148c2ecf20Sopenharmony_ci le32_to_cpu(ppm->ulSmallACPlatformTDP); 12158c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->platform_tdc = 12168c2ecf20Sopenharmony_ci le32_to_cpu(ppm->ulPlatformTDC); 12178c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = 12188c2ecf20Sopenharmony_ci le32_to_cpu(ppm->ulSmallACPlatformTDC); 12198c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->apu_tdp = 12208c2ecf20Sopenharmony_ci le32_to_cpu(ppm->ulApuTDP); 12218c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = 12228c2ecf20Sopenharmony_ci le32_to_cpu(ppm->ulDGpuTDP); 12238c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = 12248c2ecf20Sopenharmony_ci le32_to_cpu(ppm->ulDGpuUlvPower); 12258c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.ppm_table->tj_max = 12268c2ecf20Sopenharmony_ci le32_to_cpu(ppm->ulTjmax); 12278c2ecf20Sopenharmony_ci } 12288c2ecf20Sopenharmony_ci if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && 12298c2ecf20Sopenharmony_ci ext_hdr->usACPTableOffset) { 12308c2ecf20Sopenharmony_ci ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = 12318c2ecf20Sopenharmony_ci (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) 12328c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 12338c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usACPTableOffset) + 1); 12348c2ecf20Sopenharmony_ci ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; 12358c2ecf20Sopenharmony_ci u32 size = limits->numEntries * 12368c2ecf20Sopenharmony_ci sizeof(struct radeon_clock_voltage_dependency_entry); 12378c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = 12388c2ecf20Sopenharmony_ci kzalloc(size, GFP_KERNEL); 12398c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { 12408c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 12418c2ecf20Sopenharmony_ci return -ENOMEM; 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = 12448c2ecf20Sopenharmony_ci limits->numEntries; 12458c2ecf20Sopenharmony_ci entry = &limits->entries[0]; 12468c2ecf20Sopenharmony_ci for (i = 0; i < limits->numEntries; i++) { 12478c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = 12488c2ecf20Sopenharmony_ci le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); 12498c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = 12508c2ecf20Sopenharmony_ci le16_to_cpu(entry->usVoltage); 12518c2ecf20Sopenharmony_ci entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) 12528c2ecf20Sopenharmony_ci ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); 12538c2ecf20Sopenharmony_ci } 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && 12568c2ecf20Sopenharmony_ci ext_hdr->usPowerTuneTableOffset) { 12578c2ecf20Sopenharmony_ci u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + 12588c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 12598c2ecf20Sopenharmony_ci ATOM_PowerTune_Table *pt; 12608c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table = 12618c2ecf20Sopenharmony_ci kzalloc(sizeof(struct radeon_cac_tdp_table), GFP_KERNEL); 12628c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.dyn_state.cac_tdp_table) { 12638c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 12648c2ecf20Sopenharmony_ci return -ENOMEM; 12658c2ecf20Sopenharmony_ci } 12668c2ecf20Sopenharmony_ci if (rev > 0) { 12678c2ecf20Sopenharmony_ci ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) 12688c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 12698c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 12708c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 12718c2ecf20Sopenharmony_ci le16_to_cpu(ppt->usMaximumPowerDeliveryLimit); 12728c2ecf20Sopenharmony_ci pt = &ppt->power_tune_table; 12738c2ecf20Sopenharmony_ci } else { 12748c2ecf20Sopenharmony_ci ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) 12758c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 12768c2ecf20Sopenharmony_ci le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 12778c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; 12788c2ecf20Sopenharmony_ci pt = &ppt->power_tune_table; 12798c2ecf20Sopenharmony_ci } 12808c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); 12818c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = 12828c2ecf20Sopenharmony_ci le16_to_cpu(pt->usConfigurableTDP); 12838c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); 12848c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = 12858c2ecf20Sopenharmony_ci le16_to_cpu(pt->usBatteryPowerLimit); 12868c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = 12878c2ecf20Sopenharmony_ci le16_to_cpu(pt->usSmallPowerLimit); 12888c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = 12898c2ecf20Sopenharmony_ci le16_to_cpu(pt->usLowCACLeakage); 12908c2ecf20Sopenharmony_ci rdev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = 12918c2ecf20Sopenharmony_ci le16_to_cpu(pt->usHighCACLeakage); 12928c2ecf20Sopenharmony_ci } 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci return 0; 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_civoid r600_free_extended_power_table(struct radeon_device *rdev) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci struct radeon_dpm_dynamic_state *dyn_state = &rdev->pm.dpm.dyn_state; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci kfree(dyn_state->vddc_dependency_on_sclk.entries); 13038c2ecf20Sopenharmony_ci kfree(dyn_state->vddci_dependency_on_mclk.entries); 13048c2ecf20Sopenharmony_ci kfree(dyn_state->vddc_dependency_on_mclk.entries); 13058c2ecf20Sopenharmony_ci kfree(dyn_state->mvdd_dependency_on_mclk.entries); 13068c2ecf20Sopenharmony_ci kfree(dyn_state->cac_leakage_table.entries); 13078c2ecf20Sopenharmony_ci kfree(dyn_state->phase_shedding_limits_table.entries); 13088c2ecf20Sopenharmony_ci kfree(dyn_state->ppm_table); 13098c2ecf20Sopenharmony_ci kfree(dyn_state->cac_tdp_table); 13108c2ecf20Sopenharmony_ci kfree(dyn_state->vce_clock_voltage_dependency_table.entries); 13118c2ecf20Sopenharmony_ci kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); 13128c2ecf20Sopenharmony_ci kfree(dyn_state->samu_clock_voltage_dependency_table.entries); 13138c2ecf20Sopenharmony_ci kfree(dyn_state->acp_clock_voltage_dependency_table.entries); 13148c2ecf20Sopenharmony_ci} 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_cienum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, 13178c2ecf20Sopenharmony_ci u32 sys_mask, 13188c2ecf20Sopenharmony_ci enum radeon_pcie_gen asic_gen, 13198c2ecf20Sopenharmony_ci enum radeon_pcie_gen default_gen) 13208c2ecf20Sopenharmony_ci{ 13218c2ecf20Sopenharmony_ci switch (asic_gen) { 13228c2ecf20Sopenharmony_ci case RADEON_PCIE_GEN1: 13238c2ecf20Sopenharmony_ci return RADEON_PCIE_GEN1; 13248c2ecf20Sopenharmony_ci case RADEON_PCIE_GEN2: 13258c2ecf20Sopenharmony_ci return RADEON_PCIE_GEN2; 13268c2ecf20Sopenharmony_ci case RADEON_PCIE_GEN3: 13278c2ecf20Sopenharmony_ci return RADEON_PCIE_GEN3; 13288c2ecf20Sopenharmony_ci default: 13298c2ecf20Sopenharmony_ci if ((sys_mask & RADEON_PCIE_SPEED_80) && (default_gen == RADEON_PCIE_GEN3)) 13308c2ecf20Sopenharmony_ci return RADEON_PCIE_GEN3; 13318c2ecf20Sopenharmony_ci else if ((sys_mask & RADEON_PCIE_SPEED_50) && (default_gen == RADEON_PCIE_GEN2)) 13328c2ecf20Sopenharmony_ci return RADEON_PCIE_GEN2; 13338c2ecf20Sopenharmony_ci else 13348c2ecf20Sopenharmony_ci return RADEON_PCIE_GEN1; 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci return RADEON_PCIE_GEN1; 13378c2ecf20Sopenharmony_ci} 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ciu16 r600_get_pcie_lane_support(struct radeon_device *rdev, 13408c2ecf20Sopenharmony_ci u16 asic_lanes, 13418c2ecf20Sopenharmony_ci u16 default_lanes) 13428c2ecf20Sopenharmony_ci{ 13438c2ecf20Sopenharmony_ci switch (asic_lanes) { 13448c2ecf20Sopenharmony_ci case 0: 13458c2ecf20Sopenharmony_ci default: 13468c2ecf20Sopenharmony_ci return default_lanes; 13478c2ecf20Sopenharmony_ci case 1: 13488c2ecf20Sopenharmony_ci return 1; 13498c2ecf20Sopenharmony_ci case 2: 13508c2ecf20Sopenharmony_ci return 2; 13518c2ecf20Sopenharmony_ci case 4: 13528c2ecf20Sopenharmony_ci return 4; 13538c2ecf20Sopenharmony_ci case 8: 13548c2ecf20Sopenharmony_ci return 8; 13558c2ecf20Sopenharmony_ci case 12: 13568c2ecf20Sopenharmony_ci return 12; 13578c2ecf20Sopenharmony_ci case 16: 13588c2ecf20Sopenharmony_ci return 16; 13598c2ecf20Sopenharmony_ci } 13608c2ecf20Sopenharmony_ci} 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ciu8 r600_encode_pci_lane_width(u32 lanes) 13638c2ecf20Sopenharmony_ci{ 13648c2ecf20Sopenharmony_ci u8 encoded_lanes[] = { 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 }; 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci if (lanes > 16) 13678c2ecf20Sopenharmony_ci return 0; 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci return encoded_lanes[lanes]; 13708c2ecf20Sopenharmony_ci} 1371