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
34 #include "pcm_playback.h"
39 extern bool audio_is_initialized
;
41 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
42 extern unsigned long shadow_io_control_main
;
43 extern unsigned shadow_codec_reg0
;
45 #endif /* SIMULATOR */
49 const struct sound_settings_info audiohw_settings
[] = {
50 [SOUND_VOLUME
] = {"dB", 0, 1, -40, 6, -25},
51 [SOUND_BASS
] = {"dB", 0, 1, -24, 24, 0},
52 [SOUND_TREBLE
] = {"dB", 0, 1, -24, 24, 0},
53 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
54 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
55 [SOUND_STEREO_WIDTH
] = {"%", 0, 1, 0, 255, 100},
56 #if CONFIG_CODEC == MAS3587F || defined(HAVE_UDA1380) || defined(HAVE_TLV320)\
57 || defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
58 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
59 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-128, 96, 0},
60 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-128, 108, 16},
65 const char *sound_unit(int setting
)
67 return audiohw_settings
[setting
].unit
;
70 int sound_numdecimals(int setting
)
72 return audiohw_settings
[setting
].numdecimals
;
75 int sound_steps(int setting
)
77 return audiohw_settings
[setting
].steps
;
80 int sound_min(int setting
)
82 return audiohw_settings
[setting
].minval
;
85 int sound_max(int setting
)
87 return audiohw_settings
[setting
].maxval
;
90 int sound_default(int setting
)
92 return audiohw_settings
[setting
].defaultval
;
95 sound_set_type
* sound_get_fn(int setting
)
97 sound_set_type
* result
= NULL
;
101 result
= sound_set_volume
;
105 result
= sound_set_bass
;
109 result
= sound_set_treble
;
113 result
= sound_set_balance
;
117 result
= sound_set_channels
;
120 case SOUND_STEREO_WIDTH
:
121 result
= sound_set_stereo_width
;
124 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
126 result
= sound_set_loudness
;
130 result
= sound_set_avc
;
133 case SOUND_MDB_STRENGTH
:
134 result
= sound_set_mdb_strength
;
137 case SOUND_MDB_HARMONICS
:
138 result
= sound_set_mdb_harmonics
;
141 case SOUND_MDB_CENTER
:
142 result
= sound_set_mdb_center
;
145 case SOUND_MDB_SHAPE
:
146 result
= sound_set_mdb_shape
;
149 case SOUND_MDB_ENABLE
:
150 result
= sound_set_mdb_enable
;
153 case SOUND_SUPERBASS
:
154 result
= sound_set_superbass
;
162 #if CONFIG_CODEC == SWCODEC
163 /* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */
165 DSP_CALLBACK_SET_PRESCALE
= 0,
166 DSP_CALLBACK_SET_BASS
,
167 DSP_CALLBACK_SET_TREBLE
,
168 DSP_CALLBACK_SET_CHANNEL_CONFIG
,
169 DSP_CALLBACK_SET_STEREO_WIDTH
172 static int (*dsp_callback
)(int, intptr_t) = NULL
;
174 void sound_set_dsp_callback(int (*func
)(int, intptr_t))
181 #if CONFIG_CODEC == MAS3507D /* volume/balance/treble/bass interdependency */
182 #define VOLUME_MIN -780
183 #define VOLUME_MAX 180
185 static const unsigned int bass_table
[] =
220 static const unsigned int treble_table
[] =
255 static const unsigned int prescale_table
[] =
275 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
276 static int tenthdb2reg(int db
)
278 if (db
< -540) /* 3 dB steps */
279 return (db
+ 780) / 30;
280 else /* 1.5 dB steps */
281 return (db
+ 660) / 15;
285 #if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
286 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_WM8731) \
287 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
288 || defined(HAVE_AS3514)
289 /* volume/balance/treble/bass interdependency main part */
290 #define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
292 /* all values in tenth of dB MAS3507D UDA1380 */
293 int current_volume
= 0; /* -780..+180 -840.. 0 */
294 int current_balance
= 0; /* -960..+960 -840..+840 */
295 int current_treble
= 0; /* -150..+150 0.. +60 */
296 int current_bass
= 0; /* -150..+150 0..+240 */
298 static void set_prescaled_volume(void)
303 /* The WM codecs listed don't have suitable prescaler functionality, so we let
304 * the prescaler stay at 0 for these unless SW tone controls are in use */
305 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
306 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751))
308 prescale
= MAX(current_bass
, current_treble
);
310 prescale
= 0; /* no need to prescale if we don't boost
313 /* Gain up the analog volume to compensate the prescale gain reduction,
314 * but if this would push the volume over the top, reduce prescaling
315 * instead (might cause clipping). */
316 if (current_volume
+ prescale
> VOLUME_MAX
)
317 prescale
= VOLUME_MAX
- current_volume
;
320 #if defined(HAVE_SW_TONE_CONTROLS)
321 dsp_callback(DSP_CALLBACK_SET_PRESCALE
, prescale
);
322 #elif CONFIG_CODEC == MAS3507D
323 mas_writereg(MAS_REG_KPRESCALE
, prescale_table
[prescale
/10]);
324 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8758)
325 audiohw_set_mixer_vol(tenthdb2mixer(-prescale
), tenthdb2mixer(-prescale
));
328 if (current_volume
== VOLUME_MIN
)
329 prescale
= 0; /* Make sure the chip gets muted at VOLUME_MIN */
331 l
= r
= current_volume
+ prescale
;
333 if (current_balance
> 0)
335 l
-= current_balance
;
339 if (current_balance
< 0)
341 r
+= current_balance
;
346 #if CONFIG_CODEC == MAS3507D
347 dac_volume(tenthdb2reg(l
), tenthdb2reg(r
), false);
348 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
349 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
350 || defined(HAVE_AS3514)
351 audiohw_set_master_vol(tenthdb2master(l
), tenthdb2master(r
));
352 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8751)
353 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
356 #elif defined(HAVE_TLV320)
357 audiohw_set_headphone_vol(tenthdb2master(l
), tenthdb2master(r
));
360 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
361 #endif /* !SIMULATOR */
363 #if CONFIG_CODEC != SWCODEC
364 int channel_configuration
= SOUND_CHAN_STEREO
;
365 int stereo_width
= 100;
370 #if CONFIG_CODEC != SWCODEC
371 static void set_channel_config(void)
373 /* default values: stereo */
374 unsigned long val_ll
= 0x80000;
375 unsigned long val_lr
= 0;
376 unsigned long val_rl
= 0;
377 unsigned long val_rr
= 0x80000;
379 switch(channel_configuration
)
381 /* case SOUND_CHAN_STEREO unnecessary */
383 case SOUND_CHAN_MONO
:
390 case SOUND_CHAN_CUSTOM
:
392 /* fixed point variables (matching MAS internal format)
393 integer part: upper 13 bits (inlcuding sign)
394 fractional part: lower 19 bits */
395 long fp_width
, fp_straight
, fp_cross
;
397 fp_width
= (stereo_width
<< 19) / 100;
398 if (stereo_width
<= 100)
400 fp_straight
= - ((1<<19) + fp_width
) / 2;
401 fp_cross
= fp_straight
+ fp_width
;
405 /* straight = - (1 + width) / (2 * width) */
406 fp_straight
= - ((((1<<19) + fp_width
) / (fp_width
>> 9)) << 9);
407 fp_cross
= (1<<19) + fp_straight
;
409 val_ll
= val_rr
= fp_straight
& 0xfffff;
410 val_lr
= val_rl
= fp_cross
& 0xfffff;
414 case SOUND_CHAN_MONO_LEFT
:
421 case SOUND_CHAN_MONO_RIGHT
:
428 case SOUND_CHAN_KARAOKE
:
436 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
437 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_LL
, &val_ll
, 1); /* LL */
438 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_LR
, &val_lr
, 1); /* LR */
439 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_RL
, &val_rl
, 1); /* RL */
440 mas_writemem(MAS_BANK_D0
, MAS_D0_OUT_RR
, &val_rr
, 1); /* RR */
441 #elif CONFIG_CODEC == MAS3507D
442 mas_writemem(MAS_BANK_D1
, 0x7f8, &val_ll
, 1); /* LL */
443 mas_writemem(MAS_BANK_D1
, 0x7f9, &val_lr
, 1); /* LR */
444 mas_writemem(MAS_BANK_D1
, 0x7fa, &val_rl
, 1); /* RL */
445 mas_writemem(MAS_BANK_D1
, 0x7fb, &val_rr
, 1); /* RR */
449 #endif /* CONFIG_CODEC != SWCODEC */
451 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
452 unsigned long mdb_shape_shadow
= 0;
453 unsigned long loudness_shadow
= 0;
456 void sound_set_volume(int value
)
458 if(!audio_is_initialized
)
460 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
461 unsigned tmp
= ((unsigned)(value
+ 115) & 0xff) << 8;
462 mas_codec_writereg(0x10, tmp
);
463 #elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
464 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
465 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
466 || defined(HAVE_AS3514)
467 current_volume
= value
* 10; /* tenth of dB */
468 set_prescaled_volume();
469 #elif CONFIG_CPU == PNX0101
470 int tmp
= (60 - value
* 4) & 0xff;
471 CODECVOL
= tmp
| (tmp
<< 8);
475 void sound_set_balance(int value
)
477 if(!audio_is_initialized
)
479 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
480 unsigned tmp
= ((unsigned)(value
* 127 / 100) & 0xff) << 8;
481 mas_codec_writereg(0x11, tmp
);
482 #elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 \
483 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
484 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
485 || defined(HAVE_AS3514)
486 current_balance
= value
* VOLUME_RANGE
/ 100; /* tenth of dB */
487 set_prescaled_volume();
488 #elif CONFIG_CPU == PNX0101
489 /* TODO: implement for iFP */
494 void sound_set_bass(int value
)
496 if(!audio_is_initialized
)
498 #if defined(HAVE_SW_TONE_CONTROLS)
499 current_bass
= value
* 10;
500 dsp_callback(DSP_CALLBACK_SET_BASS
, current_bass
);
501 set_prescaled_volume();
502 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
503 unsigned tmp
= ((unsigned)(value
* 8) & 0xff) << 8;
504 mas_codec_writereg(0x14, tmp
);
505 #elif CONFIG_CODEC == MAS3507D
506 mas_writereg(MAS_REG_KBASS
, bass_table
[value
+15]);
507 current_bass
= value
* 10;
508 set_prescaled_volume();
509 #elif defined(HAVE_WM8751)
510 current_bass
= value
;
511 audiohw_set_bass(value
);
512 set_prescaled_volume();
513 #elif defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_UDA1380) \
514 || defined HAVE_WM8731 || defined(HAVE_WM8721)
515 current_bass
= value
* 10;
516 audiohw_set_bass(value
);
517 set_prescaled_volume();
518 #elif CONFIG_CPU == PNX0101
519 /* TODO: implement for iFP */
524 void sound_set_treble(int value
)
526 if(!audio_is_initialized
)
528 #if defined(HAVE_SW_TONE_CONTROLS)
529 current_treble
= value
* 10;
530 dsp_callback(DSP_CALLBACK_SET_TREBLE
, current_treble
);
531 set_prescaled_volume();
532 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
533 unsigned tmp
= ((unsigned)(value
* 8) & 0xff) << 8;
534 mas_codec_writereg(0x15, tmp
);
535 #elif CONFIG_CODEC == MAS3507D
536 mas_writereg(MAS_REG_KTREBLE
, treble_table
[value
+15]);
537 current_treble
= value
* 10;
538 set_prescaled_volume();
539 #elif defined(HAVE_WM8751)
540 audiohw_set_treble(value
);
541 current_treble
= value
;
542 set_prescaled_volume();
543 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_UDA1380) \
544 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
545 audiohw_set_treble(value
);
546 current_treble
= value
* 10;
547 set_prescaled_volume();
548 #elif CONFIG_CPU == PNX0101
549 /* TODO: implement for iFP */
554 void sound_set_channels(int value
)
556 #if CONFIG_CODEC == SWCODEC
557 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG
, value
);
559 if(!audio_is_initialized
)
561 channel_configuration
= value
;
562 set_channel_config();
566 void sound_set_stereo_width(int value
)
568 #if CONFIG_CODEC == SWCODEC
569 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH
, value
);
571 if(!audio_is_initialized
)
573 stereo_width
= value
;
574 if (channel_configuration
== SOUND_CHAN_CUSTOM
)
575 set_channel_config();
579 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
580 void sound_set_loudness(int value
)
582 if(!audio_is_initialized
)
584 loudness_shadow
= (loudness_shadow
& 0x04) |
585 (MAX(MIN(value
* 4, 0x44), 0) << 8);
586 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
589 void sound_set_avc(int value
)
591 if(!audio_is_initialized
)
596 tmp
= (0x1 << 8) | (0x8 << 12);
599 tmp
= (0x2 << 8) | (0x8 << 12);
602 tmp
= (0x4 << 8) | (0x8 << 12);
605 tmp
= (0x8 << 8) | (0x8 << 12);
607 case -1: /* turn off and then turn on again to decay quickly */
608 tmp
= mas_codec_readreg(MAS_REG_KAVC
);
609 mas_codec_writereg(MAS_REG_KAVC
, 0);
615 mas_codec_writereg(MAS_REG_KAVC
, tmp
);
618 void sound_set_mdb_strength(int value
)
620 if(!audio_is_initialized
)
622 mas_codec_writereg(MAS_REG_KMDB_STR
, (value
& 0x7f) << 8);
625 void sound_set_mdb_harmonics(int value
)
627 if(!audio_is_initialized
)
629 int tmp
= value
* 127 / 100;
630 mas_codec_writereg(MAS_REG_KMDB_HAR
, (tmp
& 0x7f) << 8);
633 void sound_set_mdb_center(int value
)
635 if(!audio_is_initialized
)
637 mas_codec_writereg(MAS_REG_KMDB_FC
, (value
/10) << 8);
640 void sound_set_mdb_shape(int value
)
642 if(!audio_is_initialized
)
644 mdb_shape_shadow
= (mdb_shape_shadow
& 0x02) | ((value
/10) << 8);
645 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
648 void sound_set_mdb_enable(int value
)
650 if(!audio_is_initialized
)
652 mdb_shape_shadow
= (mdb_shape_shadow
& ~0x02) | (value
?2:0);
653 mas_codec_writereg(MAS_REG_KMDB_SWITCH
, mdb_shape_shadow
);
656 void sound_set_superbass(int value
)
658 if(!audio_is_initialized
)
660 loudness_shadow
= (loudness_shadow
& ~0x04) | (value
?4:0);
661 mas_codec_writereg(MAS_REG_KLOUDNESS
, loudness_shadow
);
663 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
665 #else /* SIMULATOR */
667 void sound_set_volume(int value
)
669 sim_volume
=128*(value
+40)/46; /* 128 is SDL_MIX_MAXVOLUME */
672 void sound_set_balance(int value
)
677 void sound_set_bass(int value
)
682 void sound_set_treble(int value
)
687 void sound_set_channels(int value
)
692 void sound_set_stereo_width(int value
)
697 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
698 void sound_set_loudness(int value
)
703 void sound_set_avc(int value
)
708 void sound_set_mdb_strength(int value
)
713 void sound_set_mdb_harmonics(int value
)
718 void sound_set_mdb_center(int value
)
723 void sound_set_mdb_shape(int value
)
728 void sound_set_mdb_enable(int value
)
733 void sound_set_superbass(int value
)
737 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
738 #endif /* SIMULATOR */
740 void sound_set(int setting
, int value
)
742 sound_set_type
* sound_set_val
= sound_get_fn(setting
);
744 sound_set_val(value
);
747 #if !defined(HAVE_AS3514) || defined(SIMULATOR)
748 int sound_val2phys(int setting
, int value
)
750 #if CONFIG_CODEC == MAS3587F
755 case SOUND_LEFT_GAIN
:
756 case SOUND_RIGHT_GAIN
:
757 result
= (value
- 2) * 15;
761 result
= value
* 15 + 210;
769 #elif defined(HAVE_UDA1380)
774 case SOUND_LEFT_GAIN
:
775 case SOUND_RIGHT_GAIN
:
777 result
= value
* 5; /* (1/2) * 10 */
785 #elif defined(HAVE_TLV320)
790 case SOUND_LEFT_GAIN
:
791 case SOUND_RIGHT_GAIN
:
792 result
= (value
- 23) * 15; /* (x - 23)/1.5 *10 */
796 result
= value
* 200; /* 0 or 20 dB */
804 #elif defined(HAVE_AS3514)
805 /* This is here for the sim only and the audio driver has its own */
810 case SOUND_LEFT_GAIN
:
811 case SOUND_RIGHT_GAIN
:
813 result
= (value
- 23) * 15;
827 #endif /* !defined(HAVE_AS3514) || defined(SIMULATOR) */
829 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
831 /* This function works by telling the decoder that we have another
832 crystal frequency than we actually have. It will adjust its internal
833 parameters and the result is that the audio is played at another pitch.
835 The pitch value is in tenths of percent.
837 static int last_pitch
= 1000;
839 void sound_set_pitch(int pitch
)
843 if (pitch
!= last_pitch
)
845 /* Calculate the new (bogus) frequency */
846 val
= 18432 * 1000 / pitch
;
848 mas_writemem(MAS_BANK_D0
, MAS_D0_OFREQ_CONTROL
, &val
, 1);
850 /* We must tell the MAS that the frequency has changed.
851 * This will unfortunately cause a short silence. */
852 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
858 int sound_get_pitch(void)
862 #else /* SIMULATOR */
863 void sound_set_pitch(int pitch
)
868 int sound_get_pitch(void)
872 #endif /* SIMULATOR */
873 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */