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 -700
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 defined(HAVE_RECORDING)
70 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
71 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
72 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
74 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
75 [SOUND_BASS_CUTOFF
] = {"", 0, 1, 1, 4, 1},
77 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
78 [SOUND_TREBLE_CUTOFF
] = {"", 0, 1, 1, 4, 1},
80 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
81 [SOUND_LOUDNESS
] = {"dB", 0, 1, 0, 17, 0},
82 [SOUND_AVC
] = {"", 0, 1, -1, 4, 0},
83 [SOUND_MDB_STRENGTH
] = {"dB", 0, 1, 0, 127, 48},
84 [SOUND_MDB_HARMONICS
] = {"%", 0, 1, 0, 100, 50},
85 [SOUND_MDB_CENTER
] = {"Hz", 0, 10, 20, 300, 60},
86 [SOUND_MDB_SHAPE
] = {"Hz", 0, 10, 50, 300, 90},
87 [SOUND_MDB_ENABLE
] = {"", 0, 1, 0, 1, 0},
88 [SOUND_SUPERBASS
] = {"", 0, 1, 0, 1, 0},
93 const char *sound_unit(int setting
)
95 return audiohw_settings
[setting
].unit
;
98 int sound_numdecimals(int setting
)
100 return audiohw_settings
[setting
].numdecimals
;
103 int sound_steps(int setting
)
105 return audiohw_settings
[setting
].steps
;
108 int sound_min(int setting
)
110 return audiohw_settings
[setting
].minval
;
113 int sound_max(int setting
)
115 return audiohw_settings
[setting
].maxval
;
118 int sound_default(int setting
)
120 return audiohw_settings
[setting
].defaultval
;
123 sound_set_type
* sound_get_fn(int setting
)
125 sound_set_type
* result
= NULL
;
129 result
= sound_set_volume
;
133 result
= sound_set_bass
;
137 result
= sound_set_treble
;
141 result
= sound_set_balance
;
145 result
= sound_set_channels
;
148 case SOUND_STEREO_WIDTH
:
149 result
= sound_set_stereo_width
;
152 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
153 case SOUND_BASS_CUTOFF
:
154 result
= sound_set_bass_cutoff
;
158 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
159 case SOUND_TREBLE_CUTOFF
:
160 result
= sound_set_treble_cutoff
;
164 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
166 result
= sound_set_loudness
;
170 result
= sound_set_avc
;
173 case SOUND_MDB_STRENGTH
:
174 result
= sound_set_mdb_strength
;
177 case SOUND_MDB_HARMONICS
:
178 result
= sound_set_mdb_harmonics
;
181 case SOUND_MDB_CENTER
:
182 result
= sound_set_mdb_center
;
185 case SOUND_MDB_SHAPE
:
186 result
= sound_set_mdb_shape
;
189 case SOUND_MDB_ENABLE
:
190 result
= sound_set_mdb_enable
;
193 case SOUND_SUPERBASS
:
194 result
= sound_set_superbass
;
202 #if CONFIG_CODEC == SWCODEC
203 /* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */
205 DSP_CALLBACK_SET_PRESCALE
= 0,
206 DSP_CALLBACK_SET_BASS
,
207 DSP_CALLBACK_SET_TREBLE
,
208 DSP_CALLBACK_SET_CHANNEL_CONFIG
,
209 DSP_CALLBACK_SET_STEREO_WIDTH
212 static int (*dsp_callback
)(int, intptr_t) = NULL
;
214 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
221 #if CONFIG_CODEC == MAS3507D
222 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
223 static int tenthdb2reg(int db
)
225 if (db
< -540) /* 3 dB steps */
226 return (db
+ 780) / 30;
227 else /* 1.5 dB steps */
228 return (db
+ 660) / 15;
233 #if !defined(AUDIOHW_HAVE_CLIPPING)
235 * The prescaler compensates for any kind of boosts, to prevent clipping.
237 * It's basically just a measure to make sure that audio does not clip during
238 * tone controls processing, like if i want to boost bass 12 dB, i can decrease
239 * the audio amplitude by -12 dB before processing, then increase master gain
240 * by 12 dB after processing.
243 /* all values in tenth of dB MAS3507D UDA1380 */
244 int current_volume
= 0; /* -780..+180 -840.. 0 */
245 int current_balance
= 0; /* -960..+960 -840..+840 */
246 int current_treble
= 0; /* -150..+150 0.. +60 */
247 int current_bass
= 0; /* -150..+150 0..+240 */
249 static void set_prescaled_volume(void)
254 /* The WM codecs listed don't have suitable prescaler functionality, so we let
255 * the prescaler stay at 0 for these unless SW tone controls are in use */
256 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
257 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
258 || defined(HAVE_WM8758) || defined(HAVE_WM8985)) || defined(HAVE_TSC2100)
260 prescale
= MAX(current_bass
, current_treble
);
262 prescale
= 0; /* no need to prescale if we don't boost
265 /* Gain up the analog volume to compensate the prescale gain reduction,
266 * but if this would push the volume over the top, reduce prescaling
267 * instead (might cause clipping). */
268 if (current_volume
+ prescale
> VOLUME_MAX
)
269 prescale
= VOLUME_MAX
- current_volume
;
272 #if defined(AUDIOHW_HAVE_PRESCALER)
273 audiohw_set_prescaler(prescale
);
275 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
278 if (current_volume
== VOLUME_MIN
)
279 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
281 l
= r
= current_volume
+ prescale
;
283 if (current_balance
> 0)
285 l
-= current_balance
;
289 if (current_balance
< 0)
291 r
+= current_balance
;
296 #if CONFIG_CODEC == MAS3507D
297 dac_volume(tenthdb2reg(l
), tenthdb2reg(r
), false);
298 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
299 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
300 || defined(HAVE_AS3514) || defined(HAVE_TSC2100)
301 audiohw_set_master_vol(tenthdb2master(l
), tenthdb2master(r
));
302 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
303 || (defined(HAVE_WM8751) && !defined(MROBE_100)) \
304 || defined(HAVE_TSC2100)
305 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
308 #elif defined(HAVE_TLV320) || defined(HAVE_WM8978)
309 audiohw_set_headphone_vol(tenthdb2master(l
), tenthdb2master(r
));
312 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
313 #endif /* !SIMULATOR */
318 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
319 unsigned long mdb_shape_shadow
= 0;
320 unsigned long loudness_shadow
= 0;
323 void sound_set_volume(int value
)
325 if(!audio_is_initialized
)
328 #if defined(AUDIOHW_HAVE_CLIPPING)
329 audiohw_set_volume(value
);
330 #elif CONFIG_CPU == PNX0101
331 int tmp
= (60 - value
* 4) & 0xff;
332 CODECVOL
= tmp
| (tmp
<< 8);
334 current_volume
= value
* 10; /* tenth of dB */
335 set_prescaled_volume();
339 void sound_set_balance(int value
)
341 if(!audio_is_initialized
)
344 #ifdef AUDIOHW_HAVE_BALANCE
345 audiohw_set_balance(value
);
347 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
348 set_prescaled_volume();
352 void sound_set_bass(int value
)
354 if(!audio_is_initialized
)
357 #if !defined(AUDIOHW_HAVE_CLIPPING)
358 #if defined(HAVE_WM8751)
359 current_bass
= value
;
361 current_bass
= value
* 10;
365 #if defined(AUDIOHW_HAVE_BASS)
366 audiohw_set_bass(value
);
368 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
371 #if !defined(AUDIOHW_HAVE_CLIPPING)
372 set_prescaled_volume();
376 void sound_set_treble(int value
)
378 if(!audio_is_initialized
)
381 #if !defined(AUDIOHW_HAVE_CLIPPING)
382 #if defined(HAVE_WM8751)
383 current_treble
= value
;
385 current_treble
= value
* 10;
389 #if defined(AUDIOHW_HAVE_TREBLE)
390 audiohw_set_treble(value
);
392 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
395 #if !defined(AUDIOHW_HAVE_CLIPPING)
396 set_prescaled_volume();
400 void sound_set_channels(int value
)
402 if(!audio_is_initialized
)
405 #if CONFIG_CODEC == SWCODEC
406 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
408 audiohw_set_channel(value
);
412 void sound_set_stereo_width(int value
)
414 if(!audio_is_initialized
)
417 #if CONFIG_CODEC == SWCODEC
418 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
420 audiohw_set_stereo_width(value
);
424 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
425 void sound_set_bass_cutoff(int value
)
427 if(!audio_is_initialized
)
430 audiohw_set_bass_cutoff(value
);
434 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
435 void sound_set_treble_cutoff(int value
)
437 if(!audio_is_initialized
)
440 audiohw_set_treble_cutoff(value
);
444 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
445 void sound_set_loudness(int value
)
447 if(!audio_is_initialized
)
449 loudness_shadow
= (loudness_shadow
& 0x04) |
450 (MAX(MIN(value
* 4, 0x44), 0) << 8);
451 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
454 void sound_set_avc(int value
)
456 if(!audio_is_initialized
)
461 tmp
= (0x1 << 8) | (0x8 << 12);
464 tmp
= (0x2 << 8) | (0x8 << 12);
467 tmp
= (0x4 << 8) | (0x8 << 12);
470 tmp
= (0x8 << 8) | (0x8 << 12);
472 case -1: /* turn off and then turn on again to decay quickly */
473 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
474 mas_codec_writereg(MAS_REG_KAVC
, 0);
480 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
483 void sound_set_mdb_strength(int value
)
485 if(!audio_is_initialized
)
487 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
490 void sound_set_mdb_harmonics(int value
)
492 if(!audio_is_initialized
)
494 int tmp
= value
* 127 / 100;
495 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
498 void sound_set_mdb_center(int value
)
500 if(!audio_is_initialized
)
502 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
505 void sound_set_mdb_shape(int value
)
507 if(!audio_is_initialized
)
509 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
510 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
513 void sound_set_mdb_enable(int value
)
515 if(!audio_is_initialized
)
517 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
518 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
521 void sound_set_superbass(int value
)
523 if(!audio_is_initialized
)
525 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
526 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
528 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
530 #else /* SIMULATOR */
532 void sound_set_volume(int value
)
534 /* 128 is SDL_MIX_MAXVOLUME */
535 sim_volume
= 128 * (value
- VOLUME_MIN
/ 10) / (VOLUME_RANGE
/ 10);
538 void sound_set_balance(int value
)
543 void sound_set_bass(int value
)
548 void sound_set_treble(int value
)
553 void sound_set_channels(int value
)
558 void sound_set_stereo_width(int value
)
563 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
564 void sound_set_loudness(int value
)
569 void sound_set_avc(int value
)
574 void sound_set_mdb_strength(int value
)
579 void sound_set_mdb_harmonics(int value
)
584 void sound_set_mdb_center(int value
)
589 void sound_set_mdb_shape(int value
)
594 void sound_set_mdb_enable(int value
)
599 void sound_set_superbass(int value
)
603 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
605 #if defined(HAVE_WM8758) || defined(HAVE_WM8985)
606 void sound_set_bass_cutoff(int value
)
611 void sound_set_treble_cutoff(int value
)
615 #endif /* HAVE_WM8758 */
617 #endif /* SIMULATOR */
619 void sound_set(int setting
, int value
)
621 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
623 sound_set_val(value
);
626 #if (!defined(HAVE_AS3514) && !defined (HAVE_WM8731) && !defined(HAVE_TSC2100)) \
627 || defined(SIMULATOR)
628 int sound_val2phys(int setting
, int value
)
630 #if CONFIG_CODEC == MAS3587F
635 case SOUND_LEFT_GAIN
:
636 case SOUND_RIGHT_GAIN
:
637 result
= (value
- 2) * 15;
641 result
= value
* 15 + 210;
649 #elif defined(HAVE_UDA1380)
654 case SOUND_LEFT_GAIN
:
655 case SOUND_RIGHT_GAIN
:
657 result
= value
* 5; /* (1/2) * 10 */
665 #elif defined(HAVE_TLV320) || defined(HAVE_WM8731)
670 #ifdef HAVE_RECORDING
671 case SOUND_LEFT_GAIN
:
672 case SOUND_RIGHT_GAIN
:
673 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
677 result
= value
* 200; /* 0 or 20 dB */
685 #elif defined(HAVE_AS3514)
686 /* This is here for the sim only and the audio driver has its own */
691 case SOUND_LEFT_GAIN
:
692 case SOUND_RIGHT_GAIN
:
694 result
= (value
- 23) * 15;
708 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
710 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
712 /* This function works by telling the decoder that we have another
713 crystal frequency than we actually have. It will adjust its internal
714 parameters and the result is that the audio is played at another pitch.
716 The pitch value is in tenths of percent.
718 static int last_pitch
= 1000;
720 void sound_set_pitch(int pitch
)
724 if (pitch
!= last_pitch
)
726 /* Calculate the new (bogus) frequency */
727 val
= 18432 * 1000 / pitch
;
729 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
731 /* We must tell the MAS that the frequency has changed.
732 * This will unfortunately cause a short silence. */
733 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
739 int sound_get_pitch(void)
743 #else /* SIMULATOR */
744 void sound_set_pitch(int pitch
)
749 int sound_get_pitch(void)
753 #endif /* SIMULATOR */
754 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */