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