| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| */ |
| |
| #include <linux/version.h> |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/spinlock.h> |
| #include <linux/interrupt.h> |
| #include <linux/fs.h> |
| #include <linux/string.h> |
| #include <linux/io.h> |
| #include <linux/mm.h> |
| #include <linux/amlogic/major.h> |
| #include <linux/err.h> |
| #include <linux/mutex.h> |
| #include <linux/platform_device.h> |
| #include <linux/ctype.h> |
| #include <linux/of.h> |
| #include <linux/of_fdt.h> |
| #include <linux/amlogic/media/vfm/vframe.h> |
| #include <linux/amlogic/media/vfm/vframe_provider.h> |
| #include <linux/amlogic/media/vfm/vframe_receiver.h> |
| #include <linux/amlogic/media/utils/amstream.h> |
| #include <linux/amlogic/media/vout/vout_notify.h> |
| #include <linux/amlogic/media/video_sink/video_signal_notify.h> |
| #include <linux/sched.h> |
| #include <linux/sched/clock.h> |
| #include <linux/slab.h> |
| #include <linux/poll.h> |
| #include <linux/clk.h> |
| #include <linux/debugfs.h> |
| #include <linux/amlogic/media/canvas/canvas.h> |
| #include <linux/amlogic/media/canvas/canvas_mgr.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/dma-map-ops.h> |
| #include <linux/sched.h> |
| #include <asm/div64.h> |
| |
| #include <linux/amlogic/media/video_sink/video_keeper.h> |
| #include <linux/amlogic/media/video_sink/video.h> |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| #include <linux/amlogic/media/amdolbyvision/dolby_vision.h> |
| #endif |
| #include <linux/amlogic/media/utils/amlog.h> |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| #include "../common/rdma/rdma.h" |
| #endif |
| #include "../common/vfm/vfm.h" |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRAME_SYNC |
| #include <linux/amlogic/media/frame_sync/ptsserv.h> |
| #include <linux/amlogic/media/frame_sync/timestamp.h> |
| #include <linux/amlogic/media/frame_sync/tsync.h> |
| #endif |
| #define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VIDEO |
| #include <trace/events/meson_atrace.h> |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| #include <linux/amlogic/media/di/di.h> |
| #include <linux/amlogic/media/di/di_interface.h> |
| #endif |
| #include "vpp_pq.h" |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| #include <linux/amlogic/media/amvecm/amvecm.h> |
| #endif |
| #include <linux/amlogic/media/utils/vdec_reg.h> |
| #ifdef CONFIG_AMLOGIC_MEDIA_MSYNC |
| #include <uapi/amlogic/msync.h> |
| #endif |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| #include <linux/amlogic/media/frc/frc_common.h> |
| #endif |
| #include <linux/amlogic/media/video_processor/video_pp_common.h> |
| #include "video_common.h" |
| #include "video_hw.h" |
| #include "video_hw_s5.h" |
| #include "vpp_post_s5.h" |
| #include "video_receiver.h" |
| #include "video_priv.h" |
| #include "video_reg.h" |
| #include "video_func.h" |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| #include <linux/amlogic/aml_iotrace.h> |
| #endif |
| |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| static unsigned int vpp_new_frame; |
| #endif |
| #endif |
| /* local var */ |
| static u32 blend_conflict_cnt; |
| static u32 stop_update; |
| static u32 stop_force_dmc; |
| |
| /* 3d related */ |
| static unsigned int last_process_3d_type; |
| static unsigned int dmc_adjust = 1; |
| |
| #ifndef CONFIG_AMLOGIC_REMOVE_OLD |
| static u32 dmc_config_state; |
| static u32 last_toggle_count; |
| static u32 toggle_same_count; |
| #endif |
| |
| /* dovi related */ |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| /*amvideo, videopip dv provider*/ |
| static char dv_provider[2][32] = {"dvbldec", "dvbldec2"}; |
| #endif |
| |
| atomic_t axis_changed = ATOMIC_INIT(0); |
| |
| /* display canvas */ |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| static int enable_rdma_log_count; |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| static bool pre_vsync_rdma_enable_pre; |
| #endif |
| #endif |
| /* 0: amvideo, 1: pip */ |
| /* rdma buf + dispbuf + to_put_buf */ |
| static u32 post_canvas; |
| static bool last_mvc_status; |
| static u32 pre_vsync_count; |
| #define MAX_VIDEO_FAKE 6 |
| struct vd_func_s vd_fake_func[MAX_VIDEO_FAKE]; |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| static bool first_irq = true; |
| #endif |
| static struct cur_line_info_t g_cur_line_info[2]; |
| static u8 new_frame_mask; |
| static bool need_force_black; |
| static u32 always_new_vf_cnt; |
| bool rdma_enable_pre; |
| |
| u32 frc_mute_frames = 3; |
| u32 frc_muted_frames; |
| MODULE_PARM_DESC(frc_mute_frames, "\n frc_mute_frames\n"); |
| module_param(frc_mute_frames, uint, 0664); |
| |
| bool get_video_reverse(void) |
| { |
| return reverse == 1 ? true : false; |
| } |
| EXPORT_SYMBOL(get_video_reverse); |
| |
| bool is_di_hf_y_reverse(void) |
| { |
| if (glayer_info[0].reverse || glayer_info[0].mirror == 2) |
| return cur_dev->di_hf_y_reverse; |
| else |
| return false; |
| } |
| EXPORT_SYMBOL(is_di_hf_y_reverse); |
| |
| void get_video_axis_offset(s32 *x_offset, s32 *y_offset) |
| { |
| s32 x_end, y_end; |
| struct disp_info_s *layer = &glayer_info[0]; |
| const struct vinfo_s *info = get_current_vinfo(); |
| int orientation = 0; |
| |
| #ifdef TV_REVERSE |
| orientation = screen_orientation(); |
| #endif |
| |
| if (!info) { |
| *x_offset = 0; |
| *y_offset = 0; |
| return; |
| } |
| |
| /* reverse and mirror case */ |
| if (orientation == HV_MIRROR) { |
| /* reverse x/y start */ |
| x_end = layer->layer_left + layer->layer_width - 1; |
| *x_offset = info->width - x_end - 1; |
| y_end = layer->layer_top + layer->layer_height - 1; |
| *y_offset = info->height - y_end - 1; |
| } else if (orientation == H_MIRROR) { |
| /* horizontal mirror */ |
| x_end = layer->layer_left + layer->layer_width - 1; |
| *x_offset = info->width - x_end - 1; |
| *y_offset = layer->layer_top; |
| } else if (orientation == V_MIRROR) { |
| /* vertical mirror */ |
| *x_offset = layer->layer_left; |
| y_end = layer->layer_top + layer->layer_height - 1; |
| *y_offset = info->height - y_end - 1; |
| } else { |
| *x_offset = layer->layer_left; |
| *y_offset = layer->layer_top; |
| } |
| } |
| |
| /*********************************************************/ |
| |
| static inline struct vframe_s *pip2_vf_peek(void) |
| { |
| struct vframe_s *cur_pipbuf2 = NULL; |
| u8 path_index = 2; |
| |
| cur_pipbuf2 = cur_dispbuf[path_index]; |
| if (pip2_loop && cur_dispbuf[0] != cur_pipbuf2) |
| return cur_dispbuf[0]; |
| return vf_peek(RECEIVERPIP2_NAME); |
| } |
| |
| static inline struct vframe_s *pip2_vf_get(void) |
| { |
| struct vframe_s *vf = NULL; |
| struct vframe_s *cur_pipbuf2 = NULL; |
| u8 path_index = 2; |
| |
| cur_pipbuf2 = cur_dispbuf[path_index]; |
| if (pip2_loop && cur_dispbuf[0] != cur_pipbuf2) |
| return cur_dispbuf[0]; |
| |
| vf = vf_get(RECEIVERPIP2_NAME); |
| |
| if (vf) { |
| get_count_pip[path_index]++; |
| if (vf->type & VIDTYPE_V4L_EOS) { |
| vf_put(vf, RECEIVERPIP2_NAME); |
| return NULL; |
| } |
| /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; */ |
| atomic_set(&vf->use_cnt_pip, 1); |
| /* atomic_set(&vf->use_cnt_pip2, 1); */ |
| } |
| return vf; |
| } |
| |
| static inline int pip2_vf_put(struct vframe_s *vf) |
| { |
| struct vframe_provider_s *vfp = vf_get_provider(RECEIVERPIP2_NAME); |
| |
| if (pip2_loop) |
| return 0; |
| |
| /* if (vfp && vf && atomic_dec_and_test(&vf->use_cnt_pip2)) { */ |
| if (vfp && vf && atomic_dec_and_test(&vf->use_cnt_pip)) { |
| if (vf_put(vf, RECEIVERPIP2_NAME) < 0) |
| return -EFAULT; |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if ((glayer_info[0].display_path_id |
| == VFM_PATH_PIP2) && |
| is_amdv_enable()) |
| amdv_vf_put(vf); |
| #endif |
| /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; */ |
| } else { |
| if (vf) |
| return -EINVAL; |
| } |
| return 0; |
| } |
| |
| static inline struct vframe_s *pip_vf_peek(void) |
| { |
| struct vframe_s *vf = NULL; |
| struct vframe_s *cur_pipbuf = NULL; |
| u8 path_index = 1; |
| |
| cur_pipbuf = cur_dispbuf[path_index]; |
| if (pip_loop && cur_dispbuf[0] != cur_pipbuf) |
| return cur_dispbuf[0]; |
| vf = vf_peek(RECEIVERPIP_NAME); |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| /*tunnel mode, add dv_inst to vf*/ |
| if (vf && dv_inst_pip >= 0) |
| vf->src_fmt.dv_id = dv_inst_pip; |
| #endif |
| return vf; |
| } |
| |
| static inline struct vframe_s *pip_vf_get(void) |
| { |
| struct vframe_s *vf = NULL; |
| struct vframe_s *cur_pipbuf = NULL; |
| u8 path_index = 1; |
| |
| cur_pipbuf = cur_dispbuf[path_index]; |
| if (pip_loop && cur_dispbuf[0] != cur_pipbuf) |
| return cur_dispbuf[0]; |
| |
| vf = vf_get(RECEIVERPIP_NAME); |
| |
| if (vf) { |
| get_count_pip[path_index]++; |
| if (vf->type & VIDTYPE_V4L_EOS) { |
| vf_put(vf, RECEIVERPIP_NAME); |
| return NULL; |
| } |
| /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; */ |
| atomic_set(&vf->use_cnt_pip, 1); |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| /*tunnel mode, add dv_inst to vf*/ |
| if (dv_inst_pip >= 0) |
| vf->src_fmt.dv_id = dv_inst_pip; |
| #endif |
| } |
| return vf; |
| } |
| |
| static inline int pip_vf_put(struct vframe_s *vf) |
| { |
| struct vframe_provider_s *vfp = vf_get_provider(RECEIVERPIP_NAME); |
| |
| if (pip_loop) |
| return 0; |
| |
| if (vfp && vf && atomic_dec_and_test(&vf->use_cnt_pip)) { |
| if (vf_put(vf, RECEIVERPIP_NAME) < 0) |
| return -EFAULT; |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if ((glayer_info[0].display_path_id |
| == VFM_PATH_PIP || is_multi_dv_mode()) && |
| is_amdv_enable()) |
| amdv_vf_put(vf); |
| #endif |
| /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; */ |
| } else { |
| if (vf) |
| return -EINVAL; |
| } |
| return 0; |
| } |
| |
| static inline struct vframe_s *video_vf_peek(u8 path_index) |
| { |
| struct vframe_s *vf = NULL; |
| |
| switch (path_index) { |
| case 0: |
| vf = amvideo_vf_peek(); |
| break; |
| case 1: |
| vf = pip_vf_peek(); |
| break; |
| case 2: |
| vf = pip2_vf_peek(); |
| break; |
| default: |
| break; |
| } |
| return vf; |
| } |
| |
| static inline struct vframe_s *video_vf_get(u8 path_index) |
| { |
| struct vframe_s *vf = NULL; |
| |
| switch (path_index) { |
| case 0: |
| vf = amvideo_vf_get(); |
| break; |
| case 1: |
| vf = pip_vf_get(); |
| break; |
| case 2: |
| vf = pip2_vf_get(); |
| break; |
| default: |
| break; |
| } |
| return vf; |
| } |
| |
| static inline int video_vf_put(u8 path_index, struct vframe_s *vf) |
| { |
| int ret = -1; |
| |
| switch (path_index) { |
| case 0: |
| ret = amvideo_vf_put(vf); |
| break; |
| case 1: |
| ret = pip_vf_put(vf); |
| break; |
| case 2: |
| ret = pip2_vf_put(vf); |
| break; |
| default: |
| break; |
| } |
| return ret; |
| } |
| |
| bool check_dispbuf(u8 path_index, struct vframe_s *vf, bool is_put_err) |
| { |
| int i; |
| bool done = false; |
| |
| if (!vf) |
| return true; |
| for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) { |
| if (!is_put_err || |
| (is_put_err && IS_DI_POSTWRTIE(vf->type))) { |
| if (!dispbuf_to_put[path_index][i]) { |
| dispbuf_to_put[path_index][i] = vf; |
| dispbuf_to_put_num[path_index]++; |
| done = true; |
| break; |
| } |
| } |
| } |
| return done; |
| } |
| |
| static struct vframe_s *pipx_toggle_frame(u8 path_index, struct vframe_s *vf) |
| { |
| u32 first_picture = 0; |
| u8 i = path_index; |
| |
| if (!vf || path_index >= MAX_VD_LAYER) |
| return NULL; |
| |
| if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) |
| pr_info("%s pip%d (%p)\n", __func__, path_index - 1, vf); |
| |
| if (vf->width == 0 || vf->height == 0) { |
| amlog_level(LOG_LEVEL_ERROR, |
| "Video: invalid frame dimension\n"); |
| return vf; |
| } |
| if (cur_dispbuf[i] && cur_dispbuf[i] != |
| &vf_local[i] && cur_dispbuf[i] != vf) { |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| int j = 0; |
| |
| if (is_vsync_rdma_enable()) { |
| if (cur_rdma_buf[i] == cur_dispbuf[i]) { |
| if (!check_dispbuf(i, cur_dispbuf[i], false)) { |
| if (video_vf_put(i, cur_dispbuf[i]) < 0) |
| pr_info("put err, line: %d\n", |
| __LINE__); |
| } |
| } else { |
| if (video_vf_put(i, cur_dispbuf[i]) < 0) { |
| if (!check_dispbuf(i, cur_dispbuf[i], true)) |
| pr_info("put err,pip%d full\n", i - 1); |
| } |
| } |
| } else { |
| for (j = 0; j < dispbuf_to_put_num[i]; j++) { |
| if (dispbuf_to_put[i][j]) { |
| if (!video_vf_put(i, dispbuf_to_put[i][j])) { |
| dispbuf_to_put[i][j] = NULL; |
| dispbuf_to_put_num[i]--; |
| } |
| } |
| } |
| if (video_vf_put(i, cur_dispbuf[i]) < 0) |
| check_dispbuf(i, cur_dispbuf[i], true); |
| } |
| #else |
| if (video_vf_put(i, cur_dispbuf[i]) < 0) |
| check_dispbuf(i, cur_dispbuf[i], true); |
| #endif |
| pip_frame_count[i]++; |
| if (pip_frame_count[i] == 1) |
| first_picture = 1; |
| } else if (!cur_dispbuf[i] || (cur_dispbuf[i] == &vf_local[i])) |
| first_picture = 1; |
| |
| if (cur_dispbuf[i] != vf) |
| vf->type_backup = vf->type; |
| |
| if (first_picture && (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME)) |
| pr_info("%s pip%d (%p)\n", __func__, i - 1, vf); |
| cur_dispbuf[i] = vf; |
| return cur_dispbuf[i]; |
| } |
| |
| bool tvin_vf_is_keeped(struct vframe_s *vf) |
| { |
| struct vframe_s *src_vf; |
| |
| if (!vf) |
| return false; |
| |
| if (vf->source_type != VFRAME_SOURCE_TYPE_HDMI && |
| vf->source_type != VFRAME_SOURCE_TYPE_CVBS && |
| vf->source_type != VFRAME_SOURCE_TYPE_TUNER) |
| return false; |
| |
| if (!(vf->flag & VFRAME_FLAG_VIDEO_COMPOSER_BYPASS)) |
| return false; |
| |
| if (!vf->vc_private) |
| return false; |
| |
| src_vf = vf->vc_private->src_vf; |
| if (!src_vf) |
| return false; |
| |
| if (src_vf->flag & VFRAME_FLAG_KEEPED) |
| return true; |
| |
| return false; |
| } |
| |
| /* for sdr/hdr/single dv switch with dual dv */ |
| u32 last_el_status; |
| bool has_enhanced_layer(struct vframe_s *vf) |
| { |
| struct provider_aux_req_s req; |
| enum vframe_signal_fmt_e fmt; |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (is_amdv_el_disable() && |
| !for_amdv_certification()) |
| return 0; |
| #endif |
| if (!vf) |
| return 0; |
| if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) |
| return 0; |
| if (!is_amdv_on()) |
| return 0; |
| |
| fmt = get_vframe_src_fmt(vf); |
| /* valid src_fmt = DOVI or invalid src_fmt will check dual layer */ |
| /* otherwise, it certainly is a non-dv vframe */ |
| if (fmt != VFRAME_SIGNAL_FMT_DOVI && |
| fmt != VFRAME_SIGNAL_FMT_INVALID) |
| return 0; |
| |
| req.vf = vf; |
| req.bot_flag = 0; |
| req.aux_buf = NULL; |
| req.aux_size = 0; |
| req.dv_enhance_exist = 0; |
| vf_notify_provider_by_name |
| ("dvbldec", |
| VFRAME_EVENT_RECEIVER_GET_AUX_DATA, |
| (void *)&req); |
| return req.dv_enhance_exist; |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| bool dvel_status; |
| int dolby_vision_need_wait(u8 path_index) |
| { |
| struct vframe_s *vf; |
| int ret = 0; |
| |
| if (!is_amdv_enable()) |
| return 0; |
| |
| vf = video_vf_peek(path_index); |
| if (!vf) { |
| return 1; |
| } else { |
| ret = amdv_wait_metadata(vf, VD1_PATH); |
| if (ret > 0) |
| return ret; |
| } |
| return 0; |
| } |
| |
| int dvel_swap_frame(struct vframe_s *vf) |
| { |
| int ret = 0; |
| struct video_layer_s *layer = NULL; |
| struct disp_info_s *layer_info = NULL; |
| |
| /* use bl layer info */ |
| layer = &vd_layer[0]; |
| layer_info = &glayer_info[0]; |
| |
| if (!is_amdv_enable()) { |
| if (dvel_status) { |
| //safe_switch_videolayer(1, false, true); |
| dvel_status = false; |
| need_disable_vd[1] = true; |
| } |
| } else if (vf) { |
| /* enable the vd2 when the first el vframe coming */ |
| u32 new_dvel_w = (vf->type |
| & VIDTYPE_COMPRESS) ? |
| vf->compWidth : |
| vf->width; |
| |
| /* check if el available first */ |
| if (!dvel_status) { |
| dvel_changed = true; |
| dvel_size = new_dvel_w; |
| need_disable_vd[1] = false; |
| safe_switch_videolayer(1, true, true); |
| } |
| /* check the el size */ |
| if (dvel_size != new_dvel_w) |
| dvel_changed = true; |
| ret = set_layer_display_canvas |
| (layer, vf, layer->cur_frame_par, |
| layer_info, __LINE__); |
| dvel_status = true; |
| } else if (dvel_status) { |
| dvel_changed = true; |
| dvel_status = false; |
| dvel_size = 0; |
| need_disable_vd[1] = true; |
| } |
| return ret; |
| } |
| |
| static void amdolby_vision_proc |
| (struct video_layer_s *layer_1, |
| struct vpp_frame_par_s *cur_frame_par_1, |
| struct video_layer_s *layer_2, |
| struct vpp_frame_par_s *cur_frame_par_2) |
| { |
| static struct vframe_s *cur_dv_vf_1;/*vd1*/ |
| static u32 cur_frame_size_1;/*vd1*/ |
| struct vframe_s *disp_vf_1 = NULL;/*vd1*/ |
| static struct vframe_s *cur_dv_vf_2;/*vd2*/ |
| static u32 cur_frame_size_2;/*vd2*/ |
| struct vframe_s *disp_vf_2 = NULL;/*vd2*/ |
| u8 toggle_mode_1 = 0; |
| u8 toggle_mode_2 = 0; |
| u8 toggle_mode = 0; |
| |
| if (is_amdv_enable()) { |
| u32 frame_size_1 = 0, h_size, v_size; |
| u32 frame_size_2 = 0; |
| u8 pps_state = 0; /* pps no change */ |
| |
| /* TODO: check if need */ |
| #ifdef OLD_DV_FLOW |
| /* force toggle when keeping frame after playing */ |
| if (is_local_vf(layer_1->dispbuf) && |
| !layer_1->new_frame && |
| is_amdv_video_on() && |
| get_video_enabled(0)) { |
| if (!amdv_parse_metadata |
| (layer_1->dispbuf, VD1_PATH, 2, false, false)) |
| amdv_set_toggle_flag(1); |
| } |
| /* force toggle when keeping frame after playing */ |
| if (layer_2) { |
| if (is_local_vf(layer_2->dispbuf) && |
| !layer_2->new_frame && |
| is_amdv_video_on() && |
| get_video_enabled(0)) { |
| if (!amdv_parse_metadata |
| (layer_2->dispbuf, VD2_PATH, 2, false, false)) |
| amdv_set_toggle_flag(1); |
| } |
| } |
| #endif |
| if (layer_1->new_frame) |
| toggle_mode_1 = 1; /* new frame */ |
| else if (!layer_1->dispbuf || |
| is_local_vf(layer_1->dispbuf)) |
| toggle_mode_1 = 2; /* keep frame */ |
| else |
| toggle_mode_1 = 0; /* pasue frame */ |
| |
| if (layer_2 && layer_2->new_frame) |
| toggle_mode_2 = 1; /* new frame */ |
| else if (layer_2 && (!layer_2->dispbuf || |
| is_local_vf(layer_2->dispbuf))) |
| toggle_mode_2 = 2; /* keep frame */ |
| else |
| toggle_mode_2 = 0; /* pasue frame */ |
| |
| /* vd1 toggle_mode priority is high than vd2*/ |
| toggle_mode = toggle_mode_1 ? toggle_mode_1 : toggle_mode_2; |
| |
| /*************get vd1 disp_vf and frame_size************/ |
| |
| if (layer_1->switch_vf && layer_1->vf_ext) |
| disp_vf_1 = layer_1->vf_ext; |
| else |
| disp_vf_1 = layer_1->dispbuf; |
| |
| if (cur_frame_par_1) { |
| if (layer_1->new_vpp_setting) { |
| struct vppfilter_mode_s *vpp_filter = |
| &cur_frame_par_1->vpp_filter; |
| if (vpp_filter->vpp_hsc_start_phase_step == |
| 0x1000000 && |
| vpp_filter->vpp_vsc_start_phase_step == |
| 0x1000000 && |
| vpp_filter->vpp_hsc_start_phase_step == |
| vpp_filter->vpp_hf_start_phase_step && |
| !vpp_filter->vpp_pre_vsc_en && |
| !vpp_filter->vpp_pre_hsc_en && |
| !cur_frame_par_1->supsc0_enable && |
| !cur_frame_par_1->supsc1_enable && |
| layer_1->bypass_pps) |
| pps_state = 2; /* pps disable */ |
| else |
| pps_state = 1; /* pps enable */ |
| } |
| if (cur_frame_par_1->VPP_hd_start_lines_ |
| >= cur_frame_par_1->VPP_hd_end_lines_) |
| h_size = 0; |
| else |
| h_size = cur_frame_par_1->VPP_hd_end_lines_ |
| - cur_frame_par_1->VPP_hd_start_lines_ + 1; |
| h_size /= (cur_frame_par_1->hscale_skip_count + 1); |
| if (cur_frame_par_1->VPP_vd_start_lines_ |
| >= cur_frame_par_1->VPP_vd_end_lines_) |
| v_size = 0; |
| else |
| v_size = cur_frame_par_1->VPP_vd_end_lines_ |
| - cur_frame_par_1->VPP_vd_start_lines_ + 1; |
| v_size /= |
| (cur_frame_par_1->vscale_skip_count + 1); |
| frame_size_1 = (h_size << 16) | v_size; |
| } else if (disp_vf_1) { |
| h_size = (disp_vf_1->type & VIDTYPE_COMPRESS) ? |
| disp_vf_1->compWidth : disp_vf_1->width; |
| v_size = (disp_vf_1->type & VIDTYPE_COMPRESS) ? |
| disp_vf_1->compHeight : disp_vf_1->height; |
| frame_size_1 = (h_size << 16) | v_size; |
| } |
| |
| /* trigger dv process once when stop playing */ |
| /* because disp_vf is not sync with video off */ |
| if (cur_dv_vf_1 && !disp_vf_1) |
| amdv_set_toggle_flag(1); |
| |
| cur_dv_vf_1 = disp_vf_1; |
| |
| if (cur_frame_size_1 != frame_size_1) { |
| cur_frame_size_1 = frame_size_1; |
| amdv_set_toggle_flag(1); |
| } |
| /**************************************************/ |
| |
| /*************get vd2 disp_vf and frame_size************/ |
| if (layer_2 && cur_frame_par_2) { |
| if (layer_2->switch_vf && layer_2->vf_ext) |
| disp_vf_2 = layer_2->vf_ext; |
| else |
| disp_vf_2 = layer_2->dispbuf; |
| |
| if (cur_frame_par_2) { |
| if (layer_2->new_vpp_setting) { |
| struct vppfilter_mode_s *vpp_filter = |
| &cur_frame_par_2->vpp_filter; |
| if (vpp_filter->vpp_hsc_start_phase_step == |
| 0x1000000 && vpp_filter->vpp_vsc_start_phase_step == |
| 0x1000000 && vpp_filter->vpp_hsc_start_phase_step == |
| vpp_filter->vpp_hf_start_phase_step && |
| !vpp_filter->vpp_pre_vsc_en && |
| !vpp_filter->vpp_pre_hsc_en && |
| !cur_frame_par_2->supsc0_enable && |
| !cur_frame_par_2->supsc1_enable && |
| layer_2->bypass_pps) |
| pps_state = 2; /* pps disable */ |
| else |
| pps_state = 1; /* pps enable */ |
| } |
| if (cur_frame_par_2->VPP_hd_start_lines_ |
| >= cur_frame_par_2->VPP_hd_end_lines_) |
| h_size = 0; |
| else |
| h_size = cur_frame_par_2->VPP_hd_end_lines_ |
| - cur_frame_par_2->VPP_hd_start_lines_ + 1; |
| h_size /= (cur_frame_par_2->hscale_skip_count + 1); |
| if (cur_frame_par_2->VPP_vd_start_lines_ |
| >= cur_frame_par_2->VPP_vd_end_lines_) |
| v_size = 0; |
| else |
| v_size = cur_frame_par_2->VPP_vd_end_lines_ |
| - cur_frame_par_2->VPP_vd_start_lines_ + 1; |
| v_size /= |
| (cur_frame_par_2->vscale_skip_count + 1); |
| frame_size_2 = (h_size << 16) | v_size; |
| } |
| |
| /* trigger dv process once when stop playing */ |
| /* because disp_vf is not sync with video off */ |
| if (cur_dv_vf_2 && !disp_vf_2) |
| amdv_set_toggle_flag(1); |
| |
| cur_dv_vf_2 = disp_vf_2; |
| |
| if (cur_frame_size_2 != frame_size_2) { |
| cur_frame_size_2 = frame_size_2; |
| amdv_set_toggle_flag(1); |
| } |
| } |
| /*************************************************/ |
| if (!disp_vf_1 || is_local_vf(disp_vf_1)) |
| layer_1->vf_top1 = NULL;/*reset vf_top1 when video disable or keep*/ |
| if (is_aml_hw5()) |
| amdolby_vision_process_hw5 |
| (layer_1->vf_top1, |
| disp_vf_1, frame_size_1, |
| toggle_mode_1, pps_state); |
| else |
| amdolby_vision_process |
| (disp_vf_1, frame_size_1, |
| disp_vf_2, frame_size_2, |
| toggle_mode_1, toggle_mode_2, pps_state); |
| |
| /*update setting according to vd1*/ |
| if (!is_aml_hw5()) |
| amdv_update_setting(disp_vf_1); |
| } |
| } |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| void vsync_rdma_process(void) |
| { |
| int ret; |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_ATRACE) |
| int i; |
| #endif |
| |
| ret = vsync_rdma_config(); |
| if (ret == 1) { |
| /* rdma reset case */ |
| vd_layer[0].property_changed = true; |
| vd_layer[1].property_changed = true; |
| vd_layer[2].property_changed = true; |
| } |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_ATRACE) |
| for (i = 0; i < MAX_VD_LAYER; i++) { |
| if (vd_layer[i].dispbuf) { |
| ATRACE_COUNTER("vpp_frame_index_end", |
| vd_layer[i].dispbuf->frame_index); |
| ATRACE_COUNTER("vpp_frame_index_end", 0); |
| ATRACE_COUNTER("vpp_timestamp_end", |
| (unsigned long) |
| div_u64(vd_layer[i].dispbuf->timestamp, |
| 1000000000)); |
| ATRACE_COUNTER("vpp_timestamp_end", 0); |
| } |
| } |
| #endif |
| } |
| #endif |
| |
| #ifndef CONFIG_AMLOGIC_REMOVE_OLD |
| /* patch for 4k2k bandwidth issue, skiw mali and vpu mif */ |
| static void dmc_adjust_for_mali_vpu(unsigned int width, |
| unsigned int height, |
| bool force_adjust) |
| { |
| if (toggle_count == last_toggle_count) { |
| toggle_same_count++; |
| } else { |
| last_toggle_count = toggle_count; |
| toggle_same_count = 0; |
| } |
| /*avoid 3840x2160 crop*/ |
| if (width >= 2000 && height >= 1400 && |
| ((dmc_config_state != 1 && toggle_same_count < 30) || |
| force_adjust)) { |
| if (0) {/* if (is_dolby_vision_enable()) { */ |
| /* vpu dmc */ |
| WRITE_DMCREG |
| (DMC_AM0_CHAN_CTRL, |
| 0x85f403f4); |
| WRITE_DMCREG |
| (DMC_AM1_CHAN_CTRL, |
| 0x85f403f4); |
| WRITE_DMCREG |
| (DMC_AM2_CHAN_CTRL, |
| 0x85f403f4); |
| |
| /* mali dmc */ |
| WRITE_DMCREG |
| (DMC_AXI1_CHAN_CTRL, |
| 0xff10ff4); |
| WRITE_DMCREG |
| (DMC_AXI2_CHAN_CTRL, |
| 0xff10ff4); |
| WRITE_DMCREG |
| (DMC_AXI1_HOLD_CTRL, |
| 0x08040804); |
| WRITE_DMCREG |
| (DMC_AXI2_HOLD_CTRL, |
| 0x08040804); |
| } else { |
| /* vpu dmc */ |
| WRITE_DMCREG |
| (DMC_AM1_CHAN_CTRL, |
| 0x43028); |
| WRITE_DMCREG |
| (DMC_AM1_HOLD_CTRL, |
| 0x18101818); |
| WRITE_DMCREG |
| (DMC_AM3_CHAN_CTRL, |
| 0x85f403f4); |
| WRITE_DMCREG |
| (DMC_AM4_CHAN_CTRL, |
| 0x85f403f4); |
| /* mali dmc */ |
| WRITE_DMCREG |
| (DMC_AXI1_HOLD_CTRL, |
| 0x10080804); |
| WRITE_DMCREG |
| (DMC_AXI2_HOLD_CTRL, |
| 0x10080804); |
| } |
| dmc_config_state = 1; |
| } else if (((toggle_same_count >= 30) || |
| ((width < 2000) && (height < 1400))) && |
| (dmc_config_state != 2)) { |
| /* vpu dmc */ |
| WRITE_DMCREG |
| (DMC_AM0_CHAN_CTRL, |
| 0x8FF003C4); |
| WRITE_DMCREG |
| (DMC_AM1_CHAN_CTRL, |
| 0x3028); |
| WRITE_DMCREG |
| (DMC_AM1_HOLD_CTRL, |
| 0x18101810); |
| WRITE_DMCREG |
| (DMC_AM2_CHAN_CTRL, |
| 0x8FF003C4); |
| WRITE_DMCREG |
| (DMC_AM2_HOLD_CTRL, |
| 0x3028); |
| WRITE_DMCREG |
| (DMC_AM3_CHAN_CTRL, |
| 0x85f003f4); |
| WRITE_DMCREG |
| (DMC_AM4_CHAN_CTRL, |
| 0x85f003f4); |
| |
| /* mali dmc */ |
| WRITE_DMCREG |
| (DMC_AXI1_CHAN_CTRL, |
| 0x8FF00FF4); |
| WRITE_DMCREG |
| (DMC_AXI2_CHAN_CTRL, |
| 0x8FF00FF4); |
| WRITE_DMCREG |
| (DMC_AXI1_HOLD_CTRL, |
| 0x18101810); |
| WRITE_DMCREG |
| (DMC_AXI2_HOLD_CTRL, |
| 0x18101810); |
| toggle_same_count = 30; |
| dmc_config_state = 2; |
| } |
| } |
| #endif |
| |
| bool black_threshold_check(u8 id) |
| { |
| struct video_layer_s *layer = NULL; |
| struct disp_info_s *layer_info = NULL; |
| struct vpp_frame_par_s *frame_par = NULL; |
| bool ret = false; |
| |
| if (id >= MAX_VD_LAYERS) |
| return ret; |
| |
| if (black_threshold_width <= 0 || |
| black_threshold_height <= 0) |
| return ret; |
| |
| layer = &vd_layer[id]; |
| layer_info = &glayer_info[id]; |
| if (layer_info->layer_top == 0 && |
| layer_info->layer_left == 0 && |
| layer_info->layer_width <= 1 && |
| layer_info->layer_height <= 1) |
| /* special case to do full screen display */ |
| return ret; |
| |
| frame_par = layer->cur_frame_par; |
| if (frame_par && |
| (frame_par->VPP_pic_in_height_ <= 10 || |
| frame_par->VPP_line_in_length_ <= 10)) |
| return true; |
| if (layer_info->layer_width <= black_threshold_width || |
| layer_info->layer_height <= black_threshold_height) { |
| if (frame_par && |
| frame_par->vscale_skip_count == 8 && |
| frame_par->hscale_skip_count == 1) |
| ret = true; |
| } |
| return ret; |
| } |
| |
| bool black_threshold_check_s5(u8 id) |
| { |
| struct video_layer_s *layer = NULL; |
| struct disp_info_s *layer_info = NULL; |
| struct vpp_frame_par_s *frame_par = NULL; |
| u32 black_threshold_width_s5 = 0; |
| u32 black_threshold_height_s5 = 0; |
| bool ret = false; |
| const struct vinfo_s *vinfo = get_current_vinfo(); |
| |
| if (id >= MAX_VD_LAYERS) |
| return ret; |
| |
| black_threshold_width_s5 = black_threshold_width; |
| black_threshold_height_s5 = black_threshold_width; |
| |
| /* check output */ |
| if (vinfo) { |
| /* output: (4k-8k] */ |
| if (vinfo->width >= 3840 && vinfo->height >= 2160) { |
| black_threshold_width_s5 = black_threshold_width * 4; |
| black_threshold_height_s5 = black_threshold_height * 4 + 20; |
| } else if ((vinfo->width >= 1920 && vinfo->height >= 1080 && |
| (vinfo->sync_duration_num / |
| vinfo->sync_duration_den > 60))) { |
| /* 1080p 120hz - 4k 120hz */ |
| black_threshold_width_s5 = black_threshold_width * 2; |
| black_threshold_height_s5 = black_threshold_height * 2; |
| } else { |
| black_threshold_width_s5 = black_threshold_width; |
| black_threshold_height_s5 = black_threshold_height; |
| } |
| } |
| if (black_threshold_width_s5 <= 0 || |
| black_threshold_height_s5 <= 0) |
| return ret; |
| |
| layer = &vd_layer[id]; |
| layer_info = &glayer_info[id]; |
| if (layer_info->layer_top == 0 && |
| layer_info->layer_left == 0 && |
| layer_info->layer_width <= 1 && |
| layer_info->layer_height <= 1) |
| /* special case to do full screen display */ |
| return ret; |
| |
| frame_par = layer->cur_frame_par; |
| if (frame_par && |
| (frame_par->VPP_pic_in_height_ <= 10 || |
| frame_par->VPP_line_in_length_ <= 10)) |
| return true; |
| if (layer_info->layer_width <= black_threshold_width_s5 || |
| layer_info->layer_height <= black_threshold_height_s5) { |
| if (frame_par && |
| frame_par->vscale_skip_count == 8 && |
| frame_par->hscale_skip_count == 1) |
| ret = true; |
| } |
| return ret; |
| } |
| |
| void update_vppx_property(u8 layer_id) |
| { |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| /* vpp1 case */ |
| if (vd_layer_vpp[0].layer_id == layer_id && |
| vd_layer_vpp[0].vpp_index == VPP1) |
| vd_layer_vpp[0].property_changed = true; |
| /* vpp2 case */ |
| else if (vd_layer_vpp[1].layer_id == layer_id && |
| vd_layer_vpp[1].vpp_index == VPP2) |
| vd_layer_vpp[1].property_changed = true; |
| #endif |
| } |
| |
| void _set_video_crop(struct disp_info_s *layer, int *p) |
| { |
| int last_l, last_r, last_t, last_b; |
| int new_l, new_r, new_t, new_b; |
| |
| if (!layer) |
| return; |
| |
| last_t = layer->crop_top; |
| last_l = layer->crop_left; |
| last_b = layer->crop_bottom; |
| last_r = layer->crop_right; |
| |
| layer->crop_top = p[0]; |
| layer->crop_left = p[1]; |
| layer->crop_bottom = p[2]; |
| layer->crop_right = p[3]; |
| |
| new_t = layer->crop_top; |
| new_l = layer->crop_left; |
| new_b = layer->crop_bottom; |
| new_r = layer->crop_right; |
| if (new_t != last_t || new_l != last_l || |
| new_b != last_b || new_r != last_r) { |
| if (layer->layer_id == 0) { |
| vd_layer[0].property_changed = true; |
| } else if (layer->layer_id == 1) { |
| if (vd_layer[1].vpp_index == VPP0) |
| vd_layer[1].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } else if (layer->layer_id == 2) { |
| if (vd_layer[2].vpp_index == VPP0) |
| vd_layer[2].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } |
| } |
| } |
| |
| void _set_video_window(struct disp_info_s *layer, int *p) |
| { |
| int w, h; |
| int *parsed = p; |
| int last_x, last_y, last_w, last_h; |
| int new_x, new_y, new_w, new_h; |
| const struct vinfo_s *info = get_current_vinfo(); |
| |
| if (!layer) |
| return; |
| if (!info || info->mode == VMODE_INVALID) |
| return; |
| |
| /* move the invert logic to vpp.c */ |
| #ifdef TMP_DISABLE /* TV_REVERSE */ |
| if (reverse || video_mirror) { |
| int temp, temp1; |
| |
| temp = parsed[0]; |
| temp1 = parsed[1]; |
| if (get_osd_reverse() & 1) { |
| parsed[0] = info->width - parsed[2] - 1; |
| parsed[2] = info->width - temp - 1; |
| } |
| if (get_osd_reverse() & 2) { |
| parsed[1] = info->height - parsed[3] - 1; |
| parsed[3] = info->height - temp1 - 1; |
| } |
| } |
| #endif |
| |
| last_x = layer->layer_left; |
| last_y = layer->layer_top; |
| last_w = layer->layer_width; |
| last_h = layer->layer_height; |
| |
| if (parsed[0] < 0 && parsed[2] < 2) { |
| parsed[2] = 2; |
| parsed[0] = 0; |
| } |
| if (parsed[1] < 0 && parsed[3] < 2) { |
| parsed[3] = 2; |
| parsed[1] = 0; |
| } |
| w = parsed[2] - parsed[0] + 1; |
| h = parsed[3] - parsed[1] + 1; |
| |
| if (w > 0 && h > 0) { |
| if (w == 1 && h == 1) { |
| w = 0; |
| h = 0; |
| } |
| layer->layer_left = parsed[0]; |
| layer->layer_top = parsed[1]; |
| layer->layer_width = w; |
| layer->layer_height = h; |
| } |
| |
| new_x = layer->layer_left; |
| new_y = layer->layer_top; |
| new_w = layer->layer_width; |
| new_h = layer->layer_height; |
| vpp_trace_axis(layer->layer_left, layer->layer_top, |
| layer->layer_left + layer->layer_width - 1, |
| layer->layer_top + layer->layer_height - 1); |
| |
| if (last_x != new_x || last_y != new_y || |
| last_w != new_w || last_h != new_h) { |
| if (layer->layer_id == 0) { |
| atomic_set(&axis_changed, 1); |
| vd_layer[0].property_changed = true; |
| } else if (layer->layer_id == 1) { |
| if (vd_layer[1].vpp_index == VPP0) |
| vd_layer[1].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } else if (layer->layer_id == 2) { |
| if (vd_layer[2].vpp_index == VPP0) |
| vd_layer[2].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) |
| pr_info("VD%d axis changed: %d %d (%d %d)->%d %d (%d %d)\n", |
| layer->layer_id + 1, |
| last_x, last_y, last_w, last_h, |
| new_x, new_y, new_w, new_h); |
| } |
| } |
| |
| void _set_video_mirror(struct disp_info_s *layer, int mirror) |
| { |
| int last_mirror, new_mirror; |
| int last_reverse, new_reverse; |
| bool revser_temp = false; |
| |
| if (!layer) |
| return; |
| |
| /* 'reverse' and 'video_mirror' are not enabled at the same time */ |
| #ifdef TV_REVERSE |
| if (reverse) { |
| revser_temp = true; |
| if (mirror == H_MIRROR) { |
| mirror = V_MIRROR; |
| revser_temp = false; |
| } else if (mirror == V_MIRROR) { |
| mirror = H_MIRROR; |
| revser_temp = false; |
| } else if (mirror == HV_MIRROR) { |
| mirror = NO_MIRROR; |
| revser_temp = false; |
| } |
| } |
| #endif |
| if (video_mirror == NO_MIRROR) { |
| switch (mirror) { |
| case NO_MIRROR: |
| case H_MIRROR: |
| case V_MIRROR: |
| break; |
| case HV_MIRROR: |
| mirror = NO_MIRROR; |
| revser_temp = true; |
| break; |
| } |
| } else if (video_mirror == H_MIRROR) { |
| switch (mirror) { |
| case NO_MIRROR: |
| mirror = H_MIRROR; |
| break; |
| case H_MIRROR: |
| mirror = NO_MIRROR; |
| break; |
| case V_MIRROR: |
| mirror = NO_MIRROR; |
| revser_temp = true; |
| break; |
| case HV_MIRROR: |
| mirror = V_MIRROR; |
| break; |
| } |
| } else if (video_mirror == V_MIRROR) { |
| switch (mirror) { |
| case NO_MIRROR: |
| mirror = V_MIRROR; |
| break; |
| case H_MIRROR: |
| mirror = NO_MIRROR; |
| revser_temp = true; |
| break; |
| case V_MIRROR: |
| mirror = NO_MIRROR; |
| break; |
| case HV_MIRROR: |
| mirror = H_MIRROR; |
| break; |
| } |
| } |
| |
| last_mirror = layer->mirror; |
| new_mirror = mirror; |
| last_reverse = layer->reverse; |
| new_reverse = revser_temp; |
| layer->mirror = mirror; |
| layer->reverse = revser_temp; |
| |
| if (last_mirror != new_mirror || |
| last_reverse != new_reverse) { |
| if (layer->layer_id == 0) { |
| vd_layer[0].property_changed = true; |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) |
| pr_info("VD1 mirror changed: %d ->%d\n", |
| last_mirror, new_mirror); |
| } else if (layer->layer_id == 1) { |
| if (vd_layer[1].vpp_index == VPP0) |
| vd_layer[1].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } else if (layer->layer_id == 2) { |
| if (vd_layer[2].vpp_index == VPP0) |
| vd_layer[2].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } |
| } |
| } |
| |
| void set_video_crop_ext(int layer_index, int *p) |
| { |
| struct disp_info_s *layer = &glayer_info[layer_index]; |
| |
| _set_video_crop(layer, p); |
| } |
| |
| void set_video_window_ext(int layer_index, int *p) |
| { |
| struct disp_info_s *layer = &glayer_info[layer_index]; |
| |
| if (!(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) |
| _set_video_window(layer, p); |
| } |
| |
| void set_video_zorder_ext(int layer_index, int zorder) |
| { |
| struct disp_info_s *layer = &glayer_info[layer_index]; |
| |
| if (layer->zorder != zorder) { |
| layer->zorder = zorder; |
| if (layer->layer_id == 0) { |
| vd_layer[0].property_changed = true; |
| } else if (layer->layer_id == 1) { |
| if (vd_layer[1].vpp_index == VPP0) |
| vd_layer[1].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } else if (layer->layer_id == 2) { |
| if (vd_layer[2].vpp_index == VPP0) |
| vd_layer[2].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } |
| } |
| } |
| |
| void get_video_input_info(struct video_input_info *input_info) |
| { |
| if (!cur_frame_par[0]) |
| return; |
| input_info->height = cur_frame_par[0]->video_input_h; |
| input_info->width = cur_frame_par[0]->video_input_w; |
| input_info->crop_top = cur_frame_par[0]->crop_top; |
| input_info->crop_bottom = cur_frame_par[0]->crop_bottom; |
| input_info->crop_left = cur_frame_par[0]->crop_left; |
| input_info->crop_right = cur_frame_par[0]->crop_right; |
| } |
| |
| static void vdx_force_black(u8 layer_id) |
| { |
| if (layer_id == 0) { |
| if (vd_layer[0].dispbuf && |
| (vd_layer[0].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME || |
| need_force_black)) { |
| if ((vd_layer[0].force_black && |
| !(debug_flag & DEBUG_FLAG_NO_CLIP_SETTING)) || |
| !vd_layer[0].force_black) { |
| /*default YUV */ |
| vd_layer[0].clip_setting.clip_max = |
| (0x0 << 20) | (0x200 << 10) | 0x200; |
| vd_layer[0].clip_setting.clip_min = |
| vd_layer[0].clip_setting.clip_max; |
| if (!cpu_after_eq(MESON_CPU_MAJOR_ID_T7) || |
| cur_dev->display_module == OLD_DISPLAY_MODULE) { |
| if (vd_layer[0].dispbuf->type & VIDTYPE_RGB_444) { |
| /* chip before t7 vd1 hdr core after vd1 clip */ |
| /* RGB */ |
| vd_layer[0].clip_setting.clip_max = |
| (0x0 << 20) | (0x0 << 10) | 0; |
| vd_layer[0].clip_setting.clip_min = |
| vd_layer[0].clip_setting.clip_max; |
| } |
| } |
| vd_layer[0].clip_setting.clip_done = false; |
| } |
| if (!vd_layer[0].force_black) { |
| pr_debug("vsync: vd1 force black\n"); |
| vd_layer[0].force_black = true; |
| } |
| } else if (vd_layer[0].force_black) { |
| pr_debug("vsync: vd1 black to normal\n"); |
| vd_layer[0].clip_setting.clip_max = |
| (0x3ff << 20) | (0x3ff << 10) | 0x3ff; |
| vd_layer[0].clip_setting.clip_min = 0; |
| vd_layer[0].clip_setting.clip_done = false; |
| vd_layer[0].force_black = false; |
| } |
| } else { |
| if (vd_layer[layer_id].dispbuf && |
| (vd_layer[layer_id].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME)) |
| safe_switch_videolayer(layer_id, false, true); |
| } |
| } |
| |
| void pipx_swap_frame(struct video_layer_s *layer, struct vframe_s *vf, |
| const struct vinfo_s *vinfo) |
| { |
| struct disp_info_s *layer_info; |
| int axis[4]; |
| int crop[4]; |
| u8 layer_id = layer->layer_id; |
| |
| if (!vf || layer_id >= MAX_VD_LAYER) |
| return; |
| |
| layer_info = &glayer_info[layer_id]; |
| if ((vf->flag & (VFRAME_FLAG_VIDEO_COMPOSER | |
| VFRAME_FLAG_VIDEO_DRM)) && |
| !(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) { |
| int mirror = 0; |
| |
| axis[0] = vf->axis[0]; |
| axis[1] = vf->axis[1]; |
| axis[2] = vf->axis[2]; |
| axis[3] = vf->axis[3]; |
| crop[0] = vf->crop[0]; |
| crop[1] = vf->crop[1]; |
| crop[2] = vf->crop[2]; |
| crop[3] = vf->crop[3]; |
| _set_video_window(layer_info, axis); |
| _set_video_crop(layer_info, crop); |
| if (vf->flag & VFRAME_FLAG_MIRROR_H) |
| mirror = H_MIRROR; |
| if (vf->flag & VFRAME_FLAG_MIRROR_V) |
| mirror |= V_MIRROR; |
| _set_video_mirror(layer_info, mirror); |
| set_alpha_scpxn(layer, vf->composer_info); |
| layer_info->zorder = vf->zorder; |
| } else { |
| _set_video_mirror(layer_info, 0); |
| } |
| |
| layer_swap_frame(vf, layer, false, vinfo, 0); |
| |
| /* FIXME: free correct keep frame */ |
| if (!is_local_vf(layer->dispbuf)) |
| video_keeper_new_frame_notify(layer->keep_frame_id); |
| fgrain_update_table(layer, vf); |
| if (stop_update) |
| layer->new_vpp_setting = false; |
| } |
| |
| void primary_swap_frame(struct video_layer_s *layer, |
| struct vframe_s *vf1, |
| int line) |
| { |
| bool vf_with_el = false; |
| bool force_toggle = false; |
| int ret = 0; |
| struct disp_info_s *layer_info = NULL; |
| int axis[4]; |
| int crop[4]; |
| int crop_save[4]; |
| struct vframe_s *vf; |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| u32 vpp_index = layer->vpp_index; |
| #endif |
| |
| ATRACE_COUNTER(__func__, line); |
| |
| if (!vf1) |
| return; |
| |
| vf = vf1; |
| layer_info = &glayer_info[0]; |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| if (layer->need_switch_vf && IS_DI_POST(vf->type) && |
| dil_get_diff_ver_flag() == DI_DRV_DEINTERLACE) { |
| if ((vf1->flag & VFRAME_FLAG_DOUBLE_FRAM) && |
| is_di_post_mode(vf1)) { |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| if (di_api_get_instance_id() == vf1->di_instance_id) { |
| layer->need_switch_vf = false; |
| pr_info("set need_switch_vf false\n"); |
| } else { |
| vf = vf1->vf_ext; |
| layer->do_switch = true; |
| di_api_post_disable(); |
| } |
| #endif |
| } else { |
| layer->need_switch_vf = false; |
| } |
| } |
| #endif |
| if ((vf->flag & (VFRAME_FLAG_VIDEO_COMPOSER | |
| VFRAME_FLAG_VIDEO_DRM)) && |
| !(vf->flag & VFRAME_FLAG_FAKE_FRAME) && |
| !(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) { |
| int mirror = 0; |
| |
| axis[0] = vf->axis[0]; |
| axis[1] = vf->axis[1]; |
| axis[2] = vf->axis[2]; |
| axis[3] = vf->axis[3]; |
| crop[0] = vf->crop[0]; |
| crop[1] = vf->crop[1]; |
| crop[2] = vf->crop[2]; |
| crop[3] = vf->crop[3]; |
| _set_video_window(&glayer_info[0], axis); |
| if (vf->source_type != VFRAME_SOURCE_TYPE_HDMI && |
| vf->source_type != VFRAME_SOURCE_TYPE_CVBS && |
| vf->source_type != VFRAME_SOURCE_TYPE_TUNER && |
| vf->source_type != VFRAME_SOURCE_TYPE_HWC) { |
| _set_video_crop(&glayer_info[0], crop); |
| } else { |
| crop_save[0] = glayer_info[0].crop_top_save; |
| crop_save[1] = glayer_info[0].crop_left_save; |
| crop_save[2] = glayer_info[0].crop_bottom_save; |
| crop_save[3] = glayer_info[0].crop_right_save; |
| _set_video_crop(&glayer_info[0], crop_save); |
| } |
| if (vf->flag & VFRAME_FLAG_MIRROR_H) |
| mirror = H_MIRROR; |
| if (vf->flag & VFRAME_FLAG_MIRROR_V) |
| mirror |= V_MIRROR; |
| _set_video_mirror(&glayer_info[0], mirror); |
| set_alpha_scpxn(layer, vf->composer_info); |
| glayer_info[0].zorder = vf->zorder; |
| } else { |
| _set_video_mirror(&glayer_info[0], 0); |
| } |
| |
| if (layer->layer_id == 0 && |
| !(vf->type & VIDTYPE_COMPRESS) && |
| layer_info->need_no_compress) { |
| atomic_sub(1, &gafbc_request); |
| layer_info->need_no_compress = false; |
| force_toggle = true; |
| } |
| |
| if (is_amdv_enable()) |
| vf_with_el = has_enhanced_layer(vf); |
| |
| /* FIXME: need check the pre seq */ |
| if (vf->early_process_fun) { |
| if (vf->early_process_fun(vf->private_data, vf) == 1) |
| force_toggle = true; |
| } else { |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| /* FIXME: is_di_on */ |
| if (is_di_post_mode(vf)) { |
| /* check mif enable status, disable post di */ |
| cur_dev->rdma_func[vpp_index].rdma_wr |
| (DI_POST_CTRL, 0x3 << 30); |
| cur_dev->rdma_func[vpp_index].rdma_wr |
| (DI_POST_SIZE, |
| (32 - 1) | ((128 - 1) << 16)); |
| cur_dev->rdma_func[vpp_index].rdma_wr |
| (DI_IF1_GEN_REG, |
| READ_VCBUS_REG(DI_IF1_GEN_REG) & |
| 0xfffffffe); |
| } |
| #endif |
| } |
| |
| if (last_process_3d_type != process_3d_type || |
| last_el_status != vf_with_el) |
| force_toggle = true; |
| |
| if (!layer->dispbuf || |
| (vf->type & VIDTYPE_COMPRESS && |
| (layer->dispbuf->compWidth != vf->compWidth || |
| layer->dispbuf->compHeight != vf->compHeight)) || |
| (layer->dispbuf->width != vf->width || |
| layer->dispbuf->height != vf->height)) { |
| video_prop_status |= VIDEO_PROP_CHANGE_SIZE; |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) |
| pr_info("VD1 src size changed: %dx%x->%dx%d. cur:%p, new:%p\n", |
| layer->dispbuf ? layer->dispbuf->width : 0, |
| layer->dispbuf ? layer->dispbuf->height : 0, |
| vf->width, vf->height, |
| layer->dispbuf, vf); |
| } |
| |
| /* switch buffer */ |
| post_canvas = vf->canvas0Addr; |
| ret = layer_swap_frame |
| (vf, layer, force_toggle, vinfo, |
| cur_dispbuf2 ? OP_HAS_DV_EL : 0); |
| if (ret >= vppfilter_success) { |
| amlog_mask |
| (LOG_MASK_FRAMEINFO, |
| "%s %dx%d ar=0x%x\n", |
| ((vf->type & VIDTYPE_TYPEMASK) == |
| VIDTYPE_INTERLACE_TOP) ? "interlace-top" |
| : ((vf->type & VIDTYPE_TYPEMASK) |
| == VIDTYPE_INTERLACE_BOTTOM) |
| ? "interlace-bottom" : "progressive", vf->width, |
| vf->height, vf->ratio_control); |
| #if defined(TV_3D_FUNCTION_OPEN) && defined(CONFIG_AMLOGIC_MEDIA_TVIN) |
| amlog_mask |
| (LOG_MASK_FRAMEINFO, |
| "%s trans_fmt=%u\n", __func__, vf->trans_fmt); |
| |
| #endif |
| } |
| if (ret == vppfilter_changed_but_hold) { |
| video_notify_flag |= |
| VIDEO_NOTIFY_NEED_NO_COMP; |
| vpp_hold_setting_cnt++; |
| if (layer->global_debug & DEBUG_FLAG_BASIC_INFO) |
| pr_info("toggle_frame vpp hold setting cnt: %d\n", |
| vpp_hold_setting_cnt); |
| } else {/* apply new vpp settings */ |
| if (layer->next_frame_par->vscale_skip_count <= 1 && |
| vf->type_original & VIDTYPE_SUPPORT_COMPRESS && |
| !(vf->type_original & VIDTYPE_COMPRESS)) { |
| video_notify_flag |= |
| VIDEO_NOTIFY_NEED_NO_COMP; |
| if (layer->global_debug & DEBUG_FLAG_BASIC_INFO) |
| pr_info("disable no compress mode\n"); |
| } |
| vpp_hold_setting_cnt = 0; |
| } |
| last_process_3d_type = process_3d_type; |
| |
| /* if el is unnecessary, afbc2 need to be closed */ |
| if (last_el_status == 1 && vf_with_el == 0) |
| need_disable_vd[1] = true; |
| last_el_status = vf_with_el; |
| |
| if (((vf->type & VIDTYPE_MVC) == 0) && last_mvc_status) |
| need_disable_vd[1] = true; |
| |
| if (vf->type & VIDTYPE_MVC) |
| last_mvc_status = true; |
| else |
| last_mvc_status = false; |
| |
| /* FIXME: free correct keep frame */ |
| if (!is_local_vf(layer->dispbuf) && !layer->do_switch) |
| video_keeper_new_frame_notify(layer->keep_frame_id); |
| fgrain_update_table(layer, vf); |
| if (stop_update) |
| layer->new_vpp_setting = false; |
| ATRACE_COUNTER(__func__, 0); |
| } |
| |
| s32 primary_render_frame(struct video_layer_s *layer, |
| const struct vinfo_s *vinfo) |
| { |
| struct vpp_frame_par_s *frame_par; |
| bool force_setting = false; |
| struct scaler_setting_s local_vd2_pps = {0}; |
| struct blend_setting_s local_vd2_blend = {0}; |
| struct mif_pos_s local_vd2_mif = {0}; |
| bool update_vd2 = false; |
| struct vframe_s *dispbuf = NULL; |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| int pq_process_debug[4]; |
| int count = 0, k = 0, l = 0; |
| #endif |
| int ret = 0; |
| u8 vpp_index; |
| |
| vpp_index = layer->vpp_index; |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| if (cur_dev->vsync_2to1_enable && vsync_count_start) { |
| /* not prevsync not handle */ |
| if (!frc_drv_get_1st_frm()) |
| return 0; |
| } |
| #endif |
| local_vd2_mif.p_vd_mif_reg = &vd_layer[1].vd_mif_reg; |
| local_vd2_mif.p_vd_afbc_reg = &vd_layer[1].vd_afbc_reg; |
| /* filter setting management */ |
| if (layer->new_vpp_setting) { |
| layer->cur_frame_par = layer->next_frame_par; |
| cur_frame_par[0] = layer->cur_frame_par; |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| if (layer->mosaic_mode) { |
| int i; |
| struct mosaic_frame_s *mosaic_frame; |
| struct video_layer_s *virtual_layer; |
| |
| for (i = 0; i < SLICE_NUM; i++) { |
| mosaic_frame = get_mosaic_vframe_info(i); |
| virtual_layer = &mosaic_frame->virtual_layer; |
| if (!virtual_layer) |
| return -1; |
| virtual_layer->cur_frame_par = |
| virtual_layer->next_frame_par; |
| } |
| } |
| #endif |
| } |
| if (glayer_info[layer->layer_id].fgrain_force_update) { |
| force_setting = true; |
| glayer_info[layer->layer_id].fgrain_force_update = false; |
| } |
| frame_par = layer->cur_frame_par; |
| if (layer->switch_vf && layer->vf_ext) |
| dispbuf = layer->vf_ext; |
| else |
| dispbuf = layer->dispbuf; |
| |
| #ifdef ENABLE_PLINK |
| if (is_plink_on(layer) && |
| dispbuf && !is_local_vf(dispbuf)) { |
| int iret; |
| struct pvpp_dis_para_in_s di_in_p; |
| |
| if (layer->plink_skip_cnt == 0) { |
| memset(&di_in_p, 0, sizeof(struct pvpp_dis_para_in_s)); |
| di_in_p.win.x_st = layer->cur_frame_par->VPP_hd_start_lines_; |
| di_in_p.win.x_end = layer->cur_frame_par->VPP_hd_end_lines_; |
| di_in_p.win.y_st = layer->cur_frame_par->VPP_vd_start_lines_; |
| di_in_p.win.y_end = layer->cur_frame_par->VPP_vd_end_lines_; |
| di_in_p.vinfo.x_d_st = layer->cur_frame_par->VPP_hsc_startp; |
| di_in_p.vinfo.x_d_end = layer->cur_frame_par->VPP_hsc_endp; |
| di_in_p.vinfo.y_d_st = layer->cur_frame_par->VPP_vsc_startp; |
| di_in_p.vinfo.y_d_end = layer->cur_frame_par->VPP_vsc_endp; |
| di_in_p.vinfo.x_d_size = di_in_p.vinfo.x_d_end - di_in_p.vinfo.x_d_st + 1; |
| di_in_p.vinfo.y_d_size = di_in_p.vinfo.y_d_end - di_in_p.vinfo.y_d_st + 1; |
| di_in_p.win.x_size = di_in_p.win.x_end - di_in_p.win.x_st + 1; |
| di_in_p.win.y_size = di_in_p.win.y_end - di_in_p.win.y_st + 1; |
| di_in_p.vinfo.htotal = vinfo->htotal; |
| di_in_p.vinfo.vtotal = vinfo->vtotal; |
| di_in_p.vinfo.height = vinfo->height; |
| di_in_p.vinfo.width = vinfo->width; |
| di_in_p.vinfo.frequency = vinfo->std_duration; |
| di_in_p.plink_reverse = glayer_info[0].reverse; |
| di_in_p.plink_hv_mirror = glayer_info[0].mirror; |
| if (IS_DI_PSTLINK(dispbuf->di_flag)) { |
| di_in_p.dmode = EPVPP_DISPLAY_MODE_DI; |
| di_in_p.link_mode = EPVPP_API_MODE_POST; |
| } else { |
| di_in_p.dmode = EPVPP_DISPLAY_MODE_NR; |
| di_in_p.link_mode = EPVPP_API_MODE_PRE; |
| } |
| di_in_p.unreg_bypass = 0; |
| di_in_p.follow_hold_line = vpp_hold_line[vpp_index]; |
| iret = pvpp_display(dispbuf, &di_in_p, NULL); |
| if (iret <= 0) { |
| vd_layer[0].property_changed = true; |
| vd_layer[0].plink_bypass_check = true; |
| if (layer->global_debug & DEBUG_FLAG_PLINK) |
| pr_info("VIDEO: pvpp_display fail: %d\n", iret); |
| } else if (layer->global_debug & DEBUG_FLAG_PLINK_MORE) { |
| pr_info("do di callback iret:%d\n", iret); |
| } |
| } else { |
| layer->plink_skip_cnt--; |
| } |
| } else if (is_plink_on(layer) && |
| layer->need_disable_plink && !dispbuf) { |
| int iret; |
| struct pvpp_dis_para_in_s di_in_p; |
| bool is_interlace = false; |
| |
| if (layer->cur_link_mode == EPVPP_API_MODE_POST) |
| is_interlace = true; |
| else |
| is_interlace = false; |
| /* no keep buffer after unreg case */ |
| memset(&di_in_p, 0, sizeof(struct pvpp_dis_para_in_s)); |
| di_in_p.dmode = EPVPP_DISPLAY_MODE_BYPASS; |
| di_in_p.unreg_bypass = 1; |
| di_in_p.follow_hold_line = vpp_hold_line[vpp_index]; |
| di_in_p.link_mode = layer->cur_link_mode; |
| iret = pvpp_display(NULL, &di_in_p, NULL); |
| if (layer->global_debug & DEBUG_FLAG_PLINK) |
| pr_info("%s: unreg_bypass plink mode ret %d\n", __func__, iret); |
| layer->plink_en = false; |
| layer->plink_bypass_check = false; |
| layer->plink_skip_cnt = 0; |
| iret = pvpp_sw(false, is_interlace); |
| if (layer->global_debug & DEBUG_FLAG_PLINK) |
| pr_info("%s: Disable plink mode ret %d\n", __func__, iret); |
| layer->cur_link_mode = EPVPP_API_MODE_NONE; |
| atomic_set(&vd_layer[0].disable_plink_done, 1); |
| } |
| #endif |
| |
| /* process cur frame for each vsync */ |
| if (dispbuf) { |
| int need_afbc = |
| (dispbuf->type & VIDTYPE_COMPRESS); |
| int afbc_need_reset = |
| (layer->enabled && need_afbc && |
| !is_afbc_enabled(layer->layer_id)); |
| |
| /*video on && afbc is off && is compress frame.*/ |
| if (layer->new_vpp_setting || afbc_need_reset) |
| vd_set_dcu |
| (layer->layer_id, layer, |
| frame_par, dispbuf); |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (cur_dispbuf2 && |
| (layer->new_vpp_setting || |
| afbc_need_reset || |
| dvel_changed)) |
| vd_set_dcu |
| (1, &vd_layer[1], |
| frame_par, cur_dispbuf2); |
| if (dvel_changed) |
| force_setting = true; |
| dvel_changed = false; |
| #endif |
| |
| #ifdef TV_3D_FUNCTION_OPEN |
| if (last_mode_3d && |
| (layer->new_vpp_setting || |
| afbc_need_reset)) |
| vd_set_dcu |
| (1, &vd_layer[1], |
| frame_par, dispbuf); |
| #endif |
| /* for vout change or interlace frame */ |
| proc_vd_vsc_phase_per_vsync |
| (layer, |
| frame_par, dispbuf); |
| |
| /* because 3d and dv process, vd2 need no scale. */ |
| /* so don't call the vd2 proc_vd_vsc_phase_per_vsync */ |
| |
| /* Do 3D process if enabled */ |
| switch_3d_view_per_vsync(layer); |
| } |
| |
| /* no frame parameter change */ |
| if ((!layer->new_vpp_setting && !force_setting) || !frame_par) { |
| /* when new frame is toggled but video layer is not on */ |
| /* need always flush pps register before pwr on */ |
| /* to avoid pps coeff lost */ |
| if (frame_par && dispbuf && !is_local_vf(dispbuf) && |
| (!get_video_enabled(0) || |
| get_video_onoff_state(0) == |
| VIDEO_ENABLE_STATE_ON_PENDING)) |
| vd_scaler_setting(layer, &layer->sc_setting); |
| |
| /* dolby vision process for each vsync */ |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (!support_multi_core1()) |
| amdolby_vision_proc(layer, frame_par, NULL, NULL); |
| #endif |
| ret = 0; |
| goto render_exit; |
| } |
| /* VPP one time settings */ |
| if (dispbuf) { |
| config_vd_param(layer, dispbuf); |
| config_vd_position |
| (layer, &layer->mif_setting); |
| config_aisr_position(layer, &layer->aisr_mif_setting); |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (is_amdv_on() && cur_dispbuf2) { |
| config_dvel_position |
| (layer, |
| &local_vd2_mif, |
| cur_dispbuf2); |
| update_vd2 = true; |
| } |
| #endif |
| #ifdef TV_3D_FUNCTION_OPEN |
| if ((dispbuf->type & VIDTYPE_MVC) || |
| last_mode_3d) { |
| config_3d_vd2_position |
| (layer, &local_vd2_mif); |
| update_vd2 = true; |
| } |
| #endif |
| if (layer->vd1_vd2_mux) { |
| layer->mif_setting.p_vd_mif_reg = |
| &vd_layer[1].vd_mif_reg; |
| vd_mif_setting(&vd_layer[1], &layer->mif_setting); |
| } else { |
| vd_mif_setting(layer, &layer->mif_setting); |
| } |
| if (update_vd2) |
| vd_mif_setting(&vd_layer[1], &local_vd2_mif); |
| fgrain_config(layer, |
| layer->cur_frame_par, |
| &layer->mif_setting, |
| &layer->fgrain_setting, |
| dispbuf); |
| /* aisr mif setting */ |
| aisr_reshape_cfg(layer, &layer->aisr_mif_setting); |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| /* work around to cut the last green line */ |
| /* when two layer dv display and do vskip */ |
| if (is_amdv_on() && |
| frame_par->vscale_skip_count > 0 && |
| cur_dispbuf2 && |
| frame_par->VPP_pic_in_height_ > 0) |
| frame_par->VPP_pic_in_height_--; |
| #endif |
| /* aisr pps config */ |
| config_aisr_pps(layer, &layer->aisr_sc_setting); |
| |
| config_vd_pps |
| (layer, &layer->sc_setting, vinfo); |
| config_vd_blend |
| (layer, &layer->bld_setting); |
| |
| update_vd2 = false; |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (for_amdv_certification() && |
| !get_idk_need_pps()) |
| /*some idk2.6 cert cases need pps scaler, idk5.1 5364 need pps*/ |
| layer->sc_setting.sc_top_enable = false; |
| |
| if (is_amdv_on() && cur_dispbuf2) { |
| config_dvel_pps |
| (layer, &local_vd2_pps, vinfo); |
| config_dvel_blend |
| (layer, &local_vd2_blend, cur_dispbuf2); |
| update_vd2 = true; |
| } |
| #endif |
| #ifdef TV_3D_FUNCTION_OPEN |
| /*turn off vertical scaler when 3d display */ |
| if ((dispbuf && |
| (dispbuf->type & VIDTYPE_MVC)) || |
| last_mode_3d) { |
| layer->sc_setting.sc_v_enable = false; |
| config_3d_vd2_pps |
| (layer, &local_vd2_pps, vinfo); |
| config_3d_vd2_blend |
| (layer, &local_vd2_blend); |
| update_vd2 = true; |
| } |
| #endif |
| vd_s5_hw_set(layer, dispbuf, frame_par); |
| vd_scaler_setting(layer, &layer->sc_setting); |
| aisr_scaler_setting(layer, &layer->aisr_sc_setting); |
| aisr_demo_axis_set(layer); |
| /* update alpha win */ |
| if (!cur_dev->pre_vsync_enable) |
| alpha_win_set(layer); |
| vd_blend_setting(layer, &layer->bld_setting); |
| if (update_vd2) { |
| vd_scaler_setting(&vd_layer[1], &local_vd2_pps); |
| vd_blend_setting(&vd_layer[1], &local_vd2_blend); |
| } |
| /* dolby vision process for each vsync */ |
| /* need set after correct_vd1_mif_size_for_DV */ |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (!support_multi_core1()) |
| amdolby_vision_proc(layer, frame_par, NULL, NULL); |
| #endif |
| fgrain_setting(layer, &layer->fgrain_setting, dispbuf); |
| layer->new_vpp_setting = false; |
| ret = 1; |
| render_exit: |
| /* check if need blank */ |
| vdx_force_black(0); |
| video_secure_set(layer->vpp_index); |
| vd_clip_setting(layer->vpp_index, 0, &vd_layer[0].clip_setting); |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| memset(&ai_face_value, 0, sizeof(ai_face_value)); |
| if (vd_layer[0].dispbuf && |
| cur_dev->display_module != C3_DISPLAY_MODULE) { |
| pq_process_debug[0] = ai_pq_value; |
| pq_process_debug[1] = ai_pq_disable; |
| pq_process_debug[2] = ai_pq_debug; |
| pq_process_debug[3] = ai_pq_policy; |
| #ifdef CONFIG_AMLOGIC_VDETECT |
| vdetect_get_frame_nn_info(vd_layer[0].dispbuf); |
| #endif |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| vf_pq_process(vd_layer[0].dispbuf, vpp_scenes, |
| pq_process_debug, vpp_new_frame); |
| #endif |
| if (ai_pq_debug > 0x10) { |
| ai_pq_debug--; |
| if (ai_pq_debug == 0x10) |
| ai_pq_debug = 0; |
| } |
| memcpy(nn_scenes_value, vd_layer[0].dispbuf->nn_value, |
| sizeof(nn_scenes_value)); |
| if (vd_layer[0].dispbuf->vc_private && |
| vd_layer[0].dispbuf->vc_private->flag & VC_FLAG_AI_FACE) { |
| count = vd_layer[0].dispbuf->vc_private->aiface_info->aiface_value_count; |
| for (k = 0; k < count; k++) { |
| ai_face_value.face_value[k] = |
| vd_layer[0].dispbuf->vc_private->aiface_info->face_value[k]; |
| if (debug_flag & DEBUG_FLAG_AI_FACE) { |
| pr_info("vd0:frame_index=%d: i=%d: x=%d; y=%d; w=%d; h=%d; score=%d.\n", |
| vd_layer[0].dispbuf->frame_index, |
| k, |
| ai_face_value.face_value[k].x, |
| ai_face_value.face_value[k].y, |
| ai_face_value.face_value[k].w, |
| ai_face_value.face_value[k].h, |
| ai_face_value.face_value[k].score); |
| } |
| } |
| ai_face_value.face_count_vd0 = count; |
| } |
| } |
| |
| if (vd_layer[1].dispbuf && |
| cur_dev->display_module != C3_DISPLAY_MODULE) { |
| if (vd_layer[1].dispbuf->vc_private && |
| vd_layer[1].dispbuf->vc_private->flag & VC_FLAG_AI_FACE) { |
| count = vd_layer[1].dispbuf->vc_private->aiface_info->aiface_value_count; |
| for (k = 0; k < count; k++) { |
| l = ai_face_value.face_count_vd0 + k; |
| ai_face_value.face_value[l] = |
| vd_layer[1].dispbuf->vc_private->aiface_info->face_value[k]; |
| if (debug_flag & DEBUG_FLAG_AI_FACE) { |
| pr_info("vd1:frame_index=%d: i=%d: x=%d; y=%d; w=%d; h=%d; score=%d.\n", |
| vd_layer[1].dispbuf->frame_index, |
| k, |
| ai_face_value.face_value[l].x, |
| ai_face_value.face_value[l].y, |
| ai_face_value.face_value[l].w, |
| ai_face_value.face_value[l].h, |
| ai_face_value.face_value[l].score); |
| } |
| } |
| ai_face_value.face_count_vd1 = count; |
| } |
| } |
| #endif |
| |
| if (vd_layer[0].dispbuf && |
| (vd_layer[0].dispbuf->type & VIDTYPE_MVC)) |
| vd_layer[0].enable_3d_mode = mode_3d_mvc_enable; |
| else if (process_3d_type) |
| vd_layer[0].enable_3d_mode = mode_3d_enable; |
| else |
| vd_layer[0].enable_3d_mode = mode_3d_disable; |
| /* all frames has been renderred, so reset new frame flag */ |
| vd_layer[0].new_frame = false; |
| return ret; |
| } |
| |
| s32 vdx_render_frame(struct video_layer_s *layer, const struct vinfo_s *vinfo) |
| { |
| struct vpp_frame_par_s *frame_par; |
| u32 zoom_start_y, zoom_end_y; |
| struct vframe_s *dispbuf = NULL; |
| bool force_setting = false; |
| u8 layer_id = 0; |
| int ret = 0; |
| |
| layer_id = layer->layer_id; |
| if (layer_id == 0) |
| return primary_render_frame(layer, vinfo); |
| if (layer->new_vpp_setting) { |
| layer->cur_frame_par = layer->next_frame_par; |
| /* just keep the order variable */ |
| cur_frame_par[layer_id] = layer->cur_frame_par; |
| } |
| if (glayer_info[layer->layer_id].fgrain_force_update) { |
| force_setting = true; |
| glayer_info[layer->layer_id].fgrain_force_update = false; |
| } |
| |
| frame_par = layer->cur_frame_par; |
| |
| if (layer->switch_vf && layer->vf_ext) |
| dispbuf = layer->vf_ext; |
| else |
| dispbuf = layer->dispbuf; |
| |
| /* process cur frame for each vsync */ |
| if (dispbuf) { |
| int need_afbc = |
| (dispbuf->type & VIDTYPE_COMPRESS); |
| int afbc_need_reset = |
| (layer->enabled && need_afbc && |
| !is_afbc_enabled(layer->layer_id)); |
| |
| /*video on && afbc is off && is compress frame.*/ |
| if (layer->new_vpp_setting || afbc_need_reset) |
| vd_set_dcu |
| (layer->layer_id, layer, |
| frame_par, dispbuf); |
| |
| /* for vout change or interlace frame */ |
| proc_vd_vsc_phase_per_vsync |
| (layer, |
| frame_par, dispbuf); |
| } |
| |
| if (!layer->new_vpp_setting && !force_setting) { |
| /* when new frame is toggled but video layer is not on */ |
| /* need always flush pps register before pwr on */ |
| /* to avoid pps coeff lost */ |
| if (frame_par && dispbuf && !is_local_vf(dispbuf) && |
| (!get_video_enabled(layer_id) || |
| get_video_onoff_state(layer_id) == |
| VIDEO_ENABLE_STATE_ON_PENDING)) |
| vd_scaler_setting(layer, &layer->sc_setting); |
| ret = 0; |
| goto render_exit; |
| } |
| |
| if (dispbuf) { |
| /* progressive or decode interlace case height 1:1 */ |
| zoom_start_y = frame_par->VPP_vd_start_lines_; |
| zoom_end_y = frame_par->VPP_vd_end_lines_; |
| if (dispbuf && |
| (dispbuf->type & VIDTYPE_INTERLACE) && |
| (dispbuf->type & VIDTYPE_VIU_FIELD)) { |
| /* vdin interlace frame case height/2 */ |
| zoom_start_y /= 2; |
| zoom_end_y = ((zoom_end_y + 1) >> 1) - 1; |
| } |
| layer->start_x_lines = frame_par->VPP_hd_start_lines_; |
| layer->end_x_lines = frame_par->VPP_hd_end_lines_; |
| layer->start_y_lines = zoom_start_y; |
| layer->end_y_lines = zoom_end_y; |
| config_vd_position |
| (layer, &layer->mif_setting); |
| vd_mif_setting |
| (layer, &layer->mif_setting); |
| fgrain_config(layer, |
| layer->cur_frame_par, |
| &layer->mif_setting, |
| &layer->fgrain_setting, |
| dispbuf); |
| } |
| |
| config_vd_pps |
| (layer, &layer->sc_setting, vinfo); |
| vd_s5_hw_set(layer, dispbuf, frame_par); |
| vd_scaler_setting |
| (layer, &layer->sc_setting); |
| /* update alpha win */ |
| alpha_win_set(layer); |
| config_vd_blend |
| (layer, &layer->bld_setting); |
| vd_blend_setting |
| (layer, &layer->bld_setting); |
| if (layer->vpp_index != VPP0) |
| vppx_vd_blend_setting |
| (layer, &layer->bld_setting); |
| fgrain_setting(layer, |
| &layer->fgrain_setting, |
| dispbuf); |
| layer->new_vpp_setting = false; |
| ret = 1; |
| render_exit: |
| /* check if need blank */ |
| vdx_force_black(layer_id); |
| video_secure_set(layer->vpp_index); |
| |
| vd_clip_setting(layer->vpp_index, |
| layer_id, &vd_layer[layer_id].clip_setting); |
| /* all frames has been renderred, so reset new frame flag */ |
| vd_layer[layer_id].new_frame = false; |
| return ret; |
| } |
| |
| int update_video_recycle_buffer(u8 path_index) |
| { |
| struct vframe_s *rdma_buf = NULL; |
| struct vframe_s *to_put_buf[DISPBUF_TO_PUT_MAX]; |
| int i, j; |
| bool mismatch = true, need_force_recycle = true; |
| int put_cnt = 0; |
| |
| j = path_index; |
| memset(to_put_buf, 0, sizeof(to_put_buf)); |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| /* after one vsync processing, should be same */ |
| if (cur_rdma_buf[j] != cur_dispbuf[j] && |
| cur_dispbuf[j] != &vf_local[j]) { |
| pr_err("expection: video%d rdma_buf:%p, dispbuf:%p!\n", |
| j, |
| cur_rdma_buf[j], cur_dispbuf[j]); |
| return -1; |
| } |
| for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) |
| if (dispbuf_to_put[j][i] && |
| (dispbuf_to_put[j][i]->flag & VFRAME_FLAG_DI_PW_VFM) && |
| IS_DI_POSTWRTIE(dispbuf_to_put[j][i]->type)) |
| to_put_buf[put_cnt++] = dispbuf_to_put[j][i]; |
| #endif |
| |
| if (cur_dispbuf[j] != &vf_local[j]) |
| rdma_buf = cur_dispbuf[j]; |
| |
| if (rdma_buf && |
| (!(rdma_buf->flag & VFRAME_FLAG_DI_PW_VFM) || |
| !IS_DI_POSTWRTIE(rdma_buf->type))) |
| rdma_buf = NULL; |
| |
| if (recycle_cnt[j] && |
| (put_cnt > 0 || rdma_buf)) { |
| for (i = 0; i < recycle_cnt[j]; i++) { |
| if (recycle_buf[j][i] == rdma_buf) |
| need_force_recycle = false; |
| } |
| if (need_force_recycle) |
| return -EAGAIN; |
| |
| pr_err("expection: video%d recycle_cnt:%d, put_cnt:%d, recycle_buf:%p-%p, to_put:%p, rdma_buf:%p!\n", |
| j, |
| recycle_cnt[j], put_cnt, |
| recycle_buf[j][0], recycle_buf[j][1], |
| to_put_buf[0], rdma_buf); |
| return -1; |
| } |
| if (!recycle_cnt[j]) { |
| for (i = 0; i < DISPBUF_TO_PUT_MAX + 1; i++) |
| recycle_buf[j][i] = NULL; |
| |
| for (i = 0; i < put_cnt; i++) { |
| if (to_put_buf[i]) |
| recycle_buf[j][recycle_cnt[j]++] = |
| to_put_buf[i]; |
| if (rdma_buf && rdma_buf == to_put_buf[i]) |
| mismatch = false; |
| } |
| if (rdma_buf && mismatch) |
| recycle_buf[j][recycle_cnt[j]++] = rdma_buf; |
| pr_debug("video%d need recycle %d new buffers: %p, %p, %p, %p, put_cnt:%d, rdma_buf:%p\n", |
| j, |
| recycle_cnt[j], |
| recycle_buf[j][0], recycle_buf[j][1], |
| recycle_buf[j][2], recycle_buf[j][3], |
| put_cnt, rdma_buf); |
| } else { |
| pr_debug("video%d need recycle %d remained buffers: %p, %p, %p, %p\n", |
| j, |
| recycle_cnt[j], |
| recycle_buf[j][0], recycle_buf[j][1], |
| recycle_buf[j][2], recycle_buf[j][3]); |
| } |
| return 0; |
| } |
| |
| void set_alpha_scpxn(struct video_layer_s *layer, |
| struct composer_info_t *composer_info) |
| { |
| struct pip_alpha_scpxn_s alpha_win; |
| static struct pip_alpha_scpxn_s last_alpha_win; |
| int win_num = 0; |
| int win_en = 0; |
| static int last_alpha_win_en; |
| int i, update = 0; |
| |
| memset(&alpha_win, 0, sizeof(struct pip_alpha_scpxn_s)); |
| |
| if (composer_info) { |
| win_num = composer_info->count; |
| if (win_num >= MAX_COMPOSER_COUNT || win_num >= MAX_PIP_WINDOW) { |
| pr_info("%s, win_num%d is wrong\n", __func__, win_num); |
| return; |
| } |
| for (i = 0; i < win_num; i++) { |
| alpha_win.scpxn_bgn_h[i] = composer_info->axis[i][0]; |
| alpha_win.scpxn_end_h[i] = composer_info->axis[i][2]; |
| alpha_win.scpxn_bgn_v[i] = composer_info->axis[i][1]; |
| alpha_win.scpxn_end_v[i] = composer_info->axis[i][3]; |
| win_en |= 1 << i; |
| } |
| } |
| /* check win num first, if changed update */ |
| if (last_alpha_win_en != win_en) { |
| update = 1; |
| } else { |
| /* check win set, if changed update */ |
| for (i = 0; i < MAX_PIP_WINDOW; i++) { |
| if (alpha_win.scpxn_bgn_h[i] != last_alpha_win.scpxn_bgn_h[i] || |
| alpha_win.scpxn_end_h[i] != last_alpha_win.scpxn_end_h[i] || |
| alpha_win.scpxn_bgn_v[i] != last_alpha_win.scpxn_bgn_v[i] || |
| alpha_win.scpxn_end_v[i] != last_alpha_win.scpxn_end_v[i]) { |
| update = 1; |
| break; |
| } |
| } |
| } |
| layer->alpha_win_en = win_en; |
| last_alpha_win_en = win_en; |
| memcpy(&layer->alpha_win, &alpha_win, |
| sizeof(struct pip_alpha_scpxn_s)); |
| memcpy(&last_alpha_win, &alpha_win, |
| sizeof(struct pip_alpha_scpxn_s)); |
| if (update) { |
| if (layer->layer_id == 0) { |
| vd_layer[0].property_changed = true; |
| } else if (layer->layer_id == 1) { |
| if (vd_layer[1].vpp_index == VPP0) |
| vd_layer[1].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } else if (layer->layer_id == 2) { |
| if (vd_layer[2].vpp_index == VPP0) |
| vd_layer[2].property_changed = true; |
| else |
| update_vppx_property(layer->layer_id); |
| } |
| } |
| } |
| |
| static void blend_reg_conflict_detect(void) |
| { |
| u32 r1, r2, r3; |
| u32 blend_en = 0; |
| |
| if (cur_dev->display_module == C3_DISPLAY_MODULE) |
| return; |
| if (glayer_info[0].afbc_support) { |
| if (!legacy_vpp) { |
| r1 = READ_VCBUS_REG(VD1_BLEND_SRC_CTRL); |
| if (r1 & 0xfff) |
| blend_en = 1; |
| } else { |
| r1 = READ_VCBUS_REG(VPP_MISC); |
| if (r1 & VPP_VD1_POSTBLEND) |
| blend_en = 1; |
| } |
| r2 = READ_VCBUS_REG(vd_layer[0].vd_afbc_reg.afbc_enable); |
| r3 = READ_VCBUS_REG(vd_layer[0].vd_mif_reg.vd_if0_gen_reg); |
| if (r2 == 0 && r3 == 0 && blend_en) |
| blend_conflict_cnt++; |
| } else { |
| return; |
| } |
| |
| if (glayer_info[1].afbc_support) { |
| blend_en = 0; |
| if (!legacy_vpp) { |
| r1 = READ_VCBUS_REG(VD2_BLEND_SRC_CTRL); |
| if (r1 & 0xfff) |
| blend_en = 1; |
| } else { |
| r1 = READ_VCBUS_REG(VPP_MISC); |
| if (r1 & VPP_VD2_POSTBLEND) |
| blend_en = 1; |
| } |
| r2 = READ_VCBUS_REG(vd_layer[1].vd_afbc_reg.afbc_enable); |
| r3 = READ_VCBUS_REG(vd_layer[1].vd_mif_reg.vd_if0_gen_reg); |
| if (r2 == 0 && r3 == 0 && blend_en) |
| blend_conflict_cnt++; |
| } else { |
| return; |
| } |
| |
| if (glayer_info[2].afbc_support) { |
| blend_en = 0; |
| if (cur_dev->max_vd_layers == 3) { |
| r1 = READ_VCBUS_REG(VD3_BLEND_SRC_CTRL); |
| if (r1 & 0xfff) |
| blend_en = 1; |
| r2 = READ_VCBUS_REG(vd_layer[2].vd_afbc_reg.afbc_enable); |
| r3 = READ_VCBUS_REG(vd_layer[2].vd_mif_reg.vd_if0_gen_reg); |
| if (r2 == 0 && r3 == 0 && blend_en) |
| blend_conflict_cnt++; |
| } |
| } else { |
| return; |
| } |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM |
| void amvecm_process(struct path_id_s *path_id, |
| struct video_recv_s *p_gvideo_recv, |
| struct vframe_s *new_frame) |
| { |
| u32 vpp_index = VPP0; |
| |
| if (path_id->vd1_path_id == p_gvideo_recv->path_id) |
| amvecm_on_vs |
| ((p_gvideo_recv->cur_buf != |
| &p_gvideo_recv->local_buf) |
| ? p_gvideo_recv->cur_buf : NULL, |
| new_frame, |
| CSC_FLAG_CHECK_OUTPUT, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| VD1_PATH, |
| vd_layer[0].vpp_index); |
| else if (path_id->vd2_path_id == p_gvideo_recv->path_id) { |
| if (p_gvideo_recv->vpp_id != VPP0) |
| vpp_index = vd_layer_vpp[p_gvideo_recv->vpp_id - VPP1].vpp_index; |
| else |
| vpp_index = vd_layer[1].vpp_index; |
| amvecm_on_vs |
| ((p_gvideo_recv->cur_buf != |
| &p_gvideo_recv->local_buf) |
| ? p_gvideo_recv->cur_buf : NULL, |
| new_frame, |
| CSC_FLAG_CHECK_OUTPUT, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| VD2_PATH, |
| vpp_index); |
| } else if (path_id->vd3_path_id == p_gvideo_recv->path_id) { |
| if (p_gvideo_recv->vpp_id != VPP0) |
| vpp_index = vd_layer_vpp[p_gvideo_recv->vpp_id - VPP1].vpp_index; |
| else |
| vpp_index = vd_layer[2].vpp_index; |
| amvecm_on_vs |
| ((p_gvideo_recv->cur_buf != |
| &p_gvideo_recv->local_buf) |
| ? p_gvideo_recv->cur_buf : NULL, |
| new_frame, |
| CSC_FLAG_CHECK_OUTPUT, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| VD3_PATH, |
| vpp_index); |
| } |
| } |
| #endif |
| |
| /*tunnel mode, map dv instance when creating amvideo/videopip path*/ |
| inline bool is_tunnel_mode(const char *receiver_name) |
| { |
| char *provider_name; |
| |
| provider_name = vf_get_provider_name(receiver_name); |
| while (provider_name) { |
| if (!vf_get_provider_name(provider_name)) |
| break; |
| provider_name = |
| vf_get_provider_name(provider_name); |
| } |
| if (provider_name && |
| (strstr(provider_name, "dv_vdin") || |
| strstr(provider_name, "vdin0") || |
| strstr(provider_name, "decoder") || |
| strstr(provider_name, "vdec.h265") || |
| strstr(provider_name, "vdec.h264") || |
| strstr(provider_name, "dvbldec") || |
| strstr(provider_name, "dvbldec2") || |
| strstr(provider_name, "vdec.av1") || |
| strstr(provider_name, "vdec.vp9"))) { |
| return true; |
| } |
| return false; |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| static void set_dv_provide_name(void) |
| { |
| s32 vd1_path_id = glayer_info[0].display_path_id; |
| s32 vd2_path_id = glayer_info[1].display_path_id; |
| |
| if (is_amdv_enable()) { |
| if (is_tunnel_mode(RECEIVER_NAME) || is_tunnel_mode(RECEIVERPIP_NAME)) { |
| char *provider_name = NULL; |
| |
| if (vd1_path_id == VFM_PATH_PIP || vd2_path_id == VFM_PATH_PIP) { |
| provider_name = vf_get_provider_name(RECEIVERPIP_NAME); |
| while (provider_name) { |
| if (!vf_get_provider_name(provider_name)) |
| break; |
| provider_name = |
| vf_get_provider_name(provider_name); |
| } |
| if (provider_name) |
| amdv_set_provider(provider_name, VD2_PATH); |
| else |
| amdv_set_provider(dv_provider[1], VD2_PATH); |
| } |
| if (vd1_path_id == VFM_PATH_AMVIDEO || vd2_path_id == VFM_PATH_AMVIDEO) { |
| provider_name = vf_get_provider_name(RECEIVER_NAME); |
| while (provider_name) { |
| if (!vf_get_provider_name(provider_name)) |
| break; |
| provider_name = |
| vf_get_provider_name(provider_name); |
| } |
| if (provider_name) |
| amdv_set_provider(provider_name, VD1_PATH); |
| else |
| amdv_set_provider(dv_provider[0], VD1_PATH); |
| } |
| } else { |
| amdv_set_provider(dv_provider[0], VD1_PATH); |
| amdv_set_provider(dv_provider[1], VD2_PATH); |
| } |
| } |
| } |
| #endif |
| |
| static void dmc_adjust_process(struct vframe_s *vf) |
| { |
| #ifndef CONFIG_AMLOGIC_REMOVE_OLD |
| if (is_meson_txlx_cpu() && dmc_adjust) { |
| bool force_adjust = false; |
| u32 vf_width = 0, vf_height = 0; |
| struct vframe_s *chk_vf; |
| |
| chk_vf = vf ? vf : cur_dispbuf[0]; |
| if (chk_vf) |
| force_adjust = |
| ((chk_vf->type & VIDTYPE_VIU_444) || |
| (chk_vf->type & VIDTYPE_RGB_444)) |
| ? true : false; |
| if (chk_vf) { |
| if (cur_frame_par[0] && |
| cur_frame_par[0]->nocomp) { |
| vf_width = chk_vf->width; |
| vf_height = chk_vf->height; |
| } else if ((chk_vf->type & VIDTYPE_COMPRESS) && |
| cur_frame_par[0] && |
| cur_frame_par[0]->vscale_skip_count) { |
| vf_width = chk_vf->compWidth; |
| vf_height = chk_vf->compHeight; |
| } else { |
| vf_width = chk_vf->width; |
| vf_height = chk_vf->height; |
| } |
| dmc_adjust_for_mali_vpu |
| (vf_width, |
| vf_height, |
| force_adjust); |
| } else { |
| dmc_adjust_for_mali_vpu |
| (0, 0, force_adjust); |
| } |
| } |
| #endif |
| } |
| |
| static void check_src_fmt_change(void) |
| { |
| enum vframe_signal_fmt_e fmt; |
| |
| fmt = (enum vframe_signal_fmt_e)atomic_read(&primary_src_fmt); |
| if (fmt != atomic_read(&cur_primary_src_fmt)) { |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) { |
| char *old_str = NULL, *new_str = NULL; |
| enum vframe_signal_fmt_e old_fmt; |
| |
| old_fmt = (enum vframe_signal_fmt_e) |
| atomic_read(&cur_primary_src_fmt); |
| if (old_fmt != VFRAME_SIGNAL_FMT_INVALID) |
| old_str = (char *)src_fmt_str[old_fmt]; |
| if (fmt != VFRAME_SIGNAL_FMT_INVALID) |
| new_str = (char *)src_fmt_str[fmt]; |
| pr_info("VD1 src fmt changed: %s->%s.\n", |
| old_str ? old_str : "invalid", |
| new_str ? new_str : "invalid"); |
| } |
| atomic_set(&cur_primary_src_fmt, fmt); |
| video_prop_status |= VIDEO_PROP_CHANGE_FMT; |
| update_primary_fmt_event(); |
| } |
| } |
| |
| static void set_cur_line_info(u8 index) |
| { |
| struct cur_line_info_t *cur_line_info = &g_cur_line_info[index]; |
| struct timeval start; |
| |
| do_gettimeofday(&start); |
| cur_line_info->enc_line_start = get_cur_enc_line(); |
| cur_line_info->enc_num_start = get_cur_enc_num(); |
| cur_line_info->start = start; |
| cur_line_info->end1 = start; |
| cur_line_info->end2 = start; |
| cur_line_info->end3 = start; |
| cur_line_info->end4 = start; |
| } |
| |
| struct cur_line_info_t *get_cur_line_info(u8 index) |
| { |
| return &g_cur_line_info[index]; |
| } |
| |
| u32 get_enc_num_start(u8 index) |
| { |
| return g_cur_line_info[index].enc_num_start; |
| } |
| |
| ulong get_enc_time_start(u8 index) |
| { |
| struct timeval *t = &g_cur_line_info[index].start; |
| |
| return (t->tv_sec * 1000000 + t->tv_usec); |
| } |
| |
| static inline void trace_performance(struct cur_line_info_t *cur_line_info, |
| int cur_enc_line) |
| { |
| u32 sync_duration; |
| struct vinfo_s *video_info; |
| unsigned long time_use1 = 0; |
| unsigned long time_use2 = 0; |
| unsigned long time_use3 = 0; |
| unsigned long time_use4 = 0; |
| unsigned long time_use5 = 0; |
| int enc_line_start; |
| struct timeval end; |
| struct timeval *start; |
| struct timeval *end1; |
| struct timeval *end2; |
| struct timeval *end3; |
| struct timeval *end4; |
| |
| enc_line_start = cur_line_info->enc_line_start; |
| start = &cur_line_info->start; |
| end1 = &cur_line_info->end1; |
| end2 = &cur_line_info->end2; |
| end3 = &cur_line_info->end3; |
| end4 = &cur_line_info->end4; |
| |
| do_gettimeofday(&end); |
| time_use1 = (end1->tv_sec - start->tv_sec) * 1000000 + |
| (end1->tv_usec - start->tv_usec); |
| time_use2 = (end2->tv_sec - start->tv_sec) * 1000000 + |
| (end2->tv_usec - start->tv_usec); |
| time_use3 = (end3->tv_sec - start->tv_sec) * 1000000 + |
| (end3->tv_usec - start->tv_usec); |
| time_use4 = (end4->tv_sec - start->tv_sec) * 1000000 + |
| (end4->tv_usec - start->tv_usec); |
| time_use5 = (end.tv_sec - start->tv_sec) * 1000000 + |
| (end.tv_usec - start->tv_usec); |
| |
| video_info = get_current_vinfo(); |
| if (video_info && video_info->sync_duration_num) |
| sync_duration = video_info->sync_duration_den * 1000 / |
| video_info->sync_duration_num; |
| else |
| sync_duration = 16; |
| |
| if (cur_enc_line < enc_line_start || time_use5 > sync_duration * 1000) { |
| over_field = true; |
| ++over_field_case1_cnt; |
| if (performance_debug & DEBUG_FLAG_OVER_VSYNC) |
| pr_info("long vsync enc line: %4d/4%d, time %ld us\n", |
| enc_line_start, cur_enc_line, time_use5); |
| } |
| |
| vpp_trace_timeinfo(time_use1, time_use2, time_use3, |
| time_use4, time_use5, sync_duration * 1000); |
| |
| if (performance_debug & DEBUG_FLAG_VSYNC_PROCESS_TIME) { |
| pr_info("vsync time: %ld %ld %ld %ld %ld us\n", |
| time_use1, time_use2, time_use3, time_use4, time_use5); |
| pr_info("vsync enc line: %4d/4%d, over_field %d, count %d %d\n", |
| enc_line_start, cur_enc_line, |
| over_field, over_field_case1_cnt, over_field_case2_cnt); |
| } |
| } |
| |
| static void over_field_info_record(void) |
| { |
| bool valid_mode = false; |
| u32 timeinfo_th = 0; |
| u32 enc_num = get_cur_enc_num(); |
| struct cur_line_info_t *cur_line_info = get_cur_line_info(0); |
| struct timeval *start; |
| |
| start = &cur_line_info->start; |
| if (vinfo && |
| (vinfo->mode == VMODE_HDMI || |
| vinfo->mode == VMODE_LCD || |
| vinfo->mode == VMODE_CVBS)) { |
| valid_mode = true; |
| if (vinfo->sync_duration_num) { |
| timeinfo_th = vinfo->sync_duration_den * 1000000 / |
| vinfo->sync_duration_num; |
| /* set as 1.5 duration */ |
| timeinfo_th = (timeinfo_th * 3) >> 1; |
| } |
| } |
| /* TODO: need check each layer by new frame flag */ |
| if (!over_field && valid_mode && timeinfo_th) { |
| u32 state = atomic_read(&cur_over_field_state); |
| |
| if (state == OVER_FIELD_RDMA_READY || |
| state == OVER_FIELD_NORMAL) { |
| ulong cur_timeinfo = start->tv_sec * 1000000 + |
| start->tv_usec; |
| |
| if (enc_num == config_vsync_num && |
| cur_timeinfo < config_timeinfo + timeinfo_th) |
| over_field = true; |
| } else if (state == OVER_FIELD_NEW_VF) { |
| over_field = true; |
| } |
| if (over_field) |
| over_field_case2_cnt++; |
| } |
| update_over_field_states(OVER_FIELD_NORMAL, !valid_mode ? true : false); |
| if (atomic_read(&cur_over_field_state) == OVER_FIELD_NEW_VF) { |
| always_new_vf_cnt++; |
| if (always_new_vf_cnt > 5) { |
| update_over_field_states(OVER_FIELD_NORMAL, true); |
| pr_info("Over field state is always as new_vf. Need reset it.\n"); |
| always_new_vf_cnt = 0; |
| } |
| } else { |
| always_new_vf_cnt = 0; |
| } |
| vpp_trace_field_state("VSYNC-START", |
| atomic_read(&cur_over_field_state), |
| atomic_read(&cur_over_field_state), |
| over_field ? 1 : 0, |
| config_vsync_num, enc_num); |
| } |
| |
| static bool check_sideband_type(struct vframe_s *vf, bool *need_force_black) |
| { |
| if (!vf) |
| return false; |
| |
| pr_info("vpp: sideband vf:%d, surface:%d; type: vf:%d, tvinput:%d\n", |
| vf->sidebind_type, |
| glayer_info[0].sideband_type, |
| vf->source_type, |
| tvin_source_type); |
| |
| if (vf->sidebind_type != 0) { |
| if (vf->sidebind_type == glayer_info[0].sideband_type) { |
| /*dtv -> ATV, sidebind is ATV , but vfm is dtv, can not disp*/ |
| if (glayer_info[0].sideband_type == 1 && |
| tvin_source_type == TVIN_SOURCE_TYPE_VDIN && |
| vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) { |
| pr_info("can not disp now\n"); |
| *need_force_black = true; |
| return false; |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } else { |
| return true; |
| } |
| } |
| |
| static void vd_dispbuf_to_put(int layer_id) |
| { |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| int i; |
| |
| /* if mode is video_process_in_thread, |
| * toggle/swap/render in thread and put_buf in vsync isr, skip this func. |
| */ |
| if (is_video_process_in_thread()) |
| return; |
| |
| if (over_field) |
| return; |
| |
| for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) { |
| if (dispbuf_to_put[layer_id][i]) { |
| dispbuf_to_put[layer_id][i]->rendered = true; |
| if (!video_vf_put(layer_id, dispbuf_to_put[layer_id][i])) { |
| dispbuf_to_put[layer_id][i] = NULL; |
| dispbuf_to_put_num[layer_id]--; |
| } |
| } |
| } |
| #endif |
| } |
| |
| static void vd_dispbuf_init(u8 layer_id) |
| { |
| int i; |
| u8 path_index = 0; |
| |
| if (layer_id >= MAX_VD_LAYER) |
| return; |
| i = layer_id; |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| struct vframe_s *_cur_dispbuf; |
| struct vframe_s *_local_vf; |
| int j; |
| |
| _cur_dispbuf = cur_dispbuf[i]; |
| _local_vf = &vf_local[i]; |
| if (recycle_cnt[i] > 0 && _cur_dispbuf != _local_vf) { |
| for (j = 0; j < recycle_cnt[i]; j++) { |
| if ((recycle_buf[i][j] && |
| _cur_dispbuf != recycle_buf[i][j]) && |
| (recycle_buf[i][j]->flag & VFRAME_FLAG_DI_PW_VFM)) { |
| if (i == 0) |
| di_release_count++; |
| dim_post_keep_cmd_release2(recycle_buf[i][j]); |
| } else if (recycle_buf[i][j] && |
| _cur_dispbuf == recycle_buf[i][j]) { |
| pr_err("recycle %d di buffer conflict, recycle vf:%p\n", |
| i, recycle_buf[i][j]); |
| } |
| recycle_buf[i][j] = NULL; |
| } |
| recycle_cnt[i] = 0; |
| } |
| #endif |
| for (path_index = 0; path_index < MAX_VD_LAYER; path_index++) { |
| if (vd_layer[i].dispbuf_mapping == &cur_dispbuf[path_index] && |
| (cur_dispbuf[path_index] == &vf_local[path_index] || |
| !cur_dispbuf[path_index]) && |
| vd_layer[i].dispbuf != cur_dispbuf[path_index]) |
| vd_layer[i].dispbuf = cur_dispbuf[path_index]; |
| } |
| for (path_index = 0; path_index < MAX_VD_LAYER; path_index++) { |
| if (gvideo_recv[path_index] && |
| vd_layer[i].dispbuf_mapping == &gvideo_recv[path_index]->cur_buf && |
| (gvideo_recv[path_index]->cur_buf == &gvideo_recv[path_index]->local_buf || |
| !gvideo_recv[path_index]->cur_buf) && |
| vd_layer[i].dispbuf != gvideo_recv[path_index]->cur_buf) |
| vd_layer[i].dispbuf = gvideo_recv[path_index]->cur_buf; |
| } |
| } |
| |
| void put_buffer_proc(void) |
| { |
| int i; |
| |
| for (i = 0; i < 3; i++) { |
| if (gvideo_recv[i]) |
| gvideo_recv[i]->func->early_proc(gvideo_recv[i], 0); |
| } |
| } |
| |
| static inline int recvx_early_proc(u8 path_index) |
| { |
| if (atomic_read(&video_unreg_flag)) |
| return -1; |
| |
| check_src_fmt_change(); |
| if (!get_lowlatency_mode()) { |
| if (gvideo_recv[path_index]) { |
| /* normal mode: true; lowlatency mode: false */ |
| gvideo_recv[path_index]->irq_mode = true; |
| gvideo_recv[path_index]->func->early_proc(gvideo_recv[path_index], //0); |
| over_field ? 1 : 0); |
| } |
| } |
| return 0; |
| } |
| |
| static int amvideo_early_proc(u8 layer_id) |
| { |
| int enc_line; |
| int hold_line; |
| struct vframe_s *vf; |
| struct vframe_s *vf_tmp; |
| s32 vd1_path_id = glayer_info[0].display_path_id; |
| struct cur_line_info_t *cur_line_info = get_cur_line_info(0); |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| u16 line = glayer_info[0].layer_top; |
| #endif |
| |
| vd_dispbuf_to_put(layer_id); |
| get_count_pip[0] = 0; |
| |
| if (!hist_test_flag && cur_dispbuf[0] == &hist_test_vf) |
| cur_dispbuf[0] = NULL; |
| |
| hold_line = calc_hold_line(); |
| do_frame_detect(); |
| |
| frame_drop_process(); |
| |
| vf = video_vf_peek(0); |
| |
| if (!vf) |
| vf_tmp = cur_dispbuf[0]; |
| else |
| vf_tmp = vf; |
| |
| if (vf_tmp) { |
| if (glayer_info[0].display_path_id == VFM_PATH_AUTO) { |
| if (check_sideband_type(vf_tmp, &need_force_black)) { |
| pr_info("VID: path_id %d -> %d\n", |
| glayer_info[0].display_path_id, |
| VFM_PATH_AMVIDEO); |
| glayer_info[0].display_path_id = |
| VFM_PATH_AMVIDEO; |
| vd1_path_id = glayer_info[0].display_path_id; |
| } else if (glayer_info[0].sideband_type != -1) |
| pr_info("vf->sideband_type =%d,layertype=%d\n", |
| vf_tmp->sidebind_type, |
| glayer_info[0].sideband_type); |
| } |
| } |
| |
| /* vout mode detection under old tunnel mode */ |
| if ((vf) && ((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0)) { |
| if (strcmp(old_vmode, new_vmode)) { |
| vd_layer[0].property_changed = true; |
| vd_layer[1].property_changed = true; |
| vd_layer[2].property_changed = true; |
| pr_debug("detect vout mode change!!!!!!!!!!!!\n"); |
| strcpy(old_vmode, new_vmode); |
| } |
| } |
| |
| /*the first/second vf di maybe bypass, So we need to calculate the |
| *first three frames |
| */ |
| if (display_frame_count < 3 && vf && |
| (vf->source_type == VFRAME_SOURCE_TYPE_HDMI || |
| vf->source_type == VFRAME_SOURCE_TYPE_CVBS || |
| vf->source_type == VFRAME_SOURCE_TYPE_TUNER)) |
| hdmi_in_delay_maxmin_old(vf); |
| |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| if (cur_frame_par[0] && |
| (vd1_path_id == VFM_PATH_AMVIDEO || |
| vd1_path_id == VFM_PATH_DEF)) { |
| /*need call every vsync*/ |
| if (vf_tmp) |
| frame_lock_process(vf_tmp, cur_frame_par[0], line); |
| else |
| frame_lock_process(NULL, cur_frame_par[0], line); |
| } |
| #endif |
| |
| if (performance_debug & DEBUG_FLAG_VSYNC_PROCESS_TIME) |
| do_gettimeofday(&cur_line_info->end1); |
| enc_line = get_cur_enc_line(); |
| if (enc_line > vsync_enter_line_max) |
| vsync_enter_line_max = enc_line; |
| |
| dmc_adjust_process(vf); |
| |
| if (to_notify_trick_wait) { |
| atomic_set(&trickmode_framedone, 1); |
| video_notify_flag |= VIDEO_NOTIFY_TRICK_WAIT; |
| to_notify_trick_wait = false; |
| return -1; |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| /* check video frame before VECM process */ |
| if (is_amdv_enable() && vf && |
| (vd1_path_id == VFM_PATH_AMVIDEO || |
| vd1_path_id == VFM_PATH_DEF || |
| vd1_path_id == VFM_PATH_AUTO)) { |
| amdv_check_mvc(vf); |
| amdv_check_hdr10(vf); |
| amdv_check_hdr10plus(vf); |
| amdv_check_hlg(vf); |
| amdv_check_primesl(vf); |
| amdv_check_cuva(vf); |
| } |
| #endif |
| |
| pts_process(); |
| if (atomic_read(&video_unreg_flag)) |
| return -1; |
| |
| if (atomic_read(&video_pause_flag) && |
| !(vd_layer[0].global_output == 1 && |
| vd_layer[0].enabled != vd_layer[0].enabled_status_saved)) |
| return -1; |
| |
| check_src_fmt_change(); |
| return 0; |
| } |
| |
| static int pipx_early_proc(u8 path_index) |
| { |
| vd_dispbuf_to_put(path_index); |
| get_count_pip[path_index] = 0; |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| /* for pip */ |
| if (path_index == 1) |
| set_dv_provide_name(); |
| #endif |
| if (atomic_read(&video_unreg_flag)) |
| return -1; |
| //check_src_fmt_change(); |
| return 0; |
| } |
| |
| static int video_early_proc(u8 layer_id, u8 fake_layer_id) |
| { |
| u8 func_id = 0, path_index = 0; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (is_amdv_on() && layer_id == 0) |
| print_dv_ro(); |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| if (cur_dev->vsync_2to1_enable && |
| layer_id == 0 && |
| vsync_count_start) { |
| /* not prevsync not handle */ |
| if (!frc_drv_get_1st_frm()) |
| return 0; |
| } |
| #endif |
| if (layer_id == 0xff) |
| func_id = vd_fake_func[fake_layer_id].fake_func_id; |
| else if (layer_id < MAX_VD_LAYER) |
| func_id = vd_layer[layer_id].func_path_id; |
| switch (func_id) { |
| case AMVIDEO: |
| return amvideo_early_proc(AMVIDEO); |
| case PIP1: |
| case PIP2: |
| path_index = func_id - AMVIDEO; |
| return pipx_early_proc(path_index); |
| case RENDER0: |
| case RENDER1: |
| case RENDER2: |
| path_index = func_id - RENDER0; |
| return recvx_early_proc(path_index); |
| default: |
| break; |
| } |
| return 0; |
| } |
| |
| static int pipx_late_proc(u8 path_index) |
| { |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| cur_rdma_buf[path_index] = cur_dispbuf[path_index]; |
| #endif |
| if (debug_flag & DEBUG_FLAG_GET_COUNT) |
| pr_info("pip%d=%d\n", |
| path_index, |
| get_count_pip[path_index]); |
| return 0; |
| } |
| |
| static int video_late_proc(u8 layer_id, u8 fake_layer_id) |
| { |
| u8 func_id = 0; |
| u8 path_index = 0; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| if (cur_dev->vsync_2to1_enable && |
| layer_id == 0 && |
| vsync_count_start) { |
| /* not prevsync not handle */ |
| if (!frc_drv_get_1st_frm()) |
| return 0; |
| } |
| #endif |
| if (layer_id == 0xff) |
| func_id = vd_fake_func[fake_layer_id].fake_func_id; |
| else if (layer_id < MAX_VD_LAYER) |
| func_id = vd_layer[layer_id].func_path_id; |
| switch (func_id) { |
| case AMVIDEO: |
| case PIP1: |
| case PIP2: |
| pipx_late_proc(func_id - AMVIDEO); |
| break; |
| case RENDER0: |
| case RENDER1: |
| case RENDER2: |
| path_index = func_id - RENDER0; |
| if (gvideo_recv[path_index] && path_index < MAX_VD_LAYER) |
| gvideo_recv[path_index]->func->late_proc(gvideo_recv[path_index]); |
| break; |
| default: |
| break; |
| } |
| return 0; |
| } |
| |
| static int vdx_misc_early_proc(u8 layer_id, |
| bool rdma_enable, |
| bool rdma_enable_pre) |
| { |
| bool pre_vsync_notify = false; |
| bool post_vsync_notify = false; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| if (cur_dev->vsync_2to1_enable && |
| layer_id == 0 && |
| vsync_count_start) { |
| /* not prevsync not handle */ |
| if (!frc_drv_get_1st_frm()) |
| return 0; |
| } |
| #endif |
| /* prevsync + postvsync case */ |
| if (cur_dev->pre_vsync_enable) { |
| if (layer_id == 0) { |
| u32 pts_inc_scale_base = 0; |
| |
| if (frc_n2m_worked()) |
| pts_inc_scale_base = vsync_pts_inc_scale_base / 2; |
| else |
| pts_inc_scale_base = vsync_pts_inc_scale_base; |
| #ifdef CONFIG_AMLOGIC_VIDEO_COMPOSER |
| vsync_notify_video_composer(layer_id, |
| vsync_pts_inc_scale, |
| pts_inc_scale_base); |
| #endif |
| #ifdef CONFIG_AMLOGIC_VIDEOQUEUE |
| vsync_notify_videoqueue(layer_id, |
| vsync_pts_inc_scale, |
| pts_inc_scale_base); |
| #endif |
| pre_vsync_notify = true; |
| } |
| |
| if (layer_id != 0 && !post_vsync_notify) { |
| #ifdef CONFIG_AMLOGIC_VIDEO_COMPOSER |
| vsync_notify_video_composer(layer_id, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base); |
| #endif |
| #ifdef CONFIG_AMLOGIC_VIDEOQUEUE |
| vsync_notify_videoqueue(layer_id, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base); |
| #endif |
| post_vsync_notify = true; |
| } |
| } else { |
| if (cur_dev->vsync_2to1_enable) { |
| /* postvsync case for n2m(only for vd1) */ |
| if (layer_id == 0 && frc_n2m_worked()) { |
| #ifdef CONFIG_AMLOGIC_VIDEO_COMPOSER |
| vsync_notify_video_composer(layer_id, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base / 2); |
| #endif |
| #ifdef CONFIG_AMLOGIC_VIDEOQUEUE |
| vsync_notify_videoqueue(layer_id, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base / 2); |
| #endif |
| |
| } else { |
| #ifdef CONFIG_AMLOGIC_VIDEO_COMPOSER |
| vsync_notify_video_composer(layer_id, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base); |
| #endif |
| #ifdef CONFIG_AMLOGIC_VIDEOQUEUE |
| vsync_notify_videoqueue(layer_id, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base); |
| #endif |
| } |
| } else { |
| /* always postvsync case for no n2m */ |
| #ifdef CONFIG_AMLOGIC_VIDEO_COMPOSER |
| vsync_notify_video_composer(layer_id, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base); |
| #endif |
| #ifdef CONFIG_AMLOGIC_VIDEOQUEUE |
| vsync_notify_videoqueue(layer_id, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base); |
| #endif |
| post_vsync_notify = true; |
| } |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| if (rdma_enable) { |
| vd_layer[layer_id].cur_canvas_id = |
| vd_layer[layer_id].next_canvas_id; |
| } else { |
| if (rdma_enable_pre) { |
| /* force set state as normal without check */ |
| update_over_field_states(OVER_FIELD_NORMAL, true); |
| return -1; |
| } |
| vd_layer[layer_id].cur_canvas_id = 0; |
| vd_layer[layer_id].next_canvas_id = 1; |
| } |
| #endif |
| return 0; |
| } |
| |
| static void vdx_misc_late_proc(u8 layer_id) |
| { |
| if (layer_id == 0) { |
| /* prevsync + postvsync case */ |
| if (cur_dev->pre_vsync_enable) { |
| u32 pts_inc_scale_base = 0; |
| u32 frc_ratio = 10; |
| |
| frc_ratio = frc_get_n2m_ratio(); |
| if (frc_n2m_worked()) |
| pts_inc_scale_base = vsync_pts_inc_scale_base * 10 / frc_ratio; |
| else |
| pts_inc_scale_base = vsync_pts_inc_scale_base; |
| #ifdef CONFIG_AMLOGIC_VIDEOQUEUE |
| videoqueue_pcrscr_update(vsync_pts_inc_scale, |
| pts_inc_scale_base); |
| #endif |
| } else { |
| #ifdef CONFIG_AMLOGIC_VIDEOQUEUE |
| videoqueue_pcrscr_update(vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base); |
| #endif |
| } |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| if (cur_dev->vsync_2to1_enable && |
| layer_id == 0 && |
| vsync_count_start) { |
| /* not prevsync not handle */ |
| if (!frc_drv_get_1st_frm()) |
| return; |
| } |
| #endif |
| if (layer_id == 0) { |
| if (vd_layer[0].dispbuf && |
| (vd_layer[0].dispbuf->type & VIDTYPE_MVC)) |
| vd_layer[0].enable_3d_mode = mode_3d_mvc_enable; |
| else if (process_3d_type) |
| vd_layer[0].enable_3d_mode = mode_3d_enable; |
| else |
| vd_layer[0].enable_3d_mode = mode_3d_disable; |
| } |
| /* all frames has been renderred, so reset new frame flag */ |
| vd_layer[layer_id].new_frame = false; |
| } |
| |
| int amvecm_update(u8 layer_id, u8 path_index, struct vframe_s *vf) |
| { |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM |
| return amvecm_on_vs |
| ((cur_dispbuf[path_index] != &vf_local[path_index]) |
| ? cur_dispbuf[path_index] : NULL, |
| vf, CSC_FLAG_CHECK_OUTPUT, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| layer_id, |
| vd_layer[path_index].vpp_index); |
| #else |
| return 0; |
| #endif |
| } |
| |
| static struct vframe_s *do_pipx_toggle_frame |
| (u8 path_index, |
| struct path_id_s *path_id) |
| { |
| struct vframe_s *vf; |
| struct vframe_s *path_new_frame = NULL; |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| struct vframe_s *dv_new_vf = NULL; |
| #endif |
| s32 vd1_path_id, vd2_path_id, vd3_path_id; |
| |
| vf = video_vf_peek(path_index); |
| video_get_vf_cnt[path_index] = 0; |
| vd1_path_id = path_id->vd1_path_id; |
| vd2_path_id = path_id->vd2_path_id; |
| vd3_path_id = path_id->vd3_path_id; |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| /* check video frame before VECM process */ |
| if (((vd1_path_id == VFM_PATH_PIP || is_multi_dv_mode()) || |
| vd1_path_id == VFM_PATH_PIP2) && |
| vf && |
| is_amdv_enable()) { |
| amdv_check_hdr10(vf); |
| amdv_check_hdr10plus(vf); |
| amdv_check_hlg(vf); |
| amdv_check_primesl(vf); |
| amdv_check_cuva(vf); |
| } |
| #endif |
| while (vf && !video_suspend) { |
| if (!vf->frame_dirty) { |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| int iret1 = 0, iret2 = 0, iret3 = 0; |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if ((vd1_path_id == VFM_PATH_PIP || is_multi_dv_mode() || |
| vd1_path_id == VFM_PATH_PIP2) && |
| dolby_vision_need_wait(path_index)) |
| break; |
| #endif |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| if (vd1_path_id == VFM_PATH_PIP || |
| vd1_path_id == VFM_PATH_PIP2) |
| iret1 = amvecm_update(VD1_PATH, path_index, vf); |
| if (path_index == 1) { |
| /* pip */ |
| if (vd2_path_id == VFM_PATH_DEF || |
| vd2_path_id == VFM_PATH_PIP) |
| iret2 = amvecm_update(VD2_PATH, path_index, vf); |
| } else if (path_index == 2) { |
| /* pip2 */ |
| if (vd2_path_id == VFM_PATH_PIP2) |
| iret2 = amvecm_update(VD2_PATH, path_index, vf); |
| } |
| if (path_index == 1) { |
| /* pip */ |
| if (vd3_path_id == VFM_PATH_PIP) |
| iret3 = amvecm_update(VD3_PATH, path_index, vf); |
| } else if (path_index == 2) { |
| /* pip2 */ |
| if (vd3_path_id == VFM_PATH_DEF || |
| vd3_path_id == VFM_PATH_PIP2) |
| iret3 = amvecm_update(VD3_PATH, path_index, vf); |
| } |
| if (iret1 == 1 || iret2 == 1 || iret3 == 1) |
| break; |
| #endif |
| vf = video_vf_get(path_index); |
| if (vf) { |
| video_get_vf_cnt[path_index]++; |
| path_new_frame = pipx_toggle_frame(path_index, vf); |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (vd1_path_id == VFM_PATH_PIP || is_multi_dv_mode() || |
| vd1_path_id == VFM_PATH_PIP2) |
| dv_new_vf = dv_toggle_frame(vf, path_index, true); |
| #endif |
| } |
| } else { |
| vf = video_vf_get(path_index); |
| if (vf) { |
| video_get_vf_cnt[path_index]++; |
| if (video_vf_put(path_index, vf) < 0) |
| check_dispbuf(path_index, vf, true); |
| } |
| } |
| vf = video_vf_peek(path_index); |
| } |
| |
| /* vsync_notify_videosync(); */ |
| #ifdef CONFIG_AMLOGIC_VIDEOSYNC |
| vsync_notify_videosync(); |
| #endif |
| |
| if (video_get_vf_cnt[path_index] >= 2) { |
| video_drop_vf_cnt[path_index] += (video_get_vf_cnt[path_index] - 1); |
| if (debug_flag & DEBUG_FLAG_PRINT_DROP_FRAME) |
| pr_info("videopip%d drop frame: drop count %d\n", |
| path_index - 1, |
| video_drop_vf_cnt[path_index]); |
| } |
| return path_new_frame; |
| } |
| |
| static struct vframe_s *do_renderx_toggle_frame |
| (u8 path_index, |
| s32 *vd_path_id, |
| struct path_id_s *path_id) |
| { |
| struct vframe_s *path_new_frame = NULL; |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| u16 line = glayer_info[0].layer_top; |
| #endif |
| |
| /* video_render.x toggle frame */ |
| if (gvideo_recv[path_index]) { |
| path_new_frame = |
| gvideo_recv[path_index]->func->dequeue_frame |
| (gvideo_recv[path_index], path_id); |
| if (path_index == 0) { |
| if (path_new_frame && |
| tvin_vf_is_keeped(path_new_frame)) { |
| new_frame_count = 0; |
| } else if (path_new_frame) { |
| new_frame_count = gvideo_recv[0]->frame_count; |
| hdmi_in_delay_maxmin_new(path_new_frame); |
| } else if (gvideo_recv[0]->cur_buf) { |
| if (tvin_vf_is_keeped(gvideo_recv[0]->cur_buf)) |
| new_frame_count = 0; |
| } |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| if (vd_path_id[0] == VFM_PATH_VIDEO_RENDER0 && |
| cur_frame_par[0]) { |
| /*need call every vsync*/ |
| if (path_new_frame) |
| frame_lock_process(path_new_frame, |
| cur_frame_par[0], line); |
| else if (vd_layer[0].dispbuf) |
| frame_lock_process(vd_layer[0].dispbuf, |
| cur_frame_par[0], line); |
| else |
| frame_lock_process(NULL, cur_frame_par[0], line); |
| } |
| #endif |
| } |
| } |
| return path_new_frame; |
| } |
| |
| static struct vframe_s *video_toggle_frame |
| (u8 layer_id, |
| u8 fake_layer_id, |
| s32 *vd_path_id, |
| struct path_id_s *path_id) |
| { |
| u8 func_id = 0; |
| u8 path_index = 0; |
| struct vframe_s *path_new_frame = NULL; |
| |
| over_field = false; |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| if (cur_dev->vsync_2to1_enable && |
| layer_id == 0 && |
| vsync_count_start) { |
| /* not prevsync not handle */ |
| if (!frc_drv_get_1st_frm()) |
| return NULL; |
| } |
| #endif |
| if (layer_id == 0xff) |
| func_id = vd_fake_func[fake_layer_id].fake_func_id; |
| else if (layer_id < MAX_VD_LAYER) |
| func_id = vd_layer[layer_id].func_path_id; |
| switch (func_id) { |
| case AMVIDEO: |
| path_new_frame = amvideo_toggle_frame(vd_path_id); |
| break; |
| case PIP1: |
| case PIP2: |
| path_index = func_id - AMVIDEO; |
| if (path_index < MAX_VD_LAYER) |
| path_new_frame = do_pipx_toggle_frame(path_index, path_id); |
| break; |
| case RENDER0: |
| case RENDER1: |
| case RENDER2: |
| path_index = func_id - RENDER0; |
| if (path_index < MAX_VD_LAYER) |
| path_new_frame = do_renderx_toggle_frame(path_index, vd_path_id, path_id); |
| break; |
| default: |
| break; |
| } |
| if (cur_dev->vsync_2to1_enable && |
| layer_id == 0 && |
| path_new_frame) |
| new_frame_cnt++; |
| return path_new_frame; |
| } |
| |
| static struct vframe_s *vdx_swap_frame(u8 layer_id, |
| s32 vdx_path_id, |
| s32 cur_vdx_path_id, |
| struct vframe_s **path_new_frame) |
| { |
| struct vframe_s *new_frame = NULL; |
| u32 cur_blackout; |
| int source_type = 0; |
| int axis[4]; |
| int crop[4]; |
| int crop_save[4]; |
| u8 i = 0; |
| |
| vd_layer[layer_id].force_switch_mode = force_switch_vf_mode; |
| |
| /* i is path_index */ |
| for (i = 0; i < MAX_VD_LAYER; i++) { |
| if (vd_layer[layer_id].dispbuf_mapping == &cur_dispbuf[i] && |
| (cur_dispbuf[i] == &vf_local[i] || |
| !cur_dispbuf[i]) && |
| vd_layer[layer_id].dispbuf != cur_dispbuf[i]) |
| vd_layer[layer_id].dispbuf = cur_dispbuf[i]; |
| } |
| |
| for (i = 0; i < MAX_VD_LAYER; i++) { |
| if (gvideo_recv[i] && |
| vd_layer[layer_id].dispbuf_mapping == &gvideo_recv[i]->cur_buf && |
| (gvideo_recv[i]->cur_buf == &gvideo_recv[i]->local_buf || |
| !gvideo_recv[i]->cur_buf) && |
| vd_layer[layer_id].dispbuf != gvideo_recv[i]->cur_buf) |
| vd_layer[layer_id].dispbuf = gvideo_recv[i]->cur_buf; |
| } |
| |
| if (vd_layer[layer_id].switch_vf && |
| vd_layer[layer_id].dispbuf && |
| (vd_layer[layer_id].dispbuf->vf_ext || |
| vd_layer[layer_id].dispbuf->uvm_vf)) { |
| /* select uvm_vf first */ |
| if (vd_layer[layer_id].dispbuf->uvm_vf) |
| vd_layer[layer_id].vf_ext = |
| vd_layer[layer_id].dispbuf->uvm_vf; |
| else |
| vd_layer[layer_id].vf_ext = |
| (struct vframe_s *)vd_layer[layer_id].dispbuf->vf_ext; |
| } else { |
| vd_layer[layer_id].vf_ext = NULL; |
| } |
| |
| /* vdx config */ |
| if (gvideo_recv[0] && |
| gvideo_recv[0]->path_id == vdx_path_id) { |
| /* video_render.0 display on VDx */ |
| new_frame = path_new_frame[3]; |
| if (!new_frame) { |
| if (!gvideo_recv[0]->cur_buf) { |
| /* video_render.0 no frame in display */ |
| if (cur_vdx_path_id != vdx_path_id) |
| safe_switch_videolayer |
| (layer_id, false, true); |
| vd_layer[layer_id].dispbuf = NULL; |
| } else if (gvideo_recv[0]->cur_buf == |
| &gvideo_recv[0]->local_buf) { |
| /* video_render.0 keep frame */ |
| vd_layer[layer_id].dispbuf = |
| gvideo_recv[0]->cur_buf; |
| } else if (vd_layer[layer_id].dispbuf |
| != gvideo_recv[0]->cur_buf) { |
| /* video_render.0 has frame in display */ |
| new_frame = gvideo_recv[0]->cur_buf; |
| } |
| } |
| if (new_frame || gvideo_recv[0]->cur_buf) |
| vd_layer[layer_id].dispbuf_mapping = |
| &gvideo_recv[0]->cur_buf; |
| cur_blackout = 1; |
| } else if (gvideo_recv[1] && |
| (gvideo_recv[1]->path_id == vdx_path_id)) { |
| /* video_render.1 display on VDx */ |
| new_frame = path_new_frame[4]; |
| if (!new_frame) { |
| if (!gvideo_recv[1]->cur_buf) { |
| /* video_render.1 no frame in display */ |
| if (cur_vdx_path_id != vdx_path_id) |
| safe_switch_videolayer |
| (layer_id, false, true); |
| vd_layer[layer_id].dispbuf = NULL; |
| } else if (gvideo_recv[1]->cur_buf == |
| &gvideo_recv[1]->local_buf) { |
| /* video_render.1 keep frame */ |
| vd_layer[layer_id].dispbuf = |
| gvideo_recv[1]->cur_buf; |
| } else if (vd_layer[layer_id].dispbuf |
| != gvideo_recv[1]->cur_buf) { |
| /* video_render.1 has frame in display */ |
| new_frame = gvideo_recv[1]->cur_buf; |
| } |
| } |
| if (new_frame || gvideo_recv[1]->cur_buf) |
| vd_layer[layer_id].dispbuf_mapping = |
| &gvideo_recv[1]->cur_buf; |
| cur_blackout = 1; |
| } else if (gvideo_recv[2] && |
| (gvideo_recv[2]->path_id == vdx_path_id)) { |
| /* video_render.2 display on VDx */ |
| new_frame = path_new_frame[5]; |
| if (!new_frame) { |
| if (!gvideo_recv[2]->cur_buf) { |
| /* video_render.2 no frame in display */ |
| if (cur_vdx_path_id != vdx_path_id) |
| safe_switch_videolayer |
| (layer_id, false, true); |
| vd_layer[layer_id].dispbuf = NULL; |
| } else if (gvideo_recv[2]->cur_buf == |
| &gvideo_recv[2]->local_buf) { |
| /* video_render.2 keep frame */ |
| vd_layer[layer_id].dispbuf = |
| gvideo_recv[2]->cur_buf; |
| } else if (vd_layer[layer_id].dispbuf |
| != gvideo_recv[2]->cur_buf) { |
| /* video_render.2 has frame in display */ |
| new_frame = gvideo_recv[2]->cur_buf; |
| } |
| } |
| if (new_frame || gvideo_recv[2]->cur_buf) |
| vd_layer[layer_id].dispbuf_mapping = |
| &gvideo_recv[2]->cur_buf; |
| cur_blackout = 1; |
| } else if (vdx_path_id == VFM_PATH_AMVIDEO) { |
| /* primary display in VDx */ |
| new_frame = path_new_frame[0]; |
| if (!new_frame) { |
| if (!cur_dispbuf[0]) { |
| /* primary no frame in display */ |
| if (cur_vdx_path_id != vdx_path_id) |
| safe_switch_videolayer |
| (layer_id, false, true); |
| vd_layer[layer_id].dispbuf = NULL; |
| } else if (cur_dispbuf[0] == &vf_local[0]) { |
| /* primary keep frame */ |
| vd_layer[layer_id].dispbuf = cur_dispbuf[0]; |
| } else if (vd_layer[layer_id].dispbuf |
| != cur_dispbuf[0]) { |
| /* primary has frame in display */ |
| new_frame = cur_dispbuf[0]; |
| } |
| } |
| if (new_frame || cur_dispbuf[0]) |
| vd_layer[layer_id].dispbuf_mapping = &cur_dispbuf[0]; |
| cur_blackout = blackout[0] | force_blackout; |
| } else if (vdx_path_id == VFM_PATH_PIP) { |
| /* pip display in VDx */ |
| new_frame = path_new_frame[1]; |
| if (!new_frame) { |
| if (!cur_dispbuf[1]) { |
| /* pip no display frame */ |
| if (cur_vdx_path_id != vdx_path_id) |
| safe_switch_videolayer |
| (layer_id, false, true); |
| vd_layer[layer_id].dispbuf = NULL; |
| } else if (cur_dispbuf[1] == &vf_local[1]) { |
| /* pip keep frame */ |
| vd_layer[layer_id].dispbuf = cur_dispbuf[1]; |
| } else if (vd_layer[layer_id].dispbuf |
| != cur_dispbuf[1]) { |
| /* pip has frame in display */ |
| new_frame = cur_dispbuf[1]; |
| } |
| } |
| if (new_frame || cur_dispbuf[1]) |
| vd_layer[layer_id].dispbuf_mapping = &cur_dispbuf[1]; |
| cur_blackout = blackout[1] | force_blackout; |
| } else if (vdx_path_id == VFM_PATH_PIP2) { |
| /* pip2 display in VDx */ |
| new_frame = path_new_frame[2]; |
| if (!new_frame) { |
| if (!cur_dispbuf[2]) { |
| /* pip2 no display frame */ |
| if (cur_vdx_path_id != vdx_path_id) |
| safe_switch_videolayer |
| (layer_id, false, true); |
| vd_layer[layer_id].dispbuf = NULL; |
| } else if (cur_dispbuf[2] == &vf_local[1]) { |
| /* pip2 keep frame */ |
| vd_layer[layer_id].dispbuf = cur_dispbuf[2]; |
| } else if (vd_layer[layer_id].dispbuf |
| != cur_dispbuf[2]) { |
| /* pip2 has frame in display */ |
| new_frame = cur_dispbuf[2]; |
| } |
| } |
| if (new_frame || cur_dispbuf[2]) |
| vd_layer[layer_id].dispbuf_mapping = &cur_dispbuf[2]; |
| cur_blackout = blackout[2] | force_blackout; |
| } else if (vdx_path_id != VFM_PATH_INVALID) { |
| switch (layer_id) { |
| case 0: |
| /* primary display on VDx */ |
| new_frame = path_new_frame[0]; |
| if (vdx_path_id == VFM_PATH_AUTO) { |
| if (path_new_frame[3] && |
| (path_new_frame[3]->flag & |
| VFRAME_FLAG_FAKE_FRAME)) { |
| new_frame = path_new_frame[3]; |
| /* path3 is render0 */ |
| pr_info("vsync: auto path3 get a fake\n"); |
| } |
| if (!new_frame) { |
| if (cur_dispbuf[0] == &vf_local[0]) |
| vd_layer[layer_id].dispbuf = |
| cur_dispbuf[0]; |
| } |
| if (gvideo_recv[0]->cur_buf && |
| gvideo_recv[0]->cur_buf->flag & |
| VFRAME_FLAG_FAKE_FRAME) |
| vd_layer[layer_id].dispbuf = |
| gvideo_recv[0]->cur_buf; |
| //new add: |
| if (new_frame || cur_dispbuf[0]) { |
| if (new_frame && path_new_frame[3] == new_frame) |
| vd_layer[0].dispbuf_mapping = |
| &gvideo_recv[0]->cur_buf; |
| else |
| vd_layer[0].dispbuf_mapping = &cur_dispbuf[0]; |
| } |
| } else { |
| if (!new_frame) { |
| if (!cur_dispbuf[0]) { |
| /* primary no frame in display */ |
| if (cur_vdx_path_id != vdx_path_id) |
| safe_switch_videolayer |
| (layer_id, false, true); |
| vd_layer[layer_id].dispbuf = NULL; |
| } else if (cur_dispbuf[0] == &vf_local[0]) { |
| /* primary keep frame */ |
| vd_layer[layer_id].dispbuf = |
| cur_dispbuf[0]; |
| } else if (vd_layer[layer_id].dispbuf |
| != cur_dispbuf[0]) { |
| /* primary has frame in display */ |
| new_frame = cur_dispbuf[0]; |
| } |
| } |
| if (new_frame || cur_dispbuf[0]) |
| vd_layer[layer_id].dispbuf_mapping = &cur_dispbuf[0]; |
| } |
| |
| cur_blackout = blackout[0] | force_blackout; |
| break; |
| case 1: |
| case 2: |
| /* pip1/2 display in VDx */ |
| i = layer_id; |
| new_frame = path_new_frame[i]; |
| if (!new_frame) { |
| if (!cur_dispbuf[i]) { |
| /* pip no display frame */ |
| if (cur_vdx_path_id != vdx_path_id) |
| safe_switch_videolayer |
| (layer_id, false, true); |
| vd_layer[layer_id].dispbuf = NULL; |
| } else if (cur_dispbuf[i] == &vf_local[i]) { |
| /* pip keep frame */ |
| vd_layer[layer_id].dispbuf = cur_dispbuf[i]; |
| } else if (vd_layer[layer_id].dispbuf |
| != cur_dispbuf[i]) { |
| new_frame = cur_dispbuf[i]; |
| } |
| } |
| if (new_frame || cur_dispbuf[i]) |
| vd_layer[layer_id].dispbuf_mapping = &cur_dispbuf[i]; |
| cur_blackout = blackout[i] | force_blackout; |
| break; |
| } |
| } else { |
| cur_blackout = 1; |
| } |
| |
| /* vout mode detection under new non-tunnel mode */ |
| if (vd_layer[layer_id].dispbuf) { |
| if (strcmp(old_vmode, new_vmode)) { |
| vd_layer[0].property_changed = true; |
| vd_layer[1].property_changed = true; |
| vd_layer[2].property_changed = true; |
| pr_debug("detect vout mode change!!!!!!!!!!!!\n"); |
| strcpy(old_vmode, new_vmode); |
| } |
| } |
| /* vd1 special case */ |
| if (layer_id == 0) { |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (is_amdv_enable() && |
| vd_layer[layer_id].global_output) { |
| /* no new frame but path switched case, */ |
| if (new_frame && !is_local_vf(new_frame) && |
| (!path_new_frame[0] || new_frame != |
| path_new_frame[0]) && |
| (!path_new_frame[1] || new_frame != |
| path_new_frame[1]) && |
| (!path_new_frame[2] || new_frame != |
| path_new_frame[2]) && |
| (!path_new_frame[3] || new_frame != |
| path_new_frame[3]) && |
| (!path_new_frame[4] || new_frame != |
| path_new_frame[4]) && |
| (!path_new_frame[5] || new_frame != |
| path_new_frame[5])) |
| amdv_update_src_format(new_frame, 1, VD1_PATH); |
| else if (!new_frame && |
| vd_layer[layer_id].dispbuf && |
| !is_local_vf(vd_layer[layer_id].dispbuf)) |
| amdv_update_src_format(vd_layer[0].dispbuf, 0, VD1_PATH); |
| /* pause and video off->on case */ |
| } |
| #endif |
| } |
| |
| if (!new_frame && vd_layer[layer_id].dispbuf && |
| is_local_vf(vd_layer[layer_id].dispbuf)) { |
| if (cur_blackout) { |
| vd_layer[layer_id].property_changed = false; |
| } else if (vd_layer[layer_id].dispbuf) { |
| if ((layer_id == 0 && |
| !is_di_post_mode(vd_layer[layer_id].dispbuf) && |
| !is_plink_on(&vd_layer[layer_id])) || |
| layer_id != 0) { |
| if (vd_layer[layer_id].switch_vf && |
| vd_layer[layer_id].vf_ext) |
| vd_layer[layer_id].vf_ext->canvas0Addr = |
| get_layer_display_canvas(layer_id); |
| else |
| vd_layer[layer_id].dispbuf->canvas0Addr = |
| get_layer_display_canvas(layer_id); |
| } |
| } |
| } |
| |
| if (vd_layer[layer_id].dispbuf && |
| (vd_layer[layer_id].dispbuf->flag & (VFRAME_FLAG_VIDEO_COMPOSER | |
| VFRAME_FLAG_VIDEO_DRM)) && |
| !(vd_layer[layer_id].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME) && |
| !(debug_flag & DEBUG_FLAG_AXIS_NO_UPDATE)) { |
| int mirror = 0; |
| |
| axis[0] = vd_layer[layer_id].dispbuf->axis[0]; |
| axis[1] = vd_layer[layer_id].dispbuf->axis[1]; |
| axis[2] = vd_layer[layer_id].dispbuf->axis[2]; |
| axis[3] = vd_layer[layer_id].dispbuf->axis[3]; |
| crop[0] = vd_layer[layer_id].dispbuf->crop[0]; |
| crop[1] = vd_layer[layer_id].dispbuf->crop[1]; |
| crop[2] = vd_layer[layer_id].dispbuf->crop[2]; |
| crop[3] = vd_layer[layer_id].dispbuf->crop[3]; |
| _set_video_window(&glayer_info[layer_id], axis); |
| source_type = vd_layer[layer_id].dispbuf->source_type; |
| if (source_type != VFRAME_SOURCE_TYPE_HDMI && |
| source_type != VFRAME_SOURCE_TYPE_CVBS && |
| source_type != VFRAME_SOURCE_TYPE_TUNER && |
| source_type != VFRAME_SOURCE_TYPE_HWC) { |
| _set_video_crop(&glayer_info[layer_id], crop); |
| } else { |
| crop_save[0] = glayer_info[layer_id].crop_top_save; |
| crop_save[1] = glayer_info[layer_id].crop_left_save; |
| crop_save[2] = glayer_info[layer_id].crop_bottom_save; |
| crop_save[3] = glayer_info[layer_id].crop_right_save; |
| _set_video_crop(&glayer_info[layer_id], crop_save); |
| } |
| if (vd_layer[layer_id].dispbuf->flag & VFRAME_FLAG_MIRROR_H) |
| mirror = H_MIRROR; |
| if (vd_layer[layer_id].dispbuf->flag & VFRAME_FLAG_MIRROR_V) |
| mirror |= V_MIRROR; |
| _set_video_mirror(&glayer_info[layer_id], mirror); |
| set_alpha_scpxn(&vd_layer[layer_id], vd_layer[layer_id].dispbuf->composer_info); |
| glayer_info[layer_id].zorder = vd_layer[layer_id].dispbuf->zorder; |
| } else { |
| _set_video_mirror(&glayer_info[layer_id], 0); |
| } |
| |
| return new_frame; |
| } |
| |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| static void force_switch_slice(void) |
| { |
| const struct vinfo_s *vinfo = get_current_vinfo(); |
| u32 slice_num; |
| u32 switch_flag = 0; |
| |
| if (!video_is_meson_t3x_cpu()) |
| return; |
| |
| switch_flag = frc_ready_to_switch(); |
| if (switch_flag != 1 && switch_flag != 2) |
| return; |
| |
| if (vinfo && (vinfo->width > 1920 && vinfo->height > 1080 && |
| (vinfo->sync_duration_num / |
| vinfo->sync_duration_den > 60))) { |
| /* for t3x */ |
| if (switch_flag == 1) { |
| /* frc is ready on */ |
| /* 4k120hz and frc_n2m_worked 1 slice */ |
| slice_num = 1; |
| if (slice_num != vd_layer[0].slice_num) { |
| video_prop_status |= VIDEO_PROP_CHANGE_SLICE_NUM; |
| if (debug_flag) |
| pr_info("%s slice_num=%d-> %d, video_prop_status=%d\n", |
| __func__, |
| vd_layer[0].slice_num, slice_num, |
| video_prop_status); |
| } |
| vd_layer[0].slice_num = slice_num; |
| vd_layer[0].property_changed = true; |
| if (debug_common_flag & DEBUG_FLAG_COMMON_FRC) |
| pr_info("%s:slice_num=%d\n", |
| __func__, slice_num); |
| } else if (switch_flag == 2) { |
| /* frc is ready off */ |
| /* 4k120hz and frc_n2m_not_worked 2 slice */ |
| slice_num = 2; |
| if (slice_num != vd_layer[0].slice_num) { |
| video_prop_status |= VIDEO_PROP_CHANGE_SLICE_NUM; |
| if (debug_flag) |
| pr_info("%s slice_num=%d-> %d, video_prop_status=%d\n", |
| __func__, |
| vd_layer[0].slice_num, slice_num, |
| video_prop_status); |
| } |
| if (is_aisr_enable(&vd_layer[0])) |
| vd_layer[0].aisr_mif_setting.aisr_enable = 0; |
| vd_layer[0].slice_num = slice_num; |
| vd_layer[0].property_changed = true; |
| if (debug_common_flag & DEBUG_FLAG_COMMON_FRC) |
| pr_info("%s:slice_num=%d\n", |
| __func__, slice_num); |
| } |
| } |
| } |
| |
| #endif |
| |
| bool force_switch_to_2slice(void) |
| { |
| const struct vinfo_s *vinfo = get_current_vinfo(); |
| u32 slice_num; |
| |
| if (!video_is_meson_t3x_cpu()) |
| return false; |
| |
| if (vinfo && (vinfo->width > 1920 && vinfo->height > 1080 && |
| (vinfo->sync_duration_num / |
| vinfo->sync_duration_den > 60))) { |
| /* for t3x */ |
| /* frc is ready off */ |
| /* 4k120hz and frc_n2m_not_worked 2 slice */ |
| slice_num = 2; |
| if (debug_common_flag & DEBUG_FLAG_COMMON_FRC) |
| pr_info("%s:slice_num = %d gslice_num = %d\n", |
| __func__, slice_num, vd_layer[0].slice_num); |
| if (slice_num != vd_layer[0].slice_num) { |
| video_prop_status |= VIDEO_PROP_CHANGE_SLICE_NUM; |
| if (debug_flag) |
| pr_info("%s slice_num=%d-> %d, video_prop_status=%d\n", |
| __func__, |
| vd_layer[0].slice_num, slice_num, |
| video_prop_status); |
| if (is_aisr_enable(&vd_layer[0])) |
| vd_layer[0].aisr_mif_setting.aisr_enable = 0; |
| vd_layer[0].slice_num = slice_num; |
| vd_layer[0].property_changed = true; |
| return true; |
| } |
| } |
| return false; |
| } |
| #endif |
| |
| static void do_vd1_swap_frame(u8 layer_id, |
| s32 vd1_path_id, |
| s32 cur_vd1_path_id, |
| struct vframe_s **path_new_frame) |
| { |
| struct vframe_s *new_frame = NULL; |
| enum vframe_signal_fmt_e fmt; |
| int source_type = 0; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| if (cur_dev->vsync_2to1_enable && |
| layer_id == 0 && |
| vsync_count_start) { |
| /* not prevsync not handle */ |
| if (!frc_drv_get_1st_frm()) |
| return; |
| } |
| #endif |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| force_switch_slice(); |
| #endif |
| #endif |
| new_frame = vdx_swap_frame(0, vd1_path_id, |
| cur_vd1_path_id, |
| path_new_frame); |
| /* setting video display property in underflow mode */ |
| if (!new_frame && |
| vd_layer[0].dispbuf && |
| (vd_layer[0].property_changed || |
| is_picmode_changed(0, vd_layer[0].dispbuf))) { |
| primary_swap_frame(&vd_layer[0], vd_layer[0].dispbuf, __LINE__); |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| dvel_swap_frame(cur_dispbuf2); |
| #endif |
| } else if (new_frame) { |
| new_frame_mask |= 1; |
| vframe_walk_delay = (int)div_u64(((jiffies_64 - |
| new_frame->ready_jiffies64) * 1000), HZ); |
| vframe_walk_delay += 1000 * |
| vsync_pts_inc_scale / vsync_pts_inc_scale_base; |
| vframe_walk_delay -= new_frame->duration / 96; |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| vframe_walk_delay += frc_get_video_latency(); |
| #endif |
| primary_swap_frame(&vd_layer[0], new_frame, __LINE__); |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| dvel_swap_frame(cur_dispbuf2); |
| #endif |
| } |
| |
| /* TODO: need check more vd layer, now only vd1 */ |
| if (vd_layer[0].dispbuf && |
| (atomic_read(&vt_unreg_flag) || |
| tvin_vf_is_keeped(vd_layer[0].dispbuf))) { |
| source_type = vd_layer[0].dispbuf->source_type; |
| /* TODO: change new flag to detect video tunnel path */ |
| if (source_type == VFRAME_SOURCE_TYPE_HDMI || |
| source_type == VFRAME_SOURCE_TYPE_CVBS) { |
| if (!vd_layer[0].force_disable) { |
| safe_switch_videolayer(0, false, true); |
| atomic_set(&vt_disable_video_done, 0); |
| } |
| vd_layer[0].force_disable = true; |
| } else { |
| if (vd_layer[0].force_disable && |
| vd_layer[0].global_output && |
| !vd_layer[0].disable_video) |
| safe_switch_videolayer(0, true, true); |
| vd_layer[0].force_disable = false; |
| } |
| } else { |
| if (vd_layer[0].force_disable && |
| vd_layer[0].global_output && |
| !vd_layer[0].disable_video) |
| safe_switch_videolayer(0, true, true); |
| vd_layer[0].force_disable = false; |
| } |
| if (cur_frame_par[0]) { |
| if (cur_dev->aisr_enable && |
| cur_dev->aisr_frame_parms.aisr_enable) |
| cur_frame_par[0]->aisr_enable = 1; |
| else |
| cur_frame_par[0]->aisr_enable = 0; |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| update_frc_in_size(&vd_layer[0]); |
| frc_input_handle(vd_layer[0].dispbuf, vd_layer[0].next_frame_par); |
| vpu_set_frc_bypass(&vd_layer[0]); |
| #endif |
| if (atomic_read(&axis_changed)) { |
| video_prop_status |= VIDEO_PROP_CHANGE_AXIS; |
| atomic_set(&axis_changed, 0); |
| } |
| |
| if (vd1_path_id == VFM_PATH_AMVIDEO || |
| vd1_path_id == VFM_PATH_DEF) |
| vd_layer[0].keep_frame_id = 0; |
| else if (vd1_path_id == VFM_PATH_PIP) |
| vd_layer[0].keep_frame_id = 1; |
| else if (vd1_path_id == VFM_PATH_PIP2) |
| vd_layer[0].keep_frame_id = 2; |
| else |
| vd_layer[0].keep_frame_id = 0xff; |
| |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| struct vpp_frame_par_s *frame_par = NULL; |
| |
| if (vd_layer[0].next_frame_par) |
| frame_par = vd_layer[0].next_frame_par; |
| else |
| frame_par = vd_layer[0].cur_frame_par; |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| if (new_frame) |
| vpp_new_frame = 1; |
| else |
| vpp_new_frame = 0; |
| #endif |
| #endif |
| |
| refresh_on_vs(new_frame, vd_layer[0].dispbuf, vd_layer[0].vpp_index); |
| |
| amvecm_on_vs |
| (!is_local_vf(vd_layer[0].dispbuf) |
| ? vd_layer[0].dispbuf : NULL, |
| new_frame, |
| new_frame ? CSC_FLAG_TOGGLE_FRAME : 0, |
| frame_par ? |
| frame_par->supsc1_hori_ratio : |
| 0, |
| frame_par ? |
| frame_par->supsc1_vert_ratio : |
| 0, |
| frame_par ? |
| frame_par->spsc1_w_in : |
| 0, |
| frame_par ? |
| frame_par->spsc1_h_in : |
| 0, |
| frame_par ? |
| frame_par->cm_input_w : |
| 0, |
| frame_par ? |
| frame_par->cm_input_h : |
| 0, |
| VD1_PATH, |
| vd_layer[0].vpp_index); |
| #endif |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL |
| prime_sl_process(vd_layer[0].dispbuf); |
| #endif |
| |
| if ((new_frame || vd_layer[0].dispbuf) && |
| get_video_enabled(0)) { |
| if (new_frame) { |
| if (new_frame->ext_signal_type & 0x1) { |
| if (!atomic_read(&fmm_changed)) { |
| video_prop_status |= VIDEO_PROP_CHANGE_FMM; |
| atomic_set(&fmm_changed, 1); |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) |
| pr_info("VD1 FMM changed: %d->. cur:%p, new:%p\n", |
| new_frame ? |
| (new_frame->ext_signal_type & 0x1) : |
| (vd_layer[0].dispbuf->ext_signal_type & 0x1), |
| vd_layer[0].dispbuf, new_frame); |
| } |
| } else { |
| if (atomic_read(&fmm_changed)) { |
| video_prop_status |= VIDEO_PROP_CHANGE_FMM_DISABLE; |
| atomic_set(&fmm_changed, 0); |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) |
| pr_info("VD1 FMM changed: %d->. cur:%p, new:%p\n", |
| new_frame ? |
| (new_frame->ext_signal_type & 0x1) : |
| (vd_layer[0].dispbuf->ext_signal_type & 0x1), |
| vd_layer[0].dispbuf, new_frame); |
| } |
| } |
| } |
| } else { |
| if (atomic_read(&fmm_changed)) { |
| video_prop_status |= VIDEO_PROP_CHANGE_FMM_DISABLE; |
| atomic_set(&fmm_changed, 0); |
| } |
| } |
| |
| /* work around which dec/vdin don't call update src_fmt function */ |
| if (vd_layer[0].dispbuf && !is_local_vf(vd_layer[0].dispbuf)) { |
| int new_src_fmt = -1; |
| u32 src_map[] = { |
| VFRAME_SIGNAL_FMT_INVALID, |
| VFRAME_SIGNAL_FMT_HDR10, |
| VFRAME_SIGNAL_FMT_HDR10PLUS, |
| VFRAME_SIGNAL_FMT_DOVI, |
| VFRAME_SIGNAL_FMT_HDR10PRIME, |
| VFRAME_SIGNAL_FMT_HLG, |
| VFRAME_SIGNAL_FMT_SDR, |
| VFRAME_SIGNAL_FMT_MVC, |
| VFRAME_SIGNAL_FMT_CUVA_HDR, |
| VFRAME_SIGNAL_FMT_CUVA_HLG, |
| VFRAME_SIGNAL_FMT_SDR_2020 |
| }; |
| |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (is_amdv_on()) |
| new_src_fmt = get_amdv_src_format(VD1_PATH); |
| else |
| #endif |
| new_src_fmt = |
| (int)get_cur_source_type(VD1_PATH, VPP_TOP0); |
| #endif |
| /*coverity[dead_error_line] error report*/ |
| if (new_src_fmt > 0 && new_src_fmt < MAX_SOURCE) |
| fmt = (enum vframe_signal_fmt_e)src_map[new_src_fmt]; |
| else |
| fmt = VFRAME_SIGNAL_FMT_INVALID; |
| if (fmt != atomic_read(&cur_primary_src_fmt)) { |
| /* atomic_set(&primary_src_fmt, fmt); */ |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) { |
| char *old_str = NULL, *new_str = NULL; |
| enum vframe_signal_fmt_e old_fmt; |
| |
| old_fmt = (enum vframe_signal_fmt_e) |
| atomic_read(&cur_primary_src_fmt); |
| if (old_fmt != VFRAME_SIGNAL_FMT_INVALID) |
| old_str = (char *)src_fmt_str[old_fmt]; |
| if (fmt != VFRAME_SIGNAL_FMT_INVALID) { |
| /*coverity[dead_error_line] error report*/ |
| new_str = (char *)src_fmt_str[fmt]; |
| } |
| pr_info("VD1 src fmt changed: %s->%s. vf: %p, signal_type:0x%x\n", |
| old_str ? old_str : "invalid", |
| new_str ? new_str : "invalid", |
| vd_layer[0].dispbuf, |
| vd_layer[0].dispbuf->signal_type); |
| } |
| atomic_set(&cur_primary_src_fmt, fmt); |
| atomic_set(&primary_src_fmt, fmt); |
| video_prop_status |= VIDEO_PROP_CHANGE_FMT; |
| update_primary_fmt_event(); |
| } |
| } |
| } |
| |
| static void do_vdx_swap_frame(u8 layer_id, |
| s32 vd_path_id, |
| s32 cur_vd_path_id, |
| struct vframe_s **path_new_frame) |
| { |
| struct vframe_s *new_frame = NULL; |
| |
| new_frame = vdx_swap_frame(layer_id, vd_path_id, |
| cur_vd_path_id, |
| path_new_frame); |
| |
| /* setting video display property in underflow mode */ |
| if (!new_frame && |
| vd_layer[layer_id].dispbuf && |
| (vd_layer[layer_id].property_changed || |
| is_picmode_changed(layer_id, vd_layer[layer_id].dispbuf))) { |
| pipx_swap_frame(&vd_layer[layer_id], |
| vd_layer[layer_id].dispbuf, vinfo); |
| need_disable_vd[layer_id] = false; |
| } else if (new_frame) { |
| new_frame_mask |= 2; |
| pipx_swap_frame(&vd_layer[layer_id], new_frame, vinfo); |
| need_disable_vd[layer_id] = false; |
| } |
| |
| if (layer_id == 1) { |
| if (vd_path_id == VFM_PATH_PIP || |
| vd_path_id == VFM_PATH_DEF) |
| vd_layer[layer_id].keep_frame_id = 1; |
| else if (vd_path_id == VFM_PATH_PIP2) |
| vd_layer[layer_id].keep_frame_id = 2; |
| else if (vd_path_id == VFM_PATH_AMVIDEO) |
| vd_layer[layer_id].keep_frame_id = 0; |
| else |
| vd_layer[layer_id].keep_frame_id = 0xff; |
| } else if (layer_id == 2) { |
| if (vd_path_id == VFM_PATH_PIP2 || |
| vd_path_id == VFM_PATH_DEF) |
| vd_layer[layer_id].keep_frame_id = 2; |
| else if (vd_path_id == VFM_PATH_PIP) |
| vd_layer[layer_id].keep_frame_id = 1; |
| else if (vd_path_id == VFM_PATH_AMVIDEO) |
| vd_layer[layer_id].keep_frame_id = 0; |
| else |
| vd_layer[layer_id].keep_frame_id = 0xff; |
| } |
| |
| #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) |
| struct vpp_frame_par_s *frame_par = NULL; |
| |
| if (vd_layer[layer_id].next_frame_par) |
| frame_par = vd_layer[layer_id].next_frame_par; |
| else |
| frame_par = vd_layer[layer_id].cur_frame_par; |
| |
| amvecm_on_vs |
| (!is_local_vf(vd_layer[layer_id].dispbuf) |
| ? vd_layer[layer_id].dispbuf : NULL, |
| new_frame, |
| new_frame ? CSC_FLAG_TOGGLE_FRAME : 0, |
| frame_par ? |
| frame_par->supsc1_hori_ratio : |
| 0, |
| frame_par ? |
| frame_par->supsc1_vert_ratio : |
| 0, |
| frame_par ? |
| frame_par->spsc1_w_in : |
| 0, |
| frame_par ? |
| frame_par->spsc1_h_in : |
| 0, |
| frame_par ? |
| frame_par->cm_input_w : |
| 0, |
| frame_par ? |
| frame_par->cm_input_h : |
| 0, |
| layer_id, |
| vd_layer[layer_id].vpp_index); |
| #endif |
| |
| if (need_disable_vd[layer_id]) { |
| safe_switch_videolayer(layer_id, false, true); |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| /* reset dvel statue when disable vd2 */ |
| if (layer_id == 1) |
| dvel_status = false; |
| #endif |
| if (vd_layer[layer_id].dispbuf && |
| (vd_layer[layer_id].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME)) |
| safe_switch_videolayer(layer_id, false, true); |
| } |
| } |
| |
| static int misc_early_proc(void) |
| { |
| u32 next_afbc_request = atomic_read(&gafbc_request); |
| s32 vout_type; |
| bool rdma_enable, _rdma_enable_pre; |
| int i, ret = 0; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| if (is_video_process_in_thread()) |
| set_vsync_rdma_id(EX_VSYNC_RDMA); |
| else |
| set_vsync_rdma_id(VSYNC_RDMA); |
| |
| if (is_vsync_rdma_enable()) |
| over_field_info_record(); |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (is_amdv_on()) |
| amdv_update_backlight(); |
| #endif |
| |
| vout_type = detect_vout_type(vinfo); |
| |
| for (i = 0; i < cur_dev->max_vd_layers; i++) { |
| glayer_info[i].need_no_compress = |
| (next_afbc_request & (i + 1)) ? true : false; |
| vd_layer[i].bypass_pps = bypass_pps == 1 ? true : false; |
| vd_layer[i].global_debug = debug_flag; |
| vd_layer[i].vout_type = vout_type; |
| vd_layer[i].display_cnt++; |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| set_dv_provide_name(); |
| #endif |
| |
| vsync_count++; |
| timer_count++; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| vsync_rdma_config_pre(); |
| |
| if (debug_flag & DEBUG_FLAG_PRINT_RDMA) { |
| if (vd_layer[0].property_changed) { |
| enable_rdma_log_count = 5; |
| enable_rdma_log(1); |
| } |
| if (enable_rdma_log_count > 0) |
| enable_rdma_log_count--; |
| } |
| #endif |
| |
| rdma_enable = is_vsync_rdma_enable(); |
| _rdma_enable_pre = rdma_enable_pre; |
| for (i = 0; i < cur_dev->max_vd_layers; i++) |
| if (vd_layer[i].vd_func.vd_misc_early_proc) |
| ret = vd_layer[i].vd_func.vd_misc_early_proc |
| (i, rdma_enable, _rdma_enable_pre); |
| return ret; |
| } |
| |
| static void dump_current_display_regs_info(void) |
| { |
| int i, layer = 0, afbc, dw; |
| struct vpp_frame_par_s *cur_frame_par; |
| struct hw_vd_linear_reg_s *mif_linear_reg; |
| struct hw_vd_reg_s *mif_reg = NULL; |
| struct hw_afbc_reg_s *afbc_reg = NULL; |
| u32 vd_if_baddr_y, vd_if_baddr_cb, vd_if_baddr_cr; |
| u32 canvas_id; |
| struct canvas_s cs0, cs1, cs2; |
| u64 baddr_y = 0, baddr_cb = 0, baddr_cr = 0; |
| u64 head_addr = 0, body_addr = 0; |
| struct vframe_s *dispbuf = NULL; |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| struct afbcd_info di_vfm; |
| |
| memset(&di_vfm, 0, sizeof(struct afbcd_info)); |
| #endif |
| |
| memset(&cs0, 0, sizeof(struct canvas_s)); |
| memset(&cs1, 0, sizeof(struct canvas_s)); |
| memset(&cs2, 0, sizeof(struct canvas_s)); |
| for (i = 0; i < cur_dev->max_vd_layers; i++) { |
| dispbuf = get_dispbuf(i); |
| if (!dispbuf) |
| continue; |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| if (IS_DI_PRELINK(dispbuf->di_flag)) { |
| if (di_vfm_info(&di_vfm)) |
| pr_info("VID(%s): VD%d prelink afbc:0x%llx-0x%llx hsize:%d vsize:%d\n", |
| __func__, i + 1, (u64)di_vfm.head_addr, |
| (u64)di_vfm.body_addr, |
| di_vfm.hsize_out, di_vfm.vsize_out); |
| continue; |
| } |
| #endif |
| if (cur_dev->display_module == S5_DISPLAY_MODULE) { |
| if (i != 0) |
| layer = i + SLICE_NUM - 1; |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| mif_reg = (struct hw_vd_reg_s *)&vd_proc_reg.vd_mif_reg[layer]; |
| mif_linear_reg = (struct hw_vd_linear_reg_s *) |
| &vd_proc_reg.vd_mif_linear_reg[layer]; |
| afbc_reg = (struct hw_afbc_reg_s *)&vd_proc_reg.vd_afbc_reg[layer]; |
| #endif |
| } else { |
| mif_reg = &vd_layer[i].vd_mif_reg; |
| mif_linear_reg = &vd_layer[i].vd_mif_linear_reg; |
| afbc_reg = &vd_layer[i].vd_afbc_reg; |
| if (i == 0 && vd_layer[i].vd1_vd2_mux) { |
| /* vd2 replaced vd1 mif reg */ |
| mif_reg = &vd_layer[1].vd_mif_reg; |
| } |
| } |
| |
| cur_frame_par = vd_layer[i].cur_frame_par; |
| if (!mif_reg || !afbc_reg || !cur_frame_par) |
| return; |
| afbc = dispbuf->type & VIDTYPE_COMPRESS ? 1 : 0; |
| dw = afbc && cur_frame_par->nocomp; |
| |
| canvas_id = READ_VCBUS_REG(mif_reg->vd_if0_canvas0); |
| if (afbc && !dw) { |
| head_addr = (u64)READ_VCBUS_REG(afbc_reg->afbc_head_baddr) << 4; |
| body_addr = (u64)READ_VCBUS_REG(afbc_reg->afbc_body_baddr) << 4; |
| } else { |
| if (cur_dev->mif_linear) { |
| vd_if_baddr_y = mif_linear_reg->vd_if0_baddr_y; |
| vd_if_baddr_cb = mif_linear_reg->vd_if0_baddr_cb; |
| vd_if_baddr_cr = mif_linear_reg->vd_if0_baddr_cr; |
| baddr_y = (u64)READ_VCBUS_REG(vd_if_baddr_y) << 4; |
| baddr_cb = (u64)READ_VCBUS_REG(vd_if_baddr_cb) << 4; |
| baddr_cr = (u64)READ_VCBUS_REG(vd_if_baddr_cr) << 4; |
| } else { |
| canvas_read(canvas_id & 0xff, &cs0); |
| canvas_read((canvas_id >> 8) & 0xff, &cs1); |
| canvas_read((canvas_id >> 16) & 0xff, &cs2); |
| baddr_y = (u64)cs0.addr; |
| baddr_cb = (u64)cs1.addr; |
| baddr_cr = (u64)cs2.addr; |
| } |
| } |
| pr_info("VID(%s): VD%d afbc:%d dw:%d, canvas:%x canvas adr:0x%llx-0x%llx-0x%llx, afbc:0x%llx-0x%llx\n", |
| __func__, i + 1, afbc, dw, canvas_id, |
| baddr_y, baddr_cb, baddr_cr, |
| head_addr, body_addr); |
| } |
| } |
| |
| static void misc_late_proc(void) |
| { |
| struct cur_line_info_t *cur_line_info = NULL; |
| int enc_line; |
| int i; |
| |
| if (first_irq) { |
| first_irq = false; |
| goto RUN_FIRST_RDMA; |
| } |
| if (new_frame_mask && is_vsync_rdma_enable()) |
| update_over_field_states(OVER_FIELD_NEW_VF, false); |
| |
| for (i = 0; i < cur_dev->max_vd_layers; i++) |
| if (vd_layer[i].vd_func.vd_misc_late_proc) |
| vd_layer[i].vd_func.vd_misc_late_proc(i); |
| |
| #if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) |
| pts_trace++; |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| /* vsync_rdma_config(); */ |
| RUN_FIRST_RDMA: |
| vsync_rdma_process(); |
| set_vd_pi_input_size(); |
| enc_line = get_cur_enc_line(); |
| cur_line_info = get_cur_line_info(0); |
| vpp_trace_encline("AFTER-RDMA", cur_line_info->enc_line_start, enc_line); |
| |
| trace_performance(cur_line_info, enc_line); |
| |
| rdma_enable_pre = is_vsync_rdma_enable(); |
| if (debug_flag & DEBUG_FLAG_PRINT_RDMA) { |
| if (enable_rdma_log_count == 0) |
| enable_rdma_log(0); |
| } |
| #endif |
| |
| if (cur_dev->display_module != C3_DISPLAY_MODULE) { |
| if (timer_count > 50) { |
| timer_count = 0; |
| video_notify_flag |= VIDEO_NOTIFY_FRAME_WAIT; |
| } |
| |
| enc_line = get_cur_enc_line(); |
| if (enc_line > vsync_exit_line_max) |
| vsync_exit_line_max = enc_line; |
| if (video_suspend) |
| video_suspend_cycle++; |
| #ifdef FIQ_VSYNC |
| if (video_notify_flag) |
| fiq_bridge_pulse_trigger(&vsync_fiq_bridge); |
| #else |
| if (video_notify_flag) |
| vsync_notify(); |
| |
| /* if prop_change not zero, event will be delayed to next vsync */ |
| if (video_prop_status && |
| !atomic_read(&video_prop_change)) { |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) |
| pr_info("VD1 send event, changed status: 0x%x\n", |
| video_prop_status); |
| atomic_set(&video_prop_change, video_prop_status); |
| video_prop_status = VIDEO_PROP_CHANGE_NONE; |
| wake_up_interruptible(&amvideo_prop_change_wait); |
| } |
| if (video_info_change_status) { |
| struct vd_info_s vd_info; |
| |
| if (debug_flag & DEBUG_FLAG_TRACE_EVENT) |
| pr_info("VD1 send event to frc, changed status: 0x%x\n", |
| video_info_change_status); |
| vd_info.flags = video_info_change_status; |
| vd_signal_notifier_call_chain(VIDEO_INFO_CHANGED, |
| &vd_info); |
| video_info_change_status = VIDEO_INFO_CHANGE_NONE; |
| } |
| #ifdef CONFIG_AMLOGIC_VPU |
| vpu_work_process(); |
| #endif |
| vpp_crc_result = vpp_crc_check(vpp_crc_en, VPP0); |
| } |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| vpp_trace_field_state("VSYNC-END", |
| atomic_read(&cur_over_field_state), |
| atomic_read(&cur_over_field_state), |
| over_field ? 1 : 0, |
| over_field_case1_cnt, over_field_case2_cnt); |
| #endif |
| if (debug_flag & DEBUG_FLAG_GET_COUNT) |
| pr_info("count=%d pip=%d, pip2=%d\n", |
| get_count_pip[0], get_count_pip[1], get_count_pip[2]); |
| |
| /* clear the delay video flag of HDMI-IN AV SYNC Control */ |
| go_exit = 0; |
| } |
| |
| static int do_vd1_path_select(void) |
| { |
| int index = 0; |
| int path_switched = 0; |
| s32 vd1_path_id = glayer_info[index].display_path_id; |
| |
| /* vd1 path select */ |
| /* if pre_vsync_enable, vd1 need select to pre_vsync */ |
| if (cur_dev->pre_vsync_enable) { |
| if (vd_layer[index].vd_path_id != vd1_path_id) { |
| path_switched = 1; |
| vd_layer[index].vd_path_id = vd1_path_id; |
| } |
| if (path_switched && |
| vd_layer[index].next_pre_func == |
| vd_layer[index].cur_pre_func) { |
| vd_layer[index].next_pre_func = |
| (&vd_layer[index].pre_vd_func[0] == |
| vd_layer[index].next_pre_func) ? |
| &vd_layer[index].pre_vd_func[1] : |
| &vd_layer[index].pre_vd_func[0]; |
| if (debug_flag & DEBUG_FLAG_PRINT_PATH_SWITCH) |
| pr_info("%s: vd1_path_id=%d, next_pre_func=%p, cur_pre_func=%p\n", |
| __func__, vd1_path_id, |
| vd_layer[index].next_pre_func, |
| vd_layer[index].cur_pre_func); |
| } |
| if (!vd_layer[index].next_pre_func) |
| vd_layer[index].next_pre_func = |
| &vd_layer[index].pre_vd_func[0]; |
| |
| vd_layer[index].next_pre_func->vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].next_pre_func->vd_swap_frame = |
| do_vd1_swap_frame; |
| vd_layer[index].next_pre_func->vd_render_frame = |
| vdx_render_frame; |
| vd_layer[index].next_pre_func->vd_early_process = |
| video_early_proc; |
| vd_layer[index].next_pre_func->vd_late_process = |
| video_late_proc; |
| vd_layer[index].next_pre_func->vd_misc_early_proc = |
| vdx_misc_early_proc; |
| vd_layer[index].next_pre_func->vd_misc_late_proc = |
| vdx_misc_late_proc; |
| |
| if (gvideo_recv[0] && |
| gvideo_recv[0]->path_id == vd1_path_id) { |
| /* video_render.0 display on VD1 */ |
| vd_layer[index].next_pre_func->path_frame_index = 3; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[3].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER0; |
| } else if (gvideo_recv[1] && |
| (gvideo_recv[1]->path_id == vd1_path_id)) { |
| /* video_render.1 display on VD1 */ |
| vd_layer[index].next_pre_func->path_frame_index = 4; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[4].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER1; |
| } else if (gvideo_recv[2] && |
| (gvideo_recv[2]->path_id == vd1_path_id)) { |
| /* video_render.2 display on VD1 */ |
| vd_layer[index].next_pre_func->path_frame_index = 5; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[5].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER2; |
| } else if (vd1_path_id == VFM_PATH_PIP2) { |
| /* pip2 display on VD1 */ |
| vd_layer[index].next_pre_func->path_frame_index = 2; |
| vd_layer[index].keep_frame_id = 2; |
| vd_fake_func[2].video_process_flag = 1; |
| vd_layer[index].func_path_id = PIP2; |
| } else if (vd1_path_id == VFM_PATH_PIP) { |
| /* pip display on VD1 */ |
| vd_layer[index].next_pre_func->path_frame_index = 1; |
| vd_layer[index].keep_frame_id = 1; |
| vd_fake_func[1].video_process_flag = 1; |
| vd_layer[index].func_path_id = PIP1; |
| } else if ((vd1_path_id == VFM_PATH_AMVIDEO) || |
| (vd1_path_id == VFM_PATH_DEF) || |
| (vd1_path_id == VFM_PATH_AUTO)) { |
| /* primary display on VD1 */ |
| vd_layer[index].next_pre_func->path_frame_index = 0; |
| vd_layer[index].keep_frame_id = 0; |
| vd_fake_func[0].video_process_flag = 1; |
| vd_layer[index].func_path_id = AMVIDEO; |
| } else { |
| vd_layer[index].next_pre_func->vd_toggle_frame = NULL; |
| vd_layer[index].next_pre_func->vd_swap_frame = NULL; |
| vd_layer[index].next_pre_func->vd_render_frame = NULL; |
| vd_layer[index].next_pre_func->vd_early_process = NULL; |
| vd_layer[index].next_pre_func->vd_late_process = NULL; |
| vd_layer[index].next_pre_func->vd_misc_early_proc = |
| NULL; |
| vd_layer[index].next_pre_func->vd_misc_late_proc = NULL; |
| } |
| /* set post vsync vd_func to NULL */ |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| vd_layer[index].vd_func.vd_swap_frame = NULL; |
| vd_layer[index].vd_func.vd_render_frame = NULL; |
| vd_layer[index].vd_func.vd_early_process = NULL; |
| vd_layer[index].vd_func.vd_late_process = NULL; |
| vd_layer[index].vd_func.vd_misc_early_proc = NULL; |
| vd_layer[index].vd_func.vd_misc_late_proc = NULL; |
| |
| vd_layer[0].vpp_index = PRE_VSYNC; |
| } else { |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.vd_swap_frame = |
| do_vd1_swap_frame; |
| vd_layer[index].vd_func.vd_render_frame = |
| vdx_render_frame; |
| vd_layer[index].vd_func.vd_early_process = |
| video_early_proc; |
| vd_layer[index].vd_func.vd_late_process = |
| video_late_proc; |
| vd_layer[index].vd_func.vd_misc_early_proc = |
| vdx_misc_early_proc; |
| vd_layer[index].vd_func.vd_misc_late_proc = |
| vdx_misc_late_proc; |
| if (gvideo_recv[0] && |
| gvideo_recv[0]->path_id == vd1_path_id) { |
| /* video_render.0 display on VD1 */ |
| vd_layer[index].vd_func.path_frame_index = 3; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[3].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER0; |
| } else if (gvideo_recv[1] && |
| (gvideo_recv[1]->path_id == vd1_path_id)) { |
| /* video_render.1 display on VD1 */ |
| vd_layer[index].vd_func.path_frame_index = 4; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[4].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER1; |
| } else if (gvideo_recv[2] && |
| (gvideo_recv[2]->path_id == vd1_path_id)) { |
| /* video_render.2 display on VD1 */ |
| vd_layer[index].vd_func.path_frame_index = 5; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[5].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER2; |
| } else if (vd1_path_id == VFM_PATH_PIP2) { |
| /* pip2 display on VD1 */ |
| vd_layer[index].vd_func.path_frame_index = 2; |
| vd_layer[index].keep_frame_id = 2; |
| vd_fake_func[2].video_process_flag = 1; |
| vd_layer[index].func_path_id = PIP2; |
| } else if (vd1_path_id == VFM_PATH_PIP) { |
| /* pip display on VD1 */ |
| vd_layer[index].vd_func.path_frame_index = 1; |
| vd_layer[index].keep_frame_id = 1; |
| vd_fake_func[1].video_process_flag = 1; |
| vd_layer[index].func_path_id = PIP1; |
| } else if ((vd1_path_id == VFM_PATH_AMVIDEO) || |
| (vd1_path_id == VFM_PATH_DEF) || |
| (vd1_path_id == VFM_PATH_AUTO)) { |
| /* primary display on VD1 */ |
| vd_layer[index].vd_func.path_frame_index = 0; |
| vd_layer[index].keep_frame_id = 0; |
| vd_fake_func[0].video_process_flag = 1; |
| vd_layer[index].func_path_id = AMVIDEO; |
| } else { |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| vd_layer[index].vd_func.vd_swap_frame = NULL; |
| vd_layer[index].vd_func.vd_render_frame = NULL; |
| vd_layer[index].vd_func.vd_early_process = NULL; |
| vd_layer[index].vd_func.vd_late_process = NULL; |
| vd_layer[index].vd_func.vd_misc_early_proc = NULL; |
| vd_layer[index].vd_func.vd_misc_late_proc = NULL; |
| } |
| /* set pre vsync vd_func to NULL */ |
| vd_layer[index].pre_vd_func[0].vd_toggle_frame = NULL; |
| vd_layer[index].pre_vd_func[0].vd_swap_frame = NULL; |
| vd_layer[index].pre_vd_func[0].vd_render_frame = NULL; |
| vd_layer[index].pre_vd_func[0].vd_early_process = NULL; |
| vd_layer[index].pre_vd_func[0].vd_late_process = NULL; |
| vd_layer[index].pre_vd_func[0].vd_misc_early_proc = NULL; |
| vd_layer[index].pre_vd_func[0].vd_misc_late_proc = NULL; |
| |
| vd_layer[index].pre_vd_func[1].vd_toggle_frame = NULL; |
| vd_layer[index].pre_vd_func[1].vd_swap_frame = NULL; |
| vd_layer[index].pre_vd_func[1].vd_render_frame = NULL; |
| vd_layer[index].pre_vd_func[1].vd_early_process = NULL; |
| vd_layer[index].pre_vd_func[1].vd_late_process = NULL; |
| vd_layer[index].pre_vd_func[1].vd_misc_early_proc = NULL; |
| vd_layer[index].pre_vd_func[1].vd_misc_late_proc = NULL; |
| |
| vd_layer[0].vpp_index = VPP0; |
| vd_layer[index].vd_path_id = -1; |
| } |
| return 0; |
| } |
| |
| static int do_vd2_path_select(void) |
| { |
| int index = 1; |
| int path_used = 1; |
| s32 vd1_path_id = glayer_info[0].display_path_id; |
| s32 vd2_path_id = glayer_info[index].display_path_id; |
| |
| vd_layer[index].vd_func.vd_swap_frame = do_vdx_swap_frame; |
| vd_layer[index].vd_func.vd_render_frame = vdx_render_frame; |
| vd_layer[index].vd_func.vd_early_process = video_early_proc; |
| vd_layer[index].vd_func.vd_late_process = video_late_proc; |
| vd_layer[index].vd_func.vd_misc_early_proc = |
| vdx_misc_early_proc; |
| vd_layer[index].vd_func.vd_misc_late_proc = vdx_misc_late_proc; |
| /* vd2 path select */ |
| if (gvideo_recv[0] && |
| gvideo_recv[0]->path_id == vd2_path_id) { |
| /* video_render.0 display on VD2 */ |
| if (vd2_path_id == vd1_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 3; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[3].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER0; |
| } else if (gvideo_recv[1] && |
| (gvideo_recv[1]->path_id == vd2_path_id)) { |
| /* video_render.1 display on VD2 */ |
| if (vd2_path_id == vd1_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 4; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[4].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER1; |
| } else if (gvideo_recv[2] && |
| (gvideo_recv[2]->path_id == vd2_path_id)) { |
| /* video_render.2 display on VD2 */ |
| if (vd2_path_id == vd1_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 5; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[5].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER2; |
| } else if (vd2_path_id == VFM_PATH_PIP2) { |
| /* pip2 display on VD2 */ |
| if (vd2_path_id == vd1_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 2; |
| vd_layer[index].keep_frame_id = 2; |
| vd_fake_func[2].video_process_flag = 1; |
| vd_layer[index].func_path_id = PIP2; |
| } else if ((vd2_path_id == VFM_PATH_PIP) || |
| (vd2_path_id == VFM_PATH_DEF)) { |
| /* pip display on VD2 */ |
| if (vd2_path_id == VFM_PATH_PIP && vd2_path_id == vd1_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 1; |
| vd_layer[index].keep_frame_id = 1; |
| vd_fake_func[1].video_process_flag = 1; |
| vd_layer[index].func_path_id = PIP1; |
| } else if (vd2_path_id == VFM_PATH_AMVIDEO) { |
| /* primary display on VD2 */ |
| if (vd2_path_id == vd1_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 0; |
| vd_layer[index].keep_frame_id = 0; |
| vd_fake_func[0].video_process_flag = 1; |
| vd_layer[index].func_path_id = AMVIDEO; |
| } else { |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| vd_layer[index].vd_func.vd_swap_frame = NULL; |
| vd_layer[index].vd_func.vd_render_frame = NULL; |
| vd_layer[index].vd_func.vd_early_process = NULL; |
| vd_layer[index].vd_func.vd_late_process = NULL; |
| vd_layer[index].vd_func.vd_misc_early_proc = NULL; |
| vd_layer[index].vd_func.vd_misc_late_proc = NULL; |
| path_used = 0; |
| } |
| return path_used; |
| } |
| |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| static int do_vd3_path_select(void) |
| { |
| int index = 2; |
| int path_used = 1; |
| s32 vd1_path_id = glayer_info[0].display_path_id; |
| s32 vd2_path_id = glayer_info[1].display_path_id; |
| s32 vd3_path_id = glayer_info[index].display_path_id; |
| |
| vd_layer[index].vd_func.vd_swap_frame = do_vdx_swap_frame; |
| vd_layer[index].vd_func.vd_render_frame = vdx_render_frame; |
| vd_layer[index].vd_func.vd_early_process = video_early_proc; |
| vd_layer[index].vd_func.vd_late_process = video_late_proc; |
| vd_layer[index].vd_func.vd_misc_early_proc = |
| vdx_misc_early_proc; |
| vd_layer[index].vd_func.vd_misc_late_proc = vdx_misc_late_proc; |
| /* vd3 path select */ |
| if (gvideo_recv[0] && |
| gvideo_recv[0]->path_id == vd3_path_id) { |
| /* video_render.0 display on VD3 */ |
| if (vd3_path_id == vd1_path_id || |
| vd3_path_id == vd2_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 3; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[3].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER0; |
| } else if (gvideo_recv[1] && |
| (gvideo_recv[1]->path_id == vd3_path_id)) { |
| /* video_render.1 display on VD3 */ |
| if (vd3_path_id == vd1_path_id || |
| vd3_path_id == vd2_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 4; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[4].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER1; |
| } else if (gvideo_recv[2] && |
| (gvideo_recv[2]->path_id == vd3_path_id)) { |
| /* video_render.2 display on VD3 */ |
| if (vd3_path_id == vd1_path_id || |
| vd3_path_id == vd2_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 5; |
| vd_layer[index].keep_frame_id = 0xff; |
| vd_fake_func[5].video_process_flag = 1; |
| vd_layer[index].func_path_id = RENDER2; |
| } else if (vd3_path_id == VFM_PATH_PIP2) { |
| /* pip2 display on VD3 */ |
| if (vd3_path_id == vd1_path_id || |
| vd3_path_id == vd2_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 2; |
| vd_layer[index].keep_frame_id = 2; |
| vd_fake_func[2].video_process_flag = 1; |
| vd_layer[index].func_path_id = PIP2; |
| } else if (vd3_path_id == VFM_PATH_PIP) { |
| /* pip display on VD3 */ |
| if (vd3_path_id == vd1_path_id || |
| vd3_path_id == vd2_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 1; |
| vd_layer[index].keep_frame_id = 1; |
| vd_fake_func[1].video_process_flag = 1; |
| vd_layer[index].func_path_id = PIP1; |
| } else if (vd3_path_id == VFM_PATH_AMVIDEO) { |
| /* primary display on VD3 */ |
| if (vd3_path_id == vd1_path_id || |
| vd3_path_id == vd2_path_id) |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| else |
| vd_layer[index].vd_func.vd_toggle_frame = |
| video_toggle_frame; |
| vd_layer[index].vd_func.path_frame_index = 0; |
| vd_layer[index].keep_frame_id = 0; |
| vd_fake_func[0].video_process_flag = 1; |
| vd_layer[index].func_path_id = AMVIDEO; |
| } else { |
| vd_layer[index].vd_func.vd_toggle_frame = NULL; |
| vd_layer[index].vd_func.vd_swap_frame = NULL; |
| vd_layer[index].vd_func.vd_render_frame = NULL; |
| vd_layer[index].vd_func.vd_early_process = NULL; |
| vd_layer[index].vd_func.vd_late_process = NULL; |
| vd_layer[index].vd_func.vd_misc_early_proc = NULL; |
| vd_layer[index].vd_func.vd_misc_late_proc = NULL; |
| path_used = 0; |
| } |
| return path_used; |
| } |
| #endif |
| |
| static void do_video_path_select(void) |
| { |
| int i; |
| |
| do_vd1_path_select(); |
| do_vd2_path_select(); |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| if (cur_dev->max_vd_layers == 3) |
| do_vd3_path_select(); |
| #endif |
| /* vdx init */ |
| for (i = 0; i < cur_dev->max_vd_layers; i++) |
| vd_dispbuf_init(i); |
| } |
| |
| static void do_fake_video_select(void) |
| { |
| /* for amvideo */ |
| vd_fake_func[0].vd_toggle_frame = video_toggle_frame; |
| vd_fake_func[0].vd_swap_frame = NULL; |
| vd_fake_func[0].vd_render_frame = NULL; |
| vd_fake_func[0].vd_early_process = video_early_proc; |
| vd_fake_func[0].vd_late_process = video_late_proc; |
| vd_fake_func[0].vd_misc_early_proc = NULL; |
| vd_fake_func[0].vd_misc_late_proc = NULL; |
| vd_fake_func[0].fake_func_id = AMVIDEO; |
| |
| /* for pip */ |
| vd_fake_func[1].vd_toggle_frame = video_toggle_frame; |
| vd_fake_func[1].vd_swap_frame = NULL; |
| vd_fake_func[1].vd_render_frame = NULL; |
| vd_fake_func[1].vd_early_process = video_early_proc; |
| vd_fake_func[1].vd_late_process = video_late_proc; |
| vd_fake_func[1].vd_misc_early_proc = NULL; |
| vd_fake_func[1].vd_misc_late_proc = NULL; |
| vd_fake_func[1].fake_func_id = PIP1; |
| |
| /* for pip2 */ |
| vd_fake_func[2].vd_toggle_frame = video_toggle_frame; |
| vd_fake_func[2].vd_swap_frame = NULL; |
| vd_fake_func[2].vd_render_frame = NULL; |
| vd_fake_func[2].vd_early_process = video_early_proc; |
| vd_fake_func[2].vd_late_process = video_late_proc; |
| vd_fake_func[2].vd_misc_early_proc = NULL; |
| vd_fake_func[2].vd_misc_late_proc = NULL; |
| vd_fake_func[2].fake_func_id = PIP2; |
| |
| /* for render0 */ |
| vd_fake_func[3].vd_toggle_frame = video_toggle_frame; |
| vd_fake_func[3].vd_swap_frame = NULL; |
| vd_fake_func[3].vd_render_frame = NULL; |
| vd_fake_func[3].vd_early_process = video_early_proc; |
| vd_fake_func[3].vd_late_process = video_late_proc; |
| vd_fake_func[3].vd_misc_early_proc = NULL; |
| vd_fake_func[3].vd_misc_late_proc = NULL; |
| vd_fake_func[3].fake_func_id = RENDER0; |
| |
| /* for render1 */ |
| vd_fake_func[4].vd_toggle_frame = video_toggle_frame; |
| vd_fake_func[4].vd_swap_frame = NULL; |
| vd_fake_func[4].vd_render_frame = NULL; |
| vd_fake_func[4].vd_early_process = video_early_proc; |
| vd_fake_func[4].vd_late_process = video_late_proc; |
| vd_fake_func[4].vd_misc_early_proc = NULL; |
| vd_fake_func[4].vd_misc_late_proc = NULL; |
| vd_fake_func[4].fake_func_id = RENDER1; |
| |
| /* for render2 */ |
| vd_fake_func[5].vd_toggle_frame = video_toggle_frame; |
| vd_fake_func[5].vd_swap_frame = NULL; |
| vd_fake_func[5].vd_render_frame = NULL; |
| vd_fake_func[5].vd_early_process = video_early_proc; |
| vd_fake_func[5].vd_late_process = video_late_proc; |
| vd_fake_func[5].vd_misc_early_proc = NULL; |
| vd_fake_func[5].vd_misc_late_proc = NULL; |
| vd_fake_func[5].fake_func_id = RENDER2; |
| } |
| |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| void pre_vsync_process(void) |
| { |
| int ret = 0, i; |
| bool rdma_enable = false, _rdma_enable_pre = false; |
| u32 path_frame_index; |
| struct vframe_s *path_new_frame[6] = {NULL}; |
| static s32 cur_vd1_path_id = VFM_PATH_INVALID; |
| bool path_switch = false; |
| struct vd_func_s *cur_pre_func = NULL; |
| s32 vd_path_id[MAX_VD_LAYER] = {0}; |
| struct path_id_s path_id; |
| struct cur_line_info_t *cur_line_info = NULL; |
| int enc_line; |
| |
| if (cur_dev->vsync_2to1_enable && frc_n2m_worked()) { |
| #ifdef CONFIG_AMLOGIC_VIDEO_COMPOSER |
| vsync_notify_video_composer(0, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base / 2); |
| #endif |
| #ifdef CONFIG_AMLOGIC_VIDEOQUEUE |
| vsync_notify_videoqueue(0, |
| vsync_pts_inc_scale, |
| vsync_pts_inc_scale_base / 2); |
| #endif |
| } |
| |
| set_cur_line_info(1); |
| enc_line = get_cur_enc_line(); |
| cur_line_info = get_cur_line_info(1); |
| vpp_trace_encline("ENTER-PRE-VSYNC", cur_line_info->enc_line_start, enc_line); |
| |
| for (i = 0; i < MAX_VD_LAYER; i++) |
| vd_path_id[i] = glayer_info[i].display_path_id; |
| path_id.vd1_path_id = vd_path_id[0]; |
| path_id.vd2_path_id = vd_path_id[1]; |
| path_id.vd3_path_id = vd_path_id[2]; |
| |
| vd_path_id[1] = VFM_PATH_INVALID; |
| vd_path_id[2] = VFM_PATH_INVALID; |
| vd_layer[0].cur_pre_func = vd_layer[0].next_pre_func; |
| cur_pre_func = vd_layer[0].cur_pre_func; |
| if (!cur_pre_func) |
| goto pre_exit_1; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| pre_vsync_rdma_config_pre(); |
| rdma_enable = is_pre_vsync_rdma_enable(); |
| _rdma_enable_pre = pre_vsync_rdma_enable_pre; |
| #endif |
| /* misc early process */ |
| if (cur_pre_func->vd_misc_early_proc) { |
| ret = cur_pre_func->vd_misc_early_proc |
| (0, rdma_enable, _rdma_enable_pre); |
| if (ret < 0) |
| goto pre_exit_2; |
| } |
| /* early process */ |
| if (cur_pre_func->vd_early_process) { |
| ret = cur_pre_func->vd_early_process(0, 0); |
| if (ret < 0) |
| goto pre_exit_2; |
| } |
| |
| if (cur_pre_func->vd_toggle_frame) { |
| path_frame_index = cur_pre_func->path_frame_index; |
| path_new_frame[path_frame_index] = |
| cur_pre_func->vd_toggle_frame(0, 0, vd_path_id, &path_id); |
| pre_vsync_count++; |
| } |
| if (!vd_layer[0].global_output) { |
| cur_vd1_path_id = VFM_PATH_INVALID; |
| vd_path_id[0] = VFM_PATH_INVALID; |
| } |
| if (debug_common_flag & DEBUG_FLAG_COMMON_PER_PREVSYNC) |
| dump_current_display_regs_info(); |
| |
| if (cur_vd1_path_id != vd_path_id[0]) |
| path_switch = true; |
| /* do vd swap */ |
| if (cur_pre_func->vd_swap_frame) |
| cur_pre_func->vd_swap_frame(0, |
| vd_path_id[0], |
| cur_vd1_path_id, |
| &path_new_frame[0]); |
| |
| /* filter setting management */ |
| if (cur_pre_func->vd_render_frame) |
| cur_pre_func->vd_render_frame(&vd_layer[0], vinfo); |
| /* do blend set */ |
| if (cur_dev->pre_vsync_enable) |
| vpp_blend_update(vinfo, PRE_VSYNC); |
| pre_exit_2: |
| if (cur_pre_func->vd_late_process) |
| cur_pre_func->vd_late_process(0, 0); |
| |
| if (cur_pre_func->vd_misc_late_proc) |
| cur_pre_func->vd_misc_late_proc(0); |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| pre_vsync_rdma_config(); |
| pre_vsync_rdma_enable_pre = is_pre_vsync_rdma_enable(); |
| #endif |
| cur_vd1_path_id = vd_path_id[0]; |
| pre_exit_1: |
| //trace_for_pre_vsync(); |
| enc_line = get_cur_enc_line(); |
| vpp_trace_encline("AFTER-PRE-VSYNC-RDMA", cur_line_info->enc_line_start, enc_line); |
| } |
| #endif |
| |
| void post_vsync_process(void) |
| { |
| unsigned char frame_par_di_set = 0; |
| struct vframe_s *path_new_frame[6] = {NULL}; |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| struct vframe_s *di_post_vf = NULL; |
| bool di_post_process_done = false; |
| #endif |
| static s32 cur_vd_path_id[MAX_VD_LAYER] = {VFM_PATH_INVALID}; |
| s32 vd_path_id[MAX_VD_LAYER] = {0}; |
| s32 vd_path_id_temp[MAX_VD_LAYER] = {0}; |
| int i, ret = 0; |
| bool path_switch = false; |
| u32 path_frame_index; |
| struct path_id_s path_id; |
| struct cur_line_info_t *cur_line_info = NULL; |
| int enc_line; |
| |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| iotrace_misc_record_write(RECORD_TYPE_VSYNC_IN, 0, 0, 0); |
| #endif |
| |
| set_cur_line_info(0); |
| enc_line = get_cur_enc_line(); |
| cur_line_info = get_cur_line_info(0); |
| vpp_trace_encline("ENTER-VSYNC", cur_line_info->enc_line_start, enc_line); |
| |
| if (cur_dev->display_module != S5_DISPLAY_MODULE) |
| blend_reg_conflict_detect(); |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| else |
| check_afbc_status(); |
| #endif |
| if (vd_layer[0].force_disable) |
| atomic_set(&vt_disable_video_done, 1); |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_MSYNC |
| msync_vsync_update(); |
| #endif |
| for (i = 0; i < MAX_VD_LAYER; i++) { |
| vd_path_id[i] = glayer_info[i].display_path_id; |
| if (cur_vd_path_id[i] == 0xff) |
| cur_vd_path_id[i] = vd_path_id[i]; |
| } |
| path_id.vd1_path_id = vd_path_id[0]; |
| path_id.vd2_path_id = vd_path_id[1]; |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| path_id.vd3_path_id = vd_path_id[2]; |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| /* Just a workaround to enable RDMA without any register config. |
| * because rdma is enabled after first rdma config. |
| * Previously, it will write register directly and |
| * maybe out of blanking in first irq. |
| */ |
| if (first_irq) |
| goto LATE_PROC; |
| #endif |
| |
| for (i = 0; i < MAX_VIDEO_FAKE; i++) |
| vd_fake_func[i].video_process_flag = 0; |
| |
| do_video_path_select(); |
| do_fake_video_select(); |
| /* misc early process */ |
| ret = misc_early_proc(); |
| if (ret < 0) |
| goto exit; |
| /* early process */ |
| for (i = 0; i < cur_dev->max_vd_layers; i++) |
| if (vd_layer[i].vd_func.vd_early_process) { |
| ret = vd_layer[i].vd_func.vd_early_process(i, 0); |
| if (ret < 0) |
| goto exit; |
| } |
| for (i = 0; i < MAX_VIDEO_FAKE; i++) { |
| if (!vd_fake_func[i].video_process_flag) |
| if (vd_fake_func[i].vd_early_process) |
| vd_fake_func[i].vd_early_process(0xff, i); |
| } |
| /* do toggle frame */ |
| for (i = 0; i < cur_dev->max_vd_layers; i++) { |
| if (vd_layer[i].vd_func.vd_toggle_frame) { |
| path_frame_index = vd_layer[i].vd_func.path_frame_index; |
| path_new_frame[path_frame_index] = |
| vd_layer[i].vd_func.vd_toggle_frame(i, 0, vd_path_id, &path_id); |
| if (go_exit) |
| goto exit; |
| if (!vd_layer[i].global_output) { |
| switch (i) { |
| #ifdef CHECK_LATER |
| case 0: |
| /* CHECK_LATER FIXME: if need enable for vd1 */ |
| cur_vd_path_id[0] = VFM_PATH_INVALID; |
| vd_path_id[0] = VFM_PATH_INVALID; |
| break; |
| #endif |
| case 1: |
| case 2: |
| cur_vd_path_id[i] = VFM_PATH_INVALID; |
| vd_path_id[i] = VFM_PATH_INVALID; |
| break; |
| } |
| } |
| } |
| } |
| |
| if (debug_flag & DEBUG_FLAG_PRINT_DISBUF_PER_VSYNC) |
| dump_current_display_regs_info(); |
| |
| #ifdef CONFIG_AMLOGIC_ZAPPER_CUT |
| if (cur_vd_path_id[0] != vd_path_id[0] || |
| cur_vd_path_id[1] != vd_path_id[1]) |
| path_switch = true; |
| |
| if (path_switch && |
| (debug_flag & DEBUG_FLAG_PRINT_PATH_SWITCH)) { |
| pr_info("VID: === before path switch ===\n"); |
| pr_info("VID: \tcur_path_id: %d, %d;\nVID: \tnew_path_id: %d, %d;\nVID: \ttoggle:%p, %p, %p %p, %p, %p\nVID: \tcur:%p, %p, %p, %p;\n", |
| cur_vd_path_id[0], cur_vd_path_id[1], |
| vd_path_id[0], vd_path_id[1], |
| path_new_frame[0], path_new_frame[1], |
| path_new_frame[2], path_new_frame[3], |
| path_new_frame[4], path_new_frame[5], |
| cur_dispbuf[0], cur_dispbuf[1], |
| gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL, |
| gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL); |
| pr_info("VID: \tdispbuf:%p, %p; \tvf_ext:%p, %p;\nVID: \tlocal:%p, %p, %p, %p\n", |
| vd_layer[0].dispbuf, vd_layer[1].dispbuf, |
| vd_layer[0].vf_ext, vd_layer[1].vf_ext, |
| &vf_local[0], &vf_local[1], |
| gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL, |
| gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL); |
| pr_info("VID: \tblackout:%d %d; force:%d;\n", |
| blackout[0], blackout[1], force_blackout); |
| } |
| |
| if (debug_flag & DEBUG_FLAG_PRINT_DISBUF_PER_VSYNC) { |
| u32 frame_index[6] = {0}, i = 0; |
| u64 timestamp[6] = {0}; |
| struct vframe_s *new_frame = NULL; |
| |
| pr_info("VID(%s): path id: %d, %d; new_frame:%p, %p, %p, %p, %p, %p cur:%p, %p, %p, %p; vd dispbuf:%p, %p; vf_ext:%p, %p; local:%p, %p, %p, %p\n", |
| __func__, |
| vd_path_id[0], vd_path_id[1], |
| path_new_frame[0], path_new_frame[1], |
| path_new_frame[2], path_new_frame[3], |
| path_new_frame[4], path_new_frame[5], |
| cur_dispbuf[0], cur_dispbuf[1], |
| gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL, |
| gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL, |
| vd_layer[0].dispbuf, vd_layer[1].dispbuf, |
| vd_layer[0].vf_ext, vd_layer[1].vf_ext, |
| &vf_local, &vf_local[1], |
| gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL, |
| gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL); |
| for (i = 0; i < 6; i++) { |
| new_frame = path_new_frame[i]; |
| if (new_frame) { |
| frame_index[i] = new_frame->frame_index; |
| timestamp[i] = div_u64(new_frame->timestamp, |
| 1000000000); |
| } |
| } |
| pr_info("VID(%s): new_frame frame_index:%d, %d, %d, %d, %d, %d; new_frame timestamp:%lld %lld %lld %lld %lld %lld\n", |
| __func__, |
| frame_index[0], frame_index[1], frame_index[2], frame_index[3], |
| frame_index[4], frame_index[5], timestamp[0], timestamp[1], |
| timestamp[2], timestamp[3], timestamp[4], timestamp[5] |
| ); |
| } |
| vd_path_id_temp[0] = glayer_info[0].display_path_id; |
| vd_path_id_temp[1] = glayer_info[1].display_path_id; |
| for (i = 0; i < MAX_VIDEO_FAKE; i++) { |
| if (!vd_fake_func[i].video_process_flag) |
| if (vd_fake_func[i].vd_toggle_frame) |
| vd_fake_func[i].vd_toggle_frame |
| (0xff, i, |
| vd_path_id_temp, &path_id); |
| } |
| |
| /* do vd swap */ |
| for (i = 0; i < cur_dev->max_vd_layers; i++) |
| if (vd_layer[i].vd_func.vd_swap_frame) |
| vd_layer[i].vd_func.vd_swap_frame(i, vd_path_id[i], |
| cur_vd_path_id[i], |
| &path_new_frame[0]); |
| if (debug_flag & DEBUG_FLAG_PRINT_DISBUF_PER_VSYNC) |
| pr_info("VID(%s): layer enable status: VD1:e:%d,e_save:%d,g:%d,d:%d,f:%s; VD2:e:%d,e_save:%d,g:%d,d:%d,f:%s;", |
| __func__, |
| vd_layer[0].enabled, vd_layer[0].enabled_status_saved, |
| vd_layer[0].global_output, vd_layer[0].disable_video, |
| vd_layer[0].force_disable ? "true" : "false", |
| vd_layer[1].enabled, vd_layer[1].enabled_status_saved, |
| vd_layer[1].global_output, vd_layer[1].disable_video, |
| vd_layer[1].force_disable ? "true" : "false"); |
| |
| #else |
| if (cur_vd_path_id[0] != vd_path_id[0] || |
| cur_vd_path_id[1] != vd_path_id[1] || |
| cur_vd_path_id[2] != vd_path_id[2]) |
| path_switch = true; |
| |
| if (path_switch && |
| (debug_flag & DEBUG_FLAG_PRINT_PATH_SWITCH)) { |
| pr_info("VID: === before path switch ===\n"); |
| pr_info("VID: \tcur_path_id: %d, %d, %d;\nVID: \tnew_path_id: %d, %d, %d;\nVID: \ttoggle:%p, %p, %p %p, %p, %p\nVID: \tcur:%p, %p, %p, %p, %p, %p;\n", |
| cur_vd_path_id[0], cur_vd_path_id[1], cur_vd_path_id[2], |
| vd_path_id[0], vd_path_id[1], vd_path_id[2], |
| path_new_frame[0], path_new_frame[1], |
| path_new_frame[2], path_new_frame[3], |
| path_new_frame[4], path_new_frame[5], |
| cur_dispbuf[0], cur_dispbuf[1], cur_dispbuf[2], |
| gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL, |
| gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL, |
| gvideo_recv[2] ? gvideo_recv[2]->cur_buf : NULL); |
| |
| pr_info("VID: \tdispbuf:%p, %p, %p; \tvf_ext:%p, %p, %p;\nVID: \tlocal:%p, %p, %p, %p, %p, %p\n", |
| vd_layer[0].dispbuf, vd_layer[1].dispbuf, vd_layer[2].dispbuf, |
| vd_layer[0].vf_ext, vd_layer[1].vf_ext, vd_layer[2].vf_ext, |
| &vf_local[0], &vf_local[1], &vf_local[2], |
| gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL, |
| gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL, |
| gvideo_recv[2] ? &gvideo_recv[2]->local_buf : NULL); |
| pr_info("VID: \tblackout:%d %d, %d force:%d;\n", |
| blackout[0], blackout[1], blackout[2], force_blackout); |
| } |
| |
| if (debug_flag & DEBUG_FLAG_PRINT_DISBUF_PER_VSYNC) { |
| u32 frame_index[6] = {0}, i = 0; |
| u64 timestamp[6] = {0}; |
| struct vframe_s *new_frame = NULL; |
| |
| pr_info("VID(%s): path id: %d, %d, %d; new_frame:%p, %p, %p, %p, %p, %p cur:%p, %p, %p, %p, %p, %p; vd dispbuf:%p, %p, %p; vf_ext:%p, %p, %p; local:%p, %p, %p, %p, %p, %p\n", |
| __func__, |
| vd_path_id[0], vd_path_id[1], vd_path_id[2], |
| path_new_frame[0], path_new_frame[1], |
| path_new_frame[2], path_new_frame[3], |
| path_new_frame[4], path_new_frame[5], |
| cur_dispbuf[0], cur_dispbuf[1], cur_dispbuf[2], |
| gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL, |
| gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL, |
| gvideo_recv[2] ? gvideo_recv[2]->cur_buf : NULL, |
| vd_layer[0].dispbuf, vd_layer[1].dispbuf, vd_layer[2].dispbuf, |
| vd_layer[0].vf_ext, vd_layer[1].vf_ext, vd_layer[2].vf_ext, |
| &vf_local, &vf_local[1], &vf_local[2], |
| gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL, |
| gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL, |
| gvideo_recv[2] ? &gvideo_recv[2]->local_buf : NULL); |
| for (i = 0; i < 6; i++) { |
| new_frame = path_new_frame[i]; |
| if (new_frame) { |
| frame_index[i] = new_frame->frame_index; |
| timestamp[i] = div_u64(new_frame->timestamp, |
| 1000000000); |
| } |
| } |
| pr_info("VID(%s): new_frame frame_index:%d, %d, %d, %d, %d, %d; new_frame timestamp:%lld %lld %lld %lld %lld %lld\n", |
| __func__, |
| frame_index[0], frame_index[1], frame_index[2], frame_index[3], |
| frame_index[4], frame_index[5], timestamp[0], timestamp[1], |
| timestamp[2], timestamp[3], timestamp[4], timestamp[5] |
| ); |
| } |
| vd_path_id_temp[0] = glayer_info[0].display_path_id; |
| vd_path_id_temp[1] = glayer_info[1].display_path_id; |
| vd_path_id_temp[2] = glayer_info[2].display_path_id; |
| |
| for (i = 0; i < MAX_VIDEO_FAKE; i++) { |
| if (!vd_fake_func[i].video_process_flag) |
| if (vd_fake_func[i].vd_toggle_frame) |
| vd_fake_func[i].vd_toggle_frame |
| (0xff, i, |
| vd_path_id_temp, &path_id); |
| } |
| |
| /* do vd swap */ |
| for (i = 0; i < cur_dev->max_vd_layers; i++) |
| if (vd_layer[i].vd_func.vd_swap_frame) |
| vd_layer[i].vd_func.vd_swap_frame(i, vd_path_id[i], |
| cur_vd_path_id[i], |
| &path_new_frame[0]); |
| if (debug_flag & DEBUG_FLAG_PRINT_DISBUF_PER_VSYNC) |
| pr_info("(%s)VID: layer enable status: VD1:e:%d,e_save:%d,g:%d,d:%d,f:%s; VD2:e:%d,e_save:%d,g:%d,d:%d,f:%s; VD3:e:%d,e_save:%d,g:%d,d:%d,f:%s", |
| __func__, |
| vd_layer[0].enabled, vd_layer[0].enabled_status_saved, |
| vd_layer[0].global_output, vd_layer[0].disable_video, |
| vd_layer[0].force_disable ? "true" : "false", |
| vd_layer[1].enabled, vd_layer[1].enabled_status_saved, |
| vd_layer[1].global_output, vd_layer[1].disable_video, |
| vd_layer[1].force_disable ? "true" : "false", |
| vd_layer[2].enabled, vd_layer[2].enabled_status_saved, |
| vd_layer[2].global_output, vd_layer[2].disable_video, |
| vd_layer[2].force_disable ? "true" : "false"); |
| #endif |
| |
| /* filter setting management */ |
| for (i = 0; i < cur_dev->max_vd_layers; i++) { |
| if (vd_layer[i].vd_func.vd_render_frame) |
| ret = vd_layer[i].vd_func.vd_render_frame |
| (&vd_layer[i], vinfo); |
| if (i == 0) |
| frame_par_di_set = ret; |
| } |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (support_multi_core1()) |
| amdolby_vision_proc(&vd_layer[0], vd_layer[0].cur_frame_par, |
| &vd_layer[1], vd_layer[1].cur_frame_par); |
| set_amdv_delay_work_flag(); |
| #endif |
| |
| if (path_switch && |
| (debug_flag & DEBUG_FLAG_PRINT_PATH_SWITCH)) { |
| pr_info("VID: === After path switch ===\n"); |
| pr_info("VID: \tpath_id: %d, %d, %d;\nVID: \ttoggle:%p, %p, %p %p, %p, %p\nVID: \tcur:%p, %p, %p, %p, %p, %p;\n", |
| vd_path_id[0], vd_path_id[1], vd_path_id[2], |
| path_new_frame[0], path_new_frame[1], |
| path_new_frame[2], path_new_frame[3], |
| path_new_frame[4], path_new_frame[5], |
| cur_dispbuf[0], cur_dispbuf[1], cur_dispbuf[2], |
| gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL, |
| gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL, |
| gvideo_recv[2] ? gvideo_recv[2]->cur_buf : NULL); |
| pr_info("VID: \tdispbuf:%p, %p, %p; \tvf_ext:%p, %p, %p;\nVID: \tlocal:%p, %p, %p, %p, %p, %p\n", |
| vd_layer[0].dispbuf, vd_layer[1].dispbuf, |
| vd_layer[2].dispbuf, |
| vd_layer[0].vf_ext, vd_layer[1].vf_ext, |
| vd_layer[2].vf_ext, |
| &vf_local[0], &vf_local[1], &vf_local[2], |
| gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL, |
| gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL, |
| gvideo_recv[2] ? &gvideo_recv[2]->local_buf : NULL); |
| pr_info("VID: \tblackout:%d %d, %d force:%d;\n", |
| blackout[0], blackout[1], blackout[2], force_blackout); |
| } |
| |
| /* di post process */ |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| if (dil_get_diff_ver_flag() == DI_DRV_DEINTERLACE) { |
| if (cur_dispbuf[0] && cur_dispbuf[0]->process_fun && |
| (vd_path_id[0] == VFM_PATH_AMVIDEO || |
| vd_path_id[0] == VFM_PATH_DEF)) |
| di_post_vf = cur_dispbuf[0]; |
| else if (vd_layer[0].dispbuf && |
| vd_layer[0].dispbuf->process_fun && |
| is_di_post_mode(vd_layer[0].dispbuf)) |
| di_post_vf = vd_layer[0].dispbuf; |
| if (vd_layer[0].do_switch) |
| di_post_vf = NULL; |
| if (di_post_vf) { |
| /* for new deinterlace driver */ |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| if (debug_flag & DEBUG_FLAG_PRINT_RDMA) { |
| if (enable_rdma_log_count > 0) |
| pr_info("call process_fun\n"); |
| } |
| #endif |
| if (cur_frame_par[0]) |
| di_post_vf->process_fun |
| (di_post_vf->private_data, |
| vd_layer[0].start_x_lines | |
| (cur_frame_par[0]->vscale_skip_count << |
| 24) | (frame_par_di_set << 16), |
| vd_layer[0].end_x_lines, |
| vd_layer[0].start_y_lines, |
| vd_layer[0].end_y_lines, |
| di_post_vf); |
| di_post_process_done = true; |
| } |
| } |
| #endif |
| exit: |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| if (legacy_vpp && |
| !di_post_process_done && |
| is_di_post_on()) |
| DI_POST_UPDATE_MC(); |
| #endif |
| #ifdef ENABLE_PLINK |
| if (!vd_layer[0].need_disable_plink || !is_plink_on(&vd_layer[0])) |
| atomic_set(&vd_layer[0].disable_plink_done, 1); |
| #endif |
| |
| /* update alpha win */ |
| if (cur_dev->pre_vsync_enable) |
| alpha_win_set(&vd_layer[0]); |
| |
| /* do blend,judge really update in update_vpp_input_info for vpp_index */ |
| if (!cur_dev->pre_vsync_enable) |
| vpp_blend_update(vinfo, VPP0); |
| |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| if (cur_dev->vd1_vsr_safa_support) |
| vsr_debug_mode_update(vsr_debug_mode, &vd_layer[0].sc_setting.vsr); |
| #endif |
| |
| /* late process */ |
| for (i = 0; i < cur_dev->max_vd_layers; i++) |
| if (vd_layer[i].vd_func.vd_late_process) |
| vd_layer[i].vd_func.vd_late_process(i, 0); |
| for (i = 0; i < MAX_VIDEO_FAKE; i++) { |
| if (!vd_fake_func[i].video_process_flag) |
| if (vd_fake_func[i].vd_late_process) |
| vd_fake_func[i].vd_late_process(0xff, i); |
| } |
| LATE_PROC: |
| misc_late_proc(); |
| for (i = 0; i < MAX_VD_LAYER; i++) |
| cur_vd_path_id[i] = vd_path_id[i]; |
| if (new_frame_cnt == 1 && !vsync_count_start) { |
| vsync_count_start = 1; |
| pr_info("%s, vsync_count_started\n", __func__); |
| } |
| |
| #endif |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| iotrace_misc_record_write(RECORD_TYPE_VSYNC_OUT, 0, 0, 0); |
| #endif |
| } |
| |
| int get_current_frame_para(int *top, int *left, int *bottom, int *right) |
| { |
| if (!cur_frame_par[0]) |
| return -1; |
| *top = cur_frame_par[0]->VPP_vd_start_lines_; |
| *left = cur_frame_par[0]->VPP_hd_start_lines_; |
| *bottom = cur_frame_par[0]->VPP_vd_end_lines_; |
| *right = cur_frame_par[0]->VPP_hd_end_lines_; |
| return 0; |
| } |
| |
| int get_current_vscale_skip_count(struct vframe_s *vf) |
| { |
| int ret = 0; |
| static struct vpp_frame_par_s frame_par; |
| |
| ret = vpp_set_filters |
| (&glayer_info[0], |
| vf, &frame_par, vinfo, |
| (is_amdv_on() && |
| is_amdv_stb_mode() && |
| for_amdv_certification()), |
| OP_FORCE_NOT_SWITCH_VF); |
| if (ret < 0) { |
| pr_info("%s vpp_set_filter fail\n", __func__); |
| return ret; |
| } |
| ret = frame_par.vscale_skip_count; |
| if (cur_frame_par[0] && (process_3d_type & MODE_3D_ENABLE)) |
| ret |= (cur_frame_par[0]->vpp_3d_mode << 8); |
| return ret; |
| } |
| |
| void release_di_buffer(int inst) |
| { |
| int i; |
| |
| for (i = 0; i < recycle_cnt[inst]; i++) { |
| if (recycle_buf[inst][i] && |
| recycle_buf[inst][i]->flag & VFRAME_FLAG_DI_PW_VFM && |
| IS_DI_POSTWRTIE(recycle_buf[inst][i]->type)) { |
| di_release_count++; |
| #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE |
| dim_post_keep_cmd_release2(recycle_buf[inst][i]); |
| #endif |
| } |
| recycle_buf[inst][i] = NULL; |
| } |
| recycle_cnt[inst] = 0; |
| } |
| |
| int get_display_info(void *data) |
| { |
| s32 w, h, x, y; |
| s32 x_end, y_end; |
| struct vdisplay_info_s *info_para = (struct vdisplay_info_s *)data; |
| const struct vinfo_s *info = get_current_vinfo(); |
| struct disp_info_s *layer = &glayer_info[0]; |
| struct vpp_frame_par_s *frame_par = cur_frame_par[0]; |
| |
| if (!frame_par || !info) |
| return -1; |
| if (info->mode == VMODE_INVALID) |
| return -1; |
| |
| x = layer->layer_left; |
| y = layer->layer_top; |
| w = layer->layer_width; |
| h = layer->layer_height; |
| |
| /* reverse and mirror case */ |
| if (layer->reverse) { |
| /* reverse x/y start */ |
| x_end = x + w - 1; |
| x = info->width - x_end - 1; |
| y_end = y + h - 1; |
| y = info->height - y_end - 1; |
| } else if (layer->mirror == H_MIRROR) { |
| /* horizontal mirror */ |
| x_end = x + w - 1; |
| x = info->width - x_end - 1; |
| } else if (layer->mirror == V_MIRROR) { |
| /* vertical mirror */ |
| y_end = y + h - 1; |
| y = info->height - y_end - 1; |
| } |
| |
| if (w == 0 || w > info->width) |
| w = info->width; |
| if (h == 0 || h > info->height) |
| h = info->height; |
| |
| info_para->frame_hd_start_lines_ = frame_par->VPP_hd_start_lines_; |
| info_para->frame_hd_end_lines_ = frame_par->VPP_hd_end_lines_; |
| info_para->frame_vd_start_lines_ = frame_par->VPP_vd_start_lines_; |
| info_para->frame_vd_end_lines_ = frame_par->VPP_vd_end_lines_; |
| info_para->display_hsc_startp = frame_par->VPP_hsc_startp; |
| info_para->display_hsc_endp = frame_par->VPP_hsc_endp; |
| info_para->display_vsc_startp = frame_par->VPP_vsc_startp; |
| info_para->display_vsc_endp = frame_par->VPP_vsc_endp; |
| info_para->screen_vd_h_start_ = |
| frame_par->VPP_post_blend_vd_h_start_; |
| info_para->screen_vd_h_end_ = |
| frame_par->VPP_post_blend_vd_h_end_; |
| info_para->screen_vd_v_start_ = |
| frame_par->VPP_post_blend_vd_v_start_; |
| info_para->screen_vd_v_end_ = frame_par->VPP_post_blend_vd_v_end_; |
| |
| return 0; |
| } |
| |
| struct vframe_s *get_dispbuf(u8 layer_id) |
| { |
| struct vframe_s *dispbuf = NULL; |
| struct video_layer_s *layer = NULL; |
| int i = 0; |
| |
| if (layer_id >= MAX_VD_LAYERS) |
| return NULL; |
| switch (glayer_info[layer_id].display_path_id) { |
| case VFM_PATH_DEF: |
| for (i = 0; i < MAX_VD_LAYER; i++) |
| if (layer_id == i && cur_dispbuf[i]) |
| dispbuf = cur_dispbuf[i]; |
| break; |
| case VFM_PATH_AMVIDEO: |
| if (cur_dispbuf[0]) |
| dispbuf = cur_dispbuf[0]; |
| break; |
| case VFM_PATH_PIP: |
| if (cur_dispbuf[1]) |
| dispbuf = cur_dispbuf[1]; |
| break; |
| case VFM_PATH_PIP2: |
| if (cur_dispbuf[2]) |
| dispbuf = cur_dispbuf[2]; |
| break; |
| case VFM_PATH_VIDEO_RENDER0: |
| if (gvideo_recv[0] && |
| gvideo_recv[0]->cur_buf) |
| dispbuf = gvideo_recv[0]->cur_buf; |
| break; |
| case VFM_PATH_VIDEO_RENDER1: |
| if (gvideo_recv[1] && |
| gvideo_recv[1]->cur_buf) |
| dispbuf = gvideo_recv[1]->cur_buf; |
| break; |
| case VFM_PATH_VIDEO_RENDER2: |
| if (gvideo_recv[2] && |
| gvideo_recv[2]->cur_buf) |
| dispbuf = gvideo_recv[2]->cur_buf; |
| break; |
| case VFM_PATH_VIDEO_RENDER5: |
| if (gvideo_recv_vpp[0] && |
| gvideo_recv_vpp[0]->cur_buf) |
| dispbuf = gvideo_recv_vpp[0]->cur_buf; |
| break; |
| case VFM_PATH_VIDEO_RENDER6: |
| if (gvideo_recv_vpp[1] && |
| gvideo_recv_vpp[1]->cur_buf) |
| dispbuf = gvideo_recv_vpp[1]->cur_buf; |
| break; |
| default: |
| break; |
| } |
| |
| layer = get_layer_by_layer_id(layer_id); |
| if (layer && dispbuf && |
| !is_local_vf(dispbuf) && |
| layer->switch_vf && layer->vf_ext) |
| dispbuf = layer->vf_ext; |
| return dispbuf; |
| } |
| |
| static void pipx_vf_unreg_provider(u8 path_index) |
| { |
| ulong flags; |
| int keeped = 0, ret = 0; |
| bool layer1_used = false; |
| bool layer2_used = false; |
| bool layer3_used = false; |
| u32 enabled = 0; |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| int i; |
| #endif |
| |
| atomic_inc(&video_unreg_flag); |
| while (atomic_read(&video_inirq_flag) > 0) |
| schedule(); |
| if (cur_dev->pre_vsync_enable) |
| while (atomic_read(&video_prevsync_inirq_flag) > 0) |
| schedule(); |
| |
| spin_lock_irqsave(&lock, flags); |
| |
| ret = update_video_recycle_buffer(path_index); |
| if (ret == -EAGAIN) { |
| /* The currently displayed vf is not added to the queue |
| * that needs to be released. You need to release the vf |
| * data in the release queue before adding the currently |
| * displayed vf to the release queue. |
| */ |
| release_di_buffer(path_index); |
| update_video_recycle_buffer(path_index); |
| } |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| dispbuf_to_put_num[path_index] = 0; |
| for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) |
| dispbuf_to_put[path_index][i] = NULL; |
| |
| cur_rdma_buf[path_index] = NULL; |
| #endif |
| i = path_index; |
| if (cur_dispbuf[path_index]) { |
| if (cur_dispbuf[path_index]->vf_ext && |
| IS_DI_POSTWRTIE(cur_dispbuf[path_index]->type)) { |
| struct vframe_s *tmp; |
| |
| if (cur_dispbuf[path_index]->uvm_vf) |
| tmp = cur_dispbuf[path_index]->uvm_vf; |
| else |
| tmp = (struct vframe_s *)cur_dispbuf[path_index]->vf_ext; |
| memcpy(&tmp->pic_mode, &cur_dispbuf[path_index]->pic_mode, |
| sizeof(struct vframe_pic_mode_s)); |
| vf_local_ext[path_index] = *tmp; |
| vf_local[path_index] = *cur_dispbuf[path_index]; |
| vf_local[path_index].vf_ext = (void *)&vf_local_ext[path_index]; |
| vf_local[path_index].uvm_vf = NULL; |
| vf_local_ext[path_index].ratio_control = vf_local[path_index].ratio_control; |
| } else if (cur_dispbuf[path_index]->vf_ext && |
| is_plink_source(cur_dispbuf[path_index]) && |
| !HAS_DI_LOCAL_BUF(cur_dispbuf[path_index]->di_flag)) { |
| u32 tmp_rc; |
| struct vframe_s *tmp; |
| |
| if (cur_dispbuf[path_index]->uvm_vf) |
| tmp = cur_dispbuf[path_index]->uvm_vf; |
| else |
| tmp = (struct vframe_s *)cur_dispbuf[path_index]->vf_ext; |
| if (debug_flag & DEBUG_FLAG_PLINK) |
| pr_info("%s %d: #1 plink: cur_dispbuf:%px vf_ext:%px uvm_vf:%px flag:%x\n", |
| __func__, path_index, |
| cur_dispbuf[path_index], |
| cur_dispbuf[path_index]->vf_ext, |
| cur_dispbuf[path_index]->uvm_vf, |
| cur_dispbuf[path_index]->flag); |
| tmp_rc = cur_dispbuf[path_index]->ratio_control; |
| memcpy(&tmp->pic_mode, &cur_dispbuf[path_index]->pic_mode, |
| sizeof(struct vframe_pic_mode_s)); |
| vf_local[path_index] = *tmp; |
| vf_local[path_index].ratio_control = tmp_rc; |
| vf_local[path_index].vf_ext = NULL; |
| vf_local[path_index].uvm_vf = NULL; |
| } else if (IS_DI_POST(cur_dispbuf[path_index]->type) && |
| (cur_dispbuf[path_index]->vf_ext || cur_dispbuf[path_index]->uvm_vf) && |
| !HAS_DI_LOCAL_BUF(cur_dispbuf[path_index]->di_flag)) { |
| u32 tmp_rc; |
| struct vframe_s *tmp; |
| |
| if (cur_dispbuf[path_index]->uvm_vf) |
| tmp = cur_dispbuf[path_index]->uvm_vf; |
| else |
| tmp = (struct vframe_s *)cur_dispbuf[path_index]->vf_ext; |
| if (debug_flag & DEBUG_FLAG_PLINK) |
| pr_info("%s %d: #2 plink: cur_dispbuf:%px vf_ext:%px uvm_vf:%px flag:%x\n", |
| __func__, path_index, |
| cur_dispbuf[path_index], |
| cur_dispbuf[path_index]->vf_ext, |
| cur_dispbuf[path_index]->uvm_vf, |
| cur_dispbuf[path_index]->flag); |
| tmp_rc = cur_dispbuf[path_index]->ratio_control; |
| memcpy(&tmp->pic_mode, &cur_dispbuf[path_index]->pic_mode, |
| sizeof(struct vframe_pic_mode_s)); |
| vf_local[path_index] = *tmp; |
| vf_local[path_index].ratio_control = tmp_rc; |
| vf_local[path_index].vf_ext = NULL; |
| vf_local[path_index].uvm_vf = NULL; |
| |
| } else { |
| vf_local[path_index] = *cur_dispbuf[path_index]; |
| vf_local[path_index].vf_ext = NULL; |
| vf_local[path_index].uvm_vf = NULL; |
| |
| } |
| cur_dispbuf[path_index] = &vf_local[path_index]; |
| cur_dispbuf[path_index]->video_angle = 0; |
| } |
| pip_frame_count[path_index] = 0; |
| spin_unlock_irqrestore(&lock, flags); |
| |
| if (vd_layer[0].dispbuf_mapping |
| == &cur_dispbuf[path_index]) { |
| layer1_used = true; |
| enabled |= get_video_enabled(0); |
| } |
| if (vd_layer[1].dispbuf_mapping |
| == &cur_dispbuf[path_index]) { |
| layer2_used = true; |
| enabled |= get_video_enabled(1); |
| } |
| if (vd_layer[2].dispbuf_mapping |
| == &cur_dispbuf[path_index]) { |
| layer3_used = true; |
| enabled |= get_video_enabled(2); |
| } |
| |
| if (!layer1_used && !layer2_used && !layer3_used) |
| cur_dispbuf[path_index] = NULL; |
| |
| if (blackout[2] | force_blackout) { |
| if (layer1_used) |
| safe_switch_videolayer |
| (0, false, false); |
| if (layer2_used) |
| safe_switch_videolayer |
| (1, false, false); |
| if (layer3_used) |
| safe_switch_videolayer |
| (2, false, false); |
| try_free_keep_vdx(path_index, 1); |
| } |
| |
| if (cur_dispbuf[path_index] && enabled) |
| keeped = vf_keep_current_locked(path_index, cur_dispbuf[path_index], NULL); |
| else if (cur_dispbuf[path_index]) |
| keeped = 0; |
| |
| pr_info("%s: vd1 used: %s, vd2 used: %s, vd3 used: %s, keep_ret:%d, black_out:%d, cur_dispbuf%d:%p\n", |
| __func__, |
| layer1_used ? "true" : "false", |
| layer2_used ? "true" : "false", |
| layer3_used ? "true" : "false", |
| keeped, blackout[path_index] | force_blackout, |
| path_index, |
| cur_dispbuf[path_index]); |
| |
| if (keeped <= 0) {/*keep failed.*/ |
| if (keeped < 0) |
| pr_info("keep frame failed, disable videopip%d now.\n", |
| path_index - 1); |
| else |
| pr_info("keep frame skip, disable videopip%d again.\n", |
| path_index - 1); |
| if (layer1_used) |
| safe_switch_videolayer |
| (0, false, false); |
| if (layer2_used) |
| safe_switch_videolayer |
| (1, false, false); |
| if (layer3_used) |
| safe_switch_videolayer |
| (2, false, false); |
| try_free_keep_vdx(path_index, 1); |
| } |
| |
| /*disable_videopip = VIDEO_DISABLE_FORNEXT;*/ |
| /*DisableVideoLayer2();*/ |
| atomic_dec(&video_unreg_flag); |
| } |
| |
| static void pipx_vf_light_unreg_provider(u8 path_index, int need_keep_frame) |
| { |
| ulong flags; |
| int ret = 0; |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| int i; |
| #endif |
| |
| atomic_inc(&video_unreg_flag); |
| while (atomic_read(&video_inirq_flag) > 0) |
| schedule(); |
| if (cur_dev->pre_vsync_enable) |
| while (atomic_read(&video_prevsync_inirq_flag) > 0) |
| schedule(); |
| |
| spin_lock_irqsave(&lock, flags); |
| ret = update_video_recycle_buffer(path_index); |
| if (ret == -EAGAIN) { |
| /* The currently displayed vf is not added to the queue |
| * that needs to be released. You need to release the vf |
| * data in the release queue before adding the currently |
| * displayed vf to the release queue. |
| */ |
| release_di_buffer(path_index); |
| update_video_recycle_buffer(path_index); |
| } |
| #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA |
| dispbuf_to_put_num[path_index] = 0; |
| for (i = 0; i < DISPBUF_TO_PUT_MAX; i++) |
| dispbuf_to_put[path_index][i] = NULL; |
| cur_rdma_buf[path_index] = NULL; |
| #endif |
| |
| if (cur_dispbuf[path_index]) { |
| if (cur_dispbuf[path_index]->vf_ext && |
| IS_DI_POSTWRTIE(cur_dispbuf[path_index]->type)) { |
| struct vframe_s *tmp; |
| |
| if (cur_dispbuf[path_index]->uvm_vf) |
| tmp = cur_dispbuf[path_index]->uvm_vf; |
| else |
| tmp = (struct vframe_s *)cur_dispbuf[path_index]->vf_ext; |
| memcpy(&tmp->pic_mode, &cur_dispbuf[path_index]->pic_mode, |
| sizeof(struct vframe_pic_mode_s)); |
| vf_local_ext[path_index] = *tmp; |
| vf_local[path_index] = *cur_dispbuf[path_index]; |
| vf_local[path_index].vf_ext = (void *)&vf_local_ext[path_index]; |
| vf_local[path_index].uvm_vf = NULL; |
| vf_local_ext[path_index].ratio_control = vf_local[path_index].ratio_control; |
| } else if (cur_dispbuf[path_index]->vf_ext && |
| is_plink_source(cur_dispbuf[path_index]) && |
| !HAS_DI_LOCAL_BUF(cur_dispbuf[path_index]->di_flag)) { |
| u32 tmp_rc; |
| struct vframe_s *tmp; |
| |
| if (cur_dispbuf[path_index]->uvm_vf) |
| tmp = cur_dispbuf[path_index]->uvm_vf; |
| else |
| tmp = (struct vframe_s *)cur_dispbuf[path_index]->vf_ext; |
| if (debug_flag & DEBUG_FLAG_PLINK) |
| pr_info("%s %d: #1 plink: cur_dispbuf:%px vf_ext:%px uvm_vf:%px flag:%x\n", |
| __func__, path_index, |
| cur_dispbuf[path_index], |
| cur_dispbuf[path_index]->vf_ext, |
| cur_dispbuf[path_index]->uvm_vf, |
| cur_dispbuf[path_index]->flag); |
| tmp_rc = cur_dispbuf[path_index]->ratio_control; |
| memcpy(&tmp->pic_mode, &cur_dispbuf[path_index]->pic_mode, |
| sizeof(struct vframe_pic_mode_s)); |
| vf_local[path_index] = *tmp; |
| vf_local[path_index].ratio_control = tmp_rc; |
| vf_local[path_index].vf_ext = NULL; |
| vf_local[path_index].uvm_vf = NULL; |
| } else if (IS_DI_POST(cur_dispbuf[path_index]->type) && |
| (cur_dispbuf[path_index]->vf_ext || cur_dispbuf[path_index]->uvm_vf) && |
| !HAS_DI_LOCAL_BUF(cur_dispbuf[path_index]->di_flag)) { |
| u32 tmp_rc; |
| struct vframe_s *tmp; |
| |
| if (cur_dispbuf[path_index]->uvm_vf) |
| tmp = cur_dispbuf[path_index]->uvm_vf; |
| else |
| tmp = (struct vframe_s *)cur_dispbuf[path_index]->vf_ext; |
| if (debug_flag & DEBUG_FLAG_PLINK) |
| pr_info("%s %d: #2 plink: cur_dispbuf:%px vf_ext:%px uvm_vf:%px flag:%x\n", |
| __func__, path_index, |
| cur_dispbuf[path_index], |
| cur_dispbuf[path_index]->vf_ext, |
| cur_dispbuf[path_index]->uvm_vf, |
| cur_dispbuf[path_index]->flag); |
| tmp_rc = cur_dispbuf[path_index]->ratio_control; |
| memcpy(&tmp->pic_mode, &cur_dispbuf[path_index]->pic_mode, |
| sizeof(struct vframe_pic_mode_s)); |
| vf_local[path_index] = *tmp; |
| vf_local[path_index].ratio_control = tmp_rc; |
| vf_local[path_index].vf_ext = NULL; |
| vf_local[path_index].uvm_vf = NULL; |
| |
| } else { |
| vf_local[path_index] = *cur_dispbuf[path_index]; |
| vf_local[path_index].vf_ext = NULL; |
| vf_local[path_index].uvm_vf = NULL; |
| |
| } |
| cur_dispbuf[path_index] = &vf_local[path_index]; |
| } |
| |
| spin_unlock_irqrestore(&lock, flags); |
| |
| if (need_keep_frame && cur_dispbuf[path_index]) |
| vf_keep_current_locked(path_index, cur_dispbuf[path_index], NULL); |
| |
| atomic_dec(&video_unreg_flag); |
| } |
| |
| static int pipx_receiver_event_fun(u8 path_index, |
| int type, |
| void *data, |
| void *private_data) |
| { |
| if (type == VFRAME_EVENT_PROVIDER_UNREG) { |
| pipx_vf_unreg_provider(path_index); |
| |
| /* for pip */ |
| if (path_index == 1) { |
| atomic_dec(&video_recv_cnt); |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (is_amdv_enable()) { |
| if (dv_inst_pip >= 0) {/*tunnel modes*/ |
| dv_inst_unmap(dv_inst_pip); |
| dv_inst_pip = -1; |
| } |
| } |
| #endif |
| } |
| } else if (type == VFRAME_EVENT_PROVIDER_RESET) { |
| pipx_vf_light_unreg_provider(path_index, 1); |
| } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) { |
| pipx_vf_light_unreg_provider(path_index, 0); |
| } else if (type == VFRAME_EVENT_PROVIDER_REG) { |
| atomic_inc(&video_recv_cnt); |
| pipx_vf_light_unreg_provider(path_index, 0); |
| video_drop_vf_cnt[path_index] = 0; |
| #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION |
| if (path_index == 1) { |
| if (is_amdv_enable()) { |
| if (is_tunnel_mode(RECEIVERPIP_NAME)) { |
| dv_inst_map(&dv_inst_pip); |
| pr_info("pip receiver dv_inst_pip %d\n", dv_inst_pip); |
| } |
| } |
| } |
| #endif |
| } |
| return 0; |
| } |
| |
| int pip_receiver_event_fun(int type, |
| void *data, |
| void *private_data) |
| { |
| pipx_receiver_event_fun(1, type, data, private_data); |
| return 0; |
| } |
| |
| int pip2_receiver_event_fun(int type, |
| void *data, |
| void *private_data) |
| { |
| pipx_receiver_event_fun(2, type, data, private_data); |
| return 0; |
| } |
| |
| /////////////////////////////////////////////////////// |
| ssize_t blend_conflict_show(const struct class *cla, |
| const struct class_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "blend_conflict_cnt: %d\n", blend_conflict_cnt); |
| } |
| |
| unsigned int get_post_canvas(void) |
| { |
| return post_canvas; |
| } |
| EXPORT_SYMBOL(get_post_canvas); |
| |
| u32 get_blackout_policy(void) |
| { |
| /* only for vd1 */ |
| return blackout[0] | force_blackout; |
| } |
| EXPORT_SYMBOL(get_blackout_policy); |
| |
| u32 get_vdx_blackout_policy(u8 layer_id) |
| { |
| if (layer_id >= MAX_VD_LAYER) |
| return 1; |
| else |
| return blackout[layer_id] | force_blackout; |
| } |
| EXPORT_SYMBOL(get_vdx_blackout_policy); |
| |
| u32 set_vdx_blackout_policy(u8 layer_id, int policy) |
| { |
| if (layer_id >= MAX_VD_LAYER) |
| return 1; |
| blackout[layer_id] = policy; |
| return 0; |
| } |
| EXPORT_SYMBOL(set_vdx_blackout_policy); |
| |
| void pause_video(unsigned char pause_flag) |
| { |
| atomic_set(&video_pause_flag, pause_flag ? 1 : 0); |
| } |
| EXPORT_SYMBOL(pause_video); |
| |
| void di_unreg_notify(void) |
| { |
| u32 sleep_time = 40; |
| |
| while (atomic_read(&video_inirq_flag) > 0) |
| schedule(); |
| if (cur_dev->pre_vsync_enable) |
| while (atomic_read(&video_prevsync_inirq_flag) > 0) |
| schedule(); |
| |
| if (gvideo_recv[0] && gvideo_recv[0]->active) |
| switch_vf(gvideo_recv[0], true); |
| |
| vd_layer[0].need_switch_vf = true; |
| vd_layer[0].property_changed = true; |
| |
| if (vinfo) { |
| sleep_time = vinfo->sync_duration_den * 1000; |
| if (vinfo->sync_duration_num) { |
| sleep_time /= vinfo->sync_duration_num; |
| /* need two vsync */ |
| sleep_time = (sleep_time + 1) * 2; |
| } else { |
| sleep_time = 40; |
| } |
| } |
| msleep(sleep_time); |
| } |
| EXPORT_SYMBOL(di_unreg_notify); |
| |
| void di_disable_plink_notify(bool async) |
| { |
| u32 sleep_time = 20; |
| u32 vsync_time; |
| u32 sleep_cycle = 0; |
| u32 skip_cycle = 0; |
| |
| while (atomic_read(&video_inirq_flag) > 0) |
| schedule(); |
| if (cur_dev->pre_vsync_enable) |
| while (atomic_read(&video_prevsync_inirq_flag) > 0) |
| schedule(); |
| |
| vd_layer[0].need_disable_plink = true; |
| atomic_set(&vd_layer[0].disable_plink_done, 0); |
| vd_layer[0].property_changed = true; |
| |
| if (vinfo && !async) { |
| vsync_time = vinfo->sync_duration_den * 1000; |
| if (vinfo->sync_duration_num) { |
| vsync_time /= vinfo->sync_duration_num; |
| /* need two vsync */ |
| vsync_time = vsync_time + 1; |
| sleep_time = vsync_time >> 1; |
| } |
| while (vd_layer[0].need_disable_plink && |
| !atomic_read(&vd_layer[0].disable_plink_done) && |
| skip_cycle < 20) { |
| skip_cycle++; |
| usleep_range(sleep_time * 1000, (sleep_time + 1) * 1000); |
| } |
| /* need one more vsync for rdma config */ |
| usleep_range(vsync_time * 1000, (vsync_time + 1) * 1000); |
| sleep_cycle = 2; |
| } else { |
| sleep_cycle = 2; |
| usleep_range(sleep_time * 2 * 1000, (sleep_time + 1) * 2 * 1000); |
| } |
| if (debug_flag & DEBUG_FLAG_PLINK) |
| pr_info("%s: wait %dx(%d+%d) ms\n", __func__, sleep_time, sleep_cycle, skip_cycle); |
| } |
| EXPORT_SYMBOL(di_disable_plink_notify); |
| |
| void di_plink_state_changed_notify(void) |
| { |
| vd_layer[0].property_changed = true; |
| } |
| EXPORT_SYMBOL(di_plink_state_changed_notify); |
| |
| void di_plink_force_dmc_priority(bool urgent, bool wait, bool interlace) |
| { |
| #define DI_READ_DMC_AM1_CHAN_CTRL 0x0064 |
| #define DI_WRTIE_DMC_AM4_CHAN_CTRL 0x0070 |
| #define DI_RDARB_UGT_L1C1 0x205b |
| #define DI_WRARB_UGT_L1C1 0x205d |
| |
| bool valid = false; |
| |
| if (stop_force_dmc) |
| return; |
| |
| /* check priority adjustment function valid or not */ |
| if (!legacy_vpp) { |
| if (cur_dev->display_module == OLD_DISPLAY_MODULE || |
| video_is_meson_t5w_cpu() || video_is_meson_t5m_cpu()) |
| valid = true; |
| } |
| if (!legacy_vpp) { |
| u32 sleep_time = 40; |
| |
| if (!valid) |
| wait = false; |
| |
| while (atomic_read(&video_inirq_flag) > 0 && wait) |
| schedule(); |
| |
| if (vinfo && wait) { |
| sleep_time = vinfo->sync_duration_den * 1000; |
| if (vinfo->sync_duration_num) { |
| sleep_time /= vinfo->sync_duration_num; |
| /* need two vsync */ |
| sleep_time = (sleep_time + 1) * 2; |
| } else { |
| sleep_time = 40; |
| } |
| } |
| if (wait) |
| msleep(sleep_time); |
| else |
| sleep_time = 0; |
| |
| if (cur_dev->display_module == OLD_DISPLAY_MODULE || |
| video_is_meson_t5w_cpu()) { |
| WRITE_DMCREG |
| (DI_READ_DMC_AM1_CHAN_CTRL, |
| urgent ? 0xCFF403C4 : 0xCFF203C4); |
| if (!interlace) |
| WRITE_DMCREG |
| (DI_WRTIE_DMC_AM4_CHAN_CTRL, |
| urgent ? 0xCFF403C4 : 0xCFF203C4); |
| if (debug_flag & DEBUG_FLAG_PLINK) |
| pr_info("%s: port:0x%x 0x%x to 0x%x (%s) wait:%s time %dms\n", |
| __func__, |
| DI_READ_DMC_AM1_CHAN_CTRL, |
| DI_WRTIE_DMC_AM4_CHAN_CTRL, |
| urgent ? 0xCFF403C4 : 0xCFF203C4, |
| urgent ? "super urgent" : "not urgent", |
| wait ? "true" : "false", |
| sleep_time); |
| } |
| if (video_is_meson_t5m_cpu()) { |
| WRITE_VCBUS_REG |
| (DI_RDARB_UGT_L1C1, |
| urgent ? 0x3ffff : 0x15555); |
| WRITE_VCBUS_REG |
| (DI_WRARB_UGT_L1C1, |
| urgent ? 0xfff : 0x555); |
| if (debug_flag & DEBUG_FLAG_PLINK) |
| pr_info("%s: port:0x%x 0x%x to 0x%x 0x%x (%s) wait:%s time %dms\n", |
| __func__, |
| DI_RDARB_UGT_L1C1, |
| DI_WRARB_UGT_L1C1, |
| urgent ? 0x3ffff : 0x15555, |
| urgent ? 0xfff : 0x555, |
| urgent ? "super urgent" : "not urgent", |
| wait ? "true" : "false", |
| sleep_time); |
| } |
| } |
| } |
| EXPORT_SYMBOL(di_plink_force_dmc_priority); |
| |
| u32 get_playback_delay_duration(void) |
| { |
| u32 memc_delay = 0; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRC |
| memc_delay = frc_get_video_latency(); |
| #endif |
| return memc_delay; |
| } |
| EXPORT_SYMBOL(get_playback_delay_duration); |
| |
| u32 get_video_angle(void) |
| { |
| return glayer_info[0].angle; |
| } |
| EXPORT_SYMBOL(get_video_angle); |
| |
| void set_video_zorder(u32 zorder, u32 index) |
| { |
| if (index < 2) |
| glayer_info[index].zorder = zorder; |
| } |
| EXPORT_SYMBOL(set_video_zorder); |
| |
| int video_property_notify(int flag) |
| { |
| vd_layer[0].property_changed = flag ? true : false; |
| return 0; |
| } |
| EXPORT_SYMBOL(video_property_notify); |
| |
| void set_vsync_2to1_mode(u8 enable) |
| { |
| if (cur_dev->prevsync_support) |
| cur_dev->vsync_2to1_enable = enable; |
| } |
| EXPORT_SYMBOL(set_vsync_2to1_mode); |
| |
| void set_pre_vsync_mode(u8 enable) |
| { |
| if (cur_dev->prevsync_support) { |
| cur_dev->pre_vsync_enable = enable; |
| vd1_set_go_field(); |
| } |
| } |
| EXPORT_SYMBOL(set_pre_vsync_mode); |
| |
| /********************************************************* |
| * Utilities |
| *********************************************************/ |
| int _video_set_disable(u32 val) |
| { |
| struct video_layer_s *layer = &vd_layer[0]; |
| |
| if (val > VIDEO_DISABLE_FORNEXT) |
| return -EINVAL; |
| |
| layer->disable_video = val; |
| if (layer->disable_video == |
| VIDEO_DISABLE_FORNEXT && |
| layer->dispbuf && |
| !is_local_vf(layer->dispbuf)) |
| layer->disable_video = VIDEO_DISABLE_NONE; |
| |
| if (layer->disable_video != VIDEO_DISABLE_NONE) { |
| pr_info("VID: VD1 off\n"); |
| safe_switch_videolayer |
| (layer->layer_id, false, true); |
| |
| if (layer->disable_video == |
| VIDEO_DISABLE_FORNEXT && |
| layer->dispbuf && |
| !is_local_vf(layer->dispbuf)) |
| layer->property_changed = true; |
| /* FIXME */ |
| try_free_keep_vdx(layer->keep_frame_id, 0); |
| } else { |
| if (layer->dispbuf && |
| !is_local_vf(layer->dispbuf)) { |
| safe_switch_videolayer |
| (layer->layer_id, true, true); |
| pr_info("VID: VD1 on\n"); |
| layer->property_changed = true; |
| } |
| } |
| if (get_video_debug_flags() & DEBUG_FLAG_HDMI_DV_CRC) |
| dump_stack(); |
| |
| return 0; |
| } |
| |
| void video_set_global_output(u32 index, u32 val) |
| { |
| if (index == 0) { |
| if (val != 0) |
| vd_layer[0].global_output = 1; |
| else |
| vd_layer[0].global_output = 0; |
| } else if (index == 1) { |
| if (vd_layer[1].vpp_index == VPP0) { |
| if (val != 0) |
| vd_layer[1].global_output = 1; |
| else |
| vd_layer[1].global_output = 0; |
| } |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| else if (vd_layer_vpp[0].layer_id == index && |
| vd_layer_vpp[0].vpp_index == VPP1) { |
| if (val != 0) |
| vd_layer_vpp[0].global_output = 1; |
| else |
| vd_layer_vpp[0].global_output = 0; |
| } else if (vd_layer_vpp[1].layer_id == index && |
| vd_layer_vpp[1].vpp_index == VPP2) { |
| if (val != 0) |
| vd_layer_vpp[1].global_output = 1; |
| else |
| vd_layer_vpp[1].global_output = 0; |
| } |
| #endif |
| } else if (index == 2) { |
| if (vd_layer[2].vpp_index == VPP0) { |
| if (val != 0) |
| vd_layer[2].global_output = 1; |
| else |
| vd_layer[2].global_output = 0; |
| } |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| else if (vd_layer_vpp[0].layer_id == index && |
| vd_layer_vpp[0].vpp_index == VPP1) { |
| if (val != 0) |
| vd_layer_vpp[0].global_output = 1; |
| else |
| vd_layer_vpp[0].global_output = 0; |
| } else if (vd_layer_vpp[1].layer_id == index && |
| vd_layer_vpp[1].vpp_index == VPP2) { |
| if (val != 0) |
| vd_layer_vpp[1].global_output = 1; |
| else |
| vd_layer_vpp[1].global_output = 0; |
| } |
| #endif |
| } |
| pr_info("VID: VD%d set global output as %d\n", |
| index + 1, (val != 0) ? 1 : 0); |
| } |
| |
| struct video_layer_s *get_layer_by_layer_id(u8 layer_id) |
| { |
| struct video_layer_s *layer = NULL; |
| |
| if (layer_id == 0) { |
| layer = &vd_layer[0]; |
| } else if (layer_id == 1) { |
| if (vd_layer[layer_id].vpp_index == VPP0) |
| layer = &vd_layer[1]; |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| /* vpp1 case */ |
| else if (vd_layer_vpp[0].layer_id == layer_id && |
| vd_layer_vpp[0].vpp_index == VPP1) |
| layer = &vd_layer_vpp[0]; |
| /* vpp2 case */ |
| else if (vd_layer_vpp[1].layer_id == layer_id && |
| vd_layer_vpp[1].vpp_index == VPP2) |
| layer = &vd_layer_vpp[1]; |
| #endif |
| } else if (layer_id == 2) { |
| if (vd_layer[layer_id].vpp_index == VPP0) |
| layer = &vd_layer[2]; |
| #ifndef CONFIG_AMLOGIC_ZAPPER_CUT |
| /* vpp1 case */ |
| else if (vd_layer_vpp[0].layer_id == layer_id && |
| vd_layer_vpp[0].vpp_index == VPP1) |
| layer = &vd_layer_vpp[0]; |
| /* vpp2 case */ |
| else if (vd_layer_vpp[1].layer_id == layer_id && |
| vd_layer_vpp[1].vpp_index == VPP2) |
| layer = &vd_layer_vpp[1]; |
| #endif |
| } |
| return layer; |
| } |
| |
| int _videopip_set_disable(u32 index, u32 val) |
| { |
| struct video_layer_s *layer = NULL; |
| |
| if (val > VIDEO_DISABLE_FORNEXT) |
| return -EINVAL; |
| |
| layer = get_layer_by_layer_id(index); |
| |
| if (!layer) |
| return -EINVAL; |
| |
| layer->disable_video = val; |
| |
| if (layer->disable_video == |
| VIDEO_DISABLE_FORNEXT && |
| layer->dispbuf && |
| !is_local_vf(layer->dispbuf)) |
| layer->disable_video = VIDEO_DISABLE_NONE; |
| |
| if (layer->disable_video != VIDEO_DISABLE_NONE) { |
| pr_info("VID: VD%d off\n", index + 1); |
| safe_switch_videolayer |
| (layer->layer_id, false, true); |
| |
| if (layer->disable_video == |
| VIDEO_DISABLE_FORNEXT && |
| layer->dispbuf && |
| !is_local_vf(layer->dispbuf)) |
| layer->property_changed = true; |
| /* FIXME */ |
| try_free_keep_vdx(layer->keep_frame_id, 0); |
| } else { |
| if (layer->dispbuf && |
| !is_local_vf(layer->dispbuf)) { |
| safe_switch_videolayer |
| (layer->layer_id, true, true); |
| pr_info("VID: VD%d on\n", index + 1); |
| layer->property_changed = true; |
| } |
| } |
| return 0; |
| } |
| |
| s32 set_video_path_select(const char *recv_name, u8 layer_id) |
| { |
| u32 new_path_id; |
| struct disp_info_s *layer_info; |
| struct video_layer_s *layer; |
| |
| if (!recv_name || |
| layer_id >= MAX_VD_LAYERS) |
| return -1; |
| |
| layer_info = &glayer_info[layer_id]; |
| layer = get_layer_by_layer_id(layer_id); |
| new_path_id = layer_info->display_path_id; |
| if (!strcmp(recv_name, "default")) |
| new_path_id = VFM_PATH_DEF; |
| else if (!strcmp(recv_name, RECEIVER_NAME)) |
| new_path_id = VFM_PATH_AMVIDEO; |
| else if (!strcmp(recv_name, RECEIVERPIP_NAME)) |
| new_path_id = VFM_PATH_PIP; |
| else if (!strcmp(recv_name, RECEIVERPIP2_NAME)) |
| new_path_id = VFM_PATH_PIP2; |
| else if (!strcmp(recv_name, "video_render.0")) |
| new_path_id = VFM_PATH_VIDEO_RENDER0; |
| else if (!strcmp(recv_name, "video_render.1")) |
| new_path_id = VFM_PATH_VIDEO_RENDER1; |
| else if (!strcmp(recv_name, "video_render.2")) |
| new_path_id = VFM_PATH_VIDEO_RENDER2; |
| else if (!strcmp(recv_name, "video_render.5")) |
| new_path_id = VFM_PATH_VIDEO_RENDER5; |
| else if (!strcmp(recv_name, "video_render.6")) |
| new_path_id = VFM_PATH_VIDEO_RENDER6; |
| else if (!strcmp(recv_name, "auto")) |
| new_path_id = VFM_PATH_AUTO; |
| else if (!strcmp(recv_name, "invalid")) |
| new_path_id = VFM_PATH_INVALID; |
| if (layer_info->display_path_id != new_path_id && layer) { |
| pr_info("VID: store VD%d path_id changed %d->%d\n", |
| layer_id, layer_info->display_path_id, new_path_id); |
| layer_info->display_path_id = new_path_id; |
| layer->property_changed = true; |
| if (new_path_id == VFM_PATH_AUTO) |
| layer_info->sideband_type = -1; |
| } |
| return 0; |
| } |
| EXPORT_SYMBOL(set_video_path_select); |
| |
| s32 set_sideband_type(s32 type, u8 layer_id) |
| { |
| struct disp_info_s *layer_info; |
| |
| if (layer_id >= MAX_VD_LAYERS) |
| return -1; |
| |
| layer_info = &glayer_info[layer_id]; |
| pr_info("VID: sideband_type %d changed to %d\n", |
| layer_info->sideband_type, type); |
| layer_info->sideband_type = type; |
| |
| return 0; |
| } |
| EXPORT_SYMBOL(set_sideband_type); |
| |
| /* dummy_data is ycbcr */ |
| void set_post_blend_dummy_data(u32 vpp_index, |
| u32 dummy_data, u32 dummy_alpha) |
| { |
| if (vpp_index == 0) { |
| vd_layer[0].video_en_bg_color = dummy_data; |
| vd_layer[0].video_dis_bg_color = dummy_data; |
| vd_layer[0].dummy_alpha = dummy_alpha; |
| } |
| } |
| EXPORT_SYMBOL(set_post_blend_dummy_data); |
| |
| /*return index: 0 post vsync, 3 pre vsync*/ |
| u32 get_vpp_vsync_index(u32 layerid) |
| { |
| if (layerid < MAX_VD_LAYER) |
| return vd_layer[layerid].vpp_index; |
| |
| pr_info("error layerid %d\n", layerid); |
| return 0; |
| } |
| EXPORT_SYMBOL(get_vpp_vsync_index); |
| |
| struct video_module_debug_s debug_video_func[4] = { |
| {"dmc_adjust", &dmc_adjust, 1, 0}, |
| {"stop_update", &stop_update, 1, 0}, |
| {"pre_vsync_count", &pre_vsync_count, 1, 0}, |
| {"stop_force_dmc", &stop_force_dmc, 1, 0}, |
| }; |
| |