From 77aac25fd2b3bef689bf989be42e6631e17ede88 Mon Sep 17 00:00:00 2001
From: Troy Kisky <troy.kisky@boundarydevices.com>
Date: Sun, 3 Sep 2017 13:49:13 -0700
Subject: [PATCH] mxsfb: add mxsfb_init/mxsfb_init2 for fbp support

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 arch/arm/include/asm/mach-imx/sys_proto.h |   4 +
 drivers/video/mxsfb.c                     | 159 +++++++++++++++++-----
 2 files changed, 128 insertions(+), 35 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h
index c451d271a85..e8434d16b99 100644
--- a/arch/arm/include/asm/mach-imx/sys_proto.h
+++ b/arch/arm/include/asm/mach-imx/sys_proto.h
@@ -123,6 +123,10 @@ u32 get_ahb_clk(void);
 u32 get_periph_clk(void);
 
 void lcdif_power_down(void);
+struct fb_videomode;
+int mxsfb_init(struct fb_videomode const *mode, uint32_t pixfmt);
+void *mxsfb_init2(void);
+
 
 int mxs_reset_block(struct mxs_register_32 *reg);
 int mxs_wait_mask_set(struct mxs_register_32 *reg, u32 mask, u32 timeout);
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index c00117c8f2c..ad88ae5c894 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -13,6 +13,9 @@
 #include <asm/arch/sys_proto.h>
 #include <linux/errno.h>
 #include <asm/io.h>
+#include <linux/fb.h>
+#include <ipu_pixfmt.h>
+#include <stdio_dev.h>
 
 #include <asm/mach-imx/dma.h>
 
@@ -24,7 +27,7 @@
 
 #define	PS2KHZ(ps)	(1000000000UL / (ps))
 
-static GraphicDevice panel;
+static struct graphic_device panel;
 struct mxs_dma_desc desc;
 
 /**
@@ -50,15 +53,17 @@ __weak void mxsfb_system_setup(void)
  * 	 le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0
  */
 
-static void mxs_lcd_init(GraphicDevice *panel,
+static void mxs_lcd_init(struct graphic_device *panel,
 			struct ctfb_res_modes *mode, int bpp)
 {
 	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
 	uint32_t word_len = 0, bus_width = 0;
 	uint8_t valid_data = 0;
 
+#if !defined(CONFIG_CMD_FBPANEL)
 	/* Kick in the LCDIF clock */
 	mxs_set_lcdclk(MXS_LCDIF_BASE, PS2KHZ(mode->pixclock));
+#endif
 
 	/* Restart the LCDIF block */
 	mxs_reset_block(&regs->hw_lcdif_ctrl_reg);
@@ -154,32 +159,26 @@ void lcdif_power_down(void)
 	mxs_reset_block((struct mxs_register_32 *)&regs->hw_lcdif_ctrl_reg);
 }
 
-void *video_hw_init(void)
+static void __board_video_enable(void)
 {
-	int bpp = -1;
-	char *penv;
-	void *fb;
-	struct ctfb_res_modes mode;
+}
 
-	puts("Video: ");
+void board_video_enable(void)
+	__attribute__((weak, alias("__board_video_enable")));
 
-	/* Suck display configuration from "videomode" variable */
-	penv = env_get("videomode");
-	if (!penv) {
-		puts("MXSFB: 'videomode' variable not set!\n");
-		return NULL;
-	}
-
-	bpp = video_get_params(&mode, penv);
+static struct graphic_device *mxsfb_probe(int bpp, struct ctfb_res_modes *mode)
+{
+	void *fb;
+	unsigned mem_size;
 
 	/* fill in Graphic device struct */
 	sprintf(panel.modeIdent, "%dx%dx%d",
-			mode.xres, mode.yres, bpp);
+			mode->xres, mode->yres, bpp);
 
-	panel.winSizeX = mode.xres;
-	panel.winSizeY = mode.yres;
-	panel.plnSizeX = mode.xres;
-	panel.plnSizeY = mode.yres;
+	panel.winSizeX = mode->xres;
+	panel.winSizeY = mode->yres;
+	panel.plnSizeX = mode->xres;
+	panel.plnSizeY = mode->yres;
 
 	switch (bpp) {
 	case 24:
@@ -200,25 +199,31 @@ void *video_hw_init(void)
 		return NULL;
 	}
 
-	panel.memSize = mode.xres * mode.yres * panel.gdfBytesPP;
-
-	/* Allocate framebuffer */
-	fb = memalign(ARCH_DMA_MINALIGN,
-		      roundup(panel.memSize, ARCH_DMA_MINALIGN));
+	mem_size = mode->xres * mode->yres * panel.gdfBytesPP;
+	fb = (void *)panel.frameAdrs;
+	if (fb) {
+		if (panel.memSize < mem_size) {
+			free(fb);
+			fb = NULL;
+			panel.frameAdrs = (u32)fb;
+		}
+	}
 	if (!fb) {
-		printf("MXSFB: Error allocating framebuffer!\n");
-		return NULL;
+		/* Allocate framebuffer */
+		fb = memalign(ARCH_DMA_MINALIGN,
+			roundup(mem_size, ARCH_DMA_MINALIGN));
+		if (!fb) {
+			printf("MXSFB: Error allocating framebuffer!\n");
+			return NULL;
+		}
+		panel.memSize = mem_size;
+		panel.frameAdrs = (u32)fb;
 	}
-
 	/* Wipe framebuffer */
-	memset(fb, 0, panel.memSize);
-
-	panel.frameAdrs = (u32)fb;
-
-	printf("%s\n", panel.modeIdent);
+	memset(fb, 0, mem_size);
 
 	/* Start framebuffer */
-	mxs_lcd_init(&panel, &mode, bpp);
+	mxs_lcd_init(&panel, mode, bpp);
 
 #ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
 	/*
@@ -248,5 +253,89 @@ void *video_hw_init(void)
 	mxc_enable_gis();
 #endif
 
+	board_video_enable();
 	return (void *)&panel;
 }
+
+void cvt_fb_videomode_to_ctfb_res_modes(const struct fb_videomode *fb, struct ctfb_res_modes *ct)
+{
+	ct->xres = fb->xres;
+	ct->yres = fb->yres;
+	ct->refresh = fb->refresh;
+	ct->pixclock = fb->pixclock;
+	ct->pixclock_khz = 0;
+	ct->left_margin = fb->left_margin;
+	ct->right_margin = fb->right_margin;
+	ct->upper_margin = fb->upper_margin;
+	ct->lower_margin = fb->lower_margin;
+	ct->hsync_len = fb->hsync_len;
+	ct->vsync_len = fb->vsync_len;
+	ct->sync = fb->sync;
+	ct->vmode = fb->vmode;
+}
+
+static struct fb_videomode const *gmode;
+static uint32_t gpixfmt;
+
+static struct graphic_device *mxsfb_probe2(void)
+{
+	struct ctfb_res_modes ct;
+	int bpp = -1;
+
+	switch (gpixfmt) {
+	case IPU_PIX_FMT_RGB32:
+		bpp = 32;
+		break;
+	case IPU_PIX_FMT_RGB24:
+		bpp = 24;
+		break;
+	case IPU_PIX_FMT_RGB666:
+		bpp = 18;
+		break;
+	case IPU_PIX_FMT_RGB565:
+		bpp = 16;
+		break;
+	}
+
+	cvt_fb_videomode_to_ctfb_res_modes(gmode, &ct);
+	return mxsfb_probe(bpp, &ct);
+}
+
+void *mxsfb_init2(void)
+{
+	struct graphic_device *fb = mxsfb_probe2();
+
+	if (fb) {
+		drv_video_init2(fb);
+		debug("Framebuffer at 0x%x\n", (unsigned int)fb->frameAdrs);
+	}
+	return fb;
+}
+
+int mxsfb_init(struct fb_videomode const *mode, uint32_t pixfmt)
+{
+	gmode = mode;
+	gpixfmt = pixfmt;
+	return 0;
+}
+
+void *video_hw_init(void)
+{
+	char *penv;
+	int bpp = -1;
+	struct ctfb_res_modes mode;
+
+	if (gmode)
+		return mxsfb_probe2();
+	puts("Video: ");
+
+	/* Suck display configuration from "videomode" variable */
+	penv = env_get("videomode");
+	if (!penv) {
+		puts("MXSFB: 'videomode' variable not set!\n");
+		return NULL;
+	}
+
+	bpp = video_get_params(&mode, penv);
+	return mxsfb_probe(bpp, &mode);
+}
-- 
GitLab