@@ -217,6 +217,26 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
if (r)
goto err_vid_enable;
+ /*
+ * XXX Seems that on we easily get a flood of sync-lost errors when
+ * enabling the output. This seems to be related to the time between
+ * HDMI VSYNC and enabling the DISPC output.
+ *
+ * Testing shows that the sync-lost errors do not happen if we enable
+ * the DISPC output very soon after HDMI VBLANK. So wait here for
+ * VBLANK to reduce the chances of sync-losts.
+ */
+ hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC);
+
+ while (true) {
+ u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW);
+
+ if (v & HDMI_IRQ_VIDEO_VSYNC)
+ break;
+
+ usleep_range(500, 1000);
+ }
+
r = dss_mgr_enable(mgr);
if (r)
goto err_mgr_enable;
@@ -242,9 +262,39 @@ err_pll_enable:
static void hdmi_power_off_full(struct omap_dss_device *dssdev)
{
struct omap_overlay_manager *mgr = hdmi.output.manager;
+ const struct omap_video_timings *t;
+ unsigned vblank;
hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
+ /*
+ * XXX Seems that on we easily get a flood of sync-lost errors when
+ * disabling the output, and sometimes the DISPC seems to get stuck and
+ * we never get FRAMEDONE. This seems to happen if we disable DISPC
+ * output during HDMI VBLANK.
+ *
+ * To reduce the possibility for sync-lost errors, calculate the time
+ * for the vertical blanking, wait for VBLANK, then wait until VBLANK
+ * ends.
+ */
+ t = &hdmi.cfg.timings;
+ vblank = t->hfp + t->hsw + t->hbp + t->x_res;
+ vblank *= t->vsw + t->vbp;
+ vblank = (vblank * 1000) / (t->pixelclock / 1000);
+
+ hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC);
+
+ while (true) {
+ u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW);
+
+ if (v & HDMI_IRQ_VIDEO_VSYNC)
+ break;
+
+ usleep_range(500, 1000);
+ }
+
+ usleep_range(vblank, vblank + 1000);
+
dss_mgr_disable(mgr);
hdmi_wp_video_stop(&hdmi.wp);
@@ -234,6 +234,26 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
if (r)
goto err_vid_enable;
+ /*
+ * XXX Seems that on we easily get a flood of sync-lost errors when
+ * enabling the output. This seems to be related to the time between
+ * HDMI VSYNC and enabling the DISPC output.
+ *
+ * Testing shows that the sync-lost errors do not happen if we enable
+ * the DISPC output very soon after HDMI VBLANK. So wait here for
+ * VBLANK to reduce the chances of sync-losts.
+ */
+ hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC);
+
+ while (true) {
+ u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW);
+
+ if (v & HDMI_IRQ_VIDEO_VSYNC)
+ break;
+
+ usleep_range(500, 1000);
+ }
+
r = dss_mgr_enable(mgr);
if (r)
goto err_mgr_enable;
@@ -259,9 +279,39 @@ err_pll_enable:
static void hdmi_power_off_full(struct omap_dss_device *dssdev)
{
struct omap_overlay_manager *mgr = hdmi.output.manager;
+ const struct omap_video_timings *t;
+ unsigned vblank;
hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
+ /*
+ * XXX Seems that on we easily get a flood of sync-lost errors when
+ * disabling the output, and sometimes the DISPC seems to get stuck and
+ * we never get FRAMEDONE. This seems to happen if we disable DISPC
+ * output during HDMI VBLANK.
+ *
+ * To reduce the possibility for sync-lost errors, calculate the time
+ * for the vertical blanking, wait for VBLANK, then wait until VBLANK
+ * ends.
+ */
+ t = &hdmi.cfg.timings;
+ vblank = t->hfp + t->hsw + t->hbp + t->x_res;
+ vblank *= t->vsw + t->vbp;
+ vblank = (vblank * 1000) / (t->pixelclock / 1000);
+
+ hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC);
+
+ while (true) {
+ u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW);
+
+ if (v & HDMI_IRQ_VIDEO_VSYNC)
+ break;
+
+ usleep_range(500, 1000);
+ }
+
+ usleep_range(vblank, vblank + 1000);
+
dss_mgr_disable(mgr);
hdmi_wp_video_stop(&hdmi.wp);
DISPC and HDMI have synchronization issues when enabling or disabling the output. The symptoms are a lot of sync-lost errors and occasionally dispc gets "stuck" and we never get FRAMEDONE when disabling. Testing has shown that this is somehow related to the time when DISPC's output gets enabled: - If DISPC is disabled when HDMI is in vertical blanking area, DISPC often gets stuck. - If DISPC is disabled after vertical blanking area, no sync lost errors are seen. - If DISPC is enabled right after HDMI VSYNC event, no sync lost errors are seen. This patch is a simple work-around for the above issues: - Before enabling DISPC output, we wait for HDMI VSYNC. - Before disabling DISPC output, we wait for HDMI VSYNC and VSW+VBP. This is not perfect WA, as it relies on the enable/disable of DISPC happening relatively soon after the wait has ended. In practice I presume there is at least ~10ms timewindow to accomplish the DISPC enable/disable, which I hope is enough. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> --- drivers/video/fbdev/omap2/dss/hdmi4.c | 50 +++++++++++++++++++++++++++++++++++ drivers/video/fbdev/omap2/dss/hdmi5.c | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+)