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

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

經典好文推薦,通過閱讀本文,您將收穫以下知識點:

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

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

一、概覽

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

  • cam_core/: 關於KMD核心函數的實現都放在這,主要包括了subdev、node、context的一些諸如創建/註冊/銷燬等標準方法。
  • cam_req_mgr/: CRM的具體實現,用於創建v4l2_device,用於管理所有的子設備,同時生成video設備節點,暴露控制接口給UMD,主要包括了Session/Link的行爲管理以及Request的同步與分發,此外,還創建了media_device,用於暴露枚舉接口給UMD來輪詢查找整個KMD的子設備。
  • cam_sync/: 該部分主要實現了用於保持與UMD的圖像數據的同步相關業務邏輯,由於該模塊的特殊性,高通直接爲其創建了一個單獨的video設備節點,暴露了用於同步的一些控制接口。
  • cam_utils/: 一些共有方法的實現,包括debug方法集等
  • cam_smmu/: 高通自己實現了一套smmu api,供KMD使用
  • cam_lrme/: 低分辨率運動估計模塊的驅動實現
  • cam_fd/: 人臉識別的驅動程序
  • cam_isp/: isp的驅動程序
  • cam_jpeg/: 編碼器,可以通過該驅動完成jpeg的編碼工作
  • cam_cdm/: camera data mover,數據移動器的驅動實現,主要用於解析由CSL傳入的命令信息,其中包括了寄存器的設置以及圖像數據的處理等。
  • cam_cpas/: 該模塊主要用於CSL獲取camera 平臺驅動信息,IPE/BPS電源控制等
  • cam_icp/: image control processor ,圖像處理控制器驅動實現
  • cam_sensor_module/: 類傳感器的系列硬件模塊
    • cam_actuator/: 對焦馬達的驅動實現
    • cam_cci/: 實現了用於通訊的CCI接口,其中包括了I2C以及gpio的實現
    • cam_csiphy: 基於MIPI CSI接口的物理層驅動,用於傳輸圖像數據
    • cam_sensor_io: 使用cam_cci,向上實現了控制sensor的IO接口
    • cam_sensor: sensor 的驅動實現
    • cam_sensor_util: sensor相關的公有方法的實現
    • cam_eeprom: eeprom設備的驅動實現
    • cam_ois : 光學防抖設備的驅動實現
    • cam_flash: 閃光燈設備的驅動實現

二、核心模塊解析

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


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

1. CRM(Camera Request Manager)

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

  • 接收來自CSL的Session/Link/Request請求,並且維護其在內核的狀態。
  • 在不同pipeline delay的子模塊間,同步每一個Request狀態,並按照需要發送給每一個子設備。
  • 如果出現錯誤,負責上傳至CSL。
  • 負責針對實時子模塊的flush操作。

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

  • CAM_REQ_MGR_CREATE_SESSION/CAM_REQ_MGR_DESTROY_SESSION: 分別表示了Session的創建和銷燬,該Session保持着與CamX-CHI的一一對應關係。
  • CAM_REQ_MGR_LINK/CAM_REQ_MGR_UNLINK: 分別表示了Link的創建和銷燬動作,每一個Session可以包含多條Link,而每一個Link都連接着此次圖像採集過程中所需要的子設備,CRM也是通過該Link來管理Request同步與分發的操作。
  • CAM_REQ_MGR_SCHED_REQ:一旦CSL開始下發Request的時候,便可以通過該命令告知KMD,而在KMD中,CRM會將此次Request存入Link中的in_q數組中,當子設備告知準備好了此次Request的處理後,便通知子設備進行配置並處理Request。
  • CAM_REQ_MGR_ALLOC_BUF/CAM_REQ_MGR_RELEASE_BUF: 圖像緩衝區的申請與釋放,CRM中使用cam_mem_table結構體來管理着申請的緩衝區。

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

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

  • video: 存儲着對應的video_device。
  • v4l2_dev: 保存着初始化過程中創建的v4l2_device。
  • subdev_nodes_created: 標誌着從屬於v4l2_device的子設備是否都成功創建了設備節點。
  • cam_eventq: v4l2文件描述結構體,其中維護着event事件隊列。

之後會去創建一個cam_req_mgr_core_device,該結構體比較簡單主要用於維護一個Session鏈表,在CSL下發創建Session的動作後,會將創建好的Session放入該量表中,同時通過crm_lock保持着業務處理中的同步。

一個Session可以包含很多條Link,其中變量num_links存儲了Link數量,數組links存儲着所有link,entry變量作爲當前session的實體可以嵌入cam_req_mgr_core_device中的session鏈表中進行統一管理。

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

  • link_hdl:作爲該Link的句柄,區別於其它Link。
  • num_devs: 表示了該條Link上連接了多少個子設備。
  • max_delay: 表示了從屬於該Link上的所有子設備具有的最大的Pipeline delay值。
  • l_dev: 存儲着所有從屬於該Link上的子設備,後續對於子設備的控制都是通過該數組來進行的。
  • req: 該成員主要用於管理下發的request。
  • state: 標誌着該Link的狀態,而Link狀態主要包括了CAM_CRM_LINK_STATE_AVAILABLE/CAM_CRM_LINK_STATE_IDLE/CAM_CRM_LINK_STATE_READY/CAM_CRM_LINK_STATE_ERR幾種狀態。

創建完Link之後,會將其存入一個存儲cam_req_mgr_core_link的全局變量g_links中進行統一管理。

而當下發CAM_REQ_MGR_SCHED_REQ命令的時候,會在內部進行解析,並且將其存入cam_req_mgr_core_link中的cam_req_mgr_req_data中等待後續的流轉。
其中in_q變量主要用於存儲request,而l_tbl用於記錄pipeline delay的相關信息,而apply_data數組用於存儲所有的等待處理的request信息。

2. Cam Sync

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

  • CAM_SYNC_CREATE: 一旦CSL部分需要創建一個用於同步的實體的時候便下發該命令,而在Cam Sync中,會將傳入的信息存入內部的sync_table_row數組中進行管理,並且將生成的sync_obj傳入上層。
  • CAM_SYNC_DESTROY: 銷燬用於同步的sync實體。
  • CAM_SYNC_REGISTER_PAYLOAD: 通過該命令將一些同步的回調方法註冊到Cam Sync中,這樣一當數據處理完成,Cam Sync便可以由之前創建的sync_obj來找到相應的回調方法,進而調用該回調方法進行後續處理。
  • CAM_SYNC_DEREGISTER_PAYLOAD:釋放之前註冊的相關同步實體的信息,包括其回調方法。
  • CAM_SYNC_SIGNAL:該命令主要用於CamX-CHI中軟件Node處理完數據之後,通知Cam Sync進行後續處理的目的。

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

  • vdev: 創建的video_device。
  • v4l2_dev: 創建的v4l2_device設備。
  • sync_table: 用於存儲sync_table_row的數組。
  • cam_sync_eventq: v4l2設備描述符結構體,其中維護着event事件隊列。

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

  • sync_id:該sync object的唯一標識,同時該標識於CSL保持同步。
  • state: 代表了當前sync object的狀態。
  • user_payload_list: 存儲着該sync object所對應的來自UMD的payload,該payload在KMD中並沒有被使用,僅僅存儲與KMD中,一旦當前sync object被觸發,便直接將其再次傳入UMD中。

三、模塊初始化

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

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

  • 調用cam_v4l2_device_setup方法,創建並向系統註冊用於管理所有子設備的v4l2_device。
  • 調用cam_media_device_setup方法,創建並向系統註冊media_device,並且創建了media設備節點,用於CSL枚舉KMD中所有設備。
  • 調用cam_video_device_setup方法,創建video_device,並將v4l2_device嵌入到該結構體中,緊接着,使用標準的video註冊方法,創建了video0設備節點,其中將g_cam_ioctl_ops方法集作爲了video0的擴展方法,CSL下發的有關Session/Link/Request的諸多操作都是通過該方法集來進行分發的,最後將video0 media_entity中的function賦值CAM_VNODE_DEVICE_TYPE,這樣CSL便可以通過該function判斷出該節點便是CRM了。
  • 調用cam_req_mgr_util_init方法,其中初始化了一個cam_req_mgr_util_hdl_tbl,該結構體中存在一個handle數組,而每一個handle主要用於存儲Session、Link以及各個子設備的相關信息,後期在整個圖像採集的過程中,都是通過該結構體來找對應的操作實體,進而採取相應的動作。
  • 調用cam_req_mgr_core_device_init方法,該方法中,會去創建並初始化一個cam_req_mgr_core_device結構體,作爲全局變量g_crm_core_dev存在於整個框架中,而該結構體中主要包含了用於存儲創建的Session的session_head鏈表,以及用於保護Session臨界資源的crm_lock。

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

  • 創建sync_dev結構體,該結構中通過一個sync_table_row數組來維護着所有的sync objects。
  • 調用cam_sync_media_controller_init方法,用於創建media_deivce設備,並且創建了media設備節點,提供給CSL枚舉子設備的能力。
  • 調用v4l2_device_register方法,創建並像系統註冊一個v4l2_device結構體,其中用於ioctl的方法集是指向的g_cam_sync_ioctl_ops,一旦CSL有創建/註冊sync objects需求的時候,便會最終走到該方法中,從而實現相應的功能。
  • 調用video_register_device方法,生成video1設備節點,暴露控制接口給CSL。
  • 調用cam_sync_init_entity方法,將video1中的meida_entity中function字段賦值CAM_SYNC_DEVICE_TYPE,這樣在UMD就可以通過相應的media節點枚舉出該模塊。

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

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

  • 調用cam_subdev_probe方法,在該方法中,會去註冊一個v4l2_subdev,並且將其掛載到CRM中的v4l2_device上,同時還創建了一個node,並且存入了v4l2_subdev中的token中,方便以後進行讀取,另外,將方法集賦值爲cam_subdev_ops,最後,創建了該v4l2_subdev內部的media_entity, 並且爲其function字段賦值爲CAM_IFE_DEVICE_TYPE,這樣也方便在枚舉子設備時分辨出當前節點代表着isp模塊。
  • 調用cam_isp_hw_mgr_init方法,該方法用於初始化isp中的硬件模塊。
  • 調用cam_isp_context_init方法,該方法中會初始化node,在node內部創建一定數量的context,用於後期的狀態維護,並且爲每一個context都配置了狀態機,以及子狀態機來用於管理整個isp模塊。

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

  • 調用cam_sensor_parse_dt方法獲取dts中定義的硬件信息。
  • 調用cam_sensor_init_subdev_params方法,該方法中會創建v4l2_subdev,然後掛載到CRM中的v4l2_device中,並且將sensor的私有方法集cam_sensor_internal_ops賦值給v4l2_subdev結構體中的ops,這樣一旦操作相應的子設備節點,便最終會走到該方法集中,關於Sensor的一些操作便可以放到這個裏面進行處理。最終將創建的v4l2_subdev中的media_entity中functon賦值爲CAM_SENSOR_DEVICE_TYPE,方便CSL進行枚舉Sensor設備。

通過上面的兩個子設備的初始化代碼梳理,不難發現,並沒有進行設備節點的創建,那關於節點的創建動作發生在哪一個階段呢? 爲了解決這個疑問我們不得不先介紹下linux兩個宏定義,一個是module_init,另一個便是late_initcall,兩者都是爲了聲明初始化函數,但是執行時間有一個先後順序,而late_initcall一般在所有module_init定義的方法都運行完成之後纔會被運行,而針對所有子設備的節點的創建便是在這裏完成的,在該方法中主要做了以下工作:

  • 調用cam_dev_mgr_create_subdev_nodes方法,而在該方法中會去調用v4l2標準方法v4l2_device_register_subdev_nodes來統一創建掛載在CRM中v4l2_device下的子設備節點。

至此,整個KMD框架便初始化完成,現在便靜靜等待CSL下發請求。

四、處理UMD CSL請求

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

1. 獲取模塊資源

在CamX-CHI初始化的時候,並不知道內核驅動部分是個什麼狀態,所以需要打開所有的media設備節點來枚舉查詢每一個驅動模塊。

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

  • 調用v4l2_fh_open方法,打開v4l2文件。
  • 調用cam_mem_mgr_init方法,初始化了內存管理模塊,爲之後的緩衝區的申請與釋放做好準備。
  • 更新CRM狀態爲CAM_MEM_MGR_INITIALIZED。

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

  • V4L_EVENT_CAM_REQ_MGR_SOF/V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS: 一旦底層產生的SOF事件,便會向CSL發送該事件。
  • V4L_EVENT_CAM_REQ_MGR_ERROR: 一旦底層產生了錯誤,會向上拋出該事件。

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

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

  • 調用open方法打開video1,該方法最終會調用內核部分的cam_sync_open方法,而該方法中會調用v4l2_fh_open方法,從而打開v4l2文件。
  • 調用ioctl方法,訂閱針對CAM_SYNC_V4L_EVENT_ID_CB_TRIG事件的監聽 ,而對於該事件,一般是在子模塊處理數據完成之後,會觸發Cam Sync發送該事件至上層。

2. 打開Session

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

3. 打開設備

在打開Session之後,隨着Pipeline的創建,CamX會通過調用CSL中的相應Node的ioctl方法,下發CAM_ACQUIRE_DEV命令,來依次打開底層硬件設備,這裏我們還是以ISP爲例進行分析:

  • 一旦CSL調用了ISP設備節點的ioctl並且下發了CAM_ACQUIRE_DEV命令,並會通過層層調用一直調到__cam_node_handle_acquire_dev方法,在該方法中會首先去在ISP對應的node中的存儲空閒context的隊列中獲取一個context。
  • 緊接着,調用了cam_context_handle_acquire_dev方法,來通過調用之前獲取的context的對用的狀態機方法集中的acquire_dev方法來打開isp設備,而在該方法中,會調用cam_create_device_hdl方法,將當前session handle以及isp操作方法集存入存入hdl_tbl中,之後crm會通過該方法集操作isp模塊。之後會將當前isp context狀態更新爲CAM_CTX_ACQUIRED,並且初始化了用於管理request的active_req_list/wati_req_list/pending_req_list/pending_req_list/free_req_list鏈表,並且將初始化好req_list都掛載到free鏈表中。

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

4. 創建Link

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

  • 調用__cam_req_mgr_reserve_link方法,在該方法中,首先會去從當前Session中的links_init數組中取出一個空閒的link,將其存入links數組,並且初始化其中的用於管理所有的request的in_q隊列。
  • 調用cam_create_device_hdl,創建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狀態爲CAM_CRM_LINK_STATE_READY,並且創建了一個工作隊列用於操作的異步處理。

5. 開啓數據流

一旦整個Link創建完成之後,便可以開啓數據流了,該動作通過CSL控制每一個子設備來完成,這裏還是以ISP爲例進行分析:

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

除了ISP,還有Sensor/FLash等模塊也是需要開啓數據流,爲之後的Request的下發做好準備。

6. 下發Request

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

  • 取出該request從屬的link,並且將其中的in_q取出,找到一個空閒的slot,並將該slot便作爲此次request在內核中的實體。
  • 更新該slot的狀態爲CRM_SLOT_STATUS_REQ_ADDED,並且將link中的open_req_cnt計數加1。

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

7. 子設備處理數據

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

  • 將此次配置信息包括圖像數據放入硬件管理模塊中,但是此時並不進行處理,等待處理指示。
  • 將此次Request信息封裝一下,通過調用之前setup_link傳入的回調方法集中的add_req方法通知CRM,而在CRM中,會首先通過一系列的判斷,如果條件滿足了便將此次request對應的slot狀態更新爲CRM_REQ_STATE_READY,並將該request存入pending隊列中。

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

  • EPOCH中斷產生,觸發回調方法__cam_isp_ctx_notify_sof_in_activated_state,在該方法中會封裝事件,並且通過調用CRM中傳入的回調方法notify_trigger將事件發送至CRM中。
  • 一旦CRM收取到SOF事件,便會去找到對應的滿足要求的request,並且調用__cam_req_mgr_process_req方法通知相應的子設備進行配置。
  • 最後ISP會將此次SOF事件通過V4L2 event機制發送至UMD,通知到CSL中。

8. 數據操作完成

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

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

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

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

至此,本篇已結束。轉載網絡的文章,小編覺得很優秀,歡迎點擊閱讀原文,支持原創作者,如有侵權,懇請聯繫小編刪除,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章