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