summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugin.c1
-rw-r--r--apps/plugin.h5
-rw-r--r--firmware/export/pcm_playback.h1
-rw-r--r--firmware/export/pcm_record.h17
-rw-r--r--firmware/pcm_record.c42
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c68
6 files changed, 61 insertions, 73 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index 268fee5fd8..b129493471 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -482,6 +482,7 @@ static const struct plugin_api rockbox_api = {
482 482
483#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) && !defined(SIMULATOR) 483#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) && !defined(SIMULATOR)
484 sound_default, 484 sound_default,
485 pcm_record_more,
485#endif 486#endif
486}; 487};
487 488
diff --git a/apps/plugin.h b/apps/plugin.h
index 22f6b97fce..68841e8698 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -580,8 +580,8 @@ struct plugin_api {
580#ifndef SIMULATOR 580#ifndef SIMULATOR
581 void (*pcm_init_recording)(void); 581 void (*pcm_init_recording)(void);
582 void (*pcm_close_recording)(void); 582 void (*pcm_close_recording)(void);
583 void (*pcm_record_data)(pcm_more_callback_type more_ready, 583 void (*pcm_record_data)(pcm_more_callback_type2 more_ready,
584 unsigned char *start, size_t size); 584 void *start, size_t size);
585 void (*pcm_stop_recording)(void); 585 void (*pcm_stop_recording)(void);
586 void (*pcm_calculate_rec_peaks)(int *left, int *right); 586 void (*pcm_calculate_rec_peaks)(int *left, int *right);
587 void (*audio_set_recording_gain)(int left, int right, int type); 587 void (*audio_set_recording_gain)(int left, int right, int type);
@@ -598,6 +598,7 @@ struct plugin_api {
598 598
599#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) && !defined(SIMULATOR) 599#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) && !defined(SIMULATOR)
600 int (*sound_default)(int setting); 600 int (*sound_default)(int setting);
601 void (*pcm_record_more)(void *start, size_t size);
601#endif 602#endif
602}; 603};
603 604
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) */
25typedef void (*pcm_more_callback_type)(unsigned char **start, 25typedef void (*pcm_more_callback_type)(unsigned char **start,
26 size_t *size); 26 size_t *size);
27typedef int (*pcm_more_callback_type2)(int status);
27 28
28void pcm_init(void); 29void 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);
36void pcm_close_recording(void); 36void pcm_close_recording(void);
37 37
38/* Start recording "raw" PCM data */ 38/* Start recording "raw" PCM data */
39void pcm_record_data(pcm_more_callback_type more_ready, 39void 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 */
43void pcm_stop_recording(void); 43void pcm_stop_recording(void);
44 44
45/* Continue transferring data in - call during interrupt handler */
46void pcm_record_more(void *start, size_t size);
47
45void pcm_calculate_rec_peaks(int *left, int *right); 48void 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 */
67extern volatile pcm_more_callback_type pcm_callback_more_ready; 70extern volatile pcm_more_callback_type2 pcm_callback_more_ready;
68/* DMA transfer in is currently active */ 71/* DMA transfer in is currently active */
69extern volatile bool pcm_recording; 72extern volatile bool pcm_recording;
70 73
71/* APIs implemented in the target-specific portion */ 74/* APIs implemented in the target-specific portion */
72extern void pcm_rec_dma_start(const void *addr, size_t size); 75extern void pcm_rec_dma_start(void *addr, size_t size);
73extern void pcm_rec_dma_stop(void); 76extern 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 */
58volatile pcm_more_callback_type pcm_callback_more_ready = NULL; 58volatile pcm_more_callback_type2 pcm_callback_more_ready = NULL;
59/* DMA transfer in is currently active */ 59/* DMA transfer in is currently active */
60volatile bool pcm_recording = false; 60volatile bool pcm_recording = false;
61
62/* APIs implemented in the target-specific portion */
63void pcm_rec_dma_start(const void *addr, size_t size);
64void pcm_rec_dma_stop(void);
65 61
66/** General recording state **/ 62/** General recording state **/
67static bool is_recording; /* We are recording */ 63static 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 */
228static void pcm_rec_have_more(unsigned char **data, size_t *size) 224static 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 */
1624void pcm_record_data(pcm_more_callback_type more_ready, 1620void 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
1640void pcm_stop_recording(void) 1630void 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 **/
290void pcm_rec_dma_start(const void *addr, size_t size) 290void 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
316void pcm_rec_dma_stop(void) 314void 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
326void pcm_init_recording(void) 324void 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")));
359void DMA1(void) 357void 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 */
395void 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
411void pcm_mute(bool mute) 403void pcm_mute(bool mute)
412{ 404{
413 ac_mute(mute); 405 ac_mute(mute);