📄 dtv_ref2_audio.c
字号:
}
else if (sRate < 46050.0)
{
outputL3Regs[_CHANNEL_STATUS_REGISTER] |= TDA1315_L3_CHAN_STAT_44100_HZ;
}
else
{
outputL3Regs[_CHANNEL_STATUS_REGISTER] |= TDA1315_L3_CHAN_STAT_48000_HZ;
}
sRate = sRate * sckdiv * wsdiv * sfdiv;
/* double output clock for modes that require it (e.g. 8-channel 32-bits) */
if (dtvRef2DoubleDDSEnable)
{
sRate *= 2;
}
if (dtvRef2CPUisTM1100)
{
val = 0.5 + (477218588.0 * (sRate / dtvRef2CPUClock)); /* 2**32 / 9 */
aoSetFREQ(((UInt) val) | 0x80000000);
}
else
{
val = 0.5 + (1431655765.0 * (sRate / dtvRef2CPUClock)); /* 2**32 / 3 */
aoSetFREQ((UInt) val);
}
if (old_val != outputL3Regs[_CHANNEL_STATUS_REGISTER])
{
if (dtvRef2AoRunning)
{
outputL3Params.data = & outputL3Regs[_CHANNEL_STATUS_REGISTER];
err = tda1315AccessL3(&outputL3Params, WRITE_CHANNEL_STATUS_REGISTER);
}
else
{
dtvRef2AoNeedToConfigureTDA1315 = True;
}
}
return err;
}
/*******************************************************/
extern tmLibdevErr_t dtv_ref2_AO_GetSRate(Float * sRate)
{
UInt serial = MMIO(AO_SERIAL);
UInt freq = MMIO(AO_FREQ);
UInt sckdiv = 1 + aoExtractSCKDIV(serial);
UInt wsdiv = 1 + aoExtractWSDIV(serial);
UInt sfdiv = 1 + aoExtractSFDIV(serial);
Float rate;
if (dtvRef2CPUisTM1100)
{
rate = (Float) (freq & 0x7fffffff) * dtvRef2CPUClock / 477218588.0;
}
else
{
rate = (Float) freq * dtvRef2CPUClock / 1431655765.0;
}
rate = rate / ((Float) sckdiv * (Float) wsdiv * (Float) sfdiv);
*sRate = rate;
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtv_ref2_AO_Config(UInt32 subaddr, Pointer value)
{
return AIO_ERR_COMMAND_NOT_SUPPORTED;
}
/************************** INPUT **********************************/
/* Input IIC expander, the interrupt pin of this iic expander (low active) is
connected to the user IRQ pin of the TriMedia. An interrupt is generated when
the level changes on one of its inputs.
address 0x72
bit 0 unused
bit 1 unused
bit 2 copyprotection input
bit 3 powerdown output
bit 4 lock/unlock input
bit 5 48.0 kHz input
bit 6 44.1 kHz input
bit 7 32.0 kHz input
*/
/* L3 IIC expander:
address: 0x74
bit 0 Dout L3 mode
bit 1 Dout L3 clock
bit 2 Dout L3 data
bit 3 Dout L3 strobe
bit 4 Din L3 mode
bit 5 Din L3 clock
bit 6 Din L3 data
bit 7 Din L3 strobe
*/
/* function called in aiInstanceSetup(): On success, must leave
* the audio input system "stopped" but otherwise ready for action.
* MMIO setup will be done, as well as other board or codec specific
* actions like setting IIC control bits or initializing codec registers.
*/
extern tmLibdevErr_t dtv_ref2_AI_Init(pboardAIParam_t param)
{
UInt iicd;
Float val;
pprocCapabilities_t procCap;
Int err = TMLIBDEV_OK;
/* get the clock frequency of the TriMedia CPU */
err = procGetCapabilities(&procCap);
if (err) return err;
dtvRef2CPUClock = (Float) procCap->cpuClockFrequency;
if (procCap->deviceID == PROC_DEVICE_TM1100)
{
dtvRef2CPUisTM1100 = True;
}
/* set strobe to zero */
err = iicReadReg(L3_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd &= ~(REF2_INPUT_L3_STROBE);
err |= iicWriteReg(L3_IIC_EXPANDER_ADDRESS, -1, iicd);
if (err) return err;
aiRESET();
/* clock freq is in hz. Math is 32 bit- should be 64 bit!
In the digital input mode the clock is only needed to use the L3 interface.
In this case is the TriMedia clock slave.
In the analog input mode the clocks are needed because the CS5331 is clock
slave. */
val = param->sRate * 256; /* 256 * sampleRate */
if (dtvRef2CPUisTM1100)
{
val = 0.5 + (477218588.0 * (val / dtvRef2CPUClock)); /* 2**32 / 9 */
aiSetFREQ(((UInt) val) | 0x80000000);
}
else
{
val = 0.5 + (1431655765.0 * (val / dtvRef2CPUClock)); /* 2**32 / 3 */
aiSetFREQ((UInt) val);
}
if (param->input == aaaNone)
{
param->input = aaaDigitalInput; /* digital input is the default */
}
switch (param->input)
{
case aaaDigitalInput: /* use TDA 1315 */
/* set a small value for the input DDS frequency to disable the CS5331 */
aiSetFREQ((UInt) (( ((UInt)val) & 0x7fffffff) / 10));
/* set powerdown for input TDA1315 to zero (normal operation) */
err = iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
tmAssert(err == TMLIBDEV_OK, err);
iicd &= ~(REF2_TDA1315_IN_IIC_POWERDOWN);
err = iicWriteReg(INPUT_IIC_EXPANDER_ADDRESS, -1, iicd);
tmAssert(err == TMLIBDEV_OK, err);
microsleep(1000);
/* initalize the tda1315 */
inputL3Params.data = &inputL3Regs[0];
err = tda1315InitInput(&inputL3Params, param);
aiDisableSER_MASTER(); /* tda1315 is master of clock */
microsleep(10); /* wait until internal state of audio in unit is stable */
if (err == TMLIBDEV_OK)
{
aiSetCAP_MODE(3); /* Stereo 16 bits per sample */
aiDisableSIGN_CONVERT();
aiMsbFirst(); /* MSB first */
aiSetFRAMEMODE(0); /* ignore valid bit */
aiSampleRisingCLOCK_EDGE(); /* sample on rising edge */
aiStartFallingEdgeWS();
aiSetSSPOS(0);
aiSetLEFTPOS(0);
aiSetRIGHTPOS(32);
aiSetSIZE(param->size);
#ifdef __LITTLE_ENDIAN__
aiEnableLITTLE_ENDIAN();
#else
aiDisableLITTLE_ENDIAN();
#endif
}
else return err;
dtvRef2AiInput = aaaDigitalInput;
break;
case aaaLineInput: /* use CS5331 */
aiEnableSER_MASTER(); /* 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 |= REF2_TDA1315_IN_IIC_POWERDOWN;
err |= iicWriteReg(INPUT_IIC_EXPANDER_ADDRESS, -1, iicd);
if (err) return err;
microsleep(1000);
aiSetWSDIV(63);
aiSetSCKDIV(5);
aiSetCAP_MODE(3); /* Stereo 16 bits per sample */
aiDisableSIGN_CONVERT();
aiMsbFirst(); /* MSB first */
aiSetFRAMEMODE(0); /* ignore valid bit */
aiSampleRisingCLOCK_EDGE(); /* sample on rising edge */
aiStartFallingEdgeWS(); /* left sample starts on neg. AI_WS */
aiSetSSPOS(0);
aiSetLEFTPOS(0);
aiSetRIGHTPOS(32);
aiSetSIZE(param->size);
#ifdef __LITTLE_ENDIAN__
aiEnableLITTLE_ENDIAN();
#else
aiDisableLITTLE_ENDIAN();
#endif
dtvRef2AiInput = aaaLineInput;
break;
default:
err = AIO_ERR_UNSUPPORTED_INPUT;
break;
}
/* store parameters */
dtvRef2AiAudioTypeFormat = param->audioTypeFormat;
dtvRef2AiAudioSubtypeFormat = param->audioSubtypeFormat;
dtvRef2AiSRate = param->sRate;
dtvRef2AiSize = param->size;
return err;
}
/* called in aiClose(). Should leave audio input system shut down */
extern tmLibdevErr_t dtv_ref2_AI_Term(void)
{
return TMLIBDEV_OK;
}
/* called in aiStart(). */
extern tmLibdevErr_t dtv_ref2_AI_Start(void)
{
aiEnableCAP_ENABLE();
return TMLIBDEV_OK;
}
/* called in aiStop(). */
extern tmLibdevErr_t dtv_ref2_AI_Stop(void)
{
aiDisableCAP_ENABLE();
return TMLIBDEV_OK;
}
/* called from aiSetSampleRate(). */
extern tmLibdevErr_t dtv_ref2_AI_SetSrate(Float sRate)
{
Float val;
/* it's not possible to change the input rate for digital input */
if (dtvRef2AiInput == aaaDigitalInput)
{
return TMLIBDEV_OK;
}
val = sRate * 256.0; /* oversampling clock is 256 * fs */
if (dtvRef2CPUisTM1100)
{
val = 0.5 + (477218588.0 * (val / dtvRef2CPUClock)); /* 2**32 / 9 */
aiSetFREQ(((UInt) val) | 0x80000000);
}
else
{
val = 0.5 + (1431655765.0 * (val / dtvRef2CPUClock)); /* 2**32 / 3 */
aiSetFREQ((UInt) val);
}
return TMLIBDEV_OK;
}
/* called from aiGetSampleRate().
* Should return an accurate value from the hardware.
*/
extern tmLibdevErr_t dtv_ref2_AI_GetSrate(Float * sRate)
{
UInt iicd;
Int err = TMLIBDEV_OK;
tmAssert(sRate, TMLIBDEV_ERR_NULL_PARAMETER);
if (dtvRef2AiInput == aaaDigitalInput)
{
err = iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd |= REF2_TDA1315_IN_IIC_FREQUENCY_MASK;
err |= iicWriteReg(INPUT_IIC_EXPANDER_ADDRESS, -1, iicd);
err |= iicReadReg(INPUT_IIC_EXPANDER_ADDRESS, -1, &iicd);
if (err) return err;
switch (iicd & REF2_TDA1315_IN_IIC_FREQUENCY_MASK)
{
case REF2_TDA1315_IN_IIC_44100_HZ:
*sRate = 44100.0;
break;
case REF2_TDA1315_IN_IIC_48000_HZ:
*sRate = 48000.0;
break;
case REF2_TDA1315_IN_IIC_32000_HZ:
*sRate = 32000.0;
break;
default:
*sRate = 0.0;
break;
}
}
else
{
if (dtvRef2CPUisTM1100)
{
*sRate = (Float) (MMIO(AI_FREQ) & 0x7fffffff) * dtvRef2CPUClock / 477218588.0 / 256.0;
}
else
{
*sRate = (Float) MMIO(AI_FREQ) * dtvRef2CPUClock / 1431655765.0 / 256.0;
}
}
return TMLIBDEV_OK;
}
/* called from aiSetInput() */
extern tmLibdevErr_t dtv_ref2_AI_SetInput(tmAudioAnalogAdapter_t input)
{
boardAIParam_t param;
UInt err;
static Bool capEnable = False;
UInt32 buf1 = MMIO(AI_BASE1);
UInt32 buf2 = MMIO(AI_BASE2);
UInt32 size = MMIO(AI_SIZE);
UInt32 aiIntControl = MMIO(AI_CTL) & (AI_BUF1_INTEN | AI_BUF2_INTEN | AI_OVR_INTEN | AI_HBE_INTEN);
/* check if we realy have to change the input */
if (input == dtvRef2AiInput)
{
return TMLIBDEV_OK;
}
/* stop audio in */
if (MMIO(AI_CTL) & AI_CAP_ENABLE)
{
aiDisableCAP_ENABLE();
capEnable = True;
}
param.audioTypeFormat = dtvRef2AiAudioTypeFormat;
param.audioSubtypeFormat = dtvRef2AiAudioSubtypeFormat;
param.sRate = dtvRef2AiSRate;
param.size = dtvRef2AiSize;
param.input = input;
dtvRef2AiInput = input;
err = dtv_ref2_AI_Init(¶m);
/* restore MMIO registers */
MMIO(AI_BASE1) = buf1;
MMIO(AI_BASE2) = buf2;
MMIO(AI_SIZE) = size;
MMIO(AI_CTL) |= aiIntControl;
if (err)
{
return err;
}
if (capEnable)
{
aiEnableCAP_ENABLE();
}
return TMLIBDEV_OK;
}
/* called from aiGetInput() */
extern tmLibdevErr_t dtv_ref2_AI_GetInput(tmAudioAnalogAdapter_t * input)
{
tmAssert(input, TMLIBDEV_ERR_NULL_PARAMETER);
*input = dtvRef2AiInput;
return TMLIBDEV_OK;
}
/* called from aiGetInputFormat */
extern tmLibdevErr_t dtv_ref2_AI_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 = dtv_ref2_AI_GetSrate(&sRate);
if (err) return err;
if (sRate == 0.0)
{
return TMLIBDEV_OK;
}
inputFormat->sampleRate = sRate;
inputFormat->dataType = atfLinearPCM;
inputFormat->dataSubtype = apfStereo16;
/* get channel status information */
inputL3Params.data = statusReg;
err = tda1315AccessL3(&inputL3Params, READ_CHANNEL_STATUS_REGISTER);
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;
}
/* a backdoor to support features not forseen in the initial design */
extern tmLibdevErr_t dtv_ref2_AI_Config(UInt32 subaddr, Pointer value)
{
return TMLIBDEV_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -