(GX) Reimplement audio driver

This commit is contained in:
twinaphex 2013-11-01 20:02:21 +01:00
parent e9243a5ab4
commit 17b69cbc29
1 changed files with 27 additions and 36 deletions

View File

@ -40,26 +40,28 @@ typedef struct
bool nonblock; bool nonblock;
} gx_audio_t; } gx_audio_t;
static gx_audio_t *g_audio;
static void dma_callback(void) static void dma_callback(void)
{ {
gx_audio_t *wa = (gx_audio_t*)driver.audio_data;
// erase last chunk to avoid repeating audio // erase last chunk to avoid repeating audio
memset(g_audio->data[g_audio->dma_busy], 0, CHUNK_SIZE); memset(wa->data[wa->dma_busy], 0, CHUNK_SIZE);
g_audio->dma_busy = g_audio->dma_next; wa->dma_busy = wa->dma_next;
g_audio->dma_next = (g_audio->dma_next + 1) & (BLOCKS - 1); wa->dma_next = (wa->dma_next + 1) & (BLOCKS - 1);
DCFlushRange(g_audio->data[g_audio->dma_next], CHUNK_SIZE); DCFlushRange(wa->data[wa->dma_next], CHUNK_SIZE);
AUDIO_InitDMA((u32)g_audio->data[g_audio->dma_next], CHUNK_SIZE); AUDIO_InitDMA((uint32_t)wa->data[wa->dma_next], CHUNK_SIZE);
LWP_ThreadSignal(g_audio->cond); LWP_ThreadSignal(wa->cond);
} }
static void *gx_audio_init(const char *device, unsigned rate, unsigned latency) static void *gx_audio_init(const char *device, unsigned rate, unsigned latency)
{ {
if (g_audio) gx_audio_t *wa = (gx_audio_t*)memalign(32, sizeof(*wa));
return g_audio; if (!wa)
return NULL;
memset(wa, 0, sizeof(*wa));
AUDIO_Init(NULL); AUDIO_Init(NULL);
AUDIO_RegisterDMACallback(dma_callback); AUDIO_RegisterDMACallback(dma_callback);
@ -75,26 +77,14 @@ static void *gx_audio_init(const char *device, unsigned rate, unsigned latency)
g_settings.audio.out_rate = 48000; g_settings.audio.out_rate = 48000;
} }
if (!g_audio) LWP_InitQueue(&wa->cond);
{
g_audio = memalign(32, sizeof(*g_audio));
memset(g_audio, 0, sizeof(*g_audio));
LWP_InitQueue(&g_audio->cond);
}
else
{
memset(g_audio->data, 0, sizeof(g_audio->data));
g_audio->dma_busy = g_audio->dma_next = 0;
g_audio->write_ptr = 0;
g_audio->nonblock = false;
}
g_audio->dma_write = BLOCKS - 1; wa->dma_write = BLOCKS - 1;
DCFlushRange(g_audio->data, sizeof(g_audio->data)); DCFlushRange(wa->data, sizeof(wa->data));
AUDIO_InitDMA((u32)g_audio->data[g_audio->dma_next], CHUNK_SIZE); AUDIO_InitDMA((uint32_t)wa->data[wa->dma_next], CHUNK_SIZE);
AUDIO_StartDMA(); AUDIO_StartDMA();
return g_audio; return wa;
} }
// Wii uses silly R, L, R, L interleaving ... // Wii uses silly R, L, R, L interleaving ...
@ -141,16 +131,16 @@ static ssize_t gx_audio_write(void *data, const void *buf_, size_t size)
static bool gx_audio_stop(void *data) static bool gx_audio_stop(void *data)
{ {
(void)data; gx_audio_t *wa = (gx_audio_t*)data;
AUDIO_StopDMA(); AUDIO_StopDMA();
memset(g_audio->data, 0, sizeof(g_audio->data)); memset(wa->data, 0, sizeof(wa->data));
DCFlushRange(g_audio->data, sizeof(g_audio->data)); DCFlushRange(wa->data, sizeof(wa->data));
return true; return true;
} }
static void gx_audio_set_nonblock_state(void *data, bool state) static void gx_audio_set_nonblock_state(void *data, bool state)
{ {
gx_audio_t *wa = data; gx_audio_t *wa = (gx_audio_t*)data;
wa->nonblock = state; wa->nonblock = state;
} }
@ -163,21 +153,22 @@ static bool gx_audio_start(void *data)
static void gx_audio_free(void *data) static void gx_audio_free(void *data)
{ {
gx_audio_t *wa = (gx_audio_t*)data;
AUDIO_StopDMA(); AUDIO_StopDMA();
AUDIO_RegisterDMACallback(NULL); AUDIO_RegisterDMACallback(NULL);
if (g_audio && g_audio->cond) if (wa && wa->cond)
{ {
LWP_CloseQueue(g_audio->cond); LWP_CloseQueue(wa->cond);
g_audio->cond = 0; wa->cond = 0;
} }
if (data) if (data)
free(data); free(data);
g_audio = NULL; wa = NULL;
} }
static size_t gx_audio_write_avail(void *data) static size_t gx_audio_write_avail(void *data)
{ {
gx_audio_t *wa = data; gx_audio_t *wa = (gx_audio_t*)data;
return ((wa->dma_busy - wa->dma_write + BLOCKS) & (BLOCKS - 1)) * CHUNK_SIZE; return ((wa->dma_busy - wa->dma_write + BLOCKS) & (BLOCKS - 1)) * CHUNK_SIZE;
} }