|
@@ -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;
|
|
|
}
|
|
|
|