1)实验平台:正点原子ATK-DLRK3568开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=731866264428
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban
第二十六章 LVDS屏幕驱动实验
LVDS也是现在最流行的屏幕显示接口之一,和MIPI、RGB接口一样,主要用来驱动屏幕面板。LVDS是低电压差分信号,具有低功耗、低误码率、低串扰、低抖动等优点,广泛应用于大尺寸显示器中,比如笔记本屏幕等。瑞芯微的RK3568芯片原生自带了LVDS显示接口,可以用来连接LVDS屏幕,本章我们就来学习一下如何使用RK3568的LVDS接口。
26.1 LVDS简介
26.1.1 LVDS协议简介
LVDS全称为Low-Voltage Differential Signaling,低电压差分信号,这是一种低功耗、低误码率、低串扰和低辐射的差分信号,采用极底的电压摆幅高速差动传输数据,实现点对点或一点对多点的连接。LVDS的信号幅度非常低,-350mV~350mV,通过一对差分线来传输数据。由于电压幅度低,所以LVDS采用恒流模式驱动,因此噪音极底,功耗也很小,无论传输速率高低,其功耗几乎不变。我们一般说的LVDS协议,说的是TIA/EIA-644这个协议。LVDS协议在不断地发展,其传输速度也在不断地增加,目前最新的协议最高可以到3.125Gbps。
LVDS的基本工作原理如图26.1.1.1所示:
图26.1.1.1 LVDS工作原理图
图中左边是驱动源,右边是接收器,驱动源采用3.3mA恒流驱动一对差分线,接收端本身为高直流输入阻抗,所以几乎所有的驱动电流都经过了100Ω的终端匹配电阻,因此在接收端产生约350mV的电压。
关于LVDS接口简介就讲解到这里。
26.1.2 LVDS屏幕
LVDS屏幕就是采用LVDS接口来传输图像数据的屏幕,LVDS屏幕接口一般分为单路6位LVDS、双路6位LVDS、单路8位LVDS和双路8位LVDS,这几种接口的区别如表26.1.2.1所示:
表26.1.2.1 LVDS屏幕接口区别
从表26.1.2.1可以看出,主要有2个概念:6位和8位,单路和双路。
1、6位和8位
首先来看一下6位8位的区别,6位说的是每个基色采用6位,一共是63=18位RGB数据。6位接口采用4对差分线来传输数据,3对数据差分线(XOUT0+、XOUT0-、XOUT1+、XOUT1-、XOUT2+、XOUT2-)和一对时钟线(CLK+、CLK-)。
8位每个基色采用8bit,一共是83=24位RGB数据,8位接口接口采用5对差分线来传输数据,4对数据差分线(XOUT0+、XOUT0-、XOUT1+、XOUT1-、XOUT2+、XOUT2-、XOUT3+、XOUT3-)和一对时钟线(CLK+、CLK-)。
2、单路和双路
单路和双路就是只采用几路LVDS接口,采用双路的目的就是降低时钟频率,随着屏幕分辨率和帧率的增加,像素时钟也急剧增加。当像素时钟超过最高限制的时候就不能用一个通道传输了,而是将输出的像素按顺序分为奇像素和偶像素,将所有的奇像素用一个通道来传输,所有的偶像素用另一个通道传输。如果有必要,可以继续拆分成更多的通道。
正点原子ATK-DLRK3568开发板的LVDS屏幕接口为单路8位,可以驱动正点原子在售的10.1寸1280*800分辨率的LVDS屏幕。正点原子10.1寸LVDS屏幕如图26.1.2.1所示:
图26.1.2.1 正点原子10.1寸LVDS屏幕
正点原子的10.1寸有RGB和LVDS两种接口,大家在购买的时候要选择LVDS接口屏幕。
26.2 RK3568 LVDS简介
RK3568原生支持一个LVDS接口,可以自己连接LVDS屏幕。RK3568的LVDS接口特性如下:
①、基础特性:
·兼容TIA/EIA-644-A LVDS特性。
·支持RGB888和RGB666格式。
·支持VESA/JEIDA数据格式。
②、每条lane最高支持1.2Gbps速率
③、最高支持1280800@60Hz。
RK3568的LVDS接口与MIPI DSI0接口复用,所以只能二选一,正点原子ATK-DLRK3568开发板默认使用LVDS功能。
25.3小节讲解RK3568的VOP外设的时候,已经说了LVDS使用vp2端口,这样LVDS接口最高支持1280800@60Hz。
26.3 硬件原理图分析
ATK-DLRK3568的LVDS原理图如图26.3.1所示:
图26.3.1 LVDS接口原理图
从图26.3.1可以看出,RK3568的LVDS接口是单路8位的,4对差分数据线,1对差分时钟线。LCD0_BL_PWM4是背光调节,连接到RK3568的GPIO0_C3引脚上。正点原子的10.1寸LVDS屏幕支持电容触摸,所以还有触摸屏相关引脚。LVDS_TP_RST_L是触摸复位引脚,连接到RK3568的GPIO3_C4引脚上。LVDS_TP_INT_L是触摸屏的中断引脚,连接到RK3568的GPIO0_C5引脚上。最后就是触摸屏的IIC接口,连接到RK3568的I2C3上,I2C3_SDA和I2C3_SCL分别对应RK3568的GPIO1_A0和GPIO1_A1引脚上。
26.4 实验程序编写
26.4.1 修改设备树
首先打开RK3568的LVDS屏幕绑定文档: kernel/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt,们简单总结一下LVDS节点信息。
①、必须的参数:
compatible:可以选择:rockchip,px30-lvds、rockchip,rk3126-lvds等。对于RK3568而言,有效的是rockchip,rk3568-lvds。
phy:PHY句柄。
phy-names:PHY名字。
②、可选的参数:
dual-channel:boolean类型,是否使能双通道模式。
rockchip,data-swap:boolean类型,使能或关闭双通道模式下的奇/偶交换。
③、要求的子节点:
LVDS节点有两个与video相关的子节点:
port0:此子节点用来描述LVDS所对应的VOP端口,比如RK3568的vp1和vp2都可以连接LVDS。
port1:此子节点用来描述LVDS屏幕相关信息,比如屏幕分辨率、时序参数等。
打开rk3568.dtsi文件,找到如下内容:
示例代码26.4.1.1 lvds节点
1 lvds: lvds {
2 compatible = "rockchip,rk3568-lvds";
3 phys = <&video_phy0>;
4 phy-names = "phy";
5 status = "disabled";
6
7 ports {
8 #address-cells = <1>;
9 #size-cells = <0>;
10
11 port@0 {
12 reg = <0>;
13 #address-cells = <1>;
14 #size-cells = <0>;
15
16 lvds_in_vp1: endpoint@1 {
17 reg = <1>;
18 remote-endpoint = <&vp1_out_lvds>;
19 status = "disabled";
20 };
21
22 lvds_in_vp2: endpoint@2 {
23 reg = <2>;
24 remote-endpoint = <&vp2_out_lvds>;
25 status = "disabled";
26 };
27 };
28 };
29 };
第2行,compatible属性值为“rockchip,rk3568-lvds”,大家搜索这个值就可以找到RK3568的LVDS 驱动文件:drivers/gpu/drm/rockchip/rockchip_lvds.c。
第7~27行,ports子节点,用来描述vp1和vp2输出到LVDS。lvds_in_vp1描述VP1连接到LVDS,lvds_in_vp2描述VP2连接到LVDS。具体要用哪个输出到LVDS根据自己的实际情况而定,正点原子ATK-DLRK3568开发板选择VP2连接到LVDS。
打开rk3568-atk-evb1-ddr4-v10.dtsi文件,在里面使能lvds_in_vp2,代码如下:
示例代码26.4.1.2 使能lvds_in_vp2
1 &lvds_in_vp1 {
2 status = "disabled";
3 };
4
5 &lvds_in_vp2 {
6 status = "okay";
7 };
上述代码将lvds_in_vp1的status改为disable,将lvds_in_vp2的status改为okay,也就是VP2输出到LVDS。
接下来继续在rk3568-atk-evb1-ddr4-v10.dtsi文件中向示例代码26.4.1.1中的lvds节点追加一些内容,如下:
示例代码26.4.1.3 向lvds节点追加内容
1 &lvds {
2 status = "okay";
3
4 ports {
5 #address-cells = <1>;
6 #size-cells = <0>;
7
8 port@1 {
9 reg = <1>;
10 lvds_out_panel: endpoint {
11 remote-endpoint = <&panel_in_lvds>;
12 };
13 };
14 };
15 };
第2行,将lvds节点的status改为okay,也就是使能LVDS。
第8~13行,port1设置LVDS屏幕信息,这里panel信息指向panel_in_lvds。
继续在rk3568-atk-evb1-ddr4-v10.dtsi文件中找到panel_in_lvds,内容如下:
示例代码26.4.1.4 lvds panel信息
1 lvds_panel: lvds-panel {
2 compatible = "simple-panel";
3 backlight = <&backlight>;
4 power-supply = <&vcc5v0_sys>;
5 enable-delay-ms = <20>;
6 prepare-delay-ms = <20>;
7 unprepare-delay-ms = <20>;
8 disable-delay-ms = <20>;
9 bus-format = <MEDIA_BUS_FMT_RGB888_1X7X4_SPWG>;
10 width-mm = <230>;
11 height-mm = <150>;
12
13 display-timings {
14 native-mode = <&lvds_timing0>;
15
16 lvds_timing0: timing0 {
17 clock-frequency = <71100000>;
18 hactive = <1280>;
19 vactive = <800>;
20 hback-porch = <80>;
21 hfront-porch = <70>;
22 vback-porch = <10>;
23 vfront-porch = <10>;
24 hsync-len = <10>;
25 vsync-len = <3>;
26 hsync-active = <0>;
27 vsync-active = <0>;
28 de-active = <0>;
29 pixelclk-active = <0>;
30 };
31 };
32
33 ports {
34 #address-cells = <1>;
35 #size-cells = <0>;
36
37 port@0 {
38 reg = <0>;
39 panel_in_lvds: endpoint {
40 remote-endpoint = <&lvds_out_panel>;
41 };
42 };
43 };
44 };
lvds_panel节点描述LVDS屏幕信息,第2~31行就是正点原子的10.1寸LVDS屏幕信息,这些属性含义已经在MIPI章节讲过了,这里就不再赘述了。
第33~42行,这是panel的ports节点,第40行设置panel的远端节点为lvds_out_panel,这样RK3568的LVDS外设就和panel联系起来了。最终的port连接顺序就是:vp2→lvds_out_panel→panel_in_lvds。
26.4.2 驱动使能与编译
正点原子ATK-DLRK3568开发板配套的SDK默认没有使能LVDS屏幕,所以需要先使能LVDS屏幕,打开rk3568-lcds.dtsi文件,找到如下所示内容:
示例代码26.4.2.1 使能LVDS屏幕
1 #if defined(ATK_LCD_TYPE_LVDS)
2 &lvds {
3 status = "okay";
4 };
5
6 &lvds_in_vp2 {
7 status = "okay";
8 };
9
10 &route_lvds {
11 connect = <&vp2_out_lvds>;
12 status = "okay";
13 };
从第1行可以看出,必须定义ATK_LCD_TYPE_LVDS这个宏才能使能lvds、lvds_in_vp2和route_lvds这三个节点。
打开rk3568-screen_choose.dtsi文件,此文件定义了正点原子ATK-DLRK3568开发板所支持的所有屏幕,如下所示:
示例代码26.4.2.2 使能LVDS
1 /*
2 * 屏幕选择
3 * ATK_LCD_TYPE_MIPI_720P: 正点原子5.5寸 720*1280 MIPI屏
4 * ATK_LCD_TYPE_MIPI_1080P: 正点原子5.5寸 1080*1920 MIPI屏
5 * ATK_LCD_TYPE_MIPI_10P1_800X1280: 正点原子10.1寸 800*1280 MIPI屏
6 * ATK_LCD_TYPE_LVDS: 正点原子10.1寸 1280*800 LVDS屏
7 * ATK_LCD_TYPE_HDMI: HDMI显示器
8 * ATK_LCD_TYPE_EDP_VGA: eDP屏或者VGA显示器(硬件默认使能的是VGA接
口,若用户需要使用eDP屏,则需修改硬件具体情
9 * 况可以看正点原子RK3568底板原理图!)
10 */
11 /*
12 * RK3568可支持三屏显示,也就是三路显示 VP0 VP1 VP2
13 * 但是三屏显示需要注意一些问题,具体情况可以看正点原子提供的文档<RK3568三屏显示
参考手册>!
14 */
15
16 /*
17 * ATK_LCD_TYPE_MIPI_720P/ATK_LCD_TYPE_MIPI_1080P/
ATK_LCD_TYPE_MIPI_10P1_800X1280 三选一
18 */
19 //#define ATK_LCD_TYPE_MIPI_720P // 从VP1输入
20 //#define ATK_LCD_TYPE_MIPI_1080P // 从VP1输入
21 //#define ATK_LCD_TYPE_MIPI_10P1_800X1280 // 从VP1输入
22
23 /*
24 * ATK_LCD_TYPE_HDMI 和 ATK_LCD_TYPE_EDP_VGA 二选一
25 */
26 #define ATK_LCD_TYPE_HDMI // 从VP0输入
27 //#define ATK_LCD_TYPE_EDP_VGA // 从VP0输入
28
29 #define ATK_LCD_TYPE_LVDS // 从VP2输入
第29行,定义ATK_LCD_TYPE_LVDS,使能LVDS屏幕。
正点原子ATK-DLRK3568开发板的SDK包默认适配MIPI屏幕,正点原子有多款MIPI屏幕,不同的MIPI屏幕通过ID来区分(电压值)。但是正点原子官方的LVDS屏幕没有ID线,所以没法自适配,无法加载LVDS屏幕对应的设备树,需要我们手动指定一个设备树。
打开kernel目录下的make.sh脚本文件,修改成如下所示内容:
示例代码26.4.2.3 使能LVDS
1 #!/bin/bash
2
3 # 默认值
4 RK_ARCH=arm64
5 RK_DEFCONFIG=rockchip_linux_defconfig
6 RK_DEFCONFIG_FRAGMENT=
7 RK_DTS=rk3568-atk-evb1-ddr4-v10-linux
8 RK_JOBS=24
9
10 while [ $# -gt 0 ]; do
11 case $1 in
12 arch=*)
13 arg=${1#*=}
14 if [ -n "$arg" ]; then
15 RK_ARCH=$arg
16 fi
17 shift 1
18 ;;
19 defconfig=*)
20 arg=${1#*=}
21 if [ -n "$arg" ]; then
22 RK_DEFCONFIG=$arg
23 fi
24 shift 1
25 ;;
26 defconfig_fragment=*) # xxx.config文件
27 RK_DEFCONFIG_FRAGMENT=${1#*=}
28 shift 1
29 ;;
30 dts=*)
31 arg=${1#*=}
32 if [ -n "$arg" ]; then
33 RK_DTS=$arg
34 fi
35 shift 1
36 ;;
37 jobs=*)
38 arg=${1#*=}
39 if [ -n "$arg" ]; then
40 RK_JOBS=$arg
41 fi
42 shift 1
43 ;;
44 *)
45 shift 1
46 ;;
47 esac
48 done
49
50 # 配置
51 make ARCH=$RK_ARCH $RK_DEFCONFIG $RK_DEFCONFIG_FRAGMENT
52 # 编译
53 make ARCH=$RK_ARCH $RK_DTS.img -j$RK_JOBS
54 exit 0
55 # 编译出720p和1080p MIPI屏设备树镜像
56 echo "#################################################"
57 make ARCH=$RK_ARCH rockchip/rk3568-atk-evb1-ddr4-v10-linux.dtb -j$RK_JOBS
58 make ARCH=$RK_ARCH rockchip/rk3568-atk-evb1-mipi-dsi-1080p.dtb -j$RK_JOBS
59 make ARCH=$RK_ARCH rockchip/rk3568-atk-evb1-mipi-dsi-720p.dtb -j$RK_JOBS
60 make ARCH=$RK_ARCH rockchip/rk3568-atk-evb1-mipi-dsi-10p1_800x1280.dtb -j$RK_JOBS
61
62 # 生成包含多个dtb的resource.img镜像
63 rm -rf resource.img
64 scripts/mkmultidtb.py RK3568-ATK-EVB1
第7行,将设备树改为rk3568-atk-evb1-ddr4-v10-linux,也就是开启了LVDS屏幕配置的设备树。
第54行,添加一个exit 0,特别注意,不要写错位置了!脚本执行到这里以后就会退出,后面的脚本就不会执行了。后面的脚本是打包rk3568-atk-evb1-mipi-dsi-1080p.dtb、rk3568-atk-evb1-mipi-dsi-720p.dtb和rk3568-atk-evb1-mipi-dsi-10p1_800x1280.dtb三个设备树到resource.img中。但是此时我们不需要这些设备树,我们只需要rk3568-atk-evb1-ddr4-v10-linux设备树。
重新编译内核,得到boot.img文件,将boot.img文件烧写到开发板中,连接正点原子的10.1英寸LVDS屏幕,此时就能点亮了。
26.5 LVDS测试
请注意,由于LVDS屏幕兼容RGB接口和LVDS接口,有些用户可能早已经采购过这个正点原子的10.1英寸屏请检查屏上的电阻,如下位置,要用LVDS接口需要将LVDS接口下的5个排阻全部拆除。请检查,
图26.5.1 LVDS屏需要拆下5个排阻
重新编译生成boot.img,烧写boot.img,在开发板底板LVDS丝印处通过排线接上LVDS屏幕,上电启动效果如下。
图26.5.2 LVDS屏上电效果
注意默认LVDS屏幕方向是横屏的,而qt程序是适配竖屏的,所以我们需要旋转weston桌面方向90/270度。编辑/etc/xdg/weston/weston.ini,在文本最后加入如下内容,这样下次开机即为竖屏。
1 [output]
2 name=LVDS-1
3 transform=rotate-90