Patch by Euan Kirkhope:

* option for PIO engine instead of DMA (for dodgy X700s)
* misc RAM config changes inline with x.org codebase


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20273 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-03-01 09:28:25 +00:00
parent 300bef5821
commit a85694c375
17 changed files with 716 additions and 235 deletions
@@ -20,7 +20,8 @@
#include "ddc.h" #include "ddc.h"
// magic code for ioctls // magic code for ioctls
#define RADEON_PRIVATE_DATA_MAGIC 'TKRA' // changed from TKRA to TKR1 for RADEON_WAITFORFIFO ioctl
#define RADEON_PRIVATE_DATA_MAGIC 'TKR1'
#define MAX_RADEON_DEVICE_NAME_LENGTH MAXPATHLEN #define MAX_RADEON_DEVICE_NAME_LENGTH MAXPATHLEN
@@ -35,6 +36,7 @@ enum {
RADEON_FREE_MEM, RADEON_FREE_MEM,
RADEON_WAITFORIDLE, RADEON_WAITFORIDLE,
RADEON_WAITFORFIFO,
RADEON_RESETENGINE, RADEON_RESETENGINE,
RADEON_VIPREAD, RADEON_VIPREAD,
RADEON_VIPWRITE, RADEON_VIPWRITE,
@@ -396,6 +398,7 @@ typedef struct {
typedef struct { typedef struct {
// filled out by kernel // filled out by kernel
CP_info cp; // info concerning command processor CP_info cp; // info concerning command processor
bool acc_dma; // prevent use of dma engine
// set by accelerant // set by accelerant
struct { struct {
@@ -499,6 +502,12 @@ typedef struct {
bool keep_lock; // keep lock after engine is idle bool keep_lock; // keep lock after engine is idle
} radeon_wait_for_idle; } radeon_wait_for_idle;
// wait for idle
typedef struct {
uint32 magic;
int entries; // keep lock after engine is idle
} radeon_wait_for_fifo;
// read VIP register // read VIP register
typedef struct { typedef struct {
uint32 magic; uint32 magic;
+1 -1
View File
@@ -8,4 +8,4 @@
*/ */
// current version // current version
#define RADEON_DRIVER_VERSION "Version: 5.1.2.1" #define RADEON_DRIVER_VERSION "Version: 5.1.3.1"
+267 -42
View File
@@ -13,6 +13,7 @@
#include "generic.h" #include "generic.h"
#include "3d_regs.h" #include "3d_regs.h"
#include "2d_regs.h" #include "2d_regs.h"
#include "radeon_regs.h"
#include "mmio.h" #include "mmio.h"
#include "CP.h" #include "CP.h"
@@ -21,7 +22,7 @@
// et - ignored // et - ignored
// list - list of rectangles // list - list of rectangles
// count - number of rectangles // count - number of rectangles
void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count) void SCREEN_TO_SCREEN_BLIT_DMA(engine_token *et, blit_params *list, uint32 count)
{ {
virtual_card *vc = ai->vc; virtual_card *vc = ai->vc;
@@ -55,13 +56,63 @@ void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count)
++ai->si->engine.count; ++ai->si->engine.count;
} }
#define SRC_DSTCOLOR 0x00030000
#define DP_SRC_RECT 0x00000200
void SCREEN_TO_SCREEN_BLIT_PIO(engine_token *et, blit_params *list, uint32 count)
{
int xdir;
int ydir;
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
Radeon_WaitForFifo ( ai , 1 );
// Setup for Screen to screen blit
OUTREG(ai->regs, RADEON_DP_GUI_MASTER_CNTL, (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT
| RADEON_GMC_BRUSH_NONE
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_S
| RADEON_DP_SRC_SOURCE_MEMORY
| RADEON_GMC_SRC_PITCH_OFFSET_CNTL));
for( ; count > 0; --count, ++list ) {
// make sure there is space in the FIFO for 4 register writes
Radeon_WaitForFifo ( ai , 4 );
xdir = ((list->src_left < list->dest_left) && (list->src_top == list->dest_top)) ? -1 : 1;
ydir = (list->src_top < list->dest_top) ? -1 : 1;
if (xdir < 0) list->src_left += list->width , list->dest_left += list->width ;
if (ydir < 0) list->src_top += list->height , list->dest_top += list->height ;
OUTREG(ai->regs, RADEON_DP_CNTL, ((xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0)
| (ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
// Tell the engine where the source data resides.
OUTREG( ai->regs, RADEON_SRC_Y_X, (list->src_top << 16 ) | list->src_left);
OUTREG( ai->regs, RADEON_DST_Y_X, (list->dest_top << 16 ) | list->dest_left);
// this is the blt initiator.
OUTREG( ai->regs, RADEON_DST_HEIGHT_WIDTH, ((list->height + 1) << 16 ) | (list->width + 1));
}
++ai->si->engine.count;
et = et;
}
// fill rectangles on screen // fill rectangles on screen
// et - ignored // et - ignored
// colorIndex - fill colour // colorIndex - fill colour
// list - list of rectangles // list - list of rectangles
// count - number of rectangles // count - number of rectangles
void FILL_RECTANGLE(engine_token *et, uint32 colorIndex, void FILL_RECTANGLE_DMA(engine_token *et, uint32 colorIndex,
fill_rect_params *list, uint32 count) fill_rect_params *list, uint32 count)
{ {
virtual_card *vc = ai->vc; virtual_card *vc = ai->vc;
@@ -98,11 +149,47 @@ void FILL_RECTANGLE(engine_token *et, uint32 colorIndex,
} }
// fill rectangles on screen
// et - ignored
// colorIndex - fill colour
// list - list of rectangles
// count - number of rectangles
#define BRUSH_SOLIDCOLOR 0x00000d00
void FILL_RECTANGLE_PIO(engine_token *et, uint32 colorIndex, fill_rect_params *list, uint32 count)
{
virtual_card *vc = ai->vc;
SHOW_FLOW( 4, "colorIndex", colorIndex);
Radeon_WaitForFifo(ai, 3);
OUTREG(ai->regs, RADEON_DP_GUI_MASTER_CNTL, ((vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_P));
// Set brush colour
OUTREG(ai->regs, RADEON_DP_BRUSH_FRGD_CLR, colorIndex);
OUTREG(ai->regs, RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
for( ; count > 0; --count, ++list )
{
Radeon_WaitForFifo(ai, 2);
OUTREG(ai->regs, RADEON_DST_Y_X, (list->top << 16) | list->left);
OUTREG(ai->regs, RADEON_DST_WIDTH_HEIGHT, ((list->right - list->left + 1) << 16) | (list->bottom - list->top + 1));
}
++ai->si->engine.count;
et = et;
}
// invert rectangle on screen // invert rectangle on screen
// et - ignored // et - ignored
// list - list of rectangles // list - list of rectangles
// count - number of rectangles // count - number of rectangles
void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count) void INVERT_RECTANGLE_DMA(engine_token *et, fill_rect_params *list, uint32 count)
{ {
virtual_card *vc = ai->vc; virtual_card *vc = ai->vc;
@@ -151,12 +238,41 @@ void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count)
++ai->si->engine.count; ++ai->si->engine.count;
} }
void INVERT_RECTANGLE_PIO(engine_token *et, fill_rect_params *list, uint32 count)
{
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
Radeon_WaitForFifo(ai, 3);
OUTREG(ai->regs, RADEON_DP_GUI_MASTER_CNTL, ((vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_BRUSH_NONE
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_Dn
| RADEON_DP_SRC_SOURCE_MEMORY));
OUTREG(ai->regs, RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
for( ; count > 0; --count, ++list )
{
Radeon_WaitForFifo(ai, 2);
OUTREG(ai->regs, RADEON_DST_Y_X, (list->top << 16) | list->left);
OUTREG(ai->regs, RADEON_DST_WIDTH_HEIGHT, ((list->right - list->left + 1) << 16) | (list->bottom - list->top + 1));
}
++ai->si->engine.count;
et = et;
}
// fill horizontal spans on screen // fill horizontal spans on screen
// et - ignored // et - ignored
// colorIndex - fill colour // colorIndex - fill colour
// list - list of spans // list - list of spans
// count - number of spans // count - number of spans
void FILL_SPAN(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count) void FILL_SPAN_DMA(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
{ {
virtual_card *vc = ai->vc; virtual_card *vc = ai->vc;
@@ -196,72 +312,181 @@ void FILL_SPAN(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
} }
// fill horizontal spans on screen
// et - ignored
// colorIndex - fill colour
// list - list of spans
// count - number of spans
void FILL_SPAN_PIO(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count)
{
virtual_card *vc = ai->vc;
//int offset = 0;
uint16 y, x, width;
SHOW_FLOW0( 4, "" );
Radeon_WaitForFifo( ai , 1);
OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL, 0
| RADEON_GMC_BRUSH_SOLID_COLOR
| (vc->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_P);
if ( ai->si->asic >= rt_rv200 ) {
Radeon_WaitForFifo( ai , 1);
OUTREG( ai->regs, RADEON_DST_LINE_PATCOUNT, 0x55 << RADEON_BRES_CNTL_SHIFT);
}
Radeon_WaitForFifo( ai , 1);
OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, colorIndex);
for( ; count > 0; --count ) {
Radeon_WaitForFifo( ai , 2);
y = *list++;
x = *list++;
width = *list++ - x + 1;
OUTREG( ai->regs, RADEON_DST_LINE_START, (y << 16) | x);
OUTREG( ai->regs, RADEON_DST_LINE_END, ((y) << 16) | (x + width));
}
++ai->si->engine.count;
et = et;
}
void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count)
{
if ( ai->si->acc_dma )
SCREEN_TO_SCREEN_BLIT_DMA(et,list,count);
else
SCREEN_TO_SCREEN_BLIT_PIO(et,list,count);
}
void FILL_RECTANGLE(engine_token *et, uint32 color, fill_rect_params *list, uint32 count)
{
if ( ai->si->acc_dma )
FILL_RECTANGLE_DMA(et, color, list, count);
else
FILL_RECTANGLE_PIO(et, color, list, count);
}
void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count)
{
if ( ai->si->acc_dma )
INVERT_RECTANGLE_DMA(et, list, count);
else
INVERT_RECTANGLE_PIO(et, list, count);
}
void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count)
{
if ( ai->si->acc_dma )
FILL_SPAN_DMA(et, color, list, count);
else
FILL_SPAN_PIO(et, color, list, count);
}
// prepare 2D acceleration // prepare 2D acceleration
void Radeon_Init2D( accelerator_info *ai ) void Radeon_Init2D( accelerator_info *ai )
{ {
SHOW_FLOW0( 3, "" ); SHOW_FLOW0( 3, "" );
START_IB();
// forget about 3D // forget about 3D
WRITE_IB_REG( RADEON_RB3D_CNTL, 0 ); if ( ai->si->acc_dma ) {
START_IB();
SUBMIT_IB(); WRITE_IB_REG( RADEON_RB3D_CNTL, 0 );
SUBMIT_IB();
}
else {
OUTREG( ai->regs, RADEON_RB3D_CNTL, 0 );
}
} }
// fill state buffer that sets 2D registers up for accelerated operations // fill state buffer that sets 2D registers up for accelerated operations
void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype ) void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype )
{ {
virtual_card *vc = ai->vc; virtual_card *vc = ai->vc;
uint32 pitch_offset; uint32 pitch_offset;
uint32 *buffer, *buffer_start; uint32 *buffer = NULL, *buffer_start = NULL;
SHOW_FLOW0( 4, "" ); SHOW_FLOW0( 4, "" );
// make sure buffer is not used
Radeon_InvalidateStateBuffer( ai, vc->state_buffer_idx );
buffer = buffer_start = Radeon_GetIndirectBufferPtr( ai, vc->state_buffer_idx );
// set offset of frame buffer and pitch // set offset of frame buffer and pitch
pitch_offset = pitch_offset =
((ai->si->memory[mt_local].virtual_addr_start + vc->fb_offset) >> 10) | ((ai->si->memory[mt_local].virtual_addr_start + vc->fb_offset) >> 10) |
((vc->pitch >> 6) << 22); ((vc->pitch >> 6) << 22);
WRITE_IB_REG( RADEON_DEFAULT_OFFSET, pitch_offset );
WRITE_IB_REG( RADEON_DST_PITCH_OFFSET, pitch_offset );
WRITE_IB_REG( RADEON_SRC_PITCH_OFFSET, pitch_offset );
// no siccors if ( ai->si->acc_dma ) {
WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT, // make sure buffer is not used
(RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX)); Radeon_InvalidateStateBuffer( ai, vc->state_buffer_idx );
buffer = buffer_start = Radeon_GetIndirectBufferPtr( ai, vc->state_buffer_idx );
// setup general flags - perhaps this is not needed as all WRITE_IB_REG( RADEON_DEFAULT_OFFSET, pitch_offset );
// 2D commands contain this register WRITE_IB_REG( RADEON_DST_PITCH_OFFSET, pitch_offset );
WRITE_IB_REG( RADEON_DP_GUI_MASTER_CNTL, WRITE_IB_REG( RADEON_SRC_PITCH_OFFSET, pitch_offset );
(datatype << RADEON_GMC_DST_DATATYPE_SHIFT) // no sissors
| RADEON_GMC_CLR_CMP_CNTL_DIS WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT,
(RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX));
| RADEON_GMC_BRUSH_SOLID_COLOR // general fluff
| RADEON_GMC_SRC_DATATYPE_COLOR WRITE_IB_REG( RADEON_DP_GUI_MASTER_CNTL,
(datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_CLR_CMP_CNTL_DIS
| RADEON_ROP3_P | RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_GMC_WR_MSK_DIS );
| RADEON_ROP3_P
| RADEON_DP_SRC_SOURCE_MEMORY
| RADEON_GMC_WR_MSK_DIS );
// most of this init is probably not nessacary // most of this init is probably not necessary
// as we neither draw lines nor use brushes // as we neither draw lines nor use brushes
WRITE_IB_REG( RADEON_DST_LINE_START, 0); WRITE_IB_REG( RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
WRITE_IB_REG( RADEON_DST_LINE_END, 0); WRITE_IB_REG( RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
WRITE_IB_REG( RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); WRITE_IB_REG( RADEON_DP_SRC_FRGD_CLR, 0xffffffff);
WRITE_IB_REG( RADEON_DP_BRUSH_BKGD_CLR, 0x00000000); WRITE_IB_REG( RADEON_DP_SRC_BKGD_CLR, 0x00000000);
WRITE_IB_REG( RADEON_DP_SRC_FRGD_CLR, 0xffffffff); WRITE_IB_REG( RADEON_DP_WRITE_MASK, 0xffffffff);
WRITE_IB_REG( RADEON_DP_SRC_BKGD_CLR, 0x00000000);
WRITE_IB_REG( RADEON_DP_WRITE_MASK, 0xffffffff);
// this is required
vc->state_buffer_size = buffer - buffer_start;
vc->state_buffer_size = buffer - buffer_start; } else {
Radeon_WaitForFifo( ai, 10 );
OUTREG( ai->regs, RADEON_DEFAULT_OFFSET, pitch_offset );
OUTREG( ai->regs, RADEON_DST_PITCH_OFFSET, pitch_offset );
OUTREG( ai->regs, RADEON_SRC_PITCH_OFFSET, pitch_offset );
// no sissors
OUTREG( ai->regs, RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
| RADEON_DEFAULT_SC_BOTTOM_MAX));
// general fluff
OUTREG( ai->regs, RADEON_DP_GUI_MASTER_CNTL,
(datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
| RADEON_GMC_CLR_CMP_CNTL_DIS
| RADEON_GMC_BRUSH_SOLID_COLOR
| RADEON_GMC_SRC_DATATYPE_COLOR
| RADEON_ROP3_P
| RADEON_DP_SRC_SOURCE_MEMORY
| RADEON_GMC_WR_MSK_DIS );
// most of this init is probably not necessary
// as we neither draw lines nor use brushes
OUTREG( ai->regs, RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
OUTREG( ai->regs, RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
OUTREG( ai->regs, RADEON_DP_SRC_FRGD_CLR, 0xffffffff);
OUTREG( ai->regs, RADEON_DP_SRC_BKGD_CLR, 0x00000000);
OUTREG( ai->regs, RADEON_DP_WRITE_MASK, 0xffffffff);
}
ai->si->active_vc = vc->id; ai->si->active_vc = vc->id;
} }
@@ -65,21 +65,30 @@ static void writeSyncToken( accelerator_info *ai )
if( ai->si->engine.count == ai->si->engine.written ) if( ai->si->engine.count == ai->si->engine.written )
return; return;
START_IB(); if( ai->si->acc_dma ) {
START_IB();
// flush pending data // flush pending data
WRITE_IB_REG( RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL ); WRITE_IB_REG( RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL );
// make sure commands are finished // make sure commands are finished
WRITE_IB_REG( RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | WRITE_IB_REG( RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN |
RADEON_WAIT_3D_IDLECLEAN | RADEON_WAIT_HOST_IDLECLEAN ); RADEON_WAIT_3D_IDLECLEAN | RADEON_WAIT_HOST_IDLECLEAN );
// write scratch register // write scratch register
WRITE_IB_REG( RADEON_SCRATCH_REG0, ai->si->engine.count ); WRITE_IB_REG( RADEON_SCRATCH_REG0, ai->si->engine.count );
ai->si->engine.written = ai->si->engine.count; ai->si->engine.written = ai->si->engine.count;
SUBMIT_IB(); SUBMIT_IB();
} else {
Radeon_WaitForFifo( ai, 2 );
OUTREG( ai->regs, RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
OUTREG( ai->regs, RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN |
RADEON_WAIT_3D_IDLECLEAN |
RADEON_WAIT_HOST_IDLECLEAN);
ai->si->engine.written = ai->si->engine.count;
}
} }
// public function: acquire engine for future use // public function: acquire engine for future use
@@ -178,6 +187,13 @@ status_t SYNC_TO_TOKEN( sync_token *st )
SHOW_FLOW0( 4, "" ); SHOW_FLOW0( 4, "" );
if ( !ai->si->acc_dma )
{
Radeon_WaitForFifo( ai, 64 );
Radeon_WaitForIdle( ai, false );
return B_OK;
}
start_time = system_time(); start_time = system_time();
while( 1 ) { while( 1 ) {
@@ -111,7 +111,8 @@ err:
static void uninit_common( void ) static void uninit_common( void )
{ {
if( !ai->accelerant_is_clone ) { if( !ai->accelerant_is_clone ) {
Radeon_FreeVirtualCardStateBuffer( ai ); if ( ai->si->acc_dma )
Radeon_FreeVirtualCardStateBuffer( ai );
// the last accelerant should must wait for the card to become quite, // the last accelerant should must wait for the card to become quite,
// else some nasty command could lunger in some FIFO // else some nasty command could lunger in some FIFO
@@ -200,7 +201,8 @@ status_t INIT_ACCELERANT( int the_fd )
// mark engine as having no state // mark engine as having no state
//si->cp.active_state_buffer = -1; //si->cp.active_state_buffer = -1;
Radeon_AllocateVirtualCardStateBuffer( ai ); if ( ai->si->acc_dma )
Radeon_AllocateVirtualCardStateBuffer( ai );
// everything else is initialized upon set_display_mode // everything else is initialized upon set_display_mode
return B_OK; return B_OK;
@@ -23,6 +23,27 @@ status_t Radeon_WaitForIdle( accelerator_info *ai, bool keep_lock )
return ioctl( ai->fd, RADEON_WAITFORIDLE, &wfi, sizeof( wfi )); return ioctl( ai->fd, RADEON_WAITFORIDLE, &wfi, sizeof( wfi ));
} }
// wait until "entries" FIFO entries are empty
// lock must be hold
status_t Radeon_WaitForFifo( accelerator_info *ai, int entries )
{
while( 1 ) {
bigtime_t start_time = system_time();
do {
int slots = INREG( ai->regs, RADEON_RBBM_STATUS ) & RADEON_RBBM_FIFOCNT_MASK;
if ( slots >= entries )
return B_OK;
snooze( 1 );
} while( system_time() - start_time < 1000000 );
Radeon_ResetEngine( ai );
}
return B_ERROR;
}
void Radeon_ResetEngine( accelerator_info *ai ) void Radeon_ResetEngine( accelerator_info *ai )
{ {
+12
View File
@@ -49,6 +49,18 @@ void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count);
void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count); void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count);
void SCREEN_TO_SCREEN_BLIT_DMA(engine_token *et, blit_params *list, uint32 count);
void FILL_RECTANGLE_DMA(engine_token *et, uint32 color, fill_rect_params *list, uint32 count);
void INVERT_RECTANGLE_DMA(engine_token *et, fill_rect_params *list, uint32 count);
void FILL_SPAN_DMA(engine_token *et, uint32 color, uint16 *list, uint32 count);
void SCREEN_TO_SCREEN_BLIT_PIO(engine_token *et, blit_params *list, uint32 count);
void FILL_RECTANGLE_PIO(engine_token *et, uint32 color, fill_rect_params *list, uint32 count);
void INVERT_RECTANGLE_PIO(engine_token *et, fill_rect_params *list, uint32 count);
void FILL_SPAN_PIO(engine_token *et, uint32 color, uint16 *list, uint32 count);
uint32 OVERLAY_COUNT(const display_mode *dm); uint32 OVERLAY_COUNT(const display_mode *dm);
const uint32 *OVERLAY_SUPPORTED_SPACES(const display_mode *dm); const uint32 *OVERLAY_SUPPORTED_SPACES(const display_mode *dm);
uint32 OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space); uint32 OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space);
+16 -6
View File
@@ -973,17 +973,27 @@ static void Radeon_ReplaceOverlayBuffer(
shared_info *si = ai->si; shared_info *si = ai->si;
uint32 offset; uint32 offset;
START_IB(); if ( ai->si->acc_dma )
{
START_IB();
offset = si->pending_overlay.on->mem_offset + si->active_overlay.rel_offset; offset = si->pending_overlay.on->mem_offset + si->active_overlay.rel_offset;
WRITE_IB_REG( RADEON_OV0_VID_BUF0_BASE_ADRS, offset); WRITE_IB_REG( RADEON_OV0_VID_BUF0_BASE_ADRS, offset);
si->overlay_mgr.auto_flip_reg ^= RADEON_OV0_SOFT_EOF_TOGGLE; si->overlay_mgr.auto_flip_reg ^= RADEON_OV0_SOFT_EOF_TOGGLE;
WRITE_IB_REG( RADEON_OV0_AUTO_FLIP_CNTRL, si->overlay_mgr.auto_flip_reg ); WRITE_IB_REG( RADEON_OV0_AUTO_FLIP_CNTRL, si->overlay_mgr.auto_flip_reg );
SUBMIT_IB(); SUBMIT_IB();
} else {
Radeon_WaitForFifo( ai, 2 );
offset = si->pending_overlay.on->mem_offset + si->active_overlay.rel_offset;
OUTREG( ai->regs, RADEON_OV0_VID_BUF0_BASE_ADRS, offset);
si->overlay_mgr.auto_flip_reg ^= RADEON_OV0_SOFT_EOF_TOGGLE;
OUTREG( ai->regs, RADEON_OV0_AUTO_FLIP_CNTRL, si->overlay_mgr.auto_flip_reg );
}
ai->si->active_overlay.on = ai->si->pending_overlay.on; ai->si->active_overlay.on = ai->si->pending_overlay.on;
#endif #endif
} }
+49 -23
View File
@@ -13,33 +13,41 @@
#include "GlobalData.h" #include "GlobalData.h"
#include "dac_regs.h" #include "dac_regs.h"
#include "mmio.h"
#include "CP.h" #include "CP.h"
#include "generic.h" #include "generic.h"
// Radeon's DACs share same public registers, this function
// selects the DAC you'll talk to
#define selectPalette( crtc_idx ) \
WRITE_IB_REG( RADEON_DAC_CNTL2, \
(crtc_idx == 0 ? 0 : RADEON_DAC2_PALETTE_ACC_CTL) | \
(ai->si->dac_cntl2 & ~RADEON_DAC2_PALETTE_ACC_CTL) );
// set standard colour palette (needed for non-palette modes) // set standard colour palette (needed for non-palette modes)
void Radeon_InitPalette( void Radeon_InitPalette(
accelerator_info *ai, int crtc_idx ) accelerator_info *ai, int crtc_idx )
{ {
int i; int i;
START_IB(); if ( ai->si->acc_dma ) {
START_IB();
selectPalette( crtc_idx ); WRITE_IB_REG( RADEON_DAC_CNTL2,
(crtc_idx == 0 ? 0 : RADEON_DAC2_PALETTE_ACC_CTL) |
(ai->si->dac_cntl2 & ~RADEON_DAC2_PALETTE_ACC_CTL) );
WRITE_IB_REG( RADEON_PALETTE_INDEX, 0 ); WRITE_IB_REG( RADEON_PALETTE_INDEX, 0 );
for( i = 0; i < 256; ++i ) for( i = 0; i < 256; ++i )
WRITE_IB_REG( RADEON_PALETTE_DATA, (i << 16) | (i << 8) | i ); WRITE_IB_REG( RADEON_PALETTE_DATA, (i << 16) | (i << 8) | i );
SUBMIT_IB(); SUBMIT_IB();
} else {
Radeon_WaitForFifo ( ai , 1 );
OUTREG( ai->regs, RADEON_DAC_CNTL2,
(crtc_idx == 0 ? 0 : RADEON_DAC2_PALETTE_ACC_CTL) |
(ai->si->dac_cntl2 & ~RADEON_DAC2_PALETTE_ACC_CTL) );
OUTREG( ai->regs, RADEON_PALETTE_INDEX, 0 );
for( i = 0; i < 256; ++i ) {
Radeon_WaitForFifo ( ai , 1 ); // TODO FIXME good god this is gonna be slow...
OUTREG( ai->regs, RADEON_PALETTE_DATA, (i << 16) | (i << 8) | i );
}
}
} }
static void setPalette( static void setPalette(
@@ -75,17 +83,35 @@ static void setPalette(
{ {
uint i; uint i;
START_IB(); if ( ai->si->acc_dma ) {
START_IB();
selectPalette( crtc_idx ); WRITE_IB_REG( RADEON_DAC_CNTL2,
(crtc_idx == 0 ? 0 : RADEON_DAC2_PALETTE_ACC_CTL) |
(ai->si->dac_cntl2 & ~RADEON_DAC2_PALETTE_ACC_CTL) );
WRITE_IB_REG( RADEON_PALETTE_INDEX, first ); WRITE_IB_REG( RADEON_PALETTE_INDEX, first );
for( i = 0; i < count; ++i, color_data += 3 ) for( i = 0; i < count; ++i, color_data += 3 )
WRITE_IB_REG( RADEON_PALETTE_DATA, WRITE_IB_REG( RADEON_PALETTE_DATA,
((uint32)color_data[0] << 16) | ((uint32)color_data[0] << 16) |
((uint32)color_data[1] << 8) | ((uint32)color_data[1] << 8) |
color_data[2] ); color_data[2] );
SUBMIT_IB(); SUBMIT_IB();
} else {
Radeon_WaitForFifo ( ai , 1 );
OUTREG( ai->regs, RADEON_DAC_CNTL2,
(crtc_idx == 0 ? 0 : RADEON_DAC2_PALETTE_ACC_CTL) |
(ai->si->dac_cntl2 & ~RADEON_DAC2_PALETTE_ACC_CTL) );
OUTREG( ai->regs, RADEON_PALETTE_INDEX, first );
for( i = 0; i < count; ++i, color_data += 3 ) {
Radeon_WaitForFifo ( ai , 1 ); // TODO FIXME good god this is gonna be slow...
OUTREG( ai->regs, RADEON_PALETTE_DATA,
((uint32)color_data[0] << 16) |
((uint32)color_data[1] << 8) |
color_data[2] );
}
}
} }
@@ -115,6 +115,7 @@ void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype );
// driver_wrapper.c // driver_wrapper.c
status_t Radeon_WaitForIdle( accelerator_info *ai, bool keep_lock ); status_t Radeon_WaitForIdle( accelerator_info *ai, bool keep_lock );
status_t Radeon_WaitForFifo( accelerator_info *ai, int entries );
void Radeon_ResetEngine( accelerator_info *ai ); void Radeon_ResetEngine( accelerator_info *ai );
status_t Radeon_VIPRead( accelerator_info *ai, uint channel, uint address, uint32 *data ); status_t Radeon_VIPRead( accelerator_info *ai, uint channel, uint address, uint32 *data );
@@ -227,71 +227,54 @@ void Radeon_ResetEngine( device_info *di )
host_path_cntl = INREG( regs, RADEON_HOST_PATH_CNTL ); host_path_cntl = INREG( regs, RADEON_HOST_PATH_CNTL );
rbbm_soft_reset = INREG( regs, RADEON_RBBM_SOFT_RESET ); rbbm_soft_reset = INREG( regs, RADEON_RBBM_SOFT_RESET );
switch( di->asic ) { OUTREG( regs, RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
case rt_r300:
OUTREG( regs, RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
RADEON_SOFT_RESET_CP |
RADEON_SOFT_RESET_HI |
RADEON_SOFT_RESET_E2 |
RADEON_SOFT_RESET_AIC ));
INREG( regs, RADEON_RBBM_SOFT_RESET);
OUTREG( regs, RADEON_RBBM_SOFT_RESET, 0);
// this bit has no description
OUTREGP( regs, RADEON_RB2D_DSTCACHE_MODE, (1 << 17), ~0 );
break;
default:
OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset |
RADEON_SOFT_RESET_CP | RADEON_SOFT_RESET_CP |
RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_HI |
RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_SE |
RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_RE |
RADEON_SOFT_RESET_PP | RADEON_SOFT_RESET_PP |
RADEON_SOFT_RESET_E2 | RADEON_SOFT_RESET_E2 |
RADEON_SOFT_RESET_RB | RADEON_SOFT_RESET_RB ) );
RADEON_SOFT_RESET_AIC ); INREG( regs, RADEON_RBBM_SOFT_RESET);
INREG( regs, RADEON_RBBM_SOFT_RESET ); OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset &
OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset & ~( RADEON_SOFT_RESET_CP |
~( RADEON_SOFT_RESET_CP | RADEON_SOFT_RESET_HI |
RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE |
RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE |
RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP |
RADEON_SOFT_RESET_PP | RADEON_SOFT_RESET_E2 |
RADEON_SOFT_RESET_E2 | RADEON_SOFT_RESET_RB ) );
RADEON_SOFT_RESET_RB | INREG( regs, RADEON_RBBM_SOFT_RESET);
RADEON_SOFT_RESET_AIC ) );
INREG( regs, RADEON_RBBM_SOFT_RESET );
}
OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET ); OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET );
INREG( regs, RADEON_HOST_PATH_CNTL ); INREG( regs, RADEON_HOST_PATH_CNTL );
OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl ); OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl );
// restore regs
OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
OUTREG( regs, RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
//R300_PLLFix( regs, di->asic );
Radeon_OUTPLL( regs, di->asic, RADEON_MCLK_CNTL, mclk_cntl ); Radeon_OUTPLL( regs, di->asic, RADEON_MCLK_CNTL, mclk_cntl );
OUTREG( regs, RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
//RADEONPllErrataAfterIndex( regs, di->asic ); // drm doesn't do this here!
OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
// reset ring buffer if ( di->acc_dma )
cur_read_ptr = INREG( regs, RADEON_CP_RB_RPTR ); {
OUTREG( regs, RADEON_CP_RB_WPTR, cur_read_ptr ); // reset ring buffer
cur_read_ptr = INREG( regs, RADEON_CP_RB_RPTR );
OUTREG( regs, RADEON_CP_RB_WPTR, cur_read_ptr );
//if( si->cp.ring.head ) { //if( si->cp.ring.head ) {
// during init, there are no feedback data // during init, there are no feedback data
if( si->cp.feedback.mem_handle != 0 ) { if( si->cp.feedback.mem_handle != 0 ) {
*(uint32 *)MEM2CPU( si->cp.feedback.mem_type, si->cp.feedback.head_mem_offset) = *(uint32 *)MEM2CPU( si->cp.feedback.mem_type, si->cp.feedback.head_mem_offset) =
cur_read_ptr; cur_read_ptr;
// *si->cp.ring.head = cur_read_ptr; // *si->cp.ring.head = cur_read_ptr;
si->cp.ring.tail = cur_read_ptr; si->cp.ring.tail = cur_read_ptr;
}
// mark all buffers as being finished
Radeon_DiscardAllIndirectBuffers( di );
} }
++si->engine.count; ++si->engine.count;
// mark all buffers as being finished
Radeon_DiscardAllIndirectBuffers( di );
return; return;
} }
@@ -522,7 +505,7 @@ status_t Radeon_InitCP( device_info *di )
set_sem_owner( di->si->cp.lock.sem, thinfo.team ); set_sem_owner( di->si->cp.lock.sem, thinfo.team );
// init raw CP // init raw CP
loadMicroEngineRAMData( di ); if ( di->acc_dma ) loadMicroEngineRAMData( di );
// do soft-reset // do soft-reset
Radeon_ResetEngine( di ); Radeon_ResetEngine( di );
@@ -536,26 +519,30 @@ status_t Radeon_InitCP( device_info *di )
// reset CP to make disabling active // reset CP to make disabling active
Radeon_ResetEngine( di ); Radeon_ResetEngine( di );
res = initRingBuffer( di, CP_RING_SIZE ); if ( di->acc_dma )
if( res < 0 ) {
goto err4; res = initRingBuffer( di, CP_RING_SIZE );
if( res < 0 )
goto err4;
res = initCPFeedback( di ); res = initCPFeedback( di );
if( res < 0 ) if( res < 0 )
goto err3; goto err3;
res = initIndirectBuffers( di ); res = initIndirectBuffers( di );
if( res < 0 ) if( res < 0 )
goto err2; goto err2;
// tell CP to use BM // tell CP to use BM
Radeon_WaitForIdle( di, false, false ); Radeon_WaitForIdle( di, false, false );
// enable direct and indirect CP bus mastering // enable direct and indirect CP bus mastering
OUTREG( di->regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM ); OUTREG( di->regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM );
// allow bus mastering in general
OUTREGP( di->regs, RADEON_BUS_CNTL, 0, ~RADEON_BUS_MASTER_DIS );
}
// allow bus mastering in general
OUTREGP( di->regs, RADEON_BUS_CNTL, 0, ~RADEON_BUS_MASTER_DIS );
// don't allow mixing of 2D/3D/scratch/wait_until commands // don't allow mixing of 2D/3D/scratch/wait_until commands
// (in fact, this doesn't seem to make any difference as we do a // (in fact, this doesn't seem to make any difference as we do a
@@ -597,9 +584,12 @@ void Radeon_UninitCP( device_info *di )
// read-back for flushing // read-back for flushing
INREG( regs, RADEON_CP_CSQ_CNTL ); INREG( regs, RADEON_CP_CSQ_CNTL );
uninitRingBuffer( di ); if ( di->acc_dma )
uninitCPFeedback( di ); {
uninitIndirectBuffers( di ); uninitRingBuffer( di );
uninitCPFeedback( di );
uninitIndirectBuffers( di );
}
DELETE_BEN( di->si->cp.lock ); DELETE_BEN( di->si->cp.lock );
} }
+121 -37
View File
@@ -536,58 +536,142 @@ static void Radeon_GetFPData( device_info *di )
SHOW_INFO( 2, "pixel_clock=%d", di->fp_info.dot_clock ); SHOW_INFO( 2, "pixel_clock=%d", di->fp_info.dot_clock );
} }
// Depending on card genertation, chipset bugs, etc... the amount of vram
// accessible to the CPU can vary. This function is our best shot at figuring
// it out. Returns a value in KB.
static uint32 RADEON_GetAccessibleVRAM( device_info *di )
{
vuint8 *regs = di->regs;
pci_info *pcii = &(di->pcii);
uint32 aper_size = INREG( regs, RADEON_CONFIG_APER_SIZE );
// Set HDP_APER_CNTL only on cards that are known not to be broken,
// that is has the 2nd generation multifunction PCI interface
if (di->asic == rt_rv280 ||
di->asic == rt_rv350 ||
di->asic == rt_rv380 ||
di->asic == rt_r420 ) {
OUTREGP( regs, RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL,
~RADEON_HDP_APER_CNTL);
SHOW_INFO0( 0, "Generation 2 PCI interface, using max accessible memory");
return aper_size * 2;
}
// Older cards have all sorts of funny issues to deal with. First
// check if it's a multifunction card by reading the PCI config
// header type... Limit those to one aperture size
if (get_pci(PCI_header_type, 1) & 0x80) {
SHOW_INFO0( 0, "Generation 1 PCI interface in multifunction mode"
", accessible memory limited to one aperture\n");
return aper_size;
}
// Single function older card. We read HDP_APER_CNTL to see how the BIOS
// have set it up. We don't write this as it's broken on some ASICs but
// we expect the BIOS to have done the right thing (might be too optimistic...)
if (INREG( regs, RADEON_HOST_PATH_CNTL ) & RADEON_HDP_APER_CNTL )
return aper_size * 2;
return aper_size;
}
// detect amount of graphics memory // detect amount of graphics memory
static void Radeon_DetectRAM( device_info *di ) static void Radeon_DetectRAM( device_info *di )
{ {
vuint8 *regs = di->regs; vuint8 *regs = di->regs;
uint32 accessible, bar_size, tmp = 0;
if( !di->is_igp ) if( di->is_igp ) {
di->local_mem_size = INREG( regs, RADEON_CONFIG_MEMSIZE ) & RADEON_CONFIG_MEMSIZE_MASK;
else {
uint32 tom; uint32 tom;
tom = INREG( regs, RADEON_NB_TOM ); tom = INREG( regs, RADEON_NB_TOM );
di->local_mem_size = ((tom >> 16) + 1 - (tom & 0xffff)) << 16; di->local_mem_size = ((tom >> 16) + 1 - (tom & 0xffff)) << 16;
OUTREG( regs, RADEON_CONFIG_MEMSIZE, di->local_mem_size * 1024);
} else {
di->local_mem_size = INREG( regs, RADEON_CONFIG_MEMSIZE ) & RADEON_CONFIG_MEMSIZE_MASK;
} }
// some production boards of m6 will return 0 if it's 8 MB // some production boards of m6 will return 0 if it's 8 MB
if( di->local_mem_size == 0 ) if( di->local_mem_size == 0 ) {
di->local_mem_size = 8 * 1024 *1024; di->local_mem_size = 8 * 1024 *1024;
OUTREG( regs, RADEON_CONFIG_MEMSIZE, di->local_mem_size);
switch( INREG( regs, RADEON_MEM_SDRAM_MODE_REG ) & RADEON_MEM_CFG_TYPE_MASK ) {
case RADEON_MEM_CFG_SDR:
// SDR SGRAM (2:1)
strcpy(di->ram_type, "SDR SGRAM");
di->ram.ml = 4;
di->ram.MB = 4;
di->ram.Trcd = 1;
di->ram.Trp = 2;
di->ram.Twr = 1;
di->ram.CL = 2;
di->ram.loop_latency = 16;
di->ram.Rloop = 16;
di->ram.Tr2w = 0;
break;
case RADEON_MEM_CFG_DDR:
// DDR SGRAM
strcpy(di->ram_type, "DDR SGRAM");
di->ram.ml = 4;
di->ram.MB = 4;
di->ram.Trcd = 3;
di->ram.Trp = 3;
di->ram.Twr = 2;
di->ram.CL = 3;
di->ram.Tr2w = 1;
di->ram.loop_latency = 16;
di->ram.Rloop = 16;
break;
// only one bit, so there's no default
} }
SHOW_INFO( 1, "%ld MB %s found", di->local_mem_size / 1024 / 1024,
di->ram_type ); // Get usable Vram, after asic bugs, configuration screw ups etc
accessible = RADEON_GetAccessibleVRAM( di );
// Crop it to the size of the PCI BAR
bar_size = di->pcii.u.h0.base_register_sizes[0];
if (bar_size == 0)
bar_size = 0x200000;
if (accessible > bar_size)
accessible = bar_size;
SHOW_INFO( 0, "Detected total video RAM=%ldK, accessible=%ldK (PCI BAR=%ldK)"
, di->local_mem_size/1024, accessible/1024, bar_size/1024);
if (di->local_mem_size > accessible)
di->local_mem_size = accessible;
// detect ram bus width only used by dynamic clocks for now.
tmp = INREG( regs, RADEON_MEM_CNTL );
if (IS_DI_R300_VARIANT) {
tmp &= R300_MEM_NUM_CHANNELS_MASK;
switch (tmp) {
case 0: di->ram.width = 64; break;
case 1: di->ram.width = 128; break;
case 2: di->ram.width = 256; break;
default: di->ram.width = 128; break;
}
} else if ( (di->asic >= rt_rv100) ||
(di->asic >= rt_rs100) ||
(di->asic >= rt_rs200)) {
if (tmp & RV100_HALF_MODE)
di->ram.width = 32;
else
di->ram.width = 64;
} else {
if (tmp & RADEON_MEM_NUM_CHANNELS_MASK)
di->ram.width = 128;
else
di->ram.width = 64;
}
if (di->is_igp || (di->asic >= rt_r300))
{
uint32 mem_type = INREG( regs, RADEON_MEM_SDRAM_MODE_REG ) & RADEON_MEM_CFG_TYPE_MASK;
if ( mem_type == RADEON_MEM_CFG_SDR) {
// SDR SGRAM (2:1)
strcpy(di->ram_type, "SDR SGRAM");
di->ram.ml = 4;
di->ram.MB = 4;
di->ram.Trcd = 1;
di->ram.Trp = 2;
di->ram.Twr = 1;
di->ram.CL = 2;
di->ram.loop_latency = 16;
di->ram.Rloop = 16;
di->ram.Tr2w = 0;
} else { // RADEON_MEM_CFG_DDR
// DDR SGRAM
strcpy(di->ram_type, "DDR SGRAM");
di->ram.ml = 4;
di->ram.MB = 4;
di->ram.Trcd = 3;
di->ram.Trp = 3;
di->ram.Twr = 2;
di->ram.CL = 3;
di->ram.Tr2w = 1;
di->ram.loop_latency = 16;
di->ram.Rloop = 16;
}
}
SHOW_INFO( 1, "%ld MB %s found on %d wide bus",
di->local_mem_size / 1024 / 1024, di->ram_type, di->ram.width);
/* if( di->local_mem_size > 64 * 1024 * 1024 ) { /* if( di->local_mem_size > 64 * 1024 * 1024 ) {
di->local_mem_size = 64 * 1024 * 1024; di->local_mem_size = 64 * 1024 * 1024;
@@ -592,6 +592,60 @@ static bool probeDevice( device_info *di )
} }
// disable 2d DMA engine for chips that don't work with our
// dma code (yet). I would have used asic type, but R410s are
// treated same asic as r420s in code, and the AGP x800 works fine.
switch ( device->device_id )
{
// rv370
case DEVICE_ID_RADEON_5b60:
case DEVICE_ID_RADEON_5b62:
case DEVICE_ID_RADEON_5b64:
case DEVICE_ID_RADEON_5b65:
case DEVICE_ID_RADEON_5460:
case DEVICE_ID_RADEON_5464:
// rv380
case DEVICE_ID_RADEON_3e50:
case DEVICE_ID_RADEON_3e54:
case DEVICE_ID_RADEON_3150:
case DEVICE_ID_RADEON_3154:
case DEVICE_ID_RADEON_5462:
// rv410
case DEVICE_ID_RADEON_5e48:
case DEVICE_ID_RADEON_564a:
case DEVICE_ID_RADEON_564b:
case DEVICE_ID_RADEON_564f:
case DEVICE_ID_RADEON_5652:
case DEVICE_ID_RADEON_5653:
case DEVICE_ID_RADEON_5e4b:
case DEVICE_ID_RADEON_5e4a:
case DEVICE_ID_RADEON_5e4d:
case DEVICE_ID_RADEON_5e4c:
case DEVICE_ID_RADEON_5e4f:
// rs400
case DEVICE_ID_RS400_5a41:
case DEVICE_ID_RS400_5a42:
// rs410
case DEVICE_ID_RS410_5a61:
case DEVICE_ID_RS410_5a62:
// rs480
case DEVICE_ID_RS480_5954:
case DEVICE_ID_RS480_5955:
case DEVICE_ID_RS482_5974:
case DEVICE_ID_RS482_5975:
di->acc_dma = false;
break;
default:
di->acc_dma = true;
break;
}
if( Radeon_MapBIOS( &di->pcii, &di->rom ) != B_OK ) if( Radeon_MapBIOS( &di->pcii, &di->rom ) != B_OK )
// give up checking this device - no BIOS, no fun // give up checking this device - no BIOS, no fun
return false; return false;
@@ -273,6 +273,16 @@ static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len )
result = B_OK; result = B_OK;
} break; } break;
case RADEON_WAITFORFIFO: {
radeon_wait_for_fifo *wff = (radeon_wait_for_fifo *)buf;
if( wff->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
Radeon_WaitForFifo( di, wff->entries );
result = B_OK;
} break;
case RADEON_RESETENGINE: { case RADEON_RESETENGINE: {
radeon_no_arg *na = (radeon_no_arg *)buf; radeon_no_arg *na = (radeon_no_arg *)buf;
@@ -250,6 +250,7 @@ status_t Radeon_FirstOpen( device_info *di )
si->is_atombios = di->is_atombios; si->is_atombios = di->is_atombios;
si->is_mobility = di->is_mobility; si->is_mobility = di->is_mobility;
si->panel_pwr_delay = di->si->panel_pwr_delay; si->panel_pwr_delay = di->si->panel_pwr_delay;
si->acc_dma = di->acc_dma;
// detecting theatre channel in kernel would lead to code duplication, // detecting theatre channel in kernel would lead to code duplication,
@@ -359,14 +360,21 @@ status_t Radeon_FirstOpen( device_info *di )
if( di->asic == rt_rs100 || di->asic == rt_rs200 || di->asic == rt_rs300) if( di->asic == rt_rs100 || di->asic == rt_rs200 || di->asic == rt_rs300)
Radeon_Fix_AGP(); Radeon_Fix_AGP();
// time to init Command Processor if ( di->acc_dma )
result = Radeon_InitCP( di ); {
if( result != B_OK ) // time to init Command Processor
goto err; result = Radeon_InitCP( di );
if( result != B_OK )
goto err;
result = Radeon_InitDMA( di ); result = Radeon_InitDMA( di );
if( result != B_OK ) if( result != B_OK )
goto err0; goto err0;
}
else
{
SHOW_INFO0( 0, "DMA is diabled using PIO mode");
}
// mem_alloc( di->local_memmgr, 0x100000, (void *)-1, &dma_block, &dma_offset ); // mem_alloc( di->local_memmgr, 0x100000, (void *)-1, &dma_block, &dma_offset );
/* dma_offset = 15 * 1024 * 1024; /* dma_offset = 15 * 1024 * 1024;
@@ -402,7 +410,8 @@ err8:
// during tests) // during tests)
void Radeon_LastClose( device_info *di ) void Radeon_LastClose( device_info *di )
{ {
Radeon_UninitCP( di ); if ( di->acc_dma )
Radeon_UninitCP( di );
// M6 fix - unfortunately, the device is never closed by app_server, // M6 fix - unfortunately, the device is never closed by app_server,
// not even before reboot // not even before reboot
@@ -39,10 +39,21 @@ static uint32 getTopOfRam()
static void Radeon_SetupMCAddresses_Direct( device_info *di ) static void Radeon_SetupMCAddresses_Direct( device_info *di )
{ {
shared_info *si = di->si; shared_info *si = di->si;
uint32 mc_fb_location;
uint32 aper0 = INREG( di->regs, RADEON_CONFIG_APER_0_BASE );
// bug in asics mean memory must be aligned to memory size...
if ( IS_DI_R300_VARIANT || di->asic == rt_rv280 ) {
aper0 &= ~( di->local_mem_size - 1 );
}
mc_fb_location = ( aper0 >> 16 ) ||
(aper0 + di->local_mem_size - 1 ) & 0xffff0000;
// set address range of video memory; // set address range of video memory;
// use the same addresses the CPU sees // use the same addresses the CPU sees
si->memory[mt_local].virtual_addr_start = (uint32)si->framebuffer_pci; si->memory[mt_local].virtual_addr_start = mc_fb_location;
si->memory[mt_local].virtual_size = di->local_mem_size; si->memory[mt_local].virtual_size = di->local_mem_size;
// PCI GART has no corresponding CPU address space, so we must find an unused // PCI GART has no corresponding CPU address space, so we must find an unused
@@ -149,6 +160,10 @@ void Radeon_InitMemController( device_info *di )
//si->nonlocal_mem = di->DMABuffer.ptr; //si->nonlocal_mem = di->DMABuffer.ptr;
// Turn on PCI GART
OUTREGP( regs, RADEON_AIC_CNTL, RADEON_PCIGART_TRANSLATE_EN,
~RADEON_PCIGART_TRANSLATE_EN );
// set PCI GART page-table base address // set PCI GART page-table base address
OUTREG( regs, RADEON_AIC_PT_BASE, di->pci_gart.GATT.phys ); OUTREG( regs, RADEON_AIC_PT_BASE, di->pci_gart.GATT.phys );
@@ -159,9 +174,12 @@ void Radeon_InitMemController( device_info *di )
si->memory[mt_PCI].virtual_size/*di->pci_gart.buffer.size*/ - 1 ); si->memory[mt_PCI].virtual_size/*di->pci_gart.buffer.size*/ - 1 );
// set AGP address range // set AGP address range
OUTREG( regs, RADEON_MC_AGP_LOCATION, OUTREG( regs, RADEON_MC_AGP_LOCATION, 0xffffffc0 /* EK magic numbers from X.org
(si->memory[mt_AGP].virtual_addr_start >> 16) | (si->memory[mt_AGP].virtual_addr_start >> 16) |
((si->memory[mt_AGP].virtual_addr_start + si->memory[mt_AGP].virtual_size - 1) & 0xffff0000 )); ((si->memory[mt_AGP].virtual_addr_start + si->memory[mt_AGP].virtual_size - 1) & 0xffff0000 )*/);
// disable AGP
OUTREG( regs, RADEON_AGP_COMMAND, 0 );
// set address range of video memory // set address range of video memory
// (lower word = begin >> 16 // (lower word = begin >> 16
@@ -176,18 +194,10 @@ void Radeon_InitMemController( device_info *di )
OUTREG( regs, RADEON_CRTC2_DISPLAY_BASE_ADDRESS, si->memory[mt_local].virtual_addr_start ); OUTREG( regs, RADEON_CRTC2_DISPLAY_BASE_ADDRESS, si->memory[mt_local].virtual_addr_start );
OUTREG( regs, RADEON_OV0_BASE_ADDRESS, si->memory[mt_local].virtual_addr_start ); OUTREG( regs, RADEON_OV0_BASE_ADDRESS, si->memory[mt_local].virtual_addr_start );
// disable AGP
OUTREG( regs, RADEON_AGP_COMMAND, 0 );
// Turn on PCI GART
OUTREGP( regs, RADEON_AIC_CNTL, RADEON_PCIGART_TRANSLATE_EN,
~RADEON_PCIGART_TRANSLATE_EN );
// fix some bus controller setting // fix some bus controller setting
// I reckon this takes care of discarding data unnecessarily read // I reckon this takes care of discarding data unnecessarily read
// during a burst; let's hope this will fix the nasty CP crashing problem // during a burst; let's hope this will fix the nasty CP crashing problem
OUTREGP( regs, RADEON_BUS_CNTL, RADEON_BUS_RD_DISCARD_EN, ~RADEON_BUS_RD_DISCARD_EN ); // EK this seems unecessary. OUTREGP( regs, RADEON_BUS_CNTL, RADEON_BUS_RD_DISCARD_EN, ~RADEON_BUS_RD_DISCARD_EN );
// SHOW_FLOW0( 3, "done" ); // SHOW_FLOW0( 3, "done" );
} }
@@ -67,6 +67,7 @@ typedef struct {
int Tr2w; int Tr2w;
int loop_latency; int loop_latency;
int Rloop; int Rloop;
int width;
} ram_info; } ram_info;
// ROM information // ROM information
@@ -109,7 +110,8 @@ typedef struct device_info {
bool has_vip; bool has_vip;
bool is_igp; bool is_igp;
bool has_no_i2c; bool has_no_i2c;
//display_type_e disp_type[2]; bool acc_dma;
fp_info fp_info; fp_info fp_info;
general_pll_info pll; general_pll_info pll;