Tobias Jakobi wrote:
> Nicolas Dufresne wrote:
>> Le vendredi 03 novembre 2017 à 09:11 +0100, Marek Szyprowski a écrit :
>>> MFC driver supports only MMAP operation mode mainly due to the hardware
>>> restrictions of the addresses of the DMA buffers (MFC v5 hardware can
>>> access buffers only in 128MiB memory region starting from the base address
>>> of its firmware). When IOMMU is available, this requirement is easily
>>> fulfilled even for the buffers located anywhere in the memory - typically
>>> by mapping them in the DMA address space as close as possible to the
>>> firmware. Later hardware revisions don't have this limitations at all.
>>>
>>> The second limitation of the MFC hardware related to the memory buffers
>>> is constant buffer address. Once the hardware has been initialized for
>>> operation on given buffer set, the addresses of the buffers cannot be
>>> changed.
>>>
>>> With the above assumptions, a limited support for USERPTR and DMABUF
>>> operation modes can be added. The main requirement is to have all buffers
>>> known when starting hardware. This has been achieved by postponing
>>> hardware initialization once all the DMABUF or USERPTR buffers have been
>>> queued for the first time. Once then, buffers cannot be modified to point
>>> to other memory area.
>>
>> I am concerned about enabling this support with existing userspace.
>> Userspace application will be left with some driver with this
>> limitation and other drivers without. I think it is harmful to enable
>> that feature without providing userspace the ability to know.
> I voiced similar concern in my previous mail. I have to admit that I know very
> little about V4L2, but when I investigated this some time ago I saw that
> previously used/queued DMABUF buffers can be removed again, and, under certain
> conditions are 'reacquired', which issues a buf_cleanup() -- which does 
> nothing
> atm. My guess is that, in the worst case, one could trigger an IOMMU pagefault
> (or simply memory corruption, if not under IOMMU) this way.
> 
> Like Marek says, the hw needs to know DMA adresses of all available buffers on
> hw init. Hence a proper implementation would need to trigger some
> re-initialization once these adresses changes (DMABUFs 
> removed/reacquired/etc.).

Forgot to mention something here. Back when I looked at the code, I saw that the
MFC state machine has a state when the resolution of the video changes. IIRC
then this also triggers a reconfiguration of the hw buffers. I thought that
maybe one could re-use the states in the event of changed buffers. I didn't get
very far there, mainly because documentation of the whole state machine and the
interaction with the hw core is very sparse...

- Tobias




> These extra constraints which are introduced here, IMO they violate the API 
> then.
> 
> 
> 
>> This is specially conflicting with let's say UVC driver providing
>> buffers, since UVC driver implementing CREATE_BUFS ioctl. So even if
>> userspace start making an effort to maintain the same DMABuf for the
>> same buffer index, if a new buffer is created, we won't be able to use
>> it.
>>
>>>
>>> This patch also removes unconditional USERPTR operation mode from encoder
>>> video node, because it doesn't work with v5 MFC hardware without IOMMU
>>> being enabled.
>>>
>>> In case of MFC v5 a bidirectional queue flag has to be enabled as a
>>> workaround of the strange hardware behavior - MFC performs a few writes
>>> to source data during the operation.
>>
>> Do you have more information about this ? It is quite terrible, since
>> if you enable buffer importation, the buffer might be multi-plex across
>> multiple encoder instance. That is another way this feature can be
>> harmful to existing userspace.
> IIRC the hw stores some "housekeeping" data in the input buffers used during
> decoding. So input buffers are not strictly "input", but also output, in the
> following sense. If the buffer has total size N, and the data stored inside 
> has
> size n (with n < N), then the hw uses the remaining N-n bytes at the end of 
> the
> buffer for this housekeeping data. I'm not sure what happens if n equals N, or
> if that's even possible.
> 
> With best wishes,
> Tobias
> 
> 
>>
>>>
>>> Signed-off-by: Seung-Woo Kim <sw0312....@samsung.com>
>>> [mszyprow: adapted to v4.14 code base, rewrote and extended commit message,
>>>  added checks for changing buffer addresses, added bidirectional queue
>>>  flags and comments]
>>> Signed-off-by: Marek Szyprowski <m.szyprow...@samsung.com>
>>> ---
>>> v2:
>>> - fixed copy/paste bug, which broke encoding support (thanks to Marian
>>>   Mihailescu for reporting it)
>>> - added checks for changing buffers DMA addresses
>>> - added bidirectional queue flags
>>>
>>> v1:
>>> - inital version
>>> ---
>>>  drivers/media/platform/s5p-mfc/s5p_mfc.c     |  23 +++++-
>>>  drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 111 
>>> +++++++++++++++++++--------
>>>  drivers/media/platform/s5p-mfc/s5p_mfc_enc.c |  64 +++++++++++----
>>>  3 files changed, 147 insertions(+), 51 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c 
>>> b/drivers/media/platform/s5p-mfc/s5p_mfc.c
>>> index 1839a86cc2a5..f1ab8d198158 100644
>>> --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
>>> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
>>> @@ -754,6 +754,7 @@ static int s5p_mfc_open(struct file *file)
>>>     struct s5p_mfc_dev *dev =ideo_drvdata(file);
>>>     struct s5p_mfc_ctx *ctx =ULL;
>>>     struct vb2_queue *q;
>>> +   unsigned int io_modes;
>>>     int ret =;
>>>  
>>>     mfc_debug_enter();
>>> @@ -839,16 +840,25 @@ static int s5p_mfc_open(struct file *file)
>>>             if (ret)
>>>                     goto err_init_hw;
>>>     }
>>> +
>>> +   io_modes =B2_MMAP;
>>> +   if (exynos_is_iommu_available(&dev->plat_dev->dev) || !IS_TWOPORT(dev))
>>> +           io_modes |=B2_USERPTR | VB2_DMABUF;
>>> +
>>>     /* Init videobuf2 queue for CAPTURE */
>>>     q =ctx->vq_dst;
>>>     q->type =4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
>>> +   q->io_modes =o_modes;
>>> +   /*
>>> +    * Destination buffers are always bidirectional, they use used as
>>> +    * reference data, which require READ access
>>> +    */
>>> +   q->bidirectional =rue;
>>>     q->drv_priv =ctx->fh;
>>>     q->lock =dev->mfc_mutex;
>>>     if (vdev =dev->vfd_dec) {
>>> -           q->io_modes =B2_MMAP;
>>>             q->ops =et_dec_queue_ops();
>>>     } else if (vdev =dev->vfd_enc) {
>>> -           q->io_modes =B2_MMAP | VB2_USERPTR;
>>>             q->ops =et_enc_queue_ops();
>>>     } else {
>>>             ret =ENOENT;
>>> @@ -869,13 +879,18 @@ static int s5p_mfc_open(struct file *file)
>>>     /* Init videobuf2 queue for OUTPUT */
>>>     q =ctx->vq_src;
>>>     q->type =4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
>>> +   q->io_modes =o_modes;
>>> +   /*
>>> +    * MFV v5 performs write operations on source data, so make queue
>>> +    * bidirectional to avoid IOMMU protection fault.
>>> +    */
>>> +   if (!IS_MFCV6_PLUS(dev))
>>> +           q->bidirectional =rue;
>>>     q->drv_priv =ctx->fh;
>>>     q->lock =dev->mfc_mutex;
>>>     if (vdev =dev->vfd_dec) {
>>> -           q->io_modes =B2_MMAP;
>>>             q->ops =et_dec_queue_ops();
>>>     } else if (vdev =dev->vfd_enc) {
>>> -           q->io_modes =B2_MMAP | VB2_USERPTR;
>>>             q->ops =et_enc_queue_ops();
>>>     } else {
>>>             ret =ENOENT;
>>> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c 
>>> b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
>>> index e3e5c442902a..26ee8315e2cf 100644
>>> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
>>> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
>>> @@ -551,14 +551,27 @@ static int reqbufs_capture(struct s5p_mfc_dev *dev, 
>>> struct s5p_mfc_ctx *ctx,
>>>                     goto out;
>>>             }
>>>  
>>> -           WARN_ON(ctx->dst_bufs_cnt !=tx->total_dpb_count);
>>> -           ctx->capture_state =UEUE_BUFS_MMAPED;
>>> +           if (reqbufs->memory =V4L2_MEMORY_MMAP) {
>>> +                   if (ctx->dst_bufs_cnt =ctx->total_dpb_count) {
>>> +                           ctx->capture_state =UEUE_BUFS_MMAPED;
>>> +                   } else {
>>> +                           mfc_err("Not all buffers passed to buf_init\n");
>>> +                           reqbufs->count =;
>>> +                           ret =b2_reqbufs(&ctx->vq_dst, reqbufs);
>>> +                           s5p_mfc_hw_call(dev->mfc_ops,
>>> +                                           release_codec_buffers, ctx);
>>> +                           ret =ENOMEM;
>>> +                           goto out;
>>> +                   }
>>> +           }
>>>  
>>>             if (s5p_mfc_ctx_ready(ctx))
>>>                     set_work_bit_irqsave(ctx);
>>>             s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
>>> -           s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET,
>>> -                                     0);
>>> +           if (reqbufs->memory =V4L2_MEMORY_MMAP) {
>>> +                   s5p_mfc_wait_for_done_ctx(ctx,
>>> +                                    S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
>>> +           }
>>>     } else {
>>>             mfc_err("Buffers have already been requested\n");
>>>             ret =EINVAL;
>>> @@ -576,15 +589,19 @@ static int vidioc_reqbufs(struct file *file, void 
>>> *priv,
>>>  {
>>>     struct s5p_mfc_dev *dev =ideo_drvdata(file);
>>>     struct s5p_mfc_ctx *ctx =h_to_ctx(priv);
>>> -
>>> -   if (reqbufs->memory !=4L2_MEMORY_MMAP) {
>>> -           mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n");
>>> -           return -EINVAL;
>>> -   }
>>> +   int ret;
>>>  
>>>     if (reqbufs->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>>> +           ret =b2_verify_memory_type(&ctx->vq_src, reqbufs->memory,
>>> +                                        reqbufs->type);
>>> +           if (ret)
>>> +                   return ret;
>>>             return reqbufs_output(dev, ctx, reqbufs);
>>>     } else if (reqbufs->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
>>> +           ret =b2_verify_memory_type(&ctx->vq_dst, reqbufs->memory,
>>> +                                        reqbufs->type);
>>> +           if (ret)
>>> +                   return ret;
>>>             return reqbufs_capture(dev, ctx, reqbufs);
>>>     } else {
>>>             mfc_err("Invalid type requested\n");
>>> @@ -600,16 +617,20 @@ static int vidioc_querybuf(struct file *file, void 
>>> *priv,
>>>     int ret;
>>>     int i;
>>>  
>>> -   if (buf->memory !=4L2_MEMORY_MMAP) {
>>> -           mfc_err("Only mmaped buffers can be used\n");
>>> -           return -EINVAL;
>>> -   }
>>>     mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type);
>>>     if (ctx->state =MFCINST_GOT_INST &&
>>>                     buf->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>>> +           ret =b2_verify_memory_type(&ctx->vq_src, buf->memory,
>>> +                                        buf->type);
>>> +           if (ret)
>>> +                   return ret;
>>>             ret =b2_querybuf(&ctx->vq_src, buf);
>>>     } else if (ctx->state =MFCINST_RUNNING &&
>>>                     buf->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
>>> +           ret =b2_verify_memory_type(&ctx->vq_dst, buf->memory,
>>> +                                        buf->type);
>>> +           if (ret)
>>> +                   return ret;
>>>             ret =b2_querybuf(&ctx->vq_dst, buf);
>>>             for (i =; i < buf->length; i++)
>>>                     buf->m.planes[i].m.mem_offset +=ST_QUEUE_OFF_BASE;
>>> @@ -940,10 +961,12 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
>>>             else
>>>                     alloc_devs[0] =tx->dev->mem_dev[BANK_R_CTX];
>>>             alloc_devs[1] =tx->dev->mem_dev[BANK_L_CTX];
>>> +           memset(ctx->dst_bufs, 0, sizeof(ctx->dst_bufs));
>>>     } else if (vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
>>>                ctx->state =MFCINST_INIT) {
>>>             psize[0] =tx->dec_src_buf_size;
>>>             alloc_devs[0] =tx->dev->mem_dev[BANK_L_CTX];
>>> +           memset(ctx->src_bufs, 0, sizeof(ctx->src_bufs));
>>>     } else {
>>>             mfc_err("This video node is dedicated to decoding. Decoding not 
>>> initialized\n");
>>>             return -EINVAL;
>>> @@ -959,30 +982,35 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
>>>     unsigned int i;
>>>  
>>>     if (vq->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
>>> +           dma_addr_t luma, chroma;
>>> +
>>>             if (ctx->capture_state =QUEUE_BUFS_MMAPED)
>>>                     return 0;
>>> -           for (i =; i < ctx->dst_fmt->num_planes; i++) {
>>> -                   if (IS_ERR_OR_NULL(ERR_PTR(
>>> -                                   vb2_dma_contig_plane_dma_addr(vb, i)))) 
>>> {
>>> -                           mfc_err("Plane mem not allocated\n");
>>> -                           return -EINVAL;
>>> -                   }
>>> -           }
>>> -           if (vb2_plane_size(vb, 0) < ctx->luma_size ||
>>> -                   vb2_plane_size(vb, 1) < ctx->chroma_size) {
>>> -                   mfc_err("Plane buffer (CAPTURE) is too small\n");
>>> +
>>> +           luma =b2_dma_contig_plane_dma_addr(vb, 0);
>>> +           chroma =b2_dma_contig_plane_dma_addr(vb, 1);
>>> +           if (!luma || !chroma) {
>>> +                   mfc_err("Plane mem not allocated\n");
>>>                     return -EINVAL;
>>>             }
>>> +
>>>             i =b->index;
>>> +           if ((ctx->dst_bufs[i].cookie.raw.luma &&
>>> +                ctx->dst_bufs[i].cookie.raw.luma !=uma) ||
>>> +               (ctx->dst_bufs[i].cookie.raw.chroma &&
>>> +                ctx->dst_bufs[i].cookie.raw.chroma !=hroma)) {
>>> +                   mfc_err("Changing CAPTURE buffer address during 
>>> straming is not possible\n");
>>> +                   return -EINVAL;
>>> +           }
>>> +
>>>             ctx->dst_bufs[i].b =buf;
>>> -           ctx->dst_bufs[i].cookie.raw.luma >> -                           
>>>         vb2_dma_contig_plane_dma_addr(vb, 0);
>>> -           ctx->dst_bufs[i].cookie.raw.chroma >> -                         
>>>         vb2_dma_contig_plane_dma_addr(vb, 1);
>>> +           ctx->dst_bufs[i].cookie.raw.luma =uma;
>>> +           ctx->dst_bufs[i].cookie.raw.chroma =hroma;
>>>             ctx->dst_bufs_cnt++;
>>>     } else if (vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>>> -           if (IS_ERR_OR_NULL(ERR_PTR(
>>> -                                   vb2_dma_contig_plane_dma_addr(vb, 0)))) 
>>> {
>>> +           dma_addr_t stream =b2_dma_contig_plane_dma_addr(vb, 0);
>>> +
>>> +           if (!stream) {
>>>                     mfc_err("Plane memory not allocated\n");
>>>                     return -EINVAL;
>>>             }
>>> @@ -992,9 +1020,14 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
>>>             }
>>>  
>>>             i =b->index;
>>> +           if (ctx->src_bufs[i].cookie.stream &&
>>> +                ctx->src_bufs[i].cookie.stream !=tream) {
>>> +                   mfc_err("Changing OUTPUT buffer address during straming 
>>> is not possible\n");
>>> +                   return -EINVAL;
>>> +           }
>>> +
>>>             ctx->src_bufs[i].b =buf;
>>> -           ctx->src_bufs[i].cookie.stream >> -                             
>>>         vb2_dma_contig_plane_dma_addr(vb, 0);
>>> +           ctx->src_bufs[i].cookie.stream =tream;
>>>             ctx->src_bufs_cnt++;
>>>     } else {
>>>             mfc_err("s5p_mfc_buf_init: unknown queue type\n");
>>> @@ -1071,6 +1104,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
>>>     struct s5p_mfc_dev *dev =tx->dev;
>>>     unsigned long flags;
>>>     struct s5p_mfc_buf *mfc_buf;
>>> +   int wait_flag =;
>>>  
>>>     if (vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>>>             mfc_buf =ctx->src_bufs[vb->index];
>>> @@ -1088,12 +1122,25 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
>>>             list_add_tail(&mfc_buf->list, &ctx->dst_queue);
>>>             ctx->dst_queue_cnt++;
>>>             spin_unlock_irqrestore(&dev->irqlock, flags);
>>> +           if ((vq->memory =V4L2_MEMORY_USERPTR ||
>>> +                   vq->memory =V4L2_MEMORY_DMABUF) &&
>>> +                   ctx->dst_queue_cnt =ctx->total_dpb_count)
>>> +                   ctx->capture_state =UEUE_BUFS_MMAPED;
>>>     } else {
>>>             mfc_err("Unsupported buffer type (%d)\n", vq->type);
>>>     }
>>> -   if (s5p_mfc_ctx_ready(ctx))
>>> +   if (s5p_mfc_ctx_ready(ctx)) {
>>>             set_work_bit_irqsave(ctx);
>>> +           if ((vq->memory =V4L2_MEMORY_USERPTR ||
>>> +                   vq->memory =V4L2_MEMORY_DMABUF) &&
>>> +                   ctx->state =MFCINST_HEAD_PARSED &&
>>> +                   ctx->capture_state =QUEUE_BUFS_MMAPED)
>>> +                   wait_flag =;
>>> +   }
>>>     s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
>>> +   if (wait_flag)
>>> +           s5p_mfc_wait_for_done_ctx(ctx,
>>> +                           S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
>>>  }
>>>  
>>>  static struct vb2_ops s5p_mfc_dec_qops =
>>> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c 
>>> b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
>>> index 7b041e5ee4be..33fc3f3ef48a 100644
>>> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
>>> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
>>> @@ -1125,11 +1125,11 @@ static int vidioc_reqbufs(struct file *file, void 
>>> *priv,
>>>     struct s5p_mfc_ctx *ctx =h_to_ctx(priv);
>>>     int ret =;
>>>  
>>> -   /* if memory is not mmp or userptr return error */
>>> -   if ((reqbufs->memory !=4L2_MEMORY_MMAP) &&
>>> -           (reqbufs->memory !=4L2_MEMORY_USERPTR))
>>> -           return -EINVAL;
>>>     if (reqbufs->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
>>> +           ret =b2_verify_memory_type(&ctx->vq_dst, reqbufs->memory,
>>> +                                        reqbufs->type);
>>> +           if (ret)
>>> +                   return ret;
>>>             if (reqbufs->count =0) {
>>>                     mfc_debug(2, "Freeing buffers\n");
>>>                     ret =b2_reqbufs(&ctx->vq_dst, reqbufs);
>>> @@ -1159,6 +1159,10 @@ static int vidioc_reqbufs(struct file *file, void 
>>> *priv,
>>>                     return -ENOMEM;
>>>             }
>>>     } else if (reqbufs->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>>> +           ret =b2_verify_memory_type(&ctx->vq_src, reqbufs->memory,
>>> +                                        reqbufs->type);
>>> +           if (ret)
>>> +                   return ret;
>>>             if (reqbufs->count =0) {
>>>                     mfc_debug(2, "Freeing buffers\n");
>>>                     ret =b2_reqbufs(&ctx->vq_src, reqbufs);
>>> @@ -1190,6 +1194,8 @@ static int vidioc_reqbufs(struct file *file, void 
>>> *priv,
>>>                     mfc_err("error in vb2_reqbufs() for E(S)\n");
>>>                     return ret;
>>>             }
>>> +           if (reqbufs->memory !=4L2_MEMORY_MMAP)
>>> +                   ctx->src_bufs_cnt =eqbufs->count;
>>>             ctx->output_state =UEUE_BUFS_REQUESTED;
>>>     } else {
>>>             mfc_err("invalid buf type\n");
>>> @@ -1204,11 +1210,11 @@ static int vidioc_querybuf(struct file *file, void 
>>> *priv,
>>>     struct s5p_mfc_ctx *ctx =h_to_ctx(priv);
>>>     int ret =;
>>>  
>>> -   /* if memory is not mmp or userptr return error */
>>> -   if ((buf->memory !=4L2_MEMORY_MMAP) &&
>>> -           (buf->memory !=4L2_MEMORY_USERPTR))
>>> -           return -EINVAL;
>>>     if (buf->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
>>> +           ret =b2_verify_memory_type(&ctx->vq_dst, buf->memory,
>>> +                                        buf->type);
>>> +           if (ret)
>>> +                   return ret;
>>>             if (ctx->state !=FCINST_GOT_INST) {
>>>                     mfc_err("invalid context state: %d\n", ctx->state);
>>>                     return -EINVAL;
>>> @@ -1220,6 +1226,10 @@ static int vidioc_querybuf(struct file *file, void 
>>> *priv,
>>>             }
>>>             buf->m.planes[0].m.mem_offset +=ST_QUEUE_OFF_BASE;
>>>     } else if (buf->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>>> +           ret =b2_verify_memory_type(&ctx->vq_src, buf->memory,
>>> +                                        buf->type);
>>> +           if (ret)
>>> +                   return ret;
>>>             ret =b2_querybuf(&ctx->vq_src, buf);
>>>             if (ret !=) {
>>>                     mfc_err("error in vb2_querybuf() for E(S)\n");
>>> @@ -1828,6 +1838,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
>>>                     *buf_count =FC_MAX_BUFFERS;
>>>             psize[0] =tx->enc_dst_buf_size;
>>>             alloc_devs[0] =tx->dev->mem_dev[BANK_L_CTX];
>>> +           memset(ctx->dst_bufs, 0, sizeof(ctx->dst_bufs));
>>>     } else if (vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>>>             if (ctx->src_fmt)
>>>                     *plane_count =tx->src_fmt->num_planes;
>>> @@ -1849,6 +1860,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
>>>                     alloc_devs[0] =tx->dev->mem_dev[BANK_R_CTX];
>>>                     alloc_devs[1] =tx->dev->mem_dev[BANK_R_CTX];
>>>             }
>>> +           memset(ctx->src_bufs, 0, sizeof(ctx->src_bufs));
>>>     } else {
>>>             mfc_err("invalid queue type: %d\n", vq->type);
>>>             return -EINVAL;
>>> @@ -1865,25 +1877,47 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
>>>     int ret;
>>>  
>>>     if (vq->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
>>> +           dma_addr_t stream;
>>> +
>>>             ret =heck_vb_with_fmt(ctx->dst_fmt, vb);
>>>             if (ret < 0)
>>>                     return ret;
>>> +
>>> +           stream =b2_dma_contig_plane_dma_addr(vb, 0);
>>>             i =b->index;
>>> +           if (ctx->dst_bufs[i].cookie.stream &&
>>> +               ctx->src_bufs[i].cookie.stream !=tream) {
>>> +                   mfc_err("Changing CAPTURE buffer address during 
>>> straming is not possible\n");
>>> +                   return -EINVAL;
>>> +           }
>>> +
>>>             ctx->dst_bufs[i].b =buf;
>>> -           ctx->dst_bufs[i].cookie.stream >> -                             
>>>         vb2_dma_contig_plane_dma_addr(vb, 0);
>>> +           ctx->dst_bufs[i].cookie.stream =tream;
>>>             ctx->dst_bufs_cnt++;
>>>     } else if (vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>>> +           dma_addr_t luma, chroma;
>>> +
>>>             ret =heck_vb_with_fmt(ctx->src_fmt, vb);
>>>             if (ret < 0)
>>>                     return ret;
>>> +
>>> +           luma =b2_dma_contig_plane_dma_addr(vb, 0);
>>> +           chroma =b2_dma_contig_plane_dma_addr(vb, 1);
>>> +
>>>             i =b->index;
>>> +           if ((ctx->src_bufs[i].cookie.raw.luma &&
>>> +                ctx->src_bufs[i].cookie.raw.luma !=uma) ||
>>> +               (ctx->src_bufs[i].cookie.raw.chroma &&
>>> +                ctx->src_bufs[i].cookie.raw.chroma !=hroma)) {
>>> +                   mfc_err("Changing OUTPUT buffer address during straming 
>>> is not possible\n");
>>> +                   return -EINVAL;
>>> +           }
>>> +
>>>             ctx->src_bufs[i].b =buf;
>>> -           ctx->src_bufs[i].cookie.raw.luma >> -                           
>>>         vb2_dma_contig_plane_dma_addr(vb, 0);
>>> -           ctx->src_bufs[i].cookie.raw.chroma >> -                         
>>>         vb2_dma_contig_plane_dma_addr(vb, 1);
>>> -           ctx->src_bufs_cnt++;
>>> +           ctx->src_bufs[i].cookie.raw.luma =uma;
>>> +           ctx->src_bufs[i].cookie.raw.chroma =hroma;
>>> +           if (vb->memory =V4L2_MEMORY_MMAP)
>>> +                   ctx->src_bufs_cnt++;
>>>     } else {
>>>             mfc_err("invalid queue type: %d\n", vq->type);
>>>             return -EINVAL;
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" 
> in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Reply via email to