Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/common/displayport/inc/dp_configcaps.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ namespace DisplayPort
virtual void overrideOptimalLinkRate(LinkRate optimalLinkRate) = 0;

virtual bool isDpcdOffline() = 0;
virtual bool isVirtualSinkDpcdFallback() = 0;
virtual void setVirtualSinkDpcdFallback(bool bEnable) = 0;
virtual void setAuxBus(AuxBus * bus) = 0;
virtual NvU32 getVideoFallbackSupported() = 0;
//
Expand Down Expand Up @@ -596,6 +598,7 @@ namespace DisplayPort
AuxRetry bus;
Timer * timer;
bool dpcdOffline;
bool bVirtualSinkDpcdFallback;
bool bGrantsPostLtRequest;
bool pc2Disabled;
bool uprequestEnable;
Expand Down Expand Up @@ -795,7 +798,8 @@ namespace DisplayPort

public:
DPCDHALImpl(AuxBus * bus, Timer * timer)
: bus(bus), timer(timer), bGrantsPostLtRequest(false), uprequestEnable(false),
: bus(bus), timer(timer), bVirtualSinkDpcdFallback(false),
bGrantsPostLtRequest(false), uprequestEnable(false),
upstreamIsSource(false), bMultistream(false), bGpuFECSupported(false),
bBypassILREdpRevCheck(false), overrideDpcdMaxLinkRate(0),
overrideDpcdRev(0), gpuDPSupportedVersions(0)
Expand Down Expand Up @@ -834,6 +838,16 @@ namespace DisplayPort
return dpcdOffline;
}

bool isVirtualSinkDpcdFallback()
{
return bVirtualSinkDpcdFallback;
}

void setVirtualSinkDpcdFallback(bool bEnable)
{
bVirtualSinkDpcdFallback = bEnable;
}

void setDPCDOffline(bool bOffline)
{
dpcdOffline = bOffline;
Expand Down
1 change: 1 addition & 0 deletions src/common/displayport/inc/dp_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ namespace DisplayPort

// Notify library of hotplug/IRQ
virtual void notifyLongPulse(bool statusConnected) = 0;
virtual void notifyVirtualSinkLongPulse(bool statusConnected) = 0;
virtual void notifyShortPulse() = 0;

// Notify Library when ACPI initialization is done
Expand Down
1 change: 1 addition & 0 deletions src/common/displayport/inc/dp_connectorimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ namespace DisplayPort
virtual void disconnectDeviceList();
void notifyLongPulseInternal(bool statusConnected);
virtual void notifyLongPulse(bool status);
virtual void notifyVirtualSinkLongPulse(bool status);
virtual void notifyShortPulse();
virtual Group * newGroup();
virtual void destroy();
Expand Down
19 changes: 18 additions & 1 deletion src/common/displayport/src/dp_configcaps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,21 @@ void DPCDHALImpl::parseAndReadCaps()
// Set an invalid state here and make sure we REMEMBER we couldn't get the caps
caps.revisionMajor = 0;
dpcdOffline = true;
if (bVirtualSinkDpcdFallback)
{
//
// Forced/sink-less connector (EDID override, no AUX): fall back to
// fake caps so discovery can proceed and create a device.
//
populateFakeDpcd();
caps.revisionMinor = 0x4;
}
return;
}

// reset the faked dpcd flag since real LT should be possible now.
dpcdOffline = false;
bVirtualSinkDpcdFallback = false;

// reset edp revision to 0
caps.eDpRevision = 0;
Expand Down Expand Up @@ -634,6 +644,14 @@ bool DPCDHALImpl::getSDPExtnForColorimetry()
{
bool bSDPExtnForColorimetry = false;
NvU8 byte = 0;
if (dpcdOffline && bVirtualSinkDpcdFallback)
{
//
// Forced/sink-less connector: claim VSC SDP colorimetry support so
// HDR signaling can be enabled. No real sink interprets the SDP.
//
return true;
}
if (caps.extendedRxCapsPresent)
{
if (AuxRetry::ack == bus.read(NV_DPCD14_EXTENDED_DPRX_FEATURE_ENUM_LIST, &byte, sizeof byte))
Expand Down Expand Up @@ -3180,4 +3198,3 @@ DPCDHAL * DisplayPort::MakeDPCDHAL(AuxBus * bus, Timer * timer, MainLink * main
return new DPCDHALImpl(bus, timer);
}
}

14 changes: 13 additions & 1 deletion src/common/displayport/src/dp_connectorimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7348,6 +7348,7 @@ void ConnectorImpl::notifyLongPulse(bool statusConnected)
{
NvU32 muxState = 0;
NV_DPTRACE_INFO(HOTPLUG, statusConnected, connectorActive, previousPlugged);
hal->setVirtualSinkDpcdFallback(false);

if (!connectorActive)
{
Expand Down Expand Up @@ -7427,6 +7428,18 @@ void ConnectorImpl::notifyLongPulse(bool statusConnected)
this->notifyLongPulseInternal(statusConnected);
}

void ConnectorImpl::notifyVirtualSinkLongPulse(bool statusConnected)
{
if (!connectorActive)
{
DP_PRINTF(DP_ERROR, "DP> Got a virtual-sink long pulse before any connector is active!!");
return;
}

hal->setVirtualSinkDpcdFallback(statusConnected);
this->notifyLongPulseInternal(statusConnected);
}

/*!
* @brief Compute the max BW required across all devices and try to allocate that BW
*
Expand Down Expand Up @@ -9313,4 +9326,3 @@ void ConnectorImpl::ensureMstNodesPoweredUp(Group * target)
}
}
}

39 changes: 39 additions & 0 deletions src/common/displayport/src/dp_deviceimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,15 @@ NvBool DeviceImpl::getDSCSupport()
}
}

else if (hal->isVirtualSinkDpcdFallback())
{
//
// Forced/sink-less connector (EDID override, no AUX): assume the
// virtual sink can decompress DSC so that high-bandwidth modes pass
// validation. The stream is never decoded by a real device.
//
dscCaps.bDSCDecompressionSupported = true;
}
else
{
DP_PRINTF(DP_ERROR, "DP-DEV> DSC Support AUX READ failed for %s!", address.toString(sb));
Expand Down Expand Up @@ -2308,6 +2317,12 @@ bool DeviceImpl::getFECSupport()
bFECSupported = this->bandwidth.enum_path.bPathFECCapable;
}

else if (hal->isVirtualSinkDpcdFallback())
{
// Forced/sink-less connector: claim FEC so the DSC path is usable.
bFECSupported = true;
}

else if (AuxBus::success == this->getDpcdData(NV_DPCD14_FEC_CAPABILITY,
&byte, sizeof(byte), &size, &nakReason))
{
Expand Down Expand Up @@ -2560,6 +2575,30 @@ bool DeviceImpl::readAndParseDSCCaps()
if(AuxBus::success != this->getDpcdData(NV_DPCD14_DSC_SUPPORT,
&rawDscCaps[0], sizeof(rawDscCaps), &sizeCompleted, &nakReason))
{
if (hal->isVirtualSinkDpcdFallback())
{
//
// Forced/sink-less connector: synthesize DSC decoder caps
// modeled on a typical DSC 1.2 4K high-refresh monitor.
//
rawDscCaps[0x0] = 0x01; // decompression supported
rawDscCaps[0x1] = 0x21; // DSC algorithm revision 1.2
rawDscCaps[0x2] = 0x00; // RC buffer block size
rawDscCaps[0x3] = 0x0F; // RC buffer size
rawDscCaps[0x4] = 0xFF; // slice caps 1: up to 12 slices
rawDscCaps[0x5] = 0x03; // line buffer bit depth: 12
rawDscCaps[0x6] = 0x01; // block prediction supported
rawDscCaps[0x7] = 0xFF; // max bits per pixel LSB
rawDscCaps[0x8] = 0x03; // max bits per pixel MSB (1023/16 bpp)
rawDscCaps[0x9] = 0x1F; // color formats: RGB + all YCbCr
rawDscCaps[0xA] = 0x0E; // color depth: 8/10/12 bpc
rawDscCaps[0xB] = 0xEE; // peak throughput 1000 MP/s both modes
rawDscCaps[0xC] = 0x10; // max slice width 5120 px
rawDscCaps[0xD] = 0x00; // slice caps 2
rawDscCaps[0xE] = 0x00; // branch throughput
rawDscCaps[0xF] = 0x00; // bpp increment: 1/16
return parseDscCaps(&rawDscCaps[0], sizeof(rawDscCaps));
}
DP_PRINTF(DP_ERROR, "DP-DEV> Error querying DSC Caps on %s!", this->address.toString(sb));
return false;
}
Expand Down
5 changes: 5 additions & 0 deletions src/nvidia-modeset/include/dp/nvdp-connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@ NVDPLibConnectorPtr nvDPCreateConnector(NVConnectorEvoPtr pConnectorEvo);
void nvDPNotifyLongPulse(NVConnectorEvoPtr pConnectorEvo,
NvBool connected);

void nvDPNotifyVirtualSinkLongPulse(NVConnectorEvoPtr pConnectorEvo,
NvBool connected);

void nvDPNotifyShortPulse(NVDPLibConnectorPtr pNVDpLibConnector);

NvBool nvDPConnectorIsPlugged(const NVConnectorEvoRec *pConnectorEvo);

void nvDPDestroyConnector(NVDPLibConnectorPtr pNVDpLibConnector);

NVDPLibModesetStatePtr nvDPLibCreateModesetState(
Expand Down
16 changes: 16 additions & 0 deletions src/nvidia-modeset/src/dp/nvdp-connector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,22 @@ void nvDPNotifyLongPulse(NVConnectorEvoPtr pConnectorEvo,

}

void nvDPNotifyVirtualSinkLongPulse(NVConnectorEvoPtr pConnectorEvo,
NvBool connected)
{
NVDPLibConnectorPtr pNVDpLibConnector = pConnectorEvo->pDpLibConnector;
DisplayPort::Connector *c = pNVDpLibConnector->connector;

pNVDpLibConnector->plugged = connected;
c->notifyVirtualSinkLongPulse(connected);
}

NvBool nvDPConnectorIsPlugged(const NVConnectorEvoRec *pConnectorEvo)
{
return (pConnectorEvo->pDpLibConnector != NULL) &&
pConnectorEvo->pDpLibConnector->plugged;
}

void nvDPNotifyShortPulse(NVDPLibConnectorPtr pNVDpLibConnector)
{
DisplayPort::Connector *c = pNVDpLibConnector->connector;
Expand Down
10 changes: 10 additions & 0 deletions src/nvidia-modeset/src/nvkms-dpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
*/

#include "dp/nvdp-device.h"
#include "dp/nvdp-connector.h"
#include "dp/nvdp-connector-event-sink.h"

#include "nvkms-api-types.h"
Expand Down Expand Up @@ -3127,6 +3128,15 @@ NvBool nvDpyGetDynamicData(
connectedList = nvDPLibDpyIsConnected(pDpyEvo) ?
oneDpyIdList : nvEmptyDpyIdList();
} else if (pRequest->forceConnected) {
if (nvConnectorUsesDPLib(pConnectorEvo) &&
!nvDPConnectorIsPlugged(pConnectorEvo)) {
/*
* Forced sink-less DP connector (EDID override): simulate a
* virtual-sink plug so DPLib performs discovery with fake DPCD
* caps scoped to this explicit force-connected path.
*/
nvDPNotifyVirtualSinkLongPulse(pConnectorEvo, TRUE);
}
connectedList = oneDpyIdList;
} else if (pRequest->forceDisconnected) {
connectedList = nvEmptyDpyIdList();
Expand Down