1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2007 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 /*
25  * This source file contains codes for enabling HDMI audio.
26  */
27 
28 
29 #include "nvkms-dpy.h"
30 #include "nvkms-hdmi.h"
31 #include "nvkms-evo.h"
32 #include "nvkms-modepool.h"
33 #include "nvkms-rmapi.h"
34 #include "nvkms-utils.h"
35 #include "nvkms-vrr.h"
36 #include "dp/nvdp-connector.h"
37 
38 #include "hdmi_spec.h"
39 #include "nvos.h"
40 
41 #include <ctrl/ctrl0073/ctrl0073dfp.h> // NV0073_CTRL_CMD_DFP_SET_ELD_AUDIO_CAPS
42 #include <ctrl/ctrl0073/ctrl0073dp.h> // NV0073_CTRL_CMD_DP_SET_AUDIO_MUTESTREAM
43 #include <ctrl/ctrl0073/ctrl0073specific.h> // NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS
44 #include <ctrl/ctrl2080/ctrl2080unix.h> // NV2080_CTRL_OS_UNIX_AUDIO_DYNAMIC_POWER
45 
46 #include <hdmipacket/nvhdmipkt.h>
47 
48 #define CAP_HDMI_SUPPORT_GPU             0x00000001
49 #define CAP_HDMI_SUPPORT_MONITOR         0x00000002
50 
51 static inline const NVT_EDID_CEA861_INFO *GetExt861(const NVParsedEdidEvoRec *pParsedEdid,
52                                                     int extIndex)
53 {
54     if (!pParsedEdid->valid || extIndex > 1) {
55         return NULL;
56     }
57 
58     return (extIndex == 0) ? &pParsedEdid->info.ext861 :
59                              &pParsedEdid->info.ext861_2;
60 }
61 
62 /*
63  * CalculateVideoInfoFrameColorFormat() - calculate colorspace,
64  * colorimetry and colorrange for video infoframe.
65  */
66 static void CalculateVideoInfoFrameColorFormat(
67     const NVAttributesSetEvoRec *pAttributesSet,
68     enum NvKmsOutputTf tf,
69     const NvU32 hdTimings,
70     NVT_VIDEO_INFOFRAME_CTRL *pCtrl)
71 {
72     /*
73      * If NVKMS_OUTPUT_TF_PQ is enabled, we expect the colorSpace is RGB.  This
74      * is enforced when the colorSpace is selected.
75      */
76     nvAssert((tf != NVKMS_OUTPUT_TF_PQ) ||
77              (pAttributesSet->colorSpace ==
78                 NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB));
79 
80     // sets video infoframe colorspace (RGB/YUV).
81     switch (pAttributesSet->colorSpace) {
82     case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB:
83         pCtrl->color_space = NVT_VIDEO_INFOFRAME_BYTE1_Y1Y0_RGB;
84         break;
85     case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422:
86         pCtrl->color_space = NVT_VIDEO_INFOFRAME_BYTE1_Y1Y0_YCbCr422;
87         break;
88     case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr444:
89         pCtrl->color_space = NVT_VIDEO_INFOFRAME_BYTE1_Y1Y0_YCbCr444;
90         break;
91     case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420:
92         pCtrl->color_space = NVT_VIDEO_INFOFRAME_BYTE1_Y1Y0_YCbCr420;
93         break;
94     default:
95         nvAssert(!"Invalid colorSpace value");
96         break;
97     }
98 
99     // sets video infoframe colorimetry.
100     switch (pAttributesSet->colorSpace) {
101     case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB:
102         if (tf == NVKMS_OUTPUT_TF_PQ) {
103             pCtrl->colorimetry = NVT_COLORIMETRY_BT2020RGB;
104         } else {
105             pCtrl->colorimetry = NVT_COLORIMETRY_RGB;
106         }
107         break;
108     case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422:
109     case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr444:
110         if (hdTimings) {
111             pCtrl->colorimetry = NVT_COLORIMETRY_YUV_709;
112         } else {
113             pCtrl->colorimetry = NVT_COLORIMETRY_YUV_601;
114         }
115         break;
116     case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420:
117         pCtrl->colorimetry = NVT_COLORIMETRY_YUV_709;
118         break;
119     default:
120         nvAssert(!"Invalid colorSpace value");
121         break;
122     }
123 
124     // sets video infoframe colorrange.
125     switch (pAttributesSet->colorRange) {
126     case NV_KMS_DPY_ATTRIBUTE_COLOR_RANGE_FULL:
127         pCtrl->rgb_quantization_range =
128             NVT_VIDEO_INFOFRAME_BYTE3_Q1Q0_FULL_RANGE;
129         break;
130     case NV_KMS_DPY_ATTRIBUTE_COLOR_RANGE_LIMITED:
131         pCtrl->rgb_quantization_range =
132             NVT_VIDEO_INFOFRAME_BYTE3_Q1Q0_LIMITED_RANGE;
133         break;
134     default:
135         nvAssert(!"Invalid colorRange value");
136         break;
137     }
138 
139     /*
140      * Only limited color range is allowed with YUV444, YUV422 color spaces, or
141      * BT2020 colorimetry.
142      */
143     nvAssert(!(((pCtrl->color_space == NVT_VIDEO_INFOFRAME_BYTE1_Y1Y0_YCbCr422) ||
144                 (pCtrl->color_space == NVT_VIDEO_INFOFRAME_BYTE1_Y1Y0_YCbCr444) ||
145                 (pCtrl->colorimetry == NVT_COLORIMETRY_BT2020RGB)) &&
146                (pCtrl->rgb_quantization_range !=
147                     NVT_VIDEO_INFOFRAME_BYTE3_Q1Q0_LIMITED_RANGE)));
148 }
149 
150 /*
151  * GetHDMISupportCap() - find the HDMI capabilities of
152  * the gpu and the display device.
153  */
154 
155 static NvU32 GetHDMISupportCap(const NVDpyEvoRec *pDpyEvo)
156 {
157     NvU32 hdmiCap = 0;
158     int extIndex;
159 
160     if (pDpyEvo->hdmiCapable) {
161         hdmiCap |= CAP_HDMI_SUPPORT_GPU;
162     }
163 
164     for (extIndex = 0; TRUE; extIndex++) {
165 
166         int vsdbIndex;
167         const NVT_EDID_CEA861_INFO *pExt861 =
168             GetExt861(&pDpyEvo->parsedEdid, extIndex);
169 
170         if (pExt861 == NULL) {
171             break;
172         }
173 
174         if (pExt861->revision <= NVT_CEA861_REV_ORIGINAL) {
175             continue;
176         }
177 
178         for (vsdbIndex = 0; vsdbIndex < pExt861->total_vsdb; vsdbIndex++) {
179             if (pExt861->vsdb[vsdbIndex].ieee_id == NVT_CEA861_HDMI_IEEE_ID) {
180                 hdmiCap |= CAP_HDMI_SUPPORT_MONITOR;
181                 return hdmiCap;
182             }
183         }
184     }
185 
186     return hdmiCap;
187 }
188 
189 /*!
190  * Return whether the GPU supports HDMI and the display is connected
191  * via HDMI.
192  */
193 NvBool nvDpyIsHdmiEvo(const NVDpyEvoRec *pDpyEvo)
194 {
195     NvU32 hdmiCap;
196 
197     hdmiCap = GetHDMISupportCap(pDpyEvo);
198 
199     return ((hdmiCap & CAP_HDMI_SUPPORT_GPU) &&
200             (hdmiCap & CAP_HDMI_SUPPORT_MONITOR));
201 }
202 
203 /*!
204  * Updates the display's HDMI 2.0 capabilities to the RM.
205  */
206 void nvUpdateHdmiCaps(NVDpyEvoPtr pDpyEvo)
207 {
208     NV0073_CTRL_SPECIFIC_SET_HDMI_SINK_CAPS_PARAMS params = { 0 };
209     NVParsedEdidEvoPtr pParsedEdid = &pDpyEvo->parsedEdid;
210     NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
211     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
212     NvU32 ret;
213 
214     if (!pDevEvo->caps.supportsHDMI20 ||
215         nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo)) {
216         return;
217     }
218 
219     params.subDeviceInstance    = pDispEvo->displayOwner;
220     params.displayId            = nvDpyEvoGetConnectorId(pDpyEvo);
221     params.caps = 0;
222 
223     /*
224      * nvUpdateHdmiCaps() gets called on dpy's connect/disconnect events
225      * to set/clear capabilities, clear capabilities if parsed edid
226      * is not valid.
227      */
228     if (pParsedEdid->valid) {
229         const NVT_HDMI_FORUM_INFO *pHdmiInfo = &pParsedEdid->info.hdmiForumInfo;
230         if (pHdmiInfo->scdc_present) {
231             params.caps |= DRF_DEF(0073, _CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS,
232                                    _SCDC_SUPPORTED, _TRUE);
233         }
234 
235         if (pHdmiInfo->max_TMDS_char_rate > 0)  {
236             params.caps |= DRF_DEF(0073, _CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS,
237                                    _GT_340MHZ_CLOCK_SUPPORTED, _TRUE);
238         }
239 
240         if (pHdmiInfo->lte_340Mcsc_scramble) {
241             if (!pHdmiInfo->scdc_present) {
242                 nvEvoLogDisp(pDispEvo,
243                              EVO_LOG_WARN,
244                              "EDID inconsistency: SCDC is not present in EDID, but EDID requests 340Mcsc scrambling.");
245             }
246 
247             params.caps |= DRF_DEF(0073, _CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS,
248                                    _LTE_340MHZ_SCRAMBLING_SUPPORTED, _TRUE);
249         }
250 
251         /* HDMI Fixed-rate link information */
252         if (pDevEvo->hal->caps.supportsHDMIFRL) {
253             nvAssert((pHdmiInfo->max_FRL_Rate &
254                       ~DRF_MASK(NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS_MAX_FRL_RATE_SUPPORTED)) == 0);
255             params.caps |= DRF_NUM(0073_CTRL_CMD_SPECIFIC, _SET_HDMI_SINK_CAPS, _MAX_FRL_RATE_SUPPORTED,
256                                    pHdmiInfo->max_FRL_Rate);
257 
258             if (pHdmiInfo->dsc_1p2) {
259                 nvAssert((pHdmiInfo->dsc_1p2 &
260                           ~DRF_MASK(NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS_DSC_MAX_FRL_RATE_SUPPORTED)) == 0);
261                 params.caps |= DRF_NUM(0073_CTRL_CMD_SPECIFIC, _SET_HDMI_SINK_CAPS, _DSC_MAX_FRL_RATE_SUPPORTED,
262                                        pHdmiInfo->dsc_1p2);
263                 params.caps |= DRF_DEF(0073_CTRL_CMD_SPECIFIC, _SET_HDMI_SINK_CAPS, _DSC_12_SUPPORTED, _TRUE);
264             }
265         }
266     }
267 
268     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
269                          pDevEvo->displayCommonHandle,
270                          NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS,
271                          &params,
272                          sizeof(params));
273 
274     if (ret != NVOS_STATUS_SUCCESS) {
275         nvAssert(!"NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_SINK_CAPS failed");
276     }
277 }
278 
279 /*
280  * HdmiSendEnable() - Used to signal RM to enable various hdmi components
281  * such as audio engine.
282  */
283 
284 static void HdmiSendEnable(NVDpyEvoPtr pDpyEvo, NvBool hdmiEnable)
285 {
286     NV0073_CTRL_SPECIFIC_SET_HDMI_ENABLE_PARAMS params = { 0 };
287     NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
288     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
289     NvU32 ret;
290 
291     params.subDeviceInstance    = pDpyEvo->pDispEvo->displayOwner;
292     params.displayId            = nvDpyEvoGetConnectorId(pDpyEvo);
293     params.enable               = hdmiEnable;
294 
295     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
296                          pDevEvo->displayCommonHandle,
297                          NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_ENABLE,
298                          &params,
299                          sizeof(params));
300 
301     if (ret != NVOS_STATUS_SUCCESS) {
302         nvAssert(!"NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_ENABLE failed");
303     }
304 }
305 
306 /*!
307  * Disable sending the vendor specific infoframe on this display.
308  */
309 static void DisableVendorSpecificInfoFrame(
310     const NVDispEvoRec *pDispEvo,
311     const NvU32 head)
312 {
313     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
314     NV0073_CTRL_SPECIFIC_SET_OD_PACKET_CTRL_PARAMS params = { 0 };
315     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
316     NvU32 ret;
317 
318     params.subDeviceInstance = pDispEvo->displayOwner;
319     params.displayId = pHeadState->activeRmId;
320     params.type = pktType_VendorSpecInfoFrame;
321     params.transmitControl = DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_CTRL_TRANSMIT_CONTROL, _ENABLE, _NO);
322 
323     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
324                          pDevEvo->displayCommonHandle,
325                          NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET_CTRL,
326                          &params,
327                          sizeof(params));
328 
329     if (ret != NVOS_STATUS_SUCCESS) {
330         nvAssert(!"NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET_CTRL failed");
331     }
332 }
333 
334 /*!
335  * Sends General Control Packet to the HDMI sink.
336  */
337 static void SendHdmiGcp(const NVDispEvoRec *pDispEvo,
338                         const NvU32 head, NvBool avmute)
339 {
340     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
341     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
342     NVHDMIPKT_RESULT ret;
343 
344     NvU8 sb0 = avmute ? HDMI_GENCTRL_PACKET_MUTE_ENABLE :
345         HDMI_GENCTRL_PACKET_MUTE_DISABLE;
346 
347     NvU8 sb1 = 0;
348 
349     NvU8 sb2 = NVT_HDMI_RESET_DEFAULT_PIXELPACKING_PHASE;
350 
351     NvU8 gcp[] = {
352         pktType_GeneralControl, 0, 0, sb0, sb1, sb2, 0, 0, 0, 0
353     };
354 
355     ret = NvHdmiPkt_PacketWrite(pDevEvo->hdmiLib.handle,
356                                 pDispEvo->displayOwner,
357                                 pHeadState->activeRmId,
358                                 head,
359                                 NVHDMIPKT_TYPE_GENERAL_CONTROL,
360                                 NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME,
361                                 sizeof(gcp),
362                                 gcp);
363 
364     if (ret != NVHDMIPKT_SUCCESS) {
365         nvAssert(ret == NVHDMIPKT_SUCCESS);
366     }
367 }
368 
369 /*
370  * SendInfoFrame() - Send infoframe to the hardware through the hdmipkt
371  * library.
372  */
373 
374 static void SendInfoFrame(const NVDispEvoRec *pDispEvo,
375                           const NvU32 head,
376                           NVHDMIPKT_TC transmitControl,
377                           NVT_INFOFRAME_HEADER *pInfoFrameHeader,
378                           NvU32 infoframeSize)
379 {
380     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
381     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
382     NVHDMIPKT_TYPE hdmiLibType;
383     NVHDMIPKT_RESULT ret;
384     NvU8 *infoframe = NULL;
385     NvU8 hdmiPacketType, checksum;
386     NvU32 i;
387     NvU8 *pPayload;
388     size_t headerSize;
389     NvBool needChecksum =
390         (transmitControl & DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _CHKSUM_HW, _EN));
391 
392     /*
393      * The 'type' the timing library writes into the NVT_INFOFRAME_HEADER
394      * structure is not the same as the protocol values that hardware expects
395      * to see in the real packet header; those are defined in the
396      * HDMI_PACKET_TYPE enums (hdmi_pktType_*) from hdmi_spec.h; use those
397      * to fill in the first byte of the packet.  It's *also* not the type that
398      * the HDMI library expects to see in its NvHdmiPkt_PacketWrite call; those
399      * are NVHDMIPKT_TYPE_*.  Determine both below.
400      */
401     switch (pInfoFrameHeader->type) {
402         default:
403             nvAssert(0);
404             return;
405         case NVT_INFOFRAME_TYPE_EXTENDED_METADATA_PACKET:
406             hdmiLibType = NVHDMIPKT_TYPE_GENERIC;
407             hdmiPacketType = hdmi_pktType_ExtendedMetadata;
408             break;
409         case NVT_INFOFRAME_TYPE_VIDEO:
410             hdmiLibType = NVHDMIPKT_TYPE_AVI_INFOFRAME;
411             hdmiPacketType = hdmi_pktType_AviInfoFrame;
412             break;
413         case NVT_INFOFRAME_TYPE_VENDOR_SPECIFIC:
414             hdmiLibType = NVHDMIPKT_TYPE_VENDOR_SPECIFIC_INFOFRAME;
415             hdmiPacketType = hdmi_pktType_VendorSpecInfoFrame;
416             break;
417     }
418 
419     /*
420      * These structures are weird. The NVT_VIDEO_INFOFRAME,
421      * NVT_VENDOR_SPECIFIC_INFOFRAME, NVT_EXTENDED_METADATA_PACKET_INFOFRAME,
422      * etc structures are *kind of* what we want to send to the hdmipkt library,
423      * except the type in the header is different, and a single checksum byte
424      * may need to be inserted *between* the header and the payload (requiring
425      * us to allocate a buffer one byte larger).
426      */
427     infoframe = nvAlloc(infoframeSize + (needChecksum ? sizeof(checksum) : 0));
428     if (infoframe == NULL) {
429         return;
430     }
431 
432     /*
433      * The fields and size of NVT_EXTENDED_METADATA_PACKET_INFOFRAME_HEADER
434      * match with those of NVT_INFOFRAME_HEADER at the time of writing, but
435      * nvtiming.h declares them separately. To be safe, special case
436      * NVT_INFOFRAME_TYPE_EXTENDED_METADATA_PACKET.
437      */
438     if (pInfoFrameHeader->type == NVT_INFOFRAME_TYPE_EXTENDED_METADATA_PACKET) {
439         NVT_EXTENDED_METADATA_PACKET_INFOFRAME_HEADER *pExtMetadataHeader =
440             (NVT_EXTENDED_METADATA_PACKET_INFOFRAME_HEADER *) pInfoFrameHeader;
441 
442         pPayload = (NvU8 *)(pExtMetadataHeader + 1);
443         headerSize = sizeof(NVT_EXTENDED_METADATA_PACKET_INFOFRAME_HEADER);
444     } else {
445         pPayload = (NvU8 *)(pInfoFrameHeader + 1);
446         headerSize = sizeof(NVT_INFOFRAME_HEADER);
447     }
448 
449     infoframe[0] = hdmiPacketType;
450     nvkms_memcpy(&infoframe[1], &((NvU8*) pInfoFrameHeader)[1], headerSize - 1);
451 
452     if (needChecksum) {
453         /* PB0: checksum */
454         checksum = 0;
455         infoframe[headerSize] = 0;
456         for (i = 0; i < infoframeSize + sizeof(checksum); i++) {
457             checksum += infoframe[i];
458         }
459         infoframe[headerSize] = ~checksum + 1;
460     }
461 
462     /* copy the payload, starting after the 3-byte header and checksum */
463     nvkms_memcpy(&infoframe[headerSize + (needChecksum ? sizeof(checksum) : 0)],
464                  pPayload, infoframeSize - headerSize /* payload size */);
465 
466     ret = NvHdmiPkt_PacketWrite(pDevEvo->hdmiLib.handle,
467                                 pDispEvo->displayOwner,
468                                 pHeadState->activeRmId,
469                                 head,
470                                 hdmiLibType,
471                                 transmitControl,
472                                 infoframeSize,
473                                 infoframe);
474 
475     if (ret != NVHDMIPKT_SUCCESS) {
476         nvAssert(ret == NVHDMIPKT_SUCCESS);
477     }
478 
479     nvFree(infoframe);
480 }
481 
482 /*
483  * SendVideoInfoFrame() - Construct video infoframe using provided EDID and call
484  * SendInfoFrame() to send it to RM.
485  */
486 static void SendVideoInfoFrame(const NVDispEvoRec *pDispEvo,
487                                const NvU32 head,
488                                const NVAttributesSetEvoRec *pAttributesSet,
489                                const NVDispHeadInfoFrameStateEvoRec *pInfoFrameState,
490                                NVT_EDID_INFO *pEdidInfo)
491 {
492     NvBool hdTimings = pInfoFrameState->hdTimings;
493     NVT_VIDEO_INFOFRAME_CTRL videoCtrl = pInfoFrameState->ctrl;
494     NVT_VIDEO_INFOFRAME VideoInfoFrame;
495     NVT_STATUS status;
496 
497 
498     CalculateVideoInfoFrameColorFormat(pAttributesSet,
499                                        pDispEvo->headState[head].tf,
500                                        hdTimings,
501                                        &videoCtrl);
502 
503     status = NvTiming_ConstructVideoInfoframe(pEdidInfo,
504                                               &videoCtrl,
505                                               NULL, &VideoInfoFrame);
506     if (status != NVT_STATUS_SUCCESS) {
507         nvEvoLogDispDebug(pDispEvo, EVO_LOG_ERROR,
508                           "Error in constructing Video InfoFrame");
509         return;
510     }
511 
512     SendInfoFrame(pDispEvo,
513                   head,
514                   NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME,
515                   (NVT_INFOFRAME_HEADER *) &VideoInfoFrame,
516                   sizeof(VideoInfoFrame));
517 }
518 
519 /*
520  * SendHDMI3DVendorSpecificInfoFrame() - Construct vendor specific infoframe
521  * using provided EDID and call SendInfoFrame() to send it to RM. Currently
522  * hardcoded to send the infoframe necessary for HDMI 3D.
523  */
524 
525 static void
526 SendHDMI3DVendorSpecificInfoFrame(const NVDispEvoRec *pDispEvo,
527                                   const NvU32 head, NVT_EDID_INFO *pEdidInfo)
528 {
529     const NVDispHeadStateEvoRec *pHeadState =
530                                  &pDispEvo->headState[head];
531     NVT_VENDOR_SPECIFIC_INFOFRAME_CTRL vendorCtrl = {
532         .Enable          = 1,
533         .HDMIFormat      = NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_3D,
534         .HDMI_VIC        = NVT_HDMI_VS_BYTE5_HDMI_VIC_NA,
535         .ThreeDStruc     = NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK,
536         .ThreeDDetail    = NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_NA,
537         .MetadataPresent = 0,
538         .MetadataType    = NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_TYPE_NA,
539     };
540     NVT_VENDOR_SPECIFIC_INFOFRAME vendorInfoFrame;
541     NVT_STATUS status;
542 
543     if (!pEdidInfo->HDMI3DSupported) {
544         // Only send the HDMI 3D infoframe if the display supports HDMI 3D
545         return;
546     }
547 
548     // Send the infoframe with HDMI 3D configured if we're setting an HDMI 3D
549     // mode.
550     if (!pHeadState->timings.hdmi3D) {
551         DisableVendorSpecificInfoFrame(pDispEvo, head);
552         return;
553     }
554 
555     status = NvTiming_ConstructVendorSpecificInfoframe(pEdidInfo,
556                                                        &vendorCtrl,
557                                                        &vendorInfoFrame);
558     if (status != NVT_STATUS_SUCCESS) {
559         nvEvoLogDispDebug(pDispEvo, EVO_LOG_ERROR,
560                 "Error in constructing Vendor Specific InfoFrame");
561         return;
562     }
563 
564     SendInfoFrame(pDispEvo,
565                   head,
566                   NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME,
567                   &vendorInfoFrame.Header,
568                   sizeof(vendorInfoFrame));
569 }
570 
571 /*
572  * Send video and 3D InfoFrames for HDMI.
573  */
574 void nvUpdateHdmiInfoFrames(const NVDispEvoRec *pDispEvo,
575                             const NvU32 head,
576                             const NVAttributesSetEvoRec *pAttributesSet,
577                             const NVDispHeadInfoFrameStateEvoRec *pInfoFrameState,
578                             NVDpyEvoRec *pDpyEvo)
579 {
580     if (!nvDpyIsHdmiEvo(pDpyEvo)) {
581         return;
582     }
583 
584     if (!pDpyEvo->parsedEdid.valid) {
585         nvEvoLogDispDebug(
586             pDispEvo, EVO_LOG_WARN,
587             "No EDID: cannot construct video/vendor-specific info frame");
588         return;
589     }
590 
591     SendVideoInfoFrame(pDispEvo,
592                        head,
593                        pAttributesSet,
594                        pInfoFrameState,
595                        &pDpyEvo->parsedEdid.info);
596 
597     SendHDMI3DVendorSpecificInfoFrame(pDispEvo,
598                                       head,
599                                       &pDpyEvo->parsedEdid.info);
600 }
601 
602 static void SetDpAudioMute(const NVDispEvoRec *pDispEvo,
603                            const NvU32 displayId, const NvBool mute)
604 {
605     NV0073_CTRL_DP_SET_AUDIO_MUTESTREAM_PARAMS params = { 0 };
606     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
607     NvU32 ret;
608 
609     params.subDeviceInstance = pDispEvo->displayOwner;
610     params.displayId = displayId;
611     params.mute = mute;
612 
613     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
614                          pDevEvo->displayCommonHandle,
615                          NV0073_CTRL_CMD_DP_SET_AUDIO_MUTESTREAM,
616                          &params,
617                          sizeof(params));
618 
619     if (ret != NVOS_STATUS_SUCCESS) {
620         nvEvoLogDispDebug(pDispEvo, EVO_LOG_ERROR, "NvRmControl"
621                           "(NV0073_CTRL_CMD_DP_SET_AUDIO_MUTESTREAM) failed"
622                           "return status = %d...", ret);
623     }
624 }
625 
626 static void SetDpAudioEnable(const NVDispEvoRec *pDispEvo,
627                              const NvU32 head, const NvBool enable)
628 {
629     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
630     const NVConnectorEvoRec *pConnectorEvo = pHeadState->pConnectorEvo;
631     NV0073_CTRL_DFP_SET_AUDIO_ENABLE_PARAMS params = { 0 };
632     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
633     NvU32 ret;
634 
635     /* Mute audio stream before disabling it */
636     if (!enable) {
637         SetDpAudioMute(pDispEvo, pHeadState->activeRmId, TRUE);
638     }
639 
640     params.subDeviceInstance = pDispEvo->displayOwner;
641     params.displayId = pHeadState->activeRmId;
642     params.enable = enable;
643 
644     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
645                          pDevEvo->displayCommonHandle,
646                          NV0073_CTRL_CMD_DFP_SET_AUDIO_ENABLE,
647                          &params,
648                          sizeof(params));
649 
650     if (ret != NVOS_STATUS_SUCCESS) {
651         nvEvoLogDisp(pDispEvo, EVO_LOG_ERROR,
652                      "%s: Failed to %s DisplayPort audio stream-%u",
653                      pConnectorEvo->name,
654                      enable ? "enable" : "disable",
655                      head);
656     }
657 
658     /* Unmute audio stream after enabling it */
659     if (enable) {
660         SetDpAudioMute(pDispEvo, pHeadState->activeRmId, FALSE);
661     }
662 }
663 
664 /*
665  * Uses RM control to mute HDMI audio stream at source side.
666  */
667 static void SetHdmiAudioMute(const NVDispEvoRec *pDispEvo,
668                              const NvU32 head, const NvBool mute)
669 {
670     NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_AUDIO_MUTESTREAM_PARAMS params = { };
671     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
672     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
673     NvU32 ret;
674 
675     params.subDeviceInstance = pDispEvo->displayOwner;
676     params.displayId = pHeadState->activeRmId;
677     params.mute = (mute ? NV0073_CTRL_SPECIFIC_SET_HDMI_AUDIO_MUTESTREAM_TRUE :
678         NV0073_CTRL_SPECIFIC_SET_HDMI_AUDIO_MUTESTREAM_FALSE);
679 
680     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
681                          pDevEvo->displayCommonHandle,
682                          NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_AUDIO_MUTESTREAM,
683                          &params,
684                          sizeof(params));
685 
686     if (ret != NVOS_STATUS_SUCCESS) {
687         nvAssert(!"NV0073_CTRL_CMD_SPECIFIC_SET_HDMI_AUDIO_MUTESTREAM failed");
688     }
689 }
690 
691 static void EnableHdmiAudio(const NVDispEvoRec *pDispEvo,
692                             const NvU32 head, const NvBool enable)
693 {
694     static const NvU8 InfoframeMutePacket[] = {
695         pktType_GeneralControl, 0, 0, HDMI_GENCTRL_PACKET_MUTE_ENABLE, 0, 0, 0, 0,
696         0, 0
697     };
698     static const NvU8 InfoframeUnMutePacket[] = {
699         pktType_GeneralControl, 0, 0, HDMI_GENCTRL_PACKET_MUTE_DISABLE, 0, 0, 0, 0,
700         0, 0
701     };
702     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
703     NV0073_CTRL_SPECIFIC_SET_OD_PACKET_PARAMS params = { 0 };
704     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
705     NvU32 ret;
706 
707     params.subDeviceInstance = pDispEvo->displayOwner;
708     params.displayId = pHeadState->activeRmId;
709     params.transmitControl =
710         DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _ENABLE, _YES) |
711         DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _OTHER_FRAME, _DISABLE) |
712         DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _SINGLE_FRAME, _DISABLE) |
713         DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _ON_HBLANK, _DISABLE) |
714         DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _VIDEO_FMT, _SW_CONTROLLED) |
715         DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _RESERVED_LEGACY_MODE, _NO);
716 
717     params.packetSize = sizeof(InfoframeMutePacket);
718 
719     nvAssert(sizeof(InfoframeMutePacket) == sizeof(InfoframeUnMutePacket));
720 
721     nvkms_memcpy(params.aPacket,
722                  enable ? InfoframeUnMutePacket : InfoframeMutePacket,
723                  params.packetSize);
724 
725     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
726                          pDevEvo->displayCommonHandle,
727                          NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET,
728                          &params,
729                          sizeof(params));
730 
731     if (ret != NVOS_STATUS_SUCCESS) {
732         nvAssert(!"NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET failed");
733     }
734 }
735 
736 static const NVT_EDID_CEA861_INFO *GetMaxSampleRateExtBlock(
737     const NVParsedEdidEvoRec *pParsedEdid,
738     NvU32 *pMaxFreqSupported)
739 {
740     const NVT_EDID_CEA861_INFO *pExt861 = NULL;
741     int extIndex;
742     int i;
743 
744    *pMaxFreqSupported = 0;
745 
746     for (extIndex = 0; TRUE; extIndex++) {
747 
748         NvU8 sampleRateMask = 0;
749         const NVT_EDID_CEA861_INFO *pTmpExt861 =
750                                     GetExt861(pParsedEdid, extIndex);
751         NvU32 maxFreqSupported = 0;
752 
753         if (pTmpExt861 == NULL) {
754             break;
755         }
756 
757         if (pTmpExt861->revision == NVT_CEA861_REV_NONE) {
758             continue;
759         }
760 
761         /* loop through all SAD to find out the max supported rate */
762         for (i = 0; i < NVT_CEA861_AUDIO_MAX_DESCRIPTOR; i++) {
763 
764             const NvU8 byte1 = pTmpExt861->audio[i].byte1;
765             const NvU8 byte2 = pTmpExt861->audio[i].byte2;
766 
767             if (byte1 == 0) {
768                 break;
769             }
770 
771             if ((byte2 & NVT_CEA861_AUDIO_SAMPLE_RATE_MASK) > sampleRateMask) {
772                 sampleRateMask = byte2 & NVT_CEA861_AUDIO_SAMPLE_RATE_MASK;
773             }
774         }
775 
776         if (sampleRateMask != 0) {
777             /* get the highest bit index */
778             for (i = 7; i >= 1; i--) {
779                 if ((1<<(i-1)) & sampleRateMask) {
780                     maxFreqSupported = i;
781                     break;
782                 }
783             }
784         } else if (pTmpExt861->basic_caps & NVT_CEA861_CAP_BASIC_AUDIO) {
785             /*
786              * no short audio descriptor found, try the basic cap
787              * Uncompressed, two channel, digital audio. Exact parameters are
788              * determined by the interface specification used with CEA-861-D
789              * (e.g., 2 channel IEC 60958 LPCM, 32, 44.1, and 48 kHz
790              * sampling rates, 16 bits/sample).
791              */
792             maxFreqSupported =
793                 NV0073_CTRL_DFP_ELD_AUDIO_CAPS_MAX_FREQ_SUPPORTED_0480KHZ;
794         }
795 
796         if (maxFreqSupported > *pMaxFreqSupported) {
797             *pMaxFreqSupported = maxFreqSupported;
798             pExt861 = pTmpExt861;
799         }
800     }
801 
802     return pExt861;
803 }
804 
805 /*
806  * Search a CEA-861 block for a Vendor Specific Data Block
807  * with an IEEE "HDMI Licensing, LLC" OUI.
808  *
809  * If  found, returns VSDB_DATA * to Vendor Specific Data Block
810  * If !found, returns NULL
811  */
812 static const VSDB_DATA *GetVsdb(const NVT_EDID_CEA861_INFO *pExt861)
813 {
814     const VSDB_DATA *pVsdb = NULL;
815 
816     for (int i = 0; i < pExt861->total_vsdb; i++) {
817         if (pExt861->vsdb[i].ieee_id == NVT_CEA861_HDMI_IEEE_ID) {
818             pVsdb = &pExt861->vsdb[i];
819             break;
820         }
821     }
822     return pVsdb;
823 }
824 
825 static NvBool FillELDBuffer(const NvU32 displayId,
826                             const NvBool isDisplayPort,
827                             const NVParsedEdidEvoRec *pParsedEdid,
828                             NVEldEvoRec *pEld,
829                             NvU32 *pMaxFreqSupported)
830 {
831     const NVT_EDID_CEA861_INFO *pExt861;
832     NvU32 SADCount, monitorNameLen;
833     NvU8 name[NVT_EDID_LDD_PAYLOAD_SIZE + 1];
834     NVT_STATUS status;
835     NvU32 i;
836     NvU8 EldSAI = 0;
837     NvU8 EldAudSynchDelay = 0;
838     const VSDB_DATA *pVsdb;
839 
840     pExt861 = GetMaxSampleRateExtBlock(pParsedEdid, pMaxFreqSupported);
841 
842     if (pExt861 == NULL) {
843         return FALSE;
844     }
845 
846     /* ELD header block: offset 0: ELD_Ver */
847     pEld->buffer[0] = NVT_ELD_VER_2 << 3;
848 
849     /* Baseline block: offset 4: CEA_EDID_Ver */
850     pEld->buffer[4] = pExt861->revision << 5;
851 
852     /* offset 5: SAD_Count */
853     SADCount = 0;
854     while (SADCount < NVT_CEA861_AUDIO_MAX_DESCRIPTOR &&
855            pExt861->audio[SADCount].byte1 != 0) {
856         SADCount++;
857     }
858     pEld->buffer[5] = SADCount << 4;
859 
860     /* offset 5: Conn_Type */
861     if (isDisplayPort) {
862         pEld->buffer[5] |= NVT_ELD_CONN_TYPE_DP << 2;
863     } else {
864         pEld->buffer[5] |= NVT_ELD_CONN_TYPE_HDMI << 2;
865     }
866 
867     /* offset 5 b0: HDCP; always 0 for now */
868 
869     pVsdb = GetVsdb(pExt861);
870     /* offset 5 b1=1 if Supports_AI; always 0 for DP */
871     if ((!isDisplayPort) &&
872         (pVsdb != NULL) &&
873         (pVsdb->vendor_data_size > 2)) {
874         EldSAI = pVsdb->vendor_data[2];
875         EldSAI >>= 7;
876     }
877     pEld->buffer[5] |= EldSAI << 1;
878 
879     /* offset 6: Aud_Synch_delay in units of 2 msec */
880     if ((pVsdb != NULL) &&
881         (pVsdb->vendor_data_size > 6)) {
882         EldAudSynchDelay = pVsdb->vendor_data[6];
883     }
884     pEld->buffer[6] = EldAudSynchDelay;
885 
886     /* offset 7: speaker allocation multiple allocation is not supported in ELD */
887     pEld->buffer[7] = pExt861->speaker[0].byte1;
888 
889     /*
890      * offset 8 ~ 15: port ID; nobody knows what port ID is, so far DD/RM/Audio
891      * all agree to fill it with display Id.
892      */
893     pEld->buffer[8]  = displayId & 0xff;
894     pEld->buffer[9]  = (displayId >> 8) & 0xff;
895     pEld->buffer[10] = (displayId >> 16) & 0xff;
896     pEld->buffer[11] = (displayId >> 24) & 0xff;
897 
898     /* offset 16 ~ 17: manufacturer name */
899     pEld->buffer[16] = pParsedEdid->info.manuf_id & 0xff;
900     pEld->buffer[17] = pParsedEdid->info.manuf_id >> 8;
901     /* offset 18 ~ 19: product code */
902     pEld->buffer[18] = pParsedEdid->info.product_id & 0xff;
903     pEld->buffer[19] = (pParsedEdid->info.product_id >> 8) & 0xff;
904 
905     /*
906      * offset 20 ~ 20 + MNL - 1: monitor name string (MNL - Monitor Name
907      * Length)
908      */
909 
910     monitorNameLen = 0;
911 
912     status = NvTiming_GetProductName(&pParsedEdid->info, name, sizeof(name));
913 
914     if (status == NVT_STATUS_SUCCESS) {
915         /*
916          * NvTiming_GetProductName() returns a nul-terminated string, but the
917          * string in the EDID is terminated with 0x0A and padded with 0x20.
918          * Put back these special characters.
919          */
920         NvBool pastTerminator = FALSE;
921         NvU32 i;
922 
923         for (i = 0; i < NVT_EDID_LDD_PAYLOAD_SIZE; i++) {
924             if (pastTerminator) {
925                 name[i] = 0x20;
926             }
927             if (name[i] == '\0') {
928                 name[i] = 0x0A;
929                 pastTerminator = TRUE;
930             }
931         }
932 
933         monitorNameLen = NVT_EDID_LDD_PAYLOAD_SIZE;
934         pEld->buffer[4] |= NVT_EDID_LDD_PAYLOAD_SIZE;
935         nvkms_memcpy(&pEld->buffer[20], name,
936                      NVT_EDID_LDD_PAYLOAD_SIZE);
937     }
938 
939     /* offset 20 + MNL ~ 20 + MNL + (3 * SAD_Count) - 1 : CEA_SADs */
940     if (SADCount) {
941         const size_t sadSize = SADCount * sizeof(NVT_3BYTES);
942         const size_t bufferSize = sizeof(pEld->buffer) - monitorNameLen - 20;
943         const size_t copySize = NV_MIN(bufferSize, sadSize);
944         nvAssert(copySize == sadSize);
945 
946         nvkms_memcpy(&pEld->buffer[20 + monitorNameLen],
947                      &pExt861->audio[0], copySize);
948     }
949 
950     /*
951      * The reserved section is not used yet.
952      * offset 20 + MNL + (3 * SAD_Count) ~ 4 + Baseline_ELD_Len * 4 - 1;
953      */
954 
955     /* Baseline block size in DWORD */
956     i = (16 + monitorNameLen + SADCount * sizeof(NVT_3BYTES) +
957         sizeof(NvU32) - 1) / sizeof(NvU32);
958     pEld->buffer[2] = (NvU8)i;
959 
960     /* Update the entire ELD space */
961     pEld->size = NV0073_CTRL_DFP_ELD_AUDIO_CAPS_ELD_BUFFER;
962 
963     return TRUE;
964 }
965 
966 void nvHdmiDpConstructHeadAudioState(const NvU32 displayId,
967                                      const NVDpyEvoRec *pDpyEvo,
968                                      NVDispHeadAudioStateEvoRec *pAudioState)
969 {
970     nvkms_memset(pAudioState, 0, sizeof(*pAudioState));
971 
972     /*
973      * CRT and the DSI digital flat panel does not support audio. If (supported
974      * == FALSE) the nvHdmiDpEnableDisableAudio does nothing.
975      */
976     if (pDpyEvo->pConnectorEvo->legacyType !=
977             NV0073_CTRL_SPECIFIC_DISPLAY_TYPE_DFP ||
978         pDpyEvo->pConnectorEvo->signalFormat ==
979             NVKMS_CONNECTOR_SIGNAL_FORMAT_DSI) {
980         return;
981     }
982 
983     /*
984      * The DP/TMDS digital flat panels supports audio, but do not enable audio
985      * on the eDP and DVI displays. Some eDP panels goes blank when audio is
986      * enabled, and DVI monitors do not support audio.
987      *
988      * If (supported == TRUE) and (enabled == FALSE) then
989      * nvHdmiDpEnableDisableAudio() makes sure to keep audio disabled for
990      * a given head.
991      */
992     pAudioState->supported = TRUE;
993 
994     if ((nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo) &&
995             pDpyEvo->internal) ||
996         (!nvDpyIsHdmiEvo(pDpyEvo) &&
997             !nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo))) {
998         return;
999     }
1000 
1001     if (FillELDBuffer(displayId,
1002                       nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo),
1003                       &pDpyEvo->parsedEdid,
1004                       &pAudioState->eld,
1005                       &pAudioState->maxFreqSupported)) {
1006         pAudioState->isAudioOverHdmi = nvDpyIsHdmiEvo(pDpyEvo);
1007         pAudioState->enabled = TRUE;
1008     }
1009 }
1010 
1011 /*
1012  * Returns audio device entry of connector, which should
1013  * be attached to given head. Returns NONE if head is inactive.
1014  *
1015  * Each connector(SOR) supports four audio device entries, from 0 to 3,
1016  * which can drive four independent audio streams. Any head can be attached to
1017  * any audio device entry.
1018  *
1019  * Before audio-over-dp-mst support, by default the 0th device entry was
1020  * used when a given head was driving a DP-SST/HDMI/DVI display. This
1021  * function preserves that behavior. In the case of DP-MST, multiple heads
1022  * are attached to a single connector. In that case this functions returns
1023  * a device entry equal to the given head index.
1024  */
1025 static NvU32 GetAudioDeviceEntry(const NVDispEvoRec *pDispEvo, const NvU32 head)
1026 {
1027     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
1028     const NVConnectorEvoRec *pConnectorEvo =
1029         pHeadState->pConnectorEvo;
1030 
1031     if (pConnectorEvo == NULL) {
1032         return NV0073_CTRL_DFP_ELD_AUDIO_CAPS_DEVICE_ENTRY_NONE;
1033     }
1034 
1035     ct_assert(NV_MAX_AUDIO_DEVICE_ENTRIES == NVKMS_MAX_HEADS_PER_DISP);
1036 
1037     if (nvConnectorUsesDPLib(pConnectorEvo) &&
1038             (nvDPGetActiveLinkMode(pConnectorEvo->pDpLibConnector) ==
1039              NV_DP_LINK_MODE_MST)) {
1040         return NV0073_CTRL_DFP_ELD_AUDIO_CAPS_DEVICE_ENTRY_0 + head;
1041     }
1042 
1043     return NV0073_CTRL_DFP_ELD_AUDIO_CAPS_DEVICE_ENTRY_0;
1044 }
1045 
1046 /*!
1047  * Send EDID-Like-Data (ELD) to RM.
1048  *
1049  * ELD should be updated under the following situations:
1050  *
1051  * 1. Power on reset
1052  * 2. Pre modeset
1053  * 3. HotPlug / Post modeset
1054  *
1055  * Apart from ELD, also update the following control flags:
1056  *
1057  * isPD       - Present Detect, indicates if the monitor is attached
1058  * isELDV     - indicates if the ELD is Valid
1059  *
1060  * The values of iSPD and isELDV should be:
1061  *
1062  * NV_ELD_POWER_ON_RESET : isPD = 0, isELDV = 0
1063  * NV_ELD_PRE_MODESET    : isPD = 1, isELDV = 0
1064  * NV_ELD_POST_MODESET   : isPD = 1, isELDV = 1
1065  *
1066  * The initial ELD case of each audio device entry in hardware is unknown.
1067  * Fortunately, NVConnectorEvoRec::audioDevEldCase[] is zero-initialized,
1068  * which means each audioDevEldCase[] array element will have initial
1069  * value NV_ELD_PRE_MODESET=0.
1070  *
1071  * That ensures that nvRemoveUnusedHdmiDpAudioDevice(), during
1072  * the first modeset, will reset all unused audio device entries to
1073  * NV_ELD_POWER_ON_RESET.
1074  *
1075  * \param[in]  pDispEvo       The disp of the displayId
1076  * \param[in]  displayId      The display device whose ELD should be updated.
1077  *                            This should be NVDispHeadStateEvoRec::activeRmId
1078  *                            in case of NV_ELD_PRE_MODESET and
1079  *                            NV_ELD_POST_MODESET, otherwise it should be
1080  *                            NVConnectorEvoRec::displayId.
1081  * \param[in]  deviceEntry    The device entry of connector.
1082  * \param[in[  isDP           The DisplayPort display device.
1083  * \param[in]  pParsedEdid    The parsed edid from which ELD should be
1084  *                            extracted.
1085  * \param[in]  eldCase        The condition that requires updating the ELD.
1086  */
1087 
1088 static void RmSetELDAudioCaps(
1089     const NVDispEvoRec *pDispEvo,
1090     NVConnectorEvoRec *pConnectorEvo,
1091     const NvU32 displayId,
1092     const NvU32 deviceEntry,
1093     const NvU32 maxFreqSupported, const NVEldEvoRec *pEld,
1094     const NvEldCase eldCase)
1095 {
1096     NV0073_CTRL_DFP_SET_ELD_AUDIO_CAP_PARAMS params = { 0 };
1097     NV2080_CTRL_OS_UNIX_AUDIO_DYNAMIC_POWER_PARAMS audio_power_params = { 0 };
1098     const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
1099     NvBool isPD, isELDV;
1100     NvU32 ret;
1101 
1102     pConnectorEvo->audioDevEldCase[deviceEntry] = eldCase;
1103 
1104     /* setup the ctrl flag */
1105     switch(eldCase) {
1106         case NV_ELD_POWER_ON_RESET :
1107             isPD = isELDV = FALSE;
1108             break;
1109         case NV_ELD_PRE_MODESET :
1110             isPD = TRUE;
1111             isELDV = FALSE;
1112             break;
1113         case NV_ELD_POST_MODESET :
1114             isPD = isELDV = TRUE;
1115             break;
1116         default :
1117             return;
1118     }
1119 
1120     params.subDeviceInstance = pDispEvo->displayOwner;
1121     params.deviceEntry = deviceEntry;
1122     params.displayId = displayId;
1123 
1124     if (isELDV) {
1125         if (pEld->size == 0) {
1126             isPD = isELDV = FALSE;
1127         } else {
1128             ct_assert(sizeof(params.bufferELD) == sizeof(pEld->buffer));
1129 
1130             nvkms_memcpy(params.bufferELD, pEld->buffer, sizeof(pEld->buffer));
1131             params.numELDSize = pEld->size;
1132 
1133             params.maxFreqSupported = maxFreqSupported;
1134         }
1135     } else {
1136         params.numELDSize = 0;
1137     }
1138 
1139     params.ctrl =
1140         DRF_NUM(0073_CTRL, _DFP_ELD_AUDIO_CAPS, _CTRL_PD, isPD)|
1141         DRF_NUM(0073_CTRL, _DFP_ELD_AUDIO_CAPS, _CTRL_ELDV, isELDV);
1142 
1143     /*
1144      * ELD information won't be populated to GPU HDA controller driver if
1145      * HDA controller is in suspended state.
1146      * Issue NV2080_CTRL_CMD_OS_UNIX_AUDIO_DYNAMIC_POWER RM control call for
1147      * bringing the HDA controller in active state before writing ELD. Once ELD
1148      * data is written, then HDA controller can again go into suspended state.
1149      */
1150     audio_power_params.bEnter = FALSE;
1151     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
1152                          pDevEvo->pSubDevices[pDispEvo->displayOwner]->handle,
1153                          NV2080_CTRL_CMD_OS_UNIX_AUDIO_DYNAMIC_POWER,
1154                          &audio_power_params, sizeof(audio_power_params));
1155 
1156     if (ret != NVOS_STATUS_SUCCESS)
1157         nvAssert(!"NV2080_CTRL_CMD_OS_UNIX_AUDIO_DYNAMIC_POWER failed");
1158 
1159     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
1160                          pDevEvo->displayCommonHandle,
1161                          NV0073_CTRL_CMD_DFP_SET_ELD_AUDIO_CAPS,
1162                          &params,
1163                          sizeof(params));
1164 
1165     if (ret != NVOS_STATUS_SUCCESS) {
1166         nvEvoLogDispDebug(pDispEvo, EVO_LOG_ERROR, "NvRmControl"
1167             "(NV0073_CTRL_CMD_DFP_SET_ELD_AUDIO_CAPS) failed"
1168             "return status = %d...", ret);
1169     }
1170 
1171     audio_power_params.bEnter = TRUE;
1172     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
1173                          pDevEvo->pSubDevices[pDispEvo->displayOwner]->handle,
1174                          NV2080_CTRL_CMD_OS_UNIX_AUDIO_DYNAMIC_POWER,
1175                          &audio_power_params, sizeof(audio_power_params));
1176 
1177     if (ret != NVOS_STATUS_SUCCESS)
1178         nvAssert(!"NV2080_CTRL_CMD_OS_UNIX_AUDIO_DYNAMIC_POWER failed");
1179 
1180 }
1181 
1182 void nvHdmiDpEnableDisableAudio(const NVDispEvoRec *pDispEvo,
1183                                 const NvU32 head, const NvBool enable)
1184 {
1185     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
1186     NVConnectorEvoRec *pConnectorEvo = pHeadState->pConnectorEvo;
1187     const NvU32 deviceEntry = GetAudioDeviceEntry(pDispEvo, head);
1188 
1189     /*
1190      * We should only reach this function for active heads, and therefore
1191      * pConnectorEvo and deviceEntry are valid.
1192      */
1193     nvAssert((pHeadState->pConnectorEvo != NULL) &&
1194              (deviceEntry != NV0073_CTRL_DFP_ELD_AUDIO_CAPS_DEVICE_ENTRY_NONE));
1195 
1196     if (!pHeadState->audio.supported) {
1197         return;
1198     }
1199 
1200     if (!pHeadState->audio.enabled) {
1201 
1202         if (enable) {
1203             /* Make sure to remove corresponding audio device */
1204             RmSetELDAudioCaps(pDispEvo,
1205                               pConnectorEvo,
1206                               nvDpyIdToNvU32(pConnectorEvo->displayId),
1207                               deviceEntry,
1208                               0 /* maxFreqSupported */,
1209                               NULL /* pEld */,
1210                               NV_ELD_POWER_ON_RESET);
1211         } else {
1212             /* Do nothing. The audio device is already in the disabled state. */
1213         }
1214 
1215         return;
1216     }
1217 
1218     /* Invalidate ELD buffer before disabling audio */
1219     if (!enable) {
1220         RmSetELDAudioCaps(pDispEvo,
1221                           pConnectorEvo,
1222                           pHeadState->activeRmId,
1223                           deviceEntry,
1224                           0 /* maxFreqSupported */,
1225                           NULL /* pEld */,
1226                           NV_ELD_PRE_MODESET);
1227     }
1228 
1229     if (nvConnectorUsesDPLib(pConnectorEvo)) {
1230         SetDpAudioEnable(pDispEvo, head, enable);
1231     }
1232 
1233     if (pHeadState->audio.isAudioOverHdmi) {
1234         EnableHdmiAudio(pDispEvo, head, enable);
1235         SetHdmiAudioMute(pDispEvo, head, !enable /* mute */);
1236         SendHdmiGcp(pDispEvo, head, !enable /* avmute */);
1237     }
1238 
1239     /* Populate ELD buffer after enabling audio */
1240     if (enable) {
1241         RmSetELDAudioCaps(pDispEvo,
1242                           pConnectorEvo,
1243                           pHeadState->activeRmId,
1244                           deviceEntry,
1245                           pHeadState->audio.maxFreqSupported,
1246                           &pHeadState->audio.eld,
1247                           NV_ELD_POST_MODESET);
1248     }
1249 }
1250 
1251 /*
1252  * Report HDMI capabilities to RM before modeset.
1253  */
1254 void nvDpyUpdateHdmiPreModesetEvo(NVDpyEvoPtr pDpyEvo)
1255 {
1256     if (!nvDpyIsHdmiEvo(pDpyEvo)) {
1257         pDpyEvo->pConnectorEvo->isHdmiEnabled = FALSE;
1258         return;
1259     }
1260 
1261     HdmiSendEnable(pDpyEvo, TRUE);
1262     pDpyEvo->pConnectorEvo->isHdmiEnabled = TRUE;
1263 }
1264 
1265 /*
1266  * Parse HDMI 2.1 VRR capabilities from the EDID and GPU.
1267  */
1268 void nvDpyUpdateHdmiVRRCaps(NVDpyEvoPtr pDpyEvo)
1269 {
1270 }
1271 
1272 void nvRemoveUnusedHdmiDpAudioDevice(const NVDispEvoRec *pDispEvo)
1273 {
1274     NVConnectorEvoRec *pConnectorEvo;
1275     const NvU32 activeSorMask = nvGetActiveSorMask(pDispEvo);
1276 
1277     FOR_ALL_EVO_CONNECTORS(pConnectorEvo, pDispEvo) {
1278         NvU32 deviceEntry;
1279 
1280         // Only connectors with assigned SORs can have audio.
1281         if (pConnectorEvo->or.type != NV0073_CTRL_SPECIFIC_OR_TYPE_SOR ||
1282             pConnectorEvo->or.mask == 0x0) {
1283             continue;
1284         }
1285 
1286         // Check whether an active pConnectorEvo shares an SOR with this one.
1287         //
1288         // This is a workaround for the fact that
1289         // NV0073_CTRL_CMD_DFP_SET_ELD_AUDIO_CAPS takes a displayId rather than
1290         // an SOR index. See bug 1953489.
1291         if (nvIsConnectorActiveEvo(pConnectorEvo) &&
1292             (pConnectorEvo->or.mask & activeSorMask) != 0x0) {
1293             continue;
1294         }
1295 
1296         for (deviceEntry = 0;
1297              deviceEntry < NV_MAX_AUDIO_DEVICE_ENTRIES;
1298              deviceEntry++) {
1299 
1300             /*
1301              * Skip if the audio device is enabled (ELD case is set to
1302              * NV_ELD_POST_MODESET by nvHdmiDpEnableDisableAudio()), or if the
1303              * audio device is already disabled (ELD case is set to
1304              * NV_ELD_POWER_ON_RESET).
1305              */
1306             if ((pConnectorEvo->audioDevEldCase[deviceEntry] ==
1307                         NV_ELD_POST_MODESET) ||
1308                     (pConnectorEvo->audioDevEldCase[deviceEntry] ==
1309                      NV_ELD_POWER_ON_RESET)) {
1310                 continue;
1311             }
1312 
1313             RmSetELDAudioCaps(pDispEvo,
1314                               pConnectorEvo,
1315                               nvDpyIdToNvU32(pConnectorEvo->displayId),
1316                               deviceEntry,
1317                               0 /* maxFreqSupported */,
1318                               NULL /* pEld */,
1319                               NV_ELD_POWER_ON_RESET);
1320         }
1321     }
1322 }
1323 
1324 /*
1325  * Find the name of the given audio format, as described in the
1326  * CEA-861 specification's description of byte 1 in the Audio
1327  * Descriptor Block.  hasSampleSize and hasMaxBitRate (i.e., how to
1328  * interpret byte 3 of the Audio Descriptor Block) are a function of
1329  * audio format, so set them as a side effect of interpreting the
1330  * audio format.
1331  *
1332  * Note the return value is a const char * and should not be freed.
1333  */
1334 static const char *GetCea861AudioFormatInfo(NvU8 format,
1335                                             NvBool *hasSampleSize,
1336                                             NvBool *hasMaxBitRate)
1337 {
1338     static const struct {
1339         NvU8 format;
1340         NvBool hasSampleSize : 1;
1341         NvBool hasMaxBitRate : 1;
1342         const char *name;
1343     } audioFormatTable[] = {
1344         { NVT_CEA861_AUDIO_FORMAT_LINEAR_PCM, TRUE, FALSE,  "PCM"     },
1345         { NVT_CEA861_AUDIO_FORMAT_AC3,        FALSE, TRUE,  "AC-3"    },
1346         { NVT_CEA861_AUDIO_FORMAT_MPEG1,      FALSE, TRUE,  "MPEG-1"  },
1347         { NVT_CEA861_AUDIO_FORMAT_MP3,        FALSE, TRUE,  "MP3"     },
1348         { NVT_CEA861_AUDIO_FORMAT_MPEG2,      FALSE, TRUE,  "MPEG-2"  },
1349         { NVT_CEA861_AUDIO_FORMAT_AAC,        FALSE, TRUE,  "AAC"     },
1350         { NVT_CEA861_AUDIO_FORMAT_DTS,        FALSE, TRUE,  "DTS"     },
1351         { NVT_CEA861_AUDIO_FORMAT_ATRAC,      FALSE, TRUE,  "ATRAC"   },
1352         { NVT_CEA861_AUDIO_FORMAT_ONE_BIT,    FALSE, FALSE, "DSD"     },
1353         { NVT_CEA861_AUDIO_FORMAT_DDP,        FALSE, FALSE, "E-AC-3"  },
1354         { NVT_CEA861_AUDIO_FORMAT_DTS_HD,     FALSE, FALSE, "DTS-HD"  },
1355         { NVT_CEA861_AUDIO_FORMAT_MAT,        FALSE, FALSE, "MLP"     },
1356         { NVT_CEA861_AUDIO_FORMAT_DST,        FALSE, FALSE, "DSP"     },
1357         { NVT_CEA861_AUDIO_FORMAT_WMA_PRO,    FALSE, FALSE, "WMA Pro" },
1358     };
1359 
1360     int i;
1361 
1362     *hasSampleSize = FALSE;
1363     *hasMaxBitRate = FALSE;
1364 
1365     for (i = 0; i < ARRAY_LEN(audioFormatTable); i++) {
1366         if (format != audioFormatTable[i].format) {
1367             continue;
1368         }
1369 
1370         *hasSampleSize = audioFormatTable[i].hasSampleSize;
1371         *hasMaxBitRate = audioFormatTable[i].hasMaxBitRate;
1372 
1373         return audioFormatTable[i].name;
1374     }
1375 
1376     return "";
1377 }
1378 
1379 
1380 /*
1381  * Build a string description of the list of sample Rates, as
1382  * described in the CEA-861 specification's description of byte 2 in
1383  * the Audio Descriptor Block.
1384  *
1385  * Note the return value is a static char * and will be overwritten in
1386  * subsequent calls to this function.
1387  */
1388 static const char *GetCea861AudioSampleRateString(NvU8 sampleRates)
1389 {
1390     static const struct {
1391         NvU8 rate;
1392         const char *name;
1393     } sampleRateTable[] = {
1394         { NVT_CEA861_AUDIO_SAMPLE_RATE_32KHZ, "32KHz"  },
1395         { NVT_CEA861_AUDIO_SAMPLE_RATE_44KHZ, "44KHz"  },
1396         { NVT_CEA861_AUDIO_SAMPLE_RATE_48KHZ, "48KHz"  },
1397         { NVT_CEA861_AUDIO_SAMPLE_RATE_88KHZ, "88KHz"  },
1398         { NVT_CEA861_AUDIO_SAMPLE_RATE_96KHZ, "96KHz"  },
1399         { NVT_CEA861_AUDIO_SAMPLE_RATE_176KHZ,"176KHz" },
1400         { NVT_CEA861_AUDIO_SAMPLE_RATE_192KHZ,"192KHz" },
1401     };
1402 
1403     static char sampleRateString[64];
1404 
1405     NvBool first = TRUE;
1406     int i;
1407     char *s;
1408     int ret, bytesLeft = sizeof(sampleRateString);
1409 
1410     sampleRateString[0] = '\0';
1411     s = sampleRateString;
1412 
1413     for (i = 0; i < ARRAY_LEN(sampleRateTable); i++) {
1414         if (sampleRates & sampleRateTable[i].rate) {
1415             if (first) {
1416                 first = FALSE;
1417             } else {
1418                 ret = nvkms_snprintf(s, bytesLeft, ", ");
1419                 s += ret;
1420                 bytesLeft -= ret;
1421             }
1422             ret = nvkms_snprintf(s, bytesLeft, "%s", sampleRateTable[i].name);
1423             s += ret;
1424             bytesLeft -= ret;
1425         }
1426     }
1427 
1428     nvAssert(bytesLeft >= 0);
1429 
1430     return sampleRateString;
1431 }
1432 
1433 
1434 /*
1435  * Build a string description of the list of sample sizes, as
1436  * described in the CEA-861 specification's description of byte 3 in
1437  * the Audio Descriptor Block.
1438  *
1439  * Note the return value is a static char * and will be overwritten in
1440  * subsequent calls to this function.
1441  */
1442 static const char *GetCea861AudioSampleSizeString(NvU8 sampleSizes)
1443 {
1444     static const struct {
1445         NvU8 bit;
1446         const char *name;
1447     } sampleSizeTable[] = {
1448         { NVT_CEA861_AUDIO_SAMPLE_SIZE_16BIT, "16-bits" },
1449         { NVT_CEA861_AUDIO_SAMPLE_SIZE_20BIT, "20-bits" },
1450         { NVT_CEA861_AUDIO_SAMPLE_SIZE_24BIT, "24-bits" },
1451     };
1452 
1453     static char sampleSizeString[64];
1454 
1455     NvBool first = TRUE;
1456     int i;
1457     char *s;
1458     int ret, bytesLeft = sizeof(sampleSizeString);
1459 
1460     sampleSizeString[0] = '\0';
1461     s = sampleSizeString;
1462 
1463     for (i = 0; i < ARRAY_LEN(sampleSizeTable); i++) {
1464         if (sampleSizes & sampleSizeTable[i].bit) {
1465             if (first) {
1466                 first = FALSE;
1467             } else {
1468                 ret = nvkms_snprintf(s, bytesLeft, ", ");
1469                 s += ret;
1470                 bytesLeft -= ret;
1471             }
1472             ret = nvkms_snprintf(s, bytesLeft, "%s", sampleSizeTable[i].name);
1473             s += ret;
1474             bytesLeft -= ret;
1475         }
1476     }
1477 
1478     nvAssert(bytesLeft >= 0);
1479 
1480     return sampleSizeString;
1481 }
1482 
1483 
1484 /*
1485  * Log the speaker allocation data block, as described in the CEA-861
1486  * specification.
1487  */
1488 static void LogEdidCea861SpeakerAllocationData(NVEvoInfoStringPtr pInfoString,
1489                                                NvU8 speaker)
1490 {
1491     if ((speaker & NVT_CEA861_SPEAKER_ALLOC_MASK) == 0) {
1492         return;
1493     }
1494 
1495     nvEvoLogInfoString(pInfoString,
1496                        "  Speaker Allocation Data    :");
1497 
1498     if (speaker & NVT_CEA861_SPEAKER_ALLOC_FL_FR) {
1499         nvEvoLogInfoString(pInfoString,
1500                            "   Front Left + Front Right");
1501     }
1502     if (speaker & NVT_CEA861_SPEAKER_ALLOC_LFE) {
1503         nvEvoLogInfoString(pInfoString,
1504                            "   Low Frequency Effect");
1505     }
1506     if (speaker & NVT_CEA861_SPEAKER_ALLOC_FC) {
1507         nvEvoLogInfoString(pInfoString,
1508                            "   Front Center");
1509     }
1510     if (speaker & NVT_CEA861_SPEAKER_ALLOC_RL_RR) {
1511         nvEvoLogInfoString(pInfoString,
1512                            "   Rear Left + Rear Right");
1513     }
1514     if (speaker & NVT_CEA861_SPEAKER_ALLOC_RC) {
1515         nvEvoLogInfoString(pInfoString,
1516                            "   Rear Center");
1517     }
1518     if (speaker & NVT_CEA861_SPEAKER_ALLOC_FLC_FRC) {
1519         nvEvoLogInfoString(pInfoString,
1520                            "   Front Left Center + Front Right Center");
1521     }
1522     if (speaker & NVT_CEA861_SPEAKER_ALLOC_RLC_RRC) {
1523         nvEvoLogInfoString(pInfoString,
1524                            "   Rear Left Center + Rear Right Center");
1525     }
1526 }
1527 
1528 
1529 static void LogEdidCea861Info(NVEvoInfoStringPtr pInfoString,
1530                               const NVT_EDID_CEA861_INFO *pExt861)
1531 {
1532     int vsdbIndex;
1533     int audioIndex;
1534 
1535     nvEvoLogInfoString(pInfoString,
1536                        " CEA-861 revision            : %d\n",
1537                        pExt861->revision);
1538 
1539     /*
1540      * IEEE vendor registration IDs are tracked here:
1541      * https://standards.ieee.org/develop/regauth/oui/oui.txt
1542      */
1543     for (vsdbIndex = 0; vsdbIndex < pExt861->total_vsdb; vsdbIndex++) {
1544         const NvU32 ieeeId = pExt861->vsdb[vsdbIndex].ieee_id;
1545         nvEvoLogInfoString(pInfoString,
1546                            "  IEEE Vendor Registration ID: %02x-%02x-%02x",
1547                            (ieeeId >> 16) & 0xFF,
1548                            (ieeeId >> 8) & 0xFF,
1549                            ieeeId & 0xFF);
1550     }
1551 
1552     nvEvoLogInfoString(pInfoString,
1553                        "  Supports YCbCr 4:4:4       : %s",
1554                        (pExt861->basic_caps & NVT_CEA861_CAP_YCbCr_444) ?
1555                        "Yes" : "No");
1556 
1557     nvEvoLogInfoString(pInfoString,
1558                        "  Supports YCbCr 4:2:2       : %s",
1559                        (pExt861->basic_caps & NVT_CEA861_CAP_YCbCr_422) ?
1560                        "Yes" : "No");
1561 
1562     nvEvoLogInfoString(pInfoString,
1563                        "  Supports Basic Audio       : %s",
1564                        (pExt861->basic_caps & NVT_CEA861_CAP_BASIC_AUDIO) ?
1565                        "Yes" : "No");
1566 
1567     for (audioIndex = 0; audioIndex < ARRAY_LEN(pExt861->audio); audioIndex++) {
1568 
1569         NvU32 byte1, byte2, byte3;
1570         NvU8 format;
1571         NvU8 maxChannels;
1572         NvU8 sampleRates;
1573         const char *formatString;
1574         NvBool hasSampleSize;
1575         NvBool hasMaxBitRate;
1576 
1577         byte1 = pExt861->audio[audioIndex].byte1;
1578         byte2 = pExt861->audio[audioIndex].byte2;
1579         byte3 = pExt861->audio[audioIndex].byte3;
1580 
1581         if (byte1 == 0) {
1582             break;
1583         }
1584 
1585         nvEvoLogInfoString(pInfoString,
1586                            "  Audio Descriptor           : %d", audioIndex);
1587 
1588         /*
1589          * byte 1 contains the Audio Format and the maximum number
1590          * of channels
1591          */
1592 
1593         format = ((byte1 & NVT_CEA861_AUDIO_FORMAT_MASK) >>
1594                   NVT_CEA861_AUDIO_FORMAT_SHIFT);
1595 
1596         formatString = GetCea861AudioFormatInfo(format,
1597                                                 &hasSampleSize,
1598                                                 &hasMaxBitRate);
1599 
1600         maxChannels = (byte1 & NVT_CEA861_AUDIO_MAX_CHANNEL_MASK) + 1;
1601 
1602         /* byte 2 contains the sample rates */
1603 
1604         sampleRates = (byte2 & NVT_CEA861_AUDIO_SAMPLE_RATE_MASK);
1605 
1606         /*
1607          * byte 3 varies, depending on Audio Format; interpret
1608          * using hasSampleSize and hasMaxBitRate
1609          */
1610 
1611         nvEvoLogInfoString(pInfoString,
1612                            "   Audio Format              : %s", formatString);
1613         nvEvoLogInfoString(pInfoString,
1614                            "   Maximum Channels          : %d", maxChannels);
1615         nvEvoLogInfoString(pInfoString,
1616                            "   Sample Rates              : %s",
1617                            GetCea861AudioSampleRateString(sampleRates));
1618         if (hasSampleSize) {
1619             nvEvoLogInfoString(pInfoString,
1620                                "   Sample Sizes              : %s",
1621                                GetCea861AudioSampleSizeString(byte3));
1622         }
1623         if (hasMaxBitRate) {
1624             nvEvoLogInfoString(pInfoString,
1625                                "   Maximum Bit Rate          : %d kHz",
1626                                byte3 * 8);
1627         }
1628     }
1629 
1630     LogEdidCea861SpeakerAllocationData(pInfoString, pExt861->speaker[0].byte1);
1631 }
1632 
1633 void nvLogEdidCea861InfoEvo(NVDpyEvoPtr pDpyEvo,
1634                             NVEvoInfoStringPtr pInfoString)
1635 {
1636     int extIndex;
1637 
1638     for (extIndex = 0; TRUE; extIndex++) {
1639         const NVT_EDID_CEA861_INFO *pExt861 =
1640             GetExt861(&pDpyEvo->parsedEdid, extIndex);
1641 
1642         if (pExt861 == NULL) {
1643             break;
1644         }
1645 
1646         if (pExt861->revision == NVT_CEA861_REV_NONE) {
1647             continue;
1648         }
1649 
1650         nvEvoLogInfoString(pInfoString,
1651                            "CEA-861 extension block #    : %d\n", extIndex);
1652 
1653         LogEdidCea861Info(pInfoString, pExt861);
1654     }
1655 }
1656 
1657 /*
1658  * HDMI 2.0 4K@60hz uncompressed RGB 4:4:4 (6G mode) is allowed if:
1659  *
1660  * - The GPU supports it.
1661  * - The EDID and NVT_TIMING indicate the monitor supports it, or
1662  *   this check is overridden.
1663  */
1664 NvBool nvHdmi204k60HzRGB444Allowed(const NVDpyEvoRec *pDpyEvo,
1665                                    const struct NvKmsModeValidationParams *pParams,
1666                                    const NVT_TIMING *pTiming)
1667 {
1668     const NVParsedEdidEvoRec *pParsedEdid = &pDpyEvo->parsedEdid;
1669     const NVDevEvoRec *pDevEvo = pDpyEvo->pDispEvo->pDevEvo;
1670 
1671     const NvBool gpuSupports444 = pDevEvo->caps.supportsHDMI20;
1672 
1673     const NvBool overrideMonitorCheck = ((pParams->overrides &
1674         NVKMS_MODE_VALIDATION_NO_HDMI2_CHECK) != 0);
1675 
1676     const NvBool monitorSupports444 =
1677         (IS_BPC_SUPPORTED_COLORFORMAT(pTiming->etc.rgb444.bpcs) &&
1678          (pParsedEdid->info.hdmiForumInfo.max_TMDS_char_rate > 0));
1679 
1680     nvAssert(pParsedEdid->valid);
1681 
1682     return (gpuSupports444 &&
1683             (overrideMonitorCheck || monitorSupports444));
1684 }
1685 
1686 /*
1687  * Enable or disable HDMI 2.1 VRR infoframes.  The HDMI 2.1 VRR infoframe must
1688  * be enabled before the first extended vblank after enabling VRR, or the
1689  * display will blank.
1690  */
1691 void nvHdmiSetVRR(NVDispEvoPtr pDispEvo, NvU32 head, NvBool enable)
1692 {
1693     NVT_EXTENDED_METADATA_PACKET_INFOFRAME empInfoFrame;
1694     NVT_EXTENDED_METADATA_PACKET_INFOFRAME_CTRL empCtrl;
1695     NVHDMIPKT_TC transmitControl;
1696     NVT_STATUS status;
1697 
1698     nvkms_memset(&empCtrl, NVT_INFOFRAME_CTRL_DONTCARE,
1699                  sizeof(empCtrl));
1700 
1701     empCtrl.EnableVRR = enable;
1702 
1703     status = NvTiming_ConstructExtendedMetadataPacketInfoframe(&empCtrl,
1704                                                                &empInfoFrame);
1705 
1706     if (status != NVT_STATUS_SUCCESS) {
1707         nvEvoLogDispDebug(pDispEvo, EVO_LOG_ERROR,
1708                 "Error in constructing Extended Metadata Packet InfoFrame");
1709         return;
1710     }
1711 
1712     transmitControl =
1713         DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _ENABLE,    _EN)   |
1714         DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _OTHER,     _DIS)  |
1715         DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _CHKSUM_HW, _DIS);
1716 
1717     // Transmit the enable packet every frame, but only transmit the
1718     // disable packet once.
1719     if (enable) {
1720         transmitControl |= DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _SINGLE, _DIS);
1721     } else {
1722         transmitControl |= DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _SINGLE, _EN);
1723     }
1724 
1725     SendInfoFrame(pDispEvo,
1726                   head,
1727                   transmitControl,
1728                   (NVT_INFOFRAME_HEADER *) &empInfoFrame,
1729                   sizeof(empInfoFrame));
1730 }
1731 
1732 /*
1733  * The HDMI library calls this function during initialization to ask the
1734  * implementation to allocate and map a NV*71_DISP_SF_USER object.  The
1735  * appropriate class, mapping size, and subdevice ID are provided.  A handle is
1736  * generated here and passed back to the library; the same handle is provided
1737  * in the symmetric HdmiLibRmFreeMemoryMap() function so we don't have to save
1738  * a copy of it in nvkms's data structures.
1739  */
1740 static NvBool HdmiLibRmGetMemoryMap(
1741     NvHdmiPkt_CBHandle handle,
1742     NvU32 dispSfUserClassId,
1743     NvU32 dispSfUserSize,
1744     NvU32 sd,
1745     NvU32 *pDispSfHandle,
1746     void **pPtr)
1747 {
1748     NVDevEvoRec *pDevEvo = handle;
1749     void *ptr = NULL;
1750     NvU32 ret;
1751     NvU32 dispSfHandle = nvGenerateUnixRmHandle(&pDevEvo->handleAllocator);
1752 
1753     if (dispSfHandle == 0) {
1754         return FALSE;
1755     }
1756 
1757     ret = nvRmApiAlloc(nvEvoGlobal.clientHandle,
1758                        pDevEvo->pSubDevices[sd]->handle,
1759                        dispSfHandle,
1760                        dispSfUserClassId,
1761                        NULL);
1762 
1763     if (ret != NVOS_STATUS_SUCCESS) {
1764         nvFreeUnixRmHandle(&pDevEvo->handleAllocator,
1765                            dispSfHandle);
1766         return FALSE;
1767     }
1768 
1769     ret = nvRmApiMapMemory(nvEvoGlobal.clientHandle,
1770                            pDevEvo->pSubDevices[sd]->handle,
1771                            dispSfHandle,
1772                            0,
1773                            dispSfUserSize,
1774                            &ptr,
1775                            0);
1776     if (ret != NVOS_STATUS_SUCCESS) {
1777         nvRmApiFree(nvEvoGlobal.clientHandle,
1778                     pDevEvo->pSubDevices[sd]->handle,
1779                     dispSfHandle);
1780         nvFreeUnixRmHandle(&pDevEvo->handleAllocator,
1781                            dispSfHandle);
1782         return FALSE;
1783     }
1784 
1785     *pDispSfHandle = dispSfHandle;
1786     *pPtr = ptr;
1787 
1788     return TRUE;
1789 }
1790 
1791 static void HdmiLibRmFreeMemoryMap(
1792     NvHdmiPkt_CBHandle handle,
1793     NvU32 sd,
1794     NvU32 dispSfHandle,
1795     void *ptr)
1796 {
1797     NVDevEvoRec *pDevEvo = handle;
1798     NvU32 ret;
1799 
1800     if (ptr != NULL) {
1801         nvAssert(dispSfHandle != 0);
1802         ret = nvRmApiUnmapMemory(nvEvoGlobal.clientHandle,
1803                                  pDevEvo->pSubDevices[sd]->handle,
1804                                  dispSfHandle,
1805                                  ptr,
1806                                  0);
1807         if (ret != NVOS_STATUS_SUCCESS) {
1808             nvAssert(ret == NVOS_STATUS_SUCCESS);
1809         }
1810     }
1811 
1812     if (dispSfHandle) {
1813         ret = nvRmApiFree(nvEvoGlobal.clientHandle,
1814                           pDevEvo->pSubDevices[sd]->handle,
1815                           dispSfHandle);
1816         if (ret != NVOS_STATUS_SUCCESS) {
1817             nvAssert(ret == NVOS_STATUS_SUCCESS);
1818         }
1819         nvFreeUnixRmHandle(&pDevEvo->handleAllocator,
1820                            dispSfHandle);
1821     }
1822 }
1823 
1824 /* Wrapper around RmControl for 0073 (NV04_DISPLAY_COMMON) object. */
1825 static NvBool HdmiLibRmDispControl(
1826     NvHdmiPkt_CBHandle handle,
1827     NvU32 subDevice,
1828     NvU32 cmd,
1829     void *pParams,
1830     NvU32 paramSize)
1831 {
1832     NVDevEvoRec *pDevEvo = handle;
1833     NvU32 ret;
1834 
1835     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
1836                          pDevEvo->displayCommonHandle,
1837                          cmd,
1838                          pParams,
1839                          paramSize);
1840 
1841     return ret == NVOS_STATUS_SUCCESS;
1842 }
1843 
1844 static void HdmiLibAcquireMutex(
1845     NvHdmiPkt_CBHandle handle)
1846 {
1847     /* The HDMI library only executes when nvkms calls it, and nvkms will only
1848      * call it while holding the nvkms lock.  So there is no concurrency to
1849      * protect against with this mutex. */
1850 }
1851 
1852 static void HdmiLibReleaseMutex(
1853     NvHdmiPkt_CBHandle handle)
1854 {
1855 }
1856 
1857 static void *HdmiLibMalloc(NvHdmiPkt_CBHandle handle, NvLength len)
1858 {
1859     return nvAlloc(len);
1860 }
1861 
1862 static void HdmiLibFree(NvHdmiPkt_CBHandle handle, void *p)
1863 {
1864     nvFree(p);
1865 }
1866 
1867 static void HdmiLibPrint(
1868     NvHdmiPkt_CBHandle handle,
1869     const char *format, ...)
1870 {
1871     NVDevEvoRec *pDevEvo = handle;
1872 
1873     va_list ap;
1874     va_start(ap, format);
1875     /* The HDMI library doesn't have log levels, but currently only logs in
1876      * debug builds.  It's pretty chatty (e.g., it prints "Initialize Success"
1877      * when it inits), so hardcode it to INFO level for now. */
1878     nvVEvoLog(EVO_LOG_INFO, pDevEvo->gpuLogIndex, format, ap);
1879     va_end(ap);
1880 }
1881 
1882 static void HdmiLibAssert(
1883     NvHdmiPkt_CBHandle handle,
1884     NvBool expr)
1885 {
1886     /*
1887      * This interface isn't the best... I hope you have a kernel debugger if
1888      * this fires, because the file and line number will always be this one.
1889      */
1890     nvAssert(expr);
1891 }
1892 
1893 static const NVHDMIPKT_CALLBACK HdmiLibCallbacks =
1894 {
1895     .rmGetMemoryMap = HdmiLibRmGetMemoryMap,
1896     .rmFreeMemoryMap = HdmiLibRmFreeMemoryMap,
1897     .rmDispControl2 = HdmiLibRmDispControl,
1898     .acquireMutex = HdmiLibAcquireMutex,
1899     .releaseMutex = HdmiLibReleaseMutex,
1900     .setTimeout = NULL,     /* optional */
1901     .checkTimeout = NULL,   /* optional */
1902     .malloc = HdmiLibMalloc,
1903     .free = HdmiLibFree,
1904     .print = HdmiLibPrint,
1905     .assert = HdmiLibAssert,
1906 };
1907 
1908 void nvTeardownHdmiLibrary(NVDevEvoRec *pDevEvo)
1909 {
1910     NvHdmiPkt_DestroyLibrary(pDevEvo->hdmiLib.handle);
1911 }
1912 
1913 NvBool nvInitHdmiLibrary(NVDevEvoRec *pDevEvo)
1914 {
1915     pDevEvo->hdmiLib.handle =
1916         NvHdmiPkt_InitializeLibrary(pDevEvo->dispClass,
1917                                     pDevEvo->numSubDevices,
1918                                     pDevEvo, // callback handle
1919                                     &HdmiLibCallbacks,
1920                                     0,     // not used because we set
1921                                     NULL); // NVHDMIPKT_RM_CALLS_INTERNAL=0
1922 
1923     if (pDevEvo->hdmiLib.handle == NVHDMIPKT_INVALID_HANDLE) {
1924         pDevEvo->hdmiLib.handle = NULL;
1925         return FALSE;
1926     }
1927 
1928     return TRUE;
1929 }
1930 
1931 /*
1932  * Call the HDMI library to "assess" the link.  This basically does link
1933  * training to see what the maximum lane configuration is.  We do this when the
1934  * monitor is connected after reading the EDID, so we can validate modes
1935  * against the link capabilities.
1936  *
1937  * Returns true if the link was assessed to be capable of FRL, and false
1938  * otherwise.
1939  */
1940 NvBool nvHdmiFrlAssessLink(NVDpyEvoPtr pDpyEvo)
1941 {
1942     NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
1943     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
1944     NVHDMIPKT_RESULT ret;
1945     const NvU32 displayId = nvDpyIdToNvU32(pDpyEvo->pConnectorEvo->displayId);
1946 
1947     nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
1948 
1949     /* HDMI dpys not dynamic dpy so its connector should have a dpyId. */
1950     nvAssert(displayId != 0);
1951     nvAssert(pDpyEvo->parsedEdid.valid);
1952 
1953     ret = NvHdmi_AssessLinkCapabilities(pDevEvo->hdmiLib.handle,
1954                                         pDispEvo->displayOwner,
1955                                         displayId,
1956                                         &pDpyEvo->parsedEdid.info,
1957                                         &pDpyEvo->hdmi.srcCaps,
1958                                         &pDpyEvo->hdmi.sinkCaps);
1959     if (ret != NVHDMIPKT_SUCCESS) {
1960         nvAssert(ret == NVHDMIPKT_SUCCESS);
1961         return FALSE;
1962     }
1963 
1964     return pDpyEvo->hdmi.sinkCaps.linkMaxFRLRate != HDMI_FRL_DATA_RATE_NONE;
1965 }
1966 
1967 /*
1968  * Determine if the given HDMI dpy supports FRL.
1969  *
1970  * Returns TRUE if the dpy supports FRL, or FALSE otherwise.
1971  */
1972 NvBool nvHdmiDpySupportsFrl(const NVDpyEvoRec *pDpyEvo)
1973 {
1974     NvU32 passiveDpDongleMaxPclkKHz;
1975     const NVDevEvoRec *pDevEvo = pDpyEvo->pDispEvo->pDevEvo;
1976 
1977     nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
1978 
1979     /* Can't use FRL if the display hardware doesn't support it. */
1980     if (!pDevEvo->hal->caps.supportsHDMIFRL) {
1981         return FALSE;
1982     }
1983 
1984     /* Can't use FRL if the HDMI sink doesn't support it. */
1985     if (!pDpyEvo->parsedEdid.valid ||
1986         !pDpyEvo->parsedEdid.info.hdmiForumInfo.max_FRL_Rate) {
1987         return FALSE;
1988     }
1989 
1990     /* Can't use FRL if we are using a passive DP to HDMI dongle. */
1991     if (nvDpyGetPassiveDpDongleType(pDpyEvo, &passiveDpDongleMaxPclkKHz) !=
1992         NV_EVO_PASSIVE_DP_DONGLE_UNUSED) {
1993         return FALSE;
1994     }
1995 
1996     return TRUE;
1997 }
1998 
1999 /*
2000  * Determine if HDMI FRL is needed to drive timings with the given pixel clock
2001  * on the given dpy.
2002  *
2003  * Returns TRUE if FRL is needed, or FALSE otherwise.
2004  * */
2005 static NvBool HdmiTimingsNeedFrl(const NVDpyEvoRec *pDpyEvo,
2006                                  const NVHwModeTimingsEvo *pHwTimings)
2007 {
2008     const NvU32 pixelClock = (pHwTimings->yuv420Mode == NV_YUV420_MODE_HW) ?
2009         (pHwTimings->pixelClock / 2) : pHwTimings->pixelClock;
2010 
2011     nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
2012 
2013     /*
2014      * For HDMI, maxSingleLinkPixelClockKHz is the maximum non-FRL rate.
2015      * If the rate is higher than that, try to use FRL for the mode.
2016      */
2017     return pixelClock > pDpyEvo->maxSingleLinkPixelClockKHz;
2018 }
2019 
2020 NvBool nvHdmiFrlQueryConfig(
2021     const NVDpyEvoRec *pDpyEvo,
2022     const NvModeTimings *pModeTimings,
2023     NVHwModeTimingsEvo *pHwTimings,
2024     const struct NvKmsModeValidationParams *pValidationParams)
2025 {
2026     const NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo;
2027     const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
2028     HDMI_VIDEO_TRANSPORT_INFO videoTransportInfo = { };
2029     HDMI_QUERY_FRL_CLIENT_CONTROL clientControl = { };
2030     const NVT_TIMING *pNvtTiming;
2031     NVT_TIMING nvtTiming = { };
2032     NVHDMIPKT_RESULT ret;
2033 
2034     if (!nvDpyIsHdmiEvo(pDpyEvo) ||
2035         !HdmiTimingsNeedFrl(pDpyEvo, pHwTimings)) {
2036         return TRUE;
2037     }
2038 
2039     if (!nvHdmiDpySupportsFrl(pDpyEvo)) {
2040         return FALSE;
2041     }
2042 
2043     /* See if we can find an NVT_TIMING for this mode from the EDID. */
2044     pNvtTiming = nvFindEdidNVT_TIMING(pDpyEvo, pModeTimings, pValidationParams);
2045 
2046     if (pNvtTiming == NULL) {
2047         /*
2048          * No luck finding this mode in the EDID.
2049          *
2050          * Construct enough of an NVT_TIMING for the hdmi library, based on the
2051          * pHwTimings mode.
2052          *
2053          * The HDMI library's hdmiQueryFRLConfigC671 uses:
2054          * - pVidTransInfo->pTiming->pclk
2055          * - pVidTransInfo->pTiming->HTotal
2056          * - pVidTransInfo->pTiming->HVisible
2057          * - pVidTransInfo->pTiming->VVisible
2058          *
2059          * This is also used, although we don't have a CEA format so we just
2060          * set it to 0:
2061          * - NVT_GET_CEA_FORMAT(pVidTransInfo->pTiming->etc.status)
2062          */
2063 
2064         /* Convert from KHz to 10KHz; round up for the purposes of determining a
2065          * minimum FRL rate. */
2066         nvtTiming.pclk = (pHwTimings->pixelClock + 9) / 10;
2067         nvtTiming.HVisible = pHwTimings->rasterBlankStart.x -
2068                              pHwTimings->rasterBlankEnd.x;
2069         nvtTiming.HTotal = pHwTimings->rasterSize.x;
2070         nvtTiming.VVisible = pHwTimings->rasterBlankStart.y -
2071                              pHwTimings->rasterBlankEnd.y;
2072         nvtTiming.etc.status = 0;
2073 
2074         pNvtTiming = &nvtTiming;
2075     }
2076 
2077     videoTransportInfo.pTiming = pNvtTiming;
2078     /*
2079      * pTimings->pixelDepth isn't assigned yet at this point in mode
2080      * validation, so we can't use that.
2081      * This matches the non-DP default assigned later in
2082      * nvConstructHwModeTimingsEvo().
2083      *
2084      * TODO: we should select a higher depth by default and downgrade if not
2085      * possible.
2086      */
2087     videoTransportInfo.bpc = HDMI_BPC8;
2088     /* TODO: support YUV/YCbCr 444 and 422 packing modes. */
2089     switch (pModeTimings->yuv420Mode) {
2090         case NV_YUV420_MODE_NONE:
2091             videoTransportInfo.packing = HDMI_PIXEL_PACKING_RGB;
2092             break;
2093         case NV_YUV420_MODE_SW:
2094             /*
2095              * Don't bother implementing this with FRL.
2096              * HDMI FRL and HW YUV420 support were both added in nvdisplay 4.0
2097              * hardware, so if the hardware supports FRL it should support
2098              * YUV420_MODE_HW.
2099              */
2100             return FALSE;
2101         case NV_YUV420_MODE_HW:
2102             videoTransportInfo.packing = HDMI_PIXEL_PACKING_YCbCr420;
2103             break;
2104     }
2105     /* TODO: implement 2head1or+FRL */
2106     videoTransportInfo.bDualHeadMode = FALSE;
2107 
2108     clientControl.option = HDMI_QUERY_FRL_HIGHEST_PIXEL_QUALITY;
2109 
2110     if (pValidationParams->forceDsc) {
2111         clientControl.enableDSC = TRUE;
2112     }
2113     if (pValidationParams->dscOverrideBitsPerPixelX16 != 0) {
2114         clientControl.forceBppx16 = TRUE;
2115         clientControl.bitsPerPixelX16 =
2116             pValidationParams->dscOverrideBitsPerPixelX16;
2117     }
2118 
2119     ret = NvHdmi_QueryFRLConfig(pDevEvo->hdmiLib.handle,
2120                                 &videoTransportInfo,
2121                                 &clientControl,
2122                                 &pDpyEvo->hdmi.srcCaps,
2123                                 &pDpyEvo->hdmi.sinkCaps,
2124                                 &pHwTimings->hdmiFrlConfig);
2125 
2126     return ret == NVHDMIPKT_SUCCESS;
2127 }
2128 
2129 void nvHdmiFrlClearConfig(NVDispEvoRec *pDispEvo, NvU32 activeRmId)
2130 {
2131     const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
2132 
2133     NVHDMIPKT_RESULT ret;
2134     ret = NvHdmi_ClearFRLConfig(pDevEvo->hdmiLib.handle,
2135                                 pDispEvo->displayOwner, activeRmId);
2136     if (ret != NVHDMIPKT_SUCCESS) {
2137         nvAssert(ret == NVHDMIPKT_SUCCESS);
2138     }
2139 }
2140 
2141 void nvHdmiFrlSetConfig(NVDispEvoRec *pDispEvo, NvU32 head)
2142 {
2143     const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
2144     NVDispHeadStateEvoRec *pHeadState =
2145         &pDispEvo->headState[head];
2146     HDMI_FRL_CONFIG *pFrlConfig = &pHeadState->timings.hdmiFrlConfig;
2147     NVHDMIPKT_RESULT ret;
2148     NvU32 retries = 0;
2149     const NvU32 MAX_RETRIES = 5;
2150 
2151     if (pFrlConfig->frlRate == HDMI_FRL_DATA_RATE_NONE) {
2152         return;
2153     }
2154 
2155     nvAssert(pHeadState->activeRmId != 0);
2156 
2157     do {
2158         ret = NvHdmi_SetFRLConfig(pDevEvo->hdmiLib.handle,
2159                                   pDispEvo->displayOwner,
2160                                   pHeadState->activeRmId,
2161                                   NV_FALSE /* bFakeLt */,
2162                                   pFrlConfig);
2163     } while (ret != NVHDMIPKT_SUCCESS && retries++ < MAX_RETRIES);
2164 
2165     if (ret != NVHDMIPKT_SUCCESS) {
2166         nvEvoLogDisp(pDispEvo, EVO_LOG_WARN,
2167                      "HDMI FRL link training failed.");
2168 
2169         /*
2170          * Link training failed even after retrying.  Since link training
2171          * happens after we've already committed to a modeset and failing is
2172          * not an option, try one last time with the 'bFakeLt' parameter
2173          * set, which should enable enough of the display hardware to
2174          * prevent hangs when we attempt to drive the OR with
2175          * PROTOCOL_HDMI_FRL.
2176          */
2177         ret = NvHdmi_SetFRLConfig(pDevEvo->hdmiLib.handle,
2178                                   pDispEvo->displayOwner,
2179                                   pHeadState->activeRmId,
2180                                   NV_TRUE /* bFakeLt */,
2181                                   pFrlConfig);
2182 
2183         if (ret != NVHDMIPKT_SUCCESS) {
2184             nvEvoLogDisp(pDispEvo, EVO_LOG_ERROR,
2185                          "HDMI FRL fallback link training failed.");
2186         }
2187     }
2188 
2189     if (retries != 0) {
2190         nvEvoLogDispDebug(pDispEvo, EVO_LOG_WARN,
2191                           "HDMI FRL link training retried %d times.",
2192                           retries);
2193     }
2194 }
2195