📄 wmxscaleaclink.c
字号:
* Clear command done bit to be safe.
*/
pDeviceContext->v_pAC97Regs->GSR = AC97GSR_CDONE;
/*
* Write the data.
*/
*regAddr = (unsigned int) value;
/*
* Wait for command done.
*/
status = private_WaitForCommandDone( hDevice );
if ( WMS_DEVICE_BUSY == status )
{
WM_TRACE( hDevice, (
"WMPlatformACLinkWrite: CDONE didn't get set"
));
goto error;
}
/*
* Clear command done bit again.
*/
pDeviceContext->v_pAC97Regs->GSR = AC97GSR_CDONE;
}
/*
* It worked.
*/
done:
#endif /* WM_USE_XLLP_AC97 */
return WMS_SUCCESS;
/*
* Error cleanup.
*/
error:
/*
* Clear command done bit.
*/
pDeviceContext->v_pAC97Regs->GSR = AC97GSR_CDONE;
return status;
}
#if WM_GPIO_CONTROL
/*-----------------------------------------------------------------------------
* Function: WMPlatformACLinkClearGPIOInput
*
* Writes the given value to the GPIO status register on the codec, using
* slots 1 and 2 of the AC-link frame.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* regval the new value to write to the register. 0 clears sticky bits.
* Note: to preserve the values of output GPIOs, you must write
* the correct value to them (i.e. you cannot just write all
* zeroes if you have GPIO outputs).
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkClearGPIOInput( WM_DEVICE_HANDLE hDevice,
WM_REGVAL regval
)
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
WMSTATUS status = WMS_SUCCESS;
#if WM_USE_XLLP_AC97
{
XLLP_ACODEC_CONTEXT_T ACodecCtxStruct;
XLLP_ACODEC_ERROR_T xllpStatus;
ACODEC_FROM_DEVICE_CONTEXT( &ACodecCtxStruct, pDeviceContext );
xllpStatus = XllpAc97ACodecClearGPIO( &ACodecCtxStruct, regval );
if ( XLLP_ACODEC_SUCCESS != xllpStatus )
{
WM_TRACE( hDevice, ( "XllpAc97ACodecClearGPIO failed: 0x%X", xllpStatus ));
status = XllpStatusToWMStatus( xllpStatus );
}
}
#else /* WM_USE_XLLP_AC97 */
if ( !IS_WM9712_FAMILY( hDevice ) )
{
/*
* Do a normal R54 write - this will write to both slots 1 and 2
* and slot 12, so clearing the sticky bit as well as setting outputs.
*/
status = WMPlatformACLinkWrite( hDevice, WM97_GPIO_PIN_STATUS, regval );
}
else
{
unsigned int pCodecAddr;
volatile unsigned int *regAddr;
/*
* For the WM9711/12 we need to write via codec space to clear sticky bits.
*/
pCodecAddr = PRIMARY_CODEC_REGS( pDeviceContext );
/*
* Work out the virtual address corresponding to the register.
* The registers are based at v_pAC97Regs->CodecRegsPrimaryAud
* and are each 16-bits wide, i.e. at offset reg*2 from the base.
*/
regAddr = (volatile unsigned int *) (pCodecAddr + (WM97_GPIO_PIN_STATUS << 1));
/*
* Write the data.
*/
*regAddr = (unsigned int) regval;
/*
* Wait for 2 frames (50uSecs) for IO completion to occur.
*/
MicroSleep( hDevice, 50 );
}
#endif /* WM_USE_XLLP_AC97 */
return status;
}
#endif /* WM_GPIO_CONTROL */
#if WM_STREAM_AUXADC
/*-----------------------------------------------------------------------------
* Function: WMPlatformACLinkReadCTCAuxADC
*
* Reads the next ADC value from the stream in continuous conversion mode (CTC).
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* pValue variable to receive value
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkReadCTCAuxADC( WM_DEVICE_HANDLE hDevice,
WM_REGVAL *pValue
)
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
WMSTATUS status = WMS_SUCCESS;
#if AC97_RXFIFO_SERVICE_REQUEST
/* Check whether there's data available. */
if ( !pDeviceContext->v_pAC97Regs->MISR & AC97_RXFIFO_SERVICE_REQUEST )
{
status = WMS_NO_DATA;
goto done;
}
#endif /* AC97_RXFIFO_SERVICE_REQUEST */
/* Check for overrun */
if ( pDeviceContext->v_pAC97Regs->MISR & AC97_RXFIFO_ERROR )
{
/*
* Now clear the error condition (by writing the bit).
* Note: we don't do anything about flushing the FIFO because experiments
* have shown that this actually makes things worse.
*/
pDeviceContext->v_pAC97Regs->MISR = AC97_RXFIFO_ERROR;
}
/* Read the value */
*pValue = (WM_REGVAL) pDeviceContext->v_pAC97Regs->MODR;
/* Check for underrun */
if ( pDeviceContext->v_pAC97Regs->MISR & AC97_RXFIFO_ERROR )
{
status = WMS_NO_DATA;
/* Now clear the error condition (by writing the bit). */
pDeviceContext->v_pAC97Regs->MISR = AC97_RXFIFO_ERROR;
}
#if AC97_RXFIFO_SERVICE_REQUEST
done:
#endif /* AC97_RXFIFO_SERVICE_REQUEST */
return status;
}
#endif /* WM_STREAM_AUXADC */
/*-----------------------------------------------------------------------------
* Function: WMPlatformACLinkSetController
*
* Enables or disables the AC Link on the controller.
* After enabling a cold/warm reset must be performed for the link to come up.
* Before disabling the codec must be powered down.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* enable Whether to enable the link.
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMPlatformACLinkSetController( WM_DEVICE_HANDLE hDevice, WM_BOOL enable )
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
if ( enable )
{
pDeviceContext->v_pAC97Regs->GCR &= ~AC97GCR_AclinkOff;
}
/*
* Don't disable the PXA27X AC-Controller once it's been enabled as it causes
* undesirable effects to the FIFOs after a suspend/resume cycle.
*/
#if !WM_CPU_PXA27X
else
{
pDeviceContext->v_pAC97Regs->GCR |= AC97GCR_AclinkOff;
}
#endif
}
/*-----------------------------------------------------------------------------
* Function: WMPlatformACLinkIsCodecReady
*
* Returns whether the AC link is enabled and available for reading and writing.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WM_BOOL
* TRUE if it's enabled.
*---------------------------------------------------------------------------*/
WM_BOOL WMPlatformACLinkIsCodecReady( WM_DEVICE_HANDLE hDevice )
{
return private_IsCodecReady( hDevice );
}
/*-----------------------------------------------------------------------------
* Function: WMPlatformACLinkColdReset
*
* Forces a cold reset of the WM97xx device, restoring everything to its
* default startup condition.
*
* Note: this function assumes the workaround is in place for the
* XScale bug in the AC Link controller - using a GPIO for the reset instead
* of the AC link reset. See WMPlatformConfig.h for more details.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkColdReset( WM_DEVICE_HANDLE hDevice )
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
WMSTATUS status;
#if WM_USE_XLLP_AC97
{
XLLP_ACODEC_CONTEXT_T ACodecCtxStruct;
XLLP_ACODEC_ERROR_T xllpStatus;
ACODEC_FROM_DEVICE_CONTEXT( &ACodecCtxStruct, pDeviceContext );
/*
* We _should_ know what we are, at this point,
* so convert to an XLLP codec ID (most codecs are
* treated the same as the 9712).
*/
if ( IS_WM9705_FAMILY( hDevice ) )
{
ACodecCtxStruct.ACodecId = WM_9712_ID;
}
if ( IS_WM9707_FAMILY( hDevice ) )
{
ACodecCtxStruct.ACodecId = WM_9712_ID;
}
if ( IS_WM9712_FAMILY( hDevice ) )
{
ACodecCtxStruct.ACodecId = WM_9712_ID;
}
if ( IS_WM9713_FAMILY( hDevice ) )
{
ACodecCtxStruct.ACodecId = WM_9713_ID;
}
else
{
goto error;
}
/*
* Then call through to XLLP to do the work for us.
*/
xllpStatus = XllpACodecInit( &ACodecCtxStruct );
if ( XLLP_ACODEC_SUCCESS != xllpStatus )
{
WM_TRACE( hDevice, ( "XllpACodecInit failed: 0x%X", xllpStatus ));
status = XllpStatusToWMStatus( xllpStatus );
goto error;
}
}
#else /* WM_USE_XLLP_AC97 */
/*
* Initiate a cold reset by dragging the reset line low.
*/
pDeviceContext->v_pGPIORegs->RESET_GPIO_REG(GPCR) |= RESET_GPIO_MASK;
pDeviceContext->v_pAC97Regs->GCR &= ~AC97GCR_ColdReset;
/*
* After SDATA_IN goes high, SYNC must be held for a minimum of 1 microsecond.
* Just to be sure everything's OK there is a delay of 10 microseconds.
*/
MicroSleep( hDevice, 10 );
/*
* Take the reset line high again to bring us out of cold reset.
*/
pDeviceContext->v_pGPIORegs->RESET_GPIO_REG(GPSR) |= RESET_GPIO_MASK;
pDeviceContext->v_pAC97Regs->GCR |= AC97GCR_ColdReset;
/*
* We need to be sure the clocks have started before we do a warm reset.
* 10ms ought to be enough for even the slowest clock to react.
*/
MilliSleep( hDevice, 10 );
/*
* Do a warm reset in case the codec defaults to powered down.
*/
if ( !private_IsCodecReady( hDevice ) )
{
status = WMPlatformACLinkWarmReset( hDevice );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/* Check for codec ready. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -