msm: vidc: Download firmware using PIL.
Video driver uses PIL and IOMMU to download video
firmware.Video firmware is downloaded during the
start of video session using PIL apis.
Change-Id: If285e9b6df57ecdfa379fa82b9eef542e6aa9bba
Signed-off-by: Vinay Kalia <vkalia@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 11af7a9..dbbe46d 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -5,11 +5,20 @@
- "qcom,msm-vidc"
- reg : offset and length of the register set for the device.
- interrupts : should contain the vidc interrupt.
+- vidc-cp-map : start and size of device virtual address range for secure buffers.
+ Video hardware uses this address range to identify if the buffers are secure
+ or non-secure.
+- vidc-ns-map : start and size of device virtual address range for non-secure buffers.
+ Video hardware uses this address range to identify if the buffers are secure
+ or non-secure.
Example:
+
qcom,vidc@fdc00000 {
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
interrupts = <0 44 0>;
+ vidc-cp-map = <0x1000000 0x40000000>;
+ vidc-ns-map = <0x40000000 0x40000000>;
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 8426b52..2eb8216 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -46,6 +46,8 @@
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
interrupts = <0 44 0>;
+ vidc-cp-map = <0x1000000 0x40000000>;
+ vidc-ns-map = <0x40000000 0x40000000>;
};
serial@f991f000 {
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index 2913d74..76e3592 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -12,6 +12,7 @@
*/
#include <linux/slab.h>
+#include <mach/iommu_domains.h>
#include "msm_smem.h"
struct smem_client {
@@ -19,12 +20,44 @@
void *clnt;
};
+static int get_device_address(struct ion_client *clnt,
+ struct ion_handle *hndl, int domain_num, int partition_num,
+ unsigned long align, unsigned long *iova,
+ unsigned long *buffer_size, unsigned long flags)
+{
+ int rc;
+
+ if (!iova || !buffer_size || !hndl || !clnt) {
+ pr_err("Invalid params: %p, %p, %p, %p\n",
+ clnt, hndl, iova, buffer_size);
+ return -EINVAL;
+ }
+ if (align < 4096)
+ align = 4096;
+ flags |= UNCACHED;
+ rc = ion_map_iommu(clnt, hndl, domain_num, partition_num, align,
+ 0, iova, buffer_size, flags, 0);
+ if (rc)
+ pr_err("ion_map_iommu failed(%d).domain: %d,partition: %d\n",
+ rc, domain_num, partition_num);
+
+ return rc;
+}
+
+static void put_device_address(struct ion_client *clnt,
+ struct ion_handle *hndl, int domain_num)
+{
+ ion_unmap_iommu(clnt, hndl, domain_num, 0);
+}
+
static int ion_user_to_kernel(struct smem_client *client,
- int fd, u32 offset, struct msm_smem *mem)
+ int fd, u32 offset, int domain, int partition,
+ struct msm_smem *mem)
{
struct ion_handle *hndl;
unsigned long ionflag;
- size_t len;
+ unsigned long iova = 0;
+ unsigned long buffer_size = 0;
int rc = 0;
hndl = ion_import_dma_buf(client->clnt, fd);
if (IS_ERR_OR_NULL(hndl)) {
@@ -38,25 +71,29 @@
pr_err("Failed to get ion flags: %d", rc);
goto fail_map;
}
- rc = ion_phys(client->clnt, hndl, &mem->paddr, &len);
- if (rc) {
- pr_err("Failed to get physical address\n");
- goto fail_map;
- }
mem->kvaddr = ion_map_kernel(client->clnt, hndl, ionflag);
if (!mem->kvaddr) {
pr_err("Failed to map shared mem in kernel\n");
rc = -EIO;
goto fail_map;
}
+ mem->domain = domain;
+ mem->partition_num = partition;
+ rc = get_device_address(client->clnt, hndl, mem->domain,
+ mem->partition_num, 4096, &iova, &buffer_size, UNCACHED);
+ if (rc) {
+ pr_err("Failed to get device address: %d\n", rc);
+ goto fail_device_address;
+ }
mem->kvaddr += offset;
- mem->paddr += offset;
mem->mem_type = client->mem_type;
mem->smem_priv = hndl;
- mem->device_addr = mem->paddr;
- mem->size = len;
+ mem->device_addr = iova + offset;
+ mem->size = buffer_size;
return rc;
+fail_device_address:
+ ion_unmap_kernel(client->clnt, hndl);
fail_map:
ion_free(client->clnt, hndl);
fail_import_fd:
@@ -64,14 +101,19 @@
}
static int alloc_ion_mem(struct smem_client *client, size_t size,
- u32 align, u32 flags, struct msm_smem *mem)
+ u32 align, u32 flags, int domain, int partition,
+ struct msm_smem *mem)
{
struct ion_handle *hndl;
- size_t len;
+ unsigned long iova = 0;
+ unsigned long buffer_size = 0;
int rc = 0;
if (size == 0)
goto skip_mem_alloc;
flags = flags | ION_HEAP(ION_CP_MM_HEAP_ID);
+ if (align < 4096)
+ align = 4096;
+ size = (size + 4095) & (~4095);
hndl = ion_alloc(client->clnt, size, align, flags);
if (IS_ERR_OR_NULL(hndl)) {
pr_err("Failed to allocate shared memory = %p, %d, %d, 0x%x\n",
@@ -81,20 +123,27 @@
}
mem->mem_type = client->mem_type;
mem->smem_priv = hndl;
- if (ion_phys(client->clnt, hndl, &mem->paddr, &len)) {
- pr_err("Failed to get physical address\n");
- rc = -EIO;
- goto fail_map;
- }
- mem->device_addr = mem->paddr;
- mem->size = size;
+ mem->domain = domain;
+ mem->partition_num = partition;
mem->kvaddr = ion_map_kernel(client->clnt, hndl, 0);
if (!mem->kvaddr) {
pr_err("Failed to map shared mem in kernel\n");
rc = -EIO;
goto fail_map;
}
+ rc = get_device_address(client->clnt, hndl, mem->domain,
+ mem->partition_num, align, &iova, &buffer_size, UNCACHED);
+ if (rc) {
+ pr_err("Failed to get device address: %d\n", rc);
+ goto fail_device_address;
+ }
+ mem->device_addr = iova;
+ pr_err("device_address = 0x%lx, kvaddr = 0x%p\n",
+ mem->device_addr, mem->kvaddr);
+ mem->size = size;
return rc;
+fail_device_address:
+ ion_unmap_kernel(client->clnt, hndl);
fail_map:
ion_free(client->clnt, hndl);
fail_shared_mem_alloc:
@@ -104,6 +153,8 @@
static void free_ion_mem(struct smem_client *client, struct msm_smem *mem)
{
+ put_device_address(client->clnt,
+ mem->smem_priv, mem->domain);
ion_unmap_kernel(client->clnt, mem->smem_priv);
ion_free(client->clnt, mem->smem_priv);
}
@@ -122,7 +173,8 @@
ion_client_destroy(client->clnt);
}
-struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset)
+struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset,
+ int domain, int partition)
{
struct smem_client *client = clt;
int rc = 0;
@@ -138,7 +190,8 @@
}
switch (client->mem_type) {
case SMEM_ION:
- rc = ion_user_to_kernel(clt, fd, offset, mem);
+ rc = ion_user_to_kernel(clt, fd, offset,
+ domain, partition, mem);
break;
default:
pr_err("Mem type not supported\n");
@@ -177,7 +230,8 @@
return client;
};
-struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags)
+struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
+ int domain, int partition)
{
struct smem_client *client;
int rc = 0;
@@ -195,7 +249,8 @@
}
switch (client->mem_type) {
case SMEM_ION:
- rc = alloc_ion_mem(client, size, align, flags, mem);
+ rc = alloc_ion_mem(client, size, align, flags,
+ domain, partition, mem);
break;
default:
pr_err("Mem type not supported\n");
diff --git a/drivers/media/video/msm_vidc/msm_smem.h b/drivers/media/video/msm_vidc/msm_smem.h
index 84d12cc..b742c79 100644
--- a/drivers/media/video/msm_vidc/msm_smem.h
+++ b/drivers/media/video/msm_vidc/msm_smem.h
@@ -24,15 +24,17 @@
int mem_type;
size_t size;
void *kvaddr;
- unsigned long paddr;
unsigned long device_addr;
- /*Device address and others to follow*/
+ int domain;
+ int partition_num;
void *smem_priv;
};
void *msm_smem_new_client(enum smem_type mtype);
-struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags);
+struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
+ int domain, int partition);
void msm_smem_free(void *clt, struct msm_smem *mem);
void msm_smem_delete_client(void *clt);
-struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset);
+struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset, int
+ domain, int partition);
#endif
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 6cd9e6b..e1a71ce 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -21,7 +21,9 @@
#include <linux/debugfs.h>
#include <linux/version.h>
#include <linux/slab.h>
-
+#include <linux/of.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
#include <media/msm_vidc.h>
#include "msm_vidc_internal.h"
#include "vidc_hal_api.h"
@@ -277,8 +279,10 @@
goto exit;
}
handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1]);
+ b->m.planes[i].reserved[0],
+ b->m.planes[i].reserved[1],
+ vidc_inst->core->resources.io_map[NS_MAP].domain,
+ 0);
if (!handle) {
pr_err("Failed to get device buffer address\n");
kfree(binfo);
@@ -420,11 +424,92 @@
{
}
+static size_t read_u32_array(struct platform_device *pdev,
+ char *name, u32 *arr, size_t size)
+{
+ int len;
+ size_t sz = 0;
+ struct device_node *np = pdev->dev.of_node;
+ if (!of_get_property(np, name, &len)) {
+ pr_err("Failed to read %s from device tree\n",
+ name);
+ goto fail_read;
+ }
+ sz = len / sizeof(u32);
+ if (sz <= 0) {
+ pr_err("%s not specified in device tree\n", name);
+ goto fail_read;
+ }
+ if (sz > size) {
+ pr_err("Not enough memory to store %s values\n", name);
+ goto fail_read;
+ }
+ if (of_property_read_u32_array(np, name, arr, sz)) {
+ pr_err("error while reading %s from device tree\n",
+ name);
+ goto fail_read;
+ }
+ return sz;
+fail_read:
+ sz = 0;
+ return sz;
+}
+
+static int register_iommu_domains(struct platform_device *pdev,
+ struct msm_vidc_core *core)
+{
+ size_t len;
+ struct msm_iova_partition partition;
+ struct msm_iova_layout layout;
+ int rc = 0;
+ int i;
+ struct iommu_info *io_map = core->resources.io_map;
+ strlcpy(io_map[CP_MAP].name, "vidc-cp-map",
+ sizeof(io_map[CP_MAP].name));
+ strlcpy(io_map[CP_MAP].ctx, "venus_cp",
+ sizeof(io_map[CP_MAP].ctx));
+ strlcpy(io_map[NS_MAP].name, "vidc-ns-map",
+ sizeof(io_map[NS_MAP].name));
+ strlcpy(io_map[NS_MAP].ctx, "venus_ns",
+ sizeof(io_map[NS_MAP].ctx));
+
+ for (i = 0; i < MAX_MAP; i++) {
+ len = read_u32_array(pdev, io_map[i].name,
+ io_map[i].addr_range,
+ (sizeof(io_map[i].addr_range)/sizeof(u32)));
+ if (!len) {
+ pr_err("Error in reading cp address range\n");
+ rc = -EINVAL;
+ break;
+ }
+ partition.start = io_map[i].addr_range[0];
+ partition.size = io_map[i].addr_range[1];
+ layout.partitions = &partition;
+ layout.npartitions = 1;
+ layout.client_name = io_map[i].name;
+ layout.domain_flags = 0;
+ pr_debug("Registering domain with: %lx, %lx, %s\n",
+ partition.start, partition.size, layout.client_name);
+ io_map[i].domain = msm_register_domain(&layout);
+ if (io_map[i].domain < 0) {
+ pr_err("Failed to register cp domain\n");
+ rc = -EINVAL;
+ break;
+ }
+ }
+ /* There is no api provided as msm_unregister_domain, so
+ * we are not able to unregister the previously
+ * registered domains if any domain registration fails.*/
+ BUG_ON(i < MAX_MAP);
+ return rc;
+}
+
static int msm_vidc_initialize_core(struct platform_device *pdev,
struct msm_vidc_core *core)
{
struct resource *res;
int i = 0;
+ int rc = 0;
if (!core)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -443,13 +528,19 @@
INIT_LIST_HEAD(&core->instances);
mutex_init(&core->sync_lock);
spin_lock_init(&core->lock);
- core->base_addr = 0x14f00000;
+ core->base_addr = 0x0;
core->state = VIDC_CORE_UNINIT;
for (i = SYS_MSG_INDEX(SYS_MSG_START);
i <= SYS_MSG_INDEX(SYS_MSG_END); i++) {
init_completion(&core->completions[i]);
}
- return 0;
+ rc = register_iommu_domains(pdev, core);
+ if (rc) {
+ pr_err("Failed to register iommu domains: %d\n", rc);
+ goto fail_domain_register;
+ }
+fail_domain_register:
+ return rc;
}
static int __devinit msm_vidc_probe(struct platform_device *pdev)
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index a2e42e6..a8c6428 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -309,8 +309,21 @@
buffer_info.num_buffers = 1;
buffer_info.align_device_addr =
b->m.planes[i].m.userptr;
- buffer_info.extradata_size = 0;
- buffer_info.extradata_addr = 0;
+ if (!inst->extradata_handle) {
+ inst->extradata_handle =
+ msm_smem_alloc(inst->mem_client,
+ 4096 * 1024, 1, 0,
+ inst->core->resources.io_map[NS_MAP].domain,
+ 0);
+ if (!inst->extradata_handle) {
+ pr_err("Failed to allocate extradta memory\n");
+ rc = -ENOMEM;
+ break;
+ }
+ }
+ buffer_info.extradata_addr =
+ inst->extradata_handle->device_addr;
+ buffer_info.extradata_size = 4096 * 1024;
rc = vidc_hal_session_set_buffers((void *)inst->session,
&buffer_info);
if (rc) {
@@ -346,7 +359,8 @@
buffer_info.num_buffers = 1;
buffer_info.align_device_addr =
b->m.planes[i].m.userptr;
- buffer_info.extradata_addr = 0;
+ buffer_info.extradata_addr =
+ inst->extradata_handle->device_addr;
rc = vidc_hal_session_release_buffers(
(void *)inst->session, &buffer_info);
if (rc)
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 28fe2b8..4d4cec5 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -316,6 +316,8 @@
kfree(buf);
}
}
+ if (inst->extradata_handle)
+ msm_smem_free(inst->mem_client, inst->extradata_handle);
spin_unlock_irqrestore(&inst->lock, flags);
msm_smem_delete_client(inst->mem_client);
}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 261879d..cd330316 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -13,6 +13,10 @@
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/iommu.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/peripheral-loader.h>
#include "msm_vidc_common.h"
#include "vidc_hal_api.h"
@@ -52,6 +56,60 @@
return NULL;
}
+static int msm_comm_iommu_attach(struct msm_vidc_core *core)
+{
+ int rc;
+ struct iommu_domain *domain;
+ int i;
+ struct iommu_info *io_map;
+ struct device *dev;
+ for (i = 0; i < MAX_MAP; i++) {
+ io_map = &core->resources.io_map[i];
+ dev = msm_iommu_get_ctx(io_map->ctx);
+ domain = msm_get_iommu_domain(io_map->domain);
+ if (IS_ERR_OR_NULL(domain)) {
+ pr_err("Failed to get domain: %s\n", io_map->name);
+ rc = PTR_ERR(domain);
+ break;
+ }
+ rc = iommu_attach_device(domain, dev);
+ if (rc) {
+ pr_err("IOMMU attach failed: %s\n", io_map->name);
+ break;
+ }
+ }
+ if (i < MAX_MAP) {
+ i--;
+ for (; i >= 0; i--) {
+ io_map = &core->resources.io_map[i];
+ dev = msm_iommu_get_ctx(io_map->ctx);
+ domain = msm_get_iommu_domain(io_map->domain);
+ if (dev && domain)
+ iommu_detach_device(domain, dev);
+ }
+ }
+ return rc;
+}
+
+static void msm_comm_iommu_detach(struct msm_vidc_core *core)
+{
+ struct device *dev;
+ struct iommu_domain *domain;
+ struct iommu_info *io_map;
+ int i;
+ if (!core) {
+ pr_err("Invalid paramter: %p\n", core);
+ return;
+ }
+ for (i = 0; i < MAX_MAP; i++) {
+ io_map = &core->resources.io_map[i];
+ dev = msm_iommu_get_ctx(io_map->ctx);
+ domain = msm_get_iommu_domain(io_map->domain);
+ if (dev && domain)
+ iommu_detach_device(domain, dev);
+ }
+}
+
const struct msm_vidc_format *msm_comm_get_pixel_fmt_index(
const struct msm_vidc_format fmt[], int size, int index, int fmt_type)
{
@@ -454,6 +512,47 @@
break;
}
}
+static int msm_comm_load_fw(struct msm_vidc_core *core)
+{
+ int rc = 0;
+ if (!core) {
+ pr_err("Invalid paramter: %p\n", core);
+ return -EINVAL;
+ }
+
+ if (!core->resources.fw.cookie)
+ core->resources.fw.cookie = pil_get("venus");
+
+ if (IS_ERR_OR_NULL(core->resources.fw.cookie)) {
+ pr_err("Failed to download firmware\n");
+ rc = -ENOMEM;
+ goto fail_pil_get;
+ }
+ rc = msm_comm_iommu_attach(core);
+ if (rc) {
+ pr_err("Failed to attach iommu");
+ goto fail_iommu_attach;
+ }
+ return rc;
+fail_iommu_attach:
+ pil_put(core->resources.fw.cookie);
+ core->resources.fw.cookie = NULL;
+fail_pil_get:
+ return rc;
+}
+
+static void msm_comm_unload_fw(struct msm_vidc_core *core)
+{
+ if (!core) {
+ pr_err("Invalid paramter: %p\n", core);
+ return;
+ }
+ if (core->resources.fw.cookie) {
+ pil_put(core->resources.fw.cookie);
+ core->resources.fw.cookie = NULL;
+ msm_comm_iommu_detach(core);
+ }
+}
static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
{
@@ -499,18 +598,28 @@
core->id, core->state);
goto core_already_inited;
}
+ rc = msm_comm_load_fw(core);
+ if (rc) {
+ pr_err("Failed to load video firmware\n");
+ goto fail_fw_download;
+ }
init_completion(&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)]);
- rc = vidc_hal_core_init(core->device);
+ rc = vidc_hal_core_init(core->device,
+ core->resources.io_map[NS_MAP].domain);
if (rc) {
pr_err("Failed to init core, id = %d\n", core->id);
- goto exit;
+ goto fail_core_init;
}
spin_lock_irqsave(&core->lock, flags);
core->state = VIDC_CORE_INIT;
spin_unlock_irqrestore(&core->lock, flags);
core_already_inited:
change_inst_state(inst, MSM_VIDC_CORE_INIT);
-exit:
+ mutex_unlock(&core->sync_lock);
+ return rc;
+fail_core_init:
+ msm_comm_unload_fw(core);
+fail_fw_download:
mutex_unlock(&core->sync_lock);
return rc;
}
@@ -536,6 +645,7 @@
spin_lock_irqsave(&core->lock, flags);
core->state = VIDC_CORE_UNINIT;
spin_unlock_irqrestore(&core->lock, flags);
+ msm_comm_unload_fw(core);
}
core_already_uninited:
change_inst_state(inst, MSM_VIDC_CORE_UNINIT);
@@ -889,9 +999,16 @@
} else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
frame_data.filled_len = 0;
frame_data.buffer_type = HAL_BUFFER_OUTPUT;
- frame_data.extradata_addr = 0;
- pr_debug("Sending ftb to hal..: Alloc: %d :filled: %d\n",
+ if (inst->extradata_handle) {
+ frame_data.extradata_addr =
+ inst->extradata_handle->device_addr;
+ } else {
+ frame_data.extradata_addr = 0;
+ }
+ pr_debug("Sending ftb to hal..: Alloc: %d :filled: %d",
frame_data.alloc_len, frame_data.filled_len);
+ pr_debug(" extradata_addr: %d\n",
+ frame_data.extradata_addr);
rc = vidc_hal_session_ftb((void *) inst->session,
&frame_data);
} else {
@@ -1020,7 +1137,8 @@
for (i = 0; i < inst->buff_req.buffer[6].buffer_count_actual;
i++) {
handle = msm_smem_alloc(inst->mem_client,
- inst->buff_req.buffer[6].buffer_size, 1, 0);
+ inst->buff_req.buffer[6].buffer_size, 1, 0,
+ inst->core->resources.io_map[NS_MAP].domain, 0);
if (!handle) {
pr_err("Failed to allocate scratch memory\n");
rc = -ENOMEM;
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index fb8fbc4..151fb21 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -106,6 +106,29 @@
struct video_device vdev;
};
+struct msm_vidc_fw {
+ void *cookie;
+};
+
+struct iommu_info {
+ u32 addr_range[2];
+ char name[64];
+ char ctx[64];
+ int domain;
+ int partition;
+};
+
+enum io_maps {
+ CP_MAP,
+ NS_MAP,
+ MAX_MAP
+};
+
+struct msm_vidc_resources {
+ struct msm_vidc_fw fw;
+ struct iommu_info io_map[MAX_MAP];
+};
+
struct msm_vidc_core {
struct list_head list;
struct mutex sync_lock;
@@ -121,6 +144,7 @@
u32 register_size;
u32 irq;
enum vidc_core_state state;
+ struct msm_vidc_resources resources;
struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
};
@@ -146,6 +170,7 @@
bool in_reconfig;
u32 reconfig_width;
u32 reconfig_height;
+ struct msm_smem *extradata_handle;
};
extern struct msm_vidc_drv *vidc_driver;
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 0372f90..9052a63 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -23,7 +23,7 @@
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
/*Workaround for virtio */
-#define HFI_VIRTIO_FW_BIAS 0x14f00000
+#define HFI_VIRTIO_FW_BIAS 0x0
struct hal_device_data hal_ctxt;
@@ -300,7 +300,8 @@
return 0;
}
-static int vidc_hal_alloc(void *mem, void *clnt, u32 size, u32 align, u32 flags)
+static int vidc_hal_alloc(void *mem, void *clnt, u32 size, u32 align, u32 flags,
+ int domain)
{
struct vidc_mem_addr *vmem;
struct msm_smem *alloc;
@@ -312,7 +313,7 @@
vmem = (struct vidc_mem_addr *)mem;
HAL_MSG_HIGH("start to alloc: size:%d, Flags: %d", size, flags);
- alloc = msm_smem_alloc(clnt, size, align, flags);
+ alloc = msm_smem_alloc(clnt, size, align, flags, domain, 0);
HAL_MSG_LOW("Alloc done");
if (!alloc) {
HAL_MSG_HIGH("Alloc fail in %s", __func__);
@@ -503,7 +504,7 @@
device->hal_client = NULL;
}
-static int vidc_hal_interface_queues_init(struct hal_device *dev)
+static int vidc_hal_interface_queues_init(struct hal_device *dev, int domain)
{
struct hfi_queue_table_header *q_tbl_hdr;
struct hfi_queue_header *q_hdr;
@@ -513,7 +514,7 @@
rc = vidc_hal_alloc((void *) &dev->iface_q_table,
dev->hal_client,
- VIDC_IFACEQ_TABLE_SIZE, 1, 0);
+ VIDC_IFACEQ_TABLE_SIZE, 1, 0, domain);
if (rc) {
HAL_MSG_ERROR("%s:iface_q_table_alloc_fail", __func__);
return -ENOMEM;
@@ -533,7 +534,7 @@
iface_q = &dev->iface_queues[i];
rc = vidc_hal_alloc((void *) &iface_q->q_array,
dev->hal_client, VIDC_IFACEQ_QUEUE_SIZE,
- 1, 0);
+ 1, 0, domain);
if (rc) {
HAL_MSG_ERROR("%s:iface_q_table_alloc[%d]_fail",
__func__, i);
@@ -592,7 +593,7 @@
return rc;
}
-int vidc_hal_core_init(void *device)
+int vidc_hal_core_init(void *device, int domain)
{
struct hfi_cmd_sys_init_packet pkt;
int rc = 0;
@@ -619,10 +620,10 @@
HAL_MSG_ERROR("Device_Virt_Address : 0x%x,"
"Register_Virt_Addr: 0x%x",
- (u32) dev->hal_data->device_base_addr,
+ dev->hal_data->device_base_addr,
(u32) dev->hal_data->register_base_addr);
- rc = vidc_hal_interface_queues_init(dev);
+ rc = vidc_hal_interface_queues_init(dev, domain);
if (rc) {
HAL_MSG_ERROR("failed to init queues");
rc = -ENOMEM;
@@ -1989,11 +1990,11 @@
list_for_each_safe(curr, next, &core.dev_head) {
device = list_entry(curr, struct hal_device, list);
if (device && device->hal_data->irq == irq &&
- (CONTAINS((u32)device->hal_data->
+ (CONTAINS(device->hal_data->
device_base_addr,
FIRMWARE_SIZE, fw_addr) ||
CONTAINS(fw_addr, FIRMWARE_SIZE,
- (u32)device->hal_data->
+ device->hal_data->
device_base_addr) ||
CONTAINS((u32)device->hal_data->
register_base_addr,
@@ -2007,12 +2008,12 @@
OVERLAPS(reg_addr, reg_size,
(u32)device->hal_data->
register_base_addr, reg_size) ||
- OVERLAPS((u32)device->hal_data->
+ OVERLAPS(device->hal_data->
device_base_addr,
FIRMWARE_SIZE, fw_addr,
FIRMWARE_SIZE) ||
OVERLAPS(fw_addr, FIRMWARE_SIZE,
- (u32)device->hal_data->
+ device->hal_data->
device_base_addr,
FIRMWARE_SIZE))) {
return 0;
@@ -2062,7 +2063,7 @@
struct hal_data *hal = NULL;
int rc = 0;
- if (device_id || !fw_base_addr || !reg_base || !reg_size ||
+ if (device_id || !reg_base || !reg_size ||
!irq || !callback) {
HAL_MSG_ERROR("Invalid Paramters");
return NULL;
@@ -2080,13 +2081,7 @@
return NULL;
}
hal->irq = irq;
- hal->device_base_addr =
- ioremap_nocache(fw_base_addr, FIRMWARE_SIZE);
- if (!hal->device_base_addr) {
- HAL_MSG_ERROR("could not map fw addr %d of size %d",
- fw_base_addr, FIRMWARE_SIZE);
- goto err_map;
- }
+ hal->device_base_addr = fw_base_addr;
hal->register_base_addr =
ioremap_nocache(reg_base, reg_size);
if (!hal->register_base_addr) {
diff --git a/drivers/media/video/msm_vidc/vidc_hal.h b/drivers/media/video/msm_vidc/vidc_hal.h
index 6c7e5df..8e7c3d3 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.h
+++ b/drivers/media/video/msm_vidc/vidc_hal.h
@@ -834,7 +834,7 @@
struct hal_data {
u32 irq;
- u8 *device_base_addr;
+ u32 device_base_addr;
u8 *register_base_addr;
};
diff --git a/drivers/media/video/msm_vidc/vidc_hal_api.h b/drivers/media/video/msm_vidc/vidc_hal_api.h
index 332bbac..c77ae12 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_api.h
@@ -943,7 +943,7 @@
};
/* VIDC_HAL CORE API's */
-int vidc_hal_core_init(void *device);
+int vidc_hal_core_init(void *device, int domain);
int vidc_hal_core_release(void *device);
int vidc_hal_core_pc_prep(void *device);
int vidc_hal_core_set_resource(void *device,