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