BOOL s3c_mfc_setup_memory(void) { BOOL ret_bit, ret_dat; unsigned char *pDataBuf; /* * MFC SFR(Special Function Registers), Bitprocessor buffer, Data buffer의 * physical address 를 virtual address로 mapping 한다 */ ret_bit = s3c_mfc_memmap_bitproc_buff(); if (ret_bit == FALSE) { mfc_err("fail to mapping bitprocessor buffer memory\n"); return FALSE; } ret_dat = s3c_mfc_memmap_databuf(); if (ret_dat == FALSE) { mfc_err("fail to mapping data buffer memory \n"); return FALSE; } /* FramBufMgr Module Initialization */ pDataBuf = (unsigned char *)s3c_mfc_get_databuf_virt_addr(); s3c_mfc_init_yuvbuf_mgr(pDataBuf + S3C_MFC_STREAM_BUF_SIZE, S3C_MFC_YUV_BUF_SIZE); return TRUE; }
static int s3c_mfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; int buf_size; int nStrmLen, nHdrLen; int out; int yuv_size; int size; void *temp; unsigned int vir_mv_addr; unsigned int vir_mb_type_addr; unsigned int tmp; unsigned int in_usr_data, yuv_buffer, run_index, out_buf_size, databuf_vaddr, offset; unsigned int yuv_buff_cnt, databuf_paddr; unsigned char *OutBuf = NULL; unsigned char *start, *end; s3c_mfc_inst_context_t *pMfcInst; s3c_mfc_handle_t *handle; s3c_mfc_codec_mode_t codec_mode = 0; s3c_mfc_args_t args; s3c_mfc_enc_info_t enc_info; /* * Parameter Check */ handle = (s3c_mfc_handle_t *)file->private_data; if (handle->mfc_inst == NULL) { return -EFAULT; } pMfcInst = handle->mfc_inst; switch (cmd) { case S3C_MFC_IOCTL_MFC_MPEG4_ENC_INIT: case S3C_MFC_IOCTL_MFC_H264_ENC_INIT: case S3C_MFC_IOCTL_MFC_H263_ENC_INIT: mutex_lock(s3c_mfc_mutex); mfc_debug("cmd = %d\n", cmd); out = copy_from_user(&args.enc_init, (s3c_mfc_enc_init_arg_t *)arg, sizeof(s3c_mfc_enc_init_arg_t)); if ( cmd == S3C_MFC_IOCTL_MFC_MPEG4_ENC_INIT ) codec_mode = MP4_ENC; else if ( cmd == S3C_MFC_IOCTL_MFC_H264_ENC_INIT ) codec_mode = AVC_ENC; else if ( cmd == S3C_MFC_IOCTL_MFC_H263_ENC_INIT ) codec_mode = H263_ENC; /* * Initialize MFC Instance */ enc_info.width = args.enc_init.in_width; enc_info.height = args.enc_init.in_height; enc_info.bitrate = args.enc_init.in_bitrate; enc_info.gop_number = args.enc_init.in_gopNum; enc_info.frame_rate_residual = args.enc_init.in_frameRateRes; enc_info.frame_rate_division = args.enc_init.in_frameRateDiv; /* enc_info.intraqp = args.enc_init.in_intraqp; enc_info.qpmax = args.enc_init.in_qpmax; enc_info.gamma = args.enc_init.in_gamma; */ ret = s3c_mfc_instance_init_enc(pMfcInst, codec_mode, &enc_info); args.enc_init.ret_code = ret; out = copy_to_user((s3c_mfc_enc_init_arg_t *)arg, &args.enc_init, sizeof(s3c_mfc_enc_init_arg_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_MFC_MPEG4_ENC_EXE: case S3C_MFC_IOCTL_MFC_H264_ENC_EXE: case S3C_MFC_IOCTL_MFC_H263_ENC_EXE: mutex_lock(s3c_mfc_mutex); out = copy_from_user(&args.enc_exe, (s3c_mfc_enc_exe_arg_t *)arg, sizeof(s3c_mfc_enc_exe_arg_t)); tmp = (pMfcInst->width * pMfcInst->height * 3) >> 1; start = pMfcInst->yuv_buffer; size = tmp * pMfcInst->yuv_buffer_count; dma_cache_maint(start, size, DMA_TO_DEVICE); /* * Encode MFC Instance */ ret = s3c_mfc_inst_enc(pMfcInst, &nStrmLen, &nHdrLen); start = pMfcInst->stream_buffer; size = pMfcInst->stream_buffer_size; dma_cache_maint(start, size, DMA_FROM_DEVICE); args.enc_exe.ret_code = ret; if (ret == S3C_MFC_INST_RET_OK) { args.enc_exe.out_encoded_size = nStrmLen; args.enc_exe.out_header_size = nHdrLen; } out = copy_to_user((s3c_mfc_enc_exe_arg_t *)arg, &args.enc_exe, sizeof(s3c_mfc_enc_exe_arg_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_MFC_MPEG4_DEC_INIT: case S3C_MFC_IOCTL_MFC_H264_DEC_INIT: case S3C_MFC_IOCTL_MFC_H263_DEC_INIT: case S3C_MFC_IOCTL_MFC_VC1_DEC_INIT: mutex_lock(s3c_mfc_mutex); out = copy_from_user(&args.dec_init, (s3c_mfc_dec_init_arg_t *)arg, sizeof(s3c_mfc_dec_init_arg_t)); if ( cmd == S3C_MFC_IOCTL_MFC_MPEG4_DEC_INIT ) codec_mode = MP4_DEC; else if ( cmd == S3C_MFC_IOCTL_MFC_H264_DEC_INIT ) codec_mode = AVC_DEC; else if ( cmd == S3C_MFC_IOCTL_MFC_H263_DEC_INIT) codec_mode = H263_DEC; else { codec_mode = VC1_DEC; } start = pMfcInst->stream_buffer; size = pMfcInst->stream_buffer_size; dma_cache_maint(start, size, DMA_TO_DEVICE); /* * Initialize MFC Instance */ ret = s3c_mfc_inst_init_dec(pMfcInst, codec_mode, args.dec_init.in_strmSize); args.dec_init.ret_code = ret; if (ret == S3C_MFC_INST_RET_OK) { args.dec_init.out_width = pMfcInst->width; args.dec_init.out_height = pMfcInst->height; args.dec_init.out_buf_width = pMfcInst->buf_width; args.dec_init.out_buf_height = pMfcInst->buf_height; } out = copy_to_user((s3c_mfc_dec_init_arg_t *)arg, &args.dec_init, sizeof(s3c_mfc_dec_init_arg_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_MFC_MPEG4_DEC_EXE: case S3C_MFC_IOCTL_MFC_H264_DEC_EXE: case S3C_MFC_IOCTL_MFC_H263_DEC_EXE: case S3C_MFC_IOCTL_MFC_VC1_DEC_EXE: mutex_lock(s3c_mfc_mutex); out = copy_from_user(&args.dec_exe, (s3c_mfc_dec_exe_arg_t *)arg, sizeof(s3c_mfc_dec_exe_arg_t)); tmp = (pMfcInst->width * pMfcInst->height * 3) >> 1; start = pMfcInst->stream_buffer; size = pMfcInst->stream_buffer_size; dma_cache_maint(start, size, DMA_TO_DEVICE); ret = s3c_mfc_inst_dec(pMfcInst, args.dec_exe.in_strmSize); start = pMfcInst->yuv_buffer; size = tmp * pMfcInst->yuv_buffer_count; dma_cache_maint(start, size, DMA_FROM_DEVICE); args.dec_exe.ret_code = ret; out = copy_to_user((s3c_mfc_dec_exe_arg_t *)arg, &args.dec_exe, sizeof(s3c_mfc_dec_exe_arg_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_MFC_GET_LINE_BUF_ADDR: mutex_lock(s3c_mfc_mutex); out = copy_from_user(&args.get_buf_addr, (s3c_mfc_get_buf_addr_arg_t *)arg, sizeof(s3c_mfc_get_buf_addr_arg_t)); ret = s3c_mfc_inst_get_line_buff(pMfcInst, &OutBuf, &buf_size); args.get_buf_addr.out_buf_size = buf_size; args.get_buf_addr.out_buf_addr = args.get_buf_addr.in_usr_data + (OutBuf - s3c_mfc_get_databuf_virt_addr()); args.get_buf_addr.ret_code = ret; out = copy_to_user((s3c_mfc_get_buf_addr_arg_t *)arg, &args.get_buf_addr, sizeof(s3c_mfc_get_buf_addr_arg_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_MFC_GET_YUV_BUF_ADDR: mutex_lock(s3c_mfc_mutex); out = copy_from_user(&args.get_buf_addr, (s3c_mfc_get_buf_addr_arg_t *)arg, sizeof(s3c_mfc_get_buf_addr_arg_t)); if (pMfcInst->yuv_buffer == NULL) { mfc_err("mfc frame buffer is not internally allocated yet\n"); mutex_unlock(s3c_mfc_mutex); return -EFAULT; } /* FRAM_BUF address is calculated differently for Encoder and Decoder. */ switch (pMfcInst->codec_mode) { case MP4_DEC: case AVC_DEC: case VC1_DEC: case H263_DEC: /* Decoder case */ yuv_size = (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1; args.get_buf_addr.out_buf_size = yuv_size; in_usr_data = (unsigned int)args.get_buf_addr.in_usr_data; yuv_buffer = (unsigned int)pMfcInst->yuv_buffer; run_index = pMfcInst->run_index; out_buf_size = args.get_buf_addr.out_buf_size; databuf_vaddr = (unsigned int)s3c_mfc_get_databuf_virt_addr(); offset = yuv_buffer + run_index * out_buf_size - databuf_vaddr; #if (S3C_MFC_ROTATE_ENABLE == 1) if ((pMfcInst->codec_mode != VC1_DEC) && (pMfcInst->post_rotation_mode & 0x0010)) { yuv_buff_cnt = pMfcInst->yuv_buffer_count; offset = yuv_buffer + yuv_buff_cnt * out_buf_size - databuf_vaddr; } #endif args.get_buf_addr.out_buf_addr = in_usr_data + offset; break; case MP4_ENC: case AVC_ENC: case H263_ENC: /* Encoder case */ yuv_size = (pMfcInst->width * pMfcInst->height * 3) >> 1; in_usr_data = args.get_buf_addr.in_usr_data; run_index = pMfcInst->run_index; yuv_buffer = (unsigned int)pMfcInst->yuv_buffer; databuf_vaddr = (unsigned int)s3c_mfc_get_databuf_virt_addr(); offset = run_index * yuv_size + (yuv_buffer - databuf_vaddr); args.get_buf_addr.out_buf_addr = in_usr_data + offset; break; } /* end of switch (codec_mode) */ args.get_buf_addr.ret_code = S3C_MFC_INST_RET_OK; out = copy_to_user((s3c_mfc_get_buf_addr_arg_t *)arg, &args.get_buf_addr, sizeof(s3c_mfc_get_buf_addr_arg_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR: mutex_lock(s3c_mfc_mutex); out = copy_from_user(&args.get_buf_addr, (s3c_mfc_get_buf_addr_arg_t *)arg, sizeof(s3c_mfc_get_buf_addr_arg_t)); yuv_size = (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1; args.get_buf_addr.out_buf_size = yuv_size; yuv_buffer = (unsigned int)pMfcInst->yuv_buffer; run_index = pMfcInst->run_index; out_buf_size = args.get_buf_addr.out_buf_size; databuf_vaddr = (unsigned int)s3c_mfc_get_databuf_virt_addr(); databuf_paddr = (unsigned int)S3C_MFC_BASEADDR_DATA_BUF; offset = yuv_buffer + run_index * out_buf_size - databuf_vaddr; #if (S3C_MFC_ROTATE_ENABLE == 1) if ((pMfcInst->codec_mode != VC1_DEC) && (pMfcInst->post_rotation_mode & 0x0010)) { yuv_buff_cnt = pMfcInst->yuv_buffer_count; offset = yuv_buffer + yuv_buff_cnt * out_buf_size - databuf_vaddr; } #endif args.get_buf_addr.out_buf_addr = databuf_paddr + offset; args.get_buf_addr.ret_code = S3C_MFC_INST_RET_OK; out = copy_to_user((s3c_mfc_get_buf_addr_arg_t *)arg, &args.get_buf_addr, sizeof(s3c_mfc_get_buf_addr_arg_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_MFC_GET_MPEG4_ASP_PARAM: #if (defined(DIVX_ENABLE) && (DIVX_ENABLE == 1)) out = copy_from_user(&args.mpeg4_asp_param, (s3c_mfc_get_mpeg4asp_arg_t *)arg, \ sizeof(s3c_mfc_get_mpeg4asp_arg_t)); ret = S3C_MFC_INST_RET_OK; args.mpeg4_asp_param.ret_code = S3C_MFC_INST_RET_OK; args.mpeg4_asp_param.mp4asp_vop_time_res = pMfcInst->RET_DEC_SEQ_INIT_BAK_MP4ASP_VOP_TIME_RES; args.mpeg4_asp_param.byte_consumed = pMfcInst->RET_DEC_PIC_RUN_BAK_BYTE_CONSUMED; args.mpeg4_asp_param.mp4asp_fcode = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_FCODE; args.mpeg4_asp_param.mp4asp_time_base_last = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_TIME_BASE_LAST; args.mpeg4_asp_param.mp4asp_nonb_time_last = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_NONB_TIME_LAST; args.mpeg4_asp_param.mp4asp_trd = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_MP4ASP_TRD; args.mpeg4_asp_param.mv_addr = (args.mpeg4_asp_param.in_usr_mapped_addr + S3C_MFC_STREAM_BUF_SIZE) \ + (pMfcInst->mv_mbyte_addr - pMfcInst->phys_addr_yuv_buffer); args.mpeg4_asp_param.mb_type_addr = args.mpeg4_asp_param.mv_addr + S3C_MFC_MAX_MV_SIZE; args.mpeg4_asp_param.mv_size = S3C_MFC_MAX_MV_SIZE; args.mpeg4_asp_param.mb_type_size = S3C_MFC_MAX_MBYTE_SIZE; vir_mv_addr = (unsigned int)((pMfcInst->stream_buffer + S3C_MFC_STREAM_BUF_SIZE) + \ (pMfcInst->mv_mbyte_addr - pMfcInst->phys_addr_yuv_buffer)); vir_mb_type_addr = vir_mv_addr + S3C_MFC_MAX_MV_SIZE; out = copy_to_user((s3c_mfc_get_mpeg4asp_arg_t *)arg, &args.mpeg4_asp_param, \ sizeof(s3c_mfc_get_mpeg4asp_arg_t)); #endif break; case S3C_MFC_IOCTL_MFC_GET_CONFIG: mutex_lock(s3c_mfc_mutex); out = copy_from_user(&args, (s3c_mfc_args_t *)arg, sizeof(s3c_mfc_args_t)); ret = s3c_mfc_get_config_params(pMfcInst, &args); out = copy_to_user((s3c_mfc_args_t *)arg, &args, sizeof(s3c_mfc_args_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_MFC_SET_CONFIG: mutex_lock(s3c_mfc_mutex); out = copy_from_user(&args, (s3c_mfc_args_t *)arg, sizeof(s3c_mfc_args_t)); ret = s3c_mfc_set_config_params(pMfcInst, &args); out = copy_to_user((s3c_mfc_args_t *)arg, &args, sizeof(s3c_mfc_args_t)); mutex_unlock(s3c_mfc_mutex); break; case S3C_MFC_IOCTL_VIRT_TO_PHYS: temp = __virt_to_phys((void *)arg); return (int)temp; break; default: mutex_lock(s3c_mfc_mutex); mfc_debug("requested ioctl command is not defined (ioctl cmd = 0x%x)\n", cmd); mutex_unlock(s3c_mfc_mutex); return -ENOIOCTLCMD; } switch (ret) { case S3C_MFC_INST_RET_OK: return 0; default: return -EPERM; } return -EPERM; }
static int s3c_mfc_open(struct inode *inode, struct file *file) { s3c_mfc_handle_t *handle; unsigned char *pDataBuf; /* * Mutex Lock */ mutex_lock(s3c_mfc_mutex); clk_enable(s3c_mfc_hclk); clk_enable(s3c_mfc_sclk); clk_enable(s3c_mfc_pclk); s3c_mfc_openhandle_count++; if (s3c_mfc_openhandle_count == 1) { #if defined(CONFIG_S3C6400_KDPMD) || defined(CONFIG_S3C6400_KDPMD_MODULE) kdpmd_set_event(s3c_mfc_pmdev.devid, KDPMD_DRVOPEN); kdpmd_wakeup(); kdpmd_wait(s3c_mfc_pmdev.devid); s3c_mfc_pmdev.state = DEV_RUNNING; mfc_debug("mfc_open woke up\n"); #endif /* FramBufMgr Module Re-initialization */ s3c_mfc_yuv_buffer_mgr_final(); pDataBuf = (unsigned char *)s3c_mfc_get_databuf_virt_addr(); s3c_mfc_init_yuvbuf_mgr(pDataBuf + S3C_MFC_STREAM_BUF_SIZE, S3C_MFC_YUV_BUF_SIZE); /* * 3. MFC Hardware Initialization */ if (s3c_mfc_init_hw() == FALSE) return -ENODEV; } handle = (s3c_mfc_handle_t *)kmalloc(sizeof(s3c_mfc_handle_t), GFP_KERNEL); if (!handle) { mfc_debug("mfc open error\n"); mutex_unlock(s3c_mfc_mutex); return -ENOMEM; } memset(handle, 0, sizeof(s3c_mfc_handle_t)); /* * MFC Instance creation */ handle->mfc_inst = s3c_mfc_inst_create(); if (handle->mfc_inst == NULL) { mfc_err("fail to mfc instance allocation\n"); kfree(handle); mutex_unlock(s3c_mfc_mutex); return -EPERM; } /* * MFC supports multi-instance. so each instance have own data structure * It saves file->private_data */ file->private_data = (s3c_mfc_handle_t *)handle; mutex_unlock(s3c_mfc_mutex); mfc_debug("mfc open success\n"); return 0; }