diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-10-06 22:27:27 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-10-06 22:27:27 +0000 |
commit | 6077e5b7c85c0d6f5963e4aadb215faf2c4d10d2 (patch) | |
tree | a6bc91ee4168e83617e942eeaea46e5523e82420 /firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | |
parent | f6de0d4083a4fcb6da57f271e1f8ccaf715e571d (diff) | |
download | rockbox-6077e5b7c85c0d6f5963e4aadb215faf2c4d10d2.tar.gz rockbox-6077e5b7c85c0d6f5963e4aadb215faf2c4d10d2.zip |
Unify PCM interface just above the hardware driver level for all targets including the sims. Perform lockout of audio callback when changing states. Weird new playback or recording trouble? Check before and after this revision first though things seem quite sound.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15006 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | 114 |
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 | ||
28 | static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */ | ||
29 | |||
28 | void fiq_handler(void) __attribute__((naked)); | 30 | void 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. */ | ||
36 | struct dma_lock | ||
37 | { | ||
38 | int locked; | ||
39 | unsigned long state; | ||
40 | }; | ||
41 | |||
42 | static struct dma_play_lock = | ||
43 | { | ||
44 | .locked = 0, | ||
45 | .state = 0, /* Initialize this as disabled */ | ||
46 | }; | ||
47 | |||
48 | void 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 | |||
56 | void 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 | |||
30 | static void _pcm_apply_settings(void) | 64 | static 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 | ||
34 | void pcm_apply_settings(void) | 74 | void 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 | ||
38 | void pcm_init(void) | 82 | void 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 | ||
42 | void pcm_postinit(void) | 94 | void pcm_postinit(void) |
43 | { | 95 | { |
44 | } | 96 | } |
45 | 97 | ||
46 | void pcm_play_dma_start(const void *addr, size_t size) | 98 | /* Connect the DMA and start filling the FIFO */ |
99 | static 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 | ||
52 | static void pcm_play_dma_stop_fiq(void) | 107 | /* Disconnect the DMA and wait for the FIFO to clear */ |
108 | static 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 | ||
56 | void fiq_handler(void) | 116 | void 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 */ | ||
61 | void pcm_play_dma_stop(void) | 122 | void pcm_play_dma_stop(void) |
62 | { | 123 | { |
124 | play_stop_pcm(); | ||
63 | } | 125 | } |
64 | 126 | ||
65 | void pcm_play_pause_pause(void) | 127 | void 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 | ||
69 | void 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 */ | ||
141 | void 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. */ | ||
73 | void pcm_set_frequency(unsigned int frequency) | 153 | void 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 */ | ||
78 | size_t pcm_get_bytes_waiting(void) | 159 | size_t pcm_get_bytes_waiting(void) |
79 | { | 160 | { |
80 | } | 161 | } |
81 | 162 | ||
82 | void pcm_mute(bool mute) | 163 | /* Return a pointer to the samples and the number of them in *count */ |
164 | const 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 | */ | ||
91 | void pcm_calculate_peaks(int *left, int *right) | ||
92 | { | ||
93 | } | ||