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