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_evoadapter.cpp                                                 *
27 *    Interface for low level access to the aux bus.                         *
28 *    This is the synchronous version of the interface.                      *
29 *                                                                           *
30 \***************************************************************************/
31 #include "dp_internal.h"
32 #include "dp_evoadapter.h"
33 #include "dp_auxdefs.h"
34 #include "dp_tracing.h"
35 #include "dp_vrr.h"
36 #include <nvmisc.h>
37 
38 #include <ctrl/ctrl0073/ctrl0073specific.h>
39 #include <ctrl/ctrl0073/ctrl0073system.h>
40 #include <ctrl/ctrl5070/ctrl5070or.h>
41 
42 using namespace DisplayPort;
43 
44 //
45 //  Evo hardcodes the relationship between stream and head #
46 //    Head#x is always stream x+1
47 //
48 #define STREAM_TO_HEAD_ID(s) ((s) - 1)
49 #define HEAD_TO_STREAM_ID(s) ((s) + 1)
50 
51 //
52 // Data Base used to store all the regkey values.
53 // The type is defined in dp_regkeydatabase.h.
54 // All entries set to 0 before initialized by the first EvoMainLink constructor.
55 // The first EvoMainLink constructor will populate that data base.
56 // Later EvoMainLink will use values from that data base.
57 //
58 static struct DP_REGKEY_DATABASE dpRegkeyDatabase = {0};
59 
60 enum DP_REG_VAL_TYPE
61 {
62     DP_REG_VAL_BOOL = 0,
63     DP_REG_VAL_U32  = 1,
64     DP_REG_VAL_U16  = 2,
65     DP_REG_VAL_U8   = 3
66 };
67 
68 const struct
69 {
70     const char* pName;
71     void* pValue;
72     DP_REG_VAL_TYPE valueType;
73 } DP_REGKEY_TABLE [] =
74 {
75     {NV_DP_REGKEY_ENABLE_AUDIO_BEYOND_48K,          &dpRegkeyDatabase.bAudioBeyond48kEnabled,          DP_REG_VAL_BOOL},
76     {NV_DP_REGKEY_OVERRIDE_DPCD_REV,                &dpRegkeyDatabase.dpcdRevOveride,                  DP_REG_VAL_U32},
77     {NV_DP_REGKEY_DISABLE_SSC,                      &dpRegkeyDatabase.bSscDisabled,                    DP_REG_VAL_BOOL},
78     {NV_DP_REGKEY_ENABLE_FAST_LINK_TRAINING,        &dpRegkeyDatabase.bFastLinkTrainingEnabled,        DP_REG_VAL_BOOL},
79     {NV_DP_REGKEY_DISABLE_MST,                      &dpRegkeyDatabase.bMstDisabled,                    DP_REG_VAL_BOOL},
80     {NV_DP_REGKEY_ENABLE_INBAND_STEREO_SIGNALING,   &dpRegkeyDatabase.bInbandStereoSignalingEnabled,   DP_REG_VAL_BOOL},
81     {NV_DP_REGKEY_SKIP_POWEROFF_EDP_IN_HEAD_DETACH, &dpRegkeyDatabase.bPoweroffEdpInHeadDetachSkipped, DP_REG_VAL_BOOL},
82     {NV_DP_REGKEY_ENABLE_OCA_LOGGING,               &dpRegkeyDatabase.bOcaLoggingEnabled,              DP_REG_VAL_BOOL},
83     {NV_DP_REGKEY_REPORT_DEVICE_LOST_BEFORE_NEW,    &dpRegkeyDatabase.bReportDeviceLostBeforeNew,      DP_REG_VAL_BOOL},
84     {NV_DP_REGKEY_APPLY_LINK_BW_OVERRIDE_WAR,       &dpRegkeyDatabase.bLinkBwOverrideWarApplied,       DP_REG_VAL_BOOL},
85     {NV_DP_REGKEY_APPLY_MAX_LINK_RATE_OVERRIDES,    &dpRegkeyDatabase.applyMaxLinkRateOverrides,       DP_REG_VAL_U32},
86     {NV_DP_REGKEY_DISABLE_DSC,                      &dpRegkeyDatabase.bDscDisabled,                    DP_REG_VAL_BOOL},
87     {NV_DP_REGKEY_SKIP_ASSESSLINK_FOR_EDP,          &dpRegkeyDatabase.bAssesslinkForEdpSkipped,        DP_REG_VAL_BOOL},
88     {NV_DP_REGKEY_HDCP_AUTH_ONLY_ON_DEMAND,         &dpRegkeyDatabase.bHdcpAuthOnlyOnDemand,           DP_REG_VAL_BOOL},
89     {NV_DP_REGKEY_ENABLE_MSA_OVER_MST,              &dpRegkeyDatabase.bMsaOverMstEnabled,              DP_REG_VAL_BOOL},
90     {NV_DP_REGKEY_KEEP_OPT_LINK_ALIVE,              &dpRegkeyDatabase.bOptLinkKeptAlive,               DP_REG_VAL_BOOL},
91     {NV_DP_REGKEY_KEEP_OPT_LINK_ALIVE_MST,          &dpRegkeyDatabase.bOptLinkKeptAliveMst,            DP_REG_VAL_BOOL},
92     {NV_DP_REGKEY_KEEP_OPT_LINK_ALIVE_SST,          &dpRegkeyDatabase.bOptLinkKeptAliveSst,            DP_REG_VAL_BOOL},
93     {NV_DP_REGKEY_FORCE_EDP_ILR,                    &dpRegkeyDatabase.bBypassEDPRevCheck,              DP_REG_VAL_BOOL},
94     {NV_DP_DSC_MST_CAP_BUG_3143315,                 &dpRegkeyDatabase.bDscMstCapBug3143315,            DP_REG_VAL_BOOL},
95     {NV_DP_REGKEY_POWER_DOWN_PHY,                   &dpRegkeyDatabase.bPowerDownPhyBeforeD3,           DP_REG_VAL_BOOL},
96     {NV_DP_REGKEY_REASSESS_MAX_LINK,                &dpRegkeyDatabase.bReassessMaxLink,                DP_REG_VAL_BOOL},
97     {NV_DP_REGKEY_MST_PCON_CAPS_READ_DISABLED,      &dpRegkeyDatabase.bMSTPCONCapsReadDisabled,        DP_REG_VAL_BOOL},
98     {NV_DP_REGKEY_FORCE_DSC_ON_SINK,                &dpRegkeyDatabase.bForceDscOnSink,                 DP_REG_VAL_BOOL},
99 };
100 
101 EvoMainLink::EvoMainLink(EvoInterface * provider, Timer * timer) :
102                          provider(provider),
103                          timer(timer),
104                          displayId(provider->getDisplayId()),
105                          subdeviceIndex(provider->getSubdeviceIndex())
106 {
107     //
108     //     Process GPU caps  (This needs to be replaced with a control call caps interface)
109     //
110     NvU32 code;
111 
112     // Initialize shared regkey data base, and apply the overrides
113     this->initializeRegkeyDatabase();
114     this->applyRegkeyOverrides();
115 
116     _isDynamicMuxCapable       = false;
117     _isLTPhyRepeaterSupported  = true;
118     _rmPhyRepeaterCount        = 0;
119     dpMemZero(&_DSC, sizeof(_DSC));
120     dpMemZero(&dfpParams, sizeof(dfpParams));
121     dpMemZero(&dpParams, sizeof(dpParams));
122 
123     //
124     //  Tell RM to hands off on the DisplayPort hardware
125     //
126     NV0073_CTRL_CMD_DP_SET_MANUAL_DISPLAYPORT_PARAMS setManualParams = {0};
127     setManualParams.subDeviceInstance = subdeviceIndex;
128     code = provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_MANUAL_DISPLAYPORT, &setManualParams, sizeof setManualParams);
129     DP_ASSERT (code == NVOS_STATUS_SUCCESS && "Unable to enable library mode");
130 
131     //
132     //  Get the mask of valid heads
133     //
134     NV0073_CTRL_SPECIFIC_GET_ALL_HEAD_MASK_PARAMS allHeadMaskParams;
135     dpMemZero(&allHeadMaskParams, sizeof allHeadMaskParams);
136     allHeadMaskParams.subDeviceInstance = subdeviceIndex;
137     code = provider->rmControl0073(NV0073_CTRL_CMD_SPECIFIC_GET_ALL_HEAD_MASK, &allHeadMaskParams, sizeof(allHeadMaskParams));
138 
139     if (code != NVOS_STATUS_SUCCESS)
140     {
141         DP_ASSERT(0 && "Unable to get head mask");
142         allHeadMask = 3;
143     }
144     else
145     {
146         allHeadMask = allHeadMaskParams.headMask;
147     }
148 }
149 
150 
151 bool EvoMainLink::vrrRunEnablementStage(unsigned stage, NvU32 *status)
152 {
153     NV0073_CTRL_CMD_DP_ENABLE_VRR_PARAMS  params = {0};
154     params.subDeviceInstance = subdeviceIndex;
155     params.displayId = this->displayId;
156 
157     switch (stage)
158     {
159         case VRR_ENABLE_STAGE_MONITOR_ENABLE_BEGIN:
160             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _MONITOR_ENABLE_BEGIN);
161             break;
162         case VRR_ENABLE_STAGE_MONITOR_ENABLE_CHALLENGE:
163             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _MONITOR_ENABLE_CHALLENGE);
164             break;
165         case VRR_ENABLE_STAGE_MONITOR_ENABLE_CHECK:
166             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _MONITOR_ENABLE_CHECK);
167             break;
168         case VRR_ENABLE_STAGE_DRIVER_ENABLE_BEGIN:
169             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _DRIVER_ENABLE_BEGIN);
170             break;
171         case VRR_ENABLE_STAGE_DRIVER_ENABLE_CHALLENGE:
172             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _DRIVER_ENABLE_CHALLENGE);
173             break;
174         case VRR_ENABLE_STAGE_DRIVER_ENABLE_CHECK:
175             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _DRIVER_ENABLE_CHECK);
176             break;
177         case VRR_ENABLE_STAGE_RESET_MONITOR:
178             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _RESET_MONITOR);
179             break;
180         case VRR_ENABLE_STAGE_INIT_PUBLIC_INFO:
181             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _INIT_PUBLIC_INFO);
182             break;
183         case VRR_ENABLE_STAGE_GET_PUBLIC_INFO:
184             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _GET_PUBLIC_INFO);
185             break;
186         case VRR_ENABLE_STAGE_STATUS_CHECK:
187             params.cmd |= DRF_DEF(0073_CTRL_DP_CMD, _ENABLE_VRR_CMD, _STAGE, _STATUS_CHECK);
188             break;
189         default:
190             DP_ASSERT(0 && "Undefined VRR Enablement Stage.");
191             return false;
192     }
193     NvU32 retVal = provider->rmControl0073(NV0073_CTRL_CMD_DP_ENABLE_VRR, &params, sizeof(params));
194     if (status)
195     {
196         *status = params.result;
197     }
198     if (retVal != NVOS_STATUS_SUCCESS)
199     {
200         return false;
201     }
202     return true;
203 }
204 
205 bool EvoMainLink::getEdpPowerData(bool *panelPowerOn, bool *dpcdPowerStateD0)
206 {
207     NV0073_CTRL_DP_GET_EDP_DATA_PARAMS  params;
208     params.subDeviceInstance = subdeviceIndex;
209     params.displayId = this->displayId;
210     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_DP_GET_EDP_DATA, &params, sizeof(params));
211 
212     if (code != NVOS_STATUS_SUCCESS)
213     {
214         DP_ASSERT(0 && "Unable to get eDP power data, assuming panel off.");
215         if (panelPowerOn)
216         {
217             *panelPowerOn = false;
218         }
219         if (dpcdPowerStateD0)
220         {
221             *dpcdPowerStateD0 = false;
222         }
223         return false;
224     }
225     else
226     {
227         if (panelPowerOn)
228         {
229             *panelPowerOn = FLD_TEST_DRF(0073_CTRL_DP, _GET_EDP_DATA, _PANEL_POWER, _ON,
230                                          params.data);
231         }
232         if (dpcdPowerStateD0)
233         {
234             *dpcdPowerStateD0 = FLD_TEST_DRF(0073_CTRL_DP, _GET_EDP_DATA, _DPCD_POWER_STATE, _D0,
235                                            params.data);
236         }
237         return true;
238     }
239 }
240 
241 NvU32 EvoMainLink::streamToHead(NvU32 streamId, DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamIdentifier)
242 {
243     NvU32 headIndex = 0;
244     NvU32 maxHeads = allHeadMask;
245     NUMSETBITS_32(maxHeads);
246     headIndex = DP_MST_STREAMID_TO_HEAD(streamId, streamIdentifier, maxHeads);
247 
248     return headIndex;
249 }
250 
251 NvU32 EvoMainLink::headToStream(NvU32 head, DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamIdentifier)
252 {
253     NvU32 streamIndex = 0;
254 
255     NvU32 maxHeads = allHeadMask;
256     NUMSETBITS_32(maxHeads);
257     streamIndex = DP_MST_HEAD_TO_STREAMID(head, streamIdentifier, maxHeads);
258 
259     return streamIndex;
260 }
261 
262 bool EvoMainLink::queryGPUCapability()
263 {
264     dpMemZero(&dpParams, sizeof(dpParams));
265     dpParams.subDeviceInstance = subdeviceIndex;
266     dpParams.sorIndex = provider->getSorIndex();
267     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_DP_GET_CAPS, &dpParams, sizeof(dpParams));
268     if (code != NVOS_STATUS_SUCCESS)
269     {
270         DP_ASSERT(0 && "Unable to process GPU caps");
271         return false;
272     }
273     //
274     // Check if MST feature needs to be disabled by regkey. This is requirement by few OEMs, they don't want to support
275     // MST feature on particular sku, whenever requested through INF.
276     //
277     _hasMultistream         = (dpParams.bIsMultistreamSupported == NV_TRUE) && !_isMstDisabledByRegkey;
278 
279     _gpuSupportedDpVersions = dpParams.dpVersionsSupported;
280 
281     _isStreamCloningEnabled = (dpParams.bIsSCEnabled == NV_TRUE) ? true : false;
282     _hasIncreasedWatermarkLimits     = (dpParams.bHasIncreasedWatermarkLimits == NV_TRUE) ? true : false;
283 
284     _isFECSupported         = (dpParams.bFECSupported == NV_TRUE) ? true : false;
285 
286     _useDfpMaxLinkRateCaps  = (dpParams.bOverrideLinkBw == NV_TRUE) ? true : false;
287 
288     _isLTPhyRepeaterSupported        = (dpParams.bIsTrainPhyRepeater == NV_TRUE) ? true : false;
289 
290     if (FLD_TEST_DRF(0073, _CTRL_CMD_DP_GET_CAPS, _MAX_LINK_RATE, _1_62, dpParams.maxLinkRate))
291         _maxLinkRateSupportedGpu = RBR; //in Hz
292     else if (FLD_TEST_DRF(0073, _CTRL_CMD_DP_GET_CAPS, _MAX_LINK_RATE, _2_70, dpParams.maxLinkRate))
293         _maxLinkRateSupportedGpu = HBR; //in Hz
294     else if (FLD_TEST_DRF(0073, _CTRL_CMD_DP_GET_CAPS, _MAX_LINK_RATE, _5_40, dpParams.maxLinkRate))
295         _maxLinkRateSupportedGpu = HBR2; //in Hz
296     else if (FLD_TEST_DRF(0073, _CTRL_CMD_DP_GET_CAPS, _MAX_LINK_RATE, _8_10, dpParams.maxLinkRate))
297         _maxLinkRateSupportedGpu = HBR3; //in Hz
298     else
299     {
300         DP_ASSERT(0 && "Unable to get max link rate");
301         // Assume that we can at least support RBR.
302         _maxLinkRateSupportedGpu = RBR;
303     }
304 
305     if (!_isDscDisabledByRegkey)
306     {
307         _DSC.isDscSupported = dpParams.DSC.bDscSupported ? true : false;
308         _DSC.encoderColorFormatMask = dpParams.DSC.encoderColorFormatMask;
309         _DSC.lineBufferSizeKB = dpParams.DSC.lineBufferSizeKB;
310         _DSC.rateBufferSizeKB = dpParams.DSC.rateBufferSizeKB;
311         _DSC.bitsPerPixelPrecision = dpParams.DSC.bitsPerPixelPrecision;
312         _DSC.maxNumHztSlices = dpParams.DSC.maxNumHztSlices;
313         _DSC.lineBufferBitDepth = dpParams.DSC.lineBufferBitDepth;
314     }
315     return true;
316 }
317 
318 void EvoMainLink::triggerACT()
319 {
320     NV0073_CTRL_CMD_DP_SEND_ACT_PARAMS params = {0};
321     params.subDeviceInstance = this->subdeviceIndex;
322     params.displayId = this->displayId;
323 
324     provider->rmControl0073(NV0073_CTRL_CMD_DP_SEND_ACT, &params, sizeof params);
325 }
326 
327 void EvoMainLink::configureHDCPRenegotiate(NvU64 cN, NvU64 cKSV, bool bForceReAuth, bool bRxIDMsgPending){}
328 void EvoMainLink::configureHDCPGetHDCPState(HDCPState &hdcpState)
329 {
330     // HDCP Not Supported
331     hdcpState.HDCP_State_Repeater_Capable = false;
332     hdcpState.HDCP_State_22_Capable = false;
333     hdcpState.HDCP_State_Encryption = false;
334     hdcpState.HDCP_State_Authenticated = false;
335 }
336 
337 void EvoMainLink::configureSingleStream(NvU32 head,
338                                         NvU32 hBlankSym,
339                                         NvU32 vBlankSym,
340                                         bool  bEnhancedFraming,
341                                         NvU32 tuSize,
342                                         NvU32 waterMark,
343                                         DP_COLORFORMAT colorFormat,
344                                         DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamId,
345                                         DP_SINGLE_HEAD_MULTI_STREAM_MODE singleHeadMultiStreamMode,
346                                         bool bAudioOverRightPanel,
347                                         bool bEnable2Head1Or)
348 {
349     NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS params = {0};
350     params.subDeviceInstance = this->subdeviceIndex;
351     params.head = head;
352     params.sorIndex = provider->getSorIndex();
353     params.bEnableTwoHeadOneOr = bEnable2Head1Or;
354 
355     if (singleHeadMultiStreamMode == DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST)
356     {
357         // In 2-SST mode configure Head-SF on primary link, so primary link configuration
358         // gets copied to secondary link.
359         params.dpLink = streamId;
360     }
361     else
362     {
363         params.dpLink = provider->getLinkIndex();
364     }
365 
366     params.bEnableOverride = NV_TRUE;
367     params.bMST = NV_FALSE;
368     params.hBlankSym = hBlankSym;
369     params.vBlankSym = vBlankSym;
370     params.colorFormat = colorFormat;
371 
372     params.SST.bEnhancedFraming = bEnhancedFraming;
373     params.SST.tuSize = tuSize;
374     params.SST.waterMark = waterMark;
375     params.SST.bEnableAudioOverRightPanel = bAudioOverRightPanel;
376 
377     provider->rmControl0073(NV0073_CTRL_CMD_DP_CONFIG_STREAM, &params, sizeof params);
378 }
379 
380 void EvoMainLink::configureSingleHeadMultiStreamMode(NvU32 displayIDs[],
381                                                      NvU32 numStreams,
382                                                      NvU32 mode,
383                                                      bool  bSetConfig,
384                                                      NvU8  vbiosPrimaryDispIdIndex)
385 {
386     NV0073_CTRL_CMD_DP_CONFIG_SINGLE_HEAD_MULTI_STREAM_PARAMS params = {0};
387     params.subDeviceInstance = this->subdeviceIndex;
388 
389     for (NvU32 pipelineID = 0; pipelineID < numStreams; pipelineID++)
390     {
391         params.displayIDs[pipelineID] = displayIDs[pipelineID];
392     }
393     params.mode = mode;
394     params.bSetConfig = bSetConfig;
395     params.numStreams = numStreams;
396     params.vbiosPrimaryDispIdIndex = vbiosPrimaryDispIdIndex;
397 
398     provider->rmControl0073(NV0073_CTRL_CMD_DP_CONFIG_SINGLE_HEAD_MULTI_STREAM,
399                             &params,
400                             sizeof params);
401 }
402 
403 void EvoMainLink::configureMultiStream(NvU32 head,
404                                        NvU32 hBlankSym,
405                                        NvU32 vBlankSym,
406                                        NvU32 slotStart,
407                                        NvU32 slotEnd,
408                                        NvU32 PBN,
409                                        NvU32 Timeslice,
410                                        DP_COLORFORMAT colorFormat,
411                                        DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamIdentifier,
412                                        DP_SINGLE_HEAD_MULTI_STREAM_MODE singleHeadMultistreamMode,
413                                        bool bAudioOverRightPanel,
414                                        bool bEnable2Head1Or)
415 {
416     NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS params = {0};
417     params.head = head;
418     params.subDeviceInstance = this->subdeviceIndex;
419     params.sorIndex = provider->getSorIndex();
420     params.dpLink = provider->getLinkIndex();
421     params.bEnableOverride = NV_TRUE;
422     params.bMST = NV_TRUE;
423     params.hBlankSym = hBlankSym;
424     params.vBlankSym = vBlankSym;
425     params.colorFormat = colorFormat;
426     params.bEnableTwoHeadOneOr = bEnable2Head1Or;
427     params.singleHeadMultistreamMode = singleHeadMultistreamMode;
428 
429     params.MST.slotStart = slotStart;
430     params.MST.slotEnd = slotEnd;
431     params.MST.PBN = PBN;
432     params.MST.Timeslice = Timeslice;
433     params.MST.singleHeadMSTPipeline = streamIdentifier;
434     params.MST.bEnableAudioOverRightPanel = bAudioOverRightPanel;
435 
436     provider->rmControl0073(NV0073_CTRL_CMD_DP_CONFIG_STREAM, &params, sizeof params);
437 }
438 
439 void EvoMainLink::configureMsScratchRegisters(NvU32 address,
440                                               NvU32 hopCount,
441                                               NvU32 dpMsDevAddrState)
442 {
443     NV0073_CTRL_CMD_DP_CONFIG_RAD_SCRATCH_REG_PARAMS params = {0};
444     params.subDeviceInstance = this->subdeviceIndex;
445     params.displayId = this->displayId;
446     params.activeDevAddr = address;
447     params.sorIndex = provider->getSorIndex();
448     params.dpLink = provider->getLinkIndex();
449     params.hopCount = hopCount;
450     params.dpMsDevAddrState = dpMsDevAddrState;
451 
452     provider->rmControl0073(NV0073_CTRL_CMD_DP_CONFIG_RAD_SCRATCH_REG, &params, sizeof params);
453 }
454 
455 //
456 // EvoMainLink::setDpStereoMSAParameters does the DP library Stereo override for
457 // In-band signaling through the MSA MISC1 field and keeps the rest of the MSA
458 // params the same.
459 //
460 // On GK110 and later, when stereo is enabled, we send the stereo eye
461 // information to the sink device through the MSA MISC1 bits 2:1.  Certain
462 // DP 1.2 non-compliant DP->VGA dongles cannot handle this information, and
463 // lose all signal when these bits are non-zero.  This WAR uses a RM control
464 // to override those MSA bits to zero.  It should be called whenever a DP->VGA
465 // dongle is in use.
466 //
467 bool EvoMainLink::setDpStereoMSAParameters(bool bStereoEnable, const NV0073_CTRL_CMD_DP_SET_MSA_PROPERTIES_PARAMS &msaparams)
468 {
469     NV0073_CTRL_CMD_DP_SET_STEREO_MSA_PROPERTIES_PARAMS params = {0};
470     params.subDeviceInstance = this->subdeviceIndex;
471     params.displayId = msaparams.displayId;
472     //clubbing the MSA params passed by DD with Dp Library Stereo Override
473     params.bStereoPhaseInverse = msaparams.bStereoPhaseInverse;
474     params.featureValues.misc[1] = msaparams.featureValues.misc[1];
475 
476     if (bStereoEnable) {
477         params.bEnableMSA = NV_TRUE | msaparams.bEnableMSA;
478         params.featureMask.miscMask[1] = DRF_SHIFTMASK(NV_DP_MSA_PROPERTIES_MISC1_STEREO) | msaparams.featureMask.miscMask[1];
479     } else {
480         params.bEnableMSA = NV_FALSE | msaparams.bEnableMSA;
481         params.featureMask.miscMask[1] |= msaparams.featureMask.miscMask[1];
482     }
483 
484     NvU32 ret = provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_STEREO_MSA_PROPERTIES, &params, sizeof params);
485 
486     //
487     // NV0073_CTRL_CMD_DP_SET_MSA_PROPERTIES is only implemented on GK110 and
488     // later, but this WAR is unnecessary on other GPUs, so ignore
489     // ERROR_NOT_SUPPORTED.
490     //
491     // XXX This may fail if a future GPU requires this WAR but does not
492     // implement this rmcontrol.  To avoid that, this class would need to be
493     // aware of which evo display HAL is in use.
494     //
495     if (ret != NVOS_STATUS_SUCCESS && ret != NVOS_STATUS_ERROR_NOT_SUPPORTED) {
496         DP_ASSERT(!"Enabling MSA stereo override failed!");
497         return false;
498     }
499 
500     return true;
501 }
502 
503 //
504 // EvoMainLink::setDpMSAParameters clubs MSA parameters passed by DD for format YCbCr4:2:0
505 // with DP library Stereo override for In-band signaling through the MSA MISC1 field.
506 //
507 // On GK110 and later, when stereo is enabled, we send the stereo eye
508 // information to the sink device through the MSA MISC1 bits 2:1.  Certain
509 // DP 1.2 non-compliant DP->VGA dongles cannot handle this information, and
510 // lose all signal when these bits are non-zero.  This WAR uses a RM control
511 // to override those MSA bits to zero.  It should be called whenever a DP->VGA
512 // dongle is in use.
513 //
514 bool EvoMainLink::setDpMSAParameters(bool bStereoEnable, const NV0073_CTRL_CMD_DP_SET_MSA_PROPERTIES_PARAMS &msaparams)
515 {
516     NV0073_CTRL_CMD_DP_SET_MSA_PROPERTIES_PARAMS params = {0};
517     params.subDeviceInstance = this->subdeviceIndex;
518     params.displayId = msaparams.displayId;
519     //clubbing the MSA params passed by DD with Dp Library Stereo Override
520     params.bStereoPhaseInverse = msaparams.bStereoPhaseInverse;
521     params.bCacheMsaOverrideForNextModeset = true;
522     params.featureValues.misc[0] = msaparams.featureValues.misc[0];
523     params.featureValues.misc[1] = msaparams.featureValues.misc[1];
524     params.featureMask.miscMask[0] = msaparams.featureMask.miscMask[0];
525 
526     params.featureValues.rasterTotalHorizontal = msaparams.featureValues.rasterTotalHorizontal;
527     params.featureValues.rasterTotalVertical = msaparams.featureValues.rasterTotalVertical;
528     params.featureValues.activeStartHorizontal = msaparams.featureValues.activeStartHorizontal;
529     params.featureValues.activeStartVertical = msaparams.featureValues.activeStartVertical;
530     params.featureValues.surfaceTotalHorizontal = msaparams.featureValues.surfaceTotalHorizontal;
531     params.featureValues.surfaceTotalVertical = msaparams.featureValues.surfaceTotalVertical;
532     params.featureValues.syncWidthHorizontal = msaparams.featureValues.syncWidthHorizontal;
533     params.featureValues.syncPolarityHorizontal = msaparams.featureValues.syncPolarityHorizontal;
534     params.featureValues.syncHeightVertical = msaparams.featureValues.syncHeightVertical;
535     params.featureValues.syncPolarityVertical = msaparams.featureValues.syncPolarityVertical;
536 
537     params.featureMask.bRasterTotalHorizontal = msaparams.featureMask.bRasterTotalHorizontal;
538     params.featureMask.bRasterTotalVertical = msaparams.featureMask.bRasterTotalVertical;
539     params.featureMask.bActiveStartHorizontal = msaparams.featureMask.bActiveStartHorizontal;
540     params.featureMask.bActiveStartVertical = msaparams.featureMask.bActiveStartVertical;
541     params.featureMask.bSurfaceTotalHorizontal = msaparams.featureMask.bSurfaceTotalHorizontal;
542     params.featureMask.bSurfaceTotalVertical = msaparams.featureMask.bSurfaceTotalVertical;
543     params.featureMask.bSyncWidthHorizontal = msaparams.featureMask.bSyncWidthHorizontal;
544     params.featureMask.bSyncPolarityHorizontal = msaparams.featureMask.bSyncPolarityHorizontal;
545     params.featureMask.bSyncHeightVertical = msaparams.featureMask.bSyncHeightVertical;
546     params.featureMask.bSyncPolarityVertical = msaparams.featureMask.bSyncPolarityVertical;
547 
548     params.featureValues.reserved[0] = msaparams.featureValues.reserved[0];
549     params.featureValues.reserved[1] = msaparams.featureValues.reserved[1];
550     params.featureValues.reserved[2] = msaparams.featureValues.reserved[2];
551 
552     params.pFeatureDebugValues = msaparams.pFeatureDebugValues;
553 
554     if (bStereoEnable) {
555         params.bEnableMSA = NV_TRUE | msaparams.bEnableMSA;
556         params.featureMask.miscMask[1] = DRF_SHIFTMASK(NV_DP_MSA_PROPERTIES_MISC1_STEREO) | msaparams.featureMask.miscMask[1];
557     } else {
558         params.bEnableMSA = NV_FALSE | msaparams.bEnableMSA;
559         params.featureMask.miscMask[1] |= msaparams.featureMask.miscMask[1];
560     }
561 
562     NvU32 ret = provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_MSA_PROPERTIES, &params, sizeof params);
563 
564     //
565     // NV0073_CTRL_CMD_DP_SET_MSA_PROPERTIES is only implemented on GK110 and
566     // later, but this WAR is unnecessary on other GPUs, so ignore
567     // ERROR_NOT_SUPPORTED.
568     //
569     // XXX This may fail if a future GPU requires this WAR but does not
570     // implement this rmcontrol.  To avoid that, this class would need to be
571     // aware of which evo display HAL is in use.
572     //
573     if (ret != NVOS_STATUS_SUCCESS && ret != NVOS_STATUS_ERROR_NOT_SUPPORTED) {
574         DP_ASSERT(!"Enabling MSA stereo override failed!");
575         return false;
576     }
577 
578     return true;
579 }
580 
581 bool EvoMainLink::setFlushMode()
582 {
583     NV5070_CTRL_SET_SOR_FLUSH_MODE_PARAMS params;
584     dpMemZero(&params, sizeof(params));
585 
586     params.bFireAndForget = NV_FALSE;
587 
588     params.base.subdeviceIndex = subdeviceIndex;
589     params.sorNumber = provider->getSorIndex();
590     params.bEnable = NV_TRUE;
591     params.bForceRgDiv = NV_FALSE;
592     params.bImmediate = NV_FALSE;
593     params.headMask = 0;
594 
595     NvU32 ret = provider->rmControl5070(NV5070_CTRL_CMD_SET_SOR_FLUSH_MODE, &params, sizeof params);
596 
597     DP_ASSERT((ret == NVOS_STATUS_SUCCESS) && "Enabling flush mode failed!");
598 
599     return ret == NVOS_STATUS_SUCCESS;
600 }
601 
602 void EvoMainLink::clearFlushMode(unsigned headMask, bool testMode)
603 {
604     NV5070_CTRL_SET_SOR_FLUSH_MODE_PARAMS params;
605     dpMemZero(&params, sizeof(params));
606 
607     params.bFireAndForget = NV_FALSE;
608     params.base.subdeviceIndex = subdeviceIndex;
609     params.sorNumber = provider->getSorIndex();
610     params.bEnable = NV_FALSE;
611     params.bImmediate = NV_FALSE;
612     params.headMask = headMask;
613     params.bForceRgDiv = testMode;
614 
615     NvU32 ret = provider->rmControl5070(NV5070_CTRL_CMD_SET_SOR_FLUSH_MODE, &params, sizeof params);
616     if (ret != NVOS_STATUS_SUCCESS)
617     {
618         DP_LOG(("DP_EVO> Disabling flush mode failed!"));
619     }
620 }
621 
622 
623 bool EvoMainLink::physicalLayerSetTestPattern(PatternInfo * patternInfo)
624 {
625     // Main parameter
626     NV0073_CTRL_DP_SET_TESTPATTERN_PARAMS params;
627 
628     // To identify which test pattern to transmit.
629     NV0073_CTRL_DP_TESTPATTERN ctrlPattern;
630 
631     dpMemZero(&params, sizeof(params));
632     dpMemZero(&ctrlPattern, sizeof(ctrlPattern));
633 
634     switch (patternInfo->lqsPattern)
635     {
636         case LINK_QUAL_DISABLED:    ctrlPattern.testPattern = NV0073_CTRL_DP_TESTPATTERN_DATA_NONE; break;
637         case LINK_QUAL_D10_2:       ctrlPattern.testPattern = NV0073_CTRL_DP_TESTPATTERN_DATA_D10_2; break;
638         case LINK_QUAL_SYM_ERROR:   ctrlPattern.testPattern = NV0073_CTRL_DP_TESTPATTERN_DATA_SERMP; break;
639         case LINK_QUAL_PRBS7:       ctrlPattern.testPattern = NV0073_CTRL_DP_TESTPATTERN_DATA_PRBS_7; break;
640         case LINK_QUAL_CP2520PAT3:  ctrlPattern.testPattern = NV0073_CTRL_DP_TESTPATTERN_DATA_CP2520PAT3; break;
641         case LINK_QUAL_80BIT_CUST:
642         {
643             ctrlPattern.testPattern = NV0073_CTRL_DP_TESTPATTERN_DATA_CSTM;
644 
645             params.cstm.field_31_0 = patternInfo->ctsmLower;
646             params.cstm.field_63_32 = patternInfo->ctsmMiddle;
647             params.cstm.field_95_64 = patternInfo->ctsmUpper;
648             break;
649         }
650 #ifdef NV0073_CTRL_DP_TESTPATTERN_DATA_HBR2COMPLIANCE
651         case LINK_QUAL_HBR2_COMPLIANCE_EYE:
652         {
653             ctrlPattern.testPattern = NV0073_CTRL_DP_TESTPATTERN_DATA_HBR2COMPLIANCE;
654             params.cstm.field_31_0 = 0;
655             params.cstm.field_63_32 = 0;
656             params.cstm.field_95_64 = 0;
657             break;
658         }
659 #endif
660         default:
661             DP_ASSERT(0 && "Unknown Phy Pattern");
662             return false;
663     }
664 
665     params.subDeviceInstance       = subdeviceIndex;
666     params.displayId               = displayId;
667     params.testPattern             = ctrlPattern;
668 
669     //
670     // Set the appropriate laneMask based on the current lane count. The laneMask is used for GF119+ chips
671     // only so it doesn't matter if we populate it for all chips. It is set to all lanes since
672     // setting the test pattern on a lane that is off is effectively a nop.
673     // The laneMask allows for setting the pattern on specific lanes to check for cross-talk, which is the
674     // phenomenon of observing the signal crossing over to a different lane where it's not set.
675     //
676     params.laneMask                = 0xf;
677 
678     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_TESTPATTERN, &params, sizeof(params));
679 
680     return code == NVOS_STATUS_SUCCESS;
681 }
682 
683 AuxBus::status EvoAuxBus::transaction(Action action, Type type, int address,
684                                       NvU8 * buffer, unsigned sizeRequested,
685                                       unsigned * sizeCompleted,
686                                       unsigned *pNakReason,
687                                       NvU8 offset, NvU8 nWriteTransactions)
688 {
689     NV0073_CTRL_DP_AUXCH_CTRL_PARAMS params;
690 
691     DP_ASSERT(sizeRequested <= NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE);
692 
693     dpMemZero(&params, sizeof(params));
694     params.subDeviceInstance       = subdeviceIndex;
695     params.displayId               = displayId;
696 
697     params.cmd = 0;
698 
699     if (type == native)
700         params.cmd |= DRF_DEF(0073_CTRL, _DP, _AUXCH_CMD_TYPE, _AUX);
701     else
702         params.cmd |= DRF_DEF(0073_CTRL, _DP, _AUXCH_CMD_TYPE, _I2C);
703 
704     if (type == i2cMot)
705         params.cmd |= DRF_DEF(0073_CTRL, _DP, _AUXCH_CMD_I2C_MOT, _TRUE);
706     else
707         params.cmd |= DRF_DEF(0073_CTRL, _DP, _AUXCH_CMD_I2C_MOT, _FALSE);
708 
709     if (action == read)
710         params.cmd |= DRF_DEF(0073_CTRL, _DP, _AUXCH_CMD_REQ_TYPE, _READ);
711     else if (action == write)
712     {
713         params.cmd |= DRF_DEF(0073_CTRL, _DP, _AUXCH_CMD_REQ_TYPE, _WRITE);
714         dpMemCopy(params.data, buffer, sizeRequested);
715     }
716     else if (action == writeStatusUpdateRequest)
717         params.cmd |= DRF_DEF(0073_CTRL, _DP, _AUXCH_CMD_REQ_TYPE, _WRITE_STATUS);
718     else
719         DP_ASSERT(0 && "Unknown action");
720 
721     params.addr = address;
722 
723     //
724     // By definition, an I2C-write-over-AUX request with
725     // zero bytes of data is an "address-only" transaction.
726     //
727     if ((sizeRequested == 0) && (type & (i2cMot | i2c)) && (action == write))
728     {
729         DP_LOG(("DP> Client requested address-only transaction"));
730         params.bAddrOnly = NV_TRUE;
731     }
732     else if ((sizeRequested == 0) && (type == native))
733     {
734         // Native aux transactions with size requested zero are not allowed.
735         DP_ASSERT(0 && "Native Aux transactions shouldn't have zero size requested");
736         return nack;
737     }
738 
739     // Control call is taking size as 0-based.
740     if (sizeRequested == 0)
741     {
742         //
743         // I2c transactions with size requested zero. Decrementing by 1 will
744         // lead to 0xffffff(RM_INVALID_DATA). So keep size as zero only.
745         //
746         params.size = 0;
747     }
748     else
749     {
750         params.size = sizeRequested - 1;
751     }
752 
753     NvU32 code = 0;
754     NvU8  retries = 0;
755     do
756     {
757         retries++;
758         params.retryTimeMs = 0;
759         code = provider->rmControl0073(NV0073_CTRL_CMD_DP_AUXCH_CTRL, &params, sizeof(params));
760         // eDP is not fully powered up yet. Should not access the panel too early.
761         if (params.retryTimeMs > 0)
762         {
763             timer->sleep(params.retryTimeMs);
764         }
765     } while (NVOS_STATUS_SUCCESS != code && params.retryTimeMs && retries < 3);
766 
767     if (pNakReason != NULL)
768     {
769         *pNakReason = params.replyType;
770     }
771 
772     if (action == writeStatusUpdateRequest && code == NVOS_STATUS_ERROR_NOT_SUPPORTED)
773     {
774         //
775         // On some chips write status requests are generated implicitly by the
776         // hardware. So while the RmControl() will fail with a "not supported"
777         // error, the request still went out on the DPAUX channel as part of
778         // the last IC-over-AUX write transaction. So the error should be ignored.
779         //
780         DP_LOG(("DP> %s: Ignore ERROR_NOT_SUPPORTED for writeStatusUpdateRequest. Returning Success", __FUNCTION__));
781         return AuxBus::success;
782     }
783 
784     // In case of Timeout we need to retry again for minimum no. of times
785     if (code != NVOS_STATUS_SUCCESS && code != NVOS_STATUS_ERROR_TIMEOUT)
786     {
787         if (devicePlugged)
788         {
789             DP_LOG(("DP> AuxChCtl Failing, if a device is connected you shouldn't be seeing this"));
790         }
791         return nack;
792     }
793     else if (code == NVOS_STATUS_ERROR_TIMEOUT)
794     {
795         return AuxBus::defer;
796     }
797 
798     *sizeCompleted = params.size;
799 
800     // Reset sizeCompleted if transaction failed.
801     if (params.replyType == NV0073_CTRL_DP_AUXCH_REPLYTYPE_DEFER ||
802         params.replyType == NV0073_CTRL_DP_AUXCH_REPLYTYPE_I2CDEFER)
803         *sizeCompleted = 0;
804 
805     if (params.replyType == NV0073_CTRL_DP_AUXCH_REPLYTYPE_ACK)
806     {
807         // if it was read operation copy read data to buffer
808         if (action == read)
809         {
810             // Check the size of data to be copied. Should not be
811             // more than available buffer
812             if (params.size > sizeRequested)
813             {
814                 params.size = sizeRequested;
815             }
816             dpMemCopy(buffer, params.data, params.size);
817         }
818 
819         return AuxBus::success;
820     }
821 
822     if (params.replyType == NV0073_CTRL_DP_AUXCH_REPLYTYPE_NACK ||
823         params.replyType == NV0073_CTRL_DP_AUXCH_REPLYTYPE_I2CNACK ||
824         params.replyType == NV0073_CTRL_DP_AUXCH_REPLYTYPE_TIMEOUT)
825         return AuxBus::nack;
826 
827     if (params.replyType == NV0073_CTRL_DP_AUXCH_REPLYTYPE_DEFER ||
828         params.replyType == NV0073_CTRL_DP_AUXCH_REPLYTYPE_I2CDEFER)
829         return AuxBus::defer;
830 
831     DP_ASSERT(0 && "Unknown reply type");
832     return AuxBus::nack;
833 }
834 
835 unsigned EvoAuxBus::transactionSize()
836 {
837     return NV0073_CTRL_DP_AUXCH_MAX_DATA_SIZE;
838 }
839 
840 void EvoAuxBus::setDevicePlugged(bool plugged)
841 {
842     devicePlugged = plugged;
843 }
844 
845 void EvoMainLink::preLinkTraining(NvU32 head)
846 {
847     provider->preLinkTraining(head);
848 }
849 
850 void EvoMainLink::postLinkTraining(NvU32 head)
851 {
852     provider->postLinkTraining(head);
853 }
854 
855 void EvoMainLink::initializeRegkeyDatabase()
856 {
857     NvU32 i;
858     if (dpRegkeyDatabase.bInitialized)
859         return;
860     for (i = 0; i < sizeof(DP_REGKEY_TABLE)/sizeof(DP_REGKEY_TABLE[0]); i++)
861     {
862         NvU32 tempValue = 0;
863         tempValue = provider->getRegkeyValue(DP_REGKEY_TABLE[i].pName);
864         switch (DP_REGKEY_TABLE[i].valueType)
865         {
866             case DP_REG_VAL_U32:
867                 *(NvU32*)(DP_REGKEY_TABLE[i].pValue) = tempValue;
868                 break;
869             case DP_REG_VAL_U16:
870                 *(NvU16*)(DP_REGKEY_TABLE[i].pValue) = tempValue & 0xFFFF;
871                 break;
872             case DP_REG_VAL_U8:
873                 *(NvU8*)(DP_REGKEY_TABLE[i].pValue)  = tempValue & 0xFF;
874                 break;
875             case DP_REG_VAL_BOOL:
876                 *(bool*)(DP_REGKEY_TABLE[i].pValue)  = !!tempValue;
877                 break;
878         }
879     }
880     dpRegkeyDatabase.bInitialized = true;
881 }
882 
883 void EvoMainLink::applyRegkeyOverrides()
884 {
885     if (!dpRegkeyDatabase.bInitialized)
886     {
887         DP_ASSERT(0 && "dpRegkeyDatabase is not initialized before calling applyRegkeyOverrides.");
888         this->initializeRegkeyDatabase();
889     }
890     _isMstDisabledByRegkey               = dpRegkeyDatabase.bMstDisabled;
891     _isDscDisabledByRegkey               = dpRegkeyDatabase.bDscDisabled;
892     _skipPowerdownEDPPanelWhenHeadDetach = dpRegkeyDatabase.bPoweroffEdpInHeadDetachSkipped;
893     _applyLinkBwOverrideWarRegVal        = dpRegkeyDatabase.bLinkBwOverrideWarApplied;
894     _enableMSAOverrideOverMST            = dpRegkeyDatabase.bMsaOverMstEnabled;
895     _isMSTPCONCapsReadDisabled           = dpRegkeyDatabase.bMSTPCONCapsReadDisabled;
896 }
897 
898 NvU32 EvoMainLink::getRegkeyValue(const char *key)
899 {
900     NvU32 i;
901     if (!dpRegkeyDatabase.bInitialized)
902     {
903         DP_ASSERT(0 && "dpRegkeyDatabase is not initialized before calling getRegkeyValue.");
904         initializeRegkeyDatabase();
905     }
906     if (key == NULL || key[0] == '\0')
907         return 0;
908 
909     for (i = 0; i < sizeof(DP_REGKEY_TABLE)/sizeof(DP_REGKEY_TABLE[0]); i++)
910     {
911         NvU32 j = 0;
912         bool strSame = true;
913         while (key[j] != '\0' && DP_REGKEY_TABLE[i].pName[j] != '\0')
914         {
915             if (key[j] != DP_REGKEY_TABLE[i].pName[j])
916             {
917                 strSame = false;
918                 break;
919             }
920             ++j;
921         }
922         if (strSame && key[j] == '\0' && DP_REGKEY_TABLE[i].pName[j] == '\0')
923         {
924             switch (DP_REGKEY_TABLE[i].valueType)
925             {
926                 case DP_REG_VAL_U32:
927                     return *(NvU32*)(DP_REGKEY_TABLE[i].pValue);
928                 case DP_REG_VAL_U16:
929                     return (NvU32)*(NvU16*)(DP_REGKEY_TABLE[i].pValue);
930                 case DP_REG_VAL_U8:
931                     return (NvU32)*(NvU8*)(DP_REGKEY_TABLE[i].pValue);
932                 case DP_REG_VAL_BOOL:
933                     return (NvU32)*(bool*)(DP_REGKEY_TABLE[i].pValue);
934             }
935         }
936     }
937     DP_ASSERT(0 && "Requested regkey not found in dpRegkeyDatabase.");
938     return 0;
939 }
940 
941 const DP_REGKEY_DATABASE& EvoMainLink::getRegkeyDatabase()
942 {
943     return dpRegkeyDatabase;
944 }
945 
946 NvU32 EvoMainLink::getSorIndex()
947 {
948     return provider->getSorIndex();
949 }
950 
951 bool EvoMainLink::isInbandStereoSignalingSupported()
952 {
953     return provider->isInbandStereoSignalingSupported();
954 }
955 
956 bool EvoMainLink::train(const LinkConfiguration & link, bool force,
957                         LinkTrainingType linkTrainingType,
958                         LinkConfiguration *retLink, bool bSkipLt,
959                         bool isPostLtAdjRequestGranted, unsigned phyRepeaterCount)
960 {
961     NvU32       targetIndex;
962     NvU32       ltCounter = retLink->getLTCounter();
963     bool        bTrainPhyRepeater =
964                     (!link.bDisableLTTPR) && (_isLTPhyRepeaterSupported);
965 
966     if (provider->getSorIndex() == DP_INVALID_SOR_INDEX)
967     {
968         // bail out and Skip LT since SOR is not allocated for this displayID
969         return false;
970     }
971     NvU32 err = 0;
972 
973     NvU32 dpCtrlCmd = DRF_DEF(0073_CTRL, _DP_CMD, _SET_LANE_COUNT, _TRUE) |
974         DRF_DEF(0073_CTRL, _DP_CMD, _SET_LINK_BW,    _TRUE);
975 
976     if (link.multistream)
977         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _SET_FORMAT_MODE, _MULTI_STREAM );
978 
979     if(link.bEnableFEC)
980         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _ENABLE_FEC, _TRUE);
981 
982     if (isPostLtAdjRequestGranted)
983         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _POST_LT_ADJ_REQ_GRANTED, _YES );
984 
985     if (link.enhancedFraming)
986         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _SET_ENHANCED_FRAMING, _TRUE );
987     if (bSkipLt)
988         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _SKIP_HW_PROGRAMMING, _YES );
989     if (force)
990         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _FAKE_LINK_TRAINING, _DONOT_TOGGLE_TRANSMISSION );
991 
992     if (linkTrainingType == NO_LINK_TRAINING)
993         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _NO_LINK_TRAINING, _YES );
994     else if (linkTrainingType == FAST_LINK_TRAINING)
995         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _FAST_LINK_TRAINING, _YES );
996 
997     targetIndex = NV0073_CTRL_DP_DATA_TARGET_SINK;
998     if (bTrainPhyRepeater && (_rmPhyRepeaterCount != phyRepeaterCount))
999     {
1000         // If LTTPR count is out of sync between DPLib and RM, do not link train LTTPRs.
1001         bTrainPhyRepeater = false;
1002     }
1003 
1004     if (bTrainPhyRepeater)
1005     {
1006 
1007         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _TRAIN_PHY_REPEATER, _YES );
1008         //
1009         // Start from the one closest to GPU. Note this is 1-based index.
1010         //
1011         targetIndex = phyRepeaterCount;
1012     }
1013 
1014     NV_DPTRACE_INFO(LINK_TRAINING_START, link.multistream, link.peakRate, link.lanes,
1015                         phyRepeaterCount, _rmPhyRepeaterCount, bTrainPhyRepeater, targetIndex);
1016 
1017     NvU32 status = 0;
1018     NvU8 retries = 0;
1019     bool fallback = false;
1020 
1021     //
1022     // Limited attempts to unblock infinite LT loop while CR failure restores
1023     // high rate and lanes for EQ failure
1024     //
1025     NvU32 crHighRateFallbackCount = 0;
1026 
1027     //
1028     // The rate and lane count we send to RM might be different than what client
1029     // sent to us since fallback might happen.
1030     //
1031     LinkConfiguration requestRmLC = link;
1032     do
1033     {
1034         NvU32 dpCtrlData = 0;
1035         NvU64 linkrate = requestRmLC.peakRate;
1036         NvU64 linkBw = 0;
1037 
1038         switch (linkrate)
1039         {
1040             case RBR:
1041             case EDP_2_16GHZ:
1042             case EDP_2_43GHZ:
1043             case HBR:
1044             case EDP_3_24GHZ:
1045             case EDP_4_32GHZ:
1046             case HBR2:
1047             case HBR3:
1048                 linkBw = linkrate / DP_LINK_BW_FREQ_MULTI_MBPS;
1049                 dpCtrlData = FLD_SET_DRF_NUM(0073_CTRL, _DP_DATA, _SET_LINK_BW,
1050                                              linkBw, dpCtrlData);
1051                 break;
1052             default:
1053                 if (requestRmLC.lanes != 0)
1054                 {
1055                     DP_ASSERT(0 && "Unknown rate");
1056                     return false;
1057                 }
1058                 break;
1059         }
1060 
1061         dpCtrlData = FLD_SET_DRF_NUM(0073_CTRL, _DP_DATA, _SET_LANE_COUNT,
1062                                                 requestRmLC.lanes, dpCtrlData);
1063 
1064         if (requestRmLC.lanes == 0)
1065         {
1066             // Only need to target sink when powering down the link.
1067             targetIndex = NV0073_CTRL_DP_DATA_TARGET_SINK;
1068         }
1069 
1070         dpCtrlData = FLD_SET_DRF_NUM(0073_CTRL, _DP_DATA, _TARGET,
1071                                                         targetIndex, dpCtrlData);
1072 
1073         //  Properly wait eDP to power up before link training.
1074         status      = 0;
1075         retries     = 0;
1076         fallback    = false;
1077         dpCtrlCmd = FLD_SET_DRF(0073_CTRL, _DP_CMD, _FALLBACK_CONFIG, _FALSE, dpCtrlCmd);
1078         do
1079         {
1080             NV0073_CTRL_DP_CTRL_PARAMS params;
1081 
1082             dpMemZero(&params, sizeof(params));
1083             params.subDeviceInstance       = subdeviceIndex;
1084             params.displayId               = displayId;
1085             params.cmd                     = dpCtrlCmd;
1086             params.data                    = dpCtrlData;
1087 
1088             retries++;
1089             params.retryTimeMs = 0;
1090             status = provider->rmControl0073(NV0073_CTRL_CMD_DP_CTRL, &params, sizeof(params));
1091             ltCounter++;
1092             err = params.err;
1093 
1094             if (params.retryTimeMs > 0)
1095             {
1096                 timer->sleep(params.retryTimeMs);
1097             }
1098 
1099             if (status == NVOS_STATUS_SUCCESS || bSkipLt)
1100             {
1101                 // if LT failed when bSkipLt was marked, no point in attempting LT again.
1102                 break;
1103             }
1104 
1105             if (!params.retryTimeMs || retries >= 3)
1106             {
1107                 break;
1108             }
1109 
1110         } while (true);
1111 
1112         if (NVOS_STATUS_SUCCESS == status)
1113         {
1114             if (targetIndex != NV0073_CTRL_DP_DATA_TARGET_SINK)
1115             {
1116                 targetIndex -= 1;
1117                 continue;
1118             }
1119             else
1120             {
1121                 // all done, leave the loop.
1122                 break;
1123             }
1124         }
1125 
1126         if (requestRmLC.policy.skipFallback() || bSkipLt)
1127         {
1128             //
1129             // if LT failed when bSkipLT was marked, no point in falling back as the issue
1130             // is not with LinkConfig.
1131             //
1132             break;
1133         }
1134 
1135         if (FLD_TEST_DRF(0073_CTRL_DP, _CMD, _TRAIN_PHY_REPEATER, _YES, dpCtrlCmd) &&
1136             FLD_TEST_DRF(0073_CTRL_DP, _ERR, _INVALID_PARAMETER, _ERR, err) &&
1137             FLD_TEST_DRF(0073_CTRL_DP, _ERR, _TRAIN_PHY_REPEATER, _ERR, err))
1138         {
1139             //
1140             // RM has less LTTPR than DPLib expected.
1141             //    - Force to do transparent mode.
1142             //
1143             targetIndex = NV0073_CTRL_DP_DATA_TARGET_SINK;
1144             dpCtrlCmd = FLD_SET_DRF(0073_CTRL, _DP_CMD, _TRAIN_PHY_REPEATER,
1145                                     _NO, dpCtrlCmd);
1146             continue;
1147         }
1148 
1149         dpCtrlCmd |= DRF_DEF(0073_CTRL, _DP_CMD, _FALLBACK_CONFIG, _TRUE);
1150 
1151         if (FLD_TEST_DRF(0073_CTRL_DP, _ERR, _CLOCK_RECOVERY, _ERR, err))
1152         {
1153             // If failed CR, check if we need to fallback.
1154             if (requestRmLC.peakRate != RBR)
1155             {
1156                 //
1157                 // We need to fallback on link rate if the following conditions are met:
1158                 // 1. CR or EQ phase failed.
1159                 // 2. The request link bandwidth is NOT RBR
1160                 //
1161                 if (!requestRmLC.lowerConfig())
1162                 {
1163                     // If no valid link config could be found, break here.
1164                     break;
1165                 }
1166                 fallback = true;
1167             }
1168             else
1169             {
1170                 // Already RBR
1171                 // Check how many lanes is done.
1172                 requestRmLC.lanes = DRF_VAL(0073_CTRL_DP, _ERR, _CR_DONE_LANE, err);
1173 
1174                 while (!IS_VALID_LANECOUNT(requestRmLC.lanes))
1175                 {
1176                     requestRmLC.lanes--;
1177                 }
1178 
1179                 if (requestRmLC.lanes == 0)
1180                 {
1181                     // This is to WAR some system that doesn't set CR_DONE or EQ_DONE at all.
1182                     // In this case, we just simply try half of lanes.
1183                     requestRmLC.lanes = DRF_VAL(0073_CTRL, _DP_DATA, _SET_LANE_COUNT, dpCtrlData) / 2;
1184                     if (requestRmLC.lanes == 0)
1185                     {
1186                         // Nothing to try. Bail out.
1187                         break;
1188                     }
1189                 }
1190                 // Set back to original desired rate.
1191                 requestRmLC.peakRate = link.peakRate;
1192                 fallback = true;
1193                 crHighRateFallbackCount++;
1194             }
1195         }
1196         if (FLD_TEST_DRF(0073_CTRL_DP, _ERR, _CHANNEL_EQUALIZATION, _ERR, err))
1197         {
1198             //
1199             // If Channel equalization fails, we need to use the fallback policy
1200             // of reducing the lane count vs link rate, but in the special case
1201             // when all lanes have failed CR, we resort to lowering link rate instead
1202             // (this address the new Fallback SCR v2.0)
1203             //
1204             if (FLD_TEST_DRF(0073_CTRL_DP, _ERR, _CR_DONE_LANE, _0_LANE, err))
1205             {
1206                 //Per spec, if link rate has already been reduced to RBR, exit fallback
1207                 if(requestRmLC.peakRate == RBR || !requestRmLC.lowerConfig())
1208                     break;
1209             }
1210             else
1211             {
1212                 if(!requestRmLC.lowerConfig(true))  // bReduceLaneCnt = true
1213                     break;
1214             }
1215             fallback = true;
1216         }
1217         if (fallback == false)
1218         {
1219             // Nothing to fallback, give up.
1220             break;
1221         }
1222         if ((phyRepeaterCount > 0) && (bTrainPhyRepeater))
1223         {
1224             // If fallback, need to start from beginning.
1225             targetIndex = phyRepeaterCount;
1226         }
1227     } while (crHighRateFallbackCount < NV_DP_RBR_FALLBACK_MAX_TRIES);
1228 
1229     //
1230     // Result should be checked for only the control call status. 'err'
1231     // doesn't represent failure in LT - some compliance tests such as 700.1.1.2
1232     // intentionally test against unexpected sink caps
1233     //
1234     bool result = (status == NVOS_STATUS_SUCCESS);
1235     retLink->setLaneRate(requestRmLC.peakRate, result ? requestRmLC.lanes : 0);
1236     retLink->setLTCounter(ltCounter);
1237 
1238     if (requestRmLC.bEnableFEC && (FLD_TEST_DRF(0073_CTRL_DP, _ERR, _ENABLE_FEC, _ERR, err)))
1239     {
1240         retLink->bEnableFEC = false;
1241         DP_ASSERT(0);
1242     }
1243 
1244     NV_DPTRACE_INFO(LINK_TRAINING_DONE, status, requestRmLC.peakRate, requestRmLC.lanes);
1245 
1246     return result;
1247 }
1248 
1249 bool EvoMainLink::retrieveRingBuffer(NvU8 dpRingBuffertype, NvU32 numRecords)
1250 {
1251     return false;
1252 }
1253 
1254 // Return the current mux state. Returns false if device is not mux capable
1255 bool EvoMainLink::getDynamicMuxState(NvU32 *muxState)
1256 {
1257     bool bIsMuxCapable = false;
1258     NvU32 ret = 0;
1259     NV0073_CTRL_CMD_DFP_GET_DISP_MUX_STATUS_PARAMS muxStatusParams;
1260 
1261     if (!muxState)
1262         return false;
1263 
1264     *muxState = 0;
1265 
1266     if (!isDynamicMuxCapable())
1267         return false;
1268 
1269     dpMemZero(&muxStatusParams, sizeof(muxStatusParams));
1270     muxStatusParams.subDeviceInstance = subdeviceIndex;
1271     muxStatusParams.displayId = displayId;
1272     muxStatusParams.muxStatus = 0;
1273 
1274     ret = provider->rmControl0073(NV0073_CTRL_CMD_DFP_GET_DISP_MUX_STATUS,
1275                                   &muxStatusParams, sizeof(muxStatusParams));
1276     if (ret == NV_OK &&
1277         DRF_VAL(0073, _CTRL_DFP_DISP_MUX, _STATE, muxStatusParams.muxStatus) != NV0073_CTRL_DFP_DISP_MUX_STATE_INVALID)
1278     {
1279         bIsMuxCapable = true;
1280         *muxState = muxStatusParams.muxStatus;
1281     }
1282 
1283     return bIsMuxCapable;
1284 }
1285 
1286 bool EvoMainLink::aquireSema()
1287 {
1288     NV0073_CTRL_DP_AUXCH_SET_SEMA_PARAMS params;
1289 
1290     dpMemZero(&params, sizeof(params));
1291     params.subDeviceInstance       = subdeviceIndex;
1292     params.displayId               = displayId;
1293     params.owner                   = NV0073_CTRL_DP_AUXCH_SET_SEMA_OWNER_RM;
1294 
1295     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_DP_AUXCH_SET_SEMA, &params, sizeof(params));
1296 
1297     return code == NVOS_STATUS_SUCCESS;
1298 }
1299 
1300 void EvoMainLink::releaseSema()
1301 {
1302     NV0073_CTRL_DP_AUXCH_SET_SEMA_PARAMS params;
1303 
1304     dpMemZero(&params, sizeof(params));
1305     params.subDeviceInstance       = subdeviceIndex;
1306     params.displayId               = displayId;
1307     params.owner                   = NV0073_CTRL_DP_AUXCH_SET_SEMA_OWNER_RELEASE;
1308 
1309     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_DP_AUXCH_SET_SEMA, &params, sizeof(params));
1310 
1311     DP_USED(code);
1312     DP_ASSERT(code == NVOS_STATUS_SUCCESS);
1313 }
1314 
1315 void EvoMainLink::configurePowerState(bool bPowerUp)
1316 {
1317     NV0073_CTRL_DP_MAIN_LINK_CTRL_PARAMS params;
1318 
1319     dpMemZero(&params, sizeof(params));
1320     params.subDeviceInstance     = subdeviceIndex;
1321     params.displayId             = displayId;
1322     params.ctrl                  = bPowerUp ? NV0073_CTRL_DP_MAIN_LINK_CTRL_POWER_STATE_POWERUP :
1323                                               NV0073_CTRL_DP_MAIN_LINK_CTRL_POWER_STATE_POWERDOWN;
1324 
1325     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_DP_MAIN_LINK_CTRL, &params, sizeof(params));
1326 
1327     DP_ASSERT(code == NVOS_STATUS_SUCCESS);
1328 }
1329 
1330 void EvoMainLink::getLinkConfig(unsigned &laneCount, NvU64 & linkRate)
1331 {
1332     NV0073_CTRL_DP_GET_LINK_CONFIG_PARAMS params;
1333     dpMemZero(&params, sizeof(params));
1334 
1335     params.subDeviceInstance = subdeviceIndex;
1336     params.displayId = displayId;
1337 
1338     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_DP_GET_LINK_CONFIG, &params, sizeof(params));
1339 
1340     if (code == NVOS_STATUS_SUCCESS)
1341     {
1342         laneCount = params.laneCount;
1343 
1344         if (params.linkBW != 0)
1345         {
1346             // BUG: Beware, turbo mode need to be taken into account
1347             linkRate = ((NvU64)params.linkBW) * DP_LINK_BW_FREQ_MULTI_MBPS;
1348         }
1349         else
1350         {
1351             // No link rate available.
1352             linkRate = 0;
1353         }
1354     }
1355     else
1356     {
1357         laneCount = 0;
1358         linkRate = 0;
1359     }
1360 }
1361 
1362 bool EvoMainLink::getMaxLinkConfigFromUefi(NvU8 &linkRate, NvU8 &laneCount)
1363 {
1364     if (provider->getMaxLinkConfigFromUefi(linkRate, laneCount))
1365     {
1366         if (IS_VALID_LANECOUNT(laneCount) && IS_VALID_LINKBW(linkRate))
1367         {
1368             return true;
1369         }
1370     }
1371     return false;
1372 }
1373 
1374 bool EvoMainLink::queryAndUpdateDfpParams()
1375 {
1376     NvU32 dfpFlags;
1377     dpMemZero(&dfpParams, sizeof(dfpParams));
1378     dfpParams.subDeviceInstance = subdeviceIndex;
1379     dfpParams.displayId = displayId;
1380 
1381     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_DFP_GET_INFO, &dfpParams, sizeof(dfpParams));
1382 
1383     if (code != NVOS_STATUS_SUCCESS)
1384     {
1385         DP_ASSERT(0 && "Unable to query DFP params.");
1386         return false;
1387     }
1388 
1389     dfpFlags = dfpParams.flags;
1390     _isEDP = DRF_VAL(0073, _CTRL_DFP_FLAGS, _EMBEDDED_DISPLAYPORT, dfpFlags) ==
1391                      NV0073_CTRL_DFP_FLAGS_EMBEDDED_DISPLAYPORT_TRUE;
1392 
1393     if (_isLTPhyRepeaterSupported)
1394     {
1395         _rmPhyRepeaterCount = DRF_VAL(0073_CTRL_DFP, _FLAGS,
1396                                       _DP_PHY_REPEATER_COUNT, dfpFlags);
1397     }
1398 
1399     _needForceRmEdid = DRF_VAL(0073, _CTRL_DFP_FLAGS, _DP_FORCE_RM_EDID ,dfpFlags) ==
1400                                NV0073_CTRL_DFP_FLAGS_DP_FORCE_RM_EDID_TRUE;
1401 
1402     _isPC2Disabled   = DRF_VAL(0073, _CTRL_DFP_FLAGS, _DP_POST_CURSOR2_DISABLED, dfpFlags) ==
1403                                NV0073_CTRL_DFP_FLAGS_DP_POST_CURSOR2_DISABLED_TRUE;
1404 
1405 
1406     switch(DRF_VAL(0073, _CTRL_DFP_FLAGS, _DP_LINK_BW, dfpFlags))
1407     {
1408         default:
1409             DP_ASSERT(0 && "maxLinkRate is set improperly in dfp object.");
1410             // intentionally fall-thru.
1411         case NV0073_CTRL_DFP_FLAGS_DP_LINK_BW_1_62GBPS:
1412             _maxLinkRateSupportedDfp = RBR;
1413             break;
1414         case NV0073_CTRL_DFP_FLAGS_DP_LINK_BW_2_70GBPS:
1415             _maxLinkRateSupportedDfp = HBR;
1416             break;
1417         case NV0073_CTRL_DFP_FLAGS_DP_LINK_BW_5_40GBPS:
1418             _maxLinkRateSupportedDfp = HBR2;
1419             break;
1420         case NV0073_CTRL_DFP_FLAGS_DP_LINK_BW_8_10GBPS:
1421             _maxLinkRateSupportedDfp = HBR3;
1422             break;
1423     }
1424 
1425 
1426     _isDynamicMuxCapable = FLD_TEST_DRF(0073, _CTRL_DFP_FLAGS, _DYNAMIC_MUX_CAPABLE, _TRUE, dfpFlags);
1427 
1428     return true;
1429 }
1430 
1431 bool EvoMainLink::fetchEdidByRmCtrl(NvU8* edidBuffer, NvU32 bufferSize)
1432 {
1433     NV0073_CTRL_SPECIFIC_GET_EDID_V2_PARAMS    *pEdidParams;
1434     pEdidParams = (NV0073_CTRL_SPECIFIC_GET_EDID_V2_PARAMS*) dpMalloc(sizeof(*pEdidParams));
1435 
1436     if (pEdidParams == NULL) {
1437         return false;
1438     }
1439 
1440     dpMemZero(pEdidParams, sizeof(*pEdidParams));
1441     pEdidParams->subDeviceInstance = subdeviceIndex;
1442     pEdidParams->displayId = displayId;
1443     pEdidParams->flags = 0;       // use default settings.
1444 
1445     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_SPECIFIC_GET_EDID_V2, pEdidParams, sizeof(*pEdidParams));
1446 
1447     if (code == NVOS_STATUS_SUCCESS)
1448     {
1449         // Silently dropping part of a too-large output buffer matches the
1450         // behavior of the "V1" of this control.
1451         // But it may make sense to revisit this behavior now that it's under
1452         // control of this client.
1453         NvU32 copySize = NV_MIN(pEdidParams->bufferSize, bufferSize);
1454         dpMemCopy(edidBuffer, pEdidParams->edidBuffer, copySize);
1455     } else {
1456         DP_ASSERT(0 && "Unable to read EDID.");
1457     }
1458 
1459     dpFree(pEdidParams);
1460     return code == NVOS_STATUS_SUCCESS;
1461 }
1462 
1463 bool EvoMainLink::applyEdidOverrideByRmCtrl(NvU8* edidBuffer, NvU32 bufferSize)
1464 {
1465     NV0073_CTRL_SPECIFIC_APPLY_EDID_OVERRIDE_V2_PARAMS *pEdidOverrideParams =
1466         (NV0073_CTRL_SPECIFIC_APPLY_EDID_OVERRIDE_V2_PARAMS *)
1467             dpMalloc(sizeof(*pEdidOverrideParams));
1468 
1469     if (pEdidOverrideParams == NULL) {
1470         return false;
1471     }
1472 
1473     dpMemZero(pEdidOverrideParams, sizeof(*pEdidOverrideParams));
1474     pEdidOverrideParams->subDeviceInstance = subdeviceIndex;
1475     pEdidOverrideParams->displayId = displayId;
1476     if (bufferSize > sizeof(pEdidOverrideParams->edidBuffer)) {
1477         DP_ASSERT(0 && "EDID override too large for edidBuffer");
1478         dpFree(pEdidOverrideParams);
1479         return false;
1480     }
1481     pEdidOverrideParams->bufferSize = bufferSize;
1482     dpMemCopy(&pEdidOverrideParams->edidBuffer, edidBuffer, bufferSize);
1483 
1484     NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_SPECIFIC_APPLY_EDID_OVERRIDE_V2,
1485                                          pEdidOverrideParams,
1486                                          sizeof(*pEdidOverrideParams));
1487     if (code != NVOS_STATUS_SUCCESS)
1488     {
1489         DP_ASSERT(0 && "Unable to apply EDID override.");
1490         dpFree(pEdidOverrideParams);
1491         return false;
1492     }
1493 
1494     DP_ASSERT(pEdidOverrideParams->bufferSize == bufferSize);
1495     dpMemCopy(edidBuffer, &pEdidOverrideParams->edidBuffer, bufferSize);
1496 
1497     dpFree(pEdidOverrideParams);
1498 
1499     return true;
1500 
1501 }
1502 
1503 bool EvoMainLink::isEDP()
1504 {
1505     return _isEDP;
1506 }
1507 
1508 bool EvoMainLink::supportMSAOverMST()
1509 {
1510     return _enableMSAOverrideOverMST;
1511 }
1512 
1513 bool EvoMainLink::skipPowerdownEdpPanelWhenHeadDetach()
1514 {
1515     return _skipPowerdownEDPPanelWhenHeadDetach;
1516 }
1517 
1518 bool EvoMainLink::isMSTPCONCapsReadDisabled()
1519 {
1520     return _isMSTPCONCapsReadDisabled;
1521 }
1522 
1523 bool EvoMainLink::isActive()
1524 {
1525     NV0073_CTRL_SYSTEM_GET_ACTIVE_PARAMS params;
1526 
1527     for (int i = 0; i < 32; i++)
1528     {
1529         //
1530         //  Skip floorswept heads
1531         //
1532         if (!(allHeadMask & (1 << i)))
1533         {
1534             continue;
1535         }
1536 
1537         dpMemZero(&params, sizeof params);
1538         params.subDeviceInstance = 0;
1539         params.head = i;
1540 
1541         NvU32 code = provider->rmControl0073(NV0073_CTRL_CMD_SYSTEM_GET_ACTIVE, &params, sizeof(params));
1542 
1543         if (code != NVOS_STATUS_SUCCESS)
1544         {
1545             DP_ASSERT(0 && "We can't get active displays, RM bug!");
1546         }
1547         else if (params.displayId & displayId)
1548         {
1549             return true;
1550         }
1551     }
1552 
1553     return false;
1554 }
1555 
1556 bool EvoMainLink::controlRateGoverning(NvU32 head, bool enable, bool updateNow)
1557 {
1558     NV0073_CTRL_CMD_DP_SET_RATE_GOV_PARAMS params = {0};
1559     params.subDeviceInstance = this->subdeviceIndex;
1560     params.head = head;
1561     params.sorIndex = provider->getSorIndex();
1562 
1563     if (enable)
1564     {
1565         params.flags |= DRF_DEF(0073_CTRL, _CMD_DP_SET_RATE_GOV_FLAGS, _ENABLE_RG, _ON);
1566     }
1567     else
1568     {
1569         params.flags |= DRF_DEF(0073_CTRL, _CMD_DP_SET_RATE_GOV_FLAGS, _ENABLE_RG, _OFF);
1570     }
1571     if (updateNow)
1572     {
1573         params.flags |= DRF_DEF(0073_CTRL, _CMD_DP_SET_RATE_GOV_FLAGS, _TRIGGER_MODE, _IMMEDIATE);
1574     }
1575     else
1576     {
1577         params.flags |= DRF_DEF(0073_CTRL, _CMD_DP_SET_RATE_GOV_FLAGS, _TRIGGER_MODE, _LOADV);
1578     }
1579 
1580     provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_RATE_GOV, &params, sizeof params);
1581 
1582     return true;
1583 }
1584 
1585 bool EvoMainLink::getDpTestPattern(NV0073_CTRL_DP_TESTPATTERN * testPattern)
1586 {
1587     NV0073_CTRL_DP_GET_TESTPATTERN_PARAMS params = {0};
1588 
1589     params.subDeviceInstance = this->subdeviceIndex;
1590     params.displayId = this->displayId;
1591 
1592     if (!(provider->rmControl0073(NV0073_CTRL_CMD_DP_GET_TESTPATTERN, &params, sizeof params)))
1593     {
1594         testPattern->testPattern = params.testPattern.testPattern;
1595         return true;
1596     }
1597     else
1598         return false;
1599 }
1600 
1601 bool EvoMainLink::setDpTestPattern(NV0073_CTRL_DP_TESTPATTERN testPattern, NvU8 laneMask, NV0073_CTRL_DP_CSTM cstm, NvBool bIsHBR2, NvBool bSkipLaneDataOverride)
1602 {
1603     NV0073_CTRL_DP_SET_TESTPATTERN_PARAMS params = {0};
1604 
1605     params.subDeviceInstance = this->subdeviceIndex;
1606     params.displayId = this->displayId;
1607     params.testPattern = testPattern;
1608     params.laneMask = laneMask;
1609     params.cstm = cstm;
1610     params.bIsHBR2 = bIsHBR2;
1611     params.bSkipLaneDataOverride = bSkipLaneDataOverride;
1612 
1613     if (!(provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_TESTPATTERN, &params, sizeof params)))
1614         return true;
1615     else
1616         return false;
1617 }
1618 
1619 bool EvoMainLink::getDpLaneData(NvU32 *numLanes, NvU32 *data)
1620 {
1621     NV0073_CTRL_DP_LANE_DATA_PARAMS params = {0};
1622 
1623     params.subDeviceInstance = this->subdeviceIndex;
1624     params.displayId = this->displayId;
1625 
1626     if (!(provider->rmControl0073(NV0073_CTRL_CMD_DP_GET_LANE_DATA, &params, sizeof params)))
1627     {
1628         *numLanes = params.numLanes;
1629         dpMemCopy(data, params.data, NV0073_CTRL_MAX_LANES*4);
1630         return true;
1631     }
1632     else
1633         return false;
1634 }
1635 
1636 bool EvoMainLink::setDpLaneData(NvU32 numLanes, NvU32 *data)
1637 {
1638     NV0073_CTRL_DP_LANE_DATA_PARAMS params = {0};
1639 
1640     params.subDeviceInstance = this->subdeviceIndex;
1641     params.displayId = this->displayId;
1642     params.numLanes = numLanes;
1643     dpMemCopy(params.data, data, NV0073_CTRL_MAX_LANES*4);
1644 
1645     if (!(provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_LANE_DATA, &params, sizeof params)))
1646         return true;
1647     else
1648         return false;
1649 }
1650 
1651 NvU32 EvoMainLink::monitorDenylistInfo(NvU32 ManufacturerID, NvU32 ProductID, DpMonitorDenylistData *pDenylistData)
1652 {
1653     return provider->monitorDenylistInfo(ManufacturerID, ProductID, pDenylistData);
1654 }
1655 bool EvoMainLink::rmUpdateDynamicDfpCache(NvU32 headIndex, RmDfpCache* dfpCache, NvBool bResetDfp)
1656 {
1657     NV0073_CTRL_DFP_UPDATE_DYNAMIC_DFP_CACHE_PARAMS params = {0};
1658     params.headIndex = headIndex;
1659     params.bcaps = dfpCache->bcaps;
1660     for (unsigned i=0; i<5; i++)
1661         params.bksv[i] = dfpCache->bksv[i];
1662 
1663     params.bHdcpCapable = dfpCache->hdcpCapable;
1664     params.subDeviceInstance = subdeviceIndex;
1665     params.updateMask = dfpCache->updMask;
1666     if (bResetDfp)
1667         params.bResetDfp = NV_TRUE;
1668 
1669     if (!(provider->rmControl0073(NV0073_CTRL_CMD_DFP_UPDATE_DYNAMIC_DFP_CACHE, &params, sizeof params)))
1670         return true;
1671     else
1672         return false;
1673 }
1674 
1675 NvU32 EvoMainLink::allocDisplayId()
1676 {
1677     NV0073_CTRL_CMD_DP_TOPOLOGY_ALLOCATE_DISPLAYID_PARAMS params = {0};
1678 
1679     params.subDeviceInstance = subdeviceIndex;
1680     params.displayId = displayId;
1681 
1682     NvU32 ret = provider->rmControl0073(NV0073_CTRL_CMD_DP_TOPOLOGY_ALLOCATE_DISPLAYID, &params, sizeof(params));
1683     if (ret == NVOS_STATUS_SUCCESS)
1684     {
1685         return params.displayIdAssigned;
1686     }
1687 
1688     return 0;
1689 }
1690 
1691 bool EvoMainLink::freeDisplayId(NvU32 displayId)
1692 {
1693     NV0073_CTRL_CMD_DP_TOPOLOGY_FREE_DISPLAYID_PARAMS params = {0};
1694 
1695     params.subDeviceInstance = subdeviceIndex;
1696     params.displayId = displayId;
1697 
1698     NvU32 ret = provider->rmControl0073(NV0073_CTRL_CMD_DP_TOPOLOGY_FREE_DISPLAYID, &params, sizeof(params));
1699     return ret == NVOS_STATUS_SUCCESS;
1700 }
1701 
1702 void EvoMainLink::configureTriggerSelect(NvU32 head, DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamIdentifier)
1703 {
1704     NV0073_CTRL_CMD_DP_SET_TRIGGER_SELECT_PARAMS params = {0};
1705     params.head = head;
1706     params.subDeviceInstance = subdeviceIndex;
1707     params.sorIndex = provider->getSorIndex();
1708     params.singleHeadMSTPipeline = streamIdentifier;
1709     provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_TRIGGER_SELECT, &params, sizeof params);
1710 }
1711 
1712 void EvoMainLink::configureTriggerAll(NvU32 head, bool enable)
1713 {
1714     NV0073_CTRL_CMD_DP_SET_TRIGGER_ALL_PARAMS params = {0};
1715     params.head = head;
1716     params.subDeviceInstance = subdeviceIndex;
1717     params.enable = enable;
1718     provider->rmControl0073(NV0073_CTRL_CMD_DP_SET_TRIGGER_ALL, &params, sizeof params);
1719 }
1720 
1721 MainLink * DisplayPort::MakeEvoMainLink(EvoInterface * provider, Timer * timer)
1722 {
1723     return new EvoMainLink(provider, timer);
1724 }
1725 
1726 AuxBus   * DisplayPort::MakeEvoAuxBus(EvoInterface * provider, Timer * timer)
1727 {
1728     return new EvoAuxBus(provider, timer);
1729 }
1730 
1731 bool EvoMainLink::dscCrcTransaction(NvBool bEnable, gpuDscCrc *data, NvU16 *headIndex)
1732 {
1733     NV0073_CTRL_DFP_DSC_CRC_CONTROL_PARAMS params;
1734     NvU32 code;
1735 
1736     dpMemZero(&params, sizeof(params));
1737     params.bEnable                 = bEnable ? NV_TRUE : NV_FALSE;
1738     params.subDeviceInstance       = subdeviceIndex;
1739     params.headIndex               = *headIndex;
1740 
1741     // see if setup or querying needs to be specified
1742     if (data == NULL)
1743     {
1744         params.cmd = DRF_DEF(0073_CTRL, _DP_CRC_CONTROL, _CMD, _SETUP);
1745     }
1746     else
1747     {
1748         params.cmd = DRF_DEF(0073_CTRL, _DP_CRC_CONTROL, _CMD, _QUERY);
1749     }
1750 
1751     // GPU part of the call
1752     code = provider->rmControl0073(NV0073_CTRL_CMD_DFP_DSC_CRC_CONTROL, &params, sizeof(params));
1753     if (code != NVOS_STATUS_SUCCESS)
1754     {
1755         DP_LOG(("DP> Crc control failed."));
1756         return false;
1757     }
1758 
1759     // if the command is setup, return immediately
1760     if (data != NULL)
1761     {
1762         data->gpuCrc0 = params.gpuCrc0;
1763         data->gpuCrc1 = params.gpuCrc1;
1764         data->gpuCrc2 = params.gpuCrc2;
1765     }
1766 
1767     return true;
1768 }
1769 
1770 //
1771 // @brief This is to request RM to setup/reset link rate table, and save valid
1772 //        link rates for use.
1773 //
1774 // @param pLinkRateTable    Pointer to link rate table to configure
1775 // @param pLinkRates        Pointer to LinkRates to keep valid link rates
1776 // @return
1777 //   true                   Link rate table configured with at least one valid link rate
1778 //   false                  Otherwise
1779 //
1780 bool EvoMainLink::configureLinkRateTable
1781 (
1782     const NvU16     *pLinkRateTable,
1783     LinkRates       *pLinkRates
1784 )
1785 {
1786     NV0073_CTRL_CMD_DP_CONFIG_INDEXED_LINK_RATES_PARAMS params;
1787     dpMemZero(&params, sizeof(params));
1788 
1789     params.subDeviceInstance = subdeviceIndex;
1790     params.displayId = displayId;
1791 
1792     // Setup provided link rate table, otherwise it will be reset
1793     if (pLinkRateTable)
1794     {
1795         for (NvU32 i = 0; i < NV0073_CTRL_DP_MAX_INDEXED_LINK_RATES; i++)
1796         {
1797             params.linkRateTbl[i] = pLinkRateTable[i];
1798         }
1799     }
1800 
1801     NvU32 code = provider->rmControl0073(
1802                 NV0073_CTRL_CMD_DP_CONFIG_INDEXED_LINK_RATES,
1803                 &params, sizeof(params));
1804 
1805     if ((pLinkRates != NULL ) && (code == NVOS_STATUS_SUCCESS) &&
1806         (params.linkBwCount <= NV0073_CTRL_DP_MAX_INDEXED_LINK_RATES))
1807     {
1808         pLinkRates->clear();
1809         for (int i = 0; i < params.linkBwCount; i++)
1810         {
1811             switch (params.linkBwTbl[i])
1812             {
1813                 case linkBW_1_62Gbps:
1814                 case linkBW_2_16Gbps:
1815                 case linkBW_2_43Gbps:
1816                 case linkBW_2_70Gbps:
1817                 case linkBW_3_24Gbps:
1818                 case linkBW_4_32Gbps:
1819                 case linkBW_5_40Gbps:
1820                 case linkBW_8_10Gbps:
1821                     pLinkRates->import((NvU8)params.linkBwTbl[i]);
1822                     break;
1823                 default:
1824                     DP_LOG(("DP_EVO> %s: Unsupported link rate received",
1825                            __FUNCTION__));
1826                     DP_ASSERT(0);
1827                     break;
1828             }
1829         }
1830         return true;
1831     }
1832     return false;
1833 }
1834 
1835 //
1836 // @brief This is to request RM to enable/disable Fec
1837 //
1838 // @param enableFec         Indicates if enable/disable is requested
1839 // @return
1840 //   true                   If FEC was configured successfully
1841 //   false                  Otherwise
1842 //
1843 bool EvoMainLink::configureFec
1844 (
1845     const bool bEnableFec
1846 )
1847 {
1848     NV0073_CTRL_CMD_DP_CONFIGURE_FEC_PARAMS params;
1849     dpMemZero(&params, sizeof(params));
1850 
1851     params.subDeviceInstance = subdeviceIndex;
1852     params.displayId = displayId;
1853     params.bEnableFec = bEnableFec;
1854 
1855     NvU32 code = provider->rmControl0073(
1856                 NV0073_CTRL_CMD_DP_CONFIGURE_FEC,
1857                 &params, sizeof(params));
1858 
1859     if (code == NVOS_STATUS_SUCCESS)
1860     {
1861         return true;
1862     }
1863 
1864     return false;
1865 }
1866