From c7f2221333a2fb498af3335a5d6a6a1983a62bcc Mon Sep 17 00:00:00 2001 From: Rong Zhang Date: Wed, 3 Apr 2019 10:18:40 +0800 Subject: [PATCH] media_module: mmpeg2 [1/1] PD#SWPL-6488 Problem: Not support user data push to application Solution: update ucode and driver to support user data push for multi-mpeg12 ucode gerrit id: 65033 ucode change id: I9abd700aa72f9073d581e8192fbed0277d30ce2e Verify: Verified einstein Change-Id: I9364923d5ea9c0cd6925a1cb54febcf377ee3ce4 Signed-off-by: Rong Zhang --- .../decoder/mpeg12/vmpeg12_multi.c | 874 +++++++++++++++++- firmware/video/video_ucode.bin | Bin 1642240 -> 1642240 bytes 2 files changed, 843 insertions(+), 31 deletions(-) diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c index ffa110dae4bf..2af9c3e70dbb 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c @@ -138,6 +138,9 @@ static unsigned int decode_timeout_val = 100; u32 again_threshold = 0x40; #endif +/* +#define DUMP_USER_DATA +*/ enum { FRAME_REPEAT_TOP, @@ -163,6 +166,26 @@ static void vmpeg_vf_put(struct vframe_s *, void *); static int vmpeg_vf_states(struct vframe_states *states, void *); static int vmpeg_event_cb(int type, void *data, void *private_data); +struct mmpeg2_userdata_record_t { + struct userdata_meta_info_t meta_info; + u32 rec_start; + u32 rec_len; +}; + +#define USERDATA_FIFO_NUM 256 +#define MAX_FREE_USERDATA_NODES 5 + +struct mmpeg2_userdata_info_t { + struct mmpeg2_userdata_record_t records[USERDATA_FIFO_NUM]; + u8 *data_buf; + u8 *data_buf_end; + u32 buf_len; + u32 read_index; + u32 write_index; + u32 last_wp; +}; +#define MAX_UD_RECORDS 5 + struct vdec_mpeg12_hw_s { spinlock_t lock; struct platform_device *platform_dev; @@ -236,6 +259,26 @@ struct vdec_mpeg12_hw_s { u32 pre_parser_wr_ptr; u8 next_again_flag; #endif + + + struct work_struct userdata_push_work; + struct mutex userdata_mutex; + struct mmpeg2_userdata_info_t userdata_info; + struct mmpeg2_userdata_record_t ud_record[MAX_UD_RECORDS]; + int cur_ud_idx; + u8 *user_data_buffer; + int wait_for_udr_send; + u32 ucode_cc_last_wp; + +#ifdef DUMP_USER_DATA +#define MAX_USER_DATA_SIZE 1572864 + void *user_data_dump_buf; + unsigned char *pdump_buf_cur_start; + int total_len; + int bskip; + int n_userdata_id; + u32 reference[MAX_UD_RECORDS]; +#endif }; static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw); static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw); @@ -262,6 +305,7 @@ unsigned int mpeg12_debug_mask = 0xff; #define PRINT_FRAMEBASE_DATA 0x0400 #define PRINT_FLAG_VDEC_STATUS 0x0800 #define PRINT_FLAG_PARA_DATA 0x1000 +#define PRINT_FLAG_USERDATA_DETAIL 0x2000 @@ -423,35 +467,742 @@ static inline void vmpeg12_save_hw_context(struct vdec_mpeg12_hw_s *hw) debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA, "signal_type = %x", hw->reg_signal_type); } -#if 0 + +static void vmmpeg2_reset_udr_mgr(struct vdec_mpeg12_hw_s *hw) +{ + hw->wait_for_udr_send = 0; + hw->cur_ud_idx = 0; + memset(&hw->ud_record, 0, sizeof(hw->ud_record)); +} + +static void vmmpeg2_crate_userdata_manager( + struct vdec_mpeg12_hw_s *hw, + u8 *userdata_buf, + int buf_len) +{ + if (hw) { + mutex_init(&hw->userdata_mutex); + + memset(&hw->userdata_info, 0, + sizeof(struct mmpeg2_userdata_info_t)); + hw->userdata_info.data_buf = userdata_buf; + hw->userdata_info.buf_len = buf_len; + hw->userdata_info.data_buf_end = userdata_buf + buf_len; + + vmmpeg2_reset_udr_mgr(hw); + } +} + +static void vmmpeg2_destroy_userdata_manager(struct vdec_mpeg12_hw_s *hw) +{ + if (hw) + memset(&hw->userdata_info, + 0, + sizeof(struct mmpeg2_userdata_info_t)); +} + +static void aml_swap_data(uint8_t *user_data, int ud_size) +{ + int swap_blocks, i, j, k, m; + unsigned char c_temp; + + /* swap byte order */ + swap_blocks = ud_size / 8; + for (i = 0; i < swap_blocks; i++) { + j = i * 8; + k = j + 7; + for (m = 0; m < 4; m++) { + c_temp = user_data[j]; + user_data[j++] = user_data[k]; + user_data[k--] = c_temp; + } + } +} + +#ifdef DUMP_USER_DATA +static void push_to_buf(struct vdec_mpeg12_hw_s *hw, + u8 *pdata, + int len, + struct userdata_meta_info_t *pmeta, + u32 reference) +{ + u32 *pLen; + int info_cnt; + u8 *pbuf_end; + + if (!hw->user_data_dump_buf) + return; + + if (hw->bskip) { + pr_info("over size, skip\n"); + return; + } + info_cnt = 0; + pLen = (u32 *)hw->pdump_buf_cur_start; + + *pLen = len; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->duration; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->flags; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts_valid; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + + *pLen = hw->n_userdata_id; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = reference; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + pbuf_end = hw->userdata_info.data_buf_end; + if (pdata + len > pbuf_end) { + int first_section_len; + + first_section_len = pbuf_end - pdata; + memcpy(hw->pdump_buf_cur_start, pdata, first_section_len); + pdata = (u8 *)hw->userdata_info.data_buf; + hw->pdump_buf_cur_start += first_section_len; + memcpy(hw->pdump_buf_cur_start, pdata, len - first_section_len); + hw->pdump_buf_cur_start += len - first_section_len; + } else { + memcpy(hw->pdump_buf_cur_start, pdata, len); + hw->pdump_buf_cur_start += len; + } + + hw->total_len += len + info_cnt * sizeof(u32); + if (hw->total_len >= MAX_USER_DATA_SIZE-4096) + hw->bskip = 1; +} + +static void dump_userdata_info(struct vdec_mpeg12_hw_s *hw, + void *puser_data, + int len, + struct userdata_meta_info_t *pmeta, + u32 reference) +{ + u8 *pstart; + + pstart = (u8 *)puser_data; + +#ifdef DUMP_HEAD_INFO_DATA + push_to_buf(hw, pstart, len, pmeta, reference); +#else + push_to_buf(hw, pstart+8, len - 8, pmeta, reference); +#endif +} + + +static void print_data(unsigned char *pdata, + int len, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id, + u32 reference) +{ + int nLeft; + + nLeft = len; + + pr_info("%d len:%d, flag:0x%x, dur:%d, vpts:0x%x, valid:%d, refer:%d\n", + rec_id, len, flag, + duration, vpts, vpts_valid, + reference); + while (nLeft >= 16) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7], + pdata[8], pdata[9], pdata[10], pdata[11], + pdata[12], pdata[13], pdata[14], pdata[15]); + nLeft -= 16; + pdata += 16; + } + + + while (nLeft > 0) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7]); + nLeft -= 8; + pdata += 8; + } +} + +static void dump_data(u8 *pdata, + unsigned int user_data_length, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id, + u32 reference) +{ + unsigned char szBuf[256]; + + + memset(szBuf, 0, 256); + memcpy(szBuf, pdata, user_data_length); + + aml_swap_data(szBuf, user_data_length); + + print_data(szBuf, + user_data_length, + flag, + duration, + vpts, + vpts_valid, + rec_id, + reference); +} + + +static void show_user_data_buf(struct vdec_mpeg12_hw_s *hw) +{ + u8 *pbuf; + int len; + unsigned int flag; + unsigned int duration; + unsigned int vpts; + unsigned int vpts_valid; + int rec_id; + u32 reference; + + pr_info("show user data buf\n"); + pbuf = hw->user_data_dump_buf; + + while (pbuf < hw->pdump_buf_cur_start) { + u32 *pLen; + + pLen = (u32 *)pbuf; + + len = *pLen; + pLen++; + pbuf += sizeof(u32); + + duration = *pLen; + pLen++; + pbuf += sizeof(u32); + + flag = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts_valid = *pLen; + pLen++; + pbuf += sizeof(u32); + + rec_id = *pLen; + pLen++; + pbuf += sizeof(u32); + + reference = *pLen; + pLen++; + pbuf += sizeof(u32); + + + dump_data(pbuf, len, flag, duration, + vpts, vpts_valid, rec_id, reference); + pbuf += len; + msleep(30); + } +} + +static int amvdec_mmpeg12_init_userdata_dump(struct vdec_mpeg12_hw_s *hw) +{ + hw->user_data_dump_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); + if (hw->user_data_dump_buf) + return 1; + else + return 0; +} + +static void amvdec_mmpeg12_uninit_userdata_dump(struct vdec_mpeg12_hw_s *hw) +{ + if (hw->user_data_dump_buf) { + show_user_data_buf(hw); + kfree(hw->user_data_dump_buf); + hw->user_data_dump_buf = NULL; + } +} + +static void reset_user_data_buf(struct vdec_mpeg12_hw_s *hw) +{ + hw->total_len = 0; + hw->pdump_buf_cur_start = hw->user_data_dump_buf; + hw->bskip = 0; + hw->n_userdata_id = 0; +} +#endif + +static void user_data_ready_notify(struct vdec_mpeg12_hw_s *hw, + u32 pts, u32 pts_valid) +{ + struct mmpeg2_userdata_record_t *p_userdata_rec; + int i; + + if (hw->wait_for_udr_send) { + for (i = 0; i < hw->cur_ud_idx; i++) { + mutex_lock(&hw->userdata_mutex); + + + p_userdata_rec = hw->userdata_info.records + + hw->userdata_info.write_index; + + hw->ud_record[i].meta_info.vpts_valid = pts_valid; + hw->ud_record[i].meta_info.vpts = pts; + + *p_userdata_rec = hw->ud_record[i]; +#ifdef DUMP_USER_DATA + dump_userdata_info(hw, + hw->userdata_info.data_buf + p_userdata_rec->rec_start, + p_userdata_rec->rec_len, + &p_userdata_rec->meta_info, + hw->reference[i]); + hw->n_userdata_id++; +#endif +/* + pr_info("notify: rec_start:%d, rec_len:%d, wi:%d, reference:%d\n", + p_userdata_rec->rec_start, + p_userdata_rec->rec_len, + hw->userdata_info.write_index, + hw->reference[i]); +*/ + hw->userdata_info.write_index++; + if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) + hw->userdata_info.write_index = 0; + + mutex_unlock(&hw->userdata_mutex); + + + vdec_wakeup_userdata_poll(hw_to_vdec(hw)); + } + hw->wait_for_udr_send = 0; + hw->cur_ud_idx = 0; + } +} + +static int vmmpeg2_user_data_read(struct vdec_s *vdec, + struct userdata_param_t *puserdata_para) +{ + struct vdec_mpeg12_hw_s *hw = NULL; + int rec_ri, rec_wi; + int rec_len; + u8 *rec_data_start; + u8 *pdest_buf; + struct mmpeg2_userdata_record_t *p_userdata_rec; + u32 data_size; + u32 res; + int copy_ok = 1; + + hw = (struct vdec_mpeg12_hw_s *)vdec->private; + + pdest_buf = puserdata_para->pbuf_addr; + + mutex_lock(&hw->userdata_mutex); + +/* + pr_info("ri = %d, wi = %d\n", + hw->userdata_info.read_index, + hw->userdata_info.write_index); +*/ + rec_ri = hw->userdata_info.read_index; + rec_wi = hw->userdata_info.write_index; + + if (rec_ri == rec_wi) { + mutex_unlock(&hw->userdata_mutex); + return 0; + } + + p_userdata_rec = hw->userdata_info.records + rec_ri; + + rec_len = p_userdata_rec->rec_len; + rec_data_start = p_userdata_rec->rec_start + hw->userdata_info.data_buf; +/* + pr_info("ri:%d, wi:%d, rec_len:%d, rec_start:%d, buf_len:%d\n", + rec_ri, rec_wi, + p_userdata_rec->rec_len, + p_userdata_rec->rec_start, + puserdata_para->buf_len); +*/ + if (rec_len <= puserdata_para->buf_len) { + /* dvb user data buffer is enought to + copy the whole recored. */ + data_size = rec_len; + if (rec_data_start + data_size + > hw->userdata_info.data_buf_end) { + int first_section_len; + + first_section_len = hw->userdata_info.buf_len - + p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p1 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)hw->userdata_info.data_buf, + data_size - first_section_len); + if (res) { + pr_info("p2 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= + data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = + data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p3 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + hw->userdata_info.read_index++; + if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) + hw->userdata_info.read_index = 0; + } + } else { + /* dvb user data buffer is not enought + to copy the whole recored. */ + data_size = puserdata_para->buf_len; + if (rec_data_start + data_size + > hw->userdata_info.data_buf_end) { + int first_section_len; + + first_section_len = hw->userdata_info.buf_len - + p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p4 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + /* first secton copy is ok*/ + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)hw->userdata_info.data_buf, + data_size - first_section_len); + if (res) { + pr_info("p5 read not end res=%d, request=%d\n", + res, + data_size - first_section_len); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= + data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = + data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p6 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + hw->userdata_info.read_index++; + if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) + hw->userdata_info.read_index = 0; + } + + } + puserdata_para->meta_info = p_userdata_rec->meta_info; + + if (hw->userdata_info.read_index <= hw->userdata_info.write_index) + puserdata_para->meta_info.records_in_que = + hw->userdata_info.write_index - + hw->userdata_info.read_index; + else + puserdata_para->meta_info.records_in_que = + hw->userdata_info.write_index + + USERDATA_FIFO_NUM - + hw->userdata_info.read_index; + + puserdata_para->version = (0<<24|0<<16|0<<8|1); + + mutex_unlock(&hw->userdata_mutex); + + + return 1; +} + +static void vmmpeg2_reset_userdata_fifo(struct vdec_s *vdec, int bInit) +{ + struct vdec_mpeg12_hw_s *hw = NULL; + + hw = (struct vdec_mpeg12_hw_s *)vdec->private; + + if (hw) { + mutex_lock(&hw->userdata_mutex); + pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", + bInit, + hw->userdata_info.read_index, + hw->userdata_info.write_index); + hw->userdata_info.read_index = 0; + hw->userdata_info.write_index = 0; + + if (bInit) + hw->userdata_info.last_wp = 0; + mutex_unlock(&hw->userdata_mutex); + } +} + +static void vmmpeg2_wakeup_userdata_poll(struct vdec_s *vdec) +{ + amstream_wakeup_userdata_poll(vdec); +} + +/* +#define PRINT_HEAD_INFO +*/ static void userdata_push_do_work(struct work_struct *work) { u32 reg; - - struct userdata_poc_info_t user_data_poc; -/* struct vdec_mpeg12_hw_s *hw = - container_of(work, struct vdec_mpeg12_hw_s, work);*/ - user_data_poc.poc_info = 0; - user_data_poc.poc_number = 0; - reg = READ_VREG(MREG_BUFFEROUT); - /*pr_info("%s,%d\n",__func__,__LINE__);*/ - - if (!hw->ccbuf_phyAddress_is_remaped_nocache && - hw->ccbuf_phyAddress && - hw->ccbuf_phyAddress_virt) { - codec_mm_dma_flush( - hw->ccbuf_phyAddress_virt, - CCBUF_SIZE, - DMA_FROM_DEVICE); - } - wakeup_userdata_poll(user_data_poc, - reg & 0xffff, - (unsigned long)hw->ccbuf_phyAddress_virt, - CCBUF_SIZE, 0); - - WRITE_VREG(MREG_BUFFEROUT, 0); -} + u8 *pdata; + u8 *psrc_data; + u8 head_info[8]; + struct userdata_meta_info_t meta_info; + u32 wp; + u32 index; + u32 picture_struct; + u32 reference; + u32 picture_type; + u32 temp; + u32 data_length; + u32 data_start; + int i; + u32 offset; + u32 cur_wp; +#ifdef PRINT_HEAD_INFO + u8 *ptype_str; #endif + struct mmpeg2_userdata_record_t *pcur_ud_rec; + + struct vdec_mpeg12_hw_s *hw = container_of(work, + struct vdec_mpeg12_hw_s, userdata_push_work); + + + memset(&meta_info, 0, sizeof(meta_info)); + + meta_info.duration = hw->frame_dur; + + + reg = READ_VREG(AV_SCRATCH_J); + meta_info.flags = ((reg >> 30) << 1); + meta_info.flags |= (VFORMAT_MPEG12 << 3); + /* check top_field_first flag */ + if ((reg >> 28) & 0x1) { + meta_info.flags |= (1 << 10); + meta_info.flags |= (((reg >> 29) & 0x1) << 11); + } + + cur_wp = reg & 0x7fff; + if (cur_wp == hw->ucode_cc_last_wp) { + debug_print(DECODE_ID(hw), 0, + "Null user data package: wp = %d\n", cur_wp); + WRITE_VREG(AV_SCRATCH_J, 0); + return; + } + + if (hw->cur_ud_idx >= MAX_UD_RECORDS) { + debug_print(DECODE_ID(hw), 0, + "UD Records over: %d, skip it\n", MAX_UD_RECORDS); + WRITE_VREG(AV_SCRATCH_J, 0); + return; + } + + if (cur_wp < hw->ucode_cc_last_wp) + hw->ucode_cc_last_wp = 0; + + offset = READ_VREG(AV_SCRATCH_I); + + codec_mm_dma_flush( + hw->ccbuf_phyAddress_virt, + CCBUF_SIZE, + DMA_FROM_DEVICE); + + mutex_lock(&hw->userdata_mutex); + if (hw->ccbuf_phyAddress_virt) { + pdata = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp; + memcpy(head_info, pdata, 8); + } else + memset(head_info, 0, 8); + mutex_unlock(&hw->userdata_mutex); + aml_swap_data(head_info, 8); + + wp = (head_info[0] << 8 | head_info[1]); + index = (head_info[2] << 8 | head_info[3]); + + picture_struct = (head_info[6] << 8 | head_info[7]); + temp = (head_info[4] << 8 | head_info[5]); + reference = temp & 0x3FF; + picture_type = (temp >> 10) & 0x7; + + if (debug_enable & PRINT_FLAG_USERDATA_DETAIL) + pr_info("index:%d, wp:%d, ref:%d, type:%d, struct:0x%x, u_last_wp:0x%x\n", + index, wp, reference, + picture_type, picture_struct, + hw->ucode_cc_last_wp); + + switch (picture_type) { + case 1: + /* pr_info("I type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (1<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " I"; +#endif + break; + case 2: + /* pr_info("P type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (2<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " P"; +#endif + break; + case 3: + /* pr_info("B type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (3<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " B"; +#endif + break; + case 4: + /* pr_info("D type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (4<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " D"; +#endif + break; + default: + /* pr_info("Unknown type:0x%x, pos:%d\n", + pheader->picture_coding_type, + (meta_info.flags>>1)&0x3); */ +#ifdef PRINT_HEAD_INFO + ptype_str = " U"; +#endif + break; + } +#ifdef PRINT_HEAD_INFO + pr_info("ref:%d, type:%s, ext:%d, first:%d, data_length:%d\n", + reference, ptype_str, + (reg >> 30), + (reg >> 28)&0x3, + reg & 0xffff); +#endif + data_length = cur_wp - hw->ucode_cc_last_wp; + data_start = reg & 0xffff; + psrc_data = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp; + + pdata = hw->userdata_info.data_buf + hw->userdata_info.last_wp; + for (i = 0; i < data_length; i++) { + *pdata++ = *psrc_data++; + if (pdata >= hw->userdata_info.data_buf_end) + pdata = hw->userdata_info.data_buf; + } + + pcur_ud_rec = hw->ud_record + hw->cur_ud_idx; + + pcur_ud_rec->meta_info = meta_info; + pcur_ud_rec->rec_start = hw->userdata_info.last_wp; + pcur_ud_rec->rec_len = data_length; + + hw->userdata_info.last_wp += data_length; + if (hw->userdata_info.last_wp >= USER_DATA_SIZE) + hw->userdata_info.last_wp -= USER_DATA_SIZE; + + hw->wait_for_udr_send = 1; + + hw->ucode_cc_last_wp = cur_wp; + + if (debug_enable & PRINT_FLAG_USERDATA_DETAIL) + pr_info("cur_wp:%d, rec_start:%d, rec_len:%d\n", + cur_wp, + pcur_ud_rec->rec_start, + pcur_ud_rec->rec_len); + +#ifdef DUMP_USER_DATA + hw->reference[hw->cur_ud_idx] = reference; +#endif + + hw->cur_ud_idx++; + WRITE_VREG(AV_SCRATCH_J, 0); +} + + static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) { u32 reg, info, seqinfo, offset, pts, pts_valid = 0; @@ -475,13 +1226,15 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) return IRQ_HANDLED; } + reg = READ_VREG(AV_SCRATCH_J); + if (reg & (1<<16)) { + vdec_schedule_work(&hw->userdata_push_work); + return IRQ_HANDLED; + } + reg = READ_VREG(MREG_BUFFEROUT); - if ((reg >> 16) == 0xfe) { - /*pr_info("%s,%d\n",__func__,__LINE__);*/ - /*vdec_schedule_work(&userdata_push_work);*/ - WRITE_VREG(MREG_BUFFEROUT, 0); - } else if (reg == 2) { + if (reg == 2) { /*timeout when decoding next frame*/ debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, @@ -638,6 +1391,8 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) pts = hw->pts[index]; pts_us64 = hw->pts64[index]; + user_data_ready_notify(hw, pts, pts_valid); + if ((hw->first_i_frame_ready == 0) && ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) && ((info & PICINFO_ERROR) == 0)) @@ -1179,8 +1934,25 @@ static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw) } if (i == (MAX_BMMU_BUFFER_NUM - 1)) { + if (hw->ccbuf_phyAddress_is_remaped_nocache) + codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); + hw->ccbuf_phyAddress_virt = NULL; + hw->ccbuf_phyAddress = 0; + hw->ccbuf_phyAddress_is_remaped_nocache = 0; + hw->buf_start = decbuf_start; hw->ccbuf_phyAddress = hw->buf_start + CTX_CCBUF_OFFSET; + hw->ccbuf_phyAddress_virt + = codec_mm_phys_to_virt( + hw->ccbuf_phyAddress); + if (!hw->ccbuf_phyAddress_virt) { + hw->ccbuf_phyAddress_virt + = codec_mm_vmap( + hw->ccbuf_phyAddress, + CCBUF_SIZE); + hw->ccbuf_phyAddress_is_remaped_nocache = 1; + } + WRITE_VREG(MREG_CO_MV_START, hw->buf_start); } else { if (vdec->parallel_dec == 1) { @@ -1578,9 +2350,24 @@ static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw) fw->len = size; hw->fw = fw; + INIT_WORK(&hw->userdata_push_work, userdata_push_do_work); INIT_WORK(&hw->work, vmpeg12_work); INIT_WORK(&hw->notify_work, vmpeg12_notify_work); + if (NULL == hw->user_data_buffer) { + hw->user_data_buffer = kmalloc(USER_DATA_SIZE, + GFP_KERNEL); + if (!hw->user_data_buffer) { + pr_info("%s: Can not allocate user_data_buffer\n", + __func__); + return -1; + } + } + + vmmpeg2_crate_userdata_manager(hw, + hw->user_data_buffer, + USER_DATA_SIZE); + amvdec_enable(); init_timer(&hw->check_timer); @@ -1836,6 +2623,11 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev) pdata->irq_handler = vmpeg12_isr; pdata->threaded_irq_handler = vmpeg12_isr_thread_fn; pdata->dump_state = vmpeg2_dump_state; + + pdata->user_data_read = vmmpeg2_user_data_read; + pdata->reset_userdata_fifo = vmmpeg2_reset_userdata_fifo; + pdata->wakeup_userdata_poll = vmmpeg2_wakeup_userdata_poll; + if (pdata->use_vfm_path) { snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, VFM_DEC_PROVIDER_NAME); @@ -1871,6 +2663,10 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev) vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); } +#ifdef DUMP_USER_DATA + amvdec_mmpeg12_init_userdata_dump(hw); + reset_user_data_buf(hw); +#endif /*INIT_WORK(&userdata_push_work, userdata_push_do_work);*/ return 0; @@ -1899,7 +2695,7 @@ static int ammvdec_mpeg12_remove(struct platform_device *pdev) del_timer_sync(&hw->check_timer); hw->stat &= ~STAT_TIMER_ARM; } - + cancel_work_sync(&hw->userdata_push_work); cancel_work_sync(&hw->work); cancel_work_sync(&hw->notify_work); @@ -1920,6 +2716,22 @@ static int ammvdec_mpeg12_remove(struct platform_device *pdev) } } + if (hw->ccbuf_phyAddress_is_remaped_nocache) + codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); + hw->ccbuf_phyAddress_virt = NULL; + hw->ccbuf_phyAddress = 0; + hw->ccbuf_phyAddress_is_remaped_nocache = 0; + + if (hw->user_data_buffer != NULL) { + kfree(hw->user_data_buffer); + hw->user_data_buffer = NULL; + } + vmmpeg2_destroy_userdata_manager(hw); + +#ifdef DUMP_USER_DATA + amvdec_mmpeg12_uninit_userdata_dump(hw); +#endif + if (hw->fw) { vfree(hw->fw); hw->fw = NULL; diff --git a/firmware/video/video_ucode.bin b/firmware/video/video_ucode.bin index 61bc150a5f0c750498adc75f24cd7cb036b0c549..823fb25cca3b072b5a47535071f07779216a7b81 100755 GIT binary patch delta 13166 zcmeI2eNYtV9mk(%Z@uU4SndIN_XSRB5D74+2m+~bH80>xD5-ByG=hZ?Upb9c>a?;Z zF(Qt7O60Le#DIFK4g@91Zpl>Lc3NSaYK53|CXF^~jIq8Ym82SzrqAAinc)s@=5{Xo z4>!XsxBJ}l-S6-DeSW{)y%QQrg@)3qqW3UUb?JGa7; zdXC<`c=&R2@u6wq%?(-irrat5rw*J>c|NGw5ZArn(f`cWeYf%E&8o@s&n|6j{>P*X zN98N6_ixzj(1VzVxpUkAUFp6J-gsw zEeCtV<3WqyBi1FQ>7~ESNS%>YvZQpf)e3%it*Ka5p1R?Ml2zrkp)itPP*!T0W?N&i zq**4UWv69jPnuwvXq}MN_krG-`rZOy17LK{!G(P@OYm_f5sGrqqSb*^4e?Y>hf;7F zcNdFC0_=DI?Utagu*6IbD*Exm?aU6ciGML^u+Yv9lTCbr(?FS~7;BT*i^f6?;(f_z z6Za#Pt|$5gE7lXNCZrN9e^i|j2AjCtsDWQ+6S9f-3|c5Zpq@9YRraTNI;*MjvubJf zXPw0egTfSqDw*=3%>&?>*-jSnZA@Snn)W?U;ih5MwzFF3c3IofHPCI#Tr@#dYxc3a z-h-TJZL8P7EL~jjS79oJ(*`fpb^zi$3w3L#!7dqMLg%S#PyT2-M}^wOyI2d?Ut?&O z;MCy@1M2z>uMwXp4^yo5&nf5@nGoiTX*rgX*ktKZ2`V$VQ5FPZY0 zIqEJK{1czU6so%m@v+igDvIK{j`?<~7^9YJe=Sq(El_1m@lU%3en+p)g0)Gs8dsw2 z*J+Yyi*<_gg*r_TTdY$MI}J5)eg=L!wXT*iNv0>&o`8R_<}Z@-SB@f!O^!7o)U0Q{uirD`IqI}{wM z3xOQ{Wl=OqUWVtzz3B5$$ zKUlyWVd>EMy<>j9oCR6=9Ab)DVI|$h)Aw`ecFl5DUY74VF(n+i!7{2={*Zt=PZpc_ z|GH1CI#NKWTQ;FJf+?4d>x`BWDK0_Ago8AGVKVBB7LWlnx?&0r(0z2kmPooE&=0o# zjqEHzd2k;wug2MooIqx-#`ATc3y}IzXgB-=Nga)*GoXoVScBUbp_-(=h^L$QR}eQ- zS)+9%FBau7{A$t=i{i=67jXe2EG18`#jz%#ymz6>$*Q&Z-wa$cMPYe8bfu^oK=04cBe}wr9s;c7j8xXh$VfRR zgt-;?pSrg*=&`LdMq6o&meI74$<=lEF$P>A@eaHo<^pgf8xo35z);C`umU|lgX$f-(vn~~dz<8}N$24G3tfNNQJjLfXU&q0A~ zYQj+rD3lyc_$*6~PDEB>e-l?T!dz*@@9}(AY{4vKgGy(=T-Tz2`IZ)7wsWC6+y~}% z3TB>nFu@4Pu}lH87dT&F%C(+g^4G|coiv`8$cdd4%tSX(LJmo=Q+Rqvo}Gdj;|5d6 zB$2yl(4$DkE(&J28#<8b38oz6o<~md1QQ%5`rUNy9Fn@5g87Wwo6zzDn4o}|Y!u8s z=mr53%ncxzb{jS(GtP9LtjQsB4WD0BDWC|4z$t;BB z3Yc-mvR-P+6fSST`Ga9OPX(4jZ>8>!CI2b;>~}buvNJ}(68zIUmjc=4pkEYFEZ5Tv z>3WD|eJ_^vxSIhkEWd{#l4Bp8?U fE&FxLnup!8Mgeo17GMr_%b{*L)Gcv!U$^`}fhfob delta 13019 zcmeI2dsGzH9mnq-W_Na%h23G7-Akf%wJ0VfbOm4Ni4H~uO@e45M0qGgQXdU2T6@r* zlmTsc_(D;x5jBYE`iu`uXRv8>)Ov)(lVdeWd$ejvPTIy=TVir*Y^=S*06E7U+0&h~ z&L5S3=Ird{e&_eSzt8VJcK99h_#N}gm+efvv;6DYgMYgK?@srAupnjO&#xV8ZGQKc zWqVc}E7*K;TkRoJXU^TrV~os!+;Jx^w^Po}&e_o!jqL+6K41H*!#`Y9Jn4({oU}uw z=l&X-cD5;DQ_Rx`b~gU!mCShS6XV2N9rZ;q3FgW7Hurz;#s||ETzqSSXUp#WO($-> z^yMX~c2D`FqTKRT7nVkxnx8j2`_)tZYW(HH*)`>7-WfG%xp?y3aUCV+vQsXdTwGOr zhiPCq-BAqIPlX% z=hAvB{7T3(fegVVwsUE9Y1G`ViL8MOeK<7s3?r32b=9$%K7>T_Y2Alg%qQ><>NHh_cJh z3EOSqRaT8zXtF`C2yMFfz0K|w-Uzeb>QQgAYg{1x@70Wq@!B z>oU@EjzvQ~Mw*4bjmx5sMmJ8=Hc^IRc=HZlOLcgIwg(oH5%6f#>aT4_DJu8jhumTa zZwY%qyk)m+LWLgr)okzym)zRMIK|udwCn}I6)-LPOV2=Mp~ID*re&H6 zDPAGot!;A=OjR{je~z1Lc*AZIO;Kp3CYplDs}Hgrd4;PkZG)T~q;!$MRn{UME_r`} z-P-mS!J>Yk>B4M{`}Po&y-+me+is5+K8n`nc!=7+kN$?7!ET7wwloM)d{dXWTjO3f zMDfRD*Hu6@&)a6#t^(T=l z2RKw_Wx#Vr-X(6`i&n#@H$v-K3!u~arz~=_Hpnv>pwMChypj7&nY9f{%s$8)rS(cX zCS#yQ8dIk9`57*%M!E0`K3xFWq$0w~O&ZP9iB`DuX=exfn?WI<1Tuu6Z1}CjXXJe-*v2lBq z=XsLijo?LWIfNe1nbG~Y$%|+(ILlfyj%Uo=0Si;Pi01yCW8FuSrdi!>W-OwmQCU`o znoEQEw?O z_W{o^6khiln@Mq7@YUDYQ3gAC#6h@VEy|AI&H>!Glifh^M{!a!JAvYM;dSd!3nkUy z3G2}W3;zqoI+gg(m*RCTXd3)6zS@F*2It|~N6`RtkrFIdgr~m6w&3CKpj7w*F4=%` z-O{eEF_bDKTL#||DLY(60UG-%+5WHS-wAeT}F90^D&Nxhei7@y>DdA&t+UMu#B~D}Ia0>3R?3gc~w*xASIw+HgZ= z?(cdq7w={x%stHQCCp{0GY6dF*4Jg`x>*Xw9Je-*Ij#d2?I&hl#>e*)<_0OO@M(C+ z0m8*ioOysS=TMmAldpsAfdcm77_g5vcRb9lX0%`)LnW|^%;E{$vjiQ5;* z^%GEpv9b3S3%6s#TT>pOT`g7n?gU9P)p&co p{wPs6r#0*lA3%PUYrn?Vic*4DPKt_(