6.3.6. 屏配置指南¶
本章节将介绍 LCD 的配置方法。
小技巧
ArtInChip平台 SDK 已适配多款LCD屏幕,包括通用的RGB,LVDS屏幕以及多款MIPI屏幕。 推荐使用已有的panel驱动,如果无法满足需求再考虑对现有驱动进行扩展或单独编写一个panel驱动
6.3.6.1. 屏配置方式¶
方式一:将屏参数写入panel驱动源码中
- 时序参数 
/* Init the videomode parameter, dts will override the initial value. */
static struct videomode panel_vm = {
    .pixelclock = 130000000,
    .hactive = 1080,
    .hfront_porch = 160,
    .hback_porch = 160,
    .hsync_len = 40,
    .vactive = 1920,
    .vfront_porch = 10,
    .vback_porch = 20,
    .vsync_len = 8,
    .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
        DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE
};
- 屏接口参数 
static int panel_bind(struct device *dev, struct device *master, void *data)
{
    ...
    dsi->format = DSI_FMT_RGB888;
    dsi->mode = DSI_MOD_VID_PULSE;
    dsi->lane_num = 4;
    ...
}
方式二:将屏参数写入到board.dts文件中
panel_lvds {
    compatible = "artinchip,aic-general-lvds-panel";
    enable-gpios = <&gpio_a 4 GPIO_ACTIVE_HIGH>;
    data-mapping = "vesa-24";
    data-channel = "single-link1";
    status = "okay";
    port {
        panel_lvds_in: endpoint {
            remote-endpoint = <&lvds0_out>;
        };
    };
    display-timings {
        native-mode = <&timing0>;
        timing0: timing0 {
            clock-frequency = <130000000>;
            hactive = <1024>;
            vactive = <600>;
            hback-porch = <140>;
            hfront-porch = <160>;
            hsync-len = <20>;
            vback-porch = <20>;
            vfront-porch = <12>;
            vsync-len = <3>;
            de-active = <1>;
            pixelclk-active = <1>;
    };
};
注解
对于屏时序参数,只有当 board.dts 文件的 panel 结点没有设置 display-timings 子节点时,方式一才会生效。
6.3.6.2. 屏配置步骤¶
- 为 LCD 适配一款 panel 驱动。 
- 确保一条正确的数据通路。 
6.3.6.2.2. data flow¶
LCD 正常显示时,ArtInChip 平台的显示模块会形成一条完整的数据通道。
fb0 --> display engine  --> display interface  --> panel
数据通道的关系在 board.dts 中体现,以 LVDS 屏幕为例:
&fb0 {
    port {
        fb0_out: endpoint {
            remote-endpoint = <&de0_in>;
        };
    };
};
&de0 {
    status = "okay";
    port@0 {
        reg = <0>;
        de0_in: endpoint {
            remote-endpoint = <&fb0_out>;
        };
    };
    port@1 {
        reg = <1>;
        de0_out: endpoint {
            remote-endpoint = <&lvds0_in>;
        };
    };
};
&rgb0 {
    status = "disabled";
    port@0 {
        reg = <0>;
        rgb0_in: endpoint {
            remote-endpoint = <&rgb0_in>;
        };
    };
    port@1 {
        reg = <1>;
        rgb0_out: endpoint {
            remote-endpoint = <&panel_rgb_in>;
        };
    };
};
&lvds0 {
    status = "okay";
    port@0 {
        reg = <0>;
        lvds0_in: endpoint {
            remote-endpoint = <&de0_out>;
        };
    };
    port@1 {
        reg = <1>;
        lvds0_out: endpoint {
            remote-endpoint = <&panel_lvds_in>;
        };
    };
};
&dsi0 {
    status = "disabled";
    port@0 {
        reg = <0>;
        dsi0_in: endpoint {
            remote-endpoint = <&dsi0_in>;
        };
    };
    port@1 {
        reg = <1>;
        dsi0_out: endpoint {
            remote-endpoint = <&panel_dsi_in>;
        };
    };
};
在上述例子中,board.dts 通过 port 和 status 结点,配置了一条数据通道。
fb       |      de    |     |     lvds    |     panel
port  --> port0   port1 -->  port0   port1 -->  port
如果 board.dts 中没有正确配置一条数据通道,显示驱动无法完成初始化。
6.3.6.3. 屏驱动说明¶
6.3.6.3.2. 新屏驱动支持¶
LCD 屏驱动,即 panel,本质上是一个回调函数的集合。新屏驱动实际上是重新实现 aic_panel_funcs 结构体中一个或多个回调接口。
小技巧
如果是 LVDS 或 RGB 屏幕,这类屏幕往往不需要初始化动作,可直接使用 panel_lvds_general.c 或 panel_rgb_general.c。在 board.dts 中配置相关参数即可。
如果 LCD 屏幕需要初始化动作,则需要额外编写一份 panel 驱动。 在 panel 目录下,根据屏接口类型(RGB/LVDS/DSI)选择一个合适的模板,拷贝一个屏驱动。
- DSI 接口可参考panel_dsi_xm91080.c 
- SRGB 接口可参考panel_srgb_ili8961.c 
- I8080 接口可参考panel_i8080_ili9486l.c 
- SPI 接口可参考panel_spi_ili9341.c 
- 修改新屏驱动名字,将屏驱动添加进同级目录下的 Kconfig 和 Makefile 文件。 
- 重新实现 aic_panel_funcs 结构体中的 - prepare或者- enable接口,添加屏幕所需的初始化操作。
mipi 屏幕
- 在发送 init_sequence 之前需要调用 panel_mipi_send_perpare() 确保屏幕能正确无误地接受到命令。 
- 在发送完 init_sequence 后需要调用 panel_mipi_setup_realmode() 设置正确的mipi模式。 
- panel_dsi.c 中为 mipi-dsi 的 init_sequence 封装了两个接口: - panel_dsi_dcs_send_seq() :发送屏厂根据 mipi 协议扩展的 command 
- panel_dsi_generic_send_seq() :发送 mipi 协议标准的 command 
 
额外 gpio
- panel_comp 结构体默认支持两个 gpio
- 一个 - enable gpio, 可用于控制背光,使能屏幕
- 一个 - sleep gpio, 可用于控制屏幕供电,休眠唤醒
 
 
如果需要添加更多 gpio 引脚,可参考 panel_dsi_wuxga_7in.c/panel_srgb_ili8961.c 。
时序参数
- LCD 的 timing 参数,既可以在驱动中使用 hardcode 的方式设置 - struct videomode,也可以在 board.dts 中通过- display-timings节点设置。
- 如果 timing 参数采用 hardcode 方式设置,board.dts 必须删除 - display-timings节点。不然屏驱动源码中的 timing 参数会被 dts 中的 timing 参数覆盖。其他屏参数不受此影响。
6.3.6.3.3. 数据结构¶
6.3.6.3.3.1. struct panel_comp¶
struct panel_comp {
    struct aic_panel panel;
    struct display_timings *timings;
    bool   use_dt_timing;
    struct backlight_device *backlight;
    struct regulator *supply;
    struct gpio_desc *enable_gpio;
    struct gpio_desc *sleep_gpio;
};
6.3.6.3.3.2. struct aic_panel¶
struct aic_panel {
    struct aic_panel_funcs *funcs;
    struct aic_panel_callbacks callbacks;
    struct videomode *vm;
    struct device *dev;
    union {
        struct panel_rgb *rgb;
        struct panel_lvds *lvds;
        struct panel_dsi *dsi;
    };
};
6.3.6.3.3.3. struct aic_panel_funcs¶
panel提供,供fb调用的回调。新屏驱动必须实现。
/* Each panel driver should define the follow functions. */
struct aic_panel_funcs {
    int (*prepare)(struct aic_panel *panel);
    int (*enable)(struct aic_panel *panel);
    int (*disable)(struct aic_panel *panel);
    int (*unprepare)(struct aic_panel *panel);
    int (*get_video_mode)(struct aic_panel *panel, struct videomode *vm);
    int (*register_callback)(struct aic_panel *panel,
                struct aic_panel_callbacks *pcallback);
};
6.3.6.3.3.4. struct aic_panel_callbacks¶
panel无需实现,由DE、DI提供,供panel调用的回调。
struct aic_panel_callbacks {
    int (*di_enable)(void);
    int (*di_disable)(void);
    int (*di_send_cmd)(u32 dt, u32 vc, s8 *data, u32 len);
    int (*di_set_videomode)(struct videomode *vm, int enable);
    int (*timing_enable)(void);
    int (*timing_disable)(void);
};
6.3.6.3.3.5. struct panel_rgb¶
rgb接口屏幕参数
struct panel_rgb {
    unsigned int mode;
    unsigned int format;
    unsigned int clock_phase;
    unsigned int data_order;
    bool data_mirror;
};
6.3.6.3.3.6. struct panel_lvds¶
lvds接口屏幕参数
struct panel_lvds {
    enum lvds_mode mode;
    enum lvds_link_mode link_mode;
};
6.3.6.3.3.7. struct panel_dsi¶
dsi接口屏幕参数
struct panel_dsi {
    enum dsi_mode mode;
    enum dsi_format format;
    unsigned int lane_num;
};
6.3.6.3.4. 函数接口¶
6.3.6.3.4.1. panel_default_prepare¶
| 接口定义 | int panel_default_prepare(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 默认的prepare接口函数,使能regulator | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | 0: 成功 负数:失败 | 
| 注意事项 | 
6.3.6.3.4.2. panel_default_enable¶
| 接口定义 | int panel_default_enable(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 默认的enable接口函数,设置de模块的timing参数,使能相应的DI接口,开启背光 | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.3.6.3.4.3. panel_default_unprepare¶
| 接口定义 | int panel_default_unprepare(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 默认的unprepare接口函数,禁用regulator | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.3.6.3.4.4. panel_default_disable¶
| 接口定义 | int panel_default_disable(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 默认的disable接口函数,禁用背光,禁用DI接口,禁用DE | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.3.6.3.4.5. panel_register_callback¶
| 接口定义 | int panel_register_callback(struct aic_panel *panel, struct aic_panel_callbacks *pcallback) | 
|---|---|
| 功能说明 | DE,DI提供的回调函数,供panel调用 | 
| 参数定义 | 结构体 aic_panel 结构体 aic_panel_callbacks | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.3.6.3.4.6. panel_default_get_video_mode¶
| 接口定义 | int panel_default_get_video_mode(struct aic_panel *panel, struct videomode *vm) | 
|---|---|
| 功能说明 | panel提供的回调,供fb调用,传递从dts中解析的timing参数 | 
| 参数定义 | videomode:包含屏幕的timing参数 | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.3.6.3.4.7. panel_parse_dts¶
| 接口定义 | int panel_parse_dts(struct panel_comp *p, struct device *dev); | 
|---|---|
| 功能说明 | 解析board.dts中的panel结点 | 
| 参数定义 | panel_comp ,结构体device | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.3.6.3.4.8. panel_di_enable¶
| 接口定义 | void panel_di_enable(struct aic_panel *panel, u32 ms) | 
|---|---|
| 功能说明 | 使能相应的DI接口 | 
| 参数定义 | 结构体 aic_panel, ms延时毫秒 | 
| 返回值 | void | 
| 注意事项 | 
6.3.6.3.4.9. panel_di_disable¶
| 接口定义 | void panel_di_disable(struct aic_panel *panel, u32 ms) | 
|---|---|
| 功能说明 | 禁用相应的DI接口 | 
| 参数定义 | 结构体 aic_panel, ms延时毫秒 | 
| 返回值 | void | 
| 注意事项 | 
6.3.6.3.4.10. panel_de_timing_enable¶
| 接口定义 | void panel_de_timing_enable(struct aic_panel *panel, u32 ms) | 
|---|---|
| 功能说明 | 启用DE, 设置de模块的timing参数 | 
| 参数定义 | 结构体 aic_panel, ms延时毫秒 | 
| 返回值 | void | 
| 注意事项 | 
6.3.6.3.4.11. panel_de_timing_disable¶
| 接口定义 | void panel_de_timing_disable(struct aic_panel *panel, u32 ms) | 
|---|---|
| 功能说明 | 禁用DE, 设置de模块的timing参数 | 
| 参数定义 | 结构体 aic_panel, ms延时毫秒 | 
| 返回值 | void | 
| 注意事项 | 
6.3.6.3.4.12. panel_mipi_send_perpare¶
| 接口定义 | void panel_mipi_send_perpare(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 将mipi-dsi通道切换到command mode, 准备好给mipi屏幕发送初始化命令 | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | void | 
| 注意事项 | 在mipi屏幕发送初始化命令前要先调用这个函数,以确保mipi屏幕收到正确的初始化命令 | 
6.3.6.3.4.13. panel_send_command¶
| 接口定义 | void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel) | 
|---|---|
| 功能说明 | 给mipi屏幕发送初始化命令 | 
| 参数定义 | 结构体 aic_panel , 初始化序列大小size, 初始化序列 para_cmd | 
| 返回值 | void | 
| 注意事项 | 
6.3.6.3.4.14. panel_mipi_setup_realmode¶
| 接口定义 | void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel) | 
|---|---|
| 功能说明 | 将mipi-dsi通道切换回正确的模式 | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | void | 
| 注意事项 | 在mipi屏幕发送完初始化命令后调用这个函数,以确保mipi通道正常工作 | 
6.3.6.3.4.15. panel_dsi_generic_send_seq¶
| 接口定义 | #define panel_dsi_generic_send_seq(panel, seq…) | 
|---|---|
| 功能说明 | 发送屏厂根据 mipi 协议扩展的 command | 
| 参数定义 | 结构体 aic_panel,seq: init command | 
| 返回值 | 0: 成功, 负数:失败 | 
| 注意事项 | 
6.3.6.3.4.16. panel_dsi_dcs_send_seq¶
| 接口定义 | #define panel_dsi_dcs_send_seq(panel, seq…) | 
|---|---|
| 功能说明 | 发送 mipi 协议标准的 command | 
| 参数定义 | 结构体 aic_panel,seq: init command | 
| 返回值 | 0: 成功, 负数:失败 | 
| 注意事项 | 
6.3.6.3.4.17. panel_init¶
| 接口定义 | static inline void panel_init(struct panel_comp *p, struct device *dev, struct videomode *vm, struct aic_panel_funcs *funcs) | 
|---|---|
| 功能说明 | 初始化一个panel | 
| 参数定义 | 结构体 panel_comp , 结构体device,屏时序参数videomode, aic_panel_funcs | 
| 返回值 | void | 
| 注意事项 |