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