3. CRTC初始化与模式设置
任务目标
在Linux DRM子系统中,CRTC(Cathode Ray Tube Controller)负责将帧缓冲扫描输出到显示器。本案例实现一个最小可用的CRTC初始化流程:创建drm_crtc实例,并实现其mode_set与atomic_check回调,使CRTC能够被DRM核心正确注册并参与模式配置。
核心实现
#include <drm/drm_crtc.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_modeset_helper.h>
/* mode_set回调:在CRTC模式切换时被调用,负责设置显示时序 */
static int my_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *old_fb)
{
/* 实际硬件驱动在此配置CRTC寄存器(时序参数、分辨率等)
* 本例为最小实现,仅记录模式信息供验证 */
drm_mode_copy(&crtc->state->mode, mode);
return 0;
}
/* atomic_check回调:验证CRTC状态变更的合法性 */
static int my_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
if (!crtc_state)
return 0;
/* 检查:若CRTC使能,则必须有有效的显示模式 */
if (crtc_state->enable && !drm_mode_valid(crtc_state->mode)) {
DRM_DEBUG_ATOMIC("CRTC %d: enable with invalid mode\n", crtc->base.id);
return -EINVAL;
}
return 0;
}
/* CRTC辅助回调结构 */
static const struct drm_crtc_helper_funcs my_crtc_helper_funcs = {
.mode_set = my_crtc_mode_set,
.atomic_check = my_crtc_atomic_check,
};
/* CRTC核心回调结构 */
static const struct drm_crtc_funcs my_crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset,
.destroy = drm_crtc_cleanup,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
};
/* CRTC初始化入口 */
int my_crtc_init(struct drm_device *dev)
{
struct drm_crtc *crtc;
int ret;
crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
if (!crtc)
return -ENOMEM;
/* 创建CRTC实例,index=0表示第一个CRTC */
ret = drm_crtc_init_with_planes(dev, crtc, NULL, NULL,
&my_crtc_funcs, NULL);
if (ret) {
kfree(crtc);
return ret;
}
/* 挂载辅助回调 */
drm_crtc_helper_add(crtc, &my_crtc_helper_funcs);
DRM_INFO("CRTC initialized (id=%u)\n", crtc->base.id);
return 0;
}
集成与依赖
上述代码需嵌入你的DRM驱动中。在驱动的bind或load函数内调用my_crtc_init(dev)即可完成CRTC注册。依赖内核配置开启CONFIG_DRM与CONFIG_DRM_KMS_HELPER。若驱动使用atomic接口,还需在drm_mode_config中设置.atomic = true。
验证方法
- 编译验证:驱动模块成功编译且加载无报错,dmesg中出现
CRTC initialized (id=0)日志。 - 状态查询:加载后执行
modetest -c(需安装libdrm测试工具),输出中应包含CRTC列表,且状态为"ok"。 - atomic_check验证:使用
modetest -s <connector_id>:<mode>设置显示模式。若设置非法分辨率(如超出硬件范围),命令应失败并返回Invalid argument,dmesg中出现enable with invalid mode调试信息。 - mode_set验证:成功设置模式后,通过
cat /sys/kernel/debug/dri/0/state查看CRTC状态,确认mode字段与设置值一致。
通过标准:CRTC成功注册、合法模式可正常设置、非法模式被atomic_check拒绝,且无内核错误日志。