diff --git a/headers/private/graphics/radeon/radeon_interface.h b/headers/private/graphics/radeon/radeon_interface.h index e3edf7115b..3402fb77f7 100644 --- a/headers/private/graphics/radeon/radeon_interface.h +++ b/headers/private/graphics/radeon/radeon_interface.h @@ -20,7 +20,8 @@ #include "ddc.h" // 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 @@ -35,6 +36,7 @@ enum { RADEON_FREE_MEM, RADEON_WAITFORIDLE, + RADEON_WAITFORFIFO, RADEON_RESETENGINE, RADEON_VIPREAD, RADEON_VIPWRITE, @@ -396,6 +398,7 @@ typedef struct { typedef struct { // filled out by kernel CP_info cp; // info concerning command processor + bool acc_dma; // prevent use of dma engine // set by accelerant struct { @@ -499,6 +502,12 @@ typedef struct { bool keep_lock; // keep lock after engine is 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 typedef struct { uint32 magic; diff --git a/headers/private/graphics/radeon/version.h b/headers/private/graphics/radeon/version.h index 5abaa41fbe..70f526a862 100644 --- a/headers/private/graphics/radeon/version.h +++ b/headers/private/graphics/radeon/version.h @@ -8,4 +8,4 @@ */ // current version -#define RADEON_DRIVER_VERSION "Version: 5.1.2.1" +#define RADEON_DRIVER_VERSION "Version: 5.1.3.1" diff --git a/src/add-ons/accelerants/radeon/Acceleration.c b/src/add-ons/accelerants/radeon/Acceleration.c index 1d01288769..8c118a1999 100644 --- a/src/add-ons/accelerants/radeon/Acceleration.c +++ b/src/add-ons/accelerants/radeon/Acceleration.c @@ -13,6 +13,7 @@ #include "generic.h" #include "3d_regs.h" #include "2d_regs.h" +#include "radeon_regs.h" #include "mmio.h" #include "CP.h" @@ -21,7 +22,7 @@ // et - ignored // list - list 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; @@ -55,13 +56,63 @@ void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 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 // et - ignored // colorIndex - fill colour // list - list 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) { 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 // et - ignored // list - list 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; @@ -151,12 +238,41 @@ void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 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 // et - ignored // colorIndex - fill colour // list - list 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; @@ -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 void Radeon_Init2D( accelerator_info *ai ) { SHOW_FLOW0( 3, "" ); - START_IB(); - // forget about 3D - WRITE_IB_REG( RADEON_RB3D_CNTL, 0 ); - - SUBMIT_IB(); + if ( ai->si->acc_dma ) { + START_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 void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype ) { virtual_card *vc = ai->vc; uint32 pitch_offset; - uint32 *buffer, *buffer_start; + uint32 *buffer = NULL, *buffer_start = NULL; 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 pitch_offset = ((ai->si->memory[mt_local].virtual_addr_start + vc->fb_offset) >> 10) | ((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 - WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT, - (RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX)); - - // setup general flags - perhaps this is not needed as all - // 2D commands contain this register - WRITE_IB_REG( 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 ); - + if ( ai->si->acc_dma ) { + // make sure buffer is not used + Radeon_InvalidateStateBuffer( ai, vc->state_buffer_idx ); + buffer = buffer_start = Radeon_GetIndirectBufferPtr( ai, vc->state_buffer_idx ); - // most of this init is probably not nessacary - // as we neither draw lines nor use brushes - WRITE_IB_REG( RADEON_DST_LINE_START, 0); - WRITE_IB_REG( RADEON_DST_LINE_END, 0); - WRITE_IB_REG( RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); - WRITE_IB_REG( RADEON_DP_BRUSH_BKGD_CLR, 0x00000000); - WRITE_IB_REG( RADEON_DP_SRC_FRGD_CLR, 0xffffffff); - WRITE_IB_REG( RADEON_DP_SRC_BKGD_CLR, 0x00000000); - WRITE_IB_REG( RADEON_DP_WRITE_MASK, 0xffffffff); + 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 sissors + WRITE_IB_REG( RADEON_DEFAULT_SC_BOTTOM_RIGHT, + (RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX)); + // general fluff + WRITE_IB_REG( 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 + WRITE_IB_REG( RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); + WRITE_IB_REG( RADEON_DP_BRUSH_BKGD_CLR, 0x00000000); + WRITE_IB_REG( RADEON_DP_SRC_FRGD_CLR, 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; } diff --git a/src/add-ons/accelerants/radeon/EngineManagment.c b/src/add-ons/accelerants/radeon/EngineManagment.c index c572ad4d85..03811dcf52 100644 --- a/src/add-ons/accelerants/radeon/EngineManagment.c +++ b/src/add-ons/accelerants/radeon/EngineManagment.c @@ -65,21 +65,30 @@ static void writeSyncToken( accelerator_info *ai ) if( ai->si->engine.count == ai->si->engine.written ) return; - START_IB(); - - // flush pending data - WRITE_IB_REG( RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL ); + if( ai->si->acc_dma ) { + START_IB(); - // make sure commands are finished - WRITE_IB_REG( RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | - RADEON_WAIT_3D_IDLECLEAN | RADEON_WAIT_HOST_IDLECLEAN ); + // flush pending data + WRITE_IB_REG( RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL ); - // write scratch register - WRITE_IB_REG( RADEON_SCRATCH_REG0, ai->si->engine.count ); - - ai->si->engine.written = ai->si->engine.count; - - SUBMIT_IB(); + // make sure commands are finished + WRITE_IB_REG( RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_3D_IDLECLEAN | RADEON_WAIT_HOST_IDLECLEAN ); + + // write scratch register + WRITE_IB_REG( RADEON_SCRATCH_REG0, ai->si->engine.count ); + + ai->si->engine.written = ai->si->engine.count; + + 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 @@ -178,6 +187,13 @@ status_t SYNC_TO_TOKEN( sync_token *st ) SHOW_FLOW0( 4, "" ); + if ( !ai->si->acc_dma ) + { + Radeon_WaitForFifo( ai, 64 ); + Radeon_WaitForIdle( ai, false ); + return B_OK; + } + start_time = system_time(); while( 1 ) { diff --git a/src/add-ons/accelerants/radeon/InitAccelerant.c b/src/add-ons/accelerants/radeon/InitAccelerant.c index a8d242646a..a8f8059d1d 100644 --- a/src/add-ons/accelerants/radeon/InitAccelerant.c +++ b/src/add-ons/accelerants/radeon/InitAccelerant.c @@ -111,7 +111,8 @@ err: static void uninit_common( void ) { 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, // 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 //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 return B_OK; diff --git a/src/add-ons/accelerants/radeon/driver_wrapper.c b/src/add-ons/accelerants/radeon/driver_wrapper.c index c89eebc560..6c793f68de 100644 --- a/src/add-ons/accelerants/radeon/driver_wrapper.c +++ b/src/add-ons/accelerants/radeon/driver_wrapper.c @@ -23,6 +23,27 @@ status_t Radeon_WaitForIdle( accelerator_info *ai, bool keep_lock ) 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 ) { diff --git a/src/add-ons/accelerants/radeon/generic.h b/src/add-ons/accelerants/radeon/generic.h index 0509c956b7..afc31a4196 100644 --- a/src/add-ons/accelerants/radeon/generic.h +++ b/src/add-ons/accelerants/radeon/generic.h @@ -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 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); const uint32 *OVERLAY_SUPPORTED_SPACES(const display_mode *dm); uint32 OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space); diff --git a/src/add-ons/accelerants/radeon/overlay.c b/src/add-ons/accelerants/radeon/overlay.c index 6134671583..ba1758bd11 100644 --- a/src/add-ons/accelerants/radeon/overlay.c +++ b/src/add-ons/accelerants/radeon/overlay.c @@ -973,17 +973,27 @@ static void Radeon_ReplaceOverlayBuffer( shared_info *si = ai->si; uint32 offset; - START_IB(); - - offset = si->pending_overlay.on->mem_offset + si->active_overlay.rel_offset; - - WRITE_IB_REG( RADEON_OV0_VID_BUF0_BASE_ADRS, offset); - - 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 ); - - SUBMIT_IB(); + if ( ai->si->acc_dma ) + { + START_IB(); + offset = si->pending_overlay.on->mem_offset + si->active_overlay.rel_offset; + + WRITE_IB_REG( RADEON_OV0_VID_BUF0_BASE_ADRS, offset); + + 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 ); + + 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; #endif } diff --git a/src/add-ons/accelerants/radeon/palette.c b/src/add-ons/accelerants/radeon/palette.c index ed8e99a590..5aab89affe 100644 --- a/src/add-ons/accelerants/radeon/palette.c +++ b/src/add-ons/accelerants/radeon/palette.c @@ -13,33 +13,41 @@ #include "GlobalData.h" #include "dac_regs.h" +#include "mmio.h" #include "CP.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) void Radeon_InitPalette( accelerator_info *ai, int crtc_idx ) { int i; - START_IB(); - - selectPalette( crtc_idx ); - - WRITE_IB_REG( RADEON_PALETTE_INDEX, 0 ); - - for( i = 0; i < 256; ++i ) - WRITE_IB_REG( RADEON_PALETTE_DATA, (i << 16) | (i << 8) | i ); + if ( ai->si->acc_dma ) { + START_IB(); - SUBMIT_IB(); + 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 ); + + for( i = 0; i < 256; ++i ) + WRITE_IB_REG( RADEON_PALETTE_DATA, (i << 16) | (i << 8) | i ); + + 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( @@ -75,17 +83,35 @@ static void setPalette( { uint i; - START_IB(); - - selectPalette( crtc_idx ); - - WRITE_IB_REG( RADEON_PALETTE_INDEX, first ); - - for( i = 0; i < count; ++i, color_data += 3 ) - WRITE_IB_REG( RADEON_PALETTE_DATA, - ((uint32)color_data[0] << 16) | - ((uint32)color_data[1] << 8) | - color_data[2] ); - - SUBMIT_IB(); + if ( ai->si->acc_dma ) { + START_IB(); + + 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 ); + + for( i = 0; i < count; ++i, color_data += 3 ) + WRITE_IB_REG( RADEON_PALETTE_DATA, + ((uint32)color_data[0] << 16) | + ((uint32)color_data[1] << 8) | + color_data[2] ); + + 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] ); + } + } } diff --git a/src/add-ons/accelerants/radeon/radeon_accelerant.h b/src/add-ons/accelerants/radeon/radeon_accelerant.h index de54181708..c69035bc24 100644 --- a/src/add-ons/accelerants/radeon/radeon_accelerant.h +++ b/src/add-ons/accelerants/radeon/radeon_accelerant.h @@ -115,6 +115,7 @@ void Radeon_FillStateBuffer( accelerator_info *ai, uint32 datatype ); // driver_wrapper.c 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 ); status_t Radeon_VIPRead( accelerator_info *ai, uint channel, uint address, uint32 *data ); diff --git a/src/add-ons/kernel/drivers/graphics/radeon/CP_setup.c b/src/add-ons/kernel/drivers/graphics/radeon/CP_setup.c index 6f673a0b63..760fa07f4a 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/CP_setup.c +++ b/src/add-ons/kernel/drivers/graphics/radeon/CP_setup.c @@ -227,71 +227,54 @@ void Radeon_ResetEngine( device_info *di ) host_path_cntl = INREG( regs, RADEON_HOST_PATH_CNTL ); rbbm_soft_reset = INREG( regs, RADEON_RBBM_SOFT_RESET ); - switch( di->asic ) { - 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 | + OUTREG( regs, 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_SOFT_RESET_AIC ); - INREG( regs, RADEON_RBBM_SOFT_RESET ); - OUTREG( regs, 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_SOFT_RESET_AIC ) ); - INREG( regs, RADEON_RBBM_SOFT_RESET ); - } - + RADEON_SOFT_RESET_RB ) ); + INREG( regs, RADEON_RBBM_SOFT_RESET); + OUTREG( regs, 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 ) ); + INREG( regs, RADEON_RBBM_SOFT_RESET); + OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET ); INREG( regs, RADEON_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 ); + 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); + + if ( di->acc_dma ) + { + // 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 ) { + // during init, there are no feedback data + if( si->cp.feedback.mem_handle != 0 ) { + *(uint32 *)MEM2CPU( si->cp.feedback.mem_type, si->cp.feedback.head_mem_offset) = + cur_read_ptr; + // *si->cp.ring.head = cur_read_ptr; + si->cp.ring.tail = 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 ) { - // during init, there are no feedback data - if( si->cp.feedback.mem_handle != 0 ) { - *(uint32 *)MEM2CPU( si->cp.feedback.mem_type, si->cp.feedback.head_mem_offset) = - cur_read_ptr; - // *si->cp.ring.head = cur_read_ptr; - si->cp.ring.tail = cur_read_ptr; + // mark all buffers as being finished + Radeon_DiscardAllIndirectBuffers( di ); } ++si->engine.count; - - // mark all buffers as being finished - Radeon_DiscardAllIndirectBuffers( di ); - return; } @@ -522,7 +505,7 @@ status_t Radeon_InitCP( device_info *di ) set_sem_owner( di->si->cp.lock.sem, thinfo.team ); // init raw CP - loadMicroEngineRAMData( di ); + if ( di->acc_dma ) loadMicroEngineRAMData( di ); // do soft-reset Radeon_ResetEngine( di ); @@ -536,26 +519,30 @@ status_t Radeon_InitCP( device_info *di ) // reset CP to make disabling active Radeon_ResetEngine( di ); - res = initRingBuffer( di, CP_RING_SIZE ); - if( res < 0 ) - goto err4; - - res = initCPFeedback( di ); - if( res < 0 ) - goto err3; + if ( di->acc_dma ) + { + res = initRingBuffer( di, CP_RING_SIZE ); + if( res < 0 ) + goto err4; - res = initIndirectBuffers( di ); - if( res < 0 ) - goto err2; + res = initCPFeedback( di ); + if( res < 0 ) + goto err3; + + res = initIndirectBuffers( di ); + if( res < 0 ) + goto err2; + + // tell CP to use BM + Radeon_WaitForIdle( di, false, false ); - // tell CP to use BM - Radeon_WaitForIdle( di, false, false ); - - // enable direct and indirect CP bus mastering - 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 ); + // enable direct and indirect CP bus mastering + 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 ); + } + // 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 @@ -596,11 +583,14 @@ void Radeon_UninitCP( device_info *di ) OUTREG( regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); // read-back for flushing INREG( regs, RADEON_CP_CSQ_CNTL ); - - uninitRingBuffer( di ); - uninitCPFeedback( di ); - uninitIndirectBuffers( di ); + if ( di->acc_dma ) + { + uninitRingBuffer( di ); + uninitCPFeedback( di ); + uninitIndirectBuffers( di ); + } + DELETE_BEN( di->si->cp.lock ); } diff --git a/src/add-ons/kernel/drivers/graphics/radeon/bios.c b/src/add-ons/kernel/drivers/graphics/radeon/bios.c index 5394ab7746..03d24d59a1 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/bios.c +++ b/src/add-ons/kernel/drivers/graphics/radeon/bios.c @@ -536,58 +536,142 @@ static void Radeon_GetFPData( device_info *di ) 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 static void Radeon_DetectRAM( device_info *di ) { vuint8 *regs = di->regs; - - if( !di->is_igp ) - di->local_mem_size = INREG( regs, RADEON_CONFIG_MEMSIZE ) & RADEON_CONFIG_MEMSIZE_MASK; - else { + uint32 accessible, bar_size, tmp = 0; + + if( di->is_igp ) { uint32 tom; tom = INREG( regs, RADEON_NB_TOM ); 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 - if( di->local_mem_size == 0 ) + if( di->local_mem_size == 0 ) { 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 + + // 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", di->local_mem_size / 1024 / 1024, - di->ram_type ); + 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 ) { di->local_mem_size = 64 * 1024 * 1024; diff --git a/src/add-ons/kernel/drivers/graphics/radeon/detect.c b/src/add-ons/kernel/drivers/graphics/radeon/detect.c index 9209a14e70..11379f3168 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/detect.c +++ b/src/add-ons/kernel/drivers/graphics/radeon/detect.c @@ -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 ) // give up checking this device - no BIOS, no fun return false; diff --git a/src/add-ons/kernel/drivers/graphics/radeon/driver.c b/src/add-ons/kernel/drivers/graphics/radeon/driver.c index 1287bec8ef..01f628ca76 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/driver.c +++ b/src/add-ons/kernel/drivers/graphics/radeon/driver.c @@ -273,6 +273,16 @@ static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len ) result = B_OK; } 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: { radeon_no_arg *na = (radeon_no_arg *)buf; diff --git a/src/add-ons/kernel/drivers/graphics/radeon/init.c b/src/add-ons/kernel/drivers/graphics/radeon/init.c index 7aac99b57f..de1a7b5a9b 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/init.c +++ b/src/add-ons/kernel/drivers/graphics/radeon/init.c @@ -250,6 +250,7 @@ status_t Radeon_FirstOpen( device_info *di ) si->is_atombios = di->is_atombios; si->is_mobility = di->is_mobility; 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, @@ -359,15 +360,22 @@ status_t Radeon_FirstOpen( device_info *di ) if( di->asic == rt_rs100 || di->asic == rt_rs200 || di->asic == rt_rs300) Radeon_Fix_AGP(); - // time to init Command Processor - result = Radeon_InitCP( di ); - if( result != B_OK ) - goto err; + if ( di->acc_dma ) + { + // time to init Command Processor + result = Radeon_InitCP( di ); + if( result != B_OK ) + goto err; + + result = Radeon_InitDMA( di ); + if( result != B_OK ) + goto err0; + } + else + { + SHOW_INFO0( 0, "DMA is diabled using PIO mode"); + } - result = Radeon_InitDMA( di ); - if( result != B_OK ) - goto err0; - // mem_alloc( di->local_memmgr, 0x100000, (void *)-1, &dma_block, &dma_offset ); /* dma_offset = 15 * 1024 * 1024; @@ -402,7 +410,8 @@ err8: // during tests) 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, // not even before reboot diff --git a/src/add-ons/kernel/drivers/graphics/radeon/mem_controller.c b/src/add-ons/kernel/drivers/graphics/radeon/mem_controller.c index 6f5ffc7d11..d073d7c3d3 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/mem_controller.c +++ b/src/add-ons/kernel/drivers/graphics/radeon/mem_controller.c @@ -39,10 +39,21 @@ static uint32 getTopOfRam() static void Radeon_SetupMCAddresses_Direct( device_info *di ) { 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; // 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; // PCI GART has no corresponding CPU address space, so we must find an unused @@ -148,6 +159,10 @@ void Radeon_InitMemController( device_info *di ) si->memory[mt_AGP].virtual_size, si->memory[mt_AGP].virtual_addr_start ); //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 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 ); // 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 + 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 // (lower word = begin >> 16 @@ -175,19 +193,11 @@ void Radeon_InitMemController( device_info *di ) OUTREG( regs, RADEON_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 ); - - // 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 // I reckon this takes care of discarding data unnecessarily read // 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" ); } diff --git a/src/add-ons/kernel/drivers/graphics/radeon/radeon_driver.h b/src/add-ons/kernel/drivers/graphics/radeon/radeon_driver.h index 3a0c39cac7..625943d9ae 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/radeon_driver.h +++ b/src/add-ons/kernel/drivers/graphics/radeon/radeon_driver.h @@ -67,6 +67,7 @@ typedef struct { int Tr2w; int loop_latency; int Rloop; + int width; } ram_info; // ROM information @@ -109,7 +110,8 @@ typedef struct device_info { bool has_vip; bool is_igp; bool has_no_i2c; - //display_type_e disp_type[2]; + bool acc_dma; + fp_info fp_info; general_pll_info pll;