comparison src/audio/mint/SDL_mintaudio_xbios.c @ 961:185acc07127a

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.
author Patrice Mandin <patmandin@gmail.com>
date Fri, 29 Oct 2004 09:56:53 +0000
parents b8d311d90021
children 176240cf4405
comparison
equal deleted inserted replaced
960:eec28a5278be 961:185acc07127a
22 22
23 /* 23 /*
24 MiNT audio driver 24 MiNT audio driver
25 using XBIOS functions (Falcon) 25 using XBIOS functions (Falcon)
26 26
27 Patrice Mandin 27 Patrice Mandin, Didier Méquignon
28 */ 28 */
29 29
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <stdio.h> 31 #include <stdio.h>
32 #include <string.h> 32 #include <string.h>
33 #include <unistd.h>
33 34
34 /* Mint includes */ 35 /* Mint includes */
35 #include <mint/osbind.h> 36 #include <mint/osbind.h>
36 #include <mint/falcon.h> 37 #include <mint/falcon.h>
37 #include <mint/cookie.h> 38 #include <mint/cookie.h>
43 #include "SDL_sysaudio.h" 44 #include "SDL_sysaudio.h"
44 45
45 #include "SDL_atarimxalloc_c.h" 46 #include "SDL_atarimxalloc_c.h"
46 47
47 #include "SDL_mintaudio.h" 48 #include "SDL_mintaudio.h"
49 #include "SDL_mintaudio_dma8.h"
48 50
49 /*--- Defines ---*/ 51 /*--- Defines ---*/
50 52
51 #define MINT_AUDIO_DRIVER_NAME "mint_xbios" 53 #define MINT_AUDIO_DRIVER_NAME "mint_xbios"
52 54
53 /* Debug print info */ 55 /* Debug print info */
54 #define DEBUG_NAME "audio:xbios: " 56 #define DEBUG_NAME "audio:xbios: "
55 #if 0 57 #if 1
56 #define DEBUG_PRINT(what) \ 58 #define DEBUG_PRINT(what) \
57 { \ 59 { \
58 printf what; \ 60 printf what; \
59 } 61 }
60 #else 62 #else
184 186
185 /* Unlock sound system */ 187 /* Unlock sound system */
186 Unlocksnd(); 188 Unlocksnd();
187 } 189 }
188 190
191 /* Falcon XBIOS implementation of Devconnect() is buggy with external clock */
192 static void Devconnect2(int src, int dst, int sclk, int pre)
193 {
194 static const unsigned short MASK1[3] = { 0, 0x6000, 0 };
195 static const unsigned short MASK2[4] = { 0xFFF0, 0xFF8F, 0xF0FF, 0x0FFF };
196 static const unsigned short INDEX1[4] = { 1, 3, 5, 7 };
197 static const unsigned short INDEX2[4] = { 0, 2, 4, 6 };
198 unsigned short sync_div,dev_ctrl,dest_ctrl;
199 void *oldstack;
200
201 if (dst==0) {
202 return;
203 }
204
205 oldstack=(void *)Super(0);
206
207 dev_ctrl = DMAAUDIO_IO.dev_ctrl;
208 dest_ctrl = DMAAUDIO_IO.dest_ctrl;
209 dev_ctrl &= MASK2[src];
210
211 if (src==ADC) {
212 dev_ctrl |= MASK1[sclk];
213 } else {
214 dev_ctrl |= (INDEX1[sclk] << (src<<4));
215 }
216
217 if (dst & DMAREC) {
218 dest_ctrl &= 0xFFF0;
219 dest_ctrl |= INDEX1[src];
220 }
221
222 if (dst & DSPRECV) {
223 dest_ctrl &= 0xFF8F;
224 dest_ctrl |= (INDEX1[src]<<4);
225 }
226
227 if (dst & EXTOUT) {
228 dest_ctrl &= 0xF0FF;
229 dest_ctrl |= (INDEX1[src]<<8);
230 }
231
232 if (dst & DAC) {
233 dev_ctrl &= 0x0FFF;
234 dev_ctrl |= MASK1[sclk];
235 dest_ctrl &= 0x0FFF;
236 dest_ctrl |= (INDEX2[src]<<12);
237 }
238
239 sync_div = DMAAUDIO_IO.sync_div;
240 if (sclk==CLKEXT) {
241 pre<<=8;
242 sync_div &= 0xF0FF;
243 } else {
244 sync_div &= 0xFFF0;
245 }
246 sync_div |= pre;
247
248 DMAAUDIO_IO.dev_ctrl = dev_ctrl;
249 DMAAUDIO_IO.dest_ctrl = dest_ctrl;
250 DMAAUDIO_IO.sync_div = sync_div;
251
252 Super(oldstack);
253 }
254
255 static Uint32 Mint_CheckExternalClock(void)
256 {
257 #define SIZE_BUF_CLOCK_MEASURE (44100/10)
258
259 unsigned long cookie_snd;
260 Uint32 masterclock;
261 char *buffer;
262 int i;
263
264 /* DSP present with its GPIO port ? */
265 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
266 return 0;
267 }
268 if ((cookie_snd & SND_DSP)==0) {
269 return 0;
270 }
271
272 buffer = Atari_SysMalloc(SIZE_BUF_CLOCK_MEASURE, MX_STRAM);
273 if (buffer==NULL) {
274 DEBUG_PRINT((DEBUG_NAME "Not enough memory for the measure\n"));
275 return 0;
276 }
277 memset(buffer, 0, SIZE_BUF_CLOCK_MEASURE);
278
279 masterclock=0;
280
281 Buffoper(0);
282 Settracks(0,0);
283 Setmontracks(0);
284 Setmode(MONO8);
285 Jdisint(MFP_TIMERA);
286
287 for (i=0; i<2; i++) {
288 Gpio(GPIO_SET,7); /* DSP port gpio outputs */
289 Gpio(GPIO_WRITE,2+i); /* 22.5792/24.576 MHz for 44.1/48KHz */
290 Devconnect2(DMAPLAY, DAC, CLKEXT, CLK50K); /* Matrix and clock source */
291 Setbuffer(0, buffer, buffer + SIZE_BUF_CLOCK_MEASURE); /* Set buffer */
292 Xbtimer(XB_TIMERA, 5, 38, SDL_MintAudio_XbiosInterruptMeasureClock); /* delay mode timer A, prediv /64, 1KHz */
293 Jenabint(MFP_TIMERA);
294 SDL_MintAudio_clocktics = 0;
295 Buffoper(SB_PLA_ENA);
296 usleep(110000);
297
298 if((Buffoper(-1) & 1)==0) {
299 if (SDL_MintAudio_clocktics) {
300 unsigned long khz;
301
302 khz = ((SIZE_BUF_CLOCK_MEASURE/SDL_MintAudio_clocktics) +1) & 0xFFFFFFFE;
303 DEBUG_PRINT((DEBUG_NAME "measure %d: freq=%lu KHz\n", i+1, khz));
304
305 if (i==0) {
306 if(khz==44) {
307 masterclock = MASTERCLOCK_44K;
308 }
309 } else {
310 if(khz==48) {
311 masterclock = MASTERCLOCK_48K;
312 }
313 }
314 } else {
315 DEBUG_PRINT((DEBUG_NAME "No measure\n"));
316 }
317 } else {
318 DEBUG_PRINT((DEBUG_NAME "No SDMA clock\n"));
319 }
320
321 Buffoper(0); /* stop */
322 Jdisint(MFP_TIMERA); /* Uninstall interrupt */
323 if (masterclock == 0)
324 break;
325 }
326
327 Mfree(buffer);
328 return masterclock;
329 }
330
189 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) 331 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
190 { 332 {
191 int i; 333 int i;
334 Uint32 extclock;
192 335
193 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); 336 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
194 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); 337 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
195 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); 338 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
196 DEBUG_PRINT(("channels=%d, ", spec->channels)); 339 DEBUG_PRINT(("channels=%d, ", spec->channels));
200 if ((spec->format & 0x00ff)==16) { 343 if ((spec->format & 0x00ff)==16) {
201 spec->format |= 0x1000; /* Audio is always big endian */ 344 spec->format |= 0x1000; /* Audio is always big endian */
202 spec->channels=2; /* 16 bits always stereo */ 345 spec->channels=2; /* 16 bits always stereo */
203 } 346 }
204 347
205 /* FIXME: check for an external clock */ 348 extclock=Mint_CheckExternalClock();
206 MINTAUDIO_sfreq=1; 349
207 MINTAUDIO_nfreq=12; 350 /* Standard clocks */
208 for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) { 351 MINTAUDIO_freqcount=0;
209 MINTAUDIO_hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)); 352 for (i=1;i<12;i++) {
210 DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i])); 353 /* Remove unusable Falcon codec predivisors */
211 } 354 if ((i==6) || (i==8) || (i==10)) {
212 355 continue;
213 MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 1, spec->freq); 356 }
214 spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq]; 357 SDL_MintAudio_AddFrequency(this, MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)), MASTERCLOCK_FALCON1, i);
358 }
359
360 if (extclock>0) {
361 for (i=1; i<4; i++) {
362 SDL_MintAudio_AddFrequency(this, extclock/(MASTERPREDIV_FALCON*(1<<i)), extclock, (1<<i)-1);
363 }
364 }
365
366 #if 1
367 for (i=0; i<MINTAUDIO_freqcount; i++) {
368 DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
369 i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock,
370 MINTAUDIO_frequencies[i].predivisor
371 ));
372 }
373 #endif
374
375 MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq);
376 spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
215 377
216 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); 378 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
217 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); 379 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
218 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); 380 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
219 DEBUG_PRINT(("channels=%d, ", spec->channels)); 381 DEBUG_PRINT(("channels=%d, ", spec->channels));
222 return 0; 384 return 0;
223 } 385 }
224 386
225 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) 387 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
226 { 388 {
227 int channels_mode; 389 int channels_mode, dmaclock, prediv;
228 void *buffer; 390 void *buffer;
229 391
230 /* Stop currently playing sound */ 392 /* Stop currently playing sound */
231 Buffoper(0); 393 Buffoper(0);
232 394
247 } 409 }
248 if (Setmode(channels_mode)<0) { 410 if (Setmode(channels_mode)<0) {
249 DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); 411 DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
250 } 412 }
251 413
252 /* FIXME: select an external clock */ 414 dmaclock = MINTAUDIO_frequencies[MINTAUDIO_numfreq].masterclock;
253 415 prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
254 Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1); 416 if (dmaclock != MASTERCLOCK_FALCON1) {
255 DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq)); 417 Gpio(GPIO_SET,7); /* DSP port gpio outputs */
418 if (dmaclock == MASTERCLOCK_44K) {
419 Gpio(GPIO_WRITE,2); /* 22.5792 MHz for 44.1KHz */
420 } else {
421 Gpio(GPIO_WRITE,3); /* 24.576 MHz for 48KHz */
422 }
423 Devconnect2(DMAPLAY, DAC, CLKEXT, prediv);
424 } else {
425 Devconnect(DMAPLAY, DAC, CLK25M, prediv, 1);
426 }
256 427
257 /* Set buffer */ 428 /* Set buffer */
258 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; 429 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
259 if (Setbuffer(0, buffer, buffer + spec->size)<0) { 430 if (Setbuffer(0, buffer, buffer + spec->size)<0) {
260 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); 431 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));