162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc. 362306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc. 462306a36Sopenharmony_ci * Copyright 2009 Jerome Glisse. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 762306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 862306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 962306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1062306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 1162306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1462306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1762306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1862306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1962306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2062306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2162306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2262306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Authors: Dave Airlie 2562306a36Sopenharmony_ci * Alex Deucher 2662306a36Sopenharmony_ci * Jerome Glisse 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <linux/pci.h> 3062306a36Sopenharmony_ci#include <linux/seq_file.h> 3162306a36Sopenharmony_ci#include <linux/slab.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <drm/drm.h> 3462306a36Sopenharmony_ci#include <drm/drm_device.h> 3562306a36Sopenharmony_ci#include <drm/drm_file.h> 3662306a36Sopenharmony_ci#include <drm/radeon_drm.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include "r100_track.h" 3962306a36Sopenharmony_ci#include "r300_reg_safe.h" 4062306a36Sopenharmony_ci#include "r300d.h" 4162306a36Sopenharmony_ci#include "radeon.h" 4262306a36Sopenharmony_ci#include "radeon_asic.h" 4362306a36Sopenharmony_ci#include "radeon_reg.h" 4462306a36Sopenharmony_ci#include "rv350d.h" 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * GPU Errata: 4962306a36Sopenharmony_ci * - HOST_PATH_CNTL: r300 family seems to dislike write to HOST_PATH_CNTL 5062306a36Sopenharmony_ci * using MMIO to flush host path read cache, this lead to HARDLOCKUP. 5162306a36Sopenharmony_ci * However, scheduling such write to the ring seems harmless, i suspect 5262306a36Sopenharmony_ci * the CP read collide with the flush somehow, or maybe the MC, hard to 5362306a36Sopenharmony_ci * tell. (Jerome Glisse) 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * Indirect registers accessor 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ciuint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci unsigned long flags; 6262306a36Sopenharmony_ci uint32_t r; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci spin_lock_irqsave(&rdev->pcie_idx_lock, flags); 6562306a36Sopenharmony_ci WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); 6662306a36Sopenharmony_ci r = RREG32(RADEON_PCIE_DATA); 6762306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags); 6862306a36Sopenharmony_ci return r; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_civoid rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci unsigned long flags; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci spin_lock_irqsave(&rdev->pcie_idx_lock, flags); 7662306a36Sopenharmony_ci WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); 7762306a36Sopenharmony_ci WREG32(RADEON_PCIE_DATA, (v)); 7862306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* 8262306a36Sopenharmony_ci * rv370,rv380 PCIE GART 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_cistatic void rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_civoid rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci uint32_t tmp; 8962306a36Sopenharmony_ci int i; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* Workaround HW bug do flush 2 times */ 9262306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 9362306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 9462306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB); 9562306a36Sopenharmony_ci (void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 9662306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci mb(); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#define R300_PTE_UNSNOOPED (1 << 0) 10262306a36Sopenharmony_ci#define R300_PTE_WRITEABLE (1 << 2) 10362306a36Sopenharmony_ci#define R300_PTE_READABLE (1 << 3) 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciuint64_t rv370_pcie_gart_get_page_entry(uint64_t addr, uint32_t flags) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci addr = (lower_32_bits(addr) >> 8) | 10862306a36Sopenharmony_ci ((upper_32_bits(addr) & 0xff) << 24); 10962306a36Sopenharmony_ci if (flags & RADEON_GART_PAGE_READ) 11062306a36Sopenharmony_ci addr |= R300_PTE_READABLE; 11162306a36Sopenharmony_ci if (flags & RADEON_GART_PAGE_WRITE) 11262306a36Sopenharmony_ci addr |= R300_PTE_WRITEABLE; 11362306a36Sopenharmony_ci if (!(flags & RADEON_GART_PAGE_SNOOP)) 11462306a36Sopenharmony_ci addr |= R300_PTE_UNSNOOPED; 11562306a36Sopenharmony_ci return addr; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_civoid rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, 11962306a36Sopenharmony_ci uint64_t entry) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci void __iomem *ptr = rdev->gart.ptr; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* on x86 we want this to be CPU endian, on powerpc 12462306a36Sopenharmony_ci * on powerpc without HW swappers, it'll get swapped on way 12562306a36Sopenharmony_ci * into VRAM - so no need for cpu_to_le32 on VRAM tables */ 12662306a36Sopenharmony_ci writel(entry, ((void __iomem *)ptr) + (i * 4)); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciint rv370_pcie_gart_init(struct radeon_device *rdev) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci int r; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (rdev->gart.robj) { 13462306a36Sopenharmony_ci WARN(1, "RV370 PCIE GART already initialized\n"); 13562306a36Sopenharmony_ci return 0; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci /* Initialize common gart structure */ 13862306a36Sopenharmony_ci r = radeon_gart_init(rdev); 13962306a36Sopenharmony_ci if (r) 14062306a36Sopenharmony_ci return r; 14162306a36Sopenharmony_ci rv370_debugfs_pcie_gart_info_init(rdev); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; 14462306a36Sopenharmony_ci rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; 14562306a36Sopenharmony_ci rdev->asic->gart.get_page_entry = &rv370_pcie_gart_get_page_entry; 14662306a36Sopenharmony_ci rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; 14762306a36Sopenharmony_ci return radeon_gart_table_vram_alloc(rdev); 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ciint rv370_pcie_gart_enable(struct radeon_device *rdev) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci uint32_t table_addr; 15362306a36Sopenharmony_ci uint32_t tmp; 15462306a36Sopenharmony_ci int r; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (rdev->gart.robj == NULL) { 15762306a36Sopenharmony_ci dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); 15862306a36Sopenharmony_ci return -EINVAL; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci r = radeon_gart_table_vram_pin(rdev); 16162306a36Sopenharmony_ci if (r) 16262306a36Sopenharmony_ci return r; 16362306a36Sopenharmony_ci /* discard memory request outside of configured range */ 16462306a36Sopenharmony_ci tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; 16562306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); 16662306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_start); 16762306a36Sopenharmony_ci tmp = rdev->mc.gtt_end & ~RADEON_GPU_PAGE_MASK; 16862306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp); 16962306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0); 17062306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0); 17162306a36Sopenharmony_ci table_addr = rdev->gart.table_addr; 17262306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr); 17362306a36Sopenharmony_ci /* FIXME: setup default page */ 17462306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start); 17562306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0); 17662306a36Sopenharmony_ci /* Clear error */ 17762306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_ERROR, 0); 17862306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 17962306a36Sopenharmony_ci tmp |= RADEON_PCIE_TX_GART_EN; 18062306a36Sopenharmony_ci tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; 18162306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); 18262306a36Sopenharmony_ci rv370_pcie_gart_tlb_flush(rdev); 18362306a36Sopenharmony_ci DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", 18462306a36Sopenharmony_ci (unsigned)(rdev->mc.gtt_size >> 20), 18562306a36Sopenharmony_ci (unsigned long long)table_addr); 18662306a36Sopenharmony_ci rdev->gart.ready = true; 18762306a36Sopenharmony_ci return 0; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_civoid rv370_pcie_gart_disable(struct radeon_device *rdev) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci u32 tmp; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0); 19562306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0); 19662306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0); 19762306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0); 19862306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 19962306a36Sopenharmony_ci tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; 20062306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); 20162306a36Sopenharmony_ci radeon_gart_table_vram_unpin(rdev); 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_civoid rv370_pcie_gart_fini(struct radeon_device *rdev) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci radeon_gart_fini(rdev); 20762306a36Sopenharmony_ci rv370_pcie_gart_disable(rdev); 20862306a36Sopenharmony_ci radeon_gart_table_vram_free(rdev); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_civoid r300_fence_ring_emit(struct radeon_device *rdev, 21262306a36Sopenharmony_ci struct radeon_fence *fence) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[fence->ring]; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* Who ever call radeon_fence_emit should call ring_lock and ask 21762306a36Sopenharmony_ci * for enough space (today caller are ib schedule and buffer move) */ 21862306a36Sopenharmony_ci /* Write SC register so SC & US assert idle */ 21962306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_TL, 0)); 22062306a36Sopenharmony_ci radeon_ring_write(ring, 0); 22162306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_BR, 0)); 22262306a36Sopenharmony_ci radeon_ring_write(ring, 0); 22362306a36Sopenharmony_ci /* Flush 3D cache */ 22462306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); 22562306a36Sopenharmony_ci radeon_ring_write(ring, R300_RB3D_DC_FLUSH); 22662306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); 22762306a36Sopenharmony_ci radeon_ring_write(ring, R300_ZC_FLUSH); 22862306a36Sopenharmony_ci /* Wait until IDLE & CLEAN */ 22962306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); 23062306a36Sopenharmony_ci radeon_ring_write(ring, (RADEON_WAIT_3D_IDLECLEAN | 23162306a36Sopenharmony_ci RADEON_WAIT_2D_IDLECLEAN | 23262306a36Sopenharmony_ci RADEON_WAIT_DMA_GUI_IDLE)); 23362306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); 23462306a36Sopenharmony_ci radeon_ring_write(ring, rdev->config.r300.hdp_cntl | 23562306a36Sopenharmony_ci RADEON_HDP_READ_BUFFER_INVALIDATE); 23662306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); 23762306a36Sopenharmony_ci radeon_ring_write(ring, rdev->config.r300.hdp_cntl); 23862306a36Sopenharmony_ci /* Emit fence sequence & fire IRQ */ 23962306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0)); 24062306a36Sopenharmony_ci radeon_ring_write(ring, fence->seq); 24162306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_GEN_INT_STATUS, 0)); 24262306a36Sopenharmony_ci radeon_ring_write(ring, RADEON_SW_INT_FIRE); 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_civoid r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci unsigned gb_tile_config; 24862306a36Sopenharmony_ci int r; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* Sub pixel 1/12 so we can have 4K rendering according to doc */ 25162306a36Sopenharmony_ci gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); 25262306a36Sopenharmony_ci switch (rdev->num_gb_pipes) { 25362306a36Sopenharmony_ci case 2: 25462306a36Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R300; 25562306a36Sopenharmony_ci break; 25662306a36Sopenharmony_ci case 3: 25762306a36Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R420_3P; 25862306a36Sopenharmony_ci break; 25962306a36Sopenharmony_ci case 4: 26062306a36Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R420; 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci case 1: 26362306a36Sopenharmony_ci default: 26462306a36Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_RV350; 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 64); 26962306a36Sopenharmony_ci if (r) { 27062306a36Sopenharmony_ci return; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_ISYNC_CNTL, 0)); 27362306a36Sopenharmony_ci radeon_ring_write(ring, 27462306a36Sopenharmony_ci RADEON_ISYNC_ANY2D_IDLE3D | 27562306a36Sopenharmony_ci RADEON_ISYNC_ANY3D_IDLE2D | 27662306a36Sopenharmony_ci RADEON_ISYNC_WAIT_IDLEGUI | 27762306a36Sopenharmony_ci RADEON_ISYNC_CPSCRATCH_IDLEGUI); 27862306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_TILE_CONFIG, 0)); 27962306a36Sopenharmony_ci radeon_ring_write(ring, gb_tile_config); 28062306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); 28162306a36Sopenharmony_ci radeon_ring_write(ring, 28262306a36Sopenharmony_ci RADEON_WAIT_2D_IDLECLEAN | 28362306a36Sopenharmony_ci RADEON_WAIT_3D_IDLECLEAN); 28462306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_DST_PIPE_CONFIG, 0)); 28562306a36Sopenharmony_ci radeon_ring_write(ring, R300_PIPE_AUTO_CONFIG); 28662306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_SELECT, 0)); 28762306a36Sopenharmony_ci radeon_ring_write(ring, 0); 28862306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_ENABLE, 0)); 28962306a36Sopenharmony_ci radeon_ring_write(ring, 0); 29062306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); 29162306a36Sopenharmony_ci radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); 29262306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); 29362306a36Sopenharmony_ci radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE); 29462306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); 29562306a36Sopenharmony_ci radeon_ring_write(ring, 29662306a36Sopenharmony_ci RADEON_WAIT_2D_IDLECLEAN | 29762306a36Sopenharmony_ci RADEON_WAIT_3D_IDLECLEAN); 29862306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_AA_CONFIG, 0)); 29962306a36Sopenharmony_ci radeon_ring_write(ring, 0); 30062306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); 30162306a36Sopenharmony_ci radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); 30262306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); 30362306a36Sopenharmony_ci radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE); 30462306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_MSPOS0, 0)); 30562306a36Sopenharmony_ci radeon_ring_write(ring, 30662306a36Sopenharmony_ci ((6 << R300_MS_X0_SHIFT) | 30762306a36Sopenharmony_ci (6 << R300_MS_Y0_SHIFT) | 30862306a36Sopenharmony_ci (6 << R300_MS_X1_SHIFT) | 30962306a36Sopenharmony_ci (6 << R300_MS_Y1_SHIFT) | 31062306a36Sopenharmony_ci (6 << R300_MS_X2_SHIFT) | 31162306a36Sopenharmony_ci (6 << R300_MS_Y2_SHIFT) | 31262306a36Sopenharmony_ci (6 << R300_MSBD0_Y_SHIFT) | 31362306a36Sopenharmony_ci (6 << R300_MSBD0_X_SHIFT))); 31462306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_MSPOS1, 0)); 31562306a36Sopenharmony_ci radeon_ring_write(ring, 31662306a36Sopenharmony_ci ((6 << R300_MS_X3_SHIFT) | 31762306a36Sopenharmony_ci (6 << R300_MS_Y3_SHIFT) | 31862306a36Sopenharmony_ci (6 << R300_MS_X4_SHIFT) | 31962306a36Sopenharmony_ci (6 << R300_MS_Y4_SHIFT) | 32062306a36Sopenharmony_ci (6 << R300_MS_X5_SHIFT) | 32162306a36Sopenharmony_ci (6 << R300_MS_Y5_SHIFT) | 32262306a36Sopenharmony_ci (6 << R300_MSBD1_SHIFT))); 32362306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GA_ENHANCE, 0)); 32462306a36Sopenharmony_ci radeon_ring_write(ring, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); 32562306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GA_POLY_MODE, 0)); 32662306a36Sopenharmony_ci radeon_ring_write(ring, 32762306a36Sopenharmony_ci R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE); 32862306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GA_ROUND_MODE, 0)); 32962306a36Sopenharmony_ci radeon_ring_write(ring, 33062306a36Sopenharmony_ci R300_GEOMETRY_ROUND_NEAREST | 33162306a36Sopenharmony_ci R300_COLOR_ROUND_NEAREST); 33262306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic void r300_errata(struct radeon_device *rdev) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci rdev->pll_errata = 0; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (rdev->family == CHIP_R300 && 34062306a36Sopenharmony_ci (RREG32(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) == RADEON_CFG_ATI_REV_A11) { 34162306a36Sopenharmony_ci rdev->pll_errata |= CHIP_ERRATA_R300_CG; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ciint r300_mc_wait_for_idle(struct radeon_device *rdev) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci unsigned i; 34862306a36Sopenharmony_ci uint32_t tmp; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 35162306a36Sopenharmony_ci /* read MC_STATUS */ 35262306a36Sopenharmony_ci tmp = RREG32(RADEON_MC_STATUS); 35362306a36Sopenharmony_ci if (tmp & R300_MC_IDLE) { 35462306a36Sopenharmony_ci return 0; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci udelay(1); 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci return -1; 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic void r300_gpu_init(struct radeon_device *rdev) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci uint32_t gb_tile_config, tmp; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) || 36662306a36Sopenharmony_ci (rdev->family == CHIP_R350 && rdev->pdev->device != 0x4148)) { 36762306a36Sopenharmony_ci /* r300,r350 */ 36862306a36Sopenharmony_ci rdev->num_gb_pipes = 2; 36962306a36Sopenharmony_ci } else { 37062306a36Sopenharmony_ci /* rv350,rv370,rv380,r300 AD, r350 AH */ 37162306a36Sopenharmony_ci rdev->num_gb_pipes = 1; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci rdev->num_z_pipes = 1; 37462306a36Sopenharmony_ci gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); 37562306a36Sopenharmony_ci switch (rdev->num_gb_pipes) { 37662306a36Sopenharmony_ci case 2: 37762306a36Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R300; 37862306a36Sopenharmony_ci break; 37962306a36Sopenharmony_ci case 3: 38062306a36Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R420_3P; 38162306a36Sopenharmony_ci break; 38262306a36Sopenharmony_ci case 4: 38362306a36Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R420; 38462306a36Sopenharmony_ci break; 38562306a36Sopenharmony_ci default: 38662306a36Sopenharmony_ci case 1: 38762306a36Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_RV350; 38862306a36Sopenharmony_ci break; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci WREG32(R300_GB_TILE_CONFIG, gb_tile_config); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (r100_gui_wait_for_idle(rdev)) { 39362306a36Sopenharmony_ci pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n"); 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci tmp = RREG32(R300_DST_PIPE_CONFIG); 39762306a36Sopenharmony_ci WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci WREG32(R300_RB2D_DSTCACHE_MODE, 40062306a36Sopenharmony_ci R300_DC_AUTOFLUSH_ENABLE | 40162306a36Sopenharmony_ci R300_DC_DC_DISABLE_IGNORE_PE); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci if (r100_gui_wait_for_idle(rdev)) { 40462306a36Sopenharmony_ci pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n"); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci if (r300_mc_wait_for_idle(rdev)) { 40762306a36Sopenharmony_ci pr_warn("Failed to wait MC idle while programming pipes. Bad things might happen.\n"); 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized\n", 41062306a36Sopenharmony_ci rdev->num_gb_pipes, rdev->num_z_pipes); 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ciint r300_asic_reset(struct radeon_device *rdev, bool hard) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci struct r100_mc_save save; 41662306a36Sopenharmony_ci u32 status, tmp; 41762306a36Sopenharmony_ci int ret = 0; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci status = RREG32(R_000E40_RBBM_STATUS); 42062306a36Sopenharmony_ci if (!G_000E40_GUI_ACTIVE(status)) { 42162306a36Sopenharmony_ci return 0; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci r100_mc_stop(rdev, &save); 42462306a36Sopenharmony_ci status = RREG32(R_000E40_RBBM_STATUS); 42562306a36Sopenharmony_ci dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 42662306a36Sopenharmony_ci /* stop CP */ 42762306a36Sopenharmony_ci WREG32(RADEON_CP_CSQ_CNTL, 0); 42862306a36Sopenharmony_ci tmp = RREG32(RADEON_CP_RB_CNTL); 42962306a36Sopenharmony_ci WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); 43062306a36Sopenharmony_ci WREG32(RADEON_CP_RB_RPTR_WR, 0); 43162306a36Sopenharmony_ci WREG32(RADEON_CP_RB_WPTR, 0); 43262306a36Sopenharmony_ci WREG32(RADEON_CP_RB_CNTL, tmp); 43362306a36Sopenharmony_ci /* save PCI state */ 43462306a36Sopenharmony_ci pci_save_state(rdev->pdev); 43562306a36Sopenharmony_ci /* disable bus mastering */ 43662306a36Sopenharmony_ci r100_bm_disable(rdev); 43762306a36Sopenharmony_ci WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) | 43862306a36Sopenharmony_ci S_0000F0_SOFT_RESET_GA(1)); 43962306a36Sopenharmony_ci RREG32(R_0000F0_RBBM_SOFT_RESET); 44062306a36Sopenharmony_ci mdelay(500); 44162306a36Sopenharmony_ci WREG32(R_0000F0_RBBM_SOFT_RESET, 0); 44262306a36Sopenharmony_ci mdelay(1); 44362306a36Sopenharmony_ci status = RREG32(R_000E40_RBBM_STATUS); 44462306a36Sopenharmony_ci dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 44562306a36Sopenharmony_ci /* resetting the CP seems to be problematic sometimes it end up 44662306a36Sopenharmony_ci * hard locking the computer, but it's necessary for successful 44762306a36Sopenharmony_ci * reset more test & playing is needed on R3XX/R4XX to find a 44862306a36Sopenharmony_ci * reliable (if any solution) 44962306a36Sopenharmony_ci */ 45062306a36Sopenharmony_ci WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1)); 45162306a36Sopenharmony_ci RREG32(R_0000F0_RBBM_SOFT_RESET); 45262306a36Sopenharmony_ci mdelay(500); 45362306a36Sopenharmony_ci WREG32(R_0000F0_RBBM_SOFT_RESET, 0); 45462306a36Sopenharmony_ci mdelay(1); 45562306a36Sopenharmony_ci status = RREG32(R_000E40_RBBM_STATUS); 45662306a36Sopenharmony_ci dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 45762306a36Sopenharmony_ci /* restore PCI & busmastering */ 45862306a36Sopenharmony_ci pci_restore_state(rdev->pdev); 45962306a36Sopenharmony_ci r100_enable_bm(rdev); 46062306a36Sopenharmony_ci /* Check if GPU is idle */ 46162306a36Sopenharmony_ci if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { 46262306a36Sopenharmony_ci dev_err(rdev->dev, "failed to reset GPU\n"); 46362306a36Sopenharmony_ci ret = -1; 46462306a36Sopenharmony_ci } else 46562306a36Sopenharmony_ci dev_info(rdev->dev, "GPU reset succeed\n"); 46662306a36Sopenharmony_ci r100_mc_resume(rdev, &save); 46762306a36Sopenharmony_ci return ret; 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci/* 47162306a36Sopenharmony_ci * r300,r350,rv350,rv380 VRAM info 47262306a36Sopenharmony_ci */ 47362306a36Sopenharmony_civoid r300_mc_init(struct radeon_device *rdev) 47462306a36Sopenharmony_ci{ 47562306a36Sopenharmony_ci u64 base; 47662306a36Sopenharmony_ci u32 tmp; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci /* DDR for all card after R300 & IGP */ 47962306a36Sopenharmony_ci rdev->mc.vram_is_ddr = true; 48062306a36Sopenharmony_ci tmp = RREG32(RADEON_MEM_CNTL); 48162306a36Sopenharmony_ci tmp &= R300_MEM_NUM_CHANNELS_MASK; 48262306a36Sopenharmony_ci switch (tmp) { 48362306a36Sopenharmony_ci case 0: rdev->mc.vram_width = 64; break; 48462306a36Sopenharmony_ci case 1: rdev->mc.vram_width = 128; break; 48562306a36Sopenharmony_ci case 2: rdev->mc.vram_width = 256; break; 48662306a36Sopenharmony_ci default: rdev->mc.vram_width = 128; break; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci r100_vram_init_sizes(rdev); 48962306a36Sopenharmony_ci base = rdev->mc.aper_base; 49062306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 49162306a36Sopenharmony_ci base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; 49262306a36Sopenharmony_ci radeon_vram_location(rdev, &rdev->mc, base); 49362306a36Sopenharmony_ci rdev->mc.gtt_base_align = 0; 49462306a36Sopenharmony_ci if (!(rdev->flags & RADEON_IS_AGP)) 49562306a36Sopenharmony_ci radeon_gtt_location(rdev, &rdev->mc); 49662306a36Sopenharmony_ci radeon_update_bandwidth_info(rdev); 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_civoid rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci uint32_t link_width_cntl, mask; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 50462306a36Sopenharmony_ci return; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 50762306a36Sopenharmony_ci return; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci /* FIXME wait for idle */ 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci switch (lanes) { 51262306a36Sopenharmony_ci case 0: 51362306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X0; 51462306a36Sopenharmony_ci break; 51562306a36Sopenharmony_ci case 1: 51662306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X1; 51762306a36Sopenharmony_ci break; 51862306a36Sopenharmony_ci case 2: 51962306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X2; 52062306a36Sopenharmony_ci break; 52162306a36Sopenharmony_ci case 4: 52262306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X4; 52362306a36Sopenharmony_ci break; 52462306a36Sopenharmony_ci case 8: 52562306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X8; 52662306a36Sopenharmony_ci break; 52762306a36Sopenharmony_ci case 12: 52862306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X12; 52962306a36Sopenharmony_ci break; 53062306a36Sopenharmony_ci case 16: 53162306a36Sopenharmony_ci default: 53262306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X16; 53362306a36Sopenharmony_ci break; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) == 53962306a36Sopenharmony_ci (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT)) 54062306a36Sopenharmony_ci return; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK | 54362306a36Sopenharmony_ci RADEON_PCIE_LC_RECONFIG_NOW | 54462306a36Sopenharmony_ci RADEON_PCIE_LC_RECONFIG_LATER | 54562306a36Sopenharmony_ci RADEON_PCIE_LC_SHORT_RECONFIG_EN); 54662306a36Sopenharmony_ci link_width_cntl |= mask; 54762306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 54862306a36Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl | 54962306a36Sopenharmony_ci RADEON_PCIE_LC_RECONFIG_NOW)); 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci /* wait for lane set to complete */ 55262306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 55362306a36Sopenharmony_ci while (link_width_cntl == 0xffffffff) 55462306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ciint rv370_get_pcie_lanes(struct radeon_device *rdev) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci u32 link_width_cntl; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 56362306a36Sopenharmony_ci return 0; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 56662306a36Sopenharmony_ci return 0; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci /* FIXME wait for idle */ 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) { 57362306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X0: 57462306a36Sopenharmony_ci return 0; 57562306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X1: 57662306a36Sopenharmony_ci return 1; 57762306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X2: 57862306a36Sopenharmony_ci return 2; 57962306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X4: 58062306a36Sopenharmony_ci return 4; 58162306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X8: 58262306a36Sopenharmony_ci return 8; 58362306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X16: 58462306a36Sopenharmony_ci default: 58562306a36Sopenharmony_ci return 16; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci} 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 59062306a36Sopenharmony_cistatic int rv370_debugfs_pcie_gart_info_show(struct seq_file *m, void *unused) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci struct radeon_device *rdev = m->private; 59362306a36Sopenharmony_ci uint32_t tmp; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 59662306a36Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_CNTL 0x%08x\n", tmp); 59762306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_BASE); 59862306a36Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_BASE 0x%08x\n", tmp); 59962306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_LO); 60062306a36Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_START_LO 0x%08x\n", tmp); 60162306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_HI); 60262306a36Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_START_HI 0x%08x\n", tmp); 60362306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_LO); 60462306a36Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_END_LO 0x%08x\n", tmp); 60562306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_HI); 60662306a36Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_END_HI 0x%08x\n", tmp); 60762306a36Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_ERROR); 60862306a36Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_ERROR 0x%08x\n", tmp); 60962306a36Sopenharmony_ci return 0; 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(rv370_debugfs_pcie_gart_info); 61362306a36Sopenharmony_ci#endif 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic void rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 61862306a36Sopenharmony_ci struct dentry *root = rdev->ddev->primary->debugfs_root; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci debugfs_create_file("rv370_pcie_gart_info", 0444, root, rdev, 62162306a36Sopenharmony_ci &rv370_debugfs_pcie_gart_info_fops); 62262306a36Sopenharmony_ci#endif 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_cistatic int r300_packet0_check(struct radeon_cs_parser *p, 62662306a36Sopenharmony_ci struct radeon_cs_packet *pkt, 62762306a36Sopenharmony_ci unsigned idx, unsigned reg) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci struct radeon_bo_list *reloc; 63062306a36Sopenharmony_ci struct r100_cs_track *track; 63162306a36Sopenharmony_ci volatile uint32_t *ib; 63262306a36Sopenharmony_ci uint32_t tmp, tile_flags = 0; 63362306a36Sopenharmony_ci unsigned i; 63462306a36Sopenharmony_ci int r; 63562306a36Sopenharmony_ci u32 idx_value; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci ib = p->ib.ptr; 63862306a36Sopenharmony_ci track = (struct r100_cs_track *)p->track; 63962306a36Sopenharmony_ci idx_value = radeon_get_ib_value(p, idx); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci switch (reg) { 64262306a36Sopenharmony_ci case AVIVO_D1MODE_VLINE_START_END: 64362306a36Sopenharmony_ci case RADEON_CRTC_GUI_TRIG_VLINE: 64462306a36Sopenharmony_ci r = r100_cs_packet_parse_vline(p); 64562306a36Sopenharmony_ci if (r) { 64662306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 64762306a36Sopenharmony_ci idx, reg); 64862306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 64962306a36Sopenharmony_ci return r; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci break; 65262306a36Sopenharmony_ci case RADEON_DST_PITCH_OFFSET: 65362306a36Sopenharmony_ci case RADEON_SRC_PITCH_OFFSET: 65462306a36Sopenharmony_ci r = r100_reloc_pitch_offset(p, pkt, idx, reg); 65562306a36Sopenharmony_ci if (r) 65662306a36Sopenharmony_ci return r; 65762306a36Sopenharmony_ci break; 65862306a36Sopenharmony_ci case R300_RB3D_COLOROFFSET0: 65962306a36Sopenharmony_ci case R300_RB3D_COLOROFFSET1: 66062306a36Sopenharmony_ci case R300_RB3D_COLOROFFSET2: 66162306a36Sopenharmony_ci case R300_RB3D_COLOROFFSET3: 66262306a36Sopenharmony_ci i = (reg - R300_RB3D_COLOROFFSET0) >> 2; 66362306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 66462306a36Sopenharmony_ci if (r) { 66562306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 66662306a36Sopenharmony_ci idx, reg); 66762306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 66862306a36Sopenharmony_ci return r; 66962306a36Sopenharmony_ci } 67062306a36Sopenharmony_ci track->cb[i].robj = reloc->robj; 67162306a36Sopenharmony_ci track->cb[i].offset = idx_value; 67262306a36Sopenharmony_ci track->cb_dirty = true; 67362306a36Sopenharmony_ci ib[idx] = idx_value + ((u32)reloc->gpu_offset); 67462306a36Sopenharmony_ci break; 67562306a36Sopenharmony_ci case R300_ZB_DEPTHOFFSET: 67662306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 67762306a36Sopenharmony_ci if (r) { 67862306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 67962306a36Sopenharmony_ci idx, reg); 68062306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 68162306a36Sopenharmony_ci return r; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci track->zb.robj = reloc->robj; 68462306a36Sopenharmony_ci track->zb.offset = idx_value; 68562306a36Sopenharmony_ci track->zb_dirty = true; 68662306a36Sopenharmony_ci ib[idx] = idx_value + ((u32)reloc->gpu_offset); 68762306a36Sopenharmony_ci break; 68862306a36Sopenharmony_ci case R300_TX_OFFSET_0: 68962306a36Sopenharmony_ci case R300_TX_OFFSET_0+4: 69062306a36Sopenharmony_ci case R300_TX_OFFSET_0+8: 69162306a36Sopenharmony_ci case R300_TX_OFFSET_0+12: 69262306a36Sopenharmony_ci case R300_TX_OFFSET_0+16: 69362306a36Sopenharmony_ci case R300_TX_OFFSET_0+20: 69462306a36Sopenharmony_ci case R300_TX_OFFSET_0+24: 69562306a36Sopenharmony_ci case R300_TX_OFFSET_0+28: 69662306a36Sopenharmony_ci case R300_TX_OFFSET_0+32: 69762306a36Sopenharmony_ci case R300_TX_OFFSET_0+36: 69862306a36Sopenharmony_ci case R300_TX_OFFSET_0+40: 69962306a36Sopenharmony_ci case R300_TX_OFFSET_0+44: 70062306a36Sopenharmony_ci case R300_TX_OFFSET_0+48: 70162306a36Sopenharmony_ci case R300_TX_OFFSET_0+52: 70262306a36Sopenharmony_ci case R300_TX_OFFSET_0+56: 70362306a36Sopenharmony_ci case R300_TX_OFFSET_0+60: 70462306a36Sopenharmony_ci i = (reg - R300_TX_OFFSET_0) >> 2; 70562306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 70662306a36Sopenharmony_ci if (r) { 70762306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 70862306a36Sopenharmony_ci idx, reg); 70962306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 71062306a36Sopenharmony_ci return r; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci if (p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) { 71462306a36Sopenharmony_ci ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */ 71562306a36Sopenharmony_ci ((idx_value & ~31) + (u32)reloc->gpu_offset); 71662306a36Sopenharmony_ci } else { 71762306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) 71862306a36Sopenharmony_ci tile_flags |= R300_TXO_MACRO_TILE; 71962306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MICRO) 72062306a36Sopenharmony_ci tile_flags |= R300_TXO_MICRO_TILE; 72162306a36Sopenharmony_ci else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE) 72262306a36Sopenharmony_ci tile_flags |= R300_TXO_MICRO_TILE_SQUARE; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci tmp = idx_value + ((u32)reloc->gpu_offset); 72562306a36Sopenharmony_ci tmp |= tile_flags; 72662306a36Sopenharmony_ci ib[idx] = tmp; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci track->textures[i].robj = reloc->robj; 72962306a36Sopenharmony_ci track->tex_dirty = true; 73062306a36Sopenharmony_ci break; 73162306a36Sopenharmony_ci /* Tracked registers */ 73262306a36Sopenharmony_ci case 0x2084: 73362306a36Sopenharmony_ci /* VAP_VF_CNTL */ 73462306a36Sopenharmony_ci track->vap_vf_cntl = idx_value; 73562306a36Sopenharmony_ci break; 73662306a36Sopenharmony_ci case 0x20B4: 73762306a36Sopenharmony_ci /* VAP_VTX_SIZE */ 73862306a36Sopenharmony_ci track->vtx_size = idx_value & 0x7F; 73962306a36Sopenharmony_ci break; 74062306a36Sopenharmony_ci case 0x2134: 74162306a36Sopenharmony_ci /* VAP_VF_MAX_VTX_INDX */ 74262306a36Sopenharmony_ci track->max_indx = idx_value & 0x00FFFFFFUL; 74362306a36Sopenharmony_ci break; 74462306a36Sopenharmony_ci case 0x2088: 74562306a36Sopenharmony_ci /* VAP_ALT_NUM_VERTICES - only valid on r500 */ 74662306a36Sopenharmony_ci if (p->rdev->family < CHIP_RV515) 74762306a36Sopenharmony_ci goto fail; 74862306a36Sopenharmony_ci track->vap_alt_nverts = idx_value & 0xFFFFFF; 74962306a36Sopenharmony_ci break; 75062306a36Sopenharmony_ci case 0x43E4: 75162306a36Sopenharmony_ci /* SC_SCISSOR1 */ 75262306a36Sopenharmony_ci track->maxy = ((idx_value >> 13) & 0x1FFF) + 1; 75362306a36Sopenharmony_ci if (p->rdev->family < CHIP_RV515) { 75462306a36Sopenharmony_ci track->maxy -= 1440; 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci track->cb_dirty = true; 75762306a36Sopenharmony_ci track->zb_dirty = true; 75862306a36Sopenharmony_ci break; 75962306a36Sopenharmony_ci case 0x4E00: 76062306a36Sopenharmony_ci /* RB3D_CCTL */ 76162306a36Sopenharmony_ci if ((idx_value & (1 << 10)) && /* CMASK_ENABLE */ 76262306a36Sopenharmony_ci p->rdev->cmask_filp != p->filp) { 76362306a36Sopenharmony_ci DRM_ERROR("Invalid RB3D_CCTL: Cannot enable CMASK.\n"); 76462306a36Sopenharmony_ci return -EINVAL; 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci track->num_cb = ((idx_value >> 5) & 0x3) + 1; 76762306a36Sopenharmony_ci track->cb_dirty = true; 76862306a36Sopenharmony_ci break; 76962306a36Sopenharmony_ci case 0x4E38: 77062306a36Sopenharmony_ci case 0x4E3C: 77162306a36Sopenharmony_ci case 0x4E40: 77262306a36Sopenharmony_ci case 0x4E44: 77362306a36Sopenharmony_ci /* RB3D_COLORPITCH0 */ 77462306a36Sopenharmony_ci /* RB3D_COLORPITCH1 */ 77562306a36Sopenharmony_ci /* RB3D_COLORPITCH2 */ 77662306a36Sopenharmony_ci /* RB3D_COLORPITCH3 */ 77762306a36Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 77862306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 77962306a36Sopenharmony_ci if (r) { 78062306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 78162306a36Sopenharmony_ci idx, reg); 78262306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 78362306a36Sopenharmony_ci return r; 78462306a36Sopenharmony_ci } 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) 78762306a36Sopenharmony_ci tile_flags |= R300_COLOR_TILE_ENABLE; 78862306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MICRO) 78962306a36Sopenharmony_ci tile_flags |= R300_COLOR_MICROTILE_ENABLE; 79062306a36Sopenharmony_ci else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE) 79162306a36Sopenharmony_ci tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci tmp = idx_value & ~(0x7 << 16); 79462306a36Sopenharmony_ci tmp |= tile_flags; 79562306a36Sopenharmony_ci ib[idx] = tmp; 79662306a36Sopenharmony_ci } 79762306a36Sopenharmony_ci i = (reg - 0x4E38) >> 2; 79862306a36Sopenharmony_ci track->cb[i].pitch = idx_value & 0x3FFE; 79962306a36Sopenharmony_ci switch (((idx_value >> 21) & 0xF)) { 80062306a36Sopenharmony_ci case 9: 80162306a36Sopenharmony_ci case 11: 80262306a36Sopenharmony_ci case 12: 80362306a36Sopenharmony_ci track->cb[i].cpp = 1; 80462306a36Sopenharmony_ci break; 80562306a36Sopenharmony_ci case 3: 80662306a36Sopenharmony_ci case 4: 80762306a36Sopenharmony_ci case 13: 80862306a36Sopenharmony_ci case 15: 80962306a36Sopenharmony_ci track->cb[i].cpp = 2; 81062306a36Sopenharmony_ci break; 81162306a36Sopenharmony_ci case 5: 81262306a36Sopenharmony_ci if (p->rdev->family < CHIP_RV515) { 81362306a36Sopenharmony_ci DRM_ERROR("Invalid color buffer format (%d)!\n", 81462306a36Sopenharmony_ci ((idx_value >> 21) & 0xF)); 81562306a36Sopenharmony_ci return -EINVAL; 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci fallthrough; 81862306a36Sopenharmony_ci case 6: 81962306a36Sopenharmony_ci track->cb[i].cpp = 4; 82062306a36Sopenharmony_ci break; 82162306a36Sopenharmony_ci case 10: 82262306a36Sopenharmony_ci track->cb[i].cpp = 8; 82362306a36Sopenharmony_ci break; 82462306a36Sopenharmony_ci case 7: 82562306a36Sopenharmony_ci track->cb[i].cpp = 16; 82662306a36Sopenharmony_ci break; 82762306a36Sopenharmony_ci default: 82862306a36Sopenharmony_ci DRM_ERROR("Invalid color buffer format (%d) !\n", 82962306a36Sopenharmony_ci ((idx_value >> 21) & 0xF)); 83062306a36Sopenharmony_ci return -EINVAL; 83162306a36Sopenharmony_ci } 83262306a36Sopenharmony_ci track->cb_dirty = true; 83362306a36Sopenharmony_ci break; 83462306a36Sopenharmony_ci case 0x4F00: 83562306a36Sopenharmony_ci /* ZB_CNTL */ 83662306a36Sopenharmony_ci if (idx_value & 2) { 83762306a36Sopenharmony_ci track->z_enabled = true; 83862306a36Sopenharmony_ci } else { 83962306a36Sopenharmony_ci track->z_enabled = false; 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci track->zb_dirty = true; 84262306a36Sopenharmony_ci break; 84362306a36Sopenharmony_ci case 0x4F10: 84462306a36Sopenharmony_ci /* ZB_FORMAT */ 84562306a36Sopenharmony_ci switch ((idx_value & 0xF)) { 84662306a36Sopenharmony_ci case 0: 84762306a36Sopenharmony_ci case 1: 84862306a36Sopenharmony_ci track->zb.cpp = 2; 84962306a36Sopenharmony_ci break; 85062306a36Sopenharmony_ci case 2: 85162306a36Sopenharmony_ci track->zb.cpp = 4; 85262306a36Sopenharmony_ci break; 85362306a36Sopenharmony_ci default: 85462306a36Sopenharmony_ci DRM_ERROR("Invalid z buffer format (%d) !\n", 85562306a36Sopenharmony_ci (idx_value & 0xF)); 85662306a36Sopenharmony_ci return -EINVAL; 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci track->zb_dirty = true; 85962306a36Sopenharmony_ci break; 86062306a36Sopenharmony_ci case 0x4F24: 86162306a36Sopenharmony_ci /* ZB_DEPTHPITCH */ 86262306a36Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 86362306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 86462306a36Sopenharmony_ci if (r) { 86562306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 86662306a36Sopenharmony_ci idx, reg); 86762306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 86862306a36Sopenharmony_ci return r; 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) 87262306a36Sopenharmony_ci tile_flags |= R300_DEPTHMACROTILE_ENABLE; 87362306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MICRO) 87462306a36Sopenharmony_ci tile_flags |= R300_DEPTHMICROTILE_TILED; 87562306a36Sopenharmony_ci else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE) 87662306a36Sopenharmony_ci tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci tmp = idx_value & ~(0x7 << 16); 87962306a36Sopenharmony_ci tmp |= tile_flags; 88062306a36Sopenharmony_ci ib[idx] = tmp; 88162306a36Sopenharmony_ci } 88262306a36Sopenharmony_ci track->zb.pitch = idx_value & 0x3FFC; 88362306a36Sopenharmony_ci track->zb_dirty = true; 88462306a36Sopenharmony_ci break; 88562306a36Sopenharmony_ci case 0x4104: 88662306a36Sopenharmony_ci /* TX_ENABLE */ 88762306a36Sopenharmony_ci for (i = 0; i < 16; i++) { 88862306a36Sopenharmony_ci bool enabled; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci enabled = !!(idx_value & (1 << i)); 89162306a36Sopenharmony_ci track->textures[i].enabled = enabled; 89262306a36Sopenharmony_ci } 89362306a36Sopenharmony_ci track->tex_dirty = true; 89462306a36Sopenharmony_ci break; 89562306a36Sopenharmony_ci case 0x44C0: 89662306a36Sopenharmony_ci case 0x44C4: 89762306a36Sopenharmony_ci case 0x44C8: 89862306a36Sopenharmony_ci case 0x44CC: 89962306a36Sopenharmony_ci case 0x44D0: 90062306a36Sopenharmony_ci case 0x44D4: 90162306a36Sopenharmony_ci case 0x44D8: 90262306a36Sopenharmony_ci case 0x44DC: 90362306a36Sopenharmony_ci case 0x44E0: 90462306a36Sopenharmony_ci case 0x44E4: 90562306a36Sopenharmony_ci case 0x44E8: 90662306a36Sopenharmony_ci case 0x44EC: 90762306a36Sopenharmony_ci case 0x44F0: 90862306a36Sopenharmony_ci case 0x44F4: 90962306a36Sopenharmony_ci case 0x44F8: 91062306a36Sopenharmony_ci case 0x44FC: 91162306a36Sopenharmony_ci /* TX_FORMAT1_[0-15] */ 91262306a36Sopenharmony_ci i = (reg - 0x44C0) >> 2; 91362306a36Sopenharmony_ci tmp = (idx_value >> 25) & 0x3; 91462306a36Sopenharmony_ci track->textures[i].tex_coord_type = tmp; 91562306a36Sopenharmony_ci switch ((idx_value & 0x1F)) { 91662306a36Sopenharmony_ci case R300_TX_FORMAT_X8: 91762306a36Sopenharmony_ci case R300_TX_FORMAT_Y4X4: 91862306a36Sopenharmony_ci case R300_TX_FORMAT_Z3Y3X2: 91962306a36Sopenharmony_ci track->textures[i].cpp = 1; 92062306a36Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 92162306a36Sopenharmony_ci break; 92262306a36Sopenharmony_ci case R300_TX_FORMAT_X16: 92362306a36Sopenharmony_ci case R300_TX_FORMAT_FL_I16: 92462306a36Sopenharmony_ci case R300_TX_FORMAT_Y8X8: 92562306a36Sopenharmony_ci case R300_TX_FORMAT_Z5Y6X5: 92662306a36Sopenharmony_ci case R300_TX_FORMAT_Z6Y5X5: 92762306a36Sopenharmony_ci case R300_TX_FORMAT_W4Z4Y4X4: 92862306a36Sopenharmony_ci case R300_TX_FORMAT_W1Z5Y5X5: 92962306a36Sopenharmony_ci case R300_TX_FORMAT_D3DMFT_CxV8U8: 93062306a36Sopenharmony_ci case R300_TX_FORMAT_B8G8_B8G8: 93162306a36Sopenharmony_ci case R300_TX_FORMAT_G8R8_G8B8: 93262306a36Sopenharmony_ci track->textures[i].cpp = 2; 93362306a36Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 93462306a36Sopenharmony_ci break; 93562306a36Sopenharmony_ci case R300_TX_FORMAT_Y16X16: 93662306a36Sopenharmony_ci case R300_TX_FORMAT_FL_I16A16: 93762306a36Sopenharmony_ci case R300_TX_FORMAT_Z11Y11X10: 93862306a36Sopenharmony_ci case R300_TX_FORMAT_Z10Y11X11: 93962306a36Sopenharmony_ci case R300_TX_FORMAT_W8Z8Y8X8: 94062306a36Sopenharmony_ci case R300_TX_FORMAT_W2Z10Y10X10: 94162306a36Sopenharmony_ci case 0x17: 94262306a36Sopenharmony_ci case R300_TX_FORMAT_FL_I32: 94362306a36Sopenharmony_ci case 0x1e: 94462306a36Sopenharmony_ci track->textures[i].cpp = 4; 94562306a36Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 94662306a36Sopenharmony_ci break; 94762306a36Sopenharmony_ci case R300_TX_FORMAT_W16Z16Y16X16: 94862306a36Sopenharmony_ci case R300_TX_FORMAT_FL_R16G16B16A16: 94962306a36Sopenharmony_ci case R300_TX_FORMAT_FL_I32A32: 95062306a36Sopenharmony_ci track->textures[i].cpp = 8; 95162306a36Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 95262306a36Sopenharmony_ci break; 95362306a36Sopenharmony_ci case R300_TX_FORMAT_FL_R32G32B32A32: 95462306a36Sopenharmony_ci track->textures[i].cpp = 16; 95562306a36Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 95662306a36Sopenharmony_ci break; 95762306a36Sopenharmony_ci case R300_TX_FORMAT_DXT1: 95862306a36Sopenharmony_ci track->textures[i].cpp = 1; 95962306a36Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_DXT1; 96062306a36Sopenharmony_ci break; 96162306a36Sopenharmony_ci case R300_TX_FORMAT_ATI2N: 96262306a36Sopenharmony_ci if (p->rdev->family < CHIP_R420) { 96362306a36Sopenharmony_ci DRM_ERROR("Invalid texture format %u\n", 96462306a36Sopenharmony_ci (idx_value & 0x1F)); 96562306a36Sopenharmony_ci return -EINVAL; 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci /* The same rules apply as for DXT3/5. */ 96862306a36Sopenharmony_ci fallthrough; 96962306a36Sopenharmony_ci case R300_TX_FORMAT_DXT3: 97062306a36Sopenharmony_ci case R300_TX_FORMAT_DXT5: 97162306a36Sopenharmony_ci track->textures[i].cpp = 1; 97262306a36Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_DXT35; 97362306a36Sopenharmony_ci break; 97462306a36Sopenharmony_ci default: 97562306a36Sopenharmony_ci DRM_ERROR("Invalid texture format %u\n", 97662306a36Sopenharmony_ci (idx_value & 0x1F)); 97762306a36Sopenharmony_ci return -EINVAL; 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci track->tex_dirty = true; 98062306a36Sopenharmony_ci break; 98162306a36Sopenharmony_ci case 0x4400: 98262306a36Sopenharmony_ci case 0x4404: 98362306a36Sopenharmony_ci case 0x4408: 98462306a36Sopenharmony_ci case 0x440C: 98562306a36Sopenharmony_ci case 0x4410: 98662306a36Sopenharmony_ci case 0x4414: 98762306a36Sopenharmony_ci case 0x4418: 98862306a36Sopenharmony_ci case 0x441C: 98962306a36Sopenharmony_ci case 0x4420: 99062306a36Sopenharmony_ci case 0x4424: 99162306a36Sopenharmony_ci case 0x4428: 99262306a36Sopenharmony_ci case 0x442C: 99362306a36Sopenharmony_ci case 0x4430: 99462306a36Sopenharmony_ci case 0x4434: 99562306a36Sopenharmony_ci case 0x4438: 99662306a36Sopenharmony_ci case 0x443C: 99762306a36Sopenharmony_ci /* TX_FILTER0_[0-15] */ 99862306a36Sopenharmony_ci i = (reg - 0x4400) >> 2; 99962306a36Sopenharmony_ci tmp = idx_value & 0x7; 100062306a36Sopenharmony_ci if (tmp == 2 || tmp == 4 || tmp == 6) { 100162306a36Sopenharmony_ci track->textures[i].roundup_w = false; 100262306a36Sopenharmony_ci } 100362306a36Sopenharmony_ci tmp = (idx_value >> 3) & 0x7; 100462306a36Sopenharmony_ci if (tmp == 2 || tmp == 4 || tmp == 6) { 100562306a36Sopenharmony_ci track->textures[i].roundup_h = false; 100662306a36Sopenharmony_ci } 100762306a36Sopenharmony_ci track->tex_dirty = true; 100862306a36Sopenharmony_ci break; 100962306a36Sopenharmony_ci case 0x4500: 101062306a36Sopenharmony_ci case 0x4504: 101162306a36Sopenharmony_ci case 0x4508: 101262306a36Sopenharmony_ci case 0x450C: 101362306a36Sopenharmony_ci case 0x4510: 101462306a36Sopenharmony_ci case 0x4514: 101562306a36Sopenharmony_ci case 0x4518: 101662306a36Sopenharmony_ci case 0x451C: 101762306a36Sopenharmony_ci case 0x4520: 101862306a36Sopenharmony_ci case 0x4524: 101962306a36Sopenharmony_ci case 0x4528: 102062306a36Sopenharmony_ci case 0x452C: 102162306a36Sopenharmony_ci case 0x4530: 102262306a36Sopenharmony_ci case 0x4534: 102362306a36Sopenharmony_ci case 0x4538: 102462306a36Sopenharmony_ci case 0x453C: 102562306a36Sopenharmony_ci /* TX_FORMAT2_[0-15] */ 102662306a36Sopenharmony_ci i = (reg - 0x4500) >> 2; 102762306a36Sopenharmony_ci tmp = idx_value & 0x3FFF; 102862306a36Sopenharmony_ci track->textures[i].pitch = tmp + 1; 102962306a36Sopenharmony_ci if (p->rdev->family >= CHIP_RV515) { 103062306a36Sopenharmony_ci tmp = ((idx_value >> 15) & 1) << 11; 103162306a36Sopenharmony_ci track->textures[i].width_11 = tmp; 103262306a36Sopenharmony_ci tmp = ((idx_value >> 16) & 1) << 11; 103362306a36Sopenharmony_ci track->textures[i].height_11 = tmp; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci /* ATI1N */ 103662306a36Sopenharmony_ci if (idx_value & (1 << 14)) { 103762306a36Sopenharmony_ci /* The same rules apply as for DXT1. */ 103862306a36Sopenharmony_ci track->textures[i].compress_format = 103962306a36Sopenharmony_ci R100_TRACK_COMP_DXT1; 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci } else if (idx_value & (1 << 14)) { 104262306a36Sopenharmony_ci DRM_ERROR("Forbidden bit TXFORMAT_MSB\n"); 104362306a36Sopenharmony_ci return -EINVAL; 104462306a36Sopenharmony_ci } 104562306a36Sopenharmony_ci track->tex_dirty = true; 104662306a36Sopenharmony_ci break; 104762306a36Sopenharmony_ci case 0x4480: 104862306a36Sopenharmony_ci case 0x4484: 104962306a36Sopenharmony_ci case 0x4488: 105062306a36Sopenharmony_ci case 0x448C: 105162306a36Sopenharmony_ci case 0x4490: 105262306a36Sopenharmony_ci case 0x4494: 105362306a36Sopenharmony_ci case 0x4498: 105462306a36Sopenharmony_ci case 0x449C: 105562306a36Sopenharmony_ci case 0x44A0: 105662306a36Sopenharmony_ci case 0x44A4: 105762306a36Sopenharmony_ci case 0x44A8: 105862306a36Sopenharmony_ci case 0x44AC: 105962306a36Sopenharmony_ci case 0x44B0: 106062306a36Sopenharmony_ci case 0x44B4: 106162306a36Sopenharmony_ci case 0x44B8: 106262306a36Sopenharmony_ci case 0x44BC: 106362306a36Sopenharmony_ci /* TX_FORMAT0_[0-15] */ 106462306a36Sopenharmony_ci i = (reg - 0x4480) >> 2; 106562306a36Sopenharmony_ci tmp = idx_value & 0x7FF; 106662306a36Sopenharmony_ci track->textures[i].width = tmp + 1; 106762306a36Sopenharmony_ci tmp = (idx_value >> 11) & 0x7FF; 106862306a36Sopenharmony_ci track->textures[i].height = tmp + 1; 106962306a36Sopenharmony_ci tmp = (idx_value >> 26) & 0xF; 107062306a36Sopenharmony_ci track->textures[i].num_levels = tmp; 107162306a36Sopenharmony_ci tmp = idx_value & (1 << 31); 107262306a36Sopenharmony_ci track->textures[i].use_pitch = !!tmp; 107362306a36Sopenharmony_ci tmp = (idx_value >> 22) & 0xF; 107462306a36Sopenharmony_ci track->textures[i].txdepth = tmp; 107562306a36Sopenharmony_ci track->tex_dirty = true; 107662306a36Sopenharmony_ci break; 107762306a36Sopenharmony_ci case R300_ZB_ZPASS_ADDR: 107862306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 107962306a36Sopenharmony_ci if (r) { 108062306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 108162306a36Sopenharmony_ci idx, reg); 108262306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 108362306a36Sopenharmony_ci return r; 108462306a36Sopenharmony_ci } 108562306a36Sopenharmony_ci ib[idx] = idx_value + ((u32)reloc->gpu_offset); 108662306a36Sopenharmony_ci break; 108762306a36Sopenharmony_ci case 0x4e0c: 108862306a36Sopenharmony_ci /* RB3D_COLOR_CHANNEL_MASK */ 108962306a36Sopenharmony_ci track->color_channel_mask = idx_value; 109062306a36Sopenharmony_ci track->cb_dirty = true; 109162306a36Sopenharmony_ci break; 109262306a36Sopenharmony_ci case 0x43a4: 109362306a36Sopenharmony_ci /* SC_HYPERZ_EN */ 109462306a36Sopenharmony_ci /* r300c emits this register - we need to disable hyperz for it 109562306a36Sopenharmony_ci * without complaining */ 109662306a36Sopenharmony_ci if (p->rdev->hyperz_filp != p->filp) { 109762306a36Sopenharmony_ci if (idx_value & 0x1) 109862306a36Sopenharmony_ci ib[idx] = idx_value & ~1; 109962306a36Sopenharmony_ci } 110062306a36Sopenharmony_ci break; 110162306a36Sopenharmony_ci case 0x4f1c: 110262306a36Sopenharmony_ci /* ZB_BW_CNTL */ 110362306a36Sopenharmony_ci track->zb_cb_clear = !!(idx_value & (1 << 5)); 110462306a36Sopenharmony_ci track->cb_dirty = true; 110562306a36Sopenharmony_ci track->zb_dirty = true; 110662306a36Sopenharmony_ci if (p->rdev->hyperz_filp != p->filp) { 110762306a36Sopenharmony_ci if (idx_value & (R300_HIZ_ENABLE | 110862306a36Sopenharmony_ci R300_RD_COMP_ENABLE | 110962306a36Sopenharmony_ci R300_WR_COMP_ENABLE | 111062306a36Sopenharmony_ci R300_FAST_FILL_ENABLE)) 111162306a36Sopenharmony_ci goto fail; 111262306a36Sopenharmony_ci } 111362306a36Sopenharmony_ci break; 111462306a36Sopenharmony_ci case 0x4e04: 111562306a36Sopenharmony_ci /* RB3D_BLENDCNTL */ 111662306a36Sopenharmony_ci track->blend_read_enable = !!(idx_value & (1 << 2)); 111762306a36Sopenharmony_ci track->cb_dirty = true; 111862306a36Sopenharmony_ci break; 111962306a36Sopenharmony_ci case R300_RB3D_AARESOLVE_OFFSET: 112062306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 112162306a36Sopenharmony_ci if (r) { 112262306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 112362306a36Sopenharmony_ci idx, reg); 112462306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 112562306a36Sopenharmony_ci return r; 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci track->aa.robj = reloc->robj; 112862306a36Sopenharmony_ci track->aa.offset = idx_value; 112962306a36Sopenharmony_ci track->aa_dirty = true; 113062306a36Sopenharmony_ci ib[idx] = idx_value + ((u32)reloc->gpu_offset); 113162306a36Sopenharmony_ci break; 113262306a36Sopenharmony_ci case R300_RB3D_AARESOLVE_PITCH: 113362306a36Sopenharmony_ci track->aa.pitch = idx_value & 0x3FFE; 113462306a36Sopenharmony_ci track->aa_dirty = true; 113562306a36Sopenharmony_ci break; 113662306a36Sopenharmony_ci case R300_RB3D_AARESOLVE_CTL: 113762306a36Sopenharmony_ci track->aaresolve = idx_value & 0x1; 113862306a36Sopenharmony_ci track->aa_dirty = true; 113962306a36Sopenharmony_ci break; 114062306a36Sopenharmony_ci case 0x4f30: /* ZB_MASK_OFFSET */ 114162306a36Sopenharmony_ci case 0x4f34: /* ZB_ZMASK_PITCH */ 114262306a36Sopenharmony_ci case 0x4f44: /* ZB_HIZ_OFFSET */ 114362306a36Sopenharmony_ci case 0x4f54: /* ZB_HIZ_PITCH */ 114462306a36Sopenharmony_ci if (idx_value && (p->rdev->hyperz_filp != p->filp)) 114562306a36Sopenharmony_ci goto fail; 114662306a36Sopenharmony_ci break; 114762306a36Sopenharmony_ci case 0x4028: 114862306a36Sopenharmony_ci if (idx_value && (p->rdev->hyperz_filp != p->filp)) 114962306a36Sopenharmony_ci goto fail; 115062306a36Sopenharmony_ci /* GB_Z_PEQ_CONFIG */ 115162306a36Sopenharmony_ci if (p->rdev->family >= CHIP_RV350) 115262306a36Sopenharmony_ci break; 115362306a36Sopenharmony_ci goto fail; 115462306a36Sopenharmony_ci break; 115562306a36Sopenharmony_ci case 0x4be8: 115662306a36Sopenharmony_ci /* valid register only on RV530 */ 115762306a36Sopenharmony_ci if (p->rdev->family == CHIP_RV530) 115862306a36Sopenharmony_ci break; 115962306a36Sopenharmony_ci fallthrough; 116062306a36Sopenharmony_ci /* fallthrough do not move */ 116162306a36Sopenharmony_ci default: 116262306a36Sopenharmony_ci goto fail; 116362306a36Sopenharmony_ci } 116462306a36Sopenharmony_ci return 0; 116562306a36Sopenharmony_cifail: 116662306a36Sopenharmony_ci pr_err("Forbidden register 0x%04X in cs at %d (val=%08x)\n", 116762306a36Sopenharmony_ci reg, idx, idx_value); 116862306a36Sopenharmony_ci return -EINVAL; 116962306a36Sopenharmony_ci} 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_cistatic int r300_packet3_check(struct radeon_cs_parser *p, 117262306a36Sopenharmony_ci struct radeon_cs_packet *pkt) 117362306a36Sopenharmony_ci{ 117462306a36Sopenharmony_ci struct radeon_bo_list *reloc; 117562306a36Sopenharmony_ci struct r100_cs_track *track; 117662306a36Sopenharmony_ci volatile uint32_t *ib; 117762306a36Sopenharmony_ci unsigned idx; 117862306a36Sopenharmony_ci int r; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci ib = p->ib.ptr; 118162306a36Sopenharmony_ci idx = pkt->idx + 1; 118262306a36Sopenharmony_ci track = (struct r100_cs_track *)p->track; 118362306a36Sopenharmony_ci switch (pkt->opcode) { 118462306a36Sopenharmony_ci case PACKET3_3D_LOAD_VBPNTR: 118562306a36Sopenharmony_ci r = r100_packet3_load_vbpntr(p, pkt, idx); 118662306a36Sopenharmony_ci if (r) 118762306a36Sopenharmony_ci return r; 118862306a36Sopenharmony_ci break; 118962306a36Sopenharmony_ci case PACKET3_INDX_BUFFER: 119062306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 119162306a36Sopenharmony_ci if (r) { 119262306a36Sopenharmony_ci DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 119362306a36Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 119462306a36Sopenharmony_ci return r; 119562306a36Sopenharmony_ci } 119662306a36Sopenharmony_ci ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->gpu_offset); 119762306a36Sopenharmony_ci r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); 119862306a36Sopenharmony_ci if (r) { 119962306a36Sopenharmony_ci return r; 120062306a36Sopenharmony_ci } 120162306a36Sopenharmony_ci break; 120262306a36Sopenharmony_ci /* Draw packet */ 120362306a36Sopenharmony_ci case PACKET3_3D_DRAW_IMMD: 120462306a36Sopenharmony_ci /* Number of dwords is vtx_size * (num_vertices - 1) 120562306a36Sopenharmony_ci * PRIM_WALK must be equal to 3 vertex data in embedded 120662306a36Sopenharmony_ci * in cmd stream */ 120762306a36Sopenharmony_ci if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) { 120862306a36Sopenharmony_ci DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); 120962306a36Sopenharmony_ci return -EINVAL; 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 121262306a36Sopenharmony_ci track->immd_dwords = pkt->count - 1; 121362306a36Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 121462306a36Sopenharmony_ci if (r) { 121562306a36Sopenharmony_ci return r; 121662306a36Sopenharmony_ci } 121762306a36Sopenharmony_ci break; 121862306a36Sopenharmony_ci case PACKET3_3D_DRAW_IMMD_2: 121962306a36Sopenharmony_ci /* Number of dwords is vtx_size * (num_vertices - 1) 122062306a36Sopenharmony_ci * PRIM_WALK must be equal to 3 vertex data in embedded 122162306a36Sopenharmony_ci * in cmd stream */ 122262306a36Sopenharmony_ci if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) { 122362306a36Sopenharmony_ci DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); 122462306a36Sopenharmony_ci return -EINVAL; 122562306a36Sopenharmony_ci } 122662306a36Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx); 122762306a36Sopenharmony_ci track->immd_dwords = pkt->count; 122862306a36Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 122962306a36Sopenharmony_ci if (r) { 123062306a36Sopenharmony_ci return r; 123162306a36Sopenharmony_ci } 123262306a36Sopenharmony_ci break; 123362306a36Sopenharmony_ci case PACKET3_3D_DRAW_VBUF: 123462306a36Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 123562306a36Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 123662306a36Sopenharmony_ci if (r) { 123762306a36Sopenharmony_ci return r; 123862306a36Sopenharmony_ci } 123962306a36Sopenharmony_ci break; 124062306a36Sopenharmony_ci case PACKET3_3D_DRAW_VBUF_2: 124162306a36Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx); 124262306a36Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 124362306a36Sopenharmony_ci if (r) { 124462306a36Sopenharmony_ci return r; 124562306a36Sopenharmony_ci } 124662306a36Sopenharmony_ci break; 124762306a36Sopenharmony_ci case PACKET3_3D_DRAW_INDX: 124862306a36Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 124962306a36Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 125062306a36Sopenharmony_ci if (r) { 125162306a36Sopenharmony_ci return r; 125262306a36Sopenharmony_ci } 125362306a36Sopenharmony_ci break; 125462306a36Sopenharmony_ci case PACKET3_3D_DRAW_INDX_2: 125562306a36Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx); 125662306a36Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 125762306a36Sopenharmony_ci if (r) { 125862306a36Sopenharmony_ci return r; 125962306a36Sopenharmony_ci } 126062306a36Sopenharmony_ci break; 126162306a36Sopenharmony_ci case PACKET3_3D_CLEAR_HIZ: 126262306a36Sopenharmony_ci case PACKET3_3D_CLEAR_ZMASK: 126362306a36Sopenharmony_ci if (p->rdev->hyperz_filp != p->filp) 126462306a36Sopenharmony_ci return -EINVAL; 126562306a36Sopenharmony_ci break; 126662306a36Sopenharmony_ci case PACKET3_3D_CLEAR_CMASK: 126762306a36Sopenharmony_ci if (p->rdev->cmask_filp != p->filp) 126862306a36Sopenharmony_ci return -EINVAL; 126962306a36Sopenharmony_ci break; 127062306a36Sopenharmony_ci case PACKET3_NOP: 127162306a36Sopenharmony_ci break; 127262306a36Sopenharmony_ci default: 127362306a36Sopenharmony_ci DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 127462306a36Sopenharmony_ci return -EINVAL; 127562306a36Sopenharmony_ci } 127662306a36Sopenharmony_ci return 0; 127762306a36Sopenharmony_ci} 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ciint r300_cs_parse(struct radeon_cs_parser *p) 128062306a36Sopenharmony_ci{ 128162306a36Sopenharmony_ci struct radeon_cs_packet pkt; 128262306a36Sopenharmony_ci struct r100_cs_track *track; 128362306a36Sopenharmony_ci int r; 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci track = kzalloc(sizeof(*track), GFP_KERNEL); 128662306a36Sopenharmony_ci if (track == NULL) 128762306a36Sopenharmony_ci return -ENOMEM; 128862306a36Sopenharmony_ci r100_cs_track_clear(p->rdev, track); 128962306a36Sopenharmony_ci p->track = track; 129062306a36Sopenharmony_ci do { 129162306a36Sopenharmony_ci r = radeon_cs_packet_parse(p, &pkt, p->idx); 129262306a36Sopenharmony_ci if (r) { 129362306a36Sopenharmony_ci return r; 129462306a36Sopenharmony_ci } 129562306a36Sopenharmony_ci p->idx += pkt.count + 2; 129662306a36Sopenharmony_ci switch (pkt.type) { 129762306a36Sopenharmony_ci case RADEON_PACKET_TYPE0: 129862306a36Sopenharmony_ci r = r100_cs_parse_packet0(p, &pkt, 129962306a36Sopenharmony_ci p->rdev->config.r300.reg_safe_bm, 130062306a36Sopenharmony_ci p->rdev->config.r300.reg_safe_bm_size, 130162306a36Sopenharmony_ci &r300_packet0_check); 130262306a36Sopenharmony_ci break; 130362306a36Sopenharmony_ci case RADEON_PACKET_TYPE2: 130462306a36Sopenharmony_ci break; 130562306a36Sopenharmony_ci case RADEON_PACKET_TYPE3: 130662306a36Sopenharmony_ci r = r300_packet3_check(p, &pkt); 130762306a36Sopenharmony_ci break; 130862306a36Sopenharmony_ci default: 130962306a36Sopenharmony_ci DRM_ERROR("Unknown packet type %d !\n", pkt.type); 131062306a36Sopenharmony_ci return -EINVAL; 131162306a36Sopenharmony_ci } 131262306a36Sopenharmony_ci if (r) { 131362306a36Sopenharmony_ci return r; 131462306a36Sopenharmony_ci } 131562306a36Sopenharmony_ci } while (p->idx < p->chunk_ib->length_dw); 131662306a36Sopenharmony_ci return 0; 131762306a36Sopenharmony_ci} 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_civoid r300_set_reg_safe(struct radeon_device *rdev) 132062306a36Sopenharmony_ci{ 132162306a36Sopenharmony_ci rdev->config.r300.reg_safe_bm = r300_reg_safe_bm; 132262306a36Sopenharmony_ci rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm); 132362306a36Sopenharmony_ci} 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_civoid r300_mc_program(struct radeon_device *rdev) 132662306a36Sopenharmony_ci{ 132762306a36Sopenharmony_ci struct r100_mc_save save; 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci r100_debugfs_mc_info_init(rdev); 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci /* Stops all mc clients */ 133262306a36Sopenharmony_ci r100_mc_stop(rdev, &save); 133362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 133462306a36Sopenharmony_ci WREG32(R_00014C_MC_AGP_LOCATION, 133562306a36Sopenharmony_ci S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | 133662306a36Sopenharmony_ci S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); 133762306a36Sopenharmony_ci WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); 133862306a36Sopenharmony_ci WREG32(R_00015C_AGP_BASE_2, 133962306a36Sopenharmony_ci upper_32_bits(rdev->mc.agp_base) & 0xff); 134062306a36Sopenharmony_ci } else { 134162306a36Sopenharmony_ci WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF); 134262306a36Sopenharmony_ci WREG32(R_000170_AGP_BASE, 0); 134362306a36Sopenharmony_ci WREG32(R_00015C_AGP_BASE_2, 0); 134462306a36Sopenharmony_ci } 134562306a36Sopenharmony_ci /* Wait for mc idle */ 134662306a36Sopenharmony_ci if (r300_mc_wait_for_idle(rdev)) 134762306a36Sopenharmony_ci DRM_INFO("Failed to wait MC idle before programming MC.\n"); 134862306a36Sopenharmony_ci /* Program MC, should be a 32bits limited address space */ 134962306a36Sopenharmony_ci WREG32(R_000148_MC_FB_LOCATION, 135062306a36Sopenharmony_ci S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | 135162306a36Sopenharmony_ci S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); 135262306a36Sopenharmony_ci r100_mc_resume(rdev, &save); 135362306a36Sopenharmony_ci} 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_civoid r300_clock_startup(struct radeon_device *rdev) 135662306a36Sopenharmony_ci{ 135762306a36Sopenharmony_ci u32 tmp; 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci if (radeon_dynclks != -1 && radeon_dynclks) 136062306a36Sopenharmony_ci radeon_legacy_set_clock_gating(rdev, 1); 136162306a36Sopenharmony_ci /* We need to force on some of the block */ 136262306a36Sopenharmony_ci tmp = RREG32_PLL(R_00000D_SCLK_CNTL); 136362306a36Sopenharmony_ci tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); 136462306a36Sopenharmony_ci if ((rdev->family == CHIP_RV350) || (rdev->family == CHIP_RV380)) 136562306a36Sopenharmony_ci tmp |= S_00000D_FORCE_VAP(1); 136662306a36Sopenharmony_ci WREG32_PLL(R_00000D_SCLK_CNTL, tmp); 136762306a36Sopenharmony_ci} 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_cistatic int r300_startup(struct radeon_device *rdev) 137062306a36Sopenharmony_ci{ 137162306a36Sopenharmony_ci int r; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci /* set common regs */ 137462306a36Sopenharmony_ci r100_set_common_regs(rdev); 137562306a36Sopenharmony_ci /* program mc */ 137662306a36Sopenharmony_ci r300_mc_program(rdev); 137762306a36Sopenharmony_ci /* Resume clock */ 137862306a36Sopenharmony_ci r300_clock_startup(rdev); 137962306a36Sopenharmony_ci /* Initialize GPU configuration (# pipes, ...) */ 138062306a36Sopenharmony_ci r300_gpu_init(rdev); 138162306a36Sopenharmony_ci /* Initialize GART (initialize after TTM so we can allocate 138262306a36Sopenharmony_ci * memory through TTM but finalize after TTM) */ 138362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) { 138462306a36Sopenharmony_ci r = rv370_pcie_gart_enable(rdev); 138562306a36Sopenharmony_ci if (r) 138662306a36Sopenharmony_ci return r; 138762306a36Sopenharmony_ci } 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci if (rdev->family == CHIP_R300 || 139062306a36Sopenharmony_ci rdev->family == CHIP_R350 || 139162306a36Sopenharmony_ci rdev->family == CHIP_RV350) 139262306a36Sopenharmony_ci r100_enable_bm(rdev); 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) { 139562306a36Sopenharmony_ci r = r100_pci_gart_enable(rdev); 139662306a36Sopenharmony_ci if (r) 139762306a36Sopenharmony_ci return r; 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci /* allocate wb buffer */ 140162306a36Sopenharmony_ci r = radeon_wb_init(rdev); 140262306a36Sopenharmony_ci if (r) 140362306a36Sopenharmony_ci return r; 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 140662306a36Sopenharmony_ci if (r) { 140762306a36Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 140862306a36Sopenharmony_ci return r; 140962306a36Sopenharmony_ci } 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci /* Enable IRQ */ 141262306a36Sopenharmony_ci if (!rdev->irq.installed) { 141362306a36Sopenharmony_ci r = radeon_irq_kms_init(rdev); 141462306a36Sopenharmony_ci if (r) 141562306a36Sopenharmony_ci return r; 141662306a36Sopenharmony_ci } 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci r100_irq_set(rdev); 141962306a36Sopenharmony_ci rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); 142062306a36Sopenharmony_ci /* 1M ring buffer */ 142162306a36Sopenharmony_ci r = r100_cp_init(rdev, 1024 * 1024); 142262306a36Sopenharmony_ci if (r) { 142362306a36Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP (%d).\n", r); 142462306a36Sopenharmony_ci return r; 142562306a36Sopenharmony_ci } 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci r = radeon_ib_pool_init(rdev); 142862306a36Sopenharmony_ci if (r) { 142962306a36Sopenharmony_ci dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 143062306a36Sopenharmony_ci return r; 143162306a36Sopenharmony_ci } 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci return 0; 143462306a36Sopenharmony_ci} 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ciint r300_resume(struct radeon_device *rdev) 143762306a36Sopenharmony_ci{ 143862306a36Sopenharmony_ci int r; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci /* Make sur GART are not working */ 144162306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 144262306a36Sopenharmony_ci rv370_pcie_gart_disable(rdev); 144362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 144462306a36Sopenharmony_ci r100_pci_gart_disable(rdev); 144562306a36Sopenharmony_ci /* Resume clock before doing reset */ 144662306a36Sopenharmony_ci r300_clock_startup(rdev); 144762306a36Sopenharmony_ci /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 144862306a36Sopenharmony_ci if (radeon_asic_reset(rdev)) { 144962306a36Sopenharmony_ci dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 145062306a36Sopenharmony_ci RREG32(R_000E40_RBBM_STATUS), 145162306a36Sopenharmony_ci RREG32(R_0007C0_CP_STAT)); 145262306a36Sopenharmony_ci } 145362306a36Sopenharmony_ci /* post */ 145462306a36Sopenharmony_ci radeon_combios_asic_init(rdev->ddev); 145562306a36Sopenharmony_ci /* Resume clock after posting */ 145662306a36Sopenharmony_ci r300_clock_startup(rdev); 145762306a36Sopenharmony_ci /* Initialize surface registers */ 145862306a36Sopenharmony_ci radeon_surface_init(rdev); 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci rdev->accel_working = true; 146162306a36Sopenharmony_ci r = r300_startup(rdev); 146262306a36Sopenharmony_ci if (r) { 146362306a36Sopenharmony_ci rdev->accel_working = false; 146462306a36Sopenharmony_ci } 146562306a36Sopenharmony_ci return r; 146662306a36Sopenharmony_ci} 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ciint r300_suspend(struct radeon_device *rdev) 146962306a36Sopenharmony_ci{ 147062306a36Sopenharmony_ci radeon_pm_suspend(rdev); 147162306a36Sopenharmony_ci r100_cp_disable(rdev); 147262306a36Sopenharmony_ci radeon_wb_disable(rdev); 147362306a36Sopenharmony_ci r100_irq_disable(rdev); 147462306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 147562306a36Sopenharmony_ci rv370_pcie_gart_disable(rdev); 147662306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 147762306a36Sopenharmony_ci r100_pci_gart_disable(rdev); 147862306a36Sopenharmony_ci return 0; 147962306a36Sopenharmony_ci} 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_civoid r300_fini(struct radeon_device *rdev) 148262306a36Sopenharmony_ci{ 148362306a36Sopenharmony_ci radeon_pm_fini(rdev); 148462306a36Sopenharmony_ci r100_cp_fini(rdev); 148562306a36Sopenharmony_ci radeon_wb_fini(rdev); 148662306a36Sopenharmony_ci radeon_ib_pool_fini(rdev); 148762306a36Sopenharmony_ci radeon_gem_fini(rdev); 148862306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 148962306a36Sopenharmony_ci rv370_pcie_gart_fini(rdev); 149062306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 149162306a36Sopenharmony_ci r100_pci_gart_fini(rdev); 149262306a36Sopenharmony_ci radeon_agp_fini(rdev); 149362306a36Sopenharmony_ci radeon_irq_kms_fini(rdev); 149462306a36Sopenharmony_ci radeon_fence_driver_fini(rdev); 149562306a36Sopenharmony_ci radeon_bo_fini(rdev); 149662306a36Sopenharmony_ci radeon_atombios_fini(rdev); 149762306a36Sopenharmony_ci kfree(rdev->bios); 149862306a36Sopenharmony_ci rdev->bios = NULL; 149962306a36Sopenharmony_ci} 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ciint r300_init(struct radeon_device *rdev) 150262306a36Sopenharmony_ci{ 150362306a36Sopenharmony_ci int r; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci /* Disable VGA */ 150662306a36Sopenharmony_ci r100_vga_render_disable(rdev); 150762306a36Sopenharmony_ci /* Initialize scratch registers */ 150862306a36Sopenharmony_ci radeon_scratch_init(rdev); 150962306a36Sopenharmony_ci /* Initialize surface registers */ 151062306a36Sopenharmony_ci radeon_surface_init(rdev); 151162306a36Sopenharmony_ci /* TODO: disable VGA need to use VGA request */ 151262306a36Sopenharmony_ci /* restore some register to sane defaults */ 151362306a36Sopenharmony_ci r100_restore_sanity(rdev); 151462306a36Sopenharmony_ci /* BIOS*/ 151562306a36Sopenharmony_ci if (!radeon_get_bios(rdev)) { 151662306a36Sopenharmony_ci if (ASIC_IS_AVIVO(rdev)) 151762306a36Sopenharmony_ci return -EINVAL; 151862306a36Sopenharmony_ci } 151962306a36Sopenharmony_ci if (rdev->is_atom_bios) { 152062306a36Sopenharmony_ci dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n"); 152162306a36Sopenharmony_ci return -EINVAL; 152262306a36Sopenharmony_ci } else { 152362306a36Sopenharmony_ci r = radeon_combios_init(rdev); 152462306a36Sopenharmony_ci if (r) 152562306a36Sopenharmony_ci return r; 152662306a36Sopenharmony_ci } 152762306a36Sopenharmony_ci /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 152862306a36Sopenharmony_ci if (radeon_asic_reset(rdev)) { 152962306a36Sopenharmony_ci dev_warn(rdev->dev, 153062306a36Sopenharmony_ci "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 153162306a36Sopenharmony_ci RREG32(R_000E40_RBBM_STATUS), 153262306a36Sopenharmony_ci RREG32(R_0007C0_CP_STAT)); 153362306a36Sopenharmony_ci } 153462306a36Sopenharmony_ci /* check if cards are posted or not */ 153562306a36Sopenharmony_ci if (radeon_boot_test_post_card(rdev) == false) 153662306a36Sopenharmony_ci return -EINVAL; 153762306a36Sopenharmony_ci /* Set asic errata */ 153862306a36Sopenharmony_ci r300_errata(rdev); 153962306a36Sopenharmony_ci /* Initialize clocks */ 154062306a36Sopenharmony_ci radeon_get_clock_info(rdev->ddev); 154162306a36Sopenharmony_ci /* initialize AGP */ 154262306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 154362306a36Sopenharmony_ci r = radeon_agp_init(rdev); 154462306a36Sopenharmony_ci if (r) { 154562306a36Sopenharmony_ci radeon_agp_disable(rdev); 154662306a36Sopenharmony_ci } 154762306a36Sopenharmony_ci } 154862306a36Sopenharmony_ci /* initialize memory controller */ 154962306a36Sopenharmony_ci r300_mc_init(rdev); 155062306a36Sopenharmony_ci /* Fence driver */ 155162306a36Sopenharmony_ci radeon_fence_driver_init(rdev); 155262306a36Sopenharmony_ci /* Memory manager */ 155362306a36Sopenharmony_ci r = radeon_bo_init(rdev); 155462306a36Sopenharmony_ci if (r) 155562306a36Sopenharmony_ci return r; 155662306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) { 155762306a36Sopenharmony_ci r = rv370_pcie_gart_init(rdev); 155862306a36Sopenharmony_ci if (r) 155962306a36Sopenharmony_ci return r; 156062306a36Sopenharmony_ci } 156162306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) { 156262306a36Sopenharmony_ci r = r100_pci_gart_init(rdev); 156362306a36Sopenharmony_ci if (r) 156462306a36Sopenharmony_ci return r; 156562306a36Sopenharmony_ci } 156662306a36Sopenharmony_ci r300_set_reg_safe(rdev); 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci /* Initialize power management */ 156962306a36Sopenharmony_ci radeon_pm_init(rdev); 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci rdev->accel_working = true; 157262306a36Sopenharmony_ci r = r300_startup(rdev); 157362306a36Sopenharmony_ci if (r) { 157462306a36Sopenharmony_ci /* Something went wrong with the accel init, so stop accel */ 157562306a36Sopenharmony_ci dev_err(rdev->dev, "Disabling GPU acceleration\n"); 157662306a36Sopenharmony_ci r100_cp_fini(rdev); 157762306a36Sopenharmony_ci radeon_wb_fini(rdev); 157862306a36Sopenharmony_ci radeon_ib_pool_fini(rdev); 157962306a36Sopenharmony_ci radeon_irq_kms_fini(rdev); 158062306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 158162306a36Sopenharmony_ci rv370_pcie_gart_fini(rdev); 158262306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 158362306a36Sopenharmony_ci r100_pci_gart_fini(rdev); 158462306a36Sopenharmony_ci radeon_agp_fini(rdev); 158562306a36Sopenharmony_ci rdev->accel_working = false; 158662306a36Sopenharmony_ci } 158762306a36Sopenharmony_ci return 0; 158862306a36Sopenharmony_ci} 1589