⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c-mfc.c

📁 s3c6400 video code,you play video smooth with it,it is hardware codec
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/version.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/signal.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/arch/irqs.h>
#include <asm/semaphore.h>
#include <linux/miscdevice.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/clk.h>
#include <asm/pgtable.h>

#include <linux/version.h>
#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16)
#include <asm/arch/registers-s3c6400.h>
#else
#include <asm-arm/arch-s3c2410/regs-s3c6400-clock.h>
#include <linux/pm.h>
#include <asm/plat-s3c24xx/pm.h>
#endif


#ifdef CONFIG_S3C6400_PDFW
#include <asm/arch/pd.h>
#if defined(CONFIG_S3C6400_KDPMD) || defined(CONFIG_S3C6400_KDPMD_MODULE)
#include <asm/arch/kdpmd.h>
#endif
#endif



#include "Mfc.h"
#include "MfcConfig.h"
#include "MFC_HW_Init.h"
#include "MFC_Instance.h"
#include "MFC_Inst_Pool.h"
#include "LogMsg.h"
#include "MfcMutex.h"
#include "s3c-mfc.h"
#include "FramBufMgr.h"
#include "MfcMemory.h"
#include "DataBuf.h"
#include "MfcSfr.h"
#include "MfcIntrNotification.h"
#include "MfcDrvParams.h"

static struct clk	*mfc_hclk;
static struct clk	*mfc_sclk;
static struct clk	*mfc_pclk;

static int			_openhandle_count = 0;

#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,21)
#define SAVE_START_ADDR 0x100
#define SAVE_END_ADDR	0x200
//static struct sleep_save mfc_save[SAVE_END_ADDR - SAVE_START_ADDR];
static unsigned int mfc_save[SAVE_END_ADDR - SAVE_START_ADDR];
#define MFC_READ_REG( ADDR ) (unsigned int)*(volatile unsigned int *)(ADDR)
#define MFC_WRITE_REG( ADDR, DATA ) *(volatile unsigned int *)(ADDR) = DATA
#endif

extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);

extern int MFC_GetConfigParams(MFCInstCtx  *pMfcInst, MFC_ARGS   *args);
extern int MFC_SetConfigParams(MFCInstCtx  *pMfcInst, MFC_ARGS   *args);

#ifdef CONFIG_S3C6400_PDFW
int mfc_before_pdoff(void)
{
	printk("MFC context saving before pdoff\n");
	return 0;
}

int mfc_after_pdon(void)
{
	printk("MFC initialization after pdon\n");	
	return 0;
}

struct pm_devtype mfc_pmdev = {
	name: "mfc",
	state: DEV_IDLE,
	before_pdoff: mfc_before_pdoff,
	after_pdon: mfc_after_pdon,
};
#endif

/*
static unsigned long measureTime(struct timeval *start, struct timeval *stop)
{

        unsigned long sec, usec, time;

        sec = stop->tv_sec - start->tv_sec;
        if(stop->tv_usec >= start->tv_usec)
        {
                usec = stop->tv_usec - start->tv_usec;
        }
        else
        {
                usec = stop->tv_usec + 1000000 - start->tv_usec;
                sec--;
        }
        time = sec*1000000 + (usec);
        return time/1000;
}

static struct timeval start, stop;
static unsigned int		tmp_time;
*/

DECLARE_WAIT_QUEUE_HEAD(WaitQueue_MFC);

static struct resource	*mfc_mem;
static void __iomem	*mfc_base;


static irqreturn_t s3c_mfc_irq(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned int	intReason;
	MFCInstCtx		*pMfcInst;

	
	pMfcInst = (MFCInstCtx *)dev_id;
	
	intReason	= MfcIntrReason();

	if (intReason & 0xC00E) {	// if PIC_RUN, buffer full and buffer empty interrupt
		SendInterruptNotification(intReason);
	}
	
	MfcClearIntr();

	return IRQ_HANDLED;
}

static int s3c_mfc_open(struct inode *inode, struct file *file)
{
	MFCInstCtx	*pMfcInst;

	//////////////////
	//	Mutex Lock	//
	//////////////////
	MFC_Mutex_Lock();

	clk_enable(mfc_hclk);
	clk_enable(mfc_sclk);
	clk_enable(mfc_pclk);

	_openhandle_count++;
	if(_openhandle_count == 1) {
	#if defined(CONFIG_S3C6400_KDPMD) || defined(CONFIG_S3C6400_KDPMD_MODULE)
		kdpmd_set_event(mfc_pmdev.devid, KDPMD_DRVOPEN);
		kdpmd_wakeup();
		kdpmd_wait(mfc_pmdev.devid);
		mfc_pmdev.state = DEV_RUNNING;
		printk("mfc_open woke up\n");
	#endif

		//////////////////////////////////////
		//	3. MFC Hardware Initialization	//
		//////////////////////////////////////
		if (MFC_HW_Init() == FALSE)
			return -ENODEV;	
	}
	
	//////////////////////////////
	//	MFC Instance creation	//
	//////////////////////////////
	pMfcInst = MFCInst_Create();
	if (pMfcInst == NULL) {
		LOG_MSG(LOG_ERROR, "mfc_open", "MFC Instance allocation was failed!\r\n");
		MFC_Mutex_Release();
		return -1;
	}

	/*
	 * MFC supports multi-instance. so each instance have own data structure
	 * It saves file->private_data
	 */
	file->private_data = (MFCInstCtx *)pMfcInst;
	

	MFC_Mutex_Release();

	LOG_MSG(LOG_TRACE, "mfc_open", "MFC open success! \r\n");
	
	return 0;
}


static int s3c_mfc_release(struct inode *inode, struct file *file)
{
	MFCInstCtx				*pMfcInst;
	MFCINST_DEC_INBUF_TYPE	inbuf_type;

	MFC_Mutex_Lock();

	pMfcInst = (MFCInstCtx *)file->private_data;
	if (pMfcInst == NULL) {
		return -1;
	};
	
	printk("Exit MFC Linux Driver\n");

	inbuf_type = pMfcInst->inbuf_type;
	
	LOG_MSG(LOG_TRACE, "mfc_release", "delete inst no : %d\n", pMfcInst->inst_no);

#if (MFC_LINE_RING_SHARE == 1)
	// In case of (MFC_LINE_RING_SHARE == 1), all the instances were reserved.
	// Therefore the instances need to be released.
	if (inbuf_type == DEC_INBUF_RING_BUF) {
		MfcInstPool_ReleaseAll();
	}
#endif

	MFCInst_Delete(pMfcInst);

	_openhandle_count--;
	if(_openhandle_count == 0) {

	#if defined(CONFIG_S3C6400_KDPMD) || defined(CONFIG_S3C6400_KDPMD_MODULE)
		mfc_pmdev.state = DEV_IDLE;
		kdpmd_set_event(mfc_pmdev.devid, KDPMD_DRVCLOSE);
		kdpmd_wakeup();
		kdpmd_wait(mfc_pmdev.devid);
	#endif

		clk_disable(mfc_hclk);
		clk_disable(mfc_sclk);
		clk_disable(mfc_pclk);
	}
	
	MFC_Mutex_Release();
	
	return 0;
}


static ssize_t s3c_mfc_write (struct file *file, const char *buf, size_t
		count, loff_t *pos)
{
	return 0;
}

static ssize_t s3c_mfc_read(struct file *file, char *buf, size_t count, loff_t *pos)
{	
	return 0;
}

static int s3c_mfc_ioctl(struct inode *inode, struct file *file, unsigned
		int cmd, unsigned long arg)
{
	int					ret	= 0;
	MFCInstCtx			*pMfcInst;
	unsigned char		*OutBuf	= NULL;
	MFC_CODECMODE		codec_mode	= 0;
	int					buf_size;
	unsigned int		tmp;
	MFC_ARGS			args;
	enc_info_t			enc_info;
	int 	            nStrmLen, nHdrLen;
		
	//////////////////////
	//	Parameter Check	//
	//////////////////////
	pMfcInst = (MFCInstCtx *)file->private_data;
	if (pMfcInst == NULL) {
		return -EFAULT;
	}


	switch(cmd)
	{
		case IOCTL_MFC_MPEG4_ENC_INIT:
		case IOCTL_MFC_H264_ENC_INIT:
		case IOCTL_MFC_H263_ENC_INIT:
			MFC_Mutex_Lock();
			LOG_MSG(LOG_TRACE, "mfc_ioctl", "cmd = %d\r\n", cmd);

			Copy_From_User(&args.enc_init, (MFC_ENC_INIT_ARG *)arg, sizeof(MFC_ENC_INIT_ARG));
			
			if ( cmd == IOCTL_MFC_MPEG4_ENC_INIT )
				codec_mode = MP4_ENC;
			else if ( cmd == IOCTL_MFC_H264_ENC_INIT )
				codec_mode = AVC_ENC;
			else if ( cmd == 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.gopNum			= args.enc_init.in_gopNum;
			enc_info.frameRateRes	= args.enc_init.in_frameRateRes;
			enc_info.frameRateDiv	= args.enc_init.in_frameRateDiv;
			
			ret = MFCInst_Enc_Init(pMfcInst, codec_mode, &enc_info);
			
			args.enc_init.ret_code = ret;
			Copy_To_User((MFC_ENC_INIT_ARG *)arg, &args.enc_init, sizeof(MFC_ENC_INIT_ARG));
			
			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_MPEG4_ENC_EXE:
		case IOCTL_MFC_H264_ENC_EXE:
		case IOCTL_MFC_H263_ENC_EXE:
			MFC_Mutex_Lock();

			Copy_From_User(&args.enc_exe, (MFC_ENC_EXE_ARG *)arg, sizeof(MFC_ENC_EXE_ARG));

			//////////////////////////
			//	Decode MFC Instance	//
			//////////////////////////
			ret = MFCInst_Encode(pMfcInst, &nStrmLen, &nHdrLen);

			args.enc_exe.ret_code	= ret;
			if (ret == MFCINST_RET_OK) {
				args.enc_exe.out_encoded_size = nStrmLen;
				args.enc_exe.out_header_size  = nHdrLen;
			}
			Copy_To_User((MFC_ENC_EXE_ARG *)arg, &args.enc_exe, sizeof(MFC_ENC_EXE_ARG));
			
			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_MPEG4_DEC_INIT:
		case IOCTL_MFC_H264_DEC_INIT:
		case IOCTL_MFC_H263_DEC_INIT:
		case IOCTL_MFC_VC1_DEC_INIT:
			MFC_Mutex_Lock();

			Copy_From_User(&args.dec_init, (MFC_DEC_INIT_ARG *)arg, sizeof(MFC_DEC_INIT_ARG));
			
			if ( cmd == IOCTL_MFC_MPEG4_DEC_INIT )
				codec_mode = MP4_DEC;
			else if ( cmd == IOCTL_MFC_H264_DEC_INIT )
				codec_mode = AVC_DEC;
			else if ( cmd == IOCTL_MFC_H263_DEC_INIT)
				codec_mode = H263_DEC;
			else {
				codec_mode = VC1_DEC;
			}
			
			//////////////////////////////
			//	Initialize MFC Instance	//
			//////////////////////////////
			ret = MFCInst_Init(pMfcInst, codec_mode, args.dec_init.in_strmSize);

			args.dec_init.ret_code	= ret;
			if (ret == MFCINST_RET_OK) {
				args.dec_init.out_width	= pMfcInst->width;
				args.dec_init.out_height= pMfcInst->height;
			}
			Copy_To_User((MFC_DEC_INIT_ARG *)arg, &args.dec_init, sizeof(MFC_DEC_INIT_ARG));

			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_MPEG4_DEC_EXE:
		case IOCTL_MFC_H264_DEC_EXE:
		case IOCTL_MFC_H263_DEC_EXE:
		case IOCTL_MFC_VC1_DEC_EXE:
			MFC_Mutex_Lock();

			Copy_From_User(&args.dec_exe, (MFC_DEC_EXE_ARG *)arg, sizeof(MFC_DEC_EXE_ARG));
			
			if (pMfcInst->inbuf_type == DEC_INBUF_LINE_BUF) {
				ret = MFCInst_Decode(pMfcInst, args.dec_exe.in_strmSize); 
			}
			else if (pMfcInst->inbuf_type == DEC_INBUF_RING_BUF) {
				ret = MFCInst_Decode_Stream(pMfcInst, args.dec_exe.in_strmSize);
			}
			else {
				LOG_MSG(LOG_ERROR, "s3c_mfc_ioctl", "Buffer type is not defined.\n");
				MFC_Mutex_Release();
				args.dec_exe.ret_code = -1;
				return -EINVAL;
			}

			args.dec_exe.ret_code = ret;
			Copy_To_User((MFC_DEC_EXE_ARG *)arg, &args.dec_exe, sizeof(MFC_DEC_EXE_ARG));

			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_RING_BUF_ADDR:
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_buf_addr, (MFC_GET_BUF_ADDR_ARG *)arg, sizeof(MFC_GET_BUF_ADDR_ARG));

			ret = MFCInst_GetRingBuf(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 + ((int)(OutBuf - GetDataBufVirAddr()));
			args.get_buf_addr.ret_code		= ret;
			Copy_To_User((MFC_GET_BUF_ADDR_ARG *)arg, &args.get_buf_addr, sizeof(MFC_GET_BUF_ADDR_ARG));
			
			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_LINE_BUF_ADDR:
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_buf_addr, (MFC_GET_BUF_ADDR_ARG *)arg, sizeof(MFC_GET_BUF_ADDR_ARG));

			ret = MFCInst_GetLineBuf(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 - GetDataBufVirAddr());
			args.get_buf_addr.ret_code		= ret;

			Copy_To_User((MFC_GET_BUF_ADDR_ARG *)arg, &args.get_buf_addr, sizeof(MFC_GET_BUF_ADDR_ARG));

			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_FRAM_BUF_ADDR:
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_buf_addr, (MFC_GET_BUF_ADDR_ARG *)arg, sizeof(MFC_GET_BUF_ADDR_ARG));

			if (pMfcInst->pFramBuf == NULL) {
				LOG_MSG(LOG_ERROR, "s3c_mfc_ioctl", "MFC Frame buffer is not internally allocated yet.\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -