summaryrefslogtreecommitdiff
path: root/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-12-13 11:36:58 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2022-12-13 11:36:58 -0800
commitcdb9d3537711939e4d8fd0de2889c966f88346eb (patch)
tree2a118e0930d3e08c6303b579e89f0df388cba4e6 /drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c
parent102f9d3d455870844c47b82322c2dfc0a35eb745 (diff)
parent3178804c64ef7c8c87a53cd5bba0b2942dd64fec (diff)
Merge tag 'media/v6.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - DVB core changes to avoid refcount troubles and UAF - DVB API/core has gained support for DVB-C2 and DVB-S2X - New sensor drivers: ov08x40, ov4689.c, st-vgxy61 and tc358746.c - Removal of an unused sensor driver: s5k4ecgx - Move microchip_csi2dc to a new directory, named after the manufacturer - Add media controller support to Microship drivers - Old Atmel/Microship drivers that don't use media controler got moved to staging - New drivers added for Renesas RZ/G2L CRU and MIPI CSI-2 support - Allwinner A31 camera sensor driver code was now split into a bridge and a separate processor driver - Added a virtual stateless decoder driver in order to test core support for stateless drivers and test userspace apps using it - removed platform-based support for ov9650, as this is not used anymore - atomisp now uses videobuf2 and supports normal mmap mode - the imx7-media-csi driver got promoted from staging - rcar-vin driver has gained support for gen3 UDS (Up Down Scaler) - most i2c drivers now use I2C .probe_new() kAPI - lots of drivers fixes, cleanups and improvements * tag 'media/v6.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (544 commits) media: s5c73m3: Switch to GPIO descriptors media: i2c: s5k5baf: switch to using gpiod API media: i2c: s5k6a3: switch to using gpiod API media: imx: remove code for non-existing config IMX_GPT_ICAP media: si470x: Fix use-after-free in si470x_int_in_callback() media: staging: stkwebcam: Restore MEDIA_{USB,CAMERA}_SUPPORT dependencies media: coda: Add check for kmalloc media: coda: Add check for dcoda_iram_alloc dt-bindings: media: s5c73m3: Fix reset-gpio descriptor media: dt-bindings: allwinner: h6-vpu-g2: Add IOMMU reference property media: s5k4ecgx: Delete driver media: s5k4ecgx: Switch to GPIO descriptors media: Switch to use dev_err_probe() helper headers: Remove some left-over license text in include/uapi/linux/v4l2-* headers: Remove some left-over license text in include/uapi/linux/dvb/ media: usb: pwc-uncompress: Use flex array destination for memcpy() media: s5p-mfc: Fix to handle reference queue during finishing media: s5p-mfc: Clear workbit to handle error condition media: s5p-mfc: Fix in register read and write for H264 media: imx: Use get_mbus_config instead of parsing upstream DT endpoints ...
Diffstat (limited to 'drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c')
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c93
1 files changed, 74 insertions, 19 deletions
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c
index 576059f9bbe3..073f70c6ac68 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c
@@ -226,10 +226,10 @@ static int rvin_reset_format(struct rvin_dev *vin)
v4l2_fill_pix_format(&vin->format, &fmt.format);
- vin->src_rect.top = 0;
- vin->src_rect.left = 0;
- vin->src_rect.width = vin->format.width;
- vin->src_rect.height = vin->format.height;
+ vin->crop.top = 0;
+ vin->crop.left = 0;
+ vin->crop.width = vin->format.width;
+ vin->crop.height = vin->format.height;
/* Make use of the hardware interlacer by default. */
if (vin->format.field == V4L2_FIELD_ALTERNATE) {
@@ -239,8 +239,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
rvin_format_align(vin, &vin->format);
- vin->crop = vin->src_rect;
-
vin->compose.top = 0;
vin->compose.left = 0;
vin->compose.width = vin->format.width;
@@ -349,7 +347,6 @@ static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
v4l2_rect_map_inside(&vin->crop, &src_rect);
v4l2_rect_map_inside(&vin->compose, &fmt_rect);
- vin->src_rect = src_rect;
return 0;
}
@@ -428,10 +425,60 @@ static int rvin_enum_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
}
+static int rvin_remote_rectangle(struct rvin_dev *vin, struct v4l2_rect *rect)
+{
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_subdev *sd;
+ unsigned int index;
+ int ret;
+
+ if (vin->info->use_mc) {
+ struct media_pad *pad = media_pad_remote_pad_first(&vin->pad);
+
+ if (!pad)
+ return -EINVAL;
+
+ sd = media_entity_to_v4l2_subdev(pad->entity);
+ index = pad->index;
+ } else {
+ sd = vin_to_source(vin);
+ index = vin->parallel.source_pad;
+ }
+
+ fmt.pad = index;
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
+ if (ret)
+ return ret;
+
+ rect->left = rect->top = 0;
+ rect->width = fmt.format.width;
+ rect->height = fmt.format.height;
+
+ if (fmt.format.field == V4L2_FIELD_ALTERNATE) {
+ switch (vin->format.field) {
+ case V4L2_FIELD_INTERLACED_TB:
+ case V4L2_FIELD_INTERLACED_BT:
+ case V4L2_FIELD_INTERLACED:
+ case V4L2_FIELD_SEQ_TB:
+ case V4L2_FIELD_SEQ_BT:
+ rect->height *= 2;
+ break;
+ }
+ }
+
+ return 0;
+}
+
static int rvin_g_selection(struct file *file, void *fh,
struct v4l2_selection *s)
{
struct rvin_dev *vin = video_drvdata(file);
+ int ret;
+
+ if (!vin->scaler)
+ return -ENOIOCTLCMD;
if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -439,9 +486,10 @@ static int rvin_g_selection(struct file *file, void *fh,
switch (s->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
case V4L2_SEL_TGT_CROP_DEFAULT:
- s->r.left = s->r.top = 0;
- s->r.width = vin->src_rect.width;
- s->r.height = vin->src_rect.height;
+ ret = rvin_remote_rectangle(vin, &s->r);
+ if (ret)
+ return ret;
+
break;
case V4L2_SEL_TGT_CROP:
s->r = vin->crop;
@@ -473,6 +521,10 @@ static int rvin_s_selection(struct file *file, void *fh,
.width = 6,
.height = 2,
};
+ int ret;
+
+ if (!vin->scaler)
+ return -ENOIOCTLCMD;
if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -482,23 +534,23 @@ static int rvin_s_selection(struct file *file, void *fh,
switch (s->target) {
case V4L2_SEL_TGT_CROP:
/* Can't crop outside of source input */
- max_rect.top = max_rect.left = 0;
- max_rect.width = vin->src_rect.width;
- max_rect.height = vin->src_rect.height;
+ ret = rvin_remote_rectangle(vin, &max_rect);
+ if (ret)
+ return ret;
+
v4l2_rect_map_inside(&r, &max_rect);
- v4l_bound_align_image(&r.width, 6, vin->src_rect.width, 0,
- &r.height, 2, vin->src_rect.height, 0, 0);
+ v4l_bound_align_image(&r.width, 6, max_rect.width, 0,
+ &r.height, 2, max_rect.height, 0, 0);
- r.top = clamp_t(s32, r.top, 0,
- vin->src_rect.height - r.height);
- r.left = clamp_t(s32, r.left, 0, vin->src_rect.width - r.width);
+ r.top = clamp_t(s32, r.top, 0, max_rect.height - r.height);
+ r.left = clamp_t(s32, r.left, 0, max_rect.width - r.width);
vin->crop = s->r = r;
vin_dbg(vin, "Cropped %dx%d@%d:%d of %dx%d\n",
r.width, r.height, r.left, r.top,
- vin->src_rect.width, vin->src_rect.height);
+ max_rect.width, max_rect.height);
break;
case V4L2_SEL_TGT_COMPOSE:
/* Make sure compose rect fits inside output format */
@@ -866,6 +918,9 @@ static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = {
.vidioc_s_fmt_vid_cap = rvin_mc_s_fmt_vid_cap,
.vidioc_enum_fmt_vid_cap = rvin_enum_fmt_vid_cap,
+ .vidioc_g_selection = rvin_g_selection,
+ .vidioc_s_selection = rvin_s_selection,
+
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_querybuf = vb2_ioctl_querybuf,