2006-01-02 09:18:39 +03:00
/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
/*
2005-04-17 02:20:36 +04:00
* Copyright 2000 Precision Insight , Inc . , Cedar Park , Texas .
* Copyright 2000 VA Linux Systems , Inc . , Fremont , California .
2008-05-28 07:28:59 +04:00
* Copyright 2007 Advanced Micro Devices , Inc .
2005-04-17 02:20:36 +04:00
* All Rights Reserved .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* PRECISION INSIGHT AND / OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
*
* Authors :
* Kevin E . Martin < martin @ valinux . com >
* Gareth Hughes < gareth @ valinux . com >
*/
# include "drmP.h"
# include "drm.h"
# include "radeon_drm.h"
# include "radeon_drv.h"
2005-08-16 14:43:16 +04:00
# include "r300_reg.h"
2005-04-17 02:20:36 +04:00
2008-05-28 05:21:25 +04:00
# include "radeon_microcode.h"
2005-04-17 02:20:36 +04:00
# define RADEON_FIFO_DEBUG 0
2007-07-11 09:53:27 +04:00
static int radeon_do_cleanup_cp ( struct drm_device * dev ) ;
2008-08-13 03:46:31 +04:00
static void radeon_do_cp_start ( drm_radeon_private_t * dev_priv ) ;
2005-04-17 02:20:36 +04:00
2008-05-28 07:28:59 +04:00
static u32 R500_READ_MCIND ( drm_radeon_private_t * dev_priv , int addr )
2008-02-07 08:01:05 +03:00
{
u32 ret ;
RADEON_WRITE ( R520_MC_IND_INDEX , 0x7f0000 | ( addr & 0xff ) ) ;
ret = RADEON_READ ( R520_MC_IND_DATA ) ;
RADEON_WRITE ( R520_MC_IND_INDEX , 0 ) ;
return ret ;
}
2008-05-28 07:28:59 +04:00
static u32 RS480_READ_MCIND ( drm_radeon_private_t * dev_priv , int addr )
{
u32 ret ;
RADEON_WRITE ( RS480_NB_MC_INDEX , addr & 0xff ) ;
ret = RADEON_READ ( RS480_NB_MC_DATA ) ;
RADEON_WRITE ( RS480_NB_MC_INDEX , 0xff ) ;
return ret ;
}
2008-02-19 14:32:45 +03:00
static u32 RS690_READ_MCIND ( drm_radeon_private_t * dev_priv , int addr )
{
2008-05-28 07:28:59 +04:00
u32 ret ;
2008-02-19 14:32:45 +03:00
RADEON_WRITE ( RS690_MC_INDEX , ( addr & RS690_MC_INDEX_MASK ) ) ;
2008-05-28 07:28:59 +04:00
ret = RADEON_READ ( RS690_MC_DATA ) ;
RADEON_WRITE ( RS690_MC_INDEX , RS690_MC_INDEX_MASK ) ;
return ret ;
}
static u32 IGP_READ_MCIND ( drm_radeon_private_t * dev_priv , int addr )
{
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS690 )
return RS690_READ_MCIND ( dev_priv , addr ) ;
else
return RS480_READ_MCIND ( dev_priv , addr ) ;
2008-02-19 14:32:45 +03:00
}
2008-02-07 08:01:05 +03:00
u32 radeon_read_fb_location ( drm_radeon_private_t * dev_priv )
{
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV515 )
2008-05-28 07:28:59 +04:00
return R500_READ_MCIND ( dev_priv , RV515_MC_FB_LOCATION ) ;
2008-02-19 14:32:45 +03:00
else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS690 )
return RS690_READ_MCIND ( dev_priv , RS690_MC_FB_LOCATION ) ;
2008-02-07 08:01:05 +03:00
else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) > CHIP_RV515 )
2008-05-28 07:28:59 +04:00
return R500_READ_MCIND ( dev_priv , R520_MC_FB_LOCATION ) ;
2008-02-07 08:01:05 +03:00
else
return RADEON_READ ( RADEON_MC_FB_LOCATION ) ;
}
static void radeon_write_fb_location ( drm_radeon_private_t * dev_priv , u32 fb_loc )
{
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV515 )
2008-05-28 07:28:59 +04:00
R500_WRITE_MCIND ( RV515_MC_FB_LOCATION , fb_loc ) ;
2008-02-19 14:32:45 +03:00
else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS690 )
RS690_WRITE_MCIND ( RS690_MC_FB_LOCATION , fb_loc ) ;
2008-02-07 08:01:05 +03:00
else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) > CHIP_RV515 )
2008-05-28 07:28:59 +04:00
R500_WRITE_MCIND ( R520_MC_FB_LOCATION , fb_loc ) ;
2008-02-07 08:01:05 +03:00
else
RADEON_WRITE ( RADEON_MC_FB_LOCATION , fb_loc ) ;
}
static void radeon_write_agp_location ( drm_radeon_private_t * dev_priv , u32 agp_loc )
{
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV515 )
2008-05-28 07:28:59 +04:00
R500_WRITE_MCIND ( RV515_MC_AGP_LOCATION , agp_loc ) ;
2008-02-19 14:32:45 +03:00
else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS690 )
RS690_WRITE_MCIND ( RS690_MC_AGP_LOCATION , agp_loc ) ;
2008-02-07 08:01:05 +03:00
else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) > CHIP_RV515 )
2008-05-28 07:28:59 +04:00
R500_WRITE_MCIND ( R520_MC_AGP_LOCATION , agp_loc ) ;
2008-02-07 08:01:05 +03:00
else
RADEON_WRITE ( RADEON_MC_AGP_LOCATION , agp_loc ) ;
}
2008-06-19 05:40:44 +04:00
static void radeon_write_agp_base ( drm_radeon_private_t * dev_priv , u64 agp_base )
{
u32 agp_base_hi = upper_32_bits ( agp_base ) ;
u32 agp_base_lo = agp_base & 0xffffffff ;
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV515 ) {
R500_WRITE_MCIND ( RV515_MC_AGP_BASE , agp_base_lo ) ;
R500_WRITE_MCIND ( RV515_MC_AGP_BASE_2 , agp_base_hi ) ;
} else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS690 ) {
RS690_WRITE_MCIND ( RS690_MC_AGP_BASE , agp_base_lo ) ;
RS690_WRITE_MCIND ( RS690_MC_AGP_BASE_2 , agp_base_hi ) ;
} else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) > CHIP_RV515 ) {
R500_WRITE_MCIND ( R520_MC_AGP_BASE , agp_base_lo ) ;
R500_WRITE_MCIND ( R520_MC_AGP_BASE_2 , agp_base_hi ) ;
2008-06-19 06:38:29 +04:00
} else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS480 ) {
RADEON_WRITE ( RADEON_AGP_BASE , agp_base_lo ) ;
RADEON_WRITE ( RS480_AGP_BASE_2 , 0 ) ;
2008-06-19 05:40:44 +04:00
} else {
RADEON_WRITE ( RADEON_AGP_BASE , agp_base_lo ) ;
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) > = CHIP_R200 )
RADEON_WRITE ( RADEON_AGP_BASE_2 , agp_base_hi ) ;
}
}
2007-07-11 09:53:27 +04:00
static int RADEON_READ_PLL ( struct drm_device * dev , int addr )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
RADEON_WRITE8 ( RADEON_CLOCK_CNTL_INDEX , addr & 0x1f ) ;
return RADEON_READ ( RADEON_CLOCK_CNTL_DATA ) ;
}
2008-02-07 08:01:05 +03:00
static u32 RADEON_READ_PCIE ( drm_radeon_private_t * dev_priv , int addr )
2005-09-11 14:28:11 +04:00
{
RADEON_WRITE8 ( RADEON_PCIE_INDEX , addr & 0xff ) ;
return RADEON_READ ( RADEON_PCIE_DATA ) ;
}
2005-04-17 02:20:36 +04:00
# if RADEON_FIFO_DEBUG
2005-09-25 08:28:13 +04:00
static void radeon_status ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
2008-04-30 11:55:10 +04:00
printk ( " %s: \n " , __func__ ) ;
2005-09-25 08:28:13 +04:00
printk ( " RBBM_STATUS = 0x%08x \n " ,
( unsigned int ) RADEON_READ ( RADEON_RBBM_STATUS ) ) ;
printk ( " CP_RB_RTPR = 0x%08x \n " ,
( unsigned int ) RADEON_READ ( RADEON_CP_RB_RPTR ) ) ;
printk ( " CP_RB_WTPR = 0x%08x \n " ,
( unsigned int ) RADEON_READ ( RADEON_CP_RB_WPTR ) ) ;
printk ( " AIC_CNTL = 0x%08x \n " ,
( unsigned int ) RADEON_READ ( RADEON_AIC_CNTL ) ) ;
printk ( " AIC_STAT = 0x%08x \n " ,
( unsigned int ) RADEON_READ ( RADEON_AIC_STAT ) ) ;
printk ( " AIC_PT_BASE = 0x%08x \n " ,
( unsigned int ) RADEON_READ ( RADEON_AIC_PT_BASE ) ) ;
printk ( " TLB_ADDR = 0x%08x \n " ,
( unsigned int ) RADEON_READ ( RADEON_AIC_TLB_ADDR ) ) ;
printk ( " TLB_DATA = 0x%08x \n " ,
( unsigned int ) RADEON_READ ( RADEON_AIC_TLB_DATA ) ) ;
2005-04-17 02:20:36 +04:00
}
# endif
/* ================================================================
* Engine , FIFO control
*/
2005-09-25 08:28:13 +04:00
static int radeon_do_pixcache_flush ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
u32 tmp ;
int i ;
dev_priv - > stats . boxes | = RADEON_BOX_WAIT_IDLE ;
2008-05-28 05:51:12 +04:00
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) < = CHIP_RV280 ) {
tmp = RADEON_READ ( RADEON_RB3D_DSTCACHE_CTLSTAT ) ;
tmp | = RADEON_RB3D_DC_FLUSH_ALL ;
RADEON_WRITE ( RADEON_RB3D_DSTCACHE_CTLSTAT , tmp ) ;
for ( i = 0 ; i < dev_priv - > usec_timeout ; i + + ) {
if ( ! ( RADEON_READ ( RADEON_RB3D_DSTCACHE_CTLSTAT )
& RADEON_RB3D_DC_BUSY ) ) {
return 0 ;
}
DRM_UDELAY ( 1 ) ;
}
} else {
2008-08-13 03:46:31 +04:00
/* don't flush or purge cache here or lockup */
return 0 ;
2005-04-17 02:20:36 +04:00
}
# if RADEON_FIFO_DEBUG
2005-09-25 08:28:13 +04:00
DRM_ERROR ( " failed! \n " ) ;
radeon_status ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-08-25 13:22:43 +04:00
return - EBUSY ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
static int radeon_do_wait_for_fifo ( drm_radeon_private_t * dev_priv , int entries )
2005-04-17 02:20:36 +04:00
{
int i ;
dev_priv - > stats . boxes | = RADEON_BOX_WAIT_IDLE ;
2005-09-25 08:28:13 +04:00
for ( i = 0 ; i < dev_priv - > usec_timeout ; i + + ) {
int slots = ( RADEON_READ ( RADEON_RBBM_STATUS )
& RADEON_RBBM_FIFOCNT_MASK ) ;
if ( slots > = entries )
return 0 ;
DRM_UDELAY ( 1 ) ;
2005-04-17 02:20:36 +04:00
}
2008-09-01 02:51:52 +04:00
DRM_DEBUG ( " wait for fifo failed status : 0x%08X 0x%08X \n " ,
2008-08-13 03:46:31 +04:00
RADEON_READ ( RADEON_RBBM_STATUS ) ,
RADEON_READ ( R300_VAP_CNTL_STATUS ) ) ;
2005-04-17 02:20:36 +04:00
# if RADEON_FIFO_DEBUG
2005-09-25 08:28:13 +04:00
DRM_ERROR ( " failed! \n " ) ;
radeon_status ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-08-25 13:22:43 +04:00
return - EBUSY ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
static int radeon_do_wait_for_idle ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
int i , ret ;
dev_priv - > stats . boxes | = RADEON_BOX_WAIT_IDLE ;
2005-09-25 08:28:13 +04:00
ret = radeon_do_wait_for_fifo ( dev_priv , 64 ) ;
if ( ret )
return ret ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
for ( i = 0 ; i < dev_priv - > usec_timeout ; i + + ) {
if ( ! ( RADEON_READ ( RADEON_RBBM_STATUS )
& RADEON_RBBM_ACTIVE ) ) {
radeon_do_pixcache_flush ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2005-09-25 08:28:13 +04:00
DRM_UDELAY ( 1 ) ;
2005-04-17 02:20:36 +04:00
}
2008-09-01 02:51:52 +04:00
DRM_DEBUG ( " wait idle failed status : 0x%08X 0x%08X \n " ,
2008-08-13 03:46:31 +04:00
RADEON_READ ( RADEON_RBBM_STATUS ) ,
RADEON_READ ( R300_VAP_CNTL_STATUS ) ) ;
2005-04-17 02:20:36 +04:00
# if RADEON_FIFO_DEBUG
2005-09-25 08:28:13 +04:00
DRM_ERROR ( " failed! \n " ) ;
radeon_status ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-08-25 13:22:43 +04:00
return - EBUSY ;
2005-04-17 02:20:36 +04:00
}
2008-05-28 05:57:40 +04:00
static void radeon_init_pipes ( drm_radeon_private_t * dev_priv )
{
uint32_t gb_tile_config , gb_pipe_sel = 0 ;
/* RS4xx/RS6xx/R4xx/R5xx */
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) > = CHIP_R420 ) {
gb_pipe_sel = RADEON_READ ( R400_GB_PIPE_SELECT ) ;
dev_priv - > num_gb_pipes = ( ( gb_pipe_sel > > 12 ) & 0x3 ) + 1 ;
} else {
/* R3xx */
if ( ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R300 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R350 ) ) {
dev_priv - > num_gb_pipes = 2 ;
} else {
/* R3Vxx */
dev_priv - > num_gb_pipes = 1 ;
}
}
DRM_INFO ( " Num pipes: %d \n " , dev_priv - > num_gb_pipes ) ;
gb_tile_config = ( R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/ ) ;
switch ( dev_priv - > num_gb_pipes ) {
case 2 : gb_tile_config | = R300_PIPE_COUNT_R300 ; break ;
case 3 : gb_tile_config | = R300_PIPE_COUNT_R420_3P ; break ;
case 4 : gb_tile_config | = R300_PIPE_COUNT_R420 ; break ;
default :
case 1 : gb_tile_config | = R300_PIPE_COUNT_RV350 ; break ;
}
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) > = CHIP_RV515 ) {
RADEON_WRITE_PLL ( R500_DYN_SCLK_PWMEM_PIPE , ( 1 | ( ( gb_pipe_sel > > 8 ) & 0xf ) < < 4 ) ) ;
RADEON_WRITE ( R500_SU_REG_DEST , ( ( 1 < < dev_priv - > num_gb_pipes ) - 1 ) ) ;
}
RADEON_WRITE ( R300_GB_TILE_CONFIG , gb_tile_config ) ;
radeon_do_wait_for_idle ( dev_priv ) ;
RADEON_WRITE ( R300_DST_PIPE_CONFIG , RADEON_READ ( R300_DST_PIPE_CONFIG ) | R300_PIPE_AUTO_CONFIG ) ;
RADEON_WRITE ( R300_RB2D_DSTCACHE_MODE , ( RADEON_READ ( R300_RB2D_DSTCACHE_MODE ) |
R300_DC_AUTOFLUSH_ENABLE |
R300_DC_DC_DISABLE_IGNORE_PE ) ) ;
}
2005-04-17 02:20:36 +04:00
/* ================================================================
* CP control , initialization
*/
/* Load the microcode for the CP */
2005-09-25 08:28:13 +04:00
static void radeon_cp_load_microcode ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
int i ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
radeon_do_wait_for_idle ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_CP_ME_RAM_ADDR , 0 ) ;
2008-05-28 05:21:25 +04:00
if ( ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R100 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV100 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV200 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS100 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS200 ) ) {
DRM_INFO ( " Loading R100 Microcode \n " ) ;
for ( i = 0 ; i < 256 ; i + + ) {
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAH ,
R100_cp_microcode [ i ] [ 1 ] ) ;
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAL ,
R100_cp_microcode [ i ] [ 0 ] ) ;
}
} else if ( ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R200 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV250 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV280 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS300 ) ) {
2005-04-17 02:20:36 +04:00
DRM_INFO ( " Loading R200 Microcode \n " ) ;
2005-09-25 08:28:13 +04:00
for ( i = 0 ; i < 256 ; i + + ) {
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAH ,
R200_cp_microcode [ i ] [ 1 ] ) ;
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAL ,
R200_cp_microcode [ i ] [ 0 ] ) ;
2005-04-17 02:20:36 +04:00
}
2008-05-28 05:21:25 +04:00
} else if ( ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R300 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R350 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV350 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV380 ) | |
2008-05-28 07:28:59 +04:00
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS480 ) ) {
2005-04-17 02:20:36 +04:00
DRM_INFO ( " Loading R300 Microcode \n " ) ;
2005-09-25 08:28:13 +04:00
for ( i = 0 ; i < 256 ; i + + ) {
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAH ,
R300_cp_microcode [ i ] [ 1 ] ) ;
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAL ,
R300_cp_microcode [ i ] [ 0 ] ) ;
2005-04-17 02:20:36 +04:00
}
2008-05-28 05:21:25 +04:00
} else if ( ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R420 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV410 ) ) {
DRM_INFO ( " Loading R400 Microcode \n " ) ;
for ( i = 0 ; i < 256 ; i + + ) {
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAH ,
R420_cp_microcode [ i ] [ 1 ] ) ;
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAL ,
R420_cp_microcode [ i ] [ 0 ] ) ;
}
} else if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS690 ) {
DRM_INFO ( " Loading RS690 Microcode \n " ) ;
for ( i = 0 ; i < 256 ; i + + ) {
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAH ,
RS690_cp_microcode [ i ] [ 1 ] ) ;
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAL ,
RS690_cp_microcode [ i ] [ 0 ] ) ;
}
} else if ( ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV515 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R520 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV530 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_R580 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV560 ) | |
( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RV570 ) ) {
DRM_INFO ( " Loading R500 Microcode \n " ) ;
2005-09-25 08:28:13 +04:00
for ( i = 0 ; i < 256 ; i + + ) {
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAH ,
2008-05-28 05:21:25 +04:00
R520_cp_microcode [ i ] [ 1 ] ) ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_CP_ME_RAM_DATAL ,
2008-05-28 05:21:25 +04:00
R520_cp_microcode [ i ] [ 0 ] ) ;
2005-04-17 02:20:36 +04:00
}
}
}
/* Flush any pending commands to the CP. This should only be used just
* prior to a wait for idle , as it informs the engine that the command
* stream is ending .
*/
2005-09-25 08:28:13 +04:00
static void radeon_do_cp_flush ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
#if 0
u32 tmp ;
2005-09-25 08:28:13 +04:00
tmp = RADEON_READ ( RADEON_CP_RB_WPTR ) | ( 1 < < 31 ) ;
RADEON_WRITE ( RADEON_CP_RB_WPTR , tmp ) ;
2005-04-17 02:20:36 +04:00
# endif
}
/* Wait for the CP to go idle.
*/
2005-09-25 08:28:13 +04:00
int radeon_do_cp_idle ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
RING_LOCALS ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
BEGIN_RING ( 6 ) ;
2005-04-17 02:20:36 +04:00
RADEON_PURGE_CACHE ( ) ;
RADEON_PURGE_ZCACHE ( ) ;
RADEON_WAIT_UNTIL_IDLE ( ) ;
ADVANCE_RING ( ) ;
COMMIT_RING ( ) ;
2005-09-25 08:28:13 +04:00
return radeon_do_wait_for_idle ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
}
/* Start the Command Processor.
*/
2005-09-25 08:28:13 +04:00
static void radeon_do_cp_start ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
RING_LOCALS ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
radeon_do_wait_for_idle ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_CP_CSQ_CNTL , dev_priv - > cp_mode ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > cp_running = 1 ;
2008-08-13 03:46:31 +04:00
BEGIN_RING ( 8 ) ;
/* isync can only be written through cp on r5xx write it here */
OUT_RING ( CP_PACKET0 ( RADEON_ISYNC_CNTL , 0 ) ) ;
OUT_RING ( RADEON_ISYNC_ANY2D_IDLE3D |
RADEON_ISYNC_ANY3D_IDLE2D |
RADEON_ISYNC_WAIT_IDLEGUI |
RADEON_ISYNC_CPSCRATCH_IDLEGUI ) ;
2005-04-17 02:20:36 +04:00
RADEON_PURGE_CACHE ( ) ;
RADEON_PURGE_ZCACHE ( ) ;
RADEON_WAIT_UNTIL_IDLE ( ) ;
ADVANCE_RING ( ) ;
COMMIT_RING ( ) ;
2008-08-13 03:46:31 +04:00
dev_priv - > track_flush | = RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED ;
2005-04-17 02:20:36 +04:00
}
/* Reset the Command Processor. This will not flush any pending
* commands , so you must wait for the CP command stream to complete
* before calling this routine .
*/
2005-09-25 08:28:13 +04:00
static void radeon_do_cp_reset ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
u32 cur_read_ptr ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
cur_read_ptr = RADEON_READ ( RADEON_CP_RB_RPTR ) ;
RADEON_WRITE ( RADEON_CP_RB_WPTR , cur_read_ptr ) ;
SET_RING_HEAD ( dev_priv , cur_read_ptr ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > ring . tail = cur_read_ptr ;
}
/* Stop the Command Processor. This will not flush any pending
* commands , so you must flush the command stream and wait for the CP
* to go idle before calling this routine .
*/
2005-09-25 08:28:13 +04:00
static void radeon_do_cp_stop ( drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_CP_CSQ_CNTL , RADEON_CSQ_PRIDIS_INDDIS ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > cp_running = 0 ;
}
/* Reset the engine. This will stop the CP if it is running.
*/
2007-07-11 09:53:27 +04:00
static int radeon_do_engine_reset ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2008-05-28 05:54:06 +04:00
u32 clock_cntl_index = 0 , mclk_cntl = 0 , rbbm_soft_reset ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
radeon_do_pixcache_flush ( dev_priv ) ;
2008-05-28 05:54:06 +04:00
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) < = CHIP_RV410 ) {
/* may need something similar for newer chips */
2008-02-07 08:01:05 +03:00
clock_cntl_index = RADEON_READ ( RADEON_CLOCK_CNTL_INDEX ) ;
mclk_cntl = RADEON_READ_PLL ( dev , RADEON_MCLK_CNTL ) ;
RADEON_WRITE_PLL ( RADEON_MCLK_CNTL , ( mclk_cntl |
RADEON_FORCEON_MCLKA |
RADEON_FORCEON_MCLKB |
RADEON_FORCEON_YCLKA |
RADEON_FORCEON_YCLKB |
RADEON_FORCEON_MC |
RADEON_FORCEON_AIC ) ) ;
2008-05-28 05:54:06 +04:00
}
2008-02-07 08:01:05 +03:00
2008-05-28 05:54:06 +04:00
rbbm_soft_reset = RADEON_READ ( RADEON_RBBM_SOFT_RESET ) ;
RADEON_WRITE ( RADEON_RBBM_SOFT_RESET , ( rbbm_soft_reset |
RADEON_SOFT_RESET_CP |
RADEON_SOFT_RESET_HI |
RADEON_SOFT_RESET_SE |
RADEON_SOFT_RESET_RE |
RADEON_SOFT_RESET_PP |
RADEON_SOFT_RESET_E2 |
RADEON_SOFT_RESET_RB ) ) ;
RADEON_READ ( RADEON_RBBM_SOFT_RESET ) ;
RADEON_WRITE ( RADEON_RBBM_SOFT_RESET , ( rbbm_soft_reset &
~ ( RADEON_SOFT_RESET_CP |
RADEON_SOFT_RESET_HI |
RADEON_SOFT_RESET_SE |
RADEON_SOFT_RESET_RE |
RADEON_SOFT_RESET_PP |
RADEON_SOFT_RESET_E2 |
RADEON_SOFT_RESET_RB ) ) ) ;
RADEON_READ ( RADEON_RBBM_SOFT_RESET ) ;
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) < = CHIP_RV410 ) {
2008-02-07 08:01:05 +03:00
RADEON_WRITE_PLL ( RADEON_MCLK_CNTL , mclk_cntl ) ;
RADEON_WRITE ( RADEON_CLOCK_CNTL_INDEX , clock_cntl_index ) ;
RADEON_WRITE ( RADEON_RBBM_SOFT_RESET , rbbm_soft_reset ) ;
}
2005-04-17 02:20:36 +04:00
2008-05-28 05:57:40 +04:00
/* setup the raster pipes */
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) > = CHIP_R300 )
radeon_init_pipes ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
/* Reset the CP ring */
2005-09-25 08:28:13 +04:00
radeon_do_cp_reset ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
/* The CP is no longer running after an engine reset */
dev_priv - > cp_running = 0 ;
/* Reset any pending vertex, indirect buffers */
2005-09-25 08:28:13 +04:00
radeon_freelist_reset ( dev ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2007-07-11 09:53:27 +04:00
static void radeon_cp_init_ring_buffer ( struct drm_device * dev ,
2005-09-25 08:28:13 +04:00
drm_radeon_private_t * dev_priv )
2005-04-17 02:20:36 +04:00
{
u32 ring_start , cur_read_ptr ;
u32 tmp ;
2007-11-05 05:50:58 +03:00
2006-03-19 11:37:55 +03:00
/* Initialize the memory controller. With new memory map, the fb location
* is not changed , it should have been properly initialized already . Part
* of the problem is that the code below is bogus , assuming the GART is
* always appended to the fb which is not necessarily the case
*/
if ( ! dev_priv - > new_memmap )
2008-02-07 08:01:05 +03:00
radeon_write_fb_location ( dev_priv ,
2006-03-19 11:37:55 +03:00
( ( dev_priv - > gart_vm_start - 1 ) & 0xffff0000 )
| ( dev_priv - > fb_location > > 16 ) ) ;
2005-04-17 02:20:36 +04:00
# if __OS_HAS_AGP
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_AGP ) {
2008-06-19 05:40:44 +04:00
radeon_write_agp_base ( dev_priv , dev - > agp - > base ) ;
2008-02-07 08:01:05 +03:00
radeon_write_agp_location ( dev_priv ,
2005-09-25 08:28:13 +04:00
( ( ( dev_priv - > gart_vm_start - 1 +
dev_priv - > gart_size ) & 0xffff0000 ) |
( dev_priv - > gart_vm_start > > 16 ) ) ) ;
2005-04-17 02:20:36 +04:00
ring_start = ( dev_priv - > cp_ring - > offset
- dev - > agp - > base
+ dev_priv - > gart_vm_start ) ;
2005-10-26 14:05:25 +04:00
} else
2005-04-17 02:20:36 +04:00
# endif
ring_start = ( dev_priv - > cp_ring - > offset
2005-10-26 14:05:25 +04:00
- ( unsigned long ) dev - > sg - > virtual
2005-04-17 02:20:36 +04:00
+ dev_priv - > gart_vm_start ) ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_CP_RB_BASE , ring_start ) ;
2005-04-17 02:20:36 +04:00
/* Set the write pointer delay */
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_CP_RB_WPTR_DELAY , 0 ) ;
2005-04-17 02:20:36 +04:00
/* Initialize the ring buffer's read and write pointers */
2005-09-25 08:28:13 +04:00
cur_read_ptr = RADEON_READ ( RADEON_CP_RB_RPTR ) ;
RADEON_WRITE ( RADEON_CP_RB_WPTR , cur_read_ptr ) ;
SET_RING_HEAD ( dev_priv , cur_read_ptr ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > ring . tail = cur_read_ptr ;
# if __OS_HAS_AGP
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_AGP ) {
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_CP_RB_RPTR_ADDR ,
dev_priv - > ring_rptr - > offset
- dev - > agp - > base + dev_priv - > gart_vm_start ) ;
2005-04-17 02:20:36 +04:00
} else
# endif
{
2007-07-11 10:53:40 +04:00
struct drm_sg_mem * entry = dev - > sg ;
2005-04-17 02:20:36 +04:00
unsigned long tmp_ofs , page_ofs ;
2005-10-26 14:05:25 +04:00
tmp_ofs = dev_priv - > ring_rptr - > offset -
( unsigned long ) dev - > sg - > virtual ;
2005-04-17 02:20:36 +04:00
page_ofs = tmp_ofs > > PAGE_SHIFT ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_CP_RB_RPTR_ADDR , entry - > busaddr [ page_ofs ] ) ;
DRM_DEBUG ( " ring rptr: offset=0x%08lx handle=0x%08lx \n " ,
( unsigned long ) entry - > busaddr [ page_ofs ] ,
entry - > handle + tmp_ofs ) ;
2005-04-17 02:20:36 +04:00
}
2006-03-19 11:37:55 +03:00
/* Set ring buffer size */
# ifdef __BIG_ENDIAN
RADEON_WRITE ( RADEON_CP_RB_CNTL ,
2008-02-07 07:59:24 +03:00
RADEON_BUF_SWAP_32BIT |
( dev_priv - > ring . fetch_size_l2ow < < 18 ) |
( dev_priv - > ring . rptr_update_l2qw < < 8 ) |
dev_priv - > ring . size_l2qw ) ;
2006-03-19 11:37:55 +03:00
# else
2008-02-07 07:59:24 +03:00
RADEON_WRITE ( RADEON_CP_RB_CNTL ,
( dev_priv - > ring . fetch_size_l2ow < < 18 ) |
( dev_priv - > ring . rptr_update_l2qw < < 8 ) |
dev_priv - > ring . size_l2qw ) ;
2006-03-19 11:37:55 +03:00
# endif
/* Start with assuming that writeback doesn't work */
dev_priv - > writeback_works = 0 ;
2005-04-17 02:20:36 +04:00
/* Initialize the scratch register pointer. This will cause
* the scratch register values to be written out to memory
* whenever they are updated .
*
* We simply put this behind the ring read pointer , this works
* with PCI GART as well as ( whatever kind of ) AGP GART
*/
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_SCRATCH_ADDR , RADEON_READ ( RADEON_CP_RB_RPTR_ADDR )
+ RADEON_SCRATCH_REG_OFFSET ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > scratch = ( ( __volatile__ u32 * )
dev_priv - > ring_rptr - > handle +
( RADEON_SCRATCH_REG_OFFSET / sizeof ( u32 ) ) ) ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_SCRATCH_UMSK , 0x7 ) ;
2005-04-17 02:20:36 +04:00
2006-03-19 11:37:55 +03:00
/* Turn on bus mastering */
tmp = RADEON_READ ( RADEON_BUS_CNTL ) & ~ RADEON_BUS_MASTER_DIS ;
RADEON_WRITE ( RADEON_BUS_CNTL , tmp ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > sarea_priv - > last_frame = dev_priv - > scratch [ 0 ] = 0 ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_LAST_FRAME_REG , dev_priv - > sarea_priv - > last_frame ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > sarea_priv - > last_dispatch = dev_priv - > scratch [ 1 ] = 0 ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_LAST_DISPATCH_REG ,
dev_priv - > sarea_priv - > last_dispatch ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > sarea_priv - > last_clear = dev_priv - > scratch [ 2 ] = 0 ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_LAST_CLEAR_REG , dev_priv - > sarea_priv - > last_clear ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
radeon_do_wait_for_idle ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
/* Sync everything up */
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_ISYNC_CNTL ,
( RADEON_ISYNC_ANY2D_IDLE3D |
RADEON_ISYNC_ANY3D_IDLE2D |
RADEON_ISYNC_WAIT_IDLEGUI |
RADEON_ISYNC_CPSCRATCH_IDLEGUI ) ) ;
2006-03-19 11:37:55 +03:00
}
static void radeon_test_writeback ( drm_radeon_private_t * dev_priv )
{
u32 tmp ;
/* Writeback doesn't seem to work everywhere, test it here and possibly
* enable it if it appears to work
*/
DRM_WRITE32 ( dev_priv - > ring_rptr , RADEON_SCRATCHOFF ( 1 ) , 0 ) ;
RADEON_WRITE ( RADEON_SCRATCH_REG1 , 0xdeadbeef ) ;
for ( tmp = 0 ; tmp < dev_priv - > usec_timeout ; tmp + + ) {
if ( DRM_READ32 ( dev_priv - > ring_rptr , RADEON_SCRATCHOFF ( 1 ) ) = =
0xdeadbeef )
break ;
DRM_UDELAY ( 1 ) ;
}
if ( tmp < dev_priv - > usec_timeout ) {
dev_priv - > writeback_works = 1 ;
DRM_INFO ( " writeback test succeeded in %d usecs \n " , tmp ) ;
} else {
dev_priv - > writeback_works = 0 ;
DRM_INFO ( " writeback test failed \n " ) ;
}
if ( radeon_no_wb = = 1 ) {
dev_priv - > writeback_works = 0 ;
DRM_INFO ( " writeback forced off \n " ) ;
}
2006-08-07 14:37:46 +04:00
if ( ! dev_priv - > writeback_works ) {
/* Disable writeback to avoid unnecessary bus master transfer */
RADEON_WRITE ( RADEON_CP_RB_CNTL , RADEON_READ ( RADEON_CP_RB_CNTL ) |
RADEON_RB_NO_UPDATE ) ;
RADEON_WRITE ( RADEON_SCRATCH_UMSK , 0 ) ;
}
2005-04-17 02:20:36 +04:00
}
2007-05-08 09:19:23 +04:00
/* Enable or disable IGP GART on the chip */
static void radeon_set_igpgart ( drm_radeon_private_t * dev_priv , int on )
2008-02-19 14:32:45 +03:00
{
u32 temp ;
if ( on ) {
2008-05-28 07:28:59 +04:00
DRM_DEBUG ( " programming igp gart %08X %08lX %08X \n " ,
2008-02-19 14:32:45 +03:00
dev_priv - > gart_vm_start ,
( long ) dev_priv - > gart_info . bus_addr ,
dev_priv - > gart_size ) ;
2008-05-28 07:28:59 +04:00
temp = IGP_READ_MCIND ( dev_priv , RS480_MC_MISC_CNTL ) ;
if ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS690 )
IGP_WRITE_MCIND ( RS480_MC_MISC_CNTL , ( RS480_GART_INDEX_REG_EN |
RS690_BLOCK_GFX_D3_EN ) ) ;
else
IGP_WRITE_MCIND ( RS480_MC_MISC_CNTL , RS480_GART_INDEX_REG_EN ) ;
2008-02-19 14:32:45 +03:00
2008-05-28 07:28:59 +04:00
IGP_WRITE_MCIND ( RS480_AGP_ADDRESS_SPACE_SIZE , ( RS480_GART_EN |
RS480_VA_SIZE_32MB ) ) ;
2008-02-19 14:32:45 +03:00
2008-05-28 07:28:59 +04:00
temp = IGP_READ_MCIND ( dev_priv , RS480_GART_FEATURE_ID ) ;
IGP_WRITE_MCIND ( RS480_GART_FEATURE_ID , ( RS480_HANG_EN |
RS480_TLB_ENABLE |
RS480_GTW_LAC_EN |
RS480_1LEVEL_GART ) ) ;
2008-02-19 14:32:45 +03:00
2008-05-28 05:27:01 +04:00
temp = dev_priv - > gart_info . bus_addr & 0xfffff000 ;
temp | = ( upper_32_bits ( dev_priv - > gart_info . bus_addr ) & 0xff ) < < 4 ;
2008-05-28 07:28:59 +04:00
IGP_WRITE_MCIND ( RS480_GART_BASE , temp ) ;
temp = IGP_READ_MCIND ( dev_priv , RS480_AGP_MODE_CNTL ) ;
IGP_WRITE_MCIND ( RS480_AGP_MODE_CNTL , ( ( 1 < < RS480_REQ_TYPE_SNOOP_SHIFT ) |
RS480_REQ_TYPE_SNOOP_DIS ) ) ;
2008-06-19 06:38:29 +04:00
radeon_write_agp_base ( dev_priv , dev_priv - > gart_vm_start ) ;
2008-05-28 05:28:27 +04:00
2008-02-19 14:32:45 +03:00
dev_priv - > gart_size = 32 * 1024 * 1024 ;
temp = ( ( ( dev_priv - > gart_vm_start - 1 + dev_priv - > gart_size ) &
0xffff0000 ) | ( dev_priv - > gart_vm_start > > 16 ) ) ;
2008-05-28 07:28:59 +04:00
radeon_write_agp_location ( dev_priv , temp ) ;
2008-02-19 14:32:45 +03:00
2008-05-28 07:28:59 +04:00
temp = IGP_READ_MCIND ( dev_priv , RS480_AGP_ADDRESS_SPACE_SIZE ) ;
IGP_WRITE_MCIND ( RS480_AGP_ADDRESS_SPACE_SIZE , ( RS480_GART_EN |
RS480_VA_SIZE_32MB ) ) ;
2008-02-19 14:32:45 +03:00
do {
2008-05-28 07:28:59 +04:00
temp = IGP_READ_MCIND ( dev_priv , RS480_GART_CACHE_CNTRL ) ;
if ( ( temp & RS480_GART_CACHE_INVALIDATE ) = = 0 )
2008-02-19 14:32:45 +03:00
break ;
DRM_UDELAY ( 1 ) ;
} while ( 1 ) ;
2008-05-28 07:28:59 +04:00
IGP_WRITE_MCIND ( RS480_GART_CACHE_CNTRL ,
RS480_GART_CACHE_INVALIDATE ) ;
2008-05-28 06:54:16 +04:00
2008-02-19 14:32:45 +03:00
do {
2008-05-28 07:28:59 +04:00
temp = IGP_READ_MCIND ( dev_priv , RS480_GART_CACHE_CNTRL ) ;
if ( ( temp & RS480_GART_CACHE_INVALIDATE ) = = 0 )
2008-02-19 14:32:45 +03:00
break ;
DRM_UDELAY ( 1 ) ;
} while ( 1 ) ;
2008-05-28 07:28:59 +04:00
IGP_WRITE_MCIND ( RS480_GART_CACHE_CNTRL , 0 ) ;
2008-02-19 14:32:45 +03:00
} else {
2008-05-28 07:28:59 +04:00
IGP_WRITE_MCIND ( RS480_AGP_ADDRESS_SPACE_SIZE , 0 ) ;
2008-02-19 14:32:45 +03:00
}
}
2005-09-11 14:28:11 +04:00
static void radeon_set_pciegart ( drm_radeon_private_t * dev_priv , int on )
{
u32 tmp = RADEON_READ_PCIE ( dev_priv , RADEON_PCIE_TX_GART_CNTL ) ;
if ( on ) {
DRM_DEBUG ( " programming pcie %08X %08lX %08X \n " ,
2005-09-25 08:28:13 +04:00
dev_priv - > gart_vm_start ,
( long ) dev_priv - > gart_info . bus_addr ,
2005-09-11 14:28:11 +04:00
dev_priv - > gart_size ) ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE_PCIE ( RADEON_PCIE_TX_DISCARD_RD_ADDR_LO ,
dev_priv - > gart_vm_start ) ;
RADEON_WRITE_PCIE ( RADEON_PCIE_TX_GART_BASE ,
dev_priv - > gart_info . bus_addr ) ;
RADEON_WRITE_PCIE ( RADEON_PCIE_TX_GART_START_LO ,
dev_priv - > gart_vm_start ) ;
RADEON_WRITE_PCIE ( RADEON_PCIE_TX_GART_END_LO ,
dev_priv - > gart_vm_start +
dev_priv - > gart_size - 1 ) ;
2008-02-07 08:01:05 +03:00
radeon_write_agp_location ( dev_priv , 0xffffffc0 ) ; /* ?? */
2005-09-25 08:28:13 +04:00
RADEON_WRITE_PCIE ( RADEON_PCIE_TX_GART_CNTL ,
RADEON_PCIE_TX_GART_EN ) ;
2005-09-11 14:28:11 +04:00
} else {
2005-09-25 08:28:13 +04:00
RADEON_WRITE_PCIE ( RADEON_PCIE_TX_GART_CNTL ,
tmp & ~ RADEON_PCIE_TX_GART_EN ) ;
2005-09-11 14:28:11 +04:00
}
2005-04-17 02:20:36 +04:00
}
/* Enable or disable PCI GART on the chip */
2005-09-25 08:28:13 +04:00
static void radeon_set_pcigart ( drm_radeon_private_t * dev_priv , int on )
2005-04-17 02:20:36 +04:00
{
2006-01-02 13:32:48 +03:00
u32 tmp ;
2005-04-17 02:20:36 +04:00
2008-05-28 07:28:59 +04:00
if ( ( ( dev_priv - > flags & RADEON_FAMILY_MASK ) = = CHIP_RS690 ) | |
( dev_priv - > flags & RADEON_IS_IGPGART ) ) {
2007-05-08 09:19:23 +04:00
radeon_set_igpgart ( dev_priv , on ) ;
return ;
}
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_PCIE ) {
2005-09-11 14:28:11 +04:00
radeon_set_pciegart ( dev_priv , on ) ;
return ;
}
2005-04-17 02:20:36 +04:00
2007-11-05 05:50:58 +03:00
tmp = RADEON_READ ( RADEON_AIC_CNTL ) ;
2006-01-02 13:32:48 +03:00
2005-09-25 08:28:13 +04:00
if ( on ) {
RADEON_WRITE ( RADEON_AIC_CNTL ,
tmp | RADEON_PCIGART_TRANSLATE_EN ) ;
2005-04-17 02:20:36 +04:00
/* set PCI GART page-table base address
*/
2005-09-11 14:28:11 +04:00
RADEON_WRITE ( RADEON_AIC_PT_BASE , dev_priv - > gart_info . bus_addr ) ;
2005-04-17 02:20:36 +04:00
/* set address range for PCI address translate
*/
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_AIC_LO_ADDR , dev_priv - > gart_vm_start ) ;
RADEON_WRITE ( RADEON_AIC_HI_ADDR , dev_priv - > gart_vm_start
+ dev_priv - > gart_size - 1 ) ;
2005-04-17 02:20:36 +04:00
/* Turn off AGP aperture -- is this required for PCI GART?
*/
2008-02-07 08:01:05 +03:00
radeon_write_agp_location ( dev_priv , 0xffffffc0 ) ;
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_AGP_COMMAND , 0 ) ; /* clear AGP_COMMAND */
2005-04-17 02:20:36 +04:00
} else {
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_AIC_CNTL ,
tmp & ~ RADEON_PCIGART_TRANSLATE_EN ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-07-11 09:53:27 +04:00
static int radeon_do_init_cp ( struct drm_device * dev , drm_radeon_init_t * init )
2005-04-17 02:20:36 +04:00
{
2006-01-02 13:32:48 +03:00
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2006-03-25 10:09:46 +03:00
/* if we require new memory map but we don't have it fail */
2006-09-21 22:25:09 +04:00
if ( ( dev_priv - > flags & RADEON_NEW_MEMMAP ) & & ! dev_priv - > new_memmap ) {
2006-08-19 11:43:52 +04:00
DRM_ERROR ( " Cannot initialise DRM on this card \n This card requires a new X.org DDX for 3D \n " ) ;
2006-03-25 10:09:46 +03:00
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2006-03-25 10:09:46 +03:00
}
2006-09-21 22:25:09 +04:00
if ( init - > is_pci & & ( dev_priv - > flags & RADEON_IS_AGP ) ) {
2006-01-02 13:32:48 +03:00
DRM_DEBUG ( " Forcing AGP card to PCI mode \n " ) ;
2006-09-21 22:25:09 +04:00
dev_priv - > flags & = ~ RADEON_IS_AGP ;
} else if ( ! ( dev_priv - > flags & ( RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE ) )
2006-08-19 11:43:52 +04:00
& & ! init - > is_pci ) {
DRM_DEBUG ( " Restoring AGP flag \n " ) ;
2006-09-21 22:25:09 +04:00
dev_priv - > flags | = RADEON_IS_AGP ;
2006-01-02 13:32:48 +03:00
}
2005-04-17 02:20:36 +04:00
2006-09-21 22:25:09 +04:00
if ( ( ! ( dev_priv - > flags & RADEON_IS_AGP ) ) & & ! dev - > sg ) {
2005-09-25 08:28:13 +04:00
DRM_ERROR ( " PCI GART memory not allocated! \n " ) ;
2005-04-17 02:20:36 +04:00
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
dev_priv - > usec_timeout = init - > usec_timeout ;
2005-09-25 08:28:13 +04:00
if ( dev_priv - > usec_timeout < 1 | |
dev_priv - > usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
DRM_DEBUG ( " TIMEOUT problem! \n " ) ;
2005-04-17 02:20:36 +04:00
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
2007-07-11 06:16:01 +04:00
/* Enable vblank on CRTC1 for older X servers
*/
dev_priv - > vblank_crtc = DRM_RADEON_VBLANK_CRTC1 ;
2006-01-02 13:32:48 +03:00
switch ( init - > func ) {
2005-04-17 02:20:36 +04:00
case RADEON_INIT_R200_CP :
2005-09-25 08:28:13 +04:00
dev_priv - > microcode_version = UCODE_R200 ;
2005-04-17 02:20:36 +04:00
break ;
case RADEON_INIT_R300_CP :
2005-09-25 08:28:13 +04:00
dev_priv - > microcode_version = UCODE_R300 ;
2005-04-17 02:20:36 +04:00
break ;
default :
2005-09-25 08:28:13 +04:00
dev_priv - > microcode_version = UCODE_R100 ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
dev_priv - > do_boxes = 0 ;
dev_priv - > cp_mode = init - > cp_mode ;
/* We don't support anything other than bus-mastering ring mode,
* but the ring can be in either AGP or PCI space for the ring
* read pointer .
*/
2005-09-25 08:28:13 +04:00
if ( ( init - > cp_mode ! = RADEON_CSQ_PRIBM_INDDIS ) & &
( init - > cp_mode ! = RADEON_CSQ_PRIBM_INDBM ) ) {
DRM_DEBUG ( " BAD cp_mode (%x)! \n " , init - > cp_mode ) ;
2005-04-17 02:20:36 +04:00
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
switch ( init - > fb_bpp ) {
2005-04-17 02:20:36 +04:00
case 16 :
dev_priv - > color_fmt = RADEON_COLOR_FORMAT_RGB565 ;
break ;
case 32 :
default :
dev_priv - > color_fmt = RADEON_COLOR_FORMAT_ARGB8888 ;
break ;
}
2005-09-25 08:28:13 +04:00
dev_priv - > front_offset = init - > front_offset ;
dev_priv - > front_pitch = init - > front_pitch ;
dev_priv - > back_offset = init - > back_offset ;
dev_priv - > back_pitch = init - > back_pitch ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
switch ( init - > depth_bpp ) {
2005-04-17 02:20:36 +04:00
case 16 :
dev_priv - > depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z ;
break ;
case 32 :
default :
dev_priv - > depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z ;
break ;
}
2005-09-25 08:28:13 +04:00
dev_priv - > depth_offset = init - > depth_offset ;
dev_priv - > depth_pitch = init - > depth_pitch ;
2005-04-17 02:20:36 +04:00
/* Hardware state for depth clears. Remove this if/when we no
* longer clear the depth buffer with a 3 D rectangle . Hard - code
* all values to prevent unwanted 3 D state from slipping through
* and screwing with the clear operation .
*/
dev_priv - > depth_clear . rb3d_cntl = ( RADEON_PLANE_MASK_ENABLE |
( dev_priv - > color_fmt < < 10 ) |
2005-09-25 08:28:13 +04:00
( dev_priv - > microcode_version = =
UCODE_R100 ? RADEON_ZBLOCK16 : 0 ) ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
dev_priv - > depth_clear . rb3d_zstencilcntl =
( dev_priv - > depth_fmt |
RADEON_Z_TEST_ALWAYS |
RADEON_STENCIL_TEST_ALWAYS |
RADEON_STENCIL_S_FAIL_REPLACE |
RADEON_STENCIL_ZPASS_REPLACE |
RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > depth_clear . se_cntl = ( RADEON_FFACE_CULL_CW |
RADEON_BFACE_SOLID |
RADEON_FFACE_SOLID |
RADEON_FLAT_SHADE_VTX_LAST |
RADEON_DIFFUSE_SHADE_FLAT |
RADEON_ALPHA_SHADE_FLAT |
RADEON_SPECULAR_SHADE_FLAT |
RADEON_FOG_SHADE_FLAT |
RADEON_VTX_PIX_CENTER_OGL |
RADEON_ROUND_MODE_TRUNC |
RADEON_ROUND_PREC_8TH_PIX ) ;
dev_priv - > ring_offset = init - > ring_offset ;
dev_priv - > ring_rptr_offset = init - > ring_rptr_offset ;
dev_priv - > buffers_offset = init - > buffers_offset ;
dev_priv - > gart_textures_offset = init - > gart_textures_offset ;
2005-09-25 08:28:13 +04:00
2007-05-25 23:04:51 +04:00
dev_priv - > sarea = drm_getsarea ( dev ) ;
2005-09-25 08:28:13 +04:00
if ( ! dev_priv - > sarea ) {
2005-04-17 02:20:36 +04:00
DRM_ERROR ( " could not find sarea! \n " ) ;
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
dev_priv - > cp_ring = drm_core_findmap ( dev , init - > ring_offset ) ;
2005-09-25 08:28:13 +04:00
if ( ! dev_priv - > cp_ring ) {
2005-04-17 02:20:36 +04:00
DRM_ERROR ( " could not find cp ring region! \n " ) ;
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
dev_priv - > ring_rptr = drm_core_findmap ( dev , init - > ring_rptr_offset ) ;
2005-09-25 08:28:13 +04:00
if ( ! dev_priv - > ring_rptr ) {
2005-04-17 02:20:36 +04:00
DRM_ERROR ( " could not find ring read pointer! \n " ) ;
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
2005-08-05 16:11:22 +04:00
dev - > agp_buffer_token = init - > buffers_offset ;
2005-04-17 02:20:36 +04:00
dev - > agp_buffer_map = drm_core_findmap ( dev , init - > buffers_offset ) ;
2005-09-25 08:28:13 +04:00
if ( ! dev - > agp_buffer_map ) {
2005-04-17 02:20:36 +04:00
DRM_ERROR ( " could not find dma buffer region! \n " ) ;
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
if ( init - > gart_textures_offset ) {
dev_priv - > gart_textures =
drm_core_findmap ( dev , init - > gart_textures_offset ) ;
if ( ! dev_priv - > gart_textures ) {
2005-04-17 02:20:36 +04:00
DRM_ERROR ( " could not find GART texture region! \n " ) ;
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
}
dev_priv - > sarea_priv =
2005-09-25 08:28:13 +04:00
( drm_radeon_sarea_t * ) ( ( u8 * ) dev_priv - > sarea - > handle +
init - > sarea_priv_offset ) ;
2005-04-17 02:20:36 +04:00
# if __OS_HAS_AGP
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_AGP ) {
2005-09-25 08:28:13 +04:00
drm_core_ioremap ( dev_priv - > cp_ring , dev ) ;
drm_core_ioremap ( dev_priv - > ring_rptr , dev ) ;
drm_core_ioremap ( dev - > agp_buffer_map , dev ) ;
if ( ! dev_priv - > cp_ring - > handle | |
! dev_priv - > ring_rptr - > handle | |
! dev - > agp_buffer_map - > handle ) {
2005-04-17 02:20:36 +04:00
DRM_ERROR ( " could not find ioremap agp regions! \n " ) ;
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
} else
# endif
{
2005-09-25 08:28:13 +04:00
dev_priv - > cp_ring - > handle = ( void * ) dev_priv - > cp_ring - > offset ;
2005-04-17 02:20:36 +04:00
dev_priv - > ring_rptr - > handle =
2005-09-25 08:28:13 +04:00
( void * ) dev_priv - > ring_rptr - > offset ;
dev - > agp_buffer_map - > handle =
( void * ) dev - > agp_buffer_map - > offset ;
DRM_DEBUG ( " dev_priv->cp_ring->handle %p \n " ,
dev_priv - > cp_ring - > handle ) ;
DRM_DEBUG ( " dev_priv->ring_rptr->handle %p \n " ,
dev_priv - > ring_rptr - > handle ) ;
DRM_DEBUG ( " dev->agp_buffer_map->handle %p \n " ,
dev - > agp_buffer_map - > handle ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-07 08:01:05 +03:00
dev_priv - > fb_location = ( radeon_read_fb_location ( dev_priv ) & 0xffff ) < < 16 ;
2007-11-05 05:50:58 +03:00
dev_priv - > fb_size =
2008-02-07 08:01:05 +03:00
( ( radeon_read_fb_location ( dev_priv ) & 0xffff0000u ) + 0x10000 )
2006-03-19 11:37:55 +03:00
- dev_priv - > fb_location ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
dev_priv - > front_pitch_offset = ( ( ( dev_priv - > front_pitch / 64 ) < < 22 ) |
( ( dev_priv - > front_offset
+ dev_priv - > fb_location ) > > 10 ) ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
dev_priv - > back_pitch_offset = ( ( ( dev_priv - > back_pitch / 64 ) < < 22 ) |
( ( dev_priv - > back_offset
+ dev_priv - > fb_location ) > > 10 ) ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
dev_priv - > depth_pitch_offset = ( ( ( dev_priv - > depth_pitch / 64 ) < < 22 ) |
( ( dev_priv - > depth_offset
+ dev_priv - > fb_location ) > > 10 ) ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > gart_size = init - > gart_size ;
2006-03-19 11:37:55 +03:00
/* New let's set the memory map ... */
if ( dev_priv - > new_memmap ) {
u32 base = 0 ;
DRM_INFO ( " Setting GART location based on new memory map \n " ) ;
/* If using AGP, try to locate the AGP aperture at the same
* location in the card and on the bus , though we have to
* align it down .
*/
# if __OS_HAS_AGP
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_AGP ) {
2006-03-19 11:37:55 +03:00
base = dev - > agp - > base ;
/* Check if valid */
2007-02-18 10:03:21 +03:00
if ( ( base + dev_priv - > gart_size - 1 ) > = dev_priv - > fb_location & &
base < ( dev_priv - > fb_location + dev_priv - > fb_size - 1 ) ) {
2006-03-19 11:37:55 +03:00
DRM_INFO ( " Can't use AGP base @0x%08lx, won't fit \n " ,
dev - > agp - > base ) ;
base = 0 ;
}
}
# endif
/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
if ( base = = 0 ) {
base = dev_priv - > fb_location + dev_priv - > fb_size ;
2007-02-18 10:03:21 +03:00
if ( base < dev_priv - > fb_location | |
( ( base + dev_priv - > gart_size ) & 0xfffffffful ) < base )
2006-03-19 11:37:55 +03:00
base = dev_priv - > fb_location
- dev_priv - > gart_size ;
2007-11-05 05:50:58 +03:00
}
2006-03-19 11:37:55 +03:00
dev_priv - > gart_vm_start = base & 0xffc00000u ;
if ( dev_priv - > gart_vm_start ! = base )
DRM_INFO ( " GART aligned down from 0x%08x to 0x%08x \n " ,
base , dev_priv - > gart_vm_start ) ;
} else {
DRM_INFO ( " Setting GART location based on old memory map \n " ) ;
dev_priv - > gart_vm_start = dev_priv - > fb_location +
RADEON_READ ( RADEON_CONFIG_APER_SIZE ) ;
}
2005-04-17 02:20:36 +04:00
# if __OS_HAS_AGP
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_AGP )
2005-04-17 02:20:36 +04:00
dev_priv - > gart_buffers_offset = ( dev - > agp_buffer_map - > offset
2005-09-25 08:28:13 +04:00
- dev - > agp - > base
+ dev_priv - > gart_vm_start ) ;
2005-04-17 02:20:36 +04:00
else
# endif
dev_priv - > gart_buffers_offset = ( dev - > agp_buffer_map - > offset
2005-10-26 14:05:25 +04:00
- ( unsigned long ) dev - > sg - > virtual
+ dev_priv - > gart_vm_start ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " dev_priv->gart_size %d \n " , dev_priv - > gart_size ) ;
DRM_DEBUG ( " dev_priv->gart_vm_start 0x%x \n " , dev_priv - > gart_vm_start ) ;
DRM_DEBUG ( " dev_priv->gart_buffers_offset 0x%lx \n " ,
dev_priv - > gart_buffers_offset ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
dev_priv - > ring . start = ( u32 * ) dev_priv - > cp_ring - > handle ;
dev_priv - > ring . end = ( ( u32 * ) dev_priv - > cp_ring - > handle
2005-04-17 02:20:36 +04:00
+ init - > ring_size / sizeof ( u32 ) ) ;
dev_priv - > ring . size = init - > ring_size ;
2005-09-25 08:28:13 +04:00
dev_priv - > ring . size_l2qw = drm_order ( init - > ring_size / 8 ) ;
2005-04-17 02:20:36 +04:00
2008-02-07 07:59:24 +03:00
dev_priv - > ring . rptr_update = /* init->rptr_update */ 4096 ;
dev_priv - > ring . rptr_update_l2qw = drm_order ( /* init->rptr_update */ 4096 / 8 ) ;
dev_priv - > ring . fetch_size = /* init->fetch_size */ 32 ;
dev_priv - > ring . fetch_size_l2ow = drm_order ( /* init->fetch_size */ 32 / 16 ) ;
2005-09-25 08:28:13 +04:00
dev_priv - > ring . tail_mask = ( dev_priv - > ring . size / sizeof ( u32 ) ) - 1 ;
2005-04-17 02:20:36 +04:00
dev_priv - > ring . high_mark = RADEON_RING_HIGH_MARK ;
# if __OS_HAS_AGP
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_AGP ) {
2005-04-17 02:20:36 +04:00
/* Turn off PCI GART */
2005-09-25 08:28:13 +04:00
radeon_set_pcigart ( dev_priv , 0 ) ;
2005-04-17 02:20:36 +04:00
} else
# endif
{
2008-03-17 03:24:24 +03:00
dev_priv - > gart_info . table_mask = DMA_BIT_MASK ( 32 ) ;
2005-09-11 14:28:11 +04:00
/* if we have an offset set from userspace */
2007-05-08 09:19:23 +04:00
if ( dev_priv - > pcigart_offset_set ) {
2005-09-25 08:28:13 +04:00
dev_priv - > gart_info . bus_addr =
dev_priv - > pcigart_offset + dev_priv - > fb_location ;
2006-01-02 09:18:39 +03:00
dev_priv - > gart_info . mapping . offset =
2007-11-05 03:45:27 +03:00
dev_priv - > pcigart_offset + dev_priv - > fb_aper_offset ;
2006-01-02 09:18:39 +03:00
dev_priv - > gart_info . mapping . size =
2007-05-08 09:19:23 +04:00
dev_priv - > gart_info . table_size ;
2006-01-02 09:18:39 +03:00
2008-07-15 09:48:05 +04:00
drm_core_ioremap_wc ( & dev_priv - > gart_info . mapping , dev ) ;
2005-09-25 08:28:13 +04:00
dev_priv - > gart_info . addr =
2006-01-02 09:18:39 +03:00
dev_priv - > gart_info . mapping . handle ;
2005-09-25 08:28:13 +04:00
2007-05-08 09:19:23 +04:00
if ( dev_priv - > flags & RADEON_IS_PCIE )
dev_priv - > gart_info . gart_reg_if = DRM_ATI_GART_PCIE ;
else
dev_priv - > gart_info . gart_reg_if = DRM_ATI_GART_PCI ;
2005-09-25 08:28:13 +04:00
dev_priv - > gart_info . gart_table_location =
DRM_ATI_GART_FB ;
2006-01-02 09:18:39 +03:00
DRM_DEBUG ( " Setting phys_pci_gart to %p %08lX \n " ,
2005-09-25 08:28:13 +04:00
dev_priv - > gart_info . addr ,
dev_priv - > pcigart_offset ) ;
} else {
2007-05-08 09:19:23 +04:00
if ( dev_priv - > flags & RADEON_IS_IGPGART )
dev_priv - > gart_info . gart_reg_if = DRM_ATI_GART_IGP ;
else
dev_priv - > gart_info . gart_reg_if = DRM_ATI_GART_PCI ;
2005-09-25 08:28:13 +04:00
dev_priv - > gart_info . gart_table_location =
DRM_ATI_GART_MAIN ;
2006-01-02 09:18:39 +03:00
dev_priv - > gart_info . addr = NULL ;
dev_priv - > gart_info . bus_addr = 0 ;
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_PCIE ) {
2005-09-25 08:28:13 +04:00
DRM_ERROR
( " Cannot use PCI Express without GART in FB memory \n " ) ;
2005-09-11 14:28:11 +04:00
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-09-11 14:28:11 +04:00
}
}
if ( ! drm_ati_pcigart_init ( dev , & dev_priv - > gart_info ) ) {
2005-09-25 08:28:13 +04:00
DRM_ERROR ( " failed to init PCI GART! \n " ) ;
2005-04-17 02:20:36 +04:00
radeon_do_cleanup_cp ( dev ) ;
2007-08-25 13:22:43 +04:00
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
}
/* Turn on PCI GART */
2005-09-25 08:28:13 +04:00
radeon_set_pcigart ( dev_priv , 1 ) ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
radeon_cp_load_microcode ( dev_priv ) ;
radeon_cp_init_ring_buffer ( dev , dev_priv ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > last_buf = 0 ;
2005-09-25 08:28:13 +04:00
radeon_do_engine_reset ( dev ) ;
2006-03-19 11:37:55 +03:00
radeon_test_writeback ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2007-07-11 09:53:27 +04:00
static int radeon_do_cleanup_cp ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed , it ' s too late .
*/
2005-09-25 08:28:13 +04:00
if ( dev - > irq_enabled )
drm_irq_uninstall ( dev ) ;
2005-04-17 02:20:36 +04:00
# if __OS_HAS_AGP
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_AGP ) {
2006-01-02 13:32:48 +03:00
if ( dev_priv - > cp_ring ! = NULL ) {
2005-09-25 08:28:13 +04:00
drm_core_ioremapfree ( dev_priv - > cp_ring , dev ) ;
2006-01-02 13:32:48 +03:00
dev_priv - > cp_ring = NULL ;
}
if ( dev_priv - > ring_rptr ! = NULL ) {
2005-09-25 08:28:13 +04:00
drm_core_ioremapfree ( dev_priv - > ring_rptr , dev ) ;
2006-01-02 13:32:48 +03:00
dev_priv - > ring_rptr = NULL ;
}
2005-09-25 08:28:13 +04:00
if ( dev - > agp_buffer_map ! = NULL ) {
drm_core_ioremapfree ( dev - > agp_buffer_map , dev ) ;
2005-04-17 02:20:36 +04:00
dev - > agp_buffer_map = NULL ;
}
} else
# endif
{
2006-01-02 13:32:48 +03:00
if ( dev_priv - > gart_info . bus_addr ) {
/* Turn off PCI GART */
radeon_set_pcigart ( dev_priv , 0 ) ;
2005-09-11 14:28:11 +04:00
if ( ! drm_ati_pcigart_cleanup ( dev , & dev_priv - > gart_info ) )
DRM_ERROR ( " failed to cleanup PCI GART! \n " ) ;
2006-01-02 13:32:48 +03:00
}
2005-09-25 08:28:13 +04:00
2006-01-02 13:32:48 +03:00
if ( dev_priv - > gart_info . gart_table_location = = DRM_ATI_GART_FB )
{
2006-01-02 09:18:39 +03:00
drm_core_ioremapfree ( & dev_priv - > gart_info . mapping , dev ) ;
2007-05-08 09:19:23 +04:00
dev_priv - > gart_info . addr = 0 ;
2005-09-11 14:28:11 +04:00
}
2005-04-17 02:20:36 +04:00
}
/* only clear to the start of flags */
memset ( dev_priv , 0 , offsetof ( drm_radeon_private_t , flags ) ) ;
return 0 ;
}
2005-09-25 08:28:13 +04:00
/* This code will reinit the Radeon CP hardware after a resume from disc.
* AFAIK , it would be very difficult to pickle the state at suspend time , so
2005-04-17 02:20:36 +04:00
* here we make sure that all Radeon hardware initialisation is re - done without
* affecting running applications .
*
* Charl P . Botha < http : //cpbotha.net>
*/
2007-07-11 09:53:27 +04:00
static int radeon_do_resume_cp ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2005-09-25 08:28:13 +04:00
if ( ! dev_priv ) {
DRM_ERROR ( " Called with no initialization \n " ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
DRM_DEBUG ( " Starting radeon_do_resume_cp() \n " ) ;
# if __OS_HAS_AGP
2006-09-21 22:25:09 +04:00
if ( dev_priv - > flags & RADEON_IS_AGP ) {
2005-04-17 02:20:36 +04:00
/* Turn off PCI GART */
2005-09-25 08:28:13 +04:00
radeon_set_pcigart ( dev_priv , 0 ) ;
2005-04-17 02:20:36 +04:00
} else
# endif
{
/* Turn on PCI GART */
2005-09-25 08:28:13 +04:00
radeon_set_pcigart ( dev_priv , 1 ) ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
radeon_cp_load_microcode ( dev_priv ) ;
radeon_cp_init_ring_buffer ( dev , dev_priv ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
radeon_do_engine_reset ( dev ) ;
2008-06-19 06:36:55 +04:00
radeon_enable_interrupt ( dev ) ;
2005-04-17 02:20:36 +04:00
DRM_DEBUG ( " radeon_do_resume_cp() complete \n " ) ;
return 0 ;
}
2007-09-03 06:06:45 +04:00
int radeon_cp_init ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
drm_radeon_init_t * init = data ;
2005-04-17 02:20:36 +04:00
2007-08-25 14:23:09 +04:00
LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-17 02:20:36 +04:00
2007-09-03 06:06:45 +04:00
if ( init - > func = = RADEON_INIT_R300_CP )
2008-02-07 08:01:05 +03:00
r300_init_reg_flags ( dev ) ;
2005-08-16 14:43:16 +04:00
2007-09-03 06:06:45 +04:00
switch ( init - > func ) {
2005-04-17 02:20:36 +04:00
case RADEON_INIT_CP :
case RADEON_INIT_R200_CP :
case RADEON_INIT_R300_CP :
2007-09-03 06:06:45 +04:00
return radeon_do_init_cp ( dev , init ) ;
2005-04-17 02:20:36 +04:00
case RADEON_CLEANUP_CP :
2005-09-25 08:28:13 +04:00
return radeon_do_cleanup_cp ( dev ) ;
2005-04-17 02:20:36 +04:00
}
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
2007-09-03 06:06:45 +04:00
int radeon_cp_start ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2007-08-25 14:23:09 +04:00
LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
if ( dev_priv - > cp_running ) {
2008-01-24 08:58:57 +03:00
DRM_DEBUG ( " while CP running \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2005-09-25 08:28:13 +04:00
if ( dev_priv - > cp_mode = = RADEON_CSQ_PRIDIS_INDDIS ) {
2008-01-24 08:58:57 +03:00
DRM_DEBUG ( " called with bogus CP mode (%d) \n " ,
dev_priv - > cp_mode ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2005-09-25 08:28:13 +04:00
radeon_do_cp_start ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/* Stop the CP. The engine must have been idled before calling this
* routine .
*/
2007-09-03 06:06:45 +04:00
int radeon_cp_stop ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2007-09-03 06:06:45 +04:00
drm_radeon_cp_stop_t * stop = data ;
2005-04-17 02:20:36 +04:00
int ret ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2007-08-25 14:23:09 +04:00
LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-17 02:20:36 +04:00
if ( ! dev_priv - > cp_running )
return 0 ;
/* Flush any pending CP commands. This ensures any outstanding
* commands are exectuted by the engine before we turn it off .
*/
2007-09-03 06:06:45 +04:00
if ( stop - > flush ) {
2005-09-25 08:28:13 +04:00
radeon_do_cp_flush ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
}
/* If we fail to make the engine go idle, we return an error
* code so that the DRM ioctl wrapper can try again .
*/
2007-09-03 06:06:45 +04:00
if ( stop - > idle ) {
2005-09-25 08:28:13 +04:00
ret = radeon_do_cp_idle ( dev_priv ) ;
if ( ret )
return ret ;
2005-04-17 02:20:36 +04:00
}
/* Finally, we can turn off the CP. If the engine isn't idle,
* we will get some dropped triangles as they won ' t be fully
* rendered before the CP is shut down .
*/
2005-09-25 08:28:13 +04:00
radeon_do_cp_stop ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
/* Reset the engine */
2005-09-25 08:28:13 +04:00
radeon_do_engine_reset ( dev ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2007-07-11 09:53:27 +04:00
void radeon_do_release ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
int i , ret ;
if ( dev_priv ) {
if ( dev_priv - > cp_running ) {
/* Stop the cp */
2005-09-25 08:28:13 +04:00
while ( ( ret = radeon_do_cp_idle ( dev_priv ) ) ! = 0 ) {
2005-04-17 02:20:36 +04:00
DRM_DEBUG ( " radeon_do_cp_idle %d \n " , ret ) ;
# ifdef __linux__
schedule ( ) ;
# else
tsleep ( & ret , PZERO , " rdnrel " , 1 ) ;
# endif
}
2005-09-25 08:28:13 +04:00
radeon_do_cp_stop ( dev_priv ) ;
radeon_do_engine_reset ( dev ) ;
2005-04-17 02:20:36 +04:00
}
/* Disable *all* interrupts */
if ( dev_priv - > mmio ) /* remove this after permanent addmaps */
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_GEN_INT_CNTL , 0 ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
if ( dev_priv - > mmio ) { /* remove all surfaces */
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < RADEON_MAX_SURFACES ; i + + ) {
2005-09-25 08:28:13 +04:00
RADEON_WRITE ( RADEON_SURFACE0_INFO + 16 * i , 0 ) ;
RADEON_WRITE ( RADEON_SURFACE0_LOWER_BOUND +
16 * i , 0 ) ;
RADEON_WRITE ( RADEON_SURFACE0_UPPER_BOUND +
16 * i , 0 ) ;
2005-04-17 02:20:36 +04:00
}
}
/* Free memory heap structures */
2005-09-25 08:28:13 +04:00
radeon_mem_takedown ( & ( dev_priv - > gart_heap ) ) ;
radeon_mem_takedown ( & ( dev_priv - > fb_heap ) ) ;
2005-04-17 02:20:36 +04:00
/* deallocate kernel resources */
2005-09-25 08:28:13 +04:00
radeon_do_cleanup_cp ( dev ) ;
2005-04-17 02:20:36 +04:00
}
}
/* Just reset the CP ring. Called as part of an X Server engine reset.
*/
2007-09-03 06:06:45 +04:00
int radeon_cp_reset ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2007-08-25 14:23:09 +04:00
LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
if ( ! dev_priv ) {
2008-01-24 08:58:57 +03:00
DRM_DEBUG ( " called before init done \n " ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
radeon_do_cp_reset ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
/* The CP is no longer running after an engine reset */
dev_priv - > cp_running = 0 ;
return 0 ;
}
2007-09-03 06:06:45 +04:00
int radeon_cp_idle ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2007-08-25 14:23:09 +04:00
LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
return radeon_do_cp_idle ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
}
/* Added by Charl P. Botha to call radeon_do_resume_cp().
*/
2007-09-03 06:06:45 +04:00
int radeon_cp_resume ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
return radeon_do_resume_cp ( dev ) ;
}
2007-09-03 06:06:45 +04:00
int radeon_engine_reset ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2007-08-25 14:23:09 +04:00
LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
return radeon_do_engine_reset ( dev ) ;
2005-04-17 02:20:36 +04:00
}
/* ================================================================
* Fullscreen mode
*/
/* KW: Deprecated to say the least:
*/
2007-09-03 06:06:45 +04:00
int radeon_fullscreen ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
return 0 ;
}
/* ================================================================
* Freelist management
*/
/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
* bufs until freelist code is used . Note this hides a problem with
* the scratch register * ( used to keep track of last buffer
* completed ) being written to before * the last buffer has actually
2005-09-25 08:28:13 +04:00
* completed rendering .
2005-04-17 02:20:36 +04:00
*
* KW : It ' s also a good way to find free buffers quickly .
*
* KW : Ideally this loop wouldn ' t exist , and freelist_get wouldn ' t
* sleep . However , bugs in older versions of radeon_accel . c mean that
* we essentially have to do this , else old clients will break .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* However , it does leave open a potential deadlock where all the
* buffers are held by other clients , which can ' t release them because
2005-09-25 08:28:13 +04:00
* they can ' t get the lock .
2005-04-17 02:20:36 +04:00
*/
2007-07-11 10:17:42 +04:00
struct drm_buf * radeon_freelist_get ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
2007-07-11 10:32:08 +04:00
struct drm_device_dma * dma = dev - > dma ;
2005-04-17 02:20:36 +04:00
drm_radeon_private_t * dev_priv = dev - > dev_private ;
drm_radeon_buf_priv_t * buf_priv ;
2007-07-11 10:17:42 +04:00
struct drm_buf * buf ;
2005-04-17 02:20:36 +04:00
int i , t ;
int start ;
2005-09-25 08:28:13 +04:00
if ( + + dev_priv - > last_buf > = dma - > buf_count )
2005-04-17 02:20:36 +04:00
dev_priv - > last_buf = 0 ;
start = dev_priv - > last_buf ;
2005-09-25 08:28:13 +04:00
for ( t = 0 ; t < dev_priv - > usec_timeout ; t + + ) {
u32 done_age = GET_SCRATCH ( 1 ) ;
DRM_DEBUG ( " done_age = %d \n " , done_age ) ;
for ( i = start ; i < dma - > buf_count ; i + + ) {
2005-04-17 02:20:36 +04:00
buf = dma - > buflist [ i ] ;
buf_priv = buf - > dev_private ;
2007-08-25 14:23:09 +04:00
if ( buf - > file_priv = = NULL | | ( buf - > pending & &
buf_priv - > age < =
done_age ) ) {
2005-04-17 02:20:36 +04:00
dev_priv - > stats . requested_bufs + + ;
buf - > pending = 0 ;
return buf ;
}
start = 0 ;
}
if ( t ) {
2005-09-25 08:28:13 +04:00
DRM_UDELAY ( 1 ) ;
2005-04-17 02:20:36 +04:00
dev_priv - > stats . freelist_loops + + ;
}
}
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " returning NULL! \n " ) ;
2005-04-17 02:20:36 +04:00
return NULL ;
}
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
#if 0
2007-07-11 10:17:42 +04:00
struct drm_buf * radeon_freelist_get ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
2007-07-11 10:32:08 +04:00
struct drm_device_dma * dma = dev - > dma ;
2005-04-17 02:20:36 +04:00
drm_radeon_private_t * dev_priv = dev - > dev_private ;
drm_radeon_buf_priv_t * buf_priv ;
2007-07-11 10:17:42 +04:00
struct drm_buf * buf ;
2005-04-17 02:20:36 +04:00
int i , t ;
int start ;
u32 done_age = DRM_READ32 ( dev_priv - > ring_rptr , RADEON_SCRATCHOFF ( 1 ) ) ;
2005-09-25 08:28:13 +04:00
if ( + + dev_priv - > last_buf > = dma - > buf_count )
2005-04-17 02:20:36 +04:00
dev_priv - > last_buf = 0 ;
start = dev_priv - > last_buf ;
dev_priv - > stats . freelist_loops + + ;
2005-09-25 08:28:13 +04:00
for ( t = 0 ; t < 2 ; t + + ) {
for ( i = start ; i < dma - > buf_count ; i + + ) {
2005-04-17 02:20:36 +04:00
buf = dma - > buflist [ i ] ;
buf_priv = buf - > dev_private ;
2007-08-25 14:23:09 +04:00
if ( buf - > file_priv = = 0 | | ( buf - > pending & &
buf_priv - > age < =
done_age ) ) {
2005-04-17 02:20:36 +04:00
dev_priv - > stats . requested_bufs + + ;
buf - > pending = 0 ;
return buf ;
}
}
start = 0 ;
}
return NULL ;
}
# endif
2007-07-11 09:53:27 +04:00
void radeon_freelist_reset ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
2007-07-11 10:32:08 +04:00
struct drm_device_dma * dma = dev - > dma ;
2005-04-17 02:20:36 +04:00
drm_radeon_private_t * dev_priv = dev - > dev_private ;
int i ;
dev_priv - > last_buf = 0 ;
2005-09-25 08:28:13 +04:00
for ( i = 0 ; i < dma - > buf_count ; i + + ) {
2007-07-11 10:17:42 +04:00
struct drm_buf * buf = dma - > buflist [ i ] ;
2005-04-17 02:20:36 +04:00
drm_radeon_buf_priv_t * buf_priv = buf - > dev_private ;
buf_priv - > age = 0 ;
}
}
/* ================================================================
* CP command submission
*/
2005-09-25 08:28:13 +04:00
int radeon_wait_ring ( drm_radeon_private_t * dev_priv , int n )
2005-04-17 02:20:36 +04:00
{
drm_radeon_ring_buffer_t * ring = & dev_priv - > ring ;
int i ;
2005-09-25 08:28:13 +04:00
u32 last_head = GET_RING_HEAD ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
for ( i = 0 ; i < dev_priv - > usec_timeout ; i + + ) {
u32 head = GET_RING_HEAD ( dev_priv ) ;
2005-04-17 02:20:36 +04:00
ring - > space = ( head - ring - > tail ) * sizeof ( u32 ) ;
2005-09-25 08:28:13 +04:00
if ( ring - > space < = 0 )
2005-04-17 02:20:36 +04:00
ring - > space + = ring - > size ;
2005-09-25 08:28:13 +04:00
if ( ring - > space > n )
2005-04-17 02:20:36 +04:00
return 0 ;
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
dev_priv - > stats . boxes | = RADEON_BOX_WAIT_IDLE ;
if ( head ! = last_head )
i = 0 ;
last_head = head ;
2005-09-25 08:28:13 +04:00
DRM_UDELAY ( 1 ) ;
2005-04-17 02:20:36 +04:00
}
/* FIXME: This return value is ignored in the BEGIN_RING macro! */
# if RADEON_FIFO_DEBUG
2005-09-25 08:28:13 +04:00
radeon_status ( dev_priv ) ;
DRM_ERROR ( " failed! \n " ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-08-25 13:22:43 +04:00
return - EBUSY ;
2005-04-17 02:20:36 +04:00
}
2007-08-25 14:23:09 +04:00
static int radeon_cp_get_buffers ( struct drm_device * dev ,
struct drm_file * file_priv ,
2007-07-11 09:27:12 +04:00
struct drm_dma * d )
2005-04-17 02:20:36 +04:00
{
int i ;
2007-07-11 10:17:42 +04:00
struct drm_buf * buf ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
for ( i = d - > granted_count ; i < d - > request_count ; i + + ) {
buf = radeon_freelist_get ( dev ) ;
if ( ! buf )
2007-08-25 13:22:43 +04:00
return - EBUSY ; /* NOTE: broken client */
2005-04-17 02:20:36 +04:00
2007-08-25 14:23:09 +04:00
buf - > file_priv = file_priv ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
if ( DRM_COPY_TO_USER ( & d - > request_indices [ i ] , & buf - > idx ,
sizeof ( buf - > idx ) ) )
2007-08-25 13:22:43 +04:00
return - EFAULT ;
2005-09-25 08:28:13 +04:00
if ( DRM_COPY_TO_USER ( & d - > request_sizes [ i ] , & buf - > total ,
sizeof ( buf - > total ) ) )
2007-08-25 13:22:43 +04:00
return - EFAULT ;
2005-04-17 02:20:36 +04:00
d - > granted_count + + ;
}
return 0 ;
}
2007-09-03 06:06:45 +04:00
int radeon_cp_buffers ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-07-11 10:32:08 +04:00
struct drm_device_dma * dma = dev - > dma ;
2005-04-17 02:20:36 +04:00
int ret = 0 ;
2007-09-03 06:06:45 +04:00
struct drm_dma * d = data ;
2005-04-17 02:20:36 +04:00
2007-08-25 14:23:09 +04:00
LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-17 02:20:36 +04:00
/* Please don't send us buffers.
*/
2007-09-03 06:06:45 +04:00
if ( d - > send_count ! = 0 ) {
2005-09-25 08:28:13 +04:00
DRM_ERROR ( " Process %d trying to send %d buffers via drmDMA \n " ,
2007-09-03 06:06:45 +04:00
DRM_CURRENTPID , d - > send_count ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
/* We'll send you buffers.
*/
2007-09-03 06:06:45 +04:00
if ( d - > request_count < 0 | | d - > request_count > dma - > buf_count ) {
2005-09-25 08:28:13 +04:00
DRM_ERROR ( " Process %d trying to get %d buffers (of %d max) \n " ,
2007-09-03 06:06:45 +04:00
DRM_CURRENTPID , d - > request_count , dma - > buf_count ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
2007-09-03 06:06:45 +04:00
d - > granted_count = 0 ;
2005-04-17 02:20:36 +04:00
2007-09-03 06:06:45 +04:00
if ( d - > request_count ) {
ret = radeon_cp_get_buffers ( dev , file_priv , d ) ;
2005-04-17 02:20:36 +04:00
}
return ret ;
}
2005-11-10 14:16:34 +03:00
int radeon_driver_load ( struct drm_device * dev , unsigned long flags )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv ;
int ret = 0 ;
dev_priv = drm_alloc ( sizeof ( drm_radeon_private_t ) , DRM_MEM_DRIVER ) ;
if ( dev_priv = = NULL )
2007-08-25 13:22:43 +04:00
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
memset ( dev_priv , 0 , sizeof ( drm_radeon_private_t ) ) ;
dev - > dev_private = ( void * ) dev_priv ;
dev_priv - > flags = flags ;
2006-09-21 22:25:09 +04:00
switch ( flags & RADEON_FAMILY_MASK ) {
2005-04-17 02:20:36 +04:00
case CHIP_R100 :
case CHIP_RV200 :
case CHIP_R200 :
case CHIP_R300 :
2006-08-19 11:43:52 +04:00
case CHIP_R350 :
2005-08-16 14:43:16 +04:00
case CHIP_R420 :
2006-08-19 11:43:52 +04:00
case CHIP_RV410 :
2008-02-07 08:01:05 +03:00
case CHIP_RV515 :
case CHIP_R520 :
case CHIP_RV570 :
case CHIP_R580 :
2006-09-21 22:25:09 +04:00
dev_priv - > flags | = RADEON_HAS_HIERZ ;
2005-04-17 02:20:36 +04:00
break ;
default :
2005-09-25 08:28:13 +04:00
/* all other chips have no hierarchical z buffer */
2005-04-17 02:20:36 +04:00
break ;
}
2005-08-16 14:43:16 +04:00
if ( drm_device_is_agp ( dev ) )
2006-09-21 22:25:09 +04:00
dev_priv - > flags | = RADEON_IS_AGP ;
2006-08-19 11:43:52 +04:00
else if ( drm_device_is_pcie ( dev ) )
2006-09-21 22:25:09 +04:00
dev_priv - > flags | = RADEON_IS_PCIE ;
2006-08-19 11:43:52 +04:00
else
2006-09-21 22:25:09 +04:00
dev_priv - > flags | = RADEON_IS_PCI ;
2005-09-11 14:28:11 +04:00
2005-08-16 14:43:16 +04:00
DRM_DEBUG ( " %s card detected \n " ,
2006-09-21 22:25:09 +04:00
( ( dev_priv - > flags & RADEON_IS_AGP ) ? " AGP " : ( ( ( dev_priv - > flags & RADEON_IS_PCIE ) ? " PCIE " : " PCI " ) ) ) ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
2005-11-10 14:16:34 +03:00
/* Create mappings for registers and framebuffer so userland doesn't necessarily
* have to find them .
*/
int radeon_driver_firstopen ( struct drm_device * dev )
2005-07-10 13:27:04 +04:00
{
int ret ;
drm_local_map_t * map ;
drm_radeon_private_t * dev_priv = dev - > dev_private ;
2007-05-08 09:19:23 +04:00
dev_priv - > gart_info . table_size = RADEON_PCIGART_TABLE_SIZE ;
2005-07-10 13:27:04 +04:00
ret = drm_addmap ( dev , drm_get_resource_start ( dev , 2 ) ,
drm_get_resource_len ( dev , 2 ) , _DRM_REGISTERS ,
_DRM_READ_ONLY , & dev_priv - > mmio ) ;
if ( ret ! = 0 )
return ret ;
2007-11-05 03:45:27 +03:00
dev_priv - > fb_aper_offset = drm_get_resource_start ( dev , 0 ) ;
ret = drm_addmap ( dev , dev_priv - > fb_aper_offset ,
2005-07-10 13:27:04 +04:00
drm_get_resource_len ( dev , 0 ) , _DRM_FRAME_BUFFER ,
_DRM_WRITE_COMBINING , & map ) ;
if ( ret ! = 0 )
return ret ;
return 0 ;
}
2005-11-10 14:16:34 +03:00
int radeon_driver_unload ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
drm_radeon_private_t * dev_priv = dev - > dev_private ;
DRM_DEBUG ( " \n " ) ;
drm_free ( dev_priv , sizeof ( * dev_priv ) , DRM_MEM_DRIVER ) ;
dev - > dev_private = NULL ;
return 0 ;
}