【MTK驱动模块_3】lcm--代码流程及调试

LK阶段:

  • project\vendor\mediatek\proprietary\bootable\bootloader\lk\kernel\main.c
kmain();
--thread_t *thread_bs2 = thread_create("bootstrap2", &bootstrap2, NULL,DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
   -- bootstrap2(void *arg);
     -- platform_init();
重点从platform_init来讲起;

主要讲这3个部分:
1、初始化lk中的fb,获取大小、长宽等,同时给驱动结构体pgc分配空间,为进行驱动初始化做准备。

/* initialize the frame buffet information */
g_fb_size = mt_disp_get_vram_size();
g_fb_base = mblock_reserve_ext(&g_boot_arg->mblock_info, g_fb_size, 0x10000, 0x78000000, 0, "framebuffer");

2、mt_disp_init((void *)g_fb_base);

3、mt65xx_backlight_on();

  • project\vendor\mediatek\proprietary\bootable\bootloader\lk\platform\mt6739\platform.c
void platform_init(void)
{
    /* initialize the frame buffet information */
	g_fb_size = mt_disp_get_vram_size();
	g_fb_base = mblock_reserve_ext(&g_boot_arg->mblock_info, g_fb_size, 0x10000, 0x78000000, 0, "framebuffer");
    ...
    mt_disp_init((void *)g_fb_base);
    ...
    mt65xx_backlight_on();
    ...
}
下面分别讲解这几个函数:
1、mt_disp_get_vram_size();
--DISP_GetVRamSize();
  --vramSize = DISP_GetFBRamSize();
      -- DISP_GetScreenWidth(void)
          --primary_display_get_width();
            --if (pgc->plcm == NULL) {
		      pgc->plcm = disp_lcm_probe(NULL, LCM_INTERFACE_NOTDEFINED);//跑probe函数,lcm参数初始化。
              ...}
    vramSize += DAL_GetLayerSize();
    return vramSize;
//pgc结构体的定义start//    
#define pgc _get_context
static display_primary_path_context* _get_context(void)
{
	static int is_context_inited = 0;
	static display_primary_path_context g_context;
         > if (!is_context_inited) {
		memset((void*)&g_context, 0, sizeof(display_primary_path_context));
		is_context_inited = 1;
	}
	return &g_context;
}
//pgc结构体的定义end//  
2、mt_disp_init((void *)g_fb_base);
---/// fb base pa and va
   fb_addr_pa_k = arm_mmu_va2pa((unsigned int)lcdbase);
   fb_addr_pa   = (void *)(unsigned int)(fb_addr_pa_k & 0xffffffffull);
   fb_addr      = lcdbase;
   primary_display_init(NULL)
   --pgc->plcm = disp_lcm_probe( lcm_name, LCM_INTERFACE_NOTDEFINED)
       --//当_lcm_count() > 0时会调用lcm_drv->compare_id() != 0时break,找到相应lcm
         compare_id()
   --ret = disp_lcm_init(pgc->plcm);
     --ret = DSI_dcs_read_lcm_reg_v2(_get_dst_module_by_lcm(plcm), NULL, 0x0A, (UINT8 *)&buffer,1);
   		>DISPMSG("read from lcm 0x0A: %d\n", buffer);
   		if (ret == 0) {
   			isLCMConnected = 0;
   			DISPMSG("lcm is not connected\n");
   		} else {
   			isLCMConnected = 1;
   			DISPMSG("lcm is connected\n");
   		}
3、void mt65xx_backlight_on(void){
   --enum led_brightness backlight_level = get_cust_led_default_level();
     mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, backlight_level);//默认backlight_level = LED_FULL
     --mt65xx_led_set_cust(&cust_led_list[type], level)
        --	switch (cust->mode) {
            ...
            case MT65XX_LED_MODE_GPIO:
                return ((cust_brightness_set)(cust->data))(level);
            case MT65XX_LED_MODE_PMIC:
                return brightness_set_pmic(cust->data, level);
            case MT65XX_LED_MODE_CUST_LCM:
                return ((cust_brightness_set)(cust->data))(level);
            case MT65XX_LED_MODE_CUST_BLS_PWM:
                return ((cust_brightness_set)(cust->data))(level); ////dts中对应的背光模式 MT65XX_LED_MODE_CUST_BLS_PWM
            case MT65XX_LED_MODE_NONE:
            default:
                break;
            }
}
//与背光相关的结构体
enum led_brightness {
	LED_OFF     = 0,
	LED_HALF    = 127,
	LED_FULL    = 255,
};
enum mt65xx_led_type
{
	MT65XX_LED_TYPE_RED = 0,
	MT65XX_LED_TYPE_GREEN,
	MT65XX_LED_TYPE_BLUE,
	MT65XX_LED_TYPE_JOGBALL,
	MT65XX_LED_TYPE_KEYBOARD,
	MT65XX_LED_TYPE_BUTTON,
	MT65XX_LED_TYPE_LCD,
	MT65XX_LED_TYPE_TOTAL,
};    
enum mt65xx_led_mode
{
	MT65XX_LED_MODE_NONE,
	MT65XX_LED_MODE_PWM,
	MT65XX_LED_MODE_GPIO,
	MT65XX_LED_MODE_PMIC,
	MT65XX_LED_MODE_CUST_LCM,
	MT65XX_LED_MODE_CUST_BLS_PWM //5
};
//dts中对应的背光模式,在K39tv1_64_bsp.dts中
	led6:led@6 {
		compatible = "mediatek,lcd-backlight";
		led_mode = <5>; //对应的背光模式MT65XX_LED_MODE_CUST_BLS_PWM
		data = <1>;
		pwm_config = <0 2 0 0 0>;
	};

KERNEL阶段:

  • L:\work3\project\kernel-4.4\drivers\misc\mediatek\video\mt6739\videox\
mtkfb.c:
module_init(mtkfb_init);
int __init mtkfb_init(void)
{
platform_driver_register(&mtkfb_driver)
    --.of_match_table = mtkfb_of_ids,
        --{.compatible = "mediatek,MTKFB",}//和设备树中的相匹配后跑prob函数
...
}
static int mtkfb_probe(struct platform_device *pdev)
{
...
    |_parse_tag_videolfb();//用于获取LK传递过来的lcm型号参数
    |  --chosen_node = of_find_node_by_path("/chosen");
    |    ret = __parse_tag_videolfb(chosen_node);
    |      --videolfb_tag = (struct tag_videolfb *)of_get_property(node, "atag,videolfb", (int *)&size);
    |        memset((void *)mtkfb_lcm_name, 0, sizeof(mtkfb_lcm_name));
    |        strncpy((char *)mtkfb_lcm_name, videolfb_tag->lcmname, sizeof(mtkfb_lcm_name));
    |        mtkfb_lcm_name[strlen(videolfb_tag->lcmname)] = '\0';//解析出lcd的名字,lk在初始化时进行lcm匹配修改放入相应的到chosen节点,来传递给kernel。
    |
    |primary_display_init(mtkfb_find_lcm_driver(), lcd_fps, is_lcm_inited);  //进行LCM主要的初始化
    |   --pgc->plcm = disp_lcm_probe(lcm_name, LCM_INTERFACE_NOTDEFINED, is_lcm_inited);
    |   --primary_display_check_recovery_init();//ESD检测
    |       --primary_display_check_task =kthread_create(primary_display_check_recovery_worker_kthread, NULL,"disp_check");//创建线程
    |           --wake_up_process(primary_display_check_task);//唤醒线程函数
    |              --static int primary_display_check_recovery_worker_kthread(void *data)
    |                   --do {
    |                            ret = primary_display_esd_check();
    |            
    |                            if (ret == 1) {
    |                                DISPERR("[ESD]esd check fail, will do esd recovery. try=%d\n", i);
    |                                primary_display_esd_recovery();//ESD check failed 挂起LCM,重新进行初始化。
    |                                   -- {  ...DISPDBG("[POWER]lcm suspend[begin]\n");
    |                                        disp_lcm_suspend(primary_get_lcm());
    |                                        DISPCHECK("[POWER]lcm suspend[end]\n");
    |                                       
    |                                        mmprofile_log_ex(ddp_mmp_get_events()->esd_recovery_t, MMPROFILE_FLAG_PULSE, 0, 7);
    |                                       
    |                                        DISPDBG("[ESD]lcm force init[begin]\n");
    |                                        disp_lcm_init(primary_get_lcm(), 1);
    |                                        DISPCHECK("[ESD]lcm force init[end]\n");...}
    |                   
    |                                recovery_done = 1;
    |                            } else
    |                                break;
    |            
    |                          } while (++i < esd_try_cnt);//esd_try_cnt = 5
    |
    |
...
}

id兼容和ESD机制

lk阶段屏的兼容:

1、软件id检测(读相应寄存器的值):

【MTK驱动模块_3】lcm--代码流程及调试_第1张图片

匹配到id后返回1

【MTK驱动模块_3】lcm--代码流程及调试_第2张图片

1.2、看哪里调用了lcm_compare_id(),ctrl+Alt+c可以追踪那个来调用它的。

disp_lcm.c->disp_lcm_probe();在for循环中遍历lcm_driver_list[]这个数组。匹配到正确id后返回1,跳出for循环。
【MTK驱动模块_3】lcm--代码流程及调试_第3张图片
【MTK驱动模块_3】lcm--代码流程及调试_第4张图片

2、esd机制,静电防护机制。

ESD读取寄存器一般是读0x0A,读出0X9C。有的IC厂家为了自己产品的稳定性,会多弄几组寄存器用于读取,就不是简单的读取0x9c的值了。

【MTK驱动模块_3】lcm--代码流程及调试_第5张图片

2.1、esd的流程

在kernel阶段:

【MTK驱动模块_3】lcm--代码流程及调试_第6张图片
【MTK驱动模块_3】lcm--代码流程及调试_第7张图片

这里的esd_try_cnt为esd检测的次数,这里设置为5。

你可能感兴趣的:(MTK驱动总结)