diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index c138938784..b4739f8ba4 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -109,7 +109,7 @@ struct register_info { typedef struct { bool valid; - uint32 hwPin; // GPIO hardware pin on GPU + uint32 hwPin; // GPIO hardware pin on GPU bool hwCapable; // can do hw assisted i2c uint32 sclMaskReg; @@ -152,7 +152,8 @@ typedef struct { uint32 type; uint32 flags; uint32 lvdsFlags; - uint16 gpioID; + uint16 i2cPinIndex; // id of gpio pin for i2c communications + uint16 hpdPinIndex; // id of gpio pin for hotplug detection struct encoder_info encoder; struct encoder_info encoderExternal; // TODO struct radeon_hpd hpd; diff --git a/src/add-ons/accelerants/radeon_hd/connector.cpp b/src/add-ons/accelerants/radeon_hd/connector.cpp index 473f9208c6..ccb16b2043 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.cpp +++ b/src/add-ons/accelerants/radeon_hd/connector.cpp @@ -120,17 +120,17 @@ bool connector_read_edid(uint32 connectorIndex, edid1_info* edid) { // ensure things are sane - uint32 gpioID = gConnector[connectorIndex]->gpioID; - if (gGPIOInfo[gpioID]->valid == false) { + uint32 i2cPinIndex = gConnector[connectorIndex]->i2cPinIndex; + if (gGPIOInfo[i2cPinIndex]->valid == false) { ERROR("%s: invalid gpio %" B_PRIu32 " for connector %" B_PRIu32 "\n", - __func__, gpioID, connectorIndex); + __func__, i2cPinIndex, connectorIndex); return false; } i2c_bus bus; ddc2_init_timing(&bus); - bus.cookie = (void*)gGPIOInfo[gpioID]; + bus.cookie = (void*)gGPIOInfo[i2cPinIndex]; bus.set_signals = &gpio_set_i2c_bit; bus.get_signals = &gpio_get_i2c_bit; @@ -244,37 +244,113 @@ connector_read_mode_lvds(uint32 connectorIndex, display_mode* mode) } -status_t -connector_attach_gpio(uint32 connectorIndex, uint8 hwPin) +static status_t +gpio_manual_probe(uint8 hwPin) { - gConnector[connectorIndex]->gpioID = 0; + // manually populate some information on a GPIO pin based on pin id + + int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT); + uint16 tableOffset; + uint16 tableSize; + + struct _ATOM_GPIO_PIN_LUT* gpioInfo; + + if (atom_parse_data_header(gAtomContext, index, &tableSize, NULL, NULL, + &tableOffset)) { + ERROR("%s: could't read GPIO_Pin_LUT table from AtomBIOS index %d!\n", + __func__, index); + } + gpioInfo = (struct _ATOM_GPIO_PIN_LUT*)(gAtomContext->bios + tableOffset); + + int numIndices = (tableSize - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_GPIO_PIN_ASSIGNMENT); + + // Find the next available GPIO pin index + int gpioIndex; + for(gpioIndex = 0; gpioIndex < ATOM_MAX_SUPPORTED_DEVICE; gpioIndex++) { + if (!gGPIOInfo[gpioIndex]->valid) + break; + } + + ATOM_GPIO_PIN_ASSIGNMENT* pin = gpioInfo->asGPIO_Pin; + for (int i = 0; i < numIndices; i++) { + if (hwPin == pin->ucGPIO_ID) { + gGPIOInfo[gpioIndex]->valid = true; + gGPIOInfo[gpioIndex]->hwPin = hwPin; + #if 0 + gGPIOInfo[gpioIndex]->hwReg + = le16_to_cpu(pin->usGpioPin_AIndex) * 4; + gGPIOInfo[gpioIndex]->hwMask + = (1 << pin->ucGpioPinBitShift); + #endif + return B_OK; + } + pin = (ATOM_GPIO_PIN_ASSIGNMENT*)((uint8*)pin + + sizeof(ATOM_GPIO_PIN_ASSIGNMENT)); + } + return B_ERROR; +} + + +static status_t +connector_attach_gpio_i2c(uint32 connectorIndex, uint8 hwPin) +{ + gConnector[connectorIndex]->i2cPinIndex = 0; for (uint32 i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { if (gGPIOInfo[i]->hwPin != hwPin) continue; - gConnector[connectorIndex]->gpioID = i; + gConnector[connectorIndex]->i2cPinIndex = i; return B_OK; } - TRACE("%s: couldn't find GPIO for connector %" B_PRIu32 "\n", - __func__, connectorIndex); + // We couldnt find the GPIO pin in the known GPIO pins. + TRACE("%s: can't find GPIO pin 0x%" B_PRIX8 " for connector %" B_PRIu32 "\n", + __func__, hwPin, connectorIndex); return B_ERROR; } +static status_t +connector_attach_gpio_hpd(uint32 connectorIndex, uint8 hwPin) +{ + gConnector[connectorIndex]->hpdPinIndex = 0; + + for (uint32 i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { + if (gGPIOInfo[i]->hwPin != hwPin) + continue; + gConnector[connectorIndex]->hpdPinIndex = i; + return B_OK; + } + // We couldnt find the GPIO pin in the known GPIO pins. + // Lets call the GPIO lookup table to add in hpd pins manually + + gpio_manual_probe(hwPin); + + // Try again... + for (uint32 i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { + if (gGPIOInfo[i]->hwPin != hwPin) + continue; + gConnector[connectorIndex]->hpdPinIndex = i; + return B_OK; + } + + TRACE("%s: can't find GPIO pin 0x%" B_PRIX8 " for connector %" B_PRIu32 "\n", + __func__, hwPin, connectorIndex); + return B_ERROR; +} + + status_t gpio_probe() { radeon_shared_info &info = *gInfo->shared_info; int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); - - uint8 tableMajor; - uint8 tableMinor; uint16 tableOffset; uint16 tableSize; if (atom_parse_data_header(gAtomContext, index, &tableSize, - &tableMajor, &tableMinor, &tableOffset) != B_OK) { + NULL, NULL, &tableOffset) != B_OK) { ERROR("%s: could't read GPIO_I2C_Info table from AtomBIOS index %d!\n", __func__, index); return B_ERROR; @@ -452,7 +528,7 @@ connector_probe_legacy() gConnector[connectorIndex]->encoderExternal.valid = false; // encoder_is_external(encoderID); - connector_attach_gpio(connectorIndex, ci.sucI2cId.ucAccess); + connector_attach_gpio_i2c(connectorIndex, ci.sucI2cId.ucAccess); pll_limit_probe(&gConnector[connectorIndex]->encoder.pll); @@ -680,7 +756,7 @@ connector_probe() <= ATOM_MAX_OBJECT_RECORD_NUMBER) { ATOM_I2C_RECORD* i2cRecord; ATOM_I2C_ID_CONFIG_ACCESS* i2cConfig; - //ATOM_HPD_INT_RECORD* hpd_record; + ATOM_HPD_INT_RECORD* hpdRecord; switch (record->ucRecordType) { case ATOM_I2C_RECORD_TYPE: @@ -689,12 +765,13 @@ connector_probe() i2cConfig = (ATOM_I2C_ID_CONFIG_ACCESS*) &i2cRecord->sucI2cId; - // attach i2c gpio information for connector - connector_attach_gpio(connectorIndex, + connector_attach_gpio_i2c(connectorIndex, i2cConfig->ucAccess); break; case ATOM_HPD_INT_RECORD_TYPE: - // TODO: HPD (Hot Plug) + hpdRecord = (ATOM_HPD_INT_RECORD*)record; + connector_attach_gpio_hpd(connectorIndex, + hpdRecord->ucHPDIntGPIOID); break; } @@ -749,17 +826,22 @@ debug_connectors() for (uint32 id = 0; id < ATOM_MAX_SUPPORTED_DEVICE; id++) { if (gConnector[id]->valid == true) { uint32 connectorType = gConnector[id]->type; - uint16 gpioID = gConnector[id]->gpioID; + uint16 i2cPinIndex = gConnector[id]->i2cPinIndex; + uint16 hpdPinIndex = gConnector[id]->hpdPinIndex; 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", - gGPIOInfo[gpioID]->hwPin); - ERROR(" + gpio valid: %s\n", - gGPIOInfo[gpioID]->valid ? "true" : "false"); - + ERROR(" + i2c gpio table id: %" B_PRIu16 "\n", i2cPinIndex); + ERROR(" - gpio hw pin: 0x%" B_PRIX32 "\n", + gGPIOInfo[i2cPinIndex]->hwPin); + ERROR(" - gpio valid: %s\n", + gGPIOInfo[i2cPinIndex]->valid ? "true" : "false"); + ERROR(" + hpd gpio table id: %" B_PRIu16 "\n", hpdPinIndex); + ERROR(" - gpio hw pin: 0x%" B_PRIX32 "\n", + gGPIOInfo[hpdPinIndex]->hwPin); + ERROR(" - gpio valid: %s\n", + gGPIOInfo[hpdPinIndex]->valid ? "true" : "false"); encoder_info* encoder = &gConnector[id]->encoder; ERROR(" + encoder: %s\n", get_encoder_name(encoder->type)); diff --git a/src/add-ons/accelerants/radeon_hd/connector.h b/src/add-ons/accelerants/radeon_hd/connector.h index 302cc00158..78c8015175 100644 --- a/src/add-ons/accelerants/radeon_hd/connector.h +++ b/src/add-ons/accelerants/radeon_hd/connector.h @@ -61,7 +61,6 @@ const int kConnectorConvert[] = { status_t gpio_probe(); -status_t connector_attach_gpio(uint32 id, uint8 hwPin); bool connector_read_edid(uint32 connector, edid1_info* edid); bool connector_read_mode_lvds(uint32 connectorIndex, display_mode* mode); diff --git a/src/add-ons/accelerants/radeon_hd/displayport.cpp b/src/add-ons/accelerants/radeon_hd/displayport.cpp index 3e6b5435e3..5ebe5bf7f9 100644 --- a/src/add-ons/accelerants/radeon_hd/displayport.cpp +++ b/src/add-ons/accelerants/radeon_hd/displayport.cpp @@ -448,9 +448,9 @@ dp_setup_connectors() TRACE("%s: found dp connector on index %" B_PRIu32 "\n", __func__, index); - uint32 gpioID = gConnector[index]->gpioID; + uint32 i2cPinIndex = gConnector[index]->i2cPinIndex; - uint32 auxPin = gGPIOInfo[gpioID]->hwPin; + uint32 auxPin = gGPIOInfo[i2cPinIndex]->hwPin; dpInfo->auxPin = auxPin; uint8 auxMessage[DP_DPCD_SIZE]; @@ -824,8 +824,8 @@ dp_link_train(uint8 crtcID) uint32 linkEnumeration = gConnector[connectorIndex]->encoder.linkEnumeration; - uint32 gpioID = gConnector[connectorIndex]->gpioID; - uint32 hwPin = gGPIOInfo[gpioID]->hwPin; + uint32 i2cPinIndex = gConnector[connectorIndex]->i2cPinIndex; + uint32 hwPin = gGPIOInfo[i2cPinIndex]->hwPin; uint32 dpEncoderID = 0; if (encoder_pick_dig(connectorIndex) > 0)