1926deccbSFrançois Tigeot /* 2926deccbSFrançois Tigeot * Copyright 2008 Advanced Micro Devices, Inc. 3926deccbSFrançois Tigeot * Copyright 2008 Red Hat Inc. 4926deccbSFrançois Tigeot * Copyright 2009 Jerome Glisse. 5926deccbSFrançois Tigeot * 6926deccbSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 7926deccbSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 8926deccbSFrançois Tigeot * to deal in the Software without restriction, including without limitation 9926deccbSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10926deccbSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 11926deccbSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 12926deccbSFrançois Tigeot * 13926deccbSFrançois Tigeot * The above copyright notice and this permission notice shall be included in 14926deccbSFrançois Tigeot * all copies or substantial portions of the Software. 15926deccbSFrançois Tigeot * 16926deccbSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17926deccbSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18926deccbSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19926deccbSFrançois Tigeot * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20926deccbSFrançois Tigeot * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21926deccbSFrançois Tigeot * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22926deccbSFrançois Tigeot * OTHER DEALINGS IN THE SOFTWARE. 23926deccbSFrançois Tigeot * 24926deccbSFrançois Tigeot * Authors: Dave Airlie 25926deccbSFrançois Tigeot * Alex Deucher 26926deccbSFrançois Tigeot * Jerome Glisse 27926deccbSFrançois Tigeot */ 28926deccbSFrançois Tigeot #include <drm/drmP.h> 29*83b4b9b9SFrançois Tigeot #include <drm/radeon_drm.h> 30926deccbSFrançois Tigeot #include "radeon_reg.h" 31926deccbSFrançois Tigeot #include "radeon.h" 32926deccbSFrançois Tigeot #include "radeon_asic.h" 33926deccbSFrançois Tigeot #include "atom.h" 34926deccbSFrançois Tigeot 35926deccbSFrançois Tigeot /* 10 khz */ 36926deccbSFrançois Tigeot uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev) 37926deccbSFrançois Tigeot { 38926deccbSFrançois Tigeot struct radeon_pll *spll = &rdev->clock.spll; 39926deccbSFrançois Tigeot uint32_t fb_div, ref_div, post_div, sclk; 40926deccbSFrançois Tigeot 41926deccbSFrançois Tigeot fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); 42926deccbSFrançois Tigeot fb_div = (fb_div >> RADEON_SPLL_FB_DIV_SHIFT) & RADEON_SPLL_FB_DIV_MASK; 43926deccbSFrançois Tigeot fb_div <<= 1; 44926deccbSFrançois Tigeot fb_div *= spll->reference_freq; 45926deccbSFrançois Tigeot 46926deccbSFrançois Tigeot ref_div = 47926deccbSFrançois Tigeot RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; 48926deccbSFrançois Tigeot 49926deccbSFrançois Tigeot if (ref_div == 0) 50926deccbSFrançois Tigeot return 0; 51926deccbSFrançois Tigeot 52926deccbSFrançois Tigeot sclk = fb_div / ref_div; 53926deccbSFrançois Tigeot 54926deccbSFrançois Tigeot post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK; 55926deccbSFrançois Tigeot if (post_div == 2) 56926deccbSFrançois Tigeot sclk >>= 1; 57926deccbSFrançois Tigeot else if (post_div == 3) 58926deccbSFrançois Tigeot sclk >>= 2; 59926deccbSFrançois Tigeot else if (post_div == 4) 60926deccbSFrançois Tigeot sclk >>= 3; 61926deccbSFrançois Tigeot 62926deccbSFrançois Tigeot return sclk; 63926deccbSFrançois Tigeot } 64926deccbSFrançois Tigeot 65926deccbSFrançois Tigeot /* 10 khz */ 66926deccbSFrançois Tigeot uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) 67926deccbSFrançois Tigeot { 68926deccbSFrançois Tigeot struct radeon_pll *mpll = &rdev->clock.mpll; 69926deccbSFrançois Tigeot uint32_t fb_div, ref_div, post_div, mclk; 70926deccbSFrançois Tigeot 71926deccbSFrançois Tigeot fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); 72926deccbSFrançois Tigeot fb_div = (fb_div >> RADEON_MPLL_FB_DIV_SHIFT) & RADEON_MPLL_FB_DIV_MASK; 73926deccbSFrançois Tigeot fb_div <<= 1; 74926deccbSFrançois Tigeot fb_div *= mpll->reference_freq; 75926deccbSFrançois Tigeot 76926deccbSFrançois Tigeot ref_div = 77926deccbSFrançois Tigeot RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; 78926deccbSFrançois Tigeot 79926deccbSFrançois Tigeot if (ref_div == 0) 80926deccbSFrançois Tigeot return 0; 81926deccbSFrançois Tigeot 82926deccbSFrançois Tigeot mclk = fb_div / ref_div; 83926deccbSFrançois Tigeot 84926deccbSFrançois Tigeot post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7; 85926deccbSFrançois Tigeot if (post_div == 2) 86926deccbSFrançois Tigeot mclk >>= 1; 87926deccbSFrançois Tigeot else if (post_div == 3) 88926deccbSFrançois Tigeot mclk >>= 2; 89926deccbSFrançois Tigeot else if (post_div == 4) 90926deccbSFrançois Tigeot mclk >>= 3; 91926deccbSFrançois Tigeot 92926deccbSFrançois Tigeot return mclk; 93926deccbSFrançois Tigeot } 94926deccbSFrançois Tigeot 95926deccbSFrançois Tigeot #ifdef CONFIG_OF 96926deccbSFrançois Tigeot /* 97926deccbSFrançois Tigeot * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device 98926deccbSFrançois Tigeot * tree. Hopefully, ATI OF driver is kind enough to fill these 99926deccbSFrançois Tigeot */ 100926deccbSFrançois Tigeot static bool radeon_read_clocks_OF(struct drm_device *dev) 101926deccbSFrançois Tigeot { 102926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 103926deccbSFrançois Tigeot struct device_node *dp = rdev->pdev->dev.of_node; 104926deccbSFrançois Tigeot const u32 *val; 105926deccbSFrançois Tigeot struct radeon_pll *p1pll = &rdev->clock.p1pll; 106926deccbSFrançois Tigeot struct radeon_pll *p2pll = &rdev->clock.p2pll; 107926deccbSFrançois Tigeot struct radeon_pll *spll = &rdev->clock.spll; 108926deccbSFrançois Tigeot struct radeon_pll *mpll = &rdev->clock.mpll; 109926deccbSFrançois Tigeot 110926deccbSFrançois Tigeot if (dp == NULL) 111926deccbSFrançois Tigeot return false; 112926deccbSFrançois Tigeot val = of_get_property(dp, "ATY,RefCLK", NULL); 113926deccbSFrançois Tigeot if (!val || !*val) { 114926deccbSFrançois Tigeot printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n"); 115926deccbSFrançois Tigeot return false; 116926deccbSFrançois Tigeot } 117926deccbSFrançois Tigeot p1pll->reference_freq = p2pll->reference_freq = (*val) / 10; 118926deccbSFrançois Tigeot p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; 119926deccbSFrançois Tigeot if (p1pll->reference_div < 2) 120926deccbSFrançois Tigeot p1pll->reference_div = 12; 121926deccbSFrançois Tigeot p2pll->reference_div = p1pll->reference_div; 122926deccbSFrançois Tigeot 123926deccbSFrançois Tigeot /* These aren't in the device-tree */ 124926deccbSFrançois Tigeot if (rdev->family >= CHIP_R420) { 125926deccbSFrançois Tigeot p1pll->pll_in_min = 100; 126926deccbSFrançois Tigeot p1pll->pll_in_max = 1350; 127926deccbSFrançois Tigeot p1pll->pll_out_min = 20000; 128926deccbSFrançois Tigeot p1pll->pll_out_max = 50000; 129926deccbSFrançois Tigeot p2pll->pll_in_min = 100; 130926deccbSFrançois Tigeot p2pll->pll_in_max = 1350; 131926deccbSFrançois Tigeot p2pll->pll_out_min = 20000; 132926deccbSFrançois Tigeot p2pll->pll_out_max = 50000; 133926deccbSFrançois Tigeot } else { 134926deccbSFrançois Tigeot p1pll->pll_in_min = 40; 135926deccbSFrançois Tigeot p1pll->pll_in_max = 500; 136926deccbSFrançois Tigeot p1pll->pll_out_min = 12500; 137926deccbSFrançois Tigeot p1pll->pll_out_max = 35000; 138926deccbSFrançois Tigeot p2pll->pll_in_min = 40; 139926deccbSFrançois Tigeot p2pll->pll_in_max = 500; 140926deccbSFrançois Tigeot p2pll->pll_out_min = 12500; 141926deccbSFrançois Tigeot p2pll->pll_out_max = 35000; 142926deccbSFrançois Tigeot } 143926deccbSFrançois Tigeot /* not sure what the max should be in all cases */ 144926deccbSFrançois Tigeot rdev->clock.max_pixel_clock = 35000; 145926deccbSFrançois Tigeot 146926deccbSFrançois Tigeot spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; 147926deccbSFrançois Tigeot spll->reference_div = mpll->reference_div = 148926deccbSFrançois Tigeot RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & 149926deccbSFrançois Tigeot RADEON_M_SPLL_REF_DIV_MASK; 150926deccbSFrançois Tigeot 151926deccbSFrançois Tigeot val = of_get_property(dp, "ATY,SCLK", NULL); 152926deccbSFrançois Tigeot if (val && *val) 153926deccbSFrançois Tigeot rdev->clock.default_sclk = (*val) / 10; 154926deccbSFrançois Tigeot else 155926deccbSFrançois Tigeot rdev->clock.default_sclk = 156926deccbSFrançois Tigeot radeon_legacy_get_engine_clock(rdev); 157926deccbSFrançois Tigeot 158926deccbSFrançois Tigeot val = of_get_property(dp, "ATY,MCLK", NULL); 159926deccbSFrançois Tigeot if (val && *val) 160926deccbSFrançois Tigeot rdev->clock.default_mclk = (*val) / 10; 161926deccbSFrançois Tigeot else 162926deccbSFrançois Tigeot rdev->clock.default_mclk = 163926deccbSFrançois Tigeot radeon_legacy_get_memory_clock(rdev); 164926deccbSFrançois Tigeot 165926deccbSFrançois Tigeot DRM_INFO("Using device-tree clock info\n"); 166926deccbSFrançois Tigeot 167926deccbSFrançois Tigeot return true; 168926deccbSFrançois Tigeot } 169926deccbSFrançois Tigeot #else 170926deccbSFrançois Tigeot static bool radeon_read_clocks_OF(struct drm_device *dev) 171926deccbSFrançois Tigeot { 172926deccbSFrançois Tigeot return false; 173926deccbSFrançois Tigeot } 174926deccbSFrançois Tigeot #endif /* CONFIG_OF */ 175926deccbSFrançois Tigeot 176926deccbSFrançois Tigeot void radeon_get_clock_info(struct drm_device *dev) 177926deccbSFrançois Tigeot { 178926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 179926deccbSFrançois Tigeot struct radeon_pll *p1pll = &rdev->clock.p1pll; 180926deccbSFrançois Tigeot struct radeon_pll *p2pll = &rdev->clock.p2pll; 181926deccbSFrançois Tigeot struct radeon_pll *dcpll = &rdev->clock.dcpll; 182926deccbSFrançois Tigeot struct radeon_pll *spll = &rdev->clock.spll; 183926deccbSFrançois Tigeot struct radeon_pll *mpll = &rdev->clock.mpll; 184926deccbSFrançois Tigeot int ret; 185926deccbSFrançois Tigeot 186926deccbSFrançois Tigeot if (rdev->is_atom_bios) 187926deccbSFrançois Tigeot ret = radeon_atom_get_clock_info(dev); 188926deccbSFrançois Tigeot else 189926deccbSFrançois Tigeot ret = radeon_combios_get_clock_info(dev); 190926deccbSFrançois Tigeot if (!ret) 191926deccbSFrançois Tigeot ret = radeon_read_clocks_OF(dev); 192926deccbSFrançois Tigeot 193926deccbSFrançois Tigeot if (ret) { 194926deccbSFrançois Tigeot if (p1pll->reference_div < 2) { 195926deccbSFrançois Tigeot if (!ASIC_IS_AVIVO(rdev)) { 196926deccbSFrançois Tigeot u32 tmp = RREG32_PLL(RADEON_PPLL_REF_DIV); 197926deccbSFrançois Tigeot if (ASIC_IS_R300(rdev)) 198926deccbSFrançois Tigeot p1pll->reference_div = 199926deccbSFrançois Tigeot (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; 200926deccbSFrançois Tigeot else 201926deccbSFrançois Tigeot p1pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK; 202926deccbSFrançois Tigeot if (p1pll->reference_div < 2) 203926deccbSFrançois Tigeot p1pll->reference_div = 12; 204926deccbSFrançois Tigeot } else 205926deccbSFrançois Tigeot p1pll->reference_div = 12; 206926deccbSFrançois Tigeot } 207926deccbSFrançois Tigeot if (p2pll->reference_div < 2) 208926deccbSFrançois Tigeot p2pll->reference_div = 12; 209926deccbSFrançois Tigeot if (rdev->family < CHIP_RS600) { 210926deccbSFrançois Tigeot if (spll->reference_div < 2) 211926deccbSFrançois Tigeot spll->reference_div = 212926deccbSFrançois Tigeot RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & 213926deccbSFrançois Tigeot RADEON_M_SPLL_REF_DIV_MASK; 214926deccbSFrançois Tigeot } 215926deccbSFrançois Tigeot if (mpll->reference_div < 2) 216926deccbSFrançois Tigeot mpll->reference_div = spll->reference_div; 217926deccbSFrançois Tigeot } else { 218926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev)) { 219926deccbSFrançois Tigeot /* TODO FALLBACK */ 220926deccbSFrançois Tigeot } else { 221926deccbSFrançois Tigeot DRM_INFO("Using generic clock info\n"); 222926deccbSFrançois Tigeot 223926deccbSFrançois Tigeot /* may need to be per card */ 224926deccbSFrançois Tigeot rdev->clock.max_pixel_clock = 35000; 225926deccbSFrançois Tigeot 226926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_IGP) { 227926deccbSFrançois Tigeot p1pll->reference_freq = 1432; 228926deccbSFrançois Tigeot p2pll->reference_freq = 1432; 229926deccbSFrançois Tigeot spll->reference_freq = 1432; 230926deccbSFrançois Tigeot mpll->reference_freq = 1432; 231926deccbSFrançois Tigeot } else { 232926deccbSFrançois Tigeot p1pll->reference_freq = 2700; 233926deccbSFrançois Tigeot p2pll->reference_freq = 2700; 234926deccbSFrançois Tigeot spll->reference_freq = 2700; 235926deccbSFrançois Tigeot mpll->reference_freq = 2700; 236926deccbSFrançois Tigeot } 237926deccbSFrançois Tigeot p1pll->reference_div = 238926deccbSFrançois Tigeot RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; 239926deccbSFrançois Tigeot if (p1pll->reference_div < 2) 240926deccbSFrançois Tigeot p1pll->reference_div = 12; 241926deccbSFrançois Tigeot p2pll->reference_div = p1pll->reference_div; 242926deccbSFrançois Tigeot 243926deccbSFrançois Tigeot if (rdev->family >= CHIP_R420) { 244926deccbSFrançois Tigeot p1pll->pll_in_min = 100; 245926deccbSFrançois Tigeot p1pll->pll_in_max = 1350; 246926deccbSFrançois Tigeot p1pll->pll_out_min = 20000; 247926deccbSFrançois Tigeot p1pll->pll_out_max = 50000; 248926deccbSFrançois Tigeot p2pll->pll_in_min = 100; 249926deccbSFrançois Tigeot p2pll->pll_in_max = 1350; 250926deccbSFrançois Tigeot p2pll->pll_out_min = 20000; 251926deccbSFrançois Tigeot p2pll->pll_out_max = 50000; 252926deccbSFrançois Tigeot } else { 253926deccbSFrançois Tigeot p1pll->pll_in_min = 40; 254926deccbSFrançois Tigeot p1pll->pll_in_max = 500; 255926deccbSFrançois Tigeot p1pll->pll_out_min = 12500; 256926deccbSFrançois Tigeot p1pll->pll_out_max = 35000; 257926deccbSFrançois Tigeot p2pll->pll_in_min = 40; 258926deccbSFrançois Tigeot p2pll->pll_in_max = 500; 259926deccbSFrançois Tigeot p2pll->pll_out_min = 12500; 260926deccbSFrançois Tigeot p2pll->pll_out_max = 35000; 261926deccbSFrançois Tigeot } 262926deccbSFrançois Tigeot 263926deccbSFrançois Tigeot spll->reference_div = 264926deccbSFrançois Tigeot RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & 265926deccbSFrançois Tigeot RADEON_M_SPLL_REF_DIV_MASK; 266926deccbSFrançois Tigeot mpll->reference_div = spll->reference_div; 267926deccbSFrançois Tigeot rdev->clock.default_sclk = 268926deccbSFrançois Tigeot radeon_legacy_get_engine_clock(rdev); 269926deccbSFrançois Tigeot rdev->clock.default_mclk = 270926deccbSFrançois Tigeot radeon_legacy_get_memory_clock(rdev); 271926deccbSFrançois Tigeot } 272926deccbSFrançois Tigeot } 273926deccbSFrançois Tigeot 274926deccbSFrançois Tigeot /* pixel clocks */ 275926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev)) { 276926deccbSFrançois Tigeot p1pll->min_post_div = 2; 277926deccbSFrançois Tigeot p1pll->max_post_div = 0x7f; 278926deccbSFrançois Tigeot p1pll->min_frac_feedback_div = 0; 279926deccbSFrançois Tigeot p1pll->max_frac_feedback_div = 9; 280926deccbSFrançois Tigeot p2pll->min_post_div = 2; 281926deccbSFrançois Tigeot p2pll->max_post_div = 0x7f; 282926deccbSFrançois Tigeot p2pll->min_frac_feedback_div = 0; 283926deccbSFrançois Tigeot p2pll->max_frac_feedback_div = 9; 284926deccbSFrançois Tigeot } else { 285926deccbSFrançois Tigeot p1pll->min_post_div = 1; 286926deccbSFrançois Tigeot p1pll->max_post_div = 16; 287926deccbSFrançois Tigeot p1pll->min_frac_feedback_div = 0; 288926deccbSFrançois Tigeot p1pll->max_frac_feedback_div = 0; 289926deccbSFrançois Tigeot p2pll->min_post_div = 1; 290926deccbSFrançois Tigeot p2pll->max_post_div = 12; 291926deccbSFrançois Tigeot p2pll->min_frac_feedback_div = 0; 292926deccbSFrançois Tigeot p2pll->max_frac_feedback_div = 0; 293926deccbSFrançois Tigeot } 294926deccbSFrançois Tigeot 295926deccbSFrançois Tigeot /* dcpll is DCE4 only */ 296926deccbSFrançois Tigeot dcpll->min_post_div = 2; 297926deccbSFrançois Tigeot dcpll->max_post_div = 0x7f; 298926deccbSFrançois Tigeot dcpll->min_frac_feedback_div = 0; 299926deccbSFrançois Tigeot dcpll->max_frac_feedback_div = 9; 300926deccbSFrançois Tigeot dcpll->min_ref_div = 2; 301926deccbSFrançois Tigeot dcpll->max_ref_div = 0x3ff; 302926deccbSFrançois Tigeot dcpll->min_feedback_div = 4; 303926deccbSFrançois Tigeot dcpll->max_feedback_div = 0xfff; 304926deccbSFrançois Tigeot dcpll->best_vco = 0; 305926deccbSFrançois Tigeot 306926deccbSFrançois Tigeot p1pll->min_ref_div = 2; 307926deccbSFrançois Tigeot p1pll->max_ref_div = 0x3ff; 308926deccbSFrançois Tigeot p1pll->min_feedback_div = 4; 309926deccbSFrançois Tigeot p1pll->max_feedback_div = 0x7ff; 310926deccbSFrançois Tigeot p1pll->best_vco = 0; 311926deccbSFrançois Tigeot 312926deccbSFrançois Tigeot p2pll->min_ref_div = 2; 313926deccbSFrançois Tigeot p2pll->max_ref_div = 0x3ff; 314926deccbSFrançois Tigeot p2pll->min_feedback_div = 4; 315926deccbSFrançois Tigeot p2pll->max_feedback_div = 0x7ff; 316926deccbSFrançois Tigeot p2pll->best_vco = 0; 317926deccbSFrançois Tigeot 318926deccbSFrançois Tigeot /* system clock */ 319926deccbSFrançois Tigeot spll->min_post_div = 1; 320926deccbSFrançois Tigeot spll->max_post_div = 1; 321926deccbSFrançois Tigeot spll->min_ref_div = 2; 322926deccbSFrançois Tigeot spll->max_ref_div = 0xff; 323926deccbSFrançois Tigeot spll->min_feedback_div = 4; 324926deccbSFrançois Tigeot spll->max_feedback_div = 0xff; 325926deccbSFrançois Tigeot spll->best_vco = 0; 326926deccbSFrançois Tigeot 327926deccbSFrançois Tigeot /* memory clock */ 328926deccbSFrançois Tigeot mpll->min_post_div = 1; 329926deccbSFrançois Tigeot mpll->max_post_div = 1; 330926deccbSFrançois Tigeot mpll->min_ref_div = 2; 331926deccbSFrançois Tigeot mpll->max_ref_div = 0xff; 332926deccbSFrançois Tigeot mpll->min_feedback_div = 4; 333926deccbSFrançois Tigeot mpll->max_feedback_div = 0xff; 334926deccbSFrançois Tigeot mpll->best_vco = 0; 335926deccbSFrançois Tigeot 336926deccbSFrançois Tigeot if (!rdev->clock.default_sclk) 337926deccbSFrançois Tigeot rdev->clock.default_sclk = radeon_get_engine_clock(rdev); 338926deccbSFrançois Tigeot if ((!rdev->clock.default_mclk) && rdev->asic->pm.get_memory_clock) 339926deccbSFrançois Tigeot rdev->clock.default_mclk = radeon_get_memory_clock(rdev); 340926deccbSFrançois Tigeot 341926deccbSFrançois Tigeot rdev->pm.current_sclk = rdev->clock.default_sclk; 342926deccbSFrançois Tigeot rdev->pm.current_mclk = rdev->clock.default_mclk; 343926deccbSFrançois Tigeot 344926deccbSFrançois Tigeot } 345926deccbSFrançois Tigeot 346926deccbSFrançois Tigeot /* 10 khz */ 347926deccbSFrançois Tigeot static uint32_t calc_eng_mem_clock(struct radeon_device *rdev, 348926deccbSFrançois Tigeot uint32_t req_clock, 349926deccbSFrançois Tigeot int *fb_div, int *post_div) 350926deccbSFrançois Tigeot { 351926deccbSFrançois Tigeot struct radeon_pll *spll = &rdev->clock.spll; 352926deccbSFrançois Tigeot int ref_div = spll->reference_div; 353926deccbSFrançois Tigeot 354926deccbSFrançois Tigeot if (!ref_div) 355926deccbSFrançois Tigeot ref_div = 356926deccbSFrançois Tigeot RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & 357926deccbSFrançois Tigeot RADEON_M_SPLL_REF_DIV_MASK; 358926deccbSFrançois Tigeot 359926deccbSFrançois Tigeot if (req_clock < 15000) { 360926deccbSFrançois Tigeot *post_div = 8; 361926deccbSFrançois Tigeot req_clock *= 8; 362926deccbSFrançois Tigeot } else if (req_clock < 30000) { 363926deccbSFrançois Tigeot *post_div = 4; 364926deccbSFrançois Tigeot req_clock *= 4; 365926deccbSFrançois Tigeot } else if (req_clock < 60000) { 366926deccbSFrançois Tigeot *post_div = 2; 367926deccbSFrançois Tigeot req_clock *= 2; 368926deccbSFrançois Tigeot } else 369926deccbSFrançois Tigeot *post_div = 1; 370926deccbSFrançois Tigeot 371926deccbSFrançois Tigeot req_clock *= ref_div; 372926deccbSFrançois Tigeot req_clock += spll->reference_freq; 373926deccbSFrançois Tigeot req_clock /= (2 * spll->reference_freq); 374926deccbSFrançois Tigeot 375926deccbSFrançois Tigeot *fb_div = req_clock & 0xff; 376926deccbSFrançois Tigeot 377926deccbSFrançois Tigeot req_clock = (req_clock & 0xffff) << 1; 378926deccbSFrançois Tigeot req_clock *= spll->reference_freq; 379926deccbSFrançois Tigeot req_clock /= ref_div; 380926deccbSFrançois Tigeot req_clock /= *post_div; 381926deccbSFrançois Tigeot 382926deccbSFrançois Tigeot return req_clock; 383926deccbSFrançois Tigeot } 384926deccbSFrançois Tigeot 385926deccbSFrançois Tigeot /* 10 khz */ 386926deccbSFrançois Tigeot void radeon_legacy_set_engine_clock(struct radeon_device *rdev, 387926deccbSFrançois Tigeot uint32_t eng_clock) 388926deccbSFrançois Tigeot { 389926deccbSFrançois Tigeot uint32_t tmp; 390926deccbSFrançois Tigeot int fb_div, post_div; 391926deccbSFrançois Tigeot 392926deccbSFrançois Tigeot /* XXX: wait for idle */ 393926deccbSFrançois Tigeot 394926deccbSFrançois Tigeot eng_clock = calc_eng_mem_clock(rdev, eng_clock, &fb_div, &post_div); 395926deccbSFrançois Tigeot 396926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); 397926deccbSFrançois Tigeot tmp &= ~RADEON_DONT_USE_XTALIN; 398926deccbSFrançois Tigeot WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); 399926deccbSFrançois Tigeot 400926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 401926deccbSFrançois Tigeot tmp &= ~RADEON_SCLK_SRC_SEL_MASK; 402926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 403926deccbSFrançois Tigeot 404c4ef309bSzrj udelay(10); 405926deccbSFrançois Tigeot 406926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SPLL_CNTL); 407926deccbSFrançois Tigeot tmp |= RADEON_SPLL_SLEEP; 408926deccbSFrançois Tigeot WREG32_PLL(RADEON_SPLL_CNTL, tmp); 409926deccbSFrançois Tigeot 410c4ef309bSzrj udelay(2); 411926deccbSFrançois Tigeot 412926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SPLL_CNTL); 413926deccbSFrançois Tigeot tmp |= RADEON_SPLL_RESET; 414926deccbSFrançois Tigeot WREG32_PLL(RADEON_SPLL_CNTL, tmp); 415926deccbSFrançois Tigeot 416c4ef309bSzrj udelay(200); 417926deccbSFrançois Tigeot 418926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); 419926deccbSFrançois Tigeot tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT); 420926deccbSFrançois Tigeot tmp |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT; 421926deccbSFrançois Tigeot WREG32_PLL(RADEON_M_SPLL_REF_FB_DIV, tmp); 422926deccbSFrançois Tigeot 423926deccbSFrançois Tigeot /* XXX: verify on different asics */ 424926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SPLL_CNTL); 425926deccbSFrançois Tigeot tmp &= ~RADEON_SPLL_PVG_MASK; 426926deccbSFrançois Tigeot if ((eng_clock * post_div) >= 90000) 427926deccbSFrançois Tigeot tmp |= (0x7 << RADEON_SPLL_PVG_SHIFT); 428926deccbSFrançois Tigeot else 429926deccbSFrançois Tigeot tmp |= (0x4 << RADEON_SPLL_PVG_SHIFT); 430926deccbSFrançois Tigeot WREG32_PLL(RADEON_SPLL_CNTL, tmp); 431926deccbSFrançois Tigeot 432926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SPLL_CNTL); 433926deccbSFrançois Tigeot tmp &= ~RADEON_SPLL_SLEEP; 434926deccbSFrançois Tigeot WREG32_PLL(RADEON_SPLL_CNTL, tmp); 435926deccbSFrançois Tigeot 436c4ef309bSzrj udelay(2); 437926deccbSFrançois Tigeot 438926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SPLL_CNTL); 439926deccbSFrançois Tigeot tmp &= ~RADEON_SPLL_RESET; 440926deccbSFrançois Tigeot WREG32_PLL(RADEON_SPLL_CNTL, tmp); 441926deccbSFrançois Tigeot 442c4ef309bSzrj udelay(200); 443926deccbSFrançois Tigeot 444926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 445926deccbSFrançois Tigeot tmp &= ~RADEON_SCLK_SRC_SEL_MASK; 446926deccbSFrançois Tigeot switch (post_div) { 447926deccbSFrançois Tigeot case 1: 448926deccbSFrançois Tigeot default: 449926deccbSFrançois Tigeot tmp |= 1; 450926deccbSFrançois Tigeot break; 451926deccbSFrançois Tigeot case 2: 452926deccbSFrançois Tigeot tmp |= 2; 453926deccbSFrançois Tigeot break; 454926deccbSFrançois Tigeot case 4: 455926deccbSFrançois Tigeot tmp |= 3; 456926deccbSFrançois Tigeot break; 457926deccbSFrançois Tigeot case 8: 458926deccbSFrançois Tigeot tmp |= 4; 459926deccbSFrançois Tigeot break; 460926deccbSFrançois Tigeot } 461926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 462926deccbSFrançois Tigeot 463c4ef309bSzrj udelay(20); 464926deccbSFrançois Tigeot 465926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); 466926deccbSFrançois Tigeot tmp |= RADEON_DONT_USE_XTALIN; 467926deccbSFrançois Tigeot WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); 468926deccbSFrançois Tigeot 469c4ef309bSzrj udelay(10); 470926deccbSFrançois Tigeot } 471926deccbSFrançois Tigeot 472926deccbSFrançois Tigeot void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) 473926deccbSFrançois Tigeot { 474926deccbSFrançois Tigeot uint32_t tmp; 475926deccbSFrançois Tigeot 476926deccbSFrançois Tigeot if (enable) { 477926deccbSFrançois Tigeot if (rdev->flags & RADEON_SINGLE_CRTC) { 478926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 479926deccbSFrançois Tigeot if ((RREG32(RADEON_CONFIG_CNTL) & 480926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_ID_MASK) > 481926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_A13) { 482926deccbSFrançois Tigeot tmp &= 483926deccbSFrançois Tigeot ~(RADEON_SCLK_FORCE_CP | 484926deccbSFrançois Tigeot RADEON_SCLK_FORCE_RB); 485926deccbSFrançois Tigeot } 486926deccbSFrançois Tigeot tmp &= 487926deccbSFrançois Tigeot ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | 488926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE | 489926deccbSFrançois Tigeot RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE | 490926deccbSFrançois Tigeot RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM | 491926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TDM); 492926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 493926deccbSFrançois Tigeot } else if (ASIC_IS_R300(rdev)) { 494926deccbSFrançois Tigeot if ((rdev->family == CHIP_RS400) || 495926deccbSFrançois Tigeot (rdev->family == CHIP_RS480)) { 496926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 497926deccbSFrançois Tigeot tmp &= 498926deccbSFrançois Tigeot ~(RADEON_SCLK_FORCE_DISP2 | 499926deccbSFrançois Tigeot RADEON_SCLK_FORCE_CP | 500926deccbSFrançois Tigeot RADEON_SCLK_FORCE_HDP | 501926deccbSFrançois Tigeot RADEON_SCLK_FORCE_DISP1 | 502926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TOP | 503926deccbSFrançois Tigeot RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP 504926deccbSFrançois Tigeot | RADEON_SCLK_FORCE_IDCT | 505926deccbSFrançois Tigeot RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR 506926deccbSFrançois Tigeot | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX 507926deccbSFrançois Tigeot | R300_SCLK_FORCE_US | 508926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TV_SCLK | 509926deccbSFrançois Tigeot R300_SCLK_FORCE_SU | 510926deccbSFrançois Tigeot RADEON_SCLK_FORCE_OV0); 511926deccbSFrançois Tigeot tmp |= RADEON_DYN_STOP_LAT_MASK; 512926deccbSFrançois Tigeot tmp |= 513926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TOP | 514926deccbSFrançois Tigeot RADEON_SCLK_FORCE_VIP; 515926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 516926deccbSFrançois Tigeot 517926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); 518926deccbSFrançois Tigeot tmp &= ~RADEON_SCLK_MORE_FORCEON; 519926deccbSFrançois Tigeot tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; 520926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); 521926deccbSFrançois Tigeot 522926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); 523926deccbSFrançois Tigeot tmp |= (RADEON_PIXCLK_ALWAYS_ONb | 524926deccbSFrançois Tigeot RADEON_PIXCLK_DAC_ALWAYS_ONb); 525926deccbSFrançois Tigeot WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); 526926deccbSFrançois Tigeot 527926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); 528926deccbSFrançois Tigeot tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | 529926deccbSFrançois Tigeot RADEON_PIX2CLK_DAC_ALWAYS_ONb | 530926deccbSFrançois Tigeot RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | 531926deccbSFrançois Tigeot R300_DVOCLK_ALWAYS_ONb | 532926deccbSFrançois Tigeot RADEON_PIXCLK_BLEND_ALWAYS_ONb | 533926deccbSFrançois Tigeot RADEON_PIXCLK_GV_ALWAYS_ONb | 534926deccbSFrançois Tigeot R300_PIXCLK_DVO_ALWAYS_ONb | 535926deccbSFrançois Tigeot RADEON_PIXCLK_LVDS_ALWAYS_ONb | 536926deccbSFrançois Tigeot RADEON_PIXCLK_TMDS_ALWAYS_ONb | 537926deccbSFrançois Tigeot R300_PIXCLK_TRANS_ALWAYS_ONb | 538926deccbSFrançois Tigeot R300_PIXCLK_TVO_ALWAYS_ONb | 539926deccbSFrançois Tigeot R300_P2G2CLK_ALWAYS_ONb | 540926deccbSFrançois Tigeot R300_P2G2CLK_DAC_ALWAYS_ONb); 541926deccbSFrançois Tigeot WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); 542926deccbSFrançois Tigeot } else if (rdev->family >= CHIP_RV350) { 543926deccbSFrançois Tigeot tmp = RREG32_PLL(R300_SCLK_CNTL2); 544926deccbSFrançois Tigeot tmp &= ~(R300_SCLK_FORCE_TCL | 545926deccbSFrançois Tigeot R300_SCLK_FORCE_GA | 546926deccbSFrançois Tigeot R300_SCLK_FORCE_CBA); 547926deccbSFrançois Tigeot tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT | 548926deccbSFrançois Tigeot R300_SCLK_GA_MAX_DYN_STOP_LAT | 549926deccbSFrançois Tigeot R300_SCLK_CBA_MAX_DYN_STOP_LAT); 550926deccbSFrançois Tigeot WREG32_PLL(R300_SCLK_CNTL2, tmp); 551926deccbSFrançois Tigeot 552926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 553926deccbSFrançois Tigeot tmp &= 554926deccbSFrançois Tigeot ~(RADEON_SCLK_FORCE_DISP2 | 555926deccbSFrançois Tigeot RADEON_SCLK_FORCE_CP | 556926deccbSFrançois Tigeot RADEON_SCLK_FORCE_HDP | 557926deccbSFrançois Tigeot RADEON_SCLK_FORCE_DISP1 | 558926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TOP | 559926deccbSFrançois Tigeot RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP 560926deccbSFrançois Tigeot | RADEON_SCLK_FORCE_IDCT | 561926deccbSFrançois Tigeot RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR 562926deccbSFrançois Tigeot | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX 563926deccbSFrançois Tigeot | R300_SCLK_FORCE_US | 564926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TV_SCLK | 565926deccbSFrançois Tigeot R300_SCLK_FORCE_SU | 566926deccbSFrançois Tigeot RADEON_SCLK_FORCE_OV0); 567926deccbSFrançois Tigeot tmp |= RADEON_DYN_STOP_LAT_MASK; 568926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 569926deccbSFrançois Tigeot 570926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); 571926deccbSFrançois Tigeot tmp &= ~RADEON_SCLK_MORE_FORCEON; 572926deccbSFrançois Tigeot tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; 573926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); 574926deccbSFrançois Tigeot 575926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); 576926deccbSFrançois Tigeot tmp |= (RADEON_PIXCLK_ALWAYS_ONb | 577926deccbSFrançois Tigeot RADEON_PIXCLK_DAC_ALWAYS_ONb); 578926deccbSFrançois Tigeot WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); 579926deccbSFrançois Tigeot 580926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); 581926deccbSFrançois Tigeot tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | 582926deccbSFrançois Tigeot RADEON_PIX2CLK_DAC_ALWAYS_ONb | 583926deccbSFrançois Tigeot RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | 584926deccbSFrançois Tigeot R300_DVOCLK_ALWAYS_ONb | 585926deccbSFrançois Tigeot RADEON_PIXCLK_BLEND_ALWAYS_ONb | 586926deccbSFrançois Tigeot RADEON_PIXCLK_GV_ALWAYS_ONb | 587926deccbSFrançois Tigeot R300_PIXCLK_DVO_ALWAYS_ONb | 588926deccbSFrançois Tigeot RADEON_PIXCLK_LVDS_ALWAYS_ONb | 589926deccbSFrançois Tigeot RADEON_PIXCLK_TMDS_ALWAYS_ONb | 590926deccbSFrançois Tigeot R300_PIXCLK_TRANS_ALWAYS_ONb | 591926deccbSFrançois Tigeot R300_PIXCLK_TVO_ALWAYS_ONb | 592926deccbSFrançois Tigeot R300_P2G2CLK_ALWAYS_ONb | 593926deccbSFrançois Tigeot R300_P2G2CLK_DAC_ALWAYS_ONb); 594926deccbSFrançois Tigeot WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); 595926deccbSFrançois Tigeot 596926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_MCLK_MISC); 597926deccbSFrançois Tigeot tmp |= (RADEON_MC_MCLK_DYN_ENABLE | 598926deccbSFrançois Tigeot RADEON_IO_MCLK_DYN_ENABLE); 599926deccbSFrançois Tigeot WREG32_PLL(RADEON_MCLK_MISC, tmp); 600926deccbSFrançois Tigeot 601926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_MCLK_CNTL); 602926deccbSFrançois Tigeot tmp |= (RADEON_FORCEON_MCLKA | 603926deccbSFrançois Tigeot RADEON_FORCEON_MCLKB); 604926deccbSFrançois Tigeot 605926deccbSFrançois Tigeot tmp &= ~(RADEON_FORCEON_YCLKA | 606926deccbSFrançois Tigeot RADEON_FORCEON_YCLKB | 607926deccbSFrançois Tigeot RADEON_FORCEON_MC); 608926deccbSFrançois Tigeot 609926deccbSFrançois Tigeot /* Some releases of vbios have set DISABLE_MC_MCLKA 610926deccbSFrançois Tigeot and DISABLE_MC_MCLKB bits in the vbios table. Setting these 611926deccbSFrançois Tigeot bits will cause H/W hang when reading video memory with dynamic clocking 612926deccbSFrançois Tigeot enabled. */ 613926deccbSFrançois Tigeot if ((tmp & R300_DISABLE_MC_MCLKA) && 614926deccbSFrançois Tigeot (tmp & R300_DISABLE_MC_MCLKB)) { 615926deccbSFrançois Tigeot /* If both bits are set, then check the active channels */ 616926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_MCLK_CNTL); 617926deccbSFrançois Tigeot if (rdev->mc.vram_width == 64) { 618926deccbSFrançois Tigeot if (RREG32(RADEON_MEM_CNTL) & 619926deccbSFrançois Tigeot R300_MEM_USE_CD_CH_ONLY) 620926deccbSFrançois Tigeot tmp &= 621926deccbSFrançois Tigeot ~R300_DISABLE_MC_MCLKB; 622926deccbSFrançois Tigeot else 623926deccbSFrançois Tigeot tmp &= 624926deccbSFrançois Tigeot ~R300_DISABLE_MC_MCLKA; 625926deccbSFrançois Tigeot } else { 626926deccbSFrançois Tigeot tmp &= ~(R300_DISABLE_MC_MCLKA | 627926deccbSFrançois Tigeot R300_DISABLE_MC_MCLKB); 628926deccbSFrançois Tigeot } 629926deccbSFrançois Tigeot } 630926deccbSFrançois Tigeot 631926deccbSFrançois Tigeot WREG32_PLL(RADEON_MCLK_CNTL, tmp); 632926deccbSFrançois Tigeot } else { 633926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 634926deccbSFrançois Tigeot tmp &= ~(R300_SCLK_FORCE_VAP); 635926deccbSFrançois Tigeot tmp |= RADEON_SCLK_FORCE_CP; 636926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 637c4ef309bSzrj mdelay(15); 638926deccbSFrançois Tigeot 639926deccbSFrançois Tigeot tmp = RREG32_PLL(R300_SCLK_CNTL2); 640926deccbSFrançois Tigeot tmp &= ~(R300_SCLK_FORCE_TCL | 641926deccbSFrançois Tigeot R300_SCLK_FORCE_GA | 642926deccbSFrançois Tigeot R300_SCLK_FORCE_CBA); 643926deccbSFrançois Tigeot WREG32_PLL(R300_SCLK_CNTL2, tmp); 644926deccbSFrançois Tigeot } 645926deccbSFrançois Tigeot } else { 646926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_CLK_PWRMGT_CNTL); 647926deccbSFrançois Tigeot 648926deccbSFrançois Tigeot tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK | 649926deccbSFrançois Tigeot RADEON_DISP_DYN_STOP_LAT_MASK | 650926deccbSFrançois Tigeot RADEON_DYN_STOP_MODE_MASK); 651926deccbSFrançois Tigeot 652926deccbSFrançois Tigeot tmp |= (RADEON_ENGIN_DYNCLK_MODE | 653926deccbSFrançois Tigeot (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); 654926deccbSFrançois Tigeot WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp); 655c4ef309bSzrj mdelay(15); 656926deccbSFrançois Tigeot 657926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); 658926deccbSFrançois Tigeot tmp |= RADEON_SCLK_DYN_START_CNTL; 659926deccbSFrançois Tigeot WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); 660c4ef309bSzrj mdelay(15); 661926deccbSFrançois Tigeot 662926deccbSFrançois Tigeot /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 663926deccbSFrançois Tigeot to lockup randomly, leave them as set by BIOS. 664926deccbSFrançois Tigeot */ 665926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 666926deccbSFrançois Tigeot /*tmp &= RADEON_SCLK_SRC_SEL_MASK; */ 667926deccbSFrançois Tigeot tmp &= ~RADEON_SCLK_FORCEON_MASK; 668926deccbSFrançois Tigeot 669926deccbSFrançois Tigeot /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300 */ 670926deccbSFrançois Tigeot if (((rdev->family == CHIP_RV250) && 671926deccbSFrançois Tigeot ((RREG32(RADEON_CONFIG_CNTL) & 672926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_ID_MASK) < 673926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_A13)) 674926deccbSFrançois Tigeot || ((rdev->family == CHIP_RV100) 675926deccbSFrançois Tigeot && 676926deccbSFrançois Tigeot ((RREG32(RADEON_CONFIG_CNTL) & 677926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_ID_MASK) <= 678926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_A13))) { 679926deccbSFrançois Tigeot tmp |= RADEON_SCLK_FORCE_CP; 680926deccbSFrançois Tigeot tmp |= RADEON_SCLK_FORCE_VIP; 681926deccbSFrançois Tigeot } 682926deccbSFrançois Tigeot 683926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 684926deccbSFrançois Tigeot 685926deccbSFrançois Tigeot if ((rdev->family == CHIP_RV200) || 686926deccbSFrançois Tigeot (rdev->family == CHIP_RV250) || 687926deccbSFrançois Tigeot (rdev->family == CHIP_RV280)) { 688926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); 689926deccbSFrançois Tigeot tmp &= ~RADEON_SCLK_MORE_FORCEON; 690926deccbSFrançois Tigeot 691926deccbSFrançois Tigeot /* RV200::A11 A12 RV250::A11 A12 */ 692926deccbSFrançois Tigeot if (((rdev->family == CHIP_RV200) || 693926deccbSFrançois Tigeot (rdev->family == CHIP_RV250)) && 694926deccbSFrançois Tigeot ((RREG32(RADEON_CONFIG_CNTL) & 695926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_ID_MASK) < 696926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_A13)) { 697926deccbSFrançois Tigeot tmp |= RADEON_SCLK_MORE_FORCEON; 698926deccbSFrançois Tigeot } 699926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); 700c4ef309bSzrj mdelay(15); 701926deccbSFrançois Tigeot } 702926deccbSFrançois Tigeot 703926deccbSFrançois Tigeot /* RV200::A11 A12, RV250::A11 A12 */ 704926deccbSFrançois Tigeot if (((rdev->family == CHIP_RV200) || 705926deccbSFrançois Tigeot (rdev->family == CHIP_RV250)) && 706926deccbSFrançois Tigeot ((RREG32(RADEON_CONFIG_CNTL) & 707926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_ID_MASK) < 708926deccbSFrançois Tigeot RADEON_CFG_ATI_REV_A13)) { 709926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL); 710926deccbSFrançois Tigeot tmp |= RADEON_TCL_BYPASS_DISABLE; 711926deccbSFrançois Tigeot WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); 712926deccbSFrançois Tigeot } 713c4ef309bSzrj mdelay(15); 714926deccbSFrançois Tigeot 715926deccbSFrançois Tigeot /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */ 716926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); 717926deccbSFrançois Tigeot tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | 718926deccbSFrançois Tigeot RADEON_PIX2CLK_DAC_ALWAYS_ONb | 719926deccbSFrançois Tigeot RADEON_PIXCLK_BLEND_ALWAYS_ONb | 720926deccbSFrançois Tigeot RADEON_PIXCLK_GV_ALWAYS_ONb | 721926deccbSFrançois Tigeot RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | 722926deccbSFrançois Tigeot RADEON_PIXCLK_LVDS_ALWAYS_ONb | 723926deccbSFrançois Tigeot RADEON_PIXCLK_TMDS_ALWAYS_ONb); 724926deccbSFrançois Tigeot 725926deccbSFrançois Tigeot WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); 726c4ef309bSzrj mdelay(15); 727926deccbSFrançois Tigeot 728926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); 729926deccbSFrançois Tigeot tmp |= (RADEON_PIXCLK_ALWAYS_ONb | 730926deccbSFrançois Tigeot RADEON_PIXCLK_DAC_ALWAYS_ONb); 731926deccbSFrançois Tigeot 732926deccbSFrançois Tigeot WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); 733c4ef309bSzrj mdelay(15); 734926deccbSFrançois Tigeot } 735926deccbSFrançois Tigeot } else { 736926deccbSFrançois Tigeot /* Turn everything OFF (ForceON to everything) */ 737926deccbSFrançois Tigeot if (rdev->flags & RADEON_SINGLE_CRTC) { 738926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 739926deccbSFrançois Tigeot tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP | 740926deccbSFrançois Tigeot RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP 741926deccbSFrançois Tigeot | RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE | 742926deccbSFrançois Tigeot RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP | 743926deccbSFrançois Tigeot RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB | 744926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM | 745926deccbSFrançois Tigeot RADEON_SCLK_FORCE_RB); 746926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 747926deccbSFrançois Tigeot } else if ((rdev->family == CHIP_RS400) || 748926deccbSFrançois Tigeot (rdev->family == CHIP_RS480)) { 749926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 750926deccbSFrançois Tigeot tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | 751926deccbSFrançois Tigeot RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 752926deccbSFrançois Tigeot | RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | 753926deccbSFrançois Tigeot R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | 754926deccbSFrançois Tigeot RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | 755926deccbSFrançois Tigeot R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | 756926deccbSFrançois Tigeot R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | 757926deccbSFrançois Tigeot R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); 758926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 759926deccbSFrançois Tigeot 760926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); 761926deccbSFrançois Tigeot tmp |= RADEON_SCLK_MORE_FORCEON; 762926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); 763926deccbSFrançois Tigeot 764926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); 765926deccbSFrançois Tigeot tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | 766926deccbSFrançois Tigeot RADEON_PIXCLK_DAC_ALWAYS_ONb | 767926deccbSFrançois Tigeot R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); 768926deccbSFrançois Tigeot WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); 769926deccbSFrançois Tigeot 770926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); 771926deccbSFrançois Tigeot tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | 772926deccbSFrançois Tigeot RADEON_PIX2CLK_DAC_ALWAYS_ONb | 773926deccbSFrançois Tigeot RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | 774926deccbSFrançois Tigeot R300_DVOCLK_ALWAYS_ONb | 775926deccbSFrançois Tigeot RADEON_PIXCLK_BLEND_ALWAYS_ONb | 776926deccbSFrançois Tigeot RADEON_PIXCLK_GV_ALWAYS_ONb | 777926deccbSFrançois Tigeot R300_PIXCLK_DVO_ALWAYS_ONb | 778926deccbSFrançois Tigeot RADEON_PIXCLK_LVDS_ALWAYS_ONb | 779926deccbSFrançois Tigeot RADEON_PIXCLK_TMDS_ALWAYS_ONb | 780926deccbSFrançois Tigeot R300_PIXCLK_TRANS_ALWAYS_ONb | 781926deccbSFrançois Tigeot R300_PIXCLK_TVO_ALWAYS_ONb | 782926deccbSFrançois Tigeot R300_P2G2CLK_ALWAYS_ONb | 783926deccbSFrançois Tigeot R300_P2G2CLK_DAC_ALWAYS_ONb | 784926deccbSFrançois Tigeot R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); 785926deccbSFrançois Tigeot WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); 786926deccbSFrançois Tigeot } else if (rdev->family >= CHIP_RV350) { 787926deccbSFrançois Tigeot /* for RV350/M10, no delays are required. */ 788926deccbSFrançois Tigeot tmp = RREG32_PLL(R300_SCLK_CNTL2); 789926deccbSFrançois Tigeot tmp |= (R300_SCLK_FORCE_TCL | 790926deccbSFrançois Tigeot R300_SCLK_FORCE_GA | R300_SCLK_FORCE_CBA); 791926deccbSFrançois Tigeot WREG32_PLL(R300_SCLK_CNTL2, tmp); 792926deccbSFrançois Tigeot 793926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 794926deccbSFrançois Tigeot tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | 795926deccbSFrançois Tigeot RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 796926deccbSFrançois Tigeot | RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | 797926deccbSFrançois Tigeot R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | 798926deccbSFrançois Tigeot RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | 799926deccbSFrançois Tigeot R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | 800926deccbSFrançois Tigeot R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | 801926deccbSFrançois Tigeot R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); 802926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 803926deccbSFrançois Tigeot 804926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); 805926deccbSFrançois Tigeot tmp |= RADEON_SCLK_MORE_FORCEON; 806926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); 807926deccbSFrançois Tigeot 808926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_MCLK_CNTL); 809926deccbSFrançois Tigeot tmp |= (RADEON_FORCEON_MCLKA | 810926deccbSFrançois Tigeot RADEON_FORCEON_MCLKB | 811926deccbSFrançois Tigeot RADEON_FORCEON_YCLKA | 812926deccbSFrançois Tigeot RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC); 813926deccbSFrançois Tigeot WREG32_PLL(RADEON_MCLK_CNTL, tmp); 814926deccbSFrançois Tigeot 815926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); 816926deccbSFrançois Tigeot tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | 817926deccbSFrançois Tigeot RADEON_PIXCLK_DAC_ALWAYS_ONb | 818926deccbSFrançois Tigeot R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); 819926deccbSFrançois Tigeot WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); 820926deccbSFrançois Tigeot 821926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); 822926deccbSFrançois Tigeot tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | 823926deccbSFrançois Tigeot RADEON_PIX2CLK_DAC_ALWAYS_ONb | 824926deccbSFrançois Tigeot RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | 825926deccbSFrançois Tigeot R300_DVOCLK_ALWAYS_ONb | 826926deccbSFrançois Tigeot RADEON_PIXCLK_BLEND_ALWAYS_ONb | 827926deccbSFrançois Tigeot RADEON_PIXCLK_GV_ALWAYS_ONb | 828926deccbSFrançois Tigeot R300_PIXCLK_DVO_ALWAYS_ONb | 829926deccbSFrançois Tigeot RADEON_PIXCLK_LVDS_ALWAYS_ONb | 830926deccbSFrançois Tigeot RADEON_PIXCLK_TMDS_ALWAYS_ONb | 831926deccbSFrançois Tigeot R300_PIXCLK_TRANS_ALWAYS_ONb | 832926deccbSFrançois Tigeot R300_PIXCLK_TVO_ALWAYS_ONb | 833926deccbSFrançois Tigeot R300_P2G2CLK_ALWAYS_ONb | 834926deccbSFrançois Tigeot R300_P2G2CLK_DAC_ALWAYS_ONb | 835926deccbSFrançois Tigeot R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); 836926deccbSFrançois Tigeot WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); 837926deccbSFrançois Tigeot } else { 838926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_CNTL); 839926deccbSFrançois Tigeot tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2); 840926deccbSFrançois Tigeot tmp |= RADEON_SCLK_FORCE_SE; 841926deccbSFrançois Tigeot 842926deccbSFrançois Tigeot if (rdev->flags & RADEON_SINGLE_CRTC) { 843926deccbSFrançois Tigeot tmp |= (RADEON_SCLK_FORCE_RB | 844926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TDM | 845926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TAM | 846926deccbSFrançois Tigeot RADEON_SCLK_FORCE_PB | 847926deccbSFrançois Tigeot RADEON_SCLK_FORCE_RE | 848926deccbSFrançois Tigeot RADEON_SCLK_FORCE_VIP | 849926deccbSFrançois Tigeot RADEON_SCLK_FORCE_IDCT | 850926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TOP | 851926deccbSFrançois Tigeot RADEON_SCLK_FORCE_DISP1 | 852926deccbSFrançois Tigeot RADEON_SCLK_FORCE_DISP2 | 853926deccbSFrançois Tigeot RADEON_SCLK_FORCE_HDP); 854926deccbSFrançois Tigeot } else if ((rdev->family == CHIP_R300) || 855926deccbSFrançois Tigeot (rdev->family == CHIP_R350)) { 856926deccbSFrançois Tigeot tmp |= (RADEON_SCLK_FORCE_HDP | 857926deccbSFrançois Tigeot RADEON_SCLK_FORCE_DISP1 | 858926deccbSFrançois Tigeot RADEON_SCLK_FORCE_DISP2 | 859926deccbSFrançois Tigeot RADEON_SCLK_FORCE_TOP | 860926deccbSFrançois Tigeot RADEON_SCLK_FORCE_IDCT | 861926deccbSFrançois Tigeot RADEON_SCLK_FORCE_VIP); 862926deccbSFrançois Tigeot } 863926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_CNTL, tmp); 864926deccbSFrançois Tigeot 865c4ef309bSzrj mdelay(16); 866926deccbSFrançois Tigeot 867926deccbSFrançois Tigeot if ((rdev->family == CHIP_R300) || 868926deccbSFrançois Tigeot (rdev->family == CHIP_R350)) { 869926deccbSFrançois Tigeot tmp = RREG32_PLL(R300_SCLK_CNTL2); 870926deccbSFrançois Tigeot tmp |= (R300_SCLK_FORCE_TCL | 871926deccbSFrançois Tigeot R300_SCLK_FORCE_GA | 872926deccbSFrançois Tigeot R300_SCLK_FORCE_CBA); 873926deccbSFrançois Tigeot WREG32_PLL(R300_SCLK_CNTL2, tmp); 874c4ef309bSzrj mdelay(16); 875926deccbSFrançois Tigeot } 876926deccbSFrançois Tigeot 877926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_IGP) { 878926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_MCLK_CNTL); 879926deccbSFrançois Tigeot tmp &= ~(RADEON_FORCEON_MCLKA | 880926deccbSFrançois Tigeot RADEON_FORCEON_YCLKA); 881926deccbSFrançois Tigeot WREG32_PLL(RADEON_MCLK_CNTL, tmp); 882c4ef309bSzrj mdelay(16); 883926deccbSFrançois Tigeot } 884926deccbSFrançois Tigeot 885926deccbSFrançois Tigeot if ((rdev->family == CHIP_RV200) || 886926deccbSFrançois Tigeot (rdev->family == CHIP_RV250) || 887926deccbSFrançois Tigeot (rdev->family == CHIP_RV280)) { 888926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); 889926deccbSFrançois Tigeot tmp |= RADEON_SCLK_MORE_FORCEON; 890926deccbSFrançois Tigeot WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); 891c4ef309bSzrj mdelay(16); 892926deccbSFrançois Tigeot } 893926deccbSFrançois Tigeot 894926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); 895926deccbSFrançois Tigeot tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | 896926deccbSFrançois Tigeot RADEON_PIX2CLK_DAC_ALWAYS_ONb | 897926deccbSFrançois Tigeot RADEON_PIXCLK_BLEND_ALWAYS_ONb | 898926deccbSFrançois Tigeot RADEON_PIXCLK_GV_ALWAYS_ONb | 899926deccbSFrançois Tigeot RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | 900926deccbSFrançois Tigeot RADEON_PIXCLK_LVDS_ALWAYS_ONb | 901926deccbSFrançois Tigeot RADEON_PIXCLK_TMDS_ALWAYS_ONb); 902926deccbSFrançois Tigeot 903926deccbSFrançois Tigeot WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); 904c4ef309bSzrj mdelay(16); 905926deccbSFrançois Tigeot 906926deccbSFrançois Tigeot tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); 907926deccbSFrançois Tigeot tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | 908926deccbSFrançois Tigeot RADEON_PIXCLK_DAC_ALWAYS_ONb); 909926deccbSFrançois Tigeot WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); 910926deccbSFrançois Tigeot } 911926deccbSFrançois Tigeot } 912926deccbSFrançois Tigeot } 913926deccbSFrançois Tigeot 914