Edit online

屏驱动说明

屏源码位置:Kernel: source/linux-5.10/drivers/video/artinchip/disp/panel/

屏源码位置:bsp/artinchip/drv/display/panel/

新屏驱动适配

新屏驱动支持,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

  1. 修改新屏驱动名字,将屏驱动添加进同级目录下的 Kconfig 和 Makefile 文件。

  2. 重新实现 aic_panel_funcs 结构体中的 prepare 或者 enable 接口,添加屏幕所需的初始化操作。

mipi 屏幕

  1. 在发送 init_sequence 之前需要调用 panel_mipi_send_perpare 确保屏幕能正确无误地接受到命令。

  2. 在发送完 init_sequence 后需要调用 panel_mipi_setup_realmode 设置正确的mipi模式。

  3. panel_dsi.c 中为 mipi-dsi 的 init_sequence 封装了两个接口:

    1. panel_dsi_dcs_send_seq :发送屏厂根据 mipi 协议扩展的 command

    2. panel_dsi_generic_send_seq :发送 mipi 协议标准的 command

额外 gpio

  1. 结构体默认支持两个 gpio
    1. 一个 enable gpio , 可用于控制背光,使能屏幕

    2. 一个 sleep gpio, 可用于控制屏幕供电,休眠唤醒

如果需要添加更多 gpio 引脚,可参考 panel_dsi_wuxga_7in.c/panel_srgb_ili8961.c

时序参数

  1. LCD 的 timing 参数,既可以在驱动中使用 hardcode 的方式设置 struct videomode,也可以在 board.dts 中通过 display-timings 节点设置。

  2. 如果 timing 参数采用 hardcode 方式设置,board.dts 必须删除 display-timings 节点。不然屏驱动源码中的 timing 参数会被 dts 中的 timing 参数覆盖。其他屏参数不受此影响。

新屏驱动适配

LCD屏驱动,即 panel,本质上是一个回调函数和屏参的集合。新屏适配实际上是重新实现一个 struct aic_panel 结构体。

新增一款屏驱动,可以在 panel 源码目录下,根据屏接口选择一个模板,在模版的基础上进行修改。

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

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

以 MIPI-DSI 接口为例:

  1. 拷贝一份模板文件,命名为 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')
  2. 修改 struct aic_panel 的命名,并将其注册。

    1. 将 struct aic_panel 添加到 panel_com.c 文件的 panels[] 指针数组中

    2. panel_com.h 文件中 extern struct 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;
  3. 修改 struct display_timing 结构体,根据 LCD 屏幕规格书修改时序参数。

  4. 重新实现 aic_panel_funcs 结构体中的 prepare 或者 enable 接口,添加初始化操作。

对于 MIPI-DSI 接口屏幕

  1. 在发送 init_sequence 之前需要调用 panel_mipi_send_perpare 以确保屏幕能正确无误地接受到命令。
  2. 在发送完 init_sequence 后需要调用 panel_mipi_setup_realmode 设置正确的mipi模式。
  3. panel_dsi.c 为 MIPI-DSI 的 init_sequence 封装了两个接口:
    1. panel_dsi_dcs_send_seq:发送屏厂根据 mipi 协议扩展的 command
    2. panel_dsi_generic_send_seq:发送 mipi 协议标准的 command

对于 MIPI-DBI 接口屏幕

  1. panel_dbi.c 为 MIPI-DBI 的 init_sequence 封装了 enable 接口 panel_dbi_default_enable

数据结构

  • 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;
    };
  • 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;
        };
    };
    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提供,供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);
    };
    /* 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, s8 *data, u32 len);
        int (*di_set_videomode)(struct videomode *vm, int enable);
        int (*timing_enable)(void);
        int (*timing_disable)(void);
    };
    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;
        bool data_mirror;
    };
    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_default_get_video_mode
接口定义 int panel_default_get_video_mode(struct aic_panel *panel, struct videomode *vm)
功能说明 panel提供的回调,供fb调用,传递从dts中解析的timing参数
参数定义 videomode:包含屏幕的timing参数
返回值 0:成功
注意事项 -
7. panel_parse_dts
接口定义 int panel_parse_dts(struct panel_comp *p, struct device *dev);
功能说明 解析board.dts中的panel结点
参数定义 panel_comp ,结构体device
返回值 0:成功
注意事项 -
8. panel_di_enable
接口定义 void panel_di_enable(struct aic_panel *panel, u32 ms)
功能说明 使能相应的DI接口
参数定义 结构体 aic_panel, ms延时毫秒
返回值 void
注意事项 -
9. panel_di_disable
接口定义 void panel_di_disable(struct aic_panel *panel, u32 ms)
功能说明 禁用相应的DI接口
参数定义 结构体 aic_panel, ms延时毫秒
返回值 void
注意事项 -
10. panel_de_timing_enable
接口定义 void panel_de_timing_enable(struct aic_panel *panel, u32 ms)
功能说明 启用DE, 设置de模块的timing参数
参数定义 结构体 aic_panel, ms延时毫秒
返回值 void
注意事项 -
11. panel_de_timing_disable
接口定义 void panel_de_timing_disable(struct aic_panel *panel, u32 ms)
功能说明 禁用DE, 设置de模块的timing参数
参数定义 结构体 aic_panel, ms延时毫秒
返回值 void
注意事项 -
12. panel_mipi_send_perpare
接口定义 void panel_mipi_send_perpare(struct aic_panel *panel)
功能说明 将mipi-dsi通道切换到command mode, 准备好给mipi屏幕发送初始化命令
参数定义 结构体 aic_panel
返回值 void
注意事项 在mipi屏幕发送初始化命令前要先调用这个函数,以确保mipi屏幕收到正确的初始化命令
13. panel_send_command
接口定义 void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel)
功能说明 给mipi屏幕发送初始化命令
参数定义 结构体 aic_panel , 初始化序列大小size, 初始化序列 para_cmd
返回值 void
注意事项 -
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通道正常工作
15. panel_dsi_generic_send_seq
接口定义 #define panel_dsi_generic_send_seq(panel, seq…)
功能说明 发送屏厂根据 mipi 协议扩展的 command
参数定义 结构体 aic_panel,seq: init command
返回值 0: 成功, 负数:失败
注意事项 -
16. panel_dsi_dcs_send_seq
接口定义 #define panel_dsi_dcs_send_seq(panel, seq…)
功能说明 发送 mipi 协议标准的 command
参数定义 结构体 aic_panel,seq: init command
返回值 0: 成功, 负数:失败
注意事项 -
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
注意事项 -
18. panel_mipi_setup_realmode
接口定义 void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel)
功能说明 将mipi-dsi通道切换回正确的模式
参数定义 结构体 aic_panel
返回值 void
注意事项 在mipi屏幕发送完初始化命令后调用这个函数,以确保mipi通道正常工作
19. panel_dsi_generic_send_seq
接口定义 #define panel_dsi_generic_send_seq(panel, seq…)
功能说明 发送屏厂根据 mipi 协议扩展的 command
参数定义 结构体 aic_panel,seq: init command
返回值 0: 成功, 负数:失败
注意事项
20. panel_dsi_dcs_send_seq
接口定义 #define panel_dsi_dcs_send_seq(panel, seq…)
功能说明 发送 mipi 协议标准的 command
参数定义 结构体 aic_panel,seq: init command
返回值 0: 成功, 负数:失败
注意事项
21. panel_dbi_default_enable
接口定义 int panel_dbi_default_enable(struct aic_panel *panel)
功能说明 mipi-dbi 接口的默认使能函数, 发送 mipi-dbi 的 init_sequence
参数定义 结构体 aic_panel
返回值 0: 成功, 负数:失败
注意事项 注意事项

屏驱动说明

新屏驱动适配

LCD屏驱动,即 panel,本质上是一个回调函数和屏参的集合。新屏适配实际上是重新实现一个 struct aic_panel 结构体。

新增一款屏驱动,可以在 panel 源码目录下,根据屏接口选择一个模板,在模版的基础上进行修改。

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

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

以下以 MIPI-DSI 接口为例演示配置步骤:
  1. 拷贝一份模板文件,命名为 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')
  2. 修改 struct aic_panel 的命名,并将其注册。
    1. 将 struct aic_panel 添加到 panel_com.c 文件的 panels[] 指针数组中

    2. panel_com.h 文件中 extern struct 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;
  3. 修改 struct display_timing 结构体,根据 LCD 屏幕规格书修改时序参数。

  4. 重新实现 aic_panel_funcs 结构体中的 prepare 或者 enable 接口,添加初始化操作。