Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}