summaryrefslogtreecommitdiff
path: root/drivers/media/platform/ti-vpe/cal-video.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-09-01 20:34:52 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2021-09-01 20:34:52 +0300
commit835d31d319d9c8c4eb6cac074643360ba0ecab10 (patch)
tree824dc6286c3f34357de0a0c12d0311eca9a6da8d /drivers/media/platform/ti-vpe/cal-video.c
parent0d290223a6c77107b1c3988959e49279a8dafaba (diff)
parent9c3a0f285248899dfa81585bc5d5bc9ebdb8fead (diff)
downloadlinux-835d31d319d9c8c4eb6cac074643360ba0ecab10.tar.xz
Merge tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - new sensor drivers: imx335, imx412, ov9282 - new IR transmitter driver: meson-ir-tx - handro driver gained support for H.264 for Rockchip VDPU2 - imx gained support for i.MX8MQ - ti-vpe has gained support for other SoC variants - lots of cleanups, fixes, board additions and doc improvements * tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (195 commits) media: venus: venc: add support for V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM control media: venus: venc: Add support for intra-refresh period media: v4l2-ctrls: Add intra-refresh period control media: docs: ext-ctrls-codec: Document cyclic intra-refresh zero control value media: venus: helper: do not set constrained parameters for UBWC media: venus: venc: Fix potential null pointer dereference on pointer fmt media: venus: hfi: fix return value check in sys_get_prop_image_version() media: tegra-cec: Handle errors of clk_prepare_enable() media: cec-pin: rename timer overrun variables media: TDA1997x: report -ENOLINK after disconnecting HDMI source media: TDA1997x: fix tda1997x_query_dv_timings() return value media: Fix cosmetic error in TDA1997x driver media: v4l2-dv-timings.c: fix wrong condition in two for-loops media: imx: add a driver for i.MX8MQ mipi csi rx phy and controller media: dt-bindings: media: document the nxp,imx8mq-mipi-csi2 receiver phy and controller media: imx: imx7_mipi_csis: convert some switch cases to the default media: imx: imx7-media-csi: Fix buffer return upon stream start failure media: imx: imx7-media-csi: Don't set PIXEL_BIT in CSICR1 media: imx: imx7-media-csi: Set TWO_8BIT_SENSOR for >= 10-bit formats media: dt-bindings: media: nxp,imx7-csi: Add i.MX8MM support ...
Diffstat (limited to 'drivers/media/platform/ti-vpe/cal-video.c')
-rw-r--r--drivers/media/platform/ti-vpe/cal-video.c176
1 files changed, 128 insertions, 48 deletions
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 15fb5360cf13..7799da1cc261 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -102,8 +102,8 @@ static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
return NULL;
}
-static int cal_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
+static int cal_legacy_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@@ -128,7 +128,7 @@ static int __subdev_get_format(struct cal_ctx *ctx,
sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sd_fmt.pad = 0;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, get_fmt, NULL, &sd_fmt);
+ ret = v4l2_subdev_call(ctx->phy->source, pad, get_fmt, NULL, &sd_fmt);
if (ret)
return ret;
@@ -151,7 +151,7 @@ static int __subdev_set_format(struct cal_ctx *ctx,
sd_fmt.pad = 0;
*mbus_fmt = *fmt;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, set_fmt, NULL, &sd_fmt);
+ ret = v4l2_subdev_call(ctx->phy->source, pad, set_fmt, NULL, &sd_fmt);
if (ret)
return ret;
@@ -189,8 +189,8 @@ static void cal_calc_format_size(struct cal_ctx *ctx,
f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
}
-static int cal_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int cal_legacy_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@@ -216,7 +216,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
fse.code = fmtinfo->code;
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
for (fse.index = 0; ; fse.index++) {
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size,
+ ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size,
NULL, &fse);
if (ret)
break;
@@ -249,8 +249,8 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
-static int cal_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int cal_legacy_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct cal_ctx *ctx = video_drvdata(file);
struct vb2_queue *q = &ctx->vb_vidq;
@@ -266,7 +266,7 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
return -EBUSY;
}
- ret = cal_try_fmt_vid_cap(file, priv, f);
+ ret = cal_legacy_try_fmt_vid_cap(file, priv, f);
if (ret < 0)
return ret;
@@ -300,8 +300,8 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
-static int cal_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
+static int cal_legacy_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *fsize)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@@ -321,7 +321,7 @@ static int cal_enum_framesizes(struct file *file, void *fh,
fse.code = fmtinfo->code;
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL,
+ ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size, NULL,
&fse);
if (ret)
return ret;
@@ -337,8 +337,8 @@ static int cal_enum_framesizes(struct file *file, void *fh,
return 0;
}
-static int cal_enum_input(struct file *file, void *priv,
- struct v4l2_input *inp)
+static int cal_legacy_enum_input(struct file *file, void *priv,
+ struct v4l2_input *inp)
{
if (inp->index > 0)
return -EINVAL;
@@ -348,20 +348,20 @@ static int cal_enum_input(struct file *file, void *priv,
return 0;
}
-static int cal_g_input(struct file *file, void *priv, unsigned int *i)
+static int cal_legacy_g_input(struct file *file, void *priv, unsigned int *i)
{
*i = 0;
return 0;
}
-static int cal_s_input(struct file *file, void *priv, unsigned int i)
+static int cal_legacy_s_input(struct file *file, void *priv, unsigned int i)
{
return i > 0 ? -EINVAL : 0;
}
/* timeperframe is arbitrary and continuous */
-static int cal_enum_frameintervals(struct file *file, void *priv,
- struct v4l2_frmivalenum *fival)
+static int cal_legacy_enum_frameintervals(struct file *file, void *priv,
+ struct v4l2_frmivalenum *fival)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@@ -378,7 +378,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
return -EINVAL;
fie.code = fmtinfo->code;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval,
+ ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_interval,
NULL, &fie);
if (ret)
return ret;
@@ -388,13 +388,27 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
return 0;
}
-static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
+static int cal_legacy_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ struct cal_ctx *ctx = video_drvdata(file);
+
+ return v4l2_g_parm_cap(video_devdata(file), ctx->phy->source, a);
+}
+
+static int cal_legacy_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ struct cal_ctx *ctx = video_drvdata(file);
+
+ return v4l2_s_parm_cap(video_devdata(file), ctx->phy->source, a);
+}
+
+static const struct v4l2_ioctl_ops cal_ioctl_legacy_ops = {
.vidioc_querycap = cal_querycap,
- .vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap,
+ .vidioc_enum_fmt_vid_cap = cal_legacy_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap,
- .vidioc_enum_framesizes = cal_enum_framesizes,
+ .vidioc_try_fmt_vid_cap = cal_legacy_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = cal_legacy_s_fmt_vid_cap,
+ .vidioc_enum_framesizes = cal_legacy_enum_framesizes,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
@@ -402,15 +416,17 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_expbuf = vb2_ioctl_expbuf,
- .vidioc_enum_input = cal_enum_input,
- .vidioc_g_input = cal_g_input,
- .vidioc_s_input = cal_s_input,
- .vidioc_enum_frameintervals = cal_enum_frameintervals,
+ .vidioc_enum_input = cal_legacy_enum_input,
+ .vidioc_g_input = cal_legacy_g_input,
+ .vidioc_s_input = cal_legacy_s_input,
+ .vidioc_enum_frameintervals = cal_legacy_enum_frameintervals,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_log_status = v4l2_ctrl_log_status,
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+ .vidioc_g_parm = cal_legacy_g_parm,
+ .vidioc_s_parm = cal_legacy_s_parm,
};
/* ------------------------------------------------------------------
@@ -421,13 +437,28 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
static int cal_mc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
+ unsigned int i;
+ unsigned int idx;
+
if (f->index >= cal_num_formats)
return -EINVAL;
- f->pixelformat = cal_formats[f->index].fourcc;
- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ idx = 0;
- return 0;
+ for (i = 0; i < cal_num_formats; ++i) {
+ if (f->mbus_code && cal_formats[i].code != f->mbus_code)
+ continue;
+
+ if (idx == f->index) {
+ f->pixelformat = cal_formats[i].fourcc;
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ return 0;
+ }
+
+ idx++;
+ }
+
+ return -EINVAL;
}
static void cal_mc_try_fmt(struct cal_ctx *ctx, struct v4l2_format *f,
@@ -656,8 +687,13 @@ static void cal_release_buffers(struct cal_ctx *ctx,
static int cal_video_check_format(struct cal_ctx *ctx)
{
const struct v4l2_mbus_framefmt *format;
+ struct media_pad *remote_pad;
+
+ remote_pad = media_entity_remote_pad(&ctx->pad);
+ if (!remote_pad)
+ return -ENODEV;
- format = &ctx->phy->formats[CAL_CAMERARX_PAD_SOURCE];
+ format = &ctx->phy->formats[remote_pad->index];
if (ctx->fmtinfo->code != format->code ||
ctx->v_fmt.fmt.pix.height != format->height ||
@@ -692,9 +728,15 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
goto error_pipeline;
}
+ ret = cal_ctx_prepare(ctx);
+ if (ret) {
+ ctx_err(ctx, "Failed to prepare context: %d\n", ret);
+ goto error_pipeline;
+ }
+
spin_lock_irq(&ctx->dma.lock);
buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
- ctx->dma.pending = buf;
+ ctx->dma.active = buf;
list_del(&buf->list);
spin_unlock_irq(&ctx->dma.lock);
@@ -719,6 +761,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
error_stop:
cal_ctx_stop(ctx);
pm_runtime_put_sync(ctx->cal->dev);
+ cal_ctx_unprepare(ctx);
error_pipeline:
media_pipeline_stop(&ctx->vdev.entity);
@@ -738,6 +781,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
pm_runtime_put_sync(ctx->cal->dev);
+ cal_ctx_unprepare(ctx);
+
cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
media_pipeline_stop(&ctx->vdev.entity);
@@ -785,20 +830,20 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
memset(&mbus_code, 0, sizeof(mbus_code));
mbus_code.index = j;
mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_mbus_code,
+ ret = v4l2_subdev_call(ctx->phy->source, pad, enum_mbus_code,
NULL, &mbus_code);
if (ret == -EINVAL)
break;
if (ret) {
ctx_err(ctx, "Error enumerating mbus codes in subdev %s: %d\n",
- ctx->phy->sensor->name, ret);
+ ctx->phy->source->name, ret);
return ret;
}
ctx_dbg(2, ctx,
"subdev %s: code: %04x idx: %u\n",
- ctx->phy->sensor->name, mbus_code.code, j);
+ ctx->phy->source->name, mbus_code.code, j);
for (k = 0; k < cal_num_formats; k++) {
fmtinfo = &cal_formats[k];
@@ -816,7 +861,7 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
if (i == 0) {
ctx_err(ctx, "No suitable format reported by subdev %s\n",
- ctx->phy->sensor->name);
+ ctx->phy->source->name);
return -EINVAL;
}
@@ -841,22 +886,57 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
return 0;
}
+static int cal_ctx_v4l2_init_mc_format(struct cal_ctx *ctx)
+{
+ const struct cal_format_info *fmtinfo;
+ struct v4l2_pix_format *pix_fmt = &ctx->v_fmt.fmt.pix;
+
+ fmtinfo = cal_format_by_code(MEDIA_BUS_FMT_UYVY8_2X8);
+ if (!fmtinfo)
+ return -EINVAL;
+
+ pix_fmt->width = 640;
+ pix_fmt->height = 480;
+ pix_fmt->field = V4L2_FIELD_NONE;
+ pix_fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
+ pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
+ pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB;
+ pix_fmt->pixelformat = fmtinfo->fourcc;
+
+ ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ /* Save current format */
+ cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt);
+ ctx->fmtinfo = fmtinfo;
+
+ return 0;
+}
+
int cal_ctx_v4l2_register(struct cal_ctx *ctx)
{
struct video_device *vfd = &ctx->vdev;
int ret;
- ret = cal_ctx_v4l2_init_formats(ctx);
- if (ret)
- return ret;
-
if (!cal_mc_api) {
struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
- ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler,
+ ret = cal_ctx_v4l2_init_formats(ctx);
+ if (ret) {
+ ctx_err(ctx, "Failed to init formats: %d\n", ret);
+ return ret;
+ }
+
+ ret = v4l2_ctrl_add_handler(hdl, ctx->phy->source->ctrl_handler,
NULL, true);
if (ret < 0) {
- ctx_err(ctx, "Failed to add sensor ctrl handler\n");
+ ctx_err(ctx, "Failed to add source ctrl handler\n");
+ return ret;
+ }
+ } else {
+ ret = cal_ctx_v4l2_init_mc_format(ctx);
+ if (ret) {
+ ctx_err(ctx, "Failed to init format: %d\n", ret);
return ret;
}
}
@@ -868,13 +948,13 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx)
}
ret = media_create_pad_link(&ctx->phy->subdev.entity,
- CAL_CAMERARX_PAD_SOURCE,
+ CAL_CAMERARX_PAD_FIRST_SOURCE,
&vfd->entity, 0,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED);
if (ret) {
ctx_err(ctx, "Failed to create media link for context %u\n",
- ctx->index);
+ ctx->dma_ctx);
video_unregister_device(vfd);
return ret;
}
@@ -926,9 +1006,9 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
| (cal_mc_api ? V4L2_CAP_IO_MC : 0);
vfd->v4l2_dev = &ctx->cal->v4l2_dev;
vfd->queue = q;
- snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
+ snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->dma_ctx);
vfd->release = video_device_release_empty;
- vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_video_ops;
+ vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_legacy_ops;
vfd->lock = &ctx->mutex;
video_set_drvdata(vfd, ctx);