时间轴

2026-02-17

init


LCD 介绍

LCD 概述

LCD 全称是 Liquid Crystal Display,即液晶显示器。

液晶是一种介于固体和液体之间的特殊物质,在电场的作用下,液晶分子的排列会产生变化。从而影响到它的光学性质。

LCD 也是常用的外设之一,通过 LCD 可以显示图像、界面,搭配触摸,鼠标也可以实现人机交互。比如日常生活中常见的电脑屏幕,手机屏幕基都有 LCD 的身影。

在 LCD 显示器普及之前,CRT 显示器是主流的显示设备,也就是我们俗称的“大头”显示器。

这种显示器如今已经很少见了。CRT 显示器的全称是“阴极射线显像管”,它采用阴极射线管(Cathode Ray Tube)技术实现图像显示。

CRT 显示器主要由五个关键部分组成:

  1. 用于发射电子束的电子枪(Electron Gun)
  2. 控制电子束方向的偏转线圈(Deflection Coils)
  3. 用于精确聚焦电子束的荫罩(Shadow Mask)
  4. 提供高压支持的石墨电极
  5. 以及涂覆在屏幕内壁上的荧光粉层(Phosphor)和玻璃外壳。

这些组件共同协作,将电子信号转化为可见的图像。

除了 LCD 之外,如今还出现了更为高端的 OLED 屏幕。例如,目前许多旗舰手机都采用了 OLED 屏幕。

OLED 的全称是“有机发光二极管”(Organic Light-Emitting Diode),其显示原理与传统 LCD不同:

OLED 无需背光灯,而是使用非常薄的有机材料涂层和玻璃基板(或柔性基板),当电流通过时,这些有机材料会自行发光。

LCD 面板

LCD 可以细分为 TFT、TN、IPS、VA、SLCD,他们分别代表不同的液晶面板技术,这些技术各自具有独特的特点和应用场景,每个技术的具体描述如下所示:

技术名称 全称 描述
TFT 薄膜晶体管(Thin Film Transistor) TFT 式显示屏是各类笔记本电脑和台式机上的主流显示设备。每个液晶像素点由集成在像素点后方的薄膜晶体管驱动,因此属于有源矩阵液晶显示设备。TFT 显示器具有高响应度、高亮度、高对比度等优点,显示效果接近 CRT 显示器,是 LCD 彩色显示器中的高端产品之一。
TN 扭曲向列型(Twisted Nematic) TN 面板是一种入门级液晶面板,因生产成本低廉而被广泛应用在中低端液晶显示器中。虽然性能较为基础,但其低成本使其成为市场主流选择之一。
IPS 横向电场效应显示技术(In-Plane Switching) IPS 技术由日立于 1996 年开发,是一种广视角液晶显示技术。相比 TN 屏幕,IPS 能有效改善视角差时出现的色差问题,并广泛应用于液晶电视和平板电脑制造中,提供更优质的显示效果。
VA 多域垂直排列(Vertical Alignment) VA 面板是一种折中 TN 和 IPS 优点的液晶面板技术,具有较高的对比度和较好的色彩表现,同时价格适中。其缺点是响应时间较慢,通常用于中高端显示器以及对画质有一定要求的场景,例如家庭影院显示器。
SLCD 拼接专用液晶屏(Splice Liquid Crystal Display) SLCD 是 LCD 的高档衍生品种,采用工业级液晶面板,使用寿命长达 6 万小时。它既可单独作为显示器使用,也可拼接成超大屏幕,是完整的拼接显示单元,适用于高端显示需求场景。

IPS、VA 和 TN 面板各有优劣。

  • 从色彩和色准表现来看,IPS 最优,其次是 VA,最后是 TN;
  • 在响应时间方面,TN 面板最快,而 IPS 次之,VA 最慢;
  • 可视角度上,IPS 表现最好,VA 次之,TN 最差;
  • 对比度,VA 面板最强,IPS 居中,TN 最弱。

综合来看,不同面板类型在各项指标上各有特点,可以根据需求选择适合的面板

像素

用液晶的控制原理,可以设计出能够调节红、绿、蓝三种颜色输出强度的显示结构。将这三种显示结构组合成一个显示单位,通过精确控制每种颜色的亮度,就可以让该单位呈现出不同的颜色。这样的一个显示单位被称为“像素”。

因此,一个像素点可以被类比为一个小的 RGB 灯,而由于 RGB 是光的三原色,它们可以混合生成任意颜色。

分辨率

假如一个屏幕的分辨率是 1920x1080,那一共就有 1920x1080=2073600 个像素点。所以分辨率就是构成屏幕的像素数。

一般来说,分辨率越高,显示效果就越好,但是分辨率并不是唯一标准,像屏幕亮度,色彩色准,可视角度也是影响屏幕显示效果的重要参数。

像素

比如上面这张图横轴是 X,竖轴是 Y,如果表示的是 1920x1080 分辨率屏幕,则 X 轴方向有 1920 个像素点,Y 轴上有 1080 个像素点。由此可见,分辨率越高屏幕显示效果越好。是衡量屏幕显示效果的一个重要参数。

像素格式

一个像素点就类似于是一个 RGB 小灯,而 RGB 是光的三原色可以组成任意颜色。所以通过控制 RGB 这三种颜色的亮度就可以显示出任意颜色,那如何控制 RGB 这三种颜色的亮度呢?

RGB 这三种颜色一般分别使用 8bit 的数据,所以一个像素点就是 8 bit x 3 = 24 bit,这种像素格式被称为 RGB888。可以显示$\left(\left(2^8\right) \times \left(2^8\right) \times \left(2^8\right)\right)$种显色。

除了 RGB888 这种像素格式,还有 RGB565,RGB666 等。即:

  • RGB565:R-5bit,G-6bit,B-5bit,可以显示$\left(\left(2^5\right) \times \left(2^6\right) \times \left(2^5\right)\right)$种颜色。
  • RGB555:R-5bit,G-5bit,B-5bit,可以显示$\left(\left(2^5\right) \times \left(2^5\right) \times \left(2^5\right)\right)$种颜色。

那是不是选择像素格式越大的屏幕就越好呢?

假如现在有一个 1920x1080 分辨率的屏幕,如果采用 24bit 的像素格式,需要的带宽为 1920x1080x24,但是如果采用 16bit 的像素格式,需要的带宽为 1920x1080x16,可见:

像素格式越大,需要的带宽就越大,所以在选择像素格式时会受到接口带宽,处理器能力等限制。

PPI

PPI 即像素密度,全称为 Pixels Per Inch,表示每英寸的像素数。PPI 计算公式如下所示:
$$
\text{PPI} = \frac{\sqrt{X^2 + Y^2}}{\text{屏幕尺寸}}
$$
通过计算公式可以见,在计算屏幕 PPI 时候,是使用对角线的英寸长度作为度量衡。

举个例子,一块 10 英寸,分辨率为 2400 x1080 分辨率的屏幕,经计算 PPI 为 263,而同样分辨率的屏幕,如果换成 8 英寸大小,那么它计算所得的 PPI 为 329,所以后者的显示细腻程度自然要更好些。

LCD 接口种类

LCD 接口种类有很多,嵌入式上常见的有 RGB、MIPI、LVDS、EDP 接口,显示器上常见的有 DP、HDMI、VGA 等接口,对于每个接口的简单介绍如下所示:

接口名称 简介
RGB 并行数字接口,采用 TTL 电平传输红绿蓝信号,常用于早期液晶屏和嵌入式显示。
MIPI 高速串行数字接口,专为移动设备设计(如手机 / 平板),采用差分信号传输,具有低功耗特点且支持高分辨率。
LVDS 低压差分串行数字接口,抗干扰能力强,广泛用于笔记本、显示器等中高端屏幕。
EDP 嵌入式 DisplayPort 接口,基于高速串行数字传输,速率远超 LVDS,适用于高分辨率笔记本、平板及专业显示器。
VGA 模拟信号接口,通过 RGBHV 信号传输,兼容性强但分辨率受限,已逐渐被数字接口取代。
HDMI 全数字音视频接口,支持高分辨率和音频同步传输,广泛用于电视、显示器及消费电子设备。

DBI DPI 和 DSI 接口类别

DBI、DPI 和 DSI 接口是是 MIPI 联盟的一个工作组 DWG(Display Working Group)对屏幕接口的另一种分类,与上面提高到的 RGB,MIPI,LVDS,EDP 等接口并不冲突。

  • DBI 接口又叫做 MCU 接口和 8080 接口,全称为 Display Bus Interface。可以通过并行接口传输控制命令和数据,并通过往液晶模组自带的 GRAM 更新数据实现屏幕的刷新。

  • DPI 全称为 Display Pixel Interface,即显示像素接口,是并行接口,比如前面提到的 RGB 接口就可以归类成 DPI 接口。

  • DSI 全称为 Display serial interface,即显示串行接口,是 MIPI 联盟定义的一种图象输出接口。

LCD 触摸屏组成

在嵌入式开发中,常用的 LCD 屏幕大多带有触摸功能,通过触摸操作实现人机交互。需要注意的是,LCD 和触摸屏是两个独立的组件,分别承担不同的功能。LCD 屏幕主要负责图像和内容的显示,而触摸部分则专注于检测用户的触摸输入并实现交互控制。

LCD 屏幕部分如下所示:

LCD 屏幕

LCD 触摸组件:

LCD 触摸组件

有的 LCD 是一整块,并非是像上面所讲解的由俩个部分组成。这是由于 LCD 和触摸两者贴合在一起,形成一个既可以显示内容又支持触摸操作的模块。

根据贴合方式的不同,常见的工艺分为全贴合和框贴两种:

  • 全贴合工艺通常应用于消费类产品,其优点是模组更薄;
  • 而框贴工艺则多用于工业场景,具有更高的可靠性和耐用性。

LCD 屏幕通常需要搭配一块屏幕转接板,用于与开发板进行连接。需要注意的是,在嵌入式领域,LCD 屏幕的接口并没有统一的标准,不同厂家的线序可能存在差异。因此,在连接屏幕时务必仔细核对线序,避免因线序不一致而导致屏幕、开发板或核心板损坏的风险。

显示控制器

显示控制器的基本概念

显示控制器,又称 LCDC(全称为 LCD Controller),主要负责将内存中的图像数据传输到显示设备上。

随着技术的不断发展,显示控制器的功能也得到了增强,能够处理一些简单的图像操作,例如缩放、旋转和图像合成等。

显示控制器在处理器中的作用类似于计算机中的显卡。当处理器集成了显示控制器时,相当于内置了显卡模块,可以直接驱动显示屏输出图像信号。

例如,像 RK3399、RK3588 和 RK3568 这样的高性能 SoC 均内置了显示控制器,无需额外硬件即可实现视频输出功能。

集成了显示控制器的处理器框架图如下所示:

集成了显示控制器的处理器框架图

在嵌入式领域,一些低功耗微控制器(如 STM32 系列)通常不集成显示控制器。这类处理器如果需要实现图像输出,则必须外接带有 GRAM 的显示模块以完成图形处理和显示功能。

未集成显示控制器的处理器框架图:

未集成显示控制器的处理器框架图

未集成显示控制器的处理器架构通常具备以下特点:

  1. 图形处理能力有限,需依赖外置显示模块提供的运算资源。
  2. 系统功耗和硬件成本相对较低,适合对能效和经济性要求较高的场景。
  3. 主要应用于工业控制、传感器面板等基础显示需求的领域。

VOP 简介

在瑞芯微的系列 SoC 中,显示控制器被称为 VOP(Video Output Processor)。目前,瑞芯微处理器中存在两种 VOP 架构:VOP1 和 VOP2。

两者的区别主要体现在对多屏显示的支持方式上。通常情况下,一个 VOP 在同一时刻只能驱动一个屏幕独立显示。如果需要实现多屏显示,则需要多个 VOP 协同工作。

VOP1

VOP1 正是采用这种传统方式来支持多屏显示(一个 VOP 在同一时刻只能驱动一个屏幕独立显示),VOP1 架构的功能示意图如下所示:

VOP1

例如在 RK3399 处理器中内置的显示控制器类型为 VOP1。在 RK3399 处理器的 TRM 手册中关于 VOP 的描述如下所示:

RK3399 处理器中,集成了两个 VOP 模块,分别称为 VOP_BIG 和 VOP_LIT。因此,RK3399 最多可以支持两个屏幕同时显示。

VOP2

相比之下,VOP2 架构在处理器中仅包含一个 VOP 模块,但在其后端设计了多个独立的 VP(Video Port)输出接口。这些 VP 接口能够同时独立工作,从而实现多路显示输出。也就是说,VOP2 的显示能力取决于 VP 的数量,有几个 VP 就可以支持几路同时显示(同显或异显),VOP2 架构的功能示意图如下所示:

VOP2

以 RK3568 处理器为例,其技术参考手册(TRM)对 VOP2 的描述如下:

VOP 描述

VOP2 是连接内存帧缓冲区与显示设备的显示接口模块。它通过 AHB 从接口(AHB Slave)与 AHB 总线相连,用于寄存器配置;同时通过 AXI 主接口(AXI Master)与 AXI 总线相连,用于读取显示帧数据。

所以对于 RK3568 处理器来说,最多支持 3 屏同/异显。RK3568 处理器每路 VP 又支持不同接口的 LCD 屏幕。如下图所示:

RK3568 VP 和各显示接口连接关系:

其中,VP0 和 VP1 均支持 MIPI0、MIPI1、eDP 以及 HDMI 接口的输出,而 VP2 则支持 LVDS 和 RGB 接口的输出。这种多样化的接口配置使得 RK3568 能够适配多种显示设备,充分体现了其在 LCD 接口设计上的灵活性。

需要注意的是,每路 VP 在同一时间只能支持一种显示接口的输出。例如,若 VP1 被配置为 LVDS 输出,则无法同时用于 HDMI 输出。此外,不同 VP 接口的最大分辨率能力也有所差异。关于各 VP 接口的最大分辨率支持情况,具体如下所示:

VOP 通道 最大分辨率 @刷新率 支持接口及对应分辨率 @刷新率
VP0 4096×2304@60Hz - HDMI: 4096×2160@60Hz
- eDP: 2560×1600@60Hz
- MIPI: 1920×1080@60Hz (单通道)
- MIPI: 2048×1536@60Hz (双通道)
VP1 1920×1080@60Hz - HDMI: 1920×1080@60Hz
- eDP: 1920×1080@60Hz
- MIPI: 1920×1080@60Hz (单通道)
- LVDS: 1280×800@60Hz
VP2 1920×1080@60Hz - LVDS: 1280×800@60Hz
- RGB: 1920×1080@60Hz
Connector-mirror 技术

在 RK3568 芯片中,具备三路独立的视频处理单元(VP),因此在最基本的条件下,RK3568 支持三路显示输出。如果需要同时输出更多的画面,可以通过使用 connector-mirror 技术进行扩展。

例如,RK3588 在四路 VOP 的基础上,结合 connector-mirror 技术,可以实现同时输出七路显示信号的应用场景。

Connector-mirror 技术

上图使用 connector-mirror 技术把两路 HDMI/eDP 连接在 VP0 上,把两路 DP 连接在 VP1 上,把两路 MIPI DSI 连接在 VP2 上,VP3 通过 BT656,BT1120 输出,这样就实现了同时输出 7路。

通过上述配置,系统最多可以同时输出 7 路显示信号 ,但这些信号实际上是通过 4 组独立的显示通路实现的。需要注意的是,每一组(即同一个 Video Port 上的两个显示接口)输出的显示时序和内容是完全相同的

在这种应用模式下,每组显示通路的最大分辨率受限于对应的 Video Port 和所连接的显示接口的最大分辨率支持能力。此功能可以通过 DTS(Device Tree Source)配置来开启。在 DTS 文件中,只需将两个显示接口挂载到同一个 Video Port 下即可完成配置。

目前,该特性仅在 NVR SDK 中支持,而 Android 暂不支持此功能。

vop-split 技术

VOP-Split 功能是一种类似于 MIPI 双通道模式的技术,能够将一路 Video Port 的输出在水平方向上分割为左右两部分,从而同时驱动两个显示接口。在这种模式下,两个显示接口的显示时序保持一致,但可以分别输出内容独立的画面。

需要注意的是,该功能目前仅支持基于 VOP2 架构的硬件平台。通过使用 VOP-Split 功能,可以实现更高效的显示扩展能力。使用 VOP-Split 功能进行扩展的应用框图如下所示:

vop-split 技术

在 VP0 上启用 Split 模式后,VP0 的输出可以同时驱动两个显示接口(例如 HDMI0/1、eDP0/1或其他与 VP0 相连的显示接口)。这两个显示接口所呈现的内容是将 VP0 输出的画面在水平方向上左右平分后的结果。

例如,如果 VP0 以 3840x1080 的分辨率输出,则每个显示接口会分别显示 1920x1080 的画面。

需要注意的是,在 Split 模式下,同一个 VP 上参与输出的两个显示接口必须保持相同的显示时序和帧率。

名词解释

名词 解释
Encoder 一个编码器,能将显示控制器输出的图像信号转换成数字信号,如 HDMI、MIPI 等。
Connector 一个连接器,可将 encoder 输出的信号传输给显示器,并与显示器建立连接。
Bridge 桥接设备,一般指转换芯片,例如 RGB 转 HDMI。
Panel 一般指具体的显示屏。
Plane 图层,输出的图像由多个图层叠加而成,像有主图层、光标图层等。
GEM 全称为 generic DRM memory-management,即对 DRM 使用的显存进行管理,包括 dumb、prime、fence。
Framebuffer 帧缓存,是 Linux 将显存进行抽象后的一块缓存(内存)。目的是在应用层提供一套直接操作屏幕的接口,而无需关心物理显存的位置、换页机制等具体细节。Framebuffer 设备文件一般为 /dev/fb*

LCD 时序

名词解释

信号 全称 作用
HSYNC Horizontal Sync 控制水平扫描同步信号,确保每行像素正确对齐。
HPW Horizontal Low Pulse Width 定义水平同步信号的电子脉冲宽度。
HSA Horizontal Sync Active 表示水平同步信号处于有效状态的时间段。
HSS Horizontal Sync Start 表示水平同步信号的起始位置。
HSE Horizontal Sync End 表示水平同步信号的结束位置。
HBP Horizontal Back Porch 水平同步信号结束到有效像素区域开始之间的空白间隔。
HFP Horizontal Front Porch 有效像素区域结束到下一个水平同步信号开始之间的空白间隔。
HACT Horizontal Active 定义屏幕水平方向的有效像素区域宽度。
VSYNC Vertical Sync 控制垂直扫描同步信号,确保每帧图像正确对齐。
VPW Vertical Low Pulse Width 定义垂直同步信号的低电平脉冲宽度。
VSA Vertical Sync Active 表示垂直同步信号处于有效状态的时间段。
VSS Vertical Sync Start 表示垂直同步信号的起始位置。
VSE Vertical Sync End 表示垂直同步信号的结束位置。
VBP Vertical Back Porch 垂直同步信号结束到有效像素区域开始之间的空白间隔。
VACT Vertical Active 定义屏幕垂直方向的有效像素区域高度。
VFP Vertical Front Porch 有效像素区域结束到下一个垂直同步信号开始之间的空白间隔。

在有的资料中一些名词又有其他名称:

全称 其他名称
HBP (Horizontal Back Porch) left_margin
HFP (Horizontal Front Porch) right_margin
VBP (Vertical Back Porch) upper_margin
VFP (Vertical Front Porch) lower_margin
HPW (HSYNC pulse width) hsync_len
VPW (VSYNC pulse width) vsync_len

时序

Linux 中对 LCD 的时间参数,也就是时序做了抽象。在内核源码:Documentation/fb/framebuffer.rst 中可以找到 Linux 对 LCD 时序的抽象图,如下图所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
+----------+---------------------------------------------+----------+-------+
| | ↑ | | |
| | |upper_margin | | |
| | ↓ | | |
+----------###############################################----------+-------+
| # ↑ # | |
| # | # | |
| # | # | |
| # | # | |
| left # | # right | hsync |
| margin # | xres # margin | len |
|<-------->#<---------------+--------------------------->#<-------->|<----->|
| # | # | |
| # | # | |
| # | # | |
| # |yres # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # ↓ # | |
+----------###############################################----------+-------+
| | ↑ | | |
| | |lower_margin | | |
| | ↓ | | |
+----------+---------------------------------------------+----------+-------+
| | ↑ | | |
| | |vsync_len | | |
| | ↓ | | |
+----------+---------------------------------------------+----------+-------+

图中展示了一种物理装置,其中的“电子枪”会按照从左至右、从上到下的顺序,逐行逐像素地绘制每一个像素点。直到最后一个像素点被绘制完成,整帧画面才会完全呈现出来。这一过程在下图中有所展示:

扫描

“电子枪”绘制一帧画面的过程是按照 Z 字形逐行扫描完成的。每行从左到右绘制,完成后回到下一行的起始位置,直到整帧画面绘制完毕。

在这个过程中:

  • HSYNC(水平同步信号)用于指示开始绘制新的一行,因此它出现在每行的最右边;
  • VSYNC(垂直同步信号)则表示开始新的一帧,出现在整帧画面的底部。
  • 抽象图中的 Hactive 和 Vactive 区域代表实际的图像显示区域,而围绕其四周的 HFP(水平前沿)、HBP(水平后沿)、VFP(垂直前沿)、VBP(垂直后沿) 共同构成了所谓的“黑边”,它们的存在是为了留出信号切换和电子枪回扫的时间。

具体解释如下:

  1. HFP(Horizontal Front Porch):当前一行绘制完后,电子枪关闭,等待下一次 HSYNC 信号产生前的时间。
  2. HSYNC:指示水平回扫的开始,电子枪跳回下一行行首。
  3. HBP(Horizontal Back Porch):HSYNC 信号结束后到电子枪重新开启开始绘制新一行之间的等待时间。
  4. VFP(Vertical Front Porch):整帧画面绘制完后,电子枪关闭,等待 VSYNC 信号产生前的时间。
  5. VSYNC:指示垂直回扫的开始,电子枪回到屏幕左上角准备绘制新一帧。
  6. VBP(Vertical Back Porch):VSYNC 信号结束后到电子枪重新开启开始绘制新一帧之间的等待时间。

这些“黑边”区域虽然不参与实际图像显示,但对于保持图像稳定和同步至关重要。抽象图表示如下图:

抽象图表

“电子枪”在 CRT 显示器中比较普遍,但是现在 CRT 显示器已经被淘汰。LCD 中并没有“电子枪”的存在。而且使用芯片代替“电子枪”来控制 LCD 的时序。

LCD 时序实例

这里以 4412 处理器数据手册中的 LCD 时序图为例进行参数的分析

4412 处理器 LCD 时序图

  • HSYNC:水平扫描同步信号,也叫行同步信号。此信号产生表示开始扫描新的一行。上图中 HSYNC 信号是高电平有效。

  • HSPW:HSYNC 信号宽度。有些 LCD 数据手册中也叫做 thp。

  • HBP/HBPD:HSYNC 信号结束到下一个有效数据开始的时间。有些 LCD 数据手册也叫 thb,有些工程师也把他叫做行同步信号后肩,行同步信号后摇。

  • HFP/HFPD:一行有效数据结束到 HSYNC 信号产生的等待的时间。有些 LCD 数据手册也叫 thf,有些工程师也把他叫做行同步信号前肩,行同步信号前摇。

  • VCLK:像素时钟,也叫做 PCLK,素时钟信号的频率与 LCD 的分辨率有关,分辨率越高,像素时钟信号的频率也越高。

  • VDEN:数据使能信号,也叫做 DE 信号,表示有效数据,上图中是高电平有效。

  • HOZVAL:表示扫描一行需要的时间,有些 LCD 数据手册也叫 thd。

  • VSYNC:垂直扫描同步信号,也叫做帧同步信号。此信号产生表示开始显示新的一帧画面。上图中 HSYNC 信号是高电平有效。

  • VSPW:VSYNC 信号宽度,有些 LCD 数据手册中也叫做 tvp。VBP/VBPD:VSYNC 信号结束到新的一帧开始的时间。有些 LCD 数据手册也叫 tvb,有些工程师也把他叫做帧/垂直同步信号后肩,帧/垂直同步信号后摇。

  • VFP/VFPD:一帧画面扫描结束到 VSYNC 信号产生的时间。有些 LCD 数据手册也叫 tvf,有些工程师也把他叫做帧/垂直同步信号前肩,帧/垂直同步信号前摇。

  • FRAME:显示一帧画面需要的时间。

在点亮屏幕的时候我们需要确定这些参数的大小,可以看屏幕的数据手册也可以可以通过屏幕供应商的 FAE 人员来确定。下面就是一款 LCD 屏幕数据手册中对这些参数的描述。

Item Symbol Min. Typ. Max. Unit Remark
Horizontal Display Area thd - 1024 - DCLK
DCLK Frequency fclk 40.8 51.2 67.2 MHz
One Horizontal Line th 1114 1344 1400 DCLK
HS pulse width thpw 1 - 40 DCLK
HS Blanking thb 160 160 160 DCLK
HS Front Porch thfp 16 160 216 DCLK
Vertical Display Area tvd - 600 - TH
VS period time tv 624 635 750 TH
VS pulse width tvpw 1 - 20 TH
VS Blanking tvb 23 23 23 TH
VS Front Porch tvfp 1 12 127 TH

RGB 屏幕移植

RGB 接口介绍

iTOP-RK3568 核心板支持 RGB 接口,可以连接 RGB 接口的 LCD。需要注意的是,底板上将 RGB 接口复用成了其他功能。

iTOP-RK3568 核心板 RGB 接口资源以及在底板被复用其他功能如下:

RGB 信号 对应 GPIO 网络标号 底板复用功能
LCDC_D0 GPIO2_D0_d PCIE20_CLKREQn_M1 PCIE2.0 参考时钟请求
LCDC_D1 GPIO2_D1_d PCIE20_WAKEn_M1 PCIE2.0 唤醒
LCDC_D2 GPIO2_D2_d PCIE30X1_CLKREQn_M1/SPI0_CS0_M1 PCIE3.0 参考时钟请求 / SPI0 CS0 引脚
LCDC_D3 GPIO2_D3_d PCIE30X1_WAKEn_M1/SPI0_CLK_M1 PCIE3.0 唤醒 / SPI CLK 引脚
LCDC_D4 GPIO2_D4_d PCIE30X2_CLKREQn_M1 PCIE3.0 参考时钟请求
LCDC_D5 GPIO2_D5_d PCIE30X2_WAKEn_M1 PCIE3.0 唤醒
LCDC_D6 GPIO2_D6_d PCIE30X2_PERSTn_M1 PCIE3.0 复位
LCDC_D7 GPIO2_D7_d PCIE30X2_PRSNT_L_GPIO2_D7 PCIE3.0 插入检测
LCDC_CLK GPIO3_A0_d PCIE30X1_PRSNT_L_GPIO3_A0/PCIE20_PRSNT_L_GPIO3_A0 PCIE3.0 插入检测 / PCIE2.0 复位
LCDC_D8 GPIO3_A1_d PCIE30X1_PERSTn_M1 PCIE3.0 复位
LCDC_D9 GPIO3_A2_d I2S3_MCLK_M0 I2S3 MCLK 引脚
LCDC_D10 GPIO3_A3_d I2S3_SCLK_M0 I2S3 SCLK 引脚
LCDC_D11 GPIO3_A4_d I2S3_LRCK_M0 I2S3 LRCK 引脚
LCDC_D12 GPIO3_A5_d I2S3_SDO_M0/TP_INT_L_GPIO3_A5 I2S3 SDO 引脚 / 触摸 INT 引脚
LCDC_D13 GPIO3_A6_d I2S3_SDI_M0/USB_OTG_PWREN_H_GPIO3_A6 I2S3 SDI 引脚 / USB OTG 电源使能引脚
LCDC_D14 GPIO3_A7_d GMAC1_INT/PMEB_GPIO3_A7 GMAC1 的 INT 和 PMEB 功能
LCDC_D15 GPIO3_B0_d GMAC1_RSTn_GPIO3_B0 GMAC1 的复位引脚
LCDC_D16 GPIO3_B1_d UART4_RX_M1 UART4 RX 引脚
LCDC_D17 GPIO3_B2_d UART4_TX_M1 UART4 TX 引脚
LCDC_D18 GPIO3_B3_d I2C5_SCL_M0 I2C5 SCL 引脚
LCDC_D19 GPIO3_B4_d I2C5_SDA_M0 I2C5 SDA 引脚
LCDC_D20 GPIO3_B5_d RS485_DIR_GPIO3_B5 RS485 输入输出控制引脚
LCDC_D21 GPIO3_B6_d GPIO3_B6_d GPIO3_B6 引脚
LCDC_D22 GPIO3_B7_d GPIO3_B7_d GPIO3_B7 引脚
LCDC_D23 GPIO3_C0_d GPIO3_C0_d GPIO3_C0 引脚
LCDC_HSYNC GPIO3_C1_d PCIE20_PERSTn_M1 PCIE2.0 复位
LCDC_VSYNC GPIO3_C2_d HP_DET_L_GPIO3_C2 耳机插拔检测引脚
LCDC_DEN GPIO3_C3_d SPK_CTL_H_GPIO3_C3/5G_RESET 功放控制引脚 / 5G 复位引脚

RGB 接口通常需要 28 根信号线,这也解释了为什么在底板设计中,RGB 信号的引脚经常被复用为其他功能。原因是 RGB 接口一旦全部引出,会占用 28 个引脚,导致资源消耗过多。

在这 28 根信号线中,有 24 根用于传输颜色数据,分别对应红(R)、绿(G)、蓝(B)三种颜色信号,具体信号线为 LCD_D0 ~ LCD_D23。另外 4 根是控制信号线,包括水平同步信号(LCDC_HSYNC)、垂直同步信号(LCDC_VSYNC)、数据使能信号(LCDC_DEN)和像素时钟信号(LCDC_CLK)。具体分配如下表所示:

信号线 作用
R[7:0] 红色颜色数据线
G[7:0] 绿色颜色数据线
B[7:0] 蓝色颜色数据线
LCDC_HSYNC 水平同步数据线
LCDC_VSYNC 垂直同步数据线
LCDC_DEN 数据使能数据线
LCDC_CLK 像素时钟数据线

在 RGB 接口中 24 根颜色引脚分别对应 R、G、R 三种颜色,对应信号线为 LCD_D0~LCDD23, 在这 24 根颜色引脚中其中 R 对应的 8 根引脚, G 对应的 8 根引脚,R 对应的 8 根引脚在以 iTOP-RK3568 核心板为例,瑞芯微官方资料介绍如下所示:

R G B 分别对应的8根引脚如图所示

在 RGB 接口中,信号线的连接方式取决于所使用颜色格式。

  • 对于 RGB888 格式:

    • 核心板的 D0 ~ D7 对应蓝色通道 B0 ~ B7
    • D8 ~ D15 对应绿色通道 G0 ~ G7
    • D16 ~ D23 对应红色通道 R0 ~ R7
  • 在 RGB666 格式中:

    • 蓝色、绿色和红色通道的低两位(B0 ~ B1G0 ~ G1R0 ~R1)不连接,其余信号线仍按 RGB888 的映射规则连接。
  • 对于 RGB565 格式:

    • 蓝色、绿色和红色通道的低位(B0 ~ B2G0 ~ G1R0 ~ R2)不连接,其余信号线同样按照 RGB888 的映射规则进行连接。

这种灵活的连接方式能够适应不同的颜色格式需求,同时优化引脚资源的使用。

同步模式

通过前面的 LCD 时序分析可知,在行时序中包含 HFP(水平前肩)、HBP(水平后肩)和 HSYNC(水平同步信号),而在列时序中则包含 VFP(垂直前肩)、VBP(垂直后肩)和 VSYNC(垂直同步信号)。

这些时序部分并不包含可显示的数据,因此 LCD 和处理器之间需要一种机制来实现同步。

同步的核心作用是让 LCD 能够识别当前处理器发送的信号状态,例如在发送 HFP 等非显示时序时,LCD 不会将其作为有效数据进行显示;或者通知 LCD从某个时间点开始,后续传输的数据为有效显示数据,可以用于屏幕显示。

为了实现这一同步目的,目前主要有两种方式:

  • DE 模式
  • HV 模式

DE 模式

使用 DE 数据线来表示有效数据的开始和结束,例如 LCDC_DEN 信号线。

DE 模式

当 DE 信号变为高电平时,表示有效数据开始,当 DE 信号变为低电平时,表示有效数据结束。所以在 DE 模式下是不需要 HSYNC,VSYNC 等信号线。使用起来比较简单。

HV 模式

在 HV 模式下,需要通过 HSYNC(水平同步信号)和 VSYNC(垂直同步信号)来确定 LCD 的时序,而无需使用 DE(数据使能)信号线,同步工作完全依赖 HSYNC 和 VSYNC 信号完成。

HV 模式

目前,大多数 LCD 屏幕同时支持 HV 模式和 DE 模式。例如,以下这款屏幕就兼容这两种模式,并通过其第 8 引脚来选择具体的工作模式:

  • 当第 8 引脚为高电平时,屏幕工作在 DE 模式;

  • 当第 8 引脚为低电平时,则切换为 HV 模式。

这种设计为开发者提供了更大的灵活性,可以根据实际需求选择合适的同步方式。

例子

硬件原理图分析

iTOP-RK3568 核心板本身引出了 RGB 接口,但在标准底板中,该接口已被复用为其他功能。因此,如果需要使用 RGB 显示功能,需要自行设计并制作适配的底板。

下面以 “iTOP-RK3568 核心板+迅为电子 5 寸 RGB 屏幕” 为例进行说明。在底板设计时,可参考下方提供的原理图进行绘制与连接。

RGB

功能 引脚标号 功能 引脚标号
LCDC_D0 SPI0_MISO_M1 LCDC_D14 GMAC1_INT/PMEB_GPIO3_A7
LCDC_D1 SPI0_MOSI_M1 LCDC_D15 GMAC1_RSTn_GPIO3_B0
LCDC_D2 SPI0_CS0_M1 LCDC_D16 UART4_RX_M1
LCDC_D3 SPI0_CLK_M1 LCDC_D17 UART4_TX_M1
LCDC_D4 PCIE30X2_CLKREQn_M1 LCDC_D18 I2C5_SCL_M0
LCDC_D5 PCIE30X2_WAKEn_M1 LCDC_D19 I2C5_SDA_M0
LCDC_D6 PCIE30X2_PERSTn_M1 LCDC_D20 GPIO3_B5
LCDC_D7 PCIE30X2_PRSNT_L_GPIO2_D7 LCDC_D21 GPIO3_B6
LCDC_D8 PCIE30X1_PERSTn_M1 LCDC_D22 GMAC0_RSTn_GPIO3_B7
LCDC_D9 I2S3_MCLK_M0 LCDC_D23 GMAC0_INT/PMEB_GPIO3_C0
LCDC_D10 I2S3_SCLK_M0 LCDC_CLK PCIE20_PRSNT_L_GPIO3_A0
LCDC_D11 I2S3_LRCK_M0 LCDC_HSYNC PCIE20_PERSTn_M1
LCDC_D12 TP_INT_L_GPIO3_A5 LCDC_VSYNC HP_DET_L_GPIO3_C2
LCDC_D13 USB_OTG_PWREN_H_GPIO3_A6 LCDC_DEN 5G_RESET

通过表格可知,如果使用 RGB 接口涉及到了非常多的引脚复用冲突问题,topeet 已将配置好复用关系的设备树放在路径下。

适配步骤

要使用 RGB 接口需要在设备树中把 VP2 打开。而 VP2 的前端是 VOP,所以需要先打开 VOP,然后打开 VP2 设置 RGB 显示通路,具体设置步骤如下所示:

设置 RGB 显示通路

arch/arm64/boot/dts/rockchip/rk3568.dtsi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
vop: vop@fe040000 {
compatible = "rockchip,rk3568-vop"; // 匹配 Rockchip RK3568 视频输出处理器驱动
reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
reg-names = "regs", "gamma_lut";
rockchip,grf = <&grf>;
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; // 关联的通用寄存器文件(GRF)配置节点
// 使用 GIC SPI 中断 148,高电平触发
clocks = <&cru ACLK_VOP>, // VOP AXI 总线时钟
<&cru HCLK_VOP>, // VOP AHB 总线时钟
<&cru DCLK_VOP0>, // VP0 显示像素时钟
<&cru DCLK_VOP1>, // VP1 显示像素时钟
<&cru DCLK_VOP2>; // VP2 显示像素时钟
// 时钟名称定义(与 clocks 顺序对应)
clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
iommus = <&vop_mmu>; // 关联的 IOMMU 设备,用于内存地址转换
power-domains = <&power RK3568_PD_VO>; // 所属电源域(显示输出)
status = "disabled"; // 默认禁用,需在板级配置中启用

vop_out: ports { // 显示输出端口定义
#address-cells = <1>; // 子节点使用 1 个地址单元
#size-cells = <0>; // 子节点无大小单元

/* VP0,支持 DSI0/DSI1/eDP/HDMI 输出 */
vp0: port@0 {
#address-cells = <1>; // 端点使用 1 个地址单元
#size-cells = <0>; // 端点无大小单元
reg = <0>; // 端口编号 0

vp0_out_dsi0: endpoint@0 { // 到 DSI0 的端点
reg = <0>;
remote-endpoint = <&dsi0_in_vp0>;
};

vp0_out_dsi1: endpoint@1 { // 到 DSI1 的端点
reg = <1>;
remote-endpoint = <&dsi1_in_vp0>;
};

vp0_out_edp: endpoint@2 { // 到 eDP 的端点
reg = <2>;
remote-endpoint = <&edp_in_vp0>;
};

vp0_out_hdmi: endpoint@3 { // 到 HDMI 的端点
reg = <3>;
remote-endpoint = <&hdmi_in_vp0>;
};
};

/* VP1,支持 DSI0/DSI1/eDP/HDMI/LVDS 输出 */
vp1: port@1 {
#address-cells = <1>; // 端点使用 1 个地址单元
#size-cells = <0>; // 端点无大小单元
reg = <1>; // 端口编号 1

vp1_out_dsi0: endpoint@0 { // 到 DSI0 的端点
reg = <0>;
remote-endpoint = <&dsi0_in_vp1>;
};

vp1_out_dsi1: endpoint@1 { // 到 DSI1 的端点
reg = <1>;
remote-endpoint = <&dsi1_in_vp1>;
};

vp1_out_edp: endpoint@2 { // 到 eDP 的端点
reg = <2>;
remote-endpoint = <&edp_in_vp1>;
};

vp1_out_hdmi: endpoint@3 { // 到 HDMI 的端点
reg = <3>;
remote-endpoint = <&hdmi_in_vp1>;
};

vp1_out_lvds: endpoint@4 { // 到 LVDS 的端点
reg = <4>;
remote-endpoint = <&lvds_in_vp1>;
};

vp1_out_lvds1: endpoint@5 {
reg = <5>;
remote-endpoint = <&lvds1_in_vp1>;
};
};

/* VP2,支持 LVDS/RGB 输出 *
vp2: port@2 {
#address-cells = <1>;
#size-cells = <0>;

reg = <2>; // 端口编号 2

vp2_out_lvds: endpoint@0 { // 到 LVDS 的端点
reg = <0>;
remote-endpoint = <&lvds_in_vp2>;
};

vp2_out_rgb: endpoint@1 { // 到 RGB 接口的端点
reg = <1>;
remote-endpoint = <&rgb_in_vp2>;
};

vp2_out_lvds1: endpoint@2 {
reg = <2>;
remote-endpoint = <&lvds1_in_vp2>;
};
};
};
};
  • compatible 属性值为 rockchip,rk3568-vop,表示会使用 gpu/drm/rockchip/rockchip_vop2_reg.c 这个驱动程序。
  • status 属性值为 disabled,表示此节点被禁用,所以需要使能此节点。
  • VP0 可以支持 DSI0,DSI1,eDP,HDMI 接口。
  • VP1 可以支持 DSI0,DSI1,eDP,HDMI,LVDS 接口。
  • VP1,VP2 可以支持 LVDS,RGB 接口。

然后在 arch/arm64/boot/dts/rockchip/topeet-rk3568-linux.dtsi 设备树中,使用追加的方式将 VOP 节点使能

1
2
3
4
5
6
&vop {
status = "okay";
// VP0、VP1、VP2 的时钟以及父时钟
assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>, <&cru PLL_VPLL>;
};

其中 VP0、VP1、VP2 的时钟以及父时钟拓扑结构如下

1
2
3
4
5
PMUCRU
└─ PLL_HPLL → DCLK_VOP0 (VP0)
CRU
├─ PLL_VPLL → DCLK_VOP1 (VP1)
└─ PLL_VPLL → DCLK_VOP2 (VP2)

打开 VOP 以后,接下来设置 RGB 接口使用 VP2 输出的显示通路。打开 rk3568.dtsi 设备树文件,找到 RGB 节点,具体内容如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
grf: syscon@fdc60000 {
compatible = "rockchip,rk3568-grf", "syscon", "simple-mfd";
reg = <0x0 0xfdc60000 0x0 0x10000>;

io_domains: io-domains {
compatible = "rockchip,rk3568-io-voltage-domain";
status = "disabled";
};

lvds0: lvds: lvds {
compatible = "rockchip,rk3568-lvds";
phys = <&video_phy0>;
phy-names = "phy";
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

lvds0_in_vp1: lvds_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_lvds>;
status = "disabled";
};

lvds0_in_vp2: lvds_in_vp2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vp2_out_lvds>;
status = "disabled";
};
};
};
};

lvds1: lvds1 {
compatible = "rockchip,rk3568-lvds";
phys = <&video_phy1>;
phy-names = "phy";
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

lvds1_in_vp1: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp1_out_lvds1>;
};

lvds1_in_vp2: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp2_out_lvds1>;
};
};
};
};

rgb: rgb {
compatible = "rockchip,rk3568-rgb";
pinctrl-names = "default";
pinctrl-0 = <&lcdc_ctl>;
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

rgb_in_vp2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vp2_out_rgb>;
status = "disabled";
};
};
};
};

};

compatible 属性值为 rockchip,rk3568-rgb,表示会使用 gpu/drm/rockchip/rockchip_rgb.c 这个驱动程序。

status 属性值为 disabled,表示 RGB 节点被禁用,所以我们需要使能 RGB 节点。

rgb_in_vp2 表示 RGB 接口连接到 VP2,status 属性值为 disabled 表示使用 VP2 输出 RGB 被禁止。(RGB 接口所对应的 VP 端口,对于 RK3568 的 RGB 接口来说需要使用 VP2 进行输出。)

pinctrl-0 = <&lcdc_ctl>;使用 pinctrl 子系统设置 RGB 引脚复用。lcdc_ctl 节点在 rk3568-pinctrl.dtsi 设备树文件中。具体内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
lcdc {
/omit-if-no-ref/
lcdc_ctl: lcdc-ctl {
rockchip,pins =
/* lcdc_clk */
<3 RK_PA0 1 &pcfg_pull_none>,
/* lcdc_d0 */
<2 RK_PD0 1 &pcfg_pull_none>,
/* lcdc_d1 */
<2 RK_PD1 1 &pcfg_pull_none>,
/* lcdc_d2 */
<2 RK_PD2 1 &pcfg_pull_none>,
/* lcdc_d3 */
<2 RK_PD3 1 &pcfg_pull_none>,
/* lcdc_d4 */
<2 RK_PD4 1 &pcfg_pull_none>,
/* lcdc_d5 */
<2 RK_PD5 1 &pcfg_pull_none>,
/* lcdc_d6 */
<2 RK_PD6 1 &pcfg_pull_none>,
/* lcdc_d7 */
<2 RK_PD7 1 &pcfg_pull_none>,
/* lcdc_d8 */
<3 RK_PA1 1 &pcfg_pull_none>,
/* lcdc_d9 */
<3 RK_PA2 1 &pcfg_pull_none>,
/* lcdc_d10 */
<3 RK_PA3 1 &pcfg_pull_none>,
/* lcdc_d11 */
<3 RK_PA4 1 &pcfg_pull_none>,
/* lcdc_d12 */
<3 RK_PA5 1 &pcfg_pull_none>,
/* lcdc_d13 */
<3 RK_PA6 1 &pcfg_pull_none>,
/* lcdc_d14 */
<3 RK_PA7 1 &pcfg_pull_none>,
/* lcdc_d15 */
<3 RK_PB0 1 &pcfg_pull_none>,
/* lcdc_d16 */
<3 RK_PB1 1 &pcfg_pull_none>,
/* lcdc_d17 */
<3 RK_PB2 1 &pcfg_pull_none>,
/* lcdc_d18 */
<3 RK_PB3 1 &pcfg_pull_none>,
/* lcdc_d19 */
<3 RK_PB4 1 &pcfg_pull_none>,
/* lcdc_d20 */
<3 RK_PB5 1 &pcfg_pull_none>,
/* lcdc_d21 */
<3 RK_PB6 1 &pcfg_pull_none>,
/* lcdc_d22 */
<3 RK_PB7 1 &pcfg_pull_none>,
/* lcdc_d23 */
<3 RK_PC0 1 &pcfg_pull_none>,
/* lcdc_den */
<3 RK_PC3 1 &pcfg_pull_none>,
/* lcdc_hsync */
<3 RK_PC1 1 &pcfg_pull_none>,
/* lcdc_vsync */
<3 RK_PC2 1 &pcfg_pull_none>;
};
};

topeet_rk3568_lcds.dtsi 设备树文件中使用以下代码来设置 RGB 显示通路。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
&rgb {
status = "okay"; // 表示使能 rgb 节点

// 添加 rgb_out 节点设置 RGB 屏幕信息,通过 rgb_out_panel 节点指向 RGB 屏幕
ports {
rgb_out: port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;

rgb_out_panel: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_in_rgb>;
};
};
};
};

// 将 rgb_in_vp2 节点 的 status 属性值改为 okay,表示使能 rgb_in_vp2 节点。
&rgb_in_vp2 {
status = "okay";
};

这样从 VOP 到 VP2,再到 RGB 屏幕的显示通路就设置好了。

设置屏幕信息

topeet_rk3568_lcds.dtsi添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
rgb_panel: panel {
compatible = "simple-panel";
status = "disabled";
backlight = <&backlight>;
power-supply = <&vcc3v3_lcd0_n>;
enable-delay-ms = <10>;
prepare-delay-ms = <20>;
unprepare-delay-ms = <20>;
disable-delay-ms = <20>;
bus-format = <MEDIA_BUS_FMT_RGB565_1X16>;
width-mm = <43>;
height-mm = <73>;

display-timings {
native-mode = <&rgb_timing0>;

rgb_timing0: rgb-timing0 {
clock-frequency = <20000000>;
hactive = <800>;
vactive = <480>;
hback-porch = <24>;//<100>;
hfront-porch = <72>;//<1580>;
vback-porch = <10>;//<25>;
vfront-porch = <12>;//<10>;
hsync-len = <24>;//<10>;
vsync-len = <2>;//<4>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
dual-lvds-even-pixels;
panel_in_rgb: endpoint {
remote-endpoint = <&rgb_out_panel>;
};
};
};

compatible属性值为 simple-panel,表示会使用 gpu/drm/panel/panel-simple.c 驱动程序,也就是通用屏幕驱动程序。

status 属性值为 disabled,表示禁止使用该节点所表示的 RGB 屏幕。需要将此属性设置成 okay。

backlight 属性表示使用 &backlight 背光控制节点。

power-supply:可选属性,属性表示屏幕所使用的供电电源。

enable-delay-ms:可选属性,电源使能到面板启动的延迟。

prepare-delay-ms:可选属性,面板接收图像数据前的延迟。

unprepare-delay-ms:可选属性,关闭面板前的等待时间。

disable-delay-ms:可选属性,面板断电前的延迟。

width-mm:可选属性,屏幕的物理宽度

height-mm:可选属性,屏幕的物理高度

bus-format :属性用来配置像素格式,属性值 MEDIA_BUS_FMT_RGB565_1X16 表示使用 RGB565 格式。属性值MEDIA_BUS_FMT_RGB666_1X18 表示使用 RGB666 格式,属性值 MEDIA_BUS_FMT_RGB888_1X24 表示使用 RGB888 格式。

display-timings节点:是 LCD 时序参数,具体说明请参考 LCD 时序章节。

ports:是屏幕的 ports 节点,其中第 40 行设置了屏幕的远端端点是 rgb_out_panel

这样 RK3568 的 RGB 接口就和屏幕关联了起来。

又因为rgb_panel 节点默认是禁止的,所以还需将 rgb_panel 节点打开,在 topeet_rk3568_lcds.dtsi 设备树文件中添加以下代码。

1
2
3
&rgb_panel{
status = "okay";
}

设置背光

rgb_panel 节点中使用 backlight 属性引用 backlight 背光控制节点,设备树如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts
backlight: backlight {
compatible = "pwm-backlight";
brightness-levels = <
0 20 20 21 21 22 22 23
23 24 24 25 25 26 26 27
27 28 28 29 29 30 30 31
31 32 32 33 33 34 34 35
35 36 36 37 37 38 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <200>;
};

compatible 属性值为 pwm-backlight,表示使用 video/backlight/pwm_bl.c 这个驱动程序。

pwms 属性表示使用的 PWM 通道和 PWM 的频率。如 pwms = <&pwm4 0 2500 0 0>表示使用 PWM4 第 0 个通道,频率为 40KHZ(25000 是周期,单位是 ns,换算成频率为 40KHZ),最后一个 0 表示极性,0 对应 PWM_POLARITY_NORMAL 正常极性,1 对应 PWM_POLARITY_INVERTED 表示反转极性。

brightness-levels 表示亮度等级,范围是 0 到 255,其中 0 表示 PWM 占空比为 0%,255 表示 PWM 占空比为 100%。

default-brightness-level 属性表示默认亮度等级,该节点中默认亮度等级是 220。

如果要控制 PWM 背光节点的打开和关闭以及 PWM 频率等信息。可以在 arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 设备树文件中添加以下代码。通过追加的方式去修改。

1
2
3
4
&backlight {
status = "okay";
pwms = <&pwm4 0 25000 0>;
};

设置触摸

以迅为 RGB 接口 5 寸屏幕为例,该屏幕使用 FT5X 触摸芯片,使用 I2C5 进行通信。打开 arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 设备树文件,添加以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
&i2c5 {
status = "okay";
ft5x061:ft5x06@38 {
status = "disabled";
compatible = "edt,edt-ft5306";
reg = <0x38>;
touch-gpio = <&gpio3 RK_PB1 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PB1 IRQ_TYPE_LEVEL_LOW>;
reset-gpio = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <800>;
touchscreen-size-y = <480>;
touch_type = <1>;
};
};

compatible 属性值为 edt,edt-ft5306,表示使用 input/touchscreen/edt-ft5x06.c 驱动程序。

reg 属性值为 0x38,表示从机地址是 0x38。

touch-gpio 属性表示使用 GPIO3_B1 引脚作为触摸中断引脚。IRQ_TYPE_EDGE_RISING 表示上升沿触发。

interrupt-parent 属性中断父节点是 gpio3。

interrupts 属性表示使用 GPIO 中的 B1 引脚,触发方式改为低电平触发。

reset-gpio 属性表示使用 GPIO3_B2 引脚作为复位引脚。

touchscreen-size-x 表示在 x 轴上的分辨率

touchscreen-size-y 表示在 y 轴上的分辨率。

touch_type 属性表示触摸类型

如果需要使用触摸,可以在 arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 设备树文件中添加以下代码,通过追加
的方式去控制触摸节点的打开和关闭。

1
2
3
&ft5x063 {
status = "okay";
};

如果需要显示 uboot 和内核阶段 logo,需要打开 route_rgb 节点,需要注意的是 uboot 阶段 logo 如果没有开启,内核阶段也无法显示 logo。

打开 rk3568.dtsi 设备树文件,route_rgb 节点定义如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
display_subsystem: display-subsystem {
compatible = "rockchip,display-subsystem";
memory-region = <&drm_logo>, <&drm_cubic_lut>;
memory-region-names = "drm-logo", "drm-cubic-lut";
ports = <&vop_out>;
devfreq = <&dmc>;

route {
route_dsi0: route-dsi0 {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vp0_out_dsi0>;
};
route_dsi1: route-dsi1 {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vp0_out_dsi1>;
};
route_edp: route-edp {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vp0_out_edp>;
};
route_hdmi: route-hdmi {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vp1_out_hdmi>;
};
route_lvds: route-lvds {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vp1_out_lvds>;
};
route_rgb: route-rgb {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vp2_out_rgb>;
};
};
};

status 属性为 disabled,表示禁止 logo 显示,如果需要显示 logo,则需要将此状态的属性值改成 okay。

logo,ubootlogo,kernel:分别对应 uboot 和内核 logo,logo 图片的格式为 bmp 格式。当属性留空或者指定的图片找不到时,logo 将不会显示。

logo,modecharge_logo,mode 表示 logo 模式,有俩种模式支持,center 表示居中,fullscreen 表示全屏。

connect 属性用来指定具体的显示通路。connect = <&vp2_out_rgb>表示 rgb 使用 vp2 输出。

如果需要使用 logo,可以在 arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 添加以下代码,通过追加的方式打开 route_rgb 节点。

1
2
3
&route_rgb {
status = "okay";
};

设置宏开关

点亮屏幕的工作都集中在对设备树的配置上,所以可以把要操作的节点放在条件编译所控制的代码块中来控制对某一个屏幕的打开和关闭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#if defined(LCD_TYPE_RGB_5_0)

&rgb {
status = "okay"; // 表示使能 rgb 节点

// 添加 rgb_out 节点设置 RGB 屏幕信息,通过 rgb_out_panel 节点指向 RGB 屏幕
ports {
rgb_out: port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;

rgb_out_panel: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_in_rgb>;
};
};
};
};



rgb_panel: panel {
compatible = "simple-panel";
status = "disabled";
backlight = <&backlight>;
power-supply = <&vcc3v3_lcd0_n>;
enable-delay-ms = <10>;
prepare-delay-ms = <20>;
unprepare-delay-ms = <20>;
disable-delay-ms = <20>;
bus-format = <MEDIA_BUS_FMT_RGB565_1X16>;
width-mm = <43>;
height-mm = <73>;

display-timings {
native-mode = <&rgb_timing0>;

rgb_timing0: rgb-timing0 {
clock-frequency = <20000000>;
hactive = <800>;
vactive = <480>;
hback-porch = <24>;//<100>;
hfront-porch = <72>;//<1580>;
vback-porch = <10>;//<25>;
vfront-porch = <12>;//<10>;
hsync-len = <24>;//<10>;
vsync-len = <2>;//<4>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
dual-lvds-even-pixels;
panel_in_rgb: endpoint {
remote-endpoint = <&rgb_out_panel>;
};
};
};

// 将 rgb_in_vp2 节点 的 status 属性值改为 okay,表示使能 rgb_in_vp2 节点。
&rgb_in_vp2 {
status = "okay";
};

&rgb_panel{
status = "okay";
}

&backlight {
status = "okay";
pwms = <&pwm4 0 25000 0>;
};

&ft5x063 {
status = "okay";
};

&route_rgb {
status = "okay";
};
#endif

LVDS 屏幕移植

接口介绍

LVDS 全称是 Low-Voltage Differential Signaling,即低电压差分信号。LVDS 具有低功耗,低误码率,低串扰,低抖动,低辐射和良好的信号完整性等特点。在显示器应用中非常广泛,比如笔记本电脑屏幕,医学设备显示器等。

1994 年,以美国国家半导体(National Semiconductor, NS,现 TI)为主推出了 ANS/TIA/EIA-644 标准。在 1996 年又推出了 IEEE 1596.3 标准。不过现在 IEEE 1596.3 很少使用了,主要流行的是 ANS/TIA/EIA-644 标准,RK3568 处理器的 LVDS 接口也是采用的此标准,数据手册相关内容如下所示:

LVDS Interface

LVDS 采用差分信号进行数据传输,其基本工作原理如下:

LVDS Driver and Receiver

发送器一端有一个电流源,可以提供 3.5ma 的电流。在接收器的输入端有一个 100 欧姆的电阻,因为接收器内部的阻值很高,电流会通过 100 欧姆的电阻回到发送器,所以在终端电阻的俩端会有一个 350mv 的电压。通过改变电流方向接收器就可以通过正负 350mv 来判断输入的信号是正还是负。

RK3568 这颗处理器有 1 路 LVDS 接口,最大支持 1280x800@60Hz 分辨率。LVDS 引脚如下

引脚标号 作用
MIPI_DSI_TX0_D0P/LVDS_TX0_D0P MIPI_DSI_TX0_D0P 或者 LVDS_TX0_D0P 引脚
MIPI_DSI_TX0_D0N/LVDS_TX0_D0N MIPI_DSI_TX0_D0N 或者 LVDS_TX0_D0N 引脚
MIPI_DSI_TX0_D1P/LVDS_TX0_D1P MIPI_DSI_TX0_D1P 或者 LVDS_TX0_D1P 引脚
MIPI_DSI_TX0_D1N/LVDS_TX0_D1N MIPI_DSI_TX0_D1N 或者 LVDS_TX0_D1N 引脚
MIPI_DSI_TX0_D2P/LVDS_TX0_D2P MIPI_DSI_TX0_D2P 或者 LVDS_TX0_D2P 引脚
MIPI_DSI_TX0_D2N/LVDS_TX0_D2N MIPI_DSI_TX0_D2N 或者 LVDS_TX0_D2N 引脚
MIPI_DSI_TX0_D3P/LVDS_TX0_D3P MIPI_DSI_TX0_D3P 或者 LVDS_TX0_D3P 引脚
MIPI_DSI_TX0_D3N/LVDS_TX0_D3N MIPI_DSI_TX0_D3N 或者 LVDS_TX0_D3N 引脚
MIPI_DSI_TX0_CLKP/LVDS_TX0_CLKP MIPI_DSI_TX0_CLKP 或者 LVDS_TX0_CLKP 引脚
MIPI_DSI_TX0_CLKN/LVDS_TX0_CLKN MIPI_DSI_TX0_CLKN 或者 LVDS_TX0_CLKN 引脚

LVDS 引脚也可以复用成一路 MIPI DSI,在开发板上是被复用成了 LVDS 引脚。

LVDS 屏幕介绍

在选型 LVDS 屏幕时,单 6、单 8、双 6、双 8 表示 LVDS 屏幕接口方式不同。

类型 传输方式与数据位数描述
单路 6 位 LVDS 采用单路方式传输,每个基色信号采用 6 位数据,一共 18 位 RGB 数据。
单路 8 位 LVDS 采用单路方式传输,每个基色信号采用 8 位数据,一共 24 位 RGB 数据。
双路 6 位 LVDS 采用双路方式传输,每个基色信号采用 6 位数据,奇路数据为 18 位,偶路数据为 18 位,共 36 位 RGB 数据。
双路 8 位 LVDS 采用双路方式传输,每个基色信号采用 8 位数据,奇路数据为 24 位,偶路数据为 24 位,共 48 位 RGB 数据。

6 位与 8 位 LVDS 接口对比(以单路为例):

类型 差分信号线总数 数据线对数 时钟线对数 数据线引脚名称 时钟线引脚名称
6 位 LVDS 4 对 3 对 1 对 LVDS_TX0_D0P/D0NLVDS_TX0_D1P/D1NLVDS_TX0_D2P/D2N LVDS_TX0_CLKP/CLKN
8 位 LVDS 5 对 4 对 1 对 LVDS_TX0_D0P/D0NLVDS_TX0_D1P/D1NLVDS_TX0_D2P/D2NLVDS_TX0_D3P/D3N LVDS_TX0_CLKP/CLKN

其中 6 位采用的是 4 对差分信号线,其中 3 对是数据线,1 对时钟线。8 位采用的是 5 对差分信号线,其中 4 对是数据线,1 对时钟线。通过差分信号线的数量很好区分是 6 位还是 8 位。区分完 6 位和 8 位以后,就要区分是单路还是双路。

单路与双路 LVDS 对比

单路可以理解成是只有 1 路 LVDS 接口,双路就是有俩路 LVDS 接口。所以在区分是 6 位还是 8 位的时候是以单路为例,因为双路只需要在原来的基础上 x2 就可以了。

随着屏幕的分辨率的增加,像素时钟也越来越高。但是像素时钟不能无限制的增加,所以就把要输出的像素按照顺序分为奇像素和偶像素,奇像素使用一路 LVDS 进行传输,偶像素使用一路 LVDS 进行传输。所以理论上双路 LVDS 支持的分辨率更高。

实例分析

10.1 寸 LVDS 屏幕接口定义,具体如下图所示:

Pin No. Symbol I/O Function Remark
1 NC No connection
2 VDD P Power supply
3 VDD P Power supply
4 NC No connection
5 NC No connection
6 NC No connection
7 GND P Power Ground
8 Rxin0N I -LVDS differential data
9 Rxin0P I +LVDS differential data
10 GND P Ground
11 Rxin1N I -LVDS differential data
12 Rxin1P I +LVDS differential data
13 GND P Ground
14 Rxin2N I -LVDS differential data
15 Rxin2P I +LVDS differential data
16 GND P Ground
17 RCLKN I -LVDS differential clock input
18 RCLKP I +LVDS differential clock input
19 GND P Ground
20 Rxin3N I -LVDS differential data
21 Rxin3P I +LVDS differential data
22 GND P Ground
23 NC No connection
24 NC No connection
25 GND P Power Ground

一共有 Rxin0N、Rxin0P,Rxin1N、Rxin1P,Rxin2N、Rxin2P,Rxin3N、Rxin3P,RCLKN、RCLKP 五对差分线,其中四对是数据线,一对是时钟线,并且只有 1 路 LVDS 接口,所以是单 8 接口方式。

除了路数和位数不同,LVDS 显示屏有两种信号格式,分别是 VESA 标准和 JEIDA 标准,其中:

  • VESA:全称为 Video Electronics Standards Association,即视频电子标准协会。该组织制定了许多视频、显示器周边功能的相关标准。

  • JEIDA:全称为 Japan Electronic Industry Development Association,即日本电子工业发展协

所以在调试屏幕时要注意 LVDS 屏幕默认数据格式是采用 VESA 标准还是 JEIDA 标准,从而确定驱动是使用 VESA 标准还是 JEIDA 标准进行输出。

硬件原理图分析

iTOP-RK3568 开发板有引出 LVDS 接口,接口原理图如下:

iTOP-RK3568 LVDS 接口

  1. TP_RST_L_GPIO0_B6 是触摸复位引脚。

  2. I2C2_SCL_M1 是 I2C2 SCL 引脚。用于和触摸芯片进行 I2C 通信。I2C2_SDA_M1 是 I2C2 SDA 引脚。用于和触摸芯片进行 I2C 通信。

  3. TP_INT_L_GPIO3_A5 是触摸中断引脚。

  4. LCD0_BL_PWM4 是 PWM 引脚,用于调整屏幕背光。

  5. MIPI_DSI_TX0_D3N/LVDS_TX0_D3N、MIPI_DSI_TX0_D3P/LVDS_TX0_D3P、MIPI_DSI_TX0_D0N/LVDS_TX0_D0N、MIPI_DSI_TX0_D0P/LVDS_TX0_D0P、MIPI_DSI_TX0_D1N/LVDS_TX0_D1N、MIPI_DSI_TX0_D1P/LVDS_TX0_D1P、
    MIPI_DSI_TX0_D2N/LVDS_TX0_D2N、MIPI_DSI_TX0_D2P/LVDS_TX0_D2P、MIPI_DSI_TX0_CLKN/LVDS_TX0_CLKN、MIPI_DSI_TX0_CLKP/LVDS_TX0_CLKP 是 LVDS 接口引脚。直接一一对应连接到处理器的 LVDS 接口上。

  6. J38 是跳线帽插座,防止接错屏幕导致烧坏屏幕和 CPU 使用,检查好硬件连接以后,需使用跳线帽连接电源。

适配步骤

设置 LVDS 显示通路

使用 LVDS 接口可以选择 VP1 或者 VP2,VP1 除了支持 LVDS 输出,还支持 MIPI,eDP,HDMI 输出。VP2 仅支持 LVDS 和 RGB 输出,如果使用 VP1 输出 LVDS 信号,其他信号如 MIPI,eDP,HDMI 就不能使用。所以开发板上选择支持信号较少的 VP2 作为 LVDS 输出,留下支持信号更多的 VP1 做其他选择。

RK3568 VP 和各显示接口连接关系:

RK3568 VP 和各显示接口连接关系:

设置 VP2 作为 LVDS 显示通路之前需要先打开 VOP 节点。rk3568.dtsi 中定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
vop: vop@fe040000 {
compatible = "rockchip,rk3568-vop";
reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
reg-names = "regs", "gamma_lut";
rockchip,grf = <&grf>;
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
iommus = <&vop_mmu>;
power-domains = <&power RK3568_PD_VO>;
status = "disabled";

vop_out: ports {
#address-cells = <1>;
#size-cells = <0>;

vp0: port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;

vp0_out_dsi0: endpoint@0 {
reg = <0>;
remote-endpoint = <&dsi0_in_vp0>;
};

vp0_out_dsi1: endpoint@1 {
reg = <1>;
remote-endpoint = <&dsi1_in_vp0>;
};

vp0_out_edp: endpoint@2 {
reg = <2>;
remote-endpoint = <&edp_in_vp0>;
};

vp0_out_hdmi: endpoint@3 {
reg = <3>;
remote-endpoint = <&hdmi_in_vp0>;
};
};

vp1: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;

vp1_out_dsi0: endpoint@0 {
reg = <0>;
remote-endpoint = <&dsi0_in_vp1>;
};

vp1_out_dsi1: endpoint@1 {
reg = <1>;
remote-endpoint = <&dsi1_in_vp1>;
};

vp1_out_edp: endpoint@2 {
reg = <2>;
remote-endpoint = <&edp_in_vp1>;
};

vp1_out_hdmi: endpoint@3 {
reg = <3>;
remote-endpoint = <&hdmi_in_vp1>;
};

vp1_out_lvds: endpoint@4 {
reg = <4>;
remote-endpoint = <&lvds_in_vp1>;
};

vp1_out_lvds1: endpoint@5 {
reg = <5>;
remote-endpoint = <&lvds1_in_vp1>;
};
};

vp2: port@2 {
#address-cells = <1>;
#size-cells = <0>;

reg = <2>;

vp2_out_lvds: endpoint@0 {
reg = <0>;
remote-endpoint = <&lvds_in_vp2>;
};

vp2_out_rgb: endpoint@1 {
reg = <1>;
remote-endpoint = <&rgb_in_vp2>;
};

vp2_out_lvds1: endpoint@2 {
reg = <2>;
remote-endpoint = <&lvds1_in_vp2>;
};
};
};
};

打开 VOP 以后,接下来设置 LVDS 接口使用 VP2 输出的显示通路。打开 rk3568.dtsi 设备树文件,找到 LVDS 节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
grf: syscon@fdc60000 {
compatible = "rockchip,rk3568-grf", "syscon", "simple-mfd";
reg = <0x0 0xfdc60000 0x0 0x10000>;

io_domains: io-domains {
compatible = "rockchip,rk3568-io-voltage-domain";
status = "disabled";
};

lvds0: lvds: lvds {
compatible = "rockchip,rk3568-lvds";
phys = <&video_phy0>;
phy-names = "phy";
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

lvds0_in_vp1: lvds_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_lvds>;
status = "disabled";
};

lvds0_in_vp2: lvds_in_vp2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vp2_out_lvds>;
status = "disabled";
};
};
};
};

lvds1: lvds1 {
compatible = "rockchip,rk3568-lvds";
phys = <&video_phy1>;
phy-names = "phy";
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

lvds1_in_vp1: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp1_out_lvds1>;
};

lvds1_in_vp2: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp2_out_lvds1>;
};
};
};
};

rgb: rgb {
compatible = "rockchip,rk3568-rgb";
pinctrl-names = "default";
pinctrl-0 = <&lcdc_ctl>;
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

rgb_in_vp2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vp2_out_rgb>;
status = "disabled";
};
};
};
};

};

compatible 属性值为 rockchip,rk3568-lvds,表示会使用 gpu/drm/rockchip/rockchip_lvds.c 这个驱动程序。

phys = <&video_phy0>;:使用了 video_phy0,所以我们需要使能 video_phy0 节点。

status 属性值为 disabled,表示 LVDS 节点被禁用,所以我们需要使能 LVDS 节点。

ports属性节点:表示 LVDS 接口所对应的 VP 端口,对于 RK3568 的 LVDS 接口来说需要使用 VP2 进行输出。

lvds_in_vp2 表示 LVDS 接口连接到 VP2,status 属性值为 disabled 表示使用 VP2 输出 LVDS 被禁止。

可以在 arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 设备树文件中添加以下代码来设置 LVDS 显示通路。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
&lvds {
status = "disabled";

ports {
port@1 {
reg = <1>;
lvds_out_panel: endpoint {
remote-endpoint = <&panel_in_lvds>;
};
};
};
};

&lvds {
status = "okay";
};

&lvds_in_vp1{
status = "disabled";
};
&lvds_in_vp2 {
status = "okay";
};
&video_phy0{
status="okay";
};

注意要关闭 VP1,打开 VP2 来输出 LVDS

video_phy0 节点如图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

video_phy0: phy@fe850000 {
// 指定兼容的驱动程序,用于设备与驱动匹配
compatible = "rockchip,rk3568-dsi-dphy", "rockchip,rk3568-video-phy";
//寄存器地址映射:定义两个物理地址段
reg = <0x0 0xfe850000 0x0 0x10000>,
<0x0 0xfe060000 0x0 0x10000>;
reg-names = "phy", "host";
// 时钟信号配置:引用三个时钟源
// ref: PHY 参考时钟(如 MIPI DSI 高速时钟)
// pclk_phy: PHY 模块的 APB 总线时钟
// pclk_host: 主机控制器(如 DSI TX)的 APB 总线时钟
clocks = <&pmucru CLK_MIPIDSIPHY0_REF>,
<&cru PCLK_MIPIDSIPHY0>, <&cru PCLK_DSITX_0>;
clock-names = "ref", "pclk", "pclk_host";
#clock-cells = <0>;
// 复位控制:关联 PHY 模块的软复位信号
resets = <&cru SRST_P_MIPIDSIPHY0>;
reset-names = "apb";
// 电源域管理:绑定到显示子系统电源域
power-domains = <&power RK3568_PD_VO>;
#phy-cells = <0>;
// 初始状态:默认不启用
status = "disabled";
};

video_phy1: phy@fe860000 {
compatible = "rockchip,rk3568-dsi-dphy", "rockchip,rk3568-video-phy";
reg = <0x0 0xfe860000 0x0 0x10000>,
<0x0 0xfe070000 0x0 0x10000>;
reg-names = "phy", "host";
clocks = <&pmucru CLK_MIPIDSIPHY1_REF>,
<&cru PCLK_MIPIDSIPHY1>, <&cru PCLK_DSITX_1>;
clock-names = "ref", "pclk", "pclk_host";
#clock-cells = <0>;
resets = <&cru SRST_P_MIPIDSIPHY1>;
reset-names = "apb";
power-domains = <&power RK3568_PD_VO>;
#phy-cells = <0>;
status = "disabled";
};

设置屏幕信息

arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 设备树文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/{
lvds_panel: panel {
compatible = "simple-panel";
status = "disabled";
backlight = <&backlight>;
power-supply = <&vcc3v3_lcd0_n>;
enable-delay-ms = <20>;
prepare-delay-ms = <20>;
unprepare-delay-ms = <20>;
disable-delay-ms = <20>;
width-mm = <217>;
height-mm = <136>;
};
};

&lvds_panel{
status = "okay";
bus-format = <MEDIA_BUS_FMT_RGB666_1X7X3_SPWG>;
display-timings {
native-mode = <&lvds_timing0>;
lvds_timing0: lvds-timing0 {
clock-frequency = <71900000>;
hactive = <800>;
vactive = <1280>;
hback-porch = <24>;//<100>;
hfront-porch = <72>;//<1580>;
vback-porch = <10>;//<25>;
vfront-porch = <12>;//<10>;
hsync-len = <24>;//<10>;
vsync-len = <2>;//<4>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dual-lvds-even-pixels;
panel_in_lvds: endpoint {
remote-endpoint = <&lvds_out_panel>;
};
};
};
};

bus-format 属性用来配置输出格式,输出格式要和 LVDS 屏幕所支持的格式对应,其中:

  • 属性值 MEDIA_BUS_FMT_RGB666_1X7X3_SPWG 表示采用 JEIDA_6BIT
  • 属性值 MEDIA_BUS_FMT_RGB888_1X7X4_SPWG 表示采用 VESA_8BIT
  • 属性值 MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA 表示采用 JEIDA_8BIT

设置背光和触摸

arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 设备树文件添加以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/ {
backlight: backlight {
compatible = "pwm-backlight";
brightness-levels = <
0 20 20 21 21 22 22 23
23 24 24 25 25 26 26 27
27 28 28 29 29 30 30 31
31 32 32 33 33 34 34 35
35 36 36 37 37 38 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <200>;
};

backlight1: backlight1 {
compatible = "pwm-backlight";
brightness-levels = <
0 20 20 21 21 22 22 23
23 24 24 25 25 26 26 27
27 28 28 29 29 30 30 31
31 32 32 33 33 34 34 35
35 36 36 37 37 38 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <200>;
};
};

&i2c2 {
status = "okay";
pinctrl-0 = <&i2c2m1_xfer>;

ft5x062:ft5x06@38 {
status = "disabled";
compatible = "edt,edt-ft5306";
reg = <0x38>;
touch-gpio = <&gpio3 RK_PA5 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <800>;
touchscreen-size-y = <1280>;

};

gt9xx:gt9xx_ts@5d {
compatible = "goodix,gt9xx";
reg = <0x5d>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&gt9xx_pins>;
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
touch-gpio = <&gpio3 RK_PA5 IRQ_TYPE_EDGE_RISING>;
status = "disabled";
tp-size = <911>;
max-x = <1024>;
max-y = <600>;
};

gt9271:gt9271_ts@5d {
compatible = "goodix,gt9271";
reg = <0x5d>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&gt9xx_pins>;
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
touch-gpio = <&gpio3 RK_PA5 IRQ_TYPE_EDGE_RISING>;
status = "disabled";
tp-size = <9271>;
max-x = <1280>;
max-y = <800>;
};
};

&pinctrl {
gt9xx {
gt9xx_pins: gt9xx-pins {
rockchip,pins =
<3 RK_PA5 0 &pcfg_pull_up>,
<0 RK_PB6 0 &pcfg_pull_none>;
};
};
};

&pwm4{
status = "okay";
};

&backlight {
status = "okay";
pwms = <&pwm4 0 25000 0>;
};

&gt9271
{
status = "okay";
};

设置屏幕 LOGO

1
2
3
4
5
&route_lvds{
// logo,rotate = <0>;
status = "okay";
connect = <&vp2_out_lvds>;
};

设置宏开关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
#define LCD_TYPE_MIPI       //in vp 1
//#define LCD_TYPE_LVDS_10_1_1024X600 //in vp 2
//#define LCD_TYPE_LVDS_10_1_1280X800_gt9271 //in vp 2
//#define LCD_TYPE_LVDS_7_0 //in vp 2
//#define LCD_TYPE_EDP_VGA //in vp 0
//#define LCD_TYPE_HDMI_VP0 //hdmi in vp 0
//#define LCD_TYPE_HDMI_VP1 //hdmi in vp 1


/ {
backlight: backlight {
compatible = "pwm-backlight";
brightness-levels = <
0 20 20 21 21 22 22 23
23 24 24 25 25 26 26 27
27 28 28 29 29 30 30 31
31 32 32 33 33 34 34 35
35 36 36 37 37 38 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <200>;
};

backlight1: backlight1 {
compatible = "pwm-backlight";
brightness-levels = <
0 20 20 21 21 22 22 23
23 24 24 25 25 26 26 27
27 28 28 29 29 30 30 31
31 32 32 33 33 34 34 35
35 36 36 37 37 38 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <200>;
};

lvds_panel: panel {
compatible = "simple-panel";
status = "disabled";
backlight = <&backlight>;
power-supply = <&vcc3v3_lcd0_n>;
enable-delay-ms = <20>;
prepare-delay-ms = <20>;
unprepare-delay-ms = <20>;
disable-delay-ms = <20>;
width-mm = <217>;
height-mm = <136>;
};
};

&i2c1 {
status = "okay";
ft5x061:ft5x06@38 {
status = "disabled";
compatible = "edt,edt-ft5306";
reg = <0x38>;
touch-gpio = <&gpio3 RK_PA5 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <800>;
touchscreen-size-y = <1280>;

};
};

&i2c2 {
status = "okay";
pinctrl-0 = <&i2c2m1_xfer>;
ft5x062:ft5x06@38 {
status = "disabled";
compatible = "edt,edt-ft5306";
reg = <0x38>;
touch-gpio = <&gpio3 RK_PA5 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <800>;
touchscreen-size-y = <1280>;

};

gt9xx:gt9xx_ts@5d {
compatible = "goodix,gt9xx";
reg = <0x5d>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&gt9xx_pins>;
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
touch-gpio = <&gpio3 RK_PA5 IRQ_TYPE_EDGE_RISING>;
status = "disabled";
tp-size = <911>;
max-x = <1024>;
max-y = <600>;

};

gt9271:gt9271_ts@5d {

compatible = "goodix,gt9271";
reg = <0x5d>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&gt9xx_pins>;
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
touch-gpio = <&gpio3 RK_PA5 IRQ_TYPE_EDGE_RISING>;
status = "disabled";
tp-size = <9271>;
max-x = <1280>;
max-y = <800>;
};


};

&pinctrl {
gt9xx {
gt9xx_pins: gt9xx-pins {
rockchip,pins =
<3 RK_PA5 0 &pcfg_pull_up>,
<0 RK_PB6 0 &pcfg_pull_none>;
};
};
};


#if defined(LCD_TYPE_LVDS_7_0)
&lvds_panel{
status = "okay";
bus-format = <MEDIA_BUS_FMT_RGB666_1X7X3_SPWG>;
display-timings {
native-mode = <&lvds_timing0>;
lvds_timing0: lvds-timing0 {
clock-frequency = <71900000>;
hactive = <800>;
vactive = <1280>;
hback-porch = <24>;//<100>;
hfront-porch = <72>;//<1580>;
vback-porch = <10>;//<25>;
vfront-porch = <12>;//<10>;
hsync-len = <24>;//<10>;
vsync-len = <2>;//<4>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dual-lvds-even-pixels;
panel_in_lvds: endpoint {
remote-endpoint = <&lvds_out_panel>;
};
};
};
};
&lvds {
status = "disabled";

ports {
port@1 {
reg = <1>;
lvds_out_panel: endpoint {
remote-endpoint = <&panel_in_lvds>;
};
};
};
};

&pwm4{
status = "okay";
};

&backlight {
status = "okay";
pwms = <&pwm4 0 25000 0>;
};

&lvds {
status = "okay";
};

&lvds_in_vp1{
status = "disabled";
};
&lvds_in_vp2 {
status = "okay";
};
&video_phy0{
status="okay";
};
&route_lvds{
// logo,rotate = <0>;
status = "okay";
connect = <&vp2_out_lvds>;
};

&ft5x062
{
status = "okay";
};
#endif

#if defined(LCD_TYPE_LVDS_10_1_1024X600)
&lvds_panel {
status = "okay";
bus-format = <MEDIA_BUS_FMT_RGB666_1X7X3_SPWG>;
display-timings {
native-mode = <&lvds_timing0>;
lvds_timing0: lvds-timing0 {
clock-frequency = <53000000>;
hactive = <1024>;
vactive = <600>;
hback-porch = <160>;//<100>;
hfront-porch = <24>;//<1580>;
vback-porch = <24>;//<25>;
vfront-porch = <2>;//<10>;
hsync-len = <116>;//<10>; DRM_PANEL_SIMPLE
vsync-len = <3>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dual-lvds-even-pixels;
panel_in_lvds: endpoint {
remote-endpoint = <&lvds_out_panel>;
};
};
};
};
&lvds {
status = "disabled";

ports {
port@1 {
reg = <1>;
lvds_out_panel: endpoint {
remote-endpoint = <&panel_in_lvds>;
};
};
};
};
&pwm4{
status = "okay";
};

&backlight {
status = "okay";
pwms = <&pwm4 0 25000 0>;
};
&lvds {
status = "okay";
};

&lvds_in_vp1{
status = "disabled";
};

&lvds_in_vp2 {
status = "okay";
};

&video_phy0{
status="okay";
};

&route_lvds{
// logo,rotate = <0>;
status = "okay";
connect = <&vp2_out_lvds>;
};

&gt9xx
{
status = "okay";
};
#endif

#if defined(LCD_TYPE_LVDS_10_1_1280X800_gt9271)
&lvds_panel {
status = "okay";
bus-format = <MEDIA_BUS_FMT_RGB888_1X7X4_SPWG>;
display-timings {
native-mode = <&lvds_timing0>;
lvds_timing0: lvds-timing0 {
clock-frequency = <82421000>;
hactive = <1280>;
vactive = <800>;
hback-porch = <88>;//<100>;
hfront-porch = <132>;//<1580>;
vback-porch = <23>;//<25>;
vfront-porch = <49>;//<10>;
hsync-len = <40>;//<10>; DRM_PANEL_SIMPLE
vsync-len = <20>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dual-lvds-even-pixels;
panel_in_lvds: endpoint {
remote-endpoint = <&lvds_out_panel>;
};
};
};
};
&lvds {
status = "disabled";

ports {
port@1 {
reg = <1>;
lvds_out_panel: endpoint {
remote-endpoint = <&panel_in_lvds>;
};
};
};
};

&pwm4{
status = "okay";
};

&backlight {
status = "okay";
pwms = <&pwm4 0 25000 0>;
};

&lvds {
status = "okay";
};

&lvds_in_vp1{
status = "disabled";
};
&lvds_in_vp2 {
status = "okay";
};
&video_phy0{
status="okay";
};
&route_lvds{
// logo,rotate = <0>;
status = "okay";
connect = <&vp2_out_lvds>;
};

&gt9271
{
status = "okay";
};
#endif

MIPI 屏幕移植

MIPI 接口介绍

MIPI 联盟成立于 2003 年,由 ARM、Nokia、ST(意法半导体)、TI(德州仪器)等公司共同发起。

MIPI 接口,全称为Mobile Industry Processor Interface(移动产业处理器接口),是由 MIPI 联盟制定的一系列开放标准和规范。这些标准旨在为移动应用处理器提供统一的接口解决方案,将手机内部的各种接口(如摄像头、显示屏、射频/基带接口等)进行标准化,从而降低手机设计的复杂性。

需要注意的是,MIPI 并不是指单一的接口或协议,而是一个包含了多种接口标准的体系。

例如:

  • MIPI DSI:用于串行显示接口(Display Serial Interface)。
  • MIPI CSI:用于摄像头串行接口(Camera Serial Interface)。
  • MIPI I3C:用于串行通信接口(改进版 I2C)。
  • MIPI RFFE:用于射频前端控制接口(RF Front-End Control Interface)。
  • MIPI SPMI:用于系统电源管理接口(System Power Management Interface)。

在本章中,我们将重点讨论 MIPI DSI,其他接口暂不涉及。移动设备中 mipi 相关接口使用示意图如下所示

MIPI Alliance

数据手册种对 RK3568 处理器 MIPI DSI 接口的介绍:

RK3568 MIPI

  • 支持 MIPI v1.2 版本
  • 支持俩通道 DSI
  • 每个通道支持 4 data lanes
  • 支持每条通道的最大数据速率为 2.5Gbps
  • 单 mipi 模式最高可达 1920x1080@60Hz 的显示输出,双 MIPI 模式最高可达 2560x1440@60Hz 的显示输出。
  • 每个颜色通道最多支持 8 位深度

对于单通道 MIPI 屏幕来说,使用一路 MIPI 接口即可,连接框图:

单通道 MIPI 屏幕

双通道 MIPI 屏幕则需要俩路 MIPI 接口,连接框图:

双通道 MIPI 屏幕

RK3568 核心板 MIPI DSI 接口引脚

MIPI DSI0 接口:

引脚 作用
MIPI_DSI_TX0_D0P/LVDS_TX0_D0P MIPI DSI TX0 D0P 引脚或 LVDS TX0 D0P 引脚
MIPI_DSI_TX0_D0N/LVDS_TX0_D0N MIPI DSI TX0 D0N 引脚或 LVDS TX0 D0N 引脚
MIPI_DSI_TX0_D1P/LVDS_TX0_D1P MIPI DSI TX0 D1P 引脚或 LVDS TX0 D1P 引脚
MIPI_DSI_TX0_D1N/LVDS_TX0_D1N MIPI DSI TX0 D1N 引脚或 LVDS TX0 D1N 引脚
MIPI_DSI_TX0_D2P/LVDS_TX0_D2P MIPI DSI TX0 D2P 引脚或 LVDS TX0 D2P 引脚
MIPI_DSI_TX0_D2N/LVDS_TX0_D2N MIPI DSI TX0 D2N 引脚或 LVDS TX0 D2N 引脚
MIPI_DSI_TX0_D3P/LVDS_TX0_D3P MIPI DSI TX0 D3P 引脚或 LVDS TX0 D3P 引脚
MIPI_DSI_TX0_D3N/LVDS_TX0_D3N MIPI DSI TX0 D3N 引脚或 LVDS TX0 D3N 引脚
MIPI_DSI_TX0_CLKP/LVDS_TX0_CLKP MIPI DSI TX0 CLKP 引脚或 LVDS TX0 CLKP 引脚
MIPI_DSI_TX0_CLKN/LVDS_TX0_CLKN MIPI DSI TX0 CLKN 引脚或 LVDS TX0 CLKN 引脚

MIPI DSI0 接口与 LVDS0 接口存在复用关系,在 iTOP-RK3568 开发板上该接口是复用成了 LVDS 接口。

MIPI DSI1 接口:

引脚 作用
MIPI_DSI_TX1_D0P MIPI DSI TX1 D0P 引脚
MIPI_DSI_TX1_D0N MIPI DSI TX1 D0N 引脚
MIPI_DSI_TX1_D1P MIPI DSI TX1 D1P 引脚
MIPI_DSI_TX1_D1N MIPI DSI TX1 D1N 引脚
MIPI_DSI_TX1_D2P MIPI DSI TX1 D2P 引脚
MIPI_DSI_TX1_D2N MIPI DSI TX1 D2N 引脚
MIPI_DSI_TX1_D3P MIPI DSI TX1 D3P 引脚
MIPI_DSI_TX1_D3N MIPI DSI TX1 D3N 引脚
MIPI_DSI_TX1_CLKP MIPI DSI TX1 CLKP 引脚
MIPI_DSI_TX1_CLKN MIPI DSI TX1 CLKN 引脚

MIPI 协议介绍

lane

在 MIPI 协议规范硬件连接框图中提到了 lane 这个词,lane 可以理解成通道,如 2 lanes 就可以理解成 2 通道,每个通道有 2 条差分数据线。如 MIPI_DSI_TX1_D0P 和 MIPI_DSI_TX1_D0N 一对数据引脚就可以看作是 1 个 lane,也就是 1 个通道。在 MIPI 章节中 lane 和通道不做区分,表示相同意思。

Host Device and Peripheral

在上面框图中告诉我们可以使用 1/2/3/4 lanes 和一对时钟线进行数据传输,对于 RK3568 核心板的 MIPI 接口来说,是使用 4 lanes 进行数据传输。

在上图中还告诉我们,在 LP(Low-Power)模式下,只用 Lane0 进行传输,并且可以进行双向传输,在 HS(High-Speed)模式下只能单向传输。

我们来看单个 lane 的框架图:

单个lane

一个通道可能包含一个 HS-TX、一个 HS-RX,或者两者都有。

在单个通道中,HS-TX 和 HS-RX 在正常操作期间不会同时启用,所以对于 HS(High-Speed)模式来说是单向传输。

如果通道中高速功能(High-Speed function)未启用,则该功能应被置于高阻抗状态。

低功耗竞争检测器(LP-CD)功能仅用于双向操作。低功耗竞争检测器功能在低功耗发射机驱动低功耗状态时启用,以检测竞争情况。

信号电平

在 LP(Low-Power)模式下只用 Lane0 进行传输,采用单端信号,信号电平在 0 到 1.2v。

在 HS(High-Speed)模式下采用差分信号进行传输,当 P 比 N 高时定义为 1,P 比 N 低时定义为 0,差分线上典型电压为差分 200mv。

信号电平

上图蓝色实线是 LP(Low-Power)模式下信号波形图,红色实线是 HS(High-Speed)模式下信号波形图。

通道状态

在 HS(High-Speed)模式下采用差分信号,当当 P 比 N 高时定义为 1,称之为 HS-1,P 比 N 低时定义为 0,称之为 HS-0。所以在 HS(High-Speed)模式下有 HS-1,HS-0 俩种状态。

在 LP(Low-Power)模式下采用单端信号,所以一共有 00,01,10,11 四种状态,分别称之为 LP-00,LP-01,LP-10,LP-11。

通道状态

三种工作模式

通道(lane)有:

  • 控制模式
  • 高速模式
  • Escape 模式

三种工作模式,高速模式工作在 HS(High-Speed)模式下,控制模式和 Escape 模式工作在 LP(Low-Power)模式下。

这三种工作模式之间可以互相切换,控制模式工作在 LP(Low-Power)模式下,所以有 LP-00,LP-01,LP-10,LP-11 四种状态。在 MIPI 协议中,将控制模式的四种不同状态组成的不同时序用来代表将要进入或者退出某种模式。比如 LP11-LP01-LP00 表示进入高速模式。

根据 MIPI 协议规范进入不同模式和退出模式的过程如下:

  1. 每个模式都必须从 Stop State(LP-11)开始。
  2. High-speed 模式和 Escape 模式之间不可以直接来回切换,必须通过控制(Control)模式进行中转,即:
    • High-speed 模式↔Control Mode↔Escape 模式。
  3. 进入 Escape mode 和退出 Escape mode 模式过程:
    • Request:LP-11→LP-10→LP-00→LP-01→LP-00
    • Exit:LP-10→LP-11
  4. 进入 High-Speed 和退出 High-Speed 模式过程:
    • Request:LP-11→LP-01→LP-00
    • Exit:EOT →LP-11
  5. 进入控制模式和退出控制模式过程:
    • Request:LP-11→LP-10→LP-00→LP-10→LP-00
    • Exit:LP-00→LP-10→LP-11

Escape 模式是数据 Lane 在 LP(Low-Power)状态下的一种特殊模式,在这个模式下有 LPDT(低功耗数据传输模式),ULPS(超低功耗模式),Trigger 等功能,一旦进入 Escape 模式,发送端必须发送一个 8bit 的命令来响应请求的动作。命令如下:

Escape Mode Action Command Type Entry Command Pattern (first bit transmitted to last bit transmitted)
Low-Power Data Transmission mode 11100001
Ultra-Low Power State mode 00011110
Undefined-1 mode 10011111
Undefined-2 mode 11011110
Reset-Trigger [Remote Application] Trigger 01100010
Entry sequence for HS Test Mode Trigger 01011101
Unknown-4 Trigger 00100001
Unknown-5 Trigger 10100000

如果不在高速模式或 Escape 模式,数据通道应保持在控制模式。

MIPI D-PHY 介绍

MIPI 除了有 D-PHY,还有 C-PHY,M-PHY。PHY 指的是物理层。如 D-PHY 可以用于摄像头和屏幕外设,C-PHY 也可以用于摄像头和屏幕外设,M-PHY 可以用于摄像头和存储外设。

M-PHY D-PHY C-PHY

D-PHY 中的 D 指的是罗马数字 500(最初的设计目标是 500 Mbits/s),不是 Display,C 和 M 分别表示罗马数字中的 100 和 1000。

MIPI DSI

上一小节提到的 PHY 属于物理层,所以对于 MIPI DSI 来说是一个分层结构。结构图如下

MIPI DSI 分层结构

从上图可以看出,一共分为 4 层,从下到上依次是:

  • PHY 层
  • 通道管理层
  • 协议层
  • 应用层

PHY 层

物理层位于整个分层结构的最底层,在物理层了规定相关的电气属性,如传输介质、电气特性、IO 电路、和同步机制等。

物理层还规定了信号传输开始(Start of Transmission,SoT)和信号传输结束(End of Transmission,EoT)的机制,以及可以在发送和接收物理层之间传递的其他“带外”信息。

物理层支持 HS(High-Speed)模式和 LP(Low-Power)模式,其中 HS 模式可以用来传输高速数据,如屏幕数据。LP 模式一般用于控制,如配置指令等。

通道管理层

数据信号的数量可能是 1、2、3 或 4 对,具体取决于应用所需的带宽要求。在接口的发射端,数据流被分配到一个或多个通道上,具有“分配器”功能。在接收端,接口从通道上收集字节,并将它们合并成一个重新组合的数据流,以恢复原始的流序列,具有“合并器”功能。

我们看 MIPI 协议规范中的这张 2 张图:

发送端:

发送端

上图左侧是使用 1 对数据线的发送方式。只使用 1 对数据线时发送只能按照串行顺序发送。

上图右侧是使用 4 对数据线的发送方式。发送端会把串行数据平均分给 4 对数据线并行传输。这个就是“分配器”功能。

接收端:

接收端

上图左侧是使用 1 对数据线的接收方式。只使用 1 对数据线时接收只能按照串行顺序接收。

上图右侧是使用 4 对数据线的接收方式。接收端会把并行的数据合并成串行数据。这个就是“合并器”功能

当发送端使用 4 对数据线时,可以按照 Byte0 分配给 Lane0,Byte1 分配给 Lane1,Byte2 分配给 Lane2,Byte3 分配给 Lane4 这样平均分配,但是如果采用 3 对数据线时就不能平均分配了。在 MIPI 协议规范中是这样解释的,对于非整数倍传输(2 对数据线的整数倍)采用以下模式:

非整数倍数传输

从上图可以看出,如果不是按照整数倍传输(也就是所有通道一起结束),则哪个通道先传输完成就先进入 Eot 模式。

协议层

协议层主要是将字节组织成预定义的单元,这些单元被称为包。即打包操作。数据会被打包成长包短包俩种格式。

短包(short packet)格式

短包(short packet)格式

从上图可知,短包一共占 4 个字节,其中 1 字节大小 DI,2 字节大小数据和 1 字节大小 ECC

  1. 数据标识符(DI):包含虚拟通道标识符和数据类型信息。数据类型表示应用程序特定负载数据的格式/内容。由应用层使用。
  2. 数据包数据:长度固定为两个字节,数据没有值限制。
  3. 数据包头部 8 位 ECC:用于纠正一位错误并检测两位错误。

这里重点介绍一下 DI 部分,DI 部分由虚拟通道和负载数据类型俩部分组成。

DI

其中 bit6 到 bit7 表示虚拟通道。DSI 协议允许最多四个虚拟通道,使多个外设可以共享一个共同的 DSI 链路。

bit0 到 bit5 表示要发送的负载数据类型。负载数据类型有:

Data Type (hex) Data Type (binary) Description Packet Size
0x01 00 0001 Sync Event, V Sync Start Short
0x11 01 0001 Sync Event, V Sync End Short
0x21 10 0001 Sync Event, H Sync Start Short
0x31 11 0001 Sync Event, H Sync End Short
0x08 00 1000 End of Transmission packet (EoTp) Short
0x02 00 0010 Color Mode (CM) Off Command Short
0x12 01 0010 Color Mode (CM) On Command Short
0x22 10 0010 Shut Down Peripheral Command Short
0x32 11 0010 Turn On Peripheral Command Short
0x03 00 0011 Generic Short WRITE, no parameters Short
0x13 01 0011 Generic Short WRITE, 1 parameter Short
0x23 10 0011 Generic Short WRITE, 2 parameters Short
0x04 00 0100 Generic READ, no parameters Short
0x14 01 0100 Generic READ, 1 parameter Short
0x24 10 0100 Generic READ, 2 parameters Short
0x05 00 0101 DCS Short WRITE, no parameters Short
0x15 01 0101 DCS Short WRITE, 1 parameter Short
0x06 00 0110 DCS READ, no parameters Short
0x37 00 1111 Set Maximum Return Packet Size Short
0x09 00 1001 Null Packet, no data Long
0x19 01 1001 Blanking Packet, no data Long
0x29 10 1001 Generic Long Write Long
0x39 11 1001 DCS Long Write/write_LUT Command Packet Long
0x0C 00 1100 Loosely Packed Pixel Stream, 20-bit YCbCr, 4:2:2 Format Long
0x1C 01 1100 Packed Pixel Stream, 24-bit YCbCr, 4:2:2 Format Long
0x2C 10 1100 Packed Pixel Stream, 16-bit YCbCr, 4:2:2 Format Long
0x0D 00 1101 Packed Pixel Stream, 30-bit RGB, 10-10-10 Format Long
0x1D 01 1101 Packed Pixel Stream, 36-bit RGB, 12-12-12 Format Long
长包(short packet)格式

长包(short packet)格式

长包应由三个部分组成:一个 32 位的包头(PH)、一个具有可变字节数的应用特定数据载荷,以及一个 16 位的包尾(PF)。

包头(PH)进一步由三个部分组成:一个 8 位的数据标识符(DI)、一个 16 位的字数计数,和一个 8 位的错误校正码(ECC)。

包传输方式

在 MIPI DSI 数据传输中是通过数据 lane 将打包好的数据包发送出去,在其最简单的传输方式中,一次传输可能只包含一个数据包。如果需要传输多个数据包,数据包是单独传输(例如,每次传输一个数据包),就需要频繁地在 LPS(Low Power State)和 HS(High-Speed)模式之间切换,所产生的开销将严重限制带宽。传输过程如下:

包传输方式

为什么需要频繁地在 LPS(Low Power State)和 HS(High-Speed)模式之间切换呢?

在上图中可以看出,当 SP(Short Packet)传输完成以后会产生 EoT(End of Transmission)信号退出 HS(High-Speed)模式。而如果不在 HS(High-Speed)模式或 Escape 模式,数据通道应保持在控制模式。而控制模式工作在 LP(Low-Power)模式下,也就是处于 LPS(Low Power State)中。下一次传输时候需要再次进入 HS(High-Speed)模式下进行传输。所以需要频繁切换。

所以在 MIPI DSI 协议中允许将多个数据包连接在一起进行传输,长包和短包可以任意顺序出现,这样可以显著提高有效带宽。这种方式对于诸如外围设备初始化等事件非常有用,因为在系统启动时,可能需要使用单独的写入命令加载许多寄存器。

传输过程如下:

将多个数据包连接在一起进行传输

在物理层(PHY 层)上,存在两种数据传输模式:HS(High-Speed)传输模式和 LP(Low-Power)传输模式。在 HS(High-Speed)传输开始之前,发射器的物理层会向接收器发出一个 SoT(开始传输)序列。之后,可以在高速模式下传输数据或命令数据包。单个 HS(High-Speed)传输中可能存在多个数据包,并且传输的结束总是在物理层上使用专用的 EoT(传输结束)序列进行信号通知。

为了增强系统的整体鲁棒性,DSI 在协议层上定义了一个专用的 EoT 数据包(EoTp)来指示 HS(High-Speed)传输的结束。为了与早期的 DSI 向后兼容,可以启用或禁用 EoTp 的功能。启用或禁用此功能的方法不在本文档的讨论范围内。

下图中是使用 EoTp 情况下的 HS(High-Speed)传输过程。

使用 EoTp 情况下的 HS(High-Speed)传输过程

上图中 EoT 短包被红色高亮显示。上图传输过程表示主机打算使用两次单独的传输来各发送一个短包,随后在发送一个长包。在这个传输过程中,每次传输结束前都会产生一个额外的EoT 短包来通知此次传输结束。

当然,使用 EoT 短包也可以将多个数据包连接在一起进行传输,传输过程如下:

使用 EoT 短包也可以将多个数据包连接在一起进行传输

  1. 包传输策略

在 MIPI 规范中规定,如果传输多个字节,低字节先传输,高字节后传输。每个字节中的位按照低位在前,高位在后的顺序传输。如下图所示

低字节先传输,高字节后传输,每个字节中的位低位在前,高位在后

  1. 应用层

高层编码和解析数据流

视频模式和命令模式

MIPI DSI 有视频模式(video mode)和命令模式(command mode)俩种。使用哪种模式取决于外设的架构和能力。一般情况下,外设只需要支持其中任意一种模式即可。但是也有部分支持视频模式的设备同时也支持一些基本的命令模式的功能。

视频模式

视频模式主要针对没有 frambuffer 的 LCD 屏进行操作,无论当前显示是否有数据更新,DSI host 端会一直发送数据给屏幕(需要不停的刷数据)。

视频模式

视频模式三种传输方式

专有名词解释

Non-Burst Mode with Sync Pulses

使外设能够准确重建原始视频时序,包括同步脉冲宽度。精确的重建时序就是通过 DSI 传输后的数据,在对端可以精确的还原成 DPI 的时序。该模式时序图如下:

Non-Burst Mode with Sync Pulses 时序图

Non-Burst Mode with Sync Pulses 方式要准确重建原始视频时序,所以在时序图中可以看到 VSYNC,HSYNC,HBP,HFP 等信号。

Non-Burst Mode with Sync Events

Non-Burst Mode with Sync Events 时序图

与 Non-Burst Mode with Sync Pulses 方式类似,但不支持准确重建同步脉冲宽度。所以在该时序中并未见到 VSE,HSE 等信号。

Burst Mode

Burst Mode 时序图

该方式 RGB 像素时间会被压缩,从而可以在行扫描期间留下更多的时间用于低功耗模式或者将其他传输复用到 DSI 链路上。从时序图中可以看出,RGB 像素数据会尽快传输完成,然后进入 BLLP 模式节省功耗。

命令模式

命令模式主要针对有 frambuffer 的 LCD 屏进行操作的,只有在画面需要变化时,DSI host 端才发送数据给屏幕。

主要针对有 frambuffer 的 LCD 屏进行操作

在命令模式中有一个重要的 TE 控制信号,TE 控制信号的作用如下:

如 LCD 拥有自己的 timing 控制器和 GRAM,为了防止 Tearing Effect,必须主动通知 Host,在 MIPI DSI 定义一个标准的 TE trigger 消息,一旦收到这个消息,自动发送像素数据。

硬件原理图分析

iTOP-RK3568 开发板有引出 MIPI 接口,接口原理图如下:

iTOP-RK3568 MIPI 接口

  1. TP_RST_L_GPIO0_B6 是触摸复位引脚。
  2. TP_INT_L_GPIO3_A5 是触摸中断引脚。
  3. I2C1_SCL_TP 是 I2C1 SCL_TP 引脚。用于和触摸芯片进行 I2C 通信。I2C1_SDA_TP 是 I2C1_SDA 引脚。用于和触摸芯片进行 I2C 通信。
  4. LCD_EN_H_GPIO3_C6 是屏幕使能引脚
  5. LCD_RST_L_GPIO3_C7 是屏幕复位引脚
  6. LCD1_BL_PWM5 是 PWM 引脚,用于调整屏幕背光。
  7. MIPI_DSI_TX1_D3N、MIPI_DSI_TX1_D3P、MIPI_DSI_TX1_D2N、MIPI_DSI_TX1_D2P、MIPI_DSI_TX1_CLKN、MIPI_DSI_TX1_CLKP、MIPI_DSI_TX1_D1N、MIPI_DSI_TX1_D1P、MIPI_DSI_TX1_D0N、MIPI_DSI_TX1_D0P 是 MIPI1 接口引脚。直接一一对应连接到处理器的 MIPI1 接口上,MIPI 接口为 4lanes 接口。

J37 是跳线帽插座,防止接错屏幕导致烧坏屏幕和 CPU 使用,检查好硬件连接以后,需使用跳线帽连接电源。

适配步骤

设置 MIPI 显示通路

使用 MIPI 接口可以选择 VP0 或者 VP1,VP0 和 VP1 均支持 MIPI0 和 MIPI1,由于在开发板上 MIPI0 和 LVDS 接口复用并被用于 LVDS 接口,所以开发板上 MIPI 接口使用 MIPI1。开发板选择 VP1 输出 MIPI 信号,因为 VP0 可以支持的最大分辨率可达 4K,可以预留 HDMI 使用。

RK3568 VP 和各显示接口连接关系:

RK3568 VP 和各显示接口连接关系:

设置 VP1 作为 MIPI 显示通路之前需要先打开 VOP 节点。rk3568.dtsi 中定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
vop: vop@fe040000 {
compatible = "rockchip,rk3568-vop";
reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
reg-names = "regs", "gamma_lut";
rockchip,grf = <&grf>;
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
iommus = <&vop_mmu>;
power-domains = <&power RK3568_PD_VO>;
status = "disabled";

vop_out: ports {
#address-cells = <1>;
#size-cells = <0>;

vp0: port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;

vp0_out_dsi0: endpoint@0 {
reg = <0>;
remote-endpoint = <&dsi0_in_vp0>;
};

vp0_out_dsi1: endpoint@1 {
reg = <1>;
remote-endpoint = <&dsi1_in_vp0>;
};

vp0_out_edp: endpoint@2 {
reg = <2>;
remote-endpoint = <&edp_in_vp0>;
};

vp0_out_hdmi: endpoint@3 {
reg = <3>;
remote-endpoint = <&hdmi_in_vp0>;
};
};

vp1: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;

vp1_out_dsi0: endpoint@0 {
reg = <0>;
remote-endpoint = <&dsi0_in_vp1>;
};

vp1_out_dsi1: endpoint@1 {
reg = <1>;
remote-endpoint = <&dsi1_in_vp1>;
};

vp1_out_edp: endpoint@2 {
reg = <2>;
remote-endpoint = <&edp_in_vp1>;
};

vp1_out_hdmi: endpoint@3 {
reg = <3>;
remote-endpoint = <&hdmi_in_vp1>;
};

vp1_out_lvds: endpoint@4 {
reg = <4>;
remote-endpoint = <&lvds_in_vp1>;
};

vp1_out_lvds1: endpoint@5 {
reg = <5>;
remote-endpoint = <&lvds1_in_vp1>;
};
};

vp2: port@2 {
#address-cells = <1>;
#size-cells = <0>;

reg = <2>;

vp2_out_lvds: endpoint@0 {
reg = <0>;
remote-endpoint = <&lvds_in_vp2>;
};

vp2_out_rgb: endpoint@1 {
reg = <1>;
remote-endpoint = <&rgb_in_vp2>;
};

vp2_out_lvds1: endpoint@2 {
reg = <2>;
remote-endpoint = <&lvds1_in_vp2>;
};
};
};
};

打开 VOP 以后,接下来设置 MIPI1 接口使用 VP1 输出的显示通路。打开 rk3568.dtsi 设备树文件,找到 MIPI1 节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
dsi0: dsi@fe060000 {
compatible = "rockchip,rk3568-mipi-dsi";
reg = <0x0 0xfe060000 0x0 0x10000>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_DSITX_0>, <&cru HCLK_VO>;
clock-names = "pclk", "hclk";
resets = <&cru SRST_P_DSITX_0>;
reset-names = "apb";
phys = <&video_phy0>;
phy-names = "dphy";
power-domains = <&power RK3568_PD_VO>;
rockchip,grf = <&grf>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

dsi0_in: port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

dsi0_in_vp0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp0_out_dsi0>;
status = "disabled";
};

dsi0_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_dsi0>;
status = "disabled";
};
};
};
};

dsi1: dsi@fe070000 {
compatible = "rockchip,rk3568-mipi-dsi";
reg = <0x0 0xfe070000 0x0 0x10000>; // 设置寄存器地址范围:起始地址 0xfe070000,大小 0x10000。
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; // 配置中断:GIC SPI 中断号 69,高电平触发。
clocks = <&cru PCLK_DSITX_1>, <&cru HCLK_VO>; // 配置 pclk, hclk, hs_clk 时钟
clock-names = "pclk", "hclk";
resets = <&cru SRST_P_DSITX_1>; // 配置 abp 复位信号
reset-names = "apb";
phys = <&video_phy1>;
phy-names = "dphy";
power-domains = <&power RK3568_PD_VO>; // 配置 PD_VO 电源域
rockchip,grf = <&grf>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled"; // 禁用此节点,因为要使用 MIPI1 所以后面需要使能该节点

ports {
#address-cells = <1>;
#size-cells = <0>;

dsi1_in: port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

dsi1_in_vp0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp0_out_dsi1>;
status = "disabled"; // 使用 VP0 输出 MIPI 被禁止
};

dsi1_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_dsi1>;
status = "disabled"; // 使用 VP1 输出 MIPI 被禁止
};
};
};
};

compatible 属性值为 rockchip,rk3568-mipi-dsi,表示会使用 gpu/drm/rockchip/dw-mipi-dsi.c 这个驱动程序。

ports节点表示 MIPI 接口所对应的 VP 端口,dsi1_in_vp0 表示 MIPI1 接口连接到 VP0,dsi1_in_vp1 表示 MIPI1 接口连接到 VP1。

可以在 arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 设备树文件中添加以下代码来设置 MIPI 显示通路。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
&dsi1{
status = "okay";
};

&dsi1_in_vp0 {
status = "disabled";
};
&dsi1_in_vp1 {
status = "okay";
};

&video_phy1{
status = "okay";
};

video_phy1 节点在 rk3568.dtsi 设备树文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
video_phy1: phy@fe860000 {
// 兼容性定义,标识硬件平台及驱动
compatible = "rockchip,rk3568-dsi-dphy", "rockchip,rk3568-video-phy";
// 寄存器区域定义:
// - PHY1 物理层寄存器:0xfe860000-0xfe86ffff
// - DSI_TX_PHY1 主控制器寄存器:0xfe070000-0xfe07ffff
reg = <0x0 0xfe860000 0x0 0x10000>,
<0x0 0xfe070000 0x0 0x10000>;
reg-names = "phy", "host";
// 时钟源定义:
// - ref: PHY 参考时钟(MIPI DSIPHY1 参考时钟)
// - pclk_phy: PHY 外设总线时钟
// - pclk_host: DSI 主机控制器时钟
clocks = <&pmucru CLK_MIPIDSIPHY1_REF>,
<&cru PCLK_MIPIDSIPHY1>, <&cru PCLK_DSITX_1>;
clock-names = "ref", "pclk", "pclk_host";
#clock-cells = <0>;
// 复位控制信号
resets = <&cru SRST_P_MIPIDSIPHY1>;
reset-names = "apb";
// 电源域配置
power-domains = <&power RK3568_PD_VO>;
#phy-cells = <0>;
// 默认不启用,需在具体板级配置中开启
status = "disabled";
};

设置屏幕信息

arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 中添加以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
&dsi1 {
status = "disabled";
//rockchip,lane-rate = <1000>;
dsi1_panel: panel@0 {
status = "disabled";
compatible = "simple-panel-dsi";
power-supply = <&vcc3v3_lcd0_n>;
reg = <0>;
backlight = <&backlight1>;
reset-delay-ms = <60>;
enable-delay-ms = <60>;
prepare-delay-ms = <60>;
unprepare-delay-ms = <60>;
disable-delay-ms = <60>;
dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
dsi,format = <MIPI_DSI_FMT_RGB888>;
dsi,lanes = <4>;
panel-init-sequence = [
29 00 03 E0 AB BA
29 00 03 E1 BA AB
15 00 02 B0 00
29 00 05 B1 10 01 47 FF
29 00 07 B2 0C 0E 04 14 14 14
29 00 04 B3 56 D3 00
29 00 04 B4 22 30 04
15 00 02 B5 00
29 00 08 B6 B0 00 00 10 00 10 00
29 00 09 B7 0E 00 FF 08 08 FF FF 00
29 00 08 B8 05 12 29 49 48 00 00
29 00 27 B9 4D 42 38 31 33 27 2F 1B 36 35 35 53 41 49 3D 3D 33 29 26 4C 42 39 31 33 27 2F 1B 36 35 35 53 41 49 3D 3D 33 29 26
29 00 09 BA 00 00 00 44 24 00 00 00
29 00 04 BB 76 00 00
29 00 03 BC 00 00
29 00 06 BD FF 00 00 00 00
15 00 02 BE 00
29 00 11 C0 98 76 12 34 33 33 44 44 06 04 8A 04 0F 00 00 00
29 00 0B C1 53 94 02 85 06 04 8A 04 54 00
29 00 0D C2 37 09 08 89 08 10 22 21 44 BB 18 00
29 00 17 C3 9C 1D 1E 1F 10 12 0C 0E 05 24 24 24 24 24 24 07 24 24 24 24 24 24
29 00 17 C4 1C 1D 1E 1F 11 13 0D 0F 04 24 24 24 24 24 24 06 24 24 24 24 24 24
29 00 04 C5 E8 85 76
29 00 03 C6 20 20
29 00 17 C7 41 01 0D 11 09 15 19 4F 10 D7 CF 19 1B 1D 03 02 25 30 00 03 FF 00
29 00 07 C8 61 00 31 42 54 16
29 00 06 C9 A1 22 FF Cd 23
29 00 03 CA 4B 43
29 00 05 CC 2E 02 04 08
29 00 09 CD 0E 64 64 20 1E 6B 06 83
29 00 04 D0 27 10 80
29 00 05 D1 00 0D FF 0F
29 00 05 D2 E3 2B 38 00
29 00 0C D4 00 01 00 0E 04 44 08 10 00 07 00
15 00 02 D5 00
29 00 03 D6 00 00
29 00 05 D7 00 00 00 00
29 00 04 E4 08 55 03
29 00 09 E6 00 01 FF FF FF FF FF FF
29 00 04 E7 00 00 00
29 00 08 E8 D5 FF FF FF 00 00 00
15 00 02 E9 FF
29 00 06 F0 12 03 20 00 FF
29 00 1B F1 A6 C8 EA E6 E4 CC E4 BE F0 B2 AA C7 FF 66 98 E3 87 C8 99 C8 8C BE 96 91 8F FF
15 00 02 F3 03
29 00 1B F4 FF FE FC FA F8 F4 F0 E8 E0 D0 C0 A0 80 7F 5F 3F 2F 1F 17 0F 0B 07 05 03 01 00
29 00 1B F5 FF FE FC FA F8 F4 F0 E8 E0 D0 C0 A0 80 7F 5F 3F 2F 1F 17 0F 0B 07 05 03 01 00
29 00 1B F6 FF FE FC FA F8 F4 F0 E8 E0 D0 C0 A0 80 7F 5F 3F 2F 1F 17 0F 0B 07 05 03 01 00
29 00 08 F7 00 00 00 00 00 00 00
29 00 08 F8 00 00 00 00 00 00 00
29 00 08 F9 00 00 00 00 00 00 00
29 00 1A FA 00 84 12 21 48 48 21 12 84 69 69 5A A5 96 96 A5 5A B7 DE ED 7B 7B ED DE B7
29 00 18 FB 00 12 0F FF FF FF 00 38 40 08 70 0B 40 19 50 21 C0 27 60 2D 00 00 0F
29 00 03 E3 20 21
05 C8 01 11
05 14 01 29
];

panel-exit-sequence = [
05 05 01 28
05 78 01 10
];
disp_timings1: display-timings {
native-mode = <&dsi1_timing0>;
dsi1_timing0: timing0 {
clock-frequency = <60000000>;
hactive = <800>;
vactive = <1280>;
hfront-porch = <80>;
hsync-len = <20>;
hback-porch = <80>;
vfront-porch = <20>;
vsync-len = <4>;
vback-porch = <12>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
panel_in_dsi1: endpoint {
remote-endpoint = <&dsi1_out_panel>;
};
};
};
};

ports {
#address-cells = <1>;
#size-cells = <0>;

port@1 {
reg = <1>;
dsi1_out_panel: endpoint {
remote-endpoint = <&panel_in_dsi1>;
};
};
};

};

第 2 行 status 属性值为 disabled,表示 dsi1 节点默认为关闭状态。在设置 MIPI 显示通路章节中已经将 dsi1 节点打开。

第 3 行 rockchip,lane-rate 属性只有在使用 Dual-link 模式时才会涉及。用于指定数据 lane 的速率,单位为 mbps/lane。

第 4 到 109 行用于设置 MIPI 屏幕信息,其中:

第 5 行 status 属性值为 disabled,表示 dsi1_panel 节点默认为关闭状态。

第 7 行 reg 属性值为 0,表示 virtual channel 通道 0。一般情况下不会涉及 virtual channel,保持默认值 0 即可。

第 8 到 13 行属性在 RGB 屏幕移植已经解释过,这里不在赘述。

第 14 行 dsi,flags 属性表示模式。其中:

  • 属性值为 MIPI_DSI_MODE_VIDEO,MIPI_DSI_MODE_VIDEO_BURST 表示 Video Burst Mode。
  • 属性值为 MIPI_DSI_MODE_LPM 表示默认在 LP 模式下发送初始化序列。
  • 属性值为 MIPI_DSI_MODE_EOT_PACKET 表示关闭 EOTP 特性。

第 16 行 dsi,format 属性表示像素格式。属性值 MIPI_DSI_FMT_RGB888 表示使用 RGB88 像素格式。

第 17 行 dsi,lanes 属性表示通道数。属性值范围为 1 到 8,大于 4 表示为 Dual-channel MIPI-DSI 屏幕。这里使用迅为 4lanes 的 MIPI 屏幕,所以属性值为 4。

第 18 到 86 行 panel-init-sequence 属性表示 MIPI 屏的上电初始化序列。

第 88 到 91 行 panel-exit-sequence 属性表示 MIPI 屏的下电初始化序列。上电和下电初始序列填写比较重要,单独使用一个篇幅讲解,请参考 MIPI 初始化序列章节。

第 111 到 134 行设置屏幕的 ports 节点。

因为 dsi1_panel 节点默认是禁止的,所以还需将 dsi1_panel 节点打开,在 arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 设备树文件中添加以下代码:

1
2
3
4
&dsi1_panel
{
status = "okay";
};

MIPI 初始化序列

当我们拿到一款 MIPI 屏幕时,厂家会给这样的一串参数,以迅为 7 寸 MIPI 屏幕为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
SSD_SEND(0x01,0xE0,0xAB,0xBA);
SSD_SEND(0x01,0xE1,0xBA,0xAB);
SSD_SEND(0x01,0xB1,0x10,0x01,0x47,0xFF);
SSD_SEND(0x01,0xB2,0x0C,0x14,0x04,0x50,0x50,0x14);
SSD_SEND(0x01,0xB3,0x56,0xD3,0x00);
SSD_SEND(0x01,0xB4,0x33,0x30,0x04);
SSD_SEND(0x01,0xB6,0x0B,0x00,0x00,0x10,0x00,0x10,0x00);
SSD_SEND(0x01,0xB8,0x05,0x12,0x29,0x49,0x48,0x00,0x00);
SSD_SEND(0x01,0xB9,0x4C,0x44,0x3C,0x33,0x33,0x26,0x2F,0x1B,0x35,0x35,0x35,0x53,0x41,0x48,0x3D,0x38,0x2
B,0x19,0x06,0x4C,0x44,0x3C,0x33,0x33,0x26,0x2F,0x1B,0x35,0x35,0x35,0x53,0x41,0x48,0x3D,0x38,0x2B,0x19,0x
06);
SSD_SEND(0x01,0xC0,0x98,0x76,0x12,0x34,0x33,0x33,0x44,0x44,0x06,0x04,0x8A,0x04,0x0F,0x00,0x00,0x00
);
SSD_SEND(0x01,0xC1,0x53,0x94,0x02,0x85,0x06,0x04,0x8A,0x04,0x54,0x00);
SSD_SEND(0x01,0xC2,0x37,0x09,0x08,0x89,0x08,0x10,0x22,0x21,0x44,0xBB,0x18,0x00);
SSD_SEND(0x01,0xC3,0x9C,0x1D,0x1E,0x1F,0x10,0x12,0x0C,0x0E,0x05,0x24,0x24,0x24,0x24,0x24,0x24,0x07
,0x24,0x24,0x24,0x24,0x24,0x24);
SSD_SEND(0x01,0xC4,0x1C,0x1D,0x1E,0x1F,0x11,0x13,0x0D,0x0F,0x04,0x24,0x24,0x24,0x24,0x24,0x24,0x06
,0x24,0x24,0x24,0x24,0x24,0x24);
SSD_SEND(0x01,0xC5,0xE8,0x85,0x77);
SSD_SEND(0x01,0xC6,0x28,0x28);
SSD_SEND(0x01,0xC8,0x21,0x00,0x31,0x42,0x54,0x16);
SSD_SEND(0x01,0xCA,0x4B,0x43);
SSD_SEND(0x01,0xCD,0x0E,0x64,0x64,0x20,0x1E,0x6B,0x06,0x83);
SSD_SEND(0x01,0xD2,0xE3,0x2B,0x38,0x00);
SSD_SEND(0x01,0xD4,0x00,0x01,0x00,0x0E,0x04,0x44,0x08,0x10,0x00,0x00,0x00);
SSD_SEND(0x01,0xE6,0x80,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
SSD_SEND(0x01,0xF0,0x12,0x03,0x20,0x00,0xFF);
SSD_SEND(0x01,0xF3,0x00);

DCS_Short_Write_NP(0x11);
Delay(600);//delay 120ms
DCS_Short_Write_NP(0x29);
Delay(100);//delay 20ms

供应商给的这段代码驱动并不认识,我们得转换成驱动认识的代码格式,这个驱动认识的代码格式就是 MIPI 初始化序列,也就是 panel-init-sequencepanel-exit-sequence 属性对应的属性值。

panel-init-sequence 属性中第一行,也就是设备树第 19 行数据 29 00 03 E0 AB BA。我们对 29 00 03 E0 AB BA 数据进行解析。

例子

从解析中可以看出,数据 E0 AB BA 是给 MIPI 发送的初始化序列。对应屏幕供应商给的 SSD_SEND(0x01,0xE0,0xAB,0xBA)这句代码。

0x29 是 Generic Long Write 指令。Generic Write 指令还有:

Data Type (hex) Data Type (binary) Description Packet Size
0x03 00 0011 Generic Short WRITE, no parameters Short
0x13 01 0011 Generic Short WRITE, 1 parameter Short
0x23 10 0011 Generic Short WRITE, 2 parameters Short
0x29 10 1001 Generic Long Write Long

如果 n < 3,将以 Short Packet 的形式对 Payload 进行打包。n 为参数数量。其中:

  • n = 0,表示没有参数, 指令选择 0x03。
  • n = 1,表示 1 个参数, 指令选择 0x13。
  • n =2,表示 2 个参数,指令选择 0x23。
  • n >= 3,将以 Long Packet 的形式进行对 Payload 打包,表示 n 个 parameters,指令选择 0x29。

除了 Generic Write 指令,还有 DCS Write 指令。

Data Type (hex) Data Type (binary) Description Packet Size
0x05 00 0101 DCS Short WRITE, no parameters Short
0x15 01 0101 DCS Short WRITE, 1 parameter Short
0x39 11 1001 DCS Long Write/write_LUT Command Packet Long

如果 n < 2,n 为参数数量。将以 Short Packet 的形式对要发送的数据进行打包。

  • n = 0,表示不带参数,指令选择 0x05。
  • n = 1,表示带一个参数,指令选择 0x15。
  • n >= 2,将以 Long Packet 的形式对要发送的数据进行打包。此时发送 dcs 指令,带 n 个参数,指令选择 0x39。

panel-init-sequencepanel-exit-sequence 属性对应的其他初始化序列分析方法与本例一致,大家可自行分析。

设置背光和触摸

arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 中添加以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
&pwm5{
status = "okay";
};

&backlight1{
pwms = <&pwm5 0 25000 0>;
status = "okay";
};

&ft5x061
{
status = "okay";
};

设置屏幕 LOGO

arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts 中添加以下代码:

1
2
3
4
&route_dsi1{
status = "okay";
connect = <&vp1_out_dsi1>;
};

HDMI 屏幕移植

HDMI 接口介绍

诞生背景

1998 年,英特尔、IBM、惠普、富士通、康柏等计算机行业巨头联合推出 DVI(Digital Visual Interface)接口,DVI 接口基于 TMDS(Transition Minimized Differential Signaling,最小化传输差分信号)技术来传输数字信号。通过编码算法把 8bit 数据(R、G、B 中的每路基色信号)编码为 10bit 数据(包含行场同步信息、时钟信息、数据 DE、纠错等),采用差分信号传输数据。

DVI 接口在 PC、DVD、高清晰电视(HDTV)、高清晰投影仪等设备上有广泛的应用。最高可以支持 2K@60Hz 和 1080P@120Hz 分辨率。然而,随着 21 世纪初高清电视(HDTV)的普及,消费者对影音一体化的需求激增。电视厂商(如索尼、松下、日立等)认为 DVI 无法满足以下需求:

  1. 电视与家庭影院设备趋向轻薄,需更紧凑的接口从而实现设备小型化,而 DVI 接口体积大,插拔不便,难以适配轻薄化设备。
  2. 数字音频与视频需通过单一接口传输实现影音一体化,而 DVI 接口功能单一,仅支持视频传输,需额外线缆传输音频。
  3. 高清内容盗版问题严重加密技术需求日益增多,而 DVI 接口未集成内容加密技术(如 HDCP)。
  4. 需支持更高带宽以支持 4K、8K 等新兴分辨率,DVI 接口带宽有限,难以满足日益增长的分辨率需求。

2002 年,索尼、松下、日立、东芝、飞利浦等电视厂商联合成立 HDMI 联盟,目标是设计一种取代 DVI 的下一代接口,即 HDMI 接口,HDMI 接口全称为 High Definition Multimedia Interface,也就是高清多媒体接口。2003 年,HDMI 1.0 标准正式发布,核心特性包括:

  1. 高带宽:5Gbps 传输速率,支持 1080P@60Hz 和无压缩 8 声道音频。
  2. 接口小型化:体积比 DVI 减少约 50%,插拔更便捷。
  3. 影音融合:单线传输数字视频与音频信号。
  4. 兼容性:通过转接器向下兼容 DVI 接口。
  5. 内容保护:集成 HDCP 加密技术,防止非法复制。

HDMI 的发展历程

HDMI 1.2(2005):支持显示器色深扩展(8/10/12bit),兼容 SACD 音频。

HDMI 1.3(2006):带宽提升至 10.2Gbps,引入深色技术(Deep Color)、xvYCC 广色域。

HDMI 1.4(2009):带宽 10.2Gbps,新增功能:支持 4K@30Hz、1080P@144Hz、3D 视频。增加以太网通道(HEC)和音频回传通道(ARC)。

HDMI 2.0a/b(2013-2016):带宽 18Gbps,支持 4K@60Hz、1080P@240Hz,引入静态 HDR(高动态范围)。

HDMI 2.1(2017):带宽跃升至 48Gbps,核心升级:分辨率与刷新率:8K@60Hz、4K@120Hz(无压缩),支持动态 HDR(Dolby Vision);游戏优化:可变刷新率(VRR)、自动低延迟模式(ALLM);增强音频:eARC(增强音频回传通道)。

HDMI 接口引脚定义

HDMI 接口有 A 到 E 五种接口。

  1. HDMI-A 接口又叫做标准接口,也是使用最广泛的接口。

HDMI-A 接口

引脚定义:

引脚标号 功能 引脚标号 功能
1 TMDS 数据 2+ 10 TMDS 时钟 +
2 TMDS 数据屏蔽 11 TMDS 时钟屏蔽
3 TMDS 数据 2- 12 TMDS 时钟 -
4 TMDS 数据 1+ 13 CEC
5 TMDS 数据 1 屏蔽 14 保留
6 TMDS 数据 1- 15 SCL(DDC CLOCK)
7 TMDS 数据 0+ 16 SDA(DDC DATA)
8 TMDS 数据 0 屏蔽 17 GND
9 TMDS 数据 0- 18 +5V 电源
19 HPD 热插拔检测
  1. HDMI-B 接口在日常使用中基本看不到。HDMI-B 接口的数据传输能力比 HDMI-A 快近 2 倍,一般用在比较专业的场景。

HDMI-B 接口

  1. HDMI-C 又叫做 Mini HDMI、迷你 HDMI 接口,尺寸比 HDMI-A 小了近三分之一,主要用在小型设备中,比如游戏机,数码相机等。

HDMI-C 接口

引脚定义:

引脚标号 功能 引脚标号 功能
1 TMDS 数据 2 屏蔽 10 TMDS 时钟屏蔽
2 TMDS 数据 2+ 11 TMDS 时钟 +
3 TMDS 数据 2- 12 TMDS 时钟 -
4 TMDS 数据 1 屏蔽 13 CEC/DDC Ground
5 TMDS 数据 1+ 14 CEC
6 TMDS 数据 1- 15 SCL(DDC CLOCK)
7 TMDS 数据 0 屏蔽 16 SDA(DDC DATA)
8 TMDS 数据 0+ 17 HEC+
9 TMDS 数据 0- 18 +5V 电源
19 HPD 热插拔检测 / HEC−
  1. HDMI-D 接口又叫做 Micro HDMI、微型 HDMI 接口。Micro HDMI 也比较小,主要应用在小型移动设备上,比如平板电脑,便携车载设备等。

HDMI-D 接口

引脚定义:

  1. HDMI-E 接口主要用于车载系统,由于车内环境不稳定,HDMI-E 接口在物理接口上采用机械式锁定设计,保证接触的可靠性。

HDMI-E 接口

引脚标号 功能 引脚标号 功能
1 HPD 热插拔检测 / HEC− 10 TMDS 数据 0 屏蔽
2 Utility/HEAC+ 11 TMDS 数据 0−
3 TMDS 数据 2+ 12 TMDS 时钟 +
4 TMDS 数据 2 屏蔽 13 TMDS 时钟屏蔽
5 TMDS 数据 2− 14 TMDS 时钟−
6 TMDS 数据 1+ 15 CEC
7 TMDS 数据 1 屏蔽 16 DDC/CEC/HEAC
8 TMDS 数据 1− 17 SCL (DDC CLOCK)
9 TMDS 数据 0+ 18 SDA (DDC DATA)
19 +5V 电源

RK3568 HDMI 接口

RK3568 处理器支持 1 路 HDMI 接口,可以支持 1.4a 和 2.0a 俩个版本。最高可支持 4K@60Hz 分辨率。

RK3568 处理器的 HDMI 接口

带宽计算

在选择 HDMI 屏幕时,如何确定处理器是不是能支持该分辨率的屏幕呢?这里就涉及到了 HDMI 带宽计算。以 RK3568 处理器为例。

RK3568 处理器最高支持 HDMI2.0,在 HDMI2.0 中 TMDS 时钟为 600Mhz,所以在 HDMI2.0 下带宽为:600000000x10x3=18Gbps。

有效带宽为 18x(10/8)=14.4Gbps。

为什么有效带宽要乘以 10/8 呢,因为在 HDMI 传输中会将 8bit 转换成 10bit。然后我们在计算 HDMI 屏幕所需要的带宽,如果 HDMI 屏幕所需要的带宽小于处理器的 HDMI 带宽,则该屏幕就可以支持。

HDMI 屏幕带宽计算公式:Htotal x Vtotal x 刷新率 x 编码方式 x 位深度

其中,Htotal 的值等于 Hsync + Hfront + Hactive + Hback,Vtotal 的值等于 Vsync + Vfront + Vactive + Vback。Htotal x Vtotal 表示每张画面的像素点。

每张画面的像素点乘以显示器的刷新率就是显示器一秒内要处理的像素量,即 Htotal x Vtotal x 刷新率。编码方式如果是 yuv444,则编码方式值为 1,编码方式如果是 yuv422,则编码方式值为 2/3,编码方式如果是 yuv420,则编码方式值为 1/2。

举例:一款 3920(Htotal)x2222(Vtotal)@60hz,采用 yuv444 编码,位深度为 8 的屏幕需要的带宽为 3920x2222x60x1x8x3 约等于 12.543Gbps。

如果不想计算,也可以通过查表来判断,通过下面的表格可知,如 HDMI2.0 版本最大支持 4K@120Hz 分辨率。

HDMI 和速率

TMDS 差分信号介绍

前面我们说 DVI 接口使用的是 TMDS 差分信号,而 HDMI 接口是为了取代 DVI 接口而开发的。

实际上 HDMI 源于 DVI 接口技术,HDMI 接口也是以美国晶像公司的 TMDS 信号传输技术为核心。HDMI 在引脚上和 DVI 兼容,只是采用了不同的封装。所以 HDMI 接口和 DVI 接口能够通过转接头相互转换。从原理上讲,HDMI 向下兼容 DVI。

所以本章节重点介绍一下 TMDS 差分信号。我们从 HDMI 规范中的连接框架图入手。

HDMI 规范中的连接框架图

从图中可以看出,TMDS 传输分为发送端 source 和接收端 sink 俩部分。TMDS 链路包括 3个传输数据的通道(Channel0,1,2)和 1 个传输时钟信号的通道(Clock Channel)。

以左侧发送端 source 为例,一共有 3 个数据通道,每个数据通道采用并行传输,宽度为 8 bit。其中:

  • D[7:0]:表示 8bit 的实际图像数据。
  • D[1:0]:在通道 0 中表示 HSYNC 和 VSYNC 信号,在通道 1 和通道 2 中表示 CTL0~CTL3 这 4 个控制信号。
  • D[3:0]: 用来表示额外的一些辅助数据,比如音频数据等。

为什么这 8bit 的数据 D[7:0]已经传输了图像数据,怎么 D[1:0]又传输了其他信号呢?

HDMI 规范中的数据传输周期概览图

在 HDMI 传输概览图中传输分成了 3 个阶段,这三个传输阶段分别是:深灰色为视频数据周期,深蓝色为数据岛周期,浅灰色为控制周期。

TMDS Periods

  1. Control Period(控制周期)

当不需要传输视频、音频或辅助数据时,使用控制周期。任何两个非控制周期之间必须有一个控制周期,采用 CTL encoding 编码,将 2bits 数据转换成 10bits 数据

在每个视频数据周期(Video Data Period)或数据岛周期(Data Island Period)之前,会通过控制周期发送前导码(Preamble)。前导码是由八个相同的控制字符组成的序列,用于指示接下来的数据周期是视频数据周期还是数据岛周期。

控制周期

CTL0、CTL1、CTL2 和 CTL3 的值指示了后续数据周期的类型,其余的控制信号(HSYNC 和 VSYNC)也可能会有所变化。

CTL0、CTL1、CTL2 和 CTL3 的值指示了后续数据周期的类型

  1. Data Island Period(数据岛周期)

在此阶段传输音频和其他额外数据,采用 TERC4 encoding 编码,将 4bits 数据转换成 10 bits 数据。数据岛周期包括三个部分:前保护边界、数据头和数据包以及后保护边界。

Data Island Period(数据岛周期)

  1. Video Data Period(视频数据周期)

在此阶段传输实际的图像数据,采用 video data encoding 编码,将 8bits 数据转换成 10bits 数据。视频数据周期有前保护边界,没有后保护边界

Video Data Period(视频数据周期)

由此可见,D[7:0]并不是同时传输这些数据,而是分阶段进行传输。

TMDS 是差分信号,LVDS 也是差分信号,他们有什么区别呢?

  • LVDS 差分信号工作原理见 LVDS 接口介绍章节。

  • TMDS 差分信号使用 2 根差分线来传输信号,信号 0 和 1 由两个引脚的电压差来决定:

    • 当 TMDS 差分线+为高电平,
    • 差分线-为低电平的时候表示 1;
    • 差分线+为低电平, 差分线-为高电平的时候为 0。
    • TMDS 接收端通过判断+和-的电压差来确定发送过来的是 1 还是 0。

EDID 介绍

不同种类,不同品牌的显示器分辨率和时序都不同,HDMI 接口又要做到兼容,如果处理器输出一个固定的分辨率和时序参数就不能很好的驱动所有显示器。

EDID 全称是 Extended Display Identification Data,即外部显示设备标识数据。在 EDID 中包含显示器相关参数,如分辨率,时序信息。还有厂商信息,产品 ID,生产日期等信息。如下图 EDID 结构图中的 08h 地址,占 2 个字节大小,用来表示生产厂家名字,采用 ISA 3 字符 ID 码。其他地址同理,可以自行阅读 EDID 结构图。

HDMI 的 EDID 的长度一般是 256 字节,分成 2 个 Block,分别是 Block0(对应下图 EDID 结构图的 00h-36h)和 Block1(对应下图 EDID 结构图的 36h-7fh)。其中 Block 0 是必须要有的,而 Block 1 是可选的。

EDID v1.4 版本结构:

Address Bytes Description Format
00h 8 Header: = (00 FF FF FF FF FF FF 00h) See Section 3.3
08h 10 Vendor & Product Identification: See Section 3.4
08h 2 ID Manufacturer Name ISA 3-character ID Code
0Ah 2 ID Product Code Vendor assigned code
0Ch 4 ID Serial Number 32-bit serial number
10h 1 Week of Manufacture Week number or Model Year Flag
11h 1 Year of Manufacture or Model Year Manufacture Year or Model Year
12h 2 EDID Structure Version & Revision: See Section 3.5
12h 1 Version Number: = 01h Binary
13h 1 Revision Number: = 04h Binary
14h 5 Basic Display Parameters & Features: See Section 3.6
14h 1 Video Input Definition See Section 3.6.1
15h 1 Horizontal Screen Size or Aspect Ratio Listed in cm. → Aspect Ratio — Landscape
16h 1 Vertical Screen Size or Aspect Ratio Listed in cm. → Aspect Ratio — Portrait
17h 1 Display Transfer Characteristic (Gamma) Binary — Factory Default Value
18h 1 Feature Support See Section 3.6.4
19h 10 Color Characteristics: See Section 3.7
19h 1 Red/Green: Low Order Bits Rx0 Rx1 Ry0 Ry1 Gx0 Gx1 Gy0 Gy1
1Ah 1 Blue/White: Low Order Bits Bx0 Bx1 By0 By1 Wx0 Wx1 Wy0 Wy1
1Bh 1 Red-x: High Order Bits Red-x Bits 9 → 2
1Ch 1 Red-y: High Order Bits Red-y Bits 9 → 2
1Dh 1 Green-x: High Order Bits Green-x Bits 9 → 2
1Eh 1 Green-y: High Order Bits Green-y Bits 9 → 2
1Fh 1 Blue-x: High Order Bits Blue-x Bits 9 → 2
20h 1 Blue-y: High Order Bits Blue-y Bits 9 → 2
21h 1 White-x: High Order Bits White-x Bits 9 → 2
22h 1 White-y: High Order Bits White-y Bits 9 → 2
23h 3 Established Timings See Section 3.8
23h 1 Established Timings I
24h 1 Established Timings II
25h 1 Manufacturer’s Reserved Timings
26h 16 Standard Timings: Identification 1 → 8 See Section 3.9
36h 72 18 Byte Data Blocks See Section 3.10
36h 18 Preferred Timing Mode
48h 18 Detailed Timing #2 or Display Descriptor
5Ah 18 Detailed Timing #3 or Display Descriptor
6Ch 18 Detailed Timing #4 or Display Descriptor
7Eh 1 Extension Block Count N Number of (optional) 128-byte EDID EXTENSION blocks to follow – if Block Maps are used then 00h ≤ N ≤ FEh and FFh is invalid.Maps are used then 254 is the maximum value of ‘N’. If Block Maps are not used then 255 is the maximum value of ‘N’. 00h ≤ N ≤ FFh.
7Fh 1 Checksum C 00h ≤ C ≤ FFhThe 1-byte sum of all 128 bytes in this EDID block shall equal zero

这样通过读取 EDID 信息就可以输出合适的屏幕参数从而兼容不同厂家,不同品牌的 HDMI屏幕。在有些资料中,可能还会见到 E-EDID,即 Enhanced Extended Display Identification Data,E-EDID 与 EDID 只是该技术发展过程中的不同版本,E-EDID 向前兼容 EDID,所以可以不做区分。

目前 DRM 驱动已经支持了绝大部分分辨率时序,但一些特殊场景下,可能存在一些特殊分辨率不支持。可以在drivers\gpu\drm\drm_edid.c 中的 drm_dmt_modes 的末尾新增屏幕信息。

1
2
3
{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 556188, 4096, 4104,
4136, 4176, 0, 2160, 2208, 2216, 2222, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
参数 说明
“4096x2160” mode name,为分辨率的 hdisplay × vdisplay
DRM_MODE_TYPE_DRIVER mode type,配置为 DRM_MODE_TYPE_DRIVER
556188 像素时钟(单位:kHz)
4096 行有效像素(hdisplay)
4104 行同步起始像素(hsync_start)
4136 行同步结束像素(hsync_end)
4176 一行总像素(htotal)
0 hskew,通常为 0
2160 帧有效行(vdisplay)
2208 帧同步开始行(vsync_start)
2216 帧同步结束行(vsync_end)
2222 一帧总行数(vtotal)
0 vscan,通常为 0
vrefresh 显示设备帧率
DRM_MODE_FLAG_PHSYNC hsync 和 vsync 极性,flags 的定义如下:DRM_MODE_FLAG_PHSYNC (1<<0)DRM_MODE_FLAG_NHSYNC (1<<1)DRM_MODE_FLAG_PVSYNC (1<<2)DRM_MODE_FLAG_NVSYNC (1<<3)DRM_MODE_FLAG_INTERLACE (1<<4)

硬件原理图分析

iTOP-RK3568 开发板有引出 HDMI 接口,接口原理图如下:

iTOP-RK3568 HDMI 接口

  • HDMI_TX2P_PORT/HDMI_TX2N_PORT、HDMI_TX1P_PORT/HDMI_TX1N_PORT、HDMI_TX0P_PORT/HDMI_TX0N_PORT、HDMI_TXCLKP_PORT/HDMI_TXCLKN_PORT 为 3 对数据引脚和 1 对时钟引脚。
  • HDMI_TX_CEC_PORT,CEC 引脚。
  • HDMI_TXDDC_SCL_PORT/HDMI_TXDDC_SDA_PORT。DDC 通道引脚,使用 I2C 进行通信,主要用于读取 EDID 信息。
  • HDMI_TX_HPD_PORT 热插拔检测引脚。

适配步骤

rk3568.dtsi中hdmi节点如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
hdmi: hdmi@fe0a0000 {
compatible = "rockchip,rk3568-dw-hdmi";
reg = <0x0 0xfe0a0000 0x0 0x20000>;
interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_HDMI_HOST>,
<&cru CLK_HDMI_SFR>,
<&cru CLK_HDMI_CEC>,
<&pmucru PLL_HPLL>,
<&cru HCLK_VOP>;
clock-names = "iahb", "isfr", "cec", "ref", "hclk";
power-domains = <&power RK3568_PD_VO>;
reg-io-width = <4>;
rockchip,grf = <&grf>;
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

hdmi_in_vp0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp0_out_hdmi>;
status = "disabled";
};

hdmi_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_hdmi>;
status = "disabled";
};
};
};
};

compatible 属性值为 rockchip,rk3568-dw-hdmi,表示会使用 gpu/drm/rockchip/dw_hdmi-rockchip.c 这个驱动程序。

pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;:使用 pinctrl 设置 scl,sda,cec 引脚复用。

status 属性值为 disabled,表示禁用此节点,因为要使用 HDMI 所以后面需要使能该节点。

ports节点表示 HDMI 接口所对应的 VP 端口,hdmi_in_vp0 表示 HDMI 接口连接到 VP0,hdmi_in_vp1 表示 HDMI 接口连接到 VP1。status 属性值为 disabled 表示使用 VP0/1 输出 HDMI 被禁止

arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#if  defined(LCD_TYPE_HDMI_VP0)
&hdmi {
status = "okay";
rockchip,phy-table =
<92812500 0x8009 0x0000 0x0270>,
<165000000 0x800b 0x0000 0x026d>,
<185625000 0x800b 0x0000 0x01ed>,
<297000000 0x800b 0x0000 0x01ad>,
<594000000 0x8029 0x0000 0x0088>,
<000000000 0x0000 0x0000 0x0000>;
};
&hdmi_in_vp0 {
status = "okay";
};
&hdmi_in_vp1 {
status = "disabled";
};
&hdmi_sound {
status = "okay";
};
&route_hdmi {
status = "okay";
connect = <&vp0_out_hdmi>;
};
#endif

#if defined(LCD_TYPE_HDMI_VP1)
&hdmi {
status = "okay";
rockchip,phy-table =
<92812500 0x8009 0x0000 0x0270>,
<165000000 0x800b 0x0000 0x026d>,
<185625000 0x800b 0x0000 0x01ed>,
<297000000 0x800b 0x0000 0x01ad>,
<594000000 0x8029 0x0000 0x0088>,
<000000000 0x0000 0x0000 0x0000>;
};
&hdmi_in_vp0 {
status = "disabled";
};
&hdmi_in_vp1 {
status = "okay";
};
&hdmi_sound {
status = "okay";
};
&route_hdmi {
status = "okay";
connect = <&vp1_out_hdmi>;
};
#endif

eDP 屏幕移植

eDP 接口介绍

eDP 全称是 Embedded DisplayPort,即嵌入式显示接口,由视频电子标准协会(VESA)创始。eDP 协议是针对 DP(Display Port)应用在嵌入式方向架构和协议的拓展,所以 eDP 协议完全兼容 DP 协议。已广泛应用于笔记本电脑、平板电脑等领域。

RK3568 支持 1 路 eDP 接口。特性如下:

  1. 支持 1 个 eDP 1.3 接口
  2. 最多 4 条物理通道,每条通道支持 2.7 Gbps
  3. 支持 面板自刷新(Panel Self Refresh, PSR)
  4. 最大支持 2560x1600 @ 60Hz 分辨率
  5. 支持 RGB 格式(最高 10 位色深)

iTOP-RK3568 开发板将引出 1 路 eDP 接口,原理图如下:

iTOP-RK3568 开发板将引出 1 路 eDP 接口

  1. EDP_TX_D0N/EDP_TX_D0P、EDP_TX_D1N/EDP_TX_D1P、EDP_TX_D2N/EDP_TX_D2P、EDP_TX_D3N/EDP_TX_D3P。由 4 对差分线组成,用来传输音视频数据。需要注意的是,具体 LCD 屏幕需要几对差分线就使用几对差分线,需要 2 对就接 2 对,需要 4 对就接 4 对。
  2. EDPAUXN/EDPAUXP 辅助通道。
  3. EDP_HPDIN_M1 热插拔引脚,原理图中没有使用。也就是说此引脚是可选的。
  4. I2C1_SCL_TP、I2C1_SDA_TP、TP_INT_L_GPIO3_A5、TP_RST_L_GPIO0_B6,触摸 I2C 通信,中断,复位引脚。
  5. LCD0_BL_PWM4 屏幕背光引脚。

适配步骤

rk3568.dtsi中 edp 节点如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
edp: edp@fe0c0000 {
compatible = "rockchip,rk3568-edp";
reg = <0x0 0xfe0c0000 0x0 0x10000>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&pmucru XIN_OSC0_EDPPHY_G>, <&cru PCLK_EDP_CTRL>,
<&cru CLK_EDP_200M>, <&cru HCLK_VO>;
clock-names = "dp", "pclk", "spdif", "hclk";
resets = <&cru SRST_EDP_24M>, <&cru SRST_P_EDP_CTRL>;
reset-names = "dp", "apb";
phys = <&edp_phy>;
phy-names = "dp";
power-domains = <&power RK3568_PD_VO>;
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

edp_in: port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

edp_in_vp0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp0_out_edp>;
status = "disabled";
};

edp_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_edp>;
status = "disabled";
};
};
};
};

compatible 属性值为 rockchip,rk3568-edp,表示会使用 gpu/drm/rockchip/analogix_dp-rockchip.c 这个驱动程序。

phys = <&edp_phy>;使用了 edp_phy,所以我们需要使能 edp_phy 节点。

status 属性值为 disabled,表示 eDP 节点被禁用,所以我们需要使能 eDP 节点。

ports 节点表示 eDP 接口所对应的 VP 端口。edp_in_vp0 表示 eDP 接口连接到 VP0,edp_in_vp1 表示 eDP 接口连接到 VP1,status 属性值为 disabled 表示输出 eDP 被禁止。

arch/arm64/boot/dts/rockchip/topeet-screen-lcds.dts如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#if defined(LCD_TYPE_EDP_VGA)
&edp {
hpd-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;
status = "okay";
};

&edp_phy {
status = "okay";
};

&edp_in_vp0 {
status = "okay";
};

&edp_in_vp1 {
status = "disabled";
};
&route_edp {
status = "okay";
connect = <&vp0_out_edp>;
};

#endif

VGA 屏幕移植

VGA 接口介绍

VGA 全称是 Video Graphice Array,即视频图像阵列。VGA 是一种使用模拟信号进行视频传输的协议,于 1987 年由 IBM 公司推出。起初因分辨率高,显示速度快,颜色丰富在台式电脑应用中非常普遍。但是 VGA 接口体积较大,现在便携笔记本电脑越来越普及,所以在追求轻薄笔记本领域已经逐渐被淘汰。

VGA 接口有公头和母头之分,两者图像传输时,会使用的是 VGA 图像传输标准。

VGA 接口

引脚编号 Name 方向 功能描述
1 RED 红色视频信号
2 GREEN 绿色视频信号
3 BLUE 蓝色视频信号
4 RES 保留
5 GND 地线
6 RGND 红色地线
7 GGND 绿色地线
8 BGND 蓝色地线
9 +5V +5V 直流电源
10 SGND 同步地线
11 ID0 显示器 ID 位 0(可选)
12 SDA DDC 串行数据线
13 HSYNC or CSYNC 水平同步信号(或复合同步信号)
14 VSYNC 垂直同步信号
15 SCL DDC 数据时钟线

RK3568 处理器本身并没有 VGA 接口,iTOP-RK3568 开发板的 VGA 接口是使用 eDP 接口转换得到的。

硬件原理图分析

topeet RK3568 VGA

eDP 转 VGA 接口原理图非常简单,使用一颗 RTD2166 转换芯片。转换芯片的输入是 eDP 信号。经过转换芯片以后输出 VGA 信号。

其中 EDP_TX_D0P/EDP_TX_D0N、EDP_TX_D1P/EDP_TX_D1N、EDP_TX_AUXP/EDP_TX_AUXN。2 对差分线用来传输音视频数据。EDPAUXN/EDPAUXP 是辅助通道。VGA_HPDIN_GPIO0_C0 是热插拔引脚。I2C5_SDA_M0/I2C5_SCL_M0 是转换芯片控制引脚。

VGA_R、VGA_G、VGA_B、VGA_HSYNC、VGA_VSYNC、VGA_DDC_SDA、VGA_DDC_SCL 是转换芯片输出引脚,也就是转换得到的 VGA 信号,连接到 VGA 座子即可。

适配步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#if defined(LCD_TYPE_EDP_VGA)
&edp {
hpd-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;
status = "okay";
};

&edp_phy {
status = "okay";
};

&edp_in_vp0 {
status = "okay";
};

&edp_in_vp1 {
status = "disabled";
};
&route_edp {
status = "okay";
connect = <&vp0_out_edp>;
};

#endif