Defined by the Mobile Industry Processor Interface \(MIPI\) Alliance, the Camera Serial Interface \(CSI\) is a specification that 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 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.
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p155578927170128"><aname="p155578927170128"></a><aname="p155578927170128"></a><strongid="b2983104693117"><aname="b2983104693117"></a><aname="b2983104693117"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p534134719170128"><aname="p534134719170128"></a><aname="p534134719170128"></a><strongid="b717683263220"><aname="b717683263220"></a><aname="b717683263220"></a>pAttr</strong>: structure pointer to the configuration structure of the MIPI CSI.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry1104973652170128p0"><aname="entry1104973652170128p0"></a><aname="entry1104973652170128p0"></a>Sets the MIPI-CSI configuration.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p548503413170128"><aname="p548503413170128"></a><aname="p548503413170128"></a><strongid="b33316314348"><aname="b33316314348"></a><aname="b33316314348"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p1389106408170128"><aname="p1389106408170128"></a><aname="p1389106408170128"></a><strongid="b7288183093611"><aname="b7288183093611"></a><aname="b7288183093611"></a>devno</strong>: Device ID, which is of the uint8_t type.</p>
<pid="p118314402170128"><aname="p118314402170128"></a><aname="p118314402170128"></a><strongid="b1347113393714"><aname="b1347113393714"></a><aname="b1347113393714"></a>cmvMode</strong>: common-mode voltage (CMV) mode.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry1506663070170128p0"><aname="entry1506663070170128p0"></a><aname="entry1506663070170128p0"></a>Sets the CMV mode.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p114389566170128"><aname="p114389566170128"></a><aname="p114389566170128"></a><strongid="b34053117344"><aname="b34053117344"></a><aname="b34053117344"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p996608377170128"><aname="p996608377170128"></a><aname="p996608377170128"></a><strongid="b784685684412"><aname="b784685684412"></a><aname="b784685684412"></a>dataType</strong>: structure pointer to the data that defines the YUV, original data formats, and bit depth.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry1309676064170128p0"><aname="entry1309676064170128p0"></a><aname="entry1309676064170128p0"></a>Sets the YUV, RAW data format, and bit depth.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p1054266120170128"><aname="p1054266120170128"></a><aname="p1054266120170128"></a><strongid="b144183117349"><aname="b144183117349"></a><aname="b144183117349"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p1574674418170128"><aname="p1574674418170128"></a><aname="p1574674418170128"></a><strongid="b18748194155516"><aname="b18748194155516"></a><aname="b18748194155516"></a>laneDivideMode</strong>: lane mode.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry1643965522170128p0"><aname="entry1643965522170128p0"></a><aname="entry1643965522170128p0"></a>Sets the MIPI RX lane distribution.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p867235167170128"><aname="p867235167170128"></a><aname="p867235167170128"></a><strongid="b94263116342"><aname="b94263116342"></a><aname="b94263116342"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p1770663973170128"><aname="p1770663973170128"></a><aname="p1770663973170128"></a><strongid="b1342116531004"><aname="b1342116531004"></a><aname="b1342116531004"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry373275246170128p0"><aname="entry373275246170128p0"></a><aname="entry373275246170128p0"></a>Enables the MIPI clock.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p252627163170128"><aname="p252627163170128"></a><aname="p252627163170128"></a><strongid="b343103114343"><aname="b343103114343"></a><aname="b343103114343"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p573650189170128"><aname="p573650189170128"></a><aname="p573650189170128"></a><strongid="b1747970172618"><aname="b1747970172618"></a><aname="b1747970172618"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry693552037170128p0"><aname="entry693552037170128p0"></a><aname="entry693552037170128p0"></a>Disables the MIPI clock.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p1214231503170128"><aname="p1214231503170128"></a><aname="p1214231503170128"></a><strongid="b1043031153417"><aname="b1043031153417"></a><aname="b1043031153417"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p104793304170128"><aname="p104793304170128"></a><aname="p104793304170128"></a><strongid="b597920533269"><aname="b597920533269"></a><aname="b597920533269"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry1692819512170128p0"><aname="entry1692819512170128p0"></a><aname="entry1692819512170128p0"></a>Resets the MIPI RX.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p1883220887170128"><aname="p1883220887170128"></a><aname="p1883220887170128"></a><strongid="b1202156153016"><aname="b1202156153016"></a><aname="b1202156153016"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p114324757170128"><aname="p114324757170128"></a><aname="p114324757170128"></a><strongid="b105520153110"><aname="b105520153110"></a><aname="b105520153110"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry1714667992170128p0"><aname="entry1714667992170128p0"></a><aname="entry1714667992170128p0"></a>Deasserts the reset of the MIPI RX.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p217879421170128"><aname="p217879421170128"></a><aname="p217879421170128"></a><strongid="b197181237203211"><aname="b197181237203211"></a><aname="b197181237203211"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p2098908158170128"><aname="p2098908158170128"></a><aname="p2098908158170128"></a><strongid="b12861154993218"><aname="b12861154993218"></a><aname="b12861154993218"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p1996780281170128"><aname="p1996780281170128"></a><aname="p1996780281170128"></a><strongid="b4445316347"><aname="b4445316347"></a><aname="b4445316347"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p2021170726170128"><aname="p2021170726170128"></a><aname="p2021170726170128"></a><strongid="b17971423820"><aname="b17971423820"></a><aname="b17971423820"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p1065048089170128"><aname="p1065048089170128"></a><aname="p1065048089170128"></a><strongid="b19451631183417"><aname="b19451631183417"></a><aname="b19451631183417"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p998202090170128"><aname="p998202090170128"></a><aname="p998202090170128"></a><strongid="b10443111911384"><aname="b10443111911384"></a><aname="b10443111911384"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry944835652170128p0"><aname="entry944835652170128p0"></a><aname="entry944835652170128p0"></a>Resets the sensor.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p416483731170128"><aname="p416483731170128"></a><aname="p416483731170128"></a><strongid="b178488417385"><aname="b178488417385"></a><aname="b178488417385"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<pid="p1988272362170128"><aname="p1988272362170128"></a><aname="p1988272362170128"></a><strongid="b6353246183818"><aname="b6353246183818"></a><aname="b6353246183818"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="entry791107803170128p0"><aname="entry791107803170128p0"></a><aname="entry791107803170128p0"></a>Deasserts the reset of a sensor.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section378858277170128"></a>
The MIPI CSI module adaptation involves the following steps:
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
-\(Optional\) Add the **mipicsi\_config.hcs** file.
3. Instantiate the MIPI CSI controller object.
- Initialize **MipiCsiCntlr**.
- Instantiate **MipiCsiCntlrMethod** in the **MipiCsiCntlr** object.
>For details, see [Available APIs](#section735525713405).
4. Debug the driver.
-\(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted.
## Development Example<a name="section2049027816170128"></a>
The following uses **mipi\_rx\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions.
1. Generally, you need to 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.
>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.
**device\_info.hcs** configuration reference:
```
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 the moduleName in the driver entry.
serviceName = "HDF_MIPI_RX";// (Mandatory) Unique name of the service published by the driver.
}
}
}
}
}
```
2. Instantiate the driver entry. 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 of 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.
MIPI CSI driver entry reference:
```
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.
```
3. Initialize the **MipiCsiCntlr** object at the core layer, including initializing the vendor custom structure \(passing parameters and data\), instantiating **MipiCsiCntlrMethod**\(used to call underlying functions of the driver\) in **MipiCsiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
>To the driver, the custom structure carries 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**.
```
typedef struct {
/** Data type: 8-bit, 10-bit, 12-bit, 14-bit, 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 input image of the sensor). */
ImgRect imgRect;
union {
MipiDevAttr mipiAttr;
LvdsDevAttr lvdsAttr;
};
} ComboDevAttr;
// MipiCsiCntlr is the core layer controller structure. Its members are assigned with values by using the Init function.
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 anonymous data, which is used to store the CSI device structure */
void *priv;
};
```
- **\(Important\)** Instantiate the callback function structure **MipiCsiCntlrMethod** in **MipiCsiCntlr**. Other members are initialized by using the **Init** function.
```
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 parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **/drivers/framework/include/utils/hdf\_base.h** file.\)
g_mipiCsi.priv = NULL; // g_mipiTx is a global variable defined.
//static struct MipiCsiCntlr g_mipiCsi = {
//.devNo = 0
//};
g_mipiCsi.ops = &g_method; // Connect to 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.
cntlr->device = device; // Enable conversion between HdfDeviceObject and MipiCsiHandle.
device->service = &(cntlr->service); // Enable 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 parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
–
Function description:
Releases the memory and deletes the controller. This function assigns a value 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. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations.