summaryrefslogtreecommitdiff
path: root/firmware/export
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/export')
-rw-r--r--firmware/export/config.h5
-rw-r--r--firmware/export/pcm-internal.h81
-rw-r--r--firmware/export/pcm.h44
-rw-r--r--firmware/export/pcm_mixer.h102
4 files changed, 190 insertions, 42 deletions
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 2c7c6e89db..70047ff866 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -1048,4 +1048,9 @@ Lyre prototype 1 */
1048#define HAVE_IO_PRIORITY 1048#define HAVE_IO_PRIORITY
1049#endif 1049#endif
1050 1050
1051#if defined(CPU_COLDIRE) || CONFIG_CPU == IMX31L
1052/* Can record and play simultaneously */
1053#define HAVE_PCM_FULL_DUPLEX
1054#endif
1055
1051#endif /* __CONFIG_H__ */ 1056#endif /* __CONFIG_H__ */
diff --git a/firmware/export/pcm-internal.h b/firmware/export/pcm-internal.h
new file mode 100644
index 0000000000..d69138f534
--- /dev/null
+++ b/firmware/export/pcm-internal.h
@@ -0,0 +1,81 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
11 * Copyright (C) 2011 by Michael Sevakis
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#ifndef PCM_INTERNAL_H
23#define PCM_INTERNAL_H
24
25/** The following are for internal use between pcm.c and target-
26 specific portion **/
27
28/* Called by the bottom layer ISR when more data is needed. Returns non-
29 * zero size if more data is to be played. Setting start to NULL
30 * forces stop. */
31void pcm_play_get_more_callback(void **start, size_t *size);
32
33/* Called by the bottom layer ISR after next transfer has begun in order
34 to fill more data for next "get more" callback to implement double-buffered
35 callbacks - except for a couple ASM handlers, help drivers to implement
36 this functionality with minimal overhead */
37static FORCE_INLINE void pcm_play_dma_started_callback(void)
38{
39 extern void (* pcm_play_dma_started)(void);
40 void (* callback)(void) = pcm_play_dma_started;
41 if (callback)
42 callback();
43}
44
45extern unsigned long pcm_curr_sampr;
46extern unsigned long pcm_sampr;
47extern int pcm_fsel;
48
49#ifdef HAVE_PCM_DMA_ADDRESS
50void * pcm_dma_addr(void *addr);
51#endif
52
53extern volatile bool pcm_playing;
54extern volatile bool pcm_paused;
55
56void pcm_play_dma_lock(void);
57void pcm_play_dma_unlock(void);
58void pcm_play_dma_init(void) INIT_ATTR;
59void pcm_play_dma_start(const void *addr, size_t size);
60void pcm_play_dma_stop(void);
61void pcm_play_dma_pause(bool pause);
62const void * pcm_play_dma_get_peak_buffer(int *count);
63
64void pcm_dma_apply_settings(void);
65
66#ifdef HAVE_RECORDING
67
68/* DMA transfer in is currently active */
69extern volatile bool pcm_recording;
70
71/* APIs implemented in the target-specific portion */
72void pcm_rec_dma_init(void);
73void pcm_rec_dma_close(void);
74void pcm_rec_dma_start(void *addr, size_t size);
75void pcm_rec_dma_record_more(void *start, size_t size);
76void pcm_rec_dma_stop(void);
77const void * pcm_rec_dma_get_peak_buffer(void);
78
79#endif /* HAVE_RECORDING */
80
81#endif /* PCM_INTERNAL_H */
diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h
index 80b5b09a79..22c5ef350e 100644
--- a/firmware/export/pcm.h
+++ b/firmware/export/pcm.h
@@ -49,7 +49,7 @@
49 49
50/** RAW PCM routines used with playback and recording **/ 50/** RAW PCM routines used with playback and recording **/
51 51
52/* Typedef for registered callback */ 52/* Typedef for registered callbacks */
53typedef void (*pcm_play_callback_type)(unsigned char **start, 53typedef void (*pcm_play_callback_type)(unsigned char **start,
54 size_t *size); 54 size_t *size);
55typedef void (*pcm_rec_callback_type)(int status, void **start, size_t *size); 55typedef void (*pcm_rec_callback_type)(int status, void **start, size_t *size);
@@ -90,34 +90,7 @@ void pcm_play_pause(bool play);
90bool pcm_is_paused(void); 90bool pcm_is_paused(void);
91bool pcm_is_playing(void); 91bool pcm_is_playing(void);
92 92
93/** The following are for internal use between pcm.c and target- 93void pcm_play_set_dma_started_callback(void (* callback)(void));
94 specific portion **/
95
96/* Called by the bottom layer ISR when more data is needed. Returns non-
97 * zero size if more data is to be played. Setting start to NULL
98 * forces stop. */
99void pcm_play_get_more_callback(void **start, size_t *size);
100
101extern unsigned long pcm_curr_sampr;
102extern unsigned long pcm_sampr;
103extern int pcm_fsel;
104
105#ifdef HAVE_PCM_DMA_ADDRESS
106void * pcm_dma_addr(void *addr);
107#endif
108
109extern volatile bool pcm_playing;
110extern volatile bool pcm_paused;
111
112void pcm_play_dma_lock(void);
113void pcm_play_dma_unlock(void);
114void pcm_play_dma_init(void) INIT_ATTR;
115void pcm_play_dma_start(const void *addr, size_t size);
116void pcm_play_dma_stop(void);
117void pcm_play_dma_pause(bool pause);
118const void * pcm_play_dma_get_peak_buffer(int *count);
119
120void pcm_dma_apply_settings(void);
121 94
122#ifdef HAVE_RECORDING 95#ifdef HAVE_RECORDING
123 96
@@ -148,19 +121,6 @@ void pcm_rec_more_ready_callback(int status, void **start, size_t *size);
148 121
149void pcm_calculate_rec_peaks(int *left, int *right); 122void pcm_calculate_rec_peaks(int *left, int *right);
150 123
151/** The following are for internal use between pcm.c and target-
152 specific portion **/
153/* DMA transfer in is currently active */
154extern volatile bool pcm_recording;
155
156/* APIs implemented in the target-specific portion */
157void pcm_rec_dma_init(void);
158void pcm_rec_dma_close(void);
159void pcm_rec_dma_start(void *addr, size_t size);
160void pcm_rec_dma_record_more(void *start, size_t size);
161void pcm_rec_dma_stop(void);
162const void * pcm_rec_dma_get_peak_buffer(void);
163
164#endif /* HAVE_RECORDING */ 124#endif /* HAVE_RECORDING */
165 125
166#endif /* PCM_PLAYBACK_H */ 126#endif /* PCM_PLAYBACK_H */
diff --git a/firmware/export/pcm_mixer.h b/firmware/export/pcm_mixer.h
new file mode 100644
index 0000000000..3b420e1320
--- /dev/null
+++ b/firmware/export/pcm_mixer.h
@@ -0,0 +1,102 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef PCM_MIXER_H
23#define PCM_MIXER_H
24
25/** Simple config **/
26
27/* Length of PCM frames (always) */
28#if CONFIG_CPU == PP5002
29/* There's far less time to do mixing because HW FIFOs are short */
30#define MIX_FRAME_SAMPLES 64
31#else
32/* Assume HW DMA engine is available or sufficient latency exists in the
33 PCM pathway */
34#define MIX_FRAME_SAMPLES 256
35#endif
36
37#if defined(CPU_COLDFIRE) || defined(CPU_PP)
38/* For Coldfire, it's just faster
39 For PortalPlayer, this also avoids more expensive cache coherency */
40#define DOWNMIX_BUF_IBSS IBSS_ATTR
41#else
42/* Otherwise can't DMA from IRAM, IRAM is pointless or worse */
43#define DOWNMIX_BUF_IBSS
44#endif
45
46
47/** Definitions **/
48
49/* Channels are preassigned for simplicity */
50enum pcm_mixer_channel
51{
52 PCM_MIXER_CHAN_PLAYBACK = 0,
53 PCM_MIXER_CHAN_VOICE,
54#ifndef HAVE_HARDWARE_BEEP
55 PCM_MIXER_CHAN_BEEP,
56#endif
57 /* Add new channel indexes above this line */
58 PCM_MIXER_NUM_CHANNELS,
59};
60
61/* Channel playback states */
62enum channel_status
63{
64 CHANNEL_STOPPED = 0,
65 CHANNEL_PLAYING,
66 CHANNEL_PAUSED,
67};
68
69#define MIX_AMP_UNITY 0x00010000
70#define MIX_AMP_MUTE 0x00000000
71
72
73/** Public interfaces **/
74
75/* Start playback on a channel */
76void mixer_channel_play_data(enum pcm_mixer_channel channel,
77 pcm_play_callback_type get_more,
78 unsigned char *start, size_t size);
79
80/* Pause or resume a channel (when started) */
81void mixer_channel_play_pause(enum pcm_mixer_channel channel, bool play);
82
83/* Stop playback on a channel */
84void mixer_channel_stop(enum pcm_mixer_channel channel);
85
86/* Set channel's amplitude factor */
87void mixer_channel_set_amplitude(enum pcm_mixer_channel channel,
88 unsigned int amplitude);
89
90/* Return channel's playback status */
91enum channel_status mixer_channel_status(enum pcm_mixer_channel channel);
92
93/* Returns amount data remaining in channel before next callback */
94size_t mixer_channel_get_bytes_waiting(enum pcm_mixer_channel channel);
95
96/* Return pointer to channel's playing audio data and the size remaining */
97void * mixer_channel_get_buffer(enum pcm_mixer_channel channel, int *count);
98
99/* Stop ALL channels and PCM and reset state */
100void mixer_reset(void);
101
102#endif /* PCM_MIXER_H */