This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_mintaudio_xbios.c
537 lines (440 loc) · 15.1 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2004 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
22
#include "SDL_config.h"
23
24
25
26
27
/*
MiNT audio driver
using XBIOS functions (Falcon)
28
Patrice Mandin, Didier Méquignon
29
30
*/
31
#include <unistd.h>
32
#include <support.h>
33
34
35
36
37
38
39
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_audio.h"
40
41
#include "../SDL_audio_c.h"
#include "../SDL_sysaudio.h"
42
43
#include "../../video/ataricommon/SDL_atarimxalloc_c.h"
44
45
#include "SDL_mintaudio.h"
46
#include "SDL_mintaudio_dma8.h"
47
48
49
50
51
52
53
/*--- Defines ---*/
#define MINT_AUDIO_DRIVER_NAME "mint_xbios"
/* Debug print info */
#define DEBUG_NAME "audio:xbios: "
54
#if 0
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#define DEBUG_PRINT(what) \
{ \
printf what; \
}
#else
#define DEBUG_PRINT(what)
#endif
/*--- Static variables ---*/
static unsigned long cookie_snd;
/*--- Audio driver functions ---*/
static void Mint_CloseAudio(_THIS);
70
static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec);
71
72
73
74
static void Mint_LockAudio(_THIS);
static void Mint_UnlockAudio(_THIS);
/* To check/init hardware audio */
75
76
static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec);
static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec);
77
78
79
/*--- Audio driver bootstrap functions ---*/
80
81
static int
Audio_Available(void)
82
{
83
84
unsigned long dummy;
const char *envr = SDL_getenv("SDL_AUDIODRIVER");
85
86
/*SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); */
87
SDL_MintAudio_mint_present = SDL_FALSE;
88
89
90
91
92
/* We can't use XBIOS in interrupt with Magic, don't know about thread */
if (Getcookie(C_MagX, &dummy) == C_FOUND) {
return (0);
}
93
94
95
96
97
98
/* Check if user asked a different audio driver */
if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) {
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
return (0);
}
99
100
101
102
103
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
104
105
106
107
108
109
/* Check if we have 16 bits audio */
if ((cookie_snd & SND_16BIT) == 0) {
DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
return (0);
}
110
111
112
113
114
115
/* Check if audio is lockable */
if (Locksnd() != 1) {
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
return (0);
}
116
117
Unlocksnd();
118
119
120
DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n"));
return (1);
121
122
}
123
124
static void
Audio_DeleteDevice(SDL_AudioDevice * device)
125
{
126
127
SDL_free(device->hidden);
SDL_free(device);
128
129
}
130
131
static SDL_AudioDevice *
Audio_CreateDevice(int devindex)
132
{
133
SDL_AudioDevice *this;
134
135
136
137
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
if (this) {
138
SDL_memset(this, 0, (sizeof *this));
139
this->hidden = (struct SDL_PrivateAudioData *)
140
SDL_malloc((sizeof *this->hidden));
141
}
142
if ((this == NULL) || (this->hidden == NULL)) {
143
SDL_OutOfMemory();
144
if (this) {
145
SDL_free(this);
146
}
147
return (0);
148
}
149
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
150
151
/* Set the function pointers */
152
153
154
this->OpenAudio = Mint_OpenAudio;
this->CloseAudio = Mint_CloseAudio;
this->LockAudio = Mint_LockAudio;
155
this->UnlockAudio = Mint_UnlockAudio;
156
this->free = Audio_DeleteDevice;
157
158
159
160
161
162
/* Uses interrupt driven audio, without thread */
#if SDL_THREADS_DISABLED
this->SkipMixerLock = 1;
#endif
163
164
165
166
return this;
}
AudioBootStrap MINTAUDIO_XBIOS_bootstrap = {
167
168
MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver",
Audio_Available, Audio_CreateDevice
169
170
};
171
172
static void
Mint_LockAudio(_THIS)
173
{
174
175
/* Stop replay */
Buffoper(0);
176
177
}
178
179
static void
Mint_UnlockAudio(_THIS)
180
{
181
182
/* Restart replay */
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
183
184
}
185
186
static void
Mint_CloseAudio(_THIS)
187
{
188
189
190
/* Stop replay */
SDL_MintAudio_WaitThread();
Buffoper(0);
191
192
193
194
195
if (!SDL_MintAudio_mint_present) {
/* Uninstall interrupt */
Jdisint(MFP_DMASOUND);
}
196
197
198
199
/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {
}
200
201
202
203
204
205
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
206
207
208
/* Unlock sound system */
Unlocksnd();
209
210
}
211
/* Falcon XBIOS implementation of Devconnect() is buggy with external clock */
212
213
214
215
216
217
218
219
220
221
222
223
224
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;
}
225
226
oldstack = (void *) Super(0);
227
228
229
230
dev_ctrl = DMAAUDIO_IO.dev_ctrl;
dest_ctrl = DMAAUDIO_IO.dest_ctrl;
dev_ctrl &= MASK2[src];
231
232
233
234
235
236
if (src == ADC) {
dev_ctrl |= MASK1[sclk];
} else {
dev_ctrl |= (INDEX1[sclk] << (src << 4));
}
237
238
239
240
241
if (dst & DMAREC) {
dest_ctrl &= 0xFFF0;
dest_ctrl |= INDEX1[src];
}
242
243
244
245
246
if (dst & DSPRECV) {
dest_ctrl &= 0xFF8F;
dest_ctrl |= (INDEX1[src] << 4);
}
247
248
249
250
251
if (dst & EXTOUT) {
dest_ctrl &= 0xF0FF;
dest_ctrl |= (INDEX1[src] << 8);
}
252
253
254
255
256
257
258
if (dst & DAC) {
dev_ctrl &= 0x0FFF;
dev_ctrl |= MASK1[sclk];
dest_ctrl &= 0x0FFF;
dest_ctrl |= (INDEX2[src] << 12);
}
259
260
261
262
263
264
265
266
267
sync_div = DMAAUDIO_IO.sync_div;
if (sclk == CLKEXT) {
pre <<= 8;
sync_div &= 0xF0FF;
} else {
sync_div &= 0xFFF0;
}
sync_div |= pre;
268
269
270
271
DMAAUDIO_IO.dev_ctrl = dev_ctrl;
DMAAUDIO_IO.dest_ctrl = dest_ctrl;
DMAAUDIO_IO.sync_div = sync_div;
272
273
Super(oldstack);
274
275
}
276
277
static void
Mint_CheckExternalClock(_THIS)
278
279
280
{
#define SIZE_BUF_CLOCK_MEASURE (44100/10)
281
282
283
unsigned long cookie_snd;
char *buffer;
int i, j;
284
285
286
287
288
289
290
291
/* DSP present with its GPIO port ? */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
return;
}
if ((cookie_snd & SND_DSP) == 0) {
return;
}
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
buffer = Atari_SysMalloc(SIZE_BUF_CLOCK_MEASURE, MX_STRAM);
if (buffer == NULL) {
DEBUG_PRINT((DEBUG_NAME "Not enough memory for the measure\n"));
return;
}
SDL_memset(buffer, 0, SIZE_BUF_CLOCK_MEASURE);
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 (khz == 44) {
for (j = 1; j < 4; j++) {
SDL_MintAudio_AddFrequency(this,
MASTERCLOCK_44K
/
(MASTERPREDIV_FALCON
* (1 << j)),
MASTERCLOCK_44K,
(1 << j) - 1, 2 + i);
}
} else if (khz == 48) {
for (j = 1; j < 4; j++) {
SDL_MintAudio_AddFrequency(this,
MASTERCLOCK_48K
/
(MASTERPREDIV_FALCON
* (1 << j)),
MASTERCLOCK_48K,
(1 << j) - 1, 2 + i);
}
}
} else {
DEBUG_PRINT((DEBUG_NAME "No measure\n"));
}
} else {
DEBUG_PRINT((DEBUG_NAME "No SDMA clock\n"));
}
354
355
356
357
358
359
Buffoper(0); /* stop */
Jdisint(MFP_TIMERA); /* Uninstall interrupt */
}
Mfree(buffer);
360
361
}
362
363
static int
Mint_CheckAudio(_THIS, SDL_AudioSpec * spec)
364
{
365
366
367
int i;
Uint32 extclock;
368
369
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",
SDL_AUDIO_BITSIZE(spec->format)));
370
371
372
DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format)));
DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format)));
DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format)));
373
374
375
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
376
spec->format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */
377
378
379
/* clamp out int32/float32 */
if (SDL_AUDIO_BITSIZE(spec->format) >= 16) {
380
spec->format = AUDIO_S16MSB; /* Audio is always big endian */
381
spec->channels = 2; /* 16 bits always stereo */
382
} else if (spec->channels > 2) {
383
spec->channels = 2; /* no more than stereo! */
384
}
385
386
MINTAUDIO_freqcount = 0;
387
388
389
/* Add external clocks if present */
Mint_CheckExternalClock(this);
390
391
392
393
394
395
396
397
398
399
400
401
/* Standard clocks */
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)),
MASTERCLOCK_FALCON1, i, -1);
}
402
403
#if 1
404
405
406
407
408
409
for (i = 0; i < MINTAUDIO_freqcount; i++) {
DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
i, MINTAUDIO_frequencies[i].frequency,
MINTAUDIO_frequencies[i].masterclock,
MINTAUDIO_frequencies[i].predivisor));
}
410
#endif
411
412
413
MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq);
spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
414
415
416
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
SDL_AUDIO_BITSIZE(spec->format)));
417
418
419
DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format)));
DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format)));
DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format)));
420
421
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
422
423
return 0;
424
425
}
426
427
static void
Mint_InitAudio(_THIS, SDL_AudioSpec * spec)
428
{
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
int channels_mode, dmaclock, prediv;
void *buffer;
/* Stop currently playing sound */
SDL_MintAudio_quit_thread = SDL_FALSE;
SDL_MintAudio_thread_finished = SDL_TRUE;
SDL_MintAudio_WaitThread();
Buffoper(0);
/* Set replay tracks */
Settracks(0, 0);
Setmontracks(0);
/* Select replay format */
channels_mode = STEREO16;
444
switch (SDL_AUDIO_BITSIZE(spec->format)) {
445
446
447
448
449
450
451
452
453
454
455
case 8:
if (spec->channels == 2) {
channels_mode = STEREO8;
} else {
channels_mode = MONO8;
}
break;
}
if (Setmode(channels_mode) < 0) {
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
}
456
457
458
459
460
461
462
463
464
465
dmaclock = MINTAUDIO_frequencies[MINTAUDIO_numfreq].masterclock;
prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
if (MINTAUDIO_frequencies[MINTAUDIO_numfreq].gpio_bits != -1) {
Gpio(GPIO_SET, 7); /* DSP port gpio outputs */
Gpio(GPIO_WRITE, MINTAUDIO_frequencies[MINTAUDIO_numfreq].gpio_bits);
Devconnect2(DMAPLAY, DAC | EXTOUT, CLKEXT, prediv);
} else {
Devconnect2(DMAPLAY, DAC, CLK25M, prediv);
}
466
467
468
469
470
471
472
473
474
475
476
477
/* Set buffer */
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
if (Setbuffer(0, buffer, buffer + spec->size) < 0) {
DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
}
if (SDL_MintAudio_mint_present) {
SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0);
} else {
/* Install interrupt */
Jdisint(MFP_DMASOUND);
478
/*Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt); */
479
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_Dma8Interrupt);
480
Jenabint(MFP_DMASOUND);
481
482
483
484
485
486
487
488
489
if (Setinterrupt(SI_TIMERA, SI_PLAY) < 0) {
DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
}
}
/* Go */
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
490
491
}
492
493
static int
Mint_OpenAudio(_THIS, SDL_AudioSpec * spec)
494
{
495
496
497
498
499
/* Lock sound system */
if (Locksnd() != 1) {
SDL_SetError("Mint_OpenAudio: Audio system already in use");
return (-1);
}
500
501
SDL_MintAudio_device = this;
502
503
504
505
506
/* Check audio capabilities */
if (Mint_CheckAudio(this, spec) == -1) {
return -1;
}
507
508
SDL_CalculateAudioSpec(spec);
509
510
511
/* Allocate memory for audio buffers in DMA-able RAM */
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
512
513
514
515
516
517
518
519
520
521
522
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM);
if (SDL_MintAudio_audiobuf[0] == NULL) {
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
return (-1);
}
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size;
SDL_MintAudio_numbuf = 0;
SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2);
SDL_MintAudio_audiosize = spec->size;
SDL_MintAudio_mutex = 0;
523
524
525
526
527
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n",
SDL_MintAudio_audiobuf[0]));
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n",
SDL_MintAudio_audiobuf[1]));
528
529
530
SDL_MintAudio_CheckFpu();
531
532
/* Setup audio hardware */
Mint_InitAudio(this, spec);
533
534
return (1); /* We don't use SDL threaded audio */
535
}
536
537
/* vi: set ts=4 sw=4 expandtab: */