1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 1993-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /******************************* DisplayPort********************************\
25 *                                                                           *
26 * Module: dp_configcaps.cpp                                                 *
27 *    Abstraction for basic caps registers                                   *
28 *                                                                           *
29 \***************************************************************************/
30 #include "dp_internal.h"
31 #include "dp_auxbus.h"
32 #include "dp_configcaps.h"
33 #include "dp_auxdefs.h"
34 #include "displayport.h"
35 
36 using namespace DisplayPort;
37 
38 struct DPCDHALImpl : DPCDHAL
39 {
40     AuxRetry  bus;
41     Timer    * timer;
42     bool      dpcdOffline;
43     bool      bGrantsPostLtRequest;
44     bool      pc2Disabled;
45     bool      uprequestEnable;
46     bool      upstreamIsSource;
47     bool      bMultistream;
48     bool      bGpuFECSupported;
49     bool      bLttprSupported;
50     bool      bBypassILREdpRevCheck;
51     NvU32     overrideDpcdMaxLinkRate;
52     NvU32     overrideDpcdRev;
53     NvU32     overrideDpcdMaxLaneCount;
54 
55     NvU32     gpuDPSupportedVersions;
56 
57     struct _LegacyPort: public LegacyPort
58     {
59         DwnStreamPortType         type;
60         DwnStreamPortAttribute    nonEDID;
61 
62         NvU64                     maxTmdsClkRate;
63 
getDownstreamPortTypeDPCDHALImpl::_LegacyPort64         DwnStreamPortType getDownstreamPortType()
65         {
66             return type;
67         }
68 
getDownstreamNonEDIDPortAttributeDPCDHALImpl::_LegacyPort69         DwnStreamPortAttribute getDownstreamNonEDIDPortAttribute()
70         {
71             return nonEDID;
72         }
73 
getMaxTmdsClkRateDPCDHALImpl::_LegacyPort74         NvU64 getMaxTmdsClkRate()
75         {
76             return maxTmdsClkRate;
77         }
78 
79     } legacyPort[16];
80 
81     struct
82     {
83         unsigned  revisionMajor, revisionMinor;                 // DPCD offset 0
84         bool      supportsESI;
85         LinkRate  maxLinkRate;                                  // DPCD offset 1
86         unsigned  maxLaneCount;                                 // DPCD offset 2
87         unsigned  maxLanesAtHBR;
88         unsigned  maxLanesAtRBR;
89         bool      enhancedFraming;
90         bool      bPostLtAdjustmentSupport;
91 
92         bool      supportsNoHandshakeTraining;
93         bool      bSupportsTPS4;
94         unsigned  NORP;                                         // DPCD offset 4
95 
96         bool      detailedCapInfo;                              // DPCD offset 5
97         bool      downStreamPortPresent;
98         NvU8      downStreamPortType;
99 
100         unsigned  downStreamPortCount;                          // DPCD offset 7
101         bool      ouiSupported;
102         bool      msaTimingParIgnored;
103 
104         NvU16     linkRateTable[NV_DPCD_SUPPORTED_LINK_RATES__SIZE]; // DPCD offset 10 ~ 1F
105 
106         bool      supportsMultistream;                          // DPCD offset 21
107         unsigned  numberAudioEndpoints;                         // DPCD offset 22
108         bool      overrideToSST;                                // force to SST even if MST capable
109         bool      noLinkTraining;                               // DPCD offset 330h
110 
111         bool      extendedRxCapsPresent;                        // DPCD offset 000Eh [7] - Extended Receiver Capability present
112 
113         // DPCD Offset 2211h;
114         unsigned  extendedSleepWakeTimeoutRequestMs;
115         // DPCD Offset 0119h [0] - If we grant the extendedSleepWakeTimeoutRequest
116         bool      bExtendedSleepWakeTimeoutGranted;
117 
118         bool      bFECSupported;
119 
120         // DPCD Offset F0002h - Number of Physical Repeaters present (after mapping) between Source and Sink
121         unsigned  phyRepeaterCount;
122         // DPCD offset 700 - EDP_DPCD_REV
123         unsigned  eDpRevision;
124 
125         struct
126         {
127             unsigned  revisionMajor, revisionMinor;             // DPCD offset F0000h
128             LinkRate  maxLinkRate;                              // DPCD offset F0001h
129             unsigned  maxLaneCount;                             // DPCD offset F0004h
130             unsigned  phyRepeaterExtendedWakeTimeoutMs;         // DPCD offset F0005h
131             // The array to keep track of FEC capability of each LTTPR
132             bool      bFECSupportedRepeater[NV_DPCD14_PHY_REPEATER_CNT_MAX];
133             // If all the LTTPRs supports FEC
134             bool      bFECSupported;
135         } repeaterCaps;
136 
137         PCONCaps pconCaps;
138         vesaPsrSinkCaps psrCaps;
139         NvU32    videoFallbackFormats;                          // DPCD offset 0200h
140 
141     } caps;
142 
143     struct
144     {
145         unsigned  sinkCount;                                    // DPCD offset 200
146         bool      automatedTestRequest;
147         bool      cpIRQ;
148         bool      mccsIRQ;
149         bool      downRepMsgRdy;
150         bool      upReqMsgRdy;
151         bool      prErrorStatus;                                // DPCD offset 2004h[3]
152         bool      rxCapChanged;                                 // DPCD offset 2005
153         bool      linkStatusChanged;                            // DPCD offset 2005
154         bool      streamStatusChanged;                          // DPCD offset 2005
155         bool      hdmiLinkStatusChanged;                        // DPCD offset 2005
156         NvU8      eightyBitCustomPat[10];                       // DPCD offset 250 - 259
157 
158         struct
159         {
160             struct
161             {
162                 bool clockRecoveryDone;
163                 bool channelEqualizationDone;
164                 bool symbolLocked;
165             } laneStatus[4];                                         // DPCD offset 202, 203
166 
167             bool interlaneAlignDone;                                 // DPCD offset 204
168             bool downstmPortChng;
169             bool linkStatusUpdated;
170 
171             //
172             // (ESI specific) signifies that we have link trained and should
173             // update the link status in the next query to isLinkLost. Keep in
174             // mind that linkStatusChanged might still be zero.
175             //
176             bool linkStatusDirtied;
177         } laneStatusIntr;
178 
179         struct
180         {
181             bool testRequestTraining;                          // DPCD offset 218
182             LinkRate testRequestLinkRate;                      // DPCD offset 219
183             unsigned testRequestLaneCount;                     // DPCD offset 220
184         } testTraining;
185 
186         struct
187         {
188             bool testRequestEdidRead;                          // DPCD offset 218
189         } testEdid;
190 
191         struct
192         {
193             bool                testRequestPattern;            // DPCD offset 218
194             TestPatternType     testPatRequested;              // DPCD offset 221
195             NvU16               testHorTotalPixels;            // DPCD offset 222, 223
196             NvU16               testVerTotalLines;             // DPCD offset 224, 225
197             NvU16               testHorStartPixels;            // DPCD offset 226, 227
198             NvU16               testVerStartLines;             // DPCD offset 228, 229
199             NvU16               testHsyncWidthPixels;          // DPCD offset 22A, 22B
200             bool                testHsyncPolarity;
201             NvU16               testVsyncWidthLines;           // DPCD offset 22C, 22D
202             bool                testVsyncPolarity;
203             NvU16               testActiveWidthPixels;         // DPCD offset 22E, 22F
204             NvU16               testActiveHeightLines;         // DPCD offset 230, 231
205         } testPattern;
206 
207         struct
208         {
209             bool testRequestPhyCompliance;                     // DPCD offset 218
210             LinkQualityPatternType phyTestPattern;             // DPCD offset 248
211         } testPhyCompliance;
212 
213     } interrupts;
214 
215     bool bIndexedLinkrateCapable, bIndexedLinkrateEnabled;
216 
217     public:
DPCDHALImplDPCDHALImpl218     DPCDHALImpl(AuxBus * bus, Timer * timer)
219     : bus(bus),
220     timer(timer),
221     bGrantsPostLtRequest(false),
222     uprequestEnable(false),
223     upstreamIsSource(false),
224     bMultistream(false),
225     bGpuFECSupported(false),
226     bBypassILREdpRevCheck(false),
227     overrideDpcdMaxLinkRate(0),
228     overrideDpcdRev(0),
229     gpuDPSupportedVersions(0)
230     {
231         // start with default caps.
232         populateFakeDpcd();
233     }
234 
~DPCDHALImplDPCDHALImpl235     ~DPCDHALImpl()
236     {
237     }
238 
setAuxBusDPCDHALImpl239     virtual void setAuxBus(AuxBus * bus)
240     {
241         this->bus = bus;
242     }
243 
isDpcdOfflineDPCDHALImpl244     bool isDpcdOffline()
245     {
246         return dpcdOffline;
247     }
248 
setDPCDOfflineDPCDHALImpl249     void setDPCDOffline(bool bOffline)
250     {
251         dpcdOffline = bOffline;
252     }
253 
updateDPCDOfflineDPCDHALImpl254     void updateDPCDOffline()
255     {
256         NvU8 buffer[16];
257         unsigned retries = 16;
258         // Burst read from 0x00 to 0x0F.
259         if (AuxRetry::ack != bus.read(NV_DPCD_REV, &buffer[0], sizeof buffer, retries))
260         {
261             dpcdOffline = true;
262         }
263         else
264         {
265             dpcdOffline = false;
266         }
267     }
268 
setPC2DisabledDPCDHALImpl269     void setPC2Disabled(bool disabled)
270     {
271         pc2Disabled = disabled;
272     }
273 
setLttprSupportedDPCDHALImpl274     void setLttprSupported(bool isLttprSupported)
275     {
276         bLttprSupported = isLttprSupported;
277     }
278 
isPC2DisabledDPCDHALImpl279     bool isPC2Disabled()
280     {
281         return pc2Disabled;
282     }
parseAndReadCapsDPCDHALImpl283     void parseAndReadCaps()
284     {
285         NvU8 buffer[16];
286         NvU8 byte = 0;
287         AuxRetry::status status;
288         unsigned retries = 16;
289 
290         NvU8 lttprIdx = 0;
291 
292         caps.phyRepeaterCount = 0;
293 
294         // Burst read from 0x00 to 0x0F.
295 
296         //
297         // The Extended Receiver Capability field at DPCD Addresses 02200h through 022FFh is valid
298         // with DPCD Rev. 1.4 (and higher).
299         //
300         // A DPRX that supports the Extended Receiver Capability field must set the
301         // EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT bit in the TRAINING_AUX_RD_INTERVAL
302         // register (DPCD Address 0000Eh, bit 7) to 1
303         //
304         caps.extendedRxCapsPresent = false;
305         if (AuxRetry::ack == bus.read(NV_DPCD_TRAINING_AUX_RD_INTERVAL, &byte, sizeof byte))
306         {
307             caps.extendedRxCapsPresent = DRF_VAL(_DPCD14, _TRAINING_AUX_RD_INTERVAL, _EXTENDED_RX_CAP, byte);
308         }
309 
310         if (caps.extendedRxCapsPresent)
311         {
312             status = bus.read(NV_DPCD14_EXTENDED_REV, &buffer[0], sizeof buffer, retries);
313         }
314         else
315         {
316             status = bus.read(NV_DPCD_REV, &buffer[0], sizeof buffer, retries);
317         }
318 
319         if (AuxRetry::ack != status)
320         {
321             // Failed to read caps.
322             // Set an invalid state here and make sure we REMEMBER we couldn't get the caps
323             caps.revisionMajor = 0;
324             dpcdOffline = true;
325             return;
326         }
327 
328         // reset the faked dpcd flag since real LT should be possible now.
329         dpcdOffline = false;
330 
331         // reset edp revision to 0
332         caps.eDpRevision = 0;
333 
334         if (overrideDpcdRev)
335         {
336             // Override the revision no. as DPCD override regkey is set
337             caps.revisionMajor = DRF_VAL(_DPCD, _REV, _MAJOR, overrideDpcdRev);
338             caps.revisionMinor = DRF_VAL(_DPCD, _REV, _MINOR, overrideDpcdRev);
339         }
340         else
341         {
342             caps.revisionMajor = DRF_VAL(_DPCD, _REV, _MAJOR, buffer[0]);
343             caps.revisionMinor = DRF_VAL(_DPCD, _REV, _MINOR, buffer[0]);
344             if (isAtLeastVersion(1, 2))
345             {
346                 //
347                 // WAR required for panels with MSTAR chip as they report themselves as
348                 // DP1.2 but they don't support DP1.2. Check OUI & ESI sinkCount. if OUI
349                 // is not supported & sinkCount is "0", downgrade the revision to 1.1.
350                 //
351                 if (FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _OUI_SUPPORT, _NO, buffer[7]))
352                 {
353                     // Read the ESI sinkCount & overwrite revision no. if ESI not supported
354                     NvU8 esiBuffer[1] = {0};
355                     NvU32 sinkCount;
356                     AuxRetry::status status;
357                     //
358                     // Don't just check the transaction status as not-supporting ESI means it may
359                     // NACK a transaction to ESI space or may return "0" as sinkCount. We need
360                     // to override the revision Minor in both cases.
361                     //
362                     status = bus.read(NV_DPCD_SINK_COUNT_ESI, &esiBuffer[0], sizeof esiBuffer);
363                     sinkCount = DRF_VAL(_DPCD, _SINK_COUNT_ESI, _SINK_COUNT, esiBuffer[0]);
364 
365                     if ((sinkCount == 0) || (status != AuxRetry::ack))
366                     {
367                         // If ESI not supported then overwrite the revision
368                         caps.revisionMajor = 1;
369                         caps.revisionMinor = 1;
370                     }
371                 }
372 
373                 // Check if DPCD_DISPLAY_CONTROL_CAPABLE = 1
374                 if (FLD_TEST_DRF(_DPCD, _EDP_CONFIG_CAP, _DISPLAY_CONTROL_CAPABLE, _YES, buffer[0x0D]))
375                 {
376                     NvU8 edpBuffer[1] = {0};
377                     status = bus.read(NV_DPCD_EDP_REV, &edpBuffer[0], sizeof edpBuffer);
378                     caps.eDpRevision = DRF_VAL(_DPCD, _EDP, _REV_VAL, edpBuffer[0]);
379                 }
380             }
381         }
382 
383         bIndexedLinkrateCapable = false;
384 
385         if (isAtLeastVersion(1,4) && caps.extendedRxCapsPresent == false)
386         {
387             DP_ASSERT(0 && "A DPRX with DPCD Rev. 1.4 (or higher) must have Extended Receiver Capability field.");
388         }
389         // Support ESI register space only when GPU support DP1.2MST
390         caps.supportsESI = (isAtLeastVersion(1,2) &&
391                             FLD_TEST_DRF(0073_CTRL_CMD_DP, _GET_CAPS_DP_VERSIONS_SUPPORTED, _DP1_2, _YES, gpuDPSupportedVersions));
392 
393         if (caps.eDpRevision >= NV_DPCD_EDP_REV_VAL_1_4 || this->bBypassILREdpRevCheck)
394         {
395             NvU16 linkRate = 0;
396             if (getRawLinkRateTable((NvU8*)&caps.linkRateTable[0]))
397             {
398                 // First entry must be non-zero for validation
399                 if (caps.linkRateTable[0] != 0)
400                 {
401                     bIndexedLinkrateCapable = true;
402                     for (int i = 0; (i < NV_DPCD_SUPPORTED_LINK_RATES__SIZE) && caps.linkRateTable[i]; i++)
403                     {
404                         if (linkRate < caps.linkRateTable[i])
405                             linkRate = caps.linkRateTable[i];
406                     }
407                     if (linkRate)
408                         caps.maxLinkRate = LINK_RATE_KHZ_TO_MBPS((NvU64)linkRate * DP_LINK_RATE_TABLE_MULTIPLIER_KHZ);
409                 }
410             }
411         }
412         if (!bIndexedLinkrateCapable)
413         {
414             if (FLD_TEST_DRF(_DPCD, _MAX_LINK_BANDWIDTH, _VAL, _1_62_GBPS, buffer[1]))
415                 caps.maxLinkRate = RBR;
416             else if (FLD_TEST_DRF(_DPCD, _MAX_LINK_BANDWIDTH, _VAL, _2_70_GBPS, buffer[1]))
417                caps.maxLinkRate = HBR;
418             else if (FLD_TEST_DRF(_DPCD, _MAX_LINK_BANDWIDTH, _VAL, _5_40_GBPS, buffer[1]))
419                 caps.maxLinkRate = HBR2;
420             else if (FLD_TEST_DRF(_DPCD14, _MAX_LINK_BANDWIDTH, _VAL, _8_10_GBPS, buffer[1]))
421                 caps.maxLinkRate = HBR3;
422             else
423             {
424                 DP_ASSERT(0 && "Unknown max link rate. Assuming DP 1.1 defaults");
425                 caps.maxLinkRate = HBR;
426             }
427         }
428 
429         //
430         // To prevent WAR being overridden.
431         //
432         if (overrideDpcdMaxLaneCount)
433         {
434             caps.maxLaneCount = overrideDpcdMaxLaneCount;
435         }
436         else
437         {
438             caps.maxLaneCount = DRF_VAL(_DPCD, _MAX_LANE_COUNT, _LANE, buffer[0x2]);
439         }
440 
441         if (!IS_VALID_LANECOUNT(caps.maxLaneCount))
442         {
443             DP_ASSERT(0 && "Invalid lane count.  Assuming 1");
444             caps.maxLaneCount = 1;
445         }
446 
447         caps.bPostLtAdjustmentSupport = FLD_TEST_DRF(_DPCD, _MAX_LANE_COUNT, _POST_LT_ADJ_REQ_SUPPORT, _YES, buffer[0x2]);
448         caps.enhancedFraming          = FLD_TEST_DRF(_DPCD, _MAX_LANE_COUNT, _ENHANCED_FRAMING, _YES, buffer[0x2]);
449         if (isAtLeastVersion(1,1) && (!caps.enhancedFraming))
450         {
451             DP_ASSERT(0 && "A DPRX with DPCD Rev. 1.1 (or higher) must have enhanced framing capability.");
452         }
453 
454         if (isAtLeastVersion(1,2) &&
455             FLD_TEST_DRF(0073_CTRL_CMD_DP, _GET_CAPS_DP_VERSIONS_SUPPORTED, _DP1_2, _YES, gpuDPSupportedVersions) &&
456             caps.bPostLtAdjustmentSupport)
457         {
458             // Source grants post Link training adjustment support
459             bGrantsPostLtRequest = true;
460         }
461         else
462         {
463             // Disable post Link training adjustment support whenever sink does not report capability
464             // This covers the case of MST to SST transition during which initially this flag is set, we need to explicitly reset this
465             // in order to avoid PostLTAdjustment during LT.
466             bGrantsPostLtRequest = false;
467         }
468 
469         caps.supportsNoHandshakeTraining = FLD_TEST_DRF(_DPCD, _MAX_DOWNSPREAD, _NO_AUX_HANDSHAKE_LT, _TRUE, buffer[0x3]);
470         caps.bSupportsTPS4               = FLD_TEST_DRF(_DPCD14, _MAX_DOWNSPREAD, _TPS4_SUPPORTED, _YES, buffer[0x3]);
471 
472         caps.NORP = DRF_VAL(_DPCD, _NORP, _VAL, buffer[0x4]) + 1;
473 
474         caps.downStreamPortPresent = FLD_TEST_DRF(_DPCD, _DOWNSTREAMPORT, _PRESENT, _YES, buffer[0x5]);
475         caps.detailedCapInfo       = FLD_TEST_DRF(_DPCD, _DOWNSTREAMPORT, _DETAILED_CAP_INFO_AVAILABLE, _YES, buffer[0x5]);
476         caps.downStreamPortType    = DRF_VAL(_DPCD, _DOWNSTREAMPORT, _TYPE, buffer[0x5]);
477 
478         switch (DRF_VAL(_DPCD, _DOWNSTREAMPORT, _TYPE, buffer[0x5]))
479         {
480             case 0: legacyPort[0].type = DISPLAY_PORT;    break;
481             case 1: legacyPort[0].type = ANALOG_VGA;      break;
482             case 2: legacyPort[0].type = DVI;             break;
483             case 3: legacyPort[0].type = WITHOUT_EDID;    break;
484             default: DP_ASSERT(0 && "Unknown port type");    break;
485         }
486 
487         caps.downStreamPortCount = DRF_VAL(_DPCD, _DOWN_STREAM_PORT, _COUNT, buffer[0x7]);
488         caps.msaTimingParIgnored = FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _YES, buffer[0x7]);
489         caps.ouiSupported        = FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _OUI_SUPPORT, _YES, buffer[0x7]);
490 
491         if (caps.downStreamPortPresent && !caps.downStreamPortCount)
492         {
493             DP_LOG(("DPHAL> Non-compliant device, reporting downstream port present, but no downstream ports. Overriding port count to 1."));
494             caps.downStreamPortCount = 1;
495         }
496 
497         // Burst read from 0x20 to 0x22.
498         bus.read(NV_DPCD_SINK_VIDEO_FALLBACK_FORMATS, &buffer[0], 0x22 - 0x20 + 1);
499 
500         caps.videoFallbackFormats = buffer[0];
501 
502         caps.supportsMultistream = FLD_TEST_DRF(_DPCD, _MSTM, _CAP, _YES, buffer[0x1]);
503 
504         caps.numberAudioEndpoints = (unsigned)(DRF_VAL(_DPCD, _NUMBER_OF_AUDIO_ENDPOINTS, _VALUE, buffer[0x2]));
505 
506         if (bLttprSupported)
507         {
508             // Burst read from 0xF0000 to 0xF0007
509             if (AuxRetry::ack == bus.read(NV_DPCD14_LT_TUNABLE_PHY_REPEATER_REV, &buffer[0], 0x8, retries))
510             {
511                 caps.repeaterCaps.revisionMinor = DRF_VAL(_DPCD14, _LT_TUNABLE_PHY_REPEATER_REV, _MINOR, buffer[0x0]);
512                 caps.repeaterCaps.revisionMajor = DRF_VAL(_DPCD14, _LT_TUNABLE_PHY_REPEATER_REV, _MAJOR, buffer[0x0]);
513 
514                 if (lttprIsAtLeastVersion(1, 4))
515                 {
516                     caps.phyRepeaterCount = mapPhyRepeaterVal(DRF_VAL(_DPCD14, _PHY_REPEATER_CNT, _VAL, buffer[0x2]));
517 
518                     if (caps.phyRepeaterCount != 0)
519                     {
520                         if (FLD_TEST_DRF(_DPCD14, _MAX_LINK_RATE_PHY_REPEATER, _VAL, _1_62_GBPS, buffer[1]))
521                             caps.repeaterCaps.maxLinkRate = RBR;
522                         else if (FLD_TEST_DRF(_DPCD14, _MAX_LINK_RATE_PHY_REPEATER, _VAL, _2_70_GBPS, buffer[1]))
523                             caps.repeaterCaps.maxLinkRate = HBR;
524                         else if (FLD_TEST_DRF(_DPCD14, _MAX_LINK_RATE_PHY_REPEATER, _VAL, _5_40_GBPS, buffer[1]))
525                             caps.repeaterCaps.maxLinkRate = HBR2;
526                         else if (FLD_TEST_DRF(_DPCD14, _MAX_LINK_RATE_PHY_REPEATER, _VAL, _8_10_GBPS, buffer[1]))
527                             caps.repeaterCaps.maxLinkRate = HBR3;
528                         else
529                         {
530                             DP_ASSERT(0 && "Unknown max link rate or HBR2 without at least DP 1.2. Assuming DP 1.1 defaults");
531                             caps.repeaterCaps.maxLinkRate = HBR;
532                         }
533 
534                         caps.repeaterCaps.maxLaneCount =
535                              DRF_VAL(_DPCD14, _MAX_LANE_COUNT_PHY_REPEATER,
536                                      _VAL, buffer[0x4]);
537 
538                         // The cumulative number of 10ms.
539                         caps.repeaterCaps.phyRepeaterExtendedWakeTimeoutMs =
540                              DRF_VAL(_DPCD14,
541                                      _PHY_REPEATER_EXTENDED_WAKE_TIMEOUT,
542                                      _REQ, buffer[0x5]) * 10;
543 
544                         for (lttprIdx = 0; lttprIdx < caps.phyRepeaterCount; lttprIdx++)
545                         {
546                             caps.repeaterCaps.bFECSupported = true;
547                             if (AuxRetry::ack ==
548                                     bus.read(NV_DPCD14_PHY_REPEATER_FEC_CAP_0(lttprIdx), &byte, 1))
549                             {
550                                 caps.repeaterCaps.bFECSupportedRepeater[lttprIdx] =
551                                                   FLD_TEST_DRF(_DPCD14,
552                                                                _PHY_REPEATER_FEC_CAP_0,
553                                                                _FEC_CAPABLE,
554                                                                _YES,
555                                                                byte);
556 
557                                 // bFECSupported is only true if all LTTPR supports FEC.
558                                 caps.repeaterCaps.bFECSupported &=
559                                                   caps.repeaterCaps.bFECSupportedRepeater[lttprIdx];
560                             }
561                         }
562                     }
563                     else
564                     {
565                         caps.repeaterCaps.maxLinkRate = 0;
566                     }
567                 }
568                 else
569                 {
570                     // not supported DP revision, we should not be doing LTTPR training
571                     caps.phyRepeaterCount = 0;
572                     caps.repeaterCaps.maxLinkRate = 0;
573                 }
574             }
575         }
576 
577         // Check if the device requests extended sleep wake timeout
578         if (AuxRetry::ack == bus.read(NV_DPCD14_EXTENDED_DPRX_SLEEP_WAKE_TIMEOUT_REQUEST, &buffer[0], 1))
579         {
580             if (buffer[0] == NV_DPCD14_EXTENDED_DPRX_SLEEP_WAKE_TIMEOUT_REQUEST_PERIOD_1MS)
581             {
582                 caps.extendedSleepWakeTimeoutRequestMs = DP_EXTENDED_DPRX_SLEEP_WAKE_TIMEOUT_DEFAULT_MS;
583             }
584             else
585             {
586                 caps.extendedSleepWakeTimeoutRequestMs = buffer[0] * 20;
587             }
588         }
589         else
590         {
591             caps.extendedSleepWakeTimeoutRequestMs = 0;
592         }
593 
594         byte = 0U;
595         dpMemZero(&caps.psrCaps, sizeof(vesaPsrSinkCaps));
596 
597         status = bus.read(NV_DPCD_EDP_PSR_VERSION, &byte, sizeof byte);
598         if (status == AuxRetry::ack && byte > 0U)
599         {
600             caps.psrCaps.psrVersion = byte;
601         }
602 
603         if (caps.psrCaps.psrVersion)
604         {
605             unsigned psrSetupTimeMap[8] = { 330U, 275U, 220U, 165U, 110U, 55U, 0U };
606             byte = 0U;
607             if (AuxRetry::ack == bus.read(NV_DPCD_EDP_PSR_CAP, &byte, sizeof byte))
608             {
609                 caps.psrCaps.linkTrainingRequired =
610                     FLD_TEST_DRF(_DPCD_EDP, _PSR_CAP, _LT_NEEDED, _YES, byte);
611                 caps.psrCaps.psrSetupTime =
612                     psrSetupTimeMap[DRF_VAL(_DPCD_EDP, _PSR_CAP,_SETUP_TIME, byte)];
613                 caps.psrCaps.yCoordinateRequired =
614                     FLD_TEST_DRF(_DPCD_EDP, _PSR_CAP,_Y_COORD_NEEDED, _YES, byte);
615                 caps.psrCaps.psr2UpdateGranularityRequired =
616                     FLD_TEST_DRF(_DPCD_EDP, _PSR_CAP,_GRAN_REQUIRED, _YES, byte);
617             }
618 
619             // Version 2 supports PSR2 and SU
620             if (caps.psrCaps.psrVersion == 2U)
621             {
622                 NvU16 xGranular = 0U;
623                 if (AuxRetry::ack == bus.read(NV_DPCD_EDP_PSR2_X_GRANULARITY_H, &byte, sizeof byte))
624                 {
625                     xGranular = byte;
626                 }
627 
628                 byte = 0U;
629                 if (AuxRetry::ack == bus.read(NV_DPCD_EDP_PSR2_X_GRANULARITY_L, &byte, sizeof byte))
630                 {
631                     xGranular = (xGranular << 8U) | byte;
632                 }
633 
634                 caps.psrCaps.suXGranularity = xGranular;
635             }
636 
637             // version 3 supports Y coordinate
638             if (caps.psrCaps.psrVersion > 2U)
639             {
640                 if (AuxRetry::ack == bus.read(NV_DPCD_EDP_PSR2_Y_GRANULARITY, &byte, sizeof byte))
641                 {
642                     caps.psrCaps.suYGranularity = byte;
643                 }
644             }
645         }
646 
647         parsePortDescriptors();
648     }
649 
getPCONCapsDPCDHALImpl650     virtual PCONCaps * getPCONCaps()
651     {
652         return &(caps.pconCaps);
653     }
654 
getRevisionMajorDPCDHALImpl655     virtual unsigned getRevisionMajor()                                        // DPCD offset 0
656     {
657         return caps.revisionMajor;
658     }
659 
getRevisionMinorDPCDHALImpl660     virtual unsigned getRevisionMinor()
661     {
662         return caps.revisionMinor;
663     }
664 
lttprGetRevisionMajorDPCDHALImpl665     virtual unsigned lttprGetRevisionMajor()                                        // DPCD offset F0000h
666     {
667         return caps.repeaterCaps.revisionMajor;
668     }
669 
lttprGetRevisionMinorDPCDHALImpl670     virtual unsigned lttprGetRevisionMinor()
671     {
672         return caps.repeaterCaps.revisionMinor;
673     }
674 
675     //
676     // Legacy link rates: DPCD offset 1 * 27000000
677     // ILRs: DPCD offset: 0x10~0x1F
678     //
getMaxLinkRateDPCDHALImpl679     virtual LinkRate getMaxLinkRate()
680     {
681         if (caps.phyRepeaterCount == 0)
682         {
683             return caps.maxLinkRate;
684         }
685         else
686         {
687             return DP_MIN(caps.maxLinkRate, caps.repeaterCaps.maxLinkRate);
688         }
689     }
690 
getMaxLaneCountDPCDHALImpl691     virtual unsigned getMaxLaneCount()                                         // DPCD offset 2
692     {
693         if (caps.phyRepeaterCount == 0)
694             return caps.maxLaneCount;
695         else
696             return DP_MIN(caps.maxLaneCount, caps.repeaterCaps.maxLaneCount);
697     }
698 
getNoLinkTrainingDPCDHALImpl699     virtual bool getNoLinkTraining()
700     {
701         return caps.noLinkTraining;
702     }
703 
getPhyRepeaterCountDPCDHALImpl704     virtual unsigned getPhyRepeaterCount()
705     {
706         return caps.phyRepeaterCount;
707     }
708 
709     // Max lanes supported at the desired link rate.
getMaxLaneCountSupportedAtLinkRateDPCDHALImpl710     virtual unsigned getMaxLaneCountSupportedAtLinkRate(LinkRate linkRate)
711     {
712         if (linkRate == HBR)
713         {
714             if (caps.maxLanesAtHBR)
715             {
716                 return DP_MIN(caps.maxLanesAtHBR, getMaxLaneCount());
717             }
718         }
719         else if (linkRate == RBR)
720         {
721             if (caps.maxLanesAtRBR)
722             {
723                 return DP_MIN(caps.maxLanesAtRBR, getMaxLaneCount());
724             }
725         }
726         // None of the above cases got hit, simply return the max lane count
727         return getMaxLaneCount();
728     }
729 
getEnhancedFramingDPCDHALImpl730     virtual bool getEnhancedFraming()
731     {
732         return caps.enhancedFraming;
733     }
734 
getDownstreamPortDPCDHALImpl735     virtual bool getDownstreamPort(NvU8 *portType)                          // DPCD offset 5
736     {
737         *portType = caps.downStreamPortType;
738         return caps.downStreamPortPresent;
739     }
740 
getSupportsNoHandshakeTrainingDPCDHALImpl741     virtual bool getSupportsNoHandshakeTraining()
742     {
743         return caps.supportsNoHandshakeTraining;
744     }
745 
getLegacyPortCountDPCDHALImpl746     virtual unsigned getLegacyPortCount()                                // DPCD offset 7
747     {
748         return caps.downStreamPortCount;
749     }
750 
getLegacyPortDPCDHALImpl751     virtual LegacyPort * getLegacyPort(unsigned index)
752     {
753         return &legacyPort[index];
754     }
755 
getMsaTimingparIgnoredDPCDHALImpl756     virtual bool getMsaTimingparIgnored()
757     {
758         return caps.msaTimingParIgnored;
759     }
760 
getOuiSupportedDPCDHALImpl761     virtual bool getOuiSupported()
762     {
763         return caps.ouiSupported;
764     }
765 
getSDPExtnForColorimetryDPCDHALImpl766     virtual bool getSDPExtnForColorimetry()
767     {
768         bool bSDPExtnForColorimetry = false;
769         NvU8 byte = 0;
770         if (caps.extendedRxCapsPresent)
771         {
772             if (AuxRetry::ack == bus.read(NV_DPCD14_EXTENDED_DPRX_FEATURE_ENUM_LIST, &byte,  sizeof byte))
773             {
774                 bSDPExtnForColorimetry = FLD_TEST_DRF(_DPCD14, _EXTENDED_DPRX_FEATURE_ENUM_LIST,
775                                                       _VSC_SDP_EXT_FOR_COLORIMETRY, _YES, byte);
776             }
777         }
778         return bSDPExtnForColorimetry;
779     }
780 
getRootAsyncSDPSupportedDPCDHALImpl781     virtual bool getRootAsyncSDPSupported()
782     {
783         NvU8 byte = 0;
784         if (!caps.extendedRxCapsPresent)
785             return false;
786         if (AuxRetry::ack != bus.read(NV_DPCD14_DPRX_FEATURE_ENUM_LIST, &byte,  sizeof byte) ||
787             FLD_TEST_DRF(_DPCD14, _DPRX_FEATURE_ENUM_LIST, _ADAPTIVE_SYNC_SDP_SUPPORTED, _NO, byte))
788         {
789             return false;
790         }
791         if (AuxRetry::ack != bus.read(NV_DPCD_DOWN_STREAM_PORT, &byte,  sizeof byte) ||
792             FLD_TEST_DRF(_DPCD, _DOWN_STREAM_PORT, _MSA_TIMING_PAR_IGNORED, _NO, byte))
793         {
794             return false;
795         }
796         return true;
797     }
798 
setOuiSourceDPCDHALImpl799     virtual AuxRetry::status setOuiSource(unsigned ouiId, const char * model, size_t modelNameLength, NvU8 chipRevision)
800     {
801         NvU8 ouiBuffer[16];
802 
803         //  The first 3 bytes are IEEE_OUI. 2 hex digits per register.
804         ouiBuffer[0] = (ouiId >> 16) & 0xFF;
805         ouiBuffer[1] = (ouiId >> 8) & 0xFF;
806         ouiBuffer[2] = ouiId & 0xFF;
807 
808         if (caps.revisionMajor <= 0)
809             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
810 
811         if (modelNameLength > NV_DPCD_SOURCE_DEV_ID_STRING__SIZE)
812         {
813             DP_LOG(("DPHAL> setOuiSource(): modelNameLength should not be greater than 6"));
814             modelNameLength = NV_DPCD_SOURCE_DEV_ID_STRING__SIZE;
815         }
816 
817         // Next 6 bytes are Device Identification String.
818         for (unsigned int i = 0; i < modelNameLength; i++)
819         {
820             ouiBuffer[3+i] = *model;
821             if (*model)
822                 model++;
823         }
824         ouiBuffer[9] = chipRevision;
825 
826         for (int i = 0xA; i<=0xF; ++i)
827             ouiBuffer[i] = 0;
828 
829         return bus.write(NV_DPCD_SOURCE_IEEE_OUI, &ouiBuffer[0], sizeof ouiBuffer);
830     }
831 
getOuiSourceDPCDHALImpl832     virtual bool getOuiSource(unsigned &ouiId, char * modelName,
833                               size_t modelNameBufferSize, NvU8 & chipRevision)
834     {
835         NvU8 ouiBuffer[16];
836         int address = NV_DPCD_SOURCE_IEEE_OUI;
837 
838         if (caps.revisionMajor <= 0)
839             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
840 
841         // If buffer size is larger than dev_id size, the extras are not used.
842         // If buffer size is smaller, than we can only get certain bytes.
843         if (modelNameBufferSize > NV_DPCD_SOURCE_DEV_ID_STRING__SIZE)
844         {
845             modelNameBufferSize = NV_DPCD_SOURCE_DEV_ID_STRING__SIZE;
846         }
847 
848         if (AuxRetry::ack != bus.read(address, &ouiBuffer[0], sizeof ouiBuffer))
849         {
850             *modelName = 0;
851             ouiId = 0;
852             chipRevision = 0;
853             return false;
854         }
855         //  The first 3 bytes are IEEE_OUI. 2 hex digits per register.
856         ouiId = ouiBuffer[2] | (ouiBuffer[1] << 8) | (ouiBuffer[0] << 16);
857 
858         // Next 6 bytes are Device Identification String, copy as much as we can (limited buffer case).
859         unsigned int i;
860         for (i = 0; i < modelNameBufferSize; i++)
861             modelName[i] = ouiBuffer[3+i];
862 
863         chipRevision = ouiBuffer[9];
864 
865         return true;
866     }
867 
getOuiSinkDPCDHALImpl868     virtual bool getOuiSink(unsigned &ouiId, char * modelName, size_t modelNameBufferSize, NvU8 & chipRevision)
869     {
870         NvU8 ouiBuffer[16];
871         int address = NV_DPCD_SINK_IEEE_OUI;
872 
873         if (caps.revisionMajor <= 0)
874             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
875 
876         // If buffer size is larger than dev_id size, the extras are not used.
877         // If buffer size is smaller, than we can only get certain bytes.
878         if (modelNameBufferSize > NV_DPCD_SOURCE_DEV_ID_STRING__SIZE)
879         {
880             modelNameBufferSize = NV_DPCD_SOURCE_DEV_ID_STRING__SIZE;
881         }
882 
883         //
884         // Check if there is a downstream facing port (DFP)
885         // If DFP is present, device is a branch device - use branch offset
886         // Else device is a sink device - use sink offset
887         //
888         if(caps.downStreamPortPresent)
889         {
890             address = NV_DPCD_BRANCH_IEEE_OUI;
891         }
892 
893         if (AuxRetry::ack != bus.read(address, &ouiBuffer[0], sizeof ouiBuffer))
894         {
895             *modelName = 0;
896             ouiId = 0;
897             chipRevision = 0;
898             return false;
899         }
900         //  The first 3 bytes are IEEE_OUI. 2 hex digits per register.
901         ouiId = ouiBuffer[0] | (ouiBuffer[1] << 8) | (ouiBuffer[2] << 16);
902 
903         // Next 6 bytes are Device Identification String, copy as much as we can (limited buffer case).
904         unsigned int i;
905         for (i = 0; i < modelNameBufferSize; i++)
906             modelName[i] = ouiBuffer[3+i];
907 
908         chipRevision = ouiBuffer[9];
909 
910         return true;
911     }
912 
getSupportsMultistreamDPCDHALImpl913     virtual bool getSupportsMultistream()                                     // DPCD offset 21h
914     {
915         return caps.supportsMultistream && (!caps.overrideToSST);
916     }
917 
setSupportsESIDPCDHALImpl918     virtual void setSupportsESI(bool bIsESISupported)
919     {
920         caps.supportsESI = bIsESISupported;
921     }
922 
923     //
924     //  Single stream specific caps
925     //
getNumberOfAudioEndpointsDPCDHALImpl926     virtual unsigned getNumberOfAudioEndpoints()                            // DPCD offset 22h
927     {
928         if (caps.numberAudioEndpoints)
929             return caps.numberAudioEndpoints;
930         else
931             return caps.NORP > 1;
932     }
933 
getGUIDDPCDHALImpl934     virtual bool getGUID(GUID & guid)                                          // DPCD offset 30h
935     {
936         NvU8 buffer[DPCD_GUID_SIZE];
937 
938         if (caps.revisionMajor <= 0)
939             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
940 
941         bus.read(NV_DPCD_GUID, &buffer[0], sizeof(buffer));
942 
943         for (unsigned i = 0; i < DPCD_GUID_SIZE; i++)
944         {
945             guid.data[i] = buffer[i];
946         }
947         return true;
948     }
949 
setGUIDDPCDHALImpl950     virtual AuxRetry::status setGUID(GUID & guid)
951     {
952         NvU8 buffer[DPCD_GUID_SIZE];
953 
954         if (caps.revisionMajor <= 0)
955             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
956 
957         for (unsigned i = 0; i < DPCD_GUID_SIZE; i++)
958         {
959             buffer[i] = guid.data[i];
960         }
961 
962         return bus.write(NV_DPCD_GUID, buffer, sizeof(buffer));
963     }
964 
parsePortDescriptorsDPCDHALImpl965     void parsePortDescriptors()
966     {
967         NvU8 basicCaps[128];
968         unsigned bytesPerPort = caps.detailedCapInfo ? 4 : 1;
969         // When Detailed_cap_info_available bit is set to 1, the max number
970         // of downstream port is limited to 32. Otherwise it supports up to 127
971         unsigned maxPorts = caps.detailedCapInfo ? 32 : 127;
972         unsigned infoByte0;
973         if (caps.downStreamPortCount > maxPorts)
974             caps.downStreamPortCount = 1;
975         unsigned size = (bytesPerPort * caps.downStreamPortCount);
976 
977         if (AuxRetry::ack != bus.read(NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT(0), &basicCaps[0], size))
978         {
979             DP_LOG(("DPHAL> Unable to read detailed caps!"));
980             caps.downStreamPortCount = 0;
981             return;
982         }
983 
984         if (!((isVersion(1,0)) ||
985               (isVersion(1,1) && basicCaps[0] == 0 &&
986                legacyPort[0].type == ANALOG_VGA)))
987         {
988             for (unsigned port = 0; port < caps.downStreamPortCount; port++)
989             {
990                 //  The index to access detailed info byte 0
991                 infoByte0 = port * bytesPerPort;
992                 switch (DRF_VAL(_DPCD, _DETAILED_CAP_INFO_DWNSTRM_PORT, _TX_TYPE, basicCaps[infoByte0]))
993                 {
994                 case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_TX_TYPE_DISPLAYPORT:
995                     {
996                         legacyPort[port].type = DISPLAY_PORT;
997                         break;
998                     }
999                 case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_TX_TYPE_ANALOG:
1000                     {
1001                         legacyPort[port].type = ANALOG_VGA;
1002                         break;
1003                     }
1004                 case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_TX_TYPE_DVI:
1005                     {
1006                         legacyPort[port].type = DVI;
1007                         break;
1008                     }
1009                 case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_TX_TYPE_HDMI:
1010                     {
1011                         NvU8    pConCaps   = basicCaps[infoByte0+2];
1012 
1013                         legacyPort[port].type = HDMI;
1014 
1015                         caps.pconCaps.maxTmdsClkRate = basicCaps[infoByte0+1];
1016 
1017                         caps.pconCaps.bSourceControlModeSupported =
1018                              FLD_TEST_DRF(_DPCD, _DETAILED_CAP_INFO, _SRC_CONTROL_MODE_SUPPORT, _YES, pConCaps);
1019                         caps.pconCaps.bConcurrentLTSupported =
1020                              FLD_TEST_DRF(_DPCD, _DETAILED_CAP_INFO, _CONCURRENT_LT_SUPPORT, _YES, pConCaps);
1021                         caps.pconCaps.maxHdmiLinkBandwidthGbps =
1022                              DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _MAX_FRL_LINK_BW_SUPPORT, pConCaps);
1023 
1024                         switch (DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _MAX_BITS_PER_COMPONENT_DEF, pConCaps))
1025                         {
1026                             case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_10BPC:
1027                                 caps.pconCaps.maxBpc = 10;
1028                                 break;
1029                             case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_12BPC:
1030                                 caps.pconCaps.maxBpc = 12;
1031                                 break;
1032                             case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_16BPC:
1033                                 caps.pconCaps.maxBpc = 16;
1034                                 break;
1035                             case NV_DPCD_DETAILED_CAP_INFO_MAX_BITS_PER_COMPONENT_DEF_8BPC:
1036                             default:
1037                                 caps.pconCaps.maxBpc = 8;
1038                                 break;
1039                         }
1040 
1041                         NvU8    pConColorConvCaps   = basicCaps[infoByte0+3];
1042                         caps.pconCaps.bConv444To420Supported = FLD_TEST_DRF(_DPCD, _DETAILED_CAP, _CONV_YCBCR444_TO_YCBCR420_SUPPORTED, _YES, pConColorConvCaps);
1043                         break;
1044                     }
1045                 case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_TX_TYPE_OTHERS_NO_EDID:
1046                     {
1047                         legacyPort[port].type = WITHOUT_EDID;
1048                         switch (DRF_VAL(_DPCD, _DETAILED_CAP_INFO_DWNSTRM_PORT, _NON_EDID_ATTR, basicCaps[infoByte0]))
1049                         {
1050                         default:
1051                             {
1052                                 DP_ASSERT(0 && "Unknown non-edid type, assume Reserved");
1053                                 legacyPort[port].nonEDID  = RESERVED;
1054                                 break;
1055                             }
1056                         case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_NON_EDID_480I_60HZ:
1057                             {
1058                                 legacyPort[port].nonEDID  = IL_720_480_60HZ;
1059                                 break;
1060                             }
1061                         case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_NON_EDID_480I_50HZ:
1062                             {
1063                                 legacyPort[port].nonEDID  = IL_720_480_50HZ;
1064                                 break;
1065                             }
1066                         case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_NON_EDID_1080I_60HZ:
1067                             {
1068                                 legacyPort[port].nonEDID  = IL_1920_1080_60HZ;
1069                                 break;
1070                             }
1071                         case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_NON_EDID_1080I_50HZ:
1072                             {
1073                                 legacyPort[port].nonEDID  = IL_1920_1080_50HZ;
1074                                 break;
1075                             }
1076                         case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_NON_EDID_720P_60HZ:
1077                             {
1078                                 legacyPort[port].nonEDID  = PG_1280_720_60HZ;
1079                                 break;
1080                             }
1081                         case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_NON_EDID_720P_50HZ:
1082                             {
1083                                 legacyPort[port].nonEDID  = PG_1280_720_50_HZ;
1084                                 break;
1085                             }
1086                         }
1087                         break;
1088                     }
1089                 case NV_DPCD_DETAILED_CAP_INFO_DWNSTRM_PORT_TX_TYPE_DP_PLUSPLUS:
1090                     {
1091                         legacyPort[port].type = DISPLAY_PORT_PLUSPLUS;
1092                         break;
1093                     }
1094                 default:
1095                     {
1096                         DP_ASSERT(0 && "Unknown port type");
1097                         break;
1098                     }
1099                 }
1100 
1101                 // Set the Init value to Zero
1102                 legacyPort[port].maxTmdsClkRate = 0;
1103 
1104                 if (legacyPort[port].type == DVI ||
1105                       legacyPort[port].type == HDMI ||
1106                       legacyPort[port].type == DISPLAY_PORT_PLUSPLUS)
1107                 {
1108                     legacyPort[port].maxTmdsClkRate = ((NvU64)basicCaps[infoByte0 + 1]) * 2500000;
1109                     if (legacyPort[port].maxTmdsClkRate == 0)
1110                     {
1111                         DP_ASSERT(legacyPort[port].maxTmdsClkRate && "No Max TMDS clock rate limits.");
1112                     }
1113 
1114                     /*
1115                         Bug : 3202060
1116                         Parse Byte 2 as well to check the Dongle supports HDMI FRL Output
1117                         If HDMI FRL is supported, the maxTmdsClkRate limit should be removed.
1118                     */
1119 
1120                     if (DRF_VAL(_DPCD, _DETAILED_CAP_INFO, _MAX_FRL_LINK_BW_SUPPORT, basicCaps[infoByte0 + 2]))
1121                     {
1122                         // Disable the TMDS CLK Limit
1123                         legacyPort[port].maxTmdsClkRate = 0;
1124                     }
1125                 }
1126             }
1127         }
1128     }
1129 
1130     //
1131     //  Notifications of external events
1132     //
notifyIRQDPCDHALImpl1133     virtual void notifyIRQ()
1134     {
1135         parseAndReadInterrupts();
1136     }
1137 
populateFakeDpcdDPCDHALImpl1138     virtual void populateFakeDpcd()
1139     {
1140         dpcdOffline = true;
1141         // fill out the bare minimum caps required ... this should be extended in for more dpcd offsets in future.
1142         caps.revisionMajor = 0x1;
1143         caps.revisionMinor = 0x1;
1144         caps.supportsESI = false;
1145         caps.maxLinkRate = HBR3;
1146         caps.maxLaneCount = 4;
1147         caps.enhancedFraming = true;
1148         caps.downStreamPortPresent = true;
1149         caps.downStreamPortCount = 1;
1150 
1151         // populate the sinkcount interrupt
1152         interrupts.sinkCount = 1;
1153     }
1154 
1155     // DPCD override routine: Max link rate override.
overrideMaxLinkRateDPCDHALImpl1156     void overrideMaxLinkRate(NvU32 overrideMaxLinkRate)
1157     {
1158         if (overrideMaxLinkRate)
1159         {
1160             caps.maxLinkRate = mapLinkBandiwdthToLinkrate(overrideMaxLinkRate);
1161         }
1162     }
1163 
1164     // DPCD override routine: Max lane count override.
overrideMaxLaneCountDPCDHALImpl1165     void overrideMaxLaneCount(NvU32 maxLaneCount)
1166     {
1167         caps.maxLaneCount = maxLaneCount;
1168         overrideDpcdMaxLaneCount = maxLaneCount;
1169     }
1170 
1171     // DPCD override routine: Max lane count override at a given link rate.
skipCableBWCheckDPCDHALImpl1172     void skipCableBWCheck(NvU32 maxLaneAtHighRate, NvU32 maxLaneAtLowRate)
1173     {
1174         caps.maxLanesAtHBR = maxLaneAtHighRate;
1175         caps.maxLanesAtRBR = maxLaneAtLowRate;
1176     }
1177 
1178     // DPCD override routine: Optimal link config (link rate and lane count) override.
overrideOptimalLinkCfgDPCDHALImpl1179     void overrideOptimalLinkCfg(LinkRate optimalLinkRate,
1180                                 NvU32 optimalLaneCount)
1181     {
1182         caps.maxLinkRate = optimalLinkRate;
1183         caps.maxLaneCount = optimalLaneCount;
1184     }
1185 
1186     // DPCD override routine: Optimal link rate
overrideOptimalLinkRateDPCDHALImpl1187     void overrideOptimalLinkRate(LinkRate optimalLinkRate)
1188     {
1189         caps.maxLinkRate = optimalLinkRate;
1190     }
1191 
notifyHPDDPCDHALImpl1192     virtual void notifyHPD(bool status, bool bSkipDPCDRead)
1193     {
1194         if (!status)
1195         {
1196             // check if dpcd is alive
1197             NvU8 buffer;
1198             unsigned retries = 16;
1199             if (AuxRetry::ack == bus.read(NV_DPCD_REV, &buffer, sizeof buffer, retries))
1200                 return;
1201 
1202             // Support for EDID locking:
1203             // Refill the cache with "default" dpcd data on an unplug event as later on
1204             // the client may send a hot-plug event for edid locked fake device (no real dpcd).
1205             // Also raise flag "dpcdOffline" so that dpcd accesses may be optimized.
1206             populateFakeDpcd();
1207             return;
1208         }
1209 
1210         // Skip DPCD read if requested.
1211         if (!bSkipDPCDRead)
1212         {
1213             parseAndReadCaps();
1214         }
1215 
1216         //
1217         // For Allienware eDp Panel more time is required to assert the HPD &
1218         // power on the AUX link. Retry 1 more time if it has failed. This is
1219         // a BAD way to do it but no EDID is available to differentiate here
1220         // this is the first access which happens before EDID read to read caps.
1221         // We also found that some LG panels on HP NBs goes in a bad state after
1222         // factory reset. Retyring 3 times works for them. So making faultyRetries as 3.
1223         //
1224         NvU32 faultyRetries = 3;
1225         while ((dpcdOffline) && (faultyRetries > 0))
1226         {
1227             // Read the caps again
1228             parseAndReadCaps();
1229             --faultyRetries;
1230         }
1231 
1232         parseAndReadInterrupts();
1233     }
1234 
isPostLtAdjustRequestSupportedDPCDHALImpl1235     virtual bool isPostLtAdjustRequestSupported()
1236     {
1237         //
1238         // If the upstream DPTX and downstream DPRX both support TPS4,
1239         // TPS4 shall be used instead of POST_LT_ADJ_REQ.
1240         //
1241         NvBool bTps4Supported = FLD_TEST_DRF(0073_CTRL_CMD_DP, _GET_CAPS_DP_VERSIONS_SUPPORTED, _DP1_4, _YES, gpuDPSupportedVersions) &&
1242                                 caps.bSupportsTPS4;
1243         return bGrantsPostLtRequest && !bTps4Supported;
1244     }
1245 
setPostLtAdjustRequestGrantedDPCDHALImpl1246     virtual void setPostLtAdjustRequestGranted(bool bGrantPostLtRequest)
1247     {
1248         NvU8 data = 0;
1249 
1250         bus.read(NV_DPCD_LANE_COUNT_SET, &data, sizeof data);
1251 
1252         if (bGrantPostLtRequest)
1253         {
1254             data = FLD_SET_DRF(_DPCD, _LANE_COUNT_SET, _POST_LT_ADJ_REQ_GRANTED, _YES, data);
1255         }
1256 
1257         else
1258         {
1259             data = FLD_SET_DRF(_DPCD, _LANE_COUNT_SET, _POST_LT_ADJ_REQ_GRANTED, _NO, data);
1260         }
1261 
1262         if (AuxRetry::ack != bus.write(NV_DPCD_LANE_COUNT_SET, &data, sizeof data))
1263         {
1264             DP_LOG(("DPCONN> Failed to set POST_LT_ADJ_REQ_GRANTED bit."));
1265         }
1266     }
1267 
getIsPostLtAdjRequestInProgressDPCDHALImpl1268     virtual bool getIsPostLtAdjRequestInProgress()               // DPCD offset 204
1269     {
1270         NvU8 buffer;
1271 
1272         if (AuxRetry::ack != bus.read(NV_DPCD_LANE_ALIGN_STATUS_UPDATED, &buffer, 1))
1273         {
1274             DP_LOG(("DPCONN> Post Link Training : Failed to read POST_LT_ADJ_REQ_IN_PROGRESS"));
1275             return false;
1276         }
1277 
1278         return FLD_TEST_DRF(_DPCD, _LANE_ALIGN_STATUS_UPDATED,
1279                             _POST_LT_ADJ_REQ_IN_PROGRESS, _YES, buffer);
1280     }
1281 
getTrainingPatternSelectDPCDHALImpl1282     virtual TrainingPatternSelectType getTrainingPatternSelect()
1283     {
1284         NvU8 trainingPat = 0;
1285         TrainingPatternSelectType pattern = TRAINING_DISABLED;
1286 
1287         if (caps.revisionMajor <= 0)
1288             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
1289 
1290         bus.read(NV_DPCD_TRAINING_PATTERN_SET, &trainingPat, sizeof trainingPat);
1291 
1292         trainingPat = DRF_VAL(_DPCD, _TRAINING_PATTERN_SET, _TPS, trainingPat);
1293 
1294         if (trainingPat == NV_DPCD_TRAINING_PATTERN_SET_TPS_NONE)
1295             pattern = TRAINING_DISABLED;
1296         if (trainingPat == NV_DPCD_TRAINING_PATTERN_SET_TPS_TP1)
1297             pattern = TRAINING_PAT_ONE;
1298         if (trainingPat == NV_DPCD_TRAINING_PATTERN_SET_TPS_TP2)
1299             pattern = TRAINING_PAT_TWO;
1300         if (trainingPat == NV_DPCD_TRAINING_PATTERN_SET_TPS_TP3)
1301             pattern = TRAINING_PAT_THREE;
1302 
1303         return pattern;
1304     }
1305 
setTrainingMultiLaneSetDPCDHALImpl1306     virtual bool setTrainingMultiLaneSet(NvU8 numLanes,
1307                                          NvU8 *voltSwingSet,
1308                                          NvU8 *preEmphasisSet)
1309     {
1310         NvU8 trainingCtrl[DP_MAX_LANES] = {0};
1311         unsigned writeAddress = NV_DPCD_TRAINING_LANE_SET(0);
1312         NvU8 laneIndex;
1313 
1314         if (caps.revisionMajor <= 0)
1315             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
1316 
1317         for (laneIndex = 0; laneIndex < numLanes; laneIndex++)
1318         {
1319             if (voltSwingSet[laneIndex] <= NV_DPCD_MAX_VOLTAGE_SWING)
1320             {
1321                 trainingCtrl[laneIndex] = FLD_SET_DRF_NUM(_DPCD, _TRAINING_LANE_SET,
1322                                                           _VOLTAGE_SWING, voltSwingSet[laneIndex],
1323                                                           trainingCtrl[laneIndex]);
1324             }
1325             else
1326             {
1327                 DP_ASSERT(0 && "Out of bounds voltage swing.  Assuming 0");
1328             }
1329 
1330             if (voltSwingSet[laneIndex] == NV_DPCD_MAX_VOLTAGE_SWING)
1331             {
1332                 trainingCtrl[laneIndex] = FLD_SET_DRF(_DPCD, _TRAINING_LANE_SET,
1333                                                       _VOLTAGE_SWING_MAX_REACHED,
1334                                                       _TRUE, trainingCtrl[laneIndex]);
1335             }
1336 
1337             if (preEmphasisSet[laneIndex] <= NV_DPCD_MAX_VOLTAGE_PREEMPHASIS)
1338             {
1339                 trainingCtrl[laneIndex] = FLD_SET_DRF_NUM(_DPCD, _TRAINING_LANE_SET,
1340                                                           _PREEMPHASIS, preEmphasisSet[laneIndex],
1341                                                           trainingCtrl[laneIndex]);
1342             }
1343             else
1344             {
1345                 DP_ASSERT(0 && "Out of bounds preemphasis.  Assuming 0");
1346             }
1347 
1348             if (preEmphasisSet[laneIndex] == NV_DPCD_MAX_VOLTAGE_PREEMPHASIS)
1349             {
1350                 trainingCtrl[laneIndex] = FLD_SET_DRF(_DPCD, _TRAINING_LANE_SET,
1351                                                       _PREEMPHASIS_MAX_REACHED, _TRUE,
1352                                                       trainingCtrl[laneIndex]);
1353             }
1354         }
1355 
1356         return(AuxRetry::ack == bus.write(writeAddress, trainingCtrl, (unsigned)numLanes));
1357     }
1358 
setIgnoreMSATimingParamtersDPCDHALImpl1359     virtual AuxRetry::status setIgnoreMSATimingParamters(bool msaTimingParamIgnoreEn)
1360     {
1361 
1362         NvU8 downspreadCtrl = 0;
1363 
1364         if (caps.revisionMajor <= 0)
1365             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
1366 
1367         bus.read(NV_DPCD_DOWNSPREAD_CTRL, &downspreadCtrl, sizeof downspreadCtrl);
1368 
1369         if (msaTimingParamIgnoreEn)
1370             downspreadCtrl = FLD_SET_DRF(_DPCD, _DOWNSPREAD_CTRL, _MSA_TIMING_PAR_IGNORED, _TRUE, downspreadCtrl);
1371         else
1372             downspreadCtrl = FLD_SET_DRF(_DPCD, _DOWNSPREAD_CTRL, _MSA_TIMING_PAR_IGNORED, _FALSE, downspreadCtrl);
1373 
1374         return bus.write(NV_DPCD_DOWNSPREAD_CTRL, &downspreadCtrl, sizeof downspreadCtrl);
1375     }
1376 
setLinkQualPatternSetDPCDHALImpl1377     virtual AuxRetry::status setLinkQualPatternSet(LinkQualityPatternType linkQualPattern, unsigned laneCount)
1378     {
1379         if (caps.revisionMajor <= 0)
1380         {
1381             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
1382             return AuxRetry::nack;
1383         }
1384 
1385         if (this->isVersion(1, 1) == true)
1386         {
1387             NvU8 buffer = 0;
1388             if (AuxRetry::ack != bus.read(NV_DPCD_TRAINING_PATTERN_SET, &buffer, 1))
1389             {
1390                 DP_ASSERT(0 && "Can't read from NV_DPCD_TRAINING_PATTERN_SET.");
1391                 return AuxRetry::nack;
1392             }
1393 
1394             // write on bits 3:2
1395             NvU8 value = ((linkQualPattern << 2) & 0xc) | (buffer & (~0xc));
1396             return bus.write(NV_DPCD_TRAINING_PATTERN_SET, &value, sizeof value);
1397         }
1398         else if (isAtLeastVersion(1,2) == true)
1399         {
1400             AuxRetry::status requestStatus = AuxRetry::nack ;
1401 
1402             // Set test patterns for all requested lanes
1403             for (unsigned i = 0; i < laneCount; i++)
1404             {
1405                 requestStatus = setLinkQualLaneSet(i, linkQualPattern);
1406                 if (requestStatus != AuxRetry::ack)
1407                     break;
1408             }
1409 
1410             return requestStatus;
1411         }
1412         else
1413         {
1414             DP_ASSERT(0 && "Regs only supported for DP1.2");
1415             return AuxRetry::unsupportedRegister;
1416         }
1417     }
1418 
setLinkQualLaneSetDPCDHALImpl1419     virtual AuxRetry::status setLinkQualLaneSet(unsigned lane, LinkQualityPatternType linkQualPattern)
1420     {
1421         NvU8 linkQuality = 0;
1422         unsigned writeAddress = NV_DPCD_LINK_QUAL_LANE_SET(lane);
1423 
1424         if (caps.revisionMajor <= 0)
1425             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
1426 
1427         if (isAtLeastVersion(1,2) == false)
1428         {
1429             DP_ASSERT(0 && "Regs only supported for DP1.2");
1430             return AuxRetry::unsupportedRegister;
1431         }
1432 
1433         // check if parameter is valid
1434         if (lane >= displayPort_LaneSupported)
1435         {
1436             DP_ASSERT(0 && "Unknown lane selected.  Assuming Lane 0");
1437             writeAddress = NV_DPCD_LINK_QUAL_LANE_SET(0);
1438         }
1439 
1440         if (linkQualPattern == LINK_QUAL_DISABLED)
1441             linkQuality = FLD_SET_DRF(_DPCD, _LINK_QUAL_LANE_SET, _LQS, _NO, linkQuality);
1442         if (linkQualPattern == LINK_QUAL_D10_2)
1443             linkQuality = FLD_SET_DRF(_DPCD, _LINK_QUAL_LANE_SET, _LQS, _D10_2, linkQuality);
1444         if (linkQualPattern == LINK_QUAL_SYM_ERROR)
1445             linkQuality = FLD_SET_DRF(_DPCD, _LINK_QUAL_LANE_SET, _LQS, _SYM_ERR_MEASUREMENT_CNT, linkQuality);
1446         if (linkQualPattern == LINK_QUAL_PRBS7)
1447             linkQuality = FLD_SET_DRF(_DPCD, _LINK_QUAL_LANE_SET, _LQS, _PRBS7, linkQuality);
1448         if (linkQualPattern == LINK_QUAL_80BIT_CUST)
1449             linkQuality = FLD_SET_DRF(_DPCD, _LINK_QUAL_LANE_SET, _LQS, _80_BIT_CUSTOM, linkQuality);
1450         if (linkQualPattern == LINK_QUAL_HBR2_COMPLIANCE_EYE)
1451             linkQuality = FLD_SET_DRF(_DPCD, _LINK_QUAL_LANE_SET, _LQS, _HBR2, linkQuality);
1452         if (linkQualPattern == LINK_QUAL_CP2520PAT3)
1453             linkQuality = FLD_SET_DRF(_DPCD14, _LINK_QUAL_LANE_SET, _LQS, _CP2520PAT3, linkQuality);
1454 
1455         return bus.write(writeAddress, &linkQuality, sizeof linkQuality);
1456     }
1457 
setMessagingEnableDPCDHALImpl1458     virtual AuxRetry::status setMessagingEnable(bool _uprequestEnable, bool _upstreamIsSource)
1459     {
1460         NvU8 mstmCtrl = 0;
1461 
1462         if (!this->isAtLeastVersion(1, 2))
1463         {
1464             DP_ASSERT(!_uprequestEnable && "Can't enable multistream on DP 1.1");
1465             return AuxRetry::nack;
1466         }
1467 
1468         uprequestEnable = _uprequestEnable;
1469         upstreamIsSource = _upstreamIsSource;
1470 
1471         //
1472         // Lets not touch the MST enable bit here.
1473         // Branch might be getting driven in MST mode and we do not want to
1474         // change that unless we are sure there are no more streams being driven.
1475         //
1476         if (AuxRetry::ack != bus.read(NV_DPCD_MSTM_CTRL, &mstmCtrl, 1))
1477         {
1478             DP_LOG(("DPHAL> ERROR! Unable to read 00111h MSTM_CTRL."));
1479         }
1480 
1481         if (_uprequestEnable)
1482         {
1483             bMultistream = FLD_TEST_DRF(_DPCD, _MSTM_CTRL, _EN, _YES, mstmCtrl);
1484         }
1485         else
1486         {
1487             bMultistream = false;
1488         }
1489         mstmCtrl = 0;
1490         if (bMultistream)
1491             mstmCtrl = FLD_SET_DRF(_DPCD, _MSTM_CTRL, _EN, _YES, mstmCtrl);
1492         if (uprequestEnable)
1493             mstmCtrl = FLD_SET_DRF(_DPCD, _MSTM_CTRL, _UP_REQ_EN, _YES, mstmCtrl);
1494         if (upstreamIsSource)
1495             mstmCtrl = FLD_SET_DRF(_DPCD, _MSTM_CTRL, _UPSTREAM_IS_SRC, _YES, mstmCtrl);
1496 
1497         return bus.write(NV_DPCD_MSTM_CTRL, &mstmCtrl, sizeof mstmCtrl);
1498     }
1499 
setMultistreamLinkDPCDHALImpl1500     virtual AuxRetry::status setMultistreamLink(bool enable)
1501     {
1502         NvU8 mstmCtrl = 0;
1503 
1504         if (!this->isAtLeastVersion(1, 2))
1505         {
1506             DP_ASSERT(!enable && "Can't enable multistream on DP 1.1");
1507             return AuxRetry::nack;
1508         }
1509 
1510         bMultistream = enable;
1511 
1512         if (bMultistream)
1513             mstmCtrl = FLD_SET_DRF(_DPCD, _MSTM_CTRL, _EN, _YES, mstmCtrl);
1514         if (uprequestEnable)
1515             mstmCtrl = FLD_SET_DRF(_DPCD, _MSTM_CTRL, _UP_REQ_EN, _YES, mstmCtrl);
1516         if (upstreamIsSource)
1517             mstmCtrl = FLD_SET_DRF(_DPCD, _MSTM_CTRL, _UPSTREAM_IS_SRC, _YES, mstmCtrl);
1518 
1519         return bus.write(NV_DPCD_MSTM_CTRL, &mstmCtrl, sizeof mstmCtrl);
1520     }
1521 
setMultistreamHotplugModeDPCDHALImpl1522     virtual AuxRetry::status setMultistreamHotplugMode(MultistreamHotplugMode notifyType)
1523     {
1524         NvU8 deviceCtrl = 0;
1525 
1526         if (caps.revisionMajor <= 0)
1527             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
1528 
1529         //  notifytype == HPD_LONG_PULSE, adapter 0
1530         if (notifyType == IRQ_HPD)
1531             deviceCtrl = FLD_SET_DRF(_DPCD, _BRANCH_DEV_CTRL, _HOTPLUG_EVENT_TYPE, _IRQ_HPD, deviceCtrl);
1532 
1533         return bus.write(NV_DPCD_BRANCH_DEV_CTRL, &deviceCtrl, sizeof deviceCtrl);
1534     }
1535 
1536 
parseTestRequestTrainingDPCDHALImpl1537     bool parseTestRequestTraining(NvU8 * buffer /* 0x18-0x28 valid */)
1538     {
1539         if (buffer[1] == 0x6)
1540             interrupts.testTraining.testRequestLinkRate = RBR;
1541         else if (buffer[1] == 0xa)
1542             interrupts.testTraining.testRequestLinkRate = HBR;
1543         else if (buffer[1] == 0x14)
1544             interrupts.testTraining.testRequestLinkRate = HBR2;
1545         else if (buffer[1] == 0x1E)
1546             interrupts.testTraining.testRequestLinkRate = HBR3;
1547         else
1548         {
1549             DP_ASSERT(0 && "Unknown max link rate.  Assuming RBR");
1550             interrupts.testTraining.testRequestLinkRate = RBR;
1551         }
1552 
1553         interrupts.testTraining.testRequestLaneCount  = buffer[(0x220 - 0x218)] & 0xf;
1554 
1555         return true;
1556     }
1557 
parseAutomatedTestRequestDPCDHALImpl1558     void parseAutomatedTestRequest(bool testRequestPending)
1559     {
1560         NvU8 buffer[16];
1561 
1562         interrupts.automatedTestRequest = false;
1563         interrupts.testEdid.testRequestEdidRead = false;
1564         interrupts.testTraining.testRequestTraining = false;
1565         interrupts.testPhyCompliance.testRequestPhyCompliance = false;
1566 
1567         if (!testRequestPending)
1568         {
1569             return;
1570         }
1571         interrupts.automatedTestRequest = true;
1572 
1573         if (AuxRetry::ack != bus.read(NV_DPCD_TEST_REQUEST, &buffer[0], 16))
1574         {
1575             DP_LOG(("DPHAL> ERROR! Automated test request found. Unable to read 0x218 register."));
1576             return;
1577         }
1578 
1579         if (FLD_TEST_DRF(_DPCD, _TEST_REQUEST, _TEST_LINK_TRAINING, _YES, buffer[0]))
1580         {
1581             interrupts.testTraining.testRequestTraining = parseTestRequestTraining(&buffer[0]);
1582         }
1583 
1584         if (FLD_TEST_DRF(_DPCD, _TEST_REQUEST, _TEST_EDID_READ, _YES, buffer[0]))
1585         {
1586             interrupts.testEdid.testRequestEdidRead = true;
1587         }
1588 
1589         if (FLD_TEST_DRF(_DPCD, _TEST_REQUEST, _TEST_PHY_TEST_PATTERN, _YES, buffer[0]))
1590         {
1591             interrupts.testPhyCompliance.testRequestPhyCompliance = parseTestRequestPhy();
1592         }
1593     }
1594 
parseTestRequestPhyDPCDHALImpl1595     virtual bool parseTestRequestPhy()
1596     {
1597         NvU8 buffer = 0;
1598         NvU8 bits = 0;
1599         if (AuxRetry::ack != bus.read(NV_DPCD_PHY_TEST_PATTERN, &buffer, 1))
1600         {
1601             DP_LOG(("DPHAL> ERROR! Test pattern request found but unable to read NV_DPCD_PHY_TEST_PATTERN register."));
1602             return false;
1603         }
1604 
1605         if (isVersion(1,0))
1606             bits = 0;
1607         else
1608             bits = DRF_VAL(_DPCD, _PHY_TEST_PATTERN_SEL, _DP12, buffer);
1609 
1610         if (bits == NV_DPCD_PHY_TEST_PATTERN_SEL_NO)
1611             interrupts.testPhyCompliance.phyTestPattern = LINK_QUAL_DISABLED;
1612         else if (bits == NV_DPCD_PHY_TEST_PATTERN_SEL_D10_2)
1613             interrupts.testPhyCompliance.phyTestPattern = LINK_QUAL_D10_2;
1614         else if (bits == NV_DPCD_PHY_TEST_PATTERN_SEL_SYM_ERR_MEASUREMENT_CNT)
1615             interrupts.testPhyCompliance.phyTestPattern = LINK_QUAL_SYM_ERROR;
1616         else if (bits == NV_DPCD_LINK_QUAL_LANE_SET_LQS_PRBS7)
1617             interrupts.testPhyCompliance.phyTestPattern = LINK_QUAL_PRBS7;
1618         else if (bits == NV_DPCD_LINK_QUAL_LANE_SET_LQS_80_BIT_CUSTOM)
1619             interrupts.testPhyCompliance.phyTestPattern = LINK_QUAL_80BIT_CUST;
1620         else if (bits == NV_DPCD_LINK_QUAL_LANE_SET_LQS_HBR2)
1621             interrupts.testPhyCompliance.phyTestPattern = LINK_QUAL_HBR2_COMPLIANCE_EYE;
1622         else if (bits == NV_DPCD14_PHY_TEST_PATTERN_SEL_CP2520PAT3)
1623             interrupts.testPhyCompliance.phyTestPattern = LINK_QUAL_CP2520PAT3;
1624         else
1625         {
1626             DP_ASSERT(0 && "Unknown pattern type, assuming none");
1627             interrupts.testPhyCompliance.phyTestPattern = LINK_QUAL_DISABLED;
1628             return false;
1629         }
1630 
1631         if (interrupts.testPhyCompliance.phyTestPattern == LINK_QUAL_80BIT_CUST)
1632         {
1633             NvU8 buffer[NV_DPCD_TEST_80BIT_CUSTOM_PATTERN__SIZE] = {0};
1634             if (AuxRetry::ack != bus.read(NV_DPCD_TEST_80BIT_CUSTOM_PATTERN(0), &buffer[0],
1635                                           NV_DPCD_TEST_80BIT_CUSTOM_PATTERN__SIZE))
1636             {
1637                 DP_LOG(("DPHAL> ERROR! Request for 80 bit custom pattern. Can't read from 250h."));
1638                 return false;
1639             }
1640 
1641             for (unsigned i = 0; i < NV_DPCD_TEST_80BIT_CUSTOM_PATTERN__SIZE; i++)
1642             {
1643                 interrupts.eightyBitCustomPat[i] = buffer[i];
1644             }
1645         }
1646 
1647         return true;
1648     }
1649 
interruptCapabilitiesChangedDPCDHALImpl1650     virtual bool interruptCapabilitiesChanged()
1651     {
1652         return interrupts.rxCapChanged;
1653     }
1654 
clearInterruptCapabilitiesChangedDPCDHALImpl1655     virtual void clearInterruptCapabilitiesChanged()
1656     {
1657         NvU8 irqVector = 0;
1658         irqVector = FLD_SET_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _RX_CAP_CHANGED, _YES, irqVector);
1659         bus.write(NV_DPCD_LINK_SERVICE_IRQ_VECTOR_ESI0, &irqVector, sizeof irqVector);
1660     }
1661 
isPanelReplayErrorSetDPCDHALImpl1662     virtual bool isPanelReplayErrorSet()
1663     {
1664         return interrupts.prErrorStatus;
1665     }
1666 
readPanelReplayErrorDPCDHALImpl1667     virtual void readPanelReplayError()
1668     {
1669         NvU8 config = 0U;
1670         bool bRetVal = (AuxRetry::ack ==
1671                 bus.read(NV_DPCD20_PANEL_REPLAY_ERROR_STATUS,
1672                     &config, sizeof(config)));
1673 
1674         if (bRetVal)
1675         {
1676             if (FLD_TEST_DRF(_DPCD20_PANEL_REPLAY, _ERROR_STATUS,
1677                     _ACTIVE_FRAME_CRC_ERROR, _YES, config))
1678             {
1679                 DP_LOG(("DPHAL> ERROR! Active Frame CRC Error set in PanelReplay status register"));
1680             }
1681             if (FLD_TEST_DRF(_DPCD20_PANEL_REPLAY, _ERROR_STATUS,
1682                     _RFB_STORAGE_ERROR, _YES, config))
1683             {
1684                 DP_LOG(("DPHAL> ERROR! RFB Storage Error set in PanelReplay status register"));
1685             }
1686             if (FLD_TEST_DRF(_DPCD20_PANEL_REPLAY, _ERROR_STATUS,
1687                     _VSC_SDP_UNCORRECTABLE_ERROR, _YES, config))
1688             {
1689                 DP_LOG(("DPHAL> ERROR! VSC SDP Uncorrectable Error set in PanelReplay status register"));
1690             }
1691         }
1692         else
1693         {
1694             DP_LOG(("DPHAL> readPanelReplayError: Failed to read PanelReplay error status"));
1695         }
1696     }
1697 
clearPanelReplayErrorDPCDHALImpl1698     virtual void clearPanelReplayError()
1699     {
1700         NvU8 irqVector = 0U;
1701         irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI1,
1702             _PANEL_REPLAY_ERROR_STATUS, _YES, irqVector);
1703         bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_ESI1, &irqVector,
1704             sizeof irqVector);
1705     }
1706 
getLinkStatusChangedDPCDHALImpl1707     virtual bool getLinkStatusChanged()
1708     {
1709         return interrupts.linkStatusChanged;
1710     }
1711 
clearLinkStatusChangedDPCDHALImpl1712     virtual void clearLinkStatusChanged()
1713     {
1714         NvU8 irqVector = 0;
1715         irqVector = FLD_SET_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _LINK_STATUS_CHANGED, _YES, irqVector);
1716         bus.write(NV_DPCD_LINK_SERVICE_IRQ_VECTOR_ESI0, &irqVector, sizeof irqVector);
1717     }
1718 
getHdmiLinkStatusChangedDPCDHALImpl1719     virtual bool getHdmiLinkStatusChanged()
1720     {
1721         return interrupts.hdmiLinkStatusChanged;
1722     }
1723 
clearHdmiLinkStatusChangedDPCDHALImpl1724     virtual void clearHdmiLinkStatusChanged()
1725     {
1726         NvU8 irqVector = 0;
1727         irqVector = FLD_SET_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _HDMI_LINK_STATUS_CHANGED, _YES, irqVector);
1728         bus.write(NV_DPCD_LINK_SERVICE_IRQ_VECTOR_ESI0, &irqVector, sizeof irqVector);
1729     }
1730 
getStreamStatusChangedDPCDHALImpl1731     virtual bool getStreamStatusChanged()
1732     {
1733         return interrupts.streamStatusChanged;
1734     }
1735 
clearStreamStatusChangedDPCDHALImpl1736     virtual void clearStreamStatusChanged()
1737     {
1738         NvU8 irqVector = 0;
1739         irqVector = FLD_SET_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _STREAM_STATUS_CHANGED, _YES, irqVector);
1740         bus.write(NV_DPCD_LINK_SERVICE_IRQ_VECTOR_ESI0, &irqVector, sizeof irqVector);
1741     }
1742 
isLinkStatusValidDPCDHALImpl1743     virtual bool isLinkStatusValid(unsigned lanes)
1744     {
1745         bool linkStatus = true;
1746 
1747         this->setDirtyLinkStatus(true);
1748         this->refreshLinkStatus();
1749 
1750         for (unsigned lane = 0; lane < lanes ; lane++)
1751         {
1752             linkStatus = linkStatus && interrupts.laneStatusIntr.laneStatus[lane].clockRecoveryDone &&
1753                          interrupts.laneStatusIntr.laneStatus[lane].channelEqualizationDone &&
1754                          interrupts.laneStatusIntr.laneStatus[lane].symbolLocked;
1755         }
1756 
1757         linkStatus = linkStatus && interrupts.laneStatusIntr.interlaneAlignDone;
1758 
1759         return linkStatus;
1760     }
1761 
refreshLinkStatusDPCDHALImpl1762     virtual void refreshLinkStatus()
1763     {
1764         if (interrupts.laneStatusIntr.linkStatusDirtied)
1765         {
1766             if (caps.supportsESI &&
1767                 (caps.eDpRevision != NV_DPCD_EDP_REV_VAL_1_4) &&
1768                 (caps.eDpRevision != NV_DPCD_EDP_REV_VAL_1_4A))
1769             {
1770                 this->fetchLinkStatusESI();
1771             }
1772             else
1773             {
1774                 this->fetchLinkStatusLegacy();
1775             }
1776         }
1777     }
1778 
setDirtyLinkStatusDPCDHALImpl1779     virtual void setDirtyLinkStatus(bool dirty)
1780     {
1781         interrupts.laneStatusIntr.linkStatusDirtied = dirty;
1782     }
1783 
parseAndReadInterruptsESIDPCDHALImpl1784     void parseAndReadInterruptsESI()
1785     {
1786         NvU8 buffer[16] = {0};
1787         bool automatedTestRequest;
1788 
1789         if (AuxRetry::ack != bus.read(NV_DPCD_SINK_COUNT_ESI, &buffer[2], 0x2005 - 0x2002 + 1))
1790             return;
1791 
1792         interrupts.sinkCount = DRF_VAL(_DPCD, _SINK_COUNT_ESI, _SINK_COUNT, buffer[2]);
1793 
1794         // check if edp revision is v1.4 or v1.4a
1795         if ((caps.eDpRevision != NV_DPCD_EDP_REV_VAL_1_4) && (caps.eDpRevision != NV_DPCD_EDP_REV_VAL_1_4A))
1796         {
1797             automatedTestRequest               = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _AUTO_TEST, _YES, buffer[3]);
1798         }
1799         else
1800         {
1801             // if edp rev is v1.4 or v1.4a, then use legacy address for auto test.
1802             NvU8 legacy = 0;
1803             if (AuxRetry::ack != bus.read(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR, &legacy, 1))
1804                 return;
1805             automatedTestRequest               = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _AUTO_TEST, _YES, legacy);
1806         }
1807 
1808         interrupts.cpIRQ                       = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _CP, _YES, buffer[3]);
1809         interrupts.mccsIRQ                     = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _MCCS_IRQ, _YES, buffer[3]);
1810         interrupts.downRepMsgRdy               = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _DOWN_REP_MSG_RDY, _YES, buffer[3]);
1811         interrupts.upReqMsgRdy                 = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _UP_REQ_MSG_RDY, _YES, buffer[3]);
1812 
1813         interrupts.prErrorStatus               = FLD_TEST_DRF(_DPCD,
1814             _DEVICE_SERVICE_IRQ_VECTOR_ESI1, _PANEL_REPLAY_ERROR_STATUS, _YES, buffer[4]);
1815 
1816         interrupts.rxCapChanged                = FLD_TEST_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _RX_CAP_CHANGED, _YES, buffer[5]);
1817         interrupts.linkStatusChanged           = FLD_TEST_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _LINK_STATUS_CHANGED, _YES, buffer[5]);
1818         interrupts.streamStatusChanged         = FLD_TEST_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _STREAM_STATUS_CHANGED, _YES, buffer[5]);
1819         interrupts.hdmiLinkStatusChanged       = FLD_TEST_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _HDMI_LINK_STATUS_CHANGED, _YES, buffer[5]);
1820         //
1821         // Link status changed bit is not necessarily set at all times when the sink
1822         // loses the lane status. Refresh the lane status in any case on an IRQ
1823         //
1824         if ((caps.eDpRevision != NV_DPCD_EDP_REV_VAL_1_4) &&
1825             (caps.eDpRevision != NV_DPCD_EDP_REV_VAL_1_4A))
1826         {
1827             fetchLinkStatusESI();
1828         }
1829         else
1830         {
1831             fetchLinkStatusLegacy();
1832         }
1833 
1834         if (interrupts.linkStatusChanged)
1835         {
1836             this->clearLinkStatusChanged();
1837         }
1838 
1839         if (interrupts.rxCapChanged)
1840         {
1841 
1842             DP_LOG(("DPHAL> RX Capabilities have changed!"));
1843             parseAndReadCaps();
1844             this->clearInterruptCapabilitiesChanged();
1845         }
1846 
1847         if (interrupts.hdmiLinkStatusChanged)
1848         {
1849             this->clearHdmiLinkStatusChanged();
1850         }
1851 
1852         if (interrupts.prErrorStatus)
1853         {
1854             this->clearPanelReplayError();
1855         }
1856 
1857         parseAutomatedTestRequest(automatedTestRequest);
1858     }
1859 
readLTTPRLinkStatusDPCDHALImpl1860     void readLTTPRLinkStatus(NvS32 rxIndex, NvU8 *buffer)
1861     {
1862         int addrLane01Status;
1863         // LINK_STATUS for LTTPR is 3 bytes. (NV_DPCD14_PHY_REPEATER_START(i) + 0x20 ~ 0x22)
1864         int bytesToRead = 3;
1865 
1866         DP_ASSERT((rxIndex > 0 && rxIndex <= 8) && "Invalid rxIndex");
1867         //
1868         // NV_DPCD14_PHY_REPEATER_START is 0-based.
1869         // rxIndex is 1-based.
1870         //
1871         addrLane01Status = NV_DPCD14_PHY_REPEATER_START(rxIndex - 1) +
1872                                 NV_DPCD14_LANE0_1_STATUS_PHY_REPEATER;
1873         bus.read(addrLane01Status, buffer, bytesToRead);
1874     }
1875 
resetIntrLaneStatusDPCDHALImpl1876     void resetIntrLaneStatus()
1877     {
1878         //
1879         // Reset all laneStatus to true.
1880         // These bits can only set to true when all DPRX (including sink and LTTPRs) set
1881         // the corresponding bit to true. Set to true as init value, and later will do &=
1882         // through all the lanes.
1883         //
1884         for (int lane = 0; lane < 4; lane++)
1885         {
1886             interrupts.laneStatusIntr.laneStatus[lane].clockRecoveryDone        = true;
1887             interrupts.laneStatusIntr.laneStatus[lane].channelEqualizationDone  = true;
1888             interrupts.laneStatusIntr.laneStatus[lane].symbolLocked             = true;
1889         }
1890         interrupts.laneStatusIntr.interlaneAlignDone    = true;
1891         interrupts.laneStatusIntr.downstmPortChng       = true;
1892         interrupts.laneStatusIntr.linkStatusUpdated     = true;
1893     }
1894 
fetchLinkStatusESIDPCDHALImpl1895     void fetchLinkStatusESI()
1896     {
1897         NvU8 buffer[16] = {0};
1898         NvS32 rxIndex;
1899 
1900         // LINK_STATUS_ESI from 0x200C to 0x200E
1901         int bytesToRead = 3;
1902 
1903         // Reset all laneStatus to true.
1904         resetIntrLaneStatus();
1905 
1906         for (rxIndex = caps.phyRepeaterCount; rxIndex >= (NvS32) NV0073_CTRL_DP_DATA_TARGET_SINK; rxIndex--)
1907         {
1908             if (rxIndex != NV0073_CTRL_DP_DATA_TARGET_SINK)
1909             {
1910                 readLTTPRLinkStatus(rxIndex, &buffer[0xC]);
1911             }
1912             else
1913             {
1914                 bus.read(NV_DPCD_LANE0_1_STATUS_ESI, &buffer[0xC], bytesToRead);
1915             }
1916 
1917             for (int lane = 0; lane < 4; lane++)
1918             {
1919                 unsigned laneBits = buffer[0xC+lane/2] >> (4*(lane & 1));
1920                 interrupts.laneStatusIntr.laneStatus[lane].clockRecoveryDone        &= !!(laneBits & 1);
1921                 interrupts.laneStatusIntr.laneStatus[lane].channelEqualizationDone  &= !!(laneBits & 2);
1922                 interrupts.laneStatusIntr.laneStatus[lane].symbolLocked             &= !!(laneBits & 4);
1923             }
1924 
1925             interrupts.laneStatusIntr.interlaneAlignDone    &=
1926                 FLD_TEST_DRF(_DPCD, _LANE_ALIGN_STATUS_UPDATED_ESI, _INTERLANE_ALIGN_DONE, _YES, buffer[0xE]);
1927             interrupts.laneStatusIntr.downstmPortChng       &=
1928                 FLD_TEST_DRF(_DPCD, _LANE_ALIGN_STATUS_UPDATED_ESI, _DOWNSTRM_PORT_STATUS_DONE, _YES, buffer[0xE]);
1929             interrupts.laneStatusIntr.linkStatusUpdated     &=
1930                 FLD_TEST_DRF(_DPCD, _LANE_ALIGN_STATUS_UPDATED_ESI, _LINK_STATUS_UPDATED, _YES, buffer[0xE]);
1931         }
1932         this->setDirtyLinkStatus(false);
1933     }
1934 
fetchLinkStatusLegacyDPCDHALImpl1935     void fetchLinkStatusLegacy()
1936     {
1937         NvU8 buffer[16] = {0};
1938         NvS32 rxIndex;
1939         // LINK_STATUS from 0x202 to 0x204
1940         int bytesToRead = 3;
1941 
1942         // Reset all laneStatus to true.
1943         resetIntrLaneStatus();
1944 
1945         for (rxIndex = caps.phyRepeaterCount; rxIndex >= (NvS32) NV0073_CTRL_DP_DATA_TARGET_SINK; rxIndex--)
1946         {
1947             if (rxIndex != NV0073_CTRL_DP_DATA_TARGET_SINK)
1948             {
1949                 readLTTPRLinkStatus(rxIndex, &buffer[2]);
1950             }
1951             else
1952             {
1953                 bus.read(NV_DPCD_LANE0_1_STATUS, &buffer[2], bytesToRead);
1954             }
1955 
1956             for (int lane = 0; lane < 4; lane++)
1957             {
1958                 unsigned laneBits = buffer[2+lane/2] >> (4*(lane & 1));
1959                 interrupts.laneStatusIntr.laneStatus[lane].clockRecoveryDone        &= !!(laneBits & 1);
1960                 interrupts.laneStatusIntr.laneStatus[lane].channelEqualizationDone  &= !!(laneBits & 2);
1961                 interrupts.laneStatusIntr.laneStatus[lane].symbolLocked             &= !!(laneBits & 4);
1962             }
1963 
1964             interrupts.laneStatusIntr.interlaneAlignDone    &=
1965                 FLD_TEST_DRF(_DPCD, _LANE_ALIGN_STATUS_UPDATED, _INTERLANE_ALIGN_DONE, _YES, buffer[4]);
1966             interrupts.laneStatusIntr.downstmPortChng       &=
1967                 FLD_TEST_DRF(_DPCD, _LANE_ALIGN_STATUS_UPDATED, _D0WNSTRM_PORT_STATUS_DONE, _YES, buffer[4]);
1968             interrupts.laneStatusIntr.linkStatusUpdated     &=
1969                 FLD_TEST_DRF(_DPCD, _LANE_ALIGN_STATUS_UPDATED, _LINK_STATUS_UPDATED, _YES, buffer[4]);
1970         }
1971         this->setDirtyLinkStatus(false);
1972     }
1973 
readTrainingDPCDHALImpl1974     virtual bool readTraining(NvU8* voltageSwingLane,  NvU8* preemphasisLane,
1975                               NvU8* trainingScoreLane, NvU8* postCursor,
1976                               NvU8  activeLaneCount)
1977     {
1978         NvU8 buffer[0xd] = {0};
1979         if (voltageSwingLane && preemphasisLane)
1980         {
1981             if (AuxRetry::ack != bus.read(NV_DPCD_LANE0_1_ADJUST_REQ, &buffer[0x6], 2))
1982             {
1983                 DP_ASSERT(0 && "Can't read NV_DPCD_LANE0_1_ADJUST_REQ.");
1984                 return false;
1985             }
1986             voltageSwingLane[0] = DRF_VAL(_DPCD, _LANEX_XPLUS1_ADJUST_REQ, _LANEX_DRIVE_CURRENT, buffer[6]);
1987             voltageSwingLane[1] = DRF_VAL(_DPCD, _LANEX_XPLUS1_ADJUST_REQ, _LANEXPLUS1_DRIVE_CURRENT, buffer[6]);
1988             voltageSwingLane[2] = DRF_VAL(_DPCD, _LANEX_XPLUS1_ADJUST_REQ, _LANEX_DRIVE_CURRENT, buffer[7]);
1989             voltageSwingLane[3] = DRF_VAL(_DPCD, _LANEX_XPLUS1_ADJUST_REQ, _LANEXPLUS1_DRIVE_CURRENT, buffer[7]);
1990 
1991             preemphasisLane[0] = DRF_VAL(_DPCD, _LANEX_XPLUS1_ADJUST_REQ, _LANEX_PREEMPHASIS, buffer[6]);
1992             preemphasisLane[1] = DRF_VAL(_DPCD, _LANEX_XPLUS1_ADJUST_REQ, _LANEXPLUS1_PREEMPHASIS, buffer[6]);
1993             preemphasisLane[2] = DRF_VAL(_DPCD, _LANEX_XPLUS1_ADJUST_REQ, _LANEX_PREEMPHASIS, buffer[7]);
1994             preemphasisLane[3] = DRF_VAL(_DPCD, _LANEX_XPLUS1_ADJUST_REQ, _LANEXPLUS1_PREEMPHASIS, buffer[7]);
1995 
1996         }
1997         if (trainingScoreLane)
1998         {
1999             if (AuxRetry::ack != bus.read(NV_DPCD_TRAINING_SCORE_LANE(0), &buffer[0x8], 4))
2000             {
2001                 DP_ASSERT(0 && "Can't read NV_DPCD_TRAINING_SCORE_LANE(0).");
2002                 return false;
2003             }
2004             trainingScoreLane[0] = buffer[0x8];
2005             trainingScoreLane[1] = buffer[0x9];
2006             trainingScoreLane[2] = buffer[0xa];
2007             trainingScoreLane[3] = buffer[0xb];
2008         }
2009         if (postCursor)
2010         {
2011             if (AuxRetry::ack != bus.read(NV_DPCD_ADJUST_REQ_POST_CURSOR2, &buffer[0xc], 1))
2012             {
2013                 DP_ASSERT(0 && "Can't read NV_DPCD_ADJUST_REQ_POST_CURSOR2.");
2014                 return false;
2015             }
2016             postCursor[0] = DRF_IDX_VAL(_DPCD, _ADJUST_REQ_POST_CURSOR2, _LANE, 0, buffer[0xc]);
2017             postCursor[1] = DRF_IDX_VAL(_DPCD, _ADJUST_REQ_POST_CURSOR2, _LANE, 1, buffer[0xc]);
2018             postCursor[2] = DRF_IDX_VAL(_DPCD, _ADJUST_REQ_POST_CURSOR2, _LANE, 2, buffer[0xc]);
2019             postCursor[3] = DRF_IDX_VAL(_DPCD, _ADJUST_REQ_POST_CURSOR2, _LANE, 3, buffer[0xc]);
2020         }
2021         return true;
2022     }
2023 
isLaneSettingsChangedDPCDHALImpl2024     virtual bool isLaneSettingsChanged(NvU8* oldVoltageSwingLane,
2025                                        NvU8* newVoltageSwingLane,
2026                                        NvU8* oldPreemphasisLane,
2027                                        NvU8* newPreemphasisLane,
2028                                        NvU8 activeLaneCount)
2029     {
2030         for (unsigned i = 0; i < activeLaneCount; i++)
2031         {
2032             if (oldVoltageSwingLane[i] != newVoltageSwingLane[i] ||
2033                 oldPreemphasisLane[i] != newPreemphasisLane[i] )
2034             {
2035                 return true;
2036             }
2037         }
2038         return false;
2039     }
2040 
parseAndReadInterruptsLegacyDPCDHALImpl2041     void parseAndReadInterruptsLegacy()
2042     {
2043         bool automatedTestRequest = false;
2044         NvU8 buffer[16] = {0};
2045 
2046         if (AuxRetry::ack != bus.read(NV_DPCD_SINK_COUNT, &buffer[0], 2))
2047             return;
2048 
2049         interrupts.sinkCount = NV_DPCD_SINK_COUNT_VAL(buffer[0]);
2050 
2051         automatedTestRequest                   = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _AUTO_TEST, _YES, buffer[1]);
2052         interrupts.cpIRQ                       = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _CP, _YES, buffer[1]);
2053         interrupts.mccsIRQ                     = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _MCCS_IRQ, _YES, buffer[1]);
2054         interrupts.downRepMsgRdy               = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _DOWN_REP_MSG_RDY, _YES, buffer[1]);
2055         interrupts.upReqMsgRdy                 = FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _UP_REQ_MSG_RDY, _YES, buffer[1]);
2056 
2057         fetchLinkStatusLegacy();
2058         this->setDirtyLinkStatus(false);
2059 
2060         parseAutomatedTestRequest(automatedTestRequest);
2061     }
2062 
parseAndReadInterruptsDPCDHALImpl2063     void parseAndReadInterrupts()
2064     {
2065         if (caps.supportsESI)
2066             parseAndReadInterruptsESI();       // DP 1.2 should use the new ESI region
2067         else
2068             parseAndReadInterruptsLegacy();
2069 
2070     }
2071 
getSinkCountDPCDHALImpl2072     virtual int getSinkCount() // DPCD offset 200
2073     {
2074         return interrupts.sinkCount;
2075     }
2076 
2077     //
2078     // This was introduced as part of WAR for HP SDC Panel since their
2079     // TCON sets DPCD 0x200 SINK_COUNT=0. It should never be called to
2080     // set the SinkCount in other cases since SinkCount comes from DPCD.
2081     //
setSinkCountDPCDHALImpl2082     virtual void setSinkCount(int sinkCount)
2083     {
2084         interrupts.sinkCount = sinkCount;
2085     }
2086 
interruptContentProtectionDPCDHALImpl2087     virtual bool interruptContentProtection()
2088     {
2089         return interrupts.cpIRQ;
2090     }
2091 
clearInterruptContentProtectionDPCDHALImpl2092     virtual void clearInterruptContentProtection()
2093     {
2094         if (caps.supportsESI)
2095         {
2096             NvU8 irqVector = 0;
2097 
2098             irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _CP, _YES, irqVector);
2099 
2100             bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_ESI0, &irqVector, sizeof irqVector);
2101         }
2102         else
2103         {
2104             NvU8 irqVector = 0;
2105 
2106             irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _CP, _YES, irqVector);
2107 
2108             bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR, &irqVector, sizeof irqVector);
2109         }
2110     }
2111 
intteruptMCCSDPCDHALImpl2112     virtual bool intteruptMCCS()
2113     {
2114         return interrupts.mccsIRQ;
2115     }
2116 
clearInterruptMCCSDPCDHALImpl2117     virtual void clearInterruptMCCS()
2118     {
2119         if (caps.supportsESI)
2120         {
2121             NvU8 irqVector = 0;
2122             irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _MCCS_IRQ, _YES, irqVector);
2123             bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_ESI0, &irqVector, sizeof irqVector);
2124         }
2125         else
2126         {
2127             NvU8 irqVector = 0;
2128             irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _MCCS_IRQ, _YES, irqVector);
2129             bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR, &irqVector, sizeof irqVector);
2130         }
2131     }
2132 
interruptDownReplyReadyDPCDHALImpl2133     virtual bool interruptDownReplyReady()
2134     {
2135         return interrupts.downRepMsgRdy;
2136     }
2137 
interruptUpRequestReadyDPCDHALImpl2138     virtual bool interruptUpRequestReady()
2139     {
2140         return interrupts.upReqMsgRdy;
2141     }
2142 
clearInterruptDownReplyReadyDPCDHALImpl2143     virtual void clearInterruptDownReplyReady()
2144     {
2145         if (caps.supportsESI)
2146         {
2147             NvU8 irqVector = 0;
2148             irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _DOWN_REP_MSG_RDY, _YES, irqVector);
2149             bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_ESI0, &irqVector, sizeof irqVector);
2150         }
2151         else
2152         {
2153             NvU8 irqVector = 0;
2154             irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _DOWN_REP_MSG_RDY, _YES, irqVector);
2155             bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR, &irqVector, sizeof irqVector);
2156         }
2157     }
2158 
clearInterruptUpRequestReadyDPCDHALImpl2159     virtual void clearInterruptUpRequestReady()
2160     {
2161         if (caps.supportsESI)
2162         {
2163             NvU8 irqVector = 0;
2164             irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _UP_REQ_MSG_RDY, _YES, irqVector);
2165             bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_ESI0, &irqVector, sizeof irqVector);
2166         }
2167         else
2168         {
2169             NvU8 irqVector = 0;
2170             irqVector = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR, _UP_REQ_MSG_RDY, _YES, irqVector);
2171             bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR, &irqVector, sizeof irqVector);
2172         }
2173     }
2174 
getLaneStatusSymbolLockDPCDHALImpl2175     virtual bool getLaneStatusSymbolLock(int lane)
2176     {
2177         return interrupts.laneStatusIntr.laneStatus[lane].symbolLocked;
2178     }
2179 
getLaneStatusClockRecoveryDoneDPCDHALImpl2180     virtual bool getLaneStatusClockRecoveryDone(int lane)
2181     {
2182         return interrupts.laneStatusIntr.laneStatus[lane].clockRecoveryDone;
2183     }
2184 
getInterlaneAlignDoneDPCDHALImpl2185     virtual bool getInterlaneAlignDone()                                             // DPCD offset 204
2186     {
2187         return interrupts.laneStatusIntr.interlaneAlignDone;
2188     }
2189 
getDownStreamPortStatusChangeDPCDHALImpl2190     virtual bool getDownStreamPortStatusChange()
2191     {
2192         return interrupts.laneStatusIntr.downstmPortChng;
2193     }
2194 
getPendingTestRequestTrainingDPCDHALImpl2195     virtual bool getPendingTestRequestTraining()                                    // DPCD offset 218
2196     {
2197         return interrupts.testTraining.testRequestTraining;
2198     }
2199 
getPendingAutomatedTestRequestDPCDHALImpl2200     virtual bool getPendingAutomatedTestRequest()
2201     {
2202         return interrupts.automatedTestRequest;
2203     }
2204 
getPendingTestRequestEdidReadDPCDHALImpl2205     virtual bool getPendingTestRequestEdidRead()
2206     {
2207         return interrupts.testEdid.testRequestEdidRead;
2208     }
2209 
getPendingTestRequestPhyComplianceDPCDHALImpl2210     virtual bool getPendingTestRequestPhyCompliance()
2211     {
2212         return interrupts.testPhyCompliance.testRequestPhyCompliance;
2213     }
2214 
getTestRequestTrainingDPCDHALImpl2215     virtual void getTestRequestTraining(LinkRate & rate, unsigned & lanes) // DPCD offset 219, 220
2216     {
2217         rate = interrupts.testTraining.testRequestLinkRate;
2218         lanes = interrupts.testTraining.testRequestLaneCount;
2219     }
2220 
getPhyTestPatternDPCDHALImpl2221     virtual LinkQualityPatternType getPhyTestPattern()                            // DPCD offset 248
2222     {
2223         return interrupts.testPhyCompliance.phyTestPattern;
2224     }
2225 
getCustomTestPatternDPCDHALImpl2226     virtual void getCustomTestPattern(NvU8 *testPattern)                         // DPCD offset 250 - 259
2227     {
2228         int i;
2229 
2230         for (i = 0; i < 10; i++)
2231         {
2232             testPattern[i] = interrupts.eightyBitCustomPat[i];
2233         }
2234     }
2235 
getBKSVDPCDHALImpl2236     virtual bool getBKSV(NvU8 *bKSV)           //DPCD offset 0x68000
2237     {
2238         if (caps.revisionMajor <= 0)
2239             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2240 
2241         if (AuxRetry::ack == bus.read(NV_DPCD_HDCP_BKSV_OFFSET, &bKSV[0], HDCP_KSV_SIZE))
2242         {
2243             DP_LOG(("Found HDCP Bksv= %02x %02x %02x %02x %02x",
2244                     bKSV[4], bKSV[3], bKSV[2], bKSV[1], bKSV[0]));
2245             return true;
2246         }
2247         return false;
2248     }
2249 
getBCapsDPCDHALImpl2250     virtual bool getBCaps(BCaps &bCaps, NvU8 * rawByte)             //DPCD offset 0x68028
2251     {
2252         NvU8 buffer;
2253         if (caps.revisionMajor <= 0)
2254             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2255 
2256         if (AuxRetry::ack == bus.read(NV_DPCD_HDCP_BCAPS_OFFSET, &buffer, sizeof buffer))
2257         {
2258             bCaps.HDCPCapable  = FLD_TEST_DRF(_DPCD, _HDCP_BCAPS_OFFSET, _HDCP_CAPABLE, _YES, buffer);
2259             bCaps.repeater     = FLD_TEST_DRF(_DPCD, _HDCP_BCAPS_OFFSET, _HDCP_REPEATER, _YES, buffer);
2260             if (rawByte)
2261                 *rawByte = buffer;
2262             return true;
2263         }
2264 
2265         DP_ASSERT(!"Unable to get BCaps");
2266         return false;
2267     }
2268 
getHdcp22BCapsDPCDHALImpl2269     virtual bool getHdcp22BCaps(BCaps &bCaps, NvU8 *rawByte)        //DPCD offset 0x6921D
2270     {
2271         NvU8 buffer;
2272         if (caps.revisionMajor <= 0)
2273             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2274 
2275         if (AuxRetry::ack == bus.read(NV_DPCD_HDCP22_BCAPS_OFFSET, &buffer, sizeof buffer))
2276         {
2277             bCaps.HDCPCapable  = FLD_TEST_DRF(_DPCD, _HDCP22_BCAPS_OFFSET, _HDCP_CAPABLE, _YES, buffer);
2278             bCaps.repeater     = FLD_TEST_DRF(_DPCD, _HDCP22_BCAPS_OFFSET, _HDCP_REPEATER, _YES, buffer);
2279             if (rawByte)
2280                 *rawByte = buffer;
2281             return true;
2282         }
2283 
2284         DP_ASSERT(!"Unable to get 22BCaps");
2285         return false;
2286     }
2287 
getBinfoDPCDHALImpl2288     virtual bool getBinfo(BInfo &bInfo)            //DPCD offset 0x6802A
2289     {
2290         NvU16 buffer;
2291         if (caps.revisionMajor <= 0)
2292             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2293 
2294         if (AuxRetry::ack == bus.read(NV_DPCD_HDCP_BINFO_OFFSET, (NvU8*)&buffer, sizeof buffer))
2295         {
2296             bInfo.maxCascadeExceeded   = FLD_TEST_DRF(_DPCD_HDCP, _BINFO_OFFSET, _MAX_CASCADE_EXCEEDED, _TRUE, buffer);
2297             bInfo.depth                = DRF_VAL(_DPCD_HDCP, _BINFO_OFFSET, _DEPTH, buffer);
2298             bInfo.maxDevsExceeded      = FLD_TEST_DRF(_DPCD_HDCP, _BINFO_OFFSET, _MAX_DEVS_EXCEEDED, _TRUE, buffer);
2299             bInfo.deviceCount          = DRF_VAL(_DPCD_HDCP, _BINFO_OFFSET, _DEVICE_COUNT, buffer);
2300             return true;
2301         }
2302 
2303         DP_ASSERT(!"Unable to get Binfo");
2304         return false;
2305     }
2306 
2307     // Get RxStatus per provided HDCP cap
getRxStatusDPCDHALImpl2308     virtual bool getRxStatus(const HDCPState &hdcpState, NvU8 *data)
2309     {
2310         if (caps.revisionMajor <= 0)
2311             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2312 
2313         NvU32 addr = hdcpState.HDCP_State_22_Capable ?
2314                      NV_DPCD_HDCP22_RX_STATUS : NV_DPCD_HDCP_BSTATUS_OFFSET;
2315 
2316         if (AuxRetry::ack == bus.read(addr, data, sizeof(NvU8)))
2317         {
2318             return true;
2319         }
2320 
2321         DP_ASSERT(!"Unable to get RxStatus//Bstatus");
2322         return false;
2323     }
2324 
setTestResponseChecksumDPCDHALImpl2325     virtual AuxRetry::status setTestResponseChecksum(NvU8 checksum)
2326     {
2327         if (caps.revisionMajor <= 0)
2328             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2329 
2330         return bus.write(NV_DPCD_TEST_EDID_CHKSUM, &checksum, sizeof checksum);
2331     }
2332 
setTestResponseDPCDHALImpl2333     virtual AuxRetry::status setTestResponse(bool ack, bool edidChecksumWrite)
2334     {
2335         NvU8 testResponse = 0;
2336 
2337         if (caps.revisionMajor <= 0)
2338             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2339 
2340         if (ack)
2341             testResponse = FLD_SET_DRF(_DPCD, _TEST_RESPONSE, _TEST_ACK, _YES, testResponse);
2342         else
2343             testResponse = FLD_SET_DRF(_DPCD, _TEST_RESPONSE, _TEST_NACK, _YES, testResponse);
2344 
2345         if (edidChecksumWrite)
2346             testResponse = FLD_SET_DRF(_DPCD, _TEST_RESPONSE, _TEST_EDID_CHKSUM_WRITE, _YES, testResponse);
2347 
2348         return bus.write(NV_DPCD_TEST_RESPONSE, &testResponse, sizeof testResponse);
2349     }
2350 
2351     //  Message box encoding
writeDownRequestMessageBoxDPCDHALImpl2352     virtual AuxRetry::status writeDownRequestMessageBox(NvU8 * data, size_t length)
2353     {
2354         //
2355         //  We can assume no message was sent if this fails.
2356         //     Reasoning:
2357         //        Sinks are not allowed to DEFER except on the first 16 byte write.
2358         //        If there isn't enough room for the 48 byte packet, that write
2359         //        will defer.
2360         //
2361         return bus.write(NV_DPCD_MBOX_DOWN_REQ, data, (unsigned)length);
2362     }
2363 
getDownRequestMessageBoxSizeDPCDHALImpl2364     virtual size_t getDownRequestMessageBoxSize()
2365     {
2366         return DP_MESSAGEBOX_SIZE;
2367     }
2368 
writeUpReplyMessageBoxDPCDHALImpl2369     virtual AuxRetry::status writeUpReplyMessageBox(NvU8 * data, size_t length)
2370     {
2371         if (caps.revisionMajor <= 0)
2372             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2373 
2374         //
2375         //  We can assume no message was sent if this fails.
2376         //     Reasoning:
2377         //        Sinks are not allowed to DEFER except on the first 16 byte write.
2378         //        If there isn't enough room for the 48 byte packet, that write
2379         //        will defer.
2380         //
2381         return bus.write(NV_DPCD_MBOX_UP_REP, data, (unsigned)length);
2382     }
2383 
getUpReplyMessageBoxSizeDPCDHALImpl2384     virtual size_t getUpReplyMessageBoxSize()
2385     {
2386         return 48;
2387     }
2388 
readDownReplyMessageBoxDPCDHALImpl2389     virtual AuxRetry::status readDownReplyMessageBox(NvU32 offset, NvU8 * data, size_t length)
2390     {
2391         //  if (caps.revisionMajor <= 0)
2392         //        DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2393 
2394         DP_ASSERT(offset + length <= DP_MESSAGEBOX_SIZE);
2395 
2396         return bus.read(NV_DPCD_MBOX_DOWN_REP + offset, data, (unsigned)length);
2397     }
2398 
getDownReplyMessageBoxSizeDPCDHALImpl2399     virtual size_t getDownReplyMessageBoxSize()
2400     {
2401         return DP_MESSAGEBOX_SIZE;
2402     }
2403 
readUpRequestMessageBoxDPCDHALImpl2404     virtual  AuxRetry::status readUpRequestMessageBox(NvU32 offset, NvU8 * data, size_t length)
2405     {
2406         if (caps.revisionMajor <= 0)
2407             DP_ASSERT(0 && "Something is wrong, revision major should be > 0");
2408 
2409         DP_ASSERT(offset + length <= DP_MESSAGEBOX_SIZE);
2410 
2411         return bus.read(NV_DPCD_MBOX_UP_REQ + offset, data, (unsigned)length);
2412     }
2413 
getUpRequestMessageBoxSizeDPCDHALImpl2414     virtual size_t getUpRequestMessageBoxSize()
2415     {
2416         return DP_MESSAGEBOX_SIZE;
2417     }
2418 
getTransactionSizeDPCDHALImpl2419     virtual size_t getTransactionSize()
2420     {
2421         return bus.getDirect()->transactionSize();
2422     }
2423 
getPowerStateDPCDHALImpl2424     virtual PowerState getPowerState()
2425     {
2426         NvU8 data;
2427         if (AuxRetry::ack != bus.read(NV_DPCD_SET_POWER, &data, sizeof data, 0))
2428         {
2429             // Assume powerdown state
2430             return PowerStateD3;
2431         }
2432 
2433         switch (DRF_VAL(_DPCD, _SET_POWER, _VAL, data))
2434         {
2435         case NV_DPCD_SET_POWER_VAL_D3_PWRDWN:
2436             return PowerStateD3;
2437 
2438         case NV_DPCD_SET_POWER_VAL_D0_NORMAL:
2439             return PowerStateD0;
2440 
2441         case NV_DPCD_SET_POWER_VAL_D3_AUX_ON:
2442             {
2443                 DP_ASSERT(isAtLeastVersion(1, 2) && "DP 1.2 specific power state to be set on a non-DP1.2 system!?");
2444                 return PowerStateD3AuxOn;
2445             }
2446         default:
2447             DP_ASSERT(0 && "Unknown power state! Assuming device is asleep");
2448             return PowerStateD3;
2449         }
2450     }
2451 
setPowerStateDPCDHALImpl2452     virtual bool setPowerState(PowerState newState)
2453     {
2454         NvU8    timeoutMs = 0;
2455 
2456         if (newState == PowerStateD0)
2457             timeoutMs = caps.extendedSleepWakeTimeoutRequestMs;
2458 
2459         // Default behavior is 2ms for better tolerance.
2460         if (timeoutMs < 2)
2461             timeoutMs = 2;
2462 
2463         //
2464         // A Branch Device must forward this value to its downstream devices.
2465         // When set to D3 state, a Sink Device may put its AUX CH circuit in a "power
2466         // saving" state. In this mode the AUX CH circuit may only detect the presence of a
2467         // differential signal input without replying to an AUX CH request transaction. Upon
2468         // detecting the presence of a differential signal input, the Sink Device must exit the
2469         // "power saving" state within 1ms.
2470         //
2471         if (isAtLeastVersion(1, 1))
2472         {
2473             NvU8 data = 0;
2474             if (newState == PowerStateD0)
2475                 data |= NV_DPCD_SET_POWER_VAL_D0_NORMAL;
2476             else if (newState == PowerStateD3)
2477             {
2478                 if (caps.extendedSleepWakeTimeoutRequestMs > 1)
2479                 {
2480                     NvU8    grant = 0;
2481                     // Grant extended sleep wake timeout before go D3.
2482                     grant = FLD_SET_DRF(_DPCD, _EXTENDED_DPRX_WAKE_TIMEOUT, _PERIOD_GRANTED, _YES, grant);
2483                     if (AuxRetry::ack == bus.write(NV_DPCD_EXTENDED_DPRX_WAKE_TIMEOUT, &grant, sizeof(grant)))
2484                     {
2485                         DP_LOG(("DisplayPort: Failed to grant extended sleep wake timeout before D3\n"));
2486                     }
2487                 }
2488                 data = NV_DPCD_SET_POWER_VAL_D3_PWRDWN;
2489             }
2490             else
2491             {
2492                 DP_ASSERT(0 && "Unknown power state");
2493             }
2494 
2495             //
2496             //  If we're powering on, we need to allow up to 1ms for the power
2497             //  to come online.  Ideally we'd handle this with a callback,
2498             //  but for now we're going to do a wait here.
2499             //
2500             Timeout timeout(timer, timeoutMs);
2501             unsigned retries = 0;
2502 
2503             do
2504             {
2505                 if (AuxRetry::ack == bus.write(NV_DPCD_SET_POWER, &data, sizeof(data)))
2506                 {
2507                     return true;
2508                 }
2509                 retries++;
2510             }
2511             while (timeout.valid() || (retries < 40) /* some panels need up to 40 retries */);
2512 
2513             DP_LOG(("DisplayPort: Failed to bring panel back to wake state"));
2514         }
2515         else
2516         {
2517             //  DP 1.0 devices cannot be put to sleep
2518             if (newState == PowerStateD0)
2519                 return true;
2520         }
2521 
2522         return false;
2523     }
2524 
payloadTableClearACTDPCDHALImpl2525     virtual void payloadTableClearACT()
2526     {
2527         NvU8 byte = NV_DPCD_PAYLOAD_TABLE_UPDATE_STATUS_UPDATED_YES;
2528         bus.write(NV_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, &byte, sizeof byte);
2529     }
2530 
payloadWaitForACTReceivedDPCDHALImpl2531     virtual bool payloadWaitForACTReceived()
2532     {
2533         NvU8 byte = 0;
2534         int retries = 0;
2535 
2536         while (true)
2537         {
2538             if (++retries > 40)
2539             {
2540                 DP_LOG(("DPHAL> ACT Not received by sink device!"));
2541                 return false;
2542             }
2543 
2544             if (AuxRetry::ack == bus.read(NV_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, &byte, sizeof byte))
2545             {
2546                 if (FLD_TEST_DRF(_DPCD, _PAYLOAD_TABLE_UPDATE_STATUS, _ACT_HANDLED, _YES, byte))
2547                 {
2548                     DP_LOG(("DPHAL> ACT Received"));
2549                     return true;
2550                 }
2551             }
2552         }
2553     }
2554 
payloadAllocateDPCDHALImpl2555     virtual bool payloadAllocate(unsigned streamId, unsigned begin, unsigned count)
2556     {
2557         bool bResult = false;
2558         NvU8 payloadAllocate[3];
2559         DP_ASSERT(streamId < 64 && "Invalid stream location");
2560         payloadAllocate[0] = (NvU8)streamId;
2561         payloadAllocate[1] = (NvU8)begin;
2562         payloadAllocate[2] = (NvU8)count;
2563 
2564         AuxRetry::status status = bus.write(NV_DPCD_PAYLOAD_ALLOC_SET, (NvU8*)&payloadAllocate, sizeof payloadAllocate);
2565 
2566         if (status == AuxRetry::ack)
2567         {
2568             //
2569             // Bit 0 = VC Payload Table Updated(Change/Read only)
2570             //       1 = Update, cleared to zero when u Packet Source writes 1
2571             //       0 = Not updated since the last time this bit was cleared
2572             //
2573             NvU8 payloadStatus;
2574             int retries = 0;
2575 
2576             //
2577             // Bug 1385165 that Synaptics branch revision 1.0 found to spend more than 200ms before table updated.
2578             // Retries without delay is too soon for device to complete table update process.
2579             // That will hit bug 1334070 and trigger monitor unplug/hotplug at early return.
2580             //
2581             do
2582             {
2583                 if ((bus.read(NV_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, &payloadStatus, sizeof(payloadStatus)) == AuxRetry::ack))
2584                 {
2585                     if (FLD_TEST_DRF(_DPCD, _PAYLOAD_TABLE_UPDATE_STATUS, _UPDATED, _YES, payloadStatus))
2586                     {
2587                         bResult = true;
2588                         break;
2589                     }
2590                 }
2591                 else
2592                 {
2593                     DP_LOG(("DPHAL> Read NV_DPCD_PAYLOAD_TABLE_UPDATE_STATUS failed."));
2594                 }
2595 
2596                 timer->sleep(1);
2597             } while (++retries < PAYLOADIDTABLE_UPDATED_CHECK_RETRIES);
2598         }
2599         else
2600         {
2601             DP_LOG(("DPHAL> Send NV_DPCD_PAYLOAD_ALLOC_SET failed."));
2602         }
2603 
2604         DP_LOG(("DPHAL> Requesting allocation Stream:%d | First Slot:%d | Count:%d  (%s)", streamId, begin, count, bResult ? "OK" : "FAILED"));
2605         return bResult;
2606     }
2607 
overrideMultiStreamCapDPCDHALImpl2608     void overrideMultiStreamCap(bool mstCapable)
2609     {
2610         caps.overrideToSST = !mstCapable;
2611     }
2612 
getMultiStreamCapOverrideDPCDHALImpl2613     bool getMultiStreamCapOverride()
2614     {
2615         return caps.overrideToSST;
2616     }
2617 
getDpcdMultiStreamCapDPCDHALImpl2618     bool getDpcdMultiStreamCap(void)
2619     {
2620         return caps.supportsMultistream;
2621     }
2622 
setGpuDPSupportedVersionsDPCDHALImpl2623     void setGpuDPSupportedVersions(NvU32 _gpuDPSupportedVersions)
2624     {
2625         bool bSupportDp1_2 = FLD_TEST_DRF(0073_CTRL_CMD_DP, _GET_CAPS_DP_VERSIONS_SUPPORTED, _DP1_2, _YES, gpuDPSupportedVersions);
2626         bool bSupportDp1_4 = FLD_TEST_DRF(0073_CTRL_CMD_DP, _GET_CAPS_DP_VERSIONS_SUPPORTED, _DP1_4, _YES, gpuDPSupportedVersions);
2627         if (bSupportDp1_4)
2628         {
2629             DP_ASSERT(bSupportDp1_2 && "GPU supports DP1.4 should also support DP1.2!");
2630         }
2631 
2632         gpuDPSupportedVersions = _gpuDPSupportedVersions;
2633     }
2634 
setGpuFECSupportedDPCDHALImpl2635     void setGpuFECSupported(bool bSupportFEC)
2636     {
2637         bGpuFECSupported = bSupportFEC;
2638     }
2639 
applyRegkeyOverridesDPCDHALImpl2640     void applyRegkeyOverrides(const DP_REGKEY_DATABASE& dpRegkeyDatabase)
2641     {
2642         DP_ASSERT(dpRegkeyDatabase.bInitialized &&
2643                   "All regkeys are invalid because dpRegkeyDatabase is not initialized!");
2644         overrideDpcdRev          = dpRegkeyDatabase.dpcdRevOveride;
2645         bBypassILREdpRevCheck    = dpRegkeyDatabase.bBypassEDPRevCheck;
2646     }
2647 
2648     // To clear pending message {DOWN_REP/UP_REQ} and reply true if existed.
clearPendingMsgDPCDHALImpl2649     virtual bool clearPendingMsg()
2650     {
2651         NvU8 irqVector, data = 0;
2652         if (AuxRetry::ack == bus.read(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_ESI0,
2653                                       &irqVector, sizeof(irqVector)))
2654         {
2655             if (FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _DOWN_REP_MSG_RDY, _YES, irqVector))
2656             {
2657                 // Clear pending DOWN_REP.
2658                 data = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _DOWN_REP_MSG_RDY, _YES, 0);
2659             }
2660             if (FLD_TEST_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _UP_REQ_MSG_RDY, _YES, irqVector))
2661             {
2662                 // Clear pending UP_REQ
2663                 data = FLD_SET_DRF(_DPCD, _DEVICE_SERVICE_IRQ_VECTOR_ESI0, _UP_REQ_MSG_RDY, _YES, data);
2664             }
2665             if (!data ||
2666                 (AuxRetry::ack != bus.write(NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_ESI0,
2667                                             &data, sizeof(data))))
2668             {
2669                 DP_LOG(("DPCONN> %s(): No Pending Message or "
2670                         "Failed to clear pending message: irqVector/data = 0x%08x/0x%08x",
2671                         __FUNCTION__, irqVector, data));
2672                 return false;
2673             }
2674 
2675             return true;
2676         }
2677         else
2678         {
2679             DP_LOG(("DPCONN> Clear Pending MSG: Failed to read ESI0"));
2680         }
2681 
2682         return false;
2683     }
2684 
isMessagingEnabledDPCDHALImpl2685     virtual bool isMessagingEnabled()
2686     {
2687         NvU8 mstmCtrl;
2688 
2689         if ((AuxRetry::ack == bus.read(NV_DPCD_MSTM_CTRL, &mstmCtrl, 1)) &&
2690             (FLD_TEST_DRF(_DPCD, _MSTM_CTRL, _EN, _YES, mstmCtrl)))
2691         {
2692             return true;
2693         }
2694         return false;
2695     }
2696 
setIndexedLinkrateEnabledDPCDHALImpl2697     virtual void setIndexedLinkrateEnabled(bool val)
2698     {
2699         bIndexedLinkrateEnabled = val;
2700     }
2701 
isIndexedLinkrateEnabledDPCDHALImpl2702     virtual bool isIndexedLinkrateEnabled()
2703     {
2704         return bIndexedLinkrateEnabled;
2705     }
2706 
isIndexedLinkrateCapableDPCDHALImpl2707     virtual bool isIndexedLinkrateCapable()
2708     {
2709         return bIndexedLinkrateCapable;
2710     }
2711 
getLinkRateTableDPCDHALImpl2712     virtual NvU16 *getLinkRateTable()
2713     {
2714         if (!bIndexedLinkrateCapable)
2715         {
2716             DP_LOG(("DPCONN> link rate table should be invalid"));
2717         }
2718         return &caps.linkRateTable[0];
2719     }
2720 
getVideoFallbackSupportedDPCDHALImpl2721     virtual NvU32 getVideoFallbackSupported()
2722     {
2723         return caps.videoFallbackFormats;
2724     }
2725 
getRawLinkRateTableDPCDHALImpl2726     virtual bool getRawLinkRateTable(NvU8 *buffer)
2727     {
2728         NvU16 temp[NV_DPCD_SUPPORTED_LINK_RATES__SIZE];
2729         NvU8 *data = (buffer == NULL) ? (NvU8*)&temp[0] : buffer;
2730 
2731         if (AuxRetry::ack != bus.read(NV_DPCD_SUPPORTED_LINK_RATES(0), data,
2732                                       NV_DPCD_SUPPORTED_LINK_RATES__SIZE * sizeof(NvU16)))
2733         {
2734             return false;
2735         }
2736         return true;
2737     }
2738 
resetProtocolConverterDPCDHALImpl2739     virtual void resetProtocolConverter()
2740     {
2741         NvU8    data = 0;
2742         bus.write(NV_DPCD14_PCON_FRL_LINK_CONFIG_1, &data, sizeof(data));
2743         bus.write(NV_DPCD14_PCON_FRL_LINK_CONFIG_2, &data, sizeof(data));
2744 
2745     }
2746 
setSourceControlModeDPCDHALImpl2747     virtual bool setSourceControlMode(bool bEnableSourceControlMode, bool bEnableFRLMode)
2748     {
2749         NvU8    data = 0;
2750 
2751         if (bEnableSourceControlMode)
2752         {
2753             data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _SRC_CONTROL_MODE, _ENABLE, data);
2754             if (bEnableFRLMode)
2755             {
2756                 data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _LINK_FRL_MODE, _ENABLE, data);
2757                 data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _IRQ_LINK_FRL_MODE, _ENABLE, data);
2758             }
2759             else
2760             {
2761                 data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _LINK_FRL_MODE, _DISABLE, data);
2762                 data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _IRQ_LINK_FRL_MODE, _DISABLE, data);
2763             }
2764         }
2765         else
2766         {
2767             data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _SRC_CONTROL_MODE, _DISABLE, data);
2768             data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _LINK_FRL_MODE, _DISABLE, data);
2769             data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _IRQ_LINK_FRL_MODE, _DISABLE, data);
2770         }
2771 
2772         if (AuxRetry::ack != bus.write(NV_DPCD14_PCON_FRL_LINK_CONFIG_1, &data, sizeof(data)))
2773         {
2774             return false;
2775         }
2776         return true;
2777     }
2778 
checkPCONFrlReadyDPCDHALImpl2779     virtual bool checkPCONFrlReady(bool *bFrlReady)
2780     {
2781         NvU8        data = 0;
2782 
2783         if (bFrlReady == NULL)
2784         {
2785             DP_ASSERT(0);
2786             return true;
2787         }
2788 
2789         *bFrlReady = false;
2790 
2791         if (AuxRetry::ack != bus.read(NV_DPCD_LINK_SERVICE_IRQ_VECTOR_ESI0, &data, sizeof(data)))
2792         {
2793             return false;
2794         }
2795 
2796         if (data == 0)
2797         {
2798             return false;
2799         }
2800 
2801         if (FLD_TEST_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _HDMI_LINK_STATUS_CHANGED, _NO, data))
2802         {
2803             parseAndReadInterruptsESI();
2804             return false;
2805         }
2806 
2807         // Clear only this interrupt bit.
2808         this->clearHdmiLinkStatusChanged();
2809 
2810         if (AuxRetry::ack != bus.read(NV_DPCD14_PCON_HDMI_TX_LINK_STATUS, &data, sizeof(data)))
2811         {
2812             return false;
2813         }
2814 
2815         if (FLD_TEST_DRF(_DPCD14, _PCON_HDMI_TX_LINK_STATUS, _LINK_READY, _YES, data))
2816         {
2817             *bFrlReady = true;
2818         }
2819         return true;
2820     }
2821 
setupPCONFrlLinkAssessmentDPCDHALImpl2822     virtual bool setupPCONFrlLinkAssessment(NvU32   linkBwMask,
2823                                             bool    bEnableExtendLTMode = false,
2824                                             bool    bEnableConcurrentMode = false)
2825     {
2826         NvU8        data = 0;
2827 
2828         NvU32       requestedMaxBw  = (NvU32)(getMaxFrlBwFromMask(linkBwMask)) + 1; // +1 to convert PCONHdmiLinkBw enum to DPCD FRL BW cap definition
2829         NvU32       targetBw        = NV_MIN(caps.pconCaps.maxHdmiLinkBandwidthGbps,
2830                                              requestedMaxBw);
2831 
2832         // Step 1: Configure FRL Link (FRL BW, BW mask / Concurrent)
2833         if (bEnableExtendLTMode)
2834         {
2835             //
2836             // Set FRL_LT_CONTROL to Extended mode:
2837             // PCON FW trains for all Link BW selected in Link BW Mask (Bit 0~5)
2838             //
2839             data = linkBwMask;
2840             data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_2, _FRL_LT_CONTROL,
2841                                _EXTENDED, data);
2842         }
2843         else
2844         {
2845             // Set FRL_LT_CONTROL to Normal mode, so PCON stops when first FRL LT succeed.
2846             data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_2, _FRL_LT_CONTROL,
2847                                _NORMAL, data);
2848         }
2849 
2850         if (AuxRetry::ack != bus.write(NV_DPCD14_PCON_FRL_LINK_CONFIG_2, &data, sizeof(data)))
2851         {
2852             return false;
2853         }
2854 
2855         if (AuxRetry::ack != bus.read(NV_DPCD14_PCON_FRL_LINK_CONFIG_1, &data, sizeof(data)))
2856         {
2857             return false;
2858         }
2859 
2860         if (bEnableConcurrentMode && caps.pconCaps.bConcurrentLTSupported)
2861         {
2862             // Client selects concurrent.
2863             data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _CONCURRENT_LT_MODE,
2864                                _ENABLE, data);
2865         }
2866         else
2867         {
2868             //
2869             // Don't do concurrent LT for now.
2870             //
2871             data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _CONCURRENT_LT_MODE,
2872                                _DISABLE, data);
2873         }
2874         data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _HDMI_LINK,
2875                            _ENABLE, data);
2876         data = FLD_SET_DRF_NUM(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _MAX_LINK_BW,
2877                                targetBw, data);
2878 
2879         if (AuxRetry::ack != bus.write(NV_DPCD14_PCON_FRL_LINK_CONFIG_1, &data, sizeof(data)))
2880         {
2881             return false;
2882         }
2883 
2884         return true;
2885     }
2886 
checkPCONFrlLinkStatusDPCDHALImpl2887     virtual bool checkPCONFrlLinkStatus(NvU32 *frlRateMask)
2888     {
2889         NvU8        data = 0;
2890 
2891         if (frlRateMask == NULL)
2892         {
2893             DP_ASSERT(0);
2894             return true;
2895         }
2896 
2897         *frlRateMask = 0;
2898         // Check if IRQ happens.
2899         if (AuxRetry::ack != bus.read(NV_DPCD_LINK_SERVICE_IRQ_VECTOR_ESI0, &data, sizeof(data)))
2900         {
2901             return false;
2902         }
2903 
2904         if (FLD_TEST_DRF(_DPCD, _LINK_SERVICE_IRQ_VECTOR_ESI0, _HDMI_LINK_STATUS_CHANGED, _NO, data))
2905         {
2906             return false;
2907         }
2908         // Check HDMI Link Active status (0x303B Bit 0) and Link Config (0x3036)
2909         if (AuxRetry::ack != bus.read(NV_DPCD14_PCON_HDMI_TX_LINK_STATUS, &data, sizeof(data)))
2910         {
2911             return false;
2912         }
2913 
2914         if (FLD_TEST_DRF(_DPCD14, _PCON_HDMI_TX_LINK_STATUS, _LINK_ACTIVE, _YES, data))
2915         {
2916             if (AuxRetry::ack == bus.read(NV_DPCD14_PCON_HDMI_LINK_CONFIG_STATUS, &data, sizeof(data)))
2917             {
2918                 *frlRateMask = DRF_VAL(_DPCD14, _PCON_HDMI_LINK_CONFIG_STATUS, _LT_RESULT, data);
2919             }
2920 
2921         }
2922 
2923         return true;
2924     }
2925 
queryHdmiLinkStatusDPCDHALImpl2926     virtual bool queryHdmiLinkStatus(bool *bLinkActive, bool *bLinkReady)
2927     {
2928         NvU8        data = 0;
2929 
2930         if (bLinkActive == NULL && bLinkReady == NULL)
2931             return false;
2932 
2933         if (AuxRetry::ack != bus.read(NV_DPCD14_PCON_HDMI_TX_LINK_STATUS, &data, sizeof(data)))
2934         {
2935             return false;
2936         }
2937         if (bLinkReady != NULL)
2938         {
2939             *bLinkReady = (FLD_TEST_DRF(_DPCD14, _PCON_HDMI_TX_LINK_STATUS,
2940                                         _LINK_READY, _YES, data));
2941         }
2942         if (bLinkActive != NULL)
2943         {
2944             *bLinkActive = (FLD_TEST_DRF(_DPCD14, _PCON_HDMI_TX_LINK_STATUS,
2945                                          _LINK_ACTIVE, _YES, data));
2946         }
2947         return true;
2948     }
2949 
restorePCONFrlLinkDPCDHALImpl2950     virtual NvU32 restorePCONFrlLink(NvU32   linkBwMask,
2951                                      bool    bEnableExtendLTMode     = false,
2952                                      bool    bEnableConcurrentMode   = false)
2953     {
2954         // Restore HDMI Link.
2955         // 1. Clear HDMI link enable bit (305A bit 7)
2956         NvU8    data = 0;
2957         NvU32   loopCount;
2958         NvU32   frlRate;
2959         if (AuxRetry::ack != bus.read(NV_DPCD14_PCON_FRL_LINK_CONFIG_1, &data, sizeof(data)))
2960         {
2961             return false;
2962         }
2963         data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _HDMI_LINK, _DISABLE, data);
2964         if (AuxRetry::ack != bus.write(NV_DPCD14_PCON_FRL_LINK_CONFIG_1, &data, sizeof(data)))
2965         {
2966             return false;
2967         }
2968         // 2. Set FRL or TMDS (Optional if not changed) (305A bit 5)
2969         // 3. Read FRL Ready Bit (303B bit 1)
2970 
2971         Timeout timeout(timer, 500 /* 500ms */);
2972         data = 0;
2973         do
2974         {
2975             if (AuxRetry::ack != bus.read(NV_DPCD14_PCON_HDMI_TX_LINK_STATUS,
2976                                           &data, sizeof(data)))
2977                 continue;
2978             if (FLD_TEST_DRF(_DPCD14, _PCON_HDMI_TX_LINK_STATUS, _LINK_READY, _YES, data))
2979                 break;
2980         } while (timeout.valid());
2981 
2982         if (FLD_TEST_DRF(_DPCD14, _PCON_HDMI_TX_LINK_STATUS, _LINK_READY, _NO, data))
2983         {
2984             return false;
2985         }
2986 
2987         // 4. Configure FRL Link (Optional if not changed)
2988         // 5. Set HDMI Enable Bit.
2989         data = 0;
2990 
2991         if (AuxRetry::ack != bus.read(NV_DPCD14_PCON_FRL_LINK_CONFIG_1, &data, sizeof(data)))
2992         {
2993             return false;
2994         }
2995         data = FLD_SET_DRF(_DPCD14, _PCON_FRL_LINK_CONFIG_1, _HDMI_LINK, _ENABLE, data);
2996         if (AuxRetry::ack != bus.write(NV_DPCD14_PCON_FRL_LINK_CONFIG_1, &data, sizeof(data)))
2997         {
2998             return false;
2999         }
3000 
3001         // 6. Read HDMI Link Status link active bit (2005 bit 3)
3002         // 7. Read HDMI link active status bit and link config status (303b bit0 / 3036)
3003         loopCount = NV_PCON_FRL_LT_TIMEOUT_THRESHOLD;
3004         do
3005         {
3006             if (checkPCONFrlLinkStatus(&frlRate) == true)
3007             {
3008                 break;
3009             }
3010             Timeout timeout(this->timer, NV_PCON_FRL_LT_TIMEOUT_INTERVAL_MS);
3011             while(timeout.valid());
3012             continue;
3013         } while (--loopCount);
3014 
3015         return frlRate;
3016     }
3017 
readPsrCapabilitiesDPCDHALImpl3018     virtual void readPsrCapabilities(vesaPsrSinkCaps *caps)
3019     {
3020         dpMemCopy(caps, &this->caps.psrCaps, sizeof(vesaPsrSinkCaps));
3021     }
3022 
updatePsrConfigurationDPCDHALImpl3023     virtual bool updatePsrConfiguration(vesaPsrConfig psrcfg)
3024     {
3025         NvU8 config = 0U;
3026 
3027         if (psrcfg.psrCfgEnable)
3028         {
3029             config = FLD_SET_DRF(_DPCD_EDP, _PSR_CONFIG,
3030                 _SINK_ENABLE, _YES, config);
3031         }
3032         if (psrcfg.srcTxEnabledInPsrActive)
3033         {
3034             config = FLD_SET_DRF(_DPCD_EDP, _PSR_CONFIG,
3035                 _SOURCE_LINK_ACTIVE, _YES, config);
3036         }
3037         if (psrcfg.crcVerifEnabledInPsrActive)
3038         {
3039             config = FLD_SET_DRF(_DPCD_EDP, _PSR_CONFIG,
3040                 _CRC_VERIFICATION_ACTIVE, _YES, config);
3041         }
3042         if (psrcfg.frameCaptureSecondActiveFrame)
3043         {
3044             config = FLD_SET_DRF(_DPCD_EDP, _PSR_CONFIG,
3045                 _FRAME_CAPTURE_INDICATION, _SECOND, config);
3046         }
3047         if (psrcfg.selectiveUpdateOnSecondActiveline)
3048         {
3049             config = FLD_SET_DRF(_DPCD_EDP, _PSR_CONFIG,
3050                 _SU_LINE_CAPTURE_INDICATION, _SECOND, config);
3051         }
3052         if (psrcfg.enableHpdIrqOnCrcMismatch)
3053         {
3054             config = FLD_SET_DRF(_DPCD_EDP, _PSR_CONFIG,
3055                 _HPD_IRQ_ON_CRC_ERROR, _YES, config);
3056         }
3057         if (psrcfg.enablePsr2)
3058         {
3059             config = FLD_SET_DRF(_DPCD_EDP, _PSR_CONFIG,
3060                 _ENABLE_PSR2, _YES, config);
3061         }
3062 
3063         return AuxRetry::ack ==
3064             bus.write(NV_DPCD_EDP_PSR_CONFIG, &config, 1);
3065     }
3066 
readPsrConfigurationDPCDHALImpl3067     virtual bool readPsrConfiguration(vesaPsrConfig *psrcfg)
3068     {
3069         NvU8 config = 0U;
3070         bool retVal = AuxRetry::ack ==
3071             bus.read(NV_DPCD_EDP_PSR_CONFIG, &config, 1);
3072 
3073         psrcfg->psrCfgEnable =
3074             FLD_TEST_DRF(_DPCD_EDP, _PSR_CONFIG, _SINK_ENABLE, _YES, config);
3075         psrcfg->srcTxEnabledInPsrActive =
3076             FLD_TEST_DRF(_DPCD_EDP, _PSR_CONFIG, _SOURCE_LINK_ACTIVE, _YES, config);
3077         psrcfg->crcVerifEnabledInPsrActive =
3078             FLD_TEST_DRF(_DPCD_EDP, _PSR_CONFIG, _CRC_VERIFICATION_ACTIVE,
3079                 _YES, config);
3080         psrcfg->frameCaptureSecondActiveFrame =
3081             FLD_TEST_DRF(_DPCD_EDP, _PSR_CONFIG, _FRAME_CAPTURE_INDICATION,
3082                 _SECOND, config);
3083         psrcfg->selectiveUpdateOnSecondActiveline =
3084             FLD_TEST_DRF(_DPCD_EDP, _PSR_CONFIG,
3085                 _SU_LINE_CAPTURE_INDICATION, _SECOND, config);
3086         psrcfg->enableHpdIrqOnCrcMismatch =
3087             FLD_TEST_DRF(_DPCD_EDP, _PSR_CONFIG, _HPD_IRQ_ON_CRC_ERROR, _YES, config);
3088         psrcfg->enablePsr2 =
3089             FLD_TEST_DRF(_DPCD_EDP, _PSR_CONFIG, _ENABLE_PSR2, _YES, config);
3090 
3091         return retVal;
3092     }
3093 
readPsrStateDPCDHALImpl3094     virtual bool readPsrState(vesaPsrState *psrState)
3095     {
3096         NvU8 config = 0U;
3097         bool retVal = AuxRetry::ack ==
3098             bus.read(NV_DPCD_PANEL_SELF_REFRESH_STATUS, &config, 1);
3099 
3100         if (retVal)
3101         {
3102             *psrState =
3103                 (vesaPsrState)DRF_VAL(_DPCD, _PANEL_SELF_REFRESH_STATUS,
3104                     _VAL, config);
3105         }
3106         return retVal;
3107     }
3108 
readPsrDebugInfoDPCDHALImpl3109     virtual bool readPsrDebugInfo(vesaPsrDebugStatus *psrDbgState)
3110     {
3111         NvU8 config[2] = { 0U , 0U };
3112         bool retVal = AuxRetry::ack ==
3113             bus.read(NV_DPCD_PANEL_SELF_REFRESH_DEBUG0,
3114                 &config[0], sizeof(config));
3115 
3116         if (retVal)
3117         {
3118             psrDbgState->maxResyncFrames    =
3119                 DRF_VAL(_DPCD_PANEL_SELF_REFRESH,
3120                         _DEBUG0, _MAX_RESYNC_FRAME_CNT, config[0]);
3121             psrDbgState->actualResyncFrames =
3122                 DRF_VAL(_DPCD_PANEL_SELF_REFRESH,
3123                         _DEBUG0, _LAST_RESYNC_FRAME_CNT, config[0]);
3124 
3125             psrDbgState->lastSdpPsrState =
3126                 !!DRF_VAL(_DPCD_PANEL_SELF_REFRESH, _LAST_SDP,
3127                     _PSR_STATE_BIT, config[1]);
3128             psrDbgState->lastSdpUpdateRfb =
3129                 !!DRF_VAL(_DPCD_PANEL_SELF_REFRESH, _LAST_SDP,
3130                     _RFB_BIT, config[1]);
3131             psrDbgState->lastSdpCrcValid =
3132                 !!DRF_VAL(_DPCD_PANEL_SELF_REFRESH, _LAST_SDP,
3133                     _CRC_VALID_BIT, config[1]);
3134             psrDbgState->lastSdpSuValid  =
3135                 !!DRF_VAL(_DPCD_PANEL_SELF_REFRESH, _LAST_SDP,
3136                     _SU_VALID_BIT, config[1]);
3137             psrDbgState->lastSdpFirstSURcvd =
3138                 !!DRF_VAL(_DPCD_PANEL_SELF_REFRESH, _LAST_SDP,
3139                     _SU_FIRST_LINE_RCVD, config[1]);
3140             psrDbgState->lastSdpLastSURcvd =
3141                 !!DRF_VAL(_DPCD_PANEL_SELF_REFRESH, _LAST_SDP,
3142                     _SU_LAST_LINE_RCVD, config[1]);
3143             psrDbgState->lastSdpYCoordValid =
3144                 !!DRF_VAL(_DPCD_PANEL_SELF_REFRESH, _LAST_SDP,
3145                     _Y_CORD_VALID, config[1]);
3146         }
3147         return retVal;
3148     }
3149 
writePsrErrorStatusDPCDHALImpl3150     virtual bool writePsrErrorStatus(vesaPsrErrorStatus psrErr)
3151     {
3152         NvU8 config = 0U;
3153         config = FLD_SET_DRF_NUM(_DPCD_PANEL_SELF_REFRESH,
3154             _ERR_STATUS,
3155             _LINK_CRC_ERR,
3156             psrErr.linkCrcError,
3157             config);
3158         config = FLD_SET_DRF_NUM(_DPCD_PANEL_SELF_REFRESH,
3159             _ERR_STATUS,
3160             _RFB_ERR,
3161             psrErr.rfbStoreError,
3162             config);
3163         config = FLD_SET_DRF_NUM(_DPCD_PANEL_SELF_REFRESH,
3164             _ERR_STATUS,
3165             _VSC_SDP_ERR,
3166             psrErr.vscSdpError,
3167             config);
3168 
3169         return AuxRetry::ack == bus.write(
3170             NV_DPCD_PANEL_SELF_REFRESH_ERR_STATUS, &config, 1);
3171     }
3172 
readPsrErrorStatusDPCDHALImpl3173     virtual bool readPsrErrorStatus(vesaPsrErrorStatus *psrErr)
3174     {
3175         NvU8 config = 0U;
3176         bool retVal;
3177         retVal = AuxRetry::ack == bus.read(
3178                                      NV_DPCD_PANEL_SELF_REFRESH_ERR_STATUS,
3179                                      &config, sizeof(config));
3180 
3181         if (retVal)
3182         {
3183             psrErr->vscSdpError = FLD_TEST_DRF(_DPCD,
3184                                                _PANEL_SELF_REFRESH_ERR_STATUS,
3185                                                _LINK_CRC_ERR, _YES, config);
3186             psrErr->rfbStoreError = FLD_TEST_DRF(_DPCD,
3187                                                _PANEL_SELF_REFRESH_ERR_STATUS,
3188                                                _RFB_ERR, _YES, config);
3189             psrErr->linkCrcError = FLD_TEST_DRF(_DPCD,
3190                                                _PANEL_SELF_REFRESH_ERR_STATUS,
3191                                                _VSC_SDP_ERR,
3192                                                _YES, config);
3193         }
3194         return retVal;
3195     }
3196 
writePsrEvtIndicatorDPCDHALImpl3197     virtual bool writePsrEvtIndicator(vesaPsrEventIndicator psrEvt)
3198     {
3199         NvU8 config = 0U;
3200 
3201         if (psrEvt.sinkCapChange)
3202         {
3203             config = FLD_SET_DRF(_DPCD,
3204                 _PANEL_SELF_REFRESH_EVENT_STATUS,
3205                 _CAP_CHANGE,
3206                 _YES, config);
3207         }
3208         return AuxRetry::ack == bus.write(
3209             NV_DPCD_PANEL_SELF_REFRESH_EVENT_STATUS, &config, 1);
3210     }
3211 
readPsrEvtIndicatorDPCDHALImpl3212     virtual bool readPsrEvtIndicator(vesaPsrEventIndicator *psrEvt)
3213     {
3214         NvU8 config = 0U;
3215         bool retVal;
3216         retVal = AuxRetry::ack == bus.read(
3217             NV_DPCD_PANEL_SELF_REFRESH_EVENT_STATUS,
3218             &config, sizeof(config));
3219 
3220         if (retVal)
3221         {
3222             psrEvt->sinkCapChange = DRF_VAL(_DPCD,
3223                                             _PANEL_SELF_REFRESH_EVENT_STATUS,
3224                                             _CAP_CHANGE,
3225                                             config);
3226         }
3227         return retVal;
3228     }
3229 
readPrSinkDebugInfoDPCDHALImpl3230     virtual bool readPrSinkDebugInfo(panelReplaySinkDebugInfo *prDbgInfo)
3231     {
3232         NvU8 config = 0U;
3233         bool bRetVal = (AuxRetry::ack ==
3234                 bus.read(NV_DPCD20_PANEL_REPLAY_ERROR_STATUS,
3235                     &config, sizeof(config)));
3236 
3237         if (bRetVal)
3238         {
3239              prDbgInfo->activeFrameCrcError =
3240                  FLD_TEST_DRF(_DPCD20_PANEL_REPLAY, _ERROR_STATUS,
3241                          _ACTIVE_FRAME_CRC_ERROR, _YES, config);
3242              prDbgInfo->rfbStorageError =
3243                  FLD_TEST_DRF(_DPCD20_PANEL_REPLAY, _ERROR_STATUS,
3244                          _RFB_STORAGE_ERROR, _YES, config);
3245              prDbgInfo->vscSdpUncorrectableError =
3246                  FLD_TEST_DRF(_DPCD20_PANEL_REPLAY, _ERROR_STATUS,
3247                      _VSC_SDP_UNCORRECTABLE_ERROR, _YES, config);
3248              prDbgInfo->adaptiveSyncSdpMissing =
3249                  FLD_TEST_DRF(_DPCD20_PANEL_REPLAY, _ERROR_STATUS,
3250                      _ADAPTIVE_SYNC_SDP_MISSING, _YES, config);
3251         }
3252         else
3253         {
3254             DP_LOG(("DPHAL> readPrSinkDebugInfo: Failed to read PanelReplay error status"));
3255             return bRetVal;
3256         }
3257 
3258         config = 0U;
3259         bRetVal = (AuxRetry::ack ==
3260             bus.read(NV_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS,
3261                 &config, sizeof(config)));
3262         if (bRetVal)
3263         {
3264             prDbgInfo->sinkPrStatus = DRF_VAL(_DPCD20,
3265                 _PANEL_REPLAY_AND_FRAME_LOCK_STATUS, _PR_STATUS, config);
3266 
3267             prDbgInfo->sinkFramelocked = DRF_VAL(_DPCD20,
3268                 _PANEL_REPLAY_AND_FRAME_LOCK_STATUS, _SINK_FRAME_LOCKED, config);
3269 
3270             prDbgInfo->sinkFrameLockedValid =
3271                 FLD_TEST_DRF(_DPCD20_PANEL_REPLAY_AND_FRAME_LOCK_STATUS,
3272                     _SINK_FRAME_LOCKED, _VALID, _YES, config);
3273         }
3274         else
3275         {
3276             DP_LOG(("DPHAL> readPanelReplayError: Failed to read PanelReplay frame lock status"));
3277             return bRetVal;
3278         }
3279 
3280         config = 0U;
3281         bRetVal = AuxRetry::ack ==
3282             bus.read(NV_DPCD20_PANEL_REPLAY_DEBUG_LAST_VSC_SDP_CARRYING_PR_INFO,
3283                 &config, sizeof(config));
3284         if (bRetVal)
3285         {
3286             prDbgInfo->currentPrState =
3287                 FLD_TEST_DRF(_DPCD20_PANEL_REPLAY_DEBUG_LAST,
3288                     _VSC_SDP_CARRYING_PR_INFO, _STATE, _ACTIVE, config);
3289             prDbgInfo->crcValid =
3290                 FLD_TEST_DRF(_DPCD20_PANEL_REPLAY_DEBUG_LAST,
3291                     _VSC_SDP_CARRYING_PR_INFO, _CRC_VALID, _YES, config);
3292             prDbgInfo->suCoordinatesValid  =
3293                 FLD_TEST_DRF(_DPCD20_PANEL_REPLAY_DEBUG_LAST,
3294                     _VSC_SDP_CARRYING_PR_INFO, _SU_COORDINATE_VALID,
3295                         _YES, config);
3296         }
3297         else
3298         {
3299             DP_LOG(("DPHAL> readPanelReplayError: Failed to read PanelReplay VSC SDP status"));
3300             return bRetVal;
3301         }
3302     return bRetVal;
3303     }
3304 
3305 };
3306 
MakeDPCDHAL(AuxBus * bus,Timer * timer)3307 DPCDHAL * DisplayPort::MakeDPCDHAL(AuxBus *  bus, Timer * timer)
3308 {
3309     return new DPCDHALImpl(bus, timer);
3310 }
3311