aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/mfc50/mfc_opr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/samsung/mfc50/mfc_opr.c')
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_opr.c2516
1 files changed, 2516 insertions, 0 deletions
diff --git a/drivers/media/video/samsung/mfc50/mfc_opr.c b/drivers/media/video/samsung/mfc50/mfc_opr.c
new file mode 100644
index 0000000..a2c2464
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_opr.c
@@ -0,0 +1,2516 @@
+/*
+ * 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 <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <plat/regs-mfc.h>
+#include <asm/cacheflush.h>
+#include <mach/map.h>
+#include <plat/map-s5p.h>
+
+#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
+
+#if DEBUG_MAKE_RAW
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#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);
+
+ 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((buf_addr + CPB_BUF_SIZE - 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);
+ WRITEL(MEM_STRUCT_TILE_ENC, 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);
+
+ 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;
+
+ /* 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);
+
+ 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);
+
+ /* 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);
+
+ /*
+ * 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;
+ }
+
+#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;
+
+ }
+
+ 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