📄 mfc_instance.c
字号:
/*
* Project Name MFC DRIVER
* Copyright 2007 Samsung Electronics Co, Ltd. All Rights Reserved.
*
* This software is the confidential and proprietary information
* of Samsung Electronics ("Confidential Information").
* you shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Samsung Electronics
*
* This source file is for initializing the MFC instance.
*
* @name MFC DRIVER MODULE Module (MFC_Inst_Init.c)
* @author name(email address)
* @date 03-28-07
*/
#include "Mfc.h"
#include "MFC_Instance.h"
#include "MfcMemory.h"
#include "DataBuf.h"
#include "FramBufMgr.h"
#include "LogMsg.h"
#include "MfcConfig.h"
#include "MfcSfr.h"
#include "BitProcBuf.h"
#include "MFC_Inst_Pool.h"
static MFCInstCtx _mfcinst_ctx[MFC_NUM_INSTANCES_MAX];
MFCInstCtx *MFCInst_GetCtx(int inst_no)
{
if ((inst_no < 0) || (inst_no >= MFC_NUM_INSTANCES_MAX))
return NULL;
if (MFCINST_STATE(&(_mfcinst_ctx[inst_no])) >= MFCINST_STATE_CREATED)
return &(_mfcinst_ctx[inst_no]);
else
return NULL;
}
// Filling the pStrmBuf and phyadrStrmBuf variables of the MfcInstCtx structure
// (pStrmBuf and phyadrStrmBuf are the virtual and physical address of STRM_BUF(stream buffer) respectively.)
static void Get_MfcStrmBufAddr(MFCInstCtx *ctx, int isLineBuf)
{
// LINE BUF
if (isLineBuf) {
ctx->pStrmBuf = (unsigned char *) ( GetDataBufVirAddr() + (ctx->inst_no * MFC_LINE_BUF_SIZE_PER_INSTANCE) );
ctx->phyadrStrmBuf = (PHYADDR_VAL) ( GetDataBufPhyAddr() + (ctx->inst_no * MFC_LINE_BUF_SIZE_PER_INSTANCE) );
ctx->nStrmBufSize = MFC_LINE_BUF_SIZE_PER_INSTANCE;
}
// RING BUF
else {
#if (MFC_LINE_RING_SHARE == 1)
ctx->pStrmBuf = (unsigned char *) GetDataBufVirAddr();
ctx->phyadrStrmBuf = (PHYADDR_VAL) GetDataBufPhyAddr();
#elif (MFC_LINE_RING_SHARE == 0)
ctx->pStrmBuf = (unsigned char *) ( GetDataBufVirAddr() + MFC_LINE_BUF_SIZE);
ctx->phyadrStrmBuf = (PHYADDR_VAL) ( GetDataBufPhyAddr() + MFC_LINE_BUF_SIZE);
#endif
ctx->nStrmBufSize = MFC_RING_BUF_SIZE;
}
LOG_MSG(LOG_TRACE, "Get_MfcStrmBufAddr", "ctx->pStrmBuf address 0x%08X\n", ctx->pStrmBuf);
LOG_MSG(LOG_TRACE, "Get_MfcStrmBufAddr", "ctx->phyadrStrmBuf address 0x%08X\n", ctx->phyadrStrmBuf);
}
// Filling the pFramBuf and phyadrFramBuf variables of the MfcInstCtx structure
// (pFramBuf and phyadrFramBuf are the virtual and physical address of FRAM_BUF(frame buffer) respectively.)
static BOOL Get_MfcFramBufAddr(MFCInstCtx *ctx, int buf_size)
{
unsigned char *pInstFramBuf;
pInstFramBuf = FramBufMgrCommit(ctx->inst_no, buf_size);
if (pInstFramBuf == NULL) {
LOG_MSG(LOG_ERROR, "Get_MfcFramBufAddr", "Frame buffer allocation was failed!\r\n");
return FALSE;
}
FramBufMgrPrintCommitInfo();
ctx->pFramBuf = pInstFramBuf; // virtual address of frame buffer
ctx->phyadrFramBuf = S3C6400_BASEADDR_MFC_DATA_BUF + ( (int)pInstFramBuf - (int)GetDataBufVirAddr() );
ctx->nFramBufSize = buf_size;
LOG_MSG(LOG_TRACE, "Get_MfcFramBufAddr", "ctx->inst_no : %d\r\n", ctx->inst_no);
LOG_MSG(LOG_TRACE, "Get_MfcFramBufAddr", "ctx->pFramBuf : 0x%X\r\n", ctx->pFramBuf);
LOG_MSG(LOG_TRACE, "Get_MfcFramBufAddr", "ctx->phyadrFramBuf : 0x%X\r\n", ctx->phyadrFramBuf);
return TRUE;
}
void MFCInst_RingBufAddrCorrection(MFCInstCtx *ctx)
{
Get_MfcStrmBufAddr(ctx, 0);
}
int MFCInst_GetLineBuf(MFCInstCtx *ctx, unsigned char **ppBuf, int *size)
{
////////////////////////////
/// STATE checking ///
////////////////////////////
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DELETED)) {
LOG_MSG(LOG_ERROR, "MFCInst_GetRingBuf", "MFC instance is deleted.\r\n");
return MFCINST_ERR_STATE_DELETED;
}
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_INVALIDATED)) {
LOG_MSG(LOG_ERROR, "MFCInst_GetRingBuf", "MFC instance is invalidated.\r\n");
return MFCINST_ERR_STATE_INVALIDATED;
}
if (ctx->inbuf_type == DEC_INBUF_NOT_SPECIFIED)
ctx->inbuf_type = DEC_INBUF_LINE_BUF;
else if (ctx->inbuf_type == DEC_INBUF_RING_BUF)
return MFCINST_ERR_ETC;
*ppBuf = ctx->pStrmBuf;
*size = MFC_LINE_BUF_SIZE_PER_INSTANCE;
return MFCINST_RET_OK;
}
int MFCInst_GetRingBuf(MFCInstCtx *ctx, unsigned char **ppBuf, int *size)
{
unsigned char *pRD_PTR, *pWR_PTR;
int num_bytes_strm_buf; // Number of bytes in STRM_BUF (used in IOCTL_MFC_GET_RING_BUF_ADDR)
MFCInstCtx *pMfcInstTmp;
int inst_no = 0;
////////////////////////////
/// STATE checking ///
////////////////////////////
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DELETED)) {
LOG_MSG(LOG_ERROR, "MFCInst_GetRingBuf", "MFC instance is deleted.\r\n");
return MFCINST_ERR_STATE_DELETED;
}
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_INVALIDATED)) {
LOG_MSG(LOG_ERROR, "MFCInst_GetRingBuf", "MFC instance is invalidated.\r\n");
return MFCINST_ERR_STATE_INVALIDATED;
}
if (ctx->inbuf_type == DEC_INBUF_NOT_SPECIFIED)
ctx->inbuf_type = DEC_INBUF_RING_BUF;
else if (ctx->inbuf_type == DEC_INBUF_LINE_BUF)
return MFCINST_ERR_ETC;
// state variable checking
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_CREATED)) {
#if (MFC_LINE_RING_SHARE == 1)
// If LINE_BUF and RING_BUF are shared,
// there must be no instances other than itself.
if (MfcInstPool_NumAvail() != (MFC_NUM_INSTANCES_MAX-1))
return MFCINST_ERR_ETC;
// Occupy all the instances
// so that the other instances won't be activated
// until this VC-1 decode instance will be closed.
MfcInstPool_OccupyAll();
#elif (MFC_LINE_RING_SHARE == 0)
// If LINE_BUF and RING_BUF are separated.
// there must be no other instances using the RING_BUF other than itself.
if (MfcInstPool_NumAvail() < (MFC_NUM_INSTANCES_MAX-1)) {
for (inst_no=0; inst_no<MFC_NUM_INSTANCES_MAX; inst_no++) {
if (inst_no == ctx->inst_no)
continue;
pMfcInstTmp = MFCInst_GetCtx(inst_no);
if (pMfcInstTmp == NULL)
continue;
if (pMfcInstTmp->inbuf_type == DEC_INBUF_RING_BUF) {
return MFCINST_ERR_ETC;
}
}
}
// If LINE_BUF & RING_BUF are not shared,
// the RING_BUF address must be different from the LINE_BUF.
// For this reason, the address needs correction at first.
MFCInst_RingBufAddrCorrection(ctx);
#endif
}
// Get the current positions of RD_PTR and WR_PTR
MFCInst_GetStreamRWPtrs(ctx, &pRD_PTR, &pWR_PTR);
// When MFC instance is in the state of MFCINST_STATE_CREATED,
// the size of data to be filled in RING_BUF is double the PARTUNIT size.
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_CREATED)) {
*ppBuf = pWR_PTR;
*size = MFC_RING_BUF_PARTUNIT_SIZE << 1;
MFCINST_STATE_BUF_FILL_REQ_SET(ctx);
return MFCINST_RET_OK;
}
*ppBuf = pWR_PTR;
num_bytes_strm_buf = (int)pWR_PTR - (int)pRD_PTR;
if (num_bytes_strm_buf <= 0) // if WR_PTR is behind the RD_PTR.
num_bytes_strm_buf += MFC_RING_BUF_SIZE;
// Num of bytes in RING_BUF is less than MFC_RING_BUF_PARTUNIT_SIZE,
// then load one more MFC_RING_BUF_PARTUNIT_SIZE unit.
if ((num_bytes_strm_buf < MFC_RING_BUF_PARTUNIT_SIZE)
&& MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF)) {
*size = MFC_RING_BUF_PARTUNIT_SIZE;
MFCINST_STATE_BUF_FILL_REQ_SET(ctx);
}
else
*size = 0;
return MFCINST_RET_OK;
}
int MFCInst_GetFramBuf(MFCInstCtx *ctx, unsigned char **ppBuf, int *size)
{
////////////////////////////
/// STATE checking ///
////////////////////////////
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DELETED)) {
LOG_MSG(LOG_ERROR, "MFCInst_GetFramBuf", "MFC instance is deleted.\r\n");
return MFCINST_ERR_STATE_DELETED;
}
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_INVALIDATED)) {
LOG_MSG(LOG_ERROR, "MFCInst_GetFramBuf", "MFC instance is invalidated.\r\n");
return MFCINST_ERR_STATE_INVALIDATED;
}
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_CREATED)) {
LOG_MSG(LOG_ERROR, "MFCInst_GetFramBuf", "MFC instance is not initialized.\r\n");
return MFCINST_ERR_STATE_CHK;
}
if (ctx->pFramBuf == NULL) {
LOG_MSG(LOG_ERROR, "MFCInst_GetFramBuf", "MFC Frame buffer is not internally allocated yet.\n");
return MFCINST_ERR_ETC;
}
*size = (ctx->width * ctx->height * 3) >> 1; // YUV420 frame size
*ppBuf = ctx->pFramBuf + (ctx->idx) * (*size);
return MFCINST_RET_OK;
}
//
// Function Name: MFCInst_GetInstNo
// Description
// It returns the instance number of the 6400 MFC instance context.
// Parameters
// ctx[IN]: MFCInstCtx
//
int MFCInst_GetInstNo(MFCInstCtx *ctx)
{
return ctx->inst_no;
}
//
// Function Name: MFCInst_GetStreamRWPtrs
// Description
// It returns the virtual address of RD_PTR and WR_PTR.
// Parameters
// ctx[IN]: MFCInstCtx
// ppRD_PTR[OUT]: RD_PTR
// ppWR_PTR[OUT]: WR_PTR
//
BOOL MFCInst_GetStreamRWPtrs(MFCInstCtx *ctx, unsigned char **ppRD_PTR, unsigned char **ppWR_PTR)
{
S3C6400_MFC_SFR *mfc_sfr; // MFC SFR pointer
int diff_vir_phy;
if (MFCINST_STATE(ctx) < MFCINST_STATE_CREATED)
return FALSE;
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_CREATED)) {
// If MFCInstCtx is just created and not initialized by MFCInst_Init,
// then the initial RD_PTR and WR_PTR are the start address of STRM_BUF.
*ppRD_PTR = ctx->pStrmBuf;
*ppWR_PTR = ctx->pStrmBuf;
}
else {
// The physical to virtual address conversion of RD_PTR and WR_PTR.
diff_vir_phy = (int) (ctx->pStrmBuf - ctx->phyadrStrmBuf);
mfc_sfr = (S3C6400_MFC_SFR *) GetMfcSfrVirAddr();
*ppRD_PTR = (unsigned char *) (diff_vir_phy + mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_RD_PTR);
*ppWR_PTR = (unsigned char *) (diff_vir_phy + mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR);
}
return TRUE;
}
BOOL MFCInst_SetInbufType(MFCInstCtx *ctx, MFCINST_DEC_INBUF_TYPE inbuf_type)
{
ctx->inbuf_type = inbuf_type;
return TRUE;
}
MFCInstCtx *MFCInst_Create(void)
{
MFCInstCtx *ctx;
int inst_no;
// Occupy the 'inst_no'.
// If it fails, it returns NULL.
inst_no = MfcInstPool_Occupy();
if (inst_no == -1)
return NULL;
ctx = &(_mfcinst_ctx[inst_no]);
Mem_Set(ctx, 0, sizeof(MFCInstCtx));
ctx->inst_no = inst_no;
ctx->inbuf_type = DEC_INBUF_NOT_SPECIFIED;
MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_CREATED);
// At first, since it is not known whether it is LINE_BUF or RING_BUF,
// it assumes to be LINE_BUF.
// Later, if it turns out to be RING_BUF, correction will be made.
Get_MfcStrmBufAddr(ctx, 1);
LOG_MSG(LOG_TRACE, "s3c_mfc_open", "state : %d\n", ctx->state_var);
return ctx;
}
//
// Function Name: MFCInst_Delete
// Description
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -