| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| */ |
| |
| #include <linux/semaphore.h> |
| #include <linux/kfifo.h> |
| #include <linux/spinlock.h> |
| |
| #include "deinterlace.h" |
| #include "di_data_l.h" |
| #include "di_pre.h" |
| #include "di_prc.h" |
| #include "di_dbg.h" |
| #include "di_que.h" |
| #include "di_task.h" |
| |
| #include "di_vframe.h" |
| |
| #ifdef MARK_HIS |
| const struct di_init_parm dim_cfg_parm_default = { |
| .work_mode = WORK_MODE_PRE_POST, |
| .buffer_mode = BUFFER_MODE_ALLOC_BUF, |
| .ops = { |
| .empty_input_done = NULL, |
| .fill_output_done = NULL, |
| }, |
| }; |
| #endif |
| #ifdef MARK_HIS //@ary_note to-do |
| /********************************************************** |
| * ops |
| **********************************************************/ |
| static void *ins_peek(struct di_ch_s *pch) |
| { |
| unsigned int index; |
| |
| if (!qued_ops.peek(pch, QUED_T_IS_IN, &index)) |
| return NULL; |
| return (void *)pch->interf.u.dinst.in[index]; |
| } |
| |
| static void *ins_get(struct di_ch_s *pch) |
| { |
| unsigned int index; |
| struct di_buffer *dbuf; |
| unsigned int dbg_cnt1, dbg_cnt2; |
| |
| if (!qued_ops.move(pch, |
| QUED_T_IS_IN, |
| QUED_T_IS_FREE, &index)) { |
| dbg_cnt1 = qued_ops.list_count(pch, QUED_T_IS_IN); |
| dbg_cnt2 = qued_ops.list_count(pch, QUED_T_IS_FREE); |
| PR_ERR("%s:no space,%d,%d\n", __func__, dbg_cnt1, dbg_cnt2); |
| return NULL; |
| } |
| sum_g_inc(pch->ch_id); |
| dbuf = pch->interf.u.dinst.in[index]; |
| pch->interf.u.dinst.in[index] = NULL; |
| return (void *)dbuf; |
| } |
| |
| static void ins_put(void *data, struct di_ch_s *pch) |
| { |
| struct dim_inter_s *pintf = &pch->interf; |
| struct di_operations_s *ops; |
| |
| ops = &pintf->u.dinst.parm.ops; |
| if (ops->empty_input_done) { |
| sum_p_inc(pch->ch_id); |
| ops->empty_input_done((struct di_buffer *)data); |
| //debug only dump_stack(); |
| } |
| } |
| |
| const struct dim_itf_ops_s inst_in_ops = { |
| .peek = ins_peek, |
| .get = ins_get, |
| .put = ins_put, |
| }; |
| |
| /* mode 2 for drop */ |
| void ins_2_doing(struct di_ch_s *pch, bool bypass, struct di_buf_s *pstdi_buf) |
| { |
| unsigned int ch = pch->ch_id; |
| struct di_buf_s *di_buf = NULL; /*post nobuf buffer*/ |
| bool ret; |
| struct di_buffer *ins_buf, *ins_in; |
| unsigned int idx; |
| struct dim_inter_s *pintf; |
| struct vframe_s *vfmin, *vfmout; |
| struct canvas_config_s cvs[2]; |
| |
| if (di_que_is_empty(ch, QUE_POST_NOBUF)) |
| return; |
| |
| if (qued_ops.is_empty(pch, QUED_T_IS_PST_DOBEF)) |
| return; |
| |
| di_buf = di_que_peek(ch, QUE_POST_NOBUF); |
| dim_print("%s:1:%p,buf[%d],t[%d]\n", __func__, di_buf, di_buf->index, di_buf->type); |
| trace_buf(di_buf, DIM_QUE_PEEK, QUE_POST_NOBUF, |
| (DIM_DBG_MARK | 0x00000001)); |
| ret = di_que_out(ch, QUE_POST_NOBUF, di_buf); |
| if (!ret) { |
| PR_ERR("%s:no buf?\n", __func__); |
| return; |
| } |
| |
| pintf = &pch->interf; |
| qued_ops.out(pch, QUED_T_IS_PST_DOBEF, &idx); |
| |
| ins_buf = pintf->u.dinst.out[idx]; |
| if (!ins_buf) { |
| PR_ERR("%s:out is null\n", __func__); |
| return; |
| } |
| di_buf->c.pdvfm->vfm_out = pintf->u.dinst.out[idx]; |
| pintf->u.dinst.out[idx] = NULL; |
| qued_ops.in(pch, QUED_T_IS_PST_FREE, idx); |
| |
| trace_buf(di_buf, DIM_QUE_OUT, QUE_POST_NOBUF, |
| (DIM_DBG_MARK | 0x00000002)); |
| |
| dbg_dbg("%s:ch[%d],type[%d], id[%d]\n", __func__, pch->ch_id, |
| di_buf->type, di_buf->index); |
| dbg_dbg("ins_buf,type[%d], id[%d]\n", |
| ins_buf->mng.type, |
| ins_buf->mng.index); |
| if (!ins_buf) |
| PR_ERR("%s:out2 is null\n", __func__); |
| |
| /*in*/ |
| ins_in = (struct di_buffer *)di_buf->c.pdvfm->vfm_in; |
| vfmin = ins_in->vf; |
| vfmout = ins_buf->vf; |
| if (!di_buf->c.wmode.is_eos) { |
| /*copy vfm */ |
| memcpy(&cvs[0], &vfmout->canvas0_config[0], sizeof(cvs)); |
| memcpy(vfmout, vfmin, sizeof(*vfmout)); |
| memcpy(&vfmout->canvas0_config[0], |
| &cvs[0], sizeof(cvs)); |
| } |
| |
| if (!di_buf->c.wmode.is_bypass) { |
| //di_buf->nr_adr = ins_buf->phy_addr; |
| //di_buf->nr_adr |
| //= ins_buf->vf->canvas0_config[0].phy_addr; |
| //ins_buf->phy_addr; |
| dim_ins_cnt_post_cvs_size2(di_buf, ins_buf, ch); |
| } else { |
| /* bypass */ |
| if (di_buf->c.wmode.is_eos) { |
| ins_buf->flag |= DI_FLAG_EOS; |
| PR_INF("%s:eos\n", __func__); |
| } else { |
| ins_buf->flag |= DI_FLAG_BUF_BY_PASS; |
| } |
| dim_print("%s:%p bypass\n", __func__, ins_buf); |
| } |
| dbg_vfm(vfmout, 1); |
| trace_buf(di_buf, DIM_QUE_IN, QUE_POST_DOING, |
| (DIM_DBG_MARK | 0x00000003)); |
| dim_print("%s:%p,buf[%d],t[%d]\n", __func__, |
| di_buf, di_buf->index, di_buf->type); |
| di_que_in(ch, QUE_POST_DOING, di_buf); |
| } |
| #endif //@ary_note todo |
| |
| /************************************** |
| * bit 0: force no release |
| * bit 1: dbg for buffer |
| **************************************/ |
| |
| static unsigned int new_int; |
| module_param_named(new_int, new_int, uint, 0664); |
| |
| bool dim_dbg_new_int(unsigned int id) |
| { |
| bool ret = false; |
| /* id is 1 ~ 32 */ |
| |
| if (id > 32 || id == 0) |
| return false; |
| |
| if (bget(&new_int, id - 1)) |
| ret = true; |
| |
| return ret; |
| } |
| |
| static void nins_m_unreg_new(struct di_ch_s *pch) |
| { |
| } |
| |
| /************************************** |
| * nins_m_recycle |
| * op_back_input |
| * _RECYCL -> _IDLE |
| * back vfm to dec |
| * run in main |
| **************************************/ |
| |
| static void nins_m_recycle_ins(struct di_ch_s *pch) |
| { |
| struct buf_que_s *pbufq; |
| int i; |
| unsigned int cnt, ch; |
| struct dim_nins_s *ins; |
| //struct vframe_s *vfm; |
| struct di_buffer *buffer; |
| |
| if (!pch || pch->itf.etype != EDIM_NIN_TYPE_INS) { |
| PR_ERR("%s:\n", __func__); |
| return; |
| } |
| ch = pch->ch_id; |
| pbufq = &pch->nin_qb; |
| |
| cnt = qbufp_count(pbufq, QBF_NINS_Q_RECYCL); |
| |
| if (!cnt) |
| return; |
| //qbuf_dbg_check_in_buffer_id(1); |
| |
| for (i = 0; i < cnt; i++) { |
| ins = nins_move(pch, QBF_NINS_Q_RECYCL, QBF_NINS_Q_IDLE); |
| // vfm = (struct vframe_s *)ins->c.ori; |
| buffer = (struct di_buffer *)ins->c.ori; |
| ins->c.ori = NULL; |
| if (buffer) { |
| // dim_dbg_buffer(buffer, 10); |
| //pw_vf_put(vfm, ch); |
| //pw_vf_notify_provider(ch, |
| // VFRAME_EVENT_RECEIVER_PUT, NULL); |
| pch->itf.u.dinst.parm.ops.empty_input_done(buffer); |
| sum_p_inc(ch); |
| } |
| |
| memset(&ins->c, 0, sizeof(ins->c)); |
| } |
| //qbuf_dbg_check_in_buffer_id(2); |
| } |
| |
| static int reg_idle_ch(void) |
| { |
| unsigned int ch; |
| struct dim_itf_s *pintf; |
| int ret = -1; |
| //int i; |
| struct di_ch_s *pch; |
| struct di_mng_s *pbm = get_bufmng(); |
| |
| for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { |
| pch = get_chdata(ch); |
| |
| pintf = &pch->itf;//get_dev_intf(ch); |
| mutex_lock(&pch->itf.lock_reg); |
| |
| if ((pbm->tmode_pre[ch] == EDIM_TMODE_2_PW_OUT || |
| pbm->tmode_pre[ch] == EDIM_TMODE_3_PW_LOCAL) && |
| !pintf->reg) { |
| /*set reg flg*/ |
| pintf->reg = true; |
| ret = (int)ch; |
| mutex_unlock(&pch->itf.lock_reg); |
| dbg_dbg("%s:ch[%d], ret[%d]\n", __func__, ch, ret); |
| break; |
| } |
| dbg_dbg("%s:ch[%d], tmode[%d], reg[%d]\n", __func__, |
| ch, pbm->tmode_pre[ch], pintf->reg); |
| |
| mutex_unlock(&pch->itf.lock_reg); |
| } |
| dbg_dbg("%s:%d\n", __func__, ret); |
| |
| return ret; |
| } |
| |
| #define ERR_INDEX (0xffff) |
| static unsigned int index_2_ch(int index) |
| { |
| unsigned int ret; |
| |
| if (index >= DI_CHANNEL_NUB || index < 0) { |
| PR_ERR("instance index is overflow:%d\n", index); |
| ret = ERR_INDEX; |
| } else { |
| ret = (unsigned int)index; |
| } |
| |
| return ret; |
| } |
| |
| void dim_dbg_buffer(struct di_buffer *buffer, unsigned int id) |
| { |
| PR_INF("%s:%d:%px\n", __func__, id, buffer); |
| PR_INF("\t:code:0x%x,ch[%d],indx[%d], type[%d]\n", |
| buffer->mng.code, buffer->mng.ch, |
| buffer->mng.index, buffer->mng.type); |
| if (buffer->vf) |
| PR_INF("\t:vf:0x%px, 0x%x\n", buffer->vf, buffer->vf->index); |
| else |
| PR_INF("\t:%s\n", "no vf"); |
| } |
| |
| void dim_dbg_buffer2(struct di_buffer *buffer, unsigned int id) |
| { |
| if (!buffer) { |
| dbg_nq("%s:%d:no buffer\n", __func__, id); |
| return; |
| } |
| dbg_nq("%s:%d:%px\n", __func__, id, buffer); |
| if (buffer->vf) { |
| dbg_nq("\t:0x%px, 0x%lx,0x%lx\n", buffer, |
| buffer->vf->canvas0_config[0].phy_addr, |
| buffer->vf->canvas0_config[1].phy_addr); |
| } else { |
| dbg_nq("\t:%s\n", "no vf"); |
| } |
| } |
| |
| static void cfg_ch_set(struct di_ch_s *pch) |
| { |
| struct di_init_parm *parm; |
| unsigned int out_format; |
| bool used_di_define = false; |
| parm = &pch->itf.u.dinst.parm; |
| out_format = parm->output_format & 0xffff; |
| |
| if (parm->output_format & DI_OUTPUT_BY_DI_DEFINE && |
| pch->itf.tmode == EDIM_TMODE_3_PW_LOCAL) |
| used_di_define = true; |
| |
| if (!used_di_define) { |
| switch (out_format) { |
| case DI_OUTPUT_422: |
| cfgsch(pch, POUT_FMT, 0); |
| cfgsch(pch, IOUT_FMT, 0); |
| break; |
| case DI_OUTPUT_NV12: |
| cfgsch(pch, POUT_FMT, 2); |
| cfgsch(pch, IOUT_FMT, 2); |
| break; |
| case DI_OUTPUT_NV21: |
| cfgsch(pch, POUT_FMT, 1); |
| cfgsch(pch, IOUT_FMT, 1); |
| break; |
| default: |
| PR_INF("%s:format not set\n", __func__); |
| break; |
| } |
| cfgsch(pch, DW_EN, 0); |
| } |
| cfgsch(pch, KEEP_DEC_VF, 0); // for all new_interface |
| if (dip_itf_is_ins_exbuf(pch)) { |
| //cfgsch(pch, KEEP_DEC_VF, 0); |
| cfgsch(pch, ALLOC_SCT, 0); |
| cfgsch(pch, 4K, 0); |
| cfgsch(pch, DW_EN, 0); |
| } |
| |
| if (!(di_dbg & DBG_M_REG)) |
| return; |
| /* debug only */ |
| PR_INF("%s:ch[%d]\n", |
| __func__, pch->ch_id); |
| PR_INF("\tkeep_dec_vf[%d]\n", cfggch(pch, KEEP_DEC_VF)); |
| PR_INF("\tout_fmt[%d][%d]\n", cfggch(pch, POUT_FMT), |
| cfggch(pch, IOUT_FMT)); |
| PR_INF("\talloc_sct[%d],4K[%d],dw[%d]\n", cfggch(pch, ALLOC_SCT), |
| cfggch(pch, 4K), |
| cfggch(pch, DW_EN)); |
| PR_INF("\ttvp:%d\n", |
| parm->output_format & DI_OUTPUT_TVP ? 1 : 0); |
| } |
| |
| /********************************************************** |
| * @brief di_create_instance creat di instance |
| * @param[in] parm Pointer of parm structure |
| * @return di index for success, or fail type if < 0 |
| **********************************************************/ |
| int di_create_instance(struct di_init_parm parm) |
| { |
| int ret; |
| unsigned int ch; |
| struct di_ch_s *pch; |
| struct dim_itf_s *itf; |
| |
| dbg_reg("%s:", __func__); |
| ret = reg_idle_ch(); |
| if (ret < 0) { |
| PR_ERR("%s:no idle ch\n", __func__); |
| return DI_ERR_REG_NO_IDLE_CH; |
| } |
| |
| if ((parm.output_format & 0xffff) == DI_OUTPUT_422 || |
| parm.output_format & DI_OUTPUT_BY_DI_DEFINE) |
| parm.output_format &= ~DI_OUTPUT_LINEAR; |
| |
| ch = (unsigned int)ret; |
| pch = get_chdata(ch); |
| itf = &pch->itf; |
| itf->etype = EDIM_NIN_TYPE_INS; |
| /*parm*/ |
| memcpy(&itf->u.dinst.parm, &parm, sizeof(struct di_init_parm)); |
| |
| itf->tmode = EDIM_TMODE_2_PW_OUT; |
| if (itf->u.dinst.parm.work_mode == WORK_MODE_PRE_POST) { |
| switch (itf->u.dinst.parm.buffer_mode) { |
| case BUFFER_MODE_ALLOC_BUF: |
| itf->tmode = EDIM_TMODE_3_PW_LOCAL; |
| break; |
| case BUFFER_MODE_USE_BUF: |
| itf->tmode = EDIM_TMODE_2_PW_OUT; |
| break; |
| default: |
| PR_ERR("%s:bmode[%d]\n", __func__, |
| itf->u.dinst.parm.buffer_mode); |
| break; |
| } |
| } else { |
| PR_ERR("%s:wmode[%d]\n", __func__, |
| itf->u.dinst.parm.work_mode); |
| } |
| |
| //reg: |
| mutex_lock(&pch->itf.lock_reg); |
| pch->sum_reg_cnt++; |
| dim_api_reg(DIME_REG_MODE_NEW, pch); |
| npst_reset(pch); |
| pch->itf.opins_m_back_in = nins_m_recycle_ins; |
| pch->itf.op_m_unreg = nins_m_unreg_new; |
| if (itf->tmode == EDIM_TMODE_3_PW_LOCAL) { |
| itf->op_fill_ready = ndis_fill_ready; |
| itf->op_ready_out = dip_itf_ndrd_ins_m2_out; |
| } else { |
| itf->op_fill_ready = ndrd_m1_fill_ready; |
| itf->op_ready_out = dip_itf_ndrd_ins_m1_out; |
| } |
| itf->op_cfg_ch_set = cfg_ch_set; |
| //cfg_ch_set(pch); |
| mutex_unlock(&pch->itf.lock_reg); |
| PR_INF("%s:ch[%d],tmode[%d]\n", "create", ch, itf->tmode); |
| PR_INF("\tout:0x%x\n", itf->u.dinst.parm.output_format); |
| return ch; |
| } |
| EXPORT_SYMBOL(di_create_instance); |
| |
| /********************************************************** |
| ** |
| * @brief di_set_parameter set parameter to di for init |
| * |
| * @param[in] index instance index |
| * |
| * @return 0 for success, or fail type if < 0 |
| * |
| **********************************************************/ |
| int di_destroy_instance(int index) |
| { |
| struct dim_itf_s *pintf; |
| unsigned int ch; |
| struct di_ch_s *pch; |
| |
| dbg_reg("%s:\n", __func__); |
| ch = index_2_ch(index); |
| if (ch == ERR_INDEX) { |
| PR_ERR("%s:index overflow\n", __func__); |
| return DI_ERR_INDEX_OVERFLOW; |
| } |
| |
| pch = get_chdata(ch); |
| |
| pintf = &pch->itf; |
| mutex_lock(&pch->itf.lock_reg); |
| if (!pintf->reg) { |
| PR_WARN("%s:double unreg\n", __func__); |
| mutex_unlock(&pch->itf.lock_reg); |
| return 0; |
| } |
| |
| pintf->reg = 0; |
| //dip_event_unreg_chst(ch); |
| dim_trig_unreg(ch); |
| dim_api_unreg(DIME_REG_MODE_NEW, pch); |
| mutex_unlock(&pch->itf.lock_reg); |
| PR_INF("%s:ch[%d]:end\n", __func__, ch); |
| return 0; |
| } |
| EXPORT_SYMBOL(di_destroy_instance); |
| |
| /********************************************************** |
| ** |
| * @brief di_empty_input_buffer send input date to di |
| * |
| * @param[in] index instance index |
| * @param[in] buffer Pointer of buffer structure |
| * |
| * @return Success or fail type |
| **********************************************************/ |
| enum DI_ERRORTYPE di_empty_input_buffer(int index, struct di_buffer *buffer) |
| { |
| struct dim_itf_s *pintf; |
| unsigned int ch; |
| struct di_ch_s *pch; |
| // unsigned int buf_index = 0xff; |
| //2020-12-10: |
| unsigned int free_nub; |
| struct buf_que_s *pbufq; |
| struct dim_nins_s *pins; |
| bool flg_q; |
| // unsigned int err; |
| |
| ch = index_2_ch(index); |
| if (ch == ERR_INDEX) { |
| PR_ERR("%s:index overflow\n", __func__); |
| return DI_ERR_INDEX_OVERFLOW; |
| } |
| pch = get_chdata(ch); |
| pintf = &pch->itf; |
| if (!pintf->reg) { |
| PR_WARN("%s:ch[%d] not reg\n", __func__, ch); |
| return DI_ERR_INDEX_NOT_ACTIVE; |
| } |
| |
| #ifdef MARK_HIS |
| qued_ops.peek(pch, QUED_T_IS_FREE, &buf_index); |
| if (buf_index == 0xff) { |
| PR_ERR("%s:no free\n", __func__); |
| return DI_ERR_IN_NO_SPACE; |
| } |
| qued_ops.out(pch, QUED_T_IS_FREE, &buf_index); |
| pintf->u.dinst.in[buf_index] = buffer; |
| qued_ops.in(pch, QUED_T_IS_IN, buf_index); |
| #endif |
| |
| //2020-12-10: |
| pbufq = &pch->nin_qb; |
| free_nub = qbufp_count(pbufq, QBF_NINS_Q_IDLE); |
| if (!free_nub) { |
| PR_WARN("%s:no nins idle\n", __func__); |
| return DI_ERR_IN_NO_SPACE; |
| } |
| |
| /* get ins */ |
| flg_q = qbuf_out(pbufq, QBF_NINS_Q_IDLE, &index); |
| if (!flg_q) { |
| PR_ERR("%s:qout\n", __func__); |
| return DI_ERR_IN_NO_SPACE; |
| } |
| pins = (struct dim_nins_s *)pbufq->pbuf[index].qbc; |
| pins->c.ori = buffer; |
| //pins->c.etype = EDIM_NIN_TYPE_VFM; |
| if (dip_itf_is_ins(pch) && dim_dbg_new_int(2)) |
| dim_dbg_buffer2(buffer, 0); |
| pins->c.cnt = pch->in_cnt; |
| pch->in_cnt++; |
| |
| if (buffer->flag & DI_FLAG_EOS) { |
| if (buffer->vf) { |
| memcpy(&pins->c.vfm_cp, |
| buffer->vf, sizeof(pins->c.vfm_cp)); |
| |
| if (IS_I_SRC(pins->c.vfm_cp.type)) { |
| PR_INF("ch[%d] in eos I\n", ch); |
| pins->c.vfm_cp.type |= 0x3800; |
| } else if (IS_COMP_MODE(pins->c.vfm_cp.type)) { |
| PR_INF("ch[%d] in eos COMP\n", ch); |
| pins->c.vfm_cp.type |= 0x9000; |
| } else { |
| pins->c.vfm_cp.type |= 0x9000; |
| PR_INF("ch[%d] in eos p-other\n", ch); |
| } |
| } else { |
| pins->c.vfm_cp.type |= VIDTYPE_INTERLACE_TOP; |
| //test only |
| pins->c.vfm_cp.type |= 0x3800; |
| PR_INF("ch[%d] in eos vf null\n", ch); |
| } |
| pins->c.vfm_cp.type |= VIDTYPE_V4L_EOS; |
| pins->c.vfm_cp.width = 1920; |
| pins->c.vfm_cp.height = 1080; |
| } else { |
| /* @ary_note: eos may be no vf */ |
| memcpy(&pins->c.vfm_cp, buffer->vf, sizeof(pins->c.vfm_cp)); |
| } |
| if (get_datal()->dct_op && get_datal()->dct_op->is_en(pch)) |
| flg_q = qbuf_in(pbufq, QBF_NINS_Q_DCT, index); |
| else |
| flg_q = qbuf_in(pbufq, QBF_NINS_Q_CHECK, index); |
| sum_g_inc(ch); |
| if (!flg_q) { |
| PR_ERR("%s:qin check\n", __func__); |
| qbuf_in(pbufq, QBF_NINS_Q_IDLE, index); |
| } |
| //dbg_itf_tmode(pch,1); |
| if (pch->in_cnt < 4) { |
| if (pch->in_cnt == 1) |
| dbg_timer(ch, EDBG_TIMER_1_GET); |
| else if (pch->in_cnt == 2) |
| dbg_timer(ch, EDBG_TIMER_2_GET); |
| else if (pch->in_cnt == 3) |
| dbg_timer(ch, EDBG_TIMER_3_GET); |
| } |
| task_send_ready(20); |
| return DI_ERR_NONE; |
| } |
| EXPORT_SYMBOL(di_empty_input_buffer); |
| |
| //@ary_note mem alloc by outside |
| static enum DI_ERRORTYPE di_fill_output_buffer_mode2(struct di_ch_s *pch, |
| struct di_buffer *buffer) |
| { |
| //bool ret; |
| |
| #ifdef MARK_HIS //@ary_note todo |
| /*from QUED_T_IS_PST_FREE to QUED_T_IS_PST_DOBEF */ |
| struct di_ch_s *pch; |
| unsigned int buf_index = 0xff; |
| struct dim_itf_s *pintf; |
| |
| pch = get_chdata(pintf->ch); |
| #ifdef MARK_HIS |
| /*que IS_PST*/ |
| if (!qued_ops.move(pch, |
| QUED_T_IS_PST_FREE, |
| QUED_T_IS_PST_DOBEF, &buf_index)) { |
| PR_WARN("%s:ch[%d]:no space for 0x%p\n", __func__, ch, buffer); |
| return DI_ERR_IN_NO_SPACE; |
| } |
| |
| pintf->u.dinst.out[buf_index] = buffer; |
| #else |
| qued_ops.peek(pch, QUED_T_IS_PST_FREE, &buf_index); |
| if (buf_index == 0xff) { |
| PR_ERR("%s: NO PST_FREE\n", __func__); |
| return DI_ERR_IN_NO_SPACE; |
| } |
| qued_ops.out(pch, QUED_T_IS_PST_FREE, &buf_index); |
| pintf->u.dinst.out[buf_index] = buffer; |
| qued_ops.in(pch, QUED_T_IS_PST_DOBEF, buf_index); |
| |
| #endif |
| #endif //@ary_note todo |
| if (dip_itf_is_ins(pch) && dim_dbg_new_int(2)) |
| dim_dbg_buffer2(buffer, 1); |
| npst_qin(pch, buffer); |
| |
| pch->sum_ext_buf_in2++; |
| return DI_ERR_NONE; |
| } |
| |
| /* @ary_note: buffer alloc by di */ |
| /* @ary_note: use this api to put back display buffer */ |
| /* @ary_note: same as vfm put */ |
| static enum DI_ERRORTYPE di_fill_output_buffer_mode3(struct di_ch_s *pch, |
| struct di_buffer *buffer) |
| { |
| /*back buf to di */ |
| struct dim_itf_s *pintf; |
| // unsigned int buf_index = 0xff; |
| //struct di_buf_s *di_buf = NULL; |
| //tmp ulong irq_flag2 = 0; |
| unsigned int ch; |
| struct dim_ndis_s *ndis1; |
| |
| //pch = get_chdata(ch); |
| ch = pch->ch_id; |
| pintf = &pch->itf; |
| |
| sum_pst_p_inc(ch); |
| ndis1 = (struct dim_ndis_s *)buffer->private_data; |
| if (IS_ERR_OR_NULL(pintf)) { |
| /* bypass */ |
| PR_WARN("%s:bypass?\n", __func__); |
| pintf->u.dinst.parm.ops.empty_input_done(buffer); |
| sum_p_inc(ch);// |
| return DI_ERR_NONE; |
| } |
| |
| task_send_cmd2(ch, |
| LCMD2(ECMD_RL_KEEP, |
| ch, |
| ndis1->header.index)); |
| //task_send_ready(); |
| return DI_ERR_NONE; |
| } |
| |
| /********************************************************** |
| * @brief di_fill_output_buffer send output buffer to di |
| * |
| * @param[in] index instance index |
| * @param[in] buffer Pointer of buffer structure |
| * |
| * @return Success or fail type |
| *********************************************************/ |
| enum DI_ERRORTYPE di_fill_output_buffer(int index, struct di_buffer *buffer) |
| { |
| struct dim_itf_s *pintf; |
| unsigned int ch; |
| struct di_ch_s *pch; |
| enum DI_ERRORTYPE ret = DI_ERR_NONE; |
| |
| /*check channel*/ |
| ch = index_2_ch(index); |
| if (ch == ERR_INDEX) { |
| PR_ERR("%s:index overflow\n", __func__); |
| return DI_ERR_INDEX_OVERFLOW; |
| } |
| pch = get_chdata(ch); |
| pintf = &pch->itf; |
| dim_print("%s:ch[%d],ptf ch[%d]\n", __func__, ch, pintf->ch); |
| if (!pintf->reg) { |
| PR_WARN("%s:ch[%d] not reg\n", __func__, ch); |
| return DI_ERR_INDEX_NOT_ACTIVE; |
| } |
| |
| if (pintf->tmode == EDIM_TMODE_2_PW_OUT) |
| ret = di_fill_output_buffer_mode2(pch, buffer); |
| else if (pintf->tmode == EDIM_TMODE_3_PW_LOCAL) |
| ret = di_fill_output_buffer_mode3(pch, buffer); |
| task_send_ready(21); |
| return ret; |
| } |
| EXPORT_SYMBOL(di_fill_output_buffer); |
| |
| int di_release_keep_buf(struct di_buffer *buffer) |
| { |
| /*back buf to di */ |
| // struct dim_itf_s *pintf; |
| struct di_ch_s *pch; |
| unsigned int ch; |
| struct dim_ndis_s *ndis1; |
| |
| if (!buffer || !buffer->private_data) { |
| PR_INF("%s:no di data\n", __func__); |
| return -1; |
| } |
| ndis1 = (struct dim_ndis_s *)buffer->private_data; |
| |
| ch = buffer->mng.ch; |
| pch = get_chdata(ch); |
| |
| sum_pst_p_inc(ch); |
| |
| task_send_cmd2(ch, |
| LCMD2(ECMD_RL_KEEP, |
| ch, |
| ndis1->header.index)); |
| return 0; |
| } |
| EXPORT_SYMBOL(di_release_keep_buf); |
| |
| /********************************************************** |
| * @brief di_get_output_buffer_num get output buffer num |
| * |
| * @param[in] index instance index |
| * @param[in] buffer Pointer of buffer structure |
| * |
| * @return number or fail type |
| *********************************************************/ |
| int di_get_output_buffer_num(int index) |
| { |
| struct dim_itf_s *pintf; |
| unsigned int ch = 0; |
| struct di_ch_s *pch; |
| int ret = -1; |
| |
| dbg_reg("%s:\n", __func__); |
| ch = index_2_ch(index); |
| if (ch == ERR_INDEX) { |
| PR_ERR("%s:index overflow\n", __func__); |
| return DI_ERR_INDEX_OVERFLOW; |
| } |
| |
| pch = get_chdata(ch); |
| pintf = &pch->itf; |
| if (pintf->tmode == EDIM_TMODE_3_PW_LOCAL) |
| ret = DIM_NDIS_NUB; |
| dbg_reg("%s:end\n", __func__); |
| return ret; |
| } |
| EXPORT_SYMBOL(di_get_output_buffer_num); |
| |
| /********************************************************** |
| * @brief di_get_input_buffer_num get inptut buffer num |
| * |
| * @param[in] index instance index |
| * @param[in] buffer Pointer of buffer structure |
| * |
| * @return number or fail type |
| *********************************************************/ |
| int di_get_input_buffer_num(int index) |
| { |
| struct dim_itf_s *pintf; |
| unsigned int ch = 0; |
| struct di_ch_s *pch; |
| int ret = -1; |
| |
| dbg_reg("%s:\n", __func__); |
| ch = index_2_ch(index); |
| if (ch == ERR_INDEX) { |
| PR_ERR("%s:index overflow\n", __func__); |
| return DI_ERR_INDEX_OVERFLOW; |
| } |
| |
| pch = get_chdata(ch); |
| pintf = &pch->itf; |
| if (pintf->tmode == EDIM_TMODE_3_PW_LOCAL) |
| ret = DIM_NINS_NUB; |
| dbg_reg("%s:end\n", __func__); |
| return ret; |
| } |
| EXPORT_SYMBOL(di_get_input_buffer_num); |
| |