[media] exynos4-is: Refactor vidioc_s_fmt, vidioc_try_fmt handlers
Remove duplicated code in the vidioc_try_fmt and vidioc_s_fmt handlers. This is a pre-requsite to allow successful fimc.capture video open even if its corresponding media entities are not linked into a complete pipeline. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
f525e176f9
commit
7536b4240f
|
@ -503,9 +503,6 @@ static int fimc_capture_open(struct file *file)
|
|||
|
||||
ret = fimc_pipeline_call(ve, open, &ve->vdev.entity, true);
|
||||
|
||||
if (ret == 0)
|
||||
ret = fimc_capture_set_default_format(fimc);
|
||||
|
||||
if (ret == 0 && vc->user_subdev_api && vc->inh_sensor_ctrls) {
|
||||
/*
|
||||
* Recreate controls of the the video node to drop
|
||||
|
@ -522,6 +519,9 @@ static int fimc_capture_open(struct file *file)
|
|||
|
||||
fimc_md_graph_unlock(ve);
|
||||
|
||||
if (ret == 0)
|
||||
ret = fimc_capture_set_default_format(fimc);
|
||||
|
||||
if (ret < 0) {
|
||||
clear_bit(ST_CAPT_BUSY, &fimc->state);
|
||||
pm_runtime_put_sync(&fimc->pdev->dev);
|
||||
|
@ -916,55 +916,83 @@ static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
|
||||
struct v4l2_format *f)
|
||||
/*
|
||||
* Try or set format on the fimc.X.capture video node and additionally
|
||||
* on the whole pipeline if @try is false.
|
||||
* Locking: the caller must _not_ hold the graph mutex.
|
||||
*/
|
||||
static int __video_try_or_set_format(struct fimc_dev *fimc,
|
||||
struct v4l2_format *f, bool try,
|
||||
struct fimc_fmt **inp_fmt,
|
||||
struct fimc_fmt **out_fmt)
|
||||
{
|
||||
struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
|
||||
struct fimc_dev *fimc = video_drvdata(file);
|
||||
struct fimc_ctx *ctx = fimc->vid_cap.ctx;
|
||||
struct exynos_video_entity *ve = &fimc->vid_cap.ve;
|
||||
struct v4l2_mbus_framefmt mf;
|
||||
struct v4l2_subdev *sensor;
|
||||
struct fimc_fmt *ffmt = NULL;
|
||||
struct fimc_vid_cap *vc = &fimc->vid_cap;
|
||||
struct exynos_video_entity *ve = &vc->ve;
|
||||
struct fimc_ctx *ctx = vc->ctx;
|
||||
unsigned int width = 0, height = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* Pre-configure format at the camera input interface, for JPEG only */
|
||||
if (fimc_jpeg_fourcc(pix->pixelformat)) {
|
||||
fimc_capture_try_format(ctx, &pix->width, &pix->height,
|
||||
NULL, &pix->pixelformat,
|
||||
FIMC_SD_PAD_SINK_CAM);
|
||||
ctx->s_frame.f_width = pix->width;
|
||||
ctx->s_frame.f_height = pix->height;
|
||||
if (try) {
|
||||
width = pix->width;
|
||||
height = pix->height;
|
||||
} else {
|
||||
ctx->s_frame.f_width = pix->width;
|
||||
ctx->s_frame.f_height = pix->height;
|
||||
}
|
||||
}
|
||||
ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
|
||||
NULL, &pix->pixelformat,
|
||||
FIMC_SD_PAD_SOURCE);
|
||||
if (!ffmt)
|
||||
|
||||
/* Try the format at the scaler and the DMA output */
|
||||
*out_fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
|
||||
NULL, &pix->pixelformat,
|
||||
FIMC_SD_PAD_SOURCE);
|
||||
if (*out_fmt == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (!fimc->vid_cap.user_subdev_api) {
|
||||
mf.width = pix->width;
|
||||
mf.height = pix->height;
|
||||
mf.code = ffmt->mbus_code;
|
||||
|
||||
fimc_md_graph_lock(ve);
|
||||
fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
|
||||
fimc_md_graph_unlock(ve);
|
||||
|
||||
pix->width = mf.width;
|
||||
pix->height = mf.height;
|
||||
if (ffmt)
|
||||
pix->pixelformat = ffmt->fourcc;
|
||||
/* Restore image width/height for JPEG (no resizing supported). */
|
||||
if (try && fimc_jpeg_fourcc(pix->pixelformat)) {
|
||||
pix->width = width;
|
||||
pix->height = height;
|
||||
}
|
||||
|
||||
fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
|
||||
/* Try to match format at the host and the sensor */
|
||||
if (!vc->user_subdev_api) {
|
||||
struct v4l2_mbus_framefmt mbus_fmt;
|
||||
struct v4l2_mbus_framefmt *mf;
|
||||
|
||||
mf = try ? &mbus_fmt : &fimc->vid_cap.ci_fmt;
|
||||
|
||||
mf->code = (*out_fmt)->mbus_code;
|
||||
mf->width = pix->width;
|
||||
mf->height = pix->height;
|
||||
|
||||
fimc_md_graph_lock(ve);
|
||||
ret = fimc_pipeline_try_format(ctx, mf, inp_fmt, try);
|
||||
fimc_md_graph_unlock(ve);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
pix->width = mf->width;
|
||||
pix->height = mf->height;
|
||||
}
|
||||
|
||||
fimc_adjust_mplane_format(*out_fmt, pix->width, pix->height, pix);
|
||||
|
||||
if ((*out_fmt)->flags & FMT_FLAGS_COMPRESSED) {
|
||||
struct v4l2_subdev *sensor;
|
||||
|
||||
if (ffmt->flags & FMT_FLAGS_COMPRESSED) {
|
||||
fimc_md_graph_lock(ve);
|
||||
|
||||
sensor = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR);
|
||||
if (sensor)
|
||||
fimc_get_sensor_frame_desc(sensor, pix->plane_fmt,
|
||||
ffmt->memplanes, true);
|
||||
(*out_fmt)->memplanes, try);
|
||||
else
|
||||
ret = -EPIPE;
|
||||
|
||||
|
@ -974,6 +1002,15 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct fimc_dev *fimc = video_drvdata(file);
|
||||
struct fimc_fmt *out_fmt = NULL, *inp_fmt = NULL;
|
||||
|
||||
return __video_try_or_set_format(fimc, f, true, &inp_fmt, &out_fmt);
|
||||
}
|
||||
|
||||
static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx,
|
||||
enum fimc_color_fmt color)
|
||||
{
|
||||
|
@ -991,58 +1028,23 @@ static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx,
|
|||
static int __fimc_capture_set_format(struct fimc_dev *fimc,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct fimc_ctx *ctx = fimc->vid_cap.ctx;
|
||||
struct fimc_vid_cap *vc = &fimc->vid_cap;
|
||||
struct fimc_ctx *ctx = vc->ctx;
|
||||
struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
|
||||
struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.ci_fmt;
|
||||
struct fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe);
|
||||
struct fimc_frame *ff = &ctx->d_frame;
|
||||
struct fimc_fmt *s_fmt = NULL;
|
||||
struct fimc_fmt *inp_fmt = NULL;
|
||||
int ret, i;
|
||||
|
||||
if (vb2_is_busy(&fimc->vid_cap.vbq))
|
||||
return -EBUSY;
|
||||
|
||||
/* Pre-configure format at camera interface input, for JPEG only */
|
||||
if (fimc_jpeg_fourcc(pix->pixelformat)) {
|
||||
fimc_capture_try_format(ctx, &pix->width, &pix->height,
|
||||
NULL, &pix->pixelformat,
|
||||
FIMC_SD_PAD_SINK_CAM);
|
||||
ctx->s_frame.f_width = pix->width;
|
||||
ctx->s_frame.f_height = pix->height;
|
||||
}
|
||||
/* Try the format at the scaler and the DMA output */
|
||||
ff->fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
|
||||
NULL, &pix->pixelformat,
|
||||
FIMC_SD_PAD_SOURCE);
|
||||
if (!ff->fmt)
|
||||
return -EINVAL;
|
||||
ret = __video_try_or_set_format(fimc, f, false, &inp_fmt, &ff->fmt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Update RGB Alpha control state and value range */
|
||||
fimc_alpha_ctrl_update(ctx);
|
||||
|
||||
/* Try to match format at the host and the sensor */
|
||||
if (!fimc->vid_cap.user_subdev_api) {
|
||||
mf->code = ff->fmt->mbus_code;
|
||||
mf->width = pix->width;
|
||||
mf->height = pix->height;
|
||||
ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pix->width = mf->width;
|
||||
pix->height = mf->height;
|
||||
}
|
||||
|
||||
fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
|
||||
|
||||
if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
|
||||
ret = fimc_get_sensor_frame_desc(p->subdevs[IDX_SENSOR],
|
||||
pix->plane_fmt, ff->fmt->memplanes,
|
||||
true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ff->fmt->memplanes; i++) {
|
||||
ff->bytesperline[i] = pix->plane_fmt[i].bytesperline;
|
||||
ff->payload[i] = pix->plane_fmt[i].sizeimage;
|
||||
|
@ -1056,8 +1058,8 @@ static int __fimc_capture_set_format(struct fimc_dev *fimc,
|
|||
fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color);
|
||||
|
||||
/* Reset cropping and set format at the camera interface input */
|
||||
if (!fimc->vid_cap.user_subdev_api) {
|
||||
ctx->s_frame.fmt = s_fmt;
|
||||
if (!vc->user_subdev_api) {
|
||||
ctx->s_frame.fmt = inp_fmt;
|
||||
set_frame_bounds(&ctx->s_frame, pix->width, pix->height);
|
||||
set_frame_crop(&ctx->s_frame, 0, 0, pix->width, pix->height);
|
||||
}
|
||||
|
@ -1069,18 +1071,8 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
|
|||
struct v4l2_format *f)
|
||||
{
|
||||
struct fimc_dev *fimc = video_drvdata(file);
|
||||
int ret;
|
||||
|
||||
fimc_md_graph_lock(&fimc->vid_cap.ve);
|
||||
/*
|
||||
* The graph is walked within __fimc_capture_set_format() to set
|
||||
* the format at subdevs thus the graph mutex needs to be held at
|
||||
* this point.
|
||||
*/
|
||||
ret = __fimc_capture_set_format(fimc, f);
|
||||
|
||||
fimc_md_graph_unlock(&fimc->vid_cap.ve);
|
||||
return ret;
|
||||
return __fimc_capture_set_format(fimc, f);
|
||||
}
|
||||
|
||||
static int fimc_cap_enum_input(struct file *file, void *priv,
|
||||
|
|
Loading…
Reference in New Issue