mx6cuboxi: Add HDMI output support

Add HDMI output using PLL5 as the source for the IPU clocks,
and accurate VESA timings.

These settings are based on the patch from Soeren Moch <smoch@web.de>
submitted for the tbs2910 mx6 based board.

It allows the display to work properly at 1024x768@60.

This should make the hdmi output signal compatible with most if not all
modern displays.

Signed-off-by: Jon Nettleton <jon.nettleton@gmail.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
Tested-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
Tested-by: Vagrant Cascadian <vagrant@aikidev.net>
diff --git a/board/solidrun/mx6cuboxi/mx6cuboxi.c b/board/solidrun/mx6cuboxi/mx6cuboxi.c
index d3a32c1..eab92f1 100644
--- a/board/solidrun/mx6cuboxi/mx6cuboxi.c
+++ b/board/solidrun/mx6cuboxi/mx6cuboxi.c
@@ -18,9 +18,11 @@
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/iomux.h>
 #include <asm/arch/mx6-pins.h>
+#include <asm/arch/mxc_hdmi.h>
 #include <asm/errno.h>
 #include <asm/gpio.h>
 #include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/video.h>
 #include <mmc.h>
 #include <fsl_esdhc.h>
 #include <miiphy.h>
@@ -159,10 +161,107 @@
 	return cpu_eth_init(bis);
 }
 
+#ifdef CONFIG_VIDEO_IPUV3
+static void do_enable_hdmi(struct display_info_t const *dev)
+{
+	imx_enable_hdmi_phy();
+}
+
+struct display_info_t const displays[] = {
+	{
+		.bus	= -1,
+		.addr	= 0,
+		.pixfmt	= IPU_PIX_FMT_RGB24,
+		.detect	= detect_hdmi,
+		.enable	= do_enable_hdmi,
+		.mode	= {
+			.name           = "HDMI",
+			/* 1024x768@60Hz (VESA)*/
+			.refresh        = 60,
+			.xres           = 1024,
+			.yres           = 768,
+			.pixclock       = 15384,
+			.left_margin    = 160,
+			.right_margin   = 24,
+			.upper_margin   = 29,
+			.lower_margin   = 3,
+			.hsync_len      = 136,
+			.vsync_len      = 6,
+			.sync           = FB_SYNC_EXT,
+			.vmode          = FB_VMODE_NONINTERLACED
+		}
+	}
+};
+
+size_t display_count = ARRAY_SIZE(displays);
+
+static int setup_display(void)
+{
+	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	int reg;
+	int timeout = 100000;
+
+	enable_ipu_clock();
+	imx_setup_hdmi();
+
+	/* set video pll to 455MHz (24MHz * (37+11/12) / 2) */
+	setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
+
+	reg = readl(&ccm->analog_pll_video);
+	reg &= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT;
+	reg |= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37);
+	reg &= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT;
+	reg |= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1);
+	writel(reg, &ccm->analog_pll_video);
+
+	writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
+	writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
+
+	reg &= ~BM_ANADIG_PLL_VIDEO_POWERDOWN;
+	writel(reg, &ccm->analog_pll_video);
+
+	while (timeout--)
+		if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
+			break;
+	if (timeout < 0) {
+		printf("Warning: video pll lock timeout!\n");
+		return -ETIMEDOUT;
+	}
+
+	reg = readl(&ccm->analog_pll_video);
+	reg |= BM_ANADIG_PLL_VIDEO_ENABLE;
+	reg &= ~BM_ANADIG_PLL_VIDEO_BYPASS;
+	writel(reg, &ccm->analog_pll_video);
+
+	/* gate ipu1_di0_clk */
+	clrbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+	/* select video_pll clock / 7  for ipu1_di0_clk -> 65MHz pixclock */
+	reg = readl(&ccm->chsccdr);
+	reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK |
+		 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK |
+		 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
+	reg |= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET) |
+	       (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) |
+	       (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
+	writel(reg, &ccm->chsccdr);
+
+	/* enable ipu1_di0_clk */
+	setbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+	return 0;
+}
+#endif /* CONFIG_VIDEO_IPUV3 */
+
 int board_early_init_f(void)
 {
+	int ret = 0;
 	setup_iomux_uart();
-	return 0;
+
+#ifdef CONFIG_VIDEO_IPUV3
+	ret = setup_display();
+#endif
+	return ret;
 }
 
 int board_init(void)
diff --git a/include/configs/mx6cuboxi.h b/include/configs/mx6cuboxi.h
index b569f34..207a2a6 100644
--- a/include/configs/mx6cuboxi.h
+++ b/include/configs/mx6cuboxi.h
@@ -27,7 +27,7 @@
 #define CONFIG_IMX6_THERMAL
 #define CONFIG_SYS_GENERIC_BOARD
 
-#define CONFIG_SYS_MALLOC_LEN		(2 * SZ_1M)
+#define CONFIG_SYS_MALLOC_LEN		(10 * SZ_1M)
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_BOARD_LATE_INIT
 #define CONFIG_MXC_GPIO
@@ -66,6 +66,22 @@
 #define CONFIG_CONS_INDEX		1
 #define CONFIG_BAUDRATE			115200
 
+/* Framebuffer */
+#define CONFIG_VIDEO
+#define CONFIG_VIDEO_IPUV3
+#define CONFIG_IPUV3_CLK		260000000
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_VIDEO_BMP_RLE8
+#define CONFIG_SPLASH_SCREEN
+#define CONFIG_SPLASH_SCREEN_ALIGN
+#define CONFIG_BMP_16BPP
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_VIDEO_BMP_LOGO
+#define CONFIG_IMX_HDMI
+#define CONFIG_IMX_VIDEO_SKIP
+
 #define CONFIG_SYS_NO_FLASH
 
 /* Command definition */