vpp: add interface to force non-afbc path [1/1]
authorBrian Zhu <brian.zhu@amlogic.com>
Mon, 15 Apr 2019 18:11:02 +0000 (02:11 +0800)
committerBrian Zhu <brian.zhu@amlogic.com>
Thu, 20 Jun 2019 06:25:35 +0000 (14:25 +0800)
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 <brian.zhu@amlogic.com>
drivers/amlogic/media/video_sink/video.c
drivers/amlogic/media/video_sink/vpp.c
include/linux/amlogic/media/vfm/vframe.h
include/linux/amlogic/media/video_sink/vpp.h

index ceed8ac..0d74cf2 100644 (file)
@@ -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 @@ SET_FILTER:
                                        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,
index f5c3f3d..6f7771d 100644 (file)
@@ -1501,7 +1501,8 @@ RESTART:
                !(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 @@ RESTART:
                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 @@ RESTART:
                !(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;
index 8214dcf..faf3d7a 100644 (file)
@@ -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
index 95088bb..f4b8eb6 100644 (file)
@@ -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 {