• Linux图形显示DRM子系统环境实践


    前言

    学习Linux图形DRM子系统,还是需要有一个运行DRM框架的linux系统,这样无论在学习DRM应用程序还是驱动程序时,可以实际动手修改调试,运行看到效果,学习起来也是比较有动力和成就感的。下面是一个搭建Linux DRM运行环境的实践

    环境

    QEMU + vexpress-a9 + linux-4.14.7 kernel

    一、linux-4.14.7默认使用的显示驱动是framebuffer子系统,当使用QEMU图形界面运行时,可以直接以图形界面运行linux(framebuffer):
    在这里插入图片描述
    但是我们需要的是用DRM子系统来显示画面,因此就需要将framebuffer替换为DRM

    二、从默认的framebuffer配置vexpress_defconfig可以得知,vexpress-a9开发板用的是ARM PrimeCell PL110 LCD controller,对应的fb驱动文件是amba-clcd.c(amba驱动)。对应的panel驱动文件是amba-clcd-versatile.c,负责和panel相关的初始化操作。对应的设备树节点如下:

    clcd@10020000 {
                    compatible = "arm,pl111", "arm,primecell";
                    reg = <0x10020000 0x1000>;
                    interrupt-names = "combined";
                    interrupts = <0 44 4>;
                    clocks = <&oscclk1>, <&oscclk2>;
                    clock-names = "clcdclk", "apb_pclk";
                    max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */
    
                    port {
                            clcd_pads: endpoint {
                                    remote-endpoint = <&clcd_panel>;
                                    arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
                            };
                    };
    
                    panel {
                            compatible = "panel-dpi";
    
                            port {
                                    clcd_panel: endpoint {
                                            remote-endpoint = <&clcd_pads>;
                                    };
                            };
    
                            panel-timing {
                                    clock-frequency = <63500127>;
                                    hactive = <1024>;
                                    hback-porch = <152>;
                                    hfront-porch = <48>;
                                    hsync-len = <104>;
                                    vactive = <768>;
                                    vback-porch = <23>;
                                    vfront-porch = <3>;
                                    vsync-len = <4>;
                            };
                    };
            };
    
    
    • 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

    三、在drivers/gpu/drm目录下找到pl111文件夹,标注是PL111 CLCD Controller,这个驱动应该就是PL111对应的DRM驱动:

    linux-4.14.7/drivers/gpu/drm/pl111$ ls
    built-in.o       modules.order          pl111_debugfs.c  pl111_drm.h
    Kconfig          pl111_connector.c      pl111_debugfs.o  pl111_drm.o
    Makefile         pl111_connector.c_bak  pl111_display.c  pl111_drv.c
    modules.builtin  pl111_connector.o      pl111_display.o  pl111_drv.o
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在内核配置中配置DRM系统和PL111 DRM驱动
    在这里插入图片描述

    四、完成上述的配置并运行后,发现并没有生成dri/card0节点,查看开机的log,发现有如下报错:

    drm-clcd-pl111 10020000.clcd: Disabling due to lack of DRM panel device.
    drm-clcd-pl111: probe of 10020000.clcd failed with error -17
    
    • 1
    • 2

    看样子是没有找到drm panel设备,应该是还缺少panel驱动文件。DRM中有panel有关的文件都放在drivers/gpu/drm/panel里

    linux-4.14.7/drivers/gpu/drm/panel$ ls
    built-in.o             panel-innolux-p079zca.c         panel-samsung-s6e8aa0.c
    Kconfig                panel-jdi-lt070me05000.c        panel-sharp-lq101r1sx01.c
    Makefile               panel-lg-lg4573.c               panel-sharp-ls043t1le01.c
    modules.builtin        panel-lvds.c                    panel-simple.c
    modules.order          panel-panasonic-vvx10f034n00.c  panel-sitronix-st7789v.c
    panel-samsung-ld9040.c  panel-samsung-s6e3ha2.c
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    panel驱动文件主要是提供panel的一些操作函数,通过调用drm_panel_init生成drm_panel实例,然后调用drm_panel_add添加到DRM CORE中。

    在上述文件里面并没有找到特别适合我们平台的panel文件,然后在更高版本的kernel中有找到panel-arm-versatile.c,看注释描述比较符合,因此将该文件作为平台的panel驱动文件

    五、稍微修改panel驱动文件、connector驱动文件、设备树文件后,DRM就运行起来了。可以看到生成了card0节点:

    /sys/class/drm # ls
    card0        card0-DPI-1  version
    
    
    • 1
    • 2
    • 3

    使用图形界面运行,就发现可以正常显示linux图形界面了!

    qemu-system-arm -M vexpress-a9 -m 512M -kernel ../zImage -dtb ./vexpress-v2p-ca9.dtb -append "root=/dev/mmcblk0 rw init=/linuxrc" -sd /home/neo/work/a9rootfs.ext3
    
    • 1

    在这里插入图片描述

    附录:Doc in pl111_drv.c

    /**
     * DOC: ARM PrimeCell PL111 CLCD Driver
     *
     * The PL111 is a simple LCD controller that can support TFT and STN
     * displays.  This driver exposes a standard KMS interface for them.
     *
     * This driver uses the same Device Tree binding as the fbdev CLCD
     * driver.  While the fbdev driver supports panels that may be
     * connected to the CLCD internally to the CLCD driver, in DRM the
     * panels get split out to drivers/gpu/drm/panels/.  This means that,
     * in converting from using fbdev to using DRM, you also need to write
     * a panel driver (which may be as simple as an entry in
     * panel-simple.c).
     *
     * The driver currently doesn't expose the cursor.  The DRM API for
     * cursors requires support for 64x64 ARGB8888 cursor images, while
     * the hardware can only support 64x64 monochrome with masking
     * cursors.  While one could imagine trying to hack something together
     * to look at the ARGB8888 and program reasonable in monochrome, we
     * just don't expose the cursor at all instead, and leave cursor
     * support to the X11 software cursor layer.
     *
     * TODO:
     *
     * - Fix race between setting plane base address and getting IRQ for
     *   vsync firing the pageflip completion.
     *
     * - Expose the correct set of formats we can support based on the
     *   "arm,pl11x,tft-r0g0b0-pads" DT property.
     *
     * - Use the "max-memory-bandwidth" DT property to filter the
     *   supported formats.
     *
     * - Read back hardware state at boot to skip reprogramming the
     *   hardware when doing a no-op modeset.
     *
     * - Use the CLKSEL bit to support switching between the two external
     *   clock parents.
     */
    
    
    • 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
  • 相关阅读:
    第八章《Java高级语法》第10节:注解
    Java内部类(自用)
    SAP MM 为UB类型的STO执行VL10B,报错-没有项目类别表存在(表T184L NL 0002 V)-之对策
    JavaScript 66 JavaScript Async 66.4 JavaScript Async
    无业游民写的最后一个.net有关项目框架
    进销存仓库管理系统:规范数据、流程与管理
    【web开发】2、css基础
    leetcode:20. 有效的括号
    华为GAUSSDB集成
    GitKraken Pro安装
  • 原文地址:https://blog.csdn.net/cjianeng/article/details/126068293