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 // Send remote DPCD for devices behind the branch 1072 if ((AuxBus::success == targetDevice->getDpcdData(NV_DPCD_TRAINING_AUX_RD_INTERVAL, 1073 &byte, sizeof byte, &size, &nakReason)) && 1074 (FLD_TEST_DRF(_DPCD14, _TRAINING_AUX_RD_INTERVAL, _EXTENDED_RX_CAP, _YES, byte))) 1075 { 1076 byte = 0; 1077 size = 0; 1078 nakReason = NakUndefined; 1079 1080 if (AuxBus::success == targetDevice->getDpcdData(NV_DPCD14_EXTENDED_DPRX_FEATURE_ENUM_LIST, 1081 &byte, sizeof byte, &size, &nakReason)) 1082 { 1083 this->bSdpExtCapable = FLD_TEST_DRF(_DPCD14, 1084 _EXTENDED_DPRX_FEATURE_ENUM_LIST, 1085 _VSC_SDP_EXT_FOR_COLORIMETRY, 1086 _YES, byte) ? True : False; 1087 } 1088 } 1089 1090 if (parentDevice && (this->bSdpExtCapable == True)) 1091 { 1092 // 1093 // Do not override bSdpExtCapable for the sink. Although result won't 1094 // change but we can keep the value for debug purpose. 1095 // 1096 return parentDevice->getSDPExtnForColorimetrySupported(); 1097 } 1098 1099 return (this->bSdpExtCapable == True); 1100 } 1101 1102 bool DeviceImpl::getPanelFwRevision(NvU16 *revision) 1103 { 1104 NvU8 fwRevisionMajor = 0; 1105 NvU8 fwRevisionMinor = 0; 1106 unsigned size = 0; 1107 unsigned nakReason = NakUndefined; 1108 1109 if (!revision) 1110 { 1111 return false; 1112 } 1113 1114 *revision = 0; 1115 1116 // 1117 // On faked mux devices, we cannot check if the device has 1118 // the capability as we don't have access to aux. 1119 // 1120 if (this->isFakedMuxDevice()) 1121 { 1122 return false; 1123 } 1124 1125 if (AuxBus::success != this->getDpcdData(NV_DPCD14_FW_SW_REVISION_MAJOR, 1126 &fwRevisionMajor, sizeof(fwRevisionMajor), &size, &nakReason)) 1127 { 1128 return false; 1129 } 1130 1131 if (AuxBus::success != this->getDpcdData(NV_DPCD14_FW_SW_REVISION_MINOR, 1132 &fwRevisionMinor, sizeof(fwRevisionMinor), &size, &nakReason)) 1133 { 1134 return false; 1135 } 1136 1137 *revision = (fwRevisionMajor << 8) | fwRevisionMinor; 1138 1139 return true; 1140 } 1141 1142 bool DeviceImpl::isPowerSuspended() 1143 { 1144 bool bPanelPowerOn, bDPCDPowerStateD0; 1145 if (connector->main->isEDP()) 1146 { 1147 connector->main->getEdpPowerData(&bPanelPowerOn, &bDPCDPowerStateD0); 1148 return !bDPCDPowerStateD0; 1149 } 1150 return (connector->hal->getPowerState() == PowerStateD3); 1151 } 1152 1153 void DeviceImpl::setPanelPowerParams(bool bSinkPowerStateD0, bool bPanelPowerStateOn) 1154 { 1155 bool bPanelPowerOn, bDPCDPowerStateD0; 1156 GroupImpl * pGroupAttached = connector->getActiveGroupForSST(); 1157 1158 // 1159 // For single head dual SST mode, set the panel power params for the 1160 // secondary connector while updating the primary connector. 1161 // 1162 if (pGroupAttached && 1163 connector->pCoupledConnector && 1164 (pGroupAttached->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST) && 1165 (pGroupAttached->singleHeadMultiStreamID == DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY)) 1166 { 1167 return; 1168 } 1169 1170 if (connector->main->isEDP()) 1171 { 1172 connector->main->getEdpPowerData(&bPanelPowerOn, &bDPCDPowerStateD0); 1173 } 1174 else 1175 { 1176 bDPCDPowerStateD0 = (connector->hal->getPowerState() == PowerStateD0)? 1177 true : false; 1178 } 1179 1180 // Going to Suspend (D3) 1181 if (!bSinkPowerStateD0) 1182 { 1183 if (this->bypassDpcdPowerOff()) 1184 { 1185 DP_LOG(("DP-DEV> Bypassing 600h write for this display")); 1186 return; 1187 } 1188 1189 if (connector->main->isEDP()) 1190 { 1191 /* 1192 * If it's an eDP panel, the setPowerState call below will turn on LCD_POWER 1193 * if it's already off. So only call the function when panel power is on 1194 * and DPCD_SET_POWER is set to _D0. 1195 */ 1196 if (bPanelPowerOn && bDPCDPowerStateD0) 1197 { 1198 // monitor to be put to sleep 1199 if (connector->hal->setPowerState(PowerStateD3)) 1200 shadow.highestAssessedLC = connector->highestAssessedLC; 1201 } 1202 } 1203 else 1204 { 1205 1206 if (connector->pCoupledConnector) 1207 { 1208 // Put secondary connctor to sleep 1209 connector->pCoupledConnector->hal->setPowerState(PowerStateD3); 1210 } 1211 1212 // monitor to be put to sleep 1213 if (connector->hal->setPowerState(PowerStateD3)) 1214 { 1215 shadow.highestAssessedLC = connector->highestAssessedLC; 1216 } 1217 } 1218 // 1219 // If bPanelPowerStateOn is false and this 1220 // is not a multistream device, then shut down the main link. Some eDP 1221 // panels are known to need this in order to actually shut down. 1222 // 1223 if (!isMultistream() && !bPanelPowerStateOn) 1224 { 1225 if (connector->pCoupledConnector) 1226 { 1227 // configure power state on secondary 1228 connector->pCoupledConnector->main->configurePowerState(false); 1229 } 1230 connector->main->configurePowerState(false); 1231 } 1232 } 1233 else 1234 { 1235 if (connector->main->isEDP() && !bPanelPowerOn) 1236 { 1237 // Turn on the eDP panel if required. 1238 connector->main->configurePowerState(true); 1239 } 1240 // monitor to be brought out of sleep 1241 if (connector->hal->setPowerState(PowerStateD0)) 1242 { 1243 if (connector->pCoupledConnector) 1244 { 1245 // power up main link on secondary 1246 connector->pCoupledConnector->hal->setPowerState(PowerStateD0); 1247 } 1248 1249 // Mark linkStatus as dirty as we need to read linkStatus again since we are resuming a power state D0, link might have lost. 1250 connector->hal->setDirtyLinkStatus(true); 1251 if (connector->pCoupledConnector) 1252 { 1253 connector->pCoupledConnector->hal->setDirtyLinkStatus(true); 1254 } 1255 1256 if (connector->activeGroups.isEmpty()) 1257 { 1258 return; 1259 } 1260 if ((!connector->isLinkActive()) || 1261 (connector->main->isEDP() && !bPanelPowerOn) || 1262 (connector->isLinkLost()) || 1263 (!bDPCDPowerStateD0)) 1264 { 1265 // 1266 // If link is inactive, lost, or the panel was off before, then 1267 // assess Link. Note that this'll detach head if required. 1268 // 1269 if (pGroupAttached && 1270 pGroupAttached->singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST) 1271 { 1272 // Special handling for single head dual SST cases 1273 connector->trainSingleHeadMultipleSSTLinkNotAlive(pGroupAttached); 1274 } 1275 else 1276 { 1277 connector->assessLink(); 1278 } 1279 } 1280 } 1281 else 1282 DP_ASSERT(0 && "Could not bring the monitor back from sleep."); 1283 } 1284 } 1285 1286 void DeviceImpl::switchToComplianceFallback() 1287 { 1288 Edid fallbackEdid; 1289 makeEdidFallback(fallbackEdid); 1290 this->processedEdid.resetData(); 1291 this->processedEdid = fallbackEdid; 1292 } 1293 1294 TriState DeviceImpl::hdcpAvailableHop() 1295 { 1296 return this->isHDCPCap; 1297 } 1298 1299 TriState DeviceImpl::hdcpAvailable() 1300 { 1301 if (isNativeDPCD()) 1302 { 1303 return this->hdcpAvailableHop(); 1304 } 1305 return False; 1306 } 1307 1308 void DeviceImpl::resetCacheInferredLink() 1309 { 1310 this->bandwidth.enum_path.dataValid = false; 1311 } 1312 1313 LinkConfiguration * DeviceImpl::inferLeafLink(unsigned * totalLinkSlots) 1314 { 1315 // update the EPR data 1316 if (!bandwidth.enum_path.dataValid) 1317 { 1318 if (plugged) 1319 { 1320 NakData nack; 1321 for (unsigned retries = 0; retries < 7; retries++) 1322 { 1323 EnumPathResMessage epr(getTopologyAddress().parent(), getTopologyAddress().tail(), true); 1324 bool sendStatus = connector->messageManager->send(&epr, nack); 1325 if (!sendStatus) 1326 { 1327 if (nack.reason == NakDefer || nack.reason == NakTimeout) 1328 continue; 1329 1330 bandwidth.enum_path.total = 0; 1331 bandwidth.enum_path.free = 0; 1332 bandwidth.enum_path.availableStreams = 0; 1333 break; 1334 } 1335 else 1336 { 1337 bandwidth.enum_path.total = epr.reply.TotalPBN; 1338 bandwidth.enum_path.free = epr.reply.FreePBN; 1339 bandwidth.enum_path.bPathFECCapable = epr.reply.bFECCapability; 1340 bandwidth.enum_path.availableStreams = epr.reply.availableStreams; 1341 1342 break; 1343 } 1344 } 1345 } 1346 else 1347 { 1348 bandwidth.enum_path.total = bandwidth.enum_path.free = 0; 1349 } 1350 1351 bandwidth.enum_path.dataValid = true; 1352 bandwidth.lastHopLinkConfig = LinkConfiguration(bandwidth.enum_path.total); 1353 // Update FEC support of the device after EPR 1354 this->getFECSupport(); 1355 } 1356 1357 if (totalLinkSlots) 1358 { 1359 *totalLinkSlots = bandwidth.lastHopLinkConfig.slotsForPBN(bandwidth.enum_path.total, true /*epr aware*/); 1360 1361 // 1362 // Override the totalLinkSlots returned to 63 only if peer device is 1363 // 2 (branch), since TS-0 will be used for MTP header. 1364 // Branch may return the total pbn corresponding to 64 timeslots. 1365 // 1366 if (*totalLinkSlots == 64 && peerDevice == DownstreamBranch) 1367 { 1368 *totalLinkSlots = 63; 1369 } 1370 } 1371 1372 return &bandwidth.lastHopLinkConfig; 1373 } 1374 1375 bool DeviceImpl::isActive() 1376 { 1377 DP_ASSERT(!activeGroup || activeGroup->isHeadAttached()); 1378 return activeGroup != NULL; 1379 } 1380 1381 bool DeviceImpl::getRawEpr(unsigned * totalEpr, unsigned * freeEpr, rawEprState eprState) 1382 { 1383 DP_ASSERT((totalEpr && freeEpr) && "Invalid arguments passed to function getRawEpr()"); 1384 bool status = true; 1385 *totalEpr = 0; 1386 *freeEpr = 0; 1387 1388 // If request has come for main link/Native branch device 1389 // return main link PBNs as "0" & return 1390 if (isNativeDPCD()) 1391 return status; 1392 1393 // Cached/Software state is queried 1394 if (eprState == software) 1395 { 1396 *totalEpr = bandwidth.enum_path.total; 1397 *freeEpr = bandwidth.enum_path.free; 1398 1399 return status; 1400 } 1401 1402 // Hardware state is queried. Send a new EPR message to get the current state 1403 EnumPathResMessage rawEpr(getTopologyAddress().parent(), getTopologyAddress().tail(), true); 1404 NakData nack; 1405 for (unsigned retries = 0; retries < 7; retries++) 1406 { 1407 bool sendStatus = connector->messageManager->send(&rawEpr, nack); 1408 if (!sendStatus) 1409 { 1410 status = false; 1411 if (nack.reason == NakDefer) 1412 continue; 1413 1414 DP_LOG(("DP-DEV> EPR message failed while getting RAW EPR")); 1415 1416 break; 1417 } 1418 else 1419 { 1420 *totalEpr = rawEpr.reply.TotalPBN; 1421 *freeEpr = rawEpr.reply.FreePBN; 1422 status = true; 1423 1424 break; 1425 } 1426 } 1427 1428 return status; 1429 } 1430 1431 unsigned DeviceImpl::getEDIDSize() const 1432 { 1433 // Return DDC EDID size only if we got a valid EDID there 1434 if (this->connector->isAcpiInitDone() && ddcEdid.isValidHeader()) 1435 { 1436 return ddcEdid.getEdidSize(); 1437 } 1438 else 1439 { 1440 return processedEdid.getEdidSize(); 1441 } 1442 } 1443 1444 bool DeviceImpl::getEDID(char * buffer, unsigned size) const 1445 { 1446 // 1447 // Return DDC EDID only if we got a valid EDID there 1448 // This has priority on regular EDID read from panel 1449 // 1450 if (this->connector->isAcpiInitDone() && ddcEdid.isValidHeader()) 1451 { 1452 if (size < ddcEdid.getEdidSize()) 1453 goto panelEdid; 1454 1455 dpMemCopy(buffer, ddcEdid.getBuffer()->getData(), ddcEdid.getEdidSize()); 1456 return true; 1457 } 1458 1459 panelEdid: 1460 // No EDID read from SBIOS. Return panel EDID now. 1461 if (size < processedEdid.getEdidSize()) 1462 return false; 1463 1464 dpMemCopy(buffer, processedEdid.getBuffer()->getData(), processedEdid.getEdidSize()); 1465 return true; 1466 } 1467 1468 unsigned DeviceImpl::getRawEDIDSize() const 1469 { 1470 // Return DDC EDID size only if we got a valid EDID there 1471 if (this->connector->isAcpiInitDone() && ddcEdid.isValidHeader()) 1472 { 1473 return ddcEdid.getEdidSize(); 1474 } 1475 else 1476 { 1477 return rawEDID.getEdidSize(); 1478 } 1479 } 1480 1481 bool DeviceImpl::getRawEDID(char * buffer, unsigned size) const 1482 { 1483 // 1484 // Return DDC EDID only if we got a valid EDID there 1485 // This has priority on regular EDID read from panel 1486 // 1487 if (this->connector->isAcpiInitDone() && ddcEdid.isValidHeader()) 1488 { 1489 if (size >= ddcEdid.getEdidSize()) 1490 { 1491 dpMemCopy(buffer, ddcEdid.getBuffer()->getData(), ddcEdid.getEdidSize()); 1492 return true; 1493 } 1494 } 1495 1496 // No EDID read from SBIOS. Return panel EDID now. 1497 if (size < rawEDID.getEdidSize()) 1498 return false; 1499 1500 dpMemCopy(buffer, rawEDID.getBuffer()->getData(), rawEDID.getEdidSize()); 1501 return true; 1502 } 1503 1504 bool DeviceImpl::startVrrEnablement() 1505 { 1506 bool ret = false; 1507 1508 if (vrrEnablement) 1509 { 1510 ret = vrrEnablement->start(); 1511 } 1512 1513 return ret; 1514 } 1515 1516 void DeviceImpl::resetVrrEnablement() 1517 { 1518 if (vrrEnablement) 1519 { 1520 vrrEnablement->reset(); 1521 } 1522 } 1523 1524 bool DeviceImpl::isVrrMonitorEnabled() 1525 { 1526 bool ret = false; 1527 1528 if (vrrEnablement) 1529 { 1530 ret = vrrEnablement->isMonitorEnabled(); 1531 } 1532 1533 return ret; 1534 } 1535 1536 bool DeviceImpl::isVrrDriverEnabled() 1537 { 1538 bool ret = false; 1539 1540 if (vrrEnablement) 1541 { 1542 ret = vrrEnablement->isDriverEnabled(); 1543 } 1544 1545 return ret; 1546 } 1547 1548 NvBool DeviceImpl::getDSCSupport() 1549 { 1550 NvU8 byte = 0; 1551 unsigned size = 0; 1552 unsigned nakReason = NakUndefined; 1553 Address::StringBuffer sb; 1554 DP_USED(sb); 1555 1556 dscCaps.bDSCSupported = false; 1557 1558 if(AuxBus::success == this->getDpcdData(NV_DPCD14_DSC_SUPPORT, 1559 &byte, sizeof(byte), &size, &nakReason)) 1560 { 1561 if (FLD_TEST_DRF(_DPCD14, _DSC_SUPPORT, _DSC_SUPPORT, _YES, byte)) 1562 { 1563 dscCaps.bDSCDecompressionSupported = true; 1564 } 1565 if (FLD_TEST_DRF(_DPCD20, _DSC_SUPPORT, _PASS_THROUGH_SUPPORT, _YES, byte)) 1566 { 1567 dscCaps.bDSCPassThroughSupported = true; 1568 } 1569 } 1570 1571 else 1572 { 1573 DP_LOG(("DP-DEV> DSC Support AUX READ failed for %s!", address.toString(sb))); 1574 } 1575 1576 if (dscCaps.bDSCDecompressionSupported || dscCaps.bDSCPassThroughSupported) 1577 { 1578 dscCaps.bDSCSupported = true; 1579 } 1580 1581 return dscCaps.bDSCSupported; 1582 } 1583 1584 bool DeviceImpl::isPanelReplaySupported() 1585 { 1586 return prCaps.panelReplaySupported; 1587 } 1588 1589 void DeviceImpl::getPanelReplayCaps() 1590 { 1591 NvU8 byte = 0; 1592 unsigned size = 0; 1593 unsigned nakReason = NakUndefined; 1594 1595 if (AuxBus::success == this->getDpcdData(NV_DPCD20_PANEL_REPLAY_CAPABILITY, 1596 &byte, sizeof(byte), &size, &nakReason)) 1597 { 1598 prCaps.panelReplaySupported = 1599 FLD_TEST_DRF(_DPCD20_PANEL, _REPLAY_CAPABILITY, _SUPPORTED, _YES, byte); 1600 } 1601 } 1602 1603 bool DeviceImpl::setPanelReplayConfig(panelReplayConfig prcfg) 1604 { 1605 NvU8 config = 0; 1606 unsigned size = 0; 1607 unsigned nakReason = NakUndefined; 1608 1609 if (prcfg.enablePanelReplay) 1610 { 1611 config = FLD_SET_DRF(_DPCD20_PANEL, _REPLAY_CONFIGURATION, 1612 _ENABLE_PR_MODE, _YES, config); 1613 } 1614 else 1615 { 1616 config = FLD_SET_DRF(_DPCD20_PANEL, _REPLAY_CONFIGURATION, 1617 _ENABLE_PR_MODE, _NO, config); 1618 } 1619 1620 if (AuxBus::success == this->setDpcdData(NV_DPCD20_PANEL_REPLAY_CONFIGURATION, 1621 &config, sizeof(config), &size, &nakReason)) 1622 { 1623 return true; 1624 } 1625 1626 return false; 1627 } 1628 1629 bool DeviceImpl::getPanelReplayStatus(PanelReplayStatus *pPrStatus) 1630 { 1631 NvU8 state = 0; 1632 unsigned size = 0; 1633 unsigned nakReason = NakUndefined; 1634 1635 if (pPrStatus == NULL) 1636 { 1637 DP_ASSERT(0); 1638 return false; 1639 } 1640 1641 if(AuxBus::success == this->getDpcdData(NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS, 1642 &state, sizeof(state), &size, &nakReason)) 1643 { 1644 switch (DRF_VAL(_DPCD20, _PANEL_REPLAY_AND_FRAME_LOCK_STATUS, _PR_STATUS, state)) 1645 { 1646 case NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS_PR_STATUS_STATE_0: 1647 pPrStatus->prState = PanelReplay_Inactive; 1648 break; 1649 1650 case NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS_PR_STATUS_STATE_1: 1651 pPrStatus->prState = PanelReplay_CaptureAndDisplay; 1652 break; 1653 1654 case NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS_PR_STATUS_STATE_2: 1655 pPrStatus->prState = PanelReplay_DisplayFromRfb; 1656 break; 1657 1658 default: 1659 pPrStatus->prState = PanelReplay_Undefined; 1660 break; 1661 } 1662 return true; 1663 } 1664 else 1665 { 1666 return false; 1667 } 1668 } 1669 bool DeviceImpl::getFECSupport() 1670 { 1671 NvU8 byte = 0; 1672 unsigned size = 0; 1673 unsigned nakReason = NakUndefined; 1674 1675 if(this->address.size() > 1) 1676 { 1677 bFECSupported = this->bandwidth.enum_path.bPathFECCapable; 1678 } 1679 1680 else if (AuxBus::success == this->getDpcdData(NV_DPCD14_FEC_CAPABILITY, 1681 &byte, sizeof(byte), &size, &nakReason)) 1682 { 1683 bFECSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _FEC_CAPABLE, _YES, byte); 1684 bFECUncorrectedSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _UNCORRECTED_BLOCK_ERROR_COUNT_CAPABLE, _YES, byte); 1685 bFECCorrectedSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _CORRECTED_BLOCK_ERROR_COUNT_CAPABLE, _YES, byte); 1686 bFECBitSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _BIT_ERROR_COUNT_CAPABLE, _YES, byte); 1687 bFECParityBlockSupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _PARITY_BLOCK_ERROR_COUNT_CAPABLE, _YES, byte); 1688 bFECParitySupported = FLD_TEST_DRF(_DPCD14, _FEC_CAPABILITY, _PARITY_ERROR_COUNT_CAPABLE, _YES, byte); 1689 } 1690 1691 return bFECSupported; 1692 } 1693 1694 NvBool DeviceImpl::isDSCSupported() 1695 { 1696 return dscCaps.bDSCSupported; 1697 } 1698 1699 NvBool DeviceImpl::isDSCDecompressionSupported() 1700 { 1701 return dscCaps.bDSCDecompressionSupported; 1702 } 1703 1704 NvBool DeviceImpl::isDSCPassThroughSupported() 1705 { 1706 return dscCaps.bDSCPassThroughSupported; 1707 } 1708 1709 NvBool DeviceImpl::isDSCPossible() 1710 { 1711 return this->bDSCPossible; 1712 } 1713 1714 bool DeviceImpl::isFECSupported() 1715 { 1716 return bFECSupported; 1717 } 1718 1719 bool DeviceImpl::parseDscCaps(const NvU8 *buffer, NvU32 bufferSize) 1720 { 1721 1722 if (bufferSize < 16) 1723 { 1724 DP_LOG((" DSC caps buffer must be greater than or equal to 16")); 1725 return false; 1726 } 1727 1728 if (FLD_TEST_DRF(_DPCD20, _DSC_SUPPORT, _PASS_THROUGH_SUPPORT, _YES, buffer[0x0])) 1729 { 1730 dscCaps.bDSCPassThroughSupported = true; 1731 } 1732 1733 dscCaps.versionMajor = DRF_VAL(_DPCD14, _DSC_ALGORITHM_REVISION, _MAJOR, buffer[0x1]); 1734 dscCaps.versionMinor = DRF_VAL(_DPCD14, _DSC_ALGORITHM_REVISION, _MINOR, buffer[0x1]); 1735 1736 dscCaps.rcBufferBlockSize = DRF_VAL(_DPCD14, _DSC_RC_BUFFER_BLOCK, _SIZE, buffer[0x2]); 1737 1738 dscCaps.rcBuffersize = DRF_VAL(_DPCD14, _DSC_RC_BUFFER, _SIZE, buffer[0x3]); 1739 1740 dscCaps.sliceCountSupportedMask = (((buffer[0xD]) << 8) | buffer[0x4]); 1741 if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_2, _SLICES_PER_SINK_24, _YES, buffer[0xD])) 1742 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_24; 1743 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_2, _SLICES_PER_SINK_20, _YES, buffer[0xD])) 1744 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_20; 1745 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_2, _SLICES_PER_SINK_16, _YES, buffer[0xD])) 1746 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_16; 1747 1748 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_12, _YES, buffer[0x4])) 1749 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_12; 1750 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_10, _YES, buffer[0x4])) 1751 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_10; 1752 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_8, _YES, buffer[0x4])) 1753 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_8; 1754 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_6, _YES, buffer[0x4])) 1755 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_6; 1756 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_4, _YES, buffer[0x4])) 1757 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_4; 1758 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_2, _YES, buffer[0x4])) 1759 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_2; 1760 else if(FLD_TEST_DRF(_DPCD14, _DSC_SLICE_CAPABILITIES_1, _SLICES_PER_SINK_1, _YES, buffer[0x4])) 1761 dscCaps.maxSlicesPerSink = DSC_SLICES_PER_SINK_1; 1762 1763 if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _8, buffer[0x5])) 1764 { 1765 dscCaps.lineBufferBitDepth = 8; 1766 } 1767 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _9, buffer[0x5])) 1768 { 1769 dscCaps.lineBufferBitDepth = 9; 1770 } 1771 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _10, buffer[0x5])) 1772 { 1773 dscCaps.lineBufferBitDepth = 10; 1774 } 1775 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _11, buffer[0x5])) 1776 { 1777 dscCaps.lineBufferBitDepth = 11; 1778 } 1779 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _12, buffer[0x5])) 1780 { 1781 dscCaps.lineBufferBitDepth = 12; 1782 } 1783 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _13, buffer[0x5])) 1784 { 1785 dscCaps.lineBufferBitDepth = 13; 1786 } 1787 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _14, buffer[0x5])) 1788 { 1789 dscCaps.lineBufferBitDepth = 14; 1790 } 1791 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _15, buffer[0x5])) 1792 { 1793 dscCaps.lineBufferBitDepth = 15; 1794 } 1795 else if (FLD_TEST_DRF(_DPCD14, _DSC_LINE_BUFFER, _BIT_DEPTH, _16, buffer[0x5])) 1796 { 1797 dscCaps.lineBufferBitDepth = 16; 1798 } 1799 1800 if(FLD_TEST_DRF(_DPCD14, _DSC_BLOCK_PREDICTION, _SUPPORT, _YES, buffer[0x6])) 1801 dscCaps.bDscBlockPredictionSupport = true; 1802 1803 unsigned maxBitsPerPixelLSB = DRF_VAL(_DPCD14, _DSC_MAXIMUM_BITS_PER_PIXEL_1, _LSB, buffer[0x7]); 1804 unsigned maxBitsPerPixelMSB = DRF_VAL(_DPCD14, _DSC_MAXIMUM_BITS_PER_PIXEL_2, _MSB, buffer[0x8]); 1805 1806 dscCaps.maxBitsPerPixelX16 = (maxBitsPerPixelMSB << 8) | maxBitsPerPixelLSB; 1807 1808 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _RGB, _YES, buffer[0x9])) 1809 dscCaps.dscDecoderColorFormatCaps.bRgb = true; 1810 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _YCbCr_444, _YES, buffer[0x9])) 1811 dscCaps.dscDecoderColorFormatCaps.bYCbCr444 = true; 1812 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _YCbCr_SIMPLE_422, _YES, buffer[0x9])) 1813 dscCaps.dscDecoderColorFormatCaps.bYCbCrSimple422 = true; 1814 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _YCbCr_NATIVE_422, _YES, buffer[0x9])) 1815 dscCaps.dscDecoderColorFormatCaps.bYCbCrNative422 = true; 1816 if(FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_FORMAT_CAPABILITIES, _YCbCr_NATIVE_420, _YES, buffer[0x9])) 1817 dscCaps.dscDecoderColorFormatCaps.bYCbCrNative420 = true; 1818 1819 if (FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_DEPTH_CAPABILITIES, _12_BITS_PER_COLOR, _YES, buffer[0xa])) 1820 dscCaps.dscDecoderColorDepthMask |= DSC_BITS_PER_COLOR_MASK_12; 1821 if (FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_DEPTH_CAPABILITIES, _10_BITS_PER_COLOR, _YES, buffer[0xa])) 1822 dscCaps.dscDecoderColorDepthMask |= DSC_BITS_PER_COLOR_MASK_10; 1823 if (FLD_TEST_DRF(_DPCD14, _DSC_DECODER_COLOR_DEPTH_CAPABILITIES, _8_BITS_PER_COLOR, _YES, buffer[0xa])) 1824 dscCaps.dscDecoderColorDepthMask |= DSC_BITS_PER_COLOR_MASK_8; 1825 1826 dscCaps.dscPeakThroughputMode0 = DRF_VAL(_DPCD14, _DSC_PEAK_THROUGHPUT, _MODE0, buffer[0xb]); 1827 dscCaps.dscPeakThroughputMode1 = DRF_VAL(_DPCD14, _DSC_PEAK_THROUGHPUT, _MODE1, buffer[0xb]); 1828 1829 unsigned numOfPixels = DRF_VAL(_DPCD14, _DSC_MAXIMUM_SLICE_WIDTH, _MAX, buffer[0xc]); 1830 dscCaps.dscMaxSliceWidth = numOfPixels * 320; 1831 1832 if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1_16, buffer[0xf])) 1833 { 1834 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1_16; 1835 } 1836 else if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1_8, buffer[0xf])) 1837 { 1838 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1_8; 1839 } 1840 else if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1_4, buffer[0xf])) 1841 { 1842 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1_4; 1843 } 1844 else if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1_2, buffer[0xf])) 1845 { 1846 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1_2; 1847 } 1848 else if (FLD_TEST_DRF(_DPCD14, _DSC_BITS_PER_PIXEL_INCREMENT, _SUPPORTED, _1, buffer[0xf])) 1849 { 1850 dscCaps.dscBitsPerPixelIncrement = BITS_PER_PIXEL_PRECISION_1; 1851 } 1852 1853 return true; 1854 } 1855 1856 bool DeviceImpl::parseBranchSpecificDscCaps(const NvU8 *buffer, NvU32 bufferSize) 1857 { 1858 if (bufferSize < 3) 1859 { 1860 DP_LOG((" Branch DSC caps buffer must be greater than or equal to 3")); 1861 return false; 1862 } 1863 1864 dscCaps.branchDSCOverallThroughputMode0 = DRF_VAL(_DPCD14, _BRANCH_DSC_OVERALL_THROUGHPUT_MODE_0, _VALUE, buffer[0x0]); 1865 if (dscCaps.branchDSCOverallThroughputMode0 == 1) 1866 { 1867 dscCaps.branchDSCOverallThroughputMode0 = 680; 1868 } 1869 else if (dscCaps.branchDSCOverallThroughputMode0 >= 2) 1870 { 1871 dscCaps.branchDSCOverallThroughputMode0 = 600 + dscCaps.branchDSCOverallThroughputMode0 * 50; 1872 } 1873 1874 dscCaps.branchDSCOverallThroughputMode1 = DRF_VAL(_DPCD14, _BRANCH_DSC_OVERALL_THROUGHPUT_MODE_1, _VALUE, buffer[0x1]); 1875 if (dscCaps.branchDSCOverallThroughputMode1 == 1) 1876 { 1877 dscCaps.branchDSCOverallThroughputMode1 = 680; 1878 } 1879 else if (dscCaps.branchDSCOverallThroughputMode1 >= 2) 1880 { 1881 dscCaps.branchDSCOverallThroughputMode1 = 600 + dscCaps.branchDSCOverallThroughputMode1 * 50; 1882 } 1883 1884 dscCaps.branchDSCMaximumLineBufferWidth = DRF_VAL(_DPCD14, _BRANCH_DSC_MAXIMUM_LINE_BUFFER_WIDTH, _VALUE, buffer[0x2]); 1885 if (dscCaps.branchDSCMaximumLineBufferWidth != 0) 1886 { 1887 if (dscCaps.branchDSCMaximumLineBufferWidth >= 16) 1888 { 1889 dscCaps.branchDSCMaximumLineBufferWidth = dscCaps.branchDSCMaximumLineBufferWidth * 320; 1890 } 1891 else 1892 { 1893 dscCaps.branchDSCMaximumLineBufferWidth = 0; 1894 DP_LOG(("Value of branch DSC maximum line buffer width is invalid, so setting it to 0.")); 1895 } 1896 } 1897 return true; 1898 } 1899 1900 bool DeviceImpl::readAndParseDSCCaps() 1901 { 1902 // Allocate a buffer of 16 bytes to read DSC caps 1903 1904 unsigned sizeCompleted = 0; 1905 unsigned nakReason = NakUndefined; 1906 Address::StringBuffer sb; 1907 DP_USED(sb); 1908 1909 if(AuxBus::success != this->getDpcdData(NV_DPCD14_DSC_SUPPORT, 1910 &rawDscCaps[0], sizeof(rawDscCaps), &sizeCompleted, &nakReason)) 1911 { 1912 DP_LOG(("DP-DEV> Error querying DSC Caps on %s!", this->address.toString(sb))); 1913 return false; 1914 } 1915 1916 return parseDscCaps(&rawDscCaps[0], sizeof(rawDscCaps)); 1917 } 1918 1919 bool DeviceImpl::readAndParseBranchSpecificDSCCaps() 1920 { 1921 unsigned sizeCompleted = 0; 1922 unsigned nakReason = NakUndefined; 1923 NvU8 rawBranchSpecificDscCaps[3]; 1924 1925 if(AuxBus::success != this->getDpcdData(NV_DPCD14_BRANCH_DSC_OVERALL_THROUGHPUT_MODE_0, 1926 &rawBranchSpecificDscCaps[0], 1927 sizeof(rawBranchSpecificDscCaps), 1928 &sizeCompleted, &nakReason)) 1929 { 1930 return false; 1931 } 1932 1933 return parseBranchSpecificDscCaps(&rawBranchSpecificDscCaps[0], sizeof(rawBranchSpecificDscCaps)); 1934 } 1935 1936 void DeviceImpl::queryGUID2() 1937 { 1938 unsigned sizeCompleted = 0; 1939 unsigned nakReason = NakUndefined; 1940 Address::StringBuffer sb; 1941 DP_USED(sb); 1942 1943 if(AuxBus::success == this->getDpcdData(NV_DPCD14_GUID_2, &this->guid2.data[0], 1944 DPCD_GUID_SIZE, &sizeCompleted, &nakReason)) 1945 { 1946 if (!(this->guid2.isGuidZero())) 1947 { 1948 this->bVirtualPeerDevice = true; 1949 } 1950 } 1951 else 1952 { 1953 DP_LOG(("DP-DEV> Error querying GUID2 on %s!", this->address.toString(sb))); 1954 } 1955 } 1956 1957 bool DeviceImpl::getDscEnable(bool *pEnable) 1958 { 1959 AuxBus::status status = AuxBus::success; 1960 unsigned sizeCompleted = 0; 1961 unsigned pNakReason = 0; 1962 NvU8 byte = 0; 1963 1964 if (!pEnable || 1965 !this->isDSCPossible() || 1966 !this->devDoingDscDecompression || 1967 !this->devDoingDscDecompression->plugged) 1968 { 1969 return false; 1970 } 1971 1972 status = this->devDoingDscDecompression->getDpcdData(NV_DPCD14_DSC_ENABLE, 1973 &byte, 1974 sizeof byte, 1975 &sizeCompleted, 1976 &pNakReason); 1977 1978 if (status != AuxBus::success) 1979 { 1980 DP_LOG(("DP-DEV> Error querying DSC Enable State!")); 1981 return false; 1982 } 1983 1984 *pEnable = FLD_TEST_DRF(_DPCD14, _DSC_ENABLE, _SINK, _YES, byte); 1985 return true; 1986 } 1987 1988 void DeviceImpl::setDscDecompressionDevice(bool bDscCapBasedOnParent) 1989 { 1990 // Decide if DSC stream can be sent to new device 1991 this->bDSCPossible = false; 1992 this->devDoingDscDecompression = NULL; 1993 1994 if (this->multistream) 1995 { 1996 if ((this->peerDevice == Dongle) && 1997 (this->dpcdRevisionMajor != 0) && 1998 !bDscCapBasedOnParent) 1999 { 2000 // For Peer Type 4 device with LAM DPCD rev != 0.0, check only the device's own DSC capability. 2001 if (this->isDSCSupported()) 2002 { 2003 this->bDSCPossible = true; 2004 this->devDoingDscDecompression = this; 2005 } 2006 } 2007 else 2008 { 2009 // 2010 // Check the device's own and its parent's DSC capability. 2011 // - Sink device will do DSC cecompression when 2012 // 1. Sink device is capable of DSC decompression 2013 // 2. Sink is on a logical port (8-15) 2014 // 2015 // OR 2016 // 2017 // 1. Sink device is capable of DSC decompression 2018 // 2. Parent of sink is a Virtual Peer device 2019 // 3. Parent of sink supports DSC Pass through 2020 // 2021 // - Sink device's parent will do DSC decompression 2022 // 1. Above conditions are not true. 2023 // 2. Parent of sink supports DSC decompression. 2024 // 2025 if (this->isDSCSupported()) 2026 { 2027 if (this->isVideoSink() && this->getParent() != NULL) 2028 { 2029 if (this->isLogical()) 2030 { 2031 this->devDoingDscDecompression = this; 2032 this->bDSCPossible = true; 2033 } 2034 else if (this->parent->isVirtualPeerDevice() && 2035 this->parent->isDSCPassThroughSupported()) 2036 { 2037 // 2038 // This condition takes care of DSC capable sink devices 2039 // connected behind a DSC Pass through capable branch 2040 // 2041 this->devDoingDscDecompression = this; 2042 this->bDSCPossible = true; 2043 } 2044 else if (this->parent->isDSCDecompressionSupported()) 2045 { 2046 // 2047 // This condition takes care of DSC capable sink devices 2048 // connected behind a branch device that is not capable 2049 // of DSC pass through but can do DSC decompression. 2050 // 2051 this->bDSCPossible = true; 2052 this->devDoingDscDecompression = this->parent; 2053 } 2054 } 2055 else 2056 { 2057 if (this->isDSCDecompressionSupported()) 2058 { 2059 // This condition takes care of branch device capable of DSC decoding. 2060 this->devDoingDscDecompression = this; 2061 this->bDSCPossible = true; 2062 } 2063 } 2064 } 2065 else if (this->parent && this->parent->isDSCDecompressionSupported()) 2066 { 2067 // 2068 // This condition takes care of sink devices not capable of DSC 2069 // but parent is capable of DSC decompression. 2070 // 2071 this->bDSCPossible = true; 2072 this->devDoingDscDecompression = this->parent; 2073 } 2074 } 2075 } 2076 else 2077 { 2078 if (this->isDSCDecompressionSupported()) 2079 { 2080 this->bDSCPossible = true; 2081 this->devDoingDscDecompression = this; 2082 } 2083 } 2084 } 2085 2086 bool DeviceImpl::setDscEnable(bool enable) 2087 { 2088 NvU8 dscEnableByte = 0; 2089 NvU8 dscPassthroughByte = 0; 2090 unsigned size = 0; 2091 unsigned nakReason = NakUndefined; 2092 bool bCurrDscEnable = false; 2093 bool bDscPassThrough = false; 2094 AuxBus::status dscEnableStatus = AuxBus::success; 2095 AuxBus::status dscPassThroughStatus = AuxBus::success; 2096 Address::StringBuffer buffer; 2097 DP_USED(buffer); 2098 2099 if (!this->isDSCPossible() || !this->devDoingDscDecompression || 2100 !this->devDoingDscDecompression->plugged) 2101 { 2102 return false; 2103 } 2104 2105 if ((this->devDoingDscDecompression == this) && !this->isLogical() && !(this->peerDevice == Dongle) && this->parent != NULL) 2106 { 2107 // 2108 // If the device has a parent, that means the sink is on a MST link and 2109 // and on a MST link if DSC is possible on the path and devDoingDscDecompression 2110 // is the sink itself and sink is not on a logical port, then the parent should be 2111 // DSC Pass through capable. 2112 // 2113 bDscPassThrough = true; 2114 } 2115 2116 // 2117 // Get Current DSC Enable State 2118 // Ideally we don't need to check the current state but Synaptics DSC device, 2119 // which was used for inital DSC code developement did not follow spec and so 2120 // we have added this code. Overwriting the same value should not have any 2121 // impact as per the spec. Will remove this check once all DSC devices follow spec. 2122 // 2123 if (!getDscEnable(&bCurrDscEnable)) 2124 { 2125 DP_LOG(("DP-DEV> Not able to get DSC Enable State!")); 2126 return false; 2127 } 2128 2129 if(enable) 2130 { 2131 if(bDscPassThrough) 2132 { 2133 dscPassthroughByte = FLD_SET_DRF(_DPCD20, _DSC_ENABLE, _PASS_THROUGH, _YES, dscPassthroughByte); 2134 DP_LOG(("DP-DEV> Enabling DSC Pass through on branch device - %s", 2135 this->parent->getTopologyAddress().toString(buffer))); 2136 } 2137 2138 if (!bCurrDscEnable) 2139 { 2140 dscEnableByte = FLD_SET_DRF(_DPCD14, _DSC_ENABLE, _SINK, _YES, dscEnableByte); 2141 DP_LOG(("DP-DEV> Enabling DSC decompression on device - %s", 2142 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2143 } 2144 else 2145 { 2146 DP_LOG(("DP-DEV> DSC decompression is already enabled on device - %s", 2147 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2148 } 2149 } 2150 else 2151 { 2152 if(bDscPassThrough) 2153 { 2154 dscPassthroughByte = FLD_SET_DRF(_DPCD20, _DSC_ENABLE, _PASS_THROUGH, _NO, dscPassthroughByte); 2155 DP_LOG(("DP-DEV> Disabling DSC Pass through on branch device - %s", 2156 this->parent->getTopologyAddress().toString(buffer))); 2157 } 2158 2159 if (bCurrDscEnable) 2160 { 2161 dscEnableByte = FLD_SET_DRF(_DPCD14, _DSC_ENABLE, _SINK, _NO, dscEnableByte); 2162 DP_LOG(("DP-DEV> Disabling DSC decompression on device - %s", 2163 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2164 } 2165 else 2166 { 2167 DP_LOG(("DP-DEV> DSC decompression is already disabled on device - %s", 2168 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2169 } 2170 } 2171 2172 if (bDscPassThrough) 2173 { 2174 dscPassThroughStatus = this->parent->setDpcdData(NV_DPCD14_DSC_ENABLE, 2175 &dscPassthroughByte, sizeof dscPassthroughByte, &size, &nakReason); 2176 if (dscPassThroughStatus != AuxBus::success) 2177 { 2178 DP_LOG(("DP-DEV> Setting DSC Passthrough on parent branch %s failed", 2179 this->parent->getTopologyAddress().toString(buffer))); 2180 } 2181 } 2182 2183 if (enable != bCurrDscEnable) 2184 { 2185 dscEnableStatus = this->devDoingDscDecompression->setDpcdData(NV_DPCD14_DSC_ENABLE, 2186 &dscEnableByte, sizeof dscEnableByte, &size, &nakReason); 2187 if (dscEnableStatus != AuxBus::success) 2188 { 2189 DP_LOG(("DP-DEV> Setting DSC Enable on sink %s failed", 2190 this->devDoingDscDecompression->getTopologyAddress().toString(buffer))); 2191 2192 } 2193 } 2194 2195 if ((dscPassThroughStatus != AuxBus::success) || (dscEnableStatus != AuxBus::success)) 2196 { 2197 return false; 2198 } 2199 else 2200 { 2201 return true; 2202 } 2203 } 2204 2205 2206 2207 bool DeviceImpl::setDscEnableDPToHDMIPCON(bool bDscEnable, bool bEnablePassThroughForPCON) 2208 { 2209 NvU8 dscEnableByte = 0; 2210 unsigned size = 0; 2211 unsigned nakReason = NakUndefined; 2212 AuxBus::status dscEnableStatus = AuxBus::success; 2213 Address::StringBuffer buffer; 2214 DP_USED(buffer); 2215 2216 if (!this->isDSCPossible()) 2217 { 2218 DP_LOG(("DP-DEV> DSC is not supported on DP to HDMI PCON - %s")); 2219 return false; 2220 } 2221 2222 if (bDscEnable) 2223 { 2224 if(bEnablePassThroughForPCON) 2225 { 2226 dscEnableByte = FLD_SET_DRF(_DPCD20, _DSC_ENABLE, _PASS_THROUGH, _YES, dscEnableByte); 2227 DP_LOG(("DP-DEV> Enabling DSC Pass through on DP to HDMI PCON device - %s", 2228 this->getTopologyAddress().toString(buffer))); 2229 } 2230 else 2231 { 2232 dscEnableByte = FLD_SET_DRF(_DPCD14, _DSC_ENABLE, _SINK, _YES, dscEnableByte); 2233 DP_LOG(("DP-DEV> Enabling DSC decompression on DP to HDMI PCON device - %s", 2234 this->getTopologyAddress().toString(buffer))); 2235 } 2236 2237 } 2238 2239 dscEnableStatus = this->setDpcdData(NV_DPCD14_DSC_ENABLE, 2240 &dscEnableByte, sizeof dscEnableByte, &size, &nakReason); 2241 2242 if (dscEnableStatus != AuxBus::success) 2243 { 2244 DP_LOG(("DP-DEV> Setting DSC Enable on DP to HDMI PCON %s failed", 2245 this->getTopologyAddress().toString(buffer))); 2246 return false; 2247 2248 } 2249 2250 return true; 2251 } 2252 2253 unsigned DeviceImpl::getDscVersionMajor() 2254 { 2255 return dscCaps.versionMajor; 2256 } 2257 2258 unsigned DeviceImpl::getDscVersionMinor() 2259 { 2260 return dscCaps.versionMinor; 2261 } 2262 2263 unsigned DeviceImpl::getDscRcBufferSize() 2264 { 2265 return dscCaps.rcBuffersize; 2266 } 2267 2268 unsigned DeviceImpl::getDscRcBufferBlockSize() 2269 { 2270 return dscCaps.rcBufferBlockSize; 2271 } 2272 2273 unsigned DeviceImpl::getDscMaxSlicesPerSink() 2274 { 2275 return dscCaps.maxSlicesPerSink; 2276 } 2277 2278 unsigned DeviceImpl::getDscLineBufferBitDepth() 2279 { 2280 return dscCaps.lineBufferBitDepth; 2281 } 2282 2283 NvBool DeviceImpl::isDscBlockPredictionSupported() 2284 { 2285 return dscCaps.bDscBlockPredictionSupport; 2286 } 2287 2288 unsigned DeviceImpl::getDscMaxBitsPerPixel() 2289 { 2290 return dscCaps.maxBitsPerPixelX16; 2291 } 2292 2293 NvBool DeviceImpl::isDscRgbSupported() 2294 { 2295 return dscCaps.dscDecoderColorFormatCaps.bRgb; 2296 } 2297 2298 NvBool DeviceImpl::isDscYCbCr444Supported() 2299 { 2300 return dscCaps.dscDecoderColorFormatCaps.bYCbCr444; 2301 } 2302 2303 NvBool DeviceImpl::isDscYCbCrSimple422Supported() 2304 { 2305 return dscCaps.dscDecoderColorFormatCaps.bYCbCrSimple422; 2306 } 2307 2308 NvBool DeviceImpl::isDscYCbCr422NativeSupported() 2309 { 2310 return dscCaps.dscDecoderColorFormatCaps.bYCbCrNative422; 2311 } 2312 2313 NvBool DeviceImpl::isDscYCbCr420NativeSupported() 2314 { 2315 return dscCaps.dscDecoderColorFormatCaps.bYCbCrNative420; 2316 } 2317 2318 unsigned DeviceImpl::getDscPeakThroughputMode0() 2319 { 2320 return dscCaps.dscPeakThroughputMode0; 2321 } 2322 2323 unsigned DeviceImpl::getDscPeakThroughputModel() 2324 { 2325 return dscCaps.dscPeakThroughputMode1; 2326 } 2327 2328 unsigned DeviceImpl::getDscMaxSliceWidth() 2329 { 2330 return dscCaps.dscMaxSliceWidth; 2331 } 2332 2333 unsigned DeviceImpl::getDscDecoderColorDepthSupportMask() 2334 { 2335 return dscCaps.dscDecoderColorDepthMask; 2336 } 2337 2338 bool DeviceImpl::isFakedMuxDevice() 2339 { 2340 return connector->main->isDynamicMuxCapable() && bIsFakedMuxDevice; 2341 } 2342 2343 bool DeviceImpl::isPreviouslyFakedMuxDevice() 2344 { 2345 return connector->main->isDynamicMuxCapable() && bIsPreviouslyFakedMuxDevice; 2346 } 2347 2348 static AuxBus::status _QueryCrcSink 2349 ( 2350 DeviceImpl *bus, 2351 NvU16 *sinkCrc0, 2352 NvU16 *sinkCrc1, 2353 NvU16 *sinkCrc2 2354 ) 2355 { 2356 AuxBus::status status = AuxBus::success; 2357 // no sink op needs to be done if registers are NULL 2358 if (sinkCrc0 == NULL) return status; 2359 NvU32 addr = NV_DPCD14_DSC_CRC_0; 2360 unsigned size = 2; 2361 NvU8 cnt[2] = {0, 0}; 2362 2363 unsigned sizeCompleted = 0; 2364 unsigned nakReason = 0; 2365 2366 status = bus->getDpcdData(addr, &cnt[0], size, &sizeCompleted, &nakReason); 2367 2368 if (status != AuxBus::success) 2369 { 2370 return status; 2371 } 2372 *sinkCrc0 = (((NvU16) cnt[1]) << (sizeof(NvU8) * 8)) | cnt[0]; 2373 2374 addr = NV_DPCD14_DSC_CRC_1; 2375 size = 2; 2376 2377 status = bus->getDpcdData(addr, &cnt[0], size, &sizeCompleted, &nakReason); 2378 2379 if (status != AuxBus::success) 2380 { 2381 return status; 2382 } 2383 *sinkCrc1 = (((NvU16) cnt[1]) << (sizeof(NvU8) * 8)) | cnt[0]; 2384 2385 addr = NV_DPCD14_DSC_CRC_2; 2386 size = 2; 2387 2388 status = bus->getDpcdData(addr, &cnt[0], size, &sizeCompleted, &nakReason); 2389 2390 if (status != AuxBus::success) 2391 { 2392 return status; 2393 } 2394 *sinkCrc2 = (((NvU16) cnt[1]) << (sizeof(NvU8) * 8)) | cnt[0]; 2395 return status; 2396 } 2397 2398 AuxBus::status DeviceImpl::dscCrcControl(NvBool bEnable, gpuDscCrc *gpuData, sinkDscCrc *sinkData) 2399 { 2400 // GPU part 2401 if (this->connector->main->dscCrcTransaction(bEnable, gpuData, (NvU16*) &(activeGroup->headIndex)) != true) 2402 { 2403 return AuxBus::nack; 2404 } 2405 2406 // sink part 2407 if (!sinkData) 2408 { 2409 return AuxBus::success; 2410 } 2411 return _QueryCrcSink(this, &(sinkData->sinkCrc0), &(sinkData->sinkCrc1), &(sinkData->sinkCrc2)); 2412 } 2413 2414 bool DeviceImpl::getPCONCaps(PCONCaps *pPCONCaps) 2415 { 2416 AuxBus::status status = AuxBus::success; 2417 NvU32 addr = NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT(0); 2418 NvU8 data[4] = {0}; 2419 unsigned sizeCompleted = 0; 2420 unsigned nakReason = 0; 2421 NvU8 pConType = 0; 2422 2423 status = this->getDpcdData(addr, &data[0], sizeof(data), &sizeCompleted, &nakReason); 2424 if (status == AuxBus::success) 2425 { 2426 pConType = DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _DWNSTRM_PORT_TX_TYPE, data[0]); 2427 if (pConType == NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_TX_TYPE_HDMI) 2428 { 2429 this->connectorType = connectorHDMI; 2430 pPCONCaps->maxTmdsClkRate = data[1] * 2500000; 2431 2432 pPCONCaps->bSourceControlModeSupported = 2433 FLD_TEST_DRF(_DPCD, _DETAILED_CAP_INFO, _SRC_CONTROL_MODE_SUPPORT, _YES, data[2]); 2434 pPCONCaps->bConcurrentLTSupported = 2435 FLD_TEST_DRF(_DPCD, _DETAILED_CAP_INFO, _CONCURRENT_LT_SUPPORT, _YES, data[2]); 2436 2437 switch (DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _MAX_FRL_LINK_BW_SUPPORT, data[2])) 2438 { 2439 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_9G: 2440 pPCONCaps->maxHdmiLinkBandwidthGbps = 9; 2441 break; 2442 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_18G: 2443 pPCONCaps->maxHdmiLinkBandwidthGbps = 18; 2444 break; 2445 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_24G: 2446 pPCONCaps->maxHdmiLinkBandwidthGbps = 24; 2447 break; 2448 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_32G: 2449 pPCONCaps->maxHdmiLinkBandwidthGbps = 32; 2450 break; 2451 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_40G: 2452 pPCONCaps->maxHdmiLinkBandwidthGbps = 40; 2453 break; 2454 case NV_DPCD_DETAILED_CAP_INFO_MAX_FRL_LINK_BW_SUPPORT_48G: 2455 pPCONCaps->maxHdmiLinkBandwidthGbps = 48; 2456 break; 2457 default: 2458 pPCONCaps->maxHdmiLinkBandwidthGbps = 0; 2459 break; 2460 } 2461 2462 switch (DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _MAX_BITS_PER_COMPONENT_DEF, data[2])) 2463 { 2464 case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_10BPC: 2465 pPCONCaps->maxBpc = 10; 2466 break; 2467 case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_12BPC: 2468 pPCONCaps->maxBpc = 12; 2469 break; 2470 case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_16BPC: 2471 pPCONCaps->maxBpc = 16; 2472 break; 2473 case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_8BPC: 2474 default: 2475 pPCONCaps->maxBpc = 8; 2476 break; 2477 } 2478 2479 DP_LOG((" DP2HDMI PCON caps - Max TMDS Clk: %u LinkBWGbps: %u MaxBpc: %u", 2480 pPCONCaps->maxTmdsClkRate, pPCONCaps->maxHdmiLinkBandwidthGbps, pPCONCaps->maxBpc)); 2481 } 2482 } 2483 else 2484 { 2485 DP_LOG((" DP-DEV> Error - DPCD Read for detailed port capabilities (0x80) failed.")); 2486 return false; 2487 } 2488 return true; 2489 } 2490 2491 bool DeviceImpl::getIgnoreMSACap() 2492 { 2493 NvU8 byte = 0; 2494 unsigned size = 0; 2495 unsigned nakReason = NakUndefined; 2496 AuxBus::status status; 2497 2498 if (bIgnoreMsaCapCached) 2499 { 2500 return bIgnoreMsaCap; 2501 } 2502 2503 if (this->isMultistream()) 2504 { 2505 status = this->getDpcdData(NV_DPCD_DOWN_STREAM_PORT, 2506 &byte, sizeof byte, &size, &nakReason); 2507 if (status == AuxBus::success) 2508 { 2509 if(FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _YES, byte)) 2510 { 2511 if (this->parent && this->parent->isVirtualPeerDevice()) 2512 { 2513 byte = 0; 2514 size = 0; 2515 nakReason = NakUndefined; 2516 2517 status = this->parent->getDpcdData(NV_DPCD_DOWN_STREAM_PORT, 2518 &byte, sizeof byte, &size, &nakReason); 2519 if (status == AuxBus::success) 2520 { 2521 if(FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _YES, byte)) 2522 { 2523 bIgnoreMsaCap = true; 2524 } 2525 else 2526 { 2527 bIgnoreMsaCap = false; 2528 } 2529 bIgnoreMsaCapCached = true; 2530 } 2531 else 2532 { 2533 DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!")); 2534 return false; 2535 } 2536 } 2537 else 2538 { 2539 bIgnoreMsaCap = true; 2540 bIgnoreMsaCapCached = true; 2541 } 2542 } 2543 else 2544 { 2545 bIgnoreMsaCap = false; 2546 bIgnoreMsaCapCached = true; 2547 } 2548 } 2549 else 2550 { 2551 DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!")); 2552 return false; 2553 } 2554 } 2555 else 2556 { 2557 bIgnoreMsaCap = hal->getMsaTimingparIgnored(); 2558 bIgnoreMsaCapCached = true; 2559 } 2560 2561 return bIgnoreMsaCap; 2562 } 2563 2564 AuxRetry::status DeviceImpl::setIgnoreMSAEnable(bool msaTimingParamIgnoreEn) 2565 { 2566 NvU8 byte = 0; 2567 unsigned size = 0; 2568 unsigned nakReason = NakUndefined; 2569 AuxBus::status status; 2570 2571 if (this->isMultistream()) 2572 { 2573 status = this->getDpcdData(NV_DPCD_DOWNSPREAD_CTRL, 2574 &byte, sizeof byte, &size, &nakReason); 2575 if (status == AuxBus::success) 2576 { 2577 if (msaTimingParamIgnoreEn) 2578 { 2579 byte = FLD_SET_DRF(_DPCD, _DOWNSPREAD_CTRL, _MSA_TIMING_PAR_IGNORED, _TRUE, byte); 2580 } 2581 else 2582 { 2583 byte = FLD_SET_DRF(_DPCD, _DOWNSPREAD_CTRL, _MSA_TIMING_PAR_IGNORED, _FALSE, byte); 2584 } 2585 2586 status = this->setDpcdData(NV_DPCD_DOWNSPREAD_CTRL, 2587 &byte, sizeof byte, &size, &nakReason); 2588 if (status == AuxBus::success) 2589 { 2590 return AuxRetry::ack; 2591 } 2592 else 2593 { 2594 DP_LOG(("DP-DEV> Aux Write to DPCD offset 0x107 failed!")); 2595 return AuxRetry::nack; 2596 } 2597 } 2598 else 2599 { 2600 DP_LOG(("DP-DEV> Aux Read from DPCD offset 0x7 failed!")); 2601 return AuxRetry::nack; 2602 } 2603 } 2604 else 2605 { 2606 return hal->setIgnoreMSATimingParamters(msaTimingParamIgnoreEn); 2607 } 2608 } 2609 2610 void 2611 DeviceHDCPDetection::start() 2612 { 2613 if (parent->isNativeDPCD()) 2614 { 2615 if (!parent->isMultistream()) 2616 { 2617 goto NativeDPCDHDCPCAPRead; 2618 } 2619 else 2620 { 2621 parent->isHDCPCap = False; 2622 waivePendingHDCPCapDoneNotification(); 2623 return; 2624 } 2625 2626 NativeDPCDHDCPCAPRead: 2627 2628 BCaps bCaps = {0}; 2629 2630 parent->hal->getBCaps(bCaps, parent->BCAPS); 2631 *(parent->nvBCaps) = *(parent->BCAPS); 2632 2633 if (bCaps.HDCPCapable) 2634 { 2635 NvU8 tempBKSV[HDCP_KSV_SIZE] = {0}; 2636 if (parent->hal->getBKSV(tempBKSV)) 2637 { 2638 if (hdcpValidateKsv(tempBKSV, HDCP_KSV_SIZE)) 2639 { 2640 for (unsigned i=0; i<HDCP_KSV_SIZE; i++) 2641 parent->BKSV[i] = tempBKSV[i]; 2642 } 2643 } 2644 parent->isHDCPCap = True; 2645 waivePendingHDCPCapDoneNotification(); 2646 return; 2647 } 2648 else 2649 { 2650 unsigned char hdcp22BCAPS[HDCP22_BCAPS_SIZE]; 2651 2652 // Check if hdcp2.x only device and probe hdcp22Bcaps. 2653 parent->hal->getHdcp22BCaps(bCaps, hdcp22BCAPS); 2654 if (bCaps.HDCPCapable) 2655 { 2656 parent->nvBCaps[0] = FLD_SET_DRF_NUM(_DPCD, _HDCP_BCAPS_OFFSET, 2657 _HDCP_CAPABLE, bCaps.HDCPCapable, 2658 parent->nvBCaps[0]) | 2659 FLD_SET_DRF_NUM(_DPCD, _HDCP_BCAPS_OFFSET, _HDCP_REPEATER, 2660 bCaps.repeater, parent->nvBCaps[0]); 2661 2662 // 2663 // No need to validate 1.x bksv here and hdcp22 authentication would 2664 // validate certificate with bksv in uproc. 2665 // 2666 parent->isHDCPCap = True; 2667 waivePendingHDCPCapDoneNotification(); 2668 return; 2669 } 2670 } 2671 2672 parent->isHDCPCap = False; 2673 waivePendingHDCPCapDoneNotification(); 2674 } 2675 else 2676 { 2677 parent->isHDCPCap = False; 2678 waivePendingHDCPCapDoneNotification(); 2679 } 2680 } 2681 2682 void 2683 DeviceHDCPDetection::messageCompleted 2684 ( 2685 MessageManager::Message *from 2686 ) 2687 { 2688 if ((from == &remoteBKSVReadMessage) || 2689 (from == &remoteBCapsReadMessage) || 2690 (from == &remote22BCapsReadMessage)) 2691 { 2692 handleRemoteDpcdReadDownReply(from); 2693 } 2694 } 2695 2696 void 2697 DeviceHDCPDetection::handleRemoteDpcdReadDownReply 2698 ( 2699 MessageManager::Message *from 2700 ) 2701 { 2702 NvU8 i2cBcaps; 2703 unsigned dataCompleted; 2704 unsigned defaultReason; 2705 Address::StringBuffer sb; 2706 DP_USED(sb); 2707 2708 if (from == &remoteBKSVReadMessage) 2709 { 2710 bksvReadCompleted = true; 2711 bBKSVReadMessagePending = false; 2712 DP_LOG(("DP-QM> REMOTE_DPCD_READ(BKSV) {%p} at '%s' completed", 2713 (MessageManager::Message *)&remoteBKSVReadMessage, 2714 parent->address.toString(sb))); 2715 2716 if (remoteBKSVReadMessage.replyNumOfBytesReadDPCD() != HDCP_KSV_SIZE) 2717 { 2718 DP_ASSERT(0 && "Incomplete BKSV in remote DPCD read message"); 2719 parent->isHDCPCap = False; 2720 2721 // Destruct only when no message is pending 2722 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2723 { 2724 parent->isDeviceHDCPDetectionAlive = false; 2725 delete this; 2726 } 2727 return; 2728 } 2729 2730 DP_ASSERT(remoteBKSVReadMessage.replyPortNumber() == parent->address.tail()); 2731 if (hdcpValidateKsv(remoteBKSVReadMessage.replyGetData(), HDCP_KSV_SIZE)) 2732 { 2733 isValidBKSV = true; 2734 for (unsigned i=0; i<HDCP_KSV_SIZE; i++) 2735 parent->BKSV[i] = (remoteBKSVReadMessage.replyGetData())[i]; 2736 2737 DP_LOG(("DP-QM> Device at '%s' is with valid BKSV.", 2738 parent->address.toString(sb))); 2739 } 2740 } 2741 else if (from == &remoteBCapsReadMessage) 2742 { 2743 bCapsReadCompleted = true; 2744 bBCapsReadMessagePending = false; 2745 DP_LOG(("DP-QM> REMOTE_DPCD_READ(BCaps) {%p} at '%s' completed", 2746 (MessageManager::Message *)&remoteBCapsReadMessage, 2747 parent->address.toString(sb))); 2748 2749 if (remoteBCapsReadMessage.replyNumOfBytesReadDPCD() != HDCP_BCAPS_SIZE) 2750 { 2751 DP_ASSERT(0 && "Incomplete BCaps in remote DPCD read message"); 2752 parent->isHDCPCap = False; 2753 2754 // Destruct only when no message is pending 2755 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2756 { 2757 parent->isDeviceHDCPDetectionAlive = false; 2758 delete this; 2759 } 2760 return; 2761 } 2762 2763 DP_ASSERT(remoteBCapsReadMessage.replyPortNumber() == parent->address.tail()); 2764 if (!!(*remoteBCapsReadMessage.replyGetData() & 0x1)) 2765 { 2766 *(parent->nvBCaps) = *(parent->BCAPS) = *remoteBCapsReadMessage.replyGetData(); 2767 isBCapsHDCP = true; 2768 2769 DP_LOG(("DP-QM> Device at '%s' is with valid BCAPS : %x", 2770 parent->address.toString(sb), *remoteBCapsReadMessage.replyGetData())); 2771 } 2772 else 2773 { 2774 if (isValidBKSV) 2775 { 2776 DP_LOG(("DP-QM> Device at '%s' is with valid BKSV but Invalid BCAPS : %x", 2777 parent->address.toString(sb), *remoteBCapsReadMessage.replyGetData())); 2778 2779 // Read the BCAPS DDC offset 2780 parent->transaction(AuxBus::read, AuxBus::i2cMot, HDCP_I2C_CLIENT_ADDR, &i2cBcaps, 2781 1, &dataCompleted, &defaultReason, HDCP_BCAPS_DDC_OFFSET, 1); 2782 2783 DP_LOG(("DP-QM> Device at '%s' is with DDC BACPS: %x", 2784 parent->address.toString(sb), i2cBcaps)); 2785 2786 // If the Reserved Bit is SET, Device supports HDCP 2787 if (i2cBcaps & HDCP_BCAPS_DDC_EN_BIT) 2788 { 2789 isBCapsHDCP = true; 2790 // Set the HDCP cap BCAPS according to DP protocol 2791 *(parent->BCAPS) |= HDCP_BCAPS_DP_EN_BIT; 2792 *(parent->nvBCaps) = *(parent->BCAPS); 2793 } 2794 } 2795 else 2796 { 2797 DP_LOG(("DP-QM> Device at '%s' is without valid BKSV and BCAPS, thus try 22BCAPS")); 2798 2799 Address parentAddress = parent->address.parent(); 2800 remote22BCapsReadMessage.setMessagePriority(NV_DP_SBMSG_PRIORITY_LEVEL_DEFAULT); 2801 remote22BCapsReadMessage.set(parentAddress, parent->address.tail(), NV_DPCD_HDCP22_BCAPS_OFFSET, HDCP22_BCAPS_SIZE); 2802 bCapsReadCompleted = false; 2803 bBCapsReadMessagePending = true; 2804 messageManager->post(&remote22BCapsReadMessage, this); 2805 } 2806 } 2807 } 2808 else if (from == &remote22BCapsReadMessage) 2809 { 2810 bCapsReadCompleted = true; 2811 bBCapsReadMessagePending = false; 2812 DP_LOG(("DP-QM> REMOTE_DPCD_READ(22BCaps) {%p} at '%s' completed", 2813 (MessageManager::Message *)&remote22BCapsReadMessage, 2814 parent->address.toString(sb))); 2815 2816 if (remote22BCapsReadMessage.replyNumOfBytesReadDPCD() != HDCP22_BCAPS_SIZE) 2817 { 2818 DP_ASSERT(0 && "Incomplete 22BCaps in remote DPCD read message"); 2819 parent->isHDCPCap = False; 2820 2821 // Destruct only when no message is pending 2822 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2823 { 2824 parent->isDeviceHDCPDetectionAlive = false; 2825 delete this; 2826 } 2827 return; 2828 } 2829 2830 DP_ASSERT(remote22BCapsReadMessage.replyPortNumber() == parent->address.tail()); 2831 if (!!(*remote22BCapsReadMessage.replyGetData() & 0x2)) 2832 { 2833 unsigned char hdcp22BCAPS; 2834 2835 hdcp22BCAPS = *remote22BCapsReadMessage.replyGetData(); 2836 2837 parent->nvBCaps[0] = FLD_SET_DRF_NUM(_DPCD, _HDCP_BCAPS_OFFSET, 2838 _HDCP_CAPABLE, (hdcp22BCAPS & 0x2) ? 1 : 0, 2839 parent->nvBCaps[0]) | 2840 FLD_SET_DRF_NUM(_DPCD, _HDCP_BCAPS_OFFSET, _HDCP_REPEATER, 2841 (hdcp22BCAPS & 0x1) ? 1 : 0, parent->nvBCaps[0]); 2842 2843 // hdcp22 will validate certificate's bksv directly. 2844 isBCapsHDCP = isValidBKSV = true; 2845 2846 DP_LOG(("DP-QM> Device at '%s' is with valid 22BCAPS : %x", 2847 parent->address.toString(sb), *remote22BCapsReadMessage.replyGetData())); 2848 } 2849 } 2850 2851 if (bCapsReadCompleted && bksvReadCompleted) 2852 { 2853 // Complete remote HDCP probe and check if can power down again. 2854 if (parent->connector) 2855 { 2856 parent->connector->decPendingRemoteHdcpDetection(); 2857 parent->connector->isNoActiveStreamAndPowerdown(); 2858 } 2859 2860 if (isValidBKSV && isBCapsHDCP) 2861 { 2862 parent->isHDCPCap = True; 2863 } 2864 else 2865 { 2866 parent->isHDCPCap = False; 2867 } 2868 2869 // Destruct only when no message is pending 2870 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2871 { 2872 parent->isDeviceHDCPDetectionAlive = false; 2873 delete this; 2874 } 2875 } 2876 else 2877 { 2878 parent->isHDCPCap = Indeterminate; 2879 } 2880 } 2881 2882 bool 2883 DeviceHDCPDetection::hdcpValidateKsv 2884 ( 2885 const NvU8 *ksv, 2886 NvU32 Size 2887 ) 2888 { 2889 2890 if (HDCP_KSV_SIZE <= Size) 2891 { 2892 NvU32 i, j; 2893 NvU32 count_ones = 0; 2894 for (i=0; i < HDCP_KSV_SIZE; i++) 2895 { 2896 for (j = 0; j < 8; j++) 2897 { 2898 if (ksv[i] & (1 <<(j))) 2899 { 2900 count_ones++; 2901 } 2902 } 2903 } 2904 2905 if (count_ones == 20) 2906 { 2907 return true; 2908 } 2909 } 2910 return false; 2911 } 2912 2913 void 2914 DeviceHDCPDetection::messageFailed 2915 ( 2916 MessageManager::Message *from, 2917 NakData *nakData 2918 ) 2919 { 2920 if (from == &remoteBKSVReadMessage) 2921 { 2922 if ((retriesRemoteBKSVReadMessage < DPCD_REMOTE_DPCD_READ_MESSAGE_RETRIES) && 2923 (nakData->reason == NakDefer || nakData->reason == NakTimeout)) 2924 { 2925 retriesRemoteBKSVReadMessage++; 2926 retryRemoteBKSVReadMessage = bBKSVReadMessagePending = true; 2927 timer->queueCallback(this, "BKSV", DPCD_REMOTE_DPCD_READ_MESSAGE_COOLDOWN_BKSV); 2928 return; 2929 } 2930 // 2931 // If message failed is called after all retries have expired or due 2932 // to any other reason then reset the bBKSVReadMessagePending flag 2933 // 2934 bBKSVReadMessagePending = false; 2935 } 2936 2937 if (from == &remoteBCapsReadMessage) 2938 { 2939 if ((retriesRemoteBCapsReadMessage < DPCD_REMOTE_DPCD_READ_MESSAGE_RETRIES) && 2940 (nakData->reason == NakDefer || nakData->reason == NakTimeout)) 2941 { 2942 retriesRemoteBCapsReadMessage++; 2943 retryRemoteBCapsReadMessage = bBCapsReadMessagePending = true; 2944 timer->queueCallback(this, "BCaps", DPCD_REMOTE_DPCD_READ_MESSAGE_COOLDOWN_BKSV); 2945 return; 2946 } 2947 // 2948 // If message failed is called after all retries have expired or due 2949 // to any other reason then reset the bBCapsReadMessagePending flag 2950 // 2951 bBCapsReadMessagePending = false; 2952 } 2953 2954 if (from == &remote22BCapsReadMessage) 2955 { 2956 if ((retriesRemote22BCapsReadMessage < DPCD_REMOTE_DPCD_READ_MESSAGE_RETRIES) && 2957 (nakData->reason == NakDefer || nakData->reason == NakTimeout)) 2958 { 2959 retriesRemote22BCapsReadMessage++; 2960 retryRemote22BCapsReadMessage = bBCapsReadMessagePending = true; 2961 timer->queueCallback(this, "22BCaps", DPCD_REMOTE_DPCD_READ_MESSAGE_COOLDOWN_BKSV); 2962 return; 2963 } 2964 // 2965 // If message failed is called after all retries have expired or due to 2966 // any other reason then reset the bBCapsReadMessagePending flag 2967 // 2968 bBCapsReadMessagePending = false; 2969 } 2970 2971 parent->isHDCPCap = False; 2972 Address::StringBuffer sb; 2973 DP_USED(sb); 2974 DP_LOG(("DP-QM> Message %s {%p} at '%s' failed. Device marked as not HDCP support.", 2975 from == &remoteBKSVReadMessage ? "REMOTE_DPCD_READ(BKSV)" : 2976 from == &remoteBCapsReadMessage ? "REMOTE_DPC_READ(BCaps)" : 2977 from == &remote22BCapsReadMessage ? "REMOTE_DPC_READ(22BCaps)" : "???", 2978 from, parent->address.toString(sb))); 2979 2980 // Destruct only when no message is pending 2981 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 2982 { 2983 parent->isDeviceHDCPDetectionAlive = false; 2984 2985 // Complete remote HDCP probe and check if can power down again. 2986 if (parent->connector) 2987 { 2988 parent->connector->decPendingRemoteHdcpDetection(); 2989 parent->connector->isNoActiveStreamAndPowerdown(); 2990 } 2991 2992 delete this; 2993 } 2994 } 2995 2996 void 2997 DeviceHDCPDetection::expired 2998 ( 2999 const void *tag 3000 ) 3001 { 3002 // Clear stale HDCP states when monitor instance is already destroyed 3003 if (!parent->plugged) 3004 { 3005 if (retryRemoteBKSVReadMessage) 3006 { 3007 retryRemoteBKSVReadMessage = false; 3008 bBKSVReadMessagePending = false; 3009 } 3010 else if (retryRemoteBCapsReadMessage) 3011 { 3012 retryRemoteBCapsReadMessage = false; 3013 bBCapsReadMessagePending = false; 3014 } 3015 else if (retryRemote22BCapsReadMessage) 3016 { 3017 retryRemote22BCapsReadMessage = false; 3018 bBCapsReadMessagePending = false; 3019 } 3020 3021 if (!(bBKSVReadMessagePending || bBCapsReadMessagePending)) 3022 { 3023 parent->isDeviceHDCPDetectionAlive = false; 3024 delete this; 3025 } 3026 return; 3027 } 3028 3029 if (retryRemoteBKSVReadMessage) 3030 { 3031 Address parentAddress = parent->address.parent(); 3032 3033 Address::StringBuffer sb; 3034 DP_USED(sb); 3035 DP_LOG(("DP-QM> Requeing REMOTE_DPCD_READ_MESSAGE(BKSV) to %s", parentAddress.toString(sb))); 3036 3037 retryRemoteBKSVReadMessage = false; 3038 remoteBKSVReadMessage.set(parentAddress, parent->address.tail(), NV_DPCD_HDCP_BKSV_OFFSET, HDCP_KSV_SIZE); 3039 DP_LOG(("DP-QM> Get BKSV (remotely) for '%s' sent REMOTE_DPCD_READ {%p}", parent->address.toString(sb), &remoteBKSVReadMessage)); 3040 3041 bBKSVReadMessagePending = true; 3042 messageManager->post(&remoteBKSVReadMessage, this); 3043 } 3044 3045 if (retryRemoteBCapsReadMessage) 3046 { 3047 Address parentAddress = parent->address.parent(); 3048 3049 Address::StringBuffer sb; 3050 DP_USED(sb); 3051 DP_LOG(("DP-QM> Requeing REMOTE_DPCD_READ_MESSAGE(BCAPS) to %s", parentAddress.toString(sb))); 3052 3053 retryRemoteBCapsReadMessage = false; 3054 remoteBCapsReadMessage.set(parentAddress, parent->address.tail(), NV_DPCD_HDCP_BCAPS_OFFSET, HDCP_BCAPS_SIZE); 3055 DP_LOG(("DP-QM> Get BCaps (remotely) for '%s' sent REMOTE_DPCD_READ {%p}", parent->address.toString(sb), &remoteBCapsReadMessage)); 3056 3057 bBCapsReadMessagePending = true; 3058 messageManager->post(&remoteBCapsReadMessage, this); 3059 } 3060 3061 if (retryRemote22BCapsReadMessage) 3062 { 3063 Address parentAddress = parent->address.parent(); 3064 3065 Address::StringBuffer sb; 3066 DP_USED(sb); 3067 DP_LOG(("DP-QM> Requeing REMOTE_DPCD_READ_MESSAGE(22BCAPS) to %s", parentAddress.toString(sb))); 3068 3069 retryRemote22BCapsReadMessage = false; 3070 remote22BCapsReadMessage.set(parentAddress, parent->address.tail(), NV_DPCD_HDCP22_BCAPS_OFFSET, HDCP22_BCAPS_SIZE); 3071 DP_LOG(("DP-QM> Get 22BCaps (remotely) for '%s' sent REMOTE_DPCD_READ {%p}", parent->address.toString(sb), &remote22BCapsReadMessage)); 3072 3073 bBCapsReadMessagePending = true; 3074 messageManager->post(&remote22BCapsReadMessage, this); 3075 } 3076 3077 } 3078 3079 DeviceHDCPDetection::~DeviceHDCPDetection() 3080 { 3081 parent->isDeviceHDCPDetectionAlive = false; 3082 3083 // Clear all pending callbacks/messages 3084 if (this->timer) 3085 { 3086 this->timer->cancelCallbacks(this); 3087 } 3088 3089 if (this->messageManager) 3090 { 3091 this->messageManager->cancelAll(&remoteBKSVReadMessage); 3092 this->messageManager->cancelAll(&remoteBCapsReadMessage); 3093 this->messageManager->cancelAll(&remote22BCapsReadMessage); 3094 } 3095 } 3096 3097 void 3098 DeviceHDCPDetection::waivePendingHDCPCapDoneNotification() 3099 { 3100 // Waive the pendingHDCPCapDone notification 3101 parent->shadow.hdcpCapDone = true; 3102 parent->isDeviceHDCPDetectionAlive = false; 3103 delete this; 3104 } 3105