第 14 篇 显示驱动(MIPI/LVDS 屏)适配与调试,DRM 框架详解

目录

[开篇先搞懂: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. 屏幕时序参数详解,再也不用瞎抄了)

水平时序参数(对应一行像素)

垂直时序参数(对应一帧画面)

像素时钟(DCLK)计算

[三、保姆级实战: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 的显示系统,核心分为两大部分:

  1. VOP(Video Output Processor,视频输出处理器):相当于显示系统的 "大脑",负责把内存里的画面数据,转换成对应的时序信号,输出给后面的显示接口。RK3568 有 2 个 VOP,支持双屏同显 / 异显,最高支持 4K 分辨率;
  2. 显示接口 :相当于显示系统的 "嘴巴",把 VOP 输出的时序信号,转换成对应屏幕能识别的信号,传输给屏幕。RK3568 支持的显示接口有:
    • MIPI DSI:最常用的接口,手机、平板、工业屏绝大多数都是 MIPI 接口,我们今天重点讲这个;
    • LVDS:工业屏常用的接口,一般用于中低分辨率的屏幕;
    • HDMI:外接显示器、电视用的接口,官方已经适配好了,不用我们自己改;
    • eDP:笔记本屏幕常用的接口,RK3568 也支持。

完整的画面显示流程

  1. 安卓系统把要显示的画面,渲染到内存的帧缓冲区里;
  2. DRM 框架把帧缓冲区的画面数据,交给 VOP;
  3. VOP 按照我们配置的屏幕时序,把画面数据转换成并行的 RGB 信号;
  4. MIPI DSI Host 控制器,把 VOP 输出的 RGB 信号,转换成 MIPI DSI 协议的串行信号,通过 MIPI 排线传输给屏幕;
  5. 屏幕的驱动芯片收到信号后,点亮对应的像素点,画面就显示出来了。

我们适配屏幕,核心就是做两件事:

  1. 给 VOP 配置正确的屏幕时序参数,让 VOP 输出符合屏幕要求的信号;
  2. 给 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),里面的这些核心参数,是我们适配的关键,必须看懂:

  1. 分辨率 :屏幕的像素点数,比如 8001280、10801920,这个是最基础的;
  2. MIPI 通道数(Lane 数) :MIPI DSI 用差分对来传输数据,一个差分对就是一个 Lane(通道),常用的有 1 Lane、2 Lane、4 Lane,分辨率越高,需要的通道数越多,比如 8001280 一般用 2 Lane,10801920 一般用 4 Lane;
  3. D-PHY 速率:每个 Lane 的传输速率,单位是 Mbps,一般在 500Mbps~1500Mbps 之间,屏幕规格书里会给最大值,我们配置的速率不能超过这个最大值;
  4. 屏幕时序参数:也就是我们常说的 HFP、HBP、HSA、VFP、VBP、VSA,这些是 VOP 输出时序的核心参数,必须和屏幕规格书里的完全一致,不然就会花屏、闪屏、不显示,后面我会详细讲每个参数的含义;
  5. 初始化命令:MIPI 屏在上电后,需要通过 MIPI 总线,给屏幕驱动芯片发送一串初始化命令,才能正常工作,厂家一般会给现成的初始化代码,我们只需要转换成设备树里的格式就行;
  6. 像素格式:一般都是 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 驱动芯片的屏为例,手把手带你完成完整的适配流程,所有步骤一步不落,小白跟着走就能点亮屏幕。

前置准备

  1. RK3568 开发板,配套的安卓 SDK;
  2. MIPI DSI 屏,厂家给的规格书、初始化代码;
  3. 已经搭建好的编译环境,能正常编译 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格式,转换规则很简单:

  1. 延时命令 :格式是15 00 02 延时高8位 延时低8位,单位是 ms。比如延时 120ms,就是15 00 02 00 78(120 的十六进制是 0x78);
  2. 写命令 + 数据 :格式是39 00 数据长度 命令 数据1 数据2 ... 10。比如写命令 0xFF,后面跟 5 个数据,数据长度是 0x02+5=0x07,所以就是39 00 07 FF 77 01 00 00 10
  3. 只写命令,无数据 :格式是05 00 01 命令 00。比如写命令 0x29,就是05 00 01 29 00

步骤 4:背光驱动配置

屏幕点亮了,还要开背光,不然还是黑的。RK 平台的背光,一般用 PWM 驱动,我们只需要在设备树里配置好对应的 PWM 引脚、频率、亮度等级就行,上面的设备树里已经加了 backlight 节点,只需要把 PWM 引脚改成你开发板对应的就行。

步骤 5:编译 SDK,烧录验证

  1. 设备树修改完成后,进入 SDK 根目录,执行完整编译,或者只编译内核和设备树: bash

    运行

    复制代码
    ./build.sh -CKu
  2. 编译完成后,把生成的 boot.img 和 update.img 烧录到开发板;

  3. 开发板上电,正常情况下,屏幕会在 U-Boot 阶段就点亮,进入安卓系统后,正常显示桌面。


四、LVDS 屏适配要点

工业屏常用的 LVDS 接口,适配流程和 MIPI 屏几乎完全一样,核心区别只有两点:

  1. 设备树里配置的是 LVDS 控制器,而不是 DSI 控制器,RK3568 有 2 路 LVDS 接口;
  2. 不需要配置 MIPI 初始化命令,只需要配置好时序参数、LVDS 格式(单路 / 双路、JEIDA/VESA 格式)就行。

厂家给的 LVDS 屏规格书里,会明确说明是 JEIDA 格式还是 VESA 格式,单路还是双路,我们只需要在设备树里对应的节点里配置好就行,其他的时序参数、背光配置,和 MIPI 屏完全一样。


五、小白屏幕适配必踩的坑,100% 问题排查指南

99% 的新手适配屏幕,都会遇到屏不亮、花屏、闪屏的问题,我把所有常见问题的排查步骤,按优先级给你整理好了,按这个顺序查,99% 的问题都能解决。

问题 1:屏幕完全不亮,黑屏

按这个顺序排查:

  1. 先查硬件
    • 测量屏幕的供电引脚,有没有 3.3V/5V 供电,没供电先查供电电路;
    • 测量复位引脚,上电后有没有正常的复位电平变化,没复位先查复位引脚的设备树配置;
    • 测量 MIPI 排线的差分信号,有没有数据输出,没数据说明 DSI 控制器没正常工作。
  2. 再查设备树配置
    • 检查 dsi0、route_dsi0、vopb 的 status 是不是 okay,有没有被禁用;
    • 检查 MIPI 通道数是不是和屏幕一致,2 Lane 的屏不能配成 4 Lane;
    • 检查初始化命令是不是正确,有没有漏掉延时命令,厂家给的初始化代码里的延时,必须严格对应;
    • 检查像素时钟是不是在合理范围内,不能太高也不能太低。
  3. 查内核日志 :开发板连串口,开机的时候看内核日志,搜索dsivoppanel相关的日志,看有没有报错,比如时序参数不对、初始化失败、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 安卓驱动开发,不踩坑。有任何屏幕适配的问题,评论区留言,我都会一一回复。

相关推荐
阿拉斯攀登3 小时前
第 18 篇 综合项目实战:基于 RK3568 的安卓智能门禁系统,全栈开发
android·驱动开发·瑞芯微·嵌入式驱动·rk3576·安卓驱动
UXbot3 小时前
APP原型生成工具测评
android·前端·人工智能·低代码·ios·开发·app原型
q***75184 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
泯仲4 小时前
从零起步学习MySQL || 第十五章:MySQL 可重复读隔离级别:它是如何工作的?是否完全解决幻读?
android·学习·mysql
qq_367719304 小时前
Android MQTT开源库paho.mqtt.android+MQTTX软件使用记录
android·java·开源·android mqtt开源库·mqttx软件使用
毕设源码-邱学长4 小时前
【开题答辩全过程】以 基于Android的仓库管理系统的设计与实现为例,包含答辩的问题和答案
android
2501_916008894 小时前
移动应用上架到应用商店的完整指南:原理与详细步骤
android·ios·小程序·https·uni-app·iphone·webview
草莓熊Lotso4 小时前
MySQL CRUD 核心指南:查询、插入、更新、删除全实战
android·开发语言·数据库·c++·人工智能·mysql
轩情吖4 小时前
MySQL之表的约束
android·数据库·c++·后端·mysql·开发·约束