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