• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![](figure/architecture-of-the-display-driver-model.png "architecture-of-the-display-driver-model")
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    ![](figure/mipi-dsi.png "mipi-dsi")
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    ![](figure/ttl-interface.png "ttl-interface")
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