blob: f1c9ff79e7cba3d95f801693e5b9bbf206a0e4bd [file] [log] [blame]
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include <stdbool.h>
Linus Nielsen Feltzingd6f297e2005-06-05 23:46:09 +000020#include <stdio.h>
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000021#include "config.h"
22#include "sound.h"
Dave Chapman5ffa8c52006-01-30 21:12:31 +000023#include "logf.h"
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000024#ifndef SIMULATOR
25#include "i2c.h"
26#include "mas.h"
Thom Johansen38c9d752005-06-15 19:56:44 +000027#ifdef HAVE_UDA1380
28#include "uda1380.h"
Dave Chapman5ffa8c52006-01-30 21:12:31 +000029#elif defined(HAVE_WM8975)
30#include "wm8975.h"
Dave Chapman9581ad32006-02-13 13:48:08 +000031#elif defined(HAVE_WM8758)
32#include "wm8758.h"
Dave Chapman2f767632006-02-26 15:59:46 +000033#elif defined(HAVE_WM8731)
34#include "wm8731l.h"
Linus Nielsen Feltzing760fea92006-02-04 00:01:15 +000035#elif defined(HAVE_TLV320)
Christian Gmeiner14e80672005-08-06 10:12:19 +000036#include "tlv320.h"
Thom Johansen38c9d752005-06-15 19:56:44 +000037#endif
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000038#include "dac.h"
39#include "system.h"
40#include "hwcompat.h"
Jens Arnoldd6c05452005-08-29 21:15:27 +000041#if CONFIG_CODEC == SWCODEC
Linus Nielsen Feltzingd6f297e2005-06-05 23:46:09 +000042#include "pcm_playback.h"
43#endif
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000044#endif
45
46#ifndef SIMULATOR
47extern bool audio_is_initialized;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000048
Jens Arnoldd6c05452005-08-29 21:15:27 +000049#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000050extern unsigned long shadow_io_control_main;
51extern unsigned shadow_codec_reg0;
52#endif
Jens Arnold8051a0b2005-11-06 23:12:11 +000053#endif /* SIMULATOR */
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000054
Jens Arnold8051a0b2005-11-06 23:12:11 +000055struct sound_settings_info {
56 const char *unit;
57 int numdecimals;
58 int steps;
59 int minval;
60 int maxval;
61 int defaultval;
62 sound_set_type *setfn;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000063};
64
Jens Arnold8051a0b2005-11-06 23:12:11 +000065static const struct sound_settings_info sound_settings_table[] = {
Jens Arnoldd6c05452005-08-29 21:15:27 +000066#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold2993ae62005-12-07 23:07:07 +000067 [SOUND_VOLUME] = {"dB", 0, 1,-100, 12, -25, sound_set_volume},
Jens Arnold8051a0b2005-11-06 23:12:11 +000068 [SOUND_BASS] = {"dB", 0, 1, -12, 12, 6, sound_set_bass},
69 [SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 6, sound_set_treble},
Thom Johansen38c9d752005-06-15 19:56:44 +000070#elif defined(HAVE_UDA1380)
Jens Arnold2993ae62005-12-07 23:07:07 +000071 [SOUND_VOLUME] = {"dB", 0, 1, -84, 0, -25, sound_set_volume},
Jens Arnold8051a0b2005-11-06 23:12:11 +000072 [SOUND_BASS] = {"dB", 0, 2, 0, 24, 0, sound_set_bass},
73 [SOUND_TREBLE] = {"dB", 0, 2, 0, 6, 0, sound_set_treble},
Dave Chapman5ffa8c52006-01-30 21:12:31 +000074#elif defined(HAVE_WM8975)
75 [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -25, sound_set_volume},
76 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
77 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
Dave Chapman9581ad32006-02-13 13:48:08 +000078#elif defined(HAVE_WM8758)
79 [SOUND_VOLUME] = {"dB", 0, 1, -57, 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},
Dave Chapman2f767632006-02-26 15:59:46 +000082#elif defined(HAVE_WM8731)
83 [SOUND_VOLUME] = {"dB", 0, 1, -73, 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},
Jens Arnold8051a0b2005-11-06 23:12:11 +000086#else /* MAS3507D */
Jens Arnold2993ae62005-12-07 23:07:07 +000087 [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume},
Jens Arnold8051a0b2005-11-06 23:12:11 +000088 [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass},
89 [SOUND_TREBLE] = {"dB", 0, 1, -15, 15, 7, sound_set_treble},
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000090#endif
Jens Arnold8051a0b2005-11-06 23:12:11 +000091 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0, sound_set_balance},
92 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0, sound_set_channels},
93 [SOUND_STEREO_WIDTH] = {"%", 0, 1, 0, 255, 100, sound_set_stereo_width},
Jens Arnoldd6c05452005-08-29 21:15:27 +000094#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold8051a0b2005-11-06 23:12:11 +000095 [SOUND_LOUDNESS] = {"dB", 0, 1, 0, 17, 0, sound_set_loudness},
96 [SOUND_AVC] = {"", 0, 1, -1, 4, 0, sound_set_avc},
97 [SOUND_MDB_STRENGTH] = {"dB", 0, 1, 0, 127, 48, sound_set_mdb_strength},
98 [SOUND_MDB_HARMONICS] = {"%", 0, 1, 0, 100, 50, sound_set_mdb_harmonics},
99 [SOUND_MDB_CENTER] = {"Hz", 0, 10, 20, 300, 60, sound_set_mdb_center},
100 [SOUND_MDB_SHAPE] = {"Hz", 0, 10, 50, 300, 90, sound_set_mdb_shape},
101 [SOUND_MDB_ENABLE] = {"", 0, 1, 0, 1, 0, sound_set_mdb_enable},
102 [SOUND_SUPERBASS] = {"", 0, 1, 0, 1, 0, sound_set_superbass},
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000103#endif
Jens Arnold8051a0b2005-11-06 23:12:11 +0000104#if CONFIG_CODEC == MAS3587F
105 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 15, 8, NULL},
106 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 15, 8, NULL},
107 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 15, 2, NULL},
Andye6e54962005-11-12 04:00:56 +0000108#elif defined(HAVE_UDA1380)
109 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 8, 8, NULL},
110 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 8, 8, NULL},
111 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 15, 2, NULL},
Hristo Kovachevdb734b42006-02-08 13:08:55 +0000112 [SOUND_DECIMATOR_LEFT_GAIN] = {"dB", 1, 1,-128, 48, 0, NULL},
113 [SOUND_DECIMATOR_RIGHT_GAIN]= {"dB", 1, 1,-128, 48, 0, NULL},
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000114#endif
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000115};
116
117const char *sound_unit(int setting)
118{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000119 return sound_settings_table[setting].unit;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000120}
121
122int sound_numdecimals(int setting)
123{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000124 return sound_settings_table[setting].numdecimals;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000125}
126
127int sound_steps(int setting)
128{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000129 return sound_settings_table[setting].steps;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000130}
131
132int sound_min(int setting)
133{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000134 return sound_settings_table[setting].minval;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000135}
136
137int sound_max(int setting)
138{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000139 return sound_settings_table[setting].maxval;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000140}
141
142int sound_default(int setting)
143{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000144 return sound_settings_table[setting].defaultval;
145}
146
147sound_set_type* sound_get_fn(int setting)
148{
149 if ((unsigned)setting < (sizeof(sound_settings_table)
150 / sizeof(struct sound_settings_info)))
151 return sound_settings_table[setting].setfn;
152 else
153 return NULL;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000154}
155
156#ifndef SIMULATOR
Jens Arnoldd6c05452005-08-29 21:15:27 +0000157#if CONFIG_CODEC == MAS3507D /* volume/balance/treble/bass interdependency */
Jens Arnold12a0e222005-06-19 23:33:23 +0000158#define VOLUME_MIN -780
159#define VOLUME_MAX 180
160
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000161static const unsigned int bass_table[] =
162{
163 0x9e400, /* -15dB */
164 0xa2800, /* -14dB */
165 0xa7400, /* -13dB */
166 0xac400, /* -12dB */
167 0xb1800, /* -11dB */
168 0xb7400, /* -10dB */
169 0xbd400, /* -9dB */
170 0xc3c00, /* -8dB */
171 0xca400, /* -7dB */
172 0xd1800, /* -6dB */
173 0xd8c00, /* -5dB */
174 0xe0400, /* -4dB */
175 0xe8000, /* -3dB */
176 0xefc00, /* -2dB */
177 0xf7c00, /* -1dB */
178 0,
179 0x800, /* 1dB */
180 0x10000, /* 2dB */
181 0x17c00, /* 3dB */
182 0x1f800, /* 4dB */
183 0x27000, /* 5dB */
184 0x2e400, /* 6dB */
185 0x35800, /* 7dB */
186 0x3c000, /* 8dB */
187 0x42800, /* 9dB */
188 0x48800, /* 10dB */
189 0x4e400, /* 11dB */
190 0x53800, /* 12dB */
191 0x58800, /* 13dB */
192 0x5d400, /* 14dB */
193 0x61800 /* 15dB */
194};
195
196static const unsigned int treble_table[] =
197{
198 0xb2c00, /* -15dB */
199 0xbb400, /* -14dB */
200 0xc1800, /* -13dB */
201 0xc6c00, /* -12dB */
202 0xcbc00, /* -11dB */
203 0xd0400, /* -10dB */
204 0xd5000, /* -9dB */
205 0xd9800, /* -8dB */
206 0xde000, /* -7dB */
207 0xe2800, /* -6dB */
208 0xe7e00, /* -5dB */
209 0xec000, /* -4dB */
210 0xf0c00, /* -3dB */
211 0xf5c00, /* -2dB */
212 0xfac00, /* -1dB */
213 0,
214 0x5400, /* 1dB */
215 0xac00, /* 2dB */
216 0x10400, /* 3dB */
217 0x16000, /* 4dB */
218 0x1c000, /* 5dB */
219 0x22400, /* 6dB */
220 0x28400, /* 7dB */
221 0x2ec00, /* 8dB */
222 0x35400, /* 9dB */
223 0x3c000, /* 10dB */
224 0x42c00, /* 11dB */
225 0x49c00, /* 12dB */
226 0x51800, /* 13dB */
227 0x58400, /* 14dB */
228 0x5f800 /* 15dB */
229};
230
231static const unsigned int prescale_table[] =
232{
233 0x80000, /* 0db */
234 0x8e000, /* 1dB */
235 0x9a400, /* 2dB */
236 0xa5800, /* 3dB */
237 0xaf400, /* 4dB */
238 0xb8000, /* 5dB */
239 0xbfc00, /* 6dB */
240 0xc6c00, /* 7dB */
241 0xcd000, /* 8dB */
242 0xd25c0, /* 9dB */
243 0xd7800, /* 10dB */
244 0xdc000, /* 11dB */
245 0xdfc00, /* 12dB */
246 0xe3400, /* 13dB */
247 0xe6800, /* 14dB */
248 0xe9400 /* 15dB */
249};
250
Jens Arnold2993ae62005-12-07 23:07:07 +0000251/* convert tenth of dB volume (-780..+180) to dac3550 register value */
252static int tenthdb2reg(int db)
253{
254 if (db < -540) /* 3 dB steps */
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000255 return (db + 780) / 30;
Jens Arnold2993ae62005-12-07 23:07:07 +0000256 else /* 1.5 dB steps */
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000257 return (db + 660) / 15;
258}
Jens Arnold12a0e222005-06-19 23:33:23 +0000259#endif
260
261#ifdef HAVE_UDA1380 /* volume/balance/treble/bass interdependency */
262#define VOLUME_MIN -840
263#define VOLUME_MAX 0
264
Jens Arnold2993ae62005-12-07 23:07:07 +0000265/* convert tenth of dB volume (-840..0) to master volume register value */
266static int tenthdb2master(int db)
267{
Jens Arnold12a0e222005-06-19 23:33:23 +0000268 if (db < -720) /* 1.5 dB steps */
269 return (2940 - db) / 15;
270 else if (db < -660) /* 0.75 dB steps */
271 return (1110 - db) * 2 / 15;
272 else if (db < -520) /* 0.5 dB steps */
273 return (520 - db) / 5;
274 else /* 0.25 dB steps */
275 return -db * 2 / 5;
276}
Anton Oleynikov2654d912005-12-04 14:33:10 +0000277
Jens Arnold2993ae62005-12-07 23:07:07 +0000278/* convert tenth of dB volume (-780..0) to mixer volume register value */
279static int tenthdb2mixer(int db)
280{
281 if (db < -660) /* 1.5 dB steps */
282 return (2640 - db) / 15;
283 else if (db < -600) /* 0.75 dB steps */
284 return (990 - db) * 2 / 15;
285 else if (db < -460) /* 0.5 dB steps */
286 return (460 - db) / 5;
287 else /* 0.25 dB steps */
Anton Oleynikov2654d912005-12-04 14:33:10 +0000288 return -db * 2 / 5;
289}
290
Dave Chapman9581ad32006-02-13 13:48:08 +0000291#elif defined(HAVE_WM8975)
292/* volume/balance/treble/bass interdependency */
Dave Chapman5ffa8c52006-01-30 21:12:31 +0000293#define VOLUME_MIN -730
294#define VOLUME_MAX 60
295
296/* convert tenth of dB volume (-730..60) to master volume register value */
297static int tenthdb2master(int db)
298{
299 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
300 /* 1111111 == +6dB (0x7f) */
301 /* 1111001 == 0dB (0x79) */
302 /* 0110000 == -73dB (0x30 */
303 /* 0101111 == mute (0x2f) */
304
305 if (db <= -730) {
Dave Chapman9581ad32006-02-13 13:48:08 +0000306 return 0x0;
Dave Chapman5ffa8c52006-01-30 21:12:31 +0000307 } else {
Dave Chapman9581ad32006-02-13 13:48:08 +0000308 return((db/10)+73+0x2f);
309 }
310}
311
312/* convert tenth of dB volume (-780..0) to mixer volume register value */
313static int tenthdb2mixer(int db)
314{
315 if (db < -660) /* 1.5 dB steps */
316 return (2640 - db) / 15;
317 else if (db < -600) /* 0.75 dB steps */
318 return (990 - db) * 2 / 15;
319 else if (db < -460) /* 0.5 dB steps */
320 return (460 - db) / 5;
321 else /* 0.25 dB steps */
322 return -db * 2 / 5;
323}
324
325#elif defined(HAVE_WM8758)
326/* volume/balance/treble/bass interdependency */
327#define VOLUME_MIN -730
328#define VOLUME_MAX 60
329
330/* convert tenth of dB volume (-730..60) to master volume register value */
331static int tenthdb2master(int db)
332{
333 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
334 /* 1111111 == +6dB (0x7f) */
335 /* 1111001 == 0dB (0x79) */
336 /* 0110000 == -73dB (0x30 */
337 /* 0101111 == mute (0x2f) */
338
339 if (db <= -570) {
340 return 0x0;
341 } else {
342 return((db/10)+57);
Dave Chapman5ffa8c52006-01-30 21:12:31 +0000343 }
344}
345
346/* convert tenth of dB volume (-780..0) to mixer volume register value */
347static int tenthdb2mixer(int db)
348{
349 if (db < -660) /* 1.5 dB steps */
350 return (2640 - db) / 15;
351 else if (db < -600) /* 0.75 dB steps */
352 return (990 - db) * 2 / 15;
353 else if (db < -460) /* 0.5 dB steps */
354 return (460 - db) / 5;
355 else /* 0.25 dB steps */
356 return -db * 2 / 5;
357}
358
Dave Chapman2f767632006-02-26 15:59:46 +0000359#elif defined(HAVE_WM8731)
360/* volume/balance/treble/bass interdependency */
361#define VOLUME_MIN -730
362#define VOLUME_MAX 60
363
364/* convert tenth of dB volume (-730..60) to master volume register value */
365static int tenthdb2master(int db)
366{
367 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
368 /* 1111111 == +6dB (0x7f) */
369 /* 1111001 == 0dB (0x79) */
370 /* 0110000 == -73dB (0x30 */
371 /* 0101111 == mute (0x2f) */
372
373 if (db <= -570) {
374 return 0x0;
375 } else {
376 return((db/10)+57);
377 }
378}
379
380/* convert tenth of dB volume (-780..0) to mixer volume register value */
381static int tenthdb2mixer(int db)
382{
383 if (db < -660) /* 1.5 dB steps */
384 return (2640 - db) / 15;
385 else if (db < -600) /* 0.75 dB steps */
386 return (990 - db) * 2 / 15;
387 else if (db < -460) /* 0.5 dB steps */
388 return (460 - db) / 5;
389 else /* 0.25 dB steps */
390 return -db * 2 / 5;
391}
392
Jens Arnold12a0e222005-06-19 23:33:23 +0000393#endif
394
Dave Chapman9581ad32006-02-13 13:48:08 +0000395#if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || \
Dave Chapman2f767632006-02-26 15:59:46 +0000396 defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_WM8731)
Jens Arnold12a0e222005-06-19 23:33:23 +0000397 /* volume/balance/treble/bass interdependency main part */
398#define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
399
400/* all values in tenth of dB MAS3507D UDA1380 */
401int current_volume = 0; /* -780..+180 -840.. 0 */
402int current_balance = 0; /* -960..+960 -840..+840 */
403int current_treble = 0; /* -150..+150 0.. +60 */
404int current_bass = 0; /* -150..+150 0..+240 */
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000405
Jens Arnold4c7da882005-06-18 01:25:47 +0000406static void set_prescaled_volume(void)
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000407{
408 int prescale;
409 int l, r;
410
411 prescale = MAX(current_bass, current_treble);
412 if (prescale < 0)
413 prescale = 0; /* no need to prescale if we don't boost
414 bass or treble */
415
Jens Arnold2993ae62005-12-07 23:07:07 +0000416 /* Gain up the analog volume to compensate the prescale gain reduction,
417 * but if this would push the volume over the top, reduce prescaling
418 * instead (might cause clipping). */
Jens Arnold12a0e222005-06-19 23:33:23 +0000419 if (current_volume + prescale > VOLUME_MAX)
420 prescale = VOLUME_MAX - current_volume;
Jens Arnold2993ae62005-12-07 23:07:07 +0000421
422#if CONFIG_CODEC == MAS3507D
423 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
Dave Chapman5ffa8c52006-01-30 21:12:31 +0000424#elif defined(HAVE_UDA1380)
Jens Arnold2993ae62005-12-07 23:07:07 +0000425 uda1380_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
Dave Chapman2f767632006-02-26 15:59:46 +0000426#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
Dave Chapman9581ad32006-02-13 13:48:08 +0000427 wmcodec_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
Jens Arnold2993ae62005-12-07 23:07:07 +0000428#endif
429
430 if (current_volume == VOLUME_MIN)
431 prescale = 0; /* Make sure the chip gets muted at VOLUME_MIN */
432
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000433 l = r = current_volume + prescale;
434
435 if (current_balance > 0)
436 {
437 l -= current_balance;
Jens Arnold12a0e222005-06-19 23:33:23 +0000438 if (l < VOLUME_MIN)
439 l = VOLUME_MIN;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000440 }
441 if (current_balance < 0)
442 {
443 r += current_balance;
Jens Arnold12a0e222005-06-19 23:33:23 +0000444 if (r < VOLUME_MIN)
445 r = VOLUME_MIN;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000446 }
447
Jens Arnold2993ae62005-12-07 23:07:07 +0000448#if CONFIG_CODEC == MAS3507D
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000449 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
Dave Chapman5ffa8c52006-01-30 21:12:31 +0000450#elif defined(HAVE_UDA1380)
Jens Arnold2993ae62005-12-07 23:07:07 +0000451 uda1380_set_master_vol(tenthdb2master(l), tenthdb2master(r));
Dave Chapman2f767632006-02-26 15:59:46 +0000452#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
Dave Chapman9581ad32006-02-13 13:48:08 +0000453 wmcodec_set_master_vol(tenthdb2master(l), tenthdb2master(r));
Anton Oleynikov2654d912005-12-04 14:33:10 +0000454#endif
Anton Oleynikov2654d912005-12-04 14:33:10 +0000455}
Jens Arnoldd6c05452005-08-29 21:15:27 +0000456#endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000457#endif /* !SIMULATOR */
458
459int channel_configuration = SOUND_CHAN_STEREO;
460int stereo_width = 100;
461
462#ifndef SIMULATOR
463static void set_channel_config(void)
464{
465 /* default values: stereo */
466 unsigned long val_ll = 0x80000;
467 unsigned long val_lr = 0;
468 unsigned long val_rl = 0;
469 unsigned long val_rr = 0x80000;
470
471 switch(channel_configuration)
472 {
473 /* case SOUND_CHAN_STEREO unnecessary */
474
475 case SOUND_CHAN_MONO:
476 val_ll = 0xc0000;
477 val_lr = 0xc0000;
478 val_rl = 0xc0000;
479 val_rr = 0xc0000;
480 break;
481
482 case SOUND_CHAN_CUSTOM:
483 {
484 /* fixed point variables (matching MAS internal format)
485 integer part: upper 13 bits (inlcuding sign)
486 fractional part: lower 19 bits */
487 long fp_width, fp_straight, fp_cross;
488
489 fp_width = (stereo_width << 19) / 100;
490 if (stereo_width <= 100)
491 {
492 fp_straight = - ((1<<19) + fp_width) / 2;
493 fp_cross = fp_straight + fp_width;
494 }
495 else
496 {
497 fp_straight = - (1<<19);
498 fp_cross = ((2 * fp_width / (((1<<19) + fp_width) >> 10))
499 << 9) - (1<<19);
500 }
501 val_ll = val_rr = fp_straight & 0xFFFFF;
502 val_lr = val_rl = fp_cross & 0xFFFFF;
503 }
504 break;
505
506 case SOUND_CHAN_MONO_LEFT:
507 val_ll = 0x80000;
508 val_lr = 0x80000;
509 val_rl = 0;
510 val_rr = 0;
511 break;
512
513 case SOUND_CHAN_MONO_RIGHT:
514 val_ll = 0;
515 val_lr = 0;
516 val_rl = 0x80000;
517 val_rr = 0x80000;
518 break;
519
520 case SOUND_CHAN_KARAOKE:
521 val_ll = 0x80001;
522 val_lr = 0x7ffff;
523 val_rl = 0x7ffff;
524 val_rr = 0x80001;
525 break;
526 }
527
Jens Arnoldd6c05452005-08-29 21:15:27 +0000528#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000529 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LL, &val_ll, 1); /* LL */
530 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LR, &val_lr, 1); /* LR */
531 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RL, &val_rl, 1); /* RL */
532 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RR, &val_rr, 1); /* RR */
Jens Arnoldd6c05452005-08-29 21:15:27 +0000533#elif CONFIG_CODEC == MAS3507D
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000534 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
535 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
536 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
537 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
538#endif
539}
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000540
Jens Arnoldd6c05452005-08-29 21:15:27 +0000541#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000542unsigned long mdb_shape_shadow = 0;
543unsigned long loudness_shadow = 0;
544#endif
545
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000546void sound_set_volume(int value)
547{
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000548 if(!audio_is_initialized)
549 return;
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000550#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold2993ae62005-12-07 23:07:07 +0000551 unsigned tmp = ((unsigned)(value + 115) & 0xff) << 8;
552 mas_codec_writereg(0x10, tmp);
Dave Chapman9581ad32006-02-13 13:48:08 +0000553#elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || \
Dave Chapman2f767632006-02-26 15:59:46 +0000554 defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731
Jens Arnold2993ae62005-12-07 23:07:07 +0000555 current_volume = value * 10; /* tenth of dB */
556 set_prescaled_volume();
Tomasz Malesinskic31d2f82006-02-03 23:14:42 +0000557#elif CONFIG_CPU == PNX0101
558 /* TODO: implement for iFP */
559 (void)value;
Jens Arnold2993ae62005-12-07 23:07:07 +0000560#endif
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000561}
562
563void sound_set_balance(int value)
564{
565 if(!audio_is_initialized)
566 return;
567#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold2993ae62005-12-07 23:07:07 +0000568 unsigned tmp = ((unsigned)(value * 127 / 100) & 0xff) << 8;
569 mas_codec_writereg(0x11, tmp);
Dave Chapman9581ad32006-02-13 13:48:08 +0000570#elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 || \
Dave Chapman2f767632006-02-26 15:59:46 +0000571 defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000572 current_balance = value * VOLUME_RANGE / 100; /* tenth of dB */
573 set_prescaled_volume();
Tomasz Malesinskic31d2f82006-02-03 23:14:42 +0000574#elif CONFIG_CPU == PNX0101
575 /* TODO: implement for iFP */
576 (void)value;
Jens Arnold2993ae62005-12-07 23:07:07 +0000577#endif
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000578}
579
580void sound_set_bass(int value)
581{
582 if(!audio_is_initialized)
583 return;
584#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold2993ae62005-12-07 23:07:07 +0000585 unsigned tmp = ((unsigned)(value * 8) & 0xff) << 8;
586 mas_codec_writereg(0x14, tmp);
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000587#elif CONFIG_CODEC == MAS3507D
588 mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
589 current_bass = value * 10;
590 set_prescaled_volume();
591#elif defined(HAVE_UDA1380)
Jens Arnold2993ae62005-12-07 23:07:07 +0000592 uda1380_set_bass(value >> 1);
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000593 current_bass = value * 10;
Jens Arnold2993ae62005-12-07 23:07:07 +0000594 set_prescaled_volume();
Dave Chapman2f767632006-02-26 15:59:46 +0000595#elif defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731
Dave Chapman5ffa8c52006-01-30 21:12:31 +0000596 current_bass = value * 10;
Dave Chapman9581ad32006-02-13 13:48:08 +0000597 wmcodec_set_bass(value);
Dave Chapman5ffa8c52006-01-30 21:12:31 +0000598 set_prescaled_volume();
Tomasz Malesinskic31d2f82006-02-03 23:14:42 +0000599#elif CONFIG_CPU == PNX0101
600 /* TODO: implement for iFP */
601 (void)value;
Jens Arnold8051a0b2005-11-06 23:12:11 +0000602#endif
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000603}
604
605void sound_set_treble(int value)
606{
607 if(!audio_is_initialized)
608 return;
609#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold2993ae62005-12-07 23:07:07 +0000610 unsigned tmp = ((unsigned)(value * 8) & 0xff) << 8;
611 mas_codec_writereg(0x15, tmp);
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000612#elif CONFIG_CODEC == MAS3507D
613 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
614 current_treble = value * 10;
615 set_prescaled_volume();
616#elif defined(HAVE_UDA1380)
617 uda1380_set_treble(value >> 1);
618 current_treble = value * 10;
Jens Arnold2993ae62005-12-07 23:07:07 +0000619 set_prescaled_volume();
Dave Chapman2f767632006-02-26 15:59:46 +0000620#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
Dave Chapman9581ad32006-02-13 13:48:08 +0000621 wmcodec_set_treble(value);
Dave Chapman5ffa8c52006-01-30 21:12:31 +0000622 current_treble = value * 10;
623 set_prescaled_volume();
Tomasz Malesinskic31d2f82006-02-03 23:14:42 +0000624#elif CONFIG_CPU == PNX0101
625 /* TODO: implement for iFP */
626 (void)value;
Jens Arnold8051a0b2005-11-06 23:12:11 +0000627#endif
628}
629
630void sound_set_channels(int value)
631{
632 if(!audio_is_initialized)
633 return;
634 channel_configuration = value;
635 set_channel_config();
636}
637
638void sound_set_stereo_width(int value)
639{
640 if(!audio_is_initialized)
641 return;
642 stereo_width = value;
643 if (channel_configuration == SOUND_CHAN_CUSTOM)
644 set_channel_config();
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000645}
646
647#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
648void sound_set_loudness(int value)
649{
650 if(!audio_is_initialized)
651 return;
652 loudness_shadow = (loudness_shadow & 0x04) |
653 (MAX(MIN(value * 4, 0x44), 0) << 8);
654 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
655}
656
657void sound_set_avc(int value)
658{
659 if(!audio_is_initialized)
660 return;
661 int tmp;
662 switch (value) {
663 case 1: /* 20ms */
664 tmp = (0x1 << 8) | (0x8 << 12);
665 break;
666 case 2: /* 2s */
667 tmp = (0x2 << 8) | (0x8 << 12);
668 break;
669 case 3: /* 4s */
670 tmp = (0x4 << 8) | (0x8 << 12);
671 break;
672 case 4: /* 8s */
673 tmp = (0x8 << 8) | (0x8 << 12);
674 break;
675 case -1: /* turn off and then turn on again to decay quickly */
676 tmp = mas_codec_readreg(MAS_REG_KAVC);
677 mas_codec_writereg(MAS_REG_KAVC, 0);
678 break;
679 default: /* off */
680 tmp = 0;
681 break;
682 }
Jens Arnold8051a0b2005-11-06 23:12:11 +0000683 mas_codec_writereg(MAS_REG_KAVC, tmp);
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000684}
685
686void sound_set_mdb_strength(int value)
687{
688 if(!audio_is_initialized)
689 return;
Jens Arnold8051a0b2005-11-06 23:12:11 +0000690 mas_codec_writereg(MAS_REG_KMDB_STR, (value & 0x7f) << 8);
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000691}
692
693void sound_set_mdb_harmonics(int value)
694{
695 if(!audio_is_initialized)
696 return;
697 int tmp = value * 127 / 100;
698 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0x7f) << 8);
699}
700
701void sound_set_mdb_center(int value)
702{
703 if(!audio_is_initialized)
704 return;
705 mas_codec_writereg(MAS_REG_KMDB_FC, (value/10) << 8);
706}
707
708void sound_set_mdb_shape(int value)
709{
710 if(!audio_is_initialized)
711 return;
712 mdb_shape_shadow = (mdb_shape_shadow & 0x02) | ((value/10) << 8);
713 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
714}
715
716void sound_set_mdb_enable(int value)
717{
718 if(!audio_is_initialized)
719 return;
720 mdb_shape_shadow = (mdb_shape_shadow & ~0x02) | (value?2:0);
721 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
722}
723
724void sound_set_superbass(int value)
725{
726 if(!audio_is_initialized)
727 return;
728 loudness_shadow = (loudness_shadow & ~0x04) | (value?4:0);
729 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
730}
731#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
732
Jens Arnold8051a0b2005-11-06 23:12:11 +0000733#else /* SIMULATOR */
734void sound_set_volume(int value)
735{
736 (void)value;
737}
738
739void sound_set_balance(int value)
740{
741 (void)value;
742}
743
744void sound_set_bass(int value)
745{
746 (void)value;
747}
748
749void sound_set_treble(int value)
750{
751 (void)value;
752}
753
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000754void sound_set_channels(int value)
755{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000756 (void)value;
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000757}
758
759void sound_set_stereo_width(int value)
760{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000761 (void)value;
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000762}
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000763
Jens Arnoldd6c05452005-08-29 21:15:27 +0000764#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold8051a0b2005-11-06 23:12:11 +0000765void sound_set_loudness(int value)
766{
767 (void)value;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000768}
769
Jens Arnold8051a0b2005-11-06 23:12:11 +0000770void sound_set_avc(int value)
771{
772 (void)value;
773}
774
775void sound_set_mdb_strength(int value)
776{
777 (void)value;
778}
779
780void sound_set_mdb_harmonics(int value)
781{
782 (void)value;
783}
784
785void sound_set_mdb_center(int value)
786{
787 (void)value;
788}
789
790void sound_set_mdb_shape(int value)
791{
792 (void)value;
793}
794
795void sound_set_mdb_enable(int value)
796{
797 (void)value;
798}
799
800void sound_set_superbass(int value)
801{
802 (void)value;
803}
804#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
805#endif /* SIMULATOR */
806
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000807void sound_set(int setting, int value)
808{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000809 sound_set_type* sound_set_val = sound_get_fn(setting);
810 if (sound_set_val)
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000811 sound_set_val(value);
812}
813
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000814int sound_val2phys(int setting, int value)
815{
Jens Arnold8051a0b2005-11-06 23:12:11 +0000816#if CONFIG_CODEC == MAS3587F
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000817 int result = 0;
Jens Arnold8051a0b2005-11-06 23:12:11 +0000818
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000819 switch(setting)
820 {
821 case SOUND_LEFT_GAIN:
822 case SOUND_RIGHT_GAIN:
823 result = (value - 2) * 15;
824 break;
825
826 case SOUND_MIC_GAIN:
827 result = value * 15 + 210;
828 break;
829
830 default:
831 result = value;
832 break;
833 }
834 return result;
Andye6e54962005-11-12 04:00:56 +0000835#elif defined(HAVE_UDA1380)
836 int result = 0;
837
838 switch(setting)
839 {
840 case SOUND_LEFT_GAIN:
841 case SOUND_RIGHT_GAIN:
842 result = value * 30; /* (24/8) *10 */
843 break;
844
845 case SOUND_MIC_GAIN:
846 result = value * 20; /* (30/15) *10 */
847 break;
848
Hristo Kovachevdb734b42006-02-08 13:08:55 +0000849 case SOUND_DECIMATOR_LEFT_GAIN:
850 case SOUND_DECIMATOR_RIGHT_GAIN:
Andye6e54962005-11-12 04:00:56 +0000851 result = value * 5; /* (1/2) *10 */
852 break;
853
854 default:
855 result = value;
856 break;
857 }
858 return result;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000859#else
860 (void)setting;
861 return value;
862#endif
863}
864
Jens Arnoldd6c05452005-08-29 21:15:27 +0000865#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold8051a0b2005-11-06 23:12:11 +0000866#ifndef SIMULATOR
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000867/* This function works by telling the decoder that we have another
868 crystal frequency than we actually have. It will adjust its internal
869 parameters and the result is that the audio is played at another pitch.
870
871 The pitch value is in tenths of percent.
872*/
Jens Arnoldb9ebe6a2005-05-22 12:45:35 +0000873static int last_pitch = 1000;
874
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000875void sound_set_pitch(int pitch)
876{
877 unsigned long val;
878
Jens Arnoldb9ebe6a2005-05-22 12:45:35 +0000879 if (pitch != last_pitch)
880 {
881 /* Calculate the new (bogus) frequency */
882 val = 18432 * 1000 / pitch;
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000883
Jens Arnoldb9ebe6a2005-05-22 12:45:35 +0000884 mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, &val, 1);
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000885
Jens Arnoldb9ebe6a2005-05-22 12:45:35 +0000886 /* We must tell the MAS that the frequency has changed.
887 * This will unfortunately cause a short silence. */
888 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
Kevin Ferrare9b5264d2005-11-06 03:18:34 +0000889
Jens Arnoldb9ebe6a2005-05-22 12:45:35 +0000890 last_pitch = pitch;
891 }
892}
893
894int sound_get_pitch(void)
895{
896 return last_pitch;
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000897}
Jens Arnold8051a0b2005-11-06 23:12:11 +0000898#else /* SIMULATOR */
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000899void sound_set_pitch(int pitch)
900{
901 (void)pitch;
902}
Jens Arnoldb9ebe6a2005-05-22 12:45:35 +0000903
904int sound_get_pitch(void)
905{
906 return 1000;
907}
Jens Arnold8051a0b2005-11-06 23:12:11 +0000908#endif /* SIMULATOR */
909#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */