radeon_cp.c revision 182080
1139749Simp/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */ 2139749Simp/*- 395584Sanholt * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. 495584Sanholt * Copyright 2000 VA Linux Systems, Inc., Fremont, California. 5182080Srnoland * Copyright 2007 Advanced Micro Devices, Inc. 695584Sanholt * All Rights Reserved. 795584Sanholt * 895584Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 995584Sanholt * copy of this software and associated documentation files (the "Software"), 1095584Sanholt * to deal in the Software without restriction, including without limitation 1195584Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1295584Sanholt * and/or sell copies of the Software, and to permit persons to whom the 1395584Sanholt * Software is furnished to do so, subject to the following conditions: 1495584Sanholt * 1595584Sanholt * The above copyright notice and this permission notice (including the next 1695584Sanholt * paragraph) shall be included in all copies or substantial portions of the 1795584Sanholt * Software. 1895584Sanholt * 1995584Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2095584Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2195584Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2295584Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2395584Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2495584Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2595584Sanholt * DEALINGS IN THE SOFTWARE. 2695584Sanholt * 2795584Sanholt * Authors: 2895584Sanholt * Kevin E. Martin <martin@valinux.com> 2995584Sanholt * Gareth Hughes <gareth@valinux.com> 3095584Sanholt */ 3195584Sanholt 32152909Sanholt#include <sys/cdefs.h> 33152909Sanholt__FBSDID("$FreeBSD: head/sys/dev/drm/radeon_cp.c 182080 2008-08-23 20:59:12Z rnoland $"); 34152909Sanholt 3595584Sanholt#include "dev/drm/drmP.h" 36112015Sanholt#include "dev/drm/drm.h" 3795746Sanholt#include "dev/drm/radeon_drm.h" 3895584Sanholt#include "dev/drm/radeon_drv.h" 39148211Sanholt#include "dev/drm/r300_reg.h" 4095584Sanholt 41182080Srnoland#include "dev/drm/radeon_microcode.h" 4295584Sanholt#define RADEON_FIFO_DEBUG 0 4395584Sanholt 44182080Srnolandstatic int radeon_do_cleanup_cp(struct drm_device * dev); 45182080Srnolandstatic void radeon_do_cp_start(drm_radeon_private_t * dev_priv); 4695584Sanholt 47182080Srnolandstatic u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) 48182080Srnoland{ 49182080Srnoland u32 ret; 50182080Srnoland RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff)); 51182080Srnoland ret = RADEON_READ(R520_MC_IND_DATA); 52182080Srnoland RADEON_WRITE(R520_MC_IND_INDEX, 0); 53182080Srnoland return ret; 54182080Srnoland} 55112015Sanholt 56182080Srnolandstatic u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) 57182080Srnoland{ 58182080Srnoland u32 ret; 59182080Srnoland RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff); 60182080Srnoland ret = RADEON_READ(RS480_NB_MC_DATA); 61182080Srnoland RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); 62182080Srnoland return ret; 63182080Srnoland} 64112015Sanholt 65182080Srnolandstatic u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) 66182080Srnoland{ 67182080Srnoland u32 ret; 68182080Srnoland RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK)); 69182080Srnoland ret = RADEON_READ(RS690_MC_DATA); 70182080Srnoland RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK); 71182080Srnoland return ret; 72182080Srnoland} 7395584Sanholt 74182080Srnolandstatic u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) 7595584Sanholt{ 76182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) 77182080Srnoland return RS690_READ_MCIND(dev_priv, addr); 78182080Srnoland else 79182080Srnoland return RS480_READ_MCIND(dev_priv, addr); 80182080Srnoland} 81182080Srnoland 82182080Srnolandu32 radeon_read_fb_location(drm_radeon_private_t *dev_priv) 83182080Srnoland{ 84182080Srnoland 85182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) 86182080Srnoland return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION); 87182080Srnoland else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) 88182080Srnoland return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION); 89182080Srnoland else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) 90182080Srnoland return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION); 91182080Srnoland else 92182080Srnoland return RADEON_READ(RADEON_MC_FB_LOCATION); 93182080Srnoland} 94182080Srnoland 95182080Srnolandstatic void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc) 96182080Srnoland{ 97182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) 98182080Srnoland R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc); 99182080Srnoland else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) 100182080Srnoland RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc); 101182080Srnoland else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) 102182080Srnoland R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc); 103182080Srnoland else 104182080Srnoland RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc); 105182080Srnoland} 106182080Srnoland 107182080Srnolandstatic void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc) 108182080Srnoland{ 109182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) 110182080Srnoland R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc); 111182080Srnoland else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) 112182080Srnoland RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc); 113182080Srnoland else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) 114182080Srnoland R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc); 115182080Srnoland else 116182080Srnoland RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc); 117182080Srnoland} 118182080Srnoland 119182080Srnolandstatic void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base) 120182080Srnoland{ 121182080Srnoland u32 agp_base_hi = upper_32_bits(agp_base); 122182080Srnoland u32 agp_base_lo = agp_base & 0xffffffff; 123182080Srnoland 124182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) { 125182080Srnoland R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo); 126182080Srnoland R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi); 127182080Srnoland } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) { 128182080Srnoland RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo); 129182080Srnoland RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi); 130182080Srnoland } else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) { 131182080Srnoland R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo); 132182080Srnoland R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi); 133182080Srnoland } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || 134182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { 135182080Srnoland RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo); 136182080Srnoland RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi); 137182080Srnoland } else { 138182080Srnoland RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo); 139182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200) 140182080Srnoland RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi); 141182080Srnoland } 142182080Srnoland} 143182080Srnoland 144182080Srnolandstatic int RADEON_READ_PLL(struct drm_device * dev, int addr) 145182080Srnoland{ 14695584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 14795584Sanholt 14895584Sanholt RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f); 14995584Sanholt return RADEON_READ(RADEON_CLOCK_CNTL_DATA); 15095584Sanholt} 15195584Sanholt 152182080Srnolandstatic u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) 153148211Sanholt{ 154148211Sanholt RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); 155148211Sanholt return RADEON_READ(RADEON_PCIE_DATA); 156148211Sanholt} 157148211Sanholt 15895584Sanholt#if RADEON_FIFO_DEBUG 159145132Sanholtstatic void radeon_status(drm_radeon_private_t * dev_priv) 16095584Sanholt{ 161145132Sanholt printk("%s:\n", __FUNCTION__); 162145132Sanholt printk("RBBM_STATUS = 0x%08x\n", 163145132Sanholt (unsigned int)RADEON_READ(RADEON_RBBM_STATUS)); 164145132Sanholt printk("CP_RB_RTPR = 0x%08x\n", 165145132Sanholt (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR)); 166145132Sanholt printk("CP_RB_WTPR = 0x%08x\n", 167145132Sanholt (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR)); 168145132Sanholt printk("AIC_CNTL = 0x%08x\n", 169145132Sanholt (unsigned int)RADEON_READ(RADEON_AIC_CNTL)); 170145132Sanholt printk("AIC_STAT = 0x%08x\n", 171145132Sanholt (unsigned int)RADEON_READ(RADEON_AIC_STAT)); 172145132Sanholt printk("AIC_PT_BASE = 0x%08x\n", 173145132Sanholt (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE)); 174145132Sanholt printk("TLB_ADDR = 0x%08x\n", 175145132Sanholt (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR)); 176145132Sanholt printk("TLB_DATA = 0x%08x\n", 177145132Sanholt (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA)); 17895584Sanholt} 17995584Sanholt#endif 18095584Sanholt 18195584Sanholt/* ================================================================ 18295584Sanholt * Engine, FIFO control 18395584Sanholt */ 18495584Sanholt 185145132Sanholtstatic int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) 18695584Sanholt{ 18795584Sanholt u32 tmp; 18895584Sanholt int i; 18995584Sanholt 190112015Sanholt dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 191112015Sanholt 192182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { 193182080Srnoland tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT); 194182080Srnoland tmp |= RADEON_RB3D_DC_FLUSH_ALL; 195182080Srnoland RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp); 19695584Sanholt 197182080Srnoland for (i = 0; i < dev_priv->usec_timeout; i++) { 198182080Srnoland if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) 199182080Srnoland & RADEON_RB3D_DC_BUSY)) { 200182080Srnoland return 0; 201182080Srnoland } 202182080Srnoland DRM_UDELAY(1); 20395584Sanholt } 204182080Srnoland } else { 205182080Srnoland /* don't flush or purge cache here or lockup */ 206182080Srnoland return 0; 20795584Sanholt } 20895584Sanholt 20995584Sanholt#if RADEON_FIFO_DEBUG 210145132Sanholt DRM_ERROR("failed!\n"); 211145132Sanholt radeon_status(dev_priv); 21295584Sanholt#endif 213182080Srnoland return -EBUSY; 21495584Sanholt} 21595584Sanholt 216145132Sanholtstatic int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) 21795584Sanholt{ 21895584Sanholt int i; 21995584Sanholt 220112015Sanholt dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 221112015Sanholt 222145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 223145132Sanholt int slots = (RADEON_READ(RADEON_RBBM_STATUS) 224145132Sanholt & RADEON_RBBM_FIFOCNT_MASK); 225145132Sanholt if (slots >= entries) 226145132Sanholt return 0; 227145132Sanholt DRM_UDELAY(1); 22895584Sanholt } 229182080Srnoland DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n", 230182080Srnoland RADEON_READ(RADEON_RBBM_STATUS), 231182080Srnoland RADEON_READ(R300_VAP_CNTL_STATUS)); 23295584Sanholt 23395584Sanholt#if RADEON_FIFO_DEBUG 234145132Sanholt DRM_ERROR("failed!\n"); 235145132Sanholt radeon_status(dev_priv); 23695584Sanholt#endif 237182080Srnoland return -EBUSY; 23895584Sanholt} 23995584Sanholt 240145132Sanholtstatic int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) 24195584Sanholt{ 24295584Sanholt int i, ret; 24395584Sanholt 244112015Sanholt dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 245112015Sanholt 246145132Sanholt ret = radeon_do_wait_for_fifo(dev_priv, 64); 247145132Sanholt if (ret) 248145132Sanholt return ret; 249112015Sanholt 250145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 251145132Sanholt if (!(RADEON_READ(RADEON_RBBM_STATUS) 252145132Sanholt & RADEON_RBBM_ACTIVE)) { 253145132Sanholt radeon_do_pixcache_flush(dev_priv); 25495584Sanholt return 0; 25595584Sanholt } 256145132Sanholt DRM_UDELAY(1); 25795584Sanholt } 258182080Srnoland DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n", 259182080Srnoland RADEON_READ(RADEON_RBBM_STATUS), 260182080Srnoland RADEON_READ(R300_VAP_CNTL_STATUS)); 26195584Sanholt 26295584Sanholt#if RADEON_FIFO_DEBUG 263145132Sanholt DRM_ERROR("failed!\n"); 264145132Sanholt radeon_status(dev_priv); 26595584Sanholt#endif 266182080Srnoland return -EBUSY; 26795584Sanholt} 26895584Sanholt 269182080Srnolandstatic void radeon_init_pipes(drm_radeon_private_t * dev_priv) 270182080Srnoland{ 271182080Srnoland uint32_t gb_tile_config, gb_pipe_sel = 0; 272182080Srnoland 273182080Srnoland /* RS4xx/RS6xx/R4xx/R5xx */ 274182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) { 275182080Srnoland gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT); 276182080Srnoland dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; 277182080Srnoland } else { 278182080Srnoland /* R3xx */ 279182080Srnoland if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) || 280182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) { 281182080Srnoland dev_priv->num_gb_pipes = 2; 282182080Srnoland } else { 283182080Srnoland /* R3Vxx */ 284182080Srnoland dev_priv->num_gb_pipes = 1; 285182080Srnoland } 286182080Srnoland } 287182080Srnoland DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes); 288182080Srnoland 289182080Srnoland gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/); 290182080Srnoland 291182080Srnoland switch(dev_priv->num_gb_pipes) { 292182080Srnoland case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; 293182080Srnoland case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; 294182080Srnoland case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; 295182080Srnoland default: 296182080Srnoland case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; 297182080Srnoland } 298182080Srnoland 299182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { 300182080Srnoland RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); 301182080Srnoland RADEON_WRITE(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1)); 302182080Srnoland } 303182080Srnoland RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config); 304182080Srnoland radeon_do_wait_for_idle(dev_priv); 305182080Srnoland RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); 306182080Srnoland RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) | 307182080Srnoland R300_DC_AUTOFLUSH_ENABLE | 308182080Srnoland R300_DC_DC_DISABLE_IGNORE_PE)); 309182080Srnoland 310182080Srnoland 311182080Srnoland} 312182080Srnoland 31395584Sanholt/* ================================================================ 31495584Sanholt * CP control, initialization 31595584Sanholt */ 31695584Sanholt 31795584Sanholt/* Load the microcode for the CP */ 318145132Sanholtstatic void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv) 31995584Sanholt{ 32095584Sanholt int i; 321145132Sanholt DRM_DEBUG("\n"); 32295584Sanholt 323145132Sanholt radeon_do_wait_for_idle(dev_priv); 32495584Sanholt 325145132Sanholt RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0); 326112015Sanholt 327182080Srnoland if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) || 328182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) || 329182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) || 330182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) || 331182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) { 332182080Srnoland DRM_INFO("Loading R100 Microcode\n"); 333182080Srnoland for (i = 0; i < 256; i++) { 334182080Srnoland RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, 335182080Srnoland R100_cp_microcode[i][1]); 336182080Srnoland RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, 337182080Srnoland R100_cp_microcode[i][0]); 338182080Srnoland } 339182080Srnoland } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) || 340182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) || 341182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) || 342182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) { 343112015Sanholt DRM_INFO("Loading R200 Microcode\n"); 344145132Sanholt for (i = 0; i < 256; i++) { 345145132Sanholt RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, 346145132Sanholt R200_cp_microcode[i][1]); 347145132Sanholt RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, 348145132Sanholt R200_cp_microcode[i][0]); 349112015Sanholt } 350182080Srnoland } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) || 351182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) || 352182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) || 353182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) || 354182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || 355182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { 356145132Sanholt DRM_INFO("Loading R300 Microcode\n"); 357157617Sanholt for (i = 0; i < 256; i++) { 358157617Sanholt RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, 359157617Sanholt R300_cp_microcode[i][1]); 360157617Sanholt RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, 361157617Sanholt R300_cp_microcode[i][0]); 362112015Sanholt } 363182080Srnoland } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || 364182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) { 365182080Srnoland DRM_INFO("Loading R400 Microcode\n"); 366145132Sanholt for (i = 0; i < 256; i++) { 367145132Sanholt RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, 368182080Srnoland R420_cp_microcode[i][1]); 369145132Sanholt RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, 370182080Srnoland R420_cp_microcode[i][0]); 371145132Sanholt } 372182080Srnoland } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) { 373182080Srnoland DRM_INFO("Loading RS690 Microcode\n"); 374182080Srnoland for (i = 0; i < 256; i++) { 375182080Srnoland RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, 376182080Srnoland RS690_cp_microcode[i][1]); 377182080Srnoland RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, 378182080Srnoland RS690_cp_microcode[i][0]); 379182080Srnoland } 380182080Srnoland } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) || 381182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) || 382182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) || 383182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) || 384182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) || 385182080Srnoland ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) { 386182080Srnoland DRM_INFO("Loading R500 Microcode\n"); 387182080Srnoland for (i = 0; i < 256; i++) { 388182080Srnoland RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, 389182080Srnoland R520_cp_microcode[i][1]); 390182080Srnoland RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, 391182080Srnoland R520_cp_microcode[i][0]); 392182080Srnoland } 393112015Sanholt } 39495584Sanholt} 39595584Sanholt 39695584Sanholt/* Flush any pending commands to the CP. This should only be used just 39795584Sanholt * prior to a wait for idle, as it informs the engine that the command 39895584Sanholt * stream is ending. 39995584Sanholt */ 400145132Sanholtstatic void radeon_do_cp_flush(drm_radeon_private_t * dev_priv) 40195584Sanholt{ 402145132Sanholt DRM_DEBUG("\n"); 40395584Sanholt#if 0 40495584Sanholt u32 tmp; 40595584Sanholt 406145132Sanholt tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31); 407145132Sanholt RADEON_WRITE(RADEON_CP_RB_WPTR, tmp); 40895584Sanholt#endif 40995584Sanholt} 41095584Sanholt 41195584Sanholt/* Wait for the CP to go idle. 41295584Sanholt */ 413145132Sanholtint radeon_do_cp_idle(drm_radeon_private_t * dev_priv) 41495584Sanholt{ 41595584Sanholt RING_LOCALS; 416145132Sanholt DRM_DEBUG("\n"); 41795584Sanholt 418145132Sanholt BEGIN_RING(6); 41995584Sanholt 42095584Sanholt RADEON_PURGE_CACHE(); 42195584Sanholt RADEON_PURGE_ZCACHE(); 42295584Sanholt RADEON_WAIT_UNTIL_IDLE(); 42395584Sanholt 42495584Sanholt ADVANCE_RING(); 425112015Sanholt COMMIT_RING(); 42695584Sanholt 427145132Sanholt return radeon_do_wait_for_idle(dev_priv); 42895584Sanholt} 42995584Sanholt 43095584Sanholt/* Start the Command Processor. 43195584Sanholt */ 432145132Sanholtstatic void radeon_do_cp_start(drm_radeon_private_t * dev_priv) 43395584Sanholt{ 43495584Sanholt RING_LOCALS; 435145132Sanholt DRM_DEBUG("\n"); 43695584Sanholt 437145132Sanholt radeon_do_wait_for_idle(dev_priv); 43895584Sanholt 439145132Sanholt RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode); 44095584Sanholt 44195584Sanholt dev_priv->cp_running = 1; 44295584Sanholt 443182080Srnoland BEGIN_RING(8); 444182080Srnoland /* isync can only be written through cp on r5xx write it here */ 445182080Srnoland OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0)); 446182080Srnoland OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D | 447182080Srnoland RADEON_ISYNC_ANY3D_IDLE2D | 448182080Srnoland RADEON_ISYNC_WAIT_IDLEGUI | 449182080Srnoland RADEON_ISYNC_CPSCRATCH_IDLEGUI); 45095584Sanholt RADEON_PURGE_CACHE(); 45195584Sanholt RADEON_PURGE_ZCACHE(); 45295584Sanholt RADEON_WAIT_UNTIL_IDLE(); 45395584Sanholt ADVANCE_RING(); 454112015Sanholt COMMIT_RING(); 455182080Srnoland 456182080Srnoland dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; 45795584Sanholt} 45895584Sanholt 45995584Sanholt/* Reset the Command Processor. This will not flush any pending 46095584Sanholt * commands, so you must wait for the CP command stream to complete 46195584Sanholt * before calling this routine. 46295584Sanholt */ 463145132Sanholtstatic void radeon_do_cp_reset(drm_radeon_private_t * dev_priv) 46495584Sanholt{ 46595584Sanholt u32 cur_read_ptr; 466145132Sanholt DRM_DEBUG("\n"); 46795584Sanholt 468145132Sanholt cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); 469145132Sanholt RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); 470145132Sanholt SET_RING_HEAD(dev_priv, cur_read_ptr); 47195584Sanholt dev_priv->ring.tail = cur_read_ptr; 47295584Sanholt} 47395584Sanholt 47495584Sanholt/* Stop the Command Processor. This will not flush any pending 47595584Sanholt * commands, so you must flush the command stream and wait for the CP 47695584Sanholt * to go idle before calling this routine. 47795584Sanholt */ 478145132Sanholtstatic void radeon_do_cp_stop(drm_radeon_private_t * dev_priv) 47995584Sanholt{ 480145132Sanholt DRM_DEBUG("\n"); 48195584Sanholt 482145132Sanholt RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS); 48395584Sanholt 48495584Sanholt dev_priv->cp_running = 0; 48595584Sanholt} 48695584Sanholt 48795584Sanholt/* Reset the engine. This will stop the CP if it is running. 48895584Sanholt */ 489182080Srnolandstatic int radeon_do_engine_reset(struct drm_device * dev) 49095584Sanholt{ 49195584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 492182080Srnoland u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset; 493145132Sanholt DRM_DEBUG("\n"); 49495584Sanholt 495145132Sanholt radeon_do_pixcache_flush(dev_priv); 49695584Sanholt 497182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) { 498182080Srnoland /* may need something similar for newer chips */ 499182080Srnoland clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX); 500182080Srnoland mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL); 50195584Sanholt 502182080Srnoland RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl | 503182080Srnoland RADEON_FORCEON_MCLKA | 504182080Srnoland RADEON_FORCEON_MCLKB | 505182080Srnoland RADEON_FORCEON_YCLKA | 506182080Srnoland RADEON_FORCEON_YCLKB | 507182080Srnoland RADEON_FORCEON_MC | 508182080Srnoland RADEON_FORCEON_AIC)); 509182080Srnoland } 51095584Sanholt 511145132Sanholt rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET); 51295584Sanholt 513145132Sanholt RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | 514145132Sanholt RADEON_SOFT_RESET_CP | 515145132Sanholt RADEON_SOFT_RESET_HI | 516145132Sanholt RADEON_SOFT_RESET_SE | 517145132Sanholt RADEON_SOFT_RESET_RE | 518145132Sanholt RADEON_SOFT_RESET_PP | 519145132Sanholt RADEON_SOFT_RESET_E2 | 520145132Sanholt RADEON_SOFT_RESET_RB)); 521145132Sanholt RADEON_READ(RADEON_RBBM_SOFT_RESET); 522145132Sanholt RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & 523145132Sanholt ~(RADEON_SOFT_RESET_CP | 52495584Sanholt RADEON_SOFT_RESET_HI | 52595584Sanholt RADEON_SOFT_RESET_SE | 52695584Sanholt RADEON_SOFT_RESET_RE | 52795584Sanholt RADEON_SOFT_RESET_PP | 52895584Sanholt RADEON_SOFT_RESET_E2 | 529145132Sanholt RADEON_SOFT_RESET_RB))); 530145132Sanholt RADEON_READ(RADEON_RBBM_SOFT_RESET); 53195584Sanholt 532182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) { 533182080Srnoland RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl); 534182080Srnoland RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); 535182080Srnoland RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); 536182080Srnoland } 53795584Sanholt 538182080Srnoland /* setup the raster pipes */ 539182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300) 540182080Srnoland radeon_init_pipes(dev_priv); 541182080Srnoland 54295584Sanholt /* Reset the CP ring */ 543145132Sanholt radeon_do_cp_reset(dev_priv); 54495584Sanholt 54595584Sanholt /* The CP is no longer running after an engine reset */ 54695584Sanholt dev_priv->cp_running = 0; 54795584Sanholt 54895584Sanholt /* Reset any pending vertex, indirect buffers */ 549145132Sanholt radeon_freelist_reset(dev); 55095584Sanholt 55195584Sanholt return 0; 55295584Sanholt} 55395584Sanholt 554182080Srnolandstatic void radeon_cp_init_ring_buffer(struct drm_device * dev, 555145132Sanholt drm_radeon_private_t * dev_priv) 55695584Sanholt{ 55795584Sanholt u32 ring_start, cur_read_ptr; 55895584Sanholt u32 tmp; 559182080Srnoland 560157617Sanholt /* Initialize the memory controller. With new memory map, the fb location 561157617Sanholt * is not changed, it should have been properly initialized already. Part 562157617Sanholt * of the problem is that the code below is bogus, assuming the GART is 563157617Sanholt * always appended to the fb which is not necessarily the case 564157617Sanholt */ 565157617Sanholt if (!dev_priv->new_memmap) 566182080Srnoland radeon_write_fb_location(dev_priv, 567157617Sanholt ((dev_priv->gart_vm_start - 1) & 0xffff0000) 568157617Sanholt | (dev_priv->fb_location >> 16)); 56995584Sanholt 570145132Sanholt#if __OS_HAS_AGP 571182080Srnoland if (dev_priv->flags & RADEON_IS_AGP) { 572182080Srnoland radeon_write_agp_base(dev_priv, dev->agp->base); 573182080Srnoland 574182080Srnoland radeon_write_agp_location(dev_priv, 575145132Sanholt (((dev_priv->gart_vm_start - 1 + 576145132Sanholt dev_priv->gart_size) & 0xffff0000) | 577145132Sanholt (dev_priv->gart_vm_start >> 16))); 57895584Sanholt 57995584Sanholt ring_start = (dev_priv->cp_ring->offset 580157617Sanholt - dev->agp->base 581157617Sanholt + dev_priv->gart_vm_start); 582145132Sanholt } else 58395584Sanholt#endif 58495584Sanholt ring_start = (dev_priv->cp_ring->offset 585157617Sanholt - (unsigned long)dev->sg->virtual 586157617Sanholt + dev_priv->gart_vm_start); 58795584Sanholt 588145132Sanholt RADEON_WRITE(RADEON_CP_RB_BASE, ring_start); 58995584Sanholt 59095584Sanholt /* Set the write pointer delay */ 591145132Sanholt RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0); 59295584Sanholt 59395584Sanholt /* Initialize the ring buffer's read and write pointers */ 594145132Sanholt cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); 595145132Sanholt RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); 596145132Sanholt SET_RING_HEAD(dev_priv, cur_read_ptr); 59795584Sanholt dev_priv->ring.tail = cur_read_ptr; 59895584Sanholt 599145132Sanholt#if __OS_HAS_AGP 600182080Srnoland if (dev_priv->flags & RADEON_IS_AGP) { 601145132Sanholt RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, 602145132Sanholt dev_priv->ring_rptr->offset 603145132Sanholt - dev->agp->base + dev_priv->gart_vm_start); 604113995Sanholt } else 605113995Sanholt#endif 606113995Sanholt { 607182080Srnoland struct drm_sg_mem *entry = dev->sg; 60895584Sanholt unsigned long tmp_ofs, page_ofs; 60995584Sanholt 610157617Sanholt tmp_ofs = dev_priv->ring_rptr->offset - 611157617Sanholt (unsigned long)dev->sg->virtual; 61295584Sanholt page_ofs = tmp_ofs >> PAGE_SHIFT; 61395584Sanholt 614145132Sanholt RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); 615145132Sanholt DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n", 616145132Sanholt (unsigned long)entry->busaddr[page_ofs], 617145132Sanholt entry->handle + tmp_ofs); 61895584Sanholt } 61995584Sanholt 620157617Sanholt /* Set ring buffer size */ 621157617Sanholt#ifdef __BIG_ENDIAN 622157617Sanholt RADEON_WRITE(RADEON_CP_RB_CNTL, 623182080Srnoland RADEON_BUF_SWAP_32BIT | 624182080Srnoland (dev_priv->ring.fetch_size_l2ow << 18) | 625182080Srnoland (dev_priv->ring.rptr_update_l2qw << 8) | 626182080Srnoland dev_priv->ring.size_l2qw); 627157617Sanholt#else 628182080Srnoland RADEON_WRITE(RADEON_CP_RB_CNTL, 629182080Srnoland (dev_priv->ring.fetch_size_l2ow << 18) | 630182080Srnoland (dev_priv->ring.rptr_update_l2qw << 8) | 631182080Srnoland dev_priv->ring.size_l2qw); 632157617Sanholt#endif 633157617Sanholt 634157617Sanholt /* Start with assuming that writeback doesn't work */ 635157617Sanholt dev_priv->writeback_works = 0; 636157617Sanholt 637112015Sanholt /* Initialize the scratch register pointer. This will cause 638112015Sanholt * the scratch register values to be written out to memory 639112015Sanholt * whenever they are updated. 640112015Sanholt * 641112015Sanholt * We simply put this behind the ring read pointer, this works 642112015Sanholt * with PCI GART as well as (whatever kind of) AGP GART 643112015Sanholt */ 644145132Sanholt RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR) 645145132Sanholt + RADEON_SCRATCH_REG_OFFSET); 646112015Sanholt 647112015Sanholt dev_priv->scratch = ((__volatile__ u32 *) 648113995Sanholt dev_priv->ring_rptr->handle + 649112015Sanholt (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); 650112015Sanholt 651145132Sanholt RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); 652112015Sanholt 653157617Sanholt /* Turn on bus mastering */ 654157617Sanholt tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 655157617Sanholt RADEON_WRITE(RADEON_BUS_CNTL, tmp); 656112015Sanholt 657112015Sanholt dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; 658145132Sanholt RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); 659112015Sanholt 660112015Sanholt dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0; 661145132Sanholt RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 662145132Sanholt dev_priv->sarea_priv->last_dispatch); 663112015Sanholt 664112015Sanholt dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; 665145132Sanholt RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); 666112015Sanholt 667145132Sanholt radeon_do_wait_for_idle(dev_priv); 66895584Sanholt 66995584Sanholt /* Sync everything up */ 670145132Sanholt RADEON_WRITE(RADEON_ISYNC_CNTL, 671145132Sanholt (RADEON_ISYNC_ANY2D_IDLE3D | 672145132Sanholt RADEON_ISYNC_ANY3D_IDLE2D | 673145132Sanholt RADEON_ISYNC_WAIT_IDLEGUI | 674145132Sanholt RADEON_ISYNC_CPSCRATCH_IDLEGUI)); 675157617Sanholt 67695584Sanholt} 67795584Sanholt 678157617Sanholtstatic void radeon_test_writeback(drm_radeon_private_t * dev_priv) 679157617Sanholt{ 680157617Sanholt u32 tmp; 681157617Sanholt 682157617Sanholt /* Writeback doesn't seem to work everywhere, test it here and possibly 683157617Sanholt * enable it if it appears to work 684157617Sanholt */ 685157617Sanholt DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); 686157617Sanholt RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); 687157617Sanholt 688157617Sanholt for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { 689157617Sanholt if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == 690157617Sanholt 0xdeadbeef) 691157617Sanholt break; 692157617Sanholt DRM_UDELAY(1); 693157617Sanholt } 694157617Sanholt 695157617Sanholt if (tmp < dev_priv->usec_timeout) { 696157617Sanholt dev_priv->writeback_works = 1; 697157617Sanholt DRM_INFO("writeback test succeeded in %d usecs\n", tmp); 698157617Sanholt } else { 699157617Sanholt dev_priv->writeback_works = 0; 700157617Sanholt DRM_INFO("writeback test failed\n"); 701157617Sanholt } 702157617Sanholt if (radeon_no_wb == 1) { 703157617Sanholt dev_priv->writeback_works = 0; 704157617Sanholt DRM_INFO("writeback forced off\n"); 705157617Sanholt } 706162132Sanholt 707162132Sanholt if (!dev_priv->writeback_works) { 708162132Sanholt /* Disable writeback to avoid unnecessary bus master transfers */ 709162132Sanholt RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) | RADEON_RB_NO_UPDATE); 710162132Sanholt RADEON_WRITE(RADEON_SCRATCH_UMSK, 0); 711162132Sanholt } 712157617Sanholt} 713157617Sanholt 714182080Srnoland/* Enable or disable IGP GART on the chip */ 715182080Srnolandstatic void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on) 716182080Srnoland{ 717182080Srnoland u32 temp; 718182080Srnoland 719182080Srnoland if (on) { 720182080Srnoland DRM_DEBUG("programming igp gart %08X %08lX %08X\n", 721182080Srnoland dev_priv->gart_vm_start, 722182080Srnoland (long)dev_priv->gart_info.bus_addr, 723182080Srnoland dev_priv->gart_size); 724182080Srnoland 725182080Srnoland temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL); 726182080Srnoland 727182080Srnoland if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) 728182080Srnoland IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN | 729182080Srnoland RS690_BLOCK_GFX_D3_EN)); 730182080Srnoland else 731182080Srnoland IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); 732182080Srnoland 733182080Srnoland IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | 734182080Srnoland RS480_VA_SIZE_32MB)); 735182080Srnoland 736182080Srnoland temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID); 737182080Srnoland IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN | 738182080Srnoland RS480_TLB_ENABLE | 739182080Srnoland RS480_GTW_LAC_EN | 740182080Srnoland RS480_1LEVEL_GART)); 741182080Srnoland 742182080Srnoland temp = dev_priv->gart_info.bus_addr & 0xfffff000; 743182080Srnoland temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4; 744182080Srnoland IGP_WRITE_MCIND(RS480_GART_BASE, temp); 745182080Srnoland 746182080Srnoland temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL); 747182080Srnoland IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) | 748182080Srnoland RS480_REQ_TYPE_SNOOP_DIS)); 749182080Srnoland 750182080Srnoland radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start); 751182080Srnoland 752182080Srnoland dev_priv->gart_size = 32*1024*1024; 753182080Srnoland temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 754182080Srnoland 0xffff0000) | (dev_priv->gart_vm_start >> 16)); 755182080Srnoland 756182080Srnoland radeon_write_agp_location(dev_priv, temp); 757182080Srnoland 758182080Srnoland temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE); 759182080Srnoland IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | 760182080Srnoland RS480_VA_SIZE_32MB)); 761182080Srnoland 762182080Srnoland do { 763182080Srnoland temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL); 764182080Srnoland if ((temp & RS480_GART_CACHE_INVALIDATE) == 0) 765182080Srnoland break; 766182080Srnoland DRM_UDELAY(1); 767182080Srnoland } while(1); 768182080Srnoland 769182080Srnoland IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 770182080Srnoland RS480_GART_CACHE_INVALIDATE); 771182080Srnoland 772182080Srnoland do { 773182080Srnoland temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL); 774182080Srnoland if ((temp & RS480_GART_CACHE_INVALIDATE) == 0) 775182080Srnoland break; 776182080Srnoland DRM_UDELAY(1); 777182080Srnoland } while(1); 778182080Srnoland 779182080Srnoland IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0); 780182080Srnoland } else { 781182080Srnoland IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0); 782182080Srnoland } 783182080Srnoland} 784182080Srnoland 785148211Sanholtstatic void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) 786148211Sanholt{ 787148211Sanholt u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); 788148211Sanholt if (on) { 789148211Sanholt 790152909Sanholt DRM_DEBUG("programming pcie %08X %08lX %08X\n", 791157617Sanholt dev_priv->gart_vm_start, 792157617Sanholt (long)dev_priv->gart_info.bus_addr, 793152909Sanholt dev_priv->gart_size); 794157617Sanholt RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, 795157617Sanholt dev_priv->gart_vm_start); 796157617Sanholt RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, 797157617Sanholt dev_priv->gart_info.bus_addr); 798157617Sanholt RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO, 799157617Sanholt dev_priv->gart_vm_start); 800157617Sanholt RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO, 801157617Sanholt dev_priv->gart_vm_start + 802157617Sanholt dev_priv->gart_size - 1); 803148211Sanholt 804182080Srnoland radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */ 805148211Sanholt 806157617Sanholt RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, 807157617Sanholt RADEON_PCIE_TX_GART_EN); 808148211Sanholt } else { 809157617Sanholt RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, 810157617Sanholt tmp & ~RADEON_PCIE_TX_GART_EN); 811148211Sanholt } 812148211Sanholt} 813148211Sanholt 814119098Sanholt/* Enable or disable PCI GART on the chip */ 815145132Sanholtstatic void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) 816119098Sanholt{ 817152909Sanholt u32 tmp; 818119098Sanholt 819182080Srnoland if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || 820182080Srnoland (dev_priv->flags & RADEON_IS_IGPGART)) { 821182080Srnoland radeon_set_igpgart(dev_priv, on); 822182080Srnoland return; 823182080Srnoland } 824182080Srnoland 825182080Srnoland if (dev_priv->flags & RADEON_IS_PCIE) { 826148211Sanholt radeon_set_pciegart(dev_priv, on); 827148211Sanholt return; 828148211Sanholt } 829148211Sanholt 830182080Srnoland tmp = RADEON_READ(RADEON_AIC_CNTL); 831152909Sanholt 832145132Sanholt if (on) { 833145132Sanholt RADEON_WRITE(RADEON_AIC_CNTL, 834145132Sanholt tmp | RADEON_PCIGART_TRANSLATE_EN); 835119098Sanholt 836119098Sanholt /* set PCI GART page-table base address 837119098Sanholt */ 838152909Sanholt RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr); 839119098Sanholt 840119098Sanholt /* set address range for PCI address translate 841119098Sanholt */ 842145132Sanholt RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start); 843145132Sanholt RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start 844145132Sanholt + dev_priv->gart_size - 1); 845119098Sanholt 846119895Sanholt /* Turn off AGP aperture -- is this required for PCI GART? 847119098Sanholt */ 848182080Srnoland radeon_write_agp_location(dev_priv, 0xffffffc0); 849145132Sanholt RADEON_WRITE(RADEON_AGP_COMMAND, 0); /* clear AGP_COMMAND */ 850119098Sanholt } else { 851145132Sanholt RADEON_WRITE(RADEON_AIC_CNTL, 852145132Sanholt tmp & ~RADEON_PCIGART_TRANSLATE_EN); 853119098Sanholt } 854119098Sanholt} 855119098Sanholt 856182080Srnolandstatic int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) 85795584Sanholt{ 858145132Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 859157617Sanholt 860145132Sanholt DRM_DEBUG("\n"); 86195584Sanholt 862157617Sanholt /* if we require new memory map but we don't have it fail */ 863182080Srnoland if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { 864157617Sanholt DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); 865157617Sanholt radeon_do_cleanup_cp(dev); 866182080Srnoland return -EINVAL; 867157617Sanholt } 868157617Sanholt 869182080Srnoland if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) 870152909Sanholt { 871152909Sanholt DRM_DEBUG("Forcing AGP card to PCI mode\n"); 872182080Srnoland dev_priv->flags &= ~RADEON_IS_AGP; 873152909Sanholt } 874182080Srnoland else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) 875162132Sanholt && !init->is_pci) 876162132Sanholt { 877162132Sanholt DRM_DEBUG("Restoring AGP flag\n"); 878182080Srnoland dev_priv->flags |= RADEON_IS_AGP; 879162132Sanholt } 880152909Sanholt 881182080Srnoland if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) { 882145132Sanholt DRM_ERROR("PCI GART memory not allocated!\n"); 88395584Sanholt radeon_do_cleanup_cp(dev); 884182080Srnoland return -EINVAL; 88595584Sanholt } 88695584Sanholt 88795584Sanholt dev_priv->usec_timeout = init->usec_timeout; 888145132Sanholt if (dev_priv->usec_timeout < 1 || 889145132Sanholt dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { 890145132Sanholt DRM_DEBUG("TIMEOUT problem!\n"); 89195584Sanholt radeon_do_cleanup_cp(dev); 892182080Srnoland return -EINVAL; 89395584Sanholt } 89495584Sanholt 895182080Srnoland /* Enable vblank on CRTC1 for older X servers 896182080Srnoland */ 897182080Srnoland dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1; 898145132Sanholt 899112015Sanholt dev_priv->do_boxes = 0; 90095584Sanholt dev_priv->cp_mode = init->cp_mode; 90195584Sanholt 90295584Sanholt /* We don't support anything other than bus-mastering ring mode, 90395584Sanholt * but the ring can be in either AGP or PCI space for the ring 90495584Sanholt * read pointer. 90595584Sanholt */ 906145132Sanholt if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && 907145132Sanholt (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { 908145132Sanholt DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); 90995584Sanholt radeon_do_cleanup_cp(dev); 910182080Srnoland return -EINVAL; 91195584Sanholt } 91295584Sanholt 913145132Sanholt switch (init->fb_bpp) { 91495584Sanholt case 16: 91595584Sanholt dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565; 91695584Sanholt break; 91795584Sanholt case 32: 91895584Sanholt default: 91995584Sanholt dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; 92095584Sanholt break; 92195584Sanholt } 922145132Sanholt dev_priv->front_offset = init->front_offset; 923145132Sanholt dev_priv->front_pitch = init->front_pitch; 924145132Sanholt dev_priv->back_offset = init->back_offset; 925145132Sanholt dev_priv->back_pitch = init->back_pitch; 92695584Sanholt 927145132Sanholt switch (init->depth_bpp) { 92895584Sanholt case 16: 92995584Sanholt dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; 93095584Sanholt break; 93195584Sanholt case 32: 93295584Sanholt default: 93395584Sanholt dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; 93495584Sanholt break; 93595584Sanholt } 936145132Sanholt dev_priv->depth_offset = init->depth_offset; 937145132Sanholt dev_priv->depth_pitch = init->depth_pitch; 93895584Sanholt 93995584Sanholt /* Hardware state for depth clears. Remove this if/when we no 94095584Sanholt * longer clear the depth buffer with a 3D rectangle. Hard-code 94195584Sanholt * all values to prevent unwanted 3D state from slipping through 94295584Sanholt * and screwing with the clear operation. 94395584Sanholt */ 94495584Sanholt dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | 94595584Sanholt (dev_priv->color_fmt << 10) | 946182080Srnoland (dev_priv->chip_family < CHIP_R200 ? RADEON_ZBLOCK16 : 0)); 94795584Sanholt 948145132Sanholt dev_priv->depth_clear.rb3d_zstencilcntl = 949145132Sanholt (dev_priv->depth_fmt | 950145132Sanholt RADEON_Z_TEST_ALWAYS | 951145132Sanholt RADEON_STENCIL_TEST_ALWAYS | 952145132Sanholt RADEON_STENCIL_S_FAIL_REPLACE | 953145132Sanholt RADEON_STENCIL_ZPASS_REPLACE | 954145132Sanholt RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE); 95595584Sanholt 95695584Sanholt dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW | 95795584Sanholt RADEON_BFACE_SOLID | 95895584Sanholt RADEON_FFACE_SOLID | 95995584Sanholt RADEON_FLAT_SHADE_VTX_LAST | 96095584Sanholt RADEON_DIFFUSE_SHADE_FLAT | 96195584Sanholt RADEON_ALPHA_SHADE_FLAT | 96295584Sanholt RADEON_SPECULAR_SHADE_FLAT | 96395584Sanholt RADEON_FOG_SHADE_FLAT | 96495584Sanholt RADEON_VTX_PIX_CENTER_OGL | 96595584Sanholt RADEON_ROUND_MODE_TRUNC | 96695584Sanholt RADEON_ROUND_PREC_8TH_PIX); 96795584Sanholt 968113995Sanholt 969113995Sanholt dev_priv->ring_offset = init->ring_offset; 970113995Sanholt dev_priv->ring_rptr_offset = init->ring_rptr_offset; 971113995Sanholt dev_priv->buffers_offset = init->buffers_offset; 972119895Sanholt dev_priv->gart_textures_offset = init->gart_textures_offset; 973145132Sanholt 974182080Srnoland dev_priv->sarea = drm_getsarea(dev); 975145132Sanholt if (!dev_priv->sarea) { 97695584Sanholt DRM_ERROR("could not find sarea!\n"); 97795584Sanholt radeon_do_cleanup_cp(dev); 978182080Srnoland return -EINVAL; 97995584Sanholt } 98095584Sanholt 981145132Sanholt dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); 982145132Sanholt if (!dev_priv->cp_ring) { 98395584Sanholt DRM_ERROR("could not find cp ring region!\n"); 98495584Sanholt radeon_do_cleanup_cp(dev); 985182080Srnoland return -EINVAL; 98695584Sanholt } 987145132Sanholt dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); 988145132Sanholt if (!dev_priv->ring_rptr) { 98995584Sanholt DRM_ERROR("could not find ring read pointer!\n"); 99095584Sanholt radeon_do_cleanup_cp(dev); 991182080Srnoland return -EINVAL; 99295584Sanholt } 993152909Sanholt dev->agp_buffer_token = init->buffers_offset; 994145132Sanholt dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); 995145132Sanholt if (!dev->agp_buffer_map) { 99695584Sanholt DRM_ERROR("could not find dma buffer region!\n"); 99795584Sanholt radeon_do_cleanup_cp(dev); 998182080Srnoland return -EINVAL; 99995584Sanholt } 100095584Sanholt 1001145132Sanholt if (init->gart_textures_offset) { 1002145132Sanholt dev_priv->gart_textures = 1003145132Sanholt drm_core_findmap(dev, init->gart_textures_offset); 1004145132Sanholt if (!dev_priv->gart_textures) { 1005119895Sanholt DRM_ERROR("could not find GART texture region!\n"); 100695584Sanholt radeon_do_cleanup_cp(dev); 1007182080Srnoland return -EINVAL; 100895584Sanholt } 100995584Sanholt } 101095584Sanholt 101195584Sanholt dev_priv->sarea_priv = 1012145132Sanholt (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle + 1013145132Sanholt init->sarea_priv_offset); 101495584Sanholt 1015145132Sanholt#if __OS_HAS_AGP 1016182080Srnoland if (dev_priv->flags & RADEON_IS_AGP) { 1017145132Sanholt drm_core_ioremap(dev_priv->cp_ring, dev); 1018145132Sanholt drm_core_ioremap(dev_priv->ring_rptr, dev); 1019145132Sanholt drm_core_ioremap(dev->agp_buffer_map, dev); 1020145132Sanholt if (!dev_priv->cp_ring->handle || 1021145132Sanholt !dev_priv->ring_rptr->handle || 1022145132Sanholt !dev->agp_buffer_map->handle) { 102395584Sanholt DRM_ERROR("could not find ioremap agp regions!\n"); 102495584Sanholt radeon_do_cleanup_cp(dev); 1025182080Srnoland return -EINVAL; 102695584Sanholt } 1027119098Sanholt } else 1028119098Sanholt#endif 1029119098Sanholt { 1030145132Sanholt dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset; 103195584Sanholt dev_priv->ring_rptr->handle = 1032145132Sanholt (void *)dev_priv->ring_rptr->offset; 1033145132Sanholt dev->agp_buffer_map->handle = 1034145132Sanholt (void *)dev->agp_buffer_map->offset; 103595584Sanholt 1036145132Sanholt DRM_DEBUG("dev_priv->cp_ring->handle %p\n", 1037145132Sanholt dev_priv->cp_ring->handle); 1038145132Sanholt DRM_DEBUG("dev_priv->ring_rptr->handle %p\n", 1039145132Sanholt dev_priv->ring_rptr->handle); 1040145132Sanholt DRM_DEBUG("dev->agp_buffer_map->handle %p\n", 1041145132Sanholt dev->agp_buffer_map->handle); 104295584Sanholt } 104395584Sanholt 1044182080Srnoland dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16; 1045182080Srnoland dev_priv->fb_size = 1046182080Srnoland ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000) 1047157617Sanholt - dev_priv->fb_location; 104895584Sanholt 1049145132Sanholt dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | 1050145132Sanholt ((dev_priv->front_offset 1051145132Sanholt + dev_priv->fb_location) >> 10)); 1052122580Sanholt 1053145132Sanholt dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) | 1054145132Sanholt ((dev_priv->back_offset 1055145132Sanholt + dev_priv->fb_location) >> 10)); 1056122580Sanholt 1057145132Sanholt dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) | 1058145132Sanholt ((dev_priv->depth_offset 1059145132Sanholt + dev_priv->fb_location) >> 10)); 1060122580Sanholt 1061119895Sanholt dev_priv->gart_size = init->gart_size; 1062122580Sanholt 1063157617Sanholt /* New let's set the memory map ... */ 1064157617Sanholt if (dev_priv->new_memmap) { 1065157617Sanholt u32 base = 0; 1066157617Sanholt 1067157617Sanholt DRM_INFO("Setting GART location based on new memory map\n"); 1068157617Sanholt 1069157617Sanholt /* If using AGP, try to locate the AGP aperture at the same 1070157617Sanholt * location in the card and on the bus, though we have to 1071157617Sanholt * align it down. 1072157617Sanholt */ 1073145132Sanholt#if __OS_HAS_AGP 1074182080Srnoland if (dev_priv->flags & RADEON_IS_AGP) { 1075157617Sanholt base = dev->agp->base; 1076157617Sanholt /* Check if valid */ 1077182080Srnoland if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && 1078182080Srnoland base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { 1079157617Sanholt DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", 1080157617Sanholt dev->agp->base); 1081157617Sanholt base = 0; 1082157617Sanholt } 1083157617Sanholt } 1084157617Sanholt#endif 1085157617Sanholt /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ 1086157617Sanholt if (base == 0) { 1087157617Sanholt base = dev_priv->fb_location + dev_priv->fb_size; 1088182080Srnoland if (base < dev_priv->fb_location || 1089182080Srnoland ((base + dev_priv->gart_size) & 0xfffffffful) < base) 1090157617Sanholt base = dev_priv->fb_location 1091157617Sanholt - dev_priv->gart_size; 1092182080Srnoland } 1093157617Sanholt dev_priv->gart_vm_start = base & 0xffc00000u; 1094157617Sanholt if (dev_priv->gart_vm_start != base) 1095157617Sanholt DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", 1096157617Sanholt base, dev_priv->gart_vm_start); 1097157617Sanholt } else { 1098157617Sanholt DRM_INFO("Setting GART location based on old memory map\n"); 1099157617Sanholt dev_priv->gart_vm_start = dev_priv->fb_location + 1100157617Sanholt RADEON_READ(RADEON_CONFIG_APER_SIZE); 1101157617Sanholt } 1102157617Sanholt 1103157617Sanholt#if __OS_HAS_AGP 1104182080Srnoland if (dev_priv->flags & RADEON_IS_AGP) 1105145132Sanholt dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset 1106145132Sanholt - dev->agp->base 1107145132Sanholt + dev_priv->gart_vm_start); 110895584Sanholt else 110995584Sanholt#endif 1110145132Sanholt dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset 1111157617Sanholt - (unsigned long)dev->sg->virtual 1112157617Sanholt + dev_priv->gart_vm_start); 111395584Sanholt 1114145132Sanholt DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size); 1115145132Sanholt DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start); 1116145132Sanholt DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n", 1117145132Sanholt dev_priv->gart_buffers_offset); 111895584Sanholt 1119145132Sanholt dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle; 1120145132Sanholt dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle 112195584Sanholt + init->ring_size / sizeof(u32)); 112295584Sanholt dev_priv->ring.size = init->ring_size; 1123145132Sanholt dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); 112495584Sanholt 1125182080Srnoland dev_priv->ring.rptr_update = /* init->rptr_update */ 4096; 1126182080Srnoland dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8); 1127182080Srnoland 1128182080Srnoland dev_priv->ring.fetch_size = /* init->fetch_size */ 32; 1129182080Srnoland dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16); 1130182080Srnoland 1131145132Sanholt dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; 113295584Sanholt 113395584Sanholt dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; 113495584Sanholt 1135145132Sanholt#if __OS_HAS_AGP 1136182080Srnoland if (dev_priv->flags & RADEON_IS_AGP) { 1137119098Sanholt /* Turn off PCI GART */ 1138145132Sanholt radeon_set_pcigart(dev_priv, 0); 1139119098Sanholt } else 1140119098Sanholt#endif 1141119098Sanholt { 1142182080Srnoland dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); 1143152909Sanholt /* if we have an offset set from userspace */ 1144182080Srnoland if (dev_priv->pcigart_offset_set) { 1145157617Sanholt dev_priv->gart_info.bus_addr = 1146157617Sanholt dev_priv->pcigart_offset + dev_priv->fb_location; 1147157617Sanholt dev_priv->gart_info.mapping.offset = 1148182080Srnoland dev_priv->pcigart_offset + dev_priv->fb_aper_offset; 1149157617Sanholt dev_priv->gart_info.mapping.size = 1150182080Srnoland dev_priv->gart_info.table_size; 1151157617Sanholt 1152182080Srnoland drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev); 1153157617Sanholt dev_priv->gart_info.addr = 1154157617Sanholt dev_priv->gart_info.mapping.handle; 1155152909Sanholt 1156182080Srnoland if (dev_priv->flags & RADEON_IS_PCIE) 1157182080Srnoland dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; 1158182080Srnoland else 1159182080Srnoland dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; 1160157617Sanholt dev_priv->gart_info.gart_table_location = 1161157617Sanholt DRM_ATI_GART_FB; 1162157617Sanholt 1163157617Sanholt DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", 1164157617Sanholt dev_priv->gart_info.addr, 1165157617Sanholt dev_priv->pcigart_offset); 1166157617Sanholt } else { 1167182080Srnoland if (dev_priv->flags & RADEON_IS_IGPGART) 1168182080Srnoland dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; 1169182080Srnoland else 1170182080Srnoland dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; 1171157617Sanholt dev_priv->gart_info.gart_table_location = 1172157617Sanholt DRM_ATI_GART_MAIN; 1173152909Sanholt dev_priv->gart_info.addr = NULL; 1174152909Sanholt dev_priv->gart_info.bus_addr = 0; 1175182080Srnoland if (dev_priv->flags & RADEON_IS_PCIE) { 1176157617Sanholt DRM_ERROR 1177157617Sanholt ("Cannot use PCI Express without GART in FB memory\n"); 1178152909Sanholt radeon_do_cleanup_cp(dev); 1179182080Srnoland return -EINVAL; 1180152909Sanholt } 1181152909Sanholt } 1182152909Sanholt 1183152909Sanholt if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { 1184145132Sanholt DRM_ERROR("failed to init PCI GART!\n"); 118595584Sanholt radeon_do_cleanup_cp(dev); 1186182080Srnoland return -ENOMEM; 118795584Sanholt } 118895584Sanholt 1189119098Sanholt /* Turn on PCI GART */ 1190145132Sanholt radeon_set_pcigart(dev_priv, 1); 119195584Sanholt } 119295584Sanholt 1193145132Sanholt radeon_cp_load_microcode(dev_priv); 1194145132Sanholt radeon_cp_init_ring_buffer(dev, dev_priv); 119595584Sanholt 119695584Sanholt dev_priv->last_buf = 0; 119795584Sanholt 1198145132Sanholt radeon_do_engine_reset(dev); 1199157617Sanholt radeon_test_writeback(dev_priv); 120095584Sanholt 120195584Sanholt return 0; 120295584Sanholt} 120395584Sanholt 1204182080Srnolandstatic int radeon_do_cleanup_cp(struct drm_device * dev) 120595584Sanholt{ 1206145132Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1207145132Sanholt DRM_DEBUG("\n"); 120895584Sanholt 1209119098Sanholt /* Make sure interrupts are disabled here because the uninstall ioctl 1210119098Sanholt * may not have been called from userspace and after dev_private 1211119098Sanholt * is freed, it's too late. 1212119098Sanholt */ 1213145132Sanholt if (dev->irq_enabled) 1214145132Sanholt drm_irq_uninstall(dev); 1215119098Sanholt 1216145132Sanholt#if __OS_HAS_AGP 1217182080Srnoland if (dev_priv->flags & RADEON_IS_AGP) { 1218145132Sanholt if (dev_priv->cp_ring != NULL) { 1219145132Sanholt drm_core_ioremapfree(dev_priv->cp_ring, dev); 1220145132Sanholt dev_priv->cp_ring = NULL; 1221145132Sanholt } 1222145132Sanholt if (dev_priv->ring_rptr != NULL) { 1223145132Sanholt drm_core_ioremapfree(dev_priv->ring_rptr, dev); 1224145132Sanholt dev_priv->ring_rptr = NULL; 1225145132Sanholt } 1226145132Sanholt if (dev->agp_buffer_map != NULL) { 1227145132Sanholt drm_core_ioremapfree(dev->agp_buffer_map, dev); 1228145132Sanholt dev->agp_buffer_map = NULL; 1229145132Sanholt } 1230145132Sanholt } else 1231119098Sanholt#endif 1232145132Sanholt { 1233152909Sanholt 1234152909Sanholt if (dev_priv->gart_info.bus_addr) { 1235152909Sanholt /* Turn off PCI GART */ 1236152909Sanholt radeon_set_pcigart(dev_priv, 0); 1237152909Sanholt if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) 1238152909Sanholt DRM_ERROR("failed to cleanup PCI GART!\n"); 1239152909Sanholt } 1240152909Sanholt 1241152909Sanholt if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) 1242152909Sanholt { 1243152909Sanholt drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); 1244152909Sanholt dev_priv->gart_info.addr = 0; 1245152909Sanholt } 124695584Sanholt } 1247145132Sanholt /* only clear to the start of flags */ 1248145132Sanholt memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); 124995584Sanholt 125095584Sanholt return 0; 125195584Sanholt} 125295584Sanholt 1253145132Sanholt/* This code will reinit the Radeon CP hardware after a resume from disc. 1254145132Sanholt * AFAIK, it would be very difficult to pickle the state at suspend time, so 1255119098Sanholt * here we make sure that all Radeon hardware initialisation is re-done without 1256119098Sanholt * affecting running applications. 1257119098Sanholt * 1258119098Sanholt * Charl P. Botha <http://cpbotha.net> 1259119098Sanholt */ 1260182080Srnolandstatic int radeon_do_resume_cp(struct drm_device * dev) 1261119098Sanholt{ 1262119098Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1263119098Sanholt 1264145132Sanholt if (!dev_priv) { 1265145132Sanholt DRM_ERROR("Called with no initialization\n"); 1266182080Srnoland return -EINVAL; 1267119098Sanholt } 1268119098Sanholt 1269119098Sanholt DRM_DEBUG("Starting radeon_do_resume_cp()\n"); 1270119098Sanholt 1271145132Sanholt#if __OS_HAS_AGP 1272182080Srnoland if (dev_priv->flags & RADEON_IS_AGP) { 1273119098Sanholt /* Turn off PCI GART */ 1274145132Sanholt radeon_set_pcigart(dev_priv, 0); 1275119098Sanholt } else 1276119098Sanholt#endif 1277119098Sanholt { 1278119098Sanholt /* Turn on PCI GART */ 1279145132Sanholt radeon_set_pcigart(dev_priv, 1); 1280119098Sanholt } 1281119098Sanholt 1282145132Sanholt radeon_cp_load_microcode(dev_priv); 1283145132Sanholt radeon_cp_init_ring_buffer(dev, dev_priv); 1284119098Sanholt 1285145132Sanholt radeon_do_engine_reset(dev); 1286182080Srnoland radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); 1287119098Sanholt 1288119098Sanholt DRM_DEBUG("radeon_do_resume_cp() complete\n"); 1289119098Sanholt 1290119098Sanholt return 0; 1291119098Sanholt} 1292119098Sanholt 1293182080Srnolandint radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 129495584Sanholt{ 1295182080Srnoland drm_radeon_init_t *init = data; 129695584Sanholt 1297182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 1298119098Sanholt 1299182080Srnoland if (init->func == RADEON_INIT_R300_CP) 1300182080Srnoland r300_init_reg_flags(dev); 130195584Sanholt 1302182080Srnoland switch (init->func) { 130395584Sanholt case RADEON_INIT_CP: 1304112015Sanholt case RADEON_INIT_R200_CP: 1305145132Sanholt case RADEON_INIT_R300_CP: 1306182080Srnoland return radeon_do_init_cp(dev, init); 130795584Sanholt case RADEON_CLEANUP_CP: 1308145132Sanholt return radeon_do_cleanup_cp(dev); 130995584Sanholt } 131095584Sanholt 1311182080Srnoland return -EINVAL; 131295584Sanholt} 131395584Sanholt 1314182080Srnolandint radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv) 131595584Sanholt{ 131695584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1317145132Sanholt DRM_DEBUG("\n"); 131895584Sanholt 1319182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 132095584Sanholt 1321145132Sanholt if (dev_priv->cp_running) { 1322182080Srnoland DRM_DEBUG("while CP running\n"); 132395584Sanholt return 0; 132495584Sanholt } 1325145132Sanholt if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) { 1326182080Srnoland DRM_DEBUG("called with bogus CP mode (%d)\n", 1327182080Srnoland dev_priv->cp_mode); 132895584Sanholt return 0; 132995584Sanholt } 133095584Sanholt 1331145132Sanholt radeon_do_cp_start(dev_priv); 133295584Sanholt 133395584Sanholt return 0; 133495584Sanholt} 133595584Sanholt 133695584Sanholt/* Stop the CP. The engine must have been idled before calling this 133795584Sanholt * routine. 133895584Sanholt */ 1339182080Srnolandint radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) 134095584Sanholt{ 134195584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1342182080Srnoland drm_radeon_cp_stop_t *stop = data; 134395584Sanholt int ret; 1344145132Sanholt DRM_DEBUG("\n"); 134595584Sanholt 1346182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 134795584Sanholt 1348112015Sanholt if (!dev_priv->cp_running) 1349112015Sanholt return 0; 1350112015Sanholt 135195584Sanholt /* Flush any pending CP commands. This ensures any outstanding 135295584Sanholt * commands are exectuted by the engine before we turn it off. 135395584Sanholt */ 1354182080Srnoland if (stop->flush) { 1355145132Sanholt radeon_do_cp_flush(dev_priv); 135695584Sanholt } 135795584Sanholt 135895584Sanholt /* If we fail to make the engine go idle, we return an error 135995584Sanholt * code so that the DRM ioctl wrapper can try again. 136095584Sanholt */ 1361182080Srnoland if (stop->idle) { 1362145132Sanholt ret = radeon_do_cp_idle(dev_priv); 1363145132Sanholt if (ret) 1364145132Sanholt return ret; 136595584Sanholt } 136695584Sanholt 136795584Sanholt /* Finally, we can turn off the CP. If the engine isn't idle, 136895584Sanholt * we will get some dropped triangles as they won't be fully 136995584Sanholt * rendered before the CP is shut down. 137095584Sanholt */ 1371145132Sanholt radeon_do_cp_stop(dev_priv); 137295584Sanholt 137395584Sanholt /* Reset the engine */ 1374145132Sanholt radeon_do_engine_reset(dev); 137595584Sanholt 137695584Sanholt return 0; 137795584Sanholt} 137895584Sanholt 1379182080Srnolandvoid radeon_do_release(struct drm_device * dev) 1380112015Sanholt{ 1381112015Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1382145132Sanholt int i, ret; 1383112015Sanholt 1384112015Sanholt if (dev_priv) { 1385112015Sanholt if (dev_priv->cp_running) { 1386112015Sanholt /* Stop the cp */ 1387145132Sanholt while ((ret = radeon_do_cp_idle(dev_priv)) != 0) { 1388112015Sanholt DRM_DEBUG("radeon_do_cp_idle %d\n", ret); 1389112015Sanholt#ifdef __linux__ 1390112015Sanholt schedule(); 1391112015Sanholt#else 1392152909Sanholt#if defined(__FreeBSD__) && __FreeBSD_version > 500000 1393182080Srnoland mtx_sleep(&ret, &dev->dev_lock, PZERO, "rdnrel", 1394152909Sanholt 1); 1395152909Sanholt#else 1396112015Sanholt tsleep(&ret, PZERO, "rdnrel", 1); 1397112015Sanholt#endif 1398152909Sanholt#endif 1399112015Sanholt } 1400145132Sanholt radeon_do_cp_stop(dev_priv); 1401145132Sanholt radeon_do_engine_reset(dev); 1402112015Sanholt } 1403112015Sanholt 1404112015Sanholt /* Disable *all* interrupts */ 1405145132Sanholt if (dev_priv->mmio) /* remove this after permanent addmaps */ 1406145132Sanholt RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); 1407112015Sanholt 1408157617Sanholt if (dev_priv->mmio) { /* remove all surfaces */ 1409145132Sanholt for (i = 0; i < RADEON_MAX_SURFACES; i++) { 1410157617Sanholt RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0); 1411157617Sanholt RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 1412157617Sanholt 16 * i, 0); 1413157617Sanholt RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 1414157617Sanholt 16 * i, 0); 1415145132Sanholt } 1416145132Sanholt } 1417145132Sanholt 1418112015Sanholt /* Free memory heap structures */ 1419145132Sanholt radeon_mem_takedown(&(dev_priv->gart_heap)); 1420145132Sanholt radeon_mem_takedown(&(dev_priv->fb_heap)); 1421112015Sanholt 1422112015Sanholt /* deallocate kernel resources */ 1423145132Sanholt radeon_do_cleanup_cp(dev); 1424112015Sanholt } 1425112015Sanholt} 1426112015Sanholt 142795584Sanholt/* Just reset the CP ring. Called as part of an X Server engine reset. 142895584Sanholt */ 1429182080Srnolandint radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) 143095584Sanholt{ 143195584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1432145132Sanholt DRM_DEBUG("\n"); 143395584Sanholt 1434182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 143595584Sanholt 1436145132Sanholt if (!dev_priv) { 1437182080Srnoland DRM_DEBUG("called before init done\n"); 1438182080Srnoland return -EINVAL; 143995584Sanholt } 144095584Sanholt 1441145132Sanholt radeon_do_cp_reset(dev_priv); 144295584Sanholt 144395584Sanholt /* The CP is no longer running after an engine reset */ 144495584Sanholt dev_priv->cp_running = 0; 144595584Sanholt 144695584Sanholt return 0; 144795584Sanholt} 144895584Sanholt 1449182080Srnolandint radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) 145095584Sanholt{ 145195584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1452145132Sanholt DRM_DEBUG("\n"); 145395584Sanholt 1454182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 145595584Sanholt 1456145132Sanholt return radeon_do_cp_idle(dev_priv); 145795584Sanholt} 145895584Sanholt 1459119098Sanholt/* Added by Charl P. Botha to call radeon_do_resume_cp(). 1460119098Sanholt */ 1461182080Srnolandint radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) 1462119098Sanholt{ 1463119098Sanholt 1464119098Sanholt return radeon_do_resume_cp(dev); 1465119098Sanholt} 1466119098Sanholt 1467182080Srnolandint radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) 146895584Sanholt{ 1469145132Sanholt DRM_DEBUG("\n"); 147095584Sanholt 1471182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 147295584Sanholt 1473145132Sanholt return radeon_do_engine_reset(dev); 147495584Sanholt} 147595584Sanholt 147695584Sanholt/* ================================================================ 147795584Sanholt * Fullscreen mode 147895584Sanholt */ 147995584Sanholt 1480112015Sanholt/* KW: Deprecated to say the least: 1481112015Sanholt */ 1482182080Srnolandint radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) 148395584Sanholt{ 148495584Sanholt return 0; 148595584Sanholt} 148695584Sanholt 148795584Sanholt/* ================================================================ 148895584Sanholt * Freelist management 148995584Sanholt */ 149095584Sanholt 1491112015Sanholt/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through 1492112015Sanholt * bufs until freelist code is used. Note this hides a problem with 1493112015Sanholt * the scratch register * (used to keep track of last buffer 1494112015Sanholt * completed) being written to before * the last buffer has actually 1495145132Sanholt * completed rendering. 1496112015Sanholt * 1497112015Sanholt * KW: It's also a good way to find free buffers quickly. 1498112015Sanholt * 1499112015Sanholt * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't 1500112015Sanholt * sleep. However, bugs in older versions of radeon_accel.c mean that 1501112015Sanholt * we essentially have to do this, else old clients will break. 1502145132Sanholt * 1503112015Sanholt * However, it does leave open a potential deadlock where all the 1504112015Sanholt * buffers are held by other clients, which can't release them because 1505145132Sanholt * they can't get the lock. 1506112015Sanholt */ 1507112015Sanholt 1508182080Srnolandstruct drm_buf *radeon_freelist_get(struct drm_device * dev) 150995584Sanholt{ 1510182080Srnoland struct drm_device_dma *dma = dev->dma; 151195584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1512112015Sanholt drm_radeon_buf_priv_t *buf_priv; 1513182080Srnoland struct drm_buf *buf; 1514112015Sanholt int i, t; 1515112015Sanholt int start; 151695584Sanholt 1517145132Sanholt if (++dev_priv->last_buf >= dma->buf_count) 1518112015Sanholt dev_priv->last_buf = 0; 151995584Sanholt 1520112015Sanholt start = dev_priv->last_buf; 152195584Sanholt 1522145132Sanholt for (t = 0; t < dev_priv->usec_timeout; t++) { 1523145132Sanholt u32 done_age = GET_SCRATCH(1); 1524145132Sanholt DRM_DEBUG("done_age = %d\n", done_age); 1525145132Sanholt for (i = start; i < dma->buf_count; i++) { 1526112015Sanholt buf = dma->buflist[i]; 1527112015Sanholt buf_priv = buf->dev_private; 1528182080Srnoland if (buf->file_priv == NULL || (buf->pending && 1529182080Srnoland buf_priv->age <= 1530182080Srnoland done_age)) { 1531112015Sanholt dev_priv->stats.requested_bufs++; 1532112015Sanholt buf->pending = 0; 1533112015Sanholt return buf; 1534112015Sanholt } 1535112015Sanholt start = 0; 1536112015Sanholt } 153795584Sanholt 1538112015Sanholt if (t) { 1539145132Sanholt DRM_UDELAY(1); 1540112015Sanholt dev_priv->stats.freelist_loops++; 1541112015Sanholt } 154295584Sanholt } 154395584Sanholt 1544145132Sanholt DRM_DEBUG("returning NULL!\n"); 1545112015Sanholt return NULL; 154695584Sanholt} 1547145132Sanholt 1548112015Sanholt#if 0 1549182080Srnolandstruct drm_buf *radeon_freelist_get(struct drm_device * dev) 155095584Sanholt{ 1551182080Srnoland struct drm_device_dma *dma = dev->dma; 155295584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 155395584Sanholt drm_radeon_buf_priv_t *buf_priv; 1554182080Srnoland struct drm_buf *buf; 155595584Sanholt int i, t; 155695584Sanholt int start; 1557112015Sanholt u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)); 155895584Sanholt 1559145132Sanholt if (++dev_priv->last_buf >= dma->buf_count) 156095584Sanholt dev_priv->last_buf = 0; 1561112015Sanholt 156295584Sanholt start = dev_priv->last_buf; 1563112015Sanholt dev_priv->stats.freelist_loops++; 1564145132Sanholt 1565145132Sanholt for (t = 0; t < 2; t++) { 1566145132Sanholt for (i = start; i < dma->buf_count; i++) { 156795584Sanholt buf = dma->buflist[i]; 156895584Sanholt buf_priv = buf->dev_private; 1569182080Srnoland if (buf->file_priv == 0 || (buf->pending && 1570182080Srnoland buf_priv->age <= 1571182080Srnoland done_age)) { 1572112015Sanholt dev_priv->stats.requested_bufs++; 157395584Sanholt buf->pending = 0; 157495584Sanholt return buf; 157595584Sanholt } 157695584Sanholt } 1577112015Sanholt start = 0; 157895584Sanholt } 157995584Sanholt 158095584Sanholt return NULL; 158195584Sanholt} 1582112015Sanholt#endif 158395584Sanholt 1584182080Srnolandvoid radeon_freelist_reset(struct drm_device * dev) 158595584Sanholt{ 1586182080Srnoland struct drm_device_dma *dma = dev->dma; 158795584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 158895584Sanholt int i; 158995584Sanholt 159095584Sanholt dev_priv->last_buf = 0; 1591145132Sanholt for (i = 0; i < dma->buf_count; i++) { 1592182080Srnoland struct drm_buf *buf = dma->buflist[i]; 159395584Sanholt drm_radeon_buf_priv_t *buf_priv = buf->dev_private; 159495584Sanholt buf_priv->age = 0; 159595584Sanholt } 159695584Sanholt} 159795584Sanholt 159895584Sanholt/* ================================================================ 159995584Sanholt * CP command submission 160095584Sanholt */ 160195584Sanholt 1602145132Sanholtint radeon_wait_ring(drm_radeon_private_t * dev_priv, int n) 160395584Sanholt{ 160495584Sanholt drm_radeon_ring_buffer_t *ring = &dev_priv->ring; 160595584Sanholt int i; 1606145132Sanholt u32 last_head = GET_RING_HEAD(dev_priv); 160795584Sanholt 1608145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 1609145132Sanholt u32 head = GET_RING_HEAD(dev_priv); 1610112015Sanholt 1611112015Sanholt ring->space = (head - ring->tail) * sizeof(u32); 1612145132Sanholt if (ring->space <= 0) 1613112015Sanholt ring->space += ring->size; 1614145132Sanholt if (ring->space > n) 161595584Sanholt return 0; 1616145132Sanholt 1617112015Sanholt dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 1618112015Sanholt 1619112015Sanholt if (head != last_head) 1620112015Sanholt i = 0; 1621112015Sanholt last_head = head; 1622112015Sanholt 1623145132Sanholt DRM_UDELAY(1); 162495584Sanholt } 162595584Sanholt 162695584Sanholt /* FIXME: This return value is ignored in the BEGIN_RING macro! */ 162795584Sanholt#if RADEON_FIFO_DEBUG 1628145132Sanholt radeon_status(dev_priv); 1629145132Sanholt DRM_ERROR("failed!\n"); 163095584Sanholt#endif 1631182080Srnoland return -EBUSY; 163295584Sanholt} 163395584Sanholt 1634182080Srnolandstatic int radeon_cp_get_buffers(struct drm_device *dev, 1635182080Srnoland struct drm_file *file_priv, 1636182080Srnoland struct drm_dma * d) 163795584Sanholt{ 163895584Sanholt int i; 1639182080Srnoland struct drm_buf *buf; 164095584Sanholt 1641145132Sanholt for (i = d->granted_count; i < d->request_count; i++) { 1642145132Sanholt buf = radeon_freelist_get(dev); 1643145132Sanholt if (!buf) 1644182080Srnoland return -EBUSY; /* NOTE: broken client */ 164595584Sanholt 1646182080Srnoland buf->file_priv = file_priv; 164795584Sanholt 1648145132Sanholt if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, 1649145132Sanholt sizeof(buf->idx))) 1650182080Srnoland return -EFAULT; 1651145132Sanholt if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, 1652145132Sanholt sizeof(buf->total))) 1653182080Srnoland return -EFAULT; 165495584Sanholt 165595584Sanholt d->granted_count++; 165695584Sanholt } 165795584Sanholt return 0; 165895584Sanholt} 165995584Sanholt 1660182080Srnolandint radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) 166195584Sanholt{ 1662182080Srnoland struct drm_device_dma *dma = dev->dma; 166395584Sanholt int ret = 0; 1664182080Srnoland struct drm_dma *d = data; 166595584Sanholt 1666182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 166795584Sanholt 166895584Sanholt /* Please don't send us buffers. 166995584Sanholt */ 1670182080Srnoland if (d->send_count != 0) { 1671145132Sanholt DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", 1672182080Srnoland DRM_CURRENTPID, d->send_count); 1673182080Srnoland return -EINVAL; 167495584Sanholt } 167595584Sanholt 167695584Sanholt /* We'll send you buffers. 167795584Sanholt */ 1678182080Srnoland if (d->request_count < 0 || d->request_count > dma->buf_count) { 1679145132Sanholt DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", 1680182080Srnoland DRM_CURRENTPID, d->request_count, dma->buf_count); 1681182080Srnoland return -EINVAL; 168295584Sanholt } 168395584Sanholt 1684182080Srnoland d->granted_count = 0; 168595584Sanholt 1686182080Srnoland if (d->request_count) { 1687182080Srnoland ret = radeon_cp_get_buffers(dev, file_priv, d); 168895584Sanholt } 168995584Sanholt 169095584Sanholt return ret; 169195584Sanholt} 1692145132Sanholt 1693152909Sanholtint radeon_driver_load(struct drm_device *dev, unsigned long flags) 1694145132Sanholt{ 1695145132Sanholt drm_radeon_private_t *dev_priv; 1696145132Sanholt int ret = 0; 1697145132Sanholt 1698145132Sanholt dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER); 1699145132Sanholt if (dev_priv == NULL) 1700182080Srnoland return -ENOMEM; 1701145132Sanholt 1702145132Sanholt memset(dev_priv, 0, sizeof(drm_radeon_private_t)); 1703145132Sanholt dev->dev_private = (void *)dev_priv; 1704145132Sanholt dev_priv->flags = flags; 1705145132Sanholt 1706182080Srnoland switch (flags & RADEON_FAMILY_MASK) { 1707145132Sanholt case CHIP_R100: 1708145132Sanholt case CHIP_RV200: 1709145132Sanholt case CHIP_R200: 1710145132Sanholt case CHIP_R300: 1711157617Sanholt case CHIP_R350: 1712148211Sanholt case CHIP_R420: 1713157617Sanholt case CHIP_RV410: 1714182080Srnoland case CHIP_RV515: 1715182080Srnoland case CHIP_R520: 1716182080Srnoland case CHIP_RV570: 1717182080Srnoland case CHIP_R580: 1718182080Srnoland dev_priv->flags |= RADEON_HAS_HIERZ; 1719145132Sanholt break; 1720145132Sanholt default: 1721157617Sanholt /* all other chips have no hierarchical z buffer */ 1722145132Sanholt break; 1723145132Sanholt } 1724145132Sanholt 1725182080Srnoland dev_priv->chip_family = flags & RADEON_FAMILY_MASK; 1726145132Sanholt if (drm_device_is_agp(dev)) 1727182080Srnoland dev_priv->flags |= RADEON_IS_AGP; 1728162132Sanholt else if (drm_device_is_pcie(dev)) 1729182080Srnoland dev_priv->flags |= RADEON_IS_PCIE; 1730162132Sanholt else 1731182080Srnoland dev_priv->flags |= RADEON_IS_PCI; 1732148211Sanholt 1733145132Sanholt DRM_DEBUG("%s card detected\n", 1734182080Srnoland ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); 1735145132Sanholt return ret; 1736145132Sanholt} 1737145132Sanholt 1738152909Sanholt/* Create mappings for registers and framebuffer so userland doesn't necessarily 1739152909Sanholt * have to find them. 1740152909Sanholt */ 1741152909Sanholtint radeon_driver_firstopen(struct drm_device *dev) 1742145132Sanholt{ 1743152909Sanholt int ret; 1744152909Sanholt drm_local_map_t *map; 1745145132Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1746145132Sanholt 1747182080Srnoland dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; 1748182080Srnoland 1749152909Sanholt ret = drm_addmap(dev, drm_get_resource_start(dev, 2), 1750152909Sanholt drm_get_resource_len(dev, 2), _DRM_REGISTERS, 1751152909Sanholt _DRM_READ_ONLY, &dev_priv->mmio); 1752152909Sanholt if (ret != 0) 1753152909Sanholt return ret; 1754152909Sanholt 1755182080Srnoland dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); 1756182080Srnoland ret = drm_addmap(dev, dev_priv->fb_aper_offset, 1757152909Sanholt drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, 1758152909Sanholt _DRM_WRITE_COMBINING, &map); 1759152909Sanholt if (ret != 0) 1760152909Sanholt return ret; 1761152909Sanholt 1762152909Sanholt return 0; 1763152909Sanholt} 1764152909Sanholt 1765152909Sanholtint radeon_driver_unload(struct drm_device *dev) 1766152909Sanholt{ 1767152909Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 1768152909Sanholt 1769145132Sanholt DRM_DEBUG("\n"); 1770145132Sanholt drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); 1771145132Sanholt 1772145132Sanholt dev->dev_private = NULL; 1773145132Sanholt return 0; 1774145132Sanholt} 1775