平台:mt6582 + Android 4.4
前面就说过,在mtk代码中支持屏是可兼容的,通过调用驱动中的compare_id函数来匹配驱动和屏,这里来细看一下代码。
1. LK部分(mediatek/platform/mt6582/lk/disp_drv.c)
OOL DISP_DetectDevice(void) { //LCD_STATUS ret; DISP_LOG("shi=>%s, %d\n", __func__, __LINE__); lcm_drv = disp_drv_get_lcm_driver(NULL); if (NULL == lcm_drv) { printk("%s, disp_drv_get_lcm_driver() returns NULL\n", __func__); return FALSE; } disp_dump_lcm_parameters(lcm_params); return TRUE; }
在DISP_DetectDevice函数中调用了disp_drv_get_lcm_driver。
const LCM_DRIVER *disp_drv_get_lcm_driver(const char *lcm_name) { LCM_DRIVER *lcm = NULL; printk("[LCM Auto Detect], we have %d lcm drivers built in\n", lcm_count); printk("[LCM Auto Detect], try to find driver for [%s]\n", (lcm_name==NULL)?"unknown":lcm_name); if(lcm_count ==1) { // we need to verify whether the lcm is connected // even there is only one lcm type defined lcm = lcm_driver_list[0]; lcm->set_util_funcs(&lcm_utils); lcm->get_params(&s_lcm_params); u4IndexOfLCMList = 0; lcm_params = &s_lcm_params; lcm_drv = lcm; /* disp_drv_init_ctrl_if(); disp_drv_set_driving_current(lcm_params); disp_drv_init_io_pad(lcm_params); if(lcm_drv->compare_id) { if(LCM_TYPE_DSI == lcm_params->type){ init_dsi(FALSE); } if(lcm_drv->compare_id() == TRUE) { printk("[LCM Specified] compare id success\n"); isLCMFound = TRUE; } else { printk("[LCM Specified] compare id fail\n"); printk("%s, lcm is not connected\n", __func__); if(LCM_TYPE_DSI == lcm_params->type) DSI_Deinit(); } } else */ { isLCMFound = TRUE; } printk("[LCM Specified]\t[%s]\n", (lcm->name==NULL)?"unknown":lcm->name); goto done; } else { unsigned int i; for(i = 0;i < lcm_count;i++) { lcm_params = &s_lcm_params; lcm = lcm_driver_list[i]; printk("[LCM Auto Detect] [%d] - [%s]\t", i, (lcm->name==NULL)?"unknown":lcm->name); lcm->set_util_funcs(&lcm_utils); memset((void*)lcm_params, 0, sizeof(LCM_PARAMS)); lcm->get_params(lcm_params); disp_drv_init_ctrl_if(); disp_drv_set_driving_current(lcm_params); disp_drv_init_io_pad(lcm_params); if(lcm_name != NULL) { if(!strcmp(lcm_name,lcm->name)) { printk("\t\t[success]\n"); isLCMFound = TRUE; u4IndexOfLCMList = i; lcm_drv = lcm; goto done; } else { printk("\t\t[fail]\n"); } } else { if(LCM_TYPE_DSI == lcm_params->type){ init_dsi(FALSE); MASKREG32(DSI_BASE + 0x10, 0x2, 0x2); } if(lcm->compare_id != NULL && lcm->compare_id()) { printk("\t\t[success]\n"); isLCMFound = TRUE; lcm_drv = lcm; u4IndexOfLCMList = i; goto done; } else { lcm_drv = lcm; if(LCM_TYPE_DSI == lcm_params->type){ DSI_Deinit(); DSI_PHY_clk_switch(false); } printk("\t\t[fail]\n"); } } } } done: if(LCM_TYPE_DSI == lcm_params->type) { int ret = 0; unsigned int data_array[3]; char buffer[4]; init_dsi(FALSE); MASKREG32(DSI_BASE + 0x10, 0x2, 0x2); data_array[0] = 0x00043700; DSI_set_cmdq(data_array, 1, 1); ret = DSI_dcs_read_lcm_reg_v2(0x0A, &buffer,1); if(ret == 0) { isLCMConnected = 0; printk("lcm is not connected\n"); } else { isLCMConnected = 1; printk("lcm is connected\n"); } DSI_Deinit(); } return lcm_drv; }lcm_count变量是通过mt65xx_lcm_list.c中的lcm_driver_list计算得来的,如果在ProjectConfig.mk中只配置了一个屏,那么lcm_count值就为1,否则就不会1。
注意:这里会有一个问题,如果是多个屏驱动的话,当前面都没有匹配成功的话,将使用最后一个屏驱动,请看代码:
lcm_drv = lcm; if(LCM_TYPE_DSI == lcm_params->type){ DSI_Deinit(); DSI_PHY_clk_switch(false); } printk("\t\t[fail]\n");
const LCM_DRIVER *disphal_get_lcm_driver(const char *lcm_name, unsigned int *lcm_index) { LCM_DRIVER *lcm = NULL; bool isLCMFound = false; printk("[LCM Auto Detect], we have %d lcm drivers built in\n", lcm_count); printk("[LCM Auto Detect], try to find driver for [%s]\n", (lcm_name==NULL)?"unknown":lcm_name); if(lcm_count == 1) { // we need to verify whether the lcm is connected // even there is only one lcm type defined lcm = lcm_driver_list[0]; lcm->set_util_funcs(&lcm_utils); *lcm_index = 0; printk("[LCM Specified]\t[%s]\n", (lcm->name==NULL)?"unknown":lcm->name); isLCMFound = true; goto done; } else { int i; for(i = 0;i < lcm_count;i++) { lcm = lcm_driver_list[i]; printk("[LCM Auto Detect] [%d] - [%s]\t", i, (lcm->name==NULL)?"unknown":lcm->name); lcm->set_util_funcs(&lcm_utils); memset((void*)&s_lcm_params, 0, sizeof(LCM_PARAMS)); lcm->get_params(&s_lcm_params); disphal_init_ctrl_if(); LCD_Set_DrivingCurrent(&s_lcm_params); LCD_Init_IO_pad(&s_lcm_params); if(lcm_name != NULL) { if(!strcmp(lcm_name,lcm->name)) { printk("\t\t[success]\n"); *lcm_index = i; isLCMFound = true; goto done; } else { printk("\t\t[fail]\n"); } } else { if(LCM_TYPE_DSI == lcm_params->type) { init_dsi(FALSE); } if(lcm->compare_id != NULL && lcm->compare_id()) { printk("\t\t[success]\n"); isLCMFound = true; *lcm_index = i; goto done; } else { if(LCM_TYPE_DSI == lcm_params->type) DSI_Deinit(); printk("\t\t[fail]\n"); } } } } done: if (isLCMFound) { memset((void*)&s_lcm_params, 0, sizeof(LCM_PARAMS)); lcm->get_params(&s_lcm_params); return lcm; } else return NULL; }注意,同LK部分不同的是,LK会给kernel传递一个命令行参数,而这个参数中就有可能包括屏的驱动,例如:
lcm=1-hx8389b_qhd_dsi_vdo这部分代码其实同LK的差不多,只是参数lcm_name字段就有可能不为空,即在LK中已经找到了合适的屏驱动,kernel中就不用再去匹配了。