radeon_hd: Add support for external encoders
* Some encoders are bridges (DVO) and some encoders can act like bridges (UNIPHY). Probe for encoders further out in the display path and set them up properly. * Debug output support for external encoders * Fix cases where we should use external encoder information vs main encoder info.
This commit is contained in:
@@ -167,6 +167,7 @@ typedef struct {
|
||||
uint32 lvdsFlags;
|
||||
uint16 gpioID;
|
||||
struct encoder_info encoder;
|
||||
struct encoder_info encoderExternal;
|
||||
// TODO struct radeon_hpd hpd;
|
||||
} connector_info;
|
||||
|
||||
|
||||
@@ -445,8 +445,10 @@ connector_probe_legacy()
|
||||
gConnector[connectorIndex]->encoder.objectID = encoderID;
|
||||
gConnector[connectorIndex]->encoder.type
|
||||
= encoder_type_lookup(encoderID, (1 << i));
|
||||
gConnector[connectorIndex]->encoder.isExternal
|
||||
= encoder_is_external(encoderID);
|
||||
|
||||
// TODO: Eval external encoders on legacy connector probe
|
||||
gConnector[connectorIndex]->encoderExternal.valid = false;
|
||||
// encoder_is_external(encoderID);
|
||||
|
||||
connector_attach_gpio(connectorIndex, ci.sucI2cId.ucAccess);
|
||||
|
||||
@@ -584,7 +586,6 @@ connector_probe()
|
||||
|
||||
if (graphicObjectType == GRAPH_OBJECT_TYPE_ENCODER) {
|
||||
// Found an encoder
|
||||
// TODO: it may be possible to have more then one encoder
|
||||
int32 k;
|
||||
for (k = 0; k < encoderObject->ucNumberOfObjects; k++) {
|
||||
uint16 encoderObjectRaw
|
||||
@@ -629,20 +630,42 @@ connector_probe()
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set up found connector
|
||||
connector->encoder.valid = true;
|
||||
connector->encoder.flags = connectorFlags;
|
||||
connector->encoder.objectID = encoderID;
|
||||
connector->encoder.type = encoderType;
|
||||
connector->encoder.linkEnumeration
|
||||
= (encoderObjectRaw & ENUM_ID_MASK)
|
||||
>> ENUM_ID_SHIFT;
|
||||
connector->encoder.isExternal
|
||||
= encoder_is_external(encoderID);
|
||||
connector->encoder.isDPBridge
|
||||
= encoder_is_dp_bridge(encoderID);
|
||||
// External encoders are behind DVO or UNIPHY
|
||||
if(encoder_is_external(encoderID)) {
|
||||
encoder_info* encoder
|
||||
= &connector->encoderExternal;
|
||||
encoder->isExternal = true;
|
||||
|
||||
pll_limit_probe(&connector->encoder.pll);
|
||||
// Set up found connector
|
||||
encoder->valid = true;
|
||||
encoder->flags = connectorFlags;
|
||||
encoder->objectID = encoderID;
|
||||
encoder->type = encoderType;
|
||||
encoder->linkEnumeration
|
||||
= (encoderObjectRaw & ENUM_ID_MASK)
|
||||
>> ENUM_ID_SHIFT;
|
||||
encoder->isDPBridge
|
||||
= encoder_is_dp_bridge(encoderID);
|
||||
|
||||
pll_limit_probe(&encoder->pll);
|
||||
} else {
|
||||
encoder_info* encoder
|
||||
= &connector->encoder;
|
||||
encoder->isExternal = false;
|
||||
|
||||
// Set up found connector
|
||||
encoder->valid = true;
|
||||
encoder->flags = connectorFlags;
|
||||
encoder->objectID = encoderID;
|
||||
encoder->type = encoderType;
|
||||
encoder->linkEnumeration
|
||||
= (encoderObjectRaw & ENUM_ID_MASK)
|
||||
>> ENUM_ID_SHIFT;
|
||||
encoder->isDPBridge
|
||||
= encoder_is_dp_bridge(encoderID);
|
||||
|
||||
pll_limit_probe(&encoder->pll);
|
||||
}
|
||||
}
|
||||
}
|
||||
// END if object is encoder
|
||||
@@ -728,90 +751,96 @@ debug_connectors()
|
||||
for (uint32 id = 0; id < ATOM_MAX_SUPPORTED_DEVICE; id++) {
|
||||
if (gConnector[id]->valid == true) {
|
||||
uint32 connectorType = gConnector[id]->type;
|
||||
uint32 encoderType = gConnector[id]->encoder.type;
|
||||
uint16 encoderID = gConnector[id]->encoder.objectID;
|
||||
uint32 encoderFlags = gConnector[id]->encoder.flags;
|
||||
uint16 gpioID = gConnector[id]->gpioID;
|
||||
|
||||
ERROR("Connector #%" B_PRIu32 ")\n", id);
|
||||
ERROR(" + connector: %s\n", get_connector_name(connectorType));
|
||||
ERROR(" + gpio table id: %" B_PRIu16 "\n", gpioID);
|
||||
ERROR(" + gpio hw pin: 0x%" B_PRIX32 "\n",
|
||||
ERROR(" + connector: %s\n", get_connector_name(connectorType));
|
||||
ERROR(" + gpio table id: %" B_PRIu16 "\n", gpioID);
|
||||
ERROR(" + gpio hw pin: 0x%" B_PRIX32 "\n",
|
||||
gGPIOInfo[gpioID]->hwPin);
|
||||
ERROR(" + gpio valid: %s\n",
|
||||
ERROR(" + gpio valid: %s\n",
|
||||
gGPIOInfo[gpioID]->valid ? "true" : "false");
|
||||
ERROR(" + encoder: %s\n", get_encoder_name(encoderType));
|
||||
ERROR(" - id: %" B_PRIu16 "\n", encoderID);
|
||||
ERROR(" - type: %s\n",
|
||||
encoder_name_lookup(encoderID));
|
||||
ERROR(" - enumeration: %" B_PRIu32 "\n",
|
||||
gConnector[id]->encoder.linkEnumeration);
|
||||
|
||||
bool attribute = false;
|
||||
ERROR(" - attributes:\n");
|
||||
if (gConnector[id]->encoder.isExternal == true) {
|
||||
attribute = true;
|
||||
ERROR(" * is external\n");
|
||||
}
|
||||
if (gConnector[id]->encoder.isDPBridge == true) {
|
||||
attribute = true;
|
||||
ERROR(" * is DisplayPort bridge\n");
|
||||
}
|
||||
if (attribute == false)
|
||||
ERROR(" * no extra attributes\n");
|
||||
encoder_info* encoder = &gConnector[id]->encoder;
|
||||
ERROR(" + encoder: %s\n", get_encoder_name(encoder->type));
|
||||
ERROR(" - id: %" B_PRIu16 "\n", encoder->objectID);
|
||||
ERROR(" - type: %s\n",
|
||||
encoder_name_lookup(encoder->objectID));
|
||||
ERROR(" - enumeration: %" B_PRIu32 "\n",
|
||||
encoder->linkEnumeration);
|
||||
|
||||
encoder = &gConnector[id]->encoderExternal;
|
||||
|
||||
ERROR(" - is bridge: %s\n",
|
||||
encoder->valid ? "true" : "false");
|
||||
|
||||
if (!encoder->valid)
|
||||
ERROR(" + external encoder: none\n");
|
||||
else {
|
||||
ERROR(" + external encoder: %s\n",
|
||||
get_encoder_name(encoder->type));
|
||||
ERROR(" - valid: true\n");
|
||||
ERROR(" - id: %" B_PRIu16 "\n",
|
||||
encoder->objectID);
|
||||
ERROR(" - type: %s\n",
|
||||
encoder_name_lookup(encoder->objectID));
|
||||
ERROR(" - enumeration: %" B_PRIu32 "\n",
|
||||
encoder->linkEnumeration);
|
||||
}
|
||||
|
||||
uint32 encoderFlags = gConnector[id]->encoder.flags;
|
||||
bool flags = false;
|
||||
ERROR(" - flags:\n");
|
||||
ERROR(" + flags:\n");
|
||||
if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
|
||||
ERROR(" * device CRT1 support\n");
|
||||
ERROR(" * device CRT1 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
|
||||
ERROR(" * device CRT2 support\n");
|
||||
ERROR(" * device CRT2 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
|
||||
ERROR(" * device LCD1 support\n");
|
||||
ERROR(" * device LCD1 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_LCD2_SUPPORT) != 0) {
|
||||
ERROR(" * device LCD2 support\n");
|
||||
ERROR(" * device LCD2 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
|
||||
ERROR(" * device TV1 support\n");
|
||||
ERROR(" * device TV1 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
|
||||
ERROR(" * device CV support\n");
|
||||
ERROR(" * device CV support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
|
||||
ERROR(" * device DFP1 support\n");
|
||||
ERROR(" * device DFP1 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
|
||||
ERROR(" * device DFP2 support\n");
|
||||
ERROR(" * device DFP2 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
|
||||
ERROR(" * device DFP3 support\n");
|
||||
ERROR(" * device DFP3 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) {
|
||||
ERROR(" * device DFP4 support\n");
|
||||
ERROR(" * device DFP4 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) {
|
||||
ERROR(" * device DFP5 support\n");
|
||||
ERROR(" * device DFP5 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if ((encoderFlags & ATOM_DEVICE_DFP6_SUPPORT) != 0) {
|
||||
ERROR(" * device DFP6 support\n");
|
||||
ERROR(" * device DFP6 support\n");
|
||||
flags = true;
|
||||
}
|
||||
if (flags == false)
|
||||
ERROR(" * no known flags\n");
|
||||
ERROR(" * no known flags\n");
|
||||
}
|
||||
}
|
||||
ERROR("==========================================\n");
|
||||
|
||||
@@ -55,10 +55,11 @@ encoder_init()
|
||||
break;
|
||||
}
|
||||
|
||||
if ((info.chipsetFlags & CHIP_APU) != 0
|
||||
&& gConnector[id]->encoder.isExternal) {
|
||||
encoder_external_setup(id, 0,
|
||||
EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
|
||||
if ((info.chipsetFlags & CHIP_APU) != 0) {
|
||||
if (gConnector[id]->encoderExternal.valid == true) {
|
||||
encoder_external_setup(id, 0,
|
||||
EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,7 +353,7 @@ encoder_mode_set(uint8 id, uint32 pixelClock)
|
||||
break;
|
||||
}
|
||||
|
||||
if (gConnector[connectorIndex]->encoder.isExternal == true) {
|
||||
if (gConnector[connectorIndex]->encoderExternal.valid == true) {
|
||||
if ((info.chipsetFlags & CHIP_APU) != 0) {
|
||||
// aka DCE 4.1
|
||||
encoder_external_setup(connectorIndex, pixelClock,
|
||||
@@ -709,6 +710,15 @@ encoder_external_setup(uint32 connectorIndex, uint32 pixelClock, int command)
|
||||
{
|
||||
TRACE("%s\n", __func__);
|
||||
|
||||
encoder_info* encoder
|
||||
= &gConnector[connectorIndex]->encoderExternal;
|
||||
|
||||
if (encoder->valid != true) {
|
||||
ERROR("%s: connector %" B_PRIu32 " doesn't have a valid "
|
||||
"external encoder!", __func__, connectorIndex);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
uint8 tableMajor;
|
||||
uint8 tableMinor;
|
||||
|
||||
@@ -790,8 +800,8 @@ encoder_external_setup(uint32 connectorIndex, uint32 pixelClock, int command)
|
||||
args.v3.sExtEncoder.ucLaneNum = 4;
|
||||
}
|
||||
|
||||
uint16 encoderFlags
|
||||
= gConnector[connectorIndex]->encoder.flags;
|
||||
uint16 encoderFlags = encoder->flags;
|
||||
|
||||
switch ((encoderFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) {
|
||||
case GRAPH_OBJECT_ENUM_ID1:
|
||||
TRACE("%s: external encoder 1\n", __func__);
|
||||
@@ -909,9 +919,7 @@ encoder_analog_load_detect(uint32 connectorIndex)
|
||||
{
|
||||
TRACE("%s\n", __func__);
|
||||
|
||||
uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
|
||||
|
||||
if (encoder_is_external(encoderID))
|
||||
if (gConnector[connectorIndex]->encoderExternal.valid == true)
|
||||
return encoder_dig_load_detect(connectorIndex);
|
||||
|
||||
return encoder_dac_load_detect(connectorIndex);
|
||||
@@ -1074,12 +1082,8 @@ transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
|
||||
index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
|
||||
break;
|
||||
default:
|
||||
// Multiple encoders can be wired to a single connector
|
||||
// An example is UNIPHY -> DP -> TRAVIS -> LVDS
|
||||
ERROR("%s: BUG: guessing UNIPHY as this isn't a dig encoder!\n",
|
||||
__func__);
|
||||
index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
|
||||
break;
|
||||
ERROR("%s: BUG: dig setup run on non-dig encoder!\n", __func__);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
@@ -1116,7 +1120,7 @@ transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
|
||||
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
|
||||
|
||||
bool isDP = connector_is_dp(connectorIndex);
|
||||
bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
|
||||
bool linkB = gConnector[connectorIndex]->encoderExternal.linkEnumeration
|
||||
== GRAPH_OBJECT_ENUM_ID2 ? true : false;
|
||||
|
||||
uint8 dpClock = 0;
|
||||
|
||||
Reference in New Issue
Block a user