diff options
author | Marcoen Hirschberg <marcoen@gmail.com> | 2007-04-19 10:46:50 +0000 |
---|---|---|
committer | Marcoen Hirschberg <marcoen@gmail.com> | 2007-04-19 10:46:50 +0000 |
commit | 15dfe87f9606a191707d5c7b3b33b21963510f53 (patch) | |
tree | 5c31520b84dc60aff6997eac6a7e8b4b3ec1127e /firmware/drivers/audio/uda1380.c | |
parent | f725ef12565a65d46ff2f9bd34eb3e19da7b763e (diff) | |
download | rockbox-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.c | 460 |
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 */ | ||
39 | int 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 */ | ||
52 | int 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 | |||
68 | int uda1380_write_reg(unsigned char reg, unsigned short value); | ||
69 | unsigned short uda1380_regs[0x30]; | ||
70 | short recgain_mic; | ||
71 | short recgain_line; | ||
72 | |||
73 | /* Definition of a playback configuration to start with */ | ||
74 | |||
75 | #define NUM_DEFAULT_REGS 13 | ||
76 | unsigned 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 */ | ||
104 | int 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 | */ | ||
126 | int 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 | */ | ||
135 | int 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 | */ | ||
144 | void 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 | */ | ||
153 | void 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 | */ | ||
163 | int 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 */ | ||
176 | int 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 */ | ||
195 | void 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 | |||
205 | void 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 | */ | ||
232 | void 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) */ | ||
260 | int 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 | |||
273 | void 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 */ | ||
287 | void 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 | */ | ||
305 | void 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 | */ | ||
340 | void 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 | */ | ||
369 | void 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 | */ | ||
454 | void 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 | } | ||