和你一起終身學習,這里是程序員 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
至此,本篇已結束。轉載網絡的文章,小編覺得很優秀,歡迎點擊閱讀原文,支持原創作者,如有侵權,懇請聯系小編刪除,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!