drm/i915: fix ILK+ infoframe support
authorJesse Barnes <jbarnes@virtuousgeek.org>
Thu, 22 Sep 2011 05:46:00 +0000 (11:16 +0530)
committerKeith Packard <keithp@keithp.com>
Fri, 21 Oct 2011 06:22:02 +0000 (23:22 -0700)
Misc fixes based on tests with an infoframe analyzer:
  - checksum *does* include header bytes
  - DIP enable & AVI infoframe are tied together in hw, so disable both
    and make sure AVI frames are enabled first
  - use every vsync flag for SPD frames to avoid reserved value in
    frequency field when enabling both AVI & SPD

Fixes https://bugs.freedesktop.org/show_bug.cgi?id=40281.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: stable@kernel.org
Signed-off-by: Keith Packard <keithp@keithp.com>
drivers/gpu/drm/i915/intel_hdmi.c

index e7e716c..d4f5a0b 100644 (file)
@@ -69,8 +69,7 @@ void intel_dip_infoframe_csum(struct dip_infoframe *frame)
        frame->checksum = 0;
        frame->ecc = 0;
 
-       /* Header isn't part of the checksum */
-       for (i = 5; i < frame->len; i++)
+       for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
                sum += data[i];
 
        frame->checksum = 0x100 - sum;
@@ -104,7 +103,7 @@ static u32 intel_infoframe_flags(struct dip_infoframe *frame)
                flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
                break;
        case DIP_TYPE_SPD:
-               flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC;
+               flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC;
                break;
        default:
                DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
@@ -165,9 +164,9 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder,
 
        flags = intel_infoframe_index(frame);
 
-       val &= ~VIDEO_DIP_SELECT_MASK;
+       val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
 
-       I915_WRITE(reg, val | flags);
+       I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
 
        for (i = 0; i < len; i += 4) {
                I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
@@ -487,6 +486,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
        struct intel_encoder *intel_encoder;
        struct intel_connector *intel_connector;
        struct intel_hdmi *intel_hdmi;
+       int i;
 
        intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
        if (!intel_hdmi)
@@ -539,10 +539,14 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
        intel_hdmi->sdvox_reg = sdvox_reg;
 
-       if (!HAS_PCH_SPLIT(dev))
+       if (!HAS_PCH_SPLIT(dev)) {
                intel_hdmi->write_infoframe = i9xx_write_infoframe;
-       else
+               I915_WRITE(VIDEO_DIP_CTL, 0);
+       } else {
                intel_hdmi->write_infoframe = ironlake_write_infoframe;
+               for_each_pipe(i)
+                       I915_WRITE(TVIDEO_DIP_CTL(i), 0);
+       }
 
        drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);