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

📄 xllp_ac97.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 2 页
字号:
    do
    {
        gotLink = XllpAc97LinkLock(pAc97Reg);
        if (XLLP_FALSE == gotLink)	// 1 usec is a long time.  Skip delay if possible.
        {
			XllpOstDelayMicroSeconds(pOstRegs, 1);
        }
    }        // Wait while time remaining and ACLINK not available
    while (timeRemaining-- && (XLLP_FALSE == gotLink));

    if (XLLP_FALSE == gotLink)	// Didn't get the ACLINK
    {
        status = XLLP_AC97_LINK_LOCK_FAIL;
    }
    else	// We got the link. Perform the write operation and don't wait.
    {

        // First, clear old write status indication CDONE by writing a ONE to that bit.
        pAc97Reg->GSR = XLLP_AC97_GSR_CDONE_MSK;

        *pCodecReg = data;       // Now the write!

        // Wait until write cycle is complete. There should be a way
        //  to do this speculatively at the beginning of the procedure.
        //  Need to discover it. Too inefficient to always wait.

        timeRemaining = maxRWTimeOutUs;
        do
        {
			XllpOstDelayMicroSeconds(pOstRegs, 1);
        }     // Wait while time remaining and command I/O still incomplete.
        while ( (timeRemaining--) && !(pAc97Reg->GSR & XLLP_AC97_GSR_CDONE_MSK));
		if (!(pAc97Reg->GSR & XLLP_AC97_GSR_CDONE_MSK))
			status = XLLP_AC97_CODEC_ACCESS_TIMEOUT;
    }  // Got AC link

done:
    return(status);
} // Ac97CtrlCodecWrite()


/*******************************************************************************
 *
 * FUNCTION:         XllpAc97Read
 *
 * DESCRIPTION:      Read the value of a specific mixer register in a specified 
 *                   AC'97 codec or modem, using the AC Link.
 *
 * INPUT PARAMETERS: 
 *        XLLP_UINT16_T offset : the offset address of the codec register to read.  
 *        XLLP_UINT16_T pData : the pointer to where will hold the read result. 
 *        P_XLLP_AC97_T pAc97Reg : a pointer to AC97 unit registers structure.  
 *        XLLP_UINT32_T maxRWTimeOutUs : timeout value in the reading process. 
 *        XLLP_AC97_CODEC_SEL_T codecSel : specify which codec device to read.
 *
 * RETURNS:          
 *       Success:    0 (XLLP_AC97_NO_ERROR)
 *       Failure:    XLLP_AC97_LINK_LOCK_FAIL: AC Link was not available within the 
 *                           timeout interval.
 *                   XLLP_AC97_CODEC_ACCESS_TIMEOUT: Reading was not finished within the 
 *                           timeout interval.
 *
 *
 * CALLS:            XllpAc97LinkLock, XllpOstDelayMicroSeconds          
 *
 * CALLED BY:        
 *
 * PROTOTYPE:        XLLP_AC97_ERROR_T  XllpAc97Read(XLLP_UINT16_T offset, 
 *								XLLP_UINT16_T *pdata,
 *								P_XLLP_AC97_T pAc97Reg, 
 *								P_XLLP_OST_T pOstRegs,
 *								XLLP_UINT32_T maxRWTimeOutUs, 
 *								XLLP_AC97_CODEC_SEL_T codecSel);
 *
 *******************************************************************************/
 
XLLP_AC97_ERROR_T  XllpAc97Read(XLLP_UINT16_T offset, 
								XLLP_UINT16_T *pdata,
								P_XLLP_AC97_T pAc97Reg, 
								P_XLLP_OST_T pOstRegs,
								XLLP_UINT32_T maxRWTimeOutUs, 
								XLLP_AC97_CODEC_SEL_T codecSel)
{
    XLLP_AC97_ERROR_T	status = XLLP_AC97_NO_ERROR;
    XLLP_BOOL_T			gotLink;
	XLLP_UINT32_T		timeRemaining;
    P_XLLP_VUINT32_T	pCodecReg;

    // Point to specified register within area mapped to target codec regs
    // Check for special case register 54h the GPIO status register
#ifdef WM9712
    if(offset == XLLP_AC97_CR_E_MDM_GPIO_PIN_STAT)
    {
        // Select the Primary or Secondary modem IO address space
	    if (XLLP_AC97_CODEC_PRIMARY == codecSel)
            pCodecReg = &(pAc97Reg->CodecRegsPrimaryMdm[0]);
        else
            pCodecReg = &(pAc97Reg->CodecRegsSecondaryMdm[0]);

        pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;

        // The data is received on Slot 12 and stored by the
        // ACUNIT so we can read back straight away.
        *pdata = (XLLP_UINT16_T)(*pCodecReg);
            
        goto done;
    }
    else
    {
        // Select the Primary or Secondary Audio IO address space
	    if (XLLP_AC97_CODEC_PRIMARY == codecSel)
            pCodecReg = &(pAc97Reg->CodecRegsPrimaryAud[0]);
        else
            pCodecReg = &(pAc97Reg->CodecRegsSecondaryAud[0]);

        pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;  
    }
#else
    // Select the Primary or Secondary Audio IO address space
	if (XLLP_AC97_CODEC_PRIMARY == codecSel)
        pCodecReg = &(pAc97Reg->CodecRegsPrimaryAud[0]);
    else
        pCodecReg = &(pAc97Reg->CodecRegsSecondaryAud[0]);
    pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;  
#endif
	//Lock the ACLINK
    timeRemaining = XLLP_AC97_LOCK_TIMEOUT_DEF;
    do
    {
        gotLink = XllpAc97LinkLock(pAc97Reg);
        if (XLLP_FALSE == gotLink)	// 1 usec is a long time.  Skip delay if possible.
        {
			XllpOstDelayMicroSeconds(pOstRegs, 1);
        }
    }        // Wait while time remaining and ACLINK not available
    while (timeRemaining-- && (XLLP_FALSE == gotLink));

    if (XLLP_FALSE == gotLink)	// Didn't get the ACLINK
    {
        status = XLLP_AC97_LINK_LOCK_FAIL;
    }
    else	// We got the link. Perform the write operation and don't wait.
    {
         // First, clear old read status indications.
        pAc97Reg->GSR = XLLP_AC97_GSR_SDONE_MSK | XLLP_AC97_GSR_RCS_ERR_MSK;

        *pdata = (XLLP_UINT16_T)(*pCodecReg); // This is THE DUMMY READ.

         // Wait for read I/O with codec to complete before doing real read.
        timeRemaining = maxRWTimeOutUs;
        do
        {
			XllpOstDelayMicroSeconds(pOstRegs, 1);
        }   // Wait while time remaining and read I/O still incomplete
        while( (timeRemaining--) && (!(pAc97Reg->GSR & XLLP_AC97_GSR_SDONE_MSK)) );

        if ((pAc97Reg->GSR & XLLP_AC97_GSR_SDONE_MSK) && (!(pAc97Reg->GSR & XLLP_AC97_GSR_RCS_ERR_MSK)) )
        {
             // succeed in reading. clear status bits first.
             pAc97Reg->GSR = XLLP_AC97_GSR_SDONE_MSK | XLLP_AC97_GSR_RCS_ERR_MSK;
            *pdata = (XLLP_UINT16_T)(*pCodecReg);	// THE REAL READ.
     		timeRemaining = maxRWTimeOutUs;
    	    do
	        {
				XllpOstDelayMicroSeconds(pOstRegs, 1);
  		    }   // Wait while time remaining and read I/O still incomplete
    	    while( (timeRemaining--) && (!(pAc97Reg->GSR & XLLP_AC97_GSR_SDONE_MSK)) );

        }
        else	// failed
        {
            status = XLLP_AC97_CODEC_ACCESS_TIMEOUT;
            pAc97Reg->CAR = XLLP_AC97_CAR_CAIP_CLEAR;

        } // else  (OK to do real read)

    } // else  (We got the link.  Perform the read operations.)

    return (status);
} // XllpAc97Read ()


/*******************************************************************************
 *
 * FUNCTION:         XllpAc97ColdReset
 *
 * DESCRIPTION:      After a cold reset of the processor's AC'97 Controller,
 *                   check the AC Link and all AC'97 codecs and modems attached to 
 *                   the controller's AC'97 cold reset pin.
 *
 * INPUT PARAMETERS: 
 *       pAc97ctxt   a pointer to a XLLP_AC97_CONTEXT_T struct, which contains 
 *						necessary information.
 *
 * RETURNS:
 *       Success:    0 (XLLP_AC97_NO_ERROR)
 *       Failure:    XLLP_AC97_CODEC_NOT_READY:   A timeout occurred on one of the codecs.
 *                        In systems with multiple codecs, the calling function 
 *                        could determine which device(s) is/are not ready by 
 *                        performing XllpAc97GetStatus() on 
 *                        AC97CTRL_STAT_PCRDY and AC97CTRL_STAT_SCRDY.
 *
 * GLOBAL EFFECTS:   All codecs initialized to default settings.  Controller
 *                   set to default state and is operational.
 *
 * ASSUMPTIONS:      Not used in an interrupt service routine.
 *
 * CALLS:            XllpOstDelayMicroSeconds     
 *
 * CALLED BY:        XllpAc97Init 
 *
 * PROTOTYPE:        XLLP_AC97_ERROR_T  XllpAc97ColdReset(P_XLLP_AC97_CONTEXT_T pAc97ctxt);
 *
 *******************************************************************************/
XLLP_AC97_ERROR_T  XllpAc97ColdReset(P_XLLP_AC97_CONTEXT_T pAc97ctxt)  
{ 
    XLLP_AC97_ERROR_T	status = XLLP_AC97_NO_ERROR; 
    P_XLLP_AC97_T		pAC97 = pAc97ctxt->pAc97Reg;
    P_XLLP_OST_T 		pOstRegs = pAc97ctxt->pOstRegs;
    XLLP_BOOL_T			priCodecReady, secCodecReady; 
    XLLP_UINT32_T		timeRemaining; 

    pAC97->GCR = 0;    

    // Hold reset active for a minimum time
	XllpOstDelayMicroSeconds(pOstRegs, XLLP_AC97_COLD_HOLDTIME);

    // Deactivate cold reset condition
	pAC97->GCR |= XLLP_AC97_GCR_COLD_RESET_MSK; 
    
    // Set nReset high. This is a workaround for some strange behavior of nReset pin.
    {
	    XLLP_UINT32_T pins[6];
    	pins[0] = 1;
    	pins[1] = 113;
    	XllpGpioSetOutputState1(pAc97ctxt->pGpioReg, pins);
    }
    	
    // And wait with timeout for all codecs to respond.

    priCodecReady = XLLP_FALSE;
	if (XLLP_FALSE == pAc97ctxt->useSecondaryCodec)
	{
	    secCodecReady = XLLP_TRUE;
	}
	else
	{
	    secCodecReady = XLLP_FALSE;
	}
    timeRemaining = pAc97ctxt->maxSetupTimeOutUs;
    do
    {
		XllpOstDelayMicroSeconds(pOstRegs, 1);
        if (pAC97->GSR & XLLP_AC97_GSR_PCRDY_MSK)
            priCodecReady = XLLP_TRUE;
        if (pAC97->GSR & XLLP_AC97_GSR_SCRDY_MSK)
            secCodecReady = XLLP_TRUE;
    }
    while (timeRemaining-- && ((priCodecReady == XLLP_FALSE) || (secCodecReady == XLLP_FALSE)));

    // Timeout status if some of the devices weren't ready.
    if ((priCodecReady == XLLP_FALSE) || (secCodecReady == XLLP_FALSE))
    {
        status = XLLP_AC97_CODEC_NOT_READY;
    }

    return (status);
} // XllpAc97ColdReset ()

/*******************************************************************************
 *
 * FUNCTION:         XllpAc97ShutdownAcLink
 *
 * DESCRIPTION:      Try to shutdown the AC Link by setting the corresponding bit
 *                      in GCR of AC97 unit.
 *
 * INPUT PARAMETERS: None
 *        P_XLLP_AC97_T pAc97Reg : a pointer to AC97 unit registers structure.  
 *
 * RETURNS:          
 *       Success:    0 (XLLP_AC97_NO_ERROR)
 *       Failure:    XLLP_AC97_LINK_SHUTDOWN_FAIL: A timeout occurred in shutdown process.
 *
 * CALLS:            XllpOstDelayMicroSeconds       
 *
 * CALLED BY:        XllpAc97DeInit
 *
 * PROTOTYPE:        XLLP_AC97_ERROR_T  XllpAc97ShutdownAclink(P_XLLP_AC97_T pAc97Reg,
 *															   P_XLLP_OST_T pOstRegs);
 *
 *******************************************************************************/

XLLP_AC97_ERROR_T  XllpAc97ShutdownAclink(P_XLLP_AC97_T pAc97Reg, P_XLLP_OST_T pOstRegs)
{
    XLLP_AC97_ERROR_T status = XLLP_AC97_NO_ERROR; 
    XLLP_UINT32_T timeRemaining = XLLP_AC97_LINKOFF_TIMEOUT_DEF; 

    pAc97Reg->GCR |= XLLP_AC97_GCR_LINK_OFF_MSK;
	
	while (!(pAc97Reg->GSR & XLLP_AC97_GSR_ACOFFD_MSK))
	{
		timeRemaining --;
		if (0 == timeRemaining)
		{
    		status = XLLP_AC97_LINK_SHUTDOWN_FAIL;
    		break;
		}
		XllpOstDelayMicroSeconds(pOstRegs, 1);
    }
	
    return(status);
}

/*******************************************************************************
 *
 * FUNCTION:         XllpAc97LinkLock
 *
 * DESCRIPTION:      Try to lock the AC Link for command/status accesses to a
 *                   codec.
 *
 * INPUT PARAMETERS: 
 *        P_XLLP_AC97_T pAc97Reg : a pointer to AC97 unit registers structure.  
 *
 * RETURNS:          XLLP_TRUE if the attempt was successful; XLLP_FALSE if not.
 *
 * GLOBAL EFFECTS:   If true, the hardware indicator will show that the AC Link
 *                   is locked until either a codec command or status I/O 
 *                   operation has completed, or Ac97CtrlReleaseAcLink 
 *                   is called.
 *
 * CALLS:            
 *
 * CALLED BY:		 XllpAc97Write, XllpAc97Read        
 *
 * PROTOTYPE:        XLLP_BOOL_T XllpAc97LinkLock(P_XLLP_AC97_T pAc97Reg);
 *
 *******************************************************************************/
XLLP_BOOL_T XllpAc97LinkLock(P_XLLP_AC97_T pAc97Reg)
{
    XLLP_BOOL_T		status = XLLP_TRUE;
    XLLP_VUINT32_T	carTmp;

    carTmp = pAc97Reg->CAR;
    if (carTmp & XLLP_AC97_CAR_CAIP_MSK)	// "1" in CAIP bit means lock failed.
    {
        status = XLLP_FALSE;
    }
    return (status);
} // XllpAc97LinkLock()



⌨️ 快捷键说明

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