From: Vikash Garodia <quic_vgarodia@xxxxxxxxxxx> Implement the iris vb2 mem ops for buffer management for DMABUF streaming mode. Update video driver buffer with dma buf information. Signed-off-by: Vikash Garodia <quic_vgarodia@xxxxxxxxxxx> Signed-off-by: Dikshita Agarwal <quic_dikshita@xxxxxxxxxxx> --- .../media/platform/qcom/vcodec/iris/iris_probe.c | 1 + drivers/media/platform/qcom/vcodec/iris/iris_vb2.c | 147 +++++++++++++++++++++ drivers/media/platform/qcom/vcodec/iris/iris_vb2.h | 10 ++ .../media/platform/qcom/vcodec/iris/iris_vidc.c | 11 ++ 4 files changed, 169 insertions(+) diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_probe.c b/drivers/media/platform/qcom/vcodec/iris/iris_probe.c index 50fb93e..bf484a3 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_probe.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_probe.c @@ -233,5 +233,6 @@ static struct platform_driver qcom_iris_driver = { }; module_platform_driver(qcom_iris_driver); +MODULE_IMPORT_NS(DMA_BUF); MODULE_DESCRIPTION("Qualcomm Iris video driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c index b040d27..a57b5fb 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c @@ -69,3 +69,150 @@ int iris_vb2_queue_setup(struct vb2_queue *q, return ret; } + +void *iris_vb2_attach_dmabuf(struct vb2_buffer *vb, struct device *dev, + struct dma_buf *dbuf, unsigned long size) +{ + enum iris_buffer_type buf_type; + struct iris_buffers *buffers; + struct iris_buffer *iter; + struct iris_buffer *buf; + struct iris_inst *inst; + bool found = false; + + if (!vb || !dev || !dbuf || !vb->vb2_queue) + return ERR_PTR(-EINVAL); + + inst = vb->vb2_queue->drv_priv; + + buf_type = v4l2_type_to_driver(vb->type); + + buffers = iris_get_buffer_list(inst, buf_type); + if (!buffers) + return NULL; + + list_for_each_entry(iter, &buffers->list, list) { + if (iter->index == vb->index) { + found = true; + buf = iter; + break; + } + } + + if (!found) + return NULL; + + buf->inst = inst; + buf->dmabuf = dbuf; + + buf->attach = dma_buf_attach(dbuf, dev); + if (IS_ERR(buf->attach)) { + buf->attach = NULL; + return NULL; + } + + return buf; +} + +int iris_vb2_map_dmabuf(void *buf_priv) +{ + struct iris_buffer *buf = buf_priv; + struct iris_core *core; + struct iris_inst *inst; + + if (!buf || !buf->inst) + return -EINVAL; + + inst = buf->inst; + core = inst->core; + + if (!buf->attach) { + dev_err(core->dev, "trying to map a non attached buffer\n"); + return -EINVAL; + } + + buf->sg_table = dma_buf_map_attachment(buf->attach, DMA_BIDIRECTIONAL); + if (IS_ERR(buf->sg_table)) + return -EINVAL; + + if (!buf->sg_table->sgl) { + dma_buf_unmap_attachment(buf->attach, buf->sg_table, DMA_BIDIRECTIONAL); + buf->sg_table = NULL; + return -EINVAL; + } + + buf->device_addr = sg_dma_address(buf->sg_table->sgl); + + return 0; +} + +void iris_vb2_unmap_dmabuf(void *buf_priv) +{ + struct iris_buffer *buf = buf_priv; + struct iris_core *core; + struct iris_inst *inst; + + if (!buf || !buf->inst) + return; + + inst = buf->inst; + core = inst->core; + + if (!buf->attach) { + dev_err(core->dev, "trying to unmap a non attached buffer\n"); + return; + } + + if (!buf->sg_table) { + dev_err(core->dev, "dmabuf buffer is already unmapped\n"); + return; + } + + if (buf->attach && buf->sg_table) { + dma_buf_unmap_attachment(buf->attach, buf->sg_table, DMA_BIDIRECTIONAL); + buf->sg_table = NULL; + buf->device_addr = 0x0; + } +} + +void iris_vb2_detach_dmabuf(void *buf_priv) +{ + struct iris_buffer *buf = buf_priv; + struct iris_core *core; + struct iris_inst *inst; + + if (!buf || !buf->inst) + return; + + inst = buf->inst; + core = inst->core; + + if (buf->sg_table) { + dev_err(core->dev, "trying to detach an unmapped buffer\n"); + dma_buf_unmap_attachment(buf->attach, buf->sg_table, DMA_BIDIRECTIONAL); + buf->sg_table = NULL; + } + + if (buf->attach && buf->dmabuf) { + dma_buf_detach(buf->dmabuf, buf->attach); + buf->attach = NULL; + } + + buf->dmabuf = NULL; + buf->inst = NULL; +} + +void *iris_vb2_alloc(struct vb2_buffer *vb, struct device *dev, + unsigned long size) +{ + return (void *)0xdeadbeef; +} + +void iris_vb2_put(void *buf_priv) +{ +} + +int iris_vb2_mmap(void *buf_priv, struct vm_area_struct *vma) +{ + return 0; +} diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.h b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.h index 8a8e1039..4342034 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.h +++ b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.h @@ -12,4 +12,14 @@ int iris_vb2_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], struct device *alloc_devs[]); +/* vb2_mem_ops */ +void *iris_vb2_alloc(struct vb2_buffer *vb, struct device *dev, unsigned long size); +void *iris_vb2_attach_dmabuf(struct vb2_buffer *vb, struct device *dev, struct dma_buf *dbuf, + unsigned long size); +void iris_vb2_put(void *buf_priv); +int iris_vb2_mmap(void *buf_priv, struct vm_area_struct *vma); +void iris_vb2_detach_dmabuf(void *buf_priv); +int iris_vb2_map_dmabuf(void *buf_priv); +void iris_vb2_unmap_dmabuf(void *buf_priv); + #endif diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vidc.c b/drivers/media/platform/qcom/vcodec/iris/iris_vidc.c index 410de720..124333a 100644 --- a/drivers/media/platform/qcom/vcodec/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/vcodec/iris/iris_vidc.c @@ -320,10 +320,21 @@ static const struct vb2_ops iris_vb2_ops = { .queue_setup = iris_vb2_queue_setup, }; +static struct vb2_mem_ops iris_vb2_mem_ops = { + .alloc = iris_vb2_alloc, + .put = iris_vb2_put, + .mmap = iris_vb2_mmap, + .attach_dmabuf = iris_vb2_attach_dmabuf, + .detach_dmabuf = iris_vb2_detach_dmabuf, + .map_dmabuf = iris_vb2_map_dmabuf, + .unmap_dmabuf = iris_vb2_unmap_dmabuf, +}; + int init_ops(struct iris_core *core) { core->v4l2_file_ops = &v4l2_file_ops; core->vb2_ops = &iris_vb2_ops; + core->vb2_mem_ops = &iris_vb2_mem_ops; return 0; } -- 2.7.4