第 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 安卓驱动开发,不踩坑。有任何屏幕适配的问题,评论区留言,我都会一一回复。

相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui