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) {
|
||||
TRACE("%s: found EDID information!\n", PortName());
|
||||
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
|
||||
Port::GetPLLLimits(pll_limits& limits)
|
||||
{
|
||||
|
@ -453,7 +467,19 @@ Port::_IsDisplayPortInVBT()
|
|||
if (!_IsPortInVBT(&foundIndex))
|
||||
return false;
|
||||
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)
|
||||
{
|
||||
CALLED();
|
||||
DigitalDisplayInterface* port = (DigitalDisplayInterface*)bus->cookie;
|
||||
Port* port = (Port*)bus->cookie;
|
||||
return port->_DpAuxSendReceive(slaveAddress, writeBuffer, writeLength, readBuffer, readLength);
|
||||
}
|
||||
|
||||
|
@ -693,9 +719,12 @@ Port::_DpAuxTransfer(dp_aux_msg* message)
|
|||
else if (result < B_OK)
|
||||
return result;
|
||||
|
||||
switch(message->reply & DP_AUX_NATIVE_REPLY_MASK) {
|
||||
switch (message->reply & DP_AUX_NATIVE_REPLY_MASK) {
|
||||
case DP_AUX_NATIVE_REPLY_ACK:
|
||||
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:
|
||||
TRACE("%s: aux reply defer received. Snoozing.\n", __func__);
|
||||
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
|
||||
DigitalDisplayInterface::IsConnected()
|
||||
{
|
||||
|
@ -2310,17 +2354,11 @@ DigitalDisplayInterface::IsConnected()
|
|||
break;
|
||||
}
|
||||
pipeState = read32(pipeReg);
|
||||
if (!(pipeState & PIPE_DDI_FUNC_CTL_ENABLE)) {
|
||||
TRACE("%s: Connected but port down: enabling port on pipe nr %" B_PRIx32 "\n", __func__, pipeCnt + 1);
|
||||
//fixme: turn on port and power
|
||||
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;
|
||||
if ((pipeState & PIPE_DDI_FUNC_CTL_ENABLE) == 0) {
|
||||
TRACE("%s: Connected but port down\n", __func__);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
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,
|
||||
bool forceRead = false);
|
||||
virtual status_t SetupI2c(struct i2c_bus *bus);
|
||||
virtual status_t SetupI2cFallback(struct i2c_bus *bus);
|
||||
|
||||
virtual status_t GetPLLLimits(pll_limits& limits);
|
||||
|
||||
|
@ -77,6 +78,7 @@ static status_t _SetI2CSignals(void* cookie, int clock,
|
|||
int data);
|
||||
bool _IsPortInVBT(uint32* foundIndex = NULL);
|
||||
bool _IsDisplayPortInVBT();
|
||||
bool _IsHdmiInVBT();
|
||||
bool _IsEDPPort();
|
||||
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 SetupI2c(i2c_bus *bus);
|
||||
virtual status_t SetupI2cFallback(struct i2c_bus *bus);
|
||||
|
||||
virtual bool IsConnected();
|
||||
|
||||
|
|
Loading…
Reference in New Issue