From f93596fd90fec804aa45f941157929178574bfe5 Mon Sep 17 00:00:00 2001 From: Patrice Mandin Date: Fri, 29 Oct 2004 09:56:53 +0000 Subject: [PATCH] Date: Fri, 29 Oct 2004 11:47:09 +0200 From: Patrice Mandin Subject: Reworked audio drivers for Atari platform These are reworked audio drivers for the Atari platform. Previous drivers were missing some features: - Test external clock plugged to DSP port on Atari Falcon 030. - Ability to select internal or external clock. So now, I generate a list of frequencies available, with the master clock and predivisor to use. One big caveat to this: I do not have an external clock, so I hope it works. --- src/audio/mint/SDL_mintaudio.c | 56 ++++++-- src/audio/mint/SDL_mintaudio.h | 25 +++- src/audio/mint/SDL_mintaudio_dma8.c | 39 ++++-- src/audio/mint/SDL_mintaudio_dma8.h | 27 +++- src/audio/mint/SDL_mintaudio_gsxb.c | 36 ++--- src/audio/mint/SDL_mintaudio_it.S | 15 +- src/audio/mint/SDL_mintaudio_mcsn.c | 59 ++++---- src/audio/mint/SDL_mintaudio_stfa.c | 25 ++-- src/audio/mint/SDL_mintaudio_xbios.c | 201 +++++++++++++++++++++++++-- 9 files changed, 373 insertions(+), 110 deletions(-) diff --git a/src/audio/mint/SDL_mintaudio.c b/src/audio/mint/SDL_mintaudio.c index 649706f71..2a065af11 100644 --- a/src/audio/mint/SDL_mintaudio.c +++ b/src/audio/mint/SDL_mintaudio.c @@ -41,6 +41,7 @@ Uint8 *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */ unsigned long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->size */ unsigned short SDL_MintAudio_numbuf; /* Buffer to play */ unsigned short SDL_MintAudio_mutex; +unsigned long SDL_MintAudio_clocktics; cookie_stfa_t *SDL_MintAudio_stfa; /* The callback function, called by each driver whenever needed */ @@ -64,30 +65,57 @@ void SDL_MintAudio_Callback(void) } } -/* Simple function to search for the nearest frequency */ -int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq) +/* Add a new frequency/clock/predivisor to the current list */ +void SDL_MintAudio_AddFrequency(_THIS, Uint32 frequency, Uint32 clock, Uint32 prediv) +{ + int i, p; + + if (MINTAUDIO_freqcount==MINTAUDIO_maxfreqs) { + return; + } + + /* Search where to insert the frequency (highest first) */ + for (p=0; p MINTAUDIO_frequencies[p].frequency) { + break; + } + } + + /* Put all following ones farer */ + if (MINTAUDIO_freqcount>0) { + for (i=MINTAUDIO_freqcount; i>p; i--) { + MINTAUDIO_frequencies[i].frequency = MINTAUDIO_frequencies[i-1].frequency; + MINTAUDIO_frequencies[i].masterclock = MINTAUDIO_frequencies[i-1].masterclock; + MINTAUDIO_frequencies[i].predivisor = MINTAUDIO_frequencies[i-1].predivisor; + } + } + + /* And insert new one */ + MINTAUDIO_frequencies[p].frequency = frequency; + MINTAUDIO_frequencies[p].masterclock = clock; + MINTAUDIO_frequencies[p].predivisor = prediv; + + MINTAUDIO_freqcount++; +} + +/* Search for the nearest frequency */ +int SDL_MintAudio_SearchFrequency(_THIS, int desired_freq) { int i; /* Only 1 freq ? */ - if (MINTAUDIO_nfreq==1) { - return(MINTAUDIO_sfreq); + if (MINTAUDIO_freqcount==1) { + return 0; } /* Check the array */ - for (i=MINTAUDIO_sfreq; i= ((MINTAUDIO_hardfreq[i]+MINTAUDIO_hardfreq[i+1])>>1)) { + for (i=0; i= ((MINTAUDIO_frequencies[i].frequency+ + MINTAUDIO_frequencies[i+1].frequency)>>1)) { return i; } } /* Not in the array, give the latest */ - return MINTAUDIO_nfreq-1; + return MINTAUDIO_freqcount-1; } diff --git a/src/audio/mint/SDL_mintaudio.h b/src/audio/mint/SDL_mintaudio.h index 63ebf97cf..5515ad145 100644 --- a/src/audio/mint/SDL_mintaudio.h +++ b/src/audio/mint/SDL_mintaudio.h @@ -35,17 +35,25 @@ /* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this +/* 16 predivisors with 3 clocks max. */ +#define MINTAUDIO_maxfreqs (16*3) + +typedef struct { + Uint32 frequency; + Uint32 masterclock; + Uint32 predivisor; +} mint_frequency_t; + struct SDL_PrivateAudioData { - Uint32 hardfreq[16]; /* Array of replay freqs of the hardware */ - int sfreq; /* First number of freq to use in the array */ - int nfreq; /* Number of freqs to use in the array */ + mint_frequency_t frequencies[MINTAUDIO_maxfreqs]; + int freq_count; /* Number of frequencies in the array */ int numfreq; /* Number of selected frequency */ }; /* Old variable names */ -#define MINTAUDIO_hardfreq (this->hidden->hardfreq) -#define MINTAUDIO_sfreq (this->hidden->sfreq) -#define MINTAUDIO_nfreq (this->hidden->nfreq) + +#define MINTAUDIO_frequencies (this->hidden->frequencies) +#define MINTAUDIO_freqcount (this->hidden->freq_count) #define MINTAUDIO_numfreq (this->hidden->numfreq) /* _MCH cookie (values>>16) */ @@ -110,14 +118,17 @@ extern unsigned long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->s extern unsigned short SDL_MintAudio_numbuf; /* Buffer to play */ extern unsigned short SDL_MintAudio_mutex; extern cookie_stfa_t *SDL_MintAudio_stfa; +extern unsigned long SDL_MintAudio_clocktics; /* Functions */ void SDL_MintAudio_Callback(void); -int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq); +void SDL_MintAudio_AddFrequency(_THIS, Uint32 frequency, Uint32 clock, Uint32 prediv); +int SDL_MintAudio_SearchFrequency(_THIS, int desired_freq); /* ASM interrupt functions */ void SDL_MintAudio_GsxbInterrupt(void); void SDL_MintAudio_EmptyGsxbInterrupt(void); +void SDL_MintAudio_XbiosInterruptMeasureClock(void); void SDL_MintAudio_XbiosInterrupt(void); void SDL_MintAudio_Dma8Interrupt(void); void SDL_MintAudio_StfaInterrupt(void); diff --git a/src/audio/mint/SDL_mintaudio_dma8.c b/src/audio/mint/SDL_mintaudio_dma8.c index 8edfb01e3..0c793ca7d 100644 --- a/src/audio/mint/SDL_mintaudio_dma8.c +++ b/src/audio/mint/SDL_mintaudio_dma8.c @@ -53,7 +53,7 @@ /* Debug print info */ #define DEBUG_NAME "audio:dma8: " -#if 0 +#if 1 #define DEBUG_PRINT(what) \ { \ printf what; \ @@ -100,11 +100,12 @@ static int Audio_Available(void) } /* Check if we have 8 bits audio */ +/* if ((cookie_snd & SND_8BIT)==0) { DEBUG_PRINT((DEBUG_NAME "no 8 bits sound\n")); return(0); } - +*/ if ((cookie_mch>>16)>MCH_F30) { DEBUG_PRINT((DEBUG_NAME "unknown 8 bits audio chip\n")); return 0; @@ -218,7 +219,7 @@ static void Mint_CloseAudio(_THIS) static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) { - int i, masterprediv; + int i, masterprediv, sfreq; unsigned long masterclock; DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); @@ -231,8 +232,7 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) spec->format = AUDIO_S8; /* Calculate and select the closest frequency */ - MINTAUDIO_nfreq=4; - MINTAUDIO_sfreq=0; + sfreq=0; masterclock=MASTERCLOCK_STE; masterprediv=MASTERPREDIV_STE; switch(cookie_mch>>16) { @@ -248,18 +248,27 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) break; case MCH_F30: masterclock=MASTERCLOCK_FALCON1; - masterprediv=MASTERPREDIV_FALCON<<1; - MINTAUDIO_nfreq=3; - MINTAUDIO_sfreq=1; + masterprediv=MASTERPREDIV_FALCON; + sfreq=1; break; } - for (i=MINTAUDIO_sfreq;ifreq); - spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq]; +#if 1 + for (i=0; ifreq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); @@ -298,11 +307,11 @@ static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) DMAAUDIO_IO.end_mid = (buffer>>8) & 255; DMAAUDIO_IO.end_low = buffer & 255; - mode = 3-MINTAUDIO_numfreq; + mode = 3-MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; if (spec->channels==1) { mode |= 1<<7; } - DMAAUDIO_IO.mode = mode; + DMAAUDIO_IO.sound_ctrl = mode; /* Set interrupt */ Jdisint(MFP_DMASOUND); diff --git a/src/audio/mint/SDL_mintaudio_dma8.h b/src/audio/mint/SDL_mintaudio_dma8.h index 4313a5c85..3ef50a244 100644 --- a/src/audio/mint/SDL_mintaudio_dma8.h +++ b/src/audio/mint/SDL_mintaudio_dma8.h @@ -21,9 +21,9 @@ */ /* - DMA 8bits audio definitions + DMA 8bits and Falcon Codec audio definitions - Patrice Mandin + Patrice Mandin, Didier Méquignon */ #ifndef _SDL_mintaudio_dma8_h @@ -57,8 +57,27 @@ struct DMAAUDIO_IO_S { unsigned char dummy10[12]; - unsigned char track_select; /* CODEC only */ - unsigned char mode; + unsigned char track_ctrl; /* CODEC only */ + unsigned char sound_ctrl; + unsigned short sound_data; + unsigned short sound_mask; + + unsigned char dummy11[10]; + + unsigned short dev_ctrl; + unsigned short dest_ctrl; + unsigned short sync_div; + unsigned char track_rec; + unsigned char adderin_input; + unsigned char channel_input; + unsigned char channel_amplification; + unsigned char channel_reduction; + + unsigned char dummy12[6]; + + unsigned char data_direction; + unsigned char dummy13; + unsigned char dev_data; }; #define DMAAUDIO_IO ((*(volatile struct DMAAUDIO_IO_S *)DMAAUDIO_IO_BASE)) diff --git a/src/audio/mint/SDL_mintaudio_gsxb.c b/src/audio/mint/SDL_mintaudio_gsxb.c index 962a73f02..84660b095 100644 --- a/src/audio/mint/SDL_mintaudio_gsxb.c +++ b/src/audio/mint/SDL_mintaudio_gsxb.c @@ -53,7 +53,7 @@ /* Debug print info */ #define DEBUG_NAME "audio:gsxb: " -#if 0 +#if 1 #define DEBUG_PRINT(what) \ { \ printf what; \ @@ -179,29 +179,21 @@ static void Mint_CloseAudio(_THIS) /* Stop replay */ Buffoper(0); - DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n")); - /* Uninstall interrupt */ if (NSetinterrupt(2, SI_NONE, SDL_MintAudio_EmptyGsxbInterrupt)<0) { DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n")); } - DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n")); - /* Wait if currently playing sound */ while (SDL_MintAudio_mutex != 0) { } - DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n")); - /* Clear buffers */ if (SDL_MintAudio_audiobuf[0]) { Mfree(SDL_MintAudio_audiobuf[0]); SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; } - DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n")); - /* Unlock sound system */ Unlocksnd(); } @@ -278,15 +270,22 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) } /* Calculate and select the closest frequency */ - MINTAUDIO_sfreq=1; - MINTAUDIO_nfreq=12; - for (i=MINTAUDIO_sfreq;ifreq); - spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq]; +#if 1 + for (i=0; ifreq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); @@ -299,7 +298,7 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) { - int channels_mode; + int channels_mode, prediv; void *buffer; /* Stop currently playing sound */ @@ -333,7 +332,8 @@ static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); } - Devconnect(DMAPLAY, DAC, CLKEXT, MINTAUDIO_numfreq, 1); + prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; + Devconnect(DMAPLAY, DAC, CLKEXT, prediv, 1); /* Set buffer */ buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; diff --git a/src/audio/mint/SDL_mintaudio_it.S b/src/audio/mint/SDL_mintaudio_it.S index 2ac0353c5..764bbd7ea 100644 --- a/src/audio/mint/SDL_mintaudio_it.S +++ b/src/audio/mint/SDL_mintaudio_it.S @@ -23,7 +23,7 @@ /* Audio interrupts - Patrice Mandin + Patrice Mandin, Didier Méquignon */ .text @@ -33,6 +33,7 @@ .globl _SDL_MintAudio_GsxbInterrupt .globl _SDL_MintAudio_EmptyGsxbInterrupt .globl _SDL_MintAudio_XbiosInterrupt + .globl _SDL_MintAudio_XbiosInterruptMeasureClock .globl _SDL_MintAudio_Dma8Interrupt .globl _SDL_MintAudio_StfaInterrupt @@ -40,6 +41,7 @@ .globl _SDL_MintAudio_audiobuf .globl _SDL_MintAudio_numbuf .globl _SDL_MintAudio_audiosize + .globl _SDL_MintAudio_clocktics .globl _SDL_MintAudio_stfa @@ -94,6 +96,17 @@ _SDL_MintAudio_GsxbInterrupt: _SDL_MintAudio_EmptyGsxbInterrupt: rts +/*--- Xbios interrupt vector to measure Falcon external clock ---*/ + +_SDL_MintAudio_XbiosInterruptMeasureClock: /* 1 mS */ + + btst #0,0xFFFF8901:w /* state DMA sound */ + beqs SDL_MintAudio_EndIntMeasure + addql #1,_SDL_MintAudio_clocktics +SDL_MintAudio_EndIntMeasure: + bclr #5,0xFFFFFA0F:w /* Clear service bit */ + rte + /*--- Xbios interrupt vector ---*/ _SDL_MintAudio_XbiosInterrupt: diff --git a/src/audio/mint/SDL_mintaudio_mcsn.c b/src/audio/mint/SDL_mintaudio_mcsn.c index 4515fef93..fe9ae90b1 100644 --- a/src/audio/mint/SDL_mintaudio_mcsn.c +++ b/src/audio/mint/SDL_mintaudio_mcsn.c @@ -53,7 +53,7 @@ /* Debug print info */ #define DEBUG_NAME "audio:mcsn: " -#if 0 +#if 1 #define DEBUG_PRINT(what) \ { \ printf what; \ @@ -217,14 +217,12 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) DEBUG_PRINT(("freq=%d\n", spec->freq)); /* Check formats available */ - MINTAUDIO_nfreq=4; - MINTAUDIO_sfreq=0; + MINTAUDIO_freqcount=0; switch(cookie_mcsn->play) { case MCSN_ST: spec->channels=1; spec->format=8; /* FIXME: is it signed or unsigned ? */ - MINTAUDIO_nfreq=1; - MINTAUDIO_hardfreq[0]=12500; + SDL_MintAudio_AddFrequency(this, 12500, 0, 0); break; case MCSN_TT: /* Also STE, Mega STE */ spec->format=AUDIO_S8; @@ -234,21 +232,22 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) masterclock=MASTERCLOCK_TT; masterprediv=MASTERPREDIV_TT; } - for (i=MINTAUDIO_sfreq;ires1 != 0) { - masterclock=cookie_mcsn->res1; + for (i=1; i<12; i++) { + /* Remove unusable Falcon codec predivisors */ + if ((i==6) || (i==8) || (i==10)) { + continue; + } + SDL_MintAudio_AddFrequency(this, MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)), CLK25M, i+1); } - for (i=MINTAUDIO_sfreq;ires1 != 0) { + for (i=1; i<4; i++) { + SDL_MintAudio_AddFrequency(this, (cookie_mcsn->res1)/(MASTERPREDIV_FALCON*(1<format |= 0x8000; /* Audio is always signed */ if ((spec->format & 0x00ff)==16) { @@ -258,8 +257,17 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) break; } - MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, (cookie_mch>>16)==MCH_F30, spec->freq); - spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq]; +#if 1 + for (i=0; ifreq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); @@ -272,7 +280,7 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) { - int channels_mode; + int channels_mode, prediv, dmaclock; void *buffer; /* Stop currently playing sound */ @@ -297,20 +305,17 @@ static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); } + dmaclock = MINTAUDIO_frequencies[MINTAUDIO_numfreq].masterclock; + prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; switch(cookie_mcsn->play) { case MCSN_TT: Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, 1); - Soundcmd(SETPRESCALE, 3-MINTAUDIO_numfreq); + Soundcmd(SETPRESCALE, prediv); DEBUG_PRINT((DEBUG_NAME "STE/TT prescaler selected\n")); break; case MCSN_FALCON: - if (cookie_mcsn->res1 != 0) { - Devconnect(DMAPLAY, DAC, CLKEXT, MINTAUDIO_numfreq, 1); - DEBUG_PRINT((DEBUG_NAME "External clock selected, prescaler %d\n", MINTAUDIO_numfreq)); - } else { - Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1); - DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq)); - } + Devconnect(DMAPLAY, DAC, dmaclock, prediv, 1); + DEBUG_PRINT((DEBUG_NAME "Falcon prescaler selected\n")); break; } diff --git a/src/audio/mint/SDL_mintaudio_stfa.c b/src/audio/mint/SDL_mintaudio_stfa.c index addffdb2a..e2ae4cc91 100644 --- a/src/audio/mint/SDL_mintaudio_stfa.c +++ b/src/audio/mint/SDL_mintaudio_stfa.c @@ -53,7 +53,7 @@ /* Debug print info */ #define DEBUG_NAME "audio:stfa: " -#if 0 +#if 1 #define DEBUG_PRINT(what) \ { \ printf what; \ @@ -211,15 +211,22 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) DEBUG_PRINT(("freq=%d\n", spec->freq)); /* Check formats available */ - MINTAUDIO_nfreq=16; - MINTAUDIO_sfreq=0; - for (i=MINTAUDIO_sfreq;ifreq); - spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq]; +#if 1 + for (i=0; ifreq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); @@ -243,7 +250,7 @@ static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) cookie_stfa->sound_enable=STFA_PLAY_DISABLE; /* Select replay format */ - cookie_stfa->sound_control = 15-MINTAUDIO_numfreq; + cookie_stfa->sound_control = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; if ((spec->format & 0xff)==8) { cookie_stfa->sound_control |= STFA_FORMAT_8BIT; } else { diff --git a/src/audio/mint/SDL_mintaudio_xbios.c b/src/audio/mint/SDL_mintaudio_xbios.c index 211d85165..4509f716b 100644 --- a/src/audio/mint/SDL_mintaudio_xbios.c +++ b/src/audio/mint/SDL_mintaudio_xbios.c @@ -24,12 +24,13 @@ MiNT audio driver using XBIOS functions (Falcon) - Patrice Mandin + Patrice Mandin, Didier Méquignon */ #include #include #include +#include /* Mint includes */ #include @@ -45,6 +46,7 @@ #include "SDL_atarimxalloc_c.h" #include "SDL_mintaudio.h" +#include "SDL_mintaudio_dma8.h" /*--- Defines ---*/ @@ -52,7 +54,7 @@ /* Debug print info */ #define DEBUG_NAME "audio:xbios: " -#if 0 +#if 1 #define DEBUG_PRINT(what) \ { \ printf what; \ @@ -186,9 +188,150 @@ static void Mint_CloseAudio(_THIS) Unlocksnd(); } +/* Falcon XBIOS implementation of Devconnect() is buggy with external clock */ +static void Devconnect2(int src, int dst, int sclk, int pre) +{ + static const unsigned short MASK1[3] = { 0, 0x6000, 0 }; + static const unsigned short MASK2[4] = { 0xFFF0, 0xFF8F, 0xF0FF, 0x0FFF }; + static const unsigned short INDEX1[4] = { 1, 3, 5, 7 }; + static const unsigned short INDEX2[4] = { 0, 2, 4, 6 }; + unsigned short sync_div,dev_ctrl,dest_ctrl; + void *oldstack; + + if (dst==0) { + return; + } + + oldstack=(void *)Super(0); + + dev_ctrl = DMAAUDIO_IO.dev_ctrl; + dest_ctrl = DMAAUDIO_IO.dest_ctrl; + dev_ctrl &= MASK2[src]; + + if (src==ADC) { + dev_ctrl |= MASK1[sclk]; + } else { + dev_ctrl |= (INDEX1[sclk] << (src<<4)); + } + + if (dst & DMAREC) { + dest_ctrl &= 0xFFF0; + dest_ctrl |= INDEX1[src]; + } + + if (dst & DSPRECV) { + dest_ctrl &= 0xFF8F; + dest_ctrl |= (INDEX1[src]<<4); + } + + if (dst & EXTOUT) { + dest_ctrl &= 0xF0FF; + dest_ctrl |= (INDEX1[src]<<8); + } + + if (dst & DAC) { + dev_ctrl &= 0x0FFF; + dev_ctrl |= MASK1[sclk]; + dest_ctrl &= 0x0FFF; + dest_ctrl |= (INDEX2[src]<<12); + } + + sync_div = DMAAUDIO_IO.sync_div; + if (sclk==CLKEXT) { + pre<<=8; + sync_div &= 0xF0FF; + } else { + sync_div &= 0xFFF0; + } + sync_div |= pre; + + DMAAUDIO_IO.dev_ctrl = dev_ctrl; + DMAAUDIO_IO.dest_ctrl = dest_ctrl; + DMAAUDIO_IO.sync_div = sync_div; + + Super(oldstack); +} + +static Uint32 Mint_CheckExternalClock(void) +{ +#define SIZE_BUF_CLOCK_MEASURE (44100/10) + + unsigned long cookie_snd; + Uint32 masterclock; + char *buffer; + int i; + + /* DSP present with its GPIO port ? */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + return 0; + } + if ((cookie_snd & SND_DSP)==0) { + return 0; + } + + buffer = Atari_SysMalloc(SIZE_BUF_CLOCK_MEASURE, MX_STRAM); + if (buffer==NULL) { + DEBUG_PRINT((DEBUG_NAME "Not enough memory for the measure\n")); + return 0; + } + memset(buffer, 0, SIZE_BUF_CLOCK_MEASURE); + + masterclock=0; + + Buffoper(0); + Settracks(0,0); + Setmontracks(0); + Setmode(MONO8); + Jdisint(MFP_TIMERA); + + for (i=0; i<2; i++) { + Gpio(GPIO_SET,7); /* DSP port gpio outputs */ + Gpio(GPIO_WRITE,2+i); /* 22.5792/24.576 MHz for 44.1/48KHz */ + Devconnect2(DMAPLAY, DAC, CLKEXT, CLK50K); /* Matrix and clock source */ + Setbuffer(0, buffer, buffer + SIZE_BUF_CLOCK_MEASURE); /* Set buffer */ + Xbtimer(XB_TIMERA, 5, 38, SDL_MintAudio_XbiosInterruptMeasureClock); /* delay mode timer A, prediv /64, 1KHz */ + Jenabint(MFP_TIMERA); + SDL_MintAudio_clocktics = 0; + Buffoper(SB_PLA_ENA); + usleep(110000); + + if((Buffoper(-1) & 1)==0) { + if (SDL_MintAudio_clocktics) { + unsigned long khz; + + khz = ((SIZE_BUF_CLOCK_MEASURE/SDL_MintAudio_clocktics) +1) & 0xFFFFFFFE; + DEBUG_PRINT((DEBUG_NAME "measure %d: freq=%lu KHz\n", i+1, khz)); + + if (i==0) { + if(khz==44) { + masterclock = MASTERCLOCK_44K; + } + } else { + if(khz==48) { + masterclock = MASTERCLOCK_48K; + } + } + } else { + DEBUG_PRINT((DEBUG_NAME "No measure\n")); + } + } else { + DEBUG_PRINT((DEBUG_NAME "No SDMA clock\n")); + } + + Buffoper(0); /* stop */ + Jdisint(MFP_TIMERA); /* Uninstall interrupt */ + if (masterclock == 0) + break; + } + + Mfree(buffer); + return masterclock; +} + static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) { int i; + Uint32 extclock; DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); @@ -202,16 +345,35 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) spec->channels=2; /* 16 bits always stereo */ } - /* FIXME: check for an external clock */ - MINTAUDIO_sfreq=1; - MINTAUDIO_nfreq=12; - for (i=MINTAUDIO_sfreq;i0) { + for (i=1; i<4; i++) { + SDL_MintAudio_AddFrequency(this, extclock/(MASTERPREDIV_FALCON*(1<freq); - spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq]; + MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); @@ -224,7 +386,7 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) { - int channels_mode; + int channels_mode, dmaclock, prediv; void *buffer; /* Stop currently playing sound */ @@ -249,10 +411,19 @@ static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); } - /* FIXME: select an external clock */ - - Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1); - DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq)); + dmaclock = MINTAUDIO_frequencies[MINTAUDIO_numfreq].masterclock; + prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; + if (dmaclock != MASTERCLOCK_FALCON1) { + Gpio(GPIO_SET,7); /* DSP port gpio outputs */ + if (dmaclock == MASTERCLOCK_44K) { + Gpio(GPIO_WRITE,2); /* 22.5792 MHz for 44.1KHz */ + } else { + Gpio(GPIO_WRITE,3); /* 24.576 MHz for 48KHz */ + } + Devconnect2(DMAPLAY, DAC, CLKEXT, prediv); + } else { + Devconnect(DMAPLAY, DAC, CLK25M, prediv, 1); + } /* Set buffer */ buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];