一、mtk_drm_fb.c代码分析
主要函数接口的作用
以下是代码中主要函数接口的分析。这些函数主要围绕MediaTek DRM框架中的framebuffer(帧缓冲)管理,包括创建、销毁、获取属性(如GEM对象、DMA地址、安全属性)、等待同步等。代码使用DRM(Direct Rendering Manager)框架的结构和函数,扩展了MediaTek特定的功能(如安全缓冲支持)。我将按功能逻辑顺序列出主要函数,并简要说明其作用、参数、返回值和关键逻辑。
*mtk_fb_get_gem_obj(struct drm_framebuffer fb)
作用: 从给定的framebuffer中获取关联的GEM(Graphics Execution Manager)对象。GEM对象用于管理图形缓冲内存。参数: fb – DRM framebuffer对象。返回值: GEM对象指针(struct drm_gem_object *),如果无效则返回NULL。关键逻辑: 通过container_of宏转换为mtk_drm_fb结构,然后返回其gem_obj字段。
*mtk_fb_get_size(struct drm_framebuffer fb)
作用: 获取framebuffer关联GEM对象的内存大小(size)。用于查询缓冲区容量。参数: fb – DRM framebuffer对象。返回值: GEM对象的size(size_t),如果无效则返回0。关键逻辑: 调用mtk_fb_get_gem_obj获取GEM对象,然后转换为mtk_drm_gem_obj并返回其size字段。
*mtk_fb_get_dma(struct drm_framebuffer fb)
作用: 获取framebuffer关联GEM对象的DMA(Direct Memory Access)地址。用于硬件直接访问缓冲区。参数: fb – DRM framebuffer对象。返回值: DMA地址(dma_addr_t),如果无效则返回0。关键逻辑: 调用mtk_fb_get_gem_obj获取GEM对象,然后转换为mtk_drm_gem_obj并返回其dma_addr字段。
*mtk_drm_fb_is_secure(struct drm_framebuffer fb)
作用: 检查framebuffer关联的GEM对象是否是安全的(secure),即是否用于加密或保护内容(如DRM保护的视频)。参数: fb – DRM framebuffer对象。返回值: true(安全)或false(不安全)。关键逻辑: 调用mtk_fb_get_gem_obj获取GEM对象,然后转换为mtk_drm_gem_obj并检查其sec字段。
**mtk_drm_fb_create_handle(struct drm_framebuffer *fb, struct drm_file file_priv, unsigned int handle)
作用: 为framebuffer的GEM对象创建一个用户空间句柄(handle),用于文件私有数据中引用GEM对象。参数: fb – DRM framebuffer;file_priv – DRM文件私有数据;handle – 输出句柄指针。返回值: 0(成功)或其他错误码。关键逻辑: 调用drm_gem_handle_create创建句柄。
*mtk_drm_fb_destroy(struct drm_framebuffer fb)
作用: 销毁framebuffer对象,释放相关资源。参数: fb – DRM framebuffer对象。返回值: 无。关键逻辑: 调用drm_framebuffer_cleanup清理framebuffer,然后释放GEM对象并释放mtk_drm_fb内存。
**mtk_drm_framebuffer_init(struct drm_device *dev, const struct drm_mode_fb_cmd2 mode, struct drm_gem_object obj)
作用: 初始化一个mtk_drm_fb结构,包括填充framebuffer的基本信息并绑定GEM对象。参数: dev – DRM设备;mode – 帧缓冲模式命令;obj – GEM对象。返回值: mtk_drm_fb指针(成功)或错误指针(ERR_PTR)。关键逻辑: 分配mtk_drm_fb内存,调用drm_helper_mode_fill_fb_struct填充模式信息,绑定GEM对象,然后调用drm_framebuffer_init初始化framebuffer(绑定mtk_drm_fb_funcs回调)。
**mtk_drm_framebuffer_create(struct drm_device *dev, const struct drm_mode_fb_cmd2 mode, struct drm_gem_object obj)
作用: 创建一个完整的DRM framebuffer对象,基于给定的模式和GEM对象。参数: dev – DRM设备;mode – 帧缓冲模式命令;obj – GEM对象。返回值: DRM framebuffer指针(成功)或错误指针(ERR_CAST)。关键逻辑: 调用mtk_drm_framebuffer_init进行初始化,然后返回base字段。
*mtk_fb_wait(struct drm_framebuffer fb)
作用: 等待framebuffer关联GEM对象的独占fence(栅栏同步),确保缓冲区同步完成(用于显示等待同步,DWFS)。参数: fb – DRM framebuffer对象。返回值: 0(成功)或-ERESTARTSYS(中断)。关键逻辑: 调用mtk_fb_get_gem_obj获取GEM对象,获取其DMA缓冲的reservation对象,然后(注释中)等待超时(当前实现简化返回0,实际可能需dma_resv_wait_timeout_rcu)。
**mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file file, const struct drm_mode_fb_cmd2 cmd)
作用: 根据用户空间的模式命令(drm_mode_fb_cmd2)创建framebuffer,支持安全缓冲检查和大小验证。这是DRM模式设置的入口函数。参数: dev – DRM设备;file – DRM文件;cmd – 模式命令(包含句柄、格式、宽高等)。返回值: DRM framebuffer指针(成功)或错误指针(ERR_PTR)。关键逻辑: 如果格式为DRM_FORMAT_C8,直接初始化;否则查找GEM对象,计算bpp和size,检查安全标志和大小有效性,然后调用mtk_drm_framebuffer_init初始化。
这些函数主要服务于DRM驱动的framebuffer子系统,支持单平面(single plane)缓冲,强调安全缓冲(sec字段)和GEM内存管理。代码中有些部分有TODO注释(如移除!mtk_gem->sec检查)和调试日志(DDPINFO/DDPAEE)。
基于文本的函数关系调用图
以下是函数调用关系的文本表示图,使用缩进和箭头(->)表示调用层次(从上到下为调用栈)。根节点是入口函数(如mtk_drm_mode_fb_create,常用于DRM ioctl调用),叶子节点是底层DRM API或简单访问。静态结构如mtk_drm_fb_funcs是回调集合,在初始化时绑定。
mtk_drm_mode_fb_create (DRM模式创建入口)
-> drm_gem_object_lookup (查找GEM对象基于句柄)
-> to_mtk_gem_obj (转换为MediaTek GEM对象)
-> (访问mtk_gem->sec检查安全标志)
-> mtk_drm_framebuffer_init (初始化mtk_drm_fb)
-> drm_helper_mode_fill_fb_struct (填充framebuffer模式信息)
-> drm_framebuffer_init (初始化DRM framebuffer)
-> (绑定mtk_drm_fb_funcs回调集合)
- .create_handle -> mtk_drm_fb_create_handle
-> drm_gem_handle_create (创建用户空间句柄)
- .destroy -> mtk_drm_fb_destroy
-> drm_framebuffer_cleanup (清理framebuffer)
-> drm_gem_object_put (释放GEM引用)
-> kfree (释放mtk_drm_fb内存)
-> (如果失败: drm_gem_object_put释放GEM)
mtk_drm_framebuffer_create (简化创建接口)
-> mtk_drm_framebuffer_init (同上)
mtk_fb_wait (同步等待入口)
-> mtk_fb_get_gem_obj (获取GEM对象)
-> to_mtk_fb (转换为mtk_drm_fb)
-> (访问gem->dma_buf->resv)
-> (dma_resv_wait_timeout_rcu - 注释中,实际简化返回0)
mtk_drm_fb_is_secure (安全检查)
-> mtk_fb_get_gem_obj (同上)
-> to_mtk_gem_obj (转换为MediaTek GEM)
-> (访问mtk_gem->sec)
mtk_fb_get_size (大小查询)
-> to_mtk_fb (转换为mtk_drm_fb)
-> to_mtk_gem_obj (转换为MediaTek GEM)
-> (访问mtk_gem->size)
mtk_fb_get_dma (DMA地址查询)
-> to_mtk_fb (转换为mtk_drm_fb)
-> to_mtk_gem_obj (转换为MediaTek GEM)
-> (访问mtk_gem->dma_addr)
mtk_fb_get_gem_obj (GEM对象查询 - 基础函数,被多个上层调用)
-> to_mtk_fb (转换为mtk_drm_fb)
-> (访问mtk_fb->gem_obj)
此图覆盖了代码中所有显式调用关系。注意:
to_mtk_fb 和 to_mtk_gem_obj 是宏(container_of),用于类型转换,不是函数调用,但逻辑上等效于访问成员。mtk_drm_fb_funcs 是静态回调表,在drm_framebuffer_init中绑定,由DRM框架在适当时机(如ioctl或销毁)调用。代码中有条件分支(如格式检查、安全标志),图中简化为主路径。
static const struct drm_framebuffer_funcs mtk_drm_fb_funcs = {
.create_handle = mtk_drm_fb_create_handle,
.destroy = mtk_drm_fb_destroy,
};
二、mtk_drm_fbconsole.c代码分析
主要函数接口的作用
以下是代码中主要函数接口的分析。这些函数主要实现了MediaTek DRM框架下的framebuffer console(MFC,MediaTek Framebuffer Console),用于在framebuffer上绘制文本字符、处理光标、滚动、颜色设置等,支持RGB565等格式。代码使用自定义的MFC_CONTEXT结构管理上下文,支持信号量锁保护多线程访问。重点是文本绘制和屏幕日志系统(screen_logger)。我将按功能逻辑顺序列出主要函数(包括私有辅助函数),并简要说明其作用、参数、返回值和关键逻辑。枚举类型MFC_STATUS用于返回状态(如OK、INVALID_ARGUMENT等)。
MFC_Get_Cursor_Offset(MFC_HANDLE handle)
作用: 计算当前光标位置在framebuffer中的字节偏移量,用于定位绘制或访问。参数: handle – MFC上下文句柄(struct MFC_CONTEXT *)。返回值: 偏移量(UINT32)。关键逻辑: 根据光标行列(cursor_col, cursor_row)、字体宽高、bpp(字节每像素)和缩放因子(scale)计算偏移。
**_mfc_draw_row(struct MFC_CONTEXT ctxt, BYTE dest, BYTE raw_color)
作用: 私有函数,绘制字体的一行像素,支持缩放(scale)。用于字符绘制的子过程。参数: ctxt – MFC上下文;dest – 目标像素地址;raw_color – 原始颜色位图(8位)。返回值: 无。关键逻辑: 遍历行像素,根据位图位设置前景/背景色,并根据scale重复像素。
*_mfc_draw_char(struct MFC_CONTEXT ctxt, UINT32 x, UINT32 y, char c)
作用: 私有函数,在指定位置(x, y)绘制单个字符,支持不同bpp(2、3、4字节)。参数: ctxt – MFC上下文;x, y – 像素坐标;c – 要绘制的字符。返回值: 无。关键逻辑: 从字体数据(VGA 8×16)获取位图,根据bpp分支处理像素填充(RGB565表或字节级设置),检查坐标边界。
*_mfc_scroll_up(struct MFC_CONTEXT ctxt)
作用: 私有函数,向上滚动屏幕一行,清除最后一行。参数: ctxt – MFC上下文。返回值: 无。关键逻辑: 使用memcpy复制行数据,然后用背景色填充最后一行。
*_mfc_newline(struct MFC_CONTEXT ctxt)
作用: 私有函数,处理换行:填充当前行空白,移动光标到下一行,并检查是否需要滚动。参数: ctxt – MFC上下文。返回值: 无。关键逻辑: 用空格绘制剩余列,递增cursor_row,如果超出rows则调用_mfc_scroll_up。
*_mfc_putc(struct MFC_CONTEXT ctxt, const char c)
作用: 私有函数,放置单个字符到当前光标位置,支持特殊字符如
、
、 。参数: ctxt – MFC上下文;c – 字符。返回值: 无。关键逻辑: 检查换行,处理特殊字符(换行、回车、制表),否则调用_mfc_draw_char绘制并移动光标。
MFC_GetScale(unsigned int fb_width, unsigned int fb_height, unsigned int fb_bpp)
作用: 根据framebuffer尺寸和bpp计算缩放因子(scale),用于高分辨率下放大字体。参数: fb_width, fb_height – 宽高;fb_bpp – 字节每像素。返回值: 缩放因子(int),默认1,特定条件下2。关键逻辑: 如果bpp=2且分辨率>=1080×1920,返回2;否则1。
**MFC_Open(MFC_HANDLE *handle, void fb_addr, unsigned int fb_width, unsigned int fb_height, unsigned int fb_bpp, unsigned int fg_color, unsigned int bg_color, struct file filp)
作用: 打开MFC上下文,初始化framebuffer console。参数: handle – 输出句柄;fb_addr – framebuffer地址;fb_width, fb_height, fb_bpp – 尺寸和bpp;fg_color, bg_color – 前景/背景色;filp – 文件指针。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 分配ctxt,计算scale,初始化信号量、行列数等。
**MFC_Open_Ex(MFC_HANDLE *handle, void fb_addr, unsigned int fb_width, unsigned int fb_height, unsigned int fb_pitch, unsigned int fb_bpp, unsigned int fg_color, unsigned int bg_color, struct file filp)
作用: 扩展打开函数,支持指定pitch(行字节数),仅限bpp=2。参数: 同MFC_Open,但fb_width为pitch,实际宽度由调用者管理。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 类似MFC_Open,但限制bpp=2,使用fb_pitch作为宽度。
MFC_Close(MFC_HANDLE handle)
作用: 关闭MFC上下文,释放内存。参数: handle – MFC句柄。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 简单kfree释放ctxt。
MFC_SetColor(MFC_HANDLE handle, unsigned int fg_color, unsigned int bg_color)
作用: 设置前景和背景颜色。参数: handle – MFC句柄;fg_color, bg_color – 新颜色。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 加锁,更新ctxt颜色,解锁。
MFC_SetWH(MFC_HANDLE handle, unsigned int fb_width, unsigned int fb_height)
作用: 更新framebuffer宽高,重新计算scale、行列数,并重置光标。参数: handle – MFC句柄;fb_width, fb_height – 新尺寸。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 加锁,更新尺寸,重新计算rows/cols,重置光标和screen_color。
MFC_ResetCursor(MFC_HANDLE handle)
作用: 重置光标到(0,0)位置。参数: handle – MFC句柄。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 加锁,设置cursor_row/col=0,解锁。
*MFC_Print(MFC_HANDLE handle, const char str)
作用: 在当前光标位置打印字符串,支持换行等。参数: handle – MFC句柄;str – 字符串。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 加锁,遍历str调用_mfc_putc,解锁。
*MFC_SetMem(MFC_HANDLE handle, const char str, UINT32 color)
作用: 用指定颜色填充字符串宽度对应的区域(用于覆盖内存)。参数: handle – MFC句柄;str – 字符串(用于计算宽度);color – 填充色。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 加锁,计算宽度,逐行填充像素,解锁。
*MFC_LowMemory_Printf(MFC_HANDLE handle, const char str, UINT32 fg_color, UINT32 bg_color)
作用: 低内存模式下打印字符串到屏幕右下角,临时改变颜色和光标。参数: handle – MFC句柄;str – 字符串;fg_color, bg_color – 临时颜色。返回值: MFC_STATUS_OK(成功)或其他错误。关键逻辑: 加锁,保存当前光标/颜色,移动到右下角打印,恢复原状态,解锁。
screen_logger_init(void)
作用: 初始化屏幕日志链表(双向链表)。参数: 无。返回值: 无。关键逻辑: 如果未初始化,INIT_LIST_HEAD并设置标志。
**screen_logger_add_message(char obj, enum message_mode mode, char message)
作用: 添加或更新日志消息,根据mode替换或追加。参数: obj – 对象名(键);mode – 模式(MESSAGE_REPLACE/APPEND);message – 消息。返回值: 无。关键逻辑: 遍历链表查找obj,如果存在按mode更新;否则新建节点添加。
*screen_logger_remove_message(const char obj)
作用: 移除指定对象的日志消息。参数: obj – 对象名。返回值: 无。关键逻辑: 遍历链表,找到后释放内存并删除节点(注:有内存泄漏TODO)。
screen_logger_print(MFC_HANDLE handle)
作用: 打印所有日志消息到console。参数: handle – MFC句柄。返回值: 无。关键逻辑: 遍历链表,调用MFC_Print打印每个消息。
screen_logger_empty(void)
作用: 清空所有日志消息。参数: 无。返回值: 无。关键逻辑: 循环移除链表尾节点直到空。
screen_logger_test_case(MFC_HANDLE handle)
作用: 测试日志系统:添加/替换消息,打印,清空。参数: handle – MFC句柄。返回值: 无。关键逻辑: 添加测试消息,调用screen_logger_print和screen_logger_empty。
这些函数主要用于嵌入式显示调试或控制台,支持字体VGA_8x16,强调线程安全(信号量)和低内存场景。
基于文本的函数关系调用图
以下是函数调用关系的文本表示图,使用缩进和箭头(->)表示调用层次(从上到下为调用栈)。根节点是入口函数(如MFC_Open、MFC_Print等,常用于外部调用),叶子节点是底层操作或简单访问。宏如MFC_WIDTH是常量访问,不是调用。信号量锁(down_interruptible/up)在多数公共函数中包裹,但图中简化标注。
MFC_Open (打开入口)
-> MFC_GetScale (计算缩放)
-> kzalloc (分配ctxt)
-> sema_init (初始化信号量)
-> (计算rows/cols)
MFC_Open_Ex (扩展打开入口)
-> MFC_GetScale (同上)
-> kzalloc (分配ctxt)
-> sema_init (初始化信号量)
-> (计算rows/cols, 限制bpp=2)
MFC_Close (关闭入口)
-> kfree (释放ctxt)
MFC_SetColor (设置颜色入口)
-> down_interruptible (加锁)
-> (更新fg_color/bg_color)
-> up (解锁)
MFC_SetWH (设置宽高入口)
-> down_interruptible (加锁)
-> MFC_GetScale (同上)
-> (更新宽高/rows/cols,重置光标)
-> up (解锁)
MFC_ResetCursor (重置光标入口)
-> down_interruptible (加锁)
-> (设置cursor_row/col=0)
-> up (解锁)
MFC_Print (打印字符串入口)
-> down_interruptible (加锁)
-> _mfc_putc (放置单个字符 - 循环调用)
-> check_newline (宏: 检查列是否满)
-> _mfc_newline (换行)
-> _mfc_draw_char (绘制空格 - 填充剩余列)
-> _mfc_scroll_up (滚动如果超出行)
-> memcpy (复制行数据)
-> (填充背景色)
-> _mfc_newline (处理
)
-> (处理
: 重置col)
-> (处理 : 跳过8列)
-> _mfc_draw_char (绘制默认字符)
-> _mfc_draw_row (绘制行 - 如果scale>=2)
-> (bpp分支: 填充像素表或字节)
-> up (解锁)
MFC_SetMem (填充内存入口)
-> down_interruptible (加锁)
-> strlen (计算宽度)
-> (逐行填充像素色)
-> up (解锁)
MFC_LowMemory_Printf (低内存打印入口)
-> down_interruptible (加锁)
-> strlen (计算长度)
-> (保存/临时设置光标/颜色)
-> _mfc_putc (同上 - 循环调用)
-> (恢复光标/颜色)
-> up (解锁)
screen_logger_init (日志初始化)
-> INIT_LIST_HEAD (链表初始化)
screen_logger_add_message (添加消息入口)
-> screen_logger_init (同上)
-> list_for_each_entry (遍历链表)
-> strcmp (比较obj)
-> kstrdup (复制字符串)
-> kzalloc/strncpy/strncat (追加/替换模式)
-> kfree (释放旧消息)
-> kmalloc (新建节点)
-> kstrdup (复制obj/message)
-> list_add_tail (添加链表)
screen_logger_remove_message (移除消息入口)
-> list_for_each_entry (遍历链表)
-> strcmp (比较obj)
-> kfree (释放obj/message)
-> list_del (删除节点)
-> kfree (释放节点)
screen_logger_print (打印日志入口)
-> list_for_each_entry (遍历链表)
-> MFC_Print (同上)
screen_logger_empty (清空日志入口)
-> list_entry (获取尾节点)
-> screen_logger_remove_message (循环调用直到空)
screen_logger_test_case (测试入口)
-> screen_logger_add_message (添加/替换测试消息)
-> screen_logger_print (同上)
-> screen_logger_empty (同上)
MFC_Get_Cursor_Offset (光标偏移入口)
-> (计算基于ctxt成员)
此图覆盖了代码中所有显式调用关系。私有函数(如_mfc_系列)主要被公共接口调用。链表操作使用Linux内核list.h宏。
实现了哪些回调函数
这个代码文件中没有实现标准的DRM框架回调函数(如drm_framebuffer_funcs或drm_crtc_helper_funcs那样的结构体回调集合),而是提供了一组自定义的MFC_接口函数(如MFC_Open、MFC_Print等)作为framebuffer console的操作接口。这些接口可能在更高层的DRM驱动中被调用,用于console渲染。没有显式的回调表(如const struct xxx_funcs),所有函数都是直接导出的或私有的。screen_logger系列是独立的日志系统,也没有回调。
三、mtk_drm_fbdev.c代码分析
主要函数接口的作用
以下是代码中主要函数接口的分析。这些函数主要实现了MediaTek DRM驱动的framebuffer device(fbdev)支持,包括初始化、探针、IOCTL处理、pan display(缓冲翻转)、内存管理,以及与LCM(LCD模块)的集成。代码使用DRM框架的fb_helper和fb_ops扩展MediaTek特定功能,如LCM自动测试、预分配缓冲解析(从DT或ATAG)。强调兼容LK(Little Kernel)预分配缓冲和AEE(Android Early Exit)层。条件编译如MTK_LEGACY_FB_MAP影响mmap行为。我将按功能逻辑顺序列出主要函数,并简要说明其作用、参数、返回值和关键逻辑。
*mtk_drm_fb_fm_auto_test(struct fb_info info)
作用: 执行工厂模式下的LCM自动测试(ATA),仅针对CRTC0,用于调试或测试显示链路。参数: info – framebuffer信息。返回值: 0(成功)或其他负值(失败)。关键逻辑: 获取CRTC0,锁定互斥锁,禁用/启用idle manager,调用mtk_crtc_lcm_ATA测试,打印结果。
*mtk_drm_fb_ioctl(struct fb_info info, unsigned int cmd, unsigned long arg)
作用: 处理framebuffer IOCTL命令,支持MTKFB_FACTORY_AUTO_TEST进行LCM测试,其他命令忽略。参数: info – framebuffer信息;cmd – 命令码;arg – 参数。返回值: 0(成功)或其他错误(如-EFAULT)。关键逻辑: 根据cmd分支,调用mtk_drm_fb_fm_auto_test并拷贝结果到用户空间。
**mtk_drm_fb_pan_display(struct fb_var_screeninfo var, struct fb_info info)
作用: 执行pan display操作(更新屏幕偏移),支持MediaTek的CMDQ(Command Queue)同步。参数: var – 可变屏幕信息(包含x/y偏移);info – framebuffer信息。返回值: 0(成功)或其他错误。关键逻辑: 调用DRM的pan_display,锁定CRTC,创建CMDQ包,等待帧完成,flush并销毁包。
*disp_get_fb_address(unsigned long fbVirAddr)
作用: 获取framebuffer的虚拟地址,用于调试或早期移植。参数: fbVirAddr – 输出虚拟地址指针。返回值: 无。关键逻辑: 从全局debug_info中提取screen_base。
pan_display_test(int frame_num, int bpp)
作用: 测试pan display功能,填充渐变像素并循环翻转缓冲,用于早期移植验证。参数: frame_num – 帧数;bpp – 位每像素。返回值: 0(成功)。关键逻辑: 获取fb_va,填充像素,更新var偏移,循环调用mtk_drm_fb_pan_display。
**mtk_drm_fbdev_mmap(struct fb_info info, struct vm_area_struct vma) (条件编译,非MTK_LEGACY_FB_MAP)
作用: 映射framebuffer内存到用户空间,使用GEM对象。参数: info – framebuffer信息;vma – 虚拟内存区域。返回值: 0(成功)或其他错误。关键逻辑: 调用mtk_drm_gem_mmap_buf映射fbdev_bo。
mtk_drm_lcm_is_connect(void)
作用: 检查LCM是否连接,从DT(Device Tree)的chosen节点解析ATAG videolfb标签。参数: 无。返回值: true(连接)或false。关键逻辑: 查找/chosen节点,获取islcmfound字段。
**_parse_tag_videolfb(unsigned int *vramsize, phys_addr_t fb_base, unsigned int fps)
作用: 解析ATAG videolfb标签,获取预分配framebuffer的尺寸、基地址和FPS(仅LK模式)。参数: vramsize, fb_base, fps – 输出参数。返回值: 0(成功)或-1(失败)。关键逻辑: 查找/chosen节点,提取vram/fb_base/fps,默认FPS=6000。
free_reserved_buf(phys_addr_t start_phys, phys_addr_t end_phys)
作用: 释放预分配的物理内存页(reserved pages)。参数: start_phys, end_phys – 物理地址范围。返回值: 0(成功)或-1(无效范围)。关键逻辑: 页对齐检查,循环free_reserved_page。
free_fb_buf(void)
作用: 释放LK预分配的framebuffer内存。参数: 无。返回值: 0(成功)或-1(错误)。关键逻辑: 调用_parse_tag_videolfb获取参数,然后调用free_reserved_buf。
**mtk_fbdev_probe(struct drm_fb_helper helper, struct drm_fb_helper_surface_size sizes)
作用: DRM fb_helper的探针函数,创建GEM对象、framebuffer和fb_info,支持LK预分配缓冲。参数: helper – DRM fb_helper;sizes – 表面尺寸。返回值: 0(成功)或其他错误。关键逻辑: 计算模式,解析videolfb或创建新GEM,分配fb_info,创建framebuffer,填充info,初始化AEE层。
**mtk_drm_fb_add_one_connector(struct drm_device dev, struct drm_fb_helper helper)
作用: 添加一个连接器到fb_helper,仅限CRTC0可能的编码器。参数: dev – DRM设备;helper – fb_helper。返回值: 0(成功)。关键逻辑: 遍历连接器,查找最佳编码器,注释中添加连接器(当前未启用)。
*mtk_fbdev_init(struct drm_device dev)
作用: 初始化fbdev支持,包括准备fb_helper、添加连接器、初始配置。参数: dev – DRM设备。返回值: 0(成功)或其他错误。关键逻辑: 检查CRTC/连接器数,调用drm_fb_helper_init,添加连接器,初始配置(bpp=32)。
*mtk_fbdev_fini(struct drm_device dev)
作用: 清理fbdev资源,注销framebuffer并释放。参数: dev – DRM设备。返回值: 无。关键逻辑: 注销fbi,移除framebuffer,调用drm_fb_helper_fini。
这些函数主要服务于DRM fbdev子系统,支持遗留fbdev接口,集成MediaTek特定硬件如CMDQ和LCM。
基于文本的函数关系调用图
以下是函数调用关系的文本表示图,使用缩进和箭头(->)表示调用层次(从上到下为调用栈)。根节点是入口函数(如mtk_fbdev_init,常用于DRM驱动初始化),叶子节点是底层DRM API或简单访问。宏如ALIGN_TO_32是常量计算,不是调用。条件编译路径标注。
mtk_fbdev_init (初始化入口)
-> drm_fb_helper_prepare (准备fb_helper)
-> drm_fb_helper_init (初始化fb_helper)
-> mtk_drm_fb_add_one_connector (添加连接器)
-> drm_connector_list_iter_begin/end (迭代连接器)
-> drm_for_each_connector_iter (遍历连接器)
-> (helper_private->best_encoder 或 drm_encoder_find)
-> drm_fb_helper_initial_config (初始配置,bpp=32)
-> (内部调用mtk_fbdev_probe - 通过fb_helper_funcs)
mtk_fbdev_probe (探针回调入口)
-> _parse_tag_videolfb (解析videolfb标签)
-> of_find_node_by_path (查找/chosen节点)
-> of_get_property (获取ATAG videolfb)
-> drm_mode_legacy_fb_format (计算像素格式)
-> mtk_drm_gem_create (创建GEM对象 - 非LK)
-> mtk_drm_fb_gem_insert (插入GEM对象 - LK)
-> kmemleak_ignore (忽略kmemleak)
-> drm_fb_helper_alloc_fbi (分配fb_info)
-> mtk_drm_framebuffer_create (创建framebuffer)
-> drm_fb_helper_fill_info (填充fb_info)
-> mtk_drm_assert_fb_init (初始化AEE层 - 条件)
mtk_fbdev_fini (清理入口)
-> drm_fb_helper_unregister_fbi (注销fbi)
-> drm_framebuffer_unregister_private (注销framebuffer)
-> drm_framebuffer_remove (移除framebuffer)
-> drm_fb_helper_fini (清理fb_helper)
mtk_drm_fb_pan_display (pan display入口)
-> drm_fb_helper_pan_display (DRM pan display)
-> (获取CRTC0)
-> DDP_MUTEX_LOCK/UNLOCK (锁定CRTC)
-> mtk_crtc_pkt_create (创建CMDQ包)
-> mtk_crtc_with_sub_path (检查子路径)
-> mtk_crtc_wait_frame_done (等待帧完成)
-> cmdq_pkt_flush (flush CMDQ)
-> cmdq_pkt_destroy (销毁CMDQ包)
mtk_drm_fb_ioctl (IOCTL入口)
-> mtk_drm_fb_fm_auto_test (工厂测试 - MTKFB_FACTORY_AUTO_TEST)
-> (获取CRTC0)
-> DDP_MUTEX_LOCK/UNLOCK (锁定CRTC)
-> mtk_drm_helper_get_opt (获取idle mgr选项)
-> mtk_drm_set_idlemgr (设置idle mgr)
-> mtk_crtc_lcm_ATA (LCM ATA测试)
-> copy_to_user (拷贝结果到用户空间)
pan_display_test (测试入口)
-> disp_get_fb_address (获取fb_va)
-> (从debug_info提取screen_base)
-> mtk_crtc_frame_buffer_existed (检查缓冲存在)
-> (填充像素循环)
-> mtk_drm_fb_pan_display (循环调用)
free_fb_buf (释放入口)
-> _parse_tag_videolfb (同上)
-> free_reserved_buf (释放页)
-> free_reserved_page (循环释放)
mtk_drm_lcm_is_connect (连接检查入口)
-> of_find_node_by_path (同上)
-> of_get_property (获取islcmfound)
mtk_drm_fbdev_mmap (mmap入口 - 非遗留模式)
-> mtk_drm_gem_mmap_buf (映射GEM缓冲)
此图覆盖了代码中所有显式调用关系。全局变量如debug_info用于调试。回调通过结构体绑定,由DRM/fb框架调用。
实现了哪些回调函数
代码中实现了以下回调函数,通过静态结构体绑定:
mtk_fbdev_ops (struct fb_ops): 这是framebuffer操作回调集合,用于fb_info->fbops。在mtk_fbdev_probe中绑定到info。实现的回调包括:
.fb_fillrect = drm_fb_helper_cfb_fillrect (填充矩形).fb_copyarea = drm_fb_helper_cfb_copyarea (拷贝区域).fb_imageblit = drm_fb_helper_cfb_imageblit (图像blit).fb_check_var = drm_fb_helper_check_var (检查var).fb_set_par = drm_fb_helper_set_par (设置par).fb_blank = drm_fb_helper_blank (空白屏幕).fb_pan_display = mtk_drm_fb_pan_display (pan display – 自定义).fb_setcmap = drm_fb_helper_setcmap (设置colormap).fb_mmap = mtk_drm_fbdev_mmap (mmap – 条件编译,非遗留模式).fb_ioctl = mtk_drm_fb_ioctl (IOCTL – 自定义)
mtk_drm_fb_helper_funcs (const struct drm_fb_helper_funcs): 这是DRM fb_helper回调集合。在mtk_fbdev_init中通过drm_fb_helper_prepare绑定。实现的回调包括:
.fb_probe = mtk_fbdev_probe (探针函数 – 自定义)
这些回调由DRM/fbdev框架在适当时机(如init、ioctl、pan)调用,支持标准fbdev接口的扩展。
四、总结
常见命令行工具(基于 DRM/KMS)
🔹
modetest
modetest
来自 libdrm 包
用来枚举和测试 DRM/KMS 的 mode、connector、plane、fb
常用命令:
# 列出所有显示资源
modetest -c
# 列出所有可用的显示模式
modetest -p
# 设置某个输出为指定模式并显示纯色
modetest -M <driver> -s <connector_id>@<crtc_id>:<wxh@refresh> -P <plane_id>@<crtc_id>:<wxh@x,y>