• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# HDMI
2
3
4## 概述
5
6### 功能简介
7
8HDMI(High Definition Multimedia Interface),即高清多媒体接口,主要用于DVD、机顶盒等音视频Source到TV、显示器等Sink设备的传输。
9HDMI以主从方式工作,通常有一个Source端和一个Sink端。
10HDMI接口定义了完成HDMI传输的通用方法集合,包括:
11
12- HDMI控制器管理:打开或关闭HDMI控制器
13- HDMI启动/停止传输:启动或停止HDMI传输
14- HDMI控制器设置:设置音频、视频及HDR属性,设置色彩深度、声音图像消隐等
15- HDMI读取EDID:读取Sink端原始的EDID数据
16- HDMI热插拔:注册/注销热插拔回调函数
17
18### 基本概念
19
20HDMI是Hitachi、Panasonic、Philips、Silicon Image、Sony、Thomson、Toshiba共同发布的一款音视频传输协议。传输过程遵循TMDS(Transition Minimized Differential Signaling)协议。
21
22- TMDS(Transition Minimized Differential signal):过渡调制差分信号,也被称为最小化传输差分信号,用于发送音频、视频及各种辅助数据。
23- DDC(Display Data Channel):显示数据通道,发送端与接收端可利用DDC通道得知彼此的发送与接收能力,但HDMI仅需单向获知接收端(显示器)的能力。
24- CEC(Consumer Electronics Control):消费电子控制,该功能应该能够在连接HDMI的发送设备与接收设备之间实现交互操作。
25- FRL(Fixed Rate Link):TMDS 的架构进行讯号传输时,最高带宽可达 18Gbps,而FRL模式的带宽则提升到48 Gbps。
26- HDCP(High-bandwidth Digital Content Protection):即高带宽数字内容保护技术,当用户对高清晰信号进行非法复制时,该技术会进行干扰,降低复制出来的影像的质量,从而对内容进行保护。
27- EDID(Extended Display Identification Data):扩展显示标识数据,通常存储在显示器的固件中,标识供应商信息、EDID版本信息、最大图像大小、颜色设置、厂商预设置、频率范围的限制以及显示器名和序列号的字符串。
28
29### 运作机制
30
31HDMI的Source端提供+5V和GND,用于DDC和CEC通信。通过DDC通道,Source端可以读取Sink端的各项参数,如接受能力等;CEC为可选通道,用于同步Source端与Sink端的控制信号,改善用户体验。TMDS通道有四组差分信号,TMDS Clock Channel为TMDS提供时钟信号,其余三组传输音视频数据及各种辅助数据;HDP为热插拔检测端口,当有Sink端接入时,Source端会通过中断服务程序进行响应。
32
33HDMI物理连接如图1所示:
34
35**图 1**  HDMI物理连线示意图
36
37![](figures/HDMI物理连线示意图.png "HDMI物理连线示意图")
38
39### 约束与限制
40
41HDMI模块当前仅支持轻量和小型系统内核(LiteOS)。
42
43## 使用指导
44
45### 场景介绍
46
47HDMI具有体积小,传输速率高,传输带宽宽,兼容性好,能同时传输无压缩音视频信号等优点。与传统的全模拟接口相比,HDMI不但增加了设备间接线的便捷性,还提供了一些HDMI特有的智能化功能,可用于小体积设备进行高质量音视频传输的场景。
48
49### 接口说明
50
51**表 1**  HDMI驱动API接口功能介绍
52
53
54| 接口名                        | 描述                       |
55| ----------------------------- | -------------------------- |
56| HdmiOpen                      | 打开HDMI控制器             |
57| HdmiClose                     | 关闭HDMI控制器             |
58| HdmiStart                     | 启动HDMI传输               |
59| HdmiStop                      | 停止HDMI传输               |
60| HdmiAvmuteSet                 | 声音图像消隐设置           |
61| HdmiDeepColorSet              | 设置色彩深度               |
62| HdmiDeepColorGet              | 获取色彩深度               |
63| HdmiSetVideoAttribute         | 设置视频属性               |
64| HdmiSetAudioAttribute         | 设置音频属性               |
65| HdmiSetHdrAttribute           | 设置HDR属性                |
66| HdmiReadSinkEdid              | 读取Sink端原始EDID数据     |
67| HdmiRegisterHpdCallbackFunc   | 注册HDMI热插拔检测回调函数 |
68| HdmiUnregisterHpdCallbackFunc | 注销HDMI热插拔检测回调函数 |
69
70### 开发步骤
71
72使用HDMI设备的一般流程如图2所示。
73
74**图 2**  HDMI设备使用流程图
75
76![](figures/HDMI使用流程图.png "HDMI使用流程图")
77
78#### 打开HDMI控制器
79
80在进行HDMI通信前,首先要调用HdmiOpen打开HDMI控制器。
81
82```c
83DevHandle HdmiOpen(int16_t number);
84```
85
86**表 2**  HdmiOpen参数和返回值描述
87
88| 参数       | 参数描述             |
89| ---------- | -------------------- |
90| number     | HDMI控制器号         |
91| **返回值** | **返回值描述**       |
92| NULL       | 打开HDMI控制器失败   |
93| 控制器句柄 | 打开的HDMI控制器句柄 |
94
95假设系统中存在2个HDMI控制器,编号从0到1,以下代码示例为获取0号控制器:
96
97```c
98DevHandle hdmiHandle = NULL;  /* HDMI控制器句柄 /
99
100/* 打开HDMI控制器 */
101hdmiHandle = HdmiOpen(0);
102if (hdmiHandle == NULL) {
103    HDF_LOGE("HdmiOpen: failed\n");
104    return;
105}
106```
107
108#### 注册热插拔检测回调函数
109
110```c
111int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback);
112```
113
114**表 3**  HdmiRegisterHpdCallbackFunc参数和返回值描述
115
116| 参数       | 参数描述           |
117| ---------- | ------------------ |
118| handle     | HDMI控制器句柄     |
119| callback   | 热插拔回调函数信息 |
120| **返回值** | **返回值描述**     |
121| 0          | 注册成功           |
122| 负数       | 注册失败           |
123
124注册热插拔检测回调函数示例:
125
126```c
127/* 热插拔检测回调函数定义 */
128static void HdmiHpdHandle(void *data, bool hpd)
129{
130    if (data == NULL) {
131        HDF_LOGE("priv data is NULL");
132        return;
133    }
134    if (hpd == true) {
135        HDF_LOGD("HdmiHpdHandle: hot plug");
136        /* 调用者添加相关处理 */
137    } else {
138        HDF_LOGD("HdmiHpdHandle: hot unplug");
139        /* 调用者添加相关处理 */
140    }
141}
142
143/* 热插拔检测回调函数注册示例 */
144···
145struct HdmiHpdCallbackInfo info = {0};
146info.data = handle;
147info.callbackFunc = HdmiHpdHandle;
148ret = HdmiRegisterHpdCallbackFunc(hdmiHandle, info);
149if (ret != 0) {
150    HDF_LOGE("HdmiRegisterHpdCallbackFunc: Register failed.");
151}
152···
153```
154
155#### 读取EDID
156
157```c
158int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);
159```
160
161**表 4**  HdmiReadSinkEdid参数和返回值描述
162
163| 参数       | 参数描述               |
164| ---------- | ---------------------- |
165| handle     | HDMI控制器句柄         |
166| buffer     | 数据缓冲区             |
167| len        | 数据长度               |
168| **返回值** | **返回值描述**         |
169| 正整数     | 成功读取的原始EDID数据 |
170| 负数或0    | 读取失败               |
171
172读取Sink端的原始EDID数据示例:
173
174```c
175int32_t len;
176uint8_t edid[HDMI_EDID_MAX_LEN] = {0};
177
178len = HdmiReadSinkEdid(hdmiHandle, edid, HDMI_EDID_MAX_LEN);
179if (len <= 0) {
180    HDF_LOGE("%s: HdmiReadSinkEdid failed len = %d.", __func__, len);
181}
182```
183
184#### 设置音频属性
185
186```c
187int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr);
188```
189
190**表 5**  HdmiSetAudioAttribute参数和返回值描述
191
192
193| 参数   | 参数描述       |
194| ------ | -------------- |
195| handle | HDMI控制器句柄 |
196| attr   | 音频属性       |
197| 返回值 | 返回值描述     |
198| 0      | 设置成功       |
199| 负数   | 设置失败       |
200
201设置音频属性示例:
202
203```c
204struct HdmiAudioAttr audioAttr = {0};
205int32_t ret;
206
207audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3;
208audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S;
209audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16;
210audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K;
211audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3;
212ret = HdmiSetAudioAttribute(handle, &audioAttr);
213if (ret != 0) {
214    HDF_LOGE("HdmiSetAudioAttribute failed.");
215}
216```
217
218#### 设置视频属性
219
220```c
221int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr);
222```
223
224**表 6**  HdmiSetVideoAttribute参数和返回值描述
225
226
227| 参数       | 参数描述       |
228| ---------- | -------------- |
229| handle     | HDMI控制器句柄 |
230| attr       | 视频属性       |
231| **返回值** | **返回值描述** |
232| 0          | 设置成功       |
233| 负数       | 设置失败       |
234
235设置视频属性示例:
236
237```c
238struct HdmiVideoAttr videoAttr = {0};
239int32_t ret;
240
241videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444;
242videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED;
243videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM;
244videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL;
245ret = HdmiSetVideoAttribute(handle, &videoAttr);
246if (ret != 0) {
247    HDF_LOGE("HdmiSetVideoAttribute failed.");
248}
249```
250
251#### 设置HDR属性
252
253```c
254int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr);
255```
256
257**表 7**  HdmiSetHdrAttribute参数和返回值描述
258
259
260| 参数       | 参数描述       |
261| ---------- | -------------- |
262| handle     | HDMI控制器句柄 |
263| attr       | HDR属性        |
264| **返回值** | **返回值描述** |
265| 0          | 设置成功       |
266| 负数       | 设置失败       |
267
268设置HDR属性示例:
269
270```c
271struct HdmiHdrAttr hdrAttr = {0};
272int32_t ret;
273
274hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3;
275hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY;
276hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048;
277hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1;
278hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709;
279ret = HdmiSetHdrAttribute(handle, &hdrAttr);
280if (ret != 0) {
281    HDF_LOGE("HdmiSetHdrAttribute failed.");
282}
283```
284
285#### 设置HDMI声音图像消隐
286
287```c
288int32_t HdmiAvmuteSet(DevHandle handle, bool enable);
289```
290
291**表 8**  HdmiAvmuteSet参数和返回值描述
292
293
294| 参数       | 参数描述          |
295| ---------- | ----------------- |
296| handle     | HDMI控制器句柄    |
297| enable     | 使能/去使能avmute |
298| **返回值** | **返回值描述**    |
299| 0          | 设置成功          |
300| 负数       | 设置失败          |
301
302设置声音图像消隐示例:
303
304```c
305int32_t ret;
306
307ret = HdmiAvmuteSet(hdmiHandle, true);
308if (ret != 0) {
309    HDF_LOGE("HdmiAvmuteSet failed.");
310}
311```
312
313#### 设置色彩深度
314
315```c
316int32_t HdmiDeepColorSet(DevHandle handle, enum HdmiDeepColor color);
317```
318
319**表 9**  HdmiDeepColorSet参数和返回值描述
320
321
322| 参数       | 参数描述       |
323| ---------- | -------------- |
324| handle     | HDMI控制器句柄 |
325| color      | 色彩深度       |
326| **返回值** | **返回值描述** |
327| 0          | 设置成功       |
328| 负数       | 设置失败       |
329
330设置色彩深度示例:
331
332```c
333int32_t ret;
334
335ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS);
336if (ret != 0) {
337    HDF_LOGE("HdmiDeepColorSet failed.");
338}
339```
340
341#### 获取色彩深度
342
343```c
344int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color);
345```
346
347**表 10**  HdmiDeepColorGet参数和返回值描述
348
349
350| 参数       | 参数描述       |
351| ---------- | -------------- |
352| handle     | HDMI控制器句柄 |
353| color      | 色彩深度       |
354| **返回值** | **返回值描述** |
355| 0          | 获取成功       |
356| 负数       | 获取失败       |
357
358获取色彩深度示例:
359
360```c
361enum HdmiDeepColor color;
362int32_t ret;
363
364ret = HdmiDeepColorGet(handle, &color);
365if (ret != 0) {
366    HDF_LOGE("HdmiDeepColorGet failed.");
367}
368```
369
370#### 启动HDMI传输
371
372```c
373int32_t HdmiStart(DevHandle handle);
374```
375
376**表 11**  HdmiStart参数和返回值描述
377
378
379| 参数       | 参数描述       |
380| ---------- | -------------- |
381| handle     | HDMI控制器句柄 |
382| **返回值** | **返回值描述** |
383| 0          | 启动成功       |
384| 负数       | 启动失败       |
385
386启动HDMI传输示例:
387
388```c
389int32_t ret;
390
391ret = HdmiStart(hdmiHandle);
392if (ret != 0) {
393    HDF_LOGE("start transmission failed.");
394}
395```
396
397#### 停止HDMI传输<a name="section11"></a>
398
399```c
400int32_t HdmiStop(DevHandle handle);
401```
402
403**表 12**  HdmiStop参数和返回值描述
404
405
406| 参数       | 参数描述       |
407| ---------- | -------------- |
408| handle     | HDMI控制器句柄 |
409| **返回值** | **返回值描述** |
410| 0          | 停止成功       |
411| 负数       | 停止失败       |
412
413停止HDMI传输示例:
414
415```c
416int32_t ret;
417
418ret = HdmiStop(hdmiHandle);
419if (ret != 0) {
420    HDF_LOGE("stop transmission failed.");
421}
422```
423
424#### 注销热插拔检测回调函数
425
426```c
427int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle);
428```
429
430**表 13**  HdmiUnregisterHpdCallbackFunc参数和返回值描述
431
432
433| 参数       | 参数描述       |
434| ---------- | -------------- |
435| handle     | HDMI控制器句柄 |
436| **返回值** | **返回值描述** |
437| 0          | 注销成功       |
438| 负数       | 注销失败       |
439
440注销热插拔检测回调函数示例:
441
442```c
443int32_t ret;
444
445ret = HdmiUnregisterHpdCallbackFunc(hdmiHandle);
446if (ret != 0) {
447    HDF_LOGE("unregister failed.");
448}
449```
450
451#### 关闭HDMI控制器
452
453```c
454void HdmiClose(DevHandle handle);
455```
456
457**表 14**  HdmiClose参数和返回值描述
458
459
460| 参数       | 参数描述       |
461| ---------- | -------------- |
462| handle     | HDMI控制器句柄 |
463
464关闭HDMI控制器示例:
465
466```c
467HdmiClose(hdmiHandle);
468```
469
470### 使用实例
471
472本例程以操作开发板上的HDMI设备为例,详细展示HDMI接口的完整使用流程。
473
474本例拟在Hi3516DV300开发板上对虚拟驱动进行简单的传输操作:
475
476-   SOC:hi3516dv300。
477
478-   HDMI控制器:使用0号HDMI控制器。
479
480
481示例如下:
482
483```c
484#include "hdmi_if.h"          /* HDMI标准接口头文件 */
485#include "hdf_log.h"         /* 标准日志打印头文件 */
486#include "osal_time.h"       /* 标准延迟&睡眠接口头文件 */
487
488/* 热插拔回调函数 */
489static void HdmiHpdHandle(void *data, bool hpd)
490{
491    if (data == NULL) {
492    HDF_LOGE("priv data is NULL");
493    return;
494    }
495
496    if (hpd == true) {
497        HDF_LOGD("HdmiHpdHandle: hot plug");
498        /* 调用者添加相关处理 */
499    } else {
500        HDF_LOGD("HdmiHpdHandle: hot unplug");
501        /* 调用者添加相关处理 */
502    }
503}
504
505/* 设置HDMI相关属性 */
506static int32_t TestHdmiSetAttr(DevHandle handle)
507{
508    enum HdmiDeepColor color;
509    struct HdmiVideoAttr videoAttr = {0};
510    struct HdmiAudioAttr audioAttr = {0};
511    struct HdmiHdrAttr hdrAttr = {0};
512    int32_t ret;
513
514    ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS);
515
516    if (ret != 0) {
517        HDF_LOGE("HdmiDeepColorSet failed.");
518        return ret;
519    }
520    ret = HdmiDeepColorGet(handle, &color);
521    if (ret != 0) {
522        HDF_LOGE("HdmiDeepColorGet failed.");
523        return ret;
524    }
525    HDF_LOGE("HdmiDeepColorGet successful, color = %d.", color);
526    videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444;
527    videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED;
528    videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM;
529    videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL;
530    ret = HdmiSetVideoAttribute(handle, &videoAttr);
531    if (ret != 0) {
532        HDF_LOGE("HdmiSetVideoAttribute failed.");
533        return ret;
534    }
535    audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3;
536    audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S;
537    audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16;
538    audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K;
539    audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3;
540    ret = HdmiSetAudioAttribute(handle, &audioAttr);
541    if (ret != 0) {
542        HDF_LOGE("HdmiSetAudioAttribute failed.");
543        return ret;
544    }
545    hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3;
546    hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY;
547    hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048;
548    hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1;
549    hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709;
550    ret = HdmiSetHdrAttribute(handle, &hdrAttr);
551    if (ret != 0) {
552        HDF_LOGE("HdmiSetHdrAttribute failed.");
553        return ret;
554    }
555
556    return 0;
557}
558
559/* HDMI例程总入口 */
560static int32_t TestCaseHdmi(void)
561{
562    DevHandle handle = NULL;
563    int32_t ret;
564
565    struct HdmiHpdCallbackInfo info = {0};
566    uint8_t data[128] = {0};
567
568    HDF_LOGD("HdmiAdapterInit: successful.");
569    handle = HdmiOpen(0);
570    if (handle == NULL) {
571        HDF_LOGE("HdmiOpen failed.");
572        return ret;
573    }
574    info.data = handle;
575    info.callbackFunc = HdmiHpdHandle;
576    ret = HdmiRegisterHpdCallbackFunc(handle, &info);
577    if (ret != 0) {
578        HDF_LOGE("HdmiRegisterHpdCallbackFunc failed.");
579        return ret;
580    }
581
582    ret = HdmiReadSinkEdid(handle, data, 128);
583    if (ret <= 0) {
584        HDF_LOGE("HdmiReadSinkEdid failed.");
585        return ret;
586    }
587    HDF_LOGE("HdmiReadSinkEdid successful, data[6] = %d, data[8] = %d.", data[6], data[8]);
588
589    ret = TestHdmiSetAttr(handle);
590    if (ret != 0) {
591        HDF_LOGE("TestHdmiSetAttr failed.");
592        return ret;
593    }
594
595    ret = HdmiStart(handle);
596    if (ret != 0) {
597        HDF_LOGE("HdmiStart failed.");
598        return ret;
599    }
600
601    OsalMSleep(1000);
602
603    ret = HdmiStop(handle);
604    if (ret != 0) {
605        HDF_LOGE("HdmiStop failed.");
606        return ret;
607    }
608
609    ret = HdmiUnregisterHpdCallbackFunc(handle);
610    if (ret != 0) {
611        HDF_LOGE("HdmiUnregisterHpdCallbackFunc failed.");
612        return ret;
613    }
614    HdmiClose(handle);
615    return 0;
616}
617
618```