]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
video/hdmi: Introduce helpers for the HDMI vendor specific infoframe
authorLespiau, Damien <damien.lespiau@intel.com>
Mon, 19 Aug 2013 15:58:58 +0000 (16:58 +0100)
committerDave Airlie <airlied@gmail.com>
Thu, 29 Aug 2013 22:40:45 +0000 (08:40 +1000)
Provide the same programming model than the other infoframe types.

The generic _pack() function can't handle those yet as we need to move
the vendor OUI in the generic hdmi_vendor_infoframe structure to know
which kind of vendor infoframe we are dealing with.

v2: Fix the value of Side-by-side (half), hmdi typo, pack 3D_Ext_Data
    (Ville Syrjälä)
v3: Future proof the sending of 3D_Ext_Data (Ville Syrjälä), Fix
    multi-lines comment style (Thierry Reding)

Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dave Airlie <airlied@gmail.com>
drivers/video/hdmi.c
include/linux/hdmi.h

index 1201357f3e3cf8a01640f65efa0085e53703043b..4c42bcb8653562d91bd03a1abf496c206619d0cc 100644 (file)
@@ -287,6 +287,96 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
 }
 EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
 
+/**
+ * hdmi_hdmi_infoframe_init() - initialize an HDMI vendor infoframe
+ * @frame: HDMI vendor infoframe
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_hdmi_infoframe_init(struct hdmi_hdmi_infoframe *frame)
+{
+       memset(frame, 0, sizeof(*frame));
+
+       frame->type = HDMI_INFOFRAME_TYPE_VENDOR;
+       frame->version = 1;
+
+       /*
+        * 0 is a valid value for s3d_struct, so we use a special "not set"
+        * value
+        */
+       frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID;
+
+       return 0;
+}
+EXPORT_SYMBOL(hdmi_hdmi_infoframe_init);
+
+/**
+ * hdmi_hdmi_infoframe_pack() - write a HDMI vendor infoframe to binary buffer
+ * @frame: HDMI infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers. 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_hdmi_infoframe_pack(struct hdmi_hdmi_infoframe *frame,
+                                void *buffer, size_t size)
+{
+       u8 *ptr = buffer;
+       size_t length;
+
+       /* empty info frame */
+       if (frame->vic == 0 && frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID)
+               return -EINVAL;
+
+       /* only one of those can be supplied */
+       if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
+               return -EINVAL;
+
+       /* for side by side (half) we also need to provide 3D_Ext_Data */
+       if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
+               frame->length = 6;
+       else
+               frame->length = 5;
+
+       length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
+
+       if (size < length)
+               return -ENOSPC;
+
+       memset(buffer, 0, size);
+
+       ptr[0] = frame->type;
+       ptr[1] = frame->version;
+       ptr[2] = frame->length;
+       ptr[3] = 0; /* checksum */
+
+       /* HDMI OUI */
+       ptr[4] = 0x03;
+       ptr[5] = 0x0c;
+       ptr[6] = 0x00;
+
+       if (frame->vic) {
+               ptr[7] = 0x1 << 5;      /* video format */
+               ptr[8] = frame->vic;
+       } else {
+               ptr[7] = 0x2 << 5;      /* video format */
+               ptr[8] = (frame->s3d_struct & 0xf) << 4;
+               if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
+                       ptr[9] = (frame->s3d_ext_data & 0xf) << 4;
+       }
+
+       hdmi_infoframe_checksum(buffer, length);
+
+       return length;
+}
+EXPORT_SYMBOL(hdmi_hdmi_infoframe_pack);
+
 /**
  * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary
  *                                buffer
index b98340b82e0570672b04847c5f2b51113ad5c0c5..e733252c2b5db028824d884657f894f2cd8de427 100644 (file)
@@ -234,11 +234,37 @@ struct hdmi_vendor_infoframe {
 ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
                                   void *buffer, size_t size);
 
+enum hdmi_3d_structure {
+       HDMI_3D_STRUCTURE_INVALID = -1,
+       HDMI_3D_STRUCTURE_FRAME_PACKING = 0,
+       HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE,
+       HDMI_3D_STRUCTURE_LINE_ALTERNATIVE,
+       HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL,
+       HDMI_3D_STRUCTURE_L_DEPTH,
+       HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH,
+       HDMI_3D_STRUCTURE_TOP_AND_BOTTOM,
+       HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF = 8,
+};
+
+struct hdmi_hdmi_infoframe {
+       enum hdmi_infoframe_type type;
+       unsigned char version;
+       unsigned char length;
+       u8 vic;
+       enum hdmi_3d_structure s3d_struct;
+       unsigned int s3d_ext_data;
+};
+
+int hdmi_hdmi_infoframe_init(struct hdmi_hdmi_infoframe *frame);
+ssize_t hdmi_hdmi_infoframe_pack(struct hdmi_hdmi_infoframe *frame,
+                                void *buffer, size_t size);
+
 union hdmi_infoframe {
        struct hdmi_any_infoframe any;
        struct hdmi_avi_infoframe avi;
        struct hdmi_spd_infoframe spd;
        struct hdmi_vendor_infoframe vendor;
+       struct hdmi_hdmi_infoframe hdmi;
        struct hdmi_audio_infoframe audio;
 };