平台:RK3288
板型:Firefly-RK3288
Host:Ubuntu 16.04
LCD:BP101WX1-206
Firefly Linux SDK:具体参考Firefly-RK3288维基教程
由于Firefly-RK3288这块板默认没有开启LVDS输出,所以编写了这份文档,记录LVDS屏幕如何驱动。
vop
是一个把frame buffer
数据传输到指定显示设备(RGB LCD Panel,LVDS
,MIPI,eDP
,HDMI
等)的接口,它还包含了显示处理和图层处理等功能,传统意义上就是一个显示控制器(Display Controller)。rk3288内部有两个vop单元,分别是vopb
和vopl
。具体可参考《rk3288-chapter-27-visual-output-processor-(vop)
》
LVDS
接口把vop
输出的CMOS
信号为低压差分
信号,以此减少噪声对视频信号的干扰,同时减少了线路数量,RGB
接口的线路比LVDS
要多很多。具体参考《rk3288-chapter-33-lvds
》。
主要用来把RGB信号转为视觉画面展示出来。
有几个重要参数必须要了解的,这些参数都可以在显示屏的datasheet里面找到。
名称 | 解释 | 缩写 | 单位 |
---|---|---|---|
Clock Frequency | 像素时钟 | cf |
hz |
Horizontal Back Porch | 水平后肩,水平同步信号之后的时延 | hbp |
clk |
Horizontal Front Porch | 水平前肩,水平同步信号之前的时延 | hfp |
clk |
Horizontal Pulse Width | 水平同步信号的长度 | hsync |
clk |
Vertical Back Porch | 垂直后肩,垂直同步信号之后的时延 | vbp |
line |
Vertical Front Porch | 垂直前肩,垂直同步信号之前的时延 | vfp |
line |
Vertical Pulse Width | 垂直同步信号长度 | vsync |
line |
这里clk
= 1 / cf,line
=(hbp + hfp + hsync)* clk,假如显示屏的像素时钟规定为65000000hz,则clk = 1 / 65000000s(具体我就不算了)。
1、屏幕datasheet第32页显示的关键参数
从屏幕datasheet可知道
Main clock = clock-frequency = 65000000hz
Hor Blanking = hbp + hfb + hsync = 50
H Sync Pulse Width = hsync = 32
H Sync Offset = hbp = 10
所以 hfp = 50 - 32 - 10 = 8
Ver Blanking = vbp + vfp + vsync = 12
V Sync Pulse Width = vsync = 6
V Sync Offset = vbp = 3
所以vfp = 12 - 6 - 3 = 3
2、屏幕datasheet第20页显示的时序图
可知道在DCLK(这里就是我指的cf)下降沿采集数据,DE为高电平时数据有效。而hsync和vsync都是低电平触发。
3、进入arch/arm/boot/dts
,修改rk3288-firefly.dts
cd arch/arm/boot/dts/
vi rk3288-firefly.dts
4、增加使用LVDS
相关节点
#include // 需要增加这个头文件
......
&route_hdmi {
status = "okay";
};
&route_lvds { // 使能lvds路由,使显示子系统的数据能够经过vopl传输到lvds
status = "okay";
};
......
&lvds_in_vopb { // 我们屏幕是1280x800使用vopl输入即可,所以关闭vopb的输入
status = "disabled";
};
&lvds { // 使能lvds接口
status = "okay";
};
&lvds_panel {
status = "okay";
compatible ="simple-panel"; // 使用4.x内核的simple panel框架
// power-supply = <&vcc_lcd>; // 因为屏幕不使用gpio供电,所以注释掉
// backlight = <&backlight>; // 因为屏幕不使用背光调节,所以注释掉
bus-format = <MEDIA_BUS_FMT_RBG888_1X24>; // RGB888
enable-delay-ms = <10>;
rockchip,data-mapping = "vesa"; // lvds数据格式
rockchip,data-width = <24>; // 24位
rockchip,output = "lvds"; // lvds接口输出
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <65000000>; // 参考第1点
hactive = <1280>; // 这里填分辨率即可
vactive = <800>;
hback-porch = <10>; // 参考第1点
hfront-porch = <8>; // 参考第1点
vback-porch = <3>; // 参考第1点
vfront-porch = <3>; // 参考第1点
hsync-len = <32>; // 参考第1点
vsync-len = <6>; // 参考第1点
hsync-active = <0>; // 参考第2点
vsync-active = <0>; // 参考第2点
de-active = <1>; // 参考第2点
pixelclk-active = <0>; // 参考第2点
};
};
};
5、相关dts节点查看
文件rk3288-linux.dtsi
display-subsystem {
status = "okay";
ports = <&vopb_out>, <&vopl_out>;
logo-memory-region = <&drm_logo>;
route {
route_hdmi: route-hdmi {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vopb_out_hdmi>;
};
route_edp: route-edp {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vopl_out_edp>;
};
route_dsi0: route-dsi0 {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vopl_out_dsi0>;
};
route_lvds: route-lvds {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vopl_out_lvds>; // 这里连接到vopl输出lvds的链路
};
};
文件rk3288.dtsi
vopl: vop@ff940000 {
compatible = "rockchip,rk3288-vop-lit";
rockchip,grf = <&grf>;
reg = <0x0 0xff940000 0x0 0x19c>, <0x0 0xff941000 0x0 0x1000>;
reg-names = "regs", "gamma_lut";
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
power-domains = <&power RK3288_PD_VIO>;
resets = <&cru SRST_LCDC1_AXI>, <&cru SRST_LCDC1_AHB>, <&cru SRST_LCDC1_DCLK>;
reset-names = "axi", "ahb", "dclk";
iommus = <&vopl_mmu>;
status = "disabled";
vopl_out: port {
#address-cells = <1>;
#size-cells = <0>;
vopl_out_hdmi: endpoint@0 {
reg = <0>;
remote-endpoint = <&hdmi_in_vopl>;
};
vopl_out_edp: endpoint@1 {
reg = <1>;
remote-endpoint = <&edp_in_vopl>;
};
vopl_out_dsi0: endpoint@2 {
reg = <2>;
remote-endpoint = <&dsi0_in_vopl>;
};
vopl_out_lvds: endpoint@3 { // 端点3
reg = <3>;
remote-endpoint = <&lvds_in_vopl>; // 连接到lvds的输入端
};
vopl_out_dsi1: endpoint@4 {
reg = <4>;
remote-endpoint = <&dsi1_in_vopl>;
};
};
};
lvds: lvds@ff96c000 {
compatible = "rockchip,rk3288-lvds";
reg = <0x0 0xff96c000 0x0 0x4000>;
clocks = <&cru PCLK_LVDS_PHY>;
clock-names = "pclk_lvds";
power-domains = <&power RK3288_PD_VIO>;
rockchip,grf = <&grf>;
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
lvds_in: port@0 { // 两个端点
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
lvds_in_vopb: endpoint@0 { // 连接到vopb的输出端
reg = <0>;
remote-endpoint = <&vopb_out_lvds>;
};
lvds_in_vopl: endpoint@1 { // 连接到vopl的输出端
reg = <1>;
remote-endpoint = <&vopl_out_lvds>;
};
};
};