mx6sabresd: Add LVDS splash screen support
mx6sabresd boards can be connected to a Hannstar XGA LVDS panel. Add support for displaying U-boot splashscreen on it. By default, HDMI splash is selected. In order to use splash via LVDS, do the following in the U-boot prompt: setenv panel Hannstar-XGA save and reboot. Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
This commit is contained in:
parent
7b8657e2bd
commit
d9b8946035
@ -234,7 +234,42 @@ int board_phy_config(struct phy_device *phydev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_VIDEO_IPUV3)
|
#if defined(CONFIG_VIDEO_IPUV3)
|
||||||
static struct fb_videomode const hdmi = {
|
struct display_info_t {
|
||||||
|
int bus;
|
||||||
|
int addr;
|
||||||
|
int pixfmt;
|
||||||
|
int (*detect)(struct display_info_t const *dev);
|
||||||
|
void (*enable)(struct display_info_t const *dev);
|
||||||
|
struct fb_videomode mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int detect_hdmi(struct display_info_t const *dev)
|
||||||
|
{
|
||||||
|
struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
|
||||||
|
return readb(&hdmi->phy_stat0) & HDMI_DVI_STAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_enable_hdmi(struct display_info_t const *dev)
|
||||||
|
{
|
||||||
|
imx_enable_hdmi_phy();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enable_lvds(struct display_info_t const *dev)
|
||||||
|
{
|
||||||
|
struct iomuxc *iomux = (struct iomuxc *)
|
||||||
|
IOMUXC_BASE_ADDR;
|
||||||
|
u32 reg = readl(&iomux->gpr[2]);
|
||||||
|
reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT |
|
||||||
|
IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT;
|
||||||
|
writel(reg, &iomux->gpr[2]);
|
||||||
|
}
|
||||||
|
static 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",
|
.name = "HDMI",
|
||||||
.refresh = 60,
|
.refresh = 60,
|
||||||
.xres = 1024,
|
.xres = 1024,
|
||||||
@ -248,33 +283,122 @@ static struct fb_videomode const hdmi = {
|
|||||||
.vsync_len = 10,
|
.vsync_len = 10,
|
||||||
.sync = FB_SYNC_EXT,
|
.sync = FB_SYNC_EXT,
|
||||||
.vmode = FB_VMODE_NONINTERLACED
|
.vmode = FB_VMODE_NONINTERLACED
|
||||||
};
|
} }, {
|
||||||
|
.bus = -1,
|
||||||
|
.addr = 0,
|
||||||
|
.pixfmt = IPU_PIX_FMT_LVDS666,
|
||||||
|
.detect = NULL,
|
||||||
|
.enable = enable_lvds,
|
||||||
|
.mode = {
|
||||||
|
.name = "Hannstar-XGA",
|
||||||
|
.refresh = 60,
|
||||||
|
.xres = 1024,
|
||||||
|
.yres = 768,
|
||||||
|
.pixclock = 15385,
|
||||||
|
.left_margin = 220,
|
||||||
|
.right_margin = 40,
|
||||||
|
.upper_margin = 21,
|
||||||
|
.lower_margin = 7,
|
||||||
|
.hsync_len = 60,
|
||||||
|
.vsync_len = 10,
|
||||||
|
.sync = FB_SYNC_EXT,
|
||||||
|
.vmode = FB_VMODE_NONINTERLACED
|
||||||
|
} } };
|
||||||
|
|
||||||
int board_video_skip(void)
|
int board_video_skip(void)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
char const *panel = getenv("panel");
|
||||||
|
if (!panel) {
|
||||||
|
for (i = 0; i < ARRAY_SIZE(displays); i++) {
|
||||||
|
struct display_info_t const *dev = displays+i;
|
||||||
|
if (dev->detect(dev)) {
|
||||||
|
panel = dev->mode.name;
|
||||||
|
printf("auto-detected panel %s\n", panel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!panel) {
|
||||||
|
panel = displays[0].mode.name;
|
||||||
|
printf("No panel detected: default to %s\n", panel);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < ARRAY_SIZE(displays); i++) {
|
||||||
|
if (!strcmp(panel, displays[i].mode.name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < ARRAY_SIZE(displays)) {
|
||||||
|
ret = ipuv3_fb_init(&displays[i].mode, 0,
|
||||||
|
displays[i].pixfmt);
|
||||||
|
if (!ret) {
|
||||||
|
displays[i].enable(displays+i);
|
||||||
|
printf("Display: %s (%ux%u)\n",
|
||||||
|
displays[i].mode.name,
|
||||||
|
displays[i].mode.xres,
|
||||||
|
displays[i].mode.yres);
|
||||||
|
} else
|
||||||
|
printf("LCD %s cannot be configured: %d\n",
|
||||||
|
displays[i].mode.name, ret);
|
||||||
|
} else {
|
||||||
|
printf("unsupported panel %s\n", panel);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ipuv3_fb_init(&hdmi, 0, IPU_PIX_FMT_RGB24);
|
return 0;
|
||||||
|
|
||||||
if (ret)
|
|
||||||
printf("HDMI cannot be configured: %d\n", ret);
|
|
||||||
|
|
||||||
imx_enable_hdmi_phy();
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_display(void)
|
static void setup_display(void)
|
||||||
{
|
{
|
||||||
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
|
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
|
||||||
|
struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
|
||||||
int reg;
|
int reg;
|
||||||
|
|
||||||
enable_ipu_clock();
|
enable_ipu_clock();
|
||||||
imx_setup_hdmi();
|
imx_setup_hdmi();
|
||||||
|
|
||||||
|
/* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */
|
||||||
|
reg = __raw_readl(&mxc_ccm->CCGR3);
|
||||||
|
reg |= MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK;
|
||||||
|
writel(reg, &mxc_ccm->CCGR3);
|
||||||
|
|
||||||
|
/* set LDB0, LDB1 clk select to 011/011 */
|
||||||
|
reg = readl(&mxc_ccm->cs2cdr);
|
||||||
|
reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
|
||||||
|
| MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
|
||||||
|
reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
|
||||||
|
| (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
|
||||||
|
writel(reg, &mxc_ccm->cs2cdr);
|
||||||
|
|
||||||
|
reg = readl(&mxc_ccm->cscmr2);
|
||||||
|
reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
|
||||||
|
writel(reg, &mxc_ccm->cscmr2);
|
||||||
|
|
||||||
reg = readl(&mxc_ccm->chsccdr);
|
reg = readl(&mxc_ccm->chsccdr);
|
||||||
reg |= (CHSCCDR_CLK_SEL_LDB_DI0
|
reg |= (CHSCCDR_CLK_SEL_LDB_DI0
|
||||||
<< MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
|
<< MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
|
||||||
|
reg |= (CHSCCDR_CLK_SEL_LDB_DI0
|
||||||
|
<< MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET);
|
||||||
writel(reg, &mxc_ccm->chsccdr);
|
writel(reg, &mxc_ccm->chsccdr);
|
||||||
|
|
||||||
|
reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
|
||||||
|
| IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW
|
||||||
|
| IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
|
||||||
|
| IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
|
||||||
|
| IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
|
||||||
|
| IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
|
||||||
|
| IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
|
||||||
|
| IOMUXC_GPR2_LVDS_CH0_MODE_DISABLED
|
||||||
|
| IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0;
|
||||||
|
writel(reg, &iomux->gpr[2]);
|
||||||
|
|
||||||
|
reg = readl(&iomux->gpr[3]);
|
||||||
|
reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK
|
||||||
|
| IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
|
||||||
|
| (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
|
||||||
|
<< IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
|
||||||
|
writel(reg, &iomux->gpr[3]);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_VIDEO_IPUV3 */
|
#endif /* CONFIG_VIDEO_IPUV3 */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user