18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc. 48c2ecf20Sopenharmony_ci * Copyright 2009 Jerome Glisse. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Authors: Dave Airlie 258c2ecf20Sopenharmony_ci * Alex Deucher 268c2ecf20Sopenharmony_ci * Jerome Glisse 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <linux/pci.h> 308c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 318c2ecf20Sopenharmony_ci#include <linux/slab.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include <drm/drm.h> 348c2ecf20Sopenharmony_ci#include <drm/drm_crtc_helper.h> 358c2ecf20Sopenharmony_ci#include <drm/drm_debugfs.h> 368c2ecf20Sopenharmony_ci#include <drm/drm_device.h> 378c2ecf20Sopenharmony_ci#include <drm/drm_file.h> 388c2ecf20Sopenharmony_ci#include <drm/radeon_drm.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#include "r100_track.h" 418c2ecf20Sopenharmony_ci#include "r300_reg_safe.h" 428c2ecf20Sopenharmony_ci#include "r300d.h" 438c2ecf20Sopenharmony_ci#include "radeon.h" 448c2ecf20Sopenharmony_ci#include "radeon_asic.h" 458c2ecf20Sopenharmony_ci#include "radeon_reg.h" 468c2ecf20Sopenharmony_ci#include "rv350d.h" 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * GPU Errata: 518c2ecf20Sopenharmony_ci * - HOST_PATH_CNTL: r300 family seems to dislike write to HOST_PATH_CNTL 528c2ecf20Sopenharmony_ci * using MMIO to flush host path read cache, this lead to HARDLOCKUP. 538c2ecf20Sopenharmony_ci * However, scheduling such write to the ring seems harmless, i suspect 548c2ecf20Sopenharmony_ci * the CP read collide with the flush somehow, or maybe the MC, hard to 558c2ecf20Sopenharmony_ci * tell. (Jerome Glisse) 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* 598c2ecf20Sopenharmony_ci * Indirect registers accessor 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ciuint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci unsigned long flags; 648c2ecf20Sopenharmony_ci uint32_t r; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->pcie_idx_lock, flags); 678c2ecf20Sopenharmony_ci WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); 688c2ecf20Sopenharmony_ci r = RREG32(RADEON_PCIE_DATA); 698c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags); 708c2ecf20Sopenharmony_ci return r; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_civoid rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci unsigned long flags; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->pcie_idx_lock, flags); 788c2ecf20Sopenharmony_ci WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); 798c2ecf20Sopenharmony_ci WREG32(RADEON_PCIE_DATA, (v)); 808c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* 848c2ecf20Sopenharmony_ci * rv370,rv380 PCIE GART 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_cistatic int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_civoid rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci uint32_t tmp; 918c2ecf20Sopenharmony_ci int i; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Workaround HW bug do flush 2 times */ 948c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 958c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 968c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB); 978c2ecf20Sopenharmony_ci (void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 988c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci mb(); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define R300_PTE_UNSNOOPED (1 << 0) 1048c2ecf20Sopenharmony_ci#define R300_PTE_WRITEABLE (1 << 2) 1058c2ecf20Sopenharmony_ci#define R300_PTE_READABLE (1 << 3) 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ciuint64_t rv370_pcie_gart_get_page_entry(uint64_t addr, uint32_t flags) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci addr = (lower_32_bits(addr) >> 8) | 1108c2ecf20Sopenharmony_ci ((upper_32_bits(addr) & 0xff) << 24); 1118c2ecf20Sopenharmony_ci if (flags & RADEON_GART_PAGE_READ) 1128c2ecf20Sopenharmony_ci addr |= R300_PTE_READABLE; 1138c2ecf20Sopenharmony_ci if (flags & RADEON_GART_PAGE_WRITE) 1148c2ecf20Sopenharmony_ci addr |= R300_PTE_WRITEABLE; 1158c2ecf20Sopenharmony_ci if (!(flags & RADEON_GART_PAGE_SNOOP)) 1168c2ecf20Sopenharmony_ci addr |= R300_PTE_UNSNOOPED; 1178c2ecf20Sopenharmony_ci return addr; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_civoid rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, 1218c2ecf20Sopenharmony_ci uint64_t entry) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci void __iomem *ptr = rdev->gart.ptr; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* on x86 we want this to be CPU endian, on powerpc 1268c2ecf20Sopenharmony_ci * on powerpc without HW swappers, it'll get swapped on way 1278c2ecf20Sopenharmony_ci * into VRAM - so no need for cpu_to_le32 on VRAM tables */ 1288c2ecf20Sopenharmony_ci writel(entry, ((void __iomem *)ptr) + (i * 4)); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ciint rv370_pcie_gart_init(struct radeon_device *rdev) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci int r; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (rdev->gart.robj) { 1368c2ecf20Sopenharmony_ci WARN(1, "RV370 PCIE GART already initialized\n"); 1378c2ecf20Sopenharmony_ci return 0; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci /* Initialize common gart structure */ 1408c2ecf20Sopenharmony_ci r = radeon_gart_init(rdev); 1418c2ecf20Sopenharmony_ci if (r) 1428c2ecf20Sopenharmony_ci return r; 1438c2ecf20Sopenharmony_ci r = rv370_debugfs_pcie_gart_info_init(rdev); 1448c2ecf20Sopenharmony_ci if (r) 1458c2ecf20Sopenharmony_ci DRM_ERROR("Failed to register debugfs file for PCIE gart !\n"); 1468c2ecf20Sopenharmony_ci rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; 1478c2ecf20Sopenharmony_ci rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; 1488c2ecf20Sopenharmony_ci rdev->asic->gart.get_page_entry = &rv370_pcie_gart_get_page_entry; 1498c2ecf20Sopenharmony_ci rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; 1508c2ecf20Sopenharmony_ci return radeon_gart_table_vram_alloc(rdev); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ciint rv370_pcie_gart_enable(struct radeon_device *rdev) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci uint32_t table_addr; 1568c2ecf20Sopenharmony_ci uint32_t tmp; 1578c2ecf20Sopenharmony_ci int r; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (rdev->gart.robj == NULL) { 1608c2ecf20Sopenharmony_ci dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); 1618c2ecf20Sopenharmony_ci return -EINVAL; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci r = radeon_gart_table_vram_pin(rdev); 1648c2ecf20Sopenharmony_ci if (r) 1658c2ecf20Sopenharmony_ci return r; 1668c2ecf20Sopenharmony_ci /* discard memory request outside of configured range */ 1678c2ecf20Sopenharmony_ci tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; 1688c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); 1698c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_start); 1708c2ecf20Sopenharmony_ci tmp = rdev->mc.gtt_end & ~RADEON_GPU_PAGE_MASK; 1718c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp); 1728c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0); 1738c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0); 1748c2ecf20Sopenharmony_ci table_addr = rdev->gart.table_addr; 1758c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr); 1768c2ecf20Sopenharmony_ci /* FIXME: setup default page */ 1778c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start); 1788c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0); 1798c2ecf20Sopenharmony_ci /* Clear error */ 1808c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_ERROR, 0); 1818c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 1828c2ecf20Sopenharmony_ci tmp |= RADEON_PCIE_TX_GART_EN; 1838c2ecf20Sopenharmony_ci tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; 1848c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); 1858c2ecf20Sopenharmony_ci rv370_pcie_gart_tlb_flush(rdev); 1868c2ecf20Sopenharmony_ci DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", 1878c2ecf20Sopenharmony_ci (unsigned)(rdev->mc.gtt_size >> 20), 1888c2ecf20Sopenharmony_ci (unsigned long long)table_addr); 1898c2ecf20Sopenharmony_ci rdev->gart.ready = true; 1908c2ecf20Sopenharmony_ci return 0; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_civoid rv370_pcie_gart_disable(struct radeon_device *rdev) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci u32 tmp; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0); 1988c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0); 1998c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0); 2008c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0); 2018c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 2028c2ecf20Sopenharmony_ci tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; 2038c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); 2048c2ecf20Sopenharmony_ci radeon_gart_table_vram_unpin(rdev); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_civoid rv370_pcie_gart_fini(struct radeon_device *rdev) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci radeon_gart_fini(rdev); 2108c2ecf20Sopenharmony_ci rv370_pcie_gart_disable(rdev); 2118c2ecf20Sopenharmony_ci radeon_gart_table_vram_free(rdev); 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_civoid r300_fence_ring_emit(struct radeon_device *rdev, 2158c2ecf20Sopenharmony_ci struct radeon_fence *fence) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[fence->ring]; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* Who ever call radeon_fence_emit should call ring_lock and ask 2208c2ecf20Sopenharmony_ci * for enough space (today caller are ib schedule and buffer move) */ 2218c2ecf20Sopenharmony_ci /* Write SC register so SC & US assert idle */ 2228c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_TL, 0)); 2238c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 2248c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_BR, 0)); 2258c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 2268c2ecf20Sopenharmony_ci /* Flush 3D cache */ 2278c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); 2288c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_RB3D_DC_FLUSH); 2298c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); 2308c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_ZC_FLUSH); 2318c2ecf20Sopenharmony_ci /* Wait until IDLE & CLEAN */ 2328c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); 2338c2ecf20Sopenharmony_ci radeon_ring_write(ring, (RADEON_WAIT_3D_IDLECLEAN | 2348c2ecf20Sopenharmony_ci RADEON_WAIT_2D_IDLECLEAN | 2358c2ecf20Sopenharmony_ci RADEON_WAIT_DMA_GUI_IDLE)); 2368c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); 2378c2ecf20Sopenharmony_ci radeon_ring_write(ring, rdev->config.r300.hdp_cntl | 2388c2ecf20Sopenharmony_ci RADEON_HDP_READ_BUFFER_INVALIDATE); 2398c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); 2408c2ecf20Sopenharmony_ci radeon_ring_write(ring, rdev->config.r300.hdp_cntl); 2418c2ecf20Sopenharmony_ci /* Emit fence sequence & fire IRQ */ 2428c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0)); 2438c2ecf20Sopenharmony_ci radeon_ring_write(ring, fence->seq); 2448c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_GEN_INT_STATUS, 0)); 2458c2ecf20Sopenharmony_ci radeon_ring_write(ring, RADEON_SW_INT_FIRE); 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_civoid r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci unsigned gb_tile_config; 2518c2ecf20Sopenharmony_ci int r; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* Sub pixel 1/12 so we can have 4K rendering according to doc */ 2548c2ecf20Sopenharmony_ci gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); 2558c2ecf20Sopenharmony_ci switch(rdev->num_gb_pipes) { 2568c2ecf20Sopenharmony_ci case 2: 2578c2ecf20Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R300; 2588c2ecf20Sopenharmony_ci break; 2598c2ecf20Sopenharmony_ci case 3: 2608c2ecf20Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R420_3P; 2618c2ecf20Sopenharmony_ci break; 2628c2ecf20Sopenharmony_ci case 4: 2638c2ecf20Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R420; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci case 1: 2668c2ecf20Sopenharmony_ci default: 2678c2ecf20Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_RV350; 2688c2ecf20Sopenharmony_ci break; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 64); 2728c2ecf20Sopenharmony_ci if (r) { 2738c2ecf20Sopenharmony_ci return; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_ISYNC_CNTL, 0)); 2768c2ecf20Sopenharmony_ci radeon_ring_write(ring, 2778c2ecf20Sopenharmony_ci RADEON_ISYNC_ANY2D_IDLE3D | 2788c2ecf20Sopenharmony_ci RADEON_ISYNC_ANY3D_IDLE2D | 2798c2ecf20Sopenharmony_ci RADEON_ISYNC_WAIT_IDLEGUI | 2808c2ecf20Sopenharmony_ci RADEON_ISYNC_CPSCRATCH_IDLEGUI); 2818c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_TILE_CONFIG, 0)); 2828c2ecf20Sopenharmony_ci radeon_ring_write(ring, gb_tile_config); 2838c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); 2848c2ecf20Sopenharmony_ci radeon_ring_write(ring, 2858c2ecf20Sopenharmony_ci RADEON_WAIT_2D_IDLECLEAN | 2868c2ecf20Sopenharmony_ci RADEON_WAIT_3D_IDLECLEAN); 2878c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_DST_PIPE_CONFIG, 0)); 2888c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_PIPE_AUTO_CONFIG); 2898c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_SELECT, 0)); 2908c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 2918c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_ENABLE, 0)); 2928c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 2938c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); 2948c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); 2958c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); 2968c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE); 2978c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); 2988c2ecf20Sopenharmony_ci radeon_ring_write(ring, 2998c2ecf20Sopenharmony_ci RADEON_WAIT_2D_IDLECLEAN | 3008c2ecf20Sopenharmony_ci RADEON_WAIT_3D_IDLECLEAN); 3018c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_AA_CONFIG, 0)); 3028c2ecf20Sopenharmony_ci radeon_ring_write(ring, 0); 3038c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); 3048c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); 3058c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); 3068c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE); 3078c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_MSPOS0, 0)); 3088c2ecf20Sopenharmony_ci radeon_ring_write(ring, 3098c2ecf20Sopenharmony_ci ((6 << R300_MS_X0_SHIFT) | 3108c2ecf20Sopenharmony_ci (6 << R300_MS_Y0_SHIFT) | 3118c2ecf20Sopenharmony_ci (6 << R300_MS_X1_SHIFT) | 3128c2ecf20Sopenharmony_ci (6 << R300_MS_Y1_SHIFT) | 3138c2ecf20Sopenharmony_ci (6 << R300_MS_X2_SHIFT) | 3148c2ecf20Sopenharmony_ci (6 << R300_MS_Y2_SHIFT) | 3158c2ecf20Sopenharmony_ci (6 << R300_MSBD0_Y_SHIFT) | 3168c2ecf20Sopenharmony_ci (6 << R300_MSBD0_X_SHIFT))); 3178c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GB_MSPOS1, 0)); 3188c2ecf20Sopenharmony_ci radeon_ring_write(ring, 3198c2ecf20Sopenharmony_ci ((6 << R300_MS_X3_SHIFT) | 3208c2ecf20Sopenharmony_ci (6 << R300_MS_Y3_SHIFT) | 3218c2ecf20Sopenharmony_ci (6 << R300_MS_X4_SHIFT) | 3228c2ecf20Sopenharmony_ci (6 << R300_MS_Y4_SHIFT) | 3238c2ecf20Sopenharmony_ci (6 << R300_MS_X5_SHIFT) | 3248c2ecf20Sopenharmony_ci (6 << R300_MS_Y5_SHIFT) | 3258c2ecf20Sopenharmony_ci (6 << R300_MSBD1_SHIFT))); 3268c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GA_ENHANCE, 0)); 3278c2ecf20Sopenharmony_ci radeon_ring_write(ring, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); 3288c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GA_POLY_MODE, 0)); 3298c2ecf20Sopenharmony_ci radeon_ring_write(ring, 3308c2ecf20Sopenharmony_ci R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE); 3318c2ecf20Sopenharmony_ci radeon_ring_write(ring, PACKET0(R300_GA_ROUND_MODE, 0)); 3328c2ecf20Sopenharmony_ci radeon_ring_write(ring, 3338c2ecf20Sopenharmony_ci R300_GEOMETRY_ROUND_NEAREST | 3348c2ecf20Sopenharmony_ci R300_COLOR_ROUND_NEAREST); 3358c2ecf20Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic void r300_errata(struct radeon_device *rdev) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci rdev->pll_errata = 0; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if (rdev->family == CHIP_R300 && 3438c2ecf20Sopenharmony_ci (RREG32(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) == RADEON_CFG_ATI_REV_A11) { 3448c2ecf20Sopenharmony_ci rdev->pll_errata |= CHIP_ERRATA_R300_CG; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ciint r300_mc_wait_for_idle(struct radeon_device *rdev) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci unsigned i; 3518c2ecf20Sopenharmony_ci uint32_t tmp; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 3548c2ecf20Sopenharmony_ci /* read MC_STATUS */ 3558c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_MC_STATUS); 3568c2ecf20Sopenharmony_ci if (tmp & R300_MC_IDLE) { 3578c2ecf20Sopenharmony_ci return 0; 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci udelay(1); 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci return -1; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic void r300_gpu_init(struct radeon_device *rdev) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci uint32_t gb_tile_config, tmp; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) || 3698c2ecf20Sopenharmony_ci (rdev->family == CHIP_R350 && rdev->pdev->device != 0x4148)) { 3708c2ecf20Sopenharmony_ci /* r300,r350 */ 3718c2ecf20Sopenharmony_ci rdev->num_gb_pipes = 2; 3728c2ecf20Sopenharmony_ci } else { 3738c2ecf20Sopenharmony_ci /* rv350,rv370,rv380,r300 AD, r350 AH */ 3748c2ecf20Sopenharmony_ci rdev->num_gb_pipes = 1; 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci rdev->num_z_pipes = 1; 3778c2ecf20Sopenharmony_ci gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); 3788c2ecf20Sopenharmony_ci switch (rdev->num_gb_pipes) { 3798c2ecf20Sopenharmony_ci case 2: 3808c2ecf20Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R300; 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci case 3: 3838c2ecf20Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R420_3P; 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci case 4: 3868c2ecf20Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_R420; 3878c2ecf20Sopenharmony_ci break; 3888c2ecf20Sopenharmony_ci default: 3898c2ecf20Sopenharmony_ci case 1: 3908c2ecf20Sopenharmony_ci gb_tile_config |= R300_PIPE_COUNT_RV350; 3918c2ecf20Sopenharmony_ci break; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci WREG32(R300_GB_TILE_CONFIG, gb_tile_config); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci if (r100_gui_wait_for_idle(rdev)) { 3968c2ecf20Sopenharmony_ci pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n"); 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci tmp = RREG32(R300_DST_PIPE_CONFIG); 4008c2ecf20Sopenharmony_ci WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci WREG32(R300_RB2D_DSTCACHE_MODE, 4038c2ecf20Sopenharmony_ci R300_DC_AUTOFLUSH_ENABLE | 4048c2ecf20Sopenharmony_ci R300_DC_DC_DISABLE_IGNORE_PE); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (r100_gui_wait_for_idle(rdev)) { 4078c2ecf20Sopenharmony_ci pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n"); 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci if (r300_mc_wait_for_idle(rdev)) { 4108c2ecf20Sopenharmony_ci pr_warn("Failed to wait MC idle while programming pipes. Bad things might happen.\n"); 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized\n", 4138c2ecf20Sopenharmony_ci rdev->num_gb_pipes, rdev->num_z_pipes); 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ciint r300_asic_reset(struct radeon_device *rdev, bool hard) 4178c2ecf20Sopenharmony_ci{ 4188c2ecf20Sopenharmony_ci struct r100_mc_save save; 4198c2ecf20Sopenharmony_ci u32 status, tmp; 4208c2ecf20Sopenharmony_ci int ret = 0; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci status = RREG32(R_000E40_RBBM_STATUS); 4238c2ecf20Sopenharmony_ci if (!G_000E40_GUI_ACTIVE(status)) { 4248c2ecf20Sopenharmony_ci return 0; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci r100_mc_stop(rdev, &save); 4278c2ecf20Sopenharmony_ci status = RREG32(R_000E40_RBBM_STATUS); 4288c2ecf20Sopenharmony_ci dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 4298c2ecf20Sopenharmony_ci /* stop CP */ 4308c2ecf20Sopenharmony_ci WREG32(RADEON_CP_CSQ_CNTL, 0); 4318c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_CP_RB_CNTL); 4328c2ecf20Sopenharmony_ci WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); 4338c2ecf20Sopenharmony_ci WREG32(RADEON_CP_RB_RPTR_WR, 0); 4348c2ecf20Sopenharmony_ci WREG32(RADEON_CP_RB_WPTR, 0); 4358c2ecf20Sopenharmony_ci WREG32(RADEON_CP_RB_CNTL, tmp); 4368c2ecf20Sopenharmony_ci /* save PCI state */ 4378c2ecf20Sopenharmony_ci pci_save_state(rdev->pdev); 4388c2ecf20Sopenharmony_ci /* disable bus mastering */ 4398c2ecf20Sopenharmony_ci r100_bm_disable(rdev); 4408c2ecf20Sopenharmony_ci WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) | 4418c2ecf20Sopenharmony_ci S_0000F0_SOFT_RESET_GA(1)); 4428c2ecf20Sopenharmony_ci RREG32(R_0000F0_RBBM_SOFT_RESET); 4438c2ecf20Sopenharmony_ci mdelay(500); 4448c2ecf20Sopenharmony_ci WREG32(R_0000F0_RBBM_SOFT_RESET, 0); 4458c2ecf20Sopenharmony_ci mdelay(1); 4468c2ecf20Sopenharmony_ci status = RREG32(R_000E40_RBBM_STATUS); 4478c2ecf20Sopenharmony_ci dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 4488c2ecf20Sopenharmony_ci /* resetting the CP seems to be problematic sometimes it end up 4498c2ecf20Sopenharmony_ci * hard locking the computer, but it's necessary for successful 4508c2ecf20Sopenharmony_ci * reset more test & playing is needed on R3XX/R4XX to find a 4518c2ecf20Sopenharmony_ci * reliable (if any solution) 4528c2ecf20Sopenharmony_ci */ 4538c2ecf20Sopenharmony_ci WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1)); 4548c2ecf20Sopenharmony_ci RREG32(R_0000F0_RBBM_SOFT_RESET); 4558c2ecf20Sopenharmony_ci mdelay(500); 4568c2ecf20Sopenharmony_ci WREG32(R_0000F0_RBBM_SOFT_RESET, 0); 4578c2ecf20Sopenharmony_ci mdelay(1); 4588c2ecf20Sopenharmony_ci status = RREG32(R_000E40_RBBM_STATUS); 4598c2ecf20Sopenharmony_ci dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 4608c2ecf20Sopenharmony_ci /* restore PCI & busmastering */ 4618c2ecf20Sopenharmony_ci pci_restore_state(rdev->pdev); 4628c2ecf20Sopenharmony_ci r100_enable_bm(rdev); 4638c2ecf20Sopenharmony_ci /* Check if GPU is idle */ 4648c2ecf20Sopenharmony_ci if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { 4658c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed to reset GPU\n"); 4668c2ecf20Sopenharmony_ci ret = -1; 4678c2ecf20Sopenharmony_ci } else 4688c2ecf20Sopenharmony_ci dev_info(rdev->dev, "GPU reset succeed\n"); 4698c2ecf20Sopenharmony_ci r100_mc_resume(rdev, &save); 4708c2ecf20Sopenharmony_ci return ret; 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci/* 4748c2ecf20Sopenharmony_ci * r300,r350,rv350,rv380 VRAM info 4758c2ecf20Sopenharmony_ci */ 4768c2ecf20Sopenharmony_civoid r300_mc_init(struct radeon_device *rdev) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci u64 base; 4798c2ecf20Sopenharmony_ci u32 tmp; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci /* DDR for all card after R300 & IGP */ 4828c2ecf20Sopenharmony_ci rdev->mc.vram_is_ddr = true; 4838c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_MEM_CNTL); 4848c2ecf20Sopenharmony_ci tmp &= R300_MEM_NUM_CHANNELS_MASK; 4858c2ecf20Sopenharmony_ci switch (tmp) { 4868c2ecf20Sopenharmony_ci case 0: rdev->mc.vram_width = 64; break; 4878c2ecf20Sopenharmony_ci case 1: rdev->mc.vram_width = 128; break; 4888c2ecf20Sopenharmony_ci case 2: rdev->mc.vram_width = 256; break; 4898c2ecf20Sopenharmony_ci default: rdev->mc.vram_width = 128; break; 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci r100_vram_init_sizes(rdev); 4928c2ecf20Sopenharmony_ci base = rdev->mc.aper_base; 4938c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 4948c2ecf20Sopenharmony_ci base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; 4958c2ecf20Sopenharmony_ci radeon_vram_location(rdev, &rdev->mc, base); 4968c2ecf20Sopenharmony_ci rdev->mc.gtt_base_align = 0; 4978c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_IS_AGP)) 4988c2ecf20Sopenharmony_ci radeon_gtt_location(rdev, &rdev->mc); 4998c2ecf20Sopenharmony_ci radeon_update_bandwidth_info(rdev); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_civoid rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes) 5038c2ecf20Sopenharmony_ci{ 5048c2ecf20Sopenharmony_ci uint32_t link_width_cntl, mask; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 5078c2ecf20Sopenharmony_ci return; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 5108c2ecf20Sopenharmony_ci return; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci /* FIXME wait for idle */ 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci switch (lanes) { 5158c2ecf20Sopenharmony_ci case 0: 5168c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X0; 5178c2ecf20Sopenharmony_ci break; 5188c2ecf20Sopenharmony_ci case 1: 5198c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X1; 5208c2ecf20Sopenharmony_ci break; 5218c2ecf20Sopenharmony_ci case 2: 5228c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X2; 5238c2ecf20Sopenharmony_ci break; 5248c2ecf20Sopenharmony_ci case 4: 5258c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X4; 5268c2ecf20Sopenharmony_ci break; 5278c2ecf20Sopenharmony_ci case 8: 5288c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X8; 5298c2ecf20Sopenharmony_ci break; 5308c2ecf20Sopenharmony_ci case 12: 5318c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X12; 5328c2ecf20Sopenharmony_ci break; 5338c2ecf20Sopenharmony_ci case 16: 5348c2ecf20Sopenharmony_ci default: 5358c2ecf20Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X16; 5368c2ecf20Sopenharmony_ci break; 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) == 5428c2ecf20Sopenharmony_ci (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT)) 5438c2ecf20Sopenharmony_ci return; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK | 5468c2ecf20Sopenharmony_ci RADEON_PCIE_LC_RECONFIG_NOW | 5478c2ecf20Sopenharmony_ci RADEON_PCIE_LC_RECONFIG_LATER | 5488c2ecf20Sopenharmony_ci RADEON_PCIE_LC_SHORT_RECONFIG_EN); 5498c2ecf20Sopenharmony_ci link_width_cntl |= mask; 5508c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 5518c2ecf20Sopenharmony_ci WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl | 5528c2ecf20Sopenharmony_ci RADEON_PCIE_LC_RECONFIG_NOW)); 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* wait for lane set to complete */ 5558c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 5568c2ecf20Sopenharmony_ci while (link_width_cntl == 0xffffffff) 5578c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ciint rv370_get_pcie_lanes(struct radeon_device *rdev) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci u32 link_width_cntl; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 5668c2ecf20Sopenharmony_ci return 0; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 5698c2ecf20Sopenharmony_ci return 0; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci /* FIXME wait for idle */ 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) { 5768c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X0: 5778c2ecf20Sopenharmony_ci return 0; 5788c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X1: 5798c2ecf20Sopenharmony_ci return 1; 5808c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X2: 5818c2ecf20Sopenharmony_ci return 2; 5828c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X4: 5838c2ecf20Sopenharmony_ci return 4; 5848c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X8: 5858c2ecf20Sopenharmony_ci return 8; 5868c2ecf20Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X16: 5878c2ecf20Sopenharmony_ci default: 5888c2ecf20Sopenharmony_ci return 16; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 5938c2ecf20Sopenharmony_cistatic int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci struct drm_info_node *node = (struct drm_info_node *) m->private; 5968c2ecf20Sopenharmony_ci struct drm_device *dev = node->minor->dev; 5978c2ecf20Sopenharmony_ci struct radeon_device *rdev = dev->dev_private; 5988c2ecf20Sopenharmony_ci uint32_t tmp; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 6018c2ecf20Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_CNTL 0x%08x\n", tmp); 6028c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_BASE); 6038c2ecf20Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_BASE 0x%08x\n", tmp); 6048c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_LO); 6058c2ecf20Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_START_LO 0x%08x\n", tmp); 6068c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_HI); 6078c2ecf20Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_START_HI 0x%08x\n", tmp); 6088c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_LO); 6098c2ecf20Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_END_LO 0x%08x\n", tmp); 6108c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_HI); 6118c2ecf20Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_END_HI 0x%08x\n", tmp); 6128c2ecf20Sopenharmony_ci tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_ERROR); 6138c2ecf20Sopenharmony_ci seq_printf(m, "PCIE_TX_GART_ERROR 0x%08x\n", tmp); 6148c2ecf20Sopenharmony_ci return 0; 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_cistatic struct drm_info_list rv370_pcie_gart_info_list[] = { 6188c2ecf20Sopenharmony_ci {"rv370_pcie_gart_info", rv370_debugfs_pcie_gart_info, 0, NULL}, 6198c2ecf20Sopenharmony_ci}; 6208c2ecf20Sopenharmony_ci#endif 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cistatic int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 6258c2ecf20Sopenharmony_ci return radeon_debugfs_add_files(rdev, rv370_pcie_gart_info_list, 1); 6268c2ecf20Sopenharmony_ci#else 6278c2ecf20Sopenharmony_ci return 0; 6288c2ecf20Sopenharmony_ci#endif 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic int r300_packet0_check(struct radeon_cs_parser *p, 6328c2ecf20Sopenharmony_ci struct radeon_cs_packet *pkt, 6338c2ecf20Sopenharmony_ci unsigned idx, unsigned reg) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci struct radeon_bo_list *reloc; 6368c2ecf20Sopenharmony_ci struct r100_cs_track *track; 6378c2ecf20Sopenharmony_ci volatile uint32_t *ib; 6388c2ecf20Sopenharmony_ci uint32_t tmp, tile_flags = 0; 6398c2ecf20Sopenharmony_ci unsigned i; 6408c2ecf20Sopenharmony_ci int r; 6418c2ecf20Sopenharmony_ci u32 idx_value; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci ib = p->ib.ptr; 6448c2ecf20Sopenharmony_ci track = (struct r100_cs_track *)p->track; 6458c2ecf20Sopenharmony_ci idx_value = radeon_get_ib_value(p, idx); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci switch(reg) { 6488c2ecf20Sopenharmony_ci case AVIVO_D1MODE_VLINE_START_END: 6498c2ecf20Sopenharmony_ci case RADEON_CRTC_GUI_TRIG_VLINE: 6508c2ecf20Sopenharmony_ci r = r100_cs_packet_parse_vline(p); 6518c2ecf20Sopenharmony_ci if (r) { 6528c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 6538c2ecf20Sopenharmony_ci idx, reg); 6548c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 6558c2ecf20Sopenharmony_ci return r; 6568c2ecf20Sopenharmony_ci } 6578c2ecf20Sopenharmony_ci break; 6588c2ecf20Sopenharmony_ci case RADEON_DST_PITCH_OFFSET: 6598c2ecf20Sopenharmony_ci case RADEON_SRC_PITCH_OFFSET: 6608c2ecf20Sopenharmony_ci r = r100_reloc_pitch_offset(p, pkt, idx, reg); 6618c2ecf20Sopenharmony_ci if (r) 6628c2ecf20Sopenharmony_ci return r; 6638c2ecf20Sopenharmony_ci break; 6648c2ecf20Sopenharmony_ci case R300_RB3D_COLOROFFSET0: 6658c2ecf20Sopenharmony_ci case R300_RB3D_COLOROFFSET1: 6668c2ecf20Sopenharmony_ci case R300_RB3D_COLOROFFSET2: 6678c2ecf20Sopenharmony_ci case R300_RB3D_COLOROFFSET3: 6688c2ecf20Sopenharmony_ci i = (reg - R300_RB3D_COLOROFFSET0) >> 2; 6698c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 6708c2ecf20Sopenharmony_ci if (r) { 6718c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 6728c2ecf20Sopenharmony_ci idx, reg); 6738c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 6748c2ecf20Sopenharmony_ci return r; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci track->cb[i].robj = reloc->robj; 6778c2ecf20Sopenharmony_ci track->cb[i].offset = idx_value; 6788c2ecf20Sopenharmony_ci track->cb_dirty = true; 6798c2ecf20Sopenharmony_ci ib[idx] = idx_value + ((u32)reloc->gpu_offset); 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci case R300_ZB_DEPTHOFFSET: 6828c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 6838c2ecf20Sopenharmony_ci if (r) { 6848c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 6858c2ecf20Sopenharmony_ci idx, reg); 6868c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 6878c2ecf20Sopenharmony_ci return r; 6888c2ecf20Sopenharmony_ci } 6898c2ecf20Sopenharmony_ci track->zb.robj = reloc->robj; 6908c2ecf20Sopenharmony_ci track->zb.offset = idx_value; 6918c2ecf20Sopenharmony_ci track->zb_dirty = true; 6928c2ecf20Sopenharmony_ci ib[idx] = idx_value + ((u32)reloc->gpu_offset); 6938c2ecf20Sopenharmony_ci break; 6948c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0: 6958c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+4: 6968c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+8: 6978c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+12: 6988c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+16: 6998c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+20: 7008c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+24: 7018c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+28: 7028c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+32: 7038c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+36: 7048c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+40: 7058c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+44: 7068c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+48: 7078c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+52: 7088c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+56: 7098c2ecf20Sopenharmony_ci case R300_TX_OFFSET_0+60: 7108c2ecf20Sopenharmony_ci i = (reg - R300_TX_OFFSET_0) >> 2; 7118c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 7128c2ecf20Sopenharmony_ci if (r) { 7138c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 7148c2ecf20Sopenharmony_ci idx, reg); 7158c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 7168c2ecf20Sopenharmony_ci return r; 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci if (p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) { 7208c2ecf20Sopenharmony_ci ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */ 7218c2ecf20Sopenharmony_ci ((idx_value & ~31) + (u32)reloc->gpu_offset); 7228c2ecf20Sopenharmony_ci } else { 7238c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) 7248c2ecf20Sopenharmony_ci tile_flags |= R300_TXO_MACRO_TILE; 7258c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MICRO) 7268c2ecf20Sopenharmony_ci tile_flags |= R300_TXO_MICRO_TILE; 7278c2ecf20Sopenharmony_ci else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE) 7288c2ecf20Sopenharmony_ci tile_flags |= R300_TXO_MICRO_TILE_SQUARE; 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci tmp = idx_value + ((u32)reloc->gpu_offset); 7318c2ecf20Sopenharmony_ci tmp |= tile_flags; 7328c2ecf20Sopenharmony_ci ib[idx] = tmp; 7338c2ecf20Sopenharmony_ci } 7348c2ecf20Sopenharmony_ci track->textures[i].robj = reloc->robj; 7358c2ecf20Sopenharmony_ci track->tex_dirty = true; 7368c2ecf20Sopenharmony_ci break; 7378c2ecf20Sopenharmony_ci /* Tracked registers */ 7388c2ecf20Sopenharmony_ci case 0x2084: 7398c2ecf20Sopenharmony_ci /* VAP_VF_CNTL */ 7408c2ecf20Sopenharmony_ci track->vap_vf_cntl = idx_value; 7418c2ecf20Sopenharmony_ci break; 7428c2ecf20Sopenharmony_ci case 0x20B4: 7438c2ecf20Sopenharmony_ci /* VAP_VTX_SIZE */ 7448c2ecf20Sopenharmony_ci track->vtx_size = idx_value & 0x7F; 7458c2ecf20Sopenharmony_ci break; 7468c2ecf20Sopenharmony_ci case 0x2134: 7478c2ecf20Sopenharmony_ci /* VAP_VF_MAX_VTX_INDX */ 7488c2ecf20Sopenharmony_ci track->max_indx = idx_value & 0x00FFFFFFUL; 7498c2ecf20Sopenharmony_ci break; 7508c2ecf20Sopenharmony_ci case 0x2088: 7518c2ecf20Sopenharmony_ci /* VAP_ALT_NUM_VERTICES - only valid on r500 */ 7528c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_RV515) 7538c2ecf20Sopenharmony_ci goto fail; 7548c2ecf20Sopenharmony_ci track->vap_alt_nverts = idx_value & 0xFFFFFF; 7558c2ecf20Sopenharmony_ci break; 7568c2ecf20Sopenharmony_ci case 0x43E4: 7578c2ecf20Sopenharmony_ci /* SC_SCISSOR1 */ 7588c2ecf20Sopenharmony_ci track->maxy = ((idx_value >> 13) & 0x1FFF) + 1; 7598c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_RV515) { 7608c2ecf20Sopenharmony_ci track->maxy -= 1440; 7618c2ecf20Sopenharmony_ci } 7628c2ecf20Sopenharmony_ci track->cb_dirty = true; 7638c2ecf20Sopenharmony_ci track->zb_dirty = true; 7648c2ecf20Sopenharmony_ci break; 7658c2ecf20Sopenharmony_ci case 0x4E00: 7668c2ecf20Sopenharmony_ci /* RB3D_CCTL */ 7678c2ecf20Sopenharmony_ci if ((idx_value & (1 << 10)) && /* CMASK_ENABLE */ 7688c2ecf20Sopenharmony_ci p->rdev->cmask_filp != p->filp) { 7698c2ecf20Sopenharmony_ci DRM_ERROR("Invalid RB3D_CCTL: Cannot enable CMASK.\n"); 7708c2ecf20Sopenharmony_ci return -EINVAL; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci track->num_cb = ((idx_value >> 5) & 0x3) + 1; 7738c2ecf20Sopenharmony_ci track->cb_dirty = true; 7748c2ecf20Sopenharmony_ci break; 7758c2ecf20Sopenharmony_ci case 0x4E38: 7768c2ecf20Sopenharmony_ci case 0x4E3C: 7778c2ecf20Sopenharmony_ci case 0x4E40: 7788c2ecf20Sopenharmony_ci case 0x4E44: 7798c2ecf20Sopenharmony_ci /* RB3D_COLORPITCH0 */ 7808c2ecf20Sopenharmony_ci /* RB3D_COLORPITCH1 */ 7818c2ecf20Sopenharmony_ci /* RB3D_COLORPITCH2 */ 7828c2ecf20Sopenharmony_ci /* RB3D_COLORPITCH3 */ 7838c2ecf20Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 7848c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 7858c2ecf20Sopenharmony_ci if (r) { 7868c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 7878c2ecf20Sopenharmony_ci idx, reg); 7888c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 7898c2ecf20Sopenharmony_ci return r; 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) 7938c2ecf20Sopenharmony_ci tile_flags |= R300_COLOR_TILE_ENABLE; 7948c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MICRO) 7958c2ecf20Sopenharmony_ci tile_flags |= R300_COLOR_MICROTILE_ENABLE; 7968c2ecf20Sopenharmony_ci else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE) 7978c2ecf20Sopenharmony_ci tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci tmp = idx_value & ~(0x7 << 16); 8008c2ecf20Sopenharmony_ci tmp |= tile_flags; 8018c2ecf20Sopenharmony_ci ib[idx] = tmp; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci i = (reg - 0x4E38) >> 2; 8048c2ecf20Sopenharmony_ci track->cb[i].pitch = idx_value & 0x3FFE; 8058c2ecf20Sopenharmony_ci switch (((idx_value >> 21) & 0xF)) { 8068c2ecf20Sopenharmony_ci case 9: 8078c2ecf20Sopenharmony_ci case 11: 8088c2ecf20Sopenharmony_ci case 12: 8098c2ecf20Sopenharmony_ci track->cb[i].cpp = 1; 8108c2ecf20Sopenharmony_ci break; 8118c2ecf20Sopenharmony_ci case 3: 8128c2ecf20Sopenharmony_ci case 4: 8138c2ecf20Sopenharmony_ci case 13: 8148c2ecf20Sopenharmony_ci case 15: 8158c2ecf20Sopenharmony_ci track->cb[i].cpp = 2; 8168c2ecf20Sopenharmony_ci break; 8178c2ecf20Sopenharmony_ci case 5: 8188c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_RV515) { 8198c2ecf20Sopenharmony_ci DRM_ERROR("Invalid color buffer format (%d)!\n", 8208c2ecf20Sopenharmony_ci ((idx_value >> 21) & 0xF)); 8218c2ecf20Sopenharmony_ci return -EINVAL; 8228c2ecf20Sopenharmony_ci } 8238c2ecf20Sopenharmony_ci fallthrough; 8248c2ecf20Sopenharmony_ci case 6: 8258c2ecf20Sopenharmony_ci track->cb[i].cpp = 4; 8268c2ecf20Sopenharmony_ci break; 8278c2ecf20Sopenharmony_ci case 10: 8288c2ecf20Sopenharmony_ci track->cb[i].cpp = 8; 8298c2ecf20Sopenharmony_ci break; 8308c2ecf20Sopenharmony_ci case 7: 8318c2ecf20Sopenharmony_ci track->cb[i].cpp = 16; 8328c2ecf20Sopenharmony_ci break; 8338c2ecf20Sopenharmony_ci default: 8348c2ecf20Sopenharmony_ci DRM_ERROR("Invalid color buffer format (%d) !\n", 8358c2ecf20Sopenharmony_ci ((idx_value >> 21) & 0xF)); 8368c2ecf20Sopenharmony_ci return -EINVAL; 8378c2ecf20Sopenharmony_ci } 8388c2ecf20Sopenharmony_ci track->cb_dirty = true; 8398c2ecf20Sopenharmony_ci break; 8408c2ecf20Sopenharmony_ci case 0x4F00: 8418c2ecf20Sopenharmony_ci /* ZB_CNTL */ 8428c2ecf20Sopenharmony_ci if (idx_value & 2) { 8438c2ecf20Sopenharmony_ci track->z_enabled = true; 8448c2ecf20Sopenharmony_ci } else { 8458c2ecf20Sopenharmony_ci track->z_enabled = false; 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci track->zb_dirty = true; 8488c2ecf20Sopenharmony_ci break; 8498c2ecf20Sopenharmony_ci case 0x4F10: 8508c2ecf20Sopenharmony_ci /* ZB_FORMAT */ 8518c2ecf20Sopenharmony_ci switch ((idx_value & 0xF)) { 8528c2ecf20Sopenharmony_ci case 0: 8538c2ecf20Sopenharmony_ci case 1: 8548c2ecf20Sopenharmony_ci track->zb.cpp = 2; 8558c2ecf20Sopenharmony_ci break; 8568c2ecf20Sopenharmony_ci case 2: 8578c2ecf20Sopenharmony_ci track->zb.cpp = 4; 8588c2ecf20Sopenharmony_ci break; 8598c2ecf20Sopenharmony_ci default: 8608c2ecf20Sopenharmony_ci DRM_ERROR("Invalid z buffer format (%d) !\n", 8618c2ecf20Sopenharmony_ci (idx_value & 0xF)); 8628c2ecf20Sopenharmony_ci return -EINVAL; 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci track->zb_dirty = true; 8658c2ecf20Sopenharmony_ci break; 8668c2ecf20Sopenharmony_ci case 0x4F24: 8678c2ecf20Sopenharmony_ci /* ZB_DEPTHPITCH */ 8688c2ecf20Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 8698c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 8708c2ecf20Sopenharmony_ci if (r) { 8718c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 8728c2ecf20Sopenharmony_ci idx, reg); 8738c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 8748c2ecf20Sopenharmony_ci return r; 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) 8788c2ecf20Sopenharmony_ci tile_flags |= R300_DEPTHMACROTILE_ENABLE; 8798c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MICRO) 8808c2ecf20Sopenharmony_ci tile_flags |= R300_DEPTHMICROTILE_TILED; 8818c2ecf20Sopenharmony_ci else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE) 8828c2ecf20Sopenharmony_ci tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci tmp = idx_value & ~(0x7 << 16); 8858c2ecf20Sopenharmony_ci tmp |= tile_flags; 8868c2ecf20Sopenharmony_ci ib[idx] = tmp; 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci track->zb.pitch = idx_value & 0x3FFC; 8898c2ecf20Sopenharmony_ci track->zb_dirty = true; 8908c2ecf20Sopenharmony_ci break; 8918c2ecf20Sopenharmony_ci case 0x4104: 8928c2ecf20Sopenharmony_ci /* TX_ENABLE */ 8938c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 8948c2ecf20Sopenharmony_ci bool enabled; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci enabled = !!(idx_value & (1 << i)); 8978c2ecf20Sopenharmony_ci track->textures[i].enabled = enabled; 8988c2ecf20Sopenharmony_ci } 8998c2ecf20Sopenharmony_ci track->tex_dirty = true; 9008c2ecf20Sopenharmony_ci break; 9018c2ecf20Sopenharmony_ci case 0x44C0: 9028c2ecf20Sopenharmony_ci case 0x44C4: 9038c2ecf20Sopenharmony_ci case 0x44C8: 9048c2ecf20Sopenharmony_ci case 0x44CC: 9058c2ecf20Sopenharmony_ci case 0x44D0: 9068c2ecf20Sopenharmony_ci case 0x44D4: 9078c2ecf20Sopenharmony_ci case 0x44D8: 9088c2ecf20Sopenharmony_ci case 0x44DC: 9098c2ecf20Sopenharmony_ci case 0x44E0: 9108c2ecf20Sopenharmony_ci case 0x44E4: 9118c2ecf20Sopenharmony_ci case 0x44E8: 9128c2ecf20Sopenharmony_ci case 0x44EC: 9138c2ecf20Sopenharmony_ci case 0x44F0: 9148c2ecf20Sopenharmony_ci case 0x44F4: 9158c2ecf20Sopenharmony_ci case 0x44F8: 9168c2ecf20Sopenharmony_ci case 0x44FC: 9178c2ecf20Sopenharmony_ci /* TX_FORMAT1_[0-15] */ 9188c2ecf20Sopenharmony_ci i = (reg - 0x44C0) >> 2; 9198c2ecf20Sopenharmony_ci tmp = (idx_value >> 25) & 0x3; 9208c2ecf20Sopenharmony_ci track->textures[i].tex_coord_type = tmp; 9218c2ecf20Sopenharmony_ci switch ((idx_value & 0x1F)) { 9228c2ecf20Sopenharmony_ci case R300_TX_FORMAT_X8: 9238c2ecf20Sopenharmony_ci case R300_TX_FORMAT_Y4X4: 9248c2ecf20Sopenharmony_ci case R300_TX_FORMAT_Z3Y3X2: 9258c2ecf20Sopenharmony_ci track->textures[i].cpp = 1; 9268c2ecf20Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 9278c2ecf20Sopenharmony_ci break; 9288c2ecf20Sopenharmony_ci case R300_TX_FORMAT_X16: 9298c2ecf20Sopenharmony_ci case R300_TX_FORMAT_FL_I16: 9308c2ecf20Sopenharmony_ci case R300_TX_FORMAT_Y8X8: 9318c2ecf20Sopenharmony_ci case R300_TX_FORMAT_Z5Y6X5: 9328c2ecf20Sopenharmony_ci case R300_TX_FORMAT_Z6Y5X5: 9338c2ecf20Sopenharmony_ci case R300_TX_FORMAT_W4Z4Y4X4: 9348c2ecf20Sopenharmony_ci case R300_TX_FORMAT_W1Z5Y5X5: 9358c2ecf20Sopenharmony_ci case R300_TX_FORMAT_D3DMFT_CxV8U8: 9368c2ecf20Sopenharmony_ci case R300_TX_FORMAT_B8G8_B8G8: 9378c2ecf20Sopenharmony_ci case R300_TX_FORMAT_G8R8_G8B8: 9388c2ecf20Sopenharmony_ci track->textures[i].cpp = 2; 9398c2ecf20Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 9408c2ecf20Sopenharmony_ci break; 9418c2ecf20Sopenharmony_ci case R300_TX_FORMAT_Y16X16: 9428c2ecf20Sopenharmony_ci case R300_TX_FORMAT_FL_I16A16: 9438c2ecf20Sopenharmony_ci case R300_TX_FORMAT_Z11Y11X10: 9448c2ecf20Sopenharmony_ci case R300_TX_FORMAT_Z10Y11X11: 9458c2ecf20Sopenharmony_ci case R300_TX_FORMAT_W8Z8Y8X8: 9468c2ecf20Sopenharmony_ci case R300_TX_FORMAT_W2Z10Y10X10: 9478c2ecf20Sopenharmony_ci case 0x17: 9488c2ecf20Sopenharmony_ci case R300_TX_FORMAT_FL_I32: 9498c2ecf20Sopenharmony_ci case 0x1e: 9508c2ecf20Sopenharmony_ci track->textures[i].cpp = 4; 9518c2ecf20Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 9528c2ecf20Sopenharmony_ci break; 9538c2ecf20Sopenharmony_ci case R300_TX_FORMAT_W16Z16Y16X16: 9548c2ecf20Sopenharmony_ci case R300_TX_FORMAT_FL_R16G16B16A16: 9558c2ecf20Sopenharmony_ci case R300_TX_FORMAT_FL_I32A32: 9568c2ecf20Sopenharmony_ci track->textures[i].cpp = 8; 9578c2ecf20Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 9588c2ecf20Sopenharmony_ci break; 9598c2ecf20Sopenharmony_ci case R300_TX_FORMAT_FL_R32G32B32A32: 9608c2ecf20Sopenharmony_ci track->textures[i].cpp = 16; 9618c2ecf20Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_NONE; 9628c2ecf20Sopenharmony_ci break; 9638c2ecf20Sopenharmony_ci case R300_TX_FORMAT_DXT1: 9648c2ecf20Sopenharmony_ci track->textures[i].cpp = 1; 9658c2ecf20Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_DXT1; 9668c2ecf20Sopenharmony_ci break; 9678c2ecf20Sopenharmony_ci case R300_TX_FORMAT_ATI2N: 9688c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_R420) { 9698c2ecf20Sopenharmony_ci DRM_ERROR("Invalid texture format %u\n", 9708c2ecf20Sopenharmony_ci (idx_value & 0x1F)); 9718c2ecf20Sopenharmony_ci return -EINVAL; 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci /* The same rules apply as for DXT3/5. */ 9748c2ecf20Sopenharmony_ci fallthrough; 9758c2ecf20Sopenharmony_ci case R300_TX_FORMAT_DXT3: 9768c2ecf20Sopenharmony_ci case R300_TX_FORMAT_DXT5: 9778c2ecf20Sopenharmony_ci track->textures[i].cpp = 1; 9788c2ecf20Sopenharmony_ci track->textures[i].compress_format = R100_TRACK_COMP_DXT35; 9798c2ecf20Sopenharmony_ci break; 9808c2ecf20Sopenharmony_ci default: 9818c2ecf20Sopenharmony_ci DRM_ERROR("Invalid texture format %u\n", 9828c2ecf20Sopenharmony_ci (idx_value & 0x1F)); 9838c2ecf20Sopenharmony_ci return -EINVAL; 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci track->tex_dirty = true; 9868c2ecf20Sopenharmony_ci break; 9878c2ecf20Sopenharmony_ci case 0x4400: 9888c2ecf20Sopenharmony_ci case 0x4404: 9898c2ecf20Sopenharmony_ci case 0x4408: 9908c2ecf20Sopenharmony_ci case 0x440C: 9918c2ecf20Sopenharmony_ci case 0x4410: 9928c2ecf20Sopenharmony_ci case 0x4414: 9938c2ecf20Sopenharmony_ci case 0x4418: 9948c2ecf20Sopenharmony_ci case 0x441C: 9958c2ecf20Sopenharmony_ci case 0x4420: 9968c2ecf20Sopenharmony_ci case 0x4424: 9978c2ecf20Sopenharmony_ci case 0x4428: 9988c2ecf20Sopenharmony_ci case 0x442C: 9998c2ecf20Sopenharmony_ci case 0x4430: 10008c2ecf20Sopenharmony_ci case 0x4434: 10018c2ecf20Sopenharmony_ci case 0x4438: 10028c2ecf20Sopenharmony_ci case 0x443C: 10038c2ecf20Sopenharmony_ci /* TX_FILTER0_[0-15] */ 10048c2ecf20Sopenharmony_ci i = (reg - 0x4400) >> 2; 10058c2ecf20Sopenharmony_ci tmp = idx_value & 0x7; 10068c2ecf20Sopenharmony_ci if (tmp == 2 || tmp == 4 || tmp == 6) { 10078c2ecf20Sopenharmony_ci track->textures[i].roundup_w = false; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci tmp = (idx_value >> 3) & 0x7; 10108c2ecf20Sopenharmony_ci if (tmp == 2 || tmp == 4 || tmp == 6) { 10118c2ecf20Sopenharmony_ci track->textures[i].roundup_h = false; 10128c2ecf20Sopenharmony_ci } 10138c2ecf20Sopenharmony_ci track->tex_dirty = true; 10148c2ecf20Sopenharmony_ci break; 10158c2ecf20Sopenharmony_ci case 0x4500: 10168c2ecf20Sopenharmony_ci case 0x4504: 10178c2ecf20Sopenharmony_ci case 0x4508: 10188c2ecf20Sopenharmony_ci case 0x450C: 10198c2ecf20Sopenharmony_ci case 0x4510: 10208c2ecf20Sopenharmony_ci case 0x4514: 10218c2ecf20Sopenharmony_ci case 0x4518: 10228c2ecf20Sopenharmony_ci case 0x451C: 10238c2ecf20Sopenharmony_ci case 0x4520: 10248c2ecf20Sopenharmony_ci case 0x4524: 10258c2ecf20Sopenharmony_ci case 0x4528: 10268c2ecf20Sopenharmony_ci case 0x452C: 10278c2ecf20Sopenharmony_ci case 0x4530: 10288c2ecf20Sopenharmony_ci case 0x4534: 10298c2ecf20Sopenharmony_ci case 0x4538: 10308c2ecf20Sopenharmony_ci case 0x453C: 10318c2ecf20Sopenharmony_ci /* TX_FORMAT2_[0-15] */ 10328c2ecf20Sopenharmony_ci i = (reg - 0x4500) >> 2; 10338c2ecf20Sopenharmony_ci tmp = idx_value & 0x3FFF; 10348c2ecf20Sopenharmony_ci track->textures[i].pitch = tmp + 1; 10358c2ecf20Sopenharmony_ci if (p->rdev->family >= CHIP_RV515) { 10368c2ecf20Sopenharmony_ci tmp = ((idx_value >> 15) & 1) << 11; 10378c2ecf20Sopenharmony_ci track->textures[i].width_11 = tmp; 10388c2ecf20Sopenharmony_ci tmp = ((idx_value >> 16) & 1) << 11; 10398c2ecf20Sopenharmony_ci track->textures[i].height_11 = tmp; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci /* ATI1N */ 10428c2ecf20Sopenharmony_ci if (idx_value & (1 << 14)) { 10438c2ecf20Sopenharmony_ci /* The same rules apply as for DXT1. */ 10448c2ecf20Sopenharmony_ci track->textures[i].compress_format = 10458c2ecf20Sopenharmony_ci R100_TRACK_COMP_DXT1; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci } else if (idx_value & (1 << 14)) { 10488c2ecf20Sopenharmony_ci DRM_ERROR("Forbidden bit TXFORMAT_MSB\n"); 10498c2ecf20Sopenharmony_ci return -EINVAL; 10508c2ecf20Sopenharmony_ci } 10518c2ecf20Sopenharmony_ci track->tex_dirty = true; 10528c2ecf20Sopenharmony_ci break; 10538c2ecf20Sopenharmony_ci case 0x4480: 10548c2ecf20Sopenharmony_ci case 0x4484: 10558c2ecf20Sopenharmony_ci case 0x4488: 10568c2ecf20Sopenharmony_ci case 0x448C: 10578c2ecf20Sopenharmony_ci case 0x4490: 10588c2ecf20Sopenharmony_ci case 0x4494: 10598c2ecf20Sopenharmony_ci case 0x4498: 10608c2ecf20Sopenharmony_ci case 0x449C: 10618c2ecf20Sopenharmony_ci case 0x44A0: 10628c2ecf20Sopenharmony_ci case 0x44A4: 10638c2ecf20Sopenharmony_ci case 0x44A8: 10648c2ecf20Sopenharmony_ci case 0x44AC: 10658c2ecf20Sopenharmony_ci case 0x44B0: 10668c2ecf20Sopenharmony_ci case 0x44B4: 10678c2ecf20Sopenharmony_ci case 0x44B8: 10688c2ecf20Sopenharmony_ci case 0x44BC: 10698c2ecf20Sopenharmony_ci /* TX_FORMAT0_[0-15] */ 10708c2ecf20Sopenharmony_ci i = (reg - 0x4480) >> 2; 10718c2ecf20Sopenharmony_ci tmp = idx_value & 0x7FF; 10728c2ecf20Sopenharmony_ci track->textures[i].width = tmp + 1; 10738c2ecf20Sopenharmony_ci tmp = (idx_value >> 11) & 0x7FF; 10748c2ecf20Sopenharmony_ci track->textures[i].height = tmp + 1; 10758c2ecf20Sopenharmony_ci tmp = (idx_value >> 26) & 0xF; 10768c2ecf20Sopenharmony_ci track->textures[i].num_levels = tmp; 10778c2ecf20Sopenharmony_ci tmp = idx_value & (1 << 31); 10788c2ecf20Sopenharmony_ci track->textures[i].use_pitch = !!tmp; 10798c2ecf20Sopenharmony_ci tmp = (idx_value >> 22) & 0xF; 10808c2ecf20Sopenharmony_ci track->textures[i].txdepth = tmp; 10818c2ecf20Sopenharmony_ci track->tex_dirty = true; 10828c2ecf20Sopenharmony_ci break; 10838c2ecf20Sopenharmony_ci case R300_ZB_ZPASS_ADDR: 10848c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 10858c2ecf20Sopenharmony_ci if (r) { 10868c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 10878c2ecf20Sopenharmony_ci idx, reg); 10888c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 10898c2ecf20Sopenharmony_ci return r; 10908c2ecf20Sopenharmony_ci } 10918c2ecf20Sopenharmony_ci ib[idx] = idx_value + ((u32)reloc->gpu_offset); 10928c2ecf20Sopenharmony_ci break; 10938c2ecf20Sopenharmony_ci case 0x4e0c: 10948c2ecf20Sopenharmony_ci /* RB3D_COLOR_CHANNEL_MASK */ 10958c2ecf20Sopenharmony_ci track->color_channel_mask = idx_value; 10968c2ecf20Sopenharmony_ci track->cb_dirty = true; 10978c2ecf20Sopenharmony_ci break; 10988c2ecf20Sopenharmony_ci case 0x43a4: 10998c2ecf20Sopenharmony_ci /* SC_HYPERZ_EN */ 11008c2ecf20Sopenharmony_ci /* r300c emits this register - we need to disable hyperz for it 11018c2ecf20Sopenharmony_ci * without complaining */ 11028c2ecf20Sopenharmony_ci if (p->rdev->hyperz_filp != p->filp) { 11038c2ecf20Sopenharmony_ci if (idx_value & 0x1) 11048c2ecf20Sopenharmony_ci ib[idx] = idx_value & ~1; 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci break; 11078c2ecf20Sopenharmony_ci case 0x4f1c: 11088c2ecf20Sopenharmony_ci /* ZB_BW_CNTL */ 11098c2ecf20Sopenharmony_ci track->zb_cb_clear = !!(idx_value & (1 << 5)); 11108c2ecf20Sopenharmony_ci track->cb_dirty = true; 11118c2ecf20Sopenharmony_ci track->zb_dirty = true; 11128c2ecf20Sopenharmony_ci if (p->rdev->hyperz_filp != p->filp) { 11138c2ecf20Sopenharmony_ci if (idx_value & (R300_HIZ_ENABLE | 11148c2ecf20Sopenharmony_ci R300_RD_COMP_ENABLE | 11158c2ecf20Sopenharmony_ci R300_WR_COMP_ENABLE | 11168c2ecf20Sopenharmony_ci R300_FAST_FILL_ENABLE)) 11178c2ecf20Sopenharmony_ci goto fail; 11188c2ecf20Sopenharmony_ci } 11198c2ecf20Sopenharmony_ci break; 11208c2ecf20Sopenharmony_ci case 0x4e04: 11218c2ecf20Sopenharmony_ci /* RB3D_BLENDCNTL */ 11228c2ecf20Sopenharmony_ci track->blend_read_enable = !!(idx_value & (1 << 2)); 11238c2ecf20Sopenharmony_ci track->cb_dirty = true; 11248c2ecf20Sopenharmony_ci break; 11258c2ecf20Sopenharmony_ci case R300_RB3D_AARESOLVE_OFFSET: 11268c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 11278c2ecf20Sopenharmony_ci if (r) { 11288c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 11298c2ecf20Sopenharmony_ci idx, reg); 11308c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 11318c2ecf20Sopenharmony_ci return r; 11328c2ecf20Sopenharmony_ci } 11338c2ecf20Sopenharmony_ci track->aa.robj = reloc->robj; 11348c2ecf20Sopenharmony_ci track->aa.offset = idx_value; 11358c2ecf20Sopenharmony_ci track->aa_dirty = true; 11368c2ecf20Sopenharmony_ci ib[idx] = idx_value + ((u32)reloc->gpu_offset); 11378c2ecf20Sopenharmony_ci break; 11388c2ecf20Sopenharmony_ci case R300_RB3D_AARESOLVE_PITCH: 11398c2ecf20Sopenharmony_ci track->aa.pitch = idx_value & 0x3FFE; 11408c2ecf20Sopenharmony_ci track->aa_dirty = true; 11418c2ecf20Sopenharmony_ci break; 11428c2ecf20Sopenharmony_ci case R300_RB3D_AARESOLVE_CTL: 11438c2ecf20Sopenharmony_ci track->aaresolve = idx_value & 0x1; 11448c2ecf20Sopenharmony_ci track->aa_dirty = true; 11458c2ecf20Sopenharmony_ci break; 11468c2ecf20Sopenharmony_ci case 0x4f30: /* ZB_MASK_OFFSET */ 11478c2ecf20Sopenharmony_ci case 0x4f34: /* ZB_ZMASK_PITCH */ 11488c2ecf20Sopenharmony_ci case 0x4f44: /* ZB_HIZ_OFFSET */ 11498c2ecf20Sopenharmony_ci case 0x4f54: /* ZB_HIZ_PITCH */ 11508c2ecf20Sopenharmony_ci if (idx_value && (p->rdev->hyperz_filp != p->filp)) 11518c2ecf20Sopenharmony_ci goto fail; 11528c2ecf20Sopenharmony_ci break; 11538c2ecf20Sopenharmony_ci case 0x4028: 11548c2ecf20Sopenharmony_ci if (idx_value && (p->rdev->hyperz_filp != p->filp)) 11558c2ecf20Sopenharmony_ci goto fail; 11568c2ecf20Sopenharmony_ci /* GB_Z_PEQ_CONFIG */ 11578c2ecf20Sopenharmony_ci if (p->rdev->family >= CHIP_RV350) 11588c2ecf20Sopenharmony_ci break; 11598c2ecf20Sopenharmony_ci goto fail; 11608c2ecf20Sopenharmony_ci break; 11618c2ecf20Sopenharmony_ci case 0x4be8: 11628c2ecf20Sopenharmony_ci /* valid register only on RV530 */ 11638c2ecf20Sopenharmony_ci if (p->rdev->family == CHIP_RV530) 11648c2ecf20Sopenharmony_ci break; 11658c2ecf20Sopenharmony_ci /* fallthrough do not move */ 11668c2ecf20Sopenharmony_ci default: 11678c2ecf20Sopenharmony_ci goto fail; 11688c2ecf20Sopenharmony_ci } 11698c2ecf20Sopenharmony_ci return 0; 11708c2ecf20Sopenharmony_cifail: 11718c2ecf20Sopenharmony_ci pr_err("Forbidden register 0x%04X in cs at %d (val=%08x)\n", 11728c2ecf20Sopenharmony_ci reg, idx, idx_value); 11738c2ecf20Sopenharmony_ci return -EINVAL; 11748c2ecf20Sopenharmony_ci} 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_cistatic int r300_packet3_check(struct radeon_cs_parser *p, 11778c2ecf20Sopenharmony_ci struct radeon_cs_packet *pkt) 11788c2ecf20Sopenharmony_ci{ 11798c2ecf20Sopenharmony_ci struct radeon_bo_list *reloc; 11808c2ecf20Sopenharmony_ci struct r100_cs_track *track; 11818c2ecf20Sopenharmony_ci volatile uint32_t *ib; 11828c2ecf20Sopenharmony_ci unsigned idx; 11838c2ecf20Sopenharmony_ci int r; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci ib = p->ib.ptr; 11868c2ecf20Sopenharmony_ci idx = pkt->idx + 1; 11878c2ecf20Sopenharmony_ci track = (struct r100_cs_track *)p->track; 11888c2ecf20Sopenharmony_ci switch(pkt->opcode) { 11898c2ecf20Sopenharmony_ci case PACKET3_3D_LOAD_VBPNTR: 11908c2ecf20Sopenharmony_ci r = r100_packet3_load_vbpntr(p, pkt, idx); 11918c2ecf20Sopenharmony_ci if (r) 11928c2ecf20Sopenharmony_ci return r; 11938c2ecf20Sopenharmony_ci break; 11948c2ecf20Sopenharmony_ci case PACKET3_INDX_BUFFER: 11958c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 11968c2ecf20Sopenharmony_ci if (r) { 11978c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 11988c2ecf20Sopenharmony_ci radeon_cs_dump_packet(p, pkt); 11998c2ecf20Sopenharmony_ci return r; 12008c2ecf20Sopenharmony_ci } 12018c2ecf20Sopenharmony_ci ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->gpu_offset); 12028c2ecf20Sopenharmony_ci r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); 12038c2ecf20Sopenharmony_ci if (r) { 12048c2ecf20Sopenharmony_ci return r; 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci break; 12078c2ecf20Sopenharmony_ci /* Draw packet */ 12088c2ecf20Sopenharmony_ci case PACKET3_3D_DRAW_IMMD: 12098c2ecf20Sopenharmony_ci /* Number of dwords is vtx_size * (num_vertices - 1) 12108c2ecf20Sopenharmony_ci * PRIM_WALK must be equal to 3 vertex data in embedded 12118c2ecf20Sopenharmony_ci * in cmd stream */ 12128c2ecf20Sopenharmony_ci if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) { 12138c2ecf20Sopenharmony_ci DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); 12148c2ecf20Sopenharmony_ci return -EINVAL; 12158c2ecf20Sopenharmony_ci } 12168c2ecf20Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 12178c2ecf20Sopenharmony_ci track->immd_dwords = pkt->count - 1; 12188c2ecf20Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 12198c2ecf20Sopenharmony_ci if (r) { 12208c2ecf20Sopenharmony_ci return r; 12218c2ecf20Sopenharmony_ci } 12228c2ecf20Sopenharmony_ci break; 12238c2ecf20Sopenharmony_ci case PACKET3_3D_DRAW_IMMD_2: 12248c2ecf20Sopenharmony_ci /* Number of dwords is vtx_size * (num_vertices - 1) 12258c2ecf20Sopenharmony_ci * PRIM_WALK must be equal to 3 vertex data in embedded 12268c2ecf20Sopenharmony_ci * in cmd stream */ 12278c2ecf20Sopenharmony_ci if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) { 12288c2ecf20Sopenharmony_ci DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); 12298c2ecf20Sopenharmony_ci return -EINVAL; 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx); 12328c2ecf20Sopenharmony_ci track->immd_dwords = pkt->count; 12338c2ecf20Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 12348c2ecf20Sopenharmony_ci if (r) { 12358c2ecf20Sopenharmony_ci return r; 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci break; 12388c2ecf20Sopenharmony_ci case PACKET3_3D_DRAW_VBUF: 12398c2ecf20Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 12408c2ecf20Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 12418c2ecf20Sopenharmony_ci if (r) { 12428c2ecf20Sopenharmony_ci return r; 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci break; 12458c2ecf20Sopenharmony_ci case PACKET3_3D_DRAW_VBUF_2: 12468c2ecf20Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx); 12478c2ecf20Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 12488c2ecf20Sopenharmony_ci if (r) { 12498c2ecf20Sopenharmony_ci return r; 12508c2ecf20Sopenharmony_ci } 12518c2ecf20Sopenharmony_ci break; 12528c2ecf20Sopenharmony_ci case PACKET3_3D_DRAW_INDX: 12538c2ecf20Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 12548c2ecf20Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 12558c2ecf20Sopenharmony_ci if (r) { 12568c2ecf20Sopenharmony_ci return r; 12578c2ecf20Sopenharmony_ci } 12588c2ecf20Sopenharmony_ci break; 12598c2ecf20Sopenharmony_ci case PACKET3_3D_DRAW_INDX_2: 12608c2ecf20Sopenharmony_ci track->vap_vf_cntl = radeon_get_ib_value(p, idx); 12618c2ecf20Sopenharmony_ci r = r100_cs_track_check(p->rdev, track); 12628c2ecf20Sopenharmony_ci if (r) { 12638c2ecf20Sopenharmony_ci return r; 12648c2ecf20Sopenharmony_ci } 12658c2ecf20Sopenharmony_ci break; 12668c2ecf20Sopenharmony_ci case PACKET3_3D_CLEAR_HIZ: 12678c2ecf20Sopenharmony_ci case PACKET3_3D_CLEAR_ZMASK: 12688c2ecf20Sopenharmony_ci if (p->rdev->hyperz_filp != p->filp) 12698c2ecf20Sopenharmony_ci return -EINVAL; 12708c2ecf20Sopenharmony_ci break; 12718c2ecf20Sopenharmony_ci case PACKET3_3D_CLEAR_CMASK: 12728c2ecf20Sopenharmony_ci if (p->rdev->cmask_filp != p->filp) 12738c2ecf20Sopenharmony_ci return -EINVAL; 12748c2ecf20Sopenharmony_ci break; 12758c2ecf20Sopenharmony_ci case PACKET3_NOP: 12768c2ecf20Sopenharmony_ci break; 12778c2ecf20Sopenharmony_ci default: 12788c2ecf20Sopenharmony_ci DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 12798c2ecf20Sopenharmony_ci return -EINVAL; 12808c2ecf20Sopenharmony_ci } 12818c2ecf20Sopenharmony_ci return 0; 12828c2ecf20Sopenharmony_ci} 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ciint r300_cs_parse(struct radeon_cs_parser *p) 12858c2ecf20Sopenharmony_ci{ 12868c2ecf20Sopenharmony_ci struct radeon_cs_packet pkt; 12878c2ecf20Sopenharmony_ci struct r100_cs_track *track; 12888c2ecf20Sopenharmony_ci int r; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci track = kzalloc(sizeof(*track), GFP_KERNEL); 12918c2ecf20Sopenharmony_ci if (track == NULL) 12928c2ecf20Sopenharmony_ci return -ENOMEM; 12938c2ecf20Sopenharmony_ci r100_cs_track_clear(p->rdev, track); 12948c2ecf20Sopenharmony_ci p->track = track; 12958c2ecf20Sopenharmony_ci do { 12968c2ecf20Sopenharmony_ci r = radeon_cs_packet_parse(p, &pkt, p->idx); 12978c2ecf20Sopenharmony_ci if (r) { 12988c2ecf20Sopenharmony_ci return r; 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci p->idx += pkt.count + 2; 13018c2ecf20Sopenharmony_ci switch (pkt.type) { 13028c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE0: 13038c2ecf20Sopenharmony_ci r = r100_cs_parse_packet0(p, &pkt, 13048c2ecf20Sopenharmony_ci p->rdev->config.r300.reg_safe_bm, 13058c2ecf20Sopenharmony_ci p->rdev->config.r300.reg_safe_bm_size, 13068c2ecf20Sopenharmony_ci &r300_packet0_check); 13078c2ecf20Sopenharmony_ci break; 13088c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE2: 13098c2ecf20Sopenharmony_ci break; 13108c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE3: 13118c2ecf20Sopenharmony_ci r = r300_packet3_check(p, &pkt); 13128c2ecf20Sopenharmony_ci break; 13138c2ecf20Sopenharmony_ci default: 13148c2ecf20Sopenharmony_ci DRM_ERROR("Unknown packet type %d !\n", pkt.type); 13158c2ecf20Sopenharmony_ci return -EINVAL; 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci if (r) { 13188c2ecf20Sopenharmony_ci return r; 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci } while (p->idx < p->chunk_ib->length_dw); 13218c2ecf20Sopenharmony_ci return 0; 13228c2ecf20Sopenharmony_ci} 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_civoid r300_set_reg_safe(struct radeon_device *rdev) 13258c2ecf20Sopenharmony_ci{ 13268c2ecf20Sopenharmony_ci rdev->config.r300.reg_safe_bm = r300_reg_safe_bm; 13278c2ecf20Sopenharmony_ci rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm); 13288c2ecf20Sopenharmony_ci} 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_civoid r300_mc_program(struct radeon_device *rdev) 13318c2ecf20Sopenharmony_ci{ 13328c2ecf20Sopenharmony_ci struct r100_mc_save save; 13338c2ecf20Sopenharmony_ci int r; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci r = r100_debugfs_mc_info_init(rdev); 13368c2ecf20Sopenharmony_ci if (r) { 13378c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Failed to create r100_mc debugfs file.\n"); 13388c2ecf20Sopenharmony_ci } 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci /* Stops all mc clients */ 13418c2ecf20Sopenharmony_ci r100_mc_stop(rdev, &save); 13428c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 13438c2ecf20Sopenharmony_ci WREG32(R_00014C_MC_AGP_LOCATION, 13448c2ecf20Sopenharmony_ci S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | 13458c2ecf20Sopenharmony_ci S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); 13468c2ecf20Sopenharmony_ci WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); 13478c2ecf20Sopenharmony_ci WREG32(R_00015C_AGP_BASE_2, 13488c2ecf20Sopenharmony_ci upper_32_bits(rdev->mc.agp_base) & 0xff); 13498c2ecf20Sopenharmony_ci } else { 13508c2ecf20Sopenharmony_ci WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF); 13518c2ecf20Sopenharmony_ci WREG32(R_000170_AGP_BASE, 0); 13528c2ecf20Sopenharmony_ci WREG32(R_00015C_AGP_BASE_2, 0); 13538c2ecf20Sopenharmony_ci } 13548c2ecf20Sopenharmony_ci /* Wait for mc idle */ 13558c2ecf20Sopenharmony_ci if (r300_mc_wait_for_idle(rdev)) 13568c2ecf20Sopenharmony_ci DRM_INFO("Failed to wait MC idle before programming MC.\n"); 13578c2ecf20Sopenharmony_ci /* Program MC, should be a 32bits limited address space */ 13588c2ecf20Sopenharmony_ci WREG32(R_000148_MC_FB_LOCATION, 13598c2ecf20Sopenharmony_ci S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | 13608c2ecf20Sopenharmony_ci S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); 13618c2ecf20Sopenharmony_ci r100_mc_resume(rdev, &save); 13628c2ecf20Sopenharmony_ci} 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_civoid r300_clock_startup(struct radeon_device *rdev) 13658c2ecf20Sopenharmony_ci{ 13668c2ecf20Sopenharmony_ci u32 tmp; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci if (radeon_dynclks != -1 && radeon_dynclks) 13698c2ecf20Sopenharmony_ci radeon_legacy_set_clock_gating(rdev, 1); 13708c2ecf20Sopenharmony_ci /* We need to force on some of the block */ 13718c2ecf20Sopenharmony_ci tmp = RREG32_PLL(R_00000D_SCLK_CNTL); 13728c2ecf20Sopenharmony_ci tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); 13738c2ecf20Sopenharmony_ci if ((rdev->family == CHIP_RV350) || (rdev->family == CHIP_RV380)) 13748c2ecf20Sopenharmony_ci tmp |= S_00000D_FORCE_VAP(1); 13758c2ecf20Sopenharmony_ci WREG32_PLL(R_00000D_SCLK_CNTL, tmp); 13768c2ecf20Sopenharmony_ci} 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_cistatic int r300_startup(struct radeon_device *rdev) 13798c2ecf20Sopenharmony_ci{ 13808c2ecf20Sopenharmony_ci int r; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci /* set common regs */ 13838c2ecf20Sopenharmony_ci r100_set_common_regs(rdev); 13848c2ecf20Sopenharmony_ci /* program mc */ 13858c2ecf20Sopenharmony_ci r300_mc_program(rdev); 13868c2ecf20Sopenharmony_ci /* Resume clock */ 13878c2ecf20Sopenharmony_ci r300_clock_startup(rdev); 13888c2ecf20Sopenharmony_ci /* Initialize GPU configuration (# pipes, ...) */ 13898c2ecf20Sopenharmony_ci r300_gpu_init(rdev); 13908c2ecf20Sopenharmony_ci /* Initialize GART (initialize after TTM so we can allocate 13918c2ecf20Sopenharmony_ci * memory through TTM but finalize after TTM) */ 13928c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) { 13938c2ecf20Sopenharmony_ci r = rv370_pcie_gart_enable(rdev); 13948c2ecf20Sopenharmony_ci if (r) 13958c2ecf20Sopenharmony_ci return r; 13968c2ecf20Sopenharmony_ci } 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci if (rdev->family == CHIP_R300 || 13998c2ecf20Sopenharmony_ci rdev->family == CHIP_R350 || 14008c2ecf20Sopenharmony_ci rdev->family == CHIP_RV350) 14018c2ecf20Sopenharmony_ci r100_enable_bm(rdev); 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) { 14048c2ecf20Sopenharmony_ci r = r100_pci_gart_enable(rdev); 14058c2ecf20Sopenharmony_ci if (r) 14068c2ecf20Sopenharmony_ci return r; 14078c2ecf20Sopenharmony_ci } 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci /* allocate wb buffer */ 14108c2ecf20Sopenharmony_ci r = radeon_wb_init(rdev); 14118c2ecf20Sopenharmony_ci if (r) 14128c2ecf20Sopenharmony_ci return r; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 14158c2ecf20Sopenharmony_ci if (r) { 14168c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 14178c2ecf20Sopenharmony_ci return r; 14188c2ecf20Sopenharmony_ci } 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci /* Enable IRQ */ 14218c2ecf20Sopenharmony_ci if (!rdev->irq.installed) { 14228c2ecf20Sopenharmony_ci r = radeon_irq_kms_init(rdev); 14238c2ecf20Sopenharmony_ci if (r) 14248c2ecf20Sopenharmony_ci return r; 14258c2ecf20Sopenharmony_ci } 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci r100_irq_set(rdev); 14288c2ecf20Sopenharmony_ci rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); 14298c2ecf20Sopenharmony_ci /* 1M ring buffer */ 14308c2ecf20Sopenharmony_ci r = r100_cp_init(rdev, 1024 * 1024); 14318c2ecf20Sopenharmony_ci if (r) { 14328c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP (%d).\n", r); 14338c2ecf20Sopenharmony_ci return r; 14348c2ecf20Sopenharmony_ci } 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci r = radeon_ib_pool_init(rdev); 14378c2ecf20Sopenharmony_ci if (r) { 14388c2ecf20Sopenharmony_ci dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 14398c2ecf20Sopenharmony_ci return r; 14408c2ecf20Sopenharmony_ci } 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci return 0; 14438c2ecf20Sopenharmony_ci} 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ciint r300_resume(struct radeon_device *rdev) 14468c2ecf20Sopenharmony_ci{ 14478c2ecf20Sopenharmony_ci int r; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci /* Make sur GART are not working */ 14508c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 14518c2ecf20Sopenharmony_ci rv370_pcie_gart_disable(rdev); 14528c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 14538c2ecf20Sopenharmony_ci r100_pci_gart_disable(rdev); 14548c2ecf20Sopenharmony_ci /* Resume clock before doing reset */ 14558c2ecf20Sopenharmony_ci r300_clock_startup(rdev); 14568c2ecf20Sopenharmony_ci /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 14578c2ecf20Sopenharmony_ci if (radeon_asic_reset(rdev)) { 14588c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 14598c2ecf20Sopenharmony_ci RREG32(R_000E40_RBBM_STATUS), 14608c2ecf20Sopenharmony_ci RREG32(R_0007C0_CP_STAT)); 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci /* post */ 14638c2ecf20Sopenharmony_ci radeon_combios_asic_init(rdev->ddev); 14648c2ecf20Sopenharmony_ci /* Resume clock after posting */ 14658c2ecf20Sopenharmony_ci r300_clock_startup(rdev); 14668c2ecf20Sopenharmony_ci /* Initialize surface registers */ 14678c2ecf20Sopenharmony_ci radeon_surface_init(rdev); 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci rdev->accel_working = true; 14708c2ecf20Sopenharmony_ci r = r300_startup(rdev); 14718c2ecf20Sopenharmony_ci if (r) { 14728c2ecf20Sopenharmony_ci rdev->accel_working = false; 14738c2ecf20Sopenharmony_ci } 14748c2ecf20Sopenharmony_ci return r; 14758c2ecf20Sopenharmony_ci} 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ciint r300_suspend(struct radeon_device *rdev) 14788c2ecf20Sopenharmony_ci{ 14798c2ecf20Sopenharmony_ci radeon_pm_suspend(rdev); 14808c2ecf20Sopenharmony_ci r100_cp_disable(rdev); 14818c2ecf20Sopenharmony_ci radeon_wb_disable(rdev); 14828c2ecf20Sopenharmony_ci r100_irq_disable(rdev); 14838c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 14848c2ecf20Sopenharmony_ci rv370_pcie_gart_disable(rdev); 14858c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 14868c2ecf20Sopenharmony_ci r100_pci_gart_disable(rdev); 14878c2ecf20Sopenharmony_ci return 0; 14888c2ecf20Sopenharmony_ci} 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_civoid r300_fini(struct radeon_device *rdev) 14918c2ecf20Sopenharmony_ci{ 14928c2ecf20Sopenharmony_ci radeon_pm_fini(rdev); 14938c2ecf20Sopenharmony_ci r100_cp_fini(rdev); 14948c2ecf20Sopenharmony_ci radeon_wb_fini(rdev); 14958c2ecf20Sopenharmony_ci radeon_ib_pool_fini(rdev); 14968c2ecf20Sopenharmony_ci radeon_gem_fini(rdev); 14978c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 14988c2ecf20Sopenharmony_ci rv370_pcie_gart_fini(rdev); 14998c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 15008c2ecf20Sopenharmony_ci r100_pci_gart_fini(rdev); 15018c2ecf20Sopenharmony_ci radeon_agp_fini(rdev); 15028c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 15038c2ecf20Sopenharmony_ci radeon_fence_driver_fini(rdev); 15048c2ecf20Sopenharmony_ci radeon_bo_fini(rdev); 15058c2ecf20Sopenharmony_ci radeon_atombios_fini(rdev); 15068c2ecf20Sopenharmony_ci kfree(rdev->bios); 15078c2ecf20Sopenharmony_ci rdev->bios = NULL; 15088c2ecf20Sopenharmony_ci} 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ciint r300_init(struct radeon_device *rdev) 15118c2ecf20Sopenharmony_ci{ 15128c2ecf20Sopenharmony_ci int r; 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci /* Disable VGA */ 15158c2ecf20Sopenharmony_ci r100_vga_render_disable(rdev); 15168c2ecf20Sopenharmony_ci /* Initialize scratch registers */ 15178c2ecf20Sopenharmony_ci radeon_scratch_init(rdev); 15188c2ecf20Sopenharmony_ci /* Initialize surface registers */ 15198c2ecf20Sopenharmony_ci radeon_surface_init(rdev); 15208c2ecf20Sopenharmony_ci /* TODO: disable VGA need to use VGA request */ 15218c2ecf20Sopenharmony_ci /* restore some register to sane defaults */ 15228c2ecf20Sopenharmony_ci r100_restore_sanity(rdev); 15238c2ecf20Sopenharmony_ci /* BIOS*/ 15248c2ecf20Sopenharmony_ci if (!radeon_get_bios(rdev)) { 15258c2ecf20Sopenharmony_ci if (ASIC_IS_AVIVO(rdev)) 15268c2ecf20Sopenharmony_ci return -EINVAL; 15278c2ecf20Sopenharmony_ci } 15288c2ecf20Sopenharmony_ci if (rdev->is_atom_bios) { 15298c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n"); 15308c2ecf20Sopenharmony_ci return -EINVAL; 15318c2ecf20Sopenharmony_ci } else { 15328c2ecf20Sopenharmony_ci r = radeon_combios_init(rdev); 15338c2ecf20Sopenharmony_ci if (r) 15348c2ecf20Sopenharmony_ci return r; 15358c2ecf20Sopenharmony_ci } 15368c2ecf20Sopenharmony_ci /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 15378c2ecf20Sopenharmony_ci if (radeon_asic_reset(rdev)) { 15388c2ecf20Sopenharmony_ci dev_warn(rdev->dev, 15398c2ecf20Sopenharmony_ci "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 15408c2ecf20Sopenharmony_ci RREG32(R_000E40_RBBM_STATUS), 15418c2ecf20Sopenharmony_ci RREG32(R_0007C0_CP_STAT)); 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci /* check if cards are posted or not */ 15448c2ecf20Sopenharmony_ci if (radeon_boot_test_post_card(rdev) == false) 15458c2ecf20Sopenharmony_ci return -EINVAL; 15468c2ecf20Sopenharmony_ci /* Set asic errata */ 15478c2ecf20Sopenharmony_ci r300_errata(rdev); 15488c2ecf20Sopenharmony_ci /* Initialize clocks */ 15498c2ecf20Sopenharmony_ci radeon_get_clock_info(rdev->ddev); 15508c2ecf20Sopenharmony_ci /* initialize AGP */ 15518c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 15528c2ecf20Sopenharmony_ci r = radeon_agp_init(rdev); 15538c2ecf20Sopenharmony_ci if (r) { 15548c2ecf20Sopenharmony_ci radeon_agp_disable(rdev); 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci } 15578c2ecf20Sopenharmony_ci /* initialize memory controller */ 15588c2ecf20Sopenharmony_ci r300_mc_init(rdev); 15598c2ecf20Sopenharmony_ci /* Fence driver */ 15608c2ecf20Sopenharmony_ci r = radeon_fence_driver_init(rdev); 15618c2ecf20Sopenharmony_ci if (r) 15628c2ecf20Sopenharmony_ci return r; 15638c2ecf20Sopenharmony_ci /* Memory manager */ 15648c2ecf20Sopenharmony_ci r = radeon_bo_init(rdev); 15658c2ecf20Sopenharmony_ci if (r) 15668c2ecf20Sopenharmony_ci return r; 15678c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) { 15688c2ecf20Sopenharmony_ci r = rv370_pcie_gart_init(rdev); 15698c2ecf20Sopenharmony_ci if (r) 15708c2ecf20Sopenharmony_ci return r; 15718c2ecf20Sopenharmony_ci } 15728c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) { 15738c2ecf20Sopenharmony_ci r = r100_pci_gart_init(rdev); 15748c2ecf20Sopenharmony_ci if (r) 15758c2ecf20Sopenharmony_ci return r; 15768c2ecf20Sopenharmony_ci } 15778c2ecf20Sopenharmony_ci r300_set_reg_safe(rdev); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci /* Initialize power management */ 15808c2ecf20Sopenharmony_ci radeon_pm_init(rdev); 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci rdev->accel_working = true; 15838c2ecf20Sopenharmony_ci r = r300_startup(rdev); 15848c2ecf20Sopenharmony_ci if (r) { 15858c2ecf20Sopenharmony_ci /* Something went wrong with the accel init, so stop accel */ 15868c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Disabling GPU acceleration\n"); 15878c2ecf20Sopenharmony_ci r100_cp_fini(rdev); 15888c2ecf20Sopenharmony_ci radeon_wb_fini(rdev); 15898c2ecf20Sopenharmony_ci radeon_ib_pool_fini(rdev); 15908c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 15918c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCIE) 15928c2ecf20Sopenharmony_ci rv370_pcie_gart_fini(rdev); 15938c2ecf20Sopenharmony_ci if (rdev->flags & RADEON_IS_PCI) 15948c2ecf20Sopenharmony_ci r100_pci_gart_fini(rdev); 15958c2ecf20Sopenharmony_ci radeon_agp_fini(rdev); 15968c2ecf20Sopenharmony_ci rdev->accel_working = false; 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci return 0; 15998c2ecf20Sopenharmony_ci} 1600