Patch by Euan Kirkhope:

* Laptop LCD Backlight rework + powermanagement


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20276 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-03-01 09:38:11 +00:00
parent b8fb3d1705
commit df647a5c3d
7 changed files with 460 additions and 39 deletions
+1 -1
View File
@@ -8,4 +8,4 @@
*/
// current version
#define RADEON_DRIVER_VERSION "Version: 5.1.4.0"
#define RADEON_DRIVER_VERSION "Version: 5.1.4.5"
+37 -36
View File
@@ -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;
}
+51 -2
View File
@@ -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 );
}
}
}
}
@@ -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;
@@ -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;
}
}
@@ -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:
@@ -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