From 7fa2db93fd52fc2b42562217e2d5121e0a2bfce2 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Tue, 7 May 2019 09:58:49 +0800 Subject: [PATCH] di: request afbc when vpp use [1/2] 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 --- .../amlogic/media/deinterlace/deinterlace.c | 140 +++++++++++++++++- .../amlogic/media/deinterlace/deinterlace.h | 4 + .../media/deinterlace/deinterlace_hw.c | 26 +++- .../media/deinterlace/deinterlace_hw.h | 2 + 4 files changed, 164 insertions(+), 8 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index dc8d63a0ad7b..c2be0d7e3825 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -131,7 +131,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; @@ -236,6 +236,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); @@ -637,6 +638,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"); @@ -656,7 +665,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); @@ -3811,6 +3822,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; @@ -3819,6 +3843,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; @@ -3853,6 +3880,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; @@ -3880,13 +3908,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; @@ -3907,11 +3937,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()); @@ -3983,6 +4040,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 ( @@ -4032,7 +4092,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 = @@ -4083,7 +4144,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) @@ -4410,6 +4494,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; @@ -4438,6 +4528,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"); @@ -5845,6 +5936,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; @@ -5864,6 +5956,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; @@ -5940,6 +6037,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 ( @@ -5966,6 +6066,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] @@ -6113,6 +6217,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 @@ -6205,6 +6313,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) @@ -6231,6 +6343,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) || @@ -6261,6 +6377,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; @@ -6910,6 +7030,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 { @@ -7081,6 +7203,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: @@ -7453,6 +7577,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*/ @@ -7585,6 +7710,7 @@ get_vframe: vframe_ret->early_process_fun( vframe_ret->private_data, vframe_ret); } + return vframe_ret; } diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index e0ca3acd91ac..be2b72fbd96c 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -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 { @@ -445,6 +447,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); /*---------------------*/ diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index eeeadef7c4c2..837d89e183c4 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -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) { diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index fde9d83ac394..d69bb1e16f93 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -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 {