Add legacy card connectior detection using table method

* attempt AtomBIOS table probe first, then fallback to legacy method if
  no connectors found (or table version is too old)
* add function to look up object info on older cards
* dcc still needs some work on old cards
* my X1200 IGP gets video now
This commit is contained in:
Alexander von Gluck IV
2011-11-12 19:04:17 -06:00
parent 9638d7f4aa
commit 91affb2da4
5 changed files with 128 additions and 33 deletions
@@ -256,6 +256,12 @@ radeon_init_accelerant(int device)
// detect physical connectors // detect physical connectors
status = detect_connectors(); status = detect_connectors();
if (status != B_OK) {
TRACE("%s: falling back to legacy connector detection.\n", __func__);
status = detect_connectors_legacy();
}
if (status != B_OK) { if (status != B_OK) {
TRACE("%s: couldn't detect supported connectors!\n", __func__); TRACE("%s: couldn't detect supported connectors!\n", __func__);
return status; return status;
+43 -32
View File
@@ -237,8 +237,6 @@ detect_crt_ranges(uint32 crtid)
} }
// TODO: only used on r4xx, r5xx, and rs600/rs690/rs740
#if 0
union atom_supported_devices { union atom_supported_devices {
struct _ATOM_SUPPORTED_DEVICES_INFO info; struct _ATOM_SUPPORTED_DEVICES_INFO info;
struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2;
@@ -261,21 +259,28 @@ detect_connectors_legacy()
return B_ERROR; return B_ERROR;
} }
union atom_supported_devices *supported_devices; union atom_supported_devices *supportedDevices;
supported_devices supportedDevices = (union atom_supported_devices *)
= (union atom_supported_devices *)
(gAtomContext->bios + tableOffset); (gAtomContext->bios + tableOffset);
uint16 device_support uint16 deviceSupport
= B_LENDIAN_TO_HOST_INT16(supported_devices->info.usDeviceSupport); = B_LENDIAN_TO_HOST_INT16(supportedDevices->info.usDeviceSupport);
int32 i; uint32 maxDevice;
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
gConnector[i]->valid = false; if (tableMajor > 1)
maxDevice = ATOM_MAX_SUPPORTED_DEVICE;
else
maxDevice = ATOM_MAX_SUPPORTED_DEVICE_INFO;
uint32 i;
uint32 connectorIndex = 0;
for (i = 0; i < maxDevice; i++) {
gConnector[connectorIndex]->valid = false;
// check if this connector is used // check if this connector is used
if ((device_support & (1 << i)) == 0) if ((deviceSupport & (1 << i)) == 0)
continue; continue;
if (i == ATOM_DEVICE_CV_INDEX) { if (i == ATOM_DEVICE_CV_INDEX) {
@@ -285,57 +290,63 @@ detect_connectors_legacy()
} }
ATOM_CONNECTOR_INFO_I2C ci ATOM_CONNECTOR_INFO_I2C ci
= supported_devices->info.asConnInfo[i]; = supportedDevices->info.asConnInfo[i];
gConnector[i]->type gConnector[connectorIndex]->type = connector_convert_legacy[
= connector_convert_legacy[ ci.sucConnectorInfo.sbfAccess.bfConnectorType];
ci.sucConnectorInfo.sbfAccess.bfConnectorType];
if (gConnector[i]->type == VIDEO_CONNECTOR_UNKNOWN) { if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_UNKNOWN) {
TRACE("%s: skipping unknown connector at %" B_PRId32 TRACE("%s: skipping unknown connector at %" B_PRId32
" of 0x%" B_PRIX8 "\n", __func__, i, " of 0x%" B_PRIX8 "\n", __func__, i,
ci.sucConnectorInfo.sbfAccess.bfConnectorType); ci.sucConnectorInfo.sbfAccess.bfConnectorType);
continue; continue;
} }
// uint8 dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
// gConnector[i]->line_mux = ci.sucI2cId.ucAccess;
// TODO: give tv unique connector ids // TODO: give tv unique connector ids
// Always set CRT1 and CRT2 as VGA, some cards incorrectly set // Always set CRT1 and CRT2 as VGA, some cards incorrectly set
// VGA ports as DVI // VGA ports as DVI
if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX)
gConnector[i]->type = VIDEO_CONNECTOR_VGA; gConnector[connectorIndex]->type = VIDEO_CONNECTOR_VGA;
gConnector[i]->valid = true; uint8 dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
gConnector[i]->encoder.flags = (1 << i); uint32 encoderObject = encoder_object_lookup((1 << i), dac);
// TODO: add the encoder gConnector[connectorIndex]->valid = true;
#if 0 gConnector[connectorIndex]->encoder.flags = (1 << i);
radeon_add_atom_encoder(dev, gConnector[connectorIndex]->encoder.valid = true;
radeon_get_encoder_enum(dev, gConnector[connectorIndex]->encoder.objectID
(1 << i), = (encoderObject & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
dac),
(1 << i), radeon_gpu_i2c_attach(connectorIndex, ci.sucI2cId.ucAccess);
0);
#endif //gConnector[connectorIndex]->encoder.isExternal
// = encoderExternal;
pll_limit_probe(&gConnector[connectorIndex]->encoder.pll);
connectorIndex++;
} }
// TODO: combine shared connectors // TODO: combine shared connectors
// TODO: add connectors // TODO: add connectors
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE_INFO; i++) { for (i = 0; i < maxDevice; i++) {
if (gConnector[i]->valid == true) { if (gConnector[i]->valid == true) {
TRACE("%s: connector #%" B_PRId32 " is %s\n", __func__, i, TRACE("%s: connector #%" B_PRId32 " is %s\n", __func__, i,
get_connector_name(gConnector[i]->type)); get_connector_name(gConnector[i]->type));
} }
} }
if (connectorIndex == 0) {
TRACE("%s: zero connectors found using legacy detection\n", __func__);
return B_ERROR;
}
return B_OK; return B_OK;
} }
#endif
// r600+ // r600+
+1 -1
View File
@@ -58,7 +58,7 @@ const int connector_convert[] = {
}; };
status_t init_registers(register_info* reg, uint8 crtid); status_t init_registers(register_info* reg, uint8 crtid);
// status_t detect_connectors_legacy(); status_t detect_connectors_legacy();
status_t detect_connectors(); status_t detect_connectors();
status_t detect_crt_ranges(uint32 crtid); status_t detect_crt_ranges(uint32 crtid);
status_t detect_displays(); status_t detect_displays();
@@ -929,3 +929,79 @@ encoder_output_lock(bool lock)
Write32(OUT, R600_BIOS_6_SCRATCH, biosScratch6); Write32(OUT, R600_BIOS_6_SCRATCH, biosScratch6);
} }
uint32
encoder_object_lookup(uint32 encoderFlags, uint8 dacID)
{
// used on older cards to take a guess at the encoder
// objectID
radeon_shared_info &info = *gInfo->shared_info;
uint32 ret = 0;
switch (encoderFlags) {
case ATOM_DEVICE_CRT1_SUPPORT:
case ATOM_DEVICE_TV1_SUPPORT:
case ATOM_DEVICE_TV2_SUPPORT:
case ATOM_DEVICE_CRT2_SUPPORT:
case ATOM_DEVICE_CV_SUPPORT:
switch (dacID) {
case 1:
if ((info.chipsetID == RADEON_RS400)
|| (info.chipsetID == RADEON_RS480))
ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
else if (info.chipsetID >= RADEON_RS600)
ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
else
ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
break;
case 2:
if (info.chipsetID >= RADEON_RS600)
ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
else {
ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
}
break;
case 3: // external dac
if (info.chipsetID >= RADEON_RS600)
ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
else
ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
break;
}
break;
case ATOM_DEVICE_LCD1_SUPPORT:
if (info.chipsetID >= RADEON_RS600)
ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
else
ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
break;
case ATOM_DEVICE_DFP1_SUPPORT:
if ((info.chipsetID == RADEON_RS400)
|| (info.chipsetID == RADEON_RS480))
ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
else if (info.chipsetID >= RADEON_RS600)
ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
else
ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
break;
case ATOM_DEVICE_LCD2_SUPPORT:
case ATOM_DEVICE_DFP2_SUPPORT:
if ((info.chipsetID == RADEON_RS600)
|| (info.chipsetID == RADEON_RS690)
|| (info.chipsetID == RADEON_RS740))
ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
else if (info.chipsetID >= RADEON_RS600)
ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
else
ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
break;
case ATOM_DEVICE_DFP3_SUPPORT:
ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
break;
}
return ret;
}
@@ -21,6 +21,8 @@ void encoder_output_lock(bool lock);
void encoder_crtc_scratch(uint8 crtcID); void encoder_crtc_scratch(uint8 crtcID);
void encoder_dpms_scratch(uint8 crtcID, bool power); void encoder_dpms_scratch(uint8 crtcID, bool power);
void encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode); void encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode);
uint32 encoder_object_lookup(uint32 encoderFlags, uint8 dacID);
#endif /* RADEON_HD_ENCODER_H */ #endif /* RADEON_HD_ENCODER_H */