📄 xllp_ac97acodec.c
字号:
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 + -