RK356x MIPI屏显示调试


1. 前言

最近接触RK3566,同时也是第一次调试MIPI屏,本文主要记录,从拿到RK3566原厂SDK后到点亮MIPI屏的过程。

2. 环境介绍

硬件:野火鲁班猫1开发板(RK3566)、野火5.5寸MIPI屏
软件:原厂RK3566 SDK

3. 思路介绍

本文不仅分享点屏的过程,顺便分享当遇到一个新平台时,又应该做哪些准备?
其实在Linux中,想把一块屏幕点亮(无论是MIPI、RGB、LVDS),无非都是改改设备树,一般是不需要改驱动的。那第一个问题来了,既然要改设备树,那具体改哪个设备树文件?里面的参数怎么去改?改完之后怎么编译及如何验证?这些问题就是去熟悉新平台的SDK时,要做的准备工作。
对于MIPI屏而言,在调试层面上来看,只是比别的接口类型的屏幕多了一些调试参数,如初始化序列、反初始化序列,这部分参数要向屏幕厂商获取。
所以调试思路总结如下:
1、确认要修改的设备树文件;
2、设备树中修改关键引脚(背光脚、复位脚、使能脚);
3、修改屏幕timing时序
4、修改上下电时序
5、修改初始化序列和反初始化序列;
6、显示路由配置

4. 确认要修改的设备树文件

在SDK根目录执行./build.sh lunch选择板级配置时,会列出如下选择:
image.png
各配置单的说明如下表:
image.png
这里我选择的是rockchip_rk3566_evb2_lp4x_v10_defconfig,该配置文件的内容如下:

# <SDK>/device/rockchip/rk3566_rk3568/rockchip_rk3566_evb2_lp4x_v10_defconfig

RK_KERNEL_DTS_NAME="rk3566-evb2-lp4x-v10-linux"
RK_PARAMETER="parameter-buildroot-fit.txt"
RK_USE_FIT_IMG=y

可以看到,这里写出了编译时所使用的设备树文件为:rk3566-evb2-lp4x-v10-linux.dts
但是打开这个设备树文件一看,什么东西都没有:
image.png
这个设备树文件应该是RK留出来给用户修改用的,后续MIPI屏的适配,主要都是在这个设备树作修改。其它设备树节点的定义都在*.dtsi中。这个设备树文件最后总共会包含4个*.dtsi,分别是:rk3566-evb2-lp4x-v10.dtsirk3566.dtsirk3568.dtsirk3568-evb.dtsi

5. 设备树中修改关键引脚

5.1. 添加dsi0节点

RK3566有两个MIPI-DSI接口,鲁班猫1开发板上的MIPI接口使用的是MIPI-DSI0,那就复制rk3568-evb.dtsi中的dsi0节点到rk3566-evb2-lp4x-v10-linux.dts中,以备后续的修改。
同时先修改status属性为okay:
image.png

5.2. 修改屏幕背光引脚

背光用的是PWM0_M1,而原厂默认用的是PWM4。
image.png
自行添加backlight节点,修改pwms = <&pwm0 0 50000 0>:
image.png
继续自行添加pwm0节点,使能pwm0并修改pinctrl-0为pwm0m1:
image.png
至此,关于背光部分修改结束。

5.3. 添加屏幕复位引脚

根据原理图可以得出复位引脚为GPIO3_A4:
image.png
原本的dsi0节点没有描述复位引脚,所以这里自行添加复位引脚:
image.png

5.4. 添加屏幕使能引脚

根据原理图可以得出使能引脚为GPIO0_C0:
image.png
原本的dsi0节点没有描述使能引脚,所以这里自行添加使能引脚。但在最后的测试中,屏幕一直点不亮,对比野火已经适配好的设备树发现,这里的enable-gpios并不起作用,同时还需添加power-supply属性,这应该是屏幕电源相关的控制:
image.png
同时在rk3568-evb.dtsi中添加mipi_dsi0_power属性和在pinctrl节点下添加mipi_dsi0_pwr_en引脚:image.png
image.png

6. 修改屏幕timing参数

修改dsi0节点下的屏幕timing参数,这部分参考规格书或直接向屏厂咨询:
image.png

# 分辨率fps = 60
其中clock-frequency = (hactive+hsync+hbp+hfp) * (vactive+vsync+vbp+vfp) * fps

7. 修改上下电时序

MIPI屏的上下电时序通常都在规格书的Power on/off sequence章节中:
image.png

8. 修改初始化序列和反初始化序列

MIPI上下电后需要发送初始化或退出指令才能使之正常工作,我们需要向屏幕厂商获得所谓的初始化序列,如下图只是一部分:
image.png
图中的是初始化代码,不是初始化序列,我们需要将初始化代码转换成初始化序列后填入设备树中。
这些初始化代码可以总结出三个指令:SET_GENERIC、W_D、delay_ms,不同厂商呈现出的代码可能不同,但实际是一个意思。
SET_GENERIC:写命令
W_D:写数据
delay_ms:毫秒延时
了解了代码的基本构成后,如何将这些初始化代码转换成初始化序列呢?
首先初始化序列的格式如下:

命令类型 + 延时数量 + 数据长度 + 数据

转换可以分三个步骤:
1、确认数据的个数;
2、根据数据的个数确定命令类型;
3、确定延时时间;

现在以下图为例将初始化代码转换成初始化序列:
image.png
1、有几个W_D(),就代表数据个数有几个,这里的数据个数为4;
2、命令类型一共有三种(0x05、0x15、0x39):
0x05: 单字节数据 (DCS Short Write, no parameters)
0x15: 双字节数据 (DCS Short Write, 1 parameter)
0x39: 多字节数据 (DCS Long Write, n parameters n > 2)
这个例子中,数据个数超过了两个,所以命令类型为0x39;
3、这里没有延时时间,所以延时时间为0x00
所以最后的初始化序列为:

39 00 04 B9 FF 83 99

再举一个双字节数据的例子:
image.png
1、有几个W_D(),就代表数据个数有几个,这里的数据个数为2;
2、命令类型一共有三种(0x05、0x15、0x39):
0x05: 单字节数据 (DCS Short Write, no parameters)
0x15: 双字节数据 (DCS Short Write, 1 parameter)
0x39: 多字节数据 (DCS Long Write, n parameters n > 2)
这个例子中,数据个数为两个,所以命令类型为0x15;
3、这里没有延时时间,所以延时时间为0x00
所以最后的初始化序列为:

15 00 02 D2 77

再举一个有延时的例子:
image.png
1、有几个W_D(),就代表数据个数有几个,这里的数据个数为1;
2、命令类型一共有三种(0x05、0x15、0x39):
0x05: 单字节数据 (DCS Short Write, no parameters)
0x15: 双字节数据 (DCS Short Write, 1 parameter)
0x39: 多字节数据 (DCS Long Write, n parameters n > 2)
这个例子中,数据个数为1个,所以命令类型为0x05;
3、这里的延时时间为200ms,需要转为16进制,转换后为0xC8;
所以最后的初始化序列为:

05 C8 01 11

了解了转换方法后,将所有初始化代码转换成初始化序列,这个过程需要耐心。最后填到设备树dsi0节点的panel-init-sequence属性中:
image.png
反初始化序列也是如此:
image.png

9. 显示路由配置

Rockchip平台的LCD Controller称为VOP(Video Output Processor),芯片中一般集
成1~2个VOP。只有支持两个VOP的芯片,才能支持双屏异显。RK3566不支持双屏异显。
自行在设备树中添加关于dsi的相关配置:
image.png
route_dsi0:打开logo显示,指定VOP为vp0
video_phy0:使能phy0
dsi0_in_vp0:VOP Rounting,使能vp0
dsi0_in_vp1:VOP Rounting,关闭vp1
同时关闭hdmi的相关配置:
image.png

10. 最终的设备树文件

这里给出最终修改后的设备树文件作参考:

# rk3566-evb2-lp4x-v10-linux.dts

// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
 *
 */

#include "rk3566-evb2-lp4x-v10.dtsi"
#include "rk3568-linux.dtsi"
#include <dt-bindings/display/rockchip_vop.h>

&vp0 {
	cursor-win-id = <ROCKCHIP_VOP2_CLUSTER0>;
};

// 电源域配置,和本次调试MIPI屏无关
&pmu_io_domains {
	status = "okay";
	pmuio2-supply = <&vcc3v3_pmu>;
	vccio1-supply = <&vccio_acodec>;
	vccio3-supply = <&vccio_sd>;
	vccio4-supply = <&vcc_3v3>;
	vccio5-supply = <&vcc_3v3>;
	vccio6-supply = <&vcc_1v8>;
	vccio7-supply = <&vcc_3v3>;
};

// dsi Host
&dsi0 {
	status = "okay";
	#address-cells = <1>;
	#size-cells = <0>;

	dsi0_panel: panel@0 {
		compatible = "simple-panel-dsi";
		reg = <0>;
		backlight = <&backlight>;

		reset-gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>;
		power-supply = <&mipi_dsi0_power>;
		//enable-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;
		
		enable-delay-ms = <35>;
		prepare-delay-ms = <6>;
		reset-delay-ms = <0>;
		init-delay-ms = <20>;
		unprepare-delay-ms = <0>;
		disable-delay-ms = <20>;

		size,width = <74>;
		size,height = <133>;

		dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
		dsi,format = <MIPI_DSI_FMT_RGB888>;
		dsi,lanes  = <4>;

		panel-init-sequence = [
			39 00 04 B9 FF 83 99
			15 00 02 D2 77
			39 00 10 B1 02 04 74 94 01 32 33 11 11 AB 4D 56 73 02 02
			39 00 10 B2 00 80 80 AE 05 07 5A 11 00 00 10 1E 70 03 D4
			15 00 02 36 02
			39 00 2D B4 00 FF 02 C0 02 C0 00 00 08 00 04 06 00 32 04 0A 08 21 03 01 00 0F B8 8B 02 C0 02 C0 00 00 08 00 04 06 00 32 04 0A 08 01 00 0F B8 01
			39 05 22 D3 00 00 00 00 00 00 06 00 00 10 04 00 04 00 00 00 00 00 00 00 00 00 00 01 00 05 05 07 00 00 00 05 40
			39 05 21 D5 18 18 19 19 18 18 21 20 01 00 07 06 05 04 03 02 18 18 18 18 18 18 2F 2F 30 30 31 31 18 18 18 18
			39 05 21 D6 18 18 19 19 40 40 20 21 06 07 00 01 02 03 04 05 40 40 40 40 40 40 2F 2F 30 30 31 31 40 40 40 40
			39 00 11 D8 A2 AA 02 A0 A2 A8 02 A0 B0 00 00 00 B0 00 00 00
			15 00 02 BD 01
			39 00 11 D8 B0 00 00 00 B0 00 00 00 E2 AA 03 F0 E2 AA 03 F0
			15 00 02 BD 02
			39 00 09 D8 E2 AA 03 F0 E2 AA 03 F0
			15 00 02 BD 00
			39 00 03 B6 8D 8D
			39 05 37 E0 00 0E 19 13 2E 39 48 44 4D 57 5F 66 6C 76 7F 85 8A 95 9A A4 9B AB B0 5C 58 64 77 00 0E 19 13 2E 39 48 44 4D 57 5F 66 6C 76 7F 85 8A 95 9A A4 9B AB B0 5C 58 64 77
			05 C8 01 11
			05 C8 01 29
		];

		panel-exit-sequence = [
			05 78 01 28
			05 00 01 10
		];

		disp_timings0: display-timings {
			native-mode = <&dsi0_timing0>;
			dsi0_timing0: timing0 {
				clock-frequency = <126884880>;
				hactive = <1080>;		//
				vactive = <1920>;		//
				hfront-porch = <5>;		//
				hsync-len = <5>;		//
				hback-porch = <5>;		//
				vfront-porch = <2>;		//
				vsync-len = <2>;		//
				vback-porch = <2>;		//
				hsync-active = <0>;
				vsync-active = <0>;
				de-active = <0>;
				pixelclk-active = <0>;
			};
		};

		ports {
			#address-cells = <1>;
			#size-cells = <0>;

			port@0 {
				reg = <0>;
				panel_in_dsi: endpoint {
					remote-endpoint = <&dsi_out_panel>;
				};
			};
		};
	};

	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		port@1 {
			reg = <1>;
			dsi_out_panel: endpoint {
				remote-endpoint = <&panel_in_dsi>;
			};
		};
	};
};

// backlight
&backlight {
	pwms = <&pwm0 0 50000 0>;
};

// backlight
&pwm0 {
	status = "okay";
	pinctrl-0 = <&pwm0m1_pins>;
};

// dsi logo
&route_dsi0 {
	status = "okay";
	connect = <&vp0_out_dsi0>;
};

// dsi phy
&video_phy0 {
	status = "okay";
};

// dsi VOP Routing
&dsi0_in_vp0 {
	status = "okay";
};

// dsi VOP Routing
&dsi0_in_vp1 {
	status = "disabled";
};

// hdmi logo
&route_hdmi {
	status = "disabled";
};

// hdmi VOP Routing
&hdmi_in_vp0 {
	status = "disabled";
};

// hdmi VOP Routing
&hdmi_in_vp1 {
	status = "disabled";
};

// hdmi Host
&hdmi {
	status = "disabled";
};

11. 调试

编译设备树:

./build.sh kernel

打包:

./build.sh firware

更新镜像,如果成功的话,在启动过程中会显示RK的logo,最后会启动weston桌面环境:
79200a8e-4209-4436-b53a-cdfff1d3daed.jpg

12. 总结

嵌入式Linux学习交流群:424571391

参考文章:LKD3568RK3399 Linux-SDK mipi屏幕驱动及调试

### 调试方法 在RK3568平台上调试MIPI显示时,首先需要确保硬件连接正确。MIPI接口的物理层由一对差分信号线组成,用于传输高速数据。因此,检查PCB布线是否符合MIPI标准是非常重要的,包括差分对的长度匹配和阻抗控制[^1]。 接下来是软件配置部分。对于Linux系统而言,内核中的DRM(Direct Rendering Manager)框架支持多种显示控制器,包括Rockchip系列芯片所使用的。你需要确认设备树中关于MIPI DSI控制器的部分是否正确设置了时钟频率、像素格式等参数。例如,在设备树源文件(.dtsi)中可能会有类似如下的配置: ```dts &mipi_dsi { status = "okay"; reset-gpios = <&gpio7 RK_PD4 GPIO_ACTIVE_LOW>; power-supply = <&vcc_3v3>; panel@0 { compatible = "your,panel-model"; reg = <0>; // 其他面板特定属性 }; }; ``` 此外,如果涉及到触摸功能,则需确保I2C接口的触摸控制器被正确识别并加载相应的驱动程序。比如Goodix GT9xx系列触控芯片就需要对应的驱动支持,并且要设置好GPIO中断引脚以及可能的复位引脚[^3]。 ### 常见问题及解决办法 - **驱动匹配失败**:这通常是因为设备树中的`compatible`字符串与实际使用的幕型号不一致导致的。查阅幕规格书来获取正确的`compatible`值,并更新到设备树中。 - **时钟计算误差**:MIPI DSI接口依赖于精确的时钟同步。若出现图像不稳定或无法显示的情况,请仔细核对DSI PHY时钟配置是否符合幕要求的数据速率。有时候需要调整内核中的时钟参数或者修改启动参数以达到最佳效果[^2]。 - **触摸坐标异常**:当发现触摸位置与实际点击位置不符时,可以尝试交换`touchscreen-size-x`和`touchscreen-size-y`这两个属性值,因为它们定义了触摸区域的实际尺寸,错误地设定会导致坐标映射出错[^3]。 - **无触摸响应**:检查I2C总线状态,使用`i2cdetect -y [bus number]`命令查看能否检测到触摸IC地址;同时确认驱动程序已加载并且没有报错信息。 - **显示颜色/分辨率不对**:验证视频模式定时寄存器配置是否准确反映了幕的最大分辨率和支持的颜色深度。这些信息一般可以在幕的技术文档中找到。 调试过程中遇到的具体障碍往往还需要结合日志输出(如dmesg)、示波器测量信号完整性等因素综合判断。建议充分利用现有的开源资源和技术论坛寻求帮助,特别是针对特定硬件平台的问题,参与相关社区讨论能够快速定位解决方案[^2]。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值