#define R300_TEST #include "r5xx_regs.h" #define R5XX_LOOP_COUNT 2000000 #define RADEON_CLOCK_CNTL_DATA 0x000c #define RADEON_CLOCK_CNTL_INDEX 0x0008 # define RADEON_PLL_WR_EN (1 << 7) # define RADEON_PLL_DIV_SEL (3 << 8) # define RADEON_PLL2_DIV_SEL_MASK ~(3 << 8) #define RADEON_MCLK_CNTL 0x0012 /* PLL */ # define RADEON_FORCEON_MCLKA (1 << 16) # define RADEON_FORCEON_MCLKB (1 << 17) # define RADEON_FORCEON_YCLKA (1 << 18) # define RADEON_FORCEON_YCLKB (1 << 19) # define RADEON_FORCEON_MC (1 << 20) # define RADEON_FORCEON_AIC (1 << 21) # define R300_DISABLE_MC_MCLKA (1 << 21) # define R300_DISABLE_MC_MCLKB (1 << 21) void radeon_engine_reset(RHDPtr info) { u32_t clock_cntl_index; u32_t mclk_cntl; u32_t rbbm_soft_reset; u32_t host_path_cntl; if (info->ChipFamily <= CHIP_FAMILY_RV410) { /* may need something similar for newer chips */ clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); mclk_cntl = INPLL( RADEON_MCLK_CNTL); OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl | RADEON_FORCEON_MCLKA | RADEON_FORCEON_MCLKB | RADEON_FORCEON_YCLKA | RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC | RADEON_FORCEON_AIC)); } rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); OUTREG(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(RADEON_RBBM_SOFT_RESET); OUTREG(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(RADEON_RBBM_SOFT_RESET); if (info->ChipFamily <= CHIP_FAMILY_RV410) { OUTPLL(RADEON_MCLK_CNTL, mclk_cntl); OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); } }; static Bool R5xxFIFOWaitLocal(u32_t required) //R100-R500 { int i; for (i = 0; i < RADEON_TIMEOUT; i++) if (required <= (INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK)) return TRUE; dbgprintf("%s: Timeout 0x%08X.\n", __func__, (u32_t) INREG(RADEON_RBBM_STATUS)); return FALSE; } void FIFOWait(u32_t required) { int i; for (i = 0; i < 200; i++) { if (required <= (INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK)) return ; delay(2); }; }; /* * Flush all dirty data in the Pixel Cache to memory. */ static Bool R5xx2DFlush() { int i; MASKREG(R5XX_DSTCACHE_CTLSTAT, R5XX_DSTCACHE_FLUSH_ALL, R5XX_DSTCACHE_FLUSH_ALL); for (i = 0; i < R5XX_LOOP_COUNT; i++) if (!(INREG(R5XX_DSTCACHE_CTLSTAT) & R5XX_DSTCACHE_BUSY)) return TRUE; dbgprintf("%s: Timeout 0x%08x.\n", __func__, (unsigned int)INREG(R5XX_DSTCACHE_CTLSTAT)); return FALSE; } static Bool R5xx2DIdleLocal() //R100-R500 { int i; /* wait for fifo to clear */ for (i = 0; i < R5XX_LOOP_COUNT; i++) if (64 == (INREG(R5XX_RBBM_STATUS) & R5XX_RBBM_FIFOCNT_MASK)) break; if (i == R5XX_LOOP_COUNT) { dbgprintf("%s: FIFO Timeout 0x%08X.\n", __func__,INREG(R5XX_RBBM_STATUS)); return FALSE; } /* wait for engine to go idle */ for (i = 0; i < R5XX_LOOP_COUNT; i++) { if (!(INREG(R5XX_RBBM_STATUS) & R5XX_RBBM_ACTIVE)) { R5xx2DFlush(); return TRUE; } } dbgprintf("%s: Idle Timeout 0x%08X.\n", __func__,INREG(R5XX_RBBM_STATUS)); return FALSE; } void R5xx2DSetup() { /* Setup engine location. This shouldn't be necessary since we * set them appropriately before any accel ops, but let's avoid * random bogus DMA in case we inadvertently trigger the engine * in the wrong place (happened). */ R5xxFIFOWaitLocal(2); OUTREG(R5XX_DST_PITCH_OFFSET,rhd.dst_pitch_offset); OUTREG(R5XX_SRC_PITCH_OFFSET,rhd.dst_pitch_offset); R5xxFIFOWaitLocal(1); MASKREG(R5XX_DP_DATATYPE, 0, R5XX_HOST_BIG_ENDIAN_EN); OUTREG(R5XX_SURFACE_CNTL, rhd.surface_cntl); R5xxFIFOWaitLocal(3); OUTREG(R5XX_SC_TOP_LEFT, 0); OUTREG(R5XX_SC_BOTTOM_RIGHT, RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX); OUTREG(R5XX_DEFAULT_SC_BOTTOM_RIGHT, RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX); R5xxFIFOWaitLocal(1); // OUTREG(R5XX_DP_GUI_MASTER_CNTL, rhd.gui_control | // R5XX_GMC_BRUSH_SOLID_COLOR | R5XX_GMC_SRC_DATATYPE_COLOR); OUTREG(R5XX_DP_CNTL, R5XX_DST_X_LEFT_TO_RIGHT | R5XX_DST_Y_TOP_TO_BOTTOM); R5xxFIFOWaitLocal(5); OUTREG(R5XX_DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); OUTREG(R5XX_DP_BRUSH_BKGD_CLR, 0x00000000); OUTREG(R5XX_DP_SRC_FRGD_CLR, 0xFFFFFFFF); OUTREG(R5XX_DP_SRC_BKGD_CLR, 0x00000000); OUTREG(R5XX_DP_WRITE_MASK, 0xFFFFFFFF); R5xx2DIdleLocal(); } void R5xxFIFOWait(u32_t required) { if (!R5xxFIFOWaitLocal(required)) { radeon_engine_reset(&rhd); R5xx2DSetup(); } } void R5xx2DIdle() { if (!R5xx2DIdleLocal()) { // R5xx2DReset(); R5xx2DSetup(); } } void R5xx2DInit() { u32_t base; int screensize; int screenpitch; screensize = GetScreenSize(); screenpitch = GetScreenPitch(); rhd.displayWidth = screensize >> 16; rhd.displayHeight = screensize & 0xFFFF; rhd.__xmin = 0; rhd.__ymin = 0; rhd.__xmax = rhd.displayWidth - 1; rhd.__ymax = rhd.displayHeight - 1; clip.xmin = 0; clip.ymin = 0; clip.xmax = rhd.displayWidth - 1; clip.ymax = rhd.displayHeight - 1; dbgprintf("screen width %d height %d\n", rhd.displayWidth, rhd.displayHeight); rhd.gui_control = ((6 << RADEON_GMC_DST_DATATYPE_SHIFT) | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_DST_PITCH_OFFSET_CNTL); dbgprintf("gui_control %x \n", rhd.gui_control); rhd.surface_cntl = 0; rhd.dst_pitch_offset = (((rhd.displayWidth * 4 / 64)<< 22) | (rhd.fbLocation >> 10)); dbgprintf("dst_pitch_offset %x \n", rhd.dst_pitch_offset); scr_pixmap.width = rhd.displayWidth; scr_pixmap.height = rhd.displayHeight; scr_pixmap.format = PICT_a8r8g8b8; scr_pixmap.flags = PX_MEM_LOCAL; scr_pixmap.pitch = rhd.displayWidth * 4 ;//screenpitch; scr_pixmap.local = rhd.fbLocation; scr_pixmap.pitch_offset = rhd.dst_pitch_offset; scr_pixmap.mapped = 0; R5xxFIFOWaitLocal(2); OUTREG(R5XX_DST_PITCH_OFFSET,rhd.dst_pitch_offset); OUTREG(R5XX_SRC_PITCH_OFFSET,rhd.dst_pitch_offset); R5xxFIFOWaitLocal(1); MASKREG(R5XX_DP_DATATYPE, 0, R5XX_HOST_BIG_ENDIAN_EN); OUTREG(R5XX_SURFACE_CNTL, rhd.surface_cntl); #if !R300_PIO init_cp(&rhd); #endif R5xx2DSetup(); }