#include "radeon_accelerant.h"
#include "generic.h"
#include "GlobalData.h"
void Radeon_DetectMultiMode( virtual_card *vc, display_mode *mode )
{
(void)vc;
mode->timing.flags &= ~RADEON_MODE_MASK;
if( (mode->flags & B_SCROLL) == 0 )
return;
SHOW_FLOW0( 3, "possibly combine mode" );
mode->flags &= ~B_SCROLL;
mode->timing.flags &= ~RADEON_MODE_POSITION_MASK;
if( mode->virtual_width == 2 * mode->timing.h_display ) {
SHOW_FLOW0( 2, "horizontal combine mode" );
mode->timing.flags |= RADEON_MODE_POSITION_HORIZONTAL;
mode->timing.flags &= ~RADEON_MODE_MASK;
mode->timing.flags |= RADEON_MODE_COMBINE;
} else if( mode->virtual_height == 2 * mode->timing.v_display ) {
SHOW_FLOW0( 2, "vertical combine mode" );
mode->timing.flags |= RADEON_MODE_POSITION_VERTICAL;
mode->timing.flags &= ~RADEON_MODE_MASK;
mode->timing.flags |= RADEON_MODE_COMBINE;
} else {
SHOW_FLOW0( 2, "wasn't really a combine mode" );
mode->timing.flags &= ~RADEON_MODE_MASK;
mode->flags |= B_SCROLL;
}
}
void Radeon_VerifyMultiMode( virtual_card *vc, shared_info *si, display_mode *mode )
{
int num_usable_crtcs = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none;
if( si->num_crtc > 1 )
num_usable_crtcs += vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none;
if( num_usable_crtcs < 2 ) {
SHOW_FLOW0( 2, "only one monitor - disabling any multi-mon mode" );
if( (mode->timing.flags & RADEON_MODE_MASK) == RADEON_MODE_COMBINE )
mode->flags |= B_SCROLL;
mode->timing.flags &= ~RADEON_MODE_MASK;
mode->timing.flags |= RADEON_MODE_STANDARD;
}
}
void Radeon_HideMultiMode( virtual_card *vc, display_mode *mode )
{
(void) vc;
if( (mode->timing.flags & RADEON_MODE_MASK) == RADEON_MODE_COMBINE )
mode->flags |= B_SCROLL;
}
void Radeon_InitMultiModeVars(
accelerator_info *ai, display_mode *mode )
{
virtual_card *vc = ai->vc;
shared_info *si = ai->si;
uint32 x, y;
vc->eff_width = mode->timing.h_display;
vc->eff_height = mode->timing.v_display;
if( vc->used_crtc[0] ) {
si->crtc[0].rel_x = 0;
si->crtc[0].rel_y = 0;
}
if( vc->used_crtc[1] ) {
si->crtc[1].rel_x = 0;
si->crtc[1].rel_y = 0;
}
switch( mode->timing.flags & RADEON_MODE_MASK ) {
case RADEON_MODE_COMBINE:
if( (mode->timing.flags & RADEON_MODE_POSITION_MASK) == RADEON_MODE_POSITION_HORIZONTAL ) {
vc->eff_width = 2 * mode->timing.h_display;
x = mode->timing.h_display;
y = 0;
} else {
vc->eff_height = 2 * mode->timing.v_display;
x = 0;
y = mode->timing.v_display;
}
SHOW_FLOW( 3, "relative position of second screen: %d, %d", x, y );
if( !vc->swap_displays ) {
si->crtc[1].rel_x = x;
si->crtc[1].rel_y = y;
} else {
si->crtc[0].rel_x = x;
si->crtc[0].rel_y = y;
}
break;
default:
break;
}
}
static const uint32 private2be[] = {
0, 1, 3, 4, 103, 3, 102 };
status_t Radeon_CheckMultiMonTunnel( virtual_card *vc, display_mode *mode,
const display_mode *low, const display_mode *high, bool *isTunneled )
{
if( (mode->timing.flags & RADEON_MODE_MULTIMON_REQUEST) != 0 &&
(mode->timing.flags & RADEON_MODE_MULTIMON_REPLY) == 0 )
{
mode->timing.flags &= ~RADEON_MODE_MULTIMON_REQUEST;
mode->timing.flags |= RADEON_MODE_MULTIMON_REPLY;
*isTunneled = true;
return B_OK;
}
if( mode->space != 0 || low->space != 0 || high->space != 0
|| low->virtual_width != 0xffff || low->virtual_height != 0xffff
|| high->virtual_width != 0 || high->virtual_height != 0
|| mode->timing.pixel_clock != 0
|| low->timing.pixel_clock != 'TKTK' || high->timing.pixel_clock != 'KTKT' )
{
*isTunneled = false;
return B_OK;
}
*isTunneled = true;
switch( mode->h_display_start ) {
case ms_swap:
switch( mode->v_display_start ) {
case 0:
mode->timing.flags = vc->swap_displays;
return B_OK;
case 1:
vc->swap_displays = mode->timing.flags != 0;
vc->enforce_mode_change = true;
Radeon_WriteSettings( vc );
return B_OK;
}
break;
case ms_use_laptop_panel:
if( (vc->connected_displays & dd_lvds) == 0 )
return B_ERROR;
switch( mode->v_display_start ) {
case 0:
mode->timing.flags = vc->use_laptop_panel;
return B_OK;
case 1:
vc->use_laptop_panel = mode->timing.flags != 0;
vc->enforce_mode_change = true;
Radeon_WriteSettings( vc );
return B_OK;
}
break;
case ms_tv_standard:
switch( mode->v_display_start ) {
case 0:
mode->timing.flags = private2be[vc->tv_standard];
return B_OK;
case 1:
switch( mode->timing.flags ) {
case 0: vc->tv_standard = ts_off; break;
case 1: vc->tv_standard = ts_ntsc; break;
case 2: break;
case 3: vc->tv_standard = ts_pal_bdghi; break;
case 4: vc->tv_standard = ts_pal_m; break;
case 5: break;
case 6: break;
case 101: break;
case 102: vc->tv_standard = ts_pal_60; break;
case 103: vc->tv_standard = ts_pal_nc; break;
}
SHOW_FLOW( 1, "set tv_standard (internal %d, public %d)",
vc->tv_standard, mode->timing.flags );
vc->enforce_mode_change = true;
Radeon_WriteSettings( vc );
return B_OK;
case 2: {
uint32 idx = mode->timing.flags;
if( idx < sizeof( private2be ) / sizeof( private2be[0] ) &&
idx < 3 ) {
mode->timing.flags = private2be[idx];
return B_OK;
} else
return B_ERROR;
}
}
}
return B_ERROR;
}
bool Radeon_NeedsSecondPort( display_mode *mode )
{
switch( mode->timing.flags & RADEON_MODE_MASK ) {
case RADEON_MODE_COMBINE:
return true;
default:
return false;
}
}
bool Radeon_DifferentPorts( display_mode *mode )
{
switch( mode->timing.flags & RADEON_MODE_MASK ) {
case RADEON_MODE_COMBINE:
return 2;
default:
return 1;
}
}