目录
HDMI涉及的知识较多,这里做一些HDMI的简要分析,希望能给大家提供一些思路
所在层次 | 名称 | 代码路径 |
---|---|---|
kernel | driver | release/aml-comp/kernel/aml-5.4/drivers/amlogic/media/cec release/aml-comp/kernel/aml-5.4/drivers/amlogic/media/vin/tvin/hdmirx //注意TV没有tx的应用场景 release/aml-comp/kernel/aml-5.4/drivers/amlogic/media/vout/hdmitx release/aml-comp/kernel/aml-5.4/drivers/amlogic/media/vout/hdmitx21 |
kernel | dts | release/aml-comp/kernel/aml-5.4/arch/arm/boot/dts/amlogic/t5d_t950d4_am301_linux_1.5g_cvte.dts //1.5g指ddr内存 release/aml-comp/kernel/aml-5.4/arch/arm/boot/dts/amlogic/t5d_t950d4_am301_linux_1g_cvte.dts release/aml-comp/kernel/aml-5.4/arch/arm/boot/dts/amlogic/t5d_t950d4_am301_linux_512m_cvtelinux.dts //以上修改的话最好一起修改,覆盖不同芯片多个方案 |
kernel | pinctrl子系统 | release/aml-comp/kernel/aml-5.4/kernel/aml-5.4/drivers/pinctrl/meson/* |
boot | board config | release/aml-comp/uboot/bl33/v2015/board/amlogic/configs/t5d_am301_v1.h |
boot | hdmi | release/aml-comp/uboot/bl33/v2015/arch/arm/cpu/armv8/txl/hdmirx release/aml-comp/uboot/bl33/v2015/arch/arm/cpu/armv8/txl/hdmitx20 release/aml-comp/uboot/bl33/v2015/arch/arm/cpu/armv8/txl/cec |
boot | cli 命令行实现 | release/aml-comp/linux/uboot/bl33/v2015/common/cmd_hdmirx.c |
1、T950D4 原厂文档 通过最重要的datasheet文档查看HDMI简介和寄存器;
2、内部kb
硬件专区:22.HDMI
维基百科:https://zh.wikipedia.org/wiki/HDMI
3、标准协议
4、知网论文
5、网络资料
HDMI接口规范:HDMI 信号接口及显示规范 - 百度文库
HDMI驱动框架(安卓方案,可参考):S5pv210 HDMI 接口在 Linux 3.0.8 驱动框架解析 (By liukun321 咕唧咕唧)_liukun321咕唧咕唧-CSDN博客
6、Debug文档
7、HDMI相关名词缩写速查表
HDMI: High-Definition Multimedia Interface
HDMI视屏和音频信号传输通道采用了的TMDS(Time Minimized Differential Signal)最小化差分信号传输。是一种差分信号传输方式。
HDCP: HDCP的全称是High-bandwidthDigital Content Protection,也就是“高带宽数字内容保护”。
DDC(IIC总线): Display Data Channel
CEC(单总线): Consumer Electronics Control消费电子控制通道
EDID: Extended Display Identification Data
E-EDIO: Enhanced Extended Display Identification Data 增强扩展显示识别数据
HDP(高低电平信号):HotPlugDetection
ARC:Audio Return Channel
ESM:ESM是HDMIRX里面跟HDCP2.2相关的模块
OTP(CEC):One Touch Play 一键播放
1)原理图
2)通过原理图查看HDMI电路是端子通过简单的阻容电路,然后直连主芯片的,注意这里只有HDMI_RX相关IO口,无HDMI_TX
详细介绍在手册Video Path章节,这里可以看出HDMI作为Video输入接口,由于TV方案没有TX场景(HDMI单向传输模式是最常见的用法,,也有高版本Hdmi2.1支持双向传输场景),因此这里没有HDMI_TX。
这里的框图也指示着video驱动系统的基本组成:
1)HDMI相关的驱动都是编进内核的
2)由于HDMI由多个组件组成,不同组件被划分为单个驱动模块管理,大致分类如下:
1、
值得注意,hdmirx文件夹下包含两个驱动
一个是hdcp相关的esm_rx模块
release/aml-comp/kernel/aml-5.4/drivers/amlogic/media/vin/tvin/hdmirx/hdcp_rx_main.c
一个是hdmi rx,这里重点分析
3、hdmi rx设备树介绍
release/aml-comp/kernel/aml-5.4/arch/arm/boot/dts/amlogic/t5d_t950d4_am301_linux_1.5g_cvte.dts
1)pinctrl
1)驱动入口init
release/aml-comp/kernel/aml-5.4/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c
驱动模型为平台设备驱动,这里实现了driver,没有实现device,设备信息从设备树里获取;
alloc_chrdev_region注册主设备号,后面会使用
class_create 在/sys/class创建hdmirx文件目录
2)probe初始化函数中的关键操作
1、获取设备树里的设备信息
后面使用设备树相关api获取设备信息
of_property_read_u32
2、寄存器map
3、字符设备注册与设备文件创建
hdmirx_add_cdev 将字符设备添加到系统
hdmirx_create_device:
分别在/dev/创建hdmirx0设备文件,在/sys/class/hdmirx创建hdmirx0文件目录
4、创建tasklet和队列任务处理中断等任务
5、hdmi寄存器初始化
6、创建输入设备
会统一在/dev/input/下创建event*文件,/sys/class/input/创建input*文件
具体的event号/input号可以通过查看 cat /proc/bus/input/devices (该文件记录所有的输入设备信息)获得
可以使用evtest/cat来监测event1事件
至此,driver probe完成
1)上电会执行hdmirx与esm hld驱动初始化
2)HDMI驱动的交互方法
1、用户->系统:用户主动调用fops接口
2、系统→用户:中断
1)
TV产品中,没有用到TX功能,这里就不做分析。
AO CEC说明 :?media: platform: Add support for the Amlogic Meson G12A AO CEC Controller [LWN.net]
实际作用是什么?可以支持同时与两个HDMI设备进行交互和控制
从上可以判断走的是else分支,接下来可以分析以下三个文件
├── hdmi_aocec_api.c //提供应用操作、硬件相关、msg相关、逻辑处理的api接口 ├── hdmi_ao_cec.c //cec驱动实现文件 ├── hdmi_cec_dump.c //提供dump调试接口 |
驱动模型在hdmi_ao_cec.c文件中实现,接下来主要分析这个文件
1)CEC采用的是经典的平台设备驱动模型
cec实现了driver,没有实现device,设备信息从设备树里获取;
2)先看probe的关键初始化操作
1、注册class和字符设备
1)class注册会在/sys/class创建名为cec的文件夹,用来放一些cec驱动相关的系统属性文件
2)字符设备注册后调用device_create 会在/dev和/sys/class/cec目录下生成cec设备文件"cec"
2、获取设备树id
后续可以使用设备树相关api去获取dts的配置
of_property_read_u32
of_property_read_bool
platform_get_resource_byname
3、注册输入设备
会统一在/dev/input/下创建event*文件,/sys/class/input/创建input*文件
具体的event号/input号可以通过查看 cat /proc/bus/input/devices (该文件记录所有的输入设备信息)获得
4、硬件初始化(配置cec寄存器)
5、创建队列和tasklet(中断下部分)来处理cec消息
6、fs_init
该操作主要目的是在/sys/class/cec下生成系统属性文件
1)上电初始化
可以看到上电会调用cec_init->cec probe:
2)cec驱动的交互方法
1、用户->系统:用户主动调用fops接口
2、系统->用户:中断 - 当有cec消息来到,首先进入中断,然后通过输入子系统上报给上层处理
可以利用以下属性来获取驱动信息和配置驱动
详细使用可详见驱动代码(原理参见linux sysfs机制):
release/aml-comp/kernel/aml-5.4/drivers/amlogic/media/cec/hdmi_ao_cec.c release/aml-comp/kernel/aml-5.4/drivers/amlogic/media/cec/hdmi_cec_dump.c |
以开启cec的log为例:
1、根据文件名找到对应的函数,查看文件的具体作用
dbg_en对应如下两个函数(说明,系统会省略掉show/store后缀)
2、操作dbg_en_show,则使用cat
cat /sys/class/cec/dbg_en |
3、操作dbg_en_store,,则使用echo
echo 1 > /sys/class/cec/dbg_en |
4、常用的还有:
/sys/class/input/
TV端HDMI的Hotplug功能依赖HPD/5V信号线,HPD/5V是主从设备交互的信号线,因此多个HDMI组件都会涉及HPD操作,比如edid交换、HDCP、CEC等都会用到,其中TV端负责接收,会操作HPD,source端(比如DVD碟机)负责5v。
以DVD碟机为source端为例:
1、DVD碟机(source端)->5v信号->TV(接受端)
2、TV检测到5V,再拉高HDP,完成握手,注意发送端负责主动拉5V,接收端负责拉HPD回应source端
3、DVD碟机读取TV的EDID,决定输出什么类型信号给TV
hotplug相关接口在hdmi_rx_hw.c文件中 1、设置接口 void hdmirx_hdcp22_hpd(bool value); void rx_force_hpd_cfg(u8 hpd_level); int rx_set_port_hpd(u8 port_id, bool val); void rx_set_cur_hpd(u8 val, u8 func); unsigned int rx_get_hdmi5v_sts(void); unsigned int rx_get_hpd_sts(void); void rx_force_hpd_cfg(u8 hpd_level); void rx_force_rxsense_cfg(u8 level); void rx_force_hpd_rxsense_cfg(u8 level); void rx_hpd_to_esm_handle(struct work_struct *work); 2、相关标志位 hpd_low_cec_off 初始化代码(hdmi_rx_drv.c): ret = of_property_read_u32(pdev->dev.of_node,"hpd_low_cec_off", &hpd_low_cec_off); if (ret) hpd_low_cec_off = 1; 设备树配置: hpd_low_cec_off = <1>; |
关于RxSense的简单介绍:原理是通过TMDS信号来检查是否插入,是5V和HPD的重要补充。
https://www.linkedin.com/pulse/importance-hdmi-rxsense-accurate-connection-detection-ariel-marcus
hotplug接口比较零散,被不同的场景功能函数所调用,需要具体场景具体分析
1、hdmi_rx驱动中会Export一个hotplug控制接口给到cec驱动调用 - “hdmirx_set_cec_cfg”
hdmitx_cec_ioctl中两个case会涉及hotplug操作
CEC_IOC_SET_OPTION_ENALBE_CEC
CEC_IOC_SET_OPTION_WAKEUP
即CEC使能,CEC唤醒功能
2、hdmi_rx休眠关闭时会根据hdmirx_set_cec_cfg接口中设置cec和auto_power_on使能标志位是否拉低或者无动作
3、关于CEC唤醒为什么要求Hotplug为高的说明,这是因为考虑到设备兼容性问题,设备与TV的交互大致流程如下:
当设备唤醒TV后,TV输出hdp信号时间不确定,有些外设备如果上电后检测不到hotplug信号,则之后不会输出信号给TV,即使等到TV上电完后拉高hpd也不会输出,因此要保持待机时hpd为恒高,或者TV开机第一时间拉高hpd。