news 2026/1/26 5:52:15

[Linux外设驱动详解]RK3588 U-Boot 启动 Logo 显示流程详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[Linux外设驱动详解]RK3588 U-Boot 启动 Logo 显示流程详解

RK3588 U-Boot 启动 Logo 显示流程详解

目录

  1. 概述
  2. 显示子系统架构
  3. Logo显示流程
  4. 关键数据结构
  5. BMP图像处理
  6. VOP2显示控制器
  7. 设备树配置
  8. 时序图
  9. 源码路径参考

概述

RK3588 的 U-Boot 启动 Logo 显示功能基于 DRM (Direct Rendering Manager) 子系统实现,支持多种显示接口(HDMI、eDP、MIPI、LVDS等)和多种格式的 BMP Logo 图片。

主要特性

特性描述
显示接口HDMI0/1, eDP0/1, MIPI0/1, LVDS0/1, RGB, BT1120/656
VOPVOP2 (Video Output Processor 2) - 支持4个Video Port
BMP格式8bpp(RLE8压缩), 24bpp, 32bpp
显示模式全屏(Fullscreen), 居中(Center)
Logo来源Resource分区, Distro分区, 内置编译

显示子系统架构

┌─────────────────────────────────────────────────────────────────────┐ │ RK3588 显示子系统架构 │ └─────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ │ 应用层 (U-Boot 命令) │ │ rockchip_show_logo | rockchip_show_bmp | bmp info │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ DRM Display Framework │ │ rockchip_display.c (显示子系统管理) │ │ ├─ display_init() 初始化显示设备 │ │ ├─ display_logo() 显示Logo │ │ ├─ load_bmp_logo() 加载BMP图片 │ │ └─ display_set_plane() 设置显示平面 │ └─────────────────────────────────────────────────────────────────┘ │ ┌──────────────────────────┼──────────────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ VOP2 │ │ Panel │ │ Bridge │ │ (CRTC) │◄────────────►│ (Connector)◄─────────┤ (HDMI/ │ │ │ │ │ │ MIPI/ │ │ Overlay │ │ ┌─────┐│ │ eDP) │ │ Cluster │ │ │ LCD ││ └─────────┘ │ Smart │ │ └─────┘│ │ Layer │ │ ┌─────┐│ │ │ │ │ HDMI││ │ │ │ └─────┘│ └─────────┘ └─────────┘ │ │ └──────────┬───────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ 显示输出 │ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ HDMI│ │ eDP │ │ MIPI│ │ LVDS│ │ RGB │ │ │ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │ └─────────────────────────────────────────────────────────────────┘

Logo显示流程

1. 整体流程

┌────────────────────────────────────────────────────────────────────┐ │ Logo 显示完整流程 │ └────────────────────────────────────────────────────────────────────┘ U-Boot 启动 │ ▼ ┌──────────────────────────────────────────────────────────────────┐ │ 1. rockchip_display_probe() │ │ drivers/video/drm/rockchip_display.c:1871 │ │ ├─ 解析设备树 display-subsystem │ │ ├─ 解析 route 节点获取显示路径 │ │ ├─ 为每个显示路径创建 display_state │ │ ├─ 关联 CRTC (VOP2) 和 Connector (Panel/Bridge) │ │ ├─ 读取 Logo 配置 (logo,uboot / logo,kernel) │ │ └─ 初始化显示缓冲区 │ └──────────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────────┐ │ 2. rockchip_show_logo() │ │ drivers/video/drm/rockchip_display.c:1412 │ │ 遍历所有 display_state,为每个显示设备加载并显示 Logo │ └──────────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────────┐ │ 3. load_bmp_logo() │ │ drivers/video/drm/rockchip_display.c:1251 │ │ ├─ 检查 logo cache,已加载则直接返回 │ │ ├─ 读取 BMP 头部 (512 bytes) │ │ ├─ 确定图片来源: │ │ │ ├─ FROM_RESOURCE: resource 分区 │ │ │ ├─ FROM_DISTRO: distro 分区 │ │ │ └─ FROM_INTERNEL: 编译内置 │ │ ├─ 读取完整 BMP 数据到显示缓冲区 │ │ ├─ 解码 BMP (如果不是 16/32 bpp) │ │ └─ 填充 logo_info 结构体 │ └──────────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────────┐ │ 4. display_logo() │ │ drivers/video/drm/ockchip_display.c:997 │ │ ├─ display_init() │ │ │ ├─ 初始化 Connector (Panel/Bridge) │ │ │ ├─ 获取显示时序 (display_get_timing) │ │ │ ├─ 验证时序 (display_mode_valid) │ │ │ ├─ 初始化 CRTC (VOP2) │ │ │ └─ 设置显示模式 │ │ ├─ 根据 logo bpp 设置 crtc format │ │ ├─ 计算 src_rect (Logo尺寸) 和 crtc_rect (显示位置) │ │ ├─ display_check() 检查配置 │ │ ├─ display_set_plane() 设置显示平面 │ │ └─ display_enable() 启用显示输出 │ └──────────────────────────────────────────────────────────────────┘ │ ▼ Logo 显示完成

2. 显示子系统初始化

文件位置: drivers/video/drm/rockchip_display.c:1871

staticintrockchip_display_probe(structudevice*dev){structvideo_priv*uc_priv=dev_get_uclass_priv(dev);structvideo_uc_platdata*plat=dev_get_uclass_platdata(dev);// 1. 初始化显示缓冲区init_display_buffer(plat->base);// 2. 解析 display-subsystem/route 节点route_node=dev_read_subnode(dev,"route");ofnode_for_each_subnode(node,route_node){if(!ofnode_is_available(node))continue;// 3. 获取连接器 endpointphandle=ofnode_read_u32_default(node,"connect",-1);ep_node=of_find_node_by_phandle(phandle);// 4. 通过 endpoint 找到对应的 CRTC (VOP)vop_node=of_get_parent(port_parent_node);uclass_get_device_by_ofnode(UCLASS_VIDEO_CRTC,np_to_ofnode(vop_node),&crtc_dev);crtc=(structrockchip_crtc*)dev_get_driver_data(crtc_dev);// 5. 获取 Connector (Panel/Bridge)conn=rockchip_of_get_connector(np_to_ofnode(ep_node));// 6. 读取 Logo 配置if(!ret&&!ofnode_read_string_index(node,"logo,uboot",0,&name))memcpy(s->ulogo_name,name,strlen(name));if(!ret&&!ofnode_read_string_index(node,"logo,kernel",0,&name))memcpy(s->klogo_name,name,strlen(name));// 7. 读取显示模式ofnode_read_string_index(node,"logo,mode",0,&name);if(!strcmp(name,"fullscreen"))s->logo_mode=ROCKCHIP_DISPLAY_FULLSCREEN;elses->logo_mode=ROCKCHIP_DISPLAY_CENTER;// 8. 创建 display_state 并加入链表s=malloc(sizeof(*s));s->conn_state.connector=conn;s->crtc_state.crtc=crtc;list_add_tail(&s->head,&rockchip_display_list);}// 9. 预初始化显示设备display_pre_init();return0;}

3. Logo加载流程

文件位置: drivers/video/drm/rockchip_display.c:1251

staticintload_bmp_logo(structlogo_info*logo,constchar*bmp_name){structrockchip_logo_cache*logo_cache;structbmp_header*header;void*dst=NULL,*pdst;intsize;// 1. 查找或创建 logo cachelogo_cache=find_or_alloc_logo_cache(bmp_name);if(logo_cache->logo.mem){memcpy(logo,&logo_cache->logo,sizeof(*logo));return0;// 已缓存,直接返回}// 2. 读取 BMP 头部header=malloc(RK_BLK_SIZE);// 512 bytes#ifdefCONFIG_ROCKCHIP_RESOURCE_IMAGElen=rockchip_read_resource_file(header,bmp_name,0,RK_BLK_SIZE);if(len==RK_BLK_SIZE)logo_source=FROM_RESOURCE;#endifif(rockchip_read_distro_logo(header,bmp_name,RK_BLK_SIZE)==0)logo_source=FROM_DISTRO;else{header=(structbmp_header*)logo_bmp;logo_source=FROM_INTERNEL;}// 3. 获取 BMP 信息logo->bpp=get_unaligned_le16(&header->bit_count);logo->width=get_unaligned_le32(&header->width);logo->height=get_unaligned_le32(&header->height);size=get_unaligned_le32(&header->file_size);// 4. 分配显示缓冲区pdst=get_display_buffer(size);// 5. 读取完整 BMP 数据if(logo_source==FROM_RESOURCE)rockchip_read_resource_file(pdst,bmp_name,0,size);elseif(logo_source==FROM_DISTRO)rockchip_read_distro_logo(pdst,bmp_name,size);elsepdst=(void*)logo_bmp;// 内置// 6. 解码 BMP (如果不是 16/32 bpp)if(!can_direct_logo(logo->bpp)){// 需要解码,使用 bmpdecoderlogo->bpp=(logo->bpp<=16)?16:logo->bpp;dst_size=logo->width*logo->height*logo->bpp>>3;dst=get_display_buffer(dst_size);bmpdecoder(pdst,dst,logo->bpp);// 解码为 RGB565/RGB888logo->offset=0;logo->ymirror=0;}else{// 16/32 bpp 可以直接使用logo->offset=get_unaligned_le32(&header->data_offset);if(reserved==BMP_PROCESSED_FLAG)logo->ymirror=0;elselogo->ymirror=1;}logo->mem=dst;// 7. 缓存 logo 信息memcpy(&logo_cache->logo,logo,sizeof(*logo));// 8. 刷新缓存flush_dcache_range((ulong)dst,ALIGN((ulong)dst+dst_size,CONFIG_SYS_CACHELINE_SIZE));returnret;}

4. Logo显示流程

文件位置: drivers/video/drm/rockchip_display.c:997

staticintdisplay_logo(structdisplay_state*state){structcrtc_state*crtc_state=&state->crtc_state;structconnector_state*conn_state=&state->conn_state;structlogo_info*logo=&state->logo;inthdisplay,vdisplay,ret;// 1. 初始化显示设备ret=display_init(state);if(!state->is_init||ret)return-ENODEV;// 2. 根据 logo bpp 设置格式switch(logo->bpp){case16:crtc_state->format=ROCKCHIP_FMT_RGB565;break;case24:crtc_state->format=ROCKCHIP_FMT_RGB888;break;case32:crtc_state->format=ROCKCHIP_FMT_ARGB8888;break;default:printf("can't support bmp bits[%d]\n",logo->bpp);return-EINVAL;}// 3. 设置源矩形 (Logo尺寸)hdisplay=conn_state->mode.crtc_hdisplay;vdisplay=conn_state->mode.vdisplay;crtc_state->src_rect.w=logo->width;crtc_state->src_rect.h=logo->height;crtc_state->src_rect.x=0;crtc_state->src_rect.y=0;crtc_state->ymirror=logo->ymirror;crtc_state->rb_swap=0
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/20 19:45:02

Windows 11 LTSC缺失微软商店?技术深度解析与完整解决方案

Windows 11 LTSC缺失微软商店&#xff1f;技术深度解析与完整解决方案 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore Windows 11 LTSC系统以其稳定性…

作者头像 李华
网站建设 2026/1/21 10:21:52

frpc-desktop智能连接守护技术:构建永不中断的内网穿透通道

在远程办公和智能家居日益普及的今天&#xff0c;内网穿透技术已成为连接内外网络的关键桥梁。然而&#xff0c;传统frp工具在面对网络波动、路由器策略限制等复杂环境时&#xff0c;频繁的连接中断严重影响了用户体验。frpc-desktop通过创新的智能连接守护机制&#xff0c;成功…

作者头像 李华
网站建设 2026/1/21 7:35:30

利用PaddlePaddle镜像快速实现工业级目标检测(PaddleDetection)

利用PaddlePaddle镜像快速实现工业级目标检测 在智能制造产线日益智能化的今天&#xff0c;一个常见的挑战是&#xff1a;如何在短短几天内完成从数据标注到模型上线的全流程&#xff1f;许多团队曾因环境配置冲突、依赖版本不匹配或部署链路断裂而延误项目进度。尤其是在边缘设…

作者头像 李华
网站建设 2026/1/24 7:47:30

【C++】面试官爱的C++多态八股文,这次让你彻底搞懂!

问题引入&#xff1a;这篇文章重点介绍C中的多态特性。前面我们知道了&#xff0c;派生类中可以调用基类中的方法&#xff0c;对于同名的函数我们有隐藏的相关概念。但是现实可能存在一个问题&#xff0c;就是基类中的方法和派生类中的方法是不同的&#xff0c;不同的对象调用的…

作者头像 李华
网站建设 2026/1/25 11:28:31

PaddleDetection实战:用PaddlePaddle镜像完成YOLOv3目标检测

PaddleDetection实战&#xff1a;用PaddlePaddle镜像完成YOLOv3目标检测 在智能安防、无人零售和工业质检等现实场景中&#xff0c;开发者常常面临一个共性难题&#xff1a;如何在有限时间内快速搭建一个稳定、高效的目标检测系统&#xff1f;传统方式往往需要花费大量精力配置…

作者头像 李华
网站建设 2026/1/24 15:46:45

终极跨平台模组下载神器:WorkshopDL完整使用指南

终极跨平台模组下载神器&#xff1a;WorkshopDL完整使用指南 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 问题发现&#xff1a;非Steam玩家的模组困境 你是否曾经在Epic Ga…

作者头像 李华