1. 初始化Rockchip DRM/KMS框架
任务目标
在Rockchip平台(以RK3568为例)上编写一个最小DRM驱动模块,完成向DRM子系统的注册与注销,验证模块加载/卸载时驱动的bind与unbind回调被正确调用。
环境依赖
- Linux内核源码树(版本4.19或5.10,Rockchip SDK内核)
- 交叉编译工具链(aarch64-linux-gnu-)
- 目标板:RK3568 EVB或类似平台,内核已开启
CONFIG_DRM与CONFIG_DRM_ROCKCHIP
核心实现
驱动通过platform_driver匹配设备树节点,在probe中调用drm_dev_alloc分配DRM设备并注册到DRM子系统。使用component框架与Rockchip DRM主设备协同工作,这是Rockchip平台DRM驱动的标准接入方式。
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/component.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_print.h>
static int demo_drm_bind(struct device *dev)
{
struct drm_device *drm;
int ret;
drm = drm_dev_alloc(NULL, dev);
if (IS_ERR(drm))
return PTR_ERR(drm);
/* 设置最小DRM驱动能力:仅支持PRIME内存管理 */
drm->driver = kzalloc(sizeof(struct drm_driver), GFP_KERNEL);
if (!drm->driver) {
drm_dev_put(drm);
return -ENOMEM;
}
drm->driver->prime_fd_to_handle = drm_gem_prime_fd_to_handle;
drm->driver->gem_prime_handle_to_fd = drm_gem_prime_handle_to_fd;
ret = drm_dev_register(drm, 0);
if (ret) {
kfree(drm->driver);
drm_dev_put(drm);
return ret;
}
dev_set_drvdata(dev, drm);
drm_info(drm, "Rockchip DRM demo driver registered\n");
return 0;
}
static void demo_drm_unbind(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
drm_dev_unregister(drm);
kfree(drm->driver);
drm_dev_put(drm);
dev_set_drvdata(dev, NULL);
}
static const struct component_ops demo_drm_ops = {
.bind = demo_drm_bind,
.unbind = demo_drm_unbind,
};
static int demo_drm_probe(struct platform_device *pdev)
{
return component_add(&pdev->dev, &demo_drm_ops);
}
static int demo_drm_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &demo_drm_ops);
return 0;
}
static const struct of_device_id demo_drm_of_match[] = {
{ .compatible = "rockchip,drm-demo" },
{ }
};
MODULE_DEVICE_TABLE(of, demo_drm_of_match);
static struct platform_driver demo_drm_platform_driver = {
.probe = demo_drm_probe,
.remove = demo_drm_remove,
.driver = {
.name = "rockchip-drm-demo",
.of_match_table = demo_drm_of_match,
},
};
module_platform_driver(demo_drm_platform_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("DRM Demo");
MODULE_DESCRIPTION("Rockchip DRM minimal init/cleanup demo");
设备树节点
在目标板设备树中追加以下节点,使驱动能够匹配并绑定:
&drm_demo {
status = "okay";
};
/ {
drm_demo: drm-demo {
compatible = "rockchip,drm-demo";
status = "disabled";
};
};
编译与安装
# 将源码放入 drivers/gpu/drm/rockchip/drm-demo.c
# 在 drivers/gpu/drm/rockchip/Makefile 中添加:
# obj-$(CONFIG_DRM_ROCKCHIP) += drm-demo.o
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image dtbs
# 将内核与dtb烧录至目标板后重启
验证方法
- 模块加载后执行
dmesg | grep "drm-demo",应看到Rockchip DRM demo driver registered日志,说明bind回调成功执行且DRM设备已注册。 - 执行
ls /sys/class/drm/,若注册成功,会出现新的card节点(如card0或card1),且cat /sys/class/drm/cardX/device/uevent中DRIVER=rockchip-drm-demo。 - 卸载模块(
rmmod drm_demo)后再次执行dmesg,确认无错误信息,且对应card节点消失,说明unbind清理路径正确。
通过条件:上述三条均满足,且系统无内核崩溃或内存泄漏警告。