📄 hwctxt.cpp
字号:
m_vpAudioXmitA->DSADR= (UINT32)(m_Output_pbDMA_PAGES_Physical[0]); // destination address of the XmitA buffer
m_vpAudioXmitA->DCMD = CmdBuff.DcmdDword ; // size and cmd values of the XmitA buffer
//
// fill XmitB Descriptor
//
m_vpAudioXmitB->DDADR= (UINT32)m_vpAudioXmitA_Physical; // address of the next (XmitA) descriptor
m_vpAudioXmitB->DTADR= DMAC_AC97_AUDIO_XMIT_FIFO; // source address of the AC97 XmitB buffer
m_vpAudioXmitB->DSADR= (UINT32)(m_Output_pbDMA_PAGES_Physical[1]) ; // destination address of the XmitB buffer
m_vpAudioXmitB->DCMD = CmdBuff.DcmdDword ; // size and cmd values of the XmitB buffer
return TRUE;
}
//------------------------------------------------------------------------------------------------------------
// Function: FillDescriptors
//
// Purpose: Fill the descriptors with appropriate data
//
// Note: This code could be cleaner, but I want to be explicit on the programming of descriptors
//
//-------------------------------------------------------------------------------------------------------------
BOOL HardwareContext::FillInputDescriptors( void )
{
union DmaCmdReg CmdBuff;
memset (&CmdBuff,0, sizeof (CmdBuff));
// set individual bit fields to for debug.
#define USE_BITFIELD
#ifdef USE_BITFIELD
// set values with bit fields
CmdBuff.DcmdReg.len = AUDIO_BUFFER_SIZE; //length of the memory buffer
CmdBuff.DcmdReg.width = 0x3; // binary 11 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
CmdBuff.DcmdReg.size = 0x3; // binary 11
CmdBuff.DcmdReg.endian = 0; // little endian
CmdBuff.DcmdReg.flybyt = 0; // Flowthrough
CmdBuff.DcmdReg.flybys = 0; // Flowthrough
CmdBuff.DcmdReg.endirqen = 1; // 1 means Interrupt when decrement length = 0;
CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
CmdBuff.DcmdReg.flowtrg = 0; // 1 means the target is an external peripheral
CmdBuff.DcmdReg.flowsrc = 1; // 1 means the source is an external peripheral (and needs flow control)
CmdBuff.DcmdReg.inctrgadd = 1; // 1 means increment the target address (since it's memory)
CmdBuff.DcmdReg.incsrcadd = 0; // 1 means increment the source address (since it's a peripheral)
#else
// set value based on masks
CmdBuff.DcmdDword = DMAC_AC97_RCVAB_CMD_MASK | AUDIO_BUFFER_SIZE;
#endif
//
// fill RcvA Descriptor
//
m_vpAudioRcvA-> DDADR= (UINT32)m_vpAudioRcvB_Physical; // address of the next (RcvB) descriptor
m_vpAudioRcvA-> DTADR= (UINT32)(m_Input_pbDMA_PAGES_Physical[0]); // source address of the AC97 RcvA buffer
m_vpAudioRcvA-> DSADR= DMAC_AC97_AUDIO_RCV_FIFO; // destination address of the RcvA buffer
m_vpAudioRcvA-> DCMD = CmdBuff.DcmdDword ; // size and cmd values of the RcvA buffer
//
// fill RcvB Descriptor
//
m_vpAudioRcvB-> DDADR= (UINT32)m_vpAudioRcvA_Physical ; // address of the next (RcvA) descriptor
m_vpAudioRcvB-> DTADR= (UINT32)(m_Input_pbDMA_PAGES_Physical[1]); // source address of the AC97 RcvB buffer
m_vpAudioRcvB-> DSADR= DMAC_AC97_AUDIO_RCV_FIFO; // destination address of the RcvB buffer
m_vpAudioRcvB-> DCMD = CmdBuff.DcmdDword ; // size and cmd values of the RcvB buffer
return TRUE;
}
//------------------------------------------------------------------------------------------------------------
// Function: StopDmac
//
// Purpose: To stop DMA transmit
//-------------------------------------------------------------------------------------------------------------
void HardwareContext::StopDmac(int Channel)
{
m_pDMARegisters->DCSR[Channel] &= ~DCSR_RUN; //clear the run but
return;
}
//------------------------------------------------------------------------------------------------------------
// Function: ClearDmac
//
// Purpose: To clear DMA status
//-------------------------------------------------------------------------------------------------------------
VOID HardwareContext::ClearDmac(int Channel)
{
DWORD dwDCSR;
dwDCSR = m_pDMARegisters->DCSR[Channel];
if(dwDCSR & DCSR_STOPINTR)
{
dwDCSR &= ~DCSR_STOPIRQEN;
}
// Clear the status
m_pDMARegisters->DCSR[Channel] = dwDCSR;
return;
}
//------------------------------------------------------------------------------------------------------------
// Function: AC97SetSampleRate
//
// Purpose: Write the sample rate value to the ac97 codec
//-------------------------------------------------------------------------------------------------------------
BOOL HardwareContext::SetSampleRate(unsigned short int SampleRate, WAPI_INOUT apidir )
{
short int RetVal=TRUE;
unsigned short int value = 0;
switch(SampleRate)
{
case 8000:
value = UCB_DR_8000;
break;
case 11025:
value = UCB_DR_11025;
break;
case 16000:
value = UCB_DR_16000;
break;
case 22050:
value = UCB_DR_22050;
break;
case 32000:
value = UCB_DR_32000;
break;
case 44100:
value = UCB_DR_44100;
break;
case 48000:
value = UCB_DR_48000;
break;
default:
DEBUGCHK(0); //we sent a bad rate
RetVal=FALSE;
return (RetVal);
}
if (apidir == WAPI_IN)
RetVal=SafeWriteAC97((UINT16_T)AUDIO_ADC_RATE,value ); //set the input sample rate
else
RetVal=SafeWriteAC97((UINT16_T)AUDIO_DAC_RATE,value ); //set the output sample rate
return (RetVal);
}
void HardwareContext::DumpDmacRegs()
{
int i;
DEBUGMSG(ZONE_ERROR, (TEXT( "gsr %x, posr %x, pocr %x, pisr %x, picr %x\r\n" ),
m_pAc97regs->GSR,
m_pAc97regs->POSR,
m_pAc97regs->POCR,
m_pAc97regs->PISR,
m_pAc97regs->PICR
) );
for (i=0; i< 16; i++)
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->dcsr[%d] %x \r\n" ),i,m_pDMARegisters->DCSR[i] ) );
//skip rsvd section rsvd0[44];
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->dint %x \r\n" ),m_pDMARegisters->DINT ) );
//skip rsvd seciton rsvd1[3];
for (i=0; i< 39; i++)
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->drcmr[%d] %x \r\n" ),i,m_pDMARegisters->DRCMR[i] ) );
for (i=0; i<16; i++)
{
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].DDADR %x \r\n" ),i,m_pDMARegisters->DDG[i].DDADR ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].DSADR %x \r\n" ),i,m_pDMARegisters->DDG[i].DSADR ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].DTADR %x \r\n" ),i,m_pDMARegisters->DDG[i].DTADR ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].DCMD %x \r\n" ),i,m_pDMARegisters->DDG[i].DCMD ) );
}
}
void HardwareContext::InitCodec(void)
{
static DWORD VendorId=0;
unsigned short int VidTemp=0;
unsigned short int Ac97RegisterData=0;
unsigned short int FeatureCrs1Data=0;
DEBUGMSG(ZONE_INIT, (TEXT("HardwareContext::InitCodec\r\n")));
//Force VRA (variable rate audio) to be on
SafeWriteAC97(EXTENDED_AUDIO_CTRL, VRA_ENABLED_MASK);
//Default is AUDIO_MIC_INPUT_MONO
SafeWriteAC97(RECORD_SELECT, 0x0);
//Set the output volume from the OS
SafeWriteAC97(MASTER_VOLUME, 0);
//Set the record gain value. The ADC is 20-bit but AC97 PCDR register is only 16-bit.
//Setting to 0x0F0F might cause clipping.
SafeWriteAC97(RECORD_GAIN, 0x0808);
//Enable microphone Boost, but keep the line from mic to speakers muted.
SafeWriteAC97(MIC_VOLUME, 0x8040);
//Set bass and treble to a good sounding value
SafeWriteAC97(FEATURE_CSR1, 0x5400);
//Get vendor ID
if(VendorId == 0)
{
SafeReadAC97(VENDOR_ID1, &VidTemp);
VendorId= (VidTemp <<16); //ffffffffssssssss // f=first ascii s = second ascii
SafeReadAC97(VENDOR_ID2, &VidTemp);
VendorId |=VidTemp; //ttttttttrrrrrrrr //t = third ascii, r=rev #
VendorId &= 0xfffffff0;//trim of version number
}
//
//compliant codecs such as Crystal require the PCM volume
//if it's a ucb1400 then don't write the PCM volume (although it shouldn't hurt)
//
//vendor specific
switch (VendorId)
{
case 0x50534300: //philips UCB1400
SafeWriteAC97(FEATURE_CSR2, PWR_SMART_CODEC);
//
//CAREFULL, writing the FEATURE_CSR1 could mess up the touch screen
//
SafeReadAC97(FEATURE_CSR1,&Ac97RegisterData);
Ac97RegisterData = Ac97RegisterData & EQ_MASK; //get just EQ data
SafeReadAC97(FEATURE_CSR1,&FeatureCrs1Data);
//mask off eq data
FeatureCrs1Data = FeatureCrs1Data & 0x8000; // lob off reserved bit (must be 0)
FeatureCrs1Data = FeatureCrs1Data & ~EQ_MASK; // lob off eq data
FeatureCrs1Data = FeatureCrs1Data | Ac97RegisterData; // stored EQ data with actual Feature data
//comment out headphone enable to save power, use an app to turn it on instead
//HACK: If the capabiliters reads 0x2a0 it's rev 2a, if its 0x2a then its rev 1b.
SafeReadAC97(0, (UINT16 *)&m_ResetCaps);
if (m_ResetCaps==REV_2A)
{
FeatureCrs1Data = FeatureCrs1Data | (unsigned short) HPEN_MASK; //turn on head phone
m_CodecType=UCB14002A;
DEBUGMSG(ZONE_VERBOSE, (TEXT( "-- UCB14002A \r\n") ) );
}
else
{
m_CodecType=UCB14001B;
DEBUGMSG(ZONE_VERBOSE, (TEXT( "-- UCB14001b \r\n") ) );
}
SafeWriteAC97(FEATURE_CSR1, FeatureCrs1Data);
break;
default: //vanilla AC97
SafeWriteAC97(PCM_OUT_VOL, 0x1f1f);
DEBUGMSG(ZONE_VERBOSE, (TEXT( "-- vanilla AC97 \r\n") ) );
break;
}
return;
}
void HardwareContext::DeInitCodec(void)
{
DEBUGMSG(ZONE_INIT, (TEXT("HardwareContext::DeInitCodec\r\n")));
// Power down Codec
// SafeWriteAC97(AC97_CR_POWERDOWN_CTRL_STAT, 0x1000);
return;
}
void HardwareContext::PowerDown()
{
m_Sleeping=TRUE;
DEBUGMSG(ZONE_FUNCTION | ZONE_VERBOSE, (TEXT("WaveDev2: PowerDown\r\n")));
// Power down AC97 link
// UnConfigureAC97Control();
} // PowerDown()
void HardwareContext::PowerUp()
{
// Initialize GPIO and power up AC97 link
// ConfigureAC97Control();
// Clear DMA status
ClearDmac(m_RecordingChannel);
ClearDmac(m_PlaybackChannel);
InterruptDone(m_SysIntrAudioDMA);
if (TRUE == m_InPowerHandler)
{
m_Sleeping=FALSE;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("Wavedev:HardwareContext::PowerUp: Done\r\n")));
}
// Control the hardware speaker enable
void HardwareContext::SetSpeakerEnable(BOOL bEnable)
{
// Code to turn speaker on/off here
return;
}
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// RecalcSpeakerEnable decides whether to enable the speaker or not.
// For now, it only looks at the m_bForceSpeaker variable, but it could
// also look at whether the headset is plugged in
// and/or whether we're in a voice call. Some mechanism would
// need to be implemented to inform the wave driver of changes in the state of
// these variables however.
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
void HardwareContext::RecalcSpeakerEnable()
{
SetSpeakerEnable(m_NumForcedSpeaker);
}
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// SetForceSpeaker is called from the device context to update the state of the
// m_bForceSpeaker variable.
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
DWORD HardwareContext::ForceSpeaker( BOOL bForceSpeaker )
{
// If m_NumForcedSpeaker is non-zero, audio should be routed to an
// external speaker (if hw permits).
if (bForceSpeaker)
{
m_NumForcedSpeaker++;
if (m_NumForcedSpeaker==1)
{
RecalcSpeakerEnable();
}
}
else
{
m_NumForcedSpeaker--;
if (m_NumForcedSpeaker==0)
{
RecalcSpeakerEnable();
}
}
return MMSYSERR_NOERROR;
}
short int HardwareContext::MsgWriteAC97(DWORD dwParam1,DWORD dwParam2)
{
DEBUGMSG(ZONE_VERBOSE, (TEXT( "write %x %x \r\n" ),dwParam1,dwParam2));
SafeWriteAC97((BYTE)dwParam1,(unsigned short int)dwParam2 );
return (MMSYSERR_NOERROR);
}
short int HardwareContext::MsgReadAC97(DWORD dwParam1,DWORD dwParam2)
{
unsigned short int MyData=0;
DEBUGMSG(ZONE_VERBOSE, (TEXT( "read %x %x \r\n" ),dwParam1,MyData ));
SafeReadAC97((BYTE)dwParam1, &MyData);
if (dwParam2 != (unsigned short int) NULL)
* (unsigned short int *) dwParam2 = MyData;
return (MMSYSERR_NOERROR);
}
/*
#define RIL_AUDIO_NONE (0x00000000) // @constdefine No audio devices
#define RIL_AUDIO_HANDSET (0x00000001) // @constdefine Handset
#define RIL_AUDIO_SPEAKERPHONE (0x00000002) // @constdefine Speakerphone
#define RIL_AUDIO_HEADSET (0x00000003) // @constdefine Headset
#define RIL_AUDIO_CARKIT (0x00000004) // @constdefine Carkit
*/
BOOL HardwareContext::SetCfgHeadSet()
{
return TRUE;
}
BOOL HardwareContext::SetCfgHandSet()
{
return TRUE;
}
BOOL HardwareContext::SetCfgSpeakerPhone()
{
return TRUE;
}
BOOL HardwareContext::SetCfgCarKit()
{
return TRUE;
}
BOOL HardwareContext::SetCfgNone()
{
return TRUE;
}
//------------------------------------------------------------------------------------------------------------
// Function: MapDMADescriptors
//
// Purpose: Map the physical DMA Descriptors into virtual space
//
// Returns: TRUE indicates success. FALSE indicates failure
//
//-------------------------------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -