#include <linux/rockchip_ion.h>\r
#endif\r
\r
+//#define CONFIG_VCODEC_MMU\r
+\r
+#ifdef CONFIG_VCODEC_MMU\r
+#include <linux/rockchip/iovmm.h>\r
+#include <linux/rockchip/sysmmu.h>\r
+#include <linux/dma-buf.h>\r
+#endif\r
+\r
#ifdef CONFIG_DEBUG_FS\r
#include <linux/debugfs.h>\r
#endif\r
*/\r
typedef struct vpu_reg {\r
VPU_CLIENT_TYPE type;\r
- VPU_FREQ freq;\r
+ VPU_FREQ freq;\r
vpu_session *session;\r
struct list_head session_link; /* link to vpu service session */\r
struct list_head status_link; /* link to register set list */\r
unsigned long size;\r
+#if defined(CONFIG_VCODEC_MMU) \r
+ struct list_head mem_region_list;\r
+#endif \r
unsigned long *reg;\r
} vpu_reg;\r
\r
VCODEC_DEVICE_ID_HEVC\r
};\r
\r
+struct vcodec_mem_region {\r
+ struct list_head srv_lnk;\r
+ struct list_head reg_lnk;\r
+ struct list_head session_lnk;\r
+ dma_addr_t iova; /* virtual address for iommu */\r
+ struct dma_buf *buf;\r
+ struct dma_buf_attachment *attachment;\r
+ struct sg_table *sg_table;\r
+ struct ion_handle *hdl;\r
+};\r
+\r
typedef struct vpu_service_info {\r
struct wake_lock wake_lock;\r
struct delayed_work power_off_work;\r
struct ion_client * ion_client;\r
#endif \r
\r
+#if defined(CONFIG_VCODEC_MMU)\r
+ struct list_head mem_region_list;\r
+#endif\r
+\r
enum vcodec_device_id dev_id;\r
\r
struct delayed_work simulate_work;\r
}\r
\r
#if defined(CONFIG_VCODEC_MMU)\r
+\r
+static unsigned int vcodec_map_ion_handle(vpu_service_info *pservice, \r
+ vpu_reg *reg,\r
+ struct ion_handle *ion_handle,\r
+ struct dma_buf *buf, int offset)\r
+{\r
+ struct vcodec_mem_region *mem_region = kzalloc(sizeof(struct vcodec_mem_region), GFP_KERNEL);\r
+ if (mem_region == NULL) {\r
+ dev_err(pservice->dev, "allocate memory for iommu memory region failed\n");\r
+ return -1;\r
+ }\r
+ \r
+ mem_region->buf = buf;\r
+ mem_region->hdl = ion_handle;\r
+ \r
+ mem_region->attachment = dma_buf_attach(buf, pservice->dev);\r
+ if (IS_ERR_OR_NULL(mem_region->attachment)) {\r
+ dev_err(pservice->dev, "dma_buf_attach() failed: %ld\n", PTR_ERR(mem_region->attachment));\r
+ goto err_buf_map_attach;\r
+ }\r
+ \r
+ mem_region->sg_table = dma_buf_map_attachment(mem_region->attachment, DMA_BIDIRECTIONAL);\r
+ if (IS_ERR_OR_NULL(mem_region->sg_table)) {\r
+ dev_err(pservice->dev, "dma_buf_map_attachment() failed: %ld\n", PTR_ERR(mem_region->sg_table));\r
+ goto err_buf_map_attachment;\r
+ }\r
+ \r
+ mem_region->iova = iovmm_map(pservice->dev, mem_region->sg_table->sgl, offset, buf->size);\r
+ if (mem_region->iova == 0 || IS_ERR_VALUE(mem_region->iova)) {\r
+ dev_err(pservice->dev, "iovmm_map() failed: %d\n", mem_region->iova);\r
+ goto err_iovmm_map;\r
+ }\r
+ \r
+ INIT_LIST_HEAD(&mem_region->reg_lnk);\r
+ list_add_tail(&mem_region->reg_lnk, ®->mem_region_list);\r
+ \r
+ return mem_region->iova;\r
+ \r
+err_iovmm_map:\r
+ dma_buf_unmap_attachment(mem_region->attachment, mem_region->sg_table, DMA_BIDIRECTIONAL);\r
+err_buf_map_attachment:\r
+ dma_buf_detach(buf, mem_region->attachment);\r
+err_buf_map_attach:\r
+ kfree(mem_region);\r
+ return 0;\r
+}\r
+\r
static u8 table_vpu_dec[] = {\r
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 41\r
};\r
\r
};\r
\r
-static int reg_address_translate(struct vpu_service_info *pservice, vpu_reg *reg)\r
+static int vcodec_reg_address_translate(struct vpu_service_info *pservice, vpu_reg *reg)\r
{\r
VPU_HW_ID hw_id;\r
int i;\r
for (i=0; i<sizeof(table_vpu_dec); i++) {\r
int usr_fd;\r
struct ion_handle *hdl;\r
- ion_phys_addr_t phy_addr;\r
- size_t len;\r
+ //ion_phys_addr_t phy_addr;\r
+ struct dma_buf *buf;\r
+ //size_t len;\r
int offset;\r
\r
#if 0\r
hdl = ion_import_dma_buf(pservice->ion_client, usr_fd);\r
if (IS_ERR(hdl)) {\r
pr_err("import dma-buf from fd %d failed\n", usr_fd);\r
- return ERR_PTR(hdl);\r
+ return PTR_ERR(hdl);\r
}\r
\r
+#if 0\r
ion_phys(pservice->ion_client, hdl, &phy_addr, &len);\r
\r
reg->reg[table_vpu_dec[i]] = phy_addr + offset;\r
-\r
- ion_free(pservice->ion_client, hdl);\r
+ \r
+ ion_free(pservice->ion_client, hdl);\r
+#else \r
+ buf = ion_share_dma_buf(pservice->ion_client, hdl);\r
+ if (IS_ERR_OR_NULL(buf)) {\r
+ dev_err(pservice->dev, "ion_share_dma_buf() failed\n");\r
+ ion_free(pservice->ion_client, hdl);\r
+ return PTR_ERR(buf);\r
+ }\r
+ \r
+ reg->reg[table_vpu_dec[i]] = vcodec_map_ion_handle(pservice, reg, hdl, buf, offset);\r
+#endif\r
+ \r
}\r
}\r
} else if (reg->type == VPU_ENC) {\r
INIT_LIST_HEAD(®->session_link);\r
INIT_LIST_HEAD(®->status_link);\r
\r
+#if defined(CONFIG_VCODEC_MMU) \r
+ INIT_LIST_HEAD(®->mem_region_list);\r
+#endif \r
+\r
if (copy_from_user(®->reg[0], (void __user *)src, size)) {\r
pr_err("error: copy_from_user failed in reg_init\n");\r
kfree(reg);\r
}\r
\r
#if defined(CONFIG_VCODEC_MMU)\r
- if (0 > reg_address_translate(pservice, reg)) {\r
+ if (0 > vcodec_reg_address_translate(pservice, reg)) {\r
pr_err("error: translate reg address failed\n");\r
kfree(reg);\r
return NULL;\r
\r
static void reg_deinit(struct vpu_service_info *pservice, vpu_reg *reg)\r
{\r
+#if defined(CONFIG_VCODEC_MMU) \r
+ struct vcodec_mem_region *mem_region = NULL, *n;\r
+#endif\r
+ \r
list_del_init(®->session_link);\r
list_del_init(®->status_link);\r
if (reg == pservice->reg_codec) pservice->reg_codec = NULL;\r
if (reg == pservice->reg_pproc) pservice->reg_pproc = NULL;\r
+ \r
+#if defined(CONFIG_VCODEC_MMU)\r
+ // release memory region attach to this registers table.\r
+ list_for_each_entry_safe(mem_region, n, ®->mem_region_list, reg_lnk) {\r
+ iovmm_unmap(pservice->dev, mem_region->iova);\r
+ \r
+ dma_buf_unmap_attachment(mem_region->attachment, mem_region->sg_table, DMA_BIDIRECTIONAL);\r
+ dma_buf_detach(mem_region->buf, mem_region->attachment);\r
+ \r
+ dma_buf_put(mem_region->buf);\r
+ ion_free(pservice->ion_client, mem_region->hdl);\r
+ \r
+ list_del_init(&mem_region->reg_lnk);\r
+ \r
+ kfree(mem_region);\r
+ }\r
+#endif \r
+ \r
kfree(reg);\r
}\r
\r
}\r
case VPU_DEC : {\r
int reg_len = pservice->hw_info->hw_id == HEVC_ID ? REG_NUM_HEVC_DEC : REG_NUM_9190_DEC;\r
- if (copy_to_user(dst, ®->reg[0], reg_len))\r
+ if (copy_to_user(dst, ®->reg[0], SIZE_REG(reg_len)))\r
ret = -EFAULT;\r
break;\r
}\r
struct device_node *np = pdev->dev.of_node;\r
struct vpu_service_info *pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL);\r
char *prop = (char*)dev_name(dev);\r
+#if defined(CONFIG_VCODEC_MMU)\r
+ struct device *mmu_dev = NULL;\r
+ char mmu_dev_dts_name[40];\r
+#endif\r
\r
pr_info("probe device %s\n", dev_name(dev));\r
\r
} else {\r
dev_info(&pdev->dev, "vcodec ion client create success!\n");\r
}\r
+ \r
+ sprintf(mmu_dev_dts_name, "iommu,%s", dev_name(dev));\r
+ \r
+ mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);\r
+ platform_set_sysmmu(mmu_dev, pservice->dev);\r
+ \r
+ iovmm_activate(pservice->dev);\r
#endif\r
\r
#if HEVC_SIM_ENABLE\r