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(struct HdmiCntlr *cntlr, struct DeviceResourceIface *drsOps,
354 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(struct HdmiCntlr *cntlr, struct DeviceResourceIface *drsOps,
403 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(struct HdmiCntlr *cntlr, struct DeviceResourceIface *drsOps,
438 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 &&
568 cntlr->cap.baseCap.bits.frl > 0) {
569 return;
570 }
571
572 if (cntlr->cap.baseCap.bits.scdc > 0) {
573 ret = HdmiScdcFillScrambleCap(cntlr->scdc, &scramble, &tmdsMode);
574 if (ret != HDF_SUCCESS) {
575 return;
576 }
577 } else {
578 tmdsMode = (commAttr->enableHdmi == true) ? HDMI_TMDS_MODE_HDMI_1_4 : HDMI_TMDS_MODE_DVI;
579 }
580
581 cntlr->tmdsMode = tmdsMode;
582 HdmiCntlrTmdsModeSet(cntlr, tmdsMode);
583 HdmiCntlrReset(cntlr);
584
585 if (cntlr->cap.baseCap.bits.scdc > 0 &&
586 HdmiEdidScdcSupport(cntlr->hdmi) == true) {
587 ret = HdmiScdcScrambleGet(cntlr->scdc, &curScramble);
588 if (ret != HDF_SUCCESS) {
589 return;
590 }
591 if (scramble.sinkScramble != curScramble.sinkScramble ||
592 scramble.sourceScramble != curScramble.sourceScramble ||
593 scramble.tmdsBitClockRatio40 != curScramble.tmdsBitClockRatio40) {
594 (void)HdmiScdcScrambleSet(cntlr->scdc, &scramble);
595 }
596 }
597 }
598
HdmiCommonAttrInit(struct HdmiCntlr * cntlr)599 static void HdmiCommonAttrInit(struct HdmiCntlr *cntlr)
600 {
601 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr);
602
603 commAttr->enableHdmi = true;
604 commAttr->enableVideo = true;
605 commAttr->enableAudio = true;
606 commAttr->audio = true;
607 commAttr->avi = true;
608 commAttr->hdcpMode = HDMI_HDCP_MODE_1_4;
609 commAttr->colorSpace = (enum HdmiColorSpace)cntlr->cap.colorSpace;
610 commAttr->quantization = (enum HdmiQuantizationRange)cntlr->cap.quantization;
611 }
612
HdmiVideoAttrInit(struct HdmiCntlr * cntlr)613 static void HdmiVideoAttrInit(struct HdmiCntlr *cntlr)
614 {
615 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr);
616 bool colorimetry601;
617
618 videoAttr->colorSpace = (enum HdmiColorSpace)cntlr->cap.colorSpace;
619 videoAttr->colorimetry = (enum HdmiColorimetry)cntlr->cap.colorimetry;
620 videoAttr->timing = (enum HdmiVideoTiming)cntlr->cap.videoTiming;
621 colorimetry601 = ((videoAttr->timing == HDMI_VIDEO_TIMING_720X480P60) ||
622 (videoAttr->timing == HDMI_VIDEO_TIMING_720X576P50) ||
623 (videoAttr->timing == HDMI_VIDEO_TIMING_1440X240P60) ||
624 (videoAttr->timing == HDMI_VIDEO_TIMING_1440X480I60) ||
625 (videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I50) ||
626 (videoAttr->timing == HDMI_VIDEO_TIMING_1440X576P50) ||
627 (videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I60));
628
629 if (videoAttr->timing == HDMI_VIDEO_TIMING_640X480P60) {
630 videoAttr->colorimetry = HDMI_COLORIMETRY_ITU709;
631 videoAttr->aspect = HDMI_PICTURE_ASPECT_4_3;
632 } else if (colorimetry601 == true) {
633 videoAttr->colorimetry = HDMI_COLORIMETRY_ITU601;
634 videoAttr->aspect = HDMI_PICTURE_ASPECT_4_3;
635 } else if (videoAttr->timing <= HDMI_VIDEO_TIMING_4096X2160P120 &&
636 videoAttr->timing >= HDMI_VIDEO_TIMING_4096X2160P24) {
637 videoAttr->colorimetry = HDMI_COLORIMETRY_ITU709;
638 videoAttr->aspect = HDMI_PICTURE_ASPECT_256_135;
639 } else {
640 videoAttr->colorimetry = HDMI_COLORIMETRY_ITU709;
641 videoAttr->aspect = HDMI_PICTURE_ASPECT_16_9;
642 }
643
644 videoAttr->pixelRepeat = 1;
645 if (videoAttr->timing == HDMI_VIDEO_TIMING_1440X480I60 ||
646 videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I50) {
647 videoAttr->pixelRepeat = 2;
648 }
649
650 if (videoAttr->timing <= HDMI_VIDEO_TIMING_640X480P60) {
651 videoAttr->quantization = HDMI_QUANTIZATION_RANGE_DEFAULT;
652 } else {
653 videoAttr->yccQuantization = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
654 }
655
656 if (videoAttr->timing != HDMI_VIDEO_TIMING_NONE &&
657 videoAttr->timing != HDMI_VIDEO_TIMING_640X480P60) {
658 videoAttr->colorSpace = HDMI_COLOR_SPACE_YCBCR444;
659 } else {
660 videoAttr->colorSpace = HDMI_COLOR_SPACE_RGB;
661 }
662
663 videoAttr->_3dStruct = HDMI_VS_VIDEO_3D_BUTT;
664 videoAttr->activeAspect = HDMI_ACTIVE_FORMAT_ASPECT_PICTURE;
665 }
666
HdmiAudioAttrInit(struct HdmiCntlr * cntlr)667 static void HdmiAudioAttrInit(struct HdmiCntlr *cntlr)
668 {
669 struct HdmiAudioAttr *audioAttr = &(cntlr->attr.audioAttr);
670
671 audioAttr->ifType = (enum HdmiAudioInterfaceType)cntlr->cap.audioIfType;
672 audioAttr->bitDepth = (enum HdmiAudioBitDepth)cntlr->cap.audioBitDepth;
673 audioAttr->sampleRate = (enum HdmiSampleRate)cntlr->cap.audioSampleRate;
674 audioAttr->channels = (enum HdmiAudioFormatChannel)cntlr->cap.audioChannels;
675 }
676
HdmiHdrAttrInit(struct HdmiCntlr * cntlr)677 static void HdmiHdrAttrInit(struct HdmiCntlr *cntlr)
678 {
679 struct HdmiHdrAttr *hdrAttr = &(cntlr->attr.hdrAttr);
680
681 hdrAttr->userMode = (enum HdmiHdrUserMode)cntlr->cap.hdrUserMode;
682 hdrAttr->colorimetry = (enum HdmiHdrColormetry)cntlr->cap.hdrColorimetry;
683 }
684
HdmiAttrInit(struct HdmiCntlr * cntlr)685 static void HdmiAttrInit(struct HdmiCntlr *cntlr)
686 {
687 HdmiCommonAttrInit(cntlr);
688 HdmiVideoAttrInit(cntlr);
689 HdmiAudioAttrInit(cntlr);
690 HdmiHdrAttrInit(cntlr);
691 }
692
HdmiCntlrOpen(struct HdmiCntlr * cntlr)693 int32_t HdmiCntlrOpen(struct HdmiCntlr *cntlr)
694 {
695 int32_t ret;
696
697 if (cntlr == NULL) {
698 return HDF_ERR_INVALID_OBJECT;
699 }
700 HdmiInfoFrameInit(cntlr);
701 HdmiDdcInit(cntlr);
702 HdmiScdcInit(cntlr);
703 HdmiFrlInit(cntlr);
704 HdmiHdcpInit(cntlr);
705 HdmiCecInit(cntlr);
706 HdmiHdrInit(cntlr);
707 HdmiAttrInit(cntlr);
708 HdmiCntlrHardWareInit(cntlr);
709 /* HDCP on. */
710 if ((cntlr->cap.baseCap.data & HDMI_CAP_HDCP_MARK) > 0) {
711 ret = HdmiHdcpOpen(cntlr->hdcp);
712 if (ret != HDF_SUCCESS) {
713 HdmiHdcpClose(cntlr->hdcp);
714 }
715 }
716 cntlr->state |= HDMI_CNTLR_STATE_OPEN;
717 return HDF_SUCCESS;
718 }
719
HdmiCntlrStart(struct HdmiCntlr * cntlr)720 int32_t HdmiCntlrStart(struct HdmiCntlr *cntlr)
721 {
722 if (cntlr == NULL || cntlr->ops == NULL) {
723 return HDF_ERR_INVALID_OBJECT;
724 }
725
726 HdmiCntlrLowPowerSet(cntlr, false);
727 /* select mode */
728 HdmiCntlrModeSelect(cntlr);
729 HdmiCntlrAvmuteSet(cntlr, false);
730
731 if (cntlr->cap.baseCap.bits.hdr > 0 &&
732 cntlr->cap.baseCap.bits.frl > 0) {
733 HdmiFrlEnable(cntlr->frl, true);
734 } else {
735 /* TMDS Transfer. */
736 if (cntlr->ops->phyOutputEnable != NULL) {
737 HdmiCntlrLock(cntlr);
738 cntlr->ops->phyOutputEnable(cntlr, true);
739 HdmiCntlrUnlock(cntlr);
740 }
741 }
742
743 HdmiCntlrAudioPathEnable(cntlr, true);
744 HdmiCntlrBlackDataSet(cntlr, false);
745
746 cntlr->state |= HDMI_CNTLR_STATE_START;
747 return HDF_SUCCESS;
748 }
749
HdmiCntlrStop(struct HdmiCntlr * cntlr)750 int32_t HdmiCntlrStop(struct HdmiCntlr *cntlr)
751 {
752 if (cntlr == NULL || cntlr->ops == NULL) {
753 return HDF_ERR_INVALID_OBJECT;
754 }
755
756 HdmiCntlrLock(cntlr);
757 if (cntlr->ops->audioPathEnable != NULL) {
758 cntlr->ops->audioPathEnable(cntlr, false);
759 }
760 if (cntlr->ops->avmuteSet != NULL) {
761 cntlr->ops->avmuteSet(cntlr, true);
762 }
763 if (cntlr->ops->blackDataSet != NULL) {
764 cntlr->ops->blackDataSet(cntlr, true);
765 }
766 HdmiFrlEnable(cntlr->frl, false);
767 if (cntlr->ops->phyOutputEnable != NULL) {
768 cntlr->ops->phyOutputEnable(cntlr, false);
769 }
770 HdmiCntlrUnlock(cntlr);
771
772 HdmiCntlrLowPowerSet(cntlr, true);
773 cntlr->state = HDMI_CNTLR_STATE_STOP;
774 return HDF_SUCCESS;
775 }
776
HdmiTmdsClockUpdate(struct HdmiVideoAttr * videoAttr,struct HdmiCommonAttr * commAttr)777 static void HdmiTmdsClockUpdate(struct HdmiVideoAttr *videoAttr, struct HdmiCommonAttr *commAttr)
778 {
779 /*
780 * Video at the default 24-bit color depth is carried at a TMDS clock rate equal to the pixel clock rate.
781 * YCBCB 4:2:0 video is carried at a TMDS clock rate equal to the 1/2 pixel clock rate.
782 */
783 if (commAttr->colorSpace == HDMI_COLOR_SPACE_YCBCR420) {
784 videoAttr->tmdsClock = HDMI_MULTIPLE_0P5(videoAttr->pixelClock);
785 return;
786 }
787
788 /*
789 * The TMDS clock rate is ibcreased by the ratio of the pixel size to 24-bits:
790 * 24-bit mode: TMDS clock is 1.0 X pixel clock;
791 * 30-bit mode: TMDS clock is 1.25 X pixel clock;
792 * 36-bit mode: TMDS clock is 1.5 X pixel clock;
793 * 48-bit mode: TMDS clock is 2.0 X pixel clock;
794 */
795 videoAttr->tmdsClock = videoAttr->pixelClock;
796 if (commAttr->colorSpace != HDMI_COLOR_SPACE_YCBCR422) {
797 if (commAttr->deepColor == HDMI_DEEP_COLOR_30BITS) {
798 videoAttr->tmdsClock = HDMI_MULTIPLE_1P25(videoAttr->pixelClock);
799 } else if (commAttr->deepColor == HDMI_DEEP_COLOR_36BITS) {
800 videoAttr->tmdsClock = HDMI_MULTIPLE_1P5(videoAttr->pixelClock);
801 } else if (commAttr->deepColor == HDMI_DEEP_COLOR_48BITS) {
802 videoAttr->tmdsClock = HDMI_MULTIPLE_2P0(videoAttr->pixelClock);
803 }
804 } else {
805 if ((commAttr->deepColor != HDMI_DEEP_COLOR_OFF) &&
806 (commAttr->deepColor != HDMI_DEEP_COLOR_24BITS)) {
807 HDF_LOGD("Y422 foce deepcolor 8bit");
808 commAttr->deepColor = HDMI_DEEP_COLOR_24BITS;
809 }
810 if (videoAttr->timing == HDMI_VIDEO_TIMING_1440X480I60 ||
811 videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I50) {
812 HDF_LOGD("Y422 is not support at pal and ntsc, force adapt to rgb!");
813 commAttr->colorSpace = HDMI_COLOR_SPACE_RGB;
814 }
815 }
816 }
817
HdmiYcbcr420FormatCheck(struct HdmiSinkDeviceCapability * sinkCap,struct HdmiVideoAttr * videoAttr)818 static bool HdmiYcbcr420FormatCheck(struct HdmiSinkDeviceCapability *sinkCap, struct HdmiVideoAttr *videoAttr)
819 {
820 uint32_t i;
821 enum HdmiVic vic;
822
823 vic = HdmiCommonGetVic(videoAttr->timing, videoAttr->aspect, false);
824 if (vic == HDMI_VIC_NONE) {
825 HDF_LOGD("Y420 not have supported vic.");
826 return false;
827 }
828
829 for (i = 0; i < sinkCap->y420Cap.SupportY420VicNum; i++) {
830 if (vic == sinkCap->y420Cap.SupportY420Format[i]) {
831 HDF_LOGD("Y420 supported vic is %d.", vic);
832 return true;
833 }
834 }
835
836 for (i = 0; i < sinkCap->y420Cap.onlySupportY420VicNum; i++) {
837 if (vic == sinkCap->y420Cap.onlySupportY420Format[i]) {
838 HDF_LOGD("Y420 supported vic is %d.", vic);
839 return true;
840 }
841 }
842
843 HDF_LOGD("Y420 have no supported vic.");
844 return false;
845 }
846
HdmiColorSpaceCheck(struct HdmiCntlr * cntlr,struct HdmiSinkDeviceCapability * sinkCap,uint32_t maxTmdsClk)847 static int32_t HdmiColorSpaceCheck(struct HdmiCntlr *cntlr, struct HdmiSinkDeviceCapability *sinkCap,
848 uint32_t maxTmdsClk)
849 {
850 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr);
851 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr);
852 union HdmiCap *cap = &(cntlr->cap.baseCap);
853 bool supportColorSpace = false;
854
855 if (videoAttr->pixelClock > maxTmdsClk &&
856 commAttr->colorSpace != HDMI_COLOR_SPACE_YCBCR420) {
857 return HDF_ERR_INVALID_PARAM;
858 }
859
860 switch (commAttr->colorSpace) {
861 case HDMI_COLOR_SPACE_RGB:
862 supportColorSpace = true;
863 if ((sinkCap->colorSpace.rgb444 && cap->bits.rgb444) == false) {
864 HDF_LOGD("sink or source not support RGB!");
865 }
866 break;
867 case HDMI_COLOR_SPACE_YCBCR422:
868 supportColorSpace = sinkCap->colorSpace.ycbcr422 && cap->bits.ycbcr422;
869 break;
870 case HDMI_COLOR_SPACE_YCBCR444:
871 supportColorSpace = sinkCap->colorSpace.ycbcr444 && cap->bits.ycbcr444;
872 break;
873 case HDMI_COLOR_SPACE_YCBCR420:
874 supportColorSpace = cap->bits.ycbcr420 && HdmiYcbcr420FormatCheck(sinkCap, videoAttr);
875 break;
876 default:
877 HDF_LOGE("unknow color_space = %u!\n", commAttr->colorSpace);
878 break;
879 }
880
881 if (supportColorSpace != true) {
882 return HDF_ERR_INVALID_PARAM;
883 }
884 return HDF_SUCCESS;
885 }
886
HdmiDeepColor10bitsCheck(struct HdmiSinkDeviceCapability * sinkCap,struct HdmiCommonAttr * commAttr,union HdmiCap * cap,uint32_t * tmdsClock,bool * supportDeepColor)887 static void HdmiDeepColor10bitsCheck(struct HdmiSinkDeviceCapability *sinkCap, struct HdmiCommonAttr *commAttr,
888 union HdmiCap *cap, uint32_t *tmdsClock, bool *supportDeepColor)
889 {
890 uint32_t tmpTmdsClk = *tmdsClock;
891
892 switch (commAttr->colorSpace) {
893 case HDMI_COLOR_SPACE_RGB:
894 tmpTmdsClk = HDMI_MULTIPLE_1P25(tmpTmdsClk);
895 *supportDeepColor = (sinkCap->vsdbInfo.deepColor.dc30bit && cap->bits.deepColor10bits) ? true : false;
896 break;
897 case HDMI_COLOR_SPACE_YCBCR444:
898 tmpTmdsClk = HDMI_MULTIPLE_1P25(tmpTmdsClk);
899 *supportDeepColor = (sinkCap->vsdbInfo.deepColor.dc30bit && cap->bits.deepColor10bits &&
900 sinkCap->vsdbInfo.deepColor.dcY444) ? true : false;
901 break;
902 case HDMI_COLOR_SPACE_YCBCR420:
903 tmpTmdsClk = HDMI_MULTIPLE_1P25(tmpTmdsClk);
904 *supportDeepColor = (sinkCap->hfVsdbInfo.dc.dc30bit && cap->bits.deepColor10bits) ? true : false;
905 break;
906 default:
907 /* Y422, ignore deepclr */
908 *supportDeepColor = true;
909 break;
910 }
911 *tmdsClock = tmpTmdsClk;
912 }
913
HdmiDeepColor12bitsCheck(struct HdmiSinkDeviceCapability * sinkCap,struct HdmiCommonAttr * commAttr,union HdmiCap * cap,uint32_t * tmdsClock,bool * supportDeepColor)914 static void HdmiDeepColor12bitsCheck(struct HdmiSinkDeviceCapability *sinkCap, struct HdmiCommonAttr *commAttr,
915 union HdmiCap *cap, uint32_t *tmdsClock, bool *supportDeepColor)
916 {
917 uint32_t tmpTmdsClk = *tmdsClock;
918
919 switch (commAttr->colorSpace) {
920 case HDMI_COLOR_SPACE_RGB:
921 tmpTmdsClk = HDMI_MULTIPLE_1P5(tmpTmdsClk);
922 *supportDeepColor = (sinkCap->vsdbInfo.deepColor.dc36bit && cap->bits.deepColor12bits) ? true : false;
923 break;
924 case HDMI_COLOR_SPACE_YCBCR444:
925 tmpTmdsClk = HDMI_MULTIPLE_1P5(tmpTmdsClk);
926 *supportDeepColor = (sinkCap->vsdbInfo.deepColor.dc36bit && cap->bits.deepColor12bits &&
927 sinkCap->vsdbInfo.deepColor.dcY444) ? true : false;
928 break;
929 case HDMI_COLOR_SPACE_YCBCR420:
930 tmpTmdsClk = HDMI_MULTIPLE_1P5(tmpTmdsClk);
931 *supportDeepColor = (sinkCap->hfVsdbInfo.dc.dc36bit && cap->bits.deepColor12bits) ? true : false;
932 break;
933 default:
934 /* Y422, ignore deepclr */
935 *supportDeepColor = true;
936 break;
937 }
938 *tmdsClock = tmpTmdsClk;
939 }
940
HdmiDeepColorCheck(struct HdmiCntlr * cntlr,struct HdmiSinkDeviceCapability * sinkCap,uint32_t maxTmdsClk)941 static int32_t HdmiDeepColorCheck(struct HdmiCntlr *cntlr, struct HdmiSinkDeviceCapability *sinkCap,
942 uint32_t maxTmdsClk)
943 {
944 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr);
945 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr);
946 union HdmiCap *cap = &(cntlr->cap.baseCap);
947 uint32_t tmdsClock = videoAttr->pixelClock;
948 bool supportDeepColor = false;
949
950 if (commAttr->colorSpace == HDMI_COLOR_SPACE_YCBCR420) {
951 tmdsClock = HDMI_MULTIPLE_0P5(tmdsClock);
952 }
953
954 switch (commAttr->deepColor) {
955 case HDMI_DEEP_COLOR_30BITS:
956 HdmiDeepColor10bitsCheck(sinkCap, commAttr, cap, &tmdsClock, &supportDeepColor);
957 break;
958 case HDMI_DEEP_COLOR_36BITS:
959 HdmiDeepColor12bitsCheck(sinkCap, commAttr, cap, &tmdsClock, &supportDeepColor);
960 break;
961 default:
962 commAttr->deepColor = HDMI_DEEP_COLOR_24BITS;
963 supportDeepColor = true;
964 break;
965 }
966
967 if (supportDeepColor == false || tmdsClock > maxTmdsClk) {
968 return HDF_ERR_INVALID_PARAM;
969 }
970 videoAttr->tmdsClock = tmdsClock;
971 /* Y422 default 12bit output, deep_color force adapt to 8bit(24bit). */
972 if (commAttr->colorSpace == HDMI_COLOR_SPACE_YCBCR422) {
973 if (videoAttr->timing == HDMI_VIDEO_TIMING_1440X480I60 ||
974 videoAttr->timing == HDMI_VIDEO_TIMING_1440X576I50) {
975 HDF_LOGD("force change colorspace to RGB!");
976 commAttr->colorSpace = HDMI_COLOR_SPACE_RGB;
977 }
978 if ((videoAttr->deepColor != HDMI_DEEP_COLOR_24BITS) &&
979 (videoAttr->deepColor != HDMI_DEEP_COLOR_OFF)) {
980 videoAttr->deepColor = HDMI_DEEP_COLOR_OFF;
981 HDF_LOGD("when Y422, deep_color not support 10/12bit!");
982 }
983 }
984 return HDF_SUCCESS;
985 }
986
HdmiColorBitSelect(struct HdmiCntlr * cntlr)987 static int32_t HdmiColorBitSelect(struct HdmiCntlr *cntlr)
988 {
989 struct HdmiSinkDeviceCapability *sinkCap = NULL;
990 uint32_t maxTmdsClk = 0;
991
992 /* DVI mode, must set RGB and DEEP_COLOR_OFF */
993 if (cntlr->attr.commAttr.enableHdmi == false) {
994 if (cntlr->attr.commAttr.colorSpace != HDMI_COLOR_SPACE_RGB) {
995 HDF_LOGE("DVI mode, the color space is not RGB!");
996 return HDF_ERR_INVALID_PARAM;
997 }
998 cntlr->attr.commAttr.deepColor = HDMI_DEEP_COLOR_OFF;
999 cntlr->attr.videoAttr.tmdsClock = cntlr->attr.videoAttr.pixelClock;
1000 return HDF_SUCCESS;
1001 }
1002
1003 /* FRL mode. */
1004 if (cntlr->cap.baseCap.bits.hdr > 0) {
1005 HdmiTmdsClockUpdate(&(cntlr->attr.videoAttr), &(cntlr->attr.commAttr));
1006 if (cntlr->attr.videoAttr.tmdsClock > HDMI_HDMI20_MAX_TMDS_RATE) {
1007 HDF_LOGD("HDMI2.1, tmds clock exceed max.");
1008 return HDF_SUCCESS;
1009 }
1010 }
1011
1012 sinkCap = HdmiGetSinkCapability(cntlr->hdmi);
1013 if (sinkCap == NULL) {
1014 HdmiTmdsClockUpdate(&(cntlr->attr.videoAttr), &(cntlr->attr.commAttr));
1015 return HDF_SUCCESS;
1016 }
1017
1018 if (sinkCap->maxTmdsClk == 0) {
1019 /* use default clock. */
1020 maxTmdsClk = cntlr->cap.defTmdsClock;
1021 } else {
1022 maxTmdsClk = (sinkCap->maxTmdsClk < cntlr->cap.maxTmdsClock) ?
1023 sinkCap->maxTmdsClk : cntlr->cap.maxTmdsClock;
1024 }
1025 /* MHz is converted to KHz */
1026 maxTmdsClk *= 1000;
1027
1028 if (HdmiColorSpaceCheck(cntlr, sinkCap, maxTmdsClk) != HDF_SUCCESS) {
1029 return HDF_ERR_INVALID_PARAM;
1030 }
1031 if (HdmiDeepColorCheck(cntlr, sinkCap, maxTmdsClk) != HDF_SUCCESS) {
1032 return HDF_ERR_INVALID_PARAM;
1033 }
1034 return HDF_SUCCESS;
1035 }
1036
HdmiAudioAttrHandle(struct HdmiCntlr * cntlr)1037 static int32_t HdmiAudioAttrHandle(struct HdmiCntlr *cntlr)
1038 {
1039 struct HdmiAudioConfigInfo audioCfg = {0};
1040 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr);
1041 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr);
1042 struct HdmiAudioAttr *audioAttr = &(cntlr->attr.audioAttr);
1043 int32_t ret;
1044
1045 audioCfg.downSample = audioAttr->downSample;
1046 audioCfg.channels = audioAttr->channels;
1047 audioCfg.bitDepth = audioAttr->bitDepth;
1048 audioCfg.sampleRate = audioAttr->sampleRate;
1049 audioCfg.ifType = audioAttr->ifType;
1050 audioCfg.enable = (commAttr->enableAudio) && (commAttr->enableHdmi);
1051 audioCfg.tmdsClock = videoAttr->tmdsClock;
1052 audioCfg.pixelRepeat = videoAttr->pixelRepeat;
1053
1054 HdmiCntlrAudioPathEnable(cntlr, false);
1055 HdmiCntlrAudioPathSet(cntlr, &audioCfg);
1056 ret = HdmiAudioInfoFrameSend(&(cntlr->infoFrame), ((commAttr->enableAudio) && (commAttr->audio)));
1057 HdmiCntlrAudioPathEnable(cntlr, true);
1058 return ret;
1059 }
1060
HdmiHdrModeCheck(struct HdmiCommonAttr * commAttr,struct HdmiVideoAttr * videoAttr,struct HdmiHdrAttr * hdrAttr)1061 static void HdmiHdrModeCheck(struct HdmiCommonAttr *commAttr,
1062 struct HdmiVideoAttr *videoAttr, struct HdmiHdrAttr *hdrAttr)
1063 {
1064 switch (hdrAttr->userMode) {
1065 case HDMI_HDR_USERMODE_DOLBY:
1066 videoAttr->yccQuantization = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
1067 commAttr->colorSpace = HDMI_COLOR_SPACE_YCBCR444;
1068 videoAttr->tmdsClock = videoAttr->pixelClock;
1069 commAttr->deepColor = HDMI_DEEP_COLOR_24BITS;
1070 videoAttr->quantization = HDMI_QUANTIZATION_RANGE_DEFAULT;
1071 break;
1072 case HDMI_HDR_USERMODE_HDR10:
1073 if (hdrAttr->mode == HDMI_HDR_MODE_CEA_861_3) {
1074 if (hdrAttr->colorimetry > HDMI_HDR_COLORIMETRY_EXTENDED) {
1075 videoAttr->colorimetry = HDMI_COLORIMETRY_EXTENDED;
1076 videoAttr->extColorimetry = (enum HdmiExtendedColorimetry)(hdrAttr->colorimetry -
1077 HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_601);
1078 } else {
1079 videoAttr->colorimetry = (enum HdmiColorimetry)(hdrAttr->colorimetry);
1080 videoAttr->extColorimetry = HDMI_EXTENDED_COLORIMETRY_BUTT;
1081 }
1082 commAttr->xvyccMode = false;
1083 }
1084 break;
1085 default:
1086 break;
1087 }
1088 }
1089
HdmiFillVideoAttrFromHardwareStatus(struct HdmiVideoAttr * videoAttr,struct HdmiHardwareStatus * hwStatus,struct HdmiCommonAttr * commAttr)1090 static void HdmiFillVideoAttrFromHardwareStatus(struct HdmiVideoAttr *videoAttr,
1091 struct HdmiHardwareStatus *hwStatus, struct HdmiCommonAttr *commAttr)
1092 {
1093 bool rgb = false;
1094 bool aspectIs256 = false;
1095 uint8_t vic;
1096 enum HdmiVsVideoFormat format;
1097 enum Hdmi4kVic vic4k;
1098
1099 rgb = ((hwStatus->videoStatus.rgb2Ycbcr) ||
1100 ((!hwStatus->videoStatus.ycbcr2Rgb) && (hwStatus->videoStatus.outColorSpace == HDMI_COLOR_SPACE_RGB)));
1101 videoAttr->colorSpace = (rgb == true) ? HDMI_COLOR_SPACE_RGB : HDMI_COLOR_SPACE_YCBCR444;
1102
1103 if (hwStatus->infoFrameStatus.aviEnable) {
1104 vic = hwStatus->infoFrameStatus.avi[7];
1105 /*
1106 * when the timing is 4096*2160, the aspect ratio in AVI infoFrame is 0
1107 * (but the real aspect ratio is 256:135<0x04>, the video_code is 0)
1108 */
1109 aspectIs256 = (((vic == 0) && (hwStatus->infoFrameStatus.vsif[8] == 0x04)) ||
1110 ((vic >= HDMI_VIC_4096X2160P25_256_135) && (vic <= HDMI_VIC_4096X2160P60_256_135)));
1111 videoAttr->aspect = (aspectIs256 == true) ? HDMI_PICTURE_ASPECT_256_135 :
1112 ((hwStatus->infoFrameStatus.avi[5] >> 4) & 0x3); /* 4'b, BIT[2:1] */
1113 videoAttr->activeAspect = hwStatus->infoFrameStatus.avi[5] & 0xf;
1114 videoAttr->colorimetry = (hwStatus->infoFrameStatus.avi[5] >> 6) & 0x3; /* 6'b, BIT[2:1] */
1115 videoAttr->quantization = (hwStatus->infoFrameStatus.avi[6] >> 2) & 0x3; /* 2'b, BIT[2:1] */
1116 videoAttr->extColorimetry = (hwStatus->infoFrameStatus.avi[6] >> 4) & 0x07; /* 4'b, BIT[3:1] */
1117 videoAttr->yccQuantization = (hwStatus->infoFrameStatus.avi[8] >> 6) & 0x3; /* 6'b, BIT[2:1] */
1118 videoAttr->pixelRepeat = (hwStatus->infoFrameStatus.avi[8] & 0xf) + 1;
1119 videoAttr->timing = HdmiCommonGetVideoTiming(vic, videoAttr->aspect);
1120 if ((!hwStatus->infoFrameStatus.vsifEnable) && (!vic)) {
1121 videoAttr->timing = HDMI_VIDEO_TIMING_NONE;
1122 }
1123 commAttr->quantization = (commAttr->colorSpace == HDMI_COLOR_SPACE_RGB) ?
1124 videoAttr->quantization : (videoAttr->yccQuantization + 1);
1125 }
1126
1127 videoAttr->_3dStruct = HDMI_VS_VIDEO_3D_BUTT;
1128 if (hwStatus->infoFrameStatus.vsifEnable) {
1129 format = (hwStatus->infoFrameStatus.vsif[7] >> 5) & 0x3; /* 5'b, BIT[2:1] */
1130 if (format == HDMI_VS_VIDEO_FORMAT_4K) {
1131 vic4k = hwStatus->infoFrameStatus.vsif[8];
1132 videoAttr->timing = HdmiCommonGetVideo4kTiming(vic4k);
1133 } else if (format == HDMI_VS_VIDEO_FORMAT_3D) {
1134 videoAttr->_3dStruct = (hwStatus->infoFrameStatus.vsif[8] >> 4) & 0xf; /* 4'b, BIT[4:1] */
1135 }
1136 }
1137 }
1138
HdmiFillCommonAttrFromHardwareStatus(struct HdmiCommonAttr * commAttr,struct HdmiHardwareStatus * hwStatus,struct HdmiAttr * attr)1139 static void HdmiFillCommonAttrFromHardwareStatus(struct HdmiCommonAttr *commAttr,
1140 struct HdmiHardwareStatus *hwStatus, struct HdmiAttr *attr)
1141 {
1142 bool dolby = false;
1143
1144 switch (hwStatus->commonStatus.tmdsMode) {
1145 case HDMI_TMDS_MODE_HDMI_1_4:
1146 case HDMI_TMDS_MODE_HDMI_2_0:
1147 commAttr->enableHdmi = true;
1148 commAttr->enableVideo = true;
1149 break;
1150 case HDMI_TMDS_MODE_DVI:
1151 commAttr->enableHdmi = false;
1152 commAttr->enableVideo = true;
1153 break;
1154 default:
1155 commAttr->enableHdmi = false;
1156 commAttr->enableVideo = false;
1157 break;
1158 }
1159
1160 commAttr->enableAudio = (hwStatus->audioStatus.enable && hwStatus->infoFrameStatus.audioEnable);
1161 commAttr->avi = hwStatus->infoFrameStatus.aviEnable;
1162 commAttr->audio = hwStatus->infoFrameStatus.audioEnable;
1163 commAttr->xvyccMode = hwStatus->infoFrameStatus.gdbEnable;
1164 commAttr->deepColor = HdmiCommonColorDepthConvertToDeepClolor(hwStatus->videoStatus.outBitDepth);
1165
1166 /* color space is ycbcr444 when the hdr mode is dolby. */
1167 dolby = ((attr->hdrAttr.userMode == HDMI_HDR_USERMODE_DOLBY) &&
1168 (!hwStatus->videoStatus.rgb2Ycbcr) &&
1169 (!hwStatus->videoStatus.ycbcr2Rgb) &&
1170 (!hwStatus->videoStatus.ycbcr444422) &&
1171 (!hwStatus->videoStatus.ycbcr422420) &&
1172 (!hwStatus->videoStatus.ycbcr422444) &&
1173 (!hwStatus->videoStatus.ycbcr420422));
1174 commAttr->colorSpace = (dolby == true) ? HDMI_COLOR_SPACE_YCBCR444 : hwStatus->videoStatus.outColorSpace;
1175 }
1176
HdmiCommonAttrChanged(struct HdmiCommonAttr * curCommAttr,struct HdmiCommonAttr * commAttr)1177 static bool HdmiCommonAttrChanged(struct HdmiCommonAttr *curCommAttr, struct HdmiCommonAttr *commAttr)
1178 {
1179 bool change;
1180
1181 change = (commAttr->enableHdmi != curCommAttr->enableHdmi) ||
1182 (commAttr->colorSpace != curCommAttr->colorSpace) ||
1183 (commAttr->xvyccMode != curCommAttr->xvyccMode) ||
1184 (commAttr->avi != curCommAttr->avi) ||
1185 (commAttr->quantization != curCommAttr->quantization);
1186
1187 if (change == true) {
1188 return true;
1189 }
1190
1191 if (((commAttr->deepColor == HDMI_DEEP_COLOR_OFF) ||
1192 (commAttr->deepColor == HDMI_DEEP_COLOR_24BITS)) &&
1193 ((curCommAttr->deepColor == HDMI_DEEP_COLOR_OFF) ||
1194 (curCommAttr->deepColor == HDMI_DEEP_COLOR_24BITS))) {
1195 HDF_LOGI("deep color not change: %u", curCommAttr->deepColor);
1196 } else if (commAttr->deepColor != curCommAttr->deepColor) {
1197 return true;
1198 }
1199 return false;
1200 }
1201
HdmiVideoAttrChanged(struct HdmiVideoAttr * curVideoAttr,struct HdmiVideoAttr * videoAttr)1202 static bool HdmiVideoAttrChanged(struct HdmiVideoAttr *curVideoAttr, struct HdmiVideoAttr *videoAttr)
1203 {
1204 bool change;
1205
1206 change = (videoAttr->timing != curVideoAttr->timing) ||
1207 (videoAttr->colorSpace != curVideoAttr->colorSpace) ||
1208 (videoAttr->_3dStruct != curVideoAttr->_3dStruct) ||
1209 (videoAttr->pixelRepeat != curVideoAttr->pixelRepeat) ||
1210 (videoAttr->colorimetry != curVideoAttr->colorimetry) ||
1211 (videoAttr->extColorimetry != curVideoAttr->extColorimetry) ||
1212 (videoAttr->quantization != curVideoAttr->quantization) ||
1213 (videoAttr->yccQuantization != curVideoAttr->yccQuantization) ||
1214 (videoAttr->aspect != curVideoAttr->aspect);
1215 return change;
1216 }
1217
HdmiVedioAttrHandle(struct HdmiCntlr * cntlr,struct HdmiHardwareStatus * hwStatus)1218 static int32_t HdmiVedioAttrHandle(struct HdmiCntlr *cntlr, struct HdmiHardwareStatus *hwStatus)
1219 {
1220 struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr);
1221 struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr);
1222 struct HdmiCommonAttr curCommAttr = {0};
1223 struct HdmiVideoAttr curVideoAttr = {0};
1224 int32_t ret;
1225
1226 /* support HDR. */
1227 if (cntlr->cap.baseCap.bits.hdr > 0) {
1228 HdmiHdrModeCheck(commAttr, videoAttr, &(cntlr->attr.hdrAttr));
1229 }
1230
1231 /* support FRL. */
1232 if (cntlr->cap.baseCap.bits.frl > 0) {
1233 ret = HdmiFrlModeSelect(cntlr->frl);
1234 if (ret != HDF_SUCCESS) {
1235 return ret;
1236 }
1237 }
1238
1239 HdmiFillCommonAttrFromHardwareStatus(&curCommAttr, hwStatus, &(cntlr->attr));
1240 HdmiFillVideoAttrFromHardwareStatus(&curVideoAttr, hwStatus, &curCommAttr);
1241 if (HdmiCommonAttrChanged(&curCommAttr, commAttr) == false &&
1242 HdmiVideoAttrChanged(&curVideoAttr, videoAttr) == false &&
1243 HdmiFrlModeChanged(cntlr->frl) == false) {
1244 HDF_LOGI("video and common attr is not changed.");
1245 return HDF_SUCCESS;
1246 }
1247
1248 if (commAttr->enableVideo == true) {
1249 HdmiCntlrVideoPathSet(cntlr, videoAttr);
1250 }
1251
1252 (void)HdmiAviInfoFrameSend(&(cntlr->infoFrame), (commAttr->enableHdmi && commAttr->avi));
1253 (void)HdmiVsInfoFrameSend(&(cntlr->infoFrame), commAttr->enableHdmi, commAttr->vsifDolby);
1254 /* the drm infoFrame is stop because software was reset in videopath, so re-enable it if the mode is HDR10. */
1255 if (cntlr->cap.baseCap.bits.hdr > 0) {
1256 if (cntlr->attr.hdrAttr.mode == HDMI_HDR_MODE_CEA_861_3) {
1257 (void)HdmiDrmInfoFrameSend(&(cntlr->infoFrame), false);
1258 (void)HdmiDrmInfoFrameSend(&(cntlr->infoFrame), true);
1259 }
1260 }
1261 return HDF_SUCCESS;
1262 }
1263
HdmiAttrUpdate(struct HdmiCntlr * cntlr)1264 static void HdmiAttrUpdate(struct HdmiCntlr *cntlr)
1265 {
1266 struct HdmiHardwareStatus hwStatus = {0};
1267
1268 if (HdmiColorBitSelect(cntlr) != HDF_SUCCESS) {
1269 HDF_LOGD("attr update: color bit select fail.");
1270 return;
1271 }
1272
1273 if (cntlr->ops->hardWareStatusGet == NULL) {
1274 return;
1275 }
1276
1277 HdmiCntlrLock(cntlr);
1278 cntlr->ops->hardWareStatusGet(cntlr, &hwStatus);
1279 HdmiCntlrUnlock(cntlr);
1280
1281 if (HdmiAudioAttrHandle(cntlr) != HDF_SUCCESS) {
1282 HDF_LOGD("audio attr check fail");
1283 return;
1284 }
1285 if (HdmiVedioAttrHandle(cntlr, &hwStatus) != HDF_SUCCESS) {
1286 HDF_LOGD("vedio attr check fail");
1287 }
1288 }
1289
HdmiCntlrDeepColorSet(struct HdmiCntlr * cntlr,enum HdmiDeepColor color)1290 int32_t HdmiCntlrDeepColorSet(struct HdmiCntlr *cntlr, enum HdmiDeepColor color)
1291 {
1292 if (cntlr == NULL || cntlr->ops == NULL) {
1293 return HDF_ERR_INVALID_OBJECT;
1294 }
1295
1296 if (cntlr->attr.commAttr.colorSpace == HDMI_COLOR_SPACE_YCBCR422) {
1297 if (color != HDMI_DEEP_COLOR_24BITS && color != HDMI_DEEP_COLOR_OFF) {
1298 HDF_LOGE("not support deepcolor %u when colorspace is ycbcr422.", color);
1299 return HDF_ERR_INVALID_PARAM;
1300 }
1301 }
1302
1303 /* if the current hdmi mode is dolby, deep color set is invalid. */
1304 if (cntlr->attr.hdrAttr.mode == HDMI_HDR_MODE_DOLBY_NORMAL ||
1305 cntlr->attr.hdrAttr.mode == HDMI_HDR_MODE_DOLBY_TUNNELING) {
1306 HDF_LOGD("don't change deepcolor when dolby mode is %u.", cntlr->attr.hdrAttr.mode);
1307 return HDF_ERR_NOT_SUPPORT;
1308 }
1309
1310 cntlr->attr.commAttr.deepColor = color;
1311 HdmiCntlrAvmuteSet(cntlr, true);
1312 HdmiAttrUpdate(cntlr);
1313 HdmiCntlrAvmuteSet(cntlr, false);
1314 return HDF_SUCCESS;
1315 }
1316
HdmiCntlrDeepColorGet(struct HdmiCntlr * cntlr,enum HdmiDeepColor * color)1317 int32_t HdmiCntlrDeepColorGet(struct HdmiCntlr *cntlr, enum HdmiDeepColor *color)
1318 {
1319 if (cntlr == NULL || cntlr->ops == NULL) {
1320 return HDF_ERR_INVALID_OBJECT;
1321 }
1322 if (color == NULL) {
1323 return HDF_ERR_INVALID_PARAM;
1324 }
1325
1326 *color = cntlr->attr.commAttr.deepColor;
1327 return HDF_SUCCESS;
1328 }
1329
HdmiCntlrSetVideoAttribute(struct HdmiCntlr * cntlr,struct HdmiVideoAttr * attr)1330 int32_t HdmiCntlrSetVideoAttribute(struct HdmiCntlr *cntlr, struct HdmiVideoAttr *attr)
1331 {
1332 struct HdmiHardwareStatus hwStatus = {0};
1333
1334 if (cntlr == NULL || cntlr->ops == NULL) {
1335 return HDF_ERR_INVALID_OBJECT;
1336 }
1337 if (attr == NULL) {
1338 return HDF_ERR_INVALID_PARAM;
1339 }
1340
1341 cntlr->attr.videoAttr = *attr;
1342
1343 if (cntlr->ops->hardWareStatusGet == NULL) {
1344 return HDF_ERR_NOT_SUPPORT;
1345 }
1346
1347 HdmiCntlrLock(cntlr);
1348 cntlr->ops->hardWareStatusGet(cntlr, &hwStatus);
1349 HdmiCntlrUnlock(cntlr);
1350 return HdmiVedioAttrHandle(cntlr, &hwStatus);
1351 }
1352
HdmiCntlrSetAudioAttribute(struct HdmiCntlr * cntlr,struct HdmiAudioAttr * attr)1353 int32_t HdmiCntlrSetAudioAttribute(struct HdmiCntlr *cntlr, struct HdmiAudioAttr *attr)
1354 {
1355 if (cntlr == NULL || cntlr->ops == NULL) {
1356 return HDF_ERR_INVALID_OBJECT;
1357 }
1358 if (attr == NULL) {
1359 return HDF_ERR_INVALID_PARAM;
1360 }
1361
1362 cntlr->attr.audioAttr = *attr;
1363 return HdmiAudioAttrHandle(cntlr);
1364 }
1365
HdmiCntlrSetHdrAttribute(struct HdmiCntlr * cntlr,struct HdmiHdrAttr * attr)1366 int32_t HdmiCntlrSetHdrAttribute(struct HdmiCntlr *cntlr, struct HdmiHdrAttr *attr)
1367 {
1368 if (cntlr == NULL || cntlr->ops == NULL) {
1369 return HDF_ERR_INVALID_OBJECT;
1370 }
1371 if (attr == NULL) {
1372 return HDF_ERR_INVALID_PARAM;
1373 }
1374
1375 return HdmiHdrAttrHandle(cntlr->hdr, attr);
1376 }
1377
HdmiCntlrInfoFrameGet(struct HdmiCntlr * cntlr,enum HdmiPacketType type,union HdmiInfoFrameInfo * frame)1378 int32_t HdmiCntlrInfoFrameGet(struct HdmiCntlr *cntlr, enum HdmiPacketType type, union HdmiInfoFrameInfo *frame)
1379 {
1380 if (cntlr == NULL) {
1381 return HDF_ERR_INVALID_OBJECT;
1382 }
1383 return HdmiInfoFrameGetInfo(&(cntlr->infoFrame), type, frame);
1384 }
1385
HdmiCntlrInfoFrameSet(struct HdmiCntlr * cntlr,enum HdmiPacketType type,union HdmiInfoFrameInfo * frame)1386 int32_t HdmiCntlrInfoFrameSet(struct HdmiCntlr *cntlr, enum HdmiPacketType type, union HdmiInfoFrameInfo *frame)
1387 {
1388 if (cntlr == NULL || cntlr->ops == NULL) {
1389 return HDF_ERR_INVALID_OBJECT;
1390 }
1391 if (frame == NULL) {
1392 return HDF_ERR_INVALID_PARAM;
1393 }
1394 return HdmiInfoFrameSetInfo(&(cntlr->infoFrame), type, frame);
1395 }
1396
HdmiCntlrRegisterHpdCallbackFunc(struct HdmiCntlr * cntlr,struct HdmiHpdCallbackInfo * callback)1397 int32_t HdmiCntlrRegisterHpdCallbackFunc(struct HdmiCntlr *cntlr, struct HdmiHpdCallbackInfo *callback)
1398 {
1399 if (cntlr == NULL) {
1400 return HDF_ERR_INVALID_OBJECT;
1401 }
1402 if (callback == NULL) {
1403 return HDF_ERR_INVALID_PARAM;
1404 }
1405
1406 cntlr->event.callback.data = callback->data;
1407 cntlr->event.callback.callbackFunc = callback->callbackFunc;
1408 return HDF_SUCCESS;
1409 }
1410
HdmiCntlrUnregisterHpdCallbackFunc(struct HdmiCntlr * cntlr)1411 int32_t HdmiCntlrUnregisterHpdCallbackFunc(struct HdmiCntlr *cntlr)
1412 {
1413 if (cntlr == NULL) {
1414 return HDF_ERR_INVALID_OBJECT;
1415 }
1416 cntlr->event.callback.data = NULL;
1417 cntlr->event.callback.callbackFunc = NULL;
1418 return HDF_SUCCESS;
1419 }
1420
HdmiCntlrClose(struct HdmiCntlr * cntlr)1421 void HdmiCntlrClose(struct HdmiCntlr *cntlr)
1422 {
1423 if (cntlr == NULL || cntlr->ops == NULL) {
1424 return;
1425 }
1426
1427 if ((cntlr->state & HDMI_CNTLR_STATE_START) > 0) {
1428 HdmiCntlrStop(cntlr);
1429 }
1430
1431 HdmiInfoFrameDeInit(cntlr);
1432 HdmiDdcDeinit(cntlr);
1433 HdmiScdcDeinit(cntlr);
1434 HdmiFrlDeinit(cntlr);
1435 HdmiHdcpDeinit(cntlr);
1436 HdmiCecDeinit(cntlr);
1437 HdmiHdrDeinit(cntlr);
1438 cntlr->state = HDMI_CNTLR_STATE_CLOSE;
1439 }
1440