安卓系统从power键按下释放,到lcm驱动显示,整个驱动的加载流程as follows:
LK阶段:
首先执行main.c(vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6739/src/core/main.c)文件,然后执行
platform_init(/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6739/platform.c),然后执行mt_disp_init((void *)g_fb_base);
然后执行disp_lcm_probe -->
其中重点分析下 disp_lcm_probe(vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6739/disp_lcm.c)
check_lcm_node_from_DT() == 0 读取dts节点信息?
if (_lcm_count() == 0) 得到lcm的数量,如果为0返回NULL,如果为1,则
(_lcm_count()返回的是lcm_count,而lcm_count是从mt65xx_lcm_list.c中extern过来的lcm_count= sizeof(lcm_driver_list) / sizeof(LCM_DRIVER *))
lcm_drv = lcm_driver_list[0]; 读取这个数组的第一个元素;
lcm_driver_list数组从mt65xx_lcm_list.c中extern过来的
这个数组中在添加lcm驱动的时候添加了各个驱动的lcm_drv
比如,我们要添加名为Eighty_80的lcm驱动
那么我们就会在vendor/mediatek/proprietary/bootable/bootloader/lk/dev/lcm/mt65xx_lcm_list.c添加
+extern LCM_DRIVER Eighty_80_lcm_drv;
并且在LCM_DRIVER *lcm_driver_list[]中添加
#if defined(EIGHTY_80)
&Eighty_80_lcm_drv,//对应lcm驱动的主函数
#endif
其中&Eighty_80_lcm_drv则对应驱动文件中的lcm_drv
这样的话,lcm_drv= lcm_driver_list[0];就是取得驱动文件中的lcm_drv
如果为大于一个lcm驱动,首先是for循环,依次遍历lcm_driver_list这个数组:lcm_drv=lcm_driver_list[i],遍历取得各个lcm驱动的lcm_drv
之后会做判断if(lcm_drv->compare_id() != 0)
这个函数会调用到lk中lcm ic 驱动文件的compare_id函数,返回lcd的id,如果id存在,就会break跳出遍历,告诉系统使用当前这个lcm,这样的话遍历的目的就是取得机器上当前所使用的lcm的各种信息
之后会将这个lcm的各类信息传递给kernel…………这里 disp_lcm_probe就执行完
–>然后执行到primary_display_init(vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6739/primary_display.c)
–> 执行pgc->plcm= disp_lcm_probe,将当前使用的lcm驱动模型赋值给pgc->plcm
–> 之后执行ret = disp_lcm_init(pgc->plcm)就是调用到这个lcm驱动文件中的各个函数,进行初始化,load参数等等。到这里就把lcm lk加载流程串通了。
KERNEL阶段:
驱动入口函数:mtkfb_init(kernel-4.4/drivers/misc/mediatek/video/mt6739/videox/mtkfb.c)–> 执行mtkfb_driver的mtkfb_probe
–> 执行_parse_tag_videolfb(mtkfb.c) --> primary_display_init(kernel-4.4/drivers/misc/mediatek/video/mt6739/videox/primary_display.c)
–> mtkfb_find_lcm_driver(mtkfb.c)
–> mtkfb_fbinfo_init(mtkfb.c)初始化fbi
–>disp_lcm_probe():
check_lcm_node_from_DT() == 0 读取dts节点信息?
if (_lcm_count() == 0) 得到lcm的数量,如果为0返回NULL,如果为1,则
lcm_drv = lcm_driver_list[0]; if (plcm_name == NULL) 读取lcm_driver_list这个数组的第一个元素,isLCMFound = true;isLCMInited = false;
if (strcmp(lcm_drv->name, plcm_name):比较lcm_drv->name和 plcm_name,如果kernel lcm name和lk lcm name不同,return NULL;
lcm_driver_list数组从mt65xx_lcm_list.c(kernel-4.4/drivers/misc/mediatek/lcm/mt65xx_lcm_list.c)中extern过来的
这个数组中在添加lcm驱动的时候添加了各个驱动的lcm_drv
执行lcm_drv = lcm_driver_list[i]遍历取得各个lcm驱动的lcm_drv, if (!strcmp(lcm_drv->name, plcm_name))如果kernel lcm name和lk lcm name一致,
isLCMFound = true;isLCMInited = true;lcmindex = i; 然后break 跳出遍历。去执行相应lcm ic驱动的函数。
————————————————
1、Android中查看当前函数被哪个函数调用,也就是打印函数栈,方便自己平常跟读代码
a、内核的C代码中
dump_stack()
b、框架层的JAVA代码中
Exception dump = new Exception("[dumplog]");
dump.printStackTrace();
c、HAL层的CPP代码中
#include <utils/CallStack.h>
android::CallStack stack;
stack.update();
stack.log("[dumplog]", ANDROID_LOG_ERROR, "stackdump:");
Android.mk中增加(默认一般都有加了可以检查一下):
LOCAL_SHARED_LIBRARIES += libutils
2、开机过程lcm驱动初始化的重要函数调用过程
Lk中涉及到的主要文件:
vendor/mediatek/proprietary/bootable/bootloader/lk/kernel/main.c
vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6735/ddp_manager.c
vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6735/disp_lcm.c
vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6735/mt_disp_drv.c
vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6735/platform.c
vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6735/primary_display.c
vendor/mediatek/proprietary/bootable/bootloader/lk/dev/lcm/hx8363a_wvga_dsi_vdo_dz/hx8363a_wvga_dsi_vdo_dz.c
lk中重点函数调用过程:
\void kmain(void)//main.c
\static int bootstrap2(void *arg)
\void platform_init(void)//platform.c
\g_fb_size = mt_disp_get_vram_size();
\UINT32 mt_disp_get_vram_size(void)
\unsigned int DISP_GetVRamSize(void)
\vramSize = DISP_GetFBRamSize();
\UINT32 DISP_GetFBRamSize(void)
\return ALIGN_TO(DISP_GetScreenWidth(), MTK_FB_ALIGNMENT) *
DISP_GetScreenHeight() * ((DISP
\UINT32 DISP_GetScreenWidth(void)
\int primary_display_get_width(void)
\pgc->plcm = disp_lcm_probe(NULL, LCM_INTERFACE_NOTDEFINED);
\disp_lcm_handle *disp_lcm_probe(char *plcm_name, LCM_INTERFACE_ID lcm_id)
\plcm->drv->get_params(plcm->params);
\static void lcm_get_params(LCM_PARAMS *params)//LCM driver c file
\UINT32 DISP_GetScreenHeight(void)
\int primary_display_get_height(void)
\mt_disp_init((void *)g_fb_base);
\void mt_disp_init(void *lcdbase)
\primary_display_init(NULL);
\int primary_display_init(char *lcm_name)
\_build_path_direct_link();
\static int _build_path_direct_link(void)
\dpmgr_set_lcm_utils(pgc->dpmgr_handle, pgc->plcm->drv);
\ddp_modules_driver[module_name]->set_lcm_utils(module_name, lcm_drv);
\static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)//LCM driver c file
\ret = disp_lcm_init(pgc->plcm);
\lcm_drv->init()
\static void lcm_init(void)//LCM driver c file
kernel中涉及到的主要文件:
kernel-3.18/drivers/misc/mediatek/video/common/mtkfb.c
kernel-3.18/drivers/misc/mediatek/video/mt6735/ddp_manager.c
kernel-3.18/drivers/misc/mediatek/video/mt6735/disp_lcm.c
kernel-3.18/drivers/misc/mediatek/video/mt6735/primary_display.c
kernel-3.18/drivers/misc/mediatek/lcm/ hx8363a_wvga_dsi_vdo_dz/hx8363a_wvga_dsi_vdo_dz.c
kernel中重点函数调用过程:
\static int mtkfb_probe(struct device *dev)//mtkfb.c
\primary_display_init(mtkfb_find_lcm_driver(), lcd_fps, is_lcm_inited);
\int primary_display_init(char *lcm_name, unsigned int lcm_fps, int is_lcm_inited)
\pgc->plcm = disp_lcm_probe(lcm_name, LCM_INTERFACE_NOTDEFINED, is_lcm_inited);//disp_lcm.c
\disp_lcm_handle *disp_lcm_probe(char *plcm_name, LCM_INTERFACE_ID lcm_id, int is_lcm_inited)
\plcm->drv->get_params(plcm->params);
\static void lcm_get_params(LCM_PARAMS *params) //LCM driver c file
\__build_path_direct_link();
\static int __build_path_direct_link(void)
\dpmgr_set_lcm_utils(pgc->dpmgr_handle, pgc->plcm->drv);
\int dpmgr_set_lcm_utils(disp_path_handle dp_handle, void *lcm_drv)
\ddp_modules_driver[module_name]->set_lcm_utils(module_name, lcm_drv);
\static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util) //LCM driver c file