# MIPI-DSI
## Overview
The Display Serial Interface \(DSI\) is a specification developed by the Mobile Industry Processor Interface \(MIPI\) Alliance to reduce the cost of display controllers in mobile devices. In the Hardware Driver Foundation (HDF) framework, the MIPI-DSI 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 system 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.
**Figure 1** Service-free mode
![](figures/service-free-mode-9.png "service-free-mode-9")
## How to Develop
The MIPI-DSI 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **mipidsi\_config.hcs** file.
3. Instantiate the MIPI-DSI controller object.
- Initialize **MipiDsiCntlr**.
- Instantiate **MipiDsiCntlrMethod** in the **MipiDsiCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [MipiDsiCntlrMethod](#section10711202141617) and [Table 1](#table218771071713).
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.
### MipiDsiCntlrMethod
```
struct MipiDsiCntlrMethod {// Member functions of the core layer structure
int32_t (*setCntlrCfg)(struct MipiDsiCntlr *cntlr);
int32_t (*setCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd);
int32_t (*getCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out);
void (*toHs)(struct MipiDsiCntlr *cntlr);
void (*toLp)(struct MipiDsiCntlr *cntlr);
void (*enterUlps)(struct MipiDsiCntlr *cntlr);//(Optional) Enter the ultra-low power consumption mode.
void (*exitUlps)(struct MipiDsiCntlr *cntlr); // (Optional) Exit the ultra-low power consumption mode.
int32_t (*powerControl)(struct MipiDsiCntlr *cntlr, uint8_t enable);// (Optional) Enable or disable power control.
int32_t (*attach)(struct MipiDsiCntlr *cntlr);// (Optional) Connect a DSI device to the host.
};
```
**Table 1** Callbacks for the members in the MipiDsiCntlrMethod structure
Callback
|
Input Parameter
|
Output Parameter
|
Return Value
|
Description
|
setCntlrCfg
|
cntlr: structure pointer to the MIPI-DSI controller.
|
–
|
HDF_STATUS
|
Sets controller parameters.
|
setCmd
|
cntlr: structure pointer to the MIPI-DSI controller.
cmd: structure pointer to the input instruction.
|
–
|
HDF_STATUS
|
Sends instructions to a display device.
|
getCmd
|
cntlr: structure pointer to the MIPI-DSI controller.
|
cmd: structure pointer to the instruction to output.
|
HDF_STATUS
|
Reads instructions from the display device.
|
toHs
|
cntlr: structure pointer to the MIPI-DSI controller.
|
–
|
HDF_STATUS
|
Sets the high-speed mode.
|
toLp
|
cntlr: structure pointer to the MIPI-DSI controller.
|
–
|
HDF_STATUS
|
Sets the low-power mode.
|
## Development Example
The following uses **mipi\_tx\_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 **xx\_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 **MipiDsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration.
In this example, no additional attribute needs to be configured for the MIPI-DSI controller. If required, you need to add the **deviceMatchAttr** information to **deviceNode** in the **device\_info** file and add the **mipidsi\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_mipi_dsi:: device {
device0 :: deviceNode {
policy = 0;
priority = 150;
permission = 0644;
moduleName = "HDF_MIPI_TX"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
serviceName = "HDF_MIPI_TX";// (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 framework, 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, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits.
- MIPI-DSI driver entry reference
```
struct HdfDriverEntry g_mipiTxDriverEntry = {
.moduleVersion = 1,
.Init = Hi35xxMipiTxInit, // See the Init function.
.Release = Hi35xxMipiTxRelease, //See the Release function.
.moduleName = "HDF_MIPI_TX", // (Mandatory) The value must be the same as that in the device_info.hcs file.
};
HDF_INIT(g_mipiTxDriverEntry); // Call HDF_INIT to register the driver entry with the HDF framework.
```
3. Initialize the **MipiDsiCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **MipiDsiCntlrMethod** \(used to call underlying functions of the driver\) in **MipiDsiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
- Custom structure reference
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-DSI has no device attribute file. Therefore, the basic member structure is similar to that of **MipiDsiCntlr**.
```
typedef struct {
unsigned int devno; // Device number
short laneId[LANE_MAX_NUM]; // Lane ID
OutPutModeTag outputMode; // Output mode, which can be CSI mode, DSI Video mode, or DSI Command mode.
VideoModeTag videoMode; // Synchronization mode of the display device
OutputFormatTag outputFormat; // Format of the output DSI image, which can be RGB or YUV.
SyncInfoTag syncInfo; // Settings related to timing
unsigned int phyDataRate; // mbps
unsigned int pixelClk; // KHz
} ComboDevCfgTag;
// MipiDsiCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct MipiDsiCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
unsigned int devNo; // Device number
struct MipiCfg cfg;
struct MipiDsiCntlrMethod *ops;
struct OsalMutex lock;
void *priv;
};
```
- Instantiate the callback function structure **MipiDsiCntlrMethod** in **MipiDsiCntlr**. Other members are initialized by using the Init function.
```
static struct MipiDsiCntlrMethod g_method = {
.setCntlrCfg = Hi35xxSetCntlrCfg,
.setCmd = Hi35xxSetCmd,
.getCmd = Hi35xxGetCmd,
.toHs = Hi35xxToHs,
.toLp = Hi35xxToLp,
};
```
- 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.\)
Status (Value)
|
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:
Connects to the **MipiDsiCntlrMethod** instance, calls **MipiDsiRegisterCntlr**, and performs other vendor-defined initialization operations.
```
static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device)
{
int32_t ret;
g_mipiTx.priv = NULL; // g_mipiTx is a global variable.
//static struct MipiDsiCntlr g_mipiTx {
// .devNo=0
//};
g_mipiTx.ops = &g_method;// Connect to the MipiDsiCntlrMethod instance.
ret = MipiDsiRegisterCntlr(&g_mipiTx, device);// (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer.
...
return MipiTxDrvInit(0); // (Mandatory) Device initialization customized by the vendor.
}
// mipi_dsi_core.c, core layer file.
int32_t MipiDsiRegisterCntlr(struct MipiDsiCntlr *cntlr, struct HdfDeviceObject *device)
{
...
// Define the global variable static struct MipiDsiHandle g_mipiDsihandle[MAX_CNTLR_CNT].
if (g_mipiDsihandle[cntlr->devNo].cntlr == NULL) {
(void)OsalMutexInit(&g_mipiDsihandle[cntlr->devNo].lock);
(void)OsalMutexInit(&(cntlr->lock));
g_mipiDsihandle[cntlr->devNo].cntlr = cntlr;// Initialize MipiDsiHandle.
g_mipiDsihandle[cntlr->devNo].priv = NULL;
cntlr->device = device; // Enable conversion between HdfDeviceObject and MipiDsiHandle.
device->service = &(cntlr->service); // Enable conversion between HdfDeviceObject and MipiDsiHandle.
cntlr->priv = NULL;
...
return HDF_SUCCESS;
}
...
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 framework 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.
```
static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device)
{
struct MipiDsiCntlr *cntlr = NULL;
...
cntlr = MipiDsiCntlrFromDevice(device);// A forced conversion from HdfDeviceObject to MipiDsiCntlr is involved.
//return (device == NULL) ? NULL : (struct MipiDsiCntlr *)device->service;
...
MipiTxDrvExit(); // (Mandatory) Release the resources occupied by the vendor's devices.
MipiDsiUnregisterCntlr(&g_mipiTx); // Empty function
g_mipiTx.priv = NULL;
HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__);
}
```