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