📄 s3c-mfc.c
字号:
#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 + -