]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
[media] s5p-fimc: Improved pipeline try format routine
authorSylwester Nawrocki <s.nawrocki@samsung.com>
Mon, 3 Dec 2012 09:24:32 +0000 (06:24 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 21 Dec 2012 15:58:31 +0000 (13:58 -0200)
Make the pipeline try format routine more generic to support any
number of subdevs in the pipeline, rather than hard coding it for
only a sensor, MIPI-CSIS and FIMC subdevs and the FIMC video node.

Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/platform/s5p-fimc/fimc-capture.c

index 50c0da9c788b881cf58afa42d51a4d398f2e495f..95e6a7820b5e3e91aad51aec83ebbc13e5c31b2b 100644 (file)
@@ -793,6 +793,21 @@ static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv,
        return 0;
 }
 
+static struct media_entity *fimc_pipeline_get_head(struct media_entity *me)
+{
+       struct media_pad *pad = &me->pads[0];
+
+       while (!(pad->flags & MEDIA_PAD_FL_SOURCE)) {
+               pad = media_entity_remote_source(pad);
+               if (!pad)
+                       break;
+               me = pad->entity;
+               pad = &me->pads[0];
+       }
+
+       return me;
+}
+
 /**
  * fimc_pipeline_try_format - negotiate and/or set formats at pipeline
  *                            elements
@@ -808,19 +823,23 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
 {
        struct fimc_dev *fimc = ctx->fimc_dev;
        struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
-       struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
        struct v4l2_subdev_format sfmt;
        struct v4l2_mbus_framefmt *mf = &sfmt.format;
-       struct fimc_fmt *ffmt = NULL;
-       int ret, i = 0;
+       struct media_entity *me;
+       struct fimc_fmt *ffmt;
+       struct media_pad *pad;
+       int ret, i = 1;
+       u32 fcc;
 
        if (WARN_ON(!sd || !tfmt))
                return -EINVAL;
 
        memset(&sfmt, 0, sizeof(sfmt));
        sfmt.format = *tfmt;
-
        sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY;
+
+       me = fimc_pipeline_get_head(&sd->entity);
+
        while (1) {
                ffmt = fimc_find_format(NULL, mf->code != 0 ? &mf->code : NULL,
                                        FMT_FLAGS_CAM, i++);
@@ -833,40 +852,52 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
                }
                mf->code = tfmt->code = ffmt->mbus_code;
 
-               ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt);
-               if (ret)
-                       return ret;
-               if (mf->code != tfmt->code) {
-                       mf->code = 0;
-                       continue;
-               }
-               if (mf->width != tfmt->width || mf->height != tfmt->height) {
-                       u32 fcc = ffmt->fourcc;
-                       tfmt->width  = mf->width;
-                       tfmt->height = mf->height;
-                       ffmt = fimc_capture_try_format(ctx,
-                                              &tfmt->width, &tfmt->height,
-                                              NULL, &fcc, FIMC_SD_PAD_SOURCE);
-                       if (ffmt && ffmt->mbus_code)
-                               mf->code = ffmt->mbus_code;
-                       if (mf->width != tfmt->width ||
-                           mf->height != tfmt->height)
-                               continue;
-                       tfmt->code = mf->code;
+               /* set format on all pipeline subdevs */
+               while (me != &fimc->vid_cap.subdev.entity) {
+                       sd = media_entity_to_v4l2_subdev(me);
+
+                       sfmt.pad = 0;
+                       ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt);
+                       if (ret)
+                               return ret;
+
+                       if (me->pads[0].flags & MEDIA_PAD_FL_SINK) {
+                               sfmt.pad = me->num_pads - 1;
+                               mf->code = tfmt->code;
+                               ret = v4l2_subdev_call(sd, pad, set_fmt, NULL,
+                                                                       &sfmt);
+                               if (ret)
+                                       return ret;
+                       }
+
+                       pad = media_entity_remote_source(&me->pads[sfmt.pad]);
+                       if (!pad)
+                               return -EINVAL;
+                       me = pad->entity;
                }
-               if (csis)
-                       ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt);
 
-               if (mf->code == tfmt->code &&
-                   mf->width == tfmt->width && mf->height == tfmt->height)
-                       break;
+               if (mf->code != tfmt->code)
+                       continue;
+
+               fcc = ffmt->fourcc;
+               tfmt->width  = mf->width;
+               tfmt->height = mf->height;
+               ffmt = fimc_capture_try_format(ctx, &tfmt->width, &tfmt->height,
+                                       NULL, &fcc, FIMC_SD_PAD_SINK);
+               ffmt = fimc_capture_try_format(ctx, &tfmt->width, &tfmt->height,
+                                       NULL, &fcc, FIMC_SD_PAD_SOURCE);
+               if (ffmt && ffmt->mbus_code)
+                       mf->code = ffmt->mbus_code;
+               if (mf->width != tfmt->width || mf->height != tfmt->height)
+                       continue;
+               tfmt->code = mf->code;
+               break;
        }
 
        if (fmt_id && ffmt)
                *fmt_id = ffmt;
        *tfmt = *mf;
 
-       dbg("code: 0x%x, %dx%d, %p", mf->code, mf->width, mf->height, ffmt);
        return 0;
 }