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