From 2da8af54059bd8c0d7bdf1f56b39cbec7f9c6f05 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 May 2012 17:12:51 -0300 Subject: [PATCH] drm/i915: implement hsw_write_infoframe Both the control and data registers are completely different now. Signed-off-by: Paulo Zanoni Reviewed-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 +++ drivers/gpu/drm/i915/intel_hdmi.c | 53 ++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fb76b19e32b2..2d49b9507ed0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1697,6 +1697,7 @@ /* Video Data Island Packet control */ #define VIDEO_DIP_DATA 0x61178 #define VIDEO_DIP_CTL 0x61170 +/* Pre HSW: */ #define VIDEO_DIP_ENABLE (1 << 31) #define VIDEO_DIP_PORT_B (1 << 29) #define VIDEO_DIP_PORT_C (2 << 29) @@ -1713,6 +1714,9 @@ #define VIDEO_DIP_FREQ_VSYNC (1 << 16) #define VIDEO_DIP_FREQ_2VSYNC (2 << 16) #define VIDEO_DIP_FREQ_MASK (3 << 16) +/* HSW and later: */ +#define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) +#define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) /* Panel power sequencing */ #define PP_STATUS 0x61200 diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index cd5d9a9bdedc..2ead3bf7c21d 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -89,6 +89,32 @@ static u32 g4x_infoframe_enable(struct dip_infoframe *frame) } } +static u32 hsw_infoframe_enable(struct dip_infoframe *frame) +{ + switch (frame->type) { + case DIP_TYPE_AVI: + return VIDEO_DIP_ENABLE_AVI_HSW; + case DIP_TYPE_SPD: + return VIDEO_DIP_ENABLE_SPD_HSW; + default: + DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); + return 0; + } +} + +static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame, enum pipe pipe) +{ + switch (frame->type) { + case DIP_TYPE_AVI: + return HSW_TVIDEO_DIP_AVI_DATA(pipe); + case DIP_TYPE_SPD: + return HSW_TVIDEO_DIP_SPD_DATA(pipe); + default: + DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); + return 0; + } +} + static void g4x_write_infoframe(struct drm_encoder *encoder, struct dip_infoframe *frame) { @@ -251,13 +277,30 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, static void hsw_write_infoframe(struct drm_encoder *encoder, struct dip_infoframe *frame) { - /* Not implemented yet, so avoid doing anything at all. - * This is the placeholder for Paulo Zanoni's infoframe writing patch - */ - DRM_DEBUG_DRIVER("Attempting to write infoframe on Haswell, this is not implemented yet.\n"); + uint32_t *data = (uint32_t *)frame; + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); + u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->pipe); + unsigned int i, len = DIP_HEADER_SIZE + frame->len; + u32 val = I915_READ(ctl_reg); - return; + if (data_reg == 0) + return; + + intel_wait_for_vblank(dev, intel_crtc->pipe); + + val &= ~hsw_infoframe_enable(frame); + I915_WRITE(ctl_reg, val); + + for (i = 0; i < len; i += 4) { + I915_WRITE(data_reg + i, *data); + data++; + } + val |= hsw_infoframe_enable(frame); + I915_WRITE(ctl_reg, val); } static void intel_set_infoframe(struct drm_encoder *encoder, -- 2.30.2