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

📄 xllp_ac97acodec.c

📁 优龙pxa270平台试验程序
💻 C
📖 第 1 页 / 共 2 页
字号:
        pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;

        // The data will be sent out on slots 1&2 to register 54h.
        *pCodecReg = (XLLP_VUINT32_T)data;

        pCodecReg = &(pAc97Reg->CodecRegsPrimaryMdm[0]);

        pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;

        // The data will be sent out on slot 12.
        *pCodecReg = (XLLP_VUINT32_T)offsetdata;
       
        goto done;
    }
    
	if(offset == XLLP_AC97_CR_E_MDM_GPIO_PIN_STAT)
	{//it is a special register and sent out on slot 12
    	if (XLLP_AC97_ACODEC_PRIMARY == codecSel)
	    	pCodecReg = &(pAc97Reg->CodecRegsPrimaryMdm[0]);
    	else
	    	pCodecReg = &(pAc97Reg->CodecRegsSecondaryMdm[0]);
    	pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;
        // The data will be sent out on slot 12.
        *pCodecReg = (XLLP_VUINT32_T)data;
        goto done;
	}
        
    // Point to specified register within area mapped to target codec regs
	if (XLLP_AC97_ACODEC_PRIMARY == codecSel)
		pCodecReg = &(pAc97Reg->CodecRegsPrimaryAud[0]);
	else
		pCodecReg = &(pAc97Reg->CodecRegsSecondaryAud[0]);
	pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;

	
	//Lock the ACLINK
    timeRemaining = XLLP_AC97_LOCK_TIMEOUT_DEF;
    do
    {
        gotLink = XllpAc97ACODECLinkLock(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_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
    }
    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 = (XLLP_VUINT32_T)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_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
    }  // Got AC link

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


XLLP_ACODEC_ERROR_T XllpAc97ACodecRead  (XLLP_ACODEC_CONTEXT_T *pDevContext, XLLP_UINT16_T offset,  XLLP_UINT16_T *pdata)
{
    XLLP_ACODEC_ERROR_T	status = XLLP_ACODEC_SUCCESS;
    XLLP_BOOL_T			gotLink;
	XLLP_UINT32_T		timeRemaining;
    P_XLLP_VUINT32_T	pCodecReg;
    P_XLLP_AC97ACODEC_T pAc97Reg = (P_XLLP_AC97ACODEC_T)(pDevContext->pPCMReg); 
	P_XLLP_OST_T pOstRegs = pDevContext->pOSTRegs;
	XLLP_UINT32_T maxRWTimeOutUs = (pDevContext->uMaxReadWriteTimeOutMs) * 1000; 
	XLLP_AC97_ACODEC_SEL_T codecSel = XLLP_AC97_ACODEC_PRIMARY;

    if(offset == XLLP_AC97_CR_E_MDM_GPIO_PIN_STAT)
    {//it is a special register. it does not need dummy read and must be read in modem IO space
        // Select the Primary or Secondary modem IO address space
	    if (XLLP_AC97_ACODEC_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;
    }
    
    // Point to specified register within area mapped to target codec regs
	if (XLLP_AC97_ACODEC_PRIMARY == codecSel)
		pCodecReg = &(pAc97Reg->CodecRegsPrimaryAud[0]);
	else
		pCodecReg = &(pAc97Reg->CodecRegsSecondaryAud[0]);
	pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;

	//Lock the ACLINK
    timeRemaining = XLLP_AC97_LOCK_TIMEOUT_DEF;
    do
    {
        gotLink = XllpAc97ACODECLinkLock(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_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
    }
    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_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
            pAc97Reg->CAR = XLLP_AC97_CAR_CAIP_CLEAR;

        } // else  (OK to do real read)

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

done:    
    return (status);
} 


static XLLP_ACODEC_ERROR_T  XllpAc97ACODECColdReset(XLLP_ACODEC_CONTEXT_T * pAc97ctxt)  
{ 
    XLLP_ACODEC_ERROR_T	status = XLLP_ACODEC_SUCCESS;
    P_XLLP_AC97ACODEC_T pAC97 = (P_XLLP_AC97ACODEC_T)(pAc97ctxt->pPCMReg);
    P_XLLP_OST_T 		pOstRegs = pAc97ctxt->pOSTRegs;
    XLLP_BOOL_T			priCodecReady, secCodecReady; 
    XLLP_UINT32_T		timeRemaining; 
    volatile XLLP_GPIO_T	*pGPIO = (volatile XLLP_GPIO_T *) pAc97ctxt->pGpioReg;

    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((XLLP_GPIO_T *)pGPIO, pins);
    }
    	
    // And wait with timeout for all codecs to respond.

    priCodecReady = XLLP_FALSE;
	if (XLLP_FALSE == pAc97ctxt->bUseSecondaryCodec)
	{
	    secCodecReady = XLLP_TRUE;
	}
	else
	{
	    secCodecReady = XLLP_FALSE;
	}
    timeRemaining = (pAc97ctxt->uMaxSetupTimeOutMs) * 1000;
    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_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
    }

    return (status);
} 


static XLLP_ACODEC_ERROR_T  XllpAc97ACODECShutdownAclink(P_XLLP_AC97ACODEC_T pAc97Reg, P_XLLP_OST_T pOstRegs)
{
    XLLP_ACODEC_ERROR_T	status = XLLP_ACODEC_SUCCESS;
    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_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
    		break;
		}
		XllpOstDelayMicroSeconds(pOstRegs, 1);
    }
	
    return(status);
}

static XLLP_BOOL_T XllpAc97ACODECLinkLock(P_XLLP_AC97ACODEC_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 + -