这篇文章给大家介绍一下在Rk356X等平台,HDMIIN的调试,RK356X的平台没有自带的HDMIRX的模块,因此只能通过外接转接芯片来完成,常见的一般是HDMI转MIPI-CSI和HDMI转BT1120等芯片,这篇文章主要介绍一下在RK356X平台上面,上面两种转接芯片的调试。
目录
(一)HDMIIN VIDEO框架
(1)类camera框架
RK356X/RK3399平台上的HDMIIN实现都是通过HDMI转MIPI或者转BT1120等转接芯片实现的,因此驱动代码框架是基于V4L2的camera框架实现的,将转接芯片当做是一个类camera设备,注册成v4l2的节点,通过media-framework的框架与主控vicap控制器link,应用层从对应的video节点取数据流。这里需要注意一下几点:
- HDMIIN的转接芯片一般直接输出YUV422的数据格式,主控将其当做是SOC camera设备,不需要ISP的3A调试。
- RK3399/RK3288等CIF不支持MIPI接口,因此只能使用ISP接收HDMIIN的数据。
- RK3568/RK3566平台VICAP(CIF)控制器支持MIPI接口,因此在该平台上的时候,不需要经过ISP,vicap接收数据即可。本文即以RK3568为例进行介绍。
- 针对HDMIN的特定功能,如拔插、分辨率切换等功能,驱动定制化实现相关接口。
(2)HDMIIN基本流程
HDMIIN的基本流程如下图所示,驱动成功注册,安卓上层将转接芯片识别成camera设备后,HDMIIN定制的APK打开预览,会定时查询当前的拔插状态和分辨率,识别到插入的状态,APK会下发正确的分辨率进行预览。
(二)功能调试
(1)驱动调试
HDMIIN的设备驱动相比于正常的camera驱动会针对HDMIIN的应用场景多出几个部分内容:拔插和分辨率切换功能的识别。这里以龙讯的LT6911UXC调试作为示例。
①驱动接口介绍
这里主要介绍一下HDMIIN的驱动对比camera的驱动增加的一些接口,并对接口进行说明
query_dv_timings:查询timing信息的接口,给应用查询分辨率格式等信息
s_dv_timings:设置timing
g_dv_timings:获取timing
lt6911uxc_res_change_irq_handler:分辨率变化的中断处理函数,最终执行到lt6911uxc_format_change,会上报分辨率变化的事件。
plugin_detect_irq_handler:拔插的中断处理函数。
lt6911uxc_get_ctrl:获取拔插状态的接口,应用通过这个接口获取拔插的状态。
驱动代码主要主要注意增加拔插和分辨率变化中断,query_dv_timings和_get_ctrl,APK分别通过这两个接口获取分辨率信息和拔插的状态。
②DTS配置说明
dts配置参考如下,链路对应为:LT6911UXC->CSI_DPHY0->MIPI_CSI2->RKCIF_MIPI_LVDS
&i2c3 {
status = "okay";
lt6911uxc: lt6911uxc@2b {
status = "okay";
reg = <0x2b>;
compatible = "lontium,lt6911uxc";
clocks = <&ext_cam_clk>;
clock-names = "xvclk";
interrupt-parent = <&gpio4>;
interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
power-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
plugin-det-gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
hpd-ctl-gpios = <&gpio3 27 GPIO_ACTIVE_LOW>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "LT6911UXC";
rockchip,camera-module-lens-name = "NC";
port {
lt6911uxc_out: endpoint {
remote-endpoint = <&hdmi_to_mipi_in>;
data-lanes = <1 2 3 4>;
};
};
};
};
&csi2_dphy_hw {
status = "okay";
};
&csi2_dphy0 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
hdmi_to_mipi_in: endpoint@1 {
reg = <1>;
remote-endpoint = <<6911uxc_out>;
data-lanes = <1 2 3 4>;
};
};
port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
csidphy_out: endpoint@1 {
reg = <1>;
remote-endpoint = <&mipi_csi2_input>;
data-lanes = <1 2 3 4>;
};
};
};
};
&mipi_csi2 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
mipi_csi2_input: endpoint@1 {
reg = <1>;
remote-endpoint = <&csidphy_out>;
data-lanes = <1 2 3 4>;
};
};
port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
mipi_csi2_output: endpoint@0 {
reg = <0>;
remote-endpoint = <&cif_mipi_in>;
data-lanes = <1 2 3 4>;
};
};
};
};
&rkcif {
status = "okay";
};
&rkcif_mipi_lvds {
status = "okay";
port {
cif_mipi_in: endpoint {
remote-endpoint = <&mipi_csi2_output>;
data-lanes = <1 2 3 4>;
};
};
};
&rkcif_mmu {
status = "okay";
};
③常见调试命令
以下是常见的调试命令。
查看拓扑结构:
media-ctl -p
抓数据流,正常会输出帧率信息
v4l2-ctl --verbose -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat='NV12' --stream-mmap=4 --set-selection=target=crop,flags=0,top=0,left=0,width=1920,height=1080
抓图命令:
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat='NV12' --stream-mmap=3 --stream-skip=4 --stream-to=/data/1920x1080p60_nv12.yuv --stream-count=5 --stream-poll
(2)应用调试
①XML适配
类似camera,需要配置对应的xml,安卓应用才能注册上camera设备:
<Profiles cameraId="0" name="LT6911UXC" moduleId="m00">
②APK适配
APK通过ioctl的方式访问LT6911UXC设备节点,获取当前的连接状态和分辨率。LT6911UXC设备节点在isp/isp/vicap链路上可能会差异。需要根据实际情况修改APK源码.
rkCamera2/jni/native.cpp
(三)总结
HDMIIN设备类似camera设备,基于V4L2框架和media-framework,只需要重点注意HDMIIN相比于camera多了分辨率切换和拔插的动作,在rk356x/rk3399等的平台上,驱动是提供对应的接口,应用上面通过ioctl查询对应的状态,然后apk执行开关的操作,在RK3588后续的平台上,已经改成由驱动上报事件,应用订阅事件的方式来完成,后续会再介绍。