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

📄 pfclass.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

    PF_FUNCTION_ENTRY();

    // PF must have been configured at least once 
    // in order to start the channel
    if (!m_bConfigured)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Error.  Cannot start post-processing channel without first configuring\r\n"),
            __WFUNCTION__));
        return FALSE;
    }

    if (m_bRunning)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Viewfinding channel already running.\r\n"), __WFUNCTION__));
        return TRUE;
    }

    m_bRunning = TRUE;

    // Reset EOF event, in case stale EOF events were triggered, 
    // which would cause Pin to believe a frame was ready.
    ResetEvent(m_hEOFEvent);

    if (m_pfMode == pfMode_H264Deblock) // H.264 requires output buffer equal to input
    {
        pStartParms->out = pStartParms->in;

        if (pStartParms->h264_pause_row != 0)
        {
            // Enable and set up pause row
            INSREG32BF(&P_IPU_REGS->PF_CONF, IPU_PF_CONF_H264_Y_PAUSE_EN, 
                IPU_PF_CONF_H264_Y_PAUSE_EN_ENABLE);
            INSREG32BF(&P_IPU_REGS->PF_CONF, IPU_PF_CONF_H264_Y_PAUSE_ROW, 
                pStartParms->h264_pause_row);

            m_bPauseEnabled = TRUE;
        }
        else
        {
            // Disable pause row
            INSREG32BF(&P_IPU_REGS->PF_CONF, IPU_PF_CONF_H264_Y_PAUSE_EN, 
                IPU_PF_CONF_H264_Y_PAUSE_EN_DISABLE);

            m_bPauseEnabled = FALSE;
        }
    }
    else
    {
        // Disable pause row
        INSREG32BF(&P_IPU_REGS->PF_CONF, IPU_PF_CONF_H264_Y_PAUSE_EN, 
            IPU_PF_CONF_H264_Y_PAUSE_EN_DISABLE);

        m_bPauseEnabled = FALSE;
    }


    // Protect access to IPU_INT_CTRL_1 and IDMAC_CHA_EN registers.

    // Compute bitmask and shifted bit value for IPU_INT_CTRL_1 register
    iMask = CSP_BITFMASK(IPU_DMA_CHA_DMAPF_5)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_6)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_7);
    iBitval = CSP_BITFVAL(IPU_DMA_CHA_DMAPF_5, IPU_ENABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_6, IPU_ENABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_7, IPU_ENABLE);

    // enable IPU interrupts for channels 29, 30, 31 (PF Y, U, and V Output)
    do
    {
        oldVal = INREG32(&P_IPU_REGS->IPU_INT_CTRL_1);
        newVal = (oldVal & (~iMask)) | iBitval;
    } while (InterlockedTestExchange((LPLONG)&P_IPU_REGS->IPU_INT_CTRL_1, 
                oldVal, newVal) != oldVal);

    // Compute bitmask and shifted bit value for IDMAC enable register.
    iMask = CSP_BITFMASK(IPU_DMA_CHA_DMAPF_0)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_2)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_3)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_4)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_5)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_6)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_7);
    iBitval = CSP_BITFVAL(IPU_DMA_CHA_DMAPF_0, IPU_ENABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_2, IPU_ENABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_3, IPU_ENABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_4, IPU_ENABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_5, IPU_ENABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_6, IPU_ENABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_7, IPU_ENABLE);
    if (m_pfMode == pfMode_H264Deblock)
    {
        iMask |= CSP_BITFMASK(IPU_DMA_CHA_DMAPF_1);
        iBitval |= CSP_BITFVAL(IPU_DMA_CHA_DMAPF_1, IPU_ENABLE);
    }

    // Set the bits to enable the IDMAC channels.
    do
    {
        oldVal = INREG32(&P_IPU_REGS->IDMAC_CHA_EN);
        newVal = (oldVal & (~iMask)) | iBitval;
    } while (InterlockedTestExchange((LPLONG)&P_IPU_REGS->IDMAC_CHA_EN, 
                oldVal, newVal) != oldVal);

    iInputYBufPtr = (UINT32)pStartParms->in->yBufPtr;
    iInputUBufPtr = iInputYBufPtr + pStartParms->in->uOffset;
    iInputVBufPtr = iInputYBufPtr + pStartParms->in->vOffset;

    // Program input Y, U, and V buffers into channel parameter memory
    controlledWriteDMAChannelParam(PF_Y_INPUT_DMA_CHANNEL, 1, 0, iInputYBufPtr); //Buffer 0    31-0
    controlledWriteDMAChannelParam(PF_U_INPUT_DMA_CHANNEL, 1, 0, (unsigned int)iInputUBufPtr); //Buffer 0    31-0
    controlledWriteDMAChannelParam(PF_V_INPUT_DMA_CHANNEL, 1, 0, (unsigned int)iInputVBufPtr); //Buffer 0    31-0

    iOutputYBufPtr = (UINT32)pStartParms->out->yBufPtr;
    iOutputUBufPtr = iOutputYBufPtr + pStartParms->out->uOffset;
    iOutputVBufPtr = iOutputYBufPtr + pStartParms->out->vOffset;
    
    // Program output Y, U, and V buffers into channel parameter memory
    controlledWriteDMAChannelParam(PF_Y_OUTPUT_DMA_CHANNEL, 1, 0, (unsigned int)iOutputYBufPtr); //Buffer 0    31-0
    controlledWriteDMAChannelParam(PF_U_OUTPUT_DMA_CHANNEL, 1, 0, (unsigned int)iOutputUBufPtr); //Buffer 0    31-0
    controlledWriteDMAChannelParam(PF_V_OUTPUT_DMA_CHANNEL, 1, 0, (unsigned int)iOutputVBufPtr); //Buffer 0    31-0

    dumpIpuRegisters(P_IPU_REGS);

    // Buffers ready for all PF DMA Channels
    SETREG32(&P_IPU_REGS->IPU_CHA_BUF0_RDY, 
         CSP_BITFVAL(IPU_DMA_CHA_DMAPF_0, IPU_DMA_CHA_READY) |
         CSP_BITFVAL(IPU_DMA_CHA_DMAPF_2, IPU_DMA_CHA_READY) |
         CSP_BITFVAL(IPU_DMA_CHA_DMAPF_3, IPU_DMA_CHA_READY) |
         CSP_BITFVAL(IPU_DMA_CHA_DMAPF_4, IPU_DMA_CHA_READY) |
         CSP_BITFVAL(IPU_DMA_CHA_DMAPF_5, IPU_DMA_CHA_READY) |
         CSP_BITFVAL(IPU_DMA_CHA_DMAPF_6, IPU_DMA_CHA_READY) |
         CSP_BITFVAL(IPU_DMA_CHA_DMAPF_7, IPU_DMA_CHA_READY));
    if (m_pfMode == pfMode_H264Deblock)
    {
        SETREG32(&P_IPU_REGS->IPU_CHA_BUF0_RDY, 
             CSP_BITFVAL(IPU_DMA_CHA_DMAPF_1, IPU_DMA_CHA_READY));
    }

    PF_FUNCTION_EXIT();

    return TRUE;
}

//-----------------------------------------------------------------------------
//
// Function: PfResume
//
// This function resumes the Postfilter operation after pausingstarts the post-filtering channel.
//
// Parameters:
//      h264_pause_row
//		[in] Specifies a new pause row for the h264 postfilter operation.  This pause row
//		must be greater than the original pause row in order to pause the operation.  Set
//		this parameter to 0 to disable pausing.
//
// Returns:
//      TRUE if success
//      FALSE if failure
//
//-----------------------------------------------------------------------------
DWORD PfClass::PfResume(UINT32 h264_pause_row) // Row to pause at for H.264 mode. 0 to disable pause)
{
    // Only resume if we are running and were paused 
    if (!m_bRunning)
    {
        // return error since Postfilter is not running
        return PF_ERR_NOT_RUNNING;
    }
    else if (!m_bPauseEnabled)
    {
        // return error since pause is not enabled
        return PF_ERR_PAUSE_NOT_ENABLED;
    }
    else
    {
        if (h264_pause_row != 0)
        {
            if ((h264_pause_row > PF_MAX_PAUSE_ROW) || (h264_pause_row < 0))
            {
                // return error since pause row value is not in a valid range
                return PF_ERR_INVALID_PARAMETER;
            }

            // Enable and set up pause row
            INSREG32BF(&P_IPU_REGS->PF_CONF, IPU_PF_CONF_H264_Y_PAUSE_ROW, 
                h264_pause_row);

            m_bPauseEnabled = TRUE;
        }
        else
        {
            // Disable pause row
            INSREG32BF(&P_IPU_REGS->PF_CONF, IPU_PF_CONF_H264_Y_PAUSE_EN, 
                IPU_PF_CONF_H264_Y_PAUSE_EN_DISABLE);
            
            m_bPauseEnabled = FALSE;
        }
    }

    return PF_SUCCESS;
}

//-----------------------------------------------------------------------------
//
// Function: PfStopChannel
//
// This function halts the post-filtering channels.
//
// Parameters:
//      None.
//
// Returns:
//      TRUE if success
//      FALSE if failure
//
//-----------------------------------------------------------------------------
BOOL PfClass::PfStopChannel(void)
{
    UINT32 uTempReg, uTempReg1, uCount = 0;
    UINT32 oldVal, newVal, iMask, iBitval;

    PF_FUNCTION_ENTRY();

    // If not running, return
    if (m_bRunning == FALSE)
    {
        return TRUE;
    }

    m_bRunning = FALSE;

    // initalize ... for the first time through
    uTempReg = INREG32(&P_IPU_REGS->IDMAC_CHA_BUSY);
    uTempReg1 = INREG32(&P_IPU_REGS->IPU_CHA_BUF0_RDY);

    // We can't disable tasks until the active channels
    // have completed their current frames.  Make sure
    // that buffers aren't set as ready (indicating that
    // they are yet to start) and that channels are
    // not busy (indicating that channels are still running).
    while ((uTempReg1 & 0xFE000000) || (uTempReg & 0xFE000000))
    {
        if (uCount <= 1000)
        {
            //..give up the remainder of time slice
            Sleep(1);
            uCount++;

            //.. need to check after the sleep delay
            uTempReg = INREG32(&P_IPU_REGS->IDMAC_CHA_BUSY);
            uTempReg1 = INREG32(&P_IPU_REGS->IPU_CHA_BUF0_RDY);
        }
        else
        {
            //.. there is something wrong ....break out
            DEBUGMSG(ZONE_ERROR,
                (TEXT("%s(): Error in stopping PF channel!\r\n"), __WFUNCTION__));
            break;
        }
    }

    ResetEvent(m_hEOFEvent);

    // Protect access to IDMAC_CHA_EN and IPU_INT_CTRL_1 registers.

    // Compute bitmask and shifted bit value for IDMAC enable register.
    iMask = CSP_BITFMASK(IPU_DMA_CHA_DMAPF_0)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_1)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_2)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_3)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_4)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_5)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_6)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_7);
    iBitval = CSP_BITFVAL(IPU_DMA_CHA_DMAPF_0, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_1, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_2, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_3, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_4, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_5, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_6, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_7, IPU_DISABLE);

    // Use interlocked function to disable the IDMAC channels.
    do
    {
        oldVal = INREG32(&P_IPU_REGS->IDMAC_CHA_EN);
        newVal = (oldVal & (~iMask)) | iBitval;
    } while (InterlockedTestExchange((LPLONG)&P_IPU_REGS->IDMAC_CHA_EN, 
                oldVal, newVal) != oldVal);

    // Compute bitmask and shifted bit value for INT CTRL register.
    iMask = CSP_BITFMASK(IPU_DMA_CHA_DMAPF_5)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_6)
        | CSP_BITFMASK(IPU_DMA_CHA_DMAPF_7);
    iBitval = CSP_BITFVAL(IPU_DMA_CHA_DMAPF_5, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_6, IPU_DISABLE)
        | CSP_BITFVAL(IPU_DMA_CHA_DMAPF_7, IPU_DISABLE);

    // Use interlocked function to disable IPU interrupts 
    // for viewfinding channel.
    do
    {
        oldVal = INREG32(&P_IPU_REGS->IPU_INT_CTRL_1);
        newVal = (oldVal & (~iMask)) | iBitval;
    } while (InterlockedTestExchange((LPLONG)&P_IPU_REGS->IPU_INT_CTRL_1, 
                oldVal, newVal) != oldVal);

    dumpIpuRegisters(P_IPU_REGS);

    PF_FUNCTION_EXIT();

    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: controlledWriteDMAChannelParam
//
// This function uses Interlocked APIs to access IPU_IMA registers
// and then initializes the IDMAC channel parameters.
//
// Parameters:
//      channel
//          [in] String to identify buffer 1 EOF event.
//
// Returns:
//      None.
//
//-----------------------------------------------------------------------------
void PfClass::controlledWriteDMAChannelParam(int channel, int row, int word, unsigned int data)
{
    unsigned addr  =
        0x10000                            // MEM_NU = DMA CPM
        + (((channel * 2) + row)<< 3)    // ROW_NU = (channel*2) << 3
        + word;                            // WORD_NU

    // Software-controlled access to IMA registers
    // IMA registers may only be accessed if IMA_ADDR is
    // set to 0.

    while (1)
    {
        if (INREG32(&P_IPU_REGS->IPU_IMA_ADDR) == 0)
        {
            // Try to set IPU_IMA registers.
            if (InterlockedTestExchange((LPLONG)&P_IPU_REGS->IPU_IMA_ADDR, 0, addr) == 0)
            {
                // Successfully set IMA_ADDR.
                break;
            }
        }
        // IPU_IMA controlled by another process.
        // Surrender CPU and then try again.
        Sleep(0);
    }

    OUTREG32(&P_IPU_REGS->IPU_IMA_DATA, data);
    
    // Cede control of IPU_IMA registers by writing 0 to IPU_IMA_ADDR
    OUTREG32(&P_IPU_REGS->IPU_IMA_ADDR, 0);
}

//-----------------------------------------------------------------------------
//
// Function: writeDMAChannelParam
//
// This function initializes the IDMAC channel parameters.
//
// Parameters:
//      channel
//          [in] String to identify buffer 1 EOF event.
//
// Returns:
//      None.
//
//-----------------------------------------------------------------------------
void PfClass::writeDMAChannelParam(int channel, int row, int word, unsigned int data)
{
    unsigned addr  =
        0x10000                            // MEM_NU = DMA CPM
        + (((channel * 2) + row)<< 3)    // ROW_NU = (channel*2) << 3
        + word;                            // WORD_NU

    OUTREG32(&P_IPU_REGS->IPU_IMA_ADDR, addr);
    OUTREG32(&P_IPU_REGS->IPU_IMA_DATA, data);
}

//-----------------------------------------------------------------------------
//
// Function: PfIDMACChannelConfig
//
// This function initializes the IDMAC channel parameters.
//
// Parameters:
//      None.
//
// Returns:
//      None.
//
//-----------------------------------------------------------------------------
void PfClass::PfIDMACChannelConfig(UINT8 ch, pPfIDMACChannelParams pChannelParams)
{
    UINT32 newVal;

    PF_FUNCTION_ENTRY();

    dumpChannelParams(pChannelParams);

    // Software-controlled access to IMA registers
    // IMA registers may only be accessed if IMA_ADDR is
    // set to 0.

    // Set IPU_IMA_ADDR to 1 to gain control of IPU_IMA registers.
    newVal = 1;

    while (1)
    {
        if (INREG32(&P_IPU_REGS->IPU_IMA_ADDR) == 0)
        {
            // Try to set IPU_IMA registers.
            if (InterlockedTestExchange((LPLONG)&P_IPU_REGS->IPU_IMA_ADDR, 0, newVal) == 0)
            {
                // Successfully set IMA_ADDR.
                break;
            }
        }
        // IPU_IMA controlled by another process.
        // Surrender CPU and then try again.
        Sleep(0);
    }

    writeDMAChannelParam(ch, 0, 0, 0); //Variable data set to 0    31-0

⌨️ 快捷键说明

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