mtk lcm驱动加载流程

平台: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_count值为1,那么直接获取lcm_driver_list这个数组的第一个元素并把它赋值给一个全局变量lcm_drv,调用屏相关的set_util_funcs和get_params函数,所以如果只有一个屏驱动话,那是很简单的,也不用去匹配,直接拿来用就是了。

如果lcm_count值不为1呢,也就是有多个屏驱动呢,那么来看看是如何匹配的。
首先是for循环,依次遍历lcm_driver_list这个数组,如果lcm_name这个变量不为NULL,那么直接匹配lcm_name和屏驱动中的name字段是否相同,如果匹配成功,也就找到了相应的屏驱动,但是需要注意的是在LK中,这个变量值是为空的,有DISP_DetectDevice函数为证,所以说LK中肯定不会走这部分代码。那么是接下来的else部分,在else代码中,首先是判断屏驱动中的compare_id是否为空,如果不空的话,还会调用compare_id函数来匹配屏和驱动,如果两者都满足,那说明找到了合适的驱动,否则继续循环。所以匹配屏和驱动还是靠驱动中的compare_id函数来实现的。

注意:这里会有一个问题,如果是多个屏驱动的话,当前面都没有匹配成功的话,将使用最后一个屏驱动,请看代码:

lcm_drv = lcm;
if(LCM_TYPE_DSI == lcm_params->type){
	DSI_Deinit();
	DSI_PHY_clk_switch(false);
}
printk("\t\t[fail]\n");

2. kernel部分(mediatek/platform/mt6582/kernel/drivers/video/disp_hal.c)
LK部分代码看完了,那么再来看kernel部分。
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中就不用再去匹配了。

你可能感兴趣的:(mtk lcm驱动加载流程)