📄 dtv_ttr_audio.c
字号:
aoSetSCKDIV(1);
aoSetSFDIV(2);
#ifdef __LITTLE_ENDIAN__
aoSetLEFTPOS(16);
aoSetRIGHTPOS(0);
#else
aoSetLEFTPOS(0);
aoSetRIGHTPOS(16);
#endif
aoSetSIZE(param->size * 6);
break;
}
case apfSevenDotOne16: /* Eight Channel Audio */
{ /* 64 * 4 * 1 = 256 fs*/
DP(("eight channels 16 bit\n"));
iicd |= (_SET_OUTPUT_8_CHANS | _SET_OUTPUT_16_BITS);
aoSetWSDIV(63);
aoSetSCKDIV(0);
aoSetSFDIV(3);
aoSetLEFTPOS(16);
aoSetRIGHTPOS(48);
aoSetSIZE(param->size * 4);
if (param->audioTypeFormat & atf1937)
{
/* set fourth pair's tda1315 to transmit non-PCM data */
dataFlag = True;
}
break;
}
case apfSevenDotOne32: /* Eight Channel Audio, 32-bit */
{ /* 32 * 4 * 1 = 128fs -> In 32-bit mode the audio out hardware runs at
the double speed. Therefore the resulting oversampling clock is 256 fs.*/
DP(("eight channels 32 bit\n"));
iicd |= (_SET_OUTPUT_8_CHANS | _SET_OUTPUT_32_BITS);
aoSetWSDIV(31);
aoSetSCKDIV(0);
aoSetSFDIV(3);
#ifdef __LITTLE_ENDIAN__
aoSetLEFTPOS(16);
aoSetRIGHTPOS(0);
#else
aoSetLEFTPOS(0);
aoSetRIGHTPOS(16);
#endif
aoSetSIZE(param->size * 8);
if (param->audioTypeFormat & atf1937)
{
/* set fourth pair's tda1315 to transmit non-PCM data */
dataFlag = True;
}
break;
}
default:
/* unsupported subtype */
return(AIO_ERR_UNSUPPORTED_FORMAT);
}
/* initialize the TDA 1315 for S/PDIF output */
outputL3Params.data = & outputL3Regs[_CONTROL_REGISTER];
err = tda1315InitOutput(&outputL3Params, param);
/* set sample rate */
err = dtv_ttr_AO_SetSRate(param->sRate);
if (err)
return err;
if (dataFlag)
{
/* set data mode for TDA1315 */
err = dtv_ttr_AO_Config(AO_SPDIF_SET_DATA_MODE, Null);
if (err)
return err;
}
/* set mute bit */
iicd |= _SET_MUTE_BIT;
/* take FPGA out of reset in the proper mode */
err = iicWriteReg(TTR_IIC_EXPANDER_ADDRESS, -1, iicd);
/* Reset Audio Out */
err |= iicReadReg(TTR_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd &= ~_SET_RESET_BIT;
err |= iicWriteReg(TTR_IIC_EXPANDER_ADDRESS, -1, iicd);
microsleep(300);
err |= iicReadReg(TTR_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd |= _SET_RESET_BIT;
err |= iicWriteReg(TTR_IIC_EXPANDER_ADDRESS, -1, iicd);
if (err) return err;
return TMLIBDEV_OK;
} /* end of dtv_ttr_AO_Init() */
/*******************************************************/
extern tmLibdevErr_t dtv_ttr_AO_Term(void)
{
Int err = TMLIBDEV_OK;
/* reset statics */
dtvTtrDoubleDDSEnable = False;
dtvTtrAoRunning = False;
dtvTtrAoNeedToConfigureTDA1315 = False;
aoRESET();
err = iicWriteReg(TTR_IIC_EXPANDER_ADDRESS, -1, ~TTR_OUTPUT_IIC_AUDIOMODE_MASK);
return err;
}
/*******************************************************/
extern tmLibdevErr_t dtv_ttr_AO_Start(void)
{
Int err = TMLIBDEV_OK;
aoEnableTRANS_ENABLE();
dtvTtrAoRunning = True;
if (dtvTtrAoNeedToConfigureTDA1315)
{
outputL3Params.data = & outputL3Regs[_CHANNEL_STATUS_REGISTER];
err = tda1315AccessL3(&outputL3Params, WRITE_CHANNEL_STATUS_REGISTER);
}
return err;
}
/*******************************************************/
extern tmLibdevErr_t dtv_ttr_AO_Stop(void)
{
aoDisableTRANS_ENABLE();
dtvTtrAoRunning = False;
return TMLIBDEV_OK;
}
/***********************************************************************
* Convert a floating point sample rate value
* to a 32 bit frequency control value for the DDS.
*
* NOTE: YOU MUST SET THE sckdiv, wsdiv and sfdiv FIELDS FOR THIS TO WORK!
*
* Accurate to .5 ppm.
* The DDS can do better than this, but 64 bit math is
* required to use this interface.
*/
extern tmLibdevErr_t dtv_ttr_AO_SetSRate(Float sRate)
{
UInt ao_serial;
Float sckdiv, wsdiv, val, sfdiv;
tmLibdevErr_t err = TMLIBDEV_OK;
Char old_val = outputL3Regs[_CHANNEL_STATUS_REGISTER];
ao_serial = MMIO(AO_SERIAL);
sckdiv = (Float) (aoExtractSCKDIV(ao_serial) + 1);
wsdiv = (Float) (aoExtractWSDIV(ao_serial) + 1);
sfdiv = (Float) (aoExtractSFDIV(ao_serial) + 1);
/* set the right value to the channel status register of the TDA1315 */
outputL3Regs[_CHANNEL_STATUS_REGISTER] &= ~TDA1315_L3_CHAN_STAT_FREQUENCY_MASK;
if (sRate < 38050.0)
{
outputL3Regs[_CHANNEL_STATUS_REGISTER] |= TDA1315_L3_CHAN_STAT_32000_HZ;
}
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 (dtvTtrDoubleDDSEnable)
{
sRate *= 2;
}
if (dtvTtrCPUisTM1100)
{
val = 0.5 + (477218588.0 * (sRate / dtvTtrCPUClock)); /* 2**32 / 9 */
aoSetFREQ(((UInt) val) | 0x80000000);
}
else
{
val = 0.5 + (1431655765.0 * (sRate / dtvTtrCPUClock)); /* 2**32 / 3 */
aoSetFREQ((UInt) val);
}
if (old_val != outputL3Regs[_CHANNEL_STATUS_REGISTER])
{
if (dtvTtrAoRunning)
{
outputL3Params.data = & outputL3Regs[_CHANNEL_STATUS_REGISTER];
err = tda1315AccessL3(&outputL3Params, WRITE_CHANNEL_STATUS_REGISTER);
}
else
{
dtvTtrAoNeedToConfigureTDA1315 = True;
}
}
return err;
}
/*******************************************************/
extern tmLibdevErr_t dtv_ttr_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 (dtvTtrCPUisTM1100)
{
rate = (Float) (freq & 0x7fffffff) * dtvTtrCPUClock / 477218588.0;
}
else
{
rate = (Float) freq * dtvTtrCPUClock / 1431655765.0;
}
rate = rate / ((Float) sckdiv * (Float) wsdiv * (Float) sfdiv);
*sRate = rate;
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtv_ttr_AO_Config(UInt32 subaddr, Pointer value)
{
tmLibdevErr_t rVal = TMLIBDEV_OK;
Bool setCopyright = False;
UInt categoryInfo = 0;
switch (subaddr)
{
case AO_MUTE_SPDIF:
/* mute S/PDIF output only */
outputL3Regs[_CONTROL_REGISTER + 1] &= ~TDA1315_L3_CONTROL_MUTE_MASK;
outputL3Regs[_CONTROL_REGISTER + 1] |= TDA1315_L3_CONTROL_MUTE;
outputL3Params.data = & outputL3Regs[_CONTROL_REGISTER];
rVal = tda1315AccessL3(&outputL3Params, WRITE_CONTROL_REGISTER);
break;
case AO_UNMUTE_SPDIF:
/* unmute S/PDIF output only */
outputL3Regs[_CONTROL_REGISTER + 1] &= ~TDA1315_L3_CONTROL_MUTE_MASK;
outputL3Regs[_CONTROL_REGISTER + 1] |= TDA1315_L3_CONTROL_UNMUTE;
outputL3Params.data = & outputL3Regs[_CONTROL_REGISTER];
rVal = tda1315AccessL3(&outputL3Params, WRITE_CONTROL_REGISTER);
break;
case AO_MUTE_ANALOG_OUTPUTS:
{
UInt iicd;
rVal = iicReadReg(TTR_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd &= ~_SET_MUTE_BIT;
rVal |= iicWriteReg(TTR_IIC_EXPANDER_ADDRESS, -1, iicd);
}
break;
case AO_UNMUTE_ANALOG_OUTPUTS:
{
UInt iicd;
rVal = iicReadReg(TTR_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd |= _SET_MUTE_BIT;
rVal |= iicWriteReg(TTR_IIC_EXPANDER_ADDRESS, -1, iicd);
}
break;
case AO_SPDIF_SET_COPYRIGHT_INFO:
/* get source information */
switch ((UInt32) value & SPDIF_SOURCE_MASK)
{
case SPDIF_SOURCE_GENERAL:
case SPDIF_SOURCE_CD:
case SPDIF_SOURCE_OTHER_LASER_OPTICAL:
case SPDIF_SOURCE_DAT:
case SPDIF_SOURCE_MD:
if ((UInt32) value & SPDIF_COPYRIGHT_MASK)
setCopyright = True;
categoryInfo = 0x00;
break;
case SPDIF_SOURCE_BROADCAST:
if ((UInt32) value & SPDIF_COPYRIGHT_MASK)
setCopyright = True;
categoryInfo = 0x26;
if (!((UInt32) value & SPDIF_PRERECORDED_SOFTWARE))
categoryInfo |= 0x01;
break;
case SPDIF_SOURCE_DVD:
if ((UInt32) value & SPDIF_COPYRIGHT_MASK)
setCopyright = True;
categoryInfo = 0x92;
if (!((UInt32) value & SPDIF_PRERECORDED_SOFTWARE))
categoryInfo |= 0x01;
break;
default:
return AIO_ERR_MISC_ERROR;
}
outputL3Regs[_CHANNEL_STATUS_REGISTER + 1] &= ~TDA1315_L3_CHAN_STAT_CATEGORY_MASK;
outputL3Regs[_CHANNEL_STATUS_REGISTER + 1] |= categoryInfo << 8;
outputL3Regs[_CHANNEL_STATUS_REGISTER + 1] &= ~TDA1315_L3_CHAN_STAT_COPYRIGHT_MASK;
if (!setCopyright)
outputL3Regs[_CHANNEL_STATUS_REGISTER + 1] |= TDA1315_L3_CHAN_STAT_NO_COPYRIGHT;
outputL3Params.data = & outputL3Regs[_CHANNEL_STATUS_REGISTER];
rVal = tda1315AccessL3(&outputL3Params, WRITE_CHANNEL_STATUS_REGISTER);
break;
case AO_SPDIF_SET_DATA_MODE:
outputL3Regs[_CHANNEL_STATUS_REGISTER] &= ~TDA1315_L3_CHAN_STAT_DATA_MASK;
outputL3Regs[_CHANNEL_STATUS_REGISTER] |= TDA1315_L3_CHAN_STAT_DATA;
outputL3Params.data = & outputL3Regs[_CHANNEL_STATUS_REGISTER];
rVal = tda1315AccessL3(&outputL3Params, WRITE_CHANNEL_STATUS_REGISTER);
break;
case AO_SPDIF_PCM_MODE:
outputL3Regs[_CHANNEL_STATUS_REGISTER] &= ~TDA1315_L3_CHAN_STAT_DATA_MASK;
outputL3Regs[_CHANNEL_STATUS_REGISTER] |= TDA1315_L3_CHAN_STAT_AUDIO;
outputL3Params.data = & outputL3Regs[_CHANNEL_STATUS_REGISTER];
rVal = tda1315AccessL3(&outputL3Params, WRITE_CHANNEL_STATUS_REGISTER);
break;
default:
/* unknown config parameter */
return AIO_ERR_MISC_ERROR;
}
return rVal;
}
/************************** 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -