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