windows-nt/Source/XPSP1/NT/drivers/wdm/dvd/mini/jbs/staudio.c
2020-09-26 16:20:57 +08:00

649 lines
16 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MODULE : STAUDIO.C
// PURPOSE : Audio Routines
// AUTHOR : JBS Yadawa
// CREATED : 7/20/96
//
//
// Copyright (C) 1996 SGS-THOMSON Microelectronics
//
//
// REVISION HISTORY :
//
// DATE :
//
// COMMENTS :
//
#include "common.h"
#include "stdefs.h"
#include "staudio.h"
#include "debug.h"
#include "error.h"
#include "board.h"
#include "sti3520A.h"
#include <dos.h> ///////////
static PAUDIO pAudio;
#define SLOW_MODE 0
#define PLAY_MODE 1
#define FAST_MODE 2
#define IT_A 0 // interrupt detected
void AudioOpen(PAUDIO pAud)
{
pAudio = pAud;
pAudio->AudioState = AUDIO_POWER_UP;
pAudio->IntAudio = NO_IT_A;
pAudio->MaskItAudio = 0;
pAudio->ErrorMsg = NO_ERROR;
pAudio->FirstPTS = FALSE; // First PTS not reached yet
pAudio->mute = FALSE;
pAudio->Stepped = FALSE;
pAudio->FrameCount = 0;
}
void AudioClose(void)
{
}
void AudioInitDecoder(WORD StreamType)
{
/*
#if 0
pAudio->StrType = StreamType;
switch(pAudio->AudioState) {
case AUDIO_POWER_UP:
BoardWriteAudio(RESET, 1); // reset the decoder
//ALTERAClearPendingAudioIT(); // Clear pending audio interrupt generated by soft reset
BoardWriteAudio(INTR_EN, 0); // disable all interupts
BoardWriteAudio(INTR_EN + LSB, 0);
BoardWriteAudio(PLAY, 0); // disable play output
BoardWriteAudio(MUTE, 0); // do not mute output. LRclk and Sclk Stopped here
BoardWriteAudio(INVERT_SCLK, 0); // standard
BoardWriteAudio(INVERT_LRCLK, 1);// standard
#ifndef VALID3520
//**************************************************************
// Philips TDA1311 is a 16 bit DAC (oversampling 1x, 2x, 4x, 8x)
// -> LRCLK = SCLK / 32
// -> SCLK = PCMCLK / 8 (8 times oversampling => PCM_DIV = 3)
// => PCMCLK = 256 * Sampling Frequency
//**************************************************************
BoardWriteAudio(PCM_DIV, 3);
BoardWriteAudio(PCM_ORD, 0); // MSB first
BoardWriteAudio(PCM_18, 0); // 16 bits of PCM data
BoardWriteAudio(FORMAT, 0); // I2S output format
BoardWriteAudio(DIF, 0); // Optionnal in 16 bit output
#else
//**************************************************************
// Crystal CS4330 is an 18 bit DAC (oversampling 1x, 4x, 6x, 8x)
// -> LRCLK = SCLK / 64
// -> SCLK = PCMCLK / 4 (4 times oversampling => PCM_DIV = 1)
// => PCMCLK = 256 * Sampling Frequency
//**************************************************************
BoardWriteAudio(PCM_DIV, 1);
BoardWriteAudio(PCM_ORD, 0);
BoardWriteAudio(PCM_18, 1); // 18 bits of PCM data
BoardWriteAudio(FORMAT, 0); // I2S output format
BoardWriteAudio(DIF, 0); // Optionnal in 16 bit
#endif
BoardWriteAudio(STR_SEL, 0); // Default Stream Type is audio elem stream
BoardWriteAudio(CRC_ECM, 1); // mute on CRC error correction
BoardWriteAudio(SYNC_ECM, 1); // mute if Sync lost
BoardWriteAudio(SYNCHRO_CONFIRM, 1); // synchro confirmation mode
BoardWriteAudio(SYNC_REG, 0x3F); // layer, bitrate, fs fields not used
BoardWriteAudio(PACKET_SYNC_CHOICE, 0);// multiplexed stream
BoardWriteAudio(LATENCY, 0x0); // Low Lattency decoding
BoardWriteAudio(SYNC_LCK, 0x2); // locked after 2 good Sync
BoardWriteAudio(SIN_EN, 0x01); // Serial data input to enable bit buffer access
BoardWriteAudio(AUDIO_ID_EN, 0x0);// ignore audio stream ID
BoardWriteAudio(AUDIO_ID, 0x0); // audio stream ID ignored
BoardWriteAudio(FREE_FORM_H, 0x0);// not free format
BoardWriteAudio(FREE_FORM_L, 0x0);
BoardWriteAudio(DUAL_REG, 0); // Select Stereo Mode
AudioSetSTCParameters(44100UL);
BoardAudioSetSamplingFrequency(44100UL);
pAudio->FrameCount = 0; // Reset Frame Count.
pAudio->AudioState = AUDIO_INIT;
break;
default:
break;
}
#else
BoardWriteAudio(0xF0, 1); // reset the decoder
BoardWriteAudio(0xC6, 0);
BoardWriteAudio(0xEF, 1);
BoardWriteAudio(PCM_DIV, 2);
BoardWriteAudio(0x9f, 0);
BoardWriteAudio(0x99, 0);
BoardWriteAudio(0xB6, 3);
BoardWriteAudio(0x9e, 0);
BoardWriteAudio(0xa0, 0);
BoardWriteAudio(0x91, 0);
BoardWriteAudio(0xb8, 0);
BoardWriteAudio(0x96, 1);
BoardWriteAudio(0xd3, 0);
BoardWriteAudio(0xac, 0);
BoardWriteAudio(0xc4, 0);
BoardWriteAudio(0xc2, 1);
BoardWriteAudio(0xAE, 1);
#endif
*/
}
WORD AudioTestReg(void)
{
#if 0
WORD ReadValue;
BoardWriteAudio(ATTEN_L, 0x55);
BoardWriteAudio(ATTEN_R, 0xAA);
ReadValue = BoardReadAudio(ATTEN_L);
if ((ReadValue & 0x3F) != 0x15)
goto Error;
ReadValue = BoardReadAudio(ATTEN_R);
if ((ReadValue & 0x3F) != 0x2A)
goto Error;
return NO_ERROR;
Error :
SetErrorCode(ERR_AUDIO_REG_TEST_FAILED);
return BAD_REG_A;
#else
return NO_ERROR;
#endif
}
WORD AudioTest(void)
{
#if 0
WORD TestResult;
TestResult = AudioTestReg();
if (TestResult != NO_ERROR)
return TestResult;
else {
#ifdef DOSAPP
if (AudioTestInt(pAudio) == NO_IT_A)
return NO_IT_A;
else
#endif
return NO_ERROR;
}
#else
return NO_ERROR;
#endif
}
WORD AudioTestInt(void)
{
WORD err = NO_ERROR;
#if 0
U8 Threshold;
WORD a = 0;
pAudio->MaskItAudio = FIFT;
Threshold = BoardReadAudio(FIFO_IN_TRESHOLD);
//---- Configure audio
BoardWriteAudio(PLAY, 0x00);
BoardWriteAudio(FIFO_IN_TRESHOLD, 0x01);
//---- Enable FIFO full interrupt
BoardWriteAudio(INTR_EN, 0x00);
BoardWriteAudio(INTR_EN + LSB, 0x10);
//---- Write a byte to force an interrupt
BoardWriteAudio(DATA_IN, 0x00);
// wait for occurrence of first audio interrupt
while (pAudio->IntAudio == NO_IT_A) {
Delay(1000);
a++; /* incremented every 1 ms */
if (a >= 1000) {
DPF((Trace, "AudioTestInt failed !!"));
SetErrorCode(ERR_NO_AUDIO_INTR);
err = NO_IT_A; /* No interrupt */
break;
}
}
// Restore Interrupt mask
pAudio->MaskItAudio = 0;
AudioMaskInt();
BoardWriteAudio(FIFO_IN_TRESHOLD, Threshold);
BoardReadAudio(INTR); /* to clear audio interrupts flags */
#endif
return err;
}
// Set the decoding mode and parameters
void AudioSetMode(WORD Mode, WORD param)
{
#if 0
pAudio->DecodeMode = Mode;
switch (pAudio->DecodeMode) {
case PLAY_MODE:
BoardWriteAudio(MUTE, 0);
pAudio->fastForward = 0;
pAudio->decSlowDown = 0;
break;
case FAST_MODE:
pAudio->fastForward = 1;
pAudio->decSlowDown = 0;
break;
case SLOW_MODE:
pAudio->fastForward = 0;
pAudio->decSlowDown = param;
break;
}
#endif
}
// Decode
void AudioDecode(void)
{
#if 0
switch (pAudio->AudioState) {
case AUDIO_POWER_UP:
break;
case AUDIO_INIT:
// Change in synchro + buffer over BALF +PTS
pAudio->MaskItAudio = SYNC|BOF|PCMU|CRC| PTS;
BoardWriteAudio(INTR_EN, (BYTE)(pAudio->MaskItAudio & 0xFF));
BoardWriteAudio(INTR_EN + LSB, (BYTE)(pAudio->MaskItAudio >> 8 ));
//yg BoardWriteAudio(MUTE, 1); // This Starts SClk and LRClk outputs
BoardWriteAudio(PLAY, 1); // Start decoding Output is Mute
pAudio->AudioState = AUDIO_STC_INIT;
break;
case AUDIO_STC_INIT:
pAudio->AudioState = AUDIO_DECODE;
BoardWriteAudio(PLAY, 1); // Restart decoding (decoding had been stopped when first audio PTS detected)
BoardWriteAudio(MUTE, 0); // Stop Muting output
break;
case AUDIO_DECODE:
break;
case AUDIO_PAUSE:
case AUDIO_STEP:
BoardWriteAudio(PLAY, 1);
BoardWriteAudio(MUTE, 0);
pAudio->AudioState = AUDIO_DECODE;
break;
}
#endif
}
void AudioStep(void)
{
#if 0
BoardWriteAudio(MUTE, 0);
BoardWriteAudio(PLAY, 1);
pAudio->AudioState = AUDIO_STEP;
pAudio->Stepped = FALSE;
#endif
}
void AudioStop(void)
{
#if 0
switch(pAudio->AudioState) {
case AUDIO_POWER_UP:
break;
case AUDIO_INIT:
break;
case AUDIO_STC_INIT:
case AUDIO_DECODE:
pAudio->AudioState = AUDIO_POWER_UP;
AudioInitDecoder(pAudio, pAudio->StrType);
break;
}
#endif
}
void AudioPause(void)
{
#if 0
switch(pAudio->AudioState) {
case AUDIO_POWER_UP: /* After reset */
case AUDIO_INIT: /* Initialisation + test of the decoders */
case AUDIO_STC_INIT: /* STC of audio decoder initialized */
case AUDIO_DECODE: /* Normal decode */
BoardWriteAudio(MUTE, 1);
BoardWriteAudio(PLAY, 0);
pAudio->AudioState = AUDIO_PAUSE;
break;
}
#endif
}
WORD AudioGetState(void)
{
return ( pAudio->AudioState);
}
void AudioSetSTCParameters(DWORD SampFreq)
{
#if 0
// Note :
// STCCLK = PCMCLK (fixed inside STi3520A)
// (PCMCLK * inc) / div = 90kHz
switch(SampFreq){
case 32000UL:
// PCMCLK = 256 * 32 = 8192 kHz, inc = 45, div = 4096 -> 90kHz
BoardWriteAudio(STC_INC, 45);
BoardWriteAudio(STC_DIVH, 0x10);
BoardWriteAudio(STC_DIVL, 0x00);
break;
case 44100UL:
// PCMCLK = 256 * 44.1 = 11289.6 kHz, inc = 25, div = 3136 -> 90kHz
BoardWriteAudio(STC_INC, 25);
BoardWriteAudio(STC_DIVH, 0x0C);
BoardWriteAudio(STC_DIVL, 0x40);
break;
case 48000UL:
// PCMCLK = 256 * 48 = 12288 kHz, inc = 15, div = 2048 -> 90kHz
BoardWriteAudio(STC_INC, 15);
BoardWriteAudio(STC_DIVH, 0x08);
BoardWriteAudio(STC_DIVL, 0x00);
break;
default :
break;
}
BoardWriteAudio(STC_CTL, 0x40); // Load STC_VID on rising edge of VSYNC
#endif
}
DWORD AudioGetSTC(void)
{
#if 0
DWORD stc;
WORD j;
BoardWriteAudio(STC_CTL, 0x44); // load current STC value to STC
for ( j = 0; j < 0xF; j++)
;
stc = ( BoardReadAudio(STC_3 ) & 0xFFL ) << 24;
stc = stc | ( ( BoardReadAudio(STC_2 ) & 0xFFL ) << 16);
stc = stc | ( ( BoardReadAudio(STC_1 ) & 0xFFL ) << 8);
stc = stc | ( BoardReadAudio(STC_0 ) & 0xFFL);
return ( stc);
#else
return 0;
#endif
}
DWORD AudioGetVideoSTC(void)
{
#if 0
DWORD stc;
WORD j;
BoardWriteAudio(STC_CTL, 0x48); // load STC_VID to STC, Mode 0 mapping
// BoardWriteAudio(STC_CTL, 0x44); accu
// BoardWriteAudio(STC_CTL, 0x50);
for ( j = 0; j < 0xF; j++)
;
/*
stc = ( BoardReadAudio(STC_3 ) & 0xFFL ) << 24;
stc = stc | ((BoardReadAudio(STC_2) & 0xFFL ) << 16);
stc = stc | ((BoardReadAudio(STC_1) & 0xFFL ) << 8);
stc = stc | ((BoardReadAudio(STC_0) & 0xFFL ));
*/
stc = ( BoardReadAudio(STC_0) & 0xFFL ) << 0;
stc = stc | ((BoardReadAudio(STC_1) & 0xFFL ) << 8);
stc = stc | ((BoardReadAudio(STC_2) & 0xFFL ) << 16);
stc = stc | ((BoardReadAudio(STC_3) & 0xFFL ) << 24);
return stc;
#else
return 0;
#endif
}
void AudioInitSTC(DWORD stc)
{
#if 0
BoardWriteAudio(STC_0, (U8)(stc & 0xFFL));
stc >>= 8;
BoardWriteAudio(STC_1, (U8)(stc & 0xFFL));
stc >>= 8;
BoardWriteAudio(STC_2, (U8)(stc & 0xFFL));
stc >>= 8;
BoardWriteAudio(STC_3, (U8)(stc & 0xFFL));
BoardWriteAudio(STC_CTL, 0x41); // load STC to accumulator,
#endif
}
DWORD AudioGetPTS(void)
{
return pAudio->PtsAudio;
}
WORD AudioGetErrorMsg(void)
{
return pAudio->ErrorMsg;
}
void AudioSetRightVolume(WORD volume)
{
#if 0
BoardWriteAudio(ATTEN_R, (BYTE)volume);
#endif
}
void AudioSetLeftVolume(WORD volume)
{
#if 0
BoardWriteAudio(ATTEN_L, (BYTE)volume);
#endif
}
void AudioMute(void)
{
#if 0
if (pAudio->mute) {
BoardWriteAudio(MUTE, 0);
pAudio->mute = FALSE;
}
else {
BoardWriteAudio(MUTE, 1);
pAudio->mute = TRUE;
}
#endif
}
BOOL AudioIsFirstPTS(void)
{
return pAudio->FirstPTS;
}
void AudioSetStreamType(WORD StrType)
{
#if 0
BoardWriteAudio(STR_SEL, (BYTE)StrType);
#endif
}
void AudioInitPesParser (WORD StreamType)
{
#if 0
switch(StreamType)
{
case SYSTEM_STREAM:
case VIDEO_PACKET:
case AUDIO_PACKET:
case VIDEO_PES:
case AUDIO_PES:
BoardWriteAudio( STR_SEL, 1);
break;
case DUAL_PES:
BoardWriteAudio( STR_SEL, 4);
break;
case DUAL_ES:
BoardWriteAudio( STR_SEL, 0);
break;
case VIDEO_STREAM:
case AUDIO_STREAM:
BoardWriteAudio( STR_SEL, 0);
break;
}
#endif
}
void AudioMaskInt(void)
{
#if 0
BoardWriteAudio(INTR_EN, 0);
BoardWriteAudio(INTR_EN + LSB, 0);
#endif
}
void AudioRestoreInt(void)
{
#if 0
//HostDisplay(DISPLAY_FASTEST, "!%x!", pAudio->MaskItAudio);
BoardWriteAudio(INTR_EN, (BYTE)(pAudio->MaskItAudio & 0xFF));
BoardWriteAudio(INTR_EN + LSB, (BYTE)(pAudio->MaskItAudio >> 8));
#endif
}
BOOL AudioAudioInt(void)
{
#if 0
WORD int_stat_reg, i;
BOOLEAN bAudioIntr = FALSE;
// Read the interrupt status register
int_stat_reg = BoardReadAudio(INTR);
i = BoardReadAudio(INTR + LSB);
i = i << 8;
int_stat_reg = ( int_stat_reg & 0xFF ) | i;
int_stat_reg = int_stat_reg & pAudio->MaskItAudio; /* Mask the IT not used */
if(int_stat_reg)
bAudioIntr = TRUE;
/******************************************************/
/** FIFO FULL used to test audio interrupt generation**/
/******************************************************/
if (int_stat_reg & FIFT) {
pAudio->IntAudio = IT_A;
}
/******************************************************/
/** CHANGE SYNCHRO **/
/******************************************************/
if (int_stat_reg & SYNC) {
i = BoardReadAudio(SYNC_ST); // Synchronization status
if ((i & 0x3) == 3) { // Locked
// Disable Change in synchro
pAudio->MaskItAudio = pAudio->MaskItAudio & NSYNC;
// Next Interrupt should be change in sampling freq
pAudio->MaskItAudio = pAudio->MaskItAudio | SAMP;
}
}
/******************************************************/
/** CHANGE IN SAMPLING FREQUENCY **/
/******************************************************/
if (int_stat_reg & SAMP) {
i = BoardReadAudio(PCM_FS ) & 0x3; // Get Sampling frequency
switch(i) {
case 0 :
BoardAudioSetSamplingFrequency(44100UL);
AudioSetSTCParameters(44100UL);
break;
case 1 :
BoardAudioSetSamplingFrequency(48000UL);
AudioSetSTCParameters(48000UL);
break;
case 2 :
BoardAudioSetSamplingFrequency(32000UL);
AudioSetSTCParameters(32000UL);
break;
default :
break;
}
// Disable change in sampling frequency
pAudio->MaskItAudio = pAudio->MaskItAudio & NSAMP;
}
/******************************************************/
/** CRC error **/
/******************************************************/
if (int_stat_reg & CRC) {
}
/******************************************************/
/** PCM Underflow **/
/******************************************************/
if (int_stat_reg & PCMU) {
}
/******************************************************/
/** Begining of Frame **/
/******************************************************/
if (int_stat_reg & BOF) {
DWORD STC = AudioGetVideoSTC();
static DWORD STCOld;
// HostDisplay(DISPLAY_FASTEST, "STCBOF = %8lu D = %5ld\r\n", STC, STC - STCOld);
// STCOld = STC;
// Check if stepping
if ((pAudio->AudioState == AUDIO_STEP) && (pAudio->Stepped == FALSE)) {
BoardWriteAudio(MUTE, 1);
BoardWriteAudio(PLAY, 0);
pAudio->Stepped = TRUE;
}
// If Slow motion or Fast forward, Mute Audio
if ( pAudio->DecodeMode != PLAY_MODE ) {
BoardWriteAudio(MUTE, 1);
pAudio->mute = TRUE;
if ((pAudio->FrameCount % 4) && (pAudio->fastForward))
BoardWriteAudio(SKIP, 1);
else if ((pAudio->DecodeMode == SLOW_MODE ) &&
((pAudio->FrameCount % (pAudio->decSlowDown + 1)) != 0))
BoardWriteAudio(REPEAT, 1);
}
pAudio->FrameCount++; // Increment Frame Count
}
/******************************************************/
/** PTS detected **/
/******************************************************/
if ( int_stat_reg & PTS ) {
DWORD pts;
//DBG1('p');
/*
BoardReadAudio(PTS_4); // To clear pts interrupt
pts = (BoardReadAudio(PTS_3) & 0xFFL) << 24;
pts = pts | ((BoardReadAudio(PTS_2 ) & 0xFFL) << 16);
pts = pts | ((BoardReadAudio(PTS_1 ) & 0xFFL) << 8);
pts = pts | ( BoardReadAudio(PTS_0 ) & 0xFFL);
*/
pts = (BoardReadAudio(PTS_0) & 0xFFL) << 0;
pts = pts | ((BoardReadAudio(PTS_1) & 0xFFL) << 8);
pts = pts | ((BoardReadAudio(PTS_2) & 0xFFL) << 16);
pts = pts | ((BoardReadAudio(PTS_3) & 0xFFL) << 24);
BoardReadAudio(PTS_4); // To clear pts interrupt
pAudio->PtsAudio = pts;
if (pAudio->AudioState == AUDIO_STC_INIT) {
pAudio->FirstPTS = TRUE;
//yg BoardWriteAudio(PLAY, 0);
}
if (pAudio->AudioState == AUDIO_DECODE) {
// HostDirectPutChar('P', BLACK, LIGHTBLUE);
AudioInitSTC ( pts);
// DWORD STC = AudioGetVideoSTC();
// HostDisplay(DISPLAY_FASTEST, "STC = %8lu PTSA = %8lu D = %8ld\r\n", STC, pts, STC - pts);
}
}
return bAudioIntr;
#else
return FALSE;
#endif
}