buffer[3] = 0;
        len++;
  
 -      intel_dig_port->write_infoframe(encoder,
 -                                      crtc_state,
 -                                      frame->any.type, buffer, len);
 +      intel_dig_port->write_infoframe(encoder, crtc_state, type, buffer, len);
  }
  
 -static void intel_hdmi_set_avi_infoframe(struct intel_encoder *encoder,
 -                                       const struct intel_crtc_state *crtc_state,
 -                                       const struct drm_connector_state *conn_state)
 +void intel_read_infoframe(struct intel_encoder *encoder,
 +                        const struct intel_crtc_state *crtc_state,
 +                        enum hdmi_infoframe_type type,
 +                        union hdmi_infoframe *frame)
  {
 +      struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base);
 +      u8 buffer[VIDEO_DIP_DATA_SIZE];
 +      int ret;
 +
 +      if ((crtc_state->infoframes.enable &
 +           intel_hdmi_infoframe_enable(type)) == 0)
 +              return;
 +
 +      intel_dig_port->read_infoframe(encoder, crtc_state,
 +                                     type, buffer, sizeof(buffer));
 +
 +      /* Fill the 'hole' (see big comment above) at position 3 */
 +      memmove(&buffer[1], &buffer[0], 3);
 +
 +      /* see comment above for the reason for this offset */
 +      ret = hdmi_infoframe_unpack(frame, buffer + 1, sizeof(buffer) - 1);
 +      if (ret) {
 +              DRM_DEBUG_KMS("Failed to unpack infoframe type 0x%02x\n", type);
 +              return;
 +      }
 +
 +      if (frame->any.type != type)
 +              DRM_DEBUG_KMS("Found the wrong infoframe type 0x%x (expected 0x%02x)\n",
 +                            frame->any.type, type);
 +}
 +
 +static bool
 +intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder,
 +                               struct intel_crtc_state *crtc_state,
 +                               struct drm_connector_state *conn_state)
 +{
 +      struct hdmi_avi_infoframe *frame = &crtc_state->infoframes.avi.avi;
        const struct drm_display_mode *adjusted_mode =
                &crtc_state->base.adjusted_mode;
 -      union hdmi_infoframe frame;
 +      struct drm_connector *connector = conn_state->connector;
        int ret;
  
 -      ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
 -                                                     conn_state->connector,
 +      if (!crtc_state->has_infoframe)
 +              return true;
 +
 +      crtc_state->infoframes.enable |=
 +              intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI);
 +
 +      ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector,
                                                       adjusted_mode);
 -      if (ret < 0) {
 -              DRM_ERROR("couldn't fill AVI infoframe\n");
 -              return;
 -      }
 +      if (ret)
 +              return false;
  
        if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
 -              frame.avi.colorspace = HDMI_COLORSPACE_YUV420;
 +              frame->colorspace = HDMI_COLORSPACE_YUV420;
        else if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
 -              frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
 +              frame->colorspace = HDMI_COLORSPACE_YUV444;
        else
 -              frame.avi.colorspace = HDMI_COLORSPACE_RGB;
 +              frame->colorspace = HDMI_COLORSPACE_RGB;
  
 -      drm_hdmi_avi_infoframe_colorspace(&frame.avi, conn_state);
++      drm_hdmi_avi_infoframe_colorspace(frame, conn_state);
+ 
 -      drm_hdmi_avi_infoframe_quant_range(&frame.avi,
 -                                         conn_state->connector,
 +      drm_hdmi_avi_infoframe_quant_range(frame, connector,
                                           adjusted_mode,
                                           crtc_state->limited_color_range ?
                                           HDMI_QUANTIZATION_RANGE_LIMITED :