IEP_REGB_SRC_ADDR_CR1 (base, src_addr_cr);\r
}\r
\r
+#if defined(CONFIG_IEP_IOMMU)\r
+static int iep_bufid_to_iova(iep_service_info *pservice, u8 *tbl, int size, struct iep_reg *reg)\r
+{\r
+ int i;\r
+ int usr_fd = 0;\r
+ int offset = 0;\r
+ \r
+ if (tbl == NULL || size <= 0) {\r
+ dev_err(pservice->iommu_dev, "input arguments invalidate\n");\r
+ return -1;\r
+ }\r
+ \r
+ for (i=0; i<size; i++) {\r
+#if 0\r
+ if (copy_from_user(&usr_fd, ®->reg[addr_tbl_vpu_dec[i]], sizeof(usr_fd)))\r
+ return -EFAULT;\r
+#else\r
+ usr_fd = reg->reg[tbl[i]] & 0x3FF;\r
+ offset = reg->reg[tbl[i]] >> 10;\r
+ \r
+#endif\r
+ if (usr_fd != 0) {\r
+ struct ion_handle *hdl;\r
+ \r
+ hdl = ion_import_dma_buf(pservice->ion_client, usr_fd);\r
+ if (IS_ERR(hdl)) {\r
+ dev_err(pservice->iommu_dev, "import dma-buf from fd %d failed, reg[%d]\n", usr_fd, tbl[i]);\r
+ return PTR_ERR(hdl);\r
+ }\r
+\r
+#if 0\r
+ {\r
+ ion_phys_addr_t phy_addr;\r
+ size_t len;\r
+ ion_phys(pservice->ion_client, hdl, &phy_addr, &len);\r
+ \r
+ reg->reg[tbl[i]] = phy_addr + offset;\r
+ \r
+ ion_free(pservice->ion_client, hdl);\r
+ }\r
+#else \r
+ {\r
+ int ret;\r
+ struct iep_mem_region *mem_region;\r
+ mem_region = kzalloc(sizeof(struct iep_mem_region), GFP_KERNEL);\r
+ \r
+ if (mem_region == NULL) {\r
+ dev_err(pservice->iommu_dev, "allocate memory for iommu memory region failed\n");\r
+ ion_free(pservice->ion_client, hdl);\r
+ return -1;\r
+ }\r
+ \r
+ mem_region->hdl = hdl;\r
+ \r
+ ret = ion_map_iommu(pservice->iommu_dev, pservice->ion_client, mem_region->hdl, &mem_region->iova, &mem_region->len);\r
+ if (ret < 0) {\r
+ dev_err(pservice->iommu_dev, "ion map iommu failed\n");\r
+ kfree(mem_region);\r
+ ion_free(pservice->ion_client, hdl);\r
+ return ret;\r
+ }\r
+ \r
+ reg->reg[tbl[i]] = mem_region->iova + offset;\r
+ INIT_LIST_HEAD(&mem_region->reg_lnk);\r
+ list_add_tail(&mem_region->reg_lnk, ®->mem_region_list);\r
+ }\r
+#endif\r
+ }\r
+ }\r
+ \r
+ return 0;\r
+}\r
+\r
+static u8 addr_tbl_iep[] = {\r
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55\r
+};\r
+\r
+static int iep_reg_address_translate(iep_service_info *pservice, struct iep_reg *reg)\r
+{\r
+ return iep_bufid_to_iova(pservice, addr_tbl_iep, sizeof(addr_tbl_iep), reg);\r
+}\r
+#endif\r
+\r
/**\r
* generating a series of registers copy from iep message\r
*/\r
\r
INIT_LIST_HEAD(®->session_link);\r
INIT_LIST_HEAD(®->status_link);\r
+ \r
+#if defined(CONFIG_IEP_IOMMU)\r
+ INIT_LIST_HEAD(®->mem_region_list); \r
+#endif \r
\r
//write config\r
iep_config_src_size(iep_msg);\r
iep_config_mmu_dte_addr(iep_msg->base, (uint32_t)virt_to_phys((uint32_t*)session->dte_table));\r
#endif\r
\r
+#if defined(CONFIG_IEP_IOMMU)\r
+ if (0 > iep_reg_address_translate(&iep_service, reg)) {\r
+ pr_err("error: translate reg address failed\n");\r
+ kfree(reg);\r
+ return;\r
+ }\r
+#endif\r
+\r
mutex_lock(&iep_service.lock);\r
\r
list_add_tail(®->status_link, &iep_service.waiting);\r
\r
static void iep_reg_deinit(struct iep_reg *reg)\r
{\r
+#if defined(CONFIG_IEP_IOMMU)\r
+ struct iep_mem_region *mem_region = NULL, *n;\r
+ // release memory region attach to this registers table.\r
+ list_for_each_entry_safe(mem_region, n, ®->mem_region_list, reg_lnk) {\r
+ ion_unmap_iommu(iep_service.iommu_dev, iep_service.ion_client, mem_region->hdl);\r
+ ion_free(iep_service.ion_client, mem_region->hdl);\r
+ list_del_init(&mem_region->reg_lnk);\r
+ kfree(mem_region);\r
+ }\r
+#endif \r
list_del_init(®->session_link);\r
list_del_init(®->status_link);\r
kfree(reg);\r
\r
if (ret == 0) {\r
if (atomic_read(&iep_service.waitcnt) < 10) {\r
+#if defined(CONFIG_IEP_IOMMU)\r
+ iep_power_on(); /* for iep iommu reg configure. */\r
+#endif\r
iep_config(session, msg);\r
atomic_inc(&iep_service.waitcnt);\r
} else {\r
.fops = &iep_fops,\r
};\r
\r
+#if defined(CONFIG_IEP_IOMMU)\r
+extern struct ion_client *rockchip_ion_client_create(const char * name);\r
+#endif\r
static int iep_drv_probe(struct platform_device *pdev)\r
{\r
struct iep_drvdata *data;\r
int ret = 0;\r
struct resource *res = NULL;\r
+#if defined(CONFIG_IEP_IOMMU)\r
+ struct device *mmu_dev = NULL;\r
+#endif\r
\r
data = (struct iep_drvdata*)devm_kzalloc(&pdev->dev, sizeof(struct iep_drvdata), GFP_KERNEL);\r
if (NULL == data) {\r
IEP_ERR("cannot register miscdev (%d)\n", ret);\r
goto err_misc_register;\r
}\r
+ \r
+#if defined(CONFIG_IEP_IOMMU)\r
+ iep_power_on();\r
+ iep_service.ion_client = rockchip_ion_client_create("iep");\r
+ if (IS_ERR(iep_service.ion_client)) {\r
+ dev_err(&pdev->dev, "failed to create ion client for vcodec");\r
+ return PTR_ERR(iep_service.ion_client);\r
+ } else {\r
+ dev_info(&pdev->dev, "vcodec ion client create success!\n");\r
+ }\r
+ \r
+ mmu_dev = rockchip_get_sysmmu_device_by_compatible("iommu,iep");\r
+ \r
+ if (mmu_dev) {\r
+ platform_set_sysmmu(mmu_dev, &pdev->dev);\r
+ iovmm_activate(&pdev->dev);\r
+ }\r
+ \r
+ iep_service.iommu_dev = &pdev->dev;\r
+ iep_power_off();\r
+#endif\r
\r
IEP_INFO("IEP Driver loaded succesfully\n");\r
\r
#include <linux/device.h>\r
#include <linux/miscdevice.h>\r
#include <linux/mutex.h>\r
+\r
+#if defined(CONFIG_ROCKCHIP_IOMMU) && defined(CONFIG_ION_ROCKCHIP)\r
+//#define CONFIG_IEP_IOMMU\r
+#endif\r
+\r
+#ifdef CONFIG_IEP_IOMMU\r
+#include <linux/rockchip_ion.h>\r
+#include <linux/rockchip/iovmm.h>\r
+#include <linux/rockchip/sysmmu.h>\r
+#include <linux/dma-buf.h>\r
+#endif\r
#include "iep.h"\r
\r
#define IEP_REG_LEN 0x100\r
bool enable;\r
\r
struct mutex mutex; // mutex\r
+ \r
+#ifdef CONFIG_IEP_IOMMU\r
+ struct ion_client *ion_client;\r
+ struct device *iommu_dev;\r
+#endif \r
} iep_service_info;\r
\r
struct iep_reg {\r
int vir_height;\r
int layer;\r
unsigned int format;\r
+#if defined(CONFIG_IEP_IOMMU) \r
+ struct list_head mem_region_list;\r
+#endif \r
};\r
\r
+#if defined(CONFIG_IEP_IOMMU)\r
+struct iep_mem_region {\r
+ struct list_head srv_lnk;\r
+ struct list_head reg_lnk;\r
+ struct list_head session_lnk;\r
+ unsigned long iova; /* virtual address for iommu */\r
+ unsigned long len;\r
+ struct ion_handle *hdl;\r
+};\r
+#endif\r
+\r
#endif\r
\r