driver-platform-mipicsi-develop.md 17.0 KB
Newer Older
A
Annie_wang 已提交
1
# MIPI CSI
D
duangavin123 已提交
2

A
Annie_wang 已提交
3
## Overview
D
duangavin123 已提交
4

A
Annie_wang 已提交
5
The 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.
D
duangavin123 已提交
6

A
Annie_wang 已提交
7
**Figure 1** Service-free mode
D
duangavin123 已提交
8

A
Annie_wang 已提交
9
![image1](figures/service-free-mode.png "service-free-mode")
D
duangavin123 已提交
10

A
Annie_wang 已提交
11
## Available APIs
D
duangavin123 已提交
12

A
Annie_wang 已提交
13
**MipiCsiCntlrMethod**:
D
duangavin123 已提交
14

A
Annie_wang 已提交
15
```c
D
duangavin123 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
struct MipiCsiCntlrMethod {
    int32_t (*setComboDevAttr)(struct MipiCsiCntlr *cntlr, ComboDevAttr *pAttr);
    int32_t (*setPhyCmvmode)(struct MipiCsiCntlr *cntlr, uint8_t devno, PhyCmvMode cmvMode);
    int32_t (*setExtDataType)(struct MipiCsiCntlr *cntlr, ExtDataType* dataType);
    int32_t (*setHsMode)(struct MipiCsiCntlr *cntlr, LaneDivideMode laneDivideMode);
    int32_t (*enableClock)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
    int32_t (*disableClock)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
    int32_t (*resetRx)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
    int32_t (*unresetRx)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
    int32_t (*enableSensorClock)(struct MipiCsiCntlr *cntlr, uint8_t snsClkSource);
    int32_t (*disableSensorClock)(struct MipiCsiCntlr *cntlr, uint8_t snsClkSource);
    int32_t (*resetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource);
    int32_t (*unresetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource);
};
```
A
Annie_wang 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44
**Table 1** Description of the callback functions in the MipiCsiCntlrMethod structure
| Function          | Input Parameter                                                        | Output Parameter| Return Value          | Description                      |
| ------------------ | ------------------------------------------------------------ | ---- | ------------------ | -------------------------- |
| setComboDevAttr    | **cntlr**: structure pointer to the MIPI CSI controller.<br>**pAttr**: structure pointer to the MIPI CSI configuration.| –  | HDF_STATUS| Sets MIPI CSI attributes.          |
| 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.          |
| 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.|
| setHsMode          | **cntlr**: structure pointer to the MIPI CSI controller.<br>**laneDivideMode**: lane mode.| –  | HDF_STATUS| Sets the MIPI RX lane distribution.    |
| 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.            |
| 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.            |
| 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.               |
| 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.           |
| 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.    |
| 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.    |
| 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.                |
A
Annie_wang 已提交
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.     |
A
Annie_wang 已提交
46 47

## How to Develop
D
duangavin123 已提交
48 49 50

The MIPI CSI module adaptation involves the following steps:

A
Annie_wang 已提交
51
1. Configure attribute files.     
A
Annie_wang 已提交
52 53 54 55

   - Add the **deviceNode** information to the **device_info.hcs** file.
   - (Optional) Add the **mipicsi_config.hcs** file.

A
Annie_wang 已提交
56 57 58 59 60
2. Instantiate the driver entry. 
   
   - Instantiate the **HdfDriverEntry** structure.
   - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
   
A
Annie_wang 已提交
61
3. Instantiate the MIPI CSI controller object.  
A
Annie_wang 已提交
62
   
A
Annie_wang 已提交
63 64
   - Initialize **MipiCsiCntlr**.
   - Instantiate **MipiCsiCntlrMethod** in the **MipiCsiCntlr** object.
A
Annie_wang 已提交
65
     >![](../public_sys-resources/icon-note.gif) **NOTE**<br>
A
Annie_wang 已提交
66 67 68 69
     >For details about the functions in **MipiCsiCntlrMethod**, see [Available APIs](#available-apis).
   
4. Debug the driver.

A
Annie_wang 已提交
70
   (Optional) For new drivers, verify the basic functions, for example, the data transmission and the information returned after the **MipiCsiCntlrMethod** instance is attached.
A
Annie_wang 已提交
71

A
Annie_wang 已提交
72
   
A
Annie_wang 已提交
73 74 75 76 77 78 79 80 81
## Development Example

The following uses **mipi_rx_hi35xx.c** as an example to present the information required for implementing device functions.


1. Configure the device attributes in **busxx_config.hcs** and add the **deviceNode** information to the **device_info.hcs** file. 

   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.
   
A
Annie_wang 已提交
82 83
    >![](../public_sys-resources/icon-note.gif) **NOTE**<br>
    >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.
A
Annie_wang 已提交
84
   
A
Annie_wang 已提交
85
   - **device_info.hcs** configuration example
A
Annie_wang 已提交
86
   
A
Annie_wang 已提交
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
     ```c
     root {
     device_info {
         match_attr = "hdf_manager";
         platform :: host {
         hostName = "platform_host";
         priority = 50;
         device_mipi_csi:: device {
         	device0 :: deviceNode {
                 policy = 0;
                 priority = 160;
                 permission = 0644;
                 moduleName = "HDF_MIPI_RX";    // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
                 serviceName = "HDF_MIPI_RX";   // (Mandatory) Unique name of the service published by the driver.
             }
         }
         }
     }
     }
     ```
     
A
Annie_wang 已提交
108
   
A
Annie_wang 已提交
109
2. Instantiate the driver entry.
A
Annie_wang 已提交
110

A
Annie_wang 已提交
111 112 113
   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.
   
   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.
A
Annie_wang 已提交
114
   
A
Annie_wang 已提交
115
   - MIPI CSI driver entry example
A
Annie_wang 已提交
116
   
A
Annie_wang 已提交
117 118 119 120 121 122 123 124 125
     ```c
     struct HdfDriverEntry g_mipiCsiDriverEntry = {
         .moduleVersion = 1,
         .Init = Hi35xxMipiCsiInit,          // See the Init function.
         .Release = Hi35xxMipiCsiRelease,    // See the Release function.
         .moduleName = "HDF_MIPI_RX",        // (Mandatory) The value must be the same as that in the device_info.hcs file.
     };
     HDF_INIT(g_mipiCsiDriverEntry);         // Call HDF_INIT to register the driver entry with the HDF.
     ```
A
Annie_wang 已提交
126
   
A
Annie_wang 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
     

3. 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).

   - Defining a custom structure

     To the driver, the custom structure hols 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**.

     ```c
     typedef struct {
         /** The data type can be 8-, 10-, 12-, 14-, or 16-bit. */
         DataType inputDataType;
         /** MIPI WDM mode */
         MipiWdrMode wdrMode;
         /** laneId: -1 - disabled */
         short laneId[MIPI_LANE_NUM];
     
         union {
             /** Used for HI_MIPI_WDR_MODE_DT */
             short dataType[WDR_VC_NUM];
         };
     } MipiDevAttr;
     
     typedef struct {
         /** Device number */
         uint8_t devno;
         /** Input mode, which can be MIPI, LVDS, sub-LVDS, HiSPi, or DC. */
         InputMode inputMode;
         MipiDataRate dataRate;
         /** Crop area of the MIPI RX device (same as the size of the sensor input image) */
         ImgRect imgRect;
     
         union {
             MipiDevAttr mipiAttr;
             LvdsDevAttr lvdsAttr;
         };
     } ComboDevAttr;
     
     // MipiCsiCntlr is the core layer controller structure. The Init function assigns values to the members of MipiCsiCntlr.
     struct MipiCsiCntlr {
         /** Send the service provided by this controller when the driver is bound to the HDF. */
         struct IDeviceIoService service;
         /** Pass the pointer to the device when the driver is bound to the HDF. */
         struct HdfDeviceObject *device;
         /** Device number */
         unsigned int devNo;
         /** All APIs provided by the controller */
         struct MipiCsiCntlrMethod *ops;
         /** All APIs for controller debugging. Set it to null if the driver is not implemented. */
         struct MipiCsiCntlrDebugMethod *debugs;
         /** Controller context variable. */
         MipiDevCtx ctx;
         /** Spinlock used when the controller context variable is accessed. */
         OsalSpinlock ctxLock;
         /** Lock method when the controller is managed */
         struct OsalMutex lock;
         /** Pointer to the anonymous structure that holds the CSI device data */
         void *priv;
     };
     ```

   - Instantiating **MipiCsiCntlrMethod** in **MipiCsiCntlr**

       >![](../public_sys-resources/icon-note.gif)
       >
       >Other members are initialized by **Init**.
     
       
        ```c
          static struct MipiCsiCntlrMethod g_method = {
                .setComboDevAttr = Hi35xxSetComboDevAttr,
                .setPhyCmvmode = Hi35xxSetPhyCmvmode,
                .setExtDataType = Hi35xxSetExtDataType,
                .setHsMode = Hi35xxSetHsMode,
                .enableClock = Hi35xxEnableClock,
                .disableClock = Hi35xxDisableClock,
                .resetRx = Hi35xxResetRx,
                .unresetRx = Hi35xxUnresetRx,
                .enableSensorClock = Hi35xxEnableSensorClock,
                .disableSensorClock = Hi35xxDisableSensorClock,
                .resetSensor = Hi35xxResetSensor,
                .unresetSensor = Hi35xxUnresetSensor
            };
        ```
       
   - **Init** function
     
     **Input parameter**:
     
     **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
     
      **Return value**:
     
      **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.
     
     | Status                 |        Description         |
     | :--------------------- | :------------------------: |
     | HDF_ERR_INVALID_OBJECT |      Invalid object.       |
     | HDF_ERR_MALLOC_FAIL    | Failed to allocate memory. |
     | HDF_ERR_INVALID_PARAM  |     Invalid parameter.     |
     | HDF_ERR_IO             |         I/O error.         |
     | HDF_SUCCESS            |   Operation successful.    |
     | HDF_FAILURE            |     Operation failed.      |
     
     **Function description**:
     
     Attaches the **MipiCsiCntlrMethod** instance, calls **MipiCsiRegisterCntlr**, and initializes the custom structure.
     
     ```c
     static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device)
       {
           int32_t ret;
       
           HDF_LOGI("%s: enter!", __func__);
           g_mipiCsi.priv = NULL;       // g_mipiTx is a global variable defined.
           							// static struct MipiCsiCntlr g_mipiCsi = {
           							// .devNo = 0
       								//};
           g_mipiCsi.ops = &g_method;   // Attach the MipiCsiCntlrMethod instance.
       #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
           g_mipiCsi.debugs = &g_debugMethod;
       #endif
           ret = MipiCsiRegisterCntlr(&g_mipiCsi, device);    // (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer.
           if (ret != HDF_SUCCESS) {
               HDF_LOGE("%s: [MipiCsiRegisterCntlr] failed!", __func__);
               return ret;
           }
       
           ret = MipiRxDrvInit(); // (Mandatory) Device initialization customized by the vendor.
           if (ret != HDF_SUCCESS) {
               HDF_LOGE("%s: [MipiRxDrvInit] failed.", __func__);
               return ret;
           }
       #ifdef MIPICSI_VFS_SUPPORT
           ret = MipiCsiDevModuleInit(g_mipiCsi.devNo);
           if (ret != HDF_SUCCESS) {
               HDF_LOGE("%s: [MipiCsiDevModuleInit] failed!", __func__);
               return ret;
           }
       #endif
       
           OsalSpinInit(&g_mipiCsi.ctxLock);
           HDF_LOGI("%s: load mipi csi driver success!", __func__);
       
           return ret;
       }
       
       // mipi_csi_core.c file
       int32_t MipiCsiRegisterCntlr(struct MipiCsiCntlr *cntlr, struct HdfDeviceObject *device)
       {
       ...
       // Global variable static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT];
           if (g_mipiCsihandle[cntlr->devNo].cntlr == NULL) {
               (void)OsalMutexInit(&g_mipiCsihandle[cntlr->devNo].lock);
               (void)OsalMutexInit(&(cntlr->lock));
       
               g_mipiCsihandle[cntlr->devNo].cntlr = cntlr;    // Initialize MipiCsiHandle.
               g_mipiCsihandle[cntlr->devNo].priv = NULL;
               cntlr->device = device;			  // Prerequisites for conversion between HdfDeviceObject and MipiCsiHandle
               device->service = &(cntlr->service);		  // Prerequisites for conversion between HdfDeviceObject and MipiCsiHandle.
               cntlr->priv = NULL;
               HDF_LOGI("%s: success.", __func__);
       
               return HDF_SUCCESS;
           }
       
           HDF_LOGE("%s: cntlr already exists.", __func__);
           return HDF_FAILURE;
       }
     ```
     
     

     
   - **Release** function
     
     **Input parameter**:
     
     **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
     
     **Return value**:
     
      No value is returned.
     
     **Function description**:
     
     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. 
     
     >![](../public_sys-resources/icon-note.gif) **NOTE**
     >
     >All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the value assignment operations.
     
     ```c
      static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device)
       {
           struct MipiCsiCntlr *cntlr = NULL;
       	...
           cntlr = MipiCsiCntlrFromDevice(device);    // A forced conversion from HdfDeviceObject to MipiCsiCntlr is involved.
                                                 	 // return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service;
       	...
       
           OsalSpinDestroy(&cntlr->ctxLock);
       #ifdef MIPICSI_VFS_SUPPORT
           MipiCsiDevModuleExit(cntlr->devNo);
       #endif
           MipiRxDrvExit();				 // (Mandatory) Release the resources occupied by vendor devices.
           MipiCsiUnregisterCntlr(&g_mipiCsi);        // Null function
           g_mipiCsi.priv = NULL;
       
           HDF_LOGI("%s: unload mipi csi driver success!", __func__);
       }
     ```