[media] cx23885: fix format/crop handling
[sfrench/cifs-2.6.git] / drivers / media / pci / cx23885 / cx23885-video.c
index 71a80e2b842ca9c395cb4a000f77ae482fb57dbc..ad4d7e683ba7717bdc5f9e798ae3b83d9cc408b1 100644 (file)
@@ -35,7 +35,7 @@
 #include "cx23885-ioctl.h"
 #include "tuner-xc2028.h"
 
-#include <media/cx25840.h>
+#include <media/drv-intf/cx25840.h>
 
 MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
@@ -114,11 +114,19 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
 
 int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
 {
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .format.code = MEDIA_BUS_FMT_FIXED,
+       };
+
        dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
                __func__,
                (unsigned int)norm,
                v4l2_norm_to_name(norm));
 
+       if (dev->tvnorm == norm)
+               return 0;
+
        if (dev->tvnorm != norm) {
                if (vb2_is_busy(&dev->vb2_vidq) || vb2_is_busy(&dev->vb2_vbiq) ||
                    vb2_is_busy(&dev->vb2_mpegq))
@@ -126,9 +134,17 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
        }
 
        dev->tvnorm = norm;
+       dev->width = 720;
+       dev->height = norm_maxh(norm);
+       dev->field = V4L2_FIELD_INTERLACED;
 
        call_all(dev, video, s_std, norm);
 
+       format.format.width = dev->width;
+       format.format.height = dev->height;
+       format.format.field = dev->field;
+       call_all(dev, pad, set_fmt, NULL, &format);
+
        return 0;
 }
 
@@ -545,7 +561,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                return -EINVAL;
 
        field = f->fmt.pix.field;
-       maxw  = norm_maxw(dev->tvnorm);
+       maxw  = 720;
        maxh  = norm_maxh(dev->tvnorm);
 
        if (V4L2_FIELD_ANY == field) {
@@ -648,6 +664,26 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
        return 0;
 }
 
+static int vidioc_cropcap(struct file *file, void *priv,
+                         struct v4l2_cropcap *cc)
+{
+       struct cx23885_dev *dev = video_drvdata(file);
+       bool is_50hz = dev->tvnorm & V4L2_STD_625_50;
+
+       if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       cc->bounds.left = 0;
+       cc->bounds.top = 0;
+       cc->bounds.width = 720;
+       cc->bounds.height = norm_maxh(dev->tvnorm);
+       cc->defrect = cc->bounds;
+       cc->pixelaspect.numerator = is_50hz ? 54 : 11;
+       cc->pixelaspect.denominator = is_50hz ? 59 : 10;
+
+       return 0;
+}
+
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 {
        struct cx23885_dev *dev = video_drvdata(file);
@@ -1082,6 +1118,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_dqbuf         = vb2_ioctl_dqbuf,
        .vidioc_streamon      = vb2_ioctl_streamon,
        .vidioc_streamoff     = vb2_ioctl_streamoff,
+       .vidioc_cropcap       = vidioc_cropcap,
        .vidioc_s_std         = vidioc_s_std,
        .vidioc_g_std         = vidioc_g_std,
        .vidioc_enum_input    = vidioc_enum_input,