diff mbox

drm/exynos: power up HDMI before mixer

Message ID 1393015867-20333-1-git-send-email-drake@endlessm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Drake Feb. 21, 2014, 8:51 p.m. UTC
Testing on Exynos4412, when changing screen resolution under GNOME/X11,
first DPMS is set to OFF via drm_mode_obj_set_property_ioctl.

This is done via drm_hdmi_dpms which powers down the mixer then the
HDMI component.

Then the mode change happens. We then see this call chain, powering things
back on:
 exynos_drm_crtc_commit
  exynos_drm_crtc_dpms
   exynos_drm_encoder_crtc_dpms
    drm_hdmi_dpms

And at this point, drm_hdmi_dpms first powers on the mixer, then the
HDMI component.

Strangely enough, this works fine on the first resolution change, but
on the second it hangs in mixer_poweron() in:
	mixer_reg_write(res, MXR_INT_EN, ctx->int_en);

Through some experiments I determined that this register write will
hang the machine here unless the hdmi_resources.hdmi clock is running.
I can't explain why there is a difference between the first and second
time; I did check that the underlying clock gating register has the
same value in both cases.

Anyway, the mixer clearly has some kind of dependency on the HDMI
component, so lets make sure we power that up first.

Signed-off-by: Daniel Drake <drake@endlessm.com>
---
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 8548b97..3bfd9d6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -261,10 +261,17 @@  static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 
+	/* When powering up, we must first power up the HDMI component, as
+	 * otherwise mixer register accesses will sometimes hang.
+	 * When powering down, we do the opposite: mixer off, HDMI off. */
+
+	if (mode == DRM_MODE_DPMS_ON && hdmi_ops && hdmi_ops->dpms)
+		hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
+
 	if (mixer_ops && mixer_ops->dpms)
 		mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
 
-	if (hdmi_ops && hdmi_ops->dpms)
+	if (mode != DRM_MODE_DPMS_ON && hdmi_ops && hdmi_ops->dpms)
 		hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
 }