return pix->bytesperline * pix->height;
 }
 
-static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
+static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
 {
        u32 walign;
 
 
        vin_dbg(vin, "Format %ux%u bpl: %u size: %u\n",
                pix->width, pix->height, pix->bytesperline, pix->sizeimage);
-
-       return 0;
 }
 
 /* -----------------------------------------------------------------------------
  * V4L2
  */
 
-static void rvin_reset_crop_compose(struct rvin_dev *vin)
-{
-       vin->crop.top = vin->crop.left = 0;
-       vin->crop.width = vin->source.width;
-       vin->crop.height = vin->source.height;
-
-       vin->compose.top = vin->compose.left = 0;
-       vin->compose.width = vin->format.width;
-       vin->compose.height = vin->format.height;
-}
-
 static int rvin_reset_format(struct rvin_dev *vin)
 {
        struct v4l2_subdev_format fmt = {
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .pad = vin->digital->source_pad,
        };
-       struct v4l2_mbus_framefmt *mf = &fmt.format;
        int ret;
 
-       fmt.pad = vin->digital->source_pad;
-
        ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
        if (ret)
                return ret;
 
-       vin->format.width       = mf->width;
-       vin->format.height      = mf->height;
-       vin->format.colorspace  = mf->colorspace;
-       vin->format.field       = mf->field;
+       v4l2_fill_pix_format(&vin->format, &fmt.format);
+
+       rvin_format_align(vin, &vin->format);
 
-       rvin_reset_crop_compose(vin);
+       vin->source.top = 0;
+       vin->source.left = 0;
+       vin->source.width = vin->format.width;
+       vin->source.height = vin->format.height;
 
-       vin->format.bytesperline = rvin_format_bytesperline(&vin->format);
-       vin->format.sizeimage = rvin_format_sizeimage(&vin->format);
+       vin->crop = vin->source;
+       vin->compose = vin->source;
 
        return 0;
 }
 
-static int __rvin_try_format_source(struct rvin_dev *vin,
-                                   u32 which,
-                                   struct v4l2_pix_format *pix,
-                                   struct rvin_source_fmt *source)
+static int rvin_try_format(struct rvin_dev *vin, u32 which,
+                          struct v4l2_pix_format *pix,
+                          struct v4l2_rect *crop, struct v4l2_rect *compose)
 {
-       struct v4l2_subdev *sd;
+       struct v4l2_subdev *sd = vin_to_source(vin);
        struct v4l2_subdev_pad_config *pad_cfg;
        struct v4l2_subdev_format format = {
                .which = which,
+               .pad = vin->digital->source_pad,
        };
        enum v4l2_field field;
        u32 width, height;
        int ret;
 
-       sd = vin_to_source(vin);
-
-       v4l2_fill_mbus_format(&format.format, pix, vin->digital->code);
-
        pad_cfg = v4l2_subdev_alloc_pad_config(sd);
        if (pad_cfg == NULL)
                return -ENOMEM;
 
-       format.pad = vin->digital->source_pad;
+       if (!rvin_format_from_pixel(pix->pixelformat) ||
+           (vin->info->model == RCAR_M1 &&
+            pix->pixelformat == V4L2_PIX_FMT_XBGR32))
+               pix->pixelformat = RVIN_DEFAULT_FORMAT;
+
+       v4l2_fill_mbus_format(&format.format, pix, vin->digital->code);
 
        /* Allow the video device to override field and to scale */
        field = pix->field;
 
        v4l2_fill_pix_format(pix, &format.format);
 
-       source->width = pix->width;
-       source->height = pix->height;
+       if (crop) {
+               crop->top = 0;
+               crop->left = 0;
+               crop->width = pix->width;
+               crop->height = pix->height;
+
+               /*
+                * If source is ALTERNATE the driver will use the VIN hardware
+                * to INTERLACE it. The crop height then needs to be doubled.
+                */
+               if (pix->field == V4L2_FIELD_ALTERNATE)
+                       crop->height *= 2;
+       }
 
        if (field != V4L2_FIELD_ANY)
                pix->field = field;
        pix->width = width;
        pix->height = height;
 
-       vin_dbg(vin, "Source resolution: %ux%u\n", source->width,
-               source->height);
+       rvin_format_align(vin, pix);
 
+       if (compose) {
+               compose->top = 0;
+               compose->left = 0;
+               compose->width = pix->width;
+               compose->height = pix->height;
+       }
 done:
        v4l2_subdev_free_pad_config(pad_cfg);
-       return ret;
-}
 
-static int __rvin_try_format(struct rvin_dev *vin,
-                            u32 which,
-                            struct v4l2_pix_format *pix,
-                            struct rvin_source_fmt *source)
-{
-       int ret;
-
-       if (!rvin_format_from_pixel(pix->pixelformat) ||
-           (vin->info->model == RCAR_M1 &&
-            pix->pixelformat == V4L2_PIX_FMT_XBGR32))
-               pix->pixelformat = RVIN_DEFAULT_FORMAT;
-
-       /* Limit to source capabilities */
-       ret = __rvin_try_format_source(vin, which, pix, source);
-       if (ret)
-               return ret;
-
-       return rvin_format_align(vin, pix);
+       return 0;
 }
 
 static int rvin_querycap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
        struct rvin_dev *vin = video_drvdata(file);
-       struct rvin_source_fmt source;
 
-       return __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix,
-                                &source);
+       return rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix, NULL,
+                              NULL);
 }
 
 static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
                              struct v4l2_format *f)
 {
        struct rvin_dev *vin = video_drvdata(file);
-       struct rvin_source_fmt source;
+       struct v4l2_rect crop, compose;
        int ret;
 
        if (vb2_is_busy(&vin->queue))
                return -EBUSY;
 
-       ret = __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
-                               &source);
+       ret = rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
+                             &crop, &compose);
        if (ret)
                return ret;
 
-       vin->source.width = source.width;
-       vin->source.height = source.height;
-
        vin->format = f->fmt.pix;
-
-       rvin_reset_crop_compose(vin);
+       vin->crop = crop;
+       vin->compose = compose;
+       vin->source = crop;
 
        return 0;
 }