HDMI-IN背景知识
现在家庭娱乐中心,设备一般有IPTV盒子、NAS带影音播放器、投影仪、音箱、甚至高级点有KTV点歌机等设备。这些设备如果分别切换使用那是相当麻烦,关掉A打开B,电源不断开关、线需要不断拔插。这种场景下,HDMI作为一个非常流行的标准接口就派上用场了,可以实现一个设备的显示输出作为另一个设备的输入。这样,通过一个屏幕就可以直接显示另外一个设备的音视频,显示器不需要切换非常方便。
市面上大部分的家庭娱乐设备大多是arm架构,一些主流的arm芯片已支持HDMI-IN功能、即使不支持通过第三方的HDMI-IN芯片也可以实现这样的功能。
大部分HDMI-IN的功能实现和USB Camera一样,基于V4L2(Video4linux2)的框架,所以很明显的暴露给上层的接口就是 /dev/videoXX的一个设备,可以通过普通的相机就可以录音拍照,实现视听功能。
故障记录
公司的产品(SoC自带HDMI RX功能)上发现某些HDMI-IN输入源无法显示,查看kernel log信息,可以看到有热拔插信号被检测到,但是kernel HDMI-IN驱动检测到HDMI输入源接入,初始化的过程中判断hdmi输入源的信息时无法获取到正确的寄存器状态,导致驱动没有正常运行。这时看起来问题很显然,但是确无从下手,只能稍微抽象下“不同输入源,驱动运行有别”,这仿佛是一个哲学问题。
故障分析定位
人性最大的弱点就是在错误中徘徊,这一点码农最为洞悉,犹如马云说花钱比赚钱难一样,这东西违背常理但是事实。这不,面对这个bug,我又犯了常规错误,万劫不复方现光明。
开始分析时一通操作猛如虎,各种出错定位、逻辑分析、结构清晰的代码被分析的支离破碎,觉得哪哪都可能是问题之源,由于故障导致的无法走下去的逻辑被强制修改,事实无济于事。收获如下:
驱动似乎没问题啊
接着想到,差别只有输入源,但是不同的hdmi输入源之间的差别是不知道的,唯一确定的是差别的输入源的会导致寄存器初始化状态异常,这种情况最大的可能是一些驱动本身init的执行中导致,即使init执行是完整的,也是导致问题的根源。
沉下心和世界沟通,总能发现美好。这时可以看到Hdmi_InitSrc的一个函数名,假想在驱动作者的思路,这多么符合输入源初始化这个步骤。这段代码刚才也扫过多次确未能引起重视,现在确可以限定范围在此精读,别无他法。
Hdmi_InitSrc中又包含了hdmi_phy_port_select、Hdmi_Power、Hdmi_TmdsInit、Hdmi_MacInit、 Hdmi_AudioOutputDisable等几个分步骤,分别分析,这时看到Hdmi_MacInit中有一段针对hdmi 2.0协议的特殊逻辑,怀疑与这些特殊的输入源有关。继续分析可以看到有i2c通道资源占用的一些设置,如果当前i2c空闲则写入正确,否则写入的值是空的,这样hdmi-in工作异常了。
这时kernel增加配置一个i2c通道,编译测试工作ok。
总结
故障总是出现在细微处,不能完全理解作者意图的时候,分析非常耗时。耗费整整3天半的时间。
网友评论