高通平台MSM8916LCM模块移植(一)-bootloader部分

2023-10-30

此次移植打算分成两个模块来说,bootloader部分和kernel部分。在实际的移植调试过程中也是这么分成了两个部分分别调试。

           高通平台中的bootloader叫做LK(Little Kernel,对于LCM来说LK部分相当重要,它不仅要负责开机部分的LCD显示任务,还要负责传参给kernel的LCM驱动,指导kernel选择合适的LCM参数。

1、LK中LCM启动流程

注:read_panel_id()和read_panel_id_ddr3()为私有添加,非高通库上代码。
在这个流程图中,需要着重了解的有oem_panel_select() mdss_dsi_initialize() 和read_panel_id()函数,这三个函数主要是做lcd兼容,下面来具体看函数内容。

2、oem_panel_select()

这个函数在 android/bootloader/lk/target/msm8916/oem_panel.c文件中
主要是识别不同IC,赋值给参数panel_id,panel_id的使用在同一文件中的 init_panel_data()函数中。
[objc]  view plain  copy
  1. /********************************************************  
  2. *Name:        oem_panel_select  
  3. *Function:    selection different lcm panel  
  4. *Description: 1)This func will be roaded twice,first time use default value  
[objc]  view plain  copy
  1.                 second time depend on lk_lcd_id value match correct branch.  
  2. *Author:      Jerry.peng  
  3. *********************************************************/  
  4. bool oem_panel_select(const charchar *panel_name, struct panel_struct *panelstruct,  
  5.             struct msm_panel_info *pinfo,  
  6.             struct mdss_dsi_phy_ctrl *phy_db)  
  7. {  
  8.     uint32_t soc_version = board_soc_version();  
  9.     uint32_t gpio_state = 0;  
  10.   
  11.     gpio_tlmm_config(LCM_GPIO_DETECT, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_ENABLE);<span style="color:#33ff33;"> </span><span style="color:#009900;">//这个主要是硬件检测lcd_id引脚,用来区分同一IC不同模组厂屏</span>  
  12.     mdelay(10);  
  13.     gpio_state = gpio_status(LCM_GPIO_DETECT);  
  14.     dprintf(CRITICAL, "[PHC]:oem_panel.c soc_version = 0X%x value,gpio_state=%d\n",soc_version,gpio_state);  
  15.             if(0x6089 == lk_lcd_id || 0xFFFF == lk_lcd_id){                     <span style="color:#009900;">  //lk_lcd_id 是自己设定的一个全局变量,赋值在mipi_dsi.c文件中</span>  
  16.                 if(gpio_state){                                            <span style="color:#009900;">//这个是同一个IC,不同模组厂的情况,由之前说的lcd_id引脚来判定</span>  
  17.                     panel_id = ILI9806E_WVGA_VIDEO_HONGTAO_PANEL;  
  18.                     dprintf(CRITICAL,"[PHC]: ILI9806E hongtao panel choosed\n");  
  19.                 } else {  
  20.                     panel_id = ILI9806E_WVGA_VIDEO_HAIFEI_PANEL;  
  21.                     dprintf(CRITICAL,"[PHC]: ILI9806E haifei panel choosed\n");  
  22.                 }  
  23.             }  
[objc]  view plain  copy
  1. else if(0x8018 == lk_lcd_id){                                     <span style="background-color: rgb(255, 255, 255);"><span style="color:#009900;">//此处为IC(OTM8019)的情况</span></span>  
  2.     if(gpio_state){  
  3.         panel_id = OTM8019_WVGA_VIDEO_SUXIAN_PANEL;  
  4.         dprintf(CRITICAL,"[PHC]: otm8019 panel choosed\n");  
  5.     } else {  
  6.         panel_id = OTM8019_WVGA_VIDEO_HAOSHITONG_PANEL;  
  7.         dprintf(CRITICAL,"[PHC]: otm8018b panel choosed\n");  
  8.     }  
  9. }  
[objc]  view plain  copy
  1.             else if (0x3551 == lk_lcd_id){                               <span style="font-family: Arial, Helvetica, sans-serif;"><span style="color:#009900;">//此处为IC(NT35512S)的情况</span></span>  
  2.   
  3.                     panel_id = NT35512S_WVGA_VIDEO_HAIFEI_PANEL;  
  4.                     dprintf(CRITICAL,"[PHC]: NT35512S haifei panel choosed\n");  
  5.             }  
  6. panel_init:  
  7.     pinfo->pipe_type = MDSS_MDP_PIPE_TYPE_RGB;  
  8.     return init_panel_data(panelstruct, pinfo, phy_db);  
  9. }  

3、mdss_dsi_initialize()

mdss_dsi_initialize() 在文件Android/bootable/bootloader/lk/platform/msm_shared/mipi_dsi.c 中

在 mipi_dsi.c 文件开始先申明全局变量 lk_lcd_id

[cpp]  view plain  copy
  1. uint32_t lk_lcd_id = 0xFFFF;  

[cpp]  view plain  copy
  1. /***************************************************************** 
  2. *Name:        mdss_dsi_panel_initialize 
  3. *Function:    Read LCM id & send lcm config 
  4. *Descritpion: 1/ soc_version use for identify T3F project 
  5.               2/ lcm_id_retry usr for identify 2 lane or 4lane mipi 
  6. *******************************************************************/  
  7. int mdss_dsi_panel_initialize(struct mipi_dsi_panel_config *pinfo, uint32_t  
  8.         broadcast)  
  9. {  
  10.     int status = 0;  
  11.       
  12. #if (DISPLAY_TYPE_MDSS == 1)  
  13. <span style="background-color: rgb(255, 255, 255);"><span style="color:#cc33cc;">   if (0xffff == lk_lcd_id ){                                      </span><span style="color:#009900;">//洋红色这部分代码是自己添加的和上面函数所说的oem_panel_select()配合使用</span><span style="color:#cc33cc;">  
  14.             lk_lcd_id = read_panel_id();                   </span><span style="color:#009900;"//此为读ID的函数调用处</span><span style="color:#cc33cc;">  
  15.         target_force_cont_splash_disable(true);  
  16.         msm_display_off();  
  17.         target_force_cont_splash_disable(false);  
  18.         target_display_init(NULL);                             </span><span style="color:#009900;">//从上面流程图看以看出,这个是屏初始化的开始函数,相当于第二次初始化屏幕</span><span style="color:#cc33cc;">  
  19.         return 1;  
  20.     }</span></span>  
  21.     if (pinfo->panel_cmds) {  
  22.         if (broadcast) {  
  23.             status = mdss_dual_dsi_cmds_tx(pinfo->panel_cmds,  
  24.                     pinfo->num_of_panel_cmds);  
  25.   
  26.         } else {  
  27.             status = mipi_dsi_cmds_tx(pinfo->panel_cmds,  
  28.                     pinfo->num_of_panel_cmds);  
  29.             if (!status && target_panel_auto_detect_enabled())  
  30.                 status =  
  31.                     mdss_dsi_read_panel_signature(pinfo->signature);  
  32.         }  
  33.         dprintf(CRITICAL,"[PHC]: status=%d\n",status);  
  34.     }  
  35. #endif  
  36.     return status;  
  37. }  

4、read_panel_id()

read_panel_id()为读取LCM ID的函数,里面包括读取各中IC函数,详细看下面代码。

[cpp]  view plain  copy
  1. <pre name="code" class="cpp">/***************************************************************** 
  2. *Name:        read_panel_id 
  3. *Function:    Read LCM id 
  4. *Descritpion: 1/ lcm_id_retry usr for identify 2 lane or 4lane mipi 
  5.               2/ lcm_id_retry == 0 means 2 lane 
  6. *Author:      Jerry.peng 
  7. *******************************************************************/  
  8. uint32_t read_panel_id(void)  
  9. {  
  10.     uint32_t lcd_id = 0xffff;  
[cpp]  view plain  copy
  1. <span style="white-space:pre">    </span>if( mdss_dsi_read_ili9806e_id() )  
  2. <span style="white-space:pre">        </span>lcd_id = 0x6089;       /* panel ic is ili9806e */  
  3. <span style="white-space:pre">    </span>else if( mdss_dsi_read_otm8018b_id())  
  4. <span style="white-space:pre">        </span>lcd_id = 0x8018;       /* panel ic is otm8018b */  
  5. <span style="white-space:pre">    </span>else if( mdss_dsi_read_nt35512s_id() )  
  6. <span style="white-space:pre">        </span>lcd_id = 0x3551;       /* panel ic is nt35512s */  
  7.     if(lcd_id == 0xffff){  
  8.         lcd_id = 0x1283;  
  9.         dprintf(CRITICAL,"[PHC]: no panel id readed use default \n");  
  10.     return lcd_id;  
  11. }  

不同IC的读取ID的函数都大同小异,我这里就用ili9806e这颗IC来举例:
[cpp]  view plain  copy
  1. <pre name="code" class="cpp">static struct mipi_dsi_cmd apex_ili9806e_panel_set_cmd[] = {  
  2.        {sizeof(apex_ili9806e_cmd0), apex_ili9806e_cmd0},  
  3. };  
  4.   
  5. static char apex_ili9806e_panel_set_pkt_size[4] = {0x08, 0x00, 0x37, 0x80};  
  6. static struct mipi_dsi_cmd apex_ili9806e_panel_set_pkt_size_cmd[] = {  
  7.     {sizeof(apex_ili9806e_panel_set_pkt_size), apex_ili9806e_panel_set_pkt_size},};  
  8. static char apex_ili9806e_panel_manufacture_id[4] = {0x00, 0x00, 0x06, 0xA0};  
  9. static struct mipi_dsi_cmd apex_ili9806e_panel_manufacture_id_cmd[] = {  
  10.     {sizeof(apex_ili9806e_panel_manufacture_id), apex_ili9806e_panel_manufacture_id},};  
[cpp]  view plain  copy
  1. <pre name="code" class="cpp">static bool mdss_dsi_read_ili9806e_id(void)  
  2. {  
  3.     char rec_buf[24];  
  4.     char *rp = rec_buf;  
  5.     uint32_t *lp,temp,ret, data = 0;  
  6.   
  7.   
  8.         ret = mipi_dsi_cmds_tx(apex_ili9806e_panel_set_cmd, ARRAY_SIZE(apex_ili9806e_panel_set_cmd));  
  9.         mdelay(10);  
  10.         ret = mipi_dsi_cmds_tx(apex_ili9806e_panel_set_pkt_size_cmd, ARRAY_SIZE(apex_ili9806e_panel_set_pkt_size_cmd));  
  11.         mdelay(10);  
  12.         ret = mipi_dsi_cmds_tx(apex_ili9806e_panel_manufacture_id_cmd, ARRAY_SIZE(apex_ili9806e_panel_manufacture_id_cmd));  
  13.         mdelay(10);  
  14.         if(ret == 1)  
  15.             lcm_id_retry += 1;  
  16.         mipi_dsi_cmds_rx(&rp, 3);  
  17.   
  18.   
  19.         lp = (uint32_t *)rp;  
  20.         data = (uint32_t)*lp;  
  21.         data = ntohl(data);  
  22.   
  23.   
  24.         data = data & 0xFF;  
  25.         dprintf(CRITICAL,"[PHC]: ili9806e id: 0x%x\n", data);  
  26.         if(data == 0x98) {  
  27.             lcm_id_retry = 0;  
  28.             return true;  
  29.         }  
  30.         else  
  31.             return false;  
  32. }  

       到此,整个lk中LCM兼容和移植的主体部分就已经完成了,剩下就是填LCM参数进.h文件,这里再对整个流程进行一个补充整理。
       首先解释下为什么不用高通默认的兼容方法,因为高通默认的兼容需要用到各种硬件id,平台id,这些都是在SBL中设定的,修改起来麻烦,而且可以兼容的屏幕个数有限,我上面所说的这种方法加上我拓展的一些代码,已经可以兼容十多块屏幕。
整个兼容方法的思路是,在LCM进行第一遍初始化的时候,什么都不变,但进行到mipi_dsi.c文件中的mdss_dsi_initialize()函数的时候,回去读当前使用的LCM IC 的id
,如果和默认的屏幕id一样,则不进行第二次初始化,若不一样,则重新初始化,这个时候全局变量lk_lcd_id已经被赋值,当第二遍初始化到了oem_panel.c文件的oem_panel_select()函数中,函数根据lk_lcd_id的值来匹配正确的屏幕变量。匹配完成之后继续未完成的屏幕初始化,至此整个流程走完,屏幕点亮!

      文章介绍完毕,如有错误欢迎大家指正~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高通平台MSM8916LCM模块移植(一)-bootloader部分 的相关文章

  • 如何在android中点击画布上绘制的圆圈?

    我正在开发一个人脸检测应用程序 在这个应用程序中 我必须在脸上的眼睛和嘴巴用户可以点击拖动圆圈 在检测到的人脸上根据自己设置位置 因此 所有圆圈都已成功绘制在脸上 但我无法单击特定圆圈并使用缩小选项在整个脸上移动 请建议我有关相同问题的正确
  • Whatsapp 在 Android 中共享音频文件时正在剪切音频文件

    我在共享格式不是 mp3 的音频文件时遇到问题 文件被共享 但长度较短 例如 如果文件有 10 秒 则仅共享 5 秒 如果我使用 mp3 格式 它会完全共享 但其他格式会出现问题 注意 该文件在其他应用程序 如Messenger 中共享没有
  • 如何使用 Android 版 Facebook 同步的联系人图片

    我的手机上安装了 Android 版 Facebook 它会自动将联系人列表中人员的 FB 个人资料图片同步到我的手机 我想在我访问的应用程序中使用这些图片ContactsContract PhoneLookup 我真的需要 Faceboo
  • Android 构建 gradle 在特定设备上失败

    我面临一个奇怪的问题 当我编译我的应用程序以在 Android 7 0 的设备上运行它时 它可以工作 但是当我尝试为 Android 4 2 1 的设备进行编译时 它会失败并出现以下错误 错误 任务 app transformClasses
  • 在屏幕上随机生成一个圆圈并将其设为绿色或红色

    所以我一直在尝试制作一个游戏应用程序 它可以在 Android 屏幕上随机显示带有文本的红色按钮或带有文本的绿色按钮 如果有人可以帮助我 我将不胜感激 另外 如果有人知道如何做到这一点 我想慢慢地产生更快的酷优势 谢谢 SuppressLi
  • 如何从静态快捷方式启动活动的现有实例

    我的应用程序中有一个活动 MainActivity 并且有一个静态快捷方式 指向 TempActivity 由于静态快捷方式将始终设置 FLAG ACTIVITY NEW TASK 和 FLAG ACTIVITY CLEAR TASK 因此
  • 不使用 CookieManager 的 Android 会话 cookie

    我的应用程序进行多次网络调用以获得身份验证 我需要将此会话存储在 cookie 中 我想使用 Cookie Manager 但经过一些研究后 我发现它仅适用于 API 9 及更高版本 并且我的应用程序需要向后兼容 我使用 HTTPURLCo
  • Android 上的硬币识别

    我目前正在开发一个 Android 应用程序 它能够拍摄硬币的现有图像 或者使用内置摄像头扫描单个硬币 非常像 Google Goggles 我正在使用 Android 版 OpenCV 我的问题如下 什么方法最适合使用 OpenCV 在
  • Twitter 集成期间获取访问令牌函数行为不当

    我只是想使用 twitter4j 从我的 Android 应用程序向 Twitter 分享文本 首先 我尝试的是我创建了一个新项目 并且这个特定的代码运行成功 然后我在我的应用程序中混合了该特定代码 登录 Twitter 成功完成 之后我发
  • NullPointerException org.chromium.android_webview.AwContents$AwViewMethodsImpl.onDragEvent

    大约 10 天前 我的应用程序开始记录此异常 在开发控制台上看到 java lang NullPointerException at org chromium android webview AwContents AwViewMethods
  • 将 ArrayList 保存在捆绑包 savingInstanceState 中

    ArrayList 是在类级别定义的 这些是我保存的实例方法 Override protected void onSaveInstanceState Bundle outState super onSaveInstanceState out
  • 如何在Firebase Android应用程序中分离两个不同的用户?

    我有一个应用程序 有两种不同类型的用户 一种是教师 第二种是普通用户 如果普通会员登录 他会去normal memberActivity如果他是教师会员 他会去Teacher memberActivity 我如何在登录活动中执行此操作 我的
  • Android 在创建时出现 SQLiteException

    首先我想说我是android新手 所以如果这个问题太愚蠢我很抱歉 我正在为带有两个表的 SQLite 数据库编写一个内容提供程序 表格上是在导航抽屉活动中显示列表 第二个表格是在 ListFragment 中显示 每次启动应用程序时 我都会
  • 将搜索结果更新为 Android 中的 Lazy Adapter

    我有项目列表 想为其实现搜索功能 因此 我有一个带有 addTextChangedListener 的文本框 搜索结果运行良好 但当我尝试将结果设置为 ListView 时 新结果将附加到旧结果中 我正在使用惰性适配器 如何清除适配器中的旧
  • BluetoothLeScanner 服务内部问题

    Update从Android 10以上我认为你需要ACCESS BACKGROUND LOCATION权限 因此 如果此代码在最新的 Android 版本上不起作用 就是针对此问题的 ACCESS BACKGROUND LOCATION 受
  • 在Android的activity中调用onResume

    在活动的过程中通过调用 this OnResume 强制 onResume 事件可以吗 或者我应该实现另一个由 OnResume 和第一个成员调用的过程 实现在您的重写中调用的另一个过程onResume 后者不打算由您调用 它是一种方便的方
  • Android 将菜单项在操作栏中向左对齐

    我的应用程序中有一个操作栏 它显示我定义的菜单项res menu activity main xml 我的菜单项在操作栏上向右对齐 我希望它们左对齐 我为此找到的唯一解决方案使用了自定义操作栏 如下所示 将菜单项放置在 Honeycomb
  • 协程和 Firebase:如何实现类似 Javascript 的 Promise.all()

    在 Javascript 中 您可以同时启动两个 或更多 异步任务 等待它们完成 然后执行某些操作 继续 const firstReturn secondReturn await Promise all firstPromise secon
  • RecyclerView元素更新+异步网络调用

    我有一个按预期工作的回收视图 我的布局中有一个按钮可以填充列表 该按钮应该进行异步调用 根据结果 我更改按钮的外观 这一切都发生得很好 但是 当我单击按钮并快速向下滚动列表时 异步调用的结果会更新新视图的按钮 代替旧视图的视图 我该如何处理
  • SambaFileInputStream 和 FileInputStream 有什么不同?

    我需要从 samba 服务器流式传输视频 并且我使用 nanohttpd 在我的项目中创建简单的服务器 当我使用本地文件中的 fileinputstream 时 视频视图可以按设置播放视频 http localhost 8080 publi

随机推荐

  • GTest基础学习-05-第5个单元测试-父test fixture和子test fixture的使用

    这篇来学习Gtest官方示例中的第5个 为什么直接跳过第4个 因为第四个是测试一个简单的计数器 看了下单元测试内容 没有新的知识点 就一个TEST 里面使用了连续3 4个EXPECT TRUE断言宏 完全没有任何新的知识点 就不再介绍第4个
  • html打印,可以控制换页

    显示效果 核心代码 div class pageBreak div 完整代码
  • 计算机网络之域名

    文章目录 计算机网络之域名 1 域名组成 2 域名分类 2 1顶级域名 2 2二级域名 2 3三级域名 2 4顶级域名其他分类 3 中文域名 4 www 计算机网络之域名 1 域名组成 2 域名分类 顶级域名包括顶级域名 二级域名 三级域名
  • docker学习(四)docker run用法

    目录 前言 一 参数列表 二 使用示例 前言 docker run 命令用于创建一个新的容器 启动一个新的进程 并为这个进程分配其独占的文件系统 网络资源等 通过参数设置可以覆盖镜像和容器的一些默认配置 一 参数列表 a 指定标准输入输出内
  • shell的内置命令

    shell有很多内置在其源代码中的命令 这些命令是内置的 所以shell不必到磁盘上搜索它们 执行速度因此加快 bash提供的help功能 能提供任何内置命令的在线帮助 表14 12列出了这些内置命令 表14 12 内置命令 命 令 功 能
  • eclipse常用设置

    eclipse常用设置 设置字体 window preferences General Appearace Colors and Fonts 设置字符编码 window preferences General Workspace Text
  • Spire.XLS 图表系列教程:C# 如何不使用工作数据创建Excel图表以及Excel雷达图

    更多资源查看 Spire XLS工作表教程 Spire Doc系列教程 Spire PDF系列教程 下载Spire XLS最新试用版 Spire XLS for NET 是一款专业的 NET Excel 组件 它可以用在各种 NET 框架中
  • 利用Dialogflow构建聊天机器人

    作者 Priyanka Vergadia Developer Advocate Google Anu Srivastava Developer Advocate AI ML 在如今的办公环境下 在线协同工作至关重要 保持生产力也是关键 聊天
  • 用Python自动化操作PPT,看完这篇文章就够了!

    作者 超级大洋葱806 https tangxing blog csdn net article details 109568830 大家好 我是小z 今天给大家分享一波Python自动化操作PPT的干货 1 PPT自动化能干什么 有什么优
  • django 项目中脚本启动

    django项目中的脚本如何快速方便启动 如上如 创建文件script放置脚本项目文件 在manage py同目录下创建run script py文件启动脚本 run script py代码 coding utf 8 import os i
  • ==与equals有什么区别

    与equals的区别 相同点 1 和equals都是用于完成比较操作 2 和equals的判定结果都是boolean值 true或false 不同点 1 是个运算符 本质上用于比较两个值是否相等 2 使用 运算符比较的值可以是基本类型的值
  • 在ubuntu20.4下安装ROS-noetic(全步骤经反复验证成功)

    注意 如果有conda环境 conda deactivate推出环境 1 4步骤都是很顺利的 如果下载失败请换源 第5步rosdep比较繁琐 但是根据我的使用情况 发现不按照rosdep也能正常使用 更新于2022 3 安装过程的打印信息可
  • 【图像处理】《数字图像处理-冈萨雷斯》笔记

    数字图像处理 冈萨雷斯 笔记 第一章 绪论 图像处理实例 伽马射线成像 X射线成像 紫外波段成像 可见光以及红外线成像 微波波段成像 无线电波成像 声波成像 图像处理的基本步骤 图像获取 滤波与增强 图像复原 彩色图像处理 小波与分辨率处理
  • JMeter 安装教程(详细安装教程)

    JMeter 安装教程 详细安装教程 一 jdk下载 注意 因为jmeter运行依赖jdk环境 所以在安装jmeter之前需要安装jdk且配置环境变量 需要jdk1 8以上版本 1 jdk下载地址 http www oracle com t
  • Vue实现下载及文件重命名

    效果如下 实现步骤 html
  • 理解JavaScript作用域和作用域链

    一 JavaScript中的作用域 作用域是当前的执行上下文 值和表达式在其中 可见 或可被访问 如果一个变量或表达式不在当前的作用域中 那么它是不可用的 function foo var x sfa console log x x is
  • 31黑马QT笔记之QPixmap、QImage、QPicture功能大总结

    31黑马QT笔记之QPixmap QImage QPicture功能大总结 QPixmap QImage既可以用于绘图 又可以作绘图设备时保存图片 而QPicture只能用于作绘图设备时保存图片状态 保存前需要用到前两种方法绘图 要显示必须
  • Go Lang 从Request中解析文件和参数

    如果要处理上传的文件 就必须使用multipart form data编码 处理multipart form data编码的请求时 解析使用ParseMultipartForm 之后从MultipartForm字段取值 前端上传代码
  • powershell 学习笔记

    命令模式 字符串不需要加引号 除变量和圆括号中的内容外的所有内容均可看作字符串 copy users txt accounts txt copy src dest write host 2 2 表达式模式 以最高级别语言分析方法来进行分析
  • 高通平台MSM8916LCM模块移植(一)-bootloader部分

    目录 LK中LCM启动流程 oem panel select mdss dsi initialize read panel id 此次移植打算分成两个模块来说 bootloader部分和kernel部分 在实际的移植调试过程中也是这么分成了