summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c114
1 files changed, 95 insertions, 19 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
index 73bd9fef14..c29c4b2930 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
@@ -25,69 +25,145 @@
25#include "file.h" 25#include "file.h"
26#include "mmu-imx31.h" 26#include "mmu-imx31.h"
27 27
28static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
29
28void fiq_handler(void) __attribute__((naked)); 30void fiq_handler(void) __attribute__((naked));
29 31
32/* Implement separately on recording and playback - simply disable the
33 specific DMA interrupt. Disable the FIQ itself only temporarily to sync
34 with the DMA interrupt and restore its previous state. The pcm routines
35 will call the lockout first then call into these low-level routines. */
36struct dma_lock
37{
38 int locked;
39 unsigned long state;
40};
41
42static struct dma_play_lock =
43{
44 .locked = 0,
45 .state = 0, /* Initialize this as disabled */
46};
47
48void pcm_play_lock(void)
49{
50 int status = set_fiq_status(FIQ_DISABLED);
51 if (++dma_play_lock.locked == 1)
52 ; /* Mask the DMA interrupt */
53 set_fiq_status(status);
54}
55
56void pcm_play_unlock(void)
57{
58 int status = set_fiq_status(FIQ_DISABLED);
59 if (--dma_play_lock.locked == 0)
60 ; /* Unmask the DMA interrupt if enabled */
61 set_fiq_status(status);
62}
63
30static void _pcm_apply_settings(void) 64static void _pcm_apply_settings(void)
31{ 65{
66 if (pcm_freq != pcm_curr_sampr)
67 {
68 pcm_curr_sampr = pcm_freq;
69 /* Change hardware sample rate */
70 /* */
71 }
32} 72}
33 73
34void pcm_apply_settings(void) 74void pcm_apply_settings(void)
35{ 75{
76 /* Lockout FIQ and sync the hardware to the settings */
77 int oldstatus = set_fiq_status(FIQ_DISABLED);
78 _pcm_apply_settings();
79 set_fiq_status(oldstatus);
36} 80}
37 81
38void pcm_init(void) 82void pcm_play_dma_init(void)
39{ 83{
84 pcm_set_frequency(SAMPR_44);
85
86#if 0
87 /* Do basic init enable output in pcm_postinit if popping is a
88 problem at boot to enable a lenghy delay and let the boot
89 process continue */
90 audiohw_init();
91#endif
40} 92}
41 93
42void pcm_postinit(void) 94void pcm_postinit(void)
43{ 95{
44} 96}
45 97
46void pcm_play_dma_start(const void *addr, size_t size) 98/* Connect the DMA and start filling the FIFO */
99static void play_start_pcm(void)
47{ 100{
48 (void)addr; 101#if 0
49 (void)size; 102 /* unmask DMA interrupt when unlocking */
103 dma_play_lock.state = 0; /* Set to allow pcm_play_unlock to unmask interrupt */
104#endif
50} 105}
51 106
52static void pcm_play_dma_stop_fiq(void) 107/* Disconnect the DMA and wait for the FIFO to clear */
108static void play_stop_pcm(void)
53{ 109{
110#if 0
111 /* Keep interrupt masked when unlocking */
112 dma_play_lock.state = 0; /* Set to keep pcm_play_unlock from unmasking interrupt */
113#endif
54} 114}
55 115
56void fiq_handler(void) 116void pcm_play_dma_start(const void *addr, size_t size)
57{ 117{
118 (void)addr;
119 (void)size;
58} 120}
59 121
60/* Disconnect the DMA and wait for the FIFO to clear */
61void pcm_play_dma_stop(void) 122void pcm_play_dma_stop(void)
62{ 123{
124 play_stop_pcm();
63} 125}
64 126
65void pcm_play_pause_pause(void) 127void pcm_play_dma_pause(bool pause)
66{ 128{
129 if (pause)
130 {
131 play_stop_pcm();
132 }
133 else
134 {
135 play_start_pcm();
136 }
67} 137}
68 138
69void pcm_play_pause_unpause(void) 139/* Get more samples to play out - call pcm_play_dma_stop and
140 pcm_play_dma_stopped_callback if the data runs out */
141void fiq_handler(void)
70{ 142{
143#if 0
144 /* Callback missing or no more DMA to do */
145 pcm_play_dma_stop();
146 pcm_play_dma_stopped_callback();
147#endif
71} 148}
72 149
150/* Set the pcm frequency hardware will use when play is next started or
151 when pcm_apply_settings is called. Do not apply the setting to the
152 hardware here but simply cache it. */
73void pcm_set_frequency(unsigned int frequency) 153void pcm_set_frequency(unsigned int frequency)
74{ 154{
75 (void)frequency; 155 pcm_freq = frequency;
76} 156}
77 157
158/* Return the number of bytes waiting - full L-R sample pairs only */
78size_t pcm_get_bytes_waiting(void) 159size_t pcm_get_bytes_waiting(void)
79{ 160{
80} 161}
81 162
82void pcm_mute(bool mute) 163/* Return a pointer to the samples and the number of them in *count */
164const void * pcm_play_dma_get_peak_buffer(int *count)
83{ 165{
166 (void)count;
84} 167}
85 168
86/** 169/* Any recording functionality should be implemented similarly */
87 * Return playback peaks - Peaks ahead in the DMA buffer based upon the
88 * calling period to attempt to compensate for
89 * delay.
90 */
91void pcm_calculate_peaks(int *left, int *right)
92{
93}