#include "radeon_accelerant.h"
#include "mmio.h"
#include "crtc_regs.h"
#include "fp_regs.h"
#include "pll_regs.h"
#include "pll_access.h"
#include "tv_out_regs.h"
#include "theatre_regs.h"
#include "GlobalData.h"
#include "generic.h"
status_t SET_DPMS_MODE(uint32 dpms_flags)
{
virtual_card *vc = ai->vc;
status_t
result1 = B_OK,
result2 = B_OK;
if( vc->used_crtc[0] )
result1 = Radeon_SetDPMS( ai, 0, dpms_flags );
if( vc->used_crtc[0] )
result1 = Radeon_SetDPMS( ai, 0, dpms_flags );
if( result1 == B_OK && result2 == B_OK )
return B_OK;
else
return B_ERROR;
}
uint32 DPMS_CAPABILITIES(void)
{
return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF;
}
uint32 DPMS_MODE(void)
{
return Radeon_GetDPMS( ai, ai->vc->used_crtc[0] ? 0 : 1 );
}
static void Radeon_SetDPMS_LVDS( accelerator_info *ai, int mode )
{
vuint8 *regs = ai->regs;
switch( mode ) {
case B_DPMS_ON:
OUTREGP( regs, RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON );
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:
case B_DPMS_SUSPEND:
case B_DPMS_OFF: {
uint32 old_pixclks_cntl;
old_pixclks_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL);
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, 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 );
break; }
}
}
static void Radeon_SetDPMS_DVI( accelerator_info *ai, int mode )
{
vuint8 *regs = ai->regs;
switch( mode ) {
case B_DPMS_ON:
OUTREGP( regs, RADEON_FP_GEN_CNTL, RADEON_FP_FPON | RADEON_FP_TMDS_EN,
~(RADEON_FP_FPON | RADEON_FP_TMDS_EN));
break;
case B_DPMS_STAND_BY:
case B_DPMS_SUSPEND:
case B_DPMS_OFF:
OUTREGP( regs, RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_FPON | RADEON_FP_TMDS_EN );
break;
}
}
static void Radeon_SetDPMS_FP2( accelerator_info *ai, int mode )
{
vuint8 *regs = ai->regs;
switch( mode ) {
case B_DPMS_ON:
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, 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;
}
}
static void Radeon_SetDPMS_CRT( accelerator_info *ai, int mode )
{
vuint8 *regs = ai->regs;
switch( mode ) {
case B_DPMS_ON:
OUTREGP( regs, RADEON_CRTC_EXT_CNTL, 0, ~RADEON_CRTC_DISPLAY_DIS );
break;
case B_DPMS_STAND_BY:
case B_DPMS_SUSPEND:
case B_DPMS_OFF:
OUTREGP( regs, RADEON_CRTC_EXT_CNTL,
RADEON_CRTC_DISPLAY_DIS, ~RADEON_CRTC_DISPLAY_DIS );
break;
}
}
static void Radeon_SetDPMS_TVCRT( accelerator_info *ai, int mode )
{
vuint8 *regs = ai->regs;
switch( mode ) {
case B_DPMS_ON:
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_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS),
~(RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS) );
break;
}
}
static void Radeon_SetDPMS_CRTC1( accelerator_info *ai, int mode )
{
vuint8 *regs = ai->regs;
uint32 mask = ~(RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS);
switch( mode ) {
case B_DPMS_ON:
OUTREGP( regs, RADEON_CRTC_EXT_CNTL, 0, mask );
break;
case B_DPMS_STAND_BY:
OUTREGP( regs, RADEON_CRTC_EXT_CNTL,
(RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), mask );
break;
case B_DPMS_SUSPEND:
OUTREGP( regs, RADEON_CRTC_EXT_CNTL,
(RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), mask );
break;
case B_DPMS_OFF:
OUTREGP( regs, RADEON_CRTC_EXT_CNTL,
(RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS), mask );
break;
}
switch( mode ) {
case B_DPMS_ON:
OUTREGP( regs, RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B );
Radeon_ShowCursor( ai, 0 );
break;
case B_DPMS_STAND_BY:
case B_DPMS_SUSPEND:
case B_DPMS_OFF:
OUTREGP( regs, RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B,
~(RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_CUR_EN) );
break;
}
}
static void Radeon_SetDPMS_CRTC2( accelerator_info *ai, int mode )
{
vuint8 *regs = ai->regs;
int mask = ~(RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS);
switch( mode ) {
case B_DPMS_ON:
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, 0, mask );
break;
case B_DPMS_STAND_BY:
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), mask );
break;
case B_DPMS_SUSPEND:
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), mask);
break;
case B_DPMS_OFF:
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL,
(RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS), mask);
break;
}
switch( mode ) {
case B_DPMS_ON:
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_DISP_REQ_EN_B );
Radeon_ShowCursor( ai, 1 );
break;
case B_DPMS_STAND_BY:
case B_DPMS_SUSPEND:
case B_DPMS_OFF:
OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_REQ_EN_B,
~(RADEON_CRTC2_DISP_REQ_EN_B | RADEON_CRTC2_CUR_EN) );
break;
}
}
static void Radeon_SetDPMS_TVOUT( accelerator_info *ai, int mode )
{
if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) {
OUTREG( ai->regs, RADEON_TV_LINEAR_GAIN_SETTINGS,
mode == B_DPMS_ON ? 0x01000100 : 0 );
} else {
Radeon_VIPWrite( ai, ai->si->theatre_channel, RADEON_TV_LINEAR_GAIN_SETTINGS,
mode == B_DPMS_ON ? 0x01000100 : 0 );
}
}
status_t Radeon_SetDPMS( accelerator_info *ai, int crtc_idx, int mode )
{
crtc_info *crtc = &ai->si->crtc[crtc_idx];
switch( mode ) {
case B_DPMS_ON:
case B_DPMS_STAND_BY:
case B_DPMS_SUSPEND:
case B_DPMS_OFF:
break;
default:
return B_BAD_VALUE;
}
if( crtc_idx == 0 )
Radeon_SetDPMS_CRTC1( ai, mode );
else
Radeon_SetDPMS_CRTC2( ai, mode );
if( crtc_idx == 0 || 1)
Radeon_SetDPMS_CRT( ai, mode );
if( crtc_idx == 1 || (crtc->active_displays & (dd_tv_crt | dd_ctv | dd_stv)) != 0 )
Radeon_SetDPMS_TVCRT( ai, mode );
if( (crtc->active_displays & (dd_ctv | dd_stv)) != 0 )
Radeon_SetDPMS_TVOUT( ai, mode );
if( (crtc->active_displays & dd_lvds) != 0 )
Radeon_SetDPMS_LVDS( ai, mode );
if( (crtc->active_displays & dd_dvi) != 0 )
Radeon_SetDPMS_DVI( ai, mode );
if( (crtc->active_displays & dd_dvi_ext) != 0 )
Radeon_SetDPMS_FP2( ai, mode );
return B_OK;
}
static uint32 Radeon_GetDPMS_CRTC1( accelerator_info *di )
{
uint32 tmp;
tmp = INREG( di->regs, RADEON_CRTC_EXT_CNTL );
if( (tmp & RADEON_CRTC_DISPLAY_DIS) == 0 )
return B_DPMS_ON;
if( (tmp & RADEON_CRTC_VSYNC_DIS) == 0 )
return B_DPMS_STAND_BY;
if( (tmp & RADEON_CRTC_HSYNC_DIS) == 0 )
return B_DPMS_SUSPEND;
return B_DPMS_OFF;
}
static uint32 Radeon_GetDPMS_CRTC2( accelerator_info *di )
{
uint32 tmp;
tmp = INREG( di->regs, RADEON_CRTC2_GEN_CNTL );
if( (tmp & RADEON_CRTC2_DISP_DIS) == 0 )
return B_DPMS_ON;
if( (tmp & RADEON_CRTC2_VSYNC_DIS) == 0 )
return B_DPMS_STAND_BY;
if( (tmp & RADEON_CRTC2_HSYNC_DIS) == 0 )
return B_DPMS_SUSPEND;
return B_DPMS_OFF;
}
uint32 Radeon_GetDPMS( accelerator_info *ai, int crtc_idx )
{
if( crtc_idx == 0 )
return Radeon_GetDPMS_CRTC1( ai );
else
return Radeon_GetDPMS_CRTC2( ai );
}