目录
[开篇先搞懂:RK 平台的显示架构,到底是怎么回事?](#开篇先搞懂:RK 平台的显示架构,到底是怎么回事?)
[RK3568 显示核心:VOP+DSI Host](#RK3568 显示核心:VOP+DSI Host)
[一、核心框架:DRM 显示框架,大白话全解析](#一、核心框架:DRM 显示框架,大白话全解析)
[什么是 DRM 框架?](#什么是 DRM 框架?)
[DRM 框架的核心作用](#DRM 框架的核心作用)
[我们适配屏幕,需要和 DRM 框架打什么交道?](#我们适配屏幕,需要和 DRM 框架打什么交道?)
[二、MIPI DSI 屏核心知识点,小白必懂](#二、MIPI DSI 屏核心知识点,小白必懂)
[1. 什么是 MIPI DSI?](#1. 什么是 MIPI DSI?)
[2. MIPI DSI 核心参数,适配屏幕必须搞懂](#2. MIPI DSI 核心参数,适配屏幕必须搞懂)
[3. 屏幕时序参数详解,再也不用瞎抄了](#3. 屏幕时序参数详解,再也不用瞎抄了)
[三、保姆级实战:MIPI DSI 屏完整适配流程,基于 RK3568](#三、保姆级实战:MIPI DSI 屏完整适配流程,基于 RK3568)
[步骤 1:解析屏幕规格书,整理核心参数](#步骤 1:解析屏幕规格书,整理核心参数)
[步骤 2:修改设备树,添加屏幕配置](#步骤 2:修改设备树,添加屏幕配置)
[步骤 3:初始化命令的转换方法](#步骤 3:初始化命令的转换方法)
[步骤 4:背光驱动配置](#步骤 4:背光驱动配置)
[步骤 5:编译 SDK,烧录验证](#步骤 5:编译 SDK,烧录验证)
[四、LVDS 屏适配要点](#四、LVDS 屏适配要点)
[五、小白屏幕适配必踩的坑,100% 问题排查指南](#五、小白屏幕适配必踩的坑,100% 问题排查指南)
[问题 1:屏幕完全不亮,黑屏](#问题 1:屏幕完全不亮,黑屏)
[问题 2:屏幕能亮,但是花屏、画面错乱](#问题 2:屏幕能亮,但是花屏、画面错乱)
[问题 3:屏幕能亮,但是闪屏、画面抖动](#问题 3:屏幕能亮,但是闪屏、画面抖动)
[问题 4:屏幕能亮,但是没有背光,还是黑的](#问题 4:屏幕能亮,但是没有背光,还是黑的)
大家好,我是黒漂技术佬。上一篇我们搞定了 input 输入设备驱动,后台收到最多的哭诉就是:
"佬,我买了个 MIPI 屏,按照厂家给的参数改了设备树,结果屏就是不亮,要么就是花屏、闪屏,根本不知道从哪里排查,快崩溃了"
太懂这种痛苦了!当年我入门的时候,第一次适配 MIPI 屏,光点亮屏幕就折腾了整整一周,踩了无数坑,要么是屏参不对,要么是时序错了,要么是背光没开,根本不知道从哪里下手排查。
今天这篇,我就用大白话给你讲透 RK 平台的显示架构、DRM 显示框架,手把手带你完成MIPI DSI 屏的完整适配流程,从屏参解析、设备树配置、编译烧录,到花屏、不亮、闪屏的全场景问题排查,小白跟着走,也能一次点亮屏幕。
开篇先搞懂:RK 平台的显示架构,到底是怎么回事?
很多新手适配屏幕,上来就瞎改设备树,连 RK 的显示架构都没搞懂,不踩坑才怪。先给大家用大白话讲清楚,RK3568 的显示系统,到底是怎么把画面显示到屏幕上的。
RK3568 显示核心:VOP+DSI Host
RK3568 的显示系统,核心分为两大部分:
- VOP(Video Output Processor,视频输出处理器):相当于显示系统的 "大脑",负责把内存里的画面数据,转换成对应的时序信号,输出给后面的显示接口。RK3568 有 2 个 VOP,支持双屏同显 / 异显,最高支持 4K 分辨率;
- 显示接口 :相当于显示系统的 "嘴巴",把 VOP 输出的时序信号,转换成对应屏幕能识别的信号,传输给屏幕。RK3568 支持的显示接口有:
- MIPI DSI:最常用的接口,手机、平板、工业屏绝大多数都是 MIPI 接口,我们今天重点讲这个;
- LVDS:工业屏常用的接口,一般用于中低分辨率的屏幕;
- HDMI:外接显示器、电视用的接口,官方已经适配好了,不用我们自己改;
- eDP:笔记本屏幕常用的接口,RK3568 也支持。
完整的画面显示流程
- 安卓系统把要显示的画面,渲染到内存的帧缓冲区里;
- DRM 框架把帧缓冲区的画面数据,交给 VOP;
- VOP 按照我们配置的屏幕时序,把画面数据转换成并行的 RGB 信号;
- MIPI DSI Host 控制器,把 VOP 输出的 RGB 信号,转换成 MIPI DSI 协议的串行信号,通过 MIPI 排线传输给屏幕;
- 屏幕的驱动芯片收到信号后,点亮对应的像素点,画面就显示出来了。
我们适配屏幕,核心就是做两件事:
- 给 VOP 配置正确的屏幕时序参数,让 VOP 输出符合屏幕要求的信号;
- 给 MIPI DSI Host 配置正确的初始化命令、通道数、速率,让它能和屏幕正常通信。
一、核心框架:DRM 显示框架,大白话全解析
很多新手一听到 DRM 就头大,觉得是天书,其实完全不用怕,我用大白话给你讲明白,你只需要知道它是干嘛的,不用深入啃源码,就能完成屏幕适配。
什么是 DRM 框架?
DRM 的全称是 Direct Rendering Manager,直接渲染管理器,是现在 Linux 内核里标准的显示框架,RK3568 的安卓 11/12 系统,全都是用的 DRM 框架,之前老旧的 FBDEV(帧缓冲)框架,已经被淘汰了。
DRM 框架的核心作用
简单说,DRM 框架就是安卓系统和显示硬件之间的桥梁,它统一管理显示硬件(VOP、DSI 控制器、HDMI 控制器),给上层安卓系统提供标准的显示接口,负责画面的渲染、缓冲、输出,让安卓系统不用关心底层的硬件细节。
我们适配屏幕,需要和 DRM 框架打什么交道?
99% 的场景下,我们不需要修改 DRM 框架的代码,RK 官方已经把 DRM 框架、VOP 驱动、MIPI DSI Host 驱动都写好了,我们只需要在设备树里,把屏幕的时序参数、初始化命令、接口配置填进去,内核的 DRM 驱动会自动读取这些配置,完成屏幕的初始化和显示。
对,你没看错!适配屏幕,90% 的工作就是修改设备树,把屏幕厂家给的参数,填到对应的设备树节点里就行,不用写一行驱动代码!这就是 RK 平台的优势,官方已经把底层驱动全做好了。
二、MIPI DSI 屏核心知识点,小白必懂
1. 什么是 MIPI DSI?
MIPI DSI 的全称是 Mobile Industry Processor Interface Display Serial Interface,也就是移动行业处理器接口的显示串行接口,是现在手机、平板、工业屏最主流的显示接口,它的核心优势是引脚少、传输速率高、抗干扰能力强。
2. MIPI DSI 核心参数,适配屏幕必须搞懂
你买屏幕的时候,厂家一定会给你一份屏幕规格书(datasheet),里面的这些核心参数,是我们适配的关键,必须看懂:
- 分辨率 :屏幕的像素点数,比如 8001280、10801920,这个是最基础的;
- MIPI 通道数(Lane 数) :MIPI DSI 用差分对来传输数据,一个差分对就是一个 Lane(通道),常用的有 1 Lane、2 Lane、4 Lane,分辨率越高,需要的通道数越多,比如 8001280 一般用 2 Lane,10801920 一般用 4 Lane;
- D-PHY 速率:每个 Lane 的传输速率,单位是 Mbps,一般在 500Mbps~1500Mbps 之间,屏幕规格书里会给最大值,我们配置的速率不能超过这个最大值;
- 屏幕时序参数:也就是我们常说的 HFP、HBP、HSA、VFP、VBP、VSA,这些是 VOP 输出时序的核心参数,必须和屏幕规格书里的完全一致,不然就会花屏、闪屏、不显示,后面我会详细讲每个参数的含义;
- 初始化命令:MIPI 屏在上电后,需要通过 MIPI 总线,给屏幕驱动芯片发送一串初始化命令,才能正常工作,厂家一般会给现成的初始化代码,我们只需要转换成设备树里的格式就行;
- 像素格式:一般都是 RGB888,24 位色,或者 RGB565,16 位色,绝大多数屏幕都是 RGB888。
3. 屏幕时序参数详解,再也不用瞎抄了
很多新手适配屏幕,就是从网上随便抄一套时序参数,结果屏不亮,就是因为没搞懂这些参数的含义。时序参数分为水平(Horizontal)和垂直(Vertical)两部分,对应屏幕的行和列,我用 800*1280 分辨率的屏举例,给你讲透每个参数:
水平时序参数(对应一行像素)
- HACTIVE(Hdisp):水平有效像素,也就是屏幕的水平分辨率,800*1280 的屏,这个值就是 800;
- HSA(Horizontal Sync Width):水平同步宽度,行同步信号的持续时间,单位是像素时钟;
- HBP(Horizontal Back Porch):水平后沿,行同步信号结束后,到有效像素开始前的时钟数;
- HFP(Horizontal Front Porch):水平前沿,有效像素结束后,到下一个行同步信号开始前的时钟数;
- HTOTAL:水平总长度 = HACTIVE + HSA + HBP + HFP,也就是一行完整的时钟数。
垂直时序参数(对应一帧画面)
- VACTIVE(Vdisp):垂直有效像素,也就是屏幕的垂直分辨率,800*1280 的屏,这个值就是 1280;
- VSA(Vertical Sync Width):垂直同步宽度,帧同步信号的持续时间,单位是行;
- VBP(Vertical Back Porch):垂直后沿,帧同步信号结束后,到有效帧开始前的行数;
- VFP(Vertical Front Porch):垂直前沿,有效帧结束后,到下一个帧同步信号开始前的行数;
- VTOTAL:垂直总长度 = VACTIVE + VSA + VBP + VFP,也就是一帧完整的行数。
像素时钟(DCLK)计算
像素时钟是 VOP 输出的时钟频率,单位是 MHz,计算公式是:
plaintext
DCLK = HTOTAL * VTOTAL * 帧率 / 1000000
比如 8001280 的屏,帧率 60fps,HTOTAL=1000,VTOTAL=1300,那么 DCLK=10001300*60/1000000=78MHz。
这些参数,屏幕厂家的规格书里都会给,我们只需要照着填到设备树里就行,不用自己算,千万别自己瞎编!
三、保姆级实战:MIPI DSI 屏完整适配流程,基于 RK3568
我们以 800*1280 分辨率、2 Lane MIPI、ST7701 驱动芯片的屏为例,手把手带你完成完整的适配流程,所有步骤一步不落,小白跟着走就能点亮屏幕。
前置准备
- RK3568 开发板,配套的安卓 SDK;
- MIPI DSI 屏,厂家给的规格书、初始化代码;
- 已经搭建好的编译环境,能正常编译 SDK。
步骤 1:解析屏幕规格书,整理核心参数
首先,从屏幕厂家给的规格书里,整理出我们需要的核心参数,举个例子:
表格
| 参数名 | 值 |
|---|---|
| 分辨率 | 800*1280 |
| MIPI 通道数 | 2 Lane |
| 最大 D-PHY 速率 | 800Mbps |
| 帧率 | 60fps |
| 像素格式 | RGB888 |
| HACTIVE | 800 |
| HFP | 20 |
| HBP | 20 |
| HSA | 10 |
| VACTIVE | 1280 |
| VFP | 10 |
| VBP | 10 |
| VSA | 2 |
| 初始化命令 | 厂家给的 ST7701 初始化代码 |
步骤 2:修改设备树,添加屏幕配置
RK3568 的屏幕配置,都在rk3568.dtsi和板级.dts 文件里,我们只需要在板级.dts 文件里,添加对应的 dsi 屏节点,修改对应的参数就行。
打开你的板级.dts 文件,添加下面的配置,每一行都加了注释,你只需要把参数换成你自己屏幕的就行:
dts
// 1. 配置MIPI DSI Host控制器
&dsi0 {
status = "okay";
// MIPI通道数,2 Lane
rockchip,lane-count = <2>;
// D-PHY最大速率,单位是Mbps,不能超过屏幕的最大值
rockchip,max-bandwidth = <800>;
// 屏幕格式,RGB888
rockchip,format = <MIPI_DSI_FMT_RGB888>;
// 视频模式,还是命令模式,绝大多数屏都是视频模式
rockchip,mode = <MIPI_DSI_MODE_VIDEO>;
// 视频模式配置:突发模式
rockchip,video-mode = <MIPI_DSI_VIDEO_MODE_BURST>;
// 同步信号极性,根据屏幕规格书修改
rockchip,sync-pol = <0>;
// 屏幕时序节点
panel@0 {
compatible = "simple-mipi-dsi-panel";
reg = <0>;
status = "okay";
// 屏幕时序参数,核心中的核心,必须和规格书一致
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <78000000>; // 像素时钟,单位Hz,78MHz
hactive = <800>; // 水平有效像素
hfront-porch = <20>; // HFP
hback-porch = <20>; // HBP
hsync-len = <10>; // HSA
vactive = <1280>; // 垂直有效像素
vfront-porch = <10>; // VFP
vback-porch = <10>; // VBP
vsync-len = <2>; // VSA
hsync-active = <0>; // 行同步极性,0=低电平有效
vsync-active = <0>; // 帧同步极性,0=低电平有效
de-active = <1>; // 数据使能极性,1=高电平有效
pixelclk-active = <0>; // 像素时钟极性,0=上升沿采样
};
};
// 屏幕上电时序配置,根据屏幕规格书修改
power-supply = <&vcc3v3_lcd0>; // 屏幕供电引脚,根据你的开发板修改
reset-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_LOW>; // 屏幕复位引脚
// 上电时序:上电后,延时10ms,拉低复位,延时10ms,拉高复位,延时120ms
reset-delay-ms = <10>;
prepare-delay-ms = <10>;
init-delay-ms = <120>;
// MIPI屏初始化命令,厂家给的初始化代码,转换成这个格式
dsi,init-commands = [
15 00 02 80 10 // 延时120ms
39 00 02 FF 77 01 00 00 10 // 发送命令FF 77 01 00 00 10
39 00 02 C0 63 00 10 // 发送命令C0 63 00 10
// 把厂家给的所有初始化命令,都转换成这个格式,后面讲转换方法
15 00 02 20 00 // 延时20ms
05 00 01 29 00 // 发送命令29,开启显示
];
};
};
// 2. 配置VOP,绑定DSI控制器
&route_dsi0 {
status = "okay";
// 绑定VOP,RK3568有vopb和vopl,这里用vopb
connect = <&vopb_out_dsi0>;
};
&vopb {
status = "okay";
};
&vopb_out_dsi0 {
status = "okay";
};
// 3. 配置背光,后面讲
&backlight {
status = "okay";
pwms = <&pwm0 0 50000 0>;
brightness-levels = <0 20 40 60 80 100 120 140 160 180 200 220 240 255>;
default-brightness = <200>;
};
步骤 3:初始化命令的转换方法
厂家给的初始化代码,一般是这样的格式:
c
运行
Delay(120);
Write_Cmd(0xFF);
Write_Data(0x77);
Write_Data(0x01);
Write_Data(0x00);
Write_Data(0x00);
Write_Data(0x10);
Delay(20);
Write_Cmd(0x29);
我们需要把它转换成设备树里的dsi,init-commands格式,转换规则很简单:
- 延时命令 :格式是
15 00 02 延时高8位 延时低8位,单位是 ms。比如延时 120ms,就是15 00 02 00 78(120 的十六进制是 0x78); - 写命令 + 数据 :格式是
39 00 数据长度 命令 数据1 数据2 ... 10。比如写命令 0xFF,后面跟 5 个数据,数据长度是 0x02+5=0x07,所以就是39 00 07 FF 77 01 00 00 10; - 只写命令,无数据 :格式是
05 00 01 命令 00。比如写命令 0x29,就是05 00 01 29 00。
步骤 4:背光驱动配置
屏幕点亮了,还要开背光,不然还是黑的。RK 平台的背光,一般用 PWM 驱动,我们只需要在设备树里配置好对应的 PWM 引脚、频率、亮度等级就行,上面的设备树里已经加了 backlight 节点,只需要把 PWM 引脚改成你开发板对应的就行。
步骤 5:编译 SDK,烧录验证
-
设备树修改完成后,进入 SDK 根目录,执行完整编译,或者只编译内核和设备树: bash
运行
./build.sh -CKu -
编译完成后,把生成的 boot.img 和 update.img 烧录到开发板;
-
开发板上电,正常情况下,屏幕会在 U-Boot 阶段就点亮,进入安卓系统后,正常显示桌面。
四、LVDS 屏适配要点
工业屏常用的 LVDS 接口,适配流程和 MIPI 屏几乎完全一样,核心区别只有两点:
- 设备树里配置的是 LVDS 控制器,而不是 DSI 控制器,RK3568 有 2 路 LVDS 接口;
- 不需要配置 MIPI 初始化命令,只需要配置好时序参数、LVDS 格式(单路 / 双路、JEIDA/VESA 格式)就行。
厂家给的 LVDS 屏规格书里,会明确说明是 JEIDA 格式还是 VESA 格式,单路还是双路,我们只需要在设备树里对应的节点里配置好就行,其他的时序参数、背光配置,和 MIPI 屏完全一样。
五、小白屏幕适配必踩的坑,100% 问题排查指南
99% 的新手适配屏幕,都会遇到屏不亮、花屏、闪屏的问题,我把所有常见问题的排查步骤,按优先级给你整理好了,按这个顺序查,99% 的问题都能解决。
问题 1:屏幕完全不亮,黑屏
按这个顺序排查:
- 先查硬件 :
- 测量屏幕的供电引脚,有没有 3.3V/5V 供电,没供电先查供电电路;
- 测量复位引脚,上电后有没有正常的复位电平变化,没复位先查复位引脚的设备树配置;
- 测量 MIPI 排线的差分信号,有没有数据输出,没数据说明 DSI 控制器没正常工作。
- 再查设备树配置 :
- 检查 dsi0、route_dsi0、vopb 的 status 是不是 okay,有没有被禁用;
- 检查 MIPI 通道数是不是和屏幕一致,2 Lane 的屏不能配成 4 Lane;
- 检查初始化命令是不是正确,有没有漏掉延时命令,厂家给的初始化代码里的延时,必须严格对应;
- 检查像素时钟是不是在合理范围内,不能太高也不能太低。
- 查内核日志 :开发板连串口,开机的时候看内核日志,搜索
dsi、vop、panel相关的日志,看有没有报错,比如时序参数不对、初始化失败、DSI 通信失败,日志里会明确告诉你哪里出了问题。
问题 2:屏幕能亮,但是花屏、画面错乱
99% 的原因是时序参数不对:
- 检查 HACTIVE、VACTIVE 是不是和屏幕分辨率完全一致;
- 检查 HFP、HBP、HSA、VFP、VBP、VSA 是不是和规格书里的完全一致,差一个数都会花屏;
- 检查同步信号极性(hsync-active、vsync-active)是不是和规格书一致;
- 检查 MIPI D-PHY 速率是不是超过了屏幕的最大值,降一点速率试试。
问题 3:屏幕能亮,但是闪屏、画面抖动
核心原因:
- 像素时钟不对,计算错误,导致帧率不对,重新计算像素时钟;
- 时序参数里的前后沿太小,不符合屏幕要求,适当加大 HFP、HBP、VFP、VBP 的值;
- MIPI 排线太长,或者干扰太大,降低 D-PHY 速率试试;
- 电源纹波太大,屏幕供电不稳定,加滤波电容。
问题 4:屏幕能亮,但是没有背光,还是黑的
- 检查背光驱动的设备树配置,PWM 引脚是不是正确,有没有正常输出;
- 测量背光引脚的电压,有没有正常输出,背光使能引脚有没有拉高;
- 进入安卓系统后,在设置里调节亮度,看背光有没有变化;
- 串口看 backlight 相关的日志,有没有报错。
结尾说两句
这篇文章,我们彻底搞懂了 RK 平台的显示架构、DRM 框架,完成了 MIPI/LVDS 屏的完整适配流程,还给了你一套万能的屏幕问题排查指南,以后再遇到屏点不亮、花屏的问题,再也不用瞎改了。
下一篇,我们进入音频驱动的内容,详解 ALSA 音频架构,手把手带你完成 RK 平台的音频驱动适配与调试,解决没声音、杂音、录音无声的问题。
我是黒漂技术佬,关注我,带你零基础入门 RK 安卓驱动开发,不踩坑。有任何屏幕适配的问题,评论区留言,我都会一一回复。