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
44 extern bool audio_is_initialized
;
46 const char *sound_unit(int setting
)
48 return audiohw_settings
[setting
].unit
;
51 int sound_numdecimals(int setting
)
53 return audiohw_settings
[setting
].numdecimals
;
56 int sound_steps(int setting
)
58 return audiohw_settings
[setting
].steps
;
61 int sound_min(int setting
)
63 return audiohw_settings
[setting
].minval
;
66 int sound_max(int setting
)
68 return audiohw_settings
[setting
].maxval
;
71 int sound_default(int setting
)
73 return audiohw_settings
[setting
].defaultval
;
76 static sound_set_type
* const sound_set_fns
[] =
78 [0 ... SOUND_LAST_SETTING
-1] = NULL
,
79 [SOUND_VOLUME
] = sound_set_volume
,
80 [SOUND_BASS
] = sound_set_bass
,
81 [SOUND_TREBLE
] = sound_set_treble
,
82 [SOUND_BALANCE
] = sound_set_balance
,
83 [SOUND_CHANNELS
] = sound_set_channels
,
84 [SOUND_STEREO_WIDTH
] = sound_set_stereo_width
,
85 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
86 [SOUND_LOUDNESS
] = sound_set_loudness
,
87 [SOUND_AVC
] = sound_set_avc
,
88 [SOUND_MDB_STRENGTH
] = sound_set_mdb_strength
,
89 [SOUND_MDB_HARMONICS
] = sound_set_mdb_harmonics
,
90 [SOUND_MDB_CENTER
] = sound_set_mdb_center
,
91 [SOUND_MDB_SHAPE
] = sound_set_mdb_shape
,
92 [SOUND_MDB_ENABLE
] = sound_set_mdb_enable
,
93 [SOUND_SUPERBASS
] = sound_set_superbass
,
94 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
95 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
96 [SOUND_BASS_CUTOFF
] = sound_set_bass_cutoff
,
98 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
99 [SOUND_TREBLE_CUTOFF
] = sound_set_treble_cutoff
,
103 sound_set_type
* sound_get_fn(int setting
)
105 return ((unsigned)setting
>= ARRAYLEN(sound_set_fns
)?
106 NULL
: sound_set_fns
[setting
]);
109 #if CONFIG_CODEC == SWCODEC
110 static int (*dsp_callback
)(int, intptr_t) = NULL
;
112 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
118 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
119 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
120 static int tenthdb2reg(int db
)
122 if (db
< -540) /* 3 dB steps */
123 return (db
+ 780) / 30;
124 else /* 1.5 dB steps */
125 return (db
+ 660) / 15;
130 #if !defined(AUDIOHW_HAVE_CLIPPING)
132 * The prescaler compensates for any kind of boosts, to prevent clipping.
134 * It's basically just a measure to make sure that audio does not clip during
135 * tone controls processing, like if i want to boost bass 12 dB, i can decrease
136 * the audio amplitude by -12 dB before processing, then increase master gain
137 * by 12 dB after processing.
140 /* all values in tenth of dB MAS3507D UDA1380 */
141 int current_volume
= 0; /* -780..+180 -840.. 0 */
142 int current_balance
= 0; /* -960..+960 -840..+840 */
143 int current_treble
= 0; /* -150..+150 0.. +60 */
144 int current_bass
= 0; /* -150..+150 0..+240 */
146 static void set_prescaled_volume(void)
151 /* The codecs listed use HW tone controls but don't have suitable prescaler
152 * functionality, so we let the prescaler stay at 0 for these, unless
153 * SW tone controls are in use. This is to avoid needing the SW DSP just for
156 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
157 || defined(HAVE_WM8711) || defined(HAVE_WM8721) || defined(HAVE_WM8731) \
158 || defined(HAVE_WM8758) || defined(HAVE_WM8985) || defined(HAVE_UDA1341))
160 prescale
= MAX(current_bass
, current_treble
);
162 prescale
= 0; /* no need to prescale if we don't boost
165 /* Gain up the analog volume to compensate the prescale gain reduction,
166 * but if this would push the volume over the top, reduce prescaling
167 * instead (might cause clipping). */
168 if (current_volume
+ prescale
> VOLUME_MAX
)
169 prescale
= VOLUME_MAX
- current_volume
;
172 #if defined(AUDIOHW_HAVE_PRESCALER)
173 audiohw_set_prescaler(prescale
);
175 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
178 if (current_volume
== VOLUME_MIN
)
179 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
181 l
= r
= current_volume
+ prescale
;
183 /* Balance the channels scaled by the current volume and min volume. */
184 /* Subtract a dB from VOLUME_MIN to get it to a mute level */
185 if (current_balance
> 0)
187 l
-= ((l
- (VOLUME_MIN
- ONE_DB
)) * current_balance
) / VOLUME_RANGE
;
189 else if (current_balance
< 0)
191 r
+= ((r
- (VOLUME_MIN
- ONE_DB
)) * current_balance
) / VOLUME_RANGE
;
194 #ifdef HAVE_SW_VOLUME_CONTROL
195 dsp_callback(DSP_CALLBACK_SET_SW_VOLUME
, 0);
199 #if CONFIG_CODEC == MAS3507D
200 dac_volume(tenthdb2reg(l
), tenthdb2reg(r
), false);
201 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
202 || defined(HAVE_WM8711) || defined(HAVE_WM8721) || defined(HAVE_WM8731) \
203 || defined(HAVE_WM8750) || defined(HAVE_WM8751) || defined(HAVE_AS3514) \
204 || defined(HAVE_TSC2100) || defined(HAVE_AK4537) || defined(HAVE_UDA1341)
205 audiohw_set_master_vol(tenthdb2master(l
), tenthdb2master(r
));
206 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
207 || defined(HAVE_WM8750) || (defined(HAVE_WM8751) && !defined(MROBE_100)) \
208 || defined(HAVE_WM8985)
209 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
212 #elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985)
213 audiohw_set_headphone_vol(tenthdb2master(l
), tenthdb2master(r
));
214 #elif defined(HAVE_JZ4740_CODEC) || defined(HAVE_SDL_AUDIO)
215 audiohw_set_volume(current_volume
);
217 #else /* SIMULATOR */
218 audiohw_set_volume(current_volume
);
219 #endif /* !SIMULATOR */
221 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
224 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
225 unsigned long mdb_shape_shadow
= 0;
226 unsigned long loudness_shadow
= 0;
229 void sound_set_volume(int value
)
231 if(!audio_is_initialized
)
234 #if defined(AUDIOHW_HAVE_CLIPPING)
235 audiohw_set_volume(value
);
236 #elif CONFIG_CPU == PNX0101
237 int tmp
= (60 - value
* 4) & 0xff;
238 CODECVOL
= tmp
| (tmp
<< 8);
240 current_volume
= value
* 10; /* tenth of dB */
241 set_prescaled_volume();
245 void sound_set_balance(int value
)
247 if(!audio_is_initialized
)
250 #ifdef AUDIOHW_HAVE_BALANCE
251 audiohw_set_balance(value
);
253 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
254 set_prescaled_volume();
258 void sound_set_bass(int value
)
260 if(!audio_is_initialized
)
263 #if !defined(AUDIOHW_HAVE_CLIPPING)
264 #if defined(HAVE_WM8750) || defined(HAVE_WM8751)
265 current_bass
= value
;
267 current_bass
= value
* 10;
271 #if defined(AUDIOHW_HAVE_BASS)
272 audiohw_set_bass(value
);
274 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
277 #if !defined(AUDIOHW_HAVE_CLIPPING)
278 set_prescaled_volume();
282 void sound_set_treble(int value
)
284 if(!audio_is_initialized
)
287 #if !defined(AUDIOHW_HAVE_CLIPPING)
288 #if defined(HAVE_WM8750) || defined(HAVE_WM8751)
289 current_treble
= value
;
291 current_treble
= value
* 10;
295 #if defined(AUDIOHW_HAVE_TREBLE)
296 audiohw_set_treble(value
);
298 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
301 #if !defined(AUDIOHW_HAVE_CLIPPING)
302 set_prescaled_volume();
306 void sound_set_channels(int value
)
308 if(!audio_is_initialized
)
311 #if CONFIG_CODEC == SWCODEC
312 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
314 audiohw_set_channel(value
);
318 void sound_set_stereo_width(int value
)
320 if(!audio_is_initialized
)
323 #if CONFIG_CODEC == SWCODEC
324 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
326 audiohw_set_stereo_width(value
);
330 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
331 void sound_set_bass_cutoff(int value
)
333 if(!audio_is_initialized
)
336 audiohw_set_bass_cutoff(value
);
340 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
341 void sound_set_treble_cutoff(int value
)
343 if(!audio_is_initialized
)
346 audiohw_set_treble_cutoff(value
);
350 #if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F))
351 void sound_set_loudness(int value
)
353 if(!audio_is_initialized
)
355 loudness_shadow
= (loudness_shadow
& 0x04) |
356 (MAX(MIN(value
* 4, 0x44), 0) << 8);
357 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
360 void sound_set_avc(int value
)
362 if(!audio_is_initialized
)
366 static const uint16_t avc_vals
[] =
368 (0x1 << 8) | (0x8 << 12), /* 20ms */
369 (0x2 << 8) | (0x8 << 12), /* 2s */
370 (0x4 << 8) | (0x8 << 12), /* 4s */
371 (0x8 << 8) | (0x8 << 12), /* 8s */
378 tmp
= avc_vals
[value
-1];
380 case -1: /* turn off and then turn on again to decay quickly */
381 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
382 mas_codec_writereg(MAS_REG_KAVC
, 0);
388 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
391 void sound_set_mdb_strength(int value
)
393 if(!audio_is_initialized
)
395 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
398 void sound_set_mdb_harmonics(int value
)
400 if(!audio_is_initialized
)
402 int tmp
= value
* 127 / 100;
403 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
406 void sound_set_mdb_center(int value
)
408 if(!audio_is_initialized
)
410 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
413 void sound_set_mdb_shape(int value
)
415 if(!audio_is_initialized
)
417 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
418 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
421 void sound_set_mdb_enable(int value
)
423 if(!audio_is_initialized
)
425 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
426 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
429 void sound_set_superbass(int value
)
431 if(!audio_is_initialized
)
433 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
434 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
436 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
438 void sound_set(int setting
, int value
)
440 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
442 sound_set_val(value
);
445 #if (!defined(HAVE_AS3514) && !defined(HAVE_WM8975) \
446 && !defined(HAVE_WM8758) && !defined(HAVE_TSC2100) \
447 && !defined (HAVE_WM8711) && !defined (HAVE_WM8721) \
448 && !defined (HAVE_WM8731) && !defined (HAVE_WM8978) \
449 && !defined(HAVE_AK4537)) || defined(SIMULATOR)
450 int sound_val2phys(int setting
, int value
)
452 #if CONFIG_CODEC == MAS3587F
457 case SOUND_LEFT_GAIN
:
458 case SOUND_RIGHT_GAIN
:
459 result
= (value
- 2) * 15;
463 result
= value
* 15 + 210;
471 #elif defined(HAVE_UDA1380)
476 #ifdef HAVE_RECORDING
477 case SOUND_LEFT_GAIN
:
478 case SOUND_RIGHT_GAIN
:
480 result
= value
* 5; /* (1/2) * 10 */
488 #elif defined(HAVE_TLV320) || defined(HAVE_WM8711) \
489 || defined(HAVE_WM8721) || defined(HAVE_WM8731)
494 #ifdef HAVE_RECORDING
495 case SOUND_LEFT_GAIN
:
496 case SOUND_RIGHT_GAIN
:
497 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
501 result
= value
* 200; /* 0 or 20 dB */
509 #elif defined(HAVE_AS3514)
510 /* This is here for the sim only and the audio driver has its own */
515 #ifdef HAVE_RECORDING
516 case SOUND_LEFT_GAIN
:
517 case SOUND_RIGHT_GAIN
:
519 result
= (value
- 23) * 15;
528 #elif defined(HAVE_WM8978)
533 #ifdef HAVE_RECORDING
534 case SOUND_LEFT_GAIN
:
535 case SOUND_RIGHT_GAIN
:
551 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
553 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
554 /* This function works by telling the decoder that we have another
555 crystal frequency than we actually have. It will adjust its internal
556 parameters and the result is that the audio is played at another pitch.
558 The pitch value precision is based on PITCH_SPEED_PRECISION (in dsp.h)
566 unsigned long shadow_io_control_main
;
567 static int last_pitch
= PITCH_SPEED_100
;
569 void sound_set_pitch(int32_t pitch
)
573 if (pitch
!= last_pitch
)
575 /* Calculate the new (bogus) frequency */
576 val
= 18432 * PITCH_SPEED_100
/ pitch
;
578 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
580 /* We must tell the MAS that the frequency has changed.
581 * This will unfortunately cause a short silence. */
582 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
588 int32_t sound_get_pitch(void)
592 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */