msm: vidc: Separate meta buffers support in secure mode
Extradata is appended at the end of each output buffer
in non secure video use case but in secure video playback,
the client/CPU don't have access to the output buffer
to parse the extradata. This change allows the client/CPU
to parse the extradata by allocating separate buffers for
video hardware to store extradata.
Change-Id: I12927ea3d142b9cecd6fb1ae1086c5624d0e08d6
Signed-off-by: Deepak Verma <dverma@codeaurora.org>
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 4909725..3499dde 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -88,7 +88,7 @@
ddl_context->dram_base_a.align_virtual_addr;
}
if (!status) {
- ddl_context->metadata_shared_input.mem_type = DDL_FW_MEM;
+ ddl_context->metadata_shared_input.mem_type = DDL_CMD_MEM;
ptr = ddl_pmem_alloc(&ddl_context->metadata_shared_input,
DDL_METADATA_TOTAL_INPUTBUFSIZE,
DDL_LINEAR_BUFFER_ALIGN_BYTES);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 7a1d521..b47d9ac 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -188,6 +188,7 @@
struct ddl_buf_addr h264_nb_ip;
struct ddl_buf_addr context;
struct ddl_buf_addr extnuserdata;
+ struct ddl_buf_addr meta_hdr[DDL_MAX_BUFFER_COUNT];
};
struct ddl_enc_buffer_size{
u32 sz_cur_y;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index 1782fd2..4eee8b7 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -780,7 +780,7 @@
}
}
if (buf_size.sz_extnuserdata > 0) {
- dec_bufs->extnuserdata.mem_type = DDL_FW_MEM;
+ dec_bufs->extnuserdata.mem_type = DDL_CMD_MEM;
ptr = ddl_pmem_alloc(&dec_bufs->extnuserdata,
buf_size.sz_extnuserdata, DDL_KILO_BYTE(2));
if (!ptr)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
index f70c47c..e17dd00 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -158,7 +158,8 @@
ddl->codec_data.decoder.codec.codec;
flag |= (VCD_METADATA_CONCEALMB | VCD_METADATA_PASSTHROUGH |
- VCD_METADATA_QPARRAY);
+ VCD_METADATA_QPARRAY |
+ VCD_METADATA_SEPARATE_BUF);
if (codec == VCD_CODEC_H264)
flag |= (VCD_METADATA_SEI | VCD_METADATA_VUI);
else if (codec == VCD_CODEC_VC1 ||
@@ -249,6 +250,9 @@
DDL_METADATA_ALIGNSIZE(suffix);
decoder->suffix = suffix;
output_buf_req->sz += suffix;
+ output_buf_req->meta_buffer_size = suffix;
+ output_buf_req->meta_buffer_size =
+ (output_buf_req->meta_buffer_size + 8191) & (~8191);
decoder->meta_data_offset = 0;
DDL_MSG_LOW("metadata output buf size : %d", suffix);
}
@@ -464,13 +468,14 @@
void ddl_vidc_decode_set_metadata_output(struct ddl_decoder_data *decoder)
{
struct ddl_context *ddl_context;
- u32 loopc, yuv_size;
+ u32 loopc, yuv_size, dpb;
u32 *buffer;
-
+ struct ddl_dec_buffers *dec_buffers = &decoder->hw_bufs;
if (!decoder->meta_data_enable_flag) {
decoder->meta_data_offset = 0;
return;
}
+ dpb = decoder->dp_buf.no_of_dec_pic_buf;
ddl_context = ddl_get_context();
yuv_size = ddl_get_yuv_buffer_size(&decoder->client_frame_size,
&decoder->buf_format, !decoder->progressive_only,
@@ -478,15 +483,22 @@
decoder->meta_data_offset = DDL_ALIGN_SIZE(yuv_size,
DDL_LINEAR_BUF_ALIGN_GUARD_BYTES, DDL_LINEAR_BUF_ALIGN_MASK);
buffer = (u32 *) decoder->meta_data_input.align_virtual_addr;
- *buffer++ = decoder->suffix;
DDL_MSG_LOW("Metadata offset & size : %d/%d",
decoder->meta_data_offset, decoder->suffix);
- for (loopc = 0; loopc < decoder->dp_buf.no_of_dec_pic_buf;
- ++loopc) {
- *buffer++ = (u32)(decoder->meta_data_offset + (u8 *)
+ if (!(decoder->meta_data_enable_flag & VCD_METADATA_SEPARATE_BUF)) {
+ *buffer++ = decoder->suffix;
+ for (loopc = 0; loopc < dpb; ++loopc) {
+ *buffer++ = (u32)(decoder->meta_data_offset + (u8 *)
DDL_OFFSET(ddl_context->dram_base_a.
align_physical_addr, decoder->dp_buf.
dec_pic_buffers[loopc].vcd_frm.physical));
+ }
+ } else {
+ *buffer++ = decoder->actual_output_buf_req.meta_buffer_size;
+ for (loopc = 0; loopc < dpb; ++loopc) {
+ *buffer++ = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ dec_buffers->meta_hdr[loopc]);
+ }
}
}
@@ -545,7 +557,8 @@
DDL_MSG_LOW("data_len/metadata_offset : %d/%d",
output_frame->data_len, decoder->meta_data_offset);
output_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
- if (output_frame->data_len != decoder->meta_data_offset) {
+ if (!(decoder->meta_data_enable_flag & VCD_METADATA_SEPARATE_BUF)
+ && (output_frame->data_len != decoder->meta_data_offset)) {
qfiller = (u32 *)((u32)((output_frame->data_len +
output_frame->offset +
(u8 *) output_frame->virtual) + 3) & ~3);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 9b22285..6fb8f6c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -319,6 +319,61 @@
}
}
break;
+ case VCD_I_SET_EXT_METABUFFER:
+ {
+ int index, buffer_size;
+ u8 *phys_addr;
+ u8 *virt_addr;
+ struct vcd_property_meta_buffer *meta_buffer =
+ (struct vcd_property_meta_buffer *) property_value;
+ DDL_MSG_LOW("Entered VCD_I_SET_EXT_METABUFFER Virt: %p,"\
+ "Phys %p, fd: %d size: %d count: %d",
+ meta_buffer->kernel_virtual_addr,
+ meta_buffer->physical_addr,
+ meta_buffer->pmem_fd,
+ meta_buffer->size, meta_buffer->count);
+ if ((property_hdr->sz == sizeof(struct
+ vcd_property_meta_buffer)) &&
+ (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_INITCODEC) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB) ||
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN))) {
+ phys_addr = meta_buffer->dev_addr;
+ virt_addr = meta_buffer->kernel_virtual_addr;
+ buffer_size = meta_buffer->size/meta_buffer->count;
+
+ for (index = 0; index < meta_buffer->count; index++) {
+ ddl->codec_data.decoder.hw_bufs.
+ meta_hdr[index].align_physical_addr
+ = phys_addr;
+ ddl->codec_data.decoder.hw_bufs.
+ meta_hdr[index].align_virtual_addr
+ = virt_addr;
+ ddl->codec_data.decoder.hw_bufs.
+ meta_hdr[index].buffer_size
+ = buffer_size;
+ ddl->codec_data.decoder.hw_bufs.
+ meta_hdr[index].physical_base_addr
+ = phys_addr;
+ ddl->codec_data.decoder.hw_bufs.
+ meta_hdr[index].virtual_base_addr
+ = virt_addr;
+
+ DDL_MSG_LOW("Meta Buffer: "\
+ "Assigned %d buffer for "
+ "virt: %p, phys %p for "
+ "meta_buffers "
+ "of size: %d\n",
+ index, virt_addr,
+ phys_addr, buffer_size);
+
+ phys_addr += buffer_size;
+ virt_addr += buffer_size;
+ }
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
case VCD_I_H264_MV_BUFFER:
{
int index, buffer_size;
@@ -379,6 +434,13 @@
vcd_status = VCD_S_SUCCESS;
}
break;
+ case VCD_I_FREE_EXT_METABUFFER:
+ {
+ memset(&decoder->hw_bufs.meta_hdr, 0, sizeof(struct
+ ddl_buf_addr) * DDL_MAX_BUFFER_COUNT);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
case VCD_I_OUTPUT_ORDER:
{
if (sizeof(u32) == property_hdr->sz &&
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index bbabae8..c858c0a 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -271,6 +271,38 @@
&phy_addr, &pmem_fd, &file,
&buffer_index) ||
(vcd_frame_data->flags & VCD_FRAME_FLAG_EOS)) {
+
+ if (res_trk_check_for_sec_session() &&
+ event == VCD_EVT_RESP_OUTPUT_DONE) {
+ DBG("Buffer Index = %d", buffer_index);
+ if (buffer_index != -1) {
+ if (client_ctx->meta_addr_table[buffer_index].
+ kernel_vir_addr_iommu &&
+ client_ctx->
+ meta_addr_table[buffer_index].
+ kernel_vir_addr) {
+
+ memcpy(client_ctx->
+ meta_addr_table[buffer_index].
+ kernel_vir_addr_iommu,
+ client_ctx->
+ meta_addr_table[buffer_index].
+ kernel_vir_addr,
+ client_ctx->meta_buf_size);
+ DBG("Copying Meta Buffer from "\
+ "secure memory"
+ "kernel_virt_iommu = %p "
+ "kernel_virt = %p",
+ client_ctx->
+ meta_addr_table[buffer_index].
+ kernel_vir_addr_iommu,
+ client_ctx->
+ meta_addr_table[buffer_index].
+ kernel_vir_addr);
+ }
+ }
+ }
+
/* Buffer address in user space */
vdec_msg->vdec_msg_info.msgdata.output_frame.bufferaddr =
(u8 *) user_vaddr;
@@ -838,7 +870,263 @@
return false;
return true;
}
+static u32 vid_dec_set_meta_buffers(struct video_client_ctx *client_ctx,
+ struct vdec_meta_buffers *meta_buffers)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_meta_buffer *vcd_meta_buffer = NULL;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
+ struct msm_mapped_buffer *mapped_buffer_iommu = NULL;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 len = 0, flags = 0, len_iommu = 0, flags_iommu = 0, buf_size = 0;
+ struct file *file, *file_iommu;
+ int rc = 0;
+ unsigned long ionflag = 0, ionflag_iommu = 0;
+ unsigned long buffer_size = 0, buffer_size_iommu = 0;
+ unsigned long iova = 0, iova_iommu = 0;
+ int index = -1, num_buffers = 0;
+ u8 *ker_vir_addr = NULL, *ker_vir_addr_iommu = NULL;
+ if (!client_ctx || !meta_buffers)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_SET_EXT_METABUFFER;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_meta_buffer);
+ vcd_meta_buffer = &client_ctx->vcd_meta_buffer;
+
+ memset(&client_ctx->vcd_meta_buffer, 0,
+ sizeof(struct vcd_property_meta_buffer));
+ vcd_meta_buffer->size = meta_buffers->size;
+ vcd_meta_buffer->count = meta_buffers->count;
+ vcd_meta_buffer->pmem_fd = meta_buffers->pmem_fd;
+ vcd_meta_buffer->offset = meta_buffers->offset;
+ vcd_meta_buffer->pmem_fd_iommu = meta_buffers->pmem_fd_iommu;
+
+ if (!vcd_get_ion_status()) {
+ if (get_pmem_file(vcd_meta_buffer->pmem_fd,
+ (unsigned long *) (&(vcd_meta_buffer->
+ physical_addr)),
+ (unsigned long *) (&vcd_meta_buffer->
+ kernel_virtual_addr),
+ (unsigned long *) (&len), &file)) {
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ return false;
+ }
+ put_pmem_file(file);
+ flags = MSM_SUBSYSTEM_MAP_IOVA;
+ mapped_buffer = msm_subsystem_map_buffer(
+ (unsigned long)vcd_meta_buffer->physical_addr,
+ len, flags, vidc_mmu_subsystem,
+ sizeof(vidc_mmu_subsystem)/
+ sizeof(unsigned int));
+ if (IS_ERR(mapped_buffer)) {
+ pr_err("buffer map failed");
+ return false;
+ }
+ vcd_meta_buffer->client_data = (void *) mapped_buffer;
+ vcd_meta_buffer->dev_addr =
+ (u8 *)mapped_buffer->iova[0];
+
+ if (get_pmem_file(vcd_meta_buffer->pmem_fd_iommu,
+ (unsigned long *) (&(vcd_meta_buffer->
+ physical_addr_iommu)),
+ (unsigned long *) (&vcd_meta_buffer->
+ kernel_virt_addr_iommu),
+ (unsigned long *) (&len_iommu), &file_iommu)) {
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ return false;
+ }
+ put_pmem_file(file_iommu);
+ flags_iommu = MSM_SUBSYSTEM_MAP_IOVA;
+ mapped_buffer_iommu = msm_subsystem_map_buffer(
+ (unsigned long)vcd_meta_buffer->physical_addr_iommu,
+ len_iommu, flags_iommu, vidc_mmu_subsystem,
+ sizeof(vidc_mmu_subsystem)/
+ sizeof(unsigned int));
+ if (IS_ERR(mapped_buffer_iommu)) {
+ pr_err("buffer map failed");
+ return false;
+ }
+ vcd_meta_buffer->client_data_iommu =
+ (void *) mapped_buffer_iommu;
+ vcd_meta_buffer->dev_addr_iommu =
+ (u8 *)mapped_buffer_iommu->iova[0];
+ } else {
+ client_ctx->meta_buffer_ion_handle = ion_import_dma_buf(
+ client_ctx->user_ion_client,
+ vcd_meta_buffer->pmem_fd);
+ if (IS_ERR_OR_NULL(client_ctx->meta_buffer_ion_handle)) {
+ ERR("%s(): get_ION_handle failed\n", __func__);
+ goto import_ion_error;
+ }
+ rc = ion_handle_get_flags(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle,
+ &ionflag);
+ if (rc) {
+ ERR("%s():get_ION_flags fail\n",
+ __func__);
+ goto import_ion_error;
+ }
+ vcd_meta_buffer->kernel_virtual_addr =
+ (u8 *) ion_map_kernel(
+ client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle);
+ if (!vcd_meta_buffer->kernel_virtual_addr) {
+ ERR("%s(): get_ION_kernel virtual addr failed\n",
+ __func__);
+ goto import_ion_error;
+ }
+ if (res_trk_check_for_sec_session() ||
+ (res_trk_get_core_type() == (u32)VCD_CORE_720P)) {
+ rc = ion_phys(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle,
+ (unsigned long *) (&(vcd_meta_buffer->
+ physical_addr)), &len);
+ if (rc) {
+ ERR("%s():get_ION_kernel physical addr fail\n",
+ __func__);
+ goto ion_map_error;
+ }
+ vcd_meta_buffer->client_data = NULL;
+ vcd_meta_buffer->dev_addr = (u8 *)
+ vcd_meta_buffer->physical_addr;
+ } else {
+ rc = ion_map_iommu(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle,
+ VIDEO_DOMAIN, VIDEO_MAIN_POOL,
+ SZ_4K, 0, (unsigned long *)&iova,
+ (unsigned long *)&buffer_size,
+ 0, 0);
+ if (rc || !iova) {
+ ERR("%s():get_ION_kernel physical addr fail,"\
+ " rc = %d iova = 0x%lx\n",
+ __func__, rc, iova);
+ goto ion_map_error;
+ }
+ vcd_meta_buffer->physical_addr = (u8 *) iova;
+ vcd_meta_buffer->client_data = NULL;
+ vcd_meta_buffer->dev_addr = (u8 *) iova;
+ }
+
+ client_ctx->meta_buffer_iommu_ion_handle = ion_import_dma_buf(
+ client_ctx->user_ion_client,
+ vcd_meta_buffer->pmem_fd_iommu);
+ if (IS_ERR_OR_NULL(client_ctx->meta_buffer_iommu_ion_handle)) {
+ ERR("%s(): get_ION_handle failed\n", __func__);
+ goto import_ion_error;
+ }
+ rc = ion_handle_get_flags(client_ctx->user_ion_client,
+ client_ctx->
+ meta_buffer_iommu_ion_handle,
+ &ionflag_iommu);
+ if (rc) {
+ ERR("%s():get_ION_flags fail\n",
+ __func__);
+ goto import_ion_error;
+ }
+ vcd_meta_buffer->kernel_virt_addr_iommu =
+ (u8 *) ion_map_kernel(
+ client_ctx->user_ion_client,
+ client_ctx->meta_buffer_iommu_ion_handle);
+ if (!vcd_meta_buffer->kernel_virt_addr_iommu) {
+ ERR("%s(): get_ION_kernel virtual addr failed\n",
+ __func__);
+ goto import_ion_error;
+ }
+ if (res_trk_get_core_type() == (u32)VCD_CORE_720P) {
+ rc = ion_phys(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_iommu_ion_handle,
+ (unsigned long *) (&(vcd_meta_buffer->
+ physical_addr_iommu)), &len_iommu);
+ if (rc) {
+ ERR("%s():get_ION_kernel physical addr fail\n",
+ __func__);
+ goto ion_map_error_iommu;
+ }
+ vcd_meta_buffer->client_data_iommu = NULL;
+ vcd_meta_buffer->dev_addr_iommu = (u8 *)
+ vcd_meta_buffer->physical_addr_iommu;
+ } else {
+ rc = ion_map_iommu(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_iommu_ion_handle,
+ VIDEO_DOMAIN, VIDEO_MAIN_POOL,
+ SZ_4K, 0, (unsigned long *)&iova_iommu,
+ (unsigned long *)&buffer_size_iommu,
+ 0, 0);
+ if (rc || !iova_iommu) {
+ ERR("%s():get_ION_kernel physical addr fail, "\
+ "rc = %d iova = 0x%lx\n",
+ __func__, rc, iova);
+ goto ion_map_error_iommu;
+ }
+ vcd_meta_buffer->physical_addr_iommu =
+ (u8 *) iova_iommu;
+ vcd_meta_buffer->client_data_iommu = NULL;
+ vcd_meta_buffer->dev_addr_iommu = (u8 *) iova_iommu;
+ }
+ }
+
+ /*fill the meta addr table*/
+ num_buffers = vcd_meta_buffer->count;
+ buf_size = vcd_meta_buffer->size/num_buffers;
+ ker_vir_addr = vcd_meta_buffer->kernel_virtual_addr;
+ ker_vir_addr_iommu = vcd_meta_buffer->kernel_virt_addr_iommu;
+ client_ctx->meta_buf_size = buf_size;
+ for (index = 0; index < num_buffers; index++) {
+ client_ctx->meta_addr_table[index].kernel_vir_addr =
+ ker_vir_addr;
+ client_ctx->meta_addr_table[index].kernel_vir_addr_iommu =
+ ker_vir_addr_iommu;
+ DBG("[%d] kernel_virtual = %p kernel_vir_iommu = %p",
+ index, ker_vir_addr, ker_vir_addr_iommu);
+ ker_vir_addr += buf_size;
+ ker_vir_addr_iommu += buf_size;
+ }
+
+ DBG("Meta Buffer: Virt: %p, Phys %p, fd: %d",
+ vcd_meta_buffer->kernel_virtual_addr,
+ vcd_meta_buffer->physical_addr,
+ vcd_meta_buffer->pmem_fd);
+ DBG("IOMMU Meta Buffer: Virt: %p, Phys %p, fd: %d",
+ vcd_meta_buffer->kernel_virt_addr_iommu,
+ vcd_meta_buffer->physical_addr_iommu,
+ vcd_meta_buffer->pmem_fd_iommu);
+ DBG("Meta_buffer: Dev addr %p", vcd_meta_buffer->dev_addr);
+ DBG("IOMMU Meta_buffer: Dev addr %p",
+ vcd_meta_buffer->dev_addr_iommu);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr,
+ vcd_meta_buffer);
+
+ if (vcd_status)
+ return false;
+ else
+ return true;
+ion_map_error_iommu:
+ if (vcd_meta_buffer->kernel_virt_addr_iommu) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_iommu_ion_handle);
+ vcd_meta_buffer->kernel_virt_addr_iommu = NULL;
+ }
+ if (!IS_ERR_OR_NULL(client_ctx->meta_buffer_iommu_ion_handle)) {
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_iommu_ion_handle);
+ client_ctx->meta_buffer_iommu_ion_handle = NULL;
+ }
+ion_map_error:
+ if (vcd_meta_buffer->kernel_virtual_addr) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle);
+ vcd_meta_buffer->kernel_virtual_addr = NULL;
+ }
+ if (!IS_ERR_OR_NULL(client_ctx->meta_buffer_ion_handle)) {
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle);
+ client_ctx->meta_buffer_ion_handle = NULL;
+ }
+import_ion_error:
+ return false;
+}
static u32 vid_dec_set_h264_mv_buffers(struct video_client_ctx *client_ctx,
struct vdec_h264_mv *mv_data)
{
@@ -1018,6 +1306,65 @@
return true;
}
+static u32 vid_dec_free_meta_buffers(struct video_client_ctx *client_ctx)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_size meta_buffer_size;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx)
+ return false;
+ if (client_ctx->vcd_meta_buffer.client_data)
+ msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+ client_ctx->vcd_meta_buffer.client_data);
+
+ if (client_ctx->vcd_meta_buffer.client_data_iommu)
+ msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+ client_ctx->vcd_meta_buffer.client_data_iommu);
+
+ vcd_property_hdr.prop_id = VCD_I_FREE_EXT_METABUFFER;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &meta_buffer_size);
+
+ if (!IS_ERR_OR_NULL(client_ctx->meta_buffer_ion_handle)) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle);
+ if (!res_trk_check_for_sec_session() &&
+ (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ }
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_ion_handle);
+ client_ctx->meta_buffer_ion_handle = NULL;
+ }
+
+ if (!IS_ERR_OR_NULL(client_ctx->meta_buffer_iommu_ion_handle)) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_iommu_ion_handle);
+ if (res_trk_check_for_sec_session() &&
+ (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_iommu_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ }
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->meta_buffer_iommu_ion_handle);
+ client_ctx->meta_buffer_iommu_ion_handle = NULL;
+ }
+
+ if (vcd_status)
+ return false;
+ else
+ return true;
+}
+
+
static u32 vid_dec_free_h264_mv_buffers(struct video_client_ctx *client_ctx)
{
struct vcd_property_hdr vcd_property_hdr;
@@ -1085,6 +1432,7 @@
vdec_buf_req->buffer_size = vcd_buf_req.sz;
vdec_buf_req->alignment = vcd_buf_req.align;
vdec_buf_req->buf_poolid = vcd_buf_req.buf_pool_id;
+ vdec_buf_req->meta_buffer_size = vcd_buf_req.meta_buffer_size;
return true;
}
@@ -1977,6 +2325,29 @@
return -EIO;
break;
}
+ case VDEC_IOCTL_SET_META_BUFFERS:
+ {
+ struct vdec_meta_buffers meta_buffers;
+ DBG("VDEC_IOCTL_SET_META_BUFFERS\n");
+ if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+ return -EFAULT;
+ if (copy_from_user(&meta_buffers, vdec_msg.in,
+ sizeof(meta_buffers)))
+ return -EFAULT;
+ result = vid_dec_set_meta_buffers(client_ctx, &meta_buffers);
+
+ if (!result)
+ return -EIO;
+ break;
+ }
+ case VDEC_IOCTL_FREE_META_BUFFERS:
+ {
+ DBG("VDEC_IOCTL_FREE_META_BUFFERS\n");
+ result = vid_dec_free_meta_buffers(client_ctx);
+ if (!result)
+ return -EIO;
+ break;
+ }
case VDEC_IOCTL_SET_H264_MV_BUFFER:
{
struct vdec_h264_mv mv_data;
diff --git a/include/linux/msm_vidc_dec.h b/include/linux/msm_vidc_dec.h
index 3c99562..cc864f0 100644
--- a/include/linux/msm_vidc_dec.h
+++ b/include/linux/msm_vidc_dec.h
@@ -78,6 +78,7 @@
#define VDEC_EXTRADATA_EXT_DATA 0x0800
#define VDEC_EXTRADATA_USER_DATA 0x1000
+#define VDEC_EXTRADATA_EXT_BUFFER 0x2000
#define VDEC_CMDBASE 0x800
#define VDEC_CMD_SET_INTF_VERSION (VDEC_CMDBASE)
@@ -213,6 +214,12 @@
#define VDEC_IOCTL_SET_PERF_CLK \
_IOR(VDEC_IOCTL_MAGIC, 38, struct vdec_ioctl_msg)
+#define VDEC_IOCTL_SET_META_BUFFERS \
+ _IOW(VDEC_IOCTL_MAGIC, 39, struct vdec_ioctl_msg)
+
+#define VDEC_IOCTL_FREE_META_BUFFERS \
+ _IO(VDEC_IOCTL_MAGIC, 40)
+
enum vdec_picture {
PICTURE_TYPE_I,
PICTURE_TYPE_P,
@@ -236,6 +243,7 @@
size_t buffer_size;
uint32_t alignment;
uint32_t buf_poolid;
+ size_t meta_buffer_size;
};
struct vdec_bufferpayload {
@@ -526,6 +534,11 @@
uint32_t par_height;
};
+struct vdec_sep_metadatainfo {
+ void __user *metabufaddr;
+ uint32_t size;
+};
+
struct vdec_output_frameinfo {
void __user *bufferaddr;
size_t offset;
@@ -538,6 +551,7 @@
struct vdec_framesize framesize;
enum vdec_interlaced_format interlaced_format;
struct vdec_aspectratioinfo aspect_ratio_info;
+ struct vdec_sep_metadatainfo metadata_info;
};
union vdec_msgdata {
@@ -571,4 +585,12 @@
int alignment;
};
+struct vdec_meta_buffers {
+ size_t size;
+ int count;
+ int pmem_fd;
+ int pmem_fd_iommu;
+ int offset;
+};
+
#endif /* end of macro _VDECDECODER_H_ */
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 7104028..7472fb2 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -100,6 +100,7 @@
size_t sz;
u32 align;
u32 buf_pool_id;
+ size_t meta_buffer_size;
};
struct vcd_init_config {
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 545dcd2..698dd3b 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -57,7 +57,8 @@
#define VCD_I_SET_TURBO_CLK (VCD_START_BASE + 0x29)
#define VCD_I_ENABLE_DELIMITER_FLAG (VCD_START_BASE + 0x2A)
#define VCD_I_ENABLE_VUI_TIMING_INFO (VCD_START_BASE + 0x2B)
-
+#define VCD_I_SET_EXT_METABUFFER (VCD_START_BASE + 0x2C)
+#define VCD_I_FREE_EXT_METABUFFER (VCD_START_BASE + 0x2D)
#define VCD_START_REQ (VCD_START_BASE + 0x1000)
#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
@@ -118,6 +119,7 @@
#define VCD_METADATA_EXT_DATA 0x0800
#define VCD_METADATA_USER_DATA 0x1000
+#define VCD_METADATA_SEPARATE_BUF 0x2000
struct vcd_property_meta_data_enable {
u32 meta_data_enable_flag;
@@ -384,4 +386,19 @@
u32 vui_timing_info;
};
+struct vcd_property_meta_buffer {
+ u8 *kernel_virtual_addr;
+ u8 *physical_addr;
+ u32 size;
+ u32 count;
+ int pmem_fd;
+ u32 offset;
+ u8 *dev_addr;
+ void *client_data;
+ u8 *kernel_virt_addr_iommu;
+ u8 *physical_addr_iommu;
+ int pmem_fd_iommu;
+ u8 *dev_addr_iommu;
+ void *client_data_iommu;
+};
#endif
diff --git a/include/media/msm/vidc_init.h b/include/media/msm/vidc_init.h
index f7d4e58..4cbd4a6 100644
--- a/include/media/msm/vidc_init.h
+++ b/include/media/msm/vidc_init.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#define VIDC_MAX_NUM_CLIENTS 4
#define MAX_VIDEO_NUM_OF_BUFF 100
+#define MAX_META_BUFFERS 32
enum buffer_dir {
BUFFER_TYPE_INPUT,
@@ -37,6 +38,11 @@
void *client_data;
};
+struct meta_buffer_addr_table {
+ u8 *kernel_vir_addr;
+ u8 *kernel_vir_addr_iommu;
+};
+
struct video_client_ctx {
void *vcd_handle;
u32 num_of_input_buffers;
@@ -49,17 +55,22 @@
wait_queue_head_t msg_wait;
struct completion event;
struct vcd_property_h264_mv_buffer vcd_h264_mv_buffer;
+ struct vcd_property_meta_buffer vcd_meta_buffer;
struct vcd_property_enc_recon_buffer recon_buffer[4];
u32 event_status;
u32 seq_header_set;
u32 stop_msg;
u32 stop_called;
u32 stop_sync_cb;
+ size_t meta_buf_size;
struct ion_client *user_ion_client;
struct ion_handle *seq_hdr_ion_handle;
struct ion_handle *h264_mv_ion_handle;
struct ion_handle *recon_buffer_ion_handle[4];
+ struct ion_handle *meta_buffer_ion_handle;
+ struct ion_handle *meta_buffer_iommu_ion_handle;
u32 dmx_disable;
+ struct meta_buffer_addr_table meta_addr_table[MAX_META_BUFFERS];
};
void __iomem *vidc_get_ioaddr(void);