diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.cpp b/src/add-ons/accelerants/radeon_hd/accelerant.cpp index 569cc82a68..94d50f319c 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.cpp +++ b/src/add-ons/accelerants/radeon_hd/accelerant.cpp @@ -256,6 +256,12 @@ radeon_init_accelerant(int device) // detect physical 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) { TRACE("%s: couldn't detect supported connectors!\n", __func__); return status; diff --git a/src/add-ons/accelerants/radeon_hd/display.cpp b/src/add-ons/accelerants/radeon_hd/display.cpp index 4c834d480e..b3b8ca732e 100644 --- a/src/add-ons/accelerants/radeon_hd/display.cpp +++ b/src/add-ons/accelerants/radeon_hd/display.cpp @@ -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 { struct _ATOM_SUPPORTED_DEVICES_INFO info; struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; @@ -261,21 +259,28 @@ detect_connectors_legacy() return B_ERROR; } - union atom_supported_devices *supported_devices; - supported_devices - = (union atom_supported_devices *) + union atom_supported_devices *supportedDevices; + supportedDevices = (union atom_supported_devices *) (gAtomContext->bios + tableOffset); - uint16 device_support - = B_LENDIAN_TO_HOST_INT16(supported_devices->info.usDeviceSupport); + uint16 deviceSupport + = B_LENDIAN_TO_HOST_INT16(supportedDevices->info.usDeviceSupport); - int32 i; - for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { + uint32 maxDevice; - 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 - if ((device_support & (1 << i)) == 0) + if ((deviceSupport & (1 << i)) == 0) continue; if (i == ATOM_DEVICE_CV_INDEX) { @@ -285,57 +290,63 @@ detect_connectors_legacy() } ATOM_CONNECTOR_INFO_I2C ci - = supported_devices->info.asConnInfo[i]; + = supportedDevices->info.asConnInfo[i]; - gConnector[i]->type - = connector_convert_legacy[ - ci.sucConnectorInfo.sbfAccess.bfConnectorType]; + gConnector[connectorIndex]->type = connector_convert_legacy[ + 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 " of 0x%" B_PRIX8 "\n", __func__, i, ci.sucConnectorInfo.sbfAccess.bfConnectorType); continue; } - // uint8 dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; - // gConnector[i]->line_mux = ci.sucI2cId.ucAccess; // TODO: give tv unique connector ids // Always set CRT1 and CRT2 as VGA, some cards incorrectly set // VGA ports as DVI 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; - gConnector[i]->encoder.flags = (1 << i); + uint8 dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; + uint32 encoderObject = encoder_object_lookup((1 << i), dac); - // TODO: add the encoder - #if 0 - radeon_add_atom_encoder(dev, - radeon_get_encoder_enum(dev, - (1 << i), - dac), - (1 << i), - 0); - #endif + gConnector[connectorIndex]->valid = true; + gConnector[connectorIndex]->encoder.flags = (1 << i); + gConnector[connectorIndex]->encoder.valid = true; + gConnector[connectorIndex]->encoder.objectID + = (encoderObject & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + + radeon_gpu_i2c_attach(connectorIndex, ci.sucI2cId.ucAccess); + + //gConnector[connectorIndex]->encoder.isExternal + // = encoderExternal; + + pll_limit_probe(&gConnector[connectorIndex]->encoder.pll); + + connectorIndex++; } // TODO: combine shared 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) { TRACE("%s: connector #%" B_PRId32 " is %s\n", __func__, i, 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; } -#endif // r600+ diff --git a/src/add-ons/accelerants/radeon_hd/display.h b/src/add-ons/accelerants/radeon_hd/display.h index 49250c6542..3b937ef6bd 100644 --- a/src/add-ons/accelerants/radeon_hd/display.h +++ b/src/add-ons/accelerants/radeon_hd/display.h @@ -58,7 +58,7 @@ const int connector_convert[] = { }; 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_crt_ranges(uint32 crtid); status_t detect_displays(); diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp b/src/add-ons/accelerants/radeon_hd/encoder.cpp index dfd1bda3f9..2701b27395 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.cpp +++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp @@ -929,3 +929,79 @@ encoder_output_lock(bool lock) 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; +} diff --git a/src/add-ons/accelerants/radeon_hd/encoder.h b/src/add-ons/accelerants/radeon_hd/encoder.h index ab60e401a8..ad358e1447 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.h +++ b/src/add-ons/accelerants/radeon_hd/encoder.h @@ -21,6 +21,8 @@ void encoder_output_lock(bool lock); void encoder_crtc_scratch(uint8 crtcID); void encoder_dpms_scratch(uint8 crtcID, bool power); void encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode); +uint32 encoder_object_lookup(uint32 encoderFlags, uint8 dacID); + #endif /* RADEON_HD_ENCODER_H */