一、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 reg
qcom,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 value
qcom,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的时候没有配置上;

解决方案:修改相关屏的初始化参数,

最新文章

  1. 配置putty自动登陆服务器
  2. Vimium使用快捷键总结
  3. linux设备驱动归纳总结(四):3.抢占和上下文切换【转】
  4. pcap文件格式及文件解析
  5. 如何做到尽可能不使用庞大的jQuery
  6. CADisplayLink
  7. 一步步学习NHibernate(5)——多对一,一对多,懒加载(2)
  8. [PWA] 18. Clean the photo cache
  9. asp.net中的主题
  10. java时间验证工具
  11. Amazon Hiring Campus 2013 - Final 6
  12. VARCHAR2 他们占几个字节? NLS_LENGTH_SEMANTICS,nls_language
  13. Couchbase集群和Redis集群解析
  14. iOS开发——UIImageView
  15. 用MPLAB IDE编程时,软件总是弹出一个窗口提示: “the extended cpu mode configuration bit is enabled,but the program that was loaded was not built using extended cpu instructions. therefore,your code may not work properly
  16. wget访问SOAP接口
  17. Ubuntu linux安装putty
  18. 201521123010 《Java程序设计》第13周学习总结
  19. QQ小橙团队排表机器人使用方法
  20. Python-TXT文本操作

热门文章

  1. SpringBoot系列之集成Mybatis教程
  2. IP,MAC
  3. JVM系列三(垃圾收集器).
  4. 【Spring MVC】Properties文件的加载
  5. Java中的两种异常类型是什么?他们有什么区别?
  6. 基于 TrueLicense 的项目证书验证
  7. 服务器端Mysql常用操作
  8. 数百道BAT等大厂最新Python面试真题,学到你手软!
  9. ABAP分享六 alv显示的几种方式的简单示例
  10. java基础练习题