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