VPU_FREQ_300M,
VPU_FREQ_400M,
VPU_FREQ_DEFAULT,
+ VPU_FREQ_BUT,
} VPU_FREQ;
typedef struct {
unsigned long dec_io_size;
} VPU_HW_INFO_E;
+#define VPU_SERVICE_SHOW_TIME 0
+
+#if VPU_SERVICE_SHOW_TIME
+static struct timeval enc_start, enc_end;
+static struct timeval dec_start, dec_end;
+static struct timeval pp_start, pp_end;
+#endif
+
#define MHZ (1000*1000)
#define VCODEC_PHYS (0x10104000)
VPU_HW_INFO_E *hw_info;
unsigned long reg_size;
bool auto_freq;
+ atomic_t freq_status;
} vpu_service_info;
typedef struct vpu_request
static void vpu_get_clk(void)
{
pd_video = clk_get(NULL, "pd_video");
+ if (IS_ERR(pd_video)) {
+ pr_err("failed on clk_get pd_video\n");
+ }
aclk_vepu = clk_get(NULL, "aclk_vepu");
+ if (IS_ERR(aclk_vepu)) {
+ pr_err("failed on clk_get aclk_vepu\n");
+ }
hclk_vepu = clk_get(NULL, "hclk_vepu");
+ if (IS_ERR(hclk_vepu)) {
+ pr_err("failed on clk_get hclk_vepu\n");
+ }
aclk_ddr_vepu = clk_get(NULL, "aclk_ddr_vepu");
+ if (IS_ERR(aclk_ddr_vepu)) {
+ pr_err("failed on clk_get aclk_ddr_vepu\n");
+ }
hclk_cpu_vcodec = clk_get(NULL, "hclk_cpu_vcodec");
+ if (IS_ERR(hclk_cpu_vcodec)) {
+ pr_err("failed on clk_get hclk_cpu_vcodec\n");
+ }
}
static void vpu_put_clk(void)
if (service.auto_freq) {
if (reg->type == VPU_DEC || reg->type == VPU_DEC_PP) {
if (reg_check_rmvb_wmv(reg)) {
- reg->freq = VPU_FREQ_266M;
+ reg->freq = VPU_FREQ_200M;
} else {
if (reg_check_interlace(reg)) {
reg->freq = VPU_FREQ_400M;
static void vpu_service_set_freq(vpu_reg *reg)
{
+ VPU_FREQ curr = atomic_read(&service.freq_status);
+ if (curr == reg->freq) {
+ return ;
+ }
+ atomic_set(&service.freq_status, reg->freq);
switch (reg->freq) {
case VPU_FREQ_200M : {
clk_set_rate(aclk_vepu, 200*MHZ);
+ //printk("default: 200M\n");
} break;
case VPU_FREQ_266M : {
clk_set_rate(aclk_vepu, 266*MHZ);
+ //printk("default: 266M\n");
} break;
case VPU_FREQ_300M : {
clk_set_rate(aclk_vepu, 300*MHZ);
+ //printk("default: 300M\n");
} break;
case VPU_FREQ_400M : {
clk_set_rate(aclk_vepu, 400*MHZ);
+ //printk("default: 400M\n");
} break;
default : {
clk_set_rate(aclk_vepu, 300*MHZ);
+ //printk("default: 300M\n");
} break;
}
}
dst[VPU_REG_ENC_GATE] = src[VPU_REG_ENC_GATE] | VPU_REG_ENC_GATE_BIT;
dst[VPU_REG_EN_ENC] = src[VPU_REG_EN_ENC];
+
+#if VPU_SERVICE_SHOW_TIME
+ do_gettimeofday(&enc_start);
+#endif
+
} break;
case VPU_DEC : {
u32 *dst = (u32 *)dec_dev.hwregs;
dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;
dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];
+
+#if VPU_SERVICE_SHOW_TIME
+ do_gettimeofday(&dec_start);
+#endif
+
} break;
case VPU_PP : {
u32 *dst = (u32 *)dec_dev.hwregs + PP_INTERRUPT_REGISTER;
dsb();
dst[VPU_REG_EN_PP] = src[VPU_REG_EN_PP];
+
+#if VPU_SERVICE_SHOW_TIME
+ do_gettimeofday(&pp_start);
+#endif
+
} break;
case VPU_DEC_PP : {
u32 *dst = (u32 *)dec_dev.hwregs;
dst[VPU_REG_DEC_PP_GATE] = src[VPU_REG_DEC_PP_GATE] | VPU_REG_PP_GATE_BIT;
dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;
dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];
+
+#if VPU_SERVICE_SHOW_TIME
+ do_gettimeofday(&dec_start);
+#endif
+
} break;
default : {
pr_err("error: unsupport session type %d", reg->type);
service.auto_freq = soc_is_rk2928g() || soc_is_rk2928l() || soc_is_rk2926();
if (service.auto_freq) {
printk("vpu_service set to auto frequency mode\n");
+ atomic_set(&service.freq_status, VPU_FREQ_BUT);
}
}
mutex_lock(&service.lock);
if (atomic_read(&dev->irq_count_codec)) {
+#if VPU_SERVICE_SHOW_TIME
+ do_gettimeofday(&dec_end);
+ printk("dec task: %ld ms\n",
+ (dec_end.tv_sec - dec_start.tv_sec) * 1000 +
+ (dec_end.tv_usec - dec_start.tv_usec) / 1000);
+#endif
atomic_sub(1, &dev->irq_count_codec);
if (NULL == service.reg_codec) {
pr_err("error: dec isr with no task waiting\n");
}
if (atomic_read(&dev->irq_count_pp)) {
+
+#if VPU_SERVICE_SHOW_TIME
+ do_gettimeofday(&pp_end);
+ printk("pp task: %ld ms\n",
+ (pp_end.tv_sec - pp_start.tv_sec) * 1000 +
+ (pp_end.tv_usec - pp_start.tv_usec) / 1000);
+#endif
+
atomic_sub(1, &dev->irq_count_pp);
if (NULL == service.reg_pproc) {
pr_err("error: pp isr with no task waiting\n");
pr_debug("vepu_irq irq status %x\n", irq_status);
+#if VPU_SERVICE_SHOW_TIME
+ do_gettimeofday(&enc_end);
+ printk("enc task: %ld ms\n",
+ (enc_end.tv_sec - enc_start.tv_sec) * 1000 +
+ (enc_end.tv_usec - enc_start.tv_usec) / 1000);
+#endif
+
if (likely(irq_status & ENC_INTERRUPT_BIT)) {
/* clear enc IRQ */
writel(irq_status & (~ENC_INTERRUPT_BIT), dev->hwregs + ENC_INTERRUPT_REGISTER);