qcom平台 LCD亮灭屏流程及LCD知识点总结

news/2024/5/20 19:32:52

一、LK中亮屏流程
1.gcdb_display_init(),进行display初始化的起始地方;
2.oem_panel_select(),在这里去选择哪一款屏,也可以在这里添加新一款屏;
3.dsi_panel_init()把屏头文件中的配置信息拷贝到结构体中,并一些屏需要的配置;
4.msm_display_init(),给屏上电和初始化时钟,申请FB缓冲区,配置display,点亮屏幕,打开背光;
5.读取图片数据放到缓冲区中,调用函数fbcon_extract_to_screen()来把图片显示到屏幕上;原理:splash.img内容都会加载到内存中,然后把内存图片的数据拷贝到FB内存中;
6.最后FB的数据会通过DMA的方式把FB中的数据给DSI控制器;

函数加载流程:
dsi_panel_init(struct msm_panel_info *pinfo,struct panel_struct *pstruct)---->panel初始化,获取屏的基本信息,从屏对应的头文件中;
msm_display_init();---->亮屏的开始pdata->power_func(1, &(panel->panel_info));---->给屏上电,panel.power_func = mdss_dsi_panel_power;pdata->dfps_func(&(panel->panel_info));---->panel.dfps_func = mdss_dsi_mipi_dfps_config;pdata->pll_clk_func(1, &(panel->panel_info));---->使能时钟;panel.pll_clk_func = mdss_dsi_panel_clock;msm_fb_alloc(&(panel->fb));----->申请FB缓冲区msm_display_config();------->LCD的基本配置;如;mipi的配置,DSI控制器的初始化等;msm_display_on();------>向LCD屏的寄存器中写入ON_command命令参数,并检测mipi的数据通道是否是通路;ret = pdata->bl_func(1);---->背光使能;初始化背光;

二、kernel中亮屏流程
上层调用ioctrl()函数向底层FB节点发送亮灭屏事件命令,底层调用fb_ioctrl()函数去调用fb_blank()以通知链的方式去通知TP和加载一系列事件函数,根据事件命令去处理对应的操作,而这个
事件处理函数是在DSI驱动中的probe()函数中注册的;1.先执行LCD上电事件命令,再执行亮屏事件命令,经过函数调用,最终会调用到在DSI驱动中解析屏的on_command命令参数写入到LCD屏对应的寄存器中,亮屏后,在打开背光;
2.执行灭屏操作和亮屏操作其实差不多,也是把灭屏的OFF_command指令写到LCD寄存器中,但在执行命令之前,会把背光设置为0,关闭背光;在执行完灭屏事件后,再去执行给LCD下电的操作;
亮屏操作流程;

fb_ioctl()------->framebuff节点对应的函数操作,位置:fbdev/core/fbmem.c ,创建一个FB节点给上层去操作;info = file_fb_info(file);---->获取mdss_fb_probe()里面注册的一些函数;do_fb_ioctl();fb_blank(struct fb_info *info, int blank);---->参数blank就是下面函数中的blank_mode;这个是亮屏的起始函数;fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);---->TP通知链,通知TP做一些相应的动作;mdss_fb_blank(int blank_mode, struct fb_info *info);------>启动事件子系统;---->fb_blank = mdss_fb_blank();在fb_probe中注册的;mdss_fb_blank_sub(int blank_mode, struct fb_info *info,int op_enable);----->switch函数中判断的根据blank_mode;mdss_fb_blank_unblank(mfd);----->亮屏操作;mfd->mdp.on_fnc();--->mdp5_interface->on_fnc = mdss_mdp_overlay_on;mdss_mdp_overlay_on();------>mdp5_interface->on_fnc = mdss_mdp_overlay_on;mdss_mdp_overlay_kickoff();mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,struct mdss_mdp_commit_cb *commit_cb);ctl->ops.display_fnc;----->ctl->ops.display_fnc = mdss_mdp_video_display;  mdss_mdp_video_display()回调函数注册在mdss_mdp_video_start()中;///mdss_mdp_video_display();------->亮屏的主要函数;mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_LINK_READY, NULL,CTL_INTF_EVENT_FLAG_DEFAULT);---->上电操作;mdss_dsi_on(struct mdss_panel_data *pdata);mdss_dsi_panel_power_ctrl(pdata, MDSS_PANEL_POWER_ON);---->上电操作mdss_mdp_ctl_intf_event(ctl,MDSS_EVENT_UNBLANK, NULL,CTL_INTF_EVENT_FLAG_DEFAULT);----->发送亮屏(MDSS_EVENT_UNBLANK)和灭屏(MDSS_EVENT_BLANK)事件来点亮和熄灭屏;rc = pdata->event_handler(pdata, event, arg);------->接受事件去处理;ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;mdss_dsi_event_handler(struct mdss_panel_data *pdata,int event, void *arg);-----》事件处理函数;mdss_dsi_unblank(struct mdss_panel_data *pdata);----->点亮屏和使能TE引脚中断等功能;ctrl_pdata->on(pdata);--->ctrl_pdata->on = mdss_dsi_panel_on;mdss_dsi_panel_on(struct mdss_panel_data *pdata);---->发送on命令和屏幕相关参数命令;mdss_dsi_panel_cmds_send(ctrl, on_cmds, CMD_REQ_COMMIT);---->发送on_cmds,CE_cmds,CABC_cmds等命令;mdss_mdp_ctl_intf_event(ctl,MDSS_EVENT_PANEL_ON, NULL);---->也是点亮屏,只是这个另一模式HS模式,这个模式主要在dtsi文件中去配;mdss_fb_set_backlight(mfd, mfd->unset_bl_level);----->打开背光;

灭屏函数流程:

在这里插入fb_ioctl()------->framebuff节点对应的函数操作,位置:fbdev/core/fbmem.c ,创建一个FB节点给上层去操作;info = file_fb_info(file);---->获取mdss_fb_probe()里面注册的一些函数;do_fb_ioctl();fb_blank(struct fb_info *info, int blank);---->参数blank就是下面函数中的blank_mode;这个是亮屏的起始函数;fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);---->TP通知链,通知TP;mdss_fb_blank(int blank_mode, struct fb_info *info);------>启动事件子系统;---->fb_blank = mdss_fb_blank();在fb_probe中注册的;mdss_fb_blank_sub(int blank_mode, struct fb_info *info,int op_enable);----->switch函数中判断的根据blank_mode;mdss_fb_blank_blank();mdss_panel_is_power_off(req_power_state);----->有一个电源状态检测;mdss_fb_stop_disp_thread(mfd);--->关闭那个dispaly处理线程;mdss_fb_set_backlight(mfd, 0);---->设置背光亮度为0;关闭背光;mdss_mdp_overlay_off(mfd);---->mdp5_interface->off_fnc = mdss_mdp_overlay_off;mdss_mdp_ctl_stop(mdp5_data->ctl, mfd->panel_power_state);--->灭屏mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl, int panel_power_state);-------->ctl->ops.stop_fnc = mdss_mdp_video_stop;mdss_mdp_video_intfs_stop();mdss_mdp_video_ctx_stop();mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_BLANK, NULL,CTL_INTF_EVENT_FLAG_DEFAULT);mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_OFF, NULL,CTL_INTF_EVENT_FLAG_DEFAULT);mdss_dsi_blank();----->灭屏事件处理函数ctrl_pdata->off(pdata);---->灭屏指令的发送;mdss_dsi_panel_off(struct mdss_panel_data *pdata);mdss_dsi_panel_cmds_send(ctrl, &ctrl->off_cmds, CMD_REQ_COMMIT);mdss_dsi_off(pdata, power_state);---->下电操作;mdss_dsi_panel_power_ctrl(pdata, power_state);----下电;代码片

三、背光调用流程

背光概念:背光是控制屏幕亮度,
背光控制有3种方式: 1.LED灯控制背光,通过控制LED的电流大小,来控制最大亮度,通过控制级数来控制背光的变化;(pmic提供引脚)2.PWM的方式控制背光,从电路中引出某一引脚来控制三极管电路,从而控制电路的电流大小;(单独的电路芯片)3.命令集的方式控制背光,通过以命令的方式向寄存器中写入控制的值来控制电路;(它的供电的脚是从LCD芯片引出来的)
wled方式背光驱动路径:kernel/msm-3.18/drivers/leds

背光级别的映射关系:(这个很重要,跟上层设置滑动亮度进度条,亮度值大小有关系,)
#define MDSS_BRIGHT_TO_BL(out, v, bl_max, max_bright) do {
out = (2 * (v) * (bl_max) + max_bright);
do_div(out, 2 * max_bright);
} while (0)

mdss_fb_probe():
backlight_led.brightness = mfd->panel_info->brightness_max;
backlight_led.max_brightness = mfd->panel_info->brightness_max;
led_classdev_register(&pdev->dev, &backlight_led);---->注册背光目录和节点供上层使用;(重要点,上层会操作该目录的节点去控制背光亮度)
device_create_with_groups();----->创建背光组控制;一系列的节点文件;

上层对节点写亮度值,底层亮度设置的操作流程:
mdss_fb_set_bl_brightness();---->mdss_fb.c
mdss_fb_set_backlight();----->mdss_fb.c
mdss_fb_scale_bl(mfd, &temp);----->CABL开启后,会重新计算出一个背光值,目的是降低功耗;
pdata->set_backlight(pdata, temp);----->mdss_dsi_panel.c
mdss_dsi_panel_bl_ctrl(struct mdss_panel_data *pdata, int level);----->这边已经可以达到4095级别;
led_trigger_event(struct led_trigger *trig, int brightness);
led_set_brightness(struct led_classdev *led_cdev, int brightness);
__led_set_brightness(struct led_classdev *led_cdev, int brightness);
led_cdev->brightness_set(led_cdev, brightness);----->函数指针的方式跳转到设置函数;
qpnp_wled_set(led_cdev, brightness);------->kernel/msm-3.18/drivers/leds/leds-qpnp-wled.c
schedule_work(&wled->work);----->调用工作队列,使用工作线程去执行这设置函数;
qpnp_wled_set_level(struct qpnp_wled *wled, int level);
qpnp_wled_write_reg();------>分别向寄存器中写入高8位和低8位数据;
qpnp_wled_sync_reg_toggle();---->同步寄存器
qpnp_wled_module_en();----->背光是否使能;

四、LCD知识点总结
4.1.数据显示流程frambuff的注册
4.1.1 FB注册流程

4.1.2 图像数据显示流程

4.2.LCD屏上下电机时钟

DSI时钟计算如下:
H-total = HorizontalActive + HorizontalFrontPorch + HorizontalBackPorch + HorizontalSyncPulse + HorizontalSyncSkew(data + 前肩 +后肩 + 行同步(换行时钟 + 电子前移时钟))

V-total = VerticalActive + VerticalFrontPorch + VerticalBackPorch + VerticalSyncPulse + VerticalSyncSkew

Total pixel = H-total * V-total * 60(Hz通常都是这个,当然可以变).

Bitclk = Total pixel * bpp(byte) *8/lane number(有几路mipi data lane).

Byteclk = bitclk/8

Dsipclk(Dsi pixel clock) = (Byteclk * lane number)/bpp(byte) = Total pixel * 8

Byteclk = pclk * pixel depth / lane number

另一种写法:(一秒传输数据的所需要的时钟,这跟帧率有关系)
PLL_CLOCK:Mipiclock = [ (width+hsync+hfp+hbp) x (height+vsync+vfp+vbp) ] x(bus_width) x fps/ (lane_num)/2;

MIPI时钟是每一条数据通道的时钟,因为在传输数据的时候,是多数据通道同时在传输数据,并且只用一个时钟脚;

4.3.ESD防静电

高通的esd功能也是通过dtsi来配置的。如:
qcom,esd-check-enabled;qcom,mdss-dsi-panel-status-command      = [06 01 00 01 05 00 01 0A];//read regqcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mpde";qcom,mdss-dsi-panel-status-check-mode   = "reg_read";qcom,mdss-dsi-panel-status-read-length  = <1>;qcom,mdss-dsi-panel-status-valid-params = <1>;qcom,mdss-dsi-panel-status-value        = <0x9C>;//right valueqcom,mdss-dsi-panel-max-error-count     = <3>;
需要注意的是,这些属性对应的参数除qcom,mdss-dsi-panel-max-error-count都没有默认值,如果配置不完整,可能会导致整个esd功能失效。配置完成后,确保屏幕无异常。
可以修改qcom,mdss-dsi-panel-status-value为其他值,观察是否有esd resume情况发生。判断esd机制是否生效。

总结:上层会在定时去检查屏幕是否有问题,而ESD这个功能的检测就去检测是否有问题,ESD功能的检测有两种方式,一种是TE引脚的方式(硬件),一种是读取寄存器值的方式(软件);
到时候系统去定时检测屏状态时,会根据dtsi里配置的ESD方式去调用相应的函数来检测;根据 "qcom,mdss-dsi-panel-status-check-mode"去判断哪一种模式;

1.读寄存器方式check dsi 状态的流程:
__init mdss_dsi_status_init(void);—>驱动加载函数;
check_dsi_ctrl_status();---->INIT_DELAYED_WORK(&pstatus_data->check_status, check_dsi_ctrl_status);工作队列的方式;
mdss_check_dsi_ctrl_status();----->pdsi_status->mfd->mdp.check_dsi_status(work, ESD_interval);工作队列的方式;
mdss_dsi_reg_status_check();---->会把这个函数放在延迟工作队列中去执行;
mdss_dsi_gen_read_status();------->check_read_status(ctrl_pdata);---->ctrl->check_read_status = mdss_dsi_gen_read_status;
mdss_dsi_cmp_panel_reg_v2();----->读取对应的寄存器值,并与在之前的dtsi文件设置的值,进行比较;

2.TE引脚中断方式去check dsi 状态的流程;
__init mdss_dsi_status_init(void);—>q驱动加载函数;
check_dsi_ctrl_status();---->INIT_DELAYED_WORK(&pstatus_data->check_status, check_dsi_ctrl_status);工作队列的方式;
mdss_check_dsi_ctrl_status();----->pdsi_status->mfd->mdp.check_dsi_status(work, ESD_interval);工作队列的方式;
mdss_dsi_TE_NT35596_check();------->硬件中断的方式去检测DSI状态;

4.4.屏幕效果及色温设置方式

4.5.LCD屏dtsi文件解析

4.6 LCD常见的问题
花屏问题:
1.LCD初始化时序信号不对;
2.花屏还有一种可能是Baseband给LCD送的数据跟LCD工作模式不对。比如你对LCD的工作模式设为RGB565,但你给它送的数据是RGB444或RGB666;
3.host对LCD读写过快;

开机LCD亮的瞬间有花屏问题:
解释:一般都是由于LCD在初始化完成后刷新第一副图像未完全准备好的时候背光已经亮了。解决的办法就是在UBOOT时候背光亮之前的延时相应的加长一点。

屏幕闪烁问题:1.背光闪烁;2.屏幕闪烁;
1.关闭panel打开背光,看是否闪,如果闪可能panel的背光设计有问题或者是残次品,或者背关芯片供电不稳。(背光闪烁)
2.如果背光不闪,panel闪的话大部分原因跟频率有关系,把频率调整到何时的值看是否还有闪的现象,调整panel自身的刷新率看所否还有有闪的现象;(屏幕闪烁)

在休眠情况下,重新唤醒屏,使用一段时间出现烧屏问题:
原因:在灭屏情况下,不断唤醒上电操作和睡眠操作导致IC芯片;PM频繁调用TP suspend/resume,当LCD 处于sleep in状态,频繁进出LPWG会导致IC状态异常,击穿VCOM。
解决方案:1.只在FFBM模式下PM才能调用TP resume/suspend(唤醒/休眠); 2.IC厂商修改TP固件,保证出现这种现象也不会造成IC芯片烧坏;

打开CABC开关,偶现花屏现象:
原因:屏幕的相关参数问题,在config的时候没有配置上;
解决方案:修改相关屏的初始化参数,

                                </div>

https://www.xjx100.cn/news/444345.html

相关文章

一文搞懂显示技术的底层框架

1. DPU与GPU的耦合是历史产物&#xff0c;完全可以独立出来2. DPU的原型设计 2.1【DPU的四大组成部分】2.2【KSM与DPU】3. DPU的最新设计 3.1【Source Suface Pipes or Overlays】3.2【Blender】3.3【Destination surface post-processor】3.4【Display Interface】4. 总结 PC上…

MTK LCM驱动知识

1.lcm 相关概念 1.1) MIPI接口&#xff1a;一共有三种接口&#xff1a;DBI(也做CPU或MCU接口)、DPI(也叫RGB接口)、DSI.在使用DSI接口时&#xff0c; 目前75/77都只支持到2条data lane&#xff0c;加上一条clock lane.使用DPI接口时&#xff0c;根据LCM IC支持的情况&#xf…

2.原版rom备份

为防止在调试的时候把开发板弄成砖块&#xff0c;需要先将原始镜像拷贝出来。原版系统为安卓7.1.2 可参考链接https://blog.csdn.net/oxp7085915/article/details/80291057 1.装备工作 adb命令行工具cmdadb驱动&#xff0c;瑞芯微开发工具AndroidTool 2. 安装usb驱动Drive…

三相并网变换器虚拟同步控制

一、研究/设计内容 1.1 逆变器控制策略研究现状 合理有效的逆变器控制策略能够有效改善电能的输出质量和电力系统运行的稳定性。根据不同的微网控制结构和并网要求&#xff0c;微网逆变器主要采用以下几种控制策略&#xff1a;恒功率控制&#xff08;主要应用场景为并网模式&…

项目中实现读写分离

1、AbstractRoutingDataSource Spring boot提供了AbstractRoutingDataSource 根据用户定义的规则选择当前的数据源&#xff0c;这样我们可以在执行查询之前&#xff0c;设置使用的数据源。实现可动态路由的数据源&#xff0c;在每次数据库查询操作前执行。它的抽象方法 det…

RecyclerView使用问题集合http://www.jianshu.com/p/333fe22cabc6

1.RecyclerViewCursorAdapter & Loader机制:http://www.jianshu.com/p/333fe22cabc6 2RecyclerView侧边字母索引排序 3.使用RecyclerView notifyItemChanged()出现图片闪烁问题解决 4.RecyclerView的实现item中下划线的长度最后一行长度全长&#xff0c;其余长度较短的实…

SpringBoot后端篇(一)创建SpringBoot项目

最近看了大佬的文章&#xff0c;觉得写的很不错&#xff0c;于是动手实践实践&#xff0c;但是也走了很多的坑&#xff0c;目前自己整理了以下&#xff0c;谨以此作自己成长过程中的垫脚石....... 数据库设计 -- ---------------------------------------------------- -- 用…

虚拟化概述

虚拟化概述 本文重点介绍了SR-IOV技术以及MLU270对SR-IOV的支持。 SR-IOV简介 SR-IOV&#xff08;Single Root I/O Virtualization&#xff09;技术是一种基于硬件的虚拟化解决方案&#xff0c;可提供高性能和可伸缩性的虚拟解决方案。SR-IOV制定了标准化机制来实现多个虚拟机共…