📄 dtv_ttr_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_ttr_audio.c 1.1
*
* Last update : 16:30:33 - 99/03/04
*
* 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 <tm1/tmAudioConfig.h>
#include "tda1315.h"
#include "l3.h"
#include "philips_dtv_ttr.h"
#include "dtv_ttr_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 (TTR_OUTPUT_IIC_AUDIOMODE_1 | TTR_OUTPUT_IIC_AUDIOMODE_2)
#define _SET_OUTPUT_6_CHANS TTR_OUTPUT_IIC_AUDIOMODE_2
#define _SET_OUTPUT_4_CHANS TTR_OUTPUT_IIC_AUDIOMODE_1
#define _SET_OUTPUT_2_CHANS 0x00
#define _SET_OUTPUT_32_BITS 0x00 /* 0000 0000 */
#define _SET_OUTPUT_16_BITS TTR_OUTPUT_IIC_AUDIOMODE_3
#define _SET_RESET_BIT TTR_OUTPUT_IIC_AUDIOMODE_5
#define _SET_MUTE_BIT TTR_OUTPUT_IIC_AUDIOMODE_4
#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 */
TTR_L3_IIC_EXPANDER_ADDRESS, /* address */
TDA1315_L3_ADDRESS, /* l3Address */
TTR_OUTPUT_L3_DATA, /* l3Data */
TTR_OUTPUT_L3_MODE, /* l3Mode */
TTR_OUTPUT_L3_CLOCK, /* l3Clock */
TTR_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 */
TTR_L3_IIC_EXPANDER_ADDRESS, /* address */
TDA1315_L3_ADDRESS, /* l3Address */
TTR_INPUT_L3_DATA, /* l3Data */
TTR_INPUT_L3_MODE, /* l3Mode */
TTR_INPUT_L3_CLOCK, /* l3Clock */
TTR_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 dtvTtrDoubleDDSEnable = False;
static Float dtvTtrCPUClock = 0.0;
static Bool dtvTtrCPUisTM1100 = False;
static Bool dtvTtrAoRunning = False;
static Bool dtvTtrAoNeedToConfigureTDA1315 = False;
static UInt dtvTtrAiAudioTypeFormat;
static UInt dtvTtrAiAudioSubtypeFormat;
static Float dtvTtrAiSRate;
static Int dtvTtrAiSize;
static UInt dtvTtrAiInput;
/*******************************************************/
extern tmLibdevErr_t dtv_ttr_AO_Init(boardAOParam_t * param)
{
UInt iicd;
Float val;
pprocCapabilities_t procCap;
Int err = TMLIBDEV_OK;
Bool dataFlag = False;
/* get the clock frequency of the TriMedia CPU */
err = procGetCapabilities(&procCap);
if (err) return err;
dtvTtrCPUClock = (Float) procCap->cpuClockFrequency;
if (procCap->deviceID == PROC_DEVICE_TM1100)
{
dtvTtrCPUisTM1100 = 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 (dtvTtrCPUisTM1100)
{
val = 0.5 + (477218588.0 * (val / dtvTtrCPUClock)); /* 2**32 / 9 */
aoSetFREQ(((UInt) val) | 0x80000000);
}
else
{
val = 0.5 + (1431655765.0 * (val / dtvTtrCPUClock)); /* 2**32 / 3 */
aoSetFREQ((UInt) val);
}
aoEnableSER_MASTER();
microsleep(10); /* wait until AO unit stabalized */
if (! (param->audioTypeFormat & DTV_TTR_SUPPORTED_AUDIO_OUT_TYPES) )
return AIO_ERR_UNSUPPORTED_FORMAT;
if (! (param->audioSubtypeFormat & DTV_TTR_SUPPORTED_AUDIO_OUT_SUBTYPES) )
return AIO_ERR_UNSUPPORTED_FORMAT;
if (param->audioSubtypeFormat & _DOUBLE_CLOCK_MODES)
{
dtvTtrDoubleDDSEnable = 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(TTR_IIC_EXPANDER_ADDRESS, -1, &iicd);
iicd &= ~TTR_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 */
dataFlag = True;
}
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 */
dataFlag = True;
}
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 */
dataFlag = True;
}
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 */
dataFlag = True;
}
break;
}
case apfFiveDotOne16: /* Six channel Audio */
{ /* 64 * 3 * 2 = 384 fs */
DP(("six channels 16 bit\n"));
iicd |= (_SET_OUTPUT_6_CHANS | _SET_OUTPUT_16_BITS);
aoSetWSDIV(63);
aoSetSCKDIV(1);
aoSetSFDIV(2);
aoSetLEFTPOS(16);
aoSetRIGHTPOS(48);
aoSetSIZE(param->size * 3);
break;
}
case apfFiveDotOne32: /* Six channel Audio */
{ /* 32 * 3 * 2 = 192 fs -> audio out runs at double speed = 384 fs */
DP(("six channels 32 bit\n"));
iicd |= (_SET_OUTPUT_6_CHANS | _SET_OUTPUT_32_BITS);
aoSetWSDIV(31);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -