From e8a8a1be43afe63079ae48ce1a9eb3052df3b1a4 Mon Sep 17 00:00:00 2001 From: Tomasz Moń Date: Wed, 16 Nov 2011 14:08:01 +0000 Subject: Sandisk Sansa Connect port (FS #12363) Included are drivers for buttons, backlight, lcd, audio and storage. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31000 a1c6a512-1295-4272-9138-f99709370657 --- .../tms320dm320/sansa-connect/pcm-sansaconnect.c | 207 +++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c (limited to 'firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c') diff --git a/firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c new file mode 100644 index 0000000000..3f04838388 --- /dev/null +++ b/firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c @@ -0,0 +1,207 @@ +/*************************************************************************** + * __________ __ ___. + * 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 +#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 "mmu-arm.h" +#include "pcm-internal.h" +#include "dma-target.h" + +/* This is global to save some latency when pcm_play_dma_get_peak_buffer is + * called. + */ +static void *start; +static int dma_channel; + +void pcm_play_dma_postinit(void) +{ + audiohw_postinit(); +} + +/* Return the current location in the SDRAM to SARAM transfer along with the + * number of bytes read in the current buffer (count). There is latency with + * this method equivalent to ~ the size of the SARAM buffer since there is + * another buffer between your ears and this calculation, but this works for + * key clicks and an approximate peak meter. + */ +const void * pcm_play_dma_get_peak_buffer(int *count) +{ + int cnt = DSP_(_sdem_level); + + unsigned long addr = (unsigned long) start + cnt; + + *count = (cnt & 0xFFFFF) >> 1; + return (void *)((addr + 2) & ~3); +} + +void pcm_play_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)); + + /* Enable IMGBUF clock */ + bitset16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF); + + 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(); +} + +void pcm_dma_apply_settings(void) +{ + audiohw_set_frequency(pcm_fsel); +} + +/* 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) + */ +void pcm_play_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(); +} + +void pcm_play_dma_stop(void) +{ + DSP_(_dma0_stopped)=1; + dsp_wake(); +} + +void pcm_play_lock(void) +{ + +} + +void pcm_play_unlock(void) +{ + +} + +void pcm_play_dma_pause(bool pause) +{ + if (pause) + { + DSP_(_dma0_stopped)=2; + dsp_wake(); + } + else + { + DSP_(_dma0_stopped)=0; + dsp_wake(); + } +} + +size_t pcm_get_bytes_waiting(void) +{ + return DSP_(_sdem_dsp_size)-DSP_(_sdem_level); +} + +/* 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. */ + pcm_play_get_more_callback(&start, &size); + + if (size != 0) + { + unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START; + /* Flush any pending cache writes */ + clean_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_started_callback(); + } + + break; + default: + DEBUGF("DSP: unknown msg 0x%04x", dsp_message.msg); + break; + } + + /* Re-Activate the channel */ + dsp_wake(); + + DEBUGF("DSP: %s", buffer); +} + -- cgit v1.2.3