qcom 8953平臺 LCD亮滅屏流程及LCD知識點總結【轉】

来源:https://www.cnblogs.com/linhaostudy/archive/2019/11/08/11818722.html
-Advertisement-
Play Games

一、LK中亮屏流程 1. gcdb_display_init(),進行display初始化的起始地方; 2. oem_panel_select(),在這裡去選擇哪一款屏,也可以在這裡添加新一款屏; 3. dsi_panel_init()把屏頭文件中的配置信息拷貝到結構體中,並一些屏需要的配置; 4. ...


一、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的時候沒有配置上;

解決方案:修改相關屏的初始化參數,


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 查看系統版本 CentOS系統 # centos7查看命令 [root@localhost ~]# cat /etc/os-release # centos6/7通用命令 [root@localhost ~]# cat /etc/redhat-release [root@localhost ~]# ...
  • 什麼是bazel https://docs.bazel.build/versions/master/bazel-overview.html 使用 bazel 構建 c++ 工程 https://github.com/bazelbuild/examples/tree/master/cpp-tutori ...
  • 安裝Ubuntu18過程中,從u盤啟動ubunt安裝,出現mmx64.efi not found問題 如下圖: 製作好ubunt啟動盤之後在EFI/BOOT下會看到兩個文件,將其中grubx64.efi改名為mmx64.efi即可重裝系統。 ...
  • 問題描述 今天要去後臺看日誌查個問題,通過ssh登陸到伺服器後準備用平時非常熟悉的 命令打開日誌查看,突然xshell客戶端就閃退了。一時感覺很蒙,怎麼回事??由於之前有同事遇到類似的問題,提醒我說可能是伺服器磁碟滿了。一時也沒什麼其他頭緒,我就又登陸到伺服器上使用 命令看了下磁碟使用情況: 我們發 ...
  • 創建用戶 我們創建的這個用戶要放到 sudo 用戶組,以便於我們可以執行一些需要 root 許可權的操作。 最後一步是給 username 用戶設置一個密碼,方便遠程登錄主機使用。建議密碼要設置的相對複雜一些,避免被黑客猜測到密碼。 磁碟掛載 如果主機上有額外的磁碟,需要在操作系統進行掛載。磁碟分區、 ...
  • 1.安裝環境 Docker支持以下的CentOS版本 CentOS 6.5 (64-bit) 或更高的版本 Docker 要求 CentOS 系統的內核版本高於 3.10 ,查看本頁面的前提條件來驗證你的CentOS 版本是否支持 Docker 1 [root@tenghao510 ~]# unam ...
  • 參數|介紹 |: : maxThreads|最大可以創建請求的線程數 minSpareThreads|服務啟動時創建的處理請求的進程數 Connector中的port|創建伺服器端的埠號,此埠監聽用戶端的請求 enableLookups|如果為true,則可以通過調用request.getRem ...
  • 如何解決問題:程式無法正常啟動(0xc0000022) 下文是由NeoSmart技術,通過全球網路上的工程師開發者和技術人員一起收集起來的信息,進行彙總並編輯而成的。 錯誤現象 該錯誤一般會通過警告,錯誤,提示等形式在屏幕上提示0xc0000022 觸發錯誤的方式 文件占用或者訪問異常 安全軟體 缺 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...