515.48.07

This commit is contained in:
Andy Ritger
2022-05-27 16:40:24 -07:00
parent af26e1ea89
commit 965db98552
114 changed files with 18493 additions and 22785 deletions

View File

@@ -320,6 +320,9 @@ namespace DisplayPort
//
bool bDscMstEnablePassThrough;
// Reduce number of 2H1OR LTs which fixes bug 3534707
bool bDscOptimizeLTBug3534707;
//
// Synaptics branch device doesn't support Virtual Peer Devices so DSC
// capability of downstream device should be decided based on device's own
@@ -505,6 +508,7 @@ namespace DisplayPort
void populateDscGpuCaps(DSC_INFO* dscInfo);
void populateForcedDscParams(DSC_INFO* dscInfo, DSC_INFO::FORCED_DSC_PARAMS* forcedParams);
void populateDscSinkCaps(DSC_INFO* dscInfo, DeviceImpl * dev);
void populateDscBranchCaps(DSC_INFO* dscInfo, DeviceImpl * dev);
void populateDscModesetInfo(MODESET_INFO * pModesetInfo, const DpModesetParams * pModesetParams);
bool train(const LinkConfiguration & lConfig, bool force, LinkTrainingType trainType = NORMAL_LINK_TRAINING);

View File

@@ -425,7 +425,9 @@ namespace DisplayPort
NvBool isDSCPossible();
bool isFECSupported();
bool readAndParseDSCCaps();
bool readAndParseBranchSpecificDSCCaps();
bool parseDscCaps(const NvU8 *buffer, NvU32 bufferSize);
bool parseBranchSpecificDscCaps(const NvU8 *buffer, NvU32 bufferSize);
bool setDscEnable(bool enable);
bool getDscEnable(bool *pEnable);
unsigned getDscVersionMajor();

View File

@@ -53,6 +53,8 @@ namespace DisplayPort
bool bWaitForDeAllocACT;
bool bDeferredPayloadAlloc;
ModesetInfo lastModesetInfo;
DSC_MODE dscModeRequest; // DSC mode requested during NAB
DSC_MODE dscModeActive; // DSC mode currently active, set in NAE
DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID singleHeadMultiStreamID;
DP_SINGLE_HEAD_MULTI_STREAM_MODE singleHeadMultiStreamMode;
DP_COLORFORMAT colorFormat;
@@ -76,6 +78,8 @@ namespace DisplayPort
hdcpEnabled(false),
hdcpPreviousStatus(false),
bWaitForDeAllocACT(false),
dscModeRequest(DSC_MODE_NONE),
dscModeActive(DSC_MODE_NONE),
singleHeadMultiStreamID(DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY),
singleHeadMultiStreamMode(DP_SINGLE_HEAD_MULTI_STREAM_MODE_NONE),
bIsCurrentModesetGroup(false),

View File

@@ -116,6 +116,8 @@ namespace DisplayPort
bool isBeingDestroyed;
bool isPaused;
bool bNoReplyTimerForBusyWaiting;
List messageReceivers;
List notYetSentDownRequest; // Down Messages yet to be processed
List notYetSentUpReply; // Up Reply Messages yet to be processed
@@ -153,6 +155,13 @@ namespace DisplayPort
mergerDownReply.mailboxInterrupt();
}
void applyRegkeyOverrides(const DP_REGKEY_DATABASE& dpRegkeyDatabase)
{
DP_ASSERT(dpRegkeyDatabase.bInitialized &&
"All regkeys are invalid because dpRegkeyDatabase is not initialized!");
bNoReplyTimerForBusyWaiting = dpRegkeyDatabase.bNoReplyTimerForBusyWaiting;
}
MessageManager(DPCDHAL * hal, Timer * timer)
: timer(timer), hal(hal),
splitterDownRequest(hal, timer),
@@ -236,6 +245,7 @@ namespace DisplayPort
MessageManager * parent;
bool transmitReply;
bool bTransmitted;
bool bBusyWaiting;
unsigned requestIdentifier;
unsigned messagePriority;
unsigned sinkPort;
@@ -261,6 +271,7 @@ namespace DisplayPort
parent(0),
transmitReply(false),
bTransmitted(false),
bBusyWaiting(false),
requestIdentifier(requestIdentifier),
messagePriority(messagePriority),
sinkPort(0xFF)

View File

@@ -65,11 +65,13 @@
//
#define NV_DP_DSC_MST_CAP_BUG_3143315 "DP_DSC_MST_CAP_BUG_3143315"
//
// Enable DSC Pass through support in MST mode.
//
#define NV_DP_DSC_MST_ENABLE_PASS_THROUGH "DP_DSC_MST_ENABLE_PASS_THROUGH"
// Regkey to reduce number of 2H1OR LTs which fixes bug 3534707
#define NV_DP_DSC_OPTIMIZE_LT_BUG_3534707 "DP_DSC_OPTIMIZE_LT_BUG_3534707"
#define NV_DP_REGKEY_NO_REPLY_TIMER_FOR_BUSY_WAITING "NO_REPLY_TIMER_FOR_BUSY_WAITING"
//
// Data Base used to store all the regkey values.
// The actual data base is declared statically in dp_evoadapter.cpp.
@@ -102,6 +104,8 @@ struct DP_REGKEY_DATABASE
bool bBypassEDPRevCheck;
bool bDscMstCapBug3143315;
bool bDscMstEnablePassThrough;
bool bDscOptimizeLTBug3534707;
bool bNoReplyTimerForBusyWaiting;
};
#endif //INCLUDED_DP_REGKEYDATABASE_H

View File

@@ -189,6 +189,7 @@ void ConnectorImpl::applyRegkeyOverrides(const DP_REGKEY_DATABASE& dpRegkeyDatab
this->bEnableFastLT = dpRegkeyDatabase.bFastLinkTrainingEnabled;
this->bDscMstCapBug3143315 = dpRegkeyDatabase.bDscMstCapBug3143315;
this->bDscMstEnablePassThrough = dpRegkeyDatabase.bDscMstEnablePassThrough;
this->bDscOptimizeLTBug3534707 = dpRegkeyDatabase.bDscOptimizeLTBug3534707;
}
void ConnectorImpl::setPolicyModesetOrderMitigation(bool enabled)
@@ -630,6 +631,12 @@ create:
{
// Read and parse DSC caps only if panel supports DSC
newDev->readAndParseDSCCaps();
// Read and Parse Branch Specific DSC Caps
if (!newDev->isVideoSink() && !newDev->isAudioSink())
{
newDev->readAndParseBranchSpecificDSCCaps();
}
}
// Decide if DSC stream can be sent to new device
@@ -655,13 +662,13 @@ create:
if (this->bDscMstEnablePassThrough)
{
//
// Check the device's own and its parent's DSC capability.
// - Sink device will do DSC cecompression when
// Check the device's own and its parent's DSC capability.
// - Sink device will do DSC cecompression when
// 1. Sink device is capable of DSC decompression and parent
// supports DSC pass through.
//
// - Sink device's parent will do DSC decompression
// 1. If sink device supports DSC decompression but it's parent does not support
// - Sink device's parent will do DSC decompression
// 1. If sink device supports DSC decompression but it's parent does not support
// DSC Pass through, but supports DSC decompression.
// 2. If the device does not support DSC decompression, but parent supports it.
//
@@ -672,7 +679,7 @@ create:
if (newDev->parent->isDSCPassThroughSupported())
{
//
// This condition takes care of DSC capable sink devices
// This condition takes care of DSC capable sink devices
// connected behind a DSC Pass through capable branch
//
newDev->devDoingDscDecompression = newDev;
@@ -681,12 +688,12 @@ create:
else if (newDev->parent->isDSCSupported())
{
//
// This condition takes care of DSC capable sink devices
// This condition takes care of DSC capable sink devices
// connected behind a branch device that is not capable
// of DSC pass through but can do DSC decompression.
//
newDev->bDSCPossible = true;
newDev->devDoingDscDecompression = newDev->parent;
newDev->devDoingDscDecompression = newDev->parent;
}
}
else
@@ -695,11 +702,11 @@ create:
newDev->devDoingDscDecompression = newDev;
newDev->bDSCPossible = true;
}
}
}
else if (newDev->parent && newDev->parent->isDSCSupported())
{
//
// This condition takes care of sink devices not capable of DSC
// This condition takes care of sink devices not capable of DSC
// but parent is capable of DSC decompression.
//
newDev->bDSCPossible = true;
@@ -709,7 +716,7 @@ create:
else
{
//
// Revert to old code if DSC Pass through support is not requested.
// Revert to old code if DSC Pass through support is not requested.
// This code will be deleted once DSC Pass through support will be enabled
// by default which will be done when 2Head1OR MST (GR-133) will be in production.
//
@@ -1726,6 +1733,15 @@ void ConnectorImpl::populateDscGpuCaps(DSC_INFO* dscInfo)
dscInfo->gpuCaps.lineBufferBitDepth = lineBufferBitDepth;
}
void ConnectorImpl::populateDscBranchCaps(DSC_INFO* dscInfo, DeviceImpl * dev)
{
dscInfo->branchCaps.overallThroughputMode0 = dev->dscCaps.branchDSCOverallThroughputMode0;
dscInfo->branchCaps.overallThroughputMode1 = dev->dscCaps.branchDSCOverallThroughputMode1;
dscInfo->branchCaps.maxLineBufferWidth = dev->dscCaps.branchDSCMaximumLineBufferWidth;
return;
}
void ConnectorImpl::populateDscSinkCaps(DSC_INFO* dscInfo, DeviceImpl * dev)
{
// Early return if dscInfo or dev is NULL
@@ -1846,6 +1862,12 @@ void ConnectorImpl::populateDscCaps(DSC_INFO* dscInfo, DeviceImpl * dev, DSC_INF
// Sink DSC capabilities
populateDscSinkCaps(dscInfo, dev);
// Branch Specific DSC Capabilities
if (!dev->isVideoSink() && !dev->isAudioSink())
{
populateDscBranchCaps(dscInfo, dev);
}
// GPU DSC capabilities
populateDscGpuCaps(dscInfo);
@@ -2621,11 +2643,6 @@ bool ConnectorImpl::notifyAttachBegin(Group * target, // Gr
}
}
if (bEnableDsc)
{
DP_LOG(("DPCONN> DSC Mode = %s", (modesetParams.modesetInfo.mode == DSC_SINGLE) ? "SINGLE" : "DUAL"));
}
for (Device * dev = target->enumDevices(0); dev; dev = target->enumDevices(dev))
{
Address::StringBuffer buffer;
@@ -2641,6 +2658,12 @@ bool ConnectorImpl::notifyAttachBegin(Group * target, // Gr
GroupImpl* targetImpl = (GroupImpl*)target;
targetImpl->bIsCurrentModesetGroup = true;
if (bEnableDsc)
{
DP_LOG(("DPCONN> DSC Mode = %s", (modesetParams.modesetInfo.mode == DSC_SINGLE) ? "SINGLE" : "DUAL"));
targetImpl->dscModeRequest = modesetParams.modesetInfo.mode;
}
DP_ASSERT(!(targetImpl->isHeadAttached() && targetImpl->bIsHeadShutdownNeeded) && "Head should have been shut down but it is still active!");
targetImpl->headInFirmware = false;
@@ -2788,6 +2811,10 @@ void ConnectorImpl::notifyAttachEnd(bool modesetCancelled)
currentModesetDeviceGroup->setHeadAttached(false);
}
// set dscModeActive to what was requested in NAB and clear dscModeRequest
currentModesetDeviceGroup->dscModeActive = currentModesetDeviceGroup->dscModeRequest;
currentModesetDeviceGroup->dscModeRequest = DSC_MODE_NONE;
currentModesetDeviceGroup->setHeadAttached(true);
RmDfpCache dfpCache = {0};
dfpCache.updMask = 0;
@@ -2934,6 +2961,7 @@ void ConnectorImpl::notifyDetachEnd(bool bKeepOdAlive)
dpMemZero(&currentModesetDeviceGroup->lastModesetInfo, sizeof(ModesetInfo));
currentModesetDeviceGroup->setHeadAttached(false);
currentModesetDeviceGroup->headInFirmware = false;
currentModesetDeviceGroup->dscModeActive = DSC_MODE_NONE;
// Mark head as disconnected
bNoLtDoneAfterHeadDetach = true;
@@ -3980,18 +4008,36 @@ bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
GroupImpl * groupAttached = 0;
for (ListElement * e = activeGroups.begin(); e != activeGroups.end(); e = e->next)
{
DP_ASSERT(bIsUefiSystem || (!groupAttached && "Multiple attached heads"));
DP_ASSERT(bIsUefiSystem);
groupAttached = (GroupImpl * )e;
if ((groupAttached->lastModesetInfo.mode == DSC_DUAL) && groupAttached->bIsCurrentModesetGroup)
if (bDscOptimizeLTBug3534707)
{
//
// If current modeset group requires 2Head1OR mode, we should retrain link.
// For SST, there will be only one group per connector.
// For MST, we need to re-run LT in case the current modeset group requires DSC_DUAL.
//
bTwoHeadOneOrLinkRetrain = true;
break;
if ((groupAttached->dscModeRequest == DSC_DUAL) && (groupAttached->dscModeActive != DSC_DUAL))
{
//
// If current modeset group requires 2Head1OR and
// - group is not active yet (first modeset on the group)
// - group is active but not in 2Head1OR mode (last modeset on the group did not require 2Head1OR)
// then re-train the link
// This is because for 2Head1OR mode, we need to set some LT parametes for slave SOR after
// successful LT on primary SOR without which 2Head1OR modeset will lead to HW hang.
//
bTwoHeadOneOrLinkRetrain = true;
break;
}
}
else
{
if (groupAttached->lastModesetInfo.mode == DSC_DUAL && groupAttached->bIsCurrentModesetGroup)
{
//
// If current modeset group requires 2Head1OR mode, we should retrain link.
// For SST, there will be only one group per connector.
// For MST, we need to re-run LT in case the current modeset group requires DSC_DUAL.
bTwoHeadOneOrLinkRetrain = true;
break;
}
}
}
@@ -4077,10 +4123,10 @@ bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
{
//
// Check if we are already trained to the desired link config?
// Even if we are, we need to redo LT if FEC is enabled or DSC mode is DSC_DUAL
// since if current modeset requires 2H1OR, LT done during assessLink will not
// have 2H1Or flag set or if last modeset required DSC but not 2H1OR, still 2H1Or
// flag will not be set and modeset will lead to HW hang.
// Make sure requested FEC state matches with the current FEC state of link.
// If 2Head1OR mode is requested, retrain if group is not active or
// last modeset on active group was not in 2Head1OR mode.
// bTwoHeadOneOrLinkRetrain tracks this requirement.
//
//
@@ -4093,7 +4139,8 @@ bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
if ((activeLinkConfig == lowestSelected) &&
(!isLinkInD3()) &&
(!isLinkLost()) &&
!(this->bFECEnable) &&
((!bDscOptimizeLTBug3534707 && !this->bFECEnable) ||
(bDscOptimizeLTBug3534707 && (this->bFECEnable == activeLinkConfig.bEnableFEC))) &&
!bTwoHeadOneOrLinkRetrain)
{
if (bSkipRedundantLt || main->isInternalPanelDynamicMuxCapable())
@@ -4209,11 +4256,9 @@ bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
//
// Make sure link is physically active and healthy, otherwise re-train.
// We need to retrain if the link is in 2Head1OR MST mode. For example,
// if we plug in a 2Head1OR panel to an active link that is already driving
// a MST panel in DSC mode, RM will assign a secondary OR to the 2Head1OR panel.
// But since there is no change required in linkConfig DPlib will skip
// LT, resutling in not adding secondary OR to LT; this will lead to HW hang.
// Make sure requested FEC state matches with the current FEC state of link.
// If 2Head1OR mode is requested, retrain if group is not active or last modeset on active group
// was not in 2Head1OR mode. bTwoHeadOneOrLinkRetrain tracks this requirement.
//
bRetrainToEnsureLinkStatus = (isLinkActive() && isLinkInD3()) ||
isLinkLost() ||
@@ -5660,7 +5705,7 @@ void ConnectorImpl::notifyLongPulseInternal(bool statusConnected)
if (hal->getSupportsMultistream() && main->hasMultistream())
{
bool bDeleteFirmwareVC = false;
const DP_REGKEY_DATABASE& dpRegkeyDatabase = main->getRegkeyDatabase();
DP_LOG(("DP> Multistream panel detected, building message manager"));
//
@@ -5669,6 +5714,7 @@ void ConnectorImpl::notifyLongPulseInternal(bool statusConnected)
//
messageManager = new MessageManager(hal, timer);
messageManager->registerReceiver(&ResStatus);
messageManager->applyRegkeyOverrides(dpRegkeyDatabase);
//
// Create a discovery manager to initiate detection

View File

@@ -1687,6 +1687,50 @@ bool DeviceImpl::parseDscCaps(const NvU8 *buffer, NvU32 bufferSize)
return true;
}
bool DeviceImpl::parseBranchSpecificDscCaps(const NvU8 *buffer, NvU32 bufferSize)
{
if (bufferSize < 3)
{
DP_LOG((" Branch DSC caps buffer must be greater than or equal to 3"));
return false;
}
dscCaps.branchDSCOverallThroughputMode0 = DRF_VAL(_DPCD20, _BRANCH_DSC_OVERALL_THROUGHPUT_MODE_0, _VALUE, buffer[0x0]);
if (dscCaps.branchDSCOverallThroughputMode0 == 1)
{
dscCaps.branchDSCOverallThroughputMode0 = 680;
}
else if (dscCaps.branchDSCOverallThroughputMode0 >= 2)
{
dscCaps.branchDSCOverallThroughputMode0 = 600 + dscCaps.branchDSCOverallThroughputMode0 * 50;
}
dscCaps.branchDSCOverallThroughputMode1 = DRF_VAL(_DPCD20, _BRANCH_DSC_OVERALL_THROUGHPUT_MODE_1, _VALUE, buffer[0x1]);
if (dscCaps.branchDSCOverallThroughputMode1 == 1)
{
dscCaps.branchDSCOverallThroughputMode1 = 680;
}
else if (dscCaps.branchDSCOverallThroughputMode1 >= 2)
{
dscCaps.branchDSCOverallThroughputMode1 = 600 + dscCaps.branchDSCOverallThroughputMode1 * 50;
}
dscCaps.branchDSCMaximumLineBufferWidth = DRF_VAL(_DPCD20, _BRANCH_DSC_MAXIMUM_LINE_BUFFER_WIDTH, _VALUE, buffer[0x2]);
if (dscCaps.branchDSCMaximumLineBufferWidth != 0)
{
if (dscCaps.branchDSCMaximumLineBufferWidth >= 16)
{
dscCaps.branchDSCMaximumLineBufferWidth = dscCaps.branchDSCMaximumLineBufferWidth * 320;
}
else
{
dscCaps.branchDSCMaximumLineBufferWidth = 0;
DP_LOG(("Value of branch DSC maximum line buffer width is invalid, so setting it to 0."));
}
}
return true;
}
bool DeviceImpl::readAndParseDSCCaps()
{
// Allocate a buffer of 16 bytes to read DSC caps
@@ -1703,6 +1747,21 @@ bool DeviceImpl::readAndParseDSCCaps()
return parseDscCaps(&rawDscCaps[0], sizeof(rawDscCaps));
}
bool DeviceImpl::readAndParseBranchSpecificDSCCaps()
{
unsigned sizeCompleted = 0;
unsigned nakReason = NakUndefined;
NvU8 rawBranchSpecificDscCaps[3];
if(AuxBus::success != this->getDpcdData(NV_DPCD20_BRANCH_DSC_OVERALL_THROUGHPUT_MODE_0,
&rawBranchSpecificDscCaps[0], sizeof(rawBranchSpecificDscCaps), &sizeCompleted, &nakReason))
{
return false;
}
return parseBranchSpecificDscCaps(&rawBranchSpecificDscCaps[0], sizeof(rawBranchSpecificDscCaps));
}
bool DeviceImpl::getDscEnable(bool *pEnable)
{
AuxBus::status status = AuxBus::success;

View File

@@ -94,7 +94,9 @@ const struct
{NV_DP_REGKEY_KEEP_OPT_LINK_ALIVE_SST, &dpRegkeyDatabase.bOptLinkKeptAliveSst, DP_REG_VAL_BOOL},
{NV_DP_REGKEY_FORCE_EDP_ILR, &dpRegkeyDatabase.bBypassEDPRevCheck, DP_REG_VAL_BOOL},
{NV_DP_DSC_MST_CAP_BUG_3143315, &dpRegkeyDatabase.bDscMstCapBug3143315, DP_REG_VAL_BOOL},
{NV_DP_DSC_MST_ENABLE_PASS_THROUGH, &dpRegkeyDatabase.bDscMstEnablePassThrough, DP_REG_VAL_BOOL}
{NV_DP_DSC_MST_ENABLE_PASS_THROUGH, &dpRegkeyDatabase.bDscMstEnablePassThrough, DP_REG_VAL_BOOL},
{NV_DP_DSC_OPTIMIZE_LT_BUG_3534707, &dpRegkeyDatabase.bDscOptimizeLTBug3534707, DP_REG_VAL_BOOL},
{NV_DP_REGKEY_NO_REPLY_TIMER_FOR_BUSY_WAITING, &dpRegkeyDatabase.bNoReplyTimerForBusyWaiting, DP_REG_VAL_BOOL}
};
EvoMainLink::EvoMainLink(EvoInterface * provider, Timer * timer) :

View File

@@ -63,6 +63,11 @@ bool MessageManager::send(MessageManager::Message * message, NakData & nakData)
DP_USED(sb);
NvU64 startTime, elapsedTime;
if (bNoReplyTimerForBusyWaiting)
{
message->bBusyWaiting = true;
}
post(message, &completion);
startTime = timer->getTimeUs();
do
@@ -152,14 +157,13 @@ void MessageManager::Message::splitterTransmitted(OutgoingTransactionManager * f
if (from == &parent->splitterDownRequest)
{
//
// Start the countdown timer for the reply
//
parent->timer->queueCallback(this, "SPLI", DPCD_MESSAGE_REPLY_TIMEOUT);
//
// Client will busy-waiting for the message to complete, we don't need the countdown timer.
if (!bBusyWaiting)
{
// Start the countdown timer for the reply
parent->timer->queueCallback(this, "SPLI", DPCD_MESSAGE_REPLY_TIMEOUT);
}
// Tell the message manager he may begin sending the next message
//
parent->transmitAwaitingDownRequests();
}
else // UpReply