1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 1993-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /******************************* DisplayPort********************************\
25 *                                                                           *
26 * Module: dp_connectorimpl.cpp                                              *
27 *    DP connector implementation                                            *
28 *                                                                           *
29 \***************************************************************************/
30 
31 #include "dp_internal.h"
32 #include "dp_guid.h"
33 #include "dp_configcaps.h"
34 #include "dp_list.h"
35 #include "dp_buffer.h"
36 #include "dp_auxdefs.h"
37 #include "dp_watermark.h"
38 #include "dp_edid.h"
39 #include "dp_discovery.h"
40 #include "dp_groupimpl.h"
41 #include "dp_deviceimpl.h"
42 #include "dp_connectorimpl.h"
43 
44 #include "dp_auxbus.h"
45 #include "dpringbuffertypes.h"
46 
47 #include "ctrl/ctrl0073/ctrl0073dfp.h"
48 #include "ctrl/ctrl0073/ctrl0073dp.h"
49 #include "dp_tracing.h"
50 
51 #define SET_DP_IMP_ERROR(pErrorCode, errorCode) \
52         if (pErrorCode && *pErrorCode == DP_IMP_ERROR_NONE) *pErrorCode = errorCode;
53 
54 using namespace DisplayPort;
55 
56 ConnectorImpl::ConnectorImpl(MainLink * main, AuxBus * auxBus, Timer * timer, Connector::EventSink * sink)
57     : main(main),
58       auxBus(auxBus),
59       timer(timer),
60       sink(sink),
61       bOuiCached(false),
62       bIgnoreSrcOuiHandshake(false),
63       linkPolicy(),
64       linkGuessed(false),
65       isLinkQuiesced(false),
66       bNoLtDoneAfterHeadDetach(false),
67       isDP12AuthCap(false),
68       isHDCPAuthOn(false),
69       isHDCPReAuthPending(false),
70       isHDCPAuthTriggered(false),
71       isHopLimitExceeded(false),
72       isDiscoveryDetectComplete(false),
73       bDeferNotifyLostDevice(false),
74       hdcpValidateData(),
75       authRetries(0),
76       retryLT(0),
77       hdcpCapsRetries(0),
78       hdcpCpIrqRxStatusRetries(0),
79       bFromResumeToNAB(false),
80       bAttachOnResume(false),
81       bHdcpAuthOnlyOnDemand(false),
82       constructorFailed(false),
83       policyModesetOrderMitigation(false),
84       policyForceLTAtNAB(false),
85       policyAssessLinkSafely(false),
86       bDisableVbiosScratchRegisterUpdate(false),
87       modesetOrderMitigation(false),
88       compoundQueryActive(false),
89       compoundQueryResult(false),
90       compoundQueryCount(0),
91       messageManager(0),
92       discoveryManager(0),
93       numPossibleLnkCfg(0),
94       linkAwaitingTransition(false),
95       linkState(DP_TRANSPORT_MODE_INIT),
96       bAudioOverRightPanel(false),
97       connectorActive(false),
98       firmwareGroup(0),
99       bAcpiInitDone(false),
100       bIsUefiSystem(false),
101       bSkipLt(false),
102       bMitigateZombie(false),
103       bDelayAfterD3(false),
104       bKeepOptLinkAlive(false),
105       bNoFallbackInPostLQA(false),
106       LT2FecLatencyMs(0),
107       bFECEnable(false),
108       bDscCapBasedOnParent(false),
109       inTransitionHeadMask(0x0),
110       ResStatus(this)
111 {
112     clearTimeslices();
113     hal = MakeDPCDHAL(auxBus, timer);
114     if (hal == NULL)
115     {
116         constructorFailed = true;
117         return;
118     }
119     firmwareGroup = createFirmwareGroup();
120 
121     if (firmwareGroup == NULL)
122     {
123         constructorFailed = true;
124         return;
125     }
126 
127     main->queryGPUCapability();
128     main->queryAndUpdateDfpParams();
129 
130     hal->setPC2Disabled(main->isPC2Disabled());
131 
132     //
133     // If a GPU is DP1.2 or DP1.4 supported then set these capalibilities.
134     // This is used for accessing DP1.2/DP1.4 specific register space & features
135     //
136     hal->setGpuDPSupportedVersions(main->getGpuDpSupportedVersions());
137 
138     // Set if GPU supports FEC. Check panel FEC caps only if GPU supports it.
139     hal->setGpuFECSupported(main->isFECSupported());
140 
141     // Set if LTTPR training is supported per regKey
142     hal->setLttprSupported(main->isLttprSupported());
143 
144 
145     const DP_REGKEY_DATABASE& dpRegkeyDatabase = main->getRegkeyDatabase();
146     this->applyRegkeyOverrides(dpRegkeyDatabase);
147     hal->applyRegkeyOverrides(dpRegkeyDatabase);
148 
149     highestAssessedLC = getMaxLinkConfig();
150 }
151 
152 void ConnectorImpl::applyRegkeyOverrides(const DP_REGKEY_DATABASE& dpRegkeyDatabase)
153 {
154     DP_ASSERT(dpRegkeyDatabase.bInitialized &&
155               "All regkeys are invalid because dpRegkeyDatabase is not initialized!");
156 
157     this->bSkipAssessLinkForEDP = dpRegkeyDatabase.bAssesslinkForEdpSkipped;
158 
159     // If Hdcp authenticatoin on demand regkey is set, override to the provided value.
160     this->bHdcpAuthOnlyOnDemand = dpRegkeyDatabase.bHdcpAuthOnlyOnDemand;
161 
162     if (dpRegkeyDatabase.bOptLinkKeptAlive)
163     {
164         this->bKeepLinkAliveMST = true;
165         this->bKeepLinkAliveSST = true;
166     }
167     else
168     {
169         this->bKeepLinkAliveMST = dpRegkeyDatabase.bOptLinkKeptAliveMst;
170         this->bKeepLinkAliveSST = dpRegkeyDatabase.bOptLinkKeptAliveSst;
171     }
172     this->bReportDeviceLostBeforeNew    = dpRegkeyDatabase.bReportDeviceLostBeforeNew;
173     this->maxLinkRateFromRegkey         = dpRegkeyDatabase.applyMaxLinkRateOverrides;
174     this->bEnableAudioBeyond48K         = dpRegkeyDatabase.bAudioBeyond48kEnabled;
175     this->bDisableSSC                   = dpRegkeyDatabase.bSscDisabled;
176     this->bEnableFastLT                 = dpRegkeyDatabase.bFastLinkTrainingEnabled;
177     this->bDscMstCapBug3143315          = dpRegkeyDatabase.bDscMstCapBug3143315;
178     this->bPowerDownPhyBeforeD3         = dpRegkeyDatabase.bPowerDownPhyBeforeD3;
179     this->bReassessMaxLink              = dpRegkeyDatabase.bReassessMaxLink;
180 }
181 
182 void ConnectorImpl::setPolicyModesetOrderMitigation(bool enabled)
183 {
184     policyModesetOrderMitigation = enabled;
185 }
186 
187 void ConnectorImpl::setPolicyForceLTAtNAB(bool enabled)
188 {
189     policyForceLTAtNAB = enabled;
190 }
191 
192 void ConnectorImpl::setPolicyAssessLinkSafely(bool enabled)
193 {
194     policyAssessLinkSafely = enabled;
195 }
196 
197 //
198 // This function is to re-read remote HDCP BKSV and BCAPS.
199 //
200 // Function is added for DP1.2 devices which don't have valid BKSV at HPD and
201 // make BKSV available after Payload Ack.
202 //
203 void ConnectorImpl::readRemoteHdcpCaps()
204 {
205     if (hdcpCapsRetries)
206     {
207         fireEvents();
208         return;
209     }
210 
211 }
212 
213 void ConnectorImpl::discoveryDetectComplete()
214 {
215     fireEvents();
216     // no outstanding EDID reads and branch/sink detections for MST
217     if (pendingEdidReads.isEmpty() &&
218         (!discoveryManager ||
219          (discoveryManager->outstandingBranchDetections.isEmpty() &&
220           discoveryManager->outstandingSinkDetections.isEmpty())))
221     {
222         bDeferNotifyLostDevice = false;
223         isDiscoveryDetectComplete = true;
224         bIsDiscoveryDetectActive = false;
225 
226         // Complete detection and see if can enter power saving state.
227         isNoActiveStreamAndPowerdown();
228 
229         fireEvents();
230     }
231 }
232 
233 void ConnectorImpl::applyEdidWARs(Edid & edid, DiscoveryManager::Device device)
234 {
235     DpMonitorDenylistData *pDenylistData = new DpMonitorDenylistData();
236     NvU32 warFlag = 0;
237     warFlag = main->monitorDenylistInfo(edid.getManufId(), edid.getProductId(), pDenylistData);
238 
239     // Apply any edid overrides if required
240     edid.applyEdidWorkArounds(warFlag, pDenylistData);
241 
242     delete pDenylistData;
243 }
244 
245 void DisplayPort::DevicePendingEDIDRead::mstEdidCompleted(EdidReadMultistream * from)
246 {
247     Address::StringBuffer sb;
248     DP_USED(sb);
249     DP_LOG(("DP-CONN> Edid read complete: %s %s",
250             from->topologyAddress.toString(sb),
251             from->edid.getName()));
252     ConnectorImpl * connector = parent;
253     parent->applyEdidWARs(from->edid, device);
254     parent->processNewDevice(device, from->edid, true, DISPLAY_PORT, RESERVED);
255     delete this;
256     connector->discoveryDetectComplete();
257 }
258 
259 void DisplayPort::DevicePendingEDIDRead::mstEdidReadFailed(EdidReadMultistream * from)
260 {
261     Address::StringBuffer sb;
262     DP_USED(sb);
263     DP_LOG(("DP-CONN> Edid read failed: %s (using fallback)",
264              from->topologyAddress.toString(sb)));
265     ConnectorImpl * connector = parent;
266     parent->processNewDevice(device, Edid(), true, DISPLAY_PORT, RESERVED);
267     delete this;
268     connector->discoveryDetectComplete();
269 }
270 
271 void ConnectorImpl::messageProcessed(MessageManager::MessageReceiver * from)
272 {
273     if (from == &ResStatus)
274     {
275         for (Device * i = enumDevices(0); i; i = enumDevices(i))
276             if (i->getGUID() == ResStatus.request.guid)
277             {
278                 DeviceImpl * child = ((DeviceImpl *)i)->children[ResStatus.request.port];
279                 if (child)
280                 {
281                     child->resetCacheInferredLink();
282                     sink->bandwidthChangeNotification((DisplayPort::Device*)child, false);
283                     return;
284                 }
285 
286                 break;
287             }
288 
289         // Child wasn't found... Invalidate all bandwidths on topology
290         for (Device * i = enumDevices(0); i; i = enumDevices(i)) {
291             ((DeviceImpl *)i)->resetCacheInferredLink();
292         }
293     }
294     else
295         DP_ASSERT(0 && "Received unexpected upstream message that we AREN'T registered for");
296 }
297 
298 void ConnectorImpl::discoveryNewDevice(const DiscoveryManager::Device & device)
299 {
300     //
301     //  We're guaranteed that there isn't already a device on the list with the same
302     //  address.  If we receive the same device announce again - it is considered
303     //  a notification that the device underlying may have seen an HPD.
304     //
305     //  We're going to queue an EDID read, and remember which device we did it on.
306     //  If the EDID comes back different we'll have mark the old device object
307     //  as disconnected - and create a new one.  This is required because
308     //  EDID is one of the fields considered to be immutable.
309     //
310 
311     if (!device.branch)
312     {
313         if (!device.videoSink)
314         {
315             // Don't read EDID on a device having no videoSink
316             processNewDevice(device, Edid(), false, DISPLAY_PORT, RESERVED);
317             return;
318         }
319         pendingEdidReads.insertBack(new DevicePendingEDIDRead(this, messageManager, device));
320     }
321     else
322     {
323         // Don't try to read the EDID on a branch device
324         processNewDevice(device, Edid(), true, DISPLAY_PORT, RESERVED);
325     }
326 }
327 
328 void ConnectorImpl::processNewDevice(const DiscoveryManager::Device & device,
329                                      const Edid & edid,
330                                      bool isMultistream,
331                                      DwnStreamPortType portType,
332                                      DwnStreamPortAttribute portAttribute,
333                                      bool isCompliance)
334 {
335     //
336     // Ideally we should read EDID here. But instead just report the device
337     //   try to find device in list of devices
338     //
339     DeviceImpl * existingDev = findDeviceInList(device.address);
340     if (existingDev)
341         existingDev->resetCacheInferredLink();
342 
343     //
344     //  Process fallback EDID
345     //
346     Edid processedEdid = edid;
347 
348     if (!edid.getEdidSize()   || !edid.isChecksumValid() || !edid.isValidHeader() ||
349         edid.isPatchedChecksum())
350     {
351         if (portType == WITHOUT_EDID)
352         {
353             switch(portAttribute)
354             {
355             case RESERVED:
356             case IL_720_480_60HZ:
357             case IL_720_480_50HZ:
358             case IL_1920_1080_60HZ:
359             case IL_1920_1080_50HZ:
360             case PG_1280_720_60HZ:
361             case PG_1280_720_50_HZ:
362                 DP_ASSERT(0 && "Default EDID feature not supported!");
363                 break;
364             }
365 
366         }
367         if (portType == ANALOG_VGA)
368             makeEdidFallbackVGA(processedEdid);
369         else
370         {
371             makeEdidFallback(processedEdid, hal->getVideoFallbackSupported());
372         }
373     }
374 
375     //
376     //  Process caps
377     //
378     bool   hasAudio = device.SDPStreams && device.SDPStreamSinks;
379     bool   hasVideo = device.videoSink;
380     NvU64  maxTmdsClkRate = 0U;
381     ConnectorType connector = connectorDisplayPort;
382 
383     if (portType == DISPLAY_PORT_PLUSPLUS || portType == DVI || portType == HDMI)
384     {
385         maxTmdsClkRate = device.maxTmdsClkRate;
386     }
387 
388     switch(portType)
389     {
390         case DISPLAY_PORT:
391         case DISPLAY_PORT_PLUSPLUS: // DP port that supports DP and TMDS
392             connector = connectorDisplayPort;
393             break;
394 
395         case ANALOG_VGA:
396             connector = connectorVGA;
397             break;
398 
399         case DVI:
400             connector = connectorDVI;
401             break;
402 
403         case HDMI:
404             connector = connectorHDMI;
405             break;
406 
407         case WITHOUT_EDID:
408             connector = connectorDisplayPort;
409             break;
410     }
411 
412     // Dongle in SST mode.
413     if ((device.peerDevice == Dongle) && (device.address.size() == 0))
414         hasAudio = hasVideo = false;
415 
416     if (device.branch)
417         hasAudio = hasVideo = false;
418 
419     if (!existingDev)
420         goto create;
421 
422     if (isCompliance && (existingDev->processedEdid == processedEdid))
423     {
424         // unzombie the old device
425     }
426     else if (existingDev->audioSink != hasAudio ||
427              existingDev->videoSink != hasVideo ||
428              existingDev->rawEDID != edid ||
429              existingDev->processedEdid != processedEdid ||
430              existingDev->connectorType != connector ||
431              existingDev->multistream != isMultistream ||
432              existingDev->complianceDeviceEdidReadTest != isCompliance ||
433              existingDev->maxTmdsClkRate != maxTmdsClkRate ||
434              (existingDev->address.size() > 1 && !existingDev->getParent()) ||
435              // If it is an Uninitialized Mux device, goto create so that we can properly
436              // initialize the device and all its caps
437              existingDev->isFakedMuxDevice())
438         goto create;
439 
440     // Complete match, make sure its marked as plugged
441     existingDev->plugged = true;
442      if (existingDev->isActive())
443         existingDev->activeGroup->update(existingDev, true);
444 
445 
446     fireEvents();
447     return;
448 create:
449     // If there is an existing device, mark it as no longer available.
450     if (existingDev)
451         existingDev->plugged = false;
452 
453     // Find parent
454     DeviceImpl * parent = 0;
455     if (device.address.size() != 0)
456     {
457         for (Device * i = enumDevices(0); i; i = enumDevices(i))
458         {
459             if ((i->getTopologyAddress() == device.address.parent()) &&
460                 (((DeviceImpl *)i)->plugged))
461             {
462                 parent = (DeviceImpl*)i;
463                 break;
464             }
465         }
466     }
467 
468     DP_ASSERT((parent || device.address.size() <= 1) && "Device was registered before parent");
469 
470     DeviceImpl * newDev;
471     //
472     // If it is a faked Mux device, we have already notified DD of few of its caps.
473     // Reuse the same device to make sure that DD updates the same device's parameters
474     // otherwise create a new device
475     //
476     if (existingDev && existingDev->isFakedMuxDevice())
477     {
478         newDev = existingDev;
479         existingDev = NULL;
480     }
481     else
482     {
483         newDev = new DeviceImpl(hal, this, parent);
484     }
485 
486     if (parent)
487         parent->children[device.address.tail()] = newDev;
488 
489     if (!newDev)
490     {
491         DP_ASSERT(0 && "new failed");
492         return;
493     }
494 
495     // Fill out the new device
496     newDev->address = device.address;
497     newDev->multistream = isMultistream;
498     newDev->videoSink = hasVideo;
499     newDev->audioSink = hasAudio;
500     newDev->plugged = true;
501     newDev->rawEDID = edid;
502     newDev->processedEdid = processedEdid;
503     newDev->connectorType = connector;
504     newDev->guid = device.peerGuid;
505     newDev->peerDevice = device.peerDevice;
506     newDev->portMap = device.portMap;
507     newDev->dpcdRevisionMajor = device.dpcdRevisionMajor;
508     newDev->dpcdRevisionMinor = device.dpcdRevisionMinor;
509     newDev->complianceDeviceEdidReadTest = isCompliance;
510     newDev->maxTmdsClkRate = maxTmdsClkRate;
511 
512     Address::NvU32Buffer addrBuffer;
513     dpMemZero(addrBuffer, sizeof(addrBuffer));
514     newDev->address.toNvU32Buffer(addrBuffer);
515     NV_DPTRACE_INFO(NEW_SINK_DETECTED, newDev->address.size(), addrBuffer[0], addrBuffer[1], addrBuffer[2], addrBuffer[3],
516                         newDev->multistream, newDev->rawEDID.getManufId(), newDev->rawEDID.getProductId());
517 
518     // Apply any DPCD overrides if required
519     newDev->dpcdOverrides();
520 
521     //
522     // Some 4K eDP panel needs HBR2 to support higher modes, Highest assessed LC
523     // remains in a stale state after applying DPCD overrides here. So we need to
524     // assess the link again.
525     //
526     if (newDev->isOptimalLinkConfigOverridden())
527     {
528         this->assessLink();
529     }
530 
531     // Panel has issues with LQA, reassess link
532     if (processedEdid.WARFlags.reassessMaxLink)
533     {
534         //
535         // If the highest assessed LC is not equal to max possible link config and
536         // panel is branch device which GPU is link training, re-assess link
537         //
538         int retries = 0;
539 
540         while((retries < WAR_MAX_REASSESS_ATTEMPT) && (highestAssessedLC != getMaxLinkConfig()))
541         {
542             DP_LOG(("DP> Assessed link is not equal to highest possible config. Reassess link."));
543             this->assessLink();
544             retries++;
545         }
546     }
547 
548     // Postpone the remote HDCPCap read for Dongles
549     DP_ASSERT(!isLinkInD3() && "Hdcp probe at D3");
550     if (device.peerDevice != Dongle)
551     {
552         DP_ASSERT(newDev->isDeviceHDCPDetectionAlive == false);
553         if ((newDev->deviceHDCPDetection = new DeviceHDCPDetection(newDev, messageManager, timer)))
554         {
555             //
556             // We cannot move the hdcpDetection after stream added because DD
557             // needs hdcp Cap before stream added.
558             //
559             newDev->isDeviceHDCPDetectionAlive = true;
560             newDev->deviceHDCPDetection->start();
561         }
562         else
563         {
564             // For the risk control, make the device as not HDCPCap.
565             DP_ASSERT(0 && "new failed");
566             newDev->isDeviceHDCPDetectionAlive = false;
567             newDev->isHDCPCap = False;
568 
569             if (!newDev->isMultistream())
570                 newDev->shadow.hdcpCapDone = true;
571         }
572     }
573 
574     newDev->vrrEnablement = new VrrEnablement(newDev);
575     if (!newDev->vrrEnablement)
576     {
577         DP_ASSERT(0 && "new VrrEnablement failed");
578     }
579 
580     BInfo bInfo;
581     if ((!isHopLimitExceeded) && (hal->getBinfo(bInfo)))
582     {
583         if (bInfo.maxCascadeExceeded || bInfo.maxDevsExceeded)
584         {
585             if (isHDCPAuthOn)
586             {
587                 isHDCPAuthOn = false;
588             }
589             isHopLimitExceeded = true;
590         }
591         else
592             isHopLimitExceeded = false;
593     }
594 
595     //
596     // If the device is a faked Mux device, then we just initizlied it.
597     // Reset its faked status and skip adding it to the deviceList
598     //
599     if (newDev->isFakedMuxDevice())
600     {
601         newDev->bIsFakedMuxDevice = false;
602         newDev->bIsPreviouslyFakedMuxDevice = true;
603     }
604     else
605     {
606         deviceList.insertBack(newDev);
607     }
608 
609     // if a new device has replaced a previous compliance device; let this event be exposed to DD now.
610     // ie : the old device will be zombied/lost now ... lazily(instead of at an unplug which happened a while back.)
611     if (existingDev && existingDev->complianceDeviceEdidReadTest)
612         existingDev->lazyExitNow = true;
613 
614     if(newDev->isBranchDevice() && newDev->isAtLeastVersion(1,4))
615     {
616         //
617         // GUID_2 will be non-zero for a virtual peer device and 0 for others.
618         // This will help identify if a device is virtual peer device or not.
619         //
620         newDev->queryGUID2();
621     }
622 
623     if (!linkAwaitingTransition)
624     {
625         //
626         // When link is awaiting SST<->MST transition, DSC caps read from downstream
627         // DSC branch device might be wrong. DSC Caps exposed by DSC MST branch depends
628         // on the current link state. If it is in SST mode ie MST_EN (0x111[bit 0]) is 0 and
629         // panel connected behind it supports DSC, then branch will expose the DSC caps
630         // of the panel connected down stream rather than it's own. This is because source
631         // will have no other way to read the caps of the downstream panel. In fact when
632         // MST_EN = 0 and UP_REQ_EN (0x111 [bit 1]) = 1 source can read the caps of the
633         // downstream panel using REMOTE_DPCD_READ but branch device's behavior depends
634         // only on MST_EN bit. Similarly in SST, if the panel connected downstream to branch
635         // does not support DSC, DSC MST branch will expose it's own DSC caps.
636         // During boot since VBIOS drives display in SST mode and when driver takes over,
637         // linkAwaitingTransition will be true. DpLib does link assessment and topology
638         // discovery by setting UP_REQ_EN to true while still keeping MST_EN to false.
639         // This is to ensure we detach the head and active modeset groups that are in SST mode
640         // before switching the link to MST mode. When processNewDevice is called at this
641         // point to create new devices we should not read DSC caps due to above mentioned reason.
642         // As long as linkIsAwaitingTransition is true, Dplib will not report new Devices to
643         // to client since isPendingNewDevice() will be false even though DPlib discovered
644         // new devices. After Dplib completes topology discovery, DD initiates notifyDetachBegin/End
645         // to remove active groups from the link and notifyDetachEnd calls assessLink
646         // where we toggle the link state. Only after this we should read DSC caps in this case.
647         // Following this assesslink calls fireEvents() which will report
648         // the new devies to clients and client will have the correct DSC caps.
649         //
650         bool bGpuDscSupported;
651 
652         // Check GPU DSC Support
653         main->getDscCaps(&bGpuDscSupported);
654         if (bGpuDscSupported)
655         {
656             if (newDev->getDSCSupport())
657             {
658                 // Read and parse DSC caps only if panel supports DSC
659                 newDev->readAndParseDSCCaps();
660 
661                 // Read and Parse Branch Specific DSC Caps
662                 if (!newDev->isVideoSink() && !newDev->isAudioSink())
663                 {
664                     newDev->readAndParseBranchSpecificDSCCaps();
665                 }
666             }
667 
668             if (!processedEdid.WARFlags.bIgnoreDscCap)
669             {
670                 // Check if DSC is possible for the device and if so, set DSC Decompression device.
671                 newDev->setDscDecompressionDevice(this->bDscCapBasedOnParent);
672             }
673         }
674     }
675 
676     if (newDev->peerDevice == Dongle)
677     {
678         // For Dongle, we need to read detailed port caps if DPCD access is available on DP 1.4+.
679         if (newDev->isAtLeastVersion(1,4))
680         {
681             newDev->getPCONCaps(&(newDev->pconCaps));
682         }
683 
684         //
685         // If dongle does not have DPCD access but it is native PCON with Virtual peer support,
686         // we can get dongle port capabilities from parent VP DPCD detailed port descriptors.
687         //
688         else if (newDev->parent && (newDev->parent)->isVirtualPeerDevice())
689         {
690             newDev->parent->getPCONCaps(&(newDev->pconCaps));
691             newDev->connectorType = newDev->parent->getConnectorType();
692         }
693     }
694 
695     // Read panel replay capabilities
696     newDev->getPanelReplayCaps();
697 
698     // Get Panel FEC support only if GPU supports FEC
699     if (this->isFECSupported())
700     {
701         newDev->getFECSupport();
702     }
703 
704     if (main->supportMSAOverMST())
705     {
706         newDev->bMSAOverMSTCapable = newDev->getSDPExtnForColorimetrySupported();
707     }
708     else
709     {
710         newDev->bMSAOverMSTCapable = false;
711     }
712 
713     newDev->applyOUIOverrides();
714 
715     if (main->isEDP() && !bOuiCached)
716     {
717         // Save Source OUI information for eDP.
718         hal->getOuiSource(cachedSourceOUI, &cachedSourceModelName[0],
719                           sizeof(cachedSourceModelName), cachedSourceChipRevision);
720         bOuiCached = true;
721     }
722 
723     fireEvents();
724 }
725 
726 LinkRates* ConnectorImpl::importDpLinkRates()
727 {
728     LinkRate   linkRate;
729     LinkRates  *pConnectorLinkRates = linkPolicy.getLinkRates();
730 
731     // Attempt to configure link rate table mode if supported
732     if (hal->isIndexedLinkrateCapable() &&
733         main->configureLinkRateTable(hal->getLinkRateTable(), pConnectorLinkRates))
734     {
735         // Maximal link rate is limited with link rate table
736         hal->overrideOptimalLinkRate(pConnectorLinkRates->getMaxRate());
737         hal->setIndexedLinkrateEnabled(true);
738     }
739     else
740     {
741         // Reset configured link rate table if ever enabled to get RM act right
742         if (hal->isIndexedLinkrateEnabled())
743         {
744             main->configureLinkRateTable(NULL, NULL);
745             hal->setIndexedLinkrateEnabled(false);
746         }
747 
748         // Get maximal link rate supported by GPU
749         linkRate = main->maxLinkRateSupported();
750 
751         // Insert by order
752         pConnectorLinkRates->clear();
753 
754         if (linkRate >= RBR)
755             pConnectorLinkRates->import((NvU8)linkBW_1_62Gbps);
756 
757         if (linkRate >= HBR)
758             pConnectorLinkRates->import((NvU8)linkBW_2_70Gbps);
759 
760         if (linkRate >= HBR2)
761             pConnectorLinkRates->import((NvU8)linkBW_5_40Gbps);
762 
763         if (linkRate >= HBR3)
764             pConnectorLinkRates->import((NvU8)linkBW_8_10Gbps);
765     }
766     return pConnectorLinkRates;
767 }
768 
769 void ConnectorImpl::populateAllDpConfigs()
770 {
771     LinkRate   linkRate;
772     LinkRates  *pConnectorLinkRates = linkPolicy.getLinkRates();
773 
774     unsigned   laneCounts[] = {laneCount_1, laneCount_2, laneCount_4};
775     unsigned   laneSets = sizeof(laneCounts) / sizeof(laneCounts[0]);
776 
777     //
778     //    Following sequence is to be followed for saving power by default;
779     //    It may vary with sinks which support link rate table.
780     //
781     //    Link Config     MBPS
782     //    1*RBR           162
783     //    1*HBR           270
784     //    2*RBR           324
785     //    1*HBR2          540
786     //    2*HBR           540
787     //    4*RBR           648
788     //    1*HBR3          810
789     //    ...
790     //
791     if (numPossibleLnkCfg)
792     {
793         DP_LOG(("DP> DPCONN> Rebuild possible link rate confgiurations"));
794         delete[] allPossibleLinkCfgs;
795         numPossibleLnkCfg = 0;
796     }
797 
798     importDpLinkRates();
799 
800     numPossibleLnkCfg = laneSets * pConnectorLinkRates->getNumLinkRates();
801     if (numPossibleLnkCfg == 0)
802     {
803         DP_LOG(("DPCONN> %s: lane count %d or link rates %d!",
804                 __FUNCTION__, pConnectorLinkRates->getNumLinkRates(), laneSets));
805         DP_ASSERT(0 && "Invalid lane count or link rates!");
806         return;
807     }
808 
809     allPossibleLinkCfgs = new LinkConfiguration[numPossibleLnkCfg]();
810 
811     if (allPossibleLinkCfgs == NULL)
812     {
813         DP_LOG(("DPCONN> %s: Failed to allocate allPossibleLinkCfgs array",
814                 __FUNCTION__));
815         numPossibleLnkCfg = 0;
816         return;
817     }
818 
819     // Populate all possible link configuration
820     linkRate = pConnectorLinkRates->getMaxRate();
821     for (unsigned i = 0; i < pConnectorLinkRates->getNumLinkRates(); i++)
822     {
823         for (unsigned j = 0; j < laneSets; j++)
824         {
825             allPossibleLinkCfgs[i * laneSets + j].setLaneRate(linkRate, laneCounts[j]);
826         }
827         linkRate = pConnectorLinkRates->getLowerRate(linkRate);
828     }
829 
830     // Sort link configurations per bandwidth from low to high
831     for (unsigned i = 0; i < numPossibleLnkCfg - 1; i++)
832     {
833         LinkConfiguration *pLowCfg = &allPossibleLinkCfgs[i];
834         for (unsigned j = i + 1; j < numPossibleLnkCfg; j++)
835         {
836             if (allPossibleLinkCfgs[j] < *pLowCfg)
837                 pLowCfg = &allPossibleLinkCfgs[j];
838         }
839         // Swap
840         if (pLowCfg != &allPossibleLinkCfgs[i])
841         {
842             LinkRate swapRate  = pLowCfg->peakRate;
843             unsigned swapLanes = pLowCfg->lanes;
844             pLowCfg->setLaneRate(allPossibleLinkCfgs[i].peakRate,
845                                  allPossibleLinkCfgs[i].lanes);
846             allPossibleLinkCfgs[i].setLaneRate(swapRate, swapLanes);
847         }
848     }
849 }
850 
851 void ConnectorImpl::discoveryLostDevice(const Address & address)
852 {
853     DeviceImpl * existingDev = findDeviceInList(address);
854 
855     if (!existingDev)
856     {
857         DP_ASSERT(0 && "Device lost on device not in database?!");
858         return;
859     }
860 
861     existingDev->plugged = false;
862     existingDev->devDoingDscDecompression = NULL;
863     fireEvents();
864 }
865 
866 ConnectorImpl::~ConnectorImpl()
867 {
868     if (numPossibleLnkCfg)
869         delete[] allPossibleLinkCfgs;
870 
871     timer->cancelCallbacks(this);
872     delete discoveryManager;
873     pendingEdidReads.clear();
874     delete messageManager;
875     delete hal;
876 }
877 
878 //
879 //   Clear all the state associated with the head attachment
880 //
881 void ConnectorImpl::hardwareWasReset()
882 {
883     activeLinkConfig.lanes = 0;
884 
885     while (!activeGroups.isEmpty())
886     {
887         GroupImpl * g = (GroupImpl *)activeGroups.front();
888         activeGroups.remove(g);
889         inactiveGroups.insertBack(g);
890 
891         g->setHeadAttached(false);
892     }
893 }
894 
895 Group * ConnectorImpl::resume(bool firmwareLinkHandsOff,
896                               bool firmwareDPActive,
897                               bool plugged,
898                               bool isUefiSystem,
899                               unsigned firmwareHead,
900                               bool bFirmwareLinkUseMultistream,
901                               bool bDisableVbiosScratchRegisterUpdate,
902                               bool bAllowMST)
903 {
904     Group  * result = 0;
905     hardwareWasReset();
906     previousPlugged = false;
907     connectorActive = true;
908     bIsUefiSystem = isUefiSystem;
909 
910     this->bDisableVbiosScratchRegisterUpdate = bDisableVbiosScratchRegisterUpdate;
911 
912     bFromResumeToNAB = true;
913 
914     if (firmwareLinkHandsOff)
915     {
916         isLinkQuiesced = true;
917     }
918     else if (firmwareDPActive)
919     {
920         DP_LOG(("CONN> Detected firmware panel is active on head %d.", firmwareHead));
921         ((GroupImpl *)firmwareGroup)->setHeadAttached(true);
922         ((GroupImpl *)firmwareGroup)->headIndex = firmwareHead;
923         ((GroupImpl *)firmwareGroup)->streamIndex = 1;
924         ((GroupImpl *)firmwareGroup)->headInFirmware = true;
925 
926         this->linkState = bFirmwareLinkUseMultistream ? DP_TRANSPORT_MODE_MULTI_STREAM : DP_TRANSPORT_MODE_SINGLE_STREAM;
927 
928         inactiveGroups.remove((GroupImpl *)firmwareGroup);
929         activeGroups.remove((GroupImpl *)firmwareGroup);
930         activeGroups.insertBack((GroupImpl *)firmwareGroup);
931 
932         result = firmwareGroup;
933     }
934 
935     hal->overrideMultiStreamCap(bAllowMST);
936 
937     //
938     // In resume code path, all devices on this connector gets lost and deleted on first fireEvents()
939     // and that could generate unnecessary new/lost device events. Therefore defer to lost devices
940     // until discovery detect gets completed, this allows processNewDevice() function to look
941     // at matching existing devices and optimize creation of new devices. We only have to set the flag
942     // to true when plugged = true, since if disconnected, we are not going to defer anything.
943     //
944     bDeferNotifyLostDevice = plugged;
945     bAttachOnResume = true;
946     notifyLongPulse(plugged);
947     bAttachOnResume = false;
948 
949     return result;
950 }
951 
952 
953 void ConnectorImpl::pause()
954 {
955     connectorActive = false;
956     if (messageManager)
957     {
958         messageManager->pause();
959     }
960 }
961 
962 // Query current Device topology
963 Device * ConnectorImpl::enumDevices(Device * previousDevice)
964 {
965     if (previousDevice)
966         previousDevice = (DeviceImpl *)((DeviceImpl*)previousDevice)->next;
967     else
968         previousDevice = (DeviceImpl *)deviceList.begin();
969 
970     if ((DeviceImpl*)previousDevice == deviceList.end())
971         return 0;
972     else
973         return (DeviceImpl *)previousDevice;
974 }
975 
976 LinkConfiguration ConnectorImpl::getMaxLinkConfig()
977 {
978     NvU64 maxLinkRate;
979 
980     DP_ASSERT(hal);
981 
982     if (main->isEDP())
983     {
984         // Regkey is supported on eDP panels only
985         maxLinkRate = maxLinkRateFromRegkey;
986         // Check if valid value is present in regkey
987         if (maxLinkRate && (IS_VALID_LINKBW(maxLinkRate)))
988         {
989             maxLinkRate = maxLinkRate * DP_LINK_BW_FREQ_MULTI_MBPS;
990         }
991         else
992         {
993             maxLinkRate = hal->getMaxLinkRate();
994         }
995     }
996     else
997     {
998         maxLinkRate = hal->getMaxLinkRate();
999     }
1000 
1001     LinkRate linkRate = maxLinkRate ?
1002                 DP_MIN(maxLinkRate, main->maxLinkRateSupported()) :
1003                 main->maxLinkRateSupported();
1004 
1005     unsigned laneCount = hal->getMaxLaneCount() ?
1006                         DP_MIN(hal->getMaxLaneCountSupportedAtLinkRate(linkRate), hal->getMaxLaneCount()) :
1007                         4;
1008 
1009     return LinkConfiguration (&this->linkPolicy,
1010                             laneCount, linkRate,
1011                             this->hal->getEnhancedFraming(),
1012                             linkUseMultistream(),
1013                             false,  /* disablePostLTRequest */
1014                             this->bFECEnable);
1015 }
1016 
1017 LinkConfiguration ConnectorImpl::getActiveLinkConfig()
1018 {
1019     DP_ASSERT(hal);
1020 
1021     return activeLinkConfig;
1022 }
1023 
1024 void ConnectorImpl::beginCompoundQuery(const bool bForceEnableFEC)
1025 {
1026     if (linkGuessed && (main->getSorIndex() != DP_INVALID_SOR_INDEX))
1027     {
1028         assessLink();
1029     }
1030 
1031     DP_ASSERT( !compoundQueryActive && "Previous compoundQuery was not ended.");
1032     compoundQueryActive = true;
1033     compoundQueryCount = 0;
1034     compoundQueryResult = true;
1035     compoundQueryLocalLinkPBN = 0;
1036     compoundQueryForceEnableFEC = bForceEnableFEC;
1037 
1038     for (Device * i = enumDevices(0); i; i=enumDevices(i))
1039     {
1040         DeviceImpl * dev = (DeviceImpl *)i;
1041 
1042         if (i->getTopologyAddress().size() <= 1)
1043         {
1044             dev->bandwidth.lastHopLinkConfig = highestAssessedLC;
1045             dev->bandwidth.compound_query_state.totalTimeSlots = 63;
1046             dev->bandwidth.compound_query_state.timeslots_used_by_query = 0;
1047             continue;
1048         }
1049 
1050         if (!this->linkUseMultistream())
1051             continue;
1052 
1053         // Initialize starting conditions
1054         //
1055         // Note: this compound query code assumes that the total bandwidth is
1056         // available for the configuration being queried.  This ignores the
1057         // concentrator case where some bandwidth may be in use by streams not
1058         // controlled by this driver instance.  Concentrators are currently not
1059         // supported.
1060         dev->bandwidth.compound_query_state.timeslots_used_by_query = 0;
1061         dev->inferLeafLink(&dev->bandwidth.compound_query_state.totalTimeSlots);
1062 
1063         //
1064         // Some VBIOS leave the branch in stale state and allocatePayload request queued
1065         // at branch end gets processed much later causing the FreePBN returned to be stale.
1066         // Clear the PBN in case EPR reports 0 free PBN when we have not explicitly requested
1067         // for it, to clear up any previous stale allocations
1068         //
1069         if (dev->bandwidth.compound_query_state.totalTimeSlots == 0 &&
1070            !dev->payloadAllocated && dev->plugged)
1071         {
1072             GroupImpl *group = dev->activeGroup;
1073             if (group != NULL)
1074             {
1075                 NakData nakData;
1076                 Address devAddress = dev->getTopologyAddress();
1077 
1078                 AllocatePayloadMessage allocate;
1079                 unsigned sink = 0;    // hardcode the audio sink to 0th in the device.
1080                 allocate.set(devAddress.parent(), devAddress.tail(),
1081                     dev->isAudioSink() ? 1 : 0, group->streamIndex, 0, &sink, true);
1082 
1083                 ((DeviceImpl *)dev)->bandwidth.enum_path.dataValid = false;
1084 
1085                 if (group->parent->messageManager->send(&allocate, nakData))
1086                     dev->inferLeafLink(&dev->bandwidth.compound_query_state.totalTimeSlots);
1087             }
1088         }
1089 
1090         // Clear assement state
1091         dev->bandwidth.compound_query_state.bandwidthAllocatedForIndex = 0;
1092     }
1093 }
1094 
1095 static DP_IMP_ERROR translatePpsErrorToDpImpError(NVT_STATUS ppsErrorCode)
1096 {
1097     switch (ppsErrorCode)
1098     {
1099         case NVT_STATUS_COLOR_FORMAT_NOT_SUPPORTED:
1100             return DP_IMP_ERROR_PPS_COLOR_FORMAT_NOT_SUPPORTED;
1101         case NVT_STATUS_INVALID_HBLANK:
1102             return DP_IMP_ERROR_PPS_INVALID_HBLANK;
1103         case NVT_STATUS_INVALID_BPC:
1104             return DP_IMP_ERROR_PPS_INVALID_BPC;
1105         case NVT_STATUS_MAX_LINE_BUFFER_ERROR:
1106             return DP_IMP_ERROR_PPS_MAX_LINE_BUFFER_ERROR;
1107         case NVT_STATUS_OVERALL_THROUGHPUT_ERROR:
1108             return DP_IMP_ERROR_PPS_OVERALL_THROUGHPUT_ERROR;
1109         case NVT_STATUS_DSC_SLICE_ERROR:
1110             return DP_IMP_ERROR_PPS_DSC_SLICE_ERROR;
1111         case NVT_STATUS_PPS_SLICE_COUNT_ERROR:
1112             return DP_IMP_ERROR_PPS_PPS_SLICE_COUNT_ERROR;
1113         case NVT_STATUS_PPS_SLICE_HEIGHT_ERROR:
1114             return DP_IMP_ERROR_PPS_PPS_SLICE_HEIGHT_ERROR;
1115         case NVT_STATUS_PPS_SLICE_WIDTH_ERROR:
1116             return DP_IMP_ERROR_PPS_PPS_SLICE_WIDTH_ERROR;
1117         case NVT_STATUS_INVALID_PEAK_THROUGHPUT:
1118             return DP_IMP_ERROR_PPS_INVALID_PEAK_THROUGHPUT;
1119         case NVT_STATUS_MIN_SLICE_COUNT_ERROR:
1120             return DP_IMP_ERROR_PPS_MIN_SLICE_COUNT_ERROR;
1121         default:
1122             return DP_IMP_ERROR_PPS_GENERIC_ERROR;
1123     }
1124 }
1125 
1126 //
1127 // This call will be deprecated as soon as all clients move to the new API
1128 //
1129 bool ConnectorImpl::compoundQueryAttach(Group * target,
1130                                         unsigned twoChannelAudioHz,         // if you need 192khz stereo specify 192000 here
1131                                         unsigned eightChannelAudioHz,       // Same setting for multi channel audio.
1132                                                                             //  DisplayPort encodes 3-8 channel streams as 8 channel
1133                                         NvU64 pixelClockHz,                 // Requested pixel clock for the mode
1134                                         unsigned rasterWidth,
1135                                         unsigned rasterHeight,
1136                                         unsigned rasterBlankStartX,
1137                                         unsigned rasterBlankEndX,
1138                                         unsigned depth,
1139                                         DP_IMP_ERROR *pErrorCode)
1140 {
1141     ModesetInfo modesetInfo(twoChannelAudioHz, eightChannelAudioHz, pixelClockHz,
1142                             rasterWidth, rasterHeight, (rasterBlankStartX - rasterBlankEndX),
1143                             0/*surfaceHeight*/, depth, rasterBlankStartX, rasterBlankEndX);
1144 
1145     DpModesetParams modesetParams(0, modesetInfo);
1146     return compoundQueryAttach(target, modesetParams, NULL, pErrorCode);
1147 }
1148 
1149 bool ConnectorImpl::compoundQueryAttach(Group * target,
1150                                         const DpModesetParams &modesetParams,         // Modeset info
1151                                         DscParams *pDscParams,                        // DSC parameters
1152                                         DP_IMP_ERROR *pErrorCode)
1153 {
1154     DP_ASSERT(compoundQueryActive);
1155     if (pErrorCode)
1156         *pErrorCode = DP_IMP_ERROR_NONE;
1157 
1158     compoundQueryCount++;
1159 
1160     if (!modesetParams.modesetInfo.depth || !modesetParams.modesetInfo.pixelClockHz)
1161     {
1162         DP_ASSERT(!"DP-CONN> Params with zero value passed to query!");
1163         compoundQueryResult = false;
1164         SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_ZERO_VALUE_PARAMS)
1165         return false;
1166     }
1167 
1168     //
1169     // Bug 925211: In some case we need to clamp the supporting frequencies to <= 48KHz.
1170     // Check if audio frequency is greater than 48Khz & is not overridden by regkey
1171     // "ENABLE_AUDIO_BEYOND48K" simply return false.
1172     //
1173     if (((modesetParams.modesetInfo.twoChannelAudioHz > WAR_AUDIOCLAMPING_FREQ)
1174         || (modesetParams.modesetInfo.eightChannelAudioHz > WAR_AUDIOCLAMPING_FREQ))
1175         && !(bEnableAudioBeyond48K))
1176     {
1177         compoundQueryResult = false;
1178         SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_AUDIO_BEYOND_48K)
1179         return false;
1180     }
1181 
1182     if (linkUseMultistream())
1183     {
1184         compoundQueryResult = compoundQueryAttachMST(target, modesetParams,
1185                                                      pDscParams, pErrorCode);
1186     }
1187     else    // SingleStream case
1188     {
1189         compoundQueryResult = compoundQueryAttachSST(target, modesetParams,
1190                                                      pDscParams, pErrorCode);
1191     }
1192 
1193     return compoundQueryResult;
1194 }
1195 
1196 bool ConnectorImpl::dpLinkIsModePossible(const DpLinkIsModePossibleParams &params)
1197 {
1198     bool bResult;
1199     NvU32 numNonDscStreams;
1200     bool bEnableFEC = false;
1201 
1202 reRunCompoundQuery:
1203     bResult = true;
1204     numNonDscStreams = 0;
1205 
1206     for (NvU32 i = 0; i < NV_MAX_HEADS; i++)
1207     {
1208         if (params.head[i].pDscParams != NULL)
1209             params.head[i].pDscParams->bEnableDsc = false;
1210 
1211         if (params.head[i].pErrorStatus != NULL)
1212             *params.head[i].pErrorStatus = DP_IMP_ERROR_NONE;
1213     }
1214 
1215     this->beginCompoundQuery(bEnableFEC /* bForceEnableFEC */);
1216 
1217     for (NvU32 i = 0; i < NV_MAX_HEADS; i++)
1218     {
1219         if (params.head[i].pTarget == NULL)
1220             continue;
1221 
1222         DP_ASSERT(params.head[i].pModesetParams->headIndex == i);
1223 
1224         bResult = this->compoundQueryAttach(params.head[i].pTarget,
1225                                             *params.head[i].pModesetParams,
1226                                             params.head[i].pDscParams,
1227                                             params.head[i].pErrorStatus);
1228         if (!bResult)
1229             break;
1230 
1231         if ((params.head[i].pDscParams == NULL) ||
1232             !params.head[i].pDscParams->bEnableDsc)
1233         {
1234             numNonDscStreams++;
1235             continue;
1236         }
1237 
1238         //
1239         // When DSC is enabled, FEC also need to be enabled. The previously
1240         // attached non-dsc streams needs to consider 3% FEC overhead,
1241         // therefore terminate existing compound query, force enable FEC and
1242         // re-run the compound query.
1243         //
1244         if ((numNonDscStreams > 0) && !bEnableFEC)
1245         {
1246             this->endCompoundQuery();
1247             bEnableFEC = true;
1248             goto reRunCompoundQuery;
1249         }
1250 
1251         bEnableFEC = true;
1252     }
1253 
1254     if (!this->endCompoundQuery())
1255         bResult = false;
1256 
1257     return bResult;
1258 }
1259 
1260 bool ConnectorImpl::compoundQueryAttachMST(Group * target,
1261                                            const DpModesetParams &modesetParams,         // Modeset info
1262                                            DscParams *pDscParams,                        // DSC parameters
1263                                            DP_IMP_ERROR *pErrorCode)
1264 {
1265     CompoundQueryAttachMSTInfo localInfo;
1266     NvBool result = true;
1267 
1268     localInfo.localModesetInfo = modesetParams.modesetInfo;
1269     if (this->preferredLinkConfig.isValid())
1270         localInfo.lc = preferredLinkConfig;
1271     else
1272         localInfo.lc = highestAssessedLC;
1273 
1274     if (compoundQueryForceEnableFEC) {
1275         localInfo.lc.enableFEC(isFECCapable());
1276     }
1277 
1278     if (compoundQueryAttachMSTIsDscPossible(target, modesetParams, pDscParams))
1279     {
1280         result = compoundQueryAttachMSTDsc(target, modesetParams, &localInfo,
1281                                            pDscParams, pErrorCode);
1282         if (!result)
1283         {
1284             return false;
1285         }
1286 
1287         if (!pDscParams->bEnableDsc)
1288         {
1289             DP_LOG(("CompoundQueryAttach failed with DSC, will try non-DSC path"));
1290         }
1291     }
1292 
1293     return compoundQueryAttachMSTGeneric(target, modesetParams, &localInfo,
1294                                          pDscParams, pErrorCode);
1295 }
1296 
1297 bool ConnectorImpl::compoundQueryAttachMSTIsDscPossible
1298 (
1299     Group * target,
1300     const DpModesetParams &modesetParams,       // Modeset info
1301     DscParams *pDscParams                       // DSC parameters
1302 )
1303 {
1304     Device     * newDev = target->enumDevices(0);
1305     DeviceImpl * dev    = (DeviceImpl *)newDev;
1306     bool bFecCapable = false;
1307     bool bGpuDscSupported;
1308     main->getDscCaps(&bGpuDscSupported);
1309 
1310     if (pDscParams && (pDscParams->forceDsc != DSC_FORCE_DISABLE))
1311     {
1312         if (dev && dev->isDSCPossible())
1313         {
1314             if (dev->devDoingDscDecompression != dev)
1315             {
1316                 //
1317                 // If DSC decoding is going to happen at sink's parent then
1318                 // we have to make sure the path from source to sink's parent
1319                 // is fec is capable.
1320                 // Refer DP 1.4 Spec 5.4.5
1321                 //
1322                 if(dev->address.size() == 2)
1323                 {
1324                     //
1325                     // if there is only one branch between source and sink then branch
1326                     // should be directly connected to source (sst-case) and dpcd cap
1327                     // should already be available.
1328                     //
1329                     bFecCapable = dev->parent->isFECSupported();
1330                 }
1331                 else
1332                 {
1333                     //
1334                     // If there are multiple branches in the path, we have to check
1335                     // fecCapability field in epr reply to sink's parent's parent.
1336                     // Epr reply for each branch should already be updated with inferLeafLink.
1337                     // fecCapability field being true here means up to sink's parent,
1338                     // which is "downstream end of path" for sink's parent's parent,
1339                     // is fec capable.
1340                     // Refer DP 1.4 Spec 2.11.9.4.1
1341                     //
1342                     bFecCapable = dev->parent->parent->isFECSupported();
1343                 }
1344             }
1345             else
1346             {
1347                 bFecCapable = dev->isFECSupported();
1348             }
1349         }
1350     }
1351     else
1352     {
1353         return false;
1354     }
1355     // Make sure panel/it's parent & GPU supports DSC and the whole path supports FEC
1356     if (bGpuDscSupported &&                                 // If GPU supports DSC
1357         this->isFECSupported() &&                           // If GPU supports FEC
1358         pDscParams &&                                       // If client sent DSC info
1359         pDscParams->bCheckWithDsc &&                        // If client wants to check with DSC
1360         (dev && dev->devDoingDscDecompression) &&           // Either device or it's parent supports DSC
1361         bFecCapable &&                                      // If path up to dsc decoding device supports FEC
1362         (modesetParams.modesetInfo.bitsPerComponent != 6))  // DSC doesn't support bpc = 6
1363     {
1364         return true;
1365     }
1366     else
1367     {
1368         return false;
1369     }
1370 }
1371 
1372 bool ConnectorImpl::compoundQueryAttachMSTDsc(Group * target,
1373                                               const DpModesetParams &modesetParams,         // Modeset info
1374                                               CompoundQueryAttachMSTInfo * localInfo,
1375                                               DscParams *pDscParams,                        // DSC parameters
1376                                               DP_IMP_ERROR *pErrorCode)
1377 {
1378     NVT_STATUS result;
1379 
1380     Device     * newDev = target->enumDevices(0);
1381     DeviceImpl * dev    = (DeviceImpl *)newDev;
1382 
1383     bool bGpuDscSupported;
1384     main->getDscCaps(&bGpuDscSupported);
1385 
1386     DSC_INFO dscInfo;
1387     MODESET_INFO modesetInfoDSC;
1388     WAR_DATA warData;
1389     NvU64 availableBandwidthBitsPerSecond = 0;
1390     unsigned PPS[DSC_MAX_PPS_SIZE_DWORD];
1391     unsigned bitsPerPixelX16 = 0;
1392     bool bDscBppForced = false;
1393 
1394     if (!pDscParams->bitsPerPixelX16)
1395     {
1396         //
1397         // For now, we will keep a pre defined value for bitsPerPixel for MST = 10
1398         // bitsPerPixelX16 = 160
1399         //
1400         pDscParams->bitsPerPixelX16 = PREDEFINED_DSC_MST_BPPX16;
1401     }
1402     else
1403     {
1404         bDscBppForced = true;
1405     }
1406 
1407     bitsPerPixelX16 = pDscParams->bitsPerPixelX16;
1408 
1409     if (!this->preferredLinkConfig.isValid())
1410     {
1411         localInfo->lc.enableFEC(true);
1412     }
1413 
1414     dpMemZero(PPS, sizeof(unsigned) * DSC_MAX_PPS_SIZE_DWORD);
1415     dpMemZero(&dscInfo, sizeof(DSC_INFO));
1416 
1417     // Populate DSC related info for PPS calculations
1418     populateDscCaps(&dscInfo, dev->devDoingDscDecompression, pDscParams->forcedParams);
1419 
1420     // populate modeset related info for PPS calculations
1421     populateDscModesetInfo(&modesetInfoDSC, &modesetParams);
1422 
1423     // checking for DSC v1.1 and YUV combination
1424     if ((dscInfo.sinkCaps.algorithmRevision.versionMajor == 1) &&
1425         (dscInfo.sinkCaps.algorithmRevision.versionMinor == 1) &&
1426         (modesetParams.colorFormat == dpColorFormat_YCbCr444 ))
1427     {
1428         DP_LOG(("WARNING: DSC v1.2 or higher is recommended for using YUV444"));
1429         DP_LOG(("Current version is 1.1"));
1430     }
1431 
1432     if ((dev->devDoingDscDecompression == dev) && dev->parent)
1433     {
1434         if (dev->parent->bDscPassThroughColorFormatWar)
1435         {
1436             //
1437             // Bug 3692417
1438             // Color format should only depend on device doing DSC decompression when DSC is enabled according to DP Spec.
1439             // But when Synaptics VMM5320 is the parent of the device doing DSC decompression, if a certain color
1440             // format is not supported by Synaptics Virtual Peer Device decoder(parent), even though it is pass through mode
1441             // and panel supports the color format, panel cannot light up. Once Synaptics fixes this issue, we will modify
1442             // the WAR to be applied only before the firmware version that fixes it.
1443             //
1444             if ((modesetParams.colorFormat == dpColorFormat_RGB      && !dev->parent->dscCaps.dscDecoderColorFormatCaps.bRgb)      ||
1445                 (modesetParams.colorFormat == dpColorFormat_YCbCr444 && !dev->parent->dscCaps.dscDecoderColorFormatCaps.bYCbCr444) ||
1446                 (modesetParams.colorFormat == dpColorFormat_YCbCr422 && !dev->parent->dscCaps.dscDecoderColorFormatCaps.bYCbCrSimple422))
1447             {
1448                 if ((pDscParams->forceDsc == DSC_FORCE_ENABLE) ||
1449                     (modesetParams.modesetInfo.mode == DSC_DUAL))
1450                 {
1451                     //
1452                     // If DSC is force enabled or DSC_DUAL mode is requested,
1453                     // then return failure here
1454                     //
1455                     compoundQueryResult = false;
1456                     SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_DSC_SYNAPTICS_COLOR_FORMAT)
1457                     pDscParams->bEnableDsc = false;
1458                     return false;
1459                 }
1460                 else
1461                 {
1462                     // We should check if mode is possible without DSC.
1463                     pDscParams->bEnableDsc = false;
1464                     if (!compoundQueryForceEnableFEC)
1465                     {
1466                         localInfo->lc.enableFEC(false);
1467                     }
1468                     return true;
1469                 }
1470             }
1471         }
1472     }
1473 
1474     availableBandwidthBitsPerSecond = localInfo->lc.minRate * 8 * localInfo->lc.lanes;
1475 
1476     warData.dpData.linkRateHz = localInfo->lc.peakRate;
1477     warData.dpData.laneCount = localInfo->lc.lanes;
1478     warData.dpData.dpMode = DSC_DP_MST;
1479     warData.dpData.hBlank = modesetParams.modesetInfo.rasterWidth - modesetParams.modesetInfo.surfaceWidth;
1480     warData.connectorType = DSC_DP;
1481 
1482     DSC_GENERATE_PPS_OPAQUE_WORKAREA *pScratchBuffer = nullptr;
1483     pScratchBuffer = (DSC_GENERATE_PPS_OPAQUE_WORKAREA*) dpMalloc(sizeof(DSC_GENERATE_PPS_OPAQUE_WORKAREA));
1484 
1485     result = DSC_GeneratePPS(&dscInfo, &modesetInfoDSC,
1486                              &warData, availableBandwidthBitsPerSecond,
1487                              (NvU32*)(PPS), (NvU32*)(&bitsPerPixelX16),
1488                              pScratchBuffer);
1489 
1490     // Try max dsc compression bpp = 8 once to check if that can support that mode.
1491     if (result != NVT_STATUS_SUCCESS && !bDscBppForced)
1492     {
1493         pDscParams->bitsPerPixelX16 = MAX_DSC_COMPRESSION_BPPX16;
1494 
1495         bitsPerPixelX16 = pDscParams->bitsPerPixelX16;
1496 
1497         result = DSC_GeneratePPS(&dscInfo, &modesetInfoDSC,
1498                                  &warData, availableBandwidthBitsPerSecond,
1499                                  (NvU32*)(PPS), (NvU32*)(&bitsPerPixelX16),
1500                                  pScratchBuffer);
1501     }
1502 
1503     if (pScratchBuffer)
1504     {
1505         dpFree(pScratchBuffer);
1506         pScratchBuffer = nullptr;
1507     }
1508 
1509     if (result != NVT_STATUS_SUCCESS)
1510     {
1511         //
1512         // If generating PPS failed
1513         //          AND
1514         //    (DSC is force enabled
1515         //          OR
1516         //    the requested DSC mode = DUAL)
1517         //then
1518         //    return failure here
1519         // Else
1520         //    we will check if non DSC path is possible.
1521         //
1522         // If dsc mode = DUAL failed to generate PPS and if we pursue
1523         // non DSC path, DD will still follow 2Head1OR modeset path with
1524         // DSC disabled, eventually leading to HW hang. Bug 3632901
1525         //
1526         if ((pDscParams->forceDsc == DSC_FORCE_ENABLE) ||
1527             (modesetParams.modesetInfo.mode == DSC_DUAL))
1528         {
1529             compoundQueryResult = false;
1530             SET_DP_IMP_ERROR(pErrorCode, translatePpsErrorToDpImpError(result))
1531             pDscParams->bEnableDsc = false;
1532             return false;
1533         }
1534         else
1535         {
1536             // If PPS calculation failed then try without DSC
1537             pDscParams->bEnableDsc = false;
1538             if (!compoundQueryForceEnableFEC)
1539             {
1540                 localInfo->lc.enableFEC(false);
1541             }
1542             return true;
1543         }
1544     }
1545     else
1546     {
1547         pDscParams->bEnableDsc = true;
1548         compoundQueryResult = true;
1549         localInfo->localModesetInfo.bEnableDsc = true;
1550         localInfo->localModesetInfo.depth = bitsPerPixelX16;
1551 
1552         if (dev->peerDevice == Dongle && dev->connectorType == connectorHDMI)
1553         {
1554             //
1555             // For DP2HDMI PCON, if FRL BW is available in detailed caps,
1556             // we need to check if we have enough BW for the stream on FRL link.
1557             //
1558             if (dev->pconCaps.maxHdmiLinkBandwidthGbps != 0)
1559             {
1560                 NvU64 requiredBW = (NvU64)(modesetParams.modesetInfo.pixelClockHz * modesetParams.modesetInfo.depth);
1561                 NvU64 availableBw = (NvU64)(dev->pconCaps.maxHdmiLinkBandwidthGbps * 1000000000);
1562                 if (requiredBW > availableBw)
1563                 {
1564                     compoundQueryResult = false;
1565                     SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_DSC_PCON_FRL_BANDWIDTH)
1566                     pDscParams->bEnableDsc = false;
1567                     return false;
1568                 }
1569             }
1570             //
1571             // If DP2HDMI PCON does not support FRL, but advertises TMDS
1572             // Character clock rate on detailed caps, we need to honor that.
1573             //
1574             else if (dev->pconCaps.maxTmdsClkRate != 0)
1575             {
1576                 NvU64 maxTmdsClkRateU64 = (NvU64)(dev->pconCaps.maxTmdsClkRate);
1577                 NvU64 requireBw         = (NvU64)(modesetParams.modesetInfo.pixelClockHz * modesetParams.modesetInfo.depth);
1578                 if (modesetParams.colorFormat == dpColorFormat_YCbCr420)
1579                 {
1580                     if (maxTmdsClkRateU64 < ((requireBw/24)/2))
1581                     {
1582                         compoundQueryResult = false;
1583                         SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_DSC_PCON_HDMI2_BANDWIDTH)
1584                         return false;
1585                     }
1586                 }
1587                 else
1588                 {
1589                     if (maxTmdsClkRateU64 < (requireBw/24))
1590                     {
1591                         compoundQueryResult = false;
1592                         SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_DSC_PCON_HDMI2_BANDWIDTH)
1593                         return false;
1594                     }
1595                 }
1596             }
1597         }
1598         else if (dev->devDoingDscDecompression != dev)
1599         {
1600             //
1601             // Device's parent is doing DSC decompression so we need to check
1602             // if device's parent can send uncompressed stream to Sink.
1603             //
1604             unsigned mode_pbn;
1605 
1606             mode_pbn = pbnForMode(modesetParams.modesetInfo);
1607 
1608             //
1609             // As Device's Parent is doing DSC decompression, this is leaf device and
1610             // complete available bandwidth at this node is available for requested mode.
1611             //
1612             if (mode_pbn > dev->bandwidth.enum_path.total)
1613             {
1614                 compoundQueryResult = false;
1615                 SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_DSC_LAST_HOP_BANDWIDTH)
1616                 pDscParams->bEnableDsc = false;
1617                 return false;
1618             }
1619         }
1620 
1621         if (pDscParams->pDscOutParams != NULL)
1622         {
1623             //
1624             // If requested then DP Library is supposed to return if mode is
1625             // possible with DSC and calculated PPS and bits per pixel.
1626             //
1627             dpMemCopy(pDscParams->pDscOutParams->PPS, PPS, sizeof(unsigned) * DSC_MAX_PPS_SIZE_DWORD);
1628             pDscParams->bitsPerPixelX16 = bitsPerPixelX16;
1629         }
1630         else
1631         {
1632             //
1633             // Client only wants to know if mode is possible or not but doesn't
1634             // need all calculated PPS parameters in case DSC is required. Do nothing.
1635             //
1636         }
1637     }
1638     return true;
1639 }
1640 
1641 bool ConnectorImpl::compoundQueryAttachMSTGeneric(Group * target,
1642                                                   const DpModesetParams &modesetParams,         // Modeset info
1643                                                   CompoundQueryAttachMSTInfo * localInfo,
1644                                                   DscParams *pDscParams,                        // DSC parameters
1645                                                   DP_IMP_ERROR *pErrorCode)
1646 {
1647     // I. Evaluate use of local link bandwidth
1648 
1649     //      Calculate the PBN required
1650     unsigned base_pbn, slots, slots_pbn;
1651     localInfo->lc.pbnRequired(localInfo->localModesetInfo, base_pbn, slots, slots_pbn);
1652 
1653     //      Accumulate the amount of PBN rounded up to nearest timeslot
1654     compoundQueryLocalLinkPBN += slots_pbn;
1655     if (compoundQueryLocalLinkPBN > localInfo->lc.pbnTotal())
1656     {
1657         compoundQueryResult = false;
1658         SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_INSUFFICIENT_BANDWIDTH)
1659     }
1660 
1661     //      Verify the min blanking, etc
1662     Watermark dpinfo;
1663 
1664     if (this->isFECSupported())
1665     {
1666         if (!isModePossibleMSTWithFEC(localInfo->lc, localInfo->localModesetInfo, &dpinfo))
1667         {
1668             compoundQueryResult = false;
1669             SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_WATERMARK_BLANKING)
1670         }
1671     }
1672     else
1673     {
1674         if (!isModePossibleMST(localInfo->lc, localInfo->localModesetInfo, &dpinfo))
1675         {
1676             compoundQueryResult = false;
1677             SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_WATERMARK_BLANKING)
1678         }
1679     }
1680 
1681     for(Device * d = target->enumDevices(0); d; d = target->enumDevices(d))
1682     {
1683         DeviceImpl * i = (DeviceImpl *)d;
1684 
1685         // Allocate bandwidth for the entire path to the root
1686         //   NOTE: Above we're already handle the local link
1687         DeviceImpl * tail = i;
1688         while (tail && tail->getParent())
1689         {
1690             // Have we already accounted for this stream?
1691             if (!(tail->bandwidth.compound_query_state.bandwidthAllocatedForIndex & (1 << compoundQueryCount)))
1692             {
1693                 tail->bandwidth.compound_query_state.bandwidthAllocatedForIndex |= (1 << compoundQueryCount);
1694 
1695                 LinkConfiguration * linkConfig = tail->inferLeafLink(NULL);
1696                 tail->bandwidth.compound_query_state.timeslots_used_by_query += linkConfig->slotsForPBN(base_pbn);
1697 
1698                 if ( tail->bandwidth.compound_query_state.timeslots_used_by_query > tail->bandwidth.compound_query_state.totalTimeSlots)
1699                 {
1700                     compoundQueryResult = false;
1701                     SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_INSUFFICIENT_BANDWIDTH)
1702                 }
1703             }
1704             tail = (DeviceImpl*)tail->getParent();
1705         }
1706     }
1707     return compoundQueryResult;
1708 }
1709 bool ConnectorImpl::compoundQueryAttachSST(Group * target,
1710                                            const DpModesetParams &modesetParams,         // Modeset info
1711                                            DscParams *pDscParams,                        // DSC parameters
1712                                            DP_IMP_ERROR *pErrorCode)
1713 {
1714     ModesetInfo localModesetInfo = modesetParams.modesetInfo;
1715     bool bGpuDscSupported;
1716     main->getDscCaps(&bGpuDscSupported);
1717 
1718     DeviceImpl * nativeDev = findDeviceInList(Address());
1719 
1720     if (compoundQueryCount != 1)
1721     {
1722         compoundQueryResult = false;
1723         return false;
1724     }
1725 
1726     if (nativeDev && (nativeDev->connectorType == connectorHDMI))
1727     {
1728         if (modesetParams.colorFormat == dpColorFormat_YCbCr420)
1729         {
1730             if ((nativeDev->maxTmdsClkRate) &&
1731                 (nativeDev->maxTmdsClkRate <
1732                 ((modesetParams.modesetInfo.pixelClockHz * modesetParams.modesetInfo.depth /24)/2)))
1733             {
1734                 compoundQueryResult = false;
1735                 SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_DSC_PCON_HDMI2_BANDWIDTH)
1736                 return false;
1737             }
1738         }
1739         else
1740         {
1741             if ((nativeDev->maxTmdsClkRate) &&
1742                 (nativeDev->maxTmdsClkRate <
1743                 (modesetParams.modesetInfo.pixelClockHz * modesetParams.modesetInfo.depth /24)))
1744             {
1745                 compoundQueryResult = false;
1746                 SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_DSC_PCON_HDMI2_BANDWIDTH)
1747                 return false;
1748             }
1749         }
1750     }
1751 
1752     LinkConfiguration lc = highestAssessedLC;
1753 
1754     // check if there is a special request from the client
1755     if (this->preferredLinkConfig.isValid())
1756     {
1757         lc = preferredLinkConfig;
1758     }
1759     else
1760     {
1761         //
1762         // Always check for DP IMP without FEC overhead first before
1763         // trying with DSC/FEC
1764         //
1765         lc.enableFEC(false);
1766     }
1767 
1768     // If do not found valid native device the force lagacy DP IMP
1769     if (!nativeDev)
1770     {
1771         compoundQueryResult = this->willLinkSupportModeSST(lc, modesetParams.modesetInfo);
1772         if (!compoundQueryResult)
1773         {
1774             SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_WATERMARK_BLANKING)
1775         }
1776     }
1777     else if ((pDscParams && (pDscParams->forceDsc == DSC_FORCE_ENABLE)) ||      // DD has forced DSC Enable
1778                 (modesetParams.modesetInfo.mode == DSC_DUAL) ||                    // DD decided to use 2 Head 1 OR mode
1779                 (!this->willLinkSupportModeSST(lc, modesetParams.modesetInfo)))    // Mode is not possible without DSC
1780     {
1781         // If DP IMP fails without DSC or client requested to force DSC
1782         if (pDscParams && pDscParams->forceDsc != DSC_FORCE_DISABLE)
1783         {
1784             // Check if panel and GPU both supports DSC or not. Also check if panel supports FEC
1785             if (bGpuDscSupported &&                                 // if GPU supports DSC
1786                 this->isFECSupported() &&                           // If GPU supports FEC
1787                 pDscParams &&                                       // if client sent DSC info
1788                 pDscParams->bCheckWithDsc &&                        // if client wants to check with DSC
1789                 nativeDev->isDSCPossible() &&                       // if device supports DSC decompression
1790                 (nativeDev->isFECSupported() || main->isEDP()) &&   // if device supports FEC decoding or is an DSC capable eDP panel which doesn't support FEC
1791                 (modesetParams.modesetInfo.bitsPerComponent != 6))  // DSC doesn't support bpc = 6
1792             {
1793                 DSC_INFO dscInfo;
1794                 MODESET_INFO modesetInfoDSC;
1795                 WAR_DATA warData;
1796                 NvU64 availableBandwidthBitsPerSecond = 0;
1797                 unsigned PPS[DSC_MAX_PPS_SIZE_DWORD];
1798                 unsigned bitsPerPixelX16 = pDscParams->bitsPerPixelX16;
1799 
1800                 if (!this->preferredLinkConfig.isValid() && nativeDev->isFECSupported())
1801                 {
1802                     lc.enableFEC(true);
1803                 }
1804 
1805                 dpMemZero(PPS, sizeof(unsigned) * DSC_MAX_PPS_SIZE_DWORD);
1806                 dpMemZero(&dscInfo, sizeof(DSC_INFO));
1807 
1808                 // Populate DSC related info for PPS calculations
1809                 populateDscCaps(&dscInfo, nativeDev->devDoingDscDecompression, pDscParams->forcedParams);
1810 
1811                 // Populate modeset related info for PPS calculations
1812                 populateDscModesetInfo(&modesetInfoDSC, &modesetParams);
1813 
1814                 // checking for DSC v1.1 and YUV combination
1815                 if ( (dscInfo.sinkCaps.algorithmRevision.versionMajor == 1) &&
1816                         (dscInfo.sinkCaps.algorithmRevision.versionMinor == 1) &&
1817                         (modesetParams.colorFormat == dpColorFormat_YCbCr444 ))
1818                 {
1819                     DP_LOG(("WARNING: DSC v1.2 or higher is recommended for using YUV444"));
1820                     DP_LOG(("Current version is 1.1"));
1821                 }
1822 
1823                 availableBandwidthBitsPerSecond = lc.minRate * 8 * lc.lanes;
1824 
1825                 warData.dpData.linkRateHz = lc.peakRate;
1826                 warData.dpData.laneCount = lc.lanes;
1827                 warData.dpData.hBlank = modesetParams.modesetInfo.rasterWidth - modesetParams.modesetInfo.surfaceWidth;
1828                 warData.dpData.dpMode = DSC_DP_SST;
1829                 warData.connectorType = DSC_DP;
1830 
1831                 DSC_GENERATE_PPS_OPAQUE_WORKAREA *pScratchBuffer = nullptr;
1832                 pScratchBuffer = (DSC_GENERATE_PPS_OPAQUE_WORKAREA*) dpMalloc(sizeof(DSC_GENERATE_PPS_OPAQUE_WORKAREA));
1833 
1834                 NVT_STATUS ppsStatus = DSC_GeneratePPS(&dscInfo, &modesetInfoDSC,
1835                                         &warData, availableBandwidthBitsPerSecond,
1836                                         (NvU32*)(PPS),
1837                                         (NvU32*)(&bitsPerPixelX16),
1838                                         pScratchBuffer);
1839                 if (pScratchBuffer)
1840                 {
1841                     dpFree(pScratchBuffer);
1842                     pScratchBuffer = nullptr;
1843                 }
1844 
1845                 if (ppsStatus != NVT_STATUS_SUCCESS)
1846                 {
1847                     compoundQueryResult = false;
1848                     SET_DP_IMP_ERROR(pErrorCode, translatePpsErrorToDpImpError(ppsStatus))
1849                     pDscParams->bEnableDsc = false;
1850                 }
1851                 else
1852                 {
1853                     localModesetInfo.bEnableDsc = true;
1854                     localModesetInfo.depth = bitsPerPixelX16;
1855                     LinkConfiguration lowestSelected;
1856                     bool bIsModeSupported = false;
1857 
1858 
1859                     if (this->preferredLinkConfig.isValid())
1860                     {
1861                         // Check if mode is possible with preferred link config
1862                         bIsModeSupported = willLinkSupportModeSST(lc, localModesetInfo);
1863                     }
1864                     else
1865                     {
1866                         //
1867                         // Check if mode is possible with calculated bits_per_pixel.
1868                         // Check with all possible link configs and not just highest
1869                         // assessed because with DSC, mode can fail with higher
1870                         // link config and pass for lower one. This is because
1871                         // if raster parameters are really small and DP bandwidth is
1872                         // very high then we may end up with some TU with 0 active
1873                         // symbols in SST. This may cause HW hang and so DP IMP rejects
1874                         // this mode. Refer Bug 200379426.
1875                         //
1876                         bIsModeSupported = getValidLowestLinkConfig(lc, lowestSelected, localModesetInfo);
1877                     }
1878 
1879                     if (!bIsModeSupported)
1880                     {
1881                         pDscParams->bEnableDsc = false;
1882                         SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_INSUFFICIENT_BANDWIDTH_DSC)
1883                         compoundQueryResult = false;
1884                     }
1885                     else
1886                     {
1887                         pDscParams->bEnableDsc = true;
1888                         compoundQueryResult = true;
1889 
1890                         if (pDscParams->pDscOutParams != NULL)
1891                         {
1892                             //
1893                             // If requested then DP Library is supposed to return if mode is
1894                             // possible with DSC and calculated PPS and bits per pixel.
1895                             //
1896                             dpMemCopy(pDscParams->pDscOutParams->PPS, PPS, sizeof(unsigned) * DSC_MAX_PPS_SIZE_DWORD);
1897                             pDscParams->bitsPerPixelX16 = bitsPerPixelX16;
1898                         }
1899                         else
1900                         {
1901                             //
1902                             // Client only wants to know if mode is possible or not but doesn't
1903                             // need all calculated PPS parameters in case DSC is required. Do nothing.
1904                             //
1905                         }
1906                     }
1907                 }
1908             }
1909             else
1910             {
1911                 // Either GPU or Sink doesn't support DSC
1912                 compoundQueryResult = false;
1913                 SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_INSUFFICIENT_BANDWIDTH_NO_DSC)
1914             }
1915         }
1916         else
1917         {
1918             // Client hasn't sent DSC params info or has asked to force disable DSC.
1919             compoundQueryResult = false;
1920             SET_DP_IMP_ERROR(pErrorCode, DP_IMP_ERROR_INSUFFICIENT_BANDWIDTH_NO_DSC)
1921         }
1922     }
1923     else
1924     {
1925         // Mode was successful
1926         compoundQueryResult = true;
1927     }
1928     return compoundQueryResult;
1929 }
1930 
1931 void ConnectorImpl::populateDscModesetInfo(MODESET_INFO* pModesetInfo, const DpModesetParams* pModesetParams)
1932 {
1933     pModesetInfo->pixelClockHz = pModesetParams->modesetInfo.pixelClockHz;
1934     pModesetInfo->activeWidth = pModesetParams->modesetInfo.surfaceWidth;
1935     pModesetInfo->activeHeight = pModesetParams->modesetInfo.surfaceHeight;
1936     pModesetInfo->bitsPerComponent = pModesetParams->modesetInfo.bitsPerComponent;
1937 
1938     if (pModesetParams->colorFormat == dpColorFormat_RGB)
1939     {
1940         pModesetInfo->colorFormat = NVT_COLOR_FORMAT_RGB;
1941     }
1942     else if (pModesetParams->colorFormat == dpColorFormat_YCbCr444)
1943     {
1944         pModesetInfo->colorFormat = NVT_COLOR_FORMAT_YCbCr444;
1945     }
1946     else if (pModesetParams->colorFormat == dpColorFormat_YCbCr422)
1947     {
1948         pModesetInfo->colorFormat = NVT_COLOR_FORMAT_YCbCr422;
1949     }
1950     else if (pModesetParams->colorFormat == dpColorFormat_YCbCr420)
1951     {
1952         pModesetInfo->colorFormat = NVT_COLOR_FORMAT_YCbCr420;
1953     }
1954     else
1955     {
1956         pModesetInfo->colorFormat = NVT_COLOR_FORMAT_RGB;
1957     }
1958 
1959     if (pModesetParams->modesetInfo.mode == DSC_DUAL)
1960     {
1961         pModesetInfo->bDualMode = true;
1962     }
1963     else
1964     {
1965         pModesetInfo->bDualMode = false;
1966     }
1967 
1968     if (pModesetParams->modesetInfo.mode == DSC_DROP)
1969     {
1970         pModesetInfo->bDropMode = true;
1971     }
1972     else
1973     {
1974         pModesetInfo->bDropMode = false;
1975     }
1976 }
1977 
1978 void ConnectorImpl::populateDscGpuCaps(DSC_INFO* dscInfo)
1979 {
1980     unsigned encoderColorFormatMask;
1981     unsigned lineBufferSizeKB;
1982     unsigned rateBufferSizeKB;
1983     unsigned bitsPerPixelPrecision;
1984     unsigned maxNumHztSlices;
1985     unsigned lineBufferBitDepth;
1986 
1987     // Get GPU DSC capabilities
1988     main->getDscCaps(NULL,
1989         &encoderColorFormatMask,
1990         &lineBufferSizeKB,
1991         &rateBufferSizeKB,
1992         &bitsPerPixelPrecision,
1993         &maxNumHztSlices,
1994         &lineBufferBitDepth);
1995 
1996     if (encoderColorFormatMask & NV0073_CTRL_CMD_DP_GET_CAPS_DSC_ENCODER_COLOR_FORMAT_RGB)
1997     {
1998         dscInfo->gpuCaps.encoderColorFormatMask |= DSC_ENCODER_COLOR_FORMAT_RGB;
1999     }
2000 
2001     if (encoderColorFormatMask & NV0073_CTRL_CMD_DP_GET_CAPS_DSC_ENCODER_COLOR_FORMAT_Y_CB_CR_444)
2002     {
2003         dscInfo->gpuCaps.encoderColorFormatMask |= DSC_ENCODER_COLOR_FORMAT_Y_CB_CR_444;
2004     }
2005 
2006     if (encoderColorFormatMask & NV0073_CTRL_CMD_DP_GET_CAPS_DSC_ENCODER_COLOR_FORMAT_Y_CB_CR_NATIVE_422)
2007     {
2008         dscInfo->gpuCaps.encoderColorFormatMask |= DSC_ENCODER_COLOR_FORMAT_Y_CB_CR_NATIVE_422;
2009     }
2010 
2011     if (encoderColorFormatMask & NV0073_CTRL_CMD_DP_GET_CAPS_DSC_ENCODER_COLOR_FORMAT_Y_CB_CR_NATIVE_420)
2012     {
2013         dscInfo->gpuCaps.encoderColorFormatMask |= DSC_ENCODER_COLOR_FORMAT_Y_CB_CR_NATIVE_420;
2014     }
2015 
2016     dscInfo->gpuCaps.lineBufferSize = lineBufferSizeKB;
2017 
2018     if (bitsPerPixelPrecision == NV0073_CTRL_CMD_DP_GET_CAPS_DSC_BITS_PER_PIXEL_PRECISION_1_16)
2019     {
2020         dscInfo->gpuCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1_16;
2021     }
2022 
2023     if (bitsPerPixelPrecision == NV0073_CTRL_CMD_DP_GET_CAPS_DSC_BITS_PER_PIXEL_PRECISION_1_8)
2024     {
2025         dscInfo->gpuCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1_8;
2026     }
2027 
2028     if (bitsPerPixelPrecision == NV0073_CTRL_CMD_DP_GET_CAPS_DSC_BITS_PER_PIXEL_PRECISION_1_4)
2029     {
2030         dscInfo->gpuCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1_4;
2031     }
2032 
2033     if (bitsPerPixelPrecision == NV0073_CTRL_CMD_DP_GET_CAPS_DSC_BITS_PER_PIXEL_PRECISION_1_2)
2034     {
2035         dscInfo->gpuCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1_2;
2036     }
2037 
2038     if (bitsPerPixelPrecision == NV0073_CTRL_CMD_DP_GET_CAPS_DSC_BITS_PER_PIXEL_PRECISION_1)
2039     {
2040         dscInfo->gpuCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1;
2041     }
2042 
2043     dscInfo->gpuCaps.maxNumHztSlices = maxNumHztSlices;
2044 
2045     dscInfo->gpuCaps.lineBufferBitDepth = lineBufferBitDepth;
2046 }
2047 
2048 void ConnectorImpl::populateDscBranchCaps(DSC_INFO* dscInfo, DeviceImpl * dev)
2049 {
2050     dscInfo->branchCaps.overallThroughputMode0 = dev->dscCaps.branchDSCOverallThroughputMode0;
2051     dscInfo->branchCaps.overallThroughputMode1 = dev->dscCaps.branchDSCOverallThroughputMode1;
2052     dscInfo->branchCaps.maxLineBufferWidth = dev->dscCaps.branchDSCMaximumLineBufferWidth;
2053 
2054     return;
2055 }
2056 
2057 void ConnectorImpl::populateDscSinkCaps(DSC_INFO* dscInfo, DeviceImpl * dev)
2058 {
2059     // Early return if dscInfo or dev is NULL
2060     if ((dscInfo == NULL) || (dev == NULL))
2061     {
2062         return;
2063     }
2064 
2065     if (dev->dscCaps.dscDecoderColorFormatCaps.bRgb)
2066     {
2067         dscInfo->sinkCaps.decoderColorFormatMask |= DSC_DECODER_COLOR_FORMAT_RGB;
2068     }
2069 
2070     if (dev->dscCaps.dscDecoderColorFormatCaps.bYCbCr444)
2071     {
2072         dscInfo->sinkCaps.decoderColorFormatMask |= DSC_DECODER_COLOR_FORMAT_Y_CB_CR_444;
2073     }
2074     if (dev->dscCaps.dscDecoderColorFormatCaps.bYCbCrSimple422)
2075     {
2076         dscInfo->sinkCaps.decoderColorFormatMask |= DSC_DECODER_COLOR_FORMAT_Y_CB_CR_SIMPLE_422;
2077     }
2078     if (dev->dscCaps.dscDecoderColorFormatCaps.bYCbCrNative422)
2079     {
2080         dscInfo->sinkCaps.decoderColorFormatMask |= DSC_DECODER_COLOR_FORMAT_Y_CB_CR_NATIVE_422;
2081     }
2082     if (dev->dscCaps.dscDecoderColorFormatCaps.bYCbCrNative420)
2083     {
2084         dscInfo->sinkCaps.decoderColorFormatMask |= DSC_DECODER_COLOR_FORMAT_Y_CB_CR_NATIVE_420;
2085     }
2086 
2087     switch (dev->dscCaps.dscBitsPerPixelIncrement)
2088     {
2089         case BITS_PER_PIXEL_PRECISION_1_16:
2090             dscInfo->sinkCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1_16;
2091             break;
2092         case BITS_PER_PIXEL_PRECISION_1_8:
2093             dscInfo->sinkCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1_8;
2094             break;
2095         case BITS_PER_PIXEL_PRECISION_1_4:
2096             dscInfo->sinkCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1_4;
2097             break;
2098         case BITS_PER_PIXEL_PRECISION_1_2:
2099             dscInfo->sinkCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1_2;
2100             break;
2101         case BITS_PER_PIXEL_PRECISION_1:
2102             dscInfo->sinkCaps.bitsPerPixelPrecision = DSC_BITS_PER_PIXEL_PRECISION_1;
2103             break;
2104     }
2105 
2106     // Decoder color depth mask
2107     if (dev->dscCaps.dscDecoderColorDepthMask & DSC_BITS_PER_COLOR_MASK_12)
2108     {
2109         dscInfo->sinkCaps.decoderColorDepthMask |= DSC_DECODER_COLOR_DEPTH_CAPS_12_BITS;
2110     }
2111 
2112     if (dev->dscCaps.dscDecoderColorDepthMask & DSC_BITS_PER_COLOR_MASK_10)
2113     {
2114         dscInfo->sinkCaps.decoderColorDepthMask |= DSC_DECODER_COLOR_DEPTH_CAPS_10_BITS;
2115     }
2116 
2117     if (dev->dscCaps.dscDecoderColorDepthMask & DSC_BITS_PER_COLOR_MASK_8)
2118     {
2119         dscInfo->sinkCaps.decoderColorDepthMask |= DSC_DECODER_COLOR_DEPTH_CAPS_8_BITS;
2120     }
2121 
2122     dscInfo->sinkCaps.maxSliceWidth = dev->dscCaps.dscMaxSliceWidth;
2123     dscInfo->sinkCaps.sliceCountSupportedMask = dev->dscCaps.sliceCountSupportedMask;
2124     dscInfo->sinkCaps.maxNumHztSlices = dev->dscCaps.maxSlicesPerSink;
2125     dscInfo->sinkCaps.lineBufferBitDepth = dev->dscCaps.lineBufferBitDepth;
2126     dscInfo->sinkCaps.bBlockPrediction = dev->dscCaps.bDscBlockPredictionSupport;
2127     dscInfo->sinkCaps.algorithmRevision.versionMajor = dev->dscCaps.versionMajor;
2128     dscInfo->sinkCaps.algorithmRevision.versionMinor = dev->dscCaps.versionMinor;
2129     dscInfo->sinkCaps.peakThroughputMode0 = dev->dscCaps.dscPeakThroughputMode0;
2130     dscInfo->sinkCaps.peakThroughputMode1 = dev->dscCaps.dscPeakThroughputMode1;
2131     dscInfo->sinkCaps.maxBitsPerPixelX16 = dev->dscCaps.maxBitsPerPixelX16;
2132 
2133     if (main->isEDP())
2134     {
2135         // If eDP panel does not populate peak DSC throughput, use _MODE0_340.
2136         if (!dscInfo->sinkCaps.peakThroughputMode0)
2137         {
2138             dscInfo->sinkCaps.peakThroughputMode0 = NV_DPCD14_DSC_PEAK_THROUGHPUT_MODE0_340;
2139         }
2140 
2141         // If eDP panel does not populate max slice width, use 2560.
2142         if (!dscInfo->sinkCaps.maxSliceWidth)
2143         {
2144             dscInfo->sinkCaps.maxSliceWidth = 2560;
2145         }
2146     }
2147 }
2148 
2149 void ConnectorImpl::populateForcedDscParams(DSC_INFO* dscInfo, DSC_INFO::FORCED_DSC_PARAMS * forcedParams)
2150 {
2151     if(forcedParams)
2152     {
2153         dscInfo->forcedDscParams.sliceWidth = forcedParams->sliceWidth;
2154         dscInfo->forcedDscParams.sliceHeight = forcedParams->sliceHeight;
2155         dscInfo->forcedDscParams.sliceCount = forcedParams->sliceCount;
2156         dscInfo->forcedDscParams.dscRevision = forcedParams->dscRevision;
2157     }
2158 
2159 }
2160 
2161 void ConnectorImpl::populateDscCaps(DSC_INFO* dscInfo, DeviceImpl * dev, DSC_INFO::FORCED_DSC_PARAMS * forcedParams)
2162 {
2163     // Sink DSC capabilities
2164     populateDscSinkCaps(dscInfo, dev);
2165 
2166     // Branch Specific DSC Capabilities
2167     if (!dev->isVideoSink() && !dev->isAudioSink())
2168     {
2169         populateDscBranchCaps(dscInfo, dev);
2170     }
2171 
2172     // GPU DSC capabilities
2173     populateDscGpuCaps(dscInfo);
2174 
2175     // Forced DSC params
2176     populateForcedDscParams(dscInfo, forcedParams);
2177 }
2178 
2179 bool ConnectorImpl::endCompoundQuery()
2180 {
2181     DP_ASSERT(compoundQueryActive && "Spurious compoundQuery end.");
2182     compoundQueryActive = false;
2183     return compoundQueryResult;
2184 }
2185 
2186 //
2187 //     Set link to HDMI mode
2188 //
2189 void ConnectorImpl::enableLinkHandsOff()
2190 {
2191     if (isLinkQuiesced)
2192     {
2193         DP_ASSERT(0 && "Link is already quiesced.");
2194         return;
2195     }
2196 
2197     isLinkQuiesced = true;
2198 
2199     // Set the Lane Count to 0 to shut down the link.
2200     powerdownLink();
2201 }
2202 
2203 //
2204 //     Restore from HDMI mode
2205 //
2206 void ConnectorImpl::releaseLinkHandsOff()
2207 {
2208     if (!isLinkQuiesced)
2209     {
2210         DP_LOG(("DPCONN> Link is already in use."));
2211         return;
2212     }
2213 
2214     isLinkQuiesced = false;
2215     assessLink();
2216 }
2217 
2218 //
2219 //     Timer callback for event management
2220 //          Uses: fireEvents()
2221 void ConnectorImpl::expired(const void * tag)
2222 {
2223     if (tag == &tagFireEvents)
2224         fireEventsInternal();
2225     else
2226         DP_ASSERT(0);
2227 }
2228 
2229 // Generate Events.
2230 //          useTimer specifies whether we fire the events on the timer
2231 //      context, or this context.
2232 void ConnectorImpl::fireEvents()
2233 {
2234     bool eventsPending = false;
2235 
2236     // Don't fire any events if we're not done with the modeset
2237     if (!intransitionGroups.isEmpty())
2238     {
2239         return;
2240     }
2241 
2242     // Walk through the devices looking for state changes
2243     for (ListElement * e = deviceList.begin(); e != deviceList.end(); e = e->next)
2244     {
2245         DeviceImpl * dev  = (DeviceImpl *)e;
2246 
2247         if (dev->isPendingNewDevice()  ||
2248             dev->isPendingLostDevice() ||
2249             dev->isPendingCableOk() ||
2250             dev->isPendingZombie() ||
2251             dev->isPendingHDCPCapDone())
2252             eventsPending = true;
2253     }
2254 
2255     // If there were any queue an immediate callback to handle them
2256     if (eventsPending || isDiscoveryDetectComplete)
2257     {
2258         // Queue the fireEventsInternal.
2259         //   It's critical we don't allow this to be processed in a sleep
2260         //   since DD may do a modeset in response
2261         timer->queueCallback(this, &tagFireEvents, 0, false /* not allowed in sleep */);
2262     }
2263 }
2264 
2265 void ConnectorImpl::fireEventsInternal()
2266 {
2267     ListElement * next;
2268     Address::StringBuffer sb, sb1;
2269     DP_USED(sb);
2270     DP_USED(sb1);
2271     for (ListElement * e = deviceList.begin(); e != deviceList.end(); e = next)
2272     {
2273         next = e->next;
2274         DeviceImpl * dev  = (DeviceImpl *)e;
2275 
2276         if (dev->isPendingLostDevice())
2277         {
2278             //
2279             // For bug 2335599, where the connected monitor is switched to MST
2280             // from SST after S3 resume, we need to disconnect SST monitor
2281             // early before adding MST monitors. This will avoid client from
2282             // mistaking the disconnection of SST monitor later as parent of
2283             // MST monitors, which will wrongly disconnect MST monitors too.
2284             //
2285             if (!(!dev->multistream && linkUseMultistream()) &&
2286                 bDeferNotifyLostDevice)
2287             {
2288                 continue;
2289             }
2290             dev->shadow.plugged = false;
2291             DP_LOG(("DPCONN> Lost device %s", dev->address.toString(sb)));
2292             Address::NvU32Buffer addrBuffer;
2293             dpMemZero(addrBuffer, sizeof(addrBuffer));
2294             dev->address.toNvU32Buffer(addrBuffer);
2295             NV_DPTRACE_WARNING(LOST_DEVICE, dev->address.size(), addrBuffer[0], addrBuffer[1],
2296                                    addrBuffer[2], addrBuffer[3]);
2297             sink->lostDevice(dev);
2298 #if defined(DEBUG)
2299             // Assert that this device is not contained in any groups.
2300             List* groupLists[] = {
2301                 &activeGroups,
2302                 &inactiveGroups
2303             };
2304 
2305             for (unsigned i = 0; i < sizeof(groupLists) / sizeof(groupLists[0]); i++)
2306             {
2307                 List *groupList = groupLists[i];
2308                 for (ListElement *e = groupList->begin(); e != groupList->end(); e = e->next)
2309                 {
2310                     GroupImpl *g = (GroupImpl *)e;
2311                     DP_ASSERT(!g->contains(dev));
2312                 }
2313             }
2314 #endif
2315             delete dev;
2316             continue;
2317         }
2318 
2319         if (dev->isPendingCableOk())
2320         {
2321             dev->shadow.cableOk = dev->isCableOk();
2322             sink->notifyCableOkStateChange(dev, dev->shadow.cableOk);
2323         }
2324 
2325         if (dev->isPendingZombie())
2326         {
2327             dev->shadow.zombie =  dev->isZombie();
2328             if (dev->complianceDeviceEdidReadTest)
2329             {
2330                 // the zombie event will be hidden for DD/OS
2331                 DP_LOG(("DPCONN> Compliance: Device Internal Zombie? :  %d 0x%x", dev->shadow.zombie ? 1 : 0, dev));
2332                 return;
2333             }
2334             bMitigateZombie = false;
2335             DP_LOG(("DPCONN> Zombie? :  %d 0x%x", dev->shadow.zombie ? 1 : 0, dev));
2336             sink->notifyZombieStateChange(dev, dev->shadow.zombie);
2337         }
2338 
2339         if (dev->isPendingHDCPCapDone())
2340         {
2341             DP_ASSERT(dev->isHDCPCap != Indeterminate && "HDCPCap reading is not done!!");
2342             if (dev->isHDCPCap != Indeterminate)
2343             {
2344                 // Notify RM about the new Bcaps..
2345                 if (dev->isActive())
2346                 {
2347                     RmDfpCache dfpCache = {0};
2348                     dfpCache.updMask = 0;
2349                     dfpCache.bcaps = *dev->BCAPS;
2350                     for (unsigned i=0; i<HDCP_KSV_SIZE; i++)
2351                         dfpCache.bksv[i] = dev->BKSV[i];
2352 
2353                     dfpCache.updMask |= (1 << NV0073_CTRL_DFP_UPDATE_DYNAMIC_DFP_CACHE_MASK_BCAPS);
2354                     dfpCache.updMask |= (1 << NV0073_CTRL_DFP_UPDATE_DYNAMIC_DFP_CACHE_MASK_BKSV);
2355                     dev->connector->main->rmUpdateDynamicDfpCache(dev->activeGroup->headIndex, &dfpCache, False);
2356                 }
2357 
2358                 sink->notifyHDCPCapDone(dev, !!dev->isHDCPCap);
2359                 DP_LOG(("DPCONN> Notify HDCP cap Done : %x", !!dev->isHDCPCap));
2360             }
2361             else
2362             {
2363                 sink->notifyHDCPCapDone(dev, false);
2364             }
2365 
2366             dev->shadow.hdcpCapDone = true;
2367         }
2368 
2369         bool mustDisconnect = dev->isMustDisconnect();
2370         if (dev->shadow.mustDisconnect != mustDisconnect && mustDisconnect)
2371         {
2372             dev->shadow.mustDisconnect = mustDisconnect;
2373             sink->notifyMustDisconnect(dev->activeGroup);
2374         }
2375     }
2376 
2377     for (ListElement * e = deviceList.begin(); e != deviceList.end(); e = next)
2378     {
2379         next = e->next;
2380         DeviceImpl * dev  = (DeviceImpl *)e;
2381 
2382         if (dev->isPendingNewDevice())
2383         {
2384             if (bReportDeviceLostBeforeNew && bDeferNotifyLostDevice)
2385             {
2386                 // Let's try to find if there's a device pending lost on the same address
2387                 DeviceImpl* _device = NULL;
2388                 for (ListElement * le = deviceList.begin(); le != deviceList.end(); le = le->next)
2389                 {
2390                     _device = (DeviceImpl*)le;
2391                     if ((_device->address == dev->address) && (_device->plugged != dev->plugged))
2392                         break;
2393                 }
2394                 if (_device &&
2395                     (_device->address == dev->address) &&
2396                     (_device->plugged != dev->plugged))
2397                 {
2398                     // If yes, then we need to report this lost device first.
2399                     _device->shadow.plugged = false;
2400                     DP_LOG(("DPCONN> Lost device 0x%x", _device));
2401                     sink->lostDevice(_device);
2402                     DP_ASSERT(!_device->activeGroup && "DD didn't remove panel from group");
2403                     delete _device;
2404                 }
2405             }
2406             dev->shadow.plugged = true;
2407             if (dev->isDSCPossible())
2408             {
2409                 DP_LOG(("DPCONN> New device %s | Native DSC Capability - %s | DSC Decompression Device - %s",
2410                         dev->address.toString(sb),
2411                         (dev->isDSCSupported() ? "Capable" : "Not Capable"),
2412                         (dev->devDoingDscDecompression) ? dev->devDoingDscDecompression->address.toString(sb1):"NA"));
2413             }
2414             else
2415             {
2416                 DP_LOG(("DPCONN> New device %s", dev->address.toString(sb)));
2417             }
2418 
2419             Address::NvU32Buffer addrBuffer;
2420             dpMemZero(addrBuffer, sizeof(addrBuffer));
2421             dev->address.toNvU32Buffer(addrBuffer);
2422             NV_DPTRACE_INFO(NEW_SINK_REPORTED, dev->address.size(), addrBuffer[0], addrBuffer[1],
2423                                 addrBuffer[2], addrBuffer[3]);
2424 
2425             sink->newDevice(dev);
2426         }
2427     }
2428 
2429     if (isDiscoveryDetectComplete)
2430     {
2431         //
2432         // Bug 200236666 :
2433         // isDiscoveryDetectComplete can be set when we process a new device after
2434         // completing last edid read. In such scenario we will send notifyDetectComplete
2435         // before newDevice for that sink has been sent to DD
2436         //    a/ sink->newDevice(dev) above can trigger the pending edid read
2437         //    b/ after last edid read completes (::mstEdidCompleted), ::processNewDevice
2438         //       will set the plugged flag for new device
2439         //    c/ this will queue pendingNewDevice event callback for the last device pending discovery
2440         //    d/ isDiscoveryDetectComplete flag set during b/ will trigger a
2441         //       premature notifyDetectComplete to DD before pendingNewDevice callback
2442         // To fix above scenario : check if there is any newly pending new/lost device
2443         //                         if yes, then defer sending notifyDetectComplete till next callback
2444         //
2445         bool bDeferNotifyDetectComplete = false;
2446         for (ListElement * e = deviceList.begin(); e != deviceList.end(); e = next)
2447         {
2448             next = e->next;
2449             DeviceImpl * dev  = (DeviceImpl *)e;
2450 
2451             if (dev->isPendingNewDevice() || dev->isPendingLostDevice())
2452             {
2453                 bDeferNotifyDetectComplete = true;
2454                 DP_ASSERT(0 && "DP-CONN> Defer notifyDetectComplete as a new/lost device is pending!");
2455                 break;
2456             }
2457         }
2458 
2459         if (!bDeferNotifyDetectComplete)
2460         {
2461             isDiscoveryDetectComplete = false;
2462             DP_LOG(("DP-CONN> NotifyDetectComplete"));
2463             sink->notifyDetectComplete();
2464         }
2465     }
2466 
2467 }
2468 
2469 //
2470 // This call will be deprecated as soon as all clients move to the new API
2471 //
2472 bool ConnectorImpl::isHeadShutDownNeeded(Group * target,               // Group of panels we're attaching to this head
2473                                          unsigned headIndex,
2474                                          unsigned twoChannelAudioHz,   // if you need 192khz stereo specify 192000 here
2475                                          unsigned eightChannelAudioHz, // Same setting for multi channel audio.
2476                                          //  DisplayPort encodes 3-8 channel streams as 8 channel
2477                                          NvU64 pixelClockHz,           // Requested pixel clock for the mode
2478                                          unsigned rasterWidth,
2479                                          unsigned rasterHeight,
2480                                          unsigned rasterBlankStartX,
2481                                          unsigned rasterBlankEndX,
2482                                          unsigned depth)
2483 {
2484     ModesetInfo modesetInfo = ModesetInfo(twoChannelAudioHz, eightChannelAudioHz, pixelClockHz,
2485                                           rasterWidth, rasterHeight, (rasterBlankStartX - rasterBlankEndX), 0 /*surfaceHeight*/,
2486                                           depth, rasterBlankStartX, rasterBlankEndX);
2487     return isHeadShutDownNeeded(target, headIndex, modesetInfo);
2488 }
2489 
2490 //
2491 // Head shutdown will be needed if any of the following conditions are true:
2492 // a. Link rate is going lower than current
2493 // b. Head is activated as MST
2494 //
2495 bool ConnectorImpl::isHeadShutDownNeeded(Group * target,               // Group of panels we're attaching to this head
2496                                          unsigned headIndex,
2497                                          ModesetInfo modesetInfo)
2498 {
2499     if (linkUseMultistream())
2500     {
2501          return true;
2502     }
2503     if (activeGroups.isEmpty())
2504     {
2505         return false;
2506     }
2507 
2508     bool bHeadShutdownNeeded = true;
2509     LinkConfiguration lowestSelected;
2510 
2511     // Force highestLink config in SST
2512     bool bSkipLowestConfigCheck = false;
2513     bool bIsModeSupported = false;
2514     LinkConfiguration maxLc = getMaxLinkConfig();
2515     lowestSelected = maxLc;
2516     GroupImpl* targetImpl = (GroupImpl*)target;
2517 
2518     // Certain panels only work when link train to highest linkConfig in SST mode.
2519     for (Device * i = enumDevices(0); i; i=enumDevices(i))
2520     {
2521         DeviceImpl * dev = (DeviceImpl *)i;
2522         if (dev->forceMaxLinkConfig())
2523         {
2524             bSkipLowestConfigCheck = true;
2525         }
2526     }
2527 
2528     //
2529     // Check if there is a special request from the client,
2530     // If so, skip lowering down the link config.
2531     //
2532     if (this->preferredLinkConfig.isValid())
2533     {
2534         lowestSelected = preferredLinkConfig;
2535         bSkipLowestConfigCheck = true;
2536     }
2537 
2538     // If the flag is set, simply neglect downgrading to lowest possible linkConfig
2539     if (!bSkipLowestConfigCheck)
2540     {
2541         LinkConfiguration lConfig = lowestSelected;
2542 
2543         bIsModeSupported = getValidLowestLinkConfig(lConfig, lowestSelected, modesetInfo);
2544     }
2545     else
2546     {
2547         if (this->willLinkSupportModeSST(lowestSelected, modesetInfo))
2548         {
2549             bIsModeSupported = true;
2550         }
2551     }
2552 
2553     if (bIsModeSupported)
2554     {
2555         //
2556         // This is to handle a case where we query current link config
2557         // to UEFI during boot time and it fails to return. Currently
2558         // we do not handle this scenario and head is not shut down
2559         // though it's actually required. This is to allow head shutdown
2560         // in such cases.
2561         //
2562         if (!isLinkActive())
2563         {
2564             return true;
2565         }
2566 
2567         // For dual DP while changing link config, we need to shut
2568         // down the head
2569         if (lowestSelected.lanes == 8)
2570         {
2571             // If link config is changing, head shutdown will be needed.
2572             if ((activeLinkConfig.lanes == lowestSelected.lanes) &&
2573                 (activeLinkConfig.peakRate == lowestSelected.peakRate))
2574             {
2575                 bHeadShutdownNeeded = false;
2576             }
2577         }
2578         //
2579         // If link config is going lower then we need to shut down the
2580         // head. If we link train to a lower config before reducing the
2581         // mode, we will hang the HW since head would still be driving
2582         // the higher mode at the time of link train.
2583         //
2584         else if ((lowestSelected.peakRate * lowestSelected.lanes) >= (activeLinkConfig.peakRate * activeLinkConfig.lanes))
2585         {
2586             bHeadShutdownNeeded = false;
2587         }
2588     }
2589     else
2590     {
2591         DP_ASSERT( 0 && "DP-CONN> This mode is not possible at any link configuration!");
2592     }
2593 
2594     if (targetImpl)
2595     {
2596         targetImpl->bIsHeadShutdownNeeded = bHeadShutdownNeeded;
2597     }
2598 
2599     return bHeadShutdownNeeded;
2600 }
2601 
2602 bool ConnectorImpl::isLinkTrainingNeededForModeset (ModesetInfo modesetInfo)
2603 {
2604     // Force highestLink config in SST
2605     bool bSkipLowestConfigCheck      = false;
2606     bool bIsModeSupported            = false;
2607     LinkConfiguration lowestSelected = getMaxLinkConfig();
2608 
2609     if (linkUseMultistream())
2610     {
2611         if (!isLinkActive())
2612         {
2613             // If MST, we always need to link train if link is not active
2614             return true;
2615         }
2616         else if (getMaxLinkConfig() != activeLinkConfig)
2617         {
2618             //
2619             // If the link is active, we have to retrain, if active Link Config is
2620             // not the highest possible Link Config.
2621             //
2622             return true;
2623         }
2624         else
2625         {
2626             //
2627             // We don't have to retrain if link is active and at highest possible config
2628             // since for MST we should always link train to highest possible Link Config.
2629             //
2630             return false;
2631         }
2632     }
2633 
2634     //
2635     // Link training is needed if link is not alive OR alive but inactive
2636     // ie., lane status reports symbol lock/interlane align/CR failures
2637     //
2638     if (isLinkLost() || !isLinkActive())
2639     {
2640         return true;
2641     }
2642 
2643     //
2644     // Link training is needed if link config was previously guessed (not assessed by the driver).
2645     // The link config is marked as guessed in below cases -
2646     //    a. Invalid link rate returned by UEFI
2647     //    b. When max link config is HBR3 and currently assessed by UEFI != HBR3
2648     //    c. If a SOR is not assigned to display during link assessment
2649     //
2650     if (this->linkGuessed)
2651     {
2652         return true;
2653     }
2654 
2655     // Certain panels only work when link train to highest linkConfig in SST mode.
2656     for (Device * i = enumDevices(0); i; i=enumDevices(i))
2657     {
2658         DeviceImpl * dev = (DeviceImpl *)i;
2659         if (dev->forceMaxLinkConfig())
2660         {
2661             bSkipLowestConfigCheck = true;
2662         }
2663     }
2664 
2665     //
2666     // Check if there is a special request from the client,
2667     // If so, skip lowering down the link config.
2668     //
2669     if (this->preferredLinkConfig.isValid())
2670     {
2671         lowestSelected = preferredLinkConfig;
2672         bSkipLowestConfigCheck = true;
2673     }
2674 
2675     // If the flag is set, simply neglect downgrading to lowest possible linkConfig
2676     if (!bSkipLowestConfigCheck)
2677     {
2678         LinkConfiguration lConfig = lowestSelected;
2679 
2680         bIsModeSupported = getValidLowestLinkConfig(lConfig, lowestSelected, modesetInfo);
2681     }
2682     else
2683     {
2684         if (this->willLinkSupportModeSST(lowestSelected, modesetInfo))
2685         {
2686             bIsModeSupported = true;
2687         }
2688     }
2689 
2690     //
2691     // Link training is needed if requested mode/link config is
2692     // different from the active mode/link config
2693     //
2694     if (bIsModeSupported)
2695     {
2696         if ((activeLinkConfig.lanes != lowestSelected.lanes) ||
2697                 (activeLinkConfig.peakRate != lowestSelected.peakRate))
2698         {
2699             return true;
2700         }
2701     }
2702     else
2703     {
2704         DP_ASSERT( 0 && "DP-CONN> This mode is not possible at any link configuration!");
2705     }
2706 
2707     return false;
2708 }
2709 
2710 bool DisplayPort::SetConfigSingleHeadMultiStreamMode(Group **targets,
2711                                                 NvU32 displayIDs[],
2712                                                 NvU32 numStreams,
2713                                                 DP_SINGLE_HEAD_MULTI_STREAM_MODE mode,
2714                                                 bool bSetConfig,
2715                                                 NvU8 vbiosPrimaryDispIdIndex,
2716                                                 bool bEnableAudioOverRightPanel)
2717 {
2718     GroupImpl     *pTargetImpl = NULL;
2719     ConnectorImpl *pConnectorImpl = NULL;
2720     ConnectorImpl *pPrevConnectorImpl = NULL;
2721 
2722     if (numStreams > NV0073_CTRL_CMD_DP_SINGLE_HEAD_MAX_STREAMS || numStreams <= 0)
2723     {
2724         DP_LOG(("DP-CONN> ERROR: in configuring single head multistream mode "
2725                         "invalid number of streams"));
2726         return false;
2727     }
2728 
2729     for (NvU32 iter = 0; iter < numStreams; iter++)
2730     {
2731         pTargetImpl = (GroupImpl*)targets[iter];
2732 
2733         if(pTargetImpl == NULL)
2734         {
2735             DP_LOG(("DP-CONN> ERROR: in configuring single head multistream mode:"
2736                     "invalid target passed by client"));
2737             return false;
2738         }
2739 
2740         pConnectorImpl = (ConnectorImpl*) (pTargetImpl->parent);
2741 
2742         if (bSetConfig)
2743         {
2744             if (DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST == mode)
2745             {
2746                 //
2747                 // Detach any active firmware groups before configuring singleHead dual SST
2748                 //
2749                 if (pTargetImpl->isHeadAttached() && pTargetImpl->headInFirmware)
2750                 {
2751                     pConnectorImpl->notifyDetachBegin(NULL);
2752                     pConnectorImpl->notifyDetachEnd();
2753                 }
2754 
2755                 if (displayIDs[iter] != pConnectorImpl->main->getRootDisplayId())
2756                 {
2757                     DP_ASSERT( 0 && "DP-CONN> invalid single head multistream SST configuration !");
2758                     return false;
2759                 }
2760 
2761                 // 0th index is primary connector index,
2762                 // 1st is secondary connector index so on
2763                 if (iter > DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY)
2764                 {
2765                     pPrevConnectorImpl->pCoupledConnector = pConnectorImpl;
2766                     if (iter == (numStreams - 1))
2767                     {
2768                         pConnectorImpl->pCoupledConnector =
2769                             (ConnectorImpl*)((GroupImpl*)targets[DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY])->parent;
2770                     }
2771                     // Clear secondary connector's link guessed state
2772                     pConnectorImpl->linkGuessed = false;
2773                 }
2774 
2775                 pPrevConnectorImpl = pConnectorImpl;
2776             }
2777 
2778             pTargetImpl->singleHeadMultiStreamMode = mode;
2779             pTargetImpl->singleHeadMultiStreamID = (DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID)iter;
2780 
2781             // Save the 'Audio over Right Pannel' configuration in Connector Impl
2782             // Use this configuration when SF gets programed.
2783             if (bEnableAudioOverRightPanel)
2784             {
2785                 pConnectorImpl->bAudioOverRightPanel = true;
2786             }
2787         }
2788         else
2789         {
2790             pTargetImpl->singleHeadMultiStreamMode = DP_SINGLE_HEAD_MULTI_STREAM_MODE_NONE;
2791             pTargetImpl->singleHeadMultiStreamID = DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY;
2792             pConnectorImpl->pCoupledConnector = NULL;
2793             pConnectorImpl->bAudioOverRightPanel = false;
2794         }
2795     }
2796 
2797     pConnectorImpl->main->configureSingleHeadMultiStreamMode(displayIDs,
2798                     numStreams,
2799                     (NvU32)mode,
2800                     bSetConfig,
2801                     vbiosPrimaryDispIdIndex);
2802 
2803     return true;
2804 }
2805 
2806 //
2807 // This call will be deprecated as soon as all clients move to the new API
2808 //
2809 bool ConnectorImpl::notifyAttachBegin(Group * target,               // Group of panels we're attaching to this head
2810                                       unsigned headIndex,
2811                                       unsigned twoChannelAudioHz,         // if you need 192khz stereo specify 192000 here
2812                                       unsigned eightChannelAudioHz,       // Same setting for multi channel audio.
2813                                       //  DisplayPort encodes 3-8 channel streams as 8 channel
2814                                       NvU64 pixelClockHz,                 // Requested pixel clock for the mode
2815                                       unsigned rasterWidth,
2816                                       unsigned rasterHeight,
2817                                       unsigned rasterBlankStartX,
2818                                       unsigned rasterBlankEndX,
2819                                       unsigned depth)
2820 {
2821     ModesetInfo modesetInfo(twoChannelAudioHz, eightChannelAudioHz, pixelClockHz, rasterWidth,
2822                             rasterHeight, (rasterBlankStartX - rasterBlankEndX), 0 /*surfaceHeight*/,
2823                             depth, rasterBlankStartX, rasterBlankEndX);
2824 
2825     DpModesetParams modesetParams(headIndex, modesetInfo);
2826 
2827     return notifyAttachBegin (target, modesetParams);
2828 }
2829 
2830 bool ConnectorImpl::setDeviceDscState(Device * dev, bool bEnableDsc)
2831 {
2832     if (!((DeviceImpl *)dev)->isDSCPossible())
2833     {
2834         return true;
2835     }
2836 
2837     if (bEnableDsc)
2838     {
2839         if (dscEnabledDevices.contains(dev))
2840         {
2841             DP_LOG(("DP> DSC already enabled on device"));
2842             return true;
2843         }
2844         if(!(((DeviceImpl *)dev)->setDscEnable(true /*bEnableDsc*/)))
2845         {
2846             DP_ASSERT(!"DP-CONN> Failed to configure DSC on Sink!");
2847             return false;
2848         }
2849         dscEnabledDevices.insertFront(dev);
2850     }
2851     else
2852     {
2853         if (!dscEnabledDevices.contains(dev))
2854         {
2855             return true;
2856         }
2857         bool bCurrDscEnable = false;
2858         // Get Current DSC Enable State
2859         if (!((DeviceImpl *)dev)->getDscEnable(&bCurrDscEnable))
2860         {
2861             DP_LOG(("DP> Not able to get DSC Enable State!"));
2862         }
2863 
2864         if (bCurrDscEnable)
2865         {
2866 
2867             bool bDisableDsc = true;
2868             // Before disabling DSC check if other device with same parent has DSC enabled or not
2869             for (Device * i = dscEnabledDevices.next(NULL); i != NULL; i = dscEnabledDevices.next(i))
2870             {
2871                 if ((i != dev) && (((DeviceImpl *)i)->parent == ((DeviceImpl *)dev)->parent))
2872                 {
2873                     DP_LOG(("Parent is shared among devices and other device has DSC enabled so we can't disable DSC"));
2874                     bDisableDsc = false;
2875                     break;
2876                 }
2877             }
2878             if(bDisableDsc && !((DeviceImpl *)dev)->setDscEnable(false /*bEnableDsc*/))
2879             {
2880                 DP_ASSERT(!"DP-CONN> Failed to configure DSC on Sink!");
2881                 return false;
2882             }
2883         }
2884         dscEnabledDevices.remove(dev);
2885     }
2886     return true;
2887 }
2888 
2889 bool ConnectorImpl::needToEnableFEC(const DpPreModesetParams &params)
2890 {
2891     for (NvU32 i = 0; i < NV_MAX_HEADS; i++)
2892     {
2893         if ((params.headMask & NVBIT(i)) == 0x0)
2894             continue;
2895 
2896         if ((params.head[i].pTarget == NULL) ||
2897             !params.head[i].pModesetParams->modesetInfo.bEnableDsc)
2898             continue;
2899 
2900         // eDP can support DSC with and without FEC
2901         DeviceImpl * nativeDev = this->findDeviceInList(Address());
2902         if (this->main->isEDP() && nativeDev)
2903             return nativeDev->getFECSupport();
2904         else
2905             return true;
2906     }
2907 
2908     return false;
2909 }
2910 
2911 void ConnectorImpl::dpPreModeset(const DpPreModesetParams &params)
2912 {
2913     this->bFECEnable |= this->needToEnableFEC(params);
2914 
2915     DP_ASSERT(this->inTransitionHeadMask == 0x0);
2916     this->inTransitionHeadMask = 0x0;
2917 
2918     for (NvU32 i = 0; i < NV_MAX_HEADS; i++)
2919     {
2920         if ((params.headMask & NVBIT(i)) == 0x0)
2921             continue;
2922 
2923         this->inTransitionHeadMask |= NVBIT(i);
2924 
2925         if (params.head[i].pTarget != NULL)
2926         {
2927             DP_ASSERT(params.head[i].pModesetParams->headIndex == i);
2928             this->notifyAttachBegin(params.head[i].pTarget,
2929                                     *params.head[i].pModesetParams);
2930         }
2931         else
2932         {
2933             this->notifyDetachBegin(this->perHeadAttachedGroup[i]);
2934         }
2935         this->perHeadAttachedGroup[i] = params.head[i].pTarget;
2936     }
2937 }
2938 
2939 void ConnectorImpl::dpPostModeset(void)
2940 {
2941     for (NvU32 i = 0; i < NV_MAX_HEADS; i++)
2942     {
2943         if ((this->inTransitionHeadMask & NVBIT(i)) == 0x0)
2944             continue;
2945 
2946         if (this->perHeadAttachedGroup[i] != NULL)
2947             this->notifyAttachEnd(false);
2948         else
2949             this->notifyDetachEnd();
2950 
2951         this->inTransitionHeadMask &= ~NVBIT(i);
2952     }
2953 }
2954 
2955 //
2956 // Notify library before/after modeset (update)
2957 // Here is what NAB essentially does:
2958 //   0. Makes sure TMDS is not attached
2959 //   1. Trains link to optimized link config ("optimized" depends on DP1.1, DP1.2)
2960 //   2. Performs quick watermark check for IMP. If IMP is not possible, forces link, zombies devices
2961 //   3. if anything of above fails, marks devices in given group as zombies
2962 //
2963 // Return : true  - NAB passed
2964 //          false - NAB failed due to invalid params or link training failure
2965 //                  Link configs are forced in case of link training failure
2966 //
2967 bool ConnectorImpl::notifyAttachBegin(Group *                target,       // Group of panels we're attaching to this head
2968                                       const DpModesetParams       &modesetParams)
2969 {
2970     unsigned twoChannelAudioHz         = modesetParams.modesetInfo.twoChannelAudioHz;
2971     unsigned eightChannelAudioHz       = modesetParams.modesetInfo.eightChannelAudioHz;
2972     NvU64    pixelClockHz              = modesetParams.modesetInfo.pixelClockHz;
2973     unsigned rasterWidth               = modesetParams.modesetInfo.rasterWidth;
2974     unsigned rasterHeight              = modesetParams.modesetInfo.rasterHeight;
2975     unsigned rasterBlankStartX         = modesetParams.modesetInfo.rasterBlankStartX;
2976     unsigned rasterBlankEndX           = modesetParams.modesetInfo.rasterBlankEndX;
2977     unsigned depth                     = modesetParams.modesetInfo.depth;
2978     bool     bLinkTrainingStatus       = true;
2979     bool     bEnableDsc                = modesetParams.modesetInfo.bEnableDsc;
2980     bool     bEnableFEC;
2981     bool     bEnablePassThroughForPCON = modesetParams.modesetInfo.bEnablePassThroughForPCON;
2982 
2983     if(preferredLinkConfig.isValid())
2984     {
2985         bEnableFEC = preferredLinkConfig.bEnableFEC;
2986     }
2987     else
2988     {
2989         DeviceImpl * nativeDev = findDeviceInList(Address());
2990         if (main->isEDP() && nativeDev)
2991         {
2992             // eDP can support DSC with and without FEC
2993             bEnableFEC = bEnableDsc && nativeDev->getFECSupport();
2994         }
2995         else
2996         {
2997             bEnableFEC = bEnableDsc;
2998         }
2999     }
3000 
3001     DP_LOG(("DPCONN> Notify Attach Begin (Head %d, pclk %d raster %d x %d  %d bpp",
3002             modesetParams.headIndex, pixelClockHz, rasterWidth, rasterHeight, depth));
3003     NV_DPTRACE_INFO(NOTIFY_ATTACH_BEGIN, modesetParams.headIndex, pixelClockHz, rasterWidth, rasterHeight,
3004                        depth, bEnableDsc, bEnableFEC);
3005 
3006     if (!depth || !pixelClockHz)
3007     {
3008         DP_ASSERT(!"DP-CONN> Params with zero value passed to query!");
3009         return false;
3010     }
3011 
3012     if ((modesetParams.modesetInfo.mode == DSC_DUAL) ||
3013         (modesetParams.modesetInfo.mode == DSC_DROP))
3014     {
3015         if ((modesetParams.headIndex == NV_SECONDARY_HEAD_INDEX_1) ||
3016             (modesetParams.headIndex == NV_SECONDARY_HEAD_INDEX_3))
3017         {
3018             DP_ASSERT(!"DP-CONN> For Two Head One OR, client should send Primary Head index!");
3019             return false;
3020         }
3021     }
3022 
3023     for (Device * dev = target->enumDevices(0); dev; dev = target->enumDevices(dev))
3024     {
3025         Address::StringBuffer buffer;
3026         DP_USED(buffer);
3027         DP_LOG(("DPCONN>   | %s (%s) |", dev->getTopologyAddress().toString(buffer), dev->isVideoSink() ? "VIDEO" : "BRANCH"));
3028     }
3029 
3030     if (firmwareGroup && ((GroupImpl *)firmwareGroup)->headInFirmware)
3031     {
3032         DP_ASSERT(bIsUefiSystem || (0 && "DPCONN> Firmware still active on head. De-activating"));
3033     }
3034 
3035     GroupImpl* targetImpl = (GroupImpl*)target;
3036 
3037     if (bEnableDsc)
3038     {
3039         DP_LOG(("DPCONN> DSC Mode = %s", (modesetParams.modesetInfo.mode == DSC_SINGLE) ? "SINGLE" : "DUAL"));
3040         targetImpl->dscModeRequest = modesetParams.modesetInfo.mode;
3041     }
3042 
3043     DP_ASSERT(!(targetImpl->isHeadAttached() && targetImpl->bIsHeadShutdownNeeded) && "Head should have been shut down but it is still active!");
3044 
3045     targetImpl->headInFirmware = false;
3046     if (firmwareGroup)
3047     {
3048         ((GroupImpl *)firmwareGroup)->headInFirmware = false;
3049     }
3050 
3051     if (firmwareGroup && activeGroups.contains((GroupImpl*)firmwareGroup))
3052     {
3053         if (((GroupImpl *)firmwareGroup)->isHeadAttached())
3054         {
3055             targetImpl->setHeadAttached(true);
3056         }
3057         activeGroups.remove((GroupImpl*)firmwareGroup);
3058         inactiveGroups.insertBack((GroupImpl*)firmwareGroup);
3059     }
3060 
3061     if (this->linkGuessed && (targetImpl->singleHeadMultiStreamMode != DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST))
3062     {
3063         DP_ASSERT(!(this->linkGuessed) && "Link was not assessed previously. Probable reason: system was not in driver mode. Assessing now.");
3064         this->assessLink();
3065     }
3066 
3067     DP_ASSERT(this->isLinkQuiesced == 0 && "According to bracketting calls TMDS/alternate DP still active!");
3068 
3069     // Transfer the group to active list
3070     inactiveGroups.remove(targetImpl);
3071     activeGroups.insertBack(targetImpl);
3072     intransitionGroups.insertFront(targetImpl);
3073 
3074     targetImpl->lastModesetInfo = ModesetInfo(twoChannelAudioHz, eightChannelAudioHz,
3075         pixelClockHz, rasterWidth, rasterHeight,
3076         (rasterBlankStartX - rasterBlankEndX), modesetParams.modesetInfo.surfaceHeight,
3077         depth, rasterBlankStartX, rasterBlankEndX, bEnableDsc, modesetParams.modesetInfo.mode);
3078 
3079     targetImpl->headIndex = modesetParams.headIndex;
3080     targetImpl->streamIndex = main->headToStream(modesetParams.headIndex, targetImpl->singleHeadMultiStreamID);
3081     targetImpl->colorFormat = modesetParams.colorFormat;
3082 
3083     DP_ASSERT(!this->isLinkQuiesced && "TMDS is attached, NABegin is impossible!");
3084 
3085     //
3086     // Update the FEC enabled flag according to the mode requested.
3087     //
3088     // In MST config, if one panel needs DSC/FEC and the other one does not,
3089     // we still need to keep FEC enabled on the connector since at least one
3090     // stream needs it.
3091     //
3092     this->bFECEnable |= bEnableFEC;
3093 
3094     highestAssessedLC.enableFEC(this->bFECEnable);
3095 
3096     if (main->isEDP())
3097     {
3098         main->configurePowerState(true);
3099         if (bOuiCached)
3100         {
3101             hal->setOuiSource(cachedSourceOUI, &cachedSourceModelName[0],
3102                               6 /* string length of ieeeOuiDevId */,
3103                               cachedSourceChipRevision);
3104         }
3105         else
3106         {
3107             DP_ASSERT("eDP Source OUI is not cached!");
3108         }
3109     }
3110 
3111     // if failed, we're guaranteed that assessed link rate didn't meet the mode requirements
3112     // isZombie() will catch this
3113     bLinkTrainingStatus = trainLinkOptimized(getMaxLinkConfig());
3114 
3115     // if LT is successful, see if panel supports DSC and if so, set DSC enabled/disabled
3116     // according to the mode requested.
3117     if(bLinkTrainingStatus)
3118     {
3119         for (Device * dev = target->enumDevices(0); dev; dev = target->enumDevices(dev))
3120         {
3121             if (bPConConnected)
3122             {
3123                 if (!(((DeviceImpl *)dev)->setDscEnableDPToHDMIPCON(bEnableDsc, bEnablePassThroughForPCON)))
3124                 {
3125                     DP_ASSERT(!"DP-CONN> Failed to configure DSC on DP to HDMI PCON!");
3126                 }
3127             }
3128             else if(!setDeviceDscState(dev, bEnableDsc))
3129             {
3130                 DP_ASSERT(!"DP-CONN> Failed to configure DSC on Sink!");
3131             }
3132         }
3133     }
3134 
3135 // TODO: Need to check if we can completely remove DP_OPTION_HDCP_12_ENABLED and remove it
3136 
3137     beforeAddStream(targetImpl);
3138 
3139     if (linkUseMultistream())
3140     {
3141         // Which pipeline to take the affect out of trigger ACT
3142         if ((DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST != targetImpl->singleHeadMultiStreamMode) ||
3143             (DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY == targetImpl->singleHeadMultiStreamID))
3144         {
3145             main->configureTriggerSelect(targetImpl->headIndex, targetImpl->singleHeadMultiStreamID);
3146         }
3147     }
3148 
3149     if (!linkUseMultistream() || main->supportMSAOverMST())
3150     {
3151         bool enableInbandStereoSignaling = false;
3152 
3153         DP_ASSERT(activeGroups.isEmpty() == false);
3154 
3155         if (main->isInbandStereoSignalingSupported())
3156         {
3157             enableInbandStereoSignaling = true;
3158         }
3159 
3160         //
3161         // Bug 200362535
3162         // setDpStereoMSAParameters does not cache the msa params. It will immediately
3163         // apply just the stereo specific parameters. This is required because we
3164         // can toggle the msa params using nvidia control panel and in that scenario
3165         // we do not get supervisor interrupts. Since SV interrupts do not occur the
3166         // msa parameters do not get applied. So to avoid having to reboot to apply the
3167         // stereo msa params setDpStereoMSAParameters is called.
3168         //
3169         // setDpMSAParameters will contain all msa params, including stereo cached.
3170         // These will be applied during supervisor interrupt. So if we will get
3171         // SV interrupts later the same stereo settings will be applied twice.
3172         // first by setDpStereoMSAParameters and later by setDpMSAParameters.
3173         //
3174         main->setDpStereoMSAParameters(!enableInbandStereoSignaling, modesetParams.msaparams);
3175         main->setDpMSAParameters(!enableInbandStereoSignaling, modesetParams.msaparams);
3176     }
3177 
3178     NV_DPTRACE_INFO(NOTIFY_ATTACH_BEGIN_STATUS, bLinkTrainingStatus);
3179 
3180     bFromResumeToNAB = false;
3181     return bLinkTrainingStatus;
3182 }
3183 
3184 
3185 //
3186 // modesetCancelled True, when DD respected NAB failure and cancelled modeset.
3187 //                  False, when NAB succeeded, or DD didn't honor NAB failure
3188 //
3189 // Here is what NAE supposed to do:
3190 // 1. modesetCancelled == TRUE, NAB failed:
3191 //         unzombie all devices and set linkForced to false; We have Status Quo for next modeset
3192 // 2. modesetCancelled == False, NAB failed:
3193 //        If NAB failed, linkForces is TRUE. NAE goes finds zombied devices and notifies DD about them.
3194 // 3. modesetCancelled == False, NAB succeeded:
3195 //        NAE is no-op. (but we have some special sanity code)
3196 //
3197 void ConnectorImpl::notifyAttachEnd(bool modesetCancelled)
3198 {
3199     GroupImpl* currentModesetDeviceGroup = NULL;
3200     DP_LOG(("DPCONN> Notify Attach End"));
3201     NV_DPTRACE_INFO(NOTIFY_ATTACH_END);
3202 
3203     bFromResumeToNAB = false;
3204 
3205     if (intransitionGroups.isEmpty())
3206     {
3207         DP_ASSERT( 0 && "INVALID STATE: Modeset Group is NULL");
3208         return;
3209     }
3210 
3211     currentModesetDeviceGroup = intransitionGroups.pop();
3212 
3213     if (modesetCancelled)
3214     {
3215         currentModesetDeviceGroup->setHeadAttached(false);
3216     }
3217 
3218     // set dscModeActive to what was requested in NAB and clear dscModeRequest
3219     currentModesetDeviceGroup->dscModeActive = currentModesetDeviceGroup->dscModeRequest;
3220     currentModesetDeviceGroup->dscModeRequest = DSC_MODE_NONE;
3221 
3222     currentModesetDeviceGroup->setHeadAttached(true);
3223     RmDfpCache dfpCache = {0};
3224     dfpCache.updMask = 0;
3225     if (currentModesetDeviceGroup->isHeadAttached())
3226     {
3227         for (DeviceImpl * dev = (DeviceImpl *)currentModesetDeviceGroup->enumDevices(0);
3228             dev; dev = (DeviceImpl *)currentModesetDeviceGroup->enumDevices(dev))
3229         {
3230             dfpCache.bcaps = *dev->BCAPS;
3231             for (unsigned i=0; i<HDCP_KSV_SIZE; i++)
3232                 dfpCache.bksv[i] = dev->BKSV[i];
3233 
3234             dfpCache.updMask |= (1 << NV0073_CTRL_DFP_UPDATE_DYNAMIC_DFP_CACHE_MASK_BCAPS);
3235             dfpCache.updMask |= (1 << NV0073_CTRL_DFP_UPDATE_DYNAMIC_DFP_CACHE_MASK_BKSV);
3236             main->rmUpdateDynamicDfpCache(dev->activeGroup->headIndex, &dfpCache, True);
3237 
3238             // Remove this while enabling HDCP for MSC
3239             break;
3240         }
3241     }
3242 
3243     //
3244     // Add rest of the streams (other than primary) in notifyAE, since this can't be done
3245     // unless a SOR is attached to a Head (part of modeset), and trigger ACT immediate
3246     //
3247     if ((DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST == currentModesetDeviceGroup->singleHeadMultiStreamMode) &&
3248         (currentModesetDeviceGroup->singleHeadMultiStreamID > DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY))
3249     {
3250         DP_ASSERT(linkUseMultistream() && "it should be multistream link to configure single head MST");
3251         hal->payloadTableClearACT();
3252         hal->payloadAllocate(currentModesetDeviceGroup->streamIndex,
3253             currentModesetDeviceGroup->timeslot.begin, currentModesetDeviceGroup->timeslot.count);
3254         main->configureTriggerSelect(currentModesetDeviceGroup->headIndex, currentModesetDeviceGroup->singleHeadMultiStreamID);
3255         main->triggerACT();
3256     }
3257 
3258     afterAddStream(currentModesetDeviceGroup);
3259 
3260     //
3261     // Turn on the Authentication/Encryption back if previous is on.
3262     // For DP1.1, let the upstream to turn it back.
3263     // For DP1.2, we should turn the modeset back if it was on.
3264     // The authentication will be called off during the modeset.
3265     //
3266     HDCPState hdcpState = {0};
3267     main->configureHDCPGetHDCPState(hdcpState);
3268     if ((!hdcpState.HDCP_State_Authenticated) && (isHDCPAuthOn == true)
3269         && (currentModesetDeviceGroup->hdcpEnabled))
3270     {
3271         if (!this->linkUseMultistream())
3272         {
3273             currentModesetDeviceGroup->hdcpEnabled = isHDCPAuthOn = false;
3274         }
3275     }
3276 
3277     fireEvents();
3278 }
3279 
3280 // Notify library before/after shutdown (update)
3281 void ConnectorImpl::notifyDetachBegin(Group * target)
3282 {
3283     if (!target)
3284         target = firmwareGroup;
3285 
3286     NV_DPTRACE_INFO(NOTIFY_DETACH_BEGIN);
3287 
3288     GroupImpl * group = (GroupImpl*)target;
3289 
3290     DP_LOG(("DPCONN> Notify detach begin"));
3291     DP_ASSERT((group->headInFirmware || group->isHeadAttached()) && "Disconnecting an inactive device");
3292 
3293     // check to see if a pattern request was on. if yes clear the pattern
3294     PatternInfo pattern_info;
3295     pattern_info.lqsPattern = hal->getPhyTestPattern();
3296     // send control call to rm for the pattern
3297     if (pattern_info.lqsPattern != LINK_QUAL_DISABLED)
3298     {
3299         pattern_info.lqsPattern = LINK_QUAL_DISABLED;
3300         if (!main->physicalLayerSetTestPattern(&pattern_info))
3301             DP_ASSERT(0 && "Could not set the PHY_TEST_PATTERN");
3302     }
3303 
3304     beforeDeleteStream(group);
3305 
3306     //
3307     // Set the trigger select so as to which frontend corresponding to the stream
3308     // to take the affect
3309     //
3310     if(linkUseMultistream())
3311     {
3312         main->configureTriggerSelect(group->headIndex, group->singleHeadMultiStreamID);
3313 
3314         // Clear payload of other than primary streams and trigger ACT immediate
3315         if ((DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST == group->singleHeadMultiStreamMode) &&
3316             (DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY != group->singleHeadMultiStreamID))
3317         {
3318             main->triggerACT();
3319             if (!hal->payloadWaitForACTReceived())
3320             {
3321                 DP_LOG(("DP-TS> Downstream device did not receive ACT during stream clear"));
3322                 DP_ASSERT(0);
3323             }
3324         }
3325     }
3326 
3327     intransitionGroups.insertFront(group);
3328 }
3329 
3330 //
3331 // Here is what NDE does:
3332 //  1. delete unplugged devices (they were zombies, if they're on this list)
3333 //  2. unmark zombies (they were plugged zombies, they might want to get link trained next time)
3334 //  3. mark head as detached (so that we can delete any HPD unplugged devices)
3335 //
3336 void ConnectorImpl::notifyDetachEnd(bool bKeepOdAlive)
3337 {
3338     GroupImpl* currentModesetDeviceGroup = NULL;
3339     DP_LOG(("DPCONN> Notify detach end"));
3340     NV_DPTRACE_INFO(NOTIFY_DETACH_END);
3341 
3342     if (intransitionGroups.isEmpty())
3343     {
3344         DP_ASSERT( 0 && "INVALID STATE: Modeset Group is NULL");
3345         return;
3346     }
3347 
3348     currentModesetDeviceGroup = intransitionGroups.pop();
3349 
3350     afterDeleteStream(currentModesetDeviceGroup);
3351 
3352     if (!linkUseMultistream())
3353     {
3354         Device * d = 0;
3355         for (d = currentModesetDeviceGroup->enumDevices(0);
3356              currentModesetDeviceGroup->enumDevices(d) != 0;
3357              d = currentModesetDeviceGroup->enumDevices(d))
3358         {
3359             // only one device in the group
3360             DP_ASSERT(d && (((DeviceImpl*)d)->activeGroup == currentModesetDeviceGroup));
3361         }
3362     }
3363 
3364     // nullify last modeset info
3365     dpMemZero(&currentModesetDeviceGroup->lastModesetInfo, sizeof(ModesetInfo));
3366     currentModesetDeviceGroup->setHeadAttached(false);
3367     currentModesetDeviceGroup->headInFirmware = false;
3368     currentModesetDeviceGroup->dscModeActive = DSC_MODE_NONE;
3369 
3370     // Mark head as disconnected
3371     bNoLtDoneAfterHeadDetach = true;
3372 
3373     //
3374     // Update the last modeset HDCP status here. Hdcp got disabled after modeset
3375     // thus hdcpPreviousStatus would be false to SST after device inserted.
3376     //
3377     HDCPState hdcpState = {0};
3378     main->configureHDCPGetHDCPState(hdcpState);
3379     if (!(isHDCPAuthOn = hdcpState.HDCP_State_Authenticated))
3380     {
3381         currentModesetDeviceGroup->hdcpEnabled = false;
3382     }
3383 
3384     // Update Vbios scratch register
3385     for (Device * d = currentModesetDeviceGroup->enumDevices(0); d;
3386          d = currentModesetDeviceGroup->enumDevices(d))
3387     {
3388         currentModesetDeviceGroup->updateVbiosScratchRegister(d);
3389     }
3390 
3391     // Reset value of bIsHeadShutdownNeeded to get rid of false asserts
3392     currentModesetDeviceGroup->bIsHeadShutdownNeeded = false;
3393 
3394     // If this is eDP and the LCD power is not ON, we don't need to Disable DSC here
3395     bool bPanelPwrSts = true;
3396     if ((!main->isEDP()) || (main->getEdpPowerData(&bPanelPwrSts, NULL) && bPanelPwrSts))
3397     {
3398         // Disable DSC decompression on the panel if panel supports DSC and reset bFECEnable Flag
3399         for (Device * dev = currentModesetDeviceGroup->enumDevices(0); dev; dev = currentModesetDeviceGroup->enumDevices(dev))
3400         {
3401             if(!(setDeviceDscState(dev, false/*bEnableDsc*/)))
3402             {
3403                 DP_ASSERT(!"DP-CONN> Failed to configure DSC on Sink!");
3404             }
3405         }
3406     }
3407 
3408     // Transfer to inactive group and cancel pending callbacks for that group.
3409     currentModesetDeviceGroup->cancelHdcpCallbacks();
3410     activeGroups.remove(currentModesetDeviceGroup);
3411     inactiveGroups.insertBack(currentModesetDeviceGroup);
3412 
3413     if (activeGroups.isEmpty())
3414     {
3415         cancelHdcpCallbacks();
3416 
3417         // We disconnected a panel, try to clear the transition
3418         if (linkAwaitingTransition)
3419         {
3420             assessLink();
3421         }
3422         //
3423         // Power down the links as we have switched away from the monitor.
3424         // Only power down if we are in single stream
3425         //
3426         else
3427         {
3428             //
3429             // Power down the links as we have switched away from the monitor.
3430             // For shared SOR case, we need this to keep SW stats in DP instances in sync.
3431             // Only power down the link when it's not a compliance test device.
3432             //
3433             // Some eDP panels are known having problems when power down.
3434             // See bug 1425706, 1376753, 1347872, 1355592
3435             //
3436             // Hotplug may trigger detach before processNewDevice if previous state has
3437             // lost device not yet detached. Avoid to powerdown for the case for following
3438             // device discovery hdcp probe.
3439             //
3440             if (!bIsDiscoveryDetectActive)
3441                 powerdownLink(!main->skipPowerdownEdpPanelWhenHeadDetach() && !bKeepOdAlive);
3442         }
3443         if (this->policyModesetOrderMitigation && this->modesetOrderMitigation)
3444             this->modesetOrderMitigation = false;
3445     }
3446     fireEvents();
3447 }
3448 
3449 bool ConnectorImpl::trainPCONFrlLink(PCONLinkControl *pconControl)
3450 {
3451     NvU32   loopCount   = NV_PCON_SOURCE_CONTROL_MODE_TIMEOUT_THRESHOLD;
3452     NvU32   frlRateMask = 0;
3453     bool    bFrlReady   = false;
3454     bool    result      = false;
3455 
3456     // Initial return values.
3457     pconControl->result.trainedFrlBwMask    = 0;
3458     pconControl->result.maxFrlBwTrained     = PCON_HDMI_LINK_BW_FRL_INVALID;
3459 
3460     // Step 1: Setup PCON for later operation
3461 
3462     // Step 1.1: Set D0 power
3463     hal->setPowerState(PowerStateD0);
3464 
3465     hal->resetProtocolConverter();
3466 
3467     // Step 1.2: Enable Source Control Mode and FRL mode, enable FRL-Ready IRQ
3468     hal->setSourceControlMode(true, true);
3469 
3470     do
3471     {
3472         //
3473         // Step 1.3: Poll for HDMI-Link-Status Change (0x2005 Bit 3)
3474         //           Get FRL Ready Bit (0x303B Bit 1)
3475         //
3476         hal->checkPCONFrlReady(&bFrlReady);
3477         if (bFrlReady == true)
3478         {
3479             break;
3480         }
3481         Timeout timeout(this->timer, NV_PCON_SOURCE_CONTROL_MODE_TIMEOUT_INTERVAL_MS);
3482         while(timeout.valid());
3483         continue;
3484     } while (--loopCount);
3485 
3486     if (bFrlReady == false)
3487     {
3488         pconControl->result.status = NV_DP_PCON_CONTROL_STATUS_ERROR_TIMEOUT;
3489         return false;
3490     }
3491 
3492     // Step 2: Assess FRL Link capability.
3493 
3494     //
3495     // Step 2.1: Configure FRL Link (FRL BW, BW mask / Concurrent)
3496     // Start with mask for all bandwidth. Please refer to definition of DPCD 0x305B.
3497     //
3498     result = hal->setupPCONFrlLinkAssessment(pconControl->frlHdmiBwMask,
3499                                              pconControl->flags.bExtendedLTMode,
3500                                              pconControl->flags.bConcurrentMode);
3501     if (result == false)
3502     {
3503         pconControl->result.status = NV_DP_PCON_CONTROL_STATUS_ERROR_GENERIC;
3504         return false;
3505     }
3506 
3507     // Step 2.2: Poll for HDMI-Link-Status Change (0x2005 Bit 3)
3508     loopCount = NV_PCON_FRL_LT_TIMEOUT_THRESHOLD;
3509     do
3510     {
3511         result = hal->checkPCONFrlLinkStatus(&frlRateMask);
3512         if (result == true)
3513         {
3514             break;
3515         }
3516         Timeout timeout(this->timer, NV_PCON_FRL_LT_TIMEOUT_INTERVAL_MS);
3517         while(timeout.valid());
3518         continue;
3519     } while (--loopCount);
3520 
3521     if (result == true)
3522     {
3523         //
3524         // frlRateMask is result from checkPCONFrlLinkStatus (0x3036) Bit 1~6.
3525         //
3526         pconControl->result.status              = NV_DP_PCON_CONTROL_STATUS_SUCCESS;
3527         pconControl->result.trainedFrlBwMask    = frlRateMask;
3528         pconControl->result.maxFrlBwTrained     = getMaxFrlBwFromMask(frlRateMask);
3529     }
3530     else
3531     {
3532         pconControl->result.status              = NV_DP_PCON_CONTROL_STATUS_ERROR_FRL_LT_FAILURE;
3533     }
3534     return result;
3535 }
3536 
3537 bool ConnectorImpl::assessPCONLinkCapability(PCONLinkControl *pConControl)
3538 {
3539     if (pConControl == NULL || !this->previousPlugged)
3540         return false;
3541 
3542     bool bIsFlushModeEnabled = enableFlush();
3543 
3544     if (!bIsFlushModeEnabled)
3545     {
3546         return false;
3547     }
3548 
3549     if (pConControl->flags.bSourceControlMode)
3550     {
3551         if (trainPCONFrlLink(pConControl) == false)
3552         {
3553             // restore Autonomous mode and treat this as an active DP dongle.
3554             hal->resetProtocolConverter();
3555             // Exit flush mode
3556             disableFlush();
3557             if (!pConControl->flags.bSkipFallback)
3558             {
3559                 bSkipAssessLinkForPCon = false;
3560                 assessLink();
3561             }
3562             return false;
3563         }
3564         activePConLinkControl.flags = pConControl->flags;
3565         activePConLinkControl.frlHdmiBwMask = pConControl->frlHdmiBwMask;
3566         activePConLinkControl.result = pConControl->result;
3567     }
3568     else
3569     {
3570         // restore Autonomous mode and treat this as an active DP dongle.
3571         hal->resetProtocolConverter();
3572     }
3573 
3574     // Step 3: Assess DP Link capability.
3575     LinkConfiguration lConfig = getMaxLinkConfig();
3576     highestAssessedLC = getMaxLinkConfig();
3577 
3578     hal->updateDPCDOffline();
3579     if (hal->isDpcdOffline())
3580     {
3581         disableFlush();
3582         return false;
3583     }
3584     if (!train(lConfig, false /* do not force LT */))
3585     {
3586         //
3587         // Note that now train() handles fallback, activeLinkConfig
3588         // has the max link config that was assessed.
3589         //
3590         lConfig = activeLinkConfig;
3591     }
3592 
3593     highestAssessedLC = lConfig;
3594     linkGuessed = false;
3595     disableFlush();
3596 
3597     this->bKeepLinkAliveForPCON = pConControl->flags.bKeepPCONLinkAlive;
3598     return true;
3599 }
3600 
3601 bool ConnectorImpl::getOuiSink(unsigned &ouiId, char * modelName, size_t modelNameBufferSize, NvU8 & chipRevision)
3602 {
3603     if (!previousPlugged || !hal->getOuiSupported())
3604         return false;
3605 
3606     return hal->getOuiSink(ouiId, modelName, modelNameBufferSize, chipRevision);
3607 }
3608 
3609 void ConnectorImpl::setIgnoreSourceOuiHandshake(bool bIgnoreOuiHandShake)
3610 {
3611     bIgnoreSrcOuiHandshake = bIgnoreOuiHandShake;
3612 }
3613 
3614 bool ConnectorImpl::getIgnoreSourceOuiHandshake()
3615 {
3616     return bIgnoreSrcOuiHandshake;
3617 }
3618 
3619 bool ConnectorImpl::performIeeeOuiHandshake()
3620 {
3621     const char *ieeeOuiDevId = "NVIDIA";
3622 
3623     if (!hal->getOuiSupported() || getIgnoreSourceOuiHandshake())
3624         return false;
3625 
3626     if (hal->setOuiSource(DPCD_OUI_NVIDIA, ieeeOuiDevId, 6 /* string length of ieeeOuiDevId */, 0) == AuxRetry::ack)
3627     {
3628         NvU8 chipRevision = 0;
3629 
3630         // parse client OUI.
3631         if (hal->getOuiSink(ouiId, &modelName[0], sizeof(modelName), chipRevision))
3632         {
3633             DP_LOG(("DP> SINK-OUI id(0x%08x) %s: rev:%d.%d", ouiId,
3634                         (NvU8*)modelName,
3635                         (unsigned)DRF_VAL(_DPCD, _SINK_HARDWARE_REV, _MAJOR, chipRevision),
3636                         (unsigned)DRF_VAL(_DPCD, _SINK_HARDWARE_REV, _MINOR, chipRevision)));
3637             return true;
3638         }
3639     }
3640     return false;
3641 }
3642 
3643 
3644 bool ConnectorImpl::willLinkSupportModeSST(const LinkConfiguration & linkConfig, const ModesetInfo & modesetInfo)
3645 {
3646     DP_ASSERT(!linkUseMultistream() && "IMP for SST only");
3647 
3648     //
3649     // mode is not known yet, we have to report is possible
3650     // Otherwise we're going to mark all devices as zombies on first HPD(c),
3651     // since modeset info is not available.
3652     //
3653     if (modesetInfo.pixelClockHz == 0)
3654         return true;
3655 
3656     if (linkConfig.lanes == 0 || linkConfig.peakRate == 0)
3657         return false;
3658 
3659     Watermark water;
3660 
3661     if (this->isFECSupported())
3662     {
3663         if (!isModePossibleSSTWithFEC(linkConfig, modesetInfo, &water, main->hasIncreasedWatermarkLimits()))
3664         {
3665             // Verify audio
3666             return false;
3667         }
3668     }
3669     else
3670     {
3671         if (!isModePossibleSST(linkConfig, modesetInfo, &water, main->hasIncreasedWatermarkLimits()))
3672         {
3673             // Verify audio
3674             return false;
3675         }
3676     }
3677     return true;
3678 }
3679 
3680 // gets max values for DPCD HAL and forces link trainig with that config
3681 void ConnectorImpl::forceLinkTraining()
3682 {
3683     LinkConfiguration forcedMaxConfig(getMaxLinkConfig());
3684     train(forcedMaxConfig, true);
3685 }
3686 
3687 void ConnectorImpl::powerdownLink(bool bPowerdownPanel)
3688 {
3689     LinkConfiguration powerOff = getMaxLinkConfig();
3690     bool bPanelPwrSts = true;
3691     powerOff.lanes = 0;
3692     // Inform Sink about Main Link Power Down.
3693 
3694     if (linkUseMultistream() && bPowerDownPhyBeforeD3)
3695     {
3696         PowerDownPhyMessage powerDownPhyMsg;
3697         NakData nack;
3698 
3699         for (Device * i = enumDevices(0); i; i=enumDevices(i))
3700         {
3701             if (i->isPlugged() && i->isVideoSink())
3702             {
3703                 Address devAddress = ((DeviceImpl*)i)->address;
3704                 powerDownPhyMsg.set(devAddress.parent(), devAddress.tail(), NV_TRUE);
3705                 this->messageManager->send(&powerDownPhyMsg, nack);
3706             }
3707         }
3708     }
3709 
3710     //
3711     // 1> If it is eDP and the power is not on, we don't need to put it into D3 here
3712     // 2> If FEC is enabled then we have to put panel in D3 after powering down mainlink
3713     //    as FEC disable has to be detected by panel which will happen as part of link
3714     //    power down, we need to keep panel in D0 for this.
3715     //
3716     if (!this->bFECEnable &&
3717         ((!main->isEDP()) || (main->getEdpPowerData(&bPanelPwrSts, NULL) && bPanelPwrSts)))
3718     {
3719         hal->setPowerState(PowerStateD3);
3720     }
3721 
3722     train(powerOff, !bPowerdownPanel);  // Train to 0 links 0 BW
3723 
3724     //
3725     // If FEC is enabled, put panel to D3 here for non-eDP.
3726     // For eDP with FEC support, FEC state would be cleared as part of panel
3727     // power down
3728     //
3729     if (this->bFECEnable && (!main->isEDP()))
3730     {
3731         hal->setPowerState(PowerStateD3);
3732     }
3733 
3734     // Set FEC state as false in link power down
3735     this->bFECEnable = false;
3736     highestAssessedLC.enableFEC(false);
3737 }
3738 
3739 GroupImpl * ConnectorImpl::getActiveGroupForSST()
3740 {
3741     if (this->linkUseMultistream())
3742         return 0;
3743     GroupImpl * groupAttached = 0;
3744     for (ListElement * e = activeGroups.begin(); e != activeGroups.end(); e = e->next)
3745     {
3746         // there should only be one group for the connector.
3747         if (groupAttached)
3748         {
3749             DP_ASSERT(0 && "Multiple attached heads");
3750             return 0;
3751         }
3752         groupAttached = (GroupImpl * )e;
3753     }
3754     return groupAttached;
3755 }
3756 
3757 bool ConnectorImpl::trainSingleHeadMultipleSSTLinkNotAlive(GroupImpl *pGroupAttached)
3758 {
3759     GroupImpl *pPriGrpAttached =  NULL;
3760     GroupImpl *pSecGrpAttached =  NULL;
3761     ConnectorImpl *pPriConnImpl = NULL;
3762     ConnectorImpl *pSecConnImpl = NULL;
3763 
3764     if ((pGroupAttached == NULL) ||
3765         (pCoupledConnector == NULL) ||
3766         (pGroupAttached->singleHeadMultiStreamMode != DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST))
3767     {
3768         return false;
3769     }
3770     if (pGroupAttached->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY)
3771     {
3772         pSecGrpAttached = pCoupledConnector->getActiveGroupForSST();
3773         pPriGrpAttached = pGroupAttached;
3774         pSecConnImpl = pCoupledConnector;
3775         pPriConnImpl = this;
3776     }
3777     else if (pGroupAttached->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY)
3778     {
3779         pPriGrpAttached = pCoupledConnector->getActiveGroupForSST();
3780         pSecGrpAttached = pGroupAttached;
3781         pPriConnImpl = pCoupledConnector;
3782         pSecConnImpl = this;
3783     }
3784     else
3785     {
3786         DP_ASSERT(0 && "Invalid 2-SST configuration ");
3787         return false;
3788     }
3789 
3790     if (!pPriGrpAttached || !pSecGrpAttached || !pPriConnImpl || !pSecConnImpl)
3791     {
3792         DP_ASSERT(0 && "Invalid 2-SST configuration ");
3793         return false;
3794     }
3795 
3796     if (!pPriConnImpl->trainLinkOptimizedSingleHeadMultipleSST(pPriGrpAttached))
3797     {
3798         DP_ASSERT(0 && "not able to configure 2-SST mode on primary link");
3799         return false;
3800     }
3801 
3802     if (!pSecConnImpl->trainLinkOptimizedSingleHeadMultipleSST(pSecGrpAttached))
3803     {
3804         DP_ASSERT(0 && "not able to configure 2-SST mode for secondary link");
3805         return false;
3806     }
3807 
3808     return true;
3809 }
3810 
3811 void ConnectorImpl::assessLink(LinkTrainingType trainType)
3812 {
3813     this->bSkipLt = false;  // Assesslink should never skip LT, so let's reset it in case it was set.
3814     bool bLinkStateToggle = false;
3815     LinkConfiguration _maxLinkConfig = getMaxLinkConfig();
3816 
3817     if (bSkipAssessLinkForPCon)
3818     {
3819         // Skip assessLink() for PCON. client should call assessPCONLinkCapability later.
3820         return;
3821     }
3822 
3823     if (trainType == NO_LINK_TRAINING)
3824     {
3825         train(preferredLinkConfig, false, trainType);
3826         return;
3827     }
3828 
3829 
3830     if (isLinkQuiesced ||
3831         (firmwareGroup && ((GroupImpl *)firmwareGroup)->headInFirmware))
3832     {
3833         highestAssessedLC = _maxLinkConfig;
3834         if (bIsUefiSystem && !hal->getSupportsMultistream())
3835         {
3836             //
3837             // Since this is a UEFI based system which can provide max link config
3838             // supported on this panel. So try to get the max supported link config
3839             // and update the highestAssessedLC. Once done set linkGuessed as false.
3840             //
3841             unsigned laneCount = 0;
3842             NvU64    linkRate = 0;
3843             NvU8     linkRateFromUefi, laneCountFromUefi;
3844 
3845             // Query the max link config if provided by UEFI.
3846             if ((!linkGuessed) && (main->getMaxLinkConfigFromUefi(linkRateFromUefi, laneCountFromUefi)))
3847             {
3848                 laneCount = laneCountFromUefi;
3849 
3850                 if (linkRateFromUefi == 0x6)
3851                 {
3852                     linkRate = RBR;
3853                 }
3854                 else if (linkRateFromUefi == 0xA)
3855                 {
3856                     linkRate = HBR;
3857                 }
3858                 else if (linkRateFromUefi == 0x14)
3859                 {
3860                     linkRate = HBR2;
3861                 }
3862                 else if (linkRateFromUefi == 0x1E)
3863                 {
3864                     linkRate = HBR3;
3865                 }
3866                 else
3867                 {
3868                     DP_ASSERT(0 && "DP> Invalid link rate returned from UEFI!");
3869                     linkGuessed = true;
3870                 }
3871 
3872                 if ((highestAssessedLC.peakRate == HBR3) &&
3873                     (linkRate != HBR3))
3874                 {
3875                     //
3876                     // UEFI does not support HBR3 yet (The support will be added in Volta).
3877                     // Mark the link as guessed when max supported link config is HBR3 and
3878                     // the currently assessed link config, by UEFI is not the highest, to
3879                     // force the link assessment by driver.
3880                     //
3881                     linkGuessed = true;
3882                 }
3883                 else
3884                 {
3885                     //
3886                     // SW policy change: If the BIOS max link config isn't same as max of panel, mark DPlib for re-link
3887                     // assessment by marking linkGuessed as true.
3888                     // Re-link training is prefereable over glitchless and booting at low resolutions
3889                     //
3890                     if (laneCount != highestAssessedLC.lanes || linkRate != highestAssessedLC.peakRate)
3891                     {
3892                         linkGuessed = true;
3893                     }
3894                     else
3895                     {
3896                         linkGuessed = false;
3897                         // Update software state with latest link status info
3898                         hal->setDirtyLinkStatus(true);
3899                         hal->refreshLinkStatus();
3900                     }
3901                 }
3902             }
3903             else if (!linkGuessed)
3904             {
3905                 // We failed to query max link config from UEFI. Mark link as guessed.
3906                 DP_LOG(("DP CONN> Failed to query max link config from UEFI."));
3907                 linkGuessed = true;
3908             }
3909 
3910             if (!linkGuessed)
3911             {
3912                 // Update SW state with UEFI provided max link config
3913                 highestAssessedLC = LinkConfiguration (&this->linkPolicy,
3914                                                        laneCount, linkRate,
3915                                                        this->hal->getEnhancedFraming(),
3916                                                        linkUseMultistream());
3917 
3918                 // Get the currently applied linkconfig and update SW state
3919                 getCurrentLinkConfig(laneCount, linkRate);
3920 
3921                 activeLinkConfig = LinkConfiguration (&this->linkPolicy,
3922                                                       laneCount, linkRate,
3923                                                       this->hal->getEnhancedFraming(),
3924                                                       linkUseMultistream());
3925             }
3926         }
3927         else
3928         {
3929             linkGuessed = true;
3930         }
3931 
3932         return;
3933     }
3934 
3935     if (linkAwaitingTransition)
3936     {
3937         if (activeGroups.isEmpty())
3938         {
3939             linkState = hal->getSupportsMultistream() ?
3940                 DP_TRANSPORT_MODE_MULTI_STREAM : DP_TRANSPORT_MODE_SINGLE_STREAM;
3941             linkAwaitingTransition = false;
3942             bLinkStateToggle = true;
3943         }
3944         else
3945         {
3946             //
3947             // If modesetOrderMitigation isn't on, we need to reassess
3948             // immediately. This is because we will report the connects at the
3949             // same time as the disconnects.  IMP Query can be done immediately
3950             // on connects. On the other hand if modeset order mitigation is
3951             // off - all attached devices are going to be reported as
3952             // disconnected and might as well use the old configuration.
3953             //
3954             if (this->policyModesetOrderMitigation && this->modesetOrderMitigation)
3955                 return;
3956         }
3957     }
3958     else
3959     {
3960         if (hal->isDpcdOffline())
3961             linkState = DP_TRANSPORT_MODE_INIT;
3962     }
3963 
3964     // linkState might be different from beginning, update _maxLinkConfig to keep it in sync.
3965     _maxLinkConfig.multistream = this->linkUseMultistream();
3966 
3967     //
3968     // Bug 1545352: This is done to avoid shutting down a display for freeing up a SOR for LT,
3969     // when no SOR is assigned properly to the connector. It can happen when more
3970     // than max supported number of display(s) is connected.
3971     // It came as a requirement from some clients to avoid glitches when shutting
3972     // down a display to make SOR availability for those monitors.
3973     //
3974     if (main->getSorIndex() == DP_INVALID_SOR_INDEX)
3975     {
3976         highestAssessedLC = _maxLinkConfig;
3977         linkGuessed = true;
3978         return;
3979     }
3980 
3981     LinkConfiguration lConfig = _maxLinkConfig;
3982 
3983     LinkConfiguration preFlushModeActiveLinkConfig = activeLinkConfig;
3984 
3985     if (main->isInternalPanelDynamicMuxCapable())
3986     {
3987         // Skip Link assessment for Dynamic MUX capable Internal Panel
3988         if ((activeLinkConfig.lanes == lConfig.lanes) &&
3989             (activeLinkConfig.peakRate == lConfig.peakRate) &&
3990             (!isLinkInD3()) && (!isLinkLost()))
3991         {
3992             linkGuessed = false;
3993             return;
3994         }
3995     }
3996 
3997     //
3998     //  Disconnect heads
3999     //
4000     bool bIsFlushModeEnabled = enableFlush();
4001 
4002     if (!bIsFlushModeEnabled)
4003     {
4004         goto done;
4005     }
4006 
4007     //
4008     // if dpcd is offline; avoid assessing. Just consider max.
4009     // keep lowering lane/rate config till train succeeds
4010     //
4011     hal->updateDPCDOffline();
4012     if (!hal->isDpcdOffline())
4013     {
4014         if (!train(lConfig, false /* do not force LT */))
4015         {
4016             //
4017             // Note that now train() handles fallback, activeLinkConfig
4018             // has the max link config that was assessed.
4019             //
4020             lConfig = activeLinkConfig;
4021         }
4022 
4023         if (!this->linkUseMultistream() && this->policyAssessLinkSafely)
4024         {
4025             GroupImpl * groupAttached = this->getActiveGroupForSST();
4026 
4027             if (groupAttached && groupAttached->isHeadAttached() &&
4028                 !willLinkSupportModeSST(lConfig, groupAttached->lastModesetInfo))
4029             {
4030                 DP_ASSERT(0 && "DP> Maximum assessed link configuration is not capable to driver existing raster!");
4031 
4032                 train(preFlushModeActiveLinkConfig, true);
4033                 linkGuessed = true;
4034                 goto done;
4035             }
4036         }
4037     }
4038 
4039     highestAssessedLC = lConfig;
4040 
4041     // It is critical that this restore the original (desired) configuration
4042     trainLinkOptimized(lConfig);
4043 
4044     linkGuessed = false;
4045 
4046 done:
4047 
4048     NV_DPTRACE_INFO(LINK_ASSESSMENT, highestAssessedLC.peakRate, highestAssessedLC.lanes);
4049 
4050     if (bIsFlushModeEnabled)
4051     {
4052         disableFlush();
4053     }
4054 
4055     if (bLinkStateToggle)
4056     {
4057         DP_LOG(("DP> Link state toggled, reading DSC caps now"));
4058         // Read panel DSC support only if GPU supports DSC
4059         bool bGpuDscSupported;
4060         main->getDscCaps(&bGpuDscSupported);
4061         if (bGpuDscSupported)
4062         {
4063             for (Device * i = enumDevices(0); i; i=enumDevices(i))
4064             {
4065                 DeviceImpl * dev = (DeviceImpl *)i;
4066                 if(dev->getDSCSupport())
4067                 {
4068                     // Read and parse DSC caps only if panel and GPU supports DSC
4069                     dev->readAndParseDSCCaps();
4070                 }
4071                 if (!(dev->processedEdid.WARFlags.bIgnoreDscCap))
4072                 {
4073                     dev->setDscDecompressionDevice(this->bDscCapBasedOnParent);
4074                 }
4075             }
4076         }
4077     }
4078 }
4079 
4080 bool ConnectorImpl::handleCPIRQ()
4081 {
4082     NvU8        bStatus;
4083     HDCPState   hdcpState = {0};
4084 
4085     if (!isLinkActive())
4086     {
4087         DP_LOG(("DP> CP_IRQ: Ignored with link down"));
4088         return true;
4089     }
4090 
4091     main->configureHDCPGetHDCPState(hdcpState);
4092     if (hal->getRxStatus(hdcpState, &bStatus))
4093     {
4094         NvBool bReAuthReq = NV_FALSE;
4095         NvBool bRxIDMsgPending = NV_FALSE;
4096         DP_LOG(("DP> CP_IRQ HDCP ver:%s RxStatus:0x%2x HDCP Authenticated:%s Encryption:%s",
4097                 hdcpState.HDCP_State_22_Capable ? "2.2" : "1.x",
4098                 bStatus,
4099                 hdcpState.HDCP_State_Authenticated ? "YES" : "NO",
4100                 hdcpState.HDCP_State_Encryption ? "ON" : "OFF"));
4101 
4102         // Check device if HDCP2.2 capable instead actual encryption status,
4103         if (hdcpState.HDCP_State_22_Capable)
4104         {
4105             if (FLD_TEST_DRF(_DPCD, _HDCP22_RX_STATUS, _REAUTH_REQUEST, _YES, bStatus) ||
4106                 FLD_TEST_DRF(_DPCD, _HDCP22_RX_STATUS, _LINK_INTEGRITY_FAILURE, _YES, bStatus))
4107             {
4108                 if (this->linkUseMultistream())
4109                 {
4110                     //
4111                     // Bug 2860192: Some MST hub throw integrity failure before source trigger
4112                     // authentication. This may be stale data since Branch is
4113                     // doing protocol translation(DP to HDMI), and cannot treat
4114                     // as sink's fault.
4115                     // For MST, we would not lose anything here by ignoring either
4116                     // CP_Irq event since Auth never started after HPD high or
4117                     // LinkTraining start.
4118                     //
4119                     if (isHDCPAuthTriggered)
4120                     {
4121                         bReAuthReq = NV_TRUE;
4122                     }
4123                     else
4124                     {
4125                         DP_LOG(("DP>Ignore integrity failure or ReAuth in transition or before AKE_INIT."));
4126                     }
4127                 }
4128                 else
4129                 {
4130                     bReAuthReq = NV_TRUE;
4131                 }
4132             }
4133 
4134             if (FLD_TEST_DRF(_DPCD, _HDCP22_RX_STATUS, _READY, _YES, bStatus))
4135             {
4136                 bRxIDMsgPending = NV_TRUE;
4137             }
4138         }
4139         else
4140         {
4141             if (FLD_TEST_DRF(_DPCD, _HDCP_BSTATUS, _REAUTHENTICATION_REQUESET, _TRUE, bStatus) ||
4142                 FLD_TEST_DRF(_DPCD, _HDCP_BSTATUS, _LINK_INTEGRITY_FAILURE, _TRUE, bStatus))
4143             {
4144                 bReAuthReq = NV_TRUE;
4145             }
4146         }
4147 
4148         if (bReAuthReq || bRxIDMsgPending)
4149         {
4150             DP_LOG(("DP> CP_IRQ: REAUTHENTICATION/RXIDPENDING REQUEST"));
4151 
4152             if (bReAuthReq)
4153             {
4154                 authRetries = 0;
4155             }
4156 
4157             if (!this->linkUseMultistream())
4158             {
4159                 // Get primary connector when multi-stream SST deployed.
4160                 GroupImpl *pGroupAttached = getActiveGroupForSST();
4161                 ConnectorImpl *sstPrim = this;
4162 
4163                 if (pGroupAttached &&
4164                     (pGroupAttached->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST) &&
4165                     (pGroupAttached->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY))
4166                 {
4167                     DP_ASSERT(this->pCoupledConnector);
4168                     sstPrim = this->pCoupledConnector;
4169                 }
4170 
4171                 sstPrim->main->configureHDCPRenegotiate(HDCP_DUMMY_CN,
4172                                                         HDCP_DUMMY_CKSV,
4173                                                         !!bReAuthReq,
4174                                                         !!bRxIDMsgPending);
4175                 sstPrim->main->configureHDCPGetHDCPState(hdcpState);
4176                 isHDCPAuthOn = hdcpState.HDCP_State_Authenticated;
4177             }
4178         }
4179 
4180         return true;
4181     }
4182     else
4183     {
4184         DP_LOG(("DP> CP_IRQ: RxStatus Read failed."));
4185         return false;
4186     }
4187 }
4188 
4189 void ConnectorImpl::handleSSC()
4190 {
4191 }
4192 
4193 void ConnectorImpl::handleHdmiLinkStatusChanged()
4194 {
4195     bool    bLinkActive;
4196     NvU32   newFrlRate;
4197     // Check Link status
4198     if (!hal->queryHdmiLinkStatus(&bLinkActive, NULL))
4199     {
4200         return;
4201     }
4202     if (!bLinkActive)
4203     {
4204         newFrlRate = hal->restorePCONFrlLink(activePConLinkControl.frlHdmiBwMask,
4205                                              activePConLinkControl.flags.bExtendedLTMode,
4206                                              activePConLinkControl.flags.bConcurrentMode);
4207 
4208         if (newFrlRate != activePConLinkControl.result.trainedFrlBwMask)
4209         {
4210             activePConLinkControl.result.trainedFrlBwMask = newFrlRate;
4211             activePConLinkControl.result.maxFrlBwTrained  = getMaxFrlBwFromMask(newFrlRate);
4212             for (Device *i = enumDevices(0); i; i = enumDevices(i))
4213             {
4214                 DeviceImpl *dev = (DeviceImpl *)i;
4215                 if ((dev->activeGroup != NULL) && (dev->plugged))
4216                 {
4217                     sink->bandwidthChangeNotification(dev, false);
4218                 }
4219             }
4220         }
4221     }
4222 }
4223 
4224 void ConnectorImpl::handleMCCSIRQ()
4225 {
4226     for (Device *i = enumDevices(0); i; i = enumDevices(i))
4227     {
4228         DeviceImpl *dev = (DeviceImpl *)i;
4229         if ((dev->activeGroup != NULL) && (dev->plugged))
4230         {
4231             sink->notifyMCCSEvent(dev);
4232         }
4233     }
4234 }
4235 
4236 void ConnectorImpl::handlePanelReplayError()
4237 {
4238     hal->readPanelReplayError();
4239 }
4240 
4241 //
4242 // Checks if the link is still trained.
4243 // Note that these hal registers are ONLY re-read in response to an IRQ.
4244 // Calling this function returns the information from the last interrupt.
4245 //
4246 bool ConnectorImpl::isLinkLost()
4247 {
4248     if (isLinkActive())
4249     {
4250         // Bug 200320196: Add DPCD offline check to avoid link-train in unplugged state.
4251         if (!hal->isDpcdOffline())
4252         {
4253             unsigned laneCount;
4254             NvU64 linkRate;
4255             getCurrentLinkConfig(laneCount, linkRate);
4256             //
4257             // Check SW lane count in RM in case it's disabled beyond DPLib.
4258             // Bug 1933751/2897747
4259             //
4260             if (laneCount == laneCount_0)
4261                 return true;
4262         }
4263 
4264         // update the sw cache if required
4265         hal->refreshLinkStatus();
4266         if (!hal->getInterlaneAlignDone())
4267             return true;
4268 
4269         for (unsigned i = 0; i < activeLinkConfig.lanes; i++)
4270         {
4271             if (!hal->getLaneStatusSymbolLock(i))
4272                 return true;
4273             if (!hal->getLaneStatusClockRecoveryDone(i))
4274                 return true;
4275         }
4276 
4277         if (!hal->getInterlaneAlignDone())
4278             return true;
4279     }
4280     return false;
4281 }
4282 
4283 bool ConnectorImpl::isLinkActive()
4284 {
4285     return (activeLinkConfig.isValid());
4286 }
4287 
4288 bool ConnectorImpl::isLinkInD3()
4289 {
4290     return (hal->getPowerState() == PowerStateD3);
4291 }
4292 
4293 bool ConnectorImpl::trainLinkOptimizedSingleHeadMultipleSST(GroupImpl *pGroupAttached)
4294 {
4295     if (!pGroupAttached)
4296     {
4297         DP_LOG(("DP-CONN> 2-sst group not valid"));
4298         return false;
4299     }
4300 
4301     if (preferredLinkConfig.isValid())
4302     {
4303         ConnectorImpl *pSecConImpl = this->pCoupledConnector;
4304         if (pSecConImpl->preferredLinkConfig.isValid() &&
4305             (preferredLinkConfig.lanes == laneCount_4) && (pSecConImpl->preferredLinkConfig.lanes == laneCount_4) &&
4306             (preferredLinkConfig.peakRate == pSecConImpl->preferredLinkConfig.peakRate))
4307         {
4308             if (willLinkSupportModeSST(preferredLinkConfig, pGroupAttached->lastModesetInfo))
4309             {
4310                 if (pGroupAttached->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY)
4311                 {
4312                     if (!this->enableFlush())
4313                         return false;
4314                 }
4315                 preferredLinkConfig.policy.setSkipFallBack(true);
4316                 if (!train(preferredLinkConfig, false))
4317                 {
4318                     DP_LOG(("DP-CONN> Unable to set preferred linkconfig on 2-SST display"));
4319                     return false;
4320                 }
4321                 if (pGroupAttached->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY)
4322                 {
4323                     this->disableFlush();
4324                 }
4325                 return true;
4326             }
4327             else
4328             {
4329                 DP_LOG(("DP-CONN> Invalid 2-SST Preferred link configuration"));
4330                 return false;
4331             }
4332         }
4333     }
4334 
4335     if (pGroupAttached->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST)
4336     {
4337         if (pGroupAttached->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY)
4338         {
4339             if (this->pCoupledConnector->oneHeadSSTSecPrefLnkCfg.isValid())
4340             {
4341                 bool trainDone = false;
4342                 this->pCoupledConnector->oneHeadSSTSecPrefLnkCfg.policy.setSkipFallBack(true);
4343                 if (!train(this->pCoupledConnector->oneHeadSSTSecPrefLnkCfg, false))
4344                 {
4345                     DP_LOG(("DP-CONN> Unable set the primary configuration on secondary display"));
4346                     trainDone = false;
4347                 }
4348                 else
4349                 {
4350                     trainDone =  true;
4351                 }
4352                 this->disableFlush();
4353                 return trainDone;
4354             }
4355         }
4356 
4357     }
4358 
4359     // Order for 2-SST link training and must be with 4 lanes
4360     unsigned linkRateList[] = {RBR, HBR, HBR2, HBR3};
4361     NvU8     linkRateCount = sizeof(linkRateList) / sizeof(unsigned);
4362 
4363     for (NvU8 i = 0; i < linkRateCount; i++)
4364     {
4365         LinkConfiguration linkCfg = LinkConfiguration(&this->linkPolicy,
4366                                         laneCount_4, linkRateList[i],
4367                                         hal->getEnhancedFraming(), false);
4368         linkCfg.policy.setSkipFallBack(true);
4369         if (willLinkSupportModeSST(linkCfg, pGroupAttached->lastModesetInfo))
4370         {
4371             if (!this->enableFlush())
4372                 return false;
4373             if (!train(linkCfg, false))
4374             {
4375                 if (i == linkRateCount - 1)
4376                 {
4377                     // Re-train max link config
4378                     linkCfg = getMaxLinkConfig();
4379                     linkCfg.policy.setSkipFallBack(true);
4380                     if (!train(linkCfg, false))
4381                     {
4382                         DP_ASSERT(0 && "DPCONN> 2-SST setting max link configuration failed ");
4383                         break;
4384                     }
4385                 }
4386             }
4387             else
4388             {
4389                 oneHeadSSTSecPrefLnkCfg = linkCfg;
4390                 break;
4391             }
4392         }
4393     }
4394 
4395     return true;
4396 }
4397 
4398 bool ConnectorImpl::isNoActiveStreamAndPowerdown()
4399 {
4400     if (activeGroups.isEmpty())
4401     {
4402         bool bKeepMSTLinkAlive = (this->bKeepLinkAliveMST && activeLinkConfig.multistream);
4403         bool bKeepSSTLinkAlive = (this->bKeepLinkAliveSST && !activeLinkConfig.multistream);
4404         //
4405         // Power saving unless:
4406         // - Setting fake flag as true to prevent panel power down here.
4407         // - Regkey sets to keep link alive for MST and it's in MST.
4408         // - Regkey sets to keep link alive for SST and it's in SST.
4409         // - bKeepOptLinkAlive is set to true - to avoid link retraining.
4410         // - Device discovery processing that processNewDevice has HDCP probe.
4411         // - Pending remote HDCP detection messages - prevent power down to access HDCP DCPD regs.
4412         // - Keep link active with compliance device as we always do
4413         //
4414         if ((!bKeepMSTLinkAlive) &&
4415             (!bKeepSSTLinkAlive) &&
4416             (!bKeepOptLinkAlive) &&
4417             (!bKeepLinkAliveForPCON) &&
4418             (!bIsDiscoveryDetectActive) &&
4419             (pendingRemoteHdcpDetections == 0) &&
4420             (!main->isInternalPanelDynamicMuxCapable()))
4421         {
4422             powerdownLink();
4423 
4424             // Sharp panel for HP Valor QHD+ needs 50 ms after D3
4425             if (bDelayAfterD3)
4426             {
4427                 timer->sleep(50);
4428             }
4429         }
4430 
4431         return true;
4432     }
4433 
4434     return false;
4435 }
4436 
4437 bool ConnectorImpl::trainLinkOptimized(LinkConfiguration lConfig)
4438 {
4439     LinkConfiguration lowestSelected;         // initializes to 0
4440     bool bSkipLowestConfigCheck  = false;     // Force highestLink config in SST
4441     bool bSkipRedundantLt        = false;     // Skip redundant LT
4442     bool bEnteredFlushMode       = false;
4443     bool bLinkTrainingSuccessful = true;      // status indicating if link training actually succeeded
4444                                               // forced link training is considered a failure
4445     bool bTwoHeadOneOrLinkRetrain = false;    // force link re-train if any attached
4446                                               // groups are in 2Head1OR mode.
4447 
4448     // Power off the link if no stream are active
4449     if (isNoActiveStreamAndPowerdown())
4450     {
4451         return true;
4452     }
4453 
4454     //
4455     //   Split policy.
4456     //    If we're multistream we *always pick the highest link configuration available
4457     //           - we don't want to interrupt existing panels to light up new ones
4458     //    If we're singlestream we always pick the lowest power configurations
4459     //           - there can't be multiple streams, so the previous limitation doesn't apply
4460     //
4461 
4462     //
4463     // Find the active group(s)
4464     //
4465     GroupImpl * groupAttached = 0;
4466     for (ListElement * e = activeGroups.begin(); e != activeGroups.end(); e = e->next)
4467     {
4468         DP_ASSERT(bIsUefiSystem || linkUseMultistream() || (!groupAttached && "Multiple attached heads"));
4469         groupAttached = (GroupImpl * )e;
4470 
4471         if ((groupAttached->dscModeRequest == DSC_DUAL) && (groupAttached->dscModeActive != DSC_DUAL))
4472         {
4473             //
4474             // If current modeset group requires 2Head1OR and
4475             //  - group is not active yet (first modeset on the group)
4476             //  - group is active but not in 2Head1OR mode (last modeset on the group did not require 2Head1OR)
4477             // then re-train the link
4478             // This is because for 2Head1OR mode, we need to set some LT parametes for slave SOR after
4479             // successful LT on primary SOR without which 2Head1OR modeset will lead to HW hang.
4480             //
4481             bTwoHeadOneOrLinkRetrain = true;
4482             break;
4483         }
4484     }
4485 
4486     lowestSelected = getMaxLinkConfig();
4487 
4488     if (!activeLinkConfig.multistream)
4489     {
4490         if (groupAttached &&
4491             groupAttached->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST)
4492         {
4493             return trainLinkOptimizedSingleHeadMultipleSST(groupAttached);
4494         }
4495 
4496         if (preferredLinkConfig.isValid())
4497         {
4498             if (activeLinkConfig != preferredLinkConfig)
4499             {
4500                 // if a tool has requested a preferred link config; check if its possible; and train to it.
4501                 // else choose the normal path
4502                 if (groupAttached &&
4503                     willLinkSupportModeSST(preferredLinkConfig, groupAttached->lastModesetInfo))
4504                 {
4505                     if (!this->enableFlush())
4506                         return false;
4507                     if (!train(preferredLinkConfig, false))
4508                     {
4509                         DP_LOG(("DP-CONN> Preferred linkconfig could not be applied. Forcing on gpu side."));
4510                         train(preferredLinkConfig, true);
4511                     }
4512                     this->disableFlush();
4513                     return true;
4514                 }
4515                 else
4516                 {
4517                     DP_LOG(("DP-CONN> Preferred linkconfig does not support the mode"));
4518                     return false;
4519                 }
4520             }
4521             else
4522             {
4523                 // We are already at preferred. Nothing to do here. Return.
4524                 return true;
4525             }
4526         }
4527 
4528         //
4529         // This is required for making certain panels to work by training them in
4530         // highest linkConfig in SST mode.
4531         //
4532         for (Device * i = enumDevices(0); i; i=enumDevices(i))
4533         {
4534             DeviceImpl * dev = (DeviceImpl *)i;
4535             if (dev->forceMaxLinkConfig())
4536             {
4537                 bSkipLowestConfigCheck = true;
4538             }
4539             if (dev->skipRedundantLt())
4540             {
4541                 bSkipRedundantLt = true;
4542             }
4543         }
4544 
4545         if (bPConConnected)
4546         {
4547             // When PCON is connected, always LT to max to avoid LT.
4548             bSkipLowestConfigCheck = true;
4549         }
4550 
4551         // If the flag is set, simply neglect downgrading to lowest possible linkConfig
4552         if (!bSkipLowestConfigCheck)
4553         {
4554             lConfig = lowestSelected;
4555 
4556             if (groupAttached)
4557             {
4558                 lConfig.enableFEC(this->bFECEnable);
4559                 // Find lowest link configuration supporting the mode
4560                 getValidLowestLinkConfig(lConfig, lowestSelected, groupAttached->lastModesetInfo);
4561             }
4562         }
4563 
4564         if (lowestSelected.isValid())
4565         {
4566             //
4567             // Check if we are already trained to the desired link config?
4568             // Make sure requested FEC state matches with the current FEC state of link.
4569             // If 2Head1OR mode is requested, retrain if group is not active or
4570             // last modeset on active group was not in 2Head1OR mode.
4571             // bTwoHeadOneOrLinkRetrain tracks this requirement.
4572             //
4573 
4574             //
4575             // Set linkStatus to be dirty so that when isLinkLost() calls
4576             // refreshLinkStatus() it will get real time status. This is to
4577             // fix an issue that when UEFI-to-Driver transition, LTTPR is not
4578             // link trainined but will be link trainined by RM.
4579             //
4580             hal->setDirtyLinkStatus(true);
4581             if ((activeLinkConfig == lowestSelected) &&
4582                 (!isLinkInD3()) &&
4583                 (!isLinkLost()) &&
4584                 (this->bFECEnable == activeLinkConfig.bEnableFEC) &&
4585                 !bTwoHeadOneOrLinkRetrain)
4586             {
4587                 if (bSkipRedundantLt || main->isInternalPanelDynamicMuxCapable())
4588                 {
4589                     // Skip LT if the links are already trained to desired config.
4590                     DP_LOG(("DP-CONN> Skipping redundant LT."));
4591                     return true;
4592                 }
4593                 else
4594                 {
4595                     // Make sure link status is still good.
4596                     if (activeLinkConfig.lanes && hal->isLinkStatusValid(activeLinkConfig.lanes))
4597                     {
4598                         // Pass on a flag to RM ctrl call to skip LT at RM level.
4599                         DP_LOG(("DP-CONN> Skipping redundant LT from RM."));
4600                         bSkipLt = true;
4601                     }
4602                 }
4603             }
4604             else
4605             {
4606                 bSkipLt = false;
4607             }
4608 
4609             if (groupAttached && groupAttached->isHeadAttached())
4610             {
4611                 // Enter flush mode/detach head before LT
4612                 if (!bSkipLt)
4613                 {
4614                     if (!(bEnteredFlushMode = this->enableFlush()))
4615                         return false;
4616                 }
4617             }
4618 
4619             bLinkTrainingSuccessful = train(lowestSelected, false);
4620             //
4621             // If LT failed, check if skipLT was marked. If so, clear the flag and
4622             // enable flush mode if required (headattached) and try real LT once.
4623             //
4624             if (!bLinkTrainingSuccessful && bSkipLt)
4625             {
4626                 bSkipLt = false;
4627                 if (groupAttached && groupAttached->isHeadAttached())
4628                 {
4629                     if (!(bEnteredFlushMode = this->enableFlush()))
4630                         return false;
4631                 }
4632                 bLinkTrainingSuccessful = train(lowestSelected, false);
4633             }
4634             if (!bLinkTrainingSuccessful)
4635             {
4636                 // Try fall back to max link config and if that fails try original assessed link configuration
4637                 if (!train(getMaxLinkConfig(), false))
4638                 {
4639                     if (!willLinkSupportModeSST(activeLinkConfig, groupAttached->lastModesetInfo))
4640                     {
4641                         train(lowestSelected, true);
4642 
4643                         // Mark link training as failed since we forced it
4644                         bLinkTrainingSuccessful = false;
4645                     }
4646                 }
4647             }
4648         }
4649         else
4650         {
4651             if (groupAttached && groupAttached->isHeadAttached())
4652             {
4653                 if (!(bEnteredFlushMode = this->enableFlush()))
4654                     return false;
4655             }
4656 
4657             // Mode wasn't possible at any assessed configuration.
4658             train(getMaxLinkConfig(), true);
4659 
4660             // Mark link training as failed since we forced it
4661             bLinkTrainingSuccessful = false;
4662         }
4663 
4664         lConfig = activeLinkConfig;
4665 
4666         if (bEnteredFlushMode)
4667         {
4668             this->disableFlush();
4669         }
4670 
4671         // In case this was set, we should reset it to prevent skipping LT next time.
4672         bSkipLt = false;
4673     }
4674     else
4675     {
4676         bool bRetrainToEnsureLinkStatus;
4677 
4678         //
4679         //     Multistream:
4680         //          If we can't restore all streams after a link train - we need to make sure that
4681         //          we set RG_DIV to "slow down" the effective pclk for that head.  RG_DIV does give
4682         //          us enough room to account for both the HBR2->RBR drop and the 4->1 drop.
4683         //          This should allow us to keep the link up and operating at a sane frequency.
4684         //          .. thus we'll allow training at any frequency ..
4685         //
4686 
4687         // for MST; the setPreferred calls assessLink directly.
4688         if (preferredLinkConfig.isValid() && (activeLinkConfig != preferredLinkConfig))
4689         {
4690             if (!train(preferredLinkConfig, false))
4691             {
4692                 DP_LOG(("DP-CONN> Preferred linkconfig could not be applied. Forcing on gpu side."));
4693                 train(preferredLinkConfig, true);
4694             }
4695             return true;
4696         }
4697 
4698         //
4699         // Make sure link is physically active and healthy, otherwise re-train.
4700         // Make sure requested FEC state matches with the current FEC state of link.
4701         // If 2Head1OR mode is requested, retrain if group is not active or last modeset on active group
4702         // was not in 2Head1OR mode. bTwoHeadOneOrLinkRetrain tracks this requirement.
4703         //
4704         bRetrainToEnsureLinkStatus = (isLinkActive() && isLinkInD3()) ||
4705                                      isLinkLost() ||
4706                                      (activeLinkConfig.bEnableFEC != this->bFECEnable) ||
4707                                      bTwoHeadOneOrLinkRetrain;
4708 
4709         if (bRetrainToEnsureLinkStatus || (!isLinkActive()))
4710         {
4711             //
4712             // Train to the highestAssesed link config for MST cases to avoid redundant
4713             // fallback. There is no point of trying to link train at highest link config
4714             // when it failed during the assessment.
4715             // train() handles fallback now. So we don't need to step down when LT fails.
4716             //
4717             LinkConfiguration desired = highestAssessedLC;
4718 
4719             NvU8 retries = DP_LT_MAX_FOR_MST_MAX_RETRIES;
4720 
4721             desired.enableFEC(this->bFECEnable);
4722 
4723             if (bRetrainToEnsureLinkStatus)
4724             {
4725                 bEnteredFlushMode = enableFlush();
4726             }
4727 
4728             //
4729             // In some cases, the FEC isn't enabled and link is not lost (e.g. DP_KEEP_OPT_LINK_ALIVE = 1),
4730             // but we're going to enable DSC. We need to update bSkipLt for retraining the link with FEC.
4731             // As the bSkipLt was set to true prviously while link is not lost.
4732             //
4733             if (activeLinkConfig.bEnableFEC != this->bFECEnable)
4734             {
4735                 bSkipLt = false;
4736             }
4737 
4738             train(desired, false);
4739             if (!activeLinkConfig.isValid())
4740             {
4741                 DP_LOG(("DPCONN> Unable to train link (at all).  Forcing training (picture won't show up)"));
4742                 train(getMaxLinkConfig(), true);
4743 
4744                 // Mark link training as failed since we forced it
4745                 bLinkTrainingSuccessful = false;
4746             }
4747 
4748             //
4749             // Bug 2354318: On some MST branches, we might see a problem that LT failed during
4750             // assessLink(), but somehow works later. In this case, we should not
4751             // retry since highestAssessedLC is not a valid comparison now.
4752             //
4753             if (highestAssessedLC.isValid())
4754             {
4755                 while ((highestAssessedLC != activeLinkConfig) && retries > 0)
4756                 {
4757                     // Give it a few more chances.
4758                     train(desired, false);
4759                     retries--;
4760                 };
4761             }
4762 
4763             lConfig = activeLinkConfig;
4764 
4765             if (bEnteredFlushMode)
4766             {
4767                 disableFlush();
4768             }
4769         }
4770     }
4771 
4772     return (bLinkTrainingSuccessful && lConfig.isValid());
4773 }
4774 
4775 bool ConnectorImpl::getValidLowestLinkConfig
4776 (
4777     LinkConfiguration &lConfig,
4778     LinkConfiguration &lowestSelected,
4779     ModesetInfo modesetInfo
4780 )
4781 {
4782     bool bIsModeSupported = false;
4783     unsigned i;
4784     LinkConfiguration selectedConfig;
4785 
4786     for (i = 0; i < numPossibleLnkCfg; i++)
4787     {
4788         if ((this->allPossibleLinkCfgs[i].lanes > lConfig.lanes) ||
4789             (this->allPossibleLinkCfgs[i].peakRate > lConfig.peakRate))
4790         {
4791             continue;
4792         }
4793 
4794         // Update enhancedFraming for target config
4795         this->allPossibleLinkCfgs[i].enhancedFraming = lConfig.enhancedFraming;
4796 
4797         selectedConfig = this->allPossibleLinkCfgs[i];
4798 
4799         selectedConfig.enableFEC(lConfig.bEnableFEC);
4800 
4801         if (willLinkSupportModeSST(selectedConfig, modesetInfo))
4802         {
4803             bIsModeSupported = true;
4804             break;
4805         }
4806     }
4807 
4808     if (bIsModeSupported)
4809     {
4810         lowestSelected = selectedConfig;
4811     }
4812     else
4813     {
4814         // Invalidate link config if mode is not possible at all
4815         lowestSelected.lanes = 0;
4816     }
4817 
4818     return bIsModeSupported;
4819 }
4820 
4821 bool ConnectorImpl::postLTAdjustment(const LinkConfiguration & lConfig, bool force)
4822 {
4823     NvU8 lastVoltageSwingLane[DP_MAX_LANES]     = {0};
4824     NvU8 lastPreemphasisLane[DP_MAX_LANES]      = {0};
4825     NvU8 lastTrainingScoreLane[DP_MAX_LANES]    = {0};
4826     NvU8 lastPostCursor[DP_MAX_LANES]           = {0};
4827     NvU8 currVoltageSwingLane[DP_MAX_LANES]     = {0};
4828     NvU8 currPreemphasisLane[DP_MAX_LANES]      = {0};
4829     NvU8 currTrainingScoreLane[DP_MAX_LANES]    = {0};
4830     NvU8 currPostCursor[DP_MAX_LANES]           = {0};
4831     NvU32 updatedLaneSettings[DP_MAX_LANES]     = {0};
4832     NvU8 adjReqCount = 0;
4833     NvU64 startTime;
4834     LinkConfiguration linkConfig = lConfig;
4835 
4836     // Cache Voltage Swing and Preemphasis value just after Link training
4837     if (!hal->readTraining(lastVoltageSwingLane,
4838                            lastPreemphasisLane,
4839                            lastTrainingScoreLane,
4840                            lastPostCursor,
4841                            (NvU8)activeLinkConfig.lanes))
4842     {
4843         DP_LOG(("DPCONN> Post Link Training : Unable to read current training values"));
4844     }
4845 
4846     if (hal->getTrainingPatternSelect() != TRAINING_DISABLED)
4847     {
4848         DP_LOG(("DPCONN> Post Link Training : Training pattern is not disabled."));
4849     }
4850 
4851     //
4852     // We have cleared DPCD 102h
4853     // Now hardware will automatically send the idle pattern
4854     //
4855     startTime = timer->getTimeUs();
4856 
4857     do
4858     {
4859         if (!hal->getIsPostLtAdjRequestInProgress())
4860         {
4861             // Clear POST_LT_ADJ_REQ_GRANTED bit and start normal AV transmission
4862             hal->setPostLtAdjustRequestGranted(false);
4863             return true;
4864         }
4865 
4866         // Wait for 2ms
4867         Timeout timeout(timer, 2);
4868 
4869         // check if DPCD 00206h~00207h change has reached to ADJ_REQ_LIMIT
4870         if (adjReqCount > DP_POST_LT_ADJ_REQ_LIMIT)
4871         {
4872             // Clear POST_LT_ADJ_REQ_GRANTED bit and start normal AV transmission
4873             hal->setPostLtAdjustRequestGranted(false);
4874             return true;
4875         }
4876 
4877         if (!hal->readTraining(currVoltageSwingLane,
4878                                currPreemphasisLane,
4879                                currTrainingScoreLane,
4880                                currPostCursor,
4881                                (NvU8)activeLinkConfig.lanes))
4882         {
4883             DP_LOG(("DPCONN> Post Link Training : Unable to read current training values"));
4884         }
4885         else
4886         {
4887             if (!hal->isLaneSettingsChanged(lastVoltageSwingLane,
4888                                             currVoltageSwingLane,
4889                                             lastPreemphasisLane,
4890                                             currPreemphasisLane,
4891                                             (NvU8)activeLinkConfig.lanes))
4892             {
4893                 // Check if we have exceeded DP_POST_LT_ADJ_REQ_TIMER (200 ms)
4894                 if ((timer->getTimeUs() - startTime) > DP_POST_LT_ADJ_REQ_TIMER)
4895                 {
4896                     DP_LOG(("DPCONN> Post Link Training : DP_POST_LT_ADJ_REQ_TIMER is timed out."));
4897                     // Clear POST_LT_ADJ_REQ_GRANTED bit and start normal AV transmission
4898                     hal->setPostLtAdjustRequestGranted(false);
4899                     return true;
4900                 }
4901             }
4902             else
4903             {
4904                 adjReqCount++;
4905 
4906                 // Clear ADJ_REQ_TIMER
4907                 startTime = timer->getTimeUs();
4908 
4909                 // Change RX drive settings according to DPCD 00206h & 00207h
4910                 if (!hal->setTrainingMultiLaneSet((NvU8)activeLinkConfig.lanes,
4911                                                   currVoltageSwingLane,
4912                                                   currPreemphasisLane))
4913                 {
4914                     DP_LOG(("DPCONN> Post Link Training : Failed to set RX drive setting according to DPCD 00206h & 00207h."));
4915                 }
4916 
4917                 // Populate updated lane settings for currently active lanes
4918                 populateUpdatedLaneSettings(currVoltageSwingLane, currPreemphasisLane, updatedLaneSettings);
4919 
4920                 // Change TX drive settings according to DPCD 00206h & 00207h
4921                 if (!setLaneConfig(activeLinkConfig.lanes, updatedLaneSettings))
4922                 {
4923                     DP_LOG(("DPCONN> Post Link Training : Failed to set TX drive setting according to DPCD 00206h & 00207h."));
4924                 }
4925 
4926                 // Update last Voltage Swing and Preemphasis values
4927                 if (!hal->readTraining(lastVoltageSwingLane,
4928                                        lastPreemphasisLane,
4929                                        lastTrainingScoreLane,
4930                                        lastPostCursor,
4931                                        (NvU8)activeLinkConfig.lanes))
4932                 {
4933                     DP_LOG(("DPCONN> Post Link Training : Unable to read current training values"));
4934                 }
4935             }
4936         }
4937 
4938         // Mark the linkStatus as dirty since we need to retrain in case Rx has lost sync
4939          hal->setDirtyLinkStatus(true);
4940     }while (!isLinkLost());
4941 
4942     // Clear POST_LT_ADJ_REQ_GRANTED bit
4943     hal->setPostLtAdjustRequestGranted(false);
4944 
4945     if (isLinkLost())
4946     {
4947         if (bNoFallbackInPostLQA && (retryLT < WAR_MAX_RETRAIN_ATTEMPT))
4948         {
4949             //
4950             // A monitor may lose link sometimes during assess link or link training.
4951             // So retry for 3 times before fallback to lower config
4952             //
4953             retryLT++;
4954             train(lConfig, force);
4955             return true;
4956         }
4957         //
4958         // If the link is not alive, then we need to retrain at a lower config
4959         // There is no reason to try at the same link configuration. Follow the
4960         // fallback policy that is followed for CR phase of LT
4961         //
4962         if (!linkConfig.lowerConfig())
4963         {
4964             DP_LOG(("DPCONN> Post Link Training : Already at the lowest link rate. Cannot reduce further"));
4965             return false;
4966         }
4967         train(linkConfig, force);
4968     }
4969     else if (bNoFallbackInPostLQA && (retryLT != 0))
4970     {
4971         retryLT = 0;
4972     }
4973 
4974     return true;
4975 }
4976 
4977 void ConnectorImpl::populateUpdatedLaneSettings(NvU8* voltageSwingLane, NvU8* preemphasisLane, NvU32 *data)
4978 {
4979     NvU32 laneIndex;
4980 
4981     for (laneIndex = 0; laneIndex < activeLinkConfig.lanes; laneIndex++)
4982     {
4983         switch (voltageSwingLane[laneIndex])
4984         {
4985             case driveCurrent_Level0:
4986                 data[laneIndex] = FLD_SET_DRF(0073_CTRL, _DP_LANE_DATA, _DRIVECURRENT, _LEVEL0, data[laneIndex]);
4987                 break;
4988 
4989             case driveCurrent_Level1:
4990                 data[laneIndex] = FLD_SET_DRF(0073_CTRL, _DP_LANE_DATA, _DRIVECURRENT, _LEVEL1, data[laneIndex]);
4991                 break;
4992 
4993             case driveCurrent_Level2:
4994                 data[laneIndex] = FLD_SET_DRF(0073_CTRL, _DP_LANE_DATA, _DRIVECURRENT, _LEVEL2, data[laneIndex]);
4995                 break;
4996 
4997             case driveCurrent_Level3:
4998                 data[laneIndex] = FLD_SET_DRF(0073_CTRL, _DP_LANE_DATA, _DRIVECURRENT, _LEVEL3, data[laneIndex]);
4999                 break;
5000         }
5001 
5002         switch (preemphasisLane[laneIndex])
5003         {
5004             case preEmphasis_Level1:
5005                 data[laneIndex] = FLD_SET_DRF(0073_CTRL, _DP_LANE_DATA, _PREEMPHASIS, _LEVEL1, data[laneIndex]);
5006                 break;
5007 
5008             case preEmphasis_Level2:
5009                 data[laneIndex] = FLD_SET_DRF(0073_CTRL, _DP_LANE_DATA, _PREEMPHASIS, _LEVEL2, data[laneIndex]);
5010                 break;
5011 
5012             case preEmphasis_Level3:
5013                 data[laneIndex] = FLD_SET_DRF(0073_CTRL, _DP_LANE_DATA, _PREEMPHASIS, _LEVEL3, data[laneIndex]);
5014                 break;
5015         }
5016     }
5017 }
5018 
5019 bool ConnectorImpl::validateLinkConfiguration(const LinkConfiguration & lConfig)
5020 {
5021     if (!IS_VALID_LANECOUNT(lConfig.lanes))
5022         return false;
5023 
5024     if (lConfig.lanes > hal->getMaxLaneCount())
5025         return false;
5026 
5027     if (lConfig.lanes != 0)
5028     {
5029         if (!IS_VALID_LINKBW(lConfig.peakRate/DP_LINK_BW_FREQ_MULTI_MBPS))
5030             return false;
5031 
5032         if (lConfig.peakRate > hal->getMaxLinkRate())
5033             return false;
5034 
5035         if (IS_INTERMEDIATE_LINKBW(lConfig.peakRate/DP_LINK_BW_FREQ_MULTI_MBPS))
5036         {
5037             NvU16 *ilrTable;
5038             NvU32 i;
5039             if (!hal->isIndexedLinkrateEnabled())
5040                 return false;
5041 
5042             ilrTable = hal->getLinkRateTable();
5043             for (i = 0; i < NV0073_CTRL_DP_MAX_INDEXED_LINK_RATES; i++)
5044             {
5045                 //
5046                 // lConfig.peakRate is in MBPS and ilrTable entries are the values read from DPCD
5047                 // Convert the ilrTable value to MBPS before the comparison
5048                 //
5049                 if (LINK_RATE_KHZ_TO_MBPS(ilrTable[i] * DP_LINK_RATE_TABLE_MULTIPLIER_KHZ) == lConfig.peakRate)
5050                     break;
5051                 if (ilrTable[i] == 0)
5052                     return false;
5053             }
5054             if (i == NV0073_CTRL_DP_MAX_INDEXED_LINK_RATES)
5055                 return false;
5056         }
5057     }
5058 
5059     return true;
5060 }
5061 
5062 bool ConnectorImpl::train(const LinkConfiguration & lConfig, bool force,
5063                           LinkTrainingType trainType)
5064 {
5065     LinkTrainingType preferredTrainingType = trainType;
5066     bool result;
5067 
5068     //
5069     //  Validate link config against caps
5070     //
5071     if (!force)
5072     {
5073         if (!validateLinkConfiguration(lConfig))
5074             return false;
5075     }
5076 
5077     if (!lConfig.multistream)
5078     {
5079           for (Device * i = enumDevices(0); i; i=enumDevices(i))
5080         {
5081             DeviceImpl * dev = (DeviceImpl *)i;
5082             if (dev->powerOnMonitorBeforeLt() && lConfig.lanes != 0)
5083             {
5084                 //
5085                 // Some panels expose that they are in D0 even when they are not.
5086                 // Explicit write to DPCD 0x600 is required to wake up such panel before LT.
5087                 //
5088                 hal->setPowerState(PowerStateD0);
5089             }
5090         }
5091         //
5092         // Enable special LT only when regkey 'ENABLE_FAST_LINK_TRAINING' set
5093         // to 1 in DD's path.
5094         //
5095         if (bEnableFastLT)
5096         {
5097             // If the panel can support NLT or FLT, then let's try it first
5098             if (hal->getNoLinkTraining())
5099                 preferredTrainingType = NO_LINK_TRAINING;
5100             else if (hal->getSupportsNoHandshakeTraining())
5101                 preferredTrainingType = FAST_LINK_TRAINING;
5102         }
5103 
5104     }
5105 
5106     //
5107     //    Don't set the stream if we're shutting off the link
5108     //    or forcing the config
5109     //
5110     if (!force && lConfig.lanes != 0)
5111     {
5112         if (isLinkActive())
5113         {
5114             if (activeLinkConfig.multistream != lConfig.multistream)
5115             {
5116                 activeLinkConfig.lanes = 0;
5117                 rawTrain(activeLinkConfig, true, NORMAL_LINK_TRAINING);
5118             }
5119         }
5120 
5121         if (AuxRetry::ack != hal->setMultistreamLink(lConfig.multistream))
5122         {
5123             DP_LOG(("DP> Failed to enable multistream mode on current link"));
5124         }
5125     }
5126 
5127     //
5128     // Read link rate table before link-train to assure on-board re-driver
5129     // knows link rate going to be set in link rate table.
5130     // If eDP's power has been shutdown here, don't query Link rate table,
5131     // else it will cause panel wake up.
5132     //
5133     if (hal->isIndexedLinkrateEnabled() && (lConfig.lanes != 0))
5134     {
5135         hal->getRawLinkRateTable();
5136     }
5137 
5138     activeLinkConfig = lConfig;
5139     result = rawTrain(lConfig, force, preferredTrainingType);
5140 
5141     // If NLT or FLT failed, then fallback to normal LT again
5142     if (!result && (preferredTrainingType != NORMAL_LINK_TRAINING))
5143         result = rawTrain(lConfig, force, NORMAL_LINK_TRAINING);
5144 
5145     if (!result)
5146         activeLinkConfig.lanes = 0;
5147     else
5148         bNoLtDoneAfterHeadDetach = false;
5149 
5150     if (!force && result)
5151         this->hal->setDirtyLinkStatus(true);
5152 
5153     // We don't need post LQA while powering down the lanes.
5154     if ((lConfig.lanes != 0) && hal->isPostLtAdjustRequestSupported() && result)
5155     {
5156         result = postLTAdjustment(activeLinkConfig, force);
5157     }
5158 
5159     if((lConfig.lanes != 0) && result && activeLinkConfig.bEnableFEC)
5160     {
5161         //
5162         // Extended latency from link-train end to FEC enable pattern
5163         // to avoid link lost or blank screen with Synaptics branch.
5164         // (Bug 2561206)
5165         //
5166         if (LT2FecLatencyMs)
5167         {
5168             timer->sleep(LT2FecLatencyMs);
5169         }
5170 
5171         result = main->configureFec(true /*bEnableFec*/);
5172         DP_ASSERT(result);
5173     }
5174 
5175     //
5176     // Do not compare bEnableFEC here. In DDS case FEC might be requested but
5177     // not performed in RM.
5178     //
5179     if ((lConfig.lanes != activeLinkConfig.lanes) ||
5180         (lConfig.peakRate != activeLinkConfig.peakRate) ||
5181         (lConfig.enhancedFraming != activeLinkConfig.enhancedFraming) ||
5182         (lConfig.multistream != activeLinkConfig.multistream))
5183     {
5184         // fallback happens, returns fail to make sure clients notice it.
5185         result = false;
5186     }
5187     return result;
5188 }
5189 
5190 void ConnectorImpl::sortActiveGroups(bool ascending)
5191 {
5192     List activeSortedGroups;
5193 
5194     while(!activeGroups.isEmpty())
5195     {
5196         ListElement * e = activeGroups.begin();
5197         GroupImpl * g = (GroupImpl *)e;
5198 
5199         GroupImpl * groupToInsertBefore = NULL;
5200 
5201         // Remove from active group for sorting
5202         activeGroups.remove(g);
5203 
5204         for (ListElement *e1 = activeSortedGroups.begin(); e1 != activeSortedGroups.end(); e1 = e1->next)
5205         {
5206             GroupImpl * g1 = (GroupImpl *)e1;
5207             if ((g->headIndex < g1->headIndex) ||
5208                 ((g->headIndex == g1->headIndex) &&
5209                  ((ascending && (g->singleHeadMultiStreamID < g1->singleHeadMultiStreamID)) ||
5210                  (!ascending && (g->singleHeadMultiStreamID > g1->singleHeadMultiStreamID)))
5211                 ))
5212             {
5213                 groupToInsertBefore = g1;
5214                 break;
5215             }
5216         }
5217 
5218         if (NULL == groupToInsertBefore)
5219         {
5220             activeSortedGroups.insertBack(g);
5221         }
5222         else
5223         {
5224             activeSortedGroups.insertBefore(groupToInsertBefore, g);
5225         }
5226     }
5227 
5228     // Repopulate active group list
5229     while (!activeSortedGroups.isEmpty())
5230     {
5231         ListElement * e = activeSortedGroups.begin();
5232 
5233         // Remove from sorted list
5234         activeSortedGroups.remove(e);
5235         // Insert back to active group list
5236         activeGroups.insertBack(e);
5237     }
5238 }
5239 
5240 bool ConnectorImpl::enableFlush()
5241 {
5242     bool bHeadAttached = false;
5243 
5244     if (activeGroups.isEmpty())
5245         return true;
5246 
5247     //
5248     // If SST check that head should be attached with single group else if MST at least
5249     // 1 group should have headAttached before calling flush on SOR
5250     //
5251     if (!this->linkUseMultistream())
5252     {
5253         GroupImpl * activeGroup = this->getActiveGroupForSST();
5254 
5255         if (activeGroup && !activeGroup->isHeadAttached() && intransitionGroups.isEmpty())
5256         {
5257             DP_LOG(("DPCONN> SST-Flush mode should not be called when head is not attached. Returning early without enabling flush"));
5258             return true;
5259         }
5260     }
5261     else
5262     {
5263         for (ListElement * e = activeGroups.begin(); e != activeGroups.end(); e = e->next)
5264         {
5265             GroupImpl * group = (GroupImpl *)e;
5266             if (group->isHeadAttached())
5267             {
5268                 bHeadAttached  = true;
5269                 break;
5270             }
5271         }
5272 
5273         if (!bHeadAttached)
5274         {
5275             DP_LOG(("DPCONN> MST-Flush mode should not be called when head is not attached. Returning early without enabling flush"));
5276             return true;
5277         }
5278     }
5279 
5280     if (!main->setFlushMode())
5281         return false;
5282 
5283     //
5284     // Enabling flush mode shuts down the link, so the next link training
5285     // call must not skip programming the hardware.  Otherwise, EVO will
5286     // hang if the head is still active when flush mode is disabled.
5287     //
5288     bSkipLt = false;
5289 
5290     sortActiveGroups(false);
5291 
5292     for (ListElement * e = activeGroups.begin(); e != activeGroups.end(); e = e->next)
5293     {
5294         GroupImpl * g = (GroupImpl *)e;
5295 
5296         if (!this->linkUseMultistream())
5297         {
5298             GroupImpl * activeGroup = this->getActiveGroupForSST();
5299             DP_ASSERT(g == activeGroup);
5300         }
5301 
5302         bool skipPreLinkTraining = (((g->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST) ||
5303                                      (g->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST)) &&
5304                                     (g->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY));
5305          if (!skipPreLinkTraining)
5306             main->preLinkTraining(g->headIndex);
5307 
5308         beforeDeleteStream(g, true);
5309         if (this->linkUseMultistream())
5310         {
5311             main->configureTriggerSelect(g->headIndex, g->singleHeadMultiStreamID);
5312             main->triggerACT();
5313         }
5314         afterDeleteStream(g);
5315     }
5316 
5317     return true;
5318 }
5319 
5320 //
5321 // This is a wrapper for call to mainlink::train().
5322 bool ConnectorImpl::rawTrain(const LinkConfiguration & lConfig, bool force, LinkTrainingType linkTrainingType)
5323 {
5324     {
5325         //
5326         // this is the common path
5327         // activeLinkConfig will be updated in main->train() in case fallback happens.
5328         // if the link config sent has disable Post LT request set, we send false for corresponding flag
5329         //
5330         if (lConfig.disablePostLTRequest)
5331         {
5332             return (main->train(lConfig, force, linkTrainingType, &activeLinkConfig, bSkipLt, false,
5333                     hal->getPhyRepeaterCount()));
5334         }
5335         return (main->train(lConfig, force, linkTrainingType, &activeLinkConfig, bSkipLt, hal->isPostLtAdjustRequestSupported(),
5336             hal->getPhyRepeaterCount()));
5337     }
5338 }
5339 
5340 //
5341 //  Timeslot management
5342 //
5343 
5344 bool ConnectorImpl::deleteAllVirtualChannels()
5345 {
5346     // Clear the payload table
5347     hal->payloadTableClearACT();
5348     if (!hal->payloadAllocate(0, 0, 63))
5349     {
5350         DP_LOG(("DPCONN> Payload table could not be cleared"));
5351     }
5352 
5353     // send clear_payload_id_table
5354     DP_LOG(("DPCONN> Sending CLEAR_PAYLOAD_ID_TABLE broadcast"));
5355 
5356     for (unsigned retries = 0 ; retries < 7; retries++)
5357     {
5358         ClearPayloadIdTableMessage clearPayload;
5359         NakData nack;
5360 
5361         if (this->messageManager->send(&clearPayload, nack))
5362             return true;
5363     }
5364 
5365     // we should not have reached here.
5366     DP_ASSERT(0 && "DPCONN> CLEAR_PAYLOAD_ID failed!");
5367     return false;
5368 }
5369 
5370 void ConnectorImpl::clearTimeslices()
5371 {
5372     for (ListElement * i = activeGroups.begin(); i != activeGroups.end(); i = i->next)
5373     {
5374         GroupImpl * group = (GroupImpl *)((Group *)i);
5375         group->timeslot.PBN = 0;
5376         group->timeslot.count = 0;
5377         group->timeslot.begin = 1;
5378         group->timeslot.hardwareDirty = false;
5379     }
5380 
5381     maximumSlots = 63;
5382     freeSlots = maximumSlots;
5383 }
5384 
5385 
5386 void ConnectorImpl::freeTimeslice(GroupImpl * targetGroup)
5387 {
5388     // compact timeslot allocation
5389     for (ListElement * e = activeGroups.begin(); e != activeGroups.end(); e = e->next)
5390     {
5391         GroupImpl * group = (GroupImpl *)e;
5392 
5393         if (group->timeslot.begin > targetGroup->timeslot.begin) {
5394             group->timeslot.begin -= targetGroup->timeslot.count;
5395             group->timeslot.hardwareDirty = true;
5396 
5397             //
5398             // enable TRIGGER_ALL on SFs corresponding to the the single head MST driving heads
5399             // as both both pipelines need to take the affect of the shift happening due to deactivating
5400             // an MST display being driven through same SOR
5401             //
5402             if ((DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST == group->singleHeadMultiStreamMode) &&
5403                 (DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY == group->singleHeadMultiStreamID))
5404             {
5405                 main->configureTriggerAll(group->headIndex, true);
5406             }
5407         }
5408     }
5409 
5410     // mark stream as free
5411     freeSlots += targetGroup->timeslot.count;
5412     targetGroup->timeslot.PBN = 0;
5413     targetGroup->timeslot.count = 0;
5414     targetGroup->timeslot.hardwareDirty = true;
5415 }
5416 
5417 bool ConnectorImpl::allocateTimeslice(GroupImpl * targetGroup)
5418 {
5419     unsigned base_pbn, slot_count, slots_pbn;
5420 
5421     DP_ASSERT(isLinkActive());
5422     if (this->isFECSupported())
5423     {
5424         if (!isModePossibleMSTWithFEC(activeLinkConfig,
5425                                       targetGroup->lastModesetInfo,
5426                                       &targetGroup->timeslot.watermarks))
5427         {
5428             DP_ASSERT(0 && "DisplayDriver bug! This mode is not possible at any "
5429                            "link configuration. It would have been reject at mode filtering time!");
5430             return false;
5431         }
5432     }
5433     else
5434     {
5435         if (!isModePossibleMST(activeLinkConfig,
5436                                targetGroup->lastModesetInfo,
5437                                &targetGroup->timeslot.watermarks))
5438         {
5439             DP_ASSERT(0 && "DisplayDriver bug! This mode is not possible at any "
5440                            "link configuration. It would have been reject at mode filtering time!");
5441             return false;
5442         }
5443     }
5444 
5445     activeLinkConfig.pbnRequired(targetGroup->lastModesetInfo, base_pbn, slot_count, slots_pbn);
5446 
5447     // Check for available timeslots
5448     if (slot_count > freeSlots)
5449         return false;
5450 
5451     int firstFreeSlot = 1;
5452 
5453     for (ListElement * i = activeGroups.begin(); i != activeGroups.end(); i = i->next)
5454     {
5455         GroupImpl * group = (GroupImpl *)i;
5456 
5457         if (group->timeslot.count != 0 &&
5458             (group->timeslot.begin + group->timeslot.count) >= firstFreeSlot)
5459         {
5460             firstFreeSlot = group->timeslot.begin + group->timeslot.count;
5461         }
5462     }
5463 
5464     DP_ASSERT((maximumSlots - firstFreeSlot + 1) == freeSlots && "Timeslot allocation table corrupted");
5465 
5466     // Already allocated?
5467     DP_ASSERT(!targetGroup->timeslot.count && "Reallocation of stream that is already present");
5468 
5469     targetGroup->timeslot.count = slot_count;
5470     targetGroup->timeslot.begin = firstFreeSlot;
5471     targetGroup->timeslot.PBN = base_pbn;
5472     targetGroup->timeslot.hardwareDirty = true;
5473     freeSlots -= slot_count;
5474 
5475     return true;
5476 }
5477 
5478 
5479 void ConnectorImpl::flushTimeslotsToHardware()
5480 {
5481     for (ListElement * i = activeGroups.begin(); i != activeGroups.end(); i = i->next)
5482     {
5483         GroupImpl * group = (GroupImpl *)i;
5484 
5485         if (group->timeslot.hardwareDirty)
5486         {
5487             group->timeslot.hardwareDirty = false;
5488             bool bEnable2Head1Or = false;
5489 
5490             if ((group->lastModesetInfo.mode == DSC_DUAL) ||
5491                 (group->lastModesetInfo.mode == DSC_DROP))
5492             {
5493                 bEnable2Head1Or = true;
5494             }
5495 
5496             main->configureMultiStream(group->headIndex,
5497                                            group->timeslot.watermarks.hBlankSym,
5498                                            group->timeslot.watermarks.vBlankSym,
5499                                            group->timeslot.begin,
5500                                            group->timeslot.begin+group->timeslot.count-1,
5501                                            group->timeslot.PBN,
5502                                            activeLinkConfig.PBNForSlots(group->timeslot.count),
5503                                            group->colorFormat,
5504                                            group->singleHeadMultiStreamID,
5505                                            group->singleHeadMultiStreamMode,
5506                                            bAudioOverRightPanel,
5507                                            bEnable2Head1Or);
5508         }
5509     }
5510 }
5511 
5512 void ConnectorImpl::beforeDeleteStream(GroupImpl * group, bool forFlushMode)
5513 {
5514 
5515     //
5516     // During flush entry, if the link is not trained, retrain
5517     // the link so that ACT can be ack'd by the sink.
5518     // (ACK is only for multistream case)
5519     //
5520     // Note: A re-training might be required even in cases where link is not
5521     // alive in non-flush mode case (Eg: beforeDeleteStream called from NAB).
5522     // However we cannot simply re-train is such cases, without ensuring that
5523     // head is not actively driving pixels and this needs to be handled
5524     // differently .
5525     //
5526     if(forFlushMode && linkUseMultistream())
5527     {
5528         if(isLinkLost())
5529         {
5530             train(activeLinkConfig, false);
5531         }
5532     }
5533 
5534     // check if this is a firmware group
5535     if (group && group->isHeadAttached() && group->headInFirmware)
5536     {
5537         // check if MST is enabled and we have inited messagemanager
5538         if (hal->getSupportsMultistream() && messageManager)
5539         {
5540             // Firmware group can be assumed to be taking up all 63 slots.
5541             group->timeslot.begin = 1;
5542             group->timeslot.count = 63;
5543             this->freeSlots = 0;
5544 
5545             // 1. clear the timeslots using CLEAR_PAYLAOD_TABLE
5546             // 2. clear gpu timeslots.
5547             if (!deleteAllVirtualChannels())
5548                 DP_ASSERT(0 && "Failed to delete VCs. Vbios state in branch could not be cleaned.");
5549 
5550             freeTimeslice(group);
5551             flushTimeslotsToHardware();
5552             group->bWaitForDeAllocACT = false;
5553 
5554             return;
5555         }
5556     }
5557 
5558     if (linkUseMultistream() && group && group->isHeadAttached() && group->timeslot.count)
5559     {
5560         // Detach all the panels from payload
5561         for (Device * d = group->enumDevices(0); d; d = group->enumDevices(d))
5562         {
5563             group->update(d, false);
5564         }
5565 
5566         freeTimeslice(group);
5567         flushTimeslotsToHardware();
5568         group->bWaitForDeAllocACT = true;
5569 
5570         // Delete the stream
5571         hal->payloadTableClearACT();
5572         hal->payloadAllocate(group->streamIndex, group->timeslot.begin, 0);
5573 
5574         //
5575         // If entering flush mode, enable RG (with Immediate effect) otherwise for detaching a display,
5576         // if not single heas MST, not required to enable RG. For single head MST streams deletion, enable
5577         // RG at loadv
5578         //
5579         if (forFlushMode ||
5580             ((DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST == group->singleHeadMultiStreamMode) &&
5581             (DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY != group->singleHeadMultiStreamID)))
5582         {
5583             main->controlRateGoverning(group->headIndex, true/*enable*/, forFlushMode /*Immediate/loadv*/);
5584         }
5585     }
5586 }
5587 
5588 void ConnectorImpl::afterDeleteStream(GroupImpl * group)
5589 {
5590     if (linkUseMultistream() && group->isHeadAttached() && group->bWaitForDeAllocACT)
5591     {
5592         if (!hal->payloadWaitForACTReceived())
5593         {
5594             DP_LOG(("DP> Delete stream failed.  Device did not acknowledge stream deletion ACT!"));
5595             DP_ASSERT(0);
5596         }
5597     }
5598 }
5599 
5600 void ConnectorImpl::afterAddStream(GroupImpl * group)
5601 {
5602     // Skip this as there is no timeslot allocation
5603     if (!linkUseMultistream() || !group->timeslot.count)
5604         return;
5605 
5606     if (group->bDeferredPayloadAlloc)
5607     {
5608         DP_ASSERT(addStreamMSTIntransitionGroups.contains(group));
5609         hal->payloadTableClearACT();
5610         hal->payloadAllocate(group->streamIndex, group->timeslot.begin, group->timeslot.count);
5611         main->triggerACT();
5612     }
5613     group->bDeferredPayloadAlloc = false;
5614 
5615     if (addStreamMSTIntransitionGroups.contains(group)) {
5616         addStreamMSTIntransitionGroups.remove(group);
5617     }
5618 
5619     if (!hal->payloadWaitForACTReceived())
5620     {
5621         DP_LOG(("ACT has not been received.Triggering ACT once more"));
5622         DP_ASSERT(0);
5623 
5624         //
5625         // Bug 1334070: During modeset for cloned displays on certain GPU family,
5626         // ACT triggered during SOR attach is not being received due to timing issues.
5627         // Also DP1.2 spec mentions that there is no harm in sending the ACT
5628         // again if there is no change in payload table. Hence triggering ACT once more here
5629         //
5630         main->triggerACT();
5631         if (!hal->payloadWaitForACTReceived())
5632         {
5633             DP_LOG(("DP-TS> Downstream device did not receive ACT during stream re-add."));
5634             return;
5635         }
5636     }
5637 
5638     for (Device * d = group->enumDevices(0); d; d = group->enumDevices(d))
5639     {
5640         group->update((DeviceImpl *)d, true);
5641 
5642         lastDeviceSetForVbios = d;
5643     }
5644 
5645     // Disable rate gov at the end of adding all streams
5646     if ((DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST != group->singleHeadMultiStreamMode) ||
5647         (DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_MAX == group->singleHeadMultiStreamID))
5648     {
5649         main->controlRateGoverning(group->headIndex, false/*disable*/, false/*loadv*/);
5650     }
5651 
5652     group->updateVbiosScratchRegister(lastDeviceSetForVbios);
5653 }
5654 
5655 bool ConnectorImpl::beforeAddStream(GroupImpl * group, bool test, bool forFlushMode)
5656 {
5657     bool res = false;
5658     if (linkUseMultistream())
5659     {
5660         res = beforeAddStreamMST(group, test, forFlushMode);
5661     }
5662     else
5663     {
5664         // SST
5665         Watermark water;
5666         bool bEnable2Head1Or = false;
5667         bool bIsModePossible = false;
5668 
5669         if ((group->lastModesetInfo.mode == DSC_DUAL) ||
5670             (group->lastModesetInfo.mode == DSC_DROP))
5671         {
5672             bEnable2Head1Or = true;
5673         }
5674 
5675         if (this->isFECSupported())
5676         {
5677             bIsModePossible = isModePossibleSSTWithFEC(activeLinkConfig,
5678                                                        group->lastModesetInfo,
5679                                                        &water,
5680                                                        main->hasIncreasedWatermarkLimits());
5681         }
5682         else
5683         {
5684             bIsModePossible = isModePossibleSST(activeLinkConfig,
5685                                                 group->lastModesetInfo,
5686                                                 &water,
5687                                                 main->hasIncreasedWatermarkLimits());
5688         }
5689 
5690         if (bIsModePossible)
5691         {
5692             if (group->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST)
5693             {
5694                 if (group->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY)
5695                 {
5696                     //
5697                     // configure sf parameters after secondary linktraining on primary link.
5698                     //
5699                     main->configureSingleStream(group->headIndex,
5700                                                 water.hBlankSym,
5701                                                 water.vBlankSym,
5702                                                 activeLinkConfig.enhancedFraming,
5703                                                 water.tuSize,
5704                                                 water.waterMark,
5705                                                 group->colorFormat,
5706                                                 DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY,
5707                                                 group->singleHeadMultiStreamMode,
5708                                                 bAudioOverRightPanel);
5709                 }
5710             }
5711             else
5712             {
5713                 main->configureSingleStream(group->headIndex,
5714                                             water.hBlankSym,
5715                                             water.vBlankSym,
5716                                             activeLinkConfig.enhancedFraming,
5717                                             water.tuSize,
5718                                             water.waterMark,
5719                                             group->colorFormat,
5720                                             DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY,
5721                                             DP_SINGLE_HEAD_MULTI_STREAM_MODE_NONE,
5722                                             false /*bEnableAudioOverRightPanel*/,
5723                                             bEnable2Head1Or);
5724             }
5725         }
5726         else
5727         {
5728             if (test)
5729             {
5730                 main->configureSingleStream(group->headIndex,
5731                                             water.hBlankSym,
5732                                             water.vBlankSym,
5733                                             activeLinkConfig.enhancedFraming,
5734                                             water.tuSize,
5735                                             water.waterMark,
5736                                             group->colorFormat,
5737                                             DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY,
5738                                             DP_SINGLE_HEAD_MULTI_STREAM_MODE_NONE,
5739                                             false /*bEnableAudioOverRightPanel*/,
5740                                             bEnable2Head1Or);
5741                 DP_LOG(("DP-TS> Unable to allocate stream. Setting RG_DIV mode"));
5742                 res = true;
5743             }
5744             else
5745                 DP_ASSERT(0);
5746         }
5747     }
5748     return res;
5749 }
5750 
5751 bool ConnectorImpl::beforeAddStreamMST(GroupImpl * group, bool test, bool forFlushMode)
5752 {
5753     bool res = false;
5754     bool isPrimaryStream = (DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY == group->singleHeadMultiStreamID);
5755     if (allocateTimeslice(group))
5756     {
5757         flushTimeslotsToHardware();
5758         if (!forFlushMode && isPrimaryStream)
5759         {
5760             main->controlRateGoverning(group->headIndex, true /*enable*/);
5761         }
5762 
5763         // If not single Head MST mode or if primary stream then program here
5764         // other streams programmed in NAE
5765         if (forFlushMode ||
5766             (isPrimaryStream &&
5767              addStreamMSTIntransitionGroups.isEmpty()))
5768         {
5769             hal->payloadTableClearACT();
5770             hal->payloadAllocate(group->streamIndex, group->timeslot.begin, group->timeslot.count);
5771         }
5772         else if (isPrimaryStream &&
5773                  !addStreamMSTIntransitionGroups.isEmpty())
5774         {
5775 
5776             group->bDeferredPayloadAlloc = true;
5777         }
5778 
5779         addStreamMSTIntransitionGroups.insertFront(group);
5780     }
5781     else
5782     {
5783         if (!test)
5784         {
5785             DP_LOG(("DP-TS> Unable to allocate stream.  Should call mainLink->configureStream to trigger RG_DIV mode"));
5786             main->configureMultiStream(group->headIndex,
5787                 group->timeslot.watermarks.hBlankSym, group->timeslot.watermarks.vBlankSym,
5788                 1, 0, 0, 0, group->colorFormat, group->singleHeadMultiStreamID, group->singleHeadMultiStreamMode, bAudioOverRightPanel);
5789         }
5790         else
5791         {
5792             flushTimeslotsToHardware();
5793 
5794             if (forFlushMode ||
5795                 (DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST != group->singleHeadMultiStreamMode) || isPrimaryStream)
5796             {
5797                 main->configureTriggerSelect(group->headIndex, group->singleHeadMultiStreamID);
5798                 hal->payloadTableClearACT();
5799                 hal->payloadAllocate(group->streamIndex, group->timeslot.begin, group->timeslot.count);
5800             }
5801 
5802             DP_LOG(("DP-TS> Unable to allocate stream. Setting RG_DIV mode"));
5803             res = true;
5804         }
5805     }
5806 
5807     return res;
5808 }
5809 
5810 void ConnectorImpl::disableFlush( bool test)
5811 {
5812     bool bHeadAttached = false;
5813 
5814     if (activeGroups.isEmpty())
5815         return;
5816 
5817     sortActiveGroups(true);
5818 
5819     //
5820     // If SST check that head should be attached with single group else if MST at least
5821     // 1 group should have headAttached before calling disable flush on SOR
5822     //
5823     if (!this->linkUseMultistream())
5824     {
5825         GroupImpl * activeGroup = this->getActiveGroupForSST();
5826 
5827         if (activeGroup && !activeGroup->isHeadAttached() && intransitionGroups.isEmpty())
5828         {
5829             DP_LOG(("DPCONN> SST-Flush mode disable should not be called when head is not attached. Returning early without disabling flush\n"));
5830             return;
5831         }
5832     }
5833     else
5834     {
5835         for (ListElement * e = activeGroups.begin(); e != activeGroups.end(); e = e->next)
5836         {
5837             GroupImpl * group = (GroupImpl *)e;
5838             if (group->isHeadAttached())
5839             {
5840                 bHeadAttached  = true;
5841                 break;
5842             }
5843         }
5844 
5845         if (!bHeadAttached)
5846         {
5847             DP_LOG(("DPCONN> MST-Flush mode disable should not be called when head is not attached. Returning early without disabling flush\n"));
5848             return;
5849         }
5850     }
5851 
5852     //
5853     // We need to rebuild the tiemslot configuration when exiting flush mode
5854     // Bug 1550750: Change the order to proceed from last to front as they were added.
5855     // Some tiled monitors are happy with this.
5856     //
5857     for (ListElement * e = activeGroups.last(); e != activeGroups.end(); e = e->prev)
5858     {
5859         GroupImpl * g = (GroupImpl *)e;
5860         bool force = false;
5861         NvU32 headMask = 0;
5862 
5863         if (!g->isHeadAttached() && this->linkUseMultistream())
5864             continue;
5865 
5866         bool skipPostLinkTraining = (((g->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST) ||
5867                                       (g->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST)) &&
5868                                      (g->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY));
5869 
5870         //
5871         // Allocate the timeslot configuration
5872         //
5873         force = beforeAddStream(g, test, true);
5874         if (this->linkUseMultistream())
5875         {
5876             main->configureTriggerSelect(g->headIndex, g->singleHeadMultiStreamID);
5877         }
5878 
5879         if (g->lastModesetInfo.mode == DSC_DUAL)
5880         {
5881             // For 2 Head 1 OR - Legal combinations are Head0 and Head1, Head2 and Head3
5882             headMask = (1 << g->headIndex) | (1 << (g->headIndex + 1));
5883         }
5884         else
5885         {
5886             headMask = (1 << g->headIndex);
5887         }
5888 
5889         main->clearFlushMode(headMask, force);       // ACT is triggered here
5890         if (!skipPostLinkTraining)
5891             main->postLinkTraining(g->headIndex);
5892         afterAddStream(g);
5893     }
5894 }
5895 
5896 DeviceImpl* ConnectorImpl::findDeviceInList(const Address & address)
5897 {
5898     for (ListElement * e = deviceList.begin(); e != deviceList.end(); e = e->next)
5899     {
5900         DeviceImpl* device = (DeviceImpl*)e;
5901 
5902         //
5903         // There may be multiple hits with the same address.  This can
5904         // happen when the head is still attached to the old device.branch
5905         // We never need to resurrect old unplugged devices - and their
5906         // object will be destroyed as soon as the DD handles the
5907         // notifyZombie message.
5908         //
5909         if ((device->address == address) && device->plugged)
5910             return device;
5911     }
5912 
5913     //
5914     // If no plugged devices are found, we should search back through zombied devices.
5915     // This is purely as an optimizations to allow the automatic restoration of a
5916     // panel if it 'reappears' while its still being driven
5917     //
5918     for (ListElement * e = deviceList.begin(); e != deviceList.end(); e = e->next)
5919     {
5920         DeviceImpl* device = (DeviceImpl*)e;
5921 
5922         if (device->address == address)
5923             return device;
5924     }
5925 
5926     return 0;
5927 }
5928 
5929 void ConnectorImpl::disconnectDeviceList()
5930 {
5931     for (Device * d = enumDevices(0); d; d = enumDevices(d))
5932     {
5933         ((DeviceImpl*)d)->plugged = false;
5934         // Clear the active bit (payload_allocate)
5935         ((DeviceImpl*)d)->payloadAllocated = false;
5936 
5937         // Deallocate object which may go stale after long pulse handling.
5938         if (((DeviceImpl*)d)->isDeviceHDCPDetectionAlive)
5939         {
5940             delete ((DeviceImpl*)d)->deviceHDCPDetection;
5941             ((DeviceImpl*)d)->deviceHDCPDetection = NULL;
5942             ((DeviceImpl*)d)->isHDCPCap = False;
5943         }
5944     }
5945 }
5946 
5947 // status == true: attach, == false: detach
5948 void ConnectorImpl::notifyLongPulse(bool statusConnected)
5949 {
5950     NvU32 muxState = 0;
5951     NV_DPTRACE_INFO(HOTPLUG, statusConnected, connectorActive, previousPlugged);
5952 
5953     if (!connectorActive)
5954     {
5955         DP_LOG(("DP> Got a long pulse before any connector is active!!"));
5956         return;
5957     }
5958 
5959     if (main->getDynamicMuxState(&muxState))
5960     {
5961         DeviceImpl * existingDev = findDeviceInList(Address());
5962         bool bIsMuxOnDgpu = DRF_VAL(0073, _CTRL_DFP_DISP_MUX, _STATE, muxState) == NV0073_CTRL_DFP_DISP_MUX_STATE_DISCRETE_GPU;
5963 
5964         if (existingDev && existingDev->isFakedMuxDevice() && !bIsMuxOnDgpu)
5965         {
5966             DP_LOG((" NotifyLongPulse ignored as mux is not pointing to dGPU and there is a faked device. Marking detect complete"));
5967             sink->notifyDetectComplete();
5968             return;
5969         }
5970 
5971         if (existingDev && existingDev->isPreviouslyFakedMuxDevice() && !existingDev->isMarkedForDeletion())
5972         {
5973             DP_LOG((" NotifyLongPulse ignored as there is a previously faked device but it is not marked for deletion"));
5974             if (!statusConnected)
5975             {
5976                 DP_LOG((" Calling notifyDetectComplete"));
5977                 sink->notifyDetectComplete();
5978             }
5979             return;
5980         }
5981     }
5982 
5983     if (previousPlugged && statusConnected)
5984     {
5985         if (main->isInternalPanelDynamicMuxCapable())
5986             return;
5987 
5988         DP_LOG(("DP> Redundant plug"));
5989         for (Device * i = enumDevices(0); i; i=enumDevices(i))
5990         {
5991             DeviceImpl * dev = (DeviceImpl *)i;
5992             if (dev->ignoreRedundantHotplug())
5993             {
5994                 DP_LOG(("DP> Skipping link assessment"));
5995                 return;
5996             }
5997         }
5998 
5999         //
6000         // Exit early to avoid coonector re-initialization from breaking MST
6001         // branch state when streams are allocated.
6002         // Additional exceptions:
6003         // - UEFI post(firmwareGroup->headInFirmware)for fresh init.
6004         // - MST to SST transition for that unplug event may be filtered by RM.
6005         //   Messaging will be disabled in this case.
6006         //
6007         if (linkUseMultistream() && (!activeGroups.isEmpty()) &&
6008             (!(firmwareGroup && ((GroupImpl *)firmwareGroup)->headInFirmware)) &&
6009             (hal->isMessagingEnabled()))
6010         {
6011             DP_LOG(("DP> Bail out early on redundant hotplug with active"
6012                     "MST stream"));
6013             return;
6014         }
6015     }
6016 
6017     this->notifyLongPulseInternal(statusConnected);
6018 }
6019 
6020 //
6021 // notifyLongPulse() filters redundant hotplug notifications and calls into
6022 // notifyLongPulseInternal().
6023 //
6024 // setAllowMultiStreaming() calls into notifyLongPulseInternal() in order to
6025 // re-detect already connected sink after enabling/disabling
6026 // MST support.
6027 //
6028 void ConnectorImpl::notifyLongPulseInternal(bool statusConnected)
6029 {
6030     // start from scratch
6031     preferredLinkConfig = LinkConfiguration();
6032 
6033     bPConConnected = false;
6034     bSkipAssessLinkForPCon = false;
6035 
6036     //
6037     // Check if the panel is eDP and DPCD data for that is already parsed.
6038     // Passing this as a parameter inside notifyHPD to skip reading of DPCD
6039     // data in case of eDP after sleep/hibernate resume.
6040     //
6041     hal->notifyHPD(statusConnected, (!hal->isDpcdOffline() && main->isEDP()));
6042     if (main->isLttprSupported())
6043     {
6044         //
6045         // Update LTTPR counts since it's only correct after HPD.
6046         // If there are some other DFP parameters might change during HPD cycle
6047         // then we can remove the isLttprSupported() check.
6048         //
6049         main->queryAndUpdateDfpParams();
6050     }
6051 
6052     // For bug 2489143, max link rate needs to be forced on eDP through regkey
6053     if (main->isEDP())
6054     {
6055         hal->overrideMaxLinkRate(maxLinkRateFromRegkey);
6056     }
6057 
6058     // Some panels whose TCON erroneously sets DPCD 0x200 SINK_COUNT=0.
6059     if (main->isEDP() && hal->getSinkCount() == 0)
6060         hal->setSinkCount(1);
6061 
6062     // disconnect all devices
6063     for (ListElement * i = activeGroups.begin(); i != activeGroups.end(); i = i->next) {
6064         GroupImpl * g = (GroupImpl *)i;
6065 
6066         // Clear the timeslot table
6067         freeTimeslice(g);
6068     }
6069 
6070     disconnectDeviceList();
6071 
6072     auxBus->setDevicePlugged(statusConnected);
6073 
6074     if (statusConnected)
6075     {
6076         // Reset all settings for previous downstream device
6077         configInit();
6078 
6079         if (!hal->isAtLeastVersion(1, 0))
6080             goto completed;
6081 
6082         DP_LOG(("DP> HPD v%d.%d", hal->getRevisionMajor(), hal->getRevisionMinor()));
6083 
6084         //
6085         // Handle to clear pending CP_IRQ that throw short pulse before L-HPD. There's no
6086         // more short pulse corresponding to CP_IRQ after HPD, but IRQ vector needs to be
6087         // clear or block following CP_IRQ.
6088         //
6089         if (hal->interruptContentProtection())
6090         {
6091             DP_LOG(("DP>clear pending CP interrupt at hpd"));
6092             hal->clearInterruptContentProtection();
6093         }
6094 
6095         populateAllDpConfigs();
6096 
6097         //
6098         // Perform OUI authentication
6099         //
6100         if (!performIeeeOuiHandshake() && hal->isAtLeastVersion(1, 2))
6101         {
6102             DP_LOG(("DP> OUI Noncompliance! Sink is DP 1.2 and is required to implement"));
6103         }
6104 
6105         // Apply Oui WARs here
6106         applyOuiWARs();
6107 
6108         // Tear down old message manager
6109         DP_ASSERT( !hal->getSupportsMultistream() || (hal->isAtLeastVersion(1, 2) && " Device supports multistream but not DP 1.2 !?!? "));
6110 
6111         // Check if we should be attempting a transition between MST<->SST
6112         if (main->hasMultistream())
6113         {
6114             if (linkState == DP_TRANSPORT_MODE_INIT)
6115             {
6116                 linkState = hal->getSupportsMultistream() ?
6117                                     DP_TRANSPORT_MODE_MULTI_STREAM :
6118                                     DP_TRANSPORT_MODE_SINGLE_STREAM;
6119                 linkAwaitingTransition = false;
6120             }
6121             else
6122             {
6123                 if (linkUseMultistream() != hal->getSupportsMultistream())
6124                 {
6125                     linkAwaitingTransition = true;
6126                     DP_LOG(("CONN> Link Awaiting Transition."));
6127                 }
6128                 else
6129                 {
6130                     linkAwaitingTransition = false;
6131                 }
6132             }
6133         }
6134 
6135         //
6136         //    Only transition between multiStream and single stream when there
6137         //    are no active panels.  Note: that if we're unable to transition
6138         //    we will mark all of the displays as MUST_DISCONNECT.
6139         //
6140 
6141         //
6142         //     Shutdown the old message manager if there was one
6143         //
6144         delete discoveryManager;
6145         isDiscoveryDetectComplete = false;
6146         bIsDiscoveryDetectActive = true;
6147 
6148         pendingEdidReads.clear();   // destroy any half completed requests
6149         delete messageManager;
6150         messageManager = 0;
6151         discoveryManager = 0;
6152 
6153         cancelHdcpCallbacks();
6154         if (hal->getSupportsMultistream() && main->hasMultistream())
6155         {
6156             bool bDeleteFirmwareVC = false;
6157 
6158             DP_LOG(("DP> Multistream panel detected, building message manager"));
6159 
6160             //
6161             // Rebuild the message manager to reset and half received messages
6162             //   that may be in the pipe.
6163             //
6164             messageManager = new MessageManager(hal, timer);
6165             messageManager->registerReceiver(&ResStatus);
6166 
6167             //
6168             // Create a discovery manager to initiate detection
6169             //
6170             if (AuxRetry::ack != hal->setMessagingEnable(true, true))
6171             {
6172                 DP_LOG(("DP> Failed to enable messaging for multistream panel"));
6173             }
6174 
6175             if (AuxRetry::ack != hal->setMultistreamHotplugMode(IRQ_HPD))
6176             {
6177                 DP_LOG(("DP> Failed to enable hotplug mode for multistream panel"));
6178             }
6179 
6180             discoveryManager = new DiscoveryManager(messageManager, this, timer, hal);
6181 
6182             // Check and clear if any pending message here
6183             if (hal->clearPendingMsg())
6184             {
6185                 DP_LOG(("DP> Stale MSG found: set branch to D3 and back to D0..."));
6186                 if (hal->isAtLeastVersion(1, 4))
6187                 {
6188                     hal->setMessagingEnable(false, true);
6189                 }
6190                 hal->setPowerState(PowerStateD3);
6191                 hal->setPowerState(PowerStateD0);
6192                 if (hal->isAtLeastVersion(1, 4))
6193                 {
6194                     hal->setMessagingEnable(true, true);
6195                 }
6196             }
6197             pendingRemoteHdcpDetections = 0;
6198 
6199             //
6200             // We need to clear payload table and payload id table during a hotplug in cases
6201             // where DD does not send a null modeset for a device that was plugged. Otherwise
6202             // this will lead to issues where branch does not clear the PBN and sends stale
6203             // available PBN values. One of the scenarios is BSOD in SLI mode, where the secondary
6204             // GPUs are not used for primary boot by VBIOS
6205             //
6206             bDeleteFirmwareVC = ((GroupImpl *)firmwareGroup &&
6207                                    !((GroupImpl *)firmwareGroup)->isHeadAttached() &&
6208                                    !bIsUefiSystem);
6209 
6210             if (bDeleteFirmwareVC || !bAttachOnResume)
6211             {
6212                 deleteAllVirtualChannels();
6213             }
6214 
6215             assessLink();                                   // Link assessment may re-add a stream
6216                                                             // and must be done AFTER the messaging system
6217                                                             // is restored.
6218             discoveryManager->notifyLongPulse(true);
6219         }
6220         else  // SST case
6221         {
6222             DiscoveryManager::Device dev;
6223             Edid tmpEdid;
6224             bool isComplianceForEdidTest = false;
6225             dev.address = Address();
6226 
6227 
6228             //  We will report a dongle as new device with videoSink flag as false.
6229             if (hal->getSinkCount() == 0)
6230             {
6231                 dev.peerDevice = Dongle;
6232             }
6233             else
6234             {
6235                 dev.peerDevice = DownstreamSink;
6236 
6237                 //  Handle fallback EDID
6238                 if(!EdidReadSST(tmpEdid, auxBus, timer,
6239                                 hal->getPendingTestRequestEdidRead(),
6240                                 main->isForceRmEdidRequired(),
6241                                 main->isForceRmEdidRequired() ? main : 0))
6242                 {
6243                     bool status = false;
6244                     //
6245                     // For some DP2VGA dongle which is unable to get the right after several retries.
6246                     // Before library, we do give 26 times retries for DP2VGA dongle EDID retries.
6247                     // Give most 24 times here for another re-start in library.
6248                     // Bug 996248.
6249                     //
6250                     if (hal->getLegacyPortCount())
6251                     {
6252                         LegacyPort * port = hal->getLegacyPort(0);
6253                         if (port->getDownstreamPortType() == ANALOG_VGA)
6254                         {
6255                             NvU8 retries = DP_READ_EDID_MAX_RETRIES;
6256                             for (NvU8 i = 0; i < retries; i++)
6257                             {
6258                                 status = EdidReadSST(tmpEdid, auxBus, timer,
6259                                                      hal->getPendingTestRequestEdidRead(),
6260                                                      main->isForceRmEdidRequired(),
6261                                                      main->isForceRmEdidRequired() ? main : 0);
6262                                 if (status)
6263                                     break;
6264                             }
6265                         }
6266                     }
6267                     if (!status)
6268                     {
6269                         // corrupt edid
6270                         DP_LOG(("DP-CONN> Corrupt Edid!"));
6271 
6272                         // Reading the EDID can fail if AUX is dead.
6273                         // So update DPCD state after max number of retries.
6274                         hal->updateDPCDOffline();
6275                     }
6276                 }
6277 
6278                 DP_LOG(("DP-CONN> Edid read complete: Manuf Id: 0x%x, Name: %s", tmpEdid.getManufId(), tmpEdid.getName()));
6279                 dev.branch = false;
6280                 dev.dpcdRevisionMajor = hal->getRevisionMajor();
6281                 dev.dpcdRevisionMinor = hal->getRevisionMinor();
6282                 dev.legacy = false;
6283                 dev.SDPStreams = hal->getNumberOfAudioEndpoints() ? 1 : 0;
6284                 dev.SDPStreamSinks = hal->getNumberOfAudioEndpoints();
6285                 dev.videoSink = true;
6286                 dev.maxTmdsClkRate = 0U;
6287 
6288                 // Apply EDID based WARs and update the WAR flags if needed
6289                 applyEdidWARs(tmpEdid, dev);
6290 
6291                 //
6292                 // HP Valor QHD+ needs 50ms delay after D3
6293                 // to prevent black screen
6294                 //
6295                 if (tmpEdid.WARFlags.delayAfterD3)
6296                 {
6297                     bDelayAfterD3 = true;
6298                 }
6299 
6300                 // Panels use Legacy address range for interrupt reporting
6301                 if (tmpEdid.WARFlags.useLegacyAddress)
6302                 {
6303                     hal->setSupportsESI(false);
6304                 }
6305 
6306                 //
6307                 // For some devices short pulse comes in after we disconnect the
6308                 // link, so DPLib ignores the request and link trains after modeset
6309                 // happens. When modeset happens the link configuration picked may
6310                 // be different than what we assessed before. So we skip the link
6311                 // power down in assessLink() in such cases
6312                 //
6313                 if (tmpEdid.WARFlags.keepLinkAlive)
6314                 {
6315                     DP_LOG(("tmpEdid.WARFlags.keepLinkAlive = true, set bKeepOptLinkAlive to true. (keep link alive after assessLink())\n"));
6316                     bKeepOptLinkAlive = true;
6317                 }
6318                 // Ack the test response, no matter it is a ref sink or not
6319                 if (hal->getPendingTestRequestEdidRead())
6320                 {
6321                     isComplianceForEdidTest = true;
6322                     hal->setTestResponseChecksum(tmpEdid.getLastPageChecksum());
6323                     hal->setTestResponse(true, true);
6324                 }
6325             }
6326 
6327             //
6328             // If this is a zombie VRR device that was previously enabled,
6329             // re-enable it now.  This must happen before link training if
6330             // VRR was enabled before the device became a zombie or else the
6331             // monitor will report that it's in normal mode even if the GPU is
6332             // driving it in VRR mode.
6333             //
6334             {
6335                 DeviceImpl * existingDev = findDeviceInList(dev.address);
6336                 if (existingDev && existingDev->isVrrMonitorEnabled() &&
6337                     !existingDev->isVrrDriverEnabled())
6338                 {
6339                     DP_LOG(("DP> Re-enabling previously enabled zombie VRR monitor"));
6340                     existingDev->resetVrrEnablement();
6341                     existingDev->startVrrEnablement();
6342                 }
6343             }
6344 
6345             if ((hal->getPCONCaps())->bSourceControlModeSupported)
6346             {
6347                 bPConConnected = true;
6348             }
6349 
6350             LinkConfiguration maxLinkConfig = getMaxLinkConfig();
6351 
6352             if (bPConConnected ||
6353                 (main->isEDP() && this->bSkipAssessLinkForEDP) ||
6354                 (main->isInternalPanelDynamicMuxCapable()))
6355             {
6356                 this->highestAssessedLC = maxLinkConfig;
6357                 this->linkGuessed = bPConConnected;
6358                 this->bSkipAssessLinkForPCon = bPConConnected;
6359             }
6360             else
6361             {
6362                 if (tmpEdid.WARFlags.powerOnBeforeLt)
6363                 {
6364                     //
6365                     // Some panels expose that they are in D0 even when they are not.
6366                     // Explicit write to DPCD 0x600 is required to wake up such panel before LT.
6367                     //
6368                     hal->setPowerState(PowerStateD0);
6369                 }
6370                 this->assessLink();
6371 
6372                 if (this->bReassessMaxLink)
6373                 {
6374                     //
6375                     // If the highest assessed LC is not equal to
6376                     // max possible link config, re-assess link
6377                     //
6378                     NvU8 retries = 0U;
6379 
6380                     while((retries < WAR_MAX_REASSESS_ATTEMPT) && (highestAssessedLC != maxLinkConfig))
6381                     {
6382                         DP_LOG(("DP> Assessed link is not equal to highest possible config. Reassess link."));
6383                         this->assessLink();
6384                         retries++;
6385                     }
6386                 }
6387             }
6388 
6389             if (hal->getLegacyPortCount() != 0)
6390             {
6391                 LegacyPort * port = hal->getLegacyPort(0);
6392                 DwnStreamPortType portType = port->getDownstreamPortType();
6393                 dev.maxTmdsClkRate = port->getMaxTmdsClkRate();
6394                 processNewDevice(dev, tmpEdid, false, portType, port->getDownstreamNonEDIDPortAttribute());
6395             }
6396             else
6397             {
6398                 processNewDevice(dev, tmpEdid, false, DISPLAY_PORT, RESERVED, isComplianceForEdidTest);
6399             }
6400 
6401             // After processNewDevice, we should not defer any lost device.
6402             bDeferNotifyLostDevice = false;
6403         }
6404     }
6405     else    // HPD unplug
6406     {
6407         //
6408         //     Shutdown the old message manager if there was one
6409         //
6410         delete discoveryManager;
6411         isDiscoveryDetectComplete = false;
6412         pendingEdidReads.clear();   // destroy any half completed requests
6413         bDeferNotifyLostDevice = false;
6414 
6415         delete messageManager;
6416         messageManager = 0;
6417         discoveryManager = 0;
6418         bAcpiInitDone = false;
6419         bKeepOptLinkAlive = false;
6420         bNoFallbackInPostLQA = false;
6421         bDscCapBasedOnParent = false;
6422 
6423     }
6424 completed:
6425     previousPlugged = statusConnected;
6426     fireEvents();
6427 
6428     if (!statusConnected)
6429     {
6430         sink->notifyDetectComplete();
6431         return;
6432     }
6433     if (!(hal->getSupportsMultistream() && main->hasMultistream()))
6434     {
6435         // Ensure NewDev will be processed before notifyDetectComplete on SST
6436         discoveryDetectComplete();
6437     }
6438 }
6439 
6440 void ConnectorImpl::notifyShortPulse()
6441 {
6442     //
6443     // Do nothing if device is not plugged or
6444     // resume has not been called after hibernate
6445     // to activate the connector
6446     //
6447     if (!connectorActive || !previousPlugged)
6448     {
6449         DP_LOG(("DP> Got a short pulse after an unplug or before any connector is active!!"));
6450         return;
6451     }
6452     DP_LOG(("DP> IRQ"));
6453     hal->notifyIRQ();
6454 
6455     // Handle CP_IRQ
6456     if (hal->interruptContentProtection())
6457     {
6458         // Cancel previous queued delay handling and reset retry counter.
6459         hdcpCpIrqRxStatusRetries = 0;
6460         timer->cancelCallback(this, &tagDelayedHDCPCPIrqHandling);
6461 
6462         if (handleCPIRQ())
6463         {
6464             hal->clearInterruptContentProtection();
6465         }
6466         else
6467         {
6468             timer->queueCallback(this, &tagDelayedHDCPCPIrqHandling, HDCP_CPIRQ_RXSTATUS_COOLDOWN);
6469         }
6470     }
6471 
6472     if (hal->getStreamStatusChanged())
6473     {
6474         if (!messageManager)
6475         {
6476             DP_LOG(("DP> Received Stream status changed Interrupt, but not in multistream mode. Ignoring."));
6477         }
6478         else
6479         {
6480             handleSSC();
6481             hal->clearStreamStatusChanged();
6482 
6483             //
6484             // Handling of SSC takes longer time during which time we miss IRQs.
6485             // Populate interrupts again.
6486             //
6487             hal->notifyIRQ();
6488         }
6489     }
6490 
6491     if (hal->interruptCapabilitiesChanged())
6492     {
6493         DP_LOG(("DP> Sink capabilities changed, re-reading caps and reinitializing the link."));
6494         // We need to set dpcdOffline to re-read the caps
6495         hal->setDPCDOffline(true);
6496         hal->clearInterruptCapabilitiesChanged();
6497         notifyLongPulse(true);
6498         return;
6499     }
6500 
6501     if (detectSinkCountChange())
6502     {
6503         DP_LOG(("DP> Change in downstream sink count. Re-analysing link."));
6504         // We need to set dpcdOffline to re-read the caps
6505         hal->setDPCDOffline(true);
6506         notifyLongPulse(true);
6507         return;
6508     }
6509 
6510     if (hal->interruptDownReplyReady())
6511     {
6512         if (!messageManager)
6513         {
6514             DP_LOG(("DP> Received DownReply Interrupt, but not in multistream mode. Ignoring."));
6515         }
6516         else
6517         {
6518             messageManager->IRQDownReply();
6519         }
6520     }
6521 
6522     if (hal->interruptUpRequestReady())
6523     {
6524         if (!messageManager)
6525         {
6526             DP_LOG(("DP> Received UpRequest Interrupt, but not in multistream mode. Ignoring."));
6527         }
6528         else
6529         {
6530             messageManager->IRQUpReqest();
6531         }
6532     }
6533 
6534     if (hal->getDownStreamPortStatusChange() && hal->getSinkCount())
6535     {
6536         Edid target;
6537         if (!EdidReadSST(target, auxBus, timer, hal->getPendingTestRequestEdidRead()))
6538         {
6539             DP_LOG(("DP> Failed to read EDID."));
6540         }
6541 
6542         return;
6543     }
6544 
6545     if (hal->getPendingAutomatedTestRequest())
6546     {
6547         if (hal->getPendingTestRequestEdidRead())
6548         {
6549             Edid target;
6550             if (EdidReadSST(target, auxBus, timer, true))
6551             {
6552                 hal->setTestResponseChecksum(target.getLastPageChecksum());
6553                 hal->setTestResponse(true, true);
6554             }
6555             else
6556                 hal->setTestResponse(false);
6557         }
6558         else if (hal->getPendingTestRequestTraining())
6559         {
6560             if (activeLinkConfig.multistream)
6561             {
6562                 hal->setTestResponse(false);
6563             }
6564             else
6565             {
6566                 LinkRate    requestedRate;
6567                 unsigned    requestedLanes;
6568 
6569                 hal->getTestRequestTraining(requestedRate, requestedLanes);
6570                 // if one of them is illegal; don't ack. let the box try again.
6571                 if (requestedRate == 0 || requestedLanes == 0)
6572                 {
6573                     DP_ASSERT(0 && "illegal requestedRate/Lane, retry..");
6574                     hal->setTestResponse(false);
6575                 }
6576                 else
6577                 {
6578                     // Compliance shouldn't ask us to train above its caps
6579                     if (requestedRate == 0 || requestedRate > hal->getMaxLinkRate())
6580                     {
6581                         DP_ASSERT(0 && "illegal requestedRate");
6582                         requestedRate = hal->getMaxLinkRate();
6583                     }
6584 
6585                     if (requestedLanes == 0 || requestedLanes > hal->getMaxLaneCount())
6586                     {
6587                         DP_ASSERT(0 && "illegal requestedLanes");
6588                         requestedLanes = hal->getMaxLaneCount();
6589                     }
6590 
6591                     DeviceImpl * dev = findDeviceInList(Address());
6592                     if (!dev || !dev->plugged || dev->multistream)
6593                     {
6594                         hal->setTestResponse(false);
6595                     }
6596                     else
6597                     {
6598                         GroupImpl * groupAttached = this->getActiveGroupForSST();
6599                         DP_ASSERT(groupAttached && groupAttached->isHeadAttached());
6600 
6601                         if (!dev->activeGroup || (dev->activeGroup != groupAttached))
6602                         {
6603                             DP_ASSERT(0 && "Compliance: no group attached");
6604                         }
6605 
6606                         DP_LOG(("DP> Compliance: LT on IRQ request: 0x%x, %d.", requestedRate, requestedLanes));
6607                         // now see whether the current resolution is supported on the requested link config
6608                         LinkConfiguration lc(&linkPolicy, requestedLanes, requestedRate, hal->getEnhancedFraming(), false);
6609 
6610                         if (groupAttached && groupAttached->isHeadAttached())
6611                         {
6612                             if (willLinkSupportModeSST(lc, groupAttached->lastModesetInfo))
6613                             {
6614                                 DP_LOG(("DP> Compliance: Executing LT on IRQ: 0x%x, %d.", requestedRate, requestedLanes));
6615                                 // we need to force the requirement irrespective of whether is supported or not.
6616                                 if (!enableFlush())
6617                                 {
6618                                     hal->setTestResponse(false);
6619                                 }
6620                                 else
6621                                 {
6622                                     //
6623                                     // Check if linkTraining fails, perform fake linktraining. This is required because
6624                                     // if we simply fail linkTraining we will not configure the head which results in
6625                                     // TDRs if any modset happens after this.
6626                                     //
6627                                     hal->setTestResponse(true);
6628                                     if (!train(lc, false))
6629                                         train(lc, true);
6630                                     disableFlush();
6631                                     // Don't force/commit. Only keep the request.
6632                                     setPreferredLinkConfig(lc, false, false);
6633                                 }
6634                             }
6635                             else // linkconfig is not supporting bandwidth. Fallback to default edid and notify DD.
6636                             {
6637                                 // override the device with fallback edid and notify a bw change to DD.
6638                                 DP_LOG(("DP> Compliance: Switching to compliance fallback EDID after IMP failure."));
6639                                 dev->switchToComplianceFallback();
6640 
6641                                 DP_LOG(("DP> Compliance: Notifying bandwidth change to DD after IMP failure."));
6642                                 // notify a bandwidth change to DD
6643                                 sink->bandwidthChangeNotification(dev, true);
6644                             }
6645                         }
6646                         else
6647                         {
6648                             hal->setTestResponse(true);
6649                             DP_LOG(("DP> Compliance: Link Training when the head is not attached."));
6650                             if (!train(lc, false))
6651                                 train(lc, true);
6652                         }
6653                     }
6654                 }
6655             }
6656         }
6657 
6658         else if (hal->getPendingTestRequestPhyCompliance())
6659         {
6660             hal->setTestResponse(handlePhyPatternRequest());
6661         }
6662     }
6663 
6664     // Handle MCCS_IRQ
6665     if (hal->intteruptMCCS())
6666     {
6667         DP_LOG(("DP> MCCS_IRQ"));
6668         handleMCCSIRQ();
6669         hal->clearInterruptMCCS();
6670     }
6671 
6672     if (hal->getHdmiLinkStatusChanged())
6673     {
6674         DP_LOG(("DP> HDMI Link Status Changed"));
6675         handleHdmiLinkStatusChanged();
6676     }
6677 
6678     if (hal->isPanelReplayErrorSet())
6679     {
6680         DP_LOG(("DP> Sink set Panel replay error"));
6681         handlePanelReplayError();
6682         hal->clearPanelReplayError();
6683     }
6684 
6685     //
6686     //  Check to make sure sink is not in D3 low power mode
6687     //  and interlane alignment is good, etc
6688     //  if not - trigger training
6689     //
6690     if (!isLinkInD3() && isLinkLost())
6691     {
6692         // If the link status of a VRR monitor has changed, we need to check the enablement again.
6693         if (hal->getLinkStatusChanged())
6694         {
6695             for (Device *i = enumDevices(0); i; i = enumDevices(i))
6696             {
6697                 DeviceImpl *dev = (DeviceImpl *)i;
6698 
6699                 if ((dev->plugged) && (dev->activeGroup != NULL) && (dev->isVrrMonitorEnabled()))
6700                 {
6701                     // Trigger the full enablement, if the monitor is in locked state.
6702                     NvU8 retries = VRR_MAX_RETRIES;
6703                     if (!dev->isVrrDriverEnabled())
6704                     {
6705                         DP_LOG(("DP> VRR enablement state is not synced. Re-enable it."));
6706                         do
6707                         {
6708                             if (!dev->startVrrEnablement())
6709                             {
6710                                 continue;
6711                             }
6712                             else
6713                                 break;
6714                         }while(--retries);
6715 
6716                         if (!retries)
6717                         {
6718                             DP_LOG(("DP> VRR enablement failed on multiple retries."));
6719                         }
6720                     }
6721                 }
6722             }
6723         }
6724 
6725         // If DPCD access is not available, skip trying to restore link configuration.
6726         hal->updateDPCDOffline();
6727         if (hal->isDpcdOffline())
6728         {
6729             return;
6730         }
6731 
6732         DP_LOG(("DP> Link not alive, Try to restore link configuration"));
6733 
6734         if (trainSingleHeadMultipleSSTLinkNotAlive(getActiveGroupForSST()))
6735         {
6736             return;
6737         }
6738         //save the previous highest assessed LC
6739         LinkConfiguration previousAssessedLC = highestAssessedLC;
6740 
6741         assessLink();
6742 
6743         //If the highest assessed LC has changed, send notification
6744         if(highestAssessedLC != previousAssessedLC)
6745         {
6746             DeviceImpl * dev = findDeviceInList(Address());
6747             if (dev)
6748             {
6749                 sink->bandwidthChangeNotification(dev, false);
6750             }
6751         }
6752     }
6753 }
6754 
6755 bool ConnectorImpl::detectSinkCountChange()
6756 {
6757     if (this->linkUseMultistream())
6758         return false;
6759 
6760     DeviceImpl * existingDev = findDeviceInList(Address());
6761     if (!existingDev)
6762         return false;
6763 
6764     // detect a zero to non-zero sink count change or vice versa
6765     bool hasSink = !!(hal->getSinkCount());
6766     return ((existingDev->videoSink || existingDev->audioSink) != hasSink);
6767 }
6768 
6769 bool ConnectorImpl::setPreferredLinkConfig(LinkConfiguration & lc, bool commit,
6770                                            bool force, LinkTrainingType trainType)
6771 {
6772     bool bEnteredFlushMode;
6773     Device *dev;
6774 
6775     dev = enumDevices(0);
6776     DeviceImpl * nativeDev = (DeviceImpl *)dev;
6777     if (preferredLinkConfig.lanes || preferredLinkConfig.peakRate || preferredLinkConfig.minRate)
6778         DP_ASSERT(0 && "Missing reset call for a preveious set preferred call");
6779 
6780     if (lc.bEnableFEC &&
6781         ((nativeDev && !nativeDev->isFECSupported()) || (!this->isFECSupported())))
6782     {
6783         DP_ASSERT(0 && "Client requested to enable FEC but either panel or GPU doesn't support FEC");
6784         return false;
6785     }
6786 
6787     if (!validateLinkConfiguration(lc))
6788     {
6789         DP_LOG(("Client requested bad LinkConfiguration."));
6790         return false;
6791     }
6792 
6793     preferredLinkConfig = lc;
6794     preferredLinkConfig.enhancedFraming = hal->getEnhancedFraming();
6795     preferredLinkConfig.multistream = this->linkUseMultistream();
6796     preferredLinkConfig.policy = this->linkPolicy;
6797     if (force)
6798     {
6799         // Do flushmode
6800         if (!(bEnteredFlushMode = this->enableFlush()))
6801             DP_ASSERT(0 && "Flush fails");
6802         if (this->train(preferredLinkConfig, false))
6803             activeLinkConfig = preferredLinkConfig;
6804         if (bEnteredFlushMode)
6805             this->disableFlush(true);
6806     }
6807     else
6808     {
6809         if (commit)
6810         {
6811             assessLink(trainType);
6812         }
6813     }
6814     return true;
6815 }
6816 
6817 bool ConnectorImpl::resetPreferredLinkConfig(bool force)
6818 {
6819     preferredLinkConfig = LinkConfiguration();
6820 
6821     if (force)
6822         assessLink();
6823     return true;
6824 }
6825 
6826 bool ConnectorImpl::isAcpiInitDone()
6827 {
6828     return (hal->getSupportsMultistream() ? false : bAcpiInitDone);
6829 }
6830 
6831 void ConnectorImpl::notifyAcpiInitDone()
6832 {
6833     Edid ddcReadEdid;
6834 
6835     // Initiate the EDID Read mechanism only if it is in SST mode & plugged
6836     if (!hal->getSupportsMultistream() && previousPlugged)
6837     {
6838         // Read EDID using RM Control call - NV0073_CTRL_CMD_SPECIFIC_GET_EDID_V2
6839         if (EdidReadSST(ddcReadEdid, auxBus, timer, false, true, main))
6840         {
6841             // Fill the data in device's ddcEdid & mark ACPI Init done
6842             for (Device * i = enumDevices(0); i; i=enumDevices(i))
6843             {
6844                 DP_LOG(("DPCONN> ACPI Init Done. DDC EDID Read completed!!"));
6845 
6846                 DeviceImpl * dev = (DeviceImpl*)i;
6847                 dev->ddcEdid = ddcReadEdid;
6848 
6849                 this->bAcpiInitDone = true;
6850                 break;
6851             }
6852         }
6853     }
6854 
6855     return;
6856 }
6857 
6858 bool ConnectorImpl::getHDCPAbortCodesDP12(NvU32 &hdcpAbortCodesDP12)
6859 {
6860     hdcpAbortCodesDP12 = 0;
6861 
6862     return false;
6863 }
6864 
6865 bool ConnectorImpl::hdcpValidateKsv(const NvU8 *ksv, NvU32 Size)
6866 {
6867 
6868     if (HDCP_KSV_SIZE <= Size)
6869     {
6870         NvU32 i, j;
6871         NvU32 count_ones = 0;
6872         for (i=0; i < HDCP_KSV_SIZE; i++)
6873         {
6874             for (j = 0; j < 8; j++)
6875             {
6876                 if (ksv[i] & (1 <<(j)))
6877                 {
6878                     count_ones++;
6879                 }
6880             }
6881         }
6882 
6883         if (count_ones == 20)
6884         {
6885             return true;
6886         }
6887     }
6888     return false;
6889 }
6890 
6891 void ConnectorImpl::cancelHdcpCallbacks()
6892 {
6893     this->isHDCPReAuthPending = false;
6894     this->isHDCPAuthTriggered = false;
6895     this->authRetries = 0;
6896 
6897     timer->cancelCallback(this, &tagHDCPReauthentication);      // Cancel any queue the auth callback.
6898     timer->cancelCallback(this, &tagDelayedHdcpCapRead);        // Cancel any HDCP cap callbacks.
6899 
6900 
6901     for (ListElement * i = activeGroups.begin(); i != activeGroups.end(); i = i->next)
6902     {
6903         GroupImpl * group = (GroupImpl *)i;
6904         group->cancelHdcpCallbacks();
6905     }
6906 }
6907 
6908 // Create a new Group
6909 Group * ConnectorImpl::newGroup()
6910 {
6911     Group * g = new GroupImpl(this);
6912     if (g)
6913     {
6914         inactiveGroups.insertBack((GroupImpl*)g);
6915     }
6916     return g;
6917 }
6918 
6919 // Create a new Group
6920 Group * ConnectorImpl::createFirmwareGroup()
6921 {
6922     Group * g = new GroupImpl(this, true);
6923     if (g)
6924     {
6925         inactiveGroups.insertBack((GroupImpl*)g);
6926     }
6927     return g;
6928 }
6929 
6930 // Shutdown and the destroy the connector manager
6931 void ConnectorImpl::destroy()
6932 {
6933     delete this;
6934 }
6935 
6936 void ConnectorImpl::createFakeMuxDevice(const NvU8 *buffer, NvU32 bufferSize)
6937 {
6938     if (!buffer)
6939         return;
6940 
6941     // Return immediately if DSC is not supported
6942     if(FLD_TEST_DRF(_DPCD14, _DSC_SUPPORT, _DSC_SUPPORT, _YES, buffer[0]) != 1)
6943         return;
6944 
6945     DeviceImpl * existingDev = findDeviceInList(Address());
6946 
6947     // Return immediately if we already have a device
6948     if (existingDev)
6949     {
6950         return;
6951     }
6952 
6953     DeviceImpl *newDev = new DeviceImpl(hal, this, NULL);
6954     if (!newDev)
6955     {
6956         return;
6957     }
6958 
6959     newDev->connectorType               = connectorDisplayPort;
6960     newDev->plugged                     = true;
6961     newDev->videoSink                   = true;
6962     newDev->bIsFakedMuxDevice           = true;
6963     newDev->bIsPreviouslyFakedMuxDevice = false;
6964 
6965     // Initialize DSC state
6966     newDev->dscCaps.bDSCSupported = true;
6967     newDev->dscCaps.bDSCDecompressionSupported = true;
6968     newDev->parseDscCaps(buffer, bufferSize);
6969     dpMemCopy(newDev->rawDscCaps, buffer, DP_MIN(bufferSize, 16));
6970     newDev->bDSCPossible = true;
6971     newDev->devDoingDscDecompression = newDev;
6972 
6973     populateAllDpConfigs();
6974     deviceList.insertBack(newDev);
6975     sink->newDevice(newDev);
6976     sink->notifyDetectComplete();
6977 }
6978 
6979 void ConnectorImpl::deleteFakeMuxDevice()
6980 {
6981     DeviceImpl * existingDev = findDeviceInList(Address());
6982     if (!existingDev)
6983         return;
6984 
6985     // If this is not a fake device then don't delete it
6986     if (!existingDev->isPreviouslyFakedMuxDevice())
6987         return;
6988 
6989     existingDev->markDeviceForDeletion();
6990     notifyLongPulse(false);
6991 
6992     return;
6993 }
6994 
6995 bool ConnectorImpl::getRawDscCaps(NvU8 *buffer, NvU32 bufferSize)
6996 {
6997     DeviceImpl * existingDev = findDeviceInList(Address());
6998     if (!existingDev)
6999         return false;
7000 
7001     return existingDev->getRawDscCaps(buffer, bufferSize);
7002 }
7003 
7004 bool ConnectorImpl::isMultiStreamCapable()
7005 {
7006     return main->hasMultistream();
7007 }
7008 
7009 bool ConnectorImpl::isFlushSupported()
7010 {
7011     return true;
7012 }
7013 
7014 bool ConnectorImpl::isStreamCloningEnabled()
7015 {
7016     return main->isStreamCloningEnabled();
7017 }
7018 
7019 bool ConnectorImpl::isFECSupported()
7020 {
7021     return main->isFECSupported();
7022 }
7023 
7024 bool ConnectorImpl::isFECCapable()
7025 {
7026     DeviceImpl *dev;
7027 
7028     for (Device * i = enumDevices(0); i; i = enumDevices(i))
7029     {
7030         dev = (DeviceImpl *)i;
7031         // If it's SST, or if it's the first connected branch.
7032         if (!this->linkUseMultistream() || dev->address.size() == 1)
7033         {
7034             return (dev->getFECSupport() && this->isFECSupported());
7035         }
7036     }
7037     return false;
7038 }
7039 
7040 NvU32 ConnectorImpl::maxLinkRateSupported()
7041 {
7042     return main->maxLinkRateSupported();
7043 }
7044 
7045 Connector * DisplayPort::createConnector
7046 (
7047     MainLink * main,
7048     AuxBus * aux,
7049     Timer * timer,
7050     Connector::EventSink * sink
7051 )
7052 {
7053     ConnectorImpl *connector = new ConnectorImpl(main, aux, timer, sink);
7054 
7055     if (connector == NULL || connector->constructorFailed) {
7056         delete connector;
7057         return NULL;
7058     }
7059 
7060     if (main->getRegkeyValue(NV_DP_REGKEY_ENABLE_OCA_LOGGING))
7061     {
7062         main->retrieveRingBuffer(LOG_CALL, MAX_RECORD_COUNT);
7063         main->retrieveRingBuffer(ASSERT_HIT, MAX_RECORD_COUNT);
7064     }
7065     return connector;
7066 }
7067 
7068 void ConnectorImpl::setAllowMultiStreaming(bool bAllowMST)
7069 {
7070     //
7071     // hal->getMultiStreamCapOverride() returns true, if MST cap has been
7072     // overridden to SST.
7073     //
7074     if (!hal->getMultiStreamCapOverride() == bAllowMST)
7075         return;
7076 
7077     if (previousPlugged &&
7078         getSinkMultiStreamCap() &&
7079         !activeGroups.isEmpty() && linkUseMultistream() != bAllowMST)
7080     {
7081         DP_ASSERT(!"If connected sink is MST capable then:"
7082                    "Client should detach all active MST video/audio streams "
7083                    "before disallowing MST, vise-versa client should detach "
7084                    "active SST stream before allowing MST.");
7085     }
7086 
7087     //
7088     // Disable MST messaging, if client has disallowed MST;
7089     // notifyLongPulseInternal() enable back MST messaging when client
7090     // allow MST.
7091     //
7092     if (previousPlugged && linkUseMultistream() && !bAllowMST)
7093         hal->setMessagingEnable(
7094             false /* _uprequestEnable */, true /* _upstreamIsSource */);
7095 
7096     hal->overrideMultiStreamCap(bAllowMST /* mstCapable */ );
7097 
7098     // Re-detect already connected sink, and to keep software state in sync
7099     if (previousPlugged && getSinkMultiStreamCap())
7100     {
7101         isHDCPAuthOn = isDP12AuthCap = false;
7102         notifyLongPulseInternal(true);
7103     }
7104 }
7105 
7106 bool ConnectorImpl::getAllowMultiStreaming(void)
7107 {
7108     //
7109     // hal->getMultiStreamCapOverride() returns true, if MST cap has been
7110     // overridden to SST.
7111     //
7112     return !hal->getMultiStreamCapOverride();
7113 }
7114 
7115 bool ConnectorImpl::getSinkMultiStreamCap(void)
7116 {
7117     return hal->getDpcdMultiStreamCap();
7118 }
7119 
7120 void ConnectorImpl::setDp11ProtocolForced()
7121 {
7122     if (!this->linkUseMultistream())
7123     {
7124         return;
7125     }
7126 
7127     this->notifyLongPulse(false);
7128     hal->setMessagingEnable(false, true);
7129     hal->setMultistreamLink(false);
7130     hal->overrideMultiStreamCap(false /*no mst*/);
7131     this->notifyLongPulse(true);
7132 }
7133 
7134 void ConnectorImpl::resetDp11ProtocolForced()
7135 {
7136     if (this->linkUseMultistream())
7137     {
7138         return;
7139     }
7140 
7141     this->notifyLongPulse(false);
7142     hal->overrideMultiStreamCap(true /*mst capable*/);
7143     this->notifyLongPulse(true);
7144 }
7145 
7146 bool ConnectorImpl::isDp11ProtocolForced()
7147 {
7148     return hal->getMultiStreamCapOverride();
7149 }
7150 
7151 bool ConnectorImpl::getTestPattern(NV0073_CTRL_DP_TESTPATTERN * testPattern)
7152 {
7153     return (main->getDpTestPattern(testPattern));
7154 }
7155 
7156 bool ConnectorImpl::setTestPattern(NV0073_CTRL_DP_TESTPATTERN testPattern, NvU8 laneMask, NV0073_CTRL_DP_CSTM cstm, NvBool bIsHBR2, NvBool bSkipLaneDataOverride)
7157 {
7158     return (main->setDpTestPattern(testPattern, laneMask, cstm, bIsHBR2, bSkipLaneDataOverride));
7159 }
7160 
7161 bool ConnectorImpl::getLaneConfig(NvU32 *numLanes, NvU32 *data)
7162 {
7163     return (main->getDpLaneData(numLanes, data));
7164 }
7165 
7166 bool ConnectorImpl::setLaneConfig(NvU32 numLanes, NvU32 *data)
7167 {
7168     return (main->setDpLaneData(numLanes, data));
7169 }
7170 
7171 void ConnectorImpl::getCurrentLinkConfig(unsigned & laneCount, NvU64 & linkRate)
7172 {
7173     main->getLinkConfig(laneCount, linkRate);
7174 }
7175 
7176 unsigned ConnectorImpl::getPanelDataClockMultiplier()
7177 {
7178     LinkConfiguration linkConfig = getMaxLinkConfig();
7179     return getDataClockMultiplier(linkConfig.peakRatePossible, linkConfig.lanes);
7180 }
7181 
7182 unsigned ConnectorImpl::getGpuDataClockMultiplier()
7183 {
7184     unsigned laneCount;
7185     NvU64 linkRate;
7186     // Need to get the GPU caps, not monitor caps.
7187     linkRate = maxLinkRateSupported();
7188 
7189     laneCount = laneCount_4;
7190 
7191     return getDataClockMultiplier(linkRate, laneCount);
7192 }
7193 
7194 void ConnectorImpl::configurePowerState(bool bPowerUp)
7195 {
7196     main->configurePowerState(bPowerUp);
7197 }
7198 
7199 bool ConnectorImpl::readPsrState(vesaPsrState *psrState)
7200 {
7201     return hal->readPsrState(psrState);
7202 }
7203 
7204 void ConnectorImpl::readPsrCapabilities(vesaPsrSinkCaps *caps)
7205 {
7206     hal->readPsrCapabilities(caps);
7207 }
7208 
7209 bool ConnectorImpl::readPsrConfiguration(vesaPsrConfig *psrConfig)
7210 {
7211     return hal->readPsrConfiguration(psrConfig);
7212 }
7213 
7214 bool ConnectorImpl::updatePsrConfiguration(vesaPsrConfig config)
7215 {
7216     return hal->updatePsrConfiguration(config);
7217 }
7218 
7219 bool ConnectorImpl::readPsrDebugInfo(vesaPsrDebugStatus *psrDbgState)
7220 {
7221     return hal->readPsrDebugInfo(psrDbgState);
7222 }
7223 
7224 bool ConnectorImpl::writePsrErrorStatus(vesaPsrErrorStatus psrErr)
7225 {
7226     return hal->writePsrErrorStatus(psrErr);
7227 }
7228 
7229 bool ConnectorImpl::readPsrErrorStatus(vesaPsrErrorStatus *psrErr)
7230 {
7231     return hal->readPsrErrorStatus(psrErr);
7232 }
7233 
7234 bool ConnectorImpl::writePsrEvtIndicator(vesaPsrEventIndicator psrEvt)
7235 {
7236     return hal->writePsrEvtIndicator(psrEvt);
7237 }
7238 
7239 bool ConnectorImpl::readPsrEvtIndicator(vesaPsrEventIndicator *psrEvt)
7240 {
7241     return hal->readPsrEvtIndicator(psrEvt);
7242 }
7243 
7244 bool ConnectorImpl::updatePsrLinkState(bool bTrainLink)
7245 {
7246     bool bRet = true;
7247     if (bTrainLink)
7248     {
7249         // Bug 3438892 If the panel is turned off the reciever on its side,
7250         // force panel link on by writting 600 = 1
7251         this->hal->setDirtyLinkStatus(true);
7252         if (this->isLinkLost())
7253         {
7254             hal->setPowerState(PowerStateD0);
7255             return false;
7256         }
7257 
7258         // Check if Link config is valid
7259         if (!this->psrLinkConfig.isValid())
7260         {
7261             return false;
7262         }
7263         // Restore Link config/do Link Train
7264         bRet = setPreferredLinkConfig(this->psrLinkConfig, false, true, NORMAL_LINK_TRAINING);
7265     }
7266     else
7267     {
7268         // Save the link config
7269         this->psrLinkConfig = getActiveLinkConfig();
7270     }
7271     return bRet;
7272 }
7273 
7274 bool ConnectorImpl::readPrSinkDebugInfo(panelReplaySinkDebugInfo *prDbgInfo)
7275 {
7276     return hal->readPrSinkDebugInfo(prDbgInfo);
7277 }
7278 
7279 bool ConnectorImpl::handlePhyPatternRequest()
7280 {
7281 
7282     bool status = true;
7283     PatternInfo pattern_info;
7284 
7285     pattern_info.lqsPattern = hal->getPhyTestPattern();
7286 
7287     // Get lane count from most current link training
7288     unsigned requestedLanes = this->activeLinkConfig.lanes;
7289 
7290     if (pattern_info.lqsPattern == LINK_QUAL_80BIT_CUST)
7291     {
7292         hal->getCustomTestPattern((NvU8 *)&pattern_info.ctsmLower);
7293     }
7294 
7295     // send control call to rm for the pattern
7296     if (!main->physicalLayerSetTestPattern(&pattern_info))
7297     {
7298         DP_ASSERT(0 && "Could not set the PHY_TEST_PATTERN");
7299         status = false;
7300     }
7301     else
7302     {
7303         if (AuxRetry::ack != hal->setLinkQualPatternSet(pattern_info.lqsPattern, requestedLanes))
7304         {
7305             DP_ASSERT(0 && "Could not set the LINK_QUAL_PATTERN");
7306             status = false;
7307         }
7308     }
7309     return status;
7310 }
7311 
7312 //
7313 // This function is used to send dp test message.
7314 // requestSize indicates the buffer size pointed by pBuffer
7315 //
7316 DP_TESTMESSAGE_STATUS ConnectorImpl::sendDPTestMessage
7317 (
7318     void    *pBuffer,
7319     NvU32    requestSize,
7320     NvU32   *pDpStatus
7321 )
7322 {
7323     if (messageManager)
7324     {
7325         testMessage.setupTestMessage(messageManager, this);
7326         return testMessage.sendDPTestMessage(pBuffer, requestSize, pDpStatus);
7327     }
7328     else
7329     {
7330         return DP_TESTMESSAGE_STATUS_ERROR;
7331     }
7332 }
7333 
7334 //
7335 // This function is designed for user to call twcie. The first time with NULL of
7336 // pStreamIDs to get the number of streams.
7337 // The second time, user would call the function with allocated buffer.
7338 //
7339 DP_TESTMESSAGE_STATUS ConnectorImpl::getStreamIDs(NvU32 *pStreamIDs, NvU32 *pCount)
7340 {
7341     DP_TESTMESSAGE_STATUS ret;
7342 
7343     NvU32 streamCnt = activeGroups.size();
7344     if (NULL == pStreamIDs)
7345     {
7346         ret = DP_TESTMESSAGE_STATUS_SUCCESS;
7347     }
7348     else if (*pCount >= streamCnt)
7349     {
7350         NvU32 n = 0;
7351         for (ListElement * i = activeGroups.begin(); i != activeGroups.end(); i = i->next)
7352         {
7353             GroupImpl * group = (GroupImpl *)i;
7354             pStreamIDs[n++] = group->streamIndex;
7355         }
7356         ret = DP_TESTMESSAGE_STATUS_SUCCESS;
7357     }
7358     else
7359     {
7360         //buffer size not enough, the return value will be mapped and returned to nvapi
7361         ret = DP_TESTMESSAGE_STATUS_ERROR_INSUFFICIENT_INPUT_BUFFER;
7362     }
7363 
7364     *pCount = streamCnt;
7365 
7366     return ret;
7367 }
7368 
7369 void ConnectorImpl::notifyGPUCapabilityChange()
7370 {
7371     // Query current GPU capabilities.
7372     main->queryGPUCapability();
7373 }
7374 
7375 void ConnectorImpl::notifyHBR2WAREngage()
7376 {
7377     bool peakBwChanged = false;
7378     LinkConfiguration preLc = getMaxLinkConfig();
7379     // Update GPU capabilities
7380     this->notifyGPUCapabilityChange();
7381     LinkConfiguration postLc = getMaxLinkConfig();
7382 
7383     peakBwChanged = (preLc.peakRatePossible != postLc.peakRatePossible);
7384 
7385     if (this->previousPlugged && peakBwChanged)
7386     {
7387         // Set caps change status to make sure device becomes zombie
7388         this->bMitigateZombie = true;
7389 
7390         if (this->policyModesetOrderMitigation)
7391         {
7392             this->modesetOrderMitigation = true;
7393         }
7394         // NEED TO CHECK. MAY GO AFTER LONGPULSE TRUE ????
7395         // If multistream, delete the MST slots allocation in Branch device
7396         if (this->linkUseMultistream())
7397             this->deleteAllVirtualChannels();
7398 
7399         // Disconnect the device
7400         this->notifyLongPulse(false);
7401 
7402         // Connect the device again
7403         this->notifyLongPulse(true);
7404     }
7405 
7406 }
7407 
7408 bool ConnectorImpl::isLinkAwaitingTransition()
7409 {
7410     return this->linkAwaitingTransition;
7411 }
7412 
7413 void ConnectorImpl::configInit()
7414 {
7415     // Reset branch specific flags
7416     bKeepOptLinkAlive = 0;
7417     bNoFallbackInPostLQA = 0;
7418     LT2FecLatencyMs = 0;
7419     bDscCapBasedOnParent = false;
7420 }
7421 
7422