# HDMI
## Overview
- The High-Definition Multimedia Interface (HDMI) is an audio/video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, Toshiba.
- The HDMI works in master/slave mode and usually has a source and a sink.
- The HDMI APIs provide a set of common functions for HDMI transmission, including:
- Opening and closing an HDMI controller.
- Starting and stopping HDMI transmission.
- Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute.
- Reading the raw Extended Display Identification Data (EDID) from a sink.
- Registering and unregistering a callback for HDMI hot plug detect.
- [Figure 1](#fig1) shows the HDMI physical connection.
**Figure 1** HDMI physical connection
![](figures/HDMI_physical_connection.png "HDMI_physical_connection")
## Available APIs
**Table 1** HDMI driver APIs
Category
|
API
|
Description
|
Managing HDMI controllers
|
HdmiOpen
|
Opens an HDMI controller.
|
HdmiClose
|
Closes an HDMI controller.
|
Starting or stopping HDMI transmission
|
HdmiStart
|
Starts HDMI transmission.
|
HdmiStop
|
Stops HDMI transmission.
|
Setting an HDMI controller
|
HdmiAvmuteSet
|
Sets the AV mute feature.
|
HdmiDeepColorSet
|
Sets the color depth.
|
HdmiDeepColorGet
|
Obtains the color depth.
|
HdmiSetVideoAttribute
|
Sets video attributes.
|
HdmiSetAudioAttribute
|
Sets audio attributes.
|
HdmiSetHdrAttribute
|
Sets HDR attributes.
|
Reading EDID
|
HdmiReadSinkEdid
|
Reads the raw EDID from a sink.
|
Registering or unregistering a callback for HDMI hot plug detect
|
HdmiRegisterHpdCallbackFunc
|
Registers a callback for HDMI hot plug detect.
|
HdmiUnregisterHpdCallbackFunc
|
Unregisters the callback for HDMI hot plug detect.
|
## Usage Guidelines
### How to Use
[Figure 2](#fig2) shows how HDMI works.
**Figure 2** How HDMI works
![](figures/HDMI_usage_flowchart.png "HDMI_usage_flowchart")
### Opening an HDMI Controller
Before HDMI communication, call **HdmiOpen** to enable an HDMI controller.
```c
DevHandle HdmiOpen(int16_t number);
```
**Table 2** Description of HdmiOpen
Parameter
|
Description
|
number
|
HDMI controller ID.
|
Return Value
|
Description
|
NULL
|
Failed to open the HDMI controller.
|
Controller handle
|
Handle of the HDMI controller opened.
|
For example, the system has two HDMI controllers, numbered 0 and 1. Open controller 0.
```c
DevHandle hdmiHandle = NULL; /* HDMI controller handle /
/* Open HDMI controller 0. */
hdmiHandle = HdmiOpen(0);
if (hdmiHandle == NULL) {
HDF_LOGE("HdmiOpen: failed\n");
return;
}
```
### Registering a Callback for Hot Plug Detect
```c
int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback);
```
**Table 3** Description of HdmiRegisterHpdCallbackFunc
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
callback
|
Callback invoked to return the hot plug detect result.
|
Return Value
|
Description
|
0
|
The callback is registered successfully.
|
Negative number
|
Failed to register the callback.
|
The following is an example of registering a callback for hot plug detect:
```c
/* Definition of the callback for hot plug detect */
static void HdmiHpdHandle(void *data, bool hpd)
{
if (data == NULL) {
HDF_LOGE("priv data is NULL");
return;
}
if (hpd == true) {
HDF_LOGD("HdmiHpdHandle: hot plug");
/* Add related processing if required. */
} else {
HDF_LOGD("HdmiHpdHandle: hot unplog");
/* Add related processing if required. */
}
}
/* Example of registering a callback for hot plug detect */
struct HdmiHpdCallbackInfo info = {0};
info.data = handle;
info.callbackFunc = HdmiHpdHandle;
ret = HdmiRegisterHpdCallbackFunc(hdmiHandle, info);
if (ret != 0) {
HDF_LOGE("HdmiRegisterHpdCallbackFunc: Register failed.");
}
```
### Reading the EDID
```c
int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);
```
**Table 4** Description of HdmiReadSinkEdid
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
buffer
|
Data buffer.
|
len
|
Data length.
|
Return Value
|
Description
|
Positive integer
|
Raw EDID read.
|
Negative number or **0**
|
Failed to read the EDID.
|
The following is an example of reading the raw EDID data from a sink:
```c
int32_t len;
uint8_t edid[HDMI_EDID_MAX_LEN] = {0};
len = HdmiReadSinkEdid(hdmiHandle, edid, HDMI_EDID_MAX_LEN);
if (len <= 0) {
HDF_LOGE("%s: HdmiReadSinkEdid failed len = %d.", __func__, len);
}
```
### Setting Video, Audio, and HDR Attributes
#### Setting Audio Attributes
```c
int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr);
```
**Table 5** Description of HdmiSetAudioAttribute
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
attr
|
Audio attributes.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of setting audio attributes:
```c
struct HdmiAudioAttr audioAttr = {0};
int32_t ret;
audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3;
audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S;
audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16;
audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K;
audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3;
ret = HdmiSetAudioAttribute(handle, &audioAttr);
if (ret != 0) {
HDF_LOGE("HdmiSetAudioAttribute failed.");
}
```
#### Setting Video Attributes
```c
int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr);
```
**Table 6** Description of HdmiSetVideoAttribute
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
attr
|
Video attributes.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of setting video attributes:
```c
struct HdmiVideoAttr videoAttr = {0};
int32_t ret;
videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444;
videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED;
videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM;
videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL;
ret = HdmiSetVideoAttribute(handle, &videoAttr);
if (ret != 0) {
HDF_LOGE("HdmiSetVideoAttribute failed.");
}
```
#### Setting HDR Attributes
```c
int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr);
```
**Table 7** Description of HdmiSetHdrAttribute
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
attr
|
HDR attributes.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of setting HDR attributes:
```c
struct HdmiHdrAttr hdrAttr = {0};
int32_t ret;
hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3;
hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY;
hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048;
hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1;
hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709;
ret = HdmiSetHdrAttribute(handle, &hdrAttr);
if (ret != 0) {
HDF_LOGE("HdmiSetHdrAttribute failed.");
}
```
### Setting Other Attributes
#### Setting HDMI AV Mute
```c
int32_t HdmiAvmuteSet(DevHandle handle, bool enable);
```
**Table 8** Description of HdmiAvmuteSet
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
enable
|
Whether the AV mute feature is enabled.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of setting AV mute:
```c
int32_t ret;
ret = HdmiAvmuteSet(hdmiHandle, true);
if (ret != 0) {
HDF_LOGE("HdmiAvmuteSet failed.");
}
```
#### Setting the Color Depth
```c
int32_t HdmiDeepColorSet(DevHandle handle, enum HdmiDeepColor color);
```
**Table 9** Description of HdmiDeepColorSet
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
color
|
Color depth to set.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of setting the color depth:
```c
int32_t ret;
ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS);
if (ret != 0) {
HDF_LOGE("HdmiDeepColorSet failed.");
}
```
#### Obtaining the Color Depth
```c
int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color);
```
**Table 10** Description of HdmiDeepColorGet
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
color
|
Color depth.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of obtaining the color depth:
```c
enum HdmiDeepColor color;
int32_t ret;
ret = HdmiDeepColorGet(handle, &color);
if (ret != 0) {
HDF_LOGE("HdmiDeepColorGet failed.");
}
```
### Starting HDMI Transmission
```c
int32_t HdmiStart(DevHandle handle);
```
**Table 11** Description of HdmiStart
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of starting HDMI transmission:
```c
int32_t ret;
ret = HdmiStart(hdmiHandle);
if (ret != 0) {
HDF_LOGE("Failed to start transmission.");
}
```
### Stopping HDMI Transmission
```c
int32_t HdmiStop(DevHandle handle);
```
**Table 12** Description of HdmiStop
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of stopping HDMI transmission:
```c
int32_t ret;
ret = HdmiStop(hdmiHandle);
if (ret != 0) {
HDF_LOGE("Failed to stop transmission.");
}
```
### Unregistering the Callback for Hot Plug Detect
```c
int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle);
```
**Table 13** Description of HdmiUnregisterHpdCallbackFunc
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
Return Value
|
Description
|
0
|
The operation is successful.
|
Negative number
|
The operation failed.
|
The following is an example of unregistering the callback for hot plug detect:
```c
int32_t ret;
ret = HdmiUnregisterHpdCallbackFunc(hdmiHandle);
if (ret != 0) {
HDF_LOGE("unregister failed.");
}
```
### Closing an HDMI Controller
```c
void HdmiClose(DevHandle handle);
```
**Table 14** Description of HdmiClose
Parameter
|
Description
|
handle
|
HDMI controller handle.
|
The following is an example of closing an HDMI controller:
```c
HdmiClose(hdmiHandle);
```
## Example
This following example shows how to use HDMI APIs to manage an HDMI device on a Hi3516D V300 development board.
A virtual driver is used in this example. The hardware information is as follows:
- SoC: Hi3516D V300
- HDMI controller: HDMI controller 0
The sample code is as follows:
```c
#include "hdmi_if.h" /* Header file for HDMI standard APIs */
#include "hdf_log.h" /* Header file for log APIs */
##include "osal_time.h" /* Header file for delay and sleep APIs */
/* Callback for hog plug detect */
static void HdmiHpdHandle(void *data, bool hpd)
{
if (data == NULL) {
HDF_LOGE("priv data is NULL");
return;
}
if (hpd == true) {
HDF_LOGD("HdmiHpdHandle: hot plug");
/* Add related processing if required. */
} else {
HDF_LOGD("HdmiHpdHandle: hot unplog");
/* Add related processing if required. */
}
}
/* Set HDMI attributes. */
static int32_t TestHdmiSetAttr(DevHandle handle)
{
enum HdmiDeepColor color;
struct HdmiVideoAttr videoAttr = {0};
struct HdmiAudioAttr audioAttr = {0};
struct HdmiHdrAttr hdrAttr = {0};
int32_t ret;
ret = HdmiDeepColorSet(handle, HDMI_DEEP_COLOR_48BITS);
if (ret != 0) {
HDF_LOGE("HdmiDeepColorSet failed.");
return ret;
}
ret = HdmiDeepColorGet(handle, &color);
if (ret != 0) {
HDF_LOGE("HdmiDeepColorGet failed.");
return ret;
}
HDF_LOGE("HdmiDeepColorGet successful, color = %d.", color);
videoAttr.colorSpace = HDMI_COLOR_SPACE_YCBCR444;
videoAttr.colorimetry = HDMI_COLORIMETRY_EXTENDED;
videoAttr.extColorimetry = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM;
videoAttr.quantization = HDMI_QUANTIZATION_RANGE_FULL;
ret = HdmiSetVideoAttribute(handle, &videoAttr);
if (ret != 0) {
HDF_LOGE("HdmiSetVideoAttribute failed.");
return ret;
}
audioAttr.codingType = HDMI_AUDIO_CODING_TYPE_MP3;
audioAttr.ifType = HDMI_AUDIO_IF_TYPE_I2S;
audioAttr.bitDepth = HDMI_ADIO_BIT_DEPTH_16;
audioAttr.sampleRate = HDMI_SAMPLE_RATE_8K;
audioAttr.channels = HDMI_AUDIO_FORMAT_CHANNEL_3;
ret = HdmiSetAudioAttribute(handle, &audioAttr);
if (ret != 0) {
HDF_LOGE("HdmiSetAudioAttribute failed.");
return ret;
}
hdrAttr.mode = HDMI_HDR_MODE_CEA_861_3;
hdrAttr.userMode = HDMI_HDR_USERMODE_DOLBY;
hdrAttr.eotfType = HDMI_EOTF_SMPTE_ST_2048;
hdrAttr.metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1;
hdrAttr.colorimetry = HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709;
ret = HdmiSetHdrAttribute(handle, &hdrAttr);
if (ret != 0) {
HDF_LOGE("HdmiSetHdrAttribute failed.");
return ret;
}
return 0;
}
/* Main entry of HDMI routines */
static int32_t TestCaseHdmi(void)
{
DevHandle handle = NULL;
int32_t ret;
struct HdmiHpdCallbackInfo info = {0};
uint8_t data[128] = {0};
HDF_LOGD("HdmiAdapterInit: successful.");
handle = HdmiOpen(0);
if (handle == NULL) {
HDF_LOGE("HdmiOpen failed.");
return ret;
}
info.data = handle;
info.callbackFunc = HdmiHpdHandle;
ret = HdmiRegisterHpdCallbackFunc(handle, &info);
if (ret != 0) {
HDF_LOGE("HdmiRegisterHpdCallbackFunc failed.");
return ret;
}
ret = HdmiReadSinkEdid(handle, data, 128);
if (ret <= 0) {
HDF_LOGE("HdmiReadSinkEdid failed.");
return ret;
}
HDF_LOGE("HdmiReadSinkEdid successful, data[6] = %d, data[8] = %d.", data[6], data[8]);
ret = TestHdmiSetAttr(handle);
if (ret != 0) {
HDF_LOGE("TestHdmiSetAttr failed.");
return ret;
}
ret = HdmiStart(handle);
if (ret != 0) {
HDF_LOGE("HdmiStart failed.");
return ret;
}
OsalMSleep(1000);
ret = HdmiStop(handle);
if (ret != 0) {
HDF_LOGE("HdmiStop failed.");
return ret;
}
ret = HdmiUnregisterHpdCallbackFunc(handle);
if (ret != 0) {
HDF_LOGE("HdmiUnregisterHpdCallbackFunc failed.");
return ret;
}
HdmiClose(handle);
return 0;
}
```