summaryrefslogtreecommitdiff
path: root/firmware/drivers/audio/uda1380.c
diff options
context:
space:
mode:
authorMarcoen Hirschberg <marcoen@gmail.com>2007-04-19 10:46:50 +0000
committerMarcoen Hirschberg <marcoen@gmail.com>2007-04-19 10:46:50 +0000
commit15dfe87f9606a191707d5c7b3b33b21963510f53 (patch)
tree5c31520b84dc60aff6997eac6a7e8b4b3ec1127e /firmware/drivers/audio/uda1380.c
parentf725ef12565a65d46ff2f9bd34eb3e19da7b763e (diff)
downloadrockbox-15dfe87f9606a191707d5c7b3b33b21963510f53.tar.gz
rockbox-15dfe87f9606a191707d5c7b3b33b21963510f53.zip
move audio drivers together into a subdir
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13209 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/audio/uda1380.c')
-rw-r--r--firmware/drivers/audio/uda1380.c460
1 files changed, 460 insertions, 0 deletions
diff --git a/firmware/drivers/audio/uda1380.c b/firmware/drivers/audio/uda1380.c
new file mode 100644
index 0000000000..6984427fc9
--- /dev/null
+++ b/firmware/drivers/audio/uda1380.c
@@ -0,0 +1,460 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Andy Young
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 "lcd.h"
20#include "cpu.h"
21#include "kernel.h"
22#include "thread.h"
23#include "power.h"
24#include "debug.h"
25#include "system.h"
26#include "sprintf.h"
27#include "button.h"
28#include "string.h"
29#include "file.h"
30#include "buffer.h"
31#include "audio.h"
32#include "logf.h"
33
34#include "i2c-coldfire.h"
35#include "uda1380.h"
36#include "pcf50606.h"
37
38/* convert tenth of dB volume (-840..0) to master volume register value */
39int tenthdb2master(int db)
40{
41 if (db < -720) /* 1.5 dB steps */
42 return (2940 - db) / 15;
43 else if (db < -660) /* 0.75 dB steps */
44 return (1110 - db) * 2 / 15;
45 else if (db < -520) /* 0.5 dB steps */
46 return (520 - db) / 5;
47 else /* 0.25 dB steps */
48 return -db * 2 / 5;
49}
50
51/* convert tenth of dB volume (-780..0) to mixer volume register value */
52int tenthdb2mixer(int db)
53{
54 if (db < -660) /* 1.5 dB steps */
55 return (2640 - db) / 15;
56 else if (db < -600) /* 0.75 dB steps */
57 return (990 - db) * 2 / 15;
58 else if (db < -460) /* 0.5 dB steps */
59 return (460 - db) / 5;
60 else /* 0.25 dB steps */
61 return -db * 2 / 5;
62}
63
64/* ------------------------------------------------- */
65/* Local functions and variables */
66/* ------------------------------------------------- */
67
68int uda1380_write_reg(unsigned char reg, unsigned short value);
69unsigned short uda1380_regs[0x30];
70short recgain_mic;
71short recgain_line;
72
73/* Definition of a playback configuration to start with */
74
75#define NUM_DEFAULT_REGS 13
76unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
77{
78 REG_0, EN_DAC | EN_INT | EN_DEC | ADC_CLK | DAC_CLK |
79 SYSCLK_256FS | WSPLL_25_50,
80 REG_I2S, I2S_IFMT_IIS,
81 REG_PWR, PON_PLL | PON_BIAS,
82 /* PON_HP & PON_DAC is enabled later */
83 REG_AMIX, AMIX_RIGHT(0x3f) | AMIX_LEFT(0x3f),
84 /* 00=max, 3f=mute */
85 REG_MASTER_VOL, MASTER_VOL_LEFT(0x20) | MASTER_VOL_RIGHT(0x20),
86 /* 00=max, ff=mute */
87 REG_MIX_VOL, MIX_VOL_CH_1(0) | MIX_VOL_CH_2(0xff),
88 /* 00=max, ff=mute */
89 REG_EQ, EQ_MODE_MAX,
90 /* Bass and treble = 0 dB */
91 REG_MUTE, MUTE_MASTER | MUTE_CH2,
92 /* Mute everything to start with */
93 REG_MIX_CTL, MIX_CTL_MIX,
94 /* Enable mixer */
95 REG_DEC_VOL, 0,
96 REG_PGA, MUTE_ADC,
97 REG_ADC, SKIP_DCFIL,
98 REG_AGC, 0
99};
100
101
102
103/* Returns 0 if register was written or -1 if write failed */
104int uda1380_write_reg(unsigned char reg, unsigned short value)
105{
106 unsigned char data[3];
107
108 data[0] = reg;
109 data[1] = value >> 8;
110 data[2] = value & 0xff;
111
112 if (i2c_write(I2C_IFACE_0, UDA1380_ADDR, data, 3) != 3)
113 {
114 DEBUGF("uda1380 error reg=0x%x", reg);
115 return -1;
116 }
117
118 uda1380_regs[reg] = value;
119
120 return 0;
121}
122
123/**
124 * Sets left and right master volume (0(max) to 252(muted))
125 */
126int audiohw_set_master_vol(int vol_l, int vol_r)
127{
128 return uda1380_write_reg(REG_MASTER_VOL,
129 MASTER_VOL_LEFT(vol_l) | MASTER_VOL_RIGHT(vol_r));
130}
131
132/**
133 * Sets mixer volume for both channels (0(max) to 228(muted))
134 */
135int audiohw_set_mixer_vol(int channel1, int channel2)
136{
137 return uda1380_write_reg(REG_MIX_VOL,
138 MIX_VOL_CH_1(channel1) | MIX_VOL_CH_2(channel2));
139}
140
141/**
142 * Sets the bass value (0-12)
143 */
144void audiohw_set_bass(int value)
145{
146 uda1380_write_reg(REG_EQ, (uda1380_regs[REG_EQ] & ~BASS_MASK)
147 | BASSL(value) | BASSR(value));
148}
149
150/**
151 * Sets the treble value (0-3)
152 */
153void audiohw_set_treble(int value)
154{
155 uda1380_write_reg(REG_EQ, (uda1380_regs[REG_EQ] & ~TREBLE_MASK)
156 | TREBLEL(value) | TREBLER(value));
157}
158
159/**
160 * Mute (mute=1) or enable sound (mute=0)
161 *
162 */
163int audiohw_mute(int mute)
164{
165 unsigned int value = uda1380_regs[REG_MUTE];
166
167 if (mute)
168 value = value | MUTE_MASTER;
169 else
170 value = value & ~MUTE_MASTER;
171
172 return uda1380_write_reg(REG_MUTE, value);
173}
174
175/* Returns 0 if successful or -1 if some register failed */
176int audiohw_set_regs(void)
177{
178 int i;
179 memset(uda1380_regs, 0, sizeof(uda1380_regs));
180
181 /* Initialize all registers */
182 for (i=0; i<NUM_DEFAULT_REGS; i++)
183 {
184 unsigned char reg = uda1380_defaults[i*2+0];
185 unsigned short value = uda1380_defaults[i*2+1];
186
187 if (uda1380_write_reg(reg, value) == -1)
188 return -1;
189 }
190
191 return 0;
192}
193
194/* Silently enable / disable audio output */
195void audiohw_enable_output(bool enable)
196{
197 if (enable) {
198 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_DAC | PON_HP);
199 } else {
200 uda1380_write_reg(REG_MUTE, MUTE_MASTER);
201 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] & ~PON_DAC);
202 }
203}
204
205void audiohw_reset(void)
206{
207#ifdef IRIVER_H300_SERIES
208 int mask = set_irq_level(HIGHEST_IRQ_LEVEL);
209 pcf50606_write(0x3b, 0x00); /* GPOOD2 high Z */
210 pcf50606_write(0x3b, 0x07); /* GPOOD2 low */
211 set_irq_level(mask);
212#else
213 /* RESET signal */
214 or_l(1<<29, &GPIO_OUT);
215 or_l(1<<29, &GPIO_ENABLE);
216 or_l(1<<29, &GPIO_FUNCTION);
217 sleep(HZ/100);
218 and_l(~(1<<29), &GPIO_OUT);
219#endif
220}
221
222/**
223 * Sets frequency settings for DAC and ADC relative to MCLK
224 *
225 * Selection for frequency ranges:
226 * Fs: range: with:
227 * 11025: 0 = 6.25 to 12.5 MCLK/2 SCLK, LRCK: Audio Clk / 16
228 * 22050: 1 = 12.5 to 25 MCLK/2 SCLK, LRCK: Audio Clk / 8
229 * 44100: 2 = 25 to 50 MCLK SCLK, LRCK: Audio Clk / 4 (default)
230 * 88200: 3 = 50 to 100 MCLK SCLK, LRCK: Audio Clk / 2 <= TODO: Needs WSPLL
231 */
232void audiohw_set_frequency(unsigned fsel)
233{
234 static const unsigned short values_reg[4][2] =
235 {
236 /* Fs: */
237 { 0, WSPLL_625_125 | SYSCLK_512FS }, /* 11025 */
238 { 0, WSPLL_125_25 | SYSCLK_256FS }, /* 22050 */
239 { MIX_CTL_SEL_NS, WSPLL_25_50 | SYSCLK_256FS }, /* 44100 */
240 { MIX_CTL_SEL_NS, WSPLL_50_100 | SYSCLK_256FS }, /* 88200 */
241 };
242
243 const unsigned short *ent;
244
245 if (fsel >= ARRAYLEN(values_reg))
246 fsel = 2;
247
248 ent = values_reg[fsel];
249
250 /* Set WSPLL input frequency range or SYSCLK divider */
251 uda1380_regs[REG_0] &= ~0xf;
252 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | ent[1]);
253
254 /* Choose 3rd order or 5th order noise shaper */
255 uda1380_regs[REG_MIX_CTL] &= ~MIX_CTL_SEL_NS;
256 uda1380_write_reg(REG_MIX_CTL, uda1380_regs[REG_MIX_CTL] | ent[0]);
257}
258
259/* Initialize UDA1380 codec with default register values (uda1380_defaults) */
260int audiohw_init(void)
261{
262 recgain_mic = 0;
263 recgain_line = 0;
264
265 audiohw_reset();
266
267 if (audiohw_set_regs() == -1)
268 return -1;
269
270 return 0;
271}
272
273void audiohw_postinit(void)
274{
275 /* Sleep a while so the power can stabilize (especially a long
276 delay is needed for the line out connector). */
277 sleep(HZ);
278 /* Power on FSDAC and HP amp. */
279 audiohw_enable_output(true);
280
281 /* UDA1380: Unmute the master channel
282 (DAC should be at zero point now). */
283 audiohw_mute(false);
284}
285
286/* Nice shutdown of UDA1380 codec */
287void audiohw_close(void)
288{
289 /* First enable mute and sleep a while */
290 uda1380_write_reg(REG_MUTE, MUTE_MASTER);
291 sleep(HZ/8);
292
293 /* Then power off the rest of the chip */
294 uda1380_write_reg(REG_PWR, 0);
295 uda1380_write_reg(REG_0, 0); /* Disable codec */
296}
297
298/**
299 * Calling this function enables the UDA1380 to send
300 * sound samples over the I2S bus, which is connected
301 * to the processor's IIS1 interface.
302 *
303 * source_mic: true=record from microphone, false=record from line-in (or radio)
304 */
305void audiohw_enable_recording(bool source_mic)
306{
307 uda1380_regs[REG_0] &= ~(ADC_CLK | DAC_CLK);
308 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | EN_ADC);
309
310 if (source_mic)
311 {
312 /* VGA_GAIN: 0=0 dB, F=30dB */
313 /* Output of left ADC is fed into right bitstream */
314 uda1380_regs[REG_PWR] &= ~(PON_PGAR | PON_ADCR);
315 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_LNA | PON_ADCL);
316 uda1380_regs[REG_ADC] &= ~SKIP_DCFIL;
317 uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC] & VGA_GAIN_MASK)
318 | SEL_LNA | SEL_MIC | EN_DCFIL);
319 uda1380_write_reg(REG_PGA, 0);
320 }
321 else
322 {
323 /* PGA_GAIN: 0=0 dB, F=24dB */
324 uda1380_regs[REG_PWR] &= ~PON_LNA;
325 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_PGAL | PON_ADCL
326 | PON_PGAR | PON_ADCR);
327 uda1380_write_reg(REG_ADC, EN_DCFIL);
328 uda1380_write_reg(REG_PGA, uda1380_regs[REG_PGA] & PGA_GAIN_MASK);
329 }
330
331 sleep(HZ/8);
332
333 uda1380_write_reg(REG_I2S, uda1380_regs[REG_I2S] | I2S_MODE_MASTER);
334 uda1380_write_reg(REG_MIX_CTL, MIX_MODE(1));
335}
336
337/**
338 * Stop sending samples on the I2S bus
339 */
340void audiohw_disable_recording(void)
341{
342 uda1380_write_reg(REG_PGA, MUTE_ADC);
343 sleep(HZ/8);
344
345 uda1380_write_reg(REG_I2S, I2S_IFMT_IIS);
346
347 uda1380_regs[REG_PWR] &= ~(PON_LNA | PON_ADCL | PON_ADCR |
348 PON_PGAL | PON_PGAR);
349 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR]);
350
351 uda1380_regs[REG_0] &= ~EN_ADC;
352 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | ADC_CLK | DAC_CLK);
353
354 uda1380_write_reg(REG_ADC, SKIP_DCFIL);
355}
356
357/**
358 * Set recording gain and volume
359 *
360 * type: params: ranges:
361 * AUDIO_GAIN_MIC: left -128 .. 108 -> -64 .. 54 dB gain
362 * AUDIO_GAIN_LINEIN left & right -128 .. 96 -> -64 .. 48 dB gain
363 *
364 * Note: - For all types the value 0 gives 0 dB gain.
365 * - order of setting both values determines if the small glitch will
366 be a peak or a dip. The small glitch is caused by the time between
367 setting the two gains
368 */
369void audiohw_set_recvol(int left, int right, int type)
370{
371 int left_ag, right_ag;
372
373 switch (type)
374 {
375 case AUDIO_GAIN_MIC:
376 left_ag = MIN(MAX(0, left / 4), 15);
377 left -= left_ag * 4;
378
379 if(left < recgain_mic)
380 {
381 uda1380_write_reg(REG_DEC_VOL, DEC_VOLL(left)
382 | DEC_VOLR(left));
383 uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC]
384 & ~VGA_GAIN_MASK)
385 | VGA_GAIN(left_ag));
386 }
387 else
388 {
389 uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC]
390 & ~VGA_GAIN_MASK)
391 | VGA_GAIN(left_ag));
392 uda1380_write_reg(REG_DEC_VOL, DEC_VOLL(left)
393 | DEC_VOLR(left));
394 }
395 recgain_mic = left;
396 logf("Mic: %dA/%dD", left_ag, left);
397 break;
398
399 case AUDIO_GAIN_LINEIN:
400 left_ag = MIN(MAX(0, left / 6), 8);
401 left -= left_ag * 6;
402 right_ag = MIN(MAX(0, right / 6), 8);
403 right -= right_ag * 6;
404
405 if(left < recgain_line)
406 {
407 /* for this order we can combine both registers,
408 making the glitch even smaller */
409 unsigned char data[5];
410 unsigned short value_dec;
411 unsigned short value_pga;
412 value_dec = DEC_VOLL(left) | DEC_VOLR(right);
413 value_pga = (uda1380_regs[REG_PGA] & ~PGA_GAIN_MASK)
414 | PGA_GAINL(left_ag) | PGA_GAINR(right_ag);
415
416 data[0] = REG_DEC_VOL;
417 data[1] = value_dec >> 8;
418 data[2] = value_dec & 0xff;
419 data[3] = value_pga >> 8;
420 data[4] = value_pga & 0xff;
421
422 if (i2c_write(I2C_IFACE_0, UDA1380_ADDR, data, 5) != 5)
423 {
424 DEBUGF("uda1380 error reg=combi rec gain");
425 }
426 else
427 {
428 uda1380_regs[REG_DEC_VOL] = value_dec;
429 uda1380_regs[REG_PGA] = value_pga;
430 }
431 }
432 else
433 {
434 uda1380_write_reg(REG_PGA, (uda1380_regs[REG_PGA]
435 & ~PGA_GAIN_MASK)
436 | PGA_GAINL(left_ag)
437 | PGA_GAINR(right_ag));
438 uda1380_write_reg(REG_DEC_VOL, DEC_VOLL(left)
439 | DEC_VOLR(right));
440 }
441
442 recgain_line = left;
443 logf("Line L: %dA/%dD", left_ag, left);
444 logf("Line R: %dA/%dD", right_ag, right);
445 break;
446 }
447}
448
449
450/**
451 * Enable or disable recording monitor (so one can listen to the recording)
452 *
453 */
454void audiohw_set_monitor(int enable)
455{
456 if (enable) /* enable channel 2 */
457 uda1380_write_reg(REG_MUTE, uda1380_regs[REG_MUTE] & ~MUTE_CH2);
458 else /* mute channel 2 */
459 uda1380_write_reg(REG_MUTE, uda1380_regs[REG_MUTE] | MUTE_CH2);
460}