We just released 2.3...
[kugel-rb.git] / firmware / mp3_playback.c
blobdd36578c78825c172c89fe270f93c23c31949159
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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.
13 * Copyright (C) 2004 by Linus Nielsen Feltzing
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
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
37 /* hacking into mpeg.c, recording is still there */
38 #if CONFIG_HWCODEC == MAS3587F
39 enum
41 MPEG_DECODER,
42 MPEG_ENCODER
43 } mpeg_mode;
44 #endif /* #ifdef MAS3587F */
46 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
47 extern unsigned long shadow_io_control_main;
48 #endif
50 /**** globals ****/
52 /* own version, independent of mpeg.c */
53 static bool paused; /* playback is paused */
54 static bool playing; /* We are playing an MP3 stream */
56 #ifndef SIMULATOR
57 /* for measuring the play time */
58 static long playstart_tick;
59 static long cumulative_ticks;
61 /* the registered callback function to ask for more mp3 data */
62 static void (*callback_for_more)(unsigned char**, int*);
63 #endif /* #ifndef SIMULATOR */
65 static const char* const units[] =
67 "%", /* Volume */
68 "dB", /* Bass */
69 "dB", /* Treble */
70 "%", /* Balance */
71 "dB", /* Loudness */
72 "", /* AVC */
73 "", /* Channels */
74 "dB", /* Left gain */
75 "dB", /* Right gain */
76 "dB", /* Mic gain */
77 "dB", /* MDB Strength */
78 "%", /* MDB Harmonics */
79 "Hz", /* MDB Center */
80 "Hz", /* MDB Shape */
81 "", /* MDB Enable */
82 "", /* Super bass */
85 static const int numdecimals[] =
87 0, /* Volume */
88 0, /* Bass */
89 0, /* Treble */
90 0, /* Balance */
91 0, /* Loudness */
92 0, /* AVC */
93 0, /* Channels */
94 1, /* Left gain */
95 1, /* Right gain */
96 1, /* Mic gain */
97 0, /* MDB Strength */
98 0, /* MDB Harmonics */
99 0, /* MDB Center */
100 0, /* MDB Shape */
101 0, /* MDB Enable */
102 0, /* Super bass */
105 static const int steps[] =
107 1, /* Volume */
108 1, /* Bass */
109 1, /* Treble */
110 1, /* Balance */
111 1, /* Loudness */
112 1, /* AVC */
113 1, /* Channels */
114 1, /* Left gain */
115 1, /* Right gain */
116 1, /* Mic gain */
117 1, /* MDB Strength */
118 1, /* MDB Harmonics */
119 10, /* MDB Center */
120 10, /* MDB Shape */
121 1, /* MDB Enable */
122 1, /* Super bass */
125 static const int minval[] =
127 0, /* Volume */
128 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
129 -12, /* Bass */
130 -12, /* Treble */
131 #else
132 -15, /* Bass */
133 -15, /* Treble */
134 #endif
135 -100, /* Balance */
136 0, /* Loudness */
137 -1, /* AVC */
138 0, /* Channels */
139 0, /* Left gain */
140 0, /* Right gain */
141 0, /* Mic gain */
142 0, /* MDB Strength */
143 0, /* MDB Harmonics */
144 20, /* MDB Center */
145 50, /* MDB Shape */
146 0, /* MDB Enable */
147 0, /* Super bass */
150 static const int maxval[] =
152 100, /* Volume */
153 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
154 12, /* Bass */
155 12, /* Treble */
156 #else
157 15, /* Bass */
158 15, /* Treble */
159 #endif
160 100, /* Balance */
161 17, /* Loudness */
162 4, /* AVC */
163 6, /* Channels */
164 15, /* Left gain */
165 15, /* Right gain */
166 15, /* Mic gain */
167 127, /* MDB Strength */
168 100, /* MDB Harmonics */
169 300, /* MDB Center */
170 300, /* MDB Shape */
171 1, /* MDB Enable */
172 1, /* Super bass */
175 static const int defaultval[] =
177 70, /* Volume */
178 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
179 6, /* Bass */
180 6, /* Treble */
181 #else
182 7, /* Bass */
183 7, /* Treble */
184 #endif
185 0, /* Balance */
186 0, /* Loudness */
187 0, /* AVC */
188 0, /* Channels */
189 8, /* Left gain */
190 8, /* Right gain */
191 2, /* Mic gain */
192 50, /* MDB Strength */
193 48, /* MDB Harmonics */
194 60, /* MDB Center */
195 90, /* MDB Shape */
196 0, /* MDB Enable */
197 0, /* Super bass */
200 const char *mpeg_sound_unit(int setting)
202 return units[setting];
205 int mpeg_sound_numdecimals(int setting)
207 return numdecimals[setting];
210 int mpeg_sound_steps(int setting)
212 return steps[setting];
215 int mpeg_sound_min(int setting)
217 return minval[setting];
220 int mpeg_sound_max(int setting)
222 return maxval[setting];
225 int mpeg_sound_default(int setting)
227 return defaultval[setting];
230 /* list of tracks in memory */
231 #define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
232 #define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
234 #ifndef SIMULATOR
235 static bool mpeg_is_initialized = false;
236 #endif
238 #ifndef SIMULATOR
240 unsigned long mas_version_code;
242 #if CONFIG_HWCODEC == MAS3507D
244 static const unsigned int bass_table[] =
246 0x9e400, /* -15dB */
247 0xa2800, /* -14dB */
248 0xa7400, /* -13dB */
249 0xac400, /* -12dB */
250 0xb1800, /* -11dB */
251 0xb7400, /* -10dB */
252 0xbd400, /* -9dB */
253 0xc3c00, /* -8dB */
254 0xca400, /* -7dB */
255 0xd1800, /* -6dB */
256 0xd8c00, /* -5dB */
257 0xe0400, /* -4dB */
258 0xe8000, /* -3dB */
259 0xefc00, /* -2dB */
260 0xf7c00, /* -1dB */
262 0x800, /* 1dB */
263 0x10000, /* 2dB */
264 0x17c00, /* 3dB */
265 0x1f800, /* 4dB */
266 0x27000, /* 5dB */
267 0x2e400, /* 6dB */
268 0x35800, /* 7dB */
269 0x3c000, /* 8dB */
270 0x42800, /* 9dB */
271 0x48800, /* 10dB */
272 0x4e400, /* 11dB */
273 0x53800, /* 12dB */
274 0x58800, /* 13dB */
275 0x5d400, /* 14dB */
276 0x61800 /* 15dB */
279 static const unsigned int treble_table[] =
281 0xb2c00, /* -15dB */
282 0xbb400, /* -14dB */
283 0xc1800, /* -13dB */
284 0xc6c00, /* -12dB */
285 0xcbc00, /* -11dB */
286 0xd0400, /* -10dB */
287 0xd5000, /* -9dB */
288 0xd9800, /* -8dB */
289 0xde000, /* -7dB */
290 0xe2800, /* -6dB */
291 0xe7e00, /* -5dB */
292 0xec000, /* -4dB */
293 0xf0c00, /* -3dB */
294 0xf5c00, /* -2dB */
295 0xfac00, /* -1dB */
297 0x5400, /* 1dB */
298 0xac00, /* 2dB */
299 0x10400, /* 3dB */
300 0x16000, /* 4dB */
301 0x1c000, /* 5dB */
302 0x22400, /* 6dB */
303 0x28400, /* 7dB */
304 0x2ec00, /* 8dB */
305 0x35400, /* 9dB */
306 0x3c000, /* 10dB */
307 0x42c00, /* 11dB */
308 0x49c00, /* 12dB */
309 0x51800, /* 13dB */
310 0x58400, /* 14dB */
311 0x5f800 /* 15dB */
314 static const unsigned int prescale_table[] =
316 0x80000, /* 0db */
317 0x8e000, /* 1dB */
318 0x9a400, /* 2dB */
319 0xa5800, /* 3dB */
320 0xaf400, /* 4dB */
321 0xb8000, /* 5dB */
322 0xbfc00, /* 6dB */
323 0xc6c00, /* 7dB */
324 0xcd000, /* 8dB */
325 0xd25c0, /* 9dB */
326 0xd7800, /* 10dB */
327 0xdc000, /* 11dB */
328 0xdfc00, /* 12dB */
329 0xe3400, /* 13dB */
330 0xe6800, /* 14dB */
331 0xe9400 /* 15dB */
333 #endif
335 bool dma_on; /* The DMA is active */
337 #if CONFIG_HWCODEC == MAS3507D
338 static void mas_poll_start(int interval_in_ms)
340 unsigned int count;
342 count = (FREQ * interval_in_ms) / 1000 / 8;
344 if(count > 0xffff)
346 panicf("Error! The MAS poll interval is too long (%d ms)\n",
347 interval_in_ms);
348 return;
351 /* We are using timer 1 */
353 TSTR &= ~0x02; /* Stop the timer */
354 TSNC &= ~0x02; /* No synchronization */
355 TMDR &= ~0x02; /* Operate normally */
357 TCNT1 = 0; /* Start counting at 0 */
358 GRA1 = count;
359 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
361 /* Enable interrupt on level 5 */
362 IPRC = (IPRC & ~0x000f) | 0x0005;
364 TSR1 &= ~0x02;
365 TIER1 = 0xf9; /* Enable GRA match interrupt */
367 TSTR |= 0x02; /* Start timer 1 */
369 #else
370 static void postpone_dma_tick(void)
372 unsigned int count;
374 count = FREQ / 2000 / 8;
376 /* We are using timer 1 */
378 TSTR &= ~0x02; /* Stop the timer */
379 TSNC &= ~0x02; /* No synchronization */
380 TMDR &= ~0x02; /* Operate normally */
382 TCNT1 = 0; /* Start counting at 0 */
383 GRA1 = count;
384 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
386 /* Enable interrupt on level 5 */
387 IPRC = (IPRC & ~0x000f) | 0x0005;
389 TSR1 &= ~0x02;
390 TIER1 = 0xf9; /* Enable GRA match interrupt */
392 TSTR |= 0x02; /* Start timer 1 */
394 #endif
397 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
398 void demand_irq_enable(bool on)
400 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
402 if(on)
404 IPRA = (IPRA & 0xfff0) | 0x000b;
405 ICR &= ~0x0010; /* IRQ3 level sensitive */
407 else
408 IPRA &= 0xfff0;
410 set_irq_level(oldlevel);
412 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
415 void play_tick(void)
417 if(playing && !paused)
419 /* Start DMA if it is disabled and the DEMAND pin is high */
420 if(!(SCR0 & 0x80) && (PBDR & 0x4000))
422 SCR0 |= 0x80;
425 playback_tick(); /* dirty call to mpeg.c */
429 #pragma interrupt
430 void DEI3(void)
432 unsigned char* start;
433 int size = 0;
435 if (callback_for_more != NULL)
437 callback_for_more(&start, &size);
440 if (size > 0)
442 DTCR3 = size & 0xffff;
443 SAR3 = (unsigned int) start;
445 else
447 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
450 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
453 #pragma interrupt
454 void IMIA1(void) /* Timer 1 interrupt */
456 if(playing)
457 play_tick();
458 TSR1 &= ~0x01;
459 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
460 /* Disable interrupt */
461 IPRC &= ~0x000f;
462 #endif
465 #pragma interrupt
466 void IRQ6(void) /* PB14: MAS stop demand IRQ */
468 SCR0 &= ~0x80;
471 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
472 #pragma interrupt
473 void IRQ3(void) /* PA15: MAS demand IRQ */
475 /* Begin with setting the IRQ to edge sensitive */
476 ICR |= 0x0010;
478 #if CONFIG_HWCODEC == MAS3587F
479 if(mpeg_mode == MPEG_ENCODER)
480 rec_tick();
481 else
482 #endif
483 postpone_dma_tick();
485 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
487 static void setup_sci0(void)
489 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
490 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
492 /* Set PB12 to output */
493 or_b(0x10, &PBIORH);
495 /* Disable serial port */
496 SCR0 = 0x00;
498 /* Synchronous, no prescale */
499 SMR0 = 0x80;
501 /* Set baudrate 1Mbit/s */
502 BRR0 = 0x03;
504 /* use SCK as serial clock output */
505 SCR0 = 0x01;
507 /* Clear FER and PER */
508 SSR0 &= 0xe7;
510 /* Set interrupt ITU2 and SCI0 priority to 0 */
511 IPRD &= 0x0ff0;
513 /* set PB15 and PB14 to inputs */
514 and_b(~0x80, &PBIORH);
515 and_b(~0x40, &PBIORH);
517 /* Enable End of DMA interrupt at prio 8 */
518 IPRC = (IPRC & 0xf0ff) | 0x0800;
520 /* Enable Tx (only!) */
521 SCR0 |= 0x20;
523 #endif /* SIMULATOR */
525 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
526 static void init_playback(void)
528 unsigned long val;
529 int rc;
531 mp3_play_pause(false);
533 mas_reset();
535 /* Enable the audio CODEC and the DSP core, max analog voltage range */
536 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
537 if(rc < 0)
538 panicf("mas_ctrl_w: %d", rc);
540 /* Stop the current application */
541 val = 0;
542 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
545 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
546 } while(val);
548 /* Enable the D/A Converter */
549 mas_codec_writereg(0x0, 0x0001);
551 /* ADC scale 0%, DSP scale 100% */
552 mas_codec_writereg(6, 0x0000);
553 mas_codec_writereg(7, 0x4000);
555 #ifdef HAVE_SPDIF_OUT
556 val = 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
557 #else
558 val = 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
559 #endif
560 mas_writemem(MAS_BANK_D0, MAS_D0_INTERFACE_CONTROL, &val, 1);
562 /* Set Demand mode and validate all settings */
563 shadow_io_control_main = 0x25;
564 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
566 /* Start the Layer2/3 decoder applications */
567 val = 0x0c;
568 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
571 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
572 } while((val & 0x0c) != 0x0c);
574 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
576 #if CONFIG_HWCODEC == MAS3587F
577 mpeg_mode = MPEG_DECODER;
578 #endif
580 /* set IRQ6 to edge detect */
581 ICR |= 0x02;
583 /* set IRQ6 prio 8 */
584 IPRB = ( IPRB & 0xff0f ) | 0x0080;
586 DEBUGF("MAS Decoding application started\n");
588 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
590 #ifndef SIMULATOR
591 #if CONFIG_HWCODEC == MAS3507D
592 int current_left_volume = 0; /* all values in tenth of dB */
593 int current_right_volume = 0; /* all values in tenth of dB */
594 int current_treble = 0;
595 int current_bass = 0;
596 int current_balance = 0;
598 /* convert tenth of dB volume to register value */
599 static int tenthdb2reg(int db) {
600 if (db < -540)
601 return (db + 780) / 30;
602 else
603 return (db + 660) / 15;
606 void set_prescaled_volume(void)
608 int prescale;
609 int l, r;
611 prescale = MAX(current_bass, current_treble);
612 if (prescale < 0)
613 prescale = 0; /* no need to prescale if we don't boost
614 bass or treble */
616 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
618 /* gain up the analog volume to compensate the prescale reduction gain */
619 l = current_left_volume + prescale;
620 r = current_right_volume + prescale;
622 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
624 #endif /* MAS3507D */
625 #endif /* !SIMULATOR */
627 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
628 unsigned long mdb_shape_shadow = 0;
629 unsigned long loudness_shadow = 0;
630 #endif
632 void mpeg_sound_set(int setting, int value)
634 #ifdef SIMULATOR
635 setting = value;
636 #else
637 #if CONFIG_HWCODEC == MAS3507D
638 int l, r;
639 #else
640 int tmp;
641 #endif
643 if(!mpeg_is_initialized)
644 return;
646 switch(setting)
648 case SOUND_VOLUME:
649 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
650 tmp = 0x7f00 * value / 100;
651 mas_codec_writereg(0x10, tmp & 0xff00);
652 #else
653 l = value;
654 r = value;
656 if(current_balance > 0)
658 l -= current_balance;
659 if(l < 0)
660 l = 0;
663 if(current_balance < 0)
665 r += current_balance;
666 if(r < 0)
667 r = 0;
670 l = 0x38 * l / 100;
671 r = 0x38 * r / 100;
673 /* store volume in tenth of dB */
674 current_left_volume = ( l < 0x08 ? l*30 - 780 : l*15 - 660 );
675 current_right_volume = ( r < 0x08 ? r*30 - 780 : r*15 - 660 );
677 set_prescaled_volume();
678 #endif
679 break;
681 case SOUND_BALANCE:
682 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
683 tmp = ((value * 127 / 100) & 0xff) << 8;
684 mas_codec_writereg(0x11, tmp & 0xff00);
685 #else
686 current_balance = value;
687 #endif
688 break;
690 case SOUND_BASS:
691 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
692 tmp = ((value * 8) & 0xff) << 8;
693 mas_codec_writereg(0x14, tmp & 0xff00);
694 #else
695 mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
696 current_bass = (value) * 10;
697 set_prescaled_volume();
698 #endif
699 break;
701 case SOUND_TREBLE:
702 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
703 tmp = ((value * 8) & 0xff) << 8;
704 mas_codec_writereg(0x15, tmp & 0xff00);
705 #else
706 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
707 current_treble = (value) * 10;
708 set_prescaled_volume();
709 #endif
710 break;
712 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
713 case SOUND_LOUDNESS:
714 loudness_shadow = (loudness_shadow & 0x04) |
715 (MAX(MIN(value * 4, 0x44), 0) << 8);
716 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
717 break;
719 case SOUND_AVC:
720 switch (value) {
721 case 1: /* 20ms */
722 tmp = (0x1 << 8) | (0x8 << 12);
723 break;
724 case 2: /* 2s */
725 tmp = (0x2 << 8) | (0x8 << 12);
726 break;
727 case 3: /* 4s */
728 tmp = (0x4 << 8) | (0x8 << 12);
729 break;
730 case 4: /* 8s */
731 tmp = (0x8 << 8) | (0x8 << 12);
732 break;
733 case -1: /* turn off and then turn on again to decay quickly */
734 tmp = mas_codec_readreg(MAS_REG_KAVC);
735 mas_codec_writereg(MAS_REG_KAVC, 0);
736 break;
737 default: /* off */
738 tmp = 0;
739 break;
741 mas_codec_writereg(MAS_REG_KAVC, tmp);
742 break;
744 case SOUND_MDB_STRENGTH:
745 mas_codec_writereg(MAS_REG_KMDB_STR, (value & 0x7f) << 8);
746 break;
748 case SOUND_MDB_HARMONICS:
749 tmp = value * 127 / 100;
750 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0x7f) << 8);
751 break;
753 case SOUND_MDB_CENTER:
754 mas_codec_writereg(MAS_REG_KMDB_FC, (value/10) << 8);
755 break;
757 case SOUND_MDB_SHAPE:
758 mdb_shape_shadow = (mdb_shape_shadow & 0x02) | ((value/10) << 8);
759 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
760 break;
762 case SOUND_MDB_ENABLE:
763 mdb_shape_shadow = (mdb_shape_shadow & ~0x02) | (value?2:0);
764 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
765 break;
767 case SOUND_SUPERBASS:
768 loudness_shadow = (loudness_shadow & ~0x04) |
769 (value?4:0);
770 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
771 break;
772 #endif
773 case SOUND_CHANNELS:
774 mpeg_sound_channel_config(value);
775 break;
777 #endif /* SIMULATOR */
780 int mpeg_val2phys(int setting, int value)
782 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
783 int result = 0;
785 switch(setting)
787 case SOUND_LEFT_GAIN:
788 case SOUND_RIGHT_GAIN:
789 result = (value - 2) * 15;
790 break;
792 case SOUND_MIC_GAIN:
793 result = value * 15 + 210;
794 break;
796 default:
797 result = value;
798 break;
800 return result;
801 #else
802 (void)setting;
803 return value;
804 #endif
807 void mpeg_sound_channel_config(int configuration)
809 #ifdef SIMULATOR
810 (void)configuration;
811 #else
812 unsigned long val_ll = 0x80000;
813 unsigned long val_lr = 0;
814 unsigned long val_rl = 0;
815 unsigned long val_rr = 0x80000;
817 switch(configuration)
819 case MPEG_SOUND_STEREO:
820 val_ll = 0x80000;
821 val_lr = 0;
822 val_rl = 0;
823 val_rr = 0x80000;
824 break;
826 case MPEG_SOUND_MONO:
827 val_ll = 0xc0000;
828 val_lr = 0xc0000;
829 val_rl = 0xc0000;
830 val_rr = 0xc0000;
831 break;
833 case MPEG_SOUND_MONO_LEFT:
834 val_ll = 0x80000;
835 val_lr = 0x80000;
836 val_rl = 0;
837 val_rr = 0;
838 break;
840 case MPEG_SOUND_MONO_RIGHT:
841 val_ll = 0;
842 val_lr = 0;
843 val_rl = 0x80000;
844 val_rr = 0x80000;
845 break;
847 case MPEG_SOUND_STEREO_NARROW:
848 val_ll = 0xa0000;
849 val_lr = 0xe0000;
850 val_rl = 0xe0000;
851 val_rr = 0xa0000;
852 break;
854 case MPEG_SOUND_STEREO_WIDE:
855 val_ll = 0x80000;
856 val_lr = 0x40000;
857 val_rl = 0x40000;
858 val_rr = 0x80000;
859 break;
861 case MPEG_SOUND_KARAOKE:
862 val_ll = 0x80001;
863 val_lr = 0x7ffff;
864 val_rl = 0x7ffff;
865 val_rr = 0x80001;
866 break;
869 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
870 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LL, &val_ll, 1); /* LL */
871 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LR, &val_lr, 1); /* LR */
872 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RL, &val_rl, 1); /* RL */
873 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RR, &val_rr, 1); /* RR */
874 #else
875 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
876 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
877 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
878 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
879 #endif
880 #endif
883 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
884 /* This function works by telling the decoder that we have another
885 crystal frequency than we actually have. It will adjust its internal
886 parameters and the result is that the audio is played at another pitch.
888 The pitch value is in tenths of percent.
890 void mpeg_set_pitch(int pitch)
892 unsigned long val;
894 /* invert pitch value */
895 pitch = 1000000/pitch;
897 /* Calculate the new (bogus) frequency */
898 val = 18432*pitch/1000;
900 mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, &val, 1);
902 /* We must tell the MAS that the frequency has changed.
903 This will unfortunately cause a short silence. */
904 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
906 #endif
908 void mp3_init(int volume, int bass, int treble, int balance, int loudness,
909 int avc, int channel_config,
910 int mdb_strength, int mdb_harmonics,
911 int mdb_center, int mdb_shape, bool mdb_enable,
912 bool superbass)
914 #ifdef SIMULATOR
915 (void)volume;
916 (void)bass;
917 (void)treble;
918 (void)balance;
919 (void)loudness;
920 (void)avc;
921 (void)channel_config;
922 (void)mdb_strength;
923 (void)mdb_harmonics;
924 (void)mdb_center;
925 (void)mdb_shape;
926 (void)mdb_enable;
927 (void)superbass;
928 #else
929 #if CONFIG_HWCODEC == MAS3507D
930 unsigned long val;
931 (void)loudness;
932 (void)avc;
933 (void)mdb_strength;
934 (void)mdb_harmonics;
935 (void)mdb_center;
936 (void)mdb_shape;
937 (void)mdb_enable;
938 (void)superbass;
939 #endif
941 setup_sci0();
943 #ifdef HAVE_MAS_SIBI_CONTROL
944 and_b(~0x01, &PBDRH); /* drive SIBI low */
945 or_b(0x01, &PBIORH); /* output for PB8 */
946 #endif
948 #if CONFIG_HWCODEC == MAS3587F
949 or_b(0x08, &PAIORH); /* output for /PR */
950 init_playback();
952 mas_version_code = mas_readver();
953 DEBUGF("MAS3587 derivate %d, version %c%d\n",
954 (mas_version_code & 0xf000) >> 12,
955 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
956 #elif CONFIG_HWCODEC == MAS3539F
957 or_b(0x08, &PAIORH); /* output for /PR */
958 init_playback();
960 mas_version_code = mas_readver();
961 DEBUGF("MAS3539 derivate %d, version %c%d\n",
962 (mas_version_code & 0xf000) >> 12,
963 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
964 #endif
966 #ifdef HAVE_DAC3550A
967 dac_init();
968 #endif
970 #if CONFIG_HWCODEC == MAS3507D
971 and_b(~0x20, &PBDRL);
972 sleep(HZ/5);
973 or_b(0x20, &PBDRL);
974 sleep(HZ/5);
976 /* set IRQ6 to edge detect */
977 ICR |= 0x02;
979 /* set IRQ6 prio 8 */
980 IPRB = ( IPRB & 0xff0f ) | 0x0080;
982 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
984 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
985 mas_run(1);
986 sleep(HZ);
988 /* Clear the upper 12 bits of the 32-bit samples */
989 mas_writereg(0xc5, 0);
990 mas_writereg(0xc6, 0);
992 /* We need to set the PLL for a 14.1318MHz crystal */
993 if(mas_version_code == 0x0601) /* Version F10? */
995 val = 0x5d9d0;
996 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
997 val = 0xfffceceb;
998 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
999 val = 0x0;
1000 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
1001 mas_run(0x475);
1003 else
1005 val = 0x5d9d0;
1006 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
1007 val = 0xfffceceb;
1008 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
1009 val = 0x0;
1010 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
1011 mas_run(0xfcb);
1014 #endif
1016 #if CONFIG_HWCODEC == MAS3507D
1017 mas_poll_start(1);
1019 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
1020 dac_enable(true);
1022 mpeg_sound_channel_config(channel_config);
1023 #endif
1025 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1026 ICR &= ~0x0010; /* IRQ3 level sensitive */
1027 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
1028 #endif
1030 /* Must be done before calling mpeg_sound_set() */
1031 mpeg_is_initialized = true;
1033 mpeg_sound_set(SOUND_BASS, bass);
1034 mpeg_sound_set(SOUND_TREBLE, treble);
1035 mpeg_sound_set(SOUND_BALANCE, balance);
1036 mpeg_sound_set(SOUND_VOLUME, volume);
1038 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1039 mpeg_sound_channel_config(channel_config);
1040 mpeg_sound_set(SOUND_LOUDNESS, loudness);
1041 mpeg_sound_set(SOUND_AVC, avc);
1042 mpeg_sound_set(SOUND_MDB_STRENGTH, mdb_strength);
1043 mpeg_sound_set(SOUND_MDB_HARMONICS, mdb_harmonics);
1044 mpeg_sound_set(SOUND_MDB_CENTER, mdb_center);
1045 mpeg_sound_set(SOUND_MDB_SHAPE, mdb_shape);
1046 mpeg_sound_set(SOUND_MDB_ENABLE, mdb_enable);
1047 mpeg_sound_set(SOUND_SUPERBASS, superbass);
1048 #endif
1049 #endif /* !SIMULATOR */
1051 playing = false;
1052 paused = true;
1055 void mp3_shutdown(void)
1057 #ifndef SIMULATOR
1058 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1059 unsigned long val = 1;
1060 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &val, 1); /* Mute */
1061 #endif
1063 #if CONFIG_HWCODEC == MAS3507D
1064 dac_volume(0, 0, false);
1065 #endif
1067 #endif
1070 /* new functions, to be exported to plugin API */
1072 #ifndef SIMULATOR
1074 void mp3_play_init(void)
1076 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1077 init_playback();
1078 #endif
1079 playing = false;
1080 paused = true;
1081 callback_for_more = NULL;
1082 mp3_reset_playtime();
1085 void mp3_play_data(const unsigned char* start, int size,
1086 void (*get_more)(unsigned char** start, int* size) /* callback fn */
1089 /* init DMA */
1090 DAR3 = 0x5FFFEC3;
1091 CHCR3 &= ~0x0002; /* Clear interrupt */
1092 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
1093 DMAOR = 0x0001; /* Enable DMA */
1095 callback_for_more = get_more;
1097 SAR3 = (unsigned int)start;
1098 DTCR3 = size & 0xffff;
1100 playing = true;
1101 paused = true;
1103 CHCR3 |= 0x0001; /* Enable DMA IRQ */
1105 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1106 demand_irq_enable(true);
1107 #endif
1110 void mp3_play_pause(bool play)
1112 if (paused && play)
1113 { /* resume playback */
1114 SCR0 |= 0x80;
1115 paused = false;
1116 playstart_tick = current_tick;
1118 else if (!paused && !play)
1119 { /* stop playback */
1120 SCR0 &= 0x7f;
1121 paused = true;
1122 cumulative_ticks += current_tick - playstart_tick;
1126 void mp3_play_stop(void)
1128 playing = false;
1129 mp3_play_pause(false);
1130 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
1131 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1132 demand_irq_enable(false);
1133 #endif
1136 long mp3_get_playtime(void)
1138 if (paused)
1139 return cumulative_ticks;
1140 else
1141 return cumulative_ticks + current_tick - playstart_tick;
1144 void mp3_reset_playtime(void)
1146 cumulative_ticks = 0;
1147 playstart_tick = current_tick;
1151 bool mp3_is_playing(void)
1153 return playing;
1157 /* returns the next byte position which would be transferred */
1158 unsigned char* mp3_get_pos(void)
1160 return (unsigned char*)SAR3;
1164 #endif /* #ifndef SIMULATOR */