📄 i2saudio.cpp
字号:
if((m_ulCodec != 4228) && (m_ulCodec != 4271))
{
//
// Use a default.
//
m_ulCodec = 4228;
}
if(m_ulCodec == 4228)
{
RETAILMSG(1, (TEXT("Audio configuring for CS4228\r\n")));
}
else if(m_ulCodec == 4271)
{
RETAILMSG(1, (TEXT("Audio configuring for CS4271\r\n")));
}
else
{
RETAILMSG(1, (TEXT("Audio has unknown codec setting!\r\n")));
}
//
// Set the sample rate at 441Khz. Need to set the sample rate in order to
// talk to the CS4228.
//
mmRet = SetSampleRate(44100, 0);
//
// Set up the I2S audio to use the AC97 port EGPIO for secondary I2S
// channels.
//
HalWriteCommonReg
(
CSC_DEVCFG,
DEVCFG_I2SONSSP | DEVCFG_I2SONAC97,
DEVCFG_I2SONAC97
);
//
// Disable all transmit audio channels.
// Disable all recieve audio channels.
// Set the global configuration register to Disable PCLK to it.
//
*SAI_TX0_EN = *SAI_TX1_EN =* SAI_TX2_EN = 0;
*SAI_RX0_EN = *SAI_RX1_EN =* SAI_RX2_EN = 0;
*SAI_GCR = 0;
//
// Initialize the SAI interface.
//
*SAI_TX_CLKCFG = CLKCFG_MST | CLKCFG_TREL | CLKCFG_POLARITY;
*SAI_RX_CLKCFG = CLKCFG_MST | CLKCFG_TREL | CLKCFG_NBCG | CLKCFG_POLARITY;
//
// Left justified, MSB first, Repeat zero if underflow.
// Outputing zero's will cause the dac to mute.
//
// *SAI_TX_LCR = TX_LCR_UNDERFLOW_ZERO;
*SAI_TX_LCR = 0;
//
// Generate a Interrupt on Halfempty
// (Don't think this makes a difference for DMA.)
//
*SAI_TX_CR = TX_CR_TXUFIE;
//
// Transmit word length. I don't think this matters in Left Justified
// mode.
//
*SAI_TX_WL = WL_24BIT;
//
// Left justified, MSB first.
//
*SAI_RX_LCR = 0;
//
// Generate a Interrupt on Half full
// (Don't think this makes a difference for DMA.)
//
*SAI_RX_CR = RX_CR_OVERFLOW_INT;
//
// Receive word length. I don't think this matters in Left Justified
// mode.
//
*SAI_RX_WL = WL_24BIT;
//
// Set the global configuration register to enable PCLK to it.
//
*SAI_GCR = GCR_PCLK;
//
// Get the Performance counter.
//
bRet = QueryPerformanceFrequency(&m_PerfFreq);
ASSERT(bRet);
if(m_bTwoWire)
{
//
// Sleep for a couple milliseconds to wait for the codec to power up.
//
Sleep(4);
if(m_ulCodec == 4228)
{
//
// Using the CS4228 codec.
//
//
// Unmute the three DACs. Perform auto mute if the samples are zero.
//
WriteCodecReg(CS4228_DAC_MUTE2, MUTE2_MUTEZ);
//
// Set up clock ratios. MCLK = 4 * SCLK
// MCLK = 4 * 64 *LRCLK = 128
//
WriteCodecReg(CS4228_CLOCK_MODE, CLOCK_MODE_BASERATE_256);
//
// Power up the chip - all dacs and the adc powered up.
//
WriteCodecReg(CS4228_CHIP_CNTL, CHIP_CNTL_NDIGPN);
//
// Unmute the three DACs
//
WriteCodecReg(CS4228_DAC_MUTE1, 0);
//
// Set ADC serial mode.
//
// SCLK = 64 * LRCLK
// Put the EP9312 as the master.
// Put in 24 bit left I2S mode.
//
WriteCodecReg
(
CS4228_SERIAL_MODE,
SERIAL_MODE_DCK_B64 | SERIAL_MODE_DMS_SLAVE | SERIAL_MODE_DDF_I2S_24BIT
);
}
else
{
//
// The driver supports CS4228 and CS4271. So, treat this as a CS4271.
//
//
// Write to the control port, setting the enable control port bit
// so that we can write to the control port...
//
WriteCodecReg
(
CS4271_MODE_CNTL2,
0x02
);
//
// Select slave, 24Bit I2S
//
WriteCodecReg
(
CS4271_MODE_CNTL,
0x01
);
//
// Select 24Bit I2S
//
WriteCodecReg
(
CS4271_ADC_CNTL,
0x10
);
}
ReadAllCodecReg();
}
else
{
//
// Reconfigure the SPI so that we can setup our codec
//
SetSPIToI2S(m_ulCodec);
if(m_ulCodec == 4228)
{
//
// Using the CS4228 codec.
//
//
// Unmute the three DACs. Perform auto mute if the samples are zero.
//
WriteCodecRegSPI(CS4228_DAC_MUTE2, MUTE2_MUTEZ);
//
// Set up clock ratios. MCLK = 4 * SCLK
// MCLK = 4 * 64 *LRCLK = 128
//
WriteCodecRegSPI(CS4228_CLOCK_MODE, CLOCK_MODE_BASERATE_256);
//
// Power up the chip - all dacs and the adc powered up.
//
WriteCodecRegSPI(CS4228_CHIP_CNTL, CHIP_CNTL_NDIGPN);
//
// Unmute the three DACs
//
WriteCodecRegSPI(CS4228_DAC_MUTE1, 0);
//
// Set ADC serial mode.
//
// SCLK = 64 * LRCLK
// Put the EP9312 as the master.
// Put in 24 bit I2S mode.
//
WriteCodecRegSPI
(
CS4228_SERIAL_MODE,
SERIAL_MODE_DCK_H32 | SERIAL_MODE_DMS_SLAVE | SERIAL_MODE_DDF_I2S_24BIT
// SERIAL_MODE_DCK_B64 | SERIAL_MODE_DMS_SLAVE | SERIAL_MODE_DDF_I2S_24BIT
);
}
else
{
//
// The driver supports CS4228 and CS4271. So, treat this as a CS4271.
//
//
// For the 4271 (on the 930x boards), we need to reset the codec
// so we can bring it out of standalone mode and configure it.
// First, clear bit 1 of the data register
//
HalWriteCommonReg
(
GPIO_PADR,
0x02,
0x00
);
//
// Set bit 1 of the DDR to set it to output
// Now we are driving the reset pin low.
//
HalWriteCommonReg
(
GPIO_PADDR,
0x02,
0x02
);
Sleep(2);
//
// Set bit 1 of the data reg. Now we drive the reset pin high.
//
HalWriteCommonReg
(
GPIO_PADR,
0x02,
0x02
);
Sleep(1);
//
// Write to the control port, setting the enable control port bit
// and the PDN bit - so that we can write to the control port...
//
WriteCodecRegSPI
(
CS4271_MODE_CNTL2,
0x03
);
//
// Select slave, 24Bit I2S
//
WriteCodecRegSPI
(
CS4271_MODE_CNTL,
0x01
);
//
// Select 24Bit I2S
//
WriteCodecRegSPI
(
CS4271_ADC_CNTL,
0x10
);
//
// Ummute and set volumes to mid-range
//
WriteCodecRegSPI
(
CS4271_DACA_VOL,
0x40
);
WriteCodecRegSPI
(
CS4271_DACB_VOL,
0x40
);
//
// Clear the PDN bit and bring the codec up with our changes
//
WriteCodecRegSPI
(
CS4271_MODE_CNTL2,
0x02
);
}
//
// Done with setup, configure SPI to handle PS2
//
SetSPIToPS2(m_ulCodec);
}
FUNC_I2S((L"-I2SCodec::Initialize\r\n"));
return (MMSYSERR_NOERROR);
}
//****************************************************************************
// I2SCodec::SetRecordSampleRate
//****************************************************************************
// Sets the Record Sample Rate.
//
// ulFreq - Sample Rate
// ulChannel - Setting the Sample Rate for a specific channel.
//
MMRESULT I2SCodec::SetRecordSampleRate(ULONG ulFrequency, ULONG ulChannel)
{
//
// Check to see if we are playing audio.
//
if( m_ulCurrentFreq != ulFrequency)
{
return MMSYSERR_ALLOCATED;
}
return (MMSYSERR_NOERROR);
}
//****************************************************************************
// I2SCodec::SetPlaybackSampleRate
//****************************************************************************
// Sets the Sample Rate.
//
// ulFreq - Sample Rate
// ulChannel - Setting the Sample Rate for a specific channel.
//
MMRESULT I2SCodec::SetPlaybackSampleRate(ULONG ulFrequency, ULONG ulChannel)
{
//
// Check to see if we are playing audio.
//
if( m_ulCurrentFreq != ulFrequency)
{
return MMSYSERR_ALLOCATED;
}
return (MMSYSERR_NOERROR);
}
//****************************************************************************
// I2SCodec::SetSampleRate
//****************************************************************************
// Sets the Sample Rate.
//
// ulFreq - Sample Rate
// ulChannel - Setting the Sample Rate for a specific channel.
//
MMRESULT I2SCodec::SetSampleRate(ULONG ulFrequency, ULONG ulChannel)
{
ULONG ulRequestedMClkFreq;
ULONG ulMClkFreq1, ulMClkFreq2;
ULONG ulI2SDiv, ulI2SDiv1, ulI2SDiv2;
FUNC_I2S((L"+I2SCodec::SetSampleRate\r\n"));
ulRequestedMClkFreq = ( ulFrequency * m_ulM2SClock * m_ulS2LRClock);
CalculateClosestFreq
(
PLL1_CLOCK,
ulRequestedMClkFreq,
&ulMClkFreq1,
&ulI2SDiv1
);
CalculateClosestFreq
(
PLL2_CLOCK,
ulRequestedMClkFreq,
&ulMClkFreq2,
&ulI2SDiv2
);
//
// See which is closer, MClk rate 1 or MClk rate 2.
//
if(abs(ulMClkFreq1 - ulRequestedMClkFreq) < abs(ulMClkFreq2 -ulRequestedMClkFreq))
{
ulI2SDiv = ulI2SDiv1;
m_ulActualFreq = ulMClkFreq1/ (m_ulM2SClock * m_ulS2LRClock);
}
else
{
ulI2SDiv = ulI2SDiv2 | I2SDIV_PSEL;;
m_ulActualFreq = ulMClkFreq1 / (m_ulM2SClock * m_ulS2LRClock);
}
//
// Calculate the new I2S rate.
//
HalWriteCommonReg
(
CSC_I2SDIV,
0xFFFFFFFF,
ulI2SDiv |I2SDIV_SENA | I2SDIV_ORIDE | I2SDIV_SPOL|
I2SDIV_LRDIV_64 | I2SDIV_SDIV | I2SDIV_MENA | I2SDIV_ESEL
);
//
// Save off the requested frequency.
//
m_ulCurrentFreq = ulFrequency;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -