summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-05-24 16:42:32 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-05-24 16:42:32 +0000
commitd56999890f2aacf197d9ae4383313271499509a9 (patch)
tree76a0177e2cf19bb15a065199b812ef20158422e1
parent6688988ec42aa2254c8e370ec1932033a258b6fa (diff)
downloadrockbox-d56999890f2aacf197d9ae4383313271499509a9.tar.gz
rockbox-d56999890f2aacf197d9ae4383313271499509a9.zip
Make PCM->driver interface about as simple as it will get. Registered callback, zero data, alignment and stops are handled entirely inside pcm.c; driver merely calls fixed pcm.c callback. Remove pcm_record_more and do it just like playback; the original reason behind it isn't very practical in general. Everything checks out on supported targets. There wer some compat changes I can't check out on many unsupoorted but if there's a problem it will be a minor oops. Plugins become incompatible due to recording tweak-- full update. Sorted API.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26253 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugin.c30
-rw-r--r--apps/plugin.h46
-rw-r--r--apps/plugins/pitch_detector.c7
-rw-r--r--apps/recorder/pcm_record.c10
-rw-r--r--apps/voice_thread.c4
-rw-r--r--firmware/export/pcm.h30
-rw-r--r--firmware/pcm.c150
-rw-r--r--firmware/target/arm/as3525/pcm-as3525.c43
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c81
-rw-r--r--firmware/target/arm/pcm-pp.c83
-rw-r--r--firmware/target/arm/pcm-telechips.c43
-rw-r--r--firmware/target/arm/pnx0101/pcm-pnx0101.c7
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c34
-rw-r--r--firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c34
-rw-r--r--firmware/target/arm/s5l8700/pcm-s5l8700.c22
-rw-r--r--firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c15
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c63
-rw-r--r--firmware/target/hosted/sdl/pcm-sdl.c18
-rw-r--r--firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c21
19 files changed, 279 insertions, 462 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index b45220acdb..83f27ea249 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -177,6 +177,9 @@ static const struct plugin_api rockbox_api = {
177 &button_queue, 177 &button_queue,
178#endif 178#endif
179 bidi_l2v, 179 bidi_l2v,
180#ifdef HAVE_LCD_BITMAP
181 is_diacritic,
182#endif
180 font_get_bits, 183 font_get_bits,
181 font_load, 184 font_load,
182 font_get, 185 font_get,
@@ -461,6 +464,9 @@ static const struct plugin_api rockbox_api = {
461 sound_max, 464 sound_max,
462 sound_unit, 465 sound_unit,
463 sound_val2phys, 466 sound_val2phys,
467#ifdef AUDIOHW_HAVE_EQ
468 sound_enum_hw_eq_band_setting,
469#endif
464#ifndef SIMULATOR 470#ifndef SIMULATOR
465 mp3_play_data, 471 mp3_play_data,
466 mp3_play_pause, 472 mp3_play_pause,
@@ -491,7 +497,6 @@ static const struct plugin_api rockbox_api = {
491 pcm_init_recording, 497 pcm_init_recording,
492 pcm_close_recording, 498 pcm_close_recording,
493 pcm_record_data, 499 pcm_record_data,
494 pcm_record_more,
495 pcm_stop_recording, 500 pcm_stop_recording,
496 pcm_calculate_rec_peaks, 501 pcm_calculate_rec_peaks,
497 audio_set_recording_gain, 502 audio_set_recording_gain,
@@ -630,7 +635,12 @@ static const struct plugin_api rockbox_api = {
630 codec_thread_do_callback, 635 codec_thread_do_callback,
631 codec_load_file, 636 codec_load_file,
632 get_codec_filename, 637 get_codec_filename,
638 find_array_ptr,
639 remove_array_ptr,
640#if defined(HAVE_RECORDING) && (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
641 round_value_to_list32,
633#endif 642#endif
643#endif /* CONFIG_CODEC == SWCODEC */
634 get_metadata, 644 get_metadata,
635 mp3info, 645 mp3info,
636 count_mp3_frames, 646 count_mp3_frames,
@@ -711,24 +721,6 @@ static const struct plugin_api rockbox_api = {
711 appsversion, 721 appsversion,
712 /* new stuff at the end, sort into place next time 722 /* new stuff at the end, sort into place next time
713 the API gets incompatible */ 723 the API gets incompatible */
714
715#ifdef HAVE_LCD_BITMAP
716 is_diacritic,
717#endif
718
719#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && \
720 (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
721 round_value_to_list32,
722#endif
723
724#ifdef AUDIOHW_HAVE_EQ
725 sound_enum_hw_eq_band_setting,
726#endif
727
728#if CONFIG_CODEC == SWCODEC
729 find_array_ptr,
730 remove_array_ptr,
731#endif
732}; 724};
733 725
734int plugin_load(const char* plugin, const void* parameter) 726int plugin_load(const char* plugin, const void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index 6727ca4caf..7e198c97bd 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -144,12 +144,12 @@ void* plugin_get_buffer(size_t *buffer_size);
144#define PLUGIN_MAGIC 0x526F634B /* RocK */ 144#define PLUGIN_MAGIC 0x526F634B /* RocK */
145 145
146/* increase this every time the api struct changes */ 146/* increase this every time the api struct changes */
147#define PLUGIN_API_VERSION 186 147#define PLUGIN_API_VERSION 187
148 148
149/* update this to latest version if a change to the api struct breaks 149/* update this to latest version if a change to the api struct breaks
150 backwards compatibility (and please take the opportunity to sort in any 150 backwards compatibility (and please take the opportunity to sort in any
151 new function which are "waiting" at the end of the function table) */ 151 new function which are "waiting" at the end of the function table) */
152#define PLUGIN_MIN_API_VERSION 182 152#define PLUGIN_MIN_API_VERSION 187
153 153
154/* plugin return codes */ 154/* plugin return codes */
155enum plugin_status { 155enum plugin_status {
@@ -259,6 +259,9 @@ struct plugin_api {
259 struct event_queue *button_queue; 259 struct event_queue *button_queue;
260#endif 260#endif
261 unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation ); 261 unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation );
262#ifdef HAVE_LCD_BITMAP
263 bool (*is_diacritic)(const unsigned short char_code, bool *is_rtl);
264#endif
262 const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code ); 265 const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code );
263 int (*font_load)(struct font*, const char *path); 266 int (*font_load)(struct font*, const char *path);
264 struct font* (*font_get)(int font); 267 struct font* (*font_get)(int font);
@@ -577,6 +580,10 @@ struct plugin_api {
577 int (*sound_max)(int setting); 580 int (*sound_max)(int setting);
578 const char * (*sound_unit)(int setting); 581 const char * (*sound_unit)(int setting);
579 int (*sound_val2phys)(int setting, int value); 582 int (*sound_val2phys)(int setting, int value);
583#ifdef AUDIOHW_HAVE_EQ
584 int (*sound_enum_hw_eq_band_setting)(unsigned int band,
585 unsigned int band_setting);
586#endif /* AUDIOHW_HAVE_EQ */
580#ifndef SIMULATOR 587#ifndef SIMULATOR
581 void (*mp3_play_data)(const unsigned char* start, int size, 588 void (*mp3_play_data)(const unsigned char* start, int size,
582 void (*get_more)(unsigned char** start, size_t* size)); 589 void (*get_more)(unsigned char** start, size_t* size));
@@ -591,7 +598,7 @@ struct plugin_api {
591 const unsigned long *audio_master_sampr_list; 598 const unsigned long *audio_master_sampr_list;
592 const unsigned long *hw_freq_sampr; 599 const unsigned long *hw_freq_sampr;
593 void (*pcm_apply_settings)(void); 600 void (*pcm_apply_settings)(void);
594 void (*pcm_play_data)(pcm_more_callback_type get_more, 601 void (*pcm_play_data)(pcm_play_callback_type get_more,
595 unsigned char* start, size_t size); 602 unsigned char* start, size_t size);
596 void (*pcm_play_stop)(void); 603 void (*pcm_play_stop)(void);
597 void (*pcm_set_frequency)(unsigned int frequency); 604 void (*pcm_set_frequency)(unsigned int frequency);
@@ -610,9 +617,8 @@ struct plugin_api {
610 const unsigned long *rec_freq_sampr; 617 const unsigned long *rec_freq_sampr;
611 void (*pcm_init_recording)(void); 618 void (*pcm_init_recording)(void);
612 void (*pcm_close_recording)(void); 619 void (*pcm_close_recording)(void);
613 void (*pcm_record_data)(pcm_more_callback_type2 more_ready, 620 void (*pcm_record_data)(pcm_rec_callback_type more_ready,
614 void *start, size_t size); 621 void *start, size_t size);
615 void (*pcm_record_more)(void *start, size_t size);
616 void (*pcm_stop_recording)(void); 622 void (*pcm_stop_recording)(void);
617 void (*pcm_calculate_rec_peaks)(int *left, int *right); 623 void (*pcm_calculate_rec_peaks)(int *left, int *right);
618 void (*audio_set_recording_gain)(int left, int right, int type); 624 void (*audio_set_recording_gain)(int left, int right, int type);
@@ -774,7 +780,15 @@ struct plugin_api {
774 unsigned int *audio_thread_id); 780 unsigned int *audio_thread_id);
775 int (*codec_load_file)(const char* codec, struct codec_api *api); 781 int (*codec_load_file)(const char* codec, struct codec_api *api);
776 const char *(*get_codec_filename)(int cod_spec); 782 const char *(*get_codec_filename)(int cod_spec);
783 void ** (*find_array_ptr)(void **arr, void *ptr);
784 int (*remove_array_ptr)(void **arr, void *ptr);
785#if defined(HAVE_RECORDING) && (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
786int (*round_value_to_list32)(unsigned long value,
787 const unsigned long list[],
788 int count,
789 bool signd);
777#endif 790#endif
791#endif /* CONFIG_CODEC == SWCODEC */
778 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname); 792 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
779 bool (*mp3info)(struct mp3entry *entry, const char *filename); 793 bool (*mp3info)(struct mp3entry *entry, const char *filename);
780 int (*count_mp3_frames)(int fd, int startpos, int filesize, 794 int (*count_mp3_frames)(int fd, int startpos, int filesize,
@@ -874,28 +888,6 @@ struct plugin_api {
874 const char *appsversion; 888 const char *appsversion;
875 /* new stuff at the end, sort into place next time 889 /* new stuff at the end, sort into place next time
876 the API gets incompatible */ 890 the API gets incompatible */
877
878#ifdef HAVE_LCD_BITMAP
879 bool (*is_diacritic)(const unsigned short char_code, bool *is_rtl);
880#endif
881
882#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && \
883 (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
884int (*round_value_to_list32)(unsigned long value,
885 const unsigned long list[],
886 int count,
887 bool signd);
888#endif
889
890#ifdef AUDIOHW_HAVE_EQ
891 int (*sound_enum_hw_eq_band_setting)(unsigned int band,
892 unsigned int band_setting);
893#endif /* AUDIOHW_HAVE_EQ */
894
895#if CONFIG_CODEC == SWCODEC
896 void ** (*find_array_ptr)(void **arr, void *ptr);
897 int (*remove_array_ptr)(void **arr, void *ptr);
898#endif
899}; 891};
900 892
901/* plugin header */ 893/* plugin header */
diff --git a/apps/plugins/pitch_detector.c b/apps/plugins/pitch_detector.c
index 538e0886fa..208b146c4e 100644
--- a/apps/plugins/pitch_detector.c
+++ b/apps/plugins/pitch_detector.c
@@ -982,7 +982,7 @@ uint32_t ICODE_ATTR buffer_magnitude(int16_t *input)
982 982
983/* Stop the recording when the buffer is full */ 983/* Stop the recording when the buffer is full */
984#ifndef SIMULATOR 984#ifndef SIMULATOR
985int recording_callback(int status) 985void recording_callback(int status, void **start, size_t *size)
986{ 986{
987 int tail = audio_tail ^ 1; 987 int tail = audio_tail ^ 1;
988 988
@@ -991,10 +991,9 @@ int recording_callback(int status)
991 audio_tail = tail; 991 audio_tail = tail;
992 992
993 /* Always record full buffer, even if not required */ 993 /* Always record full buffer, even if not required */
994 rb->pcm_record_more(audio_data[tail], 994 *start = audio_data[tail];
995 BUFFER_SIZE * sizeof (int16_t)); 995 *size = BUFFER_SIZE * sizeof (int16_t);
996 996
997 return 0;
998 (void)status; 997 (void)status;
999} 998}
1000#endif 999#endif
diff --git a/apps/recorder/pcm_record.c b/apps/recorder/pcm_record.c
index 2567b56ef3..687a70664d 100644
--- a/apps/recorder/pcm_record.c
+++ b/apps/recorder/pcm_record.c
@@ -256,7 +256,7 @@ enum
256/*******************************************************************/ 256/*******************************************************************/
257 257
258/* Callback for when more data is ready - called in interrupt context */ 258/* Callback for when more data is ready - called in interrupt context */
259static int pcm_rec_have_more(int status) 259static void pcm_rec_have_more(int status, void **start, size_t *size)
260{ 260{
261 if (status < 0) 261 if (status < 0)
262 { 262 {
@@ -265,9 +265,9 @@ static int pcm_rec_have_more(int status)
265 { 265 {
266 /* Flush recorded data to disk and stop recording */ 266 /* Flush recorded data to disk and stop recording */
267 queue_post(&pcmrec_queue, PCMREC_STOP, 0); 267 queue_post(&pcmrec_queue, PCMREC_STOP, 0);
268 return -1; 268 return;
269 } 269 }
270 /* else try again next transmission */ 270 /* else try again next transmission - frame is invalid */
271 } 271 }
272 else if (!dma_lock) 272 else if (!dma_lock)
273 { 273 {
@@ -282,8 +282,8 @@ static int pcm_rec_have_more(int status)
282 dma_wr_pos = next_pos; 282 dma_wr_pos = next_pos;
283 } 283 }
284 284
285 pcm_record_more(GET_PCM_CHUNK(dma_wr_pos), PCM_CHUNK_SIZE); 285 *start = GET_PCM_CHUNK(dma_wr_pos);
286 return 0; 286 *size = PCM_CHUNK_SIZE;
287} /* pcm_rec_have_more */ 287} /* pcm_rec_have_more */
288 288
289static void reset_hardware(void) 289static void reset_hardware(void)
diff --git a/apps/voice_thread.c b/apps/voice_thread.c
index 076bd2ea1b..a65ec566d1 100644
--- a/apps/voice_thread.c
+++ b/apps/voice_thread.c
@@ -89,7 +89,7 @@ enum voice_thread_messages
89/* Structure to store clip data callback info */ 89/* Structure to store clip data callback info */
90struct voice_info 90struct voice_info
91{ 91{
92 pcm_more_callback_type get_more; /* Callback to get more clips */ 92 pcm_play_callback_type get_more; /* Callback to get more clips */
93 unsigned char *start; /* Start of clip */ 93 unsigned char *start; /* Start of clip */
94 size_t size; /* Size of clip */ 94 size_t size; /* Size of clip */
95}; 95};
@@ -117,7 +117,7 @@ static inline bool playback_is_playing(void)
117 117
118/* Stop any current clip and start playing a new one */ 118/* Stop any current clip and start playing a new one */
119void mp3_play_data(const unsigned char* start, int size, 119void mp3_play_data(const unsigned char* start, int size,
120 pcm_more_callback_type get_more) 120 pcm_play_callback_type get_more)
121{ 121{
122 /* Shared struct to get data to the thread - once it replies, it has 122 /* Shared struct to get data to the thread - once it replies, it has
123 * safely cached it in its own private data */ 123 * safely cached it in its own private data */
diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h
index 0d2d39b03d..40bfe6fa46 100644
--- a/firmware/export/pcm.h
+++ b/firmware/export/pcm.h
@@ -50,9 +50,9 @@
50/** RAW PCM routines used with playback and recording **/ 50/** RAW PCM routines used with playback and recording **/
51 51
52/* Typedef for registered callback */ 52/* Typedef for registered callback */
53typedef void (*pcm_more_callback_type)(unsigned char **start, 53typedef void (*pcm_play_callback_type)(unsigned char **start,
54 size_t *size); 54 size_t *size);
55typedef int (*pcm_more_callback_type2)(int status); 55typedef void (*pcm_rec_callback_type)(int status, void **start, size_t *size);
56 56
57/* set the pcm frequency - use values in hw_sampr_list 57/* set the pcm frequency - use values in hw_sampr_list
58 * use -1 for the default frequency 58 * use -1 for the default frequency
@@ -71,7 +71,7 @@ void pcm_init(void);
71void pcm_postinit(void); 71void pcm_postinit(void);
72 72
73/* This is for playing "raw" PCM data */ 73/* This is for playing "raw" PCM data */
74void pcm_play_data(pcm_more_callback_type get_more, 74void pcm_play_data(pcm_play_callback_type get_more,
75 unsigned char* start, size_t size); 75 unsigned char* start, size_t size);
76 76
77void pcm_calculate_peaks(int *left, int *right); 77void pcm_calculate_peaks(int *left, int *right);
@@ -86,6 +86,11 @@ bool pcm_is_playing(void);
86/** The following are for internal use between pcm.c and target- 86/** The following are for internal use between pcm.c and target-
87 specific portion **/ 87 specific portion **/
88 88
89/* Called by the bottom layer ISR when more data is needed. Returns non-
90 * zero size if more data is to be played. Setting start to NULL
91 * forces stop. */
92void pcm_play_get_more_callback(void **start, size_t *size);
93
89extern unsigned long pcm_curr_sampr; 94extern unsigned long pcm_curr_sampr;
90extern unsigned long pcm_sampr; 95extern unsigned long pcm_sampr;
91extern int pcm_fsel; 96extern int pcm_fsel;
@@ -94,10 +99,8 @@ extern int pcm_fsel;
94void * pcm_dma_addr(void *addr); 99void * pcm_dma_addr(void *addr);
95#endif 100#endif
96 101
97/* the registered callback function to ask for more mp3 data */ 102extern volatile bool pcm_playing;
98extern volatile pcm_more_callback_type pcm_callback_for_more; 103extern volatile bool pcm_paused;
99extern volatile bool pcm_playing;
100extern volatile bool pcm_paused;
101 104
102void pcm_play_dma_lock(void); 105void pcm_play_dma_lock(void);
103void pcm_play_dma_unlock(void); 106void pcm_play_dma_unlock(void);
@@ -105,7 +108,6 @@ void pcm_play_dma_init(void);
105void pcm_play_dma_start(const void *addr, size_t size); 108void pcm_play_dma_start(const void *addr, size_t size);
106void pcm_play_dma_stop(void); 109void pcm_play_dma_stop(void);
107void pcm_play_dma_pause(bool pause); 110void pcm_play_dma_pause(bool pause);
108void pcm_play_dma_stopped_callback(void);
109const void * pcm_play_dma_get_peak_buffer(int *count); 111const void * pcm_play_dma_get_peak_buffer(int *count);
110 112
111void pcm_dma_apply_settings(void); 113void pcm_dma_apply_settings(void);
@@ -124,7 +126,7 @@ void pcm_init_recording(void);
124void pcm_close_recording(void); 126void pcm_close_recording(void);
125 127
126/* Start recording "raw" PCM data */ 128/* Start recording "raw" PCM data */
127void pcm_record_data(pcm_more_callback_type2 more_ready, 129void pcm_record_data(pcm_rec_callback_type more_ready,
128 void *start, size_t size); 130 void *start, size_t size);
129 131
130/* Stop tranferring data into supplied buffer */ 132/* Stop tranferring data into supplied buffer */
@@ -133,17 +135,16 @@ void pcm_stop_recording(void);
133/* Is pcm currently recording? */ 135/* Is pcm currently recording? */
134bool pcm_is_recording(void); 136bool pcm_is_recording(void);
135 137
136/* Continue transferring data in - call during interrupt handler */ 138/* Called by bottom layer ISR when transfer is complete. Returns non-zero
137void pcm_record_more(void *start, size_t size); 139 * size if successful. Setting start to NULL forces stop. */
140void pcm_rec_more_ready_callback(int status, void **start, size_t *size);
138 141
139void pcm_calculate_rec_peaks(int *left, int *right); 142void pcm_calculate_rec_peaks(int *left, int *right);
140 143
141/** The following are for internal use between pcm.c and target- 144/** The following are for internal use between pcm.c and target-
142 specific portion **/ 145 specific portion **/
143/* the registered callback function for when more data is available */
144extern volatile pcm_more_callback_type2 pcm_callback_more_ready;
145/* DMA transfer in is currently active */ 146/* DMA transfer in is currently active */
146extern volatile bool pcm_recording; 147extern volatile bool pcm_recording;
147 148
148/* APIs implemented in the target-specific portion */ 149/* APIs implemented in the target-specific portion */
149void pcm_rec_dma_init(void); 150void pcm_rec_dma_init(void);
@@ -151,7 +152,6 @@ void pcm_rec_dma_close(void);
151void pcm_rec_dma_start(void *addr, size_t size); 152void pcm_rec_dma_start(void *addr, size_t size);
152void pcm_rec_dma_record_more(void *start, size_t size); 153void pcm_rec_dma_record_more(void *start, size_t size);
153void pcm_rec_dma_stop(void); 154void pcm_rec_dma_stop(void);
154void pcm_rec_dma_stopped_callback(void);
155const void * pcm_rec_dma_get_peak_buffer(void); 155const void * pcm_rec_dma_get_peak_buffer(void);
156 156
157#endif /* HAVE_RECORDING */ 157#endif /* HAVE_RECORDING */
diff --git a/firmware/pcm.c b/firmware/pcm.c
index a69f0a8232..8080823077 100644
--- a/firmware/pcm.c
+++ b/firmware/pcm.c
@@ -39,6 +39,7 @@
39 * pcm_play_lock 39 * pcm_play_lock
40 * pcm_play_unlock 40 * pcm_play_unlock
41 * Semi-private - 41 * Semi-private -
42 * pcm_play_get_more_callback
42 * pcm_play_dma_init 43 * pcm_play_dma_init
43 * pcm_play_dma_start 44 * pcm_play_dma_start
44 * pcm_play_dma_stop 45 * pcm_play_dma_stop
@@ -48,28 +49,27 @@
48 * pcm_sampr (R) 49 * pcm_sampr (R)
49 * pcm_fsel (R) 50 * pcm_fsel (R)
50 * pcm_curr_sampr (R) 51 * pcm_curr_sampr (R)
51 * pcm_callback_for_more (R)
52 * pcm_playing (R) 52 * pcm_playing (R)
53 * pcm_paused (R) 53 * pcm_paused (R)
54 * 54 *
55 * ==Playback/Recording== 55 * ==Playback/Recording==
56 * Public -
57 * pcm_dma_addr
56 * Semi-private - 58 * Semi-private -
57 * pcm_dma_apply_settings 59 * pcm_dma_apply_settings
58 * pcm_dma_addr
59 * 60 *
60 * ==Recording== 61 * ==Recording==
61 * Public - 62 * Public -
62 * pcm_rec_lock 63 * pcm_rec_lock
63 * pcm_rec_unlock 64 * pcm_rec_unlock
64 * Semi-private - 65 * Semi-private -
66 * pcm_rec_more_ready_callback
65 * pcm_rec_dma_init 67 * pcm_rec_dma_init
66 * pcm_rec_dma_close 68 * pcm_rec_dma_close
67 * pcm_rec_dma_start 69 * pcm_rec_dma_start
68 * pcm_rec_dma_record_more
69 * pcm_rec_dma_stop 70 * pcm_rec_dma_stop
70 * pcm_rec_dma_get_peak_buffer 71 * pcm_rec_dma_get_peak_buffer
71 * Data Read/Written within TSP - 72 * Data Read/Written within TSP -
72 * pcm_callback_more_ready (R)
73 * pcm_recording (R) 73 * pcm_recording (R)
74 * 74 *
75 * States are set _after_ the target's pcm driver is called so that it may 75 * States are set _after_ the target's pcm driver is called so that it may
@@ -78,7 +78,7 @@
78 */ 78 */
79 79
80/* the registered callback function to ask for more mp3 data */ 80/* the registered callback function to ask for more mp3 data */
81volatile pcm_more_callback_type pcm_callback_for_more 81static volatile pcm_play_callback_type pcm_callback_for_more
82 SHAREDBSS_ATTR = NULL; 82 SHAREDBSS_ATTR = NULL;
83/* PCM playback state */ 83/* PCM playback state */
84volatile bool pcm_playing SHAREDBSS_ATTR = false; 84volatile bool pcm_playing SHAREDBSS_ATTR = false;
@@ -91,6 +91,14 @@ unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT;
91/* samplerate frequency selection index */ 91/* samplerate frequency selection index */
92int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT; 92int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
93 93
94/* Called internally by functions to reset the state */
95static void pcm_play_stopped(void)
96{
97 pcm_callback_for_more = NULL;
98 pcm_paused = false;
99 pcm_playing = false;
100}
101
94/** 102/**
95 * Perform peak calculation on a buffer of packed 16-bit samples. 103 * Perform peak calculation on a buffer of packed 16-bit samples.
96 * 104 *
@@ -187,6 +195,16 @@ const void* pcm_get_peak_buffer(int * count)
187 return pcm_play_dma_get_peak_buffer(count); 195 return pcm_play_dma_get_peak_buffer(count);
188} 196}
189 197
198bool pcm_is_playing(void)
199{
200 return pcm_playing;
201}
202
203bool pcm_is_paused(void)
204{
205 return pcm_paused;
206}
207
190/**************************************************************************** 208/****************************************************************************
191 * Functions that do not require targeted implementation but only a targeted 209 * Functions that do not require targeted implementation but only a targeted
192 * interface 210 * interface
@@ -198,7 +216,7 @@ void pcm_init(void)
198{ 216{
199 logf("pcm_init"); 217 logf("pcm_init");
200 218
201 pcm_play_dma_stopped_callback(); 219 pcm_play_stopped();
202 220
203 pcm_set_frequency(HW_SAMPR_DEFAULT); 221 pcm_set_frequency(HW_SAMPR_DEFAULT);
204 222
@@ -214,7 +232,7 @@ static void pcm_play_data_start(unsigned char *start, size_t size)
214 232
215 if (!(start && size)) 233 if (!(start && size))
216 { 234 {
217 pcm_more_callback_type get_more = pcm_callback_for_more; 235 pcm_play_callback_type get_more = pcm_callback_for_more;
218 size = 0; 236 size = 0;
219 if (get_more) 237 if (get_more)
220 { 238 {
@@ -239,10 +257,10 @@ static void pcm_play_data_start(unsigned char *start, size_t size)
239 /* Force a stop */ 257 /* Force a stop */
240 logf(" pcm_play_dma_stop"); 258 logf(" pcm_play_dma_stop");
241 pcm_play_dma_stop(); 259 pcm_play_dma_stop();
242 pcm_play_dma_stopped_callback(); 260 pcm_play_stopped();
243} 261}
244 262
245void pcm_play_data(pcm_more_callback_type get_more, 263void pcm_play_data(pcm_play_callback_type get_more,
246 unsigned char *start, size_t size) 264 unsigned char *start, size_t size)
247{ 265{
248 logf("pcm_play_data"); 266 logf("pcm_play_data");
@@ -257,6 +275,29 @@ void pcm_play_data(pcm_more_callback_type get_more,
257 pcm_play_unlock(); 275 pcm_play_unlock();
258} 276}
259 277
278void pcm_play_get_more_callback(void **start, size_t *size)
279{
280 pcm_play_callback_type get_more = pcm_callback_for_more;
281
282 *size = 0;
283
284 if (get_more && start)
285 {
286 /* Call registered callback */
287 get_more((unsigned char **)start, size);
288
289 *start = (void *)(((uintptr_t)*start + 3) & ~3);
290 *size &= ~3;
291
292 if (*start && *size)
293 return;
294 }
295
296 /* Error, callback missing or no more DMA to do */
297 pcm_play_dma_stop();
298 pcm_play_stopped();
299}
300
260void pcm_play_pause(bool play) 301void pcm_play_pause(bool play)
261{ 302{
262 logf("pcm_play_pause: %s", play ? "play" : "pause"); 303 logf("pcm_play_pause: %s", play ? "play" : "pause");
@@ -302,7 +343,7 @@ void pcm_play_stop(void)
302 { 343 {
303 logf(" pcm_play_dma_stop"); 344 logf(" pcm_play_dma_stop");
304 pcm_play_dma_stop(); 345 pcm_play_dma_stop();
305 pcm_play_dma_stopped_callback(); 346 pcm_play_stopped();
306 } 347 }
307 else 348 else
308 { 349 {
@@ -312,13 +353,6 @@ void pcm_play_stop(void)
312 pcm_play_unlock(); 353 pcm_play_unlock();
313} 354}
314 355
315void pcm_play_dma_stopped_callback(void)
316{
317 pcm_callback_for_more = NULL;
318 pcm_paused = false;
319 pcm_playing = false;
320}
321
322/**/ 356/**/
323 357
324/* set frequency next frequency used by the audio hardware - 358/* set frequency next frequency used by the audio hardware -
@@ -350,27 +384,24 @@ void pcm_apply_settings(void)
350 } 384 }
351} 385}
352 386
353bool pcm_is_playing(void)
354{
355 return pcm_playing;
356}
357
358bool pcm_is_paused(void)
359{
360 return pcm_paused;
361}
362
363#ifdef HAVE_RECORDING 387#ifdef HAVE_RECORDING
364/** Low level pcm recording apis **/ 388/** Low level pcm recording apis **/
365 389
366/* Next start for recording peaks */ 390/* Next start for recording peaks */
367static const void * volatile pcm_rec_peak_addr SHAREDBSS_ATTR = NULL; 391static const void * volatile pcm_rec_peak_addr SHAREDBSS_ATTR = NULL;
368/* the registered callback function for when more data is available */ 392/* the registered callback function for when more data is available */
369volatile pcm_more_callback_type2 393static volatile pcm_rec_callback_type
370 pcm_callback_more_ready SHAREDBSS_ATTR = NULL; 394 pcm_callback_more_ready SHAREDBSS_ATTR = NULL;
371/* DMA transfer in is currently active */ 395/* DMA transfer in is currently active */
372volatile bool pcm_recording SHAREDBSS_ATTR = false; 396volatile bool pcm_recording SHAREDBSS_ATTR = false;
373 397
398/* Called internally by functions to reset the state */
399static void pcm_recording_stopped(void)
400{
401 pcm_recording = false;
402 pcm_callback_more_ready = NULL;
403}
404
374/** 405/**
375 * Return recording peaks - From the end of the last peak up to 406 * Return recording peaks - From the end of the last peak up to
376 * current write position. 407 * current write position.
@@ -410,10 +441,16 @@ void pcm_calculate_rec_peaks(int *left, int *right)
410 *right = peaks[1]; 441 *right = peaks[1];
411} /* pcm_calculate_rec_peaks */ 442} /* pcm_calculate_rec_peaks */
412 443
444bool pcm_is_recording(void)
445{
446 return pcm_recording;
447}
448
413/**************************************************************************** 449/****************************************************************************
414 * Functions that do not require targeted implementation but only a targeted 450 * Functions that do not require targeted implementation but only a targeted
415 * interface 451 * interface
416 */ 452 */
453
417void pcm_init_recording(void) 454void pcm_init_recording(void)
418{ 455{
419 logf("pcm_init_recording"); 456 logf("pcm_init_recording");
@@ -424,7 +461,7 @@ void pcm_init_recording(void)
424 pcm_rec_lock(); 461 pcm_rec_lock();
425 462
426 logf(" pcm_rec_dma_init"); 463 logf(" pcm_rec_dma_init");
427 pcm_rec_dma_stopped_callback(); 464 pcm_recording_stopped();
428 pcm_rec_dma_init(); 465 pcm_rec_dma_init();
429 466
430 pcm_rec_unlock(); 467 pcm_rec_unlock();
@@ -440,7 +477,7 @@ void pcm_close_recording(void)
440 { 477 {
441 logf(" pcm_rec_dma_stop"); 478 logf(" pcm_rec_dma_stop");
442 pcm_rec_dma_stop(); 479 pcm_rec_dma_stop();
443 pcm_rec_dma_stopped_callback(); 480 pcm_recording_stopped();
444 } 481 }
445 482
446 logf(" pcm_rec_dma_close"); 483 logf(" pcm_rec_dma_close");
@@ -449,7 +486,7 @@ void pcm_close_recording(void)
449 pcm_rec_unlock(); 486 pcm_rec_unlock();
450} 487}
451 488
452void pcm_record_data(pcm_more_callback_type2 more_ready, 489void pcm_record_data(pcm_rec_callback_type more_ready,
453 void *start, size_t size) 490 void *start, size_t size)
454{ 491{
455 logf("pcm_record_data"); 492 logf("pcm_record_data");
@@ -493,43 +530,40 @@ void pcm_stop_recording(void)
493 { 530 {
494 logf(" pcm_rec_dma_stop"); 531 logf(" pcm_rec_dma_stop");
495 pcm_rec_dma_stop(); 532 pcm_rec_dma_stop();
496 pcm_rec_dma_stopped_callback(); 533 pcm_recording_stopped();
497 } 534 }
498 535
499 pcm_rec_unlock(); 536 pcm_rec_unlock();
500} /* pcm_stop_recording */ 537} /* pcm_stop_recording */
501 538
502void pcm_record_more(void *start, size_t size) 539void pcm_rec_more_ready_callback(int status, void **start, size_t *size)
503{ 540{
504 start = (void *)(((uintptr_t)start + 3) & ~3); 541 pcm_rec_callback_type have_more = pcm_callback_more_ready;
505 size = size & ~3;
506
507 if (!size)
508 {
509 pcm_rec_dma_stop();
510 pcm_rec_dma_stopped_callback();
511 return;
512 }
513 542
514#ifdef HAVE_PCM_REC_DMA_ADDRESS 543 *size = 0;
515 /* Need a physical DMA address translation, if not already physical. */
516 pcm_rec_peak_addr = pcm_dma_addr(start);
517#else
518 pcm_rec_peak_addr = start;
519#endif
520 544
521 pcm_rec_dma_record_more(start, size); 545 if (have_more && start)
522} 546 {
547 have_more(status, start, size);
548 *start = (void *)(((uintptr_t)*start + 3) & ~3);
549 *size &= ~3;
523 550
524bool pcm_is_recording(void) 551 if (*start && *size)
525{ 552 {
526 return pcm_recording; 553 #ifdef HAVE_PCM_REC_DMA_ADDRESS
527} 554 /* Need a physical DMA address translation, if not already
555 * physical. */
556 pcm_rec_peak_addr = pcm_dma_addr(*start);
557 #else
558 pcm_rec_peak_addr = *start;
559 #endif
560 return;
561 }
562 }
528 563
529void pcm_rec_dma_stopped_callback(void) 564 /* Error, callback missing or no more DMA to do */
530{ 565 pcm_rec_dma_stop();
531 pcm_recording = false; 566 pcm_recording_stopped();
532 pcm_callback_more_ready = NULL;
533} 567}
534 568
535#endif /* HAVE_RECORDING */ 569#endif /* HAVE_RECORDING */
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c
index cefca0fbe5..a2e3cfbf9f 100644
--- a/firmware/target/arm/as3525/pcm-as3525.c
+++ b/firmware/target/arm/as3525/pcm-as3525.c
@@ -74,18 +74,13 @@ static void dma_callback(void)
74{ 74{
75 if(!dma_size) 75 if(!dma_size)
76 { 76 {
77 register pcm_more_callback_type get_more = pcm_callback_for_more; 77 pcm_play_get_more_callback(&dma_start_addr, &dma_size);
78 if(get_more)
79 get_more(&dma_start_addr, &dma_size);
80 }
81 78
82 if(!dma_size) 79 if (!dma_size)
83 { 80 return;
84 pcm_play_dma_stop();
85 pcm_play_dma_stopped_callback();
86 } 81 }
87 else 82
88 play_start_pcm(); 83 play_start_pcm();
89} 84}
90 85
91void pcm_play_dma_start(const void *addr, size_t size) 86void pcm_play_dma_start(const void *addr, size_t size)
@@ -275,31 +270,19 @@ static void rec_dma_callback(void)
275 270
276 if(!rec_dma_size) 271 if(!rec_dma_size)
277 { 272 {
278 register pcm_more_callback_type2 more_ready = pcm_callback_more_ready; 273 pcm_rec_more_ready_callback(0, &rec_dma_start_addr, &rec_dma_size);
279 if (!more_ready || more_ready(0) < 0)
280 {
281 /* Finished recording */
282 pcm_rec_dma_stop();
283 pcm_rec_dma_stopped_callback();
284 return;
285 }
286 }
287
288 rec_dma_start();
289}
290
291 274
292void pcm_rec_dma_record_more(void *start, size_t size) 275 if(rec_dma_size != 0)
293{ 276 {
294 dump_dcache_range(start, size); 277 dump_dcache_range(rec_dma_start_addr, rec_dma_size);
295 rec_dma_start_addr = start;
296#if CONFIG_CPU == AS3525 278#if CONFIG_CPU == AS3525
297 mono_samples = AS3525_UNCACHED_ADDR(start); 279 mono_samples = AS3525_UNCACHED_ADDR(rec_dma_start_addr);
298#endif 280#endif
299 rec_dma_size = size; 281 rec_dma_start();
282 }
283 }
300} 284}
301 285
302
303void pcm_rec_dma_stop(void) 286void pcm_rec_dma_stop(void)
304{ 287{
305 dma_disable_channel(1); 288 dma_disable_channel(1);
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
index 02051fad90..2c65c70360 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
@@ -52,9 +52,9 @@ static struct dma_data dma_play_data =
52 52
53static void play_dma_callback(void) 53static void play_dma_callback(void)
54{ 54{
55 unsigned char *start; 55 void *start;
56 size_t size = 0; 56 size_t size;
57 pcm_more_callback_type get_more = pcm_callback_for_more; 57 bool rror;
58 58
59 if (dma_play_data.locked != 0) 59 if (dma_play_data.locked != 0)
60 { 60 {
@@ -63,28 +63,20 @@ static void play_dma_callback(void)
63 return; 63 return;
64 } 64 }
65 65
66 if (dma_play_bd.mode.status & BD_RROR) 66 rror = dma_play_bd.mode.status & BD_RROR;
67 { 67
68 /* Stop on error */ 68 pcm_play_get_more_callback(rror ? NULL : &start, &size);
69 } 69
70 else if (get_more != NULL && (get_more(&start, &size), size != 0)) 70 if (size == 0)
71 {
72 start = (void*)(((unsigned long)start + 3) & ~3);
73 size &= ~3;
74
75 /* Flush any pending cache writes */
76 clean_dcache_range(start, size);
77 dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start);
78 dma_play_bd.mode.count = size;
79 dma_play_bd.mode.command = TRANSFER_16BIT;
80 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
81 sdma_channel_run(DMA_PLAY_CH_NUM);
82 return; 71 return;
83 }
84 72
85 /* Error, callback missing or no more DMA to do */ 73 /* Flush any pending cache writes */
86 pcm_play_dma_stop(); 74 clean_dcache_range(start, size);
87 pcm_play_dma_stopped_callback(); 75 dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start);
76 dma_play_bd.mode.count = size;
77 dma_play_bd.mode.command = TRANSFER_16BIT;
78 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
79 sdma_channel_run(DMA_PLAY_CH_NUM);
88} 80}
89 81
90void pcm_play_lock(void) 82void pcm_play_lock(void)
@@ -272,12 +264,6 @@ void pcm_play_dma_start(const void *addr, size_t size)
272 SSI_STCR2 &= ~SSI_STCR_TFEN0; 264 SSI_STCR2 &= ~SSI_STCR_TFEN0;
273 SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); 265 SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN);
274 266
275 addr = (void *)(((unsigned long)addr + 3) & ~3);
276 size &= ~3;
277
278 if (size <= 0)
279 return;
280
281 if (!sdma_channel_reset(DMA_PLAY_CH_NUM)) 267 if (!sdma_channel_reset(DMA_PLAY_CH_NUM))
282 return; 268 return;
283 269
@@ -383,8 +369,9 @@ static struct dma_data dma_rec_data =
383 369
384static void rec_dma_callback(void) 370static void rec_dma_callback(void)
385{ 371{
386 pcm_more_callback_type2 more_ready;
387 int status = 0; 372 int status = 0;
373 void *start;
374 size_t size;
388 375
389 if (dma_rec_data.locked != 0) 376 if (dma_rec_data.locked != 0)
390 { 377 {
@@ -395,17 +382,22 @@ static void rec_dma_callback(void)
395 if (dma_rec_bd.mode.status & BD_RROR) 382 if (dma_rec_bd.mode.status & BD_RROR)
396 status = DMA_REC_ERROR_DMA; 383 status = DMA_REC_ERROR_DMA;
397 384
398 more_ready = pcm_callback_more_ready; 385 pcm_rec_more_ready_callback(status, &start, &size);
399 386
400 if (more_ready != NULL && more_ready(status) >= 0) 387 if (size == 0)
401 {
402 sdma_channel_run(DMA_REC_CH_NUM);
403 return; 388 return;
404 }
405 389
406 /* Finished recording */ 390 /* Invalidate - buffer must be coherent */
407 pcm_rec_dma_stop(); 391 dump_dcache_range(start, size);
408 pcm_rec_dma_stopped_callback(); 392
393 start = (void *)addr_virt_to_phys((unsigned long)start);
394
395 dma_rec_bd.buf_addr = start;
396 dma_rec_bd.mode.count = size;
397 dma_rec_bd.mode.command = TRANSFER_16BIT;
398 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
399
400 sdma_channel_run(DMA_REC_CH_NUM);
409} 401}
410 402
411void pcm_rec_lock(void) 403void pcm_rec_lock(void)
@@ -432,19 +424,6 @@ void pcm_rec_unlock(void)
432 } 424 }
433} 425}
434 426
435void pcm_rec_dma_record_more(void *start, size_t size)
436{
437 /* Invalidate - buffer must be coherent */
438 dump_dcache_range(start, size);
439
440 start = (void *)addr_virt_to_phys((unsigned long)start);
441
442 dma_rec_bd.buf_addr = start;
443 dma_rec_bd.mode.count = size;
444 dma_rec_bd.mode.command = TRANSFER_16BIT;
445 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
446}
447
448void pcm_rec_dma_stop(void) 427void pcm_rec_dma_stop(void)
449{ 428{
450 /* Stop receiving data */ 429 /* Stop receiving data */
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index e0b603c81f..6289b4c730 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -115,7 +115,6 @@ void pcm_dma_apply_settings(void)
115/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */ 115/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
116void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void) 116void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
117{ 117{
118 register pcm_more_callback_type get_more;
119 register size_t size; 118 register size_t size;
120 119
121 DMA0_STATUS; /* Clear any pending interrupt */ 120 DMA0_STATUS; /* Clear any pending interrupt */
@@ -141,15 +140,12 @@ void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
141 } 140 }
142 141
143 /* Buffer empty. Try to get more. */ 142 /* Buffer empty. Try to get more. */
144 get_more = pcm_callback_for_more; 143 pcm_play_get_more_callback((void **)&dma_play_data.addr,
145 if (get_more) { 144 &dma_play_data.size);
146 get_more((unsigned char **)&dma_play_data.addr, &dma_play_data.size);
147 dma_play_data.addr = (dma_play_data.addr + 2) & ~3;
148 dma_play_data.size &= ~3;
149 }
150 145
151 if (dma_play_data.size == 0) { 146 if (dma_play_data.size == 0) {
152 break; 147 /* No more data */
148 return;
153 } 149 }
154 150
155 if (dma_play_data.addr < UNCACHED_BASE_ADDR) { 151 if (dma_play_data.addr < UNCACHED_BASE_ADDR) {
@@ -158,10 +154,6 @@ void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
158 cpucache_flush(); 154 cpucache_flush();
159 } 155 }
160 } 156 }
161
162 /* Callback missing or no more DMA to do */
163 pcm_play_dma_stop();
164 pcm_play_dma_stopped_callback();
165} 157}
166#else 158#else
167/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by 159/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by
@@ -247,28 +239,16 @@ void fiq_playback(void)
247#endif 239#endif
248 240
249 ".more_data: \n" 241 ".more_data: \n"
250 "ldr r2, =pcm_callback_for_more \n" 242 "ldr r2, =pcm_play_get_more_callback \n"
251 "ldr r2, [r2] \n" /* get callback address */
252 "cmp r2, #0 \n" /* check for null pointer */
253 "beq .stop \n" /* callback removed, stop */
254 "stmia r11, { r8-r9 } \n" /* save internal copies of variables back */
255 "mov r0, r11 \n" /* r0 = &p */ 243 "mov r0, r11 \n" /* r0 = &p */
256 "add r1, r11, #4 \n" /* r1 = &size */ 244 "add r1, r11, #4 \n" /* r1 = &size */
257 "mov lr, pc \n" /* call pcm_callback_for_more */ 245 "mov lr, pc \n" /* call pcm_play_get_more_callback */
258 "bx r2 \n" 246 "bx r2 \n"
259 "ldmia r11, { r8-r9 } \n" /* reload p and size */ 247 "ldmia r11, { r8-r9 } \n" /* load new p and size */
260 "cmp r9, #0 \n" /* did we actually get more data? */ 248 "cmp r9, #0 \n"
261 "bne .check_fifo \n" 249 "bne .check_fifo \n" /* size != 0? refill */
262 250
263 ".stop: \n" /* call termination routines */ 251 ".exit: \n" /* (r9=0 if stopping, look above) */
264 "ldr r12, =pcm_play_dma_stop \n"
265 "mov lr, pc \n"
266 "bx r12 \n"
267 "ldr r12, =pcm_play_dma_stopped_callback \n"
268 "mov lr, pc \n"
269 "bx r12 \n"
270
271 ".exit: \n" /* (r8=0 if stopping, look above) */
272 "stmia r11, { r8-r9 } \n" /* save p and size */ 252 "stmia r11, { r8-r9 } \n" /* save p and size */
273 "ldmfd sp!, { r0-r3, lr } \n" 253 "ldmfd sp!, { r0-r3, lr } \n"
274 "subs pc, lr, #4 \n" /* FIQ specific return sequence */ 254 "subs pc, lr, #4 \n" /* FIQ specific return sequence */
@@ -284,8 +264,6 @@ void fiq_playback(void) __attribute__((interrupt ("FIQ"))) ICODE_ATTR;
284/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */ 264/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
285void fiq_playback(void) 265void fiq_playback(void)
286{ 266{
287 register pcm_more_callback_type get_more;
288
289#if CONFIG_CPU == PP5002 267#if CONFIG_CPU == PP5002
290 inl(0xcf001040); 268 inl(0xcf001040);
291#endif 269#endif
@@ -305,16 +283,11 @@ void fiq_playback(void)
305 } 283 }
306 284
307 /* p is empty, get some more data */ 285 /* p is empty, get some more data */
308 get_more = pcm_callback_for_more; 286 pcm_play_get_more_callback((void **)&dma_play_data.addr,
309 if (get_more) { 287 &dma_play_data.size);
310 get_more((unsigned char**)&dma_play_data.addr,
311 &dma_play_data.size);
312 }
313 } while (dma_play_data.size); 288 } while (dma_play_data.size);
314 289
315 /* No more data, so disable the FIFO/interrupt */ 290 /* No more data */
316 pcm_play_dma_stop();
317 pcm_play_dma_stopped_callback();
318} 291}
319#endif /* ASM / C selection */ 292#endif /* ASM / C selection */
320#endif /* CPU_PP502x */ 293#endif /* CPU_PP502x */
@@ -589,7 +562,6 @@ void fiq_record(void) ICODE_ATTR __attribute__((interrupt ("FIQ")));
589#if defined(SANSA_C200) || defined(SANSA_E200) 562#if defined(SANSA_C200) || defined(SANSA_E200)
590void fiq_record(void) 563void fiq_record(void)
591{ 564{
592 register pcm_more_callback_type2 more_ready;
593 register int32_t value; 565 register int32_t value;
594 566
595 if (audio_channels == 2) { 567 if (audio_channels == 2) {
@@ -648,20 +620,13 @@ void fiq_record(void)
648 } 620 }
649 } 621 }
650 622
651 more_ready = pcm_callback_more_ready; 623 pcm_rec_more_ready_callback(0, (void *)&dma_rec_data.addr,
652 624 &dma_rec_data.size);
653 if (more_ready == NULL || more_ready(0) < 0) {
654 /* Finished recording */
655 pcm_rec_dma_stop();
656 pcm_rec_dma_stopped_callback();
657 }
658} 625}
659 626
660#else 627#else
661void fiq_record(void) 628void fiq_record(void)
662{ 629{
663 register pcm_more_callback_type2 more_ready;
664
665 while (dma_rec_data.size > 0) { 630 while (dma_rec_data.size > 0) {
666 if (IIS_RX_FULL_COUNT < 2) { 631 if (IIS_RX_FULL_COUNT < 2) {
667 return; 632 return;
@@ -676,24 +641,12 @@ void fiq_record(void)
676 dma_rec_data.size -= 4; 641 dma_rec_data.size -= 4;
677 } 642 }
678 643
679 more_ready = pcm_callback_more_ready; 644 pcm_rec_more_ready_callback(0, (void *)&dma_rec_data.addr,
680 645 &dma_rec_data.size);
681 if (more_ready == NULL || more_ready(0) < 0) {
682 /* Finished recording */
683 pcm_rec_dma_stop();
684 pcm_rec_dma_stopped_callback();
685 }
686} 646}
687 647
688#endif /* SANSA_E200 */ 648#endif /* SANSA_E200 */
689 649
690/* Continue transferring data in */
691void pcm_rec_dma_record_more(void *start, size_t size)
692{
693 dma_rec_data.addr = (unsigned long)start; /* Start of RX buffer */
694 dma_rec_data.size = size; /* Bytes to transfer */
695}
696
697void pcm_rec_dma_stop(void) 650void pcm_rec_dma_stop(void)
698{ 651{
699 /* disable interrupt */ 652 /* disable interrupt */
diff --git a/firmware/target/arm/pcm-telechips.c b/firmware/target/arm/pcm-telechips.c
index 3ce038ffcd..d718ca38ac 100644
--- a/firmware/target/arm/pcm-telechips.c
+++ b/firmware/target/arm/pcm-telechips.c
@@ -233,12 +233,6 @@ const void * pcm_rec_dma_get_peak_buffer(void)
233{ 233{
234 return NULL; 234 return NULL;
235} 235}
236
237void pcm_record_more(void *start, size_t size)
238{
239 (void) start;
240 (void) size;
241}
242#endif 236#endif
243 237
244#if defined(CPU_TCC77X) || defined(CPU_TCC780X) 238#if defined(CPU_TCC77X) || defined(CPU_TCC780X)
@@ -289,21 +283,14 @@ void fiq_handler(void)
289 283
290 ".more_data: \n" 284 ".more_data: \n"
291 "stmfd sp!, { r0-r3, lr } \n" /* stack scratch regs and lr */ 285 "stmfd sp!, { r0-r3, lr } \n" /* stack scratch regs and lr */
292 "ldr r2, =pcm_callback_for_more \n" 286 "ldr r2, =pcm_play_get_more_callback \n"
293 "ldr r2, [r2] \n" /* get callback address */ 287 "mov r0, r11 \n" /* r0 = &p */
294 "cmp r2, #0 \n" /* check for null pointer */ 288 "add r1, r11, #4 \n" /* r1 = &size */
295 "movne r0, r11 \n" /* r0 = &p */ 289 "blx r2 \n" /* call pcm_play_get_more_callback */
296 "addne r1, r11, #4 \n" /* r1 = &size */ 290 "ldmia r11, { r8-r9 } \n" /* load new p and size */
297 "blxne r2 \n" /* call pcm_callback_for_more */ 291 "cmp r9, #0x10 \n" /* did we actually get enough data? */
298 "ldmia r11, { r8-r9 } \n" /* reload p and size */
299 "cmp r9, #0x10 \n" /* did we actually get more data? */
300 "ldmgefd sp!, { r0-r3, lr } \n"
301 "bge .fill_fifo \n" /* yes: fill the fifo */
302 "ldr r12, =pcm_play_dma_stop \n"
303 "blx r12 \n" /* no: stop playback */
304 "ldr r12, =pcm_play_dma_stopped_callback \n"
305 "blx r12 \n"
306 "ldmfd sp!, { r0-r3, lr } \n" 292 "ldmfd sp!, { r0-r3, lr } \n"
293 "bpl .fill_fifo \n" /* not stop and enough? refill */
307 "b .exit \n" 294 "b .exit \n"
308 ".ltorg \n" 295 ".ltorg \n"
309 ); 296 );
@@ -315,17 +302,11 @@ void fiq_handler(void)
315 asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */ 302 asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */
316 "sub sp, sp, #8 \n"); /* Reserve stack */ 303 "sub sp, sp, #8 \n"); /* Reserve stack */
317 304
318 register pcm_more_callback_type get_more;
319
320 if (dma_play_data.size < 16) 305 if (dma_play_data.size < 16)
321 { 306 {
322 /* p is empty, get some more data */ 307 /* p is empty, get some more data */
323 get_more = pcm_callback_for_more; 308 pcm_play_get_more_callback((void**)&dma_play_data.p,
324 if (get_more) 309 &dma_play_data.size);
325 {
326 get_more((unsigned char**)&dma_play_data.p,
327 &dma_play_data.size);
328 }
329 } 310 }
330 311
331 if (dma_play_data.size >= 16) 312 if (dma_play_data.size >= 16)
@@ -341,12 +322,6 @@ void fiq_handler(void)
341 322
342 dma_play_data.size -= 16; 323 dma_play_data.size -= 16;
343 } 324 }
344 else
345 {
346 /* No more data, so disable the FIFO/interrupt */
347 pcm_play_dma_stop();
348 pcm_play_dma_stopped_callback();
349 }
350 325
351 /* Clear FIQ status */ 326 /* Clear FIQ status */
352 CREQ = DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK; 327 CREQ = DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK;
diff --git a/firmware/target/arm/pnx0101/pcm-pnx0101.c b/firmware/target/arm/pnx0101/pcm-pnx0101.c
index fe1e05b79a..9d4ffbd773 100644
--- a/firmware/target/arm/pnx0101/pcm-pnx0101.c
+++ b/firmware/target/arm/pnx0101/pcm-pnx0101.c
@@ -104,13 +104,10 @@ static inline void fill_dma_buf(int offset)
104 p = tmp_p; 104 p = tmp_p;
105 if (l >= lend) 105 if (l >= lend)
106 return; 106 return;
107 else if (pcm_callback_for_more) 107
108 pcm_callback_for_more((unsigned char**)&p, 108 pcm_play_get_more_callback((void**)&p, &p_size);
109 &p_size);
110 } 109 }
111 while (p_size); 110 while (p_size);
112
113 pcm_play_dma_stopped_callback();
114 } 111 }
115 112
116 if (l < lend) 113 if (l < lend)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
index bb1b2d9eaa..e9f55479c7 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
@@ -214,35 +214,27 @@ void pcm_play_dma_pause(bool pause)
214 214
215void fiq_handler(void) 215void fiq_handler(void)
216{ 216{
217 static unsigned char *start; 217 static void *start;
218 static size_t size; 218 static size_t size;
219 register pcm_more_callback_type get_more; /* No stack for this */
220 219
221 /* clear any pending interrupt */ 220 /* clear any pending interrupt */
222 SRCPND = DMA2_MASK; 221 SRCPND = DMA2_MASK;
223 222
224 /* Buffer empty. Try to get more. */ 223 /* Buffer empty. Try to get more. */
225 get_more = pcm_callback_for_more; 224 pcm_play_get_more_callback(&start, &size);
226 size = 0;
227 225
228 if (get_more == NULL || (get_more(&start, &size), size == 0)) 226 if (size == 0)
229 { 227 return;
230 /* Callback missing or no more DMA to do */
231 pcm_play_dma_stop();
232 pcm_play_dma_stopped_callback();
233 }
234 else
235 {
236 /* Flush any pending cache writes */
237 clean_dcache_range(start, size);
238 228
239 /* set the new DMA values */ 229 /* Flush any pending cache writes */
240 DCON2 = DMA_CONTROL_SETUP | (size >> 1); 230 clean_dcache_range(start, size);
241 DISRC2 = (unsigned int)start + 0x30000000;
242 231
243 /* Re-Activate the channel */ 232 /* set the new DMA values */
244 DMASKTRIG2 = 0x2; 233 DCON2 = DMA_CONTROL_SETUP | (size >> 1);
245 } 234 DISRC2 = (unsigned int)start + 0x30000000;
235
236 /* Re-Activate the channel */
237 DMASKTRIG2 = 0x2;
246} 238}
247 239
248size_t pcm_get_bytes_waiting(void) 240size_t pcm_get_bytes_waiting(void)
diff --git a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
index 486a235614..30db29c42c 100644
--- a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
+++ b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
@@ -254,35 +254,27 @@ void pcm_play_dma_pause(bool pause)
254 254
255void fiq_handler(void) 255void fiq_handler(void)
256{ 256{
257 static unsigned char *start; 257 static void *start;
258 static size_t size; 258 static size_t size;
259 register pcm_more_callback_type get_more; /* No stack for this */
260 259
261 /* clear any pending interrupt */ 260 /* clear any pending interrupt */
262 SRCPND = DMA2_MASK; 261 SRCPND = DMA2_MASK;
263 262
264 /* Buffer empty. Try to get more. */ 263 /* Buffer empty. Try to get more. */
265 get_more = pcm_callback_for_more; 264 pcm_play_get_more_callback(&start, &size);
266 size = 0;
267 265
268 if (get_more == NULL || (get_more(&start, &size), size == 0)) 266 if (size == 0)
269 { 267 return;
270 /* Callback missing or no more DMA to do */
271 pcm_play_dma_stop();
272 pcm_play_dma_stopped_callback();
273 }
274 else
275 {
276 /* Flush any pending cache writes */
277 clean_dcache_range(start, size);
278 268
279 /* set the new DMA values */ 269 /* Flush any pending cache writes */
280 DCON2 = DMA_CONTROL_SETUP | (size >> 1); 270 clean_dcache_range(start, size);
281 DISRC2 = (unsigned int)start + 0x30000000;
282 271
283 /* Re-Activate the channel */ 272 /* set the new DMA values */
284 DMASKTRIG2 = 0x2; 273 DCON2 = DMA_CONTROL_SETUP | (size >> 1);
285 } 274 DISRC2 = (unsigned int)start + 0x30000000;
275
276 /* Re-Activate the channel */
277 DMASKTRIG2 = 0x2;
286} 278}
287 279
288size_t pcm_get_bytes_waiting(void) 280size_t pcm_get_bytes_waiting(void)
diff --git a/firmware/target/arm/s5l8700/pcm-s5l8700.c b/firmware/target/arm/s5l8700/pcm-s5l8700.c
index 7798f41d11..4d24b327af 100644
--- a/firmware/target/arm/s5l8700/pcm-s5l8700.c
+++ b/firmware/target/arm/s5l8700/pcm-s5l8700.c
@@ -102,11 +102,11 @@ static const void* dma_callback(void)
102{ 102{
103 if (dmamode) 103 if (dmamode)
104 { 104 {
105 unsigned char *dma_start_addr; 105 void *dma_start_addr;
106 register pcm_more_callback_type get_more = pcm_callback_for_more; 106 pcm_play_get_more_callback(&dma_start_addr, &nextsize);
107 if (get_more) 107
108 if (nextsize != 0)
108 { 109 {
109 get_more(&dma_start_addr, &nextsize);
110 if (nextsize >= 4096) 110 if (nextsize >= 4096)
111 { 111 {
112 dblbufsize = (nextsize >> 4) & ~3; 112 dblbufsize = (nextsize >> 4) & ~3;
@@ -148,7 +148,6 @@ void fiq_handler(void)
148 "mov r10, #0x00000400 \n" /* INT_DMA */ 148 "mov r10, #0x00000400 \n" /* INT_DMA */
149 "str r10, [r11] \n" /* ACK FIQ */ 149 "str r10, [r11] \n" /* ACK FIQ */
150 "stmfd sp!, {r0-r3,lr} \n" 150 "stmfd sp!, {r0-r3,lr} \n"
151 "ldreq r0, =pcm_play_dma_stopped_callback \n"
152 "ldrne r0, =dma_callback \n" 151 "ldrne r0, =dma_callback \n"
153 "mov lr, pc \n" 152 "mov lr, pc \n"
154 "bx r0 \n" 153 "bx r0 \n"
@@ -225,13 +224,6 @@ void pcm_play_dma_start(const void *addr_in, size_t size)
225#endif 224#endif
226 225
227 /* S3: DMA channel 0 on */ 226 /* S3: DMA channel 0 on */
228 if (!size)
229 {
230 register pcm_more_callback_type get_more = pcm_callback_for_more;
231 if (get_more) get_more(&addr, &size);
232 else return; /* Nothing to play!? */
233 }
234 if (!size) return; /* Nothing to play!? */
235 clean_dcache(); 227 clean_dcache();
236 if (size >= 4096) 228 if (size >= 4096)
237 { 229 {
@@ -367,12 +359,6 @@ void pcm_rec_unlock(void)
367{ 359{
368} 360}
369 361
370void pcm_rec_dma_record_more(void *start, size_t size)
371{
372 (void)start;
373 (void)size;
374}
375
376void pcm_rec_dma_stop(void) 362void pcm_rec_dma_stop(void)
377{ 363{
378} 364}
diff --git a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
index ab3ceba0f3..d7d8f92a0c 100644
--- a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
+++ b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
@@ -132,8 +132,6 @@ char buffer[80];
132void DSPHINT(void) __attribute__ ((section(".icode"))); 132void DSPHINT(void) __attribute__ ((section(".icode")));
133void DSPHINT(void) 133void DSPHINT(void)
134{ 134{
135 register pcm_more_callback_type get_more; /* No stack for this */
136
137 unsigned int i; 135 unsigned int i;
138 136
139 IO_INTC_FIQ0 = 1 << 11; 137 IO_INTC_FIQ0 = 1 << 11;
@@ -152,16 +150,9 @@ void DSPHINT(void)
152 150
153 case MSG_REFILL: 151 case MSG_REFILL:
154 /* Buffer empty. Try to get more. */ 152 /* Buffer empty. Try to get more. */
155 get_more = pcm_callback_for_more; 153 pcm_play_get_more_callback(&start, &size);
156 size = 0; 154
157 155 if (size != 0)
158 if (get_more == NULL || (get_more(&start, &size), size == 0))
159 {
160 /* Callback missing or no more DMA to do */
161 pcm_play_dma_stop();
162 pcm_play_dma_stopped_callback();
163 }
164
165 { 156 {
166 unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START; 157 unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START;
167 /* Flush any pending cache writes */ 158 /* Flush any pending cache writes */
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
index f9c0764d64..06f17d1170 100644
--- a/firmware/target/coldfire/pcm-coldfire.c
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -288,13 +288,14 @@ void DMA0(void) __attribute__ ((interrupt_handler, section(".icode")));
288void DMA0(void) 288void DMA0(void)
289{ 289{
290 unsigned long res = DSR0; 290 unsigned long res = DSR0;
291 void *start;
292 size_t size;
291 293
292 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */ 294 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
293 DSR0 = 1; /* Clear interrupt and errors */ 295 DSR0 = 1; /* Clear interrupt and errors */
294 296
295 if (res & 0x70) 297 if (res & 0x70)
296 { 298 {
297 /* Stop on error */
298 logf("DMA0 err: %02x", res); 299 logf("DMA0 err: %02x", res);
299#if 0 300#if 0
300 logf(" SAR0: %08x", SAR0); 301 logf(" SAR0: %08x", SAR0);
@@ -303,32 +304,17 @@ void DMA0(void)
303 logf(" DCR0: %08x", DCR0); 304 logf(" DCR0: %08x", DCR0);
304#endif 305#endif
305 } 306 }
306 else 307
308 /* Force stop on error */
309 pcm_play_get_more_callback((res & 0x70) ? NULL : &start, &size);
310
311 if (size != 0)
307 { 312 {
308 pcm_more_callback_type get_more = pcm_callback_for_more; 313 SAR0 = (unsigned long)start; /* Source address */
309 unsigned char *start; 314 BCR0 = size; /* Bytes to transfer */
310 size_t size = 0; 315 or_l(DMA_EEXT | DMA_INT, &DCR0); /* per request and int ON */
311
312 if (get_more)
313 get_more(&start, &size);
314
315 start = (unsigned char *)(((long)start + 3) & ~3);
316 size &= ~3;
317
318 if (size > 0)
319 {
320 SAR0 = (unsigned long)start; /* Source address */
321 BCR0 = size; /* Bytes to transfer */
322 or_l(DMA_EEXT | DMA_INT, &DCR0); /* per request and int ON */
323 return;
324 }
325 /* Finished playing */
326 } 316 }
327 317 /* else inished playing */
328 /* Stop interrupt and futher transfers */
329 pcm_play_dma_stop();
330 /* Inform PCM that we're done */
331 pcm_play_dma_stopped_callback();
332} /* DMA0 */ 318} /* DMA0 */
333 319
334const void * pcm_play_dma_get_peak_buffer(int *count) 320const void * pcm_play_dma_get_peak_buffer(int *count)
@@ -436,7 +422,8 @@ void DMA1(void)
436{ 422{
437 unsigned long res = DSR1; 423 unsigned long res = DSR1;
438 int status = 0; 424 int status = 0;
439 pcm_more_callback_type2 more_ready; 425 void *start;
426 size_t size;
440 427
441 and_l(~(DMA_EEXT | DMA_INT), &DCR1); /* per request and int OFF */ 428 and_l(~(DMA_EEXT | DMA_INT), &DCR1); /* per request and int OFF */
442 DSR1 = 1; /* Clear interrupt and errors */ 429 DSR1 = 1; /* Clear interrupt and errors */
@@ -465,25 +452,17 @@ void DMA1(void)
465 } 452 }
466#endif 453#endif
467 454
468 more_ready = pcm_callback_more_ready; 455 /* Inform PCM we have more data (or error) */
469 456 pcm_rec_more_ready_callback(status, &start, &size);
470 if (more_ready != NULL && more_ready(status) >= 0)
471 return;
472 457
473 /* Finished recording */ 458 if (size != 0)
474 pcm_rec_dma_stop(); 459 {
475 /* Inform PCM that we're done */ 460 DAR1 = (unsigned long)start; /* Destination address */
476 pcm_rec_dma_stopped_callback(); 461 BCR1 = (unsigned long)size; /* Bytes to transfer */
462 or_l(DMA_EEXT | DMA_INT, &DCR1); /* per request and int ON */
463 }
477} /* DMA1 */ 464} /* DMA1 */
478 465
479/* Continue transferring data in - call from interrupt callback */
480void pcm_rec_dma_record_more(void *start, size_t size)
481{
482 DAR1 = (unsigned long)start; /* Destination address */
483 BCR1 = (unsigned long)size; /* Bytes to transfer */
484 or_l(DMA_EEXT | DMA_INT, &DCR1); /* per request and int ON */
485} /* pcm_record_more */
486
487const void * pcm_rec_dma_get_peak_buffer(void) 466const void * pcm_rec_dma_get_peak_buffer(void)
488{ 467{
489 return (void *)(DAR1 & ~3); 468 return (void *)(DAR1 & ~3);
diff --git a/firmware/target/hosted/sdl/pcm-sdl.c b/firmware/target/hosted/sdl/pcm-sdl.c
index ee92fa208d..03e6e1336c 100644
--- a/firmware/target/hosted/sdl/pcm-sdl.c
+++ b/firmware/target/hosted/sdl/pcm-sdl.c
@@ -228,15 +228,9 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
228 228
229 /* Audio card wants more? Get some more then. */ 229 /* Audio card wants more? Get some more then. */
230 while (len > 0) { 230 while (len > 0) {
231 if ((ssize_t)pcm_data_size <= 0) { 231 pcm_play_get_more_callback(&pcm_data, &pcm_data_size);
232 pcm_data_size = 0;
233
234 if (pcm_callback_for_more)
235 pcm_callback_for_more(&pcm_data, &pcm_data_size);
236 }
237
238 if (pcm_data_size > 0) {
239 start: 232 start:
233 if (pcm_data_size != 0) {
240 udata->num_in = pcm_data_size / pcm_sample_bytes; 234 udata->num_in = pcm_data_size / pcm_sample_bytes;
241 udata->num_out = len / pcm_sample_bytes; 235 udata->num_out = len / pcm_sample_bytes;
242 236
@@ -251,8 +245,6 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
251 len -= udata->num_out; 245 len -= udata->num_out;
252 } else { 246 } else {
253 DEBUGF("sdl_audio_callback: No Data.\n"); 247 DEBUGF("sdl_audio_callback: No Data.\n");
254 pcm_play_dma_stop();
255 pcm_play_dma_stopped_callback();
256 break; 248 break;
257 } 249 }
258 } 250 }
@@ -292,12 +284,6 @@ void pcm_rec_dma_stop(void)
292{ 284{
293} 285}
294 286
295void pcm_rec_dma_record_more(void *start, size_t size)
296{
297 (void)start;
298 (void)size;
299}
300
301unsigned long pcm_rec_status(void) 287unsigned long pcm_rec_status(void)
302{ 288{
303 return 0; 289 return 0;
diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
index 993f70bad8..4cf43471eb 100644
--- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
@@ -100,23 +100,16 @@ static inline void set_dma(const void *addr, size_t size)
100 100
101static inline void play_dma_callback(void) 101static inline void play_dma_callback(void)
102{ 102{
103 unsigned char *start = NULL; 103 unsigned char *start;
104 size_t size = 0; 104 size_t size;
105 105
106 if(pcm_callback_for_more) 106 pcm_play_get_more_callback(&start, &size);
107 pcm_callback_for_more(&start, &size);
108 107
109 if(LIKELY(size > 0 && start)) 108 if (size != 0)
110 { 109 {
111 set_dma(start, size); 110 set_dma(start, size);
112 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; 111 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN;
113 } 112 }
114 else
115 {
116 /* Error, callback missing or no more DMA to do */
117 pcm_play_dma_stop();
118 pcm_play_dma_stopped_callback();
119 }
120} 113}
121 114
122void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) __attribute__ ((section(".icode"))); 115void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) __attribute__ ((section(".icode")));
@@ -292,10 +285,4 @@ const void * pcm_rec_dma_get_peak_buffer(void)
292{ 285{
293 return NULL; 286 return NULL;
294} 287}
295
296void pcm_rec_dma_record_more(void *start, size_t size)
297{
298 (void) start;
299 (void) size;
300}
301#endif 288#endif