高通LCD之亮灭屏过程简析

    xiaoxiao2021-03-25  144

    1、如何看亮灭屏时间

    adb shell

            kmsgcat |grep fb_blank

    2、code简介

            在kernel/drivers/video/msm/mdss/mdss_fb.c中,

            static intmdss_fb_blank_sub(int blank_mode, struct fb_info *info, int op_enable)  

            blank_mode这个参数的值主要有两个,FB_BLANK_UNBLANK和 FB_BLANK_POWERDOWN ,

               FB_BLANK_UNBLANK是亮屏操作;

               FB_BLANK_POWERDOWN 是灭屏操作;

            当要亮屏的时候,传入参数FB_BLANK_UNBLANK时,会执行下面这些函数,

            if (!mfd->panel_power_on &&mfd->mdp.on_fnc) {

                ret = mfd->mdp.on_fnc(mfd);

                if (ret == 0) {

                    mfd->panel_power_on = true;

                    mfd->panel_info->panel_dead= false;

                }

                    mutex_lock(&mfd->update.lock);

                    mfd->update.type =NOTIFY_TYPE_UPDATE;

                    mfd->update.is_suspend = 0;

                    mutex_unlock(&mfd->update.lock);

                    /* Start the work thread tosignal idle time */

                    if (mfd->idle_time)

                    schedule_delayed_work(&mfd->idle_notify_work,

                                    msecs_to_jiffies(mfd->idle_time));

                }

                mutex_lock(&mfd->bl_lock);

                if (!mfd->bl_updated) {

                    mfd->bl_updated = 1;

                    mdss_fb_set_backlight(mfd,mfd->bl_level_prev_scaled);

                }

            mutex_unlock(&mfd->bl_lock);

               }

           当执行ret =mfd->mdp.on_fnc(mfd);会调用(上一篇文章http://blog.csdn.NET/liwei16611/article/details/52830483)注册的函数mdss_mdp_overlay_on;

           在mdss_mdp_overlay_on函数中,

           staticint mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)

           {

                 ..................

            if (!mdp5_data->ctl) {

                    ctl =__mdss_mdp_overlay_ctl_init(mfd);

                    if (IS_ERR_OR_NULL(ctl))

                        return PTR_ERR(ctl);

                        mdp5_data->ctl = ctl;

            }

            if (!mfd->panel_info->cont_splash_enabled&&

                    (mfd->panel_info->type !=DTV_PANEL)) {

                        rc =mdss_mdp_overlay_start(mfd);

                        if (!IS_ERR_VALUE(rc)&&

                            (mfd->panel_info->type!= WRITEBACK_PANEL)) {

                                atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);

                                rc= mdss_mdp_overlay_kickoff(mfd, NULL);

                        }

                } else {

                        rc =mdss_mdp_ctl_setup(mdp5_data->ctl);

                    if (rc)

                        return rc;

                }

                ......

          }

           在这里我们看到如果mdp5_data->ctl 还没有被初始化,则对他进行初始化,实际上在fb_probe 已经被初始化了, 那在这判断的作用,是为了如果有动态切换的话,                    mdp5_data->ctl 会被置成NULL,当要亮屏的时候回去重新初始化。

           如果连续显示打开的话则mfd->panel_info->cont_splash_enabled会被置1,那么就不去执行mdss_mdp_overlay_start,因为它在fb_probe中已经被执行了。

           执行mdss_mdp_ctl_setup会对pipe 及Mixer 进行一些配置,为传入的帧数据做准备。

           当要显示数据的帧的时候,会从hal 层传入commit的命令,调用 mdss_mdp_display_commit 函数,然后调用display_fnc,

           这个回调函数是在mdss_mdp_video_start中注册的;

           ctl->display_fnc= mdss_mdp_video_display;

           在mdss_mdp_video_display函数中,

           staticint mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)

           {

             ......................    

            if(!ctx->timegen_en) {

                    rc =mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_UNBLANK, NULL);

                    if (rc) {

                            pr_warn("intf #%dunblank error (%d)\n",

                                    ctl->intf_num,rc);

                            video_vsync_irq_disable(ctl);

                            ctx->wait_pending =0;

                            return rc;

                }

                    pr_debug("enabling timinggen for intf=%d\n", ctl->intf_num);

                        if((pdata->panel_info.cont_splash_enabled &&

                            !ctl->mfd->splash_info.splash_logo_enabled)

                                ||(ctl->mfd->splash_info.splash_logo_enabled

                                &&!is_mdss_iommu_attached())) {

                            rc =wait_for_completion_timeout(&ctx->vsync_comp,

                                            usecs_to_jiffies(VSYNC_TIMEOUT_US));

                        }

                        rc = mdss_iommu_ctrl(1);

                        if (IS_ERR_VALUE(rc)) {

                            pr_err("IOMMUattach failed\n");

                            return rc;

                        }

                        mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON,false);

                     mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num);

                mdss_bus_bandwidth_ctrl(true);

                mdp_video_write(ctx,MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);

                wmb();

                rc = wait_for_completion_timeout(&ctx->vsync_comp,

                        usecs_to_jiffies(VSYNC_TIMEOUT_US));

                        WARN(rc == 0, "timeout(%d) enabling timegen on ctl=%d\n",

                            rc, ctl->num);

                        ctx->timegen_en = true;

                        rc =mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_ON, NULL);

                        WARN(rc,"intf %d panel on error (%d)\n", ctl->intf_num, rc);

                   ......................

            }

             通过mdss_mdp_ctl_intf_event(ctl,MDSS_EVENT_UNBLANK, NULL); 发送一个event事件,

             dsi_event_handler 会接收到这个事件,去执行dsi_on,mdss_dsi_op_mode_config;

             之后通过mdss_mdp_ctl_intf_event(ctl,MDSS_EVENT_PANEL_ON, NULL);

             dsi_event_handler会接收到这个事件,去执行mdss_dsi_unblank;

             当要灭屏的时候,从hal层会发送stop命令,当驱动接收到这个命令会执行mdss_mdp_video_stop函数;

             staticint mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)

             {

                rc = mdss_mdp_ctl_intf_event(ctl,MDSS_EVENT_BLANK, NULL);

                        if (rc == -EBUSY) {

                            pr_debug("intf #

    转载请注明原文地址: https://ju.6miu.com/read-13089.html

    最新回复(0)