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
38 #if CONFIG_CODEC == MAS3507D /* volume/balance/treble/bass interdependency */
39 #define VOLUME_MIN -780
40 #define VOLUME_MAX 180
41 #elif !defined(VOLUME_MIN) && !defined(VOLUME_MAX)
42 #define VOLUME_MIN -400
43 #define VOLUME_MAX 600
46 /* volume/balance/treble/bass interdependency main part */
47 #define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
50 extern bool audio_is_initialized
;
52 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
53 extern unsigned long shadow_io_control_main
;
54 extern unsigned shadow_codec_reg0
;
56 #endif /* SIMULATOR */
60 const struct sound_settings_info audiohw_settings
[] = {
61 [SOUND_VOLUME
] = {"dB", 0, 1, VOLUME_MIN
/ 10, VOLUME_MAX
/ 10, -25},
62 [SOUND_BASS
] = {"dB", 0, 1, -24, 24, 0},
63 [SOUND_TREBLE
] = {"dB", 0, 1, -24, 24, 0},
64 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
65 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
66 [SOUND_STEREO_WIDTH
] = {"%", 0, 5, 0, 250, 100},
67 #if CONFIG_CODEC == MAS3587F || defined(HAVE_UDA1380) || defined(HAVE_TLV320)\
68 || defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
69 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
70 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
71 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
76 const char *sound_unit(int setting
)
78 return audiohw_settings
[setting
].unit
;
81 int sound_numdecimals(int setting
)
83 return audiohw_settings
[setting
].numdecimals
;
86 int sound_steps(int setting
)
88 return audiohw_settings
[setting
].steps
;
91 int sound_min(int setting
)
93 return audiohw_settings
[setting
].minval
;
96 int sound_max(int setting
)
98 return audiohw_settings
[setting
].maxval
;
101 int sound_default(int setting
)
103 return audiohw_settings
[setting
].defaultval
;
106 sound_set_type
* sound_get_fn(int setting
)
108 sound_set_type
* result
= NULL
;
112 result
= sound_set_volume
;
116 result
= sound_set_bass
;
120 result
= sound_set_treble
;
124 result
= sound_set_balance
;
128 result
= sound_set_channels
;
131 case SOUND_STEREO_WIDTH
:
132 result
= sound_set_stereo_width
;
135 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
137 result
= sound_set_loudness
;
141 result
= sound_set_avc
;
144 case SOUND_MDB_STRENGTH
:
145 result
= sound_set_mdb_strength
;
148 case SOUND_MDB_HARMONICS
:
149 result
= sound_set_mdb_harmonics
;
152 case SOUND_MDB_CENTER
:
153 result
= sound_set_mdb_center
;
156 case SOUND_MDB_SHAPE
:
157 result
= sound_set_mdb_shape
;
160 case SOUND_MDB_ENABLE
:
161 result
= sound_set_mdb_enable
;
164 case SOUND_SUPERBASS
:
165 result
= sound_set_superbass
;
173 #if CONFIG_CODEC == SWCODEC
174 /* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */
176 DSP_CALLBACK_SET_PRESCALE
= 0,
177 DSP_CALLBACK_SET_BASS
,
178 DSP_CALLBACK_SET_TREBLE
,
179 DSP_CALLBACK_SET_CHANNEL_CONFIG
,
180 DSP_CALLBACK_SET_STEREO_WIDTH
183 static int (*dsp_callback
)(int, intptr_t) = NULL
;
185 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
192 #if CONFIG_CODEC == MAS3507D
193 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
194 static int tenthdb2reg(int db
)
196 if (db
< -540) /* 3 dB steps */
197 return (db
+ 780) / 30;
198 else /* 1.5 dB steps */
199 return (db
+ 660) / 15;
203 #if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
204 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_WM8731) \
205 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
206 || defined(HAVE_AS3514)
208 /* all values in tenth of dB MAS3507D UDA1380 */
209 int current_volume
= 0; /* -780..+180 -840.. 0 */
210 int current_balance
= 0; /* -960..+960 -840..+840 */
211 int current_treble
= 0; /* -150..+150 0.. +60 */
212 int current_bass
= 0; /* -150..+150 0..+240 */
214 static void set_prescaled_volume(void)
219 /* The WM codecs listed don't have suitable prescaler functionality, so we let
220 * the prescaler stay at 0 for these unless SW tone controls are in use */
221 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
222 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751))
224 prescale
= MAX(current_bass
, current_treble
);
226 prescale
= 0; /* no need to prescale if we don't boost
229 /* Gain up the analog volume to compensate the prescale gain reduction,
230 * but if this would push the volume over the top, reduce prescaling
231 * instead (might cause clipping). */
232 if (current_volume
+ prescale
> VOLUME_MAX
)
233 prescale
= VOLUME_MAX
- current_volume
;
236 #if defined(HAVE_SW_TONE_CONTROLS)
237 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
238 #elif CONFIG_CODEC == MAS3507D
239 mas_writereg(MAS_REG_KPRESCALE
, prescale_table
[prescale
/10]);
240 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8758)
241 audiohw_set_mixer_vol(tenthdb2mixer(-prescale
), tenthdb2mixer(-prescale
));
244 if (current_volume
== VOLUME_MIN
)
245 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
247 l
= r
= current_volume
+ prescale
;
249 if (current_balance
> 0)
251 l
-= current_balance
;
255 if (current_balance
< 0)
257 r
+= current_balance
;
262 #if CONFIG_CODEC == MAS3507D
263 dac_volume(tenthdb2reg(l
), tenthdb2reg(r
), false);
264 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
265 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
266 || defined(HAVE_AS3514)
267 audiohw_set_master_vol(tenthdb2master(l
), tenthdb2master(r
));
268 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8751)
269 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
272 #elif defined(HAVE_TLV320)
273 audiohw_set_headphone_vol(tenthdb2master(l
), tenthdb2master(r
));
276 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
277 #endif /* !SIMULATOR */
279 #if CONFIG_CODEC != SWCODEC
280 int channel_configuration
= SOUND_CHAN_STEREO
;
281 int stereo_width
= 100;
286 #if CONFIG_CODEC != SWCODEC
287 static void set_channel_config(void)
289 /* default values: stereo */
290 unsigned long val_ll
= 0x80000;
291 unsigned long val_lr
= 0;
292 unsigned long val_rl
= 0;
293 unsigned long val_rr
= 0x80000;
295 switch(channel_configuration
)
297 /* case SOUND_CHAN_STEREO unnecessary */
299 case SOUND_CHAN_MONO
:
306 case SOUND_CHAN_CUSTOM
:
308 /* fixed point variables (matching MAS internal format)
309 integer part: upper 13 bits (inlcuding sign)
310 fractional part: lower 19 bits */
311 long fp_width
, fp_straight
, fp_cross
;
313 fp_width
= (stereo_width
<< 19) / 100;
314 if (stereo_width
<= 100)
316 fp_straight
= - ((1<<19) + fp_width
) / 2;
317 fp_cross
= fp_straight
+ fp_width
;
321 /* straight = - (1 + width) / (2 * width) */
322 fp_straight
= - ((((1<<19) + fp_width
) / (fp_width
>> 9)) << 9);
323 fp_cross
= (1<<19) + fp_straight
;
325 val_ll
= val_rr
= fp_straight
& 0xfffff;
326 val_lr
= val_rl
= fp_cross
& 0xfffff;
330 case SOUND_CHAN_MONO_LEFT
:
337 case SOUND_CHAN_MONO_RIGHT
:
344 case SOUND_CHAN_KARAOKE
:
352 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
353 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_LL
, &val_ll
, 1); /* LL */
354 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_LR
, &val_lr
, 1); /* LR */
355 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_RL
, &val_rl
, 1); /* RL */
356 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_RR
, &val_rr
, 1); /* RR */
357 #elif CONFIG_CODEC == MAS3507D
358 mas_writemem(MAS_BANK_D1
, 0x7f8, &val_ll
, 1); /* LL */
359 mas_writemem(MAS_BANK_D1
, 0x7f9, &val_lr
, 1); /* LR */
360 mas_writemem(MAS_BANK_D1
, 0x7fa, &val_rl
, 1); /* RL */
361 mas_writemem(MAS_BANK_D1
, 0x7fb, &val_rr
, 1); /* RR */
365 #endif /* CONFIG_CODEC != SWCODEC */
367 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
368 unsigned long mdb_shape_shadow
= 0;
369 unsigned long loudness_shadow
= 0;
372 void sound_set_volume(int value
)
374 if(!audio_is_initialized
)
376 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
377 unsigned tmp
= ((unsigned)(value
+ 115) & 0xff) << 8;
378 mas_codec_writereg(0x10, tmp
);
379 #elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
380 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
381 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
382 || defined(HAVE_AS3514)
383 current_volume
= value
* 10; /* tenth of dB */
384 set_prescaled_volume();
385 #elif CONFIG_CPU == PNX0101
386 int tmp
= (60 - value
* 4) & 0xff;
387 CODECVOL
= tmp
| (tmp
<< 8);
391 void sound_set_balance(int value
)
393 if(!audio_is_initialized
)
395 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
396 unsigned tmp
= ((unsigned)(value
* 127 / 100) & 0xff) << 8;
397 mas_codec_writereg(0x11, tmp
);
398 #elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 \
399 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
400 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
401 || defined(HAVE_AS3514)
402 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
403 set_prescaled_volume();
404 #elif CONFIG_CPU == PNX0101
405 /* TODO: implement for iFP */
410 void sound_set_bass(int value
)
412 if(!audio_is_initialized
)
414 #if defined(HAVE_SW_TONE_CONTROLS)
415 current_bass
= value
* 10;
416 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
417 set_prescaled_volume();
418 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
419 unsigned tmp
= ((unsigned)(value
* 8) & 0xff) << 8;
420 mas_codec_writereg(0x14, tmp
);
421 #elif CONFIG_CODEC == MAS3507D
422 mas_writereg(MAS_REG_KBASS
, bass_table
[value
+15]);
423 current_bass
= value
* 10;
424 set_prescaled_volume();
425 #elif defined(HAVE_WM8751)
426 current_bass
= value
;
427 audiohw_set_bass(value
);
428 set_prescaled_volume();
429 #elif defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_UDA1380) \
430 || defined HAVE_WM8731 || defined(HAVE_WM8721)
431 current_bass
= value
* 10;
432 audiohw_set_bass(value
);
433 set_prescaled_volume();
434 #elif CONFIG_CPU == PNX0101
435 /* TODO: implement for iFP */
440 void sound_set_treble(int value
)
442 if(!audio_is_initialized
)
444 #if defined(HAVE_SW_TONE_CONTROLS)
445 current_treble
= value
* 10;
446 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
447 set_prescaled_volume();
448 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
449 unsigned tmp
= ((unsigned)(value
* 8) & 0xff) << 8;
450 mas_codec_writereg(0x15, tmp
);
451 #elif CONFIG_CODEC == MAS3507D
452 mas_writereg(MAS_REG_KTREBLE
, treble_table
[value
+15]);
453 current_treble
= value
* 10;
454 set_prescaled_volume();
455 #elif defined(HAVE_WM8751)
456 audiohw_set_treble(value
);
457 current_treble
= value
;
458 set_prescaled_volume();
459 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_UDA1380) \
460 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
461 audiohw_set_treble(value
);
462 current_treble
= value
* 10;
463 set_prescaled_volume();
464 #elif CONFIG_CPU == PNX0101
465 /* TODO: implement for iFP */
470 void sound_set_channels(int value
)
472 #if CONFIG_CODEC == SWCODEC
473 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
475 if(!audio_is_initialized
)
477 channel_configuration
= value
;
478 set_channel_config();
482 void sound_set_stereo_width(int value
)
484 #if CONFIG_CODEC == SWCODEC
485 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
487 if(!audio_is_initialized
)
489 stereo_width
= value
;
490 if (channel_configuration
== SOUND_CHAN_CUSTOM
)
491 set_channel_config();
495 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
496 void sound_set_loudness(int value
)
498 if(!audio_is_initialized
)
500 loudness_shadow
= (loudness_shadow
& 0x04) |
501 (MAX(MIN(value
* 4, 0x44), 0) << 8);
502 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
505 void sound_set_avc(int value
)
507 if(!audio_is_initialized
)
512 tmp
= (0x1 << 8) | (0x8 << 12);
515 tmp
= (0x2 << 8) | (0x8 << 12);
518 tmp
= (0x4 << 8) | (0x8 << 12);
521 tmp
= (0x8 << 8) | (0x8 << 12);
523 case -1: /* turn off and then turn on again to decay quickly */
524 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
525 mas_codec_writereg(MAS_REG_KAVC
, 0);
531 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
534 void sound_set_mdb_strength(int value
)
536 if(!audio_is_initialized
)
538 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
541 void sound_set_mdb_harmonics(int value
)
543 if(!audio_is_initialized
)
545 int tmp
= value
* 127 / 100;
546 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
549 void sound_set_mdb_center(int value
)
551 if(!audio_is_initialized
)
553 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
556 void sound_set_mdb_shape(int value
)
558 if(!audio_is_initialized
)
560 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
561 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
564 void sound_set_mdb_enable(int value
)
566 if(!audio_is_initialized
)
568 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
569 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
572 void sound_set_superbass(int value
)
574 if(!audio_is_initialized
)
576 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
577 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
579 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
581 #else /* SIMULATOR */
583 void sound_set_volume(int value
)
585 /* 128 is SDL_MIX_MAXVOLUME */
586 sim_volume
= 128 * (value
- VOLUME_MIN
/ 10) / (VOLUME_RANGE
/ 10);
589 void sound_set_balance(int value
)
594 void sound_set_bass(int value
)
599 void sound_set_treble(int value
)
604 void sound_set_channels(int value
)
609 void sound_set_stereo_width(int value
)
614 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
615 void sound_set_loudness(int value
)
620 void sound_set_avc(int value
)
625 void sound_set_mdb_strength(int value
)
630 void sound_set_mdb_harmonics(int value
)
635 void sound_set_mdb_center(int value
)
640 void sound_set_mdb_shape(int value
)
645 void sound_set_mdb_enable(int value
)
650 void sound_set_superbass(int value
)
654 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
655 #endif /* SIMULATOR */
657 void sound_set(int setting
, int value
)
659 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
661 sound_set_val(value
);
664 #if (!defined(HAVE_AS3514) && !defined (HAVE_WM8731)) || defined(SIMULATOR)
665 int sound_val2phys(int setting
, int value
)
667 #if CONFIG_CODEC == MAS3587F
672 case SOUND_LEFT_GAIN
:
673 case SOUND_RIGHT_GAIN
:
674 result
= (value
- 2) * 15;
678 result
= value
* 15 + 210;
686 #elif defined(HAVE_UDA1380)
691 case SOUND_LEFT_GAIN
:
692 case SOUND_RIGHT_GAIN
:
694 result
= value
* 5; /* (1/2) * 10 */
702 #elif defined(HAVE_TLV320) || defined(HAVE_WM8731)
707 case SOUND_LEFT_GAIN
:
708 case SOUND_RIGHT_GAIN
:
709 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
713 result
= value
* 200; /* 0 or 20 dB */
721 #elif defined(HAVE_AS3514)
722 /* This is here for the sim only and the audio driver has its own */
727 case SOUND_LEFT_GAIN
:
728 case SOUND_RIGHT_GAIN
:
730 result
= (value
- 23) * 15;
744 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
746 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
748 /* This function works by telling the decoder that we have another
749 crystal frequency than we actually have. It will adjust its internal
750 parameters and the result is that the audio is played at another pitch.
752 The pitch value is in tenths of percent.
754 static int last_pitch
= 1000;
756 void sound_set_pitch(int pitch
)
760 if (pitch
!= last_pitch
)
762 /* Calculate the new (bogus) frequency */
763 val
= 18432 * 1000 / pitch
;
765 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
767 /* We must tell the MAS that the frequency has changed.
768 * This will unfortunately cause a short silence. */
769 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
775 int sound_get_pitch(void)
779 #else /* SIMULATOR */
780 void sound_set_pitch(int pitch
)
785 int sound_get_pitch(void)
789 #endif /* SIMULATOR */
790 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */