diff options
Diffstat (limited to 'drivers/media/platform/coda.c')
-rw-r--r-- | drivers/media/platform/coda.c | 167 |
1 files changed, 120 insertions, 47 deletions
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index f1cf44a5aa3c..546cc7bd6a71 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -129,7 +129,7 @@ struct coda_aux_buf { struct coda_dev { struct v4l2_device v4l2_dev; - struct video_device vfd; + struct video_device vfd[2]; struct platform_device *plat_dev; const struct coda_devtype *devtype; @@ -1578,14 +1578,22 @@ static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type) static void set_default_params(struct coda_ctx *ctx) { + u32 src_fourcc, dst_fourcc; int max_w; int max_h; - ctx->codec = &ctx->dev->devtype->codecs[0]; + if (ctx->inst_type == CODA_INST_ENCODER) { + src_fourcc = V4L2_PIX_FMT_YUV420; + dst_fourcc = V4L2_PIX_FMT_H264; + } else { + src_fourcc = V4L2_PIX_FMT_H264; + dst_fourcc = V4L2_PIX_FMT_YUV420; + } + ctx->codec = coda_find_codec(ctx->dev, src_fourcc, dst_fourcc); max_w = ctx->codec->max_w; max_h = ctx->codec->max_h; - ctx->params.codec_mode = CODA_MODE_INVALID; + ctx->params.codec_mode = ctx->codec->mode; ctx->colorspace = V4L2_COLORSPACE_REC709; ctx->params.framerate = 30; ctx->aborting = 0; @@ -1595,12 +1603,19 @@ static void set_default_params(struct coda_ctx *ctx) ctx->q_data[V4L2_M2M_DST].fourcc = ctx->codec->dst_fourcc; ctx->q_data[V4L2_M2M_SRC].width = max_w; ctx->q_data[V4L2_M2M_SRC].height = max_h; - ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w; - ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2; ctx->q_data[V4L2_M2M_DST].width = max_w; ctx->q_data[V4L2_M2M_DST].height = max_h; - ctx->q_data[V4L2_M2M_DST].bytesperline = 0; - ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE; + if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) { + ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w; + ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2; + ctx->q_data[V4L2_M2M_DST].bytesperline = 0; + ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE; + } else { + ctx->q_data[V4L2_M2M_SRC].bytesperline = 0; + ctx->q_data[V4L2_M2M_SRC].sizeimage = CODA_MAX_FRAME_SIZE; + ctx->q_data[V4L2_M2M_DST].bytesperline = max_w; + ctx->q_data[V4L2_M2M_DST].sizeimage = (max_w * max_h * 3) / 2; + } ctx->q_data[V4L2_M2M_SRC].rect.width = max_w; ctx->q_data[V4L2_M2M_SRC].rect.height = max_h; ctx->q_data[V4L2_M2M_DST].rect.width = max_w; @@ -2287,11 +2302,6 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) } ctx->streamon_out = 1; - - if (coda_format_is_yuv(q_data_src->fourcc)) - ctx->inst_type = CODA_INST_ENCODER; - else - ctx->inst_type = CODA_INST_DECODER; } else { if (count < 1) return -EINVAL; @@ -2713,7 +2723,7 @@ static void coda_stop_streaming(struct vb2_queue *q) } } -static struct vb2_ops coda_qops = { +static const struct vb2_ops coda_qops = { .queue_setup = coda_queue_setup, .buf_prepare = coda_buf_prepare, .buf_queue = coda_buf_queue, @@ -2865,35 +2875,55 @@ static int coda_ctrls_setup(struct coda_ctx *ctx) return v4l2_ctrl_handler_setup(&ctx->ctrls); } -static int coda_queue_init(void *priv, struct vb2_queue *src_vq, - struct vb2_queue *dst_vq) +static int coda_queue_init(struct coda_ctx *ctx, struct vb2_queue *vq) +{ + vq->drv_priv = ctx; + vq->ops = &coda_qops; + vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + vq->lock = &ctx->dev->dev_mutex; + + return vb2_queue_init(vq); +} + +static int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) { - struct coda_ctx *ctx = priv; int ret; src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; src_vq->io_modes = VB2_DMABUF | VB2_MMAP; - src_vq->drv_priv = ctx; - src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); - src_vq->ops = &coda_qops; src_vq->mem_ops = &vb2_dma_contig_memops; - src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - src_vq->lock = &ctx->dev->dev_mutex; - ret = vb2_queue_init(src_vq); + ret = coda_queue_init(priv, src_vq); if (ret) return ret; dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; dst_vq->io_modes = VB2_DMABUF | VB2_MMAP; - dst_vq->drv_priv = ctx; - dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); - dst_vq->ops = &coda_qops; dst_vq->mem_ops = &vb2_dma_contig_memops; - dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - dst_vq->lock = &ctx->dev->dev_mutex; - return vb2_queue_init(dst_vq); + return coda_queue_init(priv, dst_vq); +} + +static int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->io_modes = VB2_DMABUF | VB2_MMAP; + src_vq->mem_ops = &vb2_dma_contig_memops; + + ret = coda_queue_init(priv, src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->io_modes = VB2_DMABUF | VB2_MMAP; + dst_vq->mem_ops = &vb2_dma_contig_memops; + + return coda_queue_init(priv, dst_vq); } static int coda_next_free_instance(struct coda_dev *dev) @@ -2907,8 +2937,10 @@ static int coda_next_free_instance(struct coda_dev *dev) return idx; } -static int coda_open(struct file *file) +static int coda_open(struct file *file, enum coda_inst_type inst_type) { + int (*queue_init)(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq); struct coda_dev *dev = video_drvdata(file); struct coda_ctx *ctx = NULL; char *name; @@ -2930,6 +2962,7 @@ static int coda_open(struct file *file) ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root); kfree(name); + ctx->inst_type = inst_type; init_completion(&ctx->completion); INIT_WORK(&ctx->pic_run_work, coda_pic_run_work); INIT_WORK(&ctx->seq_end_work, coda_seq_end_work); @@ -2963,8 +2996,11 @@ static int coda_open(struct file *file) goto err_clk_ahb; set_default_params(ctx); - ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, - &coda_queue_init); + if (inst_type == CODA_INST_ENCODER) + queue_init = coda_encoder_queue_init; + else + queue_init = coda_decoder_queue_init; + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, queue_init); if (IS_ERR(ctx->fh.m2m_ctx)) { ret = PTR_ERR(ctx->fh.m2m_ctx); @@ -3035,6 +3071,16 @@ err_coda_max: return ret; } +static int coda_encoder_open(struct file *file) +{ + return coda_open(file, CODA_INST_ENCODER); +} + +static int coda_decoder_open(struct file *file) +{ + return coda_open(file, CODA_INST_DECODER); +} + static int coda_release(struct file *file) { struct coda_dev *dev = video_drvdata(file); @@ -3079,9 +3125,18 @@ static int coda_release(struct file *file) return 0; } -static const struct v4l2_file_operations coda_fops = { +static const struct v4l2_file_operations coda_encoder_fops = { .owner = THIS_MODULE, - .open = coda_open, + .open = coda_encoder_open, + .release = coda_release, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +}; + +static const struct v4l2_file_operations coda_decoder_fops = { + .owner = THIS_MODULE, + .open = coda_decoder_open, .release = coda_release, .poll = v4l2_m2m_fop_poll, .unlocked_ioctl = video_ioctl2, @@ -3564,6 +3619,17 @@ err_clk_per: return ret; } +static int coda_register_device(struct coda_dev *dev, struct video_device *vfd) +{ + vfd->release = video_device_release_empty, + vfd->lock = &dev->dev_mutex; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->vfl_dir = VFL_DIR_M2M; + video_set_drvdata(vfd, dev); + + return video_register_device(vfd, VFL_TYPE_GRABBER, 0); +} + static void coda_fw_callback(const struct firmware *fw, void *context) { struct coda_dev *dev = context; @@ -3620,15 +3686,6 @@ static void coda_fw_callback(const struct firmware *fw, void *context) return; } - dev->vfd.fops = &coda_fops, - dev->vfd.ioctl_ops = &coda_ioctl_ops; - dev->vfd.release = video_device_release_empty, - dev->vfd.lock = &dev->dev_mutex; - dev->vfd.v4l2_dev = &dev->v4l2_dev; - dev->vfd.vfl_dir = VFL_DIR_M2M; - snprintf(dev->vfd.name, sizeof(dev->vfd.name), "%s", CODA_NAME); - video_set_drvdata(&dev->vfd, dev); - dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); if (IS_ERR(dev->alloc_ctx)) { v4l2_err(&dev->v4l2_dev, "Failed to alloc vb2 context\n"); @@ -3641,13 +3698,28 @@ static void coda_fw_callback(const struct firmware *fw, void *context) goto rel_ctx; } - ret = video_register_device(&dev->vfd, VFL_TYPE_GRABBER, 0); + dev->vfd[0].fops = &coda_encoder_fops, + dev->vfd[0].ioctl_ops = &coda_ioctl_ops; + snprintf(dev->vfd[0].name, sizeof(dev->vfd[0].name), "coda-encoder"); + ret = coda_register_device(dev, &dev->vfd[0]); if (ret) { - v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); + v4l2_err(&dev->v4l2_dev, + "Failed to register encoder video device\n"); goto rel_m2m; } - v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video%d\n", - dev->vfd.num); + + dev->vfd[1].fops = &coda_decoder_fops, + dev->vfd[1].ioctl_ops = &coda_ioctl_ops; + snprintf(dev->vfd[1].name, sizeof(dev->vfd[1].name), "coda-decoder"); + ret = coda_register_device(dev, &dev->vfd[1]); + if (ret) { + v4l2_err(&dev->v4l2_dev, + "Failed to register decoder video device\n"); + goto rel_m2m; + } + + v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video[%d-%d]\n", + dev->vfd[0].num, dev->vfd[1].num); return; @@ -3882,7 +3954,8 @@ static int coda_remove(struct platform_device *pdev) { struct coda_dev *dev = platform_get_drvdata(pdev); - video_unregister_device(&dev->vfd); + video_unregister_device(&dev->vfd[0]); + video_unregister_device(&dev->vfd[1]); if (dev->m2m_dev) v4l2_m2m_release(dev->m2m_dev); pm_runtime_disable(&pdev->dev); |