diff options
Diffstat (limited to 'drivers/media/platform/ti-vpe/cal-video.c')
-rw-r--r-- | drivers/media/platform/ti-vpe/cal-video.c | 394 |
1 files changed, 134 insertions, 260 deletions
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c index df472a175e83..779f1e1bc529 100644 --- a/drivers/media/platform/ti-vpe/cal-video.c +++ b/drivers/media/platform/ti-vpe/cal-video.c @@ -9,7 +9,6 @@ * Laurent Pinchart <laurent.pinchart@ideasonboard.com> */ -#include <linux/delay.h> #include <linux/ioctl.h> #include <linux/pm_runtime.h> #include <linux/videodev2.h> @@ -26,107 +25,6 @@ #include "cal.h" -/* ------------------------------------------------------------------ - * Format Handling - * ------------------------------------------------------------------ - */ - -static const struct cal_fmt cal_formats[] = { - { - .fourcc = V4L2_PIX_FMT_YUYV, - .code = MEDIA_BUS_FMT_YUYV8_2X8, - .bpp = 16, - }, { - .fourcc = V4L2_PIX_FMT_UYVY, - .code = MEDIA_BUS_FMT_UYVY8_2X8, - .bpp = 16, - }, { - .fourcc = V4L2_PIX_FMT_YVYU, - .code = MEDIA_BUS_FMT_YVYU8_2X8, - .bpp = 16, - }, { - .fourcc = V4L2_PIX_FMT_VYUY, - .code = MEDIA_BUS_FMT_VYUY8_2X8, - .bpp = 16, - }, { - .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ - .code = MEDIA_BUS_FMT_RGB565_2X8_LE, - .bpp = 16, - }, { - .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ - .code = MEDIA_BUS_FMT_RGB565_2X8_BE, - .bpp = 16, - }, { - .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */ - .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, - .bpp = 16, - }, { - .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */ - .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, - .bpp = 16, - }, { - .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ - .code = MEDIA_BUS_FMT_RGB888_2X12_LE, - .bpp = 24, - }, { - .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ - .code = MEDIA_BUS_FMT_RGB888_2X12_BE, - .bpp = 24, - }, { - .fourcc = V4L2_PIX_FMT_RGB32, /* argb */ - .code = MEDIA_BUS_FMT_ARGB8888_1X32, - .bpp = 32, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR8, - .code = MEDIA_BUS_FMT_SBGGR8_1X8, - .bpp = 8, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG8, - .code = MEDIA_BUS_FMT_SGBRG8_1X8, - .bpp = 8, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG8, - .code = MEDIA_BUS_FMT_SGRBG8_1X8, - .bpp = 8, - }, { - .fourcc = V4L2_PIX_FMT_SRGGB8, - .code = MEDIA_BUS_FMT_SRGGB8_1X8, - .bpp = 8, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR10, - .code = MEDIA_BUS_FMT_SBGGR10_1X10, - .bpp = 10, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG10, - .code = MEDIA_BUS_FMT_SGBRG10_1X10, - .bpp = 10, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG10, - .code = MEDIA_BUS_FMT_SGRBG10_1X10, - .bpp = 10, - }, { - .fourcc = V4L2_PIX_FMT_SRGGB10, - .code = MEDIA_BUS_FMT_SRGGB10_1X10, - .bpp = 10, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR12, - .code = MEDIA_BUS_FMT_SBGGR12_1X12, - .bpp = 12, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG12, - .code = MEDIA_BUS_FMT_SGBRG12_1X12, - .bpp = 12, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG12, - .code = MEDIA_BUS_FMT_SGRBG12_1X12, - .bpp = 12, - }, { - .fourcc = V4L2_PIX_FMT_SRGGB12, - .code = MEDIA_BUS_FMT_SRGGB12_1X12, - .bpp = 12, - }, -}; - /* Print Four-character-code (FOURCC) */ static char *fourcc_to_str(u32 fmt) { @@ -146,31 +44,31 @@ static char *fourcc_to_str(u32 fmt) * ------------------------------------------------------------------ */ -static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx, - u32 pixelformat) +static const struct cal_format_info *find_format_by_pix(struct cal_ctx *ctx, + u32 pixelformat) { - const struct cal_fmt *fmt; + const struct cal_format_info *fmtinfo; unsigned int k; for (k = 0; k < ctx->num_active_fmt; k++) { - fmt = ctx->active_fmt[k]; - if (fmt->fourcc == pixelformat) - return fmt; + fmtinfo = ctx->active_fmt[k]; + if (fmtinfo->fourcc == pixelformat) + return fmtinfo; } return NULL; } -static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx, - u32 code) +static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx, + u32 code) { - const struct cal_fmt *fmt; + const struct cal_format_info *fmtinfo; unsigned int k; for (k = 0; k < ctx->num_active_fmt; k++) { - fmt = ctx->active_fmt[k]; - if (fmt->code == code) - return fmt; + fmtinfo = ctx->active_fmt[k]; + if (fmtinfo->code == code) + return fmtinfo; } return NULL; @@ -193,14 +91,14 @@ static int cal_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { struct cal_ctx *ctx = video_drvdata(file); - const struct cal_fmt *fmt; + const struct cal_format_info *fmtinfo; if (f->index >= ctx->num_active_fmt) return -EINVAL; - fmt = ctx->active_fmt[f->index]; + fmtinfo = ctx->active_fmt[f->index]; - f->pixelformat = fmt->fourcc; + f->pixelformat = fmtinfo->fourcc; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; return 0; } @@ -248,27 +146,23 @@ static int __subdev_set_format(struct cal_ctx *ctx, return 0; } -static int cal_calc_format_size(struct cal_ctx *ctx, - const struct cal_fmt *fmt, - struct v4l2_format *f) +static void cal_calc_format_size(struct cal_ctx *ctx, + const struct cal_format_info *fmtinfo, + struct v4l2_format *f) { u32 bpl, max_width; - if (!fmt) { - ctx_dbg(3, ctx, "No cal_fmt provided!\n"); - return -EINVAL; - } - /* * Maximum width is bound by the DMA max width in bytes. * We need to recalculate the actual maxi width depending on the * number of bytes per pixels required. */ - max_width = MAX_WIDTH_BYTES / (ALIGN(fmt->bpp, 8) >> 3); + max_width = CAL_MAX_WIDTH_BYTES / (ALIGN(fmtinfo->bpp, 8) >> 3); v4l_bound_align_image(&f->fmt.pix.width, 48, max_width, 2, - &f->fmt.pix.height, 32, MAX_HEIGHT_LINES, 0, 0); + &f->fmt.pix.height, 32, CAL_MAX_HEIGHT_LINES, + 0, 0); - bpl = (f->fmt.pix.width * ALIGN(fmt->bpp, 8)) >> 3; + bpl = (f->fmt.pix.width * ALIGN(fmtinfo->bpp, 8)) >> 3; f->fmt.pix.bytesperline = ALIGN(bpl, 16); f->fmt.pix.sizeimage = f->fmt.pix.height * @@ -278,8 +172,6 @@ static int cal_calc_format_size(struct cal_ctx *ctx, __func__, fourcc_to_str(f->fmt.pix.pixelformat), f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); - - return 0; } static int cal_g_fmt_vid_cap(struct file *file, void *priv, @@ -296,18 +188,18 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct cal_ctx *ctx = video_drvdata(file); - const struct cal_fmt *fmt; + const struct cal_format_info *fmtinfo; struct v4l2_subdev_frame_size_enum fse; int ret, found; - fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat); - if (!fmt) { + fmtinfo = find_format_by_pix(ctx, f->fmt.pix.pixelformat); + if (!fmtinfo) { ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n", f->fmt.pix.pixelformat); /* Just get the first one enumerated */ - fmt = ctx->active_fmt[0]; - f->fmt.pix.pixelformat = fmt->fourcc; + fmtinfo = ctx->active_fmt[0]; + f->fmt.pix.pixelformat = fmtinfo->fourcc; } f->fmt.pix.field = ctx->v_fmt.fmt.pix.field; @@ -316,7 +208,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv, ret = 0; found = false; fse.pad = 0; - fse.code = fmt->code; + 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, @@ -348,7 +240,8 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv, * updated properly during s_fmt */ f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace; - return cal_calc_format_size(ctx, fmt, f); + cal_calc_format_size(ctx, fmtinfo, f); + return 0; } static int cal_s_fmt_vid_cap(struct file *file, void *priv, @@ -356,8 +249,11 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv, { struct cal_ctx *ctx = video_drvdata(file); struct vb2_queue *q = &ctx->vb_vidq; - const struct cal_fmt *fmt; - struct v4l2_mbus_framefmt mbus_fmt; + struct v4l2_subdev_format sd_fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .pad = CAL_CAMERARX_PAD_SINK, + }; + const struct cal_format_info *fmtinfo; int ret; if (vb2_is_busy(q)) { @@ -369,28 +265,31 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv, if (ret < 0) return ret; - fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat); + fmtinfo = find_format_by_pix(ctx, f->fmt.pix.pixelformat); - v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code); + v4l2_fill_mbus_format(&sd_fmt.format, &f->fmt.pix, fmtinfo->code); - ret = __subdev_set_format(ctx, &mbus_fmt); + ret = __subdev_set_format(ctx, &sd_fmt.format); if (ret) return ret; /* Just double check nothing has gone wrong */ - if (mbus_fmt.code != fmt->code) { + if (sd_fmt.format.code != fmtinfo->code) { ctx_dbg(3, ctx, "%s subdev changed format on us, this should not happen\n", __func__); return -EINVAL; } - v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt); + v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &sd_fmt.format); ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc; - cal_calc_format_size(ctx, fmt, &ctx->v_fmt); - ctx->fmt = fmt; - ctx->m_fmt = mbus_fmt; + ctx->v_fmt.fmt.pix.pixelformat = fmtinfo->fourcc; + ctx->v_fmt.fmt.pix.field = sd_fmt.format.field; + cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt); + + v4l2_subdev_call(&ctx->phy->subdev, pad, set_fmt, NULL, &sd_fmt); + + ctx->fmtinfo = fmtinfo; *f = ctx->v_fmt; return 0; @@ -400,13 +299,13 @@ static int cal_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { struct cal_ctx *ctx = video_drvdata(file); - const struct cal_fmt *fmt; + const struct cal_format_info *fmtinfo; struct v4l2_subdev_frame_size_enum fse; int ret; /* check for valid format */ - fmt = find_format_by_pix(ctx, fsize->pixel_format); - if (!fmt) { + fmtinfo = find_format_by_pix(ctx, fsize->pixel_format); + if (!fmtinfo) { ctx_dbg(3, ctx, "Invalid pixel code: %x\n", fsize->pixel_format); return -EINVAL; @@ -414,7 +313,7 @@ static int cal_enum_framesizes(struct file *file, void *fh, fse.index = fsize->index; fse.pad = 0; - fse.code = fmt->code; + fse.code = fmtinfo->code; fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL, @@ -460,7 +359,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv, struct v4l2_frmivalenum *fival) { struct cal_ctx *ctx = video_drvdata(file); - const struct cal_fmt *fmt; + const struct cal_format_info *fmtinfo; struct v4l2_subdev_frame_interval_enum fie = { .index = fival->index, .width = fival->width, @@ -469,11 +368,11 @@ static int cal_enum_frameintervals(struct file *file, void *priv, }; int ret; - fmt = find_format_by_pix(ctx, fival->pixel_format); - if (!fmt) + fmtinfo = find_format_by_pix(ctx, fival->pixel_format); + if (!fmtinfo) return -EINVAL; - fie.code = fmt->code; + fie.code = fmtinfo->code; ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval, NULL, &fie); if (ret) @@ -488,7 +387,6 @@ static const struct v4l2_file_operations cal_fops = { .owner = THIS_MODULE, .open = v4l2_fh_open, .release = vb2_fop_release, - .read = vb2_fop_read, .poll = vb2_fop_poll, .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ .mmap = vb2_fop_mmap, @@ -555,9 +453,6 @@ static int cal_buffer_prepare(struct vb2_buffer *vb) vb.vb2_buf); unsigned long size; - if (WARN_ON(!ctx->fmt)) - return -EINVAL; - size = ctx->v_fmt.fmt.pix.sizeimage; if (vb2_plane_size(vb, 0) < size) { ctx_err(ctx, @@ -575,121 +470,88 @@ static void cal_buffer_queue(struct vb2_buffer *vb) struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct cal_buffer *buf = container_of(vb, struct cal_buffer, vb.vb2_buf); - struct cal_dmaqueue *vidq = &ctx->vidq; unsigned long flags; /* recheck locking */ - spin_lock_irqsave(&ctx->slock, flags); - list_add_tail(&buf->list, &vidq->active); - spin_unlock_irqrestore(&ctx->slock, flags); + spin_lock_irqsave(&ctx->dma.lock, flags); + list_add_tail(&buf->list, &ctx->dma.queue); + spin_unlock_irqrestore(&ctx->dma.lock, flags); } -static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) +static void cal_release_buffers(struct cal_ctx *ctx, + enum vb2_buffer_state state) { - struct cal_ctx *ctx = vb2_get_drv_priv(vq); - struct cal_dmaqueue *dma_q = &ctx->vidq; struct cal_buffer *buf, *tmp; - unsigned long addr; - unsigned long flags; - int ret; - spin_lock_irqsave(&ctx->slock, flags); - if (list_empty(&dma_q->active)) { - spin_unlock_irqrestore(&ctx->slock, flags); - ctx_dbg(3, ctx, "buffer queue is empty\n"); - return -EIO; + /* Release all queued buffers. */ + spin_lock_irq(&ctx->dma.lock); + + list_for_each_entry_safe(buf, tmp, &ctx->dma.queue, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, state); + } + + if (ctx->dma.pending) { + vb2_buffer_done(&ctx->dma.pending->vb.vb2_buf, state); + ctx->dma.pending = NULL; + } + + if (ctx->dma.active) { + vb2_buffer_done(&ctx->dma.active->vb.vb2_buf, state); + ctx->dma.active = NULL; } - buf = list_entry(dma_q->active.next, struct cal_buffer, list); - ctx->cur_frm = buf; - ctx->next_frm = buf; + spin_unlock_irq(&ctx->dma.lock); +} + +static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + struct cal_buffer *buf; + dma_addr_t addr; + int ret; + + spin_lock_irq(&ctx->dma.lock); + buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list); + ctx->dma.pending = buf; list_del(&buf->list); - spin_unlock_irqrestore(&ctx->slock, flags); + spin_unlock_irq(&ctx->dma.lock); - addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0); - ctx->sequence = 0; + addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); pm_runtime_get_sync(ctx->cal->dev); - cal_ctx_csi2_config(ctx); - cal_ctx_pix_proc_config(ctx); - cal_ctx_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline, - ctx->v_fmt.fmt.pix.height); + cal_ctx_set_dma_addr(ctx, addr); + cal_ctx_start(ctx); - cal_camerarx_enable_irqs(ctx->phy); - - ret = cal_camerarx_start(ctx->phy, ctx->fmt); + ret = v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 1); if (ret) goto err; - cal_ctx_wr_dma_addr(ctx, addr); - cal_camerarx_ppi_enable(ctx->phy); - if (cal_debug >= 4) cal_quickdump_regs(ctx->cal); return 0; err: - spin_lock_irqsave(&ctx->slock, flags); - vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_QUEUED); - ctx->cur_frm = NULL; - ctx->next_frm = NULL; - list_for_each_entry_safe(buf, tmp, &dma_q->active, list) { - list_del(&buf->list); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); - } - spin_unlock_irqrestore(&ctx->slock, flags); + cal_ctx_stop(ctx); + pm_runtime_put_sync(ctx->cal->dev); + + cal_release_buffers(ctx, VB2_BUF_STATE_QUEUED); return ret; } static void cal_stop_streaming(struct vb2_queue *vq) { struct cal_ctx *ctx = vb2_get_drv_priv(vq); - struct cal_dmaqueue *dma_q = &ctx->vidq; - struct cal_buffer *buf, *tmp; - unsigned long timeout; - unsigned long flags; - bool dma_act; - - cal_camerarx_ppi_disable(ctx->phy); - - /* wait for stream and dma to finish */ - dma_act = true; - timeout = jiffies + msecs_to_jiffies(500); - while (dma_act && time_before(jiffies, timeout)) { - msleep(50); - - spin_lock_irqsave(&ctx->slock, flags); - dma_act = ctx->dma_act; - spin_unlock_irqrestore(&ctx->slock, flags); - } - - if (dma_act) - ctx_err(ctx, "failed to disable dma cleanly\n"); - - cal_camerarx_disable_irqs(ctx->phy); - cal_camerarx_stop(ctx->phy); - /* Release all active buffers */ - spin_lock_irqsave(&ctx->slock, flags); - list_for_each_entry_safe(buf, tmp, &dma_q->active, list) { - list_del(&buf->list); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } + cal_ctx_stop(ctx); - if (ctx->cur_frm == ctx->next_frm) { - vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } else { - vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); - vb2_buffer_done(&ctx->next_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - } - ctx->cur_frm = NULL; - ctx->next_frm = NULL; - spin_unlock_irqrestore(&ctx->slock, flags); + v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 0); pm_runtime_put_sync(ctx->cal->dev); + + cal_release_buffers(ctx, VB2_BUF_STATE_ERROR); } static const struct vb2_ops cal_video_qops = { @@ -713,20 +575,19 @@ static const struct video_device cal_videodev = { .ioctl_ops = &cal_ioctl_ops, .minor = -1, .release = video_device_release_empty, - .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE, + .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING, }; static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx) { struct v4l2_subdev_mbus_code_enum mbus_code; struct v4l2_mbus_framefmt mbus_fmt; - const struct cal_fmt *fmt; + const struct cal_format_info *fmtinfo; unsigned int i, j, k; int ret = 0; /* Enumerate sub device formats and enable all matching local formats */ - ctx->active_fmt = devm_kcalloc(ctx->cal->dev, ARRAY_SIZE(cal_formats), + ctx->active_fmt = devm_kcalloc(ctx->cal->dev, cal_num_formats, sizeof(*ctx->active_fmt), GFP_KERNEL); ctx->num_active_fmt = 0; @@ -744,15 +605,15 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx) "subdev %s: code: %04x idx: %u\n", ctx->phy->sensor->name, mbus_code.code, j); - for (k = 0; k < ARRAY_SIZE(cal_formats); k++) { - const struct cal_fmt *fmt = &cal_formats[k]; + for (k = 0; k < cal_num_formats; k++) { + fmtinfo = &cal_formats[k]; - if (mbus_code.code == fmt->code) { - ctx->active_fmt[i] = fmt; + if (mbus_code.code == fmtinfo->code) { + ctx->active_fmt[i] = fmtinfo; ctx_dbg(2, ctx, "matched fourcc: %s: code: %04x idx: %u\n", - fourcc_to_str(fmt->fourcc), - fmt->code, i); + fourcc_to_str(fmtinfo->fourcc), + fmtinfo->code, i); ctx->num_active_fmt = ++i; } } @@ -768,20 +629,20 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx) if (ret) return ret; - fmt = find_format_by_code(ctx, mbus_fmt.code); - if (!fmt) { + fmtinfo = find_format_by_code(ctx, mbus_fmt.code); + if (!fmtinfo) { ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n", mbus_fmt.code); return -EINVAL; } - /* Save current subdev format */ + /* Save current format */ v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt); ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc; - cal_calc_format_size(ctx, fmt, &ctx->v_fmt); - ctx->fmt = fmt; - ctx->m_fmt = mbus_fmt; + ctx->v_fmt.fmt.pix.pixelformat = fmtinfo->fourcc; + ctx->v_fmt.fmt.pix.field = mbus_fmt.field; + cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt); + ctx->fmtinfo = fmtinfo; return 0; } @@ -809,6 +670,18 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx) return ret; } + ret = media_create_pad_link(&ctx->phy->subdev.entity, + CAL_CAMERARX_PAD_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); + video_unregister_device(vfd); + return ret; + } + ctx_info(ctx, "V4L2 device registered as %s\n", video_device_node_name(vfd)); @@ -830,13 +703,14 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx) struct vb2_queue *q = &ctx->vb_vidq; int ret; - INIT_LIST_HEAD(&ctx->vidq.active); - spin_lock_init(&ctx->slock); + INIT_LIST_HEAD(&ctx->dma.queue); + spin_lock_init(&ctx->dma.lock); mutex_init(&ctx->mutex); + init_waitqueue_head(&ctx->dma.wait); /* Initialize the vb2 queue. */ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; + q->io_modes = VB2_MMAP | VB2_DMABUF; q->drv_priv = ctx; q->buf_struct_size = sizeof(struct cal_buffer); q->ops = &cal_video_qops; |