From b8d9145a06a417ab0c639d9b1bdc065f25d31583 Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Tue, 16 Apr 2019 02:11:02 +0800 Subject: [PATCH] vpp: add interface to force non-afbc path [1/1] PD#SWPL-7035 Problem: When DI switched to use VD AFBC, need vpp force to non-afbc first. Otherwise, display willl flash. Solution: Provide new interface to request the vpp release afbc hardware first. Then return the current afbc status. Verify: verified on x301 Change-Id: Ibb2b897db7d2f2c40006433d63709988992c84f1 Signed-off-by: Brian Zhu --- drivers/amlogic/media/video_sink/video.c | 193 ++++++++++++++++--- drivers/amlogic/media/video_sink/vpp.c | 12 +- include/linux/amlogic/media/vfm/vframe.h | 1 + include/linux/amlogic/media/video_sink/vpp.h | 3 + 4 files changed, 182 insertions(+), 27 deletions(-) diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index ceed8ac00c428c..0d74cf2cb56393 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -467,6 +467,8 @@ static bool hist_test_flag; static unsigned long hist_buffer_addr; static u32 hist_print_count; +static atomic_t gAfbc_request = ATOMIC_INIT(0); + #define MAX_ZOOM_RATIO 300 #define VPP_PREBLEND_VD_V_END_LIMIT 2304 @@ -1177,6 +1179,65 @@ static int noneseamless_play_clone_rate = 5; #define CONFIG_AM_VOUT +static s32 is_afbc_for_vpp(u8 id) +{ + s32 ret = -1; + u32 val; + + if ((id >= MAX_VD_LAYERS) + || legacy_vpp) + return ret; + + if (id == 0) + val = READ_VCBUS_REG( + VD1_AFBCD0_MISC_CTRL); + else + val = READ_VCBUS_REG( + VD2_AFBCD1_MISC_CTRL); + + if ((val & (1 << 10)) && (val & (1 << 12)) + && !(val & (1 << 9))) + ret = 1; + else + ret = 0; + return ret; +} + +s32 di_request_afbc_hw(u8 id, bool on) +{ + u32 cur_afbc_request; + u32 next_request = 0; + s32 ret = -1; + + if (id >= MAX_VD_LAYERS) + return ret; + + if (!glayer_info[id].afbc_support || legacy_vpp) + return ret; + + next_request = 1 << id; + cur_afbc_request = atomic_read(&gAfbc_request); + if (on) { + if (cur_afbc_request & next_request) + return is_afbc_for_vpp(id); + + atomic_add(next_request, &gAfbc_request); + ret = 1; + } else { + if ((cur_afbc_request & next_request) == 0) + return is_afbc_for_vpp(id); + + atomic_sub(next_request, &gAfbc_request); + ret = 1; + } + if (id == 0) + video_property_changed = 1; + else + pip_property_changed = 1; + return ret; +} +EXPORT_SYMBOL(di_request_afbc_hw); + void safe_disble_videolayer(void) { #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER @@ -1977,7 +2038,8 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, } #endif -static void zoom_display_horz(struct vframe_s *vf, int hscale) +static void zoom_display_horz( + struct vframe_s *vf, int hscale, bool no_compress) { u32 ls = 0, le = 0, rs = 0, re = 0; #ifdef TV_REVERSE @@ -2017,7 +2079,8 @@ static void zoom_display_horz(struct vframe_s *vf, int hscale) (((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 + 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + if (!no_compress && + vf && (vf->type & VIDTYPE_COMPRESS)) { int l_aligned; int r_aligned; int h_skip = cur_frame_par->hscale_skip_count + 1; @@ -2197,7 +2260,8 @@ static void vd2_zoom_display_horz(struct vframe_s *vf, int hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); } -static void zoom_display_vert(struct vframe_s *vf) +static void zoom_display_vert( + struct vframe_s *vf, int vscale, bool no_compress) { u32 ls = 0, le = 0, rs = 0, re = 0; @@ -2300,12 +2364,13 @@ static void zoom_display_vert(struct vframe_s *vf) } } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + if (!no_compress && + vf && (vf->type & VIDTYPE_COMPRESS)) { int t_aligned; int b_aligned; int ori_t_aligned; int ori_b_aligned; - int v_skip = cur_frame_par->vscale_skip_count + 1; + int v_skip = vscale + 1; int c_skip = 2; /* After TL1, afbc supports 420/422/444*/ @@ -2605,7 +2670,7 @@ static void vsync_video_pattern(void) } #endif -static inline void vd1_path_select(bool afbc) +static inline void vd1_path_select(bool afbc, bool di_afbc) { u32 misc_off = cur_dev->vpp_off; @@ -2619,13 +2684,13 @@ static inline void vd1_path_select(bool afbc) /* vd1 -> dolby -> vpp top */ (0 << 14) | /* axi sel: vd1 mif or afbc */ - ((afbc ? 1 : 0) << 12) | + (((afbc || di_afbc) ? 1 : 0) << 12) | /* data sel: vd1 & afbc0 (not osd4) */ (0 << 11) | /* data sel: afbc0 or vd1 */ ((afbc ? 1 : 0) << 10) | /* afbc0 to vd1 (not di) */ - (0 << 9) | + ((di_afbc ? 1 : 0) << 9) | /* vd1 mif to vpp (not di) */ (0 << 8) | /* afbc0 gclk ctrl */ @@ -2669,7 +2734,7 @@ static inline void vd1_path_select(bool afbc) } } -static inline void vd2_path_select(bool afbc) +static inline void vd2_path_select(bool afbc, bool di_afbc) { u32 misc_off = cur_dev->vpp_off; @@ -2683,13 +2748,13 @@ static inline void vd2_path_select(bool afbc) /* TODO: vd2 -> dolby -> vpp top ?? */ (0 << 14) | /* axi sel: vd2 mif */ - ((afbc ? 1 : 0) << 12) | + (((afbc || di_afbc) ? 1 : 0) << 12) | /* data sel: vd2 & afbc1 (not osd4) */ (0 << 11) | /* data sel: afbc1 */ ((afbc ? 1 : 0) << 10) | /* afbc1 to vd2 (not di) */ - (0 << 9) | + ((di_afbc ? 1 : 0) << 9) | /* vd2 mif to vpp (not di) */ (0 << 8) | /* afbc1 gclk ctrl */ @@ -3268,6 +3333,7 @@ static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) u32 u, v; u32 type, bit_mode = 0; u8 burst_len = 1; + u32 canvas_w; if (!vf || !frame_par) { pr_err("pip_set_dcu vf is NULL\n"); @@ -3394,12 +3460,25 @@ static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VD2_AFBCDEC_IQUANT_ENABLE, 0); } - vd2_path_select(true); + vd2_path_select(true, false); VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, 0); return; } + /* vd mif burst len is 2 as default */ + burst_len = 2; + if (vf->canvas0Addr != (u32)-1) + canvas_w = canvas_get_width( + vf->canvas0Addr & 0xff); + else + canvas_w = vf->canvas0_config[0].width; + + if (canvas_w % 32) + burst_len = 0; + else if (canvas_w % 64) + burst_len = 1; + if ((vf->bitdepth & BITDEPTH_Y10) && (!frame_par->nocomp)) { if (vf->type & VIDTYPE_VIU_444) { @@ -3413,11 +3492,14 @@ static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { bit_mode = 0; } - vd2_path_select(false); + vd2_path_select(false, false); if (!legacy_vpp) { VSYNC_WR_MPEG_REG_BITS( G12_VD2_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); + VSYNC_WR_MPEG_REG_BITS( + G12_VD2_IF0_GEN_REG3, + (burst_len & 0x3), 1, 2); } else { VSYNC_WR_MPEG_REG_BITS( VD2_IF0_GEN_REG3 + cur_dev->viu_off, @@ -3678,6 +3760,13 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) frame_count++; toggle_count++; + if (vf && !(vf->type & VIDTYPE_COMPRESS) + && glayer_info[0].need_no_compress) { + atomic_sub(1, &gAfbc_request); + glayer_info[0].need_no_compress = false; + force_toggle = true; + } + if (vf->type & VIDTYPE_MVC) is_mvc = true; @@ -3877,7 +3966,7 @@ static void vsync_toggle_frame(struct vframe_s *vf, int line) /* switch buffer */ post_canvas = vf->canvas0Addr; - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && + if (!glayer_info[0].need_no_compress && (vf->type & VIDTYPE_COMPRESS)) { VSYNC_WR_MPEG_REG(AFBC_HEAD_BADDR, vf->compHeadAddr>>4); VSYNC_WR_MPEG_REG(AFBC_BODY_BADDR, vf->compBodyAddr>>4); @@ -4360,15 +4449,30 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) AFBCDEC_IQUANT_ENABLE, 0); } - vd1_path_select(true); + vd1_path_select(true, false); VSYNC_WR_MPEG_REG( VD1_IF0_GEN_REG + cur_dev->viu_off, 0); return; } else { + u32 canvas_w; + + /* vd mif burst len is 2 as default */ + burst_len = 2; + if (vf->canvas0Addr != (u32)-1) + canvas_w = canvas_get_width( + vf->canvas0Addr & 0xff); + else + canvas_w = vf->canvas0_config[0].width; + + if (canvas_w % 32) + burst_len = 0; + else if (canvas_w % 64) + burst_len = 1; + if ((vf->bitdepth & BITDEPTH_Y10) && - (!frame_par->nocomp)) { + (!frame_par->nocomp)) { if (vf->type & VIDTYPE_VIU_444) { bit_mode = 2; } else { @@ -4384,10 +4488,17 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VSYNC_WR_MPEG_REG_BITS( G12_VD1_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); - if (is_mvc) + VSYNC_WR_MPEG_REG_BITS( + G12_VD1_IF0_GEN_REG3, + (burst_len & 0x3), 1, 2); + if (is_mvc) { VSYNC_WR_MPEG_REG_BITS( G12_VD2_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); + VSYNC_WR_MPEG_REG_BITS( + G12_VD2_IF0_GEN_REG3, + (burst_len & 0x3), 1, 2); + } } else { VSYNC_WR_MPEG_REG_BITS( VD1_IF0_GEN_REG3 + @@ -4409,8 +4520,14 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) DI_POST_WR_REG_BITS(DI_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); #endif - vd1_path_select(false); - VSYNC_WR_MPEG_REG(AFBC_ENABLE, 0); + if (glayer_info[0].need_no_compress + || (vf->type & VIDTYPE_PRE_DI_AFBC)) { + vd1_path_select(false, true); + } else { + vd1_path_select(false, false); + VSYNC_WR_MPEG_REG( + AFBC_ENABLE, 0); + } } } @@ -4904,13 +5021,28 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VD2_AFBCDEC_IQUANT_ENABLE, 0); } - vd2_path_select(true); + vd2_path_select(true, false); VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, 0); return; } else { + u32 canvas_w; + + /* vd mif burst len is 2 as default */ + burst_len = 2; + if (vf->canvas0Addr != (u32)-1) + canvas_w = canvas_get_width( + vf->canvas0Addr & 0xff); + else + canvas_w = vf->canvas0_config[0].width; + + if (canvas_w % 32) + burst_len = 0; + else if (canvas_w % 64) + burst_len = 1; + if ((vf->bitdepth & BITDEPTH_Y10) && - (!frame_par->nocomp)) { + (!frame_par->nocomp)) { if (vf->type & VIDTYPE_VIU_444) { bit_mode = 2; } else { @@ -4922,11 +5054,14 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { bit_mode = 0; } - vd2_path_select(false); + vd2_path_select(false, false); if (!legacy_vpp) { VSYNC_WR_MPEG_REG_BITS( G12_VD2_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); + VSYNC_WR_MPEG_REG_BITS( + G12_VD2_IF0_GEN_REG3, + (burst_len & 0x3), 1, 2); } else { VSYNC_WR_MPEG_REG_BITS( VD2_IF0_GEN_REG3 + cur_dev->viu_off, @@ -6405,6 +6540,12 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) static struct vframe_s *pause_vf; int force_flush = 0; static u32 interrupt_count; + u32 next_afbc_request = atomic_read(&gAfbc_request); + + glayer_info[0].need_no_compress = + (next_afbc_request & 1) ? true : false; + glayer_info[1].need_no_compress = + (next_afbc_request & 2) ? true : false; if (debug_flag & DEBUG_FLAG_VSYNC_DONONE) return IRQ_HANDLED; @@ -7583,11 +7724,14 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) cur_frame_par->VPP_hd_start_lines_; zoom_end_x_lines = cur_frame_par->VPP_hd_end_lines_; zoom_display_horz(cur_dispbuf, - cur_frame_par->hscale_skip_count); + cur_frame_par->hscale_skip_count, + cur_frame_par->nocomp); zoom_start_y_lines = zoom_start_y; zoom_end_y_lines = zoom_end_y; - zoom_display_vert(cur_dispbuf); + zoom_display_vert(cur_dispbuf, + cur_frame_par->vscale_skip_count, + cur_frame_par->nocomp); if (is_dolby_vision_enable() && cur_dispbuf2) { zoom2_start_x_lines = ori2_start_x_lines; zoom2_end_x_lines = ori2_end_x_lines; @@ -8754,6 +8898,7 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) /*alternative mode,passing two buffer in one frame */ if (platform_type == 1) { if ((process_3d_type & MODE_3D_FA) && + cur_dispbuf && !cur_dispbuf->trans_fmt) vf_notify_receiver_by_name("deinterlace", VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE, diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index f5c3f3d2881060..6f7771d3fd308f 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -1501,7 +1501,8 @@ static int vpp_set_filters_internal( !(vf->type & VIDTYPE_NO_DW) && (vf->canvas0Addr != 0) && (!next_frame_par->nocomp)) { - if ((next_frame_par->vscale_skip_count > 1) + if ((vpp_flags & VPP_FLAG_FORCE_NO_COMPRESS) + || (next_frame_par->vscale_skip_count > 1) || !input->afbc_support || force_no_compress) no_compress = true; @@ -1523,7 +1524,8 @@ static int vpp_set_filters_internal( h_in = height_in = vf->height; next_frame_par->hscale_skip_count = 0; next_frame_par->vscale_skip_count = 0; - crop_ratio = vf->compWidth / vf->width; + if (vf->width && vf->compWidth) + crop_ratio = vf->compWidth / vf->width; goto RESTART_ALL; } @@ -2996,7 +2998,8 @@ static int vpp_set_filters_no_scaler_internal( !(vf->type & VIDTYPE_NO_DW) && (vf->canvas0Addr != 0) && (!next_frame_par->nocomp)) { - if ((next_frame_par->vscale_skip_count > 1) + if ((vpp_flags & VPP_FLAG_FORCE_NO_COMPRESS) + || (next_frame_par->vscale_skip_count > 1) || !input->afbc_support || force_no_compress) no_compress = true; @@ -3227,6 +3230,9 @@ int vpp_set_filters( if (op_flag & 1) vpp_flags |= VPP_FLAG_MORE_LOG; + if (local_input.need_no_compress) + vpp_flags |= VPP_FLAG_FORCE_NO_COMPRESS; + next_frame_par->VPP_post_blend_vd_v_end_ = vinfo->field_height - 1; next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; next_frame_par->VPP_post_blend_h_size_ = vinfo->width; diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 8214dcff58243c..faf3d7a6e6307b 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -49,6 +49,7 @@ #define VIDTYPE_COMB_MODE 0x2000000 #define VIDTYPE_NO_DW 0x4000000 #define VIDTYPE_SUPPORT_COMPRESS 0x8000000 +#define VIDTYPE_PRE_DI_AFBC 0x10000000 #define DISP_RATIO_FORCECONFIG 0x80000000 #define DISP_RATIO_FORCE_NORMALWIDE 0x40000000 diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index 95088bb83be707..f4b8eb65201e06 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -35,6 +35,7 @@ extern bool super_scaler; #define VPP_FLAG_PORTRAIT_MODE 0x00040000 #define VPP_FLAG_VSCALE_DISABLE 0x00080000 #define VPP_FLAG_MORE_LOG 0x00100000 +#define VPP_FLAG_FORCE_NO_COMPRESS 0x00200000 #define IDX_H (2 << 8) #define IDX_V_Y (1 << 13) @@ -194,6 +195,8 @@ struct disp_info_s { bool afbc_support; bool pps_support; + + bool need_no_compress; }; enum select_scaler_path_e {