From 361604d658695966ba985f544800ecc7563caf41 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Wed, 19 Dec 2018 15:06:08 +0200 Subject: [PATCH 1/3] sunxi: display: Move DDC PLL setup to HDMI init Move PLL initialization code to single place so we won't call it every time we query for EDID data. Signed-off-by: Priit Laes --- drivers/video/sunxi/sunxi_display.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index 6dd9bec351..0362071f72 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; @@ -215,13 +222,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 | From 0220f8c223f088cc722b81fc1db23734de87a13d Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Wed, 19 Dec 2018 15:06:09 +0200 Subject: [PATCH 2/3] sunxi: display: Implement fallback to ddc probe when hpd fails There are HDMI displays where hpd pin is not connected, thus we cannot get it to work unless we specifically set the resolution. Rework the display probing, so hotplug detect failure causes fallback to probing ddc for EDID data. Signed-off-by: Priit Laes --- drivers/video/sunxi/sunxi_display.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index 0362071f72..46436b88c5 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -210,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]; @@ -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 */ From e25710305da0f087a374ad41d5fa1f244469f6f2 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 30 Jan 2019 08:54:12 +0100 Subject: [PATCH 3/3] video: bmp: Add support for 24bpp BMP files on 16bpp displays This patch adds support to load 24bpp BMP files on 16bpp displays. This will be used by the theadorable board. The "old" bmp command did support this operartion mode and to not break compatibility with the move to DM_VIDEO, we need to add this support to the "new" bmp code. Signed-off-by: Stefan Roese Reviewed-by: Anatolij Gustschin Acked-by: Anatolij Gustschin --- drivers/video/video_bmp.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c index 2898b0b55d..193f37d275 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 */