1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 1993-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /******************************* DisplayPort********************************\ 25 * * 26 * Module: dp_deviceimpl.cpp * 27 * DP device implementation * 28 * * 29 \***************************************************************************/ 30 31 #include "dp_connectorimpl.h" 32 #include "dp_deviceimpl.h" 33 #include "dp_auxdefs.h" 34 #include "dp_groupimpl.h" 35 #include "ctrl/ctrl0073/ctrl0073dp.h" 36 using namespace DisplayPort; 37 38 bool DeviceImpl::isMustDisconnect() 39 { 40 // 41 // Device is must disconnect if we're trying to make an SST<->MST transition 42 // 43 if ((this->isActive()) && connector->linkAwaitingTransition) 44 { 45 return true; 46 } 47 48 return false; 49 } 50 51 DeviceImpl::~DeviceImpl() 52 { 53 if (isDeviceHDCPDetectionAlive && deviceHDCPDetection) 54 { 55 delete deviceHDCPDetection; 56 deviceHDCPDetection = nullptr; 57 } 58 59 if (vrrEnablement) 60 { 61 delete vrrEnablement; 62 vrrEnablement = NULL; 63 } 64 65 // Unlink this node from its children 66 for (unsigned int i = 0; i < sizeof(children)/sizeof(*children); i++) 67 if (children[i]) 68 children[i]->parent = 0; 69 70 // Unlink this node from its parent when it's there 71 if (parent && (parent->children[this->address.tail()] == this)) 72 parent->children[this->address.tail()] = 0; 73 74 devDoingDscDecompression = NULL; 75 } 76 77 78 DeviceImpl::DeviceImpl(DPCDHAL * hal, ConnectorImpl * connector, DeviceImpl * parent) 79 : parent(parent), 80 hal(hal), 81 activeGroup(0), 82 connector(connector), 83 address(), 84 bVirtualPeerDevice(false), 85 plugged(false), 86 friendlyAux(this), 87 isHDCPCap(False), 88 isDeviceHDCPDetectionAlive(false), 89 deviceHDCPDetection(0), 90 vrrEnablement(0), 91 bIsFakedMuxDevice(false), 92 bIsPreviouslyFakedMuxDevice(false), 93 bisMarkedForDeletion(false), 94 bIgnoreMsaCap(false), 95 bIgnoreMsaCapCached(false), 96 bSdpExtCapable(Indeterminate), 97 bAsyncSDPCapable(Indeterminate), 98 bDscPassThroughColorFormatWar(false) 99 { 100 bandwidth.enum_path.dataValid = false; 101 shadow.plugged = false; 102 shadow.zombie = false; 103 shadow.cableOk = true; 104 shadow.hdcpCapDone = false; 105 shadow.highestAssessedLC = connector->highestAssessedLC; 106 dpMemZero(rawDscCaps, sizeof(rawDscCaps)); 107 } 108 109 bool DeviceImpl::isZombie() 110 { 111 // You can't be a zombie if nothing is attached 112 if (!(this->isActive())) 113 return false; 114 115 if (!plugged) 116 return true; 117 118 if (isMustDisconnect()) 119 return true; 120 121 if (!isMultistream()) 122 { 123 if (connector->bMitigateZombie) 124 return true; 125 126 return !connector->willLinkSupportModeSST(connector->highestAssessedLC, 127 ((GroupImpl*)activeGroup)->lastModesetInfo); 128 } 129 else 130 { 131 return !this->payloadAllocated; 132 } 133 } 134 135 bool DeviceImpl::isCableOk() 136 { 137 if (hal->isDpcdOffline()) 138 { 139 // Just say that the cable is ok since we do not have anything connected 140 return true; 141 } 142 else 143 { 144 return ! (connector->highestAssessedLC.peakRate < connector->getMaxLinkConfig().peakRate && 145 connector->highestAssessedLC.lanes < connector->getMaxLinkConfig().lanes); 146 } 147 } 148 149 bool DeviceImpl::isLogical() 150 { 151 if (this->address.size() == 0) 152 return false; 153 154 DP_ASSERT((this->address.tail() <= LOGICAL_PORT_END) && "Invalid port number"); 155 156 // Logical port numbers of a branching unit are from Port 0x08 up to Port 0xF 157 if (this->address.tail() >= LOGICAL_PORT_START) 158 return true; 159 160 return false; 161 } 162 163 bool DeviceImpl::isPendingNewDevice() 164 { 165 if (shadow.plugged == plugged) 166 return false; 167 168 if (!plugged) 169 return false; 170 171 // Delay the newDevice event till all enabled heads are not detached. 172 if (connector->policyModesetOrderMitigation && connector->modesetOrderMitigation) 173 return false; 174 175 return !connector->linkAwaitingTransition; 176 } 177 178 bool DeviceImpl::isPendingLostDevice() 179 { 180 // marked for lazy exit..to be done now. 181 if (complianceDeviceEdidReadTest && lazyExitNow) 182 return true; 183 184 if (isZombie()) 185 return false; 186 187 if (shadow.plugged == plugged) 188 return false; 189 190 return !plugged; 191 } 192 193 bool DeviceImpl::isPendingZombie() 194 { 195 if (isZombie() && !shadow.zombie) 196 return true; 197 else if (!isZombie() && shadow.zombie && plugged) 198 return (connector->policyModesetOrderMitigation ? false : true); 199 return false; 200 } 201 202 bool DeviceImpl::isPendingHDCPCapDone() 203 { 204 if ((isHDCPCap != Indeterminate) && !shadow.hdcpCapDone) 205 return true; 206 else 207 return false; 208 } 209 210 bool DeviceImpl::isPendingCableOk() 211 { 212 return isCableOk() != shadow.cableOk; 213 } 214 215 bool DeviceImpl::isPendingBandwidthChange() 216 { 217 return shadow.highestAssessedLC != connector->highestAssessedLC; 218 } 219 220 bool DeviceImpl::getI2cData(unsigned offset, NvU8 * buffer, unsigned sizeRequested, unsigned * sizeCompleted, bool bForceMot) 221 { 222 unsigned dataCompleted, sizeRemaining; 223 DisplayPort::AuxBus::status status; 224 Type transactionType; 225 226 if (!buffer || !sizeCompleted) 227 return false; 228 229 dataCompleted = 0; 230 *sizeCompleted = 0; 231 do 232 { 233 sizeRemaining = (sizeRequested - *sizeCompleted); 234 if ((this->address.size() < 2) && (sizeRemaining > NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE)) 235 { 236 237 // 238 // SST case 239 // if the transaction buffer is a multiple of 16 bytes (NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE). 240 // Break it to 16 bytes boundary (HW default) and the first transaction sets the middle of 241 // transaction bit (MOT). This will mark all the subsequent reads are all of a part of the 242 // same transaction (I2C restart). 243 // 244 status = transaction(AuxBus::read, AuxBus::i2cMot, offset, buffer + *sizeCompleted, 245 NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE, &dataCompleted); 246 } 247 else if (sizeRemaining > NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE) 248 { 249 250 // 251 // MST case 252 // For i2c transactions over MST devices, if the transaction buffer is divided into 253 // 16 bytes chunks, then read index keeps getting reset for subsequent 16B fetch. 254 // Refer Bug: 1233042. 255 // 256 status = transaction(AuxBus::read, AuxBus::i2cMot, offset, buffer + *sizeCompleted, 257 sizeRemaining, &dataCompleted); 258 } 259 else 260 { 261 // 262 // clear the MOT if it is a single transaction or the last bytes of 263 // a large, multiple of 16 bytes buffer (end of transaction). 264 // Note that for some customer specific needs they might force MOT bit 265 // when it shouldn't be set. So check if client forced the MOT bit and honour that. 266 // 267 transactionType = bForceMot ? AuxBus::i2cMot : AuxBus::i2c; 268 status = transaction(AuxBus::read, transactionType, offset, buffer + *sizeCompleted, 269 sizeRemaining, &dataCompleted); 270 } 271 272 if (status != AuxBus::success) 273 { 274 DP_LOG(("DPDEV> %s: Failed read transaction", __FUNCTION__)); 275 break; 276 } 277 278 if (dataCompleted == 0) 279 { 280 // Successfully read 0 bytes? Break out 281 break; 282 } 283 *sizeCompleted += dataCompleted; 284 } 285 while (*sizeCompleted < sizeRequested); 286 287 return (status == AuxBus::success); 288 } 289 290 bool DeviceImpl::setI2cData(unsigned offset, NvU8 * buffer, unsigned sizeRequested, unsigned * sizeCompleted, bool bForceMot) 291 { 292 unsigned dataCompleted, sizeRemaining; 293 DisplayPort::AuxBus::status status; 294 Type transactionType; 295 296 if (!buffer || !sizeCompleted) 297 return false; 298 299 dataCompleted = 0; 300 *sizeCompleted = 0; 301 302 // 303 // If the hop count is one, we're asking for DPCD to the root node. 304 // If hop count is zero, this is a DP 1.1 target. 305 // Hop Count Greater than or equal 2 is when we have a single or multiple branch 306 // device/s. This signifies REMOTE_I2C_WRITE transaction case. 307 // Here we should not divide the data to 16 byte boundary as if we 308 // do, the branch device will not know that it needs to set MOT=1. 309 // So we send the entire data up to a max payload of 255 Bytes. 310 // Please refer Bug 1964453 for more information. 311 // 312 if ((this->address.size() >= 2) && 313 (sizeRequested > NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE)) 314 { 315 status = transaction(AuxBus::write, AuxBus::i2cMot, offset, buffer, 316 sizeRequested, &dataCompleted); 317 318 if (status != AuxBus::success) 319 { 320 DP_LOG(("DPDEV> %s: Failed write transaction", __FUNCTION__)); 321 return false; 322 } 323 *sizeCompleted = dataCompleted; 324 DP_ASSERT(*sizeCompleted >= sizeRequested); 325 return (status == AuxBus::success); 326 } 327 328 do 329 { 330 sizeRemaining = (sizeRequested - *sizeCompleted); 331 if (sizeRemaining > NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE) 332 { 333 334 // 335 // if the transaction buffer is a multiple of 16 bytes (NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE). 336 // Break it to 16 bytes boundary (HW default) and the first transaction sets the middle of 337 // transaction bit (MOT). This will mark all the subsequent writes are all of a part of the 338 // same transaction (I2C restart). 339 // 340 status = transaction(AuxBus::write, AuxBus::i2cMot, offset, buffer + *sizeCompleted, 341 NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE, &dataCompleted); 342 } 343 else 344 { 345 // 346 // clear the MOT if it is a single transaction or the last bytes of 347 // a large, multiple of 16 bytes buffer (end of transaction). 348 // Note that for some customer specific needs they might force MOT bit 349 // when it shouldn't be set. So check if client forced the MOT bit and honour that. 350 // 351 transactionType = bForceMot ? AuxBus::i2cMot : AuxBus::i2c; 352 status = transaction(AuxBus::write, transactionType, offset, buffer + *sizeCompleted, 353 sizeRemaining, &dataCompleted); 354 } 355 356 if (status != AuxBus::success) 357 { 358 DP_LOG(("DPDEV> %s: Failed write transaction", __FUNCTION__)); 359 break; 360 } 361 362 if (dataCompleted == 0) 363 { 364 // Successfully read 0 bytes? Break out 365 break; 366 } 367 *sizeCompleted += dataCompleted; 368 } while (*sizeCompleted < sizeRequested); 369 370 return (status == AuxBus::success); 371 } 372 373 AuxBus::status DeviceImpl::getDpcdData(unsigned offset, NvU8 * buffer, 374 unsigned sizeRequested, 375 unsigned * sizeCompleted, 376 unsigned * pNakReason) 377 { 378 if (!buffer || !sizeCompleted) 379 { 380 // default param may be NULL 381 if (pNakReason) *pNakReason = NakUndefined; 382 return AuxBus::nack; 383 } 384 385 // 386 // Remote DPCD doesn't work for Peer Device 4 i.e. DP-to-Legacy Dongle. 387 // But if a virtual DP peer device with Protocol Converter functionality 388 // populates the DPCD_Revision field of the LINK_ADDRESS Message reply 389 // then allow DPCD transaction 390 // 391 if ((this->peerDevice == Dongle) && (this->dpcdRevisionMajor == 0)) 392 { 393 if (pNakReason) *pNakReason = NakBadParam; 394 return AuxBus::nack; 395 } 396 397 return (transaction(AuxBus::read, AuxBus::native, offset, buffer, 398 sizeRequested, sizeCompleted, pNakReason)); 399 } 400 401 AuxBus::status DeviceImpl::setDpcdData(unsigned offset, NvU8 * buffer, 402 unsigned sizeRequested, 403 unsigned * sizeCompleted, 404 unsigned * pNakReason) 405 { 406 if (!buffer || !sizeCompleted) 407 { 408 // default param may be NULL 409 if (pNakReason) *pNakReason = NakUndefined; 410 return AuxBus::nack; 411 } 412 413 // 414 // Remote DPCD doesn't work for Peer Device 4 i.e. DP-to-Legacy Dongle 415 // But if a virtual DP peer device with Protocol Converter functionality 416 // populates the DPCD_Revision field of the LINK_ADDRESS Message reply 417 // then allow DPCD transaction 418 // 419 if ((this->peerDevice == Dongle) && (this->dpcdRevisionMajor == 0)) 420 { 421 if (pNakReason) *pNakReason = NakBadParam; 422 return AuxBus::nack; 423 } 424 425 return (transaction(AuxBus::write, AuxBus::native, offset, buffer, 426 sizeRequested, sizeCompleted, pNakReason)); 427 } 428 429 AuxBus::status DeviceImpl::queryFecData(NvU8 *fecStatus, NvU16 **fecErrorCount, NvU32 flags) 430 { 431 if (!fecStatus || !fecErrorCount) 432 { 433 return AuxBus::nack; 434 } 435 436 return (fecTransaction(fecStatus, fecErrorCount, flags)); 437 } 438 439 DscCaps DeviceImpl::getDscCaps() 440 { 441 return dscCaps; 442 } 443 444 // 445 // This function returns the device itself or its parent device that is doing 446 // DSC decompression for it. 447 // 448 Device* DeviceImpl::getDevDoingDscDecompression() 449 { 450 return devDoingDscDecompression; 451 } 452 453 bool DeviceImpl::getRawDscCaps(NvU8 *buffer, NvU32 bufferSize) 454 { 455 if (bufferSize < sizeof(rawDscCaps)) 456 return false; 457 458 dpMemCopy(buffer, &rawDscCaps, sizeof(rawDscCaps)); 459 return true; 460 } 461 462 AuxBus::status DeviceImpl::transaction(Action action, Type type, int address, 463 NvU8 * buffer, unsigned sizeRequested, 464 unsigned * sizeCompleted, 465 unsigned * pNakReason, 466 NvU8 offset, NvU8 nWriteTransactions) 467 { 468 // In case of default implementation, the reason for transaction failure 469 // must be stored somewhere 470 unsigned defaultReason; 471 if (!pNakReason) pNakReason = &defaultReason; 472 // default failure reason is undefined 473 *pNakReason = NakUndefined; 474 475 if (type == AuxBus::i2c || type == AuxBus::i2cMot) 476 { 477 address >>= 1; // right shifted DDC Address (request identifier in spec) 478 } 479 480 // If the hop count is one, we're asking for DPCD to the root node. 481 // If hop count is zero, this is a DP 1.1 target. 482 if (this->address.size() >= 2) 483 { 484 NakData nak; 485 486 if (connector == NULL || connector->messageManager == NULL) 487 { 488 return AuxBus::nack; 489 } 490 491 if (action == AuxBus::read && type == AuxBus::native) 492 { 493 RemoteDpcdReadMessage read; 494 read.set(this->address.parent(), this->address.tail(), address, sizeRequested); 495 if (!connector->messageManager->send(&read, nak)) { 496 // Copy reason back to caller 497 *pNakReason = nak.reason; 498 // Translate the DPCD error codes 499 if (nak.reason == NakDefer) 500 return AuxBus::defer; 501 if (nak.reason == NakDpcdFail) 502 return AuxBus::nack; 503 504 // This isn't quite right. We're translating unknown messaging related 505 // failure cases into defers. This is done so that the client will retry the operation 506 return AuxBus::defer; 507 } 508 509 *sizeCompleted = read.replyNumOfBytesReadDPCD(); 510 511 if (*sizeCompleted > sizeRequested) { 512 DP_LOG(("DPDEV> DPCD Read return more data than requested. Clamping buffer to requested size!")); 513 *sizeCompleted = sizeRequested; 514 } 515 516 dpMemCopy(buffer, read.replyGetData(), *sizeCompleted); 517 518 return AuxBus::success; 519 } 520 else if ((action == AuxBus::read) && ((type == AuxBus::i2c) || (type == AuxBus::i2cMot))) 521 { 522 bool isNoStopBit = (type == AuxBus::i2cMot) ? 1:0; 523 RemoteI2cReadMessage remoteI2cRead; 524 I2cWriteTransaction i2cWriteTransactions[1]; 525 i2cWriteTransactions[0] = I2cWriteTransaction(address, 526 0, 527 &offset, 528 isNoStopBit); 529 530 if (nWriteTransactions > 1) 531 { 532 DP_LOG(("DPDEV> Set function will fail for transactions > 1, please incraease the array size!")); 533 return AuxBus::nack; 534 } 535 536 remoteI2cRead.set(this->address.parent(), // topology Address 537 nWriteTransactions, // number of write transactions 538 this->address.tail(), // port of Device 539 i2cWriteTransactions, // list of write transactions 540 address, // right shifted DDC Address (request identifier in spec) 541 sizeRequested); // requested size 542 543 if (!connector->messageManager->send(&remoteI2cRead, nak)) { 544 // Copy reason back to caller 545 *pNakReason = nak.reason; 546 // Translate the DPCD error codes 547 if (nak.reason == NakI2cNak) 548 return AuxBus::nack; 549 550 // This isn't quite right. We're translating unknown messaging related 551 // failure cases into defers. This is done so that the client will retry the operation 552 return AuxBus::defer; 553 } 554 555 *sizeCompleted = remoteI2cRead.replyNumOfBytesReadI2C(); 556 557 if (*sizeCompleted > sizeRequested) { 558 DP_LOG(("DPDEV> I2C Read return more data than requested. Clamping buffer to requested size!")); 559 *sizeCompleted = sizeRequested; 560 } 561 562 dpMemCopy(buffer, remoteI2cRead.replyGetI2CData(sizeCompleted), *sizeCompleted); 563 564 return AuxBus::success; 565 } 566 else if (action == AuxBus::write && type == AuxBus::native) 567 { 568 RemoteDpcdWriteMessage write; 569 write.set(this->address.parent(), this->address.tail(), address, sizeRequested, buffer); 570 571 if (!connector->messageManager->send(&write, nak)) { 572 // Copy reason back to caller 573 *pNakReason = nak.reason; 574 // Translate the DPCD error codes 575 if (nak.reason == NakDefer) 576 return AuxBus::defer; 577 if (nak.reason == NakDpcdFail) 578 return AuxBus::nack; 579 580 // This isn't quite right. We're translating unknown messaging related 581 // failure cases into defers. This is done so that the client will retry the operation 582 return AuxBus::defer; 583 } 584 585 *sizeCompleted = sizeRequested; 586 587 return AuxBus::success; 588 } 589 else if ((action == AuxBus::write) && ((type == AuxBus::i2c) || (type == AuxBus::i2cMot))) 590 { 591 RemoteI2cWriteMessage remoteI2cWrite; 592 593 remoteI2cWrite.set(this->address.parent(), // topology Address 594 this->address.tail(), // port of Device 595 address, // right shifted DDC Address (request identifier in spec) 596 sizeRequested, 597 buffer); 598 599 if (!connector->messageManager->send(&remoteI2cWrite, nak)) { 600 // Copy reason back to caller 601 *pNakReason = nak.reason; 602 // Translate the DPCD error codes 603 if (nak.reason == NakI2cNak) 604 return AuxBus::nack; 605 606 // This isn't quite right. We're translating unknown messaging related 607 // failure cases into defers. This is done so that the client will retry the operation 608 return AuxBus::defer; 609 } 610 611 *sizeCompleted = sizeRequested; 612 613 return AuxBus::success; 614 } 615 else 616 { 617 DP_ASSERT(0 && "Only aux native and i2c reads and writes supported"); 618 return AuxBus::nack; 619 } 620 } 621 else 622 { 623 return this->connector->auxBus->transaction(action, type, address, buffer, 624 sizeRequested, sizeCompleted, pNakReason); 625 } 626 } 627 628 unsigned DeviceImpl::transactionSize() 629 { 630 // 631 // Remote (DP 1.2) sinks can read much larger chunks at once due to messaging. 632 // 633 if (this->address.size() >= 2) 634 return 255; 635 else 636 return this->connector->auxBus->transactionSize(); 637 } 638 639 static AuxBus::status _QueryFecStatus 640 ( 641 DeviceImpl *bus, 642 NvU8 *pStatus 643 ) 644 { 645 AuxBus::status status = AuxBus::success; 646 647 NvU32 addr = NV_DPCD14_FEC_STATUS; 648 unsigned size = 1; 649 650 unsigned sizeCompleted = 0; 651 unsigned pNakReason = 0; 652 653 status = bus->getDpcdData(addr, pStatus, size, &sizeCompleted, &pNakReason); 654 655 if (status != AuxBus::success) 656 { 657 DP_LOG(("DP> Error querying FEC status!")); 658 return AuxBus::nack; 659 } 660 return AuxBus::success; 661 } 662 663 static AuxBus::status _QueryFecErrorCount 664 ( 665 DeviceImpl *bus, 666 NvU16 *pErrorCount 667 ) 668 { 669 AuxBus::status status = AuxBus::success; 670 NvU32 addr = NV_DPCD14_FEC_ERROR_COUNT; 671 unsigned size = 2; 672 673 unsigned sizeCompleted = 0; 674 NvU8 cnt[2] = {0, 0}; 675 unsigned pNakReason = 0; 676 677 status = bus->getDpcdData(addr, &cnt[0], size, &sizeCompleted, &pNakReason); 678 679 if (status != AuxBus::success) 680 { 681 DP_LOG(("DP> Error querying FEC error count!")); 682 return AuxBus::nack; 683 } 684 else 685 { 686 *pErrorCount = (((NvU16) cnt[1]) << (sizeof(NvU8) * 8)) | cnt[0]; 687 } 688 return AuxBus::success; 689 } 690 691 static AuxBus::status _WriteFecConfiguration 692 ( 693 DeviceImpl *bus, 694 NvU8 configuration 695 ) 696 { 697 AuxBus::status status = AuxBus::success; 698 699 NvU32 addr = NV_DPCD14_FEC_CONFIGURATION; 700 unsigned size = 1; 701 702 unsigned sizeCompleted = 0; 703 unsigned pNakReason = 0; 704 705 status = bus->setDpcdData(addr, &configuration, size, &sizeCompleted, &pNakReason); 706 707 if (status != AuxBus::success) 708 { 709 DP_LOG(("DP> Error setting FEC configuration!")); 710 return AuxBus::nack; 711 } 712 return AuxBus::success; 713 } 714 715 AuxBus::status DeviceImpl::fecTransaction(NvU8 *fecStatus, NvU16 **fecErrorCount, NvU32 flags) 716 { 717 AuxBus::status status; 718 // the capability needs to be checked first (bits 5:0 and 7 need to be set) 719 NvU8 data, lane, counter, laneData, offset; 720 if (!bFECSupported) 721 { 722 DP_LOG(("DP> FEC capability not correct!")); 723 return nack; 724 } 725 726 if (!bFECUncorrectedSupported) 727 { 728 // check if this counter is specified in the flags 729 if (FLD_TEST_DRF(_DP, _UNCORRECTED, _ERROR, _YES, flags)) 730 { 731 for (int i = 0; i < NV_DP_MAX_NUM_OF_LANES; i++) 732 { 733 for (int j = 0; j < NV_DP_ERROR_COUNTERS_PER_LANE; j++) 734 { 735 // specific error value for error 736 fecErrorCount[i][j] = NV_DP_FEC_ERROR_COUNT_INVALID; 737 } 738 } 739 DP_LOG(("DP> FEC capability not correct!")); 740 return success; 741 } 742 } 743 if (!bFECCorrectedSupported) 744 { 745 // check if this counter is specified in the flags 746 if (FLD_TEST_DRF(_DP, _CORRECTED, _ERROR, _YES, flags)) 747 { 748 for (int i = 0; i < NV_DP_MAX_NUM_OF_LANES; i++) 749 { 750 for (int j = 0; j < NV_DP_ERROR_COUNTERS_PER_LANE; j++) 751 { 752 // specific error value for error 753 fecErrorCount[i][j] = NV_DP_FEC_ERROR_COUNT_INVALID; 754 } 755 } 756 DP_LOG(("DP> FEC capability not correct!")); 757 return success; 758 } 759 } 760 if (!bFECBitSupported) 761 { 762 // check if this counter is specified in the flags 763 if (FLD_TEST_DRF(_DP, _BIT, _ERROR, _YES, flags)) 764 { 765 for (int i = 0; i < NV_DP_MAX_NUM_OF_LANES; i++) 766 { 767 for (int j = 0; j < NV_DP_ERROR_COUNTERS_PER_LANE; j++) 768 { 769 // specific error value for error 770 fecErrorCount[i][j] = NV_DP_FEC_ERROR_COUNT_INVALID; 771 } 772 } 773 DP_LOG(("DP> FEC capability not correct!")); 774 return success; 775 } 776 } 777 if (!bFECParityBlockSupported) 778 { 779 // check if this counter is specified in the flags 780 if (FLD_TEST_DRF(_DP, _PARITY_BLOCK, _ERROR, _YES, flags)) 781 { 782 for (int i = 0; i < NV_DP_MAX_NUM_OF_LANES; i++) 783 { 784 for (int j = 0; j < NV_DP_ERROR_COUNTERS_PER_LANE; j++) 785 { 786 // specific error value for error 787 fecErrorCount[i][j] = NV_DP_FEC_ERROR_COUNT_INVALID; 788 } 789 } 790 DP_LOG(("DP> FEC capability not correct!")); 791 return success; 792 } 793 } 794 if (!bFECParitySupported) 795 { 796 // check if this counter is specified in the flags 797 if (FLD_TEST_DRF(_DP, _PARITY_BIT, _ERROR, _YES, flags)) 798 { 799 for (int i = 0; i < NV_DP_MAX_NUM_OF_LANES; i++) 800 { 801 for (int j = 0; j < NV_DP_ERROR_COUNTERS_PER_LANE; j++) 802 { 803 // specific error value for error 804 fecErrorCount[i][j] = NV_DP_FEC_ERROR_COUNT_INVALID; 805 } 806 } 807 DP_LOG(("DP> FEC capability not correct!")); 808 return success; 809 } 810 } 811 812 status = _QueryFecStatus(this, fecStatus); 813 if(status != AuxBus::success) 814 { 815 return status; 816 } 817 // setting configuration for querying error counters for every lane 818 for (lane = NV_DPCD14_FEC_CONFIGURATION_LANE_SELECT_LANE_0; lane < connector->activeLinkConfig.lanes; lane++) 819 { 820 // keeping FEC ready bit 821 laneData = DRF_DEF(_DPCD14, _FEC_CONFIGURATION, _FEC_READY, _YES); 822 // selecting specific lane 823 laneData |= DRF_NUM(_DPCD14, _FEC_CONFIGURATION, _LANE_SELECT, lane); 824 // setting configuration for querying all the error counters for a specific lane 825 for (counter = NV_DPCD14_FEC_CONFIGURATION_FEC_ERROR_COUNT_SEL_UNCORRECTED_BLOCK_ERROR_COUNT; 826 counter <= NV_DPCD14_FEC_CONFIGURATION_FEC_ERROR_COUNT_SEL_PARITY_BIT_ERROR_COUNT; counter++) 827 { 828 // address function for the current register (in the matrix registers start from 0 and in the bit mask from 1) 829 offset = counter - 1; 830 // if flag for corresponding register is not set skip querying 831 if ((flags & NVBIT(offset)) == 0) continue; 832 // selecting specific counter 833 data = laneData | DRF_NUM(_DPCD14, _FEC_CONFIGURATION, _FEC_ERROR_COUNT_SEL, counter) ; 834 status = _WriteFecConfiguration(this, data); 835 if (status != AuxBus::success) 836 { 837 return status; 838 } 839 // reading specific error counter register based on address function 840 status = _QueryFecErrorCount(this, fecErrorCount[lane] + offset); 841 if (status != AuxBus::success) 842 { 843 return status; 844 } 845 } 846 } 847 return AuxBus::success; 848 } 849 850 // Apply DPCD overrides if required 851 void DeviceImpl::dpcdOverrides() 852 { 853 if (this->parent) 854 { 855 // 856 // Device is behind a branch. SW can't perform overrides as branch will 857 // handle link training the device not source. Also hal can only override 858 // capability of sink, not the individual device behind the branch. 859 // 860 return; 861 } 862 if (processedEdid.WARFlags.overrideMaxLaneCount) 863 { 864 hal->overrideMaxLaneCount(processedEdid.WARData.maxLaneCount); 865 } 866 if (processedEdid.WARFlags.skipCableBWCheck) 867 { 868 hal->skipCableBWCheck(processedEdid.WARData.maxLaneAtHighRate, 869 processedEdid.WARData.maxLaneAtLowRate); 870 } 871 if (processedEdid.WARFlags.overrideOptimalLinkCfg) 872 { 873 LinkRate optimalLinkRate = 0; 874 875 switch(processedEdid.WARData.optimalLinkRate) 876 { 877 case 0x6: 878 optimalLinkRate = RBR; 879 break; 880 case 0xa: 881 optimalLinkRate = HBR; 882 break; 883 case 0x14: 884 optimalLinkRate = HBR2; 885 break; 886 case 0x1E: 887 optimalLinkRate = HBR3; 888 break; 889 default: 890 optimalLinkRate = RBR; 891 DP_LOG(("DP-DEV> Invalid link rate supplied. Falling back to RBR")); 892 break; 893 } 894 hal->overrideOptimalLinkCfg(optimalLinkRate, processedEdid.WARData.optimalLaneCount); 895 } 896 } 897 898 void DeviceImpl::applyOUIOverrides() 899 { 900 // For now we only need this for Synaptic branch. 901 if ((this->peerDevice == DownstreamBranch) || 902 (this->peerDevice == UpstreamSourceOrSSTBranch)) 903 { 904 NvU8 buffer[16] = {0}; 905 unsigned size = 13; // Read 0x500 ~ 0x50C 906 unsigned sizeCompleted = 0; 907 unsigned nakReason = NakUndefined; 908 909 // 910 // Synaptic branch claims it supports MSA override, but some older firmware has problems 911 // on their decoder. We need to disable the feature in that case. 912 // 913 if (AuxBus::success != this->getDpcdData(NV_DPCD_BRANCH_IEEE_OUI, &buffer[0], 914 size, &sizeCompleted, &nakReason)) 915 return; 916 917 // Check Branch IEEE_OUI (0x500h~0x502h) is Synaptic IEEE_OUI (0x90, 0xCC, 0x24) 918 if ((buffer[0] == 0x90) && (buffer[1] == 0xCC) && (buffer[2] == 0x24)) 919 { 920 // Check if Device Identification String (0x503~0x506) is "SYNA" 921 if ((buffer[3] == 0x53) && (buffer[4] == 0x59) && (buffer[5] == 0x4E) && (buffer[6] == 0x41)) 922 { 923 // For Synaptic VMM5331 and VMM5320, it only support MSA-Over-MST for DP after Firmware 5.4.5 924 if (buffer[7] == 0x53) 925 { 926 // 927 // This flag will be checked only in DSC Pass through cases (MST). 928 // All Synaptics VMM53XX chips which support pass through can only support 929 // color formats that are listed in 0x69h even in pass through mode. 930 // 931 this->bDscPassThroughColorFormatWar = true; 932 933 if ((buffer[8] == 0x31) || (buffer[8] == 0x20)) 934 { 935 this->bSdpExtCapable = False; 936 937 // 938 // Check firmware version 939 // 0x50A: FW/SW Major Revision. 940 // 0x50B: FW/SW Minor Revision. 941 // 0x50C: Build Number. 942 // 943 if ((buffer[10] >= 0x06) || 944 ((buffer[10] == 0x05) && (buffer[11] >= 0x05)) || 945 ((buffer[10] == 0x05) && (buffer[11] == 0x04) && (buffer[12] >= 0x05))) 946 { 947 this->bSdpExtCapable = True; 948 } 949 } 950 } 951 } 952 } 953 954 } 955 } 956 957 bool DeviceImpl::getAsyncSDPSupported() 958 { 959 NvU8 byte = 0; 960 unsigned size = 1; 961 unsigned sizeCompleted; 962 unsigned nakReason = NakUndefined; 963 // 964 // On faked mux devices, we cannot check if the device has 965 // the capability as we don't have access to aux. 966 // 967 if (this->isFakedMuxDevice()) 968 { 969 return false; 970 } 971 // If the capability is queried/set already. 972 if (this->bAsyncSDPCapable != Indeterminate) 973 { 974 return (this->bAsyncSDPCapable == True); 975 } 976 // Check device capabilities first. 977 if (AuxBus::success != this->getDpcdData(NV_DPCD_DOWN_STREAM_PORT, &byte, 978 size, &sizeCompleted, &nakReason) || 979 (FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _NO, byte))) 980 { 981 this->bAsyncSDPCapable = False; 982 return false; 983 } 984 if (AuxBus::success != this->getDpcdData(NV_DPCD14_DPRX_FEATURE_ENUM_LIST, &byte, 985 size, &sizeCompleted, &nakReason) || 986 (FLD_TEST_DRF(_DPCD14, _DPRX_FEATURE_ENUM_LIST, _ADAPTIVE_SYNC_SDP_SUPPORTED, _NO, byte))) 987 { 988 this->bAsyncSDPCapable = False; 989 return false; 990 } 991 if (this->isMultistream()) 992 { 993 // For MST devices, check root branch capability. 994 this->bAsyncSDPCapable = hal->getRootAsyncSDPSupported() ? True : False; 995 } 996 else 997 { 998 // For SST, it supports Async SDP once reaches here. 999 this->bAsyncSDPCapable = True; 1000 } 1001 return (this->bAsyncSDPCapable == True); 1002 } 1003 1004 bool DeviceImpl::getSDPExtnForColorimetrySupported() 1005 { 1006 DeviceImpl *targetDevice = NULL; 1007 DeviceImpl *parentDevice = NULL; 1008 1009 NvU8 byte = 0; 1010 unsigned size = 0; 1011 unsigned nakReason = NakUndefined; 1012 1013 // 1014 // On fakeed mux devices, we cannot check if the device has 1015 // the capability as we don't have access to aux. 1016 // 1017 if (this->isFakedMuxDevice()) 1018 { 1019 return false; 1020 } 1021 1022 // If the capability is queried/set already. 1023 if (this->bSdpExtCapable != Indeterminate) 1024 { 1025 return (this->bSdpExtCapable == True); 1026 } 1027 1028 if (!this->isMultistream()) 1029 { 1030 // If the device is directly connected to the source read the DPCD directly 1031 this->bSdpExtCapable = hal->getSDPExtnForColorimetry() ? True : False; 1032 return (this->bSdpExtCapable == True); 1033 } 1034 1035 // For MST devices 1036 switch (this->peerDevice) 1037 { 1038 case DownstreamBranch: 1039 case UpstreamSourceOrSSTBranch: 1040 { 1041 targetDevice = this; 1042 break; 1043 } 1044 case DownstreamSink: 1045 { 1046 // 1047 // When the device is type of DownstreamSink and with branch(es) 1048 // between GPU and it, query goes to the device and its parent 1049 // 1050 targetDevice = this; 1051 parentDevice = (DeviceImpl *)this->getParent(); 1052 break; 1053 } 1054 case Dongle: 1055 { 1056 // 1057 // Bug 2527026: When the device is type of dongle and with branch(es) 1058 // between GPU and it, query goes to its parent. 1059 // 1060 targetDevice = (DeviceImpl *)this->getParent(); 1061 break; 1062 } 1063 default: 1064 { 1065 DP_ASSERT(0 && "Unsupported Peer Type for SDP_EXT COLORIMETRY"); 1066 return false; 1067 break; 1068 } 1069 } 1070 1071 if (!targetDevice) 1072 { 1073 DP_ASSERT(0 && "targetDevice is invalid for SDP_EXT COLORIMETRY"); 1074 return false; 1075 } 1076 1077 // Send remote DPCD for devices behind the branch 1078 if ((AuxBus::success == targetDevice->getDpcdData(NV_DPCD_TRAINING_AUX_RD_INTERVAL, 1079 &byte, sizeof byte, &size, &nakReason)) && 1080 (FLD_TEST_DRF(_DPCD14, _TRAINING_AUX_RD_INTERVAL, _EXTENDED_RX_CAP, _YES, byte))) 1081 { 1082 byte = 0; 1083 size = 0; 1084 nakReason = NakUndefined; 1085 1086 if (AuxBus::success == targetDevice->getDpcdData(NV_DPCD14_EXTENDED_DPRX_FEATURE_ENUM_LIST, 1087 &byte, sizeof byte, &size, &nakReason)) 1088 { 1089 this->bSdpExtCapable = FLD_TEST_DRF(_DPCD14, 1090 _EXTENDED_DPRX_FEATURE_ENUM_LIST, 1091 _VSC_SDP_EXT_FOR_COLORIMETRY, 1092 _YES, byte) ? True : False; 1093 } 1094 } 1095 1096 if (parentDevice && (this->bSdpExtCapable == True)) 1097 { 1098 // 1099 // Do not override bSdpExtCapable for the sink. Although result won't 1100 // change but we can keep the value for debug purpose. 1101 // 1102 return parentDevice->getSDPExtnForColorimetrySupported(); 1103 } 1104 1105 return (this->bSdpExtCapable == True); 1106 } 1107 1108 bool DeviceImpl::getPanelFwRevision(NvU16 *revision) 1109 { 1110 NvU8 fwRevisionMajor = 0; 1111 NvU8 fwRevisionMinor = 0; 1112 unsigned size = 0; 1113 unsigned nakReason = NakUndefined; 1114 1115 if (!revision) 1116 { 1117 return false; 1118 } 1119 1120 *revision = 0; 1121 1122 // 1123 // On faked mux devices, we cannot check if the device has 1124 // the capability as we don't have access to aux. 1125 // 1126 if (this->isFakedMuxDevice()) 1127 { 1128 return false; 1129 } 1130 1131 if (AuxBus::success != this->getDpcdData(NV_DPCD14_FW_SW_REVISION_MAJOR, 1132 &fwRevisionMajor, sizeof(fwRevisionMajor), &size, &nakReason)) 1133 { 1134 return false; 1135 } 1136 1137 if (AuxBus::success != this->getDpcdData(NV_DPCD14_FW_SW_REVISION_MINOR, 1138 &fwRevisionMinor, sizeof(fwRevisionMinor), &size, &nakReason)) 1139 { 1140 return false; 1141 } 1142 1143 *revision = (fwRevisionMajor << 8) | fwRevisionMinor; 1144 1145 return true; 1146 } 1147 1148 bool DeviceImpl::isPowerSuspended() 1149 { 1150 bool bPanelPowerOn, bDPCDPowerStateD0; 1151 if (connector->main->isEDP()) 1152 { 1153 connector->main->getEdpPowerData(&bPanelPowerOn, &bDPCDPowerStateD0); 1154 return !bDPCDPowerStateD0; 1155 } 1156 return (connector->hal->getPowerState() == PowerStateD3); 1157 } 1158 1159 void DeviceImpl::setPanelPowerParams(bool bSinkPowerStateD0, bool bPanelPowerStateOn) 1160 { 1161 bool bPanelPowerOn, bDPCDPowerStateD0; 1162 GroupImpl * pGroupAttached = connector->getActiveGroupForSST(); 1163 1164 // 1165 // For single head dual SST mode, set the panel power params for the 1166 // secondary connector while updating the primary connector. 1167 // 1168 if (pGroupAttached && 1169 connector->pCoupledConnector && 1170 (pGroupAttached->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST) && 1171 (pGroupAttached->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY)) 1172 { 1173 return; 1174 } 1175 1176 if (connector->main->isEDP()) 1177 { 1178 connector->main->getEdpPowerData(&bPanelPowerOn, &bDPCDPowerStateD0); 1179 } 1180 else 1181 { 1182 bDPCDPowerStateD0 = (connector->hal->getPowerState() == PowerStateD0)? 1183 true : false; 1184 } 1185 1186 // Going to Suspend (D3) 1187 if (!bSinkPowerStateD0) 1188 { 1189 if (this->bypassDpcdPowerOff()) 1190 { 1191 DP_LOG(("DP-DEV> Bypassing 600h write for this display")); 1192 return; 1193 } 1194 1195 if (connector->main->isEDP()) 1196 { 1197 /* 1198 * If it's an eDP panel, the setPowerState call below will turn on LCD_POWER 1199 * if it's already off. So only call the function when panel power is on 1200 * and DPCD_SET_POWER is set to _D0. 1201 */ 1202 if (bPanelPowerOn && bDPCDPowerStateD0) 1203 { 1204 // monitor to be put to sleep 1205 if (connector->hal->setPowerState(PowerStateD3)) 1206 shadow.highestAssessedLC = connector->highestAssessedLC; 1207 } 1208 } 1209 else 1210 { 1211 1212 if (connector->pCoupledConnector) 1213 { 1214 // Put secondary connctor to sleep 1215 connector->pCoupledConnector->hal->setPowerState(PowerStateD3); 1216 } 1217 1218 // monitor to be put to sleep 1219 if (connector->hal->setPowerState(PowerStateD3)) 1220 { 1221 shadow.highestAssessedLC = connector->highestAssessedLC; 1222 } 1223 } 1224 // 1225 // If bPanelPowerStateOn is false and this 1226 // is not a multistream device, then shut down the main link. Some eDP 1227 // panels are known to need this in order to actually shut down. 1228 // 1229 if (!isMultistream() && !bPanelPowerStateOn) 1230 { 1231 if (connector->pCoupledConnector) 1232 { 1233 // configure power state on secondary 1234 connector->pCoupledConnector->main->configurePowerState(false); 1235 } 1236 connector->main->configurePowerState(false); 1237 } 1238 } 1239 else 1240 { 1241 if (connector->main->isEDP() && !bPanelPowerOn) 1242 { 1243 // Turn on the eDP panel if required. 1244 connector->main->configurePowerState(true); 1245 } 1246 // monitor to be brought out of sleep 1247 if (connector->hal->setPowerState(PowerStateD0)) 1248 { 1249 if (connector->pCoupledConnector) 1250 { 1251 // power up main link on secondary 1252 connector->pCoupledConnector->hal->setPowerState(PowerStateD0); 1253 } 1254 1255 // Mark linkStatus as dirty as we need to read linkStatus again since we are resuming a power state D0, link might have lost. 1256 connector->hal->setDirtyLinkStatus(true); 1257 if (connector->pCoupledConnector) 1258 { 1259 connector->pCoupledConnector->hal->setDirtyLinkStatus(true); 1260 } 1261 1262 if (connector->activeGroups.isEmpty()) 1263 { 1264 return; 1265 } 1266 if ((!connector->isLinkActive()) || 1267 (connector->main->isEDP() && !bPanelPowerOn) || 1268 (connector->isLinkLost()) || 1269 (!bDPCDPowerStateD0)) 1270 { 1271 // 1272 // If link is inactive, lost, or the panel was off before, then 1273 // assess Link. Note that this'll detach head if required. 1274 // 1275 if (pGroupAttached && 1276 pGroupAttached->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST) 1277 { 1278 // Special handling for single head dual SST cases 1279 connector->trainSingleHeadMultipleSSTLinkNotAlive(pGroupAttached); 1280 } 1281 else 1282 { 1283 connector->assessLink(); 1284 } 1285 } 1286 } 1287 else 1288 DP_ASSERT(0 && "Could not bring the monitor back from sleep."); 1289 } 1290 } 1291 1292 void DeviceImpl::switchToComplianceFallback() 1293 { 1294 Edid fallbackEdid; 1295 makeEdidFallback(fallbackEdid); 1296 this->processedEdid.resetData(); 1297 this->processedEdid = fallbackEdid; 1298 } 1299 1300 TriState DeviceImpl::hdcpAvailableHop() 1301 { 1302 return this->isHDCPCap; 1303 } 1304 1305 TriState DeviceImpl::hdcpAvailable() 1306 { 1307 if (isNativeDPCD()) 1308 { 1309 return this->hdcpAvailableHop(); 1310 } 1311 return False; 1312 } 1313 1314 void DeviceImpl::resetCacheInferredLink() 1315 { 1316 this->bandwidth.enum_path.dataValid = false; 1317 } 1318 1319 LinkConfiguration * DeviceImpl::inferLeafLink(unsigned * totalLinkSlots) 1320 { 1321 // update the EPR data 1322 if (!bandwidth.enum_path.dataValid) 1323 { 1324 if (plugged) 1325 { 1326 NakData nack; 1327 for (unsigned retries = 0; retries < 7; retries++) 1328 { 1329 EnumPathResMessage epr(getTopologyAddress().parent(), getTopologyAddress().tail(), true); 1330 bool sendStatus = connector->messageManager->send(&epr, nack); 1331 if (!sendStatus) 1332 { 1333 if (nack.reason == NakDefer || nack.reason == NakTimeout) 1334 continue; 1335 1336 bandwidth.enum_path.total = 0; 1337 bandwidth.enum_path.free = 0; 1338 bandwidth.enum_path.availableStreams = 0; 1339 break; 1340 } 1341 else 1342 { 1343 bandwidth.enum_path.total = epr.reply.TotalPBN; 1344 bandwidth.enum_path.free = epr.reply.FreePBN; 1345 bandwidth.enum_path.bPathFECCapable = epr.reply.bFECCapability; 1346 bandwidth.enum_path.availableStreams = epr.reply.availableStreams; 1347 1348 break; 1349 } 1350 } 1351 } 1352 else 1353 { 1354 bandwidth.enum_path.total = bandwidth.enum_path.free = 0; 1355 } 1356 1357 bandwidth.enum_path.dataValid = true; 1358 bandwidth.lastHopLinkConfig = LinkConfiguration(bandwidth.enum_path.total); 1359 // Update FEC support of the device after EPR 1360 this->getFECSupport(); 1361 } 1362 1363 if (totalLinkSlots) 1364 { 1365 *totalLinkSlots = bandwidth.lastHopLinkConfig.slotsForPBN(bandwidth.enum_path.total, true /*epr aware*/); 1366 1367 // 1368 // Override the totalLinkSlots returned to 63 only if peer device is 1369 // 2 (branch), since TS-0 will be used for MTP header. 1370 // Branch may return the total pbn corresponding to 64 timeslots. 1371 // 1372 if (*totalLinkSlots == 64 && peerDevice == DownstreamBranch) 1373 { 1374 *totalLinkSlots = 63; 1375 } 1376 } 1377 1378 return &bandwidth.lastHopLinkConfig; 1379 } 1380 1381 bool DeviceImpl::isActive() 1382 { 1383 DP_ASSERT(!activeGroup || activeGroup->isHeadAttached()); 1384 return activeGroup != NULL; 1385 } 1386 1387 bool DeviceImpl::getRawEpr(unsigned * totalEpr, unsigned * freeEpr, rawEprState eprState) 1388 { 1389 DP_ASSERT((totalEpr && freeEpr) && "Invalid arguments passed to function getRawEpr()"); 1390 bool status = true; 1391 *totalEpr = 0; 1392 *freeEpr = 0; 1393 1394 // If request has come for main link/Native branch device 1395 // return main link PBNs as "0" & return 1396 if (isNativeDPCD()) 1397 return status; 1398 1399 // Cached/Software state is queried 1400 if (eprState == software) 1401 { 1402 *totalEpr = bandwidth.enum_path.total; 1403 *freeEpr = bandwidth.enum_path.free; 1404 1405 return status; 1406 } 1407 1408 // Hardware state is queried. Send a new EPR message to get the current state 1409 EnumPathResMessage rawEpr(getTopologyAddress().parent(), getTopologyAddress().tail(), true); 1410 NakData nack; 1411 for (unsigned retries = 0; retries < 7; retries++) 1412 { 1413 bool sendStatus = connector->messageManager->send(&rawEpr, nack); 1414 if (!sendStatus) 1415 { 1416 status = false; 1417 if (nack.reason == NakDefer) 1418 continue; 1419 1420 DP_LOG(("DP-DEV> EPR message failed while getting RAW EPR")); 1421 1422 break; 1423 } 1424 else 1425 { 1426 *totalEpr = rawEpr.reply.TotalPBN; 1427 *freeEpr = rawEpr.reply.FreePBN; 1428 status = true; 1429 1430 break; 1431 } 1432 } 1433 1434 return status; 1435 } 1436 1437 unsigned DeviceImpl::getEDIDSize() const 1438 { 1439 // Return DDC EDID size only if we got a valid EDID there 1440 if (this->connector->isAcpiInitDone() && ddcEdid.isValidHeader()) 1441 { 1442 return ddcEdid.getEdidSize(); 1443 } 1444 else 1445 { 1446 return processedEdid.getEdidSize(); 1447 } 1448 } 1449 1450 bool DeviceImpl::getEDID(char * buffer, unsigned size) const 1451 { 1452 // 1453 // Return DDC EDID only if we got a valid EDID there 1454 // This has priority on regular EDID read from panel 1455 // 1456 if (this->connector->isAcpiInitDone() && ddcEdid.isValidHeader()) 1457 { 1458 if (size < ddcEdid.getEdidSize()) 1459 goto panelEdid; 1460 1461 dpMemCopy(buffer, ddcEdid.getBuffer()->getData(), ddcEdid.getEdidSize()); 1462 return true; 1463 } 1464 1465 panelEdid: 1466 // No EDID read from SBIOS. Return panel EDID now. 1467 if (size < processedEdid.getEdidSize()) 1468 return false; 1469 1470 dpMemCopy(buffer, processedEdid.getBuffer()->getData(), processedEdid.getEdidSize()); 1471 return true; 1472 } 1473 1474 unsigned DeviceImpl::getRawEDIDSize() const 1475 { 1476 // Return DDC EDID size only if we got a valid EDID there 1477 if (this->connector->isAcpiInitDone() && ddcEdid.isValidHeader()) 1478 { 1479 return ddcEdid.getEdidSize(); 1480 } 1481 else 1482 { 1483 return rawEDID.getEdidSize(); 1484 } 1485 } 1486 1487 bool DeviceImpl::getRawEDID(char * buffer, unsigned size) const 1488 { 1489 // 1490 // Return DDC EDID only if we got a valid EDID there 1491 // This has priority on regular EDID read from panel 1492 // 1493 if (this->connector->isAcpiInitDone() && ddcEdid.isValidHeader()) 1494 { 1495 if (size >= ddcEdid.getEdidSize()) 1496 { 1497 dpMemCopy(buffer, ddcEdid.getBuffer()->getData(), ddcEdid.getEdidSize()); 1498 return true; 1499 } 1500 } 1501 1502 // No EDID read from SBIOS. Return panel EDID now. 1503 if (size < rawEDID.getEdidSize()) 1504 return false; 1505 1506 dpMemCopy(buffer, rawEDID.getBuffer()->getData(), rawEDID.getEdidSize()); 1507 return true; 1508 } 1509 1510 bool DeviceImpl::startVrrEnablement() 1511 { 1512 bool ret = false; 1513 1514 if (vrrEnablement) 1515 { 1516 ret = vrrEnablement->start(); 1517 } 1518 1519 return ret; 1520 } 1521 1522 void DeviceImpl::resetVrrEnablement() 1523 { 1524 if (vrrEnablement) 1525 { 1526 vrrEnablement->reset(); 1527 } 1528 } 1529 1530 bool DeviceImpl::isVrrMonitorEnabled() 1531 { 1532 bool ret = false; 1533 1534 if (vrrEnablement) 1535 { 1536 ret = vrrEnablement->isMonitorEnabled(); 1537 } 1538 1539 return ret; 1540 } 1541 1542 bool DeviceImpl::isVrrDriverEnabled() 1543 { 1544 bool ret = false; 1545 1546 if (vrrEnablement) 1547 { 1548 ret = vrrEnablement->isDriverEnabled(); 1549 } 1550 1551 return ret; 1552 } 1553 1554 NvBool DeviceImpl::getDSCSupport() 1555 { 1556 NvU8 byte = 0; 1557 unsigned size = 0; 1558 unsigned nakReason = NakUndefined; 1559 Address::StringBuffer sb; 1560 DP_USED(sb); 1561 1562 dscCaps.bDSCSupported = false; 1563 1564 if(AuxBus::success == this->getDpcdData(NV_DPCD14_DSC_SUPPORT, 1565 &byte, sizeof(byte), &size, &nakReason)) 1566 { 1567 if (FLD_TEST_DRF(_DPCD14, _DSC_SUPPORT, _DSC_SUPPORT, _YES, byte)) 1568 { 1569 dscCaps.bDSCDecompressionSupported = true; 1570 } 1571 if (FLD_TEST_DRF(_DPCD20, _DSC_SUPPORT, _PASS_THROUGH_SUPPORT, _YES, byte)) 1572 { 1573 dscCaps.bDSCPassThroughSupported = true; 1574 } 1575 } 1576 1577 else 1578 { 1579 DP_LOG(("DP-DEV> DSC Support AUX READ failed for %s!", address.toString(sb))); 1580 } 1581 1582 if (dscCaps.bDSCDecompressionSupported || dscCaps.bDSCPassThroughSupported) 1583 { 1584 dscCaps.bDSCSupported = true; 1585 } 1586 1587 return dscCaps.bDSCSupported; 1588 } 1589 1590 bool DeviceImpl::isPanelReplaySupported() 1591 { 1592 return prCaps.panelReplaySupported; 1593 } 1594 1595 void DeviceImpl::getPanelReplayCaps() 1596 { 1597 NvU8 byte = 0; 1598 unsigned size = 0; 1599 unsigned nakReason = NakUndefined; 1600 1601 if (AuxBus::success == this->getDpcdData(NV_DPCD20_PANEL_REPLAY_CAPABILITY, 1602 &byte, sizeof(byte), &size, &nakReason)) 1603 { 1604 prCaps.panelReplaySupported = 1605 FLD_TEST_DRF(_DPCD20_PANEL, _REPLAY_CAPABILITY, _SUPPORTED, _YES, byte); 1606 } 1607 } 1608 1609 bool DeviceImpl::setPanelReplayConfig(panelReplayConfig prcfg) 1610 { 1611 NvU8 config = 0; 1612 unsigned size = 0; 1613 unsigned nakReason = NakUndefined; 1614 1615 if (prcfg.enablePanelReplay) 1616 { 1617 config = FLD_SET_DRF(_DPCD20_PANEL, _REPLAY_CONFIGURATION, 1618 _ENABLE_PR_MODE, _YES, config); 1619 } 1620 else 1621 { 1622 config = FLD_SET_DRF(_DPCD20_PANEL, _REPLAY_CONFIGURATION, 1623 _ENABLE_PR_MODE, _NO, config); 1624 } 1625 1626 if (AuxBus::success == this->setDpcdData(NV_DPCD20_PANEL_REPLAY_CONFIGURATION, 1627 &config, sizeof(config), &size, &nakReason)) 1628 { 1629 return true; 1630 } 1631 1632 return false; 1633 } 1634 1635 bool DeviceImpl::getPanelReplayStatus(PanelReplayStatus *pPrStatus) 1636 { 1637 NvU8 state = 0; 1638 unsigned size = 0; 1639 unsigned nakReason = NakUndefined; 1640 1641 if (pPrStatus == NULL) 1642 { 1643 DP_ASSERT(0); 1644 return false; 1645 } 1646 1647 if(AuxBus::success == this->getDpcdData(NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS, 1648 &state, sizeof(state), &size, &nakReason)) 1649 { 1650 switch (DRF_VAL(_DPCD20, _PANEL_REPLAY_AND_FRAME_LOCK_STATUS, _PR_STATUS, state)) 1651 { 1652 case NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS_PR_STATUS_STATE_0: 1653 pPrStatus->prState = PanelReplay_Inactive; 1654 break; 1655 1656 case NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS_PR_STATUS_STATE_1: 1657 pPrStatus->prState = PanelReplay_CaptureAndDisplay; 1658 break; 1659 1660 case NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS_PR_STATUS_STATE_2: 1661 pPrStatus->prState = PanelReplay_DisplayFromRfb; 1662 break; 1663 1664 default: 1665 pPrStatus->prState = PanelReplay_Undefined; 1666 break; 1667 } 1668 return true; 1669 } 1670 else 1671 { 1672 return false; 1673 } 1674 } 1675 bool DeviceImpl::getFECSupport() 1676 { 1677 NvU8 byte = 0; 1678 unsigned size = 0; 1679 unsigned nakReason = NakUndefined; 1680 1681 if(this->address.size() > 1) 1682 { 1683 bFECSupported = this->bandwidth.enum_path.bPathFECCapable; 1684 } 1685 1686 else if (AuxBus::success == this->getDpcdData(NV_DPCD14_FEC_CAPABILITY, 1687 &byte, sizeof(byte), &size, &nakReason)) 1688 { 1689 bFECSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _FEC_CAPABLE, _YES, byte); 1690 bFECUncorrectedSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _UNCORRECTED_BLOCK_ERROR_COUNT_CAPABLE, _YES, byte); 1691 bFECCorrectedSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _CORRECTED_BLOCK_ERROR_COUNT_CAPABLE, _YES, byte); 1692 bFECBitSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _BIT_ERROR_COUNT_CAPABLE, _YES, byte); 1693 bFECParityBlockSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _PARITY_BLOCK_ERROR_COUNT_CAPABLE, _YES, byte); 1694 bFECParitySupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _PARITY_ERROR_COUNT_CAPABLE, _YES, byte); 1695 } 1696 1697 return bFECSupported; 1698 } 1699 1700 NvBool DeviceImpl::isDSCSupported() 1701 { 1702 return dscCaps.bDSCSupported; 1703 } 1704 1705 NvBool DeviceImpl::isDSCDecompressionSupported() 1706 { 1707 return dscCaps.bDSCDecompressionSupported; 1708 } 1709 1710 NvBool DeviceImpl::isDSCPassThroughSupported() 1711 { 1712 return dscCaps.bDSCPassThroughSupported; 1713 } 1714 1715 NvBool DeviceImpl::isDSCPossible() 1716 { 1717 return this->bDSCPossible; 1718 } 1719 1720 bool DeviceImpl::isFECSupported() 1721 { 1722 return bFECSupported; 1723 } 1724 1725 bool DeviceImpl::parseDscCaps(const NvU8 *buffer, NvU32 bufferSize) 1726 { 1727 1728 if (bufferSize < 16) 1729 { 1730 DP_LOG((" DSC caps buffer must be greater than or equal to 16")); 1731 return false; 1732 } 1733 1734 if (FLD_TEST_DRF(_DPCD20, _DSC_SUPPORT, _PASS_THROUGH_SUPPORT, _YES, buffer[0x0])) 1735 { 1736 dscCaps.bDSCPassThroughSupported = true; 1737 } 1738 1739 dscCaps.versionMajor = DRF_VAL(_DPCD14, _DSC_ALGORITHM_REVISION, _MAJOR, buffer[0x1]); 1740 dscCaps.versionMinor = DRF_VAL(_DPCD14, _DSC_ALGORITHM_REVISION, _MINOR, buffer[0x1]); 1741 1742 dscCaps.rcBufferBlockSize = DRF_VAL(_DPCD14, _DSC_RC_BUFFER_BLOCK, _SIZE, buffer[0x2]); 1743 1744 dscCaps.rcBuffersize = DRF_VAL(_DPCD14, _DSC_RC_BUFFER, _SIZE, buffer[0x3]); 1745 1746 dscCaps.sliceCountSupportedMask = (((buffer[0xD]) << 8) | buffer[0x4]); 1747 if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_2, _SLICES_PER_SINK_24, _YES, buffer[0xD])) 1748 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_24; 1749 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_2, _SLICES_PER_SINK_20, _YES, buffer[0xD])) 1750 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_20; 1751 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_2, _SLICES_PER_SINK_16, _YES, buffer[0xD])) 1752 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_16; 1753 1754 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_12, _YES, buffer[0x4])) 1755 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_12; 1756 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_10, _YES, buffer[0x4])) 1757 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_10; 1758 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_8, _YES, buffer[0x4])) 1759 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_8; 1760 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_6, _YES, buffer[0x4])) 1761 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_6; 1762 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_4, _YES, buffer[0x4])) 1763 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_4; 1764 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_2, _YES, buffer[0x4])) 1765 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_2; 1766 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_1, _YES, buffer[0x4])) 1767 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_1; 1768 1769 if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _8, buffer[0x5])) 1770 { 1771 dscCaps.lineBufferBitDepth = 8; 1772 } 1773 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _9, buffer[0x5])) 1774 { 1775 dscCaps.lineBufferBitDepth = 9; 1776 } 1777 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _10, buffer[0x5])) 1778 { 1779 dscCaps.lineBufferBitDepth = 10; 1780 } 1781 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _11, buffer[0x5])) 1782 { 1783 dscCaps.lineBufferBitDepth = 11; 1784 } 1785 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _12, buffer[0x5])) 1786 { 1787 dscCaps.lineBufferBitDepth = 12; 1788 } 1789 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _13, buffer[0x5])) 1790 { 1791 dscCaps.lineBufferBitDepth = 13; 1792 } 1793 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _14, buffer[0x5])) 1794 { 1795 dscCaps.lineBufferBitDepth = 14; 1796 } 1797 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _15, buffer[0x5])) 1798 { 1799 dscCaps.lineBufferBitDepth = 15; 1800 } 1801 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _16, buffer[0x5])) 1802 { 1803 dscCaps.lineBufferBitDepth = 16; 1804 } 1805 1806 if(FLD_TEST_DRF(_DPCD14, _DSC_BLOCK_PREDICTION, _SUPPORT, _YES, buffer[0x6])) 1807 dscCaps.bDscBlockPredictionSupport = true; 1808 1809 unsigned maxBitsPerPixelLSB = DRF_VAL(_DPCD14, _DSC_MAXIMUM_BITS_PER_PIXEL_1, _LSB, buffer[0x7]); 1810 unsigned maxBitsPerPixelMSB = DRF_VAL(_DPCD14, _DSC_MAXIMUM_BITS_PER_PIXEL_2, _MSB, buffer[0x8]); 1811 1812 dscCaps.maxBitsPerPixelX16 = (maxBitsPerPixelMSB << 8) | maxBitsPerPixelLSB; 1813 1814 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _RGB, _YES, buffer[0x9])) 1815 dscCaps.dscDecoderColorFormatCaps.bRgb = true; 1816 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _YCbCr_444, _YES, buffer[0x9])) 1817 dscCaps.dscDecoderColorFormatCaps.bYCbCr444 = true; 1818 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _YCbCr_SIMPLE_422, _YES, buffer[0x9])) 1819 dscCaps.dscDecoderColorFormatCaps.bYCbCrSimple422 = true; 1820 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _YCbCr_NATIVE_422, _YES, buffer[0x9])) 1821 dscCaps.dscDecoderColorFormatCaps.bYCbCrNative422 = true; 1822 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _YCbCr_NATIVE_420, _YES, buffer[0x9])) 1823 dscCaps.dscDecoderColorFormatCaps.bYCbCrNative420 = true; 1824 1825 if (FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_DEPTH_CAPABILITIES, _12_BITS_PER_COLOR, _YES, buffer[0xa])) 1826 dscCaps.dscDecoderColorDepthMask |= DSC_BITS_PER_COLOR_MASK_12; 1827 if (FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_DEPTH_CAPABILITIES, _10_BITS_PER_COLOR, _YES, buffer[0xa])) 1828 dscCaps.dscDecoderColorDepthMask |= DSC_BITS_PER_COLOR_MASK_10; 1829 if (FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_DEPTH_CAPABILITIES, _8_BITS_PER_COLOR, _YES, buffer[0xa])) 1830 dscCaps.dscDecoderColorDepthMask |= DSC_BITS_PER_COLOR_MASK_8; 1831 1832 dscCaps.dscPeakThroughputMode0 = DRF_VAL(_DPCD14, _DSC_PEAK_THROUGHPUT, _MODE0, buffer[0xb]); 1833 dscCaps.dscPeakThroughputMode1 = DRF_VAL(_DPCD14, _DSC_PEAK_THROUGHPUT, _MODE1, buffer[0xb]); 1834 1835 unsigned numOfPixels = DRF_VAL(_DPCD14, _DSC_MAXIMUM_SLICE_WIDTH, _MAX, buffer[0xc]); 1836 dscCaps.dscMaxSliceWidth = numOfPixels * 320; 1837 1838 if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1_16, buffer[0xf])) 1839 { 1840 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1_16; 1841 } 1842 else if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1_8, buffer[0xf])) 1843 { 1844 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1_8; 1845 } 1846 else if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1_4, buffer[0xf])) 1847 { 1848 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1_4; 1849 } 1850 else if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1_2, buffer[0xf])) 1851 { 1852 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1_2; 1853 } 1854 else if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1, buffer[0xf])) 1855 { 1856 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1; 1857 } 1858 1859 return true; 1860 } 1861 1862 bool DeviceImpl::parseBranchSpecificDscCaps(const NvU8 *buffer, NvU32 bufferSize) 1863 { 1864 if (bufferSize < 3) 1865 { 1866 DP_LOG((" Branch DSC caps buffer must be greater than or equal to 3")); 1867 return false; 1868 } 1869 1870 dscCaps.branchDSCOverallThroughputMode0 = DRF_VAL(_DPCD14, _BRANCH_DSC_OVERALL_THROUGHPUT_MODE_0, _VALUE, buffer[0x0]); 1871 if (dscCaps.branchDSCOverallThroughputMode0 == 1) 1872 { 1873 dscCaps.branchDSCOverallThroughputMode0 = 680; 1874 } 1875 else if (dscCaps.branchDSCOverallThroughputMode0 >= 2) 1876 { 1877 dscCaps.branchDSCOverallThroughputMode0 = 600 + dscCaps.branchDSCOverallThroughputMode0 * 50; 1878 } 1879 1880 dscCaps.branchDSCOverallThroughputMode1 = DRF_VAL(_DPCD14, _BRANCH_DSC_OVERALL_THROUGHPUT_MODE_1, _VALUE, buffer[0x1]); 1881 if (dscCaps.branchDSCOverallThroughputMode1 == 1) 1882 { 1883 dscCaps.branchDSCOverallThroughputMode1 = 680; 1884 } 1885 else if (dscCaps.branchDSCOverallThroughputMode1 >= 2) 1886 { 1887 dscCaps.branchDSCOverallThroughputMode1 = 600 + dscCaps.branchDSCOverallThroughputMode1 * 50; 1888 } 1889 1890 dscCaps.branchDSCMaximumLineBufferWidth = DRF_VAL(_DPCD14, _BRANCH_DSC_MAXIMUM_LINE_BUFFER_WIDTH, _VALUE, buffer[0x2]); 1891 if (dscCaps.branchDSCMaximumLineBufferWidth != 0) 1892 { 1893 if (dscCaps.branchDSCMaximumLineBufferWidth >= 16) 1894 { 1895 dscCaps.branchDSCMaximumLineBufferWidth = dscCaps.branchDSCMaximumLineBufferWidth * 320; 1896 } 1897 else 1898 { 1899 dscCaps.branchDSCMaximumLineBufferWidth = 0; 1900 DP_LOG(("Value of branch DSC maximum line buffer width is invalid, so setting it to 0.")); 1901 } 1902 } 1903 return true; 1904 } 1905 1906 bool DeviceImpl::readAndParseDSCCaps() 1907 { 1908 // Allocate a buffer of 16 bytes to read DSC caps 1909 1910 unsigned sizeCompleted = 0; 1911 unsigned nakReason = NakUndefined; 1912 Address::StringBuffer sb; 1913 DP_USED(sb); 1914 1915 if(AuxBus::success != this->getDpcdData(NV_DPCD14_DSC_SUPPORT, 1916 &rawDscCaps[0], sizeof(rawDscCaps), &sizeCompleted, &nakReason)) 1917 { 1918 DP_LOG(("DP-DEV> Error querying DSC Caps on %s!", this->address.toString(sb))); 1919 return false; 1920 } 1921 1922 return parseDscCaps(&rawDscCaps[0], sizeof(rawDscCaps)); 1923 } 1924 1925 bool DeviceImpl::readAndParseBranchSpecificDSCCaps() 1926 { 1927 unsigned sizeCompleted = 0; 1928 unsigned nakReason = NakUndefined; 1929 NvU8 rawBranchSpecificDscCaps[3]; 1930 1931 if(AuxBus::success != this->getDpcdData(NV_DPCD14_BRANCH_DSC_OVERALL_THROUGHPUT_MODE_0, 1932 &rawBranchSpecificDscCaps[0], 1933 sizeof(rawBranchSpecificDscCaps), 1934 &sizeCompleted, &nakReason)) 1935 { 1936 return false; 1937 } 1938 1939 return parseBranchSpecificDscCaps(&rawBranchSpecificDscCaps[0], sizeof(rawBranchSpecificDscCaps)); 1940 } 1941 1942 void DeviceImpl::queryGUID2() 1943 { 1944 unsigned sizeCompleted = 0; 1945 unsigned nakReason = NakUndefined; 1946 Address::StringBuffer sb; 1947 DP_USED(sb); 1948 1949 if(AuxBus::success == this->getDpcdData(NV_DPCD14_GUID_2, &this->guid2.data[0], 1950 DPCD_GUID_SIZE, &sizeCompleted, &nakReason)) 1951 { 1952 if (!(this->guid2.isGuidZero())) 1953 { 1954 this->bVirtualPeerDevice = true; 1955 } 1956 } 1957 else 1958 { 1959 DP_LOG(("DP-DEV> Error querying GUID2 on %s!", this->address.toString(sb))); 1960 } 1961 } 1962 1963 bool DeviceImpl::getDscEnable(bool *pEnable) 1964 { 1965 AuxBus::status status = AuxBus::success; 1966 unsigned sizeCompleted = 0; 1967 unsigned pNakReason = 0; 1968 NvU8 byte = 0; 1969 1970 if (!pEnable || 1971 !this->isDSCPossible() || 1972 !this->devDoingDscDecompression || 1973 !this->devDoingDscDecompression->plugged) 1974 { 1975 return false; 1976 } 1977 1978 status = this->devDoingDscDecompression->getDpcdData(NV_DPCD14_DSC_ENABLE, 1979 &byte, 1980 sizeof byte, 1981 &sizeCompleted, 1982 &pNakReason); 1983 1984 if (status != AuxBus::success) 1985 { 1986 DP_LOG(("DP-DEV> Error querying DSC Enable State!")); 1987 return false; 1988 } 1989 1990 *pEnable = FLD_TEST_DRF(_DPCD14, _DSC_ENABLE, _SINK, _YES, byte); 1991 return true; 1992 } 1993 1994 void DeviceImpl::setDscDecompressionDevice(bool bDscCapBasedOnParent) 1995 { 1996 // Decide if DSC stream can be sent to new device 1997 this->bDSCPossible = false; 1998 this->devDoingDscDecompression = NULL; 1999 2000 if (this->multistream) 2001 { 2002 if ((this->peerDevice == Dongle) && 2003 (this->dpcdRevisionMajor != 0) && 2004 !bDscCapBasedOnParent) 2005 { 2006 // For Peer Type 4 device with LAM DPCD rev != 0.0, check only the device's own DSC capability. 2007 if (this->isDSCSupported()) 2008 { 2009 this->bDSCPossible = true; 2010 this->devDoingDscDecompression = this; 2011 } 2012 } 2013 else 2014 { 2015 // 2016 // Check the device's own and its parent's DSC capability. 2017 // - Sink device will do DSC cecompression when 2018 // 1. Sink device is capable of DSC decompression 2019 // 2. Sink is on a logical port (8-15) 2020 // 2021 // OR 2022 // 2023 // 1. Sink device is capable of DSC decompression 2024 // 2. Parent of sink is a Virtual Peer device 2025 // 3. Parent of sink supports DSC Pass through 2026 // 2027 // - Sink device's parent will do DSC decompression 2028 // 1. Above conditions are not true. 2029 // 2. Parent of sink supports DSC decompression. 2030 // 2031 if (this->isDSCSupported()) 2032 { 2033 if (this->isVideoSink() && this->getParent() != NULL) 2034 { 2035 if (this->isLogical()) 2036 { 2037 this->devDoingDscDecompression = this; 2038 this->bDSCPossible = true; 2039 } 2040 else if (this->parent->isVirtualPeerDevice() && 2041 this->parent->isDSCPassThroughSupported()) 2042 { 2043 // 2044 // This condition takes care of DSC capable sink devices 2045 // connected behind a DSC Pass through capable branch 2046 // 2047 this->devDoingDscDecompression = this; 2048 this->bDSCPossible = true; 2049 } 2050 else if (this->parent->isDSCDecompressionSupported()) 2051 { 2052 // 2053 // This condition takes care of DSC capable sink devices 2054 // connected behind a branch device that is not capable 2055 // of DSC pass through but can do DSC decompression. 2056 // 2057 this->bDSCPossible = true; 2058 this->devDoingDscDecompression = this->parent; 2059 } 2060 } 2061 else 2062 { 2063 if (this->isDSCDecompressionSupported()) 2064 { 2065 // This condition takes care of branch device capable of DSC decoding. 2066 this->devDoingDscDecompression = this; 2067 this->bDSCPossible = true; 2068 } 2069 } 2070 } 2071 else if (this->parent && this->parent->isDSCDecompressionSupported()) 2072 { 2073 // 2074 // This condition takes care of sink devices not capable of DSC 2075 // but parent is capable of DSC decompression. 2076 // 2077 this->bDSCPossible = true; 2078 this->devDoingDscDecompression = this->parent; 2079 } 2080 } 2081 } 2082 else 2083 { 2084 if (this->isDSCDecompressionSupported()) 2085 { 2086 this->bDSCPossible = true; 2087 this->devDoingDscDecompression = this; 2088 } 2089 } 2090 } 2091 2092 bool DeviceImpl::setDscEnable(bool enable) 2093 { 2094 NvU8 dscEnableByte = 0; 2095 NvU8 dscPassthroughByte = 0; 2096 unsigned size = 0; 2097 unsigned nakReason = NakUndefined; 2098 bool bCurrDscEnable = false; 2099 bool bDscPassThrough = false; 2100 AuxBus::status dscEnableStatus = AuxBus::success; 2101 AuxBus::status dscPassThroughStatus = AuxBus::success; 2102 Address::StringBuffer buffer; 2103 DP_USED(buffer); 2104 2105 if (!this->isDSCPossible() || !this->devDoingDscDecompression || 2106 !this->devDoingDscDecompression->plugged) 2107 { 2108 return false; 2109 } 2110 2111 if ((this->devDoingDscDecompression == this) && !this->isLogical() && !(this->peerDevice == Dongle) && this->parent != NULL) 2112 { 2113 // 2114 // If the device has a parent, that means the sink is on a MST link and 2115 // and on a MST link if DSC is possible on the path and devDoingDscDecompression 2116 // is the sink itself and sink is not on a logical port, then the parent should be 2117 // DSC Pass through capable. 2118 // 2119 bDscPassThrough = true; 2120 } 2121 2122 // 2123 // Get Current DSC Enable State 2124 // Ideally we don't need to check the current state but Synaptics DSC device, 2125 // which was used for inital DSC code developement did not follow spec and so 2126 // we have added this code. Overwriting the same value should not have any 2127 // impact as per the spec. Will remove this check once all DSC devices follow spec. 2128 // 2129 if (!getDscEnable(&bCurrDscEnable)) 2130 { 2131 DP_LOG(("DP-DEV> Not able to get DSC Enable State!")); 2132 return false; 2133 } 2134 2135 if(enable) 2136 { 2137 if(bDscPassThrough) 2138 { 2139 dscPassthroughByte = FLD_SET_DRF(_DPCD20, _DSC_ENABLE, _PASS_THROUGH, _YES, dscPassthroughByte); 2140 DP_LOG(("DP-DEV> Enabling DSC Pass through on branch device - %s", 2141 this->parent->getTopologyAddress().toString(buffer))); 2142 } 2143 2144 if (!bCurrDscEnable) 2145 { 2146 dscEnableByte = FLD_SET_DRF(_DPCD14, _DSC_ENABLE, _SINK, _YES, dscEnableByte); 2147 DP_LOG(("DP-DEV> Enabling DSC decompression on device - %s", 2148 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2149 } 2150 else 2151 { 2152 DP_LOG(("DP-DEV> DSC decompression is already enabled on device - %s", 2153 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2154 } 2155 } 2156 else 2157 { 2158 if(bDscPassThrough) 2159 { 2160 dscPassthroughByte = FLD_SET_DRF(_DPCD20, _DSC_ENABLE, _PASS_THROUGH, _NO, dscPassthroughByte); 2161 DP_LOG(("DP-DEV> Disabling DSC Pass through on branch device - %s", 2162 this->parent->getTopologyAddress().toString(buffer))); 2163 } 2164 2165 if (bCurrDscEnable) 2166 { 2167 dscEnableByte = FLD_SET_DRF(_DPCD14, _DSC_ENABLE, _SINK, _NO, dscEnableByte); 2168 DP_LOG(("DP-DEV> Disabling DSC decompression on device - %s", 2169 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2170 } 2171 else 2172 { 2173 DP_LOG(("DP-DEV> DSC decompression is already disabled on device - %s", 2174 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2175 } 2176 } 2177 2178 if (bDscPassThrough) 2179 { 2180 dscPassThroughStatus = this->parent->setDpcdData(NV_DPCD14_DSC_ENABLE, 2181 &dscPassthroughByte, sizeof dscPassthroughByte, &size, &nakReason); 2182 if (dscPassThroughStatus != AuxBus::success) 2183 { 2184 DP_LOG(("DP-DEV> Setting DSC Passthrough on parent branch %s failed", 2185 this->parent->getTopologyAddress().toString(buffer))); 2186 } 2187 } 2188 2189 if (enable != bCurrDscEnable) 2190 { 2191 dscEnableStatus = this->devDoingDscDecompression->setDpcdData(NV_DPCD14_DSC_ENABLE, 2192 &dscEnableByte, sizeof dscEnableByte, &size, &nakReason); 2193 if (dscEnableStatus != AuxBus::success) 2194 { 2195 DP_LOG(("DP-DEV> Setting DSC Enable on sink %s failed", 2196 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2197 2198 } 2199 } 2200 2201 if ((dscPassThroughStatus != AuxBus::success) || (dscEnableStatus != AuxBus::success)) 2202 { 2203 return false; 2204 } 2205 else 2206 { 2207 return true; 2208 } 2209 } 2210 2211 2212 2213 bool DeviceImpl::setDscEnableDPToHDMIPCON(bool bDscEnable, bool bEnablePassThroughForPCON) 2214 { 2215 NvU8 dscEnableByte = 0; 2216 unsigned size = 0; 2217 unsigned nakReason = NakUndefined; 2218 AuxBus::status dscEnableStatus = AuxBus::success; 2219 Address::StringBuffer buffer; 2220 DP_USED(buffer); 2221 2222 if (!this->isDSCPossible()) 2223 { 2224 DP_LOG(("DP-DEV> DSC is not supported on DP to HDMI PCON - %s")); 2225 return false; 2226 } 2227 2228 if (bDscEnable) 2229 { 2230 if(bEnablePassThroughForPCON) 2231 { 2232 dscEnableByte = FLD_SET_DRF(_DPCD20, _DSC_ENABLE, _PASS_THROUGH, _YES, dscEnableByte); 2233 DP_LOG(("DP-DEV> Enabling DSC Pass through on DP to HDMI PCON device - %s", 2234 this->getTopologyAddress().toString(buffer))); 2235 } 2236 else 2237 { 2238 dscEnableByte = FLD_SET_DRF(_DPCD14, _DSC_ENABLE, _SINK, _YES, dscEnableByte); 2239 DP_LOG(("DP-DEV> Enabling DSC decompression on DP to HDMI PCON device - %s", 2240 this->getTopologyAddress().toString(buffer))); 2241 } 2242 2243 } 2244 2245 dscEnableStatus = this->setDpcdData(NV_DPCD14_DSC_ENABLE, 2246 &dscEnableByte, sizeof dscEnableByte, &size, &nakReason); 2247 2248 if (dscEnableStatus != AuxBus::success) 2249 { 2250 DP_LOG(("DP-DEV> Setting DSC Enable on DP to HDMI PCON %s failed", 2251 this->getTopologyAddress().toString(buffer))); 2252 return false; 2253 2254 } 2255 2256 return true; 2257 } 2258 2259 unsigned DeviceImpl::getDscVersionMajor() 2260 { 2261 return dscCaps.versionMajor; 2262 } 2263 2264 unsigned DeviceImpl::getDscVersionMinor() 2265 { 2266 return dscCaps.versionMinor; 2267 } 2268 2269 unsigned DeviceImpl::getDscRcBufferSize() 2270 { 2271 return dscCaps.rcBuffersize; 2272 } 2273 2274 unsigned DeviceImpl::getDscRcBufferBlockSize() 2275 { 2276 return dscCaps.rcBufferBlockSize; 2277 } 2278 2279 unsigned DeviceImpl::getDscMaxSlicesPerSink() 2280 { 2281 return dscCaps.maxSlicesPerSink; 2282 } 2283 2284 unsigned DeviceImpl::getDscLineBufferBitDepth() 2285 { 2286 return dscCaps.lineBufferBitDepth; 2287 } 2288 2289 NvBool DeviceImpl::isDscBlockPredictionSupported() 2290 { 2291 return dscCaps.bDscBlockPredictionSupport; 2292 } 2293 2294 unsigned DeviceImpl::getDscMaxBitsPerPixel() 2295 { 2296 return dscCaps.maxBitsPerPixelX16; 2297 } 2298 2299 NvBool DeviceImpl::isDscRgbSupported() 2300 { 2301 return dscCaps.dscDecoderColorFormatCaps.bRgb; 2302 } 2303 2304 NvBool DeviceImpl::isDscYCbCr444Supported() 2305 { 2306 return dscCaps.dscDecoderColorFormatCaps.bYCbCr444; 2307 } 2308 2309 NvBool DeviceImpl::isDscYCbCrSimple422Supported() 2310 { 2311 return dscCaps.dscDecoderColorFormatCaps.bYCbCrSimple422; 2312 } 2313 2314 NvBool DeviceImpl::isDscYCbCr422NativeSupported() 2315 { 2316 return dscCaps.dscDecoderColorFormatCaps.bYCbCrNative422; 2317 } 2318 2319 NvBool DeviceImpl::isDscYCbCr420NativeSupported() 2320 { 2321 return dscCaps.dscDecoderColorFormatCaps.bYCbCrNative420; 2322 } 2323 2324 unsigned DeviceImpl::getDscPeakThroughputMode0() 2325 { 2326 return dscCaps.dscPeakThroughputMode0; 2327 } 2328 2329 unsigned DeviceImpl::getDscPeakThroughputModel() 2330 { 2331 return dscCaps.dscPeakThroughputMode1; 2332 } 2333 2334 unsigned DeviceImpl::getDscMaxSliceWidth() 2335 { 2336 return dscCaps.dscMaxSliceWidth; 2337 } 2338 2339 unsigned DeviceImpl::getDscDecoderColorDepthSupportMask() 2340 { 2341 return dscCaps.dscDecoderColorDepthMask; 2342 } 2343 2344 bool DeviceImpl::isFakedMuxDevice() 2345 { 2346 return connector->main->isDynamicMuxCapable() && bIsFakedMuxDevice; 2347 } 2348 2349 bool DeviceImpl::isPreviouslyFakedMuxDevice() 2350 { 2351 return connector->main->isDynamicMuxCapable() && bIsPreviouslyFakedMuxDevice; 2352 } 2353 2354 static AuxBus::status _QueryCrcSink 2355 ( 2356 DeviceImpl *bus, 2357 NvU16 *sinkCrc0, 2358 NvU16 *sinkCrc1, 2359 NvU16 *sinkCrc2 2360 ) 2361 { 2362 AuxBus::status status = AuxBus::success; 2363 // no sink op needs to be done if registers are NULL 2364 if (sinkCrc0 == NULL) return status; 2365 NvU32 addr = NV_DPCD14_DSC_CRC_0; 2366 unsigned size = 2; 2367 NvU8 cnt[2] = {0, 0}; 2368 2369 unsigned sizeCompleted = 0; 2370 unsigned nakReason = 0; 2371 2372 status = bus->getDpcdData(addr, &cnt[0], size, &sizeCompleted, &nakReason); 2373 2374 if (status != AuxBus::success) 2375 { 2376 return status; 2377 } 2378 *sinkCrc0 = (((NvU16) cnt[1]) << (sizeof(NvU8) * 8)) | cnt[0]; 2379 2380 addr = NV_DPCD14_DSC_CRC_1; 2381 size = 2; 2382 2383 status = bus->getDpcdData(addr, &cnt[0], size, &sizeCompleted, &nakReason); 2384 2385 if (status != AuxBus::success) 2386 { 2387 return status; 2388 } 2389 *sinkCrc1 = (((NvU16) cnt[1]) << (sizeof(NvU8) * 8)) | cnt[0]; 2390 2391 addr = NV_DPCD14_DSC_CRC_2; 2392 size = 2; 2393 2394 status = bus->getDpcdData(addr, &cnt[0], size, &sizeCompleted, &nakReason); 2395 2396 if (status != AuxBus::success) 2397 { 2398 return status; 2399 } 2400 *sinkCrc2 = (((NvU16) cnt[1]) << (sizeof(NvU8) * 8)) | cnt[0]; 2401 return status; 2402 } 2403 2404 AuxBus::status DeviceImpl::dscCrcControl(NvBool bEnable, gpuDscCrc *gpuData, sinkDscCrc *sinkData) 2405 { 2406 // GPU part 2407 if (this->connector->main->dscCrcTransaction(bEnable, gpuData, (NvU16*) &(activeGroup->headIndex)) != true) 2408 { 2409 return AuxBus::nack; 2410 } 2411 2412 // sink part 2413 if (!sinkData) 2414 { 2415 return AuxBus::success; 2416 } 2417 return _QueryCrcSink(this, &(sinkData->sinkCrc0), &(sinkData->sinkCrc1), &(sinkData->sinkCrc2)); 2418 } 2419 2420 bool DeviceImpl::getPCONCaps(PCONCaps *pPCONCaps) 2421 { 2422 AuxBus::status status = AuxBus::success; 2423 NvU32 addr = NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT(0); 2424 NvU8 data[4] = {0}; 2425 unsigned sizeCompleted = 0; 2426 unsigned nakReason = 0; 2427 NvU8 pConType = 0; 2428 2429 status = this->getDpcdData(addr, &data[0], sizeof(data), &sizeCompleted, &nakReason); 2430 if (status == AuxBus::success) 2431 { 2432 pConType = DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _DWNSTRM_PORT_TX_TYPE, data[0]); 2433 if (pConType == NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_TX_TYPE_HDMI) 2434 { 2435 this->connectorType = connectorHDMI; 2436 pPCONCaps->maxTmdsClkRate = data[1] * 2500000; 2437 2438 pPCONCaps->bSourceControlModeSupported = 2439 FLD_TEST_DRF(_DPCD, _DETAILED_CAP_INFO, _SRC_CONTROL_MODE_SUPPORT, _YES, data[2]); 2440 pPCONCaps->bConcurrentLTSupported = 2441 FLD_TEST_DRF(_DPCD, _DETAILED_CAP_INFO, _CONCURRENT_LT_SUPPORT, _YES, data[2]); 2442 2443 switch (DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _MAX_FRL_LINK_BW_SUPPORT, data[2])) 2444 { 2445 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_9G: 2446 pPCONCaps->maxHdmiLinkBandwidthGbps = 9; 2447 break; 2448 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_18G: 2449 pPCONCaps->maxHdmiLinkBandwidthGbps = 18; 2450 break; 2451 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_24G: 2452 pPCONCaps->maxHdmiLinkBandwidthGbps = 24; 2453 break; 2454 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_32G: 2455 pPCONCaps->maxHdmiLinkBandwidthGbps = 32; 2456 break; 2457 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_40G: 2458 pPCONCaps->maxHdmiLinkBandwidthGbps = 40; 2459 break; 2460 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_48G: 2461 pPCONCaps->maxHdmiLinkBandwidthGbps = 48; 2462 break; 2463 default: 2464 pPCONCaps->maxHdmiLinkBandwidthGbps = 0; 2465 break; 2466 } 2467 2468 switch (DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _MAX_BITS_PER_COMPONENT_DEF, data[2])) 2469 { 2470 case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_10BPC: 2471 pPCONCaps->maxBpc = 10; 2472 break; 2473 case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_12BPC: 2474 pPCONCaps->maxBpc = 12; 2475 break; 2476 case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_16BPC: 2477 pPCONCaps->maxBpc = 16; 2478 break; 2479 case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_8BPC: 2480 default: 2481 pPCONCaps->maxBpc = 8; 2482 break; 2483 } 2484 2485 DP_LOG((" DP2HDMI PCON caps - Max TMDS Clk: %u LinkBWGbps: %u MaxBpc: %u", 2486 pPCONCaps->maxTmdsClkRate, pPCONCaps->maxHdmiLinkBandwidthGbps, pPCONCaps->maxBpc)); 2487 } 2488 } 2489 else 2490 { 2491 DP_LOG((" DP-DEV> Error - DPCD Read for detailed port capabilities (0x80) failed.")); 2492 return false; 2493 } 2494 return true; 2495 } 2496 2497 bool DeviceImpl::getIgnoreMSACap() 2498 { 2499 NvU8 byte = 0; 2500 unsigned size = 0; 2501 unsigned nakReason = NakUndefined; 2502 AuxBus::status status; 2503 2504 if (bIgnoreMsaCapCached) 2505 { 2506 return bIgnoreMsaCap; 2507 } 2508 2509 if (this->isMultistream()) 2510 { 2511 status = this->getDpcdData(NV_DPCD_DOWN_STREAM_PORT, 2512 &byte, sizeof byte, &size, &nakReason); 2513 if (status == AuxBus::success) 2514 { 2515 if(FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _YES, byte)) 2516 { 2517 if (this->parent && this->parent->isVirtualPeerDevice()) 2518 { 2519 byte = 0; 2520 size = 0; 2521 nakReason = NakUndefined; 2522 2523 status = this->parent->getDpcdData(NV_DPCD_DOWN_STREAM_PORT, 2524 &byte, sizeof byte, &size, &nakReason); 2525 if (status == AuxBus::success) 2526 { 2527 if(FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _YES, byte)) 2528 { 2529 bIgnoreMsaCap = true; 2530 } 2531 else 2532 { 2533 bIgnoreMsaCap = false; 2534 } 2535 bIgnoreMsaCapCached = true; 2536 } 2537 else 2538 { 2539 DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!")); 2540 return false; 2541 } 2542 } 2543 else 2544 { 2545 bIgnoreMsaCap = true; 2546 bIgnoreMsaCapCached = true; 2547 } 2548 } 2549 else 2550 { 2551 bIgnoreMsaCap = false; 2552 bIgnoreMsaCapCached = true; 2553 } 2554 } 2555 else 2556 { 2557 DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!")); 2558 return false; 2559 } 2560 } 2561 else 2562 { 2563 bIgnoreMsaCap = hal->getMsaTimingparIgnored(); 2564 bIgnoreMsaCapCached = true; 2565 } 2566 2567 return bIgnoreMsaCap; 2568 } 2569 2570 AuxRetry::status DeviceImpl::setIgnoreMSAEnable(bool msaTimingParamIgnoreEn) 2571 { 2572 NvU8 byte = 0; 2573 unsigned size = 0; 2574 unsigned nakReason = NakUndefined; 2575 AuxBus::status status; 2576 2577 if (this->isMultistream()) 2578 { 2579 status = this->getDpcdData(NV_DPCD_DOWNSPREAD_CTRL, 2580 &byte, sizeof byte, &size, &nakReason); 2581 if (status == AuxBus::success) 2582 { 2583 if (msaTimingParamIgnoreEn) 2584 { 2585 byte = FLD_SET_DRF(_DPCD, _DOWNSPREAD_CTRL, _MSA_TIMING_PAR_IGNORED, _TRUE, byte); 2586 } 2587 else 2588 { 2589 byte = FLD_SET_DRF(_DPCD, _DOWNSPREAD_CTRL, _MSA_TIMING_PAR_IGNORED, _FALSE, byte); 2590 } 2591 2592 status = this->setDpcdData(NV_DPCD_DOWNSPREAD_CTRL, 2593 &byte, sizeof byte, &size, &nakReason); 2594 if (status == AuxBus::success) 2595 { 2596 return AuxRetry::ack; 2597 } 2598 else 2599 { 2600 DP_LOG(("DP-DEV> Aux Write to DPCD offset 0x107 failed!")); 2601 return AuxRetry::nack; 2602 } 2603 } 2604 else 2605 { 2606 DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!")); 2607 return AuxRetry::nack; 2608 } 2609 } 2610 else 2611 { 2612 return hal->setIgnoreMSATimingParamters(msaTimingParamIgnoreEn); 2613 } 2614 } 2615 2616 void 2617 DeviceHDCPDetection::start() 2618 { 2619 if (parent->isNativeDPCD()) 2620 { 2621 if (!parent->isMultistream()) 2622 { 2623 goto NativeDPCDHDCPCAPRead; 2624 } 2625 else 2626 { 2627 parent->isHDCPCap = False; 2628 waivePendingHDCPCapDoneNotification(); 2629 return; 2630 } 2631 2632 NativeDPCDHDCPCAPRead: 2633 2634 BCaps bCaps = {0}; 2635 2636 parent->hal->getBCaps(bCaps, parent->BCAPS); 2637 *(parent->nvBCaps) = *(parent->BCAPS); 2638 2639 if (bCaps.HDCPCapable) 2640 { 2641 NvU8 tempBKSV[HDCP_KSV_SIZE] = {0}; 2642 if (parent->hal->getBKSV(tempBKSV)) 2643 { 2644 if (hdcpValidateKsv(tempBKSV, HDCP_KSV_SIZE)) 2645 { 2646 for (unsigned i=0; i<HDCP_KSV_SIZE; i++) 2647 parent->BKSV[i] = tempBKSV[i]; 2648 } 2649 } 2650 parent->isHDCPCap = True; 2651 waivePendingHDCPCapDoneNotification(); 2652 return; 2653 } 2654 else 2655 { 2656 unsigned char hdcp22BCAPS[HDCP22_BCAPS_SIZE]; 2657 2658 // Check if hdcp2.x only device and probe hdcp22Bcaps. 2659 parent->hal->getHdcp22BCaps(bCaps, hdcp22BCAPS); 2660 if (bCaps.HDCPCapable) 2661 { 2662 parent->nvBCaps[0] = FLD_SET_DRF_NUM(_DPCD, _HDCP_BCAPS_OFFSET, 2663 _HDCP_CAPABLE, bCaps.HDCPCapable, 2664 parent->nvBCaps[0]) | 2665 FLD_SET_DRF_NUM(_DPCD, _HDCP_BCAPS_OFFSET, _HDCP_REPEATER, 2666 bCaps.repeater, parent->nvBCaps[0]); 2667 2668 // 2669 // No need to validate 1.x bksv here and hdcp22 authentication would 2670 // validate certificate with bksv in uproc. 2671 // 2672 parent->isHDCPCap = True; 2673 waivePendingHDCPCapDoneNotification(); 2674 return; 2675 } 2676 } 2677 2678 parent->isHDCPCap = False; 2679 waivePendingHDCPCapDoneNotification(); 2680 } 2681 else 2682 { 2683 parent->isHDCPCap = False; 2684 waivePendingHDCPCapDoneNotification(); 2685 } 2686 } 2687 2688 void 2689 DeviceHDCPDetection::messageCompleted 2690 ( 2691 MessageManager::Message *from 2692 ) 2693 { 2694 if ((from == &remoteBKSVReadMessage) || 2695 (from == &remoteBCapsReadMessage) || 2696 (from == &remote22BCapsReadMessage)) 2697 { 2698 handleRemoteDpcdReadDownReply(from); 2699 } 2700 } 2701 2702 void 2703 DeviceHDCPDetection::handleRemoteDpcdReadDownReply 2704 ( 2705 MessageManager::Message *from 2706 ) 2707 { 2708 NvU8 i2cBcaps; 2709 unsigned dataCompleted; 2710 unsigned defaultReason; 2711 Address::StringBuffer sb; 2712 DP_USED(sb); 2713 2714 if (from == &remoteBKSVReadMessage) 2715 { 2716 bksvReadCompleted = true; 2717 bBKSVReadMessagePending = false; 2718 DP_LOG(("DP-QM> REMOTE_DPCD_READ(BKSV) {%p} at '%s' completed", 2719 (MessageManager::Message *)&remoteBKSVReadMessage, 2720 parent->address.toString(sb))); 2721 2722 if (remoteBKSVReadMessage.replyNumOfBytesReadDPCD() != HDCP_KSV_SIZE) 2723 { 2724 DP_ASSERT(0 && "Incomplete BKSV in remote DPCD read message"); 2725 parent->isHDCPCap = False; 2726 2727 // Destruct only when no message is pending 2728 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2729 { 2730 parent->isDeviceHDCPDetectionAlive = false; 2731 delete this; 2732 } 2733 return; 2734 } 2735 2736 DP_ASSERT(remoteBKSVReadMessage.replyPortNumber() == parent->address.tail()); 2737 if (hdcpValidateKsv(remoteBKSVReadMessage.replyGetData(), HDCP_KSV_SIZE)) 2738 { 2739 isValidBKSV = true; 2740 for (unsigned i=0; i<HDCP_KSV_SIZE; i++) 2741 parent->BKSV[i] = (remoteBKSVReadMessage.replyGetData())[i]; 2742 2743 DP_LOG(("DP-QM> Device at '%s' is with valid BKSV.", 2744 parent->address.toString(sb))); 2745 } 2746 } 2747 else if (from == &remoteBCapsReadMessage) 2748 { 2749 bCapsReadCompleted = true; 2750 bBCapsReadMessagePending = false; 2751 DP_LOG(("DP-QM> REMOTE_DPCD_READ(BCaps) {%p} at '%s' completed", 2752 (MessageManager::Message *)&remoteBCapsReadMessage, 2753 parent->address.toString(sb))); 2754 2755 if (remoteBCapsReadMessage.replyNumOfBytesReadDPCD() != HDCP_BCAPS_SIZE) 2756 { 2757 DP_ASSERT(0 && "Incomplete BCaps in remote DPCD read message"); 2758 parent->isHDCPCap = False; 2759 2760 // Destruct only when no message is pending 2761 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2762 { 2763 parent->isDeviceHDCPDetectionAlive = false; 2764 delete this; 2765 } 2766 return; 2767 } 2768 2769 DP_ASSERT(remoteBCapsReadMessage.replyPortNumber() == parent->address.tail()); 2770 if (!!(*remoteBCapsReadMessage.replyGetData() & 0x1)) 2771 { 2772 *(parent->nvBCaps) = *(parent->BCAPS) = *remoteBCapsReadMessage.replyGetData(); 2773 isBCapsHDCP = true; 2774 2775 DP_LOG(("DP-QM> Device at '%s' is with valid BCAPS : %x", 2776 parent->address.toString(sb), *remoteBCapsReadMessage.replyGetData())); 2777 } 2778 else 2779 { 2780 if (isValidBKSV) 2781 { 2782 DP_LOG(("DP-QM> Device at '%s' is with valid BKSV but Invalid BCAPS : %x", 2783 parent->address.toString(sb), *remoteBCapsReadMessage.replyGetData())); 2784 2785 // Read the BCAPS DDC offset 2786 parent->transaction(AuxBus::read, AuxBus::i2cMot, HDCP_I2C_CLIENT_ADDR, &i2cBcaps, 2787 1, &dataCompleted, &defaultReason, HDCP_BCAPS_DDC_OFFSET, 1); 2788 2789 DP_LOG(("DP-QM> Device at '%s' is with DDC BACPS: %x", 2790 parent->address.toString(sb), i2cBcaps)); 2791 2792 // If the Reserved Bit is SET, Device supports HDCP 2793 if (i2cBcaps & HDCP_BCAPS_DDC_EN_BIT) 2794 { 2795 isBCapsHDCP = true; 2796 // Set the HDCP cap BCAPS according to DP protocol 2797 *(parent->BCAPS) |= HDCP_BCAPS_DP_EN_BIT; 2798 *(parent->nvBCaps) = *(parent->BCAPS); 2799 } 2800 } 2801 else 2802 { 2803 DP_LOG(("DP-QM> Device at '%s' is without valid BKSV and BCAPS, thus try 22BCAPS")); 2804 2805 Address parentAddress = parent->address.parent(); 2806 remote22BCapsReadMessage.setMessagePriority(NV_DP_SBMSG_PRIORITY_LEVEL_DEFAULT); 2807 remote22BCapsReadMessage.set(parentAddress, parent->address.tail(), NV_DPCD_HDCP22_BCAPS_OFFSET, HDCP22_BCAPS_SIZE); 2808 bCapsReadCompleted = false; 2809 bBCapsReadMessagePending = true; 2810 messageManager->post(&remote22BCapsReadMessage, this); 2811 } 2812 } 2813 } 2814 else if (from == &remote22BCapsReadMessage) 2815 { 2816 bCapsReadCompleted = true; 2817 bBCapsReadMessagePending = false; 2818 DP_LOG(("DP-QM> REMOTE_DPCD_READ(22BCaps) {%p} at '%s' completed", 2819 (MessageManager::Message *)&remote22BCapsReadMessage, 2820 parent->address.toString(sb))); 2821 2822 if (remote22BCapsReadMessage.replyNumOfBytesReadDPCD() != HDCP22_BCAPS_SIZE) 2823 { 2824 DP_ASSERT(0 && "Incomplete 22BCaps in remote DPCD read message"); 2825 parent->isHDCPCap = False; 2826 2827 // Destruct only when no message is pending 2828 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2829 { 2830 parent->isDeviceHDCPDetectionAlive = false; 2831 delete this; 2832 } 2833 return; 2834 } 2835 2836 DP_ASSERT(remote22BCapsReadMessage.replyPortNumber() == parent->address.tail()); 2837 if (!!(*remote22BCapsReadMessage.replyGetData() & 0x2)) 2838 { 2839 unsigned char hdcp22BCAPS; 2840 2841 hdcp22BCAPS = *remote22BCapsReadMessage.replyGetData(); 2842 2843 parent->nvBCaps[0] = FLD_SET_DRF_NUM(_DPCD, _HDCP_BCAPS_OFFSET, 2844 _HDCP_CAPABLE, (hdcp22BCAPS & 0x2) ? 1 : 0, 2845 parent->nvBCaps[0]) | 2846 FLD_SET_DRF_NUM(_DPCD, _HDCP_BCAPS_OFFSET, _HDCP_REPEATER, 2847 (hdcp22BCAPS & 0x1) ? 1 : 0, parent->nvBCaps[0]); 2848 2849 // hdcp22 will validate certificate's bksv directly. 2850 isBCapsHDCP = isValidBKSV = true; 2851 2852 DP_LOG(("DP-QM> Device at '%s' is with valid 22BCAPS : %x", 2853 parent->address.toString(sb), *remote22BCapsReadMessage.replyGetData())); 2854 } 2855 } 2856 2857 if (bCapsReadCompleted && bksvReadCompleted) 2858 { 2859 // Complete remote HDCP probe and check if can power down again. 2860 if (parent->connector) 2861 { 2862 parent->connector->decPendingRemoteHdcpDetection(); 2863 parent->connector->isNoActiveStreamAndPowerdown(); 2864 } 2865 2866 if (isValidBKSV && isBCapsHDCP) 2867 { 2868 parent->isHDCPCap = True; 2869 } 2870 else 2871 { 2872 parent->isHDCPCap = False; 2873 } 2874 2875 // Destruct only when no message is pending 2876 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2877 { 2878 parent->isDeviceHDCPDetectionAlive = false; 2879 delete this; 2880 } 2881 } 2882 else 2883 { 2884 parent->isHDCPCap = Indeterminate; 2885 } 2886 } 2887 2888 bool 2889 DeviceHDCPDetection::hdcpValidateKsv 2890 ( 2891 const NvU8 *ksv, 2892 NvU32 Size 2893 ) 2894 { 2895 2896 if (HDCP_KSV_SIZE <= Size) 2897 { 2898 NvU32 i, j; 2899 NvU32 count_ones = 0; 2900 for (i=0; i < HDCP_KSV_SIZE; i++) 2901 { 2902 for (j = 0; j < 8; j++) 2903 { 2904 if (ksv[i] & (1 <<(j))) 2905 { 2906 count_ones++; 2907 } 2908 } 2909 } 2910 2911 if (count_ones == 20) 2912 { 2913 return true; 2914 } 2915 } 2916 return false; 2917 } 2918 2919 void 2920 DeviceHDCPDetection::messageFailed 2921 ( 2922 MessageManager::Message *from, 2923 NakData *nakData 2924 ) 2925 { 2926 if (from == &remoteBKSVReadMessage) 2927 { 2928 if ((retriesRemoteBKSVReadMessage < DPCD_REMOTE_DPCD_READ_MESSAGE_RETRIES) && 2929 (nakData->reason == NakDefer || nakData->reason == NakTimeout)) 2930 { 2931 retriesRemoteBKSVReadMessage++; 2932 retryRemoteBKSVReadMessage = bBKSVReadMessagePending = true; 2933 timer->queueCallback(this, "BKSV", DPCD_REMOTE_DPCD_READ_MESSAGE_COOLDOWN_BKSV); 2934 return; 2935 } 2936 // 2937 // If message failed is called after all retries have expired or due 2938 // to any other reason then reset the bBKSVReadMessagePending flag 2939 // 2940 bBKSVReadMessagePending = false; 2941 } 2942 2943 if (from == &remoteBCapsReadMessage) 2944 { 2945 if ((retriesRemoteBCapsReadMessage < DPCD_REMOTE_DPCD_READ_MESSAGE_RETRIES) && 2946 (nakData->reason == NakDefer || nakData->reason == NakTimeout)) 2947 { 2948 retriesRemoteBCapsReadMessage++; 2949 retryRemoteBCapsReadMessage = bBCapsReadMessagePending = true; 2950 timer->queueCallback(this, "BCaps", DPCD_REMOTE_DPCD_READ_MESSAGE_COOLDOWN_BKSV); 2951 return; 2952 } 2953 // 2954 // If message failed is called after all retries have expired or due 2955 // to any other reason then reset the bBCapsReadMessagePending flag 2956 // 2957 bBCapsReadMessagePending = false; 2958 } 2959 2960 if (from == &remote22BCapsReadMessage) 2961 { 2962 if ((retriesRemote22BCapsReadMessage < DPCD_REMOTE_DPCD_READ_MESSAGE_RETRIES) && 2963 (nakData->reason == NakDefer || nakData->reason == NakTimeout)) 2964 { 2965 retriesRemote22BCapsReadMessage++; 2966 retryRemote22BCapsReadMessage = bBCapsReadMessagePending = true; 2967 timer->queueCallback(this, "22BCaps", DPCD_REMOTE_DPCD_READ_MESSAGE_COOLDOWN_BKSV); 2968 return; 2969 } 2970 // 2971 // If message failed is called after all retries have expired or due to 2972 // any other reason then reset the bBCapsReadMessagePending flag 2973 // 2974 bBCapsReadMessagePending = false; 2975 } 2976 2977 parent->isHDCPCap = False; 2978 Address::StringBuffer sb; 2979 DP_USED(sb); 2980 DP_LOG(("DP-QM> Message %s {%p} at '%s' failed. Device marked as not HDCP support.", 2981 from == &remoteBKSVReadMessage ? "REMOTE_DPCD_READ(BKSV)" : 2982 from == &remoteBCapsReadMessage ? "REMOTE_DPC_READ(BCaps)" : 2983 from == &remote22BCapsReadMessage ? "REMOTE_DPC_READ(22BCaps)" : "???", 2984 from, parent->address.toString(sb))); 2985 2986 // Destruct only when no message is pending 2987 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2988 { 2989 parent->isDeviceHDCPDetectionAlive = false; 2990 2991 // Complete remote HDCP probe and check if can power down again. 2992 if (parent->connector) 2993 { 2994 parent->connector->decPendingRemoteHdcpDetection(); 2995 parent->connector->isNoActiveStreamAndPowerdown(); 2996 } 2997 2998 delete this; 2999 } 3000 } 3001 3002 void 3003 DeviceHDCPDetection::expired 3004 ( 3005 const void *tag 3006 ) 3007 { 3008 // Clear stale HDCP states when monitor instance is already destroyed 3009 if (!parent->plugged) 3010 { 3011 if (retryRemoteBKSVReadMessage) 3012 { 3013 retryRemoteBKSVReadMessage = false; 3014 bBKSVReadMessagePending = false; 3015 } 3016 else if (retryRemoteBCapsReadMessage) 3017 { 3018 retryRemoteBCapsReadMessage = false; 3019 bBCapsReadMessagePending = false; 3020 } 3021 else if (retryRemote22BCapsReadMessage) 3022 { 3023 retryRemote22BCapsReadMessage = false; 3024 bBCapsReadMessagePending = false; 3025 } 3026 3027 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 3028 { 3029 parent->isDeviceHDCPDetectionAlive = false; 3030 delete this; 3031 } 3032 return; 3033 } 3034 3035 if (retryRemoteBKSVReadMessage) 3036 { 3037 Address parentAddress = parent->address.parent(); 3038 3039 Address::StringBuffer sb; 3040 DP_USED(sb); 3041 DP_LOG(("DP-QM> Requeing REMOTE_DPCD_READ_MESSAGE(BKSV) to %s", parentAddress.toString(sb))); 3042 3043 retryRemoteBKSVReadMessage = false; 3044 remoteBKSVReadMessage.set(parentAddress, parent->address.tail(), NV_DPCD_HDCP_BKSV_OFFSET, HDCP_KSV_SIZE); 3045 DP_LOG(("DP-QM> Get BKSV (remotely) for '%s' sent REMOTE_DPCD_READ {%p}", parent->address.toString(sb), &remoteBKSVReadMessage)); 3046 3047 bBKSVReadMessagePending = true; 3048 messageManager->post(&remoteBKSVReadMessage, this); 3049 } 3050 3051 if (retryRemoteBCapsReadMessage) 3052 { 3053 Address parentAddress = parent->address.parent(); 3054 3055 Address::StringBuffer sb; 3056 DP_USED(sb); 3057 DP_LOG(("DP-QM> Requeing REMOTE_DPCD_READ_MESSAGE(BCAPS) to %s", parentAddress.toString(sb))); 3058 3059 retryRemoteBCapsReadMessage = false; 3060 remoteBCapsReadMessage.set(parentAddress, parent->address.tail(), NV_DPCD_HDCP_BCAPS_OFFSET, HDCP_BCAPS_SIZE); 3061 DP_LOG(("DP-QM> Get BCaps (remotely) for '%s' sent REMOTE_DPCD_READ {%p}", parent->address.toString(sb), &remoteBCapsReadMessage)); 3062 3063 bBCapsReadMessagePending = true; 3064 messageManager->post(&remoteBCapsReadMessage, this); 3065 } 3066 3067 if (retryRemote22BCapsReadMessage) 3068 { 3069 Address parentAddress = parent->address.parent(); 3070 3071 Address::StringBuffer sb; 3072 DP_USED(sb); 3073 DP_LOG(("DP-QM> Requeing REMOTE_DPCD_READ_MESSAGE(22BCAPS) to %s", parentAddress.toString(sb))); 3074 3075 retryRemote22BCapsReadMessage = false; 3076 remote22BCapsReadMessage.set(parentAddress, parent->address.tail(), NV_DPCD_HDCP22_BCAPS_OFFSET, HDCP22_BCAPS_SIZE); 3077 DP_LOG(("DP-QM> Get 22BCaps (remotely) for '%s' sent REMOTE_DPCD_READ {%p}", parent->address.toString(sb), &remote22BCapsReadMessage)); 3078 3079 bBCapsReadMessagePending = true; 3080 messageManager->post(&remote22BCapsReadMessage, this); 3081 } 3082 3083 } 3084 3085 DeviceHDCPDetection::~DeviceHDCPDetection() 3086 { 3087 parent->isDeviceHDCPDetectionAlive = false; 3088 3089 // Clear all pending callbacks/messages 3090 if (this->timer) 3091 { 3092 this->timer->cancelCallbacks(this); 3093 } 3094 3095 if (this->messageManager) 3096 { 3097 this->messageManager->cancelAll(&remoteBKSVReadMessage); 3098 this->messageManager->cancelAll(&remoteBCapsReadMessage); 3099 this->messageManager->cancelAll(&remote22BCapsReadMessage); 3100 } 3101 } 3102 3103 void 3104 DeviceHDCPDetection::waivePendingHDCPCapDoneNotification() 3105 { 3106 // Waive the pendingHDCPCapDone notification 3107 parent->shadow.hdcpCapDone = true; 3108 parent->isDeviceHDCPDetectionAlive = false; 3109 delete this; 3110 } 3111