rk3036: modify code for iommu enable for the rk3036 new feature
authorljf <ljf@rock-chips.com>
Thu, 24 Jul 2014 03:52:00 +0000 (11:52 +0800)
committerljf <ljf@rock-chips.com>
Thu, 24 Jul 2014 03:52:00 +0000 (11:52 +0800)
arch/arm/mach-rockchip/vcodec_service.c

index b50712cd79115660b4429e52677cddd7d2277c87..34f16367e6116e2b7521d98f3927cd71cec31d42 100755 (executable)
@@ -281,7 +281,7 @@ typedef struct vpu_session {
  */\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
@@ -378,6 +378,8 @@ typedef struct vpu_request
 /// global variable\r
 //static struct clk *pd_video;\r
 static struct dentry *parent; // debugfs root directory for all device (vpu, hevc).\r
+/* mutex for selecting operation registers of vpu or hevc */\r
+static struct mutex g_mode_mutex;\r
 \r
 #ifdef CONFIG_DEBUG_FS\r
 static int vcodec_debugfs_init(void);\r
@@ -397,9 +399,10 @@ static const struct file_operations debug_vcodec_fops = {
 #define VPU_TIMEOUT_DELAY              2*HZ /* 2s */\r
 #define VPU_SIMULATE_DELAY             msecs_to_jiffies(15)\r
 \r
-static void vcodec_select_mode(enum vcodec_device_id id)\r
+static void vcodec_enter_mode(enum vcodec_device_id id)\r
 {\r
        if (soc_is_rk3036()) {\r
+               mutex_lock(&g_mode_mutex);\r
 #define BIT_VCODEC_SEL         (1<<3)\r
                if (id == VCODEC_DEVICE_ID_HEVC) {\r
                        writel_relaxed(readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1) | (BIT_VCODEC_SEL) | (BIT_VCODEC_SEL << 16), RK_GRF_VIRT + RK3036_GRF_SOC_CON1);\r
@@ -409,6 +412,12 @@ static void vcodec_select_mode(enum vcodec_device_id id)
        }\r
 }\r
 \r
+static void vcodec_exit_mode(void)\r
+{\r
+       if (soc_is_rk3036())\r
+               mutex_unlock(&g_mode_mutex);\r
+}\r
+\r
 static int vpu_get_clk(struct vpu_service_info *pservice)\r
 {\r
 #if VCODEC_CLOCK_ENABLE\r
@@ -753,7 +762,9 @@ static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl, int
 \r
                        mem_region->hdl = hdl;\r
 \r
+                       vcodec_enter_mode(pservice->dev_id);\r
                        ret = ion_map_iommu(pservice->dev, pservice->ion_client, mem_region->hdl, &mem_region->iova, &mem_region->len);\r
+                       vcodec_exit_mode();\r
                        if (ret < 0) {\r
                                dev_err(pservice->dev, "ion map iommu failed\n");\r
                                kfree(mem_region);\r
@@ -920,7 +931,13 @@ static void reg_deinit(struct vpu_service_info *pservice, vpu_reg *reg)
        // release memory region attach to this registers table.\r
        if (pservice->mmu_dev) {\r
                list_for_each_entry_safe(mem_region, n, &reg->mem_region_list, reg_lnk) {\r
-                       ion_unmap_iommu(pservice->dev, pservice->ion_client, mem_region->hdl);\r
+                       /* do not unmap iommu manually,\r
+                          unmap will proccess when memory release */\r
+                       /*vcodec_enter_mode(pservice->dev_id);\r
+                       ion_unmap_iommu(pservice->dev,\r
+                                       pservice->ion_client,\r
+                                       mem_region->hdl);\r
+                       vcodec_exit_mode();*/\r
                        ion_free(pservice->ion_client, mem_region->hdl);\r
                        list_del_init(&mem_region->reg_lnk);\r
                        kfree(mem_region);\r
@@ -945,7 +962,6 @@ static void reg_copy_from_hw(struct vpu_service_info *pservice, vpu_reg *reg, vo
        int i;\r
        u32 *dst = (u32 *)&reg->reg[0];\r
 \r
-       vcodec_select_mode(pservice->dev_id);\r
        for (i = 0; i < count; i++)\r
                *dst++ = *src++;\r
 }\r
@@ -959,6 +975,7 @@ static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg
        list_del_init(&reg->session_link);\r
        list_add_tail(&reg->session_link, &reg->session->done);\r
 \r
+       vcodec_enter_mode(pservice->dev_id);\r
        switch (reg->type) {\r
        case VPU_ENC : {\r
                pservice->reg_codec = NULL;\r
@@ -983,7 +1000,6 @@ static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg
                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
-               vcodec_select_mode(pservice->dev_id);\r
                pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
                break;\r
        }\r
@@ -992,6 +1008,7 @@ static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg
                break;\r
        }\r
        }\r
+       vcodec_exit_mode();\r
 \r
        if (irq_reg != -1) {\r
                reg->reg[irq_reg] = pservice->irq_status;\r
@@ -1055,9 +1072,9 @@ static void reg_copy_to_hw(struct vpu_service_info *pservice, vpu_reg *reg)
        if (pservice->auto_freq) {\r
                vpu_service_set_freq(pservice, reg);\r
        }\r
-       \r
-       vcodec_select_mode(pservice->dev_id);\r
-       \r
+\r
+       vcodec_enter_mode(pservice->dev_id);\r
+\r
        switch (reg->type) {\r
        case VPU_ENC : {\r
                int enc_count = pservice->hw_info->enc_reg_num;\r
@@ -1160,6 +1177,8 @@ static void reg_copy_to_hw(struct vpu_service_info *pservice, vpu_reg *reg)
        }\r
        }\r
 \r
+       vcodec_exit_mode();\r
+\r
 #if HEVC_SIM_ENABLE\r
        if (pservice->hw_info->hw_id == HEVC_ID) {\r
                simulate_start(pservice);\r
@@ -1516,7 +1535,6 @@ static int vcodec_probe(struct platform_device *pdev)
 \r
        if (strcmp(dev_name(dev), "hevc_service") == 0) {\r
                pservice->dev_id = VCODEC_DEVICE_ID_HEVC;\r
-               vcodec_select_mode(VCODEC_DEVICE_ID_HEVC);\r
        } else if (strcmp(dev_name(dev), "vpu_service") == 0) {\r
                pservice->dev_id = VCODEC_DEVICE_ID_VPU;\r
        } else {\r
@@ -1524,6 +1542,9 @@ static int vcodec_probe(struct platform_device *pdev)
                return -1;\r
        }\r
 \r
+       mutex_init(&g_mode_mutex);\r
+       vcodec_enter_mode(pservice->dev_id);\r
+\r
        wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");\r
        INIT_LIST_HEAD(&pservice->waiting);\r
        INIT_LIST_HEAD(&pservice->running);\r
@@ -1563,7 +1584,6 @@ static int vcodec_probe(struct platform_device *pdev)
                if (soc_is_rk3036()) {\r
                        if (pservice->dev_id == VCODEC_DEVICE_ID_VPU)\r
                                offset += 0x400;\r
-                       vcodec_select_mode(pservice->dev_id);\r
                }\r
                ret = vpu_service_check_hw(pservice, offset);\r
                if (ret < 0) {\r
@@ -1576,14 +1596,10 @@ static int vcodec_probe(struct platform_device *pdev)
        pservice->dec_dev.iobaseaddr = res->start + pservice->hw_info->dec_offset;\r
        pservice->dec_dev.iosize     = pservice->hw_info->dec_io_size;\r
 \r
-       printk("%s %d\n", __func__, __LINE__);\r
-\r
        pservice->dec_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->dec_offset);\r
 \r
        pservice->reg_size   = pservice->dec_dev.iosize;\r
 \r
-       printk("%s %d\n", __func__, __LINE__);\r
-\r
        if (pservice->hw_info->hw_id != HEVC_ID && !soc_is_rk3036()) {\r
                pservice->enc_dev.iobaseaddr = res->start + pservice->hw_info->enc_offset;\r
                pservice->enc_dev.iosize     = pservice->hw_info->enc_io_size;\r
@@ -1692,6 +1708,8 @@ static int vcodec_probe(struct platform_device *pdev)
 #endif\r
 \r
        vpu_service_power_off(pservice);\r
+       vcodec_exit_mode();\r
+\r
        pr_info("init success\n");\r
 \r
 #if HEVC_SIM_ENABLE\r
@@ -1795,11 +1813,12 @@ static void get_hw_info(struct vpu_service_info *pservice)
                dec->refBufSupport  = (configReg >> DWL_REF_BUFF_E) & 0x01U;\r
                dec->vp6Support     = (configReg >> DWL_VP6_E) & 0x01U;\r
 \r
-               if (!soc_is_rk3190() && !soc_is_rk3288()) {\r
-                       dec->maxDecPicWidth = configReg & 0x07FFU;\r
-               } else {\r
+               if (soc_is_rk3190() || soc_is_rk3288())\r
                        dec->maxDecPicWidth = 4096;\r
-               }\r
+               else if (soc_is_rk3036())\r
+                       dec->maxDecPicWidth = 1920;\r
+               else\r
+                       dec->maxDecPicWidth = configReg & 0x07FFU;\r
        \r
                /* 2nd Config register */\r
                configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG1];\r
@@ -1970,6 +1989,10 @@ static void get_hw_info(struct vpu_service_info *pservice)
 \r
                pservice->bug_dec_addr = cpu_is_rk30xx();\r
        } else {\r
+               if (soc_is_rk3036())\r
+                       dec->maxDecPicWidth = 1920;\r
+               else\r
+                       dec->maxDecPicWidth = 4096;\r
                /* disable frequency switch in hevc.*/\r
                pservice->auto_freq = false;\r
        }\r
@@ -1982,7 +2005,7 @@ static irqreturn_t vdpu_irq(int irq, void *dev_id)
        u32 raw_status;\r
        u32 irq_status;\r
 \r
-       vcodec_select_mode(pservice->dev_id);\r
+       vcodec_enter_mode(pservice->dev_id);\r
 \r
        irq_status = raw_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
 \r
@@ -2016,6 +2039,7 @@ static irqreturn_t vdpu_irq(int irq, void *dev_id)
        }\r
 \r
        pservice->irq_status = raw_status;\r
+       vcodec_exit_mode();\r
 \r
        return IRQ_WAKE_THREAD;\r
 }\r
@@ -2068,7 +2092,7 @@ static irqreturn_t vepu_irq(int irq, void *dev_id)
        vpu_device *dev = &pservice->enc_dev;\r
        u32 irq_status;\r
 \r
-       vcodec_select_mode(pservice->dev_id);\r
+       vcodec_enter_mode(pservice->dev_id);\r
        irq_status= readl(dev->hwregs + ENC_INTERRUPT_REGISTER);\r
 \r
        pr_debug("vepu_irq irq status %x\n", irq_status);\r
@@ -2086,6 +2110,7 @@ static irqreturn_t vepu_irq(int irq, void *dev_id)
        }\r
 \r
        pservice->irq_status = irq_status;\r
+       vcodec_exit_mode();\r
 \r
        return IRQ_WAKE_THREAD;\r
 }\r