diff --git a/arch/arm/include/asm/mach-imx/fbpanel.h b/arch/arm/include/asm/mach-imx/fbpanel.h index e9fc9042b2407d708709f782d8426387d74bb41a..05267a033c4c60e273d9c70e6e8473efbb992a96 100644 --- a/arch/arm/include/asm/mach-imx/fbpanel.h +++ b/arch/arm/include/asm/mach-imx/fbpanel.h @@ -9,7 +9,15 @@ #include <ipu_pixfmt.h> struct display_info_t { - int bus; /* (bus >> 8) is gpio to enable bus if <>0 */ + union { + int bus; /* (bus >> 8) is gpio to enable bus if <>0 */ + struct { + unsigned char bus_num; + unsigned char bus_gp; + unsigned char enable_gp; + unsigned char spare; + }; + }; int addr; int pixfmt; int (*detect)(struct display_info_t const *dev); @@ -21,15 +29,32 @@ struct display_info_t { #define FB_LCD2 2 #define FB_LVDS 3 #define FB_LVDS2 4 -#define FB_COUNT 5 +#define FB_MIPI 5 +#define FB_MIPI_BRIDGE 6 /* Not included in FB_COUNT */ +#define FB_COUNT 6 int fbtype; #define FBF_MODESTR 1 #define FBF_JEIDA 2 #define FBF_SPLITMODE 4 #define FBF_SPI 8 -#define FBF_BKLIT_LOW_ACTIVE 0x10 -#define FBF_BKLIT_DTB 0x20 +#define FBF_BKLIT_LOW_ACTIVE 0x010 +#define FBF_BKLIT_DTB 0x020 +#define FBF_PINCTRL 0x040 +#define FBF_ENABLE_GPIOS_ACTIVE_LOW 0x080 +#define FBF_MODE_SKIP_EOT 0x100 +#define FBF_MODE_VIDEO 0x200 +#define FBF_MODE_VIDEO_BURST 0x400 +#define FBF_MIPI_CMDS 0x800 +#define FBF_DSI_LANE_SHIFT 16 +#define FBF_DSI_LANES_1 (0x1 << FBF_DSI_LANE_SHIFT) +#define FBF_DSI_LANES_2 (0x2 << FBF_DSI_LANE_SHIFT) +#define FBF_DSI_LANES_3 (0x3 << FBF_DSI_LANE_SHIFT) +#define FBF_DSI_LANES_4 (0x4 << FBF_DSI_LANE_SHIFT) + +#define FBF_LTK080A60A004T (FBF_MODE_SKIP_EOT | FBF_MODE_VIDEO | FBF_MODE_VIDEO_BURST | FBF_MIPI_CMDS | FBF_DSI_LANES_4 | FBF_PINCTRL) +#define FBF_M101NWWB (FBF_MODE_SKIP_EOT | FBF_MODE_VIDEO | FBF_MODE_VIDEO_BURST | FBF_MIPI_CMDS | FBF_DSI_LANES_4) + int fbflags; struct fb_videomode mode; }; @@ -43,6 +68,7 @@ void board_enable_lvds2(const struct display_info_t *di, int enable); void fbp_enable_fb(struct display_info_t const *di, int enable); int fbp_detect_i2c(struct display_info_t const *di); void fbp_setup_display(const struct display_info_t *displays, int cnt); +void fbp_setup_env_cmds(void); #define VD_1280_720M_60(_mode, _detect, _bus, _addr) VDF_1280_720M_60(_mode, "1280x720M@60", RGB24, FBF_MODESTR, _detect, _bus, _addr) #define VD_1920_1080M_60(_mode, _detect, _bus, _addr) VDF_1920_1080M_60(_mode, "1920x1080M@60", RGB24, FBF_MODESTR, _detect, _bus, _addr) @@ -90,6 +116,8 @@ void fbp_setup_display(const struct display_info_t *displays, int cnt); #define VD_SHARP_LQ101K1LY04(_mode, _detect, _bus, _addr) VDF_SHARP_LQ101K1LY04(_mode, "sharp-LQ101K1LY04", RGB24, FBF_JEIDA, _detect, _bus, _addr) #define VD_WXGA(_mode, _detect, _bus, _addr) VDF_WXGA(_mode, "wxga", RGB24, 0, _detect, _bus, _addr) #define VD_WXGA_J(_mode, _detect, _bus, _addr) VDF_WXGA(_mode, "wxga_j", RGB24, FBF_JEIDA, _detect, _bus, _addr) +#define VD_LTK080A60A004T(_mode, _detect, _bus, _addr) VDF_LTK080A60A004T(_mode, "ltk080a60a004t", RGB24, FBF_LTK080A60A004T, _detect, _bus, _addr) +#define VD_MIPI_M101NWWB(_mode, _detect, _bus, _addr) VDF_MIPI_M101NWWB(_mode, "m101nwwb", RGB24, FBF_M101NWWB, _detect, _bus, _addr) #define VD_LD070WSVGA(_mode, _detect, _bus, _addr) VDF_LD070WSVGA(_mode, "ld070wsvga", RGB24, 0, _detect, _bus, _addr) #define VD_SVGA(_mode, _detect, _bus, _addr) VDF_SVGA(_mode, "svga", RGB666, FBF_MODESTR, _detect, _bus, _addr) #define VD_WVGA_TX23D200_24(_mode, _detect, _bus, _addr) VDF_WVGA_TX23D200(_mode, "tx23d200_24", RGB24, 0, _detect, _bus, _addr) @@ -957,6 +985,46 @@ void fbp_setup_display(const struct display_info_t *displays, int cnt); }\ } +#define VDF_LTK080A60A004T(_mode, _name, _fmt, _flags, _detect, _bus, _addr) \ +{\ + VD_HEADER(_mode, _fmt, _flags, _detect, _bus, _addr),\ + .mode = {\ + .name = _name,\ + .refresh = 60,\ + .xres = 1200,\ + .yres = 1920,\ + .pixclock = 1000000000000ULL/120000000, /*((1200+60+42+1)*(1920+25+35+1)*60), */\ + .left_margin = 60,\ + .right_margin = 42,\ + .upper_margin = 25,\ + .lower_margin = 35,\ + .hsync_len = 1,\ + .vsync_len = 1,\ + .sync = FB_SYNC_EXT,\ + .vmode = FB_VMODE_NONINTERLACED\ + }\ +} + +#define VDF_MIPI_M101NWWB(_mode, _name, _fmt, _flags, _detect, _bus, _addr) \ +{\ + VD_HEADER(_mode, _fmt, _flags, _detect, _bus, _addr),\ + .mode = {\ + .name = _name,\ + .refresh = 60,\ + .xres = 1280,\ + .yres = 800,\ + .pixclock = 1000000000000ULL/((1280+5+123+1)*(800+3+24+1)*60),\ + .left_margin = 5,\ + .right_margin = 123,\ + .upper_margin = 3,\ + .lower_margin = 24,\ + .hsync_len = 1,\ + .vsync_len = 1,\ + .sync = FB_SYNC_EXT,\ + .vmode = FB_VMODE_NONINTERLACED\ + }\ +} + #define VDF_LD070WSVGA(_mode, _name, _fmt, _flags, _detect, _bus, _addr) \ {\ VD_HEADER(_mode, _fmt, _flags, _detect, _bus, _addr),\ diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index d0e2b4962c70eba293a1df757f1374962efea318..6e1f4b99cbeebc3268f835b9f71cf5e36a553a27 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -33,9 +33,11 @@ obj-$(CONFIG_SYS_I2C_MXC) += i2c-mxv7.o obj-$(CONFIG_ENV_IS_IN_MMC) += mmc_env.o endif -ifeq ($(SOC),$(filter $(SOC),mx5 mx6 mx7)) +ifeq ($(SOC),$(filter $(SOC),mx5 mx6 mx7 mx8m)) +ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),) obj-$(CONFIG_CMD_FBPANEL) += fbpanel.o endif +endif ifeq ($(SOC),$(filter $(SOC),mx6 mx7)) obj-y += cache.o init.o diff --git a/arch/arm/mach-imx/fbpanel.c b/arch/arm/mach-imx/fbpanel.c index 742f33ca6ceb5d25604fe0b19e6d5e6e7323458e..6be47e329aa44f7edbb378f016aa9411656d380d 100644 --- a/arch/arm/mach-imx/fbpanel.c +++ b/arch/arm/mach-imx/fbpanel.c @@ -6,14 +6,19 @@ #include <errno.h> #include <asm/arch/clock.h> #include <asm/arch/crm_regs.h> -#if !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && !defined(CONFIG_MX7D) +#if !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && !defined(CONFIG_MX7D) && !defined(CONFIG_MX8M) #include <asm/arch/mxc_hdmi.h> #endif #include <asm/arch/sys_proto.h> +#if defined(CONFIG_MX8M) +#include <asm/arch/video_common.h> +#endif #include <asm/gpio.h> #include <asm/mach-imx/fbpanel.h> #include <asm/io.h> #include <div64.h> +#include <dm/uclass.h> +#include <dt-bindings/gpio/gpio.h> #include <i2c.h> #include <malloc.h> #include <video_fb.h> @@ -63,7 +68,9 @@ static const char *const fbnames[] = { [FB_LCD] = "fb_lcd", [FB_LCD2] = "fb_lcd2", [FB_LVDS] = "fb_lvds", -[FB_LVDS2] = "fb_lvds2" +[FB_LVDS2] = "fb_lvds2", +[FB_MIPI] = "fb_mipi", +[FB_MIPI_BRIDGE] = "mipi_dsi_bridge", }; static const char *const timings_names[] = { @@ -71,7 +78,8 @@ static const char *const timings_names[] = { [FB_LCD] = "t_lcd", [FB_LCD2] = "t_lcd2", [FB_LVDS] = "t_lvds", -[FB_LVDS2] = "t_lvds2" +[FB_LVDS2] = "t_lvds2", +[FB_MIPI] = "t_mipi", }; static const char *const ch_names[] = { @@ -79,7 +87,8 @@ static const char *const ch_names[] = { [FB_LCD] = "", [FB_LCD2] = "", [FB_LVDS] = "ldb/lvds-channel@0", -[FB_LVDS2] = "ldb/lvds-channel@1" +[FB_LVDS2] = "ldb/lvds-channel@1", +[FB_MIPI] = "", }; static const char *const cmd_fbnames[] = { @@ -87,7 +96,8 @@ static const char *const cmd_fbnames[] = { [FB_LCD] = "cmd_lcd", [FB_LCD2] = "cmd_lcd2", [FB_LVDS] = "cmd_lvds", -[FB_LVDS2] = "cmd_lvds2" +[FB_LVDS2] = "cmd_lvds2", +[FB_MIPI] = "cmd_mipi", }; static const char *const backlight_names[] = { @@ -95,7 +105,8 @@ static const char *const backlight_names[] = { [FB_LCD] = "backlight_lcd", [FB_LCD2] = "backlight_lcd2", [FB_LVDS] = "backlight_lvds", -[FB_LVDS2] = "backlight_lvds2" +[FB_LVDS2] = "backlight_lvds2", +[FB_MIPI] = "backlight_mipi", }; static const char *const pwm_names[] = { @@ -103,7 +114,8 @@ static const char *const pwm_names[] = { [FB_LCD] = "pwm_lcd", [FB_LCD2] = "pwm_lcd2", [FB_LVDS] = "pwm_lvds", -[FB_LVDS2] = "pwm_lvds2" +[FB_LVDS2] = "pwm_lvds2", +[FB_MIPI] = "pwm_mipi", }; static const char *const short_names[] = { @@ -111,7 +123,8 @@ static const char *const short_names[] = { [FB_LCD] = "lcd", [FB_LCD2] = "lcd2", [FB_LVDS] = "lvds", -[FB_LVDS2] = "lvds2" +[FB_LVDS2] = "lvds2", +[FB_MIPI] = "mipi", }; static const char *const timings_properties[] = { @@ -158,6 +171,10 @@ static void __board_enable_lvds2(const struct display_info_t *di, int enable) { } +static void __board_enable_mipi(const struct display_info_t *di, int enable) +{ +} + void board_pre_enable(const struct display_info_t *di) __attribute__((weak, alias("__board_pre_enable"))); void board_enable_hdmi(const struct display_info_t *di, int enable) @@ -168,6 +185,8 @@ void board_enable_lvds(const struct display_info_t *di, int enable) __attribute__((weak, alias("__board_enable_lvds"))); void board_enable_lvds2(const struct display_info_t *di, int enable) __attribute__((weak, alias("__board_enable_lvds2"))); +void board_enable_mipi(const struct display_info_t *di, int enable) + __attribute__((weak, alias("__board_enable_mipi"))); static unsigned get_fb_available_mask(const struct display_info_t *di, int cnt) { @@ -220,6 +239,7 @@ static void setup_cmd_fb(unsigned fb, const struct display_info_t *di, char *buf const char *buf_start = buf; const struct fb_videomode *mode; const char * fmt; + unsigned fb1 = (fb == FB_MIPI) ? FB_MIPI_BRIDGE : fb; if (env_get("cmd_frozen") && env_get(cmd_fbnames[fb])) return; /* don't override if already set */ @@ -237,14 +257,21 @@ static void setup_cmd_fb(unsigned fb, const struct display_info_t *di, char *buf } } if (!mode_str) { - sz = snprintf(buf, size, "fdt set %s status disabled", fbnames[fb]); + sz = snprintf(buf, size, "fdt set %s status disabled", fbnames[fb1]); buf += sz; size -= sz; - if (fb == FB_LCD) + if (fb == FB_LCD) { sz = snprintf(buf, size, ";fdt set lcd status disabled"); - if ((fb == FB_LVDS) || (fb == FB_LVDS2)) { + } else if ((fb == FB_LVDS) || (fb == FB_LVDS2)) { sz = snprintf(buf, size, ";fdt set ldb/lvds-channel@%d status disabled", fb - FB_LVDS); } +#if defined(CONFIG_VIDEO_IMXDCSS) + else if (fb == FB_HDMI) { + sz = snprintf(buf, size, + ";fdt set dcss status disabled" + ";fdt set sound_hdmi status disabled"); + } +#endif env_set(cmd_fbnames[fb], buf_start); return; } @@ -255,7 +282,7 @@ static void setup_cmd_fb(unsigned fb, const struct display_info_t *di, char *buf if (fb == FB_LVDS) lvds_enabled = 1; - sz = snprintf(buf, size, "fdt set %s status okay;", fbnames[fb]); + sz = snprintf(buf, size, "fdt set %s status okay;", fbnames[fb1]); buf += sz; size -= sz; if ((fb == FB_LVDS2) && !lvds_enabled) { @@ -279,11 +306,10 @@ static void setup_cmd_fb(unsigned fb, const struct display_info_t *di, char *buf fmt = rgb666; } - if (di && (fb >= FB_LCD)) { + if (di && (fb >= FB_LCD) && (fb != FB_MIPI)) { #if defined(CONFIG_MX6SX) || defined(CONFIG_MX7D) sz = snprintf(buf, size, "fdt set %s bus-width <%u>;", short_names[fb], interface_width); - #else sz = snprintf(buf, size, "fdt set %s interface_pix_fmt %s;", fbnames[fb], fmt); @@ -325,6 +351,72 @@ static void setup_cmd_fb(unsigned fb, const struct display_info_t *di, char *buf } } + if (di && (di->fbflags & FBF_PINCTRL)) { + sz = snprintf(buf, size, + "fdt get value pin pinctrl_%s phandle;" + "fdt set %s pinctrl-0 <${pin}>;" + "fdt set %s pinctrl-names default;", + di->mode.name, fbnames[fb1], fbnames[fb1]); + buf += sz; + size -= sz; + } + + i = di->enable_gp; + if (di && i) { + sz = snprintf(buf, size, + "fdt get value gp gpio%u phandle;" + "fdt set %s enable-gpios <${gp} %u %u>;", + (i >> 5) + 1, fbnames[fb], i & 0x1f, + (di->fbflags & FBF_ENABLE_GPIOS_ACTIVE_LOW) ? + GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH); + buf += sz; + size -= sz; + } + + if (di && (fb == FB_MIPI)) { + sz = snprintf(buf, size, "fdt %s %s mode-skip-eot;", + (di->fbflags & FBF_MODE_SKIP_EOT) ? "set" : "rm", + fbnames[fb]); + buf += sz; + size -= sz; + + sz = snprintf(buf, size, "fdt %s %s mode-video;", + (di->fbflags & FBF_MODE_VIDEO) ? "set" : "rm", + fbnames[fb]); + buf += sz; + size -= sz; + + sz = snprintf(buf, size, "fdt %s %s mode-video-burst;", + (di->fbflags & FBF_MODE_VIDEO_BURST) ? "set" : "rm", + fbnames[fb]); + buf += sz; + size -= sz; + + if (di->fbflags & FBF_MIPI_CMDS) { + sz = snprintf(buf, size, + "fdt get value cmds mipi_cmds_%s phandle;" + "fdt set %s mipi_cmds <${cmds}>;", + di->mode.name, fbnames[fb]); + buf += sz; + size -= sz; + } + + sz = snprintf(buf, size, "fdt set %s dsi-lanes <%u>;", + fbnames[fb], (di->fbflags >> FBF_DSI_LANE_SHIFT) & 7); + buf += sz; + size -= sz; + + sz = snprintf(buf, size, + "fdt set backlight_mipi status okay;" + "fdt set lcdif status okay;" + "fdt set mipi_dsi status okay;" + "fdt set mipi_dsi_phy status okay;" + "fdt set mipi_to_lvds status %s;", + (di->addr == 0x2c) ? "okay" : "disabled"); + buf += sz; + size -= sz; + } + if (di && di->pwm_period) { sz = snprintf(buf, size, "fdt get value pwm %s phandle; fdt set %s pwms <${pwm} 0x%x 0x%x>;", pwm_names[fb], backlight_names[fb], 0, di->pwm_period); @@ -381,19 +473,30 @@ static struct display_info_t g_di_temp[FB_COUNT]; int fbp_detect_i2c(struct display_info_t const *di) { int ret; - int gp = di->bus >> 8; +#ifdef CONFIG_DM_I2C + struct udevice *dev, *chip; +#endif + + if (di->bus_gp) + gpio_set_value(di->bus_gp, 1); +#ifdef CONFIG_DM_I2C + ret = uclass_get_device(UCLASS_I2C, di->bus_num, &dev); + if (ret) + return 0; - if (gp) - gpio_set_value(gp, 1); - ret = i2c_set_bus_num(di->bus & 0xff); + ret = dm_i2c_probe(dev, di->addr, 0x0, &chip); +#else + ret = i2c_set_bus_num(di->bus_num); if (ret == 0) ret = i2c_probe(di->addr); - if (gp) - gpio_set_value(gp, 0); +#endif + if (di->bus_gp) + gpio_set_value(di->bus_gp, 0); return (ret == 0); } -int calc_gcd(int a, int b) +#if !defined(CONFIG_MX8M) && !defined(CONFIG_MX51) && !defined(CONFIG_MX53) +static int calc_gcd(int a, int b) { int n; @@ -408,9 +511,10 @@ int calc_gcd(int a, int b) } return a; } +#endif #ifdef CONFIG_MX6SX -void reparent_lvds(int fbtype, int new_parent) +static void reparent_lvds(int fbtype, int new_parent) { struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; int ldb_sel_shift = 9; @@ -423,8 +527,8 @@ void reparent_lvds(int fbtype, int new_parent) readl(&ccm->cs2cdr); /* wait for write */ } -#elif !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && !defined(CONFIG_MX7D) -void reparent_lvds(int fbtype, int new_parent) +#elif !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && !defined(CONFIG_MX7D) && !defined(CONFIG_MX8M) +static void reparent_lvds(int fbtype, int new_parent) { struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; int ldb_sel_shift = (fbtype == FB_LVDS2) ? 12 : 9; @@ -502,7 +606,7 @@ void reparent_lvds(int fbtype, int new_parent) #if defined(CONFIG_MX51) || defined(CONFIG_MX53) int get_pll3_clock(void); -void setup_clock(struct display_info_t const *di) +static void setup_clock(struct display_info_t const *di) { struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; u32 desired_freq, freq; @@ -547,8 +651,8 @@ void setup_clock(struct display_info_t const *di) #endif } -#else -void setup_clock(struct display_info_t const *di) +#elif !defined(CONFIG_MX8M) +static void setup_clock(struct display_info_t const *di) { #if defined(CONFIG_MX7D) struct mxc_ccm_anatop_reg *ccm_anatop = (struct mxc_ccm_anatop_reg *) @@ -784,11 +888,15 @@ void setup_clock(struct display_info_t const *di) : 0)); #endif } +#else +static void setup_clock(struct display_info_t const *di) +{ +} #endif void fbp_enable_fb(struct display_info_t const *di, int enable) { -#if !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && !defined(CONFIG_MX7D) +#if !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && !defined(CONFIG_MX7D) && !defined(CONFIG_MX8M) struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; u32 reg, cscmr2; @@ -805,7 +913,7 @@ void fbp_enable_fb(struct display_info_t const *di, int enable) case FB_LCD: board_enable_lcd(di, enable); break; -#if !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && !defined(CONFIG_MX7D) +#if !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && !defined(CONFIG_MX7D) && !defined(CONFIG_MX8M) case FB_LVDS: #ifdef CONFIG_MX6SX #define GPR_LDB 6 @@ -845,7 +953,7 @@ void fbp_enable_fb(struct display_info_t const *di, int enable) writel(reg, &iomux->gpr[GPR_LDB]); board_enable_lvds(di, enable); break; -#ifndef CONFIG_MX6SX +#if !defined(CONFIG_MX6SX) case FB_LVDS2: reg = readl(&iomux->gpr[2]); cscmr2 = readl(&mxc_ccm->cscmr2); @@ -870,13 +978,16 @@ void fbp_enable_fb(struct display_info_t const *di, int enable) break; #endif #endif + case FB_MIPI: + board_enable_mipi(di, enable); + break; } } static void imx_prepare_display(void) { #if !defined(CONFIG_MX51) && !defined(CONFIG_MX53) && \ - !defined(CONFIG_MX7D) + !defined(CONFIG_MX7D) && !defined(CONFIG_MX8M) struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; int reg; #if !defined(CONFIG_MX6SX) @@ -924,6 +1035,80 @@ static void imx_prepare_display(void) #endif } +struct flags_check { + char c; + int flag; +}; + +static struct flags_check fc1[] = { + { 'm', FBF_MODESTR}, + { 'j', FBF_JEIDA}, + { 's', FBF_SPLITMODE}, + { 0, 0}, +}; + +static struct flags_check fc2[] = { + { 'S', FBF_SPI}, + { 'D', FBF_BKLIT_DTB}, + { 'b', FBF_BKLIT_LOW_ACTIVE}, + { 'P', FBF_PINCTRL}, + { 'l', FBF_ENABLE_GPIOS_ACTIVE_LOW}, + { 's', FBF_MODE_SKIP_EOT}, + { 'v', FBF_MODE_VIDEO}, + { 'B', FBF_MODE_VIDEO_BURST}, + { 'c', FBF_MIPI_CMDS}, + { '4', FBF_DSI_LANES_4}, + { '3', FBF_DSI_LANES_3}, + { '2', FBF_DSI_LANES_2}, + { '1', FBF_DSI_LANES_1}, + { 0, 0}, +}; + +static void check_flags(struct display_info_t *di, const char **pp, struct flags_check *fc_base) +{ + const char *p = *pp; + char c = *p; + + while (1) { + struct flags_check *fc = fc_base; + + while (1) { + if (!fc->c) { + *pp = p; + return; + } + if (c == fc->c) { + di->fbflags |= fc->flag; + p++; + c = *p; + break; + } + fc++; + } + } +} + +static int code_flags(char *p, int size, int flags, struct flags_check *fc_base) +{ + struct flags_check *fc = fc_base; + int cnt = 0; + + while (flags) { + if (!fc->c) + break; + if ((fc->flag & flags) == fc->flag) { + if (size) { + *p++ = fc->c; + size--; + cnt++; + } + flags &= ~fc->flag; + } + fc++; + } + return cnt; +} + static const struct display_info_t * parse_mode( const struct display_info_t *gdi, int cnt, const char *p, unsigned fb, unsigned *prefer) @@ -967,21 +1152,9 @@ static const struct display_info_t * parse_mode( di->mode.name = mode_str; di->enable = fbp_enable_fb; - if (c == 'm') { - di->fbflags |= FBF_MODESTR; - p++; - c = *p; - } - if (c == 'j') { - di->fbflags |= FBF_JEIDA; - p++; - c = *p; - } - if (c == 's') { - di->fbflags |= FBF_SPLITMODE; - p++; - c = *p; - } + check_flags(di, &p, fc1); + c = *p; + if (c == 'b') { pix_fmt = IPU_PIX_FMT_BGR24; p++; @@ -998,21 +1171,19 @@ static const struct display_info_t * parse_mode( } p = endp; di->pixfmt = (value == 24) ? pix_fmt : IPU_PIX_FMT_RGB666; + + check_flags(di, &p, fc2); c = *p; - if (c == 'S') { - di->fbflags |= FBF_SPI; - p++; - c = *p; - } - if (c == 'D') { - di->fbflags |= FBF_BKLIT_DTB; - p++; - c = *p; - } - if (c == 'b') { - di->fbflags |= FBF_BKLIT_LOW_ACTIVE; + if (c == 'G') { p++; + value = simple_strtoul(p, &endp, 10); + if (endp <= p) { + printf("expecting gpio number\n"); + return NULL; + } + p = endp; + di->enable_gp = value; c = *p; } if (c == 'e') { @@ -1028,7 +1199,7 @@ static const struct display_info_t * parse_mode( return NULL; } p = endp; - di->bus = value; + di->bus_num = value; c = *p; if (c == ',') { p++; @@ -1040,6 +1211,17 @@ static const struct display_info_t * parse_mode( p = endp; di->addr = value; c = *p; + if (c == ',') { + p++; + value = simple_strtoul(p, &endp, 10); + if (endp <= p) { + printf("expecting bus gp\n"); + return NULL; + } + p = endp; + di->bus_gp = value; + c = *p; + } } } if (c == 'p') { @@ -1156,18 +1338,10 @@ static void str_mode(char *p, int size, const struct display_info_t *di, unsigne p += count; size -= count; } - if (di->fbflags & FBF_MODESTR) { - *p++ = 'm'; - size--; - } - if (di->fbflags & FBF_JEIDA) { - *p++ = 'j'; - size--; - } - if (di->fbflags & FBF_SPLITMODE) { - *p++ = 's'; - size--; - } + count = code_flags(p, size, di->fbflags, fc1); + p += count; + size -= count; + if ((di->pixfmt == IPU_PIX_FMT_RGB24) || (di->pixfmt == IPU_PIX_FMT_BGR24)) interface_width = 24; @@ -1180,28 +1354,34 @@ static void str_mode(char *p, int size, const struct display_info_t *di, unsigne p += count; size -= count; } - if (di->fbflags & FBF_SPI) { - *p++ = 'S'; - size--; - } - if (di->fbflags & FBF_BKLIT_DTB) { - *p++ = 'D'; - size--; - } - if (di->fbflags & FBF_BKLIT_LOW_ACTIVE) { - *p++ = 'b'; - size--; + count = code_flags(p, size, di->fbflags, fc2); + p += count; + size -= count; + + if (di->enable_gp) { + count = snprintf(p, size, "G%u", di->enable_gp); + if (size > count) { + p += count; + size -= count; + } } if (di->pre_enable) { *p++ = 'e'; size--; } - if (di->bus || di->addr) { - count = snprintf(p, size, "x%x,%x", di->bus, di->addr); + if (di->bus_num || di->addr || di->bus_gp) { + count = snprintf(p, size, "x%x,%x", di->bus_num, di->addr); if (size > count) { p += count; size -= count; } + if (di->bus_gp) { + count = snprintf(p, size, ",%u", di->bus_gp); + if (size > count) { + p += count; + size -= count; + } + } } if (di->pwm_period) { count = snprintf(p, size, "p%d", di->pwm_period); @@ -1281,52 +1461,57 @@ static void print_modes(const struct display_info_t *di, int cnt, unsigned mask) } } +void setup_env_cmds(const struct display_info_t *gdi, int cnt, + const struct display_info_t **displays) +{ + char *buf = malloc(4096); + if (buf) { + unsigned mask = get_fb_available_mask(gdi, cnt); + unsigned fb; + + for (fb = 0; fb < FB_COUNT; fb++) { + if (mask & (1 << fb)) + setup_cmd_fb(fb, displays[fb], buf, 4096); + } + free(buf); + } +} + static const struct display_info_t *select_display( - const struct display_info_t *gdi, int cnt) + const struct display_info_t *gdi, int cnt, + const struct display_info_t **displays) { - const struct display_info_t *disp[FB_COUNT]; const struct display_info_t *di = NULL; unsigned prefer_mask = 0; unsigned fb; - char *buf = malloc(4096); - for (fb = 0; fb < ARRAY_SIZE(disp); fb++) { + for (fb = 0; fb < FB_COUNT; fb++) { unsigned prefer = 0; - disp[fb] = find_disp(gdi, cnt, fb, &prefer); + displays[fb] = find_disp(gdi, cnt, fb, &prefer); if (prefer & 1) prefer_mask |= (1 << fb); } fb = ffs(prefer_mask) - 1; - if (fb < ARRAY_SIZE(disp)) { - di = disp[fb]; + if (fb < FB_COUNT) { + di = displays[fb]; } else { /* default to the 1st one in the list*/ - for (fb = 0; fb < ARRAY_SIZE(disp); fb++) { + for (fb = 0; fb < FB_COUNT; fb++) { if (!di) { - di = disp[fb]; + di = displays[fb]; } else { - if (disp[fb] && ((unsigned)disp[fb] - < (unsigned)di)) - di = disp[fb]; + if (displays[fb] && (displays[fb] < di)) + di = displays[fb]; } } if (!di) { di = find_first_disp(gdi, cnt); if (di) - disp[di->fbtype] = di; - } - } - - if (buf) { - unsigned mask = get_fb_available_mask(gdi, cnt); - - for (fb = 0; fb < ARRAY_SIZE(disp); fb++) { - if (mask & (1 << fb)) - setup_cmd_fb(fb, disp[fb], buf, 4096); + displays[di->fbtype] = di; } - free(buf); } + setup_env_cmds(gdi, cnt, displays); return di; } @@ -1351,6 +1536,10 @@ static int init_display(const struct display_info_t *di) setup_clock(di); #if defined(CONFIG_MX6SX) || defined(CONFIG_MX7D) ret = mxsfb_init(&di->mode, di->pixfmt); +#elif defined(CONFIG_VIDEO_IMXDCSS) + ret = 0; + if (di->fbtype == FB_HDMI) + imx8m_fb_init(&di->mode, 0, di->pixfmt); #else ret = ipuv3_fb_init(&di->mode, (di->fbtype == FB_LCD2) ? 1 : 0, di->pixfmt); @@ -1378,7 +1567,7 @@ static int do_fbpanel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int cnt = g_display_cnt; if (argc < 2) { - print_modes(di, cnt, 0xf); + print_modes(di, cnt, (1 << FB_COUNT) - 1); return 0; } fbname = argv[1]; @@ -1418,7 +1607,14 @@ static int do_fbpanel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) g_di_active = NULL; } } -#if !defined(CONFIG_MX6SX) && !defined(CONFIG_MX7D) +#if defined(CONFIG_VIDEO_IMXDCSS) + imx8m_fb_disable(); + if (!di) + return 0; + ret = init_display(di); + if (ret) + return ret; +#elif !defined(CONFIG_MX6SX) && !defined(CONFIG_MX7D) ipuv3_fb_shutdown(); if (!di) return 0; @@ -1444,13 +1640,19 @@ U_BOOT_CMD(fbpanel, 3, 0, do_fbpanel, "\n" "fbpanel - show all panels"); +static const struct display_info_t *g_disp[FB_COUNT]; + int board_video_skip(void) { - const struct display_info_t *di = select_display(g_displays, g_display_cnt); + const struct display_info_t *di = select_display(g_displays, g_display_cnt, g_disp); + int ret; if (!di) return -EINVAL; - return init_display(di); + ret = init_display(di); + if (di->fbtype == FB_MIPI) + ret = -EINVAL; + return ret; } void fbp_setup_display(const struct display_info_t *displays, int cnt) @@ -1459,3 +1661,8 @@ void fbp_setup_display(const struct display_info_t *displays, int cnt) g_display_cnt = cnt; imx_prepare_display(); } + +void fbp_setup_env_cmds(void) +{ + setup_env_cmds(g_displays, g_display_cnt, g_disp); +}