rockbox/firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c
mojyack dfa33c246b pcm: introduce pcm_sink
move target-specific pcm operations into builtin_pcm_sink.
in subsequent commits, another pcm_sink is added, and it becomes
possible to switch between them.

Change-Id: I8f8b9661e01d6e6472f34224ddc3760856778457
2026-03-02 10:09:11 +09:00

178 lines
4.7 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: $
*
* Copyright (C) 2011 by Tomasz Moń
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdlib.h>
#include "system.h"
#include "kernel.h"
#include "logf.h"
#include "audio.h"
#include "sound.h"
#include "file.h"
#include "dsp-target.h"
#include "dsp/ipc.h"
#include "pcm-internal.h"
#include "dma-target.h"
#include "pcm_sink.h"
/* This is global to save some latency when pcm_play_dma_get_peak_buffer is
* called.
*/
static const void *start;
static int dma_channel;
static void sink_dma_init(void)
{
/* GIO16 is DSP/AIC3X CLK */
IO_GIO_FSEL0 &= 0x3FFF;
IO_CLK_OSEL = (IO_CLK_OSEL & 0xFFF0) | 4; /* PLLIN clock */
IO_CLK_O0DIV = 7;
IO_GIO_DIR1 &= ~(1 << 0); /* GIO16 - output */
IO_GIO_FSEL0 |= 0xC000; /* GIO16 - CLKOUT0 */
audiohw_init();
audiohw_set_frequency(HW_FREQ_DEFAULT);
IO_INTC_IRQ0 = INTR_IRQ0_IMGBUF;
bitset16(&IO_INTC_EINT0, INTR_EINT0_IMGBUF);
/* Set this as a FIQ */
bitset16(&IO_INTC_FISEL0, INTR_EINT0_IMGBUF);
/* Enable the HPIB clock */
bitset16(&IO_CLK_MOD0, (CLK_MOD0_HPIB | CLK_MOD0_DSP));
dma_channel = dma_request_channel(DMA_PERIPHERAL_DSP,
DMA_MODE_1_BURST);
IO_DSPC_HPIB_CONTROL = 1 << 10 | 1 << 9 | 1 << 8 | 1 << 7 | 1 << 3 | 1 << 0;
dsp_reset();
dsp_load(dsp_image);
DSP_(_dma0_stopped)=1;
dsp_wake();
}
static void sink_set_freq(uint16_t freq)
{
audiohw_set_frequency(freq);
}
/* Note that size is actually limited to the size of a short right now due to
* the implementation on the DSP side (and the way that we access it)
*/
static void sink_dma_start(const void *addr, size_t size)
{
unsigned long sdem_addr=(unsigned long)addr - CONFIG_SDRAM_START;
/* Initialize codec. */
DSP_(_sdem_addrl) = sdem_addr & 0xffff;
DSP_(_sdem_addrh) = sdem_addr >> 16;
DSP_(_sdem_dsp_size) = size;
DSP_(_dma0_stopped)=0;
dsp_wake();
}
static void sink_dma_stop(void)
{
DSP_(_dma0_stopped)=1;
dsp_wake();
}
static void sink_lock(void)
{
}
static void sink_unlock(void)
{
}
/* Only used when debugging */
static char buffer[80];
void DSPHINT(void) __attribute__ ((section(".icode")));
void DSPHINT(void)
{
unsigned int i;
size_t size;
IO_INTC_FIQ0 = INTR_IRQ0_IMGBUF;
switch (dsp_message.msg)
{
case MSG_DEBUGF:
/* DSP stores one character per word. */
for (i = 0; i < sizeof(buffer); i++)
{
buffer[i] = dsp_message.payload.debugf.buffer[i];
}
DEBUGF("DSP: %s", buffer);
break;
case MSG_REFILL:
/* Buffer empty. Try to get more. */
if (pcm_play_dma_complete_callback(PCM_DMAST_OK, &start, &size))
{
unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START;
/* Flush any pending cache writes */
commit_dcache_range(start, size);
/* set the new DMA values */
DSP_(_sdem_addrl) = sdem_addr & 0xffff;
DSP_(_sdem_addrh) = sdem_addr >> 16;
DSP_(_sdem_dsp_size) = size;
DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx",
(unsigned long)start, (unsigned long)sdem_addr);
pcm_play_dma_status_callback(PCM_DMAST_STARTED);
}
break;
default:
DEBUGF("DSP: unknown msg 0x%04x", dsp_message.msg);
break;
}
/* Re-Activate the channel */
dsp_wake();
DEBUGF("DSP: %s", buffer);
}
struct pcm_sink builtin_pcm_sink = {
.caps = {
.samprs = hw_freq_sampr,
.num_samprs = HW_NUM_FREQ,
.default_freq = HW_FREQ_DEFAULT,
},
.ops = {
.init = sink_dma_init,
.postinit = audiohw_postinit,
.set_freq = sink_set_freq,
.lock = sink_lock,
.unlock = sink_unlock,
.play = sink_dma_start,
.stop = sink_dma_stop,
},
};