• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# LCD<a name="ZH-CN_TOPIC_0000001052857284"></a>
2
3-   [概述](#section141575391542)
4    -   [接口说明](#section14711163785519)
5
6-   [开发指导](#section12394223125615)
7    -   [开发步骤](#section515923045814)
8
9-   [开发实例](#section7441155155813)
10
11## 概述<a name="section141575391542"></a>
12
13LCD(Liquid Crystal Display)液晶显示驱动,对LCD进行上电,并通过接口初始化LCD内部寄存器,使LCD正常工作。Display驱动模型基于HDF( Hardware Driver Foundation)[驱动框架](driver-hdf-overview.md)开发,实现跨OS、跨平台,为LCD硬件提供上下电功能、发送初始化序列功能,使LCD进入正常的工作模式,显示芯片平台侧的图像数据,基于HDF驱动框架的Display驱动模型如[图1](#fig69138814229)。
14
15**图 1**  基于HDF驱动框架的Display驱动模型<a name="fig69138814229"></a>
16![](figure/基于HDF驱动框架的Display驱动模型.png "基于HDF驱动框架的Display驱动模型")
17
18-   **Display驱动模型介绍**
19
20    Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共hal层,支撑HDI接口的实现,通过Display-HDI(Hardware Display Interface)对图形服务提供各类驱动能力接口。
21
22    (1)Display平台驱动层:通过HDF提供的IOService数据通道,与公共Hal层对接,集中接收并处理各类上层调用指令;
23
24    (2)SOC平台驱动适配层:借助此SOC适配层,实现Display驱动和SOC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层;
25
26    (3)LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。
27
28    基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。
29
30
31### 接口说明<a name="section14711163785519"></a>
32
33LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,常用的是MIPI DSI接口和TTL接口,下面对常用的MIPI DSI接口和TTL接口作简要介绍。
34
35-   MIPI DSI接口
36
37    **图 2**  MIPI DSI接口<a name="fig6936451331"></a>
38    ![](figure/MIPI-DSI接口.png "MIPI-DSI接口")
39
40    MIPI DSI接口是MIPI(移动行业处理器接口)联盟定义的显示接口,主要用于移动终端显示屏接口,接口数据传输遵循MIPI协议,MIPI DSI接口为数据接口,传输图像数据,通常情况下MIPI DSI接口的控制信息以MIPI包形式通过MIPI DSI接口发送到对端IC,不需要额外的外设接口。
41
42-   TTL接口
43
44    **图 3**  TTL接口<a name="fig141611855635"></a>
45    ![](figure/TTL接口.png "TTL接口")
46
47    TTL(Transistor Transistor Logic)即晶体管-晶体管逻辑,TTL电平信号由TTL器件产生,TTL器件是数字集成电路的一大门类,它采用双极型工艺制造,具有高速度、低功耗和品种多等特点。
48
49    TTL接口是并行方式传输数据的接口,有数据信号、时钟信号和控制信号(行同步、帧同步、数据有效信号等),在控制信号控制下完成数据传输。通常TTL接口的LCD,内部寄存器读写需要额外的外设接口,比如SPI接口、I2C接口等。
50
51
52## 开发指导<a name="section12394223125615"></a>
53
54Display驱动模型基于HDF驱动框架、Platform接口及OSAL接口开发,可以做到不区分OS(LiteOS、Linux)和芯片平台(Hi35xx、Hi38xx、V3S等),为LCD器件提供统一的驱动模型。
55
56### 开发步骤<a name="section515923045814"></a>
57
581.  添加LCD驱动相关的设备描述配置。
592.  在SOC平台驱动适配层中适配对应的芯片平台驱动。
603.  添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口:
61    -   LCD上下电
62
63        根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC。
64
65    -   发送初始化序列
66
67        根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。
68
694.  根据需求实现HDF框架其他接口,比如Release接口。
705.  根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。
71
72## 开发实例<a name="section7441155155813"></a>
73
74添加设备描述配置:
75
76```
77/* Display驱动相关的设备描述配置 */
78display :: host {
79    hostName = "display_host";
80    /* Display平台驱动设备描述 */
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    /* SOC适配层驱动设备描述 */
91    device_hi35xx_disp :: device {
92        device0 :: deviceNode {
93            policy = 0;
94            priority = 199;
95            moduleName = "HI351XX_DISP";
96        }
97    }
98    /* LCD器件驱动设备描述 */
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
116SOC适配层驱动,以Hi35xx系列芯片为例,需要在本层驱动中适配MIPI等和芯片平台相关的配置,示例如下:
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
158LCD器件驱动示例如下:
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/* Panel Info结构体结构体 */
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/* LCD屏的初始化序列 */
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/* 设置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    /* 获取MIPI DSI设备操作句柄 */
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    /* 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    /* 使用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    /* 将mipi切换到HS模式 */
305    MipiDsiSetHsMode(g_mipiHandle);
306    return HDF_SUCCESS;
307}
308
309/* PanelInfo结构体变量 */
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/* 器件驱动需要适配的基础接口 */
330static struct PanelData g_panelData = {
331    .info = &g_panelInfo,
332    .init = SampleInit,
333    .on = SampleOn,
334    .off = SampleOff,
335    .setBacklight = SampleSetBacklight,
336};
337
338/* 器件驱动入口函数 */
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    /* 器件驱动接口注册,ops提供给平台驱动调用 */
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