MSM8909中LK阶段LCM屏适配与显示流程分析(二)
1、前言
在前面的文章《MSM8909中LK阶段LCM屏适配与显示流程分析(一)》,链接如下:
https://www.cnblogs.com/Cqlismy/p/12019317.html
介绍了如何使用GCDB工具生成要适配的屏幕的相关配置文件,同时,也介绍了如何在LK启动阶段中,在基于Qualcomm的LCD屏幕软件驱动框架中,修改相应的文件去适配一款屏幕,此外,该文章是"MSM8909中LK阶段LCM屏适配与显示流程分析"的第二部分,主要是分析LK启动阶段中屏幕的初始化和显示流程是怎么样的。
2、LK中屏初始化和显示流程分析
LK启动阶段中,LCM屏幕的初始化和log的显示是在aboot_init()函数中完成,调用的函数为target_display_init(),具体代码如下:
/* Display splash screen if enabled */
#if DISPLAY_SPLASH_SCREEN
dprintf(INFO, "Display Init: Start\n");
target_display_init(device.display_panel);
dprintf(INFO, "Display Init: Done\n");
#endif
开启debug信息后,LK启动阶段中会输出如下的调试信息:

从启动的输出的调试信息,可以知道大概的初始化流程了,调用target_display_init()函数后,会通过panel_id变量的值,选择相应要初始化和显示的LCD屏幕,根据LCD屏幕的相关配置参数,去完成MSM8909芯片的mipi dsi接口的初始化,然后打开panel,进行启动log的显示。
接下来,开始对代码进行分析,对于target_display_init()函数的定义在文件:
msm8909_7./bootable/bootloader/lk/target/msm8909/target_display.c
该函数的定义如下:
void target_display_init(const char *panel_name)
{
uint32_t panel_loop = ;
uint32_t ret = ;
...
do {
target_force_cont_splash_disable(false);
ret = gcdb_display_init(panel_name, MDP_REV_305, MIPI_FB_ADDR);
if (!ret || ret == ERR_NOT_SUPPORTED) {
break;
} else {
target_force_cont_splash_disable(true);
msm_display_off();
}
} while (++panel_loop <= oem_panel_max_auto_detect_panels());
}
在这里,panel_name字符串为空串,panel的选择是通过panel_id进行选择的,在上面的代码中,可以看到,target_display_init()函数调用了gcdb_display_init()函数,该函数在文件:
msm8909_7./bootable/bootloader/lk/dev/gcdb/display/gcdb_display.c
函数的定义如下所示:
int gcdb_display_init(const char *panel_name, uint32_t rev, void *base)
{
int ret = NO_ERROR;
int pan_type; /* 通过panel_id选择屏幕,并填充panelstruct和panel.panel_info */
pan_type = oem_panel_select(panel_name, &panelstruct, &(panel.panel_info),
&dsi_video_mode_phy_db); if (pan_type == PANEL_TYPE_DSI) { /* 判断panel是否是dsi显示接口 */
init_platform_data(); /* 初始化dsi显示模式的数据 */
if (dsi_panel_init(&(panel.panel_info), &panelstruct)) {
dprintf(CRITICAL, "DSI panel init failed!\n");
ret = ERROR;
goto error_gcdb_display_init;
} panel.panel_info.mipi.mdss_dsi_phy_db = &dsi_video_mode_phy_db;
panel.pll_clk_func = mdss_dsi_panel_clock;
panel.power_func = mdss_dsi_panel_power;
panel.pre_init_func = mdss_dsi_panel_pre_init;
panel.bl_func = mdss_dsi_bl_enable;
panel.fb.base = base;
panel.fb.width = panel.panel_info.xres;
panel.fb.height = panel.panel_info.yres;
panel.fb.stride = panel.panel_info.xres;
panel.fb.bpp = panel.panel_info.bpp;
panel.fb.format = panel.panel_info.mipi.dst_format;
} panel.fb.base = base;
panel.mdp_rev = rev; ret = msm_display_init(&panel); error_gcdb_display_init:
display_enable = ret ? : ;
return ret;
}
上面的函数调用后,调用oem_panel_select()函数来选择要初始化和显示的屏幕,在这里是通过panel_id进行选择的,而不是panel_name,oem_panel_select()函数返回panel的接口,如果为mipi dsi接口,初始化一些关于dsi平台的数据,base的显存的地址,对函数和某些成员变量赋值操作后,最后则是调用msm_display_init()函数完成最后的屏幕初始化和启动log的显示。
panel是一个静态的全局变量,为struct msm_fb_panel_data类型,该结构体的定义如下所示:
struct msm_fb_panel_data {
struct msm_panel_info panel_info; /* 描述panel的数据结构 */
struct fbcon_config fb;
int mdp_rev;
int rotate;
/* function entry chain */ /* 与msm底层寄存器操作相关函数API */
int (*power_func) (int enable, struct msm_panel_info *);
int (*clk_func) (int enable);
int (*bl_func) (int enable);
int (*pll_clk_func) (int enable, struct msm_panel_info *);
int (*post_power_func)(int enable);
int (*pre_init_func)(void);
};
该结构体中,比较重要的成员为panel_info,它描述了我们LCD屏幕相关的配置信息,还要一系列函数指针,在oem_panel_select()函数中完成了对该结构的函数指针初始化,是与SoC底层寄存器操作相关的API函数:
panel.pll_clk_func = mdss_dsi_panel_clock; /* panel时钟控制相关*/
panel.power_func = mdss_dsi_panel_power; /* 电源相关 */
panel.pre_init_func = mdss_dsi_panel_pre_init; /* 预初始化 */
panel.bl_func = mdss_dsi_bl_enable; /* panel背光灯使能函数 */
对于上面列出的函数的实现,就不贴了,本文只描述LK阶段中LCM屏幕初始化和显示流程,有兴趣可以自己琢磨源码实现。
最后,则是调用msm_display_init()函数完成LCM屏幕的初始化和log显示,该函数的定义在文件:
msm8909_7./bootable/bootloader/lk/platform/msm_shared/display.c
简化后的函数的定义如下所示:
int msm_display_init(struct msm_fb_panel_data *pdata)
{
int ret = NO_ERROR; panel = pdata;
if (!panel) {
ret = ERR_INVALID_ARGS;
goto msm_display_init_out;
} /* Turn on panel */
if (pdata->power_func) /* 开启panel的电源 */
ret = pdata->power_func(, &(panel->panel_info));
if (ret)
goto msm_display_init_out; /* Enable clock */
if (pdata->clk_func) /* 将dsi时钟使能 */
ret = pdata->clk_func(); ret = msm_fb_alloc(&(panel->fb)); /* 分配显存 */
if (ret)
goto msm_display_init_out; ret = msm_display_config(); /* 显示配置 */
if (ret)
goto msm_display_init_out; fbcon_setup(&(panel->fb));
display_image_on_screen(); /* 启动log载入并显示 */
ret = msm_display_on();
if (ret)
goto msm_display_init_out; /* Turn on backlight */
if (pdata->bl_func) /* 开启背光灯 */
ret = pdata->bl_func();
if (ret)
goto msm_display_init_out; msm_display_init_out:
return ret;
}
从注释中,可以很清楚地知道了流程,msm_display_init()函数,其实就是调用了全局变量panel填充的底层函数API接口,dsi接口初始化完成后,会将启动log图片复制到显示缓存,最后,背光灯打开后,我们就能看到了启动log图片了,这就是LK启动阶段中LCM屏幕的初始化和显示流程了。
3、小结
接下来,总结一下函数的调用过程,如下:
target_display_init()
|
gcdb_display_init()
|
oem_panel_select() /* 根据panel_id选择屏幕 */
|
init_platform_data() /* 初始化dsi接口 */
|
dsi_panel_init()
|
msm_display_init()
|
power_func() /* panel电源开启 */
|
clk_func() /* dis时钟开启 */
|
display_image_on_screen() /* 载入log并显示 */
|
msm_display_on()
|
bl_func() /* 开启panel的背光灯 */
本文,主要简单介绍了MSM8909中Android系统的LK启动阶段中LCM屏幕的初始化和显示流程。
MSM8909中LK阶段LCM屏适配与显示流程分析(二)的更多相关文章
- MSM8909中LK阶段LCM屏适配与显示流程分析(一)
1.前言 在驱动开发中,我们往往需要适配一些新的屏幕或者调试一些屏幕的参数等,对于Qualcomm的MSM8909这款SoC,当启动Android系统时,会有一个LK阶段,该阶段用来启动Linux内核 ...
- Android中的跨进程通信方法实例及特点分析(二):ContentProvider
1.ContentProvider简单介绍 在Android中有些数据(如通讯录.音频.视频文件等)是要供非常多应用程序使用的.为了更好地对外提供数据.Android系统给我们提供了Content P ...
- iOS 横竖屏适配 笔记
研究消息转发机制 已经一周多了,但是 还是没整理出博客, 还是先写一个 项目中遇到的 横竖屏适配问题. // 开启自动转屏 - (BOOL)shouldAutorotate { return YES; ...
- mtk lk阶段的lcm流程
一.lk进入kmain() 1. vendor/mediatek/proprietary/bootable/bootloader/lk/arch/arm/srt0.S bl kmain 二.初始化lk ...
- 移动端H5页面高清多屏适配方案
背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...
- Phonegap之ios对iPhone6和Plus的闪屏适配 -- xmTan
故事的发生起于,由于老板强烈要求app在iPhone6和5有一样的工具栏,然后前端妹子用@media为iPhone6和Plus做了样式适配.然后问题来了,竟然奇葩的发现@media样式只对iPhone ...
- webapp:移动端高清、多屏适配方案(zz)
来源: http://sentsin.com/web/1212.html 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉 ...
- 解惑好文:移动端H5页面高清多屏适配方案 (转)
转自:http://mobile.51cto.com/web-484304.htm https://github.com/amfe/lib-flexible/blob/master/src/makeg ...
- 移动端高清、多屏适配方案 [来源:http://div.io/topic/1092]
Lovesueee 发布于 8 月前 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视 ...
随机推荐
- 恢复Chrome 78以上版本的地址栏https和www显示
Google在Chrome不知道是脑子抽抽还是怎么回事,非要把https://www从地址栏中隐藏掉. htttps://www.pool.ntp.org就给你显示个pool.ntp.org,这分明就 ...
- redis pipeline批量处理提高性能
Redis使用的是客户端-服务器(CS)模型和请求/响应协议的TCP服务器.Redis客户端与Redis服务器之间使用TCP协议进行连接,一个客户端可以通过一个socket连接发起多个请求命令.每个请 ...
- shell 命名管道,进程间通信, ncat作http server
命名管道基础 命名管道也被称为FIFO文件, 在文件系统中是可见的,并且跟其它文件一样可以读写! 命名管道特点: 当写进程向管道中写数据的时候,如果没有进程读取这些数据,写进程会堵塞 当读取管道中的数 ...
- git clone: HTTP Basic: Access denied 错误
git clone 报 HTTP Basic: Access denied 错误 解决方案: 1. 如果账号密码有变动 用这个命令 git config –-system –-unset creden ...
- .NET Core下自带容器IServiceCollection以及AutoFac以及AutoFac中AOP简介
https://www.cnblogs.com/artech/p/net-core-di-01.html 大内老A的在.NET Core下对这些的介绍,有一系列文章 https://www.cnblo ...
- RPM包安装——手动安装
RPM包安装 手动安装 挂载光盘 首先查看光盘是否挂载(使用mount命令) RPM包存放位置 在你光盘挂载点的Packages目录下 使用 ll | grep 关键字 可以快速找到你想要的RPM包 ...
- vuejs之路由应用之二
现在我们开始一个应用: 一个应用中包含4个组件,我们暂且可以想象是4个页面,首先是App.vue,App.vue中又包含3个子组件:About.vue,Home.vue,Document.vue Ap ...
- 使QScrollArea的背景透明,并且不影响子控件
使QScrollArea的背景透明,乍看很easy,其实却是一个目前百度上百不出来的问题; 最容易想到的,用qss: scrollArea->setStyleSheet("backgr ...
- 一文解读ARM架构 (转)
本文主要介绍的是arm架构和x86架构的区别,首先介绍了ARM架构图,其次介绍了x86架构图,最后从性能.扩展能力.操作系统的兼容性.软件开发的方便性及可使用工具的多样性及功耗这五个方面详细的对比了a ...
- Python—闭包和装饰器
闭包 定义:内部函数对外部函数变量的引用,则将该函数与用到的变量称为闭包. 闭包必须满足以下三个条件: 必须有一个内嵌函数. 内嵌函数必须引用外部函数中的变量. 外部函数返回值必须是内嵌函数的引用. ...