Re: [PATCH v2] media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.kim@xxxxxxxxxxx>
>>> [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.szyprowski@xxxxxxxxxxx>
>>> ---
>>> 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 majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SoC Development]     [Linux Rockchip Development]     [Linux USB Development]     [Video for Linux]     [Linux Audio Users]     [Linux SCSI]     [Yosemite News]

  Powered by Linux