As part of this, separate format try code from *_set_fmt() into
*_try_fmt(), so that the latter function can be used to propagate
a legal format from sink to source. This also reduces subsequent
bloat in *_set_fmt().

imx-ic-prp never needed separate formats for sink and source pads,
so propagation in this case was easy, just have only a single
format shared by both pads.

Signed-off-by: Steve Longerbeam <steve_longerb...@mentor.com>
---
 drivers/staging/media/imx/imx-ic-prp.c        |  39 ++---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  95 +++++++----
 drivers/staging/media/imx/imx-media-capture.c |  13 ++
 drivers/staging/media/imx/imx-media-csi.c     | 224 +++++++++++++++-----------
 drivers/staging/media/imx/imx-media-vdic.c    |  82 ++++++----
 5 files changed, 279 insertions(+), 174 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 505f456..b4d4e48 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -56,8 +56,7 @@ struct prp_priv {
        /* the CSI id at link validate */
        int csi_id;
 
-       struct v4l2_mbus_framefmt format_mbus[PRP_NUM_PADS];
-       const struct imx_media_pixfmt *cc[PRP_NUM_PADS];
+       struct v4l2_mbus_framefmt format_mbus;
 
        bool stream_on; /* streaming is on */
 };
@@ -97,7 +96,7 @@ __prp_get_fmt(struct prp_priv *priv, struct 
v4l2_subdev_pad_config *cfg,
        if (which == V4L2_SUBDEV_FORMAT_TRY)
                return v4l2_subdev_get_try_format(&ic_priv->sd, cfg, pad);
        else
-               return &priv->format_mbus[pad];
+               return &priv->format_mbus;
 }
 
 /*
@@ -166,8 +165,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
                       struct v4l2_subdev_format *sdformat)
 {
        struct prp_priv *priv = sd_to_priv(sd);
-       const struct imx_media_pixfmt *cc = NULL;
-       struct v4l2_mbus_framefmt *infmt;
+       const struct imx_media_pixfmt *cc;
+       struct v4l2_mbus_framefmt *fmt;
        int ret = 0;
        u32 code;
 
@@ -198,20 +197,13 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
        case PRP_SRC_PAD_PRPENC:
        case PRP_SRC_PAD_PRPVF:
                /* Output pads mirror input pad */
-               infmt = __prp_get_fmt(priv, cfg, PRP_SINK_PAD,
-                                     sdformat->which);
-               cc = imx_media_find_ipu_format(infmt->code, CS_SEL_ANY);
-               sdformat->format = *infmt;
+               fmt = __prp_get_fmt(priv, cfg, PRP_SINK_PAD, sdformat->which);
+               sdformat->format = *fmt;
                break;
        }
 
-       if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
-               cfg->try_fmt = sdformat->format;
-       } else {
-               priv->format_mbus[sdformat->pad] = sdformat->format;
-               priv->cc[sdformat->pad] = cc;
-       }
-
+       fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+       *fmt = sdformat->format;
 out:
        mutex_unlock(&priv->lock);
        return ret;
@@ -392,16 +384,15 @@ static int prp_registered(struct v4l2_subdev *sd)
        for (i = 0; i < PRP_NUM_PADS; i++) {
                priv->pad[i].flags = (i == PRP_SINK_PAD) ?
                        MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
-
-               /* set a default mbus format  */
-               imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
-               ret = imx_media_init_mbus_fmt(&priv->format_mbus[i],
-                                             640, 480, code, V4L2_FIELD_NONE,
-                                             &priv->cc[i]);
-               if (ret)
-                       return ret;
        }
 
+       /* set a default mbus format  */
+       imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
+       ret = imx_media_init_mbus_fmt(&priv->format_mbus, 640, 480, code,
+                                     V4L2_FIELD_NONE, NULL);
+       if (ret)
+               return ret;
+
        return media_entity_pads_init(&sd->entity, PRP_NUM_PADS, priv->pad);
 }
 
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 9babfa3..4123b03 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -767,35 +767,23 @@ static int prp_get_fmt(struct v4l2_subdev *sd,
        return ret;
 }
 
-static int prp_set_fmt(struct v4l2_subdev *sd,
-                      struct v4l2_subdev_pad_config *cfg,
-                      struct v4l2_subdev_format *sdformat)
+static void prp_try_fmt(struct prp_priv *priv,
+                       struct v4l2_subdev_pad_config *cfg,
+                       struct v4l2_subdev_format *sdformat,
+                       const struct imx_media_pixfmt **cc)
 {
-       struct prp_priv *priv = sd_to_priv(sd);
-       const struct imx_media_pixfmt *cc;
-       struct v4l2_mbus_framefmt *infmt;
-       int ret = 0;
-       u32 code;
-
-       if (sdformat->pad >= PRPENCVF_NUM_PADS)
-               return -EINVAL;
-
-       mutex_lock(&priv->lock);
-
-       if (priv->stream_on) {
-               ret = -EBUSY;
-               goto out;
-       }
+       *cc = imx_media_find_ipu_format(sdformat->format.code, CS_SEL_ANY);
+       if (!*cc) {
+               u32 code;
 
-       cc = imx_media_find_ipu_format(sdformat->format.code, CS_SEL_ANY);
-       if (!cc) {
                imx_media_enum_ipu_format(&code, 0, CS_SEL_ANY);
-               cc = imx_media_find_ipu_format(code, CS_SEL_ANY);
-               sdformat->format.code = cc->codes[0];
+               *cc = imx_media_find_ipu_format(code, CS_SEL_ANY);
+               sdformat->format.code = (*cc)->codes[0];
        }
 
        if (sdformat->pad == PRPENCVF_SRC_PAD) {
-               infmt = __prp_get_fmt(priv, cfg, PRPENCVF_SINK_PAD,
+               struct v4l2_mbus_framefmt *infmt =
+                       __prp_get_fmt(priv, cfg, PRPENCVF_SINK_PAD,
                                      sdformat->which);
 
                if (sdformat->format.field != V4L2_FIELD_NONE)
@@ -823,14 +811,65 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
                                      MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
                                      S_ALIGN);
        }
+}
 
-       if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
-               cfg->try_fmt = sdformat->format;
-       } else {
-               priv->format_mbus[sdformat->pad] = sdformat->format;
-               priv->cc[sdformat->pad] = cc;
+static int prp_set_fmt(struct v4l2_subdev *sd,
+                      struct v4l2_subdev_pad_config *cfg,
+                      struct v4l2_subdev_format *sdformat)
+{
+       struct prp_priv *priv = sd_to_priv(sd);
+       struct imx_media_video_dev *vdev = priv->vdev;
+       const struct imx_media_pixfmt *cc;
+       struct v4l2_pix_format vdev_fmt;
+       struct v4l2_mbus_framefmt *fmt;
+       int ret = 0;
+
+       if (sdformat->pad >= PRPENCVF_NUM_PADS)
+               return -EINVAL;
+
+       mutex_lock(&priv->lock);
+
+       if (priv->stream_on) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       prp_try_fmt(priv, cfg, sdformat, &cc);
+
+       fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+       *fmt = sdformat->format;
+
+       /* propagate a default format to source pad */
+       if (sdformat->pad == PRPENCVF_SINK_PAD) {
+               const struct imx_media_pixfmt *outcc;
+               struct v4l2_mbus_framefmt *outfmt;
+               struct v4l2_subdev_format format;
+
+               format.pad = PRPENCVF_SRC_PAD;
+               format.which = sdformat->which;
+               format.format = sdformat->format;
+               prp_try_fmt(priv, cfg, &format, &outcc);
+
+               outfmt = __prp_get_fmt(priv, cfg, PRPENCVF_SRC_PAD,
+                                      sdformat->which);
+               *outfmt = format.format;
+               if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+                       priv->cc[PRPENCVF_SRC_PAD] = outcc;
        }
 
+       if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY)
+               goto out;
+
+       priv->cc[sdformat->pad] = cc;
+
+       /* propagate output pad format to capture device */
+       imx_media_mbus_fmt_to_pix_fmt(&vdev_fmt,
+                                     &priv->format_mbus[PRPENCVF_SRC_PAD],
+                                     priv->cc[PRPENCVF_SRC_PAD]);
+       mutex_unlock(&priv->lock);
+       imx_media_capture_device_set_format(vdev, &vdev_fmt);
+
+       return 0;
 out:
        mutex_unlock(&priv->lock);
        return ret;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index ff0a6ed..7521ca9 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -506,6 +506,19 @@ static struct video_device capture_videodev = {
        .device_caps    = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
 };
 
+void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,
+                                        struct v4l2_pix_format *pix)
+{
+       struct capture_priv *priv = to_capture_priv(vdev);
+
+       mutex_lock(&priv->mutex);
+       priv->vdev.fmt.fmt.pix = *pix;
+       priv->vdev.cc = imx_media_find_format(pix->pixelformat, CS_SEL_ANY,
+                                             false);
+       mutex_unlock(&priv->mutex);
+}
+EXPORT_SYMBOL_GPL(imx_media_capture_device_set_format);
+
 struct imx_media_buffer *
 imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev)
 {
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index dee5733..6b8f875 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1022,11 +1022,21 @@ __csi_get_fmt(struct csi_priv *priv, struct 
v4l2_subdev_pad_config *cfg,
                return &priv->format_mbus[pad];
 }
 
-static int csi_try_crop(struct csi_priv *priv,
-                       struct v4l2_rect *crop,
-                       struct v4l2_subdev_pad_config *cfg,
-                       struct v4l2_mbus_framefmt *infmt,
-                       struct imx_media_subdev *sensor)
+static struct v4l2_rect *
+__csi_get_crop(struct csi_priv *priv, struct v4l2_subdev_pad_config *cfg,
+              enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_crop(&priv->sd, cfg, CSI_SINK_PAD);
+       else
+               return &priv->crop;
+}
+
+static void csi_try_crop(struct csi_priv *priv,
+                        struct v4l2_rect *crop,
+                        struct v4l2_subdev_pad_config *cfg,
+                        struct v4l2_mbus_framefmt *infmt,
+                        struct imx_media_subdev *sensor)
 {
        struct v4l2_of_endpoint *sensor_ep;
 
@@ -1055,8 +1065,6 @@ static int csi_try_crop(struct csi_priv *priv,
                if (crop->top + crop->height > infmt->height)
                        crop->top = infmt->height - crop->height;
        }
-
-       return 0;
 }
 
 static int csi_enum_mbus_code(struct v4l2_subdev *sd,
@@ -1128,34 +1136,17 @@ static int csi_get_fmt(struct v4l2_subdev *sd,
        return ret;
 }
 
-static int csi_set_fmt(struct v4l2_subdev *sd,
-                      struct v4l2_subdev_pad_config *cfg,
-                      struct v4l2_subdev_format *sdformat)
+static void csi_try_fmt(struct csi_priv *priv,
+                       struct imx_media_subdev *sensor,
+                       struct v4l2_subdev_pad_config *cfg,
+                       struct v4l2_subdev_format *sdformat,
+                       struct v4l2_rect *crop,
+                       const struct imx_media_pixfmt **cc)
 {
-       struct csi_priv *priv = v4l2_get_subdevdata(sd);
-       const struct imx_media_pixfmt *cc, *incc;
+       const struct imx_media_pixfmt *incc;
        struct v4l2_mbus_framefmt *infmt;
-       struct imx_media_subdev *sensor;
-       struct v4l2_rect crop;
-       int ret = 0;
        u32 code;
 
-       if (sdformat->pad >= CSI_NUM_PADS)
-               return -EINVAL;
-
-       sensor = imx_media_find_sensor(priv->md, &priv->sd.entity);
-       if (IS_ERR(sensor)) {
-               v4l2_err(&priv->sd, "no sensor attached\n");
-               return PTR_ERR(sensor);
-       }
-
-       mutex_lock(&priv->lock);
-
-       if (priv->stream_on) {
-               ret = -EBUSY;
-               goto out;
-       }
-
        switch (sdformat->pad) {
        case CSI_SRC_PAD_DIRECT:
        case CSI_SRC_PAD_IDMAC:
@@ -1164,29 +1155,29 @@ static int csi_set_fmt(struct v4l2_subdev *sd,
                incc = imx_media_find_mbus_format(infmt->code,
                                                  CS_SEL_ANY, true);
 
-               if (sdformat->format.width < priv->crop.width * 3 / 4)
-                       sdformat->format.width = priv->crop.width / 2;
+               if (sdformat->format.width < crop->width * 3 / 4)
+                       sdformat->format.width = crop->width / 2;
                else
-                       sdformat->format.width = priv->crop.width;
+                       sdformat->format.width = crop->width;
 
-               if (sdformat->format.height < priv->crop.height * 3 / 4)
-                       sdformat->format.height = priv->crop.height / 2;
+               if (sdformat->format.height < crop->height * 3 / 4)
+                       sdformat->format.height = crop->height / 2;
                else
-                       sdformat->format.height = priv->crop.height;
+                       sdformat->format.height = crop->height;
 
                if (incc->bayer) {
                        sdformat->format.code = infmt->code;
-                       cc = incc;
+                       *cc = incc;
                } else {
                        u32 cs_sel = (incc->cs == IPUV3_COLORSPACE_YUV) ?
                                CS_SEL_YUV : CS_SEL_RGB;
 
-                       cc = imx_media_find_ipu_format(sdformat->format.code,
-                                                      cs_sel);
-                       if (!cc) {
+                       *cc = imx_media_find_ipu_format(sdformat->format.code,
+                                                       cs_sel);
+                       if (!*cc) {
                                imx_media_enum_ipu_format(&code, 0, cs_sel);
-                               cc = imx_media_find_ipu_format(code, cs_sel);
-                               sdformat->format.code = cc->codes[0];
+                               *cc = imx_media_find_ipu_format(code, cs_sel);
+                               sdformat->format.code = (*cc)->codes[0];
                        }
                }
 
@@ -1208,39 +1199,96 @@ static int csi_set_fmt(struct v4l2_subdev *sd,
                v4l_bound_align_image(&sdformat->format.width, MIN_W, MAX_W,
                                      W_ALIGN, &sdformat->format.height,
                                      MIN_H, MAX_H, H_ALIGN, S_ALIGN);
-               crop.left = 0;
-               crop.top = 0;
-               crop.width = sdformat->format.width;
-               crop.height = sdformat->format.height;
-               ret = csi_try_crop(priv, &crop, cfg, &sdformat->format, sensor);
-               if (ret)
-                       goto out;
+               crop->left = 0;
+               crop->top = 0;
+               crop->width = sdformat->format.width;
+               crop->height = sdformat->format.height;
+               csi_try_crop(priv, crop, cfg, &sdformat->format, sensor);
 
-               cc = imx_media_find_mbus_format(sdformat->format.code,
-                                               CS_SEL_ANY, true);
-               if (!cc) {
+               *cc = imx_media_find_mbus_format(sdformat->format.code,
+                                                CS_SEL_ANY, true);
+               if (!*cc) {
                        imx_media_enum_mbus_format(&code, 0,
                                                   CS_SEL_ANY, false);
-                       cc = imx_media_find_mbus_format(code,
+                       *cc = imx_media_find_mbus_format(code,
                                                        CS_SEL_ANY, false);
-                       sdformat->format.code = cc->codes[0];
+                       sdformat->format.code = (*cc)->codes[0];
                }
                break;
-       default:
-               ret = -EINVAL;
+       }
+}
+
+static int csi_set_fmt(struct v4l2_subdev *sd,
+                      struct v4l2_subdev_pad_config *cfg,
+                      struct v4l2_subdev_format *sdformat)
+{
+       struct csi_priv *priv = v4l2_get_subdevdata(sd);
+       struct imx_media_video_dev *vdev = priv->vdev;
+       const struct imx_media_pixfmt *cc;
+       struct imx_media_subdev *sensor;
+       struct v4l2_pix_format vdev_fmt;
+       struct v4l2_mbus_framefmt *fmt;
+       struct v4l2_rect *crop;
+       int ret = 0;
+
+       if (sdformat->pad >= CSI_NUM_PADS)
+               return -EINVAL;
+
+       sensor = imx_media_find_sensor(priv->md, &priv->sd.entity);
+       if (IS_ERR(sensor)) {
+               v4l2_err(&priv->sd, "no sensor attached\n");
+               return PTR_ERR(sensor);
+       }
+
+       mutex_lock(&priv->lock);
+
+       if (priv->stream_on) {
+               ret = -EBUSY;
                goto out;
        }
 
-       if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
-               cfg->try_fmt = sdformat->format;
-       } else {
-               priv->format_mbus[sdformat->pad] = sdformat->format;
-               priv->cc[sdformat->pad] = cc;
-               /* Reset the crop window if this is the input pad */
-               if (sdformat->pad == CSI_SINK_PAD)
-                       priv->crop = crop;
+       crop = __csi_get_crop(priv, cfg, sdformat->which);
+
+       csi_try_fmt(priv, sensor, cfg, sdformat, crop, &cc);
+
+       fmt = __csi_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+       *fmt = sdformat->format;
+
+       if (sdformat->pad == CSI_SINK_PAD) {
+               int pad;
+
+               /* propagate format to source pads */
+               for (pad = CSI_SINK_PAD + 1; pad < CSI_NUM_PADS; pad++) {
+                       const struct imx_media_pixfmt *outcc;
+                       struct v4l2_mbus_framefmt *outfmt;
+                       struct v4l2_subdev_format format;
+
+                       format.pad = pad;
+                       format.which = sdformat->which;
+                       format.format = sdformat->format;
+                       csi_try_fmt(priv, sensor, cfg, &format, crop, &outcc);
+
+                       outfmt = __csi_get_fmt(priv, cfg, pad, sdformat->which);
+                       *outfmt = format.format;
+
+                       if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+                               priv->cc[pad] = outcc;
+               }
        }
 
+       if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY)
+               goto out;
+
+       priv->cc[sdformat->pad] = cc;
+
+       /* propagate IDMAC output pad format to capture device */
+       imx_media_mbus_fmt_to_pix_fmt(&vdev_fmt,
+                                     &priv->format_mbus[CSI_SRC_PAD_IDMAC],
+                                     priv->cc[CSI_SRC_PAD_IDMAC]);
+       mutex_unlock(&priv->lock);
+       imx_media_capture_device_set_format(vdev, &vdev_fmt);
+
+       return 0;
 out:
        mutex_unlock(&priv->lock);
        return ret;
@@ -1252,6 +1300,7 @@ static int csi_get_selection(struct v4l2_subdev *sd,
 {
        struct csi_priv *priv = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *infmt;
+       struct v4l2_rect *crop;
        int ret = 0;
 
        if (sel->pad >= CSI_NUM_PADS || sel->pad == CSI_SINK_PAD)
@@ -1260,10 +1309,7 @@ static int csi_get_selection(struct v4l2_subdev *sd,
        mutex_lock(&priv->lock);
 
        infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sel->which);
-       if (!infmt) {
-               ret = -EINVAL;
-               goto out;
-       }
+       crop = __csi_get_crop(priv, cfg, sel->which);
 
        switch (sel->target) {
        case V4L2_SEL_TGT_CROP_BOUNDS:
@@ -1273,20 +1319,12 @@ static int csi_get_selection(struct v4l2_subdev *sd,
                sel->r.height = infmt->height;
                break;
        case V4L2_SEL_TGT_CROP:
-               if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
-                       struct v4l2_rect *try_crop =
-                               v4l2_subdev_get_try_crop(&priv->sd,
-                                                        cfg, sel->pad);
-                       sel->r = *try_crop;
-               } else {
-                       sel->r = priv->crop;
-               }
+               sel->r = *crop;
                break;
        default:
                ret = -EINVAL;
        }
 
-out:
        mutex_unlock(&priv->lock);
        return ret;
 }
@@ -1298,7 +1336,8 @@ static int csi_set_selection(struct v4l2_subdev *sd,
        struct csi_priv *priv = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *infmt;
        struct imx_media_subdev *sensor;
-       int ret = 0;
+       struct v4l2_rect *crop;
+       int pad, ret = 0;
 
        if (sel->pad >= CSI_NUM_PADS ||
            sel->pad == CSI_SINK_PAD ||
@@ -1318,6 +1357,9 @@ static int csi_set_selection(struct v4l2_subdev *sd,
                goto out;
        }
 
+       infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sel->which);
+       crop = __csi_get_crop(priv, cfg, sel->which);
+
        /*
         * Modifying the crop rectangle always changes the format on the source
         * pad. If the KEEP_CONFIG flag is set, just return the current crop
@@ -1326,25 +1368,21 @@ static int csi_set_selection(struct v4l2_subdev *sd,
        if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
                sel->r = priv->crop;
                if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
-                       cfg->try_crop = sel->r;
+                       *crop = sel->r;
                goto out;
        }
 
-       infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sel->which);
-       ret = csi_try_crop(priv, &sel->r, cfg, infmt, sensor);
-       if (ret)
-               goto out;
+       csi_try_crop(priv, &sel->r, cfg, infmt, sensor);
 
-       if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
-               cfg->try_crop = sel->r;
-       } else {
-               struct v4l2_mbus_framefmt *outfmt =
-                       &priv->format_mbus[sel->pad];
+       *crop = sel->r;
+
+       /* Update the source pad formats */
+       for (pad = CSI_SINK_PAD + 1; pad < CSI_NUM_PADS; pad++) {
+               struct v4l2_mbus_framefmt *outfmt;
 
-               priv->crop = sel->r;
-               /* Update the source format */
-               outfmt->width = sel->r.width;
-               outfmt->height = sel->r.height;
+               outfmt = __csi_get_fmt(priv, cfg, pad, sel->which);
+               outfmt->width = crop->width;
+               outfmt->height = crop->height;
        }
 
 out:
diff --git a/drivers/staging/media/imx/imx-media-vdic.c 
b/drivers/staging/media/imx/imx-media-vdic.c
index cd28dd8..0da45cf 100644
--- a/drivers/staging/media/imx/imx-media-vdic.c
+++ b/drivers/staging/media/imx/imx-media-vdic.c
@@ -561,39 +561,27 @@ static int vdic_get_fmt(struct v4l2_subdev *sd,
        return ret;
 }
 
-static int vdic_set_fmt(struct v4l2_subdev *sd,
-                       struct v4l2_subdev_pad_config *cfg,
-                       struct v4l2_subdev_format *sdformat)
+static void vdic_try_fmt(struct vdic_priv *priv,
+                        struct v4l2_subdev_pad_config *cfg,
+                        struct v4l2_subdev_format *sdformat,
+                        const struct imx_media_pixfmt **cc)
 {
-       struct vdic_priv *priv = v4l2_get_subdevdata(sd);
-       const struct imx_media_pixfmt *cc;
        struct v4l2_mbus_framefmt *infmt;
-       int ret = 0;
-       u32 code;
 
-       if (sdformat->pad >= VDIC_NUM_PADS)
-               return -EINVAL;
-
-       mutex_lock(&priv->lock);
+       *cc = imx_media_find_ipu_format(sdformat->format.code, CS_SEL_YUV);
+       if (!*cc) {
+               u32 code;
 
-       if (priv->stream_on) {
-               ret = -EBUSY;
-               goto out;
-       }
-
-       cc = imx_media_find_ipu_format(sdformat->format.code, CS_SEL_YUV);
-       if (!cc) {
                imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
-               cc = imx_media_find_ipu_format(code, CS_SEL_YUV);
-               sdformat->format.code = cc->codes[0];
+               *cc = imx_media_find_ipu_format(code, CS_SEL_YUV);
+               sdformat->format.code = (*cc)->codes[0];
        }
 
        switch (sdformat->pad) {
        case VDIC_SRC_PAD_DIRECT:
                infmt = __vdic_get_fmt(priv, cfg, priv->active_input_pad,
                                       sdformat->which);
-               sdformat->format.width = infmt->width;
-               sdformat->format.height = infmt->height;
+               sdformat->format = *infmt;
                /* output is always progressive! */
                sdformat->format.field = V4L2_FIELD_NONE;
                break;
@@ -608,18 +596,54 @@ static int vdic_set_fmt(struct v4l2_subdev *sd,
                if (!V4L2_FIELD_HAS_BOTH(sdformat->format.field))
                        sdformat->format.field = V4L2_FIELD_SEQ_TB;
                break;
-       default:
-               ret = -EINVAL;
+       }
+}
+
+static int vdic_set_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_subdev_pad_config *cfg,
+                       struct v4l2_subdev_format *sdformat)
+{
+       struct vdic_priv *priv = v4l2_get_subdevdata(sd);
+       const struct imx_media_pixfmt *cc;
+       struct v4l2_mbus_framefmt *fmt;
+       int ret = 0;
+
+       if (sdformat->pad >= VDIC_NUM_PADS)
+               return -EINVAL;
+
+       mutex_lock(&priv->lock);
+
+       if (priv->stream_on) {
+               ret = -EBUSY;
                goto out;
        }
 
-       if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
-               cfg->try_fmt = sdformat->format;
-       } else {
-               priv->format_mbus[sdformat->pad] = sdformat->format;
-               priv->cc[sdformat->pad] = cc;
+       vdic_try_fmt(priv, cfg, sdformat, &cc);
+
+       fmt = __vdic_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+       *fmt = sdformat->format;
+
+       /* propagate format to source pad */
+       if (sdformat->pad == VDIC_SINK_PAD_DIRECT ||
+           sdformat->pad == VDIC_SINK_PAD_IDMAC) {
+               const struct imx_media_pixfmt *outcc;
+               struct v4l2_mbus_framefmt *outfmt;
+               struct v4l2_subdev_format format;
+
+               format.pad = VDIC_SRC_PAD_DIRECT;
+               format.which = sdformat->which;
+               format.format = sdformat->format;
+               vdic_try_fmt(priv, cfg, &format, &outcc);
+
+               outfmt = __vdic_get_fmt(priv, cfg, VDIC_SRC_PAD_DIRECT,
+                                       sdformat->which);
+               *outfmt = format.format;
+               if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+                       priv->cc[VDIC_SRC_PAD_DIRECT] = outcc;
        }
 
+       if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               priv->cc[sdformat->pad] = cc;
 out:
        mutex_unlock(&priv->lock);
        return ret;
-- 
2.7.4

Reply via email to