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