OpenHarmony南向之LCD显示屏
概述
LCD(Liquid Crystal Display)驱动,通过对显示器上下电、初始化显示器驱动IC(Integrated Circuit)内部寄存器等操作,使其可以正常工作。
HDF Display驱动模型

LCD器件驱动是显示框架最底层的部分。
向上对接到 Display 公共 HAL 层,辅助 HDI 的实现。通过Display-HDI对图形服务提供各类驱动能力接口;
向下对接显示屏 panel 器件,驱动屏幕正常工作,自上而下打通显示全流程通路。
所以驱动LCD主要在于LCD panel器件驱动。
LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,这里以rk3568平台为例,是常见的mipi接口的显示屏
驱动主要分为2大部分:hcs配置和panel驱动
- vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs
- drivers/hdf_core/framework/model/display/driver/panel/
下面就这2大部分分别来简单分析下
hcs配置及流程
hcs配置
display :: host {
    hostName = "display_host";
    device_hdf_drm_panel :: device {
        device0 :: deviceNode {
            policy = 0;
            priority = 197;
            preload = 0;
            moduleName = "HDF_DRMPANEL";
        }
    }
    device_hdf_disp :: device {
        device0 :: deviceNode {
            policy = 2;
            priority = 196;
            permission = 0660;
            moduleName = "HDF_DISP";
            serviceName = "hdf_disp";
        }
    }
    device_lcd :: device {
        ...
        device3 :: deviceNode {
            policy = 0;
            priority = 100;
            preload = 0;
            moduleName = "LCD_ILI9881_ST_5P5";
        }
    }
    device_pwm_bl :: device {
        device0 :: deviceNode {
            policy = 0;
            priority = 95;
            preload = 0;
            moduleName = "PWM_BL";
            deviceMatchAttr = "pwm_bl_dev";
        }
    }
    device_backlight :: device {
        device0 :: deviceNode {
            policy = 2;
            priority = 90;
            preload = 0;
            permission = 0660;
            moduleName = "HDF_BL";
            serviceName = "hdf_bl";
        }
    }
}大致流程
从上面的hcs配置可以看出,这里使用的是 DRM Panel,根据 priority值,驱动加载的顺序依次为:
1:HDF_BL:
2:PWM_BL
3:LCD
4:HDF_DISP
5:HDF_DRMPANEL
这个顺序是跟驱动代码里面的逻辑是相匹配的,LCD驱动在init的时候会注册panel(RegisterPanel),然后在HDF_DISP驱动的init中会通过 GetPanelManager获取注册的panelManager, 并使用 panelManager来 DispManagerInit,HDF_DRMPANEL驱动在init的时候会通过 GetDispManager获取在前面初始化的 DispManager,并使用DRM框架的接口来init和add相应drm_panel,且将mipi接口联系起来,整个过程是环环相扣。
panel驱动
Panel驱动中最核心的主要是实现以下接口:
struct PanelData {
    struct HdfDeviceObject *object;
    int32_t (*init)(struct PanelData *panel);       /*panel的软件初始化*/
    int32_t (*on)(struct PanelData *panel);         /*主要控制上电*/
    int32_t (*off)(struct PanelData *panel);        /*主要控制下电*/
    int32_t (*prepare)(struct PanelData *panel);    /*亮屏硬件时序初始化, 通过MIPI DCS发送亮屏初始化序列*/
    int32_t (*unprepare)(struct PanelData *panel);  /*灭屏硬件时序初始化, 通过MIPI DCS发送灭屏代码*/
    struct PanelInfo *info;         /*Panel的一些参数。见下方*/
    enum PowerStatus powerStatus;
    struct PanelEsd *esd;
    struct BacklightDev *blDev;
    void *priv;
};在驱动初始化接口中实例化后使用 RegisterPanel接口向display模型注册该panel驱动
以 ili9881_st_5p5MIPI显示屏驱动为例来看看大致的流程:
...
    /*获取panel节点,rk一般都使用的 simple panel*/
    panelNode = of_find_compatible_node(NULL, NULL, "simple-panel-dsi");
    if (panelNode == NULL) {
        HDF_LOGE("%s of_find_compatible_node fail", __func__);
        goto FAIL;
    }
    /*通过panel节点进一步获取mipi dsi的节点*/
    panel_dev->dsiDev = of_find_mipi_dsi_device_by_node(panelNode);
    if (panel_dev->dsiDev == NULL) {
        HDF_LOGE("%s of_find_mipi_dsi_device_by_node fail", __func__);
        goto FAIL;
    }
    /*获取power节点*/
    panel_dev->supply = devm_regulator_get(&panel_dev->dsiDev->dev, "power");
    if (panel_dev->supply == NULL) {
        HDF_LOGE("Get regulator fail");
        goto FAIL;
    }
    /*获取其他gpio控制节点,需根据硬件配置**/
    panel_dev->enable_gpio = devm_gpiod_get_optional(&panel_dev->dsiDev->dev, "enable", GPIOD_ASIS);
    if (IS_ERR(panel_dev->enable_gpio)) {
        HDF_LOGE("get enable_gpio fail");
        goto FAIL;
    }
    ...
    /*初始化PanelData mipi_dsi_device结构体,下面会展开详细说明*/
    PanelResInit(panel_dev);
    ...
    /*注册到Panel Manager*/
    if (RegisterPanel(&panel_dev->panel) != HDF_SUCCESS) {
        HDF_LOGE("RegisterPanel fail");
        goto FAIL;
    }
    ...PanelResInit函数主要是关键结构体(struct PanelData和 struct mipi_dsi_device )的实例化:
/*mipi dsi 的一些参数*/
panel_dev->dsiDev->lanes = 4;  /* 4: dsi,lanes ,number of active data lanes */
panel_dev->dsiDev->format = MIPI_DSI_FMT_RGB888; // dsi,format pixel format for video mode MIPI_DSI_FMT_RGB888
panel_dev->dsiDev->mode_flags = (MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM \
                                      | MIPI_DSI_MODE_EOT_PACKET);
panel_dev->panel.info = &g_panelInfo; /*Panel的一些参数。见下方*/
panel_dev->panel.init = PanelInit;  /*panel的软件初始化,这里为空函数*/
panel_dev->panel.on = PanelOn;   /*主要控制上电*/
panel_dev->panel.off = PanelOff; /*主要控制下电*/
panel_dev->panel.prepare = PanelPrepare;  /*亮屏硬件时序初始化, 通过MIPI DCS发送亮屏初始化代码*/
panel_dev->panel.unprepare = PanelUnprepare;  /*灭屏硬件时序初始化, 通过MIPI DCS发送灭屏代码*/
panel_dev->panel.priv = panel_dev->dsiDev;这里,在v3.2版本的代码里,最终还是调用的是Linux下mipi dsi相关的接口,并没有使用OH实现的mipi的驱动接口
panel相关的硬件参数定义,这个主要跟显示屏硬件有关,这些参数的具体含义可参看:《做鸿蒙应用开发到底学习些啥?》
static struct PanelInfo g_panelInfo = {
    .width = 720,          /* width */
    .height = 1280,          /* height */
    .hbp = 40,             /* horizontal back porch */
    .hfp = 40,         /* horizontal front porch */
    .hsw = 10,              /* horizontal sync width */
    .vbp = 15,              /* vertical back porch */
    .vfp = 10,              /* vertical front porch */
    .vsw = 36,               /* vertical sync width */
    .clockFreq = 75000000,  /* clock */
    .pWidth = 68,           /* physical width */
    .pHeight = 121,         /* physical height */
    .connectorType = DRM_MODE_CONNECTOR_DPI,   /* DRM_MODE_CONNECTOR_DPI=17 */
    .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL },
};总结
以上的内容主要简单介绍了OpenHarmony南向之LCD显示屏,没有具体到代码分析,移植等细节。
要想成为一名鸿蒙高级开发,以上知识点是必须要掌握的,除此之外,还需要掌握一些鸿蒙应用开发相关的一些技术,需要我们共同去探索。
为了节省大家一些查找的时间,这边联合几位行业大佬,为大家准备了一份《Open Harmony4.0&Next》的学习导图 ,从入门到进阶再到南北向开发实战的一整套完整体系 ,想要学习了解更多鸿蒙开发的相关知识可以借鉴:《做鸿蒙应用开发到底学习些啥?》

除了以上的知识内容,我还为大家整理了一份**《鸿蒙 (Harmony OS)开发学习手册》都是整理成PDF文档方式,分享给大家参考学习:《鸿蒙开发学习指南》**
《鸿蒙 (Harmony OS)开发学习手册》
一、入门必看
- 
应用开发导读(ArkTS) 
- 
应用开发导读(Java) 
3.......

二、HarmonyOS 概念
- 
系统定义 
- 
技术架构 
- 
技术特性 
- 
系统安全 
5......

三、如何快速入门?《鸿蒙基础入门开发宝典!》
- 
基本概念 
- 
构建第一个ArkTS应用 
- 
构建第一个JS应用 
- 
...... 

四、开发基础知识
- 
应用基础知识 
- 
配置文件 
- 
应用数据管理 
- 
应用安全管理 
- 
应用隐私保护 
- 
三方应用调用管控机制 
- 
资源分类与访问 
- 
学习ArkTS语言 
- 
...... 

五、基于ArkTS 开发
- 
Ability开发 
- 
UI开发 
- 
公共事件与通知 
- 
窗口管理 
- 
媒体 
- 
安全 
- 
网络与链接 
- 
电话服务 
- 
数据管理 
- 
后台任务(Background Task)管理 
- 
设备管理 
- 
设备使用信息统计 
- 
DFX 
- 
国际化开发 
- 
折叠屏系列 
- 
...... 

更多了解更多鸿蒙开发的相关知识可以参考:《做鸿蒙应用开发到底学习些啥?》