summaryrefslogtreecommitdiff
path: root/firmware/sound.c
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2005-04-01 13:41:03 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2005-04-01 13:41:03 +0000
commit674eaca5ef59625f90088da006eca4d10e2bea56 (patch)
treeb0f02cec358ce1c506fb6d2256e2db059c7b6b6a /firmware/sound.c
parent88d5aab5a1098c5636584ddf06bd3012dc8c5b4c (diff)
downloadrockbox-674eaca5ef59625f90088da006eca4d10e2bea56.tar.gz
rockbox-674eaca5ef59625f90088da006eca4d10e2bea56.zip
Moved the mpeg_sound_xxx() functions to sound.c and renamed them to sound_xxx()
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6240 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/sound.c')
-rw-r--r--firmware/sound.c634
1 files changed, 634 insertions, 0 deletions
diff --git a/firmware/sound.c b/firmware/sound.c
new file mode 100644
index 0000000000..ab0ab1ed46
--- /dev/null
+++ b/firmware/sound.c
@@ -0,0 +1,634 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
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 <stdbool.h>
20#include "config.h"
21#include "sound.h"
22#ifndef SIMULATOR
23#include "i2c.h"
24#include "mas.h"
25#include "dac.h"
26#include "system.h"
27#include "hwcompat.h"
28#endif
29
30#ifndef SIMULATOR
31extern bool audio_is_initialized;
32#endif
33
34#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
35extern unsigned long shadow_io_control_main;
36extern unsigned shadow_codec_reg0;
37#endif
38
39static const char* const units[] =
40{
41 "%", /* Volume */
42 "dB", /* Bass */
43 "dB", /* Treble */
44 "%", /* Balance */
45 "dB", /* Loudness */
46 "", /* AVC */
47 "", /* Channels */
48 "%", /* Stereo width */
49 "dB", /* Left gain */
50 "dB", /* Right gain */
51 "dB", /* Mic gain */
52 "dB", /* MDB Strength */
53 "%", /* MDB Harmonics */
54 "Hz", /* MDB Center */
55 "Hz", /* MDB Shape */
56 "", /* MDB Enable */
57 "", /* Super bass */
58};
59
60static const int numdecimals[] =
61{
62 0, /* Volume */
63 0, /* Bass */
64 0, /* Treble */
65 0, /* Balance */
66 0, /* Loudness */
67 0, /* AVC */
68 0, /* Channels */
69 0, /* Stereo width */
70 1, /* Left gain */
71 1, /* Right gain */
72 1, /* Mic gain */
73 0, /* MDB Strength */
74 0, /* MDB Harmonics */
75 0, /* MDB Center */
76 0, /* MDB Shape */
77 0, /* MDB Enable */
78 0, /* Super bass */
79};
80
81static const int steps[] =
82{
83 1, /* Volume */
84 1, /* Bass */
85 1, /* Treble */
86 1, /* Balance */
87 1, /* Loudness */
88 1, /* AVC */
89 1, /* Channels */
90 1, /* Stereo width */
91 1, /* Left gain */
92 1, /* Right gain */
93 1, /* Mic gain */
94 1, /* MDB Strength */
95 1, /* MDB Harmonics */
96 10, /* MDB Center */
97 10, /* MDB Shape */
98 1, /* MDB Enable */
99 1, /* Super bass */
100};
101
102static const int minval[] =
103{
104 0, /* Volume */
105#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
106 -12, /* Bass */
107 -12, /* Treble */
108#else
109 -15, /* Bass */
110 -15, /* Treble */
111#endif
112 -100, /* Balance */
113 0, /* Loudness */
114 -1, /* AVC */
115 0, /* Channels */
116 0, /* Stereo width */
117 0, /* Left gain */
118 0, /* Right gain */
119 0, /* Mic gain */
120 0, /* MDB Strength */
121 0, /* MDB Harmonics */
122 20, /* MDB Center */
123 50, /* MDB Shape */
124 0, /* MDB Enable */
125 0, /* Super bass */
126};
127
128static const int maxval[] =
129{
130 100, /* Volume */
131#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
132 12, /* Bass */
133 12, /* Treble */
134#else
135 15, /* Bass */
136 15, /* Treble */
137#endif
138 100, /* Balance */
139 17, /* Loudness */
140 4, /* AVC */
141 5, /* Channels */
142 255, /* Stereo width */
143 15, /* Left gain */
144 15, /* Right gain */
145 15, /* Mic gain */
146 127, /* MDB Strength */
147 100, /* MDB Harmonics */
148 300, /* MDB Center */
149 300, /* MDB Shape */
150 1, /* MDB Enable */
151 1, /* Super bass */
152};
153
154static const int defaultval[] =
155{
156 70, /* Volume */
157#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
158 6, /* Bass */
159 6, /* Treble */
160#else
161 7, /* Bass */
162 7, /* Treble */
163#endif
164 0, /* Balance */
165 0, /* Loudness */
166 0, /* AVC */
167 0, /* Channels */
168 100, /* Stereo width */
169 8, /* Left gain */
170 8, /* Right gain */
171 2, /* Mic gain */
172 50, /* MDB Strength */
173 48, /* MDB Harmonics */
174 60, /* MDB Center */
175 90, /* MDB Shape */
176 0, /* MDB Enable */
177 0, /* Super bass */
178};
179
180const char *sound_unit(int setting)
181{
182 return units[setting];
183}
184
185int sound_numdecimals(int setting)
186{
187 return numdecimals[setting];
188}
189
190int sound_steps(int setting)
191{
192 return steps[setting];
193}
194
195int sound_min(int setting)
196{
197 return minval[setting];
198}
199
200int sound_max(int setting)
201{
202 return maxval[setting];
203}
204
205int sound_default(int setting)
206{
207 return defaultval[setting];
208}
209
210#ifndef SIMULATOR
211#if CONFIG_HWCODEC == MAS3507D
212static const unsigned int bass_table[] =
213{
214 0x9e400, /* -15dB */
215 0xa2800, /* -14dB */
216 0xa7400, /* -13dB */
217 0xac400, /* -12dB */
218 0xb1800, /* -11dB */
219 0xb7400, /* -10dB */
220 0xbd400, /* -9dB */
221 0xc3c00, /* -8dB */
222 0xca400, /* -7dB */
223 0xd1800, /* -6dB */
224 0xd8c00, /* -5dB */
225 0xe0400, /* -4dB */
226 0xe8000, /* -3dB */
227 0xefc00, /* -2dB */
228 0xf7c00, /* -1dB */
229 0,
230 0x800, /* 1dB */
231 0x10000, /* 2dB */
232 0x17c00, /* 3dB */
233 0x1f800, /* 4dB */
234 0x27000, /* 5dB */
235 0x2e400, /* 6dB */
236 0x35800, /* 7dB */
237 0x3c000, /* 8dB */
238 0x42800, /* 9dB */
239 0x48800, /* 10dB */
240 0x4e400, /* 11dB */
241 0x53800, /* 12dB */
242 0x58800, /* 13dB */
243 0x5d400, /* 14dB */
244 0x61800 /* 15dB */
245};
246
247static const unsigned int treble_table[] =
248{
249 0xb2c00, /* -15dB */
250 0xbb400, /* -14dB */
251 0xc1800, /* -13dB */
252 0xc6c00, /* -12dB */
253 0xcbc00, /* -11dB */
254 0xd0400, /* -10dB */
255 0xd5000, /* -9dB */
256 0xd9800, /* -8dB */
257 0xde000, /* -7dB */
258 0xe2800, /* -6dB */
259 0xe7e00, /* -5dB */
260 0xec000, /* -4dB */
261 0xf0c00, /* -3dB */
262 0xf5c00, /* -2dB */
263 0xfac00, /* -1dB */
264 0,
265 0x5400, /* 1dB */
266 0xac00, /* 2dB */
267 0x10400, /* 3dB */
268 0x16000, /* 4dB */
269 0x1c000, /* 5dB */
270 0x22400, /* 6dB */
271 0x28400, /* 7dB */
272 0x2ec00, /* 8dB */
273 0x35400, /* 9dB */
274 0x3c000, /* 10dB */
275 0x42c00, /* 11dB */
276 0x49c00, /* 12dB */
277 0x51800, /* 13dB */
278 0x58400, /* 14dB */
279 0x5f800 /* 15dB */
280};
281
282static const unsigned int prescale_table[] =
283{
284 0x80000, /* 0db */
285 0x8e000, /* 1dB */
286 0x9a400, /* 2dB */
287 0xa5800, /* 3dB */
288 0xaf400, /* 4dB */
289 0xb8000, /* 5dB */
290 0xbfc00, /* 6dB */
291 0xc6c00, /* 7dB */
292 0xcd000, /* 8dB */
293 0xd25c0, /* 9dB */
294 0xd7800, /* 10dB */
295 0xdc000, /* 11dB */
296 0xdfc00, /* 12dB */
297 0xe3400, /* 13dB */
298 0xe6800, /* 14dB */
299 0xe9400 /* 15dB */
300};
301
302/* all values in tenth of dB */
303int current_volume = 0; /* -780..+180 */
304int current_balance = 0; /* -960..+960 */
305int current_treble = 0; /* -150..+150 */
306int current_bass = 0; /* -150..+150 */
307
308/* convert tenth of dB volume to register value */
309static int tenthdb2reg(int db) {
310 if (db < -540)
311 return (db + 780) / 30;
312 else
313 return (db + 660) / 15;
314}
315
316void set_prescaled_volume(void)
317{
318 int prescale;
319 int l, r;
320
321 prescale = MAX(current_bass, current_treble);
322 if (prescale < 0)
323 prescale = 0; /* no need to prescale if we don't boost
324 bass or treble */
325
326 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
327
328 /* gain up the analog volume to compensate the prescale reduction gain,
329 * but limit to +18 dB (the maximum the DAC can do */
330 if (current_volume + prescale > 180)
331 prescale = 180 - current_volume;
332 l = r = current_volume + prescale;
333
334 if (current_balance > 0)
335 {
336 l -= current_balance;
337 if (l < -780)
338 l = -780;
339 }
340 if (current_balance < 0)
341 {
342 r += current_balance;
343 if (r < -780)
344 r = -780;
345 }
346
347 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
348}
349#endif /* MAS3507D */
350#endif /* !SIMULATOR */
351
352int channel_configuration = SOUND_CHAN_STEREO;
353int stereo_width = 100;
354
355#ifndef SIMULATOR
356static void set_channel_config(void)
357{
358 /* default values: stereo */
359 unsigned long val_ll = 0x80000;
360 unsigned long val_lr = 0;
361 unsigned long val_rl = 0;
362 unsigned long val_rr = 0x80000;
363
364 switch(channel_configuration)
365 {
366 /* case SOUND_CHAN_STEREO unnecessary */
367
368 case SOUND_CHAN_MONO:
369 val_ll = 0xc0000;
370 val_lr = 0xc0000;
371 val_rl = 0xc0000;
372 val_rr = 0xc0000;
373 break;
374
375 case SOUND_CHAN_CUSTOM:
376 {
377 /* fixed point variables (matching MAS internal format)
378 integer part: upper 13 bits (inlcuding sign)
379 fractional part: lower 19 bits */
380 long fp_width, fp_straight, fp_cross;
381
382 fp_width = (stereo_width << 19) / 100;
383 if (stereo_width <= 100)
384 {
385 fp_straight = - ((1<<19) + fp_width) / 2;
386 fp_cross = fp_straight + fp_width;
387 }
388 else
389 {
390 fp_straight = - (1<<19);
391 fp_cross = ((2 * fp_width / (((1<<19) + fp_width) >> 10))
392 << 9) - (1<<19);
393 }
394 val_ll = val_rr = fp_straight & 0xFFFFF;
395 val_lr = val_rl = fp_cross & 0xFFFFF;
396 }
397 break;
398
399 case SOUND_CHAN_MONO_LEFT:
400 val_ll = 0x80000;
401 val_lr = 0x80000;
402 val_rl = 0;
403 val_rr = 0;
404 break;
405
406 case SOUND_CHAN_MONO_RIGHT:
407 val_ll = 0;
408 val_lr = 0;
409 val_rl = 0x80000;
410 val_rr = 0x80000;
411 break;
412
413 case SOUND_CHAN_KARAOKE:
414 val_ll = 0x80001;
415 val_lr = 0x7ffff;
416 val_rl = 0x7ffff;
417 val_rr = 0x80001;
418 break;
419 }
420
421#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
422 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LL, &val_ll, 1); /* LL */
423 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LR, &val_lr, 1); /* LR */
424 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RL, &val_rl, 1); /* RL */
425 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RR, &val_rr, 1); /* RR */
426#elif CONFIG_HWCODEC == MAS3507D
427 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
428 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
429 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
430 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
431#endif
432}
433#endif /* !SIMULATOR */
434
435#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
436unsigned long mdb_shape_shadow = 0;
437unsigned long loudness_shadow = 0;
438#endif
439
440void sound_set(int setting, int value)
441{
442#ifdef SIMULATOR
443 setting = value;
444#else
445#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
446 int tmp;
447#endif
448
449 if(!audio_is_initialized)
450 return;
451
452 switch(setting)
453 {
454 case SOUND_VOLUME:
455#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
456 tmp = 0x7f00 * value / 100;
457 mas_codec_writereg(0x10, tmp & 0xff00);
458#elif CONFIG_HWCODEC == MAS3507D
459 current_volume = -780 + (value * 960 / 100); /* tenth of dB */
460 set_prescaled_volume();
461#endif
462 break;
463
464 case SOUND_BALANCE:
465#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
466 tmp = ((value * 127 / 100) & 0xff) << 8;
467 mas_codec_writereg(0x11, tmp & 0xff00);
468#elif CONFIG_HWCODEC == MAS3507D
469 current_balance = value * 960 / 100; /* tenth of dB */
470 set_prescaled_volume();
471#endif
472 break;
473
474 case SOUND_BASS:
475#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
476 tmp = ((value * 8) & 0xff) << 8;
477 mas_codec_writereg(0x14, tmp & 0xff00);
478#elif CONFIG_HWCODEC == MAS3507D
479 mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
480 current_bass = value * 10;
481 set_prescaled_volume();
482#endif
483 break;
484
485 case SOUND_TREBLE:
486#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
487 tmp = ((value * 8) & 0xff) << 8;
488 mas_codec_writereg(0x15, tmp & 0xff00);
489#elif CONFIG_HWCODEC == MAS3507D
490 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
491 current_treble = value * 10;
492 set_prescaled_volume();
493#endif
494 break;
495
496#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
497 case SOUND_LOUDNESS:
498 loudness_shadow = (loudness_shadow & 0x04) |
499 (MAX(MIN(value * 4, 0x44), 0) << 8);
500 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
501 break;
502
503 case SOUND_AVC:
504 switch (value) {
505 case 1: /* 20ms */
506 tmp = (0x1 << 8) | (0x8 << 12);
507 break;
508 case 2: /* 2s */
509 tmp = (0x2 << 8) | (0x8 << 12);
510 break;
511 case 3: /* 4s */
512 tmp = (0x4 << 8) | (0x8 << 12);
513 break;
514 case 4: /* 8s */
515 tmp = (0x8 << 8) | (0x8 << 12);
516 break;
517 case -1: /* turn off and then turn on again to decay quickly */
518 tmp = mas_codec_readreg(MAS_REG_KAVC);
519 mas_codec_writereg(MAS_REG_KAVC, 0);
520 break;
521 default: /* off */
522 tmp = 0;
523 break;
524 }
525 mas_codec_writereg(MAS_REG_KAVC, tmp);
526 break;
527
528 case SOUND_MDB_STRENGTH:
529 mas_codec_writereg(MAS_REG_KMDB_STR, (value & 0x7f) << 8);
530 break;
531
532 case SOUND_MDB_HARMONICS:
533 tmp = value * 127 / 100;
534 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0x7f) << 8);
535 break;
536
537 case SOUND_MDB_CENTER:
538 mas_codec_writereg(MAS_REG_KMDB_FC, (value/10) << 8);
539 break;
540
541 case SOUND_MDB_SHAPE:
542 mdb_shape_shadow = (mdb_shape_shadow & 0x02) | ((value/10) << 8);
543 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
544 break;
545
546 case SOUND_MDB_ENABLE:
547 mdb_shape_shadow = (mdb_shape_shadow & ~0x02) | (value?2:0);
548 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
549 break;
550
551 case SOUND_SUPERBASS:
552 loudness_shadow = (loudness_shadow & ~0x04) |
553 (value?4:0);
554 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
555 break;
556#endif
557 case SOUND_CHANNELS:
558 channel_configuration = value;
559 set_channel_config();
560 break;
561
562 case SOUND_STEREO_WIDTH:
563 stereo_width = value;
564 if (channel_configuration == SOUND_CHAN_CUSTOM)
565 set_channel_config();
566 break;
567 }
568#endif /* SIMULATOR */
569}
570
571int sound_val2phys(int setting, int value)
572{
573#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
574 int result = 0;
575
576 switch(setting)
577 {
578 case SOUND_LEFT_GAIN:
579 case SOUND_RIGHT_GAIN:
580 result = (value - 2) * 15;
581 break;
582
583 case SOUND_MIC_GAIN:
584 result = value * 15 + 210;
585 break;
586
587 default:
588 result = value;
589 break;
590 }
591 return result;
592#else
593 (void)setting;
594 return value;
595#endif
596}
597
598#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
599/* This function works by telling the decoder that we have another
600 crystal frequency than we actually have. It will adjust its internal
601 parameters and the result is that the audio is played at another pitch.
602
603 The pitch value is in tenths of percent.
604*/
605void sound_set_pitch(int pitch)
606{
607 unsigned long val;
608
609 /* invert pitch value */
610 pitch = 1000000/pitch;
611
612 /* Calculate the new (bogus) frequency */
613 val = 18432*pitch/1000;
614
615 mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, &val, 1);
616
617 /* We must tell the MAS that the frequency has changed.
618 This will unfortunately cause a short silence. */
619 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
620}
621#elif defined SIMULATOR
622void sound_set_pitch(int pitch)
623{
624 (void)pitch;
625}
626#endif
627
628#if CONFIG_HWCODEC == MASNONE
629bool mp3_is_playing(void)
630{
631 /* a dummy */
632 return false;
633}
634#endif