1e41f4b71Sopenharmony_ci# MIPI CSI
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ciThe Camera Serial Interface (CSI), defined by the Mobile Industry Processor Interface (MIPI) Alliance, allows data to be transmitted from the camera to the host processor on mobile platforms. In the Hardware Driver Foundation (HDF), the MIPI CSI module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the operating system (OS) that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** (a void pointer) directly points to the kernel-mode address of the device object.
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci**Figure 1** Service-free mode
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci![image1](figures/service-free-mode.png "service-free-mode")
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci## Available APIs
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci**MipiCsiCntlrMethod**:
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci```c
16e41f4b71Sopenharmony_cistruct MipiCsiCntlrMethod {
17e41f4b71Sopenharmony_ci    int32_t (*setComboDevAttr)(struct MipiCsiCntlr *cntlr, ComboDevAttr *pAttr);
18e41f4b71Sopenharmony_ci    int32_t (*setPhyCmvmode)(struct MipiCsiCntlr *cntlr, uint8_t devno, PhyCmvMode cmvMode);
19e41f4b71Sopenharmony_ci    int32_t (*setExtDataType)(struct MipiCsiCntlr *cntlr, ExtDataType* dataType);
20e41f4b71Sopenharmony_ci    int32_t (*setHsMode)(struct MipiCsiCntlr *cntlr, LaneDivideMode laneDivideMode);
21e41f4b71Sopenharmony_ci    int32_t (*enableClock)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
22e41f4b71Sopenharmony_ci    int32_t (*disableClock)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
23e41f4b71Sopenharmony_ci    int32_t (*resetRx)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
24e41f4b71Sopenharmony_ci    int32_t (*unresetRx)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
25e41f4b71Sopenharmony_ci    int32_t (*enableSensorClock)(struct MipiCsiCntlr *cntlr, uint8_t snsClkSource);
26e41f4b71Sopenharmony_ci    int32_t (*disableSensorClock)(struct MipiCsiCntlr *cntlr, uint8_t snsClkSource);
27e41f4b71Sopenharmony_ci    int32_t (*resetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource);
28e41f4b71Sopenharmony_ci    int32_t (*unresetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource);
29e41f4b71Sopenharmony_ci};
30e41f4b71Sopenharmony_ci```
31e41f4b71Sopenharmony_ci**Table 1** Description of the callback functions in the MipiCsiCntlrMethod structure
32e41f4b71Sopenharmony_ci| Function          | Input Parameter                                                        | Output Parameter| Return Value          | Description                      |
33e41f4b71Sopenharmony_ci| ------------------ | ------------------------------------------------------------ | ---- | ------------------ | -------------------------- |
34e41f4b71Sopenharmony_ci| setComboDevAttr    | **cntlr**: structure pointer to the MIPI CSI controller.<br>**pAttr**: structure pointer to the MIPI CSI configuration.| –  | HDF_STATUS| Sets MIPI CSI attributes.          |
35e41f4b71Sopenharmony_ci| setPhyCmvmode      | **cntlr**: structure pointer to the MIPI CSI controller.<br>**devno**: Device number, which is of the uint8_t type.<br>**cmvMode**: common-mode voltage (CMV) mode to set.| –  | HDF_STATUS| Sets the CMV mode.          |
36e41f4b71Sopenharmony_ci| setExtDataType     | **cntlr**: structure pointer to the MIPI CSI controller.<br>**dataType**: structure pointer to the data that defines the YUV, original data formats, and bit depth.| –  | HDF_STATUS| Sets the YUV, RAW data format, and bit depth.|
37e41f4b71Sopenharmony_ci| setHsMode          | **cntlr**: structure pointer to the MIPI CSI controller.<br>**laneDivideMode**: lane mode.| –  | HDF_STATUS| Sets the MIPI RX lane distribution.    |
38e41f4b71Sopenharmony_ci| enableClock        | **cntlr**: structure pointer to the MIPI CSI controller.<br>**comboDev**: channel number, which is of the uint8_t type.| –  | HDF_STATUS| Enables the MIPI clock.            |
39e41f4b71Sopenharmony_ci| disableClock       | **cntlr**: structure pointer to the MIPI CSI controller.<br>**comboDev**: channel number, which is of the uint8_t type.| –  | HDF_STATUS| Disables the MIPI clock.            |
40e41f4b71Sopenharmony_ci| resetRx            | **cntlr**: structure pointer to the MIPI CSI controller.<br>**comboDev**: channel number, which is of the uint8_t type.| –  | HDF_STATUS| Resets the MIPI RX.               |
41e41f4b71Sopenharmony_ci| unresetRx          | **cntlr**: structure pointer to the MIPI CSI controller.<br>**comboDev**: channel number, which is of the uint8_t type.| –  | HDF_STATUS| Deasserts the reset of the MIPI RX.           |
42e41f4b71Sopenharmony_ci| enableSensorClock  | **cntlr**: structure pointer to the MIPI CSI controller.<br>**snsClkSource**: number of the clock signal cable of the sensor, which is of the uint8_t type.| –  | HDF_STATUS| Enables the MIPI sensor clock.    |
43e41f4b71Sopenharmony_ci| disableSensorClock | **cntlr**: structure pointer to the MIPI CSI controller.<br>**snsClkSource**: number of the clock signal cable of the sensor, which is of the uint8_t type.| –  | HDF_STATUS| Disables the MIPI sensor clock.    |
44e41f4b71Sopenharmony_ci| resetSensor        | **cntlr**: structure pointer to the MIPI CSI controller.<br>**snsClkSource**: number of the clock signal cable of the sensor, which is of the uint8_t type.| –  | HDF_STATUS| Resets a sensor.                |
45e41f4b71Sopenharmony_ci| unresetSensor      | **cntlr**: structure pointer to the MIPI CSI controller.<br>**snsClkSource**: number of the clock signal cable of the sensor, which is of the uint8_t type.| –  | HDF_STATUS| Deasserts the reset of a sensor.     |
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ci## How to Develop
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ciThe MIPI CSI module adaptation involves the following steps:
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci1. Configure attribute files.     
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci   - Add the **deviceNode** information to the **device_info.hcs** file.
54e41f4b71Sopenharmony_ci   - (Optional) Add the **mipicsi_config.hcs** file.
55e41f4b71Sopenharmony_ci
56e41f4b71Sopenharmony_ci2. Instantiate the driver entry. 
57e41f4b71Sopenharmony_ci   
58e41f4b71Sopenharmony_ci   - Instantiate the **HdfDriverEntry** structure.
59e41f4b71Sopenharmony_ci   - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
60e41f4b71Sopenharmony_ci   
61e41f4b71Sopenharmony_ci3. Instantiate the MIPI CSI controller object.  
62e41f4b71Sopenharmony_ci   
63e41f4b71Sopenharmony_ci   - Initialize **MipiCsiCntlr**.
64e41f4b71Sopenharmony_ci   - Instantiate **MipiCsiCntlrMethod** in the **MipiCsiCntlr** object.
65e41f4b71Sopenharmony_ci     >![](../public_sys-resources/icon-note.gif) **NOTE**<br>
66e41f4b71Sopenharmony_ci     >For details about the functions in **MipiCsiCntlrMethod**, see [Available APIs](#available-apis).
67e41f4b71Sopenharmony_ci   
68e41f4b71Sopenharmony_ci4. Debug the driver.
69e41f4b71Sopenharmony_ci
70e41f4b71Sopenharmony_ci   (Optional) For new drivers, verify the basic functions, for example, the data transmission and the information returned after the **MipiCsiCntlrMethod** instance is attached.
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci   
73e41f4b71Sopenharmony_ci## Development Example
74e41f4b71Sopenharmony_ci
75e41f4b71Sopenharmony_ciThe following uses **mipi_rx_hi35xx.c** as an example to present the information required for implementing device functions.
76e41f4b71Sopenharmony_ci
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ci1. Configure the device attributes in **busxx_config.hcs** and add the **deviceNode** information to the **device_info.hcs** file. 
79e41f4b71Sopenharmony_ci
80e41f4b71Sopenharmony_ci   The device attribute values are closely related to the default values or value range of the **MipiCsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration.
81e41f4b71Sopenharmony_ci   
82e41f4b71Sopenharmony_ci    >![](../public_sys-resources/icon-note.gif) **NOTE**<br>
83e41f4b71Sopenharmony_ci    >In this example, the MIPI controller attributes are defined in the source file. If required, add the **deviceMatchAttr** information to **deviceNode** in the **device_info** file and add the **mipicsi_config.hcs** file.
84e41f4b71Sopenharmony_ci   
85e41f4b71Sopenharmony_ci   - **device_info.hcs** configuration example
86e41f4b71Sopenharmony_ci   
87e41f4b71Sopenharmony_ci     ```c
88e41f4b71Sopenharmony_ci     root {
89e41f4b71Sopenharmony_ci     device_info {
90e41f4b71Sopenharmony_ci         match_attr = "hdf_manager";
91e41f4b71Sopenharmony_ci         platform :: host {
92e41f4b71Sopenharmony_ci         hostName = "platform_host";
93e41f4b71Sopenharmony_ci         priority = 50;
94e41f4b71Sopenharmony_ci         device_mipi_csi:: device {
95e41f4b71Sopenharmony_ci         	device0 :: deviceNode {
96e41f4b71Sopenharmony_ci                 policy = 0;
97e41f4b71Sopenharmony_ci                 priority = 160;
98e41f4b71Sopenharmony_ci                 permission = 0644;
99e41f4b71Sopenharmony_ci                 moduleName = "HDF_MIPI_RX";    // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
100e41f4b71Sopenharmony_ci                 serviceName = "HDF_MIPI_RX";   // (Mandatory) Unique name of the service published by the driver.
101e41f4b71Sopenharmony_ci             }
102e41f4b71Sopenharmony_ci         }
103e41f4b71Sopenharmony_ci         }
104e41f4b71Sopenharmony_ci     }
105e41f4b71Sopenharmony_ci     }
106e41f4b71Sopenharmony_ci     ```
107e41f4b71Sopenharmony_ci     
108e41f4b71Sopenharmony_ci   
109e41f4b71Sopenharmony_ci2. Instantiate the driver entry.
110e41f4b71Sopenharmony_ci
111e41f4b71Sopenharmony_ci   The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. The function pointer members in the **HdfDriverEntry** structure are filled by the vendors' operation functions. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
112e41f4b71Sopenharmony_ci   
113e41f4b71Sopenharmony_ci   Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
114e41f4b71Sopenharmony_ci   
115e41f4b71Sopenharmony_ci   - MIPI CSI driver entry example
116e41f4b71Sopenharmony_ci   
117e41f4b71Sopenharmony_ci     ```c
118e41f4b71Sopenharmony_ci     struct HdfDriverEntry g_mipiCsiDriverEntry = {
119e41f4b71Sopenharmony_ci         .moduleVersion = 1,
120e41f4b71Sopenharmony_ci         .Init = Hi35xxMipiCsiInit,          // See the Init function.
121e41f4b71Sopenharmony_ci         .Release = Hi35xxMipiCsiRelease,    // See the Release function.
122e41f4b71Sopenharmony_ci         .moduleName = "HDF_MIPI_RX",        // (Mandatory) The value must be the same as that in the device_info.hcs file.
123e41f4b71Sopenharmony_ci     };
124e41f4b71Sopenharmony_ci     HDF_INIT(g_mipiCsiDriverEntry);         // Call HDF_INIT to register the driver entry with the HDF.
125e41f4b71Sopenharmony_ci     ```
126e41f4b71Sopenharmony_ci   
127e41f4b71Sopenharmony_ci     
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ci3. Initialize the **MipiCsiCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) to instantiate **MipiCsiCntlrMethod** in **MipiCsiCntlr** (so that the underlying driver functions can be called).
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ci   - Defining a custom structure
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci     To the driver, the custom structure holds parameters and data. The values in the **config** file are used to initialize the structure members. In this example, the MIPI CSI attributes are defined in the source file. Therefore, the basic member structure is similar to that of **MipiCsiCntlr**.
134e41f4b71Sopenharmony_ci
135e41f4b71Sopenharmony_ci     ```c
136e41f4b71Sopenharmony_ci     typedef struct {
137e41f4b71Sopenharmony_ci         /** The data type can be 8-, 10-, 12-, 14-, or 16-bit. */
138e41f4b71Sopenharmony_ci         DataType inputDataType;
139e41f4b71Sopenharmony_ci         /** MIPI WDM mode */
140e41f4b71Sopenharmony_ci         MipiWdrMode wdrMode;
141e41f4b71Sopenharmony_ci         /** laneId: -1 - disabled */
142e41f4b71Sopenharmony_ci         short laneId[MIPI_LANE_NUM];
143e41f4b71Sopenharmony_ci     
144e41f4b71Sopenharmony_ci         union {
145e41f4b71Sopenharmony_ci             /** Used for HI_MIPI_WDR_MODE_DT */
146e41f4b71Sopenharmony_ci             short dataType[WDR_VC_NUM];
147e41f4b71Sopenharmony_ci         };
148e41f4b71Sopenharmony_ci     } MipiDevAttr;
149e41f4b71Sopenharmony_ci     
150e41f4b71Sopenharmony_ci     typedef struct {
151e41f4b71Sopenharmony_ci         /** Device number */
152e41f4b71Sopenharmony_ci         uint8_t devno;
153e41f4b71Sopenharmony_ci         /** Input mode, which can be MIPI, LVDS, sub-LVDS, HiSPi, or DC. */
154e41f4b71Sopenharmony_ci         InputMode inputMode;
155e41f4b71Sopenharmony_ci         MipiDataRate dataRate;
156e41f4b71Sopenharmony_ci         /** Crop area of the MIPI RX device (same as the size of the sensor input image) */
157e41f4b71Sopenharmony_ci         ImgRect imgRect;
158e41f4b71Sopenharmony_ci     
159e41f4b71Sopenharmony_ci         union {
160e41f4b71Sopenharmony_ci             MipiDevAttr mipiAttr;
161e41f4b71Sopenharmony_ci             LvdsDevAttr lvdsAttr;
162e41f4b71Sopenharmony_ci         };
163e41f4b71Sopenharmony_ci     } ComboDevAttr;
164e41f4b71Sopenharmony_ci     
165e41f4b71Sopenharmony_ci     // MipiCsiCntlr is the core layer controller structure. The Init function assigns values to the members of MipiCsiCntlr.
166e41f4b71Sopenharmony_ci     struct MipiCsiCntlr {
167e41f4b71Sopenharmony_ci         /** Send the service provided by this controller when the driver is bound to the HDF. */
168e41f4b71Sopenharmony_ci         struct IDeviceIoService service;
169e41f4b71Sopenharmony_ci         /** Pass the pointer to the device when the driver is bound to the HDF. */
170e41f4b71Sopenharmony_ci         struct HdfDeviceObject *device;
171e41f4b71Sopenharmony_ci         /** Device number */
172e41f4b71Sopenharmony_ci         unsigned int devNo;
173e41f4b71Sopenharmony_ci         /** All APIs provided by the controller */
174e41f4b71Sopenharmony_ci         struct MipiCsiCntlrMethod *ops;
175e41f4b71Sopenharmony_ci         /** All APIs for controller debugging. Set it to null if the driver is not implemented. */
176e41f4b71Sopenharmony_ci         struct MipiCsiCntlrDebugMethod *debugs;
177e41f4b71Sopenharmony_ci         /** Controller context variable. */
178e41f4b71Sopenharmony_ci         MipiDevCtx ctx;
179e41f4b71Sopenharmony_ci         /** Spinlock used when the controller context variable is accessed. */
180e41f4b71Sopenharmony_ci         OsalSpinlock ctxLock;
181e41f4b71Sopenharmony_ci         /** Lock method when the controller is managed */
182e41f4b71Sopenharmony_ci         struct OsalMutex lock;
183e41f4b71Sopenharmony_ci         /** Pointer to the anonymous structure that holds the CSI device data */
184e41f4b71Sopenharmony_ci         void *priv;
185e41f4b71Sopenharmony_ci     };
186e41f4b71Sopenharmony_ci     ```
187e41f4b71Sopenharmony_ci
188e41f4b71Sopenharmony_ci   - Instantiating **MipiCsiCntlrMethod** in **MipiCsiCntlr**
189e41f4b71Sopenharmony_ci
190e41f4b71Sopenharmony_ci       >![](../public_sys-resources/icon-note.gif)
191e41f4b71Sopenharmony_ci       >
192e41f4b71Sopenharmony_ci       >Other members are initialized by **Init**.
193e41f4b71Sopenharmony_ci     
194e41f4b71Sopenharmony_ci       
195e41f4b71Sopenharmony_ci        ```c
196e41f4b71Sopenharmony_ci          static struct MipiCsiCntlrMethod g_method = {
197e41f4b71Sopenharmony_ci                .setComboDevAttr = Hi35xxSetComboDevAttr,
198e41f4b71Sopenharmony_ci                .setPhyCmvmode = Hi35xxSetPhyCmvmode,
199e41f4b71Sopenharmony_ci                .setExtDataType = Hi35xxSetExtDataType,
200e41f4b71Sopenharmony_ci                .setHsMode = Hi35xxSetHsMode,
201e41f4b71Sopenharmony_ci                .enableClock = Hi35xxEnableClock,
202e41f4b71Sopenharmony_ci                .disableClock = Hi35xxDisableClock,
203e41f4b71Sopenharmony_ci                .resetRx = Hi35xxResetRx,
204e41f4b71Sopenharmony_ci                .unresetRx = Hi35xxUnresetRx,
205e41f4b71Sopenharmony_ci                .enableSensorClock = Hi35xxEnableSensorClock,
206e41f4b71Sopenharmony_ci                .disableSensorClock = Hi35xxDisableSensorClock,
207e41f4b71Sopenharmony_ci                .resetSensor = Hi35xxResetSensor,
208e41f4b71Sopenharmony_ci                .unresetSensor = Hi35xxUnresetSensor
209e41f4b71Sopenharmony_ci            };
210e41f4b71Sopenharmony_ci        ```
211e41f4b71Sopenharmony_ci       
212e41f4b71Sopenharmony_ci   - **Init** function
213e41f4b71Sopenharmony_ci     
214e41f4b71Sopenharmony_ci     **Input parameter**:
215e41f4b71Sopenharmony_ci     
216e41f4b71Sopenharmony_ci     **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
217e41f4b71Sopenharmony_ci     
218e41f4b71Sopenharmony_ci      **Return value**:
219e41f4b71Sopenharmony_ci     
220e41f4b71Sopenharmony_ci      **HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
221e41f4b71Sopenharmony_ci     
222e41f4b71Sopenharmony_ci     | Status                 |        Description         |
223e41f4b71Sopenharmony_ci     | :--------------------- | :------------------------: |
224e41f4b71Sopenharmony_ci     | HDF_ERR_INVALID_OBJECT |      Invalid object.       |
225e41f4b71Sopenharmony_ci     | HDF_ERR_MALLOC_FAIL    | Failed to allocate memory. |
226e41f4b71Sopenharmony_ci     | HDF_ERR_INVALID_PARAM  |     Invalid parameter.     |
227e41f4b71Sopenharmony_ci     | HDF_ERR_IO             |         I/O error.         |
228e41f4b71Sopenharmony_ci     | HDF_SUCCESS            |   Operation successful.    |
229e41f4b71Sopenharmony_ci     | HDF_FAILURE            |     Operation failed.      |
230e41f4b71Sopenharmony_ci     
231e41f4b71Sopenharmony_ci     **Function description**:
232e41f4b71Sopenharmony_ci     
233e41f4b71Sopenharmony_ci     Attaches the **MipiCsiCntlrMethod** instance, calls **MipiCsiRegisterCntlr**, and initializes the custom structure.
234e41f4b71Sopenharmony_ci     
235e41f4b71Sopenharmony_ci     ```c
236e41f4b71Sopenharmony_ci     static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device)
237e41f4b71Sopenharmony_ci       {
238e41f4b71Sopenharmony_ci           int32_t ret;
239e41f4b71Sopenharmony_ci       
240e41f4b71Sopenharmony_ci           HDF_LOGI("%s: enter!", __func__);
241e41f4b71Sopenharmony_ci           g_mipiCsi.priv = NULL;       // g_mipiTx is a global variable defined.
242e41f4b71Sopenharmony_ci           							// static struct MipiCsiCntlr g_mipiCsi = {
243e41f4b71Sopenharmony_ci           							// .devNo = 0
244e41f4b71Sopenharmony_ci       								//};
245e41f4b71Sopenharmony_ci           g_mipiCsi.ops = &g_method;   // Attach the MipiCsiCntlrMethod instance.
246e41f4b71Sopenharmony_ci       #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
247e41f4b71Sopenharmony_ci           g_mipiCsi.debugs = &g_debugMethod;
248e41f4b71Sopenharmony_ci       #endif
249e41f4b71Sopenharmony_ci           ret = MipiCsiRegisterCntlr(&g_mipiCsi, device);    // (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer.
250e41f4b71Sopenharmony_ci           if (ret != HDF_SUCCESS) {
251e41f4b71Sopenharmony_ci               HDF_LOGE("%s: [MipiCsiRegisterCntlr] failed!", __func__);
252e41f4b71Sopenharmony_ci               return ret;
253e41f4b71Sopenharmony_ci           }
254e41f4b71Sopenharmony_ci       
255e41f4b71Sopenharmony_ci           ret = MipiRxDrvInit(); // (Mandatory) Device initialization customized by the vendor.
256e41f4b71Sopenharmony_ci           if (ret != HDF_SUCCESS) {
257e41f4b71Sopenharmony_ci               HDF_LOGE("%s: [MipiRxDrvInit] failed.", __func__);
258e41f4b71Sopenharmony_ci               return ret;
259e41f4b71Sopenharmony_ci           }
260e41f4b71Sopenharmony_ci       #ifdef MIPICSI_VFS_SUPPORT
261e41f4b71Sopenharmony_ci           ret = MipiCsiDevModuleInit(g_mipiCsi.devNo);
262e41f4b71Sopenharmony_ci           if (ret != HDF_SUCCESS) {
263e41f4b71Sopenharmony_ci               HDF_LOGE("%s: [MipiCsiDevModuleInit] failed!", __func__);
264e41f4b71Sopenharmony_ci               return ret;
265e41f4b71Sopenharmony_ci           }
266e41f4b71Sopenharmony_ci       #endif
267e41f4b71Sopenharmony_ci       
268e41f4b71Sopenharmony_ci           OsalSpinInit(&g_mipiCsi.ctxLock);
269e41f4b71Sopenharmony_ci           HDF_LOGI("%s: load mipi csi driver success!", __func__);
270e41f4b71Sopenharmony_ci       
271e41f4b71Sopenharmony_ci           return ret;
272e41f4b71Sopenharmony_ci       }
273e41f4b71Sopenharmony_ci       
274e41f4b71Sopenharmony_ci       // mipi_csi_core.c file
275e41f4b71Sopenharmony_ci       int32_t MipiCsiRegisterCntlr(struct MipiCsiCntlr *cntlr, struct HdfDeviceObject *device)
276e41f4b71Sopenharmony_ci       {
277e41f4b71Sopenharmony_ci       ...
278e41f4b71Sopenharmony_ci       // Global variable static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT];
279e41f4b71Sopenharmony_ci           if (g_mipiCsihandle[cntlr->devNo].cntlr == NULL) {
280e41f4b71Sopenharmony_ci               (void)OsalMutexInit(&g_mipiCsihandle[cntlr->devNo].lock);
281e41f4b71Sopenharmony_ci               (void)OsalMutexInit(&(cntlr->lock));
282e41f4b71Sopenharmony_ci       
283e41f4b71Sopenharmony_ci               g_mipiCsihandle[cntlr->devNo].cntlr = cntlr;    // Initialize MipiCsiHandle.
284e41f4b71Sopenharmony_ci               g_mipiCsihandle[cntlr->devNo].priv = NULL;
285e41f4b71Sopenharmony_ci               cntlr->device = device;			  // Prerequisites for conversion between HdfDeviceObject and MipiCsiHandle
286e41f4b71Sopenharmony_ci               device->service = &(cntlr->service);		  // Prerequisites for conversion between HdfDeviceObject and MipiCsiHandle.
287e41f4b71Sopenharmony_ci               cntlr->priv = NULL;
288e41f4b71Sopenharmony_ci               HDF_LOGI("%s: success.", __func__);
289e41f4b71Sopenharmony_ci       
290e41f4b71Sopenharmony_ci               return HDF_SUCCESS;
291e41f4b71Sopenharmony_ci           }
292e41f4b71Sopenharmony_ci       
293e41f4b71Sopenharmony_ci           HDF_LOGE("%s: cntlr already exists.", __func__);
294e41f4b71Sopenharmony_ci           return HDF_FAILURE;
295e41f4b71Sopenharmony_ci       }
296e41f4b71Sopenharmony_ci     ```
297e41f4b71Sopenharmony_ci     
298e41f4b71Sopenharmony_ci     
299e41f4b71Sopenharmony_ci300e41f4b71Sopenharmony_ci     
301e41f4b71Sopenharmony_ci   - **Release** function
302e41f4b71Sopenharmony_ci     
303e41f4b71Sopenharmony_ci     **Input parameter**:
304e41f4b71Sopenharmony_ci     
305e41f4b71Sopenharmony_ci     **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
306e41f4b71Sopenharmony_ci     
307e41f4b71Sopenharmony_ci     **Return value**:
308e41f4b71Sopenharmony_ci     
309e41f4b71Sopenharmony_ci      No value is returned.
310e41f4b71Sopenharmony_ci     
311e41f4b71Sopenharmony_ci     **Function description**:
312e41f4b71Sopenharmony_ci     
313e41f4b71Sopenharmony_ci     Releases the memory and deletes the controller. This function assigns values to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. 
314e41f4b71Sopenharmony_ci     
315e41f4b71Sopenharmony_ci     >![](../public_sys-resources/icon-note.gif) **NOTE**
316e41f4b71Sopenharmony_ci     >
317e41f4b71Sopenharmony_ci     >All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the value assignment operations.
318e41f4b71Sopenharmony_ci     
319e41f4b71Sopenharmony_ci     ```c
320e41f4b71Sopenharmony_ci      static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device)
321e41f4b71Sopenharmony_ci       {
322e41f4b71Sopenharmony_ci           struct MipiCsiCntlr *cntlr = NULL;
323e41f4b71Sopenharmony_ci       	...
324e41f4b71Sopenharmony_ci           cntlr = MipiCsiCntlrFromDevice(device);    // A forced conversion from HdfDeviceObject to MipiCsiCntlr is involved.
325e41f4b71Sopenharmony_ci                                                 	 // return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service;
326e41f4b71Sopenharmony_ci       	...
327e41f4b71Sopenharmony_ci       
328e41f4b71Sopenharmony_ci           OsalSpinDestroy(&cntlr->ctxLock);
329e41f4b71Sopenharmony_ci       #ifdef MIPICSI_VFS_SUPPORT
330e41f4b71Sopenharmony_ci           MipiCsiDevModuleExit(cntlr->devNo);
331e41f4b71Sopenharmony_ci       #endif
332e41f4b71Sopenharmony_ci           MipiRxDrvExit();				 // (Mandatory) Release the resources occupied by vendor devices.
333e41f4b71Sopenharmony_ci           MipiCsiUnregisterCntlr(&g_mipiCsi);        // Null function
334e41f4b71Sopenharmony_ci           g_mipiCsi.priv = NULL;
335e41f4b71Sopenharmony_ci       
336e41f4b71Sopenharmony_ci           HDF_LOGI("%s: unload mipi csi driver success!", __func__);
337e41f4b71Sopenharmony_ci       }
338e41f4b71Sopenharmony_ci     ```
339e41f4b71Sopenharmony_ci     
340e41f4b71Sopenharmony_ci     
341e41f4b71Sopenharmony_ci
342e41f4b71Sopenharmony_ci 
343e41f4b71Sopenharmony_ci
344e41f4b71Sopenharmony_ci