rk3288: raise frequency of vpu aclk when 4k avc decoding
authorljf <ljf@rock-chips.com>
Tue, 25 Mar 2014 12:46:18 +0000 (20:46 +0800)
committerljf <ljf@rock-chips.com>
Tue, 25 Mar 2014 12:46:18 +0000 (20:46 +0800)
arch/arm/mach-rockchip/vcodec_service.c

index 56bafde434d2e8bf733fe40672211adeb6e23c7d..ba109dbfe5f3b45bbd1bce82fb7664aac7c17e31 100755 (executable)
@@ -83,6 +83,8 @@ typedef enum VPU_FREQ {
        VPU_FREQ_266M,\r
        VPU_FREQ_300M,\r
        VPU_FREQ_400M,\r
+    VPU_FREQ_500M,\r
+    VPU_FREQ_600M,\r
        VPU_FREQ_DEFAULT,\r
        VPU_FREQ_BUT,\r
 } VPU_FREQ;\r
@@ -568,6 +570,19 @@ static inline bool reg_check_interlace(vpu_reg *reg)
        return (type > 0);\r
 }\r
 \r
+static inline bool reg_check_avc(vpu_reg *reg)\r
+{\r
+       unsigned long type = (reg->reg[3] & 0xF0000000) >> 28;\r
+       return (type == 0);\r
+}\r
+\r
+static inline int reg_probe_width(vpu_reg *reg)\r
+{\r
+    int width_in_mb = reg->reg[4] >> 23;\r
+    \r
+    return width_in_mb * 16;\r
+}\r
+\r
 #if defined(CONFIG_VCODEC_MMU)\r
 \r
 static unsigned int vcodec_map_ion_handle(vpu_service_info *pservice, \r
@@ -738,7 +753,12 @@ static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session
                        if (reg->type == VPU_DEC || reg->type == VPU_DEC_PP) {\r
                                if (reg_check_rmvb_wmv(reg)) {\r
                                        reg->freq = VPU_FREQ_200M;\r
-                               } else {\r
+                               } else if (reg_check_avc(reg)) {\r
+                    if (reg_probe_width(reg) > 3200) {\r
+                        // raise frequency for 4k avc.\r
+                        reg->freq = VPU_FREQ_500M;\r
+                    }\r
+                } else {\r
                                        if (reg_check_interlace(reg)) {\r
                                                reg->freq = VPU_FREQ_400M;\r
                                        }\r
@@ -876,6 +896,12 @@ static void vpu_service_set_freq(struct vpu_service_info *pservice, vpu_reg *reg
                clk_set_rate(pservice->aclk_vcodec, 400*MHZ);\r
                //printk("default: 400M\n");\r
        } break;\r
+    case VPU_FREQ_500M : {\r
+        clk_set_rate(pservice->aclk_vcodec, 500*MHZ);\r
+    } break;\r
+    case VPU_FREQ_600M : {\r
+        clk_set_rate(pservice->aclk_vcodec, 600*MHZ);\r
+    } break;\r
        default : {\r
                if (soc_is_rk2928g()) {\r
                        clk_set_rate(pservice->aclk_vcodec, 400*MHZ);\r
@@ -1791,13 +1817,16 @@ static void get_hw_info(struct vpu_service_info *pservice)
         enc->reg_size = pservice->reg_size;\r
         enc->reserv[0] = enc->reserv[1] = 0;\r
     \r
-        pservice->auto_freq = soc_is_rk2928g() || soc_is_rk2928l() || soc_is_rk2926();\r
+        pservice->auto_freq = soc_is_rk2928g() || soc_is_rk2928l() || soc_is_rk2926() || soc_is_rk3288();\r
         if (pservice->auto_freq) {\r
             pr_info("vpu_service set to auto frequency mode\n");\r
             atomic_set(&pservice->freq_status, VPU_FREQ_BUT);\r
         }\r
         pservice->bug_dec_addr = cpu_is_rk30xx();\r
         //printk("cpu 3066b bug %d\n", service.bug_dec_addr);\r
+    } else {\r
+        // disable frequency switch in hevc.\r
+        pservice->auto_freq = false;\r
     }\r
 }\r
 \r
@@ -1805,7 +1834,8 @@ static irqreturn_t vdpu_irq(int irq, void *dev_id)
 {\r
     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
+    u32 raw_status;\r
+    u32 irq_status = raw_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
 \r
        pr_debug("dec_irq\n");\r
 \r
@@ -1841,7 +1871,7 @@ static irqreturn_t vdpu_irq(int irq, void *dev_id)
         }\r
     }\r
 \r
-    pservice->irq_status = irq_status;\r
+    pservice->irq_status = raw_status;\r
 \r
        return IRQ_WAKE_THREAD;\r
 }\r