【IoT】高通LCD之亮灭屏过程简析

简介: LCD驱动

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 #%dbusy don't turn off\n",

                            ctl->intf_num);

                    return rc;

            }

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

            mdp_video_write(ctx,MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);

            /* wait for at least one VSYNCon HDMI intf for proper TG OFF */

            if (MDSS_INTF_HDMI ==ctx->intf_type) {

                    frame_rate =mdss_panel_get_framerate

                                    (&(ctl->panel_data->panel_info));

                if (!(frame_rate >= 24&& frame_rate <= 240))

                        frame_rate = 24;

                        msleep((1000/frame_rate)+ 1);

                }

                mdss_iommu_ctrl(0);

                mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF,false);

                ctx->timegen_en = false;

                rc =mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_OFF, NULL);

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

                mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN,

                                ctl->intf_num);

                sctl =mdss_mdp_get_split_ctl(ctl);

                if (sctl)

                    mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN,   sctl->intf_num);

            mdss_bus_bandwidth_ctrl(false);

            ----------------------

  }

  通过mdss_mdp_ctl_intf_event(ctl,MDSS_EVENT_BLANK, NULL);发送灭屏的事件,

  dsi_event_handler会接收到这个事件,会去执行mdss_dsi_blank。

  通过mdss_mdp_ctl_intf_event(ctl,MDSS_EVENT_PANEL_OFF, NULL);发送事件,同样dsi_event_handler 会接收到这个事件,会去执行mdss_dsi_off。

  最后在mdss_fb_suspend_sub中发送FB_BLANK_POWERDOWN,最后屏熄灭。

从《天道》的角度谈谈产品规划
原创2023-02-24 21:05·产品人卫朋
今天主要借用《天道》中丁元英的商业案例来谈谈产品规划这个话题。

《天道》这部被众人追捧的影视剧来源于豆豆的成名作《遥远的救世主》。

如果没有全局做过产品或者市场的规划,而且是初次接触这部剧。

你就会惊叹于主人公的组局、布局,以及成局的能力。

从互联网拥簇的评论声中,也可见一斑。

剧中的丁元英甚至都有一种被神化的趋势。

而随着个人知识和阅历的增加,再加上每年也都要做产品规划。

也逐渐对这部剧或者这本书有了一些新的认识。

究其本质,这是一种战略性的思维,也是一种规划的能力。

更是一种市场与内部能力的匹配过程。

笔者之前也分享过这块的内容,也看到了一些质疑。

怎么能用虚拟的案例做讲解呢?

其实这么做的原因主要有两点考虑:

首先,这部剧中的商业案例的整体逻辑是自洽的,而且也符合当时的商业环境。

其次,整部剧将整个商业案例完整地呈现了出来,也包括其中很多的决策细节。

这就要比分析现实案例直观得多,也更加有指导意义。

再回到产品规划这个话题上来。

产品规划从本质上来说是一种推演能力,也就是根据第一性原则推演产品从0到1、从1到100的一个过程。

如果说一款产品是一个点的话,那产品规划便是通过构造一种系统能力以达成企业最终的商业目的。

第一性原理是埃隆·马斯克非常推崇的一种思维模型。

通常来说,企业愿景对应的便是企业的第一性原则。

围绕第一性原则可以激发资源优势、制定细分市场目标,最终实现企业目标。

下面以影视剧中丁元英操盘的格律诗音响项目为例,谈谈产品规划。

格律诗音响公司的企业愿景是实现王庙村生产力和市场的对接,最终实现农户脱贫。

这是企业的愿景,同时也是丁元英承诺要给红颜知己芮小丹创造的神话。

启动一个项目或产品,资源和人力配置是你首先要考虑的。

企业在不同的发展周期,对人的要求是有很大差异的。

丁元英在分析完这些人的本质之后,并没有把自己的全套计划完整地告诉原始这些人。

而是通过市场的变化来淘汰掉一部分人。

因为这部分人现在不淘汰掉,在以后的市场变化中,可能会给公司带来毁灭性的灾难。

下面就先梳理一下其中的关键人物:

丁元英作为格律诗音响项目的唯一操盘手,全局规划了整个项目。

他的优势是自己在欧洲的人脉和战略规划能力,以及在欧阳雪等人心中的影响力。

同时,作为发烧级音乐玩家,他对音箱的独特见解也为他们打造差异化的产品起到了关键助力作用。

差异化的意思是相比于竞争对手,你的独特优势或者护城河,没有这个前提,整个策略也就无从谈起,这为他们赢得了时间上的先机。

在音响这个市场,竞品已经很成功了,而且他们提供的价值点已经被用户接受。

如果按照他们的价值点去做产品,你就永远只能跟在他们身后。

这时候就需要找一个跟他们不一样的价值点,做差异化。

欧阳雪这个人呢,做事很踏实,很讲义气,不贪心。优势是人脉、资金和社会地位。

这个人的价值在于她对格律诗的绝对控股,这样就可以确保关键决策权的归属。

由于每个人的认知水平的限制,很多时候不同个体看到的终局是有极大差异的,这个时候你就需要考虑如何增加成事的确定性。

如果开公司的话,股权的分配问题是你优先要考虑的。

不赚钱的时候,大家还都能力出一孔。一旦公司有起色,每个人就开始有自己的诉求,不确定性也就随之而来。

肖亚文见过世面,知道公司怎么运行,知道商务谈判和商务合作的事情,是很精明的职场人物。

而冯世杰和叶晓明想成就一番事业,但没有机会,能够脚踏实地的做事情,但眼光欠缺。刘冰是小人物,唯利是图,关键时刻不能顶上,迟早会被淘汰。

叶晓明,冯世杰,刘冰这三个人的优势就是懂音乐,会组装,可以作为高级技术工。

同时,这三人和王庙村农民有一定的关系,可以作为连接的纽带,核心竞争力是技术和人脉。

乐圣公司的掌舵人是林雨峰(竞争对手),但太过刚硬,只知道进攻,不懂防守,考虑问题存在漏洞。

这就有点类似竞争分析了,通过分析竞争对手的漏洞,找到破局点,制定商业竞争策略。

接下来就需要统一思想了:

想要以小博大,达成乐圣跟王庙村合作的目的,就必须把优势发挥到最大效果。

这才有几次股东开会,召集农民兄弟一起开会等,就是为了统一思想。

市场的生存竞争非常残酷,胜负往往就在毫厘之间,微弱的优势都可能成为关键一环,你比他多一口气,你就是赢家。

最后,丁元英就把这些人的优势资源整合起来,按照需要组建公司,精心规划。

详细案例分析可以参阅笔者之前的文章。

卫朋

人人都是产品经理受邀专栏作家,CSDN 嵌入式领域新星创作者、资深技术博主。2020 年 8 月开始写产品相关内容,截至目前,人人都是产品经理单渠道阅读 56 万+,鸟哥笔记单渠道阅读200 万+,CSDN 单渠道阅读 210 万+,51CTO单渠道阅读 180 万+。

卫朋入围2021/2022年人人都是产品经理平台年度作者,光环国际学习社区首批原创者、知识合作伙伴,商业新知 2021 年度产品十佳创作者,腾讯调研云2022年达人榜第三名。

文章被人人都是产品经理、CSDN、华为云、运营派、产品壹佰、鸟哥笔记、光环国际、商业新知、腾讯调研云等头部垂直类媒体转载。文章见仁见智,各位看官可策略性选择对于自己有用的部分。

相关文章
|
传感器 编解码 安全
|
3月前
|
物联网 数据管理 Apache
拥抱IoT浪潮,Apache IoTDB如何成为你的智能数据守护者?解锁物联网新纪元的数据管理秘籍!
【8月更文挑战第22天】随着物联网技术的发展,数据量激增对数据库提出新挑战。Apache IoTDB凭借其面向时间序列数据的设计,在IoT领域脱颖而出。相较于传统数据库,IoTDB采用树形数据模型高效管理实时数据,具备轻量级结构与高并发能力,并集成Hadoop/Spark支持复杂分析。在智能城市等场景下,IoTDB能处理如交通流量等数据,为决策提供支持。IoTDB还提供InfluxDB协议适配器简化迁移过程,并支持细致的权限管理确保数据安全。综上所述,IoTDB在IoT数据管理中展现出巨大潜力与竞争力。
108 1
|
17天前
|
安全 物联网 网络安全
智能设备的安全隐患:物联网(IoT)安全指南
智能设备的安全隐患:物联网(IoT)安全指南
45 12
|
15天前
|
传感器 监控 安全
物联网(IoT):定义、影响与未来
物联网(IoT):定义、影响与未来
42 3
|
24天前
|
存储 JSON 运维
智能物联网平台:Azure IoT Hub在设备管理中的实践
【10月更文挑战第26天】随着物联网技术的发展,Azure IoT Hub成为企业管理和连接数百万台设备的强大平台。本文介绍Azure IoT Hub的设备管理功能,包括设备注册、设备孪生、直接方法和监控诊断,并通过示例代码展示其应用。
34 4
下一篇
无影云桌面