此次移植打算分成两个模块来说,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. 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>
  11. mdelay(10);
  12. gpio_state = gpio_status(LCM_GPIO_DETECT);
  13. dprintf(CRITICAL, "[PHC]:oem_panel.c soc_version = 0X%x value,gpio_state=%d\n",soc_version,gpio_state);
  14. if(0x6089 == lk_lcd_id || 0xFFFF == lk_lcd_id){                     <span style="color:#009900;">  //lk_lcd_id 是自己设定的一个全局变量,赋值在mipi_dsi.c文件中</span>
  15. if(gpio_state){                                            <span style="color:#009900;">//这个是同一个IC,不同模组厂的情况,由之前说的lcd_id引脚来判定</span>
  16. panel_id = ILI9806E_WVGA_VIDEO_HONGTAO_PANEL;
  17. dprintf(CRITICAL,"[PHC]: ILI9806E hongtao panel choosed\n");
  18. } else {
  19. panel_id = ILI9806E_WVGA_VIDEO_HAIFEI_PANEL;
  20. dprintf(CRITICAL,"[PHC]: ILI9806E haifei panel choosed\n");
  21. }
  22. }
[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. panel_id = NT35512S_WVGA_VIDEO_HAIFEI_PANEL;
  3. dprintf(CRITICAL,"[PHC]: NT35512S haifei panel choosed\n");
  4. }
  5. panel_init:
  6. pinfo->pipe_type = MDSS_MDP_PIPE_TYPE_RGB;
  7. return init_panel_data(panelstruct, pinfo, phy_db);
  8. }

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. #if (DISPLAY_TYPE_MDSS == 1)
  12. <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;">
  13. lk_lcd_id = read_panel_id();                   </span><span style="color:#009900;"> //此为读ID的函数调用处</span><span style="color:#cc33cc;">
  14. target_force_cont_splash_disable(true);
  15. msm_display_off();
  16. target_force_cont_splash_disable(false);
  17. target_display_init(NULL);                             </span><span style="color:#009900;">//从上面流程图看以看出,这个是屏初始化的开始函数,相当于第二次初始化屏幕</span><span style="color:#cc33cc;">
  18. return 1;
  19. }</span></span>
  20. if (pinfo->panel_cmds) {
  21. if (broadcast) {
  22. status = mdss_dual_dsi_cmds_tx(pinfo->panel_cmds,
  23. pinfo->num_of_panel_cmds);
  24. } else {
  25. status = mipi_dsi_cmds_tx(pinfo->panel_cmds,
  26. pinfo->num_of_panel_cmds);
  27. if (!status && target_panel_auto_detect_enabled())
  28. status =
  29. mdss_dsi_read_panel_signature(pinfo->signature);
  30. }
  31. dprintf(CRITICAL,"[PHC]: status=%d\n",status);
  32. }
  33. #endif
  34. return status;
  35. }

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. static char apex_ili9806e_panel_set_pkt_size[4] = {0x08, 0x00, 0x37, 0x80};
  5. static struct mipi_dsi_cmd apex_ili9806e_panel_set_pkt_size_cmd[] = {
  6. {sizeof(apex_ili9806e_panel_set_pkt_size), apex_ili9806e_panel_set_pkt_size},};
  7. static char apex_ili9806e_panel_manufacture_id[4] = {0x00, 0x00, 0x06, 0xA0};
  8. static struct mipi_dsi_cmd apex_ili9806e_panel_manufacture_id_cmd[] = {
  9. {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. ret = mipi_dsi_cmds_tx(apex_ili9806e_panel_set_cmd, ARRAY_SIZE(apex_ili9806e_panel_set_cmd));
  7. mdelay(10);
  8. ret = mipi_dsi_cmds_tx(apex_ili9806e_panel_set_pkt_size_cmd, ARRAY_SIZE(apex_ili9806e_panel_set_pkt_size_cmd));
  9. mdelay(10);
  10. ret = mipi_dsi_cmds_tx(apex_ili9806e_panel_manufacture_id_cmd, ARRAY_SIZE(apex_ili9806e_panel_manufacture_id_cmd));
  11. mdelay(10);
  12. if(ret == 1)
  13. lcm_id_retry += 1;
  14. mipi_dsi_cmds_rx(&rp, 3);
  15. lp = (uint32_t *)rp;
  16. data = (uint32_t)*lp;
  17. data = ntohl(data);
  18. data = data & 0xFF;
  19. dprintf(CRITICAL,"[PHC]: ili9806e id: 0x%x\n", data);
  20. if(data == 0x98) {
  21. lcm_id_retry = 0;
  22. return true;
  23. }
  24. else
  25. return false;
  26. }

到此,整个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的值来匹配正确的屏幕变量。匹配完成之后继续未完成的屏幕初始化,至此整个流程走完,屏幕点亮!

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

0

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

  1. 高通平台MSM8916LCM模块移植(一)-bootloader部分【转】

    本文转载自:http://www.mobile-open.com/2016/970947.html 高通平台中的bootloader叫做LK(Little Kernel,对于LCM来说LK部分相当重要 ...

  2. 高通平台的bootloader过程【转】

    ====================基本知识=======================LK是(L)ittle (K)ernel的缩写.高通平台android普遍采用LK作为其bootloade ...

  3. 高通平台Bootloader启动流程【转】

    本文转载自:http://blog.csdn.net/fang_first/article/details/49615631 ====================基本知识============= ...

  4. 【转】高通平台android 环境配置编译及开发经验总结

    原文网址:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...

  5. 高通平台 lcd driver 调试小结

    一.概述 1.1 简介 本文档主要包括LCD模块的驱动流程分析.Framebuffer相关知识.Gralloc等相关内容,以及LCD调试的一些经验和相关bug的分析和讲解. 1.2  开发环境 And ...

  6. 高通、猎户机型Android典型bootloader分析

    1.bootloader是什么? 简单地说,bootloader 就是在操作系统内核运行之前运行的一段小程序.通过这段小程序,我们可以初始化硬件设备.建立内存空间的映射图,从而将系统的软硬件环境带到一 ...

  7. 高通平台msm8909 LK 实现LCD 兼容

    前段时间小米出现红米note2 换屏门,现在我们公司也要上演了:有两个供应商提供不同IC 的LCD panel. 软件区分的办法是读取LCD IC 的ID 寄存器,下面解析高通平台LK中LCD兼容的过 ...

  8. [修改高通平台WIFI MAC 地址] & [adb over wifi]

    [修改高通平台WIFI MAC 地址]fccmd --helpfccmd startfccmd getwifimacfccmd setwifimac 74:AC:5F:F5:D7:40 [adb ov ...

  9. android 6.0 高通平台sensor 工作机制及流程(原创)

    最近工作上有碰到sensor的相关问题,正好分析下其流程作个笔记. 这个笔记分三个部分: sensor硬件和驱动的工作机制 sensor 上层app如何使用 从驱动到上层app这中间的流程是如何 Se ...

随机推荐

  1. Android智能手机中各种音频场景下的audio data path

    上一篇文章(Android智能手机上的音频浅析)说本篇将详细讲解Android智能手机中各种音频场景下的音频数据流向,现在我们就开始.智能手机中音频的主要场景有音频播放.音频录制.语音通信等.不同场景 ...

  2. iOS 定位简单使用

    一.配置 导入库CoreLocation. 2.info.plist配置key NSLocationWhenInUseUsageDescription和NSLocationAlwaysUsageDes ...

  3. dev gridcontrol 无法编辑 解决方案

    1.确认表格打开编辑 gridView1.OptionsBehavior.Editable = True 2.确认列打开编辑 gridView1.Columns("Name").O ...

  4. Splay讲解

    Splay讲解 Splay是平衡树的一种,是一种二叉搜索树,我们先讲解一下它的核心部分. Splay的核心部分就是splay,可能有些人会说什么鬼?这样讲解是不是太不认真了?两个字回答:不是.第一个S ...

  5. left join 连表时,on后多条件无效问题

    http://www.cnblogs.com/guixiaoming/p/6516261.html left join 连表时,on后多条件无效问题 最近开发素材库项目,各种关系复杂的表,一度6张表的 ...

  6. mybatis源码解读(一)——初始化环境

    本系列博客将对mybatis的源码进行解读,关于mybatis的使用教程,可以查看我前面写的博客——传送门. 为了便于后面的讲解,我们这里首先构造一个统一环境.也可以参考mybatis官网. 1.数据 ...

  7. sqlserver 取日期年份月份

    select convert(varchar(10),datepart(YYYY,a.fssj)) as years,--得到年份convert(varchar(10),datepart(mm,a.f ...

  8. Hibernate QBC 条件查询(Criteria Queries) and Demos

    目录 创建一个Criteria 实例 限制结果集内容 结果集排序 关联 动态关联抓取 查询示例 投影Projections聚合aggregation和分组grouping 离线detached查询和子 ...

  9. find函数用法详解

    语法:find (string, sub3tring<, modifiers, startpos>),返回substring首次在string中出现的位置,若未找到,则返回0.其中:mod ...

  10. ACM Tempter of the Bone

    小狗在古老的迷宫(maze)中发现了一个骨头,这使它非常着迷.然而,当他把它捡起来的时候,迷宫开始摇晃,狗狗可以感觉到地面下沉(sinking).他意识到这块骨头是一个陷阱(trap),他拼命地想摆脱 ...