116 files changed, 25845 insertions, 36303 deletions
diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c index 41e84ba..15b841e 100644 --- a/drivers/frame_provider/decoder/utils/vdec.c +++ b/drivers/frame_provider/decoder/utils/vdec.c @@ -121,10 +121,8 @@ static int max_di_instance = 2; //static int path_debug = 0; -static struct vframe_qos_s *frame_info_buf_in = NULL; -static struct vframe_qos_s *frame_info_buf_out = NULL; -static int frame_qos_wr = 0; -static int frame_qos_rd = 0; +static int enable_mvdec_info = 1; + int decode_underflow = 0; #define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1) @@ -195,9 +193,63 @@ static const char * const vdec_status_string[] = { "VDEC_STATUS_CONNECTED", "VDEC_STATUS_ACTIVE" }; +/* +bit [28] enable print +bit [23:16] etc +bit [15:12] + none 0 and not 0x1: force single + none 0 and 0x1: force multi +bit [8] + 1: force dual +bit [3] + 1: use mavs for single mode +bit [2] + 1: force vfm path for frame mode +bit [1] + 1: force esparser auto mode +bit [0] + 1: disable audo manual mode ?? +*/ static int debugflags; +static char vfm_path[VDEC_MAP_NAME_SIZE] = {"disable"}; +static const char vfm_path_node[][VDEC_MAP_NAME_SIZE] = +{ + "video_render.0", + "video_render.1", + "amvideo", + "videopip", + "deinterlace", + "dimulti.1", + "amlvideo", + "aml_video.1", + "amlvideo2.0", + "amlvideo2.1", + "ppmgr", + "ionvideo", + "ionvideo.1", + "ionvideo.2", + "ionvideo.3", + "ionvideo.4", + "ionvideo.5", + "ionvideo.6", + "ionvideo.7", + "ionvideo.8", + "videosync.0", + "v4lvideo.0", + "v4lvideo.1", + "v4lvideo.2", + "v4lvideo.3", + "v4lvideo.4", + "v4lvideo.5", + "v4lvideo.6", + "v4lvideo.7", + "v4lvideo.8", + "disable", + "reserved", +}; + static struct canvas_status_s canvas_stat[AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1]; @@ -207,6 +259,13 @@ int vdec_get_debug_flags(void) } EXPORT_SYMBOL(vdec_get_debug_flags); +void VDEC_PRINT_FUN_LINENO(const char *fun, int line) +{ + if (debugflags & 0x10000000) + pr_info("%s, %d\n", fun, line); +} +EXPORT_SYMBOL(VDEC_PRINT_FUN_LINENO); + unsigned char is_mult_inc(unsigned int type) { unsigned char ret = 0; @@ -585,9 +644,15 @@ static void vdec_disable_DMC(struct vdec_s *vdec) codec_dmcbus_read(DMC_REQ_CTRL) & ~mask); spin_unlock_irqrestore(&vdec_spin_lock, flags); - while (!(codec_dmcbus_read(DMC_CHAN_STS) + if (is_cpu_tm2_revb()) { + while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS) & mask)) ; + } else { + while (!(codec_dmcbus_read(DMC_CHAN_STS) + & mask)) + ; + } pr_debug("%s input->target= 0x%x\n", __func__, input->target); } @@ -628,6 +693,7 @@ static int vdec_get_hw_type(int value) case VFORMAT_HEVC: case VFORMAT_VP9: case VFORMAT_AVS2: + case VFORMAT_AV1: type = CORE_MASK_HEVC; break; @@ -741,7 +807,6 @@ EXPORT_SYMBOL(vdec_status); int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) { int r; - if (vdec->set_trickmode) { r = vdec->set_trickmode(vdec, trickmode); @@ -750,7 +815,6 @@ int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) trickmode); return r; } - return -1; } EXPORT_SYMBOL(vdec_set_trickmode); @@ -863,7 +927,8 @@ static const char * const vdec_device_name[] = { "amvenc_avc", "amvenc_avc", "jpegenc", "jpegenc", "amvdec_vp9", "ammvdec_vp9", - "amvdec_avs2", "ammvdec_avs2" + "amvdec_avs2", "ammvdec_avs2", + "amvdec_av1", "ammvdec_av1", }; @@ -885,7 +950,8 @@ static const char * const vdec_device_name[] = { "amvenc_avc", "jpegenc", "amvdec_vp9", - "amvdec_avs2" + "amvdec_avs2", + "amvdec_av1" }; #endif @@ -897,7 +963,7 @@ static const char * const vdec_device_name[] = { static const char *get_dev_name(bool use_legacy_vdec, int format) { #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - if (use_legacy_vdec) + if (use_legacy_vdec && (debugflags & 0x8) == 0) return vdec_device_name[format * 2]; else return vdec_device_name[format * 2 + 1]; @@ -987,7 +1053,8 @@ int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p) sprintf(fmt, "m%s", ++str); if (is_support_profile(fmt) && - vdec->sys_info->format != VIDEO_DEC_FORMAT_H263) + vdec->sys_info->format != VIDEO_DEC_FORMAT_H263 && + vdec->format != VFORMAT_AV1) vdec->type = VDEC_TYPE_STREAM_PARSER; } @@ -1027,6 +1094,9 @@ struct vdec_s *vdec_create(struct stream_port_s *port, INIT_LIST_HEAD(&vdec->list); atomic_inc(&vdec_core->vdec_nr); +#ifdef CONFIG_AMLOGIC_V4L_VIDEO3 + v4lvideo_dec_count_increase(); +#endif vdec->id = id; vdec_input_init(&vdec->input, vdec); vdec->input.vdec_is_input_frame_empty = vdec_is_input_frame_empty; @@ -1036,6 +1106,12 @@ struct vdec_s *vdec_create(struct stream_port_s *port, master->slave = vdec; master->sched = 1; } + if (enable_mvdec_info) { + vdec->mvfrm = (struct vdec_frames_s *) + vzalloc(sizeof(struct vdec_frames_s)); + if (!vdec->mvfrm) + pr_err("vzalloc: vdec_frames_s failed\n"); + } } pr_debug("vdec_create instance %p, total %d\n", vdec, @@ -1137,6 +1213,13 @@ int vdec_write_vframe(struct vdec_s *vdec, const char *buf, size_t count) } EXPORT_SYMBOL(vdec_write_vframe); +int vdec_write_vframe_with_dma(struct vdec_s *vdec, + ulong addr, size_t count, u32 handle) +{ + return vdec_input_add_frame_with_dma(&vdec->input, addr, count, handle); +} +EXPORT_SYMBOL(vdec_write_vframe_with_dma); + /* add a work queue thread for vdec*/ void vdec_schedule_work(struct work_struct *work) { @@ -1693,9 +1776,15 @@ void hevc_wait_ddr(void) codec_dmcbus_read(DMC_REQ_CTRL) & ~mask); spin_unlock_irqrestore(&vdec_spin_lock, flags); - while (!(codec_dmcbus_read(DMC_CHAN_STS) - & mask)) - ; + if (is_cpu_tm2_revb()) { + while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS) + & mask)) + ; + } else { + while (!(codec_dmcbus_read(DMC_CHAN_STS) + & mask)) + ; + } } void vdec_save_input_context(struct vdec_s *vdec) @@ -1744,6 +1833,7 @@ void vdec_save_input_context(struct vdec_s *vdec) vdec->input.streaming_rp &= 0xffffffffULL << 32; vdec->input.streaming_rp |= vdec->input.stream_cookie; vdec->input.total_rd_count = vdec->input.streaming_rp; + hevc_wait_ddr(); } input->swap_valid = true; @@ -1759,8 +1849,6 @@ void vdec_save_input_context(struct vdec_s *vdec) /* pr_info("master->input.last_swap_slave = %d\n", master->input.last_swap_slave); */ } - - hevc_wait_ddr(); } } EXPORT_SYMBOL(vdec_save_input_context); @@ -1877,6 +1965,8 @@ EXPORT_SYMBOL(vdec_sync_input); const char *vdec_status_str(struct vdec_s *vdec) { + if (vdec->status < 0) + return "INVALID"; return vdec->status < ARRAY_SIZE(vdec_status_string) ? vdec_status_string[vdec->status] : "INVALID"; } @@ -2025,8 +2115,13 @@ int vdec_destroy(struct vdec_s *vdec) vdec_profile_flush(vdec); #endif ida_simple_remove(&vdec_core->ida, vdec->id); + if (vdec->mvfrm) + vfree(vdec->mvfrm); vfree(vdec); +#ifdef CONFIG_AMLOGIC_V4L_VIDEO3 + v4lvideo_dec_count_decrease(); +#endif atomic_dec(&vdec_core->vdec_nr); return 0; @@ -2044,6 +2139,7 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) const char *dev_name; int id = PLATFORM_DEVID_AUTO;/*if have used my self*/ + //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid); dev_name = get_dev_name(vdec_single(vdec), vdec->format); if (dev_name == NULL) @@ -2073,21 +2169,26 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) vdec_input_set_type(&vdec->input, vdec->type, (vdec->format == VFORMAT_HEVC || vdec->format == VFORMAT_AVS2 || - vdec->format == VFORMAT_VP9) ? + vdec->format == VFORMAT_VP9 || + vdec->format == VFORMAT_AV1 + ) ? VDEC_INPUT_TARGET_HEVC : VDEC_INPUT_TARGET_VLD); - if (vdec_single(vdec)) + if (vdec_single(vdec) || (vdec_get_debug_flags() & 0x2)) vdec_enable_DMC(vdec); p->cma_dev = vdec_core->cma_dev; p->get_canvas = get_canvas; p->get_canvas_ex = get_canvas_ex; p->free_canvas_ex = free_canvas_ex; p->vdec_fps_detec = vdec_fps_detec; + atomic_set(&p->inrelease, 0); atomic_set(&p->inirq_flag, 0); atomic_set(&p->inirq_thread_flag, 0); /* todo */ if (!vdec_dual(vdec)) p->use_vfm_path = vdec_stream_based(vdec); + if (debugflags & 0x4) + p->use_vfm_path = 1; /* vdec_dev_reg.flag = 0; */ if (vdec->id >= 0) id = vdec->id; @@ -2149,7 +2250,13 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) goto error; } - if (p->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO) { + + if (strncmp("disable", vfm_path, strlen("disable"))) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, vfm_path); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); + } else if (p->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO) { #if 1 r = ionvideo_assign_map(&vdec->vf_receiver_name, &vdec->vf_receiver_inst); @@ -2212,6 +2319,12 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) "amvideo"); snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); + } else if (p->frame_base_video_path == FRAME_BASE_PATH_PIP_TUNNEL_MODE) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "videosync.0 videopip"); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) { snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, "%s %s %s", vdec->vf_provider_name, @@ -2233,7 +2346,7 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) mutex_unlock(&vdec_mutex); goto error; } - if (!v4lvideo_add_di || vdec_secure(vdec)) + if (!v4lvideo_add_di) snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, "%s %s", vdec->vf_provider_name, vdec->vf_receiver_name); @@ -2330,32 +2443,14 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) } p->dolby_meta_with_el = 0; - pr_debug("vdec_init, vf_provider_name = %s\n", p->vf_provider_name); + pr_debug("vdec_init, vf_provider_name = %s, b %d\n", + p->vf_provider_name, is_cpu_tm2_revb()); vdec_input_prepare_bufs(/*prepared buffer for fast playing.*/ &vdec->input, vdec->sys_info->width, vdec->sys_info->height); /* vdec is now ready to be active */ vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); - if (p->use_vfm_path) { - frame_info_buf_in = (struct vframe_qos_s *) - kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL); - if (!frame_info_buf_in) - pr_err("kmalloc: frame_info_buf_in failed\n"); - else - memset(frame_info_buf_in, 0, - QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); - - frame_info_buf_out = (struct vframe_qos_s *) - kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL); - if (!frame_info_buf_out) - pr_err("kmalloc: frame_info_buf_out failed\n"); - else - memset(frame_info_buf_out, 0, - QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); - frame_qos_wr = 0; - frame_qos_rd = 0; - } return 0; error: @@ -2363,6 +2458,34 @@ error: } EXPORT_SYMBOL(vdec_init); +/* + *Remove the vdec after timeout happens both in vdec_disconnect + *and platform_device_unregister. Then after, we can release the vdec. + */ +static void vdec_connect_list_force_clear(struct vdec_core_s *core, struct vdec_s *v_ref) +{ + struct vdec_s *vdec, *tmp; + unsigned long flags; + + flags = vdec_core_lock(core); + + list_for_each_entry_safe(vdec, tmp, + &core->connected_vdec_list, list) { + if ((vdec->status == VDEC_STATUS_DISCONNECTED) && + (vdec == v_ref)) { + pr_err("%s, vdec = %p, active vdec = %p\n", + __func__, vdec, core->active_vdec); + if (core->active_vdec == v_ref) + core->active_vdec = NULL; + if (core->last_vdec == v_ref) + core->last_vdec = NULL; + list_del(&vdec->list); + } + } + + vdec_core_unlock(core, flags); +} + /* vdec_create/init/release/destroy are applied to both dual running decoders */ void vdec_release(struct vdec_s *vdec) @@ -2404,6 +2527,7 @@ void vdec_release(struct vdec_s *vdec) } } + atomic_set(&vdec->inrelease, 1); while ((atomic_read(&vdec->inirq_flag) > 0) || (atomic_read(&vdec->inirq_thread_flag) > 0)) schedule(); @@ -2415,16 +2539,10 @@ void vdec_release(struct vdec_s *vdec) if (atomic_read(&vdec_core->vdec_nr) == 1) vdec_disable_DMC(vdec); platform_device_unregister(vdec->dev); + /*Check if the vdec still in connected list, if yes, delete it*/ + vdec_connect_list_force_clear(vdec_core, vdec); pr_debug("vdec_release instance %p, total %d\n", vdec, atomic_read(&vdec_core->vdec_nr)); - if (vdec->use_vfm_path) { - kfree(frame_info_buf_in); - frame_info_buf_in = NULL; - kfree(frame_info_buf_out); - frame_info_buf_out = NULL; - frame_qos_wr = 0; - frame_qos_rd = 0; - } vdec_destroy(vdec); mutex_lock(&vdec_mutex); @@ -2657,6 +2775,8 @@ static irqreturn_t vdec_isr(int irq, void *dev_id) } if (vdec) { + if (atomic_read(&vdec->inrelease) > 0) + return ret; atomic_set(&vdec->inirq_flag, 1); vdec->isr_ns = local_clock(); } @@ -2714,11 +2834,13 @@ static irqreturn_t vdec_thread_isr(int irq, void *dev_id) if (vdec) { u32 isr2tfn = 0; + if (atomic_read(&vdec->inrelease) > 0) + return ret; atomic_set(&vdec->inirq_thread_flag, 1); vdec->tfn_ns = local_clock(); isr2tfn = vdec->tfn_ns - vdec->isr_ns; if (isr2tfn > 10000000) - pr_err("!!!!!!! %s vdec_isr to %s took %uns !!!\n", + pr_err("!!!!!!! %s vdec_isr to %s took %u ns !!!\n", vdec->vf_provider_name, __func__, isr2tfn); } if (c->dev_threaded_isr) { @@ -2863,12 +2985,7 @@ void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask) if (secure && vdec_stream_based(vdec) && force_nosecure_even_drm) { - /* Verimatrix ultra webclient (HLS) was played in drmmode and used hw demux. In drmmode VDEC only can access secure. - Now HW demux parsed es data to no-secure buffer. So the VDEC input was no-secure, VDEC playback failed. Forcing - use nosecure for verimatrix webclient HLS. If in the future HW demux can parse es data to secure buffer, make - VDEC r/w secure.*/ secure = 0; - //pr_debug("allow VDEC can access nosecure even in drmmode\n"); } if (input->target == VDEC_INPUT_TARGET_VLD) tee_config_device_secure(DMC_DEV_ID_VDEC, secure); @@ -3837,9 +3954,15 @@ void vdec_reset_core(struct vdec_s *vdec) codec_dmcbus_read(DMC_REQ_CTRL) & ~mask); spin_unlock_irqrestore(&vdec_spin_lock, flags); - while (!(codec_dmcbus_read(DMC_CHAN_STS) - & mask)) - ; + if (is_cpu_tm2_revb()) { + while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS) + & mask)) + ; + } else { + while (!(codec_dmcbus_read(DMC_CHAN_STS) + & mask)) + ; + } /* * 2: assist * 3: vld_reset @@ -3920,9 +4043,15 @@ void hevc_reset_core(struct vdec_s *vdec) codec_dmcbus_read(DMC_REQ_CTRL) & ~mask); spin_unlock_irqrestore(&vdec_spin_lock, flags); - while (!(codec_dmcbus_read(DMC_CHAN_STS) - & mask)) - ; + if (is_cpu_tm2_revb()) { + while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS) + & mask)) + ; + } else { + while (!(codec_dmcbus_read(DMC_CHAN_STS) + & mask)) + ; + } if (vdec == NULL || input_frame_based(vdec)) WRITE_VREG(HEVC_STREAM_CONTROL, 0); @@ -4193,6 +4322,28 @@ static ssize_t clock_level_show(struct class *class, return ret; } +static ssize_t enable_mvdec_info_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", enable_mvdec_info); +} + +static ssize_t enable_mvdec_info_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + enable_mvdec_info = val; + + return count; +} + + static ssize_t store_poweron_clock_level(struct class *class, struct class_attribute *attr, const char *buf, size_t size) @@ -4241,6 +4392,7 @@ static ssize_t show_keep_vdec_mem(struct class *class, return sprintf(buf, "%d\n", keep_vdec_mem); } + #ifdef VDEC_DEBUG_SUPPORT static ssize_t store_debug(struct class *class, struct class_attribute *attr, @@ -4363,6 +4515,79 @@ static ssize_t show_debug(struct class *class, } #endif +static ssize_t store_vdec_vfm_path(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) +{ + char *buf_dup, *ps, *token; + char str[VDEC_MAP_NAME_SIZE] = "\0"; + bool found = false; + int i; + + if (strlen(buf) >= VDEC_MAP_NAME_SIZE) { + pr_info("parameter is overflow\n"); + return -1; + } + + buf_dup = kstrdup(buf, GFP_KERNEL); + ps = buf_dup; + while (1) { + token = strsep(&ps, "\n "); + if (token == NULL) + break; + if (*token == '\0') + continue; + + for (i = 0; strcmp("reserved", vfm_path_node[i]) != 0; i++) { + if (!strncmp (vfm_path_node[i], token, strlen(vfm_path_node[i]))) { + break; + } + } + + if (strcmp("reserved", vfm_path_node[i]) == 0 || + strncmp("help", buf, strlen("help")) == 0) { + if (strncmp("help", buf, strlen("help")) != 0) { + pr_info("warnning! Input parameter is invalid. set failed!\n"); + } + pr_info("\nusage for example: \n"); + pr_info("echo help > /sys/class/vdec/vfm_path \n"); + pr_info("echo disable > /sys/class/vdec/vfm_path \n"); + pr_info("echo amlvideo ppmgr amvideo > /sys/class/vdec/vfm_path \n"); + found = false; + + break; + } else { + strcat(str, vfm_path_node[i]); + strcat(str, " "); + found = true; + } + } + + if (found == true) { + memset(vfm_path, 0, sizeof(vfm_path)); + strncpy(vfm_path, str, strlen(str)); + vfm_path[VDEC_MAP_NAME_SIZE - 1] = '\0'; + pr_info("cfg path success: decoder %s\n", vfm_path); + } + kfree(buf_dup); + + return count; +} + +static ssize_t show_vdec_vfm_path(struct class *class, + struct class_attribute *attr, char *buf) +{ + int len = 0; + int i; + len += sprintf(buf + len, "cfg vfm path: decoder %s\n", vfm_path); + len += sprintf(buf + len, "\nvfm path node list: \n"); + for (i = 0; strcmp("reserved", vfm_path_node[i]) != 0; i++) { + len += sprintf(buf + len, "\t%s \n", vfm_path_node[i]); + } + + return len; +} + /*irq num as same as .dts*/ /* * interrupts = <0 3 1 @@ -4846,6 +5071,8 @@ static struct class_attribute vdec_class_attrs[] = { __ATTR_RO(amrisc_regs), __ATTR_RO(dump_trace), __ATTR_RO(clock_level), + __ATTR(enable_mvdec_info, S_IRUGO | S_IWUSR | S_IWGRP, + enable_mvdec_info_show, enable_mvdec_info_store), __ATTR(poweron_clock_level, S_IRUGO | S_IWUSR | S_IWGRP, show_poweron_clock_level, store_poweron_clock_level), __ATTR(dump_risc_mem, S_IRUGO | S_IWUSR | S_IWGRP, @@ -4868,6 +5095,8 @@ static struct class_attribute vdec_class_attrs[] = { frame_check_show, frame_check_store), #endif __ATTR_RO(dump_fps), + __ATTR(vfm_path, S_IRUGO | S_IWUSR | S_IWGRP, + show_vdec_vfm_path, store_vdec_vfm_path), __ATTR_NULL }; @@ -5073,104 +5302,109 @@ static int __init vdec_mem_setup(struct reserved_mem *rmem) return 0; } -void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug) + +void vdec_set_vframe_comm(struct vdec_s *vdec, char *n) { - if (frame_info_buf_in == NULL) { - pr_info("error,frame_info_buf_in is null\n"); - return; - } - if (frame_info_buf_out == NULL) { - pr_info("error,frame_info_buf_out is null\n"); - return; - } - if (frame_qos_wr >= QOS_FRAME_NUM) - frame_qos_wr = 0; + struct vdec_frames_s *mvfrm = vdec->mvfrm; - if (frame_qos_wr >= QOS_FRAME_NUM || - frame_qos_wr < 0) { - pr_info("error,index :%d is error\n", frame_qos_wr); + if (!mvfrm) return; - } - if (frameinfo_flag == DISABLE_FRAME_INFO) + + mvfrm->comm.vdec_id = vdec->id; + + snprintf(mvfrm->comm.vdec_name, sizeof(mvfrm->comm.vdec_name)-1, + "%s", n); + mvfrm->comm.vdec_type = vdec->type; +} +EXPORT_SYMBOL(vdec_set_vframe_comm); + +void vdec_fill_vdec_frame(struct vdec_s *vdec, struct vframe_qos_s *vframe_qos, + struct vdec_info *vinfo,struct vframe_s *vf, + u32 hw_dec_time) +{ + u32 i; + struct vframe_counter_s *fifo_buf; + struct vdec_frames_s *mvfrm = vdec->mvfrm; + + if (!mvfrm) return; + fifo_buf = mvfrm->fifo_buf; + + /* assume fps==60,mv->wr max value can support system running 828 days, + this is enough for us */ + i = mvfrm->wr & (NUM_FRAME_VDEC-1); //find the slot num in fifo_buf + mvfrm->fifo_buf[i].decode_time_cost = hw_dec_time; + if (vframe_qos) + memcpy(&fifo_buf[i].qos, vframe_qos, sizeof(struct vframe_qos_s)); + if (vinfo) { + memcpy(&fifo_buf[i].frame_width, &vinfo->frame_width, + ((char*)&vinfo->reserved[0] - (char*)&vinfo->frame_width)); + } + if (vf) { + fifo_buf[i].vf_type = vf->type; + fifo_buf[i].signal_type = vf->signal_type; + fifo_buf[i].pts = vf->pts; + fifo_buf[i].pts_us64 = vf->pts_us64; + } + mvfrm->wr++; +} +EXPORT_SYMBOL(vdec_fill_vdec_frame); + +/* In this function,if we use copy_to_user, we may encounter sleep, +which may block the vdec_fill_vdec_frame,this is not acceptable. +So, we should use a tmp buffer(passed by caller) to get the content */ +u32 vdec_get_frame_vdec(struct vdec_s *vdec, struct vframe_counter_s *tmpbuf) +{ + u32 toread = 0; + u32 slot_rd; + struct vframe_counter_s *fifo_buf = NULL; + struct vdec_frames_s *mvfrm = NULL; - if (frameinfo_flag == PRINT_FRAME_INFO) { - pr_info("num %d size %d pts %d\n", - vframe_qos->num, - vframe_qos->size, - vframe_qos->pts); - pr_info("mv min_mv %d avg_mv %d max_mv %d\n", - vframe_qos->min_mv, - vframe_qos->avg_mv, - vframe_qos->max_mv); - pr_info("qp min_qp %d avg_qp %d max_qp %d\n", - vframe_qos->min_qp, - vframe_qos->avg_qp, - vframe_qos->max_qp); - pr_info("skip min_skip %d avg_skip %d max_skip %d\n", - vframe_qos->min_skip, - vframe_qos->avg_skip, - vframe_qos->max_skip); - } - memcpy(&frame_info_buf_in[frame_qos_wr++], - vframe_qos, sizeof(struct vframe_qos_s)); - if (frame_qos_wr >= QOS_FRAME_NUM) - frame_qos_wr = 0; - - /*pr_info("frame_qos_wr:%d\n", frame_qos_wr);*/ - -} -EXPORT_SYMBOL(vdec_fill_frame_info); - -struct vframe_qos_s *vdec_get_qos_info(void) -{ - int write_count = 0; - int qos_wr = frame_qos_wr; - - if (frame_info_buf_in == NULL) { - pr_info("error,frame_info_buf_in is null\n"); - return NULL; - } - if (frame_info_buf_out == NULL) { - pr_info("error,frame_info_buf_out is null\n"); - return NULL; + /* + switch (version) { + case version_1: + f1(); + case version_2: + f2(); + default: + break; } + */ + if (!vdec) + return 0; + mvfrm = vdec->mvfrm; + if (!mvfrm) + return 0; - memset(frame_info_buf_out, 0, - QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); - if (frame_qos_rd > qos_wr) { - write_count = QOS_FRAME_NUM - frame_qos_rd; - if (write_count > 0 && write_count <= QOS_FRAME_NUM) { - memcpy(frame_info_buf_out, &frame_info_buf_in[0], - write_count*sizeof(struct vframe_qos_s)); - if ((write_count + qos_wr) <= QOS_FRAME_NUM) - memcpy(&frame_info_buf_out[write_count], frame_info_buf_in, - qos_wr*sizeof(struct vframe_qos_s)); - else - pr_info("get_qos_info:%d,out of range\n", __LINE__); - } else - pr_info("get_qos_info:%d,out of range\n", __LINE__); - } else if (frame_qos_rd < qos_wr) { - write_count = qos_wr - frame_qos_rd; - if (write_count > 0 && write_count < QOS_FRAME_NUM) - memcpy(frame_info_buf_out, &frame_info_buf_in[frame_qos_rd], - (write_count)*sizeof(struct vframe_qos_s)); - else - pr_info("get_qos_info:%d, out of range\n", __LINE__); + fifo_buf = &mvfrm->fifo_buf[0]; + + toread = mvfrm->wr - mvfrm->rd; + if (toread) { + if (toread >= NUM_FRAME_VDEC - QOS_FRAME_NUM) { + /* round the fifo_buf length happens, give QOS_FRAME_NUM for buffer */ + mvfrm->rd = mvfrm->wr - (NUM_FRAME_VDEC - QOS_FRAME_NUM); + } + + if (toread >= QOS_FRAME_NUM) { + toread = QOS_FRAME_NUM; //by default, we use this num + } + + slot_rd = mvfrm->rd &( NUM_FRAME_VDEC-1); //In this case it equals to x%y + if (slot_rd + toread <= NUM_FRAME_VDEC) { + memcpy(tmpbuf, &fifo_buf[slot_rd], toread*sizeof(struct vframe_counter_s)); + } else { + u32 exeed; + exeed = slot_rd + toread - NUM_FRAME_VDEC; + memcpy(tmpbuf, &fifo_buf[slot_rd], (NUM_FRAME_VDEC - slot_rd)*sizeof(struct vframe_counter_s)); + memcpy(&tmpbuf[NUM_FRAME_VDEC-slot_rd], &fifo_buf[0], exeed*sizeof(struct vframe_counter_s)); + } + + mvfrm->rd += toread; } - /* - pr_info("cnt:%d,size:%d,num:%d,rd:%d,wr:%d\n", - wirte_count, - frame_info_buf_out[0].size, - frame_info_buf_out[0].num, - frame_qos_rd,qos_wr); - */ - frame_qos_rd = qos_wr; - return frame_info_buf_out; + return toread; } -EXPORT_SYMBOL(vdec_get_qos_info); - +EXPORT_SYMBOL(vdec_get_frame_vdec); RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup); /* |