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