1771fe6b9SJerome Glisse /* 2771fe6b9SJerome Glisse * Copyright 2008 Advanced Micro Devices, Inc. 3771fe6b9SJerome Glisse * Copyright 2008 Red Hat Inc. 4771fe6b9SJerome Glisse * Copyright 2009 Jerome Glisse. 5771fe6b9SJerome Glisse * 6771fe6b9SJerome Glisse * Permission is hereby granted, free of charge, to any person obtaining a 7771fe6b9SJerome Glisse * copy of this software and associated documentation files (the "Software"), 8771fe6b9SJerome Glisse * to deal in the Software without restriction, including without limitation 9771fe6b9SJerome Glisse * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10771fe6b9SJerome Glisse * and/or sell copies of the Software, and to permit persons to whom the 11771fe6b9SJerome Glisse * Software is furnished to do so, subject to the following conditions: 12771fe6b9SJerome Glisse * 13771fe6b9SJerome Glisse * The above copyright notice and this permission notice shall be included in 14771fe6b9SJerome Glisse * all copies or substantial portions of the Software. 15771fe6b9SJerome Glisse * 16771fe6b9SJerome Glisse * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17771fe6b9SJerome Glisse * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18771fe6b9SJerome Glisse * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19771fe6b9SJerome Glisse * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20771fe6b9SJerome Glisse * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21771fe6b9SJerome Glisse * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22771fe6b9SJerome Glisse * OTHER DEALINGS IN THE SOFTWARE. 23771fe6b9SJerome Glisse * 24771fe6b9SJerome Glisse * Authors: Dave Airlie 25771fe6b9SJerome Glisse * Alex Deucher 26771fe6b9SJerome Glisse * Jerome Glisse 27771fe6b9SJerome Glisse */ 28771fe6b9SJerome Glisse #include <linux/seq_file.h> 29771fe6b9SJerome Glisse #include "drmP.h" 30771fe6b9SJerome Glisse #include "radeon_reg.h" 31771fe6b9SJerome Glisse #include "radeon.h" 32*905b6822SJerome Glisse #include "r420d.h" 33771fe6b9SJerome Glisse 34771fe6b9SJerome Glisse /* r420,r423,rv410 depends on : */ 35771fe6b9SJerome Glisse void r100_pci_gart_disable(struct radeon_device *rdev); 36771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev); 37771fe6b9SJerome Glisse void r100_mc_setup(struct radeon_device *rdev); 38771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev); 39771fe6b9SJerome Glisse void r100_mc_disable_clients(struct radeon_device *rdev); 40771fe6b9SJerome Glisse void r300_vram_info(struct radeon_device *rdev); 41771fe6b9SJerome Glisse int r300_mc_wait_for_idle(struct radeon_device *rdev); 42771fe6b9SJerome Glisse int rv370_pcie_gart_enable(struct radeon_device *rdev); 43771fe6b9SJerome Glisse void rv370_pcie_gart_disable(struct radeon_device *rdev); 44771fe6b9SJerome Glisse 45771fe6b9SJerome Glisse /* This files gather functions specifics to : 46771fe6b9SJerome Glisse * r420,r423,rv410 47771fe6b9SJerome Glisse * 48771fe6b9SJerome Glisse * Some of these functions might be used by newer ASICs. 49771fe6b9SJerome Glisse */ 50771fe6b9SJerome Glisse void r420_gpu_init(struct radeon_device *rdev); 51771fe6b9SJerome Glisse int r420_debugfs_pipes_info_init(struct radeon_device *rdev); 52771fe6b9SJerome Glisse 53771fe6b9SJerome Glisse 54771fe6b9SJerome Glisse /* 55771fe6b9SJerome Glisse * MC 56771fe6b9SJerome Glisse */ 57771fe6b9SJerome Glisse int r420_mc_init(struct radeon_device *rdev) 58771fe6b9SJerome Glisse { 59771fe6b9SJerome Glisse int r; 60771fe6b9SJerome Glisse 61771fe6b9SJerome Glisse if (r100_debugfs_rbbm_init(rdev)) { 62771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for RBBM !\n"); 63771fe6b9SJerome Glisse } 64771fe6b9SJerome Glisse if (r420_debugfs_pipes_info_init(rdev)) { 65771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for pipes !\n"); 66771fe6b9SJerome Glisse } 67771fe6b9SJerome Glisse 68771fe6b9SJerome Glisse r420_gpu_init(rdev); 69771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 70771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_PCIE) { 71771fe6b9SJerome Glisse rv370_pcie_gart_disable(rdev); 72771fe6b9SJerome Glisse } 73771fe6b9SJerome Glisse 74771fe6b9SJerome Glisse /* Setup GPU memory space */ 75771fe6b9SJerome Glisse rdev->mc.vram_location = 0xFFFFFFFFUL; 76771fe6b9SJerome Glisse rdev->mc.gtt_location = 0xFFFFFFFFUL; 77771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 78771fe6b9SJerome Glisse r = radeon_agp_init(rdev); 79771fe6b9SJerome Glisse if (r) { 80771fe6b9SJerome Glisse printk(KERN_WARNING "[drm] Disabling AGP\n"); 81771fe6b9SJerome Glisse rdev->flags &= ~RADEON_IS_AGP; 82771fe6b9SJerome Glisse rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; 83771fe6b9SJerome Glisse } else { 84771fe6b9SJerome Glisse rdev->mc.gtt_location = rdev->mc.agp_base; 85771fe6b9SJerome Glisse } 86771fe6b9SJerome Glisse } 87771fe6b9SJerome Glisse r = radeon_mc_setup(rdev); 88771fe6b9SJerome Glisse if (r) { 89771fe6b9SJerome Glisse return r; 90771fe6b9SJerome Glisse } 91771fe6b9SJerome Glisse 92771fe6b9SJerome Glisse /* Program GPU memory space */ 93771fe6b9SJerome Glisse r100_mc_disable_clients(rdev); 94771fe6b9SJerome Glisse if (r300_mc_wait_for_idle(rdev)) { 95771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait MC idle while " 96771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 97771fe6b9SJerome Glisse } 98771fe6b9SJerome Glisse r100_mc_setup(rdev); 99771fe6b9SJerome Glisse return 0; 100771fe6b9SJerome Glisse } 101771fe6b9SJerome Glisse 102771fe6b9SJerome Glisse void r420_mc_fini(struct radeon_device *rdev) 103771fe6b9SJerome Glisse { 104771fe6b9SJerome Glisse rv370_pcie_gart_disable(rdev); 105771fe6b9SJerome Glisse radeon_gart_table_vram_free(rdev); 106771fe6b9SJerome Glisse radeon_gart_fini(rdev); 107771fe6b9SJerome Glisse } 108771fe6b9SJerome Glisse 109771fe6b9SJerome Glisse 110771fe6b9SJerome Glisse /* 111771fe6b9SJerome Glisse * Global GPU functions 112771fe6b9SJerome Glisse */ 113771fe6b9SJerome Glisse void r420_errata(struct radeon_device *rdev) 114771fe6b9SJerome Glisse { 115771fe6b9SJerome Glisse rdev->pll_errata = 0; 116771fe6b9SJerome Glisse } 117771fe6b9SJerome Glisse 118771fe6b9SJerome Glisse void r420_pipes_init(struct radeon_device *rdev) 119771fe6b9SJerome Glisse { 120771fe6b9SJerome Glisse unsigned tmp; 121771fe6b9SJerome Glisse unsigned gb_pipe_select; 122771fe6b9SJerome Glisse unsigned num_pipes; 123771fe6b9SJerome Glisse 124771fe6b9SJerome Glisse /* GA_ENHANCE workaround TCL deadlock issue */ 125771fe6b9SJerome Glisse WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); 126771fe6b9SJerome Glisse /* get max number of pipes */ 127771fe6b9SJerome Glisse gb_pipe_select = RREG32(0x402C); 128771fe6b9SJerome Glisse num_pipes = ((gb_pipe_select >> 12) & 3) + 1; 129771fe6b9SJerome Glisse rdev->num_gb_pipes = num_pipes; 130771fe6b9SJerome Glisse tmp = 0; 131771fe6b9SJerome Glisse switch (num_pipes) { 132771fe6b9SJerome Glisse default: 133771fe6b9SJerome Glisse /* force to 1 pipe */ 134771fe6b9SJerome Glisse num_pipes = 1; 135771fe6b9SJerome Glisse case 1: 136771fe6b9SJerome Glisse tmp = (0 << 1); 137771fe6b9SJerome Glisse break; 138771fe6b9SJerome Glisse case 2: 139771fe6b9SJerome Glisse tmp = (3 << 1); 140771fe6b9SJerome Glisse break; 141771fe6b9SJerome Glisse case 3: 142771fe6b9SJerome Glisse tmp = (6 << 1); 143771fe6b9SJerome Glisse break; 144771fe6b9SJerome Glisse case 4: 145771fe6b9SJerome Glisse tmp = (7 << 1); 146771fe6b9SJerome Glisse break; 147771fe6b9SJerome Glisse } 148771fe6b9SJerome Glisse WREG32(0x42C8, (1 << num_pipes) - 1); 149771fe6b9SJerome Glisse /* Sub pixel 1/12 so we can have 4K rendering according to doc */ 150771fe6b9SJerome Glisse tmp |= (1 << 4) | (1 << 0); 151771fe6b9SJerome Glisse WREG32(0x4018, tmp); 152771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 153771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 154771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 155771fe6b9SJerome Glisse } 156771fe6b9SJerome Glisse 157771fe6b9SJerome Glisse tmp = RREG32(0x170C); 158771fe6b9SJerome Glisse WREG32(0x170C, tmp | (1 << 31)); 159771fe6b9SJerome Glisse 160771fe6b9SJerome Glisse WREG32(R300_RB2D_DSTCACHE_MODE, 161771fe6b9SJerome Glisse RREG32(R300_RB2D_DSTCACHE_MODE) | 162771fe6b9SJerome Glisse R300_DC_AUTOFLUSH_ENABLE | 163771fe6b9SJerome Glisse R300_DC_DC_DISABLE_IGNORE_PE); 164771fe6b9SJerome Glisse 165771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 166771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 167771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 168771fe6b9SJerome Glisse } 169f779b3e5SAlex Deucher 170f779b3e5SAlex Deucher if (rdev->family == CHIP_RV530) { 171f779b3e5SAlex Deucher tmp = RREG32(RV530_GB_PIPE_SELECT2); 172f779b3e5SAlex Deucher if ((tmp & 3) == 3) 173f779b3e5SAlex Deucher rdev->num_z_pipes = 2; 174f779b3e5SAlex Deucher else 175f779b3e5SAlex Deucher rdev->num_z_pipes = 1; 176f779b3e5SAlex Deucher } else 177f779b3e5SAlex Deucher rdev->num_z_pipes = 1; 178f779b3e5SAlex Deucher 179f779b3e5SAlex Deucher DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n", 180f779b3e5SAlex Deucher rdev->num_gb_pipes, rdev->num_z_pipes); 181771fe6b9SJerome Glisse } 182771fe6b9SJerome Glisse 183771fe6b9SJerome Glisse void r420_gpu_init(struct radeon_device *rdev) 184771fe6b9SJerome Glisse { 185771fe6b9SJerome Glisse r100_hdp_reset(rdev); 186771fe6b9SJerome Glisse r420_pipes_init(rdev); 187771fe6b9SJerome Glisse if (r300_mc_wait_for_idle(rdev)) { 188771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait MC idle while " 189771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 190771fe6b9SJerome Glisse } 191771fe6b9SJerome Glisse } 192771fe6b9SJerome Glisse 193771fe6b9SJerome Glisse 194771fe6b9SJerome Glisse /* 195771fe6b9SJerome Glisse * r420,r423,rv410 VRAM info 196771fe6b9SJerome Glisse */ 197771fe6b9SJerome Glisse void r420_vram_info(struct radeon_device *rdev) 198771fe6b9SJerome Glisse { 199771fe6b9SJerome Glisse r300_vram_info(rdev); 200771fe6b9SJerome Glisse } 201771fe6b9SJerome Glisse 202771fe6b9SJerome Glisse 203771fe6b9SJerome Glisse /* 204771fe6b9SJerome Glisse * Debugfs info 205771fe6b9SJerome Glisse */ 206771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 207771fe6b9SJerome Glisse static int r420_debugfs_pipes_info(struct seq_file *m, void *data) 208771fe6b9SJerome Glisse { 209771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 210771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 211771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 212771fe6b9SJerome Glisse uint32_t tmp; 213771fe6b9SJerome Glisse 214771fe6b9SJerome Glisse tmp = RREG32(R400_GB_PIPE_SELECT); 215771fe6b9SJerome Glisse seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); 216771fe6b9SJerome Glisse tmp = RREG32(R300_GB_TILE_CONFIG); 217771fe6b9SJerome Glisse seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); 218771fe6b9SJerome Glisse tmp = RREG32(R300_DST_PIPE_CONFIG); 219771fe6b9SJerome Glisse seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); 220771fe6b9SJerome Glisse return 0; 221771fe6b9SJerome Glisse } 222771fe6b9SJerome Glisse 223771fe6b9SJerome Glisse static struct drm_info_list r420_pipes_info_list[] = { 224771fe6b9SJerome Glisse {"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL}, 225771fe6b9SJerome Glisse }; 226771fe6b9SJerome Glisse #endif 227771fe6b9SJerome Glisse 228771fe6b9SJerome Glisse int r420_debugfs_pipes_info_init(struct radeon_device *rdev) 229771fe6b9SJerome Glisse { 230771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 231771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1); 232771fe6b9SJerome Glisse #else 233771fe6b9SJerome Glisse return 0; 234771fe6b9SJerome Glisse #endif 235771fe6b9SJerome Glisse } 236*905b6822SJerome Glisse 237*905b6822SJerome Glisse u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) 238*905b6822SJerome Glisse { 239*905b6822SJerome Glisse u32 r; 240*905b6822SJerome Glisse 241*905b6822SJerome Glisse WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); 242*905b6822SJerome Glisse r = RREG32(R_0001FC_MC_IND_DATA); 243*905b6822SJerome Glisse return r; 244*905b6822SJerome Glisse } 245*905b6822SJerome Glisse 246*905b6822SJerome Glisse void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) 247*905b6822SJerome Glisse { 248*905b6822SJerome Glisse WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | 249*905b6822SJerome Glisse S_0001F8_MC_IND_WR_EN(1)); 250*905b6822SJerome Glisse WREG32(R_0001FC_MC_IND_DATA, v); 251*905b6822SJerome Glisse } 252