diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/platform/rcar-vin/rcar-v4l2.c | 120 | ||||
-rw-r--r-- | drivers/media/platform/rcar-vin/rcar-vin.h | 14 |
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) |