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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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