Merge tag 'drm-misc-next-2018-11-07' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-block.git] / drivers / video / hdmi.c
index 8a3e8f61b991bd7fb14a5552eed46a56c88a1d6a..799ae49774f58e1e00e70cd9fe188f39bf9b08a5 100644 (file)
@@ -31,7 +31,7 @@
 
 #define hdmi_log(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__)
 
-static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
+static u8 hdmi_infoframe_checksum(const u8 *ptr, size_t size)
 {
        u8 csum = 0;
        size_t i;
@@ -68,8 +68,36 @@ int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
 }
 EXPORT_SYMBOL(hdmi_avi_infoframe_init);
 
+static int hdmi_avi_infoframe_check_only(const struct hdmi_avi_infoframe *frame)
+{
+       if (frame->type != HDMI_INFOFRAME_TYPE_AVI ||
+           frame->version != 2 ||
+           frame->length != HDMI_AVI_INFOFRAME_SIZE)
+               return -EINVAL;
+
+       if (frame->picture_aspect > HDMI_PICTURE_ASPECT_16_9)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
- * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
+ * hdmi_avi_infoframe_check() - check a HDMI AVI infoframe
+ * @frame: HDMI AVI infoframe
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame)
+{
+       return hdmi_avi_infoframe_check_only(frame);
+}
+EXPORT_SYMBOL(hdmi_avi_infoframe_check);
+
+/**
+ * hdmi_avi_infoframe_pack_only() - write HDMI AVI infoframe to binary buffer
  * @frame: HDMI AVI infoframe
  * @buffer: destination buffer
  * @size: size of buffer
@@ -82,20 +110,22 @@ EXPORT_SYMBOL(hdmi_avi_infoframe_init);
  * Returns the number of bytes packed into the binary buffer or a negative
  * error code on failure.
  */
-ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
-                               size_t size)
+ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,
+                                    void *buffer, size_t size)
 {
        u8 *ptr = buffer;
        size_t length;
+       int ret;
+
+       ret = hdmi_avi_infoframe_check_only(frame);
+       if (ret)
+               return ret;
 
        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
        if (size < length)
                return -ENOSPC;
 
-       if (frame->picture_aspect > HDMI_PICTURE_ASPECT_16_9)
-               return -EINVAL;
-
        memset(buffer, 0, size);
 
        ptr[0] = frame->type;
@@ -152,6 +182,36 @@ ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
 
        return length;
 }
+EXPORT_SYMBOL(hdmi_avi_infoframe_pack_only);
+
+/**
+ * hdmi_avi_infoframe_pack() - check a HDMI AVI infoframe,
+ *                             and write it to binary buffer
+ * @frame: HDMI AVI infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields, after which it packs the information
+ * contained in the @frame structure into a binary representation that
+ * can be written into the corresponding controller registers. This function
+ * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame,
+                               void *buffer, size_t size)
+{
+       int ret;
+
+       ret = hdmi_avi_infoframe_check(frame);
+       if (ret)
+               return ret;
+
+       return hdmi_avi_infoframe_pack_only(frame, buffer, size);
+}
 EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
 
 /**
@@ -178,8 +238,33 @@ int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
 }
 EXPORT_SYMBOL(hdmi_spd_infoframe_init);
 
+static int hdmi_spd_infoframe_check_only(const struct hdmi_spd_infoframe *frame)
+{
+       if (frame->type != HDMI_INFOFRAME_TYPE_SPD ||
+           frame->version != 1 ||
+           frame->length != HDMI_SPD_INFOFRAME_SIZE)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
- * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer
+ * hdmi_spd_infoframe_check() - check a HDMI SPD infoframe
+ * @frame: HDMI SPD infoframe
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_spd_infoframe_check(struct hdmi_spd_infoframe *frame)
+{
+       return hdmi_spd_infoframe_check_only(frame);
+}
+EXPORT_SYMBOL(hdmi_spd_infoframe_check);
+
+/**
+ * hdmi_spd_infoframe_pack_only() - write HDMI SPD infoframe to binary buffer
  * @frame: HDMI SPD infoframe
  * @buffer: destination buffer
  * @size: size of buffer
@@ -192,11 +277,16 @@ EXPORT_SYMBOL(hdmi_spd_infoframe_init);
  * Returns the number of bytes packed into the binary buffer or a negative
  * error code on failure.
  */
-ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
-                               size_t size)
+ssize_t hdmi_spd_infoframe_pack_only(const struct hdmi_spd_infoframe *frame,
+                                    void *buffer, size_t size)
 {
        u8 *ptr = buffer;
        size_t length;
+       int ret;
+
+       ret = hdmi_spd_infoframe_check_only(frame);
+       if (ret)
+               return ret;
 
        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
@@ -222,6 +312,36 @@ ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
 
        return length;
 }
+EXPORT_SYMBOL(hdmi_spd_infoframe_pack_only);
+
+/**
+ * hdmi_spd_infoframe_pack() - check a HDMI SPD infoframe,
+ *                             and write it to binary buffer
+ * @frame: HDMI SPD infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields, after which it packs the information
+ * contained in the @frame structure into a binary representation that
+ * can be written into the corresponding controller registers. This function
+ * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame,
+                               void *buffer, size_t size)
+{
+       int ret;
+
+       ret = hdmi_spd_infoframe_check(frame);
+       if (ret)
+               return ret;
+
+       return hdmi_spd_infoframe_pack_only(frame, buffer, size);
+}
 EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
 
 /**
@@ -242,8 +362,33 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
 }
 EXPORT_SYMBOL(hdmi_audio_infoframe_init);
 
+static int hdmi_audio_infoframe_check_only(const struct hdmi_audio_infoframe *frame)
+{
+       if (frame->type != HDMI_INFOFRAME_TYPE_AUDIO ||
+           frame->version != 1 ||
+           frame->length != HDMI_AUDIO_INFOFRAME_SIZE)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
- * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
+ * hdmi_audio_infoframe_check() - check a HDMI audio infoframe
+ * @frame: HDMI audio infoframe
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_audio_infoframe_check(struct hdmi_audio_infoframe *frame)
+{
+       return hdmi_audio_infoframe_check_only(frame);
+}
+EXPORT_SYMBOL(hdmi_audio_infoframe_check);
+
+/**
+ * hdmi_audio_infoframe_pack_only() - write HDMI audio infoframe to binary buffer
  * @frame: HDMI audio infoframe
  * @buffer: destination buffer
  * @size: size of buffer
@@ -256,12 +401,17 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_init);
  * Returns the number of bytes packed into the binary buffer or a negative
  * error code on failure.
  */
-ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
-                                 void *buffer, size_t size)
+ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame,
+                                      void *buffer, size_t size)
 {
        unsigned char channels;
        u8 *ptr = buffer;
        size_t length;
+       int ret;
+
+       ret = hdmi_audio_infoframe_check_only(frame);
+       if (ret)
+               return ret;
 
        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
@@ -297,6 +447,36 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
 
        return length;
 }
+EXPORT_SYMBOL(hdmi_audio_infoframe_pack_only);
+
+/**
+ * hdmi_audio_infoframe_pack() - check a HDMI Audio infoframe,
+ *                               and write it to binary buffer
+ * @frame: HDMI Audio infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields, after which it packs the information
+ * contained in the @frame structure into a binary representation that
+ * can be written into the corresponding controller registers. This function
+ * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
+                                 void *buffer, size_t size)
+{
+       int ret;
+
+       ret = hdmi_audio_infoframe_check(frame);
+       if (ret)
+               return ret;
+
+       return hdmi_audio_infoframe_pack_only(frame, buffer, size);
+}
 EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
 
 /**
@@ -319,6 +499,7 @@ int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)
         * value
         */
        frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID;
+       frame->length = 4;
 
        return 0;
 }
@@ -335,8 +516,42 @@ static int hdmi_vendor_infoframe_length(const struct hdmi_vendor_infoframe *fram
                return 4;
 }
 
+static int hdmi_vendor_infoframe_check_only(const struct hdmi_vendor_infoframe *frame)
+{
+       if (frame->type != HDMI_INFOFRAME_TYPE_VENDOR ||
+           frame->version != 1 ||
+           frame->oui != HDMI_IEEE_OUI)
+               return -EINVAL;
+
+       /* only one of those can be supplied */
+       if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
+               return -EINVAL;
+
+       if (frame->length != hdmi_vendor_infoframe_length(frame))
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ * hdmi_vendor_infoframe_check() - check a HDMI vendor infoframe
+ * @frame: HDMI infoframe
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_vendor_infoframe_check(struct hdmi_vendor_infoframe *frame)
+{
+       frame->length = hdmi_vendor_infoframe_length(frame);
+
+       return hdmi_vendor_infoframe_check_only(frame);
+}
+EXPORT_SYMBOL(hdmi_vendor_infoframe_check);
+
 /**
- * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary buffer
+ * hdmi_vendor_infoframe_pack_only() - write a HDMI vendor infoframe to binary buffer
  * @frame: HDMI infoframe
  * @buffer: destination buffer
  * @size: size of buffer
@@ -349,17 +564,16 @@ static int hdmi_vendor_infoframe_length(const struct hdmi_vendor_infoframe *fram
  * Returns the number of bytes packed into the binary buffer or a negative
  * error code on failure.
  */
-ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
-                                void *buffer, size_t size)
+ssize_t hdmi_vendor_infoframe_pack_only(const struct hdmi_vendor_infoframe *frame,
+                                       void *buffer, size_t size)
 {
        u8 *ptr = buffer;
        size_t length;
+       int ret;
 
-       /* only one of those can be supplied */
-       if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
-               return -EINVAL;
-
-       frame->length = hdmi_vendor_infoframe_length(frame);
+       ret = hdmi_vendor_infoframe_check_only(frame);
+       if (ret)
+               return ret;
 
        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
@@ -394,24 +608,134 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
 
        return length;
 }
+EXPORT_SYMBOL(hdmi_vendor_infoframe_pack_only);
+
+/**
+ * hdmi_vendor_infoframe_pack() - check a HDMI Vendor infoframe,
+ *                                and write it to binary buffer
+ * @frame: HDMI Vendor infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields, after which it packs the information
+ * contained in the @frame structure into a binary representation that
+ * can be written into the corresponding controller registers. This function
+ * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
+                                  void *buffer, size_t size)
+{
+       int ret;
+
+       ret = hdmi_vendor_infoframe_check(frame);
+       if (ret)
+               return ret;
+
+       return hdmi_vendor_infoframe_pack_only(frame, buffer, size);
+}
 EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
 
+static int
+hdmi_vendor_any_infoframe_check_only(const union hdmi_vendor_any_infoframe *frame)
+{
+       if (frame->any.type != HDMI_INFOFRAME_TYPE_VENDOR ||
+           frame->any.version != 1)
+               return -EINVAL;
+
+       return 0;
+}
+
+/*
+ * hdmi_vendor_any_infoframe_check() - check a vendor infoframe
+ */
+static int
+hdmi_vendor_any_infoframe_check(union hdmi_vendor_any_infoframe *frame)
+{
+       int ret;
+
+       ret = hdmi_vendor_any_infoframe_check_only(frame);
+       if (ret)
+               return ret;
+
+       /* we only know about HDMI vendor infoframes */
+       if (frame->any.oui != HDMI_IEEE_OUI)
+               return -EINVAL;
+
+       return hdmi_vendor_infoframe_check(&frame->hdmi);
+}
+
 /*
- * hdmi_vendor_any_infoframe_pack() - write a vendor infoframe to binary buffer
+ * hdmi_vendor_any_infoframe_pack_only() - write a vendor infoframe to binary buffer
  */
 static ssize_t
-hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame,
-                          void *buffer, size_t size)
+hdmi_vendor_any_infoframe_pack_only(const union hdmi_vendor_any_infoframe *frame,
+                                   void *buffer, size_t size)
 {
+       int ret;
+
+       ret = hdmi_vendor_any_infoframe_check_only(frame);
+       if (ret)
+               return ret;
+
        /* we only know about HDMI vendor infoframes */
        if (frame->any.oui != HDMI_IEEE_OUI)
                return -EINVAL;
 
-       return hdmi_vendor_infoframe_pack(&frame->hdmi, buffer, size);
+       return hdmi_vendor_infoframe_pack_only(&frame->hdmi, buffer, size);
+}
+
+/*
+ * hdmi_vendor_any_infoframe_pack() - check a vendor infoframe,
+ *                                    and write it to binary buffer
+ */
+static ssize_t
+hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame,
+                              void *buffer, size_t size)
+{
+       int ret;
+
+       ret = hdmi_vendor_any_infoframe_check(frame);
+       if (ret)
+               return ret;
+
+       return hdmi_vendor_any_infoframe_pack_only(frame, buffer, size);
 }
 
 /**
- * hdmi_infoframe_pack() - write a HDMI infoframe to binary buffer
+ * hdmi_infoframe_check() - check a HDMI infoframe
+ * @frame: HDMI infoframe
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int
+hdmi_infoframe_check(union hdmi_infoframe *frame)
+{
+       switch (frame->any.type) {
+       case HDMI_INFOFRAME_TYPE_AVI:
+               return hdmi_avi_infoframe_check(&frame->avi);
+       case HDMI_INFOFRAME_TYPE_SPD:
+               return hdmi_spd_infoframe_check(&frame->spd);
+       case HDMI_INFOFRAME_TYPE_AUDIO:
+               return hdmi_audio_infoframe_check(&frame->audio);
+       case HDMI_INFOFRAME_TYPE_VENDOR:
+               return hdmi_vendor_any_infoframe_check(&frame->vendor);
+       default:
+               WARN(1, "Bad infoframe type %d\n", frame->any.type);
+               return -EINVAL;
+       }
+}
+EXPORT_SYMBOL(hdmi_infoframe_check);
+
+/**
+ * hdmi_infoframe_pack_only() - write a HDMI infoframe to binary buffer
  * @frame: HDMI infoframe
  * @buffer: destination buffer
  * @size: size of buffer
@@ -425,7 +749,56 @@ hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame,
  * error code on failure.
  */
 ssize_t
-hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size)
+hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, void *buffer, size_t size)
+{
+       ssize_t length;
+
+       switch (frame->any.type) {
+       case HDMI_INFOFRAME_TYPE_AVI:
+               length = hdmi_avi_infoframe_pack_only(&frame->avi,
+                                                     buffer, size);
+               break;
+       case HDMI_INFOFRAME_TYPE_SPD:
+               length = hdmi_spd_infoframe_pack_only(&frame->spd,
+                                                     buffer, size);
+               break;
+       case HDMI_INFOFRAME_TYPE_AUDIO:
+               length = hdmi_audio_infoframe_pack_only(&frame->audio,
+                                                       buffer, size);
+               break;
+       case HDMI_INFOFRAME_TYPE_VENDOR:
+               length = hdmi_vendor_any_infoframe_pack_only(&frame->vendor,
+                                                            buffer, size);
+               break;
+       default:
+               WARN(1, "Bad infoframe type %d\n", frame->any.type);
+               length = -EINVAL;
+       }
+
+       return length;
+}
+EXPORT_SYMBOL(hdmi_infoframe_pack_only);
+
+/**
+ * hdmi_infoframe_pack() - check a HDMI infoframe,
+ *                         and write it to binary buffer
+ * @frame: HDMI infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Validates that the infoframe is consistent and updates derived fields
+ * (eg. length) based on other fields, after which it packs the information
+ * contained in the @frame structure into a binary representation that
+ * can be written into the corresponding controller registers. This function
+ * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t
+hdmi_infoframe_pack(union hdmi_infoframe *frame,
+                   void *buffer, size_t size)
 {
        ssize_t length;
 
@@ -471,7 +844,7 @@ static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type)
 
 static void hdmi_infoframe_log_header(const char *level,
                                      struct device *dev,
-                                     struct hdmi_any_infoframe *frame)
+                                     const struct hdmi_any_infoframe *frame)
 {
        hdmi_log("HDMI infoframe: %s, version %u, length %u\n",
                hdmi_infoframe_type_get_name(frame->type),
@@ -673,10 +1046,10 @@ hdmi_content_type_get_name(enum hdmi_content_type content_type)
  */
 static void hdmi_avi_infoframe_log(const char *level,
                                   struct device *dev,
-                                  struct hdmi_avi_infoframe *frame)
+                                  const struct hdmi_avi_infoframe *frame)
 {
        hdmi_infoframe_log_header(level, dev,
-                                 (struct hdmi_any_infoframe *)frame);
+                                 (const struct hdmi_any_infoframe *)frame);
 
        hdmi_log("    colorspace: %s\n",
                        hdmi_colorspace_get_name(frame->colorspace));
@@ -750,12 +1123,12 @@ static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi)
  */
 static void hdmi_spd_infoframe_log(const char *level,
                                   struct device *dev,
-                                  struct hdmi_spd_infoframe *frame)
+                                  const struct hdmi_spd_infoframe *frame)
 {
        u8 buf[17];
 
        hdmi_infoframe_log_header(level, dev,
-                                 (struct hdmi_any_infoframe *)frame);
+                                 (const struct hdmi_any_infoframe *)frame);
 
        memset(buf, 0, sizeof(buf));
 
@@ -886,10 +1259,10 @@ hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)
  */
 static void hdmi_audio_infoframe_log(const char *level,
                                     struct device *dev,
-                                    struct hdmi_audio_infoframe *frame)
+                                    const struct hdmi_audio_infoframe *frame)
 {
        hdmi_infoframe_log_header(level, dev,
-                                 (struct hdmi_any_infoframe *)frame);
+                                 (const struct hdmi_any_infoframe *)frame);
 
        if (frame->channels)
                hdmi_log("    channels: %u\n", frame->channels - 1);
@@ -949,12 +1322,12 @@ hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)
 static void
 hdmi_vendor_any_infoframe_log(const char *level,
                              struct device *dev,
-                             union hdmi_vendor_any_infoframe *frame)
+                             const union hdmi_vendor_any_infoframe *frame)
 {
-       struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
+       const struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
 
        hdmi_infoframe_log_header(level, dev,
-                                 (struct hdmi_any_infoframe *)frame);
+                                 (const struct hdmi_any_infoframe *)frame);
 
        if (frame->any.oui != HDMI_IEEE_OUI) {
                hdmi_log("    not a HDMI vendor infoframe\n");
@@ -984,7 +1357,7 @@ hdmi_vendor_any_infoframe_log(const char *level,
  */
 void hdmi_infoframe_log(const char *level,
                        struct device *dev,
-                       union hdmi_infoframe *frame)
+                       const union hdmi_infoframe *frame)
 {
        switch (frame->any.type) {
        case HDMI_INFOFRAME_TYPE_AVI:
@@ -1005,8 +1378,9 @@ EXPORT_SYMBOL(hdmi_infoframe_log);
 
 /**
  * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe
- * @buffer: source buffer
  * @frame: HDMI AVI infoframe
+ * @buffer: source buffer
+ * @size: size of buffer
  *
  * Unpacks the information contained in binary @buffer into a structured
  * @frame of the HDMI Auxiliary Video (AVI) information frame.
@@ -1016,11 +1390,14 @@ EXPORT_SYMBOL(hdmi_infoframe_log);
  * Returns 0 on success or a negative error code on failure.
  */
 static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
-                                    void *buffer)
+                                    const void *buffer, size_t size)
 {
-       u8 *ptr = buffer;
+       const u8 *ptr = buffer;
        int ret;
 
+       if (size < HDMI_INFOFRAME_SIZE(AVI))
+               return -EINVAL;
+
        if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI ||
            ptr[1] != 2 ||
            ptr[2] != HDMI_AVI_INFOFRAME_SIZE)
@@ -1068,8 +1445,9 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
 
 /**
  * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe
- * @buffer: source buffer
  * @frame: HDMI SPD infoframe
+ * @buffer: source buffer
+ * @size: size of buffer
  *
  * Unpacks the information contained in binary @buffer into a structured
  * @frame of the HDMI Source Product Description (SPD) information frame.
@@ -1079,11 +1457,14 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
  * Returns 0 on success or a negative error code on failure.
  */
 static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
-                                    void *buffer)
+                                    const void *buffer, size_t size)
 {
-       u8 *ptr = buffer;
+       const u8 *ptr = buffer;
        int ret;
 
+       if (size < HDMI_INFOFRAME_SIZE(SPD))
+               return -EINVAL;
+
        if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD ||
            ptr[1] != 1 ||
            ptr[2] != HDMI_SPD_INFOFRAME_SIZE) {
@@ -1106,8 +1487,9 @@ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
 
 /**
  * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe
- * @buffer: source buffer
  * @frame: HDMI Audio infoframe
+ * @buffer: source buffer
+ * @size: size of buffer
  *
  * Unpacks the information contained in binary @buffer into a structured
  * @frame of the HDMI Audio information frame.
@@ -1117,11 +1499,14 @@ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
  * Returns 0 on success or a negative error code on failure.
  */
 static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
-                                      void *buffer)
+                                      const void *buffer, size_t size)
 {
-       u8 *ptr = buffer;
+       const u8 *ptr = buffer;
        int ret;
 
+       if (size < HDMI_INFOFRAME_SIZE(AUDIO))
+               return -EINVAL;
+
        if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO ||
            ptr[1] != 1 ||
            ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) {
@@ -1151,8 +1536,9 @@ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
 
 /**
  * hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe
- * @buffer: source buffer
  * @frame: HDMI Vendor infoframe
+ * @buffer: source buffer
+ * @size: size of buffer
  *
  * Unpacks the information contained in binary @buffer into a structured
  * @frame of the HDMI Vendor information frame.
@@ -1163,14 +1549,17 @@ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
  */
 static int
 hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
-                                void *buffer)
+                                const void *buffer, size_t size)
 {
-       u8 *ptr = buffer;
+       const u8 *ptr = buffer;
        size_t length;
        int ret;
        u8 hdmi_video_format;
        struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
 
+       if (size < HDMI_INFOFRAME_HEADER_SIZE)
+               return -EINVAL;
+
        if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||
            ptr[1] != 1 ||
            (ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6))
@@ -1178,6 +1567,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
 
        length = ptr[2];
 
+       if (size < HDMI_INFOFRAME_HEADER_SIZE + length)
+               return -EINVAL;
+
        if (hdmi_infoframe_checksum(buffer,
                                    HDMI_INFOFRAME_HEADER_SIZE + length) != 0)
                return -EINVAL;
@@ -1224,8 +1616,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
 
 /**
  * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe
- * @buffer: source buffer
  * @frame: HDMI infoframe
+ * @buffer: source buffer
+ * @size: size of buffer
  *
  * Unpacks the information contained in binary buffer @buffer into a structured
  * @frame of a HDMI infoframe.
@@ -1234,23 +1627,27 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
  *
  * Returns 0 on success or a negative error code on failure.
  */
-int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer)
+int hdmi_infoframe_unpack(union hdmi_infoframe *frame,
+                         const void *buffer, size_t size)
 {
        int ret;
-       u8 *ptr = buffer;
+       const u8 *ptr = buffer;
+
+       if (size < HDMI_INFOFRAME_HEADER_SIZE)
+               return -EINVAL;
 
        switch (ptr[0]) {
        case HDMI_INFOFRAME_TYPE_AVI:
-               ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer);
+               ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer, size);
                break;
        case HDMI_INFOFRAME_TYPE_SPD:
-               ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer);
+               ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer, size);
                break;
        case HDMI_INFOFRAME_TYPE_AUDIO:
-               ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer);
+               ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer, size);
                break;
        case HDMI_INFOFRAME_TYPE_VENDOR:
-               ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer);
+               ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer, size);
                break;
        default:
                ret = -EINVAL;