/* * drivers/media/video/samsung/mfc50/mfc_opr.c * * C file for Samsung MFC (Multi Function Codec - FIMV) driver * * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics * http://www.samsungsemi.com/ * * Change Logs * 2009.09.14 - Beautify source code. (Key Young, Park) * 2009.09.21 - Implement clock & power gating. * including suspend & resume fuction. (Key Young, Park) * 2009.09.23 - Use TILE mode encoding / Move MFC reserved memory * before FIMC reserved memory. (Key Young, Park) * 2009.09.24 - Minor patch. (Key Young, Park) * 2009.10.08 - Apply 9/30 firmware(Key Young, Park) * 2009.10.13 - Change wait_for_done (Key Young, Park) * 2009.10.17 - Add error handling routine for buffer allocation (Key Young, Park) * 2009.10.22 - Change codec name VC1AP_DEC -> VC1_DEC (Key Young, Park) * 2009.10.27 - Update firmware (2009.10.15) (Key Young, Park) * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park) * 2009.11.04 - remove mfc_common.[ch] * seperate buffer alloc & set (Key Young, Park) * 2009.11.06 - Apply common MFC API (Key Young, Park) * 2009.11.06 - memset shared_memory (Key Young, Park) * 2009.11.09 - implement packed PB (Key Young, Park) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */ #include #include #include #include #include #include #include #include #include #include #include "mfc_opr.h" #include "mfc_logmsg.h" #include "mfc_memory.h" #include "mfc_buffer_manager.h" #include "mfc_interface.h" #include "mfc_shared_mem.h" #include "mfc_intr.h" /* DEBUG_MAKE_RAW is option to dump input stream data of MFC.*/ #define DEBUG_MAKE_RAW 0 /* Making Dec/Enc Debugging Files */ #define ENABLE_DEBUG_MFC_INIT 0 #define ENABLE_MFC_REGISTER_DEBUG 0 /* 0: Disable 1: Enable */ #define ENABLE_ENC_MB 1 #define ENABLE_CHECK_START_CODE 1 #define ENABLE_CHECK_NULL_STREAM 1 #define ENABLE_CHECK_STREAM_SIZE 1 #define ENABLE_CHECK_SEQ_HEADER 0 #if DEBUG_MAKE_RAW #define ENABLE_DEBUG_DEC_EXE_INTR_ERR 1 /* You must make the "dec_in" folder in data folder.*/ #define ENABLE_DEBUG_DEC_EXE_INTR_OK 1 /* Make log about Normal Interrupts.*/ #define ENABLE_DEBUG_ENC_EXE_INTR_ERR 1 /* You must make the "enc_in" folder in data folder.*/ #endif #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR #define ENABLE_DEBUG_DEC_EXE_PARSER_ERR 1 /* Firstly, Set ENABLE_DEBUG_DEC_EXE_INTR_ERR is "1". */ #endif #endif #define WRITEL_SHARED_MEM(data, address) \ do { \ writel(data, address); \ dmac_flush_range((void *)address, (void *)(address + 4)); \ } while (0) #if DEBUG_MAKE_RAW #include #include #include #include #include #include #include #include #endif static void mfc_backup_context(struct mfc_inst_ctx *mfc_ctx); static void mfc_restore_context(struct mfc_inst_ctx *mfc_ctx); static void mfc_set_encode_init_param(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args); static int mfc_get_inst_no(struct mfc_inst_ctx *mfc_ctx, unsigned int context_addr, int context_size); static enum mfc_error_code mfc_encode_header(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args); static enum mfc_error_code mfc_decode_one_frame(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, unsigned int *consumed_strm_size); static void mfc_set_codec_buffer(struct mfc_inst_ctx *mfc_ctx); static void mfc_set_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx); static void mfc_set_dec_stream_buffer(struct mfc_inst_ctx *mfc_ctx, int buf_addr, unsigned int buf_size); static void mfc_set_enc_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args); static enum mfc_error_code mfc_alloc_codec_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args); static enum mfc_error_code mfc_alloc_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args); static enum mfc_error_code mfc_alloc_context_buffer(struct mfc_inst_ctx *mfc_ctx, unsigned int mapped_addr, unsigned int *context_addr, int *size); static enum mfc_error_code mfc_alloc_stream_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args); static int CheckMPEG4StartCode(unsigned char *src_mem, unsigned int remainSize); static int CheckDecStartCode(unsigned char *src_mem, unsigned int nstreamSize, enum ssbsip_mfc_codec_type nCodecType); static int CheckNullStream(unsigned char *src_mem, unsigned int streamSize); static int mfc_mem_inst_no[MFC_MAX_INSTANCE_NUM]; static bool mCheckType; /* * Debugging Functions Definition * tile_to_linear_4x2(..) * calculate_seq_size(..) * printk_mfc_init_info(..) */ #if DEBUG_MAKE_RAW static int mframe_cnt; static int mImgWidth; static int mImgHight; static void copy16(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, int mm, int nn); static void write_file(char *filename, unsigned char *data, unsigned int nSize); static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos); static void tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size); #endif #if ENABLE_CHECK_SEQ_HEADER static int calculate_seq_size(mfc_args *args); #endif #if ENABLE_DEBUG_MFC_INIT void printk_mfc_init_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_args *args); #endif #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR void printk_mfc_dec_exe_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg); void makefile_mfc_dec_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, int nReturnErrCode); void makefile_mfc_decinit_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_init_arg *decinit_arg, int nReturnErrCode); static unsigned int mcontext_addr; static int mcontext_size; static int mIsDangerError; #endif #endif #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_ENC_EXE_INTR_ERR void makefile_mfc_enc_err_info(struct mfc_enc_exe_arg *enc_arg); #endif #endif #if ENABLE_MFC_REGISTER_DEBUG void mfc_fw_debug(mfc_wait_done_type command); #endif #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_ENC_EXE_INTR_ERR static unsigned char pResLinearbuf[1280*720*3/2]; #endif #endif #define MC_STATUS_TIMEOUT 1000 /* ms */ bool mfc_cmd_reset(void) { unsigned int mc_status; unsigned long timeo = jiffies; timeo += msecs_to_jiffies(MC_STATUS_TIMEOUT); /* Stop procedure */ WRITEL(0x3f6, MFC_SW_RESET); /* reset RISC */ WRITEL(0x3e2, MFC_SW_RESET); /* All reset except for MC */ mdelay(10); /* Check MC status */ do { mc_status = (READL(MFC_MC_STATUS) & 0x3); if (mc_status == 0) break; schedule_timeout_uninterruptible(1); } while (time_before(jiffies, timeo)); if (mc_status != 0) return false; WRITEL(0x0, MFC_SW_RESET); WRITEL(0x3fe, MFC_SW_RESET); return true; } static bool mfc_cmd_host2risc(enum mfc_facade_cmd cmd, int arg1, int arg2, int arg3, int arg4) { enum mfc_facade_cmd cur_cmd = 0; unsigned long timeo = jiffies; timeo += 20; /* waiting for 100ms */ /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */ while (time_before(jiffies, timeo)) { cur_cmd = READL(MFC_HOST2RISC_COMMAND); if (cur_cmd == H2R_CMD_EMPTY) break; msleep_interruptible(2); } if (cur_cmd != H2R_CMD_EMPTY) return false; WRITEL(arg1, MFC_HOST2RISC_ARG1); WRITEL(arg2, MFC_HOST2RISC_ARG2); WRITEL(arg3, MFC_HOST2RISC_ARG3); WRITEL(arg4, MFC_HOST2RISC_ARG4); WRITEL(cmd, MFC_HOST2RISC_COMMAND); return true; } static void mfc_backup_context(struct mfc_inst_ctx *mfc_ctx) { } static void mfc_restore_context(struct mfc_inst_ctx *mfc_ctx) { } static void mfc_set_dec_stream_buffer(struct mfc_inst_ctx *mfc_ctx, int buf_addr, unsigned int buf_size) { unsigned int port0_base_paddr; mfc_debug_L0("inst_no : %d, buf_addr : 0x%08x, buf_size : 0x%08x\n", mfc_ctx->InstNo, buf_addr, buf_size); if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) { unsigned char *in_vir; in_vir = phys_to_virt(buf_addr); dma_map_single(NULL, in_vir, buf_size, DMA_TO_DEVICE); } port0_base_paddr = mfc_port0_base_paddr; /* release buffer */ WRITEL(0xffffffff, MFC_SI_CH0_RELEASE_BUFFER); /* Set stream & desc buffer */ WRITEL((buf_addr - port0_base_paddr) >> 11, MFC_SI_CH0_ES_ADDR); WRITEL(buf_size, MFC_SI_CH0_ES_DEC_UNIT_SIZE); WRITEL(CPB_BUF_SIZE, MFC_SI_CH0_CPB_SIZE); WRITEL((mfc_ctx->desc_buff_paddr - port0_base_paddr) >> 11, MFC_SI_CH0_DESC_ADDR); WRITEL(DESC_BUF_SIZE, MFC_SI_CH0_DESC_SIZE); mfc_debug_L0("stream_paddr: 0x%08x, desc_paddr: 0x%08x\n", buf_addr, buf_addr + CPB_BUF_SIZE); } static enum mfc_error_code mfc_alloc_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { struct mfc_dec_init_arg *init_arg; enum mfc_error_code ret_code; union mfc_args local_param; struct mfc_frame_buf_arg buf_size; unsigned int luma_size, chroma_size; unsigned int luma_plane_sz, chroma_plane_sz, mv_plane_sz; init_arg = (struct mfc_dec_init_arg *)args; /* width : 128B align, height : 32B align, size: 8KB align */ luma_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height); luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz); chroma_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height / 2); chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz); mv_plane_sz = 0; buf_size.luma = luma_plane_sz; buf_size.chroma = chroma_plane_sz; if (mfc_ctx->MfcCodecType == H264_DEC) { /* width : 128B align, height : 32B align, size: 8KB align */ mv_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height / 4); mv_plane_sz = ALIGN_TO_8KB(mv_plane_sz); buf_size.luma += mv_plane_sz; } mfc_ctx->shared_mem.allocated_luma_dpb_size = luma_plane_sz; mfc_ctx->shared_mem.allocated_chroma_dpb_size = chroma_plane_sz; mfc_ctx->shared_mem.allocated_mv_size = mv_plane_sz; luma_size = buf_size.luma * mfc_ctx->totalDPBCnt; chroma_size = buf_size.chroma * mfc_ctx->totalDPBCnt; /* * Allocate chroma & (Mv in case of H264) buf */ init_arg->out_frame_buf_size.chroma = chroma_size; memset(&local_param, 0, sizeof(local_param)); local_param.mem_alloc.buff_size = chroma_size; local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr; ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0); if (ret_code < 0) return ret_code; init_arg->out_u_addr.chroma = local_param.mem_alloc.out_uaddr; init_arg->out_p_addr.chroma = local_param.mem_alloc.out_paddr; /* * Allocate luma buf */ init_arg->out_frame_buf_size.luma = luma_size; memset(&local_param, 0, sizeof(local_param)); local_param.mem_alloc.buff_size = luma_size; local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr; ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1); if (ret_code < 0) return ret_code; init_arg->out_u_addr.luma = local_param.mem_alloc.out_uaddr; init_arg->out_p_addr.luma = local_param.mem_alloc.out_paddr; mfc_ctx->dec_dpb_buff_paddr = init_arg->out_p_addr; return MFCINST_RET_OK; } static void mfc_set_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx) { unsigned int port0_base_paddr, port1_base_paddr, i; struct mfc_frame_buf_arg dpb_buff_addr; unsigned int luma_plane_sz, chroma_plane_sz, mv_plane_sz; dpb_buff_addr = mfc_ctx->dec_dpb_buff_paddr; port0_base_paddr = mfc_port0_base_paddr; port1_base_paddr = mfc_port1_base_paddr; luma_plane_sz = mfc_ctx->shared_mem.allocated_luma_dpb_size; chroma_plane_sz = mfc_ctx->shared_mem.allocated_chroma_dpb_size; mv_plane_sz = mfc_ctx->shared_mem.allocated_mv_size; mfc_debug("luma_buf_addr start : 0x%08x luma_buf_size : %d\n", dpb_buff_addr.luma, (luma_plane_sz + mv_plane_sz)); mfc_debug("chroma_buf_addr start : 0x%08x chroma_buf_size : %d\n", dpb_buff_addr.chroma, chroma_plane_sz); if (mfc_ctx->MfcCodecType == H264_DEC) { for (i = 0; i < mfc_ctx->totalDPBCnt; i++) { mfc_debug("DPB[%d] luma_buf_addr : 0x%08x luma_buf_size : %d\n", i, dpb_buff_addr.luma, luma_plane_sz); mfc_debug("DPB[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, dpb_buff_addr.chroma, chroma_plane_sz); mfc_debug("DPB[%d] mv_buf_addr : 0x%08x mv_plane_sz : %d\n", i, dpb_buff_addr.luma + luma_plane_sz, mv_plane_sz); /* set Luma address */ WRITEL((dpb_buff_addr.luma - port1_base_paddr) >> 11, MFC_H264DEC_LUMA + (4 * i)); WRITEL((dpb_buff_addr.luma + luma_plane_sz - port1_base_paddr) >> 11, MFC_H264DEC_MV + (4 * i)); dpb_buff_addr.luma += (luma_plane_sz + mv_plane_sz); /* set Chroma address & set MV address */ WRITEL((dpb_buff_addr.chroma - port0_base_paddr) >> 11, MFC_H264DEC_CHROMA + (4 * i)); dpb_buff_addr.chroma += chroma_plane_sz; } } else { for (i = 0; i < mfc_ctx->totalDPBCnt; i++) { mfc_debug("DPB[%d] luma_buf_addr : 0x%08x luma_buf_size : %d\n", i, dpb_buff_addr.luma, luma_plane_sz); mfc_debug("DPB[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, dpb_buff_addr.chroma, chroma_plane_sz); /* set Luma address */ WRITEL((dpb_buff_addr.luma - port1_base_paddr) >> 11, MFC_DEC_LUMA + (4 * i)); dpb_buff_addr.luma += luma_plane_sz; /* set Chroma address */ WRITEL((dpb_buff_addr.chroma - port0_base_paddr) >> 11, MFC_DEC_CHROMA + (4 * i)); dpb_buff_addr.chroma += chroma_plane_sz; } } mfc_debug("luma_buf_addr end : 0x%08x\n", dpb_buff_addr.luma); mfc_debug("chroma_buf_addr end : 0x%08x\n", dpb_buff_addr.chroma); } /* Allocate buffers for encoder */ static enum mfc_error_code mfc_alloc_stream_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { struct mfc_enc_init_mpeg4_arg *init_arg; union mfc_args local_param; unsigned int luma_plane_sz, chroma_plane_sz; enum mfc_error_code ret_code = MFCINST_RET_OK; struct mfc_frame_buf_arg buf_size; init_arg = (struct mfc_enc_init_mpeg4_arg *)args; /* width : 128B align, height : 32B align, size: 8KB align */ luma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height); luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz); chroma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height / 2); chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz); buf_size.luma = luma_plane_sz; buf_size.chroma = chroma_plane_sz; /* * Allocate stream ref Y0, Y1 buf */ init_arg->out_buf_size.strm_ref_y = STREAM_BUF_SIZE + (buf_size.luma * 2); memset(&local_param, 0, sizeof(local_param)); local_param.mem_alloc.buff_size = init_arg->out_buf_size.strm_ref_y; local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr; ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0); if (ret_code < 0) return ret_code; init_arg->out_u_addr.strm_ref_y = local_param.mem_alloc.out_uaddr; init_arg->out_p_addr.strm_ref_y = local_param.mem_alloc.out_paddr; /* * Allocate ref C0, C1, Y2, C2, Y3, C3 buf XXX : remove MV buffer */ init_arg->out_buf_size.mv_ref_yc = (buf_size.luma * 2) + (buf_size.chroma * 4); memset(&local_param, 0, sizeof(local_param)); local_param.mem_alloc.buff_size = init_arg->out_buf_size.mv_ref_yc; local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr; ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1); if (ret_code < 0) return ret_code; init_arg->out_u_addr.mv_ref_yc = local_param.mem_alloc.out_uaddr; init_arg->out_p_addr.mv_ref_yc = local_param.mem_alloc.out_paddr; return ret_code; } static void mfc_set_enc_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { unsigned int port0_base_paddr, port1_base_paddr, i; struct mfc_strm_ref_buf_arg ref_buf_addr; unsigned int luma_plane_sz, chroma_plane_sz; struct mfc_enc_init_mpeg4_arg *init_arg; init_arg = (struct mfc_enc_init_mpeg4_arg *)args; /* width : 128B align, height : 32B align, size: 8KB align */ luma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height); luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz); chroma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height / 2); chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz); ref_buf_addr = init_arg->out_p_addr; mfc_debug("strm_ref_y_buf_addr : 0x%08x, strm_ref_y_buf_size : %d\n", ref_buf_addr.strm_ref_y, init_arg->out_buf_size.strm_ref_y); mfc_debug("mv_ref_yc_buf_addr : 0x%08x, mv_ref_yc_buf_size : %d\n", ref_buf_addr.mv_ref_yc, init_arg->out_buf_size.mv_ref_yc); port0_base_paddr = mfc_port0_base_paddr; port1_base_paddr = mfc_port1_base_paddr; mfc_debug("stream_buf_addr : 0x%08x\n", ref_buf_addr.strm_ref_y); ref_buf_addr.strm_ref_y += STREAM_BUF_SIZE; /* Set Y0, Y1 ref buffer address */ mfc_debug("REF[0] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.strm_ref_y, luma_plane_sz); WRITEL((ref_buf_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_ENC_DPB_Y0_ADDR); ref_buf_addr.strm_ref_y += luma_plane_sz; mfc_debug("REF[1] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.strm_ref_y, luma_plane_sz); WRITEL((ref_buf_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_ENC_DPB_Y1_ADDR); /* Set Y2, Y3 ref buffer address */ mfc_debug("REF[2] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.mv_ref_yc, luma_plane_sz); WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_Y2_ADDR); ref_buf_addr.mv_ref_yc += luma_plane_sz; mfc_debug("REF[3] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.mv_ref_yc, luma_plane_sz); WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_Y3_ADDR); ref_buf_addr.mv_ref_yc += luma_plane_sz; /* Set C0, C1, C2, C3 ref buffer address */ for (i = 0; i < 4; i++) { mfc_debug("REF[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, ref_buf_addr.mv_ref_yc, chroma_plane_sz); WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_C0_ADDR + (4 * i)); ref_buf_addr.mv_ref_yc += chroma_plane_sz; } } static enum mfc_error_code mfc_alloc_codec_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { struct mfc_dec_init_arg *init_arg; enum mfc_error_code ret_code; union mfc_args local_param; init_arg = (struct mfc_dec_init_arg *)args; memset(&local_param, 0, sizeof(local_param)); if (is_dec_codec(mfc_ctx->MfcCodecType)) local_param.mem_alloc.buff_size = DEC_CODEC_BUF_SIZE + SHARED_BUF_SIZE; else local_param.mem_alloc.buff_size = ENC_CODEC_BUF_SIZE + SHARED_BUF_SIZE; local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr; ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0); if (ret_code < 0) return ret_code; mfc_ctx->codec_buff_paddr = local_param.mem_alloc.out_paddr; if (is_dec_codec(mfc_ctx->MfcCodecType)) mfc_ctx->shared_mem_paddr = mfc_ctx->codec_buff_paddr + DEC_CODEC_BUF_SIZE; else mfc_ctx->shared_mem_paddr = mfc_ctx->codec_buff_paddr + ENC_CODEC_BUF_SIZE; mfc_ctx->shared_mem_vaddr = (unsigned int)mfc_get_fw_buff_vaddr() + (mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr); memset((void *)mfc_ctx->shared_mem_vaddr, 0x0, SHARED_MEM_MAX); if (mfc_ctx->MfcCodecType == H264_ENC) { memset(&local_param, 0, sizeof(local_param)); local_param.mem_alloc.buff_size = PRED_BUF_SIZE; local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr; ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1); if (ret_code < 0) return ret_code; mfc_ctx->pred_buff_paddr = local_param.mem_alloc.out_paddr; } return MFCINST_RET_OK; } static void mfc_set_codec_buffer(struct mfc_inst_ctx *mfc_ctx) { unsigned int codec_buff_paddr; unsigned int pred_buff_paddr; unsigned int port0_base_paddr; unsigned int port1_base_paddr; port0_base_paddr = mfc_port0_base_paddr; port1_base_paddr = mfc_port1_base_paddr; codec_buff_paddr = mfc_ctx->codec_buff_paddr; pred_buff_paddr = mfc_ctx->pred_buff_paddr; mfc_debug("inst_no : %d, codec_buf_start: 0x%08x\n", mfc_ctx->InstNo, codec_buff_paddr); switch (mfc_ctx->MfcCodecType) { case H264_DEC: WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_H264DEC_VERT_NB_MV); codec_buff_paddr += (16 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_H264DEC_NB_IP); codec_buff_paddr += (32 << 10); break; case MPEG4_DEC: case H263_DEC: case XVID_DEC: case FIMV1_DEC: case FIMV2_DEC: case FIMV3_DEC: case FIMV4_DEC: WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NB_DCAC); codec_buff_paddr += (16 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPNB_MV); codec_buff_paddr += (68 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_SUB_ANCHOR_MV); codec_buff_paddr += (136 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_OVERLAP_TRANSFORM); codec_buff_paddr += (32 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_STX_PARSER); codec_buff_paddr += (68 << 10); break; case VC1_DEC: case VC1RCV_DEC: WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NB_DCAC); codec_buff_paddr += (16 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPNB_MV); codec_buff_paddr += (68 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_SUB_ANCHOR_MV); codec_buff_paddr += (136 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_OVERLAP_TRANSFORM); codec_buff_paddr += (32 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE3); codec_buff_paddr += (8 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE2); codec_buff_paddr += (8 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE1); codec_buff_paddr += (8 << 10); break; case MPEG1_DEC: case MPEG2_DEC: break; case H264_ENC: case MPEG4_ENC: case H263_ENC: WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPPER_MV_ADDR); codec_buff_paddr += (64 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_DIRECT_COLZERO_FLAG_ADDR); codec_buff_paddr += (64 << 10); WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPPER_INTRA_MD_ADDR); codec_buff_paddr += (64 << 10); if (mfc_ctx->MfcCodecType == H264_ENC) { WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NBOR_INFO_MPENC_ADDR); WRITEL((pred_buff_paddr - port1_base_paddr) >> 11, MFC_UPPER_INTRA_PRED_ADDR); } else { WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_ACDC_COEF_BASE_ADDR); } codec_buff_paddr += (64 << 10); break; default: break; } mfc_debug("inst_no : %d, codec_buf_end : 0x%08x\n", mfc_ctx->InstNo, codec_buff_paddr); } /* This function sets the MFC SFR values according to the input arguments. */ static void mfc_set_encode_init_param(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { unsigned int ms_size; struct mfc_enc_init_mpeg4_arg *enc_init_mpeg4_arg; struct mfc_enc_init_h264_arg *enc_init_h264_arg; enc_init_mpeg4_arg = (struct mfc_enc_init_mpeg4_arg *)args; enc_init_h264_arg = (struct mfc_enc_init_h264_arg *)args; #if DEBUG_MAKE_RAW mImgHight = enc_init_mpeg4_arg->in_height; mImgWidth = enc_init_mpeg4_arg->in_width; #endif mfc_debug("mfc_codec_type : %d\n", mfc_ctx->MfcCodecType); WRITEL(enc_init_mpeg4_arg->in_width, MFC_HSIZE_PX); if (enc_init_mpeg4_arg->in_interlace_mode) WRITEL(enc_init_mpeg4_arg->in_height >> 1, MFC_VSIZE_PX); else WRITEL(enc_init_mpeg4_arg->in_height, MFC_VSIZE_PX); /* H.263 does not support field picture */ WRITEL(enc_init_mpeg4_arg->in_interlace_mode, MFC_PICTURE_STRUCT); WRITEL(0, MFC_ENC_INT_MASK); /* mask interrupt */ WRITEL(1, MFC_STR_BF_MODE_CTRL); /* stream buf frame mode */ WRITEL((1 << 18) | (enc_init_mpeg4_arg->in_BframeNum << 16) | enc_init_mpeg4_arg->in_gop_num, MFC_ENC_PIC_TYPE_CTRL); /* Multi-slice options */ if (enc_init_mpeg4_arg->in_MS_mode) { ms_size = (mfc_ctx->MfcCodecType == H263_ENC) ? 0 : enc_init_mpeg4_arg->in_MS_size; switch (enc_init_mpeg4_arg->in_MS_mode) { case 1: WRITEL(0x1, MFC_ENC_MSLICE_CTRL); WRITEL(ms_size, MFC_ENC_MSLICE_MB); break; case 2: WRITEL(0x3, MFC_ENC_MSLICE_CTRL); WRITEL(ms_size, MFC_ENC_MSLICE_BYTE); break; default: mfc_err("Invalid Multi-slice mode type\n"); break; } } else { WRITEL(0, MFC_ENC_MSLICE_CTRL); } /* Set circular intra refresh MB count */ WRITEL(enc_init_mpeg4_arg->in_mb_refresh, MFC_ENC_CIR_CTRL); if (enc_init_mpeg4_arg->in_frame_map == 1) WRITEL(MEM_STRUCT_TILE_ENC, MFC_ENC_MAP_FOR_CUR); else WRITEL(MEM_STRUCT_LINEAR, MFC_ENC_MAP_FOR_CUR); /* Set padding control */ WRITEL((enc_init_mpeg4_arg->in_pad_ctrl_on << 31) | (enc_init_mpeg4_arg->in_cr_pad_val << 16) | (enc_init_mpeg4_arg->in_cb_pad_val << 8) | (enc_init_mpeg4_arg->in_luma_pad_val << 0), MFC_ENC_PADDING_CTRL); /* Set Rate Control */ if (enc_init_mpeg4_arg->in_RC_frm_enable) { WRITEL(enc_init_mpeg4_arg->in_RC_framerate, MFC_RC_FRAME_RATE); WRITEL(enc_init_mpeg4_arg->in_RC_bitrate, MFC_RC_BIT_RATE); WRITEL(enc_init_mpeg4_arg->in_RC_rpara, MFC_RC_RPARA); } WRITEL(enc_init_mpeg4_arg->in_RC_qbound, MFC_RC_QBOUND); switch (mfc_ctx->MfcCodecType) { case H264_ENC: WRITEL(enc_init_h264_arg->in_profile_level, MFC_PROFILE); WRITEL(enc_init_h264_arg->in_transform8x8_mode, MFC_H264_ENC_TRANS_8X8_FLAG); WRITEL(enc_init_h264_arg->in_deblock_filt, MFC_LF_CONTROL); WRITEL(((enc_init_h264_arg->in_deblock_alpha_C0 * 2) & 0x1f), MFC_LF_ALPHA_OFF); WRITEL(((enc_init_h264_arg->in_deblock_beta * 2) & 0x1f), MFC_LF_BETA_OFF); WRITEL(1, MFC_EDFU_SF_EPB_ON_CTRL); /* Auto EPB insertion on, only for h264 */ /* if in_RC_mb_enable is '1' */ #if ENABLE_ENC_MB if (enc_init_h264_arg->in_RC_frm_enable != 1) enc_init_h264_arg->in_RC_frm_enable = 1; if (enc_init_h264_arg->in_RC_mb_enable != 1) enc_init_h264_arg->in_RC_mb_enable = 1; #endif WRITEL((enc_init_h264_arg->in_RC_frm_enable << 9) | (enc_init_h264_arg->in_RC_mb_enable << 8) | (enc_init_h264_arg->in_frame_qp & 0x3f), MFC_RC_CONFIG); if (enc_init_h264_arg->in_RC_mb_enable) { WRITEL((enc_init_h264_arg->in_RC_mb_dark_disable << 3)| (enc_init_h264_arg->in_RC_mb_smooth_disable << 2)| (enc_init_h264_arg->in_RC_mb_static_disable << 1)| (enc_init_h264_arg->in_RC_mb_activity_disable << 0), MFC_RC_MB_CTRL); } WRITEL((enc_init_h264_arg->in_symbolmode & 0x1), MFC_H264_ENC_ENTRP_MODE); if (enc_init_h264_arg->in_reference_num > 2) enc_init_h264_arg->in_reference_num = 2; if (enc_init_h264_arg->in_ref_num_p > enc_init_h264_arg->in_reference_num) enc_init_h264_arg->in_ref_num_p = enc_init_h264_arg->in_reference_num; WRITEL((enc_init_h264_arg->in_ref_num_p << 5) | (enc_init_h264_arg->in_reference_num), MFC_H264_ENC_NUM_OF_REF); WRITEL(enc_init_h264_arg->in_md_interweight_pps, MFC_H264_ENC_MDINTER_WEIGHT); WRITEL(enc_init_h264_arg->in_md_intraweight_pps, MFC_H264_ENC_MDINTRA_WEIGHT); break; case MPEG4_ENC: WRITEL(enc_init_mpeg4_arg->in_profile_level, MFC_PROFILE); WRITEL((enc_init_mpeg4_arg->in_RC_frm_enable << 9) | (enc_init_mpeg4_arg->in_frame_qp & 0x3f), MFC_RC_CONFIG); WRITEL(enc_init_mpeg4_arg->in_qpelME_enable, MFC_MPEG4_ENC_QUART_PXL); if (enc_init_mpeg4_arg->in_time_increament_res) { mfc_ctx->shared_mem.vop_timing = (1 << 31) | (enc_init_mpeg4_arg->in_time_increament_res << 16) | (enc_init_mpeg4_arg->in_time_vop_time_increament); } break; case H263_ENC: WRITEL(0x20, MFC_PROFILE); WRITEL((enc_init_mpeg4_arg->in_RC_frm_enable << 9) | (enc_init_mpeg4_arg->in_frame_qp & 0x3f), MFC_RC_CONFIG); break; default: mfc_err("Invalid MFC codec type\n"); } } int mfc_load_firmware(const unsigned char *data, size_t size) { volatile unsigned char *fw_virbuf; mfc_debug("mfc_load_firmware : MFC F/W Loading Start.................\n"); fw_virbuf = mfc_get_fw_buff_vaddr(); memset((void *)fw_virbuf, 0, MFC_FW_MAX_SIZE); invalidate_kernel_vmap_range((void *)data, size); memcpy((void *)fw_virbuf, data, size); flush_kernel_vmap_range((void *)fw_virbuf, size); mfc_debug("mfc_load_firmware : MFC F/W Loading Stop.................(fw_virbuf: 0x%08x)\n", fw_virbuf); return 0; } enum mfc_error_code mfc_init_hw() { int fw_buf_size; unsigned int fw_version; unsigned int mc_status; unsigned long idcode; int nIntrRet = 0; mfc_debug("mfc_init_hw++\n"); /* * 0-1. Check Type */ idcode = readl(S5P_VA_CHIPID); if ((idcode & 0x0F) == 0x02) mCheckType = false; else mCheckType = true; /* * 1. MFC reset */ do { mc_status = READL(MFC_MC_STATUS); } while (mc_status != 0); if (mfc_cmd_reset() == false) { mfc_err("MFCINST_ERR_INIT_FAIL\n"); return MFCINST_ERR_INIT_FAIL; } /* * 2. Set DRAM base Addr */ WRITEL(mfc_port0_base_paddr, MFC_MC_DRAMBASE_ADDR_A); WRITEL(mfc_port1_base_paddr, MFC_MC_DRAMBASE_ADDR_B); WRITEL(1, MFC_NUM_MASTER); /* * 3. Initialize registers of stream I/F for decoder */ WRITEL(0xffff, MFC_SI_CH0_INST_ID); WRITEL(0xffff, MFC_SI_CH1_INST_ID); WRITEL(0, MFC_RISC2HOST_COMMAND); WRITEL(0, MFC_HOST2RISC_COMMAND); /* * 4. Release reset signal to the RISC. */ WRITEL(0x3ff, MFC_SW_RESET); nIntrRet = mfc_wait_for_done(R2H_CMD_FW_STATUS_RET); if (nIntrRet != R2H_CMD_FW_STATUS_RET) { /* * 4-1. MFC FW downloading */ mfc_err("MFCINST_ERR_FW_LOAD_MFC_SW_RESET_FAIL............(Ret = %d)", nIntrRet); mfc_err("MFCINST_ERR_FW_LOAD_FAIL\n"); return MFCINST_ERR_FW_LOAD_FAIL; } /* * 5. Initialize firmware */ fw_buf_size = MFC_FW_MAX_SIZE; if (mfc_cmd_host2risc(H2R_CMD_SYS_INIT, fw_buf_size, 0, 0, 0) == false) { mfc_err("R2H_CMD_SYS_INIT FAIL\n"); return MFCINST_ERR_FW_INIT_FAIL; } if (mfc_wait_for_done(R2H_CMD_SYS_INIT_RET) != R2H_CMD_SYS_INIT_RET) { mfc_err("R2H_CMD_SYS_INIT_RET FAIL\n"); return MFCINST_ERR_FW_INIT_FAIL; } fw_version = READL(MFC_FW_VERSION); mfc_debug("MFC FW version : %02xyy, %02xmm, %02xdd\n", (fw_version >> 16) & 0xff, (fw_version >> 8) & 0xff, fw_version & 0xff); mfc_debug("DRAM PORT0 BASE ADDRESS: 0x%08x\n", READL(MFC_MC_DRAMBASE_ADDR_A)); mfc_debug("DRAM PORT1 BASE ADDRESS: 0x%08x\n", READL(MFC_MC_DRAMBASE_ADDR_B)); mfc_debug("mfc_init_hw-\n"); return MFCINST_RET_OK; } static unsigned int mfc_get_codec_arg(enum ssbsip_mfc_codec_type codec_type) { unsigned int codec_no = 99; switch (codec_type) { case H264_DEC: codec_no = 0; break; case VC1_DEC: codec_no = 1; break; case MPEG4_DEC: case XVID_DEC: codec_no = 2; break; case MPEG1_DEC: case MPEG2_DEC: codec_no = 3; break; case H263_DEC: codec_no = 4; break; case VC1RCV_DEC: codec_no = 5; break; case FIMV1_DEC: codec_no = 6; break; case FIMV2_DEC: codec_no = 7; break; case FIMV3_DEC: codec_no = 8; break; case FIMV4_DEC: codec_no = 9; break; case H264_ENC: codec_no = 16; break; case MPEG4_ENC: codec_no = 17; break; case H263_ENC: codec_no = 18; break; default: break; } return codec_no; } static int mfc_get_inst_no(struct mfc_inst_ctx *mfc_ctx, unsigned int context_addr, int context_size) { unsigned int codec_no; int inst_no; unsigned int port0_base_paddr; int mfc_wait_ret = 0; port0_base_paddr = mfc_port0_base_paddr; codec_no = (unsigned int)mfc_get_codec_arg(mfc_ctx->MfcCodecType); if (mfc_cmd_host2risc(H2R_CMD_OPEN_INSTANCE, codec_no, (mfc_ctx->crcEnable << 31) | PIXEL_CACHE_ON_ONLY_P_PICTURE, (context_addr - port0_base_paddr) >> 11, context_size) == false) { mfc_err("R2H_CMD_OPEN_INSTANCE FAIL\n"); return MFCINST_ERR_OPEN_FAIL; } mfc_wait_ret = mfc_wait_for_done(R2H_CMD_OPEN_INSTANCE_RET); if (mfc_wait_ret != R2H_CMD_OPEN_INSTANCE_RET) { mfc_err("R2H_CMD_OPEN_INSTANCE_RET FAIL..........(ret:%d)\n", mfc_wait_ret); return MFCINST_ERR_OPEN_FAIL; } inst_no = READL(MFC_RISC2HOST_ARG1); if (inst_no >= MFC_MAX_INSTANCE_NUM) { mfc_err("mfc_get_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", inst_no, codec_no); return -1; } else { mfc_debug("mfc_get_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", inst_no, codec_no); return inst_no; } } int mfc_return_inst_no(int inst_no, enum ssbsip_mfc_codec_type codec_type) { unsigned int codec_no; int mfc_wait_ret = 0; codec_no = (unsigned int)mfc_get_codec_arg(codec_type); if (mfc_cmd_host2risc(H2R_CMD_CLOSE_INSTANCE, inst_no, 0, 0, 0) == false) { mfc_err("R2H_CMD_CLOSE_INSTANCE FAIL\n"); return MFCINST_ERR_CLOSE_FAIL; } mfc_wait_ret = mfc_wait_for_done(R2H_CMD_CLOSE_INSTANCE_RET); if (mfc_wait_ret != R2H_CMD_CLOSE_INSTANCE_RET) { mfc_err("R2H_CMD_CLOSE_INSTANCE_RET FAIL\n"); return MFCINST_ERR_CLOSE_FAIL; } mfc_debug("mfc_return_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", READL(MFC_RISC2HOST_ARG1), codec_no); return MFCINST_RET_OK; } enum mfc_error_code mfc_init_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { struct mfc_enc_init_mpeg4_arg *enc_init_mpeg4_arg; enum mfc_error_code ret_code; unsigned int context_addr; int context_size; int frame_P_qp, frame_B_qp; int nSize = 0; enc_init_mpeg4_arg = (struct mfc_enc_init_mpeg4_arg *)args; mfc_debug("++\n"); mfc_ctx->MfcCodecType = enc_init_mpeg4_arg->in_codec_type; mfc_ctx->img_width = (unsigned int)enc_init_mpeg4_arg->in_width; mfc_ctx->img_height = (unsigned int)enc_init_mpeg4_arg->in_height; mfc_ctx->interlace_mode = enc_init_mpeg4_arg->in_interlace_mode; /* * Set Available Type */ if (mCheckType == false) { nSize = mfc_ctx->img_width * mfc_ctx->img_height; mfc_ctx->shared_mem.p720_limit_enable = 49425; if (nSize > BOUND_MEMORY_SIZE) return MFCINST_ERR_FRM_BUF_SIZE; } else { mfc_ctx->shared_mem.p720_limit_enable = 49424; } /* OPEN CHANNEL * - set open instance using codec_type * - get the instance no */ ret_code = mfc_alloc_context_buffer(mfc_ctx, enc_init_mpeg4_arg->in_mapped_addr, &context_addr, &context_size); if (ret_code != MFCINST_RET_OK) return ret_code; mfc_ctx->InstNo = mfc_get_inst_no(mfc_ctx, context_addr, context_size); if (mfc_ctx->InstNo < 0) { mfc_err("MFCINST_INST_NUM_EXCEEDED\n"); return MFCINST_INST_NUM_EXCEEDED; } /* INIT CODEC * - set init parameter * - set init sequence done command * - set codec buffer * - set input risc buffer */ mfc_set_encode_init_param(mfc_ctx, args); ret_code = mfc_alloc_codec_buffer(mfc_ctx, args); if (ret_code != MFCINST_RET_OK) { /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return ret_code; } mfc_set_codec_buffer(mfc_ctx); /* Set Ref YC0~3 & MV */ ret_code = mfc_alloc_stream_ref_buffer(mfc_ctx, args); if (ret_code != MFCINST_RET_OK) { /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return ret_code; } mfc_set_enc_ref_buffer(mfc_ctx, args); if (enc_init_mpeg4_arg->in_frame_P_qp) frame_P_qp = enc_init_mpeg4_arg->in_frame_P_qp; else frame_P_qp = enc_init_mpeg4_arg->in_frame_qp; if (enc_init_mpeg4_arg->in_frame_B_qp) frame_B_qp = enc_init_mpeg4_arg->in_frame_B_qp; else frame_B_qp = enc_init_mpeg4_arg->in_frame_qp; mfc_ctx->shared_mem.P_B_frame_qp = (frame_B_qp << 6 | frame_P_qp); if (enc_init_mpeg4_arg->in_RC_frm_enable) mfc_ctx->shared_mem.vop_timing = ((1 << 31) | (enc_init_mpeg4_arg->in_RC_framerate << 16) | 1); mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); ret_code = mfc_encode_header(mfc_ctx, args); mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); mfc_backup_context(mfc_ctx); mfc_debug_L0("--\n"); return ret_code; } static enum mfc_error_code mfc_encode_header(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { struct mfc_enc_init_mpeg4_arg *init_arg; unsigned int port0_base_paddr; int nIntrRet = 0; int nReturnErrCode = 0; init_arg = (struct mfc_enc_init_mpeg4_arg *)args; mfc_debug("++ enc_arg->in_strm_st : 0x%08x\n", init_arg->out_p_addr.strm_ref_y); port0_base_paddr = mfc_port0_base_paddr; /* Set share memory */ WRITEL((mfc_ctx->shared_mem_paddr - port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR); /* Set stream buffer addr */ WRITEL((init_arg->out_p_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_SI_CH0_SB_U_ADDR); WRITEL((init_arg->out_p_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_SI_CH0_SB_L_ADDR); WRITEL(STREAM_BUF_SIZE, MFC_SI_CH0_BUFFER_SIZE); WRITEL(1, MFC_STR_BF_U_EMPTY); WRITEL(1, MFC_STR_BF_L_EMPTY); /* buf reset command if stream buffer is frame mode */ WRITEL(0x1 << 1, MFC_EDFU_SF_BUF_CTRL); WRITEL((SEQ_HEADER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID); nIntrRet = mfc_wait_for_done(R2H_CMD_SEQ_DONE_RET); nReturnErrCode = mfc_return_code(); if (nIntrRet == 0) { mfc_err("MFCINST_ERR_ENC_EXE_TIME_OUT\n"); return MFCINST_ERR_INTR_TIME_OUT; } else if ((nIntrRet != R2H_CMD_SEQ_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) { mfc_err("MFCINST_ERR_ENC_SEQ_HEADER_FAIL ....Intr Code (%d)\n", nIntrRet); return MFCINST_ERR_ENC_HEADER_DECODE_FAIL; } else if (nIntrRet != R2H_CMD_SEQ_DONE_RET) { mfc_warn("MFCINST_WARN_ENC_SEQ_HEADER.........(code: %d)\n", nIntrRet); } init_arg->out_header_size = READL(MFC_SI_ENC_STREAM_SIZE); if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) { dma_unmap_single(NULL, init_arg->out_p_addr.strm_ref_y, init_arg->out_header_size, DMA_FROM_DEVICE); } mfc_debug("encoded header size (%d)\n", init_arg->out_header_size); return MFCINST_RET_OK; } static enum mfc_error_code mfc_encode_one_frame(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { struct mfc_enc_exe_arg *enc_arg; unsigned int port0_base_paddr, port1_base_paddr; int interrupt_flag; int nReturnErrCode; enc_arg = (struct mfc_enc_exe_arg *)args; mfc_debug("++ enc_arg->in_strm_st : 0x%08x enc_arg->in_strm_end :0x%08x \r\n", enc_arg->in_strm_st, enc_arg->in_strm_end); mfc_debug("enc_arg->in_Y_addr : 0x%08x enc_arg->in_CbCr_addr :0x%08x \r\n", enc_arg->in_Y_addr, enc_arg->in_CbCr_addr); mfc_restore_context(mfc_ctx); port0_base_paddr = mfc_port0_base_paddr; port1_base_paddr = mfc_port1_base_paddr; #ifdef ENABLE_DEBUG_ENC_EXE_INTR_ERR #if ENABLE_DEBUG_ENC_EXE_INTR_ERR makefile_mfc_enc_err_info(enc_arg); #endif #endif /* Set share memory */ WRITEL((mfc_ctx->shared_mem_paddr - port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR); /* Set stream buffer addr */ WRITEL((enc_arg->in_strm_st - port0_base_paddr) >> 11, MFC_SI_CH0_SB_U_ADDR); WRITEL((enc_arg->in_strm_st - port0_base_paddr) >> 11, MFC_SI_CH0_SB_L_ADDR); WRITEL(STREAM_BUF_SIZE, MFC_SI_CH0_BUFFER_SIZE); /* Set current frame buffer addr */ WRITEL((enc_arg->in_Y_addr - port1_base_paddr) >> 11, MFC_SI_CH0_CURRENT_Y_ADDR); WRITEL((enc_arg->in_CbCr_addr - port1_base_paddr) >> 11, MFC_SI_CH0_CURRENT_C_ADDR); WRITEL(1, MFC_STR_BF_U_EMPTY); WRITEL(1, MFC_STR_BF_L_EMPTY); /* buf reset command if stream buffer is frame mode */ WRITEL(0x1 << 1, MFC_EDFU_SF_BUF_CTRL); if (mfc_ctx->forceSetFrameType == NOT_CODED) WRITEL((0x1 << 1), MFC_SI_CH0_ENC_PARA); else if (mfc_ctx->forceSetFrameType == I_FRAME) WRITEL(0x1, MFC_SI_CH0_ENC_PARA); mfc_ctx->forceSetFrameType = DONT_CARE; if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) { unsigned char *in_vir; unsigned int aligned_width; unsigned int aligned_height; in_vir = phys_to_virt(enc_arg->in_Y_addr); aligned_width = ALIGN_TO_128B(mfc_ctx->img_width); aligned_height = ALIGN_TO_32B(mfc_ctx->img_height); dma_map_single(NULL, in_vir, aligned_width*aligned_height, DMA_TO_DEVICE); in_vir = phys_to_virt(enc_arg->in_CbCr_addr); aligned_height = ALIGN_TO_32B(mfc_ctx->img_height/2); dma_map_single(NULL, in_vir, aligned_width*aligned_height, DMA_TO_DEVICE); } /* Try frame encoding */ WRITEL((FRAME << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID); interrupt_flag = mfc_wait_for_done(R2H_CMD_FRAME_DONE_RET); nReturnErrCode = mfc_return_code(); if (interrupt_flag == 0) { mfc_err("MFCINST_ERR_ENC_EXE_TIME_OUT\n"); return MFCINST_ERR_INTR_TIME_OUT; } else if ((interrupt_flag != R2H_CMD_FRAME_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) { mfc_err("MFCINST_ERR_ENC_DONE_FAIL\n"); return MFCINST_ERR_ENC_ENCODE_DONE_FAIL; } else if (interrupt_flag != R2H_CMD_FRAME_DONE_RET) { mfc_warn("MFCINST_WARN_ENC_EXE.........(code: %d)\n", interrupt_flag); } /* Get encoded infromation */ enc_arg->out_frame_type = READL(MFC_SI_ENC_SLICE_TYPE); enc_arg->out_encoded_size = READL(MFC_SI_ENC_STREAM_SIZE); enc_arg->out_encoded_Y_paddr = READL(MFC_SI_ENCODED_Y_ADDR); enc_arg->out_encoded_C_paddr = READL(MFC_SI_ENCODED_C_ADDR); if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) { dma_unmap_single(NULL, enc_arg->in_strm_st, enc_arg->out_encoded_size, DMA_FROM_DEVICE); } mfc_debug("-- frame type(%d) encodedSize(%d)\r\n", enc_arg->out_frame_type, enc_arg->out_encoded_size); return MFCINST_RET_OK; } enum mfc_error_code mfc_exe_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { enum mfc_error_code ret_code; struct mfc_enc_exe_arg *enc_arg; enc_arg = (struct mfc_enc_exe_arg *)args; mfc_ctx->shared_mem.set_frame_tag = enc_arg->in_frametag; mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); /* 5. Encode Frame */ ret_code = mfc_encode_one_frame(mfc_ctx, args); if (ret_code != MFCINST_RET_OK) { mfc_debug("mfc_exe_encode() : Encode Fail..(%d)\n", ret_code); return ret_code; } mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); enc_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top; enc_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot; mfc_debug_L0("--\n"); return ret_code; } enum mfc_error_code mfc_init_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { enum mfc_error_code ret_code; struct mfc_dec_init_arg *init_arg; unsigned int context_addr; int context_size; int nSize; int nIntrRet = 0; int nReturnErrCode = 0; mfc_debug("[%d] mfc_init_decode() start\n", current->pid); init_arg = (struct mfc_dec_init_arg *)args; /* Calculate stream header size */ #if ENABLE_CHECK_SEQ_HEADER init_arg->in_strm_size = calculate_seq_size(init_arg); #endif /* Context setting from input param */ mfc_ctx->MfcCodecType = init_arg->in_codec_type; mfc_ctx->IsPackedPB = init_arg->in_packed_PB; /* OPEN CHANNEL * - set open instance using codec_type * - get the instance no */ ret_code = mfc_alloc_context_buffer(mfc_ctx, init_arg->in_mapped_addr, &context_addr, &context_size); if (ret_code != MFCINST_RET_OK) return ret_code; mfc_ctx->InstNo = mfc_get_inst_no(mfc_ctx, context_addr, context_size); if (mfc_ctx->InstNo < 0) { mfc_err("MFCINST_INST_NUM_EXCEEDED\n"); return MFCINST_INST_NUM_EXCEEDED; } #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR mcontext_addr = context_addr; mcontext_size = context_size; #endif #endif /* * MFC_LF_CONTROL used both encoding and decoding * H.264 encoding, MPEG4 decoding(post filter) * should disable : need more DPB for loop filter */ /* INIT CODEC * set input stream buffer * set sequence done command * set NUM_EXTRA_DPB */ if (mfc_ctx->MfcCodecType == FIMV1_DEC) { WRITEL(mfc_ctx->widthFIMV1, MFC_SI_CH0_FIMV1_HRESOL); WRITEL(mfc_ctx->heightFIMV1, MFC_SI_CH0_FIMV1_VRESOL); } ret_code = mfc_alloc_codec_buffer(mfc_ctx, args); if (ret_code != MFCINST_RET_OK) { /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return ret_code; } if (nReturnErrCode < 0) return MFCINST_ERR_DEC_INVALID_STRM; mfc_set_dec_stream_buffer(mfc_ctx, init_arg->in_strm_buf, init_arg->in_strm_size); /* Set Display Delay and SliceEnable */ mfc_ctx->sliceEnable = 0; WRITEL(((mfc_ctx->sliceEnable << 31) | (mfc_ctx->displayDelay ? ((1 << 30) | (mfc_ctx->displayDelay << 16)) : 0)), MFC_SI_CH0_DPB_CONFIG_CTRL); /* Set Available Type */ if (mCheckType == false) { nSize = mfc_ctx->img_width * mfc_ctx->img_height; mfc_ctx->shared_mem.p720_limit_enable = 49425; if (nSize > BOUND_MEMORY_SIZE) { /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return MFCINST_ERR_FRM_BUF_SIZE; } } else { mfc_ctx->shared_mem.p720_limit_enable = 49424; } WRITEL_SHARED_MEM(mfc_ctx->shared_mem.p720_limit_enable, mfc_ctx->shared_mem_vaddr + P720_LIMIT_ENABLE); WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR); /* Codec Command : Decode a sequence header */ WRITEL((SEQ_HEADER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID); nIntrRet = mfc_wait_for_done(R2H_CMD_SEQ_DONE_RET); nReturnErrCode = mfc_return_code(); if (nIntrRet == 0) { #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 300); #endif #endif mfc_err("MFCINST_ERR_DEC_INIT_TIME_OUT..........[#1]\n"); /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return MFCINST_ERR_INTR_TIME_OUT; } else if ((nIntrRet != R2H_CMD_SEQ_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) { mfc_err("MFCINST_ERR_DEC_SEQ_HEADER_FAIL ....Intr Code (%d)\n", nIntrRet); /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return MFCINST_ERR_DEC_SEQ_DONE_FAIL; } else if (nIntrRet != R2H_CMD_SEQ_DONE_RET) { mfc_warn("MFCINST_WARN_DEC_INIT.........(code: %d)\n", nIntrRet); } #ifdef ENABLE_DEBUG_DEC_EXE_INTR_OK #if ENABLE_DEBUG_DEC_EXE_INTR_OK makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 1000); #endif #endif /* out param & context setting from header decoding result */ mfc_ctx->img_width = READL(MFC_SI_HOR_RESOL); mfc_ctx->img_height = READL(MFC_SI_VER_RESOL); init_arg->out_img_width = READL(MFC_SI_HOR_RESOL); init_arg->out_img_height = READL(MFC_SI_VER_RESOL); /* in the case of VC1 interlace, height will be the multiple of 32 * otherwise, height and width is the mupltiple of 16 */ init_arg->out_buf_width = ALIGN_TO_128B(READL(MFC_SI_HOR_RESOL)); init_arg->out_buf_height = ALIGN_TO_32B(READL(MFC_SI_VER_RESOL)); if (mfc_ctx->MfcCodecType == FIMV1_DEC) { mfc_ctx->img_width = mfc_ctx->widthFIMV1; mfc_ctx->img_height = mfc_ctx->heightFIMV1; init_arg->out_img_width = mfc_ctx->widthFIMV1; init_arg->out_img_height = mfc_ctx->heightFIMV1; init_arg->out_buf_width = ALIGN_TO_128B(mfc_ctx->widthFIMV1); init_arg->out_buf_height = ALIGN_TO_32B(mfc_ctx->heightFIMV1); } /* Set totalDPB */ init_arg->out_dpb_cnt = READL(MFC_SI_MIN_NUM_DPB); mfc_ctx->DPBCnt = READL(MFC_SI_MIN_NUM_DPB); mfc_ctx->totalDPBCnt = init_arg->out_dpb_cnt; mfc_ctx->totalDPBCnt = init_arg->out_dpb_cnt + mfc_ctx->extraDPB; if (mfc_ctx->totalDPBCnt < mfc_ctx->displayDelay) mfc_ctx->totalDPBCnt = mfc_ctx->displayDelay; WRITEL(((mfc_ctx->sliceEnable << 31) | (mfc_ctx->displayDelay ? ((1 << 30) | (mfc_ctx->displayDelay << 16)) : 0) | mfc_ctx->totalDPBCnt), MFC_SI_CH0_DPB_CONFIG_CTRL); mfc_debug("buf_width : %d buf_height : %d out_dpb_cnt : %d mfc_ctx->DPBCnt : %d\n", init_arg->out_img_width, init_arg->out_img_height, init_arg->out_dpb_cnt, mfc_ctx->DPBCnt); mfc_debug("img_width : %d img_height : %d\n", init_arg->out_img_width, init_arg->out_img_height); mfc_set_codec_buffer(mfc_ctx); ret_code = mfc_alloc_dec_frame_buffer(mfc_ctx, args); if (ret_code != MFCINST_RET_OK) { /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return ret_code; } mfc_set_dec_frame_buffer(mfc_ctx); #ifdef ENABLE_DEBUG_MFC_INIT #if ENABLE_DEBUG_MFC_INIT printk_mfc_init_info(mfc_ctx, init_arg); #endif #endif mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR); WRITEL((INIT_BUFFER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID); nIntrRet = mfc_wait_for_done(R2H_CMD_INIT_BUFFERS_RET); nReturnErrCode = mfc_return_code(); if (nIntrRet == 0) { #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 300); #endif #endif mfc_err("MFCINST_ERR_DEC_INIT_TIME_OUT..............[#2]\n"); /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return MFCINST_ERR_INTR_TIME_OUT; } else if ((nIntrRet != R2H_CMD_INIT_BUFFERS_RET) && (nReturnErrCode < MFC_WARN_START_NO)) { mfc_err("MFCINST_ERR_DEC_INIT_BUFFER_FAIL ........(Intr Code : %d)\n", nIntrRet); /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); return MFCINST_ERR_DEC_INIT_BUFFER_FAIL; } else if (nIntrRet != R2H_CMD_INIT_BUFFERS_RET) { mfc_warn("MFCINST_WARN_DEC_INIT_BUFFER.........(Intr code: %d)\n", nIntrRet); } mfc_ctx->IsStartedIFrame = 0; mfc_backup_context(mfc_ctx); mfc_debug("[%d] mfc_init_decode() end\n", current->pid); mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); init_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff); init_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16); init_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff); init_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16); mfc_debug("out_crop_top_offset : %d out_crop_bottom_offset : %d\n", init_arg->out_crop_top_offset, init_arg->out_crop_bottom_offset); return MFCINST_RET_OK; } static enum mfc_error_code mfc_decode_one_frame(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, unsigned int *consumed_strm_size) { unsigned int frame_type; static int count; int interrupt_flag; int nReturnErrCode = 0; int nMaxFrameSize = 0; int nOffSet = 0; int nSum = 0; unsigned char *stream_vir; /* Check Invalid Stream Size */ #if ENABLE_CHECK_STREAM_SIZE nMaxFrameSize = mfc_ctx->img_height * mfc_ctx->img_width; if ((dec_arg->in_strm_size < 1) || (dec_arg->in_strm_size > nMaxFrameSize) || (dec_arg->in_strm_size > STREAM_BUF_SIZE)) { mfc_err("MFCINST_ERR_DEC_STRM_SIZE_INVALID : (stream size : %d), (resolution : %d)\n", dec_arg->in_strm_size, nMaxFrameSize); return MFCINST_ERR_DEC_STRM_SIZE_INVALID; } #endif /* Check Invalid Null Stream */ #if ENABLE_CHECK_NULL_STREAM if ((dec_arg->in_strm_size > 10) && (!(mfc_ctx->IsPackedPB))) { stream_vir = phys_to_virt(dec_arg->in_strm_buf); nSum = CheckNullStream(stream_vir, dec_arg->in_strm_size); if (nSum != 0) { #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 500); #endif #endif return MFCINST_ERR_STRM_BUF_INVALID; } } #endif /* Check H.263 Strat Code */ #if ENABLE_CHECK_START_CODE stream_vir = phys_to_virt(dec_arg->in_strm_buf); nOffSet = CheckDecStartCode(stream_vir, dec_arg->in_strm_size, dec_arg->in_codec_type); if (nOffSet < 0) { #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 400); #endif #endif return MFCINST_ERR_STRM_BUF_INVALID; } #endif count++; mfc_debug_L0("++ IntNo%d(%d)\r\n", mfc_ctx->InstNo, count); WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR); mfc_set_dec_stream_buffer(mfc_ctx, dec_arg->in_strm_buf, dec_arg->in_strm_size); if (mfc_ctx->endOfFrame) { WRITEL((LAST_FRAME<<16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID); mfc_ctx->endOfFrame = 0; } else { WRITEL((FRAME<<16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID); } interrupt_flag = mfc_wait_for_done(R2H_CMD_FRAME_DONE_RET); nReturnErrCode = mfc_return_code(); if (interrupt_flag == 0) { #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 300); #endif #endif #if ENABLE_MFC_REGISTER_DEBUG mfc_fw_debug(R2H_CMD_FRAME_DONE_RET); #endif mfc_err("MFCINST_ERR_DEC_EXE_TIME_OUT\n"); return MFCINST_ERR_INTR_TIME_OUT; } else if ((interrupt_flag != R2H_CMD_FRAME_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) { #ifdef ENABLE_DEBUG_DEC_EXE_PARSER_ERR #if ENABLE_DEBUG_DEC_EXE_PARSER_ERR makefile_mfc_dec_err_info(mfc_ctx, dec_arg, nReturnErrCode); #endif #endif /* Clear start_byte_num in case of error */ mfc_ctx->shared_mem.start_byte_num = 0x0; mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); #if ENABLE_MFC_REGISTER_DEBUG mfc_fw_debug(R2H_CMD_FRAME_DONE_RET); #endif mfc_err("MFCINST_ERR_DEC_DONE_FAIL.......(interrupt_flag: %d), (ERR Code: %d)\n", interrupt_flag, nReturnErrCode); return MFCINST_ERR_DEC_DECODE_DONE_FAIL; } else if (interrupt_flag != R2H_CMD_FRAME_DONE_RET) { mfc_warn("MFCINST_WARN_DEC_EXE.........(interrupt_flag: %d), (WARN Code: %d)\n", interrupt_flag, nReturnErrCode); } mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); dec_arg->out_res_change = (READL(MFC_SI_DISPLAY_STATUS) >> 4) & 0x3; if (((READL(MFC_SI_DISPLAY_STATUS) & 0x3) != DECODING_DISPLAY) && ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) != DISPLAY_ONLY)) { dec_arg->out_display_Y_addr = 0; dec_arg->out_display_C_addr = 0; mfc_debug("DECODING_ONLY frame decoded\n"); } else { /* address shift */ dec_arg->out_display_Y_addr = READL(MFC_SI_DISPLAY_Y_ADR) << 11; dec_arg->out_display_C_addr = READL(MFC_SI_DISPLAY_C_ADR) << 11; mfc_debug("DISPLAY Able frame decoded\n"); } if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_EMPTY) dec_arg->out_display_status = 0; else if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_DISPLAY) dec_arg->out_display_status = 1; else if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DISPLAY_ONLY) dec_arg->out_display_status = 2; else dec_arg->out_display_status = 3; frame_type = READL(MFC_SI_FRAME_TYPE); mfc_ctx->FrameType = (enum mfc_frame_type)(frame_type & 0x3); mfc_debug_L0("(Y_ADDR : 0x%08x C_ADDR : 0x%08x)\r\n", dec_arg->out_display_Y_addr, dec_arg->out_display_C_addr); *consumed_strm_size = READL(MFC_SI_DEC_FRM_SIZE); return MFCINST_RET_OK; } enum mfc_error_code mfc_exe_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { enum mfc_error_code ret_code; struct mfc_dec_exe_arg *dec_arg; int consumed_strm_size; /* 6. Decode Frame */ mfc_debug_L0("[%d] mfc_exe_decode() start\n", current->pid); dec_arg = (struct mfc_dec_exe_arg *)args; mfc_ctx->shared_mem.set_frame_tag = dec_arg->in_frametag; mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); ret_code = mfc_decode_one_frame(mfc_ctx, dec_arg, &consumed_strm_size); if (ret_code != MFCINST_RET_OK) { mfc_debug("mfc_exe_decode() : Decode Fail..(%d)\n", ret_code); return ret_code; } mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); dec_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top; dec_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot; dec_arg->out_timestamp_top = mfc_ctx->shared_mem.pic_time_top; dec_arg->out_timestamp_bottom = mfc_ctx->shared_mem.pic_time_bot; dec_arg->out_consume_bytes = consumed_strm_size; dec_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff); dec_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16); dec_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff); dec_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16); /* PackedPB Stream Processing */ if ((mfc_ctx->IsPackedPB) && (mfc_ctx->FrameType == MFC_RET_FRAME_P_FRAME) && (dec_arg->in_strm_size - consumed_strm_size > 4)) { unsigned char *stream_vir; int offset = 0; stream_vir = phys_to_virt(dec_arg->in_strm_buf); invalidate_kernel_vmap_range((void *)stream_vir, dec_arg->in_strm_size); offset = CheckMPEG4StartCode(stream_vir+consumed_strm_size , dec_arg->in_strm_size - consumed_strm_size); if (offset > 4) consumed_strm_size += offset; dec_arg->in_strm_size -= consumed_strm_size; mfc_ctx->shared_mem.set_frame_tag = dec_arg->in_frametag; mfc_ctx->shared_mem.start_byte_num = consumed_strm_size; mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); ret_code = mfc_decode_one_frame(mfc_ctx, dec_arg, &consumed_strm_size); if (ret_code != MFCINST_RET_OK) return ret_code; mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem)); dec_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top; dec_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot; dec_arg->out_timestamp_top = mfc_ctx->shared_mem.pic_time_top; dec_arg->out_timestamp_bottom = mfc_ctx->shared_mem.pic_time_bot; dec_arg->out_consume_bytes += consumed_strm_size; dec_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff); dec_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16); dec_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff); dec_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16); mfc_ctx->shared_mem.start_byte_num = 0; } if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) { if (((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_DISPLAY) || ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DISPLAY_ONLY)) { unsigned int aligned_width; unsigned int aligned_height; aligned_width = ALIGN_TO_128B(mfc_ctx->img_width); aligned_height = ALIGN_TO_32B(mfc_ctx->img_height); dma_unmap_single(NULL, dec_arg->out_display_Y_addr, aligned_width*aligned_height, DMA_FROM_DEVICE); aligned_height = ALIGN_TO_32B(mfc_ctx->img_height/2); dma_unmap_single(NULL, dec_arg->out_display_C_addr, aligned_width*aligned_height, DMA_FROM_DEVICE); } } mfc_debug_L0("--\n"); return ret_code; } enum mfc_error_code mfc_deinit_hw(struct mfc_inst_ctx *mfc_ctx) { mfc_restore_context(mfc_ctx); return MFCINST_RET_OK; } enum mfc_error_code mfc_get_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { struct mfc_get_config_arg *get_cnf_arg; get_cnf_arg = (struct mfc_get_config_arg *)args; switch (get_cnf_arg->in_config_param) { case MFC_DEC_GETCONF_CRC_DATA: if (mfc_ctx->MfcState != MFCINST_STATE_DEC_EXE) { mfc_err("MFC_DEC_GETCONF_CRC_DATA : state is invalid\n"); return MFC_DEC_GETCONF_CRC_DATA; } get_cnf_arg->out_config_value[0] = READL(MFC_CRC_LUMA0); get_cnf_arg->out_config_value[1] = READL(MFC_CRC_CHROMA0); break; default: mfc_err("invalid config param\n"); return MFCINST_ERR_GET_CONF; /* peter, it should be mod. */ } return MFCINST_RET_OK; } enum mfc_error_code mfc_set_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args) { struct mfc_set_config_arg *set_cnf_arg; set_cnf_arg = (struct mfc_set_config_arg *)args; switch (set_cnf_arg->in_config_param) { case MFC_DEC_SETCONF_POST_ENABLE: if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) { mfc_err("MFC_DEC_SETCONF_POST_ENABLE : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) { mfc_ctx->postEnable = set_cnf_arg->in_config_value[0]; } else { mfc_warn("POST_ENABLE should be 0 or 1\n"); mfc_ctx->postEnable = 0; } break; case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM: if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) { mfc_err("MFC_DEC_SETCONF_EXTRA_BUFFER_NUM : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } if ((set_cnf_arg->in_config_value[0] >= 0) || (set_cnf_arg->in_config_value[0] <= MFC_MAX_EXTRA_DPB)) { mfc_ctx->extraDPB = set_cnf_arg->in_config_value[0]; } else { mfc_warn("EXTRA_BUFFER_NUM should be between 0 and 5...It will be set 5 by default\n"); mfc_ctx->extraDPB = MFC_MAX_EXTRA_DPB; } break; case MFC_DEC_SETCONF_DISPLAY_DELAY: if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) { mfc_err("MFC_DEC_SETCONF_DISPLAY_DELAY : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } if ((set_cnf_arg->in_config_value[0] >= 0) || (set_cnf_arg->in_config_value[0] < 16)) { mfc_ctx->displayDelay = set_cnf_arg->in_config_value[0]; mfc_debug("DISPLAY_DELAY Number = %d\n", mfc_ctx->displayDelay); } else { mfc_warn("DISPLAY_DELAY should be between 0 and 16\n"); mfc_ctx->displayDelay = 0; } break; case MFC_DEC_SETCONF_IS_LAST_FRAME: if (mfc_ctx->MfcState != MFCINST_STATE_DEC_EXE) { mfc_err("MFC_DEC_SETCONF_IS_LAST_FRAME : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) { mfc_ctx->endOfFrame = set_cnf_arg->in_config_value[0]; } else { mfc_warn("IS_LAST_FRAME should be 0 or 1\n"); mfc_ctx->endOfFrame = 0; } break; case MFC_DEC_SETCONF_SLICE_ENABLE: if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) { mfc_err("MFC_DEC_SETCONF_SLICE_ENABLE : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) { mfc_ctx->sliceEnable = set_cnf_arg->in_config_value[0]; } else { mfc_warn("SLICE_ENABLE should be 0 or 1\n"); mfc_ctx->sliceEnable = 0; } break; case MFC_DEC_SETCONF_CRC_ENABLE: if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) { mfc_err("MFC_DEC_SETCONF_CRC_ENABLE : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) { mfc_ctx->crcEnable = set_cnf_arg->in_config_value[0]; } else { mfc_warn("CRC_ENABLE should be 0 or 1\n"); mfc_ctx->crcEnable = 0; } break; case MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT: if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) { mfc_err("MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } mfc_ctx->widthFIMV1 = set_cnf_arg->in_config_value[0]; mfc_ctx->heightFIMV1 = set_cnf_arg->in_config_value[1]; break; case MFC_ENC_SETCONF_FRAME_TYPE: if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) { mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } if ((set_cnf_arg->in_config_value[0] >= DONT_CARE) && (set_cnf_arg->in_config_value[0] <= NOT_CODED)) { mfc_ctx->forceSetFrameType = set_cnf_arg->in_config_value[0]; } else { mfc_warn("FRAME_TYPE should be between 0 and 2\n"); mfc_ctx->forceSetFrameType = DONT_CARE; } break; case MFC_ENC_SETCONF_ALLOW_FRAME_SKIP: if (mfc_ctx->MfcState >= MFCINST_STATE_ENC_INITIALIZE) { mfc_err("MFC_ENC_SETCONF_ALLOW_FRAME_SKIP : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } if (set_cnf_arg->in_config_value[0]) mfc_ctx->shared_mem.ext_enc_control = (mfc_ctx->shared_mem.ext_enc_control | (0x1 << 1)); break; /* XXX: need to implement */ case MFC_ENC_SETCONF_CHANGE_FRAME_RATE: if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) { mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } break; /* XXX: need to implement */ case MFC_ENC_SETCONF_CHANGE_BIT_RATE: if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) { mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n"); return MFCINST_ERR_STATE_INVALID; } break; default: mfc_err("invalid config param\n"); return MFCINST_ERR_SET_CONF; } return MFCINST_RET_OK; } enum mfc_error_code mfc_set_sleep() { if (mfc_cmd_host2risc(H2R_CMD_SLEEP, 0, 0, 0, 0) == false) { mfc_err("R2H_CMD_SLEEP FAIL\n"); return MFCINST_SLEEP_FAIL; } if (mfc_wait_for_done(R2H_CMD_SLEEP_RET) != R2H_CMD_SLEEP_RET) { mfc_err("R2H_CMD_SLEEP_RET FAIL\n"); return MFCINST_SLEEP_FAIL; } return MFCINST_RET_OK; } enum mfc_error_code mfc_set_wakeup() { int ret; if (mfc_cmd_host2risc(H2R_CMD_WAKEUP, 0, 0, 0, 0) == false) { mfc_err("R2H_CMD_WAKEUP FAIL\n"); return MFCINST_WAKEUP_FAIL; } WRITEL(0x3ff, MFC_SW_RESET); ret = mfc_wait_for_done(R2H_CMD_WAKEUP_RET); if ((ret != R2H_CMD_WAKEUP_RET) && (ret != R2H_CMD_FW_STATUS_RET)) { mfc_err("R2H_CMD_WAKEUP_RET FAIL\n"); return MFCINST_WAKEUP_FAIL; } return MFCINST_RET_OK; } static enum mfc_error_code mfc_alloc_context_buffer(struct mfc_inst_ctx *mfc_ctx, unsigned int mapped_addr, unsigned int *context_addr, int *size) { union mfc_args local_param; enum mfc_error_code ret_code; unsigned char *context_vir; switch (mfc_ctx->MfcCodecType) { case H264_ENC: *size = H264ENC_CONTEXT_SIZE; break; case MPEG4_ENC: *size = MPEG4ENC_CONTEXT_SIZE; break; case H263_ENC: *size = H263ENC_CONTEXT_SIZE; break; case H264_DEC: *size = H264DEC_CONTEXT_SIZE; break; case H263_DEC: *size = H263DEC_CONTEXT_SIZE; break; case MPEG2_DEC: *size = MPEG2DEC_CONTEXT_SIZE; break; case MPEG4_DEC: case FIMV1_DEC: case FIMV2_DEC: case FIMV3_DEC: case FIMV4_DEC: *size = MPEG4DEC_CONTEXT_SIZE; break; case VC1_DEC: case VC1RCV_DEC: *size = VC1DEC_CONTEXT_SIZE; break; default: return MFCINST_ERR_WRONG_CODEC_MODE; } memset(&local_param, 0, sizeof(local_param)); local_param.mem_alloc.buff_size = *size; local_param.mem_alloc.mapped_addr = mapped_addr; ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0); if (ret_code < 0) return ret_code; /* Set mfc context to "0". */ context_vir = phys_to_virt(local_param.mem_alloc.out_paddr); memset(context_vir, 0x0, local_param.mem_alloc.buff_size); dmac_flush_range(context_vir, context_vir + local_param.mem_alloc.buff_size); *context_addr = local_param.mem_alloc.out_paddr; return ret_code; } void mfc_init_mem_inst_no(void) { memset(&mfc_mem_inst_no, 0x00, sizeof(mfc_mem_inst_no)); } int mfc_get_mem_inst_no(void) { unsigned int i; for (i = 0; i < MFC_MAX_INSTANCE_NUM; i++) { if (mfc_mem_inst_no[i] == 0) { mfc_mem_inst_no[i] = 1; return i; } } return -1; } void mfc_return_mem_inst_no(int inst_no) { if ((inst_no >= 0) && (inst_no < MFC_MAX_INSTANCE_NUM)) mfc_mem_inst_no[inst_no] = 0; } bool mfc_is_running(void) { unsigned int i; bool ret = false; for (i = 0; i < MFC_MAX_INSTANCE_NUM; i++) { mfc_debug("mfc_mem_inst_no[%d] = %d\n", i, mfc_mem_inst_no[i]); if (mfc_mem_inst_no[i] == 1) ret = true; } return ret; } int mfc_set_state(struct mfc_inst_ctx *ctx, enum mfc_inst_state state) { if (ctx->MfcState > state) return -1; ctx->MfcState = state; return 0; } bool is_dec_codec(enum ssbsip_mfc_codec_type codec_type) { switch (codec_type) { case H264_DEC: case VC1_DEC: case MPEG4_DEC: case XVID_DEC: case MPEG1_DEC: case MPEG2_DEC: case H263_DEC: case VC1RCV_DEC: case FIMV1_DEC: case FIMV2_DEC: case FIMV3_DEC: case FIMV4_DEC: return true; case H264_ENC: case MPEG4_ENC: case H263_ENC: return false; default: return false; } } /* * Debugging Functions Definition * tile_to_linear_4x2(..) * calculate_seq_size(..) * printk_mfc_init_info(..) */ #if DEBUG_MAKE_RAW static void write_file(char *filename, unsigned char *data, unsigned int nSize) { struct file *file; loff_t pos = 0; int fd; mm_segment_t old_fs; invalidate_kernel_vmap_range(data, nSize); old_fs = get_fs(); set_fs(KERNEL_DS); fd = sys_open(filename, O_WRONLY|O_CREAT, 0644); if (fd >= 0) { sys_write(fd, data, nSize); file = fget(fd); if (file) { vfs_write(file, data, nSize, &pos); fput(file); } sys_close(fd); } else { mfc_err("........Open fail : %d\n", fd); } set_fs(old_fs); dmac_flush_range(data, data + nSize); } static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos) { int pixel_x_m1, pixel_y_m1; int roundup_x, roundup_y; int linear_addr0, linear_addr1, bank_addr ; int x_addr; int trans_addr; pixel_x_m1 = x_size - 1; pixel_y_m1 = y_size - 1; roundup_x = ((pixel_x_m1 >> 7) + 1); roundup_y = ((pixel_x_m1 >> 6) + 1); x_addr = (x_pos >> 2); if ((y_size <= y_pos+32) && (y_pos < y_size) && (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) { linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f)); if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) bank_addr = ((x_addr >> 4) & 0x1); else bank_addr = 0x2 | ((x_addr >> 4) & 0x1); } else { linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f)); if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) bank_addr = ((x_addr >> 4) & 0x1); else bank_addr = 0x2 | ((x_addr >> 4) & 0x1); } linear_addr0 = linear_addr0 << 2; trans_addr = (linear_addr1 << 13) | (bank_addr << 11) | linear_addr0; return trans_addr; } static void copy16(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, int mm, int nn) { p_linear_addr[mm] = p_tiled_addr[nn]; p_linear_addr[mm + 1] = p_tiled_addr[nn + 1]; p_linear_addr[mm + 2] = p_tiled_addr[nn + 2]; p_linear_addr[mm + 3] = p_tiled_addr[nn + 3]; p_linear_addr[mm + 4] = p_tiled_addr[nn + 4]; p_linear_addr[mm + 5] = p_tiled_addr[nn + 5]; p_linear_addr[mm + 6] = p_tiled_addr[nn + 6]; p_linear_addr[mm + 7] = p_tiled_addr[nn + 7]; p_linear_addr[mm + 8] = p_tiled_addr[nn + 8]; p_linear_addr[mm + 9] = p_tiled_addr[nn + 9]; p_linear_addr[mm + 10] = p_tiled_addr[nn + 10]; p_linear_addr[mm + 11] = p_tiled_addr[nn + 11]; p_linear_addr[mm + 12] = p_tiled_addr[nn + 12]; p_linear_addr[mm + 13] = p_tiled_addr[nn + 13]; p_linear_addr[mm + 14] = p_tiled_addr[nn + 14]; p_linear_addr[mm + 15] = p_tiled_addr[nn + 15]; } static void tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size) { int trans_addr; unsigned int i, j, k, nn, mm, index; /*. TILE 4x2 test */ for (i = 0; i < y_size; i = i + 16) { for (j = 0; j < x_size; j = j + 16) { trans_addr = tile_4x2_read(x_size, y_size, j, i); index = i*x_size + j; k = 0; nn = trans_addr + (k << 6); mm = index; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 1; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 2; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 3; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 4; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 5; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 6; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 7; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 8; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 9; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 10; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 11; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 12; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 13; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 14; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); k = 15; nn = trans_addr + (k << 6); mm += x_size; copy16(p_linear_addr, p_tiled_addr, mm, nn); } } } #endif #if ENABLE_CHECK_SEQ_HEADER static int calculate_seq_size(mfc_args *args) { int nn = 0; int nCnt = 0; unsigned char nSum = 0; unsigned char *stream_vir; stream_vir = phys_to_virt(args->dec_init.in_strm_buf); if (args->dec_init.in_strm_size > 31) { for (nn = 0; nn < args->dec_init.in_strm_size - 4; nn++) { nSum = (unsigned char)(((*(stream_vir + nn)) << 1) + ((*(stream_vir + nn + 1)) << 1) + ((*(stream_vir + nn + 2)) << 1) + (*(stream_vir+nn+3))); if (nSum == 0x1) { nCnt++; } if (nCnt == 3) { mfc_info("After Stream Size : %d , nCnt = %d\n", args->dec_init.in_strm_size, nCnt); return nn; } } } return args->dec_init.in_strm_size; } #endif #if ENABLE_DEBUG_MFC_INIT void printk_mfc_init_info(mfc_inst_ctx *mfc_ctx, mfc_args *args) { int nn = 0; unsigned char *stream_vir; mfc_info("MFC Decoder/Encoder Init Information\n"); mfc_info("[InstNo : %d], [DPBCnt : %d], [totalDPBCnt : %d], [extraDPB : %d], [displayDelay : %d],\n", mfc_ctx->InstNo, mfc_ctx->DPBCnt, mfc_ctx->totalDPBCnt, mfc_ctx->extraDPB, mfc_ctx->displayDelay); mfc_info("[img_width : %d], [img_height : %d], [MfcCodecType : %d], [MfcState : %d]\n", mfc_ctx->img_width, mfc_ctx->img_height, mfc_ctx->MfcCodecType, mfc_ctx->MfcState); mfc_info("Input Stream Buffer Information\n"); mfc_info("[in_strm_size : %d], [in_strm_buf : %d]\n", args->dec_init.in_strm_size, args->dec_init.in_strm_buf); stream_vir = phys_to_virt(args->dec_init.in_strm_buf); if (args->dec_init.in_strm_size > 0) { mfc_info("Input Stream Buffer\n"); for (nn = 0; nn < 40; nn++) printk("%02x ", *(stream_vir+nn)); printk("\n"); } } #endif #ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR #if ENABLE_DEBUG_DEC_EXE_INTR_ERR void printk_mfc_dec_exe_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg) { int nn = 0; unsigned char *stream_vir; mfc_info("MFC Decoder/Encoder Exe Information\n"); mfc_info("[InstNo : %d], [DPBCnt : %d], [totalDPBCnt : %d], [extraDPB : %d], [displayDelay : %d],\n", mfc_ctx->InstNo, mfc_ctx->DPBCnt, mfc_ctx->totalDPBCnt, mfc_ctx->extraDPB, mfc_ctx->displayDelay); mfc_info("[img_width : %d], [img_height : %d], [MfcCodecType : %d], [MfcState : %d], [FrameType: %d]\n", mfc_ctx->img_width, mfc_ctx->img_height, mfc_ctx->MfcCodecType, mfc_ctx->MfcState, mfc_ctx->FrameType); mfc_info("Input Stream Buffer Information\n"); mfc_info("[in_strm_size : %d], [in_strm_buf : %d]\n", dec_arg->in_strm_size, dec_arg->in_strm_buf); stream_vir = phys_to_virt(dec_arg->in_strm_buf); if (dec_arg->in_strm_size > 0) { mfc_info("Input Stream Buffer\n"); for (nn = 0; nn < 50; nn++) printk("%02x ", *(stream_vir+nn)); printk("\n"); } } void makefile_mfc_dec_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, int nReturnErrCode) { char fileName0[50]; char fileName1[50]; unsigned char *ctx_virbuf; unsigned char *mfc_dec_in_base_vaddr; mframe_cnt++; if ((nReturnErrCode < 145) || (nReturnErrCode == 300)) { mIsDangerError = 1; printk_mfc_dec_exe_info(mfc_ctx, dec_arg); } memset(fileName0, 0, 50); memset(fileName1, 0, 50); sprintf(fileName0, "/data/dec_in/mfc_decexe_instream_%d_%d.raw", nReturnErrCode, mframe_cnt); sprintf(fileName1, "/data/dec_in/mfc_decexe_mfcctx_%d_%d.bin", nReturnErrCode, mframe_cnt); mfc_dec_in_base_vaddr = phys_to_virt(dec_arg->in_strm_buf); ctx_virbuf = phys_to_virt(mcontext_addr); write_file(fileName0, mfc_dec_in_base_vaddr, dec_arg->in_strm_size); write_file(fileName1, ctx_virbuf, mcontext_size); } void makefile_mfc_decinit_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_init_arg *decinit_arg, int nReturnErrCode) { char fileName0[50]; char fileName1[50]; unsigned char *ctx_virbuf; unsigned char *mfc_dec_in_base_vaddr; mframe_cnt++; pr_info("makefile_mfc_decinit_err_info : in_strm_size(%d)\n", decinit_arg->in_strm_size); memset(fileName0, 0, 50); memset(fileName1, 0, 50); sprintf(fileName0, "/data/dec_in/mfc_decinit_instream_%d_%d.raw", nReturnErrCode, mframe_cnt); sprintf(fileName1, "/data/dec_in/mfc_decinit_mfcctx_%d_%d.bin", nReturnErrCode, mframe_cnt); mfc_dec_in_base_vaddr = phys_to_virt(decinit_arg->in_strm_buf); ctx_virbuf = phys_to_virt(mcontext_addr); write_file(fileName0, mfc_dec_in_base_vaddr, decinit_arg->in_strm_size); write_file(fileName1, ctx_virbuf, mcontext_size); } #endif #endif #ifdef ENABLE_DEBUG_ENC_EXE_INTR_ERR #if ENABLE_DEBUG_ENC_EXE_INTR_ERR void makefile_mfc_enc_err_info(struct mfc_enc_exe_arg *enc_arg) { int nFrameSize = 0; char fileName[50]; unsigned char *mfc_enc_in_base_Y_vaddr; unsigned char *mfc_enc_in_base_CbCr_vaddr; mframe_cnt++; memset(fileName, 0, 50); sprintf(fileName, "/data/enc_in/mfc_in_%04d.yuv", mframe_cnt); nFrameSize = mImgHight * mImgWidth * 3/2; mfc_enc_in_base_Y_vaddr = phys_to_virt(enc_arg->in_Y_addr); mfc_enc_in_base_CbCr_vaddr = phys_to_virt(enc_arg->in_CbCr_addr); mfc_debug("enc_arg->in_Y_addr : 0x%08x enc_arg->in_Y_addr_vir :0x%08x\r\n", enc_arg->in_Y_addr, mfc_enc_in_base_Y_vaddr); tile_to_linear_4x2(pResLinearbuf, mfc_enc_in_base_Y_vaddr, mImgWidth, mImgHight); tile_to_linear_4x2(pResLinearbuf + (mImgHight * mImgWidth), mfc_enc_in_base_CbCr_vaddr, mImgWidth, mImgHight/2); write_file(fileName, pResLinearbuf, nFrameSize); } #endif #endif static int CheckMPEG4StartCode(unsigned char *src_mem, unsigned int remainSize) { unsigned int index = 0; for (index = 0; index < remainSize-3; index++) { if ((src_mem[index] == 0x00) && (src_mem[index+1] == 0x00) && (src_mem[index+2] == 0x01)) return index; } return -1; } #if ENABLE_CHECK_START_CODE static int CheckDecStartCode(unsigned char *src_mem, unsigned int nstreamSize, enum ssbsip_mfc_codec_type nCodecType) { unsigned int index = 0; /* Check Start Code within "isearchSize" bytes. */ unsigned int isearchSize = 20; unsigned int nShift = 0; unsigned char nFlag = 0xFF; if (nCodecType == H263_DEC) { nFlag = 0x08; nShift = 4; } else if (nCodecType == MPEG4_DEC) { nFlag = 0x01; nShift = 0; } else if (nCodecType == H264_DEC) { nFlag = 0x01; nShift = 0; } else { nFlag = 0xFF; } if (nFlag != 0xFF) { if (nstreamSize > 3) { if (nstreamSize > isearchSize) { for (index = 0; index < isearchSize-3; index++) { if ((src_mem[index] == 0x00) && (src_mem[index+1] == 0x00) && ((src_mem[index+2] >> nShift) == nFlag)) return index; } } else { for (index = 0; index < nstreamSize - 3; index++) { if ((src_mem[index] == 0x00) && (src_mem[index+1] == 0x00) && ((src_mem[index+2] >> nShift) == nFlag)) return index; } } } else { return -1; } } else { return 0; } return -1; } #endif #if ENABLE_CHECK_NULL_STREAM static int CheckNullStream(unsigned char *src_mem, unsigned int streamSize) { unsigned int temp = 0; unsigned int nn; if (streamSize < 30) { for (nn = 0; nn < streamSize; nn++) temp += src_mem[nn]; } else { for (nn = 0; nn < 10; nn++) temp += src_mem[nn]; if (temp == 0) { for (nn = streamSize-10; nn < streamSize; nn++) temp += src_mem[nn]; } } if (temp == 0) { mfc_debug("Null Stream......Error\n"); return -1; } return 0; } #endif #if ENABLE_MFC_REGISTER_DEBUG void mfc_fw_debug(mfc_wait_done_type command) { mfc_err("=== MFC FW Debug (Cmd: %d)" "(Ver: 0x%08x) ===\n", command, READL(0x58)); mfc_err("=== (0x64: 0x%08x) (0x68: 0x%08x)" "(0xE4: 0x%08x) (0xE8: 0x%08x)\n", READL(0x64), READL(0x68), READL(0xe4), READL(0xe8)); mfc_err("=== (0xF0: 0x%08x) (0xF4: 0x%08x)" "(0xF8: 0x%08x) (0xFC: 0x%08x)\n", READL(0xf0), READL(0xf4), READL(0xf8), READL(0xfc)); } #endif