Patch by Euan Kirkhope:
Monitor Routing rework * mostly to fix my issues with dual monitors VGA + DVI which didn't work! ;) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20275 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
19cadc2f7d
commit
b8fb3d1705
@ -105,6 +105,97 @@ typedef enum {
|
||||
dd_dvi_ext = 64 // external DVI (only provided by few models)
|
||||
} display_device_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ddc_none_detected,
|
||||
ddc_monid,
|
||||
ddc_dvi,
|
||||
ddc_vga,
|
||||
ddc_crt2
|
||||
} radeon_ddc_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
mt_unknown = -1,
|
||||
mt_none = 0,
|
||||
mt_crt = 1,
|
||||
mt_lcd = 2,
|
||||
mt_dfp = 3,
|
||||
mt_ctv = 4,
|
||||
mt_stv = 5
|
||||
} radeon_monitor_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
connector_none,
|
||||
connector_proprietary,
|
||||
connector_crt,
|
||||
connector_dvi_i,
|
||||
connector_dvi_d,
|
||||
connector_ctv,
|
||||
connector_stv,
|
||||
connector_unsupported
|
||||
} radeon_connector_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
connector_none_atom,
|
||||
connector_vga_atom,
|
||||
connector_dvi_i_atom,
|
||||
connector_dvi_d_atom,
|
||||
connector_dvi_a_atom,
|
||||
connector_stv_atom,
|
||||
connector_ctv_atom,
|
||||
connector_lvds_atom,
|
||||
connector_digital_atom,
|
||||
connector_unsupported_atom
|
||||
} radeon_connector_type_atom;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
dac_unknown = -1,
|
||||
dac_primary = 0,
|
||||
dac_tvdac = 1
|
||||
} radeon_dac_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
tmds_unknown = -1,
|
||||
tmds_int = 0,
|
||||
tmds_ext = 1
|
||||
} radeon_tmds_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
radeon_ddc_type ddc_type;
|
||||
radeon_dac_type dac_type;
|
||||
radeon_tmds_type tmds_type;
|
||||
radeon_connector_type connector_type;
|
||||
radeon_monitor_type mon_type;
|
||||
edid1_info edid;
|
||||
bool edid_valid;
|
||||
} radeon_connector;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool has_secondary;
|
||||
|
||||
/*
|
||||
* The next two are used to make sure CRTC2 is restored before CRTC_EXT,
|
||||
* otherwise it could lead to blank screens.
|
||||
*/
|
||||
bool is_secondary_restored;
|
||||
bool restore_primary;
|
||||
|
||||
int mon_type1;
|
||||
int mon_type2;
|
||||
|
||||
bool reversed_DAC; /* TVDAC used as primary dac */
|
||||
bool reversed_TMDS; /* DDC_DVI is used for external TMDS */
|
||||
|
||||
radeon_connector port_info[2];
|
||||
} disp_entity, *ptr_disp_entity;
|
||||
|
||||
|
||||
// type of ASIC
|
||||
typedef enum {
|
||||
@ -448,6 +539,7 @@ typedef struct {
|
||||
uint8 num_crtc; // number of physical heads
|
||||
|
||||
fp_info flatpanels[2]; // info about connected flat panels (if any)
|
||||
disp_entity routing; // info if display connector routings eg DVI-I <- EXT TMDS <- DAC2 <- CRTC2
|
||||
|
||||
memory_type_info memory[mt_last]; // info about memory types
|
||||
memory_type_e nonlocal_type; // default type of non-local memory
|
||||
|
@ -8,4 +8,4 @@
|
||||
*/
|
||||
|
||||
// current version
|
||||
#define RADEON_DRIVER_VERSION "Version: 5.1.3.5"
|
||||
#define RADEON_DRIVER_VERSION "Version: 5.1.4.0"
|
||||
|
@ -834,59 +834,246 @@ static status_t Radeon_StoreFPEDID( accelerator_info *ai, const edid1_info *edid
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
static void Radeon_ConnectorInfo( accelerator_info *ai, int port, disp_entity* ptr_entity )
|
||||
{
|
||||
const char* mon;
|
||||
const char* ddc = ptr_entity->port_info[port].ddc_type == ddc_none_detected ? "None" :
|
||||
ptr_entity->port_info[port].ddc_type == ddc_monid ? "Mon ID" :
|
||||
ptr_entity->port_info[port].ddc_type == ddc_dvi ? "DVI DDC" :
|
||||
ptr_entity->port_info[port].ddc_type == ddc_vga ? "VGA DDC" :
|
||||
ptr_entity->port_info[port].ddc_type == ddc_crt2 ? "CRT2 DDC" : "Error";
|
||||
|
||||
const char* tmds = ptr_entity->port_info[port].tmds_type == tmds_unknown ? "None" :
|
||||
ptr_entity->port_info[port].tmds_type == tmds_int ? "Internal" :
|
||||
ptr_entity->port_info[port].tmds_type == tmds_ext ? "External" : "??? ";
|
||||
|
||||
const char* dac = ptr_entity->port_info[port].dac_type == dac_unknown ? "Unknown" :
|
||||
ptr_entity->port_info[port].dac_type == dac_primary ? "Primary" :
|
||||
ptr_entity->port_info[port].dac_type == dac_tvdac ? "TV / External" : "Error";
|
||||
|
||||
const char* con;
|
||||
if (ai->si->is_atombios) {
|
||||
con = ptr_entity->port_info[port].connector_type == connector_none_atom ? "None" :
|
||||
ptr_entity->port_info[port].connector_type == connector_vga_atom ? "VGA" :
|
||||
ptr_entity->port_info[port].connector_type == connector_dvi_i_atom ? "DVI-I" :
|
||||
ptr_entity->port_info[port].connector_type == connector_dvi_d_atom ? "DVI-D" :
|
||||
ptr_entity->port_info[port].connector_type == connector_dvi_a_atom ? "DVI-A" :
|
||||
ptr_entity->port_info[port].connector_type == connector_stv_atom ? "S-Video TV" :
|
||||
ptr_entity->port_info[port].connector_type == connector_ctv_atom ? "Composite TV" :
|
||||
ptr_entity->port_info[port].connector_type == connector_lvds_atom ? "LVDS" :
|
||||
ptr_entity->port_info[port].connector_type == connector_digital_atom ? "Digital" :
|
||||
ptr_entity->port_info[port].connector_type == connector_unsupported_atom ? "N/A " : "Err ";
|
||||
} else {
|
||||
con = ptr_entity->port_info[port].connector_type == connector_none ? "None" :
|
||||
ptr_entity->port_info[port].connector_type == connector_crt ? "VGA" :
|
||||
ptr_entity->port_info[port].connector_type == connector_dvi_i ? "DVI-I" :
|
||||
ptr_entity->port_info[port].connector_type == connector_dvi_d ? "DVI-D" :
|
||||
ptr_entity->port_info[port].connector_type == connector_proprietary ? "Proprietary" :
|
||||
ptr_entity->port_info[port].connector_type == connector_stv ? "S-Video TV" :
|
||||
ptr_entity->port_info[port].connector_type == connector_ctv ? "Composite TV" :
|
||||
ptr_entity->port_info[port].connector_type == connector_unsupported ? "N/A" : "Err";
|
||||
}
|
||||
|
||||
mon = ptr_entity->port_info[port].mon_type == mt_unknown ? "???" :
|
||||
ptr_entity->port_info[port].mon_type == mt_none ? "None" :
|
||||
ptr_entity->port_info[port].mon_type == mt_crt ? "CRT " :
|
||||
ptr_entity->port_info[port].mon_type == mt_lcd ? "LCD " :
|
||||
ptr_entity->port_info[port].mon_type == mt_dfp ? "DVI " :
|
||||
ptr_entity->port_info[port].mon_type == mt_ctv ? "Composite TV" :
|
||||
ptr_entity->port_info[port].mon_type == mt_stv ? "S-Video TV" : "Err ?";
|
||||
|
||||
SHOW_INFO( 2 , "Port %d:- \nMonitor: %s\nConn Type: %s\nDDC Port: %s\nTMDS Type: %s\nDAC Type: %s",
|
||||
port, mon, con, ddc, tmds, dac);
|
||||
}
|
||||
|
||||
|
||||
// detect connected displays devices
|
||||
// whished_num_heads - how many heads the requested display mode needs
|
||||
void Radeon_DetectDisplays( accelerator_info *ai )
|
||||
{
|
||||
shared_info *si = ai->si;
|
||||
|
||||
disp_entity* routes = &si->routing;
|
||||
display_device_e displays = 0;
|
||||
display_device_e controlled_displays = ai->vc->controlled_displays;
|
||||
edid1_info edid;
|
||||
int i;
|
||||
|
||||
uint32 edid_regs[] = {
|
||||
0,
|
||||
RADEON_GPIO_MONID,
|
||||
RADEON_GPIO_DVI_DDC,
|
||||
RADEON_GPIO_VGA_DDC,
|
||||
RADEON_GPIO_CRT2_DDC
|
||||
};
|
||||
|
||||
// lock hardware so noone bothers us
|
||||
Radeon_WaitForIdle( ai, true );
|
||||
|
||||
// mobile chips are for use in laptops - there must be a laptop panel
|
||||
if( si->is_mobility )
|
||||
displays |= dd_lvds;
|
||||
|
||||
// use DDC to detect monitors - if we can read DDC, there must be a monitor
|
||||
|
||||
// all non-mobility versions have a DVI port
|
||||
if( (displays & dd_lvds) == 0 &&
|
||||
Radeon_ReadEDID( ai, RADEON_GPIO_DVI_DDC, &edid ))
|
||||
{
|
||||
SHOW_FLOW0( 2, "Found monitor on DVI DDC port" );
|
||||
// there may be an analog monitor connected to DVI-I;
|
||||
// we must check EDID to see whether it's really a digital monitor
|
||||
if( edid.display.input_type == 1 ) {
|
||||
SHOW_FLOW0( 2, "Must be a DVI monitor" );
|
||||
|
||||
// store info about DVI-connected flat-panel
|
||||
if( Radeon_StoreFPEDID( ai, &edid ) == B_OK ) {
|
||||
displays |= dd_dvi;
|
||||
} else {
|
||||
SHOW_ERROR0( 2, "Disabled DVI - invalid EDID" );
|
||||
}
|
||||
} else {
|
||||
// must be the analog portion of DVI
|
||||
// I'm not sure about Radeons with one CRTC - do they have DVI-I or DVI-D?
|
||||
// anyway - if there are two CRTC, analog portion must be connected
|
||||
// to TV-DAC; if there is one CRTC, it must be the normal VGA-DAC
|
||||
if( si->num_crtc > 1 ) {
|
||||
SHOW_FLOW0( 2, "Must be an analog monitor on DVI port" );
|
||||
displays |= dd_tv_crt;
|
||||
} else {
|
||||
SHOW_FLOW0( 2, "Seems to be a CRT on VGA port!?" );
|
||||
displays |= dd_crt;
|
||||
}
|
||||
// alwats make TMDS_INT port first
|
||||
if (routes->port_info[1].tmds_type == tmds_int) {
|
||||
|
||||
radeon_connector swap_entity;
|
||||
swap_entity = routes->port_info[0];
|
||||
routes->port_info[0] = routes->port_info[1];
|
||||
routes->port_info[1] = swap_entity;
|
||||
SHOW_FLOW0( 2, "Swapping TMDS_INT to first port");
|
||||
}
|
||||
else if ( routes->port_info[0].tmds_type != tmds_int &&
|
||||
routes->port_info[1].tmds_type != tmds_int ) {
|
||||
|
||||
// no TMDS_INT port, make primary DAC port first
|
||||
// On my Inspiron 8600 both internal and external ports are
|
||||
// marked DAC_PRIMARY in BIOS. So be extra careful - only
|
||||
// swap when the first port is not DAC_PRIMARY
|
||||
if ( routes->port_info[1].dac_type == dac_primary &&
|
||||
routes->port_info[0].dac_type != dac_primary ) {
|
||||
|
||||
radeon_connector swap_entity;
|
||||
swap_entity = routes->port_info[0];
|
||||
routes->port_info[0] = routes->port_info[1];
|
||||
routes->port_info[1] = swap_entity;
|
||||
SHOW_FLOW0( 2, "Swapping Primary Dac to front");
|
||||
}
|
||||
}
|
||||
|
||||
// all chips have a standard VGA port
|
||||
if( Radeon_ReadEDID( ai, RADEON_GPIO_VGA_DDC, &edid ))
|
||||
displays |= dd_crt;
|
||||
if ( si->asic == rt_rs300 ) // RS300 only has single Dac of TV type
|
||||
{
|
||||
// For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC
|
||||
if ( routes->port_info[0].connector_type == connector_crt ) {
|
||||
routes->port_info[0].dac_type = dac_tvdac;
|
||||
routes->port_info[1].dac_type = dac_primary;
|
||||
} else {
|
||||
routes->port_info[1].dac_type = dac_primary;
|
||||
routes->port_info[0].dac_type = dac_tvdac;
|
||||
}
|
||||
} else if ( si->num_crtc == 1 ) {
|
||||
|
||||
routes->port_info[0].dac_type = dac_primary;
|
||||
}
|
||||
|
||||
// use DDC to detect monitors - if we can read DDC, there must be a monitor
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
if (routes->port_info[i].mon_type != mt_unknown ) {
|
||||
SHOW_FLOW0( 2, "known type, skpping detection" );
|
||||
continue;
|
||||
}
|
||||
|
||||
memset( &routes->port_info[i].edid , 0, sizeof(edid1_info) );
|
||||
switch ( routes->port_info[i].ddc_type ) {
|
||||
case ddc_monid:
|
||||
case ddc_dvi:
|
||||
case ddc_vga:
|
||||
case ddc_crt2:
|
||||
if ( Radeon_ReadEDID( ai, edid_regs[routes->port_info[i].ddc_type], &routes->port_info[i].edid ))
|
||||
{
|
||||
routes->port_info[i].edid_valid = true;
|
||||
SHOW_FLOW( 2, "Edid Data for CRTC %d on line %d", i, routes->port_info[i].ddc_type );
|
||||
edid_dump ( &routes->port_info[i].edid );
|
||||
} else {
|
||||
routes->port_info[i].mon_type = mt_none;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
SHOW_FLOW( 2, "No Edid Pin Assigned to CRTC %d ", i );
|
||||
routes->port_info[i].mon_type = mt_none;
|
||||
}
|
||||
|
||||
if ( routes->port_info[i].edid_valid ) {
|
||||
|
||||
if( routes->port_info[i].edid.display.input_type == 1 ) {
|
||||
SHOW_FLOW0( 2, "Must be a DVI monitor" );
|
||||
|
||||
// Note some laptops have a DVI output that uses internal TMDS,
|
||||
// when its DVI is enabled by hotkey, LVDS panel is not used.
|
||||
// In this case, the laptop is configured as DVI+VGA as a normal
|
||||
// desktop card.
|
||||
// Also for laptop, when X starts with lid closed (no DVI connection)
|
||||
// both LDVS and TMDS are disable, we still need to treat it as a LVDS panel.
|
||||
if ( routes->port_info[i].tmds_type == tmds_ext ){
|
||||
// store info about DVI-connected flat-panel
|
||||
if( Radeon_StoreFPEDID( ai, &routes->port_info[i].edid ) == B_OK ) {
|
||||
SHOW_INFO0( 2, "Found Ext Laptop DVI" );
|
||||
routes->port_info[i].mon_type = mt_dfp;
|
||||
displays |= dd_dvi_ext;
|
||||
} else {
|
||||
SHOW_ERROR0( 2, "Disabled Ext DVI - invalid EDID" );
|
||||
}
|
||||
} else {
|
||||
if( INREG( ai->regs, RADEON_FP_GEN_CNTL) & (1 << 7) || ( !si->is_mobility ) ) {
|
||||
// store info about DVI-connected flat-panel
|
||||
if( Radeon_StoreFPEDID( ai, &routes->port_info[i].edid ) == B_OK ) {
|
||||
SHOW_INFO0( 2, "Found DVI" );
|
||||
routes->port_info[i].mon_type = mt_dfp;
|
||||
displays |= dd_dvi;
|
||||
} else {
|
||||
SHOW_ERROR0( 2, "Disabled DVI - invalid EDID" );
|
||||
}
|
||||
} else {
|
||||
SHOW_INFO0( 2, "Laptop Panel Found" );
|
||||
routes->port_info[i].mon_type = mt_lcd;
|
||||
displays |= dd_lvds;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// must be the analog portion of DVI
|
||||
// I'm not sure about Radeons with one CRTC - do they have DVI-I or DVI-D?
|
||||
// anyway - if there are two CRTC, analog portion must be connected
|
||||
// to TV-DAC; if there is one CRTC, it must be the normal VGA-DAC
|
||||
if( si->num_crtc > 1 ) {
|
||||
SHOW_FLOW0( 2, "Must be an analog monitor on DVI port" );
|
||||
routes->port_info[i].mon_type = mt_crt;
|
||||
displays |= dd_tv_crt;
|
||||
} else {
|
||||
SHOW_FLOW0( 2, "Seems to be a CRT on VGA port!?" );
|
||||
routes->port_info[i].mon_type = mt_crt;
|
||||
displays |= dd_crt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( !routes->port_info[0].edid_valid ) {
|
||||
SHOW_INFO0( 2, "Searching port 0" );
|
||||
if ( si->is_mobility && (INREG( ai->regs, RADEON_BIOS_4_SCRATCH) & 4)) {
|
||||
SHOW_INFO0( 2, "Found Laptop Panel" );
|
||||
routes->port_info[0].mon_type = mt_lcd;
|
||||
displays |= dd_lvds;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !routes->port_info[1].edid_valid ) {
|
||||
|
||||
if ( si->is_mobility && (INREG( ai->regs, RADEON_FP2_GEN_CNTL) & RADEON_FP2_FPON)) {
|
||||
SHOW_INFO0( 2, "Found Ext Laptop DVI" );
|
||||
routes->port_info[1].mon_type = mt_dfp;
|
||||
displays |= dd_dvi;
|
||||
}
|
||||
}
|
||||
|
||||
if ( routes->port_info[0].mon_type == mt_none )
|
||||
{
|
||||
if ( routes->port_info[1].mon_type == mt_none ) {
|
||||
routes->port_info[0].mon_type = mt_crt;
|
||||
} else {
|
||||
radeon_connector swap_entity;
|
||||
swap_entity = routes->port_info[0];
|
||||
routes->port_info[0] = routes->port_info[1];
|
||||
routes->port_info[1] = swap_entity;
|
||||
SHOW_ERROR0( 2, "swapping active port 2 to free port 1" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
routes->reversed_DAC = false;
|
||||
if ( routes->port_info[1].dac_type == dac_tvdac ) {
|
||||
SHOW_ERROR0( 2, "Reversed dac detected (not impl. yet)" );
|
||||
routes->reversed_DAC = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// we may have overseen monitors if they don't support DDC or
|
||||
// have broken DDC data (like mine);
|
||||
@ -898,14 +1085,14 @@ void Radeon_DetectDisplays( accelerator_info *ai )
|
||||
|
||||
// all versions have a standard VGA port
|
||||
if( (displays & dd_crt) == 0 &&
|
||||
(controlled_displays && dd_crt) != 0 &&
|
||||
(controlled_displays & dd_crt) != 0 &&
|
||||
Radeon_DetectCRT( ai ))
|
||||
displays |= dd_crt;
|
||||
|
||||
// check VGA signal routed to DVI port
|
||||
// (the detection code checks whether there is hardware for that)
|
||||
if( (displays & dd_tv_crt) == 0 &&
|
||||
(controlled_displays && dd_tv_crt) != 0 &&
|
||||
(controlled_displays & dd_tv_crt) != 0 &&
|
||||
Radeon_DetectTVCRT( ai ))
|
||||
displays |= dd_tv_crt;
|
||||
|
||||
@ -920,7 +1107,10 @@ void Radeon_DetectDisplays( accelerator_info *ai )
|
||||
// if no monitor found, we define to have a CRT connected to CRT-DAC
|
||||
if( displays == 0 )
|
||||
displays = dd_crt;
|
||||
|
||||
|
||||
Radeon_ConnectorInfo( ai, 0, routes);
|
||||
Radeon_ConnectorInfo( ai, 1, routes);
|
||||
|
||||
ai->vc->connected_displays = displays;
|
||||
|
||||
RELEASE_BEN( si->cp.lock );
|
||||
|
@ -259,6 +259,223 @@ static void Radeon_GetMonType( device_info *di )
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static bool Radeon_GetConnectorInfoFromBIOS ( device_info* di )
|
||||
{
|
||||
|
||||
ptr_disp_entity ptr_entity = &di->routing;
|
||||
int i = 0, j, tmp, tmp0=0, tmp1=0;
|
||||
|
||||
int bios_header, master_data_start;
|
||||
|
||||
bios_header = RADEON_BIOS16(0x48);
|
||||
|
||||
if (di->is_atombios)
|
||||
{
|
||||
master_data_start = RADEON_BIOS16( bios_header + 32 );
|
||||
tmp = RADEON_BIOS16( master_data_start + 22);
|
||||
if (tmp) {
|
||||
int crtc = 0, id[2];
|
||||
tmp1 = RADEON_BIOS16( tmp + 4 );
|
||||
for (i=0; i<8; i++) {
|
||||
if(tmp1 & (1<<i)) {
|
||||
uint16 portinfo = RADEON_BIOS16( tmp + 6 + i * 2 );
|
||||
if (crtc < 2) {
|
||||
if ((i == 2) || (i == 6)) continue; /* ignore TV here */
|
||||
|
||||
if ( crtc == 1 ) {
|
||||
/* sharing same port with id[0] */
|
||||
if ((( portinfo >> 8) & 0xf) == id[0] ) {
|
||||
if (i == 3)
|
||||
ptr_entity->port_info[0].tmds_type = tmds_int;
|
||||
else if (i == 7)
|
||||
ptr_entity->port_info[0].tmds_type = tmds_ext;
|
||||
|
||||
if (ptr_entity->port_info[0].dac_type == dac_unknown)
|
||||
ptr_entity->port_info[0].dac_type = (portinfo & 0xf) - 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
id[crtc] = (portinfo>>8) & 0xf;
|
||||
ptr_entity->port_info[crtc].dac_type = (portinfo & 0xf) - 1;
|
||||
ptr_entity->port_info[crtc].connector_type = (portinfo>>4) & 0xf;
|
||||
if (i == 3)
|
||||
ptr_entity->port_info[crtc].tmds_type = tmds_int;
|
||||
else if (i == 7)
|
||||
ptr_entity->port_info[crtc].tmds_type = tmds_ext;
|
||||
|
||||
tmp0 = RADEON_BIOS16( master_data_start + 24);
|
||||
if( tmp0 && id[crtc] ) {
|
||||
switch (RADEON_BIOS16(tmp0 + 4 + 27 * id[crtc]) * 4)
|
||||
{
|
||||
case RADEON_GPIO_MONID:
|
||||
ptr_entity->port_info[crtc].ddc_type = ddc_monid;
|
||||
break;
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
ptr_entity->port_info[crtc].ddc_type = ddc_dvi;
|
||||
break;
|
||||
case RADEON_GPIO_VGA_DDC:
|
||||
ptr_entity->port_info[crtc].ddc_type = ddc_vga;
|
||||
break;
|
||||
case RADEON_GPIO_CRT2_DDC:
|
||||
ptr_entity->port_info[crtc].ddc_type = ddc_crt2;
|
||||
break;
|
||||
default:
|
||||
ptr_entity->port_info[crtc].ddc_type = ddc_none_detected;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
ptr_entity->port_info[crtc].ddc_type = ddc_none_detected;
|
||||
}
|
||||
crtc++;
|
||||
} else {
|
||||
/* we have already had two CRTCs assigned. the rest may share the same
|
||||
* port with the existing connector, fill in them accordingly.
|
||||
*/
|
||||
for ( j = 0; j < 2; j++ ) {
|
||||
if ((( portinfo >> 8 ) & 0xf ) == id[j] ) {
|
||||
if ( i == 3 )
|
||||
ptr_entity->port_info[j].tmds_type = tmds_int;
|
||||
else if (i == 7)
|
||||
ptr_entity->port_info[j].tmds_type = tmds_ext;
|
||||
|
||||
if ( ptr_entity->port_info[j].dac_type == dac_unknown )
|
||||
ptr_entity->port_info[j].dac_type = ( portinfo & 0xf ) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<2; i++) {
|
||||
SHOW_INFO( 2, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d",
|
||||
i, ptr_entity->port_info[i].ddc_type, ptr_entity->port_info[i].dac_type,
|
||||
ptr_entity->port_info[i].tmds_type, ptr_entity->port_info[i].connector_type);
|
||||
}
|
||||
} else {
|
||||
SHOW_INFO0( 4 , "No Device Info Table found!");
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
/* Some laptops only have one connector (VGA) listed in the connector table,
|
||||
* we need to add LVDS in as a non-DDC display.
|
||||
* Note, we can't assume the listed VGA will be filled in PortInfo[0],
|
||||
* when walking through connector table. connector_found has following meaning:
|
||||
* 0 -- nothing found,
|
||||
* 1 -- only PortInfo[0] filled,
|
||||
* 2 -- only PortInfo[1] filled,
|
||||
* 3 -- both are filled.
|
||||
*/
|
||||
int connector_found = 0;
|
||||
|
||||
if ((tmp = RADEON_BIOS16( bios_header + 0x50 ))) {
|
||||
for ( i = 1; i < 4; i++ ) {
|
||||
|
||||
if (!(RADEON_BIOS16( tmp + i * 2 )))
|
||||
break; /* end of table */
|
||||
|
||||
tmp0 = RADEON_BIOS16( tmp + i * 2 );
|
||||
if ((( tmp0 >> 12 ) & 0x0f ) == 0 )
|
||||
continue; /* no connector */
|
||||
if (connector_found > 0) {
|
||||
if (ptr_entity->port_info[tmp1].ddc_type == (( tmp0 >> 8 ) & 0x0f ))
|
||||
continue; /* same connector */
|
||||
}
|
||||
|
||||
/* internal ddc_dvi port will get assigned to portinfo[0], or if there is no ddc_dvi (like in some igps). */
|
||||
tmp1 = (((( tmp0 >> 8 ) & 0xf ) == ddc_dvi ) || ( tmp1 == 1 )) ? 0 : 1; /* determine port info index */
|
||||
|
||||
ptr_entity->port_info[tmp1].ddc_type = (tmp0 >> 8) & 0x0f;
|
||||
if (ptr_entity->port_info[tmp1].ddc_type > ddc_crt2)
|
||||
ptr_entity->port_info[tmp1].ddc_type = ddc_none_detected;
|
||||
ptr_entity->port_info[tmp1].dac_type = (tmp0 & 0x01) ? dac_tvdac : dac_primary;
|
||||
ptr_entity->port_info[tmp1].connector_type = (tmp0 >> 12) & 0x0f;
|
||||
if (ptr_entity->port_info[tmp1].connector_type > connector_unsupported)
|
||||
ptr_entity->port_info[tmp1].connector_type = connector_unsupported;
|
||||
ptr_entity->port_info[tmp1].tmds_type = ((tmp0 >> 4) & 0x01) ? tmds_ext : tmds_int;
|
||||
|
||||
/* some sanity checks */
|
||||
if (((ptr_entity->port_info[tmp1].connector_type != connector_dvi_d) &&
|
||||
(ptr_entity->port_info[tmp1].connector_type != connector_dvi_i)) &&
|
||||
ptr_entity->port_info[tmp1].tmds_type == tmds_int)
|
||||
ptr_entity->port_info[tmp1].tmds_type = tmds_unknown;
|
||||
|
||||
connector_found += (tmp1 + 1);
|
||||
}
|
||||
} else {
|
||||
SHOW_INFO0(4, "No Connector Info Table found!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (di->is_mobility)
|
||||
{
|
||||
/* For the cases where only one VGA connector is found,
|
||||
we assume LVDS is not listed in the connector table,
|
||||
add it in here as the first port.
|
||||
*/
|
||||
if ((connector_found < 3) && (ptr_entity->port_info[tmp1].connector_type == connector_crt)) {
|
||||
if (connector_found == 1) {
|
||||
memcpy (&ptr_entity->port_info[1],
|
||||
&ptr_entity->port_info[0],
|
||||
sizeof (ptr_entity->port_info[0]));
|
||||
}
|
||||
ptr_entity->port_info[0].dac_type = dac_tvdac;
|
||||
ptr_entity->port_info[0].tmds_type = tmds_unknown;
|
||||
ptr_entity->port_info[0].ddc_type = ddc_none_detected;
|
||||
ptr_entity->port_info[0].connector_type = connector_proprietary;
|
||||
|
||||
SHOW_INFO0( 4 , "lvds port is not in connector table, added in.");
|
||||
if (connector_found == 0)
|
||||
connector_found = 1;
|
||||
else
|
||||
connector_found = 3;
|
||||
}
|
||||
|
||||
if ((tmp = RADEON_BIOS16( bios_header + 0x42 ))) {
|
||||
if ((tmp0 = RADEON_BIOS16( tmp + 0x15 ))) {
|
||||
if ((tmp1 = RADEON_BIOS16( tmp0 + 2 ) & 0x07)) {
|
||||
ptr_entity->port_info[0].ddc_type = tmp1;
|
||||
if (ptr_entity->port_info[0].ddc_type > ddc_crt2) {
|
||||
SHOW_INFO( 4, "unknown ddctype %d found",
|
||||
ptr_entity->port_info[0].ddc_type);
|
||||
ptr_entity->port_info[0].ddc_type = ddc_none_detected;
|
||||
}
|
||||
SHOW_INFO0( 4, "lcd ddc info table found!");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (connector_found == 2) {
|
||||
memcpy (&ptr_entity->port_info[0],
|
||||
&ptr_entity->port_info[1],
|
||||
sizeof (ptr_entity->port_info[0]));
|
||||
ptr_entity->port_info[1].dac_type = dac_unknown;
|
||||
ptr_entity->port_info[1].tmds_type = tmds_unknown;
|
||||
ptr_entity->port_info[1].ddc_type = ddc_none_detected;
|
||||
ptr_entity->port_info[1].connector_type = connector_none;
|
||||
connector_found = 1;
|
||||
}
|
||||
|
||||
if (connector_found == 0) {
|
||||
SHOW_INFO0( 4, "no connector found in connector info table.");
|
||||
} else {
|
||||
SHOW_INFO( 2, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d",
|
||||
0, ptr_entity->port_info[0].ddc_type, ptr_entity->port_info[0].dac_type,
|
||||
ptr_entity->port_info[0].tmds_type, ptr_entity->port_info[0].connector_type);
|
||||
|
||||
}
|
||||
if (connector_found == 3) {
|
||||
SHOW_INFO( 2, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d",
|
||||
1, ptr_entity->port_info[1].ddc_type, ptr_entity->port_info[1].dac_type,
|
||||
ptr_entity->port_info[1].tmds_type, ptr_entity->port_info[1].connector_type);
|
||||
}
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// get flat panel info (does only make sense for Laptops
|
||||
// with integrated display, but looking for it doesn't hurt,
|
||||
// who knows which strange kind of combination is out there?)
|
||||
@ -740,6 +957,29 @@ status_t Radeon_ReadBIOSData( device_info *di )
|
||||
goto err1;
|
||||
|
||||
Radeon_GetPLLInfo( di );
|
||||
|
||||
// setup defaults
|
||||
di->routing.port_info[0].mon_type = mt_unknown;
|
||||
di->routing.port_info[0].ddc_type = ddc_none_detected;
|
||||
di->routing.port_info[0].dac_type = dac_unknown;
|
||||
di->routing.port_info[0].tmds_type = tmds_unknown;
|
||||
di->routing.port_info[0].connector_type = connector_none;
|
||||
|
||||
if ( !Radeon_GetConnectorInfoFromBIOS( di ) )
|
||||
{
|
||||
di->routing.port_info[0].mon_type = mt_unknown;
|
||||
di->routing.port_info[0].ddc_type = ddc_none_detected;
|
||||
di->routing.port_info[0].dac_type = dac_tvdac;
|
||||
di->routing.port_info[0].tmds_type = tmds_unknown;
|
||||
di->routing.port_info[0].connector_type = connector_proprietary;
|
||||
|
||||
di->routing.port_info[1].mon_type = mt_unknown;
|
||||
di->routing.port_info[1].ddc_type = ddc_none_detected;
|
||||
di->routing.port_info[1].dac_type = dac_primary;
|
||||
di->routing.port_info[1].tmds_type = tmds_ext;
|
||||
di->routing.port_info[1].connector_type = connector_crt;
|
||||
|
||||
}
|
||||
Radeon_GetFPData( di );
|
||||
Radeon_DetectRAM( di );
|
||||
|
||||
|
@ -260,6 +260,7 @@ status_t Radeon_FirstOpen( device_info *di )
|
||||
si->panel_pwr_delay = di->si->panel_pwr_delay;
|
||||
si->acc_dma = di->acc_dma;
|
||||
|
||||
memcpy(&si->routing, &di->routing, sizeof(disp_entity));
|
||||
|
||||
// detecting theatre channel in kernel would lead to code duplication,
|
||||
// so we let the first accelerant take care of it
|
||||
|
@ -113,6 +113,7 @@ typedef struct device_info {
|
||||
bool acc_dma;
|
||||
|
||||
fp_info fp_info;
|
||||
disp_entity routing;
|
||||
|
||||
general_pll_info pll;
|
||||
ram_info ram;
|
||||
|
Loading…
Reference in New Issue
Block a user