prepare for marging develop-3.10-next to develop-3.10
authorljf <ljf@rock-chips.com>
Tue, 12 Aug 2014 08:12:18 +0000 (16:12 +0800)
committerljf <ljf@rock-chips.com>
Tue, 12 Aug 2014 08:12:49 +0000 (16:12 +0800)
arch/arm/mach-rockchip/vcodec_service.c

index 873e83fbb31838b00f8a747e04c5ed0978d4aea1..19ef045dc0360f9080b1af89a93e0bc67fb13431 100755 (executable)
@@ -33,6 +33,7 @@
 #include <linux/wakelock.h>\r
 #include <linux/cdev.h>\r
 #include <linux/of.h>\r
+#include <linux/of_platform.h>\r
 #include <linux/rockchip/cpu.h>\r
 #include <linux/rockchip/cru.h>\r
 \r
@@ -49,8 +50,7 @@
 #endif\r
 \r
 #ifdef CONFIG_VCODEC_MMU\r
-#include <linux/rockchip/iovmm.h>\r
-#include <linux/rockchip/sysmmu.h>\r
+#include <linux/rockchip-iovmm.h>\r
 #include <linux/dma-buf.h>\r
 #endif\r
 \r
@@ -103,6 +103,19 @@ typedef struct {
        unsigned long           dec_io_size;\r
 } VPU_HW_INFO_E;\r
 \r
+struct extra_info_elem {\r
+       u32 index;\r
+       u32 offset;\r
+};\r
+\r
+#define EXTRA_INFO_MAGIC       0x4C4A46\r
+\r
+struct extra_info_for_iommu {\r
+       u32 magic;\r
+       u32 cnt;\r
+       struct extra_info_elem elem[20];\r
+};\r
+\r
 #define VPU_SERVICE_SHOW_TIME                  0\r
 \r
 #if VPU_SERVICE_SHOW_TIME\r
@@ -718,8 +731,8 @@ static void vpu_service_power_on(struct vpu_service_info *pservice)
 \r
 #if defined(CONFIG_VCODEC_MMU)\r
        if (pservice->mmu_dev)\r
-               iovmm_activate(pservice->dev);\r
-#endif\r
+               rockchip_iovmm_activate(pservice->dev);\r
+#endif    \r
 }\r
 \r
 static inline bool reg_check_rmvb_wmv(vpu_reg *reg)\r
@@ -747,7 +760,9 @@ static inline int reg_probe_width(vpu_reg *reg)
 }\r
 \r
 #if defined(CONFIG_VCODEC_MMU)\r
-static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl, int size, vpu_reg *reg)\r
+static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl,\r
+                               int size, vpu_reg *reg,\r
+                               struct extra_info_for_iommu *ext_inf)\r
 {\r
        int i;\r
        int usr_fd = 0;\r
@@ -805,10 +820,20 @@ static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl, int
                        list_add_tail(&mem_region->reg_lnk, &reg->mem_region_list);\r
                }\r
        }\r
+\r
+       if (ext_inf != NULL && ext_inf->magic == EXTRA_INFO_MAGIC) {\r
+               for (i=0; i<ext_inf->cnt; i++) {\r
+                       pr_info("reg[%d] + offset %d\n", ext_inf->elem[i].index, ext_inf->elem[i].offset);\r
+                       reg->reg[ext_inf->elem[i].index] += ext_inf->elem[i].offset;\r
+               }\r
+       }\r
+\r
        return 0;\r
 }\r
 \r
-static int vcodec_reg_address_translate(struct vpu_service_info *pservice, vpu_reg *reg)\r
+static int vcodec_reg_address_translate(struct vpu_service_info *pservice,\r
+                                       vpu_reg *reg,\r
+                                       struct extra_info_for_iommu *ext_inf)\r
 {\r
        VPU_HW_ID hw_id;\r
        u8 *tbl;\r
@@ -867,7 +892,7 @@ static int vcodec_reg_address_translate(struct vpu_service_info *pservice, vpu_r
        }\r
 \r
        if (size != 0) {\r
-               return vcodec_bufid_to_iova(pservice, tbl, size, reg);\r
+               return vcodec_bufid_to_iova(pservice, tbl, size, reg, ext_inf);\r
        } else {\r
                return -1;\r
        }\r
@@ -876,6 +901,8 @@ static int vcodec_reg_address_translate(struct vpu_service_info *pservice, vpu_r
 \r
 static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session, void __user *src, unsigned long size)\r
 {\r
+       int extra_size = 0;\r
+       struct extra_info_for_iommu extra_info;\r
        vpu_reg *reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
        if (NULL == reg) {\r
                pr_err("error: kmalloc fail in reg_init\n");\r
@@ -883,7 +910,9 @@ static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session
        }\r
 \r
        if (size > pservice->reg_size) {\r
-               printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
+               /*printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
+               size = pservice->reg_size;*/\r
+               extra_size = size - pservice->reg_size;\r
                size = pservice->reg_size;\r
        }\r
        reg->session = session;\r
@@ -905,8 +934,14 @@ static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session
                return NULL;\r
        }\r
 \r
+       if (copy_from_user(&extra_info, (u8 *)src + size, extra_size)) {\r
+               pr_err("error: copy_from_user failed in reg_init\n");\r
+               kfree(reg);\r
+               return NULL;\r
+       }\r
+\r
 #if defined(CONFIG_VCODEC_MMU)\r
-       if (pservice->mmu_dev && 0 > vcodec_reg_address_translate(pservice, reg)) {\r
+       if (pservice->mmu_dev && 0 > vcodec_reg_address_translate(pservice, reg, &extra_info)) {\r
                pr_err("error: translate reg address failed\n");\r
                kfree(reg);\r
                return NULL;\r
@@ -986,7 +1021,7 @@ static void reg_from_wait_to_run(struct vpu_service_info *pservice, vpu_reg *reg
        list_add_tail(&reg->session_link, &reg->session->running);\r
 }\r
 \r
-static void reg_copy_from_hw(struct vpu_service_info *pservice, vpu_reg *reg, volatile u32 *src, u32 count)\r
+static void reg_copy_from_hw(vpu_reg *reg, volatile u32 *src, u32 count)\r
 {\r
        int i;\r
        u32 *dst = (u32 *)&reg->reg[0];\r
@@ -1008,27 +1043,27 @@ static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg
        switch (reg->type) {\r
        case VPU_ENC : {\r
                pservice->reg_codec = NULL;\r
-               reg_copy_from_hw(pservice, reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num);\r
+               reg_copy_from_hw(reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num);\r
                irq_reg = ENC_INTERRUPT_REGISTER;\r
                break;\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
                pservice->reg_codec = NULL;\r
-               reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs, reg_len);\r
+               reg_copy_from_hw(reg, pservice->dec_dev.hwregs, reg_len);\r
                irq_reg = DEC_INTERRUPT_REGISTER;\r
                break;\r
        }\r
        case VPU_PP : {\r
                pservice->reg_pproc = NULL;\r
-               reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP);\r
+               reg_copy_from_hw(reg, pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP);\r
                pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
                break;\r
        }\r
        case VPU_DEC_PP : {\r
                pservice->reg_codec = NULL;\r
                pservice->reg_pproc = NULL;\r
-               reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP);\r
+               reg_copy_from_hw(reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP);\r
                pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
                break;\r
        }\r
@@ -1537,6 +1572,41 @@ static void simulate_start(struct vpu_service_info *pservice)
 }\r
 #endif\r
 \r
+#ifdef CONFIG_VCODEC_MMU\r
+static struct device *rockchip_get_sysmmu_device_by_compatible(const char *compt)\r
+{\r
+       struct device_node *dn = NULL;\r
+       struct platform_device *pd = NULL;\r
+       struct device *ret = NULL ;\r
+\r
+       dn = of_find_compatible_node(NULL,NULL,compt);\r
+       if(!dn) {\r
+               printk("can't find device node %s \r\n",compt);\r
+               return NULL;\r
+       }\r
+       \r
+       pd = of_find_device_by_node(dn);\r
+       if(!pd) {       \r
+               printk("can't find platform device in device node %s \r\n",compt);\r
+               return  NULL;\r
+       }\r
+       ret = &pd->dev;\r
+       \r
+       return ret;\r
+\r
+}\r
+#ifdef CONFIG_IOMMU_API\r
+static inline void platform_set_sysmmu(struct device *iommu, struct device *dev)\r
+{\r
+       dev->archdata.iommu = iommu;\r
+}\r
+#else\r
+static inline void platform_set_sysmmu(struct device *iommu, struct device *dev)\r
+{\r
+}\r
+#endif\r
+#endif\r
+\r
 #if HEVC_TEST_ENABLE\r
 static int hevc_test_case0(vpu_service_info *pservice);\r
 #endif\r
@@ -1727,15 +1797,15 @@ static int vcodec_probe(struct platform_device *pdev)
                }\r
 \r
                if (pservice->hw_info->hw_id == HEVC_ID)\r
-                       sprintf(mmu_dev_dts_name, "iommu,hevc_mmu");\r
+                       sprintf(mmu_dev_dts_name, HEVC_IOMMU_COMPATIBLE_NAME);\r
                else\r
-                       sprintf(mmu_dev_dts_name, "iommu,vpu_mmu");\r
+                       sprintf(mmu_dev_dts_name, VPU_IOMMU_COMPATIBLE_NAME);\r
 \r
                pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);\r
 \r
                if (pservice->mmu_dev) {\r
                        platform_set_sysmmu(pservice->mmu_dev, pservice->dev);\r
-                       iovmm_activate(pservice->dev);\r
+                       rockchip_iovmm_activate(pservice->dev);\r
                }\r
        }\r
 #endif\r