1# MIPI DSI 2 3 4## Overview 5 6The 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), 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 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. 7 8 **Figure 1** Service-free mode 9 10 ![](figures/service-free-mode.png "service-free-mode") 11 12 13## Available APIs 14 15**MipiDsiCntlrMethod**: 16 17 18``` 19struct MipiDsiCntlrMethod { // Member functions of the core layer structure 20 int32_t (*setCntlrCfg)(struct MipiDsiCntlr *cntlr); 21 int32_t (*setCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd); 22 int32_t (*getCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out); 23 void (*toHs)(struct MipiDsiCntlr *cntlr); 24 void (*toLp)(struct MipiDsiCntlr *cntlr); 25 void (*enterUlps)(struct MipiDsiCntlr *cntlr); // (Optional) Enter the Ultra-Low Power State (ULPS). 26 void (*exitUlps)(struct MipiDsiCntlr *cntlr); // (Optional) Exit the ULPS. 27 int32_t (*powerControl)(struct MipiDsiCntlr *cntlr, uint8_t enable);// (Optional) Enable or disable power control. 28 int32_t (*attach)(struct MipiDsiCntlr *cntlr); // (Optional) Attach a DSI device to the host. 29}; 30``` 31 32 **Table 1** Description of the callback functions in MipiDsiCntlrMethod 33 34| Function| Input Parameter| Output Parameter| Return Value| Description| 35| -------- | -------- | -------- | -------- | -------- | 36| setCntlrCfg | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets controller parameters.| 37| setCmd | **cntlr**: structure pointer to the MIPI DSI controller.<br>**cmd**: structure pointer to the commands to send. | –| HDF_STATUS| Sends commands to a display device.| 38| getCmd | **cntlr**: structure pointer to the MIPI DSI controller.<br>**cmd**: pointer to the command description structure.<br>**readLen**: length of the data to read.| **out**: structure pointer to the data obtained.| HDF_STATUS| Reads data by sending commands.| 39| toHs | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets the high speed (HS) mode.| 40| toLp | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets the low power (LP) mode.| 41 42 43## How to Develop 44 45The MIPI DSI module adaptation involves the following steps: 46 471. Configure attribute files. 48 - Add the **deviceNode** description to the **device_info.hcs** file. 49 - (Optional) Add the **mipidsi_config.hcs** file. 50 512. Instantiate the driver entry. 52 - Instantiate the **HdfDriverEntry** structure. 53 - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF. 54 553. Instantiate the MIPI DSI controller object. 56 - Initialize **MipiDsiCntlr**. 57 - Instantiate **MipiDsiCntlrMethod** in the **MipiDsiCntlr** object. 58 > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/> 59 > For details about the functions in **MipiDsiCntlrMethod**, see [Available APIs](#available-apis). 60 614. Debug the driver. 62 63 (Optional) For new drivers, verify basic functions, for example, check the information returned after the driver is attached and whether data is successfully transmitted. 64 65 66## Development Example 67 68The 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. 69 701. Configure the device attributes in **xx_config.hcs** and add the **deviceNode** information to the **device_info.hcs** file. 71 72 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. 73 74 In this example, no additional attribute needs to be configured for the MIPI DSI controller. If required, add the **deviceMatchAttr** information to **deviceNode** in the **device_info** file and add the **mipidsi_config** file. 75 76 **device_info.hcs** configuration example: 77 78 ``` 79 root { 80 device_info { 81 match_attr = "hdf_manager"; 82 platform :: host { 83 hostName = "platform_host"; 84 priority = 50; 85 device_mipi_dsi:: device { 86 device0 :: deviceNode { 87 policy = 0; 88 priority = 150; 89 permission = 0644; 90 moduleName = "HDF_MIPI_TX"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry. 91 serviceName = "HDF_MIPI_TX"; // (Mandatory) Unique name of the service published by the driver. 92 } 93 } 94 } 95 } 96 } 97 ``` 98 992. Instantiate the driver entry. 100 101 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. 102 103 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. 104 105 MIPI DSI driver entry example: 106 107 ``` 108 struct HdfDriverEntry g_mipiTxDriverEntry = { 109 .moduleVersion = 1, 110 .Init = Hi35xxMipiTxInit, // See the Init function. 111 .Release = Hi35xxMipiTxRelease, // See the Release function. 112 .moduleName = "HDF_MIPI_TX", // (Mandatory) The value must be the same as that in the device_info.hcs file. 113 }; 114 HDF_INIT(g_mipiTxDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. 115 ``` 116 1173. Initialize the **MipiDsiCntlr** 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 **MipiDsiCntlrMethod** in **MipiDsiCntlr** (so that the underlying driver functions can be called). 118 119 - Defining a custom structure 120 121 To the driver, the custom structure holds parameters and data. Generally, the values in the **config** file are used to initialize the structure members. However, in this example, the MIPI DSI has no device attribute file. Therefore, the basic member structure is similar to that of **MipiDsiCntlr**. 122 123 ``` 124 typedef struct { 125 unsigned int devno; // Device number 126 short laneId[LANE_MAX_NUM]; // Lane ID 127 OutPutModeTag outputMode; // Output mode, which can be CSI mode, DSI Video mode, or DSI Command mode. 128 VideoModeTag videoMode; // Synchronization mode of the display device 129 OutputFormatTag outputFormat; // Format of the output DSI image, which can be RGB or YUV. 130 SyncInfoTag syncInfo; // Settings related to timing 131 unsigned int phyDataRate; // Data rate, in Mbit/s 132 unsigned int pixelClk; // Clock, in kHz 133 } ComboDevCfgTag; 134 135 // MipiDsiCntlr is the controller structure at the core layer. The Init function assigns values to the members of MipiDsiCntlr. 136 struct MipiDsiCntlr { 137 struct IDeviceIoService service; 138 struct HdfDeviceObject *device; 139 unsigned int devNo; // Device number 140 struct MipiCfg cfg; 141 struct MipiDsiCntlrMethod *ops; 142 struct OsalMutex lock; 143 void *priv; 144 }; 145 ``` 146 147 - Instantiating **MipiDsiCntlrMethod** in **MipiDsiCntlr** (other members are initialized by **Init**) 148 149 ``` 150 static struct MipiDsiCntlrMethod g_method = { 151 .setCntlrCfg = Hi35xxSetCntlrCfg, 152 .setCmd = Hi35xxSetCmd, 153 .getCmd = Hi35xxGetCmd, 154 .toHs = Hi35xxToHs, 155 .toLp = Hi35xxToLp, 156 }; 157 ``` 158 159 - **Init** function 160 161 **Input parameter**: 162 163 **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information. 164 165 **Return value**: 166 167 **HDF_STATUS** 168 169 The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file. 170 171 | Status | Description | 172 | ---------------------- | -------------------------- | 173 | HDF_ERR_INVALID_OBJECT | Invalid object. | 174 | HDF_ERR_MALLOC_FAIL | Failed to allocate memory. | 175 | HDF_ERR_INVALID_PARAM | Invalid parameter. | 176 | HDF_ERR_IO | I/O error. | 177 | HDF_SUCCESS | Operation successful. | 178 | HDF_FAILURE | Operation failed. | 179 180 **Function description**: 181 182 Attaches the **MipiDsiCntlrMethod** instance, calls **MipiDsiRegisterCntlr**, and performs other vendor-defined initialization operations. 183 184 ``` 185 static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device) 186 { 187 int32_t ret; 188 g_mipiTx.priv = NULL; // g_mipiTx is a global variable defined. 189 // static struct MipiDsiCntlr g_mipiTx { 190 // .devNo=0 191 //}; 192 g_mipiTx.ops = &g_method; // Attach the MipiDsiCntlrMethod instance. 193 ret = MipiDsiRegisterCntlr(&g_mipiTx, device);// (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer. 194 ... 195 return MipiTxDrvInit(0); // (Mandatory) Device initialization customized by the vendor. 196 } 197 198 // mipi_dsi_core.c file 199 int32_t MipiDsiRegisterCntlr(struct MipiDsiCntlr *cntlr, struct HdfDeviceObject *device) 200 { 201 ... 202 // Define the global variable static struct MipiDsiHandle g_mipiDsihandle[MAX_CNTLR_CNT]. 203 if (g_mipiDsihandle[cntlr->devNo].cntlr == NULL) { 204 (void)OsalMutexInit(&g_mipiDsihandle[cntlr->devNo].lock); 205 (void)OsalMutexInit(&(cntlr->lock)); 206 207 g_mipiDsihandle[cntlr->devNo].cntlr = cntlr;// Initialize MipiDsiHandle. 208 g_mipiDsihandle[cntlr->devNo].priv = NULL; 209 cntlr->device = device; // Prerequisites for conversion between HdfDeviceObject and MipiDsiHandle. 210 device->service = &(cntlr->service); // Prerequisites for conversion between HdfDeviceObject and MipiDsiHandle. 211 cntlr->priv = NULL; 212 ... 213 return HDF_SUCCESS; 214 } 215 ... 216 return HDF_FAILURE; 217 } 218 ``` 219 220 - **Release** function 221 222 **Input parameter**: 223 224 **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information. 225 226 **Return value**: 227 228 No value is returned. 229 230 **Function description**: 231 232 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. 233 234 > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** 235 > 236 > All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. 237 238 ``` 239 static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device) 240 { 241 struct MipiDsiCntlr *cntlr = NULL; 242 ... 243 cntlr = MipiDsiCntlrFromDevice(device);// A forced conversion from HdfDeviceObject to MipiDsiCntlr is involved. 244 // return (device == NULL) ? NULL : (struct MipiDsiCntlr *)device->service; 245 ... 246 MipiTxDrvExit(; // (Mandatory) Release the resources occupied by the vendor's devices. 247 MipiDsiUnregisterCntlr(&g_mipiTx); // Empty function 248 g_mipiTx.priv = NULL; 249 HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__); 250 } 251 ``` 252