LCD相关code所在目录:
kernel/drvier/video/msm/mdss/
软件驱动主要分为三部分:
MDP 驱动
DSI 控制器驱动
FrameBuffer驱动
执行probe 的先后顺序:
MDP probe → DSI probe → FB probe
1、MDP probe
主要是对 使用的硬件资源进行初始化,同时在fb 设备中注册mdp 的使用接口,
mdss_fb_register_mdp_instance(&mdp5);
struct msm_mdp_interface mdp5 = {
.init_fnc =mdss_mdp_overlay_init,
.fb_mem_get_iommu_domain =mdss_fb_mem_get_iommu_domain,
.panel_register_done =mdss_panel_register_done,
.fb_stride =mdss_mdp_fb_stride,
.check_dsi_status =mdss_check_dsi_ctrl_status,
};
这些注册函数会在fb 初始化的时候调用。
2、DSI probe
解析模组厂提供的panel 的dtsi 文件,从那个文件中能获取到panel 的mode ,分辨率,刷新率,还有 Driver IC 的初始化 command;
这些command 对于 video mode 和 command mode 是不一样的,在command mode 的时候还需要知道TE 相关的信息。
3、Framebuffer probe
从DSI 的数据结构中获取到panel 的相关信息,对MDP 做初始化。
if (mfd->mdp.init_fnc) {
rc= mfd->mdp.init_fnc(mfd);
if(rc) {
pr_err("init_fncfailed\n");
returnrc;
}
}
init_fnc 就是 MDP probe 注册的 mdss_mdp_overlay_init,
在 mdss_mdp_overlay_init 中,首先是对mdp interface 注册回调函数,
mdp5_interface->on_fnc =mdss_mdp_overlay_on;
mdp5_interface->off_fnc =mdss_mdp_overlay_off;
mdp5_interface->release_fnc =__mdss_mdp_overlay_release_all;
mdp5_interface->do_histogram =NULL;
mdp5_interface->cursor_update =mdss_mdp_hw_cursor_update;
mdp5_interface->dma_fnc =mdss_mdp_overlay_pan_display;
mdp5_interface->ioctl_handler =mdss_mdp_overlay_ioctl_handler;
mdp5_interface->panel_register_done= mdss_panel_register_done;
mdp5_interface->kickoff_fnc =mdss_mdp_overlay_kickoff;
mdp5_interface->get_sync_fnc =mdss_mdp_rotator_sync_pt_get;
mdp5_interface->splash_init_fnc =mdss_mdp_splash_init;
mdp5_interface->configure_panel =mdss_mdp_update_panel_info;
如果连续显示被打开,则会调用mdss_mdp_overlay_handoff函数,
此时,mdp5_data->ctl 还没有被初始化,所以调用__mdss_mdp_overlay_ctl_init 函数,在这个函数中会执行mdss_mdp_ctl_init,
在这函数中,会根据panel 的 type 类 型,注册不同的控制函数,
struct mdss_mdp_ctl*mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
structmsm_fb_data_type *mfd)
{
…...........
case MIPI_VIDEO_PANEL:
ctl->is_video_mode = true;
if (pdata->panel_info.pdest ==DISPLAY_1)
ctl->intf_num =MDSS_MDP_INTF1;
else
ctl->intf_num = MDSS_MDP_INTF2;
ctl->intf_type =MDSS_INTF_DSI;
ctl->opmode =MDSS_MDP_CTL_OP_VIDEO_MODE;
ctl->start_fnc =mdss_mdp_video_start;
break;
case MIPI_CMD_PANEL:
if (pdata->panel_info.pdest ==DISPLAY_1)
ctl->intf_num =MDSS_MDP_INTF1;
else
ctl->intf_num =MDSS_MDP_INTF2;
ctl->intf_type =MDSS_INTF_DSI;
ctl->opmode =MDSS_MDP_CTL_OP_CMD_MODE;
ctl->start_fnc =mdss_mdp_cmd_start;
break;
…..........
}
在这里我们看出start_fuc根据不同的type注册的函数不同,所以在probe 的时候,不同的DSI mode 在初始化时注册的函数也不同,
当我们在显示过程中要对DSI mode 做切换的时候,需要从初始化的注册函数开始进行重新配置。
在__mdss_mdp_overlay_ctl_init 函数中,还会对vsync_handler进行注册,以及Mixer 的malloc 内存分配等工作。
在这之后还要初始化MDP 所需要的clk,以及必要的成员进行初始化。
在对MDP 初始化完成之后,还要对lcd使用的背光进行注册。
if(!lcd_backlight_registered) {
backlight_led.brightness =mfd->panel_info->brightness_max;
backlight_led.max_brightness =mfd->panel_info->brightness_max;
if(led_classdev_register(&pdev->dev, &backlight_led))
pr_err("led_classdev_registerfailed\n");
else
lcd_backlight_registered= 1;
}
当开机动画的服务起来的时候,会取调用fb_open函数,打开fb设备,在这个函数中将__mdss_fb_display_thread添加到内核线程,
同时发送FB_BLANK_UNBLANK亮屏的命令。至此,第一次使用fb驱动时,panel 已经被点亮。