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(),具体代码如下:

  1. /* Display splash screen if enabled */
  2. #if DISPLAY_SPLASH_SCREEN
  3. dprintf(INFO, "Display Init: Start\n");
  4. target_display_init(device.display_panel);
  5. dprintf(INFO, "Display Init: Done\n");
  6. #endif

开启debug信息后,LK启动阶段中会输出如下的调试信息:

从启动的输出的调试信息,可以知道大概的初始化流程了,调用target_display_init()函数后,会通过panel_id变量的值,选择相应要初始化和显示的LCD屏幕,根据LCD屏幕的相关配置参数,去完成MSM8909芯片的mipi dsi接口的初始化,然后打开panel,进行启动log的显示。

接下来,开始对代码进行分析,对于target_display_init()函数的定义在文件:

  1. msm8909_7./bootable/bootloader/lk/target/msm8909/target_display.c

该函数的定义如下:

  1. void target_display_init(const char *panel_name)
  2. {
  3. uint32_t panel_loop = ;
  4. uint32_t ret = ;
    ...
    do {
  5. target_force_cont_splash_disable(false);
  6. ret = gcdb_display_init(panel_name, MDP_REV_305, MIPI_FB_ADDR);
  7. if (!ret || ret == ERR_NOT_SUPPORTED) {
  8. break;
  9. } else {
  10. target_force_cont_splash_disable(true);
  11. msm_display_off();
  12. }
  13. } while (++panel_loop <= oem_panel_max_auto_detect_panels());
  14. }

在这里,panel_name字符串为空串,panel的选择是通过panel_id进行选择的,在上面的代码中,可以看到,target_display_init()函数调用了gcdb_display_init()函数,该函数在文件:

  1. msm8909_7./bootable/bootloader/lk/dev/gcdb/display/gcdb_display.c

函数的定义如下所示:

  1. int gcdb_display_init(const char *panel_name, uint32_t rev, void *base)
  2. {
  3. int ret = NO_ERROR;
  4. int pan_type;
  5.  
  6. /* 通过panel_id选择屏幕,并填充panelstruct和panel.panel_info */
  7. pan_type = oem_panel_select(panel_name, &panelstruct, &(panel.panel_info),
  8. &dsi_video_mode_phy_db);
  9.  
  10. if (pan_type == PANEL_TYPE_DSI) { /* 判断panel是否是dsi显示接口 */
  11. init_platform_data(); /* 初始化dsi显示模式的数据 */
  12. if (dsi_panel_init(&(panel.panel_info), &panelstruct)) {
  13. dprintf(CRITICAL, "DSI panel init failed!\n");
  14. ret = ERROR;
  15. goto error_gcdb_display_init;
  16. }
  17.  
  18. panel.panel_info.mipi.mdss_dsi_phy_db = &dsi_video_mode_phy_db;
  19. panel.pll_clk_func = mdss_dsi_panel_clock;
  20. panel.power_func = mdss_dsi_panel_power;
  21. panel.pre_init_func = mdss_dsi_panel_pre_init;
  22. panel.bl_func = mdss_dsi_bl_enable;
  23. panel.fb.base = base;
  24. panel.fb.width = panel.panel_info.xres;
  25. panel.fb.height = panel.panel_info.yres;
  26. panel.fb.stride = panel.panel_info.xres;
  27. panel.fb.bpp = panel.panel_info.bpp;
  28. panel.fb.format = panel.panel_info.mipi.dst_format;
  29. }
  30.  
  31. panel.fb.base = base;
  32. panel.mdp_rev = rev;
  33.  
  34. ret = msm_display_init(&panel);
  35.  
  36. error_gcdb_display_init:
  37. display_enable = ret ? : ;
  38. return ret;
  39. }

上面的函数调用后,调用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类型,该结构体的定义如下所示:

  1. struct msm_fb_panel_data {
  2. struct msm_panel_info panel_info; /* 描述panel的数据结构 */
  3. struct fbcon_config fb;
  4. int mdp_rev;
  5. int rotate;
  6.  
  7. /* function entry chain */ /* 与msm底层寄存器操作相关函数API */
  8. int (*power_func) (int enable, struct msm_panel_info *);
  9. int (*clk_func) (int enable);
  10. int (*bl_func) (int enable);
  11. int (*pll_clk_func) (int enable, struct msm_panel_info *);
  12. int (*post_power_func)(int enable);
  13. int (*pre_init_func)(void);
  14. };

该结构体中,比较重要的成员为panel_info,它描述了我们LCD屏幕相关的配置信息,还要一系列函数指针,在oem_panel_select()函数中完成了对该结构的函数指针初始化,是与SoC底层寄存器操作相关的API函数:

  1. panel.pll_clk_func = mdss_dsi_panel_clock;   /* panel时钟控制相关*/
  2. panel.power_func = mdss_dsi_panel_power;    /* 电源相关 */
  3. panel.pre_init_func = mdss_dsi_panel_pre_init;   /* 预初始化 */
  4. panel.bl_func = mdss_dsi_bl_enable;   /* panel背光灯使能函数 */

对于上面列出的函数的实现,就不贴了,本文只描述LK阶段中LCM屏幕初始化和显示流程,有兴趣可以自己琢磨源码实现。

最后,则是调用msm_display_init()函数完成LCM屏幕的初始化和log显示,该函数的定义在文件:

  1. msm8909_7./bootable/bootloader/lk/platform/msm_shared/display.c

简化后的函数的定义如下所示:

  1. int msm_display_init(struct msm_fb_panel_data *pdata)
  2. {
  3. int ret = NO_ERROR;
  4.  
  5. panel = pdata;
  6. if (!panel) {
  7. ret = ERR_INVALID_ARGS;
  8. goto msm_display_init_out;
  9. }
  10.  
  11. /* Turn on panel */
  12. if (pdata->power_func) /* 开启panel的电源 */
  13. ret = pdata->power_func(, &(panel->panel_info));
  14. if (ret)
  15. goto msm_display_init_out;
  16.  
  17. /* Enable clock */
  18. if (pdata->clk_func) /* 将dsi时钟使能 */
  19. ret = pdata->clk_func();
  20.  
  21. ret = msm_fb_alloc(&(panel->fb)); /* 分配显存 */
  22. if (ret)
  23. goto msm_display_init_out;
  24.  
  25. ret = msm_display_config(); /* 显示配置 */
  26. if (ret)
  27. goto msm_display_init_out;
  28.  
  29. fbcon_setup(&(panel->fb));
  30. display_image_on_screen(); /* 启动log载入并显示 */
  31. ret = msm_display_on();
  32. if (ret)
  33. goto msm_display_init_out;
  34.  
  35. /* Turn on backlight */
  36. if (pdata->bl_func) /* 开启背光灯 */
  37. ret = pdata->bl_func();
  38. if (ret)
  39. goto msm_display_init_out;
  40.  
  41. msm_display_init_out:
  42. return ret;
  43. }

从注释中,可以很清楚地知道了流程,msm_display_init()函数,其实就是调用了全局变量panel填充的底层函数API接口,dsi接口初始化完成后,会将启动log图片复制到显示缓存,最后,背光灯打开后,我们就能看到了启动log图片了,这就是LK启动阶段中LCM屏幕的初始化和显示流程了。

3、小结

接下来,总结一下函数的调用过程,如下:

  1. target_display_init()
  2. |
  3. gcdb_display_init()
  4. |
  5. oem_panel_select() /* 根据panel_id选择屏幕 */
  6. |
  7. init_platform_data() /* 初始化dsi接口 */
  8. |
  9. dsi_panel_init()
  10. |
  11. msm_display_init()
  12. |
  13. power_func() /* panel电源开启 */
  14. |
  15. clk_func() /* dis时钟开启 */
  16. |
  17. display_image_on_screen() /* 载入log并显示 */
  18. |
  19. msm_display_on()
  20. |
  21. bl_func() /* 开启panel的背光灯 */

本文,主要简单介绍了MSM8909中Android系统的LK启动阶段中LCM屏幕的初始化和显示流程。

MSM8909中LK阶段LCM屏适配与显示流程分析(二)的更多相关文章

  1. MSM8909中LK阶段LCM屏适配与显示流程分析(一)

    1.前言 在驱动开发中,我们往往需要适配一些新的屏幕或者调试一些屏幕的参数等,对于Qualcomm的MSM8909这款SoC,当启动Android系统时,会有一个LK阶段,该阶段用来启动Linux内核 ...

  2. Android中的跨进程通信方法实例及特点分析(二):ContentProvider

    1.ContentProvider简单介绍 在Android中有些数据(如通讯录.音频.视频文件等)是要供非常多应用程序使用的.为了更好地对外提供数据.Android系统给我们提供了Content P ...

  3. iOS 横竖屏适配 笔记

    研究消息转发机制 已经一周多了,但是 还是没整理出博客, 还是先写一个 项目中遇到的 横竖屏适配问题. // 开启自动转屏 - (BOOL)shouldAutorotate { return YES; ...

  4. mtk lk阶段的lcm流程

    一.lk进入kmain() 1. vendor/mediatek/proprietary/bootable/bootloader/lk/arch/arm/srt0.S bl kmain 二.初始化lk ...

  5. 移动端H5页面高清多屏适配方案

    背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...

  6. Phonegap之ios对iPhone6和Plus的闪屏适配 -- xmTan

    故事的发生起于,由于老板强烈要求app在iPhone6和5有一样的工具栏,然后前端妹子用@media为iPhone6和Plus做了样式适配.然后问题来了,竟然奇葩的发现@media样式只对iPhone ...

  7. webapp:移动端高清、多屏适配方案(zz)

    来源: http://sentsin.com/web/1212.html 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉 ...

  8. 解惑好文:移动端H5页面高清多屏适配方案 (转)

    转自:http://mobile.51cto.com/web-484304.htm https://github.com/amfe/lib-flexible/blob/master/src/makeg ...

  9. 移动端高清、多屏适配方案 [来源:http://div.io/topic/1092]

    Lovesueee 发布于 8 月前 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视 ...

随机推荐

  1. IT兄弟连 Java语法教程 流程控制语句 分支结构语句2

    2  if-else条件语句 if-else语句的完整形式如下: if(判断条件){ A代码块(判断条件的值为true,执行) }else{ B代码块(判断条件的值为false,执行) } 当然,如果 ...

  2. Linux 内存释放

    简介 linux 内存释放通过如下命令,将cache与buff根据环境进行释放操作,避免重启释放内存. 操作 1.将内存中buff数据保存磁盘 sync 2.清理cache与buff缓存 echo 3 ...

  3. 骚操作!曾经爱过!用 Python 清理收藏夹里已失效的网站

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 小詹&有乔木 PS:如有需要Python学习资料的小伙伴可 ...

  4. 易优CMS:arcview的基础用法

    [基础用法] 名称:arcview 功能:获取单条文档数据 语法: {eyou:arcview aid='文档ID'} <a href="{$field.arcurl}"&g ...

  5. Threads(异步和多线程)

    Task是.NET Framework4.5出现的,线程是基于线程池的,然后提供丰富的api,Thread方法很多很强大,但是太过强大,没有限制. DoSomethingLong方法如下: /// & ...

  6. 自定义栈Stack 和 队列Queue

    自定义栈 接口 package com.test.custom; public interface IStack<E> { E pop(); void push(E e); E peek( ...

  7. spark 在yarn模式下提交作业

    1.spark在yarn模式下提交作业需要启动hdfs集群和yarn,具体操作参照:hadoop 完全分布式集群搭建 2.spark需要配置yarn和hadoop的参数目录 将spark/conf/目 ...

  8. Windows远程桌面多用户登录的问题

    RDP WRAPPER 同时登录 多用户补丁   https://cloud.tencent.com/developer/article/1460728   解决系统更新导致无法多用户登录的问题 问题 ...

  9. 用curl通过相同IP请求不同域名的URL

    tomcat可以从一个IP响应不同的域名. $ curl -I http://127.0.0.1:8080  -H "Host:w.example.com" 可以影响http的ho ...

  10. ARM 寻址方式

    寻址方式有 9种 1.寄存器 2.立即数 3.寄存器位移 4.寄存器间接 5.基址 6.多寄存器 7.堆栈 8.块拷贝 9.相对 1. MOV R1,R2 R1 = R2 2. MOV R0,#0x1 ...