一、MTK KMS分析
mtk_drm_kms_init 函数分析
mtk_drm_kms_init 是 MediaTek DRM 驱动程序中的一个静态函数(static int mtk_drm_kms_init(struct drm_device *drm)),位于 mtk_drm_drv.c 文件中。该函数的主要作用是初始化 DRM 设备的 Kernel Mode Setting (KMS) 子系统,包括配置显示模式、绑定硬件组件、创建 CRTC(Controller)、设置 DMA 参数、初始化各种辅助结构和工作队列等。它是驱动从硬件抽象层过渡到 DRM 框架的核心入口点,通常在组件绑定(component_bind_all)后调用,确保显示管道(display pipeline)准备就绪,支持用户空间的图形渲染和模式设置。
函数的输入是一个已分配的 drm_device 结构(包含 MediaTek 特定的私有数据 mtk_drm_private)。输出为 0(成功)或负错误码(失败)。整个函数逻辑严谨,包含多个错误处理路径(使用 goto 跳转清理资源)。下面我基于提供的代码,按步骤详细分析其执行流程、关键操作和潜在逻辑。
1. 准备阶段:获取私有数据和检查依赖
struct mtk_drm_private *private = drm->dev_private;
从 drm_device 中提取 MediaTek 特定的私有数据结构 mtk_drm_private,其中包含设备树节点、寄存器映射、helper_opt 等信息(这些在 mtk_drm_probe 中已初始化)。
检查 M4U (Memory Management Unit) 支持:
if (mtk_drm_helper_get_opt(private->helper_opt, MTK_DRM_OPT_USE_M4U)) { … }
如果启用 M4U(IOMMU 相关的内存管理选项),检查 IOMMU 是否就绪(iommu_present(&platform_bus_type))。如果 IOMMU 未准备好,返回 -EPROBE_DEFER,延迟驱动探测(probe),等待 IOMMU 驱动加载。这确保了 DMA 内存分配的安全性和连续性(防止内存碎片)。
日志记录:DDPINFO(“%s+
“, __func__); – 输出调试信息,表示函数开始。
2. 初始化 DRM Mode Config
drm_mode_config_init(drm);
初始化 DRM 的模式配置结构(drm_mode_config),设置默认的模式设置回调(如 atomic_check、atomic_commit),启用原子模式设置支持。
设置默认分辨率限制:
drm->mode_config.min_width = 1; drm->mode_config.min_height = 1;
最小分辨率设置为 1×1(默认最小值,避免无效模式)。
drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096;
最大分辨率设置为 4096×4096(默认值,用于检查帧缓冲区大小限制,在 drm_mode_addfb 中使用)。
设置模式配置函数:drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
关联 MediaTek 特定的模式配置函数(未在代码中显示,但可能是自定义的页面翻转、属性处理等)。
3. 绑定组件和初始化 VBlank
ret = component_bind_all(drm->dev, drm);
绑定所有显示组件(通过 mtk_drm_ops 中的 bind 函数),这些组件在 mtk_drm_probe 中已添加到 match 列表中(如 OVL、RDMA、DSI 等)。如果绑定失败,跳转到 err_config_cleanup 清理 mode config。
ret = drm_vblank_init(drm, MAX_CRTC);
初始化 VBlank(垂直同步)支持,最多支持 MAX_CRTC 个 CRTC(通常为 3 或 4,根据 SoC)。VBlank 用于同步帧渲染和显示,避免撕裂(tearing)。失败则跳转到 err_component_unbind 解绑组件。
4. 创建 CRTC(显示控制器)
ret = mtk_drm_crtc_create(drm, private->data->main_path_data);
创建主路径 CRTC(OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 等)。main_path_data 来自 SoC 特定的数据(如 mt6885_mmsys_driver_data)。
根据设备树属性和阶段(disp_helper_get_stage())创建扩展路径:
如果是正常阶段(DISP_HELPER_STAGE_NORMAL):
检查 “enable_ext_alter_path” 属性,如果启用,使用 ext_alter_path_data 创建扩展路径 CRTC(OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0)。否则,使用 ext_path_data。
创建第三个 CRTC(third_path_data 或变体,根据 “condition-num” 属性调整路径,如是否包含 TDSHP)。创建第四个 CRTC(如果启用 “enable_secondary_path” 或 “enable_discrete_path”,使用 fourth_path_data_secondary 或 fourth_path_data_discrete)。
这些 CRTC 代表不同的显示管道,支持多屏输出(如主屏、扩展屏)。失败则跳转到 err_component_unbind。注释:/*TODO: Need to check path rule*/ – 表示路径规则检查待实现,可能涉及硬件兼容性。
5. 设置 DMA 和内存分配
选择 OVL 设备作为 DMA 分配设备:
从主路径或扩展路径的第一个组件节点获取 OVL 设备(private->comp_node[…])。private->dma_dev = &pdev->dev;
使用 OVL 设备进行所有 DMA 内存分配,确保连续 IOVA(IO Virtual Address)用于 PRIME 缓冲区导入。
配置 DMA 参数:
如果 dma_dev->dma_parms 未分配,动态分配(devm_kzalloc)。ret = dma_set_max_seg_size(dma_dev, (unsigned int)DMA_BIT_MASK(32));
设置 DMA 段最大大小为 32-bit(4GB),确保 PRIME 缓冲区导入时的连续性。
失败则清理并返回。
drm_mode_config_reset(drm);
重置模式配置到默认状态。
6. 初始化工作队列、列表和互斥锁
INIT_WORK(&private->unreference.work, mtk_unreference_work);
初始化 unreference work,用于异步释放原子状态(参考 mtk_unreference_work 函数)。
INIT_LIST_HEAD(&private->unreference.list); INIT_LIST_HEAD(&private->lyeblob_head);
初始化 unreference 和 lyeblob 链表。
spin_lock_init(&private->unreference.lock); mutex_init(&private->commit.lock); mutex_init(&private->lyeblob_list_mutex);
初始化自旋锁和互斥锁,用于保护 unreference 和 commit 操作。
重绘数据初始化:
init_waitqueue_head(&private->repaint_data.wq); INIT_LIST_HEAD(&private->repaint_data.job_queue); INIT_LIST_HEAD(&private->repaint_data.job_pool);
初始化等待队列和作业链表,用于处理重绘事件。
原子变量初始化:
for (i = 0; i < MAX_CRTC ; ++i) { atomic_set(&private->crtc_present[i], 0); atomic_set(&private->crtc_rel_present[i], 0); }
重置 CRTC 存在状态。
atomic_set(&private->rollback_all, 0);
重置回滚标志。
7. 初始化调试和辅助模块
#ifdef CONFIG_DRM_MEDIATEK_DEBUG_FS mtk_drm_debugfs_init(drm, private); #endif
如果启用 debugfs,初始化 MediaTek 特定的 debugfs 节点(用于 sysfs 调试,如寄存器 dump)。
disp_dbg_init(drm); PanelMaster_Init(drm);
初始化显示调试和 PanelMaster(面板管理模块)。
OPLUS 特性初始化(特定于 OPLUS 设备):
#ifdef OPLUS_FEATURE_DISPLAY_ADFR if (oplus_adfr_is_support()) { oplus_adfr_init(drm, private); } #endif
初始化 ADFR(Adaptive Frame Rate?)支持。
#ifdef OPLUS_FEATURE_DISPLAY_ONSCREENFINGERPRINT oplus_ofp_init(private); #endif
初始化屏幕指纹(On-Screen Fingerprint)支持。
MMDVFS 初始化:if (mtk_drm_helper_get_opt(private->helper_opt, MTK_DRM_OPT_MMDVFS_SUPPORT)) mtk_drm_mmdvfs_init(drm->dev);
如果启用 MMDVFS(Multi-Media Dynamic Voltage Frequency Scaling),初始化动态电压频率调整,支持功耗优化。
8. 最终初始化和清理
mtk_drm_init_dummy_table(private);
初始化 dummy table(可能是用于测试或 fallback 的虚拟表)。
mtk_drm_first_enable(drm);
首次启用 DRM 设备,激活显示管道。
mtk_smi_init_power_off();
初始化 SMI(System Memory Interface)电源关闭逻辑,注释说明:在内核初始化时 SMI larb 会保持 MTCMOS on,然后由显示模块自行管理电源。
日志记录:DDPINFO(“%s-
“, __func__); – 表示函数结束。
9. 错误处理路径
使用 goto 标签处理错误:
err_unset_dma_parms:如果 DMA 参数设置失败,清理 dma_parms。put_dma_dev:释放 DMA 设备引用。err_component_unbind:解绑所有组件。err_config_cleanup:清理 mode config。
确保资源泄漏最小化(如使用 devm_kzalloc 自动释放)。
10. 总体作用和注意事项
核心功能:桥接硬件组件到 DRM 框架,支持多 CRTC、多路径显示管道、原子操作和低功耗模式。性能/兼容性:依赖设备树(DT)属性(如 “enable_ext_alter_path”),针对不同 SoC(如 MT6885、MT6983)优化。双/四管道支持用于高分辨率或多屏。扩展性:支持 OPLUS 自定义特性(如 ADFR、指纹),和调试工具(如 debugfs)。潜在问题:如果 DT 节点缺失,可能导致 CRTC 创建失败。DMA 设置确保 32-bit 地址空间兼容,但高分辨率下可能需调整。调用关系:通常从 mtk_drm_bind 调用(未显示),在 probe 后执行。
二、DRM mode atomic接口实现
static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
.fb_create = mtk_drm_mode_fb_create,
.atomic_check = mtk_atomic_check,
.atomic_commit = mtk_atomic_commit,
.atomic_state_alloc = mtk_drm_atomic_state_alloc,
.atomic_state_free = mtk_atomic_state_put,
};
mtk_drm_mode_config_funcs 是一个静态的 drm_mode_config_funcs 结构,定义在 MediaTek DRM 驱动中(如 mtk_drm_drv.c 文件),用于向 DRM 核心框架注册 MediaTek 特定的模式配置回调函数。这些回调函数处理与 DRM 设备的显示模式设置(KMS, Kernel Mode Setting)相关的核心操作,包括帧缓冲区(framebuffer)创建、原子状态检查和提交等。以下是对 mtk_drm_mode_config_funcs 中每个接口的详细分析,说明其作用和功能。
1. .fb_create = mtk_drm_mode_fb_create
作用:负责创建 DRM 帧缓冲区(framebuffer),将用户空间传递的缓冲区对象(如 GEM 对象或 DMA 缓冲区)封装为 DRM 的 drm_framebuffer 结构。功能:
当用户空间调用 DRM_IOCTL_MODE_ADDFB 或 DRM_IOCTL_MODE_ADDFB2 时,DRM 核心会调用此函数。它验证用户提供的帧缓冲区参数(如宽度、高度、像素格式、pitch 等),并确保它们符合硬件限制(如最大分辨率 4096×4096,参考 mtk_drm_kms_init 中的 max_width 和 max_height)。分配并初始化 drm_framebuffer 结构,关联到对应的 GEM 对象(MediaTek 使用 mtk_drm_gem 管理缓冲区)。如果启用了 M4U(IOMMU),可能涉及将用户空间的 DMA 缓冲区映射到硬件可访问的 IOVA(IO Virtual Address)。
典型流程:
检查输入参数(如分辨率、格式)。调用 mtk_drm_gem_object 或 drm_gem_cma_helper 相关函数来获取缓冲区对象。设置帧缓冲区的元数据(如 drm_framebuffer 的 width、height、format)。返回创建的帧缓冲区对象或错误码(如 -EINVAL)。
使用场景:用户空间(如 Wayland 或 X11 合成器)请求创建帧缓冲区,用于渲染和显示内容。
2. .atomic_check = mtk_atomic_check
作用:在原子模式设置(atomic mode setting)中,检查用户请求的显示状态更改是否有效。功能:
原子模式设置是 DRM 的现代接口,允许用户空间通过 DRM_IOCTL_MODE_ATOMIC 一次性提交多个显示状态更改(如 CRTC、plane、connector 的属性)。mtk_atomic_check 验证这些更改是否符合硬件限制和驱动逻辑,例如:
检查 CRTC 的模式(如分辨率、刷新率)是否被硬件支持。验证 plane 的配置(如缩放、位置、格式,参考 mtk_atomic_disp_rsz_roi)。检查安全状态(mtk_atomic_check_plane_sec_state),确保 secure buffer 的正确处理。计算启用的 plane 数量(mtk_atomic_calculate_plane_enabled_number)。对于双管道(dual pipe)场景,检查缩放参数(mtk_atomic_rsz_calc_dual_params)。
如果检查通过,返回 0;否则返回错误码(如 -EINVAL),阻止无效配置提交。
典型流程:
遍历 drm_atomic_state 中的 CRTC、plane 和 connector 状态。调用 MediaTek 特定的辅助函数(如 mtk_plane_get_comp_state)检查硬件兼容性。更新 mtk_crtc_state 中的扩展属性(如 rsz_src_roi、rsz_dst_roi)。
使用场景:在用户空间提交原子更新(如切换分辨率、调整 plane 大小)前,确保配置合法。
3. .atomic_commit = mtk_atomic_commit
作用:执行通过 atomic_check 验证的原子状态更新,将配置应用到硬件。功能:
将用户请求的显示状态(drm_atomic_state)应用到硬件,更新 CRTC、plane 和 connector。支持同步或异步提交(通过 DRM_ATOMIC_NONBLOCK 标志)。调用 MediaTek 特定的函数来配置硬件,例如:
更新 plane 的位置、格式或缓冲区(通过 mtk_ddp_comp 相关函数)。配置 CRTC 的显示模式(调用 mtk_crtc_change_output_mode)。处理低功耗模式(doze/AOD,参考 mtk_atomic_doze_update_dsi_state)。触发硬件同步(如 VBlank,调用 mtk_drm_enable_trig)。
使用 CMDQ(Command Queue,参考 mtk_crtc_pkt_create)提交硬件命令,确保高效的硬件配置。如果涉及低功耗模式(如 AOD),可能调用 mtk_atomic_aod_scp_ipi 与 SCP(System Control Processor)交互。
典型流程:
调用 mtk_atomic_wait_for_fences 等待 fence 完成(确保缓冲区就绪)。配置硬件(如通过 cmdq_pkt 设置寄存器)。提交 VBlank 事件或触发显示更新。如果异步,调用 mtk_atomic_schedule 安排工作队列处理。
使用场景:用户空间确认原子更新后,驱动将配置写入硬件,完成显示更新。
4. .atomic_state_alloc = mtk_drm_atomic_state_alloc
作用:分配一个新的原子状态对象(drm_atomic_state)供原子模式设置使用。功能:
创建一个 MediaTek 特定的原子状态结构(mtk_atomic_state),扩展了 drm_atomic_state。初始化 mtk_atomic_state 的私有字段(如 kref 用于引用计数,参考 to_mtk_state)。返回分配的状态对象,供 atomic_check 和 atomic_commit 使用。
典型流程:
使用 kzalloc 分配 mtk_atomic_state。初始化 drm_atomic_state 的基类字段。设置引用计数(kref_init)。
使用场景:在原子操作开始时,分配状态对象以跟踪用户请求的更改。
5. .atomic_state_free = mtk_atomic_state_put
作用:释放原子状态对象,清理相关资源。功能:
释放通过 mtk_drm_atomic_state_alloc 创建的 mtk_atomic_state 对象。使用引用计数(kref_put)确保安全释放(参考 mtk_atomic_state_free)。如果状态对象被加入 unreference 队列(mtk_atomic_state_put_queue),异步释放(通过 mtk_unreference_work)。清理 drm_atomic_state 的基类字段(drm_atomic_state_clear 和 drm_atomic_state_default_release)。
典型流程:
减少 kref 计数。如果计数为 0,调用 kfree 释放 mtk_atomic_state。如果在 unreference 队列中,移出列表并释放。
使用场景:在原子操作完成后,清理不再需要的状态对象,避免内存泄漏。
总体作用和上下文
mtk_drm_mode_config_funcs 是 MediaTek DRM 驱动与 DRM 核心交互的关键接口,定义在 drm_mode_config 中(通过 mtk_drm_kms_init 中的 drm->mode_config.funcs = &mtk_drm_mode_config_funcs 设置)。这些函数共同实现 DRM 的 KMS 功能,支持:
帧缓冲区管理:创建和管理帧缓冲区(fb_create)。原子模式设置:验证和提交显示配置(atomic_check 和 atomic_commit)。状态管理:分配和释放原子状态(atomic_state_alloc 和 atomic_state_free)。
MediaTek 特定特性:
支持双管道(dual pipe)缩放(mtk_atomic_rsz_calc_dual_params)。处理低功耗模式(doze/AOD,参考 mtk_atomic_doze_update_dsi_state)。集成 CMDQ 进行高效硬件配置。支持 secure buffer 和 OPLUS 特定功能(如 ADFR、屏幕指纹)。
调用关系:
在 mtk_drm_kms_init 中注册,供 DRM 核心在处理用户空间请求时调用。与 mtk_drm_private 和 mtk_drm_crtc 等结构密切协作,依赖硬件组件(如 OVL、RDMA、DSI)。
潜在注意事项
性能:atomic_commit 使用 CMDQ 提交硬件命令,需确保命令队列效率,避免延迟。兼容性:函数需适配不同 SoC(如 MT6885、MT6983),依赖设备树正确配置。错误处理:atomic_check 必须严格验证配置,避免硬件配置错误导致显示异常。调试:结合 DDPINFO 和 debugfs(如 mtk_drm_debugfs_init)可跟踪函数执行。
三、component注册
ret = component_master_add_with_match(dev, &mtk_drm_ops, match); 出现在 MediaTek DRM 驱动程序的上下文中,通常位于 mtk_drm_probe 函数中(mtk_drm_drv.c 文件)。它用于将 MediaTek DRM 驱动注册为一个组件主设备(component master),并通过匹配机制绑定相关的子组件(如显示硬件模块:OVL、RDMA、DSI 等)。下面详细分析这行代码的含义、作用和执行逻辑。
1. 代码上下文
文件:mtk_drm_drv.c,MediaTek DRM 驱动的核心文件。函数:通常在 mtk_drm_probe 中调用,作为驱动探测(probe)阶段的一部分。目的:初始化 DRM 设备并绑定硬件组件,确保显示管道(display pipeline)能够协同工作。
这行代码是 Linux 内核组件框架(component.h)的一部分,用于管理主设备与多个子组件之间的绑定关系。MediaTek DRM 驱动使用组件框架来协调复杂的显示硬件模块(如 Overlay、RDMA、DSI、DPI 等),这些模块通常由独立的设备树节点描述。
2. 代码分解
让我们逐部分解析这行代码:
ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
ret:
整型返回值,用于存储函数执行结果。成功时返回 0,失败时返回负错误码(如 -ENOMEM、-EINVAL、-EPROBE_DEFER)。
component_master_add_with_match:
Linux 内核组件框架提供的函数,定义在 include/linux/component.h 和 drivers/base/component.c 中。功能:注册一个主设备(master),并通过匹配机制(match)绑定相关的子组件。原型:
int component_master_add_with_match(struct device *dev,
const struct component_master_ops *ops,
struct component_match *match);
参数:
dev:主设备的 struct device 指针,表示 DRM 设备(通常是 platform device)。ops:主设备的操作回调函数(mtk_drm_ops),定义了绑定和解绑逻辑。match:组件匹配规则,描述需要绑定的子组件。
dev:
主设备的设备结构,通常是 struct platform_device 的 dev 字段。在 mtk_drm_probe 中,dev 通常由 platform_get_device 获取,代表 DRM 驱动的主设备节点(如 mediatek,drm)。
&mtk_drm_ops:
指向 MediaTek DRM 驱动定义的组件操作结构(struct component_master_ops)。示例定义(可能在 mtk_drm_drv.c 中):
static const struct component_master_ops mtk_drm_ops = {
.bind = mtk_drm_bind,
.unbind = mtk_drm_unbind,
};
.bind:当所有子组件匹配并准备好后,调用 mtk_drm_bind 初始化 DRM 设备(如调用 mtk_drm_kms_init)。.unbind:在设备移除或驱动卸载时,调用 mtk_drm_unbind 清理资源。
match:
类型为 struct component_match *,定义了需要绑定的子组件列表。在 mtk_drm_probe 中,match 通过 component_match_add 或 component_match_add_typed 填充,包含设备树中描述的子组件(如 OVL、RDMA、DSI 等)。示例(mtk_drm_probe 中可能出现的代码):
struct component_match *match = NULL;
component_match_add(dev, &match, component_compare_of, of_node);
component_match_add 添加子组件的匹配规则,基于设备树节点(of_node)或比较函数(如 component_compare_of)。
3. 函数作用
component_master_add_with_match 的主要作用是将 DRM 驱动注册为主设备,并等待所有必要的子组件(显示模块)准备好后调用 mtk_drm_bind 函数。其工作流程如下:
注册主设备:
将 dev(DRM 设备)注册为组件框架的主设备。关联 mtk_drm_ops,指定绑定和解绑回调。
匹配子组件:
使用 match 结构中的规则,查找并匹配设备树中定义的子组件(如 mediatek,ovl、mediatek,rdma、mediatek,dsi)。每个子组件对应一个 struct device(通常也是 platform device),由设备树节点描述。
等待子组件就绪:
组件框架会检查所有子组件是否已探测(probe)成功。如果某个子组件尚未加载(如驱动模块未初始化),返回 -EPROBE_DEFER,延迟主设备探测。
调用 bind 回调:
当所有子组件都就绪,组件框架调用 mtk_drm_ops.bind(即 mtk_drm_bind)。mtk_drm_bind 通常:
初始化 DRM 设备(struct drm_device)。调用 mtk_drm_kms_init 配置 KMS(Kernel Mode Setting)。设置显示管道(CRTC、plane、connector 等)。
错误处理:
如果匹配或绑定失败,返回错误码(如 -ENOMEM 表示内存不足,-EINVAL 表示参数无效)。ret 捕获返回值,供 mtk_drm_probe 检查是否继续初始化。
4. 典型执行流程
假设在 mtk_drm_probe 中调用:
static int mtk_drm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct component_match *match = NULL;
int ret;
// ... 其他初始化代码 ...
// 添加子组件匹配规则
component_match_add(dev, &match, component_compare_of, of_node1); // 如 OVL
component_match_add(dev, &match, component_compare_of, of_node2); // 如 RDMA
// 注册主设备并绑定子组件
ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
if (ret)
goto err_cleanup;
// ... 继续初始化 ...
return 0;
err_cleanup:
// 清理资源
return ret;
}
步骤:
component_match_add 构建 match 列表,包含所有子组件的设备树节点(如 OVL、RDMA、DSI)。component_master_add_with_match 注册主设备,并检查子组件是否就绪。如果子组件未加载,返回 -EPROBE_DEFER,驱动推迟探测。所有子组件就绪后,调用 mtk_drm_bind,初始化 DRM 设备。ret 记录结果,成功为 0,失败则清理资源。
5. 代码作用与意义
模块化管理:
MediaTek SoC 的显示硬件由多个独立模块组成(如 OVL、RDMA、DSI),每个模块有自己的驱动。组件框架允许主设备(DRM 驱动)动态等待子组件驱动加载,简化复杂硬件的初始化。
设备树依赖:
match 基于设备树节点(如 mediatek,ovl),确保正确绑定硬件模块。设备树示例:
drm {
compatible = "mediatek,mt6885-drm";
display-components = <&ovl0>, <&rdma0>, <&dsi0>;
};
异步探测:
如果子组件(如 DSI 驱动)尚未加载,返回 -EPROBE_DEFER,驱动会稍后重试,确保初始化顺序正确。
绑定后的操作:
mtk_drm_bind 调用 mtk_drm_kms_init,设置 CRTC、plane、connector,初始化显示管道。
6. 关键点与注意事项
错误处理:
如果返回 -EPROBE_DEFER,表示子组件未就绪,驱动会延迟加载,需确保设备树和子驱动正确配置。其他错误(如 -ENOMEM)可能表示内存不足,需检查系统资源。
性能:
组件框架的匹配过程可能引入延迟,尤其在子组件较多时。mtk_drm_bind 的复杂初始化(如 CRTC 创建)需高效执行,避免影响启动时间。
硬件依赖:
依赖 MediaTek 特定的硬件模块(如 MT6885 的显示管道)。设备树节点必须准确描述硬件(如 mediatek,mt6983-disp)。
调试:
使用 DDPINFO 或 DDPPR_ERR 日志检查绑定状态。结合 debugfs(mtk_drm_debugfs_init)查看组件状态。
7. 与 mtk_drm_kms_init 的关系
在 component_master_add_with_match 成功后,mtk_drm_bind 调用 mtk_drm_kms_init,后者:
初始化 drm_mode_config。创建 CRTC(通过 mtk_drm_crtc_create)。配置 DMA 和 VBlank。初始化工作队列(如 mtk_atomic_work)和调试模块。
component_master_add_with_match 是硬件组件绑定的入口,而 mtk_drm_kms_init 是 DRM 功能初始化的核心。
8. 总结
ret = component_master_add_with_match(dev, &mtk_drm_ops, match); 是 MediaTek DRM 驱动中用于注册主设备并绑定子组件的关键代码。它利用 Linux 组件框架,通过设备树匹配显示模块(如 OVL、RDMA、DSI),并在所有组件就绪后调用 mtk_drm_bind 初始化 DRM 设备。这行代码确保硬件模块的模块化管理和正确初始化,是驱动探测的核心步骤。