6.2.6. 屏适配指南¶
本章节介绍 LCD 外设在 Luban-Lite 上的适配方法。
6.2.6.1. 屏配置方式¶
方式一:通过 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 的部分参数。
方式二:将屏参数写入 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,
};
注解
如果方式一和方式二都配置了屏幕参数,最终生效的是方式二的参数。
6.2.6.2. 屏配置说明¶
如果适配一款 RGB/LVDS 屏幕,通过 menuconfig 选择 ArtInChip simple panel ,
修改显示参数即可。这类屏幕往往不需要初始化,使用通用的屏驱动即可。详情可参考 menuconfig 配置指南章节。
如果 LCD 屏幕需要初始化动作,则需要为其编写一个 panel 驱动,详情可参考后续的屏驱动说明章节。
6.2.6.3. 屏驱动说明¶
6.2.6.3.1. 屏源码位置¶
bsp/artinchip/drv/display/panel/
6.2.6.3.2. 新屏驱动适配¶
LCD屏驱动,即 panel,本质上是一个回调函数和屏参的集合。新屏适配实际上是重新实现一个 struct aic_panel 结构体。
新增一款屏驱动,可以在 panel 源码目录下,根据屏接口选择一个模板,在模版的基础上进行修改。
- MIPI-DSI 接口可参考 panel_dsi_xm91080.c 
- MIPI-DBI 接口可参考 panel_dbi_ili9486l.c 
以 MIPI-DSI 接口为例:
- 拷贝一份模板文件,命名为 panel_dsi_xxx.c,将新文件添加进 Kconifg 和 SConscript 文件中 
// 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')
- 修改 - struct aic_panel的命名,并将其注册。- 将 struct aic_panel 添加到 - panel_com.c文件的- panels[]指针数组中
- 在 - panel_com.h文件中- externstruct aic_panel。
 
//panel_com.c
static struct aic_panel *panels[] = {
...
#ifdef AIC_PANEL_DSI_XXX
    &dsi_xxx,
#endif
};
//panel_com.h
extern struct aic_panel dsi_xxx;
- 修改 - struct display_timing结构体,根据 LCD 屏幕规格书修改时序参数。
- 重新实现 aic_panel_funcs 结构体中的 - prepare或者- enable接口,添加初始化操作。
对于 MIPI-DSI 接口屏幕
- 在发送 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 
 
对于 MIPI-DBI 接口屏幕
- panel_dbi.c 为 MIPI-DBI 的 init_sequence 封装了 enable 接口 panel_dbi_default_enable() 
6.2.6.3.3. 数据结构¶
6.2.6.3.3.1. 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;
};
6.2.6.3.3.2. 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);
};
6.2.6.3.3.3. 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);
};
6.2.6.3.3.4. 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;
};
6.2.6.3.3.5. struct panel_lvds¶
lvds接口屏幕参数
struct panel_lvds {
    enum lvds_mode mode;
    enum lvds_link_mode link_mode;
};
6.2.6.3.3.6. struct panel_dsi¶
mipi-dsi接口屏幕参数
struct panel_dsi {
    enum dsi_mode mode;
    enum dsi_format format;
    unsigned int lane_num;
};
6.2.6.3.3.7. 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;
};
6.2.6.3.4. 函数接口¶
6.2.6.3.4.1. panel_default_prepare¶
| 接口定义 | int panel_default_prepare(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 默认的prepare接口函数,使能regulator | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | 0: 成功 负数:失败 | 
| 注意事项 | 
6.2.6.3.4.2. panel_default_enable¶
| 接口定义 | int panel_default_enable(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 默认的enable接口函数,设置de模块的timing参数,使能相应的DI接口,开启背光 | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.2.6.3.4.3. panel_default_unprepare¶
| 接口定义 | int panel_default_unprepare(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 默认的unprepare接口函数,禁用regulator | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.2.6.3.4.4. panel_default_disable¶
| 接口定义 | int panel_default_disable(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 默认的disable接口函数,禁用背光,禁用DI接口,禁用DE | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | 0:成功 | 
| 注意事项 | 
6.2.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.2.6.3.4.6. panel_di_enable¶
| 接口定义 | void panel_di_enable(struct aic_panel *panel, u32 ms) | 
|---|---|
| 功能说明 | 使能相应的DI接口 | 
| 参数定义 | 结构体 aic_panel, ms延时毫秒 | 
| 返回值 | void | 
| 注意事项 | 
6.2.6.3.4.7. panel_di_disable¶
| 接口定义 | void panel_di_disable(struct aic_panel *panel, u32 ms) | 
|---|---|
| 功能说明 | 禁用相应的DI接口 | 
| 参数定义 | 结构体 aic_panel, ms延时毫秒 | 
| 返回值 | void | 
| 注意事项 | 
6.2.6.3.4.8. panel_de_timing_enable¶
| 接口定义 | void panel_de_timing_enable(struct aic_panel *panel, u32 ms) | 
|---|---|
| 功能说明 | 启用DE, 设置de模块的timing参数 | 
| 参数定义 | 结构体 aic_panel, ms延时毫秒 | 
| 返回值 | void | 
| 注意事项 | 
6.2.6.3.4.9. panel_de_timing_disable¶
| 接口定义 | void panel_de_timing_disable(struct aic_panel *panel, u32 ms) | 
|---|---|
| 功能说明 | 禁用DE, 设置de模块的timing参数 | 
| 参数定义 | 结构体 aic_panel, ms延时毫秒 | 
| 返回值 | void | 
| 注意事项 | 
6.2.6.3.4.10. panel_mipi_send_perpare¶
| 接口定义 | void panel_mipi_send_perpare(struct aic_panel *panel) | 
|---|---|
| 功能说明 | 将mipi-dsi通道切换到command mode, 准备好给mipi屏幕发送初始化命令 | 
| 参数定义 | 结构体 aic_panel | 
| 返回值 | void | 
| 注意事项 | 在mipi屏幕发送初始化命令前要先调用这个函数,以确保mipi屏幕收到正确的初始化命令 | 
6.2.6.3.4.11. panel_send_command¶
| 接口定义 | void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel) | 
|---|---|
| 功能说明 | 给mipi屏幕发送初始化命令 | 
| 参数定义 | 结构体 aic_panel , 初始化序列大小size, 初始化序列 para_cmd | 
| 返回值 | void | 
| 注意事项 | 
6.2.6.3.4.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通道正常工作 | 
6.2.6.3.4.13. panel_dsi_generic_send_seq¶
| 接口定义 | #define panel_dsi_generic_send_seq(panel, seq…) | 
|---|---|
| 功能说明 | 发送屏厂根据 mipi 协议扩展的 command | 
| 参数定义 | 结构体 aic_panel,seq: init command | 
| 返回值 | 0: 成功, 负数:失败 | 
| 注意事项 |