diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/enc_base.c | 46 | ||||
-rw-r--r-- | firmware/export/enc_base.h | 270 | ||||
-rw-r--r-- | firmware/export/general.h | 38 | ||||
-rw-r--r-- | firmware/export/pcm_sampr.h | 310 | ||||
-rw-r--r-- | firmware/general.c | 77 | ||||
-rw-r--r-- | firmware/pcm_sampr.c | 76 | ||||
-rw-r--r-- | firmware/target/coldfire/pcm-coldfire.c | 738 |
7 files changed, 1555 insertions, 0 deletions
diff --git a/firmware/enc_base.c b/firmware/enc_base.c new file mode 100644 index 0000000000..e346064fe2 --- /dev/null +++ b/firmware/enc_base.c | |||
@@ -0,0 +1,46 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "config.h" | ||
20 | #include "audio.h" | ||
21 | |||
22 | /** mp3_enc.codec **/ | ||
23 | |||
24 | /* These are in descending order rather than in MPEG frequency index | ||
25 | order */ | ||
26 | const unsigned long mp3_enc_sampr[MP3_ENC_NUM_SAMPR] = | ||
27 | { | ||
28 | 48000, 44100, 32000, /* MPEG 1 */ | ||
29 | 24000, 22050, 16000, /* MPEG 2 */ | ||
30 | #if 0 | ||
31 | 12000, 11025, 8000, /* MPEG 2.5 */ | ||
32 | #endif | ||
33 | }; | ||
34 | |||
35 | /* All bitrates used in the MPA L3 standard */ | ||
36 | const unsigned long mp3_enc_bitr[MP3_ENC_NUM_BITR] = | ||
37 | { | ||
38 | 8, 16, 24, 32, 40, 48, 56, 64, 80, | ||
39 | 96, 112, 128, 144, 160, 192, 224, 256, 320 | ||
40 | }; | ||
41 | |||
42 | /** wav_enc.codec **/ | ||
43 | |||
44 | /** wavpack_enc.codec **/ | ||
45 | |||
46 | /** public functions **/ | ||
diff --git a/firmware/export/enc_base.h b/firmware/export/enc_base.h new file mode 100644 index 0000000000..85101ac7fd --- /dev/null +++ b/firmware/export/enc_base.h | |||
@@ -0,0 +1,270 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Base declarations for working with software encoders | ||
11 | * | ||
12 | * Copyright (C) 2006 Michael Sevakis | ||
13 | * | ||
14 | * All files in this archive are subject to the GNU General Public License. | ||
15 | * See the file COPYING in the source tree root for full license agreement. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef ENC_BASE_H | ||
23 | #define ENC_BASE_H | ||
24 | |||
25 | /** encoder config structures **/ | ||
26 | |||
27 | /** mp3_enc.codec **/ | ||
28 | #define MP3_BITR_CAP_8 (1 << 0) | ||
29 | #define MP3_BITR_CAP_16 (1 << 1) | ||
30 | #define MP3_BITR_CAP_24 (1 << 2) | ||
31 | #define MP3_BITR_CAP_32 (1 << 3) | ||
32 | #define MP3_BITR_CAP_40 (1 << 4) | ||
33 | #define MP3_BITR_CAP_48 (1 << 5) | ||
34 | #define MP3_BITR_CAP_56 (1 << 6) | ||
35 | #define MP3_BITR_CAP_64 (1 << 7) | ||
36 | #define MP3_BITR_CAP_80 (1 << 8) | ||
37 | #define MP3_BITR_CAP_96 (1 << 9) | ||
38 | #define MP3_BITR_CAP_112 (1 << 10) | ||
39 | #define MP3_BITR_CAP_128 (1 << 11) | ||
40 | #define MP3_BITR_CAP_144 (1 << 12) | ||
41 | #define MP3_BITR_CAP_160 (1 << 13) | ||
42 | #define MP3_BITR_CAP_192 (1 << 14) | ||
43 | #define MP3_BITR_CAP_224 (1 << 15) | ||
44 | #define MP3_BITR_CAP_256 (1 << 16) | ||
45 | #define MP3_BITR_CAP_320 (1 << 17) | ||
46 | #define MP3_ENC_NUM_BITR 18 | ||
47 | |||
48 | /* MPEG 1 */ | ||
49 | #define MPEG1_SAMPR_CAPS (SAMPR_CAP_32 | SAMPR_CAP_48 | SAMPR_CAP_44) | ||
50 | #define MPEG1_BITR_CAPS (MP3_BITR_CAP_32 | MP3_BITR_CAP_40 | MP3_BITR_CAP_48 | \ | ||
51 | MP3_BITR_CAP_56 | MP3_BITR_CAP_64 | MP3_BITR_CAP_80 | \ | ||
52 | MP3_BITR_CAP_96 | MP3_BITR_CAP_112 | MP3_BITR_CAP_128 | \ | ||
53 | MP3_BITR_CAP_160 | MP3_BITR_CAP_192 | MP3_BITR_CAP_224 | \ | ||
54 | MP3_BITR_CAP_256 | MP3_BITR_CAP_320) | ||
55 | |||
56 | /* MPEG 2 */ | ||
57 | #define MPEG2_SAMPR_CAPS (SAMPR_CAP_22 | SAMPR_CAP_24 | SAMPR_CAP_16) | ||
58 | #define MPEG2_BITR_CAPS (MP3_BITR_CAP_8 | MP3_BITR_CAP_16 | MP3_BITR_CAP_24 | \ | ||
59 | MP3_BITR_CAP_32 | MP3_BITR_CAP_40 | MP3_BITR_CAP_48 | \ | ||
60 | MP3_BITR_CAP_56 | MP3_BITR_CAP_64 | MP3_BITR_CAP_80 | \ | ||
61 | MP3_BITR_CAP_96 | MP3_BITR_CAP_112 | MP3_BITR_CAP_128 | \ | ||
62 | MP3_BITR_CAP_144 | MP3_BITR_CAP_160) | ||
63 | |||
64 | #if 0 | ||
65 | /* MPEG 2.5 */ | ||
66 | #define MPEG2_5_SAMPR_CAPS (SAMPR_CAP_8 | SAMPR_CAP_12 | SAMPR_CAP_11) | ||
67 | #define MPEG2_5_BITR_CAPS MPEG2_BITR_CAPS | ||
68 | #endif | ||
69 | |||
70 | /* Assume 44100 is always available and therefore MPEG1 */ | ||
71 | |||
72 | /* HAVE_MPEG* defines mainly apply to the bitrate menu */ | ||
73 | #if (REC_SAMPR_CAPS & MPEG2_SAMPR_CAPS) || defined (HAVE_SPDIF_IN) | ||
74 | #define HAVE_MPEG2_SAMPR | ||
75 | #endif | ||
76 | |||
77 | #if 0 | ||
78 | #if (REC_SAMPR_CAPS & MPEG2_5_SAMPR_CAPS) || defined (HAVE_SPDIF_IN) | ||
79 | #define HAVE_MPEG2_5_SAMPR | ||
80 | #endif | ||
81 | #endif /* 0 */ | ||
82 | |||
83 | #define MP3_ENC_SAMPR_CAPS (MPEG1_SAMPR_CAPS | MPEG2_SAMPR_CAPS) | ||
84 | |||
85 | /* This number is count of full encoder set */ | ||
86 | #define MP3_ENC_NUM_SAMPR 6 | ||
87 | |||
88 | extern const unsigned long mp3_enc_sampr[MP3_ENC_NUM_SAMPR]; | ||
89 | extern const unsigned long mp3_enc_bitr[MP3_ENC_NUM_BITR]; | ||
90 | |||
91 | struct mp3_enc_config | ||
92 | { | ||
93 | unsigned long bitrate; | ||
94 | }; | ||
95 | |||
96 | #define MP3_ENC_BITRATE_CFG_DEFAULT 11 /* 128 */ | ||
97 | #define MP3_ENC_BITRATE_CFG_VALUE_LIST "8,16,24,32,40,48,56,64,80,96," \ | ||
98 | "112,128,144,160,192,224,256,320" | ||
99 | |||
100 | /** wav_enc.codec **/ | ||
101 | #define WAV_ENC_SAMPR_CAPS SAMPR_CAP_ALL | ||
102 | |||
103 | struct wav_enc_config | ||
104 | { | ||
105 | #if 0 | ||
106 | unsigned long sample_depth; | ||
107 | #endif | ||
108 | }; | ||
109 | |||
110 | /** wavpack_enc.codec **/ | ||
111 | #define WAVPACK_ENC_SAMPR_CAPS SAMPR_CAP_ALL | ||
112 | |||
113 | struct wavpack_enc_config | ||
114 | { | ||
115 | #if 0 | ||
116 | unsigned long sample_depth; | ||
117 | #endif | ||
118 | }; | ||
119 | |||
120 | struct encoder_config | ||
121 | { | ||
122 | union | ||
123 | { | ||
124 | /* states which *_enc_config member is valid */ | ||
125 | int rec_format; /* REC_FORMAT_* value */ | ||
126 | int afmt; /* AFMT_* value */ | ||
127 | }; | ||
128 | |||
129 | union | ||
130 | { | ||
131 | struct mp3_enc_config mp3_enc; | ||
132 | struct wavpack_enc_config wavpack_enc; | ||
133 | struct wav_enc_config wav_enc; | ||
134 | }; | ||
135 | }; | ||
136 | |||
137 | /** Encoder chunk macros and definitions **/ | ||
138 | #define CHUNKF_START_FILE 0x0001 /* This chunk starts a new file */ | ||
139 | #define CHUNKF_END_FILE 0x0002 /* This chunk ends the current file */ | ||
140 | #define CHUNKF_PRERECORD 0x0010 /* This chunk is prerecord data, | ||
141 | a new file could start anytime */ | ||
142 | #define CHUNKF_ABORT 0x0020 /* Encoder should not finish this | ||
143 | chunk */ | ||
144 | #define CHUNKF_ERROR 0x80000000 /* An error has occured (passed to/ | ||
145 | from encoder). Use the sign bit to | ||
146 | check (long)flags < 0. */ | ||
147 | |||
148 | /* Header at the beginning of every encoder chunk */ | ||
149 | struct enc_chunk_hdr | ||
150 | { | ||
151 | unsigned long flags; /* in/out: flags used by encoder and file | ||
152 | writing */ | ||
153 | size_t enc_size; /* out: amount of encoder data written to | ||
154 | chunk */ | ||
155 | unsigned long num_pcm; /* out: number of PCM samples eaten during | ||
156 | processing | ||
157 | (<= size of allocated buffer) */ | ||
158 | unsigned char *enc_data; /* out: pointer to enc_size_written bytes | ||
159 | of encoded audio data in chunk */ | ||
160 | /* Encoder defined data follows header. Can be audio data + any other | ||
161 | stuff the encoder needs to handle on a per chunk basis */ | ||
162 | }; | ||
163 | |||
164 | /* Paranoia: be sure header size is 4-byte aligned */ | ||
165 | #define ENC_CHUNK_HDR_SIZE \ | ||
166 | ALIGN_UP_P2(sizeof (struct enc_chunk_hdr), 2) | ||
167 | /* Skip the chunk header and return data */ | ||
168 | #define ENC_CHUNK_SKIP_HDR(t, hdr) \ | ||
169 | ((typeof (t))((char *)hdr + ENC_CHUNK_HDR_SIZE)) | ||
170 | /* Cast p to struct enc_chunk_hdr * */ | ||
171 | #define ENC_CHUNK_HDR(p) \ | ||
172 | ((struct enc_chunk_hdr *)(p)) | ||
173 | |||
174 | enum enc_events | ||
175 | { | ||
176 | /* File writing events - data points to enc_file_event_data */ | ||
177 | ENC_START_FILE = 0, /* a new file has been opened and no data has yet | ||
178 | been written */ | ||
179 | ENC_WRITE_CHUNK, /* write the current chunk to disk */ | ||
180 | ENC_END_FILE, /* current file about to be closed and all valid | ||
181 | data has been written */ | ||
182 | /* Encoder buffer events - data points to enc_buffer_event_data */ | ||
183 | ENC_REC_NEW_STREAM, /* Take steps to finish current stream and start | ||
184 | new */ | ||
185 | }; | ||
186 | |||
187 | /** | ||
188 | * encoder can write extra data to the file such as headers or more encoded | ||
189 | * samples and must update sizes and samples accordingly. | ||
190 | */ | ||
191 | struct enc_file_event_data | ||
192 | { | ||
193 | struct enc_chunk_hdr *chunk; /* Current chunk */ | ||
194 | size_t new_enc_size; /* New size of chunk */ | ||
195 | unsigned long new_num_pcm; /* New number of pcm in chunk */ | ||
196 | const char *filename; /* filename to open if ENC_START_FILE */ | ||
197 | int rec_file; /* Current file or < 0 if none */ | ||
198 | unsigned long num_pcm_samples; /* Current pcm sample count written to | ||
199 | file so far. */ | ||
200 | }; | ||
201 | |||
202 | /** | ||
203 | * encoder may add some data to the end of the last and start of the next | ||
204 | * but must never yield when called so any encoding done should be absolutely | ||
205 | * minimal. | ||
206 | */ | ||
207 | struct enc_buffer_event_data | ||
208 | { | ||
209 | unsigned long flags; /* in: One or more of: | ||
210 | * CHUNKF_PRERECORD | ||
211 | * CHUNKF_END_FILE | ||
212 | * CHUNKF_START_FILE | ||
213 | */ | ||
214 | struct enc_chunk_hdr *pre_chunk; /* in: pointer to first prerecord | ||
215 | * chunk | ||
216 | */ | ||
217 | struct enc_chunk_hdr *chunk; /* in,out: chunk were split occurs - | ||
218 | * first chunk of start | ||
219 | */ | ||
220 | }; | ||
221 | |||
222 | /** Callbacks called by encoder codec **/ | ||
223 | |||
224 | /* parameters passed to encoder by enc_get_inputs */ | ||
225 | struct enc_inputs | ||
226 | { | ||
227 | unsigned long sample_rate; /* out - pcm frequency */ | ||
228 | int num_channels; /* out - number of audio channels */ | ||
229 | struct encoder_config *config; /* out - encoder settings */ | ||
230 | }; | ||
231 | |||
232 | void enc_get_inputs(struct enc_inputs *inputs); | ||
233 | |||
234 | /* parameters pass from encoder to enc_set_parameters */ | ||
235 | struct enc_parameters | ||
236 | { | ||
237 | /* IN parameters */ | ||
238 | int afmt; /* AFMT_* id - sanity checker */ | ||
239 | size_t chunk_size; /* max chunk size required */ | ||
240 | unsigned long enc_sample_rate; /* actual sample rate used by encoder | ||
241 | (for recorded time calculation) */ | ||
242 | size_t reserve_bytes; /* number of bytes to reserve immediately | ||
243 | following chunks */ | ||
244 | void (*events_callback)(enum enc_events event, | ||
245 | void *data); /* pointer to events callback */ | ||
246 | /* OUT parameters */ | ||
247 | unsigned char *enc_buffer; /* pointer to enc_buffer */ | ||
248 | size_t buf_chunk_size; /* size of chunks in enc_buffer */ | ||
249 | int num_chunks; /* number of chunks allotted to encoder */ | ||
250 | unsigned char *reserve_buffer; /* pointer to reserve_bytes bytes */ | ||
251 | }; | ||
252 | |||
253 | /* set the encoder dimensions - called by encoder codec at initialization | ||
254 | and termination */ | ||
255 | void enc_set_parameters(struct enc_parameters *params); | ||
256 | /* returns pointer to next write chunk in circular buffer */ | ||
257 | struct enc_chunk_hdr * enc_get_chunk(void); | ||
258 | /* releases the current chunk into the available chunks */ | ||
259 | void enc_finish_chunk(void); | ||
260 | /* checks near empty state on pcm input buffer */ | ||
261 | int enc_pcm_buf_near_empty(void); | ||
262 | |||
263 | #define PCM_MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */ | ||
264 | |||
265 | /* passes a pointer to next chunk of unprocessed wav data */ | ||
266 | unsigned char * enc_get_pcm_data(size_t size); | ||
267 | /* puts some pcm data back in the queue */ | ||
268 | size_t enc_unget_pcm_data(size_t size); | ||
269 | |||
270 | #endif /* ENC_BASE_H */ | ||
diff --git a/firmware/export/general.h b/firmware/export/general.h new file mode 100644 index 0000000000..427e2773b8 --- /dev/null +++ b/firmware/export/general.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #ifndef GENERAL_H | ||
21 | #define GENERAL_H | ||
22 | |||
23 | #include <stdbool.h> | ||
24 | |||
25 | /* round a signed/unsigned 32bit value to the closest of a list of values */ | ||
26 | /* returns the index of the closest value */ | ||
27 | int round_value_to_list32(unsigned long value, | ||
28 | const unsigned long list[], | ||
29 | int count, | ||
30 | bool signd); | ||
31 | |||
32 | int make_list_from_caps32(unsigned long src_mask, | ||
33 | const unsigned long *src_list, | ||
34 | unsigned long caps_mask, | ||
35 | unsigned long *caps_list); | ||
36 | |||
37 | |||
38 | #endif /* GENERAL_H */ | ||
diff --git a/firmware/export/pcm_sampr.h b/firmware/export/pcm_sampr.h new file mode 100644 index 0000000000..c4a399b62f --- /dev/null +++ b/firmware/export/pcm_sampr.h | |||
@@ -0,0 +1,310 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #ifndef PCM_SAMPR_H | ||
21 | #define PCM_SAMPR_H | ||
22 | |||
23 | /* These must be macros for comparison with SAMPR_CAP_* flags by the | ||
24 | preprocessor. Add samplerate index in descending order renumbering | ||
25 | the ones later in the list if any */ | ||
26 | #define FREQ_96 0 | ||
27 | #define FREQ_88 1 | ||
28 | #define FREQ_64 2 | ||
29 | #define FREQ_48 3 | ||
30 | #define FREQ_44 4 | ||
31 | #define FREQ_32 5 | ||
32 | #define FREQ_24 6 | ||
33 | #define FREQ_22 7 | ||
34 | #define FREQ_16 8 | ||
35 | #define FREQ_12 9 | ||
36 | #define FREQ_11 10 | ||
37 | #define FREQ_8 11 | ||
38 | #define SAMPR_NUM_FREQ 12 | ||
39 | |||
40 | /* sample rate values in HZ */ | ||
41 | #define SAMPR_96 96000 | ||
42 | #define SAMPR_88 88200 | ||
43 | #define SAMPR_64 64000 | ||
44 | #define SAMPR_48 48000 | ||
45 | #define SAMPR_44 44100 | ||
46 | #define SAMPR_32 32000 | ||
47 | #define SAMPR_24 24000 | ||
48 | #define SAMPR_22 22050 | ||
49 | #define SAMPR_16 16000 | ||
50 | #define SAMPR_12 12000 | ||
51 | #define SAMPR_11 11025 | ||
52 | #define SAMPR_8 8000 | ||
53 | |||
54 | /* sample rate capability bits */ | ||
55 | #define SAMPR_CAP_96 (1 << FREQ_96) | ||
56 | #define SAMPR_CAP_88 (1 << FREQ_88) | ||
57 | #define SAMPR_CAP_64 (1 << FREQ_64) | ||
58 | #define SAMPR_CAP_48 (1 << FREQ_48) | ||
59 | #define SAMPR_CAP_44 (1 << FREQ_44) | ||
60 | #define SAMPR_CAP_32 (1 << FREQ_32) | ||
61 | #define SAMPR_CAP_24 (1 << FREQ_24) | ||
62 | #define SAMPR_CAP_22 (1 << FREQ_22) | ||
63 | #define SAMPR_CAP_16 (1 << FREQ_16) | ||
64 | #define SAMPR_CAP_12 (1 << FREQ_12) | ||
65 | #define SAMPR_CAP_11 (1 << FREQ_11) | ||
66 | #define SAMPR_CAP_8 (1 << FREQ_8) | ||
67 | #define SAMPR_CAP_ALL (SAMPR_CAP_96 | SAMPR_CAP_88 | SAMPR_CAP_64 | \ | ||
68 | SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32 | \ | ||
69 | SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16 | \ | ||
70 | SAMPR_CAP_12 | SAMPR_CAP_11 | SAMPR_CAP_8) | ||
71 | |||
72 | /* Master list of all "standard" rates supported. */ | ||
73 | extern const unsigned long audio_master_sampr_list[SAMPR_NUM_FREQ]; | ||
74 | |||
75 | /** Hardware sample rates **/ | ||
76 | |||
77 | /* Enumeration of supported frequencies where 0 is the highest rate | ||
78 | supported and REC_NUM_FREQUENCIES is the number available */ | ||
79 | enum hw_freq_indexes | ||
80 | { | ||
81 | __HW_FREQ_START_INDEX = -1, /* Make sure first in list is 0 */ | ||
82 | |||
83 | /* 96000 */ | ||
84 | #if (HW_SAMPR_CAPS & SAMPR_CAP_96) /* Macros and enums for each FREQ: */ | ||
85 | HW_FREQ_96, /* Index in enumeration */ | ||
86 | #define HW_HAVE_96 /* Defined if this FREQ is defined */ | ||
87 | #define HW_HAVE_96_(...) __VA_ARGS__ /* Output its parameters for this FREQ */ | ||
88 | #else | ||
89 | #define HW_HAVE_96_(...) /* Discards its parameters for this FREQ */ | ||
90 | #endif | ||
91 | /* 88200 */ | ||
92 | #if (HW_SAMPR_CAPS & SAMPR_CAP_88) | ||
93 | HW_FREQ_88, | ||
94 | #define HW_HAVE_88 | ||
95 | #define HW_HAVE_88_(...) __VA_ARGS__ | ||
96 | #else | ||
97 | #define HW_HAVE_88_(...) | ||
98 | #endif | ||
99 | /* 64000 */ | ||
100 | #if (HW_SAMPR_CAPS & SAMPR_CAP_64) | ||
101 | HW_FREQ_64, | ||
102 | #define HW_HAVE_64 | ||
103 | #define HW_HAVE_64_(...) __VA_ARGS__ | ||
104 | #else | ||
105 | #define HW_HAVE_64_(...) | ||
106 | #endif | ||
107 | /* 48000 */ | ||
108 | #if (HW_SAMPR_CAPS & SAMPR_CAP_48) | ||
109 | HW_FREQ_48, | ||
110 | #define HW_HAVE_48 | ||
111 | #define HW_HAVE_48_(...) __VA_ARGS__ | ||
112 | #else | ||
113 | #define HW_HAVE_48_(...) | ||
114 | #endif | ||
115 | /* 44100 */ | ||
116 | HW_FREQ_44, | ||
117 | #define HW_HAVE_44 | ||
118 | #define HW_HAVE_44_(...) __VA_ARGS__ | ||
119 | /* 32000 */ | ||
120 | #if (HW_SAMPR_CAPS & SAMPR_CAP_32) | ||
121 | HW_FREQ_32, | ||
122 | #define HW_HAVE_32 | ||
123 | #define HW_HAVE_32_(...) __VA_ARGS__ | ||
124 | #else | ||
125 | #define HW_HAVE_32_(...) | ||
126 | #endif | ||
127 | /* 24000 */ | ||
128 | #if (HW_SAMPR_CAPS & SAMPR_CAP_24) | ||
129 | HW_FREQ_24, | ||
130 | #define HW_HAVE_24 | ||
131 | #define HW_HAVE_24_(...) __VA_ARGS__ | ||
132 | #else | ||
133 | #define HW_HAVE_24_(...) | ||
134 | #endif | ||
135 | /* 22050 */ | ||
136 | #if (HW_SAMPR_CAPS & SAMPR_CAP_22) | ||
137 | HW_FREQ_22, | ||
138 | #define HW_HAVE_22 | ||
139 | #define HW_HAVE_22_(...) __VA_ARGS__ | ||
140 | #else | ||
141 | #define HW_HAVE_22_(...) | ||
142 | #endif | ||
143 | /* 16000 */ | ||
144 | #if (HW_SAMPR_CAPS & SAMPR_CAP_16) | ||
145 | HW_FREQ_16, | ||
146 | #define HW_HAVE_16 | ||
147 | #define HW_HAVE_16_(...) __VA_ARGS__ | ||
148 | #else | ||
149 | #define HW_HAVE_16_(...) | ||
150 | #endif | ||
151 | /* 12000 */ | ||
152 | #if (HW_SAMPR_CAPS & SAMPR_CAP_12) | ||
153 | HW_FREQ_12, | ||
154 | #define HW_HAVE_12 | ||
155 | #define HW_HAVE_12_(...) __VA_ARGS__ | ||
156 | #else | ||
157 | #define HW_HAVE_12_(...) | ||
158 | #endif | ||
159 | /* 11025 */ | ||
160 | #if (HW_SAMPR_CAPS & SAMPR_CAP_11) | ||
161 | HW_FREQ_11, | ||
162 | #define HW_HAVE_11 | ||
163 | #define HW_HAVE_11_(...) __VA_ARGS__ | ||
164 | #else | ||
165 | #define HW_HAVE_11_(...) | ||
166 | #endif | ||
167 | /* 8000 */ | ||
168 | #if (HW_SAMPR_CAPS & SAMPR_CAP_8 ) | ||
169 | HW_FREQ_8, | ||
170 | #define HW_HAVE_8 | ||
171 | #define HW_HAVE_8_(...) __VA_ARGS__ | ||
172 | #else | ||
173 | #define HW_HAVE_8_(...) | ||
174 | #endif | ||
175 | HW_NUM_FREQ, | ||
176 | HW_FREQ_DEFAULT = HW_FREQ_44, | ||
177 | HW_SAMPR_DEFAULT = SAMPR_44, | ||
178 | }; /* enum hw_freq_indexes */ | ||
179 | |||
180 | /* list of hardware sample rates */ | ||
181 | extern const unsigned long hw_freq_sampr[HW_NUM_FREQ]; | ||
182 | |||
183 | #ifdef HAVE_RECORDING | ||
184 | /* Enumeration of supported frequencies where 0 is the highest rate | ||
185 | supported and REC_NUM_FREQUENCIES is the number available */ | ||
186 | enum rec_freq_indexes | ||
187 | { | ||
188 | __REC_FREQ_START_INDEX = -1, /* Make sure first in list is 0 */ | ||
189 | |||
190 | /* 96000 */ | ||
191 | #if (REC_SAMPR_CAPS & SAMPR_CAP_96) /* Macros and enums for each FREQ: */ | ||
192 | REC_FREQ_96, /* Index in enumeration */ | ||
193 | #define REC_HAVE_96 /* Defined if this FREQ is defined */ | ||
194 | #define REC_HAVE_96_(...) __VA_ARGS__ /* Output its parameters for this FREQ */ | ||
195 | #else | ||
196 | #define REC_HAVE_96_(...) /* Discards its parameters for this FREQ */ | ||
197 | #endif | ||
198 | /* 88200 */ | ||
199 | #if (REC_SAMPR_CAPS & SAMPR_CAP_88) | ||
200 | REC_FREQ_88, | ||
201 | #define REC_HAVE_88 | ||
202 | #define REC_HAVE_88_(...) __VA_ARGS__ | ||
203 | #else | ||
204 | #define REC_HAVE_88_(...) | ||
205 | #endif | ||
206 | /* 64000 */ | ||
207 | #if (REC_SAMPR_CAPS & SAMPR_CAP_64) | ||
208 | REC_FREQ_64, | ||
209 | #define REC_HAVE_64 | ||
210 | #define REC_HAVE_64_(...) __VA_ARGS__ | ||
211 | #else | ||
212 | #define REC_HAVE_64_(...) | ||
213 | #endif | ||
214 | /* 48000 */ | ||
215 | #if (REC_SAMPR_CAPS & SAMPR_CAP_48) | ||
216 | REC_FREQ_48, | ||
217 | #define REC_HAVE_48 | ||
218 | #define REC_HAVE_48_(...) __VA_ARGS__ | ||
219 | #else | ||
220 | #define REC_HAVE_48_(...) | ||
221 | #endif | ||
222 | /* 44100 */ | ||
223 | #if (REC_SAMPR_CAPS & SAMPR_CAP_44) | ||
224 | REC_FREQ_44, | ||
225 | #define REC_HAVE_44 | ||
226 | #define REC_HAVE_44_(...) __VA_ARGS__ | ||
227 | #else | ||
228 | #define REC_HAVE_44_(...) | ||
229 | #endif | ||
230 | /* 32000 */ | ||
231 | #if (REC_SAMPR_CAPS & SAMPR_CAP_32) | ||
232 | REC_FREQ_32, | ||
233 | #define REC_HAVE_32 | ||
234 | #define REC_HAVE_32_(...) __VA_ARGS__ | ||
235 | #else | ||
236 | #define REC_HAVE_32_(...) | ||
237 | #endif | ||
238 | /* 24000 */ | ||
239 | #if (REC_SAMPR_CAPS & SAMPR_CAP_24) | ||
240 | REC_FREQ_24, | ||
241 | #define REC_HAVE_24 | ||
242 | #define REC_HAVE_24_(...) __VA_ARGS__ | ||
243 | #else | ||
244 | #define REC_HAVE_24_(...) | ||
245 | #endif | ||
246 | /* 22050 */ | ||
247 | #if (REC_SAMPR_CAPS & SAMPR_CAP_22) | ||
248 | REC_FREQ_22, | ||
249 | #define REC_HAVE_22 | ||
250 | #define REC_HAVE_22_(...) __VA_ARGS__ | ||
251 | #else | ||
252 | #define REC_HAVE_22_(...) | ||
253 | #endif | ||
254 | /* 16000 */ | ||
255 | #if (REC_SAMPR_CAPS & SAMPR_CAP_16) | ||
256 | REC_FREQ_16, | ||
257 | #define REC_HAVE_16 | ||
258 | #define REC_HAVE_16_(...) __VA_ARGS__ | ||
259 | #else | ||
260 | #define REC_HAVE_16_(...) | ||
261 | #endif | ||
262 | /* 12000 */ | ||
263 | #if (REC_SAMPR_CAPS & SAMPR_CAP_12) | ||
264 | REC_FREQ_12, | ||
265 | #define REC_HAVE_12 | ||
266 | #define REC_HAVE_12_(...) __VA_ARGS__ | ||
267 | #else | ||
268 | #define REC_HAVE_12_(...) | ||
269 | #endif | ||
270 | /* 11025 */ | ||
271 | #if (REC_SAMPR_CAPS & SAMPR_CAP_11) | ||
272 | REC_FREQ_11, | ||
273 | #define REC_HAVE_11 | ||
274 | #define REC_HAVE_11_(...) __VA_ARGS__ | ||
275 | #else | ||
276 | #define REC_HAVE_11_(...) | ||
277 | #endif | ||
278 | /* 8000 */ | ||
279 | #if (REC_SAMPR_CAPS & SAMPR_CAP_8 ) | ||
280 | REC_FREQ_8, | ||
281 | #define REC_HAVE_8 | ||
282 | #define REC_HAVE_8_(...) __VA_ARGS__ | ||
283 | #else | ||
284 | #define REC_HAVE_8_(...) | ||
285 | #endif | ||
286 | REC_NUM_FREQ, | ||
287 | /* This should always come out I reckon */ | ||
288 | REC_FREQ_DEFAULT = REC_FREQ_44, | ||
289 | /* Get the minimum bitcount needed to save the range of values */ | ||
290 | REC_FREQ_CFG_NUM_BITS = (REC_NUM_FREQ > 8 ? | ||
291 | 4 : (REC_NUM_FREQ > 4 ? | ||
292 | 3 : (REC_NUM_FREQ > 2 ? | ||
293 | 2 : 1 | ||
294 | ) | ||
295 | ) | ||
296 | ), | ||
297 | }; /* enum rec_freq_indexes */ | ||
298 | |||
299 | #define REC_FREQ_CFG_VAL_LIST &REC_HAVE_96_(",96") REC_HAVE_88_(",88") \ | ||
300 | REC_HAVE_64_(",64") REC_HAVE_48_(",48") \ | ||
301 | REC_HAVE_44_(",44") REC_HAVE_32_(",32") \ | ||
302 | REC_HAVE_24_(",24") REC_HAVE_22_(",22") \ | ||
303 | REC_HAVE_16_(",16") REC_HAVE_12_(",12") \ | ||
304 | REC_HAVE_11_(",11") REC_HAVE_8_(",8")[1] | ||
305 | |||
306 | /* List of recording supported sample rates (set or subset of master list) */ | ||
307 | extern const unsigned long rec_freq_sampr[REC_NUM_FREQ]; | ||
308 | #endif /* HAVE_RECORDING */ | ||
309 | |||
310 | #endif /* PCM_SAMPR_H */ | ||
diff --git a/firmware/general.c b/firmware/general.c new file mode 100644 index 0000000000..7f4348046c --- /dev/null +++ b/firmware/general.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <limits.h> | ||
20 | #include "config.h" | ||
21 | #include "general.h" | ||
22 | |||
23 | int round_value_to_list32(unsigned long value, | ||
24 | const unsigned long list[], | ||
25 | int count, | ||
26 | bool signd) | ||
27 | { | ||
28 | unsigned long dmin = ULONG_MAX; | ||
29 | int idmin = -1, i; | ||
30 | |||
31 | for (i = 0; i < count; i++) | ||
32 | { | ||
33 | unsigned long diff; | ||
34 | |||
35 | if (list[i] == value) | ||
36 | { | ||
37 | idmin = i; | ||
38 | break; | ||
39 | } | ||
40 | |||
41 | if (signd ? ((long)list[i] < (long)value) : (list[i] < value)) | ||
42 | diff = value - list[i]; | ||
43 | else | ||
44 | diff = list[i] - value; | ||
45 | |||
46 | if (diff < dmin) | ||
47 | { | ||
48 | dmin = diff; | ||
49 | idmin = i; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | return idmin; | ||
54 | } /* round_value_to_list32 */ | ||
55 | |||
56 | /* Number of bits set in src_mask should equal src_list length */ | ||
57 | int make_list_from_caps32(unsigned long src_mask, | ||
58 | const unsigned long *src_list, | ||
59 | unsigned long caps_mask, | ||
60 | unsigned long *caps_list) | ||
61 | { | ||
62 | int i, count; | ||
63 | unsigned long mask; | ||
64 | |||
65 | for (mask = src_mask, count = 0, i = 0; | ||
66 | mask != 0; | ||
67 | src_mask = mask, i++) | ||
68 | { | ||
69 | unsigned long test_bit; | ||
70 | mask &= mask - 1; /* Zero lowest bit set */ | ||
71 | test_bit = mask ^ src_mask; /* Isolate the bit */ | ||
72 | if (test_bit & caps_mask) /* Add item if caps has test bit set */ | ||
73 | caps_list[count++] = src_list ? src_list[i] : (unsigned long)i; | ||
74 | } | ||
75 | |||
76 | return count; | ||
77 | } /* make_list_from_caps32 */ | ||
diff --git a/firmware/pcm_sampr.c b/firmware/pcm_sampr.c new file mode 100644 index 0000000000..cceb4b7399 --- /dev/null +++ b/firmware/pcm_sampr.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "config.h" | ||
20 | #include "pcm_sampr.h" | ||
21 | |||
22 | /* Master list of all "standard" rates supported. */ | ||
23 | const unsigned long audio_master_sampr_list[SAMPR_NUM_FREQ] = | ||
24 | { | ||
25 | [0 ... SAMPR_NUM_FREQ-1] = -1, /* any gaps set to -1 */ | ||
26 | [FREQ_96] = SAMPR_96, | ||
27 | [FREQ_88] = SAMPR_88, | ||
28 | [FREQ_64] = SAMPR_64, | ||
29 | [FREQ_48] = SAMPR_48, | ||
30 | [FREQ_44] = SAMPR_44, | ||
31 | [FREQ_32] = SAMPR_32, | ||
32 | [FREQ_24] = SAMPR_24, | ||
33 | [FREQ_22] = SAMPR_22, | ||
34 | [FREQ_16] = SAMPR_16, | ||
35 | [FREQ_12] = SAMPR_12, | ||
36 | [FREQ_11] = SAMPR_11, | ||
37 | [FREQ_8 ] = SAMPR_8, | ||
38 | }; | ||
39 | |||
40 | /* List of all hardware rates supported (set or subset of master list) */ | ||
41 | const unsigned long hw_freq_sampr[HW_NUM_FREQ] = | ||
42 | { | ||
43 | [0 ... HW_NUM_FREQ-1] = -1, | ||
44 | HW_HAVE_96_([HW_FREQ_96] = SAMPR_96,) | ||
45 | HW_HAVE_88_([HW_FREQ_88] = SAMPR_88,) | ||
46 | HW_HAVE_64_([HW_FREQ_64] = SAMPR_64,) | ||
47 | HW_HAVE_48_([HW_FREQ_48] = SAMPR_48,) | ||
48 | HW_HAVE_44_([HW_FREQ_44] = SAMPR_44,) | ||
49 | HW_HAVE_32_([HW_FREQ_32] = SAMPR_32,) | ||
50 | HW_HAVE_24_([HW_FREQ_24] = SAMPR_24,) | ||
51 | HW_HAVE_22_([HW_FREQ_22] = SAMPR_22,) | ||
52 | HW_HAVE_16_([HW_FREQ_16] = SAMPR_16,) | ||
53 | HW_HAVE_12_([HW_FREQ_12] = SAMPR_12,) | ||
54 | HW_HAVE_11_([HW_FREQ_11] = SAMPR_11,) | ||
55 | HW_HAVE_8_( [HW_FREQ_8 ] = SAMPR_8 ,) | ||
56 | }; | ||
57 | |||
58 | #ifdef HAVE_RECORDING | ||
59 | /* List of recording supported sample rates (set or subset of master list) */ | ||
60 | const unsigned long rec_freq_sampr[REC_NUM_FREQ] = | ||
61 | { | ||
62 | [0 ... REC_NUM_FREQ-1] = -1, | ||
63 | REC_HAVE_96_([REC_FREQ_96] = SAMPR_96,) | ||
64 | REC_HAVE_88_([REC_FREQ_88] = SAMPR_88,) | ||
65 | REC_HAVE_64_([REC_FREQ_64] = SAMPR_64,) | ||
66 | REC_HAVE_48_([REC_FREQ_48] = SAMPR_48,) | ||
67 | REC_HAVE_44_([REC_FREQ_44] = SAMPR_44,) | ||
68 | REC_HAVE_32_([REC_FREQ_32] = SAMPR_32,) | ||
69 | REC_HAVE_24_([REC_FREQ_24] = SAMPR_24,) | ||
70 | REC_HAVE_22_([REC_FREQ_22] = SAMPR_22,) | ||
71 | REC_HAVE_16_([REC_FREQ_16] = SAMPR_16,) | ||
72 | REC_HAVE_12_([REC_FREQ_12] = SAMPR_12,) | ||
73 | REC_HAVE_11_([REC_FREQ_11] = SAMPR_11,) | ||
74 | REC_HAVE_8_( [REC_FREQ_8 ] = SAMPR_8 ,) | ||
75 | }; | ||
76 | #endif /* HAVE_RECORDING */ | ||
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c new file mode 100644 index 0000000000..6b92f9cc14 --- /dev/null +++ b/firmware/target/coldfire/pcm-coldfire.c | |||
@@ -0,0 +1,738 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <stdlib.h> | ||
20 | #include "system.h" | ||
21 | #include "kernel.h" | ||
22 | #include "logf.h" | ||
23 | #include "audio.h" | ||
24 | #if defined(HAVE_UDA1380) | ||
25 | #include "uda1380.h" | ||
26 | #elif defined(HAVE_TLV320) | ||
27 | #include "tlv320.h" | ||
28 | #endif | ||
29 | |||
30 | /* Avoid further #ifdef's for some codec functions */ | ||
31 | #if defined(HAVE_UDA1380) | ||
32 | #define ac_init uda1380_init | ||
33 | #define ac_mute uda1380_mute | ||
34 | #define ac_set_frequency uda1380_set_frequency | ||
35 | #elif defined(HAVE_TLV320) | ||
36 | #define ac_init tlv320_init | ||
37 | #define ac_mute tlv320_mute | ||
38 | #define ac_set_frequency tlv320_set_frequency | ||
39 | #endif | ||
40 | |||
41 | /** Semi-private shared symbols **/ | ||
42 | |||
43 | /* the registered callback function to ask for more pcm data */ | ||
44 | extern pcm_more_callback_type pcm_callback_for_more; | ||
45 | extern bool pcm_playing; | ||
46 | extern bool pcm_paused; | ||
47 | |||
48 | /* the registered callback function for when more data is available */ | ||
49 | extern pcm_more_callback_type pcm_callback_more_ready; | ||
50 | extern bool pcm_recording; | ||
51 | |||
52 | /* peaks */ | ||
53 | static int play_peak_left, play_peak_right; | ||
54 | static unsigned long *rec_peak_addr; | ||
55 | static int rec_peak_left, rec_peak_right; | ||
56 | |||
57 | #define IIS_DEFPARM ( (freq_ent[FPARM_CLOCKSEL] << 12) | \ | ||
58 | (pcm_txsrc_select[pcm_monitor+1] << 8) | \ | ||
59 | (4 << 2) ) /* 64 bit clocks / word clock */ | ||
60 | #define IIS_RESET 0x800 | ||
61 | |||
62 | #ifdef IAUDIO_X5 | ||
63 | #define SET_IIS_CONFIG(x) IIS1CONFIG = (x); | ||
64 | #define IIS_CONFIG IIS1CONFIG | ||
65 | #define PLLCR_SET_AUDIO_BITS_DEFPARM \ | ||
66 | ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22)) | ||
67 | #else | ||
68 | #define SET_IIS_CONFIG(x) IIS2CONFIG = (x); | ||
69 | #define IIS_CONFIG IIS2CONFIG | ||
70 | #define PLLCR_SET_AUDIO_BITS_DEFPARM \ | ||
71 | ((freq_ent[FPARM_CLSEL] << 28) | (3 << 22)) | ||
72 | |||
73 | #ifdef HAVE_SPDIF_OUT | ||
74 | #define EBU_DEFPARM ((7 << 12) | (3 << 8) | (1 << 5) | (5 << 2)) | ||
75 | #endif | ||
76 | #endif | ||
77 | |||
78 | /** Sample rates **/ | ||
79 | #define FPARM_CLOCKSEL 0 | ||
80 | #define FPARM_CLSEL 1 | ||
81 | #define FPARM_FSEL 2 | ||
82 | #if CONFIG_CPU == MCF5249 && defined(HAVE_UDA1380) | ||
83 | static const unsigned char pcm_freq_parms[HW_NUM_FREQ][3] = | ||
84 | { | ||
85 | [HW_FREQ_88] = { 0x0c, 0x01, 0x03 }, | ||
86 | [HW_FREQ_44] = { 0x06, 0x01, 0x02 }, | ||
87 | [HW_FREQ_22] = { 0x04, 0x02, 0x01 }, | ||
88 | [HW_FREQ_11] = { 0x02, 0x02, 0x00 }, | ||
89 | }; | ||
90 | #endif | ||
91 | |||
92 | #if CONFIG_CPU == MCF5250 && defined(HAVE_TLV320) | ||
93 | static const unsigned char pcm_freq_parms[HW_NUM_FREQ][3] = | ||
94 | { | ||
95 | [HW_FREQ_88] = { 0x0c, 0x01, 0x02 }, | ||
96 | [HW_FREQ_44] = { 0x06, 0x01, 0x01 }, | ||
97 | [HW_FREQ_22] = { 0x04, 0x01, 0x00 }, | ||
98 | [HW_FREQ_11] = { 0x02, 0x02, 0x00 }, | ||
99 | }; | ||
100 | #endif | ||
101 | |||
102 | static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */ | ||
103 | static const unsigned char *freq_ent = pcm_freq_parms[HW_FREQ_DEFAULT]; | ||
104 | |||
105 | /* set frequency used by the audio hardware */ | ||
106 | void pcm_set_frequency(unsigned int frequency) | ||
107 | { | ||
108 | int index; | ||
109 | |||
110 | switch(frequency) | ||
111 | { | ||
112 | case SAMPR_11: | ||
113 | index = HW_FREQ_11; | ||
114 | break; | ||
115 | case SAMPR_22: | ||
116 | index = HW_FREQ_22; | ||
117 | break; | ||
118 | default: | ||
119 | case SAMPR_44: | ||
120 | index = HW_FREQ_44; | ||
121 | break; | ||
122 | case SAMPR_88: | ||
123 | index = HW_FREQ_88; | ||
124 | break; | ||
125 | } | ||
126 | |||
127 | /* remember table entry and rate */ | ||
128 | freq_ent = pcm_freq_parms[index]; | ||
129 | pcm_freq = hw_freq_sampr[index]; | ||
130 | } /* pcm_set_frequency */ | ||
131 | |||
132 | /** monitoring/source selection **/ | ||
133 | static int pcm_monitor = AUDIO_SRC_PLAYBACK; | ||
134 | |||
135 | static const unsigned char pcm_txsrc_select[AUDIO_NUM_SOURCES+1] = | ||
136 | { | ||
137 | [AUDIO_SRC_PLAYBACK+1] = 3, /* PDOR3 */ | ||
138 | [AUDIO_SRC_MIC+1] = 4, /* IIS1 RcvData */ | ||
139 | [AUDIO_SRC_LINEIN+1] = 4, /* IIS1 RcvData */ | ||
140 | #ifdef HAVE_FMRADIO_IN | ||
141 | [AUDIO_SRC_FMRADIO+1] = 4, /* IIS1 RcvData */ | ||
142 | #endif | ||
143 | #ifdef HAVE_SPDIF_IN | ||
144 | [AUDIO_SRC_SPDIF+1] = 7, /* EBU1 RcvData */ | ||
145 | #endif | ||
146 | }; | ||
147 | |||
148 | static const unsigned short pcm_dataincontrol[AUDIO_NUM_SOURCES+1] = | ||
149 | { | ||
150 | [AUDIO_SRC_PLAYBACK+1] = 0x0200, /* Reset PDIR2 data flow */ | ||
151 | [AUDIO_SRC_MIC+1] = 0xc020, /* Int. when 6 samples in FIFO, | ||
152 | PDIR2 src = ebu1RcvData */ | ||
153 | [AUDIO_SRC_LINEIN+1] = 0xc020, /* Int. when 6 samples in FIFO, | ||
154 | PDIR2 src = ebu1RcvData */ | ||
155 | #ifdef HAVE_FMRADIO_IN | ||
156 | [AUDIO_SRC_FMRADIO+1] = 0xc020, /* Int. when 6 samples in FIFO, | ||
157 | PDIR2 src = ebu1RcvData */ | ||
158 | #endif | ||
159 | #ifdef HAVE_SPDIF_IN | ||
160 | [AUDIO_SRC_SPDIF+1] = 0xc038, /* Int. when 6 samples in FIFO, | ||
161 | PDIR2 src = ebu1RcvData */ | ||
162 | #endif | ||
163 | }; | ||
164 | |||
165 | static int pcm_rec_src = AUDIO_SRC_PLAYBACK; | ||
166 | |||
167 | void pcm_set_monitor(int monitor) | ||
168 | { | ||
169 | if ((unsigned)monitor >= AUDIO_NUM_SOURCES) | ||
170 | monitor = AUDIO_SRC_PLAYBACK; | ||
171 | pcm_monitor = monitor; | ||
172 | } /* pcm_set_monitor */ | ||
173 | |||
174 | void pcm_set_rec_source(int source) | ||
175 | { | ||
176 | if ((unsigned)source >= AUDIO_NUM_SOURCES) | ||
177 | source = AUDIO_SRC_PLAYBACK; | ||
178 | pcm_rec_src = source; | ||
179 | } /* pcm_set_rec_source */ | ||
180 | |||
181 | /* apply audio settings */ | ||
182 | void pcm_apply_settings(bool reset) | ||
183 | { | ||
184 | static int last_pcm_freq = HW_SAMPR_DEFAULT; | ||
185 | #if 0 | ||
186 | static int last_pcm_monitor = AUDIO_SRC_PLAYBACK; | ||
187 | #endif | ||
188 | static int last_pcm_rec_src = AUDIO_SRC_PLAYBACK; | ||
189 | |||
190 | /* Playback must prevent pops and record monitoring won't work at all | ||
191 | adding IIS_RESET when setting IIS_CONFIG. Use a different method for | ||
192 | each. */ | ||
193 | if (reset && (pcm_monitor != AUDIO_SRC_PLAYBACK)) | ||
194 | { | ||
195 | /* Not playback - reset first */ | ||
196 | SET_IIS_CONFIG(IIS_RESET); | ||
197 | reset = false; | ||
198 | } | ||
199 | |||
200 | if (pcm_rec_src != last_pcm_rec_src) | ||
201 | { | ||
202 | last_pcm_rec_src = pcm_rec_src; | ||
203 | DATAINCONTROL = pcm_dataincontrol[pcm_rec_src+1]; | ||
204 | } | ||
205 | |||
206 | if (pcm_freq != last_pcm_freq) | ||
207 | { | ||
208 | last_pcm_freq = pcm_freq; | ||
209 | ac_set_frequency(freq_ent[FPARM_FSEL]); | ||
210 | coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); | ||
211 | } | ||
212 | |||
213 | SET_IIS_CONFIG(IIS_DEFPARM | (reset ? IIS_RESET : 0)); | ||
214 | } /* pcm_apply_settings */ | ||
215 | |||
216 | /** DMA **/ | ||
217 | |||
218 | /**************************************************************************** | ||
219 | ** Playback DMA transfer | ||
220 | **/ | ||
221 | |||
222 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ | ||
223 | void pcm_play_dma_start(const void *addr, size_t size) | ||
224 | { | ||
225 | logf("pcm_play_dma_start"); | ||
226 | |||
227 | addr = (void *)((unsigned long)addr & ~3); /* Align data */ | ||
228 | size &= ~3; /* Size must be multiple of 4 */ | ||
229 | |||
230 | pcm_playing = true; | ||
231 | |||
232 | /* Reset the audio FIFO */ | ||
233 | #ifdef HAVE_SPDIF_OUT | ||
234 | EBU1CONFIG = IIS_RESET | EBU_DEFPARM; | ||
235 | #endif | ||
236 | |||
237 | /* Set up DMA transfer */ | ||
238 | SAR0 = (unsigned long)addr; /* Source address */ | ||
239 | DAR0 = (unsigned long)&PDOR3; /* Destination address */ | ||
240 | BCR0 = size; /* Bytes to transfer */ | ||
241 | |||
242 | /* Enable the FIFO and force one write to it */ | ||
243 | pcm_apply_settings(false); | ||
244 | |||
245 | /* Also send the audio to S/PDIF */ | ||
246 | #ifdef HAVE_SPDIF_OUT | ||
247 | EBU1CONFIG = EBU_DEFPARM; | ||
248 | #endif | ||
249 | |||
250 | DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | | ||
251 | DMA_SINC | DMA_SSIZE(3) | DMA_START; | ||
252 | } /* pcm_play_dma_start */ | ||
253 | |||
254 | /* Stops the DMA transfer and interrupt */ | ||
255 | void pcm_play_dma_stop(void) | ||
256 | { | ||
257 | logf("pcm_play_dma_stop"); | ||
258 | |||
259 | pcm_playing = false; | ||
260 | |||
261 | DCR0 = 0; | ||
262 | DSR0 = 1; | ||
263 | |||
264 | /* Reset the FIFO */ | ||
265 | pcm_apply_settings(false); | ||
266 | |||
267 | #ifdef HAVE_SPDIF_OUT | ||
268 | EBU1CONFIG = IIS_RESET | EBU_DEFPARM; | ||
269 | #endif | ||
270 | } /* pcm_play_dma_stop */ | ||
271 | |||
272 | void pcm_init(void) | ||
273 | { | ||
274 | logf("pcm_init"); | ||
275 | |||
276 | pcm_playing = false; | ||
277 | pcm_paused = false; | ||
278 | pcm_callback_for_more = NULL; | ||
279 | |||
280 | MPARK = 0x81; /* PARK[1,0]=10 + BCR24BIT */ | ||
281 | DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */ | ||
282 | DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1; | ||
283 | DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ | ||
284 | |||
285 | /* Reset the audio FIFO */ | ||
286 | SET_IIS_CONFIG(IIS_RESET); | ||
287 | |||
288 | pcm_set_frequency(-1); | ||
289 | pcm_set_monitor(-1); | ||
290 | |||
291 | /* Prevent pops (resets DAC to zero point) */ | ||
292 | SET_IIS_CONFIG(IIS_DEFPARM | IIS_RESET); | ||
293 | |||
294 | /* Initialize default register values. */ | ||
295 | ac_init(); | ||
296 | |||
297 | #if defined(HAVE_UDA1380) | ||
298 | /* Sleep a while so the power can stabilize (especially a long | ||
299 | delay is needed for the line out connector). */ | ||
300 | sleep(HZ); | ||
301 | /* Power on FSDAC and HP amp. */ | ||
302 | uda1380_enable_output(true); | ||
303 | #elif defined(HAVE_TLV320) | ||
304 | sleep(HZ/4); | ||
305 | #endif | ||
306 | |||
307 | /* UDA1380: Unmute the master channel | ||
308 | (DAC should be at zero point now). */ | ||
309 | ac_mute(false); | ||
310 | |||
311 | /* Call pcm_play_dma_stop to initialize everything. */ | ||
312 | pcm_play_dma_stop(); | ||
313 | |||
314 | /* Enable interrupt at level 7, priority 0 */ | ||
315 | ICR6 = (7 << 2); | ||
316 | IMR &= ~(1 << 14); /* bit 14 is DMA0 */ | ||
317 | } /* pcm_init */ | ||
318 | |||
319 | size_t pcm_get_bytes_waiting(void) | ||
320 | { | ||
321 | return BCR0 & 0xffffff; | ||
322 | } /* pcm_get_bytes_waiting */ | ||
323 | |||
324 | /* DMA0 Interrupt is called when the DMA has finished transfering a chunk | ||
325 | from the caller's buffer */ | ||
326 | void DMA0(void) __attribute__ ((interrupt_handler, section(".icode"))); | ||
327 | void DMA0(void) | ||
328 | { | ||
329 | int res = DSR0; | ||
330 | |||
331 | DSR0 = 1; /* Clear interrupt */ | ||
332 | DCR0 &= ~DMA_EEXT; | ||
333 | |||
334 | /* Stop on error */ | ||
335 | if ((res & 0x70) == 0) | ||
336 | { | ||
337 | pcm_more_callback_type get_more = pcm_callback_for_more; | ||
338 | unsigned char *next_start; | ||
339 | size_t next_size = 0; | ||
340 | |||
341 | if (get_more) | ||
342 | get_more(&next_start, &next_size); | ||
343 | |||
344 | if (next_size > 0) | ||
345 | { | ||
346 | SAR0 = (unsigned long)next_start; /* Source address */ | ||
347 | BCR0 = next_size; /* Bytes to transfer */ | ||
348 | DCR0 |= DMA_EEXT; | ||
349 | return; | ||
350 | } | ||
351 | else | ||
352 | { | ||
353 | /* Finished playing */ | ||
354 | #if 0 | ||
355 | /* int. logfs can trash the display */ | ||
356 | logf("DMA0 No Data:0x%04x", res); | ||
357 | #endif | ||
358 | } | ||
359 | } | ||
360 | else | ||
361 | { | ||
362 | logf("DMA Error:0x%04x", res); | ||
363 | } | ||
364 | |||
365 | pcm_play_dma_stop(); | ||
366 | } /* DMA0 */ | ||
367 | |||
368 | /**************************************************************************** | ||
369 | ** Recording DMA transfer | ||
370 | **/ | ||
371 | void pcm_rec_dma_start(const void *addr, size_t size) | ||
372 | { | ||
373 | logf("pcm_rec_dma_start"); | ||
374 | |||
375 | addr = (void *)((unsigned long)addr & ~3); /* Align data */ | ||
376 | size &= ~3; /* Size must be multiple of 4 */ | ||
377 | |||
378 | pcm_recording = true; | ||
379 | |||
380 | DAR1 = (unsigned long)addr; /* Destination address */ | ||
381 | SAR1 = (unsigned long)&PDIR2; /* Source address */ | ||
382 | BCR1 = size; /* Bytes to transfer */ | ||
383 | |||
384 | rec_peak_addr = (unsigned long *)addr; | ||
385 | |||
386 | pcm_apply_settings(false); | ||
387 | |||
388 | /* Start the DMA transfer.. */ | ||
389 | #ifdef HAVE_SPDIF_IN | ||
390 | INTERRUPTCLEAR = 0x03c00000; | ||
391 | #endif | ||
392 | |||
393 | DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | | ||
394 | DMA_DSIZE(3) | DMA_START; | ||
395 | } /* pcm_dma_start */ | ||
396 | |||
397 | void pcm_rec_dma_stop(void) | ||
398 | { | ||
399 | logf("pcm_rec_dma_stop"); | ||
400 | |||
401 | pcm_recording = false; | ||
402 | |||
403 | DCR1 = 0; | ||
404 | DSR1 = 1; /* Clear interrupt */ | ||
405 | } /* pcm_dma_stop */ | ||
406 | |||
407 | void pcm_init_recording(void) | ||
408 | { | ||
409 | logf("pcm_init_recording"); | ||
410 | |||
411 | pcm_recording = false; | ||
412 | pcm_callback_more_ready = NULL; | ||
413 | |||
414 | AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */ | ||
415 | |||
416 | DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */ | ||
417 | DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ | ||
418 | DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2; | ||
419 | |||
420 | #ifdef HAVE_SPDIF_IN | ||
421 | /* PHASECONFIG setup: gain = 3*2^13, source = EBUIN */ | ||
422 | PHASECONFIG = (6 << 3) | (4 << 0); | ||
423 | #endif | ||
424 | |||
425 | pcm_rec_dma_stop(); | ||
426 | |||
427 | ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ | ||
428 | IMR &= ~(1 << 15); /* bit 15 is DMA1 */ | ||
429 | } /* pcm_init_recording */ | ||
430 | |||
431 | void pcm_close_recording(void) | ||
432 | { | ||
433 | logf("pcm_close_recording"); | ||
434 | |||
435 | pcm_rec_dma_stop(); | ||
436 | |||
437 | DMAROUTE &= 0xffff00ff; | ||
438 | ICR7 = 0x00; /* Disable interrupt */ | ||
439 | IMR |= (1 << 15); /* bit 15 is DMA1 */ | ||
440 | } /* pcm_close_recording */ | ||
441 | |||
442 | /* DMA1 Interrupt is called when the DMA has finished transfering a chunk | ||
443 | into the caller's buffer */ | ||
444 | void DMA1(void) __attribute__ ((interrupt_handler, section(".icode"))); | ||
445 | void DMA1(void) | ||
446 | { | ||
447 | int res = DSR1; | ||
448 | pcm_more_callback_type more_ready; | ||
449 | unsigned char *next_start; | ||
450 | ssize_t next_size = 0; /* passing <> 0 is indicates | ||
451 | an error condition */ | ||
452 | |||
453 | DSR1 = 1; /* Clear interrupt */ | ||
454 | DCR1 &= ~DMA_EEXT; | ||
455 | |||
456 | if (res & 0x70) | ||
457 | { | ||
458 | next_size = DMA_REC_ERROR_DMA; | ||
459 | logf("DMA1 err: 0x%x", res); | ||
460 | } | ||
461 | #ifdef HAVE_SPDIF_IN | ||
462 | else if (pcm_rec_src == AUDIO_SRC_SPDIF && | ||
463 | (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */ | ||
464 | { | ||
465 | INTERRUPTCLEAR = 0x03c00000; | ||
466 | next_size = DMA_REC_ERROR_SPDIF; | ||
467 | logf("spdif err"); | ||
468 | } | ||
469 | #endif | ||
470 | |||
471 | more_ready = pcm_callback_more_ready; | ||
472 | |||
473 | if (more_ready) | ||
474 | more_ready(&next_start, &next_size); | ||
475 | |||
476 | if (next_size > 0) | ||
477 | { | ||
478 | /* Start peaking at dest */ | ||
479 | rec_peak_addr = (unsigned long *)next_start; | ||
480 | DAR1 = (unsigned long)next_start; /* Destination address */ | ||
481 | BCR1 = (unsigned long)next_size; /* Bytes to transfer */ | ||
482 | DCR1 |= DMA_EEXT; | ||
483 | return; | ||
484 | } | ||
485 | else | ||
486 | { | ||
487 | #if 0 | ||
488 | /* int. logfs can trash the display */ | ||
489 | logf("DMA1 No Data:0x%04x", res); | ||
490 | #endif | ||
491 | } | ||
492 | |||
493 | /* Finished recording */ | ||
494 | pcm_rec_dma_stop(); | ||
495 | } /* DMA1 */ | ||
496 | |||
497 | void pcm_mute(bool mute) | ||
498 | { | ||
499 | ac_mute(mute); | ||
500 | if (mute) | ||
501 | sleep(HZ/16); | ||
502 | } /* pcm_mute */ | ||
503 | |||
504 | void pcm_play_pause_pause(void) | ||
505 | { | ||
506 | /* Disable DMA peripheral request. */ | ||
507 | DCR0 &= ~DMA_EEXT; | ||
508 | pcm_apply_settings(true); | ||
509 | #ifdef HAVE_SPDIF_OUT | ||
510 | EBU1CONFIG = EBU_DEFPARM; | ||
511 | #endif | ||
512 | } /* pcm_play_pause_pause */ | ||
513 | |||
514 | void pcm_play_pause_unpause(void) | ||
515 | { | ||
516 | /* Enable the FIFO and force one write to it */ | ||
517 | pcm_apply_settings(false); | ||
518 | #ifdef HAVE_SPDIF_OUT | ||
519 | EBU1CONFIG = EBU_DEFPARM; | ||
520 | #endif | ||
521 | DCR0 |= DMA_EEXT | DMA_START; | ||
522 | } /* pcm_play_pause_unpause */ | ||
523 | |||
524 | /** | ||
525 | * Return playback peaks - Peaks ahead in the DMA buffer based upon the | ||
526 | * calling period to attempt to compensate for | ||
527 | * delay. | ||
528 | */ | ||
529 | void pcm_calculate_peaks(int *left, int *right) | ||
530 | { | ||
531 | unsigned long samples; | ||
532 | unsigned long *addr, *end; | ||
533 | long peak_p, peak_n; | ||
534 | int level; | ||
535 | |||
536 | static unsigned long last_peak_tick = 0; | ||
537 | static unsigned long frame_period = 0; | ||
538 | |||
539 | /* Throttled peak ahead based on calling period */ | ||
540 | unsigned long period = current_tick - last_peak_tick; | ||
541 | |||
542 | /* Keep reasonable limits on period */ | ||
543 | if (period < 1) | ||
544 | period = 1; | ||
545 | else if (period > HZ/5) | ||
546 | period = HZ/5; | ||
547 | |||
548 | frame_period = (3*frame_period + period) >> 2; | ||
549 | |||
550 | last_peak_tick = current_tick; | ||
551 | |||
552 | if (!pcm_playing || pcm_paused) | ||
553 | { | ||
554 | play_peak_left = play_peak_right = 0; | ||
555 | goto peak_done; | ||
556 | } | ||
557 | |||
558 | /* prevent interrupt from setting up next transfer and | ||
559 | be sure SAR0 and BCR0 refer to current transfer */ | ||
560 | level = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
561 | |||
562 | addr = (long *)(SAR0 & ~3); | ||
563 | samples = (BCR0 & 0xffffff) >> 2; | ||
564 | |||
565 | set_irq_level(level); | ||
566 | |||
567 | samples = MIN(frame_period*pcm_freq/HZ, samples); | ||
568 | end = addr + samples; | ||
569 | peak_p = peak_n = 0; | ||
570 | |||
571 | if (left && right) | ||
572 | { | ||
573 | if (samples > 0) | ||
574 | { | ||
575 | long peak_rp = 0, peak_rn = 0; | ||
576 | |||
577 | do | ||
578 | { | ||
579 | long value = *addr; | ||
580 | long ch; | ||
581 | |||
582 | ch = value >> 16; | ||
583 | if (ch > peak_p) peak_p = ch; | ||
584 | else if (ch < peak_n) peak_n = ch; | ||
585 | |||
586 | ch = (short)value; | ||
587 | if (ch > peak_rp) peak_rp = ch; | ||
588 | else if (ch < peak_rn) peak_rn = ch; | ||
589 | |||
590 | addr += 4; | ||
591 | } | ||
592 | while (addr < end); | ||
593 | |||
594 | play_peak_left = MAX(peak_p, -peak_n); | ||
595 | play_peak_right = MAX(peak_rp, -peak_rn); | ||
596 | } | ||
597 | } | ||
598 | else if (left || right) | ||
599 | { | ||
600 | if (samples > 0) | ||
601 | { | ||
602 | if (left) | ||
603 | { | ||
604 | /* Put left channel in low word */ | ||
605 | addr = (long *)((short *)addr - 1); | ||
606 | end = (long *)((short *)end - 1); | ||
607 | } | ||
608 | |||
609 | do | ||
610 | { | ||
611 | long value = *(short *)addr; | ||
612 | |||
613 | if (value > peak_p) peak_p = value; | ||
614 | else if (value < peak_n) peak_n = value; | ||
615 | |||
616 | addr += 4; | ||
617 | } | ||
618 | while (addr < end); | ||
619 | |||
620 | if (left) | ||
621 | play_peak_left = MAX(peak_p, -peak_n); | ||
622 | else | ||
623 | play_peak_right = MAX(peak_p, -peak_n); | ||
624 | } | ||
625 | } | ||
626 | |||
627 | peak_done: | ||
628 | if (left) | ||
629 | *left = play_peak_left; | ||
630 | |||
631 | if (right) | ||
632 | *right = play_peak_right; | ||
633 | } /* pcm_calculate_peaks */ | ||
634 | |||
635 | /** | ||
636 | * Return recording peaks - Looks at every 4th sample from last peak up to | ||
637 | * current write position. | ||
638 | */ | ||
639 | void pcm_calculate_rec_peaks(int *left, int *right) | ||
640 | { | ||
641 | unsigned long *pkaddr, *addr, *end; | ||
642 | long peak_lp, peak_ln; /* L +,- */ | ||
643 | long peak_rp, peak_rn; /* R +,- */ | ||
644 | int level; | ||
645 | |||
646 | if (!pcm_recording) | ||
647 | { | ||
648 | rec_peak_left = rec_peak_right = 0; | ||
649 | goto peak_done; | ||
650 | } | ||
651 | |||
652 | /* read these atomically or each value may not refer to the | ||
653 | same data transfer */ | ||
654 | level = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
655 | |||
656 | pkaddr = rec_peak_addr; | ||
657 | addr = pkaddr; | ||
658 | end = (unsigned long *)(DAR1 & ~3); | ||
659 | |||
660 | set_irq_level(level); | ||
661 | |||
662 | if (addr < end) | ||
663 | { | ||
664 | peak_lp = peak_ln = | ||
665 | peak_rp = peak_rn = 0; | ||
666 | |||
667 | /* peak one sample per line */ | ||
668 | do | ||
669 | { | ||
670 | long value = *addr; | ||
671 | long ch; | ||
672 | |||
673 | ch = value >> 16; | ||
674 | if (ch < peak_ln) | ||
675 | peak_ln = ch; | ||
676 | else if (ch > peak_lp) | ||
677 | peak_lp = ch; | ||
678 | |||
679 | ch = (short)value; | ||
680 | if (ch > peak_rp) | ||
681 | peak_rp = ch; | ||
682 | else if (ch < peak_rn) | ||
683 | peak_rn = ch; | ||
684 | |||
685 | addr += 4; | ||
686 | } | ||
687 | while (addr < end); | ||
688 | |||
689 | /* only update rec_peak_addr if a DMA interrupt hasn't already | ||
690 | done so */ | ||
691 | level = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
692 | |||
693 | if (pkaddr == rec_peak_addr) | ||
694 | rec_peak_addr = end; | ||
695 | |||
696 | set_irq_level(level); | ||
697 | |||
698 | /* save peaks */ | ||
699 | rec_peak_left = MAX(peak_lp, -peak_ln); | ||
700 | rec_peak_right = MAX(peak_rp, -peak_rn); | ||
701 | } | ||
702 | |||
703 | peak_done: | ||
704 | if (left) | ||
705 | *left = rec_peak_left; | ||
706 | |||
707 | if (right) | ||
708 | *right = rec_peak_right; | ||
709 | } /* pcm_calculate_rec_peaks */ | ||
710 | |||
711 | /** | ||
712 | * Select VINL & VINR source: 0=Line-in, 1=FM Radio | ||
713 | */ | ||
714 | /* All use GPIO */ | ||
715 | #if defined(IAUDIO_X5) | ||
716 | #define REC_MUX_BIT (1 << 29) | ||
717 | #define REC_MUX_SET_LINE() or_l(REC_MUX_BIT, &GPIO_OUT) | ||
718 | #define REC_MUX_SET_FM() and_l(~REC_MUX_BIT, &GPIO_OUT) | ||
719 | #else | ||
720 | #if defined(IRIVER_H100_SERIES) | ||
721 | #define REC_MUX_BIT (1 << 23) | ||
722 | #elif defined(IRIVER_H300_SERIES) | ||
723 | #define REC_MUX_BIT (1 << 30) | ||
724 | #endif | ||
725 | #define REC_MUX_SET_LINE() and_l(~REC_MUX_BIT, &GPIO_OUT) | ||
726 | #define REC_MUX_SET_FM() or_l(REC_MUX_BIT, &GPIO_OUT) | ||
727 | #endif | ||
728 | |||
729 | void pcm_rec_mux(int source) | ||
730 | { | ||
731 | if (source == 0) | ||
732 | REC_MUX_SET_LINE(); /* Line In */ | ||
733 | else | ||
734 | REC_MUX_SET_FM(); /* FM radio */ | ||
735 | |||
736 | or_l(REC_MUX_BIT, &GPIO_ENABLE); | ||
737 | or_l(REC_MUX_BIT, &GPIO_FUNCTION); | ||
738 | } /* pcm_rec_mux */ | ||