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
39 * find a nice way to handle 1.5db steps -> see wm8751 ifdef in sound_set_bass/treble
42 #if !defined(VOLUME_MIN) && !defined(VOLUME_MAX)
43 #warning define for VOLUME_MIN and VOLUME_MAX is missing
44 #define VOLUME_MIN -400
45 #define VOLUME_MAX 600
48 /* volume/balance/treble/bass interdependency main part */
49 #define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
52 extern bool audio_is_initialized
;
54 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
55 extern unsigned long shadow_io_control_main
;
56 extern unsigned shadow_codec_reg0
;
58 #endif /* SIMULATOR */
62 const struct sound_settings_info audiohw_settings
[] = {
63 [SOUND_VOLUME
] = {"dB", 0, 1, VOLUME_MIN
/ 10, VOLUME_MAX
/ 10, -25},
64 [SOUND_BASS
] = {"dB", 0, 1, -24, 24, 0},
65 [SOUND_TREBLE
] = {"dB", 0, 1, -24, 24, 0},
66 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
67 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
68 [SOUND_STEREO_WIDTH
] = {"%", 0, 5, 0, 250, 100},
69 #if CONFIG_CODEC == MAS3587F || defined(HAVE_UDA1380) || defined(HAVE_TLV320)\
70 || defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
71 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
72 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
73 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
75 #if defined(HAVE_WM8758)
76 [SOUND_BASS_CUTOFF
] = {"", 0, 1, 1, 4, 1},
77 [SOUND_TREBLE_CUTOFF
] = {"", 0, 1, 1, 4, 1},
79 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
80 [SOUND_LOUDNESS
] = {"dB", 0, 1, 0, 17, 0},
81 [SOUND_AVC
] = {"", 0, 1, -1, 4, 0},
82 [SOUND_MDB_STRENGTH
] = {"dB", 0, 1, 0, 127, 48},
83 [SOUND_MDB_HARMONICS
] = {"%", 0, 1, 0, 100, 50},
84 [SOUND_MDB_CENTER
] = {"Hz", 0, 10, 20, 300, 60},
85 [SOUND_MDB_SHAPE
] = {"Hz", 0, 10, 50, 300, 90},
86 [SOUND_MDB_ENABLE
] = {"", 0, 1, 0, 1, 0},
87 [SOUND_SUPERBASS
] = {"", 0, 1, 0, 1, 0},
92 const char *sound_unit(int setting
)
94 return audiohw_settings
[setting
].unit
;
97 int sound_numdecimals(int setting
)
99 return audiohw_settings
[setting
].numdecimals
;
102 int sound_steps(int setting
)
104 return audiohw_settings
[setting
].steps
;
107 int sound_min(int setting
)
109 return audiohw_settings
[setting
].minval
;
112 int sound_max(int setting
)
114 return audiohw_settings
[setting
].maxval
;
117 int sound_default(int setting
)
119 return audiohw_settings
[setting
].defaultval
;
122 sound_set_type
* sound_get_fn(int setting
)
124 sound_set_type
* result
= NULL
;
128 result
= sound_set_volume
;
132 result
= sound_set_bass
;
136 result
= sound_set_treble
;
140 result
= sound_set_balance
;
144 result
= sound_set_channels
;
147 case SOUND_STEREO_WIDTH
:
148 result
= sound_set_stereo_width
;
152 case SOUND_BASS_CUTOFF
:
153 result
= sound_set_bass_cutoff
;
156 case SOUND_TREBLE_CUTOFF
:
157 result
= sound_set_treble_cutoff
;
161 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
163 result
= sound_set_loudness
;
167 result
= sound_set_avc
;
170 case SOUND_MDB_STRENGTH
:
171 result
= sound_set_mdb_strength
;
174 case SOUND_MDB_HARMONICS
:
175 result
= sound_set_mdb_harmonics
;
178 case SOUND_MDB_CENTER
:
179 result
= sound_set_mdb_center
;
182 case SOUND_MDB_SHAPE
:
183 result
= sound_set_mdb_shape
;
186 case SOUND_MDB_ENABLE
:
187 result
= sound_set_mdb_enable
;
190 case SOUND_SUPERBASS
:
191 result
= sound_set_superbass
;
199 #if CONFIG_CODEC == SWCODEC
200 /* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */
202 DSP_CALLBACK_SET_PRESCALE
= 0,
203 DSP_CALLBACK_SET_BASS
,
204 DSP_CALLBACK_SET_TREBLE
,
205 DSP_CALLBACK_SET_CHANNEL_CONFIG
,
206 DSP_CALLBACK_SET_STEREO_WIDTH
209 static int (*dsp_callback
)(int, intptr_t) = NULL
;
211 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
218 #if CONFIG_CODEC == MAS3507D
219 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
220 static int tenthdb2reg(int db
)
222 if (db
< -540) /* 3 dB steps */
223 return (db
+ 780) / 30;
224 else /* 1.5 dB steps */
225 return (db
+ 660) / 15;
230 /* MAS3587F and MAS3539F handle clipping prevention internally so we do not need
233 #if (CONFIG_CODEC != MAS3587F) && (CONFIG_CODEC != MAS3539F)
236 * The prescaler compensates for any kind of boosts, to prevent clipping.
238 * It's basically just a measure to make sure that audio does not clip during
239 * tone controls processing, like if i want to boost bass 12 dB, i can decrease
240 * the audio amplitude by -12 dB before processing, then increase master gain
241 * by 12 dB after processing.
244 /* all values in tenth of dB MAS3507D UDA1380 */
245 int current_volume
= 0; /* -780..+180 -840.. 0 */
246 int current_balance
= 0; /* -960..+960 -840..+840 */
247 int current_treble
= 0; /* -150..+150 0.. +60 */
248 int current_bass
= 0; /* -150..+150 0..+240 */
250 static void set_prescaled_volume(void)
255 /* The WM codecs listed don't have suitable prescaler functionality, so we let
256 * the prescaler stay at 0 for these unless SW tone controls are in use */
257 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
258 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
259 || defined(HAVE_WM8758) || defined(HAVE_WM8985)) || defined(HAVE_TSC2100)
261 prescale
= MAX(current_bass
, current_treble
);
263 prescale
= 0; /* no need to prescale if we don't boost
266 /* Gain up the analog volume to compensate the prescale gain reduction,
267 * but if this would push the volume over the top, reduce prescaling
268 * instead (might cause clipping). */
269 if (current_volume
+ prescale
> VOLUME_MAX
)
270 prescale
= VOLUME_MAX
- current_volume
;
273 #if defined(HAVE_SW_TONE_CONTROLS)
274 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
275 #elif CONFIG_CODEC == MAS3507D
276 mas_writereg(MAS_REG_KPRESCALE
, prescale_table
[prescale
/10]);
277 #elif defined(HAVE_UDA1380)
278 audiohw_set_mixer_vol(tenthdb2mixer(-prescale
), tenthdb2mixer(-prescale
));
281 if (current_volume
== VOLUME_MIN
)
282 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
284 l
= r
= current_volume
+ prescale
;
286 if (current_balance
> 0)
288 l
-= current_balance
;
292 if (current_balance
< 0)
294 r
+= current_balance
;
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_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
303 || 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)
308 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
311 #elif defined(HAVE_TLV320) || defined(HAVE_WM8978)
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
)
330 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
331 unsigned tmp
= ((unsigned)(value
+ 115) & 0xff) << 8;
332 mas_codec_writereg(0x10, tmp
);
333 #elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
334 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
335 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
336 || defined(HAVE_AS3514) || defined(HAVE_WM8985) || defined(HAVE_TSC2100) \
337 || defined(HAVE_WM8978)
338 current_volume
= value
* 10; /* tenth of dB */
339 set_prescaled_volume();
340 #elif CONFIG_CPU == PNX0101
341 int tmp
= (60 - value
* 4) & 0xff;
342 CODECVOL
= tmp
| (tmp
<< 8);
347 void sound_set_balance(int value
)
349 if(!audio_is_initialized
)
351 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
352 unsigned tmp
= ((unsigned)(value
* 127 / 100) & 0xff) << 8;
353 mas_codec_writereg(0x11, tmp
);
354 #elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 \
355 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
356 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
357 || defined(HAVE_AS3514) || defined(HAVE_WM8985) || defined(HAVE_TSC2100) \
358 || defined(HAVE_WM8978)
359 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
360 set_prescaled_volume();
361 #elif CONFIG_CPU == PNX0101
362 /* TODO: implement for iFP */
367 void sound_set_bass(int value
)
369 if(!audio_is_initialized
)
372 #if defined(AUDIOHW_HAVE_BASS)
373 audiohw_set_bass(value
);
375 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
378 #if (CONFIG_CODEC != MAS3587F) && (CONFIG_CODEC != MAS3539F)
379 #if defined(HAVE_WM8751)
380 current_bass
= value
;
382 current_bass
= value
* 10;
384 set_prescaled_volume();
388 void sound_set_treble(int value
)
390 if(!audio_is_initialized
)
393 #if defined(AUDIOHW_HAVE_TREBLE)
394 audiohw_set_treble(value
);
396 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
399 #if (CONFIG_CODEC != MAS3587F) && (CONFIG_CODEC != MAS3539F)
400 #if defined(HAVE_WM8751)
401 current_treble
= value
;
403 current_treble
= value
* 10;
405 set_prescaled_volume();
409 void sound_set_channels(int value
)
411 if(!audio_is_initialized
)
414 #if CONFIG_CODEC == SWCODEC
415 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
417 audiohw_set_channel(value
);
421 void sound_set_stereo_width(int value
)
423 if(!audio_is_initialized
)
426 #if CONFIG_CODEC == SWCODEC
427 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
429 audiohw_set_stereo_width(value
);
433 #if defined(HAVE_WM8758) || defined(HAVE_WM8985)
434 void sound_set_bass_cutoff(int value
)
436 if(!audio_is_initialized
)
439 audiohw_set_bass_cutoff(value
);
442 void sound_set_treble_cutoff(int value
)
444 if(!audio_is_initialized
)
447 audiohw_set_treble_cutoff(value
);
451 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
452 void sound_set_loudness(int value
)
454 if(!audio_is_initialized
)
456 loudness_shadow
= (loudness_shadow
& 0x04) |
457 (MAX(MIN(value
* 4, 0x44), 0) << 8);
458 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
461 void sound_set_avc(int value
)
463 if(!audio_is_initialized
)
468 tmp
= (0x1 << 8) | (0x8 << 12);
471 tmp
= (0x2 << 8) | (0x8 << 12);
474 tmp
= (0x4 << 8) | (0x8 << 12);
477 tmp
= (0x8 << 8) | (0x8 << 12);
479 case -1: /* turn off and then turn on again to decay quickly */
480 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
481 mas_codec_writereg(MAS_REG_KAVC
, 0);
487 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
490 void sound_set_mdb_strength(int value
)
492 if(!audio_is_initialized
)
494 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
497 void sound_set_mdb_harmonics(int value
)
499 if(!audio_is_initialized
)
501 int tmp
= value
* 127 / 100;
502 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
505 void sound_set_mdb_center(int value
)
507 if(!audio_is_initialized
)
509 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
512 void sound_set_mdb_shape(int value
)
514 if(!audio_is_initialized
)
516 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
517 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
520 void sound_set_mdb_enable(int value
)
522 if(!audio_is_initialized
)
524 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
525 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
528 void sound_set_superbass(int value
)
530 if(!audio_is_initialized
)
532 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
533 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
535 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
537 #else /* SIMULATOR */
539 void sound_set_volume(int value
)
541 /* 128 is SDL_MIX_MAXVOLUME */
542 sim_volume
= 128 * (value
- VOLUME_MIN
/ 10) / (VOLUME_RANGE
/ 10);
545 void sound_set_balance(int value
)
550 void sound_set_bass(int value
)
555 void sound_set_treble(int value
)
560 void sound_set_channels(int value
)
565 void sound_set_stereo_width(int value
)
570 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
571 void sound_set_loudness(int value
)
576 void sound_set_avc(int value
)
581 void sound_set_mdb_strength(int value
)
586 void sound_set_mdb_harmonics(int value
)
591 void sound_set_mdb_center(int value
)
596 void sound_set_mdb_shape(int value
)
601 void sound_set_mdb_enable(int value
)
606 void sound_set_superbass(int value
)
610 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
612 #if defined(HAVE_WM8758) || defined(HAVE_WM8985)
613 void sound_set_bass_cutoff(int value
)
618 void sound_set_treble_cutoff(int value
)
622 #endif /* HAVE_WM8758 */
624 #endif /* SIMULATOR */
626 void sound_set(int setting
, int value
)
628 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
630 sound_set_val(value
);
633 #if (!defined(HAVE_AS3514) && !defined (HAVE_WM8731) && !defined(HAVE_TSC2100)) \
634 || defined(SIMULATOR)
635 int sound_val2phys(int setting
, int value
)
637 #if CONFIG_CODEC == MAS3587F
642 case SOUND_LEFT_GAIN
:
643 case SOUND_RIGHT_GAIN
:
644 result
= (value
- 2) * 15;
648 result
= value
* 15 + 210;
656 #elif defined(HAVE_UDA1380)
661 case SOUND_LEFT_GAIN
:
662 case SOUND_RIGHT_GAIN
:
664 result
= value
* 5; /* (1/2) * 10 */
672 #elif defined(HAVE_TLV320) || defined(HAVE_WM8731)
677 case SOUND_LEFT_GAIN
:
678 case SOUND_RIGHT_GAIN
:
679 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
683 result
= value
* 200; /* 0 or 20 dB */
691 #elif defined(HAVE_AS3514)
692 /* This is here for the sim only and the audio driver has its own */
697 case SOUND_LEFT_GAIN
:
698 case SOUND_RIGHT_GAIN
:
700 result
= (value
- 23) * 15;
714 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
716 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
718 /* This function works by telling the decoder that we have another
719 crystal frequency than we actually have. It will adjust its internal
720 parameters and the result is that the audio is played at another pitch.
722 The pitch value is in tenths of percent.
724 static int last_pitch
= 1000;
726 void sound_set_pitch(int pitch
)
730 if (pitch
!= last_pitch
)
732 /* Calculate the new (bogus) frequency */
733 val
= 18432 * 1000 / pitch
;
735 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
737 /* We must tell the MAS that the frequency has changed.
738 * This will unfortunately cause a short silence. */
739 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
745 int sound_get_pitch(void)
749 #else /* SIMULATOR */
750 void sound_set_pitch(int pitch
)
755 int sound_get_pitch(void)
759 #endif /* SIMULATOR */
760 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */