blob: 7c561e475f158affdedb05363693d95edb8d43bd [file] [log] [blame]
Jörg Hohensohnf9933652004-01-05 20:42:51 +00001/***************************************************************************
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 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000015 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
Jörg Hohensohnf9933652004-01-05 20:42:51 +000019 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24#include <stdbool.h>
25#include "config.h"
26#include "debug.h"
27#include "panic.h"
28#include <kernel.h>
29#include "mpeg.h" /* ToDo: remove crosslinks */
30#include "mp3_playback.h"
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000031#include "sound.h"
Jörg Hohensohnf9933652004-01-05 20:42:51 +000032#ifndef SIMULATOR
33#include "i2c.h"
34#include "mas.h"
35#include "dac.h"
36#include "system.h"
Jörg Hohensohnf9933652004-01-05 20:42:51 +000037#endif
Christian Gmeinercdbf33a2007-05-22 15:56:05 +000038#include "audiohw.h"
Jörg Hohensohnf9933652004-01-05 20:42:51 +000039
Jörg Hohensohnec5d4462004-01-10 15:39:56 +000040/* hacking into mpeg.c, recording is still there */
Jens Arnoldd6c05452005-08-29 21:15:27 +000041#if CONFIG_CODEC == MAS3587F
Jörg Hohensohnec5d4462004-01-10 15:39:56 +000042enum
43{
44 MPEG_DECODER,
45 MPEG_ENCODER
46} mpeg_mode;
Jörg Hohensohn593cc002004-09-28 22:13:26 +000047#endif /* #ifdef MAS3587F */
Jörg Hohensohnec5d4462004-01-10 15:39:56 +000048
Jens Arnold8051a0b2005-11-06 23:12:11 +000049#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)) && !defined(SIMULATOR)
Jens Arnoldeaa1f732004-09-29 19:51:41 +000050extern unsigned long shadow_io_control_main;
Jens Arnolde1a19262005-01-09 00:58:59 +000051extern unsigned shadow_codec_reg0;
Jens Arnoldeaa1f732004-09-29 19:51:41 +000052#endif
53
Jörg Hohensohnec5d4462004-01-10 15:39:56 +000054/**** globals ****/
55
56/* own version, independent of mpeg.c */
57static bool paused; /* playback is paused */
58static bool playing; /* We are playing an MP3 stream */
59
60#ifndef SIMULATOR
61/* for measuring the play time */
62static long playstart_tick;
63static long cumulative_ticks;
64
65/* the registered callback function to ask for more mp3 data */
Nils Wallméniusc7f9ca42007-06-13 15:35:07 +000066static void (*callback_for_more)(unsigned char**, size_t*);
Jörg Hohensohnec5d4462004-01-10 15:39:56 +000067#endif /* #ifndef SIMULATOR */
68
Jörg Hohensohnf9933652004-01-05 20:42:51 +000069/* list of tracks in memory */
70#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
71#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
72
73#ifndef SIMULATOR
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000074bool audio_is_initialized = false;
Jörg Hohensohnf9933652004-01-05 20:42:51 +000075#endif
76
Daniel Stenbergac5fbf32005-02-02 21:59:54 +000077/* FIX: this code pretty much assumes a MAS */
78
Jörg Hohensohnf9933652004-01-05 20:42:51 +000079#ifndef SIMULATOR
80
81unsigned long mas_version_code;
82
Jens Arnoldd6c05452005-08-29 21:15:27 +000083#if CONFIG_CODEC == MAS3507D
Jens Arnold6fde2432004-11-07 08:09:08 +000084static void mas_poll_start(void)
Jörg Hohensohnf9933652004-01-05 20:42:51 +000085{
86 unsigned int count;
87
Jens Arnold6fde2432004-11-07 08:09:08 +000088 count = 9 * FREQ / 10000 / 8; /* 0.9 ms */
Jörg Hohensohnf9933652004-01-05 20:42:51 +000089
Jörg Hohensohnf9933652004-01-05 20:42:51 +000090 /* We are using timer 1 */
91
92 TSTR &= ~0x02; /* Stop the timer */
93 TSNC &= ~0x02; /* No synchronization */
94 TMDR &= ~0x02; /* Operate normally */
95
96 TCNT1 = 0; /* Start counting at 0 */
97 GRA1 = count;
98 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
99
100 /* Enable interrupt on level 5 */
101 IPRC = (IPRC & ~0x000f) | 0x0005;
102
103 TSR1 &= ~0x02;
104 TIER1 = 0xf9; /* Enable GRA match interrupt */
105
106 TSTR |= 0x02; /* Start timer 1 */
107}
Jens Arnoldd6c05452005-08-29 21:15:27 +0000108#elif CONFIG_CODEC != SWCODEC
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000109static void postpone_dma_tick(void)
110{
111 unsigned int count;
112
Jens Arnold6fde2432004-11-07 08:09:08 +0000113 count = 8 * FREQ / 10000 / 8; /* 0.8 ms */
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000114
115 /* We are using timer 1 */
116
117 TSTR &= ~0x02; /* Stop the timer */
118 TSNC &= ~0x02; /* No synchronization */
119 TMDR &= ~0x02; /* Operate normally */
120
121 TCNT1 = 0; /* Start counting at 0 */
122 GRA1 = count;
123 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
124
125 /* Enable interrupt on level 5 */
126 IPRC = (IPRC & ~0x000f) | 0x0005;
127
128 TSR1 &= ~0x02;
129 TIER1 = 0xf9; /* Enable GRA match interrupt */
130
131 TSTR |= 0x02; /* Start timer 1 */
132}
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000133#endif
134
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000135
Jens Arnoldd6c05452005-08-29 21:15:27 +0000136#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000137void demand_irq_enable(bool on)
138{
Michael Sevakisaf395f42008-03-26 01:50:41 +0000139 int oldlevel = disable_irq_save();
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000140
141 if(on)
142 {
143 IPRA = (IPRA & 0xfff0) | 0x000b;
144 ICR &= ~0x0010; /* IRQ3 level sensitive */
145 }
146 else
147 IPRA &= 0xfff0;
148
Michael Sevakisaf395f42008-03-26 01:50:41 +0000149 restore_irq(oldlevel);
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000150}
Jens Arnoldd6c05452005-08-29 21:15:27 +0000151#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000152
153
154void play_tick(void)
155{
156 if(playing && !paused)
157 {
158 /* Start DMA if it is disabled and the DEMAND pin is high */
159 if(!(SCR0 & 0x80) && (PBDR & 0x4000))
160 {
161 SCR0 |= 0x80;
162 }
163
164 playback_tick(); /* dirty call to mpeg.c */
165 }
166}
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000167
Jens Arnolda7c20ac2006-04-26 20:22:27 +0000168void DEI3(void) __attribute__((interrupt_handler));
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000169void DEI3(void)
170{
171 unsigned char* start;
Nils Wallméniusc7f9ca42007-06-13 15:35:07 +0000172 size_t size = 0;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000173
174 if (callback_for_more != NULL)
175 {
176 callback_for_more(&start, &size);
177 }
178
179 if (size > 0)
180 {
181 DTCR3 = size & 0xffff;
182 SAR3 = (unsigned int) start;
183 }
184 else
185 {
186 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
187 }
188
189 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
190}
191
Jens Arnolda7c20ac2006-04-26 20:22:27 +0000192void IMIA1(void) __attribute__((interrupt_handler));
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000193void IMIA1(void) /* Timer 1 interrupt */
194{
195 if(playing)
196 play_tick();
197 TSR1 &= ~0x01;
Jens Arnoldd6c05452005-08-29 21:15:27 +0000198#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000199 /* Disable interrupt */
200 IPRC &= ~0x000f;
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000201#endif
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000202}
203
Jens Arnolda7c20ac2006-04-26 20:22:27 +0000204void IRQ6(void) __attribute__((interrupt_handler));
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000205void IRQ6(void) /* PB14: MAS stop demand IRQ */
206{
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000207 SCR0 &= ~0x80;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000208}
209
Jens Arnoldd6c05452005-08-29 21:15:27 +0000210#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnolda7c20ac2006-04-26 20:22:27 +0000211void IRQ3(void) __attribute__((interrupt_handler));
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000212void IRQ3(void) /* PA15: MAS demand IRQ */
213{
214 /* Begin with setting the IRQ to edge sensitive */
215 ICR |= 0x0010;
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000216
Jens Arnoldd6c05452005-08-29 21:15:27 +0000217#if CONFIG_CODEC == MAS3587F
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000218 if(mpeg_mode == MPEG_ENCODER)
219 rec_tick();
220 else
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000221#endif
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000222 postpone_dma_tick();
Jens Arnold96dce1d2006-04-25 22:40:55 +0000223
224 /* Workaround for sh-elf-gcc 3.3.x bug with -O2 or -Os and ISRs
225 * (invalid cross-jump optimisation) */
226 asm volatile ("");
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000227}
Jens Arnoldd6c05452005-08-29 21:15:27 +0000228#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000229
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000230static void setup_sci0(void)
231{
232 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
233 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
234
235 /* Set PB12 to output */
236 or_b(0x10, &PBIORH);
237
238 /* Disable serial port */
239 SCR0 = 0x00;
240
241 /* Synchronous, no prescale */
242 SMR0 = 0x80;
243
244 /* Set baudrate 1Mbit/s */
Jens Arnold83663942004-11-06 00:54:56 +0000245 BRR0 = 0x02;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000246
247 /* use SCK as serial clock output */
248 SCR0 = 0x01;
249
250 /* Clear FER and PER */
251 SSR0 &= 0xe7;
252
253 /* Set interrupt ITU2 and SCI0 priority to 0 */
254 IPRD &= 0x0ff0;
255
256 /* set PB15 and PB14 to inputs */
257 and_b(~0x80, &PBIORH);
258 and_b(~0x40, &PBIORH);
259
260 /* Enable End of DMA interrupt at prio 8 */
261 IPRC = (IPRC & 0xf0ff) | 0x0800;
262
263 /* Enable Tx (only!) */
264 SCR0 |= 0x20;
265}
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000266
Jens Arnoldd6c05452005-08-29 21:15:27 +0000267#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000268static void init_playback(void)
269{
270 unsigned long val;
271 int rc;
272
273 mp3_play_pause(false);
274
275 mas_reset();
Jens Arnold65bee602004-10-01 18:47:19 +0000276
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000277 /* Enable the audio CODEC and the DSP core, max analog voltage range */
278 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
279 if(rc < 0)
280 panicf("mas_ctrl_w: %d", rc);
281
282 /* Stop the current application */
283 val = 0;
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000284 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000285 do
286 {
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000287 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000288 } while(val);
289
290 /* Enable the D/A Converter */
Jens Arnolde1a19262005-01-09 00:58:59 +0000291 shadow_codec_reg0 = 0x0001;
292 mas_codec_writereg(0x0, shadow_codec_reg0);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000293
294 /* ADC scale 0%, DSP scale 100% */
295 mas_codec_writereg(6, 0x0000);
296 mas_codec_writereg(7, 0x4000);
297
Jens Arnold1acc38f2004-10-11 22:53:49 +0000298#ifdef HAVE_SPDIF_OUT
299 val = 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
300#else
301 val = 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
302#endif
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000303 mas_writemem(MAS_BANK_D0, MAS_D0_INTERFACE_CONTROL, &val, 1);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000304
305 /* Set Demand mode and validate all settings */
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000306 shadow_io_control_main = 0x25;
307 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000308
309 /* Start the Layer2/3 decoder applications */
310 val = 0x0c;
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000311 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000312 do
313 {
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000314 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000315 } while((val & 0x0c) != 0x0c);
316
Jens Arnoldd6c05452005-08-29 21:15:27 +0000317#if CONFIG_CODEC == MAS3587F
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000318 mpeg_mode = MPEG_DECODER;
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000319#endif
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000320
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000321 /* set IRQ6 to edge detect */
322 ICR |= 0x02;
323
324 /* set IRQ6 prio 8 */
325 IPRB = ( IPRB & 0xff0f ) | 0x0080;
326
327 DEBUGF("MAS Decoding application started\n");
328}
Jens Arnoldd6c05452005-08-29 21:15:27 +0000329#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
Jens Arnold8051a0b2005-11-06 23:12:11 +0000330#endif /* SIMULATOR */
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000331
Jens Arnold65bee602004-10-01 18:47:19 +0000332void mp3_init(int volume, int bass, int treble, int balance, int loudness,
Jens Arnold76b257f2005-01-12 00:24:15 +0000333 int avc, int channel_config, int stereo_width,
Linus Nielsen Feltzing7bade1a2004-07-06 12:17:14 +0000334 int mdb_strength, int mdb_harmonics,
335 int mdb_center, int mdb_shape, bool mdb_enable,
336 bool superbass)
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000337{
338#ifdef SIMULATOR
Linus Nielsen Feltzing7bade1a2004-07-06 12:17:14 +0000339 (void)volume;
340 (void)bass;
341 (void)treble;
342 (void)balance;
343 (void)loudness;
344 (void)avc;
345 (void)channel_config;
Jens Arnold76b257f2005-01-12 00:24:15 +0000346 (void)stereo_width;
Linus Nielsen Feltzing7bade1a2004-07-06 12:17:14 +0000347 (void)mdb_strength;
348 (void)mdb_harmonics;
349 (void)mdb_center;
350 (void)mdb_shape;
351 (void)mdb_enable;
352 (void)superbass;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000353#else
Jens Arnoldd6c05452005-08-29 21:15:27 +0000354#if CONFIG_CODEC == MAS3507D
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000355 unsigned long val;
Linus Nielsen Feltzing7bade1a2004-07-06 12:17:14 +0000356 (void)loudness;
357 (void)avc;
358 (void)mdb_strength;
359 (void)mdb_harmonics;
360 (void)mdb_center;
361 (void)mdb_shape;
362 (void)mdb_enable;
363 (void)superbass;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000364#endif
365
366 setup_sci0();
367
Jörg Hohensohn1e570da2004-10-01 07:36:25 +0000368#ifdef HAVE_MAS_SIBI_CONTROL
369 and_b(~0x01, &PBDRH); /* drive SIBI low */
Jens Arnold4f8d3482004-10-02 21:53:21 +0000370 or_b(0x01, &PBIORH); /* output for PB8 */
Jörg Hohensohn1e570da2004-10-01 07:36:25 +0000371#endif
372
Jens Arnoldd6c05452005-08-29 21:15:27 +0000373#if CONFIG_CODEC == MAS3507D
Jens Arnolddbd11c92004-11-22 01:54:26 +0000374 mas_reset();
Jens Arnoldd6c05452005-08-29 21:15:27 +0000375#elif CONFIG_CODEC == MAS3587F
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000376 or_b(0x08, &PAIORH); /* output for /PR */
377 init_playback();
378
379 mas_version_code = mas_readver();
Jens Arnold536dff12004-08-05 17:06:31 +0000380 DEBUGF("MAS3587 derivate %d, version %c%d\n",
381 (mas_version_code & 0xf000) >> 12,
382 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
Jens Arnoldd6c05452005-08-29 21:15:27 +0000383#elif CONFIG_CODEC == MAS3539F
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000384 or_b(0x08, &PAIORH); /* output for /PR */
385 init_playback();
386
387 mas_version_code = mas_readver();
388 DEBUGF("MAS3539 derivate %d, version %c%d\n",
389 (mas_version_code & 0xf000) >> 12,
390 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000391#endif
392
393#ifdef HAVE_DAC3550A
394 dac_init();
395#endif
396
Jens Arnoldd6c05452005-08-29 21:15:27 +0000397#if CONFIG_CODEC == MAS3507D
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000398 /* set IRQ6 to edge detect */
399 ICR |= 0x02;
400
401 /* set IRQ6 prio 8 */
402 IPRB = ( IPRB & 0xff0f ) | 0x0080;
403
404 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
405
406 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
407 mas_run(1);
408 sleep(HZ);
409
410 /* Clear the upper 12 bits of the 32-bit samples */
411 mas_writereg(0xc5, 0);
412 mas_writereg(0xc6, 0);
413
Jens Arnold83663942004-11-06 00:54:56 +0000414 /* We need to set the PLL for a 14.31818MHz crystal */
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000415 if(mas_version_code == 0x0601) /* Version F10? */
416 {
417 val = 0x5d9d0;
418 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
419 val = 0xfffceceb;
420 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
421 val = 0x0;
422 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
423 mas_run(0x475);
424 }
425 else
426 {
427 val = 0x5d9d0;
428 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
429 val = 0xfffceceb;
430 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
431 val = 0x0;
432 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
433 mas_run(0xfcb);
434 }
435
436#endif
437
Jens Arnoldd6c05452005-08-29 21:15:27 +0000438#if CONFIG_CODEC == MAS3507D
Jens Arnold6fde2432004-11-07 08:09:08 +0000439 mas_poll_start();
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000440
441 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
442 dac_enable(true);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000443#endif
444
Jens Arnoldd6c05452005-08-29 21:15:27 +0000445#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000446 ICR &= ~0x0010; /* IRQ3 level sensitive */
447 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
448#endif
449
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000450 /* Must be done before calling sound_set() */
451 audio_is_initialized = true;
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000452
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000453 sound_set(SOUND_BASS, bass);
454 sound_set(SOUND_TREBLE, treble);
455 sound_set(SOUND_BALANCE, balance);
456 sound_set(SOUND_VOLUME, volume);
457 sound_set(SOUND_CHANNELS, channel_config);
458 sound_set(SOUND_STEREO_WIDTH, stereo_width);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000459
Jens Arnoldd6c05452005-08-29 21:15:27 +0000460#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000461 sound_set(SOUND_LOUDNESS, loudness);
462 sound_set(SOUND_AVC, avc);
463 sound_set(SOUND_MDB_STRENGTH, mdb_strength);
464 sound_set(SOUND_MDB_HARMONICS, mdb_harmonics);
465 sound_set(SOUND_MDB_CENTER, mdb_center);
466 sound_set(SOUND_MDB_SHAPE, mdb_shape);
467 sound_set(SOUND_MDB_ENABLE, mdb_enable);
468 sound_set(SOUND_SUPERBASS, superbass);
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000469#endif
470#endif /* !SIMULATOR */
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000471
472 playing = false;
473 paused = true;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000474}
475
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000476void mp3_shutdown(void)
477{
478#ifndef SIMULATOR
Jens Arnoldd6c05452005-08-29 21:15:27 +0000479#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000480 unsigned long val = 1;
Jens Arnoldeaa1f732004-09-29 19:51:41 +0000481 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &val, 1); /* Mute */
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000482#endif
483
Jens Arnoldd6c05452005-08-29 21:15:27 +0000484#if CONFIG_CODEC == MAS3507D
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000485 dac_volume(0, 0, false);
486#endif
487
488#endif
489}
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000490
491/* new functions, to be exported to plugin API */
492
Jörg Hohensohndaaec5d2004-01-05 23:42:56 +0000493#ifndef SIMULATOR
494
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000495void mp3_play_init(void)
496{
Jens Arnoldd6c05452005-08-29 21:15:27 +0000497#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000498 init_playback();
499#endif
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000500 playing = false;
501 paused = true;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000502 callback_for_more = NULL;
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000503 mp3_reset_playtime();
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000504}
505
Jens Arnoldc76c5682004-08-16 23:37:23 +0000506void mp3_play_data(const unsigned char* start, int size,
Nils Wallméniusc7f9ca42007-06-13 15:35:07 +0000507 void (*get_more)(unsigned char** start, size_t* size) /* callback fn */
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000508)
509{
510 /* init DMA */
511 DAR3 = 0x5FFFEC3;
512 CHCR3 &= ~0x0002; /* Clear interrupt */
513 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
514 DMAOR = 0x0001; /* Enable DMA */
515
516 callback_for_more = get_more;
517
518 SAR3 = (unsigned int)start;
519 DTCR3 = size & 0xffff;
520
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000521 playing = true;
522 paused = true;
523
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000524 CHCR3 |= 0x0001; /* Enable DMA IRQ */
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000525
Jens Arnoldd6c05452005-08-29 21:15:27 +0000526#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000527 demand_irq_enable(true);
528#endif
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000529}
530
531void mp3_play_pause(bool play)
532{
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000533 if (paused && play)
534 { /* resume playback */
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000535 SCR0 |= 0x80;
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000536 paused = false;
537 playstart_tick = current_tick;
538 }
539 else if (!paused && !play)
540 { /* stop playback */
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000541 SCR0 &= 0x7f;
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000542 paused = true;
543 cumulative_ticks += current_tick - playstart_tick;
544 }
Jens Arnold03d08ec2005-05-13 00:16:14 +0000545}
546
547bool mp3_pause_done(void)
548{
549 unsigned long frame_count;
550
551 if (!paused)
552 return false;
553
554 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT, &frame_count, 1);
555 /* This works because the frame counter never wraps,
556 * i.e. zero always means lost sync. */
557 return frame_count == 0;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000558}
559
560void mp3_play_stop(void)
561{
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000562 playing = false;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000563 mp3_play_pause(false);
564 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
Jens Arnoldd6c05452005-08-29 21:15:27 +0000565#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jörg Hohensohnec5d4462004-01-10 15:39:56 +0000566 demand_irq_enable(false);
567#endif
568}
569
570long mp3_get_playtime(void)
571{
572 if (paused)
573 return cumulative_ticks;
574 else
575 return cumulative_ticks + current_tick - playstart_tick;
576}
577
578void mp3_reset_playtime(void)
579{
580 cumulative_ticks = 0;
581 playstart_tick = current_tick;
Jörg Hohensohnf9933652004-01-05 20:42:51 +0000582}
Jörg Hohensohndaaec5d2004-01-05 23:42:56 +0000583
Jörg Hohensohn95298a92004-01-30 22:30:40 +0000584bool mp3_is_playing(void)
585{
586 return playing;
587}
588
Jörg Hohensohn590e6af2004-03-21 17:45:45 +0000589
590/* returns the next byte position which would be transferred */
591unsigned char* mp3_get_pos(void)
592{
593 return (unsigned char*)SAR3;
594}
Jonathan Gordonc14430a2007-11-07 09:28:07 +0000595#else /* #ifndef SIMULATOR */
Jörg Hohensohn590e6af2004-03-21 17:45:45 +0000596
Jonathan Gordonc14430a2007-11-07 09:28:07 +0000597void mp3_play_pause(bool play)
598{
599 (void)play;
600}
601void mp3_play_stop(void)
602{
603}
Jörg Hohensohn590e6af2004-03-21 17:45:45 +0000604
Jonathan Gordonc14430a2007-11-07 09:28:07 +0000605unsigned char* mp3_get_pos(void)
606{
607 return NULL;
608}
609
610void mp3_play_data(const unsigned char* start, int size,
611 void (*get_more)(unsigned char** start, size_t* size) /* callback fn */
612)
613{
614 (void)start; (void)size; (void)get_more;
615}
616#endif