Fix buffer overflow when adding a radio preset.
[kugel-rb.git] / firmware / sound.c
blob2589306290adcb9f8cab6b7ead2379f1633c21a1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdbool.h>
20 #include <stdio.h>
21 #include "config.h"
22 #include "sound.h"
23 #include "logf.h"
24 #ifndef SIMULATOR
25 #include "i2c.h"
26 #include "mas.h"
27 #if CONFIG_CPU == PNX0101
28 #include "pnx0101.h"
29 #endif
30 #include "dac.h"
31 #include "system.h"
32 #if CONFIG_CODEC == SWCODEC
33 #include "pcm_playback.h"
34 #endif
35 #endif
37 #ifndef SIMULATOR
38 extern bool audio_is_initialized;
40 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
41 extern unsigned long shadow_io_control_main;
42 extern unsigned shadow_codec_reg0;
43 #endif
44 #endif /* SIMULATOR */
46 struct sound_settings_info {
47 const char *unit;
48 int numdecimals;
49 int steps;
50 int minval;
51 int maxval;
52 int defaultval;
53 sound_set_type *setfn;
56 static const struct sound_settings_info sound_settings_table[] = {
57 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
58 [SOUND_VOLUME] = {"dB", 0, 1,-100, 12, -25, sound_set_volume},
59 [SOUND_BASS] = {"dB", 0, 1, -12, 12, 6, sound_set_bass},
60 [SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 6, sound_set_treble},
61 #elif defined(HAVE_UDA1380)
62 [SOUND_VOLUME] = {"dB", 0, 1, -84, 0, -25, sound_set_volume},
63 [SOUND_BASS] = {"dB", 0, 2, 0, 24, 0, sound_set_bass},
64 [SOUND_TREBLE] = {"dB", 0, 2, 0, 6, 0, sound_set_treble},
65 #elif defined(HAVE_TLV320)
66 [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -20, sound_set_volume},
67 #elif defined(HAVE_WM8751)
68 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25, sound_set_volume},
69 [SOUND_BASS] = {"dB", 1, 15, -60, 90, 0, sound_set_bass},
70 [SOUND_TREBLE] = {"dB", 1, 15, -60, 90, 0, sound_set_treble},
71 #elif defined(HAVE_WM8975)
72 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25, sound_set_volume},
73 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
74 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
75 #elif defined(HAVE_WM8758)
76 [SOUND_VOLUME] = {"dB", 0, 1, -58, 6, -25, sound_set_volume},
77 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
78 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
79 #elif defined(HAVE_WM8731) || defined(HAVE_WM8721)
80 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25, sound_set_volume},
81 #elif (CONFIG_CPU == PNX0101)
82 [SOUND_VOLUME] = {"dB", 0, 1, -48, 15, 0, sound_set_volume},
83 #elif defined(HAVE_AS3514)
84 [SOUND_VOLUME] = {"dB", 0, 1, -40, 6, -25, sound_set_volume},
85 #else /* MAS3507D */
86 [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume},
87 [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass},
88 [SOUND_TREBLE] = {"dB", 0, 1, -15, 15, 7, sound_set_treble},
89 #endif
90 /* Override any other potentially existing treble/bass controllers if wanted */
91 #ifdef HAVE_SW_TONE_CONTROLS
92 [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0, sound_set_bass},
93 [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0, sound_set_treble},
94 #endif
95 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0, sound_set_balance},
96 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0, sound_set_channels},
97 [SOUND_STEREO_WIDTH] = {"%", 0, 1, 0, 255, 100, sound_set_stereo_width},
98 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
99 [SOUND_LOUDNESS] = {"dB", 0, 1, 0, 17, 0, sound_set_loudness},
100 [SOUND_AVC] = {"", 0, 1, -1, 4, 0, sound_set_avc},
101 [SOUND_MDB_STRENGTH] = {"dB", 0, 1, 0, 127, 48, sound_set_mdb_strength},
102 [SOUND_MDB_HARMONICS] = {"%", 0, 1, 0, 100, 50, sound_set_mdb_harmonics},
103 [SOUND_MDB_CENTER] = {"Hz", 0, 10, 20, 300, 60, sound_set_mdb_center},
104 [SOUND_MDB_SHAPE] = {"Hz", 0, 10, 50, 300, 90, sound_set_mdb_shape},
105 [SOUND_MDB_ENABLE] = {"", 0, 1, 0, 1, 0, sound_set_mdb_enable},
106 [SOUND_SUPERBASS] = {"", 0, 1, 0, 1, 0, sound_set_superbass},
107 #endif
108 #if CONFIG_CODEC == MAS3587F
109 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 15, 8, NULL},
110 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 15, 8, NULL},
111 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 15, 2, NULL},
112 #elif defined(HAVE_UDA1380)
113 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
114 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
115 [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16, NULL},
116 #elif defined(HAVE_TLV320)
117 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23, NULL},
118 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23, NULL},
119 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 1, NULL},
120 #elif defined(HAVE_WM8975)
121 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
122 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
123 [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16, NULL},
124 #elif defined(HAVE_WM8758)
125 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
126 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
127 [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16, NULL},
128 #elif defined(HAVE_WM8731)
129 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
130 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
131 [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16, NULL},
132 #endif
135 const char *sound_unit(int setting)
137 return sound_settings_table[setting].unit;
140 int sound_numdecimals(int setting)
142 return sound_settings_table[setting].numdecimals;
145 int sound_steps(int setting)
147 return sound_settings_table[setting].steps;
150 int sound_min(int setting)
152 return sound_settings_table[setting].minval;
155 int sound_max(int setting)
157 return sound_settings_table[setting].maxval;
160 int sound_default(int setting)
162 return sound_settings_table[setting].defaultval;
165 sound_set_type* sound_get_fn(int setting)
167 if ((unsigned)setting < (sizeof(sound_settings_table)
168 / sizeof(struct sound_settings_info)))
169 return sound_settings_table[setting].setfn;
170 else
171 return NULL;
174 #if CONFIG_CODEC == SWCODEC
175 /* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */
176 enum {
177 DSP_CALLBACK_SET_PRESCALE = 0,
178 DSP_CALLBACK_SET_BASS,
179 DSP_CALLBACK_SET_TREBLE,
180 DSP_CALLBACK_SET_CHANNEL_CONFIG,
181 DSP_CALLBACK_SET_STEREO_WIDTH
184 static int (*dsp_callback)(int, intptr_t) = NULL;
186 void sound_set_dsp_callback(int (*func)(int, intptr_t))
188 dsp_callback = func;
190 #endif
192 #ifndef SIMULATOR
193 #if CONFIG_CODEC == MAS3507D /* volume/balance/treble/bass interdependency */
194 #define VOLUME_MIN -780
195 #define VOLUME_MAX 180
197 static const unsigned int bass_table[] =
199 0x9e400, /* -15dB */
200 0xa2800, /* -14dB */
201 0xa7400, /* -13dB */
202 0xac400, /* -12dB */
203 0xb1800, /* -11dB */
204 0xb7400, /* -10dB */
205 0xbd400, /* -9dB */
206 0xc3c00, /* -8dB */
207 0xca400, /* -7dB */
208 0xd1800, /* -6dB */
209 0xd8c00, /* -5dB */
210 0xe0400, /* -4dB */
211 0xe8000, /* -3dB */
212 0xefc00, /* -2dB */
213 0xf7c00, /* -1dB */
215 0x800, /* 1dB */
216 0x10000, /* 2dB */
217 0x17c00, /* 3dB */
218 0x1f800, /* 4dB */
219 0x27000, /* 5dB */
220 0x2e400, /* 6dB */
221 0x35800, /* 7dB */
222 0x3c000, /* 8dB */
223 0x42800, /* 9dB */
224 0x48800, /* 10dB */
225 0x4e400, /* 11dB */
226 0x53800, /* 12dB */
227 0x58800, /* 13dB */
228 0x5d400, /* 14dB */
229 0x61800 /* 15dB */
232 static const unsigned int treble_table[] =
234 0xb2c00, /* -15dB */
235 0xbb400, /* -14dB */
236 0xc1800, /* -13dB */
237 0xc6c00, /* -12dB */
238 0xcbc00, /* -11dB */
239 0xd0400, /* -10dB */
240 0xd5000, /* -9dB */
241 0xd9800, /* -8dB */
242 0xde000, /* -7dB */
243 0xe2800, /* -6dB */
244 0xe7e00, /* -5dB */
245 0xec000, /* -4dB */
246 0xf0c00, /* -3dB */
247 0xf5c00, /* -2dB */
248 0xfac00, /* -1dB */
250 0x5400, /* 1dB */
251 0xac00, /* 2dB */
252 0x10400, /* 3dB */
253 0x16000, /* 4dB */
254 0x1c000, /* 5dB */
255 0x22400, /* 6dB */
256 0x28400, /* 7dB */
257 0x2ec00, /* 8dB */
258 0x35400, /* 9dB */
259 0x3c000, /* 10dB */
260 0x42c00, /* 11dB */
261 0x49c00, /* 12dB */
262 0x51800, /* 13dB */
263 0x58400, /* 14dB */
264 0x5f800 /* 15dB */
267 static const unsigned int prescale_table[] =
269 0x80000, /* 0db */
270 0x8e000, /* 1dB */
271 0x9a400, /* 2dB */
272 0xa5800, /* 3dB */
273 0xaf400, /* 4dB */
274 0xb8000, /* 5dB */
275 0xbfc00, /* 6dB */
276 0xc6c00, /* 7dB */
277 0xcd000, /* 8dB */
278 0xd25c0, /* 9dB */
279 0xd7800, /* 10dB */
280 0xdc000, /* 11dB */
281 0xdfc00, /* 12dB */
282 0xe3400, /* 13dB */
283 0xe6800, /* 14dB */
284 0xe9400 /* 15dB */
287 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
288 static int tenthdb2reg(int db)
290 if (db < -540) /* 3 dB steps */
291 return (db + 780) / 30;
292 else /* 1.5 dB steps */
293 return (db + 660) / 15;
295 #endif
297 #if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
298 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_WM8731) \
299 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
300 || defined(HAVE_AS3514)
301 /* volume/balance/treble/bass interdependency main part */
302 #define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
304 /* all values in tenth of dB MAS3507D UDA1380 */
305 int current_volume = 0; /* -780..+180 -840.. 0 */
306 int current_balance = 0; /* -960..+960 -840..+840 */
307 int current_treble = 0; /* -150..+150 0.. +60 */
308 int current_bass = 0; /* -150..+150 0..+240 */
310 static void set_prescaled_volume(void)
312 int prescale = 0;
313 int l, r;
315 /* The WM codecs listed don't have suitable prescaler functionality, so we let
316 * the prescaler stay at 0 for these unless SW tone controls are in use */
317 #if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \
318 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751))
320 prescale = MAX(current_bass, current_treble);
321 if (prescale < 0)
322 prescale = 0; /* no need to prescale if we don't boost
323 bass or treble */
325 /* Gain up the analog volume to compensate the prescale gain reduction,
326 * but if this would push the volume over the top, reduce prescaling
327 * instead (might cause clipping). */
328 if (current_volume + prescale > VOLUME_MAX)
329 prescale = VOLUME_MAX - current_volume;
330 #endif
332 #if defined(HAVE_SW_TONE_CONTROLS)
333 dsp_callback(DSP_CALLBACK_SET_PRESCALE, prescale);
334 #elif CONFIG_CODEC == MAS3507D
335 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
336 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8758)
337 audiohw_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
338 #endif
340 if (current_volume == VOLUME_MIN)
341 prescale = 0; /* Make sure the chip gets muted at VOLUME_MIN */
343 l = r = current_volume + prescale;
345 if (current_balance > 0)
347 l -= current_balance;
348 if (l < VOLUME_MIN)
349 l = VOLUME_MIN;
351 if (current_balance < 0)
353 r += current_balance;
354 if (r < VOLUME_MIN)
355 r = VOLUME_MIN;
358 #if CONFIG_CODEC == MAS3507D
359 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
360 #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \
361 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751) \
362 || defined(HAVE_AS3514)
363 audiohw_set_master_vol(tenthdb2master(l), tenthdb2master(r));
364 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8751)
365 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
366 #endif
368 #elif defined(HAVE_TLV320)
369 audiohw_set_headphone_vol(tenthdb2master(l), tenthdb2master(r));
370 #endif
372 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
373 #endif /* !SIMULATOR */
375 #if CONFIG_CODEC != SWCODEC
376 int channel_configuration = SOUND_CHAN_STEREO;
377 int stereo_width = 100;
378 #endif
380 #ifndef SIMULATOR
382 #if CONFIG_CODEC != SWCODEC
383 static void set_channel_config(void)
385 /* default values: stereo */
386 unsigned long val_ll = 0x80000;
387 unsigned long val_lr = 0;
388 unsigned long val_rl = 0;
389 unsigned long val_rr = 0x80000;
391 switch(channel_configuration)
393 /* case SOUND_CHAN_STEREO unnecessary */
395 case SOUND_CHAN_MONO:
396 val_ll = 0xc0000;
397 val_lr = 0xc0000;
398 val_rl = 0xc0000;
399 val_rr = 0xc0000;
400 break;
402 case SOUND_CHAN_CUSTOM:
404 /* fixed point variables (matching MAS internal format)
405 integer part: upper 13 bits (inlcuding sign)
406 fractional part: lower 19 bits */
407 long fp_width, fp_straight, fp_cross;
409 fp_width = (stereo_width << 19) / 100;
410 if (stereo_width <= 100)
412 fp_straight = - ((1<<19) + fp_width) / 2;
413 fp_cross = fp_straight + fp_width;
415 else
417 /* straight = - (1 + width) / (2 * width) */
418 fp_straight = - ((((1<<19) + fp_width) / (fp_width >> 9)) << 9);
419 fp_cross = (1<<19) + fp_straight;
421 val_ll = val_rr = fp_straight & 0xfffff;
422 val_lr = val_rl = fp_cross & 0xfffff;
424 break;
426 case SOUND_CHAN_MONO_LEFT:
427 val_ll = 0x80000;
428 val_lr = 0x80000;
429 val_rl = 0;
430 val_rr = 0;
431 break;
433 case SOUND_CHAN_MONO_RIGHT:
434 val_ll = 0;
435 val_lr = 0;
436 val_rl = 0x80000;
437 val_rr = 0x80000;
438 break;
440 case SOUND_CHAN_KARAOKE:
441 val_ll = 0xc0000;
442 val_lr = 0x40000;
443 val_rl = 0x40000;
444 val_rr = 0xc0000;
445 break;
448 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
449 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LL, &val_ll, 1); /* LL */
450 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LR, &val_lr, 1); /* LR */
451 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RL, &val_rl, 1); /* RL */
452 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RR, &val_rr, 1); /* RR */
453 #elif CONFIG_CODEC == MAS3507D
454 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
455 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
456 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
457 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
458 #endif
461 #endif /* CONFIG_CODEC != SWCODEC */
463 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
464 unsigned long mdb_shape_shadow = 0;
465 unsigned long loudness_shadow = 0;
466 #endif
468 void sound_set_volume(int value)
470 if(!audio_is_initialized)
471 return;
472 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
473 unsigned tmp = ((unsigned)(value + 115) & 0xff) << 8;
474 mas_codec_writereg(0x10, tmp);
475 #elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
476 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
477 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
478 || defined(HAVE_AS3514)
479 current_volume = value * 10; /* tenth of dB */
480 set_prescaled_volume();
481 #elif CONFIG_CPU == PNX0101
482 int tmp = (60 - value * 4) & 0xff;
483 CODECVOL = tmp | (tmp << 8);
484 #endif
487 void sound_set_balance(int value)
489 if(!audio_is_initialized)
490 return;
491 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
492 unsigned tmp = ((unsigned)(value * 127 / 100) & 0xff) << 8;
493 mas_codec_writereg(0x11, tmp);
494 #elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 \
495 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
496 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751) \
497 || defined(HAVE_AS3514)
498 current_balance = value * VOLUME_RANGE / 100; /* tenth of dB */
499 set_prescaled_volume();
500 #elif CONFIG_CPU == PNX0101
501 /* TODO: implement for iFP */
502 (void)value;
503 #endif
506 void sound_set_bass(int value)
508 if(!audio_is_initialized)
509 return;
510 #if defined(HAVE_SW_TONE_CONTROLS)
511 current_bass = value * 10;
512 dsp_callback(DSP_CALLBACK_SET_BASS, current_bass);
513 set_prescaled_volume();
514 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
515 unsigned tmp = ((unsigned)(value * 8) & 0xff) << 8;
516 mas_codec_writereg(0x14, tmp);
517 #elif CONFIG_CODEC == MAS3507D
518 mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
519 current_bass = value * 10;
520 set_prescaled_volume();
521 #elif defined(HAVE_WM8751)
522 current_bass = value;
523 audiohw_set_bass(value);
524 set_prescaled_volume();
525 #elif defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_UDA1380) \
526 || defined HAVE_WM8731 || defined(HAVE_WM8721)
527 current_bass = value * 10;
528 audiohw_set_bass(value);
529 set_prescaled_volume();
530 #elif CONFIG_CPU == PNX0101
531 /* TODO: implement for iFP */
532 (void)value;
533 #endif
536 void sound_set_treble(int value)
538 if(!audio_is_initialized)
539 return;
540 #if defined(HAVE_SW_TONE_CONTROLS)
541 current_treble = value * 10;
542 dsp_callback(DSP_CALLBACK_SET_TREBLE, current_treble);
543 set_prescaled_volume();
544 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
545 unsigned tmp = ((unsigned)(value * 8) & 0xff) << 8;
546 mas_codec_writereg(0x15, tmp);
547 #elif CONFIG_CODEC == MAS3507D
548 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
549 current_treble = value * 10;
550 set_prescaled_volume();
551 #elif defined(HAVE_WM8751)
552 audiohw_set_treble(value);
553 current_treble = value;
554 set_prescaled_volume();
555 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_UDA1380) \
556 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
557 audiohw_set_treble(value);
558 current_treble = value * 10;
559 set_prescaled_volume();
560 #elif CONFIG_CPU == PNX0101
561 /* TODO: implement for iFP */
562 (void)value;
563 #endif
566 void sound_set_channels(int value)
568 #if CONFIG_CODEC == SWCODEC
569 dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG, value);
570 #else
571 if(!audio_is_initialized)
572 return;
573 channel_configuration = value;
574 set_channel_config();
575 #endif
578 void sound_set_stereo_width(int value)
580 #if CONFIG_CODEC == SWCODEC
581 dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH, value);
582 #else
583 if(!audio_is_initialized)
584 return;
585 stereo_width = value;
586 if (channel_configuration == SOUND_CHAN_CUSTOM)
587 set_channel_config();
588 #endif
591 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
592 void sound_set_loudness(int value)
594 if(!audio_is_initialized)
595 return;
596 loudness_shadow = (loudness_shadow & 0x04) |
597 (MAX(MIN(value * 4, 0x44), 0) << 8);
598 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
601 void sound_set_avc(int value)
603 if(!audio_is_initialized)
604 return;
605 int tmp;
606 switch (value) {
607 case 1: /* 20ms */
608 tmp = (0x1 << 8) | (0x8 << 12);
609 break;
610 case 2: /* 2s */
611 tmp = (0x2 << 8) | (0x8 << 12);
612 break;
613 case 3: /* 4s */
614 tmp = (0x4 << 8) | (0x8 << 12);
615 break;
616 case 4: /* 8s */
617 tmp = (0x8 << 8) | (0x8 << 12);
618 break;
619 case -1: /* turn off and then turn on again to decay quickly */
620 tmp = mas_codec_readreg(MAS_REG_KAVC);
621 mas_codec_writereg(MAS_REG_KAVC, 0);
622 break;
623 default: /* off */
624 tmp = 0;
625 break;
627 mas_codec_writereg(MAS_REG_KAVC, tmp);
630 void sound_set_mdb_strength(int value)
632 if(!audio_is_initialized)
633 return;
634 mas_codec_writereg(MAS_REG_KMDB_STR, (value & 0x7f) << 8);
637 void sound_set_mdb_harmonics(int value)
639 if(!audio_is_initialized)
640 return;
641 int tmp = value * 127 / 100;
642 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0x7f) << 8);
645 void sound_set_mdb_center(int value)
647 if(!audio_is_initialized)
648 return;
649 mas_codec_writereg(MAS_REG_KMDB_FC, (value/10) << 8);
652 void sound_set_mdb_shape(int value)
654 if(!audio_is_initialized)
655 return;
656 mdb_shape_shadow = (mdb_shape_shadow & 0x02) | ((value/10) << 8);
657 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
660 void sound_set_mdb_enable(int value)
662 if(!audio_is_initialized)
663 return;
664 mdb_shape_shadow = (mdb_shape_shadow & ~0x02) | (value?2:0);
665 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
668 void sound_set_superbass(int value)
670 if(!audio_is_initialized)
671 return;
672 loudness_shadow = (loudness_shadow & ~0x04) | (value?4:0);
673 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
675 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
677 #else /* SIMULATOR */
678 void sound_set_volume(int value)
680 (void)value;
683 void sound_set_balance(int value)
685 (void)value;
688 void sound_set_bass(int value)
690 (void)value;
693 void sound_set_treble(int value)
695 (void)value;
698 void sound_set_channels(int value)
700 (void)value;
703 void sound_set_stereo_width(int value)
705 (void)value;
708 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
709 void sound_set_loudness(int value)
711 (void)value;
714 void sound_set_avc(int value)
716 (void)value;
719 void sound_set_mdb_strength(int value)
721 (void)value;
724 void sound_set_mdb_harmonics(int value)
726 (void)value;
729 void sound_set_mdb_center(int value)
731 (void)value;
734 void sound_set_mdb_shape(int value)
736 (void)value;
739 void sound_set_mdb_enable(int value)
741 (void)value;
744 void sound_set_superbass(int value)
746 (void)value;
748 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
749 #endif /* SIMULATOR */
751 void sound_set(int setting, int value)
753 sound_set_type* sound_set_val = sound_get_fn(setting);
754 if (sound_set_val)
755 sound_set_val(value);
758 int sound_val2phys(int setting, int value)
760 #if CONFIG_CODEC == MAS3587F
761 int result = 0;
763 switch(setting)
765 case SOUND_LEFT_GAIN:
766 case SOUND_RIGHT_GAIN:
767 result = (value - 2) * 15;
768 break;
770 case SOUND_MIC_GAIN:
771 result = value * 15 + 210;
772 break;
774 default:
775 result = value;
776 break;
778 return result;
779 #elif defined(HAVE_UDA1380)
780 int result = 0;
782 switch(setting)
784 case SOUND_LEFT_GAIN:
785 case SOUND_RIGHT_GAIN:
786 case SOUND_MIC_GAIN:
787 result = value * 5; /* (1/2) * 10 */
788 break;
790 default:
791 result = value;
792 break;
794 return result;
795 #elif defined(HAVE_TLV320)
796 int result = 0;
798 switch(setting)
800 case SOUND_LEFT_GAIN:
801 case SOUND_RIGHT_GAIN:
802 result = (value - 23) * 15; /* (x - 23)/1.5 *10 */
803 break;
805 case SOUND_MIC_GAIN:
806 result = value * 200; /* 0 or 20 dB */
807 break;
809 default:
810 result = value;
811 break;
813 return result;
814 #else
815 (void)setting;
816 return value;
817 #endif
820 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
821 #ifndef SIMULATOR
822 /* This function works by telling the decoder that we have another
823 crystal frequency than we actually have. It will adjust its internal
824 parameters and the result is that the audio is played at another pitch.
826 The pitch value is in tenths of percent.
828 static int last_pitch = 1000;
830 void sound_set_pitch(int pitch)
832 unsigned long val;
834 if (pitch != last_pitch)
836 /* Calculate the new (bogus) frequency */
837 val = 18432 * 1000 / pitch;
839 mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, &val, 1);
841 /* We must tell the MAS that the frequency has changed.
842 * This will unfortunately cause a short silence. */
843 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
845 last_pitch = pitch;
849 int sound_get_pitch(void)
851 return last_pitch;
853 #else /* SIMULATOR */
854 void sound_set_pitch(int pitch)
856 (void)pitch;
859 int sound_get_pitch(void)
861 return 1000;
863 #endif /* SIMULATOR */
864 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */