From a1bf1b1b20fd2f7a1f74fe5a52562bc310c6d141 Mon Sep 17 00:00:00 2001 From: "renjiang.han" Date: Tue, 12 Mar 2019 20:11:59 +0800 Subject: [PATCH] amvideo2: add keep last frame [1/1] PD#OTT-2452 Problem: Black screen in the middle of the cut. Solution: add keep last frame. Verify: on U212 Change-Id: Ib24f066e0682c7427024a74d9bf8cc9b8a310d62 Signed-off-by: renjiang.han --- drivers/amlogic/media/video_sink/video.c | 148 ++++++++++++++++++--- drivers/amlogic/media/video_sink/video_keeper.c | 139 ++++++++++++++++++- drivers/amlogic/media/video_sink/video_priv.h | 3 + include/linux/amlogic/media/utils/amstream.h | 8 +- include/linux/amlogic/media/video_sink/video.h | 2 + .../linux/amlogic/media/video_sink/video_keeper.h | 5 + 6 files changed, 282 insertions(+), 23 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 79a0a96..15844da 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -207,7 +207,7 @@ static struct vpp_frame_par_s *curpip_frame_par, *nextpip_frame_par; static struct vpp_frame_par_s pip_frame_parms[2]; static struct vframe_s *cur_pipbuf; static struct vframe_s local_pip; -static int _videopip_set_disable(u32 val); +//int _videopip_set_disable(u32 val); #endif static struct device *amvideo_dev; @@ -952,6 +952,7 @@ static u32 blackout; static u32 blackout = 1; #endif static u32 force_blackout; +static u32 blackout_pip; /* disable video */ @@ -983,6 +984,12 @@ u32 get_video_enabled(void) { return video_enabled; } + +u32 get_videopip_enabled(void) +{ + return video2_enabled; +} + /* show first frame*/ static bool show_first_frame_nosync; bool show_first_picture; @@ -1154,7 +1161,12 @@ void safe_disble_videolayer(void) #endif } - +#ifdef VIDEO_PIP +void safe_disble_videolayer2(void) +{ + DisableVideoLayer2(); +} +#endif /*********************************************************/ #ifdef VIDEO_PIP static inline struct vframe_s *pip_vf_peek(void) @@ -3184,6 +3196,8 @@ static void pip_toggle_frame(struct vframe_s *vf) cur_pipbuf = vf; if (first_picture) pip_frame_ready_to_set = 1; + if (cur_pipbuf != &local_pip) + video_pip_keeper_new_frame_notify(); } static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) @@ -8455,6 +8469,7 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) static void pip_vf_unreg_provider(void) { ulong flags; + int keeped = 0; /* atomic_set(&video_unreg_flag, 1); */ while (atomic_read(&video_inirq_flag) > 0) @@ -8473,11 +8488,25 @@ static void pip_vf_unreg_provider(void) pip_frame_count = 0; spin_unlock_irqrestore(&lock, flags); - disable_videopip = VIDEO_DISABLE_FORNEXT; - DisableVideoLayer2(); + if (blackout_pip | force_blackout) { + safe_disble_videolayer2(); + try_free_keep_videopip(1); + } + + if (cur_pipbuf) + keeped = vf_keep_pip_current_locked(cur_pipbuf, NULL); + + if (keeped < 0) {/*keep failed.*/ + pr_info("videopip keep failed, disable video now!\n"); + safe_disble_videolayer2(); + try_free_keep_videopip(1); + } + + /*disable_videopip = VIDEO_DISABLE_FORNEXT;*/ + /*DisableVideoLayer2();*/ } -static void pip_vf_light_unreg_provider(void) +static void pip_vf_light_unreg_provider(int need_keep_frame) { ulong flags; @@ -8492,6 +8521,11 @@ static void pip_vf_light_unreg_provider(void) cur_pipbuf = &local_pip; } spin_unlock_irqrestore(&lock, flags); + if (need_keep_frame) { + if (cur_pipbuf) { + vf_keep_pip_current_locked(cur_pipbuf, NULL); + } + } } static int pip_receiver_event_fun( @@ -8500,11 +8534,11 @@ static int pip_receiver_event_fun( if (type == VFRAME_EVENT_PROVIDER_UNREG) pip_vf_unreg_provider(); else if (type == VFRAME_EVENT_PROVIDER_RESET) - pip_vf_light_unreg_provider(); + pip_vf_light_unreg_provider(1); else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) - pip_vf_light_unreg_provider(); + pip_vf_light_unreg_provider(0); else if (type == VFRAME_EVENT_PROVIDER_REG) - pip_vf_light_unreg_provider(); + pip_vf_light_unreg_provider(0); return 0; } #endif @@ -8529,6 +8563,19 @@ u32 set_blackout_policy(int policy) } EXPORT_SYMBOL(set_blackout_policy); +u32 get_blackout_pip_policy(void) +{ + return blackout_pip | force_blackout; +} +EXPORT_SYMBOL(get_blackout_pip_policy); + +u32 set_blackout_pip_policy(int policy) +{ + blackout_pip = policy; + return 0; +} +EXPORT_SYMBOL(set_blackout_pip_policy); + u8 is_vpp_postblend(void) { if (READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) & VPP_VD1_POSTBLEND) @@ -9021,27 +9068,28 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) break; case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + put_user(disable_videopip, (u32 __user *)argp); + break; case AMSTREAM_IOC_GET_VIDEO_DISABLE: - if (layer->layer_id == 0) - put_user(disable_video, (u32 __user *)argp); -#ifdef VIDEO_PIP - else if (layer->layer_id == 1) - put_user(disable_videopip, (u32 __user *)argp); -#endif + put_user(disable_video, (u32 __user *)argp); break; case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + { + u32 val; + + if (copy_from_user(&val, argp, sizeof(u32)) == 0) + ret = _videopip_set_disable(val); + else + ret = -EFAULT; + } + break; case AMSTREAM_IOC_SET_VIDEO_DISABLE: { u32 val; if (copy_from_user(&val, argp, sizeof(u32)) == 0) { - if (layer->layer_id == 0) - ret = _video_set_disable(val); -#ifdef VIDEO_PIP - else if (layer->layer_id == 1) - ret = _videopip_set_disable(val); -#endif + ret = _video_set_disable(val); } else ret = -EFAULT; } @@ -9168,6 +9216,24 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; + case AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY: + if (copy_to_user(argp, &blackout_pip, sizeof(u32)) != 0) + ret = -EFAULT; + break; + + case AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY:{ + u32 mode; + + if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { + if (mode > 2) + ret = -EINVAL; + else + blackout_pip = mode; + } else + ret = -EFAULT; + } + break; + case AMSTREAM_IOC_CLEAR_VBUF:{ unsigned long flags; while (atomic_read(&video_inirq_flag) > 0 || @@ -9184,6 +9250,19 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) safe_disble_videolayer(); break; + case AMSTREAM_IOC_CLEAR_PIP_VBUF:{ + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + cur_pipbuf = NULL; + spin_unlock_irqrestore(&lock, flags); + } + break; + + case AMSTREAM_IOC_CLEAR_VIDEOPIP: + safe_disble_videolayer2(); + break; + case AMSTREAM_IOC_SET_FREERUN_MODE: if (arg > FREERUN_DUR) ret = -EFAULT; @@ -9460,6 +9539,8 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT: case AMSTREAM_IOC_CLEAR_VBUF: case AMSTREAM_IOC_CLEAR_VIDEO: + case AMSTREAM_IOC_CLEAR_PIP_VBUF: + case AMSTREAM_IOC_CLEAR_VIDEOPIP: case AMSTREAM_IOC_SET_FREERUN_MODE: case AMSTREAM_IOC_DISABLE_SLOW_SYNC: case AMSTREAM_IOC_SET_3D_TYPE: @@ -11389,7 +11470,7 @@ static ssize_t video_zorder_store( } #ifdef VIDEO_PIP -static int _videopip_set_disable(u32 val) +int _videopip_set_disable(u32 val) { if (val > VIDEO_DISABLE_FORNEXT) return -EINVAL; @@ -11402,6 +11483,7 @@ static int _videopip_set_disable(u32 val) if ((disable_videopip == VIDEO_DISABLE_FORNEXT) && cur_pipbuf && (cur_pipbuf != &local_pip)) pip_property_changed = 1; + try_free_keep_videopip(0); } else { if (cur_pipbuf && (cur_pipbuf != &local_pip)) EnableVideoLayer2(); @@ -11410,6 +11492,26 @@ static int _videopip_set_disable(u32 val) return 0; } +static ssize_t videopip_blackout_policy_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", blackout_pip); +} + +static ssize_t videopip_blackout_policy_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &blackout_pip); + if (r < 0) + return -EINVAL; + + return count; +} + static ssize_t videopip_axis_show( struct class *cla, struct class_attribute *attr, @@ -11759,6 +11861,10 @@ static struct class_attribute amvideo_class_attrs[] = { 0664, video_blackout_policy_show, video_blackout_policy_store), + __ATTR(blackout_pip_policy, + 0664, + videopip_blackout_policy_show, + videopip_blackout_policy_store), __ATTR(video_seek_flag, 0664, video_seek_flag_show, diff --git a/drivers/amlogic/media/video_sink/video_keeper.c b/drivers/amlogic/media/video_sink/video_keeper.c index ad8b02b..1c85320 100644 --- a/drivers/amlogic/media/video_sink/video_keeper.c +++ b/drivers/amlogic/media/video_sink/video_keeper.c @@ -64,10 +64,15 @@ static DEFINE_MUTEX(video_keeper_mutex); static unsigned long keep_y_addr, keep_u_addr, keep_v_addr; static int keep_video_on; +static int keep_video_pip_on; static int keep_id; static int keep_head_id; +static int keep_pip_id; +static int keep_pip_head_id; static int keep_el_id; static int keep_el_head_id; +static int keep_pip_el_id; +static int keep_pip_el_head_id; #define Y_BUFFER_SIZE 0x400000 /* for 1920*1088 */ #define U_BUFFER_SIZE 0x100000 /* compatible with NV21 */ @@ -722,6 +727,28 @@ void try_free_keep_video(int flags) EXPORT_SYMBOL(try_free_keep_video); #endif +void try_free_keep_videopip(int flags) +{ + int free_scatter_keeper = flags & 0x1; + + if (keep_video_pip_on || free_scatter_keeper) { + /*pr_info("disbled keep video before free keep buffer.\n");*/ + keep_video_pip_on = 0; + if (!get_videopip_enabled()) { + /*if not disable video,changed to 2 for */ + pr_info("disbled videopip for next before free keep buffer!\n"); + _videopip_set_disable(VIDEO_DISABLE_FORNEXT); + } else if (get_videopip_enabled()) { + safe_disble_videolayer2(); + } + } + mutex_lock(&video_keeper_mutex); + video_pip_keeper_new_frame_notify(); + free_alloced_keep_buffer(); + mutex_unlock(&video_keeper_mutex); +} +EXPORT_SYMBOL(try_free_keep_videopip); + static void video_keeper_update_keeper_mem( void *mem_handle, int type, int *id) @@ -747,7 +774,6 @@ static int video_keeper_frame_keep_locked( struct vframe_s *cur_dispbuf_el) { int type = MEM_TYPE_CODEC_MM; - if (cur_dispbuf->type & VIDTYPE_SCATTER) type = MEM_TYPE_CODEC_MM_SCATTER; video_keeper_update_keeper_mem( @@ -775,6 +801,41 @@ static int video_keeper_frame_keep_locked( return (keep_id + keep_head_id) > 0; } +static int video_pip_keeper_frame_keep_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + int type = MEM_TYPE_CODEC_MM; + + if (cur_dispbuf) { + if (cur_dispbuf->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + video_keeper_update_keeper_mem( + cur_dispbuf->mem_handle, + type, + &keep_pip_id); + video_keeper_update_keeper_mem( + cur_dispbuf->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_pip_head_id); + } + if (cur_dispbuf_el) { + if (cur_dispbuf_el->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + else + type = MEM_TYPE_CODEC_MM; + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_handle, + type, + &keep_pip_el_id); + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_pip_el_head_id); + } + return (keep_pip_id + keep_pip_head_id) > 0; +} + /* * call in irq. *don't used mutex @@ -795,6 +856,7 @@ void video_keeper_new_frame_notify(void) codec_mm_keeper_unmask_keeper(keep_head_id, 120); keep_head_id = -1; } + if (keep_el_id > 0) { /*wait 80 ms for vsync post.*/ codec_mm_keeper_unmask_keeper(keep_el_id, 120); @@ -808,6 +870,36 @@ void video_keeper_new_frame_notify(void) return; } +void video_pip_keeper_new_frame_notify(void) +{ + if (keep_video_pip_on) { + pr_info("new frame show, pip free keeper\n"); + keep_video_pip_on = 0; + } + if (keep_pip_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_id, 120); + keep_pip_id = -1; + } + if (keep_pip_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_head_id, 120); + keep_pip_head_id = -1; + } + if (keep_pip_el_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_el_id, 120); + keep_pip_el_id = -1; + } + if (keep_pip_el_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_el_head_id, 120); + keep_pip_el_head_id = -1; + } + +} + + static unsigned int vf_keep_current_locked( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf_el) @@ -1043,6 +1135,51 @@ static unsigned int vf_keep_current_locked( return 1; } + +unsigned int vf_keep_pip_current_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + //u32 cur_index; + //u32 y_index, u_index, v_index; + //struct canvas_s cs0, cs1, cs2, cd; + int ret; + + if (!cur_dispbuf) { + pr_info("keep pip exit without cur_dispbuf\n"); + return 0; + } + + if (get_video_debug_flags() & + DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { + pr_info("flag: keep pip exit is skip current\n"); + return 0; + } + +#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE + ext_frame_capture_poll(1); /*pull if have capture end frame */ +#endif + + if (get_blackout_pip_policy()) { + pr_info("policy: keep exit is skip current\n"); + return 0; + } + + ret = video_pip_keeper_frame_keep_locked( + cur_dispbuf, + cur_dispbuf_el); + + if (ret) { + /*keeped ok with codec keeper!*/ + pr_info("keep pip buffer on!\n"); + keep_video_pip_on = 1; + return 1; + } + + keep_video_pip_on = 0; + return 0; +} + unsigned int vf_keep_current( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf2) diff --git a/drivers/amlogic/media/video_sink/video_priv.h b/drivers/amlogic/media/video_sink/video_priv.h index f540771..34e19ee 100644 --- a/drivers/amlogic/media/video_sink/video_priv.h +++ b/drivers/amlogic/media/video_sink/video_priv.h @@ -135,6 +135,7 @@ struct blend_setting_s { }; void safe_disble_videolayer(void); +void safe_disble_videolayer2(void); void update_cur_dispbuf(void *buf); /*for video related files only.*/ @@ -145,7 +146,9 @@ struct vframe_s *get_cur_dispbuf(void); int get_video_debug_flags(void); int _video_set_disable(u32 val); +int _videopip_set_disable(u32 val); u32 get_video_enabled(void); +u32 get_videopip_enabled(void); struct device *get_video_device(void); #ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index 3366382..e79e5b2 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -90,6 +90,9 @@ #define AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT _IOR((_A_M), 0x21, int) #define AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT _IOW((_A_M), 0x22, int) #define AMSTREAM_IOC_GET_VIDEO_LAYER1_ON _IOR((_A_M), 0x23, int) +/*video pip IOCTL command list*/ +#define AMSTREAM_IOC_CLEAR_VIDEOPIP _IOW((_A_M), 0x24, int) +#define AMSTREAM_IOC_CLEAR_PIP_VBUF _IO((_A_M), 0x25) #define AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT _IOR((_A_M), 0x2b, int) #define AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT _IOW((_A_M), 0x2c, int) @@ -156,8 +159,11 @@ * 0x5c, struct userdata_buf_state_t) */ - #define AMSTREAM_IOC_VF_STATUS _IOR((_A_M), 0x60, int) + +#define AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY _IOR((_A_M), 0x62, int) +#define AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY _IOW((_A_M), 0x63, int) + #define AMSTREAM_IOC_CLEAR_VBUF _IO((_A_M), 0x80) #define AMSTREAM_IOC_APTS_LOOKUP _IOR((_A_M), 0x81, int) diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index 04cb35b..6004ec2 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -241,6 +241,8 @@ static inline int amvideo_notifier_call_chain(unsigned long val, void *v) int query_video_status(int type, int *value); u32 set_blackout_policy(int policy); u32 get_blackout_policy(void); +u32 set_blackout_pip_policy(int policy); +u32 get_blackout_pip_policy(void); void set_video_angle(u32 s_value); u32 get_video_angle(void); extern unsigned int DI_POST_REG_RD(unsigned int addr); diff --git a/include/linux/amlogic/media/video_sink/video_keeper.h b/include/linux/amlogic/media/video_sink/video_keeper.h index 1594690..8794407 100644 --- a/include/linux/amlogic/media/video_sink/video_keeper.h +++ b/include/linux/amlogic/media/video_sink/video_keeper.h @@ -21,12 +21,17 @@ #include void video_keeper_new_frame_notify(void); +void video_pip_keeper_new_frame_notify(void); void try_free_keep_video(int flags); +void try_free_keep_videopip(int flags); int __init video_keeper_init(void); void __exit video_keeper_exit(void); unsigned int vf_keep_current( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf2); +unsigned int vf_keep_pip_current_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el); #endif -- 2.7.4