mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-27 18:34:00 +00:00
520.61.05
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1993-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1993-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -260,6 +260,9 @@ namespace DisplayPort
|
||||
virtual bool isMSAOverMSTCapable() = 0;
|
||||
virtual bool isFakedMuxDevice() = 0;
|
||||
|
||||
virtual bool setPanelReplayConfig(panelReplayConfig prcfg) = 0;
|
||||
virtual bool isPanelReplaySupported() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Device() {}
|
||||
|
||||
|
||||
@@ -315,14 +315,6 @@ namespace DisplayPort
|
||||
//
|
||||
bool bDscMstCapBug3143315;
|
||||
|
||||
//
|
||||
// Enable DSC Pass through support in driver based on regkey.
|
||||
//
|
||||
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
|
||||
|
||||
@@ -173,6 +173,8 @@ namespace DisplayPort
|
||||
bool bIsFakedMuxDevice;
|
||||
bool bIsPreviouslyFakedMuxDevice;
|
||||
bool bisMarkedForDeletion;
|
||||
bool bIgnoreMsaCap;
|
||||
bool bIgnoreMsaCapCached;
|
||||
|
||||
//
|
||||
// Device doing the DSC decompression for this device. This could be device itself
|
||||
@@ -194,6 +196,7 @@ namespace DisplayPort
|
||||
|
||||
TriState bSdpExtCapable;
|
||||
bool bMSAOverMSTCapable;
|
||||
bool bDscPassThroughColorFormatWar;
|
||||
|
||||
DeviceImpl(DPCDHAL * hal, ConnectorImpl * connector, DeviceImpl * parent);
|
||||
~DeviceImpl();
|
||||
@@ -349,15 +352,9 @@ namespace DisplayPort
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getIgnoreMSACap()
|
||||
{
|
||||
return hal->getMsaTimingparIgnored();
|
||||
}
|
||||
bool getIgnoreMSACap();
|
||||
|
||||
AuxRetry::status setIgnoreMSAEnable(bool msaTimingParamIgnoreEn)
|
||||
{
|
||||
return hal->setIgnoreMSATimingParamters(msaTimingParamIgnoreEn);
|
||||
}
|
||||
AuxRetry::status setIgnoreMSAEnable(bool msaTimingParamIgnoreEn);
|
||||
|
||||
bool isVirtualPeerDevice()
|
||||
{
|
||||
|
||||
@@ -308,7 +308,9 @@ namespace DisplayPort
|
||||
|
||||
static const NvU8 ddcAddrList[] = {EDID_DDC_ADR0, EDID_DDC_ADR1, EDID_DDC_ADR2};
|
||||
const NvU8 ddcAddrListSize = sizeof(ddcAddrList)/sizeof(NvU8);
|
||||
const NvU8 EDID_READ_MAX_RETRY_COUNT = 6;
|
||||
|
||||
// HDMI 1.4 Section 8.5: HDMI Sink can have up to 100ms to get EDID ready.
|
||||
const NvU8 EDID_READ_RETRY_TIMEOUT_MS = 100;
|
||||
const NvU8 EDID_MAX_AUX_RETRIES = 10;
|
||||
const NvU8 EDID_AUX_WAIT_TIME = 1;
|
||||
NvU8 getEDIDBlockChecksum(const Buffer &);
|
||||
|
||||
@@ -68,8 +68,6 @@ namespace DisplayPort
|
||||
Watermark watermarks; // Cached watermark calculations
|
||||
} timeslot;
|
||||
|
||||
bool bIsCurrentModesetGroup; // Group that is getting attached
|
||||
|
||||
GroupImpl(ConnectorImpl * parent, bool isFirmwareGroup = false)
|
||||
: parent(parent),
|
||||
streamValidationDone(true),
|
||||
@@ -82,7 +80,6 @@ namespace DisplayPort
|
||||
dscModeActive(DSC_MODE_NONE),
|
||||
singleHeadMultiStreamID(DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY),
|
||||
singleHeadMultiStreamMode(DP_SINGLE_HEAD_MULTI_STREAM_MODE_NONE),
|
||||
bIsCurrentModesetGroup(false),
|
||||
headAttached(false)
|
||||
{
|
||||
timeslot.count = 0;
|
||||
|
||||
@@ -145,6 +145,7 @@ namespace DisplayPort
|
||||
EDP_3_24GHZ = 324000000,
|
||||
EDP_4_32GHZ = 432000000,
|
||||
HBR2 = 540000000,
|
||||
EDP_6_75GHZ = 675000000,
|
||||
HBR3 = 810000000
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2010-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2010-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2020-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -65,12 +65,6 @@
|
||||
//
|
||||
#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"
|
||||
|
||||
#define NV_DP_REGKEY_DPCD_PROBING_FOR_BUSY_WAITING "DP_DPCD_PROBING_FOR_BUSY_WAITING"
|
||||
@@ -106,8 +100,6 @@ struct DP_REGKEY_DATABASE
|
||||
bool bOptLinkKeptAliveSst;
|
||||
bool bBypassEDPRevCheck;
|
||||
bool bDscMstCapBug3143315;
|
||||
bool bDscMstEnablePassThrough;
|
||||
bool bDscOptimizeLTBug3534707;
|
||||
bool bNoReplyTimerForBusyWaiting;
|
||||
bool bDpcdProbingForBusyWaiting;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1993-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1993-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -188,8 +188,6 @@ void ConnectorImpl::applyRegkeyOverrides(const DP_REGKEY_DATABASE& dpRegkeyDatab
|
||||
this->bDisableSSC = dpRegkeyDatabase.bSscDisabled;
|
||||
this->bEnableFastLT = dpRegkeyDatabase.bFastLinkTrainingEnabled;
|
||||
this->bDscMstCapBug3143315 = dpRegkeyDatabase.bDscMstCapBug3143315;
|
||||
this->bDscMstEnablePassThrough = dpRegkeyDatabase.bDscMstEnablePassThrough;
|
||||
this->bDscOptimizeLTBug3534707 = dpRegkeyDatabase.bDscOptimizeLTBug3534707;
|
||||
}
|
||||
|
||||
void ConnectorImpl::setPolicyModesetOrderMitigation(bool enabled)
|
||||
@@ -633,27 +631,56 @@ create:
|
||||
newDev->queryGUID2();
|
||||
}
|
||||
|
||||
// Read panel DSC support only if GPU supports DSC
|
||||
bool bGpuDscSupported;
|
||||
main->getDscCaps(&bGpuDscSupported);
|
||||
if (bGpuDscSupported)
|
||||
if (!linkAwaitingTransition)
|
||||
{
|
||||
if (newDev->getDSCSupport())
|
||||
{
|
||||
// Read and parse DSC caps only if panel supports DSC
|
||||
newDev->readAndParseDSCCaps();
|
||||
//
|
||||
// When link is awaiting SST<->MST transition, DSC caps read from downstream
|
||||
// DSC branch device might be wrong. DSC Caps exposed by DSC MST branch depends
|
||||
// on the current link state. If it is in SST mode ie MST_EN (0x111[bit 0]) is 0 and
|
||||
// panel connected behind it supports DSC, then branch will expose the DSC caps
|
||||
// of the panel connected down stream rather than it's own. This is because source
|
||||
// will have no other way to read the caps of the downstream panel. In fact when
|
||||
// MST_EN = 0 and UP_REQ_EN (0x111 [bit 1]) = 1 source can read the caps of the
|
||||
// downstream panel using REMOTE_DPCD_READ but branch device's behavior depends
|
||||
// only on MST_EN bit. Similarly in SST, if the panel connected downstream to branch
|
||||
// does not support DSC, DSC MST branch will expose it's own DSC caps.
|
||||
// During boot since VBIOS drives display in SST mode and when driver takes over,
|
||||
// linkAwaitingTransition will be true. DpLib does link assessment and topology
|
||||
// discovery by setting UP_REQ_EN to true while still keeping MST_EN to false.
|
||||
// This is to ensure we detach the head and active modeset groups that are in SST mode
|
||||
// before switching the link to MST mode. When processNewDevice is called at this
|
||||
// point to create new devices we should not read DSC caps due to above mentioned reason.
|
||||
// As long as linkIsAwaitingTransition is true, Dplib will not report new Devices to
|
||||
// to client since isPendingNewDevice() will be false even though DPlib discovered
|
||||
// new devices. After Dplib completes topology discovery, DD initiates notifyDetachBegin/End
|
||||
// to remove active groups from the link and notifyDetachEnd calls assessLink
|
||||
// where we toggle the link state. Only after this we should read DSC caps in this case.
|
||||
// Following this assesslink calls fireEvents() which will report
|
||||
// the new devies to clients and client will have the correct DSC caps.
|
||||
//
|
||||
bool bGpuDscSupported;
|
||||
|
||||
// Read and Parse Branch Specific DSC Caps
|
||||
if (!newDev->isVideoSink() && !newDev->isAudioSink())
|
||||
// Check GPU DSC Support
|
||||
main->getDscCaps(&bGpuDscSupported);
|
||||
if (bGpuDscSupported)
|
||||
{
|
||||
if (newDev->getDSCSupport())
|
||||
{
|
||||
newDev->readAndParseBranchSpecificDSCCaps();
|
||||
}
|
||||
}
|
||||
// Read and parse DSC caps only if panel supports DSC
|
||||
newDev->readAndParseDSCCaps();
|
||||
|
||||
if (!processedEdid.WARFlags.bIgnoreDscCap)
|
||||
{
|
||||
// Check if DSC is possible for the device and if so, set DSC Decompression device.
|
||||
newDev->setDscDecompressionDevice(this->bDscCapBasedOnParent);
|
||||
// Read and Parse Branch Specific DSC Caps
|
||||
if (!newDev->isVideoSink() && !newDev->isAudioSink())
|
||||
{
|
||||
newDev->readAndParseBranchSpecificDSCCaps();
|
||||
}
|
||||
}
|
||||
|
||||
if (!processedEdid.WARFlags.bIgnoreDscCap)
|
||||
{
|
||||
// Check if DSC is possible for the device and if so, set DSC Decompression device.
|
||||
newDev->setDscDecompressionDevice(this->bDscCapBasedOnParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,6 +702,8 @@ create:
|
||||
newDev->bMSAOverMSTCapable = false;
|
||||
}
|
||||
|
||||
newDev->applyOUIOverrides();
|
||||
|
||||
fireEvents();
|
||||
}
|
||||
|
||||
@@ -1194,6 +1223,40 @@ bool ConnectorImpl::compoundQueryAttach(Group * target,
|
||||
DP_LOG(("Current version is 1.1"));
|
||||
}
|
||||
|
||||
if ((dev->devDoingDscDecompression == dev) && dev->parent)
|
||||
{
|
||||
if (dev->parent->bDscPassThroughColorFormatWar)
|
||||
{
|
||||
//
|
||||
// Bug 3692417
|
||||
// Color format should only depend on device doing DSC decompression when DSC is enabled according to DP Spec.
|
||||
// But when Synaptics VMM5320 is the parent of the device doing DSC decompression, if a certain color
|
||||
// format is not supported by Synaptics Virtual Peer Device decoder(parent), even though it is pass through mode
|
||||
// and panel supports the color format, panel cannot light up. Once Synaptics fixes this issue, we will modify
|
||||
// the WAR to be applied only before the firmware version that fixes it.
|
||||
//
|
||||
if ((modesetParams.colorFormat == dpColorFormat_RGB && !dev->parent->dscCaps.dscDecoderColorFormatCaps.bRgb) ||
|
||||
(modesetParams.colorFormat == dpColorFormat_YCbCr444 && !dev->parent->dscCaps.dscDecoderColorFormatCaps.bYCbCr444) ||
|
||||
(modesetParams.colorFormat == dpColorFormat_YCbCr422 && !dev->parent->dscCaps.dscDecoderColorFormatCaps.bYCbCrSimple422))
|
||||
{
|
||||
if (pDscParams->forceDsc == DSC_FORCE_ENABLE)
|
||||
{
|
||||
// If DSC is force enabled then return failure here
|
||||
compoundQueryResult = false;
|
||||
pDscParams->bEnableDsc = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should check if mode is possible without DSC.
|
||||
pDscParams->bEnableDsc = false;
|
||||
lc.enableFEC(false);
|
||||
goto nonDscDpIMP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
availableBandwidthBitsPerSecond = lc.minRate * 8 * lc.lanes;
|
||||
|
||||
warData.dpData.linkRateHz = lc.peakRate;
|
||||
@@ -2550,7 +2613,6 @@ bool ConnectorImpl::notifyAttachBegin(Group * target, // Gr
|
||||
}
|
||||
|
||||
GroupImpl* targetImpl = (GroupImpl*)target;
|
||||
targetImpl->bIsCurrentModesetGroup = true;
|
||||
|
||||
if (bEnableDsc)
|
||||
{
|
||||
@@ -2667,7 +2729,6 @@ bool ConnectorImpl::notifyAttachBegin(Group * target, // Gr
|
||||
NV_DPTRACE_INFO(NOTIFY_ATTACH_BEGIN_STATUS, bLinkTrainingStatus);
|
||||
|
||||
bFromResumeToNAB = false;
|
||||
targetImpl->bIsCurrentModesetGroup = false;
|
||||
return bLinkTrainingStatus;
|
||||
}
|
||||
|
||||
@@ -3283,6 +3344,7 @@ bool ConnectorImpl::trainSingleHeadMultipleSSTLinkNotAlive(GroupImpl *pGroupAtta
|
||||
void ConnectorImpl::assessLink(LinkTrainingType trainType)
|
||||
{
|
||||
this->bSkipLt = false; // Assesslink should never skip LT, so let's reset it in case it was set.
|
||||
bool bLinkStateToggle = false;
|
||||
|
||||
if (bSkipAssessLinkForPCon)
|
||||
{
|
||||
@@ -3409,6 +3471,7 @@ void ConnectorImpl::assessLink(LinkTrainingType trainType)
|
||||
linkState = hal->getSupportsMultistream() ?
|
||||
DP_TRANSPORT_MODE_MULTI_STREAM : DP_TRANSPORT_MODE_SINGLE_STREAM;
|
||||
linkAwaitingTransition = false;
|
||||
bLinkStateToggle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3517,6 +3580,30 @@ done:
|
||||
{
|
||||
disableFlush();
|
||||
}
|
||||
|
||||
if (bLinkStateToggle)
|
||||
{
|
||||
DP_LOG(("DP> Link state toggled, reading DSC caps now"));
|
||||
// Read panel DSC support only if GPU supports DSC
|
||||
bool bGpuDscSupported;
|
||||
main->getDscCaps(&bGpuDscSupported);
|
||||
if (bGpuDscSupported)
|
||||
{
|
||||
for (Device * i = enumDevices(0); i; i=enumDevices(i))
|
||||
{
|
||||
DeviceImpl * dev = (DeviceImpl *)i;
|
||||
if(dev->getDSCSupport())
|
||||
{
|
||||
// Read and parse DSC caps only if panel and GPU supports DSC
|
||||
dev->readAndParseDSCCaps();
|
||||
}
|
||||
if (!(dev->processedEdid.WARFlags.bIgnoreDscCap))
|
||||
{
|
||||
dev->setDscDecompressionDevice(this->bDscCapBasedOnParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ConnectorImpl::handleCPIRQ()
|
||||
@@ -3902,36 +3989,21 @@ bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
|
||||
GroupImpl * groupAttached = 0;
|
||||
for (ListElement * e = activeGroups.begin(); e != activeGroups.end(); e = e->next)
|
||||
{
|
||||
DP_ASSERT(bIsUefiSystem);
|
||||
DP_ASSERT(bIsUefiSystem || linkUseMultistream() || (!groupAttached && "Multiple attached heads"));
|
||||
groupAttached = (GroupImpl * )e;
|
||||
|
||||
if (bDscOptimizeLTBug3534707)
|
||||
if ((groupAttached->dscModeRequest == DSC_DUAL) && (groupAttached->dscModeActive != DSC_DUAL))
|
||||
{
|
||||
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;
|
||||
}
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4018,9 +4090,9 @@ bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
|
||||
//
|
||||
// Check if we are already trained to the desired link config?
|
||||
// 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.
|
||||
// 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.
|
||||
//
|
||||
|
||||
//
|
||||
@@ -4033,8 +4105,7 @@ bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
|
||||
if ((activeLinkConfig == lowestSelected) &&
|
||||
(!isLinkInD3()) &&
|
||||
(!isLinkLost()) &&
|
||||
((!bDscOptimizeLTBug3534707 && !this->bFECEnable) ||
|
||||
(bDscOptimizeLTBug3534707 && (this->bFECEnable == activeLinkConfig.bEnableFEC))) &&
|
||||
(this->bFECEnable == activeLinkConfig.bEnableFEC) &&
|
||||
!bTwoHeadOneOrLinkRetrain)
|
||||
{
|
||||
if (bSkipRedundantLt || main->isInternalPanelDynamicMuxCapable())
|
||||
@@ -4151,8 +4222,8 @@ bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
|
||||
//
|
||||
// Make sure link is physically active and healthy, otherwise re-train.
|
||||
// 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.
|
||||
// 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() ||
|
||||
@@ -6143,6 +6214,13 @@ void ConnectorImpl::notifyShortPulse()
|
||||
}
|
||||
}
|
||||
|
||||
// If DPCD access is not available, skip trying to restore link configuration.
|
||||
hal->updateDPCDOffline();
|
||||
if (hal->isDpcdOffline())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DP_LOG(("DP> Link not alive, Try to restore link configuration"));
|
||||
|
||||
if (trainSingleHeadMultipleSSTLinkNotAlive(getActiveGroupForSST()))
|
||||
|
||||
@@ -91,7 +91,10 @@ DeviceImpl::DeviceImpl(DPCDHAL * hal, ConnectorImpl * connector, DeviceImpl * pa
|
||||
bIsFakedMuxDevice(false),
|
||||
bIsPreviouslyFakedMuxDevice(false),
|
||||
bisMarkedForDeletion(false),
|
||||
bSdpExtCapable(Indeterminate)
|
||||
bIgnoreMsaCap(false),
|
||||
bIgnoreMsaCapCached(false),
|
||||
bSdpExtCapable(Indeterminate),
|
||||
bDscPassThroughColorFormatWar(false)
|
||||
{
|
||||
bandwidth.enum_path.dataValid = false;
|
||||
shadow.plugged = false;
|
||||
@@ -921,6 +924,7 @@ void DeviceImpl::applyOUIOverrides()
|
||||
(buffer[8] == 0x31 || buffer[8] == 0x20))
|
||||
{
|
||||
this->bSdpExtCapable = False;
|
||||
this->bDscPassThroughColorFormatWar = true;
|
||||
|
||||
//
|
||||
// Check firmware version
|
||||
@@ -1026,7 +1030,7 @@ bool DeviceImpl::getSDPExtnForColorimetrySupported()
|
||||
_YES, byte) ? True : False;
|
||||
}
|
||||
}
|
||||
this->applyOUIOverrides();
|
||||
|
||||
if (parentDevice && (this->bSdpExtCapable == True))
|
||||
{
|
||||
//
|
||||
@@ -1458,11 +1462,6 @@ NvBool DeviceImpl::getDSCSupport()
|
||||
{
|
||||
dscCaps.bDSCSupported = true;
|
||||
}
|
||||
|
||||
if (FLD_TEST_DRF(_DPCD20, _DSC_SUPPORT, _PASS_THROUGH_SUPPORT, _YES, byte))
|
||||
{
|
||||
dscCaps.bDSCPassThroughSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
@@ -1572,6 +1571,11 @@ bool DeviceImpl::parseDscCaps(const NvU8 *buffer, NvU32 bufferSize)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FLD_TEST_DRF(_DPCD20, _DSC_SUPPORT, _PASS_THROUGH_SUPPORT, _YES, buffer[0x0]))
|
||||
{
|
||||
dscCaps.bDSCPassThroughSupported = true;
|
||||
}
|
||||
|
||||
dscCaps.versionMajor = DRF_VAL(_DPCD14, _DSC_ALGORITHM_REVISION, _MAJOR, buffer[0x1]);
|
||||
dscCaps.versionMinor = DRF_VAL(_DPCD14, _DSC_ALGORITHM_REVISION, _MINOR, buffer[0x1]);
|
||||
|
||||
@@ -1758,6 +1762,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));
|
||||
}
|
||||
|
||||
void DeviceImpl::queryGUID2()
|
||||
{
|
||||
unsigned sizeCompleted = 0;
|
||||
@@ -1779,21 +1798,6 @@ void DeviceImpl::queryGUID2()
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1928,7 +1932,8 @@ bool DeviceImpl::setDscEnable(bool enable)
|
||||
unsigned nakReason = NakUndefined;
|
||||
bool bCurrDscEnable = false;
|
||||
bool bDscPassThrough = false;
|
||||
bool bDscPassThroughUpdated = true;
|
||||
AuxBus::status dscEnableStatus = AuxBus::success;
|
||||
AuxBus::status dscPassThroughStatus = AuxBus::success;
|
||||
Address::StringBuffer buffer;
|
||||
DP_USED(buffer);
|
||||
|
||||
@@ -1938,7 +1943,7 @@ bool DeviceImpl::setDscEnable(bool enable)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((this->devDoingDscDecompression == this) && !this->isLogical() && this->parent != NULL && this->connector->bDscMstEnablePassThrough)
|
||||
if ((this->devDoingDscDecompression == this) && !this->isLogical() && this->parent != NULL)
|
||||
{
|
||||
//
|
||||
// If the device has a parent, that means the sink is on a MST link and
|
||||
@@ -1948,20 +1953,18 @@ bool DeviceImpl::setDscEnable(bool enable)
|
||||
//
|
||||
bDscPassThrough = true;
|
||||
}
|
||||
else
|
||||
|
||||
//
|
||||
// Get Current DSC Enable State
|
||||
// Ideally we don't need to check the current state but Synaptics DSC device,
|
||||
// which was used for inital DSC code developement did not follow spec and so
|
||||
// we have added this code. Overwriting the same value should not have any
|
||||
// impact as per the spec. Will remove this check once all DSC devices follow spec.
|
||||
//
|
||||
if (!getDscEnable(&bCurrDscEnable))
|
||||
{
|
||||
//
|
||||
// Get Current DSC Enable State
|
||||
// Ideally we don't need to check the current state but Synaptics DSC device,
|
||||
// which was used for inital DSC code developement did not follow spec and so
|
||||
// we have added this code. Overwriting the same value should not have any
|
||||
// impact as per the spec. Will remove this check once all DSC devices follow spec.
|
||||
//
|
||||
if (!getDscEnable(&bCurrDscEnable))
|
||||
{
|
||||
DP_LOG(("DP-DEV> Not able to get DSC Enable State!"));
|
||||
return false;
|
||||
}
|
||||
DP_LOG(("DP-DEV> Not able to get DSC Enable State!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(enable)
|
||||
@@ -1970,7 +1973,7 @@ bool DeviceImpl::setDscEnable(bool enable)
|
||||
{
|
||||
dscPassthroughByte = FLD_SET_DRF(_DPCD20, _DSC_PASS_THROUGH, _ENABLE, _YES, dscPassthroughByte);
|
||||
DP_LOG(("DP-DEV> Enabling DSC Pass through on branch device - %s",
|
||||
this->parent->getTopologyAddress().toString(buffer)));
|
||||
this->parent->getTopologyAddress().toString(buffer)));
|
||||
}
|
||||
|
||||
if (!bCurrDscEnable)
|
||||
@@ -1983,7 +1986,6 @@ bool DeviceImpl::setDscEnable(bool enable)
|
||||
{
|
||||
DP_LOG(("DP-DEV> DSC decompression is already enabled on device - %s",
|
||||
this->devDoingDscDecompression->getTopologyAddress().toString(buffer)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2005,22 +2007,40 @@ bool DeviceImpl::setDscEnable(bool enable)
|
||||
{
|
||||
DP_LOG(("DP-DEV> DSC decompression is already disabled on device - %s",
|
||||
this->devDoingDscDecompression->getTopologyAddress().toString(buffer)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bDscPassThrough)
|
||||
{
|
||||
if(this->parent->setDpcdData(NV_DPCD20_DSC_PASS_THROUGH,
|
||||
&dscPassthroughByte, sizeof dscPassthroughByte, &size, &nakReason))
|
||||
dscPassThroughStatus = this->parent->setDpcdData(NV_DPCD20_DSC_PASS_THROUGH,
|
||||
&dscPassthroughByte, sizeof dscPassthroughByte, &size, &nakReason);
|
||||
if (dscPassThroughStatus != AuxBus::success)
|
||||
{
|
||||
DP_LOG(("DP-DEV> Setting DSC Passthrough state on parent branch failed"));
|
||||
bDscPassThroughUpdated = false;
|
||||
DP_LOG(("DP-DEV> Setting DSC Passthrough on parent branch %s failed",
|
||||
this->parent->getTopologyAddress().toString(buffer)));
|
||||
}
|
||||
}
|
||||
|
||||
return (!this->devDoingDscDecompression->setDpcdData(NV_DPCD14_DSC_ENABLE,
|
||||
&dscEnableByte, sizeof dscEnableByte, &size, &nakReason)) && bDscPassThroughUpdated;
|
||||
if (enable != bCurrDscEnable)
|
||||
{
|
||||
dscEnableStatus = this->devDoingDscDecompression->setDpcdData(NV_DPCD14_DSC_ENABLE,
|
||||
&dscEnableByte, sizeof dscEnableByte, &size, &nakReason);
|
||||
if (dscEnableStatus != AuxBus::success)
|
||||
{
|
||||
DP_LOG(("DP-DEV> Setting DSC Enable on sink %s failed",
|
||||
this->devDoingDscDecompression->getTopologyAddress().toString(buffer)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ((dscPassThroughStatus != AuxBus::success) || (dscEnableStatus != AuxBus::success))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned DeviceImpl::getDscVersionMajor()
|
||||
@@ -2236,6 +2256,124 @@ bool DeviceImpl::getPCONCaps(PCONCaps *pPCONCaps)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceImpl::getIgnoreMSACap()
|
||||
{
|
||||
NvU8 byte = 0;
|
||||
unsigned size = 0;
|
||||
unsigned nakReason = NakUndefined;
|
||||
AuxBus::status status;
|
||||
|
||||
if (bIgnoreMsaCapCached)
|
||||
{
|
||||
return bIgnoreMsaCap;
|
||||
}
|
||||
|
||||
if (this->isMultistream())
|
||||
{
|
||||
status = this->getDpcdData(NV_DPCD_DOWN_STREAM_PORT,
|
||||
&byte, sizeof byte, &size, &nakReason);
|
||||
if (status == AuxBus::success)
|
||||
{
|
||||
if(FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _YES, byte))
|
||||
{
|
||||
if (this->parent && this->parent->isVirtualPeerDevice())
|
||||
{
|
||||
byte = 0;
|
||||
size = 0;
|
||||
nakReason = NakUndefined;
|
||||
|
||||
status = this->parent->getDpcdData(NV_DPCD_DOWN_STREAM_PORT,
|
||||
&byte, sizeof byte, &size, &nakReason);
|
||||
if (status == AuxBus::success)
|
||||
{
|
||||
if(FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _YES, byte))
|
||||
{
|
||||
bIgnoreMsaCap = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bIgnoreMsaCap = false;
|
||||
}
|
||||
bIgnoreMsaCapCached = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bIgnoreMsaCap = true;
|
||||
bIgnoreMsaCapCached = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bIgnoreMsaCap = false;
|
||||
bIgnoreMsaCapCached = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bIgnoreMsaCap = hal->getMsaTimingparIgnored();
|
||||
bIgnoreMsaCapCached = true;
|
||||
}
|
||||
|
||||
return bIgnoreMsaCap;
|
||||
}
|
||||
|
||||
AuxRetry::status DeviceImpl::setIgnoreMSAEnable(bool msaTimingParamIgnoreEn)
|
||||
{
|
||||
NvU8 byte = 0;
|
||||
unsigned size = 0;
|
||||
unsigned nakReason = NakUndefined;
|
||||
AuxBus::status status;
|
||||
|
||||
if (this->isMultistream())
|
||||
{
|
||||
status = this->getDpcdData(NV_DPCD_DOWNSPREAD_CTRL,
|
||||
&byte, sizeof byte, &size, &nakReason);
|
||||
if (status == AuxBus::success)
|
||||
{
|
||||
if (msaTimingParamIgnoreEn)
|
||||
{
|
||||
byte = FLD_SET_DRF(_DPCD, _DOWNSPREAD_CTRL, _MSA_TIMING_PAR_IGNORED, _TRUE, byte);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte = FLD_SET_DRF(_DPCD, _DOWNSPREAD_CTRL, _MSA_TIMING_PAR_IGNORED, _FALSE, byte);
|
||||
}
|
||||
|
||||
status = this->setDpcdData(NV_DPCD_DOWNSPREAD_CTRL,
|
||||
&byte, sizeof byte, &size, &nakReason);
|
||||
if (status == AuxBus::success)
|
||||
{
|
||||
return AuxRetry::ack;
|
||||
}
|
||||
else
|
||||
{
|
||||
DP_LOG(("DP-DEV> Aux Write to DPCD offset 0x107 failed!"));
|
||||
return AuxRetry::nack;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!"));
|
||||
return AuxRetry::nack;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return hal->setIgnoreMSATimingParamters(msaTimingParamIgnoreEn);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeviceHDCPDetection::start()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1993-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1993-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -94,8 +94,6 @@ 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_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},
|
||||
{NV_DP_REGKEY_DPCD_PROBING_FOR_BUSY_WAITING, &dpRegkeyDatabase.bDpcdProbingForBusyWaiting, DP_REG_VAL_BOOL}
|
||||
};
|
||||
@@ -1048,6 +1046,7 @@ bool EvoMainLink::train(const LinkConfiguration & link, bool force,
|
||||
case EDP_3_24GHZ:
|
||||
case EDP_4_32GHZ:
|
||||
case HBR2:
|
||||
case EDP_6_75GHZ:
|
||||
case HBR3:
|
||||
linkBw = linkrate / DP_LINK_BW_FREQ_MULTI_MBPS;
|
||||
dpCtrlData = FLD_SET_DRF_NUM(0073_CTRL, _DP_DATA, _SET_LINK_BW,
|
||||
@@ -1797,6 +1796,7 @@ bool EvoMainLink::configureLinkRateTable
|
||||
case linkBW_3_24Gbps:
|
||||
case linkBW_4_32Gbps:
|
||||
case linkBW_5_40Gbps:
|
||||
case linkBW_6_75Gbps:
|
||||
case linkBW_8_10Gbps:
|
||||
pLinkRates->import(params.linkBwTbl[i]);
|
||||
break;
|
||||
|
||||
@@ -177,12 +177,59 @@ void GroupImpl::remove(Device * dev)
|
||||
|
||||
void GroupImpl::destroy()
|
||||
{
|
||||
ConnectorImpl* parent = NULL;
|
||||
for (Device * i = enumDevices(0); i; i = enumDevices(i))
|
||||
remove(i);
|
||||
|
||||
// Cancel any queue the auth callback.
|
||||
cancelHdcpCallbacks();
|
||||
|
||||
parent = this->parent;
|
||||
|
||||
if (parent)
|
||||
{
|
||||
if (!parent->activeGroups.isEmpty())
|
||||
{
|
||||
for (ListElement * i = parent->activeGroups.begin(); i != parent->activeGroups.end(); i = i->next)
|
||||
{
|
||||
GroupImpl * group = (GroupImpl *)i;
|
||||
if (group == this)
|
||||
{
|
||||
parent->activeGroups.remove(this);
|
||||
DP_LOG(("DP-GRP> Deleted group 0x%x from active group!", this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!parent->inactiveGroups.isEmpty())
|
||||
{
|
||||
for (ListElement * i = parent->inactiveGroups.begin(); i != parent->inactiveGroups.end(); i = i->next)
|
||||
{
|
||||
GroupImpl * group = (GroupImpl *)i;
|
||||
if (group == this)
|
||||
{
|
||||
parent->inactiveGroups.remove(this);
|
||||
DP_LOG(("DP-GRP> Deleted group 0x%x from inactive group!", this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parent->intransitionGroups.contains(this))
|
||||
{
|
||||
parent->intransitionGroups.remove(this);
|
||||
DP_LOG(("DP-GRP> Deleted group 0x%x from intransition group!", this));
|
||||
}
|
||||
|
||||
if (parent->addStreamMSTIntransitionGroups.contains(this))
|
||||
{
|
||||
parent->addStreamMSTIntransitionGroups.remove(this);
|
||||
DP_LOG(("DP-GRP> Deleted group 0x%x from addStreamMSTIntransitionGroups group!", this));
|
||||
}
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2010-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2010-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2010-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2010-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -240,10 +240,13 @@ bool DisplayPort::EdidReadSST(Edid & edid, AuxBus * auxBus, Timer* timer,
|
||||
Edid previousEdid;
|
||||
Buffer *buffer;
|
||||
bool status;
|
||||
|
||||
bool firstTrial = true;
|
||||
NvU64 startTime, elapsedTime;
|
||||
for (unsigned i = 0; i < ddcAddrListSize; i++)
|
||||
{
|
||||
for (unsigned j = 0; j < EDID_READ_MAX_RETRY_COUNT; j++)
|
||||
startTime = timer->getTimeUs();
|
||||
elapsedTime = 0;
|
||||
do
|
||||
{
|
||||
//
|
||||
// Client asks to use RM control code to fetch EDID.
|
||||
@@ -312,9 +315,10 @@ bool DisplayPort::EdidReadSST(Edid & edid, AuxBus * auxBus, Timer* timer,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (j == 0) // first failure?
|
||||
if (firstTrial) // first failure?
|
||||
{
|
||||
previousEdid.swap(edid);
|
||||
firstTrial = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -327,7 +331,9 @@ bool DisplayPort::EdidReadSST(Edid & edid, AuxBus * auxBus, Timer* timer,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elapsedTime = timer->getTimeUs() - startTime;
|
||||
timer->sleep(1);
|
||||
} while (elapsedTime < (EDID_READ_RETRY_TIMEOUT_MS * 1000));
|
||||
}
|
||||
|
||||
DP_LOG(("EDID> Failed to ping sst DDC addresses"));
|
||||
|
||||
Reference in New Issue
Block a user