From 4a15e1e1cd6c2b4a809fbebd74151ccd48b2998c Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 12 Aug 2014 16:12:18 +0800 Subject: [PATCH] prepare for marging develop-3.10-next to develop-3.10 --- arch/arm/mach-rockchip/vcodec_service.c | 104 ++++++++++++++++++++---- 1 file changed, 87 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-rockchip/vcodec_service.c b/arch/arm/mach-rockchip/vcodec_service.c index 873e83fbb318..19ef045dc036 100755 --- a/arch/arm/mach-rockchip/vcodec_service.c +++ b/arch/arm/mach-rockchip/vcodec_service.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -49,8 +50,7 @@ #endif #ifdef CONFIG_VCODEC_MMU -#include -#include +#include #include #endif @@ -103,6 +103,19 @@ typedef struct { unsigned long dec_io_size; } VPU_HW_INFO_E; +struct extra_info_elem { + u32 index; + u32 offset; +}; + +#define EXTRA_INFO_MAGIC 0x4C4A46 + +struct extra_info_for_iommu { + u32 magic; + u32 cnt; + struct extra_info_elem elem[20]; +}; + #define VPU_SERVICE_SHOW_TIME 0 #if VPU_SERVICE_SHOW_TIME @@ -718,8 +731,8 @@ static void vpu_service_power_on(struct vpu_service_info *pservice) #if defined(CONFIG_VCODEC_MMU) if (pservice->mmu_dev) - iovmm_activate(pservice->dev); -#endif + rockchip_iovmm_activate(pservice->dev); +#endif } static inline bool reg_check_rmvb_wmv(vpu_reg *reg) @@ -747,7 +760,9 @@ static inline int reg_probe_width(vpu_reg *reg) } #if defined(CONFIG_VCODEC_MMU) -static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl, int size, vpu_reg *reg) +static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl, + int size, vpu_reg *reg, + struct extra_info_for_iommu *ext_inf) { int i; int usr_fd = 0; @@ -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, ®->mem_region_list); } } + + if (ext_inf != NULL && ext_inf->magic == EXTRA_INFO_MAGIC) { + for (i=0; icnt; i++) { + pr_info("reg[%d] + offset %d\n", ext_inf->elem[i].index, ext_inf->elem[i].offset); + reg->reg[ext_inf->elem[i].index] += ext_inf->elem[i].offset; + } + } + return 0; } -static int vcodec_reg_address_translate(struct vpu_service_info *pservice, vpu_reg *reg) +static int vcodec_reg_address_translate(struct vpu_service_info *pservice, + vpu_reg *reg, + struct extra_info_for_iommu *ext_inf) { VPU_HW_ID hw_id; u8 *tbl; @@ -867,7 +892,7 @@ static int vcodec_reg_address_translate(struct vpu_service_info *pservice, vpu_r } if (size != 0) { - return vcodec_bufid_to_iova(pservice, tbl, size, reg); + return vcodec_bufid_to_iova(pservice, tbl, size, reg, ext_inf); } else { return -1; } @@ -876,6 +901,8 @@ static int vcodec_reg_address_translate(struct vpu_service_info *pservice, vpu_r static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session, void __user *src, unsigned long size) { + int extra_size = 0; + struct extra_info_for_iommu extra_info; vpu_reg *reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL); if (NULL == reg) { pr_err("error: kmalloc fail in reg_init\n"); @@ -883,7 +910,9 @@ static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session } if (size > pservice->reg_size) { - printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size); + /*printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size); + size = pservice->reg_size;*/ + extra_size = size - pservice->reg_size; size = pservice->reg_size; } reg->session = session; @@ -905,8 +934,14 @@ static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session return NULL; } + if (copy_from_user(&extra_info, (u8 *)src + size, extra_size)) { + pr_err("error: copy_from_user failed in reg_init\n"); + kfree(reg); + return NULL; + } + #if defined(CONFIG_VCODEC_MMU) - if (pservice->mmu_dev && 0 > vcodec_reg_address_translate(pservice, reg)) { + if (pservice->mmu_dev && 0 > vcodec_reg_address_translate(pservice, reg, &extra_info)) { pr_err("error: translate reg address failed\n"); kfree(reg); return NULL; @@ -986,7 +1021,7 @@ static void reg_from_wait_to_run(struct vpu_service_info *pservice, vpu_reg *reg list_add_tail(®->session_link, ®->session->running); } -static void reg_copy_from_hw(struct vpu_service_info *pservice, vpu_reg *reg, volatile u32 *src, u32 count) +static void reg_copy_from_hw(vpu_reg *reg, volatile u32 *src, u32 count) { int i; u32 *dst = (u32 *)®->reg[0]; @@ -1008,27 +1043,27 @@ static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg switch (reg->type) { case VPU_ENC : { pservice->reg_codec = NULL; - reg_copy_from_hw(pservice, reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num); + reg_copy_from_hw(reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num); irq_reg = ENC_INTERRUPT_REGISTER; break; } case VPU_DEC : { int reg_len = pservice->hw_info->hw_id == HEVC_ID ? REG_NUM_HEVC_DEC : REG_NUM_9190_DEC; pservice->reg_codec = NULL; - reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs, reg_len); + reg_copy_from_hw(reg, pservice->dec_dev.hwregs, reg_len); irq_reg = DEC_INTERRUPT_REGISTER; break; } case VPU_PP : { pservice->reg_pproc = NULL; - reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP); + reg_copy_from_hw(reg, pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP); pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0; break; } case VPU_DEC_PP : { pservice->reg_codec = NULL; pservice->reg_pproc = NULL; - reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP); + reg_copy_from_hw(reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP); pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0; break; } @@ -1537,6 +1572,41 @@ static void simulate_start(struct vpu_service_info *pservice) } #endif +#ifdef CONFIG_VCODEC_MMU +static struct device *rockchip_get_sysmmu_device_by_compatible(const char *compt) +{ + struct device_node *dn = NULL; + struct platform_device *pd = NULL; + struct device *ret = NULL ; + + dn = of_find_compatible_node(NULL,NULL,compt); + if(!dn) { + printk("can't find device node %s \r\n",compt); + return NULL; + } + + pd = of_find_device_by_node(dn); + if(!pd) { + printk("can't find platform device in device node %s \r\n",compt); + return NULL; + } + ret = &pd->dev; + + return ret; + +} +#ifdef CONFIG_IOMMU_API +static inline void platform_set_sysmmu(struct device *iommu, struct device *dev) +{ + dev->archdata.iommu = iommu; +} +#else +static inline void platform_set_sysmmu(struct device *iommu, struct device *dev) +{ +} +#endif +#endif + #if HEVC_TEST_ENABLE static int hevc_test_case0(vpu_service_info *pservice); #endif @@ -1727,15 +1797,15 @@ static int vcodec_probe(struct platform_device *pdev) } if (pservice->hw_info->hw_id == HEVC_ID) - sprintf(mmu_dev_dts_name, "iommu,hevc_mmu"); + sprintf(mmu_dev_dts_name, HEVC_IOMMU_COMPATIBLE_NAME); else - sprintf(mmu_dev_dts_name, "iommu,vpu_mmu"); + sprintf(mmu_dev_dts_name, VPU_IOMMU_COMPATIBLE_NAME); pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name); if (pservice->mmu_dev) { platform_set_sysmmu(pservice->mmu_dev, pservice->dev); - iovmm_activate(pservice->dev); + rockchip_iovmm_activate(pservice->dev); } } #endif -- 2.34.1