📄 dtv_ref2_audio.c
字号:
/*
* Copyright (c) 1995,1996,1997 by TriMedia Technologies.
*
* +------------------------------------------------------------------+
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such |
* | a license and with the inclusion of this copyright notice. This |
* | software or any other copies of this software may not be provided|
* | or otherwise made available to any other person. The ownership |
* | and title of this software is not transferred. |
* | |
* | The information in this software is subject to change without |
* | any prior notice and should not be construed as a commitment by |
* | TriMedia Technologies. |
* | |
* | this code and information is provided "as is" without any |
* | warranty of any kind, either expressed or implied, including but |
* | not limited to the implied warranties of merchantability and/or |
* | fitness for any particular purpose. |
* +------------------------------------------------------------------+
*
* Module name : dtv_ref2_audio.c 1.8
*
* Last update : 18:53:23 - 00/11/09
*
* Description :
*
* Initialize and control routines for TM1 DTV 8 channel audio DAC.
* Designed to be called from TM Device Library's board support package
*
* This audio module supports:
* stereo 16 bit
* all Four channel 16 bit modes
* Six channel 16 bit
* Eight channel 16 bit
* Six channel analog plus 2 channel IEC1937, in 8 ch format.
* (atfLinearPCM | atf1937), apfSevenDotOne16
*
* Other modes return resonable errors.
*
* Revision :
*
*
*
*/
/* TriMedia standard shared includes */
#include <tm1/tmAssert.h>
#include <tmlib/dprintf.h>
#include <tmlib/tmtypes.h>
#include <tm1/tmAOmmio.h>
#include <tm1/tmAImmio.h>
#include <tm1/tmIIC.h>
#include <tm1/tmProcessor.h>
#include <tm1/tmLibdevErr.h>
#include "tda1315.h"
#include "philips_dtv_ref2.h"
#include "dtv_ref2_audio.h"
/***********************************************************/
/* IIC "Legacy IREF" Expander (0x70)
0: SReset
1: AFE Reset
2: ClkSel2
3: ClkSel1
4: unused
5: unused
6: unused
7: unused
*/
/* IIC Audio Out Expander description on DTV Board (0x74)
0: L mode, DOut
1: L clock, DOut
2: L data, DOut
3: Audio Mode 5 -> reset (active low)
4: Audio Mode 4
5: Audio Mode 3 -> 16/32 bit mode
6: Audio Mode 2 -> channel mode1
7: Audio Mode 1 -> channel mode0
Mode IIC expander bits
7654 3210
2 Channels 00xx xxxx
4 Channels 10xx xxxx
6 Channels 01xx xxxx
8 Channels 11xx xxxx
16 bit xx1x xxxx
32 bit xx0x xxxx
Reset xxx0 xxxx
unReset xxx1 xxxx
*/
#define __SET_OUTPUT_8_CHANS (REF2_OUTPUT_IIC_AUDIOMODE_1 | REF2_OUTPUT_IIC_AUDIOMODE_2)
#define __SET_OUTPUT_6_CHANS REF2_OUTPUT_IIC_AUDIOMODE_2
#define __SET_OUTPUT_4_CHANS REF2_OUTPUT_IIC_AUDIOMODE_1
#define __SET_OUTPUT_2_CHANS 0x00
#define __SET_OUTPUT_32_BITS 0x00 /* 0000 0000 */
#define __SET_OUTPUT_16_BITS REF2_OUTPUT_IIC_AUDIOMODE_3
#define __SET_RESET_BIT REF2_OUTPUT_IIC_AUDIOMODE_5
#define __DOUBLE_CLOCK_MODES (apfFiveDotOne32 | apfSevenDotOne32)
#define _CHANNEL_STATUS_REGISTER 0
#define _CONTROL_REGISTER 2
static Char outputL3Regs[4] = {0x0, 0x0, 0x0, 0x0};
static Char inputL3Regs[2] = {0x0, 0x0};
static l3Param_t outputL3Params =
{
l3ModeIIC, /* mode */
L3_IIC_EXPANDER_ADDRESS, /* address */
TDA1315_L3_ADDRESS, /* l3Address */
REF2_OUTPUT_L3_DATA, /* l3Data */
REF2_OUTPUT_L3_MODE, /* l3Mode */
REF2_OUTPUT_L3_CLOCK, /* l3Clock */
REF2_OUTPUT_L3_STROBE, /* usrPin0 */
0, /* usrPin1 */
0, /* usrPin2 */
0, /* l3AddressAdd */
0, /* l3DataAdd */
0, /* l3ModeAdd */
0, /* l3ClockAdd */
0, /* usrPin0Add */
0, /* usrPin2Add */
0, /* usrPin3Add */
2, /* numberOfBytes */
Null /* data */
};
static l3Param_t inputL3Params =
{
l3ModeIIC, /* mode */
L3_IIC_EXPANDER_ADDRESS, /* address */
TDA1315_L3_ADDRESS, /* l3Address */
REF2_INPUT_L3_DATA, /* l3Data */
REF2_INPUT_L3_MODE, /* l3Mode */
REF2_INPUT_L3_CLOCK, /* l3Clock */
REF2_INPUT_L3_STROBE, /* usrPin0 */
0, /* usrPin1 */
0, /* usrPin2 */
0, /* l3AddressAdd */
0, /* l3DataAdd */
0, /* l3ModeAdd */
0, /* l3ClockAdd */
0, /* usrPin0Add */
0, /* usrPin2Add */
0, /* usrPin3Add */
2, /* numberOfBytes */
Null /* data */
};
/* flag to indicate that the 32-bit mode is enabled */
static Bool dtvRef2DoubleDDSEnable = False;
static Float dtvRef2CPUClock = 0.0;
static Bool dtvRef2CPUisTM1100 = False;
static Bool dtvRef2AoRunning = False;
static Bool dtvRef2AoNeedToConfigureTDA1315 = False;
static UInt dtvRef2AiAudioTypeFormat;
static UInt dtvRef2AiAudioSubtypeFormat;
static Float dtvRef2AiSRate;
static Int dtvRef2AiSize;
static UInt dtvRef2AiInput;
/*******************************************************/
extern tmLibdevErr_t dtv_ref2_AO_Init(pboardAOParam_t param)
{
UInt iicd;
Float val;
pprocCapabilities_t procCap;
Int err = TMLIBDEV_OK;
#if 0
param->maxSRate = 50000; /* TDA 1305, 32KHz,44.1KHz,48KHz supported */
param->minSRate = 20000;
#endif
/* 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;
}
/* reset the audio output peripheral */
aoRESET();
/* Set initial frequency to get AO into a stable state */
val = param->sRate * 256.0; /* 256 * sampleRate */
if (dtvRef2CPUisTM1100)
{
val = 0.5 + (477218588.0 * (val / dtvRef2CPUClock)); /* 2**32 / 9 */
aoSetFREQ(((UInt) val) | 0x80000000);
}
else
{
val = 0.5 + (1431655765.0 * (val / dtvRef2CPUClock)); /* 2**32 / 3 */
aoSetFREQ((UInt) val);
}
aoEnableSER_MASTER();
microsleep(10); /* wait until AO unit stabalized */
if (! (param->audioTypeFormat & DTV_REF2_SUPPORTED_AUDIO_OUT_TYPES) )
return AIO_ERR_UNSUPPORTED_FORMAT;
if (! (param->audioSubtypeFormat & DTV_REF2_SUPPORTED_AUDIO_OUT_SUBTYPES) )
return AIO_ERR_UNSUPPORTED_FORMAT;
if (param->audioSubtypeFormat & __DOUBLE_CLOCK_MODES)
{
dtvRef2DoubleDDSEnable = True;
}
#ifdef __LITTLE_ENDIAN__
aoEnableLITTLE_ENDIAN();
#else
aoDisableLITTLE_ENDIAN();
#endif
aoMsbFirst();
aoStartRisingEdgeWS();
aoSampleRisingCLOCK_EDGE(); /* sample on rising edge */
aoSetTRANS_MODE(3); /* Set Audio output to Stereo 16 bits per channel */
aoSetSSPOS(0); /* Left and right channel start at bit 0 */
aoDisableSIGN_CONVERT(); /* Disable Sign Convert for MSB */
aoEnableWS_PULSE(); /* word strobe in pulse mode */
aoDisableTRANS_ENABLE();
/* err = iicReadReg(IIC_EXPANDER_ADDRESS, -1, &iicd); */
iicd = 0xFF;
err = 0;
/* note: The audio code assumes that this latch is left in position FF.
* You would expect the audio code to read the latch, but there seems
* to be a problem with that in this hardware.
*/
iicd &= ~REF2_OUTPUT_IIC_AUDIOMODE_MASK;
if (err) return err;
switch (param->audioSubtypeFormat) {
case apfStereo16: /* Two channel Audio */
{ /* 64 * 4 * 1 = 256fs */
DP(("stereo 16 bit\n"));
iicd |= (__SET_OUTPUT_2_CHANS | __SET_OUTPUT_16_BITS);
aoSetWSDIV(63);
aoSetSCKDIV(3);
aoSetSFDIV(0);
aoSetLEFTPOS(16);
aoSetRIGHTPOS(48);
aoSetSIZE(param->size);
if (param->audioTypeFormat & atf1937)
{
/* set tda1315 to transmit non-PCM data */
}
break;
}
case apfStereo32: /* Two channel Audio, 32-bit */
{ /* 32 * 4 * 2 = 256 fs */
DP(("stereo 32 bit\n"));
iicd |= (__SET_OUTPUT_2_CHANS | __SET_OUTPUT_32_BITS);
aoSetWSDIV(31);
aoSetSCKDIV(3);
aoSetSFDIV(1);
#ifdef __LITTLE_ENDIAN__
aoSetLEFTPOS(16);
aoSetRIGHTPOS(0);
#else
aoSetLEFTPOS(0);
aoSetRIGHTPOS(16);
#endif
aoSetSIZE(param->size * 2);
if (param->audioTypeFormat & atf1937)
{
/* set tda1315 to transmit non-PCM data */
}
break;
}
case apfFourCh_3_1_0_16: /* Four channel Audio */
case apfFourCh_2_2_0_16: /* Four channel Audio */
case apfFourCh_2_1_1_16: /* Four channel Audio */
case apfFourCh_3_0_1_16: /* Four channel Audio */
{ /* 63 * 2 * 2 = 256fs */
DP(("four channels 16 bit\n"));
iicd |= (__SET_OUTPUT_4_CHANS | __SET_OUTPUT_16_BITS);
aoSetWSDIV(63);
aoSetSCKDIV(1);
aoSetSFDIV(1);
aoSetLEFTPOS(16);
aoSetRIGHTPOS(48);
aoSetSIZE(param->size * 2);
if ((param->audioTypeFormat & atf1937) &&
(param->audioSubtypeFormat == apfFourCh_2_2_0_16))
{
/* set second pair's tda1315 to transmit non-PCM data */
}
break;
}
case apfFourCh_3_1_0_32: /* Four channel Audio, 32-bit */
case apfFourCh_2_2_0_32: /* Four channel Audio, 32-bit */
case apfFourCh_2_1_1_32: /* Four channel Audio, 32-bit */
case apfFourCh_3_0_1_32: /* Four channel Audio, 32-bit */
{ /* 32 * 2 * 4 = 256 fs */
DP(("four channels 32 bit\n"));
iicd |= (__SET_OUTPUT_4_CHANS | __SET_OUTPUT_32_BITS);
aoSetWSDIV(31);
aoSetSCKDIV(1);
aoSetSFDIV(3);
#ifdef __LITTLE_ENDIAN__
aoSetLEFTPOS(16);
aoSetRIGHTPOS(0);
#else
aoSetLEFTPOS(0);
aoSetRIGHTPOS(16);
#endif
aoSetSIZE(param->size * 4);
if ((param->audioTypeFormat & atf1937) && (param->audioSubtypeFormat == apfFourCh_2_2_0_32))
{
/* set second pair's tda1315 to transmit non-PCM data */
}
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 */
}
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 */
}
break;
}
default:
/* unsupported subtype */
return(AIO_ERR_UNSUPPORTED_FORMAT);
}
/* set sample rate */
err = dtv_ref2_AO_SetSRate(param->sRate);
if (err) return err;
/* take FPGA out of reset in the proper mode */
err = iicWriteReg(IIC_EXPANDER_ADDRESS, -1, iicd);
/* Reset Audio Out */
/* err |= iicReadReg(IIC_EXPANDER_ADDRESS, -1, &iicd); */
iicd &= ~__SET_RESET_BIT;
err |= iicWriteReg(IIC_EXPANDER_ADDRESS, -1, iicd);
microsleep(300);
/* err |= iicReadReg(IIC_EXPANDER_ADDRESS, -1, &iicd); */
iicd |= __SET_RESET_BIT;
err |= iicWriteReg(IIC_EXPANDER_ADDRESS, -1, iicd);
if (err) return err;
return TMLIBDEV_OK;
} /* end of dtv_ref2_AO_Init() */
/*******************************************************/
extern tmLibdevErr_t dtv_ref2_AO_Term(void)
{
Int err = TMLIBDEV_OK;
/* reset statics */
dtvRef2DoubleDDSEnable = False;
dtvRef2AoRunning = False;
dtvRef2AoNeedToConfigureTDA1315 = False;
aoRESET();
err = iicWriteReg(IIC_EXPANDER_ADDRESS, -1, ~REF2_OUTPUT_IIC_AUDIOMODE_MASK);
return err;
}
/*******************************************************/
extern tmLibdevErr_t dtv_ref2_AO_Start(void)
{
Int err = TMLIBDEV_OK;
aoEnableTRANS_ENABLE();
dtvRef2AoRunning = True;
if (dtvRef2AoNeedToConfigureTDA1315)
{
outputL3Params.data = & outputL3Regs[_CHANNEL_STATUS_REGISTER];
err = tda1315AccessL3(&outputL3Params, WRITE_CHANNEL_STATUS_REGISTER);
}
return err;
}
/*******************************************************/
extern tmLibdevErr_t dtv_ref2_AO_Stop(void)
{
aoDisableTRANS_ENABLE();
dtvRef2AoRunning = 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_ref2_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -