From: Paulo Zanoni <paulo.r.zanoni at intel.com> Both the control and data registers are completely different now. Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 4 +++ drivers/gpu/drm/i915/intel_hdmi.c | 53 +++++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 5 deletions(-) V2: swap patches 1 and 2 diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index eae9495..5024551 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1703,6 +1703,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) @@ -1719,6 +1720,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 cd5d9a9..2ead3bf 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, -- 1.7.9.5