Skip to content

Commit

Permalink
[media] omap3isp: resizer: Replace the crop API by the selection API
Browse files Browse the repository at this point in the history
Support for the legacy crop API is emulated in the subdev core.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Laurent Pinchart authored and Mauro Carvalho Chehab committed May 8, 2012
1 parent 684c8e2 commit 433f75a
Showing 1 changed file with 88 additions and 50 deletions.
138 changes: 88 additions & 50 deletions drivers/media/video/omap3isp/ispresizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1187,32 +1187,6 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
return 0;
}

/*
* resizer_g_crop - handle get crop subdev operation
* @sd : pointer to v4l2 subdev structure
* @pad : subdev pad
* @crop : pointer to crop structure
* @which : active or try format
* return zero
*/
static int resizer_g_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
struct v4l2_subdev_crop *crop)
{
struct isp_res_device *res = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format;
struct resizer_ratio ratio;

/* Only sink pad has crop capability */
if (crop->pad != RESZ_PAD_SINK)
return -EINVAL;

format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE, crop->which);
crop->rect = *__resizer_get_crop(res, fh, crop->which);
resizer_calc_ratios(res, &crop->rect, format, &ratio);

return 0;
}

/*
* resizer_try_crop - mangles crop parameters.
*/
Expand All @@ -1223,7 +1197,7 @@ static void resizer_try_crop(const struct v4l2_mbus_framefmt *sink,
const unsigned int spv = DEFAULT_PHASE;
const unsigned int sph = DEFAULT_PHASE;

/* Crop rectangle is constrained to the output size so that zoom ratio
/* Crop rectangle is constrained by the output size so that zoom ratio
* cannot exceed +/-4.0.
*/
unsigned int min_width =
Expand All @@ -1248,51 +1222,115 @@ static void resizer_try_crop(const struct v4l2_mbus_framefmt *sink,
}

/*
* resizer_s_crop - handle set crop subdev operation
* @sd : pointer to v4l2 subdev structure
* @pad : subdev pad
* @crop : pointer to crop structure
* @which : active or try format
* return -EINVAL or zero when succeed
* resizer_get_selection - Retrieve a selection rectangle on a pad
* @sd: ISP resizer V4L2 subdevice
* @fh: V4L2 subdev file handle
* @sel: Selection rectangle
*
* The only supported rectangles are the crop rectangles on the sink pad.
*
* Return 0 on success or a negative error code otherwise.
*/
static int resizer_s_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
struct v4l2_subdev_crop *crop)
static int resizer_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh,
struct v4l2_subdev_selection *sel)
{
struct isp_res_device *res = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format_source;
struct v4l2_mbus_framefmt *format_sink;
struct resizer_ratio ratio;

if (sel->pad != RESZ_PAD_SINK)
return -EINVAL;

format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
sel->which);
format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
sel->which);

switch (sel->target) {
case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS:
sel->r.left = 0;
sel->r.top = 0;
sel->r.width = INT_MAX;
sel->r.height = INT_MAX;

resizer_try_crop(format_sink, format_source, &sel->r);
resizer_calc_ratios(res, &sel->r, format_source, &ratio);
break;

case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
sel->r = *__resizer_get_crop(res, fh, sel->which);
resizer_calc_ratios(res, &sel->r, format_source, &ratio);
break;

default:
return -EINVAL;
}

return 0;
}

/*
* resizer_set_selection - Set a selection rectangle on a pad
* @sd: ISP resizer V4L2 subdevice
* @fh: V4L2 subdev file handle
* @sel: Selection rectangle
*
* The only supported rectangle is the actual crop rectangle on the sink pad.
*
* FIXME: This function currently behaves as if the KEEP_CONFIG selection flag
* was always set.
*
* Return 0 on success or a negative error code otherwise.
*/
static int resizer_set_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh,
struct v4l2_subdev_selection *sel)
{
struct isp_res_device *res = v4l2_get_subdevdata(sd);
struct isp_device *isp = to_isp_device(res);
struct v4l2_mbus_framefmt *format_sink, *format_source;
struct resizer_ratio ratio;

/* Only sink pad has crop capability */
if (crop->pad != RESZ_PAD_SINK)
if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL ||
sel->pad != RESZ_PAD_SINK)
return -EINVAL;

format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
crop->which);
sel->which);
format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
crop->which);
sel->which);

dev_dbg(isp->dev, "%s: L=%d,T=%d,W=%d,H=%d,which=%d\n", __func__,
crop->rect.left, crop->rect.top, crop->rect.width,
crop->rect.height, crop->which);
sel->r.left, sel->r.top, sel->r.width, sel->r.height,
sel->which);

dev_dbg(isp->dev, "%s: input=%dx%d, output=%dx%d\n", __func__,
format_sink->width, format_sink->height,
format_source->width, format_source->height);

resizer_try_crop(format_sink, format_source, &crop->rect);
*__resizer_get_crop(res, fh, crop->which) = crop->rect;
resizer_calc_ratios(res, &crop->rect, format_source, &ratio);
/* Clamp the crop rectangle to the bounds, and then mangle it further to
* fulfill the TRM equations. Store the clamped but otherwise unmangled
* rectangle to avoid cropping the input multiple times: when an
* application sets the output format, the current crop rectangle is
* mangled during crop rectangle computation, which would lead to a new,
* smaller input crop rectangle every time the output size is set if we
* stored the mangled rectangle.
*/
resizer_try_crop(format_sink, format_source, &sel->r);
*__resizer_get_crop(res, fh, sel->which) = sel->r;
resizer_calc_ratios(res, &sel->r, format_source, &ratio);

if (crop->which == V4L2_SUBDEV_FORMAT_TRY)
if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
return 0;

res->ratio = ratio;
res->crop.active = crop->rect;
res->crop.active = sel->r;

/*
* s_crop can be called while streaming is on. In this case
* the crop values will be set in the next IRQ.
* set_selection can be called while streaming is on. In this case the
* crop values will be set in the next IRQ.
*/
if (res->state != ISP_PIPELINE_STREAM_STOPPED)
res->applycrop = 1;
Expand Down Expand Up @@ -1530,8 +1568,8 @@ static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
.enum_frame_size = resizer_enum_frame_size,
.get_fmt = resizer_get_format,
.set_fmt = resizer_set_format,
.get_crop = resizer_g_crop,
.set_crop = resizer_s_crop,
.get_selection = resizer_get_selection,
.set_selection = resizer_set_selection,
};

/* subdev operations */
Expand Down

0 comments on commit 433f75a

Please sign in to comment.