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 ****************************************************************************/
31 #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 static sound_set_type
* const sound_set_fns
[] =
129 [0 ... SOUND_LAST_SETTING
-1] = NULL
,
130 [SOUND_VOLUME
] = sound_set_volume
,
131 [SOUND_BASS
] = sound_set_bass
,
132 [SOUND_TREBLE
] = sound_set_treble
,
133 [SOUND_BALANCE
] = sound_set_balance
,
134 [SOUND_CHANNELS
] = sound_set_channels
,
135 [SOUND_STEREO_WIDTH
] = sound_set_stereo_width
,
136 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
137 [SOUND_LOUDNESS
] = sound_set_loudness
,
138 [SOUND_AVC
] = sound_set_avc
,
139 [SOUND_MDB_STRENGTH
] = sound_set_mdb_strength
,
140 [SOUND_MDB_HARMONICS
] = sound_set_mdb_harmonics
,
141 [SOUND_MDB_CENTER
] = sound_set_mdb_center
,
142 [SOUND_MDB_SHAPE
] = sound_set_mdb_shape
,
143 [SOUND_MDB_ENABLE
] = sound_set_mdb_enable
,
144 [SOUND_SUPERBASS
] = sound_set_superbass
,
146 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
147 [SOUND_BASS_CUTOFF
] = sound_set_bass_cutoff
,
149 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
150 [SOUND_TREBLE_CUTOFF
] = sound_set_treble_cutoff
,
154 sound_set_type
* sound_get_fn(int setting
)
156 return ((unsigned)setting
>= ARRAYLEN(sound_set_fns
)?
157 NULL
: sound_set_fns
[setting
]);
160 #if CONFIG_CODEC == SWCODEC
161 static int (*dsp_callback
)(int, intptr_t) = NULL
;
163 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
170 #if CONFIG_CODEC == MAS3507D
171 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
172 static int tenthdb2reg(int db
)
174 if (db
< -540) /* 3 dB steps */
175 return (db
+ 780) / 30;
176 else /* 1.5 dB steps */
177 return (db
+ 660) / 15;
182 #if !defined(AUDIOHW_HAVE_CLIPPING)
184 * The prescaler compensates for any kind of boosts, to prevent clipping.
186 * It's basically just a measure to make sure that audio does not clip during
187 * tone controls processing, like if i want to boost bass 12 dB, i can decrease
188 * the audio amplitude by -12 dB before processing, then increase master gain
189 * by 12 dB after processing.
192 /* all values in tenth of dB MAS3507D UDA1380 */
193 int current_volume
= 0; /* -780..+180 -840.. 0 */
194 int current_balance
= 0; /* -960..+960 -840..+840 */
195 int current_treble
= 0; /* -150..+150 0.. +60 */
196 int current_bass
= 0; /* -150..+150 0..+240 */
198 static void set_prescaled_volume(void)
203 /* The codecs listed use HW tone controls but don't have suitable prescaler
204 * functionality, so we let the prescaler stay at 0 for these, unless
205 * SW tone controls are in use. This is to avoid needing the SW DSP just for
208 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
209 || defined(HAVE_WM8711) || defined(HAVE_WM8721) || defined(HAVE_WM8731) \
210 || defined(HAVE_WM8751) || defined(HAVE_WM8758) || defined(HAVE_WM8985) \
211 || defined(HAVE_UDA1341))
213 prescale
= MAX(current_bass
, current_treble
);
215 prescale
= 0; /* no need to prescale if we don't boost
218 /* Gain up the analog volume to compensate the prescale gain reduction,
219 * but if this would push the volume over the top, reduce prescaling
220 * instead (might cause clipping). */
221 if (current_volume
+ prescale
> VOLUME_MAX
)
222 prescale
= VOLUME_MAX
- current_volume
;
225 #if defined(AUDIOHW_HAVE_PRESCALER)
226 audiohw_set_prescaler(prescale
);
228 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
231 if (current_volume
== VOLUME_MIN
)
232 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
234 l
= r
= current_volume
+ prescale
;
236 /* Balance the channels scaled by the current volume and min volume. */
237 /* Subtract a dB from VOLUME_MIN to get it to a mute level */
238 if (current_balance
> 0)
240 l
-= ((l
- (VOLUME_MIN
- ONE_DB
)) * current_balance
) / VOLUME_RANGE
;
242 else if (current_balance
< 0)
244 r
+= ((r
- (VOLUME_MIN
- ONE_DB
)) * current_balance
) / VOLUME_RANGE
;
247 #ifdef HAVE_SW_VOLUME_CONTROL
248 dsp_callback(DSP_CALLBACK_SET_SW_VOLUME
, 0);
251 #if CONFIG_CODEC == MAS3507D
252 dac_volume(tenthdb2reg(l
), tenthdb2reg(r
), false);
253 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
254 || defined(HAVE_WM8711) || defined(HAVE_WM8721) || defined(HAVE_WM8731) \
255 || defined(HAVE_WM8751) || defined(HAVE_AS3514) || defined(HAVE_TSC2100) \
256 || defined(HAVE_AK4537) || defined(HAVE_UDA1341)
257 audiohw_set_master_vol(tenthdb2master(l
), tenthdb2master(r
));
258 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
259 || (defined(HAVE_WM8751) && !defined(MROBE_100)) || defined(HAVE_WM8985)
260 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
263 #elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985)
264 audiohw_set_headphone_vol(tenthdb2master(l
), tenthdb2master(r
));
265 #elif defined(HAVE_JZ4740_CODEC)
266 audiohw_set_volume(current_volume
);
269 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
270 #endif /* !SIMULATOR */
275 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
276 unsigned long mdb_shape_shadow
= 0;
277 unsigned long loudness_shadow
= 0;
280 void sound_set_volume(int value
)
282 if(!audio_is_initialized
)
285 #if defined(AUDIOHW_HAVE_CLIPPING)
286 audiohw_set_volume(value
);
287 #elif CONFIG_CPU == PNX0101
288 int tmp
= (60 - value
* 4) & 0xff;
289 CODECVOL
= tmp
| (tmp
<< 8);
291 current_volume
= value
* 10; /* tenth of dB */
292 set_prescaled_volume();
296 void sound_set_balance(int value
)
298 if(!audio_is_initialized
)
301 #ifdef AUDIOHW_HAVE_BALANCE
302 audiohw_set_balance(value
);
304 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
305 set_prescaled_volume();
309 void sound_set_bass(int value
)
311 if(!audio_is_initialized
)
314 #if !defined(AUDIOHW_HAVE_CLIPPING)
315 #if defined(HAVE_WM8751)
316 current_bass
= value
;
318 current_bass
= value
* 10;
322 #if defined(AUDIOHW_HAVE_BASS)
323 audiohw_set_bass(value
);
325 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
328 #if !defined(AUDIOHW_HAVE_CLIPPING)
329 set_prescaled_volume();
333 void sound_set_treble(int value
)
335 if(!audio_is_initialized
)
338 #if !defined(AUDIOHW_HAVE_CLIPPING)
339 #if defined(HAVE_WM8751)
340 current_treble
= value
;
342 current_treble
= value
* 10;
346 #if defined(AUDIOHW_HAVE_TREBLE)
347 audiohw_set_treble(value
);
349 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
352 #if !defined(AUDIOHW_HAVE_CLIPPING)
353 set_prescaled_volume();
357 void sound_set_channels(int value
)
359 if(!audio_is_initialized
)
362 #if CONFIG_CODEC == SWCODEC
363 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
365 audiohw_set_channel(value
);
369 void sound_set_stereo_width(int value
)
371 if(!audio_is_initialized
)
374 #if CONFIG_CODEC == SWCODEC
375 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
377 audiohw_set_stereo_width(value
);
381 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
382 void sound_set_bass_cutoff(int value
)
384 if(!audio_is_initialized
)
387 audiohw_set_bass_cutoff(value
);
391 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
392 void sound_set_treble_cutoff(int value
)
394 if(!audio_is_initialized
)
397 audiohw_set_treble_cutoff(value
);
401 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
402 void sound_set_loudness(int value
)
404 if(!audio_is_initialized
)
406 loudness_shadow
= (loudness_shadow
& 0x04) |
407 (MAX(MIN(value
* 4, 0x44), 0) << 8);
408 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
411 void sound_set_avc(int value
)
413 if(!audio_is_initialized
)
417 static const uint16_t avc_vals
[] =
419 (0x1 << 8) | (0x8 << 12), /* 20ms */
420 (0x2 << 8) | (0x8 << 12), /* 2s */
421 (0x4 << 8) | (0x8 << 12), /* 4s */
422 (0x8 << 8) | (0x8 << 12), /* 8s */
429 tmp
= avc_vals
[value
-1];
431 case -1: /* turn off and then turn on again to decay quickly */
432 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
433 mas_codec_writereg(MAS_REG_KAVC
, 0);
439 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
442 void sound_set_mdb_strength(int value
)
444 if(!audio_is_initialized
)
446 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
449 void sound_set_mdb_harmonics(int value
)
451 if(!audio_is_initialized
)
453 int tmp
= value
* 127 / 100;
454 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
457 void sound_set_mdb_center(int value
)
459 if(!audio_is_initialized
)
461 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
464 void sound_set_mdb_shape(int value
)
466 if(!audio_is_initialized
)
468 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
469 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
472 void sound_set_mdb_enable(int value
)
474 if(!audio_is_initialized
)
476 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
477 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
480 void sound_set_superbass(int value
)
482 if(!audio_is_initialized
)
484 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
485 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
487 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
489 #else /* SIMULATOR */
491 void sound_set_volume(int value
)
493 /* 128 is SDL_MIX_MAXVOLUME */
494 sim_volume
= 128 * (value
- VOLUME_MIN
/ 10) / (VOLUME_RANGE
/ 10);
497 void sound_set_balance(int value
)
502 void sound_set_bass(int value
)
507 void sound_set_treble(int value
)
512 void sound_set_channels(int value
)
517 void sound_set_stereo_width(int value
)
522 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
523 void sound_set_loudness(int value
)
528 void sound_set_avc(int value
)
533 void sound_set_mdb_strength(int value
)
538 void sound_set_mdb_harmonics(int value
)
543 void sound_set_mdb_center(int value
)
548 void sound_set_mdb_shape(int value
)
553 void sound_set_mdb_enable(int value
)
558 void sound_set_superbass(int value
)
562 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
564 #if defined(HAVE_WM8758) || defined(HAVE_WM8985)
565 void sound_set_bass_cutoff(int value
)
570 void sound_set_treble_cutoff(int value
)
574 #endif /* HAVE_WM8758 */
576 #endif /* SIMULATOR */
578 void sound_set(int setting
, int value
)
580 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
582 sound_set_val(value
);
585 #if (!defined(HAVE_AS3514) && !defined(HAVE_WM8975) \
586 && !defined(HAVE_WM8758) && !defined(HAVE_TSC2100) \
587 && !defined (HAVE_WM8711) && !defined (HAVE_WM8721) \
588 && !defined (HAVE_WM8731) && !defined (HAVE_WM8978) \
589 && !defined(HAVE_AK4537)) || defined(SIMULATOR)
590 int sound_val2phys(int setting
, int value
)
592 #if CONFIG_CODEC == MAS3587F
597 case SOUND_LEFT_GAIN
:
598 case SOUND_RIGHT_GAIN
:
599 result
= (value
- 2) * 15;
603 result
= value
* 15 + 210;
611 #elif defined(HAVE_UDA1380)
616 #ifdef HAVE_RECORDING
617 case SOUND_LEFT_GAIN
:
618 case SOUND_RIGHT_GAIN
:
620 result
= value
* 5; /* (1/2) * 10 */
628 #elif defined(HAVE_TLV320) || defined(HAVE_WM8711) \
629 || defined(HAVE_WM8721) || defined(HAVE_WM8731)
634 #ifdef HAVE_RECORDING
635 case SOUND_LEFT_GAIN
:
636 case SOUND_RIGHT_GAIN
:
637 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
641 result
= value
* 200; /* 0 or 20 dB */
649 #elif defined(HAVE_AS3514)
650 /* This is here for the sim only and the audio driver has its own */
655 #ifdef HAVE_RECORDING
656 case SOUND_LEFT_GAIN
:
657 case SOUND_RIGHT_GAIN
:
659 result
= (value
- 23) * 15;
668 #elif defined(HAVE_WM8978)
673 #ifdef HAVE_RECORDING
674 case SOUND_LEFT_GAIN
:
675 case SOUND_RIGHT_GAIN
:
691 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
693 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
695 /* This function works by telling the decoder that we have another
696 crystal frequency than we actually have. It will adjust its internal
697 parameters and the result is that the audio is played at another pitch.
699 The pitch value precision is based on PITCH_SPEED_PRECISION (in dsp.h)
701 static int last_pitch
= PITCH_SPEED_100
;
703 void sound_set_pitch(int32_t pitch
)
707 if (pitch
!= last_pitch
)
709 /* Calculate the new (bogus) frequency */
710 val
= 18432 * PITCH_SPEED_100
/ pitch
;
712 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
714 /* We must tell the MAS that the frequency has changed.
715 * This will unfortunately cause a short silence. */
716 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
722 int32_t sound_get_pitch(void)
726 #else /* SIMULATOR */
727 void sound_set_pitch(int32_t pitch
)
732 int32_t sound_get_pitch(void)
734 return PITCH_SPEED_100
;
736 #endif /* SIMULATOR */
737 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */