1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
11 * Copyright (C) 2007 by Christian Gmeiner
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
28 #if CONFIG_CPU == PNX0101
33 #if CONFIG_CODEC == SWCODEC
38 #if CONFIG_CODEC == MAS3507D /* volume/balance/treble/bass interdependency */
39 #define VOLUME_MIN -780
40 #define VOLUME_MAX 180
41 #elif !defined(VOLUME_MIN) && !defined(VOLUME_MAX)
42 #define VOLUME_MIN -400
43 #define VOLUME_MAX 600
46 /* volume/balance/treble/bass interdependency main part */
47 #define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
50 extern bool audio_is_initialized
;
52 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
53 extern unsigned long shadow_io_control_main
;
54 extern unsigned shadow_codec_reg0
;
56 #endif /* SIMULATOR */
60 const struct sound_settings_info audiohw_settings
[] = {
61 [SOUND_VOLUME
] = {"dB", 0, 1, VOLUME_MIN
/ 10, VOLUME_MAX
/ 10, -25},
62 [SOUND_BASS
] = {"dB", 0, 1, -24, 24, 0},
63 [SOUND_TREBLE
] = {"dB", 0, 1, -24, 24, 0},
64 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
65 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
66 [SOUND_STEREO_WIDTH
] = {"%", 0, 5, 0, 250, 100},
67 #if CONFIG_CODEC == MAS3587F || defined(HAVE_UDA1380) || defined(HAVE_TLV320)\
68 || defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
69 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
70 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
71 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
76 const char *sound_unit(int setting
)
78 return audiohw_settings
[setting
].unit
;
81 int sound_numdecimals(int setting
)
83 return audiohw_settings
[setting
].numdecimals
;
86 int sound_steps(int setting
)
88 return audiohw_settings
[setting
].steps
;
91 int sound_min(int setting
)
93 return audiohw_settings
[setting
].minval
;
96 int sound_max(int setting
)
98 return audiohw_settings
[setting
].maxval
;
101 int sound_default(int setting
)
103 return audiohw_settings
[setting
].defaultval
;
106 sound_set_type
* sound_get_fn(int setting
)
108 sound_set_type
* result
= NULL
;
112 result
= sound_set_volume
;
116 result
= sound_set_bass
;
120 result
= sound_set_treble
;
124 result
= sound_set_balance
;
128 result
= sound_set_channels
;
131 case SOUND_STEREO_WIDTH
:
132 result
= sound_set_stereo_width
;
135 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
137 result
= sound_set_loudness
;
141 result
= sound_set_avc
;
144 case SOUND_MDB_STRENGTH
:
145 result
= sound_set_mdb_strength
;
148 case SOUND_MDB_HARMONICS
:
149 result
= sound_set_mdb_harmonics
;
152 case SOUND_MDB_CENTER
:
153 result
= sound_set_mdb_center
;
156 case SOUND_MDB_SHAPE
:
157 result
= sound_set_mdb_shape
;
160 case SOUND_MDB_ENABLE
:
161 result
= sound_set_mdb_enable
;
164 case SOUND_SUPERBASS
:
165 result
= sound_set_superbass
;
173 #if CONFIG_CODEC == SWCODEC
174 /* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */
176 DSP_CALLBACK_SET_PRESCALE
= 0,
177 DSP_CALLBACK_SET_BASS
,
178 DSP_CALLBACK_SET_TREBLE
,
179 DSP_CALLBACK_SET_CHANNEL_CONFIG
,
180 DSP_CALLBACK_SET_STEREO_WIDTH
183 static int (*dsp_callback
)(int, intptr_t) = NULL
;
185 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
192 #if CONFIG_CODEC == MAS3507D /* volume/balance/treble/bass interdependency */
194 static const unsigned int bass_table
[] =
229 static const unsigned int treble_table
[] =
264 static const unsigned int prescale_table
[] =
284 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
285 static int tenthdb2reg(int db
)
287 if (db
< -540) /* 3 dB steps */
288 return (db
+ 780) / 30;
289 else /* 1.5 dB steps */
290 return (db
+ 660) / 15;
294 #if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
295 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_WM8731) \
296 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
297 || defined(HAVE_AS3514)
299 /* all values in tenth of dB MAS3507D UDA1380 */
300 int current_volume
= 0; /* -780..+180 -840.. 0 */
301 int current_balance
= 0; /* -960..+960 -840..+840 */
302 int current_treble
= 0; /* -150..+150 0.. +60 */
303 int current_bass
= 0; /* -150..+150 0..+240 */
305 static void set_prescaled_volume(void)
310 /* The WM codecs listed don't have suitable prescaler functionality, so we let
311 * the prescaler stay at 0 for these unless SW tone controls are in use */
312 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
313 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751))
315 prescale
= MAX(current_bass
, current_treble
);
317 prescale
= 0; /* no need to prescale if we don't boost
320 /* Gain up the analog volume to compensate the prescale gain reduction,
321 * but if this would push the volume over the top, reduce prescaling
322 * instead (might cause clipping). */
323 if (current_volume
+ prescale
> VOLUME_MAX
)
324 prescale
= VOLUME_MAX
- current_volume
;
327 #if defined(HAVE_SW_TONE_CONTROLS)
328 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
329 #elif CONFIG_CODEC == MAS3507D
330 mas_writereg(MAS_REG_KPRESCALE
, prescale_table
[prescale
/10]);
331 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8758)
332 audiohw_set_mixer_vol(tenthdb2mixer(-prescale
), tenthdb2mixer(-prescale
));
335 if (current_volume
== VOLUME_MIN
)
336 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
338 l
= r
= current_volume
+ prescale
;
340 if (current_balance
> 0)
342 l
-= current_balance
;
346 if (current_balance
< 0)
348 r
+= current_balance
;
353 #if CONFIG_CODEC == MAS3507D
354 dac_volume(tenthdb2reg(l
), tenthdb2reg(r
), false);
355 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
356 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
357 || defined(HAVE_AS3514)
358 audiohw_set_master_vol(tenthdb2master(l
), tenthdb2master(r
));
359 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8751)
360 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
363 #elif defined(HAVE_TLV320)
364 audiohw_set_headphone_vol(tenthdb2master(l
), tenthdb2master(r
));
367 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
368 #endif /* !SIMULATOR */
370 #if CONFIG_CODEC != SWCODEC
371 int channel_configuration
= SOUND_CHAN_STEREO
;
372 int stereo_width
= 100;
377 #if CONFIG_CODEC != SWCODEC
378 static void set_channel_config(void)
380 /* default values: stereo */
381 unsigned long val_ll
= 0x80000;
382 unsigned long val_lr
= 0;
383 unsigned long val_rl
= 0;
384 unsigned long val_rr
= 0x80000;
386 switch(channel_configuration
)
388 /* case SOUND_CHAN_STEREO unnecessary */
390 case SOUND_CHAN_MONO
:
397 case SOUND_CHAN_CUSTOM
:
399 /* fixed point variables (matching MAS internal format)
400 integer part: upper 13 bits (inlcuding sign)
401 fractional part: lower 19 bits */
402 long fp_width
, fp_straight
, fp_cross
;
404 fp_width
= (stereo_width
<< 19) / 100;
405 if (stereo_width
<= 100)
407 fp_straight
= - ((1<<19) + fp_width
) / 2;
408 fp_cross
= fp_straight
+ fp_width
;
412 /* straight = - (1 + width) / (2 * width) */
413 fp_straight
= - ((((1<<19) + fp_width
) / (fp_width
>> 9)) << 9);
414 fp_cross
= (1<<19) + fp_straight
;
416 val_ll
= val_rr
= fp_straight
& 0xfffff;
417 val_lr
= val_rl
= fp_cross
& 0xfffff;
421 case SOUND_CHAN_MONO_LEFT
:
428 case SOUND_CHAN_MONO_RIGHT
:
435 case SOUND_CHAN_KARAOKE
:
443 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
444 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_LL
, &val_ll
, 1); /* LL */
445 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_LR
, &val_lr
, 1); /* LR */
446 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_RL
, &val_rl
, 1); /* RL */
447 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_RR
, &val_rr
, 1); /* RR */
448 #elif CONFIG_CODEC == MAS3507D
449 mas_writemem(MAS_BANK_D1
, 0x7f8, &val_ll
, 1); /* LL */
450 mas_writemem(MAS_BANK_D1
, 0x7f9, &val_lr
, 1); /* LR */
451 mas_writemem(MAS_BANK_D1
, 0x7fa, &val_rl
, 1); /* RL */
452 mas_writemem(MAS_BANK_D1
, 0x7fb, &val_rr
, 1); /* RR */
456 #endif /* CONFIG_CODEC != SWCODEC */
458 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
459 unsigned long mdb_shape_shadow
= 0;
460 unsigned long loudness_shadow
= 0;
463 void sound_set_volume(int value
)
465 if(!audio_is_initialized
)
467 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
468 unsigned tmp
= ((unsigned)(value
+ 115) & 0xff) << 8;
469 mas_codec_writereg(0x10, tmp
);
470 #elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
471 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
472 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
473 || defined(HAVE_AS3514)
474 current_volume
= value
* 10; /* tenth of dB */
475 set_prescaled_volume();
476 #elif CONFIG_CPU == PNX0101
477 int tmp
= (60 - value
* 4) & 0xff;
478 CODECVOL
= tmp
| (tmp
<< 8);
482 void sound_set_balance(int value
)
484 if(!audio_is_initialized
)
486 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
487 unsigned tmp
= ((unsigned)(value
* 127 / 100) & 0xff) << 8;
488 mas_codec_writereg(0x11, tmp
);
489 #elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 \
490 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
491 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
492 || defined(HAVE_AS3514)
493 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
494 set_prescaled_volume();
495 #elif CONFIG_CPU == PNX0101
496 /* TODO: implement for iFP */
501 void sound_set_bass(int value
)
503 if(!audio_is_initialized
)
505 #if defined(HAVE_SW_TONE_CONTROLS)
506 current_bass
= value
* 10;
507 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
508 set_prescaled_volume();
509 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
510 unsigned tmp
= ((unsigned)(value
* 8) & 0xff) << 8;
511 mas_codec_writereg(0x14, tmp
);
512 #elif CONFIG_CODEC == MAS3507D
513 mas_writereg(MAS_REG_KBASS
, bass_table
[value
+15]);
514 current_bass
= value
* 10;
515 set_prescaled_volume();
516 #elif defined(HAVE_WM8751)
517 current_bass
= value
;
518 audiohw_set_bass(value
);
519 set_prescaled_volume();
520 #elif defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_UDA1380) \
521 || defined HAVE_WM8731 || defined(HAVE_WM8721)
522 current_bass
= value
* 10;
523 audiohw_set_bass(value
);
524 set_prescaled_volume();
525 #elif CONFIG_CPU == PNX0101
526 /* TODO: implement for iFP */
531 void sound_set_treble(int value
)
533 if(!audio_is_initialized
)
535 #if defined(HAVE_SW_TONE_CONTROLS)
536 current_treble
= value
* 10;
537 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
538 set_prescaled_volume();
539 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
540 unsigned tmp
= ((unsigned)(value
* 8) & 0xff) << 8;
541 mas_codec_writereg(0x15, tmp
);
542 #elif CONFIG_CODEC == MAS3507D
543 mas_writereg(MAS_REG_KTREBLE
, treble_table
[value
+15]);
544 current_treble
= value
* 10;
545 set_prescaled_volume();
546 #elif defined(HAVE_WM8751)
547 audiohw_set_treble(value
);
548 current_treble
= value
;
549 set_prescaled_volume();
550 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_UDA1380) \
551 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
552 audiohw_set_treble(value
);
553 current_treble
= value
* 10;
554 set_prescaled_volume();
555 #elif CONFIG_CPU == PNX0101
556 /* TODO: implement for iFP */
561 void sound_set_channels(int value
)
563 #if CONFIG_CODEC == SWCODEC
564 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
566 if(!audio_is_initialized
)
568 channel_configuration
= value
;
569 set_channel_config();
573 void sound_set_stereo_width(int value
)
575 #if CONFIG_CODEC == SWCODEC
576 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
578 if(!audio_is_initialized
)
580 stereo_width
= value
;
581 if (channel_configuration
== SOUND_CHAN_CUSTOM
)
582 set_channel_config();
586 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
587 void sound_set_loudness(int value
)
589 if(!audio_is_initialized
)
591 loudness_shadow
= (loudness_shadow
& 0x04) |
592 (MAX(MIN(value
* 4, 0x44), 0) << 8);
593 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
596 void sound_set_avc(int value
)
598 if(!audio_is_initialized
)
603 tmp
= (0x1 << 8) | (0x8 << 12);
606 tmp
= (0x2 << 8) | (0x8 << 12);
609 tmp
= (0x4 << 8) | (0x8 << 12);
612 tmp
= (0x8 << 8) | (0x8 << 12);
614 case -1: /* turn off and then turn on again to decay quickly */
615 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
616 mas_codec_writereg(MAS_REG_KAVC
, 0);
622 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
625 void sound_set_mdb_strength(int value
)
627 if(!audio_is_initialized
)
629 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
632 void sound_set_mdb_harmonics(int value
)
634 if(!audio_is_initialized
)
636 int tmp
= value
* 127 / 100;
637 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
640 void sound_set_mdb_center(int value
)
642 if(!audio_is_initialized
)
644 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
647 void sound_set_mdb_shape(int value
)
649 if(!audio_is_initialized
)
651 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
652 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
655 void sound_set_mdb_enable(int value
)
657 if(!audio_is_initialized
)
659 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
660 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
663 void sound_set_superbass(int value
)
665 if(!audio_is_initialized
)
667 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
668 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
670 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
672 #else /* SIMULATOR */
674 void sound_set_volume(int value
)
676 /* 128 is SDL_MIX_MAXVOLUME */
677 sim_volume
= 128 * (value
- VOLUME_MIN
/ 10) / (VOLUME_RANGE
/ 10);
680 void sound_set_balance(int value
)
685 void sound_set_bass(int value
)
690 void sound_set_treble(int value
)
695 void sound_set_channels(int value
)
700 void sound_set_stereo_width(int value
)
705 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
706 void sound_set_loudness(int value
)
711 void sound_set_avc(int value
)
716 void sound_set_mdb_strength(int value
)
721 void sound_set_mdb_harmonics(int value
)
726 void sound_set_mdb_center(int value
)
731 void sound_set_mdb_shape(int value
)
736 void sound_set_mdb_enable(int value
)
741 void sound_set_superbass(int value
)
745 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
746 #endif /* SIMULATOR */
748 void sound_set(int setting
, int value
)
750 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
752 sound_set_val(value
);
755 #if (!defined(HAVE_AS3514) && !defined (HAVE_WM8731)) || defined(SIMULATOR)
756 int sound_val2phys(int setting
, int value
)
758 #if CONFIG_CODEC == MAS3587F
763 case SOUND_LEFT_GAIN
:
764 case SOUND_RIGHT_GAIN
:
765 result
= (value
- 2) * 15;
769 result
= value
* 15 + 210;
777 #elif defined(HAVE_UDA1380)
782 case SOUND_LEFT_GAIN
:
783 case SOUND_RIGHT_GAIN
:
785 result
= value
* 5; /* (1/2) * 10 */
793 #elif defined(HAVE_TLV320) || defined(HAVE_WM8731)
798 case SOUND_LEFT_GAIN
:
799 case SOUND_RIGHT_GAIN
:
800 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
804 result
= value
* 200; /* 0 or 20 dB */
812 #elif defined(HAVE_AS3514)
813 /* This is here for the sim only and the audio driver has its own */
818 case SOUND_LEFT_GAIN
:
819 case SOUND_RIGHT_GAIN
:
821 result
= (value
- 23) * 15;
835 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
837 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
839 /* This function works by telling the decoder that we have another
840 crystal frequency than we actually have. It will adjust its internal
841 parameters and the result is that the audio is played at another pitch.
843 The pitch value is in tenths of percent.
845 static int last_pitch
= 1000;
847 void sound_set_pitch(int pitch
)
851 if (pitch
!= last_pitch
)
853 /* Calculate the new (bogus) frequency */
854 val
= 18432 * 1000 / pitch
;
856 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
858 /* We must tell the MAS that the frequency has changed.
859 * This will unfortunately cause a short silence. */
860 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
866 int sound_get_pitch(void)
870 #else /* SIMULATOR */
871 void sound_set_pitch(int pitch
)
876 int sound_get_pitch(void)
880 #endif /* SIMULATOR */
881 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */