本系列文章基于linux 5.15
一、drm_core_init
执行一些drm core的初始化工作
static int __init drm_core_init(void)
{int ret;drm_connector_ida_init();idr_init(&drm_minors_idr);drm_memcpy_init_early();ret = drm_sysfs_init();if (ret < 0) {DRM_ERROR("Cannot create DRM class: %d\n", ret);goto error;}/*在/sys/kernel/debug/下创建dri目录*/drm_debugfs_root = debugfs_create_dir("dri", NULL);/*为drm申请主设备号,这里是DRM_MAJOR*/ret = register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops);if (ret < 0)goto error;drm_core_init_complete = true;DRM_DEBUG("Initialized\n");return 0;error:drm_core_exit();return ret;
}
1.drm_connector_ida_init
为每个连接器类型分配一个独立的 IDA,IDA(ID Allocator,ID 分配器) 是一种用于分配和管理唯一 ID 的机制,通常用于内核中需要分配唯一标识符的场景。其好处是:内核开发者可以方便地管理唯一 ID 的分配和释放,从而避免 ID 冲突和资源浪费。
static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {{ DRM_MODE_CONNECTOR_Unknown, "Unknown" },{ DRM_MODE_CONNECTOR_VGA, "VGA" },{ DRM_MODE_CONNECTOR_DVII, "DVI-I" },{ DRM_MODE_CONNECTOR_DVID, "DVI-D" },{ DRM_MODE_CONNECTOR_DVIA, "DVI-A" },{ DRM_MODE_CONNECTOR_Composite, "Composite" },{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },{ DRM_MODE_CONNECTOR_LVDS, "LVDS" },{ DRM_MODE_CONNECTOR_Component, "Component" },{ DRM_MODE_CONNECTOR_9PinDIN, "DIN" },{ DRM_MODE_CONNECTOR_DisplayPort, "DP" },{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },{ DRM_MODE_CONNECTOR_TV, "TV" },{ DRM_MODE_CONNECTOR_eDP, "eDP" },{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },{ DRM_MODE_CONNECTOR_DSI, "DSI" },{ DRM_MODE_CONNECTOR_DPI, "DPI" },{ DRM_MODE_CONNECTOR_WRITEBACK, "Writeback" },{ DRM_MODE_CONNECTOR_SPI, "SPI" },{ DRM_MODE_CONNECTOR_USB, "USB" },
};void drm_connector_ida_init(void)
{int i;for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)ida_init(&drm_connector_enum_list[i].ida);
}
2.drm_sysfs_init
创建class类drm_class,同时会在/sys/class/目录下创建一个新的文件夹drm,并设置设备节点
int drm_sysfs_init(void)
{int err;
/*创建设备类,此函数的执行会在/sys/class/目录下创建一个新的文件夹drm*/drm_class = class_create(THIS_MODULE, "drm");if (IS_ERR(drm_class))return PTR_ERR(drm_class);err = class_create_file(drm_class, &class_attr_version.attr);if (err) {class_destroy(drm_class);drm_class = NULL;return err;}/*设置设备节点*/drm_class->devnode = drm_devnode;return 0;
}
2.1 drm_devnode
在/sys/class/drm下创建节点,例如/sys/class/drm/dri/card0、/sys/class/drm/dri/card1
static char *drm_devnode(struct device *dev, umode_t *mode)
{return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
}
二、drm_core_exit
针对drm_core_init做的一些注销工作
static void drm_core_exit(void)
{unregister_chrdev(DRM_MAJOR, "drm");debugfs_remove(drm_debugfs_root);drm_sysfs_destroy();idr_destroy(&drm_minors_idr);drm_connector_ida_destroy();
}