Edit online

屏适配指南

4 Dec 2024
Read time: 9 minute(s)
本章节介绍 LCD 外设在 Luban-Lite 上的适配方法。用户可选择以下任意方式配置屏参数:
注: 如果同时使用方式一和方式二配置了屏幕参数,最终生效的是方式二的参数。

屏配置方式

方式一:通过 menuconfig 修改屏参数

Luban-Lite 根目录下执行 scons --menuconfig,进入 menuconfig 的功能配置界面,按如下选择:
Board options  --->
    Graphics Support  --->
        Graphics support
            [*] Display Support
                select Display interface (Display LVDS interface)  --->
                LVDS interface options  --->
                Display Panels  --->
                    ArtInChip Panel Drivers (ArtInChip simple panel)  --->
                    display timing of simple panel  --->
提示:

方式一仅支持修改 simple panel 的时序参数和 RGB/LVDS 的部分参数。

配置完成后,保存并退出 menuconfig,系统将根据配置重新编译内核和相关驱动。

方式二:将屏参数写入 panel 驱动源码中。

  • 时序参数

    static struct display_timing xm91080_timing = {
        .pixelclock = 130000000,
        .hactive = 1080,
        .hfront_porch = 160,
        .hback_porch = 160,
        .hsync_len = 40,
        .vactive = 1920,
        .vfront_porch = 10,
        .vback_porch = 20,
        .vsync_len = 8,
    };
  • 屏接口参数

    struct panel_dsi dsi = {
        .mode = DSI_MOD_VID_PULSE,
        .format = DSI_FMT_RGB888,
        .lane_num = 4,
    };

屏驱动适配

本节介绍如何适配一款 LCD 屏幕。LCD 屏驱动,即 panel,本质上是一个回调函数和屏参的集合。新屏适配实际上是重新实现一个 structaic_panel 结构体。

bsp/artinchip/drv/display/panel/ 源码目录下,根据屏接口选择一个模板,并在模版的基础上进行修改。

  • MIPI-DSI 接口可参考 panel_dsi_xm91080.c

  • MIPI-DBI 接口可参考 panel_dbi_ili9486l.c

新屏驱动适配 的详细流程如下所示,以 MIPI-DSI 接口为例:

  1. 拷贝一份模板文件,命名为 panel_dsi_xxx.c,将新文件添加进 KconifgSConscript 文件中。
    // bsp/artinchip/drv/display/panel/Kconfig
    config AIC_PANEL_DSI_XXX
        bool "ArtInChip MIPI DSI xxx panel"
        depends on AIC_DISP_MIPI_DSI
    
    // bsp/artinchip/SConscript
    if GetDepend('AIC_PANEL_DSI_XXX'):
        src += Glob('drv/display/panel/panel_dsi_xxx.c')
  2. 修改 struct aic_panel 的命名,并将其注册到系统中。
    1. struct aic_panel 添加到 panel_com.c 文件的 panels[] 指针数组中
      //panel_com.c
      static struct aic_panel *panels[] = {
      ...
      #ifdef AIC_PANEL_DSI_XXX
          &dsi_xxx,
      #endif
      };
    2. panel_com.h 文件中 extern struct aic_panel

      //panel_com.h
      extern struct aic_panel dsi_xxx;
  3. 修改 struct display_timing 结构体,并修改时序参数。
    注: 关于 LCD 时序参数,可查看用户手册 > 多媒体 > LCD 章节。
  4. 重新实现 aic_panel_funcs 结构体中的 prepare 或者 enable 接口,添加初始化操作。
    • 对于 MIPI-DSI 接口屏幕
      1. 在发送 init_sequence 前需要调用 panel_mipi_send_perpare() 进入 LP 模式发送命令,确保命令准确发送。

      2. 在发送完 init_sequence 后需要调用 panel_mipi_setup_realmode() 配置正确的 MIPI 模式。

      3. panel_dsi.c 为 MIPI-DSI 的 init_sequence 封装了两个接口:

        • panel_dsi_dcs_send_seq():发送 DCS 命令

        • panel_dsi_generic_send_seq():发送 Generic 命令

        提示:

        MIPI-DSI Command 有两种 Data Type: DCS 和 Generic

        • DCS (Display Command Set),MIPI 协议定义的一个专门用于显示的命令集,使用广泛

        • Generic,屏厂根据 MIPI 协议进行定制

    • 对于 MIPI-DBI 接口屏幕
      • panel_dbi.c 为 MIPI-DBI 的 init_sequence 封装了 enable 接口 panel_dbi_default_enable()

数据结构

struct aic_panel
struct aic_panel {
    const char *name;
    struct aic_panel_funcs *funcs;
    struct aic_panel_callbacks callbacks;
    const struct display_timing *timings;

    union {
        struct panel_rgb  *rgb;
        struct panel_lvds *lvds;
        struct panel_dsi  *dsi;
    };

    int connector_type;
};
struct aic_panel_funcs
panel 提供,供驱动框架调用的回调。新屏驱动只需要实现 prepare, enable, disable, unprepare 四个接口。
/* Each panel driver should define the follow functions. */
struct aic_panel_funcs {
    int (*prepare)(void);
    int (*enable)(struct aic_panel *panel);
    int (*disable)(struct aic_panel *panel);
    int (*unprepare)(void);
    int (*register_callback)(struct aic_panel *panel,
                struct aic_panel_callbacks *pcallback);
};
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, const u8 *data, u32 len);
    int (*di_set_videomode)(const struct display_timing *timings, int enable);
    int (*timing_enable)(void);
    int (*timing_disable)(void);
};
struct panel_rgb
rgb 接口屏幕参数
struct panel_rgb {
    unsigned int mode;
    unsigned int format;
    unsigned int clock_phase;
    unsigned int data_order;
    unsigned int data_mirror;
};
struct panel_lvds
lvds 接口屏幕参数
struct panel_lvds {
    enum lvds_mode mode;
    enum lvds_link_mode link_mode;
};
struct panel_dsi
mipi-dsi 接口屏幕参数
struct panel_dsi {
    enum dsi_mode mode;
    enum dsi_format format;
    unsigned int lane_num;
};
struct panel_dbi
mipi-dbi 接口屏幕参数
struct panel_dbi_commands {
    const u8 *buf;
    size_t len;
};

struct spi_cfg {
    unsigned int qspi_mode;
    unsigned int vbp_num;
    unsigned int code1_cfg;
    unsigned int code[3];
};

struct panel_dbi {
    unsigned int type;
    unsigned int format;
    unsigned int first_line;
    unsigned int other_line;
    struct panel_dbi_commands commands;
    struct spi_cfg *spi;
};

函数接口

1. panel_default_prepare
接口定义 int panel_default_prepare(struct aic_panel *panel)
功能说明 默认的 prepare 接口函数,使能 regulator
参数定义 结构体 aic_panel
返回值 0: 成功 负数:失败
注意事项 -
2. panel_default_enable
接口定义 int panel_default_enable(struct aic_panel *panel)
功能说明 默认的 enable 接口函数,设置 de 模块的 timing 参数,使能相应的 DI 接口,开启背光
参数定义 结构体 aic_panel
返回值 0:成功
注意事项 -
3. panel_default_unprepare
接口定义 int panel_default_unprepare(struct aic_panel *panel)
功能说明 默认的 unprepare 接口函数,禁用 regulator
参数定义 结构体 aic_panel
返回值 0:成功
注意事项 -
4. panel_default_disable
接口定义 int panel_default_disable(struct aic_panel *panel)
功能说明 默认的 disable 接口函数,禁用背光,禁用 DI 接口,禁用 DE
参数定义 结构体 aic_panel
返回值 0:成功
注意事项 -
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. panel_di_enable
接口定义 void panel_di_enable(struct aic_panel *panel, u32 ms)
功能说明 使能相应的 DI 接口
参数定义 结构体 aic_panel, ms 延时毫秒
返回值 void
注意事项 -
7. panel_di_disable
接口定义 void panel_di_disable(struct aic_panel *panel, u32 ms)
功能说明 禁用相应的 DI 接口
参数定义 结构体 aic_panel, ms 延时毫秒
返回值 void
注意事项 -
8. panel_de_timing_enable
接口定义 void panel_de_timing_enable(struct aic_panel *panel, u32 ms)
功能说明 启用 DE, 设置 de 模块的 timing 参数
参数定义 结构体 aic_panel, ms 延时毫秒
返回值 void
注意事项 -
9. panel_de_timing_disable
接口定义 void panel_de_timing_disable(struct aic_panel *panel, u32 ms)
功能说明 禁用 DE, 设置 de 模块的 timing 参数
参数定义 结构体 aic_panel, ms 延时毫秒
返回值 void
注意事项 -
10. panel_mipi_send_perpare
接口定义 void panel_mipi_send_perpare(struct aic_panel *panel)
功能说明 将 mipi-dsi 通道切换到 command mode, 准备好给 mipi 屏幕发送初始化命令
参数定义 结构体 aic_panel
返回值 void
注意事项 在 mipi 屏幕发送初始化命令前要先调用这个函数,以确保 mipi 屏幕收到正确的初始化命令
11. panel_send_command
接口定义 void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel)
功能说明 给 mipi 屏幕发送初始化命令
参数定义 结构体 aic_panel , 初始化序列大小 size, 初始化序列 para_cmd
返回值 void
注意事项 -
12. panel_mipi_setup_realmode
接口定义 void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel)
功能说明 将 mipi-dsi 通道切换回正确的模式
参数定义 结构体 aic_panel
返回值 void
注意事项 在 mipi 屏幕发送完初始化命令后调用这个函数,以确保 mipi 通道正常工作
13. panel_dsi_generic_send_seq
接口定义 #define panel_dsi_generic_send_seq(panel, seq…)
功能说明 发送屏厂根据 mipi 协议扩展的 command
参数定义 结构体 aic_panel,seq: init command
返回值 0: 成功, 负数:失败
注意事项 -
14. panel_dsi_dcs_send_seq
接口定义 #define panel_dsi_dcs_send_seq(panel, seq…)
功能说明 发送 mipi 协议标准的 command
参数定义 结构体 aic_panel,seq: init command
返回值 0: 成功, 负数:失败
注意事项 -
15. panel_dbi_default_enable
接口定义 int panel_dbi_default_enable(struct aic_panel *panel)
功能说明 mipi-dbi 接口的默认使能函数, 发送 mipi-dbi 的 init_sequence
参数定义 结构体 aic_panel
返回值 0: 成功, 负数:失败
注意事项 -