rgb屏幕适配

已适配的屏幕切换

board.dts(Linux设备树)

文件位置 device/config/chips/t113/configs/zqboard/linux-5.4/board.dts

  • 修改触摸参数,触摸是使用twi2,搜索ctp_name,找到相关参数,下面有写好的参数,通过define来切换

把下面的if和elif之类的后面改1或者0就可以启用某一段配置了,后面有分辨率注释。

  • 修改屏幕参数,搜索disp init configuration,从这往下是屏幕的定义,可以先看一下这个注释里面每个参数的说明,然后往下找到具体的#if #elif的地方,切换屏幕配置

还需要修改

        fb0_width                = <1024>;
        fb0_height               = <600>;

uboot-board.dts (UBoot 设备树)

文件位置 device/config/chips/t113/configs/zqboard/uboot-board.dts

  • 修改fb0_width和fb0_height

  • 修改下面的if else,选中对应的屏幕参数

新的RGB屏幕适配

在 t113 的手册中,可以看到 t113 芯片支持 1920 x 1080 @ 60fps 的 RGB 屏幕显示。 rgb1

本文将通过介绍 Tina Linux 的显示驱动、配置方法、移植适配 LCD 屏幕与测试和使用,介绍 Tina Linux 的显示系统。

LCD 的驱动

rgb2

显示驱动可划分为三个层面:驱动层,框架层及底层。底层与图形硬件相接,主要负责将上层配置的功能参数转换成硬件所需要的参数,并配置到相应寄存器中。

显示框架层对底层进行抽象封装成一个个的功能模块。驱动层对外封装功能接口,通过内核向用户空间提供相应的设备结点及统一的接口。

在驱动层,分为三个驱动,分别是framebuffer驱动,display驱动,LCD&HDMI驱动。framebuffer 驱动与 framebuffer core 对接,实现 linux 标准的framebuffer 接口。display驱动是是整个显示驱动中的核心驱动模块,所有的接口都由 display 驱动来提供,包括 lcd 的接口。

在这里,我们只需要关心 LCD&HDMI 驱动,其他部分的驱动的开发可以参考《Linux_Display_开发指南.pdf》

LCD 配置

内核配置

运行 make kernel_menuconfig 进入内核配置,找到 Video support for sunxi

Device Drivers > Graphics support > Frame buffer Devices > Video support for sunxi

rgb3 在显示驱动中最主要的是 <*> DISP Driver Support(sunxi-disp2) ,勾选后可以看到其他的选项。包括驱动支持,调试接口和 LCD 面板的选择。(LCD panels select

进入 LCD 面板选择可以看到许多已经适配了的显示屏可供选择使用。 rgb4

设备树配置

与其他设备相同,屏幕驱动也使用了两份设备树。第一份配置了显示驱动的地址,时钟等等参数,位于lichee/linux-5.4/arch/arm/boot/dts/sun8iw20p1.dtsi 一般来说这里的参数都不需要修改,默认即可,另外一份配置位于 device/config/chips/t113/configs/zqboard/linux-5.4/board.dts 包括了两个配置节点。第一个是 display 所使用的节点,配置了屏幕的特性与功能,另外一个是 lcd 所使用的节点,配置了 LCD 面板的驱动与参数。 rgb5rgb6 这里的驱动配置非常复杂,具体代表的含义请参考《Linux_LCD_调试指南.pdf》,这里不做过多说明。

LCD 驱动

LCD 显示屏与其他驱动不一样,LCD 屏幕种类繁多,接口丰富,各式各样屏幕参数层出不穷。所以 LCD 屏幕驱动都是以单独的模块存在的,驱动文件位于:

lichee/linux-5.4/drivers/video/fbdev/sunxi/disp2/disp/lcd

rgb7 从接口上来分,LCD 屏幕可以分为 RGB 屏幕,LVDS 屏幕,MIPI DSI 屏幕,eDP 屏幕、SPI 屏幕、IIC 屏幕。T113 芯片所支持的是LVDS、 MIPI 与 RGB,所以在这里其他类型的屏幕不过多说明。这里简单介绍下MIPI 与 RGB两种屏幕。

(1)RGB 接口 RGB接口在全志平台又称HV接口(Horizontal同步和Vertical同步)。有些LCD屏支持高级的功能比如 gamma,像素格式的设置等,但是 RGB 协议本身不支持图像数据之外的传输,所以无法通过 RGB 管脚进行对 LCD 屏进行配置,所以拿到一款 RGB 接口屏,要么不需要初始化命令,要么这个屏会提供额外的管脚给 SoC 来进行配置,比如 SPI 和 I2C 等。RGB 屏幕有许多格式,不同的位宽,不同的时钟周期。下表是位宽与时钟周期的区别。 rgb8

(2)MIPI DSI 接口 MIPI-DSI,即Mobile Industry Processor Interface Display Serial Interface,移动通信行业处理器接口显示串行接口。MIPI 有2种模式:

  1. Command mode,类似MPU接口,需要IC内部有GRAM来缓冲。

  2. Video mode。类似 RGB 接口,没有 GRAM,需要不停往 panel 刷数据。其中 video mode 又分为三个子 mode:

  3. Non-burst mode with sync pulses

  4. Non Burst mode with sync Events

  5. Burst mode。简单理解就是有效数据比率更高,传输效率更高。

MIPI-DSI 的管脚是差分的,分为两种管脚:一种是时钟管脚,另外一种是数据管脚。数据管脚的数量是可变的,数量的单位是 lane ,lane 也指一对差分管脚,每一条 lane 实际包含两条线。一般来说 LCD 屏说明书里面的说的 lane 的数量是指数据管脚的数量不包括时钟管脚。比如说某 4 lane MIPI-DSI 屏就总共有 (4+1)*2 根脚。

适配驱动 LCD 屏幕

适配屏幕之前,我们可以先关闭 Uboot 的屏幕驱动,保留 Kernel 的驱动方便调试

先前往 Uboot 配置文件夹修改配置文件关闭屏幕驱动。

lichee/brandy/brandy-2.0/u-boot-2018/configs/sun8iw20p1_defconfig

CONFIG_DISP2_SUNXI=y 注释了

rgb9

RGB 屏幕

下面简述如何移植一款 RGB 屏幕,型号【ZJ050NA-08C】,此 RGB 屏幕无需初始化。使用50Pin 排线,RGB666 连接开发板 rgb10

由于此 RGB 屏幕不需要初始化,所以直接使用 default_lcd 驱动即可,在 kernel 内 default_lcd 是默认启用的,所以只需要修改设备树即可。

(1)硬件连接 硬件连接如电路图与 LCD 屏幕手册所示: 50pin RGB rgb11 rgb12

对照检查所有所有信号位置和顺序都一致,可以直接连接。

(2)设备树配置 首先,我们需要给LCD需要的pin做绑定。因为我们用的是默认的pin,没有修改,所以在kernel里面的dtsi文件里面,已经帮我们绑定好了。我们直接使用这个定义就可以。我们可以检查并确认一下pin绑定正确。

节点名字为rgb18_pins_argb18_pins_b 文件为:lichee/linux-5.4/arch/arm/boot/dts/sun8iw20p1.dtsi rgb13

然后打开device/config/chips/t113/configs/zqboard/linux-5.4/board.dts文件。修改 lcd0 节点。这里将其分为几个部分,下文会对这几个部分着重说明。另外比较重要的配置项添加了注释。 rgb14 注意这里有多个已经适配好的屏幕的参数,用#if#elif来确定哪个激活。我们再最后面,按照这个格式,继续添加一个#elif即可,把前面的都改成0,最后新加的这个#elif 给1。

&lcd0 {
        // part 1
        lcd_used            = <1>;              # 启用lcd
        lcd_driver_name     = "default_lcd";    # 使用 default_lcd 驱动
        lcd_backlight       = <50>;             # 背光强度

        // part 2
        lcd_if = <0>;                           # 0:rgb 4:dsi
        lcd_hv_if = <0>;

        // part 3
        lcd_x               = <640>;            # 宽度
        lcd_y               = <480>;            # 高度
        lcd_width           = <102>;            # 屏幕物理宽度,单位 mm
        lcd_height          = <76>;             # 屏幕物理高度,单位 mm
        lcd_dclk_freq       = <25>;             # 屏幕时钟,单位 MHz
        lcd_hbp             = <46>;             # hsync back porch(pixel) + hsync plus width(pixel);
        lcd_ht              = <800>;            # hsync total cycle(pixel)
        lcd_hspw            = <4>;              # hsync plus width(pixel)
        lcd_vbp             = <34>;             # vsync back porch(line) + vysnc plus width(line)
        lcd_vt              = <525>;            # vsync total cycle(line)
        lcd_vspw            = <3>;              # vsync plus width(pixel)    

        lcd_pwm_used        = <1>;              # 启用背光 PWM
        lcd_pwm_ch          = <7>;              # 使用 PWM 通道 7 
        lcd_pwm_freq        = <50000>;          # PWM 频率,单位 Hz
        lcd_pwm_pol         = <1>;              # 背光 PWM 的极性
        lcd_pwm_max_limit   = <255>;            # 背光 PWM 的最大值(<=255)

        // part 5
        lcd_frm = <1>;                          # 0:关闭; 1:启用rgb666抖动; 2:启用rgb656抖动
        lcd_io_phase = <0x0000>;
        lcd_gamma_en = <0>;
        lcd_cmap_en = <0>;
        lcd_hv_clk_phase = <0>;
        lcd_hv_sync_polarity= <1>;

        // part 6
        lcd_power = "vcc-lcd";
        lcd_pin_power = "vcc-pd";
        pinctrl-0 = <&rgb18_pins_a>;
        pinctrl-1 = <&rgb18_pins_b>;
};

我们设置了屏幕的像素宽度、高度,物理宽度、高度,这些数据都可以在屏厂提供的数据手册中查询到。有小数点的可以遵循四舍五入原则。 rgb15

我们配置了 LCD 屏幕的背光相关属性,使用 PWM 背光实现动态调整背光,可以在电路图中看到 LCD-PWM 使用的是 PWM9,所以配置 lcd_pwm_ch = <7>; rgb16

Part3的屏幕参数是非常重要的,能不能点亮 LCD 屏幕都靠这一部分。 rgb17 rgb18

(1)DCLK 首先是 DCLK,按照手册中的Tclk的典型值13.5ns换算频率

  • Tclk = 13.5 ns

  • 频率公式:

    f = 1 / T

  • 计算:

    f = 1 / (13.5 × 10⁻⁹) Hz

    f ≈ 74.07 MHz

也就是说只要频率小于74Mhz就可以运行。这里我们写25Mhz 设置 lcd_dclk_freq = <25>;

(2)HT(Hsync Total) 查询手册可知(手册上的TH值),HT 的值是 800,这个值不需要修改。填入即可。

(3)HBP(Hsync Back Porch) 查询手册可知,HBP 值为 46 ,不过由于全志平台的 HBP 的含义是 HBP + HSPW,所以需要加上 HSPW 的值填入。这里便是 42 + 4 = 46

(4)HSPW(Hsync Plus Width) 这个其实是手册上的Thwh

(5)VT(Vsync Total)

查询手册可知(手册上的TV值),VT 的值是 525,这个值不需要修改。填入即可。

(6)VBP(Vsync Back Porch)

查询手册可知,VBP 值为 31,不过由于全志平台的 VBP 的含义是 VBP + VSPW,所以需要加上 VSPW 的值填入。这里便是 31 + 3 = 34

(7)VSPW(Vsync Plus Width)

这个其实是手册上的Tvwh

其余部分通常不需要改动,如果需要设置,请参考LCD调试手册

至此,我们将lcd节点设置完成,但是由于新屏幕和之前屏幕的分辨率不一样,所以我们还需要修改&disp中的fb0_widthfb0_height,使得framebuffer与屏幕像素一致。

rgb19

驱动勾选 不需要初始化的 RGB LCD 的驱动比较简单,勾选Video support for sunxi 即可

Device Drivers > Graphics support > Frame buffer Devices > Video support for sunxi

rgb3

测试屏幕 编译,打包。烧录系统。 先 ls 命令打印 /dev/ 目录看看有没有出现 fb0 这个节点 rgb20

可以看到这里有 fb0 节点。那就进行下最简单的花屏测试。

cat /dev/urandom > /dev/fb0

rgb21

这个测试一定会显示 cat: write error: No space left on device ,这样才是正常情况,因为 FB0 可以类比为屏幕的显存,显存是固定大小的可以被消耗完,当显存填满的时候就会报错 No space left on device。如果执行这一行命令一直没出现这个报错则有可能底层显示驱动配置有问题。

开机 LOGO 是由 UBOOT 所提供的支持,所以需要配置 UBOOT 的显示屏驱动。

在这之前,先前往 Uboot 检查是否开启了屏幕驱动。

lichee/brandy/brandy-2.0/u-boot-2018/configs/sun8iw20p1_defconfig

把 CONFIG_DISP2_SUNXI=y 取消注释 rgb22

然后如同 Kernel 一样,修改 Uboot 的设备树即可。

device/config/chips/t113/configs/zqboard/uboot-board.dts

运行结果

rgb23