1# LCD<a name="EN-US_TOPIC_0000001052857284"></a> 2 3- [Overview](#section141575391542) 4 - [API Description](#section14711163785519) 5 6- [Development Guidelines](#section12394223125615) 7 - [How to Develop](#section515923045814) 8 9- [Development Example](#section7441155155813) 10 11## Overview<a name="section141575391542"></a> 12 13The Liquid Crystal Display \(LCD\) driver powers on the LCD and initializes internal LCD registers through APIs to enable the LCD to work properly. The display driver is developed based on the hardware driver foundation \([HDF](driver-hdf-overview.md)\). It provides power-on, power-off, and sending of the initialization sequence for LCD hardware across OSs and platforms. The display driver model is shown in [Figure 1](#fig69138814229). 14 15**Figure 1** Architecture of the display driver model<a name="fig69138814229"></a> 16 17 18- **Display driver model** 19 20 The display driver model consists of the display common driver layer, SoC adapter layer, and third-party chip driver layer. The display driver model is developed based on the HDF and hides the differences between kernel forms through platform and OSAL APIs so the LCD driver can be migrated between different OSs and chip platforms. The display driver connects to the display common HAL, supports the implementation of Hardware Driver Interfaces \(HDIs\), and provides various driver interfaces for the graphics service through the display HDI. 21 22 - Display common driver layer: connects to the display common HAL through the IOService data channel provided by the HDF to receive and process upper-layer calls in a centralized manner. 23 24 - SoC adapter layer: decouples the display driver from the SoC driver, configures parameters related to the chip platform, and passes calls from the platform driver layer to the LCD driver layer. 25 26 - Third-party chip driver layer: provides LCD-related APIs for sending the LCD initialization sequence, powering on or off the LCD device, and setting the backlight. 27 28 The display driver model, capabilities, and APIs help you simplify the display driver development and improve the efficiency. 29 30 31### API Description<a name="section14711163785519"></a> 32 33The LCD interfaces are classified into the Mobile Industry Processor Interface \(MIPI\) Display Serial Interface \(DSI\), Transistor-Transistor Logic \(TTL\) interfaces, and Low Voltage Differential Signaling \(LVDS\) interfaces. The MIPI DSI and TTL interfaces are commonly used. Here is a brief introduction to them. 34 35- MIPI DSI 36 37 **Figure 2** MIPI DSI<a name="fig6936451331"></a> 38  39 40 The MIPI DSI is defined by MIPI Alliance. It is mainly used for mobile terminal display. The MIPI DSI is used to transmit image data, in compliance with the MIPI protocol. Generally, control information of the MIPI DSI is sent to the peer IC in the form of MIPI packets through the MIPI DSI. No additional interface is required. 41 42- TTL interface 43 44 **Figure 3** TTL interface<a name="fig141611855635"></a> 45  46 47 TTL level signals are generated by TTL devices, which are a major type of digital integrated circuits. They are manufactured using the bipolar process and feature high speed, low power consumption, and multiple types. 48 49 The TTL interface is used to transmit data in parallel mode under the control of control signals. It transmits data signals, clock signals, and control signals \(such as line synchronization signals, frame synchronization signals, and data validity signals\). Generally, the LCD of the TTL interface and the read/write of internal registers require additional peripheral interfaces, such as the Serial Peripheral Interface \(SPI\) and Inter-Integrated Circuit \(I2C\). 50 51 52## Development Guidelines<a name="section12394223125615"></a> 53 54The display driver model is developed based on the HDF, platform APIs, and APIs at the OS abstraction layer \(OSAL\), and provides a unified driver model for the LCD regardless of the OS \(LiteOS or Linux OS\) and chip platforms \(such as Hi35xx, Hi38xx, and V3S\). 55 56### How to Develop<a name="section515923045814"></a> 57 581. Add the LCD driver-related hardware descriptions. 592. Add a driver that adapts to the chip at the SoC adapter layer. 603. Add the LCD panel driver and register the panel driver functions in the driver entry function **Init**. The functions provide capabilities for: 61 - Powering on/off the LCD device 62 63 Based on the LCD hardware connection, use the GPIO interfaces 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. 64 65 - Sending the initialization sequence 66 67 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. 68 694. Implement other HDF interfaces as required, for example, the **Release** interface. 705. Use the HDF to create other device nodes for implementing service logic or debugging as required. 71 72## Development Example<a name="section7441155155813"></a> 73 74Add the device description. 75 76``` 77/* Description of the display driver */ 78display :: host { 79 hostName = "display_host"; 80 /* Description of the HDF display driver */ 81 device_hdf_disp :: device { 82 device0 :: deviceNode { 83 policy = 2; 84 priority = 200; 85 permission = 0660; 86 moduleName = "HDF_DISP"; 87 serviceName = "hdf_disp"; 88 } 89 } 90 /* Description of the driver device at the SoC adapter layer */ 91 device_hi35xx_disp :: device { 92 device0 :: deviceNode { 93 policy = 0; 94 priority = 199; 95 moduleName = "HI351XX_DISP"; 96 } 97 } 98 /* Description of the LCD driver */ 99 device_lcd :: device { 100 device0 :: deviceNode { 101 policy = 0; 102 priority = 100; 103 preload = 0; 104 moduleName = "LCD_Sample"; 105 } 106 device1 :: deviceNode { 107 policy = 0; 108 priority = 100; 109 preload = 2; 110 moduleName = "LCD_SampleXX"; 111 } 112 } 113} 114``` 115 116The following example shows how to adapt to the MIPI device to the Hi35xx series chips at the SoC adapter layer: 117 118``` 119static int32_t MipiDsiInit(struct PanelInfo *info) 120{ 121 int32_t ret; 122 struct DevHandle *mipiHandle = NULL; 123 struct MipiCfg cfg; 124 125 mipiHandle = MipiDsiOpen(0); 126 if (mipiHandle == NULL) { 127 HDF_LOGE("%s: MipiDsiOpen failure", __func__); 128 return HDF_FAILURE; 129 } 130 cfg.lane = info->mipi.lane; 131 cfg.mode = info->mipi.mode; 132 cfg.format = info->mipi.format; 133 cfg.burstMode = info->mipi.burstMode; 134 cfg.timing.xPixels = info->width; 135 cfg.timing.hsaPixels = info->hsw; 136 cfg.timing.hbpPixels = info->hbp; 137 cfg.timing.hlinePixels = info->width + info->hbp + info->hfp + info->hsw; 138 cfg.timing.vsaLines = info->vsw; 139 cfg.timing.vbpLines = info->vbp; 140 cfg.timing.vfpLines = info->vfp; 141 cfg.timing.ylines = info->height; 142 /* 0 : no care */ 143 cfg.timing.edpiCmdSize = 0; 144 cfg.pixelClk = CalcPixelClk(info); 145 cfg.phyDataRate = CalcDataRate(info); 146 /* config mipi device */ 147 ret = MipiDsiSetCfg(mipiHandle, &cfg); 148 if (ret != HDF_SUCCESS) { 149 HDF_LOGE("%s:MipiDsiSetCfg failure", __func__); 150 } 151 MipiDsiClose(mipiHandle); 152 HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d\n", __func__, 153 cfg.pixelClk, cfg.phyDataRate); 154 return ret; 155} 156``` 157 158The following example shows code for developing an LCD driver: 159 160``` 161#define RESET_GPIO 5 162#define MIPI_DSI0 0 163#define BLK_PWM1 1 164#define PWM_MAX_PERIOD 100000 165/* backlight setting */ 166#define MIN_LEVEL 0 167#define MAX_LEVEL 255 168#define DEFAULT_LEVEL 100 169 170#define WIDTH 480 171#define HEIGHT 960 172#define HORIZONTAL_BACK_PORCH 20 173#define HORIZONTAL_FRONT_PORCH 20 174#define HORIZONTAL_SYNC_WIDTH 10 175#define VERTIACL_BACK_PORCH 14 176#define VERTIACL_FRONT_PORCH 16 177#define VERTIACL_SYNC_WIDTH 2 178#define FRAME_RATE 60 179 180/* PanelInfo structure */ 181struct PanelInfo { 182 uint32_t width; 183 uint32_t height; 184 uint32_t hbp; 185 uint32_t hfp; 186 uint32_t hsw; 187 uint32_t vbp; 188 uint32_t vfp; 189 uint32_t vsw; 190 uint32_t frameRate; 191 enum LcdIntfType intfType; 192 enum IntfSync intfSync; 193 struct MipiDsiDesc mipi; 194 struct BlkDesc blk; 195 struct PwmCfg pwm; 196}; 197 198/* Initialization sequence of the LCD panel */ 199static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A }; 200static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 }; 201static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B }; 202static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A }; 203static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C }; 204static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C }; 205static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 }; 206static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 }; 207static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 }; 208static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 }; 209static uint8_t g_payLoad10[] = { 0xb7, 0x41 }; 210static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 }; 211static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 }; 212static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 }; 213static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF }; 214static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 }; 215static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 }; 216static uint8_t g_payLoad17[] = { 0xc7, 0x04 }; 217static uint8_t g_payLoad18[] = { 218 0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40, 219 0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 220 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06 221}; 222static uint8_t g_payLoad19[] = { 0x11 }; 223static uint8_t g_payLoad20[] = { 0x29 }; 224 225struct DsiCmdDesc g_OnCmd[] = { 226 { 0x29, 0, sizeof(g_payLoad0), g_payLoad0 }, 227 { 0x29, 0, sizeof(g_payLoad1), g_payLoad1 }, 228 { 0x29, 0, sizeof(g_payLoad2), g_payLoad2 }, 229 { 0x29, 0, sizeof(g_payLoad3), g_payLoad3 }, 230 { 0x29, 0, sizeof(g_payLoad4), g_payLoad4 }, 231 { 0x29, 0, sizeof(g_payLoad5), g_payLoad5 }, 232 { 0x29, 0, sizeof(g_payLoad6), g_payLoad6 }, 233 { 0x29, 0, sizeof(g_payLoad7), g_payLoad7 }, 234 { 0x29, 0, sizeof(g_payLoad8), g_payLoad8 }, 235 { 0x29, 0, sizeof(g_payLoad9), g_payLoad9 }, 236 { 0x23, 0, sizeof(g_payLoad10), g_payLoad10 }, 237 { 0x29, 0, sizeof(g_payLoad11), g_payLoad11 }, 238 { 0x29, 0, sizeof(g_payLoad12), g_payLoad12 }, 239 { 0x29, 0, sizeof(g_payLoad13), g_payLoad13 }, 240 { 0x29, 0, sizeof(g_payLoad14), g_payLoad14 }, 241 { 0x29, 0, sizeof(g_payLoad15), g_payLoad15 }, 242 { 0x29, 0, sizeof(g_payLoad16), g_payLoad16 }, 243 { 0x23, 0, sizeof(g_payLoad17), g_payLoad17 }, 244 { 0x29, 1, sizeof(g_payLoad18), g_payLoad18 }, 245 { 0x05, 120, sizeof(g_payLoad19), g_payLoad19 }, 246 { 0x05, 120, sizeof(g_payLoad20), g_payLoad20 }, 247}; 248static DevHandle g_mipiHandle = NULL; 249static DevHandle g_pwmHandle = NULL; 250 251/* Set the status of the reset pin. */ 252static int32_t LcdResetOn(void) 253{ 254 int32_t ret; 255 ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); 256 if (ret != HDF_SUCCESS) { 257 HDF_LOGE("GpioSetDir failure, ret:%d", ret); 258 return HDF_FAILURE; 259 } 260 ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); 261 if (ret != HDF_SUCCESS) { 262 HDF_LOGE("GpioWrite failure, ret:%d", ret); 263 return HDF_FAILURE; 264 } 265 /* delay 20ms */ 266 OsalMSleep(20); 267 return HDF_SUCCESS; 268} 269 270static int32_t SampleInit(void) 271{ 272 /* Obtain the MIPI DSI device handle. */ 273 g_mipiHandle = MipiDsiOpen(MIPI_DSI0); 274 if (g_mipiHandle == NULL) { 275 HDF_LOGE("%s: MipiDsiOpen failure", __func__); 276 return HDF_FAILURE; 277 } 278 return HDF_SUCCESS; 279} 280 281static int32_t SampleOn(void) 282{ 283 int32_t ret; 284 /* Power on the LCD. */ 285 ret = LcdResetOn(); 286 if (ret != HDF_SUCCESS) { 287 HDF_LOGE("%s: LcdResetOn failure", __func__); 288 return HDF_FAILURE; 289 } 290 if (g_mipiHandle == NULL) { 291 HDF_LOGE("%s: g_mipiHandle is null", __func__); 292 return HDF_FAILURE; 293 } 294 /* Send the initialization sequence via MIPI. */ 295 int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]); 296 int32_t i; 297 for (i = 0; i < count; i++) { 298 ret = MipiDsiTx(g_mipiHandle, &(g_OnCmd[i])); 299 if (ret != HDF_SUCCESS) { 300 HDF_LOGE("MipiDsiTx failure"); 301 return HDF_FAILURE; 302 } 303 } 304 /* Set MIPI to the high speed (HS) mode. */ 305 MipiDsiSetHsMode(g_mipiHandle); 306 return HDF_SUCCESS; 307} 308 309/* PanelInfo structure variables */ 310static struct PanelInfo g_panelInfo = { 311 .width = WIDTH, /* width */ 312 .height = HEIGHT, /* height */ 313 .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */ 314 .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */ 315 .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */ 316 .vbp = VERTIACL_BACK_PORCH, /* vertiacl back porch */ 317 .vfp = VERTIACL_FRONT_PORCH, /* vertiacl front porch */ 318 .vsw = VERTIACL_SYNC_WIDTH, /* vertiacl sync width */ 319 .frameRate = FRAME_RATE, /* frame rate */ 320 .intfType = MIPI_DSI, /* panel interface type */ 321 .intfSync = OUTPUT_USER, /* output timming type */ 322 /* mipi config info */ 323 .mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT }, 324 /* backlight config info */ 325 .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL }, 326 .pwm = { BLK_PWM1, PWM_MAX_PERIOD }, 327}; 328 329/* Basic APIs that need to be adapted for the chip driver */ 330static struct PanelData g_panelData = { 331 .info = &g_panelInfo, 332 .init = SampleInit, 333 .on = SampleOn, 334 .off = SampleOff, 335 .setBacklight = SampleSetBacklight, 336}; 337 338/* Entry function of the chip driver */ 339int32_t SampleEntryInit(struct HdfDeviceObject *object) 340{ 341 HDF_LOGI("%s: enter", __func__); 342 if (object == NULL) { 343 HDF_LOGE("%s: param is null!", __func__); 344 return HDF_FAILURE; 345 } 346 /* Register the chip driver APIs with the platform driver. */ 347 if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) { 348 HDF_LOGE("%s: PanelDataRegister error!", __func__); 349 return HDF_FAILURE; 350 } 351 return HDF_SUCCESS; 352} 353 354struct HdfDriverEntry g_sampleDevEntry = { 355 .moduleVersion = 1, 356 .moduleName = "LCD_SAMPLE", 357 .Init = SampleEntryInit, 358}; 359 360HDF_INIT(g_sampleDevEntry); 361``` 362 363