diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index 6dd9bec351f..46436b88c57 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -113,6 +113,13 @@ static int sunxi_hdmi_hpd_detect(int hpd_delay) writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl); writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0); + /* Enable PLLs for eventual DDC */ + writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE, + &hdmi->pad_ctrl1); + writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15), + &hdmi->pll_ctrl); + writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0); + while (timer_get_us() < tmo) { if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT) return 1; @@ -203,7 +210,8 @@ static int sunxi_hdmi_edid_get_block(int block, u8 *buf) return r; } -static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode) +static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode, + bool verbose_mode) { struct edid1_info edid1; struct edid_cea861_info cea681[4]; @@ -215,13 +223,6 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode) (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int i, r, ext_blocks = 0; - /* SUNXI_HDMI_CTRL_ENABLE & PAD_CTRL0 are already set by hpd_detect */ - writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE, - &hdmi->pad_ctrl1); - writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15), - &hdmi->pll_ctrl); - writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0); - /* Reset i2c controller */ setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE); writel(SUNXI_HMDI_DDC_CTRL_ENABLE | @@ -241,7 +242,8 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode) if (r == 0) { r = edid_check_info(&edid1); if (r) { - printf("EDID: invalid EDID data\n"); + if (verbose_mode) + printf("EDID: invalid EDID data\n"); r = -EINVAL; } } @@ -1082,7 +1084,8 @@ void *video_hw_init(void) struct ctfb_res_modes custom; const char *options; #ifdef CONFIG_VIDEO_HDMI - int ret, hpd, hpd_delay, edid; + int hpd, hpd_delay, edid; + bool hdmi_present; #endif int i, overscan_offset, overscan_x, overscan_y; unsigned int fb_dma_addr; @@ -1118,12 +1121,23 @@ void *video_hw_init(void) if (sunxi_display.monitor == sunxi_monitor_dvi || sunxi_display.monitor == sunxi_monitor_hdmi) { /* Always call hdp_detect, as it also enables clocks, etc. */ - ret = sunxi_hdmi_hpd_detect(hpd_delay); - if (ret) { + hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1); + if (hdmi_present && edid) { printf("HDMI connected: "); - if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0) + if (sunxi_hdmi_edid_get_mode(&custom, true) == 0) mode = &custom; - } else if (hpd) { + else + hdmi_present = false; + } + /* Fall back to EDID in case HPD failed */ + if (edid && !hdmi_present) { + if (sunxi_hdmi_edid_get_mode(&custom, false) == 0) { + mode = &custom; + hdmi_present = true; + } + } + /* Shut down when display was not found */ + if ((hpd || edid) && !hdmi_present) { sunxi_hdmi_shutdown(); sunxi_display.monitor = sunxi_get_default_mon(false); } /* else continue with hdmi/dvi without a cable connected */ diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c index 2898b0b55d7..193f37d275e 100644 --- a/drivers/video/video_bmp.c +++ b/drivers/video/video_bmp.c @@ -229,11 +229,12 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, } /* - * We support displaying 8bpp BMPs on 16bpp LCDs + * We support displaying 8bpp and 24bpp BMPs on 16bpp LCDs * and displaying 24bpp BMPs on 32bpp LCDs - * */ + */ if (bpix != bmp_bpix && !(bmp_bpix == 8 && bpix == 16) && + !(bmp_bpix == 24 && bpix == 16) && !(bmp_bpix == 24 && bpix == 32)) { printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", bpix, get_unaligned_le16(&bmp->header.bit_count)); @@ -318,12 +319,22 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, case 24: for (i = 0; i < height; ++i) { for (j = 0; j < width; j++) { - *(fb++) = *(bmap++); - *(fb++) = *(bmap++); - *(fb++) = *(bmap++); - *(fb++) = 0; + if (bpix == 16) { + /* 16bit 555RGB format */ + *(u16 *)fb = ((bmap[2] >> 3) << 10) | + ((bmap[1] >> 3) << 5) | + (bmap[0] >> 3); + bmap += 3; + fb += 2; + } else { + *(fb++) = *(bmap++); + *(fb++) = *(bmap++); + *(fb++) = *(bmap++); + *(fb++) = 0; + } } fb -= priv->line_length + width * (bpix / 8); + bmap += (padded_width - width) * 3; } break; #endif /* CONFIG_BMP_24BPP */