17ccd5a2cSjsg /* 27ccd5a2cSjsg * Copyright 2011 Advanced Micro Devices, Inc. 37ccd5a2cSjsg * 47ccd5a2cSjsg * Permission is hereby granted, free of charge, to any person obtaining a 57ccd5a2cSjsg * copy of this software and associated documentation files (the "Software"), 67ccd5a2cSjsg * to deal in the Software without restriction, including without limitation 77ccd5a2cSjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ccd5a2cSjsg * and/or sell copies of the Software, and to permit persons to whom the 97ccd5a2cSjsg * Software is furnished to do so, subject to the following conditions: 107ccd5a2cSjsg * 117ccd5a2cSjsg * The above copyright notice and this permission notice shall be included in 127ccd5a2cSjsg * all copies or substantial portions of the Software. 137ccd5a2cSjsg * 147ccd5a2cSjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157ccd5a2cSjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167ccd5a2cSjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177ccd5a2cSjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 187ccd5a2cSjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 197ccd5a2cSjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 207ccd5a2cSjsg * OTHER DEALINGS IN THE SOFTWARE. 217ccd5a2cSjsg * 227ccd5a2cSjsg * Authors: Alex Deucher 237ccd5a2cSjsg */ 247ccd5a2cSjsg 257ccd5a2cSjsg #include "radeon.h" 267ccd5a2cSjsg #include "radeon_asic.h" 277ccd5a2cSjsg #include "r600d.h" 287ccd5a2cSjsg #include "r600_dpm.h" 297ccd5a2cSjsg #include "atom.h" 307ccd5a2cSjsg 317ccd5a2cSjsg const u32 r600_utc[R600_PM_NUMBER_OF_TC] = 327ccd5a2cSjsg { 337ccd5a2cSjsg R600_UTC_DFLT_00, 347ccd5a2cSjsg R600_UTC_DFLT_01, 357ccd5a2cSjsg R600_UTC_DFLT_02, 367ccd5a2cSjsg R600_UTC_DFLT_03, 377ccd5a2cSjsg R600_UTC_DFLT_04, 387ccd5a2cSjsg R600_UTC_DFLT_05, 397ccd5a2cSjsg R600_UTC_DFLT_06, 407ccd5a2cSjsg R600_UTC_DFLT_07, 417ccd5a2cSjsg R600_UTC_DFLT_08, 427ccd5a2cSjsg R600_UTC_DFLT_09, 437ccd5a2cSjsg R600_UTC_DFLT_10, 447ccd5a2cSjsg R600_UTC_DFLT_11, 457ccd5a2cSjsg R600_UTC_DFLT_12, 467ccd5a2cSjsg R600_UTC_DFLT_13, 477ccd5a2cSjsg R600_UTC_DFLT_14, 487ccd5a2cSjsg }; 497ccd5a2cSjsg 507ccd5a2cSjsg const u32 r600_dtc[R600_PM_NUMBER_OF_TC] = 517ccd5a2cSjsg { 527ccd5a2cSjsg R600_DTC_DFLT_00, 537ccd5a2cSjsg R600_DTC_DFLT_01, 547ccd5a2cSjsg R600_DTC_DFLT_02, 557ccd5a2cSjsg R600_DTC_DFLT_03, 567ccd5a2cSjsg R600_DTC_DFLT_04, 577ccd5a2cSjsg R600_DTC_DFLT_05, 587ccd5a2cSjsg R600_DTC_DFLT_06, 597ccd5a2cSjsg R600_DTC_DFLT_07, 607ccd5a2cSjsg R600_DTC_DFLT_08, 617ccd5a2cSjsg R600_DTC_DFLT_09, 627ccd5a2cSjsg R600_DTC_DFLT_10, 637ccd5a2cSjsg R600_DTC_DFLT_11, 647ccd5a2cSjsg R600_DTC_DFLT_12, 657ccd5a2cSjsg R600_DTC_DFLT_13, 667ccd5a2cSjsg R600_DTC_DFLT_14, 677ccd5a2cSjsg }; 687ccd5a2cSjsg 697ccd5a2cSjsg void r600_dpm_print_class_info(u32 class, u32 class2) 707ccd5a2cSjsg { 717f4dd379Sjsg const char *s; 727f4dd379Sjsg 737ccd5a2cSjsg switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { 747ccd5a2cSjsg case ATOM_PPLIB_CLASSIFICATION_UI_NONE: 757ccd5a2cSjsg default: 767f4dd379Sjsg s = "none"; 777ccd5a2cSjsg break; 787ccd5a2cSjsg case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: 797f4dd379Sjsg s = "battery"; 807ccd5a2cSjsg break; 817ccd5a2cSjsg case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: 827f4dd379Sjsg s = "balanced"; 837ccd5a2cSjsg break; 847ccd5a2cSjsg case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: 857f4dd379Sjsg s = "performance"; 867ccd5a2cSjsg break; 877ccd5a2cSjsg } 887f4dd379Sjsg printk("\tui class: %s\n", s); 897f4dd379Sjsg 907ccd5a2cSjsg printk("\tinternal class:"); 917ccd5a2cSjsg if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && 927ccd5a2cSjsg (class2 == 0)) 937f4dd379Sjsg pr_cont(" none"); 947ccd5a2cSjsg else { 957ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) 967f4dd379Sjsg pr_cont(" boot"); 977ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 987f4dd379Sjsg pr_cont(" thermal"); 997ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 1007f4dd379Sjsg pr_cont(" limited_pwr"); 1017ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_REST) 1027f4dd379Sjsg pr_cont(" rest"); 1037ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) 1047f4dd379Sjsg pr_cont(" forced"); 1057ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 1067f4dd379Sjsg pr_cont(" 3d_perf"); 1077ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) 1087f4dd379Sjsg pr_cont(" ovrdrv"); 1097ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 1107f4dd379Sjsg pr_cont(" uvd"); 1117ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) 1127f4dd379Sjsg pr_cont(" 3d_low"); 1137ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) 1147f4dd379Sjsg pr_cont(" acpi"); 1157ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 1167f4dd379Sjsg pr_cont(" uvd_hd2"); 1177ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 1187f4dd379Sjsg pr_cont(" uvd_hd"); 1197ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 1207f4dd379Sjsg pr_cont(" uvd_sd"); 1217ccd5a2cSjsg if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 1227f4dd379Sjsg pr_cont(" limited_pwr2"); 1237ccd5a2cSjsg if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 1247f4dd379Sjsg pr_cont(" ulv"); 1257ccd5a2cSjsg if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 1267f4dd379Sjsg pr_cont(" uvd_mvc"); 1277ccd5a2cSjsg } 1287f4dd379Sjsg pr_cont("\n"); 1297ccd5a2cSjsg } 1307ccd5a2cSjsg 1317ccd5a2cSjsg void r600_dpm_print_cap_info(u32 caps) 1327ccd5a2cSjsg { 1337ccd5a2cSjsg printk("\tcaps:"); 1347ccd5a2cSjsg if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) 1357f4dd379Sjsg pr_cont(" single_disp"); 1367ccd5a2cSjsg if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) 1377f4dd379Sjsg pr_cont(" video"); 1387ccd5a2cSjsg if (caps & ATOM_PPLIB_DISALLOW_ON_DC) 1397f4dd379Sjsg pr_cont(" no_dc"); 1407f4dd379Sjsg pr_cont("\n"); 1417ccd5a2cSjsg } 1427ccd5a2cSjsg 1437ccd5a2cSjsg void r600_dpm_print_ps_status(struct radeon_device *rdev, 1447ccd5a2cSjsg struct radeon_ps *rps) 1457ccd5a2cSjsg { 1467ccd5a2cSjsg printk("\tstatus:"); 1477ccd5a2cSjsg if (rps == rdev->pm.dpm.current_ps) 1487f4dd379Sjsg pr_cont(" c"); 1497ccd5a2cSjsg if (rps == rdev->pm.dpm.requested_ps) 1507f4dd379Sjsg pr_cont(" r"); 1517ccd5a2cSjsg if (rps == rdev->pm.dpm.boot_ps) 1527f4dd379Sjsg pr_cont(" b"); 1537f4dd379Sjsg pr_cont("\n"); 1547ccd5a2cSjsg } 1557ccd5a2cSjsg 1567ccd5a2cSjsg u32 r600_dpm_get_vblank_time(struct radeon_device *rdev) 1577ccd5a2cSjsg { 158*33a3edb1Sjsg struct drm_device *dev = rdev_to_drm(rdev); 1597ccd5a2cSjsg struct drm_crtc *crtc; 1607ccd5a2cSjsg struct radeon_crtc *radeon_crtc; 1617ccd5a2cSjsg u32 vblank_in_pixels; 1627ccd5a2cSjsg u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ 1637ccd5a2cSjsg 1647ccd5a2cSjsg if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { 1657ccd5a2cSjsg list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1667ccd5a2cSjsg radeon_crtc = to_radeon_crtc(crtc); 1677ccd5a2cSjsg if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { 1687ccd5a2cSjsg vblank_in_pixels = 1697ccd5a2cSjsg radeon_crtc->hw_mode.crtc_htotal * 1707ccd5a2cSjsg (radeon_crtc->hw_mode.crtc_vblank_end - 1717ccd5a2cSjsg radeon_crtc->hw_mode.crtc_vdisplay + 1727ccd5a2cSjsg (radeon_crtc->v_border * 2)); 1737ccd5a2cSjsg 1747ccd5a2cSjsg vblank_time_us = vblank_in_pixels * 1000 / radeon_crtc->hw_mode.clock; 1757ccd5a2cSjsg break; 1767ccd5a2cSjsg } 1777ccd5a2cSjsg } 1787ccd5a2cSjsg } 1797ccd5a2cSjsg 1807ccd5a2cSjsg return vblank_time_us; 1817ccd5a2cSjsg } 1827ccd5a2cSjsg 1837ccd5a2cSjsg u32 r600_dpm_get_vrefresh(struct radeon_device *rdev) 1847ccd5a2cSjsg { 185*33a3edb1Sjsg struct drm_device *dev = rdev_to_drm(rdev); 1867ccd5a2cSjsg struct drm_crtc *crtc; 1877ccd5a2cSjsg struct radeon_crtc *radeon_crtc; 1887ccd5a2cSjsg u32 vrefresh = 0; 1897ccd5a2cSjsg 1907ccd5a2cSjsg if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { 1917ccd5a2cSjsg list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1927ccd5a2cSjsg radeon_crtc = to_radeon_crtc(crtc); 1937ccd5a2cSjsg if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { 1947ccd5a2cSjsg vrefresh = drm_mode_vrefresh(&radeon_crtc->hw_mode); 1957ccd5a2cSjsg break; 1967ccd5a2cSjsg } 1977ccd5a2cSjsg } 1987ccd5a2cSjsg } 1997ccd5a2cSjsg return vrefresh; 2007ccd5a2cSjsg } 2017ccd5a2cSjsg 2027ccd5a2cSjsg void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, 2037ccd5a2cSjsg u32 *p, u32 *u) 2047ccd5a2cSjsg { 2057ccd5a2cSjsg u32 b_c = 0; 2067ccd5a2cSjsg u32 i_c; 2077ccd5a2cSjsg u32 tmp; 2087ccd5a2cSjsg 2097ccd5a2cSjsg i_c = (i * r_c) / 100; 2107ccd5a2cSjsg tmp = i_c >> p_b; 2117ccd5a2cSjsg 2127ccd5a2cSjsg while (tmp) { 2137ccd5a2cSjsg b_c++; 2147ccd5a2cSjsg tmp >>= 1; 2157ccd5a2cSjsg } 2167ccd5a2cSjsg 2177ccd5a2cSjsg *u = (b_c + 1) / 2; 2187ccd5a2cSjsg *p = i_c / (1 << (2 * (*u))); 2197ccd5a2cSjsg } 2207ccd5a2cSjsg 2217ccd5a2cSjsg int r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th) 2227ccd5a2cSjsg { 2237ccd5a2cSjsg u32 k, a, ah, al; 2247ccd5a2cSjsg u32 t1; 2257ccd5a2cSjsg 2267ccd5a2cSjsg if ((fl == 0) || (fh == 0) || (fl > fh)) 2277ccd5a2cSjsg return -EINVAL; 2287ccd5a2cSjsg 2297ccd5a2cSjsg k = (100 * fh) / fl; 2307ccd5a2cSjsg t1 = (t * (k - 100)); 2317ccd5a2cSjsg a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100)); 2327ccd5a2cSjsg a = (a + 5) / 10; 2337ccd5a2cSjsg ah = ((a * t) + 5000) / 10000; 2347ccd5a2cSjsg al = a - ah; 2357ccd5a2cSjsg 2367ccd5a2cSjsg *th = t - ah; 2377ccd5a2cSjsg *tl = t + al; 2387ccd5a2cSjsg 2397ccd5a2cSjsg return 0; 2407ccd5a2cSjsg } 2417ccd5a2cSjsg 2427ccd5a2cSjsg void r600_gfx_clockgating_enable(struct radeon_device *rdev, bool enable) 2437ccd5a2cSjsg { 2447ccd5a2cSjsg int i; 2457ccd5a2cSjsg 2467ccd5a2cSjsg if (enable) { 2477ccd5a2cSjsg WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); 2487ccd5a2cSjsg } else { 2497ccd5a2cSjsg WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN); 2507ccd5a2cSjsg 2517ccd5a2cSjsg WREG32(CG_RLC_REQ_AND_RSP, 0x2); 2527ccd5a2cSjsg 2537ccd5a2cSjsg for (i = 0; i < rdev->usec_timeout; i++) { 2547ccd5a2cSjsg if (((RREG32(CG_RLC_REQ_AND_RSP) & CG_RLC_RSP_TYPE_MASK) >> CG_RLC_RSP_TYPE_SHIFT) == 1) 2557ccd5a2cSjsg break; 2567ccd5a2cSjsg udelay(1); 2577ccd5a2cSjsg } 2587ccd5a2cSjsg 2597ccd5a2cSjsg WREG32(CG_RLC_REQ_AND_RSP, 0x0); 2607ccd5a2cSjsg 2617ccd5a2cSjsg WREG32(GRBM_PWR_CNTL, 0x1); 2627ccd5a2cSjsg RREG32(GRBM_PWR_CNTL); 2637ccd5a2cSjsg } 2647ccd5a2cSjsg } 2657ccd5a2cSjsg 2667ccd5a2cSjsg void r600_dynamicpm_enable(struct radeon_device *rdev, bool enable) 2677ccd5a2cSjsg { 2687ccd5a2cSjsg if (enable) 2697ccd5a2cSjsg WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); 2707ccd5a2cSjsg else 2717ccd5a2cSjsg WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); 2727ccd5a2cSjsg } 2737ccd5a2cSjsg 2747ccd5a2cSjsg void r600_enable_thermal_protection(struct radeon_device *rdev, bool enable) 2757ccd5a2cSjsg { 2767ccd5a2cSjsg if (enable) 2777ccd5a2cSjsg WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); 2787ccd5a2cSjsg else 2797ccd5a2cSjsg WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); 2807ccd5a2cSjsg } 2817ccd5a2cSjsg 2827ccd5a2cSjsg void r600_enable_acpi_pm(struct radeon_device *rdev) 2837ccd5a2cSjsg { 2847ccd5a2cSjsg WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN); 2857ccd5a2cSjsg } 2867ccd5a2cSjsg 2877ccd5a2cSjsg void r600_enable_dynamic_pcie_gen2(struct radeon_device *rdev, bool enable) 2887ccd5a2cSjsg { 2897ccd5a2cSjsg if (enable) 2907ccd5a2cSjsg WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE); 2917ccd5a2cSjsg else 2927ccd5a2cSjsg WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE); 2937ccd5a2cSjsg } 2947ccd5a2cSjsg 2957ccd5a2cSjsg bool r600_dynamicpm_enabled(struct radeon_device *rdev) 2967ccd5a2cSjsg { 2977ccd5a2cSjsg if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN) 2987ccd5a2cSjsg return true; 2997ccd5a2cSjsg else 3007ccd5a2cSjsg return false; 3017ccd5a2cSjsg } 3027ccd5a2cSjsg 3037ccd5a2cSjsg void r600_enable_sclk_control(struct radeon_device *rdev, bool enable) 3047ccd5a2cSjsg { 3057ccd5a2cSjsg if (enable) 3067ccd5a2cSjsg WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); 3077ccd5a2cSjsg else 3087ccd5a2cSjsg WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); 3097ccd5a2cSjsg } 3107ccd5a2cSjsg 3117ccd5a2cSjsg void r600_enable_mclk_control(struct radeon_device *rdev, bool enable) 3127ccd5a2cSjsg { 3137ccd5a2cSjsg if (enable) 3147ccd5a2cSjsg WREG32_P(MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF); 3157ccd5a2cSjsg else 3167ccd5a2cSjsg WREG32_P(MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF); 3177ccd5a2cSjsg } 3187ccd5a2cSjsg 3197ccd5a2cSjsg void r600_enable_spll_bypass(struct radeon_device *rdev, bool enable) 3207ccd5a2cSjsg { 3217ccd5a2cSjsg if (enable) 3227ccd5a2cSjsg WREG32_P(CG_SPLL_FUNC_CNTL, SPLL_BYPASS_EN, ~SPLL_BYPASS_EN); 3237ccd5a2cSjsg else 3247ccd5a2cSjsg WREG32_P(CG_SPLL_FUNC_CNTL, 0, ~SPLL_BYPASS_EN); 3257ccd5a2cSjsg } 3267ccd5a2cSjsg 3277ccd5a2cSjsg void r600_wait_for_spll_change(struct radeon_device *rdev) 3287ccd5a2cSjsg { 3297ccd5a2cSjsg int i; 3307ccd5a2cSjsg 3317ccd5a2cSjsg for (i = 0; i < rdev->usec_timeout; i++) { 3327ccd5a2cSjsg if (RREG32(CG_SPLL_FUNC_CNTL) & SPLL_CHG_STATUS) 3337ccd5a2cSjsg break; 3347ccd5a2cSjsg udelay(1); 3357ccd5a2cSjsg } 3367ccd5a2cSjsg } 3377ccd5a2cSjsg 3387ccd5a2cSjsg void r600_set_bsp(struct radeon_device *rdev, u32 u, u32 p) 3397ccd5a2cSjsg { 3407ccd5a2cSjsg WREG32(CG_BSP, BSP(p) | BSU(u)); 3417ccd5a2cSjsg } 3427ccd5a2cSjsg 3437ccd5a2cSjsg void r600_set_at(struct radeon_device *rdev, 3447ccd5a2cSjsg u32 l_to_m, u32 m_to_h, 3457ccd5a2cSjsg u32 h_to_m, u32 m_to_l) 3467ccd5a2cSjsg { 3477ccd5a2cSjsg WREG32(CG_RT, FLS(l_to_m) | FMS(m_to_h)); 3487ccd5a2cSjsg WREG32(CG_LT, FHS(h_to_m) | FMS(m_to_l)); 3497ccd5a2cSjsg } 3507ccd5a2cSjsg 3517ccd5a2cSjsg void r600_set_tc(struct radeon_device *rdev, 3527ccd5a2cSjsg u32 index, u32 u_t, u32 d_t) 3537ccd5a2cSjsg { 3547ccd5a2cSjsg WREG32(CG_FFCT_0 + (index * 4), UTC_0(u_t) | DTC_0(d_t)); 3557ccd5a2cSjsg } 3567ccd5a2cSjsg 3577ccd5a2cSjsg void r600_select_td(struct radeon_device *rdev, 3587ccd5a2cSjsg enum r600_td td) 3597ccd5a2cSjsg { 3607ccd5a2cSjsg if (td == R600_TD_AUTO) 3617ccd5a2cSjsg WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL); 3627ccd5a2cSjsg else 3637ccd5a2cSjsg WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL); 3647ccd5a2cSjsg if (td == R600_TD_UP) 3657ccd5a2cSjsg WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE); 3667ccd5a2cSjsg if (td == R600_TD_DOWN) 3677ccd5a2cSjsg WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE); 3687ccd5a2cSjsg } 3697ccd5a2cSjsg 3707ccd5a2cSjsg void r600_set_vrc(struct radeon_device *rdev, u32 vrv) 3717ccd5a2cSjsg { 3727ccd5a2cSjsg WREG32(CG_FTV, vrv); 3737ccd5a2cSjsg } 3747ccd5a2cSjsg 3757ccd5a2cSjsg void r600_set_tpu(struct radeon_device *rdev, u32 u) 3767ccd5a2cSjsg { 3777ccd5a2cSjsg WREG32_P(CG_TPC, TPU(u), ~TPU_MASK); 3787ccd5a2cSjsg } 3797ccd5a2cSjsg 3807ccd5a2cSjsg void r600_set_tpc(struct radeon_device *rdev, u32 c) 3817ccd5a2cSjsg { 3827ccd5a2cSjsg WREG32_P(CG_TPC, TPCC(c), ~TPCC_MASK); 3837ccd5a2cSjsg } 3847ccd5a2cSjsg 3857ccd5a2cSjsg void r600_set_sstu(struct radeon_device *rdev, u32 u) 3867ccd5a2cSjsg { 3877ccd5a2cSjsg WREG32_P(CG_SSP, CG_SSTU(u), ~CG_SSTU_MASK); 3887ccd5a2cSjsg } 3897ccd5a2cSjsg 3907ccd5a2cSjsg void r600_set_sst(struct radeon_device *rdev, u32 t) 3917ccd5a2cSjsg { 3927ccd5a2cSjsg WREG32_P(CG_SSP, CG_SST(t), ~CG_SST_MASK); 3937ccd5a2cSjsg } 3947ccd5a2cSjsg 3957ccd5a2cSjsg void r600_set_git(struct radeon_device *rdev, u32 t) 3967ccd5a2cSjsg { 3977ccd5a2cSjsg WREG32_P(CG_GIT, CG_GICST(t), ~CG_GICST_MASK); 3987ccd5a2cSjsg } 3997ccd5a2cSjsg 4007ccd5a2cSjsg void r600_set_fctu(struct radeon_device *rdev, u32 u) 4017ccd5a2cSjsg { 4027ccd5a2cSjsg WREG32_P(CG_FC_T, FC_TU(u), ~FC_TU_MASK); 4037ccd5a2cSjsg } 4047ccd5a2cSjsg 4057ccd5a2cSjsg void r600_set_fct(struct radeon_device *rdev, u32 t) 4067ccd5a2cSjsg { 4077ccd5a2cSjsg WREG32_P(CG_FC_T, FC_T(t), ~FC_T_MASK); 4087ccd5a2cSjsg } 4097ccd5a2cSjsg 4107ccd5a2cSjsg void r600_set_ctxcgtt3d_rphc(struct radeon_device *rdev, u32 p) 4117ccd5a2cSjsg { 4127ccd5a2cSjsg WREG32_P(CG_CTX_CGTT3D_R, PHC(p), ~PHC_MASK); 4137ccd5a2cSjsg } 4147ccd5a2cSjsg 4157ccd5a2cSjsg void r600_set_ctxcgtt3d_rsdc(struct radeon_device *rdev, u32 s) 4167ccd5a2cSjsg { 4177ccd5a2cSjsg WREG32_P(CG_CTX_CGTT3D_R, SDC(s), ~SDC_MASK); 4187ccd5a2cSjsg } 4197ccd5a2cSjsg 4207ccd5a2cSjsg void r600_set_vddc3d_oorsu(struct radeon_device *rdev, u32 u) 4217ccd5a2cSjsg { 4227ccd5a2cSjsg WREG32_P(CG_VDDC3D_OOR, SU(u), ~SU_MASK); 4237ccd5a2cSjsg } 4247ccd5a2cSjsg 4257ccd5a2cSjsg void r600_set_vddc3d_oorphc(struct radeon_device *rdev, u32 p) 4267ccd5a2cSjsg { 4277ccd5a2cSjsg WREG32_P(CG_VDDC3D_OOR, PHC(p), ~PHC_MASK); 4287ccd5a2cSjsg } 4297ccd5a2cSjsg 4307ccd5a2cSjsg void r600_set_vddc3d_oorsdc(struct radeon_device *rdev, u32 s) 4317ccd5a2cSjsg { 4327ccd5a2cSjsg WREG32_P(CG_VDDC3D_OOR, SDC(s), ~SDC_MASK); 4337ccd5a2cSjsg } 4347ccd5a2cSjsg 4357ccd5a2cSjsg void r600_set_mpll_lock_time(struct radeon_device *rdev, u32 lock_time) 4367ccd5a2cSjsg { 4377ccd5a2cSjsg WREG32_P(MPLL_TIME, MPLL_LOCK_TIME(lock_time), ~MPLL_LOCK_TIME_MASK); 4387ccd5a2cSjsg } 4397ccd5a2cSjsg 4407ccd5a2cSjsg void r600_set_mpll_reset_time(struct radeon_device *rdev, u32 reset_time) 4417ccd5a2cSjsg { 4427ccd5a2cSjsg WREG32_P(MPLL_TIME, MPLL_RESET_TIME(reset_time), ~MPLL_RESET_TIME_MASK); 4437ccd5a2cSjsg } 4447ccd5a2cSjsg 4457ccd5a2cSjsg void r600_engine_clock_entry_enable(struct radeon_device *rdev, 4467ccd5a2cSjsg u32 index, bool enable) 4477ccd5a2cSjsg { 4487ccd5a2cSjsg if (enable) 4497ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4507ccd5a2cSjsg STEP_0_SPLL_ENTRY_VALID, ~STEP_0_SPLL_ENTRY_VALID); 4517ccd5a2cSjsg else 4527ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4537ccd5a2cSjsg 0, ~STEP_0_SPLL_ENTRY_VALID); 4547ccd5a2cSjsg } 4557ccd5a2cSjsg 4567ccd5a2cSjsg void r600_engine_clock_entry_enable_pulse_skipping(struct radeon_device *rdev, 4577ccd5a2cSjsg u32 index, bool enable) 4587ccd5a2cSjsg { 4597ccd5a2cSjsg if (enable) 4607ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4617ccd5a2cSjsg STEP_0_SPLL_STEP_ENABLE, ~STEP_0_SPLL_STEP_ENABLE); 4627ccd5a2cSjsg else 4637ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4647ccd5a2cSjsg 0, ~STEP_0_SPLL_STEP_ENABLE); 4657ccd5a2cSjsg } 4667ccd5a2cSjsg 4677ccd5a2cSjsg void r600_engine_clock_entry_enable_post_divider(struct radeon_device *rdev, 4687ccd5a2cSjsg u32 index, bool enable) 4697ccd5a2cSjsg { 4707ccd5a2cSjsg if (enable) 4717ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4727ccd5a2cSjsg STEP_0_POST_DIV_EN, ~STEP_0_POST_DIV_EN); 4737ccd5a2cSjsg else 4747ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2), 4757ccd5a2cSjsg 0, ~STEP_0_POST_DIV_EN); 4767ccd5a2cSjsg } 4777ccd5a2cSjsg 4787ccd5a2cSjsg void r600_engine_clock_entry_set_post_divider(struct radeon_device *rdev, 4797ccd5a2cSjsg u32 index, u32 divider) 4807ccd5a2cSjsg { 4817ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2), 4827ccd5a2cSjsg STEP_0_SPLL_POST_DIV(divider), ~STEP_0_SPLL_POST_DIV_MASK); 4837ccd5a2cSjsg } 4847ccd5a2cSjsg 4857ccd5a2cSjsg void r600_engine_clock_entry_set_reference_divider(struct radeon_device *rdev, 4867ccd5a2cSjsg u32 index, u32 divider) 4877ccd5a2cSjsg { 4887ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2), 4897ccd5a2cSjsg STEP_0_SPLL_REF_DIV(divider), ~STEP_0_SPLL_REF_DIV_MASK); 4907ccd5a2cSjsg } 4917ccd5a2cSjsg 4927ccd5a2cSjsg void r600_engine_clock_entry_set_feedback_divider(struct radeon_device *rdev, 4937ccd5a2cSjsg u32 index, u32 divider) 4947ccd5a2cSjsg { 4957ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2), 4967ccd5a2cSjsg STEP_0_SPLL_FB_DIV(divider), ~STEP_0_SPLL_FB_DIV_MASK); 4977ccd5a2cSjsg } 4987ccd5a2cSjsg 4997ccd5a2cSjsg void r600_engine_clock_entry_set_step_time(struct radeon_device *rdev, 5007ccd5a2cSjsg u32 index, u32 step_time) 5017ccd5a2cSjsg { 5027ccd5a2cSjsg WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2), 5037ccd5a2cSjsg STEP_0_SPLL_STEP_TIME(step_time), ~STEP_0_SPLL_STEP_TIME_MASK); 5047ccd5a2cSjsg } 5057ccd5a2cSjsg 5067ccd5a2cSjsg void r600_vid_rt_set_ssu(struct radeon_device *rdev, u32 u) 5077ccd5a2cSjsg { 5087ccd5a2cSjsg WREG32_P(VID_RT, SSTU(u), ~SSTU_MASK); 5097ccd5a2cSjsg } 5107ccd5a2cSjsg 5117ccd5a2cSjsg void r600_vid_rt_set_vru(struct radeon_device *rdev, u32 u) 5127ccd5a2cSjsg { 5137ccd5a2cSjsg WREG32_P(VID_RT, VID_CRTU(u), ~VID_CRTU_MASK); 5147ccd5a2cSjsg } 5157ccd5a2cSjsg 5167ccd5a2cSjsg void r600_vid_rt_set_vrt(struct radeon_device *rdev, u32 rt) 5177ccd5a2cSjsg { 5187ccd5a2cSjsg WREG32_P(VID_RT, VID_CRT(rt), ~VID_CRT_MASK); 5197ccd5a2cSjsg } 5207ccd5a2cSjsg 5217ccd5a2cSjsg void r600_voltage_control_enable_pins(struct radeon_device *rdev, 5227ccd5a2cSjsg u64 mask) 5237ccd5a2cSjsg { 5247ccd5a2cSjsg WREG32(LOWER_GPIO_ENABLE, mask & 0xffffffff); 5257ccd5a2cSjsg WREG32(UPPER_GPIO_ENABLE, upper_32_bits(mask)); 5267ccd5a2cSjsg } 5277ccd5a2cSjsg 5287ccd5a2cSjsg 5297ccd5a2cSjsg void r600_voltage_control_program_voltages(struct radeon_device *rdev, 5307ccd5a2cSjsg enum r600_power_level index, u64 pins) 5317ccd5a2cSjsg { 5327ccd5a2cSjsg u32 tmp, mask; 5337ccd5a2cSjsg u32 ix = 3 - (3 & index); 5347ccd5a2cSjsg 5357ccd5a2cSjsg WREG32(CTXSW_VID_LOWER_GPIO_CNTL + (ix * 4), pins & 0xffffffff); 5367ccd5a2cSjsg 5377ccd5a2cSjsg mask = 7 << (3 * ix); 5387ccd5a2cSjsg tmp = RREG32(VID_UPPER_GPIO_CNTL); 5397ccd5a2cSjsg tmp = (tmp & ~mask) | ((pins >> (32 - (3 * ix))) & mask); 5407ccd5a2cSjsg WREG32(VID_UPPER_GPIO_CNTL, tmp); 5417ccd5a2cSjsg } 5427ccd5a2cSjsg 5437ccd5a2cSjsg void r600_voltage_control_deactivate_static_control(struct radeon_device *rdev, 5447ccd5a2cSjsg u64 mask) 5457ccd5a2cSjsg { 5467ccd5a2cSjsg u32 gpio; 5477ccd5a2cSjsg 5487ccd5a2cSjsg gpio = RREG32(GPIOPAD_MASK); 5497ccd5a2cSjsg gpio &= ~mask; 5507ccd5a2cSjsg WREG32(GPIOPAD_MASK, gpio); 5517ccd5a2cSjsg 5527ccd5a2cSjsg gpio = RREG32(GPIOPAD_EN); 5537ccd5a2cSjsg gpio &= ~mask; 5547ccd5a2cSjsg WREG32(GPIOPAD_EN, gpio); 5557ccd5a2cSjsg 5567ccd5a2cSjsg gpio = RREG32(GPIOPAD_A); 5577ccd5a2cSjsg gpio &= ~mask; 5587ccd5a2cSjsg WREG32(GPIOPAD_A, gpio); 5597ccd5a2cSjsg } 5607ccd5a2cSjsg 5617ccd5a2cSjsg void r600_power_level_enable(struct radeon_device *rdev, 5627ccd5a2cSjsg enum r600_power_level index, bool enable) 5637ccd5a2cSjsg { 5647ccd5a2cSjsg u32 ix = 3 - (3 & index); 5657ccd5a2cSjsg 5667ccd5a2cSjsg if (enable) 5677ccd5a2cSjsg WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), CTXSW_FREQ_STATE_ENABLE, 5687ccd5a2cSjsg ~CTXSW_FREQ_STATE_ENABLE); 5697ccd5a2cSjsg else 5707ccd5a2cSjsg WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 0, 5717ccd5a2cSjsg ~CTXSW_FREQ_STATE_ENABLE); 5727ccd5a2cSjsg } 5737ccd5a2cSjsg 5747ccd5a2cSjsg void r600_power_level_set_voltage_index(struct radeon_device *rdev, 5757ccd5a2cSjsg enum r600_power_level index, u32 voltage_index) 5767ccd5a2cSjsg { 5777ccd5a2cSjsg u32 ix = 3 - (3 & index); 5787ccd5a2cSjsg 5797ccd5a2cSjsg WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 5807ccd5a2cSjsg CTXSW_FREQ_VIDS_CFG_INDEX(voltage_index), ~CTXSW_FREQ_VIDS_CFG_INDEX_MASK); 5817ccd5a2cSjsg } 5827ccd5a2cSjsg 5837ccd5a2cSjsg void r600_power_level_set_mem_clock_index(struct radeon_device *rdev, 5847ccd5a2cSjsg enum r600_power_level index, u32 mem_clock_index) 5857ccd5a2cSjsg { 5867ccd5a2cSjsg u32 ix = 3 - (3 & index); 5877ccd5a2cSjsg 5887ccd5a2cSjsg WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 5897ccd5a2cSjsg CTXSW_FREQ_MCLK_CFG_INDEX(mem_clock_index), ~CTXSW_FREQ_MCLK_CFG_INDEX_MASK); 5907ccd5a2cSjsg } 5917ccd5a2cSjsg 5927ccd5a2cSjsg void r600_power_level_set_eng_clock_index(struct radeon_device *rdev, 5937ccd5a2cSjsg enum r600_power_level index, u32 eng_clock_index) 5947ccd5a2cSjsg { 5957ccd5a2cSjsg u32 ix = 3 - (3 & index); 5967ccd5a2cSjsg 5977ccd5a2cSjsg WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 5987ccd5a2cSjsg CTXSW_FREQ_SCLK_CFG_INDEX(eng_clock_index), ~CTXSW_FREQ_SCLK_CFG_INDEX_MASK); 5997ccd5a2cSjsg } 6007ccd5a2cSjsg 6017ccd5a2cSjsg void r600_power_level_set_watermark_id(struct radeon_device *rdev, 6027ccd5a2cSjsg enum r600_power_level index, 6037ccd5a2cSjsg enum r600_display_watermark watermark_id) 6047ccd5a2cSjsg { 6057ccd5a2cSjsg u32 ix = 3 - (3 & index); 6067ccd5a2cSjsg u32 tmp = 0; 6077ccd5a2cSjsg 6087ccd5a2cSjsg if (watermark_id == R600_DISPLAY_WATERMARK_HIGH) 6097ccd5a2cSjsg tmp = CTXSW_FREQ_DISPLAY_WATERMARK; 6107ccd5a2cSjsg WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), tmp, ~CTXSW_FREQ_DISPLAY_WATERMARK); 6117ccd5a2cSjsg } 6127ccd5a2cSjsg 6137ccd5a2cSjsg void r600_power_level_set_pcie_gen2(struct radeon_device *rdev, 6147ccd5a2cSjsg enum r600_power_level index, bool compatible) 6157ccd5a2cSjsg { 6167ccd5a2cSjsg u32 ix = 3 - (3 & index); 6177ccd5a2cSjsg u32 tmp = 0; 6187ccd5a2cSjsg 6197ccd5a2cSjsg if (compatible) 6207ccd5a2cSjsg tmp = CTXSW_FREQ_GEN2PCIE_VOLT; 6217ccd5a2cSjsg WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), tmp, ~CTXSW_FREQ_GEN2PCIE_VOLT); 6227ccd5a2cSjsg } 6237ccd5a2cSjsg 6247ccd5a2cSjsg enum r600_power_level r600_power_level_get_current_index(struct radeon_device *rdev) 6257ccd5a2cSjsg { 6267ccd5a2cSjsg u32 tmp; 6277ccd5a2cSjsg 6287ccd5a2cSjsg tmp = RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK; 6297ccd5a2cSjsg tmp >>= CURRENT_PROFILE_INDEX_SHIFT; 6307ccd5a2cSjsg return tmp; 6317ccd5a2cSjsg } 6327ccd5a2cSjsg 6337ccd5a2cSjsg enum r600_power_level r600_power_level_get_target_index(struct radeon_device *rdev) 6347ccd5a2cSjsg { 6357ccd5a2cSjsg u32 tmp; 6367ccd5a2cSjsg 6377ccd5a2cSjsg tmp = RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_PROFILE_INDEX_MASK; 6387ccd5a2cSjsg tmp >>= TARGET_PROFILE_INDEX_SHIFT; 6397ccd5a2cSjsg return tmp; 6407ccd5a2cSjsg } 6417ccd5a2cSjsg 6427ccd5a2cSjsg void r600_power_level_set_enter_index(struct radeon_device *rdev, 6437ccd5a2cSjsg enum r600_power_level index) 6447ccd5a2cSjsg { 6457ccd5a2cSjsg WREG32_P(TARGET_AND_CURRENT_PROFILE_INDEX, DYN_PWR_ENTER_INDEX(index), 6467ccd5a2cSjsg ~DYN_PWR_ENTER_INDEX_MASK); 6477ccd5a2cSjsg } 6487ccd5a2cSjsg 6497ccd5a2cSjsg void r600_wait_for_power_level_unequal(struct radeon_device *rdev, 6507ccd5a2cSjsg enum r600_power_level index) 6517ccd5a2cSjsg { 6527ccd5a2cSjsg int i; 6537ccd5a2cSjsg 6547ccd5a2cSjsg for (i = 0; i < rdev->usec_timeout; i++) { 6557ccd5a2cSjsg if (r600_power_level_get_target_index(rdev) != index) 6567ccd5a2cSjsg break; 6577ccd5a2cSjsg udelay(1); 6587ccd5a2cSjsg } 6597ccd5a2cSjsg 6607ccd5a2cSjsg for (i = 0; i < rdev->usec_timeout; i++) { 6617ccd5a2cSjsg if (r600_power_level_get_current_index(rdev) != index) 6627ccd5a2cSjsg break; 6637ccd5a2cSjsg udelay(1); 6647ccd5a2cSjsg } 6657ccd5a2cSjsg } 6667ccd5a2cSjsg 6677ccd5a2cSjsg void r600_wait_for_power_level(struct radeon_device *rdev, 6687ccd5a2cSjsg enum r600_power_level index) 6697ccd5a2cSjsg { 6707ccd5a2cSjsg int i; 6717ccd5a2cSjsg 6727ccd5a2cSjsg for (i = 0; i < rdev->usec_timeout; i++) { 6737ccd5a2cSjsg if (r600_power_level_get_target_index(rdev) == index) 6747ccd5a2cSjsg break; 6757ccd5a2cSjsg udelay(1); 6767ccd5a2cSjsg } 6777ccd5a2cSjsg 6787ccd5a2cSjsg for (i = 0; i < rdev->usec_timeout; i++) { 6797ccd5a2cSjsg if (r600_power_level_get_current_index(rdev) == index) 6807ccd5a2cSjsg break; 6817ccd5a2cSjsg udelay(1); 6827ccd5a2cSjsg } 6837ccd5a2cSjsg } 6847ccd5a2cSjsg 6857ccd5a2cSjsg void r600_start_dpm(struct radeon_device *rdev) 6867ccd5a2cSjsg { 6877ccd5a2cSjsg r600_enable_sclk_control(rdev, false); 6887ccd5a2cSjsg r600_enable_mclk_control(rdev, false); 6897ccd5a2cSjsg 6907ccd5a2cSjsg r600_dynamicpm_enable(rdev, true); 6917ccd5a2cSjsg 6927ccd5a2cSjsg radeon_wait_for_vblank(rdev, 0); 6937ccd5a2cSjsg radeon_wait_for_vblank(rdev, 1); 6947ccd5a2cSjsg 6957ccd5a2cSjsg r600_enable_spll_bypass(rdev, true); 6967ccd5a2cSjsg r600_wait_for_spll_change(rdev); 6977ccd5a2cSjsg r600_enable_spll_bypass(rdev, false); 6987ccd5a2cSjsg r600_wait_for_spll_change(rdev); 6997ccd5a2cSjsg 7007ccd5a2cSjsg r600_enable_spll_bypass(rdev, true); 7017ccd5a2cSjsg r600_wait_for_spll_change(rdev); 7027ccd5a2cSjsg r600_enable_spll_bypass(rdev, false); 7037ccd5a2cSjsg r600_wait_for_spll_change(rdev); 7047ccd5a2cSjsg 7057ccd5a2cSjsg r600_enable_sclk_control(rdev, true); 7067ccd5a2cSjsg r600_enable_mclk_control(rdev, true); 7077ccd5a2cSjsg } 7087ccd5a2cSjsg 7097ccd5a2cSjsg void r600_stop_dpm(struct radeon_device *rdev) 7107ccd5a2cSjsg { 7117ccd5a2cSjsg r600_dynamicpm_enable(rdev, false); 7127ccd5a2cSjsg } 7137ccd5a2cSjsg 7147ccd5a2cSjsg int r600_dpm_pre_set_power_state(struct radeon_device *rdev) 7157ccd5a2cSjsg { 7167ccd5a2cSjsg return 0; 7177ccd5a2cSjsg } 7187ccd5a2cSjsg 7197ccd5a2cSjsg void r600_dpm_post_set_power_state(struct radeon_device *rdev) 7207ccd5a2cSjsg { 7217ccd5a2cSjsg 7227ccd5a2cSjsg } 7237ccd5a2cSjsg 7247ccd5a2cSjsg bool r600_is_uvd_state(u32 class, u32 class2) 7257ccd5a2cSjsg { 7267ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 7277ccd5a2cSjsg return true; 7287ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 7297ccd5a2cSjsg return true; 7307ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 7317ccd5a2cSjsg return true; 7327ccd5a2cSjsg if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 7337ccd5a2cSjsg return true; 7347ccd5a2cSjsg if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 7357ccd5a2cSjsg return true; 7367ccd5a2cSjsg return false; 7377ccd5a2cSjsg } 7387ccd5a2cSjsg 7397ccd5a2cSjsg static int r600_set_thermal_temperature_range(struct radeon_device *rdev, 7407ccd5a2cSjsg int min_temp, int max_temp) 7417ccd5a2cSjsg { 7427ccd5a2cSjsg int low_temp = 0 * 1000; 7437ccd5a2cSjsg int high_temp = 255 * 1000; 7447ccd5a2cSjsg 7457ccd5a2cSjsg if (low_temp < min_temp) 7467ccd5a2cSjsg low_temp = min_temp; 7477ccd5a2cSjsg if (high_temp > max_temp) 7487ccd5a2cSjsg high_temp = max_temp; 7497ccd5a2cSjsg if (high_temp < low_temp) { 7507ccd5a2cSjsg DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); 7517ccd5a2cSjsg return -EINVAL; 7527ccd5a2cSjsg } 7537ccd5a2cSjsg 7547ccd5a2cSjsg WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK); 7557ccd5a2cSjsg WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK); 7567ccd5a2cSjsg WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK); 7577ccd5a2cSjsg 7587ccd5a2cSjsg rdev->pm.dpm.thermal.min_temp = low_temp; 7597ccd5a2cSjsg rdev->pm.dpm.thermal.max_temp = high_temp; 7607ccd5a2cSjsg 7617ccd5a2cSjsg return 0; 7627ccd5a2cSjsg } 7637ccd5a2cSjsg 7647ccd5a2cSjsg bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor) 7657ccd5a2cSjsg { 7667ccd5a2cSjsg switch (sensor) { 7677ccd5a2cSjsg case THERMAL_TYPE_RV6XX: 7687ccd5a2cSjsg case THERMAL_TYPE_RV770: 7697ccd5a2cSjsg case THERMAL_TYPE_EVERGREEN: 7707ccd5a2cSjsg case THERMAL_TYPE_SUMO: 7717ccd5a2cSjsg case THERMAL_TYPE_NI: 7727ccd5a2cSjsg case THERMAL_TYPE_SI: 7737ccd5a2cSjsg case THERMAL_TYPE_CI: 7747ccd5a2cSjsg case THERMAL_TYPE_KV: 7757ccd5a2cSjsg return true; 7767ccd5a2cSjsg case THERMAL_TYPE_ADT7473_WITH_INTERNAL: 7777ccd5a2cSjsg case THERMAL_TYPE_EMC2103_WITH_INTERNAL: 7787ccd5a2cSjsg return false; /* need special handling */ 7797ccd5a2cSjsg case THERMAL_TYPE_NONE: 7807ccd5a2cSjsg case THERMAL_TYPE_EXTERNAL: 7817ccd5a2cSjsg case THERMAL_TYPE_EXTERNAL_GPIO: 7827ccd5a2cSjsg default: 7837ccd5a2cSjsg return false; 7847ccd5a2cSjsg } 7857ccd5a2cSjsg } 7867ccd5a2cSjsg 7877ccd5a2cSjsg int r600_dpm_late_enable(struct radeon_device *rdev) 7887ccd5a2cSjsg { 7897ccd5a2cSjsg int ret; 7907ccd5a2cSjsg 7917ccd5a2cSjsg if (rdev->irq.installed && 7927ccd5a2cSjsg r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 7937ccd5a2cSjsg ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); 7947ccd5a2cSjsg if (ret) 7957ccd5a2cSjsg return ret; 7967ccd5a2cSjsg rdev->irq.dpm_thermal = true; 7977ccd5a2cSjsg radeon_irq_set(rdev); 7987ccd5a2cSjsg } 7997ccd5a2cSjsg 8007ccd5a2cSjsg return 0; 8017ccd5a2cSjsg } 8027ccd5a2cSjsg 8037ccd5a2cSjsg union power_info { 8047ccd5a2cSjsg struct _ATOM_POWERPLAY_INFO info; 8057ccd5a2cSjsg struct _ATOM_POWERPLAY_INFO_V2 info_2; 8067ccd5a2cSjsg struct _ATOM_POWERPLAY_INFO_V3 info_3; 8077ccd5a2cSjsg struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 8087ccd5a2cSjsg struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 8097ccd5a2cSjsg struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 8107ccd5a2cSjsg struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; 8117ccd5a2cSjsg struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; 8127ccd5a2cSjsg }; 8137ccd5a2cSjsg 8147ccd5a2cSjsg union fan_info { 8157ccd5a2cSjsg struct _ATOM_PPLIB_FANTABLE fan; 8167ccd5a2cSjsg struct _ATOM_PPLIB_FANTABLE2 fan2; 8177ccd5a2cSjsg struct _ATOM_PPLIB_FANTABLE3 fan3; 8187ccd5a2cSjsg }; 8197ccd5a2cSjsg 8207ccd5a2cSjsg static int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependency_table *radeon_table, 8217ccd5a2cSjsg ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) 8227ccd5a2cSjsg { 8237ccd5a2cSjsg int i; 8247ccd5a2cSjsg ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; 8257ccd5a2cSjsg 8261bb76ff1Sjsg radeon_table->entries = kcalloc(atom_table->ucNumEntries, 8271bb76ff1Sjsg sizeof(struct radeon_clock_voltage_dependency_entry), 8281bb76ff1Sjsg GFP_KERNEL); 8297ccd5a2cSjsg if (!radeon_table->entries) 8307ccd5a2cSjsg return -ENOMEM; 8317ccd5a2cSjsg 8327ccd5a2cSjsg entry = &atom_table->entries[0]; 8337ccd5a2cSjsg for (i = 0; i < atom_table->ucNumEntries; i++) { 8347ccd5a2cSjsg radeon_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | 8357ccd5a2cSjsg (entry->ucClockHigh << 16); 8367ccd5a2cSjsg radeon_table->entries[i].v = le16_to_cpu(entry->usVoltage); 8377ccd5a2cSjsg entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) 8387ccd5a2cSjsg ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); 8397ccd5a2cSjsg } 8407ccd5a2cSjsg radeon_table->count = atom_table->ucNumEntries; 8417ccd5a2cSjsg 8427ccd5a2cSjsg return 0; 8437ccd5a2cSjsg } 8447ccd5a2cSjsg 8457ccd5a2cSjsg int r600_get_platform_caps(struct radeon_device *rdev) 8467ccd5a2cSjsg { 8477ccd5a2cSjsg struct radeon_mode_info *mode_info = &rdev->mode_info; 8487ccd5a2cSjsg union power_info *power_info; 8497ccd5a2cSjsg int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 8507ccd5a2cSjsg u16 data_offset; 8517ccd5a2cSjsg u8 frev, crev; 8527ccd5a2cSjsg 8537ccd5a2cSjsg if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 8547ccd5a2cSjsg &frev, &crev, &data_offset)) 8557ccd5a2cSjsg return -EINVAL; 8567ccd5a2cSjsg power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 8577ccd5a2cSjsg 8587ccd5a2cSjsg rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); 8597ccd5a2cSjsg rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); 8607ccd5a2cSjsg rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); 8617ccd5a2cSjsg 8627ccd5a2cSjsg return 0; 8637ccd5a2cSjsg } 8647ccd5a2cSjsg 8657ccd5a2cSjsg /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ 8667ccd5a2cSjsg #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 8677ccd5a2cSjsg #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 8687ccd5a2cSjsg #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 8697ccd5a2cSjsg #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 8707ccd5a2cSjsg #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 8717ccd5a2cSjsg #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 8727ccd5a2cSjsg 8737ccd5a2cSjsg int r600_parse_extended_power_table(struct radeon_device *rdev) 8747ccd5a2cSjsg { 8757ccd5a2cSjsg struct radeon_mode_info *mode_info = &rdev->mode_info; 8767ccd5a2cSjsg union power_info *power_info; 8777ccd5a2cSjsg union fan_info *fan_info; 8787ccd5a2cSjsg ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; 8797ccd5a2cSjsg int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 8807ccd5a2cSjsg u16 data_offset; 8817ccd5a2cSjsg u8 frev, crev; 8827ccd5a2cSjsg int ret, i; 8837ccd5a2cSjsg 8847ccd5a2cSjsg if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 8857ccd5a2cSjsg &frev, &crev, &data_offset)) 8867ccd5a2cSjsg return -EINVAL; 8877ccd5a2cSjsg power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 8887ccd5a2cSjsg 8897ccd5a2cSjsg /* fan table */ 8907ccd5a2cSjsg if (le16_to_cpu(power_info->pplib.usTableSize) >= 8917ccd5a2cSjsg sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 8927ccd5a2cSjsg if (power_info->pplib3.usFanTableOffset) { 8937ccd5a2cSjsg fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + 8947ccd5a2cSjsg le16_to_cpu(power_info->pplib3.usFanTableOffset)); 8957ccd5a2cSjsg rdev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; 8967ccd5a2cSjsg rdev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); 8977ccd5a2cSjsg rdev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); 8987ccd5a2cSjsg rdev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); 8997ccd5a2cSjsg rdev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); 9007ccd5a2cSjsg rdev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); 9017ccd5a2cSjsg rdev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); 9027ccd5a2cSjsg if (fan_info->fan.ucFanTableFormat >= 2) 9037ccd5a2cSjsg rdev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); 9047ccd5a2cSjsg else 9057ccd5a2cSjsg rdev->pm.dpm.fan.t_max = 10900; 9067ccd5a2cSjsg rdev->pm.dpm.fan.cycle_delay = 100000; 9077ccd5a2cSjsg if (fan_info->fan.ucFanTableFormat >= 3) { 9087ccd5a2cSjsg rdev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; 9097ccd5a2cSjsg rdev->pm.dpm.fan.default_max_fan_pwm = 9107ccd5a2cSjsg le16_to_cpu(fan_info->fan3.usFanPWMMax); 9117ccd5a2cSjsg rdev->pm.dpm.fan.default_fan_output_sensitivity = 4836; 9127ccd5a2cSjsg rdev->pm.dpm.fan.fan_output_sensitivity = 9137ccd5a2cSjsg le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); 9147ccd5a2cSjsg } 9157ccd5a2cSjsg rdev->pm.dpm.fan.ucode_fan_control = true; 9167ccd5a2cSjsg } 9177ccd5a2cSjsg } 9187ccd5a2cSjsg 9197ccd5a2cSjsg /* clock dependancy tables, shedding tables */ 9207ccd5a2cSjsg if (le16_to_cpu(power_info->pplib.usTableSize) >= 9217ccd5a2cSjsg sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { 9227ccd5a2cSjsg if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { 9237ccd5a2cSjsg dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 9247ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 9257ccd5a2cSjsg le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); 9267ccd5a2cSjsg ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, 9277ccd5a2cSjsg dep_table); 9287ccd5a2cSjsg if (ret) 9297ccd5a2cSjsg return ret; 9307ccd5a2cSjsg } 9317ccd5a2cSjsg if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { 9327ccd5a2cSjsg dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 9337ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 9347ccd5a2cSjsg le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); 9357ccd5a2cSjsg ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk, 9367ccd5a2cSjsg dep_table); 9377ccd5a2cSjsg if (ret) { 9387ccd5a2cSjsg kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); 9397ccd5a2cSjsg return ret; 9407ccd5a2cSjsg } 9417ccd5a2cSjsg } 9427ccd5a2cSjsg if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { 9437ccd5a2cSjsg dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 9447ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 9457ccd5a2cSjsg le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); 9467ccd5a2cSjsg ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, 9477ccd5a2cSjsg dep_table); 9487ccd5a2cSjsg if (ret) { 9497ccd5a2cSjsg kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); 9507ccd5a2cSjsg kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); 9517ccd5a2cSjsg return ret; 9527ccd5a2cSjsg } 9537ccd5a2cSjsg } 9547ccd5a2cSjsg if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { 9557ccd5a2cSjsg dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 9567ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 9577ccd5a2cSjsg le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); 9587ccd5a2cSjsg ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, 9597ccd5a2cSjsg dep_table); 9607ccd5a2cSjsg if (ret) { 9617ccd5a2cSjsg kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); 9627ccd5a2cSjsg kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); 9637ccd5a2cSjsg kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); 9647ccd5a2cSjsg return ret; 9657ccd5a2cSjsg } 9667ccd5a2cSjsg } 9677ccd5a2cSjsg if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { 9687ccd5a2cSjsg ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = 9697ccd5a2cSjsg (ATOM_PPLIB_Clock_Voltage_Limit_Table *) 9707ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 9717ccd5a2cSjsg le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); 9727ccd5a2cSjsg if (clk_v->ucNumEntries) { 9737ccd5a2cSjsg rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = 9747ccd5a2cSjsg le16_to_cpu(clk_v->entries[0].usSclkLow) | 9757ccd5a2cSjsg (clk_v->entries[0].ucSclkHigh << 16); 9767ccd5a2cSjsg rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = 9777ccd5a2cSjsg le16_to_cpu(clk_v->entries[0].usMclkLow) | 9787ccd5a2cSjsg (clk_v->entries[0].ucMclkHigh << 16); 9797ccd5a2cSjsg rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = 9807ccd5a2cSjsg le16_to_cpu(clk_v->entries[0].usVddc); 9817ccd5a2cSjsg rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = 9827ccd5a2cSjsg le16_to_cpu(clk_v->entries[0].usVddci); 9837ccd5a2cSjsg } 9847ccd5a2cSjsg } 9857ccd5a2cSjsg if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { 9867ccd5a2cSjsg ATOM_PPLIB_PhaseSheddingLimits_Table *psl = 9877ccd5a2cSjsg (ATOM_PPLIB_PhaseSheddingLimits_Table *) 9887ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 9897ccd5a2cSjsg le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); 9907ccd5a2cSjsg ATOM_PPLIB_PhaseSheddingLimits_Record *entry; 9917ccd5a2cSjsg 9927ccd5a2cSjsg rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = 9937f4dd379Sjsg kcalloc(psl->ucNumEntries, 9947ccd5a2cSjsg sizeof(struct radeon_phase_shedding_limits_entry), 9957ccd5a2cSjsg GFP_KERNEL); 9967ccd5a2cSjsg if (!rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { 9977ccd5a2cSjsg r600_free_extended_power_table(rdev); 9987ccd5a2cSjsg return -ENOMEM; 9997ccd5a2cSjsg } 10007ccd5a2cSjsg 10017ccd5a2cSjsg entry = &psl->entries[0]; 10027ccd5a2cSjsg for (i = 0; i < psl->ucNumEntries; i++) { 10037ccd5a2cSjsg rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = 10047ccd5a2cSjsg le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); 10057ccd5a2cSjsg rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = 10067ccd5a2cSjsg le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); 10077ccd5a2cSjsg rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = 10087ccd5a2cSjsg le16_to_cpu(entry->usVoltage); 10097ccd5a2cSjsg entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) 10107ccd5a2cSjsg ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); 10117ccd5a2cSjsg } 10127ccd5a2cSjsg rdev->pm.dpm.dyn_state.phase_shedding_limits_table.count = 10137ccd5a2cSjsg psl->ucNumEntries; 10147ccd5a2cSjsg } 10157ccd5a2cSjsg } 10167ccd5a2cSjsg 10177ccd5a2cSjsg /* cac data */ 10187ccd5a2cSjsg if (le16_to_cpu(power_info->pplib.usTableSize) >= 10197ccd5a2cSjsg sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { 10207ccd5a2cSjsg rdev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); 10217ccd5a2cSjsg rdev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); 10227ccd5a2cSjsg rdev->pm.dpm.near_tdp_limit_adjusted = rdev->pm.dpm.near_tdp_limit; 10237ccd5a2cSjsg rdev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); 10247ccd5a2cSjsg if (rdev->pm.dpm.tdp_od_limit) 10257ccd5a2cSjsg rdev->pm.dpm.power_control = true; 10267ccd5a2cSjsg else 10277ccd5a2cSjsg rdev->pm.dpm.power_control = false; 10287ccd5a2cSjsg rdev->pm.dpm.tdp_adjustment = 0; 10297ccd5a2cSjsg rdev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); 10307ccd5a2cSjsg rdev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); 10317ccd5a2cSjsg rdev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); 10327ccd5a2cSjsg if (power_info->pplib5.usCACLeakageTableOffset) { 10337ccd5a2cSjsg ATOM_PPLIB_CAC_Leakage_Table *cac_table = 10347ccd5a2cSjsg (ATOM_PPLIB_CAC_Leakage_Table *) 10357ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 10367ccd5a2cSjsg le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); 10377ccd5a2cSjsg ATOM_PPLIB_CAC_Leakage_Record *entry; 10387ccd5a2cSjsg u32 size = cac_table->ucNumEntries * sizeof(struct radeon_cac_leakage_table); 10397ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); 10407ccd5a2cSjsg if (!rdev->pm.dpm.dyn_state.cac_leakage_table.entries) { 10417ccd5a2cSjsg r600_free_extended_power_table(rdev); 10427ccd5a2cSjsg return -ENOMEM; 10437ccd5a2cSjsg } 10447ccd5a2cSjsg entry = &cac_table->entries[0]; 10457ccd5a2cSjsg for (i = 0; i < cac_table->ucNumEntries; i++) { 10467ccd5a2cSjsg if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { 10477ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = 10487ccd5a2cSjsg le16_to_cpu(entry->usVddc1); 10497ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = 10507ccd5a2cSjsg le16_to_cpu(entry->usVddc2); 10517ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = 10527ccd5a2cSjsg le16_to_cpu(entry->usVddc3); 10537ccd5a2cSjsg } else { 10547ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = 10557ccd5a2cSjsg le16_to_cpu(entry->usVddc); 10567ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = 10577ccd5a2cSjsg le32_to_cpu(entry->ulLeakageValue); 10587ccd5a2cSjsg } 10597ccd5a2cSjsg entry = (ATOM_PPLIB_CAC_Leakage_Record *) 10607ccd5a2cSjsg ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); 10617ccd5a2cSjsg } 10627ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; 10637ccd5a2cSjsg } 10647ccd5a2cSjsg } 10657ccd5a2cSjsg 10667ccd5a2cSjsg /* ext tables */ 10677ccd5a2cSjsg if (le16_to_cpu(power_info->pplib.usTableSize) >= 10687ccd5a2cSjsg sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 10697ccd5a2cSjsg ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) 10707ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 10717ccd5a2cSjsg le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); 10727ccd5a2cSjsg if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && 10737ccd5a2cSjsg ext_hdr->usVCETableOffset) { 10747ccd5a2cSjsg VCEClockInfoArray *array = (VCEClockInfoArray *) 10757ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 10767ccd5a2cSjsg le16_to_cpu(ext_hdr->usVCETableOffset) + 1); 10777ccd5a2cSjsg ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = 10787ccd5a2cSjsg (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) 10797ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 10807ccd5a2cSjsg le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 10817ccd5a2cSjsg 1 + array->ucNumEntries * sizeof(VCEClockInfo)); 10827ccd5a2cSjsg ATOM_PPLIB_VCE_State_Table *states = 10837ccd5a2cSjsg (ATOM_PPLIB_VCE_State_Table *) 10847ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 10857ccd5a2cSjsg le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 10867ccd5a2cSjsg 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + 10877ccd5a2cSjsg 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); 10887ccd5a2cSjsg ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; 10897ccd5a2cSjsg ATOM_PPLIB_VCE_State_Record *state_entry; 10907ccd5a2cSjsg VCEClockInfo *vce_clk; 10917ccd5a2cSjsg u32 size = limits->numEntries * 10927ccd5a2cSjsg sizeof(struct radeon_vce_clock_voltage_dependency_entry); 10937ccd5a2cSjsg rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = 10947ccd5a2cSjsg kzalloc(size, GFP_KERNEL); 10957ccd5a2cSjsg if (!rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { 10967ccd5a2cSjsg r600_free_extended_power_table(rdev); 10977ccd5a2cSjsg return -ENOMEM; 10987ccd5a2cSjsg } 10997ccd5a2cSjsg rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = 11007ccd5a2cSjsg limits->numEntries; 11017ccd5a2cSjsg entry = &limits->entries[0]; 11027ccd5a2cSjsg state_entry = &states->entries[0]; 11037ccd5a2cSjsg for (i = 0; i < limits->numEntries; i++) { 11047ccd5a2cSjsg vce_clk = (VCEClockInfo *) 11057ccd5a2cSjsg ((u8 *)&array->entries[0] + 11067ccd5a2cSjsg (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 11077ccd5a2cSjsg rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = 11087ccd5a2cSjsg le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 11097ccd5a2cSjsg rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = 11107ccd5a2cSjsg le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 11117ccd5a2cSjsg rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = 11127ccd5a2cSjsg le16_to_cpu(entry->usVoltage); 11137ccd5a2cSjsg entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) 11147ccd5a2cSjsg ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); 11157ccd5a2cSjsg } 11167ccd5a2cSjsg for (i = 0; i < states->numEntries; i++) { 11177ccd5a2cSjsg if (i >= RADEON_MAX_VCE_LEVELS) 11187ccd5a2cSjsg break; 11197ccd5a2cSjsg vce_clk = (VCEClockInfo *) 11207ccd5a2cSjsg ((u8 *)&array->entries[0] + 11217ccd5a2cSjsg (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 11227ccd5a2cSjsg rdev->pm.dpm.vce_states[i].evclk = 11237ccd5a2cSjsg le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 11247ccd5a2cSjsg rdev->pm.dpm.vce_states[i].ecclk = 11257ccd5a2cSjsg le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 11267ccd5a2cSjsg rdev->pm.dpm.vce_states[i].clk_idx = 11277ccd5a2cSjsg state_entry->ucClockInfoIndex & 0x3f; 11287ccd5a2cSjsg rdev->pm.dpm.vce_states[i].pstate = 11297ccd5a2cSjsg (state_entry->ucClockInfoIndex & 0xc0) >> 6; 11307ccd5a2cSjsg state_entry = (ATOM_PPLIB_VCE_State_Record *) 11317ccd5a2cSjsg ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); 11327ccd5a2cSjsg } 11337ccd5a2cSjsg } 11347ccd5a2cSjsg if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && 11357ccd5a2cSjsg ext_hdr->usUVDTableOffset) { 11367ccd5a2cSjsg UVDClockInfoArray *array = (UVDClockInfoArray *) 11377ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 11387ccd5a2cSjsg le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); 11397ccd5a2cSjsg ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = 11407ccd5a2cSjsg (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) 11417ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 11427ccd5a2cSjsg le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + 11437ccd5a2cSjsg 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); 11447ccd5a2cSjsg ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; 11457ccd5a2cSjsg u32 size = limits->numEntries * 11467ccd5a2cSjsg sizeof(struct radeon_uvd_clock_voltage_dependency_entry); 11477ccd5a2cSjsg rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = 11487ccd5a2cSjsg kzalloc(size, GFP_KERNEL); 11497ccd5a2cSjsg if (!rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { 11507ccd5a2cSjsg r600_free_extended_power_table(rdev); 11517ccd5a2cSjsg return -ENOMEM; 11527ccd5a2cSjsg } 11537ccd5a2cSjsg rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = 11547ccd5a2cSjsg limits->numEntries; 11557ccd5a2cSjsg entry = &limits->entries[0]; 11567ccd5a2cSjsg for (i = 0; i < limits->numEntries; i++) { 11577ccd5a2cSjsg UVDClockInfo *uvd_clk = (UVDClockInfo *) 11587ccd5a2cSjsg ((u8 *)&array->entries[0] + 11597ccd5a2cSjsg (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); 11607ccd5a2cSjsg rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = 11617ccd5a2cSjsg le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); 11627ccd5a2cSjsg rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = 11637ccd5a2cSjsg le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); 11647ccd5a2cSjsg rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = 11657ccd5a2cSjsg le16_to_cpu(entry->usVoltage); 11667ccd5a2cSjsg entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) 11677ccd5a2cSjsg ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); 11687ccd5a2cSjsg } 11697ccd5a2cSjsg } 11707ccd5a2cSjsg if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && 11717ccd5a2cSjsg ext_hdr->usSAMUTableOffset) { 11727ccd5a2cSjsg ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = 11737ccd5a2cSjsg (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) 11747ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 11757ccd5a2cSjsg le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); 11767ccd5a2cSjsg ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; 11777ccd5a2cSjsg u32 size = limits->numEntries * 11787ccd5a2cSjsg sizeof(struct radeon_clock_voltage_dependency_entry); 11797ccd5a2cSjsg rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = 11807ccd5a2cSjsg kzalloc(size, GFP_KERNEL); 11817ccd5a2cSjsg if (!rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { 11827ccd5a2cSjsg r600_free_extended_power_table(rdev); 11837ccd5a2cSjsg return -ENOMEM; 11847ccd5a2cSjsg } 11857ccd5a2cSjsg rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = 11867ccd5a2cSjsg limits->numEntries; 11877ccd5a2cSjsg entry = &limits->entries[0]; 11887ccd5a2cSjsg for (i = 0; i < limits->numEntries; i++) { 11897ccd5a2cSjsg rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = 11907ccd5a2cSjsg le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); 11917ccd5a2cSjsg rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = 11927ccd5a2cSjsg le16_to_cpu(entry->usVoltage); 11937ccd5a2cSjsg entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) 11947ccd5a2cSjsg ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); 11957ccd5a2cSjsg } 11967ccd5a2cSjsg } 11977ccd5a2cSjsg if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && 11987ccd5a2cSjsg ext_hdr->usPPMTableOffset) { 11997ccd5a2cSjsg ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) 12007ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 12017ccd5a2cSjsg le16_to_cpu(ext_hdr->usPPMTableOffset)); 12027ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table = 12037ccd5a2cSjsg kzalloc(sizeof(struct radeon_ppm_table), GFP_KERNEL); 12047ccd5a2cSjsg if (!rdev->pm.dpm.dyn_state.ppm_table) { 12057ccd5a2cSjsg r600_free_extended_power_table(rdev); 12067ccd5a2cSjsg return -ENOMEM; 12077ccd5a2cSjsg } 12087ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; 12097ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->cpu_core_number = 12107ccd5a2cSjsg le16_to_cpu(ppm->usCpuCoreNumber); 12117ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->platform_tdp = 12127ccd5a2cSjsg le32_to_cpu(ppm->ulPlatformTDP); 12137ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = 12147ccd5a2cSjsg le32_to_cpu(ppm->ulSmallACPlatformTDP); 12157ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->platform_tdc = 12167ccd5a2cSjsg le32_to_cpu(ppm->ulPlatformTDC); 12177ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = 12187ccd5a2cSjsg le32_to_cpu(ppm->ulSmallACPlatformTDC); 12197ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->apu_tdp = 12207ccd5a2cSjsg le32_to_cpu(ppm->ulApuTDP); 12217ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = 12227ccd5a2cSjsg le32_to_cpu(ppm->ulDGpuTDP); 12237ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = 12247ccd5a2cSjsg le32_to_cpu(ppm->ulDGpuUlvPower); 12257ccd5a2cSjsg rdev->pm.dpm.dyn_state.ppm_table->tj_max = 12267ccd5a2cSjsg le32_to_cpu(ppm->ulTjmax); 12277ccd5a2cSjsg } 12287ccd5a2cSjsg if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && 12297ccd5a2cSjsg ext_hdr->usACPTableOffset) { 12307ccd5a2cSjsg ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = 12317ccd5a2cSjsg (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) 12327ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 12337ccd5a2cSjsg le16_to_cpu(ext_hdr->usACPTableOffset) + 1); 12347ccd5a2cSjsg ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; 12357ccd5a2cSjsg u32 size = limits->numEntries * 12367ccd5a2cSjsg sizeof(struct radeon_clock_voltage_dependency_entry); 12377ccd5a2cSjsg rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = 12387ccd5a2cSjsg kzalloc(size, GFP_KERNEL); 12397ccd5a2cSjsg if (!rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { 12407ccd5a2cSjsg r600_free_extended_power_table(rdev); 12417ccd5a2cSjsg return -ENOMEM; 12427ccd5a2cSjsg } 12437ccd5a2cSjsg rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = 12447ccd5a2cSjsg limits->numEntries; 12457ccd5a2cSjsg entry = &limits->entries[0]; 12467ccd5a2cSjsg for (i = 0; i < limits->numEntries; i++) { 12477ccd5a2cSjsg rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = 12487ccd5a2cSjsg le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); 12497ccd5a2cSjsg rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = 12507ccd5a2cSjsg le16_to_cpu(entry->usVoltage); 12517ccd5a2cSjsg entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) 12527ccd5a2cSjsg ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); 12537ccd5a2cSjsg } 12547ccd5a2cSjsg } 12557ccd5a2cSjsg if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && 12567ccd5a2cSjsg ext_hdr->usPowerTuneTableOffset) { 12577ccd5a2cSjsg u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + 12587ccd5a2cSjsg le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 12597ccd5a2cSjsg ATOM_PowerTune_Table *pt; 12607ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table = 12617ccd5a2cSjsg kzalloc(sizeof(struct radeon_cac_tdp_table), GFP_KERNEL); 12627ccd5a2cSjsg if (!rdev->pm.dpm.dyn_state.cac_tdp_table) { 12637ccd5a2cSjsg r600_free_extended_power_table(rdev); 12647ccd5a2cSjsg return -ENOMEM; 12657ccd5a2cSjsg } 12667ccd5a2cSjsg if (rev > 0) { 12677ccd5a2cSjsg ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) 12687ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 12697ccd5a2cSjsg le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 12707ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 12717ccd5a2cSjsg le16_to_cpu(ppt->usMaximumPowerDeliveryLimit); 12727ccd5a2cSjsg pt = &ppt->power_tune_table; 12737ccd5a2cSjsg } else { 12747ccd5a2cSjsg ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) 12757ccd5a2cSjsg (mode_info->atom_context->bios + data_offset + 12767ccd5a2cSjsg le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 12777ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; 12787ccd5a2cSjsg pt = &ppt->power_tune_table; 12797ccd5a2cSjsg } 12807ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); 12817ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = 12827ccd5a2cSjsg le16_to_cpu(pt->usConfigurableTDP); 12837ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); 12847ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = 12857ccd5a2cSjsg le16_to_cpu(pt->usBatteryPowerLimit); 12867ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = 12877ccd5a2cSjsg le16_to_cpu(pt->usSmallPowerLimit); 12887ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = 12897ccd5a2cSjsg le16_to_cpu(pt->usLowCACLeakage); 12907ccd5a2cSjsg rdev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = 12917ccd5a2cSjsg le16_to_cpu(pt->usHighCACLeakage); 12927ccd5a2cSjsg } 12937ccd5a2cSjsg } 12947ccd5a2cSjsg 12957ccd5a2cSjsg return 0; 12967ccd5a2cSjsg } 12977ccd5a2cSjsg 12987ccd5a2cSjsg void r600_free_extended_power_table(struct radeon_device *rdev) 12997ccd5a2cSjsg { 13007ccd5a2cSjsg struct radeon_dpm_dynamic_state *dyn_state = &rdev->pm.dpm.dyn_state; 13017ccd5a2cSjsg 13027ccd5a2cSjsg kfree(dyn_state->vddc_dependency_on_sclk.entries); 13037ccd5a2cSjsg kfree(dyn_state->vddci_dependency_on_mclk.entries); 13047ccd5a2cSjsg kfree(dyn_state->vddc_dependency_on_mclk.entries); 13057ccd5a2cSjsg kfree(dyn_state->mvdd_dependency_on_mclk.entries); 13067ccd5a2cSjsg kfree(dyn_state->cac_leakage_table.entries); 13077ccd5a2cSjsg kfree(dyn_state->phase_shedding_limits_table.entries); 13087ccd5a2cSjsg kfree(dyn_state->ppm_table); 13097ccd5a2cSjsg kfree(dyn_state->cac_tdp_table); 13107ccd5a2cSjsg kfree(dyn_state->vce_clock_voltage_dependency_table.entries); 13117ccd5a2cSjsg kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); 13127ccd5a2cSjsg kfree(dyn_state->samu_clock_voltage_dependency_table.entries); 13137ccd5a2cSjsg kfree(dyn_state->acp_clock_voltage_dependency_table.entries); 13147ccd5a2cSjsg } 13157ccd5a2cSjsg 13167ccd5a2cSjsg enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, 13177ccd5a2cSjsg u32 sys_mask, 13187ccd5a2cSjsg enum radeon_pcie_gen asic_gen, 13197ccd5a2cSjsg enum radeon_pcie_gen default_gen) 13207ccd5a2cSjsg { 13217ccd5a2cSjsg switch (asic_gen) { 13227ccd5a2cSjsg case RADEON_PCIE_GEN1: 13237ccd5a2cSjsg return RADEON_PCIE_GEN1; 13247ccd5a2cSjsg case RADEON_PCIE_GEN2: 13257ccd5a2cSjsg return RADEON_PCIE_GEN2; 13267ccd5a2cSjsg case RADEON_PCIE_GEN3: 13277ccd5a2cSjsg return RADEON_PCIE_GEN3; 13287ccd5a2cSjsg default: 13297f4dd379Sjsg if ((sys_mask & RADEON_PCIE_SPEED_80) && (default_gen == RADEON_PCIE_GEN3)) 13307ccd5a2cSjsg return RADEON_PCIE_GEN3; 13317f4dd379Sjsg else if ((sys_mask & RADEON_PCIE_SPEED_50) && (default_gen == RADEON_PCIE_GEN2)) 13327ccd5a2cSjsg return RADEON_PCIE_GEN2; 13337ccd5a2cSjsg else 13347ccd5a2cSjsg return RADEON_PCIE_GEN1; 13357ccd5a2cSjsg } 13367ccd5a2cSjsg return RADEON_PCIE_GEN1; 13377ccd5a2cSjsg } 13387ccd5a2cSjsg 13397ccd5a2cSjsg u16 r600_get_pcie_lane_support(struct radeon_device *rdev, 13407ccd5a2cSjsg u16 asic_lanes, 13417ccd5a2cSjsg u16 default_lanes) 13427ccd5a2cSjsg { 13437ccd5a2cSjsg switch (asic_lanes) { 13447ccd5a2cSjsg case 0: 13457ccd5a2cSjsg default: 13467ccd5a2cSjsg return default_lanes; 13477ccd5a2cSjsg case 1: 13487ccd5a2cSjsg return 1; 13497ccd5a2cSjsg case 2: 13507ccd5a2cSjsg return 2; 13517ccd5a2cSjsg case 4: 13527ccd5a2cSjsg return 4; 13537ccd5a2cSjsg case 8: 13547ccd5a2cSjsg return 8; 13557ccd5a2cSjsg case 12: 13567ccd5a2cSjsg return 12; 13577ccd5a2cSjsg case 16: 13587ccd5a2cSjsg return 16; 13597ccd5a2cSjsg } 13607ccd5a2cSjsg } 13617ccd5a2cSjsg 13627ccd5a2cSjsg u8 r600_encode_pci_lane_width(u32 lanes) 13637ccd5a2cSjsg { 13641bb76ff1Sjsg static const u8 encoded_lanes[] = { 13651bb76ff1Sjsg 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 13661bb76ff1Sjsg }; 13677ccd5a2cSjsg 13687ccd5a2cSjsg if (lanes > 16) 13697ccd5a2cSjsg return 0; 13707ccd5a2cSjsg 13717ccd5a2cSjsg return encoded_lanes[lanes]; 13727ccd5a2cSjsg } 1373