<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          深入理解高通相機架構(八)

          共 12560字,需瀏覽 26分鐘

           ·

          2022-04-11 23:25

          和你一起終身學習,這里是程序員Android

          經(jīng)典好文推薦,通過閱讀本文,您將收獲以下知識點:

          一、概覽
          二、核心模塊解析
          三、模塊初始化
          四、處理UMD CSL請求

          相機驅動層–高通KMD框架詳解

          一、概覽

          利用了V4L2可擴展這一特性,高通在相機驅動部分實現(xiàn)了自有的一套KMD框架,該框架通過V4L2標準方法在系統(tǒng)中創(chuàng)建設備節(jié)點,將控制接口直接暴露給UMD CSL進行訪問,而其內(nèi)部主要定義了一系列核心模塊,包括CRM(Camera Request Manager),用于管理整個KMD的Session/Link的創(chuàng)建銷毀以及Request的在子設備間的流轉,該模塊創(chuàng)建video0設備節(jié)點暴露關鍵接口給UMD,此外還包括了Sync模塊,主要負責了UMD/KMD之間的數(shù)據(jù)同步與傳輸,創(chuàng)建video1設備節(jié)點暴露接口給UMD進行訪問,除此之外,為了更精細化地控制一系列的硬件圖像處理模塊,包括ISP/IPE/Sensor等硬件模塊,高通也分別為各自子模塊創(chuàng)建了設備節(jié)點,進而暴露控制接口給UMD進行訪問。
          其中主要目錄如下:

          • cam_core/:關于KMD核心函數(shù)的實現(xiàn)都放在這,主要包括了subdev、node、context的一些諸如創(chuàng)建/注冊/銷毀等標準方法。

          • cam_req_mgr/: CRM的具體實現(xiàn),用于創(chuàng)建v4l2_device,用于管理所有的子設備,同時生成video設備節(jié)點,暴露控制接口給UMD,主要包括了Session/Link的行為管理以及Request的同步與分發(fā),此外,還創(chuàng)建了media_device,用于暴露枚舉接口給UMD來輪詢查找整個KMD的子設備。

          • cam_sync/: 該部分主要實現(xiàn)了用于保持與UMD的圖像數(shù)據(jù)的同步相關業(yè)務邏輯,由于該模塊的特殊性,高通直接為其創(chuàng)建了一個單獨的video設備節(jié)點,暴露了用于同步的一些控制接口。

          • cam_utils/: 一些共有方法的實現(xiàn),包括debug方法集等

          • cam_smmu/: 高通自己實現(xiàn)了一套smmu api,供KMD使用

          • cam_lrme/: 低分辨率運動估計模塊的驅動實現(xiàn)

          • cam_fd/: 人臉識別的驅動程序

          • cam_isp/: isp的驅動程序

          • cam_jpeg/: 編碼器,可以通過該驅動完成jpeg的編碼工作

          • cam_cdm/: camera data mover,數(shù)據(jù)移動器的驅動實現(xiàn),主要用于解析由CSL傳入的命令信息,其中包括了寄存器的設置以及圖像數(shù)據(jù)的處理等。

          • cam_cpas/: 該模塊主要用于CSL獲取camera 平臺驅動信息,IPE/BPS電源控制等

          • cam_icp/: image control processor ,圖像處理控制器驅動實現(xiàn)

          • cam_sensor_module/: 類傳感器的系列硬件模塊

            • cam_actuator/: 對焦馬達的驅動實現(xiàn)

            • cam_cci/: 實現(xiàn)了用于通訊的CCI接口,其中包括了I2C以及gpio的實現(xiàn)

            • cam_csiphy: 基于MIPI CSI接口的物理層驅動,用于傳輸圖像數(shù)據(jù)

            • cam_sensor_io: 使用cam_cci,向上實現(xiàn)了控制sensor的IO接口

            • cam_sensor: sensor 的驅動實現(xiàn)

            • cam_sensor_util: sensor相關的公有方法的實現(xiàn)

            • cam_eeprom: eeprom設備的驅動實現(xiàn)

            • cam_ois :光學防抖設備的驅動實現(xiàn)

            • cam_flash: 閃光燈設備的驅動實現(xiàn)

          二、核心模塊解析

          正如之前介紹的那樣,整個框架主要由三個部分組成,CRM/Camera Sync以及子模塊,接下來我們以下圖為例簡單講解下各自的關系:


          程序員Android轉于網(wǎng)絡

          在系統(tǒng)初始化時,CRM內(nèi)部會創(chuàng)建一個v4l2_device結構體,用于管理所有的子設備,與此同時每一個子設備在注冊的時候都會創(chuàng)建各自的v4l2_subdev掛載到該v4l2_device上面。此外,CRM會創(chuàng)建一個video0設備節(jié)點提供關鍵接口給CSL來進行訪問,而每個子設備也會在系統(tǒng)中生成各自的v4l2-sbudev設備節(jié)點,提供接口給CSL進行更為精細化的控制。而其中的Cam Sync在初始化的過程中,也創(chuàng)建了一個v4l2_device設備,并且生成了video1節(jié)點給CSL進行控制。這個框架主要就是圍繞這三個部分進行的,CRM用于管理Session/Link的創(chuàng)建,控制Request在各個子設備中的流轉,子設備受CSL控制進行配置以及圖像處理工作,而一旦圖像處理完成便會將結果發(fā)送至Cam Sync模塊,進上傳至CSL中。

          1. CRM(Camera Request Manager)

          該模塊本質上是一個軟件模塊,主要做了以下幾個事情:

          • 接收來自CSL的Session/Link/Request請求,并且維護其在內(nèi)核的狀態(tài)。

          • 在不同pipeline delay的子模塊間,同步每一個Request狀態(tài),并按照需要發(fā)送給每一個子設備。

          • 如果出現(xiàn)錯誤,負責上傳至CSL。

          • 負責針對實時子模塊的flush操作。

          其中針對Session/Link/Request的請求便是通過之前創(chuàng)建的video設備節(jié)點將接口暴露給CSL,一旦接收到命令便開始進行處理,而命令主要有以下幾個:

          • CAM_REQ_MGR_CREATE_SESSION/CAM_REQ_MGR_DESTROY_SESSION:分別表示了Session的創(chuàng)建和銷毀,該Session保持著與CamX-CHI的一一對應關系。

          • CAM_REQ_MGR_LINK/CAM_REQ_MGR_UNLINK:分別表示了Link的創(chuàng)建和銷毀動作,每一個Session可以包含多條Link,而每一個Link都連接著此次圖像采集過程中所需要的子設備,CRM也是通過該Link來管理Request同步與分發(fā)的操作。

          • CAM_REQ_MGR_SCHED_REQ:一旦CSL開始下發(fā)Request的時候,便可以通過該命令告知KMD,而在KMD中,CRM會將此次Request存入Link中的in_q數(shù)組中,當子設備告知準備好了此次Request的處理后,便通知子設備進行配置并處理Request。

          • CAM_REQ_MGR_ALLOC_BUF/CAM_REQ_MGR_RELEASE_BUF: 圖像緩沖區(qū)的申請與釋放,CRM中使用cam_mem_table結構體來管理著申請的緩沖區(qū)。

          一旦CRM接收了來自CSL的請求,便會在內(nèi)部進行處理,而其中的一系列業(yè)務處理便會通過接下來的幾個結構體來完成:

          首先在初始化過程中,會去創(chuàng)建一個cam_req_mgr_device。
          該結構體有以下幾個主要的成員:

          • video: 存儲著對應的video_device。

          • v4l2_dev: 保存著初始化過程中創(chuàng)建的v4l2_device。

          • subdev_nodes_created: 標志著從屬于v4l2_device的子設備是否都成功創(chuàng)建了設備節(jié)點。

          • cam_eventq:v4l2文件描述結構體,其中維護著event事件隊列。

          之后會去創(chuàng)建一個cam_req_mgr_core_device,該結構體比較簡單主要用于維護一個Session鏈表,在CSL下發(fā)創(chuàng)建Session的動作后,會將創(chuàng)建好的Session放入該量表中,同時通過crm_lock保持著業(yè)務處理中的同步。

          一個Session可以包含很多條Link,其中變量num_links存儲了Link數(shù)量,數(shù)組links存儲著所有l(wèi)ink,entry變量作為當前session的實體可以嵌入cam_req_mgr_core_device中的session鏈表中進行統(tǒng)一管理。

          在CSL下發(fā)CAM_REQ_MGR_LINK命令的時候,會去創(chuàng)建cam_req_mgr_core_link。
          該結構體比較復雜,接下來我們主要介紹下幾個主要的變量:

          • link_hdl:作為該Link的句柄,區(qū)別于其它Link。

          • num_devs:表示了該條Link上連接了多少個子設備。

          • max_delay:表示了從屬于該Link上的所有子設備具有的最大的Pipeline delay值。

          • l_dev:存儲著所有從屬于該Link上的子設備,后續(xù)對于子設備的控制都是通過該數(shù)組來進行的。

          • req:該成員主要用于管理下發(fā)的request。

          • state: 標志著該Link的狀態(tài),而Link狀態(tài)主要包括了CAM_CRM_LINK_STATE_AVAILABLE/CAM_CRM_LINK_STATE_IDLE/CAM_CRM_LINK_STATE_READY/CAM_CRM_LINK_STATE_ERR幾種狀態(tài)。

          創(chuàng)建完Link之后,會將其存入一個存儲cam_req_mgr_core_link的全局變量g_links中進行統(tǒng)一管理。

          而當下發(fā)CAM_REQ_MGR_SCHED_REQ命令的時候,會在內(nèi)部進行解析,并且將其存入cam_req_mgr_core_link中的cam_req_mgr_req_data中等待后續(xù)的流轉。
          其中in_q變量主要用于存儲request,而l_tbl用于記錄pipeline delay的相關信息,而apply_data數(shù)組用于存儲所有的等待處理的request信息。

          2. Cam Sync

          該模塊本質上是一個軟件模塊,用于保持與UMD的圖像數(shù)據(jù)的同步,主要利用了V4L2框架的event機制,由CSL進行事件的等待,一旦數(shù)據(jù)處理完畢,該模塊便可以向上層發(fā)送事件,進而,通知CSL取出數(shù)據(jù)進行下一步處理,其中包括了幾個主要ioctl的命令:

          • CAM_SYNC_CREATE: 一旦CSL部分需要創(chuàng)建一個用于同步的實體的時候便下發(fā)該命令,而在Cam Sync中,會將傳入的信息存入內(nèi)部的sync_table_row數(shù)組中進行管理,并且將生成的sync_obj傳入上層。

          • CAM_SYNC_DESTROY:銷毀用于同步的sync實體。

          • CAM_SYNC_REGISTER_PAYLOAD:通過該命令將一些同步的回調方法注冊到Cam Sync中,這樣一當數(shù)據(jù)處理完成,Cam Sync便可以由之前創(chuàng)建的sync_obj來找到相應的回調方法,進而調用該回調方法進行后續(xù)處理。

          • CAM_SYNC_DEREGISTER_PAYLOAD:釋放之前注冊的相關同步實體的信息,包括其回調方法。

          • CAM_SYNC_SIGNAL:該命令主要用于CamX-CHI中軟件Node處理完數(shù)據(jù)之后,通知Cam Sync進行后續(xù)處理的目的。

          其中包括了幾個比較重要的結構體,首先在初始化過程中會去創(chuàng)建sync_device結構體,其主要的幾個變量如下:

          • vdev: 創(chuàng)建的video_device。

          • v4l2_dev: 創(chuàng)建的v4l2_device設備。

          • sync_table: 用于存儲sync_table_row的數(shù)組。

          • cam_sync_eventq: v4l2設備描述符結構體,其中維護著event事件隊列。

          其中最重要的時sync_table中存儲的sync_table_row結構體,它代表了整個對應于CSL中的sync object,其中比較重要的變量含義如下:

          • sync_id:該sync object的唯一標識,同時該標識于CSL保持同步。

          • state: 代表了當前sync object的狀態(tài)。

          • user_payload_list:存儲著該sync object所對應的來自UMD的payload,該payload在KMD中并沒有被使用,僅僅存儲與KMD中,一旦當前sync object被觸發(fā),便直接將其再次傳入UMD中。

          三、模塊初始化

          在系統(tǒng)啟動初期,整個相機驅動中的各個模塊都開始進行加載了,接下來我們依次介紹下:

          首先是CRM的初始化,按照linux驅動模塊的標準方法,會走到module_init宏聲明的驅動結構體中的probe方法,這里是cam_req_mgr_probe方法,在該方法中主要做了以下幾個事情:

          • 調用cam_v4l2_device_setup方法,創(chuàng)建并向系統(tǒng)注冊用于管理所有子設備的v4l2_device。

          • 調用cam_media_device_setup方法,創(chuàng)建并向系統(tǒng)注冊media_device,并且創(chuàng)建了media設備節(jié)點,用于CSL枚舉KMD中所有設備。

          • 調用cam_video_device_setup方法,創(chuàng)建video_device,并將v4l2_device嵌入到該結構體中,緊接著,使用標準的video注冊方法,創(chuàng)建了video0設備節(jié)點,其中將g_cam_ioctl_ops方法集作為了video0的擴展方法,CSL下發(fā)的有關Session/Link/Request的諸多操作都是通過該方法集來進行分發(fā)的,最后將video0 media_entity中的function賦值CAM_VNODE_DEVICE_TYPE,這樣CSL便可以通過該function判斷出該節(jié)點便是CRM了。

          • 調用cam_req_mgr_util_init方法,其中初始化了一個cam_req_mgr_util_hdl_tbl,該結構體中存在一個handle數(shù)組,而每一個handle主要用于存儲Session、Link以及各個子設備的相關信息,后期在整個圖像采集的過程中,都是通過該結構體來找對應的操作實體,進而采取相應的動作。

          • 調用cam_req_mgr_core_device_init方法,該方法中,會去創(chuàng)建并初始化一個cam_req_mgr_core_device結構體,作為全局變量g_crm_core_dev存在于整個框架中,而該結構體中主要包含了用于存儲創(chuàng)建的Session的session_head鏈表,以及用于保護Session臨界資源的crm_lock。

          其次,是Cam Sync的初始化,整個流程最終會走到驅動結構體中的probe方法中,這里是cam_sync_probe方法,在該方法中主要做了以下幾個事情:

          • 創(chuàng)建sync_dev結構體,該結構中通過一個sync_table_row數(shù)組來維護著所有的sync objects。

          • 調用cam_sync_media_controller_init方法,用于創(chuàng)建media_deivce設備,并且創(chuàng)建了media設備節(jié)點,提供給CSL枚舉子設備的能力。

          • 調用v4l2_device_register方法,創(chuàng)建并像系統(tǒng)注冊一個v4l2_device結構體,其中用于ioctl的方法集是指向的g_cam_sync_ioctl_ops,一旦CSL有創(chuàng)建/注冊sync objects需求的時候,便會最終走到該方法中,從而實現(xiàn)相應的功能。

          • 調用video_register_device方法,生成video1設備節(jié)點,暴露控制接口給CSL。

          • 調用cam_sync_init_entity方法,將video1中的meida_entity中function字段賦值CAM_SYNC_DEVICE_TYPE,這樣在UMD就可以通過相應的media節(jié)點枚舉出該模塊。

          以上兩個模塊都是具有獨立的video設備節(jié)點的,但是對于子設備而言,由于代表著相應的硬件設備,同時需要嵌入到整個框架中才能正常運行,所以高通將其抽象成了v4l2_subdev來進行管理,這里主要還是介紹兩個比較有代表性的子模塊,ISP以及Sensor。

          首先來看下ISP的初始化階段,在其相應的probe方法cam_isp_dev_probe中做了如下幾個事情:

          • 調用cam_subdev_probe方法,在該方法中,會去注冊一個v4l2_subdev,并且將其掛載到CRM中的v4l2_device上,同時還創(chuàng)建了一個node,并且存入了v4l2_subdev中的token中,方便以后進行讀取,另外,將方法集賦值為cam_subdev_ops,最后,創(chuàng)建了該v4l2_subdev內(nèi)部的media_entity, 并且為其function字段賦值為CAM_IFE_DEVICE_TYPE,這樣也方便在枚舉子設備時分辨出當前節(jié)點代表著isp模塊。

          • 調用cam_isp_hw_mgr_init方法,該方法用于初始化isp中的硬件模塊。

          • 調用cam_isp_context_init方法,該方法中會初始化node,在node內(nèi)部創(chuàng)建一定數(shù)量的context,用于后期的狀態(tài)維護,并且為每一個context都配置了狀態(tài)機,以及子狀態(tài)機來用于管理整個isp模塊。

          其次來看下Sensor模塊的初始化,在其相應的probe方法cam_sensor_driver_i2c_probe中主要做了以下幾個事情:

          • 調用cam_sensor_parse_dt方法獲取dts中定義的硬件信息。

          • 調用cam_sensor_init_subdev_params方法,該方法中會創(chuàng)建v4l2_subdev,然后掛載到CRM中的v4l2_device中,并且將sensor的私有方法集cam_sensor_internal_ops賦值給v4l2_subdev結構體中的ops,這樣一旦操作相應的子設備節(jié)點,便最終會走到該方法集中,關于Sensor的一些操作便可以放到這個里面進行處理。最終將創(chuàng)建的v4l2_subdev中的media_entity中functon賦值為CAM_SENSOR_DEVICE_TYPE,方便CSL進行枚舉Sensor設備。

          通過上面的兩個子設備的初始化代碼梳理,不難發(fā)現(xiàn),并沒有進行設備節(jié)點的創(chuàng)建,那關于節(jié)點的創(chuàng)建動作發(fā)生在哪一個階段呢?為了解決這個疑問我們不得不先介紹下linux兩個宏定義,一個是module_init,另一個便是late_initcall,兩者都是為了聲明初始化函數(shù),但是執(zhí)行時間有一個先后順序,而late_initcall一般在所有module_init定義的方法都運行完成之后才會被運行,而針對所有子設備的節(jié)點的創(chuàng)建便是在這里完成的,在該方法中主要做了以下工作:

          • 調用cam_dev_mgr_create_subdev_nodes方法,而在該方法中會去調用v4l2標準方法v4l2_device_register_subdev_nodes來統(tǒng)一創(chuàng)建掛載在CRM中v4l2_device下的子設備節(jié)點。

          至此,整個KMD框架便初始化完成,現(xiàn)在便靜靜等待CSL下發(fā)請求。

          四、處理UMD CSL請求

          整個KMD的初始化動作在linux內(nèi)核啟動的時候完成的,要稍早于CamX-CHI整個框架的初始化,所以在CamX-CHI進行初始化的時候,KMD框架的各個資源節(jié)點都已準備妥當,接下來我們就以CamX-CHI的初始化開始詳細描述下整個KMD處理來自CSL請求的流程。

          1. 獲取模塊資源

          在CamX-CHI初始化的時候,并不知道內(nèi)核驅動部分是個什么狀態(tài),所以需要打開所有的media設備節(jié)點來枚舉查詢每一個驅動模塊。

          首先,打開media0,根據(jù)CAM_VNODE_DEVICE_TYPE信枚舉并找到KMD框架中的CRM模塊,并調用標準open方法來打開該設備,該動作最終會調用到cam_req_mgr_open方法,該方法主要做了以下幾個工作:

          • 調用v4l2_fh_open方法,打開v4l2文件。

          • 調用cam_mem_mgr_init方法,初始化了內(nèi)存管理模塊,為之后的緩沖區(qū)的申請與釋放做好準備。

          • 更新CRM狀態(tài)為CAM_MEM_MGR_INITIALIZED。

          在打開video0之后,會另起一個線程用于監(jiān)聽video的事件,這樣就建立了與底層的雙向通訊,而在此之前,需要通過ioctl方法將CSL需要監(jiān)聽的事件下發(fā)到驅動層,其中包括以下幾個事件:

          • V4L_EVENT_CAM_REQ_MGR_SOF/V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS:一旦底層產(chǎn)生的SOF事件,便會向CSL發(fā)送該事件。

          • V4L_EVENT_CAM_REQ_MGR_ERROR:一旦底層產(chǎn)生了錯誤,會向上拋出該事件。

          一旦CSL獲取了CRM模塊信息成功之后,便開始枚舉查找各個子模塊了,其中會先去打開Sensor子設備,獲取硬件信息,并且存入CSL中,然后再依次獲取其它諸如IFE/IPE等硬件子模塊并獲取各自的信息,并存入CSL中,為之后的數(shù)據(jù)流轉做好準備。

          以上動作都完成之后,便開始查詢Cam Sync模塊了,基本流程與CRM大致相同:

          • 調用open方法打開video1,該方法最終會調用內(nèi)核部分的cam_sync_open方法,而該方法中會調用v4l2_fh_open方法,從而打開v4l2文件。

          • 調用ioctl方法,訂閱針對CAM_SYNC_V4L_EVENT_ID_CB_TRIG事件的監(jiān)聽 ,而對于該事件,一般是在子模塊處理數(shù)據(jù)完成之后,會觸發(fā)Cam Sync發(fā)送該事件至上層。

          2. 打開Session

          好了,到這里,整個CamX初始化過程對于底層的請求都已經(jīng)完成了,一旦用戶打開相機應用之后,經(jīng)過層層調用最終會去打開Session,進而調用video0的相應的ioctl方法傳入CAM_REQ_MGR_CREATE_SESSION命令開始在驅動層打開Session的操作,而在驅動部分,會調用到CRM中的cam_req_mgr_create_session方法,在該方法中,會去創(chuàng)建一個用于代表session的handle,并將其存入全局靜態(tài)變量hdl_tbl中。緊接著會去初始化該session中的link,其中該session管理著兩個link數(shù)組,一個是用于初始化的links_init數(shù)組,一個是用于運行起來之后使用的links數(shù)組,這里的會首先初始化所有的links_init中的link,在使用的時候,會從該數(shù)組去取出一個空閑的link放入links中進行管理。

          3. 打開設備

          在打開Session之后,隨著Pipeline的創(chuàng)建,CamX會通過調用CSL中的相應Node的ioctl方法,下發(fā)CAM_ACQUIRE_DEV命令,來依次打開底層硬件設備,這里我們還是以ISP為例進行分析:

          • 一旦CSL調用了ISP設備節(jié)點的ioctl并且下發(fā)了CAM_ACQUIRE_DEV命令,并會通過層層調用一直調到__cam_node_handle_acquire_dev方法,在該方法中會首先去在ISP對應的node中的存儲空閑context的隊列中獲取一個context。

          • 緊接著,調用了cam_context_handle_acquire_dev方法,來通過調用之前獲取的context的對用的狀態(tài)機方法集中的acquire_dev方法來打開isp設備,而在該方法中,會調用cam_create_device_hdl方法,將當前session handle以及isp操作方法集存入存入hdl_tbl中,之后crm會通過該方法集操作isp模塊。之后會將當前isp context狀態(tài)更新為CAM_CTX_ACQUIRED,并且初始化了用于管理request的active_req_list/wati_req_list/pending_req_list/pending_req_list/free_req_list鏈表,并且將初始化好req_list都掛載到free鏈表中。

          除了ISP,會根據(jù)不同的圖像采集需求,打開不同的子設備,基本流程差不多,都是通過下發(fā)CAM_ACQUIRE_DEV命令來完成的,這里我們便不進行贅述了。

          4. 創(chuàng)建Link

          在打開所有的子設備之后,緊接著需要將它們鏈接起來形成一個拓撲結構,方便各個子模塊的管理。而這個動作還是通過調用CRM對應的ioctl下發(fā)CAM_REQ_MGR_LINK命令來完成的,該動作會經(jīng)過層層調用,一直調用到CRM中的cam_req_mgr_link方法,接下來我們具體介紹下該方法的主要動作:

          • 調用__cam_req_mgr_reserve_link方法,在該方法中,首先會去從當前Session中的links_init數(shù)組中取出一個空閑的link,將其存入links數(shù)組,并且初始化其中的用于管理所有的request的in_q隊列。

          • 調用cam_create_device_hdl,創(chuàng)建link對應的handle,并且存入hdl_tbl中。

          • 調用__cam_req_mgr_create_subdevs方法,初始化用于存儲處于當前Link中的所有子設備。

          • 調用__cam_req_mgr_setup_link_info方法,該方法首先會去調用該link中的所有子設備的get_dev_info方法來獲取設備信息,然后會去依次調用hdl_tbl中的鏈接在此Link上的所有子設備的setup_link方法,來連接子設備,同時也將CRM的一些回調方法通過該方式注入到子設備中,使其具有通知CRM的能力。

          • 更新該Link狀態(tài)為CAM_CRM_LINK_STATE_READY,并且創(chuàng)建了一個工作隊列用于操作的異步處理。

          5. 開啟數(shù)據(jù)流

          一旦整個Link創(chuàng)建完成之后,便可以開啟數(shù)據(jù)流了,該動作通過CSL控制每一個子設備來完成,這里還是以ISP為例進行分析:

          由于在CamX初始化過程中已經(jīng)存有打開的ISP文件句柄,所有通過調用起iotcl方法下發(fā)CAM_START_DEV命令來通知底層ISP模塊開始進行數(shù)據(jù)流程傳輸,該命令首先會走到node,然后通過node下發(fā)到context,然后調用當前context的狀態(tài)機對應的start_dev方法,而在該方法中,會首先更新當前context狀態(tài)為CAM_CTX_ACTIVATED,然后通過操作底層硬件管理模塊開始數(shù)據(jù)流的處理。

          除了ISP,還有Sensor/FLash等模塊也是需要開啟數(shù)據(jù)流,為之后的Request的下發(fā)做好準備。

          6. 下發(fā)Request

          一旦開啟了整個數(shù)據(jù)處理流程,便可以接收Request請求了,而該動作依然還是通過CRM來完成,調用其ioctl方法,傳入CRM_WORKQ_TASK_SCHED_REQ命令,該動作最終會到達內(nèi)核CRM中的cam_req_mgr_schedule_request方法,而方法會將此次任務封裝成task交由工作隊列進行異步處理,而在工作隊列中最終會調用其回調方法cam_req_mgr_process_sched_req,該方法主要做了如下工作:

          • 取出該request從屬的link,并且將其中的in_q取出,找到一個空閑的slot,并將該slot便作為此次request在內(nèi)核中的實體。

          • 更新該slot的狀態(tài)為CRM_SLOT_STATUS_REQ_ADDED,并且將link中的open_req_cnt計數(shù)加1。

          從上面的梳理不難看出,下發(fā)Request的操作并不復雜,其中并沒有一個實際的Request下發(fā)到子設備的動作,所以很自然地會產(chǎn)生一個疑問,沒有下發(fā)Request的動作,那CRM是如何來驅動整個Request的流轉的呢? 所以接下來我們來進一步介紹下,整個Request的流轉機制。

          7. 子設備處理數(shù)據(jù)

          當CSL下發(fā)Request到KMD之后,便會進入到DRQ中進行流轉,通過之前對于CamX的學習,想必大家應該已經(jīng)熟悉了整個DRQ的運行機制,DRQ的每一個Node都會有一定依賴關系,一旦某個Node滿足依賴關系之后,便會調用其ProcessRequest開始進行此次的Request處理,而該動作會將圖像數(shù)據(jù)的以及配置信息打包,通過調用ioctl方法下發(fā)CAM_CONFIG_DEV到具體的子設備節(jié)點來將配置寫入KMD子設備中,而一旦子設備收到此次請求之后,會調用當前context的狀態(tài)機所對應的config_dev方法,接下來我們具體介紹下其中的所作的動作:

          • 將此次配置信息包括圖像數(shù)據(jù)放入硬件管理模塊中,但是此時并不進行處理,等待處理指示。

          • 將此次Request信息封裝一下,通過調用之前setup_link傳入的回調方法集中的add_req方法通知CRM,而在CRM中,會首先通過一系列的判斷,如果條件滿足了便將此次request對應的slot狀態(tài)更新為CRM_REQ_STATE_READY,并將該request存入pending隊列中。

          由上面的分析,發(fā)現(xiàn)該過程中并沒有進行實際的硬件配置或者處理,此時便需要等待SOF的事件,來驅動接下來的操作,而SOF事件是ISP來通知CRM的,具體流程如下:

          • EPOCH中斷產(chǎn)生,觸發(fā)回調方法__cam_isp_ctx_notify_sof_in_activated_state,在該方法中會封裝事件,并且通過調用CRM中傳入的回調方法notify_trigger將事件發(fā)送至CRM中。

          • 一旦CRM收取到SOF事件,便會去找到對應的滿足要求的request,并且調用__cam_req_mgr_process_req方法通知相應的子設備進行配置。

          • 最后ISP會將此次SOF事件通過V4L2 event機制發(fā)送至UMD,通知到CSL中。

          8. 數(shù)據(jù)操作完成

          當CamX中的各自Node完成了下發(fā)Request的操作之后,便會等待數(shù)據(jù)的處理完成,一旦完成便會觸發(fā)buf_done中斷,進而告知context,最終會調用cam_sync_signal方法來通知Cam Sync,而在Cam Sync中會通過子設備調用cam_sync_signal時傳入的sync_id在sync_table_row找到相應的sync object,最終通過event機制,將此次處理完成的事件傳入UMD CSL中,進而進行后續(xù)處理。

          等到最后一個Node處理完成之后,此次Request的處理便宣告完成。

          之前QCamera & Mm-Camera架構采用的相機驅動比較簡單,主要就承擔了硬件的上下電以及讀寫寄存器的任務,并且控制方向都是從上到下,并且控制邏輯由UMD負責。但是隨著時代的發(fā)展,相機硬件模塊越發(fā)復雜,所以用于直接控制硬件的驅動層也需要承擔更為復雜的控制任務,通過上面的分析,我們可以看到,高通重新設計了一套優(yōu)秀的KMD框架,在其中加入了更多復雜的控制邏輯,以達到精細化控制底層硬件模塊的目的,其中比較重要的是CRM對于子設備的橫向控制,這樣的好處很明顯,降低了UMD控制驅動的難度,UMD只需要將請求通過V4L2框架中的設備節(jié)點下發(fā)至KMD中,之后便由KMD中的CRM來統(tǒng)一管理,適時地將請求下發(fā)給各個子設備,進而控制著底層硬件模塊。

          原文鏈接:https://blog.csdn.net/u012596975/article/details/107138655

          友情推薦:

          Android 開發(fā)干貨集錦

          至此,本篇已結束。轉載網(wǎng)絡的文章,小編覺得很優(yōu)秀,歡迎點擊閱讀原文,支持原創(chuàng)作者,如有侵權,懇請聯(lián)系小編刪除,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!

          點擊閱讀原文,為大佬點贊!

          瀏覽 303
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色的一级的操逼的 | 18禁黄无码免费网站 | 色哟哟《欧美精品》 | 免费一级特黄录像 | 四虎精品成人无码A片 |