rk3288: commit hevc and vpu service
authorljf <ljf@rock-chips.com>
Thu, 20 Mar 2014 19:37:19 +0000 (03:37 +0800)
committerljf <ljf@rock-chips.com>
Thu, 20 Mar 2014 19:37:19 +0000 (03:37 +0800)
arch/arm/boot/dts/rk3288.dtsi
arch/arm/mach-rockchip/vcodec_service.c

index fd214e3d40694e869d21fe61ff163fea8c9254c6..88bc8cb3806bfb61211891885fd8289dc8d43644 100755 (executable)
                clocks = <&clk_vepu>, <&hclk_vepu>;
                clock-names = "aclk_vcodec", "hclk_vcodec";
                name = "vpu_service";
-               status = "disabled";
+               //status = "disabled";
        };
 
-       hevc: hevc_service@ff9c0000 {
+        hevc: hevc_service@ff9c0000 {
                compatible = "rockchip,hevc_service";
                reg = <0xff9c0000 0x800>;
                interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-names = "irq_dec";
                clocks = <&aclk_hevc>, <&hclk_hevc>, <&clk_hevc_core>, <&clk_hevc_cabac>;
-        clock-names = "aclk_hevc", "hclk_hevc", "clk_core", "clk_cabac";
+                clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core", "clk_cabac";
                name = "hevc_service";
-               status = "disabled";
+               //status = "disabled";
        };
 
-       iep: iep@ff900000 {
+        iep: iep@ff900000 {
                compatible = "rockchip,iep";
                reg = <0xff900000 0x800>;
                interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
index e2983a0b2745423203700ce2804e5f785aea961b..a80c578d5c3e73b57af9a82bc8e594573ef1d0c5 100755 (executable)
@@ -54,7 +54,7 @@
 #include "vcodec_service.h"\r
 \r
 #define HEVC_TEST_ENABLE    0\r
-#define HEVC_SIM_ENABLE                1\r
+#define HEVC_SIM_ENABLE                0\r
 \r
 typedef enum {\r
        VPU_DEC_ID_9190         = 0x6731,\r
@@ -99,14 +99,6 @@ static struct timeval pp_start,  pp_end;
 \r
 #define MHZ                                    (1000*1000)\r
 \r
-#if 0\r
-#if defined(CONFIG_ARCH_RK319X)\r
-#define VCODEC_PHYS             RK319X_VCODEC_PHYS\r
-#else\r
-#define VCODEC_PHYS                            (0x10104000)\r
-#endif\r
-#endif\r
-\r
 #define REG_NUM_9190_DEC                       (60)\r
 #define REG_NUM_9190_PP                                (41)\r
 #define REG_NUM_9190_DEC_PP                    (REG_NUM_9190_DEC+REG_NUM_9190_PP)\r
@@ -224,6 +216,11 @@ typedef struct vpu_device {
        volatile u32            *hwregs;\r
 } vpu_device;\r
 \r
+enum vcodec_device_id {\r
+       VCODEC_DEVICE_ID_VPU,\r
+       VCODEC_DEVICE_ID_HEVC\r
+};\r
+\r
 typedef struct vpu_service_info {\r
        struct wake_lock        wake_lock;\r
        struct delayed_work     power_off_work;\r
@@ -247,6 +244,8 @@ typedef struct vpu_service_info {
 \r
     struct clk *aclk_vcodec;\r
     struct clk *hclk_vcodec;\r
+    struct clk *clk_core;\r
+    struct clk *clk_cabac;\r
 \r
     int irq_dec;\r
     int irq_enc;\r
@@ -265,7 +264,11 @@ typedef struct vpu_service_info {
     struct dentry   *debugfs_file_regs;\r
 \r
     u32 irq_status;\r
+#if defined(CONFIG_ION_ROCKCHIP)       \r
        struct ion_client * ion_client;\r
+#endif \r
+\r
+       enum vcodec_device_id dev_id;\r
 \r
     struct delayed_work simulate_work;\r
 } vpu_service_info;\r
@@ -297,7 +300,7 @@ static const struct file_operations debug_vcodec_fops = {
 #define VPU_POWER_OFF_DELAY            4*HZ /* 4s */\r
 #define VPU_TIMEOUT_DELAY              2*HZ /* 2s */\r
 \r
-#define VPU_SIMULATE_DELAY      msecs_to_jiffies(5)\r
+#define VPU_SIMULATE_DELAY      msecs_to_jiffies(15)\r
 \r
 static void vpu_get_clk(struct vpu_service_info *pservice)\r
 {\r
@@ -305,14 +308,28 @@ static void vpu_get_clk(struct vpu_service_info *pservice)
        if (IS_ERR(pd_video)) {\r
                pr_err("failed on clk_get pd_video\n");\r
        }*/\r
+\r
        pservice->aclk_vcodec   = devm_clk_get(pservice->dev, "aclk_vcodec");\r
        if (IS_ERR(pservice->aclk_vcodec)) {\r
                dev_err(pservice->dev, "failed on clk_get aclk_vcodec\n");\r
        }\r
+\r
        pservice->hclk_vcodec   = devm_clk_get(pservice->dev, "hclk_vcodec");\r
        if (IS_ERR(pservice->hclk_vcodec)) {\r
                dev_err(pservice->dev, "failed on clk_get hclk_vcodec\n");\r
        }\r
+\r
+       if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
+               pservice->clk_core = devm_clk_get(pservice->dev, "clk_core");\r
+               if (IS_ERR(pservice->clk_core)) {\r
+                       dev_err(pservice->dev, "failed on clk_get clk_core\n");\r
+               }\r
+\r
+               pservice->clk_cabac = devm_clk_get(pservice->dev, "clk_cabac");\r
+               if (IS_ERR(pservice->clk_cabac)) {\r
+                       dev_err(pservice->dev, "failed on clk_get clk_cabac\n");\r
+               }\r
+       }\r
 }\r
 \r
 static void vpu_put_clk(struct vpu_service_info *pservice)\r
@@ -326,6 +343,16 @@ static void vpu_put_clk(struct vpu_service_info *pservice)
     if (pservice->hclk_vcodec) {\r
         devm_clk_put(pservice->dev, pservice->hclk_vcodec);\r
     }\r
+\r
+    if (pservice->hw_info->hw_id == HEVC_ID) {\r
+        if (pservice->clk_core) {\r
+            devm_clk_put(pservice->dev, pservice->clk_core);\r
+        }\r
+        \r
+        if (pservice->clk_cabac) {\r
+            devm_clk_put(pservice->dev, pservice->clk_cabac);\r
+        }\r
+    }\r
 }\r
 \r
 static void vpu_reset(struct vpu_service_info *pservice)\r
@@ -427,11 +454,13 @@ static void vpu_service_power_off(struct vpu_service_info *pservice)
        //clk_disable(pd_video);\r
 #endif\r
        udelay(10);\r
-       //clk_disable(hclk_cpu_vcodec);\r
-       //clk_disable(aclk_ddr_vepu);\r
 #if 0\r
        clk_disable_unprepare(pservice->hclk_vcodec);\r
        clk_disable_unprepare(pservice->aclk_vcodec);\r
+    if (pservice->hw_info->hw_id == HEVC_ID) {\r
+        clk_disable_unprepare(pservice->clk_core);\r
+        clk_disable_unprepare(pservice->clk_cabac);\r
+    }\r
 #endif\r
        wake_unlock(&pservice->wake_lock);\r
        printk("done\n");\r
@@ -474,8 +503,12 @@ static void vpu_service_power_on(struct vpu_service_info *pservice)
 #if 0\r
     clk_prepare_enable(pservice->aclk_vcodec);\r
        clk_prepare_enable(pservice->hclk_vcodec);\r
+    if (pservice->hw_info->hw_id == HEVC_ID) {\r
+        clk_prepare_enable(pservice->clk_core);\r
+        clk_prepare_enable(pservice->clk_cabac);\r
+    }\r
 #endif\r
-       //clk_prepare_enable(hclk_cpu_vcodec);\r
+\r
 #if defined(CONFIG_ARCH_RK319X)\r
     /// select aclk_vepu as vcodec clock source. \r
     #define BIT_VCODEC_SEL  (1<<7)\r
@@ -488,7 +521,6 @@ static void vpu_service_power_on(struct vpu_service_info *pservice)
        //clk_enable(pd_video);\r
 #endif\r
        udelay(10);\r
-       //clk_enable(aclk_ddr_vepu);\r
        wake_lock(&pservice->wake_lock);\r
 }\r
 \r
@@ -786,15 +818,28 @@ static void reg_copy_to_hw(struct vpu_service_info *pservice, vpu_reg *reg)
        } break;\r
        case VPU_DEC : {\r
                u32 *dst = (u32 *)pservice->dec_dev.hwregs;\r
+\r
                pservice->reg_codec = reg;\r
 \r
-               for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--)\r
-                       dst[i] = src[i];\r
+        if (pservice->hw_info->hw_id != HEVC_ID) {\r
+                       for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--)\r
+                               dst[i] = src[i];\r
+        } else {\r
+            for (i = REG_NUM_HEVC_DEC - 1; i > VPU_REG_EN_DEC; i--) {\r
+                               dst[i] = src[i];\r
+            }\r
+               }\r
 \r
                dsb();\r
 \r
-               dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;\r
-               dst[VPU_REG_EN_DEC]   = src[VPU_REG_EN_DEC];\r
+               if (pservice->hw_info->hw_id != HEVC_ID) {\r
+                       dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;\r
+                       dst[VPU_REG_EN_DEC]   = src[VPU_REG_EN_DEC];\r
+               } else {\r
+                       dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];\r
+               }\r
+        dsb();\r
+        dmb();\r
 \r
 #if VPU_SERVICE_SHOW_TIME\r
                do_gettimeofday(&dec_start);\r
@@ -1184,6 +1229,15 @@ static int vcodec_probe(struct platform_device *pdev)
     of_property_read_string(np, "name", (const char**)&prop);\r
     dev_set_name(dev, prop);\r
 \r
+       if (strcmp(dev_name(dev), "hevc_service") == 0) {\r
+               pservice->dev_id = 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
+               dev_err(dev, "Unknown device %s to probe\n", dev_name(dev));\r
+               return -1;\r
+       }\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
@@ -1621,6 +1675,7 @@ static irqreturn_t vdpu_irq(int irq, void *dev_id)
     struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
     vpu_device *dev = &pservice->dec_dev;\r
        u32 irq_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
+    int i;\r
 \r
        pr_debug("dec_irq\n");\r
 \r
@@ -1846,7 +1901,7 @@ static int debug_vcodec_open(struct inode *inode, struct file *file)
 \r
 #endif\r
 \r
-#if HEVC_TEST_ENABLE\r
+#if HEVC_TEST_ENABLE & defined(CONFIG_ION_ROCKCHIP)\r
 #include "hevc_test_inc/pps_00.h"\r
 #include "hevc_test_inc/register_00.h"\r
 #include "hevc_test_inc/rps_00.h"\r
@@ -1861,12 +1916,55 @@ static int debug_vcodec_open(struct inode *inode, struct file *file)
 \r
 #include "hevc_test_inc/cabac.h"\r
 \r
+extern struct ion_client *rockchip_ion_client_create(const char * name);\r
+\r
+static struct ion_client *ion_client = NULL;\r
+u8* get_align_ptr(u8* tbl, int len, u32 *phy)\r
+{\r
+       int size = (len+15) & (~15);\r
+    struct ion_handle *handle;\r
+       u8 *ptr;// = (u8*)kzalloc(size, GFP_KERNEL);\r
+\r
+    if (ion_client == NULL) {\r
+        ion_client = rockchip_ion_client_create("vcodec");\r
+    }\r
+\r
+    handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
+\r
+    ptr = ion_map_kernel(ion_client, handle);\r
+\r
+    ion_phys(ion_client, handle, phy, &size);\r
+\r
+       memcpy(ptr, tbl, len);\r
+\r
+       return ptr;\r
+}\r
+\r
+u8* get_align_ptr_no_copy(int len, u32 *phy)\r
+{\r
+       int size = (len+15) & (~15);\r
+    struct ion_handle *handle;\r
+       u8 *ptr;// = (u8*)kzalloc(size, GFP_KERNEL);\r
+\r
+    if (ion_client == NULL) {\r
+        ion_client = rockchip_ion_client_create("vcodec");\r
+    }\r
+\r
+    handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
+\r
+    ptr = ion_map_kernel(ion_client, handle);\r
+\r
+    ion_phys(ion_client, handle, phy, &size);\r
+\r
+       return ptr;\r
+}\r
+\r
 #define TEST_CNT    2\r
 static int hevc_test_case0(vpu_service_info *pservice)\r
 {\r
     vpu_session session;\r
     vpu_reg *reg; \r
-    unsigned long size = sizeof(register_00); // registers array length\r
+    unsigned long size = 272;//sizeof(register_00); // registers array length\r
     int testidx = 0;\r
     int ret = 0;\r
 \r
@@ -1876,17 +1974,30 @@ static int hevc_test_case0(vpu_service_info *pservice)
     u8 *scaling_list_tbl[TEST_CNT];\r
     u8 *stream_tbl[TEST_CNT];\r
 \r
-    int stream_size[2];\r
-\r
+       int stream_size[2];\r
+       int pps_size[2];\r
+       int rps_size[2];\r
+       int scl_size[2];\r
+       int cabac_size[2];\r
+       \r
     u32 phy_pps;\r
     u32 phy_rps;\r
     u32 phy_scl;\r
     u32 phy_str;\r
     u32 phy_yuv;\r
+    u32 phy_ref;\r
     u32 phy_cabac;\r
 \r
+       volatile u8 *stream_buf;\r
+       volatile u8 *pps_buf;\r
+       volatile u8 *rps_buf;\r
+       volatile u8 *scl_buf;\r
+       volatile u8 *yuv_buf;\r
+       volatile u8 *cabac_buf;\r
+       volatile u8 *ref_buf;\r
+\r
     u8 *pps;\r
-    u8 *yuv;\r
+    u8 *yuv[2];\r
     int i;\r
     \r
     pps_tbl[0] = pps_00;\r
@@ -1907,6 +2018,18 @@ static int hevc_test_case0(vpu_service_info *pservice)
     stream_size[0] = sizeof(stream_00);\r
     stream_size[1] = sizeof(stream_01);\r
 \r
+       pps_size[0] = sizeof(pps_00);\r
+       pps_size[1] = sizeof(pps_01);\r
+\r
+       rps_size[0] = sizeof(rps_00);\r
+       rps_size[1] = sizeof(rps_01);\r
+\r
+       scl_size[0] = sizeof(scaling_list_00);\r
+       scl_size[1] = sizeof(scaling_list_01);\r
+       \r
+       cabac_size[0] = sizeof(Cabac_table);\r
+       cabac_size[1] = sizeof(Cabac_table);\r
+\r
     // create session\r
     session.pid = current->pid;\r
     session.type = VPU_DEC;\r
@@ -1918,7 +2041,11 @@ static int hevc_test_case0(vpu_service_info *pservice)
        atomic_set(&session.task_running, 0);\r
        list_add_tail(&session.list_session, &pservice->session);\r
 \r
-    while (testidx < TEST_CNT) {\r
+    yuv[0] = get_align_ptr_no_copy(256*256*2, &phy_yuv);\r
+    yuv[1] = get_align_ptr_no_copy(256*256*2, &phy_ref);\r
+\r
+       while (testidx < TEST_CNT) {\r
+       \r
         // create registers\r
         reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
         if (NULL == reg) {\r
@@ -1926,6 +2053,7 @@ static int hevc_test_case0(vpu_service_info *pservice)
             return -1;\r
         }\r
 \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
             size = pservice->reg_size;\r
@@ -1938,20 +2066,18 @@ static int hevc_test_case0(vpu_service_info *pservice)
         INIT_LIST_HEAD(&reg->session_link);\r
         INIT_LIST_HEAD(&reg->status_link);\r
 \r
-        pps = kmalloc(sizeof(pps_00), GFP_KERNEL);\r
-        yuv = kzalloc(256*256*3/2, GFP_KERNEL);\r
-        memcpy(pps, pps_tbl[testidx], sizeof(pps_00));\r
-\r
         // TODO: stuff registers\r
-        memcpy(&reg->reg[0], register_tbl[testidx], sizeof(register_00));\r
+        memcpy(&reg->reg[0], register_tbl[testidx], /*sizeof(register_00)*/ 176);\r
+\r
+               stream_buf = get_align_ptr(stream_tbl[testidx], stream_size[testidx], &phy_str);\r
+               pps_buf = get_align_ptr(pps_tbl[0], pps_size[0], &phy_pps);\r
+               rps_buf = get_align_ptr(rps_tbl[testidx], rps_size[testidx], &phy_rps);\r
+               scl_buf = get_align_ptr(scaling_list_tbl[testidx], scl_size[testidx], &phy_scl);\r
+               cabac_buf = get_align_ptr(Cabac_table, cabac_size[testidx], &phy_cabac);\r
+\r
+               pps = pps_buf;\r
 \r
         // TODO: replace reigster address\r
-        phy_pps = virt_to_phys(pps);\r
-        phy_rps = virt_to_phys(rps_tbl[testidx]);\r
-        phy_scl = virt_to_phys(scaling_list_tbl[testidx]);\r
-        phy_str = virt_to_phys(stream_tbl[testidx]);\r
-        phy_yuv = virt_to_phys(yuv);\r
-        phy_cabac = virt_to_phys(Cabac_table);\r
 \r
         for (i=0; i<64; i++) {\r
             u32 scaling_offset;\r
@@ -1970,17 +2096,18 @@ static int hevc_test_case0(vpu_service_info *pservice)
             pps[i*80+77] = (tmp >> 24) & 0xff;\r
         }\r
 \r
-        dmac_flush_range(&pps[0], &pps[sizeof(pps_00) - 1]);\r
-        outer_flush_range(phy_pps, phy_pps + sizeof(pps_00) - 1);\r
-\r
         printk("%s %d, phy stream %08x, phy pps %08x, phy rps %08x\n", __func__, __LINE__, phy_str, phy_pps, phy_rps);\r
 \r
+        reg->reg[1] = 0x21;\r
         reg->reg[4] = phy_str;\r
         reg->reg[5] = ((stream_size[testidx]+15)&(~15))+64;\r
         reg->reg[6] = phy_cabac;\r
-        reg->reg[7] = phy_yuv;\r
+        reg->reg[7] = testidx?phy_ref:phy_yuv;\r
         reg->reg[42] = phy_pps;\r
         reg->reg[43] = phy_rps;\r
+        for (i = 10; i <= 24; i++) {\r
+            reg->reg[i] = phy_yuv;\r
+        }\r
 \r
         mutex_lock(&pservice->lock);\r
         list_add_tail(&reg->status_link, &pservice->waiting);\r
@@ -2029,8 +2156,6 @@ static int hevc_test_case0(vpu_service_info *pservice)
                }\r
 \r
             pr_err("test index %d failed\n", testidx);\r
-            kfree(pps);\r
-            kfree(yuv);\r
             break;\r
         } else {\r
             pr_info("test index %d success\n", testidx);\r
@@ -2051,8 +2176,6 @@ static int hevc_test_case0(vpu_service_info *pservice)
         }\r
 \r
         reg_deinit(pservice, reg);\r
-        kfree(pps);\r
-        kfree(yuv);\r
     }\r
 \r
     return 0;\r