diff options
author | Jörg Hohensohn <hohensoh@rockbox.org> | 2004-01-05 20:42:51 +0000 |
---|---|---|
committer | Jörg Hohensohn <hohensoh@rockbox.org> | 2004-01-05 20:42:51 +0000 |
commit | f993365447d8dc5bb28c76a003cecd045c3abaf7 (patch) | |
tree | 19d4a2cfebd7e0f43c85559c2e88114fd4ba3223 /firmware/mp3_playback.c | |
parent | 974c2f0d43c1ebc786854f48f15ccaea7803d8f0 (diff) | |
download | rockbox-f993365447d8dc5bb28c76a003cecd045c3abaf7.tar.gz rockbox-f993365447d8dc5bb28c76a003cecd045c3abaf7.zip |
Moved the low-level playback functionality into a new, separate module "mp3_playback". This e.g. allows to export a memory playback API to the plugins, opens the door to games with sound, UI sounds, etc.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4192 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/mp3_playback.c')
-rw-r--r-- | firmware/mp3_playback.c | 939 |
1 files changed, 939 insertions, 0 deletions
diff --git a/firmware/mp3_playback.c b/firmware/mp3_playback.c new file mode 100644 index 0000000000..9ded720248 --- /dev/null +++ b/firmware/mp3_playback.c | |||
@@ -0,0 +1,939 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Code that has been in mpeg.c before, now creating an encapsulated play | ||
11 | * data module, to be used by other sources than file playback as well. | ||
12 | * | ||
13 | * Copyright (C) 2004 by Linus Nielsen Feltzing | ||
14 | * | ||
15 | * All files in this archive are subject to the GNU General Public License. | ||
16 | * See the file COPYING in the source tree root for full license agreement. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | #include <stdbool.h> | ||
23 | #include "config.h" | ||
24 | #include "debug.h" | ||
25 | #include "panic.h" | ||
26 | #include <kernel.h> | ||
27 | #include "mpeg.h" /* ToDo: remove crosslinks */ | ||
28 | #include "mp3_playback.h" | ||
29 | #ifndef SIMULATOR | ||
30 | #include "i2c.h" | ||
31 | #include "mas.h" | ||
32 | #include "dac.h" | ||
33 | #include "system.h" | ||
34 | #include "hwcompat.h" | ||
35 | #endif | ||
36 | |||
37 | static char *units[] = | ||
38 | { | ||
39 | "%", /* Volume */ | ||
40 | "dB", /* Bass */ | ||
41 | "dB", /* Treble */ | ||
42 | "%", /* Balance */ | ||
43 | "dB", /* Loudness */ | ||
44 | "%", /* Bass boost */ | ||
45 | "", /* AVC */ | ||
46 | "", /* Channels */ | ||
47 | "dB", /* Left gain */ | ||
48 | "dB", /* Right gain */ | ||
49 | "dB", /* Mic gain */ | ||
50 | }; | ||
51 | |||
52 | static int numdecimals[] = | ||
53 | { | ||
54 | 0, /* Volume */ | ||
55 | 0, /* Bass */ | ||
56 | 0, /* Treble */ | ||
57 | 0, /* Balance */ | ||
58 | 0, /* Loudness */ | ||
59 | 0, /* Bass boost */ | ||
60 | 0, /* AVC */ | ||
61 | 0, /* Channels */ | ||
62 | 1, /* Left gain */ | ||
63 | 1, /* Right gain */ | ||
64 | 1, /* Mic gain */ | ||
65 | }; | ||
66 | |||
67 | static int minval[] = | ||
68 | { | ||
69 | 0, /* Volume */ | ||
70 | 0, /* Bass */ | ||
71 | 0, /* Treble */ | ||
72 | -50, /* Balance */ | ||
73 | 0, /* Loudness */ | ||
74 | 0, /* Bass boost */ | ||
75 | -1, /* AVC */ | ||
76 | 0, /* Channels */ | ||
77 | 0, /* Left gain */ | ||
78 | 0, /* Right gain */ | ||
79 | 0, /* Mic gain */ | ||
80 | }; | ||
81 | |||
82 | static int maxval[] = | ||
83 | { | ||
84 | 100, /* Volume */ | ||
85 | #ifdef HAVE_MAS3587F | ||
86 | 24, /* Bass */ | ||
87 | 24, /* Treble */ | ||
88 | #else | ||
89 | 30, /* Bass */ | ||
90 | 30, /* Treble */ | ||
91 | #endif | ||
92 | 50, /* Balance */ | ||
93 | 17, /* Loudness */ | ||
94 | 10, /* Bass boost */ | ||
95 | 3, /* AVC */ | ||
96 | 6, /* Channels */ | ||
97 | 15, /* Left gain */ | ||
98 | 15, /* Right gain */ | ||
99 | 15, /* Mic gain */ | ||
100 | }; | ||
101 | |||
102 | static int defaultval[] = | ||
103 | { | ||
104 | 70, /* Volume */ | ||
105 | #ifdef HAVE_MAS3587F | ||
106 | 12+6, /* Bass */ | ||
107 | 12+6, /* Treble */ | ||
108 | #else | ||
109 | 15+7, /* Bass */ | ||
110 | 15+7, /* Treble */ | ||
111 | #endif | ||
112 | 0, /* Balance */ | ||
113 | 0, /* Loudness */ | ||
114 | 0, /* Bass boost */ | ||
115 | 0, /* AVC */ | ||
116 | 0, /* Channels */ | ||
117 | 8, /* Left gain */ | ||
118 | 8, /* Right gain */ | ||
119 | 2, /* Mic gain */ | ||
120 | }; | ||
121 | |||
122 | char *mpeg_sound_unit(int setting) | ||
123 | { | ||
124 | return units[setting]; | ||
125 | } | ||
126 | |||
127 | int mpeg_sound_numdecimals(int setting) | ||
128 | { | ||
129 | return numdecimals[setting]; | ||
130 | } | ||
131 | |||
132 | int mpeg_sound_min(int setting) | ||
133 | { | ||
134 | return minval[setting]; | ||
135 | } | ||
136 | |||
137 | int mpeg_sound_max(int setting) | ||
138 | { | ||
139 | return maxval[setting]; | ||
140 | } | ||
141 | |||
142 | int mpeg_sound_default(int setting) | ||
143 | { | ||
144 | return defaultval[setting]; | ||
145 | } | ||
146 | |||
147 | /* list of tracks in memory */ | ||
148 | #define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */ | ||
149 | #define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1) | ||
150 | |||
151 | #ifndef SIMULATOR | ||
152 | static bool mpeg_is_initialized = false; | ||
153 | #endif | ||
154 | |||
155 | #ifndef SIMULATOR | ||
156 | |||
157 | unsigned long mas_version_code; | ||
158 | |||
159 | #ifdef HAVE_MAS3507D | ||
160 | |||
161 | static unsigned int bass_table[] = | ||
162 | { | ||
163 | 0x9e400, /* -15dB */ | ||
164 | 0xa2800, /* -14dB */ | ||
165 | 0xa7400, /* -13dB */ | ||
166 | 0xac400, /* -12dB */ | ||
167 | 0xb1800, /* -11dB */ | ||
168 | 0xb7400, /* -10dB */ | ||
169 | 0xbd400, /* -9dB */ | ||
170 | 0xc3c00, /* -8dB */ | ||
171 | 0xca400, /* -7dB */ | ||
172 | 0xd1800, /* -6dB */ | ||
173 | 0xd8c00, /* -5dB */ | ||
174 | 0xe0400, /* -4dB */ | ||
175 | 0xe8000, /* -3dB */ | ||
176 | 0xefc00, /* -2dB */ | ||
177 | 0xf7c00, /* -1dB */ | ||
178 | 0, | ||
179 | 0x800, /* 1dB */ | ||
180 | 0x10000, /* 2dB */ | ||
181 | 0x17c00, /* 3dB */ | ||
182 | 0x1f800, /* 4dB */ | ||
183 | 0x27000, /* 5dB */ | ||
184 | 0x2e400, /* 6dB */ | ||
185 | 0x35800, /* 7dB */ | ||
186 | 0x3c000, /* 8dB */ | ||
187 | 0x42800, /* 9dB */ | ||
188 | 0x48800, /* 10dB */ | ||
189 | 0x4e400, /* 11dB */ | ||
190 | 0x53800, /* 12dB */ | ||
191 | 0x58800, /* 13dB */ | ||
192 | 0x5d400, /* 14dB */ | ||
193 | 0x61800 /* 15dB */ | ||
194 | }; | ||
195 | |||
196 | static unsigned int treble_table[] = | ||
197 | { | ||
198 | 0xb2c00, /* -15dB */ | ||
199 | 0xbb400, /* -14dB */ | ||
200 | 0xc1800, /* -13dB */ | ||
201 | 0xc6c00, /* -12dB */ | ||
202 | 0xcbc00, /* -11dB */ | ||
203 | 0xd0400, /* -10dB */ | ||
204 | 0xd5000, /* -9dB */ | ||
205 | 0xd9800, /* -8dB */ | ||
206 | 0xde000, /* -7dB */ | ||
207 | 0xe2800, /* -6dB */ | ||
208 | 0xe7e00, /* -5dB */ | ||
209 | 0xec000, /* -4dB */ | ||
210 | 0xf0c00, /* -3dB */ | ||
211 | 0xf5c00, /* -2dB */ | ||
212 | 0xfac00, /* -1dB */ | ||
213 | 0, | ||
214 | 0x5400, /* 1dB */ | ||
215 | 0xac00, /* 2dB */ | ||
216 | 0x10400, /* 3dB */ | ||
217 | 0x16000, /* 4dB */ | ||
218 | 0x1c000, /* 5dB */ | ||
219 | 0x22400, /* 6dB */ | ||
220 | 0x28400, /* 7dB */ | ||
221 | 0x2ec00, /* 8dB */ | ||
222 | 0x35400, /* 9dB */ | ||
223 | 0x3c000, /* 10dB */ | ||
224 | 0x42c00, /* 11dB */ | ||
225 | 0x49c00, /* 12dB */ | ||
226 | 0x51800, /* 13dB */ | ||
227 | 0x58400, /* 14dB */ | ||
228 | 0x5f800 /* 15dB */ | ||
229 | }; | ||
230 | |||
231 | static unsigned int prescale_table[] = | ||
232 | { | ||
233 | 0x80000, /* 0db */ | ||
234 | 0x8e000, /* 1dB */ | ||
235 | 0x9a400, /* 2dB */ | ||
236 | 0xa5800, /* 3dB */ | ||
237 | 0xaf400, /* 4dB */ | ||
238 | 0xb8000, /* 5dB */ | ||
239 | 0xbfc00, /* 6dB */ | ||
240 | 0xc6c00, /* 7dB */ | ||
241 | 0xcd000, /* 8dB */ | ||
242 | 0xd25c0, /* 9dB */ | ||
243 | 0xd7800, /* 10dB */ | ||
244 | 0xdc000, /* 11dB */ | ||
245 | 0xdfc00, /* 12dB */ | ||
246 | 0xe3400, /* 13dB */ | ||
247 | 0xe6800, /* 14dB */ | ||
248 | 0xe9400 /* 15dB */ | ||
249 | }; | ||
250 | #endif | ||
251 | |||
252 | bool dma_on; /* The DMA is active */ | ||
253 | |||
254 | #ifdef HAVE_MAS3507D | ||
255 | static void mas_poll_start(int interval_in_ms) | ||
256 | { | ||
257 | unsigned int count; | ||
258 | |||
259 | count = (FREQ * interval_in_ms) / 1000 / 8; | ||
260 | |||
261 | if(count > 0xffff) | ||
262 | { | ||
263 | panicf("Error! The MAS poll interval is too long (%d ms)\n", | ||
264 | interval_in_ms); | ||
265 | return; | ||
266 | } | ||
267 | |||
268 | /* We are using timer 1 */ | ||
269 | |||
270 | TSTR &= ~0x02; /* Stop the timer */ | ||
271 | TSNC &= ~0x02; /* No synchronization */ | ||
272 | TMDR &= ~0x02; /* Operate normally */ | ||
273 | |||
274 | TCNT1 = 0; /* Start counting at 0 */ | ||
275 | GRA1 = count; | ||
276 | TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */ | ||
277 | |||
278 | /* Enable interrupt on level 5 */ | ||
279 | IPRC = (IPRC & ~0x000f) | 0x0005; | ||
280 | |||
281 | TSR1 &= ~0x02; | ||
282 | TIER1 = 0xf9; /* Enable GRA match interrupt */ | ||
283 | |||
284 | TSTR |= 0x02; /* Start timer 1 */ | ||
285 | } | ||
286 | #endif | ||
287 | |||
288 | /* the registered callback function ta ask for more mp3 data */ | ||
289 | static void (*callback_for_more)(unsigned char**, int*); | ||
290 | |||
291 | #pragma interrupt | ||
292 | void DEI3(void) | ||
293 | { | ||
294 | unsigned char* start; | ||
295 | int size = 0; | ||
296 | |||
297 | if (callback_for_more != NULL) | ||
298 | { | ||
299 | callback_for_more(&start, &size); | ||
300 | } | ||
301 | |||
302 | if (size > 0) | ||
303 | { | ||
304 | DTCR3 = size & 0xffff; | ||
305 | SAR3 = (unsigned int) start; | ||
306 | } | ||
307 | else | ||
308 | { | ||
309 | CHCR3 &= ~0x0001; /* Disable the DMA interrupt */ | ||
310 | } | ||
311 | |||
312 | CHCR3 &= ~0x0002; /* Clear DMA interrupt */ | ||
313 | } | ||
314 | |||
315 | #pragma interrupt | ||
316 | void IRQ6(void) /* PB14: MAS stop demand IRQ */ | ||
317 | { | ||
318 | mp3_play_pause(false); | ||
319 | } | ||
320 | |||
321 | static void setup_sci0(void) | ||
322 | { | ||
323 | /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */ | ||
324 | PBCR1 = (PBCR1 & 0x0cff) | 0x1208; | ||
325 | |||
326 | /* Set PB12 to output */ | ||
327 | or_b(0x10, &PBIORH); | ||
328 | |||
329 | /* Disable serial port */ | ||
330 | SCR0 = 0x00; | ||
331 | |||
332 | /* Synchronous, no prescale */ | ||
333 | SMR0 = 0x80; | ||
334 | |||
335 | /* Set baudrate 1Mbit/s */ | ||
336 | BRR0 = 0x03; | ||
337 | |||
338 | /* use SCK as serial clock output */ | ||
339 | SCR0 = 0x01; | ||
340 | |||
341 | /* Clear FER and PER */ | ||
342 | SSR0 &= 0xe7; | ||
343 | |||
344 | /* Set interrupt ITU2 and SCI0 priority to 0 */ | ||
345 | IPRD &= 0x0ff0; | ||
346 | |||
347 | /* set PB15 and PB14 to inputs */ | ||
348 | and_b(~0x80, &PBIORH); | ||
349 | and_b(~0x40, &PBIORH); | ||
350 | |||
351 | /* Enable End of DMA interrupt at prio 8 */ | ||
352 | IPRC = (IPRC & 0xf0ff) | 0x0800; | ||
353 | |||
354 | /* Enable Tx (only!) */ | ||
355 | SCR0 |= 0x20; | ||
356 | } | ||
357 | #endif /* SIMULATOR */ | ||
358 | |||
359 | #ifdef HAVE_MAS3587F | ||
360 | static void init_playback(void) | ||
361 | { | ||
362 | unsigned long val; | ||
363 | int rc; | ||
364 | |||
365 | mp3_play_pause(false); | ||
366 | |||
367 | mas_reset(); | ||
368 | |||
369 | /* Enable the audio CODEC and the DSP core, max analog voltage range */ | ||
370 | rc = mas_direct_config_write(MAS_CONTROL, 0x8c00); | ||
371 | if(rc < 0) | ||
372 | panicf("mas_ctrl_w: %d", rc); | ||
373 | |||
374 | /* Stop the current application */ | ||
375 | val = 0; | ||
376 | mas_writemem(MAS_BANK_D0,0x7f6,&val,1); | ||
377 | do | ||
378 | { | ||
379 | mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1); | ||
380 | } while(val); | ||
381 | |||
382 | /* Enable the D/A Converter */ | ||
383 | mas_codec_writereg(0x0, 0x0001); | ||
384 | |||
385 | /* ADC scale 0%, DSP scale 100% */ | ||
386 | mas_codec_writereg(6, 0x0000); | ||
387 | mas_codec_writereg(7, 0x4000); | ||
388 | |||
389 | /* Disable SDO and SDI */ | ||
390 | val = 0x0d; | ||
391 | mas_writemem(MAS_BANK_D0,0x7f2,&val,1); | ||
392 | |||
393 | /* Set Demand mode and validate all settings */ | ||
394 | val = 0x25; | ||
395 | mas_writemem(MAS_BANK_D0,0x7f1,&val,1); | ||
396 | |||
397 | /* Start the Layer2/3 decoder applications */ | ||
398 | val = 0x0c; | ||
399 | mas_writemem(MAS_BANK_D0,0x7f6,&val,1); | ||
400 | do | ||
401 | { | ||
402 | mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1); | ||
403 | } while((val & 0x0c) != 0x0c); | ||
404 | |||
405 | mpeg_sound_channel_config(MPEG_SOUND_STEREO); | ||
406 | |||
407 | /* set IRQ6 to edge detect */ | ||
408 | ICR |= 0x02; | ||
409 | |||
410 | /* set IRQ6 prio 8 */ | ||
411 | IPRB = ( IPRB & 0xff0f ) | 0x0080; | ||
412 | |||
413 | DEBUGF("MAS Decoding application started\n"); | ||
414 | } | ||
415 | #endif /* #ifdef HAVE_MAS3587F */ | ||
416 | |||
417 | #ifndef SIMULATOR | ||
418 | #ifdef HAVE_MAS3507D | ||
419 | int current_left_volume = 0; /* all values in tenth of dB */ | ||
420 | int current_right_volume = 0; /* all values in tenth of dB */ | ||
421 | int current_treble = 0; | ||
422 | int current_bass = 0; | ||
423 | int current_balance = 0; | ||
424 | |||
425 | /* convert tenth of dB volume to register value */ | ||
426 | static int tenthdb2reg(int db) { | ||
427 | if (db < -540) | ||
428 | return (db + 780) / 30; | ||
429 | else | ||
430 | return (db + 660) / 15; | ||
431 | } | ||
432 | |||
433 | void set_prescaled_volume(void) | ||
434 | { | ||
435 | int prescale; | ||
436 | int l, r; | ||
437 | |||
438 | prescale = MAX(current_bass, current_treble); | ||
439 | if (prescale < 0) | ||
440 | prescale = 0; /* no need to prescale if we don't boost | ||
441 | bass or treble */ | ||
442 | |||
443 | mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]); | ||
444 | |||
445 | /* gain up the analog volume to compensate the prescale reduction gain */ | ||
446 | l = current_left_volume + prescale; | ||
447 | r = current_right_volume + prescale; | ||
448 | |||
449 | dac_volume(tenthdb2reg(l), tenthdb2reg(r), false); | ||
450 | } | ||
451 | #endif /* HAVE_MAS3507D */ | ||
452 | #endif /* !SIMULATOR */ | ||
453 | |||
454 | void mpeg_sound_set(int setting, int value) | ||
455 | { | ||
456 | #ifdef SIMULATOR | ||
457 | setting = value; | ||
458 | #else | ||
459 | #ifdef HAVE_MAS3507D | ||
460 | int l, r; | ||
461 | #else | ||
462 | int tmp; | ||
463 | #endif | ||
464 | |||
465 | if(!mpeg_is_initialized) | ||
466 | return; | ||
467 | |||
468 | switch(setting) | ||
469 | { | ||
470 | case SOUND_VOLUME: | ||
471 | #ifdef HAVE_MAS3587F | ||
472 | tmp = 0x7f00 * value / 100; | ||
473 | mas_codec_writereg(0x10, tmp & 0xff00); | ||
474 | #else | ||
475 | l = value; | ||
476 | r = value; | ||
477 | |||
478 | if(current_balance > 0) | ||
479 | { | ||
480 | l -= current_balance; | ||
481 | if(l < 0) | ||
482 | l = 0; | ||
483 | } | ||
484 | |||
485 | if(current_balance < 0) | ||
486 | { | ||
487 | r += current_balance; | ||
488 | if(r < 0) | ||
489 | r = 0; | ||
490 | } | ||
491 | |||
492 | l = 0x38 * l / 100; | ||
493 | r = 0x38 * r / 100; | ||
494 | |||
495 | /* store volume in tenth of dB */ | ||
496 | current_left_volume = ( l < 0x08 ? l*30 - 780 : l*15 - 660 ); | ||
497 | current_right_volume = ( r < 0x08 ? r*30 - 780 : r*15 - 660 ); | ||
498 | |||
499 | set_prescaled_volume(); | ||
500 | #endif | ||
501 | break; | ||
502 | |||
503 | case SOUND_BALANCE: | ||
504 | #ifdef HAVE_MAS3587F | ||
505 | tmp = ((value * 127 / 100) & 0xff) << 8; | ||
506 | mas_codec_writereg(0x11, tmp & 0xff00); | ||
507 | #else | ||
508 | /* Convert to percent */ | ||
509 | current_balance = value * 2; | ||
510 | #endif | ||
511 | break; | ||
512 | |||
513 | case SOUND_BASS: | ||
514 | #ifdef HAVE_MAS3587F | ||
515 | tmp = (((value-12) * 8) & 0xff) << 8; | ||
516 | mas_codec_writereg(0x14, tmp & 0xff00); | ||
517 | #else | ||
518 | mas_writereg(MAS_REG_KBASS, bass_table[value]); | ||
519 | current_bass = (value-15) * 10; | ||
520 | set_prescaled_volume(); | ||
521 | #endif | ||
522 | break; | ||
523 | |||
524 | case SOUND_TREBLE: | ||
525 | #ifdef HAVE_MAS3587F | ||
526 | tmp = (((value-12) * 8) & 0xff) << 8; | ||
527 | mas_codec_writereg(0x15, tmp & 0xff00); | ||
528 | #else | ||
529 | mas_writereg(MAS_REG_KTREBLE, treble_table[value]); | ||
530 | current_treble = (value-15) * 10; | ||
531 | set_prescaled_volume(); | ||
532 | #endif | ||
533 | break; | ||
534 | |||
535 | #ifdef HAVE_MAS3587F | ||
536 | case SOUND_SUPERBASS: | ||
537 | if (value) { | ||
538 | tmp = MAX(MIN(value * 12, 0x7f), 0); | ||
539 | mas_codec_writereg(MAS_REG_KMDB_STR, (tmp & 0xff) << 8); | ||
540 | tmp = 0x30; /* MDB_HAR: Space for experiment here */ | ||
541 | mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0xff) << 8); | ||
542 | tmp = 60 / 10; /* calculate MDB_FC, 60hz - experiment here, | ||
543 | this would depend on the earphones... | ||
544 | perhaps make it tunable? */ | ||
545 | mas_codec_writereg(MAS_REG_KMDB_FC, (tmp & 0xff) << 8); | ||
546 | tmp = (3 * tmp) / 2; /* calculate MDB_SHAPE */ | ||
547 | mas_codec_writereg(MAS_REG_KMDB_SWITCH, | ||
548 | ((tmp & 0xff) << 8) /* MDB_SHAPE */ | ||
549 | | 2); /* MDB_SWITCH enable */ | ||
550 | } else { | ||
551 | mas_codec_writereg(MAS_REG_KMDB_STR, 0); | ||
552 | mas_codec_writereg(MAS_REG_KMDB_HAR, 0); | ||
553 | mas_codec_writereg(MAS_REG_KMDB_SWITCH, 0); /* MDB_SWITCH disable */ | ||
554 | } | ||
555 | break; | ||
556 | |||
557 | case SOUND_LOUDNESS: | ||
558 | tmp = MAX(MIN(value * 4, 0x44), 0); | ||
559 | mas_codec_writereg(MAS_REG_KLOUDNESS, (tmp & 0xff) << 8); | ||
560 | break; | ||
561 | |||
562 | case SOUND_AVC: | ||
563 | switch (value) { | ||
564 | case 1: /* 2s */ | ||
565 | tmp = (0x2 << 8) | (0x8 << 12); | ||
566 | break; | ||
567 | case 2: /* 4s */ | ||
568 | tmp = (0x4 << 8) | (0x8 << 12); | ||
569 | break; | ||
570 | case 3: /* 8s */ | ||
571 | tmp = (0x8 << 8) | (0x8 << 12); | ||
572 | break; | ||
573 | case -1: /* turn off and then turn on again to decay quickly */ | ||
574 | tmp = mas_codec_readreg(MAS_REG_KAVC); | ||
575 | mas_codec_writereg(MAS_REG_KAVC, 0); | ||
576 | break; | ||
577 | default: /* off */ | ||
578 | tmp = 0; | ||
579 | break; | ||
580 | } | ||
581 | mas_codec_writereg(MAS_REG_KAVC, tmp); | ||
582 | break; | ||
583 | #endif | ||
584 | case SOUND_CHANNELS: | ||
585 | mpeg_sound_channel_config(value); | ||
586 | break; | ||
587 | } | ||
588 | #endif /* SIMULATOR */ | ||
589 | } | ||
590 | |||
591 | int mpeg_val2phys(int setting, int value) | ||
592 | { | ||
593 | int result = 0; | ||
594 | |||
595 | switch(setting) | ||
596 | { | ||
597 | case SOUND_VOLUME: | ||
598 | result = value; | ||
599 | break; | ||
600 | |||
601 | case SOUND_BALANCE: | ||
602 | result = value * 2; | ||
603 | break; | ||
604 | |||
605 | case SOUND_BASS: | ||
606 | #ifdef HAVE_MAS3587F | ||
607 | result = value - 12; | ||
608 | #else | ||
609 | result = value - 15; | ||
610 | #endif | ||
611 | break; | ||
612 | |||
613 | case SOUND_TREBLE: | ||
614 | #ifdef HAVE_MAS3587F | ||
615 | result = value - 12; | ||
616 | #else | ||
617 | result = value - 15; | ||
618 | #endif | ||
619 | break; | ||
620 | |||
621 | #ifdef HAVE_MAS3587F | ||
622 | case SOUND_LOUDNESS: | ||
623 | result = value; | ||
624 | break; | ||
625 | |||
626 | case SOUND_SUPERBASS: | ||
627 | result = value * 10; | ||
628 | break; | ||
629 | |||
630 | case SOUND_LEFT_GAIN: | ||
631 | case SOUND_RIGHT_GAIN: | ||
632 | result = (value - 2) * 15; | ||
633 | break; | ||
634 | |||
635 | case SOUND_MIC_GAIN: | ||
636 | result = value * 15 + 210; | ||
637 | break; | ||
638 | #endif | ||
639 | } | ||
640 | return result; | ||
641 | } | ||
642 | |||
643 | int mpeg_phys2val(int setting, int value) | ||
644 | { | ||
645 | int result = 0; | ||
646 | |||
647 | switch(setting) | ||
648 | { | ||
649 | case SOUND_VOLUME: | ||
650 | result = value; | ||
651 | break; | ||
652 | |||
653 | case SOUND_BALANCE: | ||
654 | result = value / 2; | ||
655 | break; | ||
656 | |||
657 | case SOUND_BASS: | ||
658 | #ifdef HAVE_MAS3587F | ||
659 | result = value + 12; | ||
660 | #else | ||
661 | result = value + 15; | ||
662 | #endif | ||
663 | break; | ||
664 | |||
665 | case SOUND_TREBLE: | ||
666 | #ifdef HAVE_MAS3587F | ||
667 | result = value + 12; | ||
668 | #else | ||
669 | result = value + 15; | ||
670 | #endif | ||
671 | break; | ||
672 | |||
673 | #ifdef HAVE_MAS3587F | ||
674 | case SOUND_SUPERBASS: | ||
675 | result = value / 10; | ||
676 | break; | ||
677 | |||
678 | case SOUND_LOUDNESS: | ||
679 | case SOUND_AVC: | ||
680 | case SOUND_LEFT_GAIN: | ||
681 | case SOUND_RIGHT_GAIN: | ||
682 | case SOUND_MIC_GAIN: | ||
683 | result = value; | ||
684 | break; | ||
685 | #endif | ||
686 | } | ||
687 | |||
688 | return result; | ||
689 | } | ||
690 | |||
691 | |||
692 | void mpeg_sound_channel_config(int configuration) | ||
693 | { | ||
694 | #ifdef SIMULATOR | ||
695 | (void)configuration; | ||
696 | #else | ||
697 | unsigned long val_ll = 0x80000; | ||
698 | unsigned long val_lr = 0; | ||
699 | unsigned long val_rl = 0; | ||
700 | unsigned long val_rr = 0x80000; | ||
701 | |||
702 | switch(configuration) | ||
703 | { | ||
704 | case MPEG_SOUND_STEREO: | ||
705 | val_ll = 0x80000; | ||
706 | val_lr = 0; | ||
707 | val_rl = 0; | ||
708 | val_rr = 0x80000; | ||
709 | break; | ||
710 | |||
711 | case MPEG_SOUND_MONO: | ||
712 | val_ll = 0xc0000; | ||
713 | val_lr = 0xc0000; | ||
714 | val_rl = 0xc0000; | ||
715 | val_rr = 0xc0000; | ||
716 | break; | ||
717 | |||
718 | case MPEG_SOUND_MONO_LEFT: | ||
719 | val_ll = 0x80000; | ||
720 | val_lr = 0x80000; | ||
721 | val_rl = 0; | ||
722 | val_rr = 0; | ||
723 | break; | ||
724 | |||
725 | case MPEG_SOUND_MONO_RIGHT: | ||
726 | val_ll = 0; | ||
727 | val_lr = 0; | ||
728 | val_rl = 0x80000; | ||
729 | val_rr = 0x80000; | ||
730 | break; | ||
731 | |||
732 | case MPEG_SOUND_STEREO_NARROW: | ||
733 | val_ll = 0xa0000; | ||
734 | val_lr = 0xe0000; | ||
735 | val_rl = 0xe0000; | ||
736 | val_rr = 0xa0000; | ||
737 | break; | ||
738 | |||
739 | case MPEG_SOUND_STEREO_WIDE: | ||
740 | val_ll = 0x80000; | ||
741 | val_lr = 0x40000; | ||
742 | val_rl = 0x40000; | ||
743 | val_rr = 0x80000; | ||
744 | break; | ||
745 | |||
746 | case MPEG_SOUND_KARAOKE: | ||
747 | val_ll = 0x80001; | ||
748 | val_lr = 0x7ffff; | ||
749 | val_rl = 0x7ffff; | ||
750 | val_rr = 0x80001; | ||
751 | break; | ||
752 | } | ||
753 | |||
754 | #ifdef HAVE_MAS3587F | ||
755 | mas_writemem(MAS_BANK_D0, 0x7fc, &val_ll, 1); /* LL */ | ||
756 | mas_writemem(MAS_BANK_D0, 0x7fd, &val_lr, 1); /* LR */ | ||
757 | mas_writemem(MAS_BANK_D0, 0x7fe, &val_rl, 1); /* RL */ | ||
758 | mas_writemem(MAS_BANK_D0, 0x7ff, &val_rr, 1); /* RR */ | ||
759 | #else | ||
760 | mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */ | ||
761 | mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */ | ||
762 | mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */ | ||
763 | mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */ | ||
764 | #endif | ||
765 | #endif | ||
766 | } | ||
767 | |||
768 | #ifdef HAVE_MAS3587F | ||
769 | /* This function works by telling the decoder that we have another | ||
770 | crystal frequency than we actually have. It will adjust its internal | ||
771 | parameters and the result is that the audio is played at another pitch. | ||
772 | |||
773 | The pitch value is in tenths of percent. | ||
774 | */ | ||
775 | void mpeg_set_pitch(int pitch) | ||
776 | { | ||
777 | unsigned long val; | ||
778 | |||
779 | /* invert pitch value */ | ||
780 | pitch = 1000000/pitch; | ||
781 | |||
782 | /* Calculate the new (bogus) frequency */ | ||
783 | val = 18432*pitch/1000; | ||
784 | |||
785 | mas_writemem(MAS_BANK_D0,0x7f3,&val,1); | ||
786 | |||
787 | /* We must tell the MAS that the frequency has changed. | ||
788 | This will unfortunately cause a short silence. */ | ||
789 | val = 0x25; | ||
790 | mas_writemem(MAS_BANK_D0,0x7f1,&val,1); | ||
791 | } | ||
792 | #endif | ||
793 | |||
794 | void mp3_init(int volume, int bass, int treble, int balance, int loudness, | ||
795 | int bass_boost, int avc, int channel_config) | ||
796 | { | ||
797 | #ifdef SIMULATOR | ||
798 | volume = bass = treble = balance = loudness | ||
799 | = bass_boost = avc = channel_config; | ||
800 | #else | ||
801 | #ifdef HAVE_MAS3507D | ||
802 | unsigned long val; | ||
803 | loudness = bass_boost = avc; | ||
804 | #endif | ||
805 | |||
806 | setup_sci0(); | ||
807 | |||
808 | #ifdef HAVE_MAS3587F | ||
809 | or_b(0x08, &PAIORH); /* output for /PR */ | ||
810 | init_playback(); | ||
811 | |||
812 | mas_version_code = mas_readver(); | ||
813 | DEBUGF("MAS3587 derivate %d, version B%d\n", | ||
814 | (mas_version_code & 0xff00) >> 8, mas_version_code & 0xff); | ||
815 | #endif | ||
816 | |||
817 | #ifdef HAVE_DAC3550A | ||
818 | dac_init(); | ||
819 | #endif | ||
820 | |||
821 | #ifdef HAVE_MAS3507D | ||
822 | and_b(~0x20, &PBDRL); | ||
823 | sleep(HZ/5); | ||
824 | or_b(0x20, &PBDRL); | ||
825 | sleep(HZ/5); | ||
826 | |||
827 | /* set IRQ6 to edge detect */ | ||
828 | ICR |= 0x02; | ||
829 | |||
830 | /* set IRQ6 prio 8 */ | ||
831 | IPRB = ( IPRB & 0xff0f ) | 0x0080; | ||
832 | |||
833 | mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1); | ||
834 | |||
835 | mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */ | ||
836 | mas_run(1); | ||
837 | sleep(HZ); | ||
838 | |||
839 | /* Clear the upper 12 bits of the 32-bit samples */ | ||
840 | mas_writereg(0xc5, 0); | ||
841 | mas_writereg(0xc6, 0); | ||
842 | |||
843 | /* We need to set the PLL for a 14.1318MHz crystal */ | ||
844 | if(mas_version_code == 0x0601) /* Version F10? */ | ||
845 | { | ||
846 | val = 0x5d9d0; | ||
847 | mas_writemem(MAS_BANK_D0, 0x32d, &val, 1); | ||
848 | val = 0xfffceceb; | ||
849 | mas_writemem(MAS_BANK_D0, 0x32e, &val, 1); | ||
850 | val = 0x0; | ||
851 | mas_writemem(MAS_BANK_D0, 0x32f, &val, 1); | ||
852 | mas_run(0x475); | ||
853 | } | ||
854 | else | ||
855 | { | ||
856 | val = 0x5d9d0; | ||
857 | mas_writemem(MAS_BANK_D0, 0x36d, &val, 1); | ||
858 | val = 0xfffceceb; | ||
859 | mas_writemem(MAS_BANK_D0, 0x36e, &val, 1); | ||
860 | val = 0x0; | ||
861 | mas_writemem(MAS_BANK_D0, 0x36f, &val, 1); | ||
862 | mas_run(0xfcb); | ||
863 | } | ||
864 | |||
865 | #endif | ||
866 | |||
867 | #ifdef HAVE_MAS3507D | ||
868 | mas_poll_start(1); | ||
869 | |||
870 | mas_writereg(MAS_REG_KPRESCALE, 0xe9400); | ||
871 | dac_enable(true); | ||
872 | |||
873 | mpeg_sound_channel_config(channel_config); | ||
874 | #endif | ||
875 | |||
876 | #ifdef HAVE_MAS3587F | ||
877 | ICR &= ~0x0010; /* IRQ3 level sensitive */ | ||
878 | PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */ | ||
879 | #endif | ||
880 | |||
881 | /* Must be done before calling mpeg_sound_set() */ | ||
882 | mpeg_is_initialized = true; | ||
883 | |||
884 | mpeg_sound_set(SOUND_BASS, bass); | ||
885 | mpeg_sound_set(SOUND_TREBLE, treble); | ||
886 | mpeg_sound_set(SOUND_BALANCE, balance); | ||
887 | mpeg_sound_set(SOUND_VOLUME, volume); | ||
888 | |||
889 | #ifdef HAVE_MAS3587F | ||
890 | mpeg_sound_channel_config(channel_config); | ||
891 | mpeg_sound_set(SOUND_LOUDNESS, loudness); | ||
892 | mpeg_sound_set(SOUND_SUPERBASS, bass_boost); | ||
893 | mpeg_sound_set(SOUND_AVC, avc); | ||
894 | #endif | ||
895 | #endif /* !SIMULATOR */ | ||
896 | } | ||
897 | |||
898 | |||
899 | /* new functions, to be exported to plugin API */ | ||
900 | |||
901 | void mp3_play_init(void) | ||
902 | { | ||
903 | #ifdef HAVE_MAS3587F | ||
904 | init_playback(); | ||
905 | #endif | ||
906 | callback_for_more = NULL; | ||
907 | } | ||
908 | |||
909 | void mp3_play_data(unsigned char* start, int size, | ||
910 | void (*get_more)(unsigned char** start, int* size) /* callback fn */ | ||
911 | ) | ||
912 | { | ||
913 | /* init DMA */ | ||
914 | DAR3 = 0x5FFFEC3; | ||
915 | CHCR3 &= ~0x0002; /* Clear interrupt */ | ||
916 | CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */ | ||
917 | DMAOR = 0x0001; /* Enable DMA */ | ||
918 | |||
919 | callback_for_more = get_more; | ||
920 | |||
921 | SAR3 = (unsigned int)start; | ||
922 | DTCR3 = size & 0xffff; | ||
923 | |||
924 | CHCR3 |= 0x0001; /* Enable DMA IRQ */ | ||
925 | } | ||
926 | |||
927 | void mp3_play_pause(bool play) | ||
928 | { | ||
929 | if (play) | ||
930 | SCR0 |= 0x80; | ||
931 | else | ||
932 | SCR0 &= 0x7f; | ||
933 | } | ||
934 | |||
935 | void mp3_play_stop(void) | ||
936 | { | ||
937 | mp3_play_pause(false); | ||
938 | CHCR3 &= ~0x0001; /* Disable the DMA interrupt */ | ||
939 | } | ||