1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * 4 * HDF is dual licensed: you can use it either under the terms of 5 * the GPL, or the BSD license, at your option. 6 * See the LICENSE file in the root of this repository for complete details. 7 */ 8 9 #include "hdmi_core.h" 10 #include "device_resource_if.h" 11 #include "hdf_log.h" 12 #include "hdmi_dispatch.h" 13 #include "osal_mem.h" 14 #include "osal_time.h" 15 #include "securec.h" 16 17 #define HDF_LOG_TAG hdmi_core_c 18 HdmiCntlrAllocDev(struct HdmiCntlr * cntlr)19 int32_t HdmiCntlrAllocDev(struct HdmiCntlr *cntlr) 20 { 21 struct HdmiDevice *dev = (struct HdmiDevice *)OsalMemCalloc(sizeof(struct HdmiDevice)); 22 23 if (dev == NULL) { 24 HDF_LOGE("Hdmi alloc dev fail"); 25 return HDF_ERR_MALLOC_FAIL; 26 } 27 28 dev->cntlr = cntlr; 29 cntlr->hdmi = dev; 30 return HDF_SUCCESS; 31 } 32 HdmiCntlrFreeDev(struct HdmiCntlr * cntlr)33 void HdmiCntlrFreeDev(struct HdmiCntlr *cntlr) 34 { 35 if (cntlr == NULL || cntlr->hdmi == NULL) { 36 return; 37 } 38 39 OsalMemFree(cntlr->hdmi); 40 cntlr->hdmi = NULL; 41 } 42 HdmiCecInit(struct HdmiCntlr * cntlr)43 static void HdmiCecInit(struct HdmiCntlr *cntlr) 44 { 45 if (cntlr == NULL) { 46 return; 47 } 48 if (cntlr->cap.baseCap.bits.cec == 0) { 49 HDF_LOGD("not support cec"); 50 return; 51 } 52 53 if (cntlr->cec == NULL) { 54 cntlr->cec = (struct HdmiCec *)OsalMemCalloc(sizeof(struct HdmiCec)); 55 if (cntlr->cec == NULL) { 56 HDF_LOGE("cec malloc fail"); 57 return; 58 } 59 } 60 HDF_LOGE("HdmiCecInit, success."); 61 cntlr->cec->priv = (void *)cntlr; 62 } 63 HdmiCecDeinit(struct HdmiCntlr * cntlr)64 static void HdmiCecDeinit(struct HdmiCntlr *cntlr) 65 { 66 if (cntlr == NULL) { 67 return; 68 } 69 if (cntlr->cec != NULL) { 70 OsalMemFree(cntlr->cec); 71 cntlr->cec = NULL; 72 } 73 } 74 HdmiDdcInit(struct HdmiCntlr * cntlr)75 static void HdmiDdcInit(struct HdmiCntlr *cntlr) 76 { 77 int32_t ret; 78 79 if (cntlr == NULL) { 80 HDF_LOGE("ddc init: param is invalid"); 81 return; 82 } 83 cntlr->ddc.priv = (void *)cntlr; 84 if (cntlr->ddc.init == true) { 85 return; 86 } 87 ret = OsalMutexInit(&(cntlr->ddc.ddcMutex)); 88 if (ret != HDF_SUCCESS) { 89 HDF_LOGE("HdmiDdcInit: mutex init fail!"); 90 return; 91 } 92 HDF_LOGE("HdmiDdcInit, success."); 93 cntlr->ddc.init = true; 94 } 95 HdmiDdcDeinit(struct HdmiCntlr * cntlr)96 static void HdmiDdcDeinit(struct HdmiCntlr *cntlr) 97 { 98 if (cntlr == NULL) { 99 HDF_LOGE("ddc init: param is invalid"); 100 return; 101 } 102 103 (void)OsalMutexDestroy(&(cntlr->ddc.ddcMutex)); 104 if (memset_s(&(cntlr->ddc), sizeof(struct HdmiDdc), 0, sizeof(struct HdmiDdc)) != EOK) { 105 HDF_LOGE("deinit ddc, memset_s fail."); 106 } 107 cntlr->ddc.priv = NULL; 108 cntlr->ddc.init = false; 109 } 110 HdmiFrlInit(struct HdmiCntlr * cntlr)111 static void HdmiFrlInit(struct HdmiCntlr *cntlr) 112 { 113 if (cntlr == NULL) { 114 return; 115 } 116 if (cntlr->cap.baseCap.bits.frl == 0) { 117 HDF_LOGD("not support frl"); 118 return; 119 } 120 121 if (cntlr->frl == NULL) { 122 cntlr->frl = (struct HdmiFrl *)OsalMemCalloc(sizeof(struct HdmiFrl)); 123 if (cntlr->frl == NULL) { 124 HDF_LOGE("frl malloc fail"); 125 return; 126 } 127 } 128 HDF_LOGE("HdmiFrlInit, success."); 129 cntlr->frl->priv = (void *)cntlr; 130 } 131 HdmiFrlDeinit(struct HdmiCntlr * cntlr)132 static void HdmiFrlDeinit(struct HdmiCntlr *cntlr) 133 { 134 if (cntlr == NULL) { 135 return; 136 } 137 if (cntlr->frl != NULL) { 138 OsalMemFree(cntlr->frl); 139 cntlr->frl = NULL; 140 } 141 } 142 HdmiHdcpInit(struct HdmiCntlr * cntlr)143 static void HdmiHdcpInit(struct HdmiCntlr *cntlr) 144 { 145 int32_t ret; 146 147 if (cntlr == NULL) { 148 return; 149 } 150 if (cntlr->cap.baseCap.bits.hdcp == 0) { 151 HDF_LOGD("not support hdcp"); 152 return; 153 } 154 155 if (cntlr->hdcp == NULL) { 156 cntlr->hdcp = (struct HdmiHdcp *)OsalMemCalloc(sizeof(struct HdmiHdcp)); 157 if (cntlr->hdcp == NULL) { 158 HDF_LOGE("hdcp malloc fail"); 159 return; 160 } 161 ret = OsalMutexInit(&(cntlr->hdcp->hdcpMutex)); 162 if (ret != HDF_SUCCESS) { 163 HDF_LOGE("HdmiHdcpInit: mutex init fail!"); 164 return; 165 } 166 } 167 HDF_LOGE("HdmiHdcpInit, success."); 168 cntlr->hdcp->priv = (void *)cntlr; 169 } 170 HdmiHdcpDeinit(struct HdmiCntlr * cntlr)171 static void HdmiHdcpDeinit(struct HdmiCntlr *cntlr) 172 { 173 if (cntlr == NULL) { 174 return; 175 } 176 if (cntlr->hdcp != NULL) { 177 HdmiHdcpClose(cntlr->hdcp); 178 OsalMemFree(cntlr->hdcp); 179 cntlr->hdcp = NULL; 180 } 181 } 182 HdmiHdrInit(struct HdmiCntlr * cntlr)183 static void HdmiHdrInit(struct HdmiCntlr *cntlr) 184 { 185 if (cntlr == NULL) { 186 return; 187 } 188 if (cntlr->cap.baseCap.bits.hdr == 0) { 189 HDF_LOGD("not support hdr"); 190 return; 191 } 192 193 if (cntlr->hdr == NULL) { 194 cntlr->hdr = (struct HdmiHdr *)OsalMemCalloc(sizeof(struct HdmiHdr)); 195 if (cntlr->hdr == NULL) { 196 HDF_LOGE("hdr malloc fail"); 197 return; 198 } 199 } 200 HDF_LOGE("HdmiHdrInit, success."); 201 cntlr->hdr->priv = (void *)cntlr; 202 } 203 HdmiHdrDeinit(struct HdmiCntlr * cntlr)204 static void HdmiHdrDeinit(struct HdmiCntlr *cntlr) 205 { 206 if (cntlr == NULL) { 207 return; 208 } 209 if (cntlr->hdr != NULL) { 210 OsalMemFree(cntlr->hdr); 211 cntlr->hdr = NULL; 212 } 213 } 214 HdmiInfoFrameInit(struct HdmiCntlr * cntlr)215 static void HdmiInfoFrameInit(struct HdmiCntlr *cntlr) 216 { 217 if (cntlr == NULL) { 218 return; 219 } 220 HDF_LOGE("HdmiInfoFrameInit, success."); 221 cntlr->infoFrame.priv = (void *)cntlr; 222 } 223 HdmiInfoFrameDeInit(struct HdmiCntlr * cntlr)224 static void HdmiInfoFrameDeInit(struct HdmiCntlr *cntlr) 225 { 226 if (cntlr == NULL) { 227 return; 228 } 229 230 if (memset_s(&(cntlr->infoFrame), sizeof(struct HdmiInfoFrame), 0, sizeof(struct HdmiInfoFrame)) != EOK) { 231 HDF_LOGE("deinit infoFrame, memset_s fail."); 232 } 233 cntlr->infoFrame.priv = NULL; 234 } 235 HdmiScdcInit(struct HdmiCntlr * cntlr)236 static void HdmiScdcInit(struct HdmiCntlr *cntlr) 237 { 238 if (cntlr == NULL) { 239 return; 240 } 241 if (cntlr->cap.baseCap.bits.scdc == 0) { 242 HDF_LOGD("not support scdc"); 243 return; 244 } 245 246 if (cntlr->scdc == NULL) { 247 cntlr->scdc = (struct HdmiScdc *)OsalMemCalloc(sizeof(struct HdmiScdc)); 248 if (cntlr->scdc == NULL) { 249 HDF_LOGE("scdc malloc fail"); 250 return; 251 } 252 } 253 HDF_LOGE("HdmiScdcInit, success."); 254 cntlr->scdc->priv = (void *)cntlr; 255 } 256 HdmiScdcDeinit(struct HdmiCntlr * cntlr)257 static void HdmiScdcDeinit(struct HdmiCntlr *cntlr) 258 { 259 if (cntlr == NULL) { 260 return; 261 } 262 if (cntlr->scdc != NULL) { 263 OsalMemFree(cntlr->scdc); 264 cntlr->scdc = NULL; 265 } 266 } 267 HdmiCntlrInit(struct HdmiCntlr * cntlr)268 static int32_t HdmiCntlrInit(struct HdmiCntlr *cntlr) 269 { 270 int32_t ret; 271 272 if (cntlr == NULL) { 273 return HDF_ERR_INVALID_OBJECT; 274 } 275 276 if (cntlr->hdfDevObj == NULL) { 277 HDF_LOGE("HdmiCntlrInit: no HdfDeviceObject attached!"); 278 return HDF_ERR_INVALID_OBJECT; 279 } 280 281 ret = OsalMutexInit(&cntlr->mutex); 282 if (ret != HDF_SUCCESS) { 283 HDF_LOGE("HdmiCntlrInit: mutex init fail!"); 284 return ret; 285 } 286 287 cntlr->msgQueue = PlatformQueueCreate(HdmiEventMsgHandleDefault, "PlatformHdmiWorkerThread", cntlr); 288 if (cntlr->msgQueue == NULL) { 289 HDF_LOGE("HdmiCntlrInit: failed to create msg queue!"); 290 return HDF_PLT_ERR_OS_API; 291 } 292 ret = PlatformQueueStart(cntlr->msgQueue); 293 if (ret != HDF_SUCCESS) { 294 HDF_LOGE("HdmiCntlrInit: failed to start msg queue!"); 295 PlatformQueueDestroy(cntlr->msgQueue); 296 return ret; 297 } 298 299 cntlr->service.Dispatch = HdmiIoDispatch; 300 cntlr->hdfDevObj->service = &(cntlr->service); 301 cntlr->device.number = (int32_t)cntlr->deviceIndex; 302 cntlr->device.hdfDev = cntlr->hdfDevObj; 303 HdmiInfoFrameInit(cntlr); 304 HdmiDdcInit(cntlr); 305 return HDF_SUCCESS; 306 } 307 HdmiCntlrUninit(struct HdmiCntlr * cntlr)308 static void HdmiCntlrUninit(struct HdmiCntlr *cntlr) 309 { 310 if (cntlr != NULL) { 311 HdmiInfoFrameDeInit(cntlr); 312 HdmiScdcDeinit(cntlr); 313 HdmiDdcDeinit(cntlr); 314 HdmiCecDeinit(cntlr); 315 HdmiFrlDeinit(cntlr); 316 HdmiHdcpDeinit(cntlr); 317 HdmiCntlrFreeDev(cntlr); 318 (void)OsalMutexDestroy(&cntlr->mutex); 319 } 320 } 321 HdmiCntlrAdd(struct HdmiCntlr * cntlr)322 int32_t HdmiCntlrAdd(struct HdmiCntlr *cntlr) 323 { 324 int32_t ret; 325 326 if (cntlr == NULL) { 327 return HDF_ERR_INVALID_OBJECT; 328 } 329 330 ret = HdmiCntlrInit(cntlr); 331 if (ret != HDF_SUCCESS) { 332 return ret; 333 } 334 335 cntlr->device.manager = PlatformManagerGet(PLATFORM_MODULE_HDMI); 336 ret = PlatformDeviceAdd(&cntlr->device); 337 if (ret != HDF_SUCCESS) { 338 HDF_LOGE("HdmiCntlrAdd: device add fail!"); 339 HdmiCntlrUninit(cntlr); 340 return ret; 341 } 342 return HDF_SUCCESS; 343 } 344 HdmiCntlrRemove(struct HdmiCntlr * cntlr)345 void HdmiCntlrRemove(struct HdmiCntlr *cntlr) 346 { 347 if (cntlr != NULL) { 348 HdmiCntlrUninit(cntlr); 349 PlatformDeviceDel(&cntlr->device); 350 } 351 } 352 HdmiCntlrParseVideoCaps(struct HdmiCntlr * cntlr,struct DeviceResourceIface * drsOps,const struct DeviceResourceNode * node)353 static int32_t HdmiCntlrParseVideoCaps( 354 struct HdmiCntlr *cntlr, struct DeviceResourceIface *drsOps, const struct DeviceResourceNode *node) 355 { 356 int32_t ret; 357 358 ret = drsOps->GetUint32(node, "maxTmdsClock", &(cntlr->cap.maxTmdsClock), 0); 359 if (ret != HDF_SUCCESS) { 360 HDF_LOGE("HdmiCntlrParseVideoCaps: read maxTmdsClock fail!"); 361 return ret; 362 } 363 364 ret = drsOps->GetUint32(node, "defTmdsClock", &(cntlr->cap.defTmdsClock), 0); 365 if (ret != HDF_SUCCESS) { 366 HDF_LOGE("HdmiCntlrParseVideoCaps: read defTmdsClock fail!"); 367 return ret; 368 } 369 370 ret = drsOps->GetUint32(node, "maxFrlRate", &(cntlr->cap.maxFrlRate), 0); 371 if (ret != HDF_SUCCESS) { 372 HDF_LOGE("HdmiCntlrParseVideoCaps: read maxFrlRate fail!"); 373 return ret; 374 } 375 376 ret = drsOps->GetUint32(node, "videoTiming", &(cntlr->cap.videoTiming), 0); 377 if (ret != HDF_SUCCESS) { 378 HDF_LOGE("HdmiCntlrParseVideoCaps: read videoTiming fail!"); 379 return ret; 380 } 381 382 ret = drsOps->GetUint32(node, "quantization", &(cntlr->cap.quantization), 0); 383 if (ret != HDF_SUCCESS) { 384 HDF_LOGE("HdmiCntlrParseVideoCaps: read quantization fail!"); 385 return ret; 386 } 387 388 ret = drsOps->GetUint32(node, "colorSpace", &(cntlr->cap.colorSpace), 0); 389 if (ret != HDF_SUCCESS) { 390 HDF_LOGE("HdmiCntlrParseVideoCaps: read colorSpace fail!"); 391 return ret; 392 } 393 394 ret = drsOps->GetUint32(node, "colorimetry", &(cntlr->cap.colorimetry), 0); 395 if (ret != HDF_SUCCESS) { 396 HDF_LOGE("HdmiCntlrParseVideoCaps: read colorimetry fail!"); 397 return ret; 398 } 399 return HDF_SUCCESS; 400 } 401 HdmiCntlrParseAudioCaps(struct HdmiCntlr * cntlr,struct DeviceResourceIface * drsOps,const struct DeviceResourceNode * node)402 static int32_t HdmiCntlrParseAudioCaps( 403 struct HdmiCntlr *cntlr, struct DeviceResourceIface *drsOps, const struct DeviceResourceNode *node) 404 { 405 int32_t ret; 406 407 ret = drsOps->GetUint32(node, "audioIfType", &(cntlr->cap.audioIfType), 0); 408 if (ret != HDF_SUCCESS) { 409 HDF_LOGE("HdmiCntlrParseAudioCaps: read audioIfType fail!"); 410 return ret; 411 } 412 HDF_LOGD("HdmiCntlrParseAudioCaps: audioIfType = %d", cntlr->cap.audioIfType); 413 414 ret = drsOps->GetUint32(node, "audioBitDepth", &(cntlr->cap.audioBitDepth), 0); 415 if (ret != HDF_SUCCESS) { 416 HDF_LOGE("HdmiCntlrParseAudioCaps: read audioBitDepth fail!"); 417 return ret; 418 } 419 HDF_LOGD("HdmiCntlrParseAudioCaps: audioBitDepth = %d", cntlr->cap.audioBitDepth); 420 421 ret = drsOps->GetUint32(node, "audioSampleRate", &(cntlr->cap.audioSampleRate), 0); 422 if (ret != HDF_SUCCESS) { 423 HDF_LOGE("HdmiCntlrParseAudioCaps: read audioSampleRate fail!"); 424 return ret; 425 } 426 HDF_LOGD("HdmiCntlrParseAudioCaps: audioSampleRate = %d", cntlr->cap.audioSampleRate); 427 428 ret = drsOps->GetUint32(node, "audioChannels", &(cntlr->cap.audioChannels), 0); 429 if (ret != HDF_SUCCESS) { 430 HDF_LOGE("HdmiCntlrParseAudioCaps: read audioChannels fail!"); 431 return ret; 432 } 433 HDF_LOGD("HdmiCntlrParseAudioCaps: audioChannels = %d", cntlr->cap.audioChannels); 434 return HDF_SUCCESS; 435 } 436 HdmiCntlrParseHdrCaps(struct HdmiCntlr * cntlr,struct DeviceResourceIface * drsOps,const struct DeviceResourceNode * node)437 static int32_t HdmiCntlrParseHdrCaps( 438 struct HdmiCntlr *cntlr, struct DeviceResourceIface *drsOps, const struct DeviceResourceNode *node) 439 { 440 int32_t ret; 441 442 ret = drsOps->GetUint32(node, "hdrColorimetry", &(cntlr->cap.hdrColorimetry), 0); 443 if (ret != HDF_SUCCESS) { 444 HDF_LOGE("HdmiCntlrParseAudioCaps: read hdrColorimetry fail!"); 445 return ret; 446 } 447 HDF_LOGD("HdmiCntlrParseAudioCaps: hdrColorimetry = %d", cntlr->cap.hdrColorimetry); 448 449 ret = drsOps->GetUint32(node, "hdrUserMode", &(cntlr->cap.hdrUserMode), 0); 450 if (ret != HDF_SUCCESS) { 451 HDF_LOGE("HdmiCntlrParseAudioCaps: read hdrUserMode fail!"); 452 return ret; 453 } 454 HDF_LOGD("HdmiCntlrParseAudioCaps: hdrUserMode = %d", cntlr->cap.hdrUserMode); 455 return HDF_SUCCESS; 456 } 457 HdmiCntlrParse(struct HdmiCntlr * cntlr,struct HdfDeviceObject * obj)458 int32_t HdmiCntlrParse(struct HdmiCntlr *cntlr, struct HdfDeviceObject *obj) 459 { 460 const struct DeviceResourceNode *node = NULL; 461 struct DeviceResourceIface *drsOps = NULL; 462 int32_t ret; 463 464 if (obj == NULL || cntlr == NULL) { 465 HDF_LOGE("HdmiCntlrParse: input param is NULL."); 466 return HDF_FAILURE; 467 } 468 469 node = obj->property; 470 if (node == NULL) { 471 HDF_LOGE("HdmiCntlrParse: drs node is NULL."); 472 return HDF_FAILURE; 473 } 474 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 475 if (drsOps == NULL || drsOps->GetUint32 == NULL) { 476 HDF_LOGE("HdmiCntlrParse: invalid drs ops fail!"); 477 return HDF_FAILURE; 478 } 479 480 ret = drsOps->GetUint32(node, "index", &(cntlr->deviceIndex), 0); 481 if (ret != HDF_SUCCESS) { 482 HDF_LOGE("HdmiCntlrParse: read hostId fail!"); 483 return ret; 484 } 485 486 ret = drsOps->GetUint32(node, "cap", &(cntlr->cap.baseCap.data), 0); 487 if (ret != HDF_SUCCESS) { 488 HDF_LOGE("HdmiCntlrParse: read baseCap fail!"); 489 return ret; 490 } 491 492 ret = HdmiCntlrParseVideoCaps(cntlr, drsOps, node); 493 if (ret != HDF_SUCCESS) { 494 HDF_LOGE("HdmiCntlrParse: read video caps fail!"); 495 return ret; 496 } 497 498 ret = HdmiCntlrParseAudioCaps(cntlr, drsOps, node); 499 if (ret != HDF_SUCCESS) { 500 HDF_LOGE("HdmiCntlrParse: read audio caps fail!"); 501 return ret; 502 } 503 504 ret = HdmiCntlrParseHdrCaps(cntlr, drsOps, node); 505 if (ret != HDF_SUCCESS) { 506 HDF_LOGE("HdmiCntlrParse: read hdr caps fail!"); 507 return ret; 508 } 509 return HDF_SUCCESS; 510 } 511 HdmiGetSinkCapability(struct HdmiDevice * hdmi)512 static struct HdmiSinkDeviceCapability *HdmiGetSinkCapability(struct HdmiDevice *hdmi) 513 { 514 if (hdmi == NULL) { 515 return NULL; 516 } 517 518 if (hdmi->edid.edidPhase == false) { 519 return NULL; 520 } 521 return &(hdmi->edid.sinkCap); 522 } 523 HdmiCntlrGetSinkEdid(struct HdmiCntlr * cntlr,uint8_t * buffer,uint32_t len)524 int32_t HdmiCntlrGetSinkEdid(struct HdmiCntlr *cntlr, uint8_t *buffer, uint32_t len) 525 { 526 int32_t ret; 527 528 if (cntlr == NULL) { 529 return HDF_ERR_INVALID_OBJECT; 530 } 531 if (HdmiHpdStatusDelayGet(cntlr) == false) { 532 HDF_LOGE("no hdmi sink device"); 533 HdmiCntlrFreeDev(cntlr); 534 return HDF_DEV_ERR_NO_DEVICE; 535 } 536 if (cntlr->hdmi != NULL) { 537 return HdmiEdidGetRaw(&(cntlr->hdmi->edid), buffer, len); 538 } 539 540 ret = HdmiCntlrAllocDev(cntlr); 541 if (ret != HDF_SUCCESS) { 542 return ret; 543 } 544 545 ret = HdmiEdidRawDataRead(&(cntlr->hdmi->edid), &(cntlr->ddc)); 546 if (ret != HDF_SUCCESS) { 547 HdmiCntlrFreeDev(cntlr); 548 return ret; 549 } 550 551 if (cntlr->hdmi->edid.edidPhase != true) { 552 (void)HdmiEdidPhase(&(cntlr->hdmi->edid)); 553 cntlr->hdmi->edid.edidPhase = true; 554 } 555 return HdmiEdidGetRaw(&(cntlr->hdmi->edid), buffer, len); 556 } 557 HdmiCntlrModeSelect(struct HdmiCntlr * cntlr)558 static void HdmiCntlrModeSelect(struct HdmiCntlr *cntlr) 559 { 560 enum HdmiTmdsModeType tmdsMode; 561 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr); 562 struct HdmiScdcScrambleCap scramble = {0}; 563 struct HdmiScdcScrambleCap curScramble = {0}; 564 int32_t ret; 565 566 /* support FRL. */ 567 if (HdmiFrlSupport(cntlr->frl) == true && cntlr->cap.baseCap.bits.frl > 0) { 568 return; 569 } 570 571 if (cntlr->cap.baseCap.bits.scdc > 0) { 572 ret = HdmiScdcFillScrambleCap(cntlr->scdc, &scramble, &tmdsMode); 573 if (ret != HDF_SUCCESS) { 574 return; 575 } 576 } else { 577 tmdsMode = (commAttr->enableHdmi == true) ? HDMI_TMDS_MODE_HDMI_1_4 : HDMI_TMDS_MODE_DVI; 578 } 579 580 cntlr->tmdsMode = tmdsMode; 581 HdmiCntlrTmdsModeSet(cntlr, tmdsMode); 582 HdmiCntlrReset(cntlr); 583 584 if (cntlr->cap.baseCap.bits.scdc > 0 && HdmiEdidScdcSupport(cntlr->hdmi) == true) { 585 ret = HdmiScdcScrambleGet(cntlr->scdc, &curScramble); 586 if (ret != HDF_SUCCESS) { 587 return; 588 } 589 if (scramble.sinkScramble != curScramble.sinkScramble || 590 scramble.sourceScramble != curScramble.sourceScramble || 591 scramble.tmdsBitClockRatio40 != curScramble.tmdsBitClockRatio40) { 592 (void)HdmiScdcScrambleSet(cntlr->scdc, &scramble); 593 } 594 } 595 } 596 HdmiCommonAttrInit(struct HdmiCntlr * cntlr)597 static void HdmiCommonAttrInit(struct HdmiCntlr *cntlr) 598 { 599 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr); 600 601 commAttr->enableHdmi = true; 602 commAttr->enableVideo = true; 603 commAttr->enableAudio = true; 604 commAttr->audio = true; 605 commAttr->avi = true; 606 commAttr->hdcpMode = HDMI_HDCP_MODE_1_4; 607 commAttr->colorSpace = (enum HdmiColorSpace)cntlr->cap.colorSpace; 608 commAttr->quantization = (enum HdmiQuantizationRange)cntlr->cap.quantization; 609 } 610 HdmiVideoAttrInit(struct HdmiCntlr * cntlr)611 static void HdmiVideoAttrInit(struct HdmiCntlr *cntlr) 612 { 613 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr); 614 bool colorimetry601; 615 616 videoAttr->timing = (enum HdmiVideoTiming)cntlr->cap.videoTiming; 617 colorimetry601 = ((videoAttr->timing == HDMI_VIDEO_TIMING_720X480P60) || 618 (videoAttr->timing == HDMI_VIDEO_TIMING_720X576P50) || (videoAttr->timing == HDMI_VIDEO_TIMING_1440X240P60) || 619 (videoAttr->timing == HDMI_VIDEO_TIMING_1440X480I60) || (videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I50) || 620 (videoAttr->timing == HDMI_VIDEO_TIMING_1440X576P50) || (videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I60)); 621 622 if (videoAttr->timing == HDMI_VIDEO_TIMING_640X480P60) { 623 videoAttr->colorimetry = HDMI_COLORIMETRY_ITU709; 624 videoAttr->aspect = HDMI_PICTURE_ASPECT_4_3; 625 } else if (colorimetry601 == true) { 626 videoAttr->colorimetry = HDMI_COLORIMETRY_ITU601; 627 videoAttr->aspect = HDMI_PICTURE_ASPECT_4_3; 628 } else if (videoAttr->timing <= HDMI_VIDEO_TIMING_4096X2160P120 && 629 videoAttr->timing >= HDMI_VIDEO_TIMING_4096X2160P24) { 630 videoAttr->colorimetry = HDMI_COLORIMETRY_ITU709; 631 videoAttr->aspect = HDMI_PICTURE_ASPECT_256_135; 632 } else { 633 videoAttr->colorimetry = HDMI_COLORIMETRY_ITU709; 634 videoAttr->aspect = HDMI_PICTURE_ASPECT_16_9; 635 } 636 637 videoAttr->pixelRepeat = 1; 638 if (videoAttr->timing == HDMI_VIDEO_TIMING_1440X480I60 || videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I50) { 639 videoAttr->pixelRepeat = 2; // 2 means the number of repetitions for each pixel 640 } 641 642 if (videoAttr->timing <= HDMI_VIDEO_TIMING_640X480P60) { 643 videoAttr->quantization = HDMI_QUANTIZATION_RANGE_DEFAULT; 644 } else { 645 videoAttr->yccQuantization = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; 646 } 647 648 if (videoAttr->timing != HDMI_VIDEO_TIMING_NONE && videoAttr->timing != HDMI_VIDEO_TIMING_640X480P60) { 649 videoAttr->colorSpace = HDMI_COLOR_SPACE_YCBCR444; 650 } else { 651 videoAttr->colorSpace = HDMI_COLOR_SPACE_RGB; 652 } 653 654 videoAttr->_3dStruct = HDMI_VS_VIDEO_3D_BUTT; 655 videoAttr->activeAspect = HDMI_ACTIVE_FORMAT_ASPECT_PICTURE; 656 } 657 HdmiAudioAttrInit(struct HdmiCntlr * cntlr)658 static void HdmiAudioAttrInit(struct HdmiCntlr *cntlr) 659 { 660 struct HdmiAudioAttr *audioAttr = &(cntlr->attr.audioAttr); 661 662 audioAttr->ifType = (enum HdmiAudioInterfaceType)cntlr->cap.audioIfType; 663 audioAttr->bitDepth = (enum HdmiAudioBitDepth)cntlr->cap.audioBitDepth; 664 audioAttr->sampleRate = (enum HdmiSampleRate)cntlr->cap.audioSampleRate; 665 audioAttr->channels = (enum HdmiAudioFormatChannel)cntlr->cap.audioChannels; 666 } 667 HdmiHdrAttrInit(struct HdmiCntlr * cntlr)668 static void HdmiHdrAttrInit(struct HdmiCntlr *cntlr) 669 { 670 struct HdmiHdrAttr *hdrAttr = &(cntlr->attr.hdrAttr); 671 672 hdrAttr->userMode = (enum HdmiHdrUserMode)cntlr->cap.hdrUserMode; 673 hdrAttr->colorimetry = (enum HdmiHdrColormetry)cntlr->cap.hdrColorimetry; 674 } 675 HdmiAttrInit(struct HdmiCntlr * cntlr)676 static void HdmiAttrInit(struct HdmiCntlr *cntlr) 677 { 678 HdmiCommonAttrInit(cntlr); 679 HdmiVideoAttrInit(cntlr); 680 HdmiAudioAttrInit(cntlr); 681 HdmiHdrAttrInit(cntlr); 682 } 683 HdmiCntlrOpen(struct HdmiCntlr * cntlr)684 int32_t HdmiCntlrOpen(struct HdmiCntlr *cntlr) 685 { 686 int32_t ret; 687 688 if (cntlr == NULL) { 689 return HDF_ERR_INVALID_OBJECT; 690 } 691 HdmiInfoFrameInit(cntlr); 692 HdmiDdcInit(cntlr); 693 HdmiScdcInit(cntlr); 694 HdmiFrlInit(cntlr); 695 HdmiHdcpInit(cntlr); 696 HdmiCecInit(cntlr); 697 HdmiHdrInit(cntlr); 698 HdmiAttrInit(cntlr); 699 HdmiCntlrHardWareInit(cntlr); 700 /* HDCP on. */ 701 if ((cntlr->cap.baseCap.data & HDMI_CAP_HDCP_MARK) > 0) { 702 ret = HdmiHdcpOpen(cntlr->hdcp); 703 if (ret != HDF_SUCCESS) { 704 HdmiHdcpClose(cntlr->hdcp); 705 } 706 } 707 cntlr->state |= HDMI_CNTLR_STATE_OPEN; 708 return HDF_SUCCESS; 709 } 710 HdmiCntlrStart(struct HdmiCntlr * cntlr)711 int32_t HdmiCntlrStart(struct HdmiCntlr *cntlr) 712 { 713 if (cntlr == NULL || cntlr->ops == NULL) { 714 return HDF_ERR_INVALID_OBJECT; 715 } 716 717 HdmiCntlrLowPowerSet(cntlr, false); 718 /* select mode */ 719 HdmiCntlrModeSelect(cntlr); 720 HdmiCntlrAvmuteSet(cntlr, false); 721 722 if (cntlr->cap.baseCap.bits.hdr > 0 && cntlr->cap.baseCap.bits.frl > 0) { 723 HdmiFrlEnable(cntlr->frl, true); 724 } else { 725 /* TMDS Transfer. */ 726 if (cntlr->ops->phyOutputEnable != NULL) { 727 HdmiCntlrLock(cntlr); 728 cntlr->ops->phyOutputEnable(cntlr, true); 729 HdmiCntlrUnlock(cntlr); 730 } 731 } 732 733 HdmiCntlrAudioPathEnable(cntlr, true); 734 HdmiCntlrBlackDataSet(cntlr, false); 735 736 cntlr->state |= HDMI_CNTLR_STATE_START; 737 return HDF_SUCCESS; 738 } 739 HdmiCntlrStop(struct HdmiCntlr * cntlr)740 int32_t HdmiCntlrStop(struct HdmiCntlr *cntlr) 741 { 742 if (cntlr == NULL || cntlr->ops == NULL) { 743 return HDF_ERR_INVALID_OBJECT; 744 } 745 746 HdmiCntlrLock(cntlr); 747 if (cntlr->ops->audioPathEnable != NULL) { 748 cntlr->ops->audioPathEnable(cntlr, false); 749 } 750 if (cntlr->ops->avmuteSet != NULL) { 751 cntlr->ops->avmuteSet(cntlr, true); 752 } 753 if (cntlr->ops->blackDataSet != NULL) { 754 cntlr->ops->blackDataSet(cntlr, true); 755 } 756 HdmiFrlEnable(cntlr->frl, false); 757 if (cntlr->ops->phyOutputEnable != NULL) { 758 cntlr->ops->phyOutputEnable(cntlr, false); 759 } 760 HdmiCntlrUnlock(cntlr); 761 762 HdmiCntlrLowPowerSet(cntlr, true); 763 cntlr->state = HDMI_CNTLR_STATE_STOP; 764 return HDF_SUCCESS; 765 } 766 HdmiTmdsClockUpdate(struct HdmiVideoAttr * videoAttr,struct HdmiCommonAttr * commAttr)767 static void HdmiTmdsClockUpdate(struct HdmiVideoAttr *videoAttr, struct HdmiCommonAttr *commAttr) 768 { 769 /* 770 * Video at the default 24-bit color depth is carried at a TMDS clock rate equal to the pixel clock rate. 771 * YCBCB 4:2:0 video is carried at a TMDS clock rate equal to the 1/2 pixel clock rate. 772 */ 773 if (commAttr->colorSpace == HDMI_COLOR_SPACE_YCBCR420) { 774 videoAttr->tmdsClock = HDMI_MULTIPLE_0P5(videoAttr->pixelClock); 775 return; 776 } 777 778 /* 779 * The TMDS clock rate is ibcreased by the ratio of the pixel size to 24-bits: 780 * 24-bit mode: TMDS clock is 1.0 X pixel clock; 781 * 30-bit mode: TMDS clock is 1.25 X pixel clock; 782 * 36-bit mode: TMDS clock is 1.5 X pixel clock; 783 * 48-bit mode: TMDS clock is 2.0 X pixel clock; 784 */ 785 videoAttr->tmdsClock = videoAttr->pixelClock; 786 if (commAttr->colorSpace != HDMI_COLOR_SPACE_YCBCR422) { 787 if (commAttr->deepColor == HDMI_DEEP_COLOR_30BITS) { 788 videoAttr->tmdsClock = HDMI_MULTIPLE_1P25(videoAttr->pixelClock); 789 } else if (commAttr->deepColor == HDMI_DEEP_COLOR_36BITS) { 790 videoAttr->tmdsClock = HDMI_MULTIPLE_1P5(videoAttr->pixelClock); 791 } else if (commAttr->deepColor == HDMI_DEEP_COLOR_48BITS) { 792 videoAttr->tmdsClock = HDMI_MULTIPLE_2P0(videoAttr->pixelClock); 793 } 794 } else { 795 if ((commAttr->deepColor != HDMI_DEEP_COLOR_OFF) && (commAttr->deepColor != HDMI_DEEP_COLOR_24BITS)) { 796 HDF_LOGD("Y422 foce deepcolor 8bit"); 797 commAttr->deepColor = HDMI_DEEP_COLOR_24BITS; 798 } 799 if (videoAttr->timing == HDMI_VIDEO_TIMING_1440X480I60 || videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I50) { 800 HDF_LOGD("Y422 is not support at pal and ntsc, force adapt to rgb!"); 801 commAttr->colorSpace = HDMI_COLOR_SPACE_RGB; 802 } 803 } 804 } 805 HdmiYcbcr420FormatCheck(struct HdmiSinkDeviceCapability * sinkCap,struct HdmiVideoAttr * videoAttr)806 static bool HdmiYcbcr420FormatCheck(struct HdmiSinkDeviceCapability *sinkCap, struct HdmiVideoAttr *videoAttr) 807 { 808 uint32_t i; 809 enum HdmiVic vic; 810 811 vic = HdmiCommonGetVic(videoAttr->timing, videoAttr->aspect, false); 812 if (vic == HDMI_VIC_NONE) { 813 HDF_LOGD("Y420 not have supported vic."); 814 return false; 815 } 816 817 for (i = 0; i < sinkCap->y420Cap.SupportY420VicNum; i++) { 818 if (vic == sinkCap->y420Cap.SupportY420Format[i]) { 819 HDF_LOGD("Y420 supported vic is %d.", vic); 820 return true; 821 } 822 } 823 824 for (i = 0; i < sinkCap->y420Cap.onlySupportY420VicNum; i++) { 825 if (vic == sinkCap->y420Cap.onlySupportY420Format[i]) { 826 HDF_LOGD("Y420 supported vic is %d.", vic); 827 return true; 828 } 829 } 830 831 HDF_LOGD("Y420 have no supported vic."); 832 return false; 833 } 834 HdmiColorSpaceCheck(struct HdmiCntlr * cntlr,struct HdmiSinkDeviceCapability * sinkCap,uint32_t maxTmdsClk)835 static int32_t HdmiColorSpaceCheck( 836 struct HdmiCntlr *cntlr, struct HdmiSinkDeviceCapability *sinkCap, uint32_t maxTmdsClk) 837 { 838 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr); 839 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr); 840 union HdmiCap *cap = &(cntlr->cap.baseCap); 841 bool supportColorSpace = false; 842 843 if (videoAttr->pixelClock > maxTmdsClk && commAttr->colorSpace != HDMI_COLOR_SPACE_YCBCR420) { 844 return HDF_ERR_INVALID_PARAM; 845 } 846 847 switch (commAttr->colorSpace) { 848 case HDMI_COLOR_SPACE_RGB: 849 supportColorSpace = true; 850 if ((sinkCap->colorSpace.rgb444 && cap->bits.rgb444) == false) { 851 HDF_LOGD("sink or source not support RGB!"); 852 } 853 break; 854 case HDMI_COLOR_SPACE_YCBCR422: 855 supportColorSpace = sinkCap->colorSpace.ycbcr422 && cap->bits.ycbcr422; 856 break; 857 case HDMI_COLOR_SPACE_YCBCR444: 858 supportColorSpace = sinkCap->colorSpace.ycbcr444 && cap->bits.ycbcr444; 859 break; 860 case HDMI_COLOR_SPACE_YCBCR420: 861 supportColorSpace = cap->bits.ycbcr420 && HdmiYcbcr420FormatCheck(sinkCap, videoAttr); 862 break; 863 default: 864 HDF_LOGE("unknow color_space = %u!\n", commAttr->colorSpace); 865 break; 866 } 867 868 if (supportColorSpace != true) { 869 return HDF_ERR_INVALID_PARAM; 870 } 871 return HDF_SUCCESS; 872 } 873 HdmiDeepColor10bitsCheck(const struct HdmiSinkDeviceCapability * sinkCap,const struct HdmiCommonAttr * commAttr,const union HdmiCap * cap,uint32_t * tmdsClock,bool * supportDeepColor)874 static void HdmiDeepColor10bitsCheck(const struct HdmiSinkDeviceCapability *sinkCap, 875 const struct HdmiCommonAttr *commAttr, const union HdmiCap *cap, uint32_t *tmdsClock, bool *supportDeepColor) 876 { 877 uint32_t tmpTmdsClk = *tmdsClock; 878 879 switch (commAttr->colorSpace) { 880 case HDMI_COLOR_SPACE_RGB: 881 tmpTmdsClk = HDMI_MULTIPLE_1P25(tmpTmdsClk); 882 *supportDeepColor = (sinkCap->vsdbInfo.deepColor.dc30bit && cap->bits.deepColor10bits) ? true : false; 883 break; 884 case HDMI_COLOR_SPACE_YCBCR444: 885 tmpTmdsClk = HDMI_MULTIPLE_1P25(tmpTmdsClk); 886 *supportDeepColor = (sinkCap->vsdbInfo.deepColor.dc30bit && cap->bits.deepColor10bits && 887 sinkCap->vsdbInfo.deepColor.dcY444) ? 888 true : 889 false; 890 break; 891 case HDMI_COLOR_SPACE_YCBCR420: 892 tmpTmdsClk = HDMI_MULTIPLE_1P25(tmpTmdsClk); 893 *supportDeepColor = (sinkCap->hfVsdbInfo.dc.dc30bit && cap->bits.deepColor10bits) ? true : false; 894 break; 895 default: 896 /* Y422, ignore deepclr */ 897 *supportDeepColor = true; 898 break; 899 } 900 *tmdsClock = tmpTmdsClk; 901 } 902 HdmiDeepColor12bitsCheck(const struct HdmiSinkDeviceCapability * sinkCap,const struct HdmiCommonAttr * commAttr,const union HdmiCap * cap,uint32_t * tmdsClock,bool * supportDeepColor)903 static void HdmiDeepColor12bitsCheck(const struct HdmiSinkDeviceCapability *sinkCap, 904 const struct HdmiCommonAttr *commAttr, const union HdmiCap *cap, uint32_t *tmdsClock, bool *supportDeepColor) 905 { 906 uint32_t tmpTmdsClk = *tmdsClock; 907 908 switch (commAttr->colorSpace) { 909 case HDMI_COLOR_SPACE_RGB: 910 tmpTmdsClk = HDMI_MULTIPLE_1P5(tmpTmdsClk); 911 *supportDeepColor = (sinkCap->vsdbInfo.deepColor.dc36bit && cap->bits.deepColor12bits) ? true : false; 912 break; 913 case HDMI_COLOR_SPACE_YCBCR444: 914 tmpTmdsClk = HDMI_MULTIPLE_1P5(tmpTmdsClk); 915 *supportDeepColor = (sinkCap->vsdbInfo.deepColor.dc36bit && cap->bits.deepColor12bits && 916 sinkCap->vsdbInfo.deepColor.dcY444) ? 917 true : 918 false; 919 break; 920 case HDMI_COLOR_SPACE_YCBCR420: 921 tmpTmdsClk = HDMI_MULTIPLE_1P5(tmpTmdsClk); 922 *supportDeepColor = (sinkCap->hfVsdbInfo.dc.dc36bit && cap->bits.deepColor12bits) ? true : false; 923 break; 924 default: 925 /* Y422, ignore deepclr */ 926 *supportDeepColor = true; 927 break; 928 } 929 *tmdsClock = tmpTmdsClk; 930 } 931 HdmiDeepColorCheck(struct HdmiCntlr * cntlr,struct HdmiSinkDeviceCapability * sinkCap,uint32_t maxTmdsClk)932 static int32_t HdmiDeepColorCheck( 933 struct HdmiCntlr *cntlr, struct HdmiSinkDeviceCapability *sinkCap, uint32_t maxTmdsClk) 934 { 935 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr); 936 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr); 937 union HdmiCap *cap = &(cntlr->cap.baseCap); 938 uint32_t tmdsClock = videoAttr->pixelClock; 939 bool supportDeepColor = false; 940 941 if (commAttr->colorSpace == HDMI_COLOR_SPACE_YCBCR420) { 942 tmdsClock = HDMI_MULTIPLE_0P5(tmdsClock); 943 } 944 945 switch (commAttr->deepColor) { 946 case HDMI_DEEP_COLOR_30BITS: 947 HdmiDeepColor10bitsCheck(sinkCap, commAttr, cap, &tmdsClock, &supportDeepColor); 948 break; 949 case HDMI_DEEP_COLOR_36BITS: 950 HdmiDeepColor12bitsCheck(sinkCap, commAttr, cap, &tmdsClock, &supportDeepColor); 951 break; 952 default: 953 commAttr->deepColor = HDMI_DEEP_COLOR_24BITS; 954 supportDeepColor = true; 955 break; 956 } 957 958 if (supportDeepColor == false || tmdsClock > maxTmdsClk) { 959 return HDF_ERR_INVALID_PARAM; 960 } 961 videoAttr->tmdsClock = tmdsClock; 962 /* Y422 default 12bit output, deep_color force adapt to 8bit(24bit). */ 963 if (commAttr->colorSpace == HDMI_COLOR_SPACE_YCBCR422) { 964 if (videoAttr->timing == HDMI_VIDEO_TIMING_1440X480I60 || videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I50) { 965 HDF_LOGD("force change colorspace to RGB!"); 966 commAttr->colorSpace = HDMI_COLOR_SPACE_RGB; 967 } 968 if ((videoAttr->deepColor != HDMI_DEEP_COLOR_24BITS) && (videoAttr->deepColor != HDMI_DEEP_COLOR_OFF)) { 969 videoAttr->deepColor = HDMI_DEEP_COLOR_OFF; 970 HDF_LOGD("when Y422, deep_color not support 10/12bit!"); 971 } 972 } 973 return HDF_SUCCESS; 974 } 975 HdmiColorBitSelect(struct HdmiCntlr * cntlr)976 static int32_t HdmiColorBitSelect(struct HdmiCntlr *cntlr) 977 { 978 struct HdmiSinkDeviceCapability *sinkCap = NULL; 979 uint32_t maxTmdsClk = 0; 980 981 /* DVI mode, must set RGB and DEEP_COLOR_OFF */ 982 if (cntlr->attr.commAttr.enableHdmi == false) { 983 if (cntlr->attr.commAttr.colorSpace != HDMI_COLOR_SPACE_RGB) { 984 HDF_LOGE("DVI mode, the color space is not RGB!"); 985 return HDF_ERR_INVALID_PARAM; 986 } 987 cntlr->attr.commAttr.deepColor = HDMI_DEEP_COLOR_OFF; 988 cntlr->attr.videoAttr.tmdsClock = cntlr->attr.videoAttr.pixelClock; 989 return HDF_SUCCESS; 990 } 991 992 /* FRL mode. */ 993 if (cntlr->cap.baseCap.bits.hdr > 0) { 994 HdmiTmdsClockUpdate(&(cntlr->attr.videoAttr), &(cntlr->attr.commAttr)); 995 if (cntlr->attr.videoAttr.tmdsClock > HDMI_HDMI20_MAX_TMDS_RATE) { 996 HDF_LOGD("HDMI2.1, tmds clock exceed max."); 997 return HDF_SUCCESS; 998 } 999 } 1000 1001 sinkCap = HdmiGetSinkCapability(cntlr->hdmi); 1002 if (sinkCap == NULL) { 1003 HdmiTmdsClockUpdate(&(cntlr->attr.videoAttr), &(cntlr->attr.commAttr)); 1004 return HDF_SUCCESS; 1005 } 1006 1007 if (sinkCap->maxTmdsClk == 0) { 1008 /* use default clock. */ 1009 maxTmdsClk = cntlr->cap.defTmdsClock; 1010 } else { 1011 maxTmdsClk = (sinkCap->maxTmdsClk < cntlr->cap.maxTmdsClock) ? sinkCap->maxTmdsClk : cntlr->cap.maxTmdsClock; 1012 } 1013 /* MHz is converted to KHz */ 1014 maxTmdsClk *= 1000; 1015 1016 if (HdmiColorSpaceCheck(cntlr, sinkCap, maxTmdsClk) != HDF_SUCCESS) { 1017 return HDF_ERR_INVALID_PARAM; 1018 } 1019 if (HdmiDeepColorCheck(cntlr, sinkCap, maxTmdsClk) != HDF_SUCCESS) { 1020 return HDF_ERR_INVALID_PARAM; 1021 } 1022 return HDF_SUCCESS; 1023 } 1024 HdmiAudioAttrHandle(struct HdmiCntlr * cntlr)1025 static int32_t HdmiAudioAttrHandle(struct HdmiCntlr *cntlr) 1026 { 1027 struct HdmiAudioConfigInfo audioCfg = {0}; 1028 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr); 1029 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr); 1030 struct HdmiAudioAttr *audioAttr = &(cntlr->attr.audioAttr); 1031 int32_t ret; 1032 1033 audioCfg.downSample = audioAttr->downSample; 1034 audioCfg.channels = audioAttr->channels; 1035 audioCfg.bitDepth = audioAttr->bitDepth; 1036 audioCfg.sampleRate = audioAttr->sampleRate; 1037 audioCfg.ifType = audioAttr->ifType; 1038 audioCfg.enable = (commAttr->enableAudio) && (commAttr->enableHdmi); 1039 audioCfg.tmdsClock = videoAttr->tmdsClock; 1040 audioCfg.pixelRepeat = videoAttr->pixelRepeat; 1041 1042 HdmiCntlrAudioPathEnable(cntlr, false); 1043 HdmiCntlrAudioPathSet(cntlr, &audioCfg); 1044 ret = HdmiAudioInfoFrameSend(&(cntlr->infoFrame), ((commAttr->enableAudio) && (commAttr->audio))); 1045 HdmiCntlrAudioPathEnable(cntlr, true); 1046 return ret; 1047 } 1048 HdmiHdrModeCheck(struct HdmiCommonAttr * commAttr,struct HdmiVideoAttr * videoAttr,const struct HdmiHdrAttr * hdrAttr)1049 static void HdmiHdrModeCheck( 1050 struct HdmiCommonAttr *commAttr, struct HdmiVideoAttr *videoAttr, const struct HdmiHdrAttr *hdrAttr) 1051 { 1052 switch (hdrAttr->userMode) { 1053 case HDMI_HDR_USERMODE_DOLBY: 1054 videoAttr->yccQuantization = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; 1055 commAttr->colorSpace = HDMI_COLOR_SPACE_YCBCR444; 1056 videoAttr->tmdsClock = videoAttr->pixelClock; 1057 commAttr->deepColor = HDMI_DEEP_COLOR_24BITS; 1058 videoAttr->quantization = HDMI_QUANTIZATION_RANGE_DEFAULT; 1059 break; 1060 case HDMI_HDR_USERMODE_HDR10: 1061 if (hdrAttr->mode == HDMI_HDR_MODE_CEA_861_3) { 1062 if (hdrAttr->colorimetry > HDMI_HDR_COLORIMETRY_EXTENDED) { 1063 videoAttr->colorimetry = HDMI_COLORIMETRY_EXTENDED; 1064 videoAttr->extColorimetry = 1065 (enum HdmiExtendedColorimetry)(hdrAttr->colorimetry - HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_601); 1066 } else { 1067 videoAttr->colorimetry = (enum HdmiColorimetry)(hdrAttr->colorimetry); 1068 videoAttr->extColorimetry = HDMI_EXTENDED_COLORIMETRY_BUTT; 1069 } 1070 commAttr->xvyccMode = false; 1071 } 1072 break; 1073 default: 1074 break; 1075 } 1076 } 1077 HdmiFillVideoAttrFromHardwareStatus(struct HdmiVideoAttr * videoAttr,const struct HdmiHardwareStatus * hwStatus,struct HdmiCommonAttr * commAttr)1078 static void HdmiFillVideoAttrFromHardwareStatus( 1079 struct HdmiVideoAttr *videoAttr, const struct HdmiHardwareStatus *hwStatus, struct HdmiCommonAttr *commAttr) 1080 { 1081 bool rgb; 1082 bool aspectIs256; 1083 uint8_t vic; 1084 enum HdmiVsVideoFormat format; 1085 enum Hdmi4kVic vic4k; 1086 1087 rgb = ((hwStatus->videoStatus.rgb2Ycbcr) || 1088 ((!hwStatus->videoStatus.ycbcr2Rgb) && (hwStatus->videoStatus.outColorSpace == HDMI_COLOR_SPACE_RGB))); 1089 videoAttr->colorSpace = (rgb == true) ? HDMI_COLOR_SPACE_RGB : HDMI_COLOR_SPACE_YCBCR444; 1090 /* 1091 * avi[0]: Packet Type = 0x82 1092 * avi[1]: Version = 0x02 1093 * avi[2]: BIT[7:5]: 0, BIT[4:0]: Length = 0x0D 1094 * avi[3]: CheckSum 1095 * avi[4]: BIT[7]: Reserved, BIT[6:5]: RGB or YCbCr indicator, BIT[4]: Active information present 1096 * BIT[3:2]: Bar info data valid, BIT[1:0]: Scan information 1097 * avi[5]: BIT[7:6]: Colorimetry, BIT[5:4]: Picture aspect ratio, BIT[3:0]: Active format aspect ratio 1098 * avi[6]: BIT[7]: IT content, BIT[6:4]: Extended colorimetry, BIT[3:2]: Quantization range, 1099 * BIT[1:0]: Non-uniform picture scaling 1100 * avi[7]: BIT[7]: Reserved, BIT[6:0]: Video format identification code 1101 * avi[8]: BIT[7:6]: YCC quantization range, BIT[5:4]: Content type, BIT[3:0]: Picture repetition factor 1102 * ... 1103 */ 1104 if (hwStatus->infoFrameStatus.aviEnable) { 1105 vic = hwStatus->infoFrameStatus.avi[7]; 1106 /* 1107 * when the timing is 4096*2160, the aspect ratio in AVI infoFrame is 0 1108 * (but the real aspect ratio is 256:135<0x04>, the video_code is 0) 1109 * vsif[0]: Packet Type = 0x81 1110 * vsif[1]: Version = 0x01 1111 * vsif[2]: BIT[7:5]: 0, Bit[4:0]: Length, defines the length of HDMI vendor specific infoFrame payload. 1112 * vsif[3]: Checksum. 1113 * vsif[4]--vsif[6]: 24bit IEEE Registration Identifier(0x000C03)(least significant byte first). 1114 * vsif[7]: BIT[7]: reserved for future, BIT[6:5]: HDMI_Video_Format, BIT[4:0]: reserved. 1115 * vsif[8]: HDMI_VIC, 0x04: 4K*2K @24Hz(SMPTE). 1116 */ 1117 aspectIs256 = (((vic == 0) && (hwStatus->infoFrameStatus.vsif[8] == 0x04)) || 1118 ((vic >= HDMI_VIC_4096X2160P25_256_135) && (vic <= HDMI_VIC_4096X2160P60_256_135))); 1119 videoAttr->aspect = (aspectIs256 == true) ? HDMI_PICTURE_ASPECT_256_135 : 1120 ((hwStatus->infoFrameStatus.avi[5] >> 4) & 0x3); /* 4'b, BIT[2:1] */ 1121 videoAttr->activeAspect = hwStatus->infoFrameStatus.avi[5] & 0xf; 1122 videoAttr->colorimetry = (hwStatus->infoFrameStatus.avi[5] >> 6) & 0x3; /* 6'b, BIT[2:1] */ 1123 videoAttr->quantization = (hwStatus->infoFrameStatus.avi[6] >> 2) & 0x3; /* 2'b, BIT[2:1] */ 1124 videoAttr->extColorimetry = (hwStatus->infoFrameStatus.avi[6] >> 4) & 0x07; /* 4'b, BIT[3:1] */ 1125 videoAttr->yccQuantization = (hwStatus->infoFrameStatus.avi[8] >> 6) & 0x3; /* 6'b, BIT[2:1] */ 1126 videoAttr->pixelRepeat = (hwStatus->infoFrameStatus.avi[8] & 0xf) + 1; 1127 videoAttr->timing = HdmiCommonGetVideoTiming(vic, videoAttr->aspect); 1128 if ((!hwStatus->infoFrameStatus.vsifEnable) && (!vic)) { 1129 videoAttr->timing = HDMI_VIDEO_TIMING_NONE; 1130 } 1131 commAttr->quantization = (commAttr->colorSpace == HDMI_COLOR_SPACE_RGB) ? 1132 videoAttr->quantization : (videoAttr->yccQuantization + 1); 1133 } 1134 1135 videoAttr->_3dStruct = HDMI_VS_VIDEO_3D_BUTT; 1136 if (hwStatus->infoFrameStatus.vsifEnable) { 1137 format = (hwStatus->infoFrameStatus.vsif[7] >> 5) & 0x3; /* 5'b, BIT[2:1] */ 1138 if (format == HDMI_VS_VIDEO_FORMAT_4K) { 1139 vic4k = hwStatus->infoFrameStatus.vsif[8]; 1140 videoAttr->timing = HdmiCommonGetVideo4kTiming(vic4k); 1141 } else if (format == HDMI_VS_VIDEO_FORMAT_3D) { 1142 videoAttr->_3dStruct = (hwStatus->infoFrameStatus.vsif[8] >> 4) & 0xf; /* 4'b, BIT[4:1] */ 1143 } 1144 } 1145 } 1146 HdmiFillCommonAttrFromHardwareStatus(struct HdmiCommonAttr * commAttr,const struct HdmiHardwareStatus * hwStatus,const struct HdmiAttr * attr)1147 static void HdmiFillCommonAttrFromHardwareStatus( 1148 struct HdmiCommonAttr *commAttr, const struct HdmiHardwareStatus *hwStatus, const struct HdmiAttr *attr) 1149 { 1150 bool dolby = false; 1151 1152 switch (hwStatus->commonStatus.tmdsMode) { 1153 case HDMI_TMDS_MODE_HDMI_1_4: 1154 case HDMI_TMDS_MODE_HDMI_2_0: 1155 commAttr->enableHdmi = true; 1156 commAttr->enableVideo = true; 1157 break; 1158 case HDMI_TMDS_MODE_DVI: 1159 commAttr->enableHdmi = false; 1160 commAttr->enableVideo = true; 1161 break; 1162 default: 1163 commAttr->enableHdmi = false; 1164 commAttr->enableVideo = false; 1165 break; 1166 } 1167 1168 commAttr->enableAudio = (hwStatus->audioStatus.enable && hwStatus->infoFrameStatus.audioEnable); 1169 commAttr->avi = hwStatus->infoFrameStatus.aviEnable; 1170 commAttr->audio = hwStatus->infoFrameStatus.audioEnable; 1171 commAttr->xvyccMode = hwStatus->infoFrameStatus.gdbEnable; 1172 commAttr->deepColor = HdmiCommonColorDepthConvertToDeepClolor(hwStatus->videoStatus.outBitDepth); 1173 1174 /* color space is ycbcr444 when the hdr mode is dolby. */ 1175 dolby = ((attr->hdrAttr.userMode == HDMI_HDR_USERMODE_DOLBY) && (!hwStatus->videoStatus.rgb2Ycbcr) && 1176 (!hwStatus->videoStatus.ycbcr2Rgb) && (!hwStatus->videoStatus.ycbcr444422) && 1177 (!hwStatus->videoStatus.ycbcr422420) && (!hwStatus->videoStatus.ycbcr422444) && 1178 (!hwStatus->videoStatus.ycbcr420422)); 1179 commAttr->colorSpace = (dolby == true) ? HDMI_COLOR_SPACE_YCBCR444 : hwStatus->videoStatus.outColorSpace; 1180 } 1181 HdmiCommonAttrChanged(struct HdmiCommonAttr * curCommAttr,struct HdmiCommonAttr * commAttr)1182 static bool HdmiCommonAttrChanged(struct HdmiCommonAttr *curCommAttr, struct HdmiCommonAttr *commAttr) 1183 { 1184 bool change; 1185 1186 change = (commAttr->enableHdmi != curCommAttr->enableHdmi) || (commAttr->colorSpace != curCommAttr->colorSpace) || 1187 (commAttr->xvyccMode != curCommAttr->xvyccMode) || (commAttr->avi != curCommAttr->avi) || 1188 (commAttr->quantization != curCommAttr->quantization); 1189 1190 if (change == true) { 1191 return true; 1192 } 1193 1194 if (((commAttr->deepColor == HDMI_DEEP_COLOR_OFF) || (commAttr->deepColor == HDMI_DEEP_COLOR_24BITS)) && 1195 ((curCommAttr->deepColor == HDMI_DEEP_COLOR_OFF) || (curCommAttr->deepColor == HDMI_DEEP_COLOR_24BITS))) { 1196 HDF_LOGI("deep color not change: %u", curCommAttr->deepColor); 1197 } else if (commAttr->deepColor != curCommAttr->deepColor) { 1198 return true; 1199 } 1200 return false; 1201 } 1202 HdmiVideoAttrChanged(struct HdmiVideoAttr * curVideoAttr,struct HdmiVideoAttr * videoAttr)1203 static bool HdmiVideoAttrChanged(struct HdmiVideoAttr *curVideoAttr, struct HdmiVideoAttr *videoAttr) 1204 { 1205 bool change; 1206 1207 change = (videoAttr->timing != curVideoAttr->timing) || (videoAttr->colorSpace != curVideoAttr->colorSpace) || 1208 (videoAttr->_3dStruct != curVideoAttr->_3dStruct) || (videoAttr->pixelRepeat != curVideoAttr->pixelRepeat) || 1209 (videoAttr->colorimetry != curVideoAttr->colorimetry) || 1210 (videoAttr->extColorimetry != curVideoAttr->extColorimetry) || 1211 (videoAttr->quantization != curVideoAttr->quantization) || 1212 (videoAttr->yccQuantization != curVideoAttr->yccQuantization) || (videoAttr->aspect != curVideoAttr->aspect); 1213 return change; 1214 } 1215 HdmiVedioAttrHandle(struct HdmiCntlr * cntlr,struct HdmiHardwareStatus * hwStatus)1216 static int32_t HdmiVedioAttrHandle(struct HdmiCntlr *cntlr, struct HdmiHardwareStatus *hwStatus) 1217 { 1218 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr); 1219 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr); 1220 struct HdmiCommonAttr curCommAttr = {0}; 1221 struct HdmiVideoAttr curVideoAttr = {0}; 1222 int32_t ret; 1223 1224 /* support HDR. */ 1225 if (cntlr->cap.baseCap.bits.hdr > 0) { 1226 HdmiHdrModeCheck(commAttr, videoAttr, &(cntlr->attr.hdrAttr)); 1227 } 1228 1229 /* support FRL. */ 1230 if (cntlr->cap.baseCap.bits.frl > 0) { 1231 ret = HdmiFrlModeSelect(cntlr->frl); 1232 if (ret != HDF_SUCCESS) { 1233 return ret; 1234 } 1235 } 1236 1237 HdmiFillCommonAttrFromHardwareStatus(&curCommAttr, hwStatus, &(cntlr->attr)); 1238 HdmiFillVideoAttrFromHardwareStatus(&curVideoAttr, hwStatus, &curCommAttr); 1239 if (HdmiCommonAttrChanged(&curCommAttr, commAttr) == false && 1240 HdmiVideoAttrChanged(&curVideoAttr, videoAttr) == false && HdmiFrlModeChanged(cntlr->frl) == false) { 1241 HDF_LOGI("video and common attr is not changed."); 1242 return HDF_SUCCESS; 1243 } 1244 1245 if (commAttr->enableVideo == true) { 1246 HdmiCntlrVideoPathSet(cntlr, videoAttr); 1247 } 1248 1249 (void)HdmiAviInfoFrameSend(&(cntlr->infoFrame), (commAttr->enableHdmi && commAttr->avi)); 1250 (void)HdmiVsInfoFrameSend(&(cntlr->infoFrame), commAttr->enableHdmi, commAttr->vsifDolby); 1251 /* the drm infoFrame is stop because software was reset in videopath, so re-enable it if the mode is HDR10. */ 1252 if (cntlr->cap.baseCap.bits.hdr > 0) { 1253 if (cntlr->attr.hdrAttr.mode == HDMI_HDR_MODE_CEA_861_3) { 1254 (void)HdmiDrmInfoFrameSend(&(cntlr->infoFrame), false); 1255 (void)HdmiDrmInfoFrameSend(&(cntlr->infoFrame), true); 1256 } 1257 } 1258 return HDF_SUCCESS; 1259 } 1260 HdmiAttrUpdate(struct HdmiCntlr * cntlr)1261 static void HdmiAttrUpdate(struct HdmiCntlr *cntlr) 1262 { 1263 struct HdmiHardwareStatus hwStatus = {0}; 1264 1265 if (HdmiColorBitSelect(cntlr) != HDF_SUCCESS) { 1266 HDF_LOGD("attr update: color bit select fail."); 1267 return; 1268 } 1269 1270 if (cntlr->ops->hardWareStatusGet == NULL) { 1271 return; 1272 } 1273 1274 HdmiCntlrLock(cntlr); 1275 cntlr->ops->hardWareStatusGet(cntlr, &hwStatus); 1276 HdmiCntlrUnlock(cntlr); 1277 1278 if (HdmiAudioAttrHandle(cntlr) != HDF_SUCCESS) { 1279 HDF_LOGD("audio attr check fail"); 1280 return; 1281 } 1282 if (HdmiVedioAttrHandle(cntlr, &hwStatus) != HDF_SUCCESS) { 1283 HDF_LOGD("vedio attr check fail"); 1284 } 1285 } 1286 HdmiCntlrDeepColorSet(struct HdmiCntlr * cntlr,enum HdmiDeepColor color)1287 int32_t HdmiCntlrDeepColorSet(struct HdmiCntlr *cntlr, enum HdmiDeepColor color) 1288 { 1289 if (cntlr == NULL || cntlr->ops == NULL) { 1290 return HDF_ERR_INVALID_OBJECT; 1291 } 1292 1293 if (cntlr->attr.commAttr.colorSpace == HDMI_COLOR_SPACE_YCBCR422) { 1294 if (color != HDMI_DEEP_COLOR_24BITS && color != HDMI_DEEP_COLOR_OFF) { 1295 HDF_LOGE("not support deepcolor %u when colorspace is ycbcr422.", color); 1296 return HDF_ERR_INVALID_PARAM; 1297 } 1298 } 1299 1300 /* if the current hdmi mode is dolby, deep color set is invalid. */ 1301 if (cntlr->attr.hdrAttr.mode == HDMI_HDR_MODE_DOLBY_NORMAL || 1302 cntlr->attr.hdrAttr.mode == HDMI_HDR_MODE_DOLBY_TUNNELING) { 1303 HDF_LOGD("don't change deepcolor when dolby mode is %u.", cntlr->attr.hdrAttr.mode); 1304 return HDF_ERR_NOT_SUPPORT; 1305 } 1306 1307 cntlr->attr.commAttr.deepColor = color; 1308 HdmiCntlrAvmuteSet(cntlr, true); 1309 HdmiAttrUpdate(cntlr); 1310 HdmiCntlrAvmuteSet(cntlr, false); 1311 return HDF_SUCCESS; 1312 } 1313 HdmiCntlrDeepColorGet(struct HdmiCntlr * cntlr,enum HdmiDeepColor * color)1314 int32_t HdmiCntlrDeepColorGet(struct HdmiCntlr *cntlr, enum HdmiDeepColor *color) 1315 { 1316 if (cntlr == NULL || cntlr->ops == NULL) { 1317 return HDF_ERR_INVALID_OBJECT; 1318 } 1319 if (color == NULL) { 1320 return HDF_ERR_INVALID_PARAM; 1321 } 1322 1323 *color = cntlr->attr.commAttr.deepColor; 1324 return HDF_SUCCESS; 1325 } 1326 HdmiCntlrSetVideoAttribute(struct HdmiCntlr * cntlr,const struct HdmiVideoAttr * attr)1327 int32_t HdmiCntlrSetVideoAttribute(struct HdmiCntlr *cntlr, const struct HdmiVideoAttr *attr) 1328 { 1329 struct HdmiHardwareStatus hwStatus = {0}; 1330 1331 if (cntlr == NULL || cntlr->ops == NULL) { 1332 return HDF_ERR_INVALID_OBJECT; 1333 } 1334 if (attr == NULL) { 1335 return HDF_ERR_INVALID_PARAM; 1336 } 1337 1338 cntlr->attr.videoAttr = *attr; 1339 1340 if (cntlr->ops->hardWareStatusGet == NULL) { 1341 return HDF_ERR_NOT_SUPPORT; 1342 } 1343 1344 HdmiCntlrLock(cntlr); 1345 cntlr->ops->hardWareStatusGet(cntlr, &hwStatus); 1346 HdmiCntlrUnlock(cntlr); 1347 return HdmiVedioAttrHandle(cntlr, &hwStatus); 1348 } 1349 HdmiCntlrSetAudioAttribute(struct HdmiCntlr * cntlr,const struct HdmiAudioAttr * attr)1350 int32_t HdmiCntlrSetAudioAttribute(struct HdmiCntlr *cntlr, const struct HdmiAudioAttr *attr) 1351 { 1352 if (cntlr == NULL || cntlr->ops == NULL) { 1353 return HDF_ERR_INVALID_OBJECT; 1354 } 1355 if (attr == NULL) { 1356 return HDF_ERR_INVALID_PARAM; 1357 } 1358 1359 cntlr->attr.audioAttr = *attr; 1360 return HdmiAudioAttrHandle(cntlr); 1361 } 1362 HdmiCntlrSetHdrAttribute(struct HdmiCntlr * cntlr,struct HdmiHdrAttr * attr)1363 int32_t HdmiCntlrSetHdrAttribute(struct HdmiCntlr *cntlr, struct HdmiHdrAttr *attr) 1364 { 1365 if (cntlr == NULL || cntlr->ops == NULL) { 1366 return HDF_ERR_INVALID_OBJECT; 1367 } 1368 if (attr == NULL) { 1369 return HDF_ERR_INVALID_PARAM; 1370 } 1371 1372 return HdmiHdrAttrHandle(cntlr->hdr, attr); 1373 } 1374 HdmiCntlrInfoFrameGet(struct HdmiCntlr * cntlr,enum HdmiPacketType type,union HdmiInfoFrameInfo * frame)1375 int32_t HdmiCntlrInfoFrameGet(struct HdmiCntlr *cntlr, enum HdmiPacketType type, union HdmiInfoFrameInfo *frame) 1376 { 1377 if (cntlr == NULL) { 1378 return HDF_ERR_INVALID_OBJECT; 1379 } 1380 return HdmiInfoFrameGetInfo(&(cntlr->infoFrame), type, frame); 1381 } 1382 HdmiCntlrInfoFrameSet(struct HdmiCntlr * cntlr,enum HdmiPacketType type,union HdmiInfoFrameInfo * frame)1383 int32_t HdmiCntlrInfoFrameSet(struct HdmiCntlr *cntlr, enum HdmiPacketType type, union HdmiInfoFrameInfo *frame) 1384 { 1385 if (cntlr == NULL || cntlr->ops == NULL) { 1386 return HDF_ERR_INVALID_OBJECT; 1387 } 1388 if (frame == NULL) { 1389 return HDF_ERR_INVALID_PARAM; 1390 } 1391 return HdmiInfoFrameSetInfo(&(cntlr->infoFrame), type, frame); 1392 } 1393 HdmiCntlrRegisterHpdCallbackFunc(struct HdmiCntlr * cntlr,struct HdmiHpdCallbackInfo * callback)1394 int32_t HdmiCntlrRegisterHpdCallbackFunc(struct HdmiCntlr *cntlr, struct HdmiHpdCallbackInfo *callback) 1395 { 1396 if (cntlr == NULL) { 1397 return HDF_ERR_INVALID_OBJECT; 1398 } 1399 if (callback == NULL) { 1400 return HDF_ERR_INVALID_PARAM; 1401 } 1402 1403 cntlr->event.callback.data = callback->data; 1404 cntlr->event.callback.callbackFunc = callback->callbackFunc; 1405 return HDF_SUCCESS; 1406 } 1407 HdmiCntlrUnregisterHpdCallbackFunc(struct HdmiCntlr * cntlr)1408 int32_t HdmiCntlrUnregisterHpdCallbackFunc(struct HdmiCntlr *cntlr) 1409 { 1410 if (cntlr == NULL) { 1411 return HDF_ERR_INVALID_OBJECT; 1412 } 1413 cntlr->event.callback.data = NULL; 1414 cntlr->event.callback.callbackFunc = NULL; 1415 return HDF_SUCCESS; 1416 } 1417 HdmiCntlrClose(struct HdmiCntlr * cntlr)1418 void HdmiCntlrClose(struct HdmiCntlr *cntlr) 1419 { 1420 if (cntlr == NULL || cntlr->ops == NULL) { 1421 return; 1422 } 1423 1424 if ((cntlr->state & HDMI_CNTLR_STATE_START) > 0) { 1425 HdmiCntlrStop(cntlr); 1426 } 1427 1428 HdmiInfoFrameDeInit(cntlr); 1429 HdmiDdcDeinit(cntlr); 1430 HdmiScdcDeinit(cntlr); 1431 HdmiFrlDeinit(cntlr); 1432 HdmiHdcpDeinit(cntlr); 1433 HdmiCecDeinit(cntlr); 1434 HdmiHdrDeinit(cntlr); 1435 cntlr->state = HDMI_CNTLR_STATE_CLOSE; 1436 } 1437