diff --git a/headers/private/graphics/radeon/version.h b/headers/private/graphics/radeon/version.h index 2b0ce2bdb1..4812b5a539 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.4.0" +#define RADEON_DRIVER_VERSION "Version: 5.1.4.5" diff --git a/src/add-ons/accelerants/radeon/dpms.c b/src/add-ons/accelerants/radeon/dpms.c index 64b8c3816c..598acde4d1 100644 --- a/src/add-ons/accelerants/radeon/dpms.c +++ b/src/add-ons/accelerants/radeon/dpms.c @@ -66,9 +66,8 @@ static void Radeon_SetDPMS_LVDS( accelerator_info *ai, int mode ) // (you get a dark picture first that becomes brighter step by step, // after a couple of seconds you have full brightness again) OUTREGP( regs, RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON ); - //snooze( ai->si->fp_port.panel_pwr_delay * 1000 ); - OUTREGP( regs, RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON | RADEON_LVDS_ON, - ~(RADEON_LVDS_DISPLAY_DIS | RADEON_LVDS_BLON | RADEON_LVDS_ON) ); + snooze( ai->si->panel_pwr_delay * 1000 ); + OUTREGP( regs, RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON ); break; case B_DPMS_STAND_BY: @@ -82,8 +81,7 @@ static void Radeon_SetDPMS_LVDS( accelerator_info *ai, int mode ) if( ai->si->is_mobility || ai->si->is_igp ) Radeon_OUTPLLP( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb ); - OUTREGP( regs, RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, - ~(RADEON_LVDS_DISPLAY_DIS | RADEON_LVDS_BLON | RADEON_LVDS_ON) ); + OUTREGP( regs, RADEON_LVDS_GEN_CNTL, 0, ~(RADEON_LVDS_BLON | RADEON_LVDS_ON) ); if( ai->si->is_mobility || ai->si->is_igp ) Radeon_OUTPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL, old_pixclks_cntl ); @@ -125,15 +123,20 @@ static void Radeon_SetDPMS_FP2( accelerator_info *ai, int mode ) // *should* be supported as well) switch( mode ) { case B_DPMS_ON: - OUTREGP( regs, RADEON_FP2_GEN_CNTL, - RADEON_FP_FPON | - (ai->si->asic >= rt_r200 ? RADEON_FP2_DV0_EN : 0), - ~(RADEON_FP2_BLANK_EN | RADEON_FP2_BLANK_EN) ); + OUTREGP( regs, RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + OUTREGP( regs, RADEON_FP2_GEN_CNTL, RADEON_FP2_FPON, ~RADEON_FP2_FPON); + if (ai->si->asic >= rt_r200) { + OUTREGP( regs, RADEON_FP2_GEN_CNTL, RADEON_FP2_DV0_EN, ~RADEON_FP2_DV0_EN); + } break; case B_DPMS_STAND_BY: case B_DPMS_SUSPEND: case B_DPMS_OFF: - OUTREGP( regs, RADEON_FP2_GEN_CNTL, 0, ~(RADEON_FP2_BLANK_EN | RADEON_FP2_BLANK_EN) ); + OUTREGP( regs, RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN ); + OUTREGP( regs, RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_FPON); + if (ai->si->asic >= rt_r200) { + OUTREGP( regs, RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DV0_EN); + } break; } } @@ -170,14 +173,20 @@ static void Radeon_SetDPMS_TVCRT( accelerator_info *ai, int mode ) switch( mode ) { case B_DPMS_ON: - OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_DISP_DIS ); + OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, 0, + ~(RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS) ); break; - case B_DPMS_STAND_BY: + OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), + ~(RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS) ); + break; case B_DPMS_SUSPEND: + OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), + ~(RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS) ); + break; case B_DPMS_OFF: - OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS, ~RADEON_CRTC2_DISP_DIS ); + OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS), + ~(RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS) ); break; } } @@ -188,26 +197,23 @@ static void Radeon_SetDPMS_CRTC1( accelerator_info *ai, int mode ) { vuint8 *regs = ai->regs; - uint32 mask = RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_VSYNC_DIS; + uint32 mask = ~(RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS); switch( mode ) { case B_DPMS_ON: - /* Screen: On; HSync: On, VSync: On */ - OUTREGP( regs, RADEON_CRTC_EXT_CNTL, 0, ~mask ); + OUTREGP( regs, RADEON_CRTC_EXT_CNTL, 0, mask ); break; case B_DPMS_STAND_BY: - /* Screen: Off; HSync: Off, VSync: On */ - OUTREGP( regs, RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_HSYNC_DIS, ~mask ); + OUTREGP( regs, RADEON_CRTC_EXT_CNTL, + (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), mask ); break; case B_DPMS_SUSPEND: - /* Screen: Off; HSync: On, VSync: Off */ - OUTREGP( regs, RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_VSYNC_DIS, ~mask ); + OUTREGP( regs, RADEON_CRTC_EXT_CNTL, + (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), mask ); break; case B_DPMS_OFF: - /* Screen: Off; HSync: Off, VSync: Off */ - OUTREGP( regs, RADEON_CRTC_EXT_CNTL, mask, ~mask ); + OUTREGP( regs, RADEON_CRTC_EXT_CNTL, + (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS), mask ); break; } @@ -233,26 +239,21 @@ static void Radeon_SetDPMS_CRTC2( accelerator_info *ai, int mode ) { vuint8 *regs = ai->regs; - int mask = RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_VSYNC_DIS; + int mask = ~(RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS); switch( mode ) { case B_DPMS_ON: - /* Screen: On; HSync: On, VSync: On */ - OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, 0, ~mask ); + OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, 0, mask ); break; case B_DPMS_STAND_BY: - /* Screen: Off; HSync: Off, VSync: On */ - OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_HSYNC_DIS, ~mask ); + OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), mask ); break; case B_DPMS_SUSPEND: - /* Screen: Off; HSync: On, VSync: Off */ - OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_VSYNC_DIS, ~mask ); + OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), mask); break; case B_DPMS_OFF: - /* Screen: Off; HSync: Off, VSync: Off */ - OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, mask, ~mask ); + OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS), mask); break; } diff --git a/src/add-ons/accelerants/radeon/flat_panel.c b/src/add-ons/accelerants/radeon/flat_panel.c index d9494638f2..7d27350b81 100644 --- a/src/add-ons/accelerants/radeon/flat_panel.c +++ b/src/add-ons/accelerants/radeon/flat_panel.c @@ -126,6 +126,9 @@ void Radeon_ReadFPRegisters( values->fp_v_sync_strt_wid = INREG( regs, RADEON_FP_V_SYNC_STRT_WID ); values->fp2_h_sync_strt_wid = INREG( regs, RADEON_FP_H2_SYNC_STRT_WID ); values->fp2_v_sync_strt_wid = INREG( regs, RADEON_FP_V2_SYNC_STRT_WID ); + values->bios_4_scratch = INREG( regs, RADEON_BIOS_4_SCRATCH ); + values->bios_5_scratch = INREG( regs, RADEON_BIOS_5_SCRATCH ); + values->bios_6_scratch = INREG( regs, RADEON_BIOS_6_SCRATCH ); SHOW_FLOW( 2, "before: fp_gen_cntl=%08lx, horz=%08lx, vert=%08lx, lvds_gen_cntl=%08lx", values->fp_gen_cntl, values->fp_horz_stretch, values->fp_vert_stretch, @@ -222,8 +225,54 @@ void Radeon_ProgramFPRegisters( INREG( regs, RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); } + if ( ai->si->is_mobility ) { + OUTREG( regs, RADEON_BIOS_4_SCRATCH, values->bios_4_scratch); + OUTREG( regs, RADEON_BIOS_5_SCRATCH, values->bios_5_scratch); + OUTREG( regs, RADEON_BIOS_6_SCRATCH, values->bios_6_scratch); + } + if( (crtc->chosen_displays & dd_lvds) != 0 ) { - OUTREGP( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl, - RADEON_LVDS_ON | RADEON_LVDS_BLON ); + + //OUTREGP( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl, + // RADEON_LVDS_ON | RADEON_LVDS_BLON ); + + uint32 old_pixclks_cntl; + uint32 tmp; + + old_pixclks_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL); + + // ASIC bug: when LVDS_ON is reset, LVDS_ALWAYS_ON must be zero + if( ai->si->is_mobility || ai->si->is_igp ) + { + if (!(values->lvds_gen_cntl & RADEON_LVDS_ON)) { + Radeon_OUTPLLP( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb ); + } + } + + // get current state of LCD + tmp = INREG( regs, RADEON_LVDS_GEN_CNTL); + + // if LCD is on, and previous state was on, just write the state directly. + if (( tmp & ( RADEON_LVDS_ON | RADEON_LVDS_BLON )) == + ( values->lvds_gen_cntl & ( RADEON_LVDS_ON | RADEON_LVDS_BLON ))) { + OUTREG( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl ); + } else { + if ( values->lvds_gen_cntl & ( RADEON_LVDS_ON | RADEON_LVDS_BLON )) { + snooze( ai->si->panel_pwr_delay * 1000 ); + OUTREG( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl ); + } else { + + //turn on backlight, wait for stable before turning on data ??? + OUTREG( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl | RADEON_LVDS_BLON ); + snooze( ai->si->panel_pwr_delay * 1000 ); + OUTREG( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl ); + } + } + + if( ai->si->is_mobility || ai->si->is_igp ) { + if (!(values->lvds_gen_cntl & RADEON_LVDS_ON)) { + Radeon_OUTPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL, old_pixclks_cntl ); + } + } } } diff --git a/src/add-ons/accelerants/radeon/set_mode.h b/src/add-ons/accelerants/radeon/set_mode.h index 366adbaf43..a5d826faa6 100644 --- a/src/add-ons/accelerants/radeon/set_mode.h +++ b/src/add-ons/accelerants/radeon/set_mode.h @@ -109,6 +109,11 @@ typedef struct { // RMX registers uint32 fp_horz_stretch; uint32 fp_vert_stretch; + + // Bios values used by Mobility Asics + uint32 bios_4_scratch; + uint32 bios_5_scratch; + uint32 bios_6_scratch; } fp_regs; 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 760fa07f4a..c1acb76251 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/CP_setup.c +++ b/src/add-ons/kernel/drivers/graphics/radeon/CP_setup.c @@ -627,3 +627,356 @@ void Radeon_DiscardAllIndirectBuffers( device_info *di ) cp->buffers.oldest = tmp_oldest_buffer; } } + +// lets hide this in here, as it's got lots of lovely register headers already... +// does it go here, or in the accelerant anyway? +// for now i'm assuming you turn on dynamic clocks, and they take care of themselves onwards... +// so doing it at driver init seems sensible after a valid detection of course... +void Radeon_SetDynamicClock( device_info *di, int mode) +{ + vuint8 *regs = di->regs; + radeon_type asic = di->asic; + uint32 tmp; + + switch(mode) { + case 0: /* Turn everything OFF (ForceON to everything)*/ + if ( di->num_crtc != 2 ) { + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE | + RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP | + RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB | + RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM | + RADEON_SCLK_FORCE_RB); + Radeon_OUTPLL(regs, asic, RADEON_SCLK_CNTL, tmp); + } else if (asic == rt_rv350) { + /* for RV350/M10, no delays are required. */ + tmp = Radeon_INPLL(regs, asic, R300_SCLK_CNTL2); + tmp |= (R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + Radeon_OUTPLL(regs, asic, R300_SCLK_CNTL2, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | + R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | + R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | + R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); + Radeon_OUTPLL(regs, asic, RADEON_SCLK_CNTL, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + Radeon_OUTPLL(regs, asic, RADEON_SCLK_MORE_CNTL, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_MCLK_CNTL); + tmp |= (RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB | + RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC); + Radeon_OUTPLL(regs, asic, RADEON_MCLK_CNTL, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); + Radeon_OUTPLL(regs, asic, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); + Radeon_OUTPLL(regs, asic, RADEON_PIXCLKS_CNTL, tmp); + } else { + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2); + tmp |= RADEON_SCLK_FORCE_SE; + + if ( di->num_crtc != 2 ) { + tmp |= ( RADEON_SCLK_FORCE_RB | + RADEON_SCLK_FORCE_TDM | + RADEON_SCLK_FORCE_TAM | + RADEON_SCLK_FORCE_PB | + RADEON_SCLK_FORCE_RE | + RADEON_SCLK_FORCE_VIP | + RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_HDP ); + } else if ((asic == rt_r300) || (asic == rt_r350)) { + tmp |= ( RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP); + } + Radeon_OUTPLL(regs, asic, RADEON_SCLK_CNTL, tmp); + + snooze(16000); + + if ((asic == rt_r300) || (asic == rt_r350)) { + tmp = Radeon_INPLL(regs, asic, R300_SCLK_CNTL2); + tmp |= ( R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + Radeon_OUTPLL(regs, asic, R300_SCLK_CNTL2, tmp); + snooze(16000); + } + + if (di->is_igp) { + tmp = Radeon_INPLL(regs, asic, RADEON_MCLK_CNTL); + tmp &= ~(RADEON_FORCEON_MCLKA | + RADEON_FORCEON_YCLKA); + Radeon_OUTPLL(regs, asic, RADEON_MCLK_CNTL, tmp); + snooze(16000); + } + + if ((asic == rt_rv200) || + (asic == rt_rv250) || + (asic == rt_rv280)) { + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + Radeon_OUTPLL(regs, asic, RADEON_SCLK_MORE_CNTL, tmp); + snooze(16000); + } + + tmp = Radeon_INPLL(regs, asic, RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + Radeon_OUTPLL(regs, asic, RADEON_PIXCLKS_CNTL, tmp); + snooze(16000); + + tmp = Radeon_INPLL(regs, asic, RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + Radeon_OUTPLL(regs, asic, RADEON_VCLK_ECP_CNTL, tmp); + } + SHOW_FLOW0( 3, "Dynamic Clock Scaling Disabled" ); + break; + case 1: + if ( di->num_crtc != 2 ) { + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_CNTL); + if ((INREG( regs, RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) > RADEON_CFG_ATI_REV_A13) { + tmp &= ~(RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_RB); + } + tmp &= ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE | + RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE | + RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM | + RADEON_SCLK_FORCE_TDM); + Radeon_OUTPLL(regs, asic, RADEON_SCLK_CNTL, tmp); + } else if ((asic == rt_r300) + || (asic == rt_r350) + || (asic == rt_rv350)) { + if (asic == rt_rv350) { + tmp = Radeon_INPLL(regs, asic, R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT | + R300_SCLK_GA_MAX_DYN_STOP_LAT | + R300_SCLK_CBA_MAX_DYN_STOP_LAT); + Radeon_OUTPLL(regs, asic, R300_SCLK_CNTL2, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_CNTL); + tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | + R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | + R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | + R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); + tmp |= RADEON_DYN_STOP_LAT_MASK; + Radeon_OUTPLL(regs, asic, RADEON_SCLK_CNTL, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; + Radeon_OUTPLL(regs, asic, RADEON_SCLK_MORE_CNTL, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + Radeon_OUTPLL(regs, asic, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb); + Radeon_OUTPLL(regs, asic, RADEON_PIXCLKS_CNTL, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_MCLK_MISC); + tmp |= (RADEON_MC_MCLK_DYN_ENABLE | + RADEON_IO_MCLK_DYN_ENABLE); + Radeon_OUTPLL(regs, asic, RADEON_MCLK_MISC, tmp); + + tmp = Radeon_INPLL(regs, asic, RADEON_MCLK_CNTL); + tmp |= (RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB); + + tmp &= ~(RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC); + + /* Some releases of vbios have set DISABLE_MC_MCLKA + and DISABLE_MC_MCLKB bits in the vbios table. Setting these + bits will cause H/W hang when reading video memory with dynamic clocking + enabled. */ + if ((tmp & R300_DISABLE_MC_MCLKA) && + (tmp & R300_DISABLE_MC_MCLKB)) { + /* If both bits are set, then check the active channels */ + tmp = Radeon_INPLL(regs, asic, RADEON_MCLK_CNTL); + if (di->ram.width == 64) { + if (INREG( regs, RADEON_MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY) + tmp &= ~R300_DISABLE_MC_MCLKB; + else + tmp &= ~R300_DISABLE_MC_MCLKA; + } else { + tmp &= ~(R300_DISABLE_MC_MCLKA | + R300_DISABLE_MC_MCLKB); + } + } + + Radeon_OUTPLL(regs, asic, RADEON_MCLK_CNTL, tmp); + } else { + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_CNTL); + tmp &= ~(R300_SCLK_FORCE_VAP); + tmp |= RADEON_SCLK_FORCE_CP; + Radeon_OUTPLL(regs, asic, RADEON_SCLK_CNTL, tmp); + snooze(15000); + + tmp = Radeon_INPLL(regs, asic, R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + Radeon_OUTPLL(regs, asic, R300_SCLK_CNTL2, tmp); + } + } else { + tmp = Radeon_INPLL(regs, asic, RADEON_CLK_PWRMGT_CNTL); + + tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK | + RADEON_DISP_DYN_STOP_LAT_MASK | + RADEON_DYN_STOP_MODE_MASK); + + tmp |= (RADEON_ENGIN_DYNCLK_MODE | + (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); + Radeon_OUTPLL(regs, asic, RADEON_CLK_PWRMGT_CNTL, tmp); + snooze(15000); + + tmp = Radeon_INPLL(regs, asic, RADEON_CLK_PIN_CNTL); + tmp |= RADEON_SCLK_DYN_START_CNTL; + Radeon_OUTPLL(regs, asic, RADEON_CLK_PIN_CNTL, tmp); + snooze(15000); + + /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 + to lockup randomly, leave them as set by BIOS. + */ + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_CNTL); + /*tmp &= RADEON_SCLK_SRC_SEL_MASK;*/ + tmp &= ~RADEON_SCLK_FORCEON_MASK; + + /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ + if (((asic == rt_rv250) && + ((INREG( regs, RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) || + ((asic == rt_rv100) && + ((INREG( regs, RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <= + RADEON_CFG_ATI_REV_A13))) + { + tmp |= RADEON_SCLK_FORCE_CP; + tmp |= RADEON_SCLK_FORCE_VIP; + } + + Radeon_OUTPLL(regs, asic, RADEON_SCLK_CNTL, tmp); + + if ((asic == rt_rv200) || + (asic == rt_rv250) || + (asic == rt_rv280)) { + tmp = Radeon_INPLL(regs, asic, RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + + /* RV200::A11 A12 RV250::A11 A12 */ + if (((asic == rt_rv200) || + (asic == rt_rv250)) && + ((INREG( regs, RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) + { + tmp |= RADEON_SCLK_MORE_FORCEON; + } + Radeon_OUTPLL(regs, asic, RADEON_SCLK_MORE_CNTL, tmp); + snooze(15000); + } + + /* RV200::A11 A12, RV250::A11 A12 */ + if (((asic == rt_rv200) || + (asic == rt_rv250)) && + ((INREG( regs, RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) + { + tmp = Radeon_INPLL(regs, asic, RADEON_PLL_PWRMGT_CNTL); + tmp |= RADEON_TCL_BYPASS_DISABLE; + Radeon_OUTPLL(regs, asic, RADEON_PLL_PWRMGT_CNTL, tmp); + } + snooze(15000); + + /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK)*/ + tmp = Radeon_INPLL(regs, asic, RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + Radeon_OUTPLL(regs, asic, RADEON_PIXCLKS_CNTL, tmp); + snooze(15000); + + tmp = Radeon_INPLL(regs, asic, RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + + Radeon_OUTPLL(regs, asic, RADEON_VCLK_ECP_CNTL, tmp); + snooze(15000); + } + SHOW_FLOW0( 3, "Dynamic Clock Scaling Enabled" ); + break; + default: + break; + } +} diff --git a/src/add-ons/kernel/drivers/graphics/radeon/init.c b/src/add-ons/kernel/drivers/graphics/radeon/init.c index 9d24a0c853..a7d13c8d59 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/init.c +++ b/src/add-ons/kernel/drivers/graphics/radeon/init.c @@ -324,6 +324,14 @@ status_t Radeon_FirstOpen( device_info *di ) if( di->asic == rt_rv100 && di->is_mobility) di->dac2_cntl = INREG( di->regs, RADEON_DAC_CNTL2 ); + // print these out to capture bios status... + if ( di->is_mobility ) { + SHOW_INFO0( 4, "Copy of Laptop Display Regs for Reference:"); + SHOW_INFO( 4, "LVDS CNTL = %8lx", INREG( di->regs, RADEON_LVDS_GEN_CNTL )); + SHOW_INFO( 4, "FP1 CNTL = %8lx", INREG( di->regs, RADEON_FP_GEN_CNTL )); + SHOW_INFO( 4, "FP2 CNTL = %8lx", INREG( di->regs, RADEON_FP2_GEN_CNTL )); + } + result = Radeon_InitPCIGART( di ); if( result < 0 ) goto err5; @@ -391,6 +399,10 @@ status_t Radeon_FirstOpen( device_info *di ) si->nonlocal_mem = (uint32 *)((uint32)si->framebuffer + dma_offset); si->nonlocal_vm_start = (uint32)si->framebuffer_pci + dma_offset;*/ + // set dynamic clocks for Mobilty chips + if (di->is_mobility && di->settings.dynamic_clocks) + Radeon_SetDynamicClock( di, 1); + return B_OK; err0: 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 7bdae3a084..205ba4744e 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon/radeon_driver.h +++ b/src/add-ons/kernel/drivers/graphics/radeon/radeon_driver.h @@ -219,6 +219,7 @@ void Radeon_WaitForFifo( device_info *di, int entries ); void Radeon_ResetEngine( device_info *di ); status_t Radeon_InitCP( device_info *di ); void Radeon_UninitCP( device_info *di ); +void Radeon_SetDynamicClock( device_info *di, int mode ); // vip.c