[PATCH v2 27/29] venus: implementing multi-stream support

2018-05-15 Thread Stanimir Varbanov
This is implementing a multi-stream decoder support. The multi
stream gives an option to use the secondary decoder output
with different raw format (or the same in case of crop).

Signed-off-by: Stanimir Varbanov 
---
 drivers/media/platform/qcom/venus/core.h|   1 +
 drivers/media/platform/qcom/venus/helpers.c | 204 +++-
 drivers/media/platform/qcom/venus/helpers.h |   6 +
 drivers/media/platform/qcom/venus/vdec.c|  91 -
 drivers/media/platform/qcom/venus/venc.c|   1 +
 5 files changed, 299 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.h 
b/drivers/media/platform/qcom/venus/core.h
index 4d6c05f156c4..85e66e2dd672 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -259,6 +259,7 @@ struct venus_inst {
struct list_head list;
struct mutex lock;
struct venus_core *core;
+   struct list_head dpbbufs;
struct list_head internalbufs;
struct list_head registeredbufs;
struct list_head delayed_process;
diff --git a/drivers/media/platform/qcom/venus/helpers.c 
b/drivers/media/platform/qcom/venus/helpers.c
index ed569705ecac..87dcf9973e6f 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -85,6 +85,112 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 
v4l2_pixfmt)
 }
 EXPORT_SYMBOL_GPL(venus_helper_check_codec);
 
+static int venus_helper_queue_dpb_bufs(struct venus_inst *inst)
+{
+   struct intbuf *buf;
+   int ret = 0;
+
+   if (list_empty(&inst->dpbbufs))
+   return 0;
+
+   list_for_each_entry(buf, &inst->dpbbufs, list) {
+   struct hfi_frame_data fdata;
+
+   memset(&fdata, 0, sizeof(fdata));
+   fdata.alloc_len = buf->size;
+   fdata.device_addr = buf->da;
+   fdata.buffer_type = buf->type;
+
+   ret = hfi_session_process_buf(inst, &fdata);
+   if (ret)
+   goto fail;
+   }
+
+fail:
+   return ret;
+}
+
+int venus_helper_free_dpb_bufs(struct venus_inst *inst)
+{
+   struct intbuf *buf, *n;
+
+   if (list_empty(&inst->dpbbufs))
+   return 0;
+
+   list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) {
+   list_del_init(&buf->list);
+   dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
+  buf->attrs);
+   kfree(buf);
+   }
+
+   INIT_LIST_HEAD(&inst->dpbbufs);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs);
+
+int venus_helper_alloc_dpb_bufs(struct venus_inst *inst)
+{
+   struct venus_core *core = inst->core;
+   struct device *dev = core->dev;
+   enum hfi_version ver = core->res->hfi_version;
+   struct hfi_buffer_requirements bufreq;
+   u32 buftype = inst->dpb_buftype;
+   unsigned int dpb_size = 0;
+   struct intbuf *buf;
+   unsigned int i;
+   u32 count;
+   int ret;
+
+   /* no need to allocate dpb buffers */
+   if (!inst->dpb_fmt)
+   return 0;
+
+   if (inst->dpb_buftype == HFI_BUFFER_OUTPUT)
+   dpb_size = inst->output_buf_size;
+   else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2)
+   dpb_size = inst->output2_buf_size;
+
+   if (!dpb_size)
+   return 0;
+
+   ret = venus_helper_get_bufreq(inst, buftype, &bufreq);
+   if (ret)
+   return ret;
+
+   count = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
+
+   for (i = 0; i < count; i++) {
+   buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+   if (!buf) {
+   ret = -ENOMEM;
+   goto fail;
+   }
+
+   buf->type = buftype;
+   buf->size = dpb_size;
+   buf->attrs = DMA_ATTR_WRITE_COMBINE |
+DMA_ATTR_NO_KERNEL_MAPPING;
+   buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,
+ buf->attrs);
+   if (!buf->va) {
+   kfree(buf);
+   ret = -ENOMEM;
+   goto fail;
+   }
+
+   list_add_tail(&buf->list, &inst->dpbbufs);
+   }
+
+   return 0;
+
+fail:
+   venus_helper_free_dpb_bufs(inst);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs);
+
 static int intbufs_set_buffer(struct venus_inst *inst, u32 type)
 {
struct venus_core *core = inst->core;
@@ -342,7 +448,10 @@ session_process_buf(struct venus_inst *inst, struct 
vb2_v4l2_buffer *vbuf)
if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len)
fdata.flags |= HFI_BUFFERFLAG_EOS;
} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-   fdata.buffer_type = HFI_BUFFER_OUTPUT;
+  

Re: [PATCH v2 27/29] venus: implementing multi-stream support

2018-05-15 Thread Hans Verkuil
Hi Stanimir,

On 05/15/18 09:58, Stanimir Varbanov wrote:
> This is implementing a multi-stream decoder support. The multi
> stream gives an option to use the secondary decoder output
> with different raw format (or the same in case of crop).

You told me that multi-stream support is currently internal only.

It would be good if you could elaborate a bit about that in this
commit log and (I think) also add some comments in the code that
reflect this.

It's also not clear to me how and why this is used in the driver
if this is just internal. Does it enable a feature you would
otherwise not be able to use?

I have no complaints about the code, I would just like to see a
bit more background information in the source and commit log.

Regards,

Hans

> 
> Signed-off-by: Stanimir Varbanov 
> ---
>  drivers/media/platform/qcom/venus/core.h|   1 +
>  drivers/media/platform/qcom/venus/helpers.c | 204 
> +++-
>  drivers/media/platform/qcom/venus/helpers.h |   6 +
>  drivers/media/platform/qcom/venus/vdec.c|  91 -
>  drivers/media/platform/qcom/venus/venc.c|   1 +
>  5 files changed, 299 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/platform/qcom/venus/core.h 
> b/drivers/media/platform/qcom/venus/core.h
> index 4d6c05f156c4..85e66e2dd672 100644
> --- a/drivers/media/platform/qcom/venus/core.h
> +++ b/drivers/media/platform/qcom/venus/core.h
> @@ -259,6 +259,7 @@ struct venus_inst {
>   struct list_head list;
>   struct mutex lock;
>   struct venus_core *core;
> + struct list_head dpbbufs;
>   struct list_head internalbufs;
>   struct list_head registeredbufs;
>   struct list_head delayed_process;
> diff --git a/drivers/media/platform/qcom/venus/helpers.c 
> b/drivers/media/platform/qcom/venus/helpers.c
> index ed569705ecac..87dcf9973e6f 100644
> --- a/drivers/media/platform/qcom/venus/helpers.c
> +++ b/drivers/media/platform/qcom/venus/helpers.c
> @@ -85,6 +85,112 @@ bool venus_helper_check_codec(struct venus_inst *inst, 
> u32 v4l2_pixfmt)
>  }
>  EXPORT_SYMBOL_GPL(venus_helper_check_codec);
>  
> +static int venus_helper_queue_dpb_bufs(struct venus_inst *inst)
> +{
> + struct intbuf *buf;
> + int ret = 0;
> +
> + if (list_empty(&inst->dpbbufs))
> + return 0;
> +
> + list_for_each_entry(buf, &inst->dpbbufs, list) {
> + struct hfi_frame_data fdata;
> +
> + memset(&fdata, 0, sizeof(fdata));
> + fdata.alloc_len = buf->size;
> + fdata.device_addr = buf->da;
> + fdata.buffer_type = buf->type;
> +
> + ret = hfi_session_process_buf(inst, &fdata);
> + if (ret)
> + goto fail;
> + }
> +
> +fail:
> + return ret;
> +}
> +
> +int venus_helper_free_dpb_bufs(struct venus_inst *inst)
> +{
> + struct intbuf *buf, *n;
> +
> + if (list_empty(&inst->dpbbufs))
> + return 0;
> +
> + list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) {
> + list_del_init(&buf->list);
> + dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
> +buf->attrs);
> + kfree(buf);
> + }
> +
> + INIT_LIST_HEAD(&inst->dpbbufs);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs);
> +
> +int venus_helper_alloc_dpb_bufs(struct venus_inst *inst)
> +{
> + struct venus_core *core = inst->core;
> + struct device *dev = core->dev;
> + enum hfi_version ver = core->res->hfi_version;
> + struct hfi_buffer_requirements bufreq;
> + u32 buftype = inst->dpb_buftype;
> + unsigned int dpb_size = 0;
> + struct intbuf *buf;
> + unsigned int i;
> + u32 count;
> + int ret;
> +
> + /* no need to allocate dpb buffers */
> + if (!inst->dpb_fmt)
> + return 0;
> +
> + if (inst->dpb_buftype == HFI_BUFFER_OUTPUT)
> + dpb_size = inst->output_buf_size;
> + else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2)
> + dpb_size = inst->output2_buf_size;
> +
> + if (!dpb_size)
> + return 0;
> +
> + ret = venus_helper_get_bufreq(inst, buftype, &bufreq);
> + if (ret)
> + return ret;
> +
> + count = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
> +
> + for (i = 0; i < count; i++) {
> + buf = kzalloc(sizeof(*buf), GFP_KERNEL);
> + if (!buf) {
> + ret = -ENOMEM;
> + goto fail;
> + }
> +
> + buf->type = buftype;
> + buf->size = dpb_size;
> + buf->attrs = DMA_ATTR_WRITE_COMBINE |
> +  DMA_ATTR_NO_KERNEL_MAPPING;
> + buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,
> +   buf->attrs);
> + if (!buf->va) {
> + kfree(buf);
> + ret = -ENOMEM;
> + goto fail;
> +

Re: [PATCH v2 27/29] venus: implementing multi-stream support

2018-05-15 Thread Stanimir Varbanov
Hi Hans,

On 05/15/2018 11:17 AM, Hans Verkuil wrote:
> Hi Stanimir,
> 
> On 05/15/18 09:58, Stanimir Varbanov wrote:
>> This is implementing a multi-stream decoder support. The multi
>> stream gives an option to use the secondary decoder output
>> with different raw format (or the same in case of crop).
> 
> You told me that multi-stream support is currently internal only.
> 
> It would be good if you could elaborate a bit about that in this
> commit log and (I think) also add some comments in the code that
> reflect this.
> 
> It's also not clear to me how and why this is used in the driver
> if this is just internal. Does it enable a feature you would
> otherwise not be able to use?
> 
> I have no complaints about the code, I would just like to see a
> bit more background information in the source and commit log.

Thanks for the fast comments! Sure I will try to document multi-stream
support in the patch description and in the code if it makes sense.

-- 
regards,
Stan