summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/platform/rcar-vin/rcar-v4l2.c120
-rw-r--r--drivers/media/platform/rcar-vin/rcar-vin.h14
2 files changed, 53 insertions, 81 deletions
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 4a77bb4bb7c6..84cad5d8c93a 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -87,7 +87,7 @@ static u32 rvin_format_sizeimage(struct v4l2_pix_format *pix)
return pix->bytesperline * pix->height;
}
-static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
+static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
{
u32 walign;
@@ -130,75 +130,63 @@ static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
vin_dbg(vin, "Format %ux%u bpl: %u size: %u\n",
pix->width, pix->height, pix->bytesperline, pix->sizeimage);
-
- return 0;
}
/* -----------------------------------------------------------------------------
* V4L2
*/
-static void rvin_reset_crop_compose(struct rvin_dev *vin)
-{
- vin->crop.top = vin->crop.left = 0;
- vin->crop.width = vin->source.width;
- vin->crop.height = vin->source.height;
-
- vin->compose.top = vin->compose.left = 0;
- vin->compose.width = vin->format.width;
- vin->compose.height = vin->format.height;
-}
-
static int rvin_reset_format(struct rvin_dev *vin)
{
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .pad = vin->digital->source_pad,
};
- struct v4l2_mbus_framefmt *mf = &fmt.format;
int ret;
- fmt.pad = vin->digital->source_pad;
-
ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
if (ret)
return ret;
- vin->format.width = mf->width;
- vin->format.height = mf->height;
- vin->format.colorspace = mf->colorspace;
- vin->format.field = mf->field;
+ v4l2_fill_pix_format(&vin->format, &fmt.format);
+
+ rvin_format_align(vin, &vin->format);
- rvin_reset_crop_compose(vin);
+ vin->source.top = 0;
+ vin->source.left = 0;
+ vin->source.width = vin->format.width;
+ vin->source.height = vin->format.height;
- vin->format.bytesperline = rvin_format_bytesperline(&vin->format);
- vin->format.sizeimage = rvin_format_sizeimage(&vin->format);
+ vin->crop = vin->source;
+ vin->compose = vin->source;
return 0;
}
-static int __rvin_try_format_source(struct rvin_dev *vin,
- u32 which,
- struct v4l2_pix_format *pix,
- struct rvin_source_fmt *source)
+static int rvin_try_format(struct rvin_dev *vin, u32 which,
+ struct v4l2_pix_format *pix,
+ struct v4l2_rect *crop, struct v4l2_rect *compose)
{
- struct v4l2_subdev *sd;
+ struct v4l2_subdev *sd = vin_to_source(vin);
struct v4l2_subdev_pad_config *pad_cfg;
struct v4l2_subdev_format format = {
.which = which,
+ .pad = vin->digital->source_pad,
};
enum v4l2_field field;
u32 width, height;
int ret;
- sd = vin_to_source(vin);
-
- v4l2_fill_mbus_format(&format.format, pix, vin->digital->code);
-
pad_cfg = v4l2_subdev_alloc_pad_config(sd);
if (pad_cfg == NULL)
return -ENOMEM;
- format.pad = vin->digital->source_pad;
+ if (!rvin_format_from_pixel(pix->pixelformat) ||
+ (vin->info->model == RCAR_M1 &&
+ pix->pixelformat == V4L2_PIX_FMT_XBGR32))
+ pix->pixelformat = RVIN_DEFAULT_FORMAT;
+
+ v4l2_fill_mbus_format(&format.format, pix, vin->digital->code);
/* Allow the video device to override field and to scale */
field = pix->field;
@@ -211,8 +199,19 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
v4l2_fill_pix_format(pix, &format.format);
- source->width = pix->width;
- source->height = pix->height;
+ if (crop) {
+ crop->top = 0;
+ crop->left = 0;
+ crop->width = pix->width;
+ crop->height = pix->height;
+
+ /*
+ * If source is ALTERNATE the driver will use the VIN hardware
+ * to INTERLACE it. The crop height then needs to be doubled.
+ */
+ if (pix->field == V4L2_FIELD_ALTERNATE)
+ crop->height *= 2;
+ }
if (field != V4L2_FIELD_ANY)
pix->field = field;
@@ -220,32 +219,18 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
pix->width = width;
pix->height = height;
- vin_dbg(vin, "Source resolution: %ux%u\n", source->width,
- source->height);
+ rvin_format_align(vin, pix);
+ if (compose) {
+ compose->top = 0;
+ compose->left = 0;
+ compose->width = pix->width;
+ compose->height = pix->height;
+ }
done:
v4l2_subdev_free_pad_config(pad_cfg);
- return ret;
-}
-static int __rvin_try_format(struct rvin_dev *vin,
- u32 which,
- struct v4l2_pix_format *pix,
- struct rvin_source_fmt *source)
-{
- int ret;
-
- if (!rvin_format_from_pixel(pix->pixelformat) ||
- (vin->info->model == RCAR_M1 &&
- pix->pixelformat == V4L2_PIX_FMT_XBGR32))
- pix->pixelformat = RVIN_DEFAULT_FORMAT;
-
- /* Limit to source capabilities */
- ret = __rvin_try_format_source(vin, which, pix, source);
- if (ret)
- return ret;
-
- return rvin_format_align(vin, pix);
+ return 0;
}
static int rvin_querycap(struct file *file, void *priv,
@@ -264,33 +249,30 @@ static int rvin_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct rvin_dev *vin = video_drvdata(file);
- struct rvin_source_fmt source;
- return __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix,
- &source);
+ return rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix, NULL,
+ NULL);
}
static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct rvin_dev *vin = video_drvdata(file);
- struct rvin_source_fmt source;
+ struct v4l2_rect crop, compose;
int ret;
if (vb2_is_busy(&vin->queue))
return -EBUSY;
- ret = __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
- &source);
+ ret = rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
+ &crop, &compose);
if (ret)
return ret;
- vin->source.width = source.width;
- vin->source.height = source.height;
-
vin->format = f->fmt.pix;
-
- rvin_reset_crop_compose(vin);
+ vin->crop = crop;
+ vin->compose = compose;
+ vin->source = crop;
return 0;
}
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 1c91b774205a..e940366d7e8d 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -47,16 +47,6 @@ enum rvin_dma_state {
};
/**
- * struct rvin_source_fmt - Source information
- * @width: Width from source
- * @height: Height from source
- */
-struct rvin_source_fmt {
- u32 width;
- u32 height;
-};
-
-/**
* struct rvin_video_format - Data format stored in memory
* @fourcc: Pixelformat
* @bpp: Bytes per pixel
@@ -123,11 +113,11 @@ struct rvin_info {
* @sequence: V4L2 buffers sequence number
* @state: keeps track of operation state
*
- * @source: active format from the video source
* @format: active V4L2 pixel format
*
* @crop: active cropping
* @compose: active composing
+ * @source: active size of the video source
*/
struct rvin_dev {
struct device *dev;
@@ -151,11 +141,11 @@ struct rvin_dev {
unsigned int sequence;
enum rvin_dma_state state;
- struct rvin_source_fmt source;
struct v4l2_pix_format format;
struct v4l2_rect crop;
struct v4l2_rect compose;
+ struct v4l2_rect source;
};
#define vin_to_source(vin) ((vin)->digital->subdev)