1. 初始化DRM设备驱动框架
任务目标
编写一个最小DRM驱动,完成以下闭环:注册platform_driver,在probe回调中初始化DRM设备并注册,实现基本的open/close回调。驱动加载后,用户空间可通过/dev/dri/card0访问设备节点。
环境与依赖
- Linux内核源码树(本文以5.15版本为例)
- 内核配置启用DRM:
CONFIG_DRM=y或=m
- 编译所需头文件:
drm/drm_device.h、drm/drm_drv.h、drm/drm_file.h
完整实现
创建文件minidrm.c,代码如下:
```c
#include
#include
#include
#include
#include
static int minidrm_open(struct drm_device *dev, struct drm_file *file)
{
/* 最小实现:仅返回成功,可在此分配文件级私有数据 */
return 0;
}
static void minidrm_close(struct drm_device *dev, struct drm_file *file)
{
/* 最小实现:释放文件级私有数据(如有) */
}
static const struct drm_driver minidrm_driver = {
.driver_features = DRIVER_GEM,
.open = minidrm_open,
.close = minidrm_close,
.name = "minidrm",
.desc = "Minimal DRM driver",
.major = 1,
.minor = 0,
};
static int minidrm_probe(struct platform_device *pdev)
{
struct drm_device *drm;
int ret;
drm = drm_dev_alloc(&minidrm_driver, &pdev->dev);
if (IS_ERR(drm))
return PTR_ERR(drm);
platform_set_drvdata(pdev, drm);
ret = drm_dev_register(drm, 0);
if (ret)
goto err_free;
dev_info(&pdev->dev, "minidrm registered\n");
return 0;
err_free:
drm_dev_put(drm);
return ret;
}
static int minidrm_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 platform_device_id minidrm_id_table[] = {
{ .name = "minidrm" },
{ }
};
MODULE_DEVICE_TABLE(platform, minidrm_id_table);
static struct platform_driver minidrm_platform_driver = {
.probe = minidrm_probe,
.remove = minidrm_remove,
.id_table = minidrm_id_table,
.driver = {
.name = "minidrm",
},
};
module_platform_driver(minidrm_platform_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Minimal DRM platform driver");
```
编译与加载
创建Makefile:
```makefile
obj-m += minidrm.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
```
编译并加载:
```bash
make
sudo insmod minidrm.ko
# 绑定platform设备(若设备树未定义,需手动创建)
echo "minidrm" | sudo tee /sys/bus/platform/drivers/minidrm/bind
```
若设备树中已定义compatible = "minidrm"节点,则probe会自动触发,无需手动bind。
验证方法
- 驱动加载:执行
dmesg | tail,应看到minidrm registered日志。
- 设备节点:执行
ls -l /dev/dri/,应出现card0节点。
- open/close验证:执行以下命令,若返回
0且无错误输出,说明open/close回调正常工作:
```bash
sudo cat /dev/dri/card0 > /dev/null
echo "exit code: $?"
```
通过条件:以上三步全部成功,即驱动注册、设备节点创建、文件操作回调均正常。
常见问题
- insmod报错
Unknown symbol:确认内核已启用DRM核心(CONFIG_DRM),且版本与编译头文件一致。
- bind失败:确认platform设备名称与
id_table中.name一致,或设备树节点compatible属性匹配驱动driver.name。
- 打开设备节点返回
ENODEV:检查drm_dev_register是否成功,以及driver_features是否包含必要特性(如DRIVER_GEM)。