1926deccbSFrançois Tigeot /* 2926deccbSFrançois Tigeot * Copyright 2008 Advanced Micro Devices, Inc. 3926deccbSFrançois Tigeot * Copyright 2008 Red Hat Inc. 4926deccbSFrançois Tigeot * Copyright 2009 Jerome Glisse. 5926deccbSFrançois Tigeot * 6926deccbSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 7926deccbSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 8926deccbSFrançois Tigeot * to deal in the Software without restriction, including without limitation 9926deccbSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10926deccbSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 11926deccbSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 12926deccbSFrançois Tigeot * 13926deccbSFrançois Tigeot * The above copyright notice and this permission notice shall be included in 14926deccbSFrançois Tigeot * all copies or substantial portions of the Software. 15926deccbSFrançois Tigeot * 16926deccbSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17926deccbSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18926deccbSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19926deccbSFrançois Tigeot * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20926deccbSFrançois Tigeot * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21926deccbSFrançois Tigeot * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22926deccbSFrançois Tigeot * OTHER DEALINGS IN THE SOFTWARE. 23926deccbSFrançois Tigeot * 24926deccbSFrançois Tigeot * Authors: Dave Airlie 25926deccbSFrançois Tigeot * Alex Deucher 26926deccbSFrançois Tigeot * Jerome Glisse 27926deccbSFrançois Tigeot * 28926deccbSFrançois Tigeot * $FreeBSD: head/sys/dev/drm2/radeon/rv770.c 254885 2013-08-25 19:37:15Z dumbbell $ 29926deccbSFrançois Tigeot */ 30926deccbSFrançois Tigeot 31926deccbSFrançois Tigeot #include <drm/drmP.h> 32926deccbSFrançois Tigeot #include "radeon.h" 33926deccbSFrançois Tigeot #include "radeon_asic.h" 34926deccbSFrançois Tigeot #include <uapi_drm/radeon_drm.h> 35926deccbSFrançois Tigeot #include "rv770d.h" 36926deccbSFrançois Tigeot #include "atom.h" 37926deccbSFrançois Tigeot #include "avivod.h" 38926deccbSFrançois Tigeot 39926deccbSFrançois Tigeot #define R700_PFP_UCODE_SIZE 848 40926deccbSFrançois Tigeot #define R700_PM4_UCODE_SIZE 1360 41926deccbSFrançois Tigeot 42926deccbSFrançois Tigeot static void rv770_gpu_init(struct radeon_device *rdev); 43926deccbSFrançois Tigeot static void rv770_pcie_gen2_enable(struct radeon_device *rdev); 44926deccbSFrançois Tigeot 45*b403bed8SMichael Neumann #define PCIE_BUS_CLK 10000 46*b403bed8SMichael Neumann #define TCLK (PCIE_BUS_CLK / 10) 47*b403bed8SMichael Neumann 48*b403bed8SMichael Neumann /** 49*b403bed8SMichael Neumann * rv770_get_xclk - get the xclk 50*b403bed8SMichael Neumann * 51*b403bed8SMichael Neumann * @rdev: radeon_device pointer 52*b403bed8SMichael Neumann * 53*b403bed8SMichael Neumann * Returns the reference clock used by the gfx engine 54*b403bed8SMichael Neumann * (r7xx-cayman). 55*b403bed8SMichael Neumann */ 56*b403bed8SMichael Neumann u32 rv770_get_xclk(struct radeon_device *rdev) 57*b403bed8SMichael Neumann { 58*b403bed8SMichael Neumann u32 reference_clock = rdev->clock.spll.reference_freq; 59*b403bed8SMichael Neumann u32 tmp = RREG32(CG_CLKPIN_CNTL); 60*b403bed8SMichael Neumann 61*b403bed8SMichael Neumann if (tmp & MUX_TCLK_TO_XCLK) 62*b403bed8SMichael Neumann return TCLK; 63*b403bed8SMichael Neumann 64*b403bed8SMichael Neumann if (tmp & XTALIN_DIVIDE) 65*b403bed8SMichael Neumann return reference_clock / 4; 66*b403bed8SMichael Neumann 67*b403bed8SMichael Neumann return reference_clock; 68*b403bed8SMichael Neumann } 69*b403bed8SMichael Neumann 70926deccbSFrançois Tigeot u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) 71926deccbSFrançois Tigeot { 72926deccbSFrançois Tigeot struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 73926deccbSFrançois Tigeot u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); 74926deccbSFrançois Tigeot int i; 75926deccbSFrançois Tigeot 76926deccbSFrançois Tigeot /* Lock the graphics update lock */ 77926deccbSFrançois Tigeot tmp |= AVIVO_D1GRPH_UPDATE_LOCK; 78926deccbSFrançois Tigeot WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); 79926deccbSFrançois Tigeot 80926deccbSFrançois Tigeot /* update the scanout addresses */ 81926deccbSFrançois Tigeot if (radeon_crtc->crtc_id) { 82926deccbSFrançois Tigeot WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); 83926deccbSFrançois Tigeot WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); 84926deccbSFrançois Tigeot } else { 85926deccbSFrançois Tigeot WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); 86926deccbSFrançois Tigeot WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); 87926deccbSFrançois Tigeot } 88926deccbSFrançois Tigeot WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 89926deccbSFrançois Tigeot (u32)crtc_base); 90926deccbSFrançois Tigeot WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 91926deccbSFrançois Tigeot (u32)crtc_base); 92926deccbSFrançois Tigeot 93926deccbSFrançois Tigeot /* Wait for update_pending to go high. */ 94926deccbSFrançois Tigeot for (i = 0; i < rdev->usec_timeout; i++) { 95926deccbSFrançois Tigeot if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) 96926deccbSFrançois Tigeot break; 97926deccbSFrançois Tigeot DRM_UDELAY(1); 98926deccbSFrançois Tigeot } 99926deccbSFrançois Tigeot DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); 100926deccbSFrançois Tigeot 101926deccbSFrançois Tigeot /* Unlock the lock, so double-buffering can take place inside vblank */ 102926deccbSFrançois Tigeot tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; 103926deccbSFrançois Tigeot WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); 104926deccbSFrançois Tigeot 105926deccbSFrançois Tigeot /* Return current update_pending status: */ 106926deccbSFrançois Tigeot return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; 107926deccbSFrançois Tigeot } 108926deccbSFrançois Tigeot 109926deccbSFrançois Tigeot /* get temperature in millidegrees */ 110926deccbSFrançois Tigeot int rv770_get_temp(struct radeon_device *rdev) 111926deccbSFrançois Tigeot { 112926deccbSFrançois Tigeot u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> 113926deccbSFrançois Tigeot ASIC_T_SHIFT; 114926deccbSFrançois Tigeot int actual_temp; 115926deccbSFrançois Tigeot 116926deccbSFrançois Tigeot if (temp & 0x400) 117926deccbSFrançois Tigeot actual_temp = -256; 118926deccbSFrançois Tigeot else if (temp & 0x200) 119926deccbSFrançois Tigeot actual_temp = 255; 120926deccbSFrançois Tigeot else if (temp & 0x100) { 121926deccbSFrançois Tigeot actual_temp = temp & 0x1ff; 122926deccbSFrançois Tigeot actual_temp |= ~0x1ff; 123926deccbSFrançois Tigeot } else 124926deccbSFrançois Tigeot actual_temp = temp & 0xff; 125926deccbSFrançois Tigeot 126926deccbSFrançois Tigeot return (actual_temp * 1000) / 2; 127926deccbSFrançois Tigeot } 128926deccbSFrançois Tigeot 129926deccbSFrançois Tigeot void rv770_pm_misc(struct radeon_device *rdev) 130926deccbSFrançois Tigeot { 131926deccbSFrançois Tigeot int req_ps_idx = rdev->pm.requested_power_state_index; 132926deccbSFrançois Tigeot int req_cm_idx = rdev->pm.requested_clock_mode_index; 133926deccbSFrançois Tigeot struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; 134926deccbSFrançois Tigeot struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; 135926deccbSFrançois Tigeot 136926deccbSFrançois Tigeot if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { 137926deccbSFrançois Tigeot /* 0xff01 is a flag rather then an actual voltage */ 138926deccbSFrançois Tigeot if (voltage->voltage == 0xff01) 139926deccbSFrançois Tigeot return; 140926deccbSFrançois Tigeot if (voltage->voltage != rdev->pm.current_vddc) { 141926deccbSFrançois Tigeot radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); 142926deccbSFrançois Tigeot rdev->pm.current_vddc = voltage->voltage; 143926deccbSFrançois Tigeot DRM_DEBUG("Setting: v: %d\n", voltage->voltage); 144926deccbSFrançois Tigeot } 145926deccbSFrançois Tigeot } 146926deccbSFrançois Tigeot } 147926deccbSFrançois Tigeot 148926deccbSFrançois Tigeot /* 149926deccbSFrançois Tigeot * GART 150926deccbSFrançois Tigeot */ 151926deccbSFrançois Tigeot static int rv770_pcie_gart_enable(struct radeon_device *rdev) 152926deccbSFrançois Tigeot { 153926deccbSFrançois Tigeot u32 tmp; 154926deccbSFrançois Tigeot int r, i; 155926deccbSFrançois Tigeot 156926deccbSFrançois Tigeot if (rdev->gart.robj == NULL) { 157926deccbSFrançois Tigeot dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); 158926deccbSFrançois Tigeot return -EINVAL; 159926deccbSFrançois Tigeot } 160926deccbSFrançois Tigeot r = radeon_gart_table_vram_pin(rdev); 161926deccbSFrançois Tigeot if (r) 162926deccbSFrançois Tigeot return r; 163926deccbSFrançois Tigeot radeon_gart_restore(rdev); 164926deccbSFrançois Tigeot /* Setup L2 cache */ 165926deccbSFrançois Tigeot WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | 166926deccbSFrançois Tigeot ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | 167926deccbSFrançois Tigeot EFFECTIVE_L2_QUEUE_SIZE(7)); 168926deccbSFrançois Tigeot WREG32(VM_L2_CNTL2, 0); 169926deccbSFrançois Tigeot WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); 170926deccbSFrançois Tigeot /* Setup TLB control */ 171926deccbSFrançois Tigeot tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | 172926deccbSFrançois Tigeot SYSTEM_ACCESS_MODE_NOT_IN_SYS | 173926deccbSFrançois Tigeot SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | 174926deccbSFrançois Tigeot EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); 175926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); 176926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); 177926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); 178926deccbSFrançois Tigeot if (rdev->family == CHIP_RV740) 179926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); 180926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); 181926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); 182926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); 183926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); 184926deccbSFrançois Tigeot WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); 185926deccbSFrançois Tigeot WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); 186926deccbSFrançois Tigeot WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); 187926deccbSFrançois Tigeot WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | 188926deccbSFrançois Tigeot RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); 189926deccbSFrançois Tigeot WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, 190926deccbSFrançois Tigeot (u32)(rdev->dummy_page.addr >> 12)); 191926deccbSFrançois Tigeot for (i = 1; i < 7; i++) 192926deccbSFrançois Tigeot WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 193926deccbSFrançois Tigeot 194926deccbSFrançois Tigeot r600_pcie_gart_tlb_flush(rdev); 195926deccbSFrançois Tigeot DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", 196926deccbSFrançois Tigeot (unsigned)(rdev->mc.gtt_size >> 20), 197926deccbSFrançois Tigeot (unsigned long long)rdev->gart.table_addr); 198926deccbSFrançois Tigeot rdev->gart.ready = true; 199926deccbSFrançois Tigeot return 0; 200926deccbSFrançois Tigeot } 201926deccbSFrançois Tigeot 202926deccbSFrançois Tigeot static void rv770_pcie_gart_disable(struct radeon_device *rdev) 203926deccbSFrançois Tigeot { 204926deccbSFrançois Tigeot u32 tmp; 205926deccbSFrançois Tigeot int i; 206926deccbSFrançois Tigeot 207926deccbSFrançois Tigeot /* Disable all tables */ 208926deccbSFrançois Tigeot for (i = 0; i < 7; i++) 209926deccbSFrançois Tigeot WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 210926deccbSFrançois Tigeot 211926deccbSFrançois Tigeot /* Setup L2 cache */ 212926deccbSFrançois Tigeot WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING | 213926deccbSFrançois Tigeot EFFECTIVE_L2_QUEUE_SIZE(7)); 214926deccbSFrançois Tigeot WREG32(VM_L2_CNTL2, 0); 215926deccbSFrançois Tigeot WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); 216926deccbSFrançois Tigeot /* Setup TLB control */ 217926deccbSFrançois Tigeot tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); 218926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); 219926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); 220926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); 221926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); 222926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); 223926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); 224926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); 225926deccbSFrançois Tigeot radeon_gart_table_vram_unpin(rdev); 226926deccbSFrançois Tigeot } 227926deccbSFrançois Tigeot 228926deccbSFrançois Tigeot static void rv770_pcie_gart_fini(struct radeon_device *rdev) 229926deccbSFrançois Tigeot { 230926deccbSFrançois Tigeot radeon_gart_fini(rdev); 231926deccbSFrançois Tigeot rv770_pcie_gart_disable(rdev); 232926deccbSFrançois Tigeot radeon_gart_table_vram_free(rdev); 233926deccbSFrançois Tigeot } 234926deccbSFrançois Tigeot 235926deccbSFrançois Tigeot 236926deccbSFrançois Tigeot static void rv770_agp_enable(struct radeon_device *rdev) 237926deccbSFrançois Tigeot { 238926deccbSFrançois Tigeot u32 tmp; 239926deccbSFrançois Tigeot int i; 240926deccbSFrançois Tigeot 241926deccbSFrançois Tigeot /* Setup L2 cache */ 242926deccbSFrançois Tigeot WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | 243926deccbSFrançois Tigeot ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | 244926deccbSFrançois Tigeot EFFECTIVE_L2_QUEUE_SIZE(7)); 245926deccbSFrançois Tigeot WREG32(VM_L2_CNTL2, 0); 246926deccbSFrançois Tigeot WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); 247926deccbSFrançois Tigeot /* Setup TLB control */ 248926deccbSFrançois Tigeot tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | 249926deccbSFrançois Tigeot SYSTEM_ACCESS_MODE_NOT_IN_SYS | 250926deccbSFrançois Tigeot SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | 251926deccbSFrançois Tigeot EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); 252926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); 253926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); 254926deccbSFrançois Tigeot WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); 255926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); 256926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); 257926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); 258926deccbSFrançois Tigeot WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); 259926deccbSFrançois Tigeot for (i = 0; i < 7; i++) 260926deccbSFrançois Tigeot WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 261926deccbSFrançois Tigeot } 262926deccbSFrançois Tigeot 263926deccbSFrançois Tigeot static void rv770_mc_program(struct radeon_device *rdev) 264926deccbSFrançois Tigeot { 265926deccbSFrançois Tigeot struct rv515_mc_save save; 266926deccbSFrançois Tigeot u32 tmp; 267926deccbSFrançois Tigeot int i, j; 268926deccbSFrançois Tigeot 269926deccbSFrançois Tigeot /* Initialize HDP */ 270926deccbSFrançois Tigeot for (i = 0, j = 0; i < 32; i++, j += 0x18) { 271926deccbSFrançois Tigeot WREG32((0x2c14 + j), 0x00000000); 272926deccbSFrançois Tigeot WREG32((0x2c18 + j), 0x00000000); 273926deccbSFrançois Tigeot WREG32((0x2c1c + j), 0x00000000); 274926deccbSFrançois Tigeot WREG32((0x2c20 + j), 0x00000000); 275926deccbSFrançois Tigeot WREG32((0x2c24 + j), 0x00000000); 276926deccbSFrançois Tigeot } 277926deccbSFrançois Tigeot /* r7xx hw bug. Read from HDP_DEBUG1 rather 278926deccbSFrançois Tigeot * than writing to HDP_REG_COHERENCY_FLUSH_CNTL 279926deccbSFrançois Tigeot */ 280926deccbSFrançois Tigeot tmp = RREG32(HDP_DEBUG1); 281926deccbSFrançois Tigeot 282926deccbSFrançois Tigeot rv515_mc_stop(rdev, &save); 283926deccbSFrançois Tigeot if (r600_mc_wait_for_idle(rdev)) { 284926deccbSFrançois Tigeot dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 285926deccbSFrançois Tigeot } 286926deccbSFrançois Tigeot /* Lockout access through VGA aperture*/ 287926deccbSFrançois Tigeot WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); 288926deccbSFrançois Tigeot /* Update configuration */ 289926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_AGP) { 290926deccbSFrançois Tigeot if (rdev->mc.vram_start < rdev->mc.gtt_start) { 291926deccbSFrançois Tigeot /* VRAM before AGP */ 292926deccbSFrançois Tigeot WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, 293926deccbSFrançois Tigeot rdev->mc.vram_start >> 12); 294926deccbSFrançois Tigeot WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 295926deccbSFrançois Tigeot rdev->mc.gtt_end >> 12); 296926deccbSFrançois Tigeot } else { 297926deccbSFrançois Tigeot /* VRAM after AGP */ 298926deccbSFrançois Tigeot WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, 299926deccbSFrançois Tigeot rdev->mc.gtt_start >> 12); 300926deccbSFrançois Tigeot WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 301926deccbSFrançois Tigeot rdev->mc.vram_end >> 12); 302926deccbSFrançois Tigeot } 303926deccbSFrançois Tigeot } else { 304926deccbSFrançois Tigeot WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, 305926deccbSFrançois Tigeot rdev->mc.vram_start >> 12); 306926deccbSFrançois Tigeot WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 307926deccbSFrançois Tigeot rdev->mc.vram_end >> 12); 308926deccbSFrançois Tigeot } 309926deccbSFrançois Tigeot WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); 310926deccbSFrançois Tigeot tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; 311926deccbSFrançois Tigeot tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); 312926deccbSFrançois Tigeot WREG32(MC_VM_FB_LOCATION, tmp); 313926deccbSFrançois Tigeot WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); 314926deccbSFrançois Tigeot WREG32(HDP_NONSURFACE_INFO, (2 << 7)); 315926deccbSFrançois Tigeot WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); 316926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_AGP) { 317926deccbSFrançois Tigeot WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16); 318926deccbSFrançois Tigeot WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16); 319926deccbSFrançois Tigeot WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22); 320926deccbSFrançois Tigeot } else { 321926deccbSFrançois Tigeot WREG32(MC_VM_AGP_BASE, 0); 322926deccbSFrançois Tigeot WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); 323926deccbSFrançois Tigeot WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); 324926deccbSFrançois Tigeot } 325926deccbSFrançois Tigeot if (r600_mc_wait_for_idle(rdev)) { 326926deccbSFrançois Tigeot dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 327926deccbSFrançois Tigeot } 328926deccbSFrançois Tigeot rv515_mc_resume(rdev, &save); 329926deccbSFrançois Tigeot /* we need to own VRAM, so turn off the VGA renderer here 330926deccbSFrançois Tigeot * to stop it overwriting our objects */ 331926deccbSFrançois Tigeot rv515_vga_render_disable(rdev); 332926deccbSFrançois Tigeot } 333926deccbSFrançois Tigeot 334926deccbSFrançois Tigeot 335926deccbSFrançois Tigeot /* 336926deccbSFrançois Tigeot * CP. 337926deccbSFrançois Tigeot */ 338926deccbSFrançois Tigeot void r700_cp_stop(struct radeon_device *rdev) 339926deccbSFrançois Tigeot { 340926deccbSFrançois Tigeot radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); 341926deccbSFrançois Tigeot WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); 342926deccbSFrançois Tigeot WREG32(SCRATCH_UMSK, 0); 343926deccbSFrançois Tigeot rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; 344926deccbSFrançois Tigeot } 345926deccbSFrançois Tigeot 346926deccbSFrançois Tigeot static int rv770_cp_load_microcode(struct radeon_device *rdev) 347926deccbSFrançois Tigeot { 348926deccbSFrançois Tigeot const __be32 *fw_data; 349926deccbSFrançois Tigeot int i; 350926deccbSFrançois Tigeot 351926deccbSFrançois Tigeot if (!rdev->me_fw || !rdev->pfp_fw) 352926deccbSFrançois Tigeot return -EINVAL; 353926deccbSFrançois Tigeot 354926deccbSFrançois Tigeot r700_cp_stop(rdev); 355926deccbSFrançois Tigeot WREG32(CP_RB_CNTL, 356926deccbSFrançois Tigeot #ifdef __BIG_ENDIAN 357926deccbSFrançois Tigeot BUF_SWAP_32BIT | 358926deccbSFrançois Tigeot #endif 359926deccbSFrançois Tigeot RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3)); 360926deccbSFrançois Tigeot 361926deccbSFrançois Tigeot /* Reset cp */ 362926deccbSFrançois Tigeot WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); 363926deccbSFrançois Tigeot RREG32(GRBM_SOFT_RESET); 364926deccbSFrançois Tigeot DRM_MDELAY(15); 365926deccbSFrançois Tigeot WREG32(GRBM_SOFT_RESET, 0); 366926deccbSFrançois Tigeot 367926deccbSFrançois Tigeot fw_data = (const __be32 *)rdev->pfp_fw->data; 368926deccbSFrançois Tigeot WREG32(CP_PFP_UCODE_ADDR, 0); 369926deccbSFrançois Tigeot for (i = 0; i < R700_PFP_UCODE_SIZE; i++) 370926deccbSFrançois Tigeot WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); 371926deccbSFrançois Tigeot WREG32(CP_PFP_UCODE_ADDR, 0); 372926deccbSFrançois Tigeot 373926deccbSFrançois Tigeot fw_data = (const __be32 *)rdev->me_fw->data; 374926deccbSFrançois Tigeot WREG32(CP_ME_RAM_WADDR, 0); 375926deccbSFrançois Tigeot for (i = 0; i < R700_PM4_UCODE_SIZE; i++) 376926deccbSFrançois Tigeot WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); 377926deccbSFrançois Tigeot 378926deccbSFrançois Tigeot WREG32(CP_PFP_UCODE_ADDR, 0); 379926deccbSFrançois Tigeot WREG32(CP_ME_RAM_WADDR, 0); 380926deccbSFrançois Tigeot WREG32(CP_ME_RAM_RADDR, 0); 381926deccbSFrançois Tigeot return 0; 382926deccbSFrançois Tigeot } 383926deccbSFrançois Tigeot 384926deccbSFrançois Tigeot void r700_cp_fini(struct radeon_device *rdev) 385926deccbSFrançois Tigeot { 386926deccbSFrançois Tigeot struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 387926deccbSFrançois Tigeot r700_cp_stop(rdev); 388926deccbSFrançois Tigeot radeon_ring_fini(rdev, ring); 389926deccbSFrançois Tigeot radeon_scratch_free(rdev, ring->rptr_save_reg); 390926deccbSFrançois Tigeot } 391926deccbSFrançois Tigeot 392926deccbSFrançois Tigeot /* 393926deccbSFrançois Tigeot * Core functions 394926deccbSFrançois Tigeot */ 395926deccbSFrançois Tigeot static void rv770_gpu_init(struct radeon_device *rdev) 396926deccbSFrançois Tigeot { 397926deccbSFrançois Tigeot int i, j, num_qd_pipes; 398926deccbSFrançois Tigeot u32 ta_aux_cntl; 399926deccbSFrançois Tigeot u32 sx_debug_1; 400926deccbSFrançois Tigeot u32 smx_dc_ctl0; 401926deccbSFrançois Tigeot u32 db_debug3; 402926deccbSFrançois Tigeot u32 num_gs_verts_per_thread; 403926deccbSFrançois Tigeot u32 vgt_gs_per_es; 404926deccbSFrançois Tigeot u32 gs_prim_buffer_depth = 0; 405926deccbSFrançois Tigeot u32 sq_ms_fifo_sizes; 406926deccbSFrançois Tigeot u32 sq_config; 407926deccbSFrançois Tigeot u32 sq_thread_resource_mgmt; 408926deccbSFrançois Tigeot u32 hdp_host_path_cntl; 409926deccbSFrançois Tigeot u32 sq_dyn_gpr_size_simd_ab_0; 410926deccbSFrançois Tigeot u32 gb_tiling_config = 0; 411926deccbSFrançois Tigeot u32 cc_rb_backend_disable = 0; 412926deccbSFrançois Tigeot u32 cc_gc_shader_pipe_config = 0; 413926deccbSFrançois Tigeot u32 mc_arb_ramcfg; 414926deccbSFrançois Tigeot u32 db_debug4, tmp; 415926deccbSFrançois Tigeot u32 inactive_pipes, shader_pipe_config; 416926deccbSFrançois Tigeot u32 disabled_rb_mask; 417926deccbSFrançois Tigeot unsigned active_number; 418926deccbSFrançois Tigeot 419926deccbSFrançois Tigeot /* setup chip specs */ 420926deccbSFrançois Tigeot rdev->config.rv770.tiling_group_size = 256; 421926deccbSFrançois Tigeot switch (rdev->family) { 422926deccbSFrançois Tigeot case CHIP_RV770: 423926deccbSFrançois Tigeot rdev->config.rv770.max_pipes = 4; 424926deccbSFrançois Tigeot rdev->config.rv770.max_tile_pipes = 8; 425926deccbSFrançois Tigeot rdev->config.rv770.max_simds = 10; 426926deccbSFrançois Tigeot rdev->config.rv770.max_backends = 4; 427926deccbSFrançois Tigeot rdev->config.rv770.max_gprs = 256; 428926deccbSFrançois Tigeot rdev->config.rv770.max_threads = 248; 429926deccbSFrançois Tigeot rdev->config.rv770.max_stack_entries = 512; 430926deccbSFrançois Tigeot rdev->config.rv770.max_hw_contexts = 8; 431926deccbSFrançois Tigeot rdev->config.rv770.max_gs_threads = 16 * 2; 432926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_size = 128; 433926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_pos_size = 16; 434926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_smx_size = 112; 435926deccbSFrançois Tigeot rdev->config.rv770.sq_num_cf_insts = 2; 436926deccbSFrançois Tigeot 437926deccbSFrançois Tigeot rdev->config.rv770.sx_num_of_sets = 7; 438926deccbSFrançois Tigeot rdev->config.rv770.sc_prim_fifo_size = 0xF9; 439926deccbSFrançois Tigeot rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30; 440926deccbSFrançois Tigeot rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130; 441926deccbSFrançois Tigeot break; 442926deccbSFrançois Tigeot case CHIP_RV730: 443926deccbSFrançois Tigeot rdev->config.rv770.max_pipes = 2; 444926deccbSFrançois Tigeot rdev->config.rv770.max_tile_pipes = 4; 445926deccbSFrançois Tigeot rdev->config.rv770.max_simds = 8; 446926deccbSFrançois Tigeot rdev->config.rv770.max_backends = 2; 447926deccbSFrançois Tigeot rdev->config.rv770.max_gprs = 128; 448926deccbSFrançois Tigeot rdev->config.rv770.max_threads = 248; 449926deccbSFrançois Tigeot rdev->config.rv770.max_stack_entries = 256; 450926deccbSFrançois Tigeot rdev->config.rv770.max_hw_contexts = 8; 451926deccbSFrançois Tigeot rdev->config.rv770.max_gs_threads = 16 * 2; 452926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_size = 256; 453926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_pos_size = 32; 454926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_smx_size = 224; 455926deccbSFrançois Tigeot rdev->config.rv770.sq_num_cf_insts = 2; 456926deccbSFrançois Tigeot 457926deccbSFrançois Tigeot rdev->config.rv770.sx_num_of_sets = 7; 458926deccbSFrançois Tigeot rdev->config.rv770.sc_prim_fifo_size = 0xf9; 459926deccbSFrançois Tigeot rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30; 460926deccbSFrançois Tigeot rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130; 461926deccbSFrançois Tigeot if (rdev->config.rv770.sx_max_export_pos_size > 16) { 462926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_pos_size -= 16; 463926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_smx_size += 16; 464926deccbSFrançois Tigeot } 465926deccbSFrançois Tigeot break; 466926deccbSFrançois Tigeot case CHIP_RV710: 467926deccbSFrançois Tigeot rdev->config.rv770.max_pipes = 2; 468926deccbSFrançois Tigeot rdev->config.rv770.max_tile_pipes = 2; 469926deccbSFrançois Tigeot rdev->config.rv770.max_simds = 2; 470926deccbSFrançois Tigeot rdev->config.rv770.max_backends = 1; 471926deccbSFrançois Tigeot rdev->config.rv770.max_gprs = 256; 472926deccbSFrançois Tigeot rdev->config.rv770.max_threads = 192; 473926deccbSFrançois Tigeot rdev->config.rv770.max_stack_entries = 256; 474926deccbSFrançois Tigeot rdev->config.rv770.max_hw_contexts = 4; 475926deccbSFrançois Tigeot rdev->config.rv770.max_gs_threads = 8 * 2; 476926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_size = 128; 477926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_pos_size = 16; 478926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_smx_size = 112; 479926deccbSFrançois Tigeot rdev->config.rv770.sq_num_cf_insts = 1; 480926deccbSFrançois Tigeot 481926deccbSFrançois Tigeot rdev->config.rv770.sx_num_of_sets = 7; 482926deccbSFrançois Tigeot rdev->config.rv770.sc_prim_fifo_size = 0x40; 483926deccbSFrançois Tigeot rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30; 484926deccbSFrançois Tigeot rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130; 485926deccbSFrançois Tigeot break; 486926deccbSFrançois Tigeot case CHIP_RV740: 487926deccbSFrançois Tigeot rdev->config.rv770.max_pipes = 4; 488926deccbSFrançois Tigeot rdev->config.rv770.max_tile_pipes = 4; 489926deccbSFrançois Tigeot rdev->config.rv770.max_simds = 8; 490926deccbSFrançois Tigeot rdev->config.rv770.max_backends = 4; 491926deccbSFrançois Tigeot rdev->config.rv770.max_gprs = 256; 492926deccbSFrançois Tigeot rdev->config.rv770.max_threads = 248; 493926deccbSFrançois Tigeot rdev->config.rv770.max_stack_entries = 512; 494926deccbSFrançois Tigeot rdev->config.rv770.max_hw_contexts = 8; 495926deccbSFrançois Tigeot rdev->config.rv770.max_gs_threads = 16 * 2; 496926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_size = 256; 497926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_pos_size = 32; 498926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_smx_size = 224; 499926deccbSFrançois Tigeot rdev->config.rv770.sq_num_cf_insts = 2; 500926deccbSFrançois Tigeot 501926deccbSFrançois Tigeot rdev->config.rv770.sx_num_of_sets = 7; 502926deccbSFrançois Tigeot rdev->config.rv770.sc_prim_fifo_size = 0x100; 503926deccbSFrançois Tigeot rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30; 504926deccbSFrançois Tigeot rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130; 505926deccbSFrançois Tigeot 506926deccbSFrançois Tigeot if (rdev->config.rv770.sx_max_export_pos_size > 16) { 507926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_pos_size -= 16; 508926deccbSFrançois Tigeot rdev->config.rv770.sx_max_export_smx_size += 16; 509926deccbSFrançois Tigeot } 510926deccbSFrançois Tigeot break; 511926deccbSFrançois Tigeot default: 512926deccbSFrançois Tigeot break; 513926deccbSFrançois Tigeot } 514926deccbSFrançois Tigeot 515926deccbSFrançois Tigeot /* Initialize HDP */ 516926deccbSFrançois Tigeot j = 0; 517926deccbSFrançois Tigeot for (i = 0; i < 32; i++) { 518926deccbSFrançois Tigeot WREG32((0x2c14 + j), 0x00000000); 519926deccbSFrançois Tigeot WREG32((0x2c18 + j), 0x00000000); 520926deccbSFrançois Tigeot WREG32((0x2c1c + j), 0x00000000); 521926deccbSFrançois Tigeot WREG32((0x2c20 + j), 0x00000000); 522926deccbSFrançois Tigeot WREG32((0x2c24 + j), 0x00000000); 523926deccbSFrançois Tigeot j += 0x18; 524926deccbSFrançois Tigeot } 525926deccbSFrançois Tigeot 526926deccbSFrançois Tigeot WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); 527926deccbSFrançois Tigeot 528926deccbSFrançois Tigeot /* setup tiling, simd, pipe config */ 529926deccbSFrançois Tigeot mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); 530926deccbSFrançois Tigeot 531926deccbSFrançois Tigeot shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); 532926deccbSFrançois Tigeot inactive_pipes = (shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; 533926deccbSFrançois Tigeot for (i = 0, tmp = 1, active_number = 0; i < R7XX_MAX_PIPES; i++) { 534926deccbSFrançois Tigeot if (!(inactive_pipes & tmp)) { 535926deccbSFrançois Tigeot active_number++; 536926deccbSFrançois Tigeot } 537926deccbSFrançois Tigeot tmp <<= 1; 538926deccbSFrançois Tigeot } 539926deccbSFrançois Tigeot if (active_number == 1) { 540926deccbSFrançois Tigeot WREG32(SPI_CONFIG_CNTL, DISABLE_INTERP_1); 541926deccbSFrançois Tigeot } else { 542926deccbSFrançois Tigeot WREG32(SPI_CONFIG_CNTL, 0); 543926deccbSFrançois Tigeot } 544926deccbSFrançois Tigeot 545926deccbSFrançois Tigeot cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; 546926deccbSFrançois Tigeot tmp = R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_rb_backend_disable >> 16); 547926deccbSFrançois Tigeot if (tmp < rdev->config.rv770.max_backends) { 548926deccbSFrançois Tigeot rdev->config.rv770.max_backends = tmp; 549926deccbSFrançois Tigeot } 550926deccbSFrançois Tigeot 551926deccbSFrançois Tigeot cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; 552926deccbSFrançois Tigeot tmp = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R7XX_MAX_PIPES_MASK); 553926deccbSFrançois Tigeot if (tmp < rdev->config.rv770.max_pipes) { 554926deccbSFrançois Tigeot rdev->config.rv770.max_pipes = tmp; 555926deccbSFrançois Tigeot } 556926deccbSFrançois Tigeot tmp = R7XX_MAX_SIMDS - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK); 557926deccbSFrançois Tigeot if (tmp < rdev->config.rv770.max_simds) { 558926deccbSFrançois Tigeot rdev->config.rv770.max_simds = tmp; 559926deccbSFrançois Tigeot } 560926deccbSFrançois Tigeot 561926deccbSFrançois Tigeot switch (rdev->config.rv770.max_tile_pipes) { 562926deccbSFrançois Tigeot case 1: 563926deccbSFrançois Tigeot default: 564926deccbSFrançois Tigeot gb_tiling_config = PIPE_TILING(0); 565926deccbSFrançois Tigeot break; 566926deccbSFrançois Tigeot case 2: 567926deccbSFrançois Tigeot gb_tiling_config = PIPE_TILING(1); 568926deccbSFrançois Tigeot break; 569926deccbSFrançois Tigeot case 4: 570926deccbSFrançois Tigeot gb_tiling_config = PIPE_TILING(2); 571926deccbSFrançois Tigeot break; 572926deccbSFrançois Tigeot case 8: 573926deccbSFrançois Tigeot gb_tiling_config = PIPE_TILING(3); 574926deccbSFrançois Tigeot break; 575926deccbSFrançois Tigeot } 576926deccbSFrançois Tigeot rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes; 577926deccbSFrançois Tigeot 578926deccbSFrançois Tigeot disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R7XX_MAX_BACKENDS_MASK; 579926deccbSFrançois Tigeot tmp = (gb_tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; 580926deccbSFrançois Tigeot tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.rv770.max_backends, 581926deccbSFrançois Tigeot R7XX_MAX_BACKENDS, disabled_rb_mask); 582926deccbSFrançois Tigeot gb_tiling_config |= tmp << 16; 583926deccbSFrançois Tigeot rdev->config.rv770.backend_map = tmp; 584926deccbSFrançois Tigeot 585926deccbSFrançois Tigeot if (rdev->family == CHIP_RV770) 586926deccbSFrançois Tigeot gb_tiling_config |= BANK_TILING(1); 587926deccbSFrançois Tigeot else { 588926deccbSFrançois Tigeot if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) 589926deccbSFrançois Tigeot gb_tiling_config |= BANK_TILING(1); 590926deccbSFrançois Tigeot else 591926deccbSFrançois Tigeot gb_tiling_config |= BANK_TILING(0); 592926deccbSFrançois Tigeot } 593926deccbSFrançois Tigeot rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3); 594926deccbSFrançois Tigeot gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); 595926deccbSFrançois Tigeot if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) { 596926deccbSFrançois Tigeot gb_tiling_config |= ROW_TILING(3); 597926deccbSFrançois Tigeot gb_tiling_config |= SAMPLE_SPLIT(3); 598926deccbSFrançois Tigeot } else { 599926deccbSFrançois Tigeot gb_tiling_config |= 600926deccbSFrançois Tigeot ROW_TILING(((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT)); 601926deccbSFrançois Tigeot gb_tiling_config |= 602926deccbSFrançois Tigeot SAMPLE_SPLIT(((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT)); 603926deccbSFrançois Tigeot } 604926deccbSFrançois Tigeot 605926deccbSFrançois Tigeot gb_tiling_config |= BANK_SWAPS(1); 606926deccbSFrançois Tigeot rdev->config.rv770.tile_config = gb_tiling_config; 607926deccbSFrançois Tigeot 608926deccbSFrançois Tigeot WREG32(GB_TILING_CONFIG, gb_tiling_config); 609926deccbSFrançois Tigeot WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); 610926deccbSFrançois Tigeot WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); 611926deccbSFrançois Tigeot WREG32(DMA_TILING_CONFIG, (gb_tiling_config & 0xffff)); 612926deccbSFrançois Tigeot WREG32(DMA_TILING_CONFIG2, (gb_tiling_config & 0xffff)); 613926deccbSFrançois Tigeot 614926deccbSFrançois Tigeot WREG32(CGTS_SYS_TCC_DISABLE, 0); 615926deccbSFrançois Tigeot WREG32(CGTS_TCC_DISABLE, 0); 616926deccbSFrançois Tigeot WREG32(CGTS_USER_SYS_TCC_DISABLE, 0); 617926deccbSFrançois Tigeot WREG32(CGTS_USER_TCC_DISABLE, 0); 618926deccbSFrançois Tigeot 619926deccbSFrançois Tigeot 620926deccbSFrançois Tigeot num_qd_pipes = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); 621926deccbSFrançois Tigeot WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK); 622926deccbSFrançois Tigeot WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK); 623926deccbSFrançois Tigeot 624926deccbSFrançois Tigeot /* set HW defaults for 3D engine */ 625926deccbSFrançois Tigeot WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | 626926deccbSFrançois Tigeot ROQ_IB2_START(0x2b))); 627926deccbSFrançois Tigeot 628926deccbSFrançois Tigeot WREG32(CP_MEQ_THRESHOLDS, STQ_SPLIT(0x30)); 629926deccbSFrançois Tigeot 630926deccbSFrançois Tigeot ta_aux_cntl = RREG32(TA_CNTL_AUX); 631926deccbSFrançois Tigeot WREG32(TA_CNTL_AUX, ta_aux_cntl | DISABLE_CUBE_ANISO); 632926deccbSFrançois Tigeot 633926deccbSFrançois Tigeot sx_debug_1 = RREG32(SX_DEBUG_1); 634926deccbSFrançois Tigeot sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS; 635926deccbSFrançois Tigeot WREG32(SX_DEBUG_1, sx_debug_1); 636926deccbSFrançois Tigeot 637926deccbSFrançois Tigeot smx_dc_ctl0 = RREG32(SMX_DC_CTL0); 638926deccbSFrançois Tigeot smx_dc_ctl0 &= ~CACHE_DEPTH(0x1ff); 639926deccbSFrançois Tigeot smx_dc_ctl0 |= CACHE_DEPTH((rdev->config.rv770.sx_num_of_sets * 64) - 1); 640926deccbSFrançois Tigeot WREG32(SMX_DC_CTL0, smx_dc_ctl0); 641926deccbSFrançois Tigeot 642926deccbSFrançois Tigeot if (rdev->family != CHIP_RV740) 643926deccbSFrançois Tigeot WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) | 644926deccbSFrançois Tigeot GS_FLUSH_CTL(4) | 645926deccbSFrançois Tigeot ACK_FLUSH_CTL(3) | 646926deccbSFrançois Tigeot SYNC_FLUSH_CTL)); 647926deccbSFrançois Tigeot 648926deccbSFrançois Tigeot if (rdev->family != CHIP_RV770) 649926deccbSFrançois Tigeot WREG32(SMX_SAR_CTL0, 0x00003f3f); 650926deccbSFrançois Tigeot 651926deccbSFrançois Tigeot db_debug3 = RREG32(DB_DEBUG3); 652926deccbSFrançois Tigeot db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f); 653926deccbSFrançois Tigeot switch (rdev->family) { 654926deccbSFrançois Tigeot case CHIP_RV770: 655926deccbSFrançois Tigeot case CHIP_RV740: 656926deccbSFrançois Tigeot db_debug3 |= DB_CLK_OFF_DELAY(0x1f); 657926deccbSFrançois Tigeot break; 658926deccbSFrançois Tigeot case CHIP_RV710: 659926deccbSFrançois Tigeot case CHIP_RV730: 660926deccbSFrançois Tigeot default: 661926deccbSFrançois Tigeot db_debug3 |= DB_CLK_OFF_DELAY(2); 662926deccbSFrançois Tigeot break; 663926deccbSFrançois Tigeot } 664926deccbSFrançois Tigeot WREG32(DB_DEBUG3, db_debug3); 665926deccbSFrançois Tigeot 666926deccbSFrançois Tigeot if (rdev->family != CHIP_RV770) { 667926deccbSFrançois Tigeot db_debug4 = RREG32(DB_DEBUG4); 668926deccbSFrançois Tigeot db_debug4 |= DISABLE_TILE_COVERED_FOR_PS_ITER; 669926deccbSFrançois Tigeot WREG32(DB_DEBUG4, db_debug4); 670926deccbSFrançois Tigeot } 671926deccbSFrançois Tigeot 672926deccbSFrançois Tigeot WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.rv770.sx_max_export_size / 4) - 1) | 673926deccbSFrançois Tigeot POSITION_BUFFER_SIZE((rdev->config.rv770.sx_max_export_pos_size / 4) - 1) | 674926deccbSFrançois Tigeot SMX_BUFFER_SIZE((rdev->config.rv770.sx_max_export_smx_size / 4) - 1))); 675926deccbSFrançois Tigeot 676926deccbSFrançois Tigeot WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.rv770.sc_prim_fifo_size) | 677926deccbSFrançois Tigeot SC_HIZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_hiz_tile_fifo_size) | 678926deccbSFrançois Tigeot SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_earlyz_tile_fifo_fize))); 679926deccbSFrançois Tigeot 680926deccbSFrançois Tigeot WREG32(PA_SC_MULTI_CHIP_CNTL, 0); 681926deccbSFrançois Tigeot 682926deccbSFrançois Tigeot WREG32(VGT_NUM_INSTANCES, 1); 683926deccbSFrançois Tigeot 684926deccbSFrançois Tigeot WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4)); 685926deccbSFrançois Tigeot 686926deccbSFrançois Tigeot WREG32(CP_PERFMON_CNTL, 0); 687926deccbSFrançois Tigeot 688926deccbSFrançois Tigeot sq_ms_fifo_sizes = (CACHE_FIFO_SIZE(16 * rdev->config.rv770.sq_num_cf_insts) | 689926deccbSFrançois Tigeot DONE_FIFO_HIWATER(0xe0) | 690926deccbSFrançois Tigeot ALU_UPDATE_FIFO_HIWATER(0x8)); 691926deccbSFrançois Tigeot switch (rdev->family) { 692926deccbSFrançois Tigeot case CHIP_RV770: 693926deccbSFrançois Tigeot case CHIP_RV730: 694926deccbSFrançois Tigeot case CHIP_RV710: 695926deccbSFrançois Tigeot sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1); 696926deccbSFrançois Tigeot break; 697926deccbSFrançois Tigeot case CHIP_RV740: 698926deccbSFrançois Tigeot default: 699926deccbSFrançois Tigeot sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x4); 700926deccbSFrançois Tigeot break; 701926deccbSFrançois Tigeot } 702926deccbSFrançois Tigeot WREG32(SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes); 703926deccbSFrançois Tigeot 704926deccbSFrançois Tigeot /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT 705926deccbSFrançois Tigeot * should be adjusted as needed by the 2D/3D drivers. This just sets default values 706926deccbSFrançois Tigeot */ 707926deccbSFrançois Tigeot sq_config = RREG32(SQ_CONFIG); 708926deccbSFrançois Tigeot sq_config &= ~(PS_PRIO(3) | 709926deccbSFrançois Tigeot VS_PRIO(3) | 710926deccbSFrançois Tigeot GS_PRIO(3) | 711926deccbSFrançois Tigeot ES_PRIO(3)); 712926deccbSFrançois Tigeot sq_config |= (DX9_CONSTS | 713926deccbSFrançois Tigeot VC_ENABLE | 714926deccbSFrançois Tigeot EXPORT_SRC_C | 715926deccbSFrançois Tigeot PS_PRIO(0) | 716926deccbSFrançois Tigeot VS_PRIO(1) | 717926deccbSFrançois Tigeot GS_PRIO(2) | 718926deccbSFrançois Tigeot ES_PRIO(3)); 719926deccbSFrançois Tigeot if (rdev->family == CHIP_RV710) 720926deccbSFrançois Tigeot /* no vertex cache */ 721926deccbSFrançois Tigeot sq_config &= ~VC_ENABLE; 722926deccbSFrançois Tigeot 723926deccbSFrançois Tigeot WREG32(SQ_CONFIG, sq_config); 724926deccbSFrançois Tigeot 725926deccbSFrançois Tigeot WREG32(SQ_GPR_RESOURCE_MGMT_1, (NUM_PS_GPRS((rdev->config.rv770.max_gprs * 24)/64) | 726926deccbSFrançois Tigeot NUM_VS_GPRS((rdev->config.rv770.max_gprs * 24)/64) | 727926deccbSFrançois Tigeot NUM_CLAUSE_TEMP_GPRS(((rdev->config.rv770.max_gprs * 24)/64)/2))); 728926deccbSFrançois Tigeot 729926deccbSFrançois Tigeot WREG32(SQ_GPR_RESOURCE_MGMT_2, (NUM_GS_GPRS((rdev->config.rv770.max_gprs * 7)/64) | 730926deccbSFrançois Tigeot NUM_ES_GPRS((rdev->config.rv770.max_gprs * 7)/64))); 731926deccbSFrançois Tigeot 732926deccbSFrançois Tigeot sq_thread_resource_mgmt = (NUM_PS_THREADS((rdev->config.rv770.max_threads * 4)/8) | 733926deccbSFrançois Tigeot NUM_VS_THREADS((rdev->config.rv770.max_threads * 2)/8) | 734926deccbSFrançois Tigeot NUM_ES_THREADS((rdev->config.rv770.max_threads * 1)/8)); 735926deccbSFrançois Tigeot if (((rdev->config.rv770.max_threads * 1) / 8) > rdev->config.rv770.max_gs_threads) 736926deccbSFrançois Tigeot sq_thread_resource_mgmt |= NUM_GS_THREADS(rdev->config.rv770.max_gs_threads); 737926deccbSFrançois Tigeot else 738926deccbSFrançois Tigeot sq_thread_resource_mgmt |= NUM_GS_THREADS((rdev->config.rv770.max_gs_threads * 1)/8); 739926deccbSFrançois Tigeot WREG32(SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); 740926deccbSFrançois Tigeot 741926deccbSFrançois Tigeot WREG32(SQ_STACK_RESOURCE_MGMT_1, (NUM_PS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4) | 742926deccbSFrançois Tigeot NUM_VS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4))); 743926deccbSFrançois Tigeot 744926deccbSFrançois Tigeot WREG32(SQ_STACK_RESOURCE_MGMT_2, (NUM_GS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4) | 745926deccbSFrançois Tigeot NUM_ES_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4))); 746926deccbSFrançois Tigeot 747926deccbSFrançois Tigeot sq_dyn_gpr_size_simd_ab_0 = (SIMDA_RING0((rdev->config.rv770.max_gprs * 38)/64) | 748926deccbSFrançois Tigeot SIMDA_RING1((rdev->config.rv770.max_gprs * 38)/64) | 749926deccbSFrançois Tigeot SIMDB_RING0((rdev->config.rv770.max_gprs * 38)/64) | 750926deccbSFrançois Tigeot SIMDB_RING1((rdev->config.rv770.max_gprs * 38)/64)); 751926deccbSFrançois Tigeot 752926deccbSFrançois Tigeot WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_0, sq_dyn_gpr_size_simd_ab_0); 753926deccbSFrançois Tigeot WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_1, sq_dyn_gpr_size_simd_ab_0); 754926deccbSFrançois Tigeot WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_2, sq_dyn_gpr_size_simd_ab_0); 755926deccbSFrançois Tigeot WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_3, sq_dyn_gpr_size_simd_ab_0); 756926deccbSFrançois Tigeot WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_4, sq_dyn_gpr_size_simd_ab_0); 757926deccbSFrançois Tigeot WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_5, sq_dyn_gpr_size_simd_ab_0); 758926deccbSFrançois Tigeot WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_6, sq_dyn_gpr_size_simd_ab_0); 759926deccbSFrançois Tigeot WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0); 760926deccbSFrançois Tigeot 761926deccbSFrançois Tigeot WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | 762926deccbSFrançois Tigeot FORCE_EOV_MAX_REZ_CNT(255))); 763926deccbSFrançois Tigeot 764926deccbSFrançois Tigeot if (rdev->family == CHIP_RV710) 765926deccbSFrançois Tigeot WREG32(VGT_CACHE_INVALIDATION, (CACHE_INVALIDATION(TC_ONLY) | 766926deccbSFrançois Tigeot AUTO_INVLD_EN(ES_AND_GS_AUTO))); 767926deccbSFrançois Tigeot else 768926deccbSFrançois Tigeot WREG32(VGT_CACHE_INVALIDATION, (CACHE_INVALIDATION(VC_AND_TC) | 769926deccbSFrançois Tigeot AUTO_INVLD_EN(ES_AND_GS_AUTO))); 770926deccbSFrançois Tigeot 771926deccbSFrançois Tigeot switch (rdev->family) { 772926deccbSFrançois Tigeot case CHIP_RV770: 773926deccbSFrançois Tigeot case CHIP_RV730: 774926deccbSFrançois Tigeot case CHIP_RV740: 775926deccbSFrançois Tigeot gs_prim_buffer_depth = 384; 776926deccbSFrançois Tigeot break; 777926deccbSFrançois Tigeot case CHIP_RV710: 778926deccbSFrançois Tigeot gs_prim_buffer_depth = 128; 779926deccbSFrançois Tigeot break; 780926deccbSFrançois Tigeot default: 781926deccbSFrançois Tigeot break; 782926deccbSFrançois Tigeot } 783926deccbSFrançois Tigeot 784926deccbSFrançois Tigeot num_gs_verts_per_thread = rdev->config.rv770.max_pipes * 16; 785926deccbSFrançois Tigeot vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread; 786926deccbSFrançois Tigeot /* Max value for this is 256 */ 787926deccbSFrançois Tigeot if (vgt_gs_per_es > 256) 788926deccbSFrançois Tigeot vgt_gs_per_es = 256; 789926deccbSFrançois Tigeot 790926deccbSFrançois Tigeot WREG32(VGT_ES_PER_GS, 128); 791926deccbSFrançois Tigeot WREG32(VGT_GS_PER_ES, vgt_gs_per_es); 792926deccbSFrançois Tigeot WREG32(VGT_GS_PER_VS, 2); 793926deccbSFrançois Tigeot 794926deccbSFrançois Tigeot /* more default values. 2D/3D driver should adjust as needed */ 795926deccbSFrançois Tigeot WREG32(VGT_GS_VERTEX_REUSE, 16); 796926deccbSFrançois Tigeot WREG32(PA_SC_LINE_STIPPLE_STATE, 0); 797926deccbSFrançois Tigeot WREG32(VGT_STRMOUT_EN, 0); 798926deccbSFrançois Tigeot WREG32(SX_MISC, 0); 799926deccbSFrançois Tigeot WREG32(PA_SC_MODE_CNTL, 0); 800926deccbSFrançois Tigeot WREG32(PA_SC_EDGERULE, 0xaaaaaaaa); 801926deccbSFrançois Tigeot WREG32(PA_SC_AA_CONFIG, 0); 802926deccbSFrançois Tigeot WREG32(PA_SC_CLIPRECT_RULE, 0xffff); 803926deccbSFrançois Tigeot WREG32(PA_SC_LINE_STIPPLE, 0); 804926deccbSFrançois Tigeot WREG32(SPI_INPUT_Z, 0); 805926deccbSFrançois Tigeot WREG32(SPI_PS_IN_CONTROL_0, NUM_INTERP(2)); 806926deccbSFrançois Tigeot WREG32(CB_COLOR7_FRAG, 0); 807926deccbSFrançois Tigeot 808926deccbSFrançois Tigeot /* clear render buffer base addresses */ 809926deccbSFrançois Tigeot WREG32(CB_COLOR0_BASE, 0); 810926deccbSFrançois Tigeot WREG32(CB_COLOR1_BASE, 0); 811926deccbSFrançois Tigeot WREG32(CB_COLOR2_BASE, 0); 812926deccbSFrançois Tigeot WREG32(CB_COLOR3_BASE, 0); 813926deccbSFrançois Tigeot WREG32(CB_COLOR4_BASE, 0); 814926deccbSFrançois Tigeot WREG32(CB_COLOR5_BASE, 0); 815926deccbSFrançois Tigeot WREG32(CB_COLOR6_BASE, 0); 816926deccbSFrançois Tigeot WREG32(CB_COLOR7_BASE, 0); 817926deccbSFrançois Tigeot 818926deccbSFrançois Tigeot WREG32(TCP_CNTL, 0); 819926deccbSFrançois Tigeot 820926deccbSFrançois Tigeot hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); 821926deccbSFrançois Tigeot WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); 822926deccbSFrançois Tigeot 823926deccbSFrançois Tigeot WREG32(PA_SC_MULTI_CHIP_CNTL, 0); 824926deccbSFrançois Tigeot 825926deccbSFrançois Tigeot WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA | 826926deccbSFrançois Tigeot NUM_CLIP_SEQ(3))); 827926deccbSFrançois Tigeot WREG32(VC_ENHANCE, 0); 828926deccbSFrançois Tigeot } 829926deccbSFrançois Tigeot 830926deccbSFrançois Tigeot void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) 831926deccbSFrançois Tigeot { 832926deccbSFrançois Tigeot u64 size_bf, size_af; 833926deccbSFrançois Tigeot 834926deccbSFrançois Tigeot if (mc->mc_vram_size > 0xE0000000) { 835926deccbSFrançois Tigeot /* leave room for at least 512M GTT */ 836926deccbSFrançois Tigeot dev_warn(rdev->dev, "limiting VRAM\n"); 837926deccbSFrançois Tigeot mc->real_vram_size = 0xE0000000; 838926deccbSFrançois Tigeot mc->mc_vram_size = 0xE0000000; 839926deccbSFrançois Tigeot } 840926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_AGP) { 841926deccbSFrançois Tigeot size_bf = mc->gtt_start; 842926deccbSFrançois Tigeot size_af = 0xFFFFFFFF - mc->gtt_end; 843926deccbSFrançois Tigeot if (size_bf > size_af) { 844926deccbSFrançois Tigeot if (mc->mc_vram_size > size_bf) { 845926deccbSFrançois Tigeot dev_warn(rdev->dev, "limiting VRAM\n"); 846926deccbSFrançois Tigeot mc->real_vram_size = size_bf; 847926deccbSFrançois Tigeot mc->mc_vram_size = size_bf; 848926deccbSFrançois Tigeot } 849926deccbSFrançois Tigeot mc->vram_start = mc->gtt_start - mc->mc_vram_size; 850926deccbSFrançois Tigeot } else { 851926deccbSFrançois Tigeot if (mc->mc_vram_size > size_af) { 852926deccbSFrançois Tigeot dev_warn(rdev->dev, "limiting VRAM\n"); 853926deccbSFrançois Tigeot mc->real_vram_size = size_af; 854926deccbSFrançois Tigeot mc->mc_vram_size = size_af; 855926deccbSFrançois Tigeot } 856926deccbSFrançois Tigeot mc->vram_start = mc->gtt_end + 1; 857926deccbSFrançois Tigeot } 858926deccbSFrançois Tigeot mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; 859926deccbSFrançois Tigeot dev_info(rdev->dev, "VRAM: %juM 0x%08jX - 0x%08jX (%juM used)\n", 860926deccbSFrançois Tigeot (uintmax_t)mc->mc_vram_size >> 20, (uintmax_t)mc->vram_start, 861926deccbSFrançois Tigeot (uintmax_t)mc->vram_end, (uintmax_t)mc->real_vram_size >> 20); 862926deccbSFrançois Tigeot } else { 863926deccbSFrançois Tigeot radeon_vram_location(rdev, &rdev->mc, 0); 864926deccbSFrançois Tigeot rdev->mc.gtt_base_align = 0; 865926deccbSFrançois Tigeot radeon_gtt_location(rdev, mc); 866926deccbSFrançois Tigeot } 867926deccbSFrançois Tigeot } 868926deccbSFrançois Tigeot 869926deccbSFrançois Tigeot static int rv770_mc_init(struct radeon_device *rdev) 870926deccbSFrançois Tigeot { 871926deccbSFrançois Tigeot u32 tmp; 872926deccbSFrançois Tigeot int chansize, numchan; 873926deccbSFrançois Tigeot 874926deccbSFrançois Tigeot /* Get VRAM informations */ 875926deccbSFrançois Tigeot rdev->mc.vram_is_ddr = true; 876926deccbSFrançois Tigeot tmp = RREG32(MC_ARB_RAMCFG); 877926deccbSFrançois Tigeot if (tmp & CHANSIZE_OVERRIDE) { 878926deccbSFrançois Tigeot chansize = 16; 879926deccbSFrançois Tigeot } else if (tmp & CHANSIZE_MASK) { 880926deccbSFrançois Tigeot chansize = 64; 881926deccbSFrançois Tigeot } else { 882926deccbSFrançois Tigeot chansize = 32; 883926deccbSFrançois Tigeot } 884926deccbSFrançois Tigeot tmp = RREG32(MC_SHARED_CHMAP); 885926deccbSFrançois Tigeot switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { 886926deccbSFrançois Tigeot case 0: 887926deccbSFrançois Tigeot default: 888926deccbSFrançois Tigeot numchan = 1; 889926deccbSFrançois Tigeot break; 890926deccbSFrançois Tigeot case 1: 891926deccbSFrançois Tigeot numchan = 2; 892926deccbSFrançois Tigeot break; 893926deccbSFrançois Tigeot case 2: 894926deccbSFrançois Tigeot numchan = 4; 895926deccbSFrançois Tigeot break; 896926deccbSFrançois Tigeot case 3: 897926deccbSFrançois Tigeot numchan = 8; 898926deccbSFrançois Tigeot break; 899926deccbSFrançois Tigeot } 900926deccbSFrançois Tigeot rdev->mc.vram_width = numchan * chansize; 901926deccbSFrançois Tigeot /* Could aper size report 0 ? */ 902926deccbSFrançois Tigeot rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); 903926deccbSFrançois Tigeot rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); 904926deccbSFrançois Tigeot /* Setup GPU memory space */ 905926deccbSFrançois Tigeot rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); 906926deccbSFrançois Tigeot rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); 907926deccbSFrançois Tigeot rdev->mc.visible_vram_size = rdev->mc.aper_size; 908926deccbSFrançois Tigeot r700_vram_gtt_location(rdev, &rdev->mc); 909926deccbSFrançois Tigeot radeon_update_bandwidth_info(rdev); 910926deccbSFrançois Tigeot 911926deccbSFrançois Tigeot return 0; 912926deccbSFrançois Tigeot } 913926deccbSFrançois Tigeot 914926deccbSFrançois Tigeot /** 915926deccbSFrançois Tigeot * rv770_copy_dma - copy pages using the DMA engine 916926deccbSFrançois Tigeot * 917926deccbSFrançois Tigeot * @rdev: radeon_device pointer 918926deccbSFrançois Tigeot * @src_offset: src GPU address 919926deccbSFrançois Tigeot * @dst_offset: dst GPU address 920926deccbSFrançois Tigeot * @num_gpu_pages: number of GPU pages to xfer 921926deccbSFrançois Tigeot * @fence: radeon fence object 922926deccbSFrançois Tigeot * 923926deccbSFrançois Tigeot * Copy GPU paging using the DMA engine (r7xx). 924926deccbSFrançois Tigeot * Used by the radeon ttm implementation to move pages if 925926deccbSFrançois Tigeot * registered as the asic copy callback. 926926deccbSFrançois Tigeot */ 927926deccbSFrançois Tigeot int rv770_copy_dma(struct radeon_device *rdev, 928926deccbSFrançois Tigeot uint64_t src_offset, uint64_t dst_offset, 929926deccbSFrançois Tigeot unsigned num_gpu_pages, 930926deccbSFrançois Tigeot struct radeon_fence **fence) 931926deccbSFrançois Tigeot { 932926deccbSFrançois Tigeot struct radeon_semaphore *sem = NULL; 933926deccbSFrançois Tigeot int ring_index = rdev->asic->copy.dma_ring_index; 934926deccbSFrançois Tigeot struct radeon_ring *ring = &rdev->ring[ring_index]; 935926deccbSFrançois Tigeot u32 size_in_dw, cur_size_in_dw; 936926deccbSFrançois Tigeot int i, num_loops; 937926deccbSFrançois Tigeot int r = 0; 938926deccbSFrançois Tigeot 939926deccbSFrançois Tigeot r = radeon_semaphore_create(rdev, &sem); 940926deccbSFrançois Tigeot if (r) { 941926deccbSFrançois Tigeot DRM_ERROR("radeon: moving bo (%d).\n", r); 942926deccbSFrançois Tigeot return r; 943926deccbSFrançois Tigeot } 944926deccbSFrançois Tigeot 945926deccbSFrançois Tigeot size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4; 946926deccbSFrançois Tigeot num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFF); 947926deccbSFrançois Tigeot r = radeon_ring_lock(rdev, ring, num_loops * 5 + 8); 948926deccbSFrançois Tigeot if (r) { 949926deccbSFrançois Tigeot DRM_ERROR("radeon: moving bo (%d).\n", r); 950926deccbSFrançois Tigeot radeon_semaphore_free(rdev, &sem, NULL); 951926deccbSFrançois Tigeot return r; 952926deccbSFrançois Tigeot } 953926deccbSFrançois Tigeot 954926deccbSFrançois Tigeot if (radeon_fence_need_sync(*fence, ring->idx)) { 955926deccbSFrançois Tigeot radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring, 956926deccbSFrançois Tigeot ring->idx); 957926deccbSFrançois Tigeot radeon_fence_note_sync(*fence, ring->idx); 958926deccbSFrançois Tigeot } else { 959926deccbSFrançois Tigeot radeon_semaphore_free(rdev, &sem, NULL); 960926deccbSFrançois Tigeot } 961926deccbSFrançois Tigeot 962926deccbSFrançois Tigeot for (i = 0; i < num_loops; i++) { 963926deccbSFrançois Tigeot cur_size_in_dw = size_in_dw; 964926deccbSFrançois Tigeot if (cur_size_in_dw > 0xFFFF) 965926deccbSFrançois Tigeot cur_size_in_dw = 0xFFFF; 966926deccbSFrançois Tigeot size_in_dw -= cur_size_in_dw; 967926deccbSFrançois Tigeot radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw)); 968926deccbSFrançois Tigeot radeon_ring_write(ring, dst_offset & 0xfffffffc); 969926deccbSFrançois Tigeot radeon_ring_write(ring, src_offset & 0xfffffffc); 970926deccbSFrançois Tigeot radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); 971926deccbSFrançois Tigeot radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff); 972926deccbSFrançois Tigeot src_offset += cur_size_in_dw * 4; 973926deccbSFrançois Tigeot dst_offset += cur_size_in_dw * 4; 974926deccbSFrançois Tigeot } 975926deccbSFrançois Tigeot 976926deccbSFrançois Tigeot r = radeon_fence_emit(rdev, fence, ring->idx); 977926deccbSFrançois Tigeot if (r) { 978926deccbSFrançois Tigeot radeon_ring_unlock_undo(rdev, ring); 979926deccbSFrançois Tigeot return r; 980926deccbSFrançois Tigeot } 981926deccbSFrançois Tigeot 982926deccbSFrançois Tigeot radeon_ring_unlock_commit(rdev, ring); 983926deccbSFrançois Tigeot radeon_semaphore_free(rdev, &sem, *fence); 984926deccbSFrançois Tigeot 985926deccbSFrançois Tigeot return r; 986926deccbSFrançois Tigeot } 987926deccbSFrançois Tigeot 988926deccbSFrançois Tigeot static int rv770_startup(struct radeon_device *rdev) 989926deccbSFrançois Tigeot { 990926deccbSFrançois Tigeot struct radeon_ring *ring; 991926deccbSFrançois Tigeot int r; 992926deccbSFrançois Tigeot 993926deccbSFrançois Tigeot /* enable pcie gen2 link */ 994926deccbSFrançois Tigeot rv770_pcie_gen2_enable(rdev); 995926deccbSFrançois Tigeot 996926deccbSFrançois Tigeot if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { 997926deccbSFrançois Tigeot r = r600_init_microcode(rdev); 998926deccbSFrançois Tigeot if (r) { 999926deccbSFrançois Tigeot DRM_ERROR("Failed to load firmware!\n"); 1000926deccbSFrançois Tigeot return r; 1001926deccbSFrançois Tigeot } 1002926deccbSFrançois Tigeot } 1003926deccbSFrançois Tigeot 1004926deccbSFrançois Tigeot r = r600_vram_scratch_init(rdev); 1005926deccbSFrançois Tigeot if (r) 1006926deccbSFrançois Tigeot return r; 1007926deccbSFrançois Tigeot 1008926deccbSFrançois Tigeot rv770_mc_program(rdev); 1009926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_AGP) { 1010926deccbSFrançois Tigeot rv770_agp_enable(rdev); 1011926deccbSFrançois Tigeot } else { 1012926deccbSFrançois Tigeot r = rv770_pcie_gart_enable(rdev); 1013926deccbSFrançois Tigeot if (r) 1014926deccbSFrançois Tigeot return r; 1015926deccbSFrançois Tigeot } 1016926deccbSFrançois Tigeot 1017926deccbSFrançois Tigeot rv770_gpu_init(rdev); 1018926deccbSFrançois Tigeot r = r600_blit_init(rdev); 1019926deccbSFrançois Tigeot if (r) { 1020926deccbSFrançois Tigeot r600_blit_fini(rdev); 1021926deccbSFrançois Tigeot rdev->asic->copy.copy = NULL; 1022926deccbSFrançois Tigeot dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); 1023926deccbSFrançois Tigeot } 1024926deccbSFrançois Tigeot 1025926deccbSFrançois Tigeot /* allocate wb buffer */ 1026926deccbSFrançois Tigeot r = radeon_wb_init(rdev); 1027926deccbSFrançois Tigeot if (r) 1028926deccbSFrançois Tigeot return r; 1029926deccbSFrançois Tigeot 1030926deccbSFrançois Tigeot r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 1031926deccbSFrançois Tigeot if (r) { 1032926deccbSFrançois Tigeot dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 1033926deccbSFrançois Tigeot return r; 1034926deccbSFrançois Tigeot } 1035926deccbSFrançois Tigeot 1036926deccbSFrançois Tigeot r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); 1037926deccbSFrançois Tigeot if (r) { 1038926deccbSFrançois Tigeot dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); 1039926deccbSFrançois Tigeot return r; 1040926deccbSFrançois Tigeot } 1041926deccbSFrançois Tigeot 1042926deccbSFrançois Tigeot /* Enable IRQ */ 1043926deccbSFrançois Tigeot r = r600_irq_init(rdev); 1044926deccbSFrançois Tigeot if (r) { 1045926deccbSFrançois Tigeot DRM_ERROR("radeon: IH init failed (%d).\n", r); 1046926deccbSFrançois Tigeot radeon_irq_kms_fini(rdev); 1047926deccbSFrançois Tigeot return r; 1048926deccbSFrançois Tigeot } 1049926deccbSFrançois Tigeot r600_irq_set(rdev); 1050926deccbSFrançois Tigeot 1051926deccbSFrançois Tigeot ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 1052926deccbSFrançois Tigeot r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, 1053926deccbSFrançois Tigeot R600_CP_RB_RPTR, R600_CP_RB_WPTR, 1054926deccbSFrançois Tigeot 0, 0xfffff, RADEON_CP_PACKET2); 1055926deccbSFrançois Tigeot if (r) 1056926deccbSFrançois Tigeot return r; 1057926deccbSFrançois Tigeot 1058926deccbSFrançois Tigeot ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; 1059926deccbSFrançois Tigeot r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, 1060926deccbSFrançois Tigeot DMA_RB_RPTR, DMA_RB_WPTR, 1061926deccbSFrançois Tigeot 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); 1062926deccbSFrançois Tigeot if (r) 1063926deccbSFrançois Tigeot return r; 1064926deccbSFrançois Tigeot 1065926deccbSFrançois Tigeot r = rv770_cp_load_microcode(rdev); 1066926deccbSFrançois Tigeot if (r) 1067926deccbSFrançois Tigeot return r; 1068926deccbSFrançois Tigeot r = r600_cp_resume(rdev); 1069926deccbSFrançois Tigeot if (r) 1070926deccbSFrançois Tigeot return r; 1071926deccbSFrançois Tigeot 1072926deccbSFrançois Tigeot r = r600_dma_resume(rdev); 1073926deccbSFrançois Tigeot if (r) 1074926deccbSFrançois Tigeot return r; 1075926deccbSFrançois Tigeot 1076926deccbSFrançois Tigeot r = radeon_ib_pool_init(rdev); 1077926deccbSFrançois Tigeot if (r) { 1078926deccbSFrançois Tigeot dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 1079926deccbSFrançois Tigeot return r; 1080926deccbSFrançois Tigeot } 1081926deccbSFrançois Tigeot 1082926deccbSFrançois Tigeot r = r600_audio_init(rdev); 1083926deccbSFrançois Tigeot if (r) { 1084926deccbSFrançois Tigeot DRM_ERROR("radeon: audio init failed\n"); 1085926deccbSFrançois Tigeot return r; 1086926deccbSFrançois Tigeot } 1087926deccbSFrançois Tigeot 1088926deccbSFrançois Tigeot return 0; 1089926deccbSFrançois Tigeot } 1090926deccbSFrançois Tigeot 1091926deccbSFrançois Tigeot int rv770_resume(struct radeon_device *rdev) 1092926deccbSFrançois Tigeot { 1093926deccbSFrançois Tigeot int r; 1094926deccbSFrançois Tigeot 1095926deccbSFrançois Tigeot /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, 1096926deccbSFrançois Tigeot * posting will perform necessary task to bring back GPU into good 1097926deccbSFrançois Tigeot * shape. 1098926deccbSFrançois Tigeot */ 1099926deccbSFrançois Tigeot /* post card */ 1100926deccbSFrançois Tigeot atom_asic_init(rdev->mode_info.atom_context); 1101926deccbSFrançois Tigeot 1102926deccbSFrançois Tigeot rdev->accel_working = true; 1103926deccbSFrançois Tigeot r = rv770_startup(rdev); 1104926deccbSFrançois Tigeot if (r) { 1105926deccbSFrançois Tigeot DRM_ERROR("r600 startup failed on resume\n"); 1106926deccbSFrançois Tigeot rdev->accel_working = false; 1107926deccbSFrançois Tigeot return r; 1108926deccbSFrançois Tigeot } 1109926deccbSFrançois Tigeot 1110926deccbSFrançois Tigeot return r; 1111926deccbSFrançois Tigeot 1112926deccbSFrançois Tigeot } 1113926deccbSFrançois Tigeot 1114926deccbSFrançois Tigeot int rv770_suspend(struct radeon_device *rdev) 1115926deccbSFrançois Tigeot { 1116926deccbSFrançois Tigeot r600_audio_fini(rdev); 1117926deccbSFrançois Tigeot r700_cp_stop(rdev); 1118926deccbSFrançois Tigeot r600_dma_stop(rdev); 1119926deccbSFrançois Tigeot r600_irq_suspend(rdev); 1120926deccbSFrançois Tigeot radeon_wb_disable(rdev); 1121926deccbSFrançois Tigeot rv770_pcie_gart_disable(rdev); 1122926deccbSFrançois Tigeot 1123926deccbSFrançois Tigeot return 0; 1124926deccbSFrançois Tigeot } 1125926deccbSFrançois Tigeot 1126926deccbSFrançois Tigeot /* Plan is to move initialization in that function and use 1127926deccbSFrançois Tigeot * helper function so that radeon_device_init pretty much 1128926deccbSFrançois Tigeot * do nothing more than calling asic specific function. This 1129926deccbSFrançois Tigeot * should also allow to remove a bunch of callback function 1130926deccbSFrançois Tigeot * like vram_info. 1131926deccbSFrançois Tigeot */ 1132926deccbSFrançois Tigeot int rv770_init(struct radeon_device *rdev) 1133926deccbSFrançois Tigeot { 1134926deccbSFrançois Tigeot int r; 1135926deccbSFrançois Tigeot 1136926deccbSFrançois Tigeot /* Read BIOS */ 1137926deccbSFrançois Tigeot if (!radeon_get_bios(rdev)) { 1138926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev)) 1139926deccbSFrançois Tigeot return -EINVAL; 1140926deccbSFrançois Tigeot } 1141926deccbSFrançois Tigeot /* Must be an ATOMBIOS */ 1142926deccbSFrançois Tigeot if (!rdev->is_atom_bios) { 1143926deccbSFrançois Tigeot dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); 1144926deccbSFrançois Tigeot return -EINVAL; 1145926deccbSFrançois Tigeot } 1146926deccbSFrançois Tigeot r = radeon_atombios_init(rdev); 1147926deccbSFrançois Tigeot if (r) 1148926deccbSFrançois Tigeot return r; 1149926deccbSFrançois Tigeot /* Post card if necessary */ 1150926deccbSFrançois Tigeot if (!radeon_card_posted(rdev)) { 1151926deccbSFrançois Tigeot if (!rdev->bios) { 1152926deccbSFrançois Tigeot dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); 1153926deccbSFrançois Tigeot return -EINVAL; 1154926deccbSFrançois Tigeot } 1155926deccbSFrançois Tigeot DRM_INFO("GPU not posted. posting now...\n"); 1156926deccbSFrançois Tigeot atom_asic_init(rdev->mode_info.atom_context); 1157926deccbSFrançois Tigeot } 1158926deccbSFrançois Tigeot /* Initialize scratch registers */ 1159926deccbSFrançois Tigeot r600_scratch_init(rdev); 1160926deccbSFrançois Tigeot /* Initialize surface registers */ 1161926deccbSFrançois Tigeot radeon_surface_init(rdev); 1162926deccbSFrançois Tigeot /* Initialize clocks */ 1163926deccbSFrançois Tigeot radeon_get_clock_info(rdev->ddev); 1164926deccbSFrançois Tigeot /* Fence driver */ 1165926deccbSFrançois Tigeot r = radeon_fence_driver_init(rdev); 1166926deccbSFrançois Tigeot if (r) 1167926deccbSFrançois Tigeot return r; 1168926deccbSFrançois Tigeot /* initialize AGP */ 1169926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_AGP) { 1170926deccbSFrançois Tigeot r = radeon_agp_init(rdev); 1171926deccbSFrançois Tigeot if (r) 1172926deccbSFrançois Tigeot radeon_agp_disable(rdev); 1173926deccbSFrançois Tigeot } 1174926deccbSFrançois Tigeot r = rv770_mc_init(rdev); 1175926deccbSFrançois Tigeot if (r) 1176926deccbSFrançois Tigeot return r; 1177926deccbSFrançois Tigeot /* Memory manager */ 1178926deccbSFrançois Tigeot r = radeon_bo_init(rdev); 1179926deccbSFrançois Tigeot if (r) 1180926deccbSFrançois Tigeot return r; 1181926deccbSFrançois Tigeot 1182926deccbSFrançois Tigeot r = radeon_irq_kms_init(rdev); 1183926deccbSFrançois Tigeot if (r) 1184926deccbSFrançois Tigeot return r; 1185926deccbSFrançois Tigeot 1186926deccbSFrançois Tigeot rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; 1187926deccbSFrançois Tigeot r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); 1188926deccbSFrançois Tigeot 1189926deccbSFrançois Tigeot rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; 1190926deccbSFrançois Tigeot r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); 1191926deccbSFrançois Tigeot 1192926deccbSFrançois Tigeot rdev->ih.ring_obj = NULL; 1193926deccbSFrançois Tigeot r600_ih_ring_init(rdev, 64 * 1024); 1194926deccbSFrançois Tigeot 1195926deccbSFrançois Tigeot r = r600_pcie_gart_init(rdev); 1196926deccbSFrançois Tigeot if (r) 1197926deccbSFrançois Tigeot return r; 1198926deccbSFrançois Tigeot 1199926deccbSFrançois Tigeot rdev->accel_working = true; 1200926deccbSFrançois Tigeot r = rv770_startup(rdev); 1201926deccbSFrançois Tigeot if (r) { 1202926deccbSFrançois Tigeot dev_err(rdev->dev, "disabling GPU acceleration\n"); 1203926deccbSFrançois Tigeot r700_cp_fini(rdev); 1204926deccbSFrançois Tigeot r600_dma_fini(rdev); 1205926deccbSFrançois Tigeot r600_irq_fini(rdev); 1206926deccbSFrançois Tigeot radeon_wb_fini(rdev); 1207926deccbSFrançois Tigeot radeon_ib_pool_fini(rdev); 1208926deccbSFrançois Tigeot radeon_irq_kms_fini(rdev); 1209926deccbSFrançois Tigeot rv770_pcie_gart_fini(rdev); 1210926deccbSFrançois Tigeot rdev->accel_working = false; 1211926deccbSFrançois Tigeot } 1212926deccbSFrançois Tigeot 1213926deccbSFrançois Tigeot return 0; 1214926deccbSFrançois Tigeot } 1215926deccbSFrançois Tigeot 1216926deccbSFrançois Tigeot void rv770_fini(struct radeon_device *rdev) 1217926deccbSFrançois Tigeot { 1218926deccbSFrançois Tigeot r600_blit_fini(rdev); 1219926deccbSFrançois Tigeot r700_cp_fini(rdev); 1220926deccbSFrançois Tigeot r600_dma_fini(rdev); 1221926deccbSFrançois Tigeot r600_irq_fini(rdev); 1222926deccbSFrançois Tigeot radeon_wb_fini(rdev); 1223926deccbSFrançois Tigeot radeon_ib_pool_fini(rdev); 1224926deccbSFrançois Tigeot radeon_irq_kms_fini(rdev); 1225926deccbSFrançois Tigeot rv770_pcie_gart_fini(rdev); 1226926deccbSFrançois Tigeot r600_vram_scratch_fini(rdev); 1227926deccbSFrançois Tigeot radeon_gem_fini(rdev); 1228926deccbSFrançois Tigeot radeon_fence_driver_fini(rdev); 1229926deccbSFrançois Tigeot radeon_agp_fini(rdev); 1230926deccbSFrançois Tigeot radeon_bo_fini(rdev); 1231926deccbSFrançois Tigeot radeon_atombios_fini(rdev); 1232926deccbSFrançois Tigeot r600_fini_microcode(rdev); 12335a3b77d5SFrançois Tigeot drm_free(rdev->bios, M_DRM); 1234926deccbSFrançois Tigeot rdev->bios = NULL; 1235926deccbSFrançois Tigeot } 1236926deccbSFrançois Tigeot 1237926deccbSFrançois Tigeot static void rv770_pcie_gen2_enable(struct radeon_device *rdev) 1238926deccbSFrançois Tigeot { 1239926deccbSFrançois Tigeot u32 link_width_cntl, lanes, speed_cntl, tmp; 1240926deccbSFrançois Tigeot u16 link_cntl2; 1241926deccbSFrançois Tigeot u32 mask; 1242926deccbSFrançois Tigeot int ret; 1243926deccbSFrançois Tigeot 1244926deccbSFrançois Tigeot if (radeon_pcie_gen2 == 0) 1245926deccbSFrançois Tigeot return; 1246926deccbSFrançois Tigeot 1247926deccbSFrançois Tigeot if (rdev->flags & RADEON_IS_IGP) 1248926deccbSFrançois Tigeot return; 1249926deccbSFrançois Tigeot 1250926deccbSFrançois Tigeot if (!(rdev->flags & RADEON_IS_PCIE)) 1251926deccbSFrançois Tigeot return; 1252926deccbSFrançois Tigeot 1253926deccbSFrançois Tigeot /* x2 cards have a special sequence */ 1254926deccbSFrançois Tigeot if (ASIC_IS_X2(rdev)) 1255926deccbSFrançois Tigeot return; 1256926deccbSFrançois Tigeot 1257926deccbSFrançois Tigeot ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); 1258926deccbSFrançois Tigeot if (ret != 0) 1259926deccbSFrançois Tigeot return; 1260926deccbSFrançois Tigeot 1261926deccbSFrançois Tigeot if (!(mask & DRM_PCIE_SPEED_50)) 1262926deccbSFrançois Tigeot return; 1263926deccbSFrançois Tigeot 1264926deccbSFrançois Tigeot DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); 1265926deccbSFrançois Tigeot 1266926deccbSFrançois Tigeot /* advertise upconfig capability */ 1267926deccbSFrançois Tigeot link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); 1268926deccbSFrançois Tigeot link_width_cntl &= ~LC_UPCONFIGURE_DIS; 1269926deccbSFrançois Tigeot WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 1270926deccbSFrançois Tigeot link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); 1271926deccbSFrançois Tigeot if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) { 1272926deccbSFrançois Tigeot lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT; 1273926deccbSFrançois Tigeot link_width_cntl &= ~(LC_LINK_WIDTH_MASK | 1274926deccbSFrançois Tigeot LC_RECONFIG_ARC_MISSING_ESCAPE); 1275926deccbSFrançois Tigeot link_width_cntl |= lanes | LC_RECONFIG_NOW | 1276926deccbSFrançois Tigeot LC_RENEGOTIATE_EN | LC_UPCONFIGURE_SUPPORT; 1277926deccbSFrançois Tigeot WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 1278926deccbSFrançois Tigeot } else { 1279926deccbSFrançois Tigeot link_width_cntl |= LC_UPCONFIGURE_DIS; 1280926deccbSFrançois Tigeot WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 1281926deccbSFrançois Tigeot } 1282926deccbSFrançois Tigeot 1283926deccbSFrançois Tigeot speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); 1284926deccbSFrançois Tigeot if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) && 1285926deccbSFrançois Tigeot (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { 1286926deccbSFrançois Tigeot 1287926deccbSFrançois Tigeot tmp = RREG32(0x541c); 1288926deccbSFrançois Tigeot WREG32(0x541c, tmp | 0x8); 1289926deccbSFrançois Tigeot WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN); 1290926deccbSFrançois Tigeot link_cntl2 = RREG16(0x4088); 1291926deccbSFrançois Tigeot link_cntl2 &= ~TARGET_LINK_SPEED_MASK; 1292926deccbSFrançois Tigeot link_cntl2 |= 0x2; 1293926deccbSFrançois Tigeot WREG16(0x4088, link_cntl2); 1294926deccbSFrançois Tigeot WREG32(MM_CFGREGS_CNTL, 0); 1295926deccbSFrançois Tigeot 1296926deccbSFrançois Tigeot speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); 1297926deccbSFrançois Tigeot speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN; 1298926deccbSFrançois Tigeot WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); 1299926deccbSFrançois Tigeot 1300926deccbSFrançois Tigeot speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); 1301926deccbSFrançois Tigeot speed_cntl |= LC_CLR_FAILED_SPD_CHANGE_CNT; 1302926deccbSFrançois Tigeot WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); 1303926deccbSFrançois Tigeot 1304926deccbSFrançois Tigeot speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); 1305926deccbSFrançois Tigeot speed_cntl &= ~LC_CLR_FAILED_SPD_CHANGE_CNT; 1306926deccbSFrançois Tigeot WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); 1307926deccbSFrançois Tigeot 1308926deccbSFrançois Tigeot speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); 1309926deccbSFrançois Tigeot speed_cntl |= LC_GEN2_EN_STRAP; 1310926deccbSFrançois Tigeot WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); 1311926deccbSFrançois Tigeot 1312926deccbSFrançois Tigeot } else { 1313926deccbSFrançois Tigeot link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); 1314926deccbSFrançois Tigeot /* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */ 1315926deccbSFrançois Tigeot if (1) 1316926deccbSFrançois Tigeot link_width_cntl |= LC_UPCONFIGURE_DIS; 1317926deccbSFrançois Tigeot else 1318926deccbSFrançois Tigeot link_width_cntl &= ~LC_UPCONFIGURE_DIS; 1319926deccbSFrançois Tigeot WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 1320926deccbSFrançois Tigeot } 1321926deccbSFrançois Tigeot } 1322