di: request afbc when vpp use [1/2]
authorYong Qin <yong.qin@amlogic.com>
Tue, 7 May 2019 01:58:49 +0000 (09:58 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Mon, 24 Jun 2019 02:59:10 +0000 (19:59 -0700)
PD#SWPL-6033

Problem:
afbc mode, when di bypass mode switch di path,
will cause flashing

Solution:
when mode change, request hw afbc from vpp, when idle
di use afbc, vpp need switch to none afbc mode, vf add
VIDTYPE_PRE_DI_AFBC flag for vpp use.

Verify:
tl1

Change-Id: I4aaf96044249d5b79bdc627018f0c0714c85f941
Signed-off-by: Yong Qin <yong.qin@amlogic.com>
drivers/amlogic/media/deinterlace/deinterlace.c
drivers/amlogic/media/deinterlace/deinterlace.h
drivers/amlogic/media/deinterlace/deinterlace_hw.c
drivers/amlogic/media/deinterlace/deinterlace_hw.h

index 4507828..268c0e8 100644 (file)
@@ -132,7 +132,7 @@ static di_dev_t *de_devp;
 static dev_t di_devno;
 static struct class *di_clsp;
 
-static const char version_s[] = "2019-0423a:src chg, post ready size is wrong";
+static const char version_s[] = "2019-06-20a: afbc switch from vpp";
 
 static int bypass_state = 1;
 static int bypass_all;
@@ -237,6 +237,7 @@ static int di_vscale_skip_count;
 static int di_vscale_skip_count_real;
 static int vpp_3d_mode;
 static bool det3d_en;
+
 #ifdef DET3D
 static unsigned int det3d_mode;
 static void set3d_view(enum tvin_trans_fmt trans_fmt, struct vframe_s *vf);
@@ -676,6 +677,14 @@ store_dbg(struct device *dev,
                        afbc_sw(false);
                afbc_disable_flag = val > 0 ? 0:1;
                pr_info("afbc_disable_flag:%d\n", afbc_disable_flag);
+       } else if (strncmp(buf, "reqafbc", 7) == 0) {
+               val = di_requeset_afbc(true);
+               di_pre_stru.wait_afbc = false;
+               pr_info("request_afbc(%d)\n", val);
+       } else if (strncmp(buf, "rlsafbc", 7) == 0) {
+               val = di_requeset_afbc(false);
+               di_pre_stru.wait_afbc = false;
+               pr_info("rlease_afbc(%d)\n", val);
        } else {
                pr_info("DI no support cmd %s\n", buf);
                pr_info("supported cmd list:\n");
@@ -695,7 +704,9 @@ store_dbg(struct device *dev,
                pr_info("\t recycle_buf\n");
                pr_info("\t recycle_post\n");
                pr_info("\t mem_map\n");
-               pr_info("\t afbc_on 0/1\n");
+               pr_info("\t reqafbc\n");
+               pr_info("\t rlsafbc\n");
+               pr_info("\n trigger val\n");
        }
 
        kfree(buf_orig);
@@ -3609,6 +3620,19 @@ module_param_named(pre_hsc_down_en, pre_hsc_down_en, bool, 0644);
 static int pre_hsc_down_width = 480;
 module_param_named(pre_hsc_down_width, pre_hsc_down_width, int, 0644);
 
+
+u32 di_requeset_afbc(u32 onoff)
+{
+       u32 afbc_busy;
+
+       if (onoff)
+               afbc_busy = di_request_afbc_hw(afbc_get_decnub(), true);
+       else
+               afbc_busy = di_request_afbc_hw(afbc_get_decnub(), false);
+
+       return afbc_busy;
+}
+
 static unsigned char pre_de_buf_config(void)
 {
        struct di_buf_s *di_buf = NULL;
@@ -3617,6 +3641,9 @@ static unsigned char pre_de_buf_config(void)
        unsigned char change_type = 0;
        bool bit10_pack_patch = false;
        unsigned int width_roundup = 2;
+       u32 rls_timeout;
+       u32 afbc_busy;
+       u32 is_afbc_mode;
 
        if (di_blocking || !atomic_read(&de_devp->mem_flag))
                return 0;
@@ -3651,6 +3678,7 @@ static unsigned char pre_de_buf_config(void)
                        return 0;
                }
        }
+
        if (di_pre_stru.di_inp_buf_next) {
                di_pre_stru.di_inp_buf = di_pre_stru.di_inp_buf_next;
                di_pre_stru.di_inp_buf_next = NULL;
@@ -3678,13 +3706,15 @@ static unsigned char pre_de_buf_config(void)
 #endif
                }
 
-               vframe = vf_get(VFM_NAME);
-
                if (vframe == NULL)
                        return 0;
 
+               vframe = vf_get(VFM_NAME);
+
                /*for support compress from dec*/
-               if (IS_COMP_MODE(vframe->type)) {
+               if (IS_COMP_MODE(vframe->type) &&
+                       !is_bypass(vframe)) {
+                       is_afbc_mode = true;
                        if (IS_VDIN_SRC(vframe->source_type)
                                && IS_I_SRC(vframe->type)) {
                                vframe->width = vframe->compWidth;
@@ -3705,11 +3735,38 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
                        if (vframe->width > 10000 || vframe->height > 10000)
                                di_pre_stru.bad_frame_throw_count = 10;
                        di_pre_stru.bad_frame_throw_count--;
+
                        vf_put(vframe, VFM_NAME);
                        vf_notify_provider(
                                VFM_NAME, VFRAME_EVENT_RECEIVER_PUT, NULL);
                        return 0;
                }
+
+
+               /*
+                * for afbc used by vpp and di, when di use it,
+                * vpp need release afbc, waitting vpp release
+                */
+               if (di_pre_stru.wait_afbc) {
+                       /*check time out and afbc release status*/
+                       rls_timeout =
+                               jiffies_to_msecs(jiffies_64 -
+                                       di_pre_stru.afbc_rls_time);
+                       afbc_busy = di_requeset_afbc(true);
+                       if (afbc_busy && (rls_timeout < 80)) {
+                               vf_put(vframe, VFM_NAME);
+                               vf_notify_provider(
+                               VFM_NAME, VFRAME_EVENT_RECEIVER_PUT, NULL);
+                               pr_info("di: drop vframe (%d) t:%d\n",
+                                       afbc_busy, rls_timeout);
+                               return 0;
+                       } else if (!afbc_busy) {
+                               /*afbc_busy = di_requeset_afbc(false);*/
+                               di_pre_stru.wait_afbc = 0;
+                               pr_info("di: afbc hw free\n");
+                       }
+               }
+
                bit10_pack_patch =  (is_meson_gxtvbb_cpu() ||
                                                        is_meson_gxl_cpu() ||
                                                        is_meson_gxm_cpu());
@@ -3781,6 +3838,9 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
                /* source change, when i mix p,force p as i*/
                if (change_type == 1 || (change_type == 2 &&
                                         di_pre_stru.cur_prog_flag == 1)) {
+
+                       di_pre_stru.field_count_for_cont = 0;
+
                        if (di_pre_stru.di_mem_buf_dup_p) {
                                /*avoid only 2 i field then p field*/
                                if (
@@ -3830,7 +3890,8 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
                                di_buf->vframe->height,
                                di_buf->vframe->source_type);
 
-                       if (IS_COMP_MODE(di_buf->vframe->type)) {
+                       if (IS_COMP_MODE(di_buf->vframe->type) &&
+                               !is_bypass(vframe)) {
                                if (IS_VDIN_SRC(di_buf->vframe->source_type) &&
                                        IS_I_SRC(di_buf->vframe->type)) {
                                        di_pre_stru.cur_width =
@@ -3881,7 +3942,30 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
                                mpeg2vdin_flag = 1;
                        }
 #endif
-                       di_pre_stru.field_count_for_cont = 0;
+
+                       /*
+                        * for afbc used by vpp and di, when di use it,
+                        * vpp need release afbc, waitting vpp release
+                        */
+                       if (is_meson_tl1_cpu() || is_meson_sm1_cpu()) {
+                               /*compress mode and format changed*/
+                               if (!is_bypass(di_buf->vframe) &&
+                                       di_pre_stru.source_change_flag &&
+                                       IS_COMP_MODE(di_pre_stru.cur_inp_type)
+                                       && !afbc_is_free()
+                                       && !di_pre_stru.wait_afbc) {
+                                       afbc_busy = di_requeset_afbc(true);
+                                       vf_put(vframe, VFM_NAME);
+                                       vf_notify_provider(VFM_NAME,
+                                       VFRAME_EVENT_RECEIVER_PUT, NULL);
+                                       recycle_vframe_type_pre(di_buf);
+                                       di_pre_stru.afbc_rls_time = jiffies_64;
+                                       di_pre_stru.wait_afbc = true;
+                                       pr_info("di req afbc:%d\n", afbc_busy);
+                                       return 0;
+                               }
+                       }
+                       /*di_pre_stru.field_count_for_cont = 0;*/
                } else if (di_pre_stru.cur_prog_flag == 0) {
                        /* check if top/bot interleaved */
                        if (change_type == 2)
@@ -4208,6 +4292,12 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
                if (bypass_state == 0)
                        di_buf->vframe->type |= VIDTYPE_PRE_INTERLACE;
        }
+
+       if (is_afbc_mode) {
+               di_buf->vframe->type |= VIDTYPE_PRE_DI_AFBC;
+               /*pr_info("vf type:0x%x\n", di_buf->vframe->type);*/
+       }
+
        if (is_bypass_post()) {
                if (bypass_post_state == 0)
                        di_pre_stru.source_change_flag = 1;
@@ -4236,6 +4326,7 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
                di_buf->post_proc_flag = 1;
                di_patch_post_update_mc_sw(DI_MC_SW_OTHER, mcpre_en);//en
        }
+
        if ((di_pre_stru.di_mem_buf_dup_p == di_pre_stru.di_wr_buf) ||
            (di_pre_stru.di_chan2_buf_dup_p == di_pre_stru.di_wr_buf)) {
                pr_dbg("+++++++++++++++++++++++\n");
@@ -5643,6 +5734,7 @@ static int process_post_vframe(void)
        int itmp;
        int ready_count = list_count(QUEUE_PRE_READY);
        bool check_drop = false;
+       u32 di_afbc = false;
 
        if (queue_empty(QUEUE_POST_FREE))
                return 0;
@@ -5662,6 +5754,11 @@ static int process_post_vframe(void)
                return 0;
        }
 
+       if (ready_di_buf->vframe->type & VIDTYPE_PRE_DI_AFBC) {
+               di_afbc = 1;
+               /*pr_info("di afbc mode 0x%x\n", ready_di_buf->vframe->type);*/
+       }
+
        if ((ready_di_buf->post_proc_flag) &&
            (ready_count >= buffer_keep_count)) {
                i = 0;
@@ -5738,6 +5835,9 @@ static int process_post_vframe(void)
                                        VIDTYPE_VIU_SINGLE_PLANE |
                                        VIDTYPE_VIU_FIELD |
                                        VIDTYPE_PRE_INTERLACE;
+                               if (di_afbc)
+                                       di_buf->vframe->type |=
+                                       VIDTYPE_PRE_DI_AFBC;
                                di_buf->vframe->width =
                                        di_buf->di_buf_dup_p[1]->width_bk;
                                if (
@@ -5764,6 +5864,10 @@ static int process_post_vframe(void)
                                                  VIDTYPE_VIU_SINGLE_PLANE |
                                                        VIDTYPE_VIU_FIELD |
                                                        VIDTYPE_PRE_INTERLACE;
+                                       if (di_afbc)
+                                               di_buf->vframe->type |=
+                                               VIDTYPE_PRE_DI_AFBC;
+
                                        di_buf->vframe->height >>= 1;
                                        di_buf->vframe->canvas0Addr =
                                                di_buf->di_buf_dup_p[0]
@@ -5911,6 +6015,10 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
                                                |= VIDTYPE_VIU_FIELD;
                                        di_buf->vframe->type
                                                &= ~(VIDTYPE_TYPEMASK);
+                                       if (di_afbc)
+                                               di_buf->vframe->type |=
+                                               VIDTYPE_PRE_DI_AFBC;
+
                                        di_buf->vframe->process_fun
 = (post_wr_en && post_wr_support)?NULL:de_post_process;
                                        di_buf->process_fun_index
@@ -6003,6 +6111,10 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
                                        VIDTYPE_VIU_SINGLE_PLANE |
                                        VIDTYPE_VIU_FIELD |
                                        VIDTYPE_PRE_INTERLACE;
+                               if (di_afbc)
+                                       di_buf->vframe->type |=
+                                       VIDTYPE_PRE_DI_AFBC;
+
                                if (
                                        di_buf->di_buf_dup_p[0]->
                                        new_format_flag)
@@ -6029,6 +6141,10 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
                                        VIDTYPE_PROGRESSIVE |
                                        VIDTYPE_VIU_422 |
                                        VIDTYPE_VIU_SINGLE_PLANE;
+                               if (di_afbc)
+                                       di_buf->vframe->type |=
+                                       VIDTYPE_PRE_DI_AFBC;
+
                                if (
                                        (di_buf->di_buf_dup_p[0]->
                                         new_format_flag) ||
@@ -6059,6 +6175,10 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
                                        VIDTYPE_VIU_SINGLE_PLANE |
                                        VIDTYPE_VIU_FIELD |
                                        VIDTYPE_PRE_INTERLACE;
+                               if (di_afbc)
+                                       di_buf->vframe->type |=
+                                       VIDTYPE_PRE_DI_AFBC;
+
                                di_buf->vframe->height >>= 1;
                                di_buf->vframe->width =
                                        di_buf->di_buf_dup_p[0]->width_bk;
@@ -6706,6 +6826,8 @@ static void di_pre_trigger_work(struct di_pre_stru_s *pre_stru_p)
                                        Rd(DI_INTR_CTRL),
                                        (unsigned int)(cur_to_msecs() -
                                        di_pre_stru.irq_time[1]));
+                               pr_info("AFBCD0_MISC_CTRL=0x%x\n",
+                                       RDMA_RD(VD1_AFBCD0_MISC_CTRL));
                        }
                }
        } else {
@@ -6882,6 +7004,8 @@ static int di_receiver_event_fun(int type, void *data, void *arg)
                ddbg_mod_save(eDI_DBG_MOD_UNREGB, 0, 0);
                di_pre_stru.unreg_req_flag = 1;
                di_pre_stru.vdin_source = false;
+               di_pre_stru.wait_afbc = false;
+               /*di_requeset_afbc(false);*/
                trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG);
                di_pre_stru.unreg_req_flag_cnt = 0;
                //wait 10ms:
@@ -7254,6 +7378,7 @@ static vframe_t *di_vf_peek(void *arg)
                        vframe_type_name[di_buf->type],
                        di_buf->index, vframe_ret);
 #endif
+
        return vframe_ret;
 }
 /*recycle the buffer for keeping buffer*/
@@ -7386,6 +7511,7 @@ get_vframe:
                        vframe_ret->early_process_fun(
                                vframe_ret->private_data, vframe_ret);
        }
+
        return vframe_ret;
 }
 
index 964e203..be3c524 100644 (file)
@@ -370,6 +370,8 @@ struct di_pre_stru_s {
        unsigned long irq_time[2];
        /* combing adaptive */
        struct combing_status_s *mtn_status;
+       u64 afbc_rls_time;
+       bool wait_afbc;
 };
 
 struct di_post_stru_s {
@@ -435,6 +437,8 @@ int get_di_video_peek_cnt(void);
 unsigned long get_di_reg_unreg_timeout_cnt(void);
 struct vframe_s **get_di_vframe_in(void);
 
+extern s32 di_request_afbc_hw(u8 id, bool on);
+u32 di_requeset_afbc(u32 onoff);
 
 /*---------------------*/
 
index 6cb592c..4bf3730 100644 (file)
@@ -870,7 +870,7 @@ const unsigned int reg_AFBC[AFBC_DEC_NUB][AFBC_REG_INDEX_NUB] = {
 
 };
 
-static enum eAFBC_DEC afbc_get_decnub(void)
+enum eAFBC_DEC afbc_get_decnub(void)
 {
        enum eAFBC_DEC sel_dec = eAFBC_DEC0;
        /* info from vlsi feijun
@@ -1069,6 +1069,8 @@ u32 enable_afbc_input(struct vframe_s *vf)
        }
        RDMA_WR(reg[eAFBC_ENABLE], r);
 
+       /*pr_info("AFBC_ENABLE:0x%x\n", RDMA_RD(reg[eAFBC_ENABLE]));*/
+
        r = 0x100;
        /* TL1 add bit[13:12]: fmt_mode; 0:yuv444; 1:yuv422; 2:yuv420
         * di does not support yuv444, so for fmt yuv444 di will bypass+
@@ -1183,8 +1185,11 @@ static void afbcx_sw(bool on)    /*g12a*/
 
        if (on) {
                tmp = tmp
+                       /*0:go_file 1:go_filed_pre*/
                        | (2<<20)
+                       /*0:afbc0 mif to axi 1:vd1 mif to axi*/
                        | (1<<12)
+                       /*0:afbc0 to vpp 1:afbc0 to di*/
                        | (1<<9);
                RDMA_WR(reg_ctrl, tmp);
                /*0:vd1 to di   1:vd2 to di */
@@ -1300,6 +1305,25 @@ void afbc_reg_sw(bool on)
                afbc_reg_unreg_flag = 0;
        }
 }
+
+bool afbc_is_free(void)
+{
+       bool sts = 0;
+       u32 afbc_num = afbc_get_decnub();
+
+       if (afbc_num == eAFBC_DEC0)
+               sts = RDMA_RD_BITS(VD1_AFBCD0_MISC_CTRL, 8, 2);
+       else
+               sts = RDMA_RD_BITS(VD2_AFBCD1_MISC_CTRL, 8, 2);
+
+       if (sts)
+               return true;
+       else
+               return false;
+
+       return sts;
+}
+
 #if 0
 void afbc_sw_trig(bool  on)
 {
index fde9d83..d69bb1e 100644 (file)
@@ -231,6 +231,8 @@ extern void di_patch_post_update_mc_sw(unsigned int cmd, bool on);
 extern void di_rst_protect(bool on);
 extern void di_pre_nr_wr_done_sel(bool on);
 extern void di_arb_sw(bool on);
+extern bool afbc_is_free(void);
+extern enum eAFBC_DEC afbc_get_decnub(void);
 
 /*also see: dbg_mode_name*/
 enum eDI_DBG_MOD {