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 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 > **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 > **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 > 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_ci 300e41f4b71Sopenharmony_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 > **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