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