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 "rv740d.h"
277ccd5a2cSjsg #include "r600_dpm.h"
285ca02815Sjsg #include "rv770.h"
297ccd5a2cSjsg #include "rv770_dpm.h"
307ccd5a2cSjsg #include "atom.h"
317ccd5a2cSjsg
rv740_get_decoded_reference_divider(u32 encoded_ref)327ccd5a2cSjsg u32 rv740_get_decoded_reference_divider(u32 encoded_ref)
337ccd5a2cSjsg {
347ccd5a2cSjsg u32 ref = 0;
357ccd5a2cSjsg
367ccd5a2cSjsg switch (encoded_ref) {
377ccd5a2cSjsg case 0:
387ccd5a2cSjsg ref = 1;
397ccd5a2cSjsg break;
407ccd5a2cSjsg case 16:
417ccd5a2cSjsg ref = 2;
427ccd5a2cSjsg break;
437ccd5a2cSjsg case 17:
447ccd5a2cSjsg ref = 3;
457ccd5a2cSjsg break;
467ccd5a2cSjsg case 18:
477ccd5a2cSjsg ref = 2;
487ccd5a2cSjsg break;
497ccd5a2cSjsg case 19:
507ccd5a2cSjsg ref = 3;
517ccd5a2cSjsg break;
527ccd5a2cSjsg case 20:
537ccd5a2cSjsg ref = 4;
547ccd5a2cSjsg break;
557ccd5a2cSjsg case 21:
567ccd5a2cSjsg ref = 5;
577ccd5a2cSjsg break;
587ccd5a2cSjsg default:
597ccd5a2cSjsg DRM_ERROR("Invalid encoded Reference Divider\n");
607ccd5a2cSjsg ref = 0;
617ccd5a2cSjsg break;
627ccd5a2cSjsg }
637ccd5a2cSjsg
647ccd5a2cSjsg return ref;
657ccd5a2cSjsg }
667ccd5a2cSjsg
677ccd5a2cSjsg struct dll_speed_setting {
687ccd5a2cSjsg u16 min;
697ccd5a2cSjsg u16 max;
707ccd5a2cSjsg u32 dll_speed;
717ccd5a2cSjsg };
727ccd5a2cSjsg
737ccd5a2cSjsg static struct dll_speed_setting dll_speed_table[16] =
747ccd5a2cSjsg {
757ccd5a2cSjsg { 270, 320, 0x0f },
767ccd5a2cSjsg { 240, 270, 0x0e },
777ccd5a2cSjsg { 200, 240, 0x0d },
787ccd5a2cSjsg { 180, 200, 0x0c },
797ccd5a2cSjsg { 160, 180, 0x0b },
807ccd5a2cSjsg { 140, 160, 0x0a },
817ccd5a2cSjsg { 120, 140, 0x09 },
827ccd5a2cSjsg { 110, 120, 0x08 },
837ccd5a2cSjsg { 95, 110, 0x07 },
847ccd5a2cSjsg { 85, 95, 0x06 },
857ccd5a2cSjsg { 78, 85, 0x05 },
867ccd5a2cSjsg { 70, 78, 0x04 },
877ccd5a2cSjsg { 65, 70, 0x03 },
887ccd5a2cSjsg { 60, 65, 0x02 },
897ccd5a2cSjsg { 42, 60, 0x01 },
907ccd5a2cSjsg { 00, 42, 0x00 }
917ccd5a2cSjsg };
927ccd5a2cSjsg
rv740_get_dll_speed(bool is_gddr5,u32 memory_clock)937ccd5a2cSjsg u32 rv740_get_dll_speed(bool is_gddr5, u32 memory_clock)
947ccd5a2cSjsg {
957ccd5a2cSjsg int i;
967ccd5a2cSjsg u32 factor;
977ccd5a2cSjsg u16 data_rate;
987ccd5a2cSjsg
997ccd5a2cSjsg if (is_gddr5)
1007ccd5a2cSjsg factor = 4;
1017ccd5a2cSjsg else
1027ccd5a2cSjsg factor = 2;
1037ccd5a2cSjsg
1047ccd5a2cSjsg data_rate = (u16)(memory_clock * factor / 1000);
1057ccd5a2cSjsg
1067ccd5a2cSjsg if (data_rate < dll_speed_table[0].max) {
1077ccd5a2cSjsg for (i = 0; i < 16; i++) {
1087ccd5a2cSjsg if (data_rate > dll_speed_table[i].min &&
1097ccd5a2cSjsg data_rate <= dll_speed_table[i].max)
1107ccd5a2cSjsg return dll_speed_table[i].dll_speed;
1117ccd5a2cSjsg }
1127ccd5a2cSjsg }
1137ccd5a2cSjsg
1147ccd5a2cSjsg DRM_DEBUG_KMS("Target MCLK greater than largest MCLK in DLL speed table\n");
1157ccd5a2cSjsg
1167ccd5a2cSjsg return 0x0f;
1177ccd5a2cSjsg }
1187ccd5a2cSjsg
rv740_populate_sclk_value(struct radeon_device * rdev,u32 engine_clock,RV770_SMC_SCLK_VALUE * sclk)1197ccd5a2cSjsg int rv740_populate_sclk_value(struct radeon_device *rdev, u32 engine_clock,
1207ccd5a2cSjsg RV770_SMC_SCLK_VALUE *sclk)
1217ccd5a2cSjsg {
1227ccd5a2cSjsg struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1237ccd5a2cSjsg struct atom_clock_dividers dividers;
1247ccd5a2cSjsg u32 spll_func_cntl = pi->clk_regs.rv770.cg_spll_func_cntl;
1257ccd5a2cSjsg u32 spll_func_cntl_2 = pi->clk_regs.rv770.cg_spll_func_cntl_2;
1267ccd5a2cSjsg u32 spll_func_cntl_3 = pi->clk_regs.rv770.cg_spll_func_cntl_3;
1277ccd5a2cSjsg u32 cg_spll_spread_spectrum = pi->clk_regs.rv770.cg_spll_spread_spectrum;
1287ccd5a2cSjsg u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv770.cg_spll_spread_spectrum_2;
1297ccd5a2cSjsg u64 tmp;
1307ccd5a2cSjsg u32 reference_clock = rdev->clock.spll.reference_freq;
1317ccd5a2cSjsg u32 reference_divider;
1327ccd5a2cSjsg u32 fbdiv;
1337ccd5a2cSjsg int ret;
1347ccd5a2cSjsg
1357ccd5a2cSjsg ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
1367ccd5a2cSjsg engine_clock, false, ÷rs);
1377ccd5a2cSjsg if (ret)
1387ccd5a2cSjsg return ret;
1397ccd5a2cSjsg
1407ccd5a2cSjsg reference_divider = 1 + dividers.ref_div;
1417ccd5a2cSjsg
1427ccd5a2cSjsg tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384;
1437ccd5a2cSjsg do_div(tmp, reference_clock);
1447ccd5a2cSjsg fbdiv = (u32) tmp;
1457ccd5a2cSjsg
1467ccd5a2cSjsg spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK);
1477ccd5a2cSjsg spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
1487ccd5a2cSjsg spll_func_cntl |= SPLL_PDIV_A(dividers.post_div);
1497ccd5a2cSjsg
1507ccd5a2cSjsg spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
1517ccd5a2cSjsg spll_func_cntl_2 |= SCLK_MUX_SEL(2);
1527ccd5a2cSjsg
1537ccd5a2cSjsg spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
1547ccd5a2cSjsg spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
1557ccd5a2cSjsg spll_func_cntl_3 |= SPLL_DITHEN;
1567ccd5a2cSjsg
1577ccd5a2cSjsg if (pi->sclk_ss) {
1587ccd5a2cSjsg struct radeon_atom_ss ss;
1597ccd5a2cSjsg u32 vco_freq = engine_clock * dividers.post_div;
1607ccd5a2cSjsg
1617ccd5a2cSjsg if (radeon_atombios_get_asic_ss_info(rdev, &ss,
1627ccd5a2cSjsg ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
1637ccd5a2cSjsg u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
1647ccd5a2cSjsg u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);
1657ccd5a2cSjsg
1667ccd5a2cSjsg cg_spll_spread_spectrum &= ~CLK_S_MASK;
1677ccd5a2cSjsg cg_spll_spread_spectrum |= CLK_S(clk_s);
1687ccd5a2cSjsg cg_spll_spread_spectrum |= SSEN;
1697ccd5a2cSjsg
1707ccd5a2cSjsg cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
1717ccd5a2cSjsg cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
1727ccd5a2cSjsg }
1737ccd5a2cSjsg }
1747ccd5a2cSjsg
1757ccd5a2cSjsg sclk->sclk_value = cpu_to_be32(engine_clock);
1767ccd5a2cSjsg sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
1777ccd5a2cSjsg sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
1787ccd5a2cSjsg sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
1797ccd5a2cSjsg sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum);
1807ccd5a2cSjsg sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2);
1817ccd5a2cSjsg
1827ccd5a2cSjsg return 0;
1837ccd5a2cSjsg }
1847ccd5a2cSjsg
rv740_populate_mclk_value(struct radeon_device * rdev,u32 engine_clock,u32 memory_clock,RV7XX_SMC_MCLK_VALUE * mclk)1857ccd5a2cSjsg int rv740_populate_mclk_value(struct radeon_device *rdev,
1867ccd5a2cSjsg u32 engine_clock, u32 memory_clock,
1877ccd5a2cSjsg RV7XX_SMC_MCLK_VALUE *mclk)
1887ccd5a2cSjsg {
1897ccd5a2cSjsg struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1907ccd5a2cSjsg u32 mpll_ad_func_cntl = pi->clk_regs.rv770.mpll_ad_func_cntl;
1917ccd5a2cSjsg u32 mpll_ad_func_cntl_2 = pi->clk_regs.rv770.mpll_ad_func_cntl_2;
1927ccd5a2cSjsg u32 mpll_dq_func_cntl = pi->clk_regs.rv770.mpll_dq_func_cntl;
1937ccd5a2cSjsg u32 mpll_dq_func_cntl_2 = pi->clk_regs.rv770.mpll_dq_func_cntl_2;
1947ccd5a2cSjsg u32 mclk_pwrmgt_cntl = pi->clk_regs.rv770.mclk_pwrmgt_cntl;
1957ccd5a2cSjsg u32 dll_cntl = pi->clk_regs.rv770.dll_cntl;
1967ccd5a2cSjsg u32 mpll_ss1 = pi->clk_regs.rv770.mpll_ss1;
1977ccd5a2cSjsg u32 mpll_ss2 = pi->clk_regs.rv770.mpll_ss2;
1987ccd5a2cSjsg struct atom_clock_dividers dividers;
1997ccd5a2cSjsg u32 ibias;
2007ccd5a2cSjsg u32 dll_speed;
2017ccd5a2cSjsg int ret;
2027ccd5a2cSjsg
2037ccd5a2cSjsg ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
2047ccd5a2cSjsg memory_clock, false, ÷rs);
2057ccd5a2cSjsg if (ret)
2067ccd5a2cSjsg return ret;
2077ccd5a2cSjsg
2087ccd5a2cSjsg ibias = rv770_map_clkf_to_ibias(rdev, dividers.whole_fb_div);
2097ccd5a2cSjsg
2107ccd5a2cSjsg mpll_ad_func_cntl &= ~(CLKR_MASK |
2117ccd5a2cSjsg YCLK_POST_DIV_MASK |
2127ccd5a2cSjsg CLKF_MASK |
2137ccd5a2cSjsg CLKFRAC_MASK |
2147ccd5a2cSjsg IBIAS_MASK);
2157ccd5a2cSjsg mpll_ad_func_cntl |= CLKR(dividers.ref_div);
2167ccd5a2cSjsg mpll_ad_func_cntl |= YCLK_POST_DIV(dividers.post_div);
2177ccd5a2cSjsg mpll_ad_func_cntl |= CLKF(dividers.whole_fb_div);
2187ccd5a2cSjsg mpll_ad_func_cntl |= CLKFRAC(dividers.frac_fb_div);
2197ccd5a2cSjsg mpll_ad_func_cntl |= IBIAS(ibias);
2207ccd5a2cSjsg
2217ccd5a2cSjsg if (dividers.vco_mode)
2227ccd5a2cSjsg mpll_ad_func_cntl_2 |= VCO_MODE;
2237ccd5a2cSjsg else
2247ccd5a2cSjsg mpll_ad_func_cntl_2 &= ~VCO_MODE;
2257ccd5a2cSjsg
2267ccd5a2cSjsg if (pi->mem_gddr5) {
2277ccd5a2cSjsg mpll_dq_func_cntl &= ~(CLKR_MASK |
2287ccd5a2cSjsg YCLK_POST_DIV_MASK |
2297ccd5a2cSjsg CLKF_MASK |
2307ccd5a2cSjsg CLKFRAC_MASK |
2317ccd5a2cSjsg IBIAS_MASK);
2327ccd5a2cSjsg mpll_dq_func_cntl |= CLKR(dividers.ref_div);
2337ccd5a2cSjsg mpll_dq_func_cntl |= YCLK_POST_DIV(dividers.post_div);
2347ccd5a2cSjsg mpll_dq_func_cntl |= CLKF(dividers.whole_fb_div);
2357ccd5a2cSjsg mpll_dq_func_cntl |= CLKFRAC(dividers.frac_fb_div);
2367ccd5a2cSjsg mpll_dq_func_cntl |= IBIAS(ibias);
2377ccd5a2cSjsg
2387ccd5a2cSjsg if (dividers.vco_mode)
2397ccd5a2cSjsg mpll_dq_func_cntl_2 |= VCO_MODE;
2407ccd5a2cSjsg else
2417ccd5a2cSjsg mpll_dq_func_cntl_2 &= ~VCO_MODE;
2427ccd5a2cSjsg }
2437ccd5a2cSjsg
2447ccd5a2cSjsg if (pi->mclk_ss) {
2457ccd5a2cSjsg struct radeon_atom_ss ss;
2467ccd5a2cSjsg u32 vco_freq = memory_clock * dividers.post_div;
2477ccd5a2cSjsg
2487ccd5a2cSjsg if (radeon_atombios_get_asic_ss_info(rdev, &ss,
2497ccd5a2cSjsg ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
2507ccd5a2cSjsg u32 reference_clock = rdev->clock.mpll.reference_freq;
2517ccd5a2cSjsg u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
252*aef4c798Sjsg u32 clk_s, clk_v;
253*aef4c798Sjsg
254*aef4c798Sjsg if (!decoded_ref)
255*aef4c798Sjsg return -EINVAL;
256*aef4c798Sjsg clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
257*aef4c798Sjsg clk_v = 0x40000 * ss.percentage *
2587ccd5a2cSjsg (dividers.whole_fb_div + (dividers.frac_fb_div / 8)) / (clk_s * 10000);
2597ccd5a2cSjsg
2607ccd5a2cSjsg mpll_ss1 &= ~CLKV_MASK;
2617ccd5a2cSjsg mpll_ss1 |= CLKV(clk_v);
2627ccd5a2cSjsg
2637ccd5a2cSjsg mpll_ss2 &= ~CLKS_MASK;
2647ccd5a2cSjsg mpll_ss2 |= CLKS(clk_s);
2657ccd5a2cSjsg }
2667ccd5a2cSjsg }
2677ccd5a2cSjsg
2687ccd5a2cSjsg dll_speed = rv740_get_dll_speed(pi->mem_gddr5,
2697ccd5a2cSjsg memory_clock);
2707ccd5a2cSjsg
2717ccd5a2cSjsg mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;
2727ccd5a2cSjsg mclk_pwrmgt_cntl |= DLL_SPEED(dll_speed);
2737ccd5a2cSjsg
2747ccd5a2cSjsg mclk->mclk770.mclk_value = cpu_to_be32(memory_clock);
2757ccd5a2cSjsg mclk->mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
2767ccd5a2cSjsg mclk->mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
2777ccd5a2cSjsg mclk->mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
2787ccd5a2cSjsg mclk->mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
2797ccd5a2cSjsg mclk->mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
2807ccd5a2cSjsg mclk->mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
2817ccd5a2cSjsg mclk->mclk770.vMPLL_SS = cpu_to_be32(mpll_ss1);
2827ccd5a2cSjsg mclk->mclk770.vMPLL_SS2 = cpu_to_be32(mpll_ss2);
2837ccd5a2cSjsg
2847ccd5a2cSjsg return 0;
2857ccd5a2cSjsg }
2867ccd5a2cSjsg
rv740_read_clock_registers(struct radeon_device * rdev)2877ccd5a2cSjsg void rv740_read_clock_registers(struct radeon_device *rdev)
2887ccd5a2cSjsg {
2897ccd5a2cSjsg struct rv7xx_power_info *pi = rv770_get_pi(rdev);
2907ccd5a2cSjsg
2917ccd5a2cSjsg pi->clk_regs.rv770.cg_spll_func_cntl =
2927ccd5a2cSjsg RREG32(CG_SPLL_FUNC_CNTL);
2937ccd5a2cSjsg pi->clk_regs.rv770.cg_spll_func_cntl_2 =
2947ccd5a2cSjsg RREG32(CG_SPLL_FUNC_CNTL_2);
2957ccd5a2cSjsg pi->clk_regs.rv770.cg_spll_func_cntl_3 =
2967ccd5a2cSjsg RREG32(CG_SPLL_FUNC_CNTL_3);
2977ccd5a2cSjsg pi->clk_regs.rv770.cg_spll_spread_spectrum =
2987ccd5a2cSjsg RREG32(CG_SPLL_SPREAD_SPECTRUM);
2997ccd5a2cSjsg pi->clk_regs.rv770.cg_spll_spread_spectrum_2 =
3007ccd5a2cSjsg RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
3017ccd5a2cSjsg
3027ccd5a2cSjsg pi->clk_regs.rv770.mpll_ad_func_cntl =
3037ccd5a2cSjsg RREG32(MPLL_AD_FUNC_CNTL);
3047ccd5a2cSjsg pi->clk_regs.rv770.mpll_ad_func_cntl_2 =
3057ccd5a2cSjsg RREG32(MPLL_AD_FUNC_CNTL_2);
3067ccd5a2cSjsg pi->clk_regs.rv770.mpll_dq_func_cntl =
3077ccd5a2cSjsg RREG32(MPLL_DQ_FUNC_CNTL);
3087ccd5a2cSjsg pi->clk_regs.rv770.mpll_dq_func_cntl_2 =
3097ccd5a2cSjsg RREG32(MPLL_DQ_FUNC_CNTL_2);
3107ccd5a2cSjsg pi->clk_regs.rv770.mclk_pwrmgt_cntl =
3117ccd5a2cSjsg RREG32(MCLK_PWRMGT_CNTL);
3127ccd5a2cSjsg pi->clk_regs.rv770.dll_cntl = RREG32(DLL_CNTL);
3137ccd5a2cSjsg pi->clk_regs.rv770.mpll_ss1 = RREG32(MPLL_SS1);
3147ccd5a2cSjsg pi->clk_regs.rv770.mpll_ss2 = RREG32(MPLL_SS2);
3157ccd5a2cSjsg }
3167ccd5a2cSjsg
rv740_populate_smc_acpi_state(struct radeon_device * rdev,RV770_SMC_STATETABLE * table)3177ccd5a2cSjsg int rv740_populate_smc_acpi_state(struct radeon_device *rdev,
3187ccd5a2cSjsg RV770_SMC_STATETABLE *table)
3197ccd5a2cSjsg {
3207ccd5a2cSjsg struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3217ccd5a2cSjsg u32 mpll_ad_func_cntl = pi->clk_regs.rv770.mpll_ad_func_cntl;
3227ccd5a2cSjsg u32 mpll_ad_func_cntl_2 = pi->clk_regs.rv770.mpll_ad_func_cntl_2;
3237ccd5a2cSjsg u32 mpll_dq_func_cntl = pi->clk_regs.rv770.mpll_dq_func_cntl;
3247ccd5a2cSjsg u32 mpll_dq_func_cntl_2 = pi->clk_regs.rv770.mpll_dq_func_cntl_2;
3257ccd5a2cSjsg u32 spll_func_cntl = pi->clk_regs.rv770.cg_spll_func_cntl;
3267ccd5a2cSjsg u32 spll_func_cntl_2 = pi->clk_regs.rv770.cg_spll_func_cntl_2;
3277ccd5a2cSjsg u32 spll_func_cntl_3 = pi->clk_regs.rv770.cg_spll_func_cntl_3;
3287ccd5a2cSjsg u32 mclk_pwrmgt_cntl = pi->clk_regs.rv770.mclk_pwrmgt_cntl;
3297ccd5a2cSjsg u32 dll_cntl = pi->clk_regs.rv770.dll_cntl;
3307ccd5a2cSjsg
3317ccd5a2cSjsg table->ACPIState = table->initialState;
3327ccd5a2cSjsg
3337ccd5a2cSjsg table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
3347ccd5a2cSjsg
3357ccd5a2cSjsg if (pi->acpi_vddc) {
3367ccd5a2cSjsg rv770_populate_vddc_value(rdev, pi->acpi_vddc,
3377ccd5a2cSjsg &table->ACPIState.levels[0].vddc);
3387ccd5a2cSjsg table->ACPIState.levels[0].gen2PCIE =
3397ccd5a2cSjsg pi->pcie_gen2 ?
3407ccd5a2cSjsg pi->acpi_pcie_gen2 : 0;
3417ccd5a2cSjsg table->ACPIState.levels[0].gen2XSP =
3427ccd5a2cSjsg pi->acpi_pcie_gen2;
3437ccd5a2cSjsg } else {
3447ccd5a2cSjsg rv770_populate_vddc_value(rdev, pi->min_vddc_in_table,
3457ccd5a2cSjsg &table->ACPIState.levels[0].vddc);
3467ccd5a2cSjsg table->ACPIState.levels[0].gen2PCIE = 0;
3477ccd5a2cSjsg }
3487ccd5a2cSjsg
3497ccd5a2cSjsg mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
3507ccd5a2cSjsg
3517ccd5a2cSjsg mpll_dq_func_cntl_2 |= BYPASS | BIAS_GEN_PDNB | RESET_EN;
3527ccd5a2cSjsg
3537ccd5a2cSjsg mclk_pwrmgt_cntl |= (MRDCKA0_RESET |
3547ccd5a2cSjsg MRDCKA1_RESET |
3557ccd5a2cSjsg MRDCKB0_RESET |
3567ccd5a2cSjsg MRDCKB1_RESET |
3577ccd5a2cSjsg MRDCKC0_RESET |
3587ccd5a2cSjsg MRDCKC1_RESET |
3597ccd5a2cSjsg MRDCKD0_RESET |
3607ccd5a2cSjsg MRDCKD1_RESET);
3617ccd5a2cSjsg
3627ccd5a2cSjsg dll_cntl |= (MRDCKA0_BYPASS |
3637ccd5a2cSjsg MRDCKA1_BYPASS |
3647ccd5a2cSjsg MRDCKB0_BYPASS |
3657ccd5a2cSjsg MRDCKB1_BYPASS |
3667ccd5a2cSjsg MRDCKC0_BYPASS |
3677ccd5a2cSjsg MRDCKC1_BYPASS |
3687ccd5a2cSjsg MRDCKD0_BYPASS |
3697ccd5a2cSjsg MRDCKD1_BYPASS);
3707ccd5a2cSjsg
3717ccd5a2cSjsg spll_func_cntl |= SPLL_RESET | SPLL_SLEEP | SPLL_BYPASS_EN;
3727ccd5a2cSjsg
3737ccd5a2cSjsg spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
3747ccd5a2cSjsg spll_func_cntl_2 |= SCLK_MUX_SEL(4);
3757ccd5a2cSjsg
3767ccd5a2cSjsg table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
3777ccd5a2cSjsg table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
3787ccd5a2cSjsg table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
3797ccd5a2cSjsg table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
3807ccd5a2cSjsg table->ACPIState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
3817ccd5a2cSjsg table->ACPIState.levels[0].mclk.mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
3827ccd5a2cSjsg
3837ccd5a2cSjsg table->ACPIState.levels[0].mclk.mclk770.mclk_value = 0;
3847ccd5a2cSjsg
3857ccd5a2cSjsg table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
3867ccd5a2cSjsg table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
3877ccd5a2cSjsg table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
3887ccd5a2cSjsg
3897ccd5a2cSjsg table->ACPIState.levels[0].sclk.sclk_value = 0;
3907ccd5a2cSjsg
3917ccd5a2cSjsg table->ACPIState.levels[1] = table->ACPIState.levels[0];
3927ccd5a2cSjsg table->ACPIState.levels[2] = table->ACPIState.levels[0];
3937ccd5a2cSjsg
3947ccd5a2cSjsg rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
3957ccd5a2cSjsg
3967ccd5a2cSjsg return 0;
3977ccd5a2cSjsg }
3987ccd5a2cSjsg
rv740_enable_mclk_spread_spectrum(struct radeon_device * rdev,bool enable)3997ccd5a2cSjsg void rv740_enable_mclk_spread_spectrum(struct radeon_device *rdev,
4007ccd5a2cSjsg bool enable)
4017ccd5a2cSjsg {
4027ccd5a2cSjsg if (enable)
4037ccd5a2cSjsg WREG32_P(MPLL_CNTL_MODE, SS_SSEN, ~SS_SSEN);
4047ccd5a2cSjsg else
4057ccd5a2cSjsg WREG32_P(MPLL_CNTL_MODE, 0, ~SS_SSEN);
4067ccd5a2cSjsg }
4077ccd5a2cSjsg
rv740_get_mclk_frequency_ratio(u32 memory_clock)4087ccd5a2cSjsg u8 rv740_get_mclk_frequency_ratio(u32 memory_clock)
4097ccd5a2cSjsg {
4107ccd5a2cSjsg u8 mc_para_index;
4117ccd5a2cSjsg
4127ccd5a2cSjsg if ((memory_clock < 10000) || (memory_clock > 47500))
4137ccd5a2cSjsg mc_para_index = 0x00;
4147ccd5a2cSjsg else
4157ccd5a2cSjsg mc_para_index = (u8)((memory_clock - 10000) / 2500);
4167ccd5a2cSjsg
4177ccd5a2cSjsg return mc_para_index;
4187ccd5a2cSjsg }
419