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