打印
[公司承接]

iMX8M系列技术贴 |UBOOT添加新的显示支持

[复制链接]
386|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
琳子|  楼主 | 2022-1-6 16:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
价格:1 元
pi, ip, mx, AC, AD
OKMX8MM-C开发板基于NXP公司的i.MX8MMini 四核64位处理器设计,采用核心板+底板结构,主频最高1.8GHz,Cortex-A53架构;2GB DDR4 RAM,支持一个通用型Cortex®-M4 400MHz内核处理器提供多种外设接口,如MIPI-CSI、MIPI-DSIUSB、PCIe、UART 、eCSPI 、IIC和千兆以太网。本文主要讲解OKMX8MM-C开发板平台uboot添加新的显示支持。一、MIPI接口能够连接的显示设备
OKMX8MM-C开发板只有一个MIPI DSI显示接口,这个接口除了可以连接MIPI显示屏,还可以通过MIPI转LVDS模块,连接LVDS显示屏或HDMI显示屏。
其中MIPI显示屏还分为需要配置和不需要配置的。

1、不需要配置的MIPI屏
MIPI接口的显示屏分为需要DSI进入命令模式配置后才能显示的MIPI屏和不需要配置的MIPI屏。不需要配置的MIPI屏比较简单,只要MIPI DSI接口正常输出信号就能正常显示,飞凌嵌入式OKMX8MM-C开发板提供的1024x600分辨率的7寸MIPI屏就是一块不需要配置的MIPI屏,它默认就工作在4lanes高速模式下,只需要将CPU内的显示相关的模块配置好,并让其开始工作,MIPI屏就能够正常显示。
2、需要配置的MIPI屏
需要配置的MIPI屏,DSI接口在输出显示信号前需要进入命令模式对显示屏进行配置,配置参数一般由屏体厂家提供。NXP i.MX8MM 评估套件使用的OLED屏RM67191,就是一款需要配置的MIPI显示屏。
3、MIPI转LVDS和HDMI模块
这个模块能将MIPI信号转换为LVDS或HDMI信号,通过这个模块可以连接LVDS显示屏或者HDMI显示屏。MIPI转LVDS&HDMI模块需要通过I2C配置转接,将包含对应的显示屏的显示参数等信息配置到芯片内,然后MIPI接口输出对应的显示信号。
二、UBOOT阶段的**显示
OKMX8MM-C开发板默认添加了
1024x600的7寸屏(MIPI7);
自定义7MIPI显示(MIPICUSTOM);
MIPI转HDMI的1920x1080 (MIPI2HDMI1920x1080);
1280x720 (MIPI2HDMI1280x720);
640x480 (MIPI2HDMI640x480);
10.1寸1280x800LVDS显示屏(MIPI2HDMI1280x800);
自定义MIPI转LVDS(MIPI2HDMICUSTOM)。
小编截取了MIPI7和MIPI2HDMI_1280x720的完整的显示参数,分别对应了直接连接MIPI屏和通过MIPI转LVDS&HDMI模块连接LVDS或HDMI显示屏。


struct display_info_t const displays[] = {
{
.bus = LCDIF_BASE_ADDR,
.addr = 0,
.pixfmt = 24,
.detect = NULL,
.enable = do_enable_mipi_led,
.mode = {
.name = "MIPI7",
.refresh = 60,
.xres = 1024 ,
.yres = 600,
.pixclock = 22733, /* 43987200 */
.left_margin = 48,
.right_margin = 40,
.upper_margin = 16,
.lower_margin = 13,
.hsync_len = 48,
.vsync_len = 3,
.sync = FB_SYNC_EXT,
.vmode = FB_VMODE_NONINTERLACED } }, ... {
.bus = LCDIF_BASE_ADDR,
.addr = 0,
.pixfmt = 24,
.detect = NULL,
.enable = do_enable_mipi2hdmi,
.mode = {
.name = "MIPI2HDMI_1280x720",
.refresh = 60,
.xres = 1280,
.yres = 720,
.pixclock = 13468, //74250000
.left_margin = 220,
.right_margin = 110,
.upper_margin = 20,
.lower_margin = 5,
.hsync_len = 40,
.vsync_len = 5,
.sync = FB_SYNC_EXT,
.vmode = FB_VMODE_NONINTERLACED
}
},
...
}
1、如何选择显示参数UBOOT阶段通过读取UBOOT的环境变量panel的值来判定使用哪一组显示参数,可以通过UBOOT命令行或者UBOOT菜单设置panel的值,方法可以参考飞凌嵌入式提供的用户手册。UBOOT代码通过判断哪组参数的mode字段的name值和panel的值相等就选择哪组参数,例如panel的值等于MIPI7,那么就会选择MIPI7对应的那组显示参数,也就是飞凌嵌入式提供的1024x600分辨率的7寸MIPI屏。2、自定义参数是什么意思我们在调试显示的时候需要修改panel对应的显示参数结构体内的参数,自定义参数是指可以通过UBOOT命令行设置环境变量来修改显示参数结构体内的参数。自定义参数的用法是panel的值设置为MIPI2HDMI_CUSTOM或MIPI_CUSTOM,代码通过读取环境变量customvideomode,然后解析xres、yres等参数的值替显示参数结构体内的xres、yres等参数,其代码实现如下。

int board_video_skip(void)
{
int i;
int ret = 0;
char const *panel = env_get("panel");
if (!panel) {
...
} else {
for (i = 0; i < display_count; i++) {
if (!strcmp(panel, displays.mode.name))
break;
}
}
if (i < display_count) {
if(!strcmp(panel, "MIPI_CUSTOM") || !strcmp(panel, "MIPI2HDMI_CUSTOM")) {
char const* options = env_get("custom_video_mode");
char *opt = strdup(options);
get_mode_frome_env(&displays, opt);
}
...

static void get_mode_frome_env(struct display_info_t *dev, char *options) {
char *opt;
while ((opt = strsep(&options, ",")) != NULL) {
if (!*opt)
continue;
if (!strncmp(opt, "xres=", 5)) {
dev->mode.xres = simple_strtoul(opt + 5, NULL, 0);
} else if (!strncmp(opt, "yres=", 5)) {
dev->mode.yres = simple_strtoul(opt + 5, NULL, 0);
} else if (!strncmp(opt, "pixclock=", 9)) {
dev->mode.pixclock = simple_strtoul(opt + 9, NULL, 0);
} else if (!strncmp(opt, "left_margin=", 12)) {
dev->mode.left_margin = simple_strtoul(opt + 12, NULL, 0);
} else if (!strncmp(opt, "right_margin=", 13)) {
dev->mode.right_margin = simple_strtoul(opt + 13, NULL, 0);
} else if (!strncmp(opt, "upper_margin=", 13)) {
dev->mode.upper_margin = simple_strtoul(opt + 13, NULL, 0);
} else if (!strncmp(opt, "lower_margin=", 13)) {
dev->mode.lower_margin = simple_strtoul(opt + 13, NULL, 0);
} else if (!strncmp(opt, "hsync_len=", 10)) {
dev->mode.hsync_len = simple_strtoul(opt + 10, NULL, 0);
} else if (!strncmp(opt, "vsync_len=", 10)) {
dev->mode.vsync_len = simple_strtoul(opt + 10, NULL, 0);
} else if (!strncmp(opt, "sync=", 5)) {
dev->mode.sync = simple_strtoul(opt + 5, NULL, 0);
} else if (!strncmp(opt, "vmode=", 6)) {
dev->mode.vmode = simple_strtoul(opt + 6, NULL, 0);
} else if (!strncmp(opt, "refresh=", 8)) {
dev->mode.refresh = simple_strtoul(opt + 8 , NULL, 0);
}
}
printf("use custom mode %s: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %08X, %08X \n ", \
dev->mode.name,dev->mode.refresh, dev->mode.xres, dev->mode.yres, dev->mode.pixclock, \
dev->mode.left_margin, dev->mode.right_margin, dev->mode.upper_margin, dev->mode.lower_margin, \
dev->mode.hsync_len, dev->mode.vsync_len, dev->mode.sync, dev->mode.vmode); }


三、UBOOT新增显示调试
UBOOT新增显示屏时,先确认增加的是哪种类型的显示屏,下面跟着小编一起对不同的显示屏进行调试。
1、MIPI转LVDS和HDMI模块
MIPI转LVDS和HDMI模块,能够正常显示的条件是:
  • 显示结构体内配置当前显示屏的显示参数;
  • I2C下发正确的配置参数到转接模块。
I2C需要下发的配置参数是通过显示参数计算得出,所以当连接LVDS或HDMI显示时,只需要正确配置显示参数就能让UBOOT正常显示**。飞凌嵌入式提供的代码已经默认支持了640x480、1280x720、1920x1080、1280x800四种分辨率,如果选择这几种分辨率的显示屏,直接通过菜单显示即可(LVDS接口分辨率最大支持到1280x800)。如果要添加其它分辨率的显示屏,飞凌嵌入式提供了一组可以自定义显示的参数,只需要将panel的值设置为”MIPI2HDMICUSTOM“,然后设置环境变量customvideo_mode,修改你需要的xres、yres等值后保存环境变量,重启检测能否显示**。在启动的过程可以看到新设置的显示参数,方便验证修改的是否成功。



...
u-boot=> setenv panel MIPI2HDMI_CUSTOM
u-boot=> setenv custom_video_mode xres=1024,yres=768
u-boot=> sa
Saving Environment to MMC... Writing to MMC(1)... OK u-boot=> reset resetting ... ... Loading Environment from MMC... OK use custom mode MIPI2HDMI_CUSTOM: 60, 1024, 768, 12048, 200, 64, 24, 1, 136, 3, 00000004, 00000000 ...


2、不需配置的MIPI显示屏
不需配置的MIPI屏,只需要修改显示参数即可正常显示**。飞凌嵌入式开发板默认支持分辨率为1024x600的显示屏,如需添加新的此类型的显示屏,飞凌嵌入式提供了一组可以自定义显示的参数,只需要将panel的值设置为”MIPICUSTOM“,然后设置环境变量customvideo_mode,修改你需要的xres、yres等值后保存环境变量,重启检测能否显示**。在启动的过程可以看到新设置的显示参数,方便验证修改的是否成功。


... u-boot=> setenv panel MIPI_CUSTOM u-boot=> setenv custom_video_mode xres=800,yres=600,pixclock=20000,refresh=55 u-boot=> sa Saving Environment to MMC... Writing to MMC(1)... OK u-boot=> reset resetting ... ... Loading Environment from MMC... OK use custom mode MIPI_CUSTOM: 55, 800, 600, 20000, 48, 40, 16, 13, 48, 3, 00000004, 00000000 Display: MIPI_CUSTOM (800x600) Video: 800x600x24 ...


3、需要配置的MIPI显示屏
这种显示屏对比不需配置的MIPI显示屏多了一步配置,可以参照原厂提供的RM67191进行修改。
首先,添加一组显示参数,显示参数根据显示屏修改,修改文件board/freescale/imx8mmevk/imx8mmevk.c。

{ .bus = LCDIF_BASE_ADDR, .addr = 0, .pixfmt = 24, .detect = NULL, .enable = do_enable_mipi_led, .mode = { .name = "RM67191_OLED", .refresh = 60, .xres = 1080, .yres = 1920, .pixclock = 7575, /* 132000000 */ .left_margin = 34, .right_margin = 20, .upper_margin = 4, .lower_margin = 10, .hsync_len = 2, .vsync_len = 2, .sync = FB_SYNC_EXT, .vmode = FB_VMODE_NONINTERLACED } }

然后修改这组参数的使能函数


void do_enable_mipi_led(struct display_info_t const *dev) { imx_iomux_v3_setup_multiple_pads(backlight_pads, ARRAY_SIZE(backlight_pads)); gpio_request(
IMX
_
GPIO
_NR(1, 1), "backlight"); gpio_direction_output(IMX_GPIO_NR(1, 1), 0); gpio_request(IMX_GPIO_NR(1, 8), "DSI EN"); gpio_direction_output(IMX_GPIO_NR(1, 8), 0); mdelay(10); gpio_direction_output(IMX_GPIO_NR(1, 8), 1); /* enable the dispmix & mipi phy power domain */ call_imx_sip(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, DISPMIX, true, 0); call_imx_sip(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, MIPI, true, 0); /* Put lcdif out of reset */ disp_mix_bus_rstn_reset(imx8mm_mipi_dsim_plat_data.gpr_base, false); disp_mix_lcdif_clks_enable(imx8mm_mipi_dsim_plat_data.gpr_base, true); /* Setup mipi dsim */ sec_mipi_dsim_setup(&imx8mm_mipi_dsim_plat_data); rm67191_init(); rm67191_dev.name = dev->mode.name; imx_mipi_dsi_bridge_attach(&rm67191_dev); /* attach rm67191 device */ }struct mipi_dsi_client_dev rm67191_dev = { .channel = 0, .lanes = 4, .format = MIPI_DSI_FMT_RGB888, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE, };


修改显示屏驱动drivers/video/rm67191.c,在函数int rm67191lcdsetup(struct mipidsiclientdev *paneldev)添加自己的屏的初始化序列。
修改完成后编译测试
注意:uboot代码不开源,修改代码需要联系销售人员
原文链接:https://www.forlinx.com/article_view_807.html

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

120

主题

140

帖子

2

粉丝