Patch #5771 by Frederik Vestre: Fix BMP loader to work in 64bit environments (simulator).
[Rockbox.git] / firmware / sound.c
blob7e29fddec55be49fbeb0ef9fd8cf80929f20e82b
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 #ifdef HAVE_UDA1380
28 #include "uda1380.h"
29 #elif defined(HAVE_WM8975) || defined(HAVE_WM8751)
30 #include "wm8975.h"
31 #elif defined(HAVE_WM8758)
32 #include "wm8758.h"
33 #elif defined(HAVE_WM8731) || defined(HAVE_WM8721)
34 #include "wm8731l.h"
35 #elif defined(HAVE_TLV320)
36 #include "tlv320.h"
37 #elif CONFIG_CPU == PNX0101
38 #include "pnx0101.h"
39 #endif
40 #include "dac.h"
41 #include "system.h"
42 #include "hwcompat.h"
43 #if CONFIG_CODEC == SWCODEC
44 #include "pcm_playback.h"
45 #endif
46 #endif
48 #ifndef SIMULATOR
49 extern bool audio_is_initialized;
51 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
52 extern unsigned long shadow_io_control_main;
53 extern unsigned shadow_codec_reg0;
54 #endif
55 #endif /* SIMULATOR */
57 struct sound_settings_info {
58 const char *unit;
59 int numdecimals;
60 int steps;
61 int minval;
62 int maxval;
63 int defaultval;
64 sound_set_type *setfn;
67 static const struct sound_settings_info sound_settings_table[] = {
68 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
69 [SOUND_VOLUME] = {"dB", 0, 1,-100, 12, -25, sound_set_volume},
70 [SOUND_BASS] = {"dB", 0, 1, -12, 12, 6, sound_set_bass},
71 [SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 6, sound_set_treble},
72 #elif defined(HAVE_UDA1380)
73 [SOUND_VOLUME] = {"dB", 0, 1, -84, 0, -25, sound_set_volume},
74 [SOUND_BASS] = {"dB", 0, 2, 0, 24, 0, sound_set_bass},
75 [SOUND_TREBLE] = {"dB", 0, 2, 0, 6, 0, sound_set_treble},
76 #elif defined(HAVE_TLV320)
77 [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -20, sound_set_volume},
78 #elif defined(HAVE_WM8975) || defined(HAVE_WM8751)
79 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25, sound_set_volume},
80 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
81 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
82 #elif defined(HAVE_WM8758)
83 [SOUND_VOLUME] = {"dB", 0, 1, -58, 6, -25, sound_set_volume},
84 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
85 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
86 #elif defined(HAVE_WM8731) || defined(HAVE_WM8721)
87 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25, sound_set_volume},
88 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
89 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
90 #elif (CONFIG_CPU == PNX0101)
91 [SOUND_VOLUME] = {"dB", 0, 1, -48, 15, 0, sound_set_volume},
92 #else /* MAS3507D */
93 [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume},
94 [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass},
95 [SOUND_TREBLE] = {"dB", 0, 1, -15, 15, 7, sound_set_treble},
96 #endif
97 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0, sound_set_balance},
98 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0, sound_set_channels},
99 [SOUND_STEREO_WIDTH] = {"%", 0, 1, 0, 255, 100, sound_set_stereo_width},
100 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
101 [SOUND_LOUDNESS] = {"dB", 0, 1, 0, 17, 0, sound_set_loudness},
102 [SOUND_AVC] = {"", 0, 1, -1, 4, 0, sound_set_avc},
103 [SOUND_MDB_STRENGTH] = {"dB", 0, 1, 0, 127, 48, sound_set_mdb_strength},
104 [SOUND_MDB_HARMONICS] = {"%", 0, 1, 0, 100, 50, sound_set_mdb_harmonics},
105 [SOUND_MDB_CENTER] = {"Hz", 0, 10, 20, 300, 60, sound_set_mdb_center},
106 [SOUND_MDB_SHAPE] = {"Hz", 0, 10, 50, 300, 90, sound_set_mdb_shape},
107 [SOUND_MDB_ENABLE] = {"", 0, 1, 0, 1, 0, sound_set_mdb_enable},
108 [SOUND_SUPERBASS] = {"", 0, 1, 0, 1, 0, sound_set_superbass},
109 #endif
110 #if CONFIG_CODEC == MAS3587F
111 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 15, 8, NULL},
112 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 15, 8, NULL},
113 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 15, 2, NULL},
114 #elif defined(HAVE_UDA1380)
115 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
116 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
117 [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16, NULL},
118 #elif defined(HAVE_TLV320)
119 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23, NULL},
120 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23, NULL},
121 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 1, NULL},
122 #endif
125 const char *sound_unit(int setting)
127 return sound_settings_table[setting].unit;
130 int sound_numdecimals(int setting)
132 return sound_settings_table[setting].numdecimals;
135 int sound_steps(int setting)
137 return sound_settings_table[setting].steps;
140 int sound_min(int setting)
142 return sound_settings_table[setting].minval;
145 int sound_max(int setting)
147 return sound_settings_table[setting].maxval;
150 int sound_default(int setting)
152 return sound_settings_table[setting].defaultval;
155 sound_set_type* sound_get_fn(int setting)
157 if ((unsigned)setting < (sizeof(sound_settings_table)
158 / sizeof(struct sound_settings_info)))
159 return sound_settings_table[setting].setfn;
160 else
161 return NULL;
164 #ifndef SIMULATOR
165 #if CONFIG_CODEC == MAS3507D /* volume/balance/treble/bass interdependency */
166 #define VOLUME_MIN -780
167 #define VOLUME_MAX 180
169 static const unsigned int bass_table[] =
171 0x9e400, /* -15dB */
172 0xa2800, /* -14dB */
173 0xa7400, /* -13dB */
174 0xac400, /* -12dB */
175 0xb1800, /* -11dB */
176 0xb7400, /* -10dB */
177 0xbd400, /* -9dB */
178 0xc3c00, /* -8dB */
179 0xca400, /* -7dB */
180 0xd1800, /* -6dB */
181 0xd8c00, /* -5dB */
182 0xe0400, /* -4dB */
183 0xe8000, /* -3dB */
184 0xefc00, /* -2dB */
185 0xf7c00, /* -1dB */
187 0x800, /* 1dB */
188 0x10000, /* 2dB */
189 0x17c00, /* 3dB */
190 0x1f800, /* 4dB */
191 0x27000, /* 5dB */
192 0x2e400, /* 6dB */
193 0x35800, /* 7dB */
194 0x3c000, /* 8dB */
195 0x42800, /* 9dB */
196 0x48800, /* 10dB */
197 0x4e400, /* 11dB */
198 0x53800, /* 12dB */
199 0x58800, /* 13dB */
200 0x5d400, /* 14dB */
201 0x61800 /* 15dB */
204 static const unsigned int treble_table[] =
206 0xb2c00, /* -15dB */
207 0xbb400, /* -14dB */
208 0xc1800, /* -13dB */
209 0xc6c00, /* -12dB */
210 0xcbc00, /* -11dB */
211 0xd0400, /* -10dB */
212 0xd5000, /* -9dB */
213 0xd9800, /* -8dB */
214 0xde000, /* -7dB */
215 0xe2800, /* -6dB */
216 0xe7e00, /* -5dB */
217 0xec000, /* -4dB */
218 0xf0c00, /* -3dB */
219 0xf5c00, /* -2dB */
220 0xfac00, /* -1dB */
222 0x5400, /* 1dB */
223 0xac00, /* 2dB */
224 0x10400, /* 3dB */
225 0x16000, /* 4dB */
226 0x1c000, /* 5dB */
227 0x22400, /* 6dB */
228 0x28400, /* 7dB */
229 0x2ec00, /* 8dB */
230 0x35400, /* 9dB */
231 0x3c000, /* 10dB */
232 0x42c00, /* 11dB */
233 0x49c00, /* 12dB */
234 0x51800, /* 13dB */
235 0x58400, /* 14dB */
236 0x5f800 /* 15dB */
239 static const unsigned int prescale_table[] =
241 0x80000, /* 0db */
242 0x8e000, /* 1dB */
243 0x9a400, /* 2dB */
244 0xa5800, /* 3dB */
245 0xaf400, /* 4dB */
246 0xb8000, /* 5dB */
247 0xbfc00, /* 6dB */
248 0xc6c00, /* 7dB */
249 0xcd000, /* 8dB */
250 0xd25c0, /* 9dB */
251 0xd7800, /* 10dB */
252 0xdc000, /* 11dB */
253 0xdfc00, /* 12dB */
254 0xe3400, /* 13dB */
255 0xe6800, /* 14dB */
256 0xe9400 /* 15dB */
259 /* convert tenth of dB volume (-780..+180) to dac3550 register value */
260 static int tenthdb2reg(int db)
262 if (db < -540) /* 3 dB steps */
263 return (db + 780) / 30;
264 else /* 1.5 dB steps */
265 return (db + 660) / 15;
267 #endif
269 #ifdef HAVE_UDA1380 /* volume/balance/treble/bass interdependency */
270 #define VOLUME_MIN -840
271 #define VOLUME_MAX 0
273 /* convert tenth of dB volume (-840..0) to master volume register value */
274 static int tenthdb2master(int db)
276 if (db < -720) /* 1.5 dB steps */
277 return (2940 - db) / 15;
278 else if (db < -660) /* 0.75 dB steps */
279 return (1110 - db) * 2 / 15;
280 else if (db < -520) /* 0.5 dB steps */
281 return (520 - db) / 5;
282 else /* 0.25 dB steps */
283 return -db * 2 / 5;
286 /* convert tenth of dB volume (-780..0) to mixer volume register value */
287 static int tenthdb2mixer(int db)
289 if (db < -660) /* 1.5 dB steps */
290 return (2640 - db) / 15;
291 else if (db < -600) /* 0.75 dB steps */
292 return (990 - db) * 2 / 15;
293 else if (db < -460) /* 0.5 dB steps */
294 return (460 - db) / 5;
295 else /* 0.25 dB steps */
296 return -db * 2 / 5;
299 #elif defined(HAVE_TLV320)
300 #define VOLUME_MIN -730
301 #define VOLUME_MAX 60
303 /* convert tenth of dB volume (-840..0) to master volume register value */
304 static int tenthdb2master(int db)
306 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
307 /* 1111111 == +6dB (0x7f) */
308 /* 1111001 == 0dB (0x79) */
309 /* 0110000 == -73dB (0x30 */
310 /* 0101111 == mute (0x2f) */
312 if (db < VOLUME_MIN) {
313 return 0x2f;
314 } else {
315 return((db/10)+73+0x30);
319 #elif defined(HAVE_WM8975) || defined(HAVE_WM8751)
320 /* volume/balance/treble/bass interdependency */
321 #define VOLUME_MIN -730
322 #define VOLUME_MAX 60
324 /* convert tenth of dB volume (-730..60) to master volume register value */
325 static int tenthdb2master(int db)
327 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
328 /* 1111111 == +6dB (0x7f) */
329 /* 1111001 == 0dB (0x79) */
330 /* 0110000 == -73dB (0x30 */
331 /* 0101111 == mute (0x2f) */
333 if (db < VOLUME_MIN) {
334 return 0x0;
335 } else {
336 return((db/10)+73+0x30);
340 /* convert tenth of dB volume (-780..0) to mixer volume register value */
341 static int tenthdb2mixer(int db)
343 if (db < -660) /* 1.5 dB steps */
344 return (2640 - db) / 15;
345 else if (db < -600) /* 0.75 dB steps */
346 return (990 - db) * 2 / 15;
347 else if (db < -460) /* 0.5 dB steps */
348 return (460 - db) / 5;
349 else /* 0.25 dB steps */
350 return -db * 2 / 5;
353 #elif defined(HAVE_WM8758)
354 /* volume/balance/treble/bass interdependency */
355 #define VOLUME_MIN -570
356 #define VOLUME_MAX 60
358 /* convert tenth of dB volume (-57..6) to master volume register value */
359 static int tenthdb2master(int db)
361 /* +6 to -57dB in 1dB steps == 64 levels = 6 bits */
362 /* 0111111 == +6dB (0x3f) = 63) */
363 /* 0111001 == 0dB (0x39) = 57) */
364 /* 0000001 == -56dB (0x01) = */
365 /* 0000000 == -57dB (0x00) */
367 /* 1000000 == Mute (0x40) */
369 if (db < VOLUME_MIN) {
370 return 0x40;
371 } else {
372 return((db/10)+57);
376 /* convert tenth of dB volume (-780..0) to mixer volume register value */
377 static int tenthdb2mixer(int db)
379 if (db < -660) /* 1.5 dB steps */
380 return (2640 - db) / 15;
381 else if (db < -600) /* 0.75 dB steps */
382 return (990 - db) * 2 / 15;
383 else if (db < -460) /* 0.5 dB steps */
384 return (460 - db) / 5;
385 else /* 0.25 dB steps */
386 return -db * 2 / 5;
389 #elif defined(HAVE_WM8731) || defined(HAVE_WM8721)
390 /* volume/balance/treble/bass interdependency */
391 #define VOLUME_MIN -730
392 #define VOLUME_MAX 60
394 /* convert tenth of dB volume (-730..60) to master volume register value */
395 static int tenthdb2master(int db)
397 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
398 /* 1111111 == +6dB (0x7f) */
399 /* 1111001 == 0dB (0x79) */
400 /* 0110000 == -73dB (0x30 */
401 /* 0101111 == mute (0x2f) */
403 if (db < VOLUME_MIN) {
404 return 0x2f;
405 } else {
406 return((db/10)+0x30+73);
410 /* convert tenth of dB volume (-780..0) to mixer volume register value */
411 static int tenthdb2mixer(int db)
413 if (db < -660) /* 1.5 dB steps */
414 return (2640 - db) / 15;
415 else if (db < -600) /* 0.75 dB steps */
416 return (990 - db) * 2 / 15;
417 else if (db < -460) /* 0.5 dB steps */
418 return (460 - db) / 5;
419 else /* 0.25 dB steps */
420 return -db * 2 / 5;
423 #endif
425 #if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
426 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_WM8731) \
427 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751)
428 /* volume/balance/treble/bass interdependency main part */
429 #define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
431 /* all values in tenth of dB MAS3507D UDA1380 */
432 int current_volume = 0; /* -780..+180 -840.. 0 */
433 int current_balance = 0; /* -960..+960 -840..+840 */
434 int current_treble = 0; /* -150..+150 0.. +60 */
435 int current_bass = 0; /* -150..+150 0..+240 */
437 static void set_prescaled_volume(void)
439 int prescale = 0;
440 int l, r;
442 #ifndef HAVE_TLV320
443 prescale = MAX(current_bass, current_treble);
444 if (prescale < 0)
445 prescale = 0; /* no need to prescale if we don't boost
446 bass or treble */
448 /* Gain up the analog volume to compensate the prescale gain reduction,
449 * but if this would push the volume over the top, reduce prescaling
450 * instead (might cause clipping). */
451 if (current_volume + prescale > VOLUME_MAX)
452 prescale = VOLUME_MAX - current_volume;
453 #endif
455 #if CONFIG_CODEC == MAS3507D
456 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
457 #elif defined(HAVE_UDA1380)
458 uda1380_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
459 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
460 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751)
461 wmcodec_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
462 #endif
464 if (current_volume == VOLUME_MIN)
465 prescale = 0; /* Make sure the chip gets muted at VOLUME_MIN */
467 l = r = current_volume + prescale;
469 if (current_balance > 0)
471 l -= current_balance;
472 if (l < VOLUME_MIN)
473 l = VOLUME_MIN;
475 if (current_balance < 0)
477 r += current_balance;
478 if (r < VOLUME_MIN)
479 r = VOLUME_MIN;
482 #if CONFIG_CODEC == MAS3507D
483 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
484 #elif defined(HAVE_UDA1380)
485 uda1380_set_master_vol(tenthdb2master(l), tenthdb2master(r));
486 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
487 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751)
488 wmcodec_set_master_vol(tenthdb2master(l), tenthdb2master(r));
489 #if defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8751)
490 wmcodec_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
491 #endif
493 #elif defined(HAVE_TLV320)
494 tlv320_set_headphone_vol(tenthdb2master(l), tenthdb2master(r));
495 #endif
497 #endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
498 #endif /* !SIMULATOR */
500 #if CONFIG_CODEC != SWCODEC
501 int channel_configuration = SOUND_CHAN_STEREO;
502 int stereo_width = 100;
503 #endif
505 #ifndef SIMULATOR
507 #if CONFIG_CODEC != SWCODEC
508 static void set_channel_config(void)
510 /* default values: stereo */
511 unsigned long val_ll = 0x80000;
512 unsigned long val_lr = 0;
513 unsigned long val_rl = 0;
514 unsigned long val_rr = 0x80000;
516 switch(channel_configuration)
518 /* case SOUND_CHAN_STEREO unnecessary */
520 case SOUND_CHAN_MONO:
521 val_ll = 0xc0000;
522 val_lr = 0xc0000;
523 val_rl = 0xc0000;
524 val_rr = 0xc0000;
525 break;
527 case SOUND_CHAN_CUSTOM:
529 /* fixed point variables (matching MAS internal format)
530 integer part: upper 13 bits (inlcuding sign)
531 fractional part: lower 19 bits */
532 long fp_width, fp_straight, fp_cross;
534 fp_width = (stereo_width << 19) / 100;
535 if (stereo_width <= 100)
537 fp_straight = - ((1<<19) + fp_width) / 2;
538 fp_cross = fp_straight + fp_width;
540 else
542 /* straight = - (1 + width) / (2 * width) */
543 fp_straight = - ((((1<<19) + fp_width) / (fp_width >> 9)) << 9);
544 fp_cross = (1<<19) + fp_straight;
546 val_ll = val_rr = fp_straight & 0xfffff;
547 val_lr = val_rl = fp_cross & 0xfffff;
549 break;
551 case SOUND_CHAN_MONO_LEFT:
552 val_ll = 0x80000;
553 val_lr = 0x80000;
554 val_rl = 0;
555 val_rr = 0;
556 break;
558 case SOUND_CHAN_MONO_RIGHT:
559 val_ll = 0;
560 val_lr = 0;
561 val_rl = 0x80000;
562 val_rr = 0x80000;
563 break;
565 case SOUND_CHAN_KARAOKE:
566 val_ll = 0xc0000;
567 val_lr = 0x40000;
568 val_rl = 0x40000;
569 val_rr = 0xc0000;
570 break;
573 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
574 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LL, &val_ll, 1); /* LL */
575 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LR, &val_lr, 1); /* LR */
576 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RL, &val_rl, 1); /* RL */
577 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RR, &val_rr, 1); /* RR */
578 #elif CONFIG_CODEC == MAS3507D
579 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
580 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
581 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
582 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
583 #endif
586 #endif /* CONFIG_CODEC != SWCODEC */
588 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
589 unsigned long mdb_shape_shadow = 0;
590 unsigned long loudness_shadow = 0;
591 #endif
593 void sound_set_volume(int value)
595 if(!audio_is_initialized)
596 return;
597 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
598 unsigned tmp = ((unsigned)(value + 115) & 0xff) << 8;
599 mas_codec_writereg(0x10, tmp);
600 #elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 \
601 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
602 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751)
603 current_volume = value * 10; /* tenth of dB */
604 set_prescaled_volume();
605 #elif CONFIG_CPU == PNX0101
606 int tmp = (60 - value * 4) & 0xff;
607 CODECVOL = tmp | (tmp << 8);
608 #endif
611 void sound_set_balance(int value)
613 if(!audio_is_initialized)
614 return;
615 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
616 unsigned tmp = ((unsigned)(value * 127 / 100) & 0xff) << 8;
617 mas_codec_writereg(0x11, tmp);
618 #elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 \
619 || defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731 \
620 || defined(HAVE_WM8721) || defined(HAVE_TLV320) || defined(HAVE_WM8751)
621 current_balance = value * VOLUME_RANGE / 100; /* tenth of dB */
622 set_prescaled_volume();
623 #elif CONFIG_CPU == PNX0101
624 /* TODO: implement for iFP */
625 (void)value;
626 #endif
629 #ifndef HAVE_TLV320
630 void sound_set_bass(int value)
632 if(!audio_is_initialized)
633 return;
634 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
635 unsigned tmp = ((unsigned)(value * 8) & 0xff) << 8;
636 mas_codec_writereg(0x14, tmp);
637 #elif CONFIG_CODEC == MAS3507D
638 mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
639 current_bass = value * 10;
640 set_prescaled_volume();
641 #elif defined(HAVE_UDA1380)
642 uda1380_set_bass(value >> 1);
643 current_bass = value * 10;
644 set_prescaled_volume();
645 #elif defined HAVE_WM8975 || defined HAVE_WM8758 \
646 || defined HAVE_WM8731 || defined(HAVE_WM8721) || defined(HAVE_WM8751)
647 current_bass = value * 10;
648 wmcodec_set_bass(value);
649 set_prescaled_volume();
650 #elif CONFIG_CPU == PNX0101
651 /* TODO: implement for iFP */
652 (void)value;
653 #endif
656 void sound_set_treble(int value)
658 if(!audio_is_initialized)
659 return;
660 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
661 unsigned tmp = ((unsigned)(value * 8) & 0xff) << 8;
662 mas_codec_writereg(0x15, tmp);
663 #elif CONFIG_CODEC == MAS3507D
664 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
665 current_treble = value * 10;
666 set_prescaled_volume();
667 #elif defined(HAVE_UDA1380)
668 uda1380_set_treble(value >> 1);
669 current_treble = value * 10;
670 set_prescaled_volume();
671 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
672 || defined(HAVE_WM8731) || defined(HAVE_WM8721) || defined(HAVE_WM8751)
673 wmcodec_set_treble(value);
674 current_treble = value * 10;
675 set_prescaled_volume();
676 #elif CONFIG_CPU == PNX0101
677 /* TODO: implement for iFP */
678 (void)value;
679 #endif
681 #endif /* HAVE_TLV320 */
683 void sound_set_channels(int value)
685 #if CONFIG_CODEC == SWCODEC
686 (void)value;
687 #else
688 if(!audio_is_initialized)
689 return;
690 channel_configuration = value;
691 set_channel_config();
692 #endif
695 void sound_set_stereo_width(int value)
697 #if CONFIG_CODEC == SWCODEC
698 (void)value;
699 #else
700 if(!audio_is_initialized)
701 return;
702 stereo_width = value;
703 if (channel_configuration == SOUND_CHAN_CUSTOM)
704 set_channel_config();
705 #endif
708 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
709 void sound_set_loudness(int value)
711 if(!audio_is_initialized)
712 return;
713 loudness_shadow = (loudness_shadow & 0x04) |
714 (MAX(MIN(value * 4, 0x44), 0) << 8);
715 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
718 void sound_set_avc(int value)
720 if(!audio_is_initialized)
721 return;
722 int tmp;
723 switch (value) {
724 case 1: /* 20ms */
725 tmp = (0x1 << 8) | (0x8 << 12);
726 break;
727 case 2: /* 2s */
728 tmp = (0x2 << 8) | (0x8 << 12);
729 break;
730 case 3: /* 4s */
731 tmp = (0x4 << 8) | (0x8 << 12);
732 break;
733 case 4: /* 8s */
734 tmp = (0x8 << 8) | (0x8 << 12);
735 break;
736 case -1: /* turn off and then turn on again to decay quickly */
737 tmp = mas_codec_readreg(MAS_REG_KAVC);
738 mas_codec_writereg(MAS_REG_KAVC, 0);
739 break;
740 default: /* off */
741 tmp = 0;
742 break;
744 mas_codec_writereg(MAS_REG_KAVC, tmp);
747 void sound_set_mdb_strength(int value)
749 if(!audio_is_initialized)
750 return;
751 mas_codec_writereg(MAS_REG_KMDB_STR, (value & 0x7f) << 8);
754 void sound_set_mdb_harmonics(int value)
756 if(!audio_is_initialized)
757 return;
758 int tmp = value * 127 / 100;
759 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0x7f) << 8);
762 void sound_set_mdb_center(int value)
764 if(!audio_is_initialized)
765 return;
766 mas_codec_writereg(MAS_REG_KMDB_FC, (value/10) << 8);
769 void sound_set_mdb_shape(int value)
771 if(!audio_is_initialized)
772 return;
773 mdb_shape_shadow = (mdb_shape_shadow & 0x02) | ((value/10) << 8);
774 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
777 void sound_set_mdb_enable(int value)
779 if(!audio_is_initialized)
780 return;
781 mdb_shape_shadow = (mdb_shape_shadow & ~0x02) | (value?2:0);
782 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
785 void sound_set_superbass(int value)
787 if(!audio_is_initialized)
788 return;
789 loudness_shadow = (loudness_shadow & ~0x04) | (value?4:0);
790 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
792 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
794 #else /* SIMULATOR */
795 void sound_set_volume(int value)
797 (void)value;
800 void sound_set_balance(int value)
802 (void)value;
805 void sound_set_bass(int value)
807 (void)value;
810 void sound_set_treble(int value)
812 (void)value;
815 void sound_set_channels(int value)
817 (void)value;
820 void sound_set_stereo_width(int value)
822 (void)value;
825 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
826 void sound_set_loudness(int value)
828 (void)value;
831 void sound_set_avc(int value)
833 (void)value;
836 void sound_set_mdb_strength(int value)
838 (void)value;
841 void sound_set_mdb_harmonics(int value)
843 (void)value;
846 void sound_set_mdb_center(int value)
848 (void)value;
851 void sound_set_mdb_shape(int value)
853 (void)value;
856 void sound_set_mdb_enable(int value)
858 (void)value;
861 void sound_set_superbass(int value)
863 (void)value;
865 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
866 #endif /* SIMULATOR */
868 void sound_set(int setting, int value)
870 sound_set_type* sound_set_val = sound_get_fn(setting);
871 if (sound_set_val)
872 sound_set_val(value);
875 int sound_val2phys(int setting, int value)
877 #if CONFIG_CODEC == MAS3587F
878 int result = 0;
880 switch(setting)
882 case SOUND_LEFT_GAIN:
883 case SOUND_RIGHT_GAIN:
884 result = (value - 2) * 15;
885 break;
887 case SOUND_MIC_GAIN:
888 result = value * 15 + 210;
889 break;
891 default:
892 result = value;
893 break;
895 return result;
896 #elif defined(HAVE_UDA1380)
897 int result = 0;
899 switch(setting)
901 case SOUND_LEFT_GAIN:
902 case SOUND_RIGHT_GAIN:
903 case SOUND_MIC_GAIN:
904 result = value * 5; /* (1/2) * 10 */
905 break;
907 default:
908 result = value;
909 break;
911 return result;
912 #elif defined(HAVE_TLV320)
913 int result = 0;
915 switch(setting)
917 case SOUND_LEFT_GAIN:
918 case SOUND_RIGHT_GAIN:
919 result = (value - 23) * 15; /* (x - 23)/1.5 *10 */
920 break;
922 case SOUND_MIC_GAIN:
923 result = value * 200; /* 0 or 20 dB */
924 break;
926 default:
927 result = value;
928 break;
930 return result;
931 #else
932 (void)setting;
933 return value;
934 #endif
937 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
938 #ifndef SIMULATOR
939 /* This function works by telling the decoder that we have another
940 crystal frequency than we actually have. It will adjust its internal
941 parameters and the result is that the audio is played at another pitch.
943 The pitch value is in tenths of percent.
945 static int last_pitch = 1000;
947 void sound_set_pitch(int pitch)
949 unsigned long val;
951 if (pitch != last_pitch)
953 /* Calculate the new (bogus) frequency */
954 val = 18432 * 1000 / pitch;
956 mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, &val, 1);
958 /* We must tell the MAS that the frequency has changed.
959 * This will unfortunately cause a short silence. */
960 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
962 last_pitch = pitch;
966 int sound_get_pitch(void)
968 return last_pitch;
970 #else /* SIMULATOR */
971 void sound_set_pitch(int pitch)
973 (void)pitch;
976 int sound_get_pitch(void)
978 return 1000;
980 #endif /* SIMULATOR */
981 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */