SPI LCD 显示驱动
SPI LCD 一般用于小分辨率的 SPI 屏显示,该驱动支持使用 SPI 协议软件控制 DC 方式驱动 SPI 屏幕,另外也对支持 MIPI DBI 接口芯片支持硬件控制 DC,3 线 9Bit 模式。SPI LCD 一般遵循 MIPI DBI 协议。SPI LCD 驱动架构如下:

部分芯片平台的 SPI 接口支持 MIPI DBI 模式,其规格如下:
- 支持 DBI Type C 3线/4线接口模式,支持 2 DATA LANE 接口模式
- 支持 QSPI 1线、2线、4线接口
- 支持来自 CPU 或 DMA 的数据源
- 支持 RGB111/444/565/666/888 视频格式
- DBI 1 DATA LANE 最大分辨率:RGB666 240 x 320@30Hz
- DBI 2 DATA LANE 最大分辨率:RGB888 240 x 320@60Hz 或 RGB666 320 x 480@30Hz
- QSPI 最大分辨率:RGB666 480 x 480@30Hz
- 支持屏 TE 同步接口(DBI TE,GPIO TE)
MIPI DBI(显示总线接口)也称为MCU接口。MIPI-DBI用于与具有集成图形内存(GRAM)的LCD进行通讯的接口。像素数据首先在显示驱动芯片的本地图形内存中更新,然后该内存会不断刷新显示器。主机和显示模块可以通过简单的GPIO连接。
信息
MIPI-DBI的类型如下,V861 支持的是 DBI TYPE C 协议,完整协议内容请参考《MIPI Alliance Standard for Display Bus Interface》:
- DBI TYPE A:基于摩托罗拉 6800 总线
- 支持 8/9/16/18/24 位并行数据传输
- DBI TYPE B:基于Intel® 8080总线
- 支持8/9/16/18/24位并行数据传输
- DBI TYPE C:基于SPI协议
- 支持3线或4线SPI接口
:::
支持屏幕接口如下表所示:
| DBI 协议 | 协议名称 | 信号线 | 市场惯用叫法 | 驱动方式 | 是否支持 |
|---|---|---|---|---|---|
| L3I1 | 3 线 1 Data | CS, SCK, SDA | 3 线 SPI | ||
| 3 Line 9Bit | DBI | 是 | |||
| L3I2 | 3 线 2 Data(单独的读取IO) | CS, SCK, SDA, SDO | 3 线 SPI | ||
| 3 Line 9Bit | DBI | 是 | |||
| L4I1 | 4 线 1 Data | CS, SCK, SDA, DC | 4 线 SPI | ||
| SPI 4W | SPI/DBI | 是 | |||
| L4I2 | 4 线 2 Data(单独的读取IO) | CS, SCK, SDA, DC, SDO | 4 线 SPI | DBI | 是 |
| D2LI | 2 Data Lane | CS, SCK, SDA, WR | 2 Data SPI | ||
| 3Wire 2data 9bit DSPI | DBI | 是 | |||
| \ | QSPI 单线 | CS, CLK, D0 | QSPI | QSPI | 是 |
| \ | QSPI 双线 | CS, CLK, D0, D1 | QSPI | QSPI | 是 |
| \ | QSPI 四线 | CS, CLK, D0, D1, D2, D3 | QSPI | QSPI | 是 |
接口硬件复用关系如下表所示,DBI 复用仅有 SPI1 控制器支持,SPI/QSPI 任意 SPI 均可:
| SPI | L3I1 | L3I2 | L4I1 | L4I2 | D2LI | QSPI |
|---|---|---|---|---|---|---|
| SPI-CS | DBI-CSX | DBI-CSX | DBI-CSX | DBI-CSX | DBI-CSX | QSPI-CS |
| SPI-HOLD | / | / | DBI-DCX | DBI-DCX | DBI-WRX | QSPI-D3 |
| SPI-CLK | DBI-SCLK | DBI-SCLK | DBI-SCLK | DBI-SCLK | DBI-SCLK | QSPI-CLK |
| SPI-MOSI | DBI-SDA | DBI-SDO | DBI-SDA | DBI-SDO | DBI-SDA | QSPI-D0 |
| SPI-MISO | / | DBI-SDI | / | DBI-SDI | / | QSPI-D1 |
| SPI-WP | DBI-TE | DBI-TE | DBI-TE | DBI-TE | DBI-TE | QSPI-D2 |
提示
QSPI 不限制 SPI 控制器,任意 SPI 控制器均可
:::
时序与信号说明
SPI 时序
SPI 接口就是俗称的 4 线 SPI 模式,这是因为发送数据时需要额外借助DC线来区分命令和数据,与 SCLK,CS和SDA共四线。只支持 RGB565 模式。
提示
-
SPI 接口协议与 DBI 的
L4I1和L4I2四线模式时序一样,完全兼容,区别是 DBI 下 DC 脚的控制是硬件自动 化控制,而 SPI 模式下需要 CPU 软件控制 DC 脚,由于是非硬件操作,所以刷图性能平均较低。一般 SPI 屏幕配置 DBI L4I1 模式即可。由硬件控制 DC 脚即可。 -
有一些特殊的屏幕需要专门控制 DC 时序,此时才使用 SPI 模式,手动控制 DC 时序。
:::
SPI 时序如下时序图所示:

RGB565 送图数据如下时序图所示:

DBI 时序
DBI 3-Line L3I1/L3I2
L3I1 和L3I2 是三线模式(不需要DC脚,SPI 使用 9BIT,第一个 BIT 区分是 Command 还是 Data)
L3I1 和L3I2 的区别是读时序,也就是是否需要额外脚来读寄存器。读写时序图如下:
- L3I 写时序:

- L3I 读时序,其中 L3I1 使用 interface I 时序读取数据,L3I2 使用 Interface 2 时序读取数据。

- DBI 3-Line RGB111 送图格式

- DBI 3-Line RGB444 送图格式

- DBI 3-Line RGB565 送图格式

- DBI 3-Line RGB666 送图格式

DBI 4-Line L4I1/L4I2
L4I1 和 L4I2 是四线模式,与 SPI 接口协议一样,区别是 DBI 下 DC 脚的控制是硬件自动化控制,而 SPI 模式下需要 CPU 软件控制 DC 脚。另外 I2 和 I1 的区别是读时序,也就是否需要额外脚来读取寄存器。
- L4I 写时序

- L4I读时序

- DBI 4-Line RGB111 送图格式

- DBI 4-Line RGB444 送图格式

- DBI 4-Line RGB565 送图格式

- DBI 4-Line RGB666 送图格式

DBI 2-Data Lane D2L1
D2LI 是 2 DATA LANE 模式。硬件连接上,第二根数据脚连接到原来 1 DATA LANE 的DC脚,2 DATA LANE 在传输数据时就自带D/C (Data/Commend)信息了,所以原来的 DC 脚就可以空出来作为第二根数据线了。
| 引脚 | 功能 |
|---|---|
| CSX | 芯片使能 |
| DCX | 串行 时钟 |
| SDA | 串行数据输入/输出 |
| WRX | 串行数据输入 2 |
- D2LI 命令写时序
提示
2 DATA LANE 模式接口的命令写入协议与3线串行接口相同,因此用户可以忽略WRX的输入数据。任何指令都可以按任意顺序发送给驱动程序。最高有效位(MSB)先传输。当CSX为高电平时,串行接口初始化。在此状态下,SCL时钟脉冲或SDA数据没有影响。CSX的下降沿使串行接口启用,并指示数据传输的开始。
:::

- D2L1 读时序
提示
2 DATA LANE 模式接口的命令读协议与3线串行接口相同。
:::

- DBI 4-Line RGB444 送图格式

- DBI 4-Line RGB565 送图格式

- DBI 4-Line RGB666 送图格式(格式0)

- DBI 4-Line RGB666 送图格式(格式1,ilitek 格式)

- DBI 4-Line RGB666 送图格式(格式2,新格式,兼容RGB888)

- DBI 4-Line RGB888 送图格式

QSPI 时序
QSPI 时序是标准 SPI 4 线协议,其每一次都需要发送命令和数据,不需要用 DC 脚区分发送的是命令还是数据。支持 QSPI 1线、2线、4线模式。
QSPI 读时序
当主机读取 QSPI 的命令或参数时,主机需要先发送1字节的写命令指令(0x0B)。然后,主机发送3字节的地址数据(AD[23:0]),该地址由1字节的0x00、1字节的命令地址和1字节的0x00组成。在主机发送完读命令和地址数据(AD[23:0])后,接下来的输出数据为命令地址的参数(即参数数据)。当最后一个参数的位被输出完毕后,CSX引脚应该返回高电平。

QSPI 单线写时序
当主机向 QSPI 写入命令或参数时,主机需要发送1字节的单线写命令指令(0x02)。然后,主机发送3字节的地址数据(AD[23:0]),该地址由1字节的0x00、1字节的命令地址和1字节的0x00组成。在主机发送完指令和地址数据(AD[23:0])后,接下来的数据为命令的参数(即参数数据)。当最后一个参数位被发送完毕后,CSX引脚应该恢复为高电平。
驱动配置为 LCD_FB_QSPI_LANE1,采用 QSPI 单线写方式驱动。

- RGB565 单线写送图格式

- RGB666 单线写送图格式

QSPI 双线写时序
当主机向 QSPI 写入命令或参数时,主机需要发送1字节的双线写命令指令(0xA2)。然后,主机发送3字节的地址数据(AD[23:0]),该地址由1字节的0x00、1字节的命令地址和1字节的0x00组成。在主机发送完指令和地址数据(AD[23:0])后,接下来的数据为命令的参数(即参数数据)。当最后一个参数位被发送完毕后,CSX引脚应该恢复为高电平。
驱动配置为 LCD_FB_QSPI_LANE2,采用 QSPI 双线写方式驱动,命令还是单线模式。

- RGB565 双线写送图格式

- RGB666 双线写送图格式

QSPI 四线写时序
当主机向 QSPI 写入命令或参数时,主机需要发送1字节的四线写命令指令(0x32)。然后,主机发送3字节的地址数据(AD[23:0]),该地址由1字节的0x00、1字节的命令地址和1字节的0x00组成。在主机发送完指令和地址数据(AD[23:0])后,接下来的数据为命令的参数(即参数数据)。当最后一个参数位被发送完毕后,CSX引脚应该恢复为高电平。
驱动配置为 LCD_FB_QSPI_LANE4,采用 QSPI 四线写方式驱动,命令还是单线模式。

- RGB565 四线写送图格式

- RGB666 四线写送图格式

源码结构介绍
SPI LCD 驱动在内核中叫做 LCD FB 驱动。其源码如下所示:
.
├── dev_fb.c
├── dev_fb.h
├── dev_lcd_fb.c
├── dev_lcd_fb.h
├── disp_display.c
├── disp_display.h
├── disp_lcd.c
├── disp_lcd.h
├── include.h
├── Kconfig
├── lcd_fb_feature.h
├── lcd_fb_intf.c
├── lcd_fb_intf.h
├── logo.c
├── logo.h
├── Makefile
└── panels
├── Kconfig
├── kld2844b.c
├── kld2844b.h
├── ...
├── lcd_source.h
├── panels.c
├── panels.h
└── spi_panel.c
SPI LCD 源码包括驱动源码与 SPI 屏幕驱动。其中屏幕驱动位于 panels 文件夹内。新增一款屏幕需要在 panels 文件夹中添加新屏幕驱动。
驱动版本
驱动版本可以查看 bsp/drivers/video/sunxi/lcd_fb/dev_lcd_fb.c 中末尾的 MODULE_VERSION 定义
模块配置介绍
内核模块配置
模块配置路径如下所示:
Allwinner BSP --->
Device Drivers --->
Video Drivers --->
SPI LCD Panel Drivers --->
<*> LCD FB Driver Support (SPI LCD)

LCD 显示面板驱动位于
Allwinner BSP --->
Device Drivers --->
Video Drivers --->
SPI LCD Panel Drivers --->
LCD FB Panels select --->
[*] LCD support kld2844B panel
...

设备树配置
这里以配置双屏,不同型号屏幕,屏幕 1 使用 SPI1 的 MIPI DBI 方式驱动,屏幕 2 使用 SPI2 的 SPI 软件 DC 方式驱动作为示例。配置如下所示:
&lcd_fb {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
spi_panel0: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_st7789v_spi1>;
};
spi_panel1: endpoint@1 {
reg = <1>;
remote-endpoint = <&panel_st7789v_spi2>;
};
};
};
&spi1 {
pinctrl-0 = <&spi1_pins_default &spi1_pins_hold>;
pinctrl-1 = <&spi1_pins_sleep>;
pinctrl-names = "default", "sleep";
clock-frequency = <100000000>;
sunxi,spi-bus-mode = <SUNXI_SPI_BUS_DBI>;
sunxi,spi-cs-mode = <SUNXI_SPI_CS_SOFT>;
status = "okay";
panel_st7789v_spi1: slave@0 {
device_type = "spi-panel";
compatible = "allwinner,spi-panel";
reg = <0x0>;
spi-max-frequency = <100000000>;
lcd_used = <1>;
lcd_driver_name = "st7789v";
lcd_if = <1>;
lcd_dbi_if = <2>;
lcd_data_speed = <48>;
lcd_x = <240>;
lcd_y = <240>;
lcd_pixel_fmt = <10>;
lcd_dbi_fmt = <2>;
lcd_rgb_order = <0>;
lcd_width = <60>;
lcd_height = <60>;
lcd_pwm_used = <0>;
lcd_pwm_ch = <6>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_frm = <1>;
lcd_gamma_en = <1>;
fb_buffer_num = <2>;
lcd_backlight = <100>;
lcd_fps = <60>;
lcd_dbi_te = <0>;
lcd_dbi_clk_mode = <0>;
lcd_gpio_0 = <&pio PD 4 GPIO_ACTIVE_LOW>;
status = "okay";
};
};
&spi2 {
clock-frequency = <100000000>;
pinctrl-0 = <&spi2_pins_default>;
pinctrl-1 = <&spi2_pins_sleep>;
pinctrl-names = "default", "sleep";
sunxi,spi-bus-mode = <SUNXI_SPI_BUS_MASTER>;
sunxi,spi-cs-mode = <SUNXI_SPI_CS_AUTO>;
status = "okay";
panel_st7789v_spi2: slave@0 {
device_type = "spi-panel";
compatible = "allwinner,spi-panel";
reg = <0x0>;
spi-max-frequency = <100000000>;
lcd_used = <1>;
lcd_driver_name = "st7789v";
lcd_if = <0>;
lcd_dbi_if = <0>;
lcd_data_speed = <48>;
lcd_x = <172>;
lcd_y = <320>;
lcd_pixel_fmt = <10>;
lcd_dbi_fmt = <2>;
lcd_rgb_order = <0>;
lcd_width = <60>;
lcd_height = <60>;
lcd_pwm_used = <0>;
lcd_pwm_ch = <6>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_frm = <1>;
lcd_gamma_en = <1>;
fb_buffer_num = <2>;
lcd_backlight = <100>;
lcd_fps = <60>;
lcd_dbi_te = <0>;
lcd_dbi_clk_mode = <0>;
lcd_spi_dc_pin = <&pio PD 17 GPIO_ACTIVE_LOW>;
lcd_gpio_0 = <&pio PD 13 GPIO_ACTIVE_LOW>;
status = "okay";
};
};
lcd_fb 节点用于配置和管理 LCD 屏幕的显示功能。该节点通过 port 属性配置了两款不同的 SPI 接口屏幕,分别为 spi_panel0 和 spi_panel1。每个屏幕的配置都通过 endpoint 和 remote-endpoint 关联,指定了屏幕的接口和驱动信息。
spi 节点定义了 SPI 控制器使用的引脚,SPI 驱动方式,SPI 最大频率,其中定义了 Panel 的节 点标识该 LCD 显示面板位于该 SPI 节点下。
panel_st7789v 节点定义了屏幕的物理尺寸,时序,接口,背光 PWM 等,配置项如下表所示
| 配置项 | 说明 |
|---|---|
lcd_used | LCD显示屏是否启用。值为 <1> 表示启用。 |
lcd_driver_name | LCD显示屏驱动的名称,此处为 st7789v,表示使用ST7789V驱动。必须与屏驱动中strcut __lcd_panel变量的name成员一致。 |
lcd_if | LCD接口类型, |
<0> 代表使用SPI接口。 | |
<1> 代表使用DBI接口。 | |
lcd_dbi_if | LCD DBI接口类型 |
| 0:L3I1 | |
| 1:L3I2 | |
| 2:L4I1 | |
| 3:L4I2 | |
| 4:D2LI | |
lcd_data_speed | 数据传输速率,<48> 表示设置为48 MHz。用于设置 SPI/DBI 接口时钟的速率,单位MHz。 |
lcd_x | 屏幕的横向分辨率,<240> 表示240像素。 |
lcd_y | 屏幕的纵向分辨率,<240> 表示240像素。 |
lcd_pixel_fmt | 像素格式,<10> 表示使用RGB565格式。 |
lcd_dbi_fmt | DBI接口的格式,<2> 表示并行接口的16位数据格式。 |
lcd_rgb_order | RGB像素顺序,<0> 表示RGB顺序。 |
lcd_width | LCD宽度,<60> 表示60mm宽。 |
lcd_height | LCD高度,<60> 表示60mm高 。 |
lcd_pwm_used | 是否启用PWM调光,<0> 表示未启用。 |
lcd_pwm_ch | PWM通道,<6> 表示使用通道6。 |
lcd_pwm_freq | PWM频率,<5000> 表示5000 Hz。 |
lcd_pwm_pol | PWM极性,<1> 表示正极性。 |
lcd_frm | 是否启用 frm 模式 |
lcd_gamma_en | 是否启用Gamma校正,<1> 表示启用。 |
fb_buffer_num | 帧缓冲区的数量,<2> 表示有两个缓冲区。 |
lcd_backlight | 背光亮度,<100> 表示设置为100%。 |
lcd_fps | 显示帧率,<60> 表示每秒60帧。 |
lcd_dbi_te | DBI接口的TE信号,<0> 表示禁用。 |
lcd_dbi_clk_mode | DBI时钟模式 |
| 0: 自动停止。有数据就有时钟,没发数据就没有 | |
| 1: 一直保持。无论发不发数据都有时钟 | |
lcd_spi_dc_pin | LCD 的 DC 引脚,使用 SPI 模式时需要配置 |
lcd_gpio_0 | LCD 的 GPIO 配置,< &pio PD 4 GPIO_ACTIVE_LOW > 表示连接到PD4,低电平有效。一般配置为屏幕 RST 引脚 |
status | 配置状态,"okay" 表示配置正常启用。 |
模块参数配置
lcd_driver_name
LCD 屏驱动的名字(字符串),必须与屏驱动中 strcut __lcd_panel 变量的 name 成员一致。
lcd_if
设置相应值的对应含义为:
enum sunxi_lcd_fb_disp_lcd_if {
LCD_FB_IF_SPI = 0,
LCD_FB_IF_DBI = 1,
LCD_FB_IF_QSPI = 2,
};
SPI 接口就是俗称的 4 线 SPI 模式,这是因为发送数据时需要额外借助DC线来区分命令和数据,与sclk,cs和sda共四线。如果设置了dbi接口,那么还需要进一步区分dbi接口,需要设置 lcd_dbi_if,如果设置了 qspi 接口,那么还需要进一步区分qspi接口,需要设置 lcd_qspi_if
lcd_dbi_if
LCD DBI 接口设置。
这个参数只有在 lcd_if=1 时才有效。
设置相应值的对应含义为:
enum sunxi_lcd_fb_dbi_if {
LCD_FB_L3I1 = 0x0,
LCD_FB_L3I2 = 0x1,
LCD_FB_L4I1 = 0x2,
LCD_FB_L4I2 = 0x3,
LCD_FB_D2LI = 0x4,
};
所有模式在发送数据时每个周期的比特数量根据不同像素格式不同而不同。
lcd_dbi_fmt
DBI接口像素格式。
enum lcdfb_dbi_fmt {
LCDFB_DBI_RGB111 = 0x0,
LCDFB_DBI_RGB444 = 0x1,
LCDFB_DBI_RGB565 = 0x2,
LCDFB_DBI_RGB666 = 0x3,
LCDFB_DBI_RGB888 = 0x4,
};
选择的依据是接收端屏Driver IC的支持情况,请查看Driver IC手册或询问屏厂。
然后必须配合 lcd_pixel_fmt 的选择,比如说选 RGB565 时,lcd_pixel_fmt也要选565格式。
lcd_dbi_te
使能 DBI TE 触发。
TE 即(Tearing Effect),也就是撕裂的意思,由于读写不同导致撕裂现象,TE 脚的功能就是用于同步读写,TE 脚的频率也就是屏的刷新率,所以 TE 脚也可以看做 VSYNC 脚(垂直同步脚)
0: 禁止te
1: 下降沿触发
2: 上升沿触发
lcd_spi_te_pin
使用 GPIO 中断方式处理 TE 信号,不使用 DBI 控制器的 TE 中断,需要配置引脚,支持 SPI、DBI、QSPI 屏,使用这个模式的时候需要配置 lcd_dbi_te = <0>
配置示例:
lcd_spi_te_pin = <&pio PD 6 GPIO_ACTIVE_LOW>;
- 关闭 TE 状态下显示黑白屏,可以明显看到屏幕黑白切换滚动显示

- 开启 TE 状态下显示黑白屏,可以明显看到屏幕切换固定显示

lcd_dbi_clk_mode
选择 dbi 时钟的行为模式。
0:自动停止。有数据就有时钟,没发数据就没有
1:一直保持。无论发不发数据都有时钟
注意上面的选项关系屏兼容性。部分屏幕需要一直提供时钟进行刷屏,否则不会更新显示。
lcd_rgb_order
输入图像数据 rgb 顺序识别设置,仅当 lcd_if=1 配置为 DBI 模式时有效。
0:RGB
1:RBG
2:GRB
3:GBR
4:BRG
5:BGR
6:G_1RBG_0
7:G_0RBG_1
8:G_1BRG_0
9:G_0BRG_1
非 RGB565 格式用 0 到 5 即可。
针对 RGB565 格式说明如下:
RGB565 格式会遇到大小端问题,ARM/RISC-V 平台和 PC 平台存储都是小端(little endian,低字节放在低地址,高字节放在高地址),但是许多 SPI 屏都是默认大端(Big Endian)。
也就是存储的字节顺序和发送的字节顺序不对应。这个时候选择 6 以下,DBI接口就会自动将小端转成大端。如果遇到默认是小端的 SPI 屏,则需要选择 6 以上,DBI接口会自动用回小端方式。
提示
6 以上格式这样解释:
R是5比特,G是6比特,B是5比特,再把G拆成高3位(G_1)和低3位(G_0) 所以以下两种顺序:

- R-G_1-G_0-B,大端。
- G_0-B-R-G_1,对应上面的9,小端。
:::
lcd_qspi_if
LCD QSPI 接口设置。
这个参数只有在 lcd_if=2 时才有效。
设置相应值的对应含义为:
enum sunxi_lcd_fb_qspi_if {
LCD_FB_QSPI_LANE1 = 0x0,
LCD_FB_QSPI_LANE2 = 0x1,
LCD_FB_QSPI_LANE4 = 0x2,
};
lcd_x
显示屏的水平像素数量,注意如果屏支持横竖旋转,那么 lcd_x 和 lcd_y 也要对调。
lcd_y
显示屏的行数,注意如果屏支持横竖旋转,那么 lcd_x 和 lcd_y 也要对调。
lcd_data_speed
用于设置 SPI/DBI 接口时钟的速率,单位MHz。
- 发送端(SoC) 的最大限制需要参考芯片数据手册。
- 接收端(屏Driver IC)的限制,请查看对应Driver IC手册或者询问屏厂支持。
- 超出以上限制都有可能导致显示异常。
lcd_data_speed_hz
用于设置 SPI/DBI 接口时钟的速率,单位Hz。
- 发送端(SoC) 的最大限制需要参考芯 片数据手册。
- 接收端(屏Driver IC)的限制,请查看对应Driver IC手册或者询问屏厂支持。
- 超出以上限制都有可能导致显示异常。
- 使用该配置后,lcd_data_speed 所配置的 MHz 参数将弃用,优先使用 lcd_data_speed_hz
lcd_fps
设置屏的刷新率,单位Hz。当 lcd_dbi_te 使能时,这个值设置无效。
lcd_pwm_used
是否使用 PWM。此参数标识是否使用 PWM 用以背光亮度的控制。
lcd_pwm_ch
此参数标识使用的 PWM 通道。
lcd_pwm_freq
这个参数配置PWM信号的频率,单位为Hz。
lcd_pwm_pol
这个参数配置PWM信号的占空比的极性。设置相应值对应含义为:
0:active high
1:active low
lcd_pwm_max_limit
最高限制,以亮度值表示。
比如150,则表示背光最高只能调到150,0~255范围内的亮度值将会被线性映射到0~150范围内。用于控制最高背光亮度,节省功耗。
lcd_backlight
默认背光值,取值范围0到255,值越大越亮。
lcd_bl_en
背光使能脚定义
lcd_spi_dc_pin
指定作为 DC 的管脚,用于 SPI 接口时软件控制 DC 模式。
lcd_gpio_x
x 表示数字。如果有多个 gpio 脚需要控制,则定义 lcd_gpio_0,lcd_gpio_1 等。
lcd_pixel_fmt
选择传输数据的像素格式。
可选值如下,当你更换RGB分量顺序的时候,也得相应修改 lcd_rgb_order,或者修改屏驱动的 RGB 分量顺序(一般是3Ah寄存器)。
备注
DBI接口支持 RGB32 和 RGB16 的情况。
SPI 接口只支持 RGB16 的情况。
:::
enum lcdfb_pixel_format {
LCDFB_FORMAT_ARGB_8888 = 0x00, // MSB A-R-G-B LSB
LCDFB_FORMAT_ABGR_8888 = 0x01,
LCDFB_FORMAT_RGBA_8888 = 0x02,
LCDFB_FORMAT_BGRA_8888 = 0x03,
LCDFB_FORMAT_XRGB_8888 = 0x04,
LCDFB_FORMAT_XBGR_8888 = 0x05,
LCDFB_FORMAT_RGBX_8888 = 0x06,
LCDFB_FORMAT_BGRX_8888 = 0x07,
LCDFB_FORMAT_RGB_888 = 0x08,
LCDFB_FORMAT_BGR_888 = 0x09,
LCDFB_FORMAT_RGB_565 = 0x0a,
LCDFB_FORMAT_BGR_565 = 0x0b,
LCDFB_FORMAT_ARGB_4444 = 0x0c,
LCDFB_FORMAT_ABGR_4444 = 0x0d,
LCDFB_FORMAT_RGBA_4444 = 0x0e,
LCDFB_FORMAT_BGRA_4444 = 0x0f,
LCDFB_FORMAT_ARGB_1555 = 0x10,
LCDFB_FORMAT_ABGR_1555 = 0x11,
LCDFB_FORMAT_RGBA_5551 = 0x12,
LCDFB_FORMAT_BGRA_5551 = 0x13,
};
fb_buffer_num
显示 framebuffer 数量,为了平滑显示,这里一般是2个,为了省内存也可以改成1。
信息
以下配置为 1.0.6 版本新增配置
:::
lcd_vsync_send_frame
每一次 TE 信号都去送显,与 Vsync 信号同步。不需要等待上层调用 FBIO_PAN_DISPLAY 再去送显。会增加 CPU 占用,但是能改善帧率。需要配置 GPIO TE 模式。

配置示例:
lcd_vsync_send_frame = <0>; # 关闭功能
lcd_vsync_send_frame = <1>; # 启用功能

注意
开启功能会增加 CPU 占用,在 V861 平台将占用 4% CPU

:::
模块调试节点
在驱动 1.0.7 版本中,新增了模块调试节点,位于 /sys/class/lcd_fb/lcd_fb/attr/ 目录下,可以执行屏幕配置测试
screenid
用于配置调试使用的屏幕 ID,默认为屏幕 0,在多屏环境下可以使用这个节点切换屏幕,例如下面的把屏幕切到屏幕1
echo 1 > /sys/class/lcd_fb/lcd_fb/attr/screenid
colorbar
用于测试屏幕显示,输出彩条测试
| 参数 | 作用 | 次数 |
|---|---|---|
| 0 | 显示黑屏,清零 FB 数据 | 1 |
| 1 | 显示彩条,用于点屏测试 | 1 |
| 2 | 显示黑白屏切回,用于 TE 调试 | 500 |
echo 1 > /sys/class/lcd_fb/lcd_fb/attr/colorbar

模块配置案例
SPI 模式接口屏配置
如果 IC 支持 DBI 接口,那么就没有必要用 SPI 接口,DBI 接口其协议能覆盖所有情况。
提示
SPI 接口协议与 DBI 的 L4I1 和 L4I2 四线模式时序一样,区别是DBI 下 DC 脚的控制是硬件自动化控制,而 SPI 模式下需要 CPU 软件控制 DC 脚,由于是非硬件操作,所以刷图性能平均较低。一般 SPI 屏幕配置 DBI L4I1 模式即可。由硬件控制 DC 脚即可。
:::
注意
部分屏幕需要特殊时序的 DC 脚,需要交由 CPU 软件控制 DC 时序,此时仅可使用 SPI 模式。如果使用 SPI 接口,它有一些限制。
- 不支持 2 data lane。
- 必须指定DC脚。这是由于spi协议不会自动控制DC脚来区分数据命令,通过设置
lcd_spi_dc_pin可以完成这个目的,这跟管脚不必用 SPI 控制器中的脚,可以任意选择GPIO。 - 只支持 RGB565 的像素格式。由于只有单 data lane,速度过慢,RGB565 以上格式都不现实。
:::
配置如下:
&pio {
spi1_pins_default: spi1@0 {
pins = "PD1", "PD2", "PD3"; /* CS, SCK, SDA */
function = "spi1";
allwinner,drive = <3>;
};
spi1_pins_sleep: spi1@2 {
pins = "PD1", "PD2", "PD3";
function = "io_disabled";
};
};
&lcd_fb {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
spi_panel0: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_st7789v_spi1>;
};
};
};
&spi1 {
clock-frequency = <100000000>;
pinctrl-0 = <&spi1_pins_default>;
pinctrl-1 = <&spi1_pins_sleep>;
pinctrl-names = "default", "sleep";
sunxi,spi-bus-mode = <SUNXI_SPI_BUS_MASTER>;
sunxi,spi-cs-mode = <SUNXI_SPI_CS_SOFT>; // 使用 SPI 模式需要配置软件 CS 模式
status = "okay";
panel_st7789v_spi1: slave@0 {
device_type = "spi-panel";
compatible = "allwinner,spi-panel";
reg = <0x0>;
spi-max-frequency = <100000000>;
lcd_used = <1>;
lcd_driver_name = "st7789v";
lcd_if = <0>;
lcd_dbi_if = <0>;
lcd_data_speed = <48>;
lcd_x = <172>;
lcd_y = <320>;
lcd_pixel_fmt = <10>;
lcd_dbi_fmt = <2>;
lcd_rgb_order = <0>;
lcd_width = <60>;
lcd_height = <60>;
lcd_pwm_used = <0>;
lcd_pwm_ch = <6>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_frm = <1>;
lcd_gamma_en = <1>;
fb_buffer_num = <2>;
lcd_backlight = <100>;
lcd_fps = <60>;
lcd_dbi_te = <0>;
lcd_dbi_clk_mode = <0>;
lcd_spi_dc_pin = <&pio PD 17 GPIO_ACTIVE_LOW>;
lcd_gpio_0 = <&pio PD 13 GPIO_ACTIVE_LOW>;
status = "okay";
};
};
DBI 模式 L4I1 接口屏配置
提示
SPI 接口协议与 DBI 的 L4I1 和 L4I2 四线模式时序一样,区别是DBI 下 DC 脚的控制是硬件自动化控制,而 SPI 模式下需要 CPU 软件控制 DC 脚,由于是非硬件操作,所以刷图性能较低。一般 SPI 屏幕配置 DBI L4I1 模式即可。由硬件控制 DC 脚即可。
:::
&pio {
dbi1_pins_default: dbi1@0 {
pins = "PD1", "PD2", "PD3"; /* dbi-cs, dbi-clk, dbi-sdo */
function = "spi1";
allwinner,drive = <3>;
};
dbi1_pins_dcx: dbi1@1 {
pins = "PD5"; /* dbi-dcx */
function = "spi1_hold";
allwinner,drive = <3>;
bias-pull-up;
};
dbi1_pins_sleep: dbi1@2 {
pins = "PD1", "PD2", "PD3", "PD5";
function = "io_disabled";
};
};
&lcd_fb {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
spi_panel0: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_st7789v_spi1>;
};
};
};
&spi1 {
pinctrl-0 = <&dbi1_pins_default &dbi1_pins_dcx>;
pinctrl-1 = <&dbi1_pins_sleep>;
pinctrl-names = "default", "sleep";
clock-frequency = <100000000>;
sunxi,spi-bus-mode = <SUNXI_SPI_BUS_DBI>;
sunxi,spi-cs-mode = <SUNXI_SPI_CS_AUTO>;
status = "okay";
panel_st7789v_spi1: slave@0 {
device_type = "spi-panel";
compatible = "allwinner,spi-panel";
reg = <0x0>;
spi-max-frequency = <100000000>;
lcd_used = <1>;
lcd_driver_name = "st7789v";
lcd_if = <1>;
lcd_dbi_if = <2>;
lcd_data_speed = <48>;
lcd_x = <240>;
lcd_y = <240>;
lcd_pixel_fmt = <10>;
lcd_dbi_fmt = <2>;
lcd_rgb_order = <0>;
lcd_width = <60>;
lcd_height = <60>;
lcd_pwm_used = <0>;
lcd_pwm_ch = <6>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_frm = <1>;
lcd_gamma_en = <1>;
fb_buffer_num = <2>;
lcd_backlight = <100>;
lcd_fps = <60>;
lcd_dbi_te = <0>;
lcd_dbi_clk_mode = <0>;
lcd_gpio_0 = <&pio PD 4 GPIO_ACTIVE_LOW>;
status = "okay";
};
};
DBI 模式 L3I1 接口屏配置
&pio {
dbi1_pins_default: dbi1@0 {
pins = "PD1", "PD2", "PD3"; /* dbi-cs, dbi-clk, dbi-sdo */
function = "spi1";
allwinner,drive = <3>;
};
dbi1_pins_dcx: dbi1@1 {
pins = "PD5"; /* dbi-dcx */
function = "spi1_hold";
allwinner,drive = <3>;
bias-pull-up;
};
dbi1_pins_sleep: dbi1@2 {
pins = "PD1", "PD2", "PD3", "PD5";
function = "io_disabled";
};
};
&lcd_fb {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
spi_panel0: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_st7789v_spi1>;
};
};
};
&spi1 {
pinctrl-0 = <&dbi1_pins_default &dbi1_pins_dcx>;
pinctrl-1 = <&dbi1_pins_sleep>;
pinctrl-names = "default", "sleep";
clock-frequency = <100000000>;
sunxi,spi-bus-mode = <SUNXI_SPI_BUS_DBI>;
sunxi,spi-cs-mode = <SUNXI_SPI_CS_AUTO>;
status = "okay";
panel_st7789v_spi1: slave@0 {
device_type = "spi-panel";
compatible = "allwinner,spi-panel";
reg = <0x0>;
spi-max-frequency = <100000000>;
lcd_used = <1>;
lcd_driver_name = "st7789v";
lcd_if = <1>;
lcd_dbi_if = <0>;
lcd_data_speed = <48>;
lcd_x = <240>;
lcd_y = <240>;
lcd_pixel_fmt = <10>;
lcd_dbi_fmt = <2>;
lcd_rgb_order = <0>;
lcd_width = <60>;
lcd_height = <60>;
lcd_pwm_used = <0>;
lcd_pwm_ch = <6>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_frm = <1>;
lcd_gamma_en = <1>;
fb_buffer_num = <2>;
lcd_backlight = <100>;
lcd_fps = <60>;
lcd_dbi_te = <0>;
lcd_dbi_clk_mode = <0>;
lcd_gpio_0 = <&pio PD 4 GPIO_ACTIVE_LOW>;
status = "okay";
};
};
DBI 模式 D2I1 接口屏配置
&pio {
dbi1_pins_default: dbi1@0 {
pins = "PD1", "PD2", "PD3"; /* dbi-cs, dbi-clk, dbi-sdo */
function = "spi1";
allwinner,drive = <3>;
};
dbi1_pins_dcx: dbi1@1 {
pins = "PD5"; /* dbi-dcx */
function = "spi1_hold";
allwinner,drive = <3>;
bias-pull-up;
};
dbi1_pins_sleep: dbi1@2 {
pins = "PD1", "PD2", "PD3", "PD5";
function = "io_disabled";
};
};
&lcd_fb {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
spi_panel0: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_nv3031a_spi1>;
};
};
};
&spi1 {
pinctrl-0 = <&dbi1_pins_default &dbi1_pins_dcx>;
pinctrl-1 = <&dbi1_pins_sleep>;
pinctrl-names = "default", "sleep";
clock-frequency = <100000000>;
sunxi,spi-bus-mode = <SUNXI_SPI_BUS_DBI>;
sunxi,spi-cs-mode = <SUNXI_SPI_CS_AUTO>;
status = "okay";
panel_nv3031a_spi1: slave@0 {
device_type = "spi-panel";
compatible = "allwinner,spi-panel";
reg = <0x0>;
spi-max-frequency = <100000000>;
lcd_used = <1>;
lcd_driver_name = "nv3031a";
lcd_if = <1>;
lcd_dbi_if = <4>;
lcd_data_speed = <48>;
lcd_x = <240>;
lcd_y = <240>;
lcd_pixel_fmt = <10>;
lcd_dbi_fmt = <2>;
lcd_rgb_order = <0>;
lcd_width = <60>;
lcd_height = <60>;
lcd_pwm_used = <0>;
lcd_pwm_ch = <6>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_frm = <1>;
lcd_gamma_en = <1>;
fb_buffer_num = <2>;
lcd_backlight = <100>;
lcd_fps = <60>;
lcd_dbi_te = <0>;
lcd_dbi_clk_mode = <0>;
lcd_gpio_0 = <&pio PD 4 GPIO_ACTIVE_LOW>;
status = "okay";
};
};
QSPI 模式单线 QSPI 接口屏配置
时序图:

&pio {
spi1_pins_default: spi1@0 {
pins = "PD1", "PD2", "PD3"; /* CS, SCK, D0 */
function = "spi1";
allwinner,drive = <3>;
};
spi1_pins_sleep: spi1@3 {
pins = "PD1", "PD2", "PD3";
function = "io_disabled";
};
};
&lcd_fb {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
spi_panel0: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_st7789v_spi1>;
};
};
};
&spi1 {
pinctrl-0 = <&spi1_pins_default>;
pinctrl-1 = <&spi1_pins_sleep>;
pinctrl-names = "default", "sleep";
clock-frequency = <100000000>;
sunxi,spi-bus-mode = <SUNXI_SPI_BUS_MASTER>;
sunxi,spi-cs-mode = <SUNXI_SPI_CS_SOFT>;
status = "okay";
panel_st7789v_spi1: slave@0 {
device_type = "spi-panel";
compatible = "allwinner,spi-panel";
reg = <0x0>;
spi-max-frequency = <100000000>;
spi-rx-bus-width = <1>;
spi-tx-bus-width = <1>;
lcd_used = <1>;
lcd_driver_name = "st77916_qspi";
lcd_if = <2>;
lcd_dbi_if = <0>;
lcd_qspi_if = <0>;
lcd_data_speed = <48>;
lcd_x = <360>;
lcd_y = <360>;
lcd_pixel_fmt = <10>;
lcd_dbi_fmt = <2>;
lcd_rgb_order = <0>;
lcd_width = <60>;
lcd_height = <60>;
lcd_pwm_used = <0>;
lcd_pwm_ch = <6>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_frm = <1>;
lcd_gamma_en = <1>;
fb_buffer_num = <2>;
lcd_backlight = <100>;
lcd_fps = <60>;
lcd_dbi_te = <0>;
lcd_dbi_clk_mode = <0>;
lcd_gpio_0 = <&pio PD 14 GPIO_ACTIVE_LOW>;
status = "okay";
};
};
QSPI 模式双线 QSPI 接口屏配置
时序图:

&pio {
spi1_pins_default: spi1@0 {
pins = "PD1", "PD2", "PD3", "PD4"; /* CS, SCK, D0, D1 */
function = "spi1";
allwinner,drive = <3>;
};
spi1_pins_sleep: spi1@3 {
pins = "PD1", "PD2", "PD3", "PD4";
function = "io_disabled";
};
};
&lcd_fb {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
spi_panel0: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_st7789v_spi1>;
};
};
};
&spi1 {
pinctrl-0 = <&spi1_pins_default>;
pinctrl-1 = <&spi1_pins_sleep>;
pinctrl-names = "default", "sleep";
clock-frequency = <100000000>;
sunxi,spi-bus-mode = <SUNXI_SPI_BUS_MASTER>;
sunxi,spi-cs-mode = <SUNXI_SPI_CS_SOFT>;
status = "okay";
panel_st7789v_spi1: slave@0 {
device_type = "spi-panel";
compatible = "allwinner,spi-panel";
reg = <0x0>;
spi-max-frequency = <100000000>;
spi-rx-bus-width = <2>;
spi-tx-bus-width = <2>;
lcd_used = <1>;
lcd_driver_name = "st77916_qspi";
lcd_if = <2>;
lcd_dbi_if = <0>;
lcd_qspi_if = <1>;
lcd_data_speed = <48>;
lcd_x = <360>;
lcd_y = <360>;
lcd_pixel_fmt = <10>;
lcd_dbi_fmt = <2>;
lcd_rgb_order = <0>;
lcd_width = <60>;
lcd_height = <60>;
lcd_pwm_used = <0>;
lcd_pwm_ch = <6>;
lcd_pwm_freq = <5000>;
lcd_pwm_pol = <1>;
lcd_frm = <1>;
lcd_gamma_en = <1>;
fb_buffer_num = <2>;
lcd_backlight = <100>;
lcd_fps = <60>;
lcd_dbi_te = <0>;
lcd_dbi_clk_mode = <0>;
lcd_gpio_0 = <&pio PD 14 GPIO_ACTIVE_LOW>;
status = "okay";
};
};