📄 nim_audio.c
字号:
inputL3Params.data = &inputL3Regs[0];
err = tda1315InitInput(&inputL3Params, param);
aiDisableSER_MASTERM(AI2_STATUS); /* tda1315 is master of clock */
microsleep(10); /* wait until internal state of audio in unit is stable */
if (err == TMLIBDEV_OK)
{
aiSetCAP_MODEM(AI2_STATUS, 3); /* Stereo 16 bits per sample */
aiDisableSIGN_CONVERTM(AI2_STATUS);
aiMsbFirstM(AI2_STATUS); /* MSB first */
aiSetFRAMEMODEM(AI2_STATUS, 0); /* ignore valid bit */
aiSampleRisingCLOCK_EDGEM(AI2_STATUS); /* sample on rising edge */
aiStartFallingEdgeWSM(AI2_STATUS);
aiSetSSPOSM(AI2_STATUS, 0);
aiSetLEFTPOSM(AI2_STATUS, 0);
aiSetRIGHTPOSM(AI2_STATUS, 32);
aiSetSIZEM(AI2_STATUS, param->size);
#ifdef __LITTLE_ENDIAN__
aiEnableLITTLE_ENDIANM(AI2_STATUS);
#else
aiDisableLITTLE_ENDIANM(AI2_STATUS);
#endif
}
else goto nim_AI2_InitExit;
nimAi2Input = aaaDigitalInput;
break;
#endif
case aaaAuxInput1: /* tuner audio in, use CS5331 */
case aaaLineInput: /* use CS5331 */
if (nimBoardRevision2)
{
err = iicReadReg(AUDIO_SELECT_ID_EXPANDER_ADDRESS, -1, &iicd);
tmAssert(err == TMLIBDEV_OK, err);
iicd &= ~NIM_AUDIO_SELECT_MASK;
if (param->input == aaaAuxInput1)
iicd |= NIM_AUDIO_SELECT_TUNER;
else
iicd |= NIM_AUDIO_SELECT_ANALOG;
err = iicWriteReg(AUDIO_SELECT_ID_EXPANDER_ADDRESS, -1, iicd);
tmAssert(err == TMLIBDEV_OK, err);
}
else
{
if (param->input == aaaAuxInput1)
return AIO_ERR_UNSUPPORTED_INPUT; /* tuner is only supported on rev2 */
}
aiDisableSER_MASTERM(AI2_STATUS); /* TM is master of clock */
microsleep(2); /* wait until internal state of audio in unit is stable */
/* set powerdown for input TDA1315 to one (disable it) */
err = iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd |= NIM_TDA1315_IN_IIC_POWERDOWN;
/* Enable clock to the requested ADC */
iicd &= ~(NIM_TDA1315_IN_IIC_TUNER_AUDIO | NIM_TDA1315_IN_IIC_ANALOG_AUDIO);
if (param->input == aaaAuxInput1)
iicd |= (NIM_TDA1315_IN_IIC_TUNER_AUDIO);
else
iicd |= (NIM_TDA1315_IN_IIC_ANALOG_AUDIO);
err |= iicWriteReg(INPUT_IIC_EXPANDER_ADDRESS, -1, iicd);
if (err) goto nim_AI2_InitExit;
microsleep(1000);
aiSetWSDIVM(AI2_STATUS, 63);
aiSetSCKDIVM(AI2_STATUS, 3);
aiSetCAP_MODEM(AI2_STATUS, 3); /* Stereo 16 bits per sample */
aiDisableSIGN_CONVERTM(AI2_STATUS);
aiMsbFirstM(AI2_STATUS); /* MSB first */
aiSetFRAMEMODEM(AI2_STATUS, 0); /* ignore valid bit */
aiSampleRisingCLOCK_EDGEM(AI2_STATUS); /* sample on rising edge */
aiStartFallingEdgeWSM(AI2_STATUS); /* left sample starts on neg. AI_WS */
aiSetSSPOSM(AI2_STATUS, 0);
aiSetLEFTPOSM(AI2_STATUS, 0);
aiSetRIGHTPOSM(AI2_STATUS, 32);
aiSetSIZEM(AI2_STATUS, param->size);
#ifdef __LITTLE_ENDIAN__
aiEnableLITTLE_ENDIANM(AI2_STATUS);
#else
aiDisableLITTLE_ENDIANM(AI2_STATUS);
#endif
nimAi2Input = aaaLineInput;
break;
default:
err = AIO_ERR_UNSUPPORTED_INPUT;
goto nim_AI2_InitExit;
}
/* store parameters */
nimAi2AudioTypeFormat = param->audioTypeFormat;
nimAi2AudioSbtypeFormat = param->audioSubtypeFormat;
nimAi2SRate = param->sRate;
nimAi2Size = param->size;
nim_AI2_InitExit:
iicDirectionUnSelect(IIC_DIRECTION_NIM2);
return err;
}
/* called in aiClose(). Should leave audio input system shut down */
extern tmLibdevErr_t nim_AI2_Term(void)
{
return TMLIBDEV_OK;
}
/* called in aiStart(). */
extern tmLibdevErr_t nim_AI2_Start(void)
{
aiEnableCAP_ENABLEM(AI2_STATUS);
return TMLIBDEV_OK;
}
/* called in aiStop(). */
extern tmLibdevErr_t nim_AI2_Stop(void)
{
aiDisableCAP_ENABLEM(AI2_STATUS);
return TMLIBDEV_OK;
}
/* called from aiSetSampleRate(). */
extern tmLibdevErr_t nim_AI2_SetSrate(Float sRate)
{
Float val;
/* it's not possible to change the input rate for digital input */
if (nimAi2Input == aaaDigitalInput)
{
return TMLIBDEV_OK;
}
val = sRate * 256.0; /* oversampling clock is 256 * fs */
if (use9xMode)
{
val = 0.5 + (477218588.0 * (val / CPUClock)); /* 2**32 / 9 */
aiSetFREQM(AI2_STATUS, ((UInt) val) | 0x80000000);
}
else
{
val = 0.5 + (1431655765.0 * (val / CPUClock)); /* 2**32 / 3 */
aiSetFREQM(AI2_STATUS, (UInt) val);
}
return TMLIBDEV_OK;
}
/* called from aiGetSampleRate().
* Should return an accurate value from the hardware.
*/
extern tmLibdevErr_t nim_AI2_GetSrate(Float * sRate)
{
UInt iicd;
Int err = TMLIBDEV_OK;
tmAssert(sRate, TMLIBDEV_ERR_NULL_PARAMETER);
if (nimAi2Input == aaaDigitalInput)
{
err = iicDirectionSelect(IIC_DIRECTION_NIM2);
if (err != TMLIBDEV_OK)
return err;
err = iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd |= NIM_TDA1315_IN_IIC_FREQUENCY_MASK;
iicd &= ~(NIM_TDA1315_IN_IIC_LOCK); /* hold lock low to mask it */
err |= iicWriteReg(INPUT_IIC_EXPANDER_ADDRESS, -1, iicd);
err |= iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd &= NIM_TDA1315_IN_IIC_FREQUENCY_MASK;
DP(("nim_AI2_GetSrate: Read %x from %x (%x)\n", iicd, INPUT_IIC_EXPANDER_ADDRESS, err));
iicDirectionUnSelect(IIC_DIRECTION_NIM2);
if (err) return err;
switch (iicd)
{
case NIM_TDA1315_IN_IIC_44100_HZ:
*sRate = 44100.0;
break;
case NIM_TDA1315_IN_IIC_48000_HZ:
*sRate = 48000.0;
break;
case NIM_TDA1315_IN_IIC_32000_HZ:
*sRate = 32000.0;
break;
default:
*sRate = 0.0;
break;
}
}
else
{
if (use9xMode)
{
*sRate = (Float) (MMIO(AI2_STATUS + AI_FREQ_OFFSET) & 0x7fffffff) * CPUClock / 477218588.0 / 256.0;
}
else
{
*sRate = (Float) MMIO(AI2_STATUS + AI_FREQ_OFFSET) * CPUClock / 1431655765.0 / 256.0;
}
}
return TMLIBDEV_OK;
}
/* called from aiSetInput() */
extern tmLibdevErr_t nim_AI2_SetInput(tmAudioAnalogAdapter_t input)
{
boardAIParam_t param;
UInt err;
static Bool capEnable = False;
UInt32 buf1 = MMIO(AI2_STATUS + AI_BASE1_OFFSET);
UInt32 buf2 = MMIO(AI2_STATUS + AI_BASE2_OFFSET);
UInt32 size = MMIO(AI2_STATUS + AI_SIZE_OFFSET);
UInt32 aiIntControl = MMIO(AI2_STATUS + AI_CTL_OFFSET) & (AI_BUF1_INTEN | AI_BUF2_INTEN | AI_OVR_INTEN | AI_HBE_INTEN);
/* check if we realy have to change the input */
if (input == nimAi2Input)
{
return TMLIBDEV_OK;
}
/* stop audio in */
if (MMIO(AI2_STATUS + AI_CTL_OFFSET) & AI_CAP_ENABLE)
{
aiDisableCAP_ENABLEM(AI2_STATUS);
capEnable = True;
}
param.audioTypeFormat = nimAi2AudioTypeFormat;
param.audioSubtypeFormat = nimAi2AudioSbtypeFormat;
param.sRate = nimAi2SRate;
param.size = nimAi2Size;
param.input = input;
nimAi2Input = input;
err = nim_AI2_Init(¶m);
/* restore MMIO registers */
MMIO(AI2_STATUS + AI_BASE1_OFFSET) = buf1;
MMIO(AI2_STATUS + AI_BASE2_OFFSET) = buf2;
MMIO(AI2_STATUS + AI_SIZE_OFFSET) = size;
MMIO(AI2_STATUS + AI_CTL_OFFSET) |= aiIntControl;
if (err)
{
return err;
}
if (capEnable)
{
aiEnableCAP_ENABLEM(AI2_STATUS);
}
return TMLIBDEV_OK;
}
/* called from aiGetInput() */
extern tmLibdevErr_t nim_AI2_GetInput(tmAudioAnalogAdapter_t * input)
{
tmAssert(input, TMLIBDEV_ERR_NULL_PARAMETER);
*input = nimAi2Input;
return TMLIBDEV_OK;
}
/* called from aiGetInputFormat */
extern tmLibdevErr_t nim_AI2_GetFormat(ptmAudioFormat_t inputFormat)
{
Float sRate;
Int err;
Char statusReg[2] = {0,0};
/* initialize the inputFormat */
inputFormat->size = sizeof(tmAudioFormat_t);
inputFormat->dataClass = avdcAudio;
inputFormat->dataType = atfNone;
inputFormat->dataSubtype = apfNone;
inputFormat->sampleRate = 0.0;
/* get sample rate, if sample rate is 0.0 -> TDA 1315 is not locked */
err = nim_AI2_GetSrate(&sRate);
if (err) return err;
if (sRate == 0.0)
{
return TMLIBDEV_OK;
}
inputFormat->sampleRate = sRate;
inputFormat->dataType = atfLinearPCM;
inputFormat->dataSubtype = apfStereo16;
return TMLIBDEV_OK;
#if 0
/* get channel status information:
* In order for this to work, we need to run the 1315 in uP mode,
* and then the setup has to be changed
*/
err = iicDirectionSelect(IIC_DIRECTION_NIM2);
if (err != TMLIBDEV_OK)
return err;
inputL3Params.data = statusReg;
err = tda1315AccessL3(&inputL3Params, READ_CHANNEL_STATUS_REGISTER);
iicDirectionUnSelect(IIC_DIRECTION_NIM2);
if (err)
return err;
if ((statusReg[0] & TDA1315_L3_CHAN_STAT_DATA_MASK) == TDA1315_L3_CHAN_STAT_DATA)
{
inputFormat->dataType = atf1937;
inputFormat->dataSubtype = apfGeneric;
}
return err;
#endif
}
/* a backdoor to support features not forseen in the initial design */
extern tmLibdevErr_t nim_AI2_Config(UInt32 subaddr, Pointer value)
{
return TMLIBDEV_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -