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 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
30 #if CONFIG_CPU == PNX0101
35 #if CONFIG_CODEC == SWCODEC
41 * find a nice way to handle 1.5db steps -> see wm8751 ifdef in sound_set_bass/treble
46 #if !defined(VOLUME_MIN) && !defined(VOLUME_MAX)
47 #warning define for VOLUME_MIN and VOLUME_MAX is missing
48 #define VOLUME_MIN -700
52 /* volume/balance/treble/bass interdependency main part */
53 #define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
56 extern bool audio_is_initialized
;
58 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
59 extern unsigned long shadow_io_control_main
;
60 extern unsigned shadow_codec_reg0
;
62 #endif /* SIMULATOR */
66 const struct sound_settings_info audiohw_settings
[] = {
67 [SOUND_VOLUME
] = {"dB", 0, 1, VOLUME_MIN
/ 10, VOLUME_MAX
/ 10, -25},
68 [SOUND_BASS
] = {"dB", 0, 1, -24, 24, 0},
69 [SOUND_TREBLE
] = {"dB", 0, 1, -24, 24, 0},
70 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
71 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
72 [SOUND_STEREO_WIDTH
] = {"%", 0, 5, 0, 250, 100},
73 #if defined(HAVE_RECORDING)
74 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
75 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
76 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
78 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
79 [SOUND_BASS_CUTOFF
] = {"", 0, 1, 1, 4, 1},
81 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
82 [SOUND_TREBLE_CUTOFF
] = {"", 0, 1, 1, 4, 1},
84 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
85 [SOUND_LOUDNESS
] = {"dB", 0, 1, 0, 17, 0},
86 [SOUND_AVC
] = {"", 0, 1, -1, 4, 0},
87 [SOUND_MDB_STRENGTH
] = {"dB", 0, 1, 0, 127, 48},
88 [SOUND_MDB_HARMONICS
] = {"%", 0, 1, 0, 100, 50},
89 [SOUND_MDB_CENTER
] = {"Hz", 0, 10, 20, 300, 60},
90 [SOUND_MDB_SHAPE
] = {"Hz", 0, 10, 50, 300, 90},
91 [SOUND_MDB_ENABLE
] = {"", 0, 1, 0, 1, 0},
92 [SOUND_SUPERBASS
] = {"", 0, 1, 0, 1, 0},
97 const char *sound_unit(int setting
)
99 return audiohw_settings
[setting
].unit
;
102 int sound_numdecimals(int setting
)
104 return audiohw_settings
[setting
].numdecimals
;
107 int sound_steps(int setting
)
109 return audiohw_settings
[setting
].steps
;
112 int sound_min(int setting
)
114 return audiohw_settings
[setting
].minval
;
117 int sound_max(int setting
)
119 return audiohw_settings
[setting
].maxval
;
122 int sound_default(int setting
)
124 return audiohw_settings
[setting
].defaultval
;
127 sound_set_type
* sound_get_fn(int setting
)
129 sound_set_type
* result
= NULL
;
133 result
= sound_set_volume
;
137 result
= sound_set_bass
;
141 result
= sound_set_treble
;
145 result
= sound_set_balance
;
149 result
= sound_set_channels
;
152 case SOUND_STEREO_WIDTH
:
153 result
= sound_set_stereo_width
;
156 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
157 case SOUND_BASS_CUTOFF
:
158 result
= sound_set_bass_cutoff
;
162 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
163 case SOUND_TREBLE_CUTOFF
:
164 result
= sound_set_treble_cutoff
;
168 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
170 result
= sound_set_loudness
;
174 result
= sound_set_avc
;
177 case SOUND_MDB_STRENGTH
:
178 result
= sound_set_mdb_strength
;
181 case SOUND_MDB_HARMONICS
:
182 result
= sound_set_mdb_harmonics
;
185 case SOUND_MDB_CENTER
:
186 result
= sound_set_mdb_center
;
189 case SOUND_MDB_SHAPE
:
190 result
= sound_set_mdb_shape
;
193 case SOUND_MDB_ENABLE
:
194 result
= sound_set_mdb_enable
;
197 case SOUND_SUPERBASS
:
198 result
= sound_set_superbass
;
206 #if CONFIG_CODEC == SWCODEC
207 /* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */
209 DSP_CALLBACK_SET_PRESCALE
= 0,
210 DSP_CALLBACK_SET_BASS
,
211 DSP_CALLBACK_SET_TREBLE
,
212 DSP_CALLBACK_SET_CHANNEL_CONFIG
,
213 DSP_CALLBACK_SET_STEREO_WIDTH
216 static int (*dsp_callback
)(int, intptr_t) = NULL
;
218 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
225 #if CONFIG_CODEC == MAS3507D
226 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
227 static int tenthdb2reg(int db
)
229 if (db
< -540) /* 3 dB steps */
230 return (db
+ 780) / 30;
231 else /* 1.5 dB steps */
232 return (db
+ 660) / 15;
237 #if !defined(AUDIOHW_HAVE_CLIPPING)
239 * The prescaler compensates for any kind of boosts, to prevent clipping.
241 * It's basically just a measure to make sure that audio does not clip during
242 * tone controls processing, like if i want to boost bass 12 dB, i can decrease
243 * the audio amplitude by -12 dB before processing, then increase master gain
244 * by 12 dB after processing.
247 /* all values in tenth of dB MAS3507D UDA1380 */
248 int current_volume
= 0; /* -780..+180 -840.. 0 */
249 int current_balance
= 0; /* -960..+960 -840..+840 */
250 int current_treble
= 0; /* -150..+150 0.. +60 */
251 int current_bass
= 0; /* -150..+150 0..+240 */
253 static void set_prescaled_volume(void)
258 /* The WM codecs listed don't have suitable prescaler functionality, so we let
259 * the prescaler stay at 0 for these unless SW tone controls are in use */
260 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
261 || defined(HAVE_WM8711) || defined(HAVE_WM8721) || defined(HAVE_WM8731) \
262 || defined(HAVE_WM8751) || defined(HAVE_WM8758) || defined(HAVE_WM8985)) \
263 || defined(HAVE_TSC2100)
265 prescale
= MAX(current_bass
, current_treble
);
267 prescale
= 0; /* no need to prescale if we don't boost
270 /* Gain up the analog volume to compensate the prescale gain reduction,
271 * but if this would push the volume over the top, reduce prescaling
272 * instead (might cause clipping). */
273 if (current_volume
+ prescale
> VOLUME_MAX
)
274 prescale
= VOLUME_MAX
- current_volume
;
277 #if defined(AUDIOHW_HAVE_PRESCALER)
278 audiohw_set_prescaler(prescale
);
280 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
283 if (current_volume
== VOLUME_MIN
)
284 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
286 l
= r
= current_volume
+ prescale
;
288 /* Balance the channels scaled by the current volume and min volume. */
289 /* Subtract a dB from VOLUME_MIN to get it to a mute level */
290 if (current_balance
> 0)
292 l
-= ((l
- (VOLUME_MIN
- ONE_DB
)) * current_balance
) / VOLUME_RANGE
;
294 else if (current_balance
< 0)
296 r
+= ((r
- (VOLUME_MIN
- ONE_DB
)) * current_balance
) / VOLUME_RANGE
;
299 #if CONFIG_CODEC == MAS3507D
300 dac_volume(tenthdb2reg(l
), tenthdb2reg(r
), false);
301 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
302 || defined(HAVE_WM8711) || defined(HAVE_WM8721) || defined(HAVE_WM8731) \
303 || defined(HAVE_WM8751) || defined(HAVE_AS3514) || defined(HAVE_TSC2100)
304 audiohw_set_master_vol(tenthdb2master(l
), tenthdb2master(r
));
305 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
306 || (defined(HAVE_WM8751) && !defined(MROBE_100)) \
307 || defined(HAVE_TSC2100) || defined(HAVE_WM8985)
308 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
311 #elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985)
312 audiohw_set_headphone_vol(tenthdb2master(l
), tenthdb2master(r
));
315 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
316 #endif /* !SIMULATOR */
321 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
322 unsigned long mdb_shape_shadow
= 0;
323 unsigned long loudness_shadow
= 0;
326 void sound_set_volume(int value
)
328 if(!audio_is_initialized
)
331 #if defined(AUDIOHW_HAVE_CLIPPING)
332 audiohw_set_volume(value
);
333 #elif CONFIG_CPU == PNX0101
334 int tmp
= (60 - value
* 4) & 0xff;
335 CODECVOL
= tmp
| (tmp
<< 8);
337 current_volume
= value
* 10; /* tenth of dB */
338 set_prescaled_volume();
342 void sound_set_balance(int value
)
344 if(!audio_is_initialized
)
347 #ifdef AUDIOHW_HAVE_BALANCE
348 audiohw_set_balance(value
);
350 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
351 set_prescaled_volume();
355 void sound_set_bass(int value
)
357 if(!audio_is_initialized
)
360 #if !defined(AUDIOHW_HAVE_CLIPPING)
361 #if defined(HAVE_WM8751)
362 current_bass
= value
;
364 current_bass
= value
* 10;
368 #if defined(AUDIOHW_HAVE_BASS)
369 audiohw_set_bass(value
);
371 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
374 #if !defined(AUDIOHW_HAVE_CLIPPING)
375 set_prescaled_volume();
379 void sound_set_treble(int value
)
381 if(!audio_is_initialized
)
384 #if !defined(AUDIOHW_HAVE_CLIPPING)
385 #if defined(HAVE_WM8751)
386 current_treble
= value
;
388 current_treble
= value
* 10;
392 #if defined(AUDIOHW_HAVE_TREBLE)
393 audiohw_set_treble(value
);
395 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
398 #if !defined(AUDIOHW_HAVE_CLIPPING)
399 set_prescaled_volume();
403 void sound_set_channels(int value
)
405 if(!audio_is_initialized
)
408 #if CONFIG_CODEC == SWCODEC
409 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
411 audiohw_set_channel(value
);
415 void sound_set_stereo_width(int value
)
417 if(!audio_is_initialized
)
420 #if CONFIG_CODEC == SWCODEC
421 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
423 audiohw_set_stereo_width(value
);
427 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
428 void sound_set_bass_cutoff(int value
)
430 if(!audio_is_initialized
)
433 audiohw_set_bass_cutoff(value
);
437 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
438 void sound_set_treble_cutoff(int value
)
440 if(!audio_is_initialized
)
443 audiohw_set_treble_cutoff(value
);
447 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
448 void sound_set_loudness(int value
)
450 if(!audio_is_initialized
)
452 loudness_shadow
= (loudness_shadow
& 0x04) |
453 (MAX(MIN(value
* 4, 0x44), 0) << 8);
454 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
457 void sound_set_avc(int value
)
459 if(!audio_is_initialized
)
464 tmp
= (0x1 << 8) | (0x8 << 12);
467 tmp
= (0x2 << 8) | (0x8 << 12);
470 tmp
= (0x4 << 8) | (0x8 << 12);
473 tmp
= (0x8 << 8) | (0x8 << 12);
475 case -1: /* turn off and then turn on again to decay quickly */
476 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
477 mas_codec_writereg(MAS_REG_KAVC
, 0);
483 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
486 void sound_set_mdb_strength(int value
)
488 if(!audio_is_initialized
)
490 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
493 void sound_set_mdb_harmonics(int value
)
495 if(!audio_is_initialized
)
497 int tmp
= value
* 127 / 100;
498 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
501 void sound_set_mdb_center(int value
)
503 if(!audio_is_initialized
)
505 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
508 void sound_set_mdb_shape(int value
)
510 if(!audio_is_initialized
)
512 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
513 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
516 void sound_set_mdb_enable(int value
)
518 if(!audio_is_initialized
)
520 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
521 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
524 void sound_set_superbass(int value
)
526 if(!audio_is_initialized
)
528 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
529 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
531 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
533 #else /* SIMULATOR */
535 void sound_set_volume(int value
)
537 /* 128 is SDL_MIX_MAXVOLUME */
538 sim_volume
= 128 * (value
- VOLUME_MIN
/ 10) / (VOLUME_RANGE
/ 10);
541 void sound_set_balance(int value
)
546 void sound_set_bass(int value
)
551 void sound_set_treble(int value
)
556 void sound_set_channels(int value
)
561 void sound_set_stereo_width(int value
)
566 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
567 void sound_set_loudness(int value
)
572 void sound_set_avc(int value
)
577 void sound_set_mdb_strength(int value
)
582 void sound_set_mdb_harmonics(int value
)
587 void sound_set_mdb_center(int value
)
592 void sound_set_mdb_shape(int value
)
597 void sound_set_mdb_enable(int value
)
602 void sound_set_superbass(int value
)
606 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
608 #if defined(HAVE_WM8758) || defined(HAVE_WM8985)
609 void sound_set_bass_cutoff(int value
)
614 void sound_set_treble_cutoff(int value
)
618 #endif /* HAVE_WM8758 */
620 #endif /* SIMULATOR */
622 void sound_set(int setting
, int value
)
624 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
626 sound_set_val(value
);
629 #if (!defined(HAVE_AS3514) && !defined(HAVE_WM8975) \
630 && !defined(HAVE_WM8758) && !defined(HAVE_TSC2100) \
631 && !defined (HAVE_WM8711) && !defined (HAVE_WM8721) \
632 && !defined (HAVE_WM8731) && !defined (HAVE_WM8978)) \
633 || defined(SIMULATOR)
634 int sound_val2phys(int setting
, int value
)
636 #if CONFIG_CODEC == MAS3587F
641 case SOUND_LEFT_GAIN
:
642 case SOUND_RIGHT_GAIN
:
643 result
= (value
- 2) * 15;
647 result
= value
* 15 + 210;
655 #elif defined(HAVE_UDA1380)
660 case SOUND_LEFT_GAIN
:
661 case SOUND_RIGHT_GAIN
:
663 result
= value
* 5; /* (1/2) * 10 */
671 #elif defined(HAVE_TLV320) || defined(HAVE_WM8711) \
672 || defined(HAVE_WM8721) || defined(HAVE_WM8731)
677 #ifdef HAVE_RECORDING
678 case SOUND_LEFT_GAIN
:
679 case SOUND_RIGHT_GAIN
:
680 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
684 result
= value
* 200; /* 0 or 20 dB */
692 #elif defined(HAVE_AS3514)
693 /* This is here for the sim only and the audio driver has its own */
698 #ifdef HAVE_RECORDING
699 case SOUND_LEFT_GAIN
:
700 case SOUND_RIGHT_GAIN
:
702 result
= (value
- 23) * 15;
711 #elif defined(HAVE_WM8978)
716 #ifdef HAVE_RECORDING
717 case SOUND_LEFT_GAIN
:
718 case SOUND_RIGHT_GAIN
:
734 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
736 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
738 /* This function works by telling the decoder that we have another
739 crystal frequency than we actually have. It will adjust its internal
740 parameters and the result is that the audio is played at another pitch.
742 The pitch value is in tenths of percent.
744 static int last_pitch
= 1000;
746 void sound_set_pitch(int pitch
)
750 if (pitch
!= last_pitch
)
752 /* Calculate the new (bogus) frequency */
753 val
= 18432 * 1000 / pitch
;
755 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
757 /* We must tell the MAS that the frequency has changed.
758 * This will unfortunately cause a short silence. */
759 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
765 int sound_get_pitch(void)
769 #else /* SIMULATOR */
770 void sound_set_pitch(int pitch
)
775 int sound_get_pitch(void)
779 #endif /* SIMULATOR */
780 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */