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):
Linux图形显示DRM子系统环境实践_第1张图片
但是我们需要的是用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>;
                        };
                };
        };

三、在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

在内核配置中配置DRM系统和PL111 DRM驱动
Linux图形显示DRM子系统环境实践_第2张图片

四、完成上述的配置并运行后,发现并没有生成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

看样子是没有找到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

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

使用图形界面运行,就发现可以正常显示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

Linux图形显示DRM子系统环境实践_第3张图片

附录: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.
 */

你可能感兴趣的:(DRM,DRM,KMS,QEMU)