intel_extreme: probe DP AUX or/and DDC on DDI ports
* the VBT tells whether DDI ports can have both DP and HDMI/DVI as outputs. * tested on Dell Optiplex 9020 Gen7/Haswell with an HDMI/DP adapter on a DP connector. * avoids enabling a down DDI port when an EDID is found: the display isn't setup by the BIOS. Change-Id: I69487a2fcb74899d7c22d04e955e776b0e739151 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5317 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
parent
07d5dba065
commit
fe3aff01c0
|
@ -234,6 +234,13 @@ Port::GetEDID(edid1_info* edid, bool forceRead)
|
||||||
if (fEDIDState == B_OK) {
|
if (fEDIDState == B_OK) {
|
||||||
TRACE("%s: found EDID information!\n", PortName());
|
TRACE("%s: found EDID information!\n", PortName());
|
||||||
edid_dump(&fEDIDInfo);
|
edid_dump(&fEDIDInfo);
|
||||||
|
} else if (SetupI2cFallback(&bus) == B_OK) {
|
||||||
|
fEDIDState = ddc2_read_edid1(&bus, &fEDIDInfo, NULL, NULL);
|
||||||
|
|
||||||
|
if (fEDIDState == B_OK) {
|
||||||
|
TRACE("%s: found EDID information!\n", PortName());
|
||||||
|
edid_dump(&fEDIDInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +277,13 @@ Port::SetupI2c(i2c_bus *bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Port::SetupI2cFallback(i2c_bus *bus)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Port::GetPLLLimits(pll_limits& limits)
|
Port::GetPLLLimits(pll_limits& limits)
|
||||||
{
|
{
|
||||||
|
@ -453,7 +467,19 @@ Port::_IsDisplayPortInVBT()
|
||||||
if (!_IsPortInVBT(&foundIndex))
|
if (!_IsPortInVBT(&foundIndex))
|
||||||
return false;
|
return false;
|
||||||
child_device_config& config = gInfo->shared_info->device_configs[foundIndex];
|
child_device_config& config = gInfo->shared_info->device_configs[foundIndex];
|
||||||
return config.aux_channel > 0;
|
return config.aux_channel > 0 && (config.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Port::_IsHdmiInVBT()
|
||||||
|
{
|
||||||
|
uint32 foundIndex = 0;
|
||||||
|
if (!_IsPortInVBT(&foundIndex))
|
||||||
|
return false;
|
||||||
|
child_device_config& config = gInfo->shared_info->device_configs[foundIndex];
|
||||||
|
return config.ddc_pin > 0 && ((config.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0
|
||||||
|
|| (config.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -607,7 +633,7 @@ Port::_DpAuxSendReceiveHook(const struct i2c_bus *bus, uint32 slaveAddress,
|
||||||
const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength)
|
const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
DigitalDisplayInterface* port = (DigitalDisplayInterface*)bus->cookie;
|
Port* port = (Port*)bus->cookie;
|
||||||
return port->_DpAuxSendReceive(slaveAddress, writeBuffer, writeLength, readBuffer, readLength);
|
return port->_DpAuxSendReceive(slaveAddress, writeBuffer, writeLength, readBuffer, readLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,9 +719,12 @@ Port::_DpAuxTransfer(dp_aux_msg* message)
|
||||||
else if (result < B_OK)
|
else if (result < B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
switch(message->reply & DP_AUX_NATIVE_REPLY_MASK) {
|
switch (message->reply & DP_AUX_NATIVE_REPLY_MASK) {
|
||||||
case DP_AUX_NATIVE_REPLY_ACK:
|
case DP_AUX_NATIVE_REPLY_ACK:
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
case DP_AUX_NATIVE_REPLY_NACK:
|
||||||
|
TRACE("%s: aux native reply nack\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
case DP_AUX_NATIVE_REPLY_DEFER:
|
case DP_AUX_NATIVE_REPLY_DEFER:
|
||||||
TRACE("%s: aux reply defer received. Snoozing.\n", __func__);
|
TRACE("%s: aux reply defer received. Snoozing.\n", __func__);
|
||||||
snooze(400);
|
snooze(400);
|
||||||
|
@ -2181,6 +2210,21 @@ DigitalDisplayInterface::SetupI2c(i2c_bus *bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DigitalDisplayInterface::SetupI2cFallback(i2c_bus *bus)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
const uint32 deviceConfigCount = gInfo->shared_info->device_config_count;
|
||||||
|
if (gInfo->shared_info->device_type.Generation() >= 6 && deviceConfigCount > 0
|
||||||
|
&& _IsDisplayPortInVBT() && _IsHdmiInVBT()) {
|
||||||
|
return Port::SetupI2c(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DigitalDisplayInterface::IsConnected()
|
DigitalDisplayInterface::IsConnected()
|
||||||
{
|
{
|
||||||
|
@ -2310,17 +2354,11 @@ DigitalDisplayInterface::IsConnected()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pipeState = read32(pipeReg);
|
pipeState = read32(pipeReg);
|
||||||
if (!(pipeState & PIPE_DDI_FUNC_CTL_ENABLE)) {
|
if ((pipeState & PIPE_DDI_FUNC_CTL_ENABLE) == 0) {
|
||||||
TRACE("%s: Connected but port down: enabling port on pipe nr %" B_PRIx32 "\n", __func__, pipeCnt + 1);
|
TRACE("%s: Connected but port down\n", __func__);
|
||||||
//fixme: turn on port and power
|
return false;
|
||||||
pipeState |= PIPE_DDI_FUNC_CTL_ENABLE;
|
|
||||||
pipeState &= ~PIPE_DDI_SELECT_MASK;
|
|
||||||
pipeState |= (((uint32)PortIndex()) - 1) << PIPE_DDI_SELECT_SHIFT;
|
|
||||||
//fixme: set mode to DVI mode for now (b26..24 = %001)
|
|
||||||
write32(pipeReg, pipeState);
|
|
||||||
TRACE("%s: PIPE_DDI_FUNC_CTL after: 0x%" B_PRIx32 "\n", __func__, read32(pipeReg));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
TRACE("%s: No pipe available, ignoring connected screen\n", __func__);
|
TRACE("%s: No pipe available, ignoring connected screen\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ virtual status_t Power(bool enabled);
|
||||||
virtual status_t GetEDID(edid1_info* edid,
|
virtual status_t GetEDID(edid1_info* edid,
|
||||||
bool forceRead = false);
|
bool forceRead = false);
|
||||||
virtual status_t SetupI2c(struct i2c_bus *bus);
|
virtual status_t SetupI2c(struct i2c_bus *bus);
|
||||||
|
virtual status_t SetupI2cFallback(struct i2c_bus *bus);
|
||||||
|
|
||||||
virtual status_t GetPLLLimits(pll_limits& limits);
|
virtual status_t GetPLLLimits(pll_limits& limits);
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ static status_t _SetI2CSignals(void* cookie, int clock,
|
||||||
int data);
|
int data);
|
||||||
bool _IsPortInVBT(uint32* foundIndex = NULL);
|
bool _IsPortInVBT(uint32* foundIndex = NULL);
|
||||||
bool _IsDisplayPortInVBT();
|
bool _IsDisplayPortInVBT();
|
||||||
|
bool _IsHdmiInVBT();
|
||||||
bool _IsEDPPort();
|
bool _IsEDPPort();
|
||||||
status_t _SetupDpAuxI2c(struct i2c_bus *bus);
|
status_t _SetupDpAuxI2c(struct i2c_bus *bus);
|
||||||
|
|
||||||
|
@ -231,6 +233,7 @@ virtual status_t Power(bool enabled);
|
||||||
|
|
||||||
virtual status_t SetPipe(Pipe* pipe);
|
virtual status_t SetPipe(Pipe* pipe);
|
||||||
virtual status_t SetupI2c(i2c_bus *bus);
|
virtual status_t SetupI2c(i2c_bus *bus);
|
||||||
|
virtual status_t SetupI2cFallback(struct i2c_bus *bus);
|
||||||
|
|
||||||
virtual bool IsConnected();
|
virtual bool IsConnected();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue