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