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" 32771fe6b9SJerome Glisse 33771fe6b9SJerome Glisse /* r420,r423,rv410 depends on : */ 34771fe6b9SJerome Glisse void r100_pci_gart_disable(struct radeon_device *rdev); 35771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev); 36771fe6b9SJerome Glisse void r100_mc_setup(struct radeon_device *rdev); 37771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev); 38771fe6b9SJerome Glisse void r100_mc_disable_clients(struct radeon_device *rdev); 39771fe6b9SJerome Glisse void r300_vram_info(struct radeon_device *rdev); 40771fe6b9SJerome Glisse int r300_mc_wait_for_idle(struct radeon_device *rdev); 41771fe6b9SJerome Glisse int rv370_pcie_gart_enable(struct radeon_device *rdev); 42771fe6b9SJerome Glisse void rv370_pcie_gart_disable(struct radeon_device *rdev); 43771fe6b9SJerome Glisse 44771fe6b9SJerome Glisse /* This files gather functions specifics to : 45771fe6b9SJerome Glisse * r420,r423,rv410 46771fe6b9SJerome Glisse * 47771fe6b9SJerome Glisse * Some of these functions might be used by newer ASICs. 48771fe6b9SJerome Glisse */ 49771fe6b9SJerome Glisse void r420_gpu_init(struct radeon_device *rdev); 50771fe6b9SJerome Glisse int r420_debugfs_pipes_info_init(struct radeon_device *rdev); 51771fe6b9SJerome Glisse 52771fe6b9SJerome Glisse 53771fe6b9SJerome Glisse /* 54771fe6b9SJerome Glisse * MC 55771fe6b9SJerome Glisse */ 56771fe6b9SJerome Glisse int r420_mc_init(struct radeon_device *rdev) 57771fe6b9SJerome Glisse { 58771fe6b9SJerome Glisse int r; 59771fe6b9SJerome Glisse 60771fe6b9SJerome Glisse if (r100_debugfs_rbbm_init(rdev)) { 61771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for RBBM !\n"); 62771fe6b9SJerome Glisse } 63771fe6b9SJerome Glisse if (r420_debugfs_pipes_info_init(rdev)) { 64771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for pipes !\n"); 65771fe6b9SJerome Glisse } 66771fe6b9SJerome Glisse 67771fe6b9SJerome Glisse r420_gpu_init(rdev); 68771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 69771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_PCIE) { 70771fe6b9SJerome Glisse rv370_pcie_gart_disable(rdev); 71771fe6b9SJerome Glisse } 72771fe6b9SJerome Glisse 73771fe6b9SJerome Glisse /* Setup GPU memory space */ 74771fe6b9SJerome Glisse rdev->mc.vram_location = 0xFFFFFFFFUL; 75771fe6b9SJerome Glisse rdev->mc.gtt_location = 0xFFFFFFFFUL; 76771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 77771fe6b9SJerome Glisse r = radeon_agp_init(rdev); 78771fe6b9SJerome Glisse if (r) { 79771fe6b9SJerome Glisse printk(KERN_WARNING "[drm] Disabling AGP\n"); 80771fe6b9SJerome Glisse rdev->flags &= ~RADEON_IS_AGP; 81771fe6b9SJerome Glisse rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; 82771fe6b9SJerome Glisse } else { 83771fe6b9SJerome Glisse rdev->mc.gtt_location = rdev->mc.agp_base; 84771fe6b9SJerome Glisse } 85771fe6b9SJerome Glisse } 86771fe6b9SJerome Glisse r = radeon_mc_setup(rdev); 87771fe6b9SJerome Glisse if (r) { 88771fe6b9SJerome Glisse return r; 89771fe6b9SJerome Glisse } 90771fe6b9SJerome Glisse 91771fe6b9SJerome Glisse /* Program GPU memory space */ 92771fe6b9SJerome Glisse r100_mc_disable_clients(rdev); 93771fe6b9SJerome Glisse if (r300_mc_wait_for_idle(rdev)) { 94771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait MC idle while " 95771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 96771fe6b9SJerome Glisse } 97771fe6b9SJerome Glisse r100_mc_setup(rdev); 98771fe6b9SJerome Glisse return 0; 99771fe6b9SJerome Glisse } 100771fe6b9SJerome Glisse 101771fe6b9SJerome Glisse void r420_mc_fini(struct radeon_device *rdev) 102771fe6b9SJerome Glisse { 103771fe6b9SJerome Glisse rv370_pcie_gart_disable(rdev); 104771fe6b9SJerome Glisse radeon_gart_table_vram_free(rdev); 105771fe6b9SJerome Glisse radeon_gart_fini(rdev); 106771fe6b9SJerome Glisse } 107771fe6b9SJerome Glisse 108771fe6b9SJerome Glisse 109771fe6b9SJerome Glisse /* 110771fe6b9SJerome Glisse * Global GPU functions 111771fe6b9SJerome Glisse */ 112771fe6b9SJerome Glisse void r420_errata(struct radeon_device *rdev) 113771fe6b9SJerome Glisse { 114771fe6b9SJerome Glisse rdev->pll_errata = 0; 115771fe6b9SJerome Glisse } 116771fe6b9SJerome Glisse 117771fe6b9SJerome Glisse void r420_pipes_init(struct radeon_device *rdev) 118771fe6b9SJerome Glisse { 119771fe6b9SJerome Glisse unsigned tmp; 120771fe6b9SJerome Glisse unsigned gb_pipe_select; 121771fe6b9SJerome Glisse unsigned num_pipes; 122771fe6b9SJerome Glisse 123771fe6b9SJerome Glisse /* GA_ENHANCE workaround TCL deadlock issue */ 124771fe6b9SJerome Glisse WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); 125771fe6b9SJerome Glisse /* get max number of pipes */ 126771fe6b9SJerome Glisse gb_pipe_select = RREG32(0x402C); 127771fe6b9SJerome Glisse num_pipes = ((gb_pipe_select >> 12) & 3) + 1; 128771fe6b9SJerome Glisse rdev->num_gb_pipes = num_pipes; 129771fe6b9SJerome Glisse tmp = 0; 130771fe6b9SJerome Glisse switch (num_pipes) { 131771fe6b9SJerome Glisse default: 132771fe6b9SJerome Glisse /* force to 1 pipe */ 133771fe6b9SJerome Glisse num_pipes = 1; 134771fe6b9SJerome Glisse case 1: 135771fe6b9SJerome Glisse tmp = (0 << 1); 136771fe6b9SJerome Glisse break; 137771fe6b9SJerome Glisse case 2: 138771fe6b9SJerome Glisse tmp = (3 << 1); 139771fe6b9SJerome Glisse break; 140771fe6b9SJerome Glisse case 3: 141771fe6b9SJerome Glisse tmp = (6 << 1); 142771fe6b9SJerome Glisse break; 143771fe6b9SJerome Glisse case 4: 144771fe6b9SJerome Glisse tmp = (7 << 1); 145771fe6b9SJerome Glisse break; 146771fe6b9SJerome Glisse } 147771fe6b9SJerome Glisse WREG32(0x42C8, (1 << num_pipes) - 1); 148771fe6b9SJerome Glisse /* Sub pixel 1/12 so we can have 4K rendering according to doc */ 149771fe6b9SJerome Glisse tmp |= (1 << 4) | (1 << 0); 150771fe6b9SJerome Glisse WREG32(0x4018, tmp); 151771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 152771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 153771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 154771fe6b9SJerome Glisse } 155771fe6b9SJerome Glisse 156771fe6b9SJerome Glisse tmp = RREG32(0x170C); 157771fe6b9SJerome Glisse WREG32(0x170C, tmp | (1 << 31)); 158771fe6b9SJerome Glisse 159771fe6b9SJerome Glisse WREG32(R300_RB2D_DSTCACHE_MODE, 160771fe6b9SJerome Glisse RREG32(R300_RB2D_DSTCACHE_MODE) | 161771fe6b9SJerome Glisse R300_DC_AUTOFLUSH_ENABLE | 162771fe6b9SJerome Glisse R300_DC_DC_DISABLE_IGNORE_PE); 163771fe6b9SJerome Glisse 164771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 165771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 166771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 167771fe6b9SJerome Glisse } 168*f779b3e5SAlex Deucher 169*f779b3e5SAlex Deucher if (rdev->family == CHIP_RV530) { 170*f779b3e5SAlex Deucher tmp = RREG32(RV530_GB_PIPE_SELECT2); 171*f779b3e5SAlex Deucher if ((tmp & 3) == 3) 172*f779b3e5SAlex Deucher rdev->num_z_pipes = 2; 173*f779b3e5SAlex Deucher else 174*f779b3e5SAlex Deucher rdev->num_z_pipes = 1; 175*f779b3e5SAlex Deucher } else 176*f779b3e5SAlex Deucher rdev->num_z_pipes = 1; 177*f779b3e5SAlex Deucher 178*f779b3e5SAlex Deucher DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n", 179*f779b3e5SAlex Deucher rdev->num_gb_pipes, rdev->num_z_pipes); 180771fe6b9SJerome Glisse } 181771fe6b9SJerome Glisse 182771fe6b9SJerome Glisse void r420_gpu_init(struct radeon_device *rdev) 183771fe6b9SJerome Glisse { 184771fe6b9SJerome Glisse r100_hdp_reset(rdev); 185771fe6b9SJerome Glisse r420_pipes_init(rdev); 186771fe6b9SJerome Glisse if (r300_mc_wait_for_idle(rdev)) { 187771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait MC idle while " 188771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 189771fe6b9SJerome Glisse } 190771fe6b9SJerome Glisse } 191771fe6b9SJerome Glisse 192771fe6b9SJerome Glisse 193771fe6b9SJerome Glisse /* 194771fe6b9SJerome Glisse * r420,r423,rv410 VRAM info 195771fe6b9SJerome Glisse */ 196771fe6b9SJerome Glisse void r420_vram_info(struct radeon_device *rdev) 197771fe6b9SJerome Glisse { 198771fe6b9SJerome Glisse r300_vram_info(rdev); 199771fe6b9SJerome Glisse } 200771fe6b9SJerome Glisse 201771fe6b9SJerome Glisse 202771fe6b9SJerome Glisse /* 203771fe6b9SJerome Glisse * Debugfs info 204771fe6b9SJerome Glisse */ 205771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 206771fe6b9SJerome Glisse static int r420_debugfs_pipes_info(struct seq_file *m, void *data) 207771fe6b9SJerome Glisse { 208771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 209771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 210771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 211771fe6b9SJerome Glisse uint32_t tmp; 212771fe6b9SJerome Glisse 213771fe6b9SJerome Glisse tmp = RREG32(R400_GB_PIPE_SELECT); 214771fe6b9SJerome Glisse seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); 215771fe6b9SJerome Glisse tmp = RREG32(R300_GB_TILE_CONFIG); 216771fe6b9SJerome Glisse seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); 217771fe6b9SJerome Glisse tmp = RREG32(R300_DST_PIPE_CONFIG); 218771fe6b9SJerome Glisse seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); 219771fe6b9SJerome Glisse return 0; 220771fe6b9SJerome Glisse } 221771fe6b9SJerome Glisse 222771fe6b9SJerome Glisse static struct drm_info_list r420_pipes_info_list[] = { 223771fe6b9SJerome Glisse {"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL}, 224771fe6b9SJerome Glisse }; 225771fe6b9SJerome Glisse #endif 226771fe6b9SJerome Glisse 227771fe6b9SJerome Glisse int r420_debugfs_pipes_info_init(struct radeon_device *rdev) 228771fe6b9SJerome Glisse { 229771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 230771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1); 231771fe6b9SJerome Glisse #else 232771fe6b9SJerome Glisse return 0; 233771fe6b9SJerome Glisse #endif 234771fe6b9SJerome Glisse } 235