msm: vidc: Simplify buffer map and unmap sequence
Video driver will map the buffer twice in ETB/FTB. First map will
call iommu_map and following maps will just increment the refcount.
First unmap will happen in EBD/FBD and second unmap will happen if
READONLY flag is not present in EBD/FBD. If READONLY flag is not
present in EBD/FBD then video hardware will send RBR event
(Release Buffer Reference) to driver where second unmap will happen.
Though video driver calls iommu_unmap for second unmap the buffer
is not actually unmapped in iommu driver as video buffers are mapped
using late unmap feature. The buffer will get unmapped in iommu driver
when it is freed.
Change-Id: Ic0043ef97146e3b1081f2fc0fc3da715396be1a0
Signed-off-by: Maheshwar Ajja <majja@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 8d54e20..40c306d 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -10,9 +10,6 @@
* GNU General Public License for more details.
*
*/
-#include <linux/errno.h>
-#include <linux/log2.h>
-#include <linux/hash.h>
#include "hfi_packetization.h"
#include "msm_vidc_debug.h"
@@ -868,8 +865,6 @@
output_frame->device_addr, output_frame->timestamp,
output_frame->alloc_len, output_frame->filled_len,
output_frame->offset);
- dprintk(VIDC_DBG, "### Q OUTPUT BUFFER ###: %d, %d, %d\n",
- pkt->alloc_len, pkt->filled_len, pkt->offset);
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 08cb055..4fb65a2 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1329,10 +1329,8 @@
pkt->ubwc_cr_stats.complexity_number;
data_done.input_done.offset = pkt->offset;
data_done.input_done.filled_len = pkt->filled_len;
- data_done.input_done.packet_buffer =
- (ion_phys_addr_t)pkt->packet_buffer;
- data_done.input_done.extra_data_buffer =
- (ion_phys_addr_t)pkt->extra_data_buffer;
+ data_done.input_done.packet_buffer = pkt->packet_buffer;
+ data_done.input_done.extra_data_buffer = pkt->extra_data_buffer;
data_done.input_done.status =
hfi_map_err_status(pkt->error_type);
hfi_picture_type = (struct hfi_picture_type *)&pkt->rgData[0];
@@ -1413,10 +1411,9 @@
data_done.output_done.alloc_len1 = pkt->alloc_len;
data_done.output_done.filled_len1 = pkt->filled_len;
data_done.output_done.picture_type = pkt->picture_type;
- data_done.output_done.packet_buffer1 =
- (ion_phys_addr_t)pkt->packet_buffer;
+ data_done.output_done.packet_buffer1 = pkt->packet_buffer;
data_done.output_done.extra_data_buffer =
- (ion_phys_addr_t)pkt->extra_data_buffer;
+ pkt->extra_data_buffer;
data_done.output_done.buffer_type = HAL_BUFFER_OUTPUT;
} else /* if (is_decoder) */ {
struct hfi_msg_session_fbd_uncompressed_plane0_packet *pkt =
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index b116622..9b23376 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -30,7 +30,7 @@
enum session_type session_type;
};
-static int get_device_address(struct smem_client *smem_client,
+static int msm_ion_get_device_address(struct smem_client *smem_client,
struct ion_handle *hndl, unsigned long align,
ion_phys_addr_t *iova, unsigned long *buffer_size,
unsigned long flags, enum hal_buffer buffer_type,
@@ -122,12 +122,6 @@
goto mem_map_sg_failed;
}
if (table->sgl) {
- dprintk(VIDC_DBG,
- "%s: CB : %s, DMA buf: %pK, device: %pK, attach: %pK, table: %pK, table sgl: %pK, rc: %d, dma_address: %pa\n",
- __func__, cb->name, buf, cb->dev, attach,
- table, table->sgl, rc,
- &table->sgl->dma_address);
-
*iova = table->sgl->dma_address;
*buffer_size = table->sgl->dma_length;
} else {
@@ -153,7 +147,6 @@
}
}
- dprintk(VIDC_DBG, "mapped ion handle %pK to %pa\n", hndl, iova);
return 0;
mem_map_sg_failed:
dma_buf_unmap_attachment(attach, table, DMA_BIDIRECTIONAL);
@@ -166,38 +159,26 @@
return rc;
}
-static void put_device_address(struct smem_client *smem_client,
+static int msm_ion_put_device_address(struct smem_client *smem_client,
struct ion_handle *hndl, u32 flags,
struct dma_mapping_info *mapping_info,
enum hal_buffer buffer_type)
{
- struct ion_client *clnt = NULL;
+ int rc = 0;
if (!hndl || !smem_client || !mapping_info) {
dprintk(VIDC_WARN, "Invalid params: %pK, %pK\n",
smem_client, hndl);
- return;
+ return -EINVAL;
}
if (!mapping_info->dev || !mapping_info->table ||
!mapping_info->buf || !mapping_info->attach) {
dprintk(VIDC_WARN, "Invalid params:\n");
- return;
+ return -EINVAL;
}
- clnt = smem_client->clnt;
- if (!clnt) {
- dprintk(VIDC_WARN, "Invalid client\n");
- return;
- }
if (is_iommu_present(smem_client->res)) {
- dprintk(VIDC_DBG,
- "Calling dma_unmap_sg - device: %pK, address: %pa, buf: %pK, table: %pK, attach: %pK\n",
- mapping_info->dev,
- &mapping_info->table->sgl->dma_address,
- mapping_info->buf, mapping_info->table,
- mapping_info->attach);
-
trace_msm_smem_buffer_iommu_op_start("UNMAP", 0, 0, 0, 0, 0);
msm_dma_unmap_sg(mapping_info->dev, mapping_info->table->sgl,
mapping_info->table->nents, DMA_BIDIRECTIONAL,
@@ -207,68 +188,257 @@
dma_buf_detach(mapping_info->buf, mapping_info->attach);
dma_buf_put(mapping_info->buf);
trace_msm_smem_buffer_iommu_op_end("UNMAP", 0, 0, 0, 0, 0);
+
+ mapping_info->dev = NULL;
+ mapping_info->mapping = NULL;
+ mapping_info->table = NULL;
+ mapping_info->attach = NULL;
+ mapping_info->buf = NULL;
}
+
+ return rc;
}
-static int ion_user_to_kernel(struct smem_client *client, int fd, u32 size,
- struct msm_smem *mem, enum hal_buffer buffer_type)
+static void *msm_ion_get_dma_buf(int fd)
{
- struct ion_handle *hndl = NULL;
- ion_phys_addr_t iova = 0;
- unsigned long buffer_size = size;
+ struct dma_buf *dma_buf;
+
+ dma_buf = dma_buf_get(fd);
+ if (IS_ERR_OR_NULL(dma_buf)) {
+ dprintk(VIDC_ERR, "Failed to get dma_buf for %d, error %ld\n",
+ fd, PTR_ERR(dma_buf));
+ dma_buf = NULL;
+ }
+
+ return dma_buf;
+}
+
+void *msm_smem_get_dma_buf(int fd)
+{
+ return (void *)msm_ion_get_dma_buf(fd);
+}
+
+static void msm_ion_put_dma_buf(struct dma_buf *dma_buf)
+{
+ if (!dma_buf) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK\n",
+ __func__, dma_buf);
+ return;
+ }
+
+ dma_buf_put(dma_buf);
+}
+
+void msm_smem_put_dma_buf(void *dma_buf)
+{
+ return msm_ion_put_dma_buf((struct dma_buf *)dma_buf);
+}
+
+static struct ion_handle *msm_ion_get_handle(void *ion_client,
+ struct dma_buf *dma_buf)
+{
+ struct ion_handle *handle;
+
+ if (!ion_client || !dma_buf) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, ion_client, dma_buf);
+ return NULL;
+ }
+
+ handle = ion_import_dma_buf(ion_client, dma_buf);
+ if (IS_ERR_OR_NULL(handle)) {
+ dprintk(VIDC_ERR, "Failed to get ion_handle: %pK, %pK, %ld\n",
+ ion_client, dma_buf, PTR_ERR(handle));
+ handle = NULL;
+ }
+
+ return handle;
+}
+
+void *msm_smem_get_handle(struct smem_client *client, void *dma_buf)
+{
+ if (!client)
+ return NULL;
+
+ return (void *)msm_ion_get_handle(client->clnt,
+ (struct dma_buf *)dma_buf);
+}
+
+static void msm_ion_put_handle(struct ion_client *ion_client,
+ struct ion_handle *ion_handle)
+{
+ if (!ion_client || !ion_handle) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, ion_client, ion_handle);
+ return;
+ }
+
+ ion_free(ion_client, ion_handle);
+}
+
+void msm_smem_put_handle(struct smem_client *client, void *handle)
+{
+ if (!client) {
+ dprintk(VIDC_ERR, "%s: Invalid params %pK %pK\n",
+ __func__, client, handle);
+ return;
+ }
+ return msm_ion_put_handle(client->clnt, (struct ion_handle *)handle);
+}
+
+static int msm_ion_map_dma_buf(struct msm_vidc_inst *inst,
+ struct msm_smem *smem)
+{
int rc = 0;
+ ion_phys_addr_t iova = 0;
+ u32 temp = 0;
+ unsigned long buffer_size = 0;
unsigned long align = SZ_4K;
unsigned long ion_flags = 0;
+ struct ion_client *ion_client;
+ struct ion_handle *ion_handle;
+ struct dma_buf *dma_buf;
-#ifdef CONFIG_ION
- hndl = ion_import_dma_buf_fd(client->clnt, fd);
-#endif
- dprintk(VIDC_DBG, "%s ion handle: %pK\n", __func__, hndl);
- if (IS_ERR_OR_NULL(hndl)) {
- dprintk(VIDC_ERR, "Failed to get handle: %pK, %d, %d, %pK\n",
- client, fd, size, hndl);
- rc = -ENOMEM;
- goto fail_import_fd;
+ if (!inst || !inst->mem_client || !inst->mem_client->clnt) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, inst, smem);
+ return -EINVAL;
}
- mem->kvaddr = NULL;
- rc = ion_handle_get_flags(client->clnt, hndl, &ion_flags);
+ ion_client = inst->mem_client->clnt;
+ dma_buf = msm_ion_get_dma_buf(smem->fd);
+ if (!dma_buf)
+ return -EINVAL;
+ ion_handle = msm_ion_get_handle(ion_client, dma_buf);
+ if (!ion_handle)
+ return -EINVAL;
+
+ smem->dma_buf = dma_buf;
+ smem->handle = ion_handle;
+ rc = ion_handle_get_flags(ion_client, ion_handle, &ion_flags);
if (rc) {
dprintk(VIDC_ERR, "Failed to get ion flags: %d\n", rc);
- goto fail_device_address;
+ goto exit;
}
- mem->buffer_type = buffer_type;
if (ion_flags & ION_FLAG_CACHED)
- mem->flags |= SMEM_CACHED;
+ smem->flags |= SMEM_CACHED;
if (ion_flags & ION_FLAG_SECURE)
- mem->flags |= SMEM_SECURE;
+ smem->flags |= SMEM_SECURE;
- rc = get_device_address(client, hndl, align, &iova, &buffer_size,
- mem->flags, buffer_type, &mem->mapping_info);
+ rc = msm_ion_get_device_address(inst->mem_client, ion_handle,
+ align, &iova, &buffer_size, smem->flags,
+ smem->buffer_type, &smem->mapping_info);
if (rc) {
dprintk(VIDC_ERR, "Failed to get device address: %d\n", rc);
- goto fail_device_address;
+ goto exit;
+ }
+ temp = (u32)iova;
+ if ((ion_phys_addr_t)temp != iova) {
+ dprintk(VIDC_ERR, "iova(%pa) truncated to %#x", &iova, temp);
+ rc = -EINVAL;
+ goto exit;
}
- mem->mem_type = client->mem_type;
- mem->smem_priv = hndl;
- mem->device_addr = iova;
- mem->size = buffer_size;
- if ((u32)mem->device_addr != iova) {
- dprintk(VIDC_ERR, "iova(%pa) truncated to %#x",
- &iova, (u32)mem->device_addr);
- goto fail_device_address;
- }
- dprintk(VIDC_DBG,
- "%s: ion_handle = %pK, fd = %d, device_addr = %pa, size = %zx, kvaddr = %pK, buffer_type = %d, flags = %#lx\n",
- __func__, mem->smem_priv, fd, &mem->device_addr, mem->size,
- mem->kvaddr, mem->buffer_type, mem->flags);
+ smem->device_addr = (u32)iova + smem->offset;
+
+exit:
return rc;
-fail_device_address:
- ion_free(client->clnt, hndl);
-fail_import_fd:
+}
+
+int msm_smem_map_dma_buf(struct msm_vidc_inst *inst, struct msm_smem *smem)
+{
+ int rc = 0;
+
+ if (!inst || !smem) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, inst, smem);
+ return -EINVAL;
+ }
+
+ if (smem->refcount) {
+ smem->refcount++;
+ return rc;
+ }
+
+ switch (inst->mem_client->mem_type) {
+ case SMEM_ION:
+ rc = msm_ion_map_dma_buf(inst, smem);
+ break;
+ default:
+ dprintk(VIDC_ERR, "%s: Unknown mem_type %d\n",
+ __func__, inst->mem_client->mem_type);
+ rc = -EINVAL;
+ break;
+ }
+ if (!rc)
+ smem->refcount++;
+
+ return rc;
+}
+
+static int msm_ion_unmap_dma_buf(struct msm_vidc_inst *inst,
+ struct msm_smem *smem)
+{
+ int rc = 0;
+
+ if (!inst || !inst->mem_client || !smem) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, inst, smem);
+ return -EINVAL;
+ }
+
+ rc = msm_ion_put_device_address(inst->mem_client, smem->handle,
+ smem->flags, &smem->mapping_info, smem->buffer_type);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to put device address: %d\n", rc);
+ goto exit;
+ }
+
+ msm_ion_put_handle(inst->mem_client->clnt, smem->handle);
+ msm_ion_put_dma_buf(smem->dma_buf);
+
+ smem->device_addr = 0x0;
+ smem->handle = NULL;
+ smem->dma_buf = NULL;
+
+exit:
+ return rc;
+}
+
+int msm_smem_unmap_dma_buf(struct msm_vidc_inst *inst, struct msm_smem *smem)
+{
+ int rc = 0;
+
+ if (!inst || !smem) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, inst, smem);
+ return -EINVAL;
+ }
+
+ if (smem->refcount) {
+ smem->refcount--;
+ } else {
+ dprintk(VIDC_WARN,
+ "unmap called while refcount is zero already\n");
+ return -EINVAL;
+ }
+
+ if (smem->refcount)
+ return rc;
+
+ switch (inst->mem_client->mem_type) {
+ case SMEM_ION:
+ rc = msm_ion_unmap_dma_buf(inst, smem);
+ break;
+ default:
+ dprintk(VIDC_ERR, "%s: Unknown mem_type %d\n",
+ __func__, inst->mem_client->mem_type);
+ rc = -EINVAL;
+ break;
+ }
+
return rc;
}
@@ -321,6 +491,12 @@
int rc = 0;
int ion_flags = 0;
+ if (!client || !mem) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, client, mem);
+ return -EINVAL;
+ }
+
align = ALIGN(align, SZ_4K);
size = ALIGN(size, SZ_4K);
@@ -366,10 +542,13 @@
}
trace_msm_smem_buffer_ion_op_end("ALLOC", (u32)buffer_type,
heap_mask, size, align, flags, map_kernel);
- mem->mem_type = client->mem_type;
- mem->smem_priv = hndl;
+
+ mem->handle = hndl;
mem->flags = flags;
mem->buffer_type = buffer_type;
+ mem->offset = 0;
+ mem->size = size;
+
if (map_kernel) {
mem->kvaddr = ion_map_kernel(client->clnt, hndl);
if (IS_ERR_OR_NULL(mem->kvaddr)) {
@@ -382,24 +561,23 @@
mem->kvaddr = NULL;
}
- rc = get_device_address(client, hndl, align, &iova, &buffer_size,
- flags, buffer_type, &mem->mapping_info);
+ rc = msm_ion_get_device_address(client, hndl, align, &iova,
+ &buffer_size, flags, buffer_type, &mem->mapping_info);
if (rc) {
dprintk(VIDC_ERR, "Failed to get device address: %d\n",
rc);
goto fail_device_address;
}
- mem->device_addr = iova;
- if ((u32)mem->device_addr != iova) {
+ mem->device_addr = (u32)iova;
+ if ((ion_phys_addr_t)mem->device_addr != iova) {
dprintk(VIDC_ERR, "iova(%pa) truncated to %#x",
- &iova, (u32)mem->device_addr);
+ &iova, mem->device_addr);
goto fail_device_address;
}
- mem->size = size;
dprintk(VIDC_DBG,
- "%s: ion_handle = %pK, device_addr = %pa, size = %#zx, kvaddr = %pK, buffer_type = %#x, flags = %#lx\n",
- __func__, mem->smem_priv, &mem->device_addr,
- mem->size, mem->kvaddr, mem->buffer_type, mem->flags);
+ "%s: ion_handle = %pK, device_addr = %x, size = %d, kvaddr = %pK, buffer_type = %#x, flags = %#lx\n",
+ __func__, mem->handle, mem->device_addr, mem->size,
+ mem->kvaddr, mem->buffer_type, mem->flags);
return rc;
fail_device_address:
if (mem->kvaddr)
@@ -410,30 +588,40 @@
return rc;
}
-static void free_ion_mem(struct smem_client *client, struct msm_smem *mem)
+static int free_ion_mem(struct smem_client *client, struct msm_smem *mem)
{
+ int rc = 0;
+
+ if (!client || !mem) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, client, mem);
+ return -EINVAL;
+ }
+
dprintk(VIDC_DBG,
- "%s: ion_handle = %pK, device_addr = %pa, size = %#zx, kvaddr = %pK, buffer_type = %#x\n",
- __func__, mem->smem_priv, &mem->device_addr,
- mem->size, mem->kvaddr, mem->buffer_type);
+ "%s: ion_handle = %pK, device_addr = %x, size = %d, kvaddr = %pK, buffer_type = %#x\n",
+ __func__, mem->handle, mem->device_addr, mem->size,
+ mem->kvaddr, mem->buffer_type);
if (mem->device_addr)
- put_device_address(client, mem->smem_priv, mem->flags,
+ msm_ion_put_device_address(client, mem->handle, mem->flags,
&mem->mapping_info, mem->buffer_type);
if (mem->kvaddr)
- ion_unmap_kernel(client->clnt, mem->smem_priv);
- if (mem->smem_priv) {
+ ion_unmap_kernel(client->clnt, mem->handle);
+
+ if (mem->handle) {
trace_msm_smem_buffer_ion_op_start("FREE",
(u32)mem->buffer_type, -1, mem->size, -1,
mem->flags, -1);
- dprintk(VIDC_DBG,
- "%s: Freeing handle %pK, client: %pK\n",
- __func__, mem->smem_priv, client->clnt);
- ion_free(client->clnt, mem->smem_priv);
+ ion_free(client->clnt, mem->handle);
trace_msm_smem_buffer_ion_op_end("FREE", (u32)mem->buffer_type,
-1, mem->size, -1, mem->flags, -1);
+ } else {
+ dprintk(VIDC_ERR, "%s: invalid ion_handle\n", __func__);
}
+
+ return rc;
}
static void *ion_new_client(void)
@@ -443,135 +631,105 @@
client = msm_ion_client_create("video_client");
if (!client)
dprintk(VIDC_ERR, "Failed to create smem client\n");
+
+ dprintk(VIDC_DBG, "%s: client %pK\n", __func__, client);
+
return client;
};
static void ion_delete_client(struct smem_client *client)
{
+ if (!client) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK\n",
+ __func__, client);
+ return;
+ }
+
+ dprintk(VIDC_DBG, "%s: client %pK\n", __func__, client->clnt);
ion_client_destroy(client->clnt);
+ client->clnt = NULL;
}
-struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 size,
- enum hal_buffer buffer_type)
+static int msm_ion_cache_operations(void *ion_client, void *ion_handle,
+ unsigned long offset, unsigned long size,
+ enum smem_cache_ops cache_op)
{
- struct smem_client *client = clt;
int rc = 0;
- struct msm_smem *mem;
-
- if (fd < 0) {
- dprintk(VIDC_ERR, "Invalid fd: %d\n", fd);
- return NULL;
- }
- mem = kzalloc(sizeof(*mem), GFP_KERNEL);
- if (!mem) {
- dprintk(VIDC_ERR, "Failed to allocate shared mem\n");
- return NULL;
- }
- switch (client->mem_type) {
- case SMEM_ION:
- rc = ion_user_to_kernel(clt, fd, size, mem, buffer_type);
- break;
- default:
- dprintk(VIDC_ERR, "Mem type not supported\n");
- rc = -EINVAL;
- break;
- }
- if (rc) {
- dprintk(VIDC_ERR, "Failed to allocate shared memory\n");
- kfree(mem);
- mem = NULL;
- }
- return mem;
-}
-
-bool msm_smem_compare_buffers(void *clt, int fd, void *priv)
-{
- struct smem_client *client = clt;
- struct ion_handle *handle = NULL;
- bool ret = false;
-
- if (!clt || !priv) {
- dprintk(VIDC_ERR, "Invalid params: %pK, %pK\n",
- clt, priv);
- return false;
- }
-#ifdef CONFIG_ION
- handle = ion_import_dma_buf_fd(client->clnt, fd);
-#endif
- ret = handle == priv;
- (!IS_ERR_OR_NULL(handle)) ? ion_free(client->clnt, handle) : 0;
- return ret;
-}
-
-static int ion_cache_operations(struct smem_client *client,
- struct msm_smem *mem, enum smem_cache_ops cache_op)
-{
- unsigned long ionflag = 0;
- int rc = 0;
+ unsigned long flags = 0;
int msm_cache_ops = 0;
- if (!mem || !client) {
- dprintk(VIDC_ERR, "Invalid params: %pK, %pK\n",
- mem, client);
+ if (!ion_client || !ion_handle) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, ion_client, ion_handle);
return -EINVAL;
}
- rc = ion_handle_get_flags(client->clnt, mem->smem_priv,
- &ionflag);
+
+ rc = ion_handle_get_flags(ion_client, ion_handle, &flags);
if (rc) {
dprintk(VIDC_ERR,
- "ion_handle_get_flags failed: %d\n", rc);
- goto cache_op_failed;
+ "%s: ion_handle_get_flags failed: %d, ion client %pK, ion handle %pK\n",
+ __func__, rc, ion_client, ion_handle);
+ goto exit;
}
- if (ION_IS_CACHED(ionflag)) {
- switch (cache_op) {
- case SMEM_CACHE_CLEAN:
- msm_cache_ops = ION_IOC_CLEAN_CACHES;
- break;
- case SMEM_CACHE_INVALIDATE:
- msm_cache_ops = ION_IOC_INV_CACHES;
- break;
- case SMEM_CACHE_CLEAN_INVALIDATE:
- msm_cache_ops = ION_IOC_CLEAN_INV_CACHES;
- break;
- default:
- dprintk(VIDC_ERR, "cache operation not supported\n");
- rc = -EINVAL;
- goto cache_op_failed;
- }
- rc = msm_ion_do_cache_op(client->clnt,
- (struct ion_handle *)mem->smem_priv,
- 0, (unsigned long)mem->size,
- msm_cache_ops);
- if (rc) {
- dprintk(VIDC_ERR,
- "cache operation failed %d\n", rc);
- goto cache_op_failed;
- }
+
+ if (!ION_IS_CACHED(flags))
+ goto exit;
+
+ switch (cache_op) {
+ case SMEM_CACHE_CLEAN:
+ msm_cache_ops = ION_IOC_CLEAN_CACHES;
+ break;
+ case SMEM_CACHE_INVALIDATE:
+ msm_cache_ops = ION_IOC_INV_CACHES;
+ break;
+ case SMEM_CACHE_CLEAN_INVALIDATE:
+ msm_cache_ops = ION_IOC_CLEAN_INV_CACHES;
+ break;
+ default:
+ dprintk(VIDC_ERR, "%s: cache (%d) operation not supported\n",
+ __func__, cache_op);
+ rc = -EINVAL;
+ goto exit;
}
-cache_op_failed:
+
+ rc = msm_ion_do_cache_offset_op(ion_client, ion_handle, NULL,
+ offset, size, msm_cache_ops);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: cache operation failed %d, ion client %pK, ion handle %pK, offset %lu, size %lu, msm_cache_ops %u\n",
+ __func__, rc, ion_client, ion_handle, offset,
+ size, msm_cache_ops);
+ goto exit;
+ }
+
+exit:
return rc;
}
-int msm_smem_cache_operations(void *clt, struct msm_smem *mem,
+int msm_smem_cache_operations(struct smem_client *client,
+ void *handle, unsigned long offset, unsigned long size,
enum smem_cache_ops cache_op)
{
- struct smem_client *client = clt;
int rc = 0;
- if (!client) {
- dprintk(VIDC_ERR, "Invalid params: %pK\n",
- client);
+ if (!client || !handle) {
+ dprintk(VIDC_ERR, "%s: Invalid params: %pK %pK\n",
+ __func__, client, handle);
return -EINVAL;
}
+
switch (client->mem_type) {
case SMEM_ION:
- rc = ion_cache_operations(client, mem, cache_op);
+ rc = msm_ion_cache_operations(client->clnt, handle,
+ offset, size, cache_op);
if (rc)
dprintk(VIDC_ERR,
- "Failed cache operations: %d\n", rc);
+ "%s: Failed cache operations: %d\n", __func__, rc);
break;
default:
- dprintk(VIDC_ERR, "Mem type not supported\n");
+ dprintk(VIDC_ERR, "%s: Mem type (%d) not supported\n",
+ __func__, client->mem_type);
+ rc = -EINVAL;
break;
}
return rc;
@@ -607,32 +765,22 @@
return client;
}
-struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
- enum hal_buffer buffer_type, int map_kernel)
+int msm_smem_alloc(struct smem_client *client, size_t size,
+ u32 align, u32 flags, enum hal_buffer buffer_type,
+ int map_kernel, struct msm_smem *smem)
{
- struct smem_client *client;
int rc = 0;
- struct msm_smem *mem;
- client = clt;
- if (!client) {
- dprintk(VIDC_ERR, "Invalid client passed\n");
- return NULL;
+ if (!client || !smem || !size) {
+ dprintk(VIDC_ERR, "%s: Invalid params %pK %pK %d\n",
+ __func__, client, smem, (u32)size);
+ return -EINVAL;
}
- if (!size) {
- dprintk(VIDC_ERR, "No need to allocate memory of size: %zx\n",
- size);
- return NULL;
- }
- mem = kzalloc(sizeof(*mem), GFP_KERNEL);
- if (!mem) {
- dprintk(VIDC_ERR, "Failed to allocate shared mem\n");
- return NULL;
- }
+
switch (client->mem_type) {
case SMEM_ION:
rc = alloc_ion_mem(client, size, align, flags, buffer_type,
- mem, map_kernel);
+ smem, map_kernel);
break;
default:
dprintk(VIDC_ERR, "Mem type not supported\n");
@@ -640,30 +788,34 @@
break;
}
if (rc) {
- dprintk(VIDC_ERR, "Failed to allocate shared memory\n");
- kfree(mem);
- mem = NULL;
+ dprintk(VIDC_ERR, "Failed to allocate memory\n");
}
- return mem;
+
+ return rc;
}
-void msm_smem_free(void *clt, struct msm_smem *mem)
+int msm_smem_free(void *clt, struct msm_smem *smem)
{
+ int rc = 0;
struct smem_client *client = clt;
- if (!client || !mem) {
+ if (!client || !smem) {
dprintk(VIDC_ERR, "Invalid client/handle passed\n");
- return;
+ return -EINVAL;
}
switch (client->mem_type) {
case SMEM_ION:
- free_ion_mem(client, mem);
+ rc = free_ion_mem(client, smem);
break;
default:
dprintk(VIDC_ERR, "Mem type not supported\n");
+ rc = -EINVAL;
break;
}
- kfree(mem);
+ if (rc)
+ dprintk(VIDC_ERR, "Failed to free memory\n");
+
+ return rc;
};
void msm_smem_delete_client(void *clt)
@@ -692,7 +844,7 @@
struct context_bank_info *cb = NULL, *match = NULL;
if (!clt) {
- dprintk(VIDC_ERR, "%s - invalid params\n", __func__);
+ dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
return NULL;
}
@@ -713,12 +865,13 @@
if (cb->is_secure == is_secure &&
cb->buffer_type & buffer_type) {
match = cb;
- dprintk(VIDC_DBG,
- "context bank found for CB : %s, device: %pK mapping: %pK\n",
- match->name, match->dev, match->mapping);
break;
}
}
+ if (!match)
+ dprintk(VIDC_ERR,
+ "%s: cb not found for buffer_type %x, is_secure %d\n",
+ __func__, buffer_type, is_secure);
return match;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index ede51b6..97c8889 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include "vidc_hfi_api.h"
#include "msm_vidc_clocks.h"
+#include <linux/dma-buf.h>
#define MAX_EVENTS 30
@@ -383,507 +384,6 @@
}
EXPORT_SYMBOL(msm_vidc_reqbufs);
-struct buffer_info *get_registered_buf(struct msm_vidc_inst *inst,
- struct v4l2_buffer *b, int idx, int *plane)
-{
- struct buffer_info *temp;
- struct buffer_info *ret = NULL;
- int i;
- int fd = b->m.planes[idx].reserved[0];
- u32 buff_off = b->m.planes[idx].reserved[1];
- u32 size = b->m.planes[idx].length;
- ion_phys_addr_t device_addr = b->m.planes[idx].m.userptr;
-
- if (fd < 0 || !plane) {
- dprintk(VIDC_ERR, "Invalid input\n");
- goto err_invalid_input;
- }
-
- WARN(!mutex_is_locked(&inst->registeredbufs.lock),
- "Registered buf lock is not acquired for %s", __func__);
-
- *plane = 0;
- list_for_each_entry(temp, &inst->registeredbufs.list, list) {
- for (i = 0; i < min(temp->num_planes, VIDEO_MAX_PLANES); i++) {
- bool ion_hndl_matches = temp->handle[i] ?
- msm_smem_compare_buffers(inst->mem_client, fd,
- temp->handle[i]->smem_priv) : false;
- bool device_addr_matches = device_addr ==
- temp->device_addr[i];
- bool contains_within = CONTAINS(temp->buff_off[i],
- temp->size[i], buff_off) ||
- CONTAINS(buff_off, size, temp->buff_off[i]);
- bool overlaps = OVERLAPS(buff_off, size,
- temp->buff_off[i], temp->size[i]);
-
- if (!temp->inactive &&
- (ion_hndl_matches || device_addr_matches) &&
- (contains_within || overlaps)) {
- dprintk(VIDC_DBG,
- "This memory region is already mapped\n");
- ret = temp;
- *plane = i;
- break;
- }
- }
- if (ret)
- break;
- }
-
-err_invalid_input:
- return ret;
-}
-
-static struct msm_smem *get_same_fd_buffer(struct msm_vidc_inst *inst, int fd)
-{
- struct buffer_info *temp;
- struct msm_smem *same_fd_handle = NULL;
- int i;
-
- if (!fd)
- return NULL;
-
- if (!inst || fd < 0) {
- dprintk(VIDC_ERR, "%s: Invalid input\n", __func__);
- goto err_invalid_input;
- }
-
- mutex_lock(&inst->registeredbufs.lock);
- list_for_each_entry(temp, &inst->registeredbufs.list, list) {
- for (i = 0; i < min(temp->num_planes, VIDEO_MAX_PLANES); i++) {
- bool ion_hndl_matches = temp->handle[i] ?
- msm_smem_compare_buffers(inst->mem_client, fd,
- temp->handle[i]->smem_priv) : false;
- if (ion_hndl_matches && temp->mapped[i]) {
- temp->same_fd_ref[i]++;
- dprintk(VIDC_INFO,
- "Found same fd buffer\n");
- same_fd_handle = temp->handle[i];
- break;
- }
- }
- if (same_fd_handle)
- break;
- }
- mutex_unlock(&inst->registeredbufs.lock);
-
-err_invalid_input:
- return same_fd_handle;
-}
-
-struct buffer_info *device_to_uvaddr(struct msm_vidc_list *buf_list,
- ion_phys_addr_t device_addr)
-{
- struct buffer_info *temp = NULL;
- bool found = false;
- int i;
-
- if (!buf_list || !device_addr) {
- dprintk(VIDC_ERR,
- "Invalid input- device_addr: %pa buf_list: %pK\n",
- &device_addr, buf_list);
- goto err_invalid_input;
- }
-
- mutex_lock(&buf_list->lock);
- list_for_each_entry(temp, &buf_list->list, list) {
- for (i = 0; i < min(temp->num_planes, VIDEO_MAX_PLANES); i++) {
- if (!temp->inactive &&
- temp->device_addr[i] == device_addr) {
- dprintk(VIDC_INFO,
- "Found same fd buffer\n");
- found = true;
- break;
- }
- }
-
- if (found)
- break;
- }
- mutex_unlock(&buf_list->lock);
-
-err_invalid_input:
- return temp;
-}
-
-static inline void populate_buf_info(struct buffer_info *binfo,
- struct v4l2_buffer *b, u32 i)
-{
- if (i >= VIDEO_MAX_PLANES) {
- dprintk(VIDC_ERR, "%s: Invalid input\n", __func__);
- return;
- }
- binfo->type = b->type;
- binfo->fd[i] = b->m.planes[i].reserved[0];
- binfo->buff_off[i] = b->m.planes[i].reserved[1];
- binfo->size[i] = b->m.planes[i].length;
- binfo->uvaddr[i] = b->m.planes[i].m.userptr;
- binfo->num_planes = b->length;
- binfo->memory = b->memory;
- binfo->v4l2_index = b->index;
- binfo->timestamp.tv_sec = b->timestamp.tv_sec;
- binfo->timestamp.tv_usec = b->timestamp.tv_usec;
- dprintk(VIDC_DBG, "%s: fd[%d] = %d b->index = %d",
- __func__, i, binfo->fd[i], b->index);
-}
-
-static inline void repopulate_v4l2_buffer(struct v4l2_buffer *b,
- struct buffer_info *binfo)
-{
- int i = 0;
-
- b->type = binfo->type;
- b->length = binfo->num_planes;
- b->memory = binfo->memory;
- b->index = binfo->v4l2_index;
- b->timestamp.tv_sec = binfo->timestamp.tv_sec;
- b->timestamp.tv_usec = binfo->timestamp.tv_usec;
- binfo->dequeued = false;
- for (i = 0; i < binfo->num_planes; ++i) {
- b->m.planes[i].reserved[0] = binfo->fd[i];
- b->m.planes[i].reserved[1] = binfo->buff_off[i];
- b->m.planes[i].length = binfo->size[i];
- b->m.planes[i].m.userptr = binfo->device_addr[i];
- dprintk(VIDC_DBG, "%s %d %d %d %pa\n", __func__, binfo->fd[i],
- binfo->buff_off[i], binfo->size[i],
- &binfo->device_addr[i]);
- }
-}
-
-static struct msm_smem *map_buffer(struct msm_vidc_inst *inst,
- struct v4l2_plane *p, enum hal_buffer buffer_type)
-{
- struct msm_smem *handle = NULL;
-
- handle = msm_comm_smem_user_to_kernel(inst,
- p->reserved[0],
- p->length,
- buffer_type);
- if (!handle) {
- dprintk(VIDC_ERR,
- "%s: Failed to get device buffer address\n", __func__);
- return NULL;
- }
- return handle;
-}
-
-static inline enum hal_buffer get_hal_buffer_type(
- struct msm_vidc_inst *inst, struct v4l2_buffer *b)
-{
- if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
- return HAL_BUFFER_INPUT;
- else if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- return HAL_BUFFER_OUTPUT;
- else
- return -EINVAL;
-}
-
-static inline bool is_dynamic_buffer_mode(struct v4l2_buffer *b,
- struct msm_vidc_inst *inst)
-{
- enum vidc_ports port = b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
- OUTPUT_PORT : CAPTURE_PORT;
- return inst->buffer_mode_set[port] == HAL_BUFFER_MODE_DYNAMIC;
-}
-
-
-static inline void save_v4l2_buffer(struct v4l2_buffer *b,
- struct buffer_info *binfo)
-{
- int i = 0;
-
- for (i = 0; i < b->length; ++i) {
- if (EXTRADATA_IDX(b->length) &&
- (i == EXTRADATA_IDX(b->length)) &&
- !b->m.planes[i].length) {
- continue;
- }
- populate_buf_info(binfo, b, i);
- }
-}
-
-int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
-{
- struct buffer_info *binfo = NULL;
- struct buffer_info *temp = NULL, *iterator = NULL;
- int plane = 0;
- int i = 0, rc = 0;
- struct msm_smem *same_fd_handle = NULL;
-
- if (!b || !inst) {
- dprintk(VIDC_ERR, "%s: invalid input\n", __func__);
- return -EINVAL;
- }
-
- binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
- if (!binfo) {
- dprintk(VIDC_ERR, "Out of memory\n");
- rc = -ENOMEM;
- goto exit;
- }
- if (b->length > VIDEO_MAX_PLANES) {
- dprintk(VIDC_ERR, "Num planes exceeds max: %d, %d\n",
- b->length, VIDEO_MAX_PLANES);
- rc = -EINVAL;
- goto exit;
- }
-
- dprintk(VIDC_DBG,
- "[MAP] Create binfo = %pK fd = %d size = %d type = %d\n",
- binfo, b->m.planes[0].reserved[0],
- b->m.planes[0].length, b->type);
-
- for (i = 0; i < b->length; ++i) {
- rc = 0;
- if (EXTRADATA_IDX(b->length) &&
- (i == EXTRADATA_IDX(b->length)) &&
- !b->m.planes[i].length) {
- continue;
- }
- mutex_lock(&inst->registeredbufs.lock);
- temp = get_registered_buf(inst, b, i, &plane);
- if (temp && !is_dynamic_buffer_mode(b, inst)) {
- dprintk(VIDC_DBG,
- "This memory region has already been prepared\n");
- rc = 0;
- mutex_unlock(&inst->registeredbufs.lock);
- goto exit;
- }
-
- if (temp && is_dynamic_buffer_mode(b, inst) && !i) {
- /*
- * Buffer is already present in registered list
- * increment ref_count, populate new values of v4l2
- * buffer in existing buffer_info struct.
- *
- * We will use the saved buffer info and queue it when
- * we receive RELEASE_BUFFER_REFERENCE EVENT from f/w.
- */
- dprintk(VIDC_DBG, "[MAP] Buffer already prepared\n");
- temp->inactive = false;
- list_for_each_entry(iterator,
- &inst->registeredbufs.list, list) {
- if (iterator == temp) {
- rc = buf_ref_get(inst, temp);
- save_v4l2_buffer(b, temp);
- break;
- }
- }
- }
- mutex_unlock(&inst->registeredbufs.lock);
- /*
- * rc == 1,
- * buffer is mapped, fw has released all reference, so skip
- * mapping and queue it immediately.
- *
- * rc == 2,
- * buffer is mapped and fw is holding a reference, hold it in
- * the driver and queue it later when fw has released
- */
- if (rc == 1) {
- rc = 0;
- goto exit;
- } else if (rc >= 2) {
- rc = -EEXIST;
- goto exit;
- }
-
- same_fd_handle = get_same_fd_buffer(
- inst, b->m.planes[i].reserved[0]);
-
- populate_buf_info(binfo, b, i);
- if (same_fd_handle) {
- binfo->device_addr[i] =
- same_fd_handle->device_addr + binfo->buff_off[i];
- b->m.planes[i].m.userptr = binfo->device_addr[i];
- binfo->mapped[i] = false;
- binfo->handle[i] = same_fd_handle;
- } else {
- binfo->handle[i] = map_buffer(inst, &b->m.planes[i],
- get_hal_buffer_type(inst, b));
- if (!binfo->handle[i]) {
- rc = -EINVAL;
- goto exit;
- }
-
- binfo->mapped[i] = true;
- binfo->device_addr[i] = binfo->handle[i]->device_addr +
- binfo->buff_off[i];
- b->m.planes[i].m.userptr = binfo->device_addr[i];
- }
-
- /* We maintain one ref count for all planes*/
- if (!i && is_dynamic_buffer_mode(b, inst)) {
- rc = buf_ref_get(inst, binfo);
- if (rc < 0)
- goto exit;
- }
- dprintk(VIDC_DBG,
- "%s: [MAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n",
- __func__, binfo, i, binfo->handle[i],
- &binfo->device_addr[i], binfo->fd[i],
- binfo->buff_off[i], binfo->mapped[i]);
- }
-
- mutex_lock(&inst->registeredbufs.lock);
- list_add_tail(&binfo->list, &inst->registeredbufs.list);
- mutex_unlock(&inst->registeredbufs.lock);
- return 0;
-
-exit:
- kfree(binfo);
- return rc;
-}
-int unmap_and_deregister_buf(struct msm_vidc_inst *inst,
- struct buffer_info *binfo)
-{
- int i = 0;
- struct buffer_info *temp = NULL;
- bool found = false, keep_node = false;
-
- if (!inst || !binfo) {
- dprintk(VIDC_ERR, "%s invalid param: %pK %pK\n",
- __func__, inst, binfo);
- return -EINVAL;
- }
-
- WARN(!mutex_is_locked(&inst->registeredbufs.lock),
- "Registered buf lock is not acquired for %s", __func__);
-
- /*
- * Make sure the buffer to be unmapped and deleted
- * from the registered list is present in the list.
- */
- list_for_each_entry(temp, &inst->registeredbufs.list, list) {
- if (temp == binfo) {
- found = true;
- break;
- }
- }
-
- /*
- * Free the buffer info only if
- * - buffer info has not been deleted from registered list
- * - vidc client has called dqbuf on the buffer
- * - no references are held on the buffer
- */
- if (!found || !temp || !temp->pending_deletion || !temp->dequeued)
- goto exit;
-
- for (i = 0; i < temp->num_planes; i++) {
- dprintk(VIDC_DBG,
- "%s: [UNMAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n",
- __func__, temp, i, temp->handle[i],
- &temp->device_addr[i], temp->fd[i],
- temp->buff_off[i], temp->mapped[i]);
- /*
- * Unmap the handle only if the buffer has been mapped and no
- * other buffer has a reference to this buffer.
- * In case of buffers with same fd, we will map the buffer only
- * once and subsequent buffers will refer to the mapped buffer's
- * device address.
- * For buffers which share the same fd, do not unmap and keep
- * the buffer info in registered list.
- */
- if (temp->handle[i] && temp->mapped[i] &&
- !temp->same_fd_ref[i]) {
- msm_comm_smem_free(inst,
- temp->handle[i]);
- }
-
- if (temp->same_fd_ref[i])
- keep_node = true;
- else {
- temp->fd[i] = 0;
- temp->handle[i] = 0;
- temp->device_addr[i] = 0;
- temp->uvaddr[i] = 0;
- }
- }
- if (!keep_node) {
- dprintk(VIDC_DBG, "[UNMAP] AND-FREED binfo: %pK\n", temp);
- list_del(&temp->list);
- kfree(temp);
- } else {
- temp->inactive = true;
- dprintk(VIDC_DBG, "[UNMAP] NOT-FREED binfo: %pK\n", temp);
- }
-exit:
- return 0;
-}
-
-
-int qbuf_dynamic_buf(struct msm_vidc_inst *inst,
- struct buffer_info *binfo)
-{
- struct v4l2_buffer b = {0};
- struct v4l2_plane plane[VIDEO_MAX_PLANES] = { {0} };
- struct buf_queue *q = NULL;
- int rc = 0;
-
- if (!binfo) {
- dprintk(VIDC_ERR, "%s invalid param: %pK\n", __func__, binfo);
- return -EINVAL;
- }
- dprintk(VIDC_DBG, "%s fd[0] = %d\n", __func__, binfo->fd[0]);
-
- b.m.planes = plane;
- repopulate_v4l2_buffer(&b, binfo);
-
- q = msm_comm_get_vb2q(inst, (&b)->type);
- if (!q) {
- dprintk(VIDC_ERR, "Failed to find buffer queue for type = %d\n"
- , (&b)->type);
- return -EINVAL;
- }
-
- mutex_lock(&q->lock);
- rc = vb2_qbuf(&q->vb2_bufq, &b);
- mutex_unlock(&q->lock);
-
- if (rc)
- dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
- return rc;
-}
-
-int output_buffer_cache_invalidate(struct msm_vidc_inst *inst,
- struct buffer_info *binfo)
-{
- int i = 0;
- int rc = 0;
-
- if (!inst) {
- dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst);
- return -EINVAL;
- }
-
- if (!binfo) {
- dprintk(VIDC_ERR, "%s: invalid buffer info: %pK\n",
- __func__, inst);
- return -EINVAL;
- }
-
- for (i = 0; i < binfo->num_planes; i++) {
- if (binfo->handle[i]) {
- struct msm_smem smem = *binfo->handle[i];
-
- smem.offset = (unsigned int)(binfo->buff_off[i]);
- smem.size = binfo->size[i];
- rc = msm_comm_smem_cache_operations(inst,
- &smem, SMEM_CACHE_INVALIDATE);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s: Failed to clean caches: %d\n",
- __func__, rc);
- return -EINVAL;
- }
- } else
- dprintk(VIDC_DBG, "%s: NULL handle for plane %d\n",
- __func__, i);
- }
- return 0;
-}
-
static bool valid_v4l2_buffer(struct v4l2_buffer *b,
struct msm_vidc_inst *inst) {
enum vidc_ports port =
@@ -896,17 +396,16 @@
inst->bufq[port].num_planes == b->length;
}
-int msm_vidc_release_buffer(void *instance, int buffer_type,
- unsigned int buffer_index)
+int msm_vidc_release_buffer(void *instance, int type, unsigned int index)
{
+ int rc = 0;
struct msm_vidc_inst *inst = instance;
- struct buffer_info *bi, *dummy;
- int i, rc = 0;
- int found_buf = 0;
- struct vb2_buf_entry *temp, *next;
+ struct msm_vidc_buffer *mbuf, *dummy;
- if (!inst)
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s: invalid inst\n", __func__);
return -EINVAL;
+ }
if (!inst->in_reconfig &&
inst->state > MSM_VIDC_LOAD_RESOURCES &&
@@ -914,64 +413,26 @@
rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
if (rc) {
dprintk(VIDC_ERR,
- "Failed to move inst: %pK to release res done\n",
- inst);
+ "%s: Failed to move inst: %pK to release res done\n",
+ __func__, inst);
}
}
mutex_lock(&inst->registeredbufs.lock);
- list_for_each_entry_safe(bi, dummy, &inst->registeredbufs.list, list) {
- if (bi->type == buffer_type && bi->v4l2_index == buffer_index) {
- found_buf = 1;
- list_del(&bi->list);
- for (i = 0; i < bi->num_planes; i++) {
- if (bi->handle[i] && bi->mapped[i]) {
- dprintk(VIDC_DBG,
- "%s: [UNMAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n",
- __func__, bi, i, bi->handle[i],
- &bi->device_addr[i], bi->fd[i],
- bi->buff_off[i], bi->mapped[i]);
- msm_comm_smem_free(inst,
- bi->handle[i]);
- found_buf = 2;
- }
- }
- kfree(bi);
- break;
- }
+ list_for_each_entry_safe(mbuf, dummy, &inst->registeredbufs.list,
+ list) {
+ struct vb2_buffer *vb2 = &mbuf->vvb.vb2_buf;
+
+ if (vb2->type != type || vb2->index != index)
+ continue;
+
+ print_vidc_buffer(VIDC_DBG, "release buf", inst, mbuf);
+ msm_comm_unmap_vidc_buffer(inst, mbuf);
+ list_del(&mbuf->list);
+ kfree(mbuf);
}
mutex_unlock(&inst->registeredbufs.lock);
- switch (found_buf) {
- case 0:
- dprintk(VIDC_DBG,
- "%s: No buffer(type: %d) found for index %d\n",
- __func__, buffer_type, buffer_index);
- break;
- case 1:
- dprintk(VIDC_WARN,
- "%s: Buffer(type: %d) found for index %d.",
- __func__, buffer_type, buffer_index);
- dprintk(VIDC_WARN, "zero planes mapped.\n");
- break;
- case 2:
- dprintk(VIDC_DBG,
- "%s: Released buffer(type: %d) for index %d\n",
- __func__, buffer_type, buffer_index);
- break;
- default:
- break;
- }
-
- mutex_lock(&inst->pendingq.lock);
- list_for_each_entry_safe(temp, next, &inst->pendingq.list, list) {
- if (temp->vb->type == buffer_type) {
- list_del(&temp->list);
- kfree(temp);
- }
- }
- mutex_unlock(&inst->pendingq.lock);
-
return rc;
}
EXPORT_SYMBOL(msm_vidc_release_buffer);
@@ -979,65 +440,20 @@
int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
- struct buffer_info *binfo;
- int plane = 0;
- int rc = 0;
- int i;
+ int rc = 0, i = 0;
struct buf_queue *q = NULL;
- if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst))
+ if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst)) {
+ dprintk(VIDC_ERR, "%s: invalid params, inst %pK\n",
+ __func__, inst);
return -EINVAL;
-
- if (inst->state == MSM_VIDC_CORE_INVALID ||
- inst->core->state == VIDC_CORE_INVALID)
- return -EINVAL;
-
- rc = map_and_register_buf(inst, b);
- if (rc == -EEXIST) {
- if (atomic_read(&inst->in_flush) &&
- is_dynamic_buffer_mode(b, inst)) {
- dprintk(VIDC_ERR,
- "Flush in progress, do not hold any buffers in driver\n");
- msm_comm_flush_dynamic_buffers(inst);
- }
- return 0;
}
- if (rc)
- return rc;
- for (i = 0; i < b->length; ++i) {
- if (EXTRADATA_IDX(b->length) &&
- (i == EXTRADATA_IDX(b->length)) &&
- !b->m.planes[i].length) {
- b->m.planes[i].m.userptr = 0;
- continue;
- }
- mutex_lock(&inst->registeredbufs.lock);
- binfo = get_registered_buf(inst, b, i, &plane);
- mutex_unlock(&inst->registeredbufs.lock);
- if (!binfo) {
- dprintk(VIDC_ERR,
- "This buffer is not registered: %d, %d, %d\n",
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length);
- goto err_invalid_buff;
- }
- b->m.planes[i].m.userptr = binfo->device_addr[i];
- dprintk(VIDC_DBG, "Queueing device address = %pa\n",
- &binfo->device_addr[i]);
-
- if (binfo->handle[i] &&
- (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
- rc = msm_comm_smem_cache_operations(inst,
- binfo->handle[i], SMEM_CACHE_CLEAN);
- if (rc) {
- dprintk(VIDC_ERR,
- "Failed to clean caches: %d\n", rc);
- goto err_invalid_buff;
- }
- }
+ for (i = 0; i < b->length; i++) {
+ b->m.planes[i].m.fd = b->m.planes[i].reserved[0];
+ b->m.planes[i].data_offset = b->m.planes[i].reserved[1];
}
+ msm_comm_qbuf_cache_operations(inst, b);
q = msm_comm_get_vb2q(inst, b->type);
if (!q) {
@@ -1045,27 +461,28 @@
"Failed to find buffer queue for type = %d\n", b->type);
return -EINVAL;
}
+
mutex_lock(&q->lock);
rc = vb2_qbuf(&q->vb2_bufq, b);
mutex_unlock(&q->lock);
if (rc)
dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
- return rc;
-err_invalid_buff:
- return -EINVAL;
+ return rc;
}
EXPORT_SYMBOL(msm_vidc_qbuf);
int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
- struct buffer_info *buffer_info = NULL;
- int i = 0, rc = 0;
+ int rc = 0, i = 0;
struct buf_queue *q = NULL;
- if (!inst || !b || !valid_v4l2_buffer(b, inst))
+ if (!inst || !b || !valid_v4l2_buffer(b, inst)) {
+ dprintk(VIDC_ERR, "%s: invalid params, inst %pK\n",
+ __func__, inst);
return -EINVAL;
+ }
q = msm_comm_get_vb2q(inst, b->type);
if (!q) {
@@ -1073,54 +490,21 @@
"Failed to find buffer queue for type = %d\n", b->type);
return -EINVAL;
}
+
mutex_lock(&q->lock);
rc = vb2_dqbuf(&q->vb2_bufq, b, true);
mutex_unlock(&q->lock);
- if (rc) {
- dprintk(VIDC_DBG, "Failed to dqbuf, %d\n", rc);
+ if (rc == -EAGAIN) {
+ return rc;
+ } else if (rc) {
+ dprintk(VIDC_ERR, "Failed to dqbuf, %d\n", rc);
return rc;
}
+ msm_comm_dqbuf_cache_operations(inst, b);
for (i = 0; i < b->length; i++) {
- if (EXTRADATA_IDX(b->length) &&
- i == EXTRADATA_IDX(b->length)) {
- continue;
- }
- buffer_info = device_to_uvaddr(&inst->registeredbufs,
- b->m.planes[i].m.userptr);
-
- if (!buffer_info) {
- dprintk(VIDC_ERR,
- "%s no buffer info registered for buffer addr: %#lx\n",
- __func__, b->m.planes[i].m.userptr);
- return -EINVAL;
- }
-
- b->m.planes[i].m.userptr = buffer_info->uvaddr[i];
- b->m.planes[i].reserved[0] = buffer_info->fd[i];
- b->m.planes[i].reserved[1] = buffer_info->buff_off[i];
- }
-
- if (!buffer_info) {
- dprintk(VIDC_ERR,
- "%s: error - no buffer info found in registered list\n",
- __func__);
- return -EINVAL;
- }
-
- rc = output_buffer_cache_invalidate(inst, buffer_info);
- if (rc)
- return rc;
-
-
- if (is_dynamic_buffer_mode(b, inst)) {
- buffer_info->dequeued = true;
-
- dprintk(VIDC_DBG, "[DEQUEUED]: fd[0] = %d\n",
- buffer_info->fd[0]);
- mutex_lock(&inst->registeredbufs.lock);
- rc = unmap_and_deregister_buf(inst, buffer_info);
- mutex_unlock(&inst->registeredbufs.lock);
+ b->m.planes[i].reserved[0] = b->m.planes[i].m.fd;
+ b->m.planes[i].reserved[1] = b->m.planes[i].data_offset;
}
return rc;
@@ -1419,7 +803,6 @@
int rc = 0;
struct hfi_device *hdev;
struct hal_buffer_size_minimum b;
- struct vb2_buf_entry *temp, *next;
hdev = inst->core->device;
@@ -1536,15 +919,22 @@
fail_start:
if (rc) {
- mutex_lock(&inst->pendingq.lock);
- list_for_each_entry_safe(temp, next, &inst->pendingq.list,
- list) {
- vb2_buffer_done(temp->vb,
- VB2_BUF_STATE_QUEUED);
+ struct msm_vidc_buffer *temp, *next;
+
+ mutex_lock(&inst->registeredbufs.lock);
+ list_for_each_entry_safe(temp, next,
+ &inst->registeredbufs.list, list) {
+ struct vb2_buffer *vb;
+
+ print_vidc_buffer(VIDC_ERR, "return buf", inst, temp);
+ vb = msm_comm_get_vb_using_vidc_buffer(inst, temp);
+ if (vb)
+ vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED);
+ msm_comm_unmap_vidc_buffer(inst, temp);
list_del(&temp->list);
kfree(temp);
}
- mutex_unlock(&inst->pendingq.lock);
+ mutex_unlock(&inst->registeredbufs.lock);
}
return rc;
}
@@ -1651,12 +1041,29 @@
inst, q->type);
}
-static void msm_vidc_buf_queue(struct vb2_buffer *vb)
+static void msm_vidc_buf_queue(struct vb2_buffer *vb2)
{
- int rc = msm_comm_qbuf(vb2_get_drv_priv(vb->vb2_queue), vb);
+ int rc = 0;
+ struct msm_vidc_inst *inst = NULL;
+ struct msm_vidc_buffer *mbuf = NULL;
+ inst = vb2_get_drv_priv(vb2->vb2_queue);
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s: invalid inst\n", __func__);
+ return;
+ }
+
+ mbuf = msm_comm_get_vidc_buffer(inst, vb2);
+ if (IS_ERR_OR_NULL(mbuf)) {
+ if (PTR_ERR(mbuf) != -EEXIST)
+ print_vb2_buffer(VIDC_ERR, "failed to get vidc-buf",
+ inst, vb2);
+ return;
+ }
+
+ rc = msm_comm_qbuf(inst, mbuf);
if (rc)
- dprintk(VIDC_ERR, "Failed to queue buffer: %d\n", rc);
+ print_vidc_buffer(VIDC_ERR, "failed qbuf", inst, mbuf);
}
static const struct vb2_ops msm_vidc_vb2q_ops = {
@@ -2085,7 +1492,6 @@
mutex_init(&inst->bufq[OUTPUT_PORT].lock);
mutex_init(&inst->lock);
- INIT_MSM_VIDC_LIST(&inst->pendingq);
INIT_MSM_VIDC_LIST(&inst->scratchbufs);
INIT_MSM_VIDC_LIST(&inst->freqs);
INIT_MSM_VIDC_LIST(&inst->persistbufs);
@@ -2192,7 +1598,6 @@
mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
mutex_destroy(&inst->lock);
- DEINIT_MSM_VIDC_LIST(&inst->pendingq);
DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
@@ -2208,55 +1613,43 @@
static void cleanup_instance(struct msm_vidc_inst *inst)
{
- struct vb2_buf_entry *entry, *dummy;
-
- if (inst) {
-
- mutex_lock(&inst->pendingq.lock);
- list_for_each_entry_safe(entry, dummy, &inst->pendingq.list,
- list) {
- list_del(&entry->list);
- kfree(entry);
- }
- mutex_unlock(&inst->pendingq.lock);
-
- msm_comm_free_freq_table(inst);
-
- if (msm_comm_release_scratch_buffers(inst, false)) {
- dprintk(VIDC_ERR,
- "Failed to release scratch buffers\n");
- }
-
- if (msm_comm_release_recon_buffers(inst)) {
- dprintk(VIDC_ERR,
- "Failed to release recon buffers\n");
- }
-
- if (msm_comm_release_persist_buffers(inst)) {
- dprintk(VIDC_ERR,
- "Failed to release persist buffers\n");
- }
-
- /*
- * At this point all buffes should be with driver
- * irrespective of scenario
- */
- msm_comm_validate_output_buffers(inst);
-
- if (msm_comm_release_output_buffers(inst, true)) {
- dprintk(VIDC_ERR,
- "Failed to release output buffers\n");
- }
-
- if (inst->extradata_handle)
- msm_comm_smem_free(inst, inst->extradata_handle);
-
- debugfs_remove_recursive(inst->debugfs_root);
-
- mutex_lock(&inst->pending_getpropq.lock);
- WARN_ON(!list_empty(&inst->pending_getpropq.list));
- mutex_unlock(&inst->pending_getpropq.lock);
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
+ return;
}
+
+ msm_comm_free_freq_table(inst);
+
+ if (msm_comm_release_scratch_buffers(inst, false))
+ dprintk(VIDC_ERR,
+ "Failed to release scratch buffers\n");
+
+ if (msm_comm_release_recon_buffers(inst))
+ dprintk(VIDC_ERR,
+ "Failed to release recon buffers\n");
+
+ if (msm_comm_release_persist_buffers(inst))
+ dprintk(VIDC_ERR,
+ "Failed to release persist buffers\n");
+
+ /*
+ * At this point all buffes should be with driver
+ * irrespective of scenario
+ */
+ msm_comm_validate_output_buffers(inst);
+
+ if (msm_comm_release_output_buffers(inst, true))
+ dprintk(VIDC_ERR,
+ "Failed to release output buffers\n");
+
+ if (inst->extradata_handle)
+ msm_comm_smem_free(inst, inst->extradata_handle);
+
+ debugfs_remove_recursive(inst->debugfs_root);
+
+ mutex_lock(&inst->pending_getpropq.lock);
+ WARN_ON(!list_empty(&inst->pending_getpropq.list));
+ mutex_unlock(&inst->pending_getpropq.lock);
}
int msm_vidc_destroy(struct msm_vidc_inst *inst)
@@ -2264,8 +1657,10 @@
struct msm_vidc_core *core;
int i = 0;
- if (!inst || !inst->core)
+ if (!inst || !inst->core) {
+ dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
+ }
core = inst->core;
@@ -2276,7 +1671,6 @@
msm_comm_ctrl_deinit(inst);
- DEINIT_MSM_VIDC_LIST(&inst->pendingq);
DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
@@ -2300,22 +1694,24 @@
return 0;
}
+static void close_helper(struct kref *kref)
+{
+ struct msm_vidc_inst *inst = container_of(kref,
+ struct msm_vidc_inst, kref);
+
+ msm_vidc_destroy(inst);
+}
+
int msm_vidc_close(void *instance)
{
- void close_helper(struct kref *kref)
- {
- struct msm_vidc_inst *inst = container_of(kref,
- struct msm_vidc_inst, kref);
-
- msm_vidc_destroy(inst);
- }
-
struct msm_vidc_inst *inst = instance;
- struct buffer_info *bi, *dummy;
+ struct msm_vidc_buffer *temp, *dummy;
int rc = 0;
- if (!inst || !inst->core)
+ if (!inst || !inst->core) {
+ dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
+ }
/*
* Make sure that HW stop working on these buffers that
@@ -2327,19 +1723,13 @@
MSM_VIDC_RELEASE_RESOURCES_DONE);
mutex_lock(&inst->registeredbufs.lock);
- list_for_each_entry_safe(bi, dummy, &inst->registeredbufs.list, list) {
- int i = 0;
-
- list_del(&bi->list);
-
- for (i = 0; i < min(bi->num_planes, VIDEO_MAX_PLANES);
- i++) {
- if (bi->handle[i] && bi->mapped[i])
- msm_comm_smem_free(inst, bi->handle[i]);
- }
-
- kfree(bi);
- }
+ list_for_each_entry_safe(temp, dummy, &inst->registeredbufs.list,
+ list) {
+ print_vidc_buffer(VIDC_ERR, "undequeud buf", inst, temp);
+ msm_comm_unmap_vidc_buffer(inst, temp);
+ list_del(&temp->list);
+ kfree(temp);
+ }
mutex_unlock(&inst->registeredbufs.lock);
cleanup_instance(inst);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 60262a1..5e366d0 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -190,7 +190,7 @@
static inline int get_pending_bufs_fw(struct msm_vidc_inst *inst)
{
- int fw_out_qsize = 0, buffers_in_driver = 0;
+ int fw_out_qsize = 0;
/*
* DCVS always operates on Uncompressed buffers.
@@ -203,11 +203,9 @@
fw_out_qsize = inst->count.ftb - inst->count.fbd;
else
fw_out_qsize = inst->count.etb - inst->count.ebd;
-
- buffers_in_driver = inst->buffers_held_in_driver;
}
- return fw_out_qsize + buffers_in_driver;
+ return fw_out_qsize;
}
static int msm_dcvs_scale_clocks(struct msm_vidc_inst *inst)
@@ -266,7 +264,7 @@
}
static void msm_vidc_update_freq_entry(struct msm_vidc_inst *inst,
- unsigned long freq, ion_phys_addr_t device_addr)
+ unsigned long freq, u32 device_addr)
{
struct vidc_freq_data *temp, *next;
bool found = false;
@@ -292,7 +290,7 @@
// TODO this needs to be removed later and use queued_list
void msm_vidc_clear_freq_entry(struct msm_vidc_inst *inst,
- ion_phys_addr_t device_addr)
+ u32 device_addr)
{
struct vidc_freq_data *temp, *next;
@@ -515,10 +513,10 @@
int msm_comm_scale_clocks(struct msm_vidc_inst *inst)
{
- struct vb2_buf_entry *temp, *next;
+ struct msm_vidc_buffer *temp, *next;
unsigned long freq = 0;
u32 filled_len = 0;
- ion_phys_addr_t device_addr = 0;
+ u32 device_addr = 0;
if (!inst || !inst->core) {
dprintk(VIDC_ERR, "%s Invalid args: Inst = %pK\n",
@@ -526,15 +524,17 @@
return -EINVAL;
}
- mutex_lock(&inst->pendingq.lock);
- list_for_each_entry_safe(temp, next, &inst->pendingq.list, list) {
- if (temp->vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mutex_lock(&inst->registeredbufs.lock);
+ list_for_each_entry_safe(temp, next, &inst->registeredbufs.list, list) {
+ if (temp->vvb.vb2_buf.type ==
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+ temp->deferred) {
filled_len = max(filled_len,
- temp->vb->planes[0].bytesused);
- device_addr = temp->vb->planes[0].m.userptr;
+ temp->vvb.vb2_buf.planes[0].bytesused);
+ device_addr = temp->smem[0].device_addr;
}
}
- mutex_unlock(&inst->pendingq.lock);
+ mutex_unlock(&inst->registeredbufs.lock);
if (!filled_len || !device_addr) {
dprintk(VIDC_PROF, "No Change in frequency\n");
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
index db57647..e1226e4 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
@@ -42,7 +42,7 @@
int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst);
int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst);
void msm_vidc_clear_freq_entry(struct msm_vidc_inst *inst,
- ion_phys_addr_t device_addr);
+ u32 device_addr);
void update_recon_stats(struct msm_vidc_inst *inst,
struct recon_stats_type *recon_stats);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 12b7cc4..ee2a0e1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1068,9 +1068,9 @@
mutex_lock(&inst->scratchbufs.lock);
list_for_each_safe(ptr, next, &inst->scratchbufs.list) {
buf = list_entry(ptr, struct internal_buf, list);
- if (address == (u32)buf->handle->device_addr) {
- dprintk(VIDC_DBG, "releasing scratch: %pa\n",
- &buf->handle->device_addr);
+ if (address == buf->smem.device_addr) {
+ dprintk(VIDC_DBG, "releasing scratch: %x\n",
+ buf->smem.device_addr);
buf_found = true;
}
}
@@ -1079,9 +1079,9 @@
mutex_lock(&inst->persistbufs.lock);
list_for_each_safe(ptr, next, &inst->persistbufs.list) {
buf = list_entry(ptr, struct internal_buf, list);
- if (address == (u32)buf->handle->device_addr) {
- dprintk(VIDC_DBG, "releasing persist: %pa\n",
- &buf->handle->device_addr);
+ if (address == buf->smem.device_addr) {
+ dprintk(VIDC_DBG, "releasing persist: %x\n",
+ buf->smem.device_addr);
buf_found = true;
}
}
@@ -1447,6 +1447,20 @@
put_inst(inst);
}
+static void msm_vidc_queue_rbr_event(struct msm_vidc_inst *inst,
+ int fd, u32 offset)
+{
+ struct v4l2_event buf_event = {0};
+ u32 *ptr;
+
+ buf_event.type = V4L2_EVENT_RELEASE_BUFFER_REFERENCE;
+ ptr = (u32 *)buf_event.u.data;
+ ptr[0] = fd;
+ ptr[1] = offset;
+
+ v4l2_event_queue_fh(&inst->event_handler, &buf_event);
+}
+
static void handle_event_change(enum hal_command_response cmd, void *data)
{
struct msm_vidc_inst *inst = NULL;
@@ -1479,65 +1493,17 @@
break;
case HAL_EVENT_RELEASE_BUFFER_REFERENCE:
{
- struct v4l2_event buf_event = {0};
- struct buffer_info *binfo = NULL, *temp = NULL;
- u32 *ptr = NULL;
-
- dprintk(VIDC_DBG, "%s - inst: %pK buffer: %pa extra: %pa\n",
- __func__, inst, &event_notify->packet_buffer,
- &event_notify->extra_data_buffer);
-
- if (inst->state == MSM_VIDC_CORE_INVALID ||
- inst->core->state == VIDC_CORE_INVALID) {
- dprintk(VIDC_DBG,
- "Event release buf ref received in invalid state - discard\n");
- goto err_bad_event;
- }
-
- /*
- * Get the buffer_info entry for the
- * device address.
- */
- binfo = device_to_uvaddr(&inst->registeredbufs,
- event_notify->packet_buffer);
- if (!binfo) {
- dprintk(VIDC_ERR,
- "%s buffer not found in registered list\n",
- __func__);
- goto err_bad_event;
- }
-
- /* Fill event data to be sent to client*/
- buf_event.type = V4L2_EVENT_RELEASE_BUFFER_REFERENCE;
- ptr = (u32 *)buf_event.u.data;
- ptr[0] = binfo->fd[0];
- ptr[1] = binfo->buff_off[0];
+ u32 planes[VIDEO_MAX_PLANES] = {0};
dprintk(VIDC_DBG,
- "RELEASE REFERENCE EVENT FROM F/W - fd = %d offset = %d\n",
- ptr[0], ptr[1]);
+ "%s: inst: %pK data_buffer: %x extradata_buffer: %x\n",
+ __func__, inst, event_notify->packet_buffer,
+ event_notify->extra_data_buffer);
- /* Decrement buffer reference count*/
- mutex_lock(&inst->registeredbufs.lock);
- list_for_each_entry(temp, &inst->registeredbufs.list,
- list) {
- if (temp == binfo) {
- buf_ref_put(inst, binfo);
- break;
- }
- }
+ planes[0] = event_notify->packet_buffer;
+ planes[1] = event_notify->extra_data_buffer;
+ handle_release_buffer_reference(inst, planes);
- /*
- * Release buffer and remove from list
- * if reference goes to zero.
- */
- if (unmap_and_deregister_buf(inst, binfo))
- dprintk(VIDC_ERR,
- "%s: buffer unmap failed\n", __func__);
- mutex_unlock(&inst->registeredbufs.lock);
-
- /*send event to client*/
- v4l2_event_queue_fh(&inst->event_handler, &buf_event);
goto err_bad_event;
}
default:
@@ -1782,8 +1748,8 @@
list_for_each_entry(binfo, &inst->outputbufs.list, list) {
if (binfo->buffer_ownership != DRIVER) {
dprintk(VIDC_DBG,
- "This buffer is with FW %pa\n",
- &binfo->handle->device_addr);
+ "This buffer is with FW %x\n",
+ binfo->smem.device_addr);
continue;
}
buffers_owned_by_driver++;
@@ -1803,7 +1769,6 @@
{
struct internal_buf *binfo;
struct hfi_device *hdev;
- struct msm_smem *handle;
struct vidc_frame_data frame_data = {0};
struct hal_buffer_requirements *output_buf, *extra_buf;
int rc = 0;
@@ -1833,13 +1798,12 @@
list_for_each_entry(binfo, &inst->outputbufs.list, list) {
if (binfo->buffer_ownership != DRIVER)
continue;
- handle = binfo->handle;
frame_data.alloc_len = output_buf->buffer_size;
frame_data.filled_len = 0;
frame_data.offset = 0;
- frame_data.device_addr = handle->device_addr;
+ frame_data.device_addr = binfo->smem.device_addr;
frame_data.flags = 0;
- frame_data.extradata_addr = handle->device_addr +
+ frame_data.extradata_addr = binfo->smem.device_addr +
output_buf->buffer_size;
frame_data.buffer_type = HAL_BUFFER_OUTPUT;
frame_data.extradata_size = extra_buf ?
@@ -1890,7 +1854,7 @@
}
}
}
- atomic_dec(&inst->in_flush);
+ inst->in_flush = false;
flush_event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
ptr = (u32 *)flush_event.u.data;
@@ -2113,82 +2077,84 @@
put_inst(inst);
}
-static struct vb2_buffer *get_vb_from_device_addr(struct buf_queue *bufq,
- unsigned long dev_addr)
+struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer(
+ struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
{
+ u32 port = 0;
struct vb2_buffer *vb = NULL;
struct vb2_queue *q = NULL;
- int found = 0;
+ bool found = false;
- if (!bufq) {
- dprintk(VIDC_ERR, "Invalid parameter\n");
+ if (mbuf->vvb.vb2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ port = CAPTURE_PORT;
+ } else if (mbuf->vvb.vb2_buf.type ==
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ port = OUTPUT_PORT;
+ } else {
+ dprintk(VIDC_ERR, "%s: invalid type %d\n",
+ __func__, mbuf->vvb.vb2_buf.type);
return NULL;
}
- q = &bufq->vb2_bufq;
- mutex_lock(&bufq->lock);
+
+ q = &inst->bufq[port].vb2_bufq;
+ mutex_lock(&inst->bufq[port].lock);
+ found = false;
list_for_each_entry(vb, &q->queued_list, queued_entry) {
- if (vb->planes[0].m.userptr == dev_addr &&
- vb->state == VB2_BUF_STATE_ACTIVE) {
- found = 1;
- dprintk(VIDC_DBG, "Found v4l2_buf index : %d\n",
- vb->index);
+ if (msm_comm_compare_vb2_planes(inst, mbuf, vb)) {
+ found = true;
break;
}
}
- mutex_unlock(&bufq->lock);
+ mutex_unlock(&inst->bufq[port].lock);
if (!found) {
- dprintk(VIDC_DBG,
- "Failed to find buffer in queued list: %#lx, qtype = %d\n",
- dev_addr, q->type);
- vb = NULL;
+ print_vidc_buffer(VIDC_ERR, "vb2 not found for", inst, mbuf);
+ return NULL;
}
+
return vb;
}
-static void handle_dynamic_buffer(struct msm_vidc_inst *inst,
- ion_phys_addr_t device_addr, u32 flags)
+int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
+ struct vb2_buffer *vb)
{
- struct buffer_info *binfo = NULL, *temp = NULL;
+ u32 port;
- /*
- * Update reference count and release OR queue back the buffer,
- * only when firmware is not holding a reference.
- */
- binfo = device_to_uvaddr(&inst->registeredbufs, device_addr);
- if (!binfo) {
- dprintk(VIDC_ERR,
- "%s buffer not found in registered list\n",
- __func__);
- return;
+ if (!inst || !vb) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
+ __func__, inst, vb);
+ return -EINVAL;
}
- if (flags & HAL_BUFFERFLAG_READONLY) {
- dprintk(VIDC_DBG,
- "FBD fd[0] = %d -> Reference with f/w, addr: %pa\n",
- binfo->fd[0], &device_addr);
+
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ port = CAPTURE_PORT;
+ } else if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ port = OUTPUT_PORT;
} else {
- dprintk(VIDC_DBG,
- "FBD fd[0] = %d -> FBD_ref_released, addr: %pa\n",
- binfo->fd[0], &device_addr);
-
- mutex_lock(&inst->registeredbufs.lock);
- list_for_each_entry(temp, &inst->registeredbufs.list,
- list) {
- if (temp == binfo) {
- buf_ref_put(inst, binfo);
- break;
- }
- }
- mutex_unlock(&inst->registeredbufs.lock);
+ dprintk(VIDC_ERR, "%s: invalid type %d\n",
+ __func__, vb->type);
+ return -EINVAL;
}
+ msm_vidc_debugfs_update(inst, port == CAPTURE_PORT ?
+ MSM_VIDC_DEBUGFS_EVENT_FBD :
+ MSM_VIDC_DEBUGFS_EVENT_EBD);
+
+ mutex_lock(&inst->bufq[port].lock);
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ mutex_unlock(&inst->bufq[port].lock);
+
+ return 0;
}
static void handle_ebd(enum hal_command_response cmd, void *data)
{
struct msm_vidc_cb_data_done *response = data;
+ struct msm_vidc_buffer *mbuf;
struct vb2_buffer *vb;
struct msm_vidc_inst *inst;
struct vidc_hal_ebd *empty_buf_done;
- struct vb2_v4l2_buffer *vbuf = NULL;
+ struct vb2_v4l2_buffer *vbuf;
+ u32 planes[VIDEO_MAX_PLANES] = {0};
+ u32 extra_idx = 0, i;
if (!response) {
dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
@@ -2201,140 +2167,79 @@
dprintk(VIDC_WARN, "Got a response for an inactive session\n");
return;
}
- if (inst->buffer_mode_set[OUTPUT_PORT] == HAL_BUFFER_MODE_DYNAMIC)
- handle_dynamic_buffer(inst,
- response->input_done.packet_buffer, 0);
- vb = get_vb_from_device_addr(&inst->bufq[OUTPUT_PORT],
- response->input_done.packet_buffer);
+ empty_buf_done = (struct vidc_hal_ebd *)&response->input_done;
+ planes[0] = empty_buf_done->packet_buffer;
+ planes[1] = empty_buf_done->extra_data_buffer;
+
+ mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
+ if (!mbuf) {
+ dprintk(VIDC_ERR,
+ "%s: data_addr %x, extradata_addr %x not found\n",
+ __func__, planes[0], planes[1]);
+ goto exit;
+ }
+ vb = &mbuf->vvb.vb2_buf;
+
+ vb->planes[0].bytesused = response->input_done.filled_len;
+ if (vb->planes[0].bytesused > vb->planes[0].length)
+ dprintk(VIDC_INFO, "bytesused overflow length\n");
+
+ if (empty_buf_done->status == VIDC_ERR_NOT_SUPPORTED) {
+ dprintk(VIDC_INFO, "Failed : Unsupported input stream\n");
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_INPUT_UNSUPPORTED;
+ }
+ if (empty_buf_done->status == VIDC_ERR_BITSTREAM_ERR) {
+ dprintk(VIDC_INFO, "Failed : Corrupted input stream\n");
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
+ }
+ if (empty_buf_done->flags & HAL_BUFFERFLAG_SYNCFRAME)
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME |
+ V4L2_BUF_FLAG_KEYFRAME;
+
+ extra_idx = EXTRADATA_IDX(inst->bufq[OUTPUT_PORT].num_planes);
+ if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
+ vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
+
+ update_recon_stats(inst, &empty_buf_done->recon_stats);
+ msm_vidc_clear_freq_entry(inst, mbuf->smem[0].device_addr);
+
+ vb = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
if (vb) {
vbuf = to_vb2_v4l2_buffer(vb);
- vb->planes[0].bytesused = response->input_done.filled_len;
- vb->planes[0].data_offset = response->input_done.offset;
- if (vb->planes[0].data_offset > vb->planes[0].length)
- dprintk(VIDC_INFO, "data_offset overflow length\n");
- if (vb->planes[0].bytesused > vb->planes[0].length)
- dprintk(VIDC_INFO, "bytesused overflow length\n");
- if (vb->planes[0].m.userptr !=
- response->clnt_data)
- dprintk(VIDC_INFO, "Client data != bufaddr\n");
- empty_buf_done = (struct vidc_hal_ebd *)&response->input_done;
- if (empty_buf_done) {
- if (empty_buf_done->status == VIDC_ERR_NOT_SUPPORTED) {
- dprintk(VIDC_INFO,
- "Failed : Unsupported input stream\n");
- vbuf->flags |=
- V4L2_QCOM_BUF_INPUT_UNSUPPORTED;
- }
- if (empty_buf_done->status == VIDC_ERR_BITSTREAM_ERR) {
- dprintk(VIDC_INFO,
- "Failed : Corrupted input stream\n");
- vbuf->flags |=
- V4L2_QCOM_BUF_DATA_CORRUPT;
- }
- if (empty_buf_done->flags & HAL_BUFFERFLAG_SYNCFRAME)
- vbuf->flags |=
- V4L2_QCOM_BUF_FLAG_IDRFRAME |
- V4L2_BUF_FLAG_KEYFRAME;
- }
-
- update_recon_stats(inst, &empty_buf_done->recon_stats);
-
- dprintk(VIDC_DBG,
- "Got ebd from hal: device_addr: %pa, alloc: %d, status: %#x, pic_type: %#x, flags: %#x\n",
- &empty_buf_done->packet_buffer,
- empty_buf_done->alloc_len, empty_buf_done->status,
- empty_buf_done->picture_type, empty_buf_done->flags);
-
- msm_vidc_clear_freq_entry(inst, empty_buf_done->packet_buffer);
-
- mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
- mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);
- msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD);
+ vbuf->flags |= mbuf->vvb.flags;
+ for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++)
+ vb->planes[i].bytesused =
+ mbuf->vvb.vb2_buf.planes[i].bytesused;
}
+ /*
+ * put_buffer should be done before vb2_buffer_done else
+ * client might queue the same buffer before it is unmapped
+ * in put_buffer. also don't use mbuf after put_buffer
+ * as it may be freed in put_buffer.
+ */
+ msm_comm_put_vidc_buffer(inst, mbuf);
+ msm_comm_vb2_buffer_done(inst, vb);
+exit:
put_inst(inst);
}
-int buf_ref_get(struct msm_vidc_inst *inst, struct buffer_info *binfo)
-{
- int cnt = 0;
-
- if (!inst || !binfo)
- return -EINVAL;
-
- atomic_inc(&binfo->ref_count);
- cnt = atomic_read(&binfo->ref_count);
- if (cnt >= 2)
- inst->buffers_held_in_driver++;
-
- dprintk(VIDC_DBG, "REF_GET[%d] fd[0] = %d\n", cnt, binfo->fd[0]);
-
- return cnt;
-}
-
-int buf_ref_put(struct msm_vidc_inst *inst, struct buffer_info *binfo)
-{
- int rc = 0;
- int cnt;
- bool release_buf = false;
- bool qbuf_again = false;
-
- if (!inst || !binfo)
- return -EINVAL;
-
- atomic_dec(&binfo->ref_count);
- cnt = atomic_read(&binfo->ref_count);
- dprintk(VIDC_DBG, "REF_PUT[%d] fd[0] = %d\n", cnt, binfo->fd[0]);
- if (!cnt)
- release_buf = true;
- else if (cnt >= 1)
- qbuf_again = true;
- else {
- dprintk(VIDC_DBG, "%s: invalid ref_cnt: %d\n", __func__, cnt);
- cnt = -EINVAL;
- }
-
- if (cnt < 0)
- return cnt;
-
- if (release_buf) {
- /*
- * We can not delete binfo here as we need to set the user
- * virtual address saved in binfo->uvaddr to the dequeued v4l2
- * buffer.
- *
- * We will set the pending_deletion flag to true here and delete
- * binfo from registered list in dqbuf after setting the uvaddr.
- */
- dprintk(VIDC_DBG, "fd[0] = %d -> pending_deletion = true\n",
- binfo->fd[0]);
- binfo->pending_deletion = true;
- } else if (qbuf_again) {
- inst->buffers_held_in_driver--;
- rc = qbuf_dynamic_buf(inst, binfo);
- if (!rc)
- return rc;
- }
- return cnt;
-}
-
static int handle_multi_stream_buffers(struct msm_vidc_inst *inst,
- ion_phys_addr_t dev_addr)
+ u32 dev_addr)
{
struct internal_buf *binfo;
- struct msm_smem *handle;
+ struct msm_smem *smem;
bool found = false;
mutex_lock(&inst->outputbufs.lock);
list_for_each_entry(binfo, &inst->outputbufs.list, list) {
- handle = binfo->handle;
- if (handle && dev_addr == handle->device_addr) {
+ smem = &binfo->smem;
+ if (smem && dev_addr == smem->device_addr) {
if (binfo->buffer_ownership == DRIVER) {
dprintk(VIDC_ERR,
- "FW returned same buffer: %pa\n",
- &dev_addr);
+ "FW returned same buffer: %x\n",
+ dev_addr);
break;
}
binfo->buffer_ownership = DRIVER;
@@ -2346,8 +2251,8 @@
if (!found) {
dprintk(VIDC_ERR,
- "Failed to find output buffer in queued list: %pa\n",
- &dev_addr);
+ "Failed to find output buffer in queued list: %x\n",
+ dev_addr);
}
return 0;
@@ -2365,13 +2270,15 @@
static void handle_fbd(enum hal_command_response cmd, void *data)
{
struct msm_vidc_cb_data_done *response = data;
+ struct msm_vidc_buffer *mbuf;
struct msm_vidc_inst *inst;
struct vb2_buffer *vb = NULL;
struct vidc_hal_fbd *fill_buf_done;
+ struct vb2_v4l2_buffer *vbuf;
enum hal_buffer buffer_type;
- int extra_idx = 0;
u64 time_usec = 0;
- struct vb2_v4l2_buffer *vbuf = NULL;
+ u32 planes[VIDEO_MAX_PLANES] = {0};
+ u32 extra_idx, i;
if (!response) {
dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
@@ -2386,132 +2293,117 @@
}
fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
+ planes[0] = fill_buf_done->packet_buffer1;
+ planes[1] = fill_buf_done->extra_data_buffer;
+
buffer_type = msm_comm_get_hal_output_buffer(inst);
if (fill_buf_done->buffer_type == buffer_type) {
- vb = get_vb_from_device_addr(&inst->bufq[CAPTURE_PORT],
- fill_buf_done->packet_buffer1);
+ mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
+ if (!mbuf) {
+ dprintk(VIDC_ERR,
+ "%s: data_addr %x, extradata_addr %x not found\n",
+ __func__, planes[0], planes[1]);
+ goto exit;
+ }
} else {
if (handle_multi_stream_buffers(inst,
fill_buf_done->packet_buffer1))
dprintk(VIDC_ERR,
"Failed : Output buffer not found %pa\n",
&fill_buf_done->packet_buffer1);
- goto err_handle_fbd;
+ goto exit;
+ }
+ vb = &mbuf->vvb.vb2_buf;
+
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME ||
+ fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY)
+ fill_buf_done->filled_len1 = 0;
+ vb->planes[0].bytesused = fill_buf_done->filled_len1;
+ if (vb->planes[0].bytesused > vb->planes[0].length)
+ dprintk(VIDC_INFO,
+ "fbd:Overflow bytesused = %d; length = %d\n",
+ vb->planes[0].bytesused,
+ vb->planes[0].length);
+ if (vb->planes[0].data_offset != fill_buf_done->offset1)
+ dprintk(VIDC_ERR, "%s: data_offset %d vs %d\n",
+ __func__, vb->planes[0].data_offset,
+ fill_buf_done->offset1);
+ if (!(fill_buf_done->flags1 & HAL_BUFFERFLAG_TIMESTAMPINVALID)) {
+ time_usec = fill_buf_done->timestamp_hi;
+ time_usec = (time_usec << 32) | fill_buf_done->timestamp_lo;
+ } else {
+ time_usec = 0;
+ dprintk(VIDC_DBG,
+ "Set zero timestamp for buffer %pa, filled: %d, (hi:%u, lo:%u)\n",
+ &fill_buf_done->packet_buffer1,
+ fill_buf_done->filled_len1,
+ fill_buf_done->timestamp_hi,
+ fill_buf_done->timestamp_lo);
+ }
+ vb->timestamp = (time_usec * NSEC_PER_USEC);
+
+ extra_idx = EXTRADATA_IDX(inst->bufq[CAPTURE_PORT].num_planes);
+ if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
+ vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
+
+ mbuf->vvb.flags = 0;
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_READONLY)
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_READONLY;
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_EOS;
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_CODECCONFIG;
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_SYNCFRAME)
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOSEQ)
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_EOSEQ;
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY ||
+ fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME)
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
+ switch (fill_buf_done->picture_type) {
+ case HAL_PICTURE_IDR:
+ mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
+ mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ break;
+ case HAL_PICTURE_I:
+ mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ break;
+ case HAL_PICTURE_P:
+ mbuf->vvb.flags |= V4L2_BUF_FLAG_PFRAME;
+ break;
+ case HAL_PICTURE_B:
+ mbuf->vvb.flags |= V4L2_BUF_FLAG_BFRAME;
+ break;
+ case HAL_FRAME_NOTCODED:
+ case HAL_UNUSED_PICT:
+ /* Do we need to care about these? */
+ case HAL_FRAME_YUV:
+ break;
+ default:
+ break;
}
+ vb = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
if (vb) {
vbuf = to_vb2_v4l2_buffer(vb);
- if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME ||
- fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY)
- fill_buf_done->filled_len1 = 0;
- vb->planes[0].bytesused = fill_buf_done->filled_len1;
- vb->planes[0].data_offset = fill_buf_done->offset1;
- if (vb->planes[0].data_offset > vb->planes[0].length)
- dprintk(VIDC_INFO,
- "fbd:Overflow data_offset = %d; length = %d\n",
- vb->planes[0].data_offset,
- vb->planes[0].length);
- if (vb->planes[0].bytesused > vb->planes[0].length)
- dprintk(VIDC_INFO,
- "fbd:Overflow bytesused = %d; length = %d\n",
- vb->planes[0].bytesused,
- vb->planes[0].length);
- if (!(fill_buf_done->flags1 &
- HAL_BUFFERFLAG_TIMESTAMPINVALID)) {
- time_usec = fill_buf_done->timestamp_hi;
- time_usec = (time_usec << 32) |
- fill_buf_done->timestamp_lo;
- } else {
- time_usec = 0;
- dprintk(VIDC_DBG,
- "Set zero timestamp for buffer %pa, filled: %d, (hi:%u, lo:%u)\n",
- &fill_buf_done->packet_buffer1,
- fill_buf_done->filled_len1,
- fill_buf_done->timestamp_hi,
- fill_buf_done->timestamp_lo);
- }
- vbuf->flags = 0;
- vb->timestamp = (time_usec * NSEC_PER_USEC);
-
- extra_idx =
- EXTRADATA_IDX(inst->bufq[CAPTURE_PORT].num_planes);
- if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
- vb->planes[extra_idx].m.userptr =
- (unsigned long)fill_buf_done->extra_data_buffer;
- vb->planes[extra_idx].bytesused =
- vb->planes[extra_idx].length;
- vb->planes[extra_idx].data_offset = 0;
- }
-
- if (inst->buffer_mode_set[CAPTURE_PORT] ==
- HAL_BUFFER_MODE_DYNAMIC)
- handle_dynamic_buffer(inst, fill_buf_done->packet_buffer1,
- fill_buf_done->flags1);
- if (fill_buf_done->flags1 & HAL_BUFFERFLAG_READONLY)
- vbuf->flags |= V4L2_QCOM_BUF_FLAG_READONLY;
- if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
- vbuf->flags |= V4L2_QCOM_BUF_FLAG_EOS;
- if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
- vbuf->flags |= V4L2_QCOM_BUF_FLAG_CODECCONFIG;
- if (fill_buf_done->flags1 & HAL_BUFFERFLAG_SYNCFRAME)
- vbuf->flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
- if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOSEQ)
- vbuf->flags |= V4L2_QCOM_BUF_FLAG_EOSEQ;
- if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY ||
- fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME)
- vbuf->flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
- if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
- vbuf->flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
-
- switch (fill_buf_done->picture_type) {
- case HAL_PICTURE_IDR:
- vbuf->flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
- vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
- break;
- case HAL_PICTURE_I:
- vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
- break;
- case HAL_PICTURE_P:
- vbuf->flags |= V4L2_BUF_FLAG_PFRAME;
- break;
- case HAL_PICTURE_B:
- vbuf->flags |= V4L2_BUF_FLAG_BFRAME;
- break;
- case HAL_FRAME_NOTCODED:
- case HAL_UNUSED_PICT:
- /* Do we need to care about these? */
- case HAL_FRAME_YUV:
- break;
- default:
- break;
- }
-
- inst->count.fbd++;
-
- if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
- dprintk(VIDC_DBG,
- "extradata: userptr = %pK;"
- " bytesused = %d; length = %d\n",
- (u8 *)vb->planes[extra_idx].m.userptr,
- vb->planes[extra_idx].bytesused,
- vb->planes[extra_idx].length);
- }
- dprintk(VIDC_DBG,
- "Got fbd from hal: device_addr: %pa, alloc: %d, filled: %d, offset: %d, ts: %lld, flags: %#x, crop: %d %d %d %d, pic_type: %#x, mark_data: %#x\n",
- &fill_buf_done->packet_buffer1, fill_buf_done->alloc_len1,
- fill_buf_done->filled_len1, fill_buf_done->offset1, time_usec,
- fill_buf_done->flags1, fill_buf_done->start_x_coord,
- fill_buf_done->start_y_coord, fill_buf_done->frame_width,
- fill_buf_done->frame_height, fill_buf_done->picture_type,
- fill_buf_done->mark_data);
-
- mutex_lock(&inst->bufq[CAPTURE_PORT].lock);
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
- mutex_unlock(&inst->bufq[CAPTURE_PORT].lock);
- msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD);
+ vbuf->flags = mbuf->vvb.flags;
+ vb->timestamp = mbuf->vvb.vb2_buf.timestamp;
+ for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++)
+ vb->planes[i].bytesused =
+ mbuf->vvb.vb2_buf.planes[i].bytesused;
}
+ /*
+ * put_buffer should be done before vb2_buffer_done else
+ * client might queue the same buffer before it is unmapped
+ * in put_buffer. also don't use mbuf after put_buffer
+ * as it may be freed in put_buffer.
+ */
+ msm_comm_put_vidc_buffer(inst, mbuf);
+ msm_comm_vb2_buffer_done(inst, vb);
-err_handle_fbd:
+exit:
put_inst(inst);
}
@@ -3247,7 +3139,6 @@
enum hal_buffer buffer_type)
{
int rc = 0;
- struct msm_smem *handle;
struct internal_buf *binfo;
u32 smem_flags = 0, buffer_size;
struct hal_buffer_requirements *output_buf, *extradata_buf;
@@ -3295,33 +3186,30 @@
if (output_buf->buffer_size) {
for (i = 0; i < output_buf->buffer_count_actual;
i++) {
- handle = msm_comm_smem_alloc(inst,
- buffer_size, 1, smem_flags,
- buffer_type, 0);
- if (!handle) {
- dprintk(VIDC_ERR,
- "Failed to allocate output memory\n");
- rc = -ENOMEM;
- goto err_no_mem;
- }
- rc = msm_comm_smem_cache_operations(inst,
- handle, SMEM_CACHE_CLEAN);
- if (rc) {
- dprintk(VIDC_WARN,
- "Failed to clean cache may cause undefined behavior\n");
- }
binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
if (!binfo) {
dprintk(VIDC_ERR, "Out of memory\n");
rc = -ENOMEM;
goto fail_kzalloc;
}
-
- binfo->handle = handle;
+ rc = msm_comm_smem_alloc(inst,
+ buffer_size, 1, smem_flags,
+ buffer_type, 0, &binfo->smem);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to allocate output memory\n");
+ goto err_no_mem;
+ }
+ rc = msm_comm_smem_cache_operations(inst,
+ &binfo->smem, SMEM_CACHE_CLEAN);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to clean cache may cause undefined behavior\n");
+ }
binfo->buffer_type = buffer_type;
binfo->buffer_ownership = DRIVER;
- dprintk(VIDC_DBG, "Output buffer address: %pa\n",
- &handle->device_addr);
+ dprintk(VIDC_DBG, "Output buffer address: %#x\n",
+ binfo->smem.device_addr);
if (inst->buffer_mode_set[CAPTURE_PORT] ==
HAL_BUFFER_MODE_STATIC) {
@@ -3332,9 +3220,9 @@
buffer_info.buffer_type = buffer_type;
buffer_info.num_buffers = 1;
buffer_info.align_device_addr =
- handle->device_addr;
+ binfo->smem.device_addr;
buffer_info.extradata_addr =
- handle->device_addr +
+ binfo->smem.device_addr +
output_buf->buffer_size;
if (extradata_buf)
buffer_info.extradata_size =
@@ -3357,7 +3245,7 @@
fail_set_buffers:
kfree(binfo);
fail_kzalloc:
- msm_comm_smem_free(inst, handle);
+ msm_comm_smem_free(inst, &binfo->smem);
err_no_mem:
return rc;
}
@@ -3407,10 +3295,10 @@
buffer_info.buffer_type = buffer_type;
buffer_info.num_buffers = 1;
buffer_info.align_device_addr = handle->device_addr;
- dprintk(VIDC_DBG, "%s %s buffer : %pa\n",
+ dprintk(VIDC_DBG, "%s %s buffer : %x\n",
reuse ? "Reusing" : "Allocated",
get_buffer_name(buffer_type),
- &buffer_info.align_device_addr);
+ buffer_info.align_device_addr);
rc = call_hfi_op(hdev, session_set_buffers,
(void *) inst->session, &buffer_info);
@@ -3436,11 +3324,6 @@
mutex_lock(&buf_list->lock);
list_for_each_entry(buf, &buf_list->list, list) {
- if (!buf->handle) {
- reused = false;
- break;
- }
-
if (buf->buffer_type != buffer_type)
continue;
@@ -3456,7 +3339,7 @@
&& buffer_type != HAL_BUFFER_INTERNAL_PERSIST_1) {
rc = set_internal_buf_on_fw(inst, buffer_type,
- buf->handle, true);
+ &buf->smem, true);
if (rc) {
dprintk(VIDC_ERR,
"%s: session_set_buffers failed\n",
@@ -3477,7 +3360,6 @@
struct hal_buffer_requirements *internal_bufreq,
struct msm_vidc_list *buf_list)
{
- struct msm_smem *handle;
struct internal_buf *binfo;
u32 smem_flags = 0;
int rc = 0;
@@ -3493,27 +3375,25 @@
smem_flags |= SMEM_SECURE;
for (i = 0; i < internal_bufreq->buffer_count_actual; i++) {
- handle = msm_comm_smem_alloc(inst, internal_bufreq->buffer_size,
- 1, smem_flags, internal_bufreq->buffer_type, 0);
- if (!handle) {
- dprintk(VIDC_ERR,
- "Failed to allocate scratch memory\n");
- rc = -ENOMEM;
- goto err_no_mem;
- }
-
binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
if (!binfo) {
dprintk(VIDC_ERR, "Out of memory\n");
rc = -ENOMEM;
goto fail_kzalloc;
}
+ rc = msm_comm_smem_alloc(inst, internal_bufreq->buffer_size,
+ 1, smem_flags, internal_bufreq->buffer_type,
+ 0, &binfo->smem);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to allocate scratch memory\n");
+ goto err_no_mem;
+ }
- binfo->handle = handle;
binfo->buffer_type = internal_bufreq->buffer_type;
rc = set_internal_buf_on_fw(inst, internal_bufreq->buffer_type,
- handle, false);
+ &binfo->smem, false);
if (rc)
goto fail_set_buffers;
@@ -3524,10 +3404,10 @@
return rc;
fail_set_buffers:
+ msm_comm_smem_free(inst, &binfo->smem);
+err_no_mem:
kfree(binfo);
fail_kzalloc:
- msm_comm_smem_free(inst, handle);
-err_no_mem:
return rc;
}
@@ -3766,25 +3646,32 @@
}
static void populate_frame_data(struct vidc_frame_data *data,
- const struct vb2_buffer *vb, struct msm_vidc_inst *inst)
+ struct msm_vidc_buffer *mbuf, struct msm_vidc_inst *inst)
{
u64 time_usec;
int extra_idx;
- enum v4l2_buf_type type = vb->type;
- enum vidc_ports port = type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
- OUTPUT_PORT : CAPTURE_PORT;
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vb2_buffer *vb;
+ struct vb2_v4l2_buffer *vbuf;
+
+ if (!inst || !mbuf || !data) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
+ __func__, inst, mbuf, data);
+ return;
+ }
+
+ vb = &mbuf->vvb.vb2_buf;
+ vbuf = to_vb2_v4l2_buffer(vb);
time_usec = vb->timestamp;
do_div(time_usec, NSEC_PER_USEC);
data->alloc_len = vb->planes[0].length;
- data->device_addr = vb->planes[0].m.userptr;
+ data->device_addr = mbuf->smem[0].device_addr;
data->timestamp = time_usec;
data->flags = 0;
data->clnt_data = data->device_addr;
- if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
bool pic_decoding_mode = msm_comm_g_ctrl_for_id(inst,
V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE);
@@ -3812,59 +3699,64 @@
data->mark_data = data->mark_target =
pic_decoding_mode ? 0xdeadbeef : 0;
- } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ } else if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
data->buffer_type = msm_comm_get_hal_output_buffer(inst);
}
- extra_idx = EXTRADATA_IDX(inst->bufq[port].num_planes);
- if (extra_idx && extra_idx < VIDEO_MAX_PLANES &&
- vb->planes[extra_idx].m.userptr) {
- data->extradata_addr = vb->planes[extra_idx].m.userptr;
+ extra_idx = EXTRADATA_IDX(vb->num_planes);
+ if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
+ data->extradata_addr = mbuf->smem[extra_idx].device_addr;
data->extradata_size = vb->planes[extra_idx].length;
data->flags |= HAL_BUFFERFLAG_EXTRADATA;
}
}
-static unsigned int count_single_batch(struct msm_vidc_list *list,
+static unsigned int count_single_batch(struct msm_vidc_inst *inst,
enum v4l2_buf_type type)
{
- struct vb2_buf_entry *buf;
int count = 0;
- struct vb2_v4l2_buffer *vbuf = NULL;
+ struct msm_vidc_buffer *mbuf = NULL;
- mutex_lock(&list->lock);
- list_for_each_entry(buf, &list->list, list) {
- if (buf->vb->type != type)
+ mutex_lock(&inst->registeredbufs.lock);
+ list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
+ if (mbuf->vvb.vb2_buf.type != type)
+ continue;
+
+ /* count only deferred buffers */
+ if (!mbuf->deferred)
continue;
++count;
- vbuf = to_vb2_v4l2_buffer(buf->vb);
- if (!(vbuf->flags & V4L2_MSM_BUF_FLAG_DEFER))
+ if (!(mbuf->vvb.flags & V4L2_MSM_BUF_FLAG_DEFER))
goto found_batch;
}
- /* don't have a full batch */
+ /* don't have a full batch */
count = 0;
found_batch:
- mutex_unlock(&list->lock);
+ mutex_unlock(&inst->registeredbufs.lock);
return count;
}
-static unsigned int count_buffers(struct msm_vidc_list *list,
+static unsigned int count_buffers(struct msm_vidc_inst *inst,
enum v4l2_buf_type type)
{
- struct vb2_buf_entry *buf;
+ struct msm_vidc_buffer *mbuf;
int count = 0;
- mutex_lock(&list->lock);
- list_for_each_entry(buf, &list->list, list) {
- if (buf->vb->type != type)
+ mutex_lock(&inst->registeredbufs.lock);
+ list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
+ if (mbuf->vvb.vb2_buf.type != type)
+ continue;
+
+ /* count only deferred buffers */
+ if (!mbuf->deferred)
continue;
++count;
}
- mutex_unlock(&list->lock);
+ mutex_unlock(&inst->registeredbufs.lock);
return count;
}
@@ -3875,27 +3767,45 @@
if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
dprintk(VIDC_DBG,
- "Sending etb (%pa) to hal: filled: %d, ts: %lld, flags = %#x\n",
- &data->device_addr, data->filled_len,
+ "Sending etb (%x) to hal: filled: %d, ts: %lld, flags = %#x\n",
+ data->device_addr, data->filled_len,
data->timestamp, data->flags);
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_ETB);
} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
dprintk(VIDC_DBG,
- "Sending ftb (%pa) to hal: size: %d, ts: %lld, flags = %#x\n",
- &data->device_addr, data->alloc_len,
+ "Sending ftb (%x) to hal: size: %d, ts: %lld, flags = %#x\n",
+ data->device_addr, data->alloc_len,
data->timestamp, data->flags);
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FTB);
}
}
+enum hal_buffer get_hal_buffer_type(unsigned int type,
+ unsigned int plane_num)
+{
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (plane_num == 0)
+ return HAL_BUFFER_INPUT;
+ else
+ return HAL_BUFFER_EXTRADATA_INPUT;
+ } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (plane_num == 0)
+ return HAL_BUFFER_OUTPUT;
+ else
+ return HAL_BUFFER_EXTRADATA_OUTPUT;
+ } else {
+ return -EINVAL;
+ }
+}
+
/*
* Attempts to queue `vb` to hardware. If, for various reasons, the buffer
* cannot be queued to hardware, the buffer will be staged for commit in the
* pending queue. Once the hardware reaches a good state (or if `vb` is NULL,
* the subsequent *_qbuf will commit the previously staged buffers to hardware.
*/
-int msm_comm_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb)
+int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
{
int rc = 0, capture_count, output_count;
struct msm_vidc_core *core;
@@ -3905,8 +3815,7 @@
int count;
} etbs, ftbs;
bool defer = false, batch_mode;
- struct vb2_buf_entry *temp, *next;
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct msm_vidc_buffer *temp = NULL, *next = NULL;
if (!inst) {
dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
@@ -3916,36 +3825,21 @@
core = inst->core;
hdev = core->device;
- if (inst->state == MSM_VIDC_CORE_INVALID ||
- core->state == VIDC_CORE_INVALID ||
- core->state == VIDC_CORE_UNINIT) {
- dprintk(VIDC_ERR, "Core is in bad state. Can't Queue\n");
+ if (inst->state == MSM_VIDC_CORE_INVALID) {
+ dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__);
return -EINVAL;
}
- /*
- * Stick the buffer into the pendinq, we'll pop it out later on
- * if we want to commit it to hardware
- */
- if (vb) {
- temp = kzalloc(sizeof(*temp), GFP_KERNEL);
- if (!temp) {
- dprintk(VIDC_ERR, "Out of memory\n");
- goto err_no_mem;
- }
-
- temp->vb = vb;
- mutex_lock(&inst->pendingq.lock);
- list_add_tail(&temp->list, &inst->pendingq.list);
- mutex_unlock(&inst->pendingq.lock);
- }
+ /* initially assume every buffer is going to be deferred */
+ if (mbuf)
+ mbuf->deferred = true;
batch_mode = msm_comm_g_ctrl_for_id(inst, V4L2_CID_VIDC_QBUF_MODE)
== V4L2_VIDC_QBUF_BATCHED;
capture_count = (batch_mode ? &count_single_batch : &count_buffers)
- (&inst->pendingq, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ (inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
output_count = (batch_mode ? &count_single_batch : &count_buffers)
- (&inst->pendingq, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ (inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
/*
* Somewhat complicated logic to prevent queuing the buffer to hardware.
@@ -3959,13 +3853,18 @@
* buffer to be batched with future frames. The batch size (on both
* capabilities) is completely determined by the client.
*/
- defer = defer ? defer : (vbuf && vbuf->flags & V4L2_MSM_BUF_FLAG_DEFER);
+ defer = defer ? defer :
+ (mbuf && mbuf->vvb.flags & V4L2_MSM_BUF_FLAG_DEFER);
/* 3) If we're in batch mode, we must have full batches of both types */
defer = defer ? defer:(batch_mode && (!output_count || !capture_count));
if (defer) {
- dprintk(VIDC_DBG, "Deferring queue of %pK\n", vb);
+ if (mbuf) {
+ mbuf->deferred = true;
+ print_vidc_buffer(VIDC_DBG, "deferred qbuf",
+ inst, mbuf);
+ }
return 0;
}
@@ -3995,15 +3894,18 @@
etbs.count = ftbs.count = 0;
/*
- * Try to collect all pending buffers into 2 batches of ftb and etb
+ * Try to collect all deferred buffers into 2 batches of ftb and etb
* Note that these "batches" might be empty if we're no in batching mode
- * and the pendingq is empty
+ * and the deferred is not set for buffers.
*/
- mutex_lock(&inst->pendingq.lock);
- list_for_each_entry_safe(temp, next, &inst->pendingq.list, list) {
+ mutex_lock(&inst->registeredbufs.lock);
+ list_for_each_entry_safe(temp, next, &inst->registeredbufs.list, list) {
struct vidc_frame_data *frame_data = NULL;
- switch (temp->vb->type) {
+ if (!temp->deferred)
+ continue;
+
+ switch (temp->vvb.vb2_buf.type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (ftbs.count < capture_count && ftbs.data)
frame_data = &ftbs.data[ftbs.count++];
@@ -4019,12 +3921,14 @@
if (!frame_data)
continue;
- populate_frame_data(frame_data, temp->vb, inst);
+ populate_frame_data(frame_data, temp, inst);
- list_del(&temp->list);
- kfree(temp);
+ /* this buffer going to be queued (not deferred) */
+ temp->deferred = false;
+
+ print_vidc_buffer(VIDC_DBG, "qbuf", inst, temp);
}
- mutex_unlock(&inst->pendingq.lock);
+ mutex_unlock(&inst->registeredbufs.lock);
/* Finally commit all our frame(s) to H/W */
if (batch_mode) {
@@ -4344,11 +4248,7 @@
}
mutex_lock(&inst->outputbufs.lock);
list_for_each_entry_safe(buf, dummy, &inst->outputbufs.list, list) {
- handle = buf->handle;
- if (!handle) {
- dprintk(VIDC_ERR, "%s - invalid handle\n", __func__);
- goto exit;
- }
+ handle = &buf->smem;
if ((buf->buffer_ownership == FIRMWARE) && !force_release) {
dprintk(VIDC_INFO, "DPB is with f/w. Can't free it\n");
@@ -4368,18 +4268,17 @@
(void *)inst->session, &buffer_info);
if (rc) {
dprintk(VIDC_WARN,
- "Rel output buf fail:%pa, %d\n",
- &buffer_info.align_device_addr,
+ "Rel output buf fail:%x, %d\n",
+ buffer_info.align_device_addr,
buffer_info.buffer_size);
}
}
list_del(&buf->list);
- msm_comm_smem_free(inst, buf->handle);
+ msm_comm_smem_free(inst, &buf->smem);
kfree(buf);
}
-exit:
mutex_unlock(&inst->outputbufs.lock);
return rc;
}
@@ -4404,13 +4303,8 @@
mutex_lock(&inst->scratchbufs.lock);
list_for_each_entry(buf, &inst->scratchbufs.list, list) {
- if (!buf->handle) {
- dprintk(VIDC_ERR, "%s: invalid buf handle\n", __func__);
- mutex_unlock(&inst->scratchbufs.lock);
- goto not_sufficient;
- }
if (buf->buffer_type == buffer_type &&
- buf->handle->size >= bufreq->buffer_size)
+ buf->smem.size >= bufreq->buffer_size)
count++;
}
mutex_unlock(&inst->scratchbufs.lock);
@@ -4469,13 +4363,7 @@
mutex_lock(&inst->scratchbufs.lock);
list_for_each_entry_safe(buf, dummy, &inst->scratchbufs.list, list) {
- if (!buf->handle) {
- dprintk(VIDC_ERR, "%s - buf->handle NULL\n", __func__);
- rc = -EINVAL;
- goto exit;
- }
-
- handle = buf->handle;
+ handle = &buf->smem;
buffer_info.buffer_size = handle->size;
buffer_info.buffer_type = buf->buffer_type;
buffer_info.num_buffers = 1;
@@ -4487,8 +4375,8 @@
(void *)inst->session, &buffer_info);
if (rc) {
dprintk(VIDC_WARN,
- "Rel scrtch buf fail:%pa, %d\n",
- &buffer_info.align_device_addr,
+ "Rel scrtch buf fail:%x, %d\n",
+ buffer_info.align_device_addr,
buffer_info.buffer_size);
}
mutex_unlock(&inst->scratchbufs.lock);
@@ -4507,11 +4395,10 @@
continue;
list_del(&buf->list);
- msm_comm_smem_free(inst, buf->handle);
+ msm_comm_smem_free(inst, handle);
kfree(buf);
}
-exit:
mutex_unlock(&inst->scratchbufs.lock);
return rc;
}
@@ -4567,7 +4454,7 @@
mutex_lock(&inst->persistbufs.lock);
list_for_each_safe(ptr, next, &inst->persistbufs.list) {
buf = list_entry(ptr, struct internal_buf, list);
- handle = buf->handle;
+ handle = &buf->smem;
buffer_info.buffer_size = handle->size;
buffer_info.buffer_type = buf->buffer_type;
buffer_info.num_buffers = 1;
@@ -4579,8 +4466,8 @@
(void *)inst->session, &buffer_info);
if (rc) {
dprintk(VIDC_WARN,
- "Rel prst buf fail:%pa, %d\n",
- &buffer_info.align_device_addr,
+ "Rel prst buf fail:%x, %d\n",
+ buffer_info.align_device_addr,
buffer_info.buffer_size);
}
mutex_unlock(&inst->persistbufs.lock);
@@ -4593,7 +4480,7 @@
mutex_lock(&inst->persistbufs.lock);
}
list_del(&buf->list);
- msm_comm_smem_free(inst, buf->handle);
+ msm_comm_smem_free(inst, handle);
kfree(buf);
}
mutex_unlock(&inst->persistbufs.lock);
@@ -4771,116 +4658,20 @@
for (c = 0; c < ARRAY_SIZE(ports); ++c) {
enum vidc_ports port = ports[c];
- dprintk(VIDC_DBG, "Flushing buffers of type %d in bad state\n",
- port);
mutex_lock(&inst->bufq[port].lock);
- list_for_each_safe(ptr, next, &inst->bufq[port].
- vb2_bufq.queued_list) {
+ list_for_each_safe(ptr, next,
+ &inst->bufq[port].vb2_bufq.queued_list) {
struct vb2_buffer *vb = container_of(ptr,
struct vb2_buffer, queued_entry);
-
vb->planes[0].bytesused = 0;
- vb->planes[0].data_offset = 0;
-
+ print_vb2_buffer(VIDC_ERR, "flush in invalid",
+ inst, vb);
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
}
mutex_unlock(&inst->bufq[port].lock);
}
-
msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
-}
-
-void msm_comm_flush_dynamic_buffers(struct msm_vidc_inst *inst)
-{
- struct buffer_info *binfo = NULL;
-
- if (inst->buffer_mode_set[CAPTURE_PORT] != HAL_BUFFER_MODE_DYNAMIC)
- return;
-
- /*
- * dynamic buffer mode:- if flush is called during seek
- * driver should not queue any new buffer it has been holding.
- *
- * Each dynamic o/p buffer can have one of following ref_count:
- * ref_count : 0 - f/w has released reference and sent dynamic
- * buffer back. The buffer has been returned
- * back to client.
- *
- * ref_count : 1 - f/w is holding reference. f/w may have released
- * dynamic buffer as read_only OR dynamic buffer is
- * pending. f/w will release reference before sending
- * flush_done.
- *
- * ref_count : >=2 - f/w is holding reference, f/w has released dynamic
- * buffer as read_only, which client has queued back
- * to driver. Driver holds this buffer and will queue
- * back only when f/w releases the reference. During
- * flush_done, f/w will release the reference but
- * driver should not queue back the buffer to f/w.
- * Flush all buffers with ref_count >= 2.
- */
- mutex_lock(&inst->registeredbufs.lock);
- if (!list_empty(&inst->registeredbufs.list)) {
- struct v4l2_event buf_event = {0};
- u32 *ptr = NULL;
-
- list_for_each_entry(binfo, &inst->registeredbufs.list, list) {
- if (binfo->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
- atomic_read(&binfo->ref_count) >= 2) {
-
- atomic_dec(&binfo->ref_count);
- buf_event.type =
- V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER;
- ptr = (u32 *)buf_event.u.data;
- ptr[0] = binfo->fd[0];
- ptr[1] = binfo->buff_off[0];
- ptr[2] = binfo->uvaddr[0];
- ptr[3] = (u32) binfo->timestamp.tv_sec;
- ptr[4] = (u32) binfo->timestamp.tv_usec;
- ptr[5] = binfo->v4l2_index;
- dprintk(VIDC_DBG,
- "released buffer held in driver before issuing flush: %pa fd[0]: %d\n",
- &binfo->device_addr[0], binfo->fd[0]);
- /*send event to client*/
- v4l2_event_queue_fh(&inst->event_handler,
- &buf_event);
- }
- }
- }
- mutex_unlock(&inst->registeredbufs.lock);
-}
-
-void msm_comm_flush_pending_dynamic_buffers(struct msm_vidc_inst *inst)
-{
- struct buffer_info *binfo = NULL;
-
- if (!inst)
- return;
-
- if (inst->buffer_mode_set[CAPTURE_PORT] != HAL_BUFFER_MODE_DYNAMIC)
- return;
-
- if (list_empty(&inst->pendingq.list) ||
- list_empty(&inst->registeredbufs.list))
- return;
-
- /*
- * Dynamic Buffer mode - Since pendingq is not empty
- * no output buffers have been sent to firmware yet.
- * Hence remove reference to all pendingq o/p buffers
- * before flushing them.
- */
-
- mutex_lock(&inst->registeredbufs.lock);
- list_for_each_entry(binfo, &inst->registeredbufs.list, list) {
- if (binfo->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- dprintk(VIDC_DBG,
- "%s: binfo = %pK device_addr = %pa\n",
- __func__, binfo, &binfo->device_addr[0]);
- buf_ref_put(inst, binfo);
- }
- }
- mutex_unlock(&inst->registeredbufs.lock);
+ return;
}
int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
@@ -4888,33 +4679,25 @@
int rc = 0;
bool ip_flush = false;
bool op_flush = false;
- struct vb2_buf_entry *temp, *next;
- struct mutex *lock;
+ struct msm_vidc_buffer *mbuf, *next;
struct msm_vidc_core *core;
struct hfi_device *hdev;
- if (!inst) {
+ if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR,
- "Invalid instance pointer = %pK\n", inst);
+ "Invalid params, inst %pK\n", inst);
return -EINVAL;
}
core = inst->core;
- if (!core) {
- dprintk(VIDC_ERR,
- "Invalid core pointer = %pK\n", core);
- return -EINVAL;
- }
hdev = core->device;
- if (!hdev) {
- dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
- return -EINVAL;
- }
ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
if (ip_flush && !op_flush) {
- dprintk(VIDC_INFO, "Input only flush not supported\n");
+ dprintk(VIDC_WARN,
+ "Input only flush not supported, making it flush all\n");
+ op_flush = true;
return 0;
}
@@ -4922,11 +4705,7 @@
msm_clock_data_reset(inst);
- msm_comm_flush_dynamic_buffers(inst);
-
- if (inst->state == MSM_VIDC_CORE_INVALID ||
- core->state == VIDC_CORE_INVALID ||
- core->state == VIDC_CORE_UNINIT) {
+ if (inst->state == MSM_VIDC_CORE_INVALID) {
dprintk(VIDC_ERR,
"Core %pK and inst %pK are in bad state\n",
core, inst);
@@ -4934,68 +4713,52 @@
return 0;
}
- if (inst->in_reconfig && !ip_flush && op_flush) {
- mutex_lock(&inst->pendingq.lock);
- if (!list_empty(&inst->pendingq.list)) {
- /*
- * Execution can never reach here since port reconfig
- * wont happen unless pendingq is emptied out
- * (both pendingq and flush being secured with same
- * lock). Printing a message here incase this breaks.
- */
- dprintk(VIDC_WARN,
- "FLUSH BUG: Pending q not empty! It should be empty\n");
- }
- mutex_unlock(&inst->pendingq.lock);
- atomic_inc(&inst->in_flush);
- dprintk(VIDC_DBG, "Send flush Output to firmware\n");
+ mutex_lock(&inst->registeredbufs.lock);
+ list_for_each_entry_safe(mbuf, next, &inst->registeredbufs.list, list) {
+ /* flush only deferred buffers (which are not queued yet) */
+ if (!mbuf->deferred)
+ continue;
+
+ /* don't flush input buffers if flush not requested on it */
+ if (!ip_flush && mbuf->vvb.vb2_buf.type ==
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ continue;
+
+ print_vidc_buffer(VIDC_DBG, "flush buf", inst, mbuf);
+ msm_comm_flush_vidc_buffer(inst, mbuf);
+ msm_comm_unmap_vidc_buffer(inst, mbuf);
+
+ /* remove from list */
+ list_del(&mbuf->list);
+ kfree(mbuf);
+ mbuf = NULL;
+ }
+ mutex_unlock(&inst->registeredbufs.lock);
+
+ /* enable in flush */
+ inst->in_flush = true;
+
+ hdev = inst->core->device;
+ if (ip_flush) {
+ dprintk(VIDC_DBG, "Send flush on all ports to firmware\n");
rc = call_hfi_op(hdev, session_flush, inst->session,
- HAL_FLUSH_OUTPUT);
+ HAL_FLUSH_ALL);
} else {
- msm_comm_flush_pending_dynamic_buffers(inst);
- /*
- * If flush is called after queueing buffers but before
- * streamon driver should flush the pending queue
- */
- mutex_lock(&inst->pendingq.lock);
- list_for_each_entry_safe(temp, next,
- &inst->pendingq.list, list) {
- enum v4l2_buf_type type = temp->vb->type;
-
- if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- lock = &inst->bufq[CAPTURE_PORT].lock;
- else
- lock = &inst->bufq[OUTPUT_PORT].lock;
-
- temp->vb->planes[0].bytesused = 0;
-
- mutex_lock(lock);
- vb2_buffer_done(temp->vb, VB2_BUF_STATE_DONE);
- msm_vidc_debugfs_update(inst,
- type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
- MSM_VIDC_DEBUGFS_EVENT_FBD :
- MSM_VIDC_DEBUGFS_EVENT_EBD);
- list_del(&temp->list);
- mutex_unlock(lock);
-
- kfree(temp);
- }
- mutex_unlock(&inst->pendingq.lock);
-
- /*Do not send flush in case of session_error */
- if (!(inst->state == MSM_VIDC_CORE_INVALID &&
- core->state != VIDC_CORE_INVALID)) {
- atomic_inc(&inst->in_flush);
- dprintk(VIDC_DBG, "Send flush all to firmware\n");
- rc = call_hfi_op(hdev, session_flush, inst->session,
- HAL_FLUSH_ALL);
- }
+ dprintk(VIDC_DBG, "Send flush on output port to firmware\n");
+ rc = call_hfi_op(hdev, session_flush, inst->session,
+ HAL_FLUSH_OUTPUT);
+ }
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Sending flush to firmware failed, flush out all buffers\n");
+ msm_comm_flush_in_invalid_state(inst);
+ /* disable in_flush */
+ inst->in_flush = false;
}
return rc;
}
-
enum hal_extradata_id msm_comm_get_hal_extradata_index(
enum v4l2_mpeg_vidc_extradata index)
{
@@ -5371,19 +5134,19 @@
return rc;
}
-struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst,
- size_t size, u32 align, u32 flags,
- enum hal_buffer buffer_type, int map_kernel)
+int msm_comm_smem_alloc(struct msm_vidc_inst *inst,
+ size_t size, u32 align, u32 flags, enum hal_buffer buffer_type,
+ int map_kernel, struct msm_smem *smem)
{
- struct msm_smem *m = NULL;
+ int rc = 0;
if (!inst || !inst->core) {
dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst);
- return NULL;
+ return -EINVAL;
}
- m = msm_smem_alloc(inst->mem_client, size, align,
- flags, buffer_type, map_kernel);
- return m;
+ rc = msm_smem_alloc(inst->mem_client, size, align,
+ flags, buffer_type, map_kernel, smem);
+ return rc;
}
void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem)
@@ -5404,28 +5167,138 @@
"%s: invalid params: %pK %pK\n", __func__, inst, mem);
return -EINVAL;
}
- return msm_smem_cache_operations(inst->mem_client, mem, cache_ops);
+ return msm_smem_cache_operations(inst->mem_client, mem->handle,
+ mem->offset, mem->size, cache_ops);
}
-struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst,
- int fd, u32 offset, enum hal_buffer buffer_type)
+int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
+ struct v4l2_buffer *b)
{
- struct msm_smem *m = NULL;
+ int rc = 0, i;
+ void *dma_buf;
+ void *handle;
+ bool skip;
- if (!inst || !inst->core) {
- dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst);
- return NULL;
+ if (!inst || !b) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
+ __func__, inst, b);
+ return -EINVAL;
}
- if (inst->state == MSM_VIDC_CORE_INVALID) {
- dprintk(VIDC_ERR, "Core in Invalid state, returning from %s\n",
- __func__);
- return NULL;
+ for (i = 0; i < b->length; i++) {
+ unsigned long offset, size;
+ enum smem_cache_ops cache_ops;
+
+ dma_buf = msm_smem_get_dma_buf(b->m.planes[i].m.fd);
+ handle = msm_smem_get_handle(inst->mem_client, dma_buf);
+
+ offset = b->m.planes[i].data_offset;
+ size = b->m.planes[i].length;
+ cache_ops = SMEM_CACHE_INVALIDATE;
+ skip = false;
+
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (!i) { /* bitstream */
+ size = b->m.planes[i].bytesused;
+ cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
+ }
+ } else if (b->type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (!i) { /* yuv */
+ /* all values are correct */
+ }
+ }
+ } else if (inst->session_type == MSM_VIDC_ENCODER) {
+ if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (!i) { /* yuv */
+ size = b->m.planes[i].bytesused;
+ cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
+ } else { /* extradata */
+ cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
+ }
+ } else if (b->type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (!i) { /* bitstream */
+ /* all values are correct */
+ }
+ }
+ }
+
+ if (!skip) {
+ rc = msm_smem_cache_operations(inst->mem_client, handle,
+ offset, size, cache_ops);
+ if (rc)
+ print_v4l2_buffer(VIDC_ERR,
+ "qbuf cache ops failed", inst, b);
+ }
+
+ msm_smem_put_handle(inst->mem_client, handle);
+ msm_smem_put_dma_buf(dma_buf);
}
- m = msm_smem_user_to_kernel(inst->mem_client,
- fd, offset, buffer_type);
- return m;
+ return rc;
+}
+
+int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst,
+ struct v4l2_buffer *b)
+{
+ int rc = 0, i;
+ void *dma_buf;
+ void *handle;
+ bool skip;
+
+ if (!inst || !b) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
+ __func__, inst, b);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < b->length; i++) {
+ unsigned long offset, size;
+ enum smem_cache_ops cache_ops;
+
+ dma_buf = msm_smem_get_dma_buf(b->m.planes[i].m.fd);
+ handle = msm_smem_get_handle(inst->mem_client, dma_buf);
+
+ offset = b->m.planes[i].data_offset;
+ size = b->m.planes[i].length;
+ cache_ops = SMEM_CACHE_INVALIDATE;
+ skip = false;
+
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (!i) /* bitstream */
+ skip = true;
+ } else if (b->type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (!i) /* yuv */
+ skip = true;
+ }
+ } else if (inst->session_type == MSM_VIDC_ENCODER) {
+ if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (!i) /* yuv */
+ skip = true;
+ } else if (b->type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (!i) /* bitstream */
+ skip = true;
+ }
+ }
+
+ if (!skip) {
+ rc = msm_smem_cache_operations(inst->mem_client, handle,
+ offset, size, cache_ops);
+ if (rc)
+ print_v4l2_buffer(VIDC_ERR,
+ "dqbuf cache ops failed", inst, b);
+ }
+
+ msm_smem_put_handle(inst->mem_client, handle);
+ msm_smem_put_dma_buf(dma_buf);
+ }
+
+ return rc;
}
void msm_vidc_fw_unload_handler(struct work_struct *work)
@@ -5582,9 +5455,8 @@
void msm_comm_print_inst_info(struct msm_vidc_inst *inst)
{
- struct buffer_info *temp;
+ struct msm_vidc_buffer *mbuf;
struct internal_buf *buf;
- int i = 0;
bool is_decode = false;
enum vidc_ports port;
bool is_secure = false;
@@ -5612,37 +5484,32 @@
inst, inst->session_type);
mutex_lock(&inst->registeredbufs.lock);
dprintk(VIDC_ERR, "registered buffer list:\n");
- list_for_each_entry(temp, &inst->registeredbufs.list, list)
- for (i = 0; i < temp->num_planes; i++)
- dprintk(VIDC_ERR,
- "type: %d plane: %d addr: %pa size: %d\n",
- temp->type, i, &temp->device_addr[i],
- temp->size[i]);
-
+ list_for_each_entry(mbuf, &inst->registeredbufs.list, list)
+ print_vidc_buffer(VIDC_ERR, "buf", inst, mbuf);
mutex_unlock(&inst->registeredbufs.lock);
mutex_lock(&inst->scratchbufs.lock);
dprintk(VIDC_ERR, "scratch buffer list:\n");
list_for_each_entry(buf, &inst->scratchbufs.list, list)
- dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
- buf->buffer_type, &buf->handle->device_addr,
- buf->handle->size);
+ dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
+ buf->buffer_type, buf->smem.device_addr,
+ buf->smem.size);
mutex_unlock(&inst->scratchbufs.lock);
mutex_lock(&inst->persistbufs.lock);
dprintk(VIDC_ERR, "persist buffer list:\n");
list_for_each_entry(buf, &inst->persistbufs.list, list)
- dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
- buf->buffer_type, &buf->handle->device_addr,
- buf->handle->size);
+ dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
+ buf->buffer_type, buf->smem.device_addr,
+ buf->smem.size);
mutex_unlock(&inst->persistbufs.lock);
mutex_lock(&inst->outputbufs.lock);
dprintk(VIDC_ERR, "dpb buffer list:\n");
list_for_each_entry(buf, &inst->outputbufs.list, list)
- dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
- buf->buffer_type, &buf->handle->device_addr,
- buf->handle->size);
+ dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
+ buf->buffer_type, buf->smem.device_addr,
+ buf->smem.size);
mutex_unlock(&inst->outputbufs.lock);
}
@@ -5739,3 +5606,540 @@
return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
}
+
+void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf)
+{
+ struct vb2_buffer *vb2 = NULL;
+
+ if (!(tag & msm_vidc_debug) || !inst || !mbuf)
+ return;
+
+ vb2 = &mbuf->vvb.vb2_buf;
+
+ if (vb2->num_planes == 1)
+ dprintk(tag,
+ "%s: %s: %x : idx %2d fd %d off %d daddr %x size %d filled %d flags 0x%x ts %lld refcnt %d\n",
+ str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+ "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
+ vb2->index, vb2->planes[0].m.fd,
+ vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
+ vb2->planes[0].length, vb2->planes[0].bytesused,
+ mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
+ mbuf->smem[0].refcount);
+ else
+ dprintk(tag,
+ "%s: %s: %x : idx %2d fd %d off %d daddr %x size %d filled %d flags 0x%x ts %lld refcnt %d, extradata: fd %d off %d daddr %x size %d filled %d refcnt %d\n",
+ str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+ "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
+ vb2->index, vb2->planes[0].m.fd,
+ vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
+ vb2->planes[0].length, vb2->planes[0].bytesused,
+ mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
+ mbuf->smem[0].refcount, vb2->planes[1].m.fd,
+ vb2->planes[1].data_offset, mbuf->smem[1].device_addr,
+ vb2->planes[1].length, vb2->planes[1].bytesused,
+ mbuf->smem[1].refcount);
+}
+
+void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+ struct vb2_buffer *vb2)
+{
+ if (!(tag & msm_vidc_debug) || !inst || !vb2)
+ return;
+
+ if (vb2->num_planes == 1)
+ dprintk(tag,
+ "%s: %s: %x : idx %2d fd %d off %d size %d filled %d\n",
+ str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+ "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
+ vb2->index, vb2->planes[0].m.fd,
+ vb2->planes[0].data_offset, vb2->planes[0].length,
+ vb2->planes[0].bytesused);
+ else
+ dprintk(tag,
+ "%s: %s: %x : idx %2d fd %d off %d size %d filled %d, extradata: fd %d off %d size %d\n",
+ str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+ "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
+ vb2->index, vb2->planes[0].m.fd,
+ vb2->planes[0].data_offset, vb2->planes[0].length,
+ vb2->planes[0].bytesused, vb2->planes[1].m.fd,
+ vb2->planes[1].data_offset, vb2->planes[1].length);
+}
+
+void print_v4l2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+ struct v4l2_buffer *v4l2)
+{
+ if (!(tag & msm_vidc_debug) || !inst || !v4l2)
+ return;
+
+ if (v4l2->length == 1)
+ dprintk(tag,
+ "%s: %s: %x : idx %2d fd %d off %d size %d filled %d\n",
+ str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+ "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
+ v4l2->index, v4l2->m.planes[0].m.fd,
+ v4l2->m.planes[0].data_offset,
+ v4l2->m.planes[0].length,
+ v4l2->m.planes[0].bytesused);
+ else
+ dprintk(tag,
+ "%s: %s: %x : idx %2d fd %d off %d size %d filled %d, extradata: fd %d off %d size %d\n",
+ str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+ "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
+ v4l2->index, v4l2->m.planes[0].m.fd,
+ v4l2->m.planes[0].data_offset,
+ v4l2->m.planes[0].length,
+ v4l2->m.planes[0].bytesused,
+ v4l2->m.planes[1].m.fd,
+ v4l2->m.planes[1].data_offset,
+ v4l2->m.planes[1].length);
+}
+
+bool msm_comm_compare_vb2_plane(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2, u32 i)
+{
+ struct vb2_buffer *vb;
+
+ if (!inst || !mbuf || !vb2) {
+ dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
+ __func__, inst, mbuf, vb2);
+ return false;
+ }
+
+ vb = &mbuf->vvb.vb2_buf;
+ if (vb->planes[i].m.fd == vb2->planes[i].m.fd &&
+ vb->planes[i].data_offset == vb2->planes[i].data_offset &&
+ vb->planes[i].length == vb2->planes[i].length) {
+ return true;
+ }
+
+ return false;
+}
+
+bool msm_comm_compare_vb2_planes(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2)
+{
+ int i = 0;
+ struct vb2_buffer *vb;
+
+ if (!inst || !mbuf || !vb2) {
+ dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
+ __func__, inst, mbuf, vb2);
+ return false;
+ }
+
+ vb = &mbuf->vvb.vb2_buf;
+
+ if (vb->num_planes != vb2->num_planes)
+ return false;
+
+ for (i = 0; i < vb->num_planes; i++) {
+ if (!msm_comm_compare_vb2_plane(inst, mbuf, vb2, i))
+ return false;
+ }
+
+ return true;
+}
+
+bool msm_comm_compare_dma_plane(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf, unsigned long *dma_planes, u32 i)
+{
+ if (!inst || !mbuf || !dma_planes) {
+ dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
+ __func__, inst, mbuf, dma_planes);
+ return false;
+ }
+
+ if ((unsigned long)mbuf->smem[i].dma_buf == dma_planes[i])
+ return true;
+
+ return false;
+}
+
+bool msm_comm_compare_dma_planes(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf, unsigned long *dma_planes)
+{
+ int i = 0;
+ struct vb2_buffer *vb;
+
+ if (!inst || !mbuf || !dma_planes) {
+ dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
+ __func__, inst, mbuf, dma_planes);
+ return false;
+ }
+
+ vb = &mbuf->vvb.vb2_buf;
+ for (i = 0; i < vb->num_planes; i++) {
+ if (!msm_comm_compare_dma_plane(inst, mbuf, dma_planes, i))
+ return false;
+ }
+
+ return true;
+}
+
+
+bool msm_comm_compare_device_plane(struct msm_vidc_buffer *mbuf,
+ u32 *planes, u32 i)
+{
+ if (!mbuf || !planes) {
+ dprintk(VIDC_ERR, "%s: invalid params, %pK %pK\n",
+ __func__, mbuf, planes);
+ return false;
+ }
+
+ if (mbuf->smem[i].device_addr == planes[i])
+ return true;
+
+ return false;
+}
+
+bool msm_comm_compare_device_planes(struct msm_vidc_buffer *mbuf,
+ u32 *planes)
+{
+ int i = 0;
+
+ if (!mbuf || !planes)
+ return false;
+
+ for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
+ if (!msm_comm_compare_device_plane(mbuf, planes, i))
+ return false;
+ }
+
+ return true;
+}
+
+struct msm_vidc_buffer *msm_comm_get_buffer_using_device_planes(
+ struct msm_vidc_inst *inst, u32 *planes)
+{
+ struct msm_vidc_buffer *mbuf;
+ bool found = false;
+
+ mutex_lock(&inst->registeredbufs.lock);
+ found = false;
+ list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
+ if (msm_comm_compare_device_planes(mbuf, planes)) {
+ found = true;
+ break;
+ }
+ }
+ mutex_unlock(&inst->registeredbufs.lock);
+ if (!found) {
+ dprintk(VIDC_ERR,
+ "%s: data_addr %x, extradata_addr %x not found\n",
+ __func__, planes[0], planes[1]);
+ mbuf = NULL;
+ }
+
+ return mbuf;
+}
+
+int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf)
+{
+ int rc;
+ struct vb2_buffer *vb;
+
+ if (!inst || !mbuf) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
+ __func__, inst, mbuf);
+ return -EINVAL;
+ }
+
+ vb = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
+ if (!vb) {
+ print_vidc_buffer(VIDC_ERR,
+ "vb not found for buf", inst, mbuf);
+ return -EINVAL;
+ }
+
+ vb->planes[0].bytesused = 0;
+ rc = msm_comm_vb2_buffer_done(inst, vb);
+ if (rc)
+ print_vidc_buffer(VIDC_ERR,
+ "vb2_buffer_done failed for", inst, mbuf);
+
+ return rc;
+}
+
+struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
+ struct vb2_buffer *vb2)
+{
+ int rc = 0;
+ struct vb2_v4l2_buffer *vbuf;
+ struct vb2_buffer *vb;
+ unsigned long dma_planes[VB2_MAX_PLANES] = {0};
+ struct msm_vidc_buffer *mbuf;
+ bool found = false;
+ int i;
+
+ if (!inst || !vb2) {
+ dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
+ return NULL;
+ }
+
+ for (i = 0; i < vb2->num_planes; i++) {
+ /*
+ * always compare dma_buf addresses which is guaranteed
+ * to be same across the processes (duplicate fds).
+ */
+ dma_planes[i] = (unsigned long)dma_buf_get(vb2->planes[i].m.fd);
+ dma_buf_put((struct dma_buf *)dma_planes[i]);
+ }
+
+ mutex_lock(&inst->registeredbufs.lock);
+ list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
+ if (msm_comm_compare_dma_planes(inst, mbuf, dma_planes)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* this is new vb2_buffer */
+ mbuf = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
+ if (!mbuf) {
+ dprintk(VIDC_ERR, "%s: alloc msm_vidc_buffer failed\n",
+ __func__);
+ rc = -ENOMEM;
+ goto exit;
+ }
+ }
+
+ vbuf = to_vb2_v4l2_buffer(vb2);
+ memcpy(&mbuf->vvb, vbuf, sizeof(struct vb2_v4l2_buffer));
+ vb = &mbuf->vvb.vb2_buf;
+
+ for (i = 0; i < vb->num_planes; i++) {
+ mbuf->smem[i].buffer_type = get_hal_buffer_type(vb->type, i);
+ mbuf->smem[i].fd = vb->planes[i].m.fd;
+ mbuf->smem[i].offset = vb->planes[i].data_offset;
+ mbuf->smem[i].size = vb->planes[i].length;
+ rc = msm_smem_map_dma_buf(inst, &mbuf->smem[i]);
+ if (rc) {
+ dprintk(VIDC_ERR, "%s: map failed.\n", __func__);
+ goto exit;
+ }
+ /* increase refcount as we get both fbd and rbr */
+ rc = msm_smem_map_dma_buf(inst, &mbuf->smem[i]);
+ if (rc) {
+ dprintk(VIDC_ERR, "%s: map failed..\n", __func__);
+ goto exit;
+ }
+ }
+
+ /* special handling for decoder */
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ if (found) {
+ rc = -EEXIST;
+ } else {
+ bool found_plane0 = false;
+ struct msm_vidc_buffer *temp;
+ /*
+ * client might have queued same plane[0] but different
+ * plane[1] search plane[0] and if found don't queue the
+ * buffer, the buffer will be queued when rbr event
+ * arrived.
+ */
+ list_for_each_entry(temp, &inst->registeredbufs.list,
+ list) {
+ if (msm_comm_compare_dma_plane(inst, temp,
+ dma_planes, 0)) {
+ found_plane0 = true;
+ break;
+ }
+ }
+ if (found_plane0)
+ rc = -EEXIST;
+ }
+ }
+
+ /* add the new buffer to list */
+ if (!found)
+ list_add_tail(&mbuf->list, &inst->registeredbufs.list);
+
+ mutex_unlock(&inst->registeredbufs.lock);
+ if (rc == -EEXIST) {
+ print_vidc_buffer(VIDC_DBG, "qbuf upon rbr", inst, mbuf);
+ return ERR_PTR(rc);
+ }
+
+ return mbuf;
+
+exit:
+ mutex_unlock(&inst->registeredbufs.lock);
+ dprintk(VIDC_ERR, "%s: rc %d\n", __func__, rc);
+ msm_comm_unmap_vidc_buffer(inst, mbuf);
+ if (!found)
+ kfree(mbuf);
+
+ return ERR_PTR(rc);
+}
+
+void msm_comm_put_vidc_buffer(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf)
+{
+ struct msm_vidc_buffer *temp;
+ bool found = false;
+ int i = 0;
+
+ if (!inst || !mbuf) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
+ __func__, inst, mbuf);
+ return;
+ }
+
+ mutex_lock(&inst->registeredbufs.lock);
+ /* check if mbuf was not removed by any chance */
+ list_for_each_entry(temp, &inst->registeredbufs.list, list) {
+ if (msm_comm_compare_vb2_planes(inst, mbuf,
+ &temp->vvb.vb2_buf)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ print_vidc_buffer(VIDC_ERR, "buf was removed", inst, mbuf);
+ goto unlock;
+ }
+
+ print_vidc_buffer(VIDC_DBG, "dqbuf", inst, mbuf);
+ for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
+ if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
+ print_vidc_buffer(VIDC_ERR,
+ "dqbuf: unmap failed.", inst, mbuf);
+
+ if (!(mbuf->vvb.flags & V4L2_QCOM_BUF_FLAG_READONLY)) {
+ /* rbr won't come for this buffer */
+ if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
+ print_vidc_buffer(VIDC_ERR,
+ "dqbuf: unmap failed..", inst, mbuf);
+ } /* else RBR event expected */
+ }
+ /*
+ * remove the entry if plane[0].refcount is zero else
+ * don't remove as client queued same buffer that's why
+ * plane[0].refcount is not zero
+ */
+ if (!mbuf->smem[0].refcount) {
+ list_del(&mbuf->list);
+ kfree(mbuf);
+ mbuf = NULL;
+ }
+unlock:
+ mutex_unlock(&inst->registeredbufs.lock);
+}
+
+void handle_release_buffer_reference(struct msm_vidc_inst *inst, u32 *planes)
+{
+ int rc = 0;
+ struct msm_vidc_buffer *mbuf = NULL;
+ bool found = false;
+ int i = 0;
+
+ mutex_lock(&inst->registeredbufs.lock);
+ found = false;
+ list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
+ if (msm_comm_compare_device_planes(mbuf, planes)) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ msm_vidc_queue_rbr_event(inst,
+ mbuf->vvb.vb2_buf.planes[0].m.fd,
+ mbuf->vvb.vb2_buf.planes[0].data_offset);
+
+ for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
+ if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
+ print_vidc_buffer(VIDC_ERR,
+ "rbr unmap failed.", inst, mbuf);
+ }
+ /* refcount is not zero if client queued the same buffer */
+ if (!mbuf->smem[0].refcount) {
+ list_del(&mbuf->list);
+ kfree(mbuf);
+ mbuf = NULL;
+ }
+ } else {
+ dprintk(VIDC_ERR,
+ "%s: data_addr %x extradata_addr %x not found\n",
+ __func__, planes[0], planes[1]);
+ goto unlock;
+ }
+
+ /*
+ * 1. client might have pushed same planes in which case mbuf will be
+ * same and refcounts are positive and buffer wouldn't have been
+ * removed from the registeredbufs list.
+ * 2. client might have pushed same planes[0] but different planes[1]
+ * in which case mbuf will be different.
+ * 3. in either case we can search mbuf->smem[0].device_addr in the list
+ * and if found queue it to video hw (if not flushing).
+ */
+ found = false;
+ list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
+ if (msm_comm_compare_device_plane(mbuf, planes, 0)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ goto unlock;
+
+ /* found means client queued the buffer already */
+ if (inst->in_reconfig || inst->in_flush) {
+ print_vidc_buffer(VIDC_DBG, "rbr flush buf", inst, mbuf);
+ msm_comm_flush_vidc_buffer(inst, mbuf);
+ msm_comm_unmap_vidc_buffer(inst, mbuf);
+ /* remove from list */
+ list_del(&mbuf->list);
+ kfree(mbuf);
+ mbuf = NULL;
+
+ /* don't queue the buffer */
+ found = false;
+ }
+unlock:
+ mutex_unlock(&inst->registeredbufs.lock);
+
+ if (found) {
+ print_vidc_buffer(VIDC_DBG, "rbr qbuf", inst, mbuf);
+ rc = msm_comm_qbuf(inst, mbuf);
+ if (rc)
+ print_vidc_buffer(VIDC_ERR,
+ "rbr qbuf failed", inst, mbuf);
+ }
+}
+
+int msm_comm_unmap_vidc_buffer(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf)
+{
+ int rc = 0, i;
+
+ if (!inst || !mbuf) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
+ __func__, inst, mbuf);
+ return -EINVAL;
+ }
+ if (mbuf->vvb.vb2_buf.num_planes > VIDEO_MAX_PLANES) {
+ dprintk(VIDC_ERR, "%s: invalid num_planes %d\n", __func__,
+ mbuf->vvb.vb2_buf.num_planes);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
+ u32 refcount = mbuf->smem[i].refcount;
+
+ while (refcount) {
+ if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
+ print_vidc_buffer(VIDC_ERR,
+ "unmap failed for buf", inst, mbuf);
+ refcount--;
+ }
+ }
+
+ return rc;
+}
+
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 52925eb..5c653f5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -14,6 +14,7 @@
#ifndef _MSM_VIDC_COMMON_H_
#define _MSM_VIDC_COMMON_H_
#include "msm_vidc_internal.h"
+
struct vb2_buf_entry {
struct list_head list;
struct vb2_buffer *vb;
@@ -28,6 +29,8 @@
LOAD_CALC_IGNORE_NON_REALTIME_LOAD = 1 << 2,
};
+enum hal_buffer get_hal_buffer_type(unsigned int type,
+ unsigned int plane_num);
struct msm_vidc_core *get_vidc_core(int core_id);
const struct msm_vidc_format *msm_comm_get_pixel_fmt_index(
const struct msm_vidc_format fmt[], int size, int index, int fmt_type);
@@ -46,7 +49,7 @@
int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst);
int msm_comm_set_output_buffers(struct msm_vidc_inst *inst);
int msm_comm_queue_output_buffers(struct msm_vidc_inst *inst);
-int msm_comm_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb);
+int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf);
void msm_comm_flush_dynamic_buffers(struct msm_vidc_inst *inst);
int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags);
int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst,
@@ -69,14 +72,12 @@
int msm_comm_kill_session(struct msm_vidc_inst *inst);
enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst);
enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst);
-struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst,
- size_t size, u32 align, u32 flags,
- enum hal_buffer buffer_type, int map_kernel);
-void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem);
+int msm_comm_smem_alloc(struct msm_vidc_inst *inst, size_t size, u32 align,
+ u32 flags, enum hal_buffer buffer_type, int map_kernel,
+ struct msm_smem *smem);
+void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *smem);
int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst,
struct msm_smem *mem, enum smem_cache_ops cache_ops);
-struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst,
- int fd, u32 offset, enum hal_buffer buffer_type);
enum hal_video_codec get_hal_codec(int fourcc);
enum hal_domain get_hal_domain(int session_type);
int msm_comm_check_core_init(struct msm_vidc_core *core);
@@ -107,4 +108,41 @@
u32 get_frame_size_nv21(int plane, u32 height, u32 width);
u32 get_frame_size_tp10_ubwc(int plane, u32 height, u32 width);
void msm_comm_set_use_sys_cache(struct msm_vidc_inst *inst);
+struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer(
+ struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf);
+struct msm_vidc_buffer *msm_comm_get_buffer_using_device_planes(
+ struct msm_vidc_inst *inst, u32 *planes);
+struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
+ struct vb2_buffer *vb2);
+void msm_comm_put_vidc_buffer(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf);
+void handle_release_buffer_reference(struct msm_vidc_inst *inst, u32 *planes);
+int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
+ struct vb2_buffer *vb);
+int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf);
+int msm_comm_unmap_vidc_buffer(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf);
+bool msm_comm_compare_dma_plane(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf, unsigned long *dma_planes, u32 i);
+bool msm_comm_compare_dma_planes(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf, unsigned long *dma_planes);
+bool msm_comm_compare_vb2_plane(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2, u32 i);
+bool msm_comm_compare_vb2_planes(struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2);
+bool msm_comm_compare_device_plane(struct msm_vidc_buffer *mbuf,
+ u32 *planes, u32 i);
+bool msm_comm_compare_device_planes(struct msm_vidc_buffer *mbuf,
+ u32 *planes);
+int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
+ struct v4l2_buffer *b);
+int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst,
+ struct v4l2_buffer *b);
+void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+ struct msm_vidc_buffer *mbuf);
+void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+ struct vb2_buffer *vb2);
+void print_v4l2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+ struct v4l2_buffer *v4l2);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index 3b1d08d..58c3b0f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -265,7 +265,7 @@
static int publish_unreleased_reference(struct msm_vidc_inst *inst)
{
- struct buffer_info *temp = NULL;
+ struct msm_vidc_buffer *temp = NULL;
if (!inst) {
dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
@@ -277,14 +277,15 @@
mutex_lock(&inst->registeredbufs.lock);
list_for_each_entry(temp, &inst->registeredbufs.list, list) {
- if (temp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
- !temp->inactive && atomic_read(&temp->ref_count)) {
+ struct vb2_buffer *vb2 = &temp->vvb.vb2_buf;
+
+ if (vb2->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
write_str(&dbg_buf,
- "\tpending buffer: %#lx fd[0] = %d ref_count = %d held by: %s\n",
- temp->device_addr[0],
- temp->fd[0],
- atomic_read(&temp->ref_count),
- DYNAMIC_BUF_OWNER(temp));
+ "\tbuffer: %#x fd[0] = %d size %d refcount = %d\n",
+ temp->smem[0].device_addr,
+ vb2->planes[0].m.fd,
+ vb2->planes[0].length,
+ temp->smem[0].refcount);
}
}
mutex_unlock(&inst->registeredbufs.lock);
@@ -403,18 +404,14 @@
switch (e) {
case MSM_VIDC_DEBUGFS_EVENT_ETB:
- mutex_lock(&inst->lock);
inst->count.etb++;
- mutex_unlock(&inst->lock);
if (inst->count.ebd && inst->count.ftb > inst->count.fbd) {
d->pdata[FRAME_PROCESSING].name[0] = '\0';
tic(inst, FRAME_PROCESSING, a);
}
break;
case MSM_VIDC_DEBUGFS_EVENT_EBD:
- mutex_lock(&inst->lock);
inst->count.ebd++;
- mutex_unlock(&inst->lock);
if (inst->count.ebd && inst->count.ebd == inst->count.etb) {
toc(inst, FRAME_PROCESSING);
dprintk(VIDC_PROF, "EBD: FW needs input buffers\n");
@@ -431,6 +428,7 @@
}
break;
case MSM_VIDC_DEBUGFS_EVENT_FBD:
+ inst->count.fbd++;
inst->debug.samples++;
if (inst->count.ebd && inst->count.fbd == inst->count.ftb) {
toc(inst, FRAME_PROCESSING);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index ca61708..22772ef 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -33,7 +33,6 @@
#include <media/videobuf2-v4l2.h>
#include <media/msm_vidc.h>
#include <media/msm_media_info.h>
-
#include "vidc_hfi_api.h"
#define MSM_VIDC_DRV_NAME "msm_vidc_driver"
@@ -141,7 +140,7 @@
struct vidc_freq_data {
struct list_head list;
- ion_phys_addr_t device_addr;
+ u32 device_addr;
unsigned long freq;
};
@@ -155,7 +154,7 @@
struct internal_buf {
struct list_head list;
enum hal_buffer buffer_type;
- struct msm_smem *handle;
+ struct msm_smem smem;
enum buffer_owner buffer_ownership;
};
@@ -322,7 +321,6 @@
enum instance_state state;
struct msm_vidc_format fmts[MAX_PORT_NUM];
struct buf_queue bufq[MAX_PORT_NUM];
- struct msm_vidc_list pendingq;
struct msm_vidc_list freqs;
struct msm_vidc_list scratchbufs;
struct msm_vidc_list persistbufs;
@@ -331,7 +329,7 @@
struct msm_vidc_list reconbufs;
struct msm_vidc_list registeredbufs;
struct buffer_requirements buff_req;
- void *mem_client;
+ struct smem_client *mem_client;
struct v4l2_ctrl_handler ctrl_handler;
struct completion completions[SESSION_MSG_END - SESSION_MSG_START + 1];
struct v4l2_ctrl **cluster;
@@ -352,8 +350,7 @@
struct v4l2_ctrl **ctrls;
enum msm_vidc_pixel_depth bit_depth;
struct kref kref;
- u32 buffers_held_in_driver;
- atomic_t in_flush;
+ bool in_flush;
u32 pic_struct;
u32 colour_space;
u32 profile;
@@ -389,53 +386,33 @@
int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type);
-struct buffer_info {
+struct msm_vidc_buffer {
struct list_head list;
- int type;
- int num_planes;
- int fd[VIDEO_MAX_PLANES];
- int buff_off[VIDEO_MAX_PLANES];
- int size[VIDEO_MAX_PLANES];
- unsigned long uvaddr[VIDEO_MAX_PLANES];
- ion_phys_addr_t device_addr[VIDEO_MAX_PLANES];
- struct msm_smem *handle[VIDEO_MAX_PLANES];
- enum v4l2_memory memory;
- u32 v4l2_index;
- bool pending_deletion;
- atomic_t ref_count;
- bool dequeued;
- bool inactive;
- bool mapped[VIDEO_MAX_PLANES];
- int same_fd_ref[VIDEO_MAX_PLANES];
- struct timeval timestamp;
+ struct msm_smem smem[VIDEO_MAX_PLANES];
+ struct vb2_v4l2_buffer vvb;
+ bool deferred;
};
-struct buffer_info *device_to_uvaddr(struct msm_vidc_list *buf_list,
- ion_phys_addr_t device_addr);
-int buf_ref_get(struct msm_vidc_inst *inst, struct buffer_info *binfo);
-int buf_ref_put(struct msm_vidc_inst *inst, struct buffer_info *binfo);
-int output_buffer_cache_invalidate(struct msm_vidc_inst *inst,
- struct buffer_info *binfo);
-int qbuf_dynamic_buf(struct msm_vidc_inst *inst,
- struct buffer_info *binfo);
-int unmap_and_deregister_buf(struct msm_vidc_inst *inst,
- struct buffer_info *binfo);
-
void msm_comm_handle_thermal_event(void);
void *msm_smem_new_client(enum smem_type mtype,
void *platform_resources, enum session_type stype);
-struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
- enum hal_buffer buffer_type, int map_kernel);
-void msm_smem_free(void *clt, struct msm_smem *mem);
+int msm_smem_alloc(struct smem_client *client,
+ size_t size, u32 align, u32 flags, enum hal_buffer buffer_type,
+ int map_kernel, struct msm_smem *smem);
+int msm_smem_free(void *clt, struct msm_smem *mem);
void msm_smem_delete_client(void *clt);
-int msm_smem_cache_operations(void *clt, struct msm_smem *mem,
- enum smem_cache_ops);
-struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset,
- enum hal_buffer buffer_type);
struct context_bank_info *msm_smem_get_context_bank(void *clt,
bool is_secure, enum hal_buffer buffer_type);
+int msm_smem_map_dma_buf(struct msm_vidc_inst *inst, struct msm_smem *smem);
+int msm_smem_unmap_dma_buf(struct msm_vidc_inst *inst, struct msm_smem *smem);
+void *msm_smem_get_dma_buf(int fd);
+void msm_smem_put_dma_buf(void *dma_buf);
+void *msm_smem_get_handle(struct smem_client *client, void *dma_buf);
+void msm_smem_put_handle(struct smem_client *client, void *handle);
+int msm_smem_cache_operations(struct smem_client *client,
+ void *handle, unsigned long offset, unsigned long size,
+ enum smem_cache_ops cache_op);
void msm_vidc_fw_unload_handler(struct work_struct *work);
-bool msm_smem_compare_buffers(void *clt, int fd, void *priv);
/*
* XXX: normally should be in msm_vidc.h, but that's meant for public APIs,
* whereas this is private
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 62dcc59..f8d8842 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -560,7 +560,7 @@
struct vidc_mem_addr *mem, u32 size, u32 align,
u32 flags, u32 usage)
{
- struct msm_smem *alloc = NULL;
+ struct msm_smem *alloc = &mem->mem_data;
int rc = 0;
if (!dev || !dev->hal_client || !mem || !size) {
@@ -569,8 +569,9 @@
}
dprintk(VIDC_INFO, "start to alloc size: %d, flags: %d\n", size, flags);
- alloc = msm_smem_alloc(dev->hal_client, size, align, flags, usage, 1);
- if (!alloc) {
+ rc = msm_smem_alloc(dev->hal_client, size, align, flags,
+ usage, 1, alloc);
+ if (rc) {
dprintk(VIDC_ERR, "Alloc failed\n");
rc = -ENOMEM;
goto fail_smem_alloc;
@@ -578,17 +579,16 @@
dprintk(VIDC_DBG, "__smem_alloc: ptr = %pK, size = %d\n",
alloc->kvaddr, size);
- rc = msm_smem_cache_operations(dev->hal_client, alloc,
- SMEM_CACHE_CLEAN);
+ rc = msm_smem_cache_operations(dev->hal_client, alloc->handle, 0,
+ alloc->size, SMEM_CACHE_CLEAN);
if (rc) {
dprintk(VIDC_WARN, "Failed to clean cache\n");
- dprintk(VIDC_WARN, "This may result in undefined behavior\n");
}
mem->mem_size = alloc->size;
- mem->mem_data = alloc;
mem->align_virtual_addr = alloc->kvaddr;
mem->align_device_addr = alloc->device_addr;
+
return rc;
fail_smem_alloc:
return rc;
@@ -1312,7 +1312,7 @@
unsigned long mem_map_table_base_addr;
struct context_bank_info *cb;
- if (device->qdss.mem_data) {
+ if (device->qdss.align_virtual_addr) {
qdss = (struct hfi_mem_map_table *)
device->qdss.align_virtual_addr;
qdss->mem_map_num_entries = num_entries;
@@ -1338,32 +1338,27 @@
mem_map[i].size);
}
- __smem_free(device, device->qdss.mem_data);
+ __smem_free(device, &device->qdss.mem_data);
}
- __smem_free(device, device->iface_q_table.mem_data);
- __smem_free(device, device->sfr.mem_data);
+ __smem_free(device, &device->iface_q_table.mem_data);
+ __smem_free(device, &device->sfr.mem_data);
for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
device->iface_queues[i].q_hdr = NULL;
- device->iface_queues[i].q_array.mem_data = NULL;
device->iface_queues[i].q_array.align_virtual_addr = NULL;
device->iface_queues[i].q_array.align_device_addr = 0;
}
- device->iface_q_table.mem_data = NULL;
device->iface_q_table.align_virtual_addr = NULL;
device->iface_q_table.align_device_addr = 0;
- device->qdss.mem_data = NULL;
device->qdss.align_virtual_addr = NULL;
device->qdss.align_device_addr = 0;
- device->sfr.mem_data = NULL;
device->sfr.align_virtual_addr = NULL;
device->sfr.align_device_addr = 0;
- device->mem_addr.mem_data = NULL;
device->mem_addr.align_virtual_addr = NULL;
device->mem_addr.align_device_addr = 0;
@@ -1452,7 +1447,6 @@
struct vidc_mem_addr *mem_addr;
int offset = 0;
int num_entries = dev->res->qdss_addr_set.count;
- u32 value = 0;
phys_addr_t fw_bias = 0;
size_t q_size;
unsigned long mem_map_table_base_addr;
@@ -1483,7 +1477,6 @@
iface_q->q_array.align_virtual_addr =
mem_addr->align_virtual_addr + offset;
iface_q->q_array.mem_size = VIDC_IFACEQ_QUEUE_SIZE;
- iface_q->q_array.mem_data = NULL;
offset += iface_q->q_array.mem_size;
iface_q->q_hdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(
dev->iface_q_table.align_virtual_addr, i);
@@ -1535,65 +1528,34 @@
iface_q = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
q_hdr = iface_q->q_hdr;
- q_hdr->qhdr_start_addr = (u32)iface_q->q_array.align_device_addr;
+ q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
- if ((ion_phys_addr_t)q_hdr->qhdr_start_addr !=
- iface_q->q_array.align_device_addr) {
- dprintk(VIDC_ERR, "Invalid CMDQ device address (%pa)",
- &iface_q->q_array.align_device_addr);
- }
iface_q = &dev->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
q_hdr = iface_q->q_hdr;
- q_hdr->qhdr_start_addr = (u32)iface_q->q_array.align_device_addr;
+ q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
- if ((ion_phys_addr_t)q_hdr->qhdr_start_addr !=
- iface_q->q_array.align_device_addr) {
- dprintk(VIDC_ERR, "Invalid MSGQ device address (%pa)",
- &iface_q->q_array.align_device_addr);
- }
iface_q = &dev->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
q_hdr = iface_q->q_hdr;
- q_hdr->qhdr_start_addr = (u32)iface_q->q_array.align_device_addr;
+ q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
/*
* Set receive request to zero on debug queue as there is no
* need of interrupt from video hardware for debug messages
*/
q_hdr->qhdr_rx_req = 0;
- if ((ion_phys_addr_t)q_hdr->qhdr_start_addr !=
- iface_q->q_array.align_device_addr) {
- dprintk(VIDC_ERR, "Invalid DBGQ device address (%pa)",
- &iface_q->q_array.align_device_addr);
- }
- value = (u32)dev->iface_q_table.align_device_addr;
- if ((ion_phys_addr_t)value !=
- dev->iface_q_table.align_device_addr) {
- dprintk(VIDC_ERR,
- "Invalid iface_q_table device address (%pa)",
- &dev->iface_q_table.align_device_addr);
- }
-
- if (dev->qdss.mem_data) {
+ if (dev->qdss.align_virtual_addr) {
qdss = (struct hfi_mem_map_table *)dev->qdss.align_virtual_addr;
qdss->mem_map_num_entries = num_entries;
mem_map_table_base_addr = dev->qdss.align_device_addr +
sizeof(struct hfi_mem_map_table);
- qdss->mem_map_table_base_addr =
- (u32)mem_map_table_base_addr;
- if ((ion_phys_addr_t)qdss->mem_map_table_base_addr !=
- mem_map_table_base_addr) {
- dprintk(VIDC_ERR,
- "Invalid mem_map_table_base_addr (%#lx)",
- mem_map_table_base_addr);
- }
+ qdss->mem_map_table_base_addr = mem_map_table_base_addr;
mem_map = (struct hfi_mem_map *)(qdss + 1);
cb = msm_smem_get_context_bank(dev->hal_client, false,
HAL_BUFFER_INTERNAL_CMD_QUEUE);
-
if (!cb) {
dprintk(VIDC_ERR,
"%s: failed to get context bank\n", __func__);
@@ -1604,28 +1566,14 @@
if (rc) {
dprintk(VIDC_ERR,
"IOMMU mapping failed, Freeing qdss memdata\n");
- __smem_free(dev, dev->qdss.mem_data);
- dev->qdss.mem_data = NULL;
+ __smem_free(dev, &dev->qdss.mem_data);
dev->qdss.align_virtual_addr = NULL;
dev->qdss.align_device_addr = 0;
}
-
- value = (u32)dev->qdss.align_device_addr;
- if ((ion_phys_addr_t)value !=
- dev->qdss.align_device_addr) {
- dprintk(VIDC_ERR, "Invalid qdss device address (%pa)",
- &dev->qdss.align_device_addr);
- }
}
vsfr = (struct hfi_sfr_struct *) dev->sfr.align_virtual_addr;
vsfr->bufSize = ALIGNED_SFR_SIZE;
- value = (u32)dev->sfr.align_device_addr;
- if ((ion_phys_addr_t)value !=
- dev->sfr.align_device_addr) {
- dprintk(VIDC_ERR, "Invalid sfr device address (%pa)",
- &dev->sfr.align_device_addr);
- }
__setup_ucregion_memory_map(dev);
return 0;
@@ -1911,7 +1859,6 @@
__write_register(device, VIDC_CPU_CS_A2HSOFTINTCLR, 1);
__write_register(device, VIDC_WRAPPER_INTR_CLEAR, intr_status);
- dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt\n");
}
static int venus_hfi_core_ping(void *device)
@@ -3088,7 +3035,7 @@
mutex_lock(&device->lock);
- dprintk(VIDC_INFO, "Handling interrupt\n");
+ dprintk(VIDC_DBG, "Handling interrupt\n");
if (!__core_in_valid_state(device)) {
dprintk(VIDC_DBG, "%s - Core not in init state\n", __func__);
@@ -3123,7 +3070,8 @@
for (i = 0; !IS_ERR_OR_NULL(device->response_pkt) &&
i < num_responses; ++i) {
struct msm_vidc_cb_info *r = &device->response_pkt[i];
-
+ dprintk(VIDC_DBG, "Processing response %d of %d, type %d\n",
+ (i + 1), num_responses, r->response_type);
device->callback(r->response_type, &r->response);
}
@@ -3131,6 +3079,7 @@
if (!(intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK))
enable_irq(device->hal_data->irq);
+ dprintk(VIDC_DBG, "Handling interrupt done\n");
/*
* XXX: Don't add any code beyond here. Reacquiring locks after release
* it above doesn't guarantee the atomicity that we're aiming for.
@@ -3991,7 +3940,6 @@
dprintk(VIDC_ERR, "Invalid params: %pK\n", device);
return -EINVAL;
} else if (device->power_enabled) {
- dprintk(VIDC_DBG, "Power is already enabled\n");
goto exit;
} else if (!__core_in_valid_state(device)) {
dprintk(VIDC_DBG, "venus_hfi_device in deinit state.");
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 925918c..4c4cb06 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -126,10 +126,10 @@
};
struct vidc_mem_addr {
- ion_phys_addr_t align_device_addr;
+ u32 align_device_addr;
u8 *align_virtual_addr;
u32 mem_size;
- struct msm_smem *mem_data;
+ struct msm_smem mem_data;
};
struct vidc_iface_q_info {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 695c563..47ce0ba 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -17,6 +17,8 @@
#include <linux/log2.h>
#include <linux/platform_device.h>
#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/hash.h>
#include <media/msm_vidc.h>
#include "msm_vidc_resources.h"
@@ -882,8 +884,8 @@
enum hal_buffer buffer_type;
u32 buffer_size;
u32 num_buffers;
- ion_phys_addr_t align_device_addr;
- ion_phys_addr_t extradata_addr;
+ u32 align_device_addr;
+ u32 extradata_addr;
u32 extradata_size;
u32 response_required;
};
@@ -910,8 +912,8 @@
struct vidc_frame_data {
enum hal_buffer buffer_type;
- ion_phys_addr_t device_addr;
- ion_phys_addr_t extradata_addr;
+ u32 device_addr;
+ u32 extradata_addr;
int64_t timestamp;
u32 flags;
u32 offset;
@@ -1111,8 +1113,8 @@
u32 filled_len;
enum hal_picture picture_type;
struct recon_stats_type recon_stats;
- ion_phys_addr_t packet_buffer;
- ion_phys_addr_t extra_data_buffer;
+ u32 packet_buffer;
+ u32 extra_data_buffer;
};
struct vidc_hal_fbd {
@@ -1134,18 +1136,18 @@
u32 input_tag;
u32 input_tag1;
enum hal_picture picture_type;
- ion_phys_addr_t packet_buffer1;
- ion_phys_addr_t extra_data_buffer;
+ u32 packet_buffer1;
+ u32 extra_data_buffer;
u32 flags2;
u32 alloc_len2;
u32 filled_len2;
u32 offset2;
- ion_phys_addr_t packet_buffer2;
+ u32 packet_buffer2;
u32 flags3;
u32 alloc_len3;
u32 filled_len3;
u32 offset3;
- ion_phys_addr_t packet_buffer3;
+ u32 packet_buffer3;
enum hal_buffer buffer_type;
};
@@ -1247,8 +1249,8 @@
u32 width;
enum msm_vidc_pixel_depth bit_depth;
u32 hal_event_type;
- ion_phys_addr_t packet_buffer;
- ion_phys_addr_t extra_data_buffer;
+ u32 packet_buffer;
+ u32 extra_data_buffer;
u32 pic_struct;
u32 colour_space;
u32 profile;
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index 237fb4a..bb5a21c 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -61,15 +61,17 @@
};
struct msm_smem {
- int mem_type;
- size_t size;
+ u32 refcount;
+ int fd;
+ void *dma_buf;
+ void *handle;
void *kvaddr;
- ion_phys_addr_t device_addr;
+ u32 device_addr;
+ unsigned int offset;
+ unsigned int size;
unsigned long flags;
- void *smem_priv;
enum hal_buffer buffer_type;
struct dma_mapping_info mapping_info;
- unsigned int offset;
};
enum smem_cache_ops {