sunxi: display: Implement fallback to ddc probe when hpd fails
authorPriit Laes <priit.laes@paf.com>
Wed, 19 Dec 2018 13:06:09 +0000 (15:06 +0200)
committerAnatolij Gustschin <agust@denx.de>
Fri, 15 Feb 2019 15:30:44 +0000 (16:30 +0100)
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 <priit.laes@paf.com>
drivers/video/sunxi/sunxi_display.c

index 0362071f720b877d3c40959e4374a1a14fbe55a8..46436b88c57e15c7e715aa9b6d8a5d416610f1fd 100644 (file)
@@ -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 */