qcom 8953平台 LCD亮灭屏流程及LCD知识点总结【转】
一、LK中亮屏流程
- gcdb_display_init(),进行display初始化的起始地方;
- oem_panel_select(),在这里去选择哪一款屏,也可以在这里添加新一款屏;
- dsi_panel_init()把屏头文件中的配置信息拷贝到结构体中,并一些屏需要的配置;
- msm_display_init(),给屏上电和初始化时钟,申请FB缓冲区,配置display,点亮屏幕,打开背光;
- 读取图片数据放到缓冲区中,调用函数fbcon_extract_to_screen()来把图片显示到屏幕上;原理:splash.img内容都会加载到内存中,然后把内存图片的数据拷贝到FB内存中;
- 最后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()函数中注册的;
先执行LCD上电事件命令,再执行亮屏事件命令,经过函数调用,最终会调用到在DSI驱动中解析屏的on_command命令参数写入到LCD屏对应的寄存器中,亮屏后,在打开背光;
执行灭屏操作和亮屏操作其实差不多,也是把灭屏的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.屏幕闪烁;
- 关闭panel打开背光,看是否闪,如果闪可能panel的背光设计有问题或者是残次品,或者背关芯片供电不稳。(背光闪烁)
- 如果背光不闪,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的时候没有配置上;
解决方案:修改相关屏的初始化参数,
qcom 8953平台 LCD亮灭屏流程及LCD知识点总结【转】的更多相关文章
- Android7.0 PowerManagerService 之亮灭屏(一)
本篇从按下power按键后,按键事件从InputManagerService 传到PhoneWindowManager.java开始分析power 按键做屏幕亮灭过程的分析,关于power 按键的其他 ...
- Android7.0 PowerManagerService 之亮灭屏(二) PMS 电源状态管理updatePowerStateLocked()
本篇注意接着上篇[Android7.0 PowerManagerService 之亮灭屏(一)]继续分析量灭屏的流程,这篇主要分析PMS的状态计算和更新流程,也是PMS中最为重要和复杂的一部分电源状态 ...
- Android横竖屏切换和灭屏亮屏时Activity的生命周期探究(1)
研究这个问题的初衷在于项目中碰到了一个问题:横屏的时候灭屏再亮屏,亮屏的时候用户能够清晰的看到先启动竖屏(过程1)再切换到横屏的过程,因为灭屏的时候onSaveInstanceState()保存的时横 ...
- android系统平台显示驱动开发简要:Samsung LCD接口篇『三』
平台信息: 内核:linux3.4.39系统:android4.4 平台:S5P4418(cortex a9) 作者:瘋耔(欢迎转载,请注明作者) 欢迎指正错误,共同学习.共同进步!! 关注博主新浪博 ...
- 关机充电如何实现短按pwrkey灭屏
目前关机充电PWRKEY实现长按开机和短按亮屏功能,灭屏是根据BL_SWITCH_TIMEOUTS时间,自动灭屏的:如果需要实现PWRKEY主动灭屏,请按照如下方法修改: alps/media ...
- android灭屏后调用binder通讯竟然影响了socket的POLL_OUT事件,怪事。
当你的android在灭屏(休眠)时分派(dispatch) Ice调用过程中,如果创建了新的进程,你的响应将不会预期那样工作,尽管你已经调用 ice_response或 ice_exception, ...
- PIC12F629帮我用C语言写个程序,控制三个LED亮灭
http://power.baidu.com/question/240873584599025684.html?entry=browse_difficult PIC12F629帮我用C语言写个程序,控 ...
- (三)开关检测来控制LED灯的亮灭
开关检测案例一: 具体电路图如下: K1--K4闭合,控制 D1—D4 亮灭 产生的问题: 1.关于 R8 R9 R7 R10 的阻值选择问题,倘若太大的话, 比如10K 不管开关断开还是闭合,好像 ...
- Android -- 距离感应器控制屏幕灭屏白屏
权限 <u ...
随机推荐
- [TimLinux] TCP全连接队列满
0. TCP三次握手 该图来自:TCP SOCKET中backlog参数的用途是什么? syns queue: 半连接队列 accept queue: 全连接队列 控制参数存放在文件:/proc/sy ...
- [TimLinux] JavaScript input框的onfocus/onblur/oninput/onchange事件介绍
1. onfocus事件 input框获取到焦点时,触发了该事件,比如获取到焦点时,修改input框的背景色.这个功能其实可以使用css的伪类:focus来定义. 2. onblur事件 这个与onf ...
- Python核心笔记:在python文件中如何调用其它python脚本文件,你肯定不会
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:zhujuyu 笔者在自学python的时候遇到了这样一个练习题:将 ...
- kerberos&ssh 原理、免密登录搭建
原理 详细介绍 参考oracle文档:Kerberos 服务 安装过程 1.安装krb5 yum install -y krb5-server yum install krb5-workstation ...
- 基于FPGA+USB2.0的图像采集系统测试小结-mt9m001
基于FPGA+USB2.0的图像采集系统测试小结-mt9m001 该系统采用层层惊涛出品的FPGA_VIP_USB_V102板卡测试 板卡分为:核心板.底板.摄像头板 核心板采用:ep4ce10e22 ...
- USB视频采集系统 视频测试软件将正式发布(方便调试测试各自摄像头,RAW,RGB,YUV)
先上图,看看这个软件,学习fpga将近一年,了解视频图像开发方向也半年有余,不断学习不断总结,开发软件工具是为了更方便的学习新通信 主要相关知识: FPGA+SDRAM+VGA(双端口fifo技术) ...
- 层叠机制和继承的概念以及CSS中选择器的优先级
层叠机制: 一个元素的某个特定的样式属性可能来自行间的style属性.内联样式表或者外部引入的样式表,以及浏览器自定义的样式,还有就是继承自父元素的样式,但是最终只会选择其中的某一个来表示,这个选择的 ...
- 【Web技术】337- 秒懂 Web 缓存
点击上方"前端自习课"关注,学习起来~ 最近把前端缓存重新整理了一下,从整体的层面上把前端所有能用的缓存方案梳理了一遍.同时,对于http缓存,使用了表格的方案,使得原先晦涩难记的 ...
- Electron:主进程和渲染进程
- 一种分片更新ubi卷的方式(基于ubiupdatevol,拓展fifo支持)
ubi卷的更新方式 对于ubi卷,不能像普通块设备一样进行随机读写.每次更新需要从头写入. 具体的,需要在打开对应的设备之后,先执行一个ioctl UBI_IOCVOLUP,同时传入要更新的数据大小. ...