Android4.4系统是支持HDMI输出显示的,主要体现Androd框架层的支持,及用户设置界面关于HDMI参数设置。
下面我们看一下Android的图形显示系统框架:
HDMI的输出是由 SurfaceFlinger控制Mali Display(HW
Composer)输出的,我们会从HDMI HAL层代码看到 HW
Composer硬件合成器输出图像到HDMI显示设备,硬件合成器是Honeycomb(android
发布版本)引入的一个HAL,SurfaceFlinger使用它,利用硬件资源来加速Surface的合成,比如3D GPU和2D的图形引擎。
Android的Framwork层已经支持HDMI的输出显示,我们重点关注的是HDMI
HAL层的实现代码,这也是我们Porting工作最重要的部分。
首先我们看一下HDMI HAL层相关文件夹:
iTop4412_KK4.4/hardware/samsung_slsi/exynos4/libhdmi
iTop4412_KK4.4/hardware/samsung_slsi/exynos4/libhwc
libhdmi文件夹是我们重点关注的对象,里面共有三个子文件夹:
iTop4412_KK4.4/hardware/samsung_slsi/exynos4/libhdmi/ libhdmiservice
iTop4412_KK4.4/hardware/samsung_slsi/exynos4/libhdmi/ libsForhdmi
iTop4412_KK4.4/hardware/samsung_slsi/exynos4/libhdmi/ SecHdmi
■ libhdmiservice: 该文件夹会编译形成 libTVOut.so,
libhdmiclient.so库文件。
libhdmiservice文件夹提供了SecHdmiClient类的实现,及SecHdmiClient类对象的创建函数SecHdmiClient::getInstance(),硬件合成器libhwc会调用SecHdmiClient::getInstance()函数创建全局唯一的SecHdmiClient对象,使用对象指针mHdmiClient指向该对象。
libhwc文件夹的关键文件hwc.cpp,也是硬件合成器libhwc的HAL层文件,该文件会通过对象指针调用
SecHdmiClient的接口函数,比如使能HDMI,设置HDMI的分辨率等等:
hwc.cpp调用SecHdmiClient类接口函数的相关代码片段:
#if defined(BOARD_USES_HDMI)
*android::SecHdmiClient *mHdmiClient =
android::SecHdmiClient::getInstance();*
if (skip_hdmi_rendering == 1)
return 0;
if (contents == NULL) {
// Don’t display unnecessary image
mHdmiClient->setHdmiEnable(0);
return 0;
} else {
mHdmiClient->setHdmiEnable(1);
}
#ifdef SUPPORT_AUTO_UI_ROTATE
#if 0 //yqf, move to FramebufferNativeWindow
cur = &list->hwLayers[0];
*//LOGE(“%s, cur->tran:%d \n”,__func__,cur->transform); //added
yqf*
if (cur->transform == HAL_TRANSFORM_ROT_90 )//added yqf for test
mHdmiClient->setHdmiRotate(90, ctx->num_of_hwc_layer);
else if(cur->transform == HAL_TRANSFORM_ROT_270)
mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer);
else if(cur->transform == HAL_TRANSFORM_ROT_180)
mHdmiClient->setHdmiRotate(180, ctx->num_of_hwc_layer);
else /*if(cur->transform == HAL_TRANSFORM_ROT_0)*/
mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer);
#endif
#endif
■ libhdmi文件夹里面包含了三个字文件夹libcec,libddc,libedid,通过名字我们也就知道这个文件夹负责与HDMI显示设备进行I2C通信,查询HDMI显示设备的显示能力,设置HDMI显示设备的分辨率。
EDID: Extended display identification
data,简称EDID,是指屏幕分辨率的信息,包括厂商名称与序号。一般EDID存在于显示器的PROM或EEPROM内。一般如要读取EDID都是透过I2C,slave
address是0x50。
EDID的获取是通过DDC进行的,DDC就是开发板与HDMI显示设备之间进行通信的通道,HDMI发送端设备会通过DDC读取显示器的EDID信息,然后根据EDID信息判断显示能力等显示参数。
查看开发板的硬件原理图,我们可以知道HDMI使用I2C0与显示设备通信,这里我们需要正确设置I2C通道:
#define DEV_NAME “/dev/i2c-0”
int DDCOpen()
{
int ret = 1;
// check already open??
if (ref_cnt > 0) {
ref_cnt++;
return 1;
}
// open
if ((ddc_fd = open(DEV_NAME,O_RDWR)) < 0) {
LOGE(“%s: Cannot open I2C_DDC : %s”,__func__, DEV_NAME);
ret = 0;
}
ref_cnt++;
return ret;
}
HDMI的CEC属于HDMI的扩展功能,我们没有使用到,这里不再解释。
HDMI的设备操作是通过Kernel
HDMI驱动提供的设备节点来进行的,HDMI相关的设备节点有:
重点内容
/dev/video16 Graphics0层设备节点
/dev/video17 Graphics1层设备节点
/dev/video20 Video层设备节点
/dev/graphics/fb0 frambuffer设备节点
/dev/HPD HDMI热插拔检测设备节点
SecHdmi 文件夹实现这些设备节点的打开,控制,关闭操作。
SecHdmi文件夹对外提供SecHdmi类对象调用接口,libhdmiservice文件夹会调用该对象的接口函数,用于底层设备节点的控制。
SecHdmi 文件夹也用于调用
libsForhdmi文件夹通过的EDID接口,来获取HDMI显示设备的显示能力,及设置显示设备的分辨率。
libhwc模块及libhdmi子模块调用关系:
另外Android4.4提供了libhdmiservice_jni.so
库文件,该库文件提供了Java界面HDMI参数设置的接口实现,libhdmiservice_jni.so文件最后也会调用到
libsForhdmi层用于控制HDMI显示设备参数。
Android4.4 Setting界面可以控制HDMI输出参数:
如果需要Android4.4编译生成的镜像支持HDMI显示,那么编译Android源代码前必须配置好HDMI相关的宏定义:
配置文件:iTop4412_KK4.4/device/samsung/smdk4x12/BoardConfig.mk
添加以下宏定义:
BOARD_USES_HDMI_SUBTITLES := true
BOARD_USES_HDMI := true
BOARD_HDMI_STD := STD_720P
BOARD_HDMI_DDC_CH := DDC_CH_I2C_0
BOARD_USES_FIMGAPI := true
BOARD_USES_HDMI_EDID := true
BOARD_USES_HDMI_JUMPER := false
这样我们的Android4.4即可支持HDMI显示,且默认输出720P分辨率,DDC采用I2C0进行通信,支持HDMI显示设备EDID信息的获取与配置。
以上作为iTOP-4412开发平台移植HDMI功能的过程总结,Android4.4-2015-07-02发版本的Kernel及Android层代码均包含Porting后的代码,也就是HDMI正常工作的代码,方便大家学习和产品研发.
HDMI功能支持音视频同步输出,这里我们重点讲解的是HDMI的Porting工作,如果对音视频同步输出有研究的朋友,可以自己阅读相关的代码,iTop4412开发板的HDMI是支持1080P,720P分辨率,同样支持音视频同步输出。
如果您在实际的项目中需要HDMI功能,请参考我们的原理图设计硬件,尽量使用相同的HDMI资源,这样您只需要关注硬件部分,驱动使用我们移植好的即可,否则需要您修改HDMI相关引脚配置,进行必要的调试工作,增加自己的工作量。