| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * drivers/amlogic/media/di_multi/di_pre.c |
| * |
| * Copyright (C) 2017 Amlogic, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/err.h> |
| #include <linux/seq_file.h> |
| |
| #include <linux/amlogic/media/vfm/vframe.h> |
| #include "deinterlace.h" |
| #include "deinterlace_dbg.h" |
| |
| #include "di_data_l.h" |
| #include "di_data.h" |
| #include "di_dbg.h" |
| #include "di_vframe.h" |
| #include "di_que.h" |
| #include "di_task.h" |
| |
| #include "di_prc.h" |
| #include "di_pre.h" |
| |
| #include "nr_downscale.h" |
| #include "register.h" |
| |
| /**************************************** |
| * 1. copy curr to last |
| * 2. set curr |
| ****************************************/ |
| void pre_vinfo_set(unsigned int ch, |
| struct vframe_s *ori_vframe) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| struct di_vinfo_s *vc = &pre->vinf_curr; |
| struct di_vinfo_s *vl = &pre->vinf_lst; |
| |
| memcpy(vl, vc, sizeof(struct di_vinfo_s)); |
| |
| vc->ch = ch; |
| vc->vtype = ori_vframe->type; |
| vc->src_type = ori_vframe->source_type; |
| vc->trans_fmt = ori_vframe->trans_fmt; |
| |
| if (COM_ME(ori_vframe->type, VIDTYPE_COMPRESS)) { |
| vc->h = ori_vframe->compWidth; |
| vc->v = ori_vframe->compHeight; |
| } else { |
| vc->h = ori_vframe->width; |
| vc->v = ori_vframe->height; |
| } |
| } |
| |
| /**************************************** |
| * compare current vframe info with last |
| * return |
| * 0. no change |
| * 1. video format channge |
| * 2. scan mode channge? |
| ****************************************/ |
| unsigned int is_vinfo_change(unsigned int ch) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| struct di_vinfo_s *vc = &pre->vinf_curr; |
| struct di_vinfo_s *vl = &pre->vinf_lst; |
| struct di_pre_stru_s *ppre = get_pre_stru(ch); |
| unsigned int ret = 0; |
| |
| if (vc->src_type != vl->src_type || |
| !COM_M(DI_VFM_T_MASK_CHANGE, vc->vtype, vl->vtype) || |
| vc->v != vl->v || |
| vc->h != vl->h || |
| vc->trans_fmt != vl->trans_fmt) { |
| /* video format changed */ |
| ret = 1; |
| } else if (!COM_M(VIDTYPE_VIU_FIELD, vc->vtype, vl->vtype)) |
| /* just scan mode changed */ |
| ret = 2; |
| |
| if (ret) { |
| dim_print("%s:ch[%d]:%dth scchg2:0x%x/%d/%d/%d>0x%x/%d/%d/%d\n", |
| __func__, |
| ch, |
| /*jiffies_to_msecs(jiffies_64),*/ |
| ppre->in_seq, |
| vl->vtype, |
| vl->h, |
| vl->v, |
| vl->src_type, |
| vc->vtype, |
| vc->h, |
| vc->v, |
| vc->src_type); |
| } |
| |
| return ret; |
| } |
| |
| bool dim_bypass_detect(unsigned int ch, struct vframe_s *vfm) |
| { |
| bool ret = false; |
| |
| if (!vfm) |
| return ret; |
| pre_vinfo_set(ch, vfm); |
| if (is_vinfo_change(ch)) { |
| if (!is_bypass2(vfm, ch)) { |
| set_bypass2_complete(ch, false); |
| PR_INF("%s:\n", __func__); |
| /*task_send_ready();*/ |
| task_send_cmd(LCMD1(ECMD_CHG, ch)); |
| ret = true; |
| } |
| } |
| return ret; |
| } |
| |
| unsigned int di_get_other_ch(unsigned int curr) |
| { |
| return curr ? 0 : 1; |
| } |
| |
| bool is_bypass_i_p(void) |
| { |
| bool ret = false; |
| struct di_hpre_s *pre = get_hw_pre(); |
| struct di_vinfo_s *vc = &pre->vinf_curr; |
| #ifdef MARK_HIS |
| struct di_vinfo_s *vl = &pre->vinf_lst; |
| |
| if (vl->ch != vc->ch && |
| VFMT_IS_I(vl->vtype) && |
| VFMT_IS_P(vc->vtype)) { |
| ret = true; |
| } |
| #else |
| unsigned int ch_c, ch_l; |
| |
| struct di_pre_stru_s *ppre_c, *ppre_l; |
| |
| if (!get_reg_flag(0) || |
| !get_reg_flag(1)) |
| return ret; |
| |
| ch_c = vc->ch; |
| ch_l = (ch_c ? 0 : 1); |
| ppre_c = get_pre_stru(ch_c); |
| ppre_l = get_pre_stru(ch_l); |
| if (VFMT_IS_I(ppre_l->cur_inp_type) && |
| VFMT_IS_P(ppre_c->cur_inp_type)) { |
| ret = true; |
| dim_print("ch[%d]:bypass p\n", ch_c); |
| } |
| #endif |
| |
| return ret; |
| } |
| |
| void dpre_clear(void) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| memset(pre, 0, sizeof(struct di_hpre_s)); |
| } |
| |
| void dpre_init(void) |
| {/*reg:*/ |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| pre->pre_st = EDI_PRE_ST4_IDLE; |
| //bset(&pre->self_trig_mask, 2);// |
| |
| /*timer out*/ |
| di_tout_int(&pre->tout, 40); /*ms*/ |
| } |
| |
| void pw_use_hw_pre(enum EDI_SUB_ID channel, bool on) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| pre->hw_flg_busy_pre = on; |
| if (on) |
| pre->curr_ch = channel; |
| } |
| |
| enum EDI_SUB_ID pw_ch_next_count(enum EDI_SUB_ID channel) |
| { |
| int i; |
| unsigned int lch, nch; |
| |
| nch = channel; |
| for (i = 0; i < DI_CHANNEL_NUB; i++) { |
| lch = channel + i + 1; |
| if (lch >= DI_CHANNEL_NUB) |
| lch -= DI_CHANNEL_NUB; |
| #ifdef MARK_HIS |
| if (pbm->sub_act_flg[lch]) { |
| nch = lch; |
| break; |
| } |
| #else |
| if (get_reg_flag(lch) && |
| !get_flag_trig_unreg(lch) && |
| !is_bypss2_complete(lch)) { |
| nch = lch; |
| break; |
| } |
| #endif |
| } |
| return nch; |
| } |
| |
| /****************************************/ |
| static bool pw_try_sw_ch_next_pre(enum EDI_SUB_ID channel) |
| { |
| bool ret = false; |
| struct di_hpre_s *pre = get_hw_pre(); |
| enum EDI_SUB_ID lst_ch, nch; |
| |
| lst_ch = channel; |
| |
| nch = pw_ch_next_count(lst_ch); |
| if (!get_reg_flag(nch) || |
| get_flag_trig_unreg(nch) || |
| is_bypss2_complete(nch)) |
| return false; |
| |
| pre->curr_ch = nch; |
| pre->hw_flg_busy_pre = true; |
| ret = true; |
| |
| /*dim_print("%s:%d->%d:%d\n", __func__, lst_ch, nch, ret);*/ |
| return ret; |
| } |
| |
| /*****************************/ |
| /* debug */ |
| /*****************************/ |
| |
| unsigned int di_dbg_pre_cnt; |
| |
| void dbg_cnt_begin(void) |
| { |
| di_dbg_pre_cnt = 0x10; |
| } |
| |
| void dbg_cnt_print(void) |
| { |
| if (di_dbg_pre_cnt < 0xf) |
| return; |
| |
| if (di_dbg_pre_cnt > 0x10) { |
| di_dbg_pre_cnt++; |
| pr_info("di:[%d]\n", di_dbg_pre_cnt); |
| } |
| |
| if (di_dbg_pre_cnt > 0x15) |
| di_dbg_pre_cnt = 0; |
| } |
| |
| /*****************************/ |
| /* STEP */ |
| /*****************************/ |
| void dpre_recyc(unsigned int ch) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| pre->check_recycle_buf_cnt = 0; |
| while (dim_check_recycle_buf(ch) & 1) { |
| if (pre->check_recycle_buf_cnt++ > MAX_IN_BUF_NUM) { |
| di_pr_info("%s: dim_check_recycle_buf time out!!\n", |
| __func__); |
| break; |
| } |
| } |
| } |
| |
| void dpre_vdoing(unsigned int ch) |
| { |
| struct di_post_stru_s *ppost = get_post_stru(ch); |
| |
| ppost->di_post_process_cnt = 0; |
| while (dim_process_post_vframe(ch)) { |
| if (ppost->di_post_process_cnt++ > |
| MAX_POST_BUF_NUM) { |
| di_pr_info("%s: dim_process_post_vframe time out!!\n", |
| __func__); |
| break; |
| } |
| } |
| } |
| |
| bool dpre_can_exit(unsigned int ch) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| bool ret = false; |
| |
| if (ch != pre->curr_ch) { |
| ret = true; |
| } else { |
| if (pre->pre_st <= EDI_PRE_ST4_IDLE) |
| ret = true; |
| } |
| pr_info("%s:ch[%d]:curr[%d]:stat[%s] ret[%d]\n", |
| __func__, |
| ch, pre->curr_ch, |
| dpre_state4_name_get(pre->pre_st), |
| ret); |
| return ret; |
| } |
| |
| void dpre_dbg_f_trig(unsigned int cmd) |
| { |
| struct di_task *tsk = get_task(); |
| |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| if (down_interruptible(&tsk->sem)) { |
| PR_ERR("%s:can't get sem\n", __func__); |
| return; |
| } |
| |
| /*set on/off and trig*/ |
| if (cmd & 0x10) { |
| pre->dbg_f_en = 1; |
| pre->dbg_f_cnt = cmd & 0xf; |
| pre->dbg_f_lstate = pre->pre_st; |
| } else { |
| pre->dbg_f_en = 0; |
| } |
| |
| up(&tsk->sem); |
| } |
| |
| void dpre_process(void) |
| { |
| bool reflesh; |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| if (pre->dbg_f_en) { |
| if (pre->dbg_f_cnt) { |
| dpre_process_step4(); |
| pre->dbg_f_cnt--; |
| } |
| if (pre->dbg_f_lstate != pre->pre_st) { |
| pr_info("ch[%d]:state:%s->%s\n", |
| pre->curr_ch, |
| dpre_state4_name_get(pre->dbg_f_lstate), |
| dpre_state4_name_get(pre->pre_st)); |
| |
| pre->dbg_f_lstate = pre->pre_st; |
| } |
| return; |
| } |
| |
| reflesh = true; |
| |
| while (reflesh) { |
| reflesh = dpre_process_step4(); |
| #ifdef MARK_HIS /*debug only*/ |
| dbg_tsk("ch[%d]:st[%s]r[%d]\n", pre->curr_ch, |
| dpre_state4_name_get(pre->pre_st), reflesh); |
| #endif |
| } |
| } |
| |
| enum EDI_PRE_MT { |
| EDI_PRE_MT_CHECK = K_DO_TABLE_ID_START, |
| EDI_PRE_MT_SET, |
| EDI_PRE_MT_WAIT_INT, |
| EDI_PRE_MT_TIME_OUT, |
| }; |
| |
| /*use do_table:*/ |
| unsigned int dpre_mtotal_check(void *data) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| unsigned int ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);//K_DO_R_NOT_FINISH; |
| unsigned int cfg_val; |
| |
| dbg_src_change_simple(pre->curr_ch);/*dbg only*/ |
| #ifdef MARK_HIS |
| if (pre_run_flag == DI_RUN_FLAG_RUN || |
| pre_run_flag == DI_RUN_FLAG_STEP) { |
| if (pre_run_flag == DI_RUN_FLAG_STEP) |
| pre_run_flag = DI_RUN_FLAG_STEP_DONE; |
| dim_print("%s:\n", __func__); |
| if (dim_pre_de_buf_config(pre->curr_ch)) |
| ret = K_DO_R_FINISH; |
| else |
| ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); |
| |
| dim_dbg_pre_cnt(pre->curr_ch, "x"); |
| } |
| #else |
| cfg_val = dim_pre_de_buf_config(pre->curr_ch); |
| if (!cfg_val) {/*ok*/ |
| ret = K_DO_R_FINISH; |
| } else { |
| dbg_dt("cfg fail:%d\n", cfg_val); |
| ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); |
| } |
| |
| #endif |
| return ret; |
| } |
| |
| unsigned int dpre_mtotal_set(void *data) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| //ary 2020-12-09 ulong flags = 0; |
| |
| /*dim_print("%s:\n", __func__);*/ |
| //trace_printk("%s\n", __func__); |
| //ary 2020-12-09 spin_lock_irqsave(&plist_lock, flags); |
| dim_pre_de_process(pre->curr_ch); |
| //ary 2020-12-09 spin_unlock_irqrestore(&plist_lock, flags); |
| /*begin to count timer*/ |
| di_tout_contr(EDI_TOUT_CONTR_EN, &pre->tout); |
| |
| return K_DO_R_FINISH; |
| } |
| |
| enum EDI_WAIT_INT { |
| EDI_WAIT_INT_NEED_WAIT, |
| EDI_WAIT_INT_HAVE_INT, |
| EDI_WAIT_INT_TIME_OUT, |
| }; |
| |
| /* |
| *return: enum EDI_WAIT_INT |
| * |
| */ |
| enum EDI_WAIT_INT di_pre_wait_int(void *data) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| //tmp ulong flags = 0; |
| struct di_pre_stru_s *ppre; |
| |
| enum EDI_WAIT_INT ret = EDI_WAIT_INT_NEED_WAIT; |
| |
| if (pre->flg_int_done) { |
| /*have INT done flg*/ |
| /*DI_INTR_CTRL[bit 0], NRWR_done, set by |
| * hardware when NRWR is done,clear by write 1 |
| * by code;[bit 1] |
| * MTNWR_done, set by hardware when MTNWR |
| * is done, clear by write 1 by code;these two |
| * bits have nothing to do with |
| * DI_INTR_CTRL[16](NRW irq mask, 0 to enable |
| * irq) and DI_INTR_CTRL[17] |
| * (MTN irq mask, 0 to enable irq).two |
| * interrupts are raised if both |
| * DI_INTR_CTRL[16] and DI_INTR_CTRL[17] are 0 |
| */ |
| |
| /*di_pre_wait_irq_set(false);*/ |
| /*finish to count timer*/ |
| di_tout_contr(EDI_TOUT_CONTR_FINISH, &pre->tout); |
| //tmp spin_lock_irqsave(&plist_lock, flags); |
| |
| dim_pre_de_done_buf_config(pre->curr_ch, false); |
| |
| pre->flg_int_done = 0; |
| |
| dpre_recyc(pre->curr_ch); |
| dpre_vdoing(pre->curr_ch); |
| |
| //tmp spin_unlock_irqrestore(&plist_lock, flags); |
| |
| ppre = get_pre_stru(pre->curr_ch); |
| |
| |
| ret = EDI_WAIT_INT_HAVE_INT; |
| |
| } else { |
| /*check if timeout:*/ |
| if (di_tout_contr(EDI_TOUT_CONTR_CHECK, &pre->tout)) { |
| /*di_pre_wait_irq_set(false);*/ |
| if (!atomic_dec_and_test(&get_hw_pre()->flg_wait_int)) { |
| PR_WARN("%s:ch[%d]timeout\n", __func__, |
| pre->curr_ch); |
| di_tout_contr(EDI_TOUT_CONTR_EN, &pre->tout); |
| } else { |
| /*return K_DO_R_FINISH;*/ |
| ret = EDI_WAIT_INT_TIME_OUT; |
| } |
| } |
| } |
| /*debug:*/ |
| if (dbg_first_cnt_pre) |
| dbg_first_frame("ch[%d],w_int[%d]\n", pre->curr_ch, ret); |
| |
| return ret; |
| } |
| |
| unsigned int dpre_mtotal_wait_int(void *data) |
| { |
| enum EDI_WAIT_INT wret; |
| unsigned int ret = K_DO_R_NOT_FINISH; |
| |
| wret = di_pre_wait_int(NULL); |
| switch (wret) { |
| case EDI_WAIT_INT_NEED_WAIT: |
| ret = K_DO_R_NOT_FINISH; |
| break; |
| case EDI_WAIT_INT_HAVE_INT: |
| ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); |
| break; |
| case EDI_WAIT_INT_TIME_OUT: |
| ret = K_DO_R_FINISH; |
| break; |
| } |
| return ret; |
| } |
| |
| void dpre_mtotal_timeout_contr(void) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| /*move from di_pre_trigger_work*/ |
| if (dimp_get(edi_mp_di_dbg_mask) & 4) |
| dim_dump_mif_size_state(pre->pres, pre->psts); |
| hpre_timeout_read(); |
| |
| if (DIM_IS_IC_EF(SC2)) |
| opl1()->pre_gl_sw(false); |
| |
| dimh_enable_di_pre_mif(false, dimp_get(edi_mp_mcpre_en)); |
| dcntr_dis(); |
| if (di_get_dts_nrds_en()) |
| dim_nr_ds_hw_ctrl(false); |
| pre->pres->pre_de_irq_timeout_count++; |
| |
| pre->pres->pre_de_busy = 0; |
| pre->pres->pre_de_clear_flag = 2; |
| if ((dimp_get(edi_mp_di_dbg_mask) & 0x2)) { |
| pr_info("DI:ch[%d]*****wait %d timeout 0x%x(%d ms)*****\n", |
| pre->curr_ch, |
| pre->pres->field_count_for_cont, |
| RD(DI_INTR_CTRL), |
| (unsigned int)(cur_to_msecs() - |
| pre->pres->irq_time[1])); |
| } |
| /*******************************/ |
| dim_pre_de_done_buf_config(pre->curr_ch, true); |
| |
| dpre_recyc(pre->curr_ch); |
| dpre_vdoing(pre->curr_ch); |
| /*******************************/ |
| /*dpre_recyc(pre->curr_ch);*/ |
| } |
| |
| unsigned int dpre_mtotal_timeout(void *data) |
| { |
| //ary 2020-12-09 ulong flags = 0; |
| |
| //tmp spin_lock_irqsave(&plist_lock, flags); |
| dpre_mtotal_timeout_contr(); |
| //tmp spin_unlock_irqrestore(&plist_lock, flags); |
| |
| return K_DO_R_JUMP(K_DO_TABLE_ID_STOP); |
| } |
| |
| const struct do_table_ops_s pr_mode_total[] = { |
| /*fix*/ |
| [K_DO_TABLE_ID_PAUSE] = { |
| .id = K_DO_TABLE_ID_PAUSE, |
| .mark = 0, |
| .con = NULL, |
| .do_op = NULL, |
| .do_stop_op = NULL, |
| .name = "pause", |
| }, |
| [K_DO_TABLE_ID_STOP] = { |
| .id = K_DO_TABLE_ID_STOP, |
| .mark = 0, |
| .con = NULL, |
| .do_op = NULL, |
| .do_stop_op = NULL, |
| .name = "stop", |
| }, |
| /******************/ |
| [K_DO_TABLE_ID_START] = { /*EDI_PRE_MT_CHECK*/ |
| .id = K_DO_TABLE_ID_START, |
| .mark = 0, |
| .con = NULL, |
| .do_op = dpre_mtotal_check, |
| .do_stop_op = NULL, |
| .name = "start-check_t", |
| }, |
| [EDI_PRE_MT_SET] = { |
| .id = EDI_PRE_MT_SET, |
| .mark = 0, |
| .con = NULL, |
| .do_op = dpre_mtotal_set, |
| .do_stop_op = NULL, |
| .name = "set", |
| }, |
| [EDI_PRE_MT_WAIT_INT] = { |
| .id = EDI_PRE_MT_WAIT_INT, |
| .mark = 0, |
| .con = NULL, |
| .do_op = dpre_mtotal_wait_int, |
| .do_stop_op = NULL, |
| .name = "wait_int", |
| }, |
| [EDI_PRE_MT_TIME_OUT] = { |
| .id = EDI_PRE_MT_TIME_OUT, |
| .mark = 0, |
| .con = NULL, |
| .do_op = dpre_mtotal_timeout, |
| .do_stop_op = NULL, |
| .name = "timeout", |
| }, |
| }; |
| |
| /**************************** |
| * |
| * mode for p |
| * |
| ****************************/ |
| enum EDI_PRE_MP { |
| EDI_PRE_MP_CHECK = K_DO_TABLE_ID_START, |
| EDI_PRE_MP_SET, |
| EDI_PRE_MP_WAIT_INT, |
| EDI_PRE_MP_TIME_OUT, |
| EDI_PRE_MP_CHECK2, |
| EDI_PRE_MP_SET2, |
| EDI_PRE_MP_WAIT_INT2, |
| EDI_PRE_MP_TIME_OUT2, |
| }; |
| |
| unsigned int dpre_mp_check(void *data) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| unsigned int ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP);//K_DO_R_NOT_FINISH; |
| |
| if (pre_run_flag == DI_RUN_FLAG_RUN || |
| pre_run_flag == DI_RUN_FLAG_STEP) { |
| if (pre_run_flag == DI_RUN_FLAG_STEP) |
| pre_run_flag = DI_RUN_FLAG_STEP_DONE; |
| dim_print("%s:\n", __func__); |
| if (!dim_pre_de_buf_config(pre->curr_ch)) { |
| /*pre->flg_wait_int = false;*/ |
| /*pre_p_asi_set_next(pre->curr_ch);*/ |
| ret = K_DO_R_FINISH; |
| } else { |
| /*pre->flg_wait_int = false;*/ |
| ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); |
| } |
| dim_dbg_pre_cnt(pre->curr_ch, "x"); |
| } |
| |
| return ret; |
| } |
| |
| unsigned int dpre_mp_check2(void *data) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| unsigned int ret = K_DO_R_NOT_FINISH; |
| |
| if (!dim_pre_de_buf_config(pre->curr_ch)) { |
| /*pre->flg_wait_int = false;*/ |
| ret = K_DO_R_FINISH; |
| } else { |
| } |
| |
| return ret; |
| } |
| |
| unsigned int dpre_mp_wait_int(void *data) |
| { |
| enum EDI_WAIT_INT wret; |
| unsigned int ret = K_DO_R_NOT_FINISH; |
| |
| wret = di_pre_wait_int(NULL); |
| switch (wret) { |
| case EDI_WAIT_INT_NEED_WAIT: |
| ret = K_DO_R_NOT_FINISH; |
| break; |
| case EDI_WAIT_INT_HAVE_INT: |
| ret = K_DO_R_JUMP(EDI_PRE_MP_CHECK2); |
| break; |
| case EDI_WAIT_INT_TIME_OUT: |
| ret = K_DO_R_FINISH; |
| break; |
| } |
| return ret; |
| } |
| |
| unsigned int dpre_mp_wait_int2(void *data) |
| { |
| enum EDI_WAIT_INT wret; |
| unsigned int ret = K_DO_R_NOT_FINISH; |
| |
| wret = di_pre_wait_int(NULL); |
| switch (wret) { |
| case EDI_WAIT_INT_NEED_WAIT: |
| ret = K_DO_R_NOT_FINISH; |
| break; |
| case EDI_WAIT_INT_HAVE_INT: |
| ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); |
| break; |
| case EDI_WAIT_INT_TIME_OUT: |
| ret = K_DO_R_FINISH; |
| break; |
| } |
| return ret; |
| } |
| |
| unsigned int dpre_mp_timeout(void *data) |
| { |
| dpre_mtotal_timeout_contr(); |
| |
| return K_DO_R_FINISH; |
| } |
| |
| unsigned int dpre_mp_timeout2(void *data) |
| { |
| dpre_mtotal_timeout_contr(); |
| |
| return K_DO_R_JUMP(K_DO_TABLE_ID_STOP); |
| } |
| |
| const struct do_table_ops_s pre_mode_proc[] = { |
| /*fix*/ |
| [K_DO_TABLE_ID_PAUSE] = { |
| .id = K_DO_TABLE_ID_PAUSE, |
| .mark = 0, |
| .con = NULL, |
| .do_op = NULL, |
| .do_stop_op = NULL, |
| .name = "pause", |
| }, |
| [K_DO_TABLE_ID_STOP] = { |
| .id = K_DO_TABLE_ID_STOP, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, |
| .do_op = NULL, |
| .do_stop_op = NULL, |
| .name = "stop", |
| }, |
| /******************/ |
| [K_DO_TABLE_ID_START] = { /*EDI_PRE_MP_CHECK*/ |
| .id = K_DO_TABLE_ID_START, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, |
| .do_op = dpre_mp_check, |
| .do_stop_op = NULL, |
| .name = "start-check_p", |
| }, |
| [EDI_PRE_MP_SET] = { |
| .id = EDI_PRE_MP_SET, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, /*condition*/ |
| .do_op = dpre_mtotal_set, |
| .do_stop_op = NULL, |
| .name = "pset", |
| }, |
| [EDI_PRE_MP_WAIT_INT] = { |
| .id = EDI_PRE_MP_WAIT_INT, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, /*condition*/ |
| .do_op = dpre_mp_wait_int, |
| .do_stop_op = NULL, |
| .name = "pwait_int", |
| }, |
| [EDI_PRE_MP_TIME_OUT] = { |
| .id = EDI_PRE_MP_TIME_OUT, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, /*condition*/ |
| .do_op = dpre_mp_timeout, |
| .do_stop_op = NULL, |
| .name = "ptimeout", |
| }, |
| /******/ |
| [EDI_PRE_MP_CHECK2] = { /*eDI_PRE_MP_CHECK2*/ |
| .id = EDI_PRE_MP_CHECK2, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, /*condition*/ |
| .do_op = dpre_mp_check2, |
| .do_stop_op = NULL, |
| .name = "start-check_p2", |
| }, |
| [EDI_PRE_MP_SET2] = { |
| .id = EDI_PRE_MP_SET2, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, /*condition*/ |
| .do_op = dpre_mtotal_set, |
| .do_stop_op = NULL, |
| .name = "psetp2", |
| }, |
| [EDI_PRE_MP_WAIT_INT2] = { |
| .id = EDI_PRE_MP_WAIT_INT2, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, /*condition*/ |
| .do_op = dpre_mp_wait_int2, |
| .do_stop_op = NULL, |
| .name = "pwait_int2", |
| }, |
| [EDI_PRE_MP_TIME_OUT2] = { |
| .id = EDI_PRE_MP_TIME_OUT2, |
| .mark = 0, /*stop / pause*/ |
| .con = NULL, /*condition*/ |
| .do_op = dpre_mp_timeout2, |
| .do_stop_op = NULL, |
| .name = "ptimeout2", |
| }, |
| |
| }; |
| |
| void pre_mode_setting(void) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| |
| if (pre->pre_st != EDI_PRE_ST4_DO_TABLE) |
| return; |
| |
| do_table_working(&pre->sdt_mode); |
| } |
| |
| /*--------------------------*/ |
| enum EDI_WORK_MODE pre_cfg_count_mode(unsigned int ch, struct vframe_s *vframe) |
| { |
| enum EDI_WORK_MODE pmode; |
| |
| if (is_bypass2(vframe, ch)) { |
| pmode = EDI_WORK_MODE_BYPASS_ALL; |
| return pmode; |
| } |
| |
| if (COM_ME(vframe->type, VIDTYPE_INTERLACE)) { |
| /*interlace:*/ |
| pmode = EDI_WORK_MODE_I; |
| return pmode; |
| } |
| |
| if (dimp_get(edi_mp_prog_proc_config) & 0x10) |
| pmode = EDI_WORK_MODE_P_AS_P; |
| else if (is_from_vdin(vframe)) |
| pmode = EDI_WORK_MODE_P_USE_IBUF; |
| else |
| pmode = EDI_WORK_MODE_P_AS_I; |
| |
| return pmode; |
| } |
| |
| unsigned int dpre_check_mode(unsigned int ch) |
| { |
| struct vframe_s *vframe; |
| unsigned int mode; |
| struct di_ch_s *pch; |
| |
| pch = get_chdata(ch); |
| if (pre_run_flag == DI_RUN_FLAG_RUN || |
| pre_run_flag == DI_RUN_FLAG_STEP) { |
| if (pre_run_flag == DI_RUN_FLAG_STEP) |
| pre_run_flag = DI_RUN_FLAG_STEP_DONE; |
| vframe = nins_peekvfm(pch);//pw_vf_peek(ch); |
| } else { |
| vframe = NULL; |
| } |
| |
| if (!vframe) |
| return EDI_WORK_MODE_NONE; |
| mode = pre_cfg_count_mode(ch, vframe);/*EDI_WORK_MODE_ALL;*/ |
| |
| return mode; |
| } |
| |
| /*--------------------------*/ |
| bool dpre_step4_idle(void) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| bool reflesh = false; |
| unsigned int ch; |
| |
| ch = pre->curr_ch; |
| if (!pw_try_sw_ch_next_pre(ch)) |
| return false; |
| |
| if (pre->idle_cnt >= DI_CHANNEL_NUB) { |
| pre->idle_cnt = 0; |
| return false; |
| } |
| pre->pres = get_pre_stru(pre->curr_ch); |
| pre->psts = get_post_stru(pre->curr_ch); |
| |
| /*state*/ |
| pre->pre_st++;/*tmp*/ |
| reflesh = true; |
| |
| return reflesh; |
| } |
| |
| bool dpre_step4_check(void) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| bool reflesh = false; |
| unsigned int mode; |
| |
| /*get vframe and select mode |
| * now: fix use total table |
| */ |
| |
| mode = dpre_check_mode(pre->curr_ch); |
| |
| if (mode == EDI_WORK_MODE_NONE) { |
| pre->pre_st--; |
| pre->idle_cnt++; |
| return true; |
| } |
| pre->idle_cnt = 0; |
| if (mode == EDI_WORK_MODE_P_AS_I) { |
| #ifdef MARK_SC2 |
| do_table_init(&pre->sdt_mode, |
| &pre_mode_proc[0], |
| ARRAY_SIZE(pre_mode_proc)); |
| pre->sdt_mode.name = "mproc"; |
| #else |
| do_table_init(&pre->sdt_mode, |
| &pr_mode_total[0], |
| ARRAY_SIZE(pr_mode_total)); |
| pre->sdt_mode.name = "mtotal"; |
| #endif |
| |
| } else { |
| do_table_init(&pre->sdt_mode, |
| &pr_mode_total[0], |
| ARRAY_SIZE(pr_mode_total)); |
| pre->sdt_mode.name = "mtotal"; |
| } |
| do_talbe_cmd(&pre->sdt_mode, EDO_TABLE_CMD_START); |
| |
| /*state*/ |
| pre->pre_st++; |
| reflesh = true; |
| |
| return reflesh; |
| } |
| |
| bool dpre_step4_do_table(void) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| bool reflesh = false; |
| |
| if (do_table_is_crr(&pre->sdt_mode, K_DO_TABLE_ID_STOP)) { |
| pre->pre_st = EDI_PRE_ST4_IDLE; |
| reflesh = true; |
| } |
| return reflesh; |
| } |
| |
| bool dpre_after_do_table(void) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| enum EDI_PRE_ST4 pre_st; |
| bool ret = false; |
| |
| if (do_table_is_crr(&pre->sdt_mode, K_DO_TABLE_ID_STOP)) { |
| pre->pre_st = EDI_PRE_ST4_IDLE; |
| ret = true; |
| } |
| pre_st = pre->pre_st; |
| pre->self_trig_mask = 0; |
| if (pre_run_flag == DI_RUN_FLAG_RUN) |
| bclr(&pre->self_trig_mask, 0); |
| else |
| bset(&pre->self_trig_mask, 0); |
| |
| if (pre_st == EDI_PRE_ST4_DO_TABLE) |
| bset(&pre->self_trig_mask, 1); |
| else |
| bclr(&pre->self_trig_mask, 1); |
| return ret; |
| } |
| |
| const struct di_func_tab_s di_pre_func_tab4[] = { |
| {EDI_PRE_ST4_EXIT, NULL}, |
| {EDI_PRE_ST4_IDLE, dpre_step4_idle}, |
| {EDI_PRE_ST4_CHECK, dpre_step4_check}, |
| {EDI_PRE_ST4_DO_TABLE, dpre_step4_do_table}, |
| }; |
| |
| const char * const dpre_state_name4[] = { |
| "EXIT", |
| "IDLE", /*switch to next channel?*/ |
| "CHECK", |
| "DO_TABLE", |
| }; |
| |
| const char *dpre_state4_name_get(enum EDI_PRE_ST4 state) |
| { |
| if (state > EDI_PRE_ST4_DO_TABLE) |
| return "nothing"; |
| |
| return dpre_state_name4[state]; |
| } |
| |
| bool dpre_process_step4(void) |
| { |
| struct di_hpre_s *pre = get_hw_pre(); |
| enum EDI_PRE_ST4 pre_st = pre->pre_st; |
| //ary 2020-12-09 ulong flags = 0; |
| |
| if (pre_st > EDI_PRE_ST4_EXIT) { |
| //ary 2020-12-09 spin_lock_irqsave(&plist_lock, flags); |
| dim_recycle_post_back(pre->curr_ch); |
| dpre_recyc(pre->curr_ch); |
| dpre_vdoing(pre->curr_ch); |
| //ary 2020-12-09 spin_unlock_irqrestore(&plist_lock, flags); |
| } |
| if (pre_st <= EDI_PRE_ST4_DO_TABLE && |
| di_pre_func_tab4[pre_st].func) { |
| return di_pre_func_tab4[pre_st].func(); |
| } |
| |
| return false; |
| } |