1# LCD 2 3## Overview 4 5### Function 6 7The Liquid Crystal Display (LCD) driver performs operations such as powering on the LCD and initializing the internal registers of the driver integrated circuits (ICs). 8 9The display driver model based on the [Hardware Driver Foundation (HDF)](../driver/driver-hdf-overview.md) provides the following functions: 10 11- Provides a basic framework for LCD driver development to improve development efficiency. 12 13- Facilitates driver porting across OSs and chip platforms. 14 15The following figure shows the HDF-based display driver model. 16 17 18 **Figure 1** HDF-based display driver model 19 20 ![image](figures/architecture-of-the-display-driver-model.png "Display Driver Model") 21 22The display driver model consists of the display common driver layer, SoC adapter layer, and LCD panel driver layer. The HDF-based display driver model shields the differences between kernel forms through platform and OSAL APIs so that the LCD driver can be easily ported across OSs and chip platforms. The display driver model connects to the display common Hardware Abstraction Layer (HAL), supports the implementation of the Hardware Device Interface (HDI), and provides various driver capability interfaces for graphics services through the Display-HDI. 23 24- Display common driver layer: connects to the display common HAL through the IOService data channel provided by the HDF to receive and process various upper-layer calls in a centralized manner. 25 26- SoC adapter layer: decouples the display driver from the SoC driver, configures parameters related to the chip platform, and passes the calls from the platform driver layer to the LCD driver layer. 27 28- LCD panel driver layer: provides LCD-related APIs for sending the initialization sequence, powering on/off, and setting the backlight. 29 30The display driver model leverages the capabilities and APIs provided by the platform to simplify the display driver development and improve the efficiency. 31 32### Basic Concepts 33 34The LCD interfaces include the Mobile Industry Processor Interface (MIPI) Display Serial Interface (DSI), Transistor-Transistor Logic (TTL) interface, and Low Voltage Differential Signaling (LVDS) interface. The MIPI DSI and TTL interfaces are commonly used. Here is a brief introduction to them. 35 36- MIPI DSI 37 38 **Figure 2** MIPI DSI 39 40 ![](figures/mipi-dsi.png "MIPI DSI") 41 42 The DSI is defined by the MIPI Alliance for the displays used in mobile devices. The MIPI DSI is used to transmit image data, in compliance with the MIPI protocol. Generally, control information is sent to the peer IC in the form of MIPI packets over the MIPI DSI, without the need of additional peripheral interfaces. 43 44- TTL interface 45 46 **Figure 3** TTL interface 47 48 ![](figures/ttl-interface.png "ttl-interface") 49 50 TTL level signals are generated by TTL devices, which are a major type of digital integrated circuits. TTL devices are manufactured using the bipolar process and feature high speed, low power consumption, and diversified types. 51 52 The TTL interface is used to transmit data in parallel mode under control signals. It transmits data signals, clock signals, and control signals (such as line synchronization signals, frame synchronization signals, and data validity signals). For the LCD with the TTL, additional peripheral interfaces, such as the Serial Peripheral Interface (SPI) and Inter-Integrated Circuit (I2C), are required for the read and write of the internal registers. 53 54### Constraints 55 56In addition to the IC model, you must consider the LCD peripheral circuit design, LCD interface unit of the baseband chip, backlight IC control, and upper-layer software programs. All these factors affect the development of the LCD driver. 57 58## Development Guidelines 59 60### When to Use 61 62Before applying your device with OpenHarmony system, you need to perform LCD driver adaption. The HDF-based display driver model provides a unified driver model for LCD adaptation regardless of the OS (LiteOS or Linux OS) and chip platform (Hi35xx, Hi38xx, or V3S). 63 64### Available APIs 65 66Table 1 APIs required for LCD driver adaptation 67 68| API | Description | 69| :------------------------------------------------------ | ------------------- | 70| display :: host | Sets device information. | 71| static int32_t LcdResetOn(void) | Sets the status of the reset pin.| 72| int32_t SampleEntryInit(struct HdfDeviceObject *object) | Initializes the entry function of the device driver. | 73 74### How to Develop 75 76 771. Add the device configuration related to the LCD driver. 78 792. Adapt the driver to the chip at the SoC adapter layer. 80 813. Add the LCD panel driver and register the panel driver functions in the driver entry function **Init**. The functions provide capabilities for: 82 - Powering on/off the LCD device 83 84 Based on the LCD hardware connection, use the GPIO APIs provided by the platform to perform operations on the LCD pins, such as the reset pin and IOVCC pin. For details about the power-on sequence, see the SPEC provided by the LCD supplier. 85 86 - Sending the initialization sequence 87 88 Based on the LCD hardware interfaces, use the I2C, SPI, and MIPI interfaces provided by the platform to download the LCD initialization sequence. For details, see the SPEC provided by the LCD supplier. 89 904. (Optional) Implement other HDF APIs, such as **Release()**, as required. 91 925. (Optional) Create other device nodes for implementing service logic or debugging based on the HDF as required. 93 94### Example 95 96The following uses the Hi35xx series chips as an example to describe how to perform LCD driver adaptation. 97 981. Add device information in the **vendor/bearpi/bearpi_hm_micro/hdf_config/device_info/device_info.hcs** file. 99 100 ```c++ 101 /* Configuration of the devices related to the display driver */ 102 display :: host { 103 hostName = "display_host"; 104 /* Configuration of the HDF display driver */ 105 device_hdf_disp :: device { 106 device0 :: deviceNode { 107 policy = 2; 108 priority = 200; 109 permission = 0660; 110 moduleName = "HDF_DISP"; 111 serviceName = "hdf_disp"; 112 } 113 } 114 /* Configuration of the driver device at the SoC adapter layer */ 115 device_hi35xx_disp :: device { 116 device0 :: deviceNode { 117 policy = 0; 118 priority = 199; 119 moduleName = "HI351XX_DISP"; 120 } 121 } 122 /* Configuration of the LCD driver */ 123 device_lcd :: device { 124 device0 :: deviceNode { 125 policy = 0; 126 priority = 100; 127 preload = 0; 128 moduleName = "LCD_Sample"; 129 } 130 device1 :: deviceNode { 131 policy = 0; 132 priority = 100; 133 preload = 2; 134 moduleName = "LCD_SampleXX"; 135 } 136 } 137 } 138 ``` 139 1402. Configure the chip platform driver information in the **drivers/hdf_core/framework/model/display/driver/adapter_soc/hi35xx_disp.c file**. 141 142 ```c++ 143 /* Configuration of the display driver to adapt to the MIPI and chip platform */ 144 static int32_t MipiDsiInit(struct PanelInfo *info) 145 { 146 int32_t ret; 147 struct DevHandle *mipiHandle = NULL; 148 struct MipiCfg cfg; 149 150 mipiHandle = MipiDsiOpen(0); 151 if (mipiHandle == NULL) { 152 HDF_LOGE("%s: MipiDsiOpen failure", __func__); 153 return HDF_FAILURE; 154 } 155 cfg.lane = info->mipi.lane; 156 cfg.mode = info->mipi.mode; 157 cfg.format = info->mipi.format; 158 cfg.burstMode = info->mipi.burstMode; 159 cfg.timing.xPixels = info->width; 160 cfg.timing.hsaPixels = info->hsw; 161 cfg.timing.hbpPixels = info->hbp; 162 cfg.timing.hlinePixels = info->width + info->hbp + info->hfp + info->hsw; 163 cfg.timing.vsaLines = info->vsw; 164 cfg.timing.vbpLines = info->vbp; 165 cfg.timing.vfpLines = info->vfp; 166 cfg.timing.ylines = info->height; 167 /* 0 : no care */ 168 cfg.timing.edpiCmdSize = 0; 169 cfg.pixelClk = CalcPixelClk(info); 170 cfg.phyDataRate = CalcDataRate(info); 171 /* Configure the MIPI device. */ 172 ret = MipiDsiSetCfg(mipiHandle, &cfg); 173 if (ret != HDF_SUCCESS) { 174 HDF_LOGE("%s:MipiDsiSetCfg failure", __func__); 175 } 176 MipiDsiClose(mipiHandle); 177 HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d\n", __func__, 178 cfg.pixelClk, cfg.phyDataRate); 179 return ret; 180 } 181 ``` 182 1833. Add a device in **drivers/hdf_core/framework/model/display/driver/panel/mipi_icn9700.c**. 184 185 - Define driver-related interface information. 186 187 ```c++ 188 #define RESET_GPIO 5 189 #define MIPI_DSI0 0 190 #define BLK_PWM1 1 191 #define PWM_MAX_PERIOD 100000 192 /* Set the backlight. */ 193 #define MIN_LEVEL 0 194 #define MAX_LEVEL 255 195 #define DEFAULT_LEVEL 100 196 #define WIDTH 480 197 #define HEIGHT 960 198 #define HORIZONTAL_BACK_PORCH 20 199 #define HORIZONTAL_FRONT_PORCH 20 200 #define HORIZONTAL_SYNC_WIDTH 10 201 #define VERTICAL_BACK_PORCH 14 202 #define VERTICAL_FRONT_PORCH 16 203 #define VERTICAL_SYNC_WIDTH 2 204 #define FRAME_RATE 60 205 ``` 206 207 - Define the **PanelInfo** structure. 208 209 ```c++ 210 struct PanelInfo { 211 uint32_t width; 212 uint32_t height; 213 uint32_t hbp; 214 uint32_t hfp; 215 uint32_t hsw; 216 uint32_t vbp; 217 uint32_t vfp; 218 uint32_t vsw; 219 uint32_t frameRate; 220 enum LcdIntfType intfType; 221 enum IntfSync intfSync; 222 struct MipiDsiDesc mipi; 223 struct BlkDesc blk; 224 struct PwmCfg pwm; 225 }; 226 ``` 227 228 - Initialize the LCD. 229 230 ```c++ 231 static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A }; 232 static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 }; 233 static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B }; 234 static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A }; 235 static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C }; 236 static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C }; 237 static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 }; 238 static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 }; 239 static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 }; 240 static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 }; 241 static uint8_t g_payLoad10[] = { 0xb7, 0x41 }; 242 static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 }; 243 static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 }; 244 static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 }; 245 static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF }; 246 static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 }; 247 static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 }; 248 static uint8_t g_payLoad17[] = { 0xc7, 0x04 }; 249 static uint8_t g_payLoad18[] = { 250 0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40, 251 0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 252 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06 253 }; 254 static uint8_t g_payLoad19[] = { 0x11 }; 255 static uint8_t g_payLoad20[] = { 0x29 }; 256 static DevHandle g_mipiHandle = NULL; 257 static DevHandle g_pwmHandle = NULL; 258 ``` 259 260 - Set the status of the reset pin. 261 262 ```c++ 263 static int32_t LcdResetOn(void) 264 { 265 int32_t ret; 266 ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); 267 if (ret != HDF_SUCCESS) { 268 HDF_LOGE("GpioSetDir failure, ret:%d", ret); 269 return HDF_FAILURE; 270 } 271 ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); 272 if (ret != HDF_SUCCESS) { 273 HDF_LOGE("GpioWrite failure, ret:%d", ret); 274 return HDF_FAILURE; 275 } 276 /* Set the delay to 20 ms. */ 277 OsalMSleep(20); 278 return HDF_SUCCESS; 279 } 280 ``` 281 282 - Initialize the entry function of the device driver. 283 284 ```c++ 285 int32_t SampleEntryInit(struct HdfDeviceObject *object) 286 { 287 HDF_LOGI("%s: enter", __func__); 288 if (object == NULL) { 289 HDF_LOGE("%s: param is null!", __func__); 290 return HDF_FAILURE; 291 } 292 /* Register the device driver APIs with the platform driver. */ 293 if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) { 294 HDF_LOGE("%s: PanelDataRegister error!", __func__); 295 return HDF_FAILURE; 296 } 297 return HDF_SUCCESS; 298 } 299 300 struct HdfDriverEntry g_sampleDevEntry = { 301 .moduleVersion = 1, 302 .moduleName = "LCD_SAMPLE", 303 .Init = SampleEntryInit, 304 }; 305 306 HDF_INIT(g_sampleDevEntry); 307 ``` 308