media: v4l2-compat-ioctl32.c: add capabilities field to, v4l2_input32
[pandora-kernel.git] / drivers / media / video / v4l2-ioctl.c
index 002ce13..639abee 100644 (file)
        memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
        0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
 
+#define have_fmt_ops(foo) (                                            \
+       ops->vidioc_##foo##_fmt_vid_cap ||                              \
+       ops->vidioc_##foo##_fmt_vid_out ||                              \
+       ops->vidioc_##foo##_fmt_vid_cap_mplane ||                       \
+       ops->vidioc_##foo##_fmt_vid_out_mplane ||                       \
+       ops->vidioc_##foo##_fmt_vid_overlay ||                          \
+       ops->vidioc_##foo##_fmt_vbi_cap ||                              \
+       ops->vidioc_##foo##_fmt_vid_out_overlay ||                      \
+       ops->vidioc_##foo##_fmt_vbi_out ||                              \
+       ops->vidioc_##foo##_fmt_sliced_vbi_cap ||                       \
+       ops->vidioc_##foo##_fmt_sliced_vbi_out ||                       \
+       ops->vidioc_##foo##_fmt_type_private)
+
 struct std_descr {
        v4l2_std_id std;
        const char *descr;
@@ -260,6 +273,8 @@ static const char *v4l2_ioctls[] = {
        [_IOC_NR(VIDIOC_DQEVENT)]          = "VIDIOC_DQEVENT",
        [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)]  = "VIDIOC_SUBSCRIBE_EVENT",
        [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
+       [_IOC_NR(VIDIOC_CREATE_BUFS)]      = "VIDIOC_CREATE_BUFS",
+       [_IOC_NR(VIDIOC_PREPARE_BUF)]      = "VIDIOC_PREPARE_BUF",
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -477,63 +492,6 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
        return -EINVAL;
 }
 
-/**
- * fmt_sp_to_mp() - Convert a single-plane format to its multi-planar 1-plane
- * equivalent
- */
-static int fmt_sp_to_mp(const struct v4l2_format *f_sp,
-                       struct v4l2_format *f_mp)
-{
-       struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
-       const struct v4l2_pix_format *pix = &f_sp->fmt.pix;
-
-       if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       else
-               return -EINVAL;
-
-       pix_mp->width = pix->width;
-       pix_mp->height = pix->height;
-       pix_mp->pixelformat = pix->pixelformat;
-       pix_mp->field = pix->field;
-       pix_mp->colorspace = pix->colorspace;
-       pix_mp->num_planes = 1;
-       pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
-       pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
-
-       return 0;
-}
-
-/**
- * fmt_mp_to_sp() - Convert a multi-planar 1-plane format to its single-planar
- * equivalent
- */
-static int fmt_mp_to_sp(const struct v4l2_format *f_mp,
-                       struct v4l2_format *f_sp)
-{
-       const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
-       struct v4l2_pix_format *pix = &f_sp->fmt.pix;
-
-       if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-       else
-               return -EINVAL;
-
-       pix->width = pix_mp->width;
-       pix->height = pix_mp->height;
-       pix->pixelformat = pix_mp->pixelformat;
-       pix->field = pix_mp->field;
-       pix->colorspace = pix_mp->colorspace;
-       pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
-       pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
-
-       return 0;
-}
-
 static long __video_do_ioctl(struct file *file,
                unsigned int cmd, void *arg)
 {
@@ -541,8 +499,8 @@ static long __video_do_ioctl(struct file *file,
        const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
        void *fh = file->private_data;
        struct v4l2_fh *vfh = NULL;
-       struct v4l2_format f_copy;
        int use_fh_prio = 0;
+       long ret_prio = 0;
        long ret = -ENOTTY;
 
        if (ops == NULL) {
@@ -562,39 +520,8 @@ static long __video_do_ioctl(struct file *file,
                use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
        }
 
-       if (use_fh_prio) {
-               switch (cmd) {
-               case VIDIOC_S_CTRL:
-               case VIDIOC_S_STD:
-               case VIDIOC_S_INPUT:
-               case VIDIOC_S_OUTPUT:
-               case VIDIOC_S_TUNER:
-               case VIDIOC_S_FREQUENCY:
-               case VIDIOC_S_FMT:
-               case VIDIOC_S_CROP:
-               case VIDIOC_S_AUDIO:
-               case VIDIOC_S_AUDOUT:
-               case VIDIOC_S_EXT_CTRLS:
-               case VIDIOC_S_FBUF:
-               case VIDIOC_S_PRIORITY:
-               case VIDIOC_S_DV_PRESET:
-               case VIDIOC_S_DV_TIMINGS:
-               case VIDIOC_S_JPEGCOMP:
-               case VIDIOC_S_MODULATOR:
-               case VIDIOC_S_PARM:
-               case VIDIOC_S_HW_FREQ_SEEK:
-               case VIDIOC_ENCODER_CMD:
-               case VIDIOC_OVERLAY:
-               case VIDIOC_REQBUFS:
-               case VIDIOC_STREAMON:
-               case VIDIOC_STREAMOFF:
-                       ret = v4l2_prio_check(vfd->prio, vfh->prio);
-                       if (ret)
-                               goto exit_prio;
-                       ret = -EINVAL;
-                       break;
-               }
-       }
+       if (use_fh_prio)
+               ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
 
        switch (cmd) {
 
@@ -638,12 +565,14 @@ static long __video_do_ioctl(struct file *file,
                enum v4l2_priority *p = arg;
 
                if (!ops->vidioc_s_priority && !use_fh_prio)
-                               break;
+                       break;
                dbgarg(cmd, "setting priority to %d\n", *p);
                if (ops->vidioc_s_priority)
                        ret = ops->vidioc_s_priority(file, fh, *p);
                else
-                       ret = v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
+                       ret = ret_prio ? ret_prio :
+                               v4l2_prio_change(&vfd->v4l2_dev->prio,
+                                                       &vfh->prio, *p);
                break;
        }
 
@@ -654,37 +583,37 @@ static long __video_do_ioctl(struct file *file,
 
                switch (f->type) {
                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       if (ops->vidioc_enum_fmt_vid_cap)
+                       if (likely(ops->vidioc_enum_fmt_vid_cap))
                                ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
                        break;
                case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-                       if (ops->vidioc_enum_fmt_vid_cap_mplane)
+                       if (likely(ops->vidioc_enum_fmt_vid_cap_mplane))
                                ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,
                                                                        fh, f);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-                       if (ops->vidioc_enum_fmt_vid_overlay)
+                       if (likely(ops->vidioc_enum_fmt_vid_overlay))
                                ret = ops->vidioc_enum_fmt_vid_overlay(file,
                                        fh, f);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-                       if (ops->vidioc_enum_fmt_vid_out)
+                       if (likely(ops->vidioc_enum_fmt_vid_out))
                                ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-                       if (ops->vidioc_enum_fmt_vid_out_mplane)
+                       if (likely(ops->vidioc_enum_fmt_vid_out_mplane))
                                ret = ops->vidioc_enum_fmt_vid_out_mplane(file,
                                                                        fh, f);
                        break;
                case V4L2_BUF_TYPE_PRIVATE:
-                       if (ops->vidioc_enum_fmt_type_private)
+                       if (likely(ops->vidioc_enum_fmt_type_private))
                                ret = ops->vidioc_enum_fmt_type_private(file,
                                                                fh, f);
                        break;
                default:
                        break;
                }
-               if (!ret)
+               if (likely (!ret))
                        dbgarg(cmd, "index=%d, type=%d, flags=%d, "
                                "pixelformat=%c%c%c%c, description='%s'\n",
                                f->index, f->type, f->flags,
@@ -693,6 +622,14 @@ static long __video_do_ioctl(struct file *file,
                                (f->pixelformat >> 16) & 0xff,
                                (f->pixelformat >> 24) & 0xff,
                                f->description);
+               else if (ret == -ENOTTY &&
+                        (ops->vidioc_enum_fmt_vid_cap ||
+                         ops->vidioc_enum_fmt_vid_out ||
+                         ops->vidioc_enum_fmt_vid_cap_mplane ||
+                         ops->vidioc_enum_fmt_vid_out_mplane ||
+                         ops->vidioc_enum_fmt_vid_overlay ||
+                         ops->vidioc_enum_fmt_type_private))
+                       ret = -EINVAL;
                break;
        }
        case VIDIOC_G_FMT:
@@ -704,119 +641,67 @@ static long __video_do_ioctl(struct file *file,
 
                switch (f->type) {
                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       if (ops->vidioc_g_fmt_vid_cap) {
+                       if (ops->vidioc_g_fmt_vid_cap)
                                ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
-                       } else if (ops->vidioc_g_fmt_vid_cap_mplane) {
-                               if (fmt_sp_to_mp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh,
-                                                                      &f_copy);
-                               if (ret)
-                                       break;
-
-                               /* Driver is currently in multi-planar format,
-                                * we can't return it in single-planar API*/
-                               if (f_copy.fmt.pix_mp.num_planes > 1) {
-                                       ret = -EBUSY;
-                                       break;
-                               }
-
-                               ret = fmt_mp_to_sp(&f_copy, f);
-                       }
                        if (!ret)
                                v4l_print_pix_fmt(vfd, &f->fmt.pix);
                        break;
                case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-                       if (ops->vidioc_g_fmt_vid_cap_mplane) {
+                       if (ops->vidioc_g_fmt_vid_cap_mplane)
                                ret = ops->vidioc_g_fmt_vid_cap_mplane(file,
                                                                        fh, f);
-                       } else if (ops->vidioc_g_fmt_vid_cap) {
-                               if (fmt_mp_to_sp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_g_fmt_vid_cap(file,
-                                                               fh, &f_copy);
-                               if (ret)
-                                       break;
-
-                               ret = fmt_sp_to_mp(&f_copy, f);
-                       }
                        if (!ret)
                                v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-                       if (ops->vidioc_g_fmt_vid_overlay)
+                       if (likely(ops->vidioc_g_fmt_vid_overlay))
                                ret = ops->vidioc_g_fmt_vid_overlay(file,
                                                                    fh, f);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-                       if (ops->vidioc_g_fmt_vid_out) {
+                       if (ops->vidioc_g_fmt_vid_out)
                                ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
-                       } else if (ops->vidioc_g_fmt_vid_out_mplane) {
-                               if (fmt_sp_to_mp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_g_fmt_vid_out_mplane(file, fh,
-                                                                       &f_copy);
-                               if (ret)
-                                       break;
-
-                               /* Driver is currently in multi-planar format,
-                                * we can't return it in single-planar API*/
-                               if (f_copy.fmt.pix_mp.num_planes > 1) {
-                                       ret = -EBUSY;
-                                       break;
-                               }
-
-                               ret = fmt_mp_to_sp(&f_copy, f);
-                       }
                        if (!ret)
                                v4l_print_pix_fmt(vfd, &f->fmt.pix);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-                       if (ops->vidioc_g_fmt_vid_out_mplane) {
+                       if (ops->vidioc_g_fmt_vid_out_mplane)
                                ret = ops->vidioc_g_fmt_vid_out_mplane(file,
                                                                        fh, f);
-                       } else if (ops->vidioc_g_fmt_vid_out) {
-                               if (fmt_mp_to_sp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_g_fmt_vid_out(file,
-                                                               fh, &f_copy);
-                               if (ret)
-                                       break;
-
-                               ret = fmt_sp_to_mp(&f_copy, f);
-                       }
                        if (!ret)
                                v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-                       if (ops->vidioc_g_fmt_vid_out_overlay)
+                       if (likely(ops->vidioc_g_fmt_vid_out_overlay))
                                ret = ops->vidioc_g_fmt_vid_out_overlay(file,
                                       fh, f);
                        break;
                case V4L2_BUF_TYPE_VBI_CAPTURE:
-                       if (ops->vidioc_g_fmt_vbi_cap)
+                       if (likely(ops->vidioc_g_fmt_vbi_cap))
                                ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
                        break;
                case V4L2_BUF_TYPE_VBI_OUTPUT:
-                       if (ops->vidioc_g_fmt_vbi_out)
+                       if (likely(ops->vidioc_g_fmt_vbi_out))
                                ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
                        break;
                case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-                       if (ops->vidioc_g_fmt_sliced_vbi_cap)
+                       if (likely(ops->vidioc_g_fmt_sliced_vbi_cap))
                                ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
                                                                        fh, f);
                        break;
                case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-                       if (ops->vidioc_g_fmt_sliced_vbi_out)
+                       if (likely(ops->vidioc_g_fmt_sliced_vbi_out))
                                ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
                                                                        fh, f);
                        break;
                case V4L2_BUF_TYPE_PRIVATE:
-                       if (ops->vidioc_g_fmt_type_private)
+                       if (likely(ops->vidioc_g_fmt_type_private))
                                ret = ops->vidioc_g_fmt_type_private(file,
                                                                fh, f);
                        break;
                }
+               if (unlikely(ret == -ENOTTY && have_fmt_ops(g)))
+                       ret = -EINVAL;
 
                break;
        }
@@ -824,6 +709,14 @@ static long __video_do_ioctl(struct file *file,
        {
                struct v4l2_format *f = (struct v4l2_format *)arg;
 
+               if (!have_fmt_ops(s))
+                       break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
+               ret = -EINVAL;
+
                /* FIXME: Should be one dump per type */
                dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
 
@@ -831,44 +724,15 @@ static long __video_do_ioctl(struct file *file,
                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                        CLEAR_AFTER_FIELD(f, fmt.pix);
                        v4l_print_pix_fmt(vfd, &f->fmt.pix);
-                       if (ops->vidioc_s_fmt_vid_cap) {
+                       if (ops->vidioc_s_fmt_vid_cap)
                                ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
-                       } else if (ops->vidioc_s_fmt_vid_cap_mplane) {
-                               if (fmt_sp_to_mp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,
-                                                                       &f_copy);
-                               if (ret)
-                                       break;
-
-                               if (f_copy.fmt.pix_mp.num_planes > 1) {
-                                       /* Drivers shouldn't adjust from 1-plane
-                                        * to more than 1-plane formats */
-                                       ret = -EBUSY;
-                                       WARN_ON(1);
-                                       break;
-                               }
-
-                               ret = fmt_mp_to_sp(&f_copy, f);
-                       }
                        break;
                case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
                        CLEAR_AFTER_FIELD(f, fmt.pix_mp);
                        v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
-                       if (ops->vidioc_s_fmt_vid_cap_mplane) {
+                       if (ops->vidioc_s_fmt_vid_cap_mplane)
                                ret = ops->vidioc_s_fmt_vid_cap_mplane(file,
                                                                        fh, f);
-                       } else if (ops->vidioc_s_fmt_vid_cap &&
-                                       f->fmt.pix_mp.num_planes == 1) {
-                               if (fmt_mp_to_sp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_s_fmt_vid_cap(file,
-                                                               fh, &f_copy);
-                               if (ret)
-                                       break;
-
-                               ret = fmt_sp_to_mp(&f_copy, f);
-                       }
                        break;
                case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                        CLEAR_AFTER_FIELD(f, fmt.win);
@@ -879,44 +743,15 @@ static long __video_do_ioctl(struct file *file,
                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
                        CLEAR_AFTER_FIELD(f, fmt.pix);
                        v4l_print_pix_fmt(vfd, &f->fmt.pix);
-                       if (ops->vidioc_s_fmt_vid_out) {
+                       if (ops->vidioc_s_fmt_vid_out)
                                ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
-                       } else if (ops->vidioc_s_fmt_vid_out_mplane) {
-                               if (fmt_sp_to_mp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,
-                                                                       &f_copy);
-                               if (ret)
-                                       break;
-
-                               if (f_copy.fmt.pix_mp.num_planes > 1) {
-                                       /* Drivers shouldn't adjust from 1-plane
-                                        * to more than 1-plane formats */
-                                       ret = -EBUSY;
-                                       WARN_ON(1);
-                                       break;
-                               }
-
-                               ret = fmt_mp_to_sp(&f_copy, f);
-                       }
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
                        CLEAR_AFTER_FIELD(f, fmt.pix_mp);
                        v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
-                       if (ops->vidioc_s_fmt_vid_out_mplane) {
+                       if (ops->vidioc_s_fmt_vid_out_mplane)
                                ret = ops->vidioc_s_fmt_vid_out_mplane(file,
                                                                        fh, f);
-                       } else if (ops->vidioc_s_fmt_vid_out &&
-                                       f->fmt.pix_mp.num_planes == 1) {
-                               if (fmt_mp_to_sp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_s_fmt_vid_out(file,
-                                                               fh, &f_copy);
-                               if (ret)
-                                       break;
-
-                               ret = fmt_mp_to_sp(&f_copy, f);
-                       }
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                        CLEAR_AFTER_FIELD(f, fmt.win);
@@ -926,29 +761,30 @@ static long __video_do_ioctl(struct file *file,
                        break;
                case V4L2_BUF_TYPE_VBI_CAPTURE:
                        CLEAR_AFTER_FIELD(f, fmt.vbi);
-                       if (ops->vidioc_s_fmt_vbi_cap)
+                       if (likely(ops->vidioc_s_fmt_vbi_cap))
                                ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
                        break;
                case V4L2_BUF_TYPE_VBI_OUTPUT:
                        CLEAR_AFTER_FIELD(f, fmt.vbi);
-                       if (ops->vidioc_s_fmt_vbi_out)
+                       if (likely(ops->vidioc_s_fmt_vbi_out))
                                ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
                        break;
                case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
                        CLEAR_AFTER_FIELD(f, fmt.sliced);
-                       if (ops->vidioc_s_fmt_sliced_vbi_cap)
+                       if (likely(ops->vidioc_s_fmt_sliced_vbi_cap))
                                ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
                                                                        fh, f);
                        break;
                case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
                        CLEAR_AFTER_FIELD(f, fmt.sliced);
-                       if (ops->vidioc_s_fmt_sliced_vbi_out)
+                       if (likely(ops->vidioc_s_fmt_sliced_vbi_out))
                                ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
                                                                        fh, f);
+
                        break;
                case V4L2_BUF_TYPE_PRIVATE:
                        /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
-                       if (ops->vidioc_s_fmt_type_private)
+                       if (likely(ops->vidioc_s_fmt_type_private))
                                ret = ops->vidioc_s_fmt_type_private(file,
                                                                fh, f);
                        break;
@@ -965,132 +801,77 @@ static long __video_do_ioctl(struct file *file,
                switch (f->type) {
                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                        CLEAR_AFTER_FIELD(f, fmt.pix);
-                       if (ops->vidioc_try_fmt_vid_cap) {
+                       if (ops->vidioc_try_fmt_vid_cap)
                                ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
-                       } else if (ops->vidioc_try_fmt_vid_cap_mplane) {
-                               if (fmt_sp_to_mp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
-                                                               fh, &f_copy);
-                               if (ret)
-                                       break;
-
-                               if (f_copy.fmt.pix_mp.num_planes > 1) {
-                                       /* Drivers shouldn't adjust from 1-plane
-                                        * to more than 1-plane formats */
-                                       ret = -EBUSY;
-                                       WARN_ON(1);
-                                       break;
-                               }
-                               ret = fmt_mp_to_sp(&f_copy, f);
-                       }
                        if (!ret)
                                v4l_print_pix_fmt(vfd, &f->fmt.pix);
                        break;
                case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
                        CLEAR_AFTER_FIELD(f, fmt.pix_mp);
-                       if (ops->vidioc_try_fmt_vid_cap_mplane) {
+                       if (ops->vidioc_try_fmt_vid_cap_mplane)
                                ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
                                                                         fh, f);
-                       } else if (ops->vidioc_try_fmt_vid_cap &&
-                                       f->fmt.pix_mp.num_planes == 1) {
-                               if (fmt_mp_to_sp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_try_fmt_vid_cap(file,
-                                                                 fh, &f_copy);
-                               if (ret)
-                                       break;
-
-                               ret = fmt_sp_to_mp(&f_copy, f);
-                       }
                        if (!ret)
                                v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                        CLEAR_AFTER_FIELD(f, fmt.win);
-                       if (ops->vidioc_try_fmt_vid_overlay)
+                       if (likely(ops->vidioc_try_fmt_vid_overlay))
                                ret = ops->vidioc_try_fmt_vid_overlay(file,
                                        fh, f);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
                        CLEAR_AFTER_FIELD(f, fmt.pix);
-                       if (ops->vidioc_try_fmt_vid_out) {
+                       if (ops->vidioc_try_fmt_vid_out)
                                ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
-                       } else if (ops->vidioc_try_fmt_vid_out_mplane) {
-                               if (fmt_sp_to_mp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_try_fmt_vid_out_mplane(file,
-                                                               fh, &f_copy);
-                               if (ret)
-                                       break;
-
-                               if (f_copy.fmt.pix_mp.num_planes > 1) {
-                                       /* Drivers shouldn't adjust from 1-plane
-                                        * to more than 1-plane formats */
-                                       ret = -EBUSY;
-                                       WARN_ON(1);
-                                       break;
-                               }
-                               ret = fmt_mp_to_sp(&f_copy, f);
-                       }
                        if (!ret)
                                v4l_print_pix_fmt(vfd, &f->fmt.pix);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
                        CLEAR_AFTER_FIELD(f, fmt.pix_mp);
-                       if (ops->vidioc_try_fmt_vid_out_mplane) {
+                       if (ops->vidioc_try_fmt_vid_out_mplane)
                                ret = ops->vidioc_try_fmt_vid_out_mplane(file,
                                                                         fh, f);
-                       } else if (ops->vidioc_try_fmt_vid_out &&
-                                       f->fmt.pix_mp.num_planes == 1) {
-                               if (fmt_mp_to_sp(f, &f_copy))
-                                       break;
-                               ret = ops->vidioc_try_fmt_vid_out(file,
-                                                                 fh, &f_copy);
-                               if (ret)
-                                       break;
-
-                               ret = fmt_sp_to_mp(&f_copy, f);
-                       }
                        if (!ret)
                                v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
                        break;
                case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                        CLEAR_AFTER_FIELD(f, fmt.win);
-                       if (ops->vidioc_try_fmt_vid_out_overlay)
+                       if (likely(ops->vidioc_try_fmt_vid_out_overlay))
                                ret = ops->vidioc_try_fmt_vid_out_overlay(file,
                                       fh, f);
                        break;
                case V4L2_BUF_TYPE_VBI_CAPTURE:
                        CLEAR_AFTER_FIELD(f, fmt.vbi);
-                       if (ops->vidioc_try_fmt_vbi_cap)
+                       if (likely(ops->vidioc_try_fmt_vbi_cap))
                                ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
                        break;
                case V4L2_BUF_TYPE_VBI_OUTPUT:
                        CLEAR_AFTER_FIELD(f, fmt.vbi);
-                       if (ops->vidioc_try_fmt_vbi_out)
+                       if (likely(ops->vidioc_try_fmt_vbi_out))
                                ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
                        break;
                case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
                        CLEAR_AFTER_FIELD(f, fmt.sliced);
-                       if (ops->vidioc_try_fmt_sliced_vbi_cap)
+                       if (likely(ops->vidioc_try_fmt_sliced_vbi_cap))
                                ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
                                                                fh, f);
                        break;
                case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
                        CLEAR_AFTER_FIELD(f, fmt.sliced);
-                       if (ops->vidioc_try_fmt_sliced_vbi_out)
+                       if (likely(ops->vidioc_try_fmt_sliced_vbi_out))
                                ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
                                                                fh, f);
                        break;
                case V4L2_BUF_TYPE_PRIVATE:
                        /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
-                       if (ops->vidioc_try_fmt_type_private)
+                       if (likely(ops->vidioc_try_fmt_type_private))
                                ret = ops->vidioc_try_fmt_type_private(file,
                                                                fh, f);
                        break;
                }
-
+               if (unlikely(ret == -ENOTTY && have_fmt_ops(try)))
+                       ret = -EINVAL;
                break;
        }
        /* FIXME: Those buf reqs could be handled here,
@@ -1103,6 +884,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_reqbufs)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                ret = check_fmt(ops, p->type);
                if (ret)
                        break;
@@ -1168,6 +953,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_overlay)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "value=%d\n", *i);
                ret = ops->vidioc_overlay(file, fh, *i);
                break;
@@ -1193,6 +982,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_fbuf)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
                        p->capability, p->flags, (unsigned long)p->base);
                v4l_print_pix_fmt(vfd, &p->fmt);
@@ -1205,6 +998,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_streamon)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
                ret = ops->vidioc_streamon(file, fh, i);
                break;
@@ -1215,6 +1012,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_streamoff)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
                ret = ops->vidioc_streamoff(file, fh, i);
                break;
@@ -1227,6 +1028,10 @@ static long __video_do_ioctl(struct file *file,
                unsigned int index = p->index, i, j = 0;
                const char *descr = "";
 
+               if (id == 0)
+                       break;
+               ret = -EINVAL;
+
                /* Return norm array in a canonical way */
                for (i = 0; i <= index && id; i++) {
                        /* last std value in the standards array is 0, so this
@@ -1262,16 +1067,15 @@ static long __video_do_ioctl(struct file *file,
        {
                v4l2_std_id *id = arg;
 
-               ret = 0;
                /* Calls the specific handler */
                if (ops->vidioc_g_std)
                        ret = ops->vidioc_g_std(file, fh, id);
-               else if (vfd->current_norm)
+               else if (vfd->current_norm) {
+                       ret = 0;
                        *id = vfd->current_norm;
-               else
-                       ret = -EINVAL;
+               }
 
-               if (!ret)
+               if (likely(!ret))
                        dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
                break;
        }
@@ -1281,15 +1085,20 @@ static long __video_do_ioctl(struct file *file,
 
                dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
 
+               if (!ops->vidioc_s_std)
+                       break;
+
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
+               ret = -EINVAL;
                norm = (*id) & vfd->tvnorms;
                if (vfd->tvnorms && !norm)      /* Check if std is supported */
                        break;
 
                /* Calls the specific handler */
-               if (ops->vidioc_s_std)
-                       ret = ops->vidioc_s_std(file, fh, &norm);
-               else
-                       ret = -EINVAL;
+               ret = ops->vidioc_s_std(file, fh, &norm);
 
                /* Updates standard information */
                if (ret >= 0)
@@ -1302,6 +1111,14 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_querystd)
                        break;
+               /*
+                * If nothing detected, it should return all supported
+                * Drivers just need to mask the std argument, in order
+                * to remove the standards that don't apply from the mask.
+                * This means that tuners, audio and video decoders can join
+                * their efforts to improve the standards detection
+                */
+               *p = vfd->tvnorms;
                ret = ops->vidioc_querystd(file, fh, arg);
                if (!ret)
                        dbgarg(cmd, "detected std=%08Lx\n",
@@ -1358,6 +1175,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_input)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "value=%d\n", *i);
                ret = ops->vidioc_s_input(file, fh, *i);
                break;
@@ -1410,6 +1231,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_output)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "value=%d\n", *i);
                ret = ops->vidioc_s_output(file, fh, *i);
                break;
@@ -1479,6 +1304,10 @@ static long __video_do_ioctl(struct file *file,
                if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
                        !ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
 
                dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
 
@@ -1504,6 +1333,8 @@ static long __video_do_ioctl(struct file *file,
                ctrl.value = p->value;
                if (check_ext_ctrls(&ctrls, 1))
                        ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
+               else
+                       ret = -EINVAL;
                break;
        }
        case VIDIOC_G_EXT_CTRLS:
@@ -1515,8 +1346,10 @@ static long __video_do_ioctl(struct file *file,
                        ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
                else if (vfd->ctrl_handler)
                        ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
-               else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
-                       ret = ops->vidioc_g_ext_ctrls(file, fh, p);
+               else if (ops->vidioc_g_ext_ctrls)
+                       ret = check_ext_ctrls(p, 0) ?
+                               ops->vidioc_g_ext_ctrls(file, fh, p) :
+                               -EINVAL;
                else
                        break;
                v4l_print_ext_ctrls(cmd, vfd, p, !ret);
@@ -1530,6 +1363,10 @@ static long __video_do_ioctl(struct file *file,
                if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
                                !ops->vidioc_s_ext_ctrls)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                v4l_print_ext_ctrls(cmd, vfd, p, 1);
                if (vfh && vfh->ctrl_handler)
                        ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
@@ -1537,6 +1374,8 @@ static long __video_do_ioctl(struct file *file,
                        ret = v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
                else if (check_ext_ctrls(p, 0))
                        ret = ops->vidioc_s_ext_ctrls(file, fh, p);
+               else
+                       ret = -EINVAL;
                break;
        }
        case VIDIOC_TRY_EXT_CTRLS:
@@ -1554,6 +1393,8 @@ static long __video_do_ioctl(struct file *file,
                        ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
                else if (check_ext_ctrls(p, 0))
                        ret = ops->vidioc_try_ext_ctrls(file, fh, p);
+               else
+                       ret = -EINVAL;
                break;
        }
        case VIDIOC_QUERYMENU:
@@ -1614,6 +1455,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_audio)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
                                        "mode=0x%x\n", p->index, p->name,
                                        p->capability, p->mode);
@@ -1654,6 +1499,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_audout)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "index=%d, name=%s, capability=%d, "
                                        "mode=%d\n", p->index, p->name,
                                        p->capability, p->mode);
@@ -1683,6 +1532,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_modulator)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "index=%d, name=%s, capability=%d, "
                                "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
                                p->index, p->name, p->capability, p->rangelow,
@@ -1709,6 +1562,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_crop)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
                dbgrect(vfd, "", &p->c);
                ret = ops->vidioc_s_crop(file, fh, p);
@@ -1752,11 +1609,15 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_g_jpegcomp)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
                                        "COM_len=%d, jpeg_markers=%d\n",
                                        p->quality, p->APPn, p->APP_len,
                                        p->COM_len, p->jpeg_markers);
-                       ret = ops->vidioc_s_jpegcomp(file, fh, p);
+               ret = ops->vidioc_s_jpegcomp(file, fh, p);
                break;
        }
        case VIDIOC_G_ENC_INDEX:
@@ -1777,6 +1638,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_encoder_cmd)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                ret = ops->vidioc_encoder_cmd(file, fh, p);
                if (!ret)
                        dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1797,6 +1662,8 @@ static long __video_do_ioctl(struct file *file,
        {
                struct v4l2_streamparm *p = arg;
 
+               if (!ops->vidioc_g_parm && !vfd->current_norm)
+                       break;
                if (ops->vidioc_g_parm) {
                        ret = check_fmt(ops, p->type);
                        if (ret)
@@ -1805,14 +1672,13 @@ static long __video_do_ioctl(struct file *file,
                } else {
                        v4l2_std_id std = vfd->current_norm;
 
+                       ret = -EINVAL;
                        if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                                break;
 
                        ret = 0;
                        if (ops->vidioc_g_std)
                                ret = ops->vidioc_g_std(file, fh, &std);
-                       else if (std == 0)
-                               ret = -EINVAL;
                        if (ret == 0)
                                v4l2_video_std_frame_period(std,
                                                    &p->parm.capture.timeperframe);
@@ -1827,6 +1693,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_parm)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                ret = check_fmt(ops, p->type);
                if (ret)
                        break;
@@ -1862,6 +1732,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_tuner)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
                        V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
                dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1896,6 +1770,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_frequency)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
                                p->tuner, p->type, p->frequency);
                ret = ops->vidioc_s_frequency(file, fh, p);
@@ -1970,6 +1848,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_hw_freq_seek)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
                type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
                        V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
                dbgarg(cmd,
@@ -2074,6 +1956,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_dv_preset)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
 
                dbgarg(cmd, "preset=%d\n", p->preset);
                ret = ops->vidioc_s_dv_preset(file, fh, p);
@@ -2109,6 +1995,10 @@ static long __video_do_ioctl(struct file *file,
 
                if (!ops->vidioc_s_dv_timings)
                        break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
 
                switch (p->type) {
                case V4L2_DV_BT_656_1120:
@@ -2216,20 +2106,47 @@ static long __video_do_ioctl(struct file *file,
                dbgarg(cmd, "type=0x%8.8x", sub->type);
                break;
        }
-       default:
+       case VIDIOC_CREATE_BUFS:
        {
-               bool valid_prio = true;
+               struct v4l2_create_buffers *create = arg;
 
-               if (!ops->vidioc_default)
+               if (!ops->vidioc_create_bufs)
+                       break;
+               if (ret_prio) {
+                       ret = ret_prio;
                        break;
-               if (use_fh_prio)
-                       valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
-               ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
+               }
+               ret = check_fmt(ops, create->format.type);
+               if (ret)
+                       break;
+
+               ret = ops->vidioc_create_bufs(file, fh, create);
+
+               dbgarg(cmd, "count=%d @ %d\n", create->count, create->index);
                break;
        }
+       case VIDIOC_PREPARE_BUF:
+       {
+               struct v4l2_buffer *b = arg;
+
+               if (!ops->vidioc_prepare_buf)
+                       break;
+               ret = check_fmt(ops, b->type);
+               if (ret)
+                       break;
+
+               ret = ops->vidioc_prepare_buf(file, fh, b);
+
+               dbgarg(cmd, "index=%d", b->index);
+               break;
+       }
+       default:
+               if (!ops->vidioc_default)
+                       break;
+               ret = ops->vidioc_default(file, fh, ret_prio >= 0, cmd, arg);
+               break;
        } /* switch */
 
-exit_prio:
        if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
                if (ret < 0) {
                        v4l_print_ioctl(vfd->name, cmd);
@@ -2309,6 +2226,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
                struct v4l2_ext_controls *ctrls = parg;
 
                if (ctrls->count != 0) {
+                       if (ctrls->count > V4L2_CID_MAX_CTRLS) {
+                               ret = -EINVAL;
+                               break;
+                       }
                        *user_ptr = (void __user *)ctrls->controls;
                        *kernel_ptr = (void *)&ctrls->controls;
                        *array_size = sizeof(struct v4l2_ext_control)