drm/omap: HDMI: change enable/disable to avoid sync-losts
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Tue, 24 Mar 2015 13:46:35 +0000 (15:46 +0200)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Thu, 3 Mar 2016 15:36:40 +0000 (17:36 +0200)
We occasionally see DISPC sync-lost errors when enabling and disabling
HDMI. Sometimes we get only a few, which get handled (ignored) by the
driver, but sometimes there's a flood of the errors which doesn't seem
to stop.

The HW team has root caused this to the order in which HDMI and DISPC
are enabled/disabled. Currently we enable HDMI first, and then DISPC,
and vice versa when disabling. HW team's suggestion is to do it the
other way around.

This patch changes the order, but this has two side effects as the pixel
clock is produced by HDMI, and the clock is not running when we
enable/disable DISPC:

* When enabling DISPC first, we don't get vertical sync events
* When disabling DISPC last, we don't get FRAMEDONE event

At the moment we use both of those to verify that DISPC has been
enabled/disabled properly. Thus this patch also needs to change the
omapdrm and omapdss which handle the DISPC side.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
drivers/gpu/drm/omapdrm/dss/hdmi4.c
drivers/gpu/drm/omapdrm/dss/hdmi5.c
drivers/gpu/drm/omapdrm/omap_crtc.c

index 7103c659a53488f48495dee43091200edb95f53b..b09ce9ee82fa64ee3f2421142b7c3ed997c6cfb6 100644 (file)
@@ -214,22 +214,22 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
        /* tv size */
        dss_mgr_set_timings(mgr, p);
 
-       r = hdmi_wp_video_start(&hdmi.wp);
-       if (r)
-               goto err_vid_enable;
-
        r = dss_mgr_enable(mgr);
        if (r)
                goto err_mgr_enable;
 
+       r = hdmi_wp_video_start(&hdmi.wp);
+       if (r)
+               goto err_vid_enable;
+
        hdmi_wp_set_irqenable(wp,
                HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
 
        return 0;
 
-err_mgr_enable:
-       hdmi_wp_video_stop(&hdmi.wp);
 err_vid_enable:
+       dss_mgr_disable(mgr);
+err_mgr_enable:
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 err_phy_pwr:
 err_phy_cfg:
@@ -246,10 +246,10 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 
        hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
 
-       dss_mgr_disable(mgr);
-
        hdmi_wp_video_stop(&hdmi.wp);
 
+       dss_mgr_disable(mgr);
+
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 
        dss_pll_disable(&hdmi.pll.pll);
index a955a2c4c061f4cd1c890f61f2ec749076eb66b9..4485a1c37bd8051f27e86b996c7b7a4814524849 100644 (file)
@@ -231,22 +231,22 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
        /* tv size */
        dss_mgr_set_timings(mgr, p);
 
-       r = hdmi_wp_video_start(&hdmi.wp);
-       if (r)
-               goto err_vid_enable;
-
        r = dss_mgr_enable(mgr);
        if (r)
                goto err_mgr_enable;
 
+       r = hdmi_wp_video_start(&hdmi.wp);
+       if (r)
+               goto err_vid_enable;
+
        hdmi_wp_set_irqenable(&hdmi.wp,
                        HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
 
        return 0;
 
-err_mgr_enable:
-       hdmi_wp_video_stop(&hdmi.wp);
 err_vid_enable:
+       dss_mgr_disable(mgr);
+err_mgr_enable:
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 err_phy_pwr:
 err_phy_cfg:
@@ -263,10 +263,10 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 
        hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
 
-       dss_mgr_disable(mgr);
-
        hdmi_wp_video_stop(&hdmi.wp);
 
+       dss_mgr_disable(mgr);
+
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 
        dss_pll_disable(&hdmi.pll.pll);
index 2ed0754ed19edc586c2a70c1bdc01aecb8593aa1..7dd3d44a93e5b85c42ab31cdcb88808ce7bb1473 100644 (file)
@@ -138,6 +138,11 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
        u32 framedone_irq, vsync_irq;
        int ret;
 
+       if (omap_crtc->mgr->output->output_type == OMAP_DISPLAY_TYPE_HDMI) {
+               dispc_mgr_enable(channel, enable);
+               return;
+       }
+
        if (dispc_mgr_is_enabled(channel) == enable)
                return;