static void rvin_crop_scale_comp_gen2(struct rvin_dev *vin)
 {
+       unsigned int crop_height;
        u32 xs, ys;
 
        /* Set scaling coefficient */
+       crop_height = vin->crop.height;
+       if (V4L2_FIELD_IS_INTERLACED(vin->format.field))
+               crop_height *= 2;
+
        ys = 0;
-       if (vin->crop.height != vin->compose.height)
-               ys = (4096 * vin->crop.height) / vin->compose.height;
+       if (crop_height != vin->compose.height)
+               ys = (4096 * crop_height) / vin->compose.height;
        rvin_write(vin, ys, VNYS_REG);
 
        xs = 0;
        /* Set Start/End Pixel/Line Pre-Clip */
        rvin_write(vin, vin->crop.left, VNSPPRC_REG);
        rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG);
+       rvin_write(vin, vin->crop.top, VNSLPRC_REG);
+       rvin_write(vin, vin->crop.top + vin->crop.height - 1, VNELPRC_REG);
 
-       switch (vin->format.field) {
-       case V4L2_FIELD_INTERLACED:
-       case V4L2_FIELD_INTERLACED_TB:
-       case V4L2_FIELD_INTERLACED_BT:
-               rvin_write(vin, vin->crop.top / 2, VNSLPRC_REG);
-               rvin_write(vin, (vin->crop.top + vin->crop.height) / 2 - 1,
-                          VNELPRC_REG);
-               break;
-       default:
-               rvin_write(vin, vin->crop.top, VNSLPRC_REG);
-               rvin_write(vin, vin->crop.top + vin->crop.height - 1,
-                          VNELPRC_REG);
-               break;
-       }
 
        /* TODO: Add support for the UDS scaler. */
        if (vin->info->model != RCAR_GEN3)
                vnmc = VNMC_IM_ODD_EVEN;
                progressive = true;
                break;
+       case V4L2_FIELD_ALTERNATE:
+               vnmc = VNMC_IM_ODD_EVEN;
+               break;
        default:
                vnmc = VNMC_IM_ODD;
                break;
        return rvin_read(vin, VNMS_REG) & VNMS_CA;
 }
 
+static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
+{
+       if (vin->format.field == V4L2_FIELD_ALTERNATE) {
+               /* If FS is set it is an Even field. */
+               if (vnms & VNMS_FS)
+                       return V4L2_FIELD_BOTTOM;
+               return V4L2_FIELD_TOP;
+       }
+
+       return vin->format.field;
+}
+
 static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr)
 {
        const struct rvin_video_format *fmt;
 
        /* Capture frame */
        if (vin->queue_buf[slot]) {
-               vin->queue_buf[slot]->field = vin->format.field;
+               vin->queue_buf[slot]->field = rvin_get_active_field(vin, vnms);
                vin->queue_buf[slot]->sequence = vin->sequence;
                vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
                vb2_buffer_done(&vin->queue_buf[slot]->vb2_buf,
                case V4L2_FIELD_TOP:
                case V4L2_FIELD_BOTTOM:
                case V4L2_FIELD_NONE:
+               case V4L2_FIELD_ALTERNATE:
                        break;
                case V4L2_FIELD_INTERLACED_TB:
                case V4L2_FIELD_INTERLACED_BT:
 
        case V4L2_FIELD_INTERLACED_TB:
        case V4L2_FIELD_INTERLACED_BT:
        case V4L2_FIELD_INTERLACED:
-               break;
        case V4L2_FIELD_ALTERNATE:
-               /*
-                * Driver does not (yet) support outputting ALTERNATE to a
-                * userspace. It does support outputting INTERLACED so use
-                * the VIN hardware to combine the two fields.
-                */
-               pix->field = V4L2_FIELD_INTERLACED;
-               pix->height *= 2;
                break;
        default:
                pix->field = RVIN_DEFAULT_FIELD;
 
        v4l2_fill_pix_format(&vin->format, &fmt.format);
 
-       rvin_format_align(vin, &vin->format);
-
        vin->src_rect.top = 0;
        vin->src_rect.left = 0;
        vin->src_rect.width = vin->format.width;
        vin->src_rect.height = vin->format.height;
 
+       /*  Make use of the hardware interlacer by default. */
+       if (vin->format.field == V4L2_FIELD_ALTERNATE) {
+               vin->format.field = V4L2_FIELD_INTERLACED;
+               vin->format.height *= 2;
+       }
+
+       rvin_format_align(vin, &vin->format);
+
        vin->crop = vin->src_rect;
-       vin->compose = vin->src_rect;
+
+       vin->compose.top = 0;
+       vin->compose.left = 0;
+       vin->compose.width = vin->format.width;
+       vin->compose.height = vin->format.height;
 
        return 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)