0%

RK3399 调试记录

RK3399 有两路MIPI CSI接口,支持两个摄像头同时预览。 瑞芯微也提供了东芝TC358749XBG芯片的驱动,将HDMI输入信号转为MIPI CSI的信号。

TC358749XBG有使能、待机、复位和中断等IO(使能和待机可以不使用)。

开发包提供的DTS配置里面,需要在i2c节点下面配置tc358749x节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
&i2c1 {
status = "okay";
tc358749x: tc358749x@0f {
#sound-dai-cells = <0>;
compatible = "toshiba,tc358749x";
reg = <0x0f>;
reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
int-gpios = <&gpio4 RK_PD5 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&hdmiin_gpios>;
status = "okay";
};
};

同时使用两路HDMI输入需要使用两片TC358749XBG芯片,连到不同的i2c bus。DTS文件需要增加下面的配置:

1
2
3
4
5
6
7
8
9
10
11
12
&i2c2 {
status = "okay";
tc358749xbg: tc358749x@0f {
#sound-dai-cells = <0>;
compatible = "toshiba,tc358749x";
reg = <0x0f>;
int-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&hdmiin2_gpios>;
status = "okay";
};
};

另外需要修改cam_board.xml配置文件,BoardFile节点下面保留原来TC358749XBG的CamDevie节点,然后再复制一份。需要修改的地方有:

节点1:

1
2
3
4
<SensorDevID IDname="CAMSYS_DEVID_SENSOR_1A"/>
<SensorI2cBusNum busnum="1"/>
<SensorPhy phyMode="CamSys_Phy_Mipi" lane="4" phyIndex="0" sensorFmt="CamSys_Fmt_Yuv422_8b"/>
<SensorFacing facing="back"/>

节点2:

1
2
3
4
<SensorDevID IDname="CAMSYS_DEVID_SENSOR_1B"/>
<SensorI2cBusNum busnum="2"/>
<SensorPhy phyMode="CamSys_Phy_Mipi" lane="4" phyIndex="1" sensorFmt="CamSys_Fmt_Yuv422_8b"/>
<SensorFacing facing="back"/>

HDMI输入的图像不需要镜像,所以两路输入都设为后置摄像头。

这样修改完之后,开机就可以识别到两个摄像头,并且可以单独预览。但是两个摄像头同时预览会有问题:正常打开一次后,无法关闭摄像头。结果是再次打开单个或两个摄像头的时候会失败,需要重启系统才行。

经排查发现是第二个摄像头关闭的函数没有返回,造成了阻塞。所以再次打开摄像头会失败。

进一步排查找到问题出在TC358749XBG的驱动程序。调用启动摄像头函数时,驱动程序会启动一个线程,在后台与TC358749XBG芯片交互,处理图像数据。调用关闭摄像头函数时,需要等待后台线程正常退出。问题就出在两个摄像头同时打开的时候,第二个摄像头启动的线程不能正常退出。

原来开发TC358749XBG驱动的人没有想到会有人同时使用两路HDMI输入,所以在驱动中使用了一些静态变量来运行后台线程。两个摄像头同时预览的时候相当于两个摄像头共用了一个后台线程,然后第一个摄像头关闭的时候线程已经退出了,第二个摄像头就没办法正常关闭了,造成了死锁。

知道了问题所在,剩下的就好解决了。解决方法也很粗暴,将原来的静态变量和线程函数复制一份。在打开摄像头的时候根据i2cbusnum的值来确定使用哪组静态变量。

修改完之后就可以同时预览两路HDMI的输入了。