]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
v4l2: hdmi: update V4L2 and HDMI APIs to support HDMI IN
authorHans Verkuil <hansverk@cisco.com>
Wed, 9 Sep 2015 10:47:51 +0000 (12:47 +0200)
committermobile promotions <svcmobile_promotions@nvidia.com>
Thu, 5 May 2016 07:29:46 +0000 (00:29 -0700)
This commit squashs many patches for V4L2 API and HDMI APIs
to support HDMI IN

Bug 200169351

Change-Id: I1f82bc846fab370717be9e9e8cc5e8c9b1b50751
(cherry picked from commit dac93a08776a04f7e68b69df8f4cfb7e7aba90b6)
Signed-off-by: Ahung Cheng <ahcheng@nvidia.com>
Signed-off-by: Bryan Wu <pengw@nvidia.com>
Reviewed-on: http://git-master/r/1114725
Reviewed-on: http://git-master/r/1134597
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
47 files changed:
Documentation/DocBook/media/Makefile
Documentation/DocBook/media/v4l/pixfmt.xml
Documentation/DocBook/media/v4l/vidioc-dqevent.xml
Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
Documentation/DocBook/media/v4l/vidioc-querycap.xml
Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
drivers/media/parport/bw-qcam.c
drivers/media/pci/cx18/cx18-ioctl.c
drivers/media/pci/cx25821/cx25821-video.c
drivers/media/pci/ivtv/ivtv-ioctl.c
drivers/media/pci/meye/meye.c
drivers/media/pci/sta2x11/sta2x11_vip.c
drivers/media/platform/omap/omap_vout.c
drivers/media/platform/sh_veu.c
drivers/media/platform/vino.c
drivers/media/platform/vivi.c
drivers/media/usb/cx231xx/cx231xx-417.c
drivers/media/usb/cx231xx/cx231xx-video.c
drivers/media/usb/gspca/gspca.c
drivers/media/usb/hdpvr/hdpvr-video.c
drivers/media/usb/stkwebcam/stk-webcam.c
drivers/media/usb/tlg2300/pd-video.c
drivers/media/usb/tm6000/tm6000-video.c
drivers/media/usb/zr364xx/zr364xx.c
drivers/media/v4l2-core/Makefile
drivers/media/v4l2-core/v4l2-common.c
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/media/v4l2-core/v4l2-dev.c
drivers/media/v4l2-core/v4l2-dv-timings.c [new file with mode: 0644]
drivers/media/v4l2-core/v4l2-event.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/media/v4l2-core/v4l2-subdev.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/video/hdmi.c
include/linux/hdmi.h
include/media/v4l2-common.h
include/media/v4l2-dv-timings.h [new file with mode: 0644]
include/media/v4l2-event.h
include/media/v4l2-ioctl.h
include/media/v4l2-mediabus.h
include/media/v4l2-subdev.h
include/media/videobuf2-core.h
include/uapi/linux/v4l2-common.h
include/uapi/linux/v4l2-dv-timings.h
include/uapi/linux/v4l2-mediabus.h
include/uapi/linux/v4l2-subdev.h
include/uapi/linux/videodev2.h

index 1d27f0a1abd1e1872b0e05693ab35d6ecd64b0f2..494da944b39db6c298337f58764cc23058d52ec4 100644 (file)
@@ -174,7 +174,7 @@ FILENAME = \
 DOCUMENTED = \
        -e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1<link linkend=\"\2\">v4l2_mpeg_cx2341x_video_\2<\/link>/g" \
        -e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1<link linkend=\"\3\">\3<\/link>/g" \
-       -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /<link linkend=\"\1\">\1<\/link> /g" \
+       -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\)\(\s\+v4l2_fourcc\)/<link linkend=\"\1\">\1<\/link>\2/g" \
        -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
        -e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g"
 
index 99b8d2ad6e4ff1613db6a789c0228afde61318b5..93dd9325398b66b14b44eff3898b413adb22f050 100644 (file)
@@ -103,9 +103,28 @@ see <xref linkend="colorspaces" />.</entry>
        <row>
          <entry>__u32</entry>
          <entry><structfield>priv</structfield></entry>
-         <entry>Reserved for custom (driver defined) additional
-information about formats. When not used drivers and applications must
-set this field to zero.</entry>
+         <entry><para>This field indicates whether the remaining fields of the
+<structname>v4l2_pix_format</structname> structure, also called the extended
+fields, are valid. When set to <constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, it
+indicates that the extended fields have been correctly initialized. When set to
+any other value it indicates that the extended fields contain undefined values.
+</para>
+<para>Applications that wish to use the pixel format extended fields must first
+ensure that the feature is supported by querying the device for the
+<link linkend="querycap"><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></link>
+capability. If the capability isn't set the pixel format extended fields are not
+supported and using the extended fields will lead to undefined results.</para>
+<para>To use the extended fields, applications must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, initialize all the extended fields
+and zero the unused bytes of the <structname>v4l2_format</structname>
+<structfield>raw_data</structfield> field.</para>
+<para>When the <structfield>priv</structfield> field isn't set to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> drivers must act as if all the
+extended fields were set to zero. On return drivers must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> and all the extended fields to
+applicable values.</para></entry>
        </row>
       </tbody>
     </tgroup>
index 89891adb928a327ddca0aad20a6297563bbfce54..820f86e8744b356ae5a59144e25d4ee5edf57900 100644 (file)
       </tgroup>
     </table>
 
+    <table frame="none" pgwide="1" id="v4l2-event-src-change">
+      <title>struct <structname>v4l2_event_src_change</structname></title>
+      <tgroup cols="3">
+       &cs-str;
+       <tbody valign="top">
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>changes</structfield></entry>
+           <entry>
+             A bitmask that tells what has changed. See <xref linkend="src-changes-flags" />.
+           </entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+
     <table pgwide="1" frame="none" id="changes-flags">
       <title>Changes</title>
       <tgroup cols="3">
        </tbody>
       </tgroup>
     </table>
+
+    <table pgwide="1" frame="none" id="src-changes-flags">
+      <title>Source Changes</title>
+      <tgroup cols="3">
+       &cs-def;
+       <tbody valign="top">
+         <row>
+           <entry><constant>V4L2_EVENT_SRC_CH_RESOLUTION</constant></entry>
+           <entry>0x0001</entry>
+           <entry>This event gets triggered when a resolution change is
+           detected at an input. This can come from an input connector or
+           from a video decoder.
+           </entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
   </refsect1>
   <refsect1>
     &return-value;
index 7c63815e7afd0eb964a1848513dea5be14eb677e..20460730b02ca242e0ba5d096761ac00ea8239af 100644 (file)
@@ -152,13 +152,10 @@ a valid base address, so applications can find the corresponding Linux
 framebuffer device (see <xref linkend="osd" />).</entry>
          </row>
          <row>
-           <entry>&v4l2-pix-format;</entry>
+           <entry>struct</entry>
            <entry><structfield>fmt</structfield></entry>
            <entry></entry>
-           <entry>Layout of the frame buffer. The
-<structname>v4l2_pix_format</structname> structure is defined in <xref
-linkend="pixfmt" />, for clarification the fields and acceptable values
-           are listed below:</entry>
+           <entry>Layout of the frame buffer.</entry>
          </row>
          <row>
            <entry></entry>
@@ -276,9 +273,8 @@ see <xref linkend="colorspaces" />.</entry>
            <entry></entry>
            <entry>__u32</entry>
            <entry><structfield>priv</structfield></entry>
-           <entry>Reserved for additional information about custom
-(driver defined) formats. When not used drivers and applications must
-set this field to zero.</entry>
+           <entry>Reserved. Drivers and applications must set this field to
+zero.</entry>
          </row>
        </tbody>
       </tgroup>
index d5a3c97b206a431d9b5d7a969a56d877aee83558..1752c5b23f002103bc86727090c063dbf751aa26 100644 (file)
@@ -294,6 +294,12 @@ interface. For more information on audio inputs and outputs see <xref
 emit RF-modulated video/audio signals. For more information about
 modulator programming see
 <xref linkend="tuner" />.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></entry>
+           <entry>0x00200000</entry>
+           <entry>The device supports the &v4l2-pix-format; extended
+fields.</entry>
          </row>
          <row>
            <entry><constant>V4L2_CAP_READWRITE</constant></entry>
index 5c70b616d8185c0645044b0e270398932a0d28c9..f016254377aad2bf1c4be3d7c4e19f7e591b527f 100644 (file)
              frame interval in between them.</para>
            </entry>
          </row>
+         <row>
+           <entry><constant>V4L2_EVENT_SOURCE_CHANGE</constant></entry>
+           <entry>5</entry>
+           <entry>
+             <para>This event is triggered when a source parameter change is
+              detected during runtime by the video device. It can be a
+              runtime resolution change triggered by a video decoder or the
+              format change happening on an input connector.
+              This event requires that the <structfield>id</structfield>
+              matches the input index (when used with a video device node)
+              or the pad index (when used with a subdevice node) from which
+              you want to receive events.</para>
+
+              <para>This event has a &v4l2-event-source-change; associated
+             with it. The <structfield>changes</structfield> bitfield denotes
+             what has changed for the subscribed pad. If multiple events
+             occurred before application could dequeue them, then the changes
+             will have the ORed value of all the events generated.</para>
+           </entry>
+         </row>
          <row>
            <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
            <entry>0x08000000</entry>
index 06231b85e1a90edec58c8f76326abdc0802167cf..cef3154acb931b5892bd47525bfc67cc39059b75 100644 (file)
@@ -756,7 +756,6 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
        pix->sizeimage = pix->width * pix->height;
        /* Just a guess */
        pix->colorspace = V4L2_COLORSPACE_SRGB;
-       pix->priv = 0;
        return 0;
 }
 
@@ -782,7 +781,6 @@ static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format
        pix->sizeimage = pix->width * pix->height;
        /* Just a guess */
        pix->colorspace = V4L2_COLORSPACE_SRGB;
-       pix->priv = 0;
        return 0;
 }
 
index aee7b6dacbfe26e355b855c7eb2d90c82cfd3abe..bf6860e9fc676e681c3742034abc752e07669244 100644 (file)
@@ -157,7 +157,6 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
        pixfmt->height = cx->cxhdl.height;
        pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
        pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
        if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
                pixfmt->pixelformat = s->pixelformat;
                pixfmt->sizeimage = s->vb_bytes_per_frame;
index d270819fd8751417bb6fb60c2af1483e23a8a19a..c7ae087b668b9460172c1bd153fbb24378cd0e5a 100644 (file)
@@ -576,7 +576,6 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
        f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -615,7 +614,6 @@ static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -867,7 +865,6 @@ static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv,
        f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
index 9cbbce0eaedca38ac1cffcd0d5d723aa41699af4..ada1ed8bef13d8ff5a18d58d1b1aabb2f1136d85 100644 (file)
@@ -352,7 +352,6 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
        pixfmt->height = itv->cxhdl.height;
        pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
        pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
        if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
                pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
                /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
@@ -419,7 +418,6 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
        pixfmt->height = itv->main_rect.height;
        pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
        pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
        if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
                switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
                case IVTV_YUV_MODE_INTERLACED:
@@ -1416,7 +1414,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
        fb->fmt.bytesperline = fb->fmt.width;
        fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
        fb->fmt.field = V4L2_FIELD_INTERLACED;
-       fb->fmt.priv = 0;
        if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
                fb->fmt.bytesperline *= 2;
        if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
index 2381b05432e676da50ed335ceef75bca5f5e79cb..8a21335e8e7398bdf5466e40dba87624bda918b4 100644 (file)
@@ -1166,7 +1166,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
        f->fmt.pix.sizeimage = f->fmt.pix.height *
                               f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = 0;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -1232,7 +1231,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
        f->fmt.pix.sizeimage = f->fmt.pix.height *
                               f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = 0;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
index 7005695aa4bd26cfaffc4edabb33420412321ddb..22221184c7a0cf9cbc47f5472ac59e601ee6bf58 100644 (file)
@@ -642,7 +642,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
        f->fmt.pix.sizeimage = f->fmt.pix.width * 2 * f->fmt.pix.height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
index d338b19da544c92e8e1c73c66092ca96575bcb59..022b660c571b26bff8569f94b02ecfc22629e7d2 100644 (file)
@@ -165,7 +165,6 @@ static int omap_vout_try_format(struct v4l2_pix_format *pix)
 
        pix->pixelformat = omap_formats[ifmt].pixelformat;
        pix->field = V4L2_FIELD_ANY;
-       pix->priv = 0;
 
        switch (pix->pixelformat) {
        case V4L2_PIX_FMT_YUYV:
@@ -1896,7 +1895,6 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
        pix->field = V4L2_FIELD_ANY;
        pix->bytesperline = pix->width * 2;
        pix->sizeimage = pix->bytesperline * pix->height;
-       pix->priv = 0;
        pix->colorspace = V4L2_COLORSPACE_JPEG;
 
        vout->bpp = RGB565_BPP;
index 59a9deefb24253455d531c71888c08afd49c8dc8..5a961306785e0522076e31b3b4a69821ddeaea79 100644 (file)
@@ -428,7 +428,6 @@ static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
        pix->bytesperline       = vfmt->bytesperline;
        pix->sizeimage          = vfmt->bytesperline * pix->height *
                vfmt->fmt->depth / vfmt->fmt->ydepth;
-       pix->priv               = 0;
        dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__,
                f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat);
 
@@ -476,7 +475,6 @@ static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt
 
        pix->pixelformat        = fmt->fourcc;
        pix->colorspace         = sh_veu_4cc2cspace(pix->pixelformat);
-       pix->priv               = 0;
 
        pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage);
 
index c6af974c5b45c82eced9d54ee8d2337b2d276800..e58796e66ab1496236567174f503fb7ad1a3e876 100644 (file)
@@ -3147,7 +3147,6 @@ static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
        pf->colorspace =
                vino_data_formats[tempvcs.data_format].colorspace;
 
-       pf->priv = 0;
        return 0;
 }
 
@@ -3175,8 +3174,6 @@ static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
        pf->colorspace =
                vino_data_formats[vcs->data_format].colorspace;
 
-       pf->priv = 0;
-
        spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
        return 0;
 }
@@ -3219,8 +3216,6 @@ static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
        pf->colorspace =
                vino_data_formats[vcs->data_format].colorspace;
 
-       pf->priv = 0;
-
        spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
        return 0;
 }
index 85bc314382d3e7159c0ef67e561f0478b93f3acd..0efc2db5481ea2602407f6900d64d5ca6e2d76f8 100644 (file)
@@ -1014,7 +1014,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
        else
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
index f548db8043d4bb1bfc52d7739348ac72d45d78f7..324e84d6e22bbd6d72ab4483ea9cbbe340c9d1ff 100644 (file)
@@ -1563,7 +1563,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.width = dev->ts1.width;
        f->fmt.pix.height = dev->ts1.height;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.priv = 0;
        dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
                dev->ts1.width, dev->ts1.height);
        dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
@@ -1582,7 +1581,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
        dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
                dev->ts1.width, dev->ts1.height);
        dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
index cd221474e1b9df06dd62779aebeb8653e3e00df9..007567f455f1d4c377ab2a474e60353af4f39db3 100644 (file)
@@ -887,7 +887,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -932,7 +931,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
index 5995ec4de6bc633f62f4a3f98d7ce273dc2e4e8f..49c8abaeb6eabd2e901bf96bf5be7393a29374a7 100644 (file)
@@ -1107,8 +1107,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 
        mode = gspca_dev->curr_mode;
        fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
-       /* some drivers use priv internally, zero it before giving it to
-          userspace */
+       /* some drivers use priv internally, zero it before giving it back to
+          the core */
        fmt->fmt.pix.priv = 0;
        return 0;
 }
@@ -1138,8 +1138,8 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
                        mode = mode2;
        }
        fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
-       /* some drivers use priv internally, zero it before giving it to
-          userspace */
+       /* some drivers use priv internally, zero it before giving it back to
+          the core */
        fmt->fmt.pix.priv = 0;
        return mode;                    /* used when s_fmt */
 }
index eed70a4d24e6b264de1f1a48b579b6de4978ebdc..5942cb323237080fe75ca35fbcad962c7383a40b 100644 (file)
@@ -1015,7 +1015,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh,
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.sizeimage    = dev->bulk_in_size;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.priv         = 0;
        if (f->fmt.pix.width == 720) {
                /* SDTV formats */
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
index c43c8d32be40c30e99be96d6fedd5a8fdd3832d9..dfba48fa78151573711fd9dc01a95cf67b2a983f 100644 (file)
@@ -916,7 +916,6 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
                pix_format->bytesperline = 2 * pix_format->width;
        pix_format->sizeimage = pix_format->bytesperline
                                * pix_format->height;
-       pix_format->priv = 0;
        return 0;
 }
 
@@ -960,7 +959,6 @@ static int stk_try_fmt_vid_cap(struct file *filp,
                fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
        fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline
                * fmtd->fmt.pix.height;
-       fmtd->fmt.pix.priv = 0;
        return 0;
 }
 
index 8df668d06552bb4323ab0213889d12105e09422f..8cd7f02fcf9fc7080ea6444bfb56c50854c6c80e 100644 (file)
@@ -1321,7 +1321,6 @@ static void init_video_context(struct running_context *context)
                                .bytesperline   = 720 * 2,
                                .sizeimage      = 720 * 576 * 2,
                                .colorspace     = V4L2_COLORSPACE_SMPTE170M,
-                               .priv           = 0
                        };
 }
 
index a78de1d1bc9eebf24597a198670268239a2a09df..3a2a671fa9d085c342522f4a4e1928414c3b32e4 100644 (file)
@@ -918,7 +918,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
                (f->fmt.pix.width * fh->fmt->depth) >> 3;
        f->fmt.pix.sizeimage =
                f->fmt.pix.height * f->fmt.pix.bytesperline;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -959,7 +958,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.width &= ~0x01;
 
        f->fmt.pix.field = field;
-       f->fmt.pix.priv = 0;
 
        f->fmt.pix.bytesperline =
                (f->fmt.pix.width * fmt->depth) >> 3;
index 74d56df3347f59329ec6c4538023592c863bc1ac..0f63954ee1d448ef6d7bec5b59147b8244339e7d 100644 (file)
@@ -806,7 +806,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
        DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
            decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
            f->fmt.pix.field);
@@ -829,7 +828,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
@@ -866,7 +864,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
        cam->vb_vidq.field = f->fmt.pix.field;
 
        if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
index 8cbbadde05b20a04ecbc89eede8ad8ba2f48ddb8..da9fe6db9b7f32e42297547a7d2aa86776b6958d 100644 (file)
@@ -17,6 +17,7 @@ endif
 obj-$(CONFIG_VIDEO_V4L2) += videodev.o
 obj-$(CONFIG_VIDEO_V4L2_INT_DEVICE) += v4l2-int-device.o
 obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o
+obj-$(CONFIG_VIDEO_V4L2) += v4l2-dv-timings.o
 
 obj-$(CONFIG_VIDEO_TUNER) += tuner.o
 
index ec9a4fa3bc86641e9d148ff9efd2a3361cd38bd0..52ba9f3419a97134d200e82784ae7b9471593929 100644 (file)
@@ -546,363 +546,6 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
 }
 EXPORT_SYMBOL_GPL(v4l_bound_align_image);
 
-/**
- * v4l_match_dv_timings - check if two timings match
- * @t1 - compare this v4l2_dv_timings struct...
- * @t2 - with this struct.
- * @pclock_delta - the allowed pixelclock deviation.
- *
- * Compare t1 with t2 with a given margin of error for the pixelclock.
- */
-bool v4l_match_dv_timings(const struct v4l2_dv_timings *t1,
-                         const struct v4l2_dv_timings *t2,
-                         unsigned pclock_delta)
-{
-       if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120)
-               return false;
-       if (t1->bt.width == t2->bt.width &&
-           t1->bt.height == t2->bt.height &&
-           t1->bt.interlaced == t2->bt.interlaced &&
-           t1->bt.polarities == t2->bt.polarities &&
-           t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta &&
-           t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta &&
-           t1->bt.hfrontporch == t2->bt.hfrontporch &&
-           t1->bt.vfrontporch == t2->bt.vfrontporch &&
-           t1->bt.vsync == t2->bt.vsync &&
-           t1->bt.vbackporch == t2->bt.vbackporch &&
-           (!t1->bt.interlaced ||
-               (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch &&
-                t1->bt.il_vsync == t2->bt.il_vsync &&
-                t1->bt.il_vbackporch == t2->bt.il_vbackporch)))
-               return true;
-       return false;
-}
-EXPORT_SYMBOL_GPL(v4l_match_dv_timings);
-
-/*
- * CVT defines
- * Based on Coordinated Video Timings Standard
- * version 1.1 September 10, 2003
- */
-
-#define CVT_PXL_CLK_GRAN       250000  /* pixel clock granularity */
-
-/* Normal blanking */
-#define CVT_MIN_V_BPORCH       7       /* lines */
-#define CVT_MIN_V_PORCH_RND    3       /* lines */
-#define CVT_MIN_VSYNC_BP       550     /* min time of vsync + back porch (us) */
-
-/* Normal blanking for CVT uses GTF to calculate horizontal blanking */
-#define CVT_CELL_GRAN          8       /* character cell granularity */
-#define CVT_M                  600     /* blanking formula gradient */
-#define CVT_C                  40      /* blanking formula offset */
-#define CVT_K                  128     /* blanking formula scaling factor */
-#define CVT_J                  20      /* blanking formula scaling factor */
-#define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J)
-#define CVT_M_PRIME (CVT_K * CVT_M / 256)
-
-/* Reduced Blanking */
-#define CVT_RB_MIN_V_BPORCH    7       /* lines  */
-#define CVT_RB_V_FPORCH        3       /* lines  */
-#define CVT_RB_MIN_V_BLANK   460     /* us     */
-#define CVT_RB_H_SYNC         32       /* pixels */
-#define CVT_RB_H_BPORCH       80       /* pixels */
-#define CVT_RB_H_BLANK       160       /* pixels */
-
-/** v4l2_detect_cvt - detect if the given timings follow the CVT standard
- * @frame_height - the total height of the frame (including blanking) in lines.
- * @hfreq - the horizontal frequency in Hz.
- * @vsync - the height of the vertical sync in lines.
- * @polarities - the horizontal and vertical polarities (same as struct
- *             v4l2_bt_timings polarities).
- * @fmt - the resulting timings.
- *
- * This function will attempt to detect if the given values correspond to a
- * valid CVT format. If so, then it will return true, and fmt will be filled
- * in with the found CVT timings.
- */
-bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync,
-               u32 polarities, struct v4l2_dv_timings *fmt)
-{
-       int  v_fp, v_bp, h_fp, h_bp, hsync;
-       int  frame_width, image_height, image_width;
-       bool reduced_blanking;
-       unsigned pix_clk;
-
-       if (vsync < 4 || vsync > 7)
-               return false;
-
-       if (polarities == V4L2_DV_VSYNC_POS_POL)
-               reduced_blanking = false;
-       else if (polarities == V4L2_DV_HSYNC_POS_POL)
-               reduced_blanking = true;
-       else
-               return false;
-
-       /* Vertical */
-       if (reduced_blanking) {
-               v_fp = CVT_RB_V_FPORCH;
-               v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 999999) / 1000000;
-               v_bp -= vsync + v_fp;
-
-               if (v_bp < CVT_RB_MIN_V_BPORCH)
-                       v_bp = CVT_RB_MIN_V_BPORCH;
-       } else {
-               v_fp = CVT_MIN_V_PORCH_RND;
-               v_bp = (CVT_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync;
-
-               if (v_bp < CVT_MIN_V_BPORCH)
-                       v_bp = CVT_MIN_V_BPORCH;
-       }
-       image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
-
-       /* Aspect ratio based on vsync */
-       switch (vsync) {
-       case 4:
-               image_width = (image_height * 4) / 3;
-               break;
-       case 5:
-               image_width = (image_height * 16) / 9;
-               break;
-       case 6:
-               image_width = (image_height * 16) / 10;
-               break;
-       case 7:
-               /* special case */
-               if (image_height == 1024)
-                       image_width = (image_height * 5) / 4;
-               else if (image_height == 768)
-                       image_width = (image_height * 15) / 9;
-               else
-                       return false;
-               break;
-       default:
-               return false;
-       }
-
-       image_width = image_width & ~7;
-
-       /* Horizontal */
-       if (reduced_blanking) {
-               pix_clk = (image_width + CVT_RB_H_BLANK) * hfreq;
-               pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN;
-
-               h_bp = CVT_RB_H_BPORCH;
-               hsync = CVT_RB_H_SYNC;
-               h_fp = CVT_RB_H_BLANK - h_bp - hsync;
-
-               frame_width = image_width + CVT_RB_H_BLANK;
-       } else {
-               int h_blank;
-               unsigned ideal_duty_cycle = CVT_C_PRIME - (CVT_M_PRIME * 1000) / hfreq;
-
-               h_blank = (image_width * ideal_duty_cycle + (100 - ideal_duty_cycle) / 2) /
-                                               (100 - ideal_duty_cycle);
-               h_blank = h_blank - h_blank % (2 * CVT_CELL_GRAN);
-
-               if (h_blank * 100 / image_width < 20) {
-                       h_blank = image_width / 5;
-                       h_blank = (h_blank + 0x7) & ~0x7;
-               }
-
-               pix_clk = (image_width + h_blank) * hfreq;
-               pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN;
-
-               h_bp = h_blank / 2;
-               frame_width = image_width + h_blank;
-
-               hsync = (frame_width * 8 + 50) / 100;
-               hsync = hsync - hsync % CVT_CELL_GRAN;
-               h_fp = h_blank - hsync - h_bp;
-       }
-
-       fmt->bt.polarities = polarities;
-       fmt->bt.width = image_width;
-       fmt->bt.height = image_height;
-       fmt->bt.hfrontporch = h_fp;
-       fmt->bt.vfrontporch = v_fp;
-       fmt->bt.hsync = hsync;
-       fmt->bt.vsync = vsync;
-       fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
-       fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
-       fmt->bt.pixelclock = pix_clk;
-       fmt->bt.standards = V4L2_DV_BT_STD_CVT;
-       if (reduced_blanking)
-               fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
-       return true;
-}
-EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
-
-/*
- * GTF defines
- * Based on Generalized Timing Formula Standard
- * Version 1.1 September 2, 1999
- */
-
-#define GTF_PXL_CLK_GRAN       250000  /* pixel clock granularity */
-
-#define GTF_MIN_VSYNC_BP       550     /* min time of vsync + back porch (us) */
-#define GTF_V_FP               1       /* vertical front porch (lines) */
-#define GTF_CELL_GRAN          8       /* character cell granularity */
-
-/* Default */
-#define GTF_D_M                        600     /* blanking formula gradient */
-#define GTF_D_C                        40      /* blanking formula offset */
-#define GTF_D_K                        128     /* blanking formula scaling factor */
-#define GTF_D_J                        20      /* blanking formula scaling factor */
-#define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J)
-#define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256)
-
-/* Secondary */
-#define GTF_S_M                        3600    /* blanking formula gradient */
-#define GTF_S_C                        40      /* blanking formula offset */
-#define GTF_S_K                        128     /* blanking formula scaling factor */
-#define GTF_S_J                        35      /* blanking formula scaling factor */
-#define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J)
-#define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256)
-
-/** v4l2_detect_gtf - detect if the given timings follow the GTF standard
- * @frame_height - the total height of the frame (including blanking) in lines.
- * @hfreq - the horizontal frequency in Hz.
- * @vsync - the height of the vertical sync in lines.
- * @polarities - the horizontal and vertical polarities (same as struct
- *             v4l2_bt_timings polarities).
- * @aspect - preferred aspect ratio. GTF has no method of determining the
- *             aspect ratio in order to derive the image width from the
- *             image height, so it has to be passed explicitly. Usually
- *             the native screen aspect ratio is used for this. If it
- *             is not filled in correctly, then 16:9 will be assumed.
- * @fmt - the resulting timings.
- *
- * This function will attempt to detect if the given values correspond to a
- * valid GTF format. If so, then it will return true, and fmt will be filled
- * in with the found GTF timings.
- */
-bool v4l2_detect_gtf(unsigned frame_height,
-               unsigned hfreq,
-               unsigned vsync,
-               u32 polarities,
-               struct v4l2_fract aspect,
-               struct v4l2_dv_timings *fmt)
-{
-       int pix_clk;
-       int  v_fp, v_bp, h_fp, hsync;
-       int frame_width, image_height, image_width;
-       bool default_gtf;
-       int h_blank;
-
-       if (vsync != 3)
-               return false;
-
-       if (polarities == V4L2_DV_VSYNC_POS_POL)
-               default_gtf = true;
-       else if (polarities == V4L2_DV_HSYNC_POS_POL)
-               default_gtf = false;
-       else
-               return false;
-
-       /* Vertical */
-       v_fp = GTF_V_FP;
-       v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync;
-       image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
-
-       if (aspect.numerator == 0 || aspect.denominator == 0) {
-               aspect.numerator = 16;
-               aspect.denominator = 9;
-       }
-       image_width = ((image_height * aspect.numerator) / aspect.denominator);
-
-       /* Horizontal */
-       if (default_gtf)
-               h_blank = ((image_width * GTF_D_C_PRIME * hfreq) -
-                                       (image_width * GTF_D_M_PRIME * 1000) +
-                       (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) /
-                       (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000);
-       else
-               h_blank = ((image_width * GTF_S_C_PRIME * hfreq) -
-                                       (image_width * GTF_S_M_PRIME * 1000) +
-                       (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) /
-                       (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000);
-
-       h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN);
-       frame_width = image_width + h_blank;
-
-       pix_clk = (image_width + h_blank) * hfreq;
-       pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN;
-
-       hsync = (frame_width * 8 + 50) / 100;
-       hsync = hsync - hsync % GTF_CELL_GRAN;
-
-       h_fp = h_blank / 2 - hsync;
-
-       fmt->bt.polarities = polarities;
-       fmt->bt.width = image_width;
-       fmt->bt.height = image_height;
-       fmt->bt.hfrontporch = h_fp;
-       fmt->bt.vfrontporch = v_fp;
-       fmt->bt.hsync = hsync;
-       fmt->bt.vsync = vsync;
-       fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
-       fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
-       fmt->bt.pixelclock = pix_clk;
-       fmt->bt.standards = V4L2_DV_BT_STD_GTF;
-       if (!default_gtf)
-               fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
-       return true;
-}
-EXPORT_SYMBOL_GPL(v4l2_detect_gtf);
-
-/** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes
- *     0x15 and 0x16 from the EDID.
- * @hor_landscape - byte 0x15 from the EDID.
- * @vert_portrait - byte 0x16 from the EDID.
- *
- * Determines the aspect ratio from the EDID.
- * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2:
- * "Horizontal and Vertical Screen Size or Aspect Ratio"
- */
-struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait)
-{
-       struct v4l2_fract aspect = { 16, 9 };
-       u32 tmp;
-       u8 ratio;
-
-       /* Nothing filled in, fallback to 16:9 */
-       if (!hor_landscape && !vert_portrait)
-               return aspect;
-       /* Both filled in, so they are interpreted as the screen size in cm */
-       if (hor_landscape && vert_portrait) {
-               aspect.numerator = hor_landscape;
-               aspect.denominator = vert_portrait;
-               return aspect;
-       }
-       /* Only one is filled in, so interpret them as a ratio:
-          (val + 99) / 100 */
-       ratio = hor_landscape | vert_portrait;
-       /* Change some rounded values into the exact aspect ratio */
-       if (ratio == 79) {
-               aspect.numerator = 16;
-               aspect.denominator = 9;
-       } else if (ratio == 34) {
-               aspect.numerator = 4;
-               aspect.numerator = 3;
-       } else if (ratio == 68) {
-               aspect.numerator = 15;
-               aspect.numerator = 9;
-       } else {
-               aspect.numerator = hor_landscape + 99;
-               aspect.denominator = 100;
-       }
-       if (hor_landscape)
-               return aspect;
-       /* The aspect ratio is for portrait, so swap numerator and denominator */
-       tmp = aspect.denominator;
-       aspect.denominator = aspect.numerator;
-       aspect.numerator = tmp;
-       return aspect;
-}
-EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio);
-
 const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
                const struct v4l2_discrete_probe *probe,
                s32 width, s32 height)
index effdd4af50ca65897cbfb64edffad0a5c6cf967e..449598d01629152a9cedcfebf13be965d794bfe6 100644 (file)
@@ -200,7 +200,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
                return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
        default:
-               printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+               printk(KERN_DEBUG "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
                                                                kp->type);
                return -EINVAL;
        }
@@ -241,7 +241,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
                return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
        default:
-               printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
+               printk(KERN_DEBUG "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
                                                                kp->type);
                return -EINVAL;
        }
@@ -541,7 +541,16 @@ struct v4l2_framebuffer32 {
        __u32                   capability;
        __u32                   flags;
        compat_caddr_t          base;
-       struct v4l2_pix_format  fmt;
+       struct {
+               __u32           width;
+               __u32           height;
+               __u32           pixelformat;
+               __u32           field;
+               __u32           bytesperline;
+               __u32           sizeimage;
+               __u32           colorspace;
+               __u32           priv;
+       } fmt;
 };
 
 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
@@ -551,10 +560,10 @@ static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
        if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
                get_user(tmp, &up->base) ||
                get_user(kp->capability, &up->capability) ||
-               get_user(kp->flags, &up->flags))
+               get_user(kp->flags, &up->flags) ||
+               copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
                        return -EFAULT;
        kp->base = compat_ptr(tmp);
-       get_v4l2_pix_format(&kp->fmt, &up->fmt);
        return 0;
 }
 
@@ -565,9 +574,9 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
        if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
                put_user(tmp, &up->base) ||
                put_user(kp->capability, &up->capability) ||
-               put_user(kp->flags, &up->flags))
+               put_user(kp->flags, &up->flags) ||
+               copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
                        return -EFAULT;
-       put_v4l2_pix_format(&kp->fmt, &up->fmt);
        return 0;
 }
 
@@ -743,7 +752,7 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
        return 0;
 }
 
-struct v4l2_subdev_edid32 {
+struct v4l2_edid32 {
        __u32 pad;
        __u32 start_block;
        __u32 blocks;
@@ -751,11 +760,11 @@ struct v4l2_subdev_edid32 {
        compat_caddr_t edid;
 };
 
-static int get_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up)
+static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
 {
        u32 tmp;
 
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_subdev_edid32)) ||
+       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) ||
                get_user(kp->pad, &up->pad) ||
                get_user(kp->start_block, &up->start_block) ||
                get_user(kp->blocks, &up->blocks) ||
@@ -766,16 +775,16 @@ static int get_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subde
        return 0;
 }
 
-static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up)
+static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
 {
        u32 tmp = (u32)((unsigned long)kp->edid);
 
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_subdev_edid32)) ||
+       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) ||
                put_user(kp->pad, &up->pad) ||
                put_user(kp->start_block, &up->start_block) ||
                put_user(kp->blocks, &up->blocks) ||
                put_user(tmp, &up->edid) ||
-               copy_to_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+               copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
                        return -EFAULT;
        return 0;
 }
@@ -790,8 +799,8 @@ static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subde
 #define VIDIOC_DQBUF32         _IOWR('V', 17, struct v4l2_buffer32)
 #define VIDIOC_ENUMSTD32       _IOWR('V', 25, struct v4l2_standard32)
 #define VIDIOC_ENUMINPUT32     _IOWR('V', 26, struct v4l2_input32)
-#define VIDIOC_SUBDEV_G_EDID32 _IOWR('V', 40, struct v4l2_subdev_edid32)
-#define VIDIOC_SUBDEV_S_EDID32 _IOWR('V', 41, struct v4l2_subdev_edid32)
+#define VIDIOC_G_EDID32                _IOWR('V', 40, struct v4l2_edid32)
+#define VIDIOC_S_EDID32                _IOWR('V', 41, struct v4l2_edid32)
 #define VIDIOC_TRY_FMT32       _IOWR('V', 64, struct v4l2_format32)
 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
@@ -819,7 +828,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                struct v4l2_ext_controls v2ecs;
                struct v4l2_event v2ev;
                struct v4l2_create_buffers v2crt;
-               struct v4l2_subdev_edid v2edid;
+               struct v4l2_edid v2edid;
                unsigned long vx;
                int vi;
        } karg;
@@ -852,8 +861,8 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
        case _IOC_NR(VIDIOC_S_OUTPUT32): cmd = VIDIOC_S_OUTPUT; break;
        case _IOC_NR(VIDIOC_CREATE_BUFS32): cmd = VIDIOC_CREATE_BUFS; break;
        case _IOC_NR(VIDIOC_PREPARE_BUF32): cmd = VIDIOC_PREPARE_BUF; break;
-       case _IOC_NR(VIDIOC_SUBDEV_G_EDID32): cmd = VIDIOC_SUBDEV_G_EDID; break;
-       case _IOC_NR(VIDIOC_SUBDEV_S_EDID32): cmd = VIDIOC_SUBDEV_S_EDID; break;
+       case _IOC_NR(VIDIOC_G_EDID32): cmd = VIDIOC_G_EDID; break;
+       case _IOC_NR(VIDIOC_S_EDID32): cmd = VIDIOC_S_EDID; break;
        }
 
        switch (_IOC_NR(cmd)) {
@@ -871,9 +880,9 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                compatible_arg = 0;
                break;
 
-       case _IOC_NR(VIDIOC_SUBDEV_G_EDID):
-       case _IOC_NR(VIDIOC_SUBDEV_S_EDID):
-               err = get_v4l2_subdev_edid32(&karg.v2edid, up);
+       case _IOC_NR(VIDIOC_G_EDID):
+       case _IOC_NR(VIDIOC_S_EDID):
+               err = get_v4l2_edid32(&karg.v2edid, up);
                compatible_arg = 0;
                break;
 
@@ -969,9 +978,9 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                err = put_v4l2_event32(&karg.v2ev, up);
                break;
 
-       case _IOC_NR(VIDIOC_SUBDEV_G_EDID):
-       case _IOC_NR(VIDIOC_SUBDEV_S_EDID):
-               err = put_v4l2_subdev_edid32(&karg.v2edid, up);
+       case _IOC_NR(VIDIOC_G_EDID):
+       case _IOC_NR(VIDIOC_S_EDID):
+               err = put_v4l2_edid32(&karg.v2edid, up);
                break;
 
        case _IOC_NR(VIDIOC_G_FMT):
@@ -1090,8 +1099,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case _IOC_NR(VIDIOC_QUERY_DV_TIMINGS):
        case _IOC_NR(VIDIOC_DV_TIMINGS_CAP):
        case _IOC_NR(VIDIOC_ENUM_FREQ_BANDS):
-       case _IOC_NR(VIDIOC_SUBDEV_G_EDID32):
-       case _IOC_NR(VIDIOC_SUBDEV_S_EDID32):
+       case _IOC_NR(VIDIOC_G_EDID32):
+       case _IOC_NR(VIDIOC_S_EDID32):
                ret = do_video_ioctl(file, cmd, arg);
                break;
 
@@ -1100,7 +1109,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
                        ret = vdev->fops->compat_ioctl32(file, cmd, arg);
 
                if (ret == -ENOIOCTLCMD)
-                       printk(KERN_WARNING "compat_ioctl32: "
+                       printk(KERN_DEBUG "compat_ioctl32: "
                                "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
                                _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd),
                                cmd);
index 5923c5dfacd5ae8c8cb65af2499d42d149773803..ae9b6d86c6f4ccdeb682bc50471f1e6a8fb63738 100644 (file)
@@ -687,6 +687,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
                        SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio);
                        SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio);
                        SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings);
+                       SET_VALID_IOCTL(ops, VIDIOC_S_EDID, vidioc_s_edid);
                }
                if (is_tx) {
                        SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output);
@@ -712,6 +713,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
                SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings);
                SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings);
                SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap);
+               SET_VALID_IOCTL(ops, VIDIOC_G_EDID, vidioc_g_edid);
        }
        if (is_tx) {
                /* transmitter only ioctls */
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c
new file mode 100644 (file)
index 0000000..6a83d61
--- /dev/null
@@ -0,0 +1,745 @@
+/*
+ * v4l2-dv-timings - dv-timings helper functions
+ *
+ * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-dv-timings.h>
+#include <media/v4l2-dv-timings.h>
+#include <linux/math64.h>
+
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions");
+MODULE_LICENSE("GPL");
+
+const struct v4l2_dv_timings v4l2_dv_timings_presets[] = {
+       V4L2_DV_BT_CEA_640X480P59_94,
+       V4L2_DV_BT_CEA_720X480I59_94,
+       V4L2_DV_BT_CEA_720X480P59_94,
+       V4L2_DV_BT_CEA_720X576I50,
+       V4L2_DV_BT_CEA_720X576P50,
+       V4L2_DV_BT_CEA_1280X720P24,
+       V4L2_DV_BT_CEA_1280X720P25,
+       V4L2_DV_BT_CEA_1280X720P30,
+       V4L2_DV_BT_CEA_1280X720P50,
+       V4L2_DV_BT_CEA_1280X720P60,
+       V4L2_DV_BT_CEA_1920X1080P24,
+       V4L2_DV_BT_CEA_1920X1080P25,
+       V4L2_DV_BT_CEA_1920X1080P30,
+       V4L2_DV_BT_CEA_1920X1080I50,
+       V4L2_DV_BT_CEA_1920X1080P50,
+       V4L2_DV_BT_CEA_1920X1080I60,
+       V4L2_DV_BT_CEA_1920X1080P60,
+       V4L2_DV_BT_DMT_640X350P85,
+       V4L2_DV_BT_DMT_640X400P85,
+       V4L2_DV_BT_DMT_720X400P85,
+       V4L2_DV_BT_DMT_640X480P72,
+       V4L2_DV_BT_DMT_640X480P75,
+       V4L2_DV_BT_DMT_640X480P85,
+       V4L2_DV_BT_DMT_800X600P56,
+       V4L2_DV_BT_DMT_800X600P60,
+       V4L2_DV_BT_DMT_800X600P72,
+       V4L2_DV_BT_DMT_800X600P75,
+       V4L2_DV_BT_DMT_800X600P85,
+       V4L2_DV_BT_DMT_800X600P120_RB,
+       V4L2_DV_BT_DMT_848X480P60,
+       V4L2_DV_BT_DMT_1024X768I43,
+       V4L2_DV_BT_DMT_1024X768P60,
+       V4L2_DV_BT_DMT_1024X768P70,
+       V4L2_DV_BT_DMT_1024X768P75,
+       V4L2_DV_BT_DMT_1024X768P85,
+       V4L2_DV_BT_DMT_1024X768P120_RB,
+       V4L2_DV_BT_DMT_1152X864P75,
+       V4L2_DV_BT_DMT_1280X768P60_RB,
+       V4L2_DV_BT_DMT_1280X768P60,
+       V4L2_DV_BT_DMT_1280X768P75,
+       V4L2_DV_BT_DMT_1280X768P85,
+       V4L2_DV_BT_DMT_1280X768P120_RB,
+       V4L2_DV_BT_DMT_1280X800P60_RB,
+       V4L2_DV_BT_DMT_1280X800P60,
+       V4L2_DV_BT_DMT_1280X800P75,
+       V4L2_DV_BT_DMT_1280X800P85,
+       V4L2_DV_BT_DMT_1280X800P120_RB,
+       V4L2_DV_BT_DMT_1280X960P60,
+       V4L2_DV_BT_DMT_1280X960P85,
+       V4L2_DV_BT_DMT_1280X960P120_RB,
+       V4L2_DV_BT_DMT_1280X1024P60,
+       V4L2_DV_BT_DMT_1280X1024P75,
+       V4L2_DV_BT_DMT_1280X1024P85,
+       V4L2_DV_BT_DMT_1280X1024P120_RB,
+       V4L2_DV_BT_DMT_1360X768P60,
+       V4L2_DV_BT_DMT_1360X768P120_RB,
+       V4L2_DV_BT_DMT_1366X768P60,
+       V4L2_DV_BT_DMT_1366X768P60_RB,
+       V4L2_DV_BT_DMT_1400X1050P60_RB,
+       V4L2_DV_BT_DMT_1400X1050P60,
+       V4L2_DV_BT_DMT_1400X1050P75,
+       V4L2_DV_BT_DMT_1400X1050P85,
+       V4L2_DV_BT_DMT_1400X1050P120_RB,
+       V4L2_DV_BT_DMT_1440X900P60_RB,
+       V4L2_DV_BT_DMT_1440X900P60,
+       V4L2_DV_BT_DMT_1440X900P75,
+       V4L2_DV_BT_DMT_1440X900P85,
+       V4L2_DV_BT_DMT_1440X900P120_RB,
+       V4L2_DV_BT_DMT_1600X900P60_RB,
+       V4L2_DV_BT_DMT_1600X1200P60,
+       V4L2_DV_BT_DMT_1600X1200P65,
+       V4L2_DV_BT_DMT_1600X1200P70,
+       V4L2_DV_BT_DMT_1600X1200P75,
+       V4L2_DV_BT_DMT_1600X1200P85,
+       V4L2_DV_BT_DMT_1600X1200P120_RB,
+       V4L2_DV_BT_DMT_1680X1050P60_RB,
+       V4L2_DV_BT_DMT_1680X1050P60,
+       V4L2_DV_BT_DMT_1680X1050P75,
+       V4L2_DV_BT_DMT_1680X1050P85,
+       V4L2_DV_BT_DMT_1680X1050P120_RB,
+       V4L2_DV_BT_DMT_1792X1344P60,
+       V4L2_DV_BT_DMT_1792X1344P75,
+       V4L2_DV_BT_DMT_1792X1344P120_RB,
+       V4L2_DV_BT_DMT_1856X1392P60,
+       V4L2_DV_BT_DMT_1856X1392P75,
+       V4L2_DV_BT_DMT_1856X1392P120_RB,
+       V4L2_DV_BT_DMT_1920X1200P60_RB,
+       V4L2_DV_BT_DMT_1920X1200P60,
+       V4L2_DV_BT_DMT_1920X1200P75,
+       V4L2_DV_BT_DMT_1920X1200P85,
+       V4L2_DV_BT_DMT_1920X1200P120_RB,
+       V4L2_DV_BT_DMT_1920X1440P60,
+       V4L2_DV_BT_DMT_1920X1440P75,
+       V4L2_DV_BT_DMT_1920X1440P120_RB,
+       V4L2_DV_BT_DMT_2048X1152P60_RB,
+       V4L2_DV_BT_DMT_2560X1600P60_RB,
+       V4L2_DV_BT_DMT_2560X1600P60,
+       V4L2_DV_BT_DMT_2560X1600P75,
+       V4L2_DV_BT_DMT_2560X1600P85,
+       V4L2_DV_BT_DMT_2560X1600P120_RB,
+       V4L2_DV_BT_CEA_3840X2160P24,
+       V4L2_DV_BT_CEA_3840X2160P25,
+       V4L2_DV_BT_CEA_3840X2160P30,
+       V4L2_DV_BT_CEA_3840X2160P50,
+       V4L2_DV_BT_CEA_3840X2160P60,
+       V4L2_DV_BT_CEA_4096X2160P24,
+       V4L2_DV_BT_CEA_4096X2160P25,
+       V4L2_DV_BT_CEA_4096X2160P30,
+       V4L2_DV_BT_CEA_4096X2160P50,
+       V4L2_DV_BT_DMT_4096X2160P59_94_RB,
+       V4L2_DV_BT_CEA_4096X2160P60,
+       { }
+};
+EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets);
+
+bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t,
+                          const struct v4l2_dv_timings_cap *dvcap,
+                          v4l2_check_dv_timings_fnc fnc,
+                          void *fnc_handle)
+{
+       const struct v4l2_bt_timings *bt = &t->bt;
+       const struct v4l2_bt_timings_cap *cap = &dvcap->bt;
+       u32 caps = cap->capabilities;
+
+       if (t->type != V4L2_DV_BT_656_1120)
+               return false;
+       if (t->type != dvcap->type ||
+           bt->height < cap->min_height ||
+           bt->height > cap->max_height ||
+           bt->width < cap->min_width ||
+           bt->width > cap->max_width ||
+           bt->pixelclock < cap->min_pixelclock ||
+           bt->pixelclock > cap->max_pixelclock ||
+           (cap->standards && bt->standards &&
+            !(bt->standards & cap->standards)) ||
+           (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) ||
+           (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE)))
+               return false;
+       return fnc == NULL || fnc(t, fnc_handle);
+}
+EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings);
+
+int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t,
+                            const struct v4l2_dv_timings_cap *cap,
+                            v4l2_check_dv_timings_fnc fnc,
+                            void *fnc_handle)
+{
+       u32 i, idx;
+
+       memset(t->reserved, 0, sizeof(t->reserved));
+       for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
+               if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
+                                         fnc, fnc_handle) &&
+                   idx++ == t->index) {
+                       t->timings = v4l2_dv_timings_presets[i];
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(v4l2_enum_dv_timings_cap);
+
+bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t,
+                             const struct v4l2_dv_timings_cap *cap,
+                             unsigned pclock_delta,
+                             v4l2_check_dv_timings_fnc fnc,
+                             void *fnc_handle)
+{
+       int i;
+
+       if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle))
+               return false;
+
+       for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) {
+               if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
+                                         fnc, fnc_handle) &&
+                   v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i,
+                                         pclock_delta)) {
+                       *t = v4l2_dv_timings_presets[i];
+                       return true;
+               }
+       }
+       return false;
+}
+EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cap);
+
+/**
+ * v4l2_match_dv_timings - check if two timings match
+ * @t1 - compare this v4l2_dv_timings struct...
+ * @t2 - with this struct.
+ * @pclock_delta - the allowed pixelclock deviation.
+ *
+ * Compare t1 with t2 with a given margin of error for the pixelclock.
+ */
+bool v4l2_match_dv_timings(const struct v4l2_dv_timings *t1,
+                          const struct v4l2_dv_timings *t2,
+                          unsigned pclock_delta)
+{
+       if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120)
+               return false;
+       if (t1->bt.width == t2->bt.width &&
+           t1->bt.height == t2->bt.height &&
+           t1->bt.interlaced == t2->bt.interlaced &&
+           t1->bt.polarities == t2->bt.polarities &&
+           t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta &&
+           t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta &&
+           t1->bt.hfrontporch == t2->bt.hfrontporch &&
+           t1->bt.vfrontporch == t2->bt.vfrontporch &&
+           t1->bt.vsync == t2->bt.vsync &&
+           t1->bt.vbackporch == t2->bt.vbackporch &&
+           (!t1->bt.interlaced ||
+               (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch &&
+                t1->bt.il_vsync == t2->bt.il_vsync &&
+                t1->bt.il_vbackporch == t2->bt.il_vbackporch)))
+               return true;
+       return false;
+}
+EXPORT_SYMBOL_GPL(v4l2_match_dv_timings);
+
+void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix,
+                          const struct v4l2_dv_timings *t, bool detailed)
+{
+       const struct v4l2_bt_timings *bt = &t->bt;
+       u32 htot, vtot;
+       u32 fps;
+
+       if (t->type != V4L2_DV_BT_656_1120)
+               return;
+
+       htot = V4L2_DV_BT_FRAME_WIDTH(bt);
+       vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
+       if (bt->interlaced)
+               vtot /= 2;
+
+       fps = (htot * vtot) > 0 ? div_u64((100 * (u64)bt->pixelclock),
+                                 (htot * vtot)) : 0;
+
+       if (prefix == NULL)
+               prefix = "";
+
+       pr_info("%s: %s%ux%u%s%u.%u (%ux%u)\n", dev_prefix, prefix,
+               bt->width, bt->height, bt->interlaced ? "i" : "p",
+               fps / 100, fps % 100, htot, vtot);
+
+       if (!detailed)
+               return;
+
+       pr_info("%s: horizontal: fp = %u, %ssync = %u, bp = %u\n",
+                       dev_prefix, bt->hfrontporch,
+                       (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-",
+                       bt->hsync, bt->hbackporch);
+       pr_info("%s: vertical: fp = %u, %ssync = %u, bp = %u\n",
+                       dev_prefix, bt->vfrontporch,
+                       (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
+                       bt->vsync, bt->vbackporch);
+       if (bt->interlaced)
+               pr_info("%s: vertical bottom field: fp = %u, %ssync = %u, bp = %u\n",
+                       dev_prefix, bt->il_vfrontporch,
+                       (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
+                       bt->il_vsync, bt->il_vbackporch);
+       pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock);
+       pr_info("%s: flags (0x%x):%s%s%s%s%s%s\n", dev_prefix, bt->flags,
+                       (bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ?
+                       " REDUCED_BLANKING" : "",
+                       ((bt->flags & V4L2_DV_FL_REDUCED_BLANKING) &&
+                        bt->vsync == 8) ? " (V2)" : "",
+                       (bt->flags & V4L2_DV_FL_CAN_REDUCE_FPS) ?
+                       " CAN_REDUCE_FPS" : "",
+                       (bt->flags & V4L2_DV_FL_REDUCED_FPS) ?
+                       " REDUCED_FPS" : "",
+                       (bt->flags & V4L2_DV_FL_HALF_LINE) ?
+                       " HALF_LINE" : "",
+                       (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) ?
+                       " CE_VIDEO" : "");
+       pr_info("%s: standards (0x%x):%s%s%s%s\n", dev_prefix, bt->standards,
+                       (bt->standards & V4L2_DV_BT_STD_CEA861) ?  " CEA" : "",
+                       (bt->standards & V4L2_DV_BT_STD_DMT) ?  " DMT" : "",
+                       (bt->standards & V4L2_DV_BT_STD_CVT) ?  " CVT" : "",
+                       (bt->standards & V4L2_DV_BT_STD_GTF) ?  " GTF" : "");
+}
+EXPORT_SYMBOL_GPL(v4l2_print_dv_timings);
+
+/*
+ * CVT defines
+ * Based on Coordinated Video Timings Standard
+ * version 1.1 September 10, 2003
+ */
+
+#define CVT_PXL_CLK_GRAN       250000  /* pixel clock granularity */
+#define CVT_PXL_CLK_GRAN_RB_V2 1000    /* granularity for reduced blanking v2*/
+
+/* Normal blanking */
+#define CVT_MIN_V_BPORCH       7       /* lines */
+#define CVT_MIN_V_PORCH_RND    3       /* lines */
+#define CVT_MIN_VSYNC_BP       550     /* min time of vsync + back porch (us) */
+#define CVT_HSYNC_PERCENT       8       /* nominal hsync as percentage of line */
+
+/* Normal blanking for CVT uses GTF to calculate horizontal blanking */
+#define CVT_CELL_GRAN          8       /* character cell granularity */
+#define CVT_M                  600     /* blanking formula gradient */
+#define CVT_C                  40      /* blanking formula offset */
+#define CVT_K                  128     /* blanking formula scaling factor */
+#define CVT_J                  20      /* blanking formula scaling factor */
+#define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J)
+#define CVT_M_PRIME (CVT_K * CVT_M / 256)
+
+/* Reduced Blanking */
+#define CVT_RB_MIN_V_BPORCH    7       /* lines  */
+#define CVT_RB_V_FPORCH        3       /* lines  */
+#define CVT_RB_MIN_V_BLANK   460       /* us     */
+#define CVT_RB_H_SYNC         32       /* pixels */
+#define CVT_RB_H_BLANK       160       /* pixels */
+/* Reduce blanking Version 2 */
+#define CVT_RB_V2_H_BLANK     80       /* pixels */
+#define CVT_RB_MIN_V_FPORCH    3       /* lines  */
+#define CVT_RB_V2_MIN_V_FPORCH 1       /* lines  */
+#define CVT_RB_V_BPORCH        6       /* lines  */
+
+/** v4l2_detect_cvt - detect if the given timings follow the CVT standard
+ * @frame_height - the total height of the frame (including blanking) in lines.
+ * @hfreq - the horizontal frequency in Hz.
+ * @vsync - the height of the vertical sync in lines.
+ * @active_width - active width of image (does not include blanking). This
+ * information is needed only in case of version 2 of reduced blanking.
+ * In other cases, this parameter does not have any effect on timings.
+ * @polarities - the horizontal and vertical polarities (same as struct
+ *             v4l2_bt_timings polarities).
+ * @interlaced - if this flag is true, it indicates interlaced format
+ * @fmt - the resulting timings.
+ *
+ * This function will attempt to detect if the given values correspond to a
+ * valid CVT format. If so, then it will return true, and fmt will be filled
+ * in with the found CVT timings.
+ */
+bool v4l2_detect_cvt(unsigned frame_height,
+                    unsigned hfreq,
+                    unsigned vsync,
+                    unsigned active_width,
+                    u32 polarities,
+                    bool interlaced,
+                    struct v4l2_dv_timings *fmt)
+{
+       int  v_fp, v_bp, h_fp, h_bp, hsync;
+       int  frame_width, image_height, image_width;
+       bool reduced_blanking;
+       bool rb_v2 = false;
+       unsigned pix_clk;
+
+       if (vsync < 4 || vsync > 8)
+               return false;
+
+       if (polarities == V4L2_DV_VSYNC_POS_POL)
+               reduced_blanking = false;
+       else if (polarities == V4L2_DV_HSYNC_POS_POL)
+               reduced_blanking = true;
+       else
+               return false;
+
+       if (reduced_blanking && vsync == 8)
+               rb_v2 = true;
+
+       if (rb_v2 && active_width == 0)
+               return false;
+
+       if (!rb_v2 && vsync > 7)
+               return false;
+
+       if (hfreq == 0)
+               return false;
+
+       /* Vertical */
+       if (reduced_blanking) {
+               if (rb_v2) {
+                       v_bp = CVT_RB_V_BPORCH;
+                       v_fp = (CVT_RB_MIN_V_BLANK * hfreq) / 1000000 + 1;
+                       v_fp -= vsync + v_bp;
+
+                       if (v_fp < CVT_RB_V2_MIN_V_FPORCH)
+                               v_fp = CVT_RB_V2_MIN_V_FPORCH;
+               } else {
+                       v_fp = CVT_RB_V_FPORCH;
+                       v_bp = (CVT_RB_MIN_V_BLANK * hfreq) / 1000000 + 1;
+                       v_bp -= vsync + v_fp;
+
+                       if (v_bp < CVT_RB_MIN_V_BPORCH)
+                               v_bp = CVT_RB_MIN_V_BPORCH;
+               }
+       } else {
+               v_fp = CVT_MIN_V_PORCH_RND;
+               v_bp = (CVT_MIN_VSYNC_BP * hfreq) / 1000000 + 1 - vsync;
+
+               if (v_bp < CVT_MIN_V_BPORCH)
+                       v_bp = CVT_MIN_V_BPORCH;
+       }
+
+       if (interlaced)
+               image_height = (frame_height - 2 * v_fp - 2 * vsync - 2 * v_bp) & ~0x1;
+       else
+               image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
+
+       if (image_height < 0)
+               return false;
+
+       /* Aspect ratio based on vsync */
+       switch (vsync) {
+       case 4:
+               image_width = (image_height * 4) / 3;
+               break;
+       case 5:
+               image_width = (image_height * 16) / 9;
+               break;
+       case 6:
+               image_width = (image_height * 16) / 10;
+               break;
+       case 7:
+               /* special case */
+               if (image_height == 1024)
+                       image_width = (image_height * 5) / 4;
+               else if (image_height == 768)
+                       image_width = (image_height * 15) / 9;
+               else
+                       return false;
+               break;
+       case 8:
+               image_width = active_width;
+               break;
+       default:
+               return false;
+       }
+
+       if (!rb_v2)
+               image_width = image_width & ~7;
+
+       /* Horizontal */
+       if (reduced_blanking) {
+               int h_blank;
+               int clk_gran;
+
+               h_blank = rb_v2 ? CVT_RB_V2_H_BLANK : CVT_RB_H_BLANK;
+               clk_gran = rb_v2 ? CVT_PXL_CLK_GRAN_RB_V2 : CVT_PXL_CLK_GRAN;
+
+               pix_clk = (image_width + h_blank) * hfreq;
+               pix_clk = (pix_clk / clk_gran) * clk_gran;
+
+               h_bp  = h_blank / 2;
+               hsync = CVT_RB_H_SYNC;
+               h_fp  = h_blank - h_bp - hsync;
+
+               frame_width = image_width + h_blank;
+       } else {
+               unsigned ideal_duty_cycle_per_myriad =
+                       100 * CVT_C_PRIME - (CVT_M_PRIME * 100000) / hfreq;
+               int h_blank;
+
+               if (ideal_duty_cycle_per_myriad < 2000)
+                       ideal_duty_cycle_per_myriad = 2000;
+
+               h_blank = image_width * ideal_duty_cycle_per_myriad /
+                                       (10000 - ideal_duty_cycle_per_myriad);
+               h_blank = (h_blank / (2 * CVT_CELL_GRAN)) * 2 * CVT_CELL_GRAN;
+
+               pix_clk = (image_width + h_blank) * hfreq;
+               pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN;
+
+               h_bp = h_blank / 2;
+               frame_width = image_width + h_blank;
+
+               hsync = frame_width * CVT_HSYNC_PERCENT / 100;
+               hsync = (hsync / CVT_CELL_GRAN) * CVT_CELL_GRAN;
+               h_fp = h_blank - hsync - h_bp;
+       }
+
+       fmt->type = V4L2_DV_BT_656_1120;
+       fmt->bt.polarities = polarities;
+       fmt->bt.width = image_width;
+       fmt->bt.height = image_height;
+       fmt->bt.hfrontporch = h_fp;
+       fmt->bt.vfrontporch = v_fp;
+       fmt->bt.hsync = hsync;
+       fmt->bt.vsync = vsync;
+       fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
+
+       if (!interlaced) {
+               fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
+               fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
+       } else {
+               fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
+                                     2 * vsync) / 2;
+               fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
+                                       2 * vsync - fmt->bt.vbackporch;
+               fmt->bt.il_vfrontporch = v_fp;
+               fmt->bt.il_vsync = vsync;
+               fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
+               fmt->bt.interlaced = V4L2_DV_INTERLACED;
+       }
+
+       fmt->bt.pixelclock = pix_clk;
+       fmt->bt.standards = V4L2_DV_BT_STD_CVT;
+
+       if (reduced_blanking)
+               fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
+
+/*
+ * GTF defines
+ * Based on Generalized Timing Formula Standard
+ * Version 1.1 September 2, 1999
+ */
+
+#define GTF_PXL_CLK_GRAN       250000  /* pixel clock granularity */
+
+#define GTF_MIN_VSYNC_BP       550     /* min time of vsync + back porch (us) */
+#define GTF_V_FP               1       /* vertical front porch (lines) */
+#define GTF_CELL_GRAN          8       /* character cell granularity */
+
+/* Default */
+#define GTF_D_M                        600     /* blanking formula gradient */
+#define GTF_D_C                        40      /* blanking formula offset */
+#define GTF_D_K                        128     /* blanking formula scaling factor */
+#define GTF_D_J                        20      /* blanking formula scaling factor */
+#define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J)
+#define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256)
+
+/* Secondary */
+#define GTF_S_M                        3600    /* blanking formula gradient */
+#define GTF_S_C                        40      /* blanking formula offset */
+#define GTF_S_K                        128     /* blanking formula scaling factor */
+#define GTF_S_J                        35      /* blanking formula scaling factor */
+#define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J)
+#define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256)
+
+/** v4l2_detect_gtf - detect if the given timings follow the GTF standard
+ * @frame_height - the total height of the frame (including blanking) in lines.
+ * @hfreq - the horizontal frequency in Hz.
+ * @vsync - the height of the vertical sync in lines.
+ * @polarities - the horizontal and vertical polarities (same as struct
+ *             v4l2_bt_timings polarities).
+ * @interlaced - if this flag is true, it indicates interlaced format
+ * @aspect - preferred aspect ratio. GTF has no method of determining the
+ *             aspect ratio in order to derive the image width from the
+ *             image height, so it has to be passed explicitly. Usually
+ *             the native screen aspect ratio is used for this. If it
+ *             is not filled in correctly, then 16:9 will be assumed.
+ * @fmt - the resulting timings.
+ *
+ * This function will attempt to detect if the given values correspond to a
+ * valid GTF format. If so, then it will return true, and fmt will be filled
+ * in with the found GTF timings.
+ */
+bool v4l2_detect_gtf(unsigned frame_height,
+               unsigned hfreq,
+               unsigned vsync,
+               u32 polarities,
+               bool interlaced,
+               struct v4l2_fract aspect,
+               struct v4l2_dv_timings *fmt)
+{
+       int pix_clk;
+       int  v_fp, v_bp, h_fp, hsync;
+       int frame_width, image_height, image_width;
+       bool default_gtf;
+       int h_blank;
+
+       if (vsync != 3)
+               return false;
+
+       if (polarities == V4L2_DV_VSYNC_POS_POL)
+               default_gtf = true;
+       else if (polarities == V4L2_DV_HSYNC_POS_POL)
+               default_gtf = false;
+       else
+               return false;
+
+       if (hfreq == 0)
+               return false;
+
+       /* Vertical */
+       v_fp = GTF_V_FP;
+       v_bp = (GTF_MIN_VSYNC_BP * hfreq + 500000) / 1000000 - vsync;
+       if (interlaced)
+               image_height = (frame_height - 2 * v_fp - 2 * vsync - 2 * v_bp) & ~0x1;
+       else
+               image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
+
+       if (image_height < 0)
+               return false;
+
+       if (aspect.numerator == 0 || aspect.denominator == 0) {
+               aspect.numerator = 16;
+               aspect.denominator = 9;
+       }
+       image_width = ((image_height * aspect.numerator) / aspect.denominator);
+       image_width = (image_width + GTF_CELL_GRAN/2) & ~(GTF_CELL_GRAN - 1);
+
+       /* Horizontal */
+       if (default_gtf) {
+               u64 num;
+               u32 den;
+
+               num = ((image_width * GTF_D_C_PRIME * (u64)hfreq) -
+                     ((u64)image_width * GTF_D_M_PRIME * 1000));
+               den = (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) *
+                     (2 * GTF_CELL_GRAN);
+               h_blank = div_u64((num + (den >> 1)), den);
+               h_blank *= (2 * GTF_CELL_GRAN);
+       } else {
+               u64 num;
+               u32 den;
+
+               num = ((image_width * GTF_S_C_PRIME * (u64)hfreq) -
+                     ((u64)image_width * GTF_S_M_PRIME * 1000));
+               den = (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) *
+                     (2 * GTF_CELL_GRAN);
+               h_blank = div_u64((num + (den >> 1)), den);
+               h_blank *= (2 * GTF_CELL_GRAN);
+       }
+
+       frame_width = image_width + h_blank;
+
+       pix_clk = (image_width + h_blank) * hfreq;
+       pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN;
+
+       hsync = (frame_width * 8 + 50) / 100;
+       hsync = ((hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN) * GTF_CELL_GRAN;
+
+       h_fp = h_blank / 2 - hsync;
+
+       fmt->type = V4L2_DV_BT_656_1120;
+       fmt->bt.polarities = polarities;
+       fmt->bt.width = image_width;
+       fmt->bt.height = image_height;
+       fmt->bt.hfrontporch = h_fp;
+       fmt->bt.vfrontporch = v_fp;
+       fmt->bt.hsync = hsync;
+       fmt->bt.vsync = vsync;
+       fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
+
+       if (!interlaced) {
+               fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
+               fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
+       } else {
+               fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
+                                     2 * vsync) / 2;
+               fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
+                                       2 * vsync - fmt->bt.vbackporch;
+               fmt->bt.il_vfrontporch = v_fp;
+               fmt->bt.il_vsync = vsync;
+               fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
+               fmt->bt.interlaced = V4L2_DV_INTERLACED;
+       }
+
+       fmt->bt.pixelclock = pix_clk;
+       fmt->bt.standards = V4L2_DV_BT_STD_GTF;
+
+       if (!default_gtf)
+               fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(v4l2_detect_gtf);
+
+/** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes
+ *     0x15 and 0x16 from the EDID.
+ * @hor_landscape - byte 0x15 from the EDID.
+ * @vert_portrait - byte 0x16 from the EDID.
+ *
+ * Determines the aspect ratio from the EDID.
+ * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2:
+ * "Horizontal and Vertical Screen Size or Aspect Ratio"
+ */
+struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait)
+{
+       struct v4l2_fract aspect = { 16, 9 };
+       u8 ratio;
+
+       /* Nothing filled in, fallback to 16:9 */
+       if (!hor_landscape && !vert_portrait)
+               return aspect;
+       /* Both filled in, so they are interpreted as the screen size in cm */
+       if (hor_landscape && vert_portrait) {
+               aspect.numerator = hor_landscape;
+               aspect.denominator = vert_portrait;
+               return aspect;
+       }
+       /* Only one is filled in, so interpret them as a ratio:
+          (val + 99) / 100 */
+       ratio = hor_landscape | vert_portrait;
+       /* Change some rounded values into the exact aspect ratio */
+       if (ratio == 79) {
+               aspect.numerator = 16;
+               aspect.denominator = 9;
+       } else if (ratio == 34) {
+               aspect.numerator = 4;
+               aspect.denominator = 3;
+       } else if (ratio == 68) {
+               aspect.numerator = 15;
+               aspect.denominator = 9;
+       } else {
+               aspect.numerator = hor_landscape + 99;
+               aspect.denominator = 100;
+       }
+       if (hor_landscape)
+               return aspect;
+       /* The aspect ratio is for portrait, so swap numerator and denominator */
+       swap(aspect.denominator, aspect.numerator);
+       return aspect;
+}
+EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio);
index 86dcb5483c4219da6d86d2c3423a8c857449256b..8761aab99de95b2f6e0efc80e2a4d9780b62e9b3 100644 (file)
@@ -318,3 +318,39 @@ int v4l2_event_subdev_unsubscribe(struct v4l2_subdev *sd, struct v4l2_fh *fh,
        return v4l2_event_unsubscribe(fh, sub);
 }
 EXPORT_SYMBOL_GPL(v4l2_event_subdev_unsubscribe);
+
+static void v4l2_event_src_replace(struct v4l2_event *old,
+                               const struct v4l2_event *new)
+{
+       u32 old_changes = old->u.src_change.changes;
+
+       old->u.src_change = new->u.src_change;
+       old->u.src_change.changes |= old_changes;
+}
+
+static void v4l2_event_src_merge(const struct v4l2_event *old,
+                               struct v4l2_event *new)
+{
+       new->u.src_change.changes |= old->u.src_change.changes;
+}
+
+static const struct v4l2_subscribed_event_ops v4l2_event_src_ch_ops = {
+       .replace = v4l2_event_src_replace,
+       .merge = v4l2_event_src_merge,
+};
+
+int v4l2_src_change_event_subscribe(struct v4l2_fh *fh,
+                               const struct v4l2_event_subscription *sub)
+{
+       if (sub->type == V4L2_EVENT_SOURCE_CHANGE)
+               return v4l2_event_subscribe(fh, sub, 0, &v4l2_event_src_ch_ops);
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(v4l2_src_change_event_subscribe);
+
+int v4l2_src_change_event_subdev_subscribe(struct v4l2_subdev *sd,
+               struct v4l2_fh *fh, struct v4l2_event_subscription *sub)
+{
+       return v4l2_src_change_event_subscribe(fh, sub);
+}
+EXPORT_SYMBOL_GPL(v4l2_src_change_event_subdev_subscribe);
index b9a546c4c315a47dabe99b7620ed45f0ea77d902..3d9f9c364d24bea81cfc7f6eca28dca3327eebe3 100644 (file)
@@ -252,7 +252,9 @@ static void v4l_print_format(const void *arg, bool write_only)
                pix = &p->fmt.pix;
                pr_cont(", width=%u, height=%u, "
                        "pixelformat=%c%c%c%c, field=%s, "
-                       "bytesperline=%u, sizeimage=%u, colorspace=%d\n",
+                       "bytesperline=%u, sizeimage=%u, colorspace=%d "
+                       "flags=0x%x, ycbcr_enc=%u, quantization=%u, "
+                       "xfer_func=%u\n",
                        pix->width, pix->height,
                        (pix->pixelformat & 0xff),
                        (pix->pixelformat >>  8) & 0xff,
@@ -260,21 +262,24 @@ static void v4l_print_format(const void *arg, bool write_only)
                        (pix->pixelformat >> 24) & 0xff,
                        prt_names(pix->field, v4l2_field_names),
                        pix->bytesperline, pix->sizeimage,
-                       pix->colorspace);
+                       pix->colorspace, pix->flags, pix->ycbcr_enc,
+                       pix->quantization, pix->xfer_func);
                break;
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
                mp = &p->fmt.pix_mp;
                pr_cont(", width=%u, height=%u, "
                        "format=%c%c%c%c, field=%s, "
-                       "colorspace=%d, num_planes=%u\n",
+                       "colorspace=%d, num_planes=%u, flags=0x%x, "
+                       "ycbcr_enc=%u, quantization=%u, xfer_func=%u\n",
                        mp->width, mp->height,
                        (mp->pixelformat & 0xff),
                        (mp->pixelformat >>  8) & 0xff,
                        (mp->pixelformat >> 16) & 0xff,
                        (mp->pixelformat >> 24) & 0xff,
                        prt_names(mp->field, v4l2_field_names),
-                       mp->colorspace, mp->num_planes);
+                       mp->colorspace, mp->num_planes, mp->flags,
+                       mp->ycbcr_enc, mp->quantization, mp->xfer_func);
                for (i = 0; i < mp->num_planes; i++)
                        printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
                                        mp->plane_fmt[i].bytesperline,
@@ -846,6 +851,14 @@ static void v4l_print_freq_band(const void *arg, bool write_only)
                        p->rangehigh, p->modulation);
 }
 
+static void v4l_print_edid(const void *arg, bool write_only)
+{
+       const struct v4l2_edid *p = arg;
+
+       pr_cont("pad=%u, start_block=%u, blocks=%u\n",
+               p->pad, p->start_block, p->blocks);
+}
+
 static void v4l_print_u32(const void *arg, bool write_only)
 {
        pr_cont("value=%u\n", *(const u32 *)arg);
@@ -948,13 +961,48 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
        return -EINVAL;
 }
 
+static void v4l_sanitize_format(struct v4l2_format *fmt)
+{
+       unsigned int offset;
+
+       /*
+        * The v4l2_pix_format structure has been extended with fields that were
+        * not previously required to be set to zero by applications. The priv
+        * field, when set to a magic value, indicates the the extended fields
+        * are valid. Otherwise they will contain undefined values. To simplify
+        * the API towards drivers zero the extended fields and set the priv
+        * field to the magic value when the extended pixel format structure
+        * isn't used by applications.
+        */
+
+       if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return;
+
+       if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
+               return;
+
+       fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+       offset = offsetof(struct v4l2_pix_format, priv)
+              + sizeof(fmt->fmt.pix.priv);
+       memset(((void *)&fmt->fmt.pix) + offset, 0,
+              sizeof(fmt->fmt.pix) - offset);
+}
+
 static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_capability *cap = (struct v4l2_capability *)arg;
+       int ret;
 
        cap->version = LINUX_VERSION_CODE;
-       return ops->vidioc_querycap(file, fh, cap);
+
+       ret = ops->vidioc_querycap(file, fh, cap);
+
+       cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
+
+       return ret;
 }
 
 static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
@@ -1073,12 +1121,17 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
        bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+       int ret;
+
+       p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
 
        switch (p->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
                        break;
-               return ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+               ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+               p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+               return ret;
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
                if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
                        break;
@@ -1098,7 +1151,9 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
                if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
                        break;
-               return ops->vidioc_g_fmt_vid_out(file, fh, arg);
+               ret = ops->vidioc_g_fmt_vid_out(file, fh, arg);
+               p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+               return ret;
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
                if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
                        break;
@@ -1128,6 +1183,8 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
+       v4l_sanitize_format(p);
+
        switch (p->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap))
@@ -1192,6 +1249,8 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
+       v4l_sanitize_format(p);
+
        switch (p->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap))
@@ -1480,7 +1539,18 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
        struct v4l2_create_buffers *create = arg;
        int ret = check_fmt(file, create->format.type);
 
-       return ret ? ret : ops->vidioc_create_bufs(file, fh, create);
+       if (ret)
+               return ret;
+
+       v4l_sanitize_format(&create->format);
+
+       ret = ops->vidioc_create_bufs(file, fh, create);
+
+       if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+       return ret;
 }
 
 static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
@@ -2062,6 +2132,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
        IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
        IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0),
        IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO),
+       IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, INFO_FL_CLEAR(v4l2_edid, edid)),
+       IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_edid, edid)),
        IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0),
        IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO),
        IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
@@ -2275,9 +2347,9 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
                break;
        }
 
-       case _IOC_NR(VIDIOC_SUBDEV_G_EDID):
-       case _IOC_NR(VIDIOC_SUBDEV_S_EDID): {
-               struct v4l2_subdev_edid *edid = parg;
+       case _IOC_NR(VIDIOC_G_EDID):
+       case _IOC_NR(VIDIOC_S_EDID): {
+               struct v4l2_edid *edid = parg;
 
                if (edid->blocks) {
                        if (edid->blocks > 256) {
index bbd7a6f36e427b3a504a80e27a6a5880ce0fdd9b..fccb22b8340404ccacc12f9885e0a3c29c53db55 100644 (file)
@@ -349,10 +349,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        sd, pad, set_selection, subdev_fh, sel);
        }
 
-       case _IOC_NR(VIDIOC_SUBDEV_G_EDID):
+       case _IOC_NR(VIDIOC_G_EDID):
                return v4l2_subdev_call(sd, pad, get_edid, arg);
 
-       case _IOC_NR(VIDIOC_SUBDEV_S_EDID):
+       case _IOC_NR(VIDIOC_S_EDID):
                return v4l2_subdev_call(sd, pad, set_edid, arg);
 #endif
        default:
@@ -474,3 +474,21 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
 #endif
 }
 EXPORT_SYMBOL(v4l2_subdev_init);
+
+/**
+ * v4l2_subdev_notify_event() - Delivers event notification for subdevice
+ * @sd: The subdev for which to deliver the event
+ * @ev: The event to deliver
+ *
+ * Will deliver the specified event to all userspace event listeners which are
+ * subscribed to the v42l subdev event queue as well as to the bridge driver
+ * using the notify callback. The notification type for the notify callback
+ * will be V4L2_DEVICE_NOTIFY_EVENT.
+ */
+void v4l2_subdev_notify_event(struct v4l2_subdev *sd,
+                             const struct v4l2_event *ev)
+{
+       v4l2_event_queue(sd->devnode, ev);
+       v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT, (void *)ev);
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event);
index fbadb03d2be2f89d2bcd3a082d06a3fa252346b5..45f4bc115558823d3dc32c17fe8826c8884f595f 100644 (file)
@@ -1169,6 +1169,11 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
        struct vb2_queue *q = vb->vb2_queue;
        int ret;
 
+       if (q->error) {
+               dprintk(1, "fatal error occurred on queue\n");
+               return -EIO;
+       }
+
        switch (q->memory) {
        case V4L2_MEMORY_MMAP:
                ret = __qbuf_mmap(vb, b);
@@ -1403,6 +1408,11 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
                        return -EINVAL;
                }
 
+               if (q->error) {
+                       dprintk(1, "Queue in error state, will not wait for buffers\n");
+                       return -EIO;
+               }
+
                if (!list_empty(&q->done_list)) {
                        /*
                         * Found a buffer that we were waiting for.
@@ -1428,7 +1438,8 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
                 */
                dprintk(3, "Will sleep waiting for buffers\n");
                ret = wait_event_interruptible(q->done_wq,
-                               !list_empty(&q->done_list) || !q->streaming);
+                               !list_empty(&q->done_list) || !q->streaming ||
+                               q->error);
 
                /*
                 * We need to reevaluate both conditions again after reacquiring
@@ -1612,6 +1623,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
        if (q->streaming)
                call_qop(q, stop_streaming, q);
        q->streaming = 0;
+       q->error = 0;
 
        /*
         * Remove all buffers from videobuf's list...
@@ -1632,6 +1644,27 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
                __vb2_dqbuf(q->bufs[i]);
 }
 
+/**
+ * vb2_queue_error() - signal a fatal error on the queue
+ * @q:         videobuf2 queue
+ *
+ * Flag that a fatal unrecoverable error has occurred and wake up all processes
+ * waiting on the queue. Polling will now set POLLERR and queuing and dequeuing
+ * buffers will return -EIO.
+ *
+ * The error flag will be cleared when cancelling the queue, either from
+ * vb2_streamoff or vb2_queue_release. Drivers should thus not call this
+ * function before starting the stream, otherwise the error flag will remain set
+ * until the queue is released when closing the device node.
+ */
+void vb2_queue_error(struct vb2_queue *q)
+{
+       q->error = 1;
+
+       wake_up_all(&q->done_wq);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_error);
+
 /**
  * vb2_streamon - start streaming
  * @q:         videobuf2 queue
@@ -2013,9 +2046,10 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
        }
 
        /*
-        * There is nothing to wait for if the queue isn't streaming.
+        * There is nothing to wait for if no buffer has been queued and the
+        * queue isn't streaming, or if the error flag is set.
         */
-       if (!vb2_is_streaming(q))
+       if ((list_empty(&q->queued_list) && !vb2_is_streaming(q)) || q->error)
                return res | POLLERR;
        /*
         * For compatibility with vb1: if QBUF hasn't been called yet, then
@@ -2447,10 +2481,11 @@ size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
 }
 EXPORT_SYMBOL_GPL(vb2_read);
 
-size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count,
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
                loff_t *ppos, int nonblocking)
 {
-       return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 0);
+       return __vb2_perform_fileio(q, (char __user *) data, count,
+                                                       ppos, nonblocking, 0);
 }
 EXPORT_SYMBOL_GPL(vb2_write);
 
@@ -2620,7 +2655,7 @@ int vb2_fop_release(struct file *file)
 }
 EXPORT_SYMBOL_GPL(vb2_fop_release);
 
-ssize_t vb2_fop_write(struct file *file, char __user *buf,
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
                size_t count, loff_t *ppos)
 {
        struct video_device *vdev = video_devdata(file);
index 40178338b61994a024482db29107bd5efaa9454f..f4d2afd554cddba0cc6b3328359ec805cd970c37 100644 (file)
  */
 
 #include <linux/bitops.h>
+#include <linux/bug.h>
 #include <linux/errno.h>
 #include <linux/export.h>
 #include <linux/hdmi.h>
 #include <linux/string.h>
+#include <linux/device.h>
 
-static void hdmi_infoframe_checksum(void *buffer, size_t size)
+#define hdmi_log(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__)
+
+static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
 {
-       u8 *ptr = buffer;
        u8 csum = 0;
        size_t i;
 
@@ -37,7 +40,14 @@ static void hdmi_infoframe_checksum(void *buffer, size_t size)
        for (i = 0; i < size; i++)
                csum += ptr[i];
 
-       ptr[3] = 256 - csum;
+       return 256 - csum;
+}
+
+static void hdmi_infoframe_set_checksum(void *buffer, size_t size)
+{
+       u8 *ptr = buffer;
+
+       ptr[3] = hdmi_infoframe_checksum(buffer, size);
 }
 
 /**
@@ -83,7 +93,7 @@ ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
        if (size < length)
                return -ENOSPC;
 
-       memset(buffer, 0, length);
+       memset(buffer, 0, size);
 
        ptr[0] = frame->type;
        ptr[1] = frame->version;
@@ -95,13 +105,18 @@ ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
 
        ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
 
-       if (frame->active_info_valid)
+       /*
+        * Data byte 1, bit 4 has to be set if we provide the active format
+        * aspect ratio
+        */
+       if (frame->active_aspect & 0xf)
                ptr[0] |= BIT(4);
 
-       if (frame->horizontal_bar_valid)
+       /* Bit 3 and 2 indicate if we transmit horizontal/vertical bar data */
+       if (frame->top_bar || frame->bottom_bar)
                ptr[0] |= BIT(3);
 
-       if (frame->vertical_bar_valid)
+       if (frame->left_bar || frame->right_bar)
                ptr[0] |= BIT(2);
 
        ptr[1] = ((frame->colorimetry & 0x3) << 6) |
@@ -130,7 +145,7 @@ ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
        ptr[11] = frame->right_bar & 0xff;
        ptr[12] = (frame->right_bar >> 8) & 0xff;
 
-       hdmi_infoframe_checksum(buffer, length);
+       hdmi_infoframe_set_checksum(buffer, length);
 
        return length;
 }
@@ -185,7 +200,7 @@ ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
        if (size < length)
                return -ENOSPC;
 
-       memset(buffer, 0, length);
+       memset(buffer, 0, size);
 
        ptr[0] = frame->type;
        ptr[1] = frame->version;
@@ -200,7 +215,7 @@ ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
 
        ptr[24] = frame->sdi;
 
-       hdmi_infoframe_checksum(buffer, length);
+       hdmi_infoframe_set_checksum(buffer, length);
 
        return length;
 }
@@ -250,7 +265,7 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
        if (size < length)
                return -ENOSPC;
 
-       memset(buffer, 0, length);
+       memset(buffer, 0, size);
 
        if (frame->channels >= 2)
                channels = frame->channels - 1;
@@ -275,16 +290,40 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
        if (frame->downmix_inhibit)
                ptr[4] |= BIT(7);
 
-       hdmi_infoframe_checksum(buffer, length);
+       hdmi_infoframe_set_checksum(buffer, length);
 
        return length;
 }
 EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
 
 /**
- * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary
- *                                buffer
+ * hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe
  * @frame: HDMI vendor infoframe
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)
+{
+       memset(frame, 0, sizeof(*frame));
+
+       frame->type = HDMI_INFOFRAME_TYPE_VENDOR;
+       frame->version = 1;
+
+       frame->oui = HDMI_IEEE_OUI;
+
+       /*
+        * 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_vendor_infoframe_init);
+
+/**
+ * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary buffer
+ * @frame: HDMI infoframe
  * @buffer: destination buffer
  * @size: size of buffer
  *
@@ -297,27 +336,909 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
  * error code on failure.
  */
 ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
-                                  void *buffer, size_t size)
+                                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, length);
+       memset(buffer, 0, size);
 
        ptr[0] = frame->type;
        ptr[1] = frame->version;
        ptr[2] = frame->length;
        ptr[3] = 0; /* checksum */
 
-       memcpy(&ptr[HDMI_INFOFRAME_HEADER_SIZE], frame->data, frame->length);
+       /* HDMI OUI */
+       ptr[4] = 0x03;
+       ptr[5] = 0x0c;
+       ptr[6] = 0x00;
 
-       hdmi_infoframe_checksum(buffer, length);
+       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_set_checksum(buffer, length);
 
        return length;
 }
 EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
+
+/*
+ * hdmi_vendor_any_infoframe_pack() - 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)
+{
+       /* 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);
+}
+
+/**
+ * hdmi_infoframe_pack() - write a HDMI 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_infoframe_pack(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(&frame->avi, buffer, size);
+               break;
+       case HDMI_INFOFRAME_TYPE_SPD:
+               length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);
+               break;
+       case HDMI_INFOFRAME_TYPE_AUDIO:
+               length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size);
+               break;
+       case HDMI_INFOFRAME_TYPE_VENDOR:
+               length = hdmi_vendor_any_infoframe_pack(&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);
+
+static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type)
+{
+       if (type < 0x80 || type > 0x9f)
+               return "Invalid";
+       switch (type) {
+       case HDMI_INFOFRAME_TYPE_VENDOR:
+               return "Vendor";
+       case HDMI_INFOFRAME_TYPE_AVI:
+               return "Auxiliary Video Information (AVI)";
+       case HDMI_INFOFRAME_TYPE_SPD:
+               return "Source Product Description (SPD)";
+       case HDMI_INFOFRAME_TYPE_AUDIO:
+               return "Audio";
+       }
+       return "Reserved";
+}
+
+static void hdmi_infoframe_log_header(const char *level,
+                                     struct device *dev,
+                                     struct hdmi_any_infoframe *frame)
+{
+       hdmi_log("HDMI infoframe: %s, version %u, length %u\n",
+               hdmi_infoframe_type_get_name(frame->type),
+               frame->version, frame->length);
+}
+
+static const char *hdmi_colorspace_get_name(enum hdmi_colorspace colorspace)
+{
+       switch (colorspace) {
+       case HDMI_COLORSPACE_RGB:
+               return "RGB";
+       case HDMI_COLORSPACE_YUV422:
+               return "YCbCr 4:2:2";
+       case HDMI_COLORSPACE_YUV444:
+               return "YCbCr 4:4:4";
+       case HDMI_COLORSPACE_YUV420:
+               return "YCbCr 4:2:0";
+       case HDMI_COLORSPACE_RESERVED4:
+               return "Reserved (4)";
+       case HDMI_COLORSPACE_RESERVED5:
+               return "Reserved (5)";
+       case HDMI_COLORSPACE_RESERVED6:
+               return "Reserved (6)";
+       case HDMI_COLORSPACE_IDO_DEFINED:
+               return "IDO Defined";
+       }
+       return "Invalid";
+}
+
+static const char *hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode)
+{
+       switch (scan_mode) {
+       case HDMI_SCAN_MODE_NONE:
+               return "No Data";
+       case HDMI_SCAN_MODE_OVERSCAN:
+               return "Overscan";
+       case HDMI_SCAN_MODE_UNDERSCAN:
+               return "Underscan";
+       case HDMI_SCAN_MODE_RESERVED:
+               return "Reserved";
+       }
+       return "Invalid";
+}
+
+static const char *hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry)
+{
+       switch (colorimetry) {
+       case HDMI_COLORIMETRY_NONE:
+               return "No Data";
+       case HDMI_COLORIMETRY_ITU_601:
+               return "ITU601";
+       case HDMI_COLORIMETRY_ITU_709:
+               return "ITU709";
+       case HDMI_COLORIMETRY_EXTENDED:
+               return "Extended";
+       }
+       return "Invalid";
+}
+
+static const char *
+hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect)
+{
+       switch (picture_aspect) {
+       case HDMI_PICTURE_ASPECT_NONE:
+               return "No Data";
+       case HDMI_PICTURE_ASPECT_4_3:
+               return "4:3";
+       case HDMI_PICTURE_ASPECT_16_9:
+               return "16:9";
+       case HDMI_PICTURE_ASPECT_RESERVED:
+               return "Reserved";
+       }
+       return "Invalid";
+}
+
+static const char *
+hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect)
+{
+       if (active_aspect < 0 || active_aspect > 0xf)
+               return "Invalid";
+
+       switch (active_aspect) {
+       case HDMI_ACTIVE_ASPECT_16_9_TOP:
+               return "16:9 Top";
+       case HDMI_ACTIVE_ASPECT_14_9_TOP:
+               return "14:9 Top";
+       case HDMI_ACTIVE_ASPECT_16_9_CENTER:
+               return "16:9 Center";
+       case HDMI_ACTIVE_ASPECT_PICTURE:
+               return "Same as Picture";
+       case HDMI_ACTIVE_ASPECT_4_3:
+               return "4:3";
+       case HDMI_ACTIVE_ASPECT_16_9:
+               return "16:9";
+       case HDMI_ACTIVE_ASPECT_14_9:
+               return "14:9";
+       case HDMI_ACTIVE_ASPECT_4_3_SP_14_9:
+               return "4:3 SP 14:9";
+       case HDMI_ACTIVE_ASPECT_16_9_SP_14_9:
+               return "16:9 SP 14:9";
+       case HDMI_ACTIVE_ASPECT_16_9_SP_4_3:
+               return "16:9 SP 4:3";
+       }
+       return "Reserved";
+}
+
+static const char *
+hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col)
+{
+       switch (ext_col) {
+       case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
+               return "xvYCC 601";
+       case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
+               return "xvYCC 709";
+       case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
+               return "sYCC 601";
+       case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601:
+               return "Adobe YCC 601";
+       case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB:
+               return "Adobe RGB";
+       case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
+               return "BT.2020 Constant Luminance";
+       case HDMI_EXTENDED_COLORIMETRY_BT2020:
+               return "BT.2020";
+       case HDMI_EXTENDED_COLORIMETRY_RESERVED:
+               return "Reserved";
+       }
+       return "Invalid";
+}
+
+static const char *
+hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange)
+{
+       switch (qrange) {
+       case HDMI_QUANTIZATION_RANGE_DEFAULT:
+               return "Default";
+       case HDMI_QUANTIZATION_RANGE_LIMITED:
+               return "Limited";
+       case HDMI_QUANTIZATION_RANGE_FULL:
+               return "Full";
+       case HDMI_QUANTIZATION_RANGE_RESERVED:
+               return "Reserved";
+       }
+       return "Invalid";
+}
+
+static const char *hdmi_nups_get_name(enum hdmi_nups nups)
+{
+       switch (nups) {
+       case HDMI_NUPS_UNKNOWN:
+               return "Unknown Non-uniform Scaling";
+       case HDMI_NUPS_HORIZONTAL:
+               return "Horizontally Scaled";
+       case HDMI_NUPS_VERTICAL:
+               return "Vertically Scaled";
+       case HDMI_NUPS_BOTH:
+               return "Horizontally and Vertically Scaled";
+       }
+       return "Invalid";
+}
+
+static const char *
+hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange)
+{
+       switch (qrange) {
+       case HDMI_YCC_QUANTIZATION_RANGE_LIMITED:
+               return "Limited";
+       case HDMI_YCC_QUANTIZATION_RANGE_FULL:
+               return "Full";
+       }
+       return "Invalid";
+}
+
+static const char *
+hdmi_content_type_get_name(enum hdmi_content_type content_type)
+{
+       switch (content_type) {
+       case HDMI_CONTENT_TYPE_GRAPHICS:
+               return "Graphics";
+       case HDMI_CONTENT_TYPE_PHOTO:
+               return "Photo";
+       case HDMI_CONTENT_TYPE_CINEMA:
+               return "Cinema";
+       case HDMI_CONTENT_TYPE_GAME:
+               return "Game";
+       }
+       return "Invalid";
+}
+
+/**
+ * hdmi_avi_infoframe_log() - log info of HDMI AVI infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI AVI infoframe
+ */
+static void hdmi_avi_infoframe_log(const char *level,
+                                  struct device *dev,
+                                  struct hdmi_avi_infoframe *frame)
+{
+       hdmi_infoframe_log_header(level, dev,
+                                 (struct hdmi_any_infoframe *)frame);
+
+       hdmi_log("    colorspace: %s\n",
+                       hdmi_colorspace_get_name(frame->colorspace));
+       hdmi_log("    scan mode: %s\n",
+                       hdmi_scan_mode_get_name(frame->scan_mode));
+       hdmi_log("    colorimetry: %s\n",
+                       hdmi_colorimetry_get_name(frame->colorimetry));
+       hdmi_log("    picture aspect: %s\n",
+                       hdmi_picture_aspect_get_name(frame->picture_aspect));
+       hdmi_log("    active aspect: %s\n",
+                       hdmi_active_aspect_get_name(frame->active_aspect));
+       hdmi_log("    itc: %s\n", frame->itc ? "IT Content" : "No Data");
+       hdmi_log("    extended colorimetry: %s\n",
+                       hdmi_extended_colorimetry_get_name(frame->extended_colorimetry));
+       hdmi_log("    quantization range: %s\n",
+                       hdmi_quantization_range_get_name(frame->quantization_range));
+       hdmi_log("    nups: %s\n", hdmi_nups_get_name(frame->nups));
+       hdmi_log("    video code: %u\n", frame->video_code);
+       hdmi_log("    ycc quantization range: %s\n",
+                       hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range));
+       hdmi_log("    hdmi content type: %s\n",
+                       hdmi_content_type_get_name(frame->content_type));
+       hdmi_log("    pixel repeat: %u\n", frame->pixel_repeat);
+       hdmi_log("    bar top %u, bottom %u, left %u, right %u\n",
+                       frame->top_bar, frame->bottom_bar,
+                       frame->left_bar, frame->right_bar);
+}
+
+static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi)
+{
+       if (sdi < 0 || sdi > 0xff)
+               return "Invalid";
+       switch (sdi) {
+       case HDMI_SPD_SDI_UNKNOWN:
+               return "Unknown";
+       case HDMI_SPD_SDI_DSTB:
+               return "Digital STB";
+       case HDMI_SPD_SDI_DVDP:
+               return "DVD Player";
+       case HDMI_SPD_SDI_DVHS:
+               return "D-VHS";
+       case HDMI_SPD_SDI_HDDVR:
+               return "HDD Videorecorder";
+       case HDMI_SPD_SDI_DVC:
+               return "DVC";
+       case HDMI_SPD_SDI_DSC:
+               return "DSC";
+       case HDMI_SPD_SDI_VCD:
+               return "Video CD";
+       case HDMI_SPD_SDI_GAME:
+               return "Game";
+       case HDMI_SPD_SDI_PC:
+               return "PC General";
+       case HDMI_SPD_SDI_BD:
+               return "Blu-Ray Disc (BD)";
+       case HDMI_SPD_SDI_SACD:
+               return "Super Audio CD";
+       case HDMI_SPD_SDI_HDDVD:
+               return "HD DVD";
+       case HDMI_SPD_SDI_PMP:
+               return "PMP";
+       }
+       return "Reserved";
+}
+
+/**
+ * hdmi_spd_infoframe_log() - log info of HDMI SPD infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI SPD infoframe
+ */
+static void hdmi_spd_infoframe_log(const char *level,
+                                  struct device *dev,
+                                  struct hdmi_spd_infoframe *frame)
+{
+       u8 buf[17];
+
+       hdmi_infoframe_log_header(level, dev,
+                                 (struct hdmi_any_infoframe *)frame);
+
+       memset(buf, 0, sizeof(buf));
+
+       strncpy(buf, frame->vendor, 8);
+       hdmi_log("    vendor: %s\n", buf);
+       strncpy(buf, frame->product, 16);
+       hdmi_log("    product: %s\n", buf);
+       hdmi_log("    source device information: %s (0x%x)\n",
+               hdmi_spd_sdi_get_name(frame->sdi), frame->sdi);
+}
+
+static const char *
+hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type)
+{
+       switch (coding_type) {
+       case HDMI_AUDIO_CODING_TYPE_STREAM:
+               return "Refer to Stream Header";
+       case HDMI_AUDIO_CODING_TYPE_PCM:
+               return "PCM";
+       case HDMI_AUDIO_CODING_TYPE_AC3:
+               return "AC-3";
+       case HDMI_AUDIO_CODING_TYPE_MPEG1:
+               return "MPEG1";
+       case HDMI_AUDIO_CODING_TYPE_MP3:
+               return "MP3";
+       case HDMI_AUDIO_CODING_TYPE_MPEG2:
+               return "MPEG2";
+       case HDMI_AUDIO_CODING_TYPE_AAC_LC:
+               return "AAC";
+       case HDMI_AUDIO_CODING_TYPE_DTS:
+               return "DTS";
+       case HDMI_AUDIO_CODING_TYPE_ATRAC:
+               return "ATRAC";
+       case HDMI_AUDIO_CODING_TYPE_DSD:
+               return "One Bit Audio";
+       case HDMI_AUDIO_CODING_TYPE_EAC3:
+               return "Dolby Digital +";
+       case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+               return "DTS-HD";
+       case HDMI_AUDIO_CODING_TYPE_MLP:
+               return "MAT (MLP)";
+       case HDMI_AUDIO_CODING_TYPE_DST:
+               return "DST";
+       case HDMI_AUDIO_CODING_TYPE_WMA_PRO:
+               return "WMA PRO";
+       case HDMI_AUDIO_CODING_TYPE_CXT:
+               return "Refer to CXT";
+       }
+       return "Invalid";
+}
+
+static const char *
+hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size)
+{
+       switch (sample_size) {
+       case HDMI_AUDIO_SAMPLE_SIZE_STREAM:
+               return "Refer to Stream Header";
+       case HDMI_AUDIO_SAMPLE_SIZE_16:
+               return "16 bit";
+       case HDMI_AUDIO_SAMPLE_SIZE_20:
+               return "20 bit";
+       case HDMI_AUDIO_SAMPLE_SIZE_24:
+               return "24 bit";
+       }
+       return "Invalid";
+}
+
+static const char *
+hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq)
+{
+       switch (freq) {
+       case HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM:
+               return "Refer to Stream Header";
+       case HDMI_AUDIO_SAMPLE_FREQUENCY_32000:
+               return "32 kHz";
+       case HDMI_AUDIO_SAMPLE_FREQUENCY_44100:
+               return "44.1 kHz (CD)";
+       case HDMI_AUDIO_SAMPLE_FREQUENCY_48000:
+               return "48 kHz";
+       case HDMI_AUDIO_SAMPLE_FREQUENCY_88200:
+               return "88.2 kHz";
+       case HDMI_AUDIO_SAMPLE_FREQUENCY_96000:
+               return "96 kHz";
+       case HDMI_AUDIO_SAMPLE_FREQUENCY_176400:
+               return "176.4 kHz";
+       case HDMI_AUDIO_SAMPLE_FREQUENCY_192000:
+               return "192 kHz";
+       }
+       return "Invalid";
+}
+
+static const char *
+hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)
+{
+       if (ctx < 0 || ctx > 0x1f)
+               return "Invalid";
+
+       switch (ctx) {
+       case HDMI_AUDIO_CODING_TYPE_EXT_CT:
+               return "Refer to CT";
+       case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC:
+               return "HE AAC";
+       case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2:
+               return "HE AAC v2";
+       case HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND:
+               return "MPEG SURROUND";
+       case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC:
+               return "MPEG-4 HE AAC";
+       case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2:
+               return "MPEG-4 HE AAC v2";
+       case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC:
+               return "MPEG-4 AAC LC";
+       case HDMI_AUDIO_CODING_TYPE_EXT_DRA:
+               return "DRA";
+       case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND:
+               return "MPEG-4 HE AAC + MPEG Surround";
+       case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND:
+               return "MPEG-4 AAC LC + MPEG Surround";
+       }
+       return "Reserved";
+}
+
+/**
+ * hdmi_audio_infoframe_log() - log info of HDMI AUDIO infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI AUDIO infoframe
+ */
+static void hdmi_audio_infoframe_log(const char *level,
+                                    struct device *dev,
+                                    struct hdmi_audio_infoframe *frame)
+{
+       hdmi_infoframe_log_header(level, dev,
+                                 (struct hdmi_any_infoframe *)frame);
+
+       if (frame->channels)
+               hdmi_log("    channels: %u\n", frame->channels - 1);
+       else
+               hdmi_log("    channels: Refer to stream header\n");
+       hdmi_log("    coding type: %s\n",
+                       hdmi_audio_coding_type_get_name(frame->coding_type));
+       hdmi_log("    sample size: %s\n",
+                       hdmi_audio_sample_size_get_name(frame->sample_size));
+       hdmi_log("    sample frequency: %s\n",
+                       hdmi_audio_sample_frequency_get_name(frame->sample_frequency));
+       hdmi_log("    coding type ext: %s\n",
+                       hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext));
+       hdmi_log("    channel allocation: 0x%x\n",
+                       frame->channel_allocation);
+       hdmi_log("    level shift value: %u dB\n",
+                       frame->level_shift_value);
+       hdmi_log("    downmix inhibit: %s\n",
+                       frame->downmix_inhibit ? "Yes" : "No");
+}
+
+static const char *
+hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)
+{
+       if (s3d_struct < 0 || s3d_struct > 0xf)
+               return "Invalid";
+
+       switch (s3d_struct) {
+       case HDMI_3D_STRUCTURE_FRAME_PACKING:
+               return "Frame Packing";
+       case HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE:
+               return "Field Alternative";
+       case HDMI_3D_STRUCTURE_LINE_ALTERNATIVE:
+               return "Line Alternative";
+       case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL:
+               return "Side-by-side (Full)";
+       case HDMI_3D_STRUCTURE_L_DEPTH:
+               return "L + Depth";
+       case HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH:
+               return "L + Depth + Graphics + Graphics-depth";
+       case HDMI_3D_STRUCTURE_TOP_AND_BOTTOM:
+               return "Top-and-Bottom";
+       case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF:
+               return "Side-by-side (Half)";
+       default:
+               break;
+       }
+       return "Reserved";
+}
+
+/**
+ * hdmi_vendor_infoframe_log() - log info of HDMI VENDOR infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI VENDOR infoframe
+ */
+static void
+hdmi_vendor_any_infoframe_log(const char *level,
+                             struct device *dev,
+                             union hdmi_vendor_any_infoframe *frame)
+{
+       struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
+
+       hdmi_infoframe_log_header(level, dev,
+                                 (struct hdmi_any_infoframe *)frame);
+
+       if (frame->any.oui != HDMI_IEEE_OUI) {
+               hdmi_log("    not a HDMI vendor infoframe\n");
+               return;
+       }
+       if (hvf->vic == 0 && hvf->s3d_struct == HDMI_3D_STRUCTURE_INVALID) {
+               hdmi_log("    empty frame\n");
+               return;
+       }
+
+       if (hvf->vic)
+               hdmi_log("    HDMI VIC: %u\n", hvf->vic);
+       if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {
+               hdmi_log("    3D structure: %s\n",
+                               hdmi_3d_structure_get_name(hvf->s3d_struct));
+               if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
+                       hdmi_log("    3D extension data: %d\n",
+                                       hvf->s3d_ext_data);
+       }
+}
+
+/**
+ * hdmi_infoframe_log() - log info of HDMI infoframe
+ * @level: logging level
+ * @dev: device
+ * @frame: HDMI infoframe
+ */
+void hdmi_infoframe_log(const char *level,
+                       struct device *dev,
+                       union hdmi_infoframe *frame)
+{
+       switch (frame->any.type) {
+       case HDMI_INFOFRAME_TYPE_AVI:
+               hdmi_avi_infoframe_log(level, dev, &frame->avi);
+               break;
+       case HDMI_INFOFRAME_TYPE_SPD:
+               hdmi_spd_infoframe_log(level, dev, &frame->spd);
+               break;
+       case HDMI_INFOFRAME_TYPE_AUDIO:
+               hdmi_audio_infoframe_log(level, dev, &frame->audio);
+               break;
+       case HDMI_INFOFRAME_TYPE_VENDOR:
+               hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor);
+               break;
+       }
+}
+EXPORT_SYMBOL(hdmi_infoframe_log);
+
+/**
+ * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe
+ * @buffer: source buffer
+ * @frame: HDMI AVI infoframe
+ *
+ * Unpacks the information contained in binary @buffer into a structured
+ * @frame of the HDMI Auxiliary Video (AVI) information frame.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
+                                    void *buffer)
+{
+       u8 *ptr = buffer;
+       int ret;
+
+       if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI ||
+           ptr[1] != 2 ||
+           ptr[2] != HDMI_AVI_INFOFRAME_SIZE)
+               return -EINVAL;
+
+       if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
+               return -EINVAL;
+
+       ret = hdmi_avi_infoframe_init(frame);
+       if (ret)
+               return ret;
+
+       ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+       frame->colorspace = (ptr[0] >> 5) & 0x3;
+       if (ptr[0] & 0x10)
+               frame->active_aspect = ptr[1] & 0xf;
+       if (ptr[0] & 0x8) {
+               frame->top_bar = (ptr[5] << 8) + ptr[6];
+               frame->bottom_bar = (ptr[7] << 8) + ptr[8];
+       }
+       if (ptr[0] & 0x4) {
+               frame->left_bar = (ptr[9] << 8) + ptr[10];
+               frame->right_bar = (ptr[11] << 8) + ptr[12];
+       }
+       frame->scan_mode = ptr[0] & 0x3;
+
+       frame->colorimetry = (ptr[1] >> 6) & 0x3;
+       frame->picture_aspect = (ptr[1] >> 4) & 0x3;
+       frame->active_aspect = ptr[1] & 0xf;
+
+       frame->itc = ptr[2] & 0x80 ? true : false;
+       frame->extended_colorimetry = (ptr[2] >> 4) & 0x7;
+       frame->quantization_range = (ptr[2] >> 2) & 0x3;
+       frame->nups = ptr[2] & 0x3;
+
+       frame->video_code = ptr[3] & 0x7f;
+       frame->ycc_quantization_range = (ptr[4] >> 6) & 0x3;
+       frame->content_type = (ptr[4] >> 4) & 0x3;
+
+       frame->pixel_repeat = ptr[4] & 0xf;
+
+       return 0;
+}
+
+/**
+ * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe
+ * @buffer: source buffer
+ * @frame: HDMI SPD infoframe
+ *
+ * Unpacks the information contained in binary @buffer into a structured
+ * @frame of the HDMI Source Product Description (SPD) information frame.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
+                                    void *buffer)
+{
+       u8 *ptr = buffer;
+       int ret;
+
+       if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD ||
+           ptr[1] != 1 ||
+           ptr[2] != HDMI_SPD_INFOFRAME_SIZE) {
+               return -EINVAL;
+       }
+
+       if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0)
+               return -EINVAL;
+
+       ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+       ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8);
+       if (ret)
+               return ret;
+
+       frame->sdi = ptr[24];
+
+       return 0;
+}
+
+/**
+ * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe
+ * @buffer: source buffer
+ * @frame: HDMI Audio infoframe
+ *
+ * Unpacks the information contained in binary @buffer into a structured
+ * @frame of the HDMI Audio information frame.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
+                                      void *buffer)
+{
+       u8 *ptr = buffer;
+       int ret;
+
+       if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO ||
+           ptr[1] != 1 ||
+           ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) {
+               return -EINVAL;
+       }
+
+       if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0)
+               return -EINVAL;
+
+       ret = hdmi_audio_infoframe_init(frame);
+       if (ret)
+               return ret;
+
+       ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+       frame->channels = ptr[0] & 0x7;
+       frame->coding_type = (ptr[0] >> 4) & 0xf;
+       frame->sample_size = ptr[1] & 0x3;
+       frame->sample_frequency = (ptr[1] >> 2) & 0x7;
+       frame->coding_type_ext = ptr[2] & 0x1f;
+       frame->channel_allocation = ptr[3];
+       frame->level_shift_value = (ptr[4] >> 3) & 0xf;
+       frame->downmix_inhibit = ptr[4] & 0x80 ? true : false;
+
+       return 0;
+}
+
+/**
+ * hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe
+ * @buffer: source buffer
+ * @frame: HDMI Vendor infoframe
+ *
+ * Unpacks the information contained in binary @buffer into a structured
+ * @frame of the HDMI Vendor information frame.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int
+hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
+                                void *buffer)
+{
+       u8 *ptr = buffer;
+       size_t length;
+       int ret;
+       u8 hdmi_video_format;
+       struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
+
+       if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||
+           ptr[1] != 1 ||
+           (ptr[2] != 5 && ptr[2] != 6))
+               return -EINVAL;
+
+       length = ptr[2];
+
+       if (hdmi_infoframe_checksum(buffer,
+                                   HDMI_INFOFRAME_HEADER_SIZE + length) != 0)
+               return -EINVAL;
+
+       ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+       /* HDMI OUI */
+       if ((ptr[0] != 0x03) ||
+           (ptr[1] != 0x0c) ||
+           (ptr[2] != 0x00))
+               return -EINVAL;
+
+       hdmi_video_format = ptr[3] >> 5;
+
+       if (hdmi_video_format > 0x2)
+               return -EINVAL;
+
+       ret = hdmi_vendor_infoframe_init(hvf);
+       if (ret)
+               return ret;
+
+       hvf->length = length;
+
+       if (hdmi_video_format == 0x1) {
+               hvf->vic = ptr[4];
+       } else if (hdmi_video_format == 0x2) {
+               hvf->s3d_struct = ptr[4] >> 4;
+               if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) {
+                       if (length == 6)
+                               hvf->s3d_ext_data = ptr[5] >> 4;
+                       else
+                               return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe
+ * @buffer: source buffer
+ * @frame: HDMI infoframe
+ *
+ * Unpacks the information contained in binary buffer @buffer into a structured
+ * @frame of a HDMI infoframe.
+ * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
+ * specification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer)
+{
+       int ret;
+       u8 *ptr = buffer;
+
+       switch (ptr[0]) {
+       case HDMI_INFOFRAME_TYPE_AVI:
+               ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer);
+               break;
+       case HDMI_INFOFRAME_TYPE_SPD:
+               ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer);
+               break;
+       case HDMI_INFOFRAME_TYPE_AUDIO:
+               ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer);
+               break;
+       case HDMI_INFOFRAME_TYPE_VENDOR:
+               ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(hdmi_infoframe_unpack);
index 3b589440ecfe8c6919a52acfed5b893544747ad2..61a9f61a87dea691009fdffb32cca0ffa3824a06 100644 (file)
@@ -10,6 +10,7 @@
 #define __LINUX_HDMI_H_
 
 #include <linux/types.h>
+#include <linux/device.h>
 
 enum hdmi_infoframe_type {
        HDMI_INFOFRAME_TYPE_VENDOR = 0x81,
@@ -18,21 +19,37 @@ enum hdmi_infoframe_type {
        HDMI_INFOFRAME_TYPE_AUDIO = 0x84,
 };
 
+#define HDMI_IEEE_OUI 0x000c03
 #define HDMI_INFOFRAME_HEADER_SIZE  4
 #define HDMI_AVI_INFOFRAME_SIZE    13
 #define HDMI_SPD_INFOFRAME_SIZE    25
 #define HDMI_AUDIO_INFOFRAME_SIZE  10
 
+#define HDMI_INFOFRAME_SIZE(type)      \
+       (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE)
+
+struct hdmi_any_infoframe {
+       enum hdmi_infoframe_type type;
+       unsigned char version;
+       unsigned char length;
+};
+
 enum hdmi_colorspace {
        HDMI_COLORSPACE_RGB,
        HDMI_COLORSPACE_YUV422,
        HDMI_COLORSPACE_YUV444,
+       HDMI_COLORSPACE_YUV420,
+       HDMI_COLORSPACE_RESERVED4,
+       HDMI_COLORSPACE_RESERVED5,
+       HDMI_COLORSPACE_RESERVED6,
+       HDMI_COLORSPACE_IDO_DEFINED,
 };
 
 enum hdmi_scan_mode {
        HDMI_SCAN_MODE_NONE,
        HDMI_SCAN_MODE_OVERSCAN,
        HDMI_SCAN_MODE_UNDERSCAN,
+       HDMI_SCAN_MODE_RESERVED,
 };
 
 enum hdmi_colorimetry {
@@ -46,6 +63,7 @@ enum hdmi_picture_aspect {
        HDMI_PICTURE_ASPECT_NONE,
        HDMI_PICTURE_ASPECT_4_3,
        HDMI_PICTURE_ASPECT_16_9,
+       HDMI_PICTURE_ASPECT_RESERVED,
 };
 
 enum hdmi_active_aspect {
@@ -67,12 +85,18 @@ enum hdmi_extended_colorimetry {
        HDMI_EXTENDED_COLORIMETRY_S_YCC_601,
        HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601,
        HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB,
+
+       /* The following EC values are only defined in CEA-861-F. */
+       HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM,
+       HDMI_EXTENDED_COLORIMETRY_BT2020,
+       HDMI_EXTENDED_COLORIMETRY_RESERVED,
 };
 
 enum hdmi_quantization_range {
        HDMI_QUANTIZATION_RANGE_DEFAULT,
        HDMI_QUANTIZATION_RANGE_LIMITED,
        HDMI_QUANTIZATION_RANGE_FULL,
+       HDMI_QUANTIZATION_RANGE_RESERVED,
 };
 
 /* non-uniform picture scaling */
@@ -89,7 +113,7 @@ enum hdmi_ycc_quantization_range {
 };
 
 enum hdmi_content_type {
-       HDMI_CONTENT_TYPE_NONE,
+       HDMI_CONTENT_TYPE_GRAPHICS,
        HDMI_CONTENT_TYPE_PHOTO,
        HDMI_CONTENT_TYPE_CINEMA,
        HDMI_CONTENT_TYPE_GAME,
@@ -100,9 +124,6 @@ struct hdmi_avi_infoframe {
        unsigned char version;
        unsigned char length;
        enum hdmi_colorspace colorspace;
-       bool active_info_valid;
-       bool horizontal_bar_valid;
-       bool vertical_bar_valid;
        enum hdmi_scan_mode scan_mode;
        enum hdmi_colorimetry colorimetry;
        enum hdmi_picture_aspect picture_aspect;
@@ -172,6 +193,7 @@ enum hdmi_audio_coding_type {
        HDMI_AUDIO_CODING_TYPE_MLP,
        HDMI_AUDIO_CODING_TYPE_DST,
        HDMI_AUDIO_CODING_TYPE_WMA_PRO,
+       HDMI_AUDIO_CODING_TYPE_CXT,
 };
 
 enum hdmi_audio_sample_size {
@@ -193,10 +215,23 @@ enum hdmi_audio_sample_frequency {
 };
 
 enum hdmi_audio_coding_type_ext {
-       HDMI_AUDIO_CODING_TYPE_EXT_STREAM,
+       HDMI_AUDIO_CODING_TYPE_EXT_CT,
+       /*
+        * The next three CXT values are defined in CEA-861-E only.
+        * They do not exist in older versions, and in CEA-861-F they are
+        * defined as 'Not in use'.
+        */
        HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC,
        HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2,
        HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND,
+
+       /* The following CXT values are only defined in CEA-861-F. */
+       HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC,
+       HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2,
+       HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC,
+       HDMI_AUDIO_CODING_TYPE_EXT_DRA,
+       HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND,
+       HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND = 10,
 };
 
 struct hdmi_audio_infoframe {
@@ -218,14 +253,55 @@ int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_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_vendor_infoframe {
        enum hdmi_infoframe_type type;
        unsigned char version;
        unsigned char length;
-       u8 data[27];
+       unsigned int oui;
+       u8 vic;
+       enum hdmi_3d_structure s3d_struct;
+       unsigned int s3d_ext_data;
 };
 
+int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame);
 ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
                                   void *buffer, size_t size);
 
+union hdmi_vendor_any_infoframe {
+       struct {
+               enum hdmi_infoframe_type type;
+               unsigned char version;
+               unsigned char length;
+               unsigned int oui;
+       } any;
+       struct hdmi_vendor_infoframe hdmi;
+};
+
+union hdmi_infoframe {
+       struct hdmi_any_infoframe any;
+       struct hdmi_avi_infoframe avi;
+       struct hdmi_spd_infoframe spd;
+       union hdmi_vendor_any_infoframe vendor;
+       struct hdmi_audio_infoframe audio;
+};
+
+ssize_t
+hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size);
+int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer);
+void hdmi_infoframe_log(const char *level, struct device *dev,
+                       union hdmi_infoframe *frame);
+
 #endif /* _DRM_HDMI_H */
index 1d93c48cb3718ee405ad70a1958e1d2e26f2dd69..543dc4578bdc955970578e3ac689a2b6f468f46e 100644 (file)
@@ -211,19 +211,6 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
                const struct v4l2_discrete_probe *probe,
                s32 width, s32 height);
 
-bool v4l_match_dv_timings(const struct v4l2_dv_timings *t1,
-                         const struct v4l2_dv_timings *t2,
-                         unsigned pclock_delta);
-
-bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync,
-               u32 polarities, struct v4l2_dv_timings *fmt);
-
-bool v4l2_detect_gtf(unsigned frame_height, unsigned hfreq, unsigned vsync,
-               u32 polarities, struct v4l2_fract aspect,
-               struct v4l2_dv_timings *fmt);
-
-struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait);
-
 void v4l2_get_timestamp(struct timeval *tv);
 
 #endif /* V4L2_COMMON_H_ */
diff --git a/include/media/v4l2-dv-timings.h b/include/media/v4l2-dv-timings.h
new file mode 100644 (file)
index 0000000..b6130b5
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * v4l2-dv-timings - Internal header with dv-timings helper functions
+ *
+ * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __V4L2_DV_TIMINGS_H
+#define __V4L2_DV_TIMINGS_H
+
+#include <linux/videodev2.h>
+
+/**
+ * v4l2_dv_timings_presets: list of all dv_timings presets.
+ */
+extern const struct v4l2_dv_timings v4l2_dv_timings_presets[];
+
+/**
+ * v4l2_check_dv_timings_fnc - timings check callback
+ *
+ * @t: the v4l2_dv_timings struct.
+ * @handle: a handle from the driver.
+ *
+ * Returns true if the given timings are valid.
+ */
+typedef bool v4l2_check_dv_timings_fnc(const struct v4l2_dv_timings *t, void *handle);
+
+/**
+ * v4l2_valid_dv_timings() - are these timings valid?
+ *
+ * @t:   the v4l2_dv_timings struct.
+ * @cap: the v4l2_dv_timings_cap capabilities.
+ * @fnc: callback to check if this timing is OK. May be NULL.
+ * @fnc_handle: a handle that is passed on to @fnc.
+ *
+ * Returns true if the given dv_timings struct is supported by the
+ * hardware capabilities and the callback function (if non-NULL), returns
+ * false otherwise.
+ */
+bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t,
+                          const struct v4l2_dv_timings_cap *cap,
+                          v4l2_check_dv_timings_fnc fnc,
+                          void *fnc_handle);
+
+/**
+ * v4l2_enum_dv_timings_cap() - Helper function to enumerate possible DV
+ *      timings based on capabilities
+ *
+ * @t:   the v4l2_enum_dv_timings struct.
+ * @cap: the v4l2_dv_timings_cap capabilities.
+ * @fnc: callback to check if this timing is OK. May be NULL.
+ * @fnc_handle: a handle that is passed on to @fnc.
+ *
+ * This enumerates dv_timings using the full list of possible CEA-861 and DMT
+ * timings, filtering out any timings that are not supported based on the
+ * hardware capabilities and the callback function (if non-NULL).
+ *
+ * If a valid timing for the given index is found, it will fill in @t and
+ * return 0, otherwise it returns -EINVAL.
+ */
+int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t,
+                            const struct v4l2_dv_timings_cap *cap,
+                            v4l2_check_dv_timings_fnc fnc,
+                            void *fnc_handle);
+
+/**
+ * v4l2_find_dv_timings_cap() - Find the closest timings struct
+ *
+ * @t:   the v4l2_enum_dv_timings struct.
+ * @cap: the v4l2_dv_timings_cap capabilities.
+ * @pclock_delta: maximum delta between t->pixelclock and the timing struct
+ *             under consideration.
+ * @fnc: callback to check if a given timings struct is OK. May be NULL.
+ * @fnc_handle: a handle that is passed on to @fnc.
+ *
+ * This function tries to map the given timings to an entry in the
+ * full list of possible CEA-861 and DMT timings, filtering out any timings
+ * that are not supported based on the hardware capabilities and the callback
+ * function (if non-NULL).
+ *
+ * On success it will fill in @t with the found timings and it returns true.
+ * On failure it will return false.
+ */
+bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t,
+                             const struct v4l2_dv_timings_cap *cap,
+                             unsigned pclock_delta,
+                             v4l2_check_dv_timings_fnc fnc,
+                             void *fnc_handle);
+
+/**
+ * v4l2_match_dv_timings() - do two timings match?
+ *
+ * @measured:    the measured timings data.
+ * @standard:    the timings according to the standard.
+ * @pclock_delta: maximum delta in Hz between standard->pixelclock and
+ *             the measured timings.
+ *
+ * Returns true if the two timings match, returns false otherwise.
+ */
+bool v4l2_match_dv_timings(const struct v4l2_dv_timings *measured,
+                          const struct v4l2_dv_timings *standard,
+                          unsigned pclock_delta);
+
+/**
+ * v4l2_print_dv_timings() - log the contents of a dv_timings struct
+ * @dev_prefix:device prefix for each log line.
+ * @prefix:    additional prefix for each log line, may be NULL.
+ * @t:         the timings data.
+ * @detailed:  if true, give a detailed log.
+ */
+void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix,
+                          const struct v4l2_dv_timings *t, bool detailed);
+
+/**
+ * v4l2_detect_cvt - detect if the given timings follow the CVT standard
+ *
+ * @frame_height - the total height of the frame (including blanking) in lines.
+ * @hfreq - the horizontal frequency in Hz.
+ * @vsync - the height of the vertical sync in lines.
+ * @active_width - active width of image (does not include blanking). This
+ * information is needed only in case of version 2 of reduced blanking.
+ * In other cases, this parameter does not have any effect on timings.
+ * @polarities - the horizontal and vertical polarities (same as struct
+ *             v4l2_bt_timings polarities).
+ * @interlaced - if this flag is true, it indicates interlaced format
+ * @fmt - the resulting timings.
+ *
+ * This function will attempt to detect if the given values correspond to a
+ * valid CVT format. If so, then it will return true, and fmt will be filled
+ * in with the found CVT timings.
+ */
+bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync,
+               unsigned active_width, u32 polarities, bool interlaced,
+               struct v4l2_dv_timings *fmt);
+
+/**
+ * v4l2_detect_gtf - detect if the given timings follow the GTF standard
+ *
+ * @frame_height - the total height of the frame (including blanking) in lines.
+ * @hfreq - the horizontal frequency in Hz.
+ * @vsync - the height of the vertical sync in lines.
+ * @polarities - the horizontal and vertical polarities (same as struct
+ *             v4l2_bt_timings polarities).
+ * @interlaced - if this flag is true, it indicates interlaced format
+ * @aspect - preferred aspect ratio. GTF has no method of determining the
+ *             aspect ratio in order to derive the image width from the
+ *             image height, so it has to be passed explicitly. Usually
+ *             the native screen aspect ratio is used for this. If it
+ *             is not filled in correctly, then 16:9 will be assumed.
+ * @fmt - the resulting timings.
+ *
+ * This function will attempt to detect if the given values correspond to a
+ * valid GTF format. If so, then it will return true, and fmt will be filled
+ * in with the found GTF timings.
+ */
+bool v4l2_detect_gtf(unsigned frame_height, unsigned hfreq, unsigned vsync,
+               u32 polarities, bool interlaced, struct v4l2_fract aspect,
+               struct v4l2_dv_timings *fmt);
+
+/**
+ * v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes
+ *     0x15 and 0x16 from the EDID.
+ *
+ * @hor_landscape - byte 0x15 from the EDID.
+ * @vert_portrait - byte 0x16 from the EDID.
+ *
+ * Determines the aspect ratio from the EDID.
+ * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2:
+ * "Horizontal and Vertical Screen Size or Aspect Ratio"
+ */
+struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait);
+
+#endif
index be05d019de25e17f8aa3f5ec4698810f17ec4795..1ab9045e52e3815f88702cc91469a3646e2b46b6 100644 (file)
@@ -132,4 +132,8 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
 void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);
 int v4l2_event_subdev_unsubscribe(struct v4l2_subdev *sd, struct v4l2_fh *fh,
                                  struct v4l2_event_subscription *sub);
+int v4l2_src_change_event_subscribe(struct v4l2_fh *fh,
+                               const struct v4l2_event_subscription *sub);
+int v4l2_src_change_event_subdev_subscribe(struct v4l2_subdev *sd,
+               struct v4l2_fh *fh, struct v4l2_event_subscription *sub);
 #endif /* V4L2_EVENT_H */
index 931652f0e2af9e20a7d79053cbd718e8aeceaddc..4f6d7e32b6475233a61de81bd81dd1941b5f0dc6 100644 (file)
@@ -267,6 +267,8 @@ struct v4l2_ioctl_ops {
                                    struct v4l2_enum_dv_timings *timings);
        int (*vidioc_dv_timings_cap) (struct file *file, void *fh,
                                    struct v4l2_dv_timings_cap *cap);
+       int (*vidioc_g_edid) (struct file *file, void *fh, struct v4l2_edid *edid);
+       int (*vidioc_s_edid) (struct file *file, void *fh, struct v4l2_edid *edid);
 
        int (*vidioc_subscribe_event)  (struct v4l2_fh *fh,
                                        const struct v4l2_event_subscription *sub);
index 395c4a95a42a1821e20ebe28d1368e6c10795ee3..645a3f4182b032fcc11fcc53d05de86708ea7ee8 100644 (file)
@@ -94,6 +94,9 @@ static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
        pix_fmt->height = mbus_fmt->height;
        pix_fmt->field = mbus_fmt->field;
        pix_fmt->colorspace = mbus_fmt->colorspace;
+       pix_fmt->ycbcr_enc = mbus_fmt->ycbcr_enc;
+       pix_fmt->quantization = mbus_fmt->quantization;
+       pix_fmt->xfer_func = mbus_fmt->xfer_func;
 }
 
 static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt,
@@ -104,6 +107,9 @@ static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt,
        mbus_fmt->height = pix_fmt->height;
        mbus_fmt->field = pix_fmt->field;
        mbus_fmt->colorspace = pix_fmt->colorspace;
+       mbus_fmt->ycbcr_enc = pix_fmt->ycbcr_enc;
+       mbus_fmt->quantization = pix_fmt->quantization;
+       mbus_fmt->xfer_func = pix_fmt->xfer_func;
        mbus_fmt->code = code;
 }
 
index a2e200895775f079c0a2e48b6ab3a4bb9a2afd8c..e5d8657f07b62886163c81832557fc172cd4a029 100644 (file)
@@ -44,6 +44,7 @@
 
 struct v4l2_device;
 struct v4l2_ctrl_handler;
+struct v4l2_event;
 struct v4l2_event_subscription;
 struct v4l2_fh;
 struct v4l2_subdev;
@@ -731,4 +732,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd,
 #define v4l2_subdev_has_op(sd, o, f) \
        ((sd)->ops->o && (sd)->ops->o->f)
 
+void v4l2_subdev_notify_event(struct v4l2_subdev *sd,
+                             const struct v4l2_event *ev);
+
 #endif
index 7e0c34569a96288ae1bb366c2cb62c2f5a7abed0..708dd0afd62ac3d8f46ca584637327d9148a653b 100644 (file)
@@ -321,6 +321,7 @@ struct v4l2_fh;
  * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
  *             buffers. Only set for capture queues if qbuf has not yet been
  *             called since poll() needs to return POLLERR in that situation.
+ * @error:     a fatal error occurred on the queue
  * @fileio:    file io emulator internal data, used only if emulator is active
  */
 struct vb2_queue {
@@ -376,6 +377,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
 int __must_check vb2_queue_init(struct vb2_queue *q);
 
 void vb2_queue_release(struct vb2_queue *q);
+void vb2_queue_error(struct vb2_queue *q);
 
 int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
 int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
@@ -395,7 +397,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
 size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
                loff_t *ppos, int nonblock);
-size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count,
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
                loff_t *ppos, int nonblock);
 
 /**
@@ -513,7 +515,7 @@ int vb2_ioctl_expbuf(struct file *file, void *priv,
 
 int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
 int vb2_fop_release(struct file *file);
-ssize_t vb2_fop_write(struct file *file, char __user *buf,
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
                size_t count, loff_t *ppos);
 ssize_t vb2_fop_read(struct file *file, char __user *buf,
                size_t count, loff_t *ppos);
index 15273987093e41e7823f98a953f088332db066aa..79d402d980a2f586c4c7472db92cae289967246d 100644 (file)
@@ -77,7 +77,7 @@ struct v4l2_edid {
        __u32 start_block;
        __u32 blocks;
        __u32 reserved[5];
-       __u8  *edid;
+       __u8 __user *edid;
 };
 
 #endif /* __V4L2_COMMON__ */
index 4e0c58d25ff0df57f0ddf6ec276e06b9ddb6f356..f19fe3dd5023edb2122284a6ec2165377e09fde9 100644 (file)
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(720, 480, 1, 0, \
                13500000, 19, 62, 57, 4, 3, 15, 4, 3, 16, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_HALF_LINE) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_720X480P59_94 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
                27000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 /* Note: these are the nominal timings, for HDMI links this format is typically
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(720, 576, 1, 0, \
                13500000, 12, 63, 69, 2, 3, 19, 2, 3, 20, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_HALF_LINE) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_720X576P50 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
                27000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1280X720P24 { \
@@ -88,7 +90,7 @@
        V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 2420, 40, 220, 5, 5, 20, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1280X720P30 { \
@@ -96,7 +98,8 @@
        V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1280X720P50 { \
        V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1280X720P60 { \
        V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P24 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P25 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P30 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080I50 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 528, 44, 148, 2, 5, 15, 2, 5, 16, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_HALF_LINE) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P50 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                148500000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080I60 { \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 88, 44, 148, 2, 5, 15, 2, 5, 16, \
                V4L2_DV_BT_STD_CEA861, \
-               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE) \
+               V4L2_DV_FL_CAN_REDUCE_FPS | \
+               V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P60 { \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                148500000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
                V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CEA861, \
-               V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P24 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               297000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P25 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               297000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P30 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               297000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P50 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               594000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P60 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               594000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P24 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               297000000, 1020, 88, 296, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P25 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               297000000, 968, 88, 128, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P30 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               297000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P50 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               594000000, 968, 88, 128, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P60 { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               594000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 
                V4L2_DV_BT_STD_DMT, 0) \
 }
 
+/* 4K resolutions */
+#define V4L2_DV_BT_DMT_4096X2160P60_RB { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               556744000, 8, 32, 40, 48, 8, 6, 0, 0, 0, \
+               V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+               V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_4096X2160P59_94_RB { \
+       .type = V4L2_DV_BT_656_1120, \
+       V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+               556188000, 8, 32, 40, 48, 8, 6, 0, 0, 0, \
+               V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+               V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
 #endif
index 3fe39ea2727f9c4148ed9a896eec3c5ff65b2070..df4bb6a5617c79ecb6c9f9518c52dbce8dd3fb68 100644 (file)
@@ -120,6 +120,9 @@ enum v4l2_mbus_pixelcode {
  * @code:      data format code (from enum v4l2_mbus_pixelcode)
  * @field:     used interlacing type (from enum v4l2_field)
  * @colorspace:        colorspace of the data (from enum v4l2_colorspace)
+ * @ycbcr_enc: YCbCr encoding of the data (from enum v4l2_ycbcr_encoding)
+ * @quantization: quantization of the data (from enum v4l2_quantization)
+ * @xfer_func:  transfer function of the data (from enum v4l2_xfer_func)
  */
 struct v4l2_mbus_framefmt {
        __u32                   width;
@@ -127,7 +130,10 @@ struct v4l2_mbus_framefmt {
        __u32                   code;
        __u32                   field;
        __u32                   colorspace;
-       __u32                   reserved[7];
+       __u16                   ycbcr_enc;
+       __u16                   quantization;
+       __u16                   xfer_func;
+       __u16                   reserved[11];
 };
 
 #endif
index 8cb7cbcd02789dcaba7fb16c3a267bc8b5b76c05..f588ebe0aecb341dcbee43599efd7fccbbf24540 100644 (file)
@@ -149,13 +149,8 @@ struct v4l2_subdev_selection {
        __u32 reserved[8];
 };
 
-struct v4l2_subdev_edid {
-       __u32 pad;
-       __u32 start_block;
-       __u32 blocks;
-       __u32 reserved[5];
-       __u8 __user *edid;
-};
+/* Backwards compatibility define --- to be removed */
+#define v4l2_subdev_edid v4l2_edid
 
 #define VIDIOC_SUBDEV_G_FMT    _IOWR('V',  4, struct v4l2_subdev_format)
 #define VIDIOC_SUBDEV_S_FMT    _IOWR('V',  5, struct v4l2_subdev_format)
@@ -175,7 +170,8 @@ struct v4l2_subdev_edid {
        _IOWR('V', 61, struct v4l2_subdev_selection)
 #define VIDIOC_SUBDEV_S_SELECTION \
        _IOWR('V', 62, struct v4l2_subdev_selection)
-#define VIDIOC_SUBDEV_G_EDID   _IOWR('V', 40, struct v4l2_subdev_edid)
-#define VIDIOC_SUBDEV_S_EDID   _IOWR('V', 41, struct v4l2_subdev_edid)
+/* These two G/S_EDID ioctls are identical to the ioctls in videodev2.h */
+#define VIDIOC_SUBDEV_G_EDID   _IOWR('V', 40, struct v4l2_edid)
+#define VIDIOC_SUBDEV_S_EDID   _IOWR('V', 41, struct v4l2_edid)
 
 #endif
index 51f3740432f4414f6cc4b5c4c736ab7ccdb195a3..5e799613e5f46c3752ce5b115b87ae01135e8484 100644 (file)
@@ -79,6 +79,7 @@
 /*  Four-character-code (FOURCC) */
 #define v4l2_fourcc(a, b, c, d)\
        ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))
+#define v4l2_fourcc_be(a, b, c, d)     (v4l2_fourcc(a, b, c, d) | (1 << 31))
 
 /*
  *     E N U M S
@@ -124,6 +125,10 @@ enum v4l2_field {
         (field) == V4L2_FIELD_INTERLACED_BT ||\
         (field) == V4L2_FIELD_SEQ_TB ||\
         (field) == V4L2_FIELD_SEQ_BT)
+#define V4L2_FIELD_HAS_T_OR_B(field)   \
+       ((field) == V4L2_FIELD_BOTTOM ||\
+        (field) == V4L2_FIELD_TOP ||\
+        (field) == V4L2_FIELD_ALTERNATE)
 
 enum v4l2_buf_type {
        V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1,
@@ -170,32 +175,181 @@ enum v4l2_memory {
 
 /* see also http://vektor.theorem.ca/graphics/ycbcr/ */
 enum v4l2_colorspace {
-       /* ITU-R 601 -- broadcast NTSC/PAL */
+       /*
+        * Default colorspace, i.e. let the driver figure it out.
+        * Can only be used with video capture.
+        */
+       V4L2_COLORSPACE_DEFAULT       = 0,
+
+       /* SMPTE 170M: used for broadcast NTSC/PAL SDTV */
        V4L2_COLORSPACE_SMPTE170M     = 1,
 
-       /* 1125-Line (US) HDTV */
+       /* Obsolete pre-1998 SMPTE 240M HDTV standard, superseded by Rec 709 */
        V4L2_COLORSPACE_SMPTE240M     = 2,
 
-       /* HD and modern captures. */
+       /* Rec.709: used for HDTV */
        V4L2_COLORSPACE_REC709        = 3,
 
-       /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */
+       /*
+        * Deprecated, do not use. No driver will ever return this. This was
+        * based on a misunderstanding of the bt878 datasheet.
+        */
        V4L2_COLORSPACE_BT878         = 4,
 
-       /* These should be useful.  Assume 601 extents. */
+       /*
+        * NTSC 1953 colorspace. This only makes sense when dealing with
+        * really, really old NTSC recordings. Superseded by SMPTE 170M.
+        */
        V4L2_COLORSPACE_470_SYSTEM_M  = 5,
+
+       /*
+        * EBU Tech 3213 PAL/SECAM colorspace. This only makes sense when
+        * dealing with really old PAL/SECAM recordings. Superseded by
+        * SMPTE 170M.
+        */
        V4L2_COLORSPACE_470_SYSTEM_BG = 6,
 
-       /* I know there will be cameras that send this.  So, this is
-        * unspecified chromaticities and full 0-255 on each of the
-        * Y'CbCr components
+       /*
+        * Effectively shorthand for V4L2_COLORSPACE_SRGB, V4L2_YCBCR_ENC_601
+        * and V4L2_QUANTIZATION_FULL_RANGE. To be used for (Motion-)JPEG.
         */
        V4L2_COLORSPACE_JPEG          = 7,
 
-       /* For RGB colourspaces, this is probably a good start. */
+       /* For RGB colorspaces such as produces by most webcams. */
        V4L2_COLORSPACE_SRGB          = 8,
+
+       /* AdobeRGB colorspace */
+       V4L2_COLORSPACE_ADOBERGB      = 9,
+
+       /* BT.2020 colorspace, used for UHDTV. */
+       V4L2_COLORSPACE_BT2020        = 10,
+
+       /* Raw colorspace: for RAW unprocessed images */
+       V4L2_COLORSPACE_RAW           = 11,
+};
+
+/*
+ * Determine how COLORSPACE_DEFAULT should map to a proper colorspace.
+ * This depends on whether this is a SDTV image (use SMPTE 170M), an
+ * HDTV image (use Rec. 709), or something else (use sRGB).
+ */
+#define V4L2_MAP_COLORSPACE_DEFAULT(is_sdtv, is_hdtv) \
+       ((is_sdtv) ? V4L2_COLORSPACE_SMPTE170M : \
+        ((is_hdtv) ? V4L2_COLORSPACE_REC709 : V4L2_COLORSPACE_SRGB))
+
+enum v4l2_xfer_func {
+       /*
+        * Mapping of V4L2_XFER_FUNC_DEFAULT to actual transfer functions
+        * for the various colorspaces:
+        *
+        * V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M,
+        * V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_REC709 and
+        * V4L2_COLORSPACE_BT2020: V4L2_XFER_FUNC_709
+        *
+        * V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_JPEG: V4L2_XFER_FUNC_SRGB
+        *
+        * V4L2_COLORSPACE_ADOBERGB: V4L2_XFER_FUNC_ADOBERGB
+        *
+        * V4L2_COLORSPACE_SMPTE240M: V4L2_XFER_FUNC_SMPTE240M
+        *
+        * V4L2_COLORSPACE_RAW: V4L2_XFER_FUNC_NONE
+        */
+       V4L2_XFER_FUNC_DEFAULT     = 0,
+       V4L2_XFER_FUNC_709         = 1,
+       V4L2_XFER_FUNC_SRGB        = 2,
+       V4L2_XFER_FUNC_ADOBERGB    = 3,
+       V4L2_XFER_FUNC_SMPTE240M   = 4,
+       V4L2_XFER_FUNC_NONE        = 5,
+};
+
+/*
+ * Determine how XFER_FUNC_DEFAULT should map to a proper transfer function.
+ * This depends on the colorspace.
+ */
+#define V4L2_MAP_XFER_FUNC_DEFAULT(colsp) \
+       ((colsp) == V4L2_COLORSPACE_ADOBERGB ? V4L2_XFER_FUNC_ADOBERGB : \
+        ((colsp) == V4L2_COLORSPACE_SMPTE240M ? V4L2_XFER_FUNC_SMPTE240M : \
+         ((colsp) == V4L2_COLORSPACE_RAW ? V4L2_XFER_FUNC_NONE : \
+          ((colsp) == V4L2_COLORSPACE_SRGB || (colsp) == V4L2_COLORSPACE_JPEG ? \
+           V4L2_XFER_FUNC_SRGB : V4L2_XFER_FUNC_709))))
+
+enum v4l2_ycbcr_encoding {
+       /*
+        * Mapping of V4L2_YCBCR_ENC_DEFAULT to actual encodings for the
+        * various colorspaces:
+        *
+        * V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M,
+        * V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_ADOBERGB and
+        * V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601
+        *
+        * V4L2_COLORSPACE_REC709: V4L2_YCBCR_ENC_709
+        *
+        * V4L2_COLORSPACE_SRGB: V4L2_YCBCR_ENC_SYCC
+        *
+        * V4L2_COLORSPACE_BT2020: V4L2_YCBCR_ENC_BT2020
+        *
+        * V4L2_COLORSPACE_SMPTE240M: V4L2_YCBCR_ENC_SMPTE240M
+        */
+       V4L2_YCBCR_ENC_DEFAULT        = 0,
+
+       /* ITU-R 601 -- SDTV */
+       V4L2_YCBCR_ENC_601            = 1,
+
+       /* Rec. 709 -- HDTV */
+       V4L2_YCBCR_ENC_709            = 2,
+
+       /* ITU-R 601/EN 61966-2-4 Extended Gamut -- SDTV */
+       V4L2_YCBCR_ENC_XV601          = 3,
+
+       /* Rec. 709/EN 61966-2-4 Extended Gamut -- HDTV */
+       V4L2_YCBCR_ENC_XV709          = 4,
+
+       /* sYCC (Y'CbCr encoding of sRGB) */
+       V4L2_YCBCR_ENC_SYCC           = 5,
+
+       /* BT.2020 Non-constant Luminance Y'CbCr */
+       V4L2_YCBCR_ENC_BT2020         = 6,
+
+       /* BT.2020 Constant Luminance Y'CbcCrc */
+       V4L2_YCBCR_ENC_BT2020_CONST_LUM = 7,
+
+       /* SMPTE 240M -- Obsolete HDTV */
+       V4L2_YCBCR_ENC_SMPTE240M      = 8,
 };
 
+/*
+ * Determine how YCBCR_ENC_DEFAULT should map to a proper Y'CbCr encoding.
+ * This depends on the colorspace.
+ */
+#define V4L2_MAP_YCBCR_ENC_DEFAULT(colsp) \
+       ((colsp) == V4L2_COLORSPACE_REC709 ? V4L2_YCBCR_ENC_709 : \
+        ((colsp) == V4L2_COLORSPACE_BT2020 ? V4L2_YCBCR_ENC_BT2020 : \
+         ((colsp) == V4L2_COLORSPACE_SMPTE240M ? V4L2_YCBCR_ENC_SMPTE240M : \
+          V4L2_YCBCR_ENC_601)))
+
+enum v4l2_quantization {
+       /*
+        * The default for R'G'B' quantization is always full range, except
+        * for the BT2020 colorspace. For Y'CbCr the quantization is always
+        * limited range, except for COLORSPACE_JPEG, SYCC, XV601 or XV709:
+        * those are full range.
+        */
+       V4L2_QUANTIZATION_DEFAULT     = 0,
+       V4L2_QUANTIZATION_FULL_RANGE  = 1,
+       V4L2_QUANTIZATION_LIM_RANGE   = 2,
+};
+
+/*
+ * Determine how QUANTIZATION_DEFAULT should map to a proper quantization.
+ * This depends on whether the image is RGB or not, the colorspace and the
+ * Y'CbCr encoding.
+ */
+#define V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, colsp, ycbcr_enc) \
+       (((is_rgb) && (colsp) == V4L2_COLORSPACE_BT2020) ? V4L2_QUANTIZATION_LIM_RANGE : \
+        (((is_rgb) || (ycbcr_enc) == V4L2_YCBCR_ENC_XV601 || \
+         (ycbcr_enc) == V4L2_YCBCR_ENC_XV709 || (colsp) == V4L2_COLORSPACE_JPEG) ? \
+        V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE))
+
 enum v4l2_priority {
        V4L2_PRIORITY_UNSET       = 0,  /* not initialized */
        V4L2_PRIORITY_BACKGROUND  = 1,
@@ -263,6 +417,7 @@ struct v4l2_capability {
 #define V4L2_CAP_AUDIO                 0x00020000  /* has audio support */
 #define V4L2_CAP_RADIO                 0x00040000  /* is a radio device */
 #define V4L2_CAP_MODULATOR             0x00080000  /* has a modulator */
+#define V4L2_CAP_EXT_PIX_FORMAT                0x00200000  /* Supports the extended pixel format */
 
 #define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
 #define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
@@ -270,6 +425,9 @@ struct v4l2_capability {
 
 #define V4L2_CAP_DEVICE_CAPS            0x80000000  /* sets device capabilities field */
 
+/* priv field value to indicates that subsequent fields are valid. */
+#define V4L2_PIX_FMT_PRIV_MAGIC                0xfeedcafe
+
 /*
  *     V I D E O   I M A G E   F O R M A T
  */
@@ -282,6 +440,10 @@ struct v4l2_pix_format {
        __u32                   sizeimage;
        __u32                   colorspace;     /* enum v4l2_colorspace */
        __u32                   priv;           /* private data, depends on pixelformat */
+       __u32                   flags;          /* format flags (V4L2_PIX_FMT_FLAG_*) */
+       __u32                   ycbcr_enc;      /* enum v4l2_ycbcr_encoding */
+       __u32                   quantization;   /* enum v4l2_quantization */
+       __u32                   xfer_func;      /* enum v4l2_xfer_func */
 };
 
 /*      Pixel format         FOURCC                          depth  Description  */
@@ -289,15 +451,25 @@ struct v4l2_pix_format {
 /* RGB formats */
 #define V4L2_PIX_FMT_RGB332  v4l2_fourcc('R', 'G', 'B', '1') /*  8  RGB-3-3-2     */
 #define V4L2_PIX_FMT_RGB444  v4l2_fourcc('R', '4', '4', '4') /* 16  xxxxrrrr ggggbbbb */
+#define V4L2_PIX_FMT_ARGB444 v4l2_fourcc('A', 'R', '1', '2') /* 16  aaaarrrr ggggbbbb */
+#define V4L2_PIX_FMT_XRGB444 v4l2_fourcc('X', 'R', '1', '2') /* 16  xxxxrrrr ggggbbbb */
 #define V4L2_PIX_FMT_RGB555  v4l2_fourcc('R', 'G', 'B', 'O') /* 16  RGB-5-5-5     */
+#define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16  ARGB-1-5-5-5  */
+#define V4L2_PIX_FMT_XRGB555 v4l2_fourcc('X', 'R', '1', '5') /* 16  XRGB-1-5-5-5  */
 #define V4L2_PIX_FMT_RGB565  v4l2_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5     */
 #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
+#define V4L2_PIX_FMT_ARGB555X v4l2_fourcc_be('A', 'R', '1', '5') /* 16  ARGB-5-5-5 BE */
+#define V4L2_PIX_FMT_XRGB555X v4l2_fourcc_be('X', 'R', '1', '5') /* 16  XRGB-5-5-5 BE */
 #define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
 #define V4L2_PIX_FMT_BGR666  v4l2_fourcc('B', 'G', 'R', 'H') /* 18  BGR-6-6-6    */
 #define V4L2_PIX_FMT_BGR24   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
 #define V4L2_PIX_FMT_RGB24   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
 #define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
+#define V4L2_PIX_FMT_ABGR32  v4l2_fourcc('A', 'R', '2', '4') /* 32  BGRA-8-8-8-8  */
+#define V4L2_PIX_FMT_XBGR32  v4l2_fourcc('X', 'R', '2', '4') /* 32  BGRX-8-8-8-8  */
 #define V4L2_PIX_FMT_RGB32   v4l2_fourcc('R', 'G', 'B', '4') /* 32  RGB-8-8-8-8   */
+#define V4L2_PIX_FMT_ARGB32  v4l2_fourcc('B', 'A', '2', '4') /* 32  ARGB-8-8-8-8  */
+#define V4L2_PIX_FMT_XRGB32  v4l2_fourcc('B', 'X', '2', '4') /* 32  XRGB-8-8-8-8  */
 
 /* Grey formats */
 #define V4L2_PIX_FMT_GREY    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
@@ -306,6 +478,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_Y10     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
 #define V4L2_PIX_FMT_Y12     v4l2_fourcc('Y', '1', '2', ' ') /* 12  Greyscale     */
 #define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
+#define V4L2_PIX_FMT_Y16_BE  v4l2_fourcc_be('Y', '1', '6', ' ') /* 16  Greyscale BE  */
 
 /* Grey bit-packed formats */
 #define V4L2_PIX_FMT_Y10BPACK    v4l2_fourcc('Y', '1', '0', 'B') /* 10  Greyscale bit-packed */
@@ -348,6 +521,8 @@ struct v4l2_pix_format {
 /* two non contiguous planes - one Y, one Cr + Cb interleaved  */
 #define V4L2_PIX_FMT_NV12M   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
 #define V4L2_PIX_FMT_NV21M   v4l2_fourcc('N', 'M', '2', '1') /* 21  Y/CrCb 4:2:0  */
+#define V4L2_PIX_FMT_NV16M   v4l2_fourcc('N', 'M', '1', '6') /* 16  Y/CbCr 4:2:2  */
+#define V4L2_PIX_FMT_NV61M   v4l2_fourcc('N', 'M', '6', '1') /* 16  Y/CrCb 4:2:2  */
 #define V4L2_PIX_FMT_NV12MT  v4l2_fourcc('T', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 64x32 macroblocks */
 #define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 16x16 macroblocks */
 
@@ -364,10 +539,11 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10  GBGB.. RGRG.. */
 #define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10  GRGR.. BGBG.. */
 #define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10  RGRG.. GBGB.. */
-#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12  BGBG.. GRGR.. */
-#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12  GBGB.. RGRG.. */
-#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12  GRGR.. BGBG.. */
-#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12  RGRG.. GBGB.. */
+       /* 10bit raw bayer packed, 5 bytes for every 4 pixels */
+#define V4L2_PIX_FMT_SBGGR10P v4l2_fourcc('p', 'B', 'A', 'A')
+#define V4L2_PIX_FMT_SGBRG10P v4l2_fourcc('p', 'G', 'A', 'A')
+#define V4L2_PIX_FMT_SGRBG10P v4l2_fourcc('p', 'g', 'A', 'A')
+#define V4L2_PIX_FMT_SRGGB10P v4l2_fourcc('p', 'R', 'A', 'A')
        /* 10bit raw bayer a-law compressed to 8 bits */
 #define V4L2_PIX_FMT_SBGGR10ALAW8 v4l2_fourcc('a', 'B', 'A', '8')
 #define V4L2_PIX_FMT_SGBRG10ALAW8 v4l2_fourcc('a', 'G', 'A', '8')
@@ -378,10 +554,10 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SGBRG10DPCM8 v4l2_fourcc('b', 'G', 'A', '8')
 #define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0')
 #define V4L2_PIX_FMT_SRGGB10DPCM8 v4l2_fourcc('b', 'R', 'A', '8')
-       /*
-        * 10bit raw bayer, expanded to 16 bits
-        * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb...
-        */
+#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12  GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12  GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12  RGRG.. GBGB.. */
 #define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16  BGBG.. GRGR.. */
 
 /* compressed formats */
@@ -395,7 +571,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_H263     v4l2_fourcc('H', '2', '6', '3') /* H263          */
 #define V4L2_PIX_FMT_MPEG1    v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES     */
 #define V4L2_PIX_FMT_MPEG2    v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES     */
-#define V4L2_PIX_FMT_MPEG4    v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 ES     */
+#define V4L2_PIX_FMT_MPEG4    v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 part 2 ES */
 #define V4L2_PIX_FMT_XVID     v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid           */
 #define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */
 #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
@@ -429,6 +605,16 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
 #define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
 
+/* SDR formats - used only for Software Defined Radio devices */
+#define V4L2_SDR_FMT_CU8          v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
+#define V4L2_SDR_FMT_CU16LE       v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */
+#define V4L2_SDR_FMT_CS8          v4l2_fourcc('C', 'S', '0', '8') /* complex s8 */
+#define V4L2_SDR_FMT_CS14LE       v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */
+#define V4L2_SDR_FMT_RU12LE       v4l2_fourcc('R', 'U', '1', '2') /* real u12le */
+
+/* Flags */
+#define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA 0x00000001
+
 /*
  *     F O R M A T   E N U M E R A T I O N
  */
@@ -729,7 +915,16 @@ struct v4l2_framebuffer {
 /* FIXME: in theory we should pass something like PCI device + memory
  * region + offset instead of some physical address */
        void                    *base;
-       struct v4l2_pix_format  fmt;
+       struct {
+               __u32           width;
+               __u32           height;
+               __u32           pixelformat;
+               __u32           field;          /* enum v4l2_field */
+               __u32           bytesperline;   /* for padding, zero if unused */
+               __u32           sizeimage;
+               __u32           colorspace;     /* enum v4l2_colorspace */
+               __u32           priv;           /* reserved field, set to 0 */
+       } fmt;
 };
 /*  Flags for the 'capability' field. Read only */
 #define V4L2_FBUF_CAP_EXTERNOVERLAY    0x0001
@@ -1061,7 +1256,23 @@ struct v4l2_bt_timings {
    exactly the same number of half-lines. Whether half-lines can be detected
    or used depends on the hardware. */
 #define V4L2_DV_FL_HALF_LINE                   (1 << 3)
-
+/* If set, then this is a Consumer Electronics (CE) video format. Such formats
+ * differ from other formats (commonly called IT formats) in that if RGB
+ * encoding is used then by default the RGB values use limited range (i.e.
+ * use the range 16-235) as opposed to 0-255. All formats defined in CEA-861
+ * except for the 640x480 format are CE formats. */
+#define V4L2_DV_FL_IS_CE_VIDEO                 (1 << 4)
+
+/* A few useful defines to calculate the total blanking and frame sizes */
+#define V4L2_DV_BT_BLANKING_WIDTH(bt) \
+       ((bt)->hfrontporch + (bt)->hsync + (bt)->hbackporch)
+#define V4L2_DV_BT_FRAME_WIDTH(bt) \
+       ((bt)->width + V4L2_DV_BT_BLANKING_WIDTH(bt))
+#define V4L2_DV_BT_BLANKING_HEIGHT(bt) \
+       ((bt)->vfrontporch + (bt)->vsync + (bt)->vbackporch + \
+        (bt)->il_vfrontporch + (bt)->il_vsync + (bt)->il_vbackporch)
+#define V4L2_DV_BT_FRAME_HEIGHT(bt) \
+       ((bt)->height + V4L2_DV_BT_BLANKING_HEIGHT(bt))
 
 /** struct v4l2_dv_timings - DV timings
  * @type:      the type of the timings
@@ -1081,12 +1292,15 @@ struct v4l2_dv_timings {
 
 /** struct v4l2_enum_dv_timings - DV timings enumeration
  * @index:     enumeration index
+ * @pad:       the pad number for which to enumerate timings (used with
+ *             v4l-subdev nodes only)
  * @reserved:  must be zeroed
  * @timings:   the timings for the given index
  */
 struct v4l2_enum_dv_timings {
        __u32 index;
-       __u32 reserved[3];
+       __u32 pad;
+       __u32 reserved[2];
        struct v4l2_dv_timings timings;
 };
 
@@ -1124,11 +1338,14 @@ struct v4l2_bt_timings_cap {
 
 /** struct v4l2_dv_timings_cap - DV timings capabilities
  * @type:      the type of the timings (same as in struct v4l2_dv_timings)
+ * @pad:       the pad number for which to query capabilities (used with
+ *             v4l-subdev nodes only)
  * @bt:                the BT656/1120 timings capabilities
  */
 struct v4l2_dv_timings_cap {
        __u32 type;
-       __u32 reserved[3];
+       __u32 pad;
+       __u32 reserved[2];
        union {
                struct v4l2_bt_timings_cap bt;
                __u32 raw_data[32];
@@ -1550,6 +1767,12 @@ struct v4l2_vbi_format {
 #define V4L2_VBI_UNSYNC                (1 << 0)
 #define V4L2_VBI_INTERLACED    (1 << 1)
 
+/* ITU-R start lines for each field */
+#define V4L2_VBI_ITU_525_F1_START (1)
+#define V4L2_VBI_ITU_525_F2_START (264)
+#define V4L2_VBI_ITU_625_F1_START (1)
+#define V4L2_VBI_ITU_625_F2_START (314)
+
 /* Sliced VBI
  *
  *    This implements is a proposal V4L2 API to allow SLICED VBI
@@ -1673,6 +1896,9 @@ struct v4l2_plane_pix_format {
  * @colorspace:                enum v4l2_colorspace; supplemental to pixelformat
  * @plane_fmt:         per-plane information
  * @num_planes:                number of planes for this format
+ * @ycbcr_enc:         enum v4l2_ycbcr_encoding, Y'CbCr encoding
+ * @quantization:      enum v4l2_quantization, colorspace quantization
+ * @xfer_func:         enum v4l2_xfer_func, colorspace transfer function
  */
 struct v4l2_pix_format_mplane {
        __u32                           width;
@@ -1683,7 +1909,11 @@ struct v4l2_pix_format_mplane {
 
        struct v4l2_plane_pix_format    plane_fmt[VIDEO_MAX_PLANES];
        __u8                            num_planes;
-       __u8                            reserved[11];
+       __u8                            flags;
+       __u8                            ycbcr_enc;
+       __u8                            quantization;
+       __u8                            xfer_func;
+       __u8                            reserved[7];
 } __attribute__ ((packed));
 
 /**
@@ -1728,6 +1958,7 @@ struct v4l2_streamparm {
 #define V4L2_EVENT_EOS                         2
 #define V4L2_EVENT_CTRL                                3
 #define V4L2_EVENT_FRAME_SYNC                  4
+#define V4L2_EVENT_SOURCE_CHANGE               5
 #define V4L2_EVENT_PRIVATE_START               0x08000000
 
 /* Payload for V4L2_EVENT_VSYNC */
@@ -1759,12 +1990,19 @@ struct v4l2_event_frame_sync {
        __u32 frame_sequence;
 };
 
+#define V4L2_EVENT_SRC_CH_RESOLUTION           (1 << 0)
+
+struct v4l2_event_src_change {
+       __u32 changes;
+};
+
 struct v4l2_event {
        __u32                           type;
        union {
                struct v4l2_event_vsync         vsync;
                struct v4l2_event_ctrl          ctrl;
                struct v4l2_event_frame_sync    frame_sync;
+               struct v4l2_event_src_change    src_change;
                __u8                            data[64];
        } u;
        __u32                           pending;
@@ -1885,6 +2123,8 @@ struct v4l2_create_buffers {
 #define VIDIOC_QUERYMENU       _IOWR('V', 37, struct v4l2_querymenu)
 #define VIDIOC_G_INPUT          _IOR('V', 38, int)
 #define VIDIOC_S_INPUT         _IOWR('V', 39, int)
+#define VIDIOC_G_EDID          _IOWR('V', 40, struct v4l2_edid)
+#define VIDIOC_S_EDID          _IOWR('V', 41, struct v4l2_edid)
 #define VIDIOC_G_OUTPUT                 _IOR('V', 46, int)
 #define VIDIOC_S_OUTPUT                _IOWR('V', 47, int)
 #define VIDIOC_ENUMOUTPUT      _IOWR('V', 48, struct v4l2_output)