📄 xsac97ctrl.c
字号:
ErrorT XsAc97CtrlReadCodecReg (XsAc97CtrlCodecModemIdT ac97DeviceId,
AC97MixerRegisterIdT targetRegister,
UINT32* mixerRegValueP)
{
ErrorT retVal ;
INT badParamNum = 0; // Which param had error. Assume no errors.
INT timeoutLoc = 0; // What point had a timeout. Assume no errors.
BOOL gotLink;
VUINT32 readFinishedStatus;
UINT32 irqIntState;
UINT32 rcsErrTmp;
INT minorIterations;
INT retries = 0;
XsAc97CtrlStatsT* codeStatsP;
VUINT32* mixerRegsAccessP;
retVal = Ac97CheckRegId (targetRegister);
if (retVal)
{
badParamNum = 2;
}
else // register ID OK, set register access pointer to codec access base
{
switch (ac97DeviceId)
{
case XS_AC97CTRL_CM_ID_PRI_CODEC:
mixerRegsAccessP = &XsAc97CtrlRegsP->
XsAC97CtrlMixerRegsPrimaryAud[0];
codeStatsP = &XsAc97CtrlContext.statistics[ac97DeviceId];
break;
default:
retVal = ERR_T_ILLPARAM;
badParamNum = 1;
break;
}
// Point to specified register within area mapped to target codec regs
mixerRegsAccessP += (targetRegister / XS_AC97CTRL_MIXER_REGS_PER_WORD);
} // else (register ID OK)
if (!retVal)
{
// Some statistics. Only valid invocations are interesting.
irqIntState = XsIcDisableInterruptsIrq();
codeStatsP->readCodecNumInvocations++;
XsIcRestoreInterruptsIrq (irqIntState);
do
{
retVal = ERR_NONE; // Clear for possible retry
// Protect entire operation for simplicity. Very small extra
// execution time penalty.
irqIntState = XsIcDisableInterruptsIrq();
// Lock the ACLINK
minorIterations = 0;
do
{
gotLink = XsAc97CtrlLockAcLink();
if (!gotLink) // 1 usec is a long time. Skip delay if possible.
{
DM_WaitUs(1);
}
}
// Wait while time remaining and ACLINK not available
while ( (minorIterations++ < XS_AC97CTRL_CAIP_TIMEOUT_1USECS)
&& !gotLink );
if (!gotLink) // Didn't get the ACLINK
{
retVal = ERR_T_NOT_AVAIL;
}
else // We got the link. Perform the read operations.
{
// First, clear old read status indications.
(void) XsAc97CtrlClearStatus (XS_AC97CTRL_STAT_SDONE);
(void) XsAc97CtrlClearStatus (XS_AC97CTRL_STAT_RCS_ERR);
*mixerRegValueP = *mixerRegsAccessP; // This is THE DUMMY READ.
// Wait for read I/O with codec to complete before doing real read.
minorIterations = 0;
do
{
DM_WaitUs(1);
readFinishedStatus =
XsAc97CtrlGetStatus (XS_AC97CTRL_STAT_SDONE);
}
// Wait while time remaining and read I/O still incomplete
// SDONE bit is high when done.
while ( (minorIterations++ < XS_AC97CTRL_READ_TIMEOUT_1USECS)
&& !readFinishedStatus);
// Another way to detect a timeout is to check the Read
// Completion Status bit in the GSR. It is set for a timeout.
rcsErrTmp = XsAc97CtrlGetStatus (XS_AC97CTRL_STAT_RCS_ERR);
if ( rcsErrTmp ||
!readFinishedStatus)
{
// Timed out on read
retVal = ERR_T_TIMEOUT;
timeoutLoc = 1; // First timeout opportunity
}
else // OK to do real read
{
if (!gotLink) // Didn't get the ACLINK
{
retVal = ERR_T_TIMEOUT;
timeoutLoc = 2; // Second timeout opportunity
}
else // No problems. Perform the read operation.
{
*mixerRegValueP = *mixerRegsAccessP; // THE REAL READ.
}
} // else (OK to do real read)
} // else (We got the link. Perform the read operations.)
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
} // do: try communication until retries run out or success.
while (retries++ < XS_AC97CTRL_CODEC_READ_RETRIES && (retVal));
// Some statistics
irqIntState = XsIcDisableInterruptsIrq();
codeStatsP->readCodecTotalRetries += retries -1; // Adjust for post-increment
if (retVal)
{
codeStatsP->readCodecNumFailures++;
}
else
{
// Clean up after real read. Why must we do it here instead
// of speculatively at the beginning of the read process?
// Need to investigate proper procedure.
minorIterations = 0;
do
{
DM_WaitUs(1);
readFinishedStatus =
XsAc97CtrlGetStatus (XS_AC97CTRL_STAT_SDONE);
}
// Wait while time remaining and read I/O still incomplete
// SDONE bit is high when done.
while ( (minorIterations++ < XS_AC97CTRL_READ_TIMEOUT_1USECS)
&& !readFinishedStatus);
}
// XsIcRestoreInterruptsIrq (irqIntState);
} // if (!retVal): got past initial parameter checks
if (retVal)
{
LOGERROR (XsAc97CtrlContext.loggedError,
ERR_L_XSAC97CTRL,
ERR_S_XSAC97CTRL_CODEC_READ,
retVal,
badParamNum,
timeoutLoc,
targetRegister)
}
return (retVal);
} // XsAc97CtrlCodecRead ()
/*
*******************************************************************************
Non-standard, test-oriented API of main processor on-board
AC'97 controller driver. Lower level access provided.
*******************************************************************************
*/
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlColdReset
*
* DESCRIPTION: Perform a cold reset of the processor's AC'97 Controller,
* the AC Link and all AC'97 codecs and modems attached to
* the controller's AC'97 cold reset pin.
*
* INPUT PARAMETERS: None
*
* RETURNS:
* Success: 0 (ERR_NONE); All codecs reported ready within time limit.
* Failure: ERR_T_TIMEOUT: 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 XsAc97CtrlGetStatus() on
* XS_AC97CTRL_STAT_PCRDY and XS_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:
*
* CALLED BY:
*
* PROTOTYPE: UINT32 XsAc97CtrlColdReset (void);
*
*******************************************************************************
*/
ErrorT XsAc97CtrlColdReset (void)
{
INT numCodecsReady;
BOOL primaryCodecReady;
INT timeRemaining;
UINT32 irqIntState;
XsAc97CtrlContext.loggedError = ERR_NONE;
// Activate cold reset line under interrupt protection
irqIntState = XsIcDisableInterruptsIrq(); // Begin atomic zone.
XsAc97CtrlRegsP->GCR &= ~(XS_AC97CTRL_GCR_COLD_RESET_MSK); // Activate
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
// Hold reset active for a minimum time
for (timeRemaining = 0 ;
timeRemaining < XS_AC97CTRL_COLD_HOLD_50USECS;
timeRemaining++ )
{
DM_WaitUs(50);
}
// Deactivate cold reset line
irqIntState = XsIcDisableInterruptsIrq(); // Begin atomic zone.
XsAc97CtrlRegsP->GCR |= XS_AC97CTRL_GCR_COLD_RESET_MSK; // Deactivate
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
// And wait with timeout for all codecs to respond.
numCodecsReady = 0; // Codecs plus modems.
primaryCodecReady = FALSE;
timeRemaining = XS_AC97CTRL_COLD_TIMEOUT_50USECS;
do
{
DM_WaitUs(50);
if ((!primaryCodecReady) && (XsAc97CtrlRegsP->GSR & XS_AC97CTRL_GSR_PCRDY_MSK))
{
// Note: Don't bother trying to clear the interrupt trigger for the
// primary codec ready status indicator. This is not an
// interrupt-based function.
primaryCodecReady = TRUE;
numCodecsReady ++;
}
// Note: Other codecs or modems would be checked here, if supported by
// the platform.
} // exit loop if timeout or all devices ready
while (timeRemaining-- && (numCodecsReady < XS_AC97CTRL_NUM_CODECS));
// Timeout status if some of the devices weren't ready.
if (numCodecsReady < XS_AC97CTRL_NUM_CODECS)
{
LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL,
ERR_S_XSAC97CTRL_COLD_RESET, ERR_T_TIMEOUT, 0, 0, 0);
}
return (XsAc97CtrlContext.loggedError);
} // XsAc97CtrlColdReset ()
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlLockAcLink
*
* DESCRIPTION: Try to lock the AC Link for command/status accesses to a
* codec.
*
* INPUT PARAMETERS: None
*
* RETURNS: TRUE if the attempt was successful; 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 XsAc97CtrlReleaseAcLink
* is called.
*
* ASSUMPTIONS:
*
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE: BOOL XsAc97CtrlLockAcLink (void);
*
*******************************************************************************
*/
BOOL XsAc97CtrlLockAcLink (void)
{
BOOL status = TRUE;
VUINT32 carTmp;
carTmp = XsAc97CtrlRegsP->CAR;
if (carTmp & XS_AC97CTRL_CAIP_MSK) // "1" in CAIP bit means lock failed.
{
status = FALSE;
}
return (status);
} // XsAc97CtrlLockAcLink ()
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlReleaseAcLink
*
* DESCRIPTION: Forced release of AC Link lock set by XsAc97CtrlLockAcLink
*
* INPUT PARAMETERS: None
*
* RETURNS: None
*
* GLOBAL EFFECTS:
*
* ASSUMPTIONS: Only used if the link has been locked but SW does not
* initiate a command or status query I/O on the link.
*
* CALLS:
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -