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 "drmP.h" 29771fe6b9SJerome Glisse #include "radeon.h" 30e6990375SDaniel Vetter #include "radeon_asic.h" 31f0ed1f65SJerome Glisse #include "atom.h" 32f0ed1f65SJerome Glisse #include "r520d.h" 33771fe6b9SJerome Glisse 34f0ed1f65SJerome Glisse /* This files gather functions specifics to: r520,rv530,rv560,rv570,r580 */ 35771fe6b9SJerome Glisse 36f0ed1f65SJerome Glisse static int r520_mc_wait_for_idle(struct radeon_device *rdev) 37771fe6b9SJerome Glisse { 38771fe6b9SJerome Glisse unsigned i; 39771fe6b9SJerome Glisse uint32_t tmp; 40771fe6b9SJerome Glisse 41771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 42771fe6b9SJerome Glisse /* read MC_STATUS */ 43771fe6b9SJerome Glisse tmp = RREG32_MC(R520_MC_STATUS); 44771fe6b9SJerome Glisse if (tmp & R520_MC_STATUS_IDLE) { 45771fe6b9SJerome Glisse return 0; 46771fe6b9SJerome Glisse } 47771fe6b9SJerome Glisse DRM_UDELAY(1); 48771fe6b9SJerome Glisse } 49771fe6b9SJerome Glisse return -1; 50771fe6b9SJerome Glisse } 51771fe6b9SJerome Glisse 52f0ed1f65SJerome Glisse static void r520_gpu_init(struct radeon_device *rdev) 53771fe6b9SJerome Glisse { 54771fe6b9SJerome Glisse unsigned pipe_select_current, gb_pipe_select, tmp; 55771fe6b9SJerome Glisse 56771fe6b9SJerome Glisse r100_hdp_reset(rdev); 57d39c3b89SJerome Glisse rv515_vga_render_disable(rdev); 58771fe6b9SJerome Glisse /* 59771fe6b9SJerome Glisse * DST_PIPE_CONFIG 0x170C 60771fe6b9SJerome Glisse * GB_TILE_CONFIG 0x4018 61771fe6b9SJerome Glisse * GB_FIFO_SIZE 0x4024 62771fe6b9SJerome Glisse * GB_PIPE_SELECT 0x402C 63771fe6b9SJerome Glisse * GB_PIPE_SELECT2 0x4124 64771fe6b9SJerome Glisse * Z_PIPE_SHIFT 0 65771fe6b9SJerome Glisse * Z_PIPE_MASK 0x000000003 66771fe6b9SJerome Glisse * GB_FIFO_SIZE2 0x4128 67771fe6b9SJerome Glisse * SC_SFIFO_SIZE_SHIFT 0 68771fe6b9SJerome Glisse * SC_SFIFO_SIZE_MASK 0x000000003 69771fe6b9SJerome Glisse * SC_MFIFO_SIZE_SHIFT 2 70771fe6b9SJerome Glisse * SC_MFIFO_SIZE_MASK 0x00000000C 71771fe6b9SJerome Glisse * FG_SFIFO_SIZE_SHIFT 4 72771fe6b9SJerome Glisse * FG_SFIFO_SIZE_MASK 0x000000030 73771fe6b9SJerome Glisse * ZB_MFIFO_SIZE_SHIFT 6 74771fe6b9SJerome Glisse * ZB_MFIFO_SIZE_MASK 0x0000000C0 75771fe6b9SJerome Glisse * GA_ENHANCE 0x4274 76771fe6b9SJerome Glisse * SU_REG_DEST 0x42C8 77771fe6b9SJerome Glisse */ 78771fe6b9SJerome Glisse /* workaround for RV530 */ 79771fe6b9SJerome Glisse if (rdev->family == CHIP_RV530) { 80771fe6b9SJerome Glisse WREG32(0x4128, 0xFF); 81771fe6b9SJerome Glisse } 82771fe6b9SJerome Glisse r420_pipes_init(rdev); 83771fe6b9SJerome Glisse gb_pipe_select = RREG32(0x402C); 84771fe6b9SJerome Glisse tmp = RREG32(0x170C); 85771fe6b9SJerome Glisse pipe_select_current = (tmp >> 2) & 3; 86771fe6b9SJerome Glisse tmp = (1 << pipe_select_current) | 87771fe6b9SJerome Glisse (((gb_pipe_select >> 8) & 0xF) << 4); 88771fe6b9SJerome Glisse WREG32_PLL(0x000D, tmp); 89771fe6b9SJerome Glisse if (r520_mc_wait_for_idle(rdev)) { 90771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait MC idle while " 91771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 92771fe6b9SJerome Glisse } 93771fe6b9SJerome Glisse } 94771fe6b9SJerome Glisse 95771fe6b9SJerome Glisse static void r520_vram_get_type(struct radeon_device *rdev) 96771fe6b9SJerome Glisse { 97771fe6b9SJerome Glisse uint32_t tmp; 98771fe6b9SJerome Glisse 99771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 100771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 101771fe6b9SJerome Glisse tmp = RREG32_MC(R520_MC_CNTL0); 102771fe6b9SJerome Glisse switch ((tmp & R520_MEM_NUM_CHANNELS_MASK) >> R520_MEM_NUM_CHANNELS_SHIFT) { 103771fe6b9SJerome Glisse case 0: 104771fe6b9SJerome Glisse rdev->mc.vram_width = 32; 105771fe6b9SJerome Glisse break; 106771fe6b9SJerome Glisse case 1: 107771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 108771fe6b9SJerome Glisse break; 109771fe6b9SJerome Glisse case 2: 110771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 111771fe6b9SJerome Glisse break; 112771fe6b9SJerome Glisse case 3: 113771fe6b9SJerome Glisse rdev->mc.vram_width = 256; 114771fe6b9SJerome Glisse break; 115771fe6b9SJerome Glisse default: 116771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 117771fe6b9SJerome Glisse break; 118771fe6b9SJerome Glisse } 119771fe6b9SJerome Glisse if (tmp & R520_MC_CHANNEL_SIZE) 120771fe6b9SJerome Glisse rdev->mc.vram_width *= 2; 121771fe6b9SJerome Glisse } 122771fe6b9SJerome Glisse 123d594e46aSJerome Glisse void r520_mc_init(struct radeon_device *rdev) 124771fe6b9SJerome Glisse { 125c93bb85bSJerome Glisse 126771fe6b9SJerome Glisse r520_vram_get_type(rdev); 1272a0f8918SDave Airlie r100_vram_init_sizes(rdev); 128d594e46aSJerome Glisse radeon_vram_location(rdev, &rdev->mc, 0); 129d594e46aSJerome Glisse if (!(rdev->flags & RADEON_IS_AGP)) 130d594e46aSJerome Glisse radeon_gtt_location(rdev, &rdev->mc); 131f47299c5SAlex Deucher radeon_update_bandwidth_info(rdev); 132c93bb85bSJerome Glisse } 133c93bb85bSJerome Glisse 134f0ed1f65SJerome Glisse void r520_mc_program(struct radeon_device *rdev) 135c93bb85bSJerome Glisse { 136f0ed1f65SJerome Glisse struct rv515_mc_save save; 137f0ed1f65SJerome Glisse 138f0ed1f65SJerome Glisse /* Stops all mc clients */ 139f0ed1f65SJerome Glisse rv515_mc_stop(rdev, &save); 140f0ed1f65SJerome Glisse 141f0ed1f65SJerome Glisse /* Wait for mc idle */ 142f0ed1f65SJerome Glisse if (r520_mc_wait_for_idle(rdev)) 143f0ed1f65SJerome Glisse dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); 144f0ed1f65SJerome Glisse /* Write VRAM size in case we are limiting it */ 145f0ed1f65SJerome Glisse WREG32(R_0000F8_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 146f0ed1f65SJerome Glisse /* Program MC, should be a 32bits limited address space */ 147f0ed1f65SJerome Glisse WREG32_MC(R_000004_MC_FB_LOCATION, 148f0ed1f65SJerome Glisse S_000004_MC_FB_START(rdev->mc.vram_start >> 16) | 149f0ed1f65SJerome Glisse S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16)); 150f0ed1f65SJerome Glisse WREG32(R_000134_HDP_FB_LOCATION, 151f0ed1f65SJerome Glisse S_000134_HDP_FB_START(rdev->mc.vram_start >> 16)); 152f0ed1f65SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 153f0ed1f65SJerome Glisse WREG32_MC(R_000005_MC_AGP_LOCATION, 154f0ed1f65SJerome Glisse S_000005_MC_AGP_START(rdev->mc.gtt_start >> 16) | 155f0ed1f65SJerome Glisse S_000005_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); 156f0ed1f65SJerome Glisse WREG32_MC(R_000006_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); 157f0ed1f65SJerome Glisse WREG32_MC(R_000007_AGP_BASE_2, 158f0ed1f65SJerome Glisse S_000007_AGP_BASE_ADDR_2(upper_32_bits(rdev->mc.agp_base))); 159f0ed1f65SJerome Glisse } else { 160f0ed1f65SJerome Glisse WREG32_MC(R_000005_MC_AGP_LOCATION, 0xFFFFFFFF); 161f0ed1f65SJerome Glisse WREG32_MC(R_000006_AGP_BASE, 0); 162f0ed1f65SJerome Glisse WREG32_MC(R_000007_AGP_BASE_2, 0); 163f0ed1f65SJerome Glisse } 164f0ed1f65SJerome Glisse 165f0ed1f65SJerome Glisse rv515_mc_resume(rdev, &save); 166f0ed1f65SJerome Glisse } 167f0ed1f65SJerome Glisse 168f0ed1f65SJerome Glisse static int r520_startup(struct radeon_device *rdev) 169f0ed1f65SJerome Glisse { 170f0ed1f65SJerome Glisse int r; 171f0ed1f65SJerome Glisse 172f0ed1f65SJerome Glisse r520_mc_program(rdev); 173f0ed1f65SJerome Glisse /* Resume clock */ 174f0ed1f65SJerome Glisse rv515_clock_startup(rdev); 175f0ed1f65SJerome Glisse /* Initialize GPU configuration (# pipes, ...) */ 176f0ed1f65SJerome Glisse r520_gpu_init(rdev); 177f0ed1f65SJerome Glisse /* Initialize GART (initialize after TTM so we can allocate 178f0ed1f65SJerome Glisse * memory through TTM but finalize after TTM) */ 179f0ed1f65SJerome Glisse if (rdev->flags & RADEON_IS_PCIE) { 180f0ed1f65SJerome Glisse r = rv370_pcie_gart_enable(rdev); 181f0ed1f65SJerome Glisse if (r) 182f0ed1f65SJerome Glisse return r; 183f0ed1f65SJerome Glisse } 184f0ed1f65SJerome Glisse /* Enable IRQ */ 185ac447df4SJerome Glisse rs600_irq_set(rdev); 186cafe6609SJerome Glisse rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); 187f0ed1f65SJerome Glisse /* 1M ring buffer */ 188f0ed1f65SJerome Glisse r = r100_cp_init(rdev, 1024 * 1024); 189f0ed1f65SJerome Glisse if (r) { 190f0ed1f65SJerome Glisse dev_err(rdev->dev, "failled initializing CP (%d).\n", r); 191f0ed1f65SJerome Glisse return r; 192f0ed1f65SJerome Glisse } 193f0ed1f65SJerome Glisse r = r100_wb_init(rdev); 194f0ed1f65SJerome Glisse if (r) 195f0ed1f65SJerome Glisse dev_err(rdev->dev, "failled initializing WB (%d).\n", r); 196f0ed1f65SJerome Glisse r = r100_ib_init(rdev); 197f0ed1f65SJerome Glisse if (r) { 198f0ed1f65SJerome Glisse dev_err(rdev->dev, "failled initializing IB (%d).\n", r); 199f0ed1f65SJerome Glisse return r; 200f0ed1f65SJerome Glisse } 201f0ed1f65SJerome Glisse return 0; 202f0ed1f65SJerome Glisse } 203f0ed1f65SJerome Glisse 204f0ed1f65SJerome Glisse int r520_resume(struct radeon_device *rdev) 205f0ed1f65SJerome Glisse { 206f0ed1f65SJerome Glisse /* Make sur GART are not working */ 207f0ed1f65SJerome Glisse if (rdev->flags & RADEON_IS_PCIE) 208f0ed1f65SJerome Glisse rv370_pcie_gart_disable(rdev); 209f0ed1f65SJerome Glisse /* Resume clock before doing reset */ 210f0ed1f65SJerome Glisse rv515_clock_startup(rdev); 211f0ed1f65SJerome Glisse /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 212f0ed1f65SJerome Glisse if (radeon_gpu_reset(rdev)) { 213f0ed1f65SJerome Glisse dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 214f0ed1f65SJerome Glisse RREG32(R_000E40_RBBM_STATUS), 215f0ed1f65SJerome Glisse RREG32(R_0007C0_CP_STAT)); 216f0ed1f65SJerome Glisse } 217f0ed1f65SJerome Glisse /* post */ 218f0ed1f65SJerome Glisse atom_asic_init(rdev->mode_info.atom_context); 219f0ed1f65SJerome Glisse /* Resume clock after posting */ 220f0ed1f65SJerome Glisse rv515_clock_startup(rdev); 221550e2d92SDave Airlie /* Initialize surface registers */ 222550e2d92SDave Airlie radeon_surface_init(rdev); 223f0ed1f65SJerome Glisse return r520_startup(rdev); 224771fe6b9SJerome Glisse } 225d39c3b89SJerome Glisse 226d39c3b89SJerome Glisse int r520_init(struct radeon_device *rdev) 227d39c3b89SJerome Glisse { 228f0ed1f65SJerome Glisse int r; 229f0ed1f65SJerome Glisse 230f0ed1f65SJerome Glisse /* Initialize scratch registers */ 231f0ed1f65SJerome Glisse radeon_scratch_init(rdev); 232f0ed1f65SJerome Glisse /* Initialize surface registers */ 233f0ed1f65SJerome Glisse radeon_surface_init(rdev); 234f0ed1f65SJerome Glisse /* TODO: disable VGA need to use VGA request */ 235f0ed1f65SJerome Glisse /* BIOS*/ 236f0ed1f65SJerome Glisse if (!radeon_get_bios(rdev)) { 237f0ed1f65SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 238f0ed1f65SJerome Glisse return -EINVAL; 239f0ed1f65SJerome Glisse } 240f0ed1f65SJerome Glisse if (rdev->is_atom_bios) { 241f0ed1f65SJerome Glisse r = radeon_atombios_init(rdev); 242f0ed1f65SJerome Glisse if (r) 243f0ed1f65SJerome Glisse return r; 244f0ed1f65SJerome Glisse } else { 245f0ed1f65SJerome Glisse dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n"); 246f0ed1f65SJerome Glisse return -EINVAL; 247f0ed1f65SJerome Glisse } 248f0ed1f65SJerome Glisse /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 249f0ed1f65SJerome Glisse if (radeon_gpu_reset(rdev)) { 250f0ed1f65SJerome Glisse dev_warn(rdev->dev, 251f0ed1f65SJerome Glisse "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 252f0ed1f65SJerome Glisse RREG32(R_000E40_RBBM_STATUS), 253f0ed1f65SJerome Glisse RREG32(R_0007C0_CP_STAT)); 254f0ed1f65SJerome Glisse } 255f0ed1f65SJerome Glisse /* check if cards are posted or not */ 25672542d77SDave Airlie if (radeon_boot_test_post_card(rdev) == false) 25772542d77SDave Airlie return -EINVAL; 25872542d77SDave Airlie 259f0ed1f65SJerome Glisse if (!radeon_card_posted(rdev) && rdev->bios) { 260f0ed1f65SJerome Glisse DRM_INFO("GPU not posted. posting now...\n"); 261f0ed1f65SJerome Glisse atom_asic_init(rdev->mode_info.atom_context); 262f0ed1f65SJerome Glisse } 263f0ed1f65SJerome Glisse /* Initialize clocks */ 264f0ed1f65SJerome Glisse radeon_get_clock_info(rdev->ddev); 2657433874eSRafał Miłecki /* Initialize power management */ 2667433874eSRafał Miłecki radeon_pm_init(rdev); 267d594e46aSJerome Glisse /* initialize AGP */ 268d594e46aSJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 269d594e46aSJerome Glisse r = radeon_agp_init(rdev); 270d594e46aSJerome Glisse if (r) { 271d594e46aSJerome Glisse radeon_agp_disable(rdev); 272d594e46aSJerome Glisse } 273d594e46aSJerome Glisse } 274d594e46aSJerome Glisse /* initialize memory controller */ 275d594e46aSJerome Glisse r520_mc_init(rdev); 276f0ed1f65SJerome Glisse rv515_debugfs(rdev); 277f0ed1f65SJerome Glisse /* Fence driver */ 278f0ed1f65SJerome Glisse r = radeon_fence_driver_init(rdev); 279f0ed1f65SJerome Glisse if (r) 280f0ed1f65SJerome Glisse return r; 281f0ed1f65SJerome Glisse r = radeon_irq_kms_init(rdev); 282f0ed1f65SJerome Glisse if (r) 283f0ed1f65SJerome Glisse return r; 284f0ed1f65SJerome Glisse /* Memory manager */ 2854c788679SJerome Glisse r = radeon_bo_init(rdev); 286f0ed1f65SJerome Glisse if (r) 287f0ed1f65SJerome Glisse return r; 288f0ed1f65SJerome Glisse r = rv370_pcie_gart_init(rdev); 289f0ed1f65SJerome Glisse if (r) 290f0ed1f65SJerome Glisse return r; 291d39c3b89SJerome Glisse rv515_set_safe_registers(rdev); 292f0ed1f65SJerome Glisse rdev->accel_working = true; 293f0ed1f65SJerome Glisse r = r520_startup(rdev); 294f0ed1f65SJerome Glisse if (r) { 295f0ed1f65SJerome Glisse /* Somethings want wront with the accel init stop accel */ 296f0ed1f65SJerome Glisse dev_err(rdev->dev, "Disabling GPU acceleration\n"); 297f0ed1f65SJerome Glisse r100_cp_fini(rdev); 298f0ed1f65SJerome Glisse r100_wb_fini(rdev); 299f0ed1f65SJerome Glisse r100_ib_fini(rdev); 300655efd3dSJerome Glisse radeon_irq_kms_fini(rdev); 301f0ed1f65SJerome Glisse rv370_pcie_gart_fini(rdev); 302f0ed1f65SJerome Glisse radeon_agp_fini(rdev); 303f0ed1f65SJerome Glisse rdev->accel_working = false; 304f0ed1f65SJerome Glisse } 305d39c3b89SJerome Glisse return 0; 306d39c3b89SJerome Glisse } 307