diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/pcm_playback.h | 1 | ||||
-rw-r--r-- | firmware/export/pcm_record.h | 17 | ||||
-rw-r--r-- | firmware/pcm_record.c | 42 | ||||
-rw-r--r-- | firmware/target/coldfire/pcm-coldfire.c | 68 |
4 files changed, 57 insertions, 71 deletions
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h index e7c00edeed..80a1f557fe 100644 --- a/firmware/export/pcm_playback.h +++ b/firmware/export/pcm_playback.h | |||
@@ -24,6 +24,7 @@ | |||
24 | /* Typedef for registered callback (play and record) */ | 24 | /* Typedef for registered callback (play and record) */ |
25 | typedef void (*pcm_more_callback_type)(unsigned char **start, | 25 | typedef void (*pcm_more_callback_type)(unsigned char **start, |
26 | size_t *size); | 26 | size_t *size); |
27 | typedef int (*pcm_more_callback_type2)(int status); | ||
27 | 28 | ||
28 | void pcm_init(void); | 29 | void pcm_init(void); |
29 | 30 | ||
diff --git a/firmware/export/pcm_record.h b/firmware/export/pcm_record.h index 30d2dc7e6f..f6dddb3424 100644 --- a/firmware/export/pcm_record.h +++ b/firmware/export/pcm_record.h | |||
@@ -20,9 +20,9 @@ | |||
20 | #ifndef PCM_RECORD_H | 20 | #ifndef PCM_RECORD_H |
21 | #define PCM_RECORD_H | 21 | #define PCM_RECORD_H |
22 | 22 | ||
23 | #define DMA_REC_ERROR_DMA ((size_t)-1) | 23 | #define DMA_REC_ERROR_DMA (-1) |
24 | #ifdef HAVE_SPDIF_IN | 24 | #ifdef HAVE_SPDIF_IN |
25 | #define DMA_REC_ERROR_SPDIF ((size_t)-2) | 25 | #define DMA_REC_ERROR_SPDIF (-2) |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | /** | 28 | /** |
@@ -36,12 +36,15 @@ void pcm_init_recording(void); | |||
36 | void pcm_close_recording(void); | 36 | void pcm_close_recording(void); |
37 | 37 | ||
38 | /* Start recording "raw" PCM data */ | 38 | /* Start recording "raw" PCM data */ |
39 | void pcm_record_data(pcm_more_callback_type more_ready, | 39 | void pcm_record_data(pcm_more_callback_type2 more_ready, |
40 | unsigned char *start, size_t size); | 40 | void *start, size_t size); |
41 | 41 | ||
42 | /* Stop tranferring data into supplied buffer */ | 42 | /* Stop tranferring data into supplied buffer */ |
43 | void pcm_stop_recording(void); | 43 | void pcm_stop_recording(void); |
44 | 44 | ||
45 | /* Continue transferring data in - call during interrupt handler */ | ||
46 | void pcm_record_more(void *start, size_t size); | ||
47 | |||
45 | void pcm_calculate_rec_peaks(int *left, int *right); | 48 | void pcm_calculate_rec_peaks(int *left, int *right); |
46 | 49 | ||
47 | /** General functions for high level codec recording **/ | 50 | /** General functions for high level codec recording **/ |
@@ -64,12 +67,12 @@ int pcm_get_num_unprocessed(void); | |||
64 | /** The following are for internal use between pcm_record.c and target- | 67 | /** The following are for internal use between pcm_record.c and target- |
65 | specific portion **/ | 68 | specific portion **/ |
66 | /* the registered callback function for when more data is available */ | 69 | /* the registered callback function for when more data is available */ |
67 | extern volatile pcm_more_callback_type pcm_callback_more_ready; | 70 | extern volatile pcm_more_callback_type2 pcm_callback_more_ready; |
68 | /* DMA transfer in is currently active */ | 71 | /* DMA transfer in is currently active */ |
69 | extern volatile bool pcm_recording; | 72 | extern volatile bool pcm_recording; |
70 | 73 | ||
71 | /* APIs implemented in the target-specific portion */ | 74 | /* APIs implemented in the target-specific portion */ |
72 | extern void pcm_rec_dma_start(const void *addr, size_t size); | 75 | extern void pcm_rec_dma_start(void *addr, size_t size); |
73 | extern void pcm_rec_dma_stop(void); | 76 | extern void pcm_rec_dma_stop(void); |
74 | 77 | ||
75 | #endif /* PCM_RECORD_H */ | 78 | #endif /* PCM_RECORD_H */ |
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c index 379adc3a9c..a72641baa6 100644 --- a/firmware/pcm_record.c +++ b/firmware/pcm_record.c | |||
@@ -55,13 +55,9 @@ | |||
55 | be shared semi-privately **/ | 55 | be shared semi-privately **/ |
56 | 56 | ||
57 | /* the registered callback function for when more data is available */ | 57 | /* the registered callback function for when more data is available */ |
58 | volatile pcm_more_callback_type pcm_callback_more_ready = NULL; | 58 | volatile pcm_more_callback_type2 pcm_callback_more_ready = NULL; |
59 | /* DMA transfer in is currently active */ | 59 | /* DMA transfer in is currently active */ |
60 | volatile bool pcm_recording = false; | 60 | volatile bool pcm_recording = false; |
61 | |||
62 | /* APIs implemented in the target-specific portion */ | ||
63 | void pcm_rec_dma_start(const void *addr, size_t size); | ||
64 | void pcm_rec_dma_stop(void); | ||
65 | 61 | ||
66 | /** General recording state **/ | 62 | /** General recording state **/ |
67 | static bool is_recording; /* We are recording */ | 63 | static bool is_recording; /* We are recording */ |
@@ -225,16 +221,16 @@ static void pcm_thread_wait_for_stop(void) | |||
225 | /*******************************************************************/ | 221 | /*******************************************************************/ |
226 | 222 | ||
227 | /* Callback for when more data is ready */ | 223 | /* Callback for when more data is ready */ |
228 | static void pcm_rec_have_more(unsigned char **data, size_t *size) | 224 | static int pcm_rec_have_more(int status) |
229 | { | 225 | { |
230 | if (*size != 0) | 226 | if (status < 0) |
231 | { | 227 | { |
232 | /* some error condition */ | 228 | /* some error condition */ |
233 | if (*size == DMA_REC_ERROR_DMA) | 229 | if (status == DMA_REC_ERROR_DMA) |
234 | { | 230 | { |
235 | /* Flush recorded data to disk and stop recording */ | 231 | /* Flush recorded data to disk and stop recording */ |
236 | queue_post(&pcmrec_queue, PCMREC_STOP, NULL); | 232 | queue_post(&pcmrec_queue, PCMREC_STOP, NULL); |
237 | return; | 233 | return -1; |
238 | } | 234 | } |
239 | /* else try again next transmission */ | 235 | /* else try again next transmission */ |
240 | } | 236 | } |
@@ -243,9 +239,9 @@ static void pcm_rec_have_more(unsigned char **data, size_t *size) | |||
243 | /* advance write position */ | 239 | /* advance write position */ |
244 | dma_wr_pos = (dma_wr_pos + PCM_CHUNK_SIZE) & PCM_CHUNK_MASK; | 240 | dma_wr_pos = (dma_wr_pos + PCM_CHUNK_SIZE) & PCM_CHUNK_MASK; |
245 | } | 241 | } |
246 | 242 | ||
247 | *data = (unsigned char *)GET_PCM_CHUNK(dma_wr_pos); | 243 | pcm_record_more(GET_PCM_CHUNK(dma_wr_pos), PCM_CHUNK_SIZE); |
248 | *size = PCM_CHUNK_SIZE; | 244 | return 0; |
249 | } /* pcm_rec_have_more */ | 245 | } /* pcm_rec_have_more */ |
250 | 246 | ||
251 | /** pcm_rec_* group **/ | 247 | /** pcm_rec_* group **/ |
@@ -423,9 +419,9 @@ void audio_set_recording_options(struct audio_recording_options *options) | |||
423 | if (audio_load_encoder(enc_config.afmt)) | 419 | if (audio_load_encoder(enc_config.afmt)) |
424 | { | 420 | { |
425 | /* start DMA transfer */ | 421 | /* start DMA transfer */ |
426 | pcm_record_data(pcm_rec_have_more, NULL, 0); | ||
427 | /* do unlock after starting to prevent preincrement of dma_wr_pos */ | ||
428 | dma_lock = pre_record_ticks == 0; | 422 | dma_lock = pre_record_ticks == 0; |
423 | pcm_record_data(pcm_rec_have_more, GET_PCM_CHUNK(dma_wr_pos), | ||
424 | PCM_CHUNK_SIZE); | ||
429 | } | 425 | } |
430 | else | 426 | else |
431 | { | 427 | { |
@@ -1621,20 +1617,14 @@ size_t enc_unget_pcm_data(size_t size) | |||
1621 | * Functions that do not require targeted implementation but only a targeted | 1617 | * Functions that do not require targeted implementation but only a targeted |
1622 | * interface | 1618 | * interface |
1623 | */ | 1619 | */ |
1624 | void pcm_record_data(pcm_more_callback_type more_ready, | 1620 | void pcm_record_data(pcm_more_callback_type2 more_ready, |
1625 | unsigned char *start, size_t size) | 1621 | void *start, size_t size) |
1626 | { | 1622 | { |
1627 | pcm_callback_more_ready = more_ready; | ||
1628 | |||
1629 | if (!(start && size)) | 1623 | if (!(start && size)) |
1630 | { | 1624 | return; |
1631 | size = 0; | ||
1632 | if (more_ready) | ||
1633 | more_ready(&start, &size); | ||
1634 | } | ||
1635 | 1625 | ||
1636 | if (start && size) | 1626 | pcm_callback_more_ready = more_ready; |
1637 | pcm_rec_dma_start(start, size); | 1627 | pcm_rec_dma_start(start, size); |
1638 | } /* pcm_record_data */ | 1628 | } /* pcm_record_data */ |
1639 | 1629 | ||
1640 | void pcm_stop_recording(void) | 1630 | void pcm_stop_recording(void) |
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c index 917800d0b8..4e4e557d9b 100644 --- a/firmware/target/coldfire/pcm-coldfire.c +++ b/firmware/target/coldfire/pcm-coldfire.c | |||
@@ -287,7 +287,7 @@ void DMA0(void) | |||
287 | /**************************************************************************** | 287 | /**************************************************************************** |
288 | ** Recording DMA transfer | 288 | ** Recording DMA transfer |
289 | **/ | 289 | **/ |
290 | void pcm_rec_dma_start(const void *addr, size_t size) | 290 | void pcm_rec_dma_start(void *addr, size_t size) |
291 | { | 291 | { |
292 | logf("pcm_rec_dma_start"); | 292 | logf("pcm_rec_dma_start"); |
293 | 293 | ||
@@ -296,12 +296,6 @@ void pcm_rec_dma_start(const void *addr, size_t size) | |||
296 | 296 | ||
297 | pcm_recording = true; | 297 | pcm_recording = true; |
298 | 298 | ||
299 | DAR1 = (unsigned long)addr; /* Destination address */ | ||
300 | SAR1 = (unsigned long)&PDIR2; /* Source address */ | ||
301 | BCR1 = size; /* Bytes to transfer */ | ||
302 | |||
303 | rec_peak_addr = (unsigned long *)addr; | ||
304 | |||
305 | pcm_apply_settings(false); | 299 | pcm_apply_settings(false); |
306 | 300 | ||
307 | /* Start the DMA transfer.. */ | 301 | /* Start the DMA transfer.. */ |
@@ -309,18 +303,22 @@ void pcm_rec_dma_start(const void *addr, size_t size) | |||
309 | INTERRUPTCLEAR = 0x03c00000; | 303 | INTERRUPTCLEAR = 0x03c00000; |
310 | #endif | 304 | #endif |
311 | 305 | ||
312 | DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | | 306 | SAR1 = (unsigned long)&PDIR2; /* Source address */ |
313 | DMA_DSIZE(3) | DMA_START; | 307 | DCR1 = DMA_INT | DMA_CS | DMA_AA | DMA_DINC | DMA_DSIZE(3); |
308 | |||
309 | pcm_record_more(addr, size); | ||
310 | |||
311 | DCR1 |= DMA_START; | ||
314 | } /* pcm_dma_start */ | 312 | } /* pcm_dma_start */ |
315 | 313 | ||
316 | void pcm_rec_dma_stop(void) | 314 | void pcm_rec_dma_stop(void) |
317 | { | 315 | { |
318 | logf("pcm_rec_dma_stop"); | 316 | logf("pcm_rec_dma_stop"); |
319 | 317 | ||
320 | pcm_recording = false; | ||
321 | |||
322 | DCR1 = 0; | ||
323 | DSR1 = 1; /* Clear interrupt */ | 318 | DSR1 = 1; /* Clear interrupt */ |
319 | DCR1 = 0; | ||
320 | |||
321 | pcm_recording = false; | ||
324 | } /* pcm_dma_stop */ | 322 | } /* pcm_dma_stop */ |
325 | 323 | ||
326 | void pcm_init_recording(void) | 324 | void pcm_init_recording(void) |
@@ -338,7 +336,7 @@ void pcm_init_recording(void) | |||
338 | 336 | ||
339 | pcm_rec_dma_stop(); | 337 | pcm_rec_dma_stop(); |
340 | 338 | ||
341 | ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ | 339 | ICR7 = (6 << 2); /* Enable interrupt at level 6, priority 0 */ |
342 | IMR &= ~(1 << 15); /* bit 15 is DMA1 */ | 340 | IMR &= ~(1 << 15); /* bit 15 is DMA1 */ |
343 | } /* pcm_init_recording */ | 341 | } /* pcm_init_recording */ |
344 | 342 | ||
@@ -359,17 +357,15 @@ void DMA1(void) __attribute__ ((interrupt_handler, section(".icode"))); | |||
359 | void DMA1(void) | 357 | void DMA1(void) |
360 | { | 358 | { |
361 | int res = DSR1; | 359 | int res = DSR1; |
362 | pcm_more_callback_type more_ready; | 360 | int status = 0; |
363 | unsigned char *next_start; | 361 | pcm_more_callback_type2 more_ready; |
364 | ssize_t next_size = 0; /* passing <> 0 is indicates | ||
365 | an error condition */ | ||
366 | 362 | ||
367 | DSR1 = 1; /* Clear interrupt */ | 363 | DSR1 = 1; /* Clear interrupt */ |
368 | DCR1 &= ~DMA_EEXT; | 364 | DCR1 &= ~DMA_EEXT; /* Disable peripheral request */ |
369 | 365 | ||
370 | if (res & 0x70) | 366 | if (res & 0x70) |
371 | { | 367 | { |
372 | next_size = DMA_REC_ERROR_DMA; | 368 | status = DMA_REC_ERROR_DMA; |
373 | logf("DMA1 err: 0x%x", res); | 369 | logf("DMA1 err: 0x%x", res); |
374 | } | 370 | } |
375 | #ifdef HAVE_SPDIF_IN | 371 | #ifdef HAVE_SPDIF_IN |
@@ -377,37 +373,33 @@ void DMA1(void) | |||
377 | (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */ | 373 | (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */ |
378 | { | 374 | { |
379 | INTERRUPTCLEAR = 0x03c00000; | 375 | INTERRUPTCLEAR = 0x03c00000; |
380 | next_size = DMA_REC_ERROR_SPDIF; | 376 | status = DMA_REC_ERROR_SPDIF; |
381 | logf("spdif err"); | 377 | logf("spdif err"); |
382 | } | 378 | } |
383 | #endif | 379 | #endif |
384 | 380 | ||
385 | more_ready = pcm_callback_more_ready; | 381 | more_ready = pcm_callback_more_ready; |
386 | 382 | ||
387 | if (more_ready) | 383 | if (more_ready != NULL && more_ready(status) >= 0) |
388 | more_ready(&next_start, &next_size); | ||
389 | |||
390 | if (next_size > 0) | ||
391 | { | ||
392 | /* Start peaking at dest */ | ||
393 | rec_peak_addr = (unsigned long *)next_start; | ||
394 | DAR1 = (unsigned long)next_start; /* Destination address */ | ||
395 | BCR1 = (unsigned long)next_size; /* Bytes to transfer */ | ||
396 | DCR1 |= DMA_EEXT; | ||
397 | return; | 384 | return; |
398 | } | 385 | |
399 | else | ||
400 | { | ||
401 | #if 0 | 386 | #if 0 |
402 | /* int. logfs can trash the display */ | 387 | /* int. logfs can trash the display */ |
403 | logf("DMA1 No Data:0x%04x", res); | 388 | logf("DMA1 done:%04x %d", res, status); |
404 | #endif | 389 | #endif |
405 | } | ||
406 | |||
407 | /* Finished recording */ | 390 | /* Finished recording */ |
408 | pcm_rec_dma_stop(); | 391 | pcm_rec_dma_stop(); |
409 | } /* DMA1 */ | 392 | } /* DMA1 */ |
410 | 393 | ||
394 | /* Continue transferring data in */ | ||
395 | void pcm_record_more(void *start, size_t size) | ||
396 | { | ||
397 | rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ | ||
398 | DAR1 = (unsigned long)start; /* Destination address */ | ||
399 | BCR1 = (unsigned long)size; /* Bytes to transfer */ | ||
400 | DCR1 |= DMA_EEXT; | ||
401 | } | ||
402 | |||
411 | void pcm_mute(bool mute) | 403 | void pcm_mute(bool mute) |
412 | { | 404 | { |
413 | ac_mute(mute); | 405 | ac_mute(mute); |