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