#include <linux/rockchip_ion.h>\r
#endif\r
\r
+#if defined(CONFIG_ROCKCHIP_IOMMU)\r
//#define CONFIG_VCODEC_MMU\r
+#endif\r
\r
#ifdef CONFIG_VCODEC_MMU\r
#include <linux/rockchip/iovmm.h>\r
#include "vcodec_service.h"\r
\r
#define HEVC_TEST_ENABLE 0\r
-#define HEVC_SIM_ENABLE 0\r
+#define HEVC_SIM_ENABLE 0\r
#define VCODEC_CLOCK_ENABLE 1\r
\r
typedef enum {\r
#define VPU_REG_DEC_PP_GATE 61\r
#define VPU_REG_DEC_PP_GATE_BIT (1<<8)\r
\r
+#if defined(CONFIG_VCODEC_MMU)\r
static u8 addr_tbl_vpu_dec[] = {\r
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 41\r
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 41\r
};\r
\r
static u8 addr_tbl_vpu_enc[] = {\r
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 51\r
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 51\r
};\r
\r
static u8 addr_tbl_hevc_dec[] = {\r
4, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 42, 43\r
};\r
+#endif\r
\r
/**\r
* struct for process session which connect to vpu\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
+ unsigned long iova; /* virtual address for iommu */\r
+ unsigned long len;\r
struct ion_handle *hdl;\r
};\r
\r
\r
static void vpu_service_power_off(struct vpu_service_info *pservice)\r
{\r
- int total_running;\r
- if (!pservice->enabled) {\r
- return;\r
- }\r
+ int total_running;\r
+ if (!pservice->enabled) {\r
+ return;\r
+ }\r
\r
- pservice->enabled = false;\r
- total_running = atomic_read(&pservice->total_running);\r
- if (total_running) {\r
- pr_alert("alert: power off when %d task running!!\n", total_running);\r
- mdelay(50);\r
- pr_alert("alert: delay 50 ms for running task\n");\r
- vpu_service_dump(pservice);\r
- }\r
+ pservice->enabled = false;\r
+ total_running = atomic_read(&pservice->total_running);\r
+ if (total_running) {\r
+ pr_alert("alert: power off when %d task running!!\n", total_running);\r
+ mdelay(50);\r
+ pr_alert("alert: delay 50 ms for running task\n");\r
+ vpu_service_dump(pservice);\r
+ }\r
\r
printk("%s: power off...", dev_name(pservice->dev));\r
udelay(10);\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
+static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl, int size, vpu_reg *reg)\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
+ int i;\r
+ int usr_fd = 0;\r
+ int offset = 0;\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
+ if (tbl == NULL || size <= 0) {\r
+ dev_err(pservice->dev, "input arguments invalidate\n");\r
+ return -1;\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
+ 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]] & 0xFF;\r
+ offset = reg->reg[tbl[i]] >> 8;\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->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
- 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
+ reg->reg[tbl[i]] = phy_addr + offset;\r
+ \r
+ ion_free(pservice->ion_client, hdl);\r
+ }\r
+#else \r
+ {\r
+ int ret;\r
+ struct vcodec_mem_region *mem_region;\r
+ mem_region = kzalloc(sizeof(struct vcodec_mem_region), GFP_KERNEL);\r
+ \r
+ if (mem_region == NULL) {\r
+ dev_err(pservice->dev, "allocate memory for iommu memory region failed\n");\r
+ ion_free(pservice->ion_client, hdl);\r
+ return -1;\r
+ }\r
+ \r
+ ret = ion_map_iommu(pservice->dev, pservice->ion_client, hdl, &mem_region->iova, &mem_region->len);\r
+ if (ret < 0) {\r
+ dev_err(pservice->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
- 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
+ return 0;\r
}\r
\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
-\r
- hw_id = pservice->hw_info->hw_id;\r
-\r
+ VPU_HW_ID hw_id;\r
+ u8 *tbl;\r
+ int size = 0;\r
+ \r
+ hw_id = pservice->hw_info->hw_id;\r
+ \r
if (hw_id == HEVC_ID) {\r
-\r
+ tbl = addr_tbl_hevc_dec;\r
+ size = sizeof(addr_tbl_hevc_dec);\r
} else {\r
- if (reg->type == VPU_DEC) {\r
- for (i=0; i<sizeof(addr_tbl_vpu_dec); i++) {\r
- int usr_fd;\r
- struct ion_handle *hdl;\r
- //ion_phys_addr_t phy_addr;\r
- struct dma_buf *buf;\r
- //size_t len;\r
- int offset;\r
-\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[addr_tbl_vpu_dec[i]] & 0xFF;\r
- offset = reg->reg[addr_tbl_vpu_dec[i]] >> 8;\r
-#endif\r
- if (usr_fd != 0) {\r
-\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 PTR_ERR(hdl);\r
- }\r
-\r
-#if 0\r
- ion_phys(pservice->ion_client, hdl, &phy_addr, &len);\r
-\r
- reg->reg[addr_tbl_vpu_dec[i]] = phy_addr + offset;\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[addr_tbl_vpu_dec[i]] = vcodec_map_ion_handle(pservice, reg, hdl, buf, offset);\r
-#endif\r
- \r
- }\r
- }\r
+ if (reg->type == VPU_DEC || reg->type == VPU_DEC_PP) {\r
+ tbl = addr_tbl_vpu_dec;\r
+ size = sizeof(addr_tbl_vpu_dec);\r
} else if (reg->type == VPU_ENC) {\r
-\r
+ tbl = addr_tbl_vpu_enc;\r
+ size = sizeof(addr_tbl_vpu_enc);\r
}\r
- }\r
-\r
- return 0;\r
+ }\r
+ \r
+ if (size != 0) {\r
+ return vcodec_bufid_to_iova(pservice, tbl, size, reg);\r
+ } else {\r
+ return -1;\r
+ }\r
}\r
#endif\r
\r
\r
#if defined(CONFIG_VCODEC_MMU)\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
+ pr_err("error: translate reg address failed\n");\r
+ kfree(reg);\r
+ return NULL;\r
}\r
#endif\r
\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
+ 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_unmap_iommu(pservice->dev, pservice->ion_client, mem_region->hdl);\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
dev_info(&pdev->dev, "vcodec ion client create success!\n");\r
}\r
\r
- sprintf(mmu_dev_dts_name, "iommu,%s", dev_name(dev));\r
+ if (pservice->hw_info->hw_id == HEVC_ID) {\r
+ sprintf(mmu_dev_dts_name, "iommu,hevc_mmu");\r
+ } else {\r
+ sprintf(mmu_dev_dts_name, "iommu,vpu_mmu");\r
+ }\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
+ if (mmu_dev) {\r
+ platform_set_sysmmu(mmu_dev, pservice->dev);\r
+ iovmm_activate(pservice->dev);\r
+ }\r
#endif\r
\r
#if HEVC_SIM_ENABLE\r