1. 初始化DRM设备并注册驱动
任务目标
编写一个最小可用的DRM驱动模块,完成平台设备的初始化和DRM驱动的注册,使得系统在加载模块后能够在/dev/dri/card0创建设备节点。该驱动不实现具体的显示输出功能,仅验证DRM子系统的基础框架能够正确挂载。
环境与依赖
- Linux内核源码树(版本 ≥ 4.19,本文以5.10为例)
- 内核已开启
CONFIG_DRM=y或CONFIG_DRM=m - 目标平台:QEMU virt或任何支持DRM的设备模拟环境
核心实现
驱动通过platform_driver匹配一个虚拟平台设备,在probe回调中调用drm_dev_alloc分配DRM设备结构体,设置最小化的drm_driver回调集合,然后注册drm_dev。由于不涉及具体硬件,无需实现irq_handler或fops中的复杂操作。
// minimal_drm.c
#include <linux/module.h>
#include <linux/platform_device.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_print.h>
static int min_drm_open(struct drm_device *dev, struct drm_file *file)
{
return 0;
}
static void min_drm_release(struct drm_device *dev, struct drm_file *file)
{
}
static const struct drm_driver min_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_RENDER,
.open = min_drm_open,
.release = min_drm_release,
.name = "minimal_drm",
.desc = "Minimal DRM driver for device registration",
.major = 1,
.minor = 0,
};
static int min_drm_probe(struct platform_device *pdev)
{
struct drm_device *drm;
int ret;
drm = drm_dev_alloc(&min_drm_driver, &pdev->dev);
if (IS_ERR(drm))
return PTR_ERR(drm);
platform_set_drvdata(pdev, drm);
ret = drm_dev_register(drm, 0);
if (ret < 0) {
drm_dev_put(drm);
return ret;
}
drm_info(drm, "minimal DRM device registered\n");
return 0;
}
static int min_drm_remove(struct platform_device *pdev)
{
struct drm_device *drm = platform_get_drvdata(pdev);
drm_dev_unregister(drm);
drm_dev_put(drm);
return 0;
}
static const struct of_device_id min_drm_of_match[] = {
{ .compatible = "virtual,minimal-drm" },
{ }
};
MODULE_DEVICE_TABLE(of, min_drm_of_match);
static struct platform_driver min_drm_platform_driver = {
.probe = min_drm_probe,
.remove = min_drm_remove,
.driver = {
.name = "minimal_drm",
.of_match_table = min_drm_of_match,
},
};
module_platform_driver(min_drm_platform_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("DRM Course");
MODULE_DESCRIPTION("Minimal DRM driver for device node creation");
设备树节点(QEMU virt平台)
// 在qemu virt设备树中追加(或使用dtb overlay)
minimal-drm {
compatible = "virtual,minimal-drm";
status = "okay";
};
编译与加载
# 编译为内核模块
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
# 加载模块
insmod minimal_drm.ko
# 验证设备节点
ls -l /dev/dri/card0
验证方法与通过条件
- 模块加载:
insmod无报错,dmesg尾部出现minimal DRM device registered。 - 设备节点:执行
ls -l /dev/dri/card0,确认存在字符设备节点,主设备号为226(DRM_MAJOR),次设备号为0。 - 模块卸载:
rmmod minimal_drm后/dev/dri/card0消失,无内核错误。
若设备节点未出现,检查设备树节点是否被正确匹配(dmesg中是否有platform minimal-drm: Driver minimal_drm requests probe deferral),以及内核是否启用了DRM子系统。