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 :