📄 hssi.c
字号:
BOOL bPrint )
{
DWORD dwSize;
BYTE bData;
unsigned char Buffer[2];
dwSize = 2;
Buffer[0] = CS4226_WriteADDR;
Buffer[1] = codec_Map;
WriteFile(hCom, (LPVOID)Buffer, dwSize, &dwSize, NULL);
if ( !dwSize ){
DEBUGMSG(ZONE_ERROR, (TEXT("I2C_ReadCODEC(Write) Error! : <I2C 0x%02x> %02x (%d)\r\n"), CS4226_WriteADDR, codec_Map, GetLastError()));
}
dwSize = 1;
Buffer[0] = CS4226_ReadADDR;
ReadFile(hCom, (LPVOID)Buffer, dwSize, &dwSize, NULL);
if ( !dwSize ){
DEBUGMSG(ZONE_ERROR, (TEXT("I2C_ReadCODEC(Read) Error! : <I2C 0x%02x> %02x (%d)\r\n"), CS4226_ReadADDR, codec_Map, GetLastError()));
}
else{
bData = Buffer[0];
if ( bPrint == TRUE ){
DEBUGMSG(ZONE_TEST, (TEXT("<I2C 0x%02x> Address : 0x%02x Data : 0x%02x\r\n"), CS4226_ReadADDR, codec_Map, bData));
}
}
return bData;
}
/*****************************************************************************
* FUNCTION : I2C_SetCODEC
* DESCRIPTION : set data to cs4226 codec
* INPUTS : I2Cdata [][0] cs4226 register address
* [][1] cs4226 register data
* last entry must be (CODEC_NONE, 0)
* OUTPUTS : Return TRUE for success, FALSE for failure
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
BOOL
I2C_SetCODEC(
unsigned char I2Cdata[][2]
)
{
DWORD n;
HANDLE hI2C;
DWORD dwData;
DWORD dwRet;
FUNC_WPDD("+I2C_SetCODEC");
// Get I2C Channel for contol CS4226
hI2C = CreateFile( TEXT("I2C1:"),
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( hI2C == INVALID_HANDLE_VALUE ){
// RETAILMSG(ZONE_TEST, (TEXT("Error: I2C open %d\r\n"), GetLastError()));
return FALSE;
}
dwData = I2C_MASTER_MODE;
DeviceIoControl(hI2C, IOCTL_I2C_SET_MODE,
(PVOID)&dwData, sizeof(DWORD), NULL, 0, &dwRet, NULL);
// Set I2C to standard speed mode. (100kbps)
#ifdef I2C_STANDARD_SPEED
// 100kHz
dwData = 19<<2; // SCGD
dwData |= 2; // CDF
#else
// 400kHz
dwData = 3<<2; // SCGD
dwData |= 2; // CDF
#endif
DeviceIoControl(hI2C, IOCTL_I2C_SET_BAUDRATE,
(PVOID)&dwData, sizeof(DWORD), NULL, 0, &dwRet, NULL);
dwData = I2C_SINGLE_STAGE;
DeviceIoControl(hI2C, IOCTL_I2C_SET_BUFFER_MODE,
(PVOID)&dwData, sizeof(DWORD), NULL, 0, &dwRet, NULL);
for(n=0;;n++){
if ( I2Cdata[n][0] == CODEC_NONE )
break;
do {
if ( I2C_WriteCODEC(hI2C, I2Cdata[n][0], I2Cdata[n][1]) == FALSE ){
CloseHandle( hI2C );
return FALSE;
}
}while( I2C_ReadCODEC(hI2C, I2Cdata[n][0], FALSE) != I2Cdata[n][1] );
I2C_ReadCODEC(hI2C, I2Cdata[n][0], TRUE);
}
BusyWait(AdjustMicroSecondsToLoopCount( I2C_WAIT_COUNT )); // wait 10ms
// read codec status
I2C_ReadCODEC(hI2C, CODEC_DAC_SRB, TRUE); // DAC Status Report Byte(Read Only)(0Ah)
I2C_ReadCODEC(hI2C, CODEC_ADC_SRB, TRUE); // ADC Status Report Byte(Read Only)(0Dh)
I2C_ReadCODEC(hI2C, CODEC_RSB, TRUE); // Receiver Status Byte(Read Only)(11h)
CloseHandle( hI2C );
FUNC_WPDD("-I2C_SetCODEC");
return TRUE;
}
/*****************************************************************************
* FUNCTION : hssi2_dmastart
* DESCRIPTION : DMA(HSSI2 Tx) Start
* INPUTS : None
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
void hssi2_dmastart()
{
DWORD value; // value for register setting
FUNC_WPDD("+hssi2_dmastart");
// clear play DMA buffer
memset(pAudioBufferBase, 0, AUDIO_DMA_PAGE_SIZE * 2);
// DMA Control Register Setting
value = DCR_DPDS_32BIT |
DCR_DDRMD_MODULE |
DCR_DPDAM_FIX |
DCR_DMDL_PERIPHERAL |
DCR_SPDS_32BIT |
DCR_SDRMD_MODULE |
DCR_SPDAM_INCREMENT |
DCR_SMDL_MEMORY |
DCR_DIP_2PAGE |
DCR_ACMD_ENABLE |
DCR_CT_ENABLE |
DCR_PKMD_DISABLE |
DCR_BTMD_DISABLE |
DCR_DTAU_BYTE |
DCR_DTAC_DISABLE |
DCR_DTAMD_PIN ;
dma_SetControl(pDMA_out, value);
// DMA-TransferCompleteInterrupts Enable
dma_InterruptEnable(pDMA_out);
// DMA Enable & Next Request Enable
value = DCMDR_DMEN;
dma_SetCommand(pDMA_out, value);
FUNC_WPDD("-hssi2_dmastart");
}
/*****************************************************************************
* FUNCTION : hssi2_dmastop
* DESCRIPTION : DMA(HSSI2 Tx) Stop
* INPUTS : None
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
void hssi2_dmastop()
{
FUNC_WPDD("+hssi2_dmastop");
// DMA Transfer Stop
dma_Stop(pDMA_out);
FUNC_WPDD("+hssi2_dmastop");
}
/*****************************************************************************
* FUNCTION : check_PlayInRec
* DESCRIPTION : Check Playback in Recording(simultaneously)
* INPUTS : PlayFlag - device open flag for playback
* RecFlag - device open flag for recording
* OUTPUTS : Return MMSYSERR_NOERROR for success, other for failure
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
MMRESULT
check_PlayInRec(
int PlayFlag,
int RecFlag
)
{
MMRESULT mmRet = MMSYSERR_NOERROR;
if (CS4226_ReadADDR == SSI1_CS4226_ReadADDR && RecFlag == 1 ){
mmRet = MMSYSERR_NOMEM;
}
return mmRet;
}
/*****************************************************************************
* FUNCTION : check_RecInPlay
* DESCRIPTION : Check Recording in Playback(simultaneously)
* INPUTS : PlayFlag - device open flag for playback
* RecFlag - device open flag for recording
* OUTPUTS : Return MMSYSERR_NOERROR for success, other for failure
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
MMRESULT
check_RecInPlay(
int PlayFlag,
int RecFlag
)
{
MMRESULT mmRet = MMSYSERR_NOERROR;
#if ENABLE_HAC == 1
// HSSI0 only for HAC&HSSI
return(MMSYSERR_BADDEVICEID);
#endif
if (CS4226_ReadADDR == SSI1_CS4226_ReadADDR && PlayFlag == 1 ){
mmRet = MMSYSERR_NOMEM;
}
return mmRet;
}
/*****************************************************************************
* FUNCTION : MuteSSI
* DESCRIPTION : Mute SSI codec
* INPUTS : None
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
void MuteSSI(BOOL bMute)
{
unsigned char I2CMute[2][2] = {
{CODEC_DAC_CB, CS4226_DACCB_NORMAL}, // 0:(03h)DAC Control Byte
{CODEC_NONE, 0x00}}; // 1:delimiter
DEBUGMSG(ZONE_TEST,(TEXT("MuteSSI %d\r\n"),bMute));
if(bMute){
I2CMute[0][1] = CS4226_DACCB_MUTE;
}
else{
I2CMute[0][1] = CS4226_DACCB_NORMAL;
}
if(ulDACControl == I2CMute[0][1]){
return;
}
if(I2C_SetCODEC(I2CMute)){
ulDACControl = I2CMute[0][1];
}
}
/*****************************************************************************
* FUNCTION : UpdateInputSelect
* DESCRIPTION : UpdateInputSelect
* INPUTS : None
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
void UpdateInputSelect(void)
{
ULONG volume, regval;
unsigned char ulLVol, ulRVol;
switch (g_VolumeSettings.dwInputSelect) {
case WPDMX_LINE_MIC:
if (g_VolumeSettings.fMicMute) {
volume = 0;
}
else {
volume = g_VolumeSettings.dwMicVolume & 0xffff;
volume = volume | (volume << 16); // incoming volume is mono, cvt. to stereo
}
break;
case WPDMX_LINE_IN:
if (g_VolumeSettings.fLineInMute) {
volume = 0;
}
else {
volume = g_VolumeSettings.dwLineInVolume;
}
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("UpdateInputSelect: illegal setting %04x\r\n"), g_VolumeSettings.dwInputSelect));
return;
}
ulLVol = (unsigned char)((LOWORD(volume) & 0xc000)>>14);
ulRVol = (unsigned char)((HIWORD(volume) & 0xc000)>>12);
regval = ulLVol | ulRVol;
DEBUGMSG(ZONE_TEST, (TEXT("UpdateInputSelect: vol=%04x\r\n"), regval));
codec_updateRecordGain( regval );
}
/*****************************************************************************
* FUNCTION : private_SetMixerValue
* DESCRIPTION : Set Mixer Value
* INPUTS : None
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
MMRESULT
private_SetMixerValue(DWORD dwControl, DWORD dwSetting)
{
DWORD dwControlType = dwSetting & WPDMX_CTL_MASK;
DWORD dwLine = dwSetting & WPDMX_LINE_MASK;
DEBUGMSG(ZONE_TEST, (TEXT("private_SetMixerValue(%04x, %08x)\r\n"), dwControl, dwSetting));
switch (dwControl) {
// volume controls
case WPDMX_MASTER_VOL:
private_waveOutSetVolume(dwSetting);
break;
case WPDMX_LINEIN_VOL:
if (CS4226_ReadADDR == SSI1_CS4226_ReadADDR){
return MMSYSERR_NOTSUPPORTED;
}
g_VolumeSettings.dwLineInVolume = dwSetting;
UpdateInputSelect();
break;
case WPDMX_MIC_VOL:
return MMSYSERR_NOTSUPPORTED;
// Mute controls
case WPDMX_MASTER_MUTE:
g_VolumeSettings.fMasterMute = dwSetting;
SetMute(g_VolumeSettings.fMasterMute);
break;
case WPDMX_LINEIN_MUTE:
if (CS4226_ReadADDR == SSI1_CS4226_ReadADDR){
return MMSYSERR_NOTSUPPORTED;
}
g_VolumeSettings.fLineInMute = dwSetting;
UpdateInputSelect();
break;
case WPDMX_MIC_MUTE:
//CODEC does not have a function
return MMSYSERR_NOTSUPPORTED;
// The input Mux
case WPDMX_INPUT_MUX:
if ((CS4226_ReadADDR == SSI1_CS4226_ReadADDR && dwSetting == WPDMX_LINE_IN) ||
(CS4226_ReadADDR == SSI2_CS4226_ReadADDR && dwSetting == WPDMX_LINE_MIC)){
return MMSYSERR_NOTSUPPORTED;
}
g_VolumeSettings.dwInputSelect = dwSetting;
UpdateInputSelect();
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("private_SetMixerValue: unsupported control %d\r\n"), dwControl));
return MMSYSERR_NOTSUPPORTED;
}
return MMSYSERR_NOERROR;
}
VOID codec_updateRecordGain( ULONG regval )
{
unsigned char I2CGain[2][2] = {
{CODEC_ICB, 0x0f}, // 0:(0Ch)Input Control Byte(GNL1乣GNL0,GNR1乣GNR0)
{CODEC_NONE, 0x00}}; // 1:delimiter
DEBUGMSG(ZONE_TEST,(TEXT("codec_updateRecordGain 0x%08x\r\n"),regval));
I2CGain[0][1] = (unsigned char)regval;
I2C_SetCODEC(I2CGain);
return;
}
/*****************************************************************************
* FUNCTION : private_SetDefaultVolume
* DESCRIPTION : Set master volume and default input
* INPUTS : None
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
void private_SetDefaultVolume()
{
if (CS4226_ReadADDR == SSI1_CS4226_ReadADDR){
#if !(ENABLE_HAC == 1)
// Set the global master volume to max
private_waveOutSetVolume(0xffffffff);
// set default for input
private_SetMixerValue(WPDMX_INPUT_MUX, WPDMX_LINE_MIC);
private_SetMixerValue(WPDMX_MIC_VOL, 0xAAAAAAAA);
private_SetMixerValue(WPDMX_MIC_MUTE, 0);
#else
// Set the global master volume to WinCE default(same as HAC)
private_waveOutSetVolume(0xAC85AC85);
#endif
}
else{
// Set the global master volume to WinCE default
private_waveOutSetVolume(0x99999999);
// set default for input
private_SetMixerValue(WPDMX_INPUT_MUX, WPDMX_LINE_IN);
private_SetMixerValue(WPDMX_LINEIN_VOL, 0xAAAAAAAA);
private_SetMixerValue(WPDMX_LINEIN_MUTE, 0);
}
}
void waitSSIStatus(PVULONG pSSI_SR, ULONG stat)
{
ULONG RegValue;
do{
RegValue = READ_REGISTER_ULONG(pSSI_SR);
}while((RegValue & stat) != stat);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -