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/pci.h> 308c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 318c2ecf20Sopenharmony_ci#include <linux/slab.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include <drm/drm_debugfs.h> 348c2ecf20Sopenharmony_ci#include <drm/drm_device.h> 358c2ecf20Sopenharmony_ci#include <drm/drm_file.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include "atom.h" 388c2ecf20Sopenharmony_ci#include "r100d.h" 398c2ecf20Sopenharmony_ci#include "r420_reg_safe.h" 408c2ecf20Sopenharmony_ci#include "r420d.h" 418c2ecf20Sopenharmony_ci#include "radeon.h" 428c2ecf20Sopenharmony_ci#include "radeon_asic.h" 438c2ecf20Sopenharmony_ci#include "radeon_reg.h" 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_civoid r420_pm_init_profile(struct radeon_device *rdev) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci /* default */ 488c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 498c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 508c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 518c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 528c2ecf20Sopenharmony_ci /* low sh */ 538c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; 548c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; 558c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 568c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 578c2ecf20Sopenharmony_ci /* mid sh */ 588c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; 598c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; 608c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 618c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 628c2ecf20Sopenharmony_ci /* high sh */ 638c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; 648c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 658c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 668c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 678c2ecf20Sopenharmony_ci /* low mh */ 688c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0; 698c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 708c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 718c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 728c2ecf20Sopenharmony_ci /* mid mh */ 738c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; 748c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 758c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 768c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 778c2ecf20Sopenharmony_ci /* high mh */ 788c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; 798c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 808c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 818c2ecf20Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic void r420_set_reg_safe(struct radeon_device *rdev) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci rdev->config.r300.reg_safe_bm = r420_reg_safe_bm; 878c2ecf20Sopenharmony_ci rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_civoid r420_pipes_init(struct radeon_device *rdev) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci unsigned tmp; 938c2ecf20Sopenharmony_ci unsigned gb_pipe_select; 948c2ecf20Sopenharmony_ci unsigned num_pipes; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* GA_ENHANCE workaround TCL deadlock issue */ 978c2ecf20Sopenharmony_ci WREG32(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL | 988c2ecf20Sopenharmony_ci (1 << 2) | (1 << 3)); 998c2ecf20Sopenharmony_ci /* add idle wait as per freedesktop.org bug 24041 */ 1008c2ecf20Sopenharmony_ci if (r100_gui_wait_for_idle(rdev)) { 1018c2ecf20Sopenharmony_ci pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n"); 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci /* get max number of pipes */ 1048c2ecf20Sopenharmony_ci gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); 1058c2ecf20Sopenharmony_ci num_pipes = ((gb_pipe_select >> 12) & 3) + 1; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* SE chips have 1 pipe */ 1088c2ecf20Sopenharmony_ci if ((rdev->pdev->device == 0x5e4c) || 1098c2ecf20Sopenharmony_ci (rdev->pdev->device == 0x5e4f)) 1108c2ecf20Sopenharmony_ci num_pipes = 1; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci rdev->num_gb_pipes = num_pipes; 1138c2ecf20Sopenharmony_ci tmp = 0; 1148c2ecf20Sopenharmony_ci switch (num_pipes) { 1158c2ecf20Sopenharmony_ci default: 1168c2ecf20Sopenharmony_ci /* force to 1 pipe */ 1178c2ecf20Sopenharmony_ci num_pipes = 1; 1188c2ecf20Sopenharmony_ci fallthrough; 1198c2ecf20Sopenharmony_ci case 1: 1208c2ecf20Sopenharmony_ci tmp = (0 << 1); 1218c2ecf20Sopenharmony_ci break; 1228c2ecf20Sopenharmony_ci case 2: 1238c2ecf20Sopenharmony_ci tmp = (3 << 1); 1248c2ecf20Sopenharmony_ci break; 1258c2ecf20Sopenharmony_ci case 3: 1268c2ecf20Sopenharmony_ci tmp = (6 << 1); 1278c2ecf20Sopenharmony_ci break; 1288c2ecf20Sopenharmony_ci case 4: 1298c2ecf20Sopenharmony_ci tmp = (7 << 1); 1308c2ecf20Sopenharmony_ci break; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci WREG32(R500_SU_REG_DEST, (1 << num_pipes) - 1); 1338c2ecf20Sopenharmony_ci /* Sub pixel 1/12 so we can have 4K rendering according to doc */ 1348c2ecf20Sopenharmony_ci tmp |= R300_TILE_SIZE_16 | R300_ENABLE_TILING; 1358c2ecf20Sopenharmony_ci WREG32(R300_GB_TILE_CONFIG, tmp); 1368c2ecf20Sopenharmony_ci if (r100_gui_wait_for_idle(rdev)) { 1378c2ecf20Sopenharmony_ci pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n"); 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci tmp = RREG32(R300_DST_PIPE_CONFIG); 1418c2ecf20Sopenharmony_ci WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci WREG32(R300_RB2D_DSTCACHE_MODE, 1448c2ecf20Sopenharmony_ci RREG32(R300_RB2D_DSTCACHE_MODE) | 1458c2ecf20Sopenharmony_ci R300_DC_AUTOFLUSH_ENABLE | 1468c2ecf20Sopenharmony_ci R300_DC_DC_DISABLE_IGNORE_PE); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (r100_gui_wait_for_idle(rdev)) { 1498c2ecf20Sopenharmony_ci pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n"); 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RV530) { 1538c2ecf20Sopenharmony_ci tmp = RREG32(RV530_GB_PIPE_SELECT2); 1548c2ecf20Sopenharmony_ci if ((tmp & 3) == 3) 1558c2ecf20Sopenharmony_ci rdev->num_z_pipes = 2; 1568c2ecf20Sopenharmony_ci else 1578c2ecf20Sopenharmony_ci rdev->num_z_pipes = 1; 1588c2ecf20Sopenharmony_ci } else 1598c2ecf20Sopenharmony_ci rdev->num_z_pipes = 1; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n", 1628c2ecf20Sopenharmony_ci rdev->num_gb_pipes, rdev->num_z_pipes); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ciu32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci unsigned long flags; 1688c2ecf20Sopenharmony_ci u32 r; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->mc_idx_lock, flags); 1718c2ecf20Sopenharmony_ci WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); 1728c2ecf20Sopenharmony_ci r = RREG32(R_0001FC_MC_IND_DATA); 1738c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); 1748c2ecf20Sopenharmony_ci return r; 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_civoid r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci unsigned long flags; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->mc_idx_lock, flags); 1828c2ecf20Sopenharmony_ci WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | 1838c2ecf20Sopenharmony_ci S_0001F8_MC_IND_WR_EN(1)); 1848c2ecf20Sopenharmony_ci WREG32(R_0001FC_MC_IND_DATA, v); 1858c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic void r420_debugfs(struct radeon_device *rdev) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci if (r100_debugfs_rbbm_init(rdev)) { 1918c2ecf20Sopenharmony_ci DRM_ERROR("Failed to register debugfs file for RBBM !\n"); 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci if (r420_debugfs_pipes_info_init(rdev)) { 1948c2ecf20Sopenharmony_ci DRM_ERROR("Failed to register debugfs file for pipes !\n"); 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic void r420_clock_resume(struct radeon_device *rdev) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci u32 sclk_cntl; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (radeon_dynclks != -1 && radeon_dynclks) 2038c2ecf20Sopenharmony_ci radeon_atom_set_clock_gating(rdev, 1); 2048c2ecf20Sopenharmony_ci sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL); 2058c2ecf20Sopenharmony_ci sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); 2068c2ecf20Sopenharmony_ci if (rdev->family == CHIP_R420) 2078c2ecf20Sopenharmony_ci sclk_cntl |= S_00000D_FORCE_PX(1) | S_00000D_FORCE_TX(1); 2088c2ecf20Sopenharmony_ci WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic void r420_cp_errata_init(struct radeon_device *rdev) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci int r; 2148c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* RV410 and R420 can lock up if CP DMA to host memory happens 2178c2ecf20Sopenharmony_ci * while the 2D engine is busy. 2188c2ecf20Sopenharmony_ci * 2198c2ecf20Sopenharmony_ci * The proper workaround is to queue a RESYNC at the beginning 2208c2ecf20Sopenharmony_ci * of the CP init, apparently. 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ci radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch); 2238c2ecf20Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 8); 2248c2ecf20Sopenharmony_ci WARN_ON(r); 2258c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_CP_RESYNC_ADDR, 1)); 2268c2ecf20Sopenharmony_ci radeon_ring_write(ring, rdev->config.r300.resync_scratch); 2278c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0xDEADBEEF); 2288c2ecf20Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic void r420_cp_errata_fini(struct radeon_device *rdev) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci int r; 2348c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* Catch the RESYNC we dispatched all the way back, 2378c2ecf20Sopenharmony_ci * at the very beginning of the CP init. 2388c2ecf20Sopenharmony_ci */ 2398c2ecf20Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 8); 2408c2ecf20Sopenharmony_ci WARN_ON(r); 2418c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); 2428c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_RB3D_DC_FINISH); 2438c2ecf20Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 2448c2ecf20Sopenharmony_ci radeon_scratch_free(rdev, rdev->config.r300.resync_scratch); 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic int r420_startup(struct radeon_device *rdev) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci int r; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* set common regs */ 2528c2ecf20Sopenharmony_ci r100_set_common_regs(rdev); 2538c2ecf20Sopenharmony_ci /* program mc */ 2548c2ecf20Sopenharmony_ci r300_mc_program(rdev); 2558c2ecf20Sopenharmony_ci /* Resume clock */ 2568c2ecf20Sopenharmony_ci r420_clock_resume(rdev); 2578c2ecf20Sopenharmony_ci /* Initialize GART (initialize after TTM so we can allocate 2588c2ecf20Sopenharmony_ci * memory through TTM but finalize after TTM) */ 2598c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) { 2608c2ecf20Sopenharmony_ci r = rv370_pcie_gart_enable(rdev); 2618c2ecf20Sopenharmony_ci if (r) 2628c2ecf20Sopenharmony_ci return r; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) { 2658c2ecf20Sopenharmony_ci r = r100_pci_gart_enable(rdev); 2668c2ecf20Sopenharmony_ci if (r) 2678c2ecf20Sopenharmony_ci return r; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci r420_pipes_init(rdev); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* allocate wb buffer */ 2728c2ecf20Sopenharmony_ci r = radeon_wb_init(rdev); 2738c2ecf20Sopenharmony_ci if (r) 2748c2ecf20Sopenharmony_ci return r; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 2778c2ecf20Sopenharmony_ci if (r) { 2788c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 2798c2ecf20Sopenharmony_ci return r; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* Enable IRQ */ 2838c2ecf20Sopenharmony_ci if (!rdev->irq.installed) { 2848c2ecf20Sopenharmony_ci r = radeon_irq_kms_init(rdev); 2858c2ecf20Sopenharmony_ci if (r) 2868c2ecf20Sopenharmony_ci return r; 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci r100_irq_set(rdev); 2908c2ecf20Sopenharmony_ci rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); 2918c2ecf20Sopenharmony_ci /* 1M ring buffer */ 2928c2ecf20Sopenharmony_ci r = r100_cp_init(rdev, 1024 * 1024); 2938c2ecf20Sopenharmony_ci if (r) { 2948c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP (%d).\n", r); 2958c2ecf20Sopenharmony_ci return r; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci r420_cp_errata_init(rdev); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci r = radeon_ib_pool_init(rdev); 3008c2ecf20Sopenharmony_ci if (r) { 3018c2ecf20Sopenharmony_ci dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 3028c2ecf20Sopenharmony_ci return r; 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci return 0; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ciint r420_resume(struct radeon_device *rdev) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci int r; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* Make sur GART are not working */ 3138c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 3148c2ecf20Sopenharmony_ci rv370_pcie_gart_disable(rdev); 3158c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 3168c2ecf20Sopenharmony_ci r100_pci_gart_disable(rdev); 3178c2ecf20Sopenharmony_ci /* Resume clock before doing reset */ 3188c2ecf20Sopenharmony_ci r420_clock_resume(rdev); 3198c2ecf20Sopenharmony_ci /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 3208c2ecf20Sopenharmony_ci if (radeon_asic_reset(rdev)) { 3218c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 3228c2ecf20Sopenharmony_ci RREG32(R_000E40_RBBM_STATUS), 3238c2ecf20Sopenharmony_ci RREG32(R_0007C0_CP_STAT)); 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci /* check if cards are posted or not */ 3268c2ecf20Sopenharmony_ci if (rdev->is_atom_bios) { 3278c2ecf20Sopenharmony_ci atom_asic_init(rdev->mode_info.atom_context); 3288c2ecf20Sopenharmony_ci } else { 3298c2ecf20Sopenharmony_ci radeon_combios_asic_init(rdev->ddev); 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci /* Resume clock after posting */ 3328c2ecf20Sopenharmony_ci r420_clock_resume(rdev); 3338c2ecf20Sopenharmony_ci /* Initialize surface registers */ 3348c2ecf20Sopenharmony_ci radeon_surface_init(rdev); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci rdev->accel_working = true; 3378c2ecf20Sopenharmony_ci r = r420_startup(rdev); 3388c2ecf20Sopenharmony_ci if (r) { 3398c2ecf20Sopenharmony_ci rdev->accel_working = false; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci return r; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ciint r420_suspend(struct radeon_device *rdev) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci radeon_pm_suspend(rdev); 3478c2ecf20Sopenharmony_ci r420_cp_errata_fini(rdev); 3488c2ecf20Sopenharmony_ci r100_cp_disable(rdev); 3498c2ecf20Sopenharmony_ci radeon_wb_disable(rdev); 3508c2ecf20Sopenharmony_ci r100_irq_disable(rdev); 3518c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 3528c2ecf20Sopenharmony_ci rv370_pcie_gart_disable(rdev); 3538c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 3548c2ecf20Sopenharmony_ci r100_pci_gart_disable(rdev); 3558c2ecf20Sopenharmony_ci return 0; 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_civoid r420_fini(struct radeon_device *rdev) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci radeon_pm_fini(rdev); 3618c2ecf20Sopenharmony_ci r100_cp_fini(rdev); 3628c2ecf20Sopenharmony_ci radeon_wb_fini(rdev); 3638c2ecf20Sopenharmony_ci radeon_ib_pool_fini(rdev); 3648c2ecf20Sopenharmony_ci radeon_gem_fini(rdev); 3658c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 3668c2ecf20Sopenharmony_ci rv370_pcie_gart_fini(rdev); 3678c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 3688c2ecf20Sopenharmony_ci r100_pci_gart_fini(rdev); 3698c2ecf20Sopenharmony_ci radeon_agp_fini(rdev); 3708c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 3718c2ecf20Sopenharmony_ci radeon_fence_driver_fini(rdev); 3728c2ecf20Sopenharmony_ci radeon_bo_fini(rdev); 3738c2ecf20Sopenharmony_ci if (rdev->is_atom_bios) { 3748c2ecf20Sopenharmony_ci radeon_atombios_fini(rdev); 3758c2ecf20Sopenharmony_ci } else { 3768c2ecf20Sopenharmony_ci radeon_combios_fini(rdev); 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci kfree(rdev->bios); 3798c2ecf20Sopenharmony_ci rdev->bios = NULL; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ciint r420_init(struct radeon_device *rdev) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci int r; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci /* Initialize scratch registers */ 3878c2ecf20Sopenharmony_ci radeon_scratch_init(rdev); 3888c2ecf20Sopenharmony_ci /* Initialize surface registers */ 3898c2ecf20Sopenharmony_ci radeon_surface_init(rdev); 3908c2ecf20Sopenharmony_ci /* TODO: disable VGA need to use VGA request */ 3918c2ecf20Sopenharmony_ci /* restore some register to sane defaults */ 3928c2ecf20Sopenharmony_ci r100_restore_sanity(rdev); 3938c2ecf20Sopenharmony_ci /* BIOS*/ 3948c2ecf20Sopenharmony_ci if (!radeon_get_bios(rdev)) { 3958c2ecf20Sopenharmony_ci if (ASIC_IS_AVIVO(rdev)) 3968c2ecf20Sopenharmony_ci return -EINVAL; 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci if (rdev->is_atom_bios) { 3998c2ecf20Sopenharmony_ci r = radeon_atombios_init(rdev); 4008c2ecf20Sopenharmony_ci if (r) { 4018c2ecf20Sopenharmony_ci return r; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci } else { 4048c2ecf20Sopenharmony_ci r = radeon_combios_init(rdev); 4058c2ecf20Sopenharmony_ci if (r) { 4068c2ecf20Sopenharmony_ci return r; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 4108c2ecf20Sopenharmony_ci if (radeon_asic_reset(rdev)) { 4118c2ecf20Sopenharmony_ci dev_warn(rdev->dev, 4128c2ecf20Sopenharmony_ci "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 4138c2ecf20Sopenharmony_ci RREG32(R_000E40_RBBM_STATUS), 4148c2ecf20Sopenharmony_ci RREG32(R_0007C0_CP_STAT)); 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci /* check if cards are posted or not */ 4178c2ecf20Sopenharmony_ci if (radeon_boot_test_post_card(rdev) == false) 4188c2ecf20Sopenharmony_ci return -EINVAL; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci /* Initialize clocks */ 4218c2ecf20Sopenharmony_ci radeon_get_clock_info(rdev->ddev); 4228c2ecf20Sopenharmony_ci /* initialize AGP */ 4238c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 4248c2ecf20Sopenharmony_ci r = radeon_agp_init(rdev); 4258c2ecf20Sopenharmony_ci if (r) { 4268c2ecf20Sopenharmony_ci radeon_agp_disable(rdev); 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci /* initialize memory controller */ 4308c2ecf20Sopenharmony_ci r300_mc_init(rdev); 4318c2ecf20Sopenharmony_ci r420_debugfs(rdev); 4328c2ecf20Sopenharmony_ci /* Fence driver */ 4338c2ecf20Sopenharmony_ci r = radeon_fence_driver_init(rdev); 4348c2ecf20Sopenharmony_ci if (r) { 4358c2ecf20Sopenharmony_ci return r; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci /* Memory manager */ 4388c2ecf20Sopenharmony_ci r = radeon_bo_init(rdev); 4398c2ecf20Sopenharmony_ci if (r) { 4408c2ecf20Sopenharmony_ci return r; 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci if (rdev->family == CHIP_R420) 4438c2ecf20Sopenharmony_ci r100_enable_bm(rdev); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) { 4468c2ecf20Sopenharmony_ci r = rv370_pcie_gart_init(rdev); 4478c2ecf20Sopenharmony_ci if (r) 4488c2ecf20Sopenharmony_ci return r; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) { 4518c2ecf20Sopenharmony_ci r = r100_pci_gart_init(rdev); 4528c2ecf20Sopenharmony_ci if (r) 4538c2ecf20Sopenharmony_ci return r; 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci r420_set_reg_safe(rdev); 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci /* Initialize power management */ 4588c2ecf20Sopenharmony_ci radeon_pm_init(rdev); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci rdev->accel_working = true; 4618c2ecf20Sopenharmony_ci r = r420_startup(rdev); 4628c2ecf20Sopenharmony_ci if (r) { 4638c2ecf20Sopenharmony_ci /* Somethings want wront with the accel init stop accel */ 4648c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Disabling GPU acceleration\n"); 4658c2ecf20Sopenharmony_ci r100_cp_fini(rdev); 4668c2ecf20Sopenharmony_ci radeon_wb_fini(rdev); 4678c2ecf20Sopenharmony_ci radeon_ib_pool_fini(rdev); 4688c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 4698c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 4708c2ecf20Sopenharmony_ci rv370_pcie_gart_fini(rdev); 4718c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 4728c2ecf20Sopenharmony_ci r100_pci_gart_fini(rdev); 4738c2ecf20Sopenharmony_ci radeon_agp_fini(rdev); 4748c2ecf20Sopenharmony_ci rdev->accel_working = false; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci return 0; 4778c2ecf20Sopenharmony_ci} 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci/* 4808c2ecf20Sopenharmony_ci * Debugfs info 4818c2ecf20Sopenharmony_ci */ 4828c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 4838c2ecf20Sopenharmony_cistatic int r420_debugfs_pipes_info(struct seq_file *m, void *data) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci struct drm_info_node *node = (struct drm_info_node *) m->private; 4868c2ecf20Sopenharmony_ci struct drm_device *dev = node->minor->dev; 4878c2ecf20Sopenharmony_ci struct radeon_device *rdev = dev->dev_private; 4888c2ecf20Sopenharmony_ci uint32_t tmp; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci tmp = RREG32(R400_GB_PIPE_SELECT); 4918c2ecf20Sopenharmony_ci seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); 4928c2ecf20Sopenharmony_ci tmp = RREG32(R300_GB_TILE_CONFIG); 4938c2ecf20Sopenharmony_ci seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); 4948c2ecf20Sopenharmony_ci tmp = RREG32(R300_DST_PIPE_CONFIG); 4958c2ecf20Sopenharmony_ci seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); 4968c2ecf20Sopenharmony_ci return 0; 4978c2ecf20Sopenharmony_ci} 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_cistatic struct drm_info_list r420_pipes_info_list[] = { 5008c2ecf20Sopenharmony_ci {"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL}, 5018c2ecf20Sopenharmony_ci}; 5028c2ecf20Sopenharmony_ci#endif 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ciint r420_debugfs_pipes_info_init(struct radeon_device *rdev) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 5078c2ecf20Sopenharmony_ci return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1); 5088c2ecf20Sopenharmony_ci#else 5098c2ecf20Sopenharmony_ci return 0; 5108c2ecf20Sopenharmony_ci#endif 5118c2ecf20Sopenharmony_ci} 512