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
44 #if !defined(VOLUME_MIN) && !defined(VOLUME_MAX)
45 #warning define for VOLUME_MIN and VOLUME_MAX is missing
46 #define VOLUME_MIN -700
50 /* volume/balance/treble/bass interdependency main part */
51 #define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
54 extern bool audio_is_initialized
;
56 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
57 extern unsigned long shadow_io_control_main
;
58 extern unsigned shadow_codec_reg0
;
60 #endif /* SIMULATOR */
64 const struct sound_settings_info audiohw_settings
[] = {
65 [SOUND_VOLUME
] = {"dB", 0, 1, VOLUME_MIN
/ 10, VOLUME_MAX
/ 10, -25},
66 [SOUND_BASS
] = {"dB", 0, 1, -24, 24, 0},
67 [SOUND_TREBLE
] = {"dB", 0, 1, -24, 24, 0},
68 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
69 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
70 [SOUND_STEREO_WIDTH
] = {"%", 0, 5, 0, 250, 100},
71 #if defined(HAVE_RECORDING)
72 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
73 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
74 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
76 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
77 [SOUND_BASS_CUTOFF
] = {"", 0, 1, 1, 4, 1},
79 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
80 [SOUND_TREBLE_CUTOFF
] = {"", 0, 1, 1, 4, 1},
82 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
83 [SOUND_LOUDNESS
] = {"dB", 0, 1, 0, 17, 0},
84 [SOUND_AVC
] = {"", 0, 1, -1, 4, 0},
85 [SOUND_MDB_STRENGTH
] = {"dB", 0, 1, 0, 127, 48},
86 [SOUND_MDB_HARMONICS
] = {"%", 0, 1, 0, 100, 50},
87 [SOUND_MDB_CENTER
] = {"Hz", 0, 10, 20, 300, 60},
88 [SOUND_MDB_SHAPE
] = {"Hz", 0, 10, 50, 300, 90},
89 [SOUND_MDB_ENABLE
] = {"", 0, 1, 0, 1, 0},
90 [SOUND_SUPERBASS
] = {"", 0, 1, 0, 1, 0},
95 const char *sound_unit(int setting
)
97 return audiohw_settings
[setting
].unit
;
100 int sound_numdecimals(int setting
)
102 return audiohw_settings
[setting
].numdecimals
;
105 int sound_steps(int setting
)
107 return audiohw_settings
[setting
].steps
;
110 int sound_min(int setting
)
112 return audiohw_settings
[setting
].minval
;
115 int sound_max(int setting
)
117 return audiohw_settings
[setting
].maxval
;
120 int sound_default(int setting
)
122 return audiohw_settings
[setting
].defaultval
;
125 sound_set_type
* sound_get_fn(int setting
)
127 sound_set_type
* result
= NULL
;
131 result
= sound_set_volume
;
135 result
= sound_set_bass
;
139 result
= sound_set_treble
;
143 result
= sound_set_balance
;
147 result
= sound_set_channels
;
150 case SOUND_STEREO_WIDTH
:
151 result
= sound_set_stereo_width
;
154 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
155 case SOUND_BASS_CUTOFF
:
156 result
= sound_set_bass_cutoff
;
160 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
161 case SOUND_TREBLE_CUTOFF
:
162 result
= sound_set_treble_cutoff
;
166 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
168 result
= sound_set_loudness
;
172 result
= sound_set_avc
;
175 case SOUND_MDB_STRENGTH
:
176 result
= sound_set_mdb_strength
;
179 case SOUND_MDB_HARMONICS
:
180 result
= sound_set_mdb_harmonics
;
183 case SOUND_MDB_CENTER
:
184 result
= sound_set_mdb_center
;
187 case SOUND_MDB_SHAPE
:
188 result
= sound_set_mdb_shape
;
191 case SOUND_MDB_ENABLE
:
192 result
= sound_set_mdb_enable
;
195 case SOUND_SUPERBASS
:
196 result
= sound_set_superbass
;
204 #if CONFIG_CODEC == SWCODEC
205 /* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */
207 DSP_CALLBACK_SET_PRESCALE
= 0,
208 DSP_CALLBACK_SET_BASS
,
209 DSP_CALLBACK_SET_TREBLE
,
210 DSP_CALLBACK_SET_CHANNEL_CONFIG
,
211 DSP_CALLBACK_SET_STEREO_WIDTH
214 static int (*dsp_callback
)(int, intptr_t) = NULL
;
216 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
223 #if CONFIG_CODEC == MAS3507D
224 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
225 static int tenthdb2reg(int db
)
227 if (db
< -540) /* 3 dB steps */
228 return (db
+ 780) / 30;
229 else /* 1.5 dB steps */
230 return (db
+ 660) / 15;
235 #if !defined(AUDIOHW_HAVE_CLIPPING)
237 * The prescaler compensates for any kind of boosts, to prevent clipping.
239 * It's basically just a measure to make sure that audio does not clip during
240 * tone controls processing, like if i want to boost bass 12 dB, i can decrease
241 * the audio amplitude by -12 dB before processing, then increase master gain
242 * by 12 dB after processing.
245 /* all values in tenth of dB MAS3507D UDA1380 */
246 int current_volume
= 0; /* -780..+180 -840.. 0 */
247 int current_balance
= 0; /* -960..+960 -840..+840 */
248 int current_treble
= 0; /* -150..+150 0.. +60 */
249 int current_bass
= 0; /* -150..+150 0..+240 */
251 static void set_prescaled_volume(void)
256 /* The WM codecs listed don't have suitable prescaler functionality, so we let
257 * the prescaler stay at 0 for these unless SW tone controls are in use */
258 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
259 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
260 || defined(HAVE_WM8758) || defined(HAVE_WM8985)) || defined(HAVE_TSC2100)
262 prescale
= MAX(current_bass
, current_treble
);
264 prescale
= 0; /* no need to prescale if we don't boost
267 /* Gain up the analog volume to compensate the prescale gain reduction,
268 * but if this would push the volume over the top, reduce prescaling
269 * instead (might cause clipping). */
270 if (current_volume
+ prescale
> VOLUME_MAX
)
271 prescale
= VOLUME_MAX
- current_volume
;
274 #if defined(AUDIOHW_HAVE_PRESCALER)
275 audiohw_set_prescaler(prescale
);
277 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
280 if (current_volume
== VOLUME_MIN
)
281 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
283 l
= r
= current_volume
+ prescale
;
285 if (current_balance
> 0)
287 l
-= current_balance
;
291 if (current_balance
< 0)
293 r
+= current_balance
;
298 #if CONFIG_CODEC == MAS3507D
299 dac_volume(tenthdb2reg(l
), tenthdb2reg(r
), false);
300 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
301 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
302 || defined(HAVE_AS3514) || defined(HAVE_TSC2100)
303 audiohw_set_master_vol(tenthdb2master(l
), tenthdb2master(r
));
304 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
305 || (defined(HAVE_WM8751) && !defined(MROBE_100)) \
306 || defined(HAVE_TSC2100) || defined(HAVE_WM8985)
307 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
310 #elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985)
311 audiohw_set_headphone_vol(tenthdb2master(l
), tenthdb2master(r
));
314 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
315 #endif /* !SIMULATOR */
320 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
321 unsigned long mdb_shape_shadow
= 0;
322 unsigned long loudness_shadow
= 0;
325 void sound_set_volume(int value
)
327 if(!audio_is_initialized
)
330 #if defined(AUDIOHW_HAVE_CLIPPING)
331 audiohw_set_volume(value
);
332 #elif CONFIG_CPU == PNX0101
333 int tmp
= (60 - value
* 4) & 0xff;
334 CODECVOL
= tmp
| (tmp
<< 8);
336 current_volume
= value
* 10; /* tenth of dB */
337 set_prescaled_volume();
341 void sound_set_balance(int value
)
343 if(!audio_is_initialized
)
346 #ifdef AUDIOHW_HAVE_BALANCE
347 audiohw_set_balance(value
);
349 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
350 set_prescaled_volume();
354 void sound_set_bass(int value
)
356 if(!audio_is_initialized
)
359 #if !defined(AUDIOHW_HAVE_CLIPPING)
360 #if defined(HAVE_WM8751)
361 current_bass
= value
;
363 current_bass
= value
* 10;
367 #if defined(AUDIOHW_HAVE_BASS)
368 audiohw_set_bass(value
);
370 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
373 #if !defined(AUDIOHW_HAVE_CLIPPING)
374 set_prescaled_volume();
378 void sound_set_treble(int value
)
380 if(!audio_is_initialized
)
383 #if !defined(AUDIOHW_HAVE_CLIPPING)
384 #if defined(HAVE_WM8751)
385 current_treble
= value
;
387 current_treble
= value
* 10;
391 #if defined(AUDIOHW_HAVE_TREBLE)
392 audiohw_set_treble(value
);
394 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
397 #if !defined(AUDIOHW_HAVE_CLIPPING)
398 set_prescaled_volume();
402 void sound_set_channels(int value
)
404 if(!audio_is_initialized
)
407 #if CONFIG_CODEC == SWCODEC
408 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
410 audiohw_set_channel(value
);
414 void sound_set_stereo_width(int value
)
416 if(!audio_is_initialized
)
419 #if CONFIG_CODEC == SWCODEC
420 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
422 audiohw_set_stereo_width(value
);
426 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
427 void sound_set_bass_cutoff(int value
)
429 if(!audio_is_initialized
)
432 audiohw_set_bass_cutoff(value
);
436 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
437 void sound_set_treble_cutoff(int value
)
439 if(!audio_is_initialized
)
442 audiohw_set_treble_cutoff(value
);
446 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
447 void sound_set_loudness(int value
)
449 if(!audio_is_initialized
)
451 loudness_shadow
= (loudness_shadow
& 0x04) |
452 (MAX(MIN(value
* 4, 0x44), 0) << 8);
453 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
456 void sound_set_avc(int value
)
458 if(!audio_is_initialized
)
463 tmp
= (0x1 << 8) | (0x8 << 12);
466 tmp
= (0x2 << 8) | (0x8 << 12);
469 tmp
= (0x4 << 8) | (0x8 << 12);
472 tmp
= (0x8 << 8) | (0x8 << 12);
474 case -1: /* turn off and then turn on again to decay quickly */
475 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
476 mas_codec_writereg(MAS_REG_KAVC
, 0);
482 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
485 void sound_set_mdb_strength(int value
)
487 if(!audio_is_initialized
)
489 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
492 void sound_set_mdb_harmonics(int value
)
494 if(!audio_is_initialized
)
496 int tmp
= value
* 127 / 100;
497 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
500 void sound_set_mdb_center(int value
)
502 if(!audio_is_initialized
)
504 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
507 void sound_set_mdb_shape(int value
)
509 if(!audio_is_initialized
)
511 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
512 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
515 void sound_set_mdb_enable(int value
)
517 if(!audio_is_initialized
)
519 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
520 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
523 void sound_set_superbass(int value
)
525 if(!audio_is_initialized
)
527 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
528 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
530 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
532 #else /* SIMULATOR */
534 void sound_set_volume(int value
)
536 /* 128 is SDL_MIX_MAXVOLUME */
537 sim_volume
= 128 * (value
- VOLUME_MIN
/ 10) / (VOLUME_RANGE
/ 10);
540 void sound_set_balance(int value
)
545 void sound_set_bass(int value
)
550 void sound_set_treble(int value
)
555 void sound_set_channels(int value
)
560 void sound_set_stereo_width(int value
)
565 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
566 void sound_set_loudness(int value
)
571 void sound_set_avc(int value
)
576 void sound_set_mdb_strength(int value
)
581 void sound_set_mdb_harmonics(int value
)
586 void sound_set_mdb_center(int value
)
591 void sound_set_mdb_shape(int value
)
596 void sound_set_mdb_enable(int value
)
601 void sound_set_superbass(int value
)
605 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
607 #if defined(HAVE_WM8758) || defined(HAVE_WM8985)
608 void sound_set_bass_cutoff(int value
)
613 void sound_set_treble_cutoff(int value
)
617 #endif /* HAVE_WM8758 */
619 #endif /* SIMULATOR */
621 void sound_set(int setting
, int value
)
623 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
625 sound_set_val(value
);
628 #if (!defined(HAVE_AS3514) && !defined (HAVE_WM8731) && !defined(HAVE_TSC2100)) \
629 || defined(SIMULATOR)
630 int sound_val2phys(int setting
, int value
)
632 #if CONFIG_CODEC == MAS3587F
637 case SOUND_LEFT_GAIN
:
638 case SOUND_RIGHT_GAIN
:
639 result
= (value
- 2) * 15;
643 result
= value
* 15 + 210;
651 #elif defined(HAVE_UDA1380)
656 case SOUND_LEFT_GAIN
:
657 case SOUND_RIGHT_GAIN
:
659 result
= value
* 5; /* (1/2) * 10 */
667 #elif defined(HAVE_TLV320) || defined(HAVE_WM8731)
672 #ifdef HAVE_RECORDING
673 case SOUND_LEFT_GAIN
:
674 case SOUND_RIGHT_GAIN
:
675 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
679 result
= value
* 200; /* 0 or 20 dB */
687 #elif defined(HAVE_AS3514)
688 /* This is here for the sim only and the audio driver has its own */
693 case SOUND_LEFT_GAIN
:
694 case SOUND_RIGHT_GAIN
:
696 result
= (value
- 23) * 15;
710 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
712 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
714 /* This function works by telling the decoder that we have another
715 crystal frequency than we actually have. It will adjust its internal
716 parameters and the result is that the audio is played at another pitch.
718 The pitch value is in tenths of percent.
720 static int last_pitch
= 1000;
722 void sound_set_pitch(int pitch
)
726 if (pitch
!= last_pitch
)
728 /* Calculate the new (bogus) frequency */
729 val
= 18432 * 1000 / pitch
;
731 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
733 /* We must tell the MAS that the frequency has changed.
734 * This will unfortunately cause a short silence. */
735 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
741 int sound_get_pitch(void)
745 #else /* SIMULATOR */
746 void sound_set_pitch(int pitch
)
751 int sound_get_pitch(void)
755 #endif /* SIMULATOR */
756 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */