屏驱动说明
屏源码位置:Kernel: source/linux-5.10/drivers/video/artinchip/disp/panel/
屏源码位置:bsp/artinchip/drv/display/panel/
新屏驱动适配
如果是 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
- 结构体默认支持两个 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 参数覆盖。其他屏参数不受此影响。
新屏驱动适配
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
文件中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;
-
-
修改
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
数据结构
- 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_funcspanel提供,供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_callbackspanel无需实现,由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_rgbrgb接口屏幕参数
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_lvdslvds接口屏幕参数
struct panel_lvds { enum lvds_mode mode; enum lvds_link_mode link_mode; };
- struct panel_dsimipi-dsi接口屏幕参数
struct panel_dsi { enum dsi_mode mode; enum dsi_format format; unsigned int lane_num; };
- struct
panel_dbimipi-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; };
函数接口
接口定义 | int panel_default_prepare(struct aic_panel *panel) |
---|---|
功能说明 | 默认的prepare接口函数,使能regulator |
参数定义 | 结构体 aic_panel |
返回值 | 0: 成功 负数:失败 |
注意事项 | - |
接口定义 | int panel_default_enable(struct aic_panel *panel) |
---|---|
功能说明 | 默认的enable接口函数,设置de模块的timing参数,使能相应的DI接口,开启背光 |
参数定义 | 结构体 aic_panel |
返回值 | 0:成功 |
注意事项 | - |
接口定义 | int panel_default_unprepare(struct aic_panel *panel) |
---|---|
功能说明 | 默认的unprepare接口函数,禁用regulator |
参数定义 | 结构体 aic_panel |
返回值 | 0:成功 |
注意事项 | - |
接口定义 | int panel_default_disable(struct aic_panel *panel) |
---|---|
功能说明 | 默认的disable接口函数,禁用背光,禁用DI接口,禁用DE |
参数定义 | 结构体 aic_panel |
返回值 | 0:成功 |
注意事项 | - |
接口定义 | int panel_register_callback(struct aic_panel *panel, struct aic_panel_callbacks *pcallback) |
---|---|
功能说明 | DE,DI提供的回调函数,供panel调用 |
参数定义 | 结构体 aic_panel |
返回值 | 0:成功 |
注意事项 | - |
接口定义 | int panel_default_get_video_mode(struct aic_panel *panel, struct videomode *vm) |
---|---|
功能说明 | panel提供的回调,供fb调用,传递从dts中解析的timing参数 |
参数定义 | videomode:包含屏幕的timing参数 |
返回值 | 0:成功 |
注意事项 | - |
接口定义 | int panel_parse_dts(struct panel_comp *p, struct device *dev); |
---|---|
功能说明 | 解析board.dts中的panel结点 |
参数定义 | panel_comp ,结构体device |
返回值 | 0:成功 |
注意事项 | - |
接口定义 | void panel_di_enable(struct aic_panel *panel, u32 ms) |
---|---|
功能说明 | 使能相应的DI接口 |
参数定义 | 结构体 aic_panel, ms延时毫秒 |
返回值 | void |
注意事项 | - |
接口定义 | void panel_di_disable(struct aic_panel *panel, u32 ms) |
---|---|
功能说明 | 禁用相应的DI接口 |
参数定义 | 结构体 aic_panel, ms延时毫秒 |
返回值 | void |
注意事项 | - |
接口定义 | void panel_de_timing_enable(struct aic_panel *panel, u32 ms) |
---|---|
功能说明 | 启用DE, 设置de模块的timing参数 |
参数定义 | 结构体 aic_panel, ms延时毫秒 |
返回值 | void |
注意事项 | - |
接口定义 | void panel_de_timing_disable(struct aic_panel *panel, u32 ms) |
---|---|
功能说明 | 禁用DE, 设置de模块的timing参数 |
参数定义 | 结构体 aic_panel, ms延时毫秒 |
返回值 | void |
注意事项 | - |
接口定义 | void panel_mipi_send_perpare(struct aic_panel *panel) |
---|---|
功能说明 | 将mipi-dsi通道切换到command mode, 准备好给mipi屏幕发送初始化命令 |
参数定义 | 结构体 aic_panel |
返回值 | void |
注意事项 | 在mipi屏幕发送初始化命令前要先调用这个函数,以确保mipi屏幕收到正确的初始化命令 |
接口定义 | void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel) |
---|---|
功能说明 | 给mipi屏幕发送初始化命令 |
参数定义 | 结构体 aic_panel , 初始化序列大小size, 初始化序列 para_cmd |
返回值 | void |
注意事项 | - |
接口定义 | void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel) |
---|---|
功能说明 | 将mipi-dsi通道切换回正确的模式 |
参数定义 | 结构体 aic_panel |
返回值 | void |
注意事项 | 在mipi屏幕发送完初始化命令后调用这个函数,以确保mipi通道正常工作 |
接口定义 | #define panel_dsi_generic_send_seq(panel, seq…) |
---|---|
功能说明 | 发送屏厂根据 mipi 协议扩展的 command |
参数定义 | 结构体 aic_panel,seq: init command |
返回值 | 0: 成功, 负数:失败 |
注意事项 | - |
接口定义 | #define panel_dsi_dcs_send_seq(panel, seq…) |
---|---|
功能说明 | 发送 mipi 协议标准的 command |
参数定义 | 结构体 aic_panel,seq: init command |
返回值 | 0: 成功, 负数:失败 |
注意事项 | - |
接口定义 |
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 |
注意事项 | - |
接口定义 | void panel_send_command(u8 *para_cmd, u32 size, struct aic_panel *panel) |
---|---|
功能说明 | 将mipi-dsi通道切换回正确的模式 |
参数定义 | 结构体 aic_panel |
返回值 | void |
注意事项 | 在mipi屏幕发送完初始化命令后调用这个函数,以确保mipi通道正常工作 |
接口定义 | #define panel_dsi_generic_send_seq(panel, seq…) |
---|---|
功能说明 | 发送屏厂根据 mipi 协议扩展的 command |
参数定义 | 结构体 aic_panel,seq: init command |
返回值 | 0: 成功, 负数:失败 |
注意事项 |
接口定义 | #define panel_dsi_dcs_send_seq(panel, seq…) |
---|---|
功能说明 | 发送 mipi 协议标准的 command |
参数定义 | 结构体 aic_panel,seq: init command |
返回值 | 0: 成功, 负数:失败 |
注意事项 |
接口定义 | 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
-
拷贝一份模板文件,命名为 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
文件中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;
-
-
修改
struct display_timing
结构体,根据 LCD 屏幕规格书修改时序参数。 -
重新实现 aic_panel_funcs 结构体中的
prepare
或者enable
接口,添加初始化操作。