summaryrefslogtreecommitdiff
path: root/firmware/pcm_playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/pcm_playback.c')
-rw-r--r--firmware/pcm_playback.c185
1 files changed, 23 insertions, 162 deletions
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index d81853e1cb..e6e59ca604 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -21,9 +21,6 @@
21#include "logf.h" 21#include "logf.h"
22#include "audio.h" 22#include "audio.h"
23#include "sound.h" 23#include "sound.h"
24#if CONFIG_CPU == PNX0101
25#include "string.h"
26#endif /* CONFIG_CPU == PNX0101 */
27 24
28/** 25/**
29 * APIs implemented in the target-specific portion: 26 * APIs implemented in the target-specific portion:
@@ -53,15 +50,29 @@ void pcm_play_pause_unpause(void);
53 50
54/** Functions that require targeted implementation **/ 51/** Functions that require targeted implementation **/
55 52
56#if !defined(CPU_COLDFIRE) && (CONFIG_CPU != S3C2440) 53#if defined(CPU_COLDFIRE) || (CONFIG_CPU == S3C2440)
57 54/* Implemented in target/... */
58#if (CONFIG_CPU == PNX0101) 55#else
59 56/* dummy functions for those not actually supporting all this yet */
60#define DMA_BUF_SAMPLES 0x100 57void pcm_apply_settings(void)
58{
59}
60/** **/
61 61
62short __attribute__((section(".dmabuf"))) dma_buf_left[DMA_BUF_SAMPLES]; 62void pcm_mute(bool mute)
63short __attribute__((section(".dmabuf"))) dma_buf_right[DMA_BUF_SAMPLES]; 63{
64#if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
65 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
66 audiohw_mute(mute);
67#endif
68 if (mute)
69 sleep(HZ/16);
70}
71#endif /* defined(CPU_COLDFIRE) || (CONFIG_CPU == S3C2440) */
64 72
73#if defined(CPU_COLDFIRE) || (CONFIG_CPU == S3C2440) || defined(CPU_PP)
74/* Implemented in target/... */
75#else
65static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */ 76static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
66 77
67unsigned short* p IBSS_ATTR; 78unsigned short* p IBSS_ATTR;
@@ -90,136 +101,6 @@ void pcm_play_pause_unpause(void)
90{ 101{
91} 102}
92 103
93static inline void fill_dma_buf(int offset)
94{
95 short *l, *r, *lend;
96
97 l = dma_buf_left + offset;
98 lend = l + DMA_BUF_SAMPLES / 2;
99 r = dma_buf_right + offset;
100
101 if (pcm_playing && !pcm_paused)
102 {
103 do
104 {
105 int count;
106 unsigned short *tmp_p;
107 count = MIN(p_size / 4, (size_t)(lend - l));
108 tmp_p = p;
109 p_size -= count * 4;
110
111 if ((int)l & 3)
112 {
113 *l++ = *tmp_p++;
114 *r++ = *tmp_p++;
115 count--;
116 }
117 while (count >= 4)
118 {
119 asm("ldmia %0!, {r0, r1, r2, r3}\n\t"
120 "and r4, r0, %3\n\t"
121 "orr r4, r4, r1, lsl #16\n\t"
122 "and r5, r2, %3\n\t"
123 "orr r5, r5, r3, lsl #16\n\t"
124 "stmia %1!, {r4, r5}\n\t"
125 "bic r4, r1, %3\n\t"
126 "orr r4, r4, r0, lsr #16\n\t"
127 "bic r5, r3, %3\n\t"
128 "orr r5, r5, r2, lsr #16\n\t"
129 "stmia %2!, {r4, r5}"
130 : "+r" (tmp_p), "+r" (l), "+r" (r)
131 : "r" (0xffff)
132 : "r0", "r1", "r2", "r3", "r4", "r5", "memory");
133 count -= 4;
134 }
135 while (count > 0)
136 {
137 *l++ = *tmp_p++;
138 *r++ = *tmp_p++;
139 count--;
140 }
141 p = tmp_p;
142 if (l >= lend)
143 return;
144 else if (pcm_callback_for_more)
145 pcm_callback_for_more((unsigned char**)&p,
146 &p_size);
147 }
148 while (p_size);
149 pcm_playing = false;
150 }
151
152 if (l < lend)
153 {
154 memset(l, 0, sizeof(short) * (lend - l));
155 memset(r, 0, sizeof(short) * (lend - l));
156 }
157}
158
159static void audio_irq(void)
160{
161 unsigned long st = DMAINTSTAT & ~DMAINTEN;
162 int i;
163 for (i = 0; i < 2; i++)
164 if (st & (1 << i))
165 {
166 fill_dma_buf((i == 1) ? 0 : DMA_BUF_SAMPLES / 2);
167 DMAINTSTAT = 1 << i;
168 }
169}
170
171unsigned long physical_address(void *p)
172{
173 unsigned long adr = (unsigned long)p;
174 return (MMUBLOCK((adr >> 21) & 0xf) << 21) | (adr & ((1 << 21) - 1));
175}
176
177void pcm_init(void)
178{
179 int i;
180
181 pcm_playing = false;
182 pcm_paused = false;
183 pcm_callback_for_more = NULL;
184
185 memset(dma_buf_left, 0, sizeof(dma_buf_left));
186 memset(dma_buf_right, 0, sizeof(dma_buf_right));
187
188 for (i = 0; i < 8; i++)
189 {
190 DMASRC(i) = 0;
191 DMADEST(i) = 0;
192 DMALEN(i) = 0x1ffff;
193 DMAR0C(i) = 0;
194 DMAR10(i) = 0;
195 DMAR1C(i) = 0;
196 }
197
198 DMAINTSTAT = 0xc000ffff;
199 DMAINTEN = 0xc000ffff;
200
201 DMASRC(0) = physical_address(dma_buf_left);
202 DMADEST(0) = 0x80200280;
203 DMALEN(0) = 0xff;
204 DMAR1C(0) = 0;
205 DMAR0C(0) = 0x40408;
206
207 DMASRC(1) = physical_address(dma_buf_right);
208 DMADEST(1) = 0x80200284;
209 DMALEN(1) = 0xff;
210 DMAR1C(1) = 0;
211 DMAR0C(1) = 0x40409;
212
213 irq_set_int_handler(0x1b, audio_irq);
214 irq_enable_int(0x1b);
215
216 DMAINTSTAT = 1;
217 DMAINTSTAT = 2;
218 DMAINTEN &= ~3;
219 DMAR10(0) |= 1;
220 DMAR10(1) |= 1;
221}
222
223void pcm_postinit(void) 104void pcm_postinit(void)
224{ 105{
225 audiohw_postinit(); 106 audiohw_postinit();
@@ -234,24 +115,7 @@ size_t pcm_get_bytes_waiting(void)
234{ 115{
235 return p_size; 116 return p_size;
236} 117}
237#endif /* CONFIG_CPU == */
238 118
239/* dummy functions for those not actually supporting all this yet */
240void pcm_apply_settings(void)
241{
242}
243/** **/
244
245void pcm_mute(bool mute)
246{
247#if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
248 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
249 audiohw_mute(mute);
250#endif
251 if (mute)
252 sleep(HZ/16);
253}
254#if !defined(CPU_PP)
255/* 119/*
256 * This function goes directly into the DMA buffer to calculate the left and 120 * This function goes directly into the DMA buffer to calculate the left and
257 * right peak values. To avoid missing peaks it tries to look forward two full 121 * right peak values. To avoid missing peaks it tries to look forward two full
@@ -271,10 +135,8 @@ void pcm_calculate_peaks(int *left, int *right)
271 short *addr; 135 short *addr;
272 short *end; 136 short *end;
273 { 137 {
274#if CONFIG_CPU == PNX0101
275 size_t samples = p_size / 4; 138 size_t samples = p_size / 4;
276 addr = p; 139 addr = p;
277#endif /* CONFIG_CPU */.
278 140
279 if (samples > PEAK_SAMPLES) 141 if (samples > PEAK_SAMPLES)
280 samples = PEAK_SAMPLES - (PEAK_STRIDE - 1); 142 samples = PEAK_SAMPLES - (PEAK_STRIDE - 1);
@@ -326,9 +188,7 @@ void pcm_calculate_peaks(int *left, int *right)
326 *right = peak_value; 188 *right = peak_value;
327 } 189 }
328} 190}
329#endif /* !defined(CPU_PP) */ 191#endif /* defined(CPU_COLDFIRE) || (CONFIG_CPU == S3C2440) || defined(CPU_PP) */
330
331#endif /* !defined(CPU_COLDFIRE) && (CONFIG_CPU != S3C2440) */
332 192
333/**************************************************************************** 193/****************************************************************************
334 * Functions that do not require targeted implementation but only a targeted 194 * Functions that do not require targeted implementation but only a targeted
@@ -418,3 +278,4 @@ bool pcm_is_paused(void)
418{ 278{
419 return pcm_paused; 279 return pcm_paused;
420} 280}
281