📄 philips_iref.c
字号:
static Float __irefCPUClockFrequency;
static Bool __irefNeedToInitAD1847 = True;
static Bool __irefNeedAD1847Reset = False;
static Bool __irefSampleRate = 0.0;
static Bool __irefNeedToStartAi = False;
static Bool __irefTMIsNot1S = False;
static Bool __irefAoInitialized = False;
static Bool __irefAoRunning = False;
static Bool __irefAoNeedToConfigureOutput = False;
static tmAudioPcmFormat_t __irefAoCurrentPcmFormat = apfNone;
static tmAudioAnalogAdapter_t __irefAoOutput = aaaLineOutput1;
static Int __irefAoLGain = 0;
static Int __irefAoRGain = 0;
static Bool __irefAiInitialized = False;
static Bool __irefAiRunning = False;
static Bool __irefAiNeedToConfigureInput = False;
static tmAudioPcmFormat_t __irefAiCurrentPcmFormat = apfNone;
static tmAudioAnalogAdapter_t __irefAiInput = aaaLineInput;
static Int __irefAiAd1847Input = AD1847_SRC_LINE1;
static Int __irefAiLGain = 0;
static Int __irefAiRGain = 0;
/******************** iref_board_init *******************************
* The iref board comes up with peripherals reset.
* This function takes the board out of reset and leaves
* it in a good state.
*/
static tmLibdevErr_t iref_board_init(void)
{
pprocCapabilities_t procCap;
L1_DP(("iref_board_init\n"));
TRY(procGetCapabilities(&procCap));
/* get the clcok frequency -> this value is used to calculate audio and video
frequencies */
__irefCPUClockFrequency = (Float) procCap->cpuClockFrequency;
L2_DP(("procCap->cpuClockFrequency = %d\n", __irefCPUClockFrequency));
/* make sure VO clock is running at 27MHz! */
MMIO(VO_CLOCK) = (UInt) (0.5 +
(1431655765.0 * VO_INIT_FREQ / __irefCPUClockFrequency));
MMIO(VO_CTL) = 0x02700000;
/*
* IIC address 0x70 on IREF:
* Bit 0 is Reset
* Bit 1 is AC3_INIT (high)
* Bit 2 is st7545 AFE reset (low for reset) (formerly AC3 Mode)
* Bit 3 is unused
* Bit 4 is PWRDOWN Audio: Low powers down ad1847
* Bit 5 is CHMODE Audio: Low resets ad1847
* Bit 6 is MASTER Audio: selects ad1847 master/slave
* Bit 7 is STANDBY high to shut down 6 channel DAC
*/
TRY(iicWriteReg(0x70, -1, 0xFE)); /* lower reset */
MMIO(SSI_CTL) = 0x00040000; /* V34IO2 goes high to stay on hook! */
TRY(iicWriteReg(0x70, -1, 0xFF)); /* raise reset */
saa7125Stop(vasNTSC);
MMIO(VO_CLOCK) = 0;
microsleep(100); /* Without this, 1847 is not init'ed. */
/* check if processor is older then TM1 1.1S -> needed to set/get right audio frequencies */
if ((procCap->deviceID == PROC_DEVICE_TM1000)
&& ((procCap->revisionID == PROC_REVISION_1_1)
|| (procCap->revisionID == PROC_REVISION_1_0)))
__irefTMIsNot1S = True;
return TMLIBDEV_OK;
} /* end of iref_board_init() */
/******************** iref_board_detect *******************************
* Returns TMLIBDEV_OK if the hardware appears to be a Philips IREF board.
* This function reads subsystem ID and subsystem vendor ID from the boot
* EEPROM and compares those to the values reserved for the Philips IREF board.
*/
static tmLibdevErr_t iref_board_detect(void)
{
Int line, error;
UInt d1, d2;
UInt boardID;
UInt mfgID;
UInt8 eepromData[8];
L1_DP(("iref_board_detect\n"));
/* read boot EEPROM */
for (line = 0; line < 8; line++)
{
error = iicReadReg(IIC_EEPROM_ADDRESS, line, &d1);
if (error)
{
TRY(iicReadReg(IIC_EEPROM_ADDRESS, line, &d1));
}
error = iicReadReg(IIC_EEPROM_ADDRESS, line, &d2);
if (error)
{
TRY(iicReadReg(IIC_EEPROM_ADDRESS, line, &d2));
}
eepromData[line] = d1;
}
/* get subsystem vendor ID */
mfgID = (eepromData[3] << 8) + eepromData[4];
/* get subsystem ID */
boardID = (eepromData[1] << 8) + eepromData[2];
L2_DP(("Read in IIC: mfgID = %d / boardID = %d\n", mfgID, boardID ));
/* Actually, why return TMLIBDEV_OK as on the contrary, it is not ! */
/* zero should be returned. This is confusing */
/* check if this is a Philips board */
if (mfgID != BOARD_ID_PHILIPS_MFG_ID)
return BOARD_ERR_UNKNOWN_BOARD;
/* check if this is an IREF board */
if (boardID == BOARD_ID_PHILIPS_TM1_IREF_SUBSYS_ID)
return TMLIBDEV_OK;
/* And then return */
return BOARD_ERR_UNKNOWN_BOARD;
}
static tmLibdevErr_t iref_board_activate(pcomponent_t comp)
{
L1_DP(("iref_board_activate\n"));
TRY(iref_board_detect());
L2_DP(("Board recognized\n"));
TRY(iref_board_init());
/* This is time to register the component outputs. */
/* This will be used by all the devices to check */
/* whether they can work with this board or not */
TRY(iref_board_register(comp));
return TMLIBDEV_OK;
}
static tmLibdevErr_t iref_board_register(pcomponent_t comp)
{
UInt32 ID = BOARD_VERSION_PHILIPS_TM1_IREF;
L1_DP(("iref_board_register\n"));
TRY(tsaBoardRegisterBoard(ID, "Philips IREF"));
/* now register all the capabilities of the board : */
/* AO, AI, VO, VI, SSI, etc */
L2_DP(("Board registered\n"));
TRY(tsaBoardRegisterAO(0, &iref_ao));
TRY(tsaBoardRegisterAI(0, &iref_ai));
TRY(tsaBoardRegisterVO(0, &iref_vo));
TRY(tsaBoardRegisterVI(0, &iref_vi));
TRY(tsaBoardRegisterSSI(0, &iref_afe));
L2_DP(("Interfaces registered\n"));
return TMLIBDEV_OK;
}
/**********************************************************
* This audio module supports stereo 16 bit
* and 6 channel modes.
* Support for 4 and 8 channel modes is non-existent.
* Lower quality modes probably return resonable errors.
*
*/
/*******************************************************/
static tmLibdevErr_t iref_AO_init(pboardAOParam_t param)
{
tmLibdevErr_t rval = TMLIBDEV_OK;
tmAssert(param, TMLIBDEV_ERR_NULL_PARAMETER);
/* check audio output adapter settings */
if (param->output & IREF_OUTPUT_AUDIO_ADAPTERS)
{
__irefAoOutput = param->output;
if (param->output == aaaNone)
{
/* set default outputs */
if (param->audioSubtypeFormat == apfFiveDotOne16)
{
__irefAoOutput = aaaLineOutput2;
}
else
{
__irefAoOutput = aaaLineOutput1;
}
}
}
else
{
/* this should never happen since this is already checked in libdev layer */
return AIO_ERR_UNSUPPORTED_OUTPUT;
}
if (__irefAiInitialized && (param->audioSubtypeFormat != __irefAiCurrentPcmFormat))
{
return (AIO_ERR_UNMATCHED_FORMATS); /* we don't supposrt different formats at input
and output */
}
/* check if the IREF board has been initialized in an other PCM format */
if (__irefAoInitialized)
{
__irefAoInitialized = False;
__irefAoCurrentPcmFormat = apfNone;
}
switch (param->audioSubtypeFormat)
{
case apfFiveDotOne16:
/* initialization for 6 channel output (3 x CS4333) */
/* check if the right output adapter has been set */
if (__irefAoOutput != aaaLineOutput2)
{
return AIO_ERR_UNMATCHED_FORMATS;
}
/* reset the audio I/O peripherals */
aoRESET();
aiRESET();
MMIO(AO_FREQ) = hertz2Control(param->sRate, 4, 32, 3);
aoEnableSER_MASTER();
#ifdef __LITTLE_ENDIAN__
aoEnableLITTLE_ENDIAN();
#else
aoDisableLITTLE_ENDIAN();
#endif
aoDisableSIGN_CONVERT();
aoMsbFirst(); /* MSB first */
aoEnableWS_PULSE(); /* pulse mode because of bug 7064 */
aoSampleRisingCLOCK_EDGE(); /* sample on rising edge */
aoStartRisingEdgeWS();
aoSetLEFTPOS(0);
aoSetRIGHTPOS(16);
aoSetTRANS_MODE(3);
/* 3 * 32 * 4 = 384 fs */
aoSetSFDIV(2);
aoSetWSDIV(31);
if (__irefTMIsNot1S) /* Workaround SCOPUS_BUG_ID_3013 */
aoSetSCKDIV(5);
else
aoSetSCKDIV(3);
aoEnableBUF1_INTEN();
aoEnableBUF2_INTEN();
rval = ch6_init(param);
if (rval == 0)
{
__irefAoInitialized = True;
__irefSampleRate = param->sRate;
__irefAoCurrentPcmFormat = apfFiveDotOne16;
strcpy(iref_ao.codecName, "triple CS4333"); /* 16 chars max */
}
/* set the size after ch6_init because this function changes this
MMIO register */
aoSetSIZE(param->size * 3);
break;
case apfStereo16:
case apfMono16:
if (param->sRate > AD1847_MAX_SRATE)
{
return AIO_ERR_SRATE_TOO_HIGH;
}
if (param->sRate < AD1847_MIN_SRATE)
{
return AIO_ERR_SRATE_TOO_LOW;
}
/* check if the right output adapter has been set */
if (__irefAoOutput != aaaLineOutput1)
{
return AIO_ERR_UNMATCHED_FORMATS;
}
if (__irefNeedToInitAD1847)
{
/* reset the audio I/O peripherals */
aoRESET();
aiRESET();
/* only set the frequency for the DDS before initializing the AD1847 all other settings
* will be changed by ad1847MasterInit().
* Calculate and set frequency for DDS (512 fs).
* The frequencies for input and output are the same. */
MMIO(AO_FREQ) = hertz2Control(param->sRate, 512, 1, 1);
MMIO(AI_FREQ) = MMIO(AO_FREQ);
rval = ad1847MasterInit((tmAudioPcmFormat_t)param->audioSubtypeFormat,
param->sRate);
if (rval != TMLIBDEV_OK)
{
return rval;
}
__irefNeedToInitAD1847 = False;
__irefSampleRate = param->sRate;
}
/* initialization for AD 1847, 16 chars max */
strcpy(iref_ao.codecName, "AD1847");
/* setup audio out unit of the TriMedia */
aoDisableSER_MASTER();
#ifdef __LITTLE_ENDIAN__
aoEnableLITTLE_ENDIAN();
#else
aoDisableLITTLE_ENDIAN();
#endif
aoDisableSIGN_CONVERT();
aoMsbFirst(); /* MSB first */
aoEnableWS_PULSE(); /* pulse mode because of bug 7064 */
aoSampleFallingCLOCK_EDGE(); /* sample on falling edge */
aoStartRisingEdgeWS(); /* frame starts on rising edge */
aoSetLEFTPOS(16);
aoSetRIGHTPOS(32);
aoSetSIZE(param->size);
if (param->audioSubtypeFormat == apfStereo16)
{
aoSetTRANS_MODE(3);
}
else
{
aoSetTRANS_MODE(2);
}
__irefAoCurrentPcmFormat = (tmAudioPcmFormat_t)param->audioSubtypeFormat;
/* check if the current sample rate is the same as the requested one */
if (__irefSampleRate != param->sRate)
{
rval = iref_AO_SetSRate(param->sRate);
if (rval)
{
return rval;
}
}
__irefAoInitialized = True;
break;
default:
rval = AIO_ERR_UNSUPPORTED_FORMAT;
break;
}
return rval;
}
/*******************************************************/
static tmLibdevErr_t iref_AO_term(void)
{
tmLibdevErr_t rval;
/* reset statics */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -