static inline int karo_fdt_flexcan_enabled(void *blob)
{
- const char *can_ifs[] = {
+ static const char *can_ifs[] = {
"can0",
"can1",
};
return fdt_update_native_fb_mode(blob, off);
return off;
}
+
+int karo_fdt_get_lcd_bus_width(const void *blob, int default_width)
+{
+ int off = fdt_path_offset(blob, "display");
+
+ if (off >= 0) {
+ const uint32_t *prop;
+
+ prop = fdt_getprop(blob, off, "fsl,data-width", NULL);
+ if (prop)
+ return fdt32_to_cpu(*prop);
+ }
+ return default_width;
+}
+
+int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping)
+{
+ int off = fdt_path_offset(blob, "display");
+
+ if (off >= 0) {
+ const char *prop;
+
+ prop = fdt_getprop(blob, off, "fsl,data-mapping", NULL);
+ if (prop)
+ return strcmp(prop, "jeida") == 0;
+ }
+ return default_mapping;
+}
+
+u8 karo_fdt_get_lvds_channels(const void *blob)
+{
+ static const char *lvds_chans[] = {
+ "lvds0",
+ "lvds1",
+ };
+ u8 lvds_chan_mask = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(lvds_chans); i++) {
+ const char *status;
+ int off = fdt_path_offset(blob, lvds_chans[i]);
+
+ if (off < 0)
+ continue;
+
+ status = fdt_getprop(blob, off, "status", NULL);
+ if (status && strcmp(status, "okay") == 0) {
+ debug("%s is enabled\n", lvds_chans[i]);
+ lvds_chan_mask |= 1 << i;
+ }
+ }
+ return lvds_chan_mask;
+}
int karo_fdt_update_fb_mode(void *blob, const char *name);
int karo_fdt_create_fb_mode(void *blob, const char *name,
struct fb_videomode *mode);
+int karo_fdt_get_lcd_bus_width(const void *blob, int default_width);
+int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping);
+u8 karo_fdt_get_lvds_channels(const void *blob);
#else
static inline void karo_fdt_remove_node(void *blob, const char *node)
{
{
return 0;
}
+int karo_fdt_get_lcd_bus_width(const void *blob, int default_width)
+{
+ return default_width;
+}
+int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping)
+{
+ return default_mapping;
+}
+u8 karo_fdt_get_lvds_channels(const void *blob)
+{
+ return 0;
+}
#endif
static inline const char *karo_get_vmode(const char *video_mode)
struct fb_videomode *p = &tx53_fb_modes[0];
struct fb_videomode fb_mode;
int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
- int pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS666 : IPU_PIX_FMT_RGB24;
+ int pix_fmt;
+ int lcd_bus_width;
ipu_di_clk_parent_t di_clk_parent = is_lvds() ? DI_PCLK_LDB : DI_PCLK_PLL3;
unsigned long di_clk_rate = 65000000;
imx_iomux_v3_setup_multiple_pads(stk5_lcd_pads,
ARRAY_SIZE(stk5_lcd_pads));
- debug("Initializing FB driver\n");
-#ifdef CONFIG_SYS_LVDS_IF
- if (pix_fmt == IPU_PIX_FMT_LVDS666) {
- writel(0x01, IOMUXC_BASE_ADDR + 8);
- } else if (pix_fmt == IPU_PIX_FMT_LVDS888) {
- writel(0x21, IOMUXC_BASE_ADDR + 8);
+ lcd_bus_width = karo_fdt_get_lcd_bus_width(working_fdt, 24);
+ switch (lcd_bus_width) {
+ case 24:
+ pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS888 : IPU_PIX_FMT_RGB24;
+ break;
+
+ case 18:
+ pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS666 : IPU_PIX_FMT_RGB666;
+ break;
+
+ case 16:
+ if (!is_lvds()) {
+ pix_fmt = IPU_PIX_FMT_RGB565;
+ break;
+ }
+ /* fallthru */
+ default:
+ lcd_enabled = 0;
+ printf("Invalid %s bus width: %d\n", is_lvds() ? "LVDS" : "LCD",
+ lcd_bus_width);
+ return;
}
- {
- struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
- /* enable LDB & DI0 clock */
- writel(readl(&ccm_regs->CCGR6) | (3 << 28) | (3 << 10),
- &ccm_regs->CCGR6);
+ if (is_lvds()) {
+ int lvds_mapping = karo_fdt_get_lvds_mapping(working_fdt, 0);
+ int lvds_chan_mask = karo_fdt_get_lvds_channels(working_fdt);
+ uint32_t gpr2;
+
+ if (lvds_chan_mask == 0) {
+ printf("No LVDS channel active\n");
+ lcd_enabled = 0;
+ return;
+ }
+
+ gpr2 = (lvds_mapping << 6) | (lvds_mapping << 8);
+ if (lcd_bus_width == 24)
+ gpr2 |= (1 << 5) | (1 << 7);
+ gpr2 |= (lvds_chan_mask & 1) ? 1 << 0 : 0;
+ gpr2 |= (lvds_chan_mask & 2) ? 3 << 2 : 0;
+ debug("writing %08x to GPR2[%08x]\n", gpr2, IOMUXC_BASE_ADDR + 8);
+ writel(gpr2, IOMUXC_BASE_ADDR + 8);
}
-#endif
if (karo_load_splashimage(0) == 0) {
int ret;
struct fb_videomode *p = &tx6_fb_modes[0];
struct fb_videomode fb_mode;
int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
- int pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS666 : IPU_PIX_FMT_RGB24;
+ int pix_fmt;
+ int lcd_bus_width;
unsigned long di_clk_rate = 65000000;
if (!lcd_enabled) {
switch (val) {
case 32:
case 24:
- if (pix_fmt == IPU_PIX_FMT_LVDS666)
+ if (is_lvds())
pix_fmt = IPU_PIX_FMT_LVDS888;
/* fallthru */
case 16:
break;
case 18:
- if (pix_fmt == IPU_PIX_FMT_LVDS666) {
+ if (is_lvds()) {
color_depth = val;
break;
}
imx_iomux_v3_setup_multiple_pads(stk5_lcd_pads,
ARRAY_SIZE(stk5_lcd_pads));
- debug("Initializing FB driver\n");
-#ifdef CONFIG_SYS_LVDS_IF
- if (pix_fmt == IPU_PIX_FMT_LVDS666) {
- writel(0x01, IOMUXC_BASE_ADDR + 8);
- } else if (pix_fmt == IPU_PIX_FMT_LVDS888) {
- writel(0x21, IOMUXC_BASE_ADDR + 8);
+ lcd_bus_width = karo_fdt_get_lcd_bus_width(working_fdt, 24);
+ switch (lcd_bus_width) {
+ case 24:
+ pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS888 : IPU_PIX_FMT_RGB24;
+ break;
+
+ case 18:
+ pix_fmt = is_lvds() ? IPU_PIX_FMT_LVDS666 : IPU_PIX_FMT_RGB666;
+ break;
+
+ case 16:
+ if (!is_lvds()) {
+ pix_fmt = IPU_PIX_FMT_RGB565;
+ break;
+ }
+ /* fallthru */
+ default:
+ lcd_enabled = 0;
+ printf("Invalid %s bus width: %d\n", is_lvds() ? "LVDS" : "LCD",
+ lcd_bus_width);
+ return;
}
- {
- struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
- /* enable LDB & DI0 clock */
- writel(readl(&ccm_regs->CCGR3) | MXC_CCM_CCGR3_LDB_DI0_MASK |
- MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK,
- &ccm_regs->CCGR3);
+ if (is_lvds()) {
+ int lvds_mapping = karo_fdt_get_lvds_mapping(working_fdt, 0);
+ int lvds_chan_mask = karo_fdt_get_lvds_channels(working_fdt);
+ uint32_t gpr2;
+
+ if (lvds_chan_mask == 0) {
+ printf("No LVDS channel active\n");
+ lcd_enabled = 0;
+ return;
+ }
+
+ gpr2 = (lvds_mapping << 6) | (lvds_mapping << 8);
+ if (lcd_bus_width == 24)
+ gpr2 |= (1 << 5) | (1 << 7);
+ gpr2 |= (lvds_chan_mask & 1) ? 1 << 0 : 0;
+ gpr2 |= (lvds_chan_mask & 2) ? 3 << 2 : 0;
+ debug("writing %08x to GPR2[%08x]\n", gpr2, IOMUXC_BASE_ADDR + 8);
+ writel(gpr2, IOMUXC_BASE_ADDR + 8);
}
-#endif
if (karo_load_splashimage(0) == 0) {
+ int ret;
+
debug("Initializing LCD controller\n");
- ipuv3_fb_init(p, 0, pix_fmt, DI_PCLK_PLL3, di_clk_rate, -1);
+ ret = ipuv3_fb_init(p, 0, pix_fmt, DI_PCLK_PLL3, di_clk_rate, -1);
+ if (ret) {
+ printf("Failed to initialize FB driver: %d\n", ret);
+ lcd_enabled = 0;
+ }
} else {
debug("Skipping initialization of LCD controller\n");
}