18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc. 48c2ecf20Sopenharmony_ci * Copyright 2009 Jerome Glisse. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Authors: Dave Airlie 258c2ecf20Sopenharmony_ci * Alex Deucher 268c2ecf20Sopenharmony_ci * Jerome Glisse 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <linux/firmware.h> 308c2ecf20Sopenharmony_ci#include <linux/module.h> 318c2ecf20Sopenharmony_ci#include <linux/pci.h> 328c2ecf20Sopenharmony_ci#include <linux/slab.h> 338c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <drm/drm_debugfs.h> 368c2ecf20Sopenharmony_ci#include <drm/drm_device.h> 378c2ecf20Sopenharmony_ci#include <drm/drm_vblank.h> 388c2ecf20Sopenharmony_ci#include <drm/radeon_drm.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#include "atom.h" 418c2ecf20Sopenharmony_ci#include "avivod.h" 428c2ecf20Sopenharmony_ci#include "r600d.h" 438c2ecf20Sopenharmony_ci#include "radeon.h" 448c2ecf20Sopenharmony_ci#include "radeon_asic.h" 458c2ecf20Sopenharmony_ci#include "radeon_audio.h" 468c2ecf20Sopenharmony_ci#include "radeon_mode.h" 478c2ecf20Sopenharmony_ci#include "radeon_ucode.h" 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* Firmware Names */ 508c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/R600_pfp.bin"); 518c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/R600_me.bin"); 528c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV610_pfp.bin"); 538c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV610_me.bin"); 548c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV630_pfp.bin"); 558c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV630_me.bin"); 568c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV620_pfp.bin"); 578c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV620_me.bin"); 588c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV635_pfp.bin"); 598c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV635_me.bin"); 608c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV670_pfp.bin"); 618c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV670_me.bin"); 628c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RS780_pfp.bin"); 638c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RS780_me.bin"); 648c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV770_pfp.bin"); 658c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV770_me.bin"); 668c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV770_smc.bin"); 678c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV730_pfp.bin"); 688c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV730_me.bin"); 698c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV730_smc.bin"); 708c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV740_smc.bin"); 718c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV710_pfp.bin"); 728c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV710_me.bin"); 738c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/RV710_smc.bin"); 748c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/R600_rlc.bin"); 758c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/R700_rlc.bin"); 768c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/CEDAR_pfp.bin"); 778c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/CEDAR_me.bin"); 788c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/CEDAR_rlc.bin"); 798c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/CEDAR_smc.bin"); 808c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/REDWOOD_pfp.bin"); 818c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/REDWOOD_me.bin"); 828c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/REDWOOD_rlc.bin"); 838c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/REDWOOD_smc.bin"); 848c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/JUNIPER_pfp.bin"); 858c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/JUNIPER_me.bin"); 868c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/JUNIPER_rlc.bin"); 878c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/JUNIPER_smc.bin"); 888c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/CYPRESS_pfp.bin"); 898c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/CYPRESS_me.bin"); 908c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/CYPRESS_rlc.bin"); 918c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/CYPRESS_smc.bin"); 928c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/PALM_pfp.bin"); 938c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/PALM_me.bin"); 948c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO_rlc.bin"); 958c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO_pfp.bin"); 968c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO_me.bin"); 978c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO2_pfp.bin"); 988c2ecf20Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO2_me.bin"); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic const u32 crtc_offsets[2] = 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci 0, 1038c2ecf20Sopenharmony_ci AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL 1048c2ecf20Sopenharmony_ci}; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ciint r600_debugfs_mc_info_init(struct radeon_device *rdev); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* r600,rv610,rv630,rv620,rv635,rv670 */ 1098c2ecf20Sopenharmony_ciint r600_mc_wait_for_idle(struct radeon_device *rdev); 1108c2ecf20Sopenharmony_cistatic void r600_gpu_init(struct radeon_device *rdev); 1118c2ecf20Sopenharmony_civoid r600_fini(struct radeon_device *rdev); 1128c2ecf20Sopenharmony_civoid r600_irq_disable(struct radeon_device *rdev); 1138c2ecf20Sopenharmony_cistatic void r600_pcie_gen2_enable(struct radeon_device *rdev); 1148c2ecf20Sopenharmony_ciextern int evergreen_rlc_resume(struct radeon_device *rdev); 1158c2ecf20Sopenharmony_ciextern void rv770_set_clk_bypass_mode(struct radeon_device *rdev); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci/* 1188c2ecf20Sopenharmony_ci * Indirect registers accessor 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_ciu32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci unsigned long flags; 1238c2ecf20Sopenharmony_ci u32 r; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->rcu_idx_lock, flags); 1268c2ecf20Sopenharmony_ci WREG32(R600_RCU_INDEX, ((reg) & 0x1fff)); 1278c2ecf20Sopenharmony_ci r = RREG32(R600_RCU_DATA); 1288c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags); 1298c2ecf20Sopenharmony_ci return r; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_civoid r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci unsigned long flags; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->rcu_idx_lock, flags); 1378c2ecf20Sopenharmony_ci WREG32(R600_RCU_INDEX, ((reg) & 0x1fff)); 1388c2ecf20Sopenharmony_ci WREG32(R600_RCU_DATA, (v)); 1398c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ciu32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci unsigned long flags; 1458c2ecf20Sopenharmony_ci u32 r; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->uvd_idx_lock, flags); 1488c2ecf20Sopenharmony_ci WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff)); 1498c2ecf20Sopenharmony_ci r = RREG32(R600_UVD_CTX_DATA); 1508c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags); 1518c2ecf20Sopenharmony_ci return r; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_civoid r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci unsigned long flags; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->uvd_idx_lock, flags); 1598c2ecf20Sopenharmony_ci WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff)); 1608c2ecf20Sopenharmony_ci WREG32(R600_UVD_CTX_DATA, (v)); 1618c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/** 1658c2ecf20Sopenharmony_ci * r600_get_allowed_info_register - fetch the register for the info ioctl 1668c2ecf20Sopenharmony_ci * 1678c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 1688c2ecf20Sopenharmony_ci * @reg: register offset in bytes 1698c2ecf20Sopenharmony_ci * @val: register value 1708c2ecf20Sopenharmony_ci * 1718c2ecf20Sopenharmony_ci * Returns 0 for success or -EINVAL for an invalid register 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_ciint r600_get_allowed_info_register(struct radeon_device *rdev, 1758c2ecf20Sopenharmony_ci u32 reg, u32 *val) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci switch (reg) { 1788c2ecf20Sopenharmony_ci case GRBM_STATUS: 1798c2ecf20Sopenharmony_ci case GRBM_STATUS2: 1808c2ecf20Sopenharmony_ci case R_000E50_SRBM_STATUS: 1818c2ecf20Sopenharmony_ci case DMA_STATUS_REG: 1828c2ecf20Sopenharmony_ci case UVD_STATUS: 1838c2ecf20Sopenharmony_ci *val = RREG32(reg); 1848c2ecf20Sopenharmony_ci return 0; 1858c2ecf20Sopenharmony_ci default: 1868c2ecf20Sopenharmony_ci return -EINVAL; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci/** 1918c2ecf20Sopenharmony_ci * r600_get_xclk - get the xclk 1928c2ecf20Sopenharmony_ci * 1938c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 1948c2ecf20Sopenharmony_ci * 1958c2ecf20Sopenharmony_ci * Returns the reference clock used by the gfx engine 1968c2ecf20Sopenharmony_ci * (r6xx, IGPs, APUs). 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ciu32 r600_get_xclk(struct radeon_device *rdev) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci return rdev->clock.spll.reference_freq; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ciint r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci unsigned fb_div = 0, ref_div, vclk_div = 0, dclk_div = 0; 2068c2ecf20Sopenharmony_ci int r; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* bypass vclk and dclk with bclk */ 2098c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL_2, 2108c2ecf20Sopenharmony_ci VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), 2118c2ecf20Sopenharmony_ci ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* assert BYPASS_EN, deassert UPLL_RESET, UPLL_SLEEP and UPLL_CTLREQ */ 2148c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~( 2158c2ecf20Sopenharmony_ci UPLL_RESET_MASK | UPLL_SLEEP_MASK | UPLL_CTLREQ_MASK)); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RS780) 2188c2ecf20Sopenharmony_ci WREG32_P(GFX_MACRO_BYPASS_CNTL, UPLL_BYPASS_CNTL, 2198c2ecf20Sopenharmony_ci ~UPLL_BYPASS_CNTL); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!vclk || !dclk) { 2228c2ecf20Sopenharmony_ci /* keep the Bypass mode, put PLL to sleep */ 2238c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); 2248c2ecf20Sopenharmony_ci return 0; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (rdev->clock.spll.reference_freq == 10000) 2288c2ecf20Sopenharmony_ci ref_div = 34; 2298c2ecf20Sopenharmony_ci else 2308c2ecf20Sopenharmony_ci ref_div = 4; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 50000, 160000, 2338c2ecf20Sopenharmony_ci ref_div + 1, 0xFFF, 2, 30, ~0, 2348c2ecf20Sopenharmony_ci &fb_div, &vclk_div, &dclk_div); 2358c2ecf20Sopenharmony_ci if (r) 2368c2ecf20Sopenharmony_ci return r; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV670 && rdev->family < CHIP_RS780) 2398c2ecf20Sopenharmony_ci fb_div >>= 1; 2408c2ecf20Sopenharmony_ci else 2418c2ecf20Sopenharmony_ci fb_div |= 1; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL); 2448c2ecf20Sopenharmony_ci if (r) 2458c2ecf20Sopenharmony_ci return r; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* assert PLL_RESET */ 2488c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_RESET_MASK, ~UPLL_RESET_MASK); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* For RS780 we have to choose ref clk */ 2518c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RS780) 2528c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_REFCLK_SRC_SEL_MASK, 2538c2ecf20Sopenharmony_ci ~UPLL_REFCLK_SRC_SEL_MASK); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* set the required fb, ref and post divder values */ 2568c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, 2578c2ecf20Sopenharmony_ci UPLL_FB_DIV(fb_div) | 2588c2ecf20Sopenharmony_ci UPLL_REF_DIV(ref_div), 2598c2ecf20Sopenharmony_ci ~(UPLL_FB_DIV_MASK | UPLL_REF_DIV_MASK)); 2608c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL_2, 2618c2ecf20Sopenharmony_ci UPLL_SW_HILEN(vclk_div >> 1) | 2628c2ecf20Sopenharmony_ci UPLL_SW_LOLEN((vclk_div >> 1) + (vclk_div & 1)) | 2638c2ecf20Sopenharmony_ci UPLL_SW_HILEN2(dclk_div >> 1) | 2648c2ecf20Sopenharmony_ci UPLL_SW_LOLEN2((dclk_div >> 1) + (dclk_div & 1)) | 2658c2ecf20Sopenharmony_ci UPLL_DIVEN_MASK | UPLL_DIVEN2_MASK, 2668c2ecf20Sopenharmony_ci ~UPLL_SW_MASK); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* give the PLL some time to settle */ 2698c2ecf20Sopenharmony_ci mdelay(15); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* deassert PLL_RESET */ 2728c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci mdelay(15); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* deassert BYPASS EN */ 2778c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RS780) 2808c2ecf20Sopenharmony_ci WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~UPLL_BYPASS_CNTL); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL); 2838c2ecf20Sopenharmony_ci if (r) 2848c2ecf20Sopenharmony_ci return r; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* switch VCLK and DCLK selection */ 2878c2ecf20Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL_2, 2888c2ecf20Sopenharmony_ci VCLK_SRC_SEL(2) | DCLK_SRC_SEL(2), 2898c2ecf20Sopenharmony_ci ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci mdelay(100); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci return 0; 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_civoid dce3_program_fmt(struct drm_encoder *encoder) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci struct drm_device *dev = encoder->dev; 2998c2ecf20Sopenharmony_ci struct radeon_device *rdev = dev->dev_private; 3008c2ecf20Sopenharmony_ci struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 3018c2ecf20Sopenharmony_ci struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 3028c2ecf20Sopenharmony_ci struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 3038c2ecf20Sopenharmony_ci int bpc = 0; 3048c2ecf20Sopenharmony_ci u32 tmp = 0; 3058c2ecf20Sopenharmony_ci enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (connector) { 3088c2ecf20Sopenharmony_ci struct radeon_connector *radeon_connector = to_radeon_connector(connector); 3098c2ecf20Sopenharmony_ci bpc = radeon_get_monitor_bpc(connector); 3108c2ecf20Sopenharmony_ci dither = radeon_connector->dither; 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* LVDS FMT is set up by atom */ 3148c2ecf20Sopenharmony_ci if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) 3158c2ecf20Sopenharmony_ci return; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /* not needed for analog */ 3188c2ecf20Sopenharmony_ci if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) || 3198c2ecf20Sopenharmony_ci (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2)) 3208c2ecf20Sopenharmony_ci return; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci if (bpc == 0) 3238c2ecf20Sopenharmony_ci return; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci switch (bpc) { 3268c2ecf20Sopenharmony_ci case 6: 3278c2ecf20Sopenharmony_ci if (dither == RADEON_FMT_DITHER_ENABLE) 3288c2ecf20Sopenharmony_ci /* XXX sort out optimal dither settings */ 3298c2ecf20Sopenharmony_ci tmp |= FMT_SPATIAL_DITHER_EN; 3308c2ecf20Sopenharmony_ci else 3318c2ecf20Sopenharmony_ci tmp |= FMT_TRUNCATE_EN; 3328c2ecf20Sopenharmony_ci break; 3338c2ecf20Sopenharmony_ci case 8: 3348c2ecf20Sopenharmony_ci if (dither == RADEON_FMT_DITHER_ENABLE) 3358c2ecf20Sopenharmony_ci /* XXX sort out optimal dither settings */ 3368c2ecf20Sopenharmony_ci tmp |= (FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH); 3378c2ecf20Sopenharmony_ci else 3388c2ecf20Sopenharmony_ci tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH); 3398c2ecf20Sopenharmony_ci break; 3408c2ecf20Sopenharmony_ci case 10: 3418c2ecf20Sopenharmony_ci default: 3428c2ecf20Sopenharmony_ci /* not needed */ 3438c2ecf20Sopenharmony_ci break; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci WREG32(FMT_BIT_DEPTH_CONTROL + radeon_crtc->crtc_offset, tmp); 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci/* get temperature in millidegrees */ 3508c2ecf20Sopenharmony_ciint rv6xx_get_temp(struct radeon_device *rdev) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci u32 temp = (RREG32(CG_THERMAL_STATUS) & ASIC_T_MASK) >> 3538c2ecf20Sopenharmony_ci ASIC_T_SHIFT; 3548c2ecf20Sopenharmony_ci int actual_temp = temp & 0xff; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci if (temp & 0x100) 3578c2ecf20Sopenharmony_ci actual_temp -= 256; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci return actual_temp * 1000; 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_civoid r600_pm_get_dynpm_state(struct radeon_device *rdev) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci int i; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_upclock = true; 3678c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_downclock = true; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* power state array is low to high, default is first */ 3708c2ecf20Sopenharmony_ci if ((rdev->flags & RADEON_IS_IGP) || (rdev->family == CHIP_R600)) { 3718c2ecf20Sopenharmony_ci int min_power_state_index = 0; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (rdev->pm.num_power_states > 2) 3748c2ecf20Sopenharmony_ci min_power_state_index = 1; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci switch (rdev->pm.dynpm_planned_action) { 3778c2ecf20Sopenharmony_ci case DYNPM_ACTION_MINIMUM: 3788c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = min_power_state_index; 3798c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 3808c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci case DYNPM_ACTION_DOWNCLOCK: 3838c2ecf20Sopenharmony_ci if (rdev->pm.current_power_state_index == min_power_state_index) { 3848c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; 3858c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 3868c2ecf20Sopenharmony_ci } else { 3878c2ecf20Sopenharmony_ci if (rdev->pm.active_crtc_count > 1) { 3888c2ecf20Sopenharmony_ci for (i = 0; i < rdev->pm.num_power_states; i++) { 3898c2ecf20Sopenharmony_ci if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) 3908c2ecf20Sopenharmony_ci continue; 3918c2ecf20Sopenharmony_ci else if (i >= rdev->pm.current_power_state_index) { 3928c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = 3938c2ecf20Sopenharmony_ci rdev->pm.current_power_state_index; 3948c2ecf20Sopenharmony_ci break; 3958c2ecf20Sopenharmony_ci } else { 3968c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = i; 3978c2ecf20Sopenharmony_ci break; 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci } else { 4018c2ecf20Sopenharmony_ci if (rdev->pm.current_power_state_index == 0) 4028c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = 4038c2ecf20Sopenharmony_ci rdev->pm.num_power_states - 1; 4048c2ecf20Sopenharmony_ci else 4058c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = 4068c2ecf20Sopenharmony_ci rdev->pm.current_power_state_index - 1; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 4108c2ecf20Sopenharmony_ci /* don't use the power state if crtcs are active and no display flag is set */ 4118c2ecf20Sopenharmony_ci if ((rdev->pm.active_crtc_count > 0) && 4128c2ecf20Sopenharmony_ci (rdev->pm.power_state[rdev->pm.requested_power_state_index]. 4138c2ecf20Sopenharmony_ci clock_info[rdev->pm.requested_clock_mode_index].flags & 4148c2ecf20Sopenharmony_ci RADEON_PM_MODE_NO_DISPLAY)) { 4158c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index++; 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci break; 4188c2ecf20Sopenharmony_ci case DYNPM_ACTION_UPCLOCK: 4198c2ecf20Sopenharmony_ci if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { 4208c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; 4218c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 4228c2ecf20Sopenharmony_ci } else { 4238c2ecf20Sopenharmony_ci if (rdev->pm.active_crtc_count > 1) { 4248c2ecf20Sopenharmony_ci for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { 4258c2ecf20Sopenharmony_ci if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) 4268c2ecf20Sopenharmony_ci continue; 4278c2ecf20Sopenharmony_ci else if (i <= rdev->pm.current_power_state_index) { 4288c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = 4298c2ecf20Sopenharmony_ci rdev->pm.current_power_state_index; 4308c2ecf20Sopenharmony_ci break; 4318c2ecf20Sopenharmony_ci } else { 4328c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = i; 4338c2ecf20Sopenharmony_ci break; 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci } else 4378c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = 4388c2ecf20Sopenharmony_ci rdev->pm.current_power_state_index + 1; 4398c2ecf20Sopenharmony_ci } 4408c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 4418c2ecf20Sopenharmony_ci break; 4428c2ecf20Sopenharmony_ci case DYNPM_ACTION_DEFAULT: 4438c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; 4448c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 4458c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 4468c2ecf20Sopenharmony_ci break; 4478c2ecf20Sopenharmony_ci case DYNPM_ACTION_NONE: 4488c2ecf20Sopenharmony_ci default: 4498c2ecf20Sopenharmony_ci DRM_ERROR("Requested mode for not defined action\n"); 4508c2ecf20Sopenharmony_ci return; 4518c2ecf20Sopenharmony_ci } 4528c2ecf20Sopenharmony_ci } else { 4538c2ecf20Sopenharmony_ci /* XXX select a power state based on AC/DC, single/dualhead, etc. */ 4548c2ecf20Sopenharmony_ci /* for now just select the first power state and switch between clock modes */ 4558c2ecf20Sopenharmony_ci /* power state array is low to high, default is first (0) */ 4568c2ecf20Sopenharmony_ci if (rdev->pm.active_crtc_count > 1) { 4578c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = -1; 4588c2ecf20Sopenharmony_ci /* start at 1 as we don't want the default mode */ 4598c2ecf20Sopenharmony_ci for (i = 1; i < rdev->pm.num_power_states; i++) { 4608c2ecf20Sopenharmony_ci if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) 4618c2ecf20Sopenharmony_ci continue; 4628c2ecf20Sopenharmony_ci else if ((rdev->pm.power_state[i].type == POWER_STATE_TYPE_PERFORMANCE) || 4638c2ecf20Sopenharmony_ci (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY)) { 4648c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = i; 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci /* if nothing selected, grab the default state. */ 4698c2ecf20Sopenharmony_ci if (rdev->pm.requested_power_state_index == -1) 4708c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = 0; 4718c2ecf20Sopenharmony_ci } else 4728c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = 1; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci switch (rdev->pm.dynpm_planned_action) { 4758c2ecf20Sopenharmony_ci case DYNPM_ACTION_MINIMUM: 4768c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 4778c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 4788c2ecf20Sopenharmony_ci break; 4798c2ecf20Sopenharmony_ci case DYNPM_ACTION_DOWNCLOCK: 4808c2ecf20Sopenharmony_ci if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { 4818c2ecf20Sopenharmony_ci if (rdev->pm.current_clock_mode_index == 0) { 4828c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 4838c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 4848c2ecf20Sopenharmony_ci } else 4858c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 4868c2ecf20Sopenharmony_ci rdev->pm.current_clock_mode_index - 1; 4878c2ecf20Sopenharmony_ci } else { 4888c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 4898c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci /* don't use the power state if crtcs are active and no display flag is set */ 4928c2ecf20Sopenharmony_ci if ((rdev->pm.active_crtc_count > 0) && 4938c2ecf20Sopenharmony_ci (rdev->pm.power_state[rdev->pm.requested_power_state_index]. 4948c2ecf20Sopenharmony_ci clock_info[rdev->pm.requested_clock_mode_index].flags & 4958c2ecf20Sopenharmony_ci RADEON_PM_MODE_NO_DISPLAY)) { 4968c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index++; 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci break; 4998c2ecf20Sopenharmony_ci case DYNPM_ACTION_UPCLOCK: 5008c2ecf20Sopenharmony_ci if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { 5018c2ecf20Sopenharmony_ci if (rdev->pm.current_clock_mode_index == 5028c2ecf20Sopenharmony_ci (rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1)) { 5038c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = rdev->pm.current_clock_mode_index; 5048c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 5058c2ecf20Sopenharmony_ci } else 5068c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 5078c2ecf20Sopenharmony_ci rdev->pm.current_clock_mode_index + 1; 5088c2ecf20Sopenharmony_ci } else { 5098c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 5108c2ecf20Sopenharmony_ci rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1; 5118c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci break; 5148c2ecf20Sopenharmony_ci case DYNPM_ACTION_DEFAULT: 5158c2ecf20Sopenharmony_ci rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; 5168c2ecf20Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 5178c2ecf20Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 5188c2ecf20Sopenharmony_ci break; 5198c2ecf20Sopenharmony_ci case DYNPM_ACTION_NONE: 5208c2ecf20Sopenharmony_ci default: 5218c2ecf20Sopenharmony_ci DRM_ERROR("Requested mode for not defined action\n"); 5228c2ecf20Sopenharmony_ci return; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("Requested: e: %d m: %d p: %d\n", 5278c2ecf20Sopenharmony_ci rdev->pm.power_state[rdev->pm.requested_power_state_index]. 5288c2ecf20Sopenharmony_ci clock_info[rdev->pm.requested_clock_mode_index].sclk, 5298c2ecf20Sopenharmony_ci rdev->pm.power_state[rdev->pm.requested_power_state_index]. 5308c2ecf20Sopenharmony_ci clock_info[rdev->pm.requested_clock_mode_index].mclk, 5318c2ecf20Sopenharmony_ci rdev->pm.power_state[rdev->pm.requested_power_state_index]. 5328c2ecf20Sopenharmony_ci pcie_lanes); 5338c2ecf20Sopenharmony_ci} 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_civoid rs780_pm_init_profile(struct radeon_device *rdev) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci if (rdev->pm.num_power_states == 2) { 5388c2ecf20Sopenharmony_ci /* default */ 5398c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 5408c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 5418c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 5428c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 5438c2ecf20Sopenharmony_ci /* low sh */ 5448c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; 5458c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; 5468c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 5478c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 5488c2ecf20Sopenharmony_ci /* mid sh */ 5498c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; 5508c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0; 5518c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 5528c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 5538c2ecf20Sopenharmony_ci /* high sh */ 5548c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; 5558c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; 5568c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 5578c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 5588c2ecf20Sopenharmony_ci /* low mh */ 5598c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0; 5608c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; 5618c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 5628c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 5638c2ecf20Sopenharmony_ci /* mid mh */ 5648c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; 5658c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0; 5668c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 5678c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 5688c2ecf20Sopenharmony_ci /* high mh */ 5698c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; 5708c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1; 5718c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 5728c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 5738c2ecf20Sopenharmony_ci } else if (rdev->pm.num_power_states == 3) { 5748c2ecf20Sopenharmony_ci /* default */ 5758c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 5768c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 5778c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 5788c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 5798c2ecf20Sopenharmony_ci /* low sh */ 5808c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1; 5818c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; 5828c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 5838c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 5848c2ecf20Sopenharmony_ci /* mid sh */ 5858c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1; 5868c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; 5878c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 5888c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 5898c2ecf20Sopenharmony_ci /* high sh */ 5908c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; 5918c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2; 5928c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 5938c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 5948c2ecf20Sopenharmony_ci /* low mh */ 5958c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 1; 5968c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1; 5978c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 5988c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 5998c2ecf20Sopenharmony_ci /* mid mh */ 6008c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 1; 6018c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 1; 6028c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 6038c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 6048c2ecf20Sopenharmony_ci /* high mh */ 6058c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1; 6068c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; 6078c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 6088c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 6098c2ecf20Sopenharmony_ci } else { 6108c2ecf20Sopenharmony_ci /* default */ 6118c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6128c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6138c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 6148c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 6158c2ecf20Sopenharmony_ci /* low sh */ 6168c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 2; 6178c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2; 6188c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 6198c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 6208c2ecf20Sopenharmony_ci /* mid sh */ 6218c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 2; 6228c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 2; 6238c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 6248c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 6258c2ecf20Sopenharmony_ci /* high sh */ 6268c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2; 6278c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3; 6288c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 6298c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 6308c2ecf20Sopenharmony_ci /* low mh */ 6318c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2; 6328c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; 6338c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 6348c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 6358c2ecf20Sopenharmony_ci /* mid mh */ 6368c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2; 6378c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0; 6388c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 6398c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 6408c2ecf20Sopenharmony_ci /* high mh */ 6418c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; 6428c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3; 6438c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 6448c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci} 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_civoid r600_pm_init_profile(struct radeon_device *rdev) 6498c2ecf20Sopenharmony_ci{ 6508c2ecf20Sopenharmony_ci int idx; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (rdev->family == CHIP_R600) { 6538c2ecf20Sopenharmony_ci /* XXX */ 6548c2ecf20Sopenharmony_ci /* default */ 6558c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6568c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6578c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 6588c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 6598c2ecf20Sopenharmony_ci /* low sh */ 6608c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6618c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6628c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 6638c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 6648c2ecf20Sopenharmony_ci /* mid sh */ 6658c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6668c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6678c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 6688c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 6698c2ecf20Sopenharmony_ci /* high sh */ 6708c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6718c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6728c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 6738c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 6748c2ecf20Sopenharmony_ci /* low mh */ 6758c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6768c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6778c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 6788c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 6798c2ecf20Sopenharmony_ci /* mid mh */ 6808c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6818c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6828c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 6838c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 6848c2ecf20Sopenharmony_ci /* high mh */ 6858c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6868c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6878c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 6888c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 6898c2ecf20Sopenharmony_ci } else { 6908c2ecf20Sopenharmony_ci if (rdev->pm.num_power_states < 4) { 6918c2ecf20Sopenharmony_ci /* default */ 6928c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 6938c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 6948c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 6958c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2; 6968c2ecf20Sopenharmony_ci /* low sh */ 6978c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1; 6988c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; 6998c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 7008c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 7018c2ecf20Sopenharmony_ci /* mid sh */ 7028c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1; 7038c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; 7048c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 7058c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; 7068c2ecf20Sopenharmony_ci /* high sh */ 7078c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; 7088c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; 7098c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 7108c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; 7118c2ecf20Sopenharmony_ci /* low mh */ 7128c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2; 7138c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2; 7148c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 7158c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 7168c2ecf20Sopenharmony_ci /* low mh */ 7178c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2; 7188c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 2; 7198c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 7208c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; 7218c2ecf20Sopenharmony_ci /* high mh */ 7228c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; 7238c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; 7248c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 7258c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; 7268c2ecf20Sopenharmony_ci } else { 7278c2ecf20Sopenharmony_ci /* default */ 7288c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 7298c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 7308c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 7318c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2; 7328c2ecf20Sopenharmony_ci /* low sh */ 7338c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_MOBILITY) 7348c2ecf20Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); 7358c2ecf20Sopenharmony_ci else 7368c2ecf20Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); 7378c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx; 7388c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx; 7398c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 7408c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 7418c2ecf20Sopenharmony_ci /* mid sh */ 7428c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx; 7438c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx; 7448c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 7458c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; 7468c2ecf20Sopenharmony_ci /* high sh */ 7478c2ecf20Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); 7488c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx; 7498c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx; 7508c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 7518c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; 7528c2ecf20Sopenharmony_ci /* low mh */ 7538c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_MOBILITY) 7548c2ecf20Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); 7558c2ecf20Sopenharmony_ci else 7568c2ecf20Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); 7578c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx; 7588c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx; 7598c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 7608c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 7618c2ecf20Sopenharmony_ci /* mid mh */ 7628c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx; 7638c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx; 7648c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 7658c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; 7668c2ecf20Sopenharmony_ci /* high mh */ 7678c2ecf20Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); 7688c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx; 7698c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx; 7708c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 7718c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; 7728c2ecf20Sopenharmony_ci } 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci} 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_civoid r600_pm_misc(struct radeon_device *rdev) 7778c2ecf20Sopenharmony_ci{ 7788c2ecf20Sopenharmony_ci int req_ps_idx = rdev->pm.requested_power_state_index; 7798c2ecf20Sopenharmony_ci int req_cm_idx = rdev->pm.requested_clock_mode_index; 7808c2ecf20Sopenharmony_ci struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; 7818c2ecf20Sopenharmony_ci struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { 7848c2ecf20Sopenharmony_ci /* 0xff01 is a flag rather then an actual voltage */ 7858c2ecf20Sopenharmony_ci if (voltage->voltage == 0xff01) 7868c2ecf20Sopenharmony_ci return; 7878c2ecf20Sopenharmony_ci if (voltage->voltage != rdev->pm.current_vddc) { 7888c2ecf20Sopenharmony_ci radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); 7898c2ecf20Sopenharmony_ci rdev->pm.current_vddc = voltage->voltage; 7908c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("Setting: v: %d\n", voltage->voltage); 7918c2ecf20Sopenharmony_ci } 7928c2ecf20Sopenharmony_ci } 7938c2ecf20Sopenharmony_ci} 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_cibool r600_gui_idle(struct radeon_device *rdev) 7968c2ecf20Sopenharmony_ci{ 7978c2ecf20Sopenharmony_ci if (RREG32(GRBM_STATUS) & GUI_ACTIVE) 7988c2ecf20Sopenharmony_ci return false; 7998c2ecf20Sopenharmony_ci else 8008c2ecf20Sopenharmony_ci return true; 8018c2ecf20Sopenharmony_ci} 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci/* hpd for digital panel detect/disconnect */ 8048c2ecf20Sopenharmony_cibool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) 8058c2ecf20Sopenharmony_ci{ 8068c2ecf20Sopenharmony_ci bool connected = false; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 8098c2ecf20Sopenharmony_ci switch (hpd) { 8108c2ecf20Sopenharmony_ci case RADEON_HPD_1: 8118c2ecf20Sopenharmony_ci if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE) 8128c2ecf20Sopenharmony_ci connected = true; 8138c2ecf20Sopenharmony_ci break; 8148c2ecf20Sopenharmony_ci case RADEON_HPD_2: 8158c2ecf20Sopenharmony_ci if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE) 8168c2ecf20Sopenharmony_ci connected = true; 8178c2ecf20Sopenharmony_ci break; 8188c2ecf20Sopenharmony_ci case RADEON_HPD_3: 8198c2ecf20Sopenharmony_ci if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE) 8208c2ecf20Sopenharmony_ci connected = true; 8218c2ecf20Sopenharmony_ci break; 8228c2ecf20Sopenharmony_ci case RADEON_HPD_4: 8238c2ecf20Sopenharmony_ci if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE) 8248c2ecf20Sopenharmony_ci connected = true; 8258c2ecf20Sopenharmony_ci break; 8268c2ecf20Sopenharmony_ci /* DCE 3.2 */ 8278c2ecf20Sopenharmony_ci case RADEON_HPD_5: 8288c2ecf20Sopenharmony_ci if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE) 8298c2ecf20Sopenharmony_ci connected = true; 8308c2ecf20Sopenharmony_ci break; 8318c2ecf20Sopenharmony_ci case RADEON_HPD_6: 8328c2ecf20Sopenharmony_ci if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) 8338c2ecf20Sopenharmony_ci connected = true; 8348c2ecf20Sopenharmony_ci break; 8358c2ecf20Sopenharmony_ci default: 8368c2ecf20Sopenharmony_ci break; 8378c2ecf20Sopenharmony_ci } 8388c2ecf20Sopenharmony_ci } else { 8398c2ecf20Sopenharmony_ci switch (hpd) { 8408c2ecf20Sopenharmony_ci case RADEON_HPD_1: 8418c2ecf20Sopenharmony_ci if (RREG32(DC_HOT_PLUG_DETECT1_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) 8428c2ecf20Sopenharmony_ci connected = true; 8438c2ecf20Sopenharmony_ci break; 8448c2ecf20Sopenharmony_ci case RADEON_HPD_2: 8458c2ecf20Sopenharmony_ci if (RREG32(DC_HOT_PLUG_DETECT2_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) 8468c2ecf20Sopenharmony_ci connected = true; 8478c2ecf20Sopenharmony_ci break; 8488c2ecf20Sopenharmony_ci case RADEON_HPD_3: 8498c2ecf20Sopenharmony_ci if (RREG32(DC_HOT_PLUG_DETECT3_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) 8508c2ecf20Sopenharmony_ci connected = true; 8518c2ecf20Sopenharmony_ci break; 8528c2ecf20Sopenharmony_ci default: 8538c2ecf20Sopenharmony_ci break; 8548c2ecf20Sopenharmony_ci } 8558c2ecf20Sopenharmony_ci } 8568c2ecf20Sopenharmony_ci return connected; 8578c2ecf20Sopenharmony_ci} 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_civoid r600_hpd_set_polarity(struct radeon_device *rdev, 8608c2ecf20Sopenharmony_ci enum radeon_hpd_id hpd) 8618c2ecf20Sopenharmony_ci{ 8628c2ecf20Sopenharmony_ci u32 tmp; 8638c2ecf20Sopenharmony_ci bool connected = r600_hpd_sense(rdev, hpd); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 8668c2ecf20Sopenharmony_ci switch (hpd) { 8678c2ecf20Sopenharmony_ci case RADEON_HPD_1: 8688c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD1_INT_CONTROL); 8698c2ecf20Sopenharmony_ci if (connected) 8708c2ecf20Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 8718c2ecf20Sopenharmony_ci else 8728c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 8738c2ecf20Sopenharmony_ci WREG32(DC_HPD1_INT_CONTROL, tmp); 8748c2ecf20Sopenharmony_ci break; 8758c2ecf20Sopenharmony_ci case RADEON_HPD_2: 8768c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD2_INT_CONTROL); 8778c2ecf20Sopenharmony_ci if (connected) 8788c2ecf20Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 8798c2ecf20Sopenharmony_ci else 8808c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 8818c2ecf20Sopenharmony_ci WREG32(DC_HPD2_INT_CONTROL, tmp); 8828c2ecf20Sopenharmony_ci break; 8838c2ecf20Sopenharmony_ci case RADEON_HPD_3: 8848c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD3_INT_CONTROL); 8858c2ecf20Sopenharmony_ci if (connected) 8868c2ecf20Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 8878c2ecf20Sopenharmony_ci else 8888c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 8898c2ecf20Sopenharmony_ci WREG32(DC_HPD3_INT_CONTROL, tmp); 8908c2ecf20Sopenharmony_ci break; 8918c2ecf20Sopenharmony_ci case RADEON_HPD_4: 8928c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD4_INT_CONTROL); 8938c2ecf20Sopenharmony_ci if (connected) 8948c2ecf20Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 8958c2ecf20Sopenharmony_ci else 8968c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 8978c2ecf20Sopenharmony_ci WREG32(DC_HPD4_INT_CONTROL, tmp); 8988c2ecf20Sopenharmony_ci break; 8998c2ecf20Sopenharmony_ci case RADEON_HPD_5: 9008c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD5_INT_CONTROL); 9018c2ecf20Sopenharmony_ci if (connected) 9028c2ecf20Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 9038c2ecf20Sopenharmony_ci else 9048c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 9058c2ecf20Sopenharmony_ci WREG32(DC_HPD5_INT_CONTROL, tmp); 9068c2ecf20Sopenharmony_ci break; 9078c2ecf20Sopenharmony_ci /* DCE 3.2 */ 9088c2ecf20Sopenharmony_ci case RADEON_HPD_6: 9098c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD6_INT_CONTROL); 9108c2ecf20Sopenharmony_ci if (connected) 9118c2ecf20Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 9128c2ecf20Sopenharmony_ci else 9138c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 9148c2ecf20Sopenharmony_ci WREG32(DC_HPD6_INT_CONTROL, tmp); 9158c2ecf20Sopenharmony_ci break; 9168c2ecf20Sopenharmony_ci default: 9178c2ecf20Sopenharmony_ci break; 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci } else { 9208c2ecf20Sopenharmony_ci switch (hpd) { 9218c2ecf20Sopenharmony_ci case RADEON_HPD_1: 9228c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); 9238c2ecf20Sopenharmony_ci if (connected) 9248c2ecf20Sopenharmony_ci tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; 9258c2ecf20Sopenharmony_ci else 9268c2ecf20Sopenharmony_ci tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; 9278c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); 9288c2ecf20Sopenharmony_ci break; 9298c2ecf20Sopenharmony_ci case RADEON_HPD_2: 9308c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); 9318c2ecf20Sopenharmony_ci if (connected) 9328c2ecf20Sopenharmony_ci tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; 9338c2ecf20Sopenharmony_ci else 9348c2ecf20Sopenharmony_ci tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; 9358c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); 9368c2ecf20Sopenharmony_ci break; 9378c2ecf20Sopenharmony_ci case RADEON_HPD_3: 9388c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); 9398c2ecf20Sopenharmony_ci if (connected) 9408c2ecf20Sopenharmony_ci tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; 9418c2ecf20Sopenharmony_ci else 9428c2ecf20Sopenharmony_ci tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; 9438c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); 9448c2ecf20Sopenharmony_ci break; 9458c2ecf20Sopenharmony_ci default: 9468c2ecf20Sopenharmony_ci break; 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_civoid r600_hpd_init(struct radeon_device *rdev) 9528c2ecf20Sopenharmony_ci{ 9538c2ecf20Sopenharmony_ci struct drm_device *dev = rdev->ddev; 9548c2ecf20Sopenharmony_ci struct drm_connector *connector; 9558c2ecf20Sopenharmony_ci unsigned enable = 0; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 9588c2ecf20Sopenharmony_ci struct radeon_connector *radeon_connector = to_radeon_connector(connector); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || 9618c2ecf20Sopenharmony_ci connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { 9628c2ecf20Sopenharmony_ci /* don't try to enable hpd on eDP or LVDS avoid breaking the 9638c2ecf20Sopenharmony_ci * aux dp channel on imac and help (but not completely fix) 9648c2ecf20Sopenharmony_ci * https://bugzilla.redhat.com/show_bug.cgi?id=726143 9658c2ecf20Sopenharmony_ci */ 9668c2ecf20Sopenharmony_ci continue; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 9698c2ecf20Sopenharmony_ci u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa); 9708c2ecf20Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) 9718c2ecf20Sopenharmony_ci tmp |= DC_HPDx_EN; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci switch (radeon_connector->hpd.hpd) { 9748c2ecf20Sopenharmony_ci case RADEON_HPD_1: 9758c2ecf20Sopenharmony_ci WREG32(DC_HPD1_CONTROL, tmp); 9768c2ecf20Sopenharmony_ci break; 9778c2ecf20Sopenharmony_ci case RADEON_HPD_2: 9788c2ecf20Sopenharmony_ci WREG32(DC_HPD2_CONTROL, tmp); 9798c2ecf20Sopenharmony_ci break; 9808c2ecf20Sopenharmony_ci case RADEON_HPD_3: 9818c2ecf20Sopenharmony_ci WREG32(DC_HPD3_CONTROL, tmp); 9828c2ecf20Sopenharmony_ci break; 9838c2ecf20Sopenharmony_ci case RADEON_HPD_4: 9848c2ecf20Sopenharmony_ci WREG32(DC_HPD4_CONTROL, tmp); 9858c2ecf20Sopenharmony_ci break; 9868c2ecf20Sopenharmony_ci /* DCE 3.2 */ 9878c2ecf20Sopenharmony_ci case RADEON_HPD_5: 9888c2ecf20Sopenharmony_ci WREG32(DC_HPD5_CONTROL, tmp); 9898c2ecf20Sopenharmony_ci break; 9908c2ecf20Sopenharmony_ci case RADEON_HPD_6: 9918c2ecf20Sopenharmony_ci WREG32(DC_HPD6_CONTROL, tmp); 9928c2ecf20Sopenharmony_ci break; 9938c2ecf20Sopenharmony_ci default: 9948c2ecf20Sopenharmony_ci break; 9958c2ecf20Sopenharmony_ci } 9968c2ecf20Sopenharmony_ci } else { 9978c2ecf20Sopenharmony_ci switch (radeon_connector->hpd.hpd) { 9988c2ecf20Sopenharmony_ci case RADEON_HPD_1: 9998c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); 10008c2ecf20Sopenharmony_ci break; 10018c2ecf20Sopenharmony_ci case RADEON_HPD_2: 10028c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); 10038c2ecf20Sopenharmony_ci break; 10048c2ecf20Sopenharmony_ci case RADEON_HPD_3: 10058c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); 10068c2ecf20Sopenharmony_ci break; 10078c2ecf20Sopenharmony_ci default: 10088c2ecf20Sopenharmony_ci break; 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci } 10118c2ecf20Sopenharmony_ci if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) 10128c2ecf20Sopenharmony_ci enable |= 1 << radeon_connector->hpd.hpd; 10138c2ecf20Sopenharmony_ci radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci radeon_irq_kms_enable_hpd(rdev, enable); 10168c2ecf20Sopenharmony_ci} 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_civoid r600_hpd_fini(struct radeon_device *rdev) 10198c2ecf20Sopenharmony_ci{ 10208c2ecf20Sopenharmony_ci struct drm_device *dev = rdev->ddev; 10218c2ecf20Sopenharmony_ci struct drm_connector *connector; 10228c2ecf20Sopenharmony_ci unsigned disable = 0; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 10258c2ecf20Sopenharmony_ci struct radeon_connector *radeon_connector = to_radeon_connector(connector); 10268c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 10278c2ecf20Sopenharmony_ci switch (radeon_connector->hpd.hpd) { 10288c2ecf20Sopenharmony_ci case RADEON_HPD_1: 10298c2ecf20Sopenharmony_ci WREG32(DC_HPD1_CONTROL, 0); 10308c2ecf20Sopenharmony_ci break; 10318c2ecf20Sopenharmony_ci case RADEON_HPD_2: 10328c2ecf20Sopenharmony_ci WREG32(DC_HPD2_CONTROL, 0); 10338c2ecf20Sopenharmony_ci break; 10348c2ecf20Sopenharmony_ci case RADEON_HPD_3: 10358c2ecf20Sopenharmony_ci WREG32(DC_HPD3_CONTROL, 0); 10368c2ecf20Sopenharmony_ci break; 10378c2ecf20Sopenharmony_ci case RADEON_HPD_4: 10388c2ecf20Sopenharmony_ci WREG32(DC_HPD4_CONTROL, 0); 10398c2ecf20Sopenharmony_ci break; 10408c2ecf20Sopenharmony_ci /* DCE 3.2 */ 10418c2ecf20Sopenharmony_ci case RADEON_HPD_5: 10428c2ecf20Sopenharmony_ci WREG32(DC_HPD5_CONTROL, 0); 10438c2ecf20Sopenharmony_ci break; 10448c2ecf20Sopenharmony_ci case RADEON_HPD_6: 10458c2ecf20Sopenharmony_ci WREG32(DC_HPD6_CONTROL, 0); 10468c2ecf20Sopenharmony_ci break; 10478c2ecf20Sopenharmony_ci default: 10488c2ecf20Sopenharmony_ci break; 10498c2ecf20Sopenharmony_ci } 10508c2ecf20Sopenharmony_ci } else { 10518c2ecf20Sopenharmony_ci switch (radeon_connector->hpd.hpd) { 10528c2ecf20Sopenharmony_ci case RADEON_HPD_1: 10538c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); 10548c2ecf20Sopenharmony_ci break; 10558c2ecf20Sopenharmony_ci case RADEON_HPD_2: 10568c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); 10578c2ecf20Sopenharmony_ci break; 10588c2ecf20Sopenharmony_ci case RADEON_HPD_3: 10598c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); 10608c2ecf20Sopenharmony_ci break; 10618c2ecf20Sopenharmony_ci default: 10628c2ecf20Sopenharmony_ci break; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci } 10658c2ecf20Sopenharmony_ci if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) 10668c2ecf20Sopenharmony_ci disable |= 1 << radeon_connector->hpd.hpd; 10678c2ecf20Sopenharmony_ci } 10688c2ecf20Sopenharmony_ci radeon_irq_kms_disable_hpd(rdev, disable); 10698c2ecf20Sopenharmony_ci} 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci/* 10728c2ecf20Sopenharmony_ci * R600 PCIE GART 10738c2ecf20Sopenharmony_ci */ 10748c2ecf20Sopenharmony_civoid r600_pcie_gart_tlb_flush(struct radeon_device *rdev) 10758c2ecf20Sopenharmony_ci{ 10768c2ecf20Sopenharmony_ci unsigned i; 10778c2ecf20Sopenharmony_ci u32 tmp; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci /* flush hdp cache so updates hit vram */ 10808c2ecf20Sopenharmony_ci if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && 10818c2ecf20Sopenharmony_ci !(rdev->flags & RADEON_IS_AGP)) { 10828c2ecf20Sopenharmony_ci void __iomem *ptr = (void *)rdev->gart.ptr; 10838c2ecf20Sopenharmony_ci u32 tmp; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read 10868c2ecf20Sopenharmony_ci * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL 10878c2ecf20Sopenharmony_ci * This seems to cause problems on some AGP cards. Just use the old 10888c2ecf20Sopenharmony_ci * method for them. 10898c2ecf20Sopenharmony_ci */ 10908c2ecf20Sopenharmony_ci WREG32(HDP_DEBUG1, 0); 10918c2ecf20Sopenharmony_ci tmp = readl((void __iomem *)ptr); 10928c2ecf20Sopenharmony_ci } else 10938c2ecf20Sopenharmony_ci WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12); 10968c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12); 10978c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1)); 10988c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 10998c2ecf20Sopenharmony_ci /* read MC_STATUS */ 11008c2ecf20Sopenharmony_ci tmp = RREG32(VM_CONTEXT0_REQUEST_RESPONSE); 11018c2ecf20Sopenharmony_ci tmp = (tmp & RESPONSE_TYPE_MASK) >> RESPONSE_TYPE_SHIFT; 11028c2ecf20Sopenharmony_ci if (tmp == 2) { 11038c2ecf20Sopenharmony_ci pr_warn("[drm] r600 flush TLB failed\n"); 11048c2ecf20Sopenharmony_ci return; 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci if (tmp) { 11078c2ecf20Sopenharmony_ci return; 11088c2ecf20Sopenharmony_ci } 11098c2ecf20Sopenharmony_ci udelay(1); 11108c2ecf20Sopenharmony_ci } 11118c2ecf20Sopenharmony_ci} 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ciint r600_pcie_gart_init(struct radeon_device *rdev) 11148c2ecf20Sopenharmony_ci{ 11158c2ecf20Sopenharmony_ci int r; 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci if (rdev->gart.robj) { 11188c2ecf20Sopenharmony_ci WARN(1, "R600 PCIE GART already initialized\n"); 11198c2ecf20Sopenharmony_ci return 0; 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci /* Initialize common gart structure */ 11228c2ecf20Sopenharmony_ci r = radeon_gart_init(rdev); 11238c2ecf20Sopenharmony_ci if (r) 11248c2ecf20Sopenharmony_ci return r; 11258c2ecf20Sopenharmony_ci rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; 11268c2ecf20Sopenharmony_ci return radeon_gart_table_vram_alloc(rdev); 11278c2ecf20Sopenharmony_ci} 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_cistatic int r600_pcie_gart_enable(struct radeon_device *rdev) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci u32 tmp; 11328c2ecf20Sopenharmony_ci int r, i; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci if (rdev->gart.robj == NULL) { 11358c2ecf20Sopenharmony_ci dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); 11368c2ecf20Sopenharmony_ci return -EINVAL; 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci r = radeon_gart_table_vram_pin(rdev); 11398c2ecf20Sopenharmony_ci if (r) 11408c2ecf20Sopenharmony_ci return r; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci /* Setup L2 cache */ 11438c2ecf20Sopenharmony_ci WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | 11448c2ecf20Sopenharmony_ci ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | 11458c2ecf20Sopenharmony_ci EFFECTIVE_L2_QUEUE_SIZE(7)); 11468c2ecf20Sopenharmony_ci WREG32(VM_L2_CNTL2, 0); 11478c2ecf20Sopenharmony_ci WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); 11488c2ecf20Sopenharmony_ci /* Setup TLB control */ 11498c2ecf20Sopenharmony_ci tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | 11508c2ecf20Sopenharmony_ci SYSTEM_ACCESS_MODE_NOT_IN_SYS | 11518c2ecf20Sopenharmony_ci EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | 11528c2ecf20Sopenharmony_ci ENABLE_WAIT_L2_QUERY; 11538c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); 11548c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); 11558c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING); 11568c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); 11578c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); 11588c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); 11598c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); 11608c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); 11618c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); 11628c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); 11638c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); 11648c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); 11658c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_UVD_CNTL, tmp); 11668c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_UVD_CNTL, tmp); 11678c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); 11688c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); 11698c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); 11708c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); 11718c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); 11728c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | 11738c2ecf20Sopenharmony_ci RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); 11748c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, 11758c2ecf20Sopenharmony_ci (u32)(rdev->dummy_page.addr >> 12)); 11768c2ecf20Sopenharmony_ci for (i = 1; i < 7; i++) 11778c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci r600_pcie_gart_tlb_flush(rdev); 11808c2ecf20Sopenharmony_ci DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", 11818c2ecf20Sopenharmony_ci (unsigned)(rdev->mc.gtt_size >> 20), 11828c2ecf20Sopenharmony_ci (unsigned long long)rdev->gart.table_addr); 11838c2ecf20Sopenharmony_ci rdev->gart.ready = true; 11848c2ecf20Sopenharmony_ci return 0; 11858c2ecf20Sopenharmony_ci} 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_cistatic void r600_pcie_gart_disable(struct radeon_device *rdev) 11888c2ecf20Sopenharmony_ci{ 11898c2ecf20Sopenharmony_ci u32 tmp; 11908c2ecf20Sopenharmony_ci int i; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci /* Disable all tables */ 11938c2ecf20Sopenharmony_ci for (i = 0; i < 7; i++) 11948c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci /* Disable L2 cache */ 11978c2ecf20Sopenharmony_ci WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING | 11988c2ecf20Sopenharmony_ci EFFECTIVE_L2_QUEUE_SIZE(7)); 11998c2ecf20Sopenharmony_ci WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); 12008c2ecf20Sopenharmony_ci /* Setup L1 TLB control */ 12018c2ecf20Sopenharmony_ci tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | 12028c2ecf20Sopenharmony_ci ENABLE_WAIT_L2_QUERY; 12038c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); 12048c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); 12058c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); 12068c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); 12078c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); 12088c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); 12098c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); 12108c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); 12118c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp); 12128c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp); 12138c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); 12148c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); 12158c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp); 12168c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); 12178c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_UVD_CNTL, tmp); 12188c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_UVD_CNTL, tmp); 12198c2ecf20Sopenharmony_ci radeon_gart_table_vram_unpin(rdev); 12208c2ecf20Sopenharmony_ci} 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_cistatic void r600_pcie_gart_fini(struct radeon_device *rdev) 12238c2ecf20Sopenharmony_ci{ 12248c2ecf20Sopenharmony_ci radeon_gart_fini(rdev); 12258c2ecf20Sopenharmony_ci r600_pcie_gart_disable(rdev); 12268c2ecf20Sopenharmony_ci radeon_gart_table_vram_free(rdev); 12278c2ecf20Sopenharmony_ci} 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_cistatic void r600_agp_enable(struct radeon_device *rdev) 12308c2ecf20Sopenharmony_ci{ 12318c2ecf20Sopenharmony_ci u32 tmp; 12328c2ecf20Sopenharmony_ci int i; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci /* Setup L2 cache */ 12358c2ecf20Sopenharmony_ci WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | 12368c2ecf20Sopenharmony_ci ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | 12378c2ecf20Sopenharmony_ci EFFECTIVE_L2_QUEUE_SIZE(7)); 12388c2ecf20Sopenharmony_ci WREG32(VM_L2_CNTL2, 0); 12398c2ecf20Sopenharmony_ci WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); 12408c2ecf20Sopenharmony_ci /* Setup TLB control */ 12418c2ecf20Sopenharmony_ci tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | 12428c2ecf20Sopenharmony_ci SYSTEM_ACCESS_MODE_NOT_IN_SYS | 12438c2ecf20Sopenharmony_ci EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | 12448c2ecf20Sopenharmony_ci ENABLE_WAIT_L2_QUERY; 12458c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); 12468c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); 12478c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING); 12488c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); 12498c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); 12508c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); 12518c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); 12528c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); 12538c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); 12548c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); 12558c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); 12568c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); 12578c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); 12588c2ecf20Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); 12598c2ecf20Sopenharmony_ci for (i = 0; i < 7; i++) 12608c2ecf20Sopenharmony_ci WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 12618c2ecf20Sopenharmony_ci} 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ciint r600_mc_wait_for_idle(struct radeon_device *rdev) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci unsigned i; 12668c2ecf20Sopenharmony_ci u32 tmp; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 12698c2ecf20Sopenharmony_ci /* read MC_STATUS */ 12708c2ecf20Sopenharmony_ci tmp = RREG32(R_000E50_SRBM_STATUS) & 0x3F00; 12718c2ecf20Sopenharmony_ci if (!tmp) 12728c2ecf20Sopenharmony_ci return 0; 12738c2ecf20Sopenharmony_ci udelay(1); 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci return -1; 12768c2ecf20Sopenharmony_ci} 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ciuint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg) 12798c2ecf20Sopenharmony_ci{ 12808c2ecf20Sopenharmony_ci unsigned long flags; 12818c2ecf20Sopenharmony_ci uint32_t r; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->mc_idx_lock, flags); 12848c2ecf20Sopenharmony_ci WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg)); 12858c2ecf20Sopenharmony_ci r = RREG32(R_0028FC_MC_DATA); 12868c2ecf20Sopenharmony_ci WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR); 12878c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); 12888c2ecf20Sopenharmony_ci return r; 12898c2ecf20Sopenharmony_ci} 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_civoid rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 12928c2ecf20Sopenharmony_ci{ 12938c2ecf20Sopenharmony_ci unsigned long flags; 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->mc_idx_lock, flags); 12968c2ecf20Sopenharmony_ci WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) | 12978c2ecf20Sopenharmony_ci S_0028F8_MC_IND_WR_EN(1)); 12988c2ecf20Sopenharmony_ci WREG32(R_0028FC_MC_DATA, v); 12998c2ecf20Sopenharmony_ci WREG32(R_0028F8_MC_INDEX, 0x7F); 13008c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); 13018c2ecf20Sopenharmony_ci} 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_cistatic void r600_mc_program(struct radeon_device *rdev) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci struct rv515_mc_save save; 13068c2ecf20Sopenharmony_ci u32 tmp; 13078c2ecf20Sopenharmony_ci int i, j; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci /* Initialize HDP */ 13108c2ecf20Sopenharmony_ci for (i = 0, j = 0; i < 32; i++, j += 0x18) { 13118c2ecf20Sopenharmony_ci WREG32((0x2c14 + j), 0x00000000); 13128c2ecf20Sopenharmony_ci WREG32((0x2c18 + j), 0x00000000); 13138c2ecf20Sopenharmony_ci WREG32((0x2c1c + j), 0x00000000); 13148c2ecf20Sopenharmony_ci WREG32((0x2c20 + j), 0x00000000); 13158c2ecf20Sopenharmony_ci WREG32((0x2c24 + j), 0x00000000); 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0); 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci rv515_mc_stop(rdev, &save); 13208c2ecf20Sopenharmony_ci if (r600_mc_wait_for_idle(rdev)) { 13218c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 13228c2ecf20Sopenharmony_ci } 13238c2ecf20Sopenharmony_ci /* Lockout access through VGA aperture (doesn't exist before R600) */ 13248c2ecf20Sopenharmony_ci WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); 13258c2ecf20Sopenharmony_ci /* Update configuration */ 13268c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 13278c2ecf20Sopenharmony_ci if (rdev->mc.vram_start < rdev->mc.gtt_start) { 13288c2ecf20Sopenharmony_ci /* VRAM before AGP */ 13298c2ecf20Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, 13308c2ecf20Sopenharmony_ci rdev->mc.vram_start >> 12); 13318c2ecf20Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 13328c2ecf20Sopenharmony_ci rdev->mc.gtt_end >> 12); 13338c2ecf20Sopenharmony_ci } else { 13348c2ecf20Sopenharmony_ci /* VRAM after AGP */ 13358c2ecf20Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, 13368c2ecf20Sopenharmony_ci rdev->mc.gtt_start >> 12); 13378c2ecf20Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 13388c2ecf20Sopenharmony_ci rdev->mc.vram_end >> 12); 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci } else { 13418c2ecf20Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12); 13428c2ecf20Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12); 13438c2ecf20Sopenharmony_ci } 13448c2ecf20Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); 13458c2ecf20Sopenharmony_ci tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; 13468c2ecf20Sopenharmony_ci tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); 13478c2ecf20Sopenharmony_ci WREG32(MC_VM_FB_LOCATION, tmp); 13488c2ecf20Sopenharmony_ci WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); 13498c2ecf20Sopenharmony_ci WREG32(HDP_NONSURFACE_INFO, (2 << 7)); 13508c2ecf20Sopenharmony_ci WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); 13518c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 13528c2ecf20Sopenharmony_ci WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22); 13538c2ecf20Sopenharmony_ci WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22); 13548c2ecf20Sopenharmony_ci WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22); 13558c2ecf20Sopenharmony_ci } else { 13568c2ecf20Sopenharmony_ci WREG32(MC_VM_AGP_BASE, 0); 13578c2ecf20Sopenharmony_ci WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); 13588c2ecf20Sopenharmony_ci WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); 13598c2ecf20Sopenharmony_ci } 13608c2ecf20Sopenharmony_ci if (r600_mc_wait_for_idle(rdev)) { 13618c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 13628c2ecf20Sopenharmony_ci } 13638c2ecf20Sopenharmony_ci rv515_mc_resume(rdev, &save); 13648c2ecf20Sopenharmony_ci /* we need to own VRAM, so turn off the VGA renderer here 13658c2ecf20Sopenharmony_ci * to stop it overwriting our objects */ 13668c2ecf20Sopenharmony_ci rv515_vga_render_disable(rdev); 13678c2ecf20Sopenharmony_ci} 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci/** 13708c2ecf20Sopenharmony_ci * r600_vram_gtt_location - try to find VRAM & GTT location 13718c2ecf20Sopenharmony_ci * @rdev: radeon device structure holding all necessary informations 13728c2ecf20Sopenharmony_ci * @mc: memory controller structure holding memory informations 13738c2ecf20Sopenharmony_ci * 13748c2ecf20Sopenharmony_ci * Function will place try to place VRAM at same place as in CPU (PCI) 13758c2ecf20Sopenharmony_ci * address space as some GPU seems to have issue when we reprogram at 13768c2ecf20Sopenharmony_ci * different address space. 13778c2ecf20Sopenharmony_ci * 13788c2ecf20Sopenharmony_ci * If there is not enough space to fit the unvisible VRAM after the 13798c2ecf20Sopenharmony_ci * aperture then we limit the VRAM size to the aperture. 13808c2ecf20Sopenharmony_ci * 13818c2ecf20Sopenharmony_ci * If we are using AGP then place VRAM adjacent to AGP aperture are we need 13828c2ecf20Sopenharmony_ci * them to be in one from GPU point of view so that we can program GPU to 13838c2ecf20Sopenharmony_ci * catch access outside them (weird GPU policy see ??). 13848c2ecf20Sopenharmony_ci * 13858c2ecf20Sopenharmony_ci * This function will never fails, worst case are limiting VRAM or GTT. 13868c2ecf20Sopenharmony_ci * 13878c2ecf20Sopenharmony_ci * Note: GTT start, end, size should be initialized before calling this 13888c2ecf20Sopenharmony_ci * function on AGP platform. 13898c2ecf20Sopenharmony_ci */ 13908c2ecf20Sopenharmony_cistatic void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) 13918c2ecf20Sopenharmony_ci{ 13928c2ecf20Sopenharmony_ci u64 size_bf, size_af; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci if (mc->mc_vram_size > 0xE0000000) { 13958c2ecf20Sopenharmony_ci /* leave room for at least 512M GTT */ 13968c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "limiting VRAM\n"); 13978c2ecf20Sopenharmony_ci mc->real_vram_size = 0xE0000000; 13988c2ecf20Sopenharmony_ci mc->mc_vram_size = 0xE0000000; 13998c2ecf20Sopenharmony_ci } 14008c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 14018c2ecf20Sopenharmony_ci size_bf = mc->gtt_start; 14028c2ecf20Sopenharmony_ci size_af = mc->mc_mask - mc->gtt_end; 14038c2ecf20Sopenharmony_ci if (size_bf > size_af) { 14048c2ecf20Sopenharmony_ci if (mc->mc_vram_size > size_bf) { 14058c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "limiting VRAM\n"); 14068c2ecf20Sopenharmony_ci mc->real_vram_size = size_bf; 14078c2ecf20Sopenharmony_ci mc->mc_vram_size = size_bf; 14088c2ecf20Sopenharmony_ci } 14098c2ecf20Sopenharmony_ci mc->vram_start = mc->gtt_start - mc->mc_vram_size; 14108c2ecf20Sopenharmony_ci } else { 14118c2ecf20Sopenharmony_ci if (mc->mc_vram_size > size_af) { 14128c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "limiting VRAM\n"); 14138c2ecf20Sopenharmony_ci mc->real_vram_size = size_af; 14148c2ecf20Sopenharmony_ci mc->mc_vram_size = size_af; 14158c2ecf20Sopenharmony_ci } 14168c2ecf20Sopenharmony_ci mc->vram_start = mc->gtt_end + 1; 14178c2ecf20Sopenharmony_ci } 14188c2ecf20Sopenharmony_ci mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; 14198c2ecf20Sopenharmony_ci dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", 14208c2ecf20Sopenharmony_ci mc->mc_vram_size >> 20, mc->vram_start, 14218c2ecf20Sopenharmony_ci mc->vram_end, mc->real_vram_size >> 20); 14228c2ecf20Sopenharmony_ci } else { 14238c2ecf20Sopenharmony_ci u64 base = 0; 14248c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) { 14258c2ecf20Sopenharmony_ci base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF; 14268c2ecf20Sopenharmony_ci base <<= 24; 14278c2ecf20Sopenharmony_ci } 14288c2ecf20Sopenharmony_ci radeon_vram_location(rdev, &rdev->mc, base); 14298c2ecf20Sopenharmony_ci rdev->mc.gtt_base_align = 0; 14308c2ecf20Sopenharmony_ci radeon_gtt_location(rdev, mc); 14318c2ecf20Sopenharmony_ci } 14328c2ecf20Sopenharmony_ci} 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_cistatic int r600_mc_init(struct radeon_device *rdev) 14358c2ecf20Sopenharmony_ci{ 14368c2ecf20Sopenharmony_ci u32 tmp; 14378c2ecf20Sopenharmony_ci int chansize, numchan; 14388c2ecf20Sopenharmony_ci uint32_t h_addr, l_addr; 14398c2ecf20Sopenharmony_ci unsigned long long k8_addr; 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci /* Get VRAM informations */ 14428c2ecf20Sopenharmony_ci rdev->mc.vram_is_ddr = true; 14438c2ecf20Sopenharmony_ci tmp = RREG32(RAMCFG); 14448c2ecf20Sopenharmony_ci if (tmp & CHANSIZE_OVERRIDE) { 14458c2ecf20Sopenharmony_ci chansize = 16; 14468c2ecf20Sopenharmony_ci } else if (tmp & CHANSIZE_MASK) { 14478c2ecf20Sopenharmony_ci chansize = 64; 14488c2ecf20Sopenharmony_ci } else { 14498c2ecf20Sopenharmony_ci chansize = 32; 14508c2ecf20Sopenharmony_ci } 14518c2ecf20Sopenharmony_ci tmp = RREG32(CHMAP); 14528c2ecf20Sopenharmony_ci switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { 14538c2ecf20Sopenharmony_ci case 0: 14548c2ecf20Sopenharmony_ci default: 14558c2ecf20Sopenharmony_ci numchan = 1; 14568c2ecf20Sopenharmony_ci break; 14578c2ecf20Sopenharmony_ci case 1: 14588c2ecf20Sopenharmony_ci numchan = 2; 14598c2ecf20Sopenharmony_ci break; 14608c2ecf20Sopenharmony_ci case 2: 14618c2ecf20Sopenharmony_ci numchan = 4; 14628c2ecf20Sopenharmony_ci break; 14638c2ecf20Sopenharmony_ci case 3: 14648c2ecf20Sopenharmony_ci numchan = 8; 14658c2ecf20Sopenharmony_ci break; 14668c2ecf20Sopenharmony_ci } 14678c2ecf20Sopenharmony_ci rdev->mc.vram_width = numchan * chansize; 14688c2ecf20Sopenharmony_ci /* Could aper size report 0 ? */ 14698c2ecf20Sopenharmony_ci rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); 14708c2ecf20Sopenharmony_ci rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); 14718c2ecf20Sopenharmony_ci /* Setup GPU memory space */ 14728c2ecf20Sopenharmony_ci rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); 14738c2ecf20Sopenharmony_ci rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); 14748c2ecf20Sopenharmony_ci rdev->mc.visible_vram_size = rdev->mc.aper_size; 14758c2ecf20Sopenharmony_ci r600_vram_gtt_location(rdev, &rdev->mc); 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) { 14788c2ecf20Sopenharmony_ci rs690_pm_info(rdev); 14798c2ecf20Sopenharmony_ci rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) { 14828c2ecf20Sopenharmony_ci /* Use K8 direct mapping for fast fb access. */ 14838c2ecf20Sopenharmony_ci rdev->fastfb_working = false; 14848c2ecf20Sopenharmony_ci h_addr = G_000012_K8_ADDR_EXT(RREG32_MC(R_000012_MC_MISC_UMA_CNTL)); 14858c2ecf20Sopenharmony_ci l_addr = RREG32_MC(R_000011_K8_FB_LOCATION); 14868c2ecf20Sopenharmony_ci k8_addr = ((unsigned long long)h_addr) << 32 | l_addr; 14878c2ecf20Sopenharmony_ci#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE) 14888c2ecf20Sopenharmony_ci if (k8_addr + rdev->mc.visible_vram_size < 0x100000000ULL) 14898c2ecf20Sopenharmony_ci#endif 14908c2ecf20Sopenharmony_ci { 14918c2ecf20Sopenharmony_ci /* FastFB shall be used with UMA memory. Here it is simply disabled when sideport 14928c2ecf20Sopenharmony_ci * memory is present. 14938c2ecf20Sopenharmony_ci */ 14948c2ecf20Sopenharmony_ci if (rdev->mc.igp_sideport_enabled == false && radeon_fastfb == 1) { 14958c2ecf20Sopenharmony_ci DRM_INFO("Direct mapping: aper base at 0x%llx, replaced by direct mapping base 0x%llx.\n", 14968c2ecf20Sopenharmony_ci (unsigned long long)rdev->mc.aper_base, k8_addr); 14978c2ecf20Sopenharmony_ci rdev->mc.aper_base = (resource_size_t)k8_addr; 14988c2ecf20Sopenharmony_ci rdev->fastfb_working = true; 14998c2ecf20Sopenharmony_ci } 15008c2ecf20Sopenharmony_ci } 15018c2ecf20Sopenharmony_ci } 15028c2ecf20Sopenharmony_ci } 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci radeon_update_bandwidth_info(rdev); 15058c2ecf20Sopenharmony_ci return 0; 15068c2ecf20Sopenharmony_ci} 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ciint r600_vram_scratch_init(struct radeon_device *rdev) 15098c2ecf20Sopenharmony_ci{ 15108c2ecf20Sopenharmony_ci int r; 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci if (rdev->vram_scratch.robj == NULL) { 15138c2ecf20Sopenharmony_ci r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, 15148c2ecf20Sopenharmony_ci PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 15158c2ecf20Sopenharmony_ci 0, NULL, NULL, &rdev->vram_scratch.robj); 15168c2ecf20Sopenharmony_ci if (r) { 15178c2ecf20Sopenharmony_ci return r; 15188c2ecf20Sopenharmony_ci } 15198c2ecf20Sopenharmony_ci } 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci r = radeon_bo_reserve(rdev->vram_scratch.robj, false); 15228c2ecf20Sopenharmony_ci if (unlikely(r != 0)) 15238c2ecf20Sopenharmony_ci return r; 15248c2ecf20Sopenharmony_ci r = radeon_bo_pin(rdev->vram_scratch.robj, 15258c2ecf20Sopenharmony_ci RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr); 15268c2ecf20Sopenharmony_ci if (r) { 15278c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->vram_scratch.robj); 15288c2ecf20Sopenharmony_ci return r; 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci r = radeon_bo_kmap(rdev->vram_scratch.robj, 15318c2ecf20Sopenharmony_ci (void **)&rdev->vram_scratch.ptr); 15328c2ecf20Sopenharmony_ci if (r) 15338c2ecf20Sopenharmony_ci radeon_bo_unpin(rdev->vram_scratch.robj); 15348c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->vram_scratch.robj); 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci return r; 15378c2ecf20Sopenharmony_ci} 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_civoid r600_vram_scratch_fini(struct radeon_device *rdev) 15408c2ecf20Sopenharmony_ci{ 15418c2ecf20Sopenharmony_ci int r; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci if (rdev->vram_scratch.robj == NULL) { 15448c2ecf20Sopenharmony_ci return; 15458c2ecf20Sopenharmony_ci } 15468c2ecf20Sopenharmony_ci r = radeon_bo_reserve(rdev->vram_scratch.robj, false); 15478c2ecf20Sopenharmony_ci if (likely(r == 0)) { 15488c2ecf20Sopenharmony_ci radeon_bo_kunmap(rdev->vram_scratch.robj); 15498c2ecf20Sopenharmony_ci radeon_bo_unpin(rdev->vram_scratch.robj); 15508c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->vram_scratch.robj); 15518c2ecf20Sopenharmony_ci } 15528c2ecf20Sopenharmony_ci radeon_bo_unref(&rdev->vram_scratch.robj); 15538c2ecf20Sopenharmony_ci} 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_civoid r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung) 15568c2ecf20Sopenharmony_ci{ 15578c2ecf20Sopenharmony_ci u32 tmp = RREG32(R600_BIOS_3_SCRATCH); 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci if (hung) 15608c2ecf20Sopenharmony_ci tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; 15618c2ecf20Sopenharmony_ci else 15628c2ecf20Sopenharmony_ci tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci WREG32(R600_BIOS_3_SCRATCH, tmp); 15658c2ecf20Sopenharmony_ci} 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_cistatic void r600_print_gpu_status_regs(struct radeon_device *rdev) 15688c2ecf20Sopenharmony_ci{ 15698c2ecf20Sopenharmony_ci dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n", 15708c2ecf20Sopenharmony_ci RREG32(R_008010_GRBM_STATUS)); 15718c2ecf20Sopenharmony_ci dev_info(rdev->dev, " R_008014_GRBM_STATUS2 = 0x%08X\n", 15728c2ecf20Sopenharmony_ci RREG32(R_008014_GRBM_STATUS2)); 15738c2ecf20Sopenharmony_ci dev_info(rdev->dev, " R_000E50_SRBM_STATUS = 0x%08X\n", 15748c2ecf20Sopenharmony_ci RREG32(R_000E50_SRBM_STATUS)); 15758c2ecf20Sopenharmony_ci dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", 15768c2ecf20Sopenharmony_ci RREG32(CP_STALLED_STAT1)); 15778c2ecf20Sopenharmony_ci dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", 15788c2ecf20Sopenharmony_ci RREG32(CP_STALLED_STAT2)); 15798c2ecf20Sopenharmony_ci dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", 15808c2ecf20Sopenharmony_ci RREG32(CP_BUSY_STAT)); 15818c2ecf20Sopenharmony_ci dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", 15828c2ecf20Sopenharmony_ci RREG32(CP_STAT)); 15838c2ecf20Sopenharmony_ci dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", 15848c2ecf20Sopenharmony_ci RREG32(DMA_STATUS_REG)); 15858c2ecf20Sopenharmony_ci} 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_cistatic bool r600_is_display_hung(struct radeon_device *rdev) 15888c2ecf20Sopenharmony_ci{ 15898c2ecf20Sopenharmony_ci u32 crtc_hung = 0; 15908c2ecf20Sopenharmony_ci u32 crtc_status[2]; 15918c2ecf20Sopenharmony_ci u32 i, j, tmp; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci for (i = 0; i < rdev->num_crtc; i++) { 15948c2ecf20Sopenharmony_ci if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN) { 15958c2ecf20Sopenharmony_ci crtc_status[i] = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]); 15968c2ecf20Sopenharmony_ci crtc_hung |= (1 << i); 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci } 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci for (j = 0; j < 10; j++) { 16018c2ecf20Sopenharmony_ci for (i = 0; i < rdev->num_crtc; i++) { 16028c2ecf20Sopenharmony_ci if (crtc_hung & (1 << i)) { 16038c2ecf20Sopenharmony_ci tmp = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]); 16048c2ecf20Sopenharmony_ci if (tmp != crtc_status[i]) 16058c2ecf20Sopenharmony_ci crtc_hung &= ~(1 << i); 16068c2ecf20Sopenharmony_ci } 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci if (crtc_hung == 0) 16098c2ecf20Sopenharmony_ci return false; 16108c2ecf20Sopenharmony_ci udelay(100); 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci return true; 16148c2ecf20Sopenharmony_ci} 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ciu32 r600_gpu_check_soft_reset(struct radeon_device *rdev) 16178c2ecf20Sopenharmony_ci{ 16188c2ecf20Sopenharmony_ci u32 reset_mask = 0; 16198c2ecf20Sopenharmony_ci u32 tmp; 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci /* GRBM_STATUS */ 16228c2ecf20Sopenharmony_ci tmp = RREG32(R_008010_GRBM_STATUS); 16238c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) { 16248c2ecf20Sopenharmony_ci if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) | 16258c2ecf20Sopenharmony_ci G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) | 16268c2ecf20Sopenharmony_ci G_008010_TA_BUSY(tmp) | G_008010_VGT_BUSY(tmp) | 16278c2ecf20Sopenharmony_ci G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) | 16288c2ecf20Sopenharmony_ci G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp)) 16298c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_GFX; 16308c2ecf20Sopenharmony_ci } else { 16318c2ecf20Sopenharmony_ci if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) | 16328c2ecf20Sopenharmony_ci G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) | 16338c2ecf20Sopenharmony_ci G_008010_TA03_BUSY(tmp) | G_008010_VGT_BUSY(tmp) | 16348c2ecf20Sopenharmony_ci G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) | 16358c2ecf20Sopenharmony_ci G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp)) 16368c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_GFX; 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci if (G_008010_CF_RQ_PENDING(tmp) | G_008010_PF_RQ_PENDING(tmp) | 16408c2ecf20Sopenharmony_ci G_008010_CP_BUSY(tmp) | G_008010_CP_COHERENCY_BUSY(tmp)) 16418c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_CP; 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci if (G_008010_GRBM_EE_BUSY(tmp)) 16448c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci /* DMA_STATUS_REG */ 16478c2ecf20Sopenharmony_ci tmp = RREG32(DMA_STATUS_REG); 16488c2ecf20Sopenharmony_ci if (!(tmp & DMA_IDLE)) 16498c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_DMA; 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci /* SRBM_STATUS */ 16528c2ecf20Sopenharmony_ci tmp = RREG32(R_000E50_SRBM_STATUS); 16538c2ecf20Sopenharmony_ci if (G_000E50_RLC_RQ_PENDING(tmp) | G_000E50_RLC_BUSY(tmp)) 16548c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_RLC; 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci if (G_000E50_IH_BUSY(tmp)) 16578c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_IH; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci if (G_000E50_SEM_BUSY(tmp)) 16608c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_SEM; 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci if (G_000E50_GRBM_RQ_PENDING(tmp)) 16638c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_GRBM; 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci if (G_000E50_VMC_BUSY(tmp)) 16668c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_VMC; 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci if (G_000E50_MCB_BUSY(tmp) | G_000E50_MCDZ_BUSY(tmp) | 16698c2ecf20Sopenharmony_ci G_000E50_MCDY_BUSY(tmp) | G_000E50_MCDX_BUSY(tmp) | 16708c2ecf20Sopenharmony_ci G_000E50_MCDW_BUSY(tmp)) 16718c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_MC; 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci if (r600_is_display_hung(rdev)) 16748c2ecf20Sopenharmony_ci reset_mask |= RADEON_RESET_DISPLAY; 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci /* Skip MC reset as it's mostly likely not hung, just busy */ 16778c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_MC) { 16788c2ecf20Sopenharmony_ci DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask); 16798c2ecf20Sopenharmony_ci reset_mask &= ~RADEON_RESET_MC; 16808c2ecf20Sopenharmony_ci } 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci return reset_mask; 16838c2ecf20Sopenharmony_ci} 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_cistatic void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) 16868c2ecf20Sopenharmony_ci{ 16878c2ecf20Sopenharmony_ci struct rv515_mc_save save; 16888c2ecf20Sopenharmony_ci u32 grbm_soft_reset = 0, srbm_soft_reset = 0; 16898c2ecf20Sopenharmony_ci u32 tmp; 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci if (reset_mask == 0) 16928c2ecf20Sopenharmony_ci return; 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci r600_print_gpu_status_regs(rdev); 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci /* Disable CP parsing/prefetching */ 16998c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) 17008c2ecf20Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1)); 17018c2ecf20Sopenharmony_ci else 17028c2ecf20Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci /* disable the RLC */ 17058c2ecf20Sopenharmony_ci WREG32(RLC_CNTL, 0); 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_DMA) { 17088c2ecf20Sopenharmony_ci /* Disable DMA */ 17098c2ecf20Sopenharmony_ci tmp = RREG32(DMA_RB_CNTL); 17108c2ecf20Sopenharmony_ci tmp &= ~DMA_RB_ENABLE; 17118c2ecf20Sopenharmony_ci WREG32(DMA_RB_CNTL, tmp); 17128c2ecf20Sopenharmony_ci } 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci mdelay(50); 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci rv515_mc_stop(rdev, &save); 17178c2ecf20Sopenharmony_ci if (r600_mc_wait_for_idle(rdev)) { 17188c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 17198c2ecf20Sopenharmony_ci } 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) { 17228c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) 17238c2ecf20Sopenharmony_ci grbm_soft_reset |= S_008020_SOFT_RESET_DB(1) | 17248c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_CB(1) | 17258c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_PA(1) | 17268c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SC(1) | 17278c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SPI(1) | 17288c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SX(1) | 17298c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SH(1) | 17308c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_TC(1) | 17318c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_TA(1) | 17328c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_VC(1) | 17338c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_VGT(1); 17348c2ecf20Sopenharmony_ci else 17358c2ecf20Sopenharmony_ci grbm_soft_reset |= S_008020_SOFT_RESET_CR(1) | 17368c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_DB(1) | 17378c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_CB(1) | 17388c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_PA(1) | 17398c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SC(1) | 17408c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SMX(1) | 17418c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SPI(1) | 17428c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SX(1) | 17438c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_SH(1) | 17448c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_TC(1) | 17458c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_TA(1) | 17468c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_VC(1) | 17478c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_VGT(1); 17488c2ecf20Sopenharmony_ci } 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_CP) { 17518c2ecf20Sopenharmony_ci grbm_soft_reset |= S_008020_SOFT_RESET_CP(1) | 17528c2ecf20Sopenharmony_ci S_008020_SOFT_RESET_VGT(1); 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1); 17558c2ecf20Sopenharmony_ci } 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_DMA) { 17588c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) 17598c2ecf20Sopenharmony_ci srbm_soft_reset |= RV770_SOFT_RESET_DMA; 17608c2ecf20Sopenharmony_ci else 17618c2ecf20Sopenharmony_ci srbm_soft_reset |= SOFT_RESET_DMA; 17628c2ecf20Sopenharmony_ci } 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_RLC) 17658c2ecf20Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_RLC(1); 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_SEM) 17688c2ecf20Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_SEM(1); 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_IH) 17718c2ecf20Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_IH(1); 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_GRBM) 17748c2ecf20Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1); 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_IS_IGP)) { 17778c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_MC) 17788c2ecf20Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_MC(1); 17798c2ecf20Sopenharmony_ci } 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci if (reset_mask & RADEON_RESET_VMC) 17828c2ecf20Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_VMC(1); 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci if (grbm_soft_reset) { 17858c2ecf20Sopenharmony_ci tmp = RREG32(R_008020_GRBM_SOFT_RESET); 17868c2ecf20Sopenharmony_ci tmp |= grbm_soft_reset; 17878c2ecf20Sopenharmony_ci dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); 17888c2ecf20Sopenharmony_ci WREG32(R_008020_GRBM_SOFT_RESET, tmp); 17898c2ecf20Sopenharmony_ci tmp = RREG32(R_008020_GRBM_SOFT_RESET); 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci udelay(50); 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci tmp &= ~grbm_soft_reset; 17948c2ecf20Sopenharmony_ci WREG32(R_008020_GRBM_SOFT_RESET, tmp); 17958c2ecf20Sopenharmony_ci tmp = RREG32(R_008020_GRBM_SOFT_RESET); 17968c2ecf20Sopenharmony_ci } 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci if (srbm_soft_reset) { 17998c2ecf20Sopenharmony_ci tmp = RREG32(SRBM_SOFT_RESET); 18008c2ecf20Sopenharmony_ci tmp |= srbm_soft_reset; 18018c2ecf20Sopenharmony_ci dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); 18028c2ecf20Sopenharmony_ci WREG32(SRBM_SOFT_RESET, tmp); 18038c2ecf20Sopenharmony_ci tmp = RREG32(SRBM_SOFT_RESET); 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci udelay(50); 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci tmp &= ~srbm_soft_reset; 18088c2ecf20Sopenharmony_ci WREG32(SRBM_SOFT_RESET, tmp); 18098c2ecf20Sopenharmony_ci tmp = RREG32(SRBM_SOFT_RESET); 18108c2ecf20Sopenharmony_ci } 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci /* Wait a little for things to settle down */ 18138c2ecf20Sopenharmony_ci mdelay(1); 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci rv515_mc_resume(rdev, &save); 18168c2ecf20Sopenharmony_ci udelay(50); 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci r600_print_gpu_status_regs(rdev); 18198c2ecf20Sopenharmony_ci} 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_cistatic void r600_gpu_pci_config_reset(struct radeon_device *rdev) 18228c2ecf20Sopenharmony_ci{ 18238c2ecf20Sopenharmony_ci struct rv515_mc_save save; 18248c2ecf20Sopenharmony_ci u32 tmp, i; 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci dev_info(rdev->dev, "GPU pci config reset\n"); 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci /* disable dpm? */ 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci /* Disable CP parsing/prefetching */ 18318c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) 18328c2ecf20Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1)); 18338c2ecf20Sopenharmony_ci else 18348c2ecf20Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci /* disable the RLC */ 18378c2ecf20Sopenharmony_ci WREG32(RLC_CNTL, 0); 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci /* Disable DMA */ 18408c2ecf20Sopenharmony_ci tmp = RREG32(DMA_RB_CNTL); 18418c2ecf20Sopenharmony_ci tmp &= ~DMA_RB_ENABLE; 18428c2ecf20Sopenharmony_ci WREG32(DMA_RB_CNTL, tmp); 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci mdelay(50); 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci /* set mclk/sclk to bypass */ 18478c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) 18488c2ecf20Sopenharmony_ci rv770_set_clk_bypass_mode(rdev); 18498c2ecf20Sopenharmony_ci /* disable BM */ 18508c2ecf20Sopenharmony_ci pci_clear_master(rdev->pdev); 18518c2ecf20Sopenharmony_ci /* disable mem access */ 18528c2ecf20Sopenharmony_ci rv515_mc_stop(rdev, &save); 18538c2ecf20Sopenharmony_ci if (r600_mc_wait_for_idle(rdev)) { 18548c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 18558c2ecf20Sopenharmony_ci } 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci /* BIF reset workaround. Not sure if this is needed on 6xx */ 18588c2ecf20Sopenharmony_ci tmp = RREG32(BUS_CNTL); 18598c2ecf20Sopenharmony_ci tmp |= VGA_COHE_SPEC_TIMER_DIS; 18608c2ecf20Sopenharmony_ci WREG32(BUS_CNTL, tmp); 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci tmp = RREG32(BIF_SCRATCH0); 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_ci /* reset */ 18658c2ecf20Sopenharmony_ci radeon_pci_config_reset(rdev); 18668c2ecf20Sopenharmony_ci mdelay(1); 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci /* BIF reset workaround. Not sure if this is needed on 6xx */ 18698c2ecf20Sopenharmony_ci tmp = SOFT_RESET_BIF; 18708c2ecf20Sopenharmony_ci WREG32(SRBM_SOFT_RESET, tmp); 18718c2ecf20Sopenharmony_ci mdelay(1); 18728c2ecf20Sopenharmony_ci WREG32(SRBM_SOFT_RESET, 0); 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci /* wait for asic to come out of reset */ 18758c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 18768c2ecf20Sopenharmony_ci if (RREG32(CONFIG_MEMSIZE) != 0xffffffff) 18778c2ecf20Sopenharmony_ci break; 18788c2ecf20Sopenharmony_ci udelay(1); 18798c2ecf20Sopenharmony_ci } 18808c2ecf20Sopenharmony_ci} 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ciint r600_asic_reset(struct radeon_device *rdev, bool hard) 18838c2ecf20Sopenharmony_ci{ 18848c2ecf20Sopenharmony_ci u32 reset_mask; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci if (hard) { 18878c2ecf20Sopenharmony_ci r600_gpu_pci_config_reset(rdev); 18888c2ecf20Sopenharmony_ci return 0; 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci reset_mask = r600_gpu_check_soft_reset(rdev); 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci if (reset_mask) 18948c2ecf20Sopenharmony_ci r600_set_bios_scratch_engine_hung(rdev, true); 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci /* try soft reset */ 18978c2ecf20Sopenharmony_ci r600_gpu_soft_reset(rdev, reset_mask); 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci reset_mask = r600_gpu_check_soft_reset(rdev); 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci /* try pci config reset */ 19028c2ecf20Sopenharmony_ci if (reset_mask && radeon_hard_reset) 19038c2ecf20Sopenharmony_ci r600_gpu_pci_config_reset(rdev); 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci reset_mask = r600_gpu_check_soft_reset(rdev); 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci if (!reset_mask) 19088c2ecf20Sopenharmony_ci r600_set_bios_scratch_engine_hung(rdev, false); 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci return 0; 19118c2ecf20Sopenharmony_ci} 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci/** 19148c2ecf20Sopenharmony_ci * r600_gfx_is_lockup - Check if the GFX engine is locked up 19158c2ecf20Sopenharmony_ci * 19168c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 19178c2ecf20Sopenharmony_ci * @ring: radeon_ring structure holding ring information 19188c2ecf20Sopenharmony_ci * 19198c2ecf20Sopenharmony_ci * Check if the GFX engine is locked up. 19208c2ecf20Sopenharmony_ci * Returns true if the engine appears to be locked up, false if not. 19218c2ecf20Sopenharmony_ci */ 19228c2ecf20Sopenharmony_cibool r600_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) 19238c2ecf20Sopenharmony_ci{ 19248c2ecf20Sopenharmony_ci u32 reset_mask = r600_gpu_check_soft_reset(rdev); 19258c2ecf20Sopenharmony_ci 19268c2ecf20Sopenharmony_ci if (!(reset_mask & (RADEON_RESET_GFX | 19278c2ecf20Sopenharmony_ci RADEON_RESET_COMPUTE | 19288c2ecf20Sopenharmony_ci RADEON_RESET_CP))) { 19298c2ecf20Sopenharmony_ci radeon_ring_lockup_update(rdev, ring); 19308c2ecf20Sopenharmony_ci return false; 19318c2ecf20Sopenharmony_ci } 19328c2ecf20Sopenharmony_ci return radeon_ring_test_lockup(rdev, ring); 19338c2ecf20Sopenharmony_ci} 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ciu32 r6xx_remap_render_backend(struct radeon_device *rdev, 19368c2ecf20Sopenharmony_ci u32 tiling_pipe_num, 19378c2ecf20Sopenharmony_ci u32 max_rb_num, 19388c2ecf20Sopenharmony_ci u32 total_max_rb_num, 19398c2ecf20Sopenharmony_ci u32 disabled_rb_mask) 19408c2ecf20Sopenharmony_ci{ 19418c2ecf20Sopenharmony_ci u32 rendering_pipe_num, rb_num_width, req_rb_num; 19428c2ecf20Sopenharmony_ci u32 pipe_rb_ratio, pipe_rb_remain, tmp; 19438c2ecf20Sopenharmony_ci u32 data = 0, mask = 1 << (max_rb_num - 1); 19448c2ecf20Sopenharmony_ci unsigned i, j; 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci /* mask out the RBs that don't exist on that asic */ 19478c2ecf20Sopenharmony_ci tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff); 19488c2ecf20Sopenharmony_ci /* make sure at least one RB is available */ 19498c2ecf20Sopenharmony_ci if ((tmp & 0xff) != 0xff) 19508c2ecf20Sopenharmony_ci disabled_rb_mask = tmp; 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci rendering_pipe_num = 1 << tiling_pipe_num; 19538c2ecf20Sopenharmony_ci req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask); 19548c2ecf20Sopenharmony_ci BUG_ON(rendering_pipe_num < req_rb_num); 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci pipe_rb_ratio = rendering_pipe_num / req_rb_num; 19578c2ecf20Sopenharmony_ci pipe_rb_remain = rendering_pipe_num - pipe_rb_ratio * req_rb_num; 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci if (rdev->family <= CHIP_RV740) { 19608c2ecf20Sopenharmony_ci /* r6xx/r7xx */ 19618c2ecf20Sopenharmony_ci rb_num_width = 2; 19628c2ecf20Sopenharmony_ci } else { 19638c2ecf20Sopenharmony_ci /* eg+ */ 19648c2ecf20Sopenharmony_ci rb_num_width = 4; 19658c2ecf20Sopenharmony_ci } 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci for (i = 0; i < max_rb_num; i++) { 19688c2ecf20Sopenharmony_ci if (!(mask & disabled_rb_mask)) { 19698c2ecf20Sopenharmony_ci for (j = 0; j < pipe_rb_ratio; j++) { 19708c2ecf20Sopenharmony_ci data <<= rb_num_width; 19718c2ecf20Sopenharmony_ci data |= max_rb_num - i - 1; 19728c2ecf20Sopenharmony_ci } 19738c2ecf20Sopenharmony_ci if (pipe_rb_remain) { 19748c2ecf20Sopenharmony_ci data <<= rb_num_width; 19758c2ecf20Sopenharmony_ci data |= max_rb_num - i - 1; 19768c2ecf20Sopenharmony_ci pipe_rb_remain--; 19778c2ecf20Sopenharmony_ci } 19788c2ecf20Sopenharmony_ci } 19798c2ecf20Sopenharmony_ci mask >>= 1; 19808c2ecf20Sopenharmony_ci } 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci return data; 19838c2ecf20Sopenharmony_ci} 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ciint r600_count_pipe_bits(uint32_t val) 19868c2ecf20Sopenharmony_ci{ 19878c2ecf20Sopenharmony_ci return hweight32(val); 19888c2ecf20Sopenharmony_ci} 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_cistatic void r600_gpu_init(struct radeon_device *rdev) 19918c2ecf20Sopenharmony_ci{ 19928c2ecf20Sopenharmony_ci u32 tiling_config; 19938c2ecf20Sopenharmony_ci u32 ramcfg; 19948c2ecf20Sopenharmony_ci u32 cc_gc_shader_pipe_config; 19958c2ecf20Sopenharmony_ci u32 tmp; 19968c2ecf20Sopenharmony_ci int i, j; 19978c2ecf20Sopenharmony_ci u32 sq_config; 19988c2ecf20Sopenharmony_ci u32 sq_gpr_resource_mgmt_1 = 0; 19998c2ecf20Sopenharmony_ci u32 sq_gpr_resource_mgmt_2 = 0; 20008c2ecf20Sopenharmony_ci u32 sq_thread_resource_mgmt = 0; 20018c2ecf20Sopenharmony_ci u32 sq_stack_resource_mgmt_1 = 0; 20028c2ecf20Sopenharmony_ci u32 sq_stack_resource_mgmt_2 = 0; 20038c2ecf20Sopenharmony_ci u32 disabled_rb_mask; 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci rdev->config.r600.tiling_group_size = 256; 20068c2ecf20Sopenharmony_ci switch (rdev->family) { 20078c2ecf20Sopenharmony_ci case CHIP_R600: 20088c2ecf20Sopenharmony_ci rdev->config.r600.max_pipes = 4; 20098c2ecf20Sopenharmony_ci rdev->config.r600.max_tile_pipes = 8; 20108c2ecf20Sopenharmony_ci rdev->config.r600.max_simds = 4; 20118c2ecf20Sopenharmony_ci rdev->config.r600.max_backends = 4; 20128c2ecf20Sopenharmony_ci rdev->config.r600.max_gprs = 256; 20138c2ecf20Sopenharmony_ci rdev->config.r600.max_threads = 192; 20148c2ecf20Sopenharmony_ci rdev->config.r600.max_stack_entries = 256; 20158c2ecf20Sopenharmony_ci rdev->config.r600.max_hw_contexts = 8; 20168c2ecf20Sopenharmony_ci rdev->config.r600.max_gs_threads = 16; 20178c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_size = 128; 20188c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_pos_size = 16; 20198c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_smx_size = 128; 20208c2ecf20Sopenharmony_ci rdev->config.r600.sq_num_cf_insts = 2; 20218c2ecf20Sopenharmony_ci break; 20228c2ecf20Sopenharmony_ci case CHIP_RV630: 20238c2ecf20Sopenharmony_ci case CHIP_RV635: 20248c2ecf20Sopenharmony_ci rdev->config.r600.max_pipes = 2; 20258c2ecf20Sopenharmony_ci rdev->config.r600.max_tile_pipes = 2; 20268c2ecf20Sopenharmony_ci rdev->config.r600.max_simds = 3; 20278c2ecf20Sopenharmony_ci rdev->config.r600.max_backends = 1; 20288c2ecf20Sopenharmony_ci rdev->config.r600.max_gprs = 128; 20298c2ecf20Sopenharmony_ci rdev->config.r600.max_threads = 192; 20308c2ecf20Sopenharmony_ci rdev->config.r600.max_stack_entries = 128; 20318c2ecf20Sopenharmony_ci rdev->config.r600.max_hw_contexts = 8; 20328c2ecf20Sopenharmony_ci rdev->config.r600.max_gs_threads = 4; 20338c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_size = 128; 20348c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_pos_size = 16; 20358c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_smx_size = 128; 20368c2ecf20Sopenharmony_ci rdev->config.r600.sq_num_cf_insts = 2; 20378c2ecf20Sopenharmony_ci break; 20388c2ecf20Sopenharmony_ci case CHIP_RV610: 20398c2ecf20Sopenharmony_ci case CHIP_RV620: 20408c2ecf20Sopenharmony_ci case CHIP_RS780: 20418c2ecf20Sopenharmony_ci case CHIP_RS880: 20428c2ecf20Sopenharmony_ci rdev->config.r600.max_pipes = 1; 20438c2ecf20Sopenharmony_ci rdev->config.r600.max_tile_pipes = 1; 20448c2ecf20Sopenharmony_ci rdev->config.r600.max_simds = 2; 20458c2ecf20Sopenharmony_ci rdev->config.r600.max_backends = 1; 20468c2ecf20Sopenharmony_ci rdev->config.r600.max_gprs = 128; 20478c2ecf20Sopenharmony_ci rdev->config.r600.max_threads = 192; 20488c2ecf20Sopenharmony_ci rdev->config.r600.max_stack_entries = 128; 20498c2ecf20Sopenharmony_ci rdev->config.r600.max_hw_contexts = 4; 20508c2ecf20Sopenharmony_ci rdev->config.r600.max_gs_threads = 4; 20518c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_size = 128; 20528c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_pos_size = 16; 20538c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_smx_size = 128; 20548c2ecf20Sopenharmony_ci rdev->config.r600.sq_num_cf_insts = 1; 20558c2ecf20Sopenharmony_ci break; 20568c2ecf20Sopenharmony_ci case CHIP_RV670: 20578c2ecf20Sopenharmony_ci rdev->config.r600.max_pipes = 4; 20588c2ecf20Sopenharmony_ci rdev->config.r600.max_tile_pipes = 4; 20598c2ecf20Sopenharmony_ci rdev->config.r600.max_simds = 4; 20608c2ecf20Sopenharmony_ci rdev->config.r600.max_backends = 4; 20618c2ecf20Sopenharmony_ci rdev->config.r600.max_gprs = 192; 20628c2ecf20Sopenharmony_ci rdev->config.r600.max_threads = 192; 20638c2ecf20Sopenharmony_ci rdev->config.r600.max_stack_entries = 256; 20648c2ecf20Sopenharmony_ci rdev->config.r600.max_hw_contexts = 8; 20658c2ecf20Sopenharmony_ci rdev->config.r600.max_gs_threads = 16; 20668c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_size = 128; 20678c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_pos_size = 16; 20688c2ecf20Sopenharmony_ci rdev->config.r600.sx_max_export_smx_size = 128; 20698c2ecf20Sopenharmony_ci rdev->config.r600.sq_num_cf_insts = 2; 20708c2ecf20Sopenharmony_ci break; 20718c2ecf20Sopenharmony_ci default: 20728c2ecf20Sopenharmony_ci break; 20738c2ecf20Sopenharmony_ci } 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci /* Initialize HDP */ 20768c2ecf20Sopenharmony_ci for (i = 0, j = 0; i < 32; i++, j += 0x18) { 20778c2ecf20Sopenharmony_ci WREG32((0x2c14 + j), 0x00000000); 20788c2ecf20Sopenharmony_ci WREG32((0x2c18 + j), 0x00000000); 20798c2ecf20Sopenharmony_ci WREG32((0x2c1c + j), 0x00000000); 20808c2ecf20Sopenharmony_ci WREG32((0x2c20 + j), 0x00000000); 20818c2ecf20Sopenharmony_ci WREG32((0x2c24 + j), 0x00000000); 20828c2ecf20Sopenharmony_ci } 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci /* Setup tiling */ 20878c2ecf20Sopenharmony_ci tiling_config = 0; 20888c2ecf20Sopenharmony_ci ramcfg = RREG32(RAMCFG); 20898c2ecf20Sopenharmony_ci switch (rdev->config.r600.max_tile_pipes) { 20908c2ecf20Sopenharmony_ci case 1: 20918c2ecf20Sopenharmony_ci tiling_config |= PIPE_TILING(0); 20928c2ecf20Sopenharmony_ci break; 20938c2ecf20Sopenharmony_ci case 2: 20948c2ecf20Sopenharmony_ci tiling_config |= PIPE_TILING(1); 20958c2ecf20Sopenharmony_ci break; 20968c2ecf20Sopenharmony_ci case 4: 20978c2ecf20Sopenharmony_ci tiling_config |= PIPE_TILING(2); 20988c2ecf20Sopenharmony_ci break; 20998c2ecf20Sopenharmony_ci case 8: 21008c2ecf20Sopenharmony_ci tiling_config |= PIPE_TILING(3); 21018c2ecf20Sopenharmony_ci break; 21028c2ecf20Sopenharmony_ci default: 21038c2ecf20Sopenharmony_ci break; 21048c2ecf20Sopenharmony_ci } 21058c2ecf20Sopenharmony_ci rdev->config.r600.tiling_npipes = rdev->config.r600.max_tile_pipes; 21068c2ecf20Sopenharmony_ci rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); 21078c2ecf20Sopenharmony_ci tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); 21088c2ecf20Sopenharmony_ci tiling_config |= GROUP_SIZE((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT; 21118c2ecf20Sopenharmony_ci if (tmp > 3) { 21128c2ecf20Sopenharmony_ci tiling_config |= ROW_TILING(3); 21138c2ecf20Sopenharmony_ci tiling_config |= SAMPLE_SPLIT(3); 21148c2ecf20Sopenharmony_ci } else { 21158c2ecf20Sopenharmony_ci tiling_config |= ROW_TILING(tmp); 21168c2ecf20Sopenharmony_ci tiling_config |= SAMPLE_SPLIT(tmp); 21178c2ecf20Sopenharmony_ci } 21188c2ecf20Sopenharmony_ci tiling_config |= BANK_SWAPS(1); 21198c2ecf20Sopenharmony_ci 21208c2ecf20Sopenharmony_ci cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0x00ffff00; 21218c2ecf20Sopenharmony_ci tmp = rdev->config.r600.max_simds - 21228c2ecf20Sopenharmony_ci r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK); 21238c2ecf20Sopenharmony_ci rdev->config.r600.active_simds = tmp; 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R6XX_MAX_BACKENDS_MASK; 21268c2ecf20Sopenharmony_ci tmp = 0; 21278c2ecf20Sopenharmony_ci for (i = 0; i < rdev->config.r600.max_backends; i++) 21288c2ecf20Sopenharmony_ci tmp |= (1 << i); 21298c2ecf20Sopenharmony_ci /* if all the backends are disabled, fix it up here */ 21308c2ecf20Sopenharmony_ci if ((disabled_rb_mask & tmp) == tmp) { 21318c2ecf20Sopenharmony_ci for (i = 0; i < rdev->config.r600.max_backends; i++) 21328c2ecf20Sopenharmony_ci disabled_rb_mask &= ~(1 << i); 21338c2ecf20Sopenharmony_ci } 21348c2ecf20Sopenharmony_ci tmp = (tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; 21358c2ecf20Sopenharmony_ci tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.r600.max_backends, 21368c2ecf20Sopenharmony_ci R6XX_MAX_BACKENDS, disabled_rb_mask); 21378c2ecf20Sopenharmony_ci tiling_config |= tmp << 16; 21388c2ecf20Sopenharmony_ci rdev->config.r600.backend_map = tmp; 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci rdev->config.r600.tile_config = tiling_config; 21418c2ecf20Sopenharmony_ci WREG32(GB_TILING_CONFIG, tiling_config); 21428c2ecf20Sopenharmony_ci WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff); 21438c2ecf20Sopenharmony_ci WREG32(HDP_TILING_CONFIG, tiling_config & 0xffff); 21448c2ecf20Sopenharmony_ci WREG32(DMA_TILING_CONFIG, tiling_config & 0xffff); 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci tmp = R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); 21478c2ecf20Sopenharmony_ci WREG32(VGT_OUT_DEALLOC_CNTL, (tmp * 4) & DEALLOC_DIST_MASK); 21488c2ecf20Sopenharmony_ci WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((tmp * 4) - 2) & VTX_REUSE_DEPTH_MASK); 21498c2ecf20Sopenharmony_ci 21508c2ecf20Sopenharmony_ci /* Setup some CP states */ 21518c2ecf20Sopenharmony_ci WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | ROQ_IB2_START(0x2b))); 21528c2ecf20Sopenharmony_ci WREG32(CP_MEQ_THRESHOLDS, (MEQ_END(0x40) | ROQ_END(0x40))); 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci WREG32(TA_CNTL_AUX, (DISABLE_CUBE_ANISO | SYNC_GRADIENT | 21558c2ecf20Sopenharmony_ci SYNC_WALKER | SYNC_ALIGNER)); 21568c2ecf20Sopenharmony_ci /* Setup various GPU states */ 21578c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RV670) 21588c2ecf20Sopenharmony_ci WREG32(ARB_GDEC_RD_CNTL, 0x00000021); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci tmp = RREG32(SX_DEBUG_1); 21618c2ecf20Sopenharmony_ci tmp |= SMX_EVENT_RELEASE; 21628c2ecf20Sopenharmony_ci if ((rdev->family > CHIP_R600)) 21638c2ecf20Sopenharmony_ci tmp |= ENABLE_NEW_SMX_ADDRESS; 21648c2ecf20Sopenharmony_ci WREG32(SX_DEBUG_1, tmp); 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci if (((rdev->family) == CHIP_R600) || 21678c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RV630) || 21688c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RV610) || 21698c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RV620) || 21708c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RS780) || 21718c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RS880)) { 21728c2ecf20Sopenharmony_ci WREG32(DB_DEBUG, PREZ_MUST_WAIT_FOR_POSTZ_DONE); 21738c2ecf20Sopenharmony_ci } else { 21748c2ecf20Sopenharmony_ci WREG32(DB_DEBUG, 0); 21758c2ecf20Sopenharmony_ci } 21768c2ecf20Sopenharmony_ci WREG32(DB_WATERMARKS, (DEPTH_FREE(4) | DEPTH_CACHELINE_FREE(16) | 21778c2ecf20Sopenharmony_ci DEPTH_FLUSH(16) | DEPTH_PENDING_FREE(4))); 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci WREG32(PA_SC_MULTI_CHIP_CNTL, 0); 21808c2ecf20Sopenharmony_ci WREG32(VGT_NUM_INSTANCES, 0); 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci WREG32(SPI_CONFIG_CNTL, GPR_WRITE_PRIORITY(0)); 21838c2ecf20Sopenharmony_ci WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(0)); 21848c2ecf20Sopenharmony_ci 21858c2ecf20Sopenharmony_ci tmp = RREG32(SQ_MS_FIFO_SIZES); 21868c2ecf20Sopenharmony_ci if (((rdev->family) == CHIP_RV610) || 21878c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RV620) || 21888c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RS780) || 21898c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RS880)) { 21908c2ecf20Sopenharmony_ci tmp = (CACHE_FIFO_SIZE(0xa) | 21918c2ecf20Sopenharmony_ci FETCH_FIFO_HIWATER(0xa) | 21928c2ecf20Sopenharmony_ci DONE_FIFO_HIWATER(0xe0) | 21938c2ecf20Sopenharmony_ci ALU_UPDATE_FIFO_HIWATER(0x8)); 21948c2ecf20Sopenharmony_ci } else if (((rdev->family) == CHIP_R600) || 21958c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RV630)) { 21968c2ecf20Sopenharmony_ci tmp &= ~DONE_FIFO_HIWATER(0xff); 21978c2ecf20Sopenharmony_ci tmp |= DONE_FIFO_HIWATER(0x4); 21988c2ecf20Sopenharmony_ci } 21998c2ecf20Sopenharmony_ci WREG32(SQ_MS_FIFO_SIZES, tmp); 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT 22028c2ecf20Sopenharmony_ci * should be adjusted as needed by the 2D/3D drivers. This just sets default values 22038c2ecf20Sopenharmony_ci */ 22048c2ecf20Sopenharmony_ci sq_config = RREG32(SQ_CONFIG); 22058c2ecf20Sopenharmony_ci sq_config &= ~(PS_PRIO(3) | 22068c2ecf20Sopenharmony_ci VS_PRIO(3) | 22078c2ecf20Sopenharmony_ci GS_PRIO(3) | 22088c2ecf20Sopenharmony_ci ES_PRIO(3)); 22098c2ecf20Sopenharmony_ci sq_config |= (DX9_CONSTS | 22108c2ecf20Sopenharmony_ci VC_ENABLE | 22118c2ecf20Sopenharmony_ci PS_PRIO(0) | 22128c2ecf20Sopenharmony_ci VS_PRIO(1) | 22138c2ecf20Sopenharmony_ci GS_PRIO(2) | 22148c2ecf20Sopenharmony_ci ES_PRIO(3)); 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci if ((rdev->family) == CHIP_R600) { 22178c2ecf20Sopenharmony_ci sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(124) | 22188c2ecf20Sopenharmony_ci NUM_VS_GPRS(124) | 22198c2ecf20Sopenharmony_ci NUM_CLAUSE_TEMP_GPRS(4)); 22208c2ecf20Sopenharmony_ci sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(0) | 22218c2ecf20Sopenharmony_ci NUM_ES_GPRS(0)); 22228c2ecf20Sopenharmony_ci sq_thread_resource_mgmt = (NUM_PS_THREADS(136) | 22238c2ecf20Sopenharmony_ci NUM_VS_THREADS(48) | 22248c2ecf20Sopenharmony_ci NUM_GS_THREADS(4) | 22258c2ecf20Sopenharmony_ci NUM_ES_THREADS(4)); 22268c2ecf20Sopenharmony_ci sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(128) | 22278c2ecf20Sopenharmony_ci NUM_VS_STACK_ENTRIES(128)); 22288c2ecf20Sopenharmony_ci sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(0) | 22298c2ecf20Sopenharmony_ci NUM_ES_STACK_ENTRIES(0)); 22308c2ecf20Sopenharmony_ci } else if (((rdev->family) == CHIP_RV610) || 22318c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RV620) || 22328c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RS780) || 22338c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RS880)) { 22348c2ecf20Sopenharmony_ci /* no vertex cache */ 22358c2ecf20Sopenharmony_ci sq_config &= ~VC_ENABLE; 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_ci sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | 22388c2ecf20Sopenharmony_ci NUM_VS_GPRS(44) | 22398c2ecf20Sopenharmony_ci NUM_CLAUSE_TEMP_GPRS(2)); 22408c2ecf20Sopenharmony_ci sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(17) | 22418c2ecf20Sopenharmony_ci NUM_ES_GPRS(17)); 22428c2ecf20Sopenharmony_ci sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | 22438c2ecf20Sopenharmony_ci NUM_VS_THREADS(78) | 22448c2ecf20Sopenharmony_ci NUM_GS_THREADS(4) | 22458c2ecf20Sopenharmony_ci NUM_ES_THREADS(31)); 22468c2ecf20Sopenharmony_ci sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(40) | 22478c2ecf20Sopenharmony_ci NUM_VS_STACK_ENTRIES(40)); 22488c2ecf20Sopenharmony_ci sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(32) | 22498c2ecf20Sopenharmony_ci NUM_ES_STACK_ENTRIES(16)); 22508c2ecf20Sopenharmony_ci } else if (((rdev->family) == CHIP_RV630) || 22518c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RV635)) { 22528c2ecf20Sopenharmony_ci sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | 22538c2ecf20Sopenharmony_ci NUM_VS_GPRS(44) | 22548c2ecf20Sopenharmony_ci NUM_CLAUSE_TEMP_GPRS(2)); 22558c2ecf20Sopenharmony_ci sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(18) | 22568c2ecf20Sopenharmony_ci NUM_ES_GPRS(18)); 22578c2ecf20Sopenharmony_ci sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | 22588c2ecf20Sopenharmony_ci NUM_VS_THREADS(78) | 22598c2ecf20Sopenharmony_ci NUM_GS_THREADS(4) | 22608c2ecf20Sopenharmony_ci NUM_ES_THREADS(31)); 22618c2ecf20Sopenharmony_ci sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(40) | 22628c2ecf20Sopenharmony_ci NUM_VS_STACK_ENTRIES(40)); 22638c2ecf20Sopenharmony_ci sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(32) | 22648c2ecf20Sopenharmony_ci NUM_ES_STACK_ENTRIES(16)); 22658c2ecf20Sopenharmony_ci } else if ((rdev->family) == CHIP_RV670) { 22668c2ecf20Sopenharmony_ci sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | 22678c2ecf20Sopenharmony_ci NUM_VS_GPRS(44) | 22688c2ecf20Sopenharmony_ci NUM_CLAUSE_TEMP_GPRS(2)); 22698c2ecf20Sopenharmony_ci sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(17) | 22708c2ecf20Sopenharmony_ci NUM_ES_GPRS(17)); 22718c2ecf20Sopenharmony_ci sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | 22728c2ecf20Sopenharmony_ci NUM_VS_THREADS(78) | 22738c2ecf20Sopenharmony_ci NUM_GS_THREADS(4) | 22748c2ecf20Sopenharmony_ci NUM_ES_THREADS(31)); 22758c2ecf20Sopenharmony_ci sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(64) | 22768c2ecf20Sopenharmony_ci NUM_VS_STACK_ENTRIES(64)); 22778c2ecf20Sopenharmony_ci sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(64) | 22788c2ecf20Sopenharmony_ci NUM_ES_STACK_ENTRIES(64)); 22798c2ecf20Sopenharmony_ci } 22808c2ecf20Sopenharmony_ci 22818c2ecf20Sopenharmony_ci WREG32(SQ_CONFIG, sq_config); 22828c2ecf20Sopenharmony_ci WREG32(SQ_GPR_RESOURCE_MGMT_1, sq_gpr_resource_mgmt_1); 22838c2ecf20Sopenharmony_ci WREG32(SQ_GPR_RESOURCE_MGMT_2, sq_gpr_resource_mgmt_2); 22848c2ecf20Sopenharmony_ci WREG32(SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); 22858c2ecf20Sopenharmony_ci WREG32(SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1); 22868c2ecf20Sopenharmony_ci WREG32(SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2); 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_ci if (((rdev->family) == CHIP_RV610) || 22898c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RV620) || 22908c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RS780) || 22918c2ecf20Sopenharmony_ci ((rdev->family) == CHIP_RS880)) { 22928c2ecf20Sopenharmony_ci WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(TC_ONLY)); 22938c2ecf20Sopenharmony_ci } else { 22948c2ecf20Sopenharmony_ci WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC)); 22958c2ecf20Sopenharmony_ci } 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ci /* More default values. 2D/3D driver should adjust as needed */ 22988c2ecf20Sopenharmony_ci WREG32(PA_SC_AA_SAMPLE_LOCS_2S, (S0_X(0xc) | S0_Y(0x4) | 22998c2ecf20Sopenharmony_ci S1_X(0x4) | S1_Y(0xc))); 23008c2ecf20Sopenharmony_ci WREG32(PA_SC_AA_SAMPLE_LOCS_4S, (S0_X(0xe) | S0_Y(0xe) | 23018c2ecf20Sopenharmony_ci S1_X(0x2) | S1_Y(0x2) | 23028c2ecf20Sopenharmony_ci S2_X(0xa) | S2_Y(0x6) | 23038c2ecf20Sopenharmony_ci S3_X(0x6) | S3_Y(0xa))); 23048c2ecf20Sopenharmony_ci WREG32(PA_SC_AA_SAMPLE_LOCS_8S_WD0, (S0_X(0xe) | S0_Y(0xb) | 23058c2ecf20Sopenharmony_ci S1_X(0x4) | S1_Y(0xc) | 23068c2ecf20Sopenharmony_ci S2_X(0x1) | S2_Y(0x6) | 23078c2ecf20Sopenharmony_ci S3_X(0xa) | S3_Y(0xe))); 23088c2ecf20Sopenharmony_ci WREG32(PA_SC_AA_SAMPLE_LOCS_8S_WD1, (S4_X(0x6) | S4_Y(0x1) | 23098c2ecf20Sopenharmony_ci S5_X(0x0) | S5_Y(0x0) | 23108c2ecf20Sopenharmony_ci S6_X(0xb) | S6_Y(0x4) | 23118c2ecf20Sopenharmony_ci S7_X(0x7) | S7_Y(0x8))); 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_ci WREG32(VGT_STRMOUT_EN, 0); 23148c2ecf20Sopenharmony_ci tmp = rdev->config.r600.max_pipes * 16; 23158c2ecf20Sopenharmony_ci switch (rdev->family) { 23168c2ecf20Sopenharmony_ci case CHIP_RV610: 23178c2ecf20Sopenharmony_ci case CHIP_RV620: 23188c2ecf20Sopenharmony_ci case CHIP_RS780: 23198c2ecf20Sopenharmony_ci case CHIP_RS880: 23208c2ecf20Sopenharmony_ci tmp += 32; 23218c2ecf20Sopenharmony_ci break; 23228c2ecf20Sopenharmony_ci case CHIP_RV670: 23238c2ecf20Sopenharmony_ci tmp += 128; 23248c2ecf20Sopenharmony_ci break; 23258c2ecf20Sopenharmony_ci default: 23268c2ecf20Sopenharmony_ci break; 23278c2ecf20Sopenharmony_ci } 23288c2ecf20Sopenharmony_ci if (tmp > 256) { 23298c2ecf20Sopenharmony_ci tmp = 256; 23308c2ecf20Sopenharmony_ci } 23318c2ecf20Sopenharmony_ci WREG32(VGT_ES_PER_GS, 128); 23328c2ecf20Sopenharmony_ci WREG32(VGT_GS_PER_ES, tmp); 23338c2ecf20Sopenharmony_ci WREG32(VGT_GS_PER_VS, 2); 23348c2ecf20Sopenharmony_ci WREG32(VGT_GS_VERTEX_REUSE, 16); 23358c2ecf20Sopenharmony_ci 23368c2ecf20Sopenharmony_ci /* more default values. 2D/3D driver should adjust as needed */ 23378c2ecf20Sopenharmony_ci WREG32(PA_SC_LINE_STIPPLE_STATE, 0); 23388c2ecf20Sopenharmony_ci WREG32(VGT_STRMOUT_EN, 0); 23398c2ecf20Sopenharmony_ci WREG32(SX_MISC, 0); 23408c2ecf20Sopenharmony_ci WREG32(PA_SC_MODE_CNTL, 0); 23418c2ecf20Sopenharmony_ci WREG32(PA_SC_AA_CONFIG, 0); 23428c2ecf20Sopenharmony_ci WREG32(PA_SC_LINE_STIPPLE, 0); 23438c2ecf20Sopenharmony_ci WREG32(SPI_INPUT_Z, 0); 23448c2ecf20Sopenharmony_ci WREG32(SPI_PS_IN_CONTROL_0, NUM_INTERP(2)); 23458c2ecf20Sopenharmony_ci WREG32(CB_COLOR7_FRAG, 0); 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci /* Clear render buffer base addresses */ 23488c2ecf20Sopenharmony_ci WREG32(CB_COLOR0_BASE, 0); 23498c2ecf20Sopenharmony_ci WREG32(CB_COLOR1_BASE, 0); 23508c2ecf20Sopenharmony_ci WREG32(CB_COLOR2_BASE, 0); 23518c2ecf20Sopenharmony_ci WREG32(CB_COLOR3_BASE, 0); 23528c2ecf20Sopenharmony_ci WREG32(CB_COLOR4_BASE, 0); 23538c2ecf20Sopenharmony_ci WREG32(CB_COLOR5_BASE, 0); 23548c2ecf20Sopenharmony_ci WREG32(CB_COLOR6_BASE, 0); 23558c2ecf20Sopenharmony_ci WREG32(CB_COLOR7_BASE, 0); 23568c2ecf20Sopenharmony_ci WREG32(CB_COLOR7_FRAG, 0); 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci switch (rdev->family) { 23598c2ecf20Sopenharmony_ci case CHIP_RV610: 23608c2ecf20Sopenharmony_ci case CHIP_RV620: 23618c2ecf20Sopenharmony_ci case CHIP_RS780: 23628c2ecf20Sopenharmony_ci case CHIP_RS880: 23638c2ecf20Sopenharmony_ci tmp = TC_L2_SIZE(8); 23648c2ecf20Sopenharmony_ci break; 23658c2ecf20Sopenharmony_ci case CHIP_RV630: 23668c2ecf20Sopenharmony_ci case CHIP_RV635: 23678c2ecf20Sopenharmony_ci tmp = TC_L2_SIZE(4); 23688c2ecf20Sopenharmony_ci break; 23698c2ecf20Sopenharmony_ci case CHIP_R600: 23708c2ecf20Sopenharmony_ci tmp = TC_L2_SIZE(0) | L2_DISABLE_LATE_HIT; 23718c2ecf20Sopenharmony_ci break; 23728c2ecf20Sopenharmony_ci default: 23738c2ecf20Sopenharmony_ci tmp = TC_L2_SIZE(0); 23748c2ecf20Sopenharmony_ci break; 23758c2ecf20Sopenharmony_ci } 23768c2ecf20Sopenharmony_ci WREG32(TC_CNTL, tmp); 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci tmp = RREG32(HDP_HOST_PATH_CNTL); 23798c2ecf20Sopenharmony_ci WREG32(HDP_HOST_PATH_CNTL, tmp); 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci tmp = RREG32(ARB_POP); 23828c2ecf20Sopenharmony_ci tmp |= ENABLE_TC128; 23838c2ecf20Sopenharmony_ci WREG32(ARB_POP, tmp); 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci WREG32(PA_SC_MULTI_CHIP_CNTL, 0); 23868c2ecf20Sopenharmony_ci WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA | 23878c2ecf20Sopenharmony_ci NUM_CLIP_SEQ(3))); 23888c2ecf20Sopenharmony_ci WREG32(PA_SC_ENHANCE, FORCE_EOV_MAX_CLK_CNT(4095)); 23898c2ecf20Sopenharmony_ci WREG32(VC_ENHANCE, 0); 23908c2ecf20Sopenharmony_ci} 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci 23938c2ecf20Sopenharmony_ci/* 23948c2ecf20Sopenharmony_ci * Indirect registers accessor 23958c2ecf20Sopenharmony_ci */ 23968c2ecf20Sopenharmony_ciu32 r600_pciep_rreg(struct radeon_device *rdev, u32 reg) 23978c2ecf20Sopenharmony_ci{ 23988c2ecf20Sopenharmony_ci unsigned long flags; 23998c2ecf20Sopenharmony_ci u32 r; 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->pciep_idx_lock, flags); 24028c2ecf20Sopenharmony_ci WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); 24038c2ecf20Sopenharmony_ci (void)RREG32(PCIE_PORT_INDEX); 24048c2ecf20Sopenharmony_ci r = RREG32(PCIE_PORT_DATA); 24058c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags); 24068c2ecf20Sopenharmony_ci return r; 24078c2ecf20Sopenharmony_ci} 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_civoid r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) 24108c2ecf20Sopenharmony_ci{ 24118c2ecf20Sopenharmony_ci unsigned long flags; 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->pciep_idx_lock, flags); 24148c2ecf20Sopenharmony_ci WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); 24158c2ecf20Sopenharmony_ci (void)RREG32(PCIE_PORT_INDEX); 24168c2ecf20Sopenharmony_ci WREG32(PCIE_PORT_DATA, (v)); 24178c2ecf20Sopenharmony_ci (void)RREG32(PCIE_PORT_DATA); 24188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags); 24198c2ecf20Sopenharmony_ci} 24208c2ecf20Sopenharmony_ci 24218c2ecf20Sopenharmony_ci/* 24228c2ecf20Sopenharmony_ci * CP & Ring 24238c2ecf20Sopenharmony_ci */ 24248c2ecf20Sopenharmony_civoid r600_cp_stop(struct radeon_device *rdev) 24258c2ecf20Sopenharmony_ci{ 24268c2ecf20Sopenharmony_ci if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) 24278c2ecf20Sopenharmony_ci radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); 24288c2ecf20Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); 24298c2ecf20Sopenharmony_ci WREG32(SCRATCH_UMSK, 0); 24308c2ecf20Sopenharmony_ci rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; 24318c2ecf20Sopenharmony_ci} 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ciint r600_init_microcode(struct radeon_device *rdev) 24348c2ecf20Sopenharmony_ci{ 24358c2ecf20Sopenharmony_ci const char *chip_name; 24368c2ecf20Sopenharmony_ci const char *rlc_chip_name; 24378c2ecf20Sopenharmony_ci const char *smc_chip_name = "RV770"; 24388c2ecf20Sopenharmony_ci size_t pfp_req_size, me_req_size, rlc_req_size, smc_req_size = 0; 24398c2ecf20Sopenharmony_ci char fw_name[30]; 24408c2ecf20Sopenharmony_ci int err; 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci DRM_DEBUG("\n"); 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_ci switch (rdev->family) { 24458c2ecf20Sopenharmony_ci case CHIP_R600: 24468c2ecf20Sopenharmony_ci chip_name = "R600"; 24478c2ecf20Sopenharmony_ci rlc_chip_name = "R600"; 24488c2ecf20Sopenharmony_ci break; 24498c2ecf20Sopenharmony_ci case CHIP_RV610: 24508c2ecf20Sopenharmony_ci chip_name = "RV610"; 24518c2ecf20Sopenharmony_ci rlc_chip_name = "R600"; 24528c2ecf20Sopenharmony_ci break; 24538c2ecf20Sopenharmony_ci case CHIP_RV630: 24548c2ecf20Sopenharmony_ci chip_name = "RV630"; 24558c2ecf20Sopenharmony_ci rlc_chip_name = "R600"; 24568c2ecf20Sopenharmony_ci break; 24578c2ecf20Sopenharmony_ci case CHIP_RV620: 24588c2ecf20Sopenharmony_ci chip_name = "RV620"; 24598c2ecf20Sopenharmony_ci rlc_chip_name = "R600"; 24608c2ecf20Sopenharmony_ci break; 24618c2ecf20Sopenharmony_ci case CHIP_RV635: 24628c2ecf20Sopenharmony_ci chip_name = "RV635"; 24638c2ecf20Sopenharmony_ci rlc_chip_name = "R600"; 24648c2ecf20Sopenharmony_ci break; 24658c2ecf20Sopenharmony_ci case CHIP_RV670: 24668c2ecf20Sopenharmony_ci chip_name = "RV670"; 24678c2ecf20Sopenharmony_ci rlc_chip_name = "R600"; 24688c2ecf20Sopenharmony_ci break; 24698c2ecf20Sopenharmony_ci case CHIP_RS780: 24708c2ecf20Sopenharmony_ci case CHIP_RS880: 24718c2ecf20Sopenharmony_ci chip_name = "RS780"; 24728c2ecf20Sopenharmony_ci rlc_chip_name = "R600"; 24738c2ecf20Sopenharmony_ci break; 24748c2ecf20Sopenharmony_ci case CHIP_RV770: 24758c2ecf20Sopenharmony_ci chip_name = "RV770"; 24768c2ecf20Sopenharmony_ci rlc_chip_name = "R700"; 24778c2ecf20Sopenharmony_ci smc_chip_name = "RV770"; 24788c2ecf20Sopenharmony_ci smc_req_size = ALIGN(RV770_SMC_UCODE_SIZE, 4); 24798c2ecf20Sopenharmony_ci break; 24808c2ecf20Sopenharmony_ci case CHIP_RV730: 24818c2ecf20Sopenharmony_ci chip_name = "RV730"; 24828c2ecf20Sopenharmony_ci rlc_chip_name = "R700"; 24838c2ecf20Sopenharmony_ci smc_chip_name = "RV730"; 24848c2ecf20Sopenharmony_ci smc_req_size = ALIGN(RV730_SMC_UCODE_SIZE, 4); 24858c2ecf20Sopenharmony_ci break; 24868c2ecf20Sopenharmony_ci case CHIP_RV710: 24878c2ecf20Sopenharmony_ci chip_name = "RV710"; 24888c2ecf20Sopenharmony_ci rlc_chip_name = "R700"; 24898c2ecf20Sopenharmony_ci smc_chip_name = "RV710"; 24908c2ecf20Sopenharmony_ci smc_req_size = ALIGN(RV710_SMC_UCODE_SIZE, 4); 24918c2ecf20Sopenharmony_ci break; 24928c2ecf20Sopenharmony_ci case CHIP_RV740: 24938c2ecf20Sopenharmony_ci chip_name = "RV730"; 24948c2ecf20Sopenharmony_ci rlc_chip_name = "R700"; 24958c2ecf20Sopenharmony_ci smc_chip_name = "RV740"; 24968c2ecf20Sopenharmony_ci smc_req_size = ALIGN(RV740_SMC_UCODE_SIZE, 4); 24978c2ecf20Sopenharmony_ci break; 24988c2ecf20Sopenharmony_ci case CHIP_CEDAR: 24998c2ecf20Sopenharmony_ci chip_name = "CEDAR"; 25008c2ecf20Sopenharmony_ci rlc_chip_name = "CEDAR"; 25018c2ecf20Sopenharmony_ci smc_chip_name = "CEDAR"; 25028c2ecf20Sopenharmony_ci smc_req_size = ALIGN(CEDAR_SMC_UCODE_SIZE, 4); 25038c2ecf20Sopenharmony_ci break; 25048c2ecf20Sopenharmony_ci case CHIP_REDWOOD: 25058c2ecf20Sopenharmony_ci chip_name = "REDWOOD"; 25068c2ecf20Sopenharmony_ci rlc_chip_name = "REDWOOD"; 25078c2ecf20Sopenharmony_ci smc_chip_name = "REDWOOD"; 25088c2ecf20Sopenharmony_ci smc_req_size = ALIGN(REDWOOD_SMC_UCODE_SIZE, 4); 25098c2ecf20Sopenharmony_ci break; 25108c2ecf20Sopenharmony_ci case CHIP_JUNIPER: 25118c2ecf20Sopenharmony_ci chip_name = "JUNIPER"; 25128c2ecf20Sopenharmony_ci rlc_chip_name = "JUNIPER"; 25138c2ecf20Sopenharmony_ci smc_chip_name = "JUNIPER"; 25148c2ecf20Sopenharmony_ci smc_req_size = ALIGN(JUNIPER_SMC_UCODE_SIZE, 4); 25158c2ecf20Sopenharmony_ci break; 25168c2ecf20Sopenharmony_ci case CHIP_CYPRESS: 25178c2ecf20Sopenharmony_ci case CHIP_HEMLOCK: 25188c2ecf20Sopenharmony_ci chip_name = "CYPRESS"; 25198c2ecf20Sopenharmony_ci rlc_chip_name = "CYPRESS"; 25208c2ecf20Sopenharmony_ci smc_chip_name = "CYPRESS"; 25218c2ecf20Sopenharmony_ci smc_req_size = ALIGN(CYPRESS_SMC_UCODE_SIZE, 4); 25228c2ecf20Sopenharmony_ci break; 25238c2ecf20Sopenharmony_ci case CHIP_PALM: 25248c2ecf20Sopenharmony_ci chip_name = "PALM"; 25258c2ecf20Sopenharmony_ci rlc_chip_name = "SUMO"; 25268c2ecf20Sopenharmony_ci break; 25278c2ecf20Sopenharmony_ci case CHIP_SUMO: 25288c2ecf20Sopenharmony_ci chip_name = "SUMO"; 25298c2ecf20Sopenharmony_ci rlc_chip_name = "SUMO"; 25308c2ecf20Sopenharmony_ci break; 25318c2ecf20Sopenharmony_ci case CHIP_SUMO2: 25328c2ecf20Sopenharmony_ci chip_name = "SUMO2"; 25338c2ecf20Sopenharmony_ci rlc_chip_name = "SUMO"; 25348c2ecf20Sopenharmony_ci break; 25358c2ecf20Sopenharmony_ci default: BUG(); 25368c2ecf20Sopenharmony_ci } 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_CEDAR) { 25398c2ecf20Sopenharmony_ci pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; 25408c2ecf20Sopenharmony_ci me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; 25418c2ecf20Sopenharmony_ci rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; 25428c2ecf20Sopenharmony_ci } else if (rdev->family >= CHIP_RV770) { 25438c2ecf20Sopenharmony_ci pfp_req_size = R700_PFP_UCODE_SIZE * 4; 25448c2ecf20Sopenharmony_ci me_req_size = R700_PM4_UCODE_SIZE * 4; 25458c2ecf20Sopenharmony_ci rlc_req_size = R700_RLC_UCODE_SIZE * 4; 25468c2ecf20Sopenharmony_ci } else { 25478c2ecf20Sopenharmony_ci pfp_req_size = R600_PFP_UCODE_SIZE * 4; 25488c2ecf20Sopenharmony_ci me_req_size = R600_PM4_UCODE_SIZE * 12; 25498c2ecf20Sopenharmony_ci rlc_req_size = R600_RLC_UCODE_SIZE * 4; 25508c2ecf20Sopenharmony_ci } 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci DRM_INFO("Loading %s Microcode\n", chip_name); 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); 25558c2ecf20Sopenharmony_ci err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev); 25568c2ecf20Sopenharmony_ci if (err) 25578c2ecf20Sopenharmony_ci goto out; 25588c2ecf20Sopenharmony_ci if (rdev->pfp_fw->size != pfp_req_size) { 25598c2ecf20Sopenharmony_ci pr_err("r600_cp: Bogus length %zu in firmware \"%s\"\n", 25608c2ecf20Sopenharmony_ci rdev->pfp_fw->size, fw_name); 25618c2ecf20Sopenharmony_ci err = -EINVAL; 25628c2ecf20Sopenharmony_ci goto out; 25638c2ecf20Sopenharmony_ci } 25648c2ecf20Sopenharmony_ci 25658c2ecf20Sopenharmony_ci snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); 25668c2ecf20Sopenharmony_ci err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); 25678c2ecf20Sopenharmony_ci if (err) 25688c2ecf20Sopenharmony_ci goto out; 25698c2ecf20Sopenharmony_ci if (rdev->me_fw->size != me_req_size) { 25708c2ecf20Sopenharmony_ci pr_err("r600_cp: Bogus length %zu in firmware \"%s\"\n", 25718c2ecf20Sopenharmony_ci rdev->me_fw->size, fw_name); 25728c2ecf20Sopenharmony_ci err = -EINVAL; 25738c2ecf20Sopenharmony_ci } 25748c2ecf20Sopenharmony_ci 25758c2ecf20Sopenharmony_ci snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name); 25768c2ecf20Sopenharmony_ci err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev); 25778c2ecf20Sopenharmony_ci if (err) 25788c2ecf20Sopenharmony_ci goto out; 25798c2ecf20Sopenharmony_ci if (rdev->rlc_fw->size != rlc_req_size) { 25808c2ecf20Sopenharmony_ci pr_err("r600_rlc: Bogus length %zu in firmware \"%s\"\n", 25818c2ecf20Sopenharmony_ci rdev->rlc_fw->size, fw_name); 25828c2ecf20Sopenharmony_ci err = -EINVAL; 25838c2ecf20Sopenharmony_ci } 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_HEMLOCK)) { 25868c2ecf20Sopenharmony_ci snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", smc_chip_name); 25878c2ecf20Sopenharmony_ci err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); 25888c2ecf20Sopenharmony_ci if (err) { 25898c2ecf20Sopenharmony_ci pr_err("smc: error loading firmware \"%s\"\n", fw_name); 25908c2ecf20Sopenharmony_ci release_firmware(rdev->smc_fw); 25918c2ecf20Sopenharmony_ci rdev->smc_fw = NULL; 25928c2ecf20Sopenharmony_ci err = 0; 25938c2ecf20Sopenharmony_ci } else if (rdev->smc_fw->size != smc_req_size) { 25948c2ecf20Sopenharmony_ci pr_err("smc: Bogus length %zu in firmware \"%s\"\n", 25958c2ecf20Sopenharmony_ci rdev->smc_fw->size, fw_name); 25968c2ecf20Sopenharmony_ci err = -EINVAL; 25978c2ecf20Sopenharmony_ci } 25988c2ecf20Sopenharmony_ci } 25998c2ecf20Sopenharmony_ci 26008c2ecf20Sopenharmony_ciout: 26018c2ecf20Sopenharmony_ci if (err) { 26028c2ecf20Sopenharmony_ci if (err != -EINVAL) 26038c2ecf20Sopenharmony_ci pr_err("r600_cp: Failed to load firmware \"%s\"\n", 26048c2ecf20Sopenharmony_ci fw_name); 26058c2ecf20Sopenharmony_ci release_firmware(rdev->pfp_fw); 26068c2ecf20Sopenharmony_ci rdev->pfp_fw = NULL; 26078c2ecf20Sopenharmony_ci release_firmware(rdev->me_fw); 26088c2ecf20Sopenharmony_ci rdev->me_fw = NULL; 26098c2ecf20Sopenharmony_ci release_firmware(rdev->rlc_fw); 26108c2ecf20Sopenharmony_ci rdev->rlc_fw = NULL; 26118c2ecf20Sopenharmony_ci release_firmware(rdev->smc_fw); 26128c2ecf20Sopenharmony_ci rdev->smc_fw = NULL; 26138c2ecf20Sopenharmony_ci } 26148c2ecf20Sopenharmony_ci return err; 26158c2ecf20Sopenharmony_ci} 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ciu32 r600_gfx_get_rptr(struct radeon_device *rdev, 26188c2ecf20Sopenharmony_ci struct radeon_ring *ring) 26198c2ecf20Sopenharmony_ci{ 26208c2ecf20Sopenharmony_ci u32 rptr; 26218c2ecf20Sopenharmony_ci 26228c2ecf20Sopenharmony_ci if (rdev->wb.enabled) 26238c2ecf20Sopenharmony_ci rptr = rdev->wb.wb[ring->rptr_offs/4]; 26248c2ecf20Sopenharmony_ci else 26258c2ecf20Sopenharmony_ci rptr = RREG32(R600_CP_RB_RPTR); 26268c2ecf20Sopenharmony_ci 26278c2ecf20Sopenharmony_ci return rptr; 26288c2ecf20Sopenharmony_ci} 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_ciu32 r600_gfx_get_wptr(struct radeon_device *rdev, 26318c2ecf20Sopenharmony_ci struct radeon_ring *ring) 26328c2ecf20Sopenharmony_ci{ 26338c2ecf20Sopenharmony_ci return RREG32(R600_CP_RB_WPTR); 26348c2ecf20Sopenharmony_ci} 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_civoid r600_gfx_set_wptr(struct radeon_device *rdev, 26378c2ecf20Sopenharmony_ci struct radeon_ring *ring) 26388c2ecf20Sopenharmony_ci{ 26398c2ecf20Sopenharmony_ci WREG32(R600_CP_RB_WPTR, ring->wptr); 26408c2ecf20Sopenharmony_ci (void)RREG32(R600_CP_RB_WPTR); 26418c2ecf20Sopenharmony_ci} 26428c2ecf20Sopenharmony_ci 26438c2ecf20Sopenharmony_cistatic int r600_cp_load_microcode(struct radeon_device *rdev) 26448c2ecf20Sopenharmony_ci{ 26458c2ecf20Sopenharmony_ci const __be32 *fw_data; 26468c2ecf20Sopenharmony_ci int i; 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_ci if (!rdev->me_fw || !rdev->pfp_fw) 26498c2ecf20Sopenharmony_ci return -EINVAL; 26508c2ecf20Sopenharmony_ci 26518c2ecf20Sopenharmony_ci r600_cp_stop(rdev); 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_ci WREG32(CP_RB_CNTL, 26548c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN 26558c2ecf20Sopenharmony_ci BUF_SWAP_32BIT | 26568c2ecf20Sopenharmony_ci#endif 26578c2ecf20Sopenharmony_ci RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3)); 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_ci /* Reset cp */ 26608c2ecf20Sopenharmony_ci WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); 26618c2ecf20Sopenharmony_ci RREG32(GRBM_SOFT_RESET); 26628c2ecf20Sopenharmony_ci mdelay(15); 26638c2ecf20Sopenharmony_ci WREG32(GRBM_SOFT_RESET, 0); 26648c2ecf20Sopenharmony_ci 26658c2ecf20Sopenharmony_ci WREG32(CP_ME_RAM_WADDR, 0); 26668c2ecf20Sopenharmony_ci 26678c2ecf20Sopenharmony_ci fw_data = (const __be32 *)rdev->me_fw->data; 26688c2ecf20Sopenharmony_ci WREG32(CP_ME_RAM_WADDR, 0); 26698c2ecf20Sopenharmony_ci for (i = 0; i < R600_PM4_UCODE_SIZE * 3; i++) 26708c2ecf20Sopenharmony_ci WREG32(CP_ME_RAM_DATA, 26718c2ecf20Sopenharmony_ci be32_to_cpup(fw_data++)); 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_ci fw_data = (const __be32 *)rdev->pfp_fw->data; 26748c2ecf20Sopenharmony_ci WREG32(CP_PFP_UCODE_ADDR, 0); 26758c2ecf20Sopenharmony_ci for (i = 0; i < R600_PFP_UCODE_SIZE; i++) 26768c2ecf20Sopenharmony_ci WREG32(CP_PFP_UCODE_DATA, 26778c2ecf20Sopenharmony_ci be32_to_cpup(fw_data++)); 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_ci WREG32(CP_PFP_UCODE_ADDR, 0); 26808c2ecf20Sopenharmony_ci WREG32(CP_ME_RAM_WADDR, 0); 26818c2ecf20Sopenharmony_ci WREG32(CP_ME_RAM_RADDR, 0); 26828c2ecf20Sopenharmony_ci return 0; 26838c2ecf20Sopenharmony_ci} 26848c2ecf20Sopenharmony_ci 26858c2ecf20Sopenharmony_ciint r600_cp_start(struct radeon_device *rdev) 26868c2ecf20Sopenharmony_ci{ 26878c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 26888c2ecf20Sopenharmony_ci int r; 26898c2ecf20Sopenharmony_ci uint32_t cp_me; 26908c2ecf20Sopenharmony_ci 26918c2ecf20Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 7); 26928c2ecf20Sopenharmony_ci if (r) { 26938c2ecf20Sopenharmony_ci DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); 26948c2ecf20Sopenharmony_ci return r; 26958c2ecf20Sopenharmony_ci } 26968c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); 26978c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0x1); 26988c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) { 26998c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0x0); 27008c2ecf20Sopenharmony_ci radeon_ring_write(ring, rdev->config.rv770.max_hw_contexts - 1); 27018c2ecf20Sopenharmony_ci } else { 27028c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0x3); 27038c2ecf20Sopenharmony_ci radeon_ring_write(ring, rdev->config.r600.max_hw_contexts - 1); 27048c2ecf20Sopenharmony_ci } 27058c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); 27068c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 27078c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 27088c2ecf20Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 27098c2ecf20Sopenharmony_ci 27108c2ecf20Sopenharmony_ci cp_me = 0xff; 27118c2ecf20Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, cp_me); 27128c2ecf20Sopenharmony_ci return 0; 27138c2ecf20Sopenharmony_ci} 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_ciint r600_cp_resume(struct radeon_device *rdev) 27168c2ecf20Sopenharmony_ci{ 27178c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 27188c2ecf20Sopenharmony_ci u32 tmp; 27198c2ecf20Sopenharmony_ci u32 rb_bufsz; 27208c2ecf20Sopenharmony_ci int r; 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_ci /* Reset cp */ 27238c2ecf20Sopenharmony_ci WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); 27248c2ecf20Sopenharmony_ci RREG32(GRBM_SOFT_RESET); 27258c2ecf20Sopenharmony_ci mdelay(15); 27268c2ecf20Sopenharmony_ci WREG32(GRBM_SOFT_RESET, 0); 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci /* Set ring buffer size */ 27298c2ecf20Sopenharmony_ci rb_bufsz = order_base_2(ring->ring_size / 8); 27308c2ecf20Sopenharmony_ci tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; 27318c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN 27328c2ecf20Sopenharmony_ci tmp |= BUF_SWAP_32BIT; 27338c2ecf20Sopenharmony_ci#endif 27348c2ecf20Sopenharmony_ci WREG32(CP_RB_CNTL, tmp); 27358c2ecf20Sopenharmony_ci WREG32(CP_SEM_WAIT_TIMER, 0x0); 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_ci /* Set the write pointer delay */ 27388c2ecf20Sopenharmony_ci WREG32(CP_RB_WPTR_DELAY, 0); 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci /* Initialize the ring buffer's read and write pointers */ 27418c2ecf20Sopenharmony_ci WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); 27428c2ecf20Sopenharmony_ci WREG32(CP_RB_RPTR_WR, 0); 27438c2ecf20Sopenharmony_ci ring->wptr = 0; 27448c2ecf20Sopenharmony_ci WREG32(CP_RB_WPTR, ring->wptr); 27458c2ecf20Sopenharmony_ci 27468c2ecf20Sopenharmony_ci /* set the wb address whether it's enabled or not */ 27478c2ecf20Sopenharmony_ci WREG32(CP_RB_RPTR_ADDR, 27488c2ecf20Sopenharmony_ci ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC)); 27498c2ecf20Sopenharmony_ci WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); 27508c2ecf20Sopenharmony_ci WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); 27518c2ecf20Sopenharmony_ci 27528c2ecf20Sopenharmony_ci if (rdev->wb.enabled) 27538c2ecf20Sopenharmony_ci WREG32(SCRATCH_UMSK, 0xff); 27548c2ecf20Sopenharmony_ci else { 27558c2ecf20Sopenharmony_ci tmp |= RB_NO_UPDATE; 27568c2ecf20Sopenharmony_ci WREG32(SCRATCH_UMSK, 0); 27578c2ecf20Sopenharmony_ci } 27588c2ecf20Sopenharmony_ci 27598c2ecf20Sopenharmony_ci mdelay(1); 27608c2ecf20Sopenharmony_ci WREG32(CP_RB_CNTL, tmp); 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci WREG32(CP_RB_BASE, ring->gpu_addr >> 8); 27638c2ecf20Sopenharmony_ci WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); 27648c2ecf20Sopenharmony_ci 27658c2ecf20Sopenharmony_ci r600_cp_start(rdev); 27668c2ecf20Sopenharmony_ci ring->ready = true; 27678c2ecf20Sopenharmony_ci r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); 27688c2ecf20Sopenharmony_ci if (r) { 27698c2ecf20Sopenharmony_ci ring->ready = false; 27708c2ecf20Sopenharmony_ci return r; 27718c2ecf20Sopenharmony_ci } 27728c2ecf20Sopenharmony_ci 27738c2ecf20Sopenharmony_ci if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) 27748c2ecf20Sopenharmony_ci radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci return 0; 27778c2ecf20Sopenharmony_ci} 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_civoid r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) 27808c2ecf20Sopenharmony_ci{ 27818c2ecf20Sopenharmony_ci u32 rb_bufsz; 27828c2ecf20Sopenharmony_ci int r; 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci /* Align ring size */ 27858c2ecf20Sopenharmony_ci rb_bufsz = order_base_2(ring_size / 8); 27868c2ecf20Sopenharmony_ci ring_size = (1 << (rb_bufsz + 1)) * 4; 27878c2ecf20Sopenharmony_ci ring->ring_size = ring_size; 27888c2ecf20Sopenharmony_ci ring->align_mask = 16 - 1; 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci if (radeon_ring_supports_scratch_reg(rdev, ring)) { 27918c2ecf20Sopenharmony_ci r = radeon_scratch_get(rdev, &ring->rptr_save_reg); 27928c2ecf20Sopenharmony_ci if (r) { 27938c2ecf20Sopenharmony_ci DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); 27948c2ecf20Sopenharmony_ci ring->rptr_save_reg = 0; 27958c2ecf20Sopenharmony_ci } 27968c2ecf20Sopenharmony_ci } 27978c2ecf20Sopenharmony_ci} 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_civoid r600_cp_fini(struct radeon_device *rdev) 28008c2ecf20Sopenharmony_ci{ 28018c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 28028c2ecf20Sopenharmony_ci r600_cp_stop(rdev); 28038c2ecf20Sopenharmony_ci radeon_ring_fini(rdev, ring); 28048c2ecf20Sopenharmony_ci radeon_scratch_free(rdev, ring->rptr_save_reg); 28058c2ecf20Sopenharmony_ci} 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci/* 28088c2ecf20Sopenharmony_ci * GPU scratch registers helpers function. 28098c2ecf20Sopenharmony_ci */ 28108c2ecf20Sopenharmony_civoid r600_scratch_init(struct radeon_device *rdev) 28118c2ecf20Sopenharmony_ci{ 28128c2ecf20Sopenharmony_ci int i; 28138c2ecf20Sopenharmony_ci 28148c2ecf20Sopenharmony_ci rdev->scratch.num_reg = 7; 28158c2ecf20Sopenharmony_ci rdev->scratch.reg_base = SCRATCH_REG0; 28168c2ecf20Sopenharmony_ci for (i = 0; i < rdev->scratch.num_reg; i++) { 28178c2ecf20Sopenharmony_ci rdev->scratch.free[i] = true; 28188c2ecf20Sopenharmony_ci rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); 28198c2ecf20Sopenharmony_ci } 28208c2ecf20Sopenharmony_ci} 28218c2ecf20Sopenharmony_ci 28228c2ecf20Sopenharmony_ciint r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) 28238c2ecf20Sopenharmony_ci{ 28248c2ecf20Sopenharmony_ci uint32_t scratch; 28258c2ecf20Sopenharmony_ci uint32_t tmp = 0; 28268c2ecf20Sopenharmony_ci unsigned i; 28278c2ecf20Sopenharmony_ci int r; 28288c2ecf20Sopenharmony_ci 28298c2ecf20Sopenharmony_ci r = radeon_scratch_get(rdev, &scratch); 28308c2ecf20Sopenharmony_ci if (r) { 28318c2ecf20Sopenharmony_ci DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r); 28328c2ecf20Sopenharmony_ci return r; 28338c2ecf20Sopenharmony_ci } 28348c2ecf20Sopenharmony_ci WREG32(scratch, 0xCAFEDEAD); 28358c2ecf20Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 3); 28368c2ecf20Sopenharmony_ci if (r) { 28378c2ecf20Sopenharmony_ci DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ring->idx, r); 28388c2ecf20Sopenharmony_ci radeon_scratch_free(rdev, scratch); 28398c2ecf20Sopenharmony_ci return r; 28408c2ecf20Sopenharmony_ci } 28418c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 28428c2ecf20Sopenharmony_ci radeon_ring_write(ring, ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); 28438c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0xDEADBEEF); 28448c2ecf20Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 28458c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 28468c2ecf20Sopenharmony_ci tmp = RREG32(scratch); 28478c2ecf20Sopenharmony_ci if (tmp == 0xDEADBEEF) 28488c2ecf20Sopenharmony_ci break; 28498c2ecf20Sopenharmony_ci udelay(1); 28508c2ecf20Sopenharmony_ci } 28518c2ecf20Sopenharmony_ci if (i < rdev->usec_timeout) { 28528c2ecf20Sopenharmony_ci DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); 28538c2ecf20Sopenharmony_ci } else { 28548c2ecf20Sopenharmony_ci DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", 28558c2ecf20Sopenharmony_ci ring->idx, scratch, tmp); 28568c2ecf20Sopenharmony_ci r = -EINVAL; 28578c2ecf20Sopenharmony_ci } 28588c2ecf20Sopenharmony_ci radeon_scratch_free(rdev, scratch); 28598c2ecf20Sopenharmony_ci return r; 28608c2ecf20Sopenharmony_ci} 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci/* 28638c2ecf20Sopenharmony_ci * CP fences/semaphores 28648c2ecf20Sopenharmony_ci */ 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_civoid r600_fence_ring_emit(struct radeon_device *rdev, 28678c2ecf20Sopenharmony_ci struct radeon_fence *fence) 28688c2ecf20Sopenharmony_ci{ 28698c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[fence->ring]; 28708c2ecf20Sopenharmony_ci u32 cp_coher_cntl = PACKET3_TC_ACTION_ENA | PACKET3_VC_ACTION_ENA | 28718c2ecf20Sopenharmony_ci PACKET3_SH_ACTION_ENA; 28728c2ecf20Sopenharmony_ci 28738c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) 28748c2ecf20Sopenharmony_ci cp_coher_cntl |= PACKET3_FULL_CACHE_ENA; 28758c2ecf20Sopenharmony_ci 28768c2ecf20Sopenharmony_ci if (rdev->wb.use_event) { 28778c2ecf20Sopenharmony_ci u64 addr = rdev->fence_drv[fence->ring].gpu_addr; 28788c2ecf20Sopenharmony_ci /* flush read cache over gart */ 28798c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); 28808c2ecf20Sopenharmony_ci radeon_ring_write(ring, cp_coher_cntl); 28818c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0xFFFFFFFF); 28828c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 28838c2ecf20Sopenharmony_ci radeon_ring_write(ring, 10); /* poll interval */ 28848c2ecf20Sopenharmony_ci /* EVENT_WRITE_EOP - flush caches, send int */ 28858c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); 28868c2ecf20Sopenharmony_ci radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); 28878c2ecf20Sopenharmony_ci radeon_ring_write(ring, lower_32_bits(addr)); 28888c2ecf20Sopenharmony_ci radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); 28898c2ecf20Sopenharmony_ci radeon_ring_write(ring, fence->seq); 28908c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 28918c2ecf20Sopenharmony_ci } else { 28928c2ecf20Sopenharmony_ci /* flush read cache over gart */ 28938c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); 28948c2ecf20Sopenharmony_ci radeon_ring_write(ring, cp_coher_cntl); 28958c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0xFFFFFFFF); 28968c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 28978c2ecf20Sopenharmony_ci radeon_ring_write(ring, 10); /* poll interval */ 28988c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0)); 28998c2ecf20Sopenharmony_ci radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); 29008c2ecf20Sopenharmony_ci /* wait for 3D idle clean */ 29018c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 29028c2ecf20Sopenharmony_ci radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); 29038c2ecf20Sopenharmony_ci radeon_ring_write(ring, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); 29048c2ecf20Sopenharmony_ci /* Emit fence sequence & fire IRQ */ 29058c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 29068c2ecf20Sopenharmony_ci radeon_ring_write(ring, ((rdev->fence_drv[fence->ring].scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); 29078c2ecf20Sopenharmony_ci radeon_ring_write(ring, fence->seq); 29088c2ecf20Sopenharmony_ci /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ 29098c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(CP_INT_STATUS, 0)); 29108c2ecf20Sopenharmony_ci radeon_ring_write(ring, RB_INT_STAT); 29118c2ecf20Sopenharmony_ci } 29128c2ecf20Sopenharmony_ci} 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci/** 29158c2ecf20Sopenharmony_ci * r600_semaphore_ring_emit - emit a semaphore on the CP ring 29168c2ecf20Sopenharmony_ci * 29178c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 29188c2ecf20Sopenharmony_ci * @ring: radeon ring buffer object 29198c2ecf20Sopenharmony_ci * @semaphore: radeon semaphore object 29208c2ecf20Sopenharmony_ci * @emit_wait: Is this a sempahore wait? 29218c2ecf20Sopenharmony_ci * 29228c2ecf20Sopenharmony_ci * Emits a semaphore signal/wait packet to the CP ring and prevents the PFP 29238c2ecf20Sopenharmony_ci * from running ahead of semaphore waits. 29248c2ecf20Sopenharmony_ci */ 29258c2ecf20Sopenharmony_cibool r600_semaphore_ring_emit(struct radeon_device *rdev, 29268c2ecf20Sopenharmony_ci struct radeon_ring *ring, 29278c2ecf20Sopenharmony_ci struct radeon_semaphore *semaphore, 29288c2ecf20Sopenharmony_ci bool emit_wait) 29298c2ecf20Sopenharmony_ci{ 29308c2ecf20Sopenharmony_ci uint64_t addr = semaphore->gpu_addr; 29318c2ecf20Sopenharmony_ci unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL; 29328c2ecf20Sopenharmony_ci 29338c2ecf20Sopenharmony_ci if (rdev->family < CHIP_CAYMAN) 29348c2ecf20Sopenharmony_ci sel |= PACKET3_SEM_WAIT_ON_SIGNAL; 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1)); 29378c2ecf20Sopenharmony_ci radeon_ring_write(ring, lower_32_bits(addr)); 29388c2ecf20Sopenharmony_ci radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel); 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_ci /* PFP_SYNC_ME packet only exists on 7xx+, only enable it on eg+ */ 29418c2ecf20Sopenharmony_ci if (emit_wait && (rdev->family >= CHIP_CEDAR)) { 29428c2ecf20Sopenharmony_ci /* Prevent the PFP from running ahead of the semaphore wait */ 29438c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); 29448c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0x0); 29458c2ecf20Sopenharmony_ci } 29468c2ecf20Sopenharmony_ci 29478c2ecf20Sopenharmony_ci return true; 29488c2ecf20Sopenharmony_ci} 29498c2ecf20Sopenharmony_ci 29508c2ecf20Sopenharmony_ci/** 29518c2ecf20Sopenharmony_ci * r600_copy_cpdma - copy pages using the CP DMA engine 29528c2ecf20Sopenharmony_ci * 29538c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 29548c2ecf20Sopenharmony_ci * @src_offset: src GPU address 29558c2ecf20Sopenharmony_ci * @dst_offset: dst GPU address 29568c2ecf20Sopenharmony_ci * @num_gpu_pages: number of GPU pages to xfer 29578c2ecf20Sopenharmony_ci * @fence: radeon fence object 29588c2ecf20Sopenharmony_ci * 29598c2ecf20Sopenharmony_ci * Copy GPU paging using the CP DMA engine (r6xx+). 29608c2ecf20Sopenharmony_ci * Used by the radeon ttm implementation to move pages if 29618c2ecf20Sopenharmony_ci * registered as the asic copy callback. 29628c2ecf20Sopenharmony_ci */ 29638c2ecf20Sopenharmony_cistruct radeon_fence *r600_copy_cpdma(struct radeon_device *rdev, 29648c2ecf20Sopenharmony_ci uint64_t src_offset, uint64_t dst_offset, 29658c2ecf20Sopenharmony_ci unsigned num_gpu_pages, 29668c2ecf20Sopenharmony_ci struct dma_resv *resv) 29678c2ecf20Sopenharmony_ci{ 29688c2ecf20Sopenharmony_ci struct radeon_fence *fence; 29698c2ecf20Sopenharmony_ci struct radeon_sync sync; 29708c2ecf20Sopenharmony_ci int ring_index = rdev->asic->copy.blit_ring_index; 29718c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[ring_index]; 29728c2ecf20Sopenharmony_ci u32 size_in_bytes, cur_size_in_bytes, tmp; 29738c2ecf20Sopenharmony_ci int i, num_loops; 29748c2ecf20Sopenharmony_ci int r = 0; 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_ci radeon_sync_create(&sync); 29778c2ecf20Sopenharmony_ci 29788c2ecf20Sopenharmony_ci size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT); 29798c2ecf20Sopenharmony_ci num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff); 29808c2ecf20Sopenharmony_ci r = radeon_ring_lock(rdev, ring, num_loops * 6 + 24); 29818c2ecf20Sopenharmony_ci if (r) { 29828c2ecf20Sopenharmony_ci DRM_ERROR("radeon: moving bo (%d).\n", r); 29838c2ecf20Sopenharmony_ci radeon_sync_free(rdev, &sync, NULL); 29848c2ecf20Sopenharmony_ci return ERR_PTR(r); 29858c2ecf20Sopenharmony_ci } 29868c2ecf20Sopenharmony_ci 29878c2ecf20Sopenharmony_ci radeon_sync_resv(rdev, &sync, resv, false); 29888c2ecf20Sopenharmony_ci radeon_sync_rings(rdev, &sync, ring->idx); 29898c2ecf20Sopenharmony_ci 29908c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 29918c2ecf20Sopenharmony_ci radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); 29928c2ecf20Sopenharmony_ci radeon_ring_write(ring, WAIT_3D_IDLE_bit); 29938c2ecf20Sopenharmony_ci for (i = 0; i < num_loops; i++) { 29948c2ecf20Sopenharmony_ci cur_size_in_bytes = size_in_bytes; 29958c2ecf20Sopenharmony_ci if (cur_size_in_bytes > 0x1fffff) 29968c2ecf20Sopenharmony_ci cur_size_in_bytes = 0x1fffff; 29978c2ecf20Sopenharmony_ci size_in_bytes -= cur_size_in_bytes; 29988c2ecf20Sopenharmony_ci tmp = upper_32_bits(src_offset) & 0xff; 29998c2ecf20Sopenharmony_ci if (size_in_bytes == 0) 30008c2ecf20Sopenharmony_ci tmp |= PACKET3_CP_DMA_CP_SYNC; 30018c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_CP_DMA, 4)); 30028c2ecf20Sopenharmony_ci radeon_ring_write(ring, lower_32_bits(src_offset)); 30038c2ecf20Sopenharmony_ci radeon_ring_write(ring, tmp); 30048c2ecf20Sopenharmony_ci radeon_ring_write(ring, lower_32_bits(dst_offset)); 30058c2ecf20Sopenharmony_ci radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); 30068c2ecf20Sopenharmony_ci radeon_ring_write(ring, cur_size_in_bytes); 30078c2ecf20Sopenharmony_ci src_offset += cur_size_in_bytes; 30088c2ecf20Sopenharmony_ci dst_offset += cur_size_in_bytes; 30098c2ecf20Sopenharmony_ci } 30108c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 30118c2ecf20Sopenharmony_ci radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); 30128c2ecf20Sopenharmony_ci radeon_ring_write(ring, WAIT_CP_DMA_IDLE_bit); 30138c2ecf20Sopenharmony_ci 30148c2ecf20Sopenharmony_ci r = radeon_fence_emit(rdev, &fence, ring->idx); 30158c2ecf20Sopenharmony_ci if (r) { 30168c2ecf20Sopenharmony_ci radeon_ring_unlock_undo(rdev, ring); 30178c2ecf20Sopenharmony_ci radeon_sync_free(rdev, &sync, NULL); 30188c2ecf20Sopenharmony_ci return ERR_PTR(r); 30198c2ecf20Sopenharmony_ci } 30208c2ecf20Sopenharmony_ci 30218c2ecf20Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 30228c2ecf20Sopenharmony_ci radeon_sync_free(rdev, &sync, fence); 30238c2ecf20Sopenharmony_ci 30248c2ecf20Sopenharmony_ci return fence; 30258c2ecf20Sopenharmony_ci} 30268c2ecf20Sopenharmony_ci 30278c2ecf20Sopenharmony_ciint r600_set_surface_reg(struct radeon_device *rdev, int reg, 30288c2ecf20Sopenharmony_ci uint32_t tiling_flags, uint32_t pitch, 30298c2ecf20Sopenharmony_ci uint32_t offset, uint32_t obj_size) 30308c2ecf20Sopenharmony_ci{ 30318c2ecf20Sopenharmony_ci /* FIXME: implement */ 30328c2ecf20Sopenharmony_ci return 0; 30338c2ecf20Sopenharmony_ci} 30348c2ecf20Sopenharmony_ci 30358c2ecf20Sopenharmony_civoid r600_clear_surface_reg(struct radeon_device *rdev, int reg) 30368c2ecf20Sopenharmony_ci{ 30378c2ecf20Sopenharmony_ci /* FIXME: implement */ 30388c2ecf20Sopenharmony_ci} 30398c2ecf20Sopenharmony_ci 30408c2ecf20Sopenharmony_cistatic void r600_uvd_init(struct radeon_device *rdev) 30418c2ecf20Sopenharmony_ci{ 30428c2ecf20Sopenharmony_ci int r; 30438c2ecf20Sopenharmony_ci 30448c2ecf20Sopenharmony_ci if (!rdev->has_uvd) 30458c2ecf20Sopenharmony_ci return; 30468c2ecf20Sopenharmony_ci 30478c2ecf20Sopenharmony_ci r = radeon_uvd_init(rdev); 30488c2ecf20Sopenharmony_ci if (r) { 30498c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed UVD (%d) init.\n", r); 30508c2ecf20Sopenharmony_ci /* 30518c2ecf20Sopenharmony_ci * At this point rdev->uvd.vcpu_bo is NULL which trickles down 30528c2ecf20Sopenharmony_ci * to early fails uvd_v1_0_resume() and thus nothing happens 30538c2ecf20Sopenharmony_ci * there. So it is pointless to try to go through that code 30548c2ecf20Sopenharmony_ci * hence why we disable uvd here. 30558c2ecf20Sopenharmony_ci */ 30568c2ecf20Sopenharmony_ci rdev->has_uvd = false; 30578c2ecf20Sopenharmony_ci return; 30588c2ecf20Sopenharmony_ci } 30598c2ecf20Sopenharmony_ci rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL; 30608c2ecf20Sopenharmony_ci r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096); 30618c2ecf20Sopenharmony_ci} 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_cistatic void r600_uvd_start(struct radeon_device *rdev) 30648c2ecf20Sopenharmony_ci{ 30658c2ecf20Sopenharmony_ci int r; 30668c2ecf20Sopenharmony_ci 30678c2ecf20Sopenharmony_ci if (!rdev->has_uvd) 30688c2ecf20Sopenharmony_ci return; 30698c2ecf20Sopenharmony_ci 30708c2ecf20Sopenharmony_ci r = uvd_v1_0_resume(rdev); 30718c2ecf20Sopenharmony_ci if (r) { 30728c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed UVD resume (%d).\n", r); 30738c2ecf20Sopenharmony_ci goto error; 30748c2ecf20Sopenharmony_ci } 30758c2ecf20Sopenharmony_ci r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); 30768c2ecf20Sopenharmony_ci if (r) { 30778c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r); 30788c2ecf20Sopenharmony_ci goto error; 30798c2ecf20Sopenharmony_ci } 30808c2ecf20Sopenharmony_ci return; 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_cierror: 30838c2ecf20Sopenharmony_ci rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; 30848c2ecf20Sopenharmony_ci} 30858c2ecf20Sopenharmony_ci 30868c2ecf20Sopenharmony_cistatic void r600_uvd_resume(struct radeon_device *rdev) 30878c2ecf20Sopenharmony_ci{ 30888c2ecf20Sopenharmony_ci struct radeon_ring *ring; 30898c2ecf20Sopenharmony_ci int r; 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size) 30928c2ecf20Sopenharmony_ci return; 30938c2ecf20Sopenharmony_ci 30948c2ecf20Sopenharmony_ci ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; 30958c2ecf20Sopenharmony_ci r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0)); 30968c2ecf20Sopenharmony_ci if (r) { 30978c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); 30988c2ecf20Sopenharmony_ci return; 30998c2ecf20Sopenharmony_ci } 31008c2ecf20Sopenharmony_ci r = uvd_v1_0_init(rdev); 31018c2ecf20Sopenharmony_ci if (r) { 31028c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing UVD (%d).\n", r); 31038c2ecf20Sopenharmony_ci return; 31048c2ecf20Sopenharmony_ci } 31058c2ecf20Sopenharmony_ci} 31068c2ecf20Sopenharmony_ci 31078c2ecf20Sopenharmony_cistatic int r600_startup(struct radeon_device *rdev) 31088c2ecf20Sopenharmony_ci{ 31098c2ecf20Sopenharmony_ci struct radeon_ring *ring; 31108c2ecf20Sopenharmony_ci int r; 31118c2ecf20Sopenharmony_ci 31128c2ecf20Sopenharmony_ci /* enable pcie gen2 link */ 31138c2ecf20Sopenharmony_ci r600_pcie_gen2_enable(rdev); 31148c2ecf20Sopenharmony_ci 31158c2ecf20Sopenharmony_ci /* scratch needs to be initialized before MC */ 31168c2ecf20Sopenharmony_ci r = r600_vram_scratch_init(rdev); 31178c2ecf20Sopenharmony_ci if (r) 31188c2ecf20Sopenharmony_ci return r; 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_ci r600_mc_program(rdev); 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 31238c2ecf20Sopenharmony_ci r600_agp_enable(rdev); 31248c2ecf20Sopenharmony_ci } else { 31258c2ecf20Sopenharmony_ci r = r600_pcie_gart_enable(rdev); 31268c2ecf20Sopenharmony_ci if (r) 31278c2ecf20Sopenharmony_ci return r; 31288c2ecf20Sopenharmony_ci } 31298c2ecf20Sopenharmony_ci r600_gpu_init(rdev); 31308c2ecf20Sopenharmony_ci 31318c2ecf20Sopenharmony_ci /* allocate wb buffer */ 31328c2ecf20Sopenharmony_ci r = radeon_wb_init(rdev); 31338c2ecf20Sopenharmony_ci if (r) 31348c2ecf20Sopenharmony_ci return r; 31358c2ecf20Sopenharmony_ci 31368c2ecf20Sopenharmony_ci r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 31378c2ecf20Sopenharmony_ci if (r) { 31388c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 31398c2ecf20Sopenharmony_ci return r; 31408c2ecf20Sopenharmony_ci } 31418c2ecf20Sopenharmony_ci 31428c2ecf20Sopenharmony_ci r600_uvd_start(rdev); 31438c2ecf20Sopenharmony_ci 31448c2ecf20Sopenharmony_ci /* Enable IRQ */ 31458c2ecf20Sopenharmony_ci if (!rdev->irq.installed) { 31468c2ecf20Sopenharmony_ci r = radeon_irq_kms_init(rdev); 31478c2ecf20Sopenharmony_ci if (r) 31488c2ecf20Sopenharmony_ci return r; 31498c2ecf20Sopenharmony_ci } 31508c2ecf20Sopenharmony_ci 31518c2ecf20Sopenharmony_ci r = r600_irq_init(rdev); 31528c2ecf20Sopenharmony_ci if (r) { 31538c2ecf20Sopenharmony_ci DRM_ERROR("radeon: IH init failed (%d).\n", r); 31548c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 31558c2ecf20Sopenharmony_ci return r; 31568c2ecf20Sopenharmony_ci } 31578c2ecf20Sopenharmony_ci r600_irq_set(rdev); 31588c2ecf20Sopenharmony_ci 31598c2ecf20Sopenharmony_ci ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 31608c2ecf20Sopenharmony_ci r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, 31618c2ecf20Sopenharmony_ci RADEON_CP_PACKET2); 31628c2ecf20Sopenharmony_ci if (r) 31638c2ecf20Sopenharmony_ci return r; 31648c2ecf20Sopenharmony_ci 31658c2ecf20Sopenharmony_ci r = r600_cp_load_microcode(rdev); 31668c2ecf20Sopenharmony_ci if (r) 31678c2ecf20Sopenharmony_ci return r; 31688c2ecf20Sopenharmony_ci r = r600_cp_resume(rdev); 31698c2ecf20Sopenharmony_ci if (r) 31708c2ecf20Sopenharmony_ci return r; 31718c2ecf20Sopenharmony_ci 31728c2ecf20Sopenharmony_ci r600_uvd_resume(rdev); 31738c2ecf20Sopenharmony_ci 31748c2ecf20Sopenharmony_ci r = radeon_ib_pool_init(rdev); 31758c2ecf20Sopenharmony_ci if (r) { 31768c2ecf20Sopenharmony_ci dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 31778c2ecf20Sopenharmony_ci return r; 31788c2ecf20Sopenharmony_ci } 31798c2ecf20Sopenharmony_ci 31808c2ecf20Sopenharmony_ci r = radeon_audio_init(rdev); 31818c2ecf20Sopenharmony_ci if (r) { 31828c2ecf20Sopenharmony_ci DRM_ERROR("radeon: audio init failed\n"); 31838c2ecf20Sopenharmony_ci return r; 31848c2ecf20Sopenharmony_ci } 31858c2ecf20Sopenharmony_ci 31868c2ecf20Sopenharmony_ci return 0; 31878c2ecf20Sopenharmony_ci} 31888c2ecf20Sopenharmony_ci 31898c2ecf20Sopenharmony_civoid r600_vga_set_state(struct radeon_device *rdev, bool state) 31908c2ecf20Sopenharmony_ci{ 31918c2ecf20Sopenharmony_ci uint32_t temp; 31928c2ecf20Sopenharmony_ci 31938c2ecf20Sopenharmony_ci temp = RREG32(CONFIG_CNTL); 31948c2ecf20Sopenharmony_ci if (!state) { 31958c2ecf20Sopenharmony_ci temp &= ~(1<<0); 31968c2ecf20Sopenharmony_ci temp |= (1<<1); 31978c2ecf20Sopenharmony_ci } else { 31988c2ecf20Sopenharmony_ci temp &= ~(1<<1); 31998c2ecf20Sopenharmony_ci } 32008c2ecf20Sopenharmony_ci WREG32(CONFIG_CNTL, temp); 32018c2ecf20Sopenharmony_ci} 32028c2ecf20Sopenharmony_ci 32038c2ecf20Sopenharmony_ciint r600_resume(struct radeon_device *rdev) 32048c2ecf20Sopenharmony_ci{ 32058c2ecf20Sopenharmony_ci int r; 32068c2ecf20Sopenharmony_ci 32078c2ecf20Sopenharmony_ci /* Do not reset GPU before posting, on r600 hw unlike on r500 hw, 32088c2ecf20Sopenharmony_ci * posting will perform necessary task to bring back GPU into good 32098c2ecf20Sopenharmony_ci * shape. 32108c2ecf20Sopenharmony_ci */ 32118c2ecf20Sopenharmony_ci /* post card */ 32128c2ecf20Sopenharmony_ci atom_asic_init(rdev->mode_info.atom_context); 32138c2ecf20Sopenharmony_ci 32148c2ecf20Sopenharmony_ci if (rdev->pm.pm_method == PM_METHOD_DPM) 32158c2ecf20Sopenharmony_ci radeon_pm_resume(rdev); 32168c2ecf20Sopenharmony_ci 32178c2ecf20Sopenharmony_ci rdev->accel_working = true; 32188c2ecf20Sopenharmony_ci r = r600_startup(rdev); 32198c2ecf20Sopenharmony_ci if (r) { 32208c2ecf20Sopenharmony_ci DRM_ERROR("r600 startup failed on resume\n"); 32218c2ecf20Sopenharmony_ci rdev->accel_working = false; 32228c2ecf20Sopenharmony_ci return r; 32238c2ecf20Sopenharmony_ci } 32248c2ecf20Sopenharmony_ci 32258c2ecf20Sopenharmony_ci return r; 32268c2ecf20Sopenharmony_ci} 32278c2ecf20Sopenharmony_ci 32288c2ecf20Sopenharmony_ciint r600_suspend(struct radeon_device *rdev) 32298c2ecf20Sopenharmony_ci{ 32308c2ecf20Sopenharmony_ci radeon_pm_suspend(rdev); 32318c2ecf20Sopenharmony_ci radeon_audio_fini(rdev); 32328c2ecf20Sopenharmony_ci r600_cp_stop(rdev); 32338c2ecf20Sopenharmony_ci if (rdev->has_uvd) { 32348c2ecf20Sopenharmony_ci uvd_v1_0_fini(rdev); 32358c2ecf20Sopenharmony_ci radeon_uvd_suspend(rdev); 32368c2ecf20Sopenharmony_ci } 32378c2ecf20Sopenharmony_ci r600_irq_suspend(rdev); 32388c2ecf20Sopenharmony_ci radeon_wb_disable(rdev); 32398c2ecf20Sopenharmony_ci r600_pcie_gart_disable(rdev); 32408c2ecf20Sopenharmony_ci 32418c2ecf20Sopenharmony_ci return 0; 32428c2ecf20Sopenharmony_ci} 32438c2ecf20Sopenharmony_ci 32448c2ecf20Sopenharmony_ci/* Plan is to move initialization in that function and use 32458c2ecf20Sopenharmony_ci * helper function so that radeon_device_init pretty much 32468c2ecf20Sopenharmony_ci * do nothing more than calling asic specific function. This 32478c2ecf20Sopenharmony_ci * should also allow to remove a bunch of callback function 32488c2ecf20Sopenharmony_ci * like vram_info. 32498c2ecf20Sopenharmony_ci */ 32508c2ecf20Sopenharmony_ciint r600_init(struct radeon_device *rdev) 32518c2ecf20Sopenharmony_ci{ 32528c2ecf20Sopenharmony_ci int r; 32538c2ecf20Sopenharmony_ci 32548c2ecf20Sopenharmony_ci if (r600_debugfs_mc_info_init(rdev)) { 32558c2ecf20Sopenharmony_ci DRM_ERROR("Failed to register debugfs file for mc !\n"); 32568c2ecf20Sopenharmony_ci } 32578c2ecf20Sopenharmony_ci /* Read BIOS */ 32588c2ecf20Sopenharmony_ci if (!radeon_get_bios(rdev)) { 32598c2ecf20Sopenharmony_ci if (ASIC_IS_AVIVO(rdev)) 32608c2ecf20Sopenharmony_ci return -EINVAL; 32618c2ecf20Sopenharmony_ci } 32628c2ecf20Sopenharmony_ci /* Must be an ATOMBIOS */ 32638c2ecf20Sopenharmony_ci if (!rdev->is_atom_bios) { 32648c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); 32658c2ecf20Sopenharmony_ci return -EINVAL; 32668c2ecf20Sopenharmony_ci } 32678c2ecf20Sopenharmony_ci r = radeon_atombios_init(rdev); 32688c2ecf20Sopenharmony_ci if (r) 32698c2ecf20Sopenharmony_ci return r; 32708c2ecf20Sopenharmony_ci /* Post card if necessary */ 32718c2ecf20Sopenharmony_ci if (!radeon_card_posted(rdev)) { 32728c2ecf20Sopenharmony_ci if (!rdev->bios) { 32738c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); 32748c2ecf20Sopenharmony_ci return -EINVAL; 32758c2ecf20Sopenharmony_ci } 32768c2ecf20Sopenharmony_ci DRM_INFO("GPU not posted. posting now...\n"); 32778c2ecf20Sopenharmony_ci atom_asic_init(rdev->mode_info.atom_context); 32788c2ecf20Sopenharmony_ci } 32798c2ecf20Sopenharmony_ci /* Initialize scratch registers */ 32808c2ecf20Sopenharmony_ci r600_scratch_init(rdev); 32818c2ecf20Sopenharmony_ci /* Initialize surface registers */ 32828c2ecf20Sopenharmony_ci radeon_surface_init(rdev); 32838c2ecf20Sopenharmony_ci /* Initialize clocks */ 32848c2ecf20Sopenharmony_ci radeon_get_clock_info(rdev->ddev); 32858c2ecf20Sopenharmony_ci /* Fence driver */ 32868c2ecf20Sopenharmony_ci r = radeon_fence_driver_init(rdev); 32878c2ecf20Sopenharmony_ci if (r) 32888c2ecf20Sopenharmony_ci return r; 32898c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 32908c2ecf20Sopenharmony_ci r = radeon_agp_init(rdev); 32918c2ecf20Sopenharmony_ci if (r) 32928c2ecf20Sopenharmony_ci radeon_agp_disable(rdev); 32938c2ecf20Sopenharmony_ci } 32948c2ecf20Sopenharmony_ci r = r600_mc_init(rdev); 32958c2ecf20Sopenharmony_ci if (r) 32968c2ecf20Sopenharmony_ci return r; 32978c2ecf20Sopenharmony_ci /* Memory manager */ 32988c2ecf20Sopenharmony_ci r = radeon_bo_init(rdev); 32998c2ecf20Sopenharmony_ci if (r) 33008c2ecf20Sopenharmony_ci return r; 33018c2ecf20Sopenharmony_ci 33028c2ecf20Sopenharmony_ci if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { 33038c2ecf20Sopenharmony_ci r = r600_init_microcode(rdev); 33048c2ecf20Sopenharmony_ci if (r) { 33058c2ecf20Sopenharmony_ci DRM_ERROR("Failed to load firmware!\n"); 33068c2ecf20Sopenharmony_ci return r; 33078c2ecf20Sopenharmony_ci } 33088c2ecf20Sopenharmony_ci } 33098c2ecf20Sopenharmony_ci 33108c2ecf20Sopenharmony_ci /* Initialize power management */ 33118c2ecf20Sopenharmony_ci radeon_pm_init(rdev); 33128c2ecf20Sopenharmony_ci 33138c2ecf20Sopenharmony_ci rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; 33148c2ecf20Sopenharmony_ci r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); 33158c2ecf20Sopenharmony_ci 33168c2ecf20Sopenharmony_ci r600_uvd_init(rdev); 33178c2ecf20Sopenharmony_ci 33188c2ecf20Sopenharmony_ci rdev->ih.ring_obj = NULL; 33198c2ecf20Sopenharmony_ci r600_ih_ring_init(rdev, 64 * 1024); 33208c2ecf20Sopenharmony_ci 33218c2ecf20Sopenharmony_ci r = r600_pcie_gart_init(rdev); 33228c2ecf20Sopenharmony_ci if (r) 33238c2ecf20Sopenharmony_ci return r; 33248c2ecf20Sopenharmony_ci 33258c2ecf20Sopenharmony_ci rdev->accel_working = true; 33268c2ecf20Sopenharmony_ci r = r600_startup(rdev); 33278c2ecf20Sopenharmony_ci if (r) { 33288c2ecf20Sopenharmony_ci dev_err(rdev->dev, "disabling GPU acceleration\n"); 33298c2ecf20Sopenharmony_ci r600_cp_fini(rdev); 33308c2ecf20Sopenharmony_ci r600_irq_fini(rdev); 33318c2ecf20Sopenharmony_ci radeon_wb_fini(rdev); 33328c2ecf20Sopenharmony_ci radeon_ib_pool_fini(rdev); 33338c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 33348c2ecf20Sopenharmony_ci r600_pcie_gart_fini(rdev); 33358c2ecf20Sopenharmony_ci rdev->accel_working = false; 33368c2ecf20Sopenharmony_ci } 33378c2ecf20Sopenharmony_ci 33388c2ecf20Sopenharmony_ci return 0; 33398c2ecf20Sopenharmony_ci} 33408c2ecf20Sopenharmony_ci 33418c2ecf20Sopenharmony_civoid r600_fini(struct radeon_device *rdev) 33428c2ecf20Sopenharmony_ci{ 33438c2ecf20Sopenharmony_ci radeon_pm_fini(rdev); 33448c2ecf20Sopenharmony_ci radeon_audio_fini(rdev); 33458c2ecf20Sopenharmony_ci r600_cp_fini(rdev); 33468c2ecf20Sopenharmony_ci r600_irq_fini(rdev); 33478c2ecf20Sopenharmony_ci if (rdev->has_uvd) { 33488c2ecf20Sopenharmony_ci uvd_v1_0_fini(rdev); 33498c2ecf20Sopenharmony_ci radeon_uvd_fini(rdev); 33508c2ecf20Sopenharmony_ci } 33518c2ecf20Sopenharmony_ci radeon_wb_fini(rdev); 33528c2ecf20Sopenharmony_ci radeon_ib_pool_fini(rdev); 33538c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 33548c2ecf20Sopenharmony_ci r600_pcie_gart_fini(rdev); 33558c2ecf20Sopenharmony_ci r600_vram_scratch_fini(rdev); 33568c2ecf20Sopenharmony_ci radeon_agp_fini(rdev); 33578c2ecf20Sopenharmony_ci radeon_gem_fini(rdev); 33588c2ecf20Sopenharmony_ci radeon_fence_driver_fini(rdev); 33598c2ecf20Sopenharmony_ci radeon_bo_fini(rdev); 33608c2ecf20Sopenharmony_ci radeon_atombios_fini(rdev); 33618c2ecf20Sopenharmony_ci kfree(rdev->bios); 33628c2ecf20Sopenharmony_ci rdev->bios = NULL; 33638c2ecf20Sopenharmony_ci} 33648c2ecf20Sopenharmony_ci 33658c2ecf20Sopenharmony_ci 33668c2ecf20Sopenharmony_ci/* 33678c2ecf20Sopenharmony_ci * CS stuff 33688c2ecf20Sopenharmony_ci */ 33698c2ecf20Sopenharmony_civoid r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) 33708c2ecf20Sopenharmony_ci{ 33718c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[ib->ring]; 33728c2ecf20Sopenharmony_ci u32 next_rptr; 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci if (ring->rptr_save_reg) { 33758c2ecf20Sopenharmony_ci next_rptr = ring->wptr + 3 + 4; 33768c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 33778c2ecf20Sopenharmony_ci radeon_ring_write(ring, ((ring->rptr_save_reg - 33788c2ecf20Sopenharmony_ci PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); 33798c2ecf20Sopenharmony_ci radeon_ring_write(ring, next_rptr); 33808c2ecf20Sopenharmony_ci } else if (rdev->wb.enabled) { 33818c2ecf20Sopenharmony_ci next_rptr = ring->wptr + 5 + 4; 33828c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); 33838c2ecf20Sopenharmony_ci radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); 33848c2ecf20Sopenharmony_ci radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); 33858c2ecf20Sopenharmony_ci radeon_ring_write(ring, next_rptr); 33868c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 33878c2ecf20Sopenharmony_ci } 33888c2ecf20Sopenharmony_ci 33898c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); 33908c2ecf20Sopenharmony_ci radeon_ring_write(ring, 33918c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN 33928c2ecf20Sopenharmony_ci (2 << 0) | 33938c2ecf20Sopenharmony_ci#endif 33948c2ecf20Sopenharmony_ci (ib->gpu_addr & 0xFFFFFFFC)); 33958c2ecf20Sopenharmony_ci radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); 33968c2ecf20Sopenharmony_ci radeon_ring_write(ring, ib->length_dw); 33978c2ecf20Sopenharmony_ci} 33988c2ecf20Sopenharmony_ci 33998c2ecf20Sopenharmony_ciint r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) 34008c2ecf20Sopenharmony_ci{ 34018c2ecf20Sopenharmony_ci struct radeon_ib ib; 34028c2ecf20Sopenharmony_ci uint32_t scratch; 34038c2ecf20Sopenharmony_ci uint32_t tmp = 0; 34048c2ecf20Sopenharmony_ci unsigned i; 34058c2ecf20Sopenharmony_ci int r; 34068c2ecf20Sopenharmony_ci 34078c2ecf20Sopenharmony_ci r = radeon_scratch_get(rdev, &scratch); 34088c2ecf20Sopenharmony_ci if (r) { 34098c2ecf20Sopenharmony_ci DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); 34108c2ecf20Sopenharmony_ci return r; 34118c2ecf20Sopenharmony_ci } 34128c2ecf20Sopenharmony_ci WREG32(scratch, 0xCAFEDEAD); 34138c2ecf20Sopenharmony_ci r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256); 34148c2ecf20Sopenharmony_ci if (r) { 34158c2ecf20Sopenharmony_ci DRM_ERROR("radeon: failed to get ib (%d).\n", r); 34168c2ecf20Sopenharmony_ci goto free_scratch; 34178c2ecf20Sopenharmony_ci } 34188c2ecf20Sopenharmony_ci ib.ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1); 34198c2ecf20Sopenharmony_ci ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); 34208c2ecf20Sopenharmony_ci ib.ptr[2] = 0xDEADBEEF; 34218c2ecf20Sopenharmony_ci ib.length_dw = 3; 34228c2ecf20Sopenharmony_ci r = radeon_ib_schedule(rdev, &ib, NULL, false); 34238c2ecf20Sopenharmony_ci if (r) { 34248c2ecf20Sopenharmony_ci DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); 34258c2ecf20Sopenharmony_ci goto free_ib; 34268c2ecf20Sopenharmony_ci } 34278c2ecf20Sopenharmony_ci r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( 34288c2ecf20Sopenharmony_ci RADEON_USEC_IB_TEST_TIMEOUT)); 34298c2ecf20Sopenharmony_ci if (r < 0) { 34308c2ecf20Sopenharmony_ci DRM_ERROR("radeon: fence wait failed (%d).\n", r); 34318c2ecf20Sopenharmony_ci goto free_ib; 34328c2ecf20Sopenharmony_ci } else if (r == 0) { 34338c2ecf20Sopenharmony_ci DRM_ERROR("radeon: fence wait timed out.\n"); 34348c2ecf20Sopenharmony_ci r = -ETIMEDOUT; 34358c2ecf20Sopenharmony_ci goto free_ib; 34368c2ecf20Sopenharmony_ci } 34378c2ecf20Sopenharmony_ci r = 0; 34388c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 34398c2ecf20Sopenharmony_ci tmp = RREG32(scratch); 34408c2ecf20Sopenharmony_ci if (tmp == 0xDEADBEEF) 34418c2ecf20Sopenharmony_ci break; 34428c2ecf20Sopenharmony_ci udelay(1); 34438c2ecf20Sopenharmony_ci } 34448c2ecf20Sopenharmony_ci if (i < rdev->usec_timeout) { 34458c2ecf20Sopenharmony_ci DRM_INFO("ib test on ring %d succeeded in %u usecs\n", ib.fence->ring, i); 34468c2ecf20Sopenharmony_ci } else { 34478c2ecf20Sopenharmony_ci DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", 34488c2ecf20Sopenharmony_ci scratch, tmp); 34498c2ecf20Sopenharmony_ci r = -EINVAL; 34508c2ecf20Sopenharmony_ci } 34518c2ecf20Sopenharmony_cifree_ib: 34528c2ecf20Sopenharmony_ci radeon_ib_free(rdev, &ib); 34538c2ecf20Sopenharmony_cifree_scratch: 34548c2ecf20Sopenharmony_ci radeon_scratch_free(rdev, scratch); 34558c2ecf20Sopenharmony_ci return r; 34568c2ecf20Sopenharmony_ci} 34578c2ecf20Sopenharmony_ci 34588c2ecf20Sopenharmony_ci/* 34598c2ecf20Sopenharmony_ci * Interrupts 34608c2ecf20Sopenharmony_ci * 34618c2ecf20Sopenharmony_ci * Interrupts use a ring buffer on r6xx/r7xx hardware. It works pretty 34628c2ecf20Sopenharmony_ci * the same as the CP ring buffer, but in reverse. Rather than the CPU 34638c2ecf20Sopenharmony_ci * writing to the ring and the GPU consuming, the GPU writes to the ring 34648c2ecf20Sopenharmony_ci * and host consumes. As the host irq handler processes interrupts, it 34658c2ecf20Sopenharmony_ci * increments the rptr. When the rptr catches up with the wptr, all the 34668c2ecf20Sopenharmony_ci * current interrupts have been processed. 34678c2ecf20Sopenharmony_ci */ 34688c2ecf20Sopenharmony_ci 34698c2ecf20Sopenharmony_civoid r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) 34708c2ecf20Sopenharmony_ci{ 34718c2ecf20Sopenharmony_ci u32 rb_bufsz; 34728c2ecf20Sopenharmony_ci 34738c2ecf20Sopenharmony_ci /* Align ring size */ 34748c2ecf20Sopenharmony_ci rb_bufsz = order_base_2(ring_size / 4); 34758c2ecf20Sopenharmony_ci ring_size = (1 << rb_bufsz) * 4; 34768c2ecf20Sopenharmony_ci rdev->ih.ring_size = ring_size; 34778c2ecf20Sopenharmony_ci rdev->ih.ptr_mask = rdev->ih.ring_size - 1; 34788c2ecf20Sopenharmony_ci rdev->ih.rptr = 0; 34798c2ecf20Sopenharmony_ci} 34808c2ecf20Sopenharmony_ci 34818c2ecf20Sopenharmony_ciint r600_ih_ring_alloc(struct radeon_device *rdev) 34828c2ecf20Sopenharmony_ci{ 34838c2ecf20Sopenharmony_ci int r; 34848c2ecf20Sopenharmony_ci 34858c2ecf20Sopenharmony_ci /* Allocate ring buffer */ 34868c2ecf20Sopenharmony_ci if (rdev->ih.ring_obj == NULL) { 34878c2ecf20Sopenharmony_ci r = radeon_bo_create(rdev, rdev->ih.ring_size, 34888c2ecf20Sopenharmony_ci PAGE_SIZE, true, 34898c2ecf20Sopenharmony_ci RADEON_GEM_DOMAIN_GTT, 0, 34908c2ecf20Sopenharmony_ci NULL, NULL, &rdev->ih.ring_obj); 34918c2ecf20Sopenharmony_ci if (r) { 34928c2ecf20Sopenharmony_ci DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r); 34938c2ecf20Sopenharmony_ci return r; 34948c2ecf20Sopenharmony_ci } 34958c2ecf20Sopenharmony_ci r = radeon_bo_reserve(rdev->ih.ring_obj, false); 34968c2ecf20Sopenharmony_ci if (unlikely(r != 0)) 34978c2ecf20Sopenharmony_ci return r; 34988c2ecf20Sopenharmony_ci r = radeon_bo_pin(rdev->ih.ring_obj, 34998c2ecf20Sopenharmony_ci RADEON_GEM_DOMAIN_GTT, 35008c2ecf20Sopenharmony_ci &rdev->ih.gpu_addr); 35018c2ecf20Sopenharmony_ci if (r) { 35028c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->ih.ring_obj); 35038c2ecf20Sopenharmony_ci DRM_ERROR("radeon: failed to pin ih ring buffer (%d).\n", r); 35048c2ecf20Sopenharmony_ci return r; 35058c2ecf20Sopenharmony_ci } 35068c2ecf20Sopenharmony_ci r = radeon_bo_kmap(rdev->ih.ring_obj, 35078c2ecf20Sopenharmony_ci (void **)&rdev->ih.ring); 35088c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->ih.ring_obj); 35098c2ecf20Sopenharmony_ci if (r) { 35108c2ecf20Sopenharmony_ci DRM_ERROR("radeon: failed to map ih ring buffer (%d).\n", r); 35118c2ecf20Sopenharmony_ci return r; 35128c2ecf20Sopenharmony_ci } 35138c2ecf20Sopenharmony_ci } 35148c2ecf20Sopenharmony_ci return 0; 35158c2ecf20Sopenharmony_ci} 35168c2ecf20Sopenharmony_ci 35178c2ecf20Sopenharmony_civoid r600_ih_ring_fini(struct radeon_device *rdev) 35188c2ecf20Sopenharmony_ci{ 35198c2ecf20Sopenharmony_ci int r; 35208c2ecf20Sopenharmony_ci if (rdev->ih.ring_obj) { 35218c2ecf20Sopenharmony_ci r = radeon_bo_reserve(rdev->ih.ring_obj, false); 35228c2ecf20Sopenharmony_ci if (likely(r == 0)) { 35238c2ecf20Sopenharmony_ci radeon_bo_kunmap(rdev->ih.ring_obj); 35248c2ecf20Sopenharmony_ci radeon_bo_unpin(rdev->ih.ring_obj); 35258c2ecf20Sopenharmony_ci radeon_bo_unreserve(rdev->ih.ring_obj); 35268c2ecf20Sopenharmony_ci } 35278c2ecf20Sopenharmony_ci radeon_bo_unref(&rdev->ih.ring_obj); 35288c2ecf20Sopenharmony_ci rdev->ih.ring = NULL; 35298c2ecf20Sopenharmony_ci rdev->ih.ring_obj = NULL; 35308c2ecf20Sopenharmony_ci } 35318c2ecf20Sopenharmony_ci} 35328c2ecf20Sopenharmony_ci 35338c2ecf20Sopenharmony_civoid r600_rlc_stop(struct radeon_device *rdev) 35348c2ecf20Sopenharmony_ci{ 35358c2ecf20Sopenharmony_ci 35368c2ecf20Sopenharmony_ci if ((rdev->family >= CHIP_RV770) && 35378c2ecf20Sopenharmony_ci (rdev->family <= CHIP_RV740)) { 35388c2ecf20Sopenharmony_ci /* r7xx asics need to soft reset RLC before halting */ 35398c2ecf20Sopenharmony_ci WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC); 35408c2ecf20Sopenharmony_ci RREG32(SRBM_SOFT_RESET); 35418c2ecf20Sopenharmony_ci mdelay(15); 35428c2ecf20Sopenharmony_ci WREG32(SRBM_SOFT_RESET, 0); 35438c2ecf20Sopenharmony_ci RREG32(SRBM_SOFT_RESET); 35448c2ecf20Sopenharmony_ci } 35458c2ecf20Sopenharmony_ci 35468c2ecf20Sopenharmony_ci WREG32(RLC_CNTL, 0); 35478c2ecf20Sopenharmony_ci} 35488c2ecf20Sopenharmony_ci 35498c2ecf20Sopenharmony_cistatic void r600_rlc_start(struct radeon_device *rdev) 35508c2ecf20Sopenharmony_ci{ 35518c2ecf20Sopenharmony_ci WREG32(RLC_CNTL, RLC_ENABLE); 35528c2ecf20Sopenharmony_ci} 35538c2ecf20Sopenharmony_ci 35548c2ecf20Sopenharmony_cistatic int r600_rlc_resume(struct radeon_device *rdev) 35558c2ecf20Sopenharmony_ci{ 35568c2ecf20Sopenharmony_ci u32 i; 35578c2ecf20Sopenharmony_ci const __be32 *fw_data; 35588c2ecf20Sopenharmony_ci 35598c2ecf20Sopenharmony_ci if (!rdev->rlc_fw) 35608c2ecf20Sopenharmony_ci return -EINVAL; 35618c2ecf20Sopenharmony_ci 35628c2ecf20Sopenharmony_ci r600_rlc_stop(rdev); 35638c2ecf20Sopenharmony_ci 35648c2ecf20Sopenharmony_ci WREG32(RLC_HB_CNTL, 0); 35658c2ecf20Sopenharmony_ci 35668c2ecf20Sopenharmony_ci WREG32(RLC_HB_BASE, 0); 35678c2ecf20Sopenharmony_ci WREG32(RLC_HB_RPTR, 0); 35688c2ecf20Sopenharmony_ci WREG32(RLC_HB_WPTR, 0); 35698c2ecf20Sopenharmony_ci WREG32(RLC_HB_WPTR_LSB_ADDR, 0); 35708c2ecf20Sopenharmony_ci WREG32(RLC_HB_WPTR_MSB_ADDR, 0); 35718c2ecf20Sopenharmony_ci WREG32(RLC_MC_CNTL, 0); 35728c2ecf20Sopenharmony_ci WREG32(RLC_UCODE_CNTL, 0); 35738c2ecf20Sopenharmony_ci 35748c2ecf20Sopenharmony_ci fw_data = (const __be32 *)rdev->rlc_fw->data; 35758c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_RV770) { 35768c2ecf20Sopenharmony_ci for (i = 0; i < R700_RLC_UCODE_SIZE; i++) { 35778c2ecf20Sopenharmony_ci WREG32(RLC_UCODE_ADDR, i); 35788c2ecf20Sopenharmony_ci WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); 35798c2ecf20Sopenharmony_ci } 35808c2ecf20Sopenharmony_ci } else { 35818c2ecf20Sopenharmony_ci for (i = 0; i < R600_RLC_UCODE_SIZE; i++) { 35828c2ecf20Sopenharmony_ci WREG32(RLC_UCODE_ADDR, i); 35838c2ecf20Sopenharmony_ci WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); 35848c2ecf20Sopenharmony_ci } 35858c2ecf20Sopenharmony_ci } 35868c2ecf20Sopenharmony_ci WREG32(RLC_UCODE_ADDR, 0); 35878c2ecf20Sopenharmony_ci 35888c2ecf20Sopenharmony_ci r600_rlc_start(rdev); 35898c2ecf20Sopenharmony_ci 35908c2ecf20Sopenharmony_ci return 0; 35918c2ecf20Sopenharmony_ci} 35928c2ecf20Sopenharmony_ci 35938c2ecf20Sopenharmony_cistatic void r600_enable_interrupts(struct radeon_device *rdev) 35948c2ecf20Sopenharmony_ci{ 35958c2ecf20Sopenharmony_ci u32 ih_cntl = RREG32(IH_CNTL); 35968c2ecf20Sopenharmony_ci u32 ih_rb_cntl = RREG32(IH_RB_CNTL); 35978c2ecf20Sopenharmony_ci 35988c2ecf20Sopenharmony_ci ih_cntl |= ENABLE_INTR; 35998c2ecf20Sopenharmony_ci ih_rb_cntl |= IH_RB_ENABLE; 36008c2ecf20Sopenharmony_ci WREG32(IH_CNTL, ih_cntl); 36018c2ecf20Sopenharmony_ci WREG32(IH_RB_CNTL, ih_rb_cntl); 36028c2ecf20Sopenharmony_ci rdev->ih.enabled = true; 36038c2ecf20Sopenharmony_ci} 36048c2ecf20Sopenharmony_ci 36058c2ecf20Sopenharmony_civoid r600_disable_interrupts(struct radeon_device *rdev) 36068c2ecf20Sopenharmony_ci{ 36078c2ecf20Sopenharmony_ci u32 ih_rb_cntl = RREG32(IH_RB_CNTL); 36088c2ecf20Sopenharmony_ci u32 ih_cntl = RREG32(IH_CNTL); 36098c2ecf20Sopenharmony_ci 36108c2ecf20Sopenharmony_ci ih_rb_cntl &= ~IH_RB_ENABLE; 36118c2ecf20Sopenharmony_ci ih_cntl &= ~ENABLE_INTR; 36128c2ecf20Sopenharmony_ci WREG32(IH_RB_CNTL, ih_rb_cntl); 36138c2ecf20Sopenharmony_ci WREG32(IH_CNTL, ih_cntl); 36148c2ecf20Sopenharmony_ci /* set rptr, wptr to 0 */ 36158c2ecf20Sopenharmony_ci WREG32(IH_RB_RPTR, 0); 36168c2ecf20Sopenharmony_ci WREG32(IH_RB_WPTR, 0); 36178c2ecf20Sopenharmony_ci rdev->ih.enabled = false; 36188c2ecf20Sopenharmony_ci rdev->ih.rptr = 0; 36198c2ecf20Sopenharmony_ci} 36208c2ecf20Sopenharmony_ci 36218c2ecf20Sopenharmony_cistatic void r600_disable_interrupt_state(struct radeon_device *rdev) 36228c2ecf20Sopenharmony_ci{ 36238c2ecf20Sopenharmony_ci u32 tmp; 36248c2ecf20Sopenharmony_ci 36258c2ecf20Sopenharmony_ci WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); 36268c2ecf20Sopenharmony_ci tmp = RREG32(DMA_CNTL) & ~TRAP_ENABLE; 36278c2ecf20Sopenharmony_ci WREG32(DMA_CNTL, tmp); 36288c2ecf20Sopenharmony_ci WREG32(GRBM_INT_CNTL, 0); 36298c2ecf20Sopenharmony_ci WREG32(DxMODE_INT_MASK, 0); 36308c2ecf20Sopenharmony_ci WREG32(D1GRPH_INTERRUPT_CONTROL, 0); 36318c2ecf20Sopenharmony_ci WREG32(D2GRPH_INTERRUPT_CONTROL, 0); 36328c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 36338c2ecf20Sopenharmony_ci WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0); 36348c2ecf20Sopenharmony_ci WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0); 36358c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; 36368c2ecf20Sopenharmony_ci WREG32(DC_HPD1_INT_CONTROL, tmp); 36378c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY; 36388c2ecf20Sopenharmony_ci WREG32(DC_HPD2_INT_CONTROL, tmp); 36398c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY; 36408c2ecf20Sopenharmony_ci WREG32(DC_HPD3_INT_CONTROL, tmp); 36418c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY; 36428c2ecf20Sopenharmony_ci WREG32(DC_HPD4_INT_CONTROL, tmp); 36438c2ecf20Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 36448c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY; 36458c2ecf20Sopenharmony_ci WREG32(DC_HPD5_INT_CONTROL, tmp); 36468c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; 36478c2ecf20Sopenharmony_ci WREG32(DC_HPD6_INT_CONTROL, tmp); 36488c2ecf20Sopenharmony_ci tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 36498c2ecf20Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp); 36508c2ecf20Sopenharmony_ci tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 36518c2ecf20Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp); 36528c2ecf20Sopenharmony_ci } else { 36538c2ecf20Sopenharmony_ci tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 36548c2ecf20Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); 36558c2ecf20Sopenharmony_ci tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 36568c2ecf20Sopenharmony_ci WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); 36578c2ecf20Sopenharmony_ci } 36588c2ecf20Sopenharmony_ci } else { 36598c2ecf20Sopenharmony_ci WREG32(DACA_AUTODETECT_INT_CONTROL, 0); 36608c2ecf20Sopenharmony_ci WREG32(DACB_AUTODETECT_INT_CONTROL, 0); 36618c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; 36628c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); 36638c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; 36648c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); 36658c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; 36668c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); 36678c2ecf20Sopenharmony_ci tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 36688c2ecf20Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); 36698c2ecf20Sopenharmony_ci tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 36708c2ecf20Sopenharmony_ci WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); 36718c2ecf20Sopenharmony_ci } 36728c2ecf20Sopenharmony_ci} 36738c2ecf20Sopenharmony_ci 36748c2ecf20Sopenharmony_ciint r600_irq_init(struct radeon_device *rdev) 36758c2ecf20Sopenharmony_ci{ 36768c2ecf20Sopenharmony_ci int ret = 0; 36778c2ecf20Sopenharmony_ci int rb_bufsz; 36788c2ecf20Sopenharmony_ci u32 interrupt_cntl, ih_cntl, ih_rb_cntl; 36798c2ecf20Sopenharmony_ci 36808c2ecf20Sopenharmony_ci /* allocate ring */ 36818c2ecf20Sopenharmony_ci ret = r600_ih_ring_alloc(rdev); 36828c2ecf20Sopenharmony_ci if (ret) 36838c2ecf20Sopenharmony_ci return ret; 36848c2ecf20Sopenharmony_ci 36858c2ecf20Sopenharmony_ci /* disable irqs */ 36868c2ecf20Sopenharmony_ci r600_disable_interrupts(rdev); 36878c2ecf20Sopenharmony_ci 36888c2ecf20Sopenharmony_ci /* init rlc */ 36898c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_CEDAR) 36908c2ecf20Sopenharmony_ci ret = evergreen_rlc_resume(rdev); 36918c2ecf20Sopenharmony_ci else 36928c2ecf20Sopenharmony_ci ret = r600_rlc_resume(rdev); 36938c2ecf20Sopenharmony_ci if (ret) { 36948c2ecf20Sopenharmony_ci r600_ih_ring_fini(rdev); 36958c2ecf20Sopenharmony_ci return ret; 36968c2ecf20Sopenharmony_ci } 36978c2ecf20Sopenharmony_ci 36988c2ecf20Sopenharmony_ci /* setup interrupt control */ 36998c2ecf20Sopenharmony_ci /* set dummy read address to dummy page address */ 37008c2ecf20Sopenharmony_ci WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8); 37018c2ecf20Sopenharmony_ci interrupt_cntl = RREG32(INTERRUPT_CNTL); 37028c2ecf20Sopenharmony_ci /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi 37038c2ecf20Sopenharmony_ci * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN 37048c2ecf20Sopenharmony_ci */ 37058c2ecf20Sopenharmony_ci interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; 37068c2ecf20Sopenharmony_ci /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ 37078c2ecf20Sopenharmony_ci interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; 37088c2ecf20Sopenharmony_ci WREG32(INTERRUPT_CNTL, interrupt_cntl); 37098c2ecf20Sopenharmony_ci 37108c2ecf20Sopenharmony_ci WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8); 37118c2ecf20Sopenharmony_ci rb_bufsz = order_base_2(rdev->ih.ring_size / 4); 37128c2ecf20Sopenharmony_ci 37138c2ecf20Sopenharmony_ci ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | 37148c2ecf20Sopenharmony_ci IH_WPTR_OVERFLOW_CLEAR | 37158c2ecf20Sopenharmony_ci (rb_bufsz << 1)); 37168c2ecf20Sopenharmony_ci 37178c2ecf20Sopenharmony_ci if (rdev->wb.enabled) 37188c2ecf20Sopenharmony_ci ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; 37198c2ecf20Sopenharmony_ci 37208c2ecf20Sopenharmony_ci /* set the writeback address whether it's enabled or not */ 37218c2ecf20Sopenharmony_ci WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC); 37228c2ecf20Sopenharmony_ci WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF); 37238c2ecf20Sopenharmony_ci 37248c2ecf20Sopenharmony_ci WREG32(IH_RB_CNTL, ih_rb_cntl); 37258c2ecf20Sopenharmony_ci 37268c2ecf20Sopenharmony_ci /* set rptr, wptr to 0 */ 37278c2ecf20Sopenharmony_ci WREG32(IH_RB_RPTR, 0); 37288c2ecf20Sopenharmony_ci WREG32(IH_RB_WPTR, 0); 37298c2ecf20Sopenharmony_ci 37308c2ecf20Sopenharmony_ci /* Default settings for IH_CNTL (disabled at first) */ 37318c2ecf20Sopenharmony_ci ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10); 37328c2ecf20Sopenharmony_ci /* RPTR_REARM only works if msi's are enabled */ 37338c2ecf20Sopenharmony_ci if (rdev->msi_enabled) 37348c2ecf20Sopenharmony_ci ih_cntl |= RPTR_REARM; 37358c2ecf20Sopenharmony_ci WREG32(IH_CNTL, ih_cntl); 37368c2ecf20Sopenharmony_ci 37378c2ecf20Sopenharmony_ci /* force the active interrupt state to all disabled */ 37388c2ecf20Sopenharmony_ci if (rdev->family >= CHIP_CEDAR) 37398c2ecf20Sopenharmony_ci evergreen_disable_interrupt_state(rdev); 37408c2ecf20Sopenharmony_ci else 37418c2ecf20Sopenharmony_ci r600_disable_interrupt_state(rdev); 37428c2ecf20Sopenharmony_ci 37438c2ecf20Sopenharmony_ci /* at this point everything should be setup correctly to enable master */ 37448c2ecf20Sopenharmony_ci pci_set_master(rdev->pdev); 37458c2ecf20Sopenharmony_ci 37468c2ecf20Sopenharmony_ci /* enable irqs */ 37478c2ecf20Sopenharmony_ci r600_enable_interrupts(rdev); 37488c2ecf20Sopenharmony_ci 37498c2ecf20Sopenharmony_ci return ret; 37508c2ecf20Sopenharmony_ci} 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_civoid r600_irq_suspend(struct radeon_device *rdev) 37538c2ecf20Sopenharmony_ci{ 37548c2ecf20Sopenharmony_ci r600_irq_disable(rdev); 37558c2ecf20Sopenharmony_ci r600_rlc_stop(rdev); 37568c2ecf20Sopenharmony_ci} 37578c2ecf20Sopenharmony_ci 37588c2ecf20Sopenharmony_civoid r600_irq_fini(struct radeon_device *rdev) 37598c2ecf20Sopenharmony_ci{ 37608c2ecf20Sopenharmony_ci r600_irq_suspend(rdev); 37618c2ecf20Sopenharmony_ci r600_ih_ring_fini(rdev); 37628c2ecf20Sopenharmony_ci} 37638c2ecf20Sopenharmony_ci 37648c2ecf20Sopenharmony_ciint r600_irq_set(struct radeon_device *rdev) 37658c2ecf20Sopenharmony_ci{ 37668c2ecf20Sopenharmony_ci u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; 37678c2ecf20Sopenharmony_ci u32 mode_int = 0; 37688c2ecf20Sopenharmony_ci u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; 37698c2ecf20Sopenharmony_ci u32 grbm_int_cntl = 0; 37708c2ecf20Sopenharmony_ci u32 hdmi0, hdmi1; 37718c2ecf20Sopenharmony_ci u32 dma_cntl; 37728c2ecf20Sopenharmony_ci u32 thermal_int = 0; 37738c2ecf20Sopenharmony_ci 37748c2ecf20Sopenharmony_ci if (!rdev->irq.installed) { 37758c2ecf20Sopenharmony_ci WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); 37768c2ecf20Sopenharmony_ci return -EINVAL; 37778c2ecf20Sopenharmony_ci } 37788c2ecf20Sopenharmony_ci /* don't enable anything if the ih is disabled */ 37798c2ecf20Sopenharmony_ci if (!rdev->ih.enabled) { 37808c2ecf20Sopenharmony_ci r600_disable_interrupts(rdev); 37818c2ecf20Sopenharmony_ci /* force the active interrupt state to all disabled */ 37828c2ecf20Sopenharmony_ci r600_disable_interrupt_state(rdev); 37838c2ecf20Sopenharmony_ci return 0; 37848c2ecf20Sopenharmony_ci } 37858c2ecf20Sopenharmony_ci 37868c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 37878c2ecf20Sopenharmony_ci hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; 37888c2ecf20Sopenharmony_ci hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; 37898c2ecf20Sopenharmony_ci hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; 37908c2ecf20Sopenharmony_ci hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; 37918c2ecf20Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 37928c2ecf20Sopenharmony_ci hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; 37938c2ecf20Sopenharmony_ci hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; 37948c2ecf20Sopenharmony_ci hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK; 37958c2ecf20Sopenharmony_ci hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK; 37968c2ecf20Sopenharmony_ci } else { 37978c2ecf20Sopenharmony_ci hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 37988c2ecf20Sopenharmony_ci hdmi1 = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 37998c2ecf20Sopenharmony_ci } 38008c2ecf20Sopenharmony_ci } else { 38018c2ecf20Sopenharmony_ci hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; 38028c2ecf20Sopenharmony_ci hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; 38038c2ecf20Sopenharmony_ci hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; 38048c2ecf20Sopenharmony_ci hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 38058c2ecf20Sopenharmony_ci hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 38068c2ecf20Sopenharmony_ci } 38078c2ecf20Sopenharmony_ci 38088c2ecf20Sopenharmony_ci dma_cntl = RREG32(DMA_CNTL) & ~TRAP_ENABLE; 38098c2ecf20Sopenharmony_ci 38108c2ecf20Sopenharmony_ci if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) { 38118c2ecf20Sopenharmony_ci thermal_int = RREG32(CG_THERMAL_INT) & 38128c2ecf20Sopenharmony_ci ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); 38138c2ecf20Sopenharmony_ci } else if (rdev->family >= CHIP_RV770) { 38148c2ecf20Sopenharmony_ci thermal_int = RREG32(RV770_CG_THERMAL_INT) & 38158c2ecf20Sopenharmony_ci ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); 38168c2ecf20Sopenharmony_ci } 38178c2ecf20Sopenharmony_ci if (rdev->irq.dpm_thermal) { 38188c2ecf20Sopenharmony_ci DRM_DEBUG("dpm thermal\n"); 38198c2ecf20Sopenharmony_ci thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; 38208c2ecf20Sopenharmony_ci } 38218c2ecf20Sopenharmony_ci 38228c2ecf20Sopenharmony_ci if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { 38238c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: sw int\n"); 38248c2ecf20Sopenharmony_ci cp_int_cntl |= RB_INT_ENABLE; 38258c2ecf20Sopenharmony_ci cp_int_cntl |= TIME_STAMP_INT_ENABLE; 38268c2ecf20Sopenharmony_ci } 38278c2ecf20Sopenharmony_ci 38288c2ecf20Sopenharmony_ci if (atomic_read(&rdev->irq.ring_int[R600_RING_TYPE_DMA_INDEX])) { 38298c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: sw int dma\n"); 38308c2ecf20Sopenharmony_ci dma_cntl |= TRAP_ENABLE; 38318c2ecf20Sopenharmony_ci } 38328c2ecf20Sopenharmony_ci 38338c2ecf20Sopenharmony_ci if (rdev->irq.crtc_vblank_int[0] || 38348c2ecf20Sopenharmony_ci atomic_read(&rdev->irq.pflip[0])) { 38358c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: vblank 0\n"); 38368c2ecf20Sopenharmony_ci mode_int |= D1MODE_VBLANK_INT_MASK; 38378c2ecf20Sopenharmony_ci } 38388c2ecf20Sopenharmony_ci if (rdev->irq.crtc_vblank_int[1] || 38398c2ecf20Sopenharmony_ci atomic_read(&rdev->irq.pflip[1])) { 38408c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: vblank 1\n"); 38418c2ecf20Sopenharmony_ci mode_int |= D2MODE_VBLANK_INT_MASK; 38428c2ecf20Sopenharmony_ci } 38438c2ecf20Sopenharmony_ci if (rdev->irq.hpd[0]) { 38448c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 1\n"); 38458c2ecf20Sopenharmony_ci hpd1 |= DC_HPDx_INT_EN; 38468c2ecf20Sopenharmony_ci } 38478c2ecf20Sopenharmony_ci if (rdev->irq.hpd[1]) { 38488c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 2\n"); 38498c2ecf20Sopenharmony_ci hpd2 |= DC_HPDx_INT_EN; 38508c2ecf20Sopenharmony_ci } 38518c2ecf20Sopenharmony_ci if (rdev->irq.hpd[2]) { 38528c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 3\n"); 38538c2ecf20Sopenharmony_ci hpd3 |= DC_HPDx_INT_EN; 38548c2ecf20Sopenharmony_ci } 38558c2ecf20Sopenharmony_ci if (rdev->irq.hpd[3]) { 38568c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 4\n"); 38578c2ecf20Sopenharmony_ci hpd4 |= DC_HPDx_INT_EN; 38588c2ecf20Sopenharmony_ci } 38598c2ecf20Sopenharmony_ci if (rdev->irq.hpd[4]) { 38608c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 5\n"); 38618c2ecf20Sopenharmony_ci hpd5 |= DC_HPDx_INT_EN; 38628c2ecf20Sopenharmony_ci } 38638c2ecf20Sopenharmony_ci if (rdev->irq.hpd[5]) { 38648c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 6\n"); 38658c2ecf20Sopenharmony_ci hpd6 |= DC_HPDx_INT_EN; 38668c2ecf20Sopenharmony_ci } 38678c2ecf20Sopenharmony_ci if (rdev->irq.afmt[0]) { 38688c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: hdmi 0\n"); 38698c2ecf20Sopenharmony_ci hdmi0 |= HDMI0_AZ_FORMAT_WTRIG_MASK; 38708c2ecf20Sopenharmony_ci } 38718c2ecf20Sopenharmony_ci if (rdev->irq.afmt[1]) { 38728c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_set: hdmi 0\n"); 38738c2ecf20Sopenharmony_ci hdmi1 |= HDMI0_AZ_FORMAT_WTRIG_MASK; 38748c2ecf20Sopenharmony_ci } 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_ci WREG32(CP_INT_CNTL, cp_int_cntl); 38778c2ecf20Sopenharmony_ci WREG32(DMA_CNTL, dma_cntl); 38788c2ecf20Sopenharmony_ci WREG32(DxMODE_INT_MASK, mode_int); 38798c2ecf20Sopenharmony_ci WREG32(D1GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); 38808c2ecf20Sopenharmony_ci WREG32(D2GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); 38818c2ecf20Sopenharmony_ci WREG32(GRBM_INT_CNTL, grbm_int_cntl); 38828c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 38838c2ecf20Sopenharmony_ci WREG32(DC_HPD1_INT_CONTROL, hpd1); 38848c2ecf20Sopenharmony_ci WREG32(DC_HPD2_INT_CONTROL, hpd2); 38858c2ecf20Sopenharmony_ci WREG32(DC_HPD3_INT_CONTROL, hpd3); 38868c2ecf20Sopenharmony_ci WREG32(DC_HPD4_INT_CONTROL, hpd4); 38878c2ecf20Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 38888c2ecf20Sopenharmony_ci WREG32(DC_HPD5_INT_CONTROL, hpd5); 38898c2ecf20Sopenharmony_ci WREG32(DC_HPD6_INT_CONTROL, hpd6); 38908c2ecf20Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, hdmi0); 38918c2ecf20Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, hdmi1); 38928c2ecf20Sopenharmony_ci } else { 38938c2ecf20Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); 38948c2ecf20Sopenharmony_ci WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, hdmi1); 38958c2ecf20Sopenharmony_ci } 38968c2ecf20Sopenharmony_ci } else { 38978c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); 38988c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); 38998c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); 39008c2ecf20Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); 39018c2ecf20Sopenharmony_ci WREG32(HDMI1_AUDIO_PACKET_CONTROL, hdmi1); 39028c2ecf20Sopenharmony_ci } 39038c2ecf20Sopenharmony_ci if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) { 39048c2ecf20Sopenharmony_ci WREG32(CG_THERMAL_INT, thermal_int); 39058c2ecf20Sopenharmony_ci } else if (rdev->family >= CHIP_RV770) { 39068c2ecf20Sopenharmony_ci WREG32(RV770_CG_THERMAL_INT, thermal_int); 39078c2ecf20Sopenharmony_ci } 39088c2ecf20Sopenharmony_ci 39098c2ecf20Sopenharmony_ci /* posting read */ 39108c2ecf20Sopenharmony_ci RREG32(R_000E50_SRBM_STATUS); 39118c2ecf20Sopenharmony_ci 39128c2ecf20Sopenharmony_ci return 0; 39138c2ecf20Sopenharmony_ci} 39148c2ecf20Sopenharmony_ci 39158c2ecf20Sopenharmony_cistatic void r600_irq_ack(struct radeon_device *rdev) 39168c2ecf20Sopenharmony_ci{ 39178c2ecf20Sopenharmony_ci u32 tmp; 39188c2ecf20Sopenharmony_ci 39198c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 39208c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); 39218c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); 39228c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); 39238c2ecf20Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 39248c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET0); 39258c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET1); 39268c2ecf20Sopenharmony_ci } else { 39278c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); 39288c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi1_status = RREG32(DCE3_HDMI1_STATUS); 39298c2ecf20Sopenharmony_ci } 39308c2ecf20Sopenharmony_ci } else { 39318c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); 39328c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); 39338c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont2 = 0; 39348c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); 39358c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi1_status = RREG32(HDMI1_STATUS); 39368c2ecf20Sopenharmony_ci } 39378c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); 39388c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); 39398c2ecf20Sopenharmony_ci 39408c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED) 39418c2ecf20Sopenharmony_ci WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); 39428c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED) 39438c2ecf20Sopenharmony_ci WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); 39448c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) 39458c2ecf20Sopenharmony_ci WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); 39468c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) 39478c2ecf20Sopenharmony_ci WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); 39488c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) 39498c2ecf20Sopenharmony_ci WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); 39508c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) 39518c2ecf20Sopenharmony_ci WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); 39528c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { 39538c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 39548c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD1_INT_CONTROL); 39558c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39568c2ecf20Sopenharmony_ci WREG32(DC_HPD1_INT_CONTROL, tmp); 39578c2ecf20Sopenharmony_ci } else { 39588c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); 39598c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39608c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); 39618c2ecf20Sopenharmony_ci } 39628c2ecf20Sopenharmony_ci } 39638c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { 39648c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 39658c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD2_INT_CONTROL); 39668c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39678c2ecf20Sopenharmony_ci WREG32(DC_HPD2_INT_CONTROL, tmp); 39688c2ecf20Sopenharmony_ci } else { 39698c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); 39708c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39718c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); 39728c2ecf20Sopenharmony_ci } 39738c2ecf20Sopenharmony_ci } 39748c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { 39758c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 39768c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD3_INT_CONTROL); 39778c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39788c2ecf20Sopenharmony_ci WREG32(DC_HPD3_INT_CONTROL, tmp); 39798c2ecf20Sopenharmony_ci } else { 39808c2ecf20Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); 39818c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39828c2ecf20Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); 39838c2ecf20Sopenharmony_ci } 39848c2ecf20Sopenharmony_ci } 39858c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { 39868c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD4_INT_CONTROL); 39878c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39888c2ecf20Sopenharmony_ci WREG32(DC_HPD4_INT_CONTROL, tmp); 39898c2ecf20Sopenharmony_ci } 39908c2ecf20Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 39918c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { 39928c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD5_INT_CONTROL); 39938c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39948c2ecf20Sopenharmony_ci WREG32(DC_HPD5_INT_CONTROL, tmp); 39958c2ecf20Sopenharmony_ci } 39968c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { 39978c2ecf20Sopenharmony_ci tmp = RREG32(DC_HPD6_INT_CONTROL); 39988c2ecf20Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 39998c2ecf20Sopenharmony_ci WREG32(DC_HPD6_INT_CONTROL, tmp); 40008c2ecf20Sopenharmony_ci } 40018c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.hdmi0_status & AFMT_AZ_FORMAT_WTRIG) { 40028c2ecf20Sopenharmony_ci tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0); 40038c2ecf20Sopenharmony_ci tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; 40048c2ecf20Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp); 40058c2ecf20Sopenharmony_ci } 40068c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.hdmi1_status & AFMT_AZ_FORMAT_WTRIG) { 40078c2ecf20Sopenharmony_ci tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1); 40088c2ecf20Sopenharmony_ci tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; 40098c2ecf20Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp); 40108c2ecf20Sopenharmony_ci } 40118c2ecf20Sopenharmony_ci } else { 40128c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { 40138c2ecf20Sopenharmony_ci tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL); 40148c2ecf20Sopenharmony_ci tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; 40158c2ecf20Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); 40168c2ecf20Sopenharmony_ci } 40178c2ecf20Sopenharmony_ci if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { 40188c2ecf20Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 40198c2ecf20Sopenharmony_ci tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL); 40208c2ecf20Sopenharmony_ci tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; 40218c2ecf20Sopenharmony_ci WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); 40228c2ecf20Sopenharmony_ci } else { 40238c2ecf20Sopenharmony_ci tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL); 40248c2ecf20Sopenharmony_ci tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; 40258c2ecf20Sopenharmony_ci WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); 40268c2ecf20Sopenharmony_ci } 40278c2ecf20Sopenharmony_ci } 40288c2ecf20Sopenharmony_ci } 40298c2ecf20Sopenharmony_ci} 40308c2ecf20Sopenharmony_ci 40318c2ecf20Sopenharmony_civoid r600_irq_disable(struct radeon_device *rdev) 40328c2ecf20Sopenharmony_ci{ 40338c2ecf20Sopenharmony_ci r600_disable_interrupts(rdev); 40348c2ecf20Sopenharmony_ci /* Wait and acknowledge irq */ 40358c2ecf20Sopenharmony_ci mdelay(1); 40368c2ecf20Sopenharmony_ci r600_irq_ack(rdev); 40378c2ecf20Sopenharmony_ci r600_disable_interrupt_state(rdev); 40388c2ecf20Sopenharmony_ci} 40398c2ecf20Sopenharmony_ci 40408c2ecf20Sopenharmony_cistatic u32 r600_get_ih_wptr(struct radeon_device *rdev) 40418c2ecf20Sopenharmony_ci{ 40428c2ecf20Sopenharmony_ci u32 wptr, tmp; 40438c2ecf20Sopenharmony_ci 40448c2ecf20Sopenharmony_ci if (rdev->wb.enabled) 40458c2ecf20Sopenharmony_ci wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); 40468c2ecf20Sopenharmony_ci else 40478c2ecf20Sopenharmony_ci wptr = RREG32(IH_RB_WPTR); 40488c2ecf20Sopenharmony_ci 40498c2ecf20Sopenharmony_ci if (wptr & RB_OVERFLOW) { 40508c2ecf20Sopenharmony_ci wptr &= ~RB_OVERFLOW; 40518c2ecf20Sopenharmony_ci /* When a ring buffer overflow happen start parsing interrupt 40528c2ecf20Sopenharmony_ci * from the last not overwritten vector (wptr + 16). Hopefully 40538c2ecf20Sopenharmony_ci * this should allow us to catchup. 40548c2ecf20Sopenharmony_ci */ 40558c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", 40568c2ecf20Sopenharmony_ci wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask); 40578c2ecf20Sopenharmony_ci rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; 40588c2ecf20Sopenharmony_ci tmp = RREG32(IH_RB_CNTL); 40598c2ecf20Sopenharmony_ci tmp |= IH_WPTR_OVERFLOW_CLEAR; 40608c2ecf20Sopenharmony_ci WREG32(IH_RB_CNTL, tmp); 40618c2ecf20Sopenharmony_ci } 40628c2ecf20Sopenharmony_ci return (wptr & rdev->ih.ptr_mask); 40638c2ecf20Sopenharmony_ci} 40648c2ecf20Sopenharmony_ci 40658c2ecf20Sopenharmony_ci/* r600 IV Ring 40668c2ecf20Sopenharmony_ci * Each IV ring entry is 128 bits: 40678c2ecf20Sopenharmony_ci * [7:0] - interrupt source id 40688c2ecf20Sopenharmony_ci * [31:8] - reserved 40698c2ecf20Sopenharmony_ci * [59:32] - interrupt source data 40708c2ecf20Sopenharmony_ci * [127:60] - reserved 40718c2ecf20Sopenharmony_ci * 40728c2ecf20Sopenharmony_ci * The basic interrupt vector entries 40738c2ecf20Sopenharmony_ci * are decoded as follows: 40748c2ecf20Sopenharmony_ci * src_id src_data description 40758c2ecf20Sopenharmony_ci * 1 0 D1 Vblank 40768c2ecf20Sopenharmony_ci * 1 1 D1 Vline 40778c2ecf20Sopenharmony_ci * 5 0 D2 Vblank 40788c2ecf20Sopenharmony_ci * 5 1 D2 Vline 40798c2ecf20Sopenharmony_ci * 19 0 FP Hot plug detection A 40808c2ecf20Sopenharmony_ci * 19 1 FP Hot plug detection B 40818c2ecf20Sopenharmony_ci * 19 2 DAC A auto-detection 40828c2ecf20Sopenharmony_ci * 19 3 DAC B auto-detection 40838c2ecf20Sopenharmony_ci * 21 4 HDMI block A 40848c2ecf20Sopenharmony_ci * 21 5 HDMI block B 40858c2ecf20Sopenharmony_ci * 176 - CP_INT RB 40868c2ecf20Sopenharmony_ci * 177 - CP_INT IB1 40878c2ecf20Sopenharmony_ci * 178 - CP_INT IB2 40888c2ecf20Sopenharmony_ci * 181 - EOP Interrupt 40898c2ecf20Sopenharmony_ci * 233 - GUI Idle 40908c2ecf20Sopenharmony_ci * 40918c2ecf20Sopenharmony_ci * Note, these are based on r600 and may need to be 40928c2ecf20Sopenharmony_ci * adjusted or added to on newer asics 40938c2ecf20Sopenharmony_ci */ 40948c2ecf20Sopenharmony_ci 40958c2ecf20Sopenharmony_ciint r600_irq_process(struct radeon_device *rdev) 40968c2ecf20Sopenharmony_ci{ 40978c2ecf20Sopenharmony_ci u32 wptr; 40988c2ecf20Sopenharmony_ci u32 rptr; 40998c2ecf20Sopenharmony_ci u32 src_id, src_data; 41008c2ecf20Sopenharmony_ci u32 ring_index; 41018c2ecf20Sopenharmony_ci bool queue_hotplug = false; 41028c2ecf20Sopenharmony_ci bool queue_hdmi = false; 41038c2ecf20Sopenharmony_ci bool queue_thermal = false; 41048c2ecf20Sopenharmony_ci 41058c2ecf20Sopenharmony_ci if (!rdev->ih.enabled || rdev->shutdown) 41068c2ecf20Sopenharmony_ci return IRQ_NONE; 41078c2ecf20Sopenharmony_ci 41088c2ecf20Sopenharmony_ci /* No MSIs, need a dummy read to flush PCI DMAs */ 41098c2ecf20Sopenharmony_ci if (!rdev->msi_enabled) 41108c2ecf20Sopenharmony_ci RREG32(IH_RB_WPTR); 41118c2ecf20Sopenharmony_ci 41128c2ecf20Sopenharmony_ci wptr = r600_get_ih_wptr(rdev); 41138c2ecf20Sopenharmony_ci 41148c2ecf20Sopenharmony_cirestart_ih: 41158c2ecf20Sopenharmony_ci /* is somebody else already processing irqs? */ 41168c2ecf20Sopenharmony_ci if (atomic_xchg(&rdev->ih.lock, 1)) 41178c2ecf20Sopenharmony_ci return IRQ_NONE; 41188c2ecf20Sopenharmony_ci 41198c2ecf20Sopenharmony_ci rptr = rdev->ih.rptr; 41208c2ecf20Sopenharmony_ci DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); 41218c2ecf20Sopenharmony_ci 41228c2ecf20Sopenharmony_ci /* Order reading of wptr vs. reading of IH ring data */ 41238c2ecf20Sopenharmony_ci rmb(); 41248c2ecf20Sopenharmony_ci 41258c2ecf20Sopenharmony_ci /* display interrupts */ 41268c2ecf20Sopenharmony_ci r600_irq_ack(rdev); 41278c2ecf20Sopenharmony_ci 41288c2ecf20Sopenharmony_ci while (rptr != wptr) { 41298c2ecf20Sopenharmony_ci /* wptr/rptr are in bytes! */ 41308c2ecf20Sopenharmony_ci ring_index = rptr / 4; 41318c2ecf20Sopenharmony_ci src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff; 41328c2ecf20Sopenharmony_ci src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff; 41338c2ecf20Sopenharmony_ci 41348c2ecf20Sopenharmony_ci switch (src_id) { 41358c2ecf20Sopenharmony_ci case 1: /* D1 vblank/vline */ 41368c2ecf20Sopenharmony_ci switch (src_data) { 41378c2ecf20Sopenharmony_ci case 0: /* D1 vblank */ 41388c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)) 41398c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); 41408c2ecf20Sopenharmony_ci 41418c2ecf20Sopenharmony_ci if (rdev->irq.crtc_vblank_int[0]) { 41428c2ecf20Sopenharmony_ci drm_handle_vblank(rdev->ddev, 0); 41438c2ecf20Sopenharmony_ci rdev->pm.vblank_sync = true; 41448c2ecf20Sopenharmony_ci wake_up(&rdev->irq.vblank_queue); 41458c2ecf20Sopenharmony_ci } 41468c2ecf20Sopenharmony_ci if (atomic_read(&rdev->irq.pflip[0])) 41478c2ecf20Sopenharmony_ci radeon_crtc_handle_vblank(rdev, 0); 41488c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; 41498c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D1 vblank\n"); 41508c2ecf20Sopenharmony_ci 41518c2ecf20Sopenharmony_ci break; 41528c2ecf20Sopenharmony_ci case 1: /* D1 vline */ 41538c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)) 41548c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); 41558c2ecf20Sopenharmony_ci 41568c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; 41578c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D1 vline\n"); 41588c2ecf20Sopenharmony_ci 41598c2ecf20Sopenharmony_ci break; 41608c2ecf20Sopenharmony_ci default: 41618c2ecf20Sopenharmony_ci DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); 41628c2ecf20Sopenharmony_ci break; 41638c2ecf20Sopenharmony_ci } 41648c2ecf20Sopenharmony_ci break; 41658c2ecf20Sopenharmony_ci case 5: /* D2 vblank/vline */ 41668c2ecf20Sopenharmony_ci switch (src_data) { 41678c2ecf20Sopenharmony_ci case 0: /* D2 vblank */ 41688c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT)) 41698c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); 41708c2ecf20Sopenharmony_ci 41718c2ecf20Sopenharmony_ci if (rdev->irq.crtc_vblank_int[1]) { 41728c2ecf20Sopenharmony_ci drm_handle_vblank(rdev->ddev, 1); 41738c2ecf20Sopenharmony_ci rdev->pm.vblank_sync = true; 41748c2ecf20Sopenharmony_ci wake_up(&rdev->irq.vblank_queue); 41758c2ecf20Sopenharmony_ci } 41768c2ecf20Sopenharmony_ci if (atomic_read(&rdev->irq.pflip[1])) 41778c2ecf20Sopenharmony_ci radeon_crtc_handle_vblank(rdev, 1); 41788c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; 41798c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D2 vblank\n"); 41808c2ecf20Sopenharmony_ci 41818c2ecf20Sopenharmony_ci break; 41828c2ecf20Sopenharmony_ci case 1: /* D1 vline */ 41838c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT)) 41848c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); 41858c2ecf20Sopenharmony_ci 41868c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; 41878c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D2 vline\n"); 41888c2ecf20Sopenharmony_ci 41898c2ecf20Sopenharmony_ci break; 41908c2ecf20Sopenharmony_ci default: 41918c2ecf20Sopenharmony_ci DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); 41928c2ecf20Sopenharmony_ci break; 41938c2ecf20Sopenharmony_ci } 41948c2ecf20Sopenharmony_ci break; 41958c2ecf20Sopenharmony_ci case 9: /* D1 pflip */ 41968c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D1 flip\n"); 41978c2ecf20Sopenharmony_ci if (radeon_use_pflipirq > 0) 41988c2ecf20Sopenharmony_ci radeon_crtc_handle_flip(rdev, 0); 41998c2ecf20Sopenharmony_ci break; 42008c2ecf20Sopenharmony_ci case 11: /* D2 pflip */ 42018c2ecf20Sopenharmony_ci DRM_DEBUG("IH: D2 flip\n"); 42028c2ecf20Sopenharmony_ci if (radeon_use_pflipirq > 0) 42038c2ecf20Sopenharmony_ci radeon_crtc_handle_flip(rdev, 1); 42048c2ecf20Sopenharmony_ci break; 42058c2ecf20Sopenharmony_ci case 19: /* HPD/DAC hotplug */ 42068c2ecf20Sopenharmony_ci switch (src_data) { 42078c2ecf20Sopenharmony_ci case 0: 42088c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT)) 42098c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD1 - IH event w/o asserted irq bit?\n"); 42108c2ecf20Sopenharmony_ci 42118c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; 42128c2ecf20Sopenharmony_ci queue_hotplug = true; 42138c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD1\n"); 42148c2ecf20Sopenharmony_ci break; 42158c2ecf20Sopenharmony_ci case 1: 42168c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT)) 42178c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD2 - IH event w/o asserted irq bit?\n"); 42188c2ecf20Sopenharmony_ci 42198c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; 42208c2ecf20Sopenharmony_ci queue_hotplug = true; 42218c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD2\n"); 42228c2ecf20Sopenharmony_ci break; 42238c2ecf20Sopenharmony_ci case 4: 42248c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT)) 42258c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD3 - IH event w/o asserted irq bit?\n"); 42268c2ecf20Sopenharmony_ci 42278c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; 42288c2ecf20Sopenharmony_ci queue_hotplug = true; 42298c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD3\n"); 42308c2ecf20Sopenharmony_ci break; 42318c2ecf20Sopenharmony_ci case 5: 42328c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT)) 42338c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD4 - IH event w/o asserted irq bit?\n"); 42348c2ecf20Sopenharmony_ci 42358c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; 42368c2ecf20Sopenharmony_ci queue_hotplug = true; 42378c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD4\n"); 42388c2ecf20Sopenharmony_ci break; 42398c2ecf20Sopenharmony_ci case 10: 42408c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT)) 42418c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD5 - IH event w/o asserted irq bit?\n"); 42428c2ecf20Sopenharmony_ci 42438c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; 42448c2ecf20Sopenharmony_ci queue_hotplug = true; 42458c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD5\n"); 42468c2ecf20Sopenharmony_ci break; 42478c2ecf20Sopenharmony_ci case 12: 42488c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT)) 42498c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD6 - IH event w/o asserted irq bit?\n"); 42508c2ecf20Sopenharmony_ci 42518c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; 42528c2ecf20Sopenharmony_ci queue_hotplug = true; 42538c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HPD6\n"); 42548c2ecf20Sopenharmony_ci 42558c2ecf20Sopenharmony_ci break; 42568c2ecf20Sopenharmony_ci default: 42578c2ecf20Sopenharmony_ci DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); 42588c2ecf20Sopenharmony_ci break; 42598c2ecf20Sopenharmony_ci } 42608c2ecf20Sopenharmony_ci break; 42618c2ecf20Sopenharmony_ci case 21: /* hdmi */ 42628c2ecf20Sopenharmony_ci switch (src_data) { 42638c2ecf20Sopenharmony_ci case 4: 42648c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG)) 42658c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HDMI0 - IH event w/o asserted irq bit?\n"); 42668c2ecf20Sopenharmony_ci 42678c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; 42688c2ecf20Sopenharmony_ci queue_hdmi = true; 42698c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HDMI0\n"); 42708c2ecf20Sopenharmony_ci 42718c2ecf20Sopenharmony_ci break; 42728c2ecf20Sopenharmony_ci case 5: 42738c2ecf20Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG)) 42748c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HDMI1 - IH event w/o asserted irq bit?\n"); 42758c2ecf20Sopenharmony_ci 42768c2ecf20Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; 42778c2ecf20Sopenharmony_ci queue_hdmi = true; 42788c2ecf20Sopenharmony_ci DRM_DEBUG("IH: HDMI1\n"); 42798c2ecf20Sopenharmony_ci 42808c2ecf20Sopenharmony_ci break; 42818c2ecf20Sopenharmony_ci default: 42828c2ecf20Sopenharmony_ci DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); 42838c2ecf20Sopenharmony_ci break; 42848c2ecf20Sopenharmony_ci } 42858c2ecf20Sopenharmony_ci break; 42868c2ecf20Sopenharmony_ci case 124: /* UVD */ 42878c2ecf20Sopenharmony_ci DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data); 42888c2ecf20Sopenharmony_ci radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX); 42898c2ecf20Sopenharmony_ci break; 42908c2ecf20Sopenharmony_ci case 176: /* CP_INT in ring buffer */ 42918c2ecf20Sopenharmony_ci case 177: /* CP_INT in IB1 */ 42928c2ecf20Sopenharmony_ci case 178: /* CP_INT in IB2 */ 42938c2ecf20Sopenharmony_ci DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); 42948c2ecf20Sopenharmony_ci radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); 42958c2ecf20Sopenharmony_ci break; 42968c2ecf20Sopenharmony_ci case 181: /* CP EOP event */ 42978c2ecf20Sopenharmony_ci DRM_DEBUG("IH: CP EOP\n"); 42988c2ecf20Sopenharmony_ci radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); 42998c2ecf20Sopenharmony_ci break; 43008c2ecf20Sopenharmony_ci case 224: /* DMA trap event */ 43018c2ecf20Sopenharmony_ci DRM_DEBUG("IH: DMA trap\n"); 43028c2ecf20Sopenharmony_ci radeon_fence_process(rdev, R600_RING_TYPE_DMA_INDEX); 43038c2ecf20Sopenharmony_ci break; 43048c2ecf20Sopenharmony_ci case 230: /* thermal low to high */ 43058c2ecf20Sopenharmony_ci DRM_DEBUG("IH: thermal low to high\n"); 43068c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.high_to_low = false; 43078c2ecf20Sopenharmony_ci queue_thermal = true; 43088c2ecf20Sopenharmony_ci break; 43098c2ecf20Sopenharmony_ci case 231: /* thermal high to low */ 43108c2ecf20Sopenharmony_ci DRM_DEBUG("IH: thermal high to low\n"); 43118c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.high_to_low = true; 43128c2ecf20Sopenharmony_ci queue_thermal = true; 43138c2ecf20Sopenharmony_ci break; 43148c2ecf20Sopenharmony_ci case 233: /* GUI IDLE */ 43158c2ecf20Sopenharmony_ci DRM_DEBUG("IH: GUI idle\n"); 43168c2ecf20Sopenharmony_ci break; 43178c2ecf20Sopenharmony_ci default: 43188c2ecf20Sopenharmony_ci DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); 43198c2ecf20Sopenharmony_ci break; 43208c2ecf20Sopenharmony_ci } 43218c2ecf20Sopenharmony_ci 43228c2ecf20Sopenharmony_ci /* wptr/rptr are in bytes! */ 43238c2ecf20Sopenharmony_ci rptr += 16; 43248c2ecf20Sopenharmony_ci rptr &= rdev->ih.ptr_mask; 43258c2ecf20Sopenharmony_ci WREG32(IH_RB_RPTR, rptr); 43268c2ecf20Sopenharmony_ci } 43278c2ecf20Sopenharmony_ci if (queue_hotplug) 43288c2ecf20Sopenharmony_ci schedule_delayed_work(&rdev->hotplug_work, 0); 43298c2ecf20Sopenharmony_ci if (queue_hdmi) 43308c2ecf20Sopenharmony_ci schedule_work(&rdev->audio_work); 43318c2ecf20Sopenharmony_ci if (queue_thermal && rdev->pm.dpm_enabled) 43328c2ecf20Sopenharmony_ci schedule_work(&rdev->pm.dpm.thermal.work); 43338c2ecf20Sopenharmony_ci rdev->ih.rptr = rptr; 43348c2ecf20Sopenharmony_ci WREG32(IH_RB_RPTR, rptr); 43358c2ecf20Sopenharmony_ci atomic_set(&rdev->ih.lock, 0); 43368c2ecf20Sopenharmony_ci 43378c2ecf20Sopenharmony_ci /* make sure wptr hasn't changed while processing */ 43388c2ecf20Sopenharmony_ci wptr = r600_get_ih_wptr(rdev); 43398c2ecf20Sopenharmony_ci if (wptr != rptr) 43408c2ecf20Sopenharmony_ci goto restart_ih; 43418c2ecf20Sopenharmony_ci 43428c2ecf20Sopenharmony_ci return IRQ_HANDLED; 43438c2ecf20Sopenharmony_ci} 43448c2ecf20Sopenharmony_ci 43458c2ecf20Sopenharmony_ci/* 43468c2ecf20Sopenharmony_ci * Debugfs info 43478c2ecf20Sopenharmony_ci */ 43488c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 43498c2ecf20Sopenharmony_ci 43508c2ecf20Sopenharmony_cistatic int r600_debugfs_mc_info(struct seq_file *m, void *data) 43518c2ecf20Sopenharmony_ci{ 43528c2ecf20Sopenharmony_ci struct drm_info_node *node = (struct drm_info_node *) m->private; 43538c2ecf20Sopenharmony_ci struct drm_device *dev = node->minor->dev; 43548c2ecf20Sopenharmony_ci struct radeon_device *rdev = dev->dev_private; 43558c2ecf20Sopenharmony_ci 43568c2ecf20Sopenharmony_ci DREG32_SYS(m, rdev, R_000E50_SRBM_STATUS); 43578c2ecf20Sopenharmony_ci DREG32_SYS(m, rdev, VM_L2_STATUS); 43588c2ecf20Sopenharmony_ci return 0; 43598c2ecf20Sopenharmony_ci} 43608c2ecf20Sopenharmony_ci 43618c2ecf20Sopenharmony_cistatic struct drm_info_list r600_mc_info_list[] = { 43628c2ecf20Sopenharmony_ci {"r600_mc_info", r600_debugfs_mc_info, 0, NULL}, 43638c2ecf20Sopenharmony_ci}; 43648c2ecf20Sopenharmony_ci#endif 43658c2ecf20Sopenharmony_ci 43668c2ecf20Sopenharmony_ciint r600_debugfs_mc_info_init(struct radeon_device *rdev) 43678c2ecf20Sopenharmony_ci{ 43688c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 43698c2ecf20Sopenharmony_ci return radeon_debugfs_add_files(rdev, r600_mc_info_list, ARRAY_SIZE(r600_mc_info_list)); 43708c2ecf20Sopenharmony_ci#else 43718c2ecf20Sopenharmony_ci return 0; 43728c2ecf20Sopenharmony_ci#endif 43738c2ecf20Sopenharmony_ci} 43748c2ecf20Sopenharmony_ci 43758c2ecf20Sopenharmony_ci/** 43768c2ecf20Sopenharmony_ci * r600_mmio_hdp_flush - flush Host Data Path cache via MMIO 43778c2ecf20Sopenharmony_ci * rdev: radeon device structure 43788c2ecf20Sopenharmony_ci * 43798c2ecf20Sopenharmony_ci * Some R6XX/R7XX don't seem to take into account HDP flushes performed 43808c2ecf20Sopenharmony_ci * through the ring buffer. This leads to corruption in rendering, see 43818c2ecf20Sopenharmony_ci * http://bugzilla.kernel.org/show_bug.cgi?id=15186 . To avoid this, we 43828c2ecf20Sopenharmony_ci * directly perform the HDP flush by writing the register through MMIO. 43838c2ecf20Sopenharmony_ci */ 43848c2ecf20Sopenharmony_civoid r600_mmio_hdp_flush(struct radeon_device *rdev) 43858c2ecf20Sopenharmony_ci{ 43868c2ecf20Sopenharmony_ci /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read 43878c2ecf20Sopenharmony_ci * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL. 43888c2ecf20Sopenharmony_ci * This seems to cause problems on some AGP cards. Just use the old 43898c2ecf20Sopenharmony_ci * method for them. 43908c2ecf20Sopenharmony_ci */ 43918c2ecf20Sopenharmony_ci if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && 43928c2ecf20Sopenharmony_ci rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) { 43938c2ecf20Sopenharmony_ci void __iomem *ptr = (void *)rdev->vram_scratch.ptr; 43948c2ecf20Sopenharmony_ci u32 tmp; 43958c2ecf20Sopenharmony_ci 43968c2ecf20Sopenharmony_ci WREG32(HDP_DEBUG1, 0); 43978c2ecf20Sopenharmony_ci tmp = readl((void __iomem *)ptr); 43988c2ecf20Sopenharmony_ci } else 43998c2ecf20Sopenharmony_ci WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); 44008c2ecf20Sopenharmony_ci} 44018c2ecf20Sopenharmony_ci 44028c2ecf20Sopenharmony_civoid r600_set_pcie_lanes(struct radeon_device *rdev, int lanes) 44038c2ecf20Sopenharmony_ci{ 44048c2ecf20Sopenharmony_ci u32 link_width_cntl, mask; 44058c2ecf20Sopenharmony_ci 44068c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 44078c2ecf20Sopenharmony_ci return; 44088c2ecf20Sopenharmony_ci 44098c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 44108c2ecf20Sopenharmony_ci return; 44118c2ecf20Sopenharmony_ci 44128c2ecf20Sopenharmony_ci /* x2 cards have a special sequence */ 44138c2ecf20Sopenharmony_ci if (ASIC_IS_X2(rdev)) 44148c2ecf20Sopenharmony_ci return; 44158c2ecf20Sopenharmony_ci 44168c2ecf20Sopenharmony_ci radeon_gui_idle(rdev); 44178c2ecf20Sopenharmony_ci 44188c2ecf20Sopenharmony_ci switch (lanes) { 44198c2ecf20Sopenharmony_ci case 0: 44208c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X0; 44218c2ecf20Sopenharmony_ci break; 44228c2ecf20Sopenharmony_ci case 1: 44238c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X1; 44248c2ecf20Sopenharmony_ci break; 44258c2ecf20Sopenharmony_ci case 2: 44268c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X2; 44278c2ecf20Sopenharmony_ci break; 44288c2ecf20Sopenharmony_ci case 4: 44298c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X4; 44308c2ecf20Sopenharmony_ci break; 44318c2ecf20Sopenharmony_ci case 8: 44328c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X8; 44338c2ecf20Sopenharmony_ci break; 44348c2ecf20Sopenharmony_ci case 12: 44358c2ecf20Sopenharmony_ci /* not actually supported */ 44368c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X12; 44378c2ecf20Sopenharmony_ci break; 44388c2ecf20Sopenharmony_ci case 16: 44398c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X16; 44408c2ecf20Sopenharmony_ci break; 44418c2ecf20Sopenharmony_ci default: 44428c2ecf20Sopenharmony_ci DRM_ERROR("invalid pcie lane request: %d\n", lanes); 44438c2ecf20Sopenharmony_ci return; 44448c2ecf20Sopenharmony_ci } 44458c2ecf20Sopenharmony_ci 44468c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 44478c2ecf20Sopenharmony_ci link_width_cntl &= ~RADEON_PCIE_LC_LINK_WIDTH_MASK; 44488c2ecf20Sopenharmony_ci link_width_cntl |= mask << RADEON_PCIE_LC_LINK_WIDTH_SHIFT; 44498c2ecf20Sopenharmony_ci link_width_cntl |= (RADEON_PCIE_LC_RECONFIG_NOW | 44508c2ecf20Sopenharmony_ci R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE); 44518c2ecf20Sopenharmony_ci 44528c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 44538c2ecf20Sopenharmony_ci} 44548c2ecf20Sopenharmony_ci 44558c2ecf20Sopenharmony_ciint r600_get_pcie_lanes(struct radeon_device *rdev) 44568c2ecf20Sopenharmony_ci{ 44578c2ecf20Sopenharmony_ci u32 link_width_cntl; 44588c2ecf20Sopenharmony_ci 44598c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 44608c2ecf20Sopenharmony_ci return 0; 44618c2ecf20Sopenharmony_ci 44628c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 44638c2ecf20Sopenharmony_ci return 0; 44648c2ecf20Sopenharmony_ci 44658c2ecf20Sopenharmony_ci /* x2 cards have a special sequence */ 44668c2ecf20Sopenharmony_ci if (ASIC_IS_X2(rdev)) 44678c2ecf20Sopenharmony_ci return 0; 44688c2ecf20Sopenharmony_ci 44698c2ecf20Sopenharmony_ci radeon_gui_idle(rdev); 44708c2ecf20Sopenharmony_ci 44718c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 44728c2ecf20Sopenharmony_ci 44738c2ecf20Sopenharmony_ci switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) { 44748c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X1: 44758c2ecf20Sopenharmony_ci return 1; 44768c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X2: 44778c2ecf20Sopenharmony_ci return 2; 44788c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X4: 44798c2ecf20Sopenharmony_ci return 4; 44808c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X8: 44818c2ecf20Sopenharmony_ci return 8; 44828c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X12: 44838c2ecf20Sopenharmony_ci /* not actually supported */ 44848c2ecf20Sopenharmony_ci return 12; 44858c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X0: 44868c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X16: 44878c2ecf20Sopenharmony_ci default: 44888c2ecf20Sopenharmony_ci return 16; 44898c2ecf20Sopenharmony_ci } 44908c2ecf20Sopenharmony_ci} 44918c2ecf20Sopenharmony_ci 44928c2ecf20Sopenharmony_cistatic void r600_pcie_gen2_enable(struct radeon_device *rdev) 44938c2ecf20Sopenharmony_ci{ 44948c2ecf20Sopenharmony_ci u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; 44958c2ecf20Sopenharmony_ci u16 link_cntl2; 44968c2ecf20Sopenharmony_ci 44978c2ecf20Sopenharmony_ci if (radeon_pcie_gen2 == 0) 44988c2ecf20Sopenharmony_ci return; 44998c2ecf20Sopenharmony_ci 45008c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 45018c2ecf20Sopenharmony_ci return; 45028c2ecf20Sopenharmony_ci 45038c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 45048c2ecf20Sopenharmony_ci return; 45058c2ecf20Sopenharmony_ci 45068c2ecf20Sopenharmony_ci /* x2 cards have a special sequence */ 45078c2ecf20Sopenharmony_ci if (ASIC_IS_X2(rdev)) 45088c2ecf20Sopenharmony_ci return; 45098c2ecf20Sopenharmony_ci 45108c2ecf20Sopenharmony_ci /* only RV6xx+ chips are supported */ 45118c2ecf20Sopenharmony_ci if (rdev->family <= CHIP_R600) 45128c2ecf20Sopenharmony_ci return; 45138c2ecf20Sopenharmony_ci 45148c2ecf20Sopenharmony_ci if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && 45158c2ecf20Sopenharmony_ci (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) 45168c2ecf20Sopenharmony_ci return; 45178c2ecf20Sopenharmony_ci 45188c2ecf20Sopenharmony_ci speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); 45198c2ecf20Sopenharmony_ci if (speed_cntl & LC_CURRENT_DATA_RATE) { 45208c2ecf20Sopenharmony_ci DRM_INFO("PCIE gen 2 link speeds already enabled\n"); 45218c2ecf20Sopenharmony_ci return; 45228c2ecf20Sopenharmony_ci } 45238c2ecf20Sopenharmony_ci 45248c2ecf20Sopenharmony_ci DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); 45258c2ecf20Sopenharmony_ci 45268c2ecf20Sopenharmony_ci /* 55 nm r6xx asics */ 45278c2ecf20Sopenharmony_ci if ((rdev->family == CHIP_RV670) || 45288c2ecf20Sopenharmony_ci (rdev->family == CHIP_RV620) || 45298c2ecf20Sopenharmony_ci (rdev->family == CHIP_RV635)) { 45308c2ecf20Sopenharmony_ci /* advertise upconfig capability */ 45318c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); 45328c2ecf20Sopenharmony_ci link_width_cntl &= ~LC_UPCONFIGURE_DIS; 45338c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 45348c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); 45358c2ecf20Sopenharmony_ci if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) { 45368c2ecf20Sopenharmony_ci lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT; 45378c2ecf20Sopenharmony_ci link_width_cntl &= ~(LC_LINK_WIDTH_MASK | 45388c2ecf20Sopenharmony_ci LC_RECONFIG_ARC_MISSING_ESCAPE); 45398c2ecf20Sopenharmony_ci link_width_cntl |= lanes | LC_RECONFIG_NOW | LC_RENEGOTIATE_EN; 45408c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 45418c2ecf20Sopenharmony_ci } else { 45428c2ecf20Sopenharmony_ci link_width_cntl |= LC_UPCONFIGURE_DIS; 45438c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 45448c2ecf20Sopenharmony_ci } 45458c2ecf20Sopenharmony_ci } 45468c2ecf20Sopenharmony_ci 45478c2ecf20Sopenharmony_ci speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); 45488c2ecf20Sopenharmony_ci if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) && 45498c2ecf20Sopenharmony_ci (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { 45508c2ecf20Sopenharmony_ci 45518c2ecf20Sopenharmony_ci /* 55 nm r6xx asics */ 45528c2ecf20Sopenharmony_ci if ((rdev->family == CHIP_RV670) || 45538c2ecf20Sopenharmony_ci (rdev->family == CHIP_RV620) || 45548c2ecf20Sopenharmony_ci (rdev->family == CHIP_RV635)) { 45558c2ecf20Sopenharmony_ci WREG32(MM_CFGREGS_CNTL, 0x8); 45568c2ecf20Sopenharmony_ci link_cntl2 = RREG32(0x4088); 45578c2ecf20Sopenharmony_ci WREG32(MM_CFGREGS_CNTL, 0); 45588c2ecf20Sopenharmony_ci /* not supported yet */ 45598c2ecf20Sopenharmony_ci if (link_cntl2 & SELECTABLE_DEEMPHASIS) 45608c2ecf20Sopenharmony_ci return; 45618c2ecf20Sopenharmony_ci } 45628c2ecf20Sopenharmony_ci 45638c2ecf20Sopenharmony_ci speed_cntl &= ~LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK; 45648c2ecf20Sopenharmony_ci speed_cntl |= (0x3 << LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT); 45658c2ecf20Sopenharmony_ci speed_cntl &= ~LC_VOLTAGE_TIMER_SEL_MASK; 45668c2ecf20Sopenharmony_ci speed_cntl &= ~LC_FORCE_DIS_HW_SPEED_CHANGE; 45678c2ecf20Sopenharmony_ci speed_cntl |= LC_FORCE_EN_HW_SPEED_CHANGE; 45688c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); 45698c2ecf20Sopenharmony_ci 45708c2ecf20Sopenharmony_ci tmp = RREG32(0x541c); 45718c2ecf20Sopenharmony_ci WREG32(0x541c, tmp | 0x8); 45728c2ecf20Sopenharmony_ci WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN); 45738c2ecf20Sopenharmony_ci link_cntl2 = RREG16(0x4088); 45748c2ecf20Sopenharmony_ci link_cntl2 &= ~TARGET_LINK_SPEED_MASK; 45758c2ecf20Sopenharmony_ci link_cntl2 |= 0x2; 45768c2ecf20Sopenharmony_ci WREG16(0x4088, link_cntl2); 45778c2ecf20Sopenharmony_ci WREG32(MM_CFGREGS_CNTL, 0); 45788c2ecf20Sopenharmony_ci 45798c2ecf20Sopenharmony_ci if ((rdev->family == CHIP_RV670) || 45808c2ecf20Sopenharmony_ci (rdev->family == CHIP_RV620) || 45818c2ecf20Sopenharmony_ci (rdev->family == CHIP_RV635)) { 45828c2ecf20Sopenharmony_ci training_cntl = RREG32_PCIE_PORT(PCIE_LC_TRAINING_CNTL); 45838c2ecf20Sopenharmony_ci training_cntl &= ~LC_POINT_7_PLUS_EN; 45848c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_TRAINING_CNTL, training_cntl); 45858c2ecf20Sopenharmony_ci } else { 45868c2ecf20Sopenharmony_ci speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); 45878c2ecf20Sopenharmony_ci speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN; 45888c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); 45898c2ecf20Sopenharmony_ci } 45908c2ecf20Sopenharmony_ci 45918c2ecf20Sopenharmony_ci speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); 45928c2ecf20Sopenharmony_ci speed_cntl |= LC_GEN2_EN_STRAP; 45938c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); 45948c2ecf20Sopenharmony_ci 45958c2ecf20Sopenharmony_ci } else { 45968c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); 45978c2ecf20Sopenharmony_ci /* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */ 45988c2ecf20Sopenharmony_ci if (1) 45998c2ecf20Sopenharmony_ci link_width_cntl |= LC_UPCONFIGURE_DIS; 46008c2ecf20Sopenharmony_ci else 46018c2ecf20Sopenharmony_ci link_width_cntl &= ~LC_UPCONFIGURE_DIS; 46028c2ecf20Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 46038c2ecf20Sopenharmony_ci } 46048c2ecf20Sopenharmony_ci} 46058c2ecf20Sopenharmony_ci 46068c2ecf20Sopenharmony_ci/** 46078c2ecf20Sopenharmony_ci * r600_get_gpu_clock_counter - return GPU clock counter snapshot 46088c2ecf20Sopenharmony_ci * 46098c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 46108c2ecf20Sopenharmony_ci * 46118c2ecf20Sopenharmony_ci * Fetches a GPU clock counter snapshot (R6xx-cayman). 46128c2ecf20Sopenharmony_ci * Returns the 64 bit clock counter snapshot. 46138c2ecf20Sopenharmony_ci */ 46148c2ecf20Sopenharmony_ciuint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev) 46158c2ecf20Sopenharmony_ci{ 46168c2ecf20Sopenharmony_ci uint64_t clock; 46178c2ecf20Sopenharmony_ci 46188c2ecf20Sopenharmony_ci mutex_lock(&rdev->gpu_clock_mutex); 46198c2ecf20Sopenharmony_ci WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); 46208c2ecf20Sopenharmony_ci clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | 46218c2ecf20Sopenharmony_ci ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); 46228c2ecf20Sopenharmony_ci mutex_unlock(&rdev->gpu_clock_mutex); 46238c2ecf20Sopenharmony_ci return clock; 46248c2ecf20Sopenharmony_ci} 4625