Use the generic HDMI infoframe helpers to get rid of the duplicate
implementation in the i915 driver.

Signed-off-by: Thierry Reding <thierry.reding at avionic-design.de>
---
 drivers/gpu/drm/Kconfig           |   2 +
 drivers/gpu/drm/i915/intel_drv.h  |  62 +--------
 drivers/gpu/drm/i915/intel_hdmi.c | 268 +++++++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_sdvo.c |  22 ++--
 4 files changed, 159 insertions(+), 195 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 94a4623..5225012 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -144,6 +144,8 @@ config DRM_I915
        select INPUT if ACPI
        select ACPI_VIDEO if ACPI
        select ACPI_BUTTON if ACPI
+       select DRM_HDMI
+       select HDMI
        help
          Choose this option if you have a system that has "Intel Graphics
          Media Accelerator" or "HD Graphics" integrated graphics,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 522061c..70a7440 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -276,63 +276,6 @@ struct cxsr_latency {
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 #define to_intel_plane(x) container_of(x, struct intel_plane, base)

-#define DIP_HEADER_SIZE        5
-
-#define DIP_TYPE_AVI    0x82
-#define DIP_VERSION_AVI 0x2
-#define DIP_LEN_AVI     13
-#define DIP_AVI_PR_1    0
-#define DIP_AVI_PR_2    1
-
-#define DIP_TYPE_SPD   0x83
-#define DIP_VERSION_SPD        0x1
-#define DIP_LEN_SPD    25
-#define DIP_SPD_UNKNOWN        0
-#define DIP_SPD_DSTB   0x1
-#define DIP_SPD_DVDP   0x2
-#define DIP_SPD_DVHS   0x3
-#define DIP_SPD_HDDVR  0x4
-#define DIP_SPD_DVC    0x5
-#define DIP_SPD_DSC    0x6
-#define DIP_SPD_VCD    0x7
-#define DIP_SPD_GAME   0x8
-#define DIP_SPD_PC     0x9
-#define DIP_SPD_BD     0xa
-#define DIP_SPD_SCD    0xb
-
-struct dip_infoframe {
-       uint8_t type;           /* HB0 */
-       uint8_t ver;            /* HB1 */
-       uint8_t len;            /* HB2 - body len, not including checksum */
-       uint8_t ecc;            /* Header ECC */
-       uint8_t checksum;       /* PB0 */
-       union {
-               struct {
-                       /* PB1 - Y 6:5, A 4:4, B 3:2, S 1:0 */
-                       uint8_t Y_A_B_S;
-                       /* PB2 - C 7:6, M 5:4, R 3:0 */
-                       uint8_t C_M_R;
-                       /* PB3 - ITC 7:7, EC 6:4, Q 3:2, SC 1:0 */
-                       uint8_t ITC_EC_Q_SC;
-                       /* PB4 - VIC 6:0 */
-                       uint8_t VIC;
-                       /* PB5 - YQ 7:6, CN 5:4, PR 3:0 */
-                       uint8_t YQ_CN_PR;
-                       /* PB6 to PB13 */
-                       uint16_t top_bar_end;
-                       uint16_t bottom_bar_start;
-                       uint16_t left_bar_end;
-                       uint16_t right_bar_start;
-               } __attribute__ ((packed)) avi;
-               struct {
-                       uint8_t vn[8];
-                       uint8_t pd[16];
-                       uint8_t sdi;
-               } __attribute__ ((packed)) spd;
-               uint8_t payload[27];
-       } __attribute__ ((packed)) body;
-} __attribute__((packed));
-
 struct intel_hdmi {
        u32 sdvox_reg;
        int ddc_bus;
@@ -340,8 +283,8 @@ struct intel_hdmi {
        bool has_hdmi_sink;
        bool has_audio;
        enum hdmi_force_audio force_audio;
-       void (*write_infoframe)(struct drm_encoder *encoder,
-                               struct dip_infoframe *frame);
+       void (*write_infoframe)(struct drm_encoder *encoder, const void *frame,
+                               size_t len);
        void (*set_infoframes)(struct drm_encoder *encoder,
                               struct drm_display_mode *adjusted_mode);
 };
@@ -430,7 +373,6 @@ extern struct intel_hdmi *enc_to_intel_hdmi(struct 
drm_encoder *encoder);
 extern bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
                                  const struct drm_display_mode *mode,
                                  struct drm_display_mode *adjusted_mode);
-extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
                            bool is_sdvob);
 extern void intel_dvo_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
b/drivers/gpu/drm/i915/intel_hdmi.c
index 5c279b4..a5492b1 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -29,9 +29,11 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/hdmi.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_hdmi.h>
 #include "intel_drv.h"
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
@@ -66,102 +68,112 @@ static struct intel_hdmi *intel_attached_hdmi(struct 
drm_connector *connector)
        return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base);
 }

-void intel_dip_infoframe_csum(struct dip_infoframe *frame)
+static u32 g4x_infoframe_index(enum hdmi_infoframe_type type)
 {
-       uint8_t *data = (uint8_t *)frame;
-       uint8_t sum = 0;
-       unsigned i;
-
-       frame->checksum = 0;
-       frame->ecc = 0;
-
-       for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
-               sum += data[i];
-
-       frame->checksum = 0x100 - sum;
-}
-
-static u32 g4x_infoframe_index(struct dip_infoframe *frame)
-{
-       switch (frame->type) {
-       case DIP_TYPE_AVI:
+       switch (type) {
+       case HDMI_INFOFRAME_TYPE_AVI:
                return VIDEO_DIP_SELECT_AVI;
-       case DIP_TYPE_SPD:
+       case HDMI_INFOFRAME_TYPE_SPD:
                return VIDEO_DIP_SELECT_SPD;
        default:
-               DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+               DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
                return 0;
        }
 }

-static u32 g4x_infoframe_enable(struct dip_infoframe *frame)
+static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type)
 {
-       switch (frame->type) {
-       case DIP_TYPE_AVI:
+       switch (type) {
+       case HDMI_INFOFRAME_TYPE_AVI:
                return VIDEO_DIP_ENABLE_AVI;
-       case DIP_TYPE_SPD:
+       case HDMI_INFOFRAME_TYPE_SPD:
                return VIDEO_DIP_ENABLE_SPD;
        default:
-               DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+               DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
                return 0;
        }
 }

-static u32 hsw_infoframe_enable(struct dip_infoframe *frame)
+static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
 {
-       switch (frame->type) {
-       case DIP_TYPE_AVI:
+       switch (type) {
+       case HDMI_INFOFRAME_TYPE_AVI:
                return VIDEO_DIP_ENABLE_AVI_HSW;
-       case DIP_TYPE_SPD:
+       case HDMI_INFOFRAME_TYPE_SPD:
                return VIDEO_DIP_ENABLE_SPD_HSW;
        default:
-               DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+               DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
                return 0;
        }
 }

-static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame, enum pipe pipe)
+static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type, enum pipe 
pipe)
 {
-       switch (frame->type) {
-       case DIP_TYPE_AVI:
+       switch (type) {
+       case HDMI_INFOFRAME_TYPE_AVI:
                return HSW_TVIDEO_DIP_AVI_DATA(pipe);
-       case DIP_TYPE_SPD:
+       case HDMI_INFOFRAME_TYPE_SPD:
                return HSW_TVIDEO_DIP_SPD_DATA(pipe);
        default:
-               DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
+               DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
                return 0;
        }
 }

-static void g4x_write_infoframe(struct drm_encoder *encoder,
-                               struct dip_infoframe *frame)
+static u32 intel_dip_pack(const u8 *data, size_t size)
 {
-       uint32_t *data = (uint32_t *)frame;
+       u32 value = 0;
+       size_t i;
+
+       for (i = size; i > 0; i--)
+               value = (value << 8) | data[i - 1];
+
+       return value;
+}
+
+static void g4x_dip_write(struct drm_i915_private *dev_priv,
+                         unsigned long offset, const void *dip, size_t len)
+{
+       u32 data;
+       size_t i;
+
+       /* Write infoframe header and zero out ECC at byte 4 */
+       data = intel_dip_pack(dip, 3);
+       I915_WRITE(offset, data);
+
+       for (i = 3; i < len; i += 4) {
+               size_t rem = min_t(size_t, len - i, 4);
+               data = intel_dip_pack(dip + i, rem);
+               I915_WRITE(offset, data);
+       }
+
+       /* Write every possible data byte to force correct ECC calculation. */
+       for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
+               I915_WRITE(offset, 0);
+}
+
+static void g4x_write_infoframe(struct drm_encoder *encoder, const void *frame,
+                               size_t len)
+{
+       enum hdmi_infoframe_type type = ((const u8 *)frame)[0];
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 val = I915_READ(VIDEO_DIP_CTL);
-       unsigned i, len = DIP_HEADER_SIZE + frame->len;

        WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");

        val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
-       val |= g4x_infoframe_index(frame);
+       val |= g4x_infoframe_index(type);

-       val &= ~g4x_infoframe_enable(frame);
+       val &= ~g4x_infoframe_enable(type);

        I915_WRITE(VIDEO_DIP_CTL, val);

        mmiowb();
-       for (i = 0; i < len; i += 4) {
-               I915_WRITE(VIDEO_DIP_DATA, *data);
-               data++;
-       }
-       /* Write every possible data byte to force correct ECC calculation. */
-       for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
-               I915_WRITE(VIDEO_DIP_DATA, 0);
+       g4x_dip_write(dev_priv, VIDEO_DIP_DATA, frame, len);
        mmiowb();

-       val |= g4x_infoframe_enable(frame);
+       val |= g4x_infoframe_enable(type);
        val &= ~VIDEO_DIP_FREQ_MASK;
        val |= VIDEO_DIP_FREQ_VSYNC;

@@ -169,37 +181,31 @@ static void g4x_write_infoframe(struct drm_encoder 
*encoder,
        POSTING_READ(VIDEO_DIP_CTL);
 }

-static void ibx_write_infoframe(struct drm_encoder *encoder,
-                               struct dip_infoframe *frame)
+static void ibx_write_infoframe(struct drm_encoder *encoder, const void *frame,
+                               size_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       enum hdmi_infoframe_type type = ((const u8 *)frame)[0];
        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);
        int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
-       unsigned i, len = DIP_HEADER_SIZE + frame->len;
        u32 val = I915_READ(reg);

        WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");

        val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
-       val |= g4x_infoframe_index(frame);
+       val |= g4x_infoframe_index(type);

-       val &= ~g4x_infoframe_enable(frame);
+       val &= ~g4x_infoframe_enable(type);

        I915_WRITE(reg, val);

        mmiowb();
-       for (i = 0; i < len; i += 4) {
-               I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
-               data++;
-       }
-       /* Write every possible data byte to force correct ECC calculation. */
-       for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
-               I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
+       g4x_dip_write(dev_priv, TVIDEO_DIP_DATA(intel_crtc->pipe), frame,
+                       len);
        mmiowb();

-       val |= g4x_infoframe_enable(frame);
+       val |= g4x_infoframe_enable(type);
        val &= ~VIDEO_DIP_FREQ_MASK;
        val |= VIDEO_DIP_FREQ_VSYNC;

@@ -207,40 +213,33 @@ static void ibx_write_infoframe(struct drm_encoder 
*encoder,
        POSTING_READ(reg);
 }

-static void cpt_write_infoframe(struct drm_encoder *encoder,
-                               struct dip_infoframe *frame)
+static void cpt_write_infoframe(struct drm_encoder *encoder, const void *frame,
+                               size_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       enum hdmi_infoframe_type type = ((const u8 *)frame)[0];
        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);
        int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
-       unsigned i, len = DIP_HEADER_SIZE + frame->len;
        u32 val = I915_READ(reg);

        WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");

        val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
-       val |= g4x_infoframe_index(frame);
+       val |= g4x_infoframe_index(type);

        /* The DIP control register spec says that we need to update the AVI
         * infoframe without clearing its enable bit */
-       if (frame->type != DIP_TYPE_AVI)
-               val &= ~g4x_infoframe_enable(frame);
+       if (type != HDMI_INFOFRAME_TYPE_AVI)
+               val &= ~g4x_infoframe_enable(type);

        I915_WRITE(reg, val);

        mmiowb();
-       for (i = 0; i < len; i += 4) {
-               I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
-               data++;
-       }
-       /* Write every possible data byte to force correct ECC calculation. */
-       for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
-               I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
+       g4x_dip_write(dev_priv, TVIDEO_DIP_DATA(intel_crtc->pipe), frame, len);
        mmiowb();

-       val |= g4x_infoframe_enable(frame);
+       val |= g4x_infoframe_enable(type);
        val &= ~VIDEO_DIP_FREQ_MASK;
        val |= VIDEO_DIP_FREQ_VSYNC;

@@ -248,37 +247,31 @@ static void cpt_write_infoframe(struct drm_encoder 
*encoder,
        POSTING_READ(reg);
 }

-static void vlv_write_infoframe(struct drm_encoder *encoder,
-                                    struct dip_infoframe *frame)
+static void vlv_write_infoframe(struct drm_encoder *encoder, const void *frame,
+                               size_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       enum hdmi_infoframe_type type = ((const u8 *)frame)[0];
        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);
        int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
-       unsigned i, len = DIP_HEADER_SIZE + frame->len;
        u32 val = I915_READ(reg);

        WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");

        val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
-       val |= g4x_infoframe_index(frame);
+       val |= g4x_infoframe_index(type);

-       val &= ~g4x_infoframe_enable(frame);
+       val &= ~g4x_infoframe_enable(type);

        I915_WRITE(reg, val);

        mmiowb();
-       for (i = 0; i < len; i += 4) {
-               I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
-               data++;
-       }
-       /* Write every possible data byte to force correct ECC calculation. */
-       for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
-               I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
+       g4x_dip_write(dev_priv, VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), frame,
+                     len);
        mmiowb();

-       val |= g4x_infoframe_enable(frame);
+       val |= g4x_infoframe_enable(type);
        val &= ~VIDEO_DIP_FREQ_MASK;
        val |= VIDEO_DIP_FREQ_VSYNC;

@@ -286,76 +279,105 @@ static void vlv_write_infoframe(struct drm_encoder 
*encoder,
        POSTING_READ(reg);
 }

-static void hsw_write_infoframe(struct drm_encoder *encoder,
-                               struct dip_infoframe *frame)
+static void hsw_write_infoframe(struct drm_encoder *encoder, const void *frame,
+                               size_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       enum hdmi_infoframe_type type = ((const u8 *)frame)[0];
        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 data_reg = hsw_infoframe_data_reg(type, intel_crtc->pipe);
        u32 val = I915_READ(ctl_reg);
+       unsigned long offset;
+       u32 data;
+       size_t i;

        if (data_reg == 0)
                return;

-       val &= ~hsw_infoframe_enable(frame);
+       val &= ~hsw_infoframe_enable(type);
        I915_WRITE(ctl_reg, val);

        mmiowb();
-       for (i = 0; i < len; i += 4) {
-               I915_WRITE(data_reg + i, *data);
-               data++;
+
+       /* Write infoframe header and zero out ECC at byte 4 */
+       data = intel_dip_pack(frame, 3);
+       I915_WRITE(data_reg, data);
+
+       for (i = 3, offset = 4; i < len; i += 4, offset += 4) {
+               size_t rem = min_t(size_t, len - i, 4);
+               data = intel_dip_pack(frame + i, rem);
+               I915_WRITE(data_reg + offset, data);
        }
+
        /* Write every possible data byte to force correct ECC calculation. */
-       for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
-               I915_WRITE(data_reg + i, 0);
+       for (; i < VIDEO_DIP_DATA_SIZE; i += 4, offset += 4)
+               I915_WRITE(data_reg + offset, 0);
+
        mmiowb();

-       val |= hsw_infoframe_enable(frame);
+       val |= hsw_infoframe_enable(type);
        I915_WRITE(ctl_reg, val);
        POSTING_READ(ctl_reg);
 }

+/*
 static void intel_set_infoframe(struct drm_encoder *encoder,
-                               struct dip_infoframe *frame)
+                               const struct hdmi_infoframe *frame)
 {
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       u8 buffer[32];
+       ssize_t len;

-       intel_dip_infoframe_csum(frame);
-       intel_hdmi->write_infoframe(encoder, frame);
+       len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
+       if (len < 0)
+               return;
+
+       intel_hdmi->write_infoframe(encoder, buffer, len);
 }
+*/

 static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
                                         struct drm_display_mode *adjusted_mode)
 {
-       struct dip_infoframe avi_if = {
-               .type = DIP_TYPE_AVI,
-               .ver = DIP_VERSION_AVI,
-               .len = DIP_LEN_AVI,
-       };
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       u8 buffer[HDMI_AVI_INFOFRAME_SIZE];
+       struct hdmi_avi_infoframe frame;
+       ssize_t len;
+
+       len = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
+       if (len < 0)
+               return;

        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
-               avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2;
+               frame.pixel_repeat = 2;
+
+       len = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
+       if (len < 0)
+               return;

-       intel_set_infoframe(encoder, &avi_if);
+       intel_hdmi->write_infoframe(encoder, buffer, len);
 }

 static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
 {
-       struct dip_infoframe spd_if;
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       u8 buffer[HDMI_SPD_INFOFRAME_SIZE];
+       struct hdmi_spd_infoframe frame;
+       ssize_t len;
+
+       len = hdmi_spd_infoframe_init(&frame, "Intel", "Integrated gfx");
+       if (len < 0)
+               return;
+
+       frame.sdi = HDMI_SPD_SDI_PC;

-       memset(&spd_if, 0, sizeof(spd_if));
-       spd_if.type = DIP_TYPE_SPD;
-       spd_if.ver = DIP_VERSION_SPD;
-       spd_if.len = DIP_LEN_SPD;
-       strcpy(spd_if.body.spd.vn, "Intel");
-       strcpy(spd_if.body.spd.pd, "Integrated gfx");
-       spd_if.body.spd.sdi = DIP_SPD_PC;
+       len = hdmi_spd_infoframe_pack(&frame, buffer, sizeof(buffer));
+       if (len < 0)
+               return;

-       intel_set_infoframe(encoder, &spd_if);
+       intel_hdmi->write_infoframe(encoder, buffer, len);
 }

 static void g4x_set_infoframes(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
b/drivers/gpu/drm/i915/intel_sdvo.c
index 4b07401..192d791 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/export.h>
+#include <linux/hdmi.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -935,20 +936,17 @@ static bool intel_sdvo_write_infoframe(struct intel_sdvo 
*intel_sdvo,

 static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
 {
-       struct dip_infoframe avi_if = {
-               .type = DIP_TYPE_AVI,
-               .ver = DIP_VERSION_AVI,
-               .len = DIP_LEN_AVI,
-       };
-       uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
+       uint8_t sdvo_data[HDMI_AVI_INFOFRAME_SIZE];
+       struct hdmi_avi_infoframe frame;
+       ssize_t len;

-       intel_dip_infoframe_csum(&avi_if);
+       len = hdmi_avi_infoframe_init(&frame);
+       if (len < 0)
+               return false;

-       /* sdvo spec says that the ecc is handled by the hw, and it looks like
-        * we must not send the ecc field, either. */
-       memcpy(sdvo_data, &avi_if, 3);
-       sdvo_data[3] = avi_if.checksum;
-       memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
+       len = hdmi_avi_infoframe_pack(&frame, sdvo_data, sizeof(sdvo_data));
+       if (len < 0)
+               return false;

        return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
                                          SDVO_HBUF_TX_VSYNC,
-- 
1.8.0.1

Reply via email to