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