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 ...
随机推荐
- 数据库Oracle数字函数
数字函数不多: ROUND(arg1):四舍五入保留整数. arg1:数字类型.原数字. arg2:整数类型.小数点保留的位数. SQL> select round(1256.564,2) fr ...
- zuul+security跨域Cors问题解决
zuul+security跨域Cors问题解决 简介 场景 在服务后台都会出现跨域cors问题,不过一般spring解决起来比较方便,在框架+框架的基础上,问题就显得特别明显了,各种冲突,不了解源码的 ...
- [TimLinux] Python 再谈元类 metaclass
本博文通过对以下链接进行理解后,编写. https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python 1. 类 类 ...
- Win32_DiskDrive 硬盘 参数说明
Availability --设备的状态. BytesPerSector --在每个扇区的物理磁盘驱动器的字节数. Capabilities --媒体访问设备的能力阵列. CapabilityD ...
- 开启mode="history"模式,需要服务端的支持,因为出现“刷新页面报错404”的问题;
mode="history"是去除链接中的'#'的,但是加上后页面刷新回报404错误,怎么办呢? 解决办法:只需要在nginx中最末尾加上 try_files $uri $uri/ ...
- 关于F5负载均衡你认识多少?
关于F5负载均衡你认识多少? 2018年06月09日 18:01:09 tvk872 阅读数:14008 网络负载均衡(load balance),就是将负载(工作任务)进行平衡.分摊到多个操作单 ...
- 【hibernate】映射继承关系
[hibernate]映射继承关系 转载:https://www.cnblogs.com/yangchongxing/p/10405151.html ========================= ...
- 14个Java并发容器,你用过几个?
作者:acupt 前言 不考虑多线程并发的情况下,容器类一般使用ArrayList.HashMap等线程不安全的类,效率更高.在并发场景下,常会用到ConcurrentHashMap.ArrayBlo ...
- 学习Python编程技术的流程与步骤,自学与参加培训学习都适用
一.清楚学习目标 无论是学习什么知识,都要有一个对学习目标的清楚认识.只有这样才能朝着目标持续前进,少走弯路,从学习中得到不断的提升,享受python学习计划的过程. 虽然目前的编程语言有很多,但是 ...
- SpringBoot微服务电商项目开发实战 --- api接口安全算法、AOP切面及防SQL注入实现
上一篇主要讲了整个项目的子模块及第三方依赖的版本号统一管理维护,数据库对接及缓存(Redis)接入,今天我来说说过滤器配置及拦截设置.接口安全处理.AOP切面实现等.作为电商项目,不仅要求考虑高并发带 ...