Fix condition for compiling audiohw_set_monitor (should fix red)
[kugel-rb.git] / firmware / drivers / audio / tlv320.c
blob6b96ed212fba4605c828f54299ea6d135557c019
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 by Christian Gmeiner
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
22 #include "logf.h"
23 #include "system.h"
24 #include "string.h"
25 #include "audio.h"
27 #if CONFIG_I2C == I2C_COLDFIRE
28 #include "i2c-coldfire.h"
29 #elif CONFIG_I2C == I2C_DM320
30 #include "i2c-dm320.h"
31 #endif
32 #include "audiohw.h"
34 const struct sound_settings_info audiohw_settings[] = {
35 [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -20},
36 /* HAVE_SW_TONE_CONTROLS */
37 [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0},
38 [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0},
39 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
40 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
41 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
42 #ifdef HAVE_RECORDING
43 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23},
44 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23},
45 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 1},
46 #endif
49 /* convert tenth of dB volume (-840..0) to master volume register value */
50 int tenthdb2master(int db)
52 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
53 /* 1111111 == +6dB (0x7f) */
54 /* 1111001 == 0dB (0x79) */
55 /* 0110000 == -73dB (0x30) */
56 /* 0101111 == mute (0x2f) */
58 if (db < VOLUME_MIN) {
59 return 0x2f;
60 } else {
61 return((db/10)+73+0x30);
65 /* local functions and definations */
66 #ifndef CREATIVE_ZVx
67 #define TLV320_ADDR 0x34
68 #else
69 #define TLV320_ADDR 0x1A
70 #endif
72 static struct tlv320_info
74 int vol_l;
75 int vol_r;
76 } tlv320;
78 /* Shadow registers */
79 static unsigned tlv320_regs[0xf];
81 static void tlv320_write_reg(unsigned reg, unsigned value)
83 unsigned char data[2];
85 /* The register address is the high 7 bits and the data the low 9 bits */
86 data[0] = (reg << 1) | ((value >> 8) & 1);
87 data[1] = value;
89 #if CONFIG_I2C == I2C_COLDFIRE
90 if (i2c_write(I2C_IFACE_0, TLV320_ADDR, data, 2) != 2)
91 #elif CONFIG_I2C == I2C_DM320
92 if (i2c_write(TLV320_ADDR, data, 2) != 0)
93 #else
94 #warning Implement tlv320_write_reg()
95 #endif
97 logf("tlv320 error reg=0x%x", reg);
98 return;
101 tlv320_regs[reg] = value;
104 static void audiohw_mute(bool mute)
106 unsigned value_dap = tlv320_regs[REG_DAP];
107 unsigned value_l, value_r;
109 if (mute)
111 value_l = LHV_LHV(HEADPHONE_MUTE);
112 value_r = RHV_RHV(HEADPHONE_MUTE);
113 value_dap |= DAP_DACM;
115 else
117 value_l = LHV_LHV(tlv320.vol_l);
118 value_r = RHV_RHV(tlv320.vol_r);
119 if (value_l > HEADPHONE_MUTE || value_r > HEADPHONE_MUTE)
120 value_dap &= ~DAP_DACM;
123 tlv320_write_reg(REG_LHV, LHV_LZC | value_l);
124 tlv320_write_reg(REG_RHV, RHV_RZC | value_r);
125 tlv320_write_reg(REG_DAP, value_dap);
128 /* public functions */
131 * Init our tlv with default values
133 void audiohw_init(void)
135 logf("TLV320 init");
136 memset(tlv320_regs, 0, sizeof(tlv320_regs));
138 /* Initialize all registers */
140 /* All ON except OUT, ADC, MIC and LINE */
141 tlv320_write_reg(REG_PC, PC_OUT | PC_ADC | PC_MIC | PC_LINE);
142 #ifdef HAVE_RECORDING
143 audiohw_set_recvol(0, 0, AUDIO_GAIN_MIC);
144 audiohw_set_recvol(0, 0, AUDIO_GAIN_LINEIN);
145 #endif
146 audiohw_mute(true);
147 tlv320_write_reg(REG_AAP, AAP_DAC | AAP_MICM);
148 tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */
149 #ifndef CREATIVE_ZVx
150 tlv320_write_reg(REG_DAIF, DAIF_IWL_16 | DAIF_FOR_I2S);
151 #else
152 tlv320_write_reg(REG_DAIF, DAIF_IWL_32 | DAIF_FOR_DSP);
153 #endif
154 tlv320_write_reg(REG_DIA, DIA_ACT);
155 audiohw_set_frequency(-1); /* default */
159 * Switch outputs ON
161 void audiohw_postinit(void)
163 /* All ON except ADC, MIC and LINE */
164 sleep(HZ);
165 tlv320_write_reg(REG_PC, PC_ADC | PC_MIC | PC_LINE);
166 sleep(HZ/4);
167 audiohw_mute(false);
171 * Sets internal sample rate for DAC and ADC relative to MCLK
172 * Selection for frequency:
173 * Fs: tlv: with:
174 * 11025: 0 = MCLK/2 MCLK/2 SCLK, LRCK: Audio Clk / 16
175 * 22050: 0 = MCLK/2 MCLK SCLK, LRCK: Audio Clk / 8
176 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default)
177 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2
179 void audiohw_set_frequency(int fsel)
181 /* All rates available for 11.2896MHz besides 8.021 */
182 static const unsigned char values_src[HW_NUM_FREQ] =
184 HW_HAVE_11_([HW_FREQ_11] = (0x8 << 2) | SRC_CLKIN,)
185 HW_HAVE_22_([HW_FREQ_22] = (0x8 << 2) | SRC_CLKIN,)
186 HW_HAVE_44_([HW_FREQ_44] = (0x8 << 2),)
187 HW_HAVE_88_([HW_FREQ_88] = (0xf << 2),)
190 unsigned value_dap, value_pc;
192 if ((unsigned)fsel >= HW_NUM_FREQ)
193 fsel = HW_FREQ_DEFAULT;
195 /* Temporarily turn off the DAC and ADC before switching sample
196 rates or they don't choose their filters correctly */
197 value_dap = tlv320_regs[REG_DAP];
198 value_pc = tlv320_regs[REG_PC];
200 tlv320_write_reg(REG_DAP, value_dap | DAP_DACM);
201 tlv320_write_reg(REG_PC, value_pc | PC_DAC | PC_ADC);
202 tlv320_write_reg(REG_SRC, values_src[fsel]);
203 tlv320_write_reg(REG_PC, value_pc | PC_DAC);
204 tlv320_write_reg(REG_PC, value_pc);
205 tlv320_write_reg(REG_DAP, value_dap);
209 * Sets left and right headphone volume
211 * Left & Right: 48 .. 121 .. 127 => Volume -73dB (mute) .. +0 dB .. +6 dB
213 void audiohw_set_headphone_vol(int vol_l, int vol_r)
215 unsigned value_dap = tlv320_regs[REG_DAP];
216 unsigned value_dap_last = value_dap;
217 unsigned value_l = LHV_LHV(vol_l);
218 unsigned value_r = RHV_RHV(vol_r);
220 /* keep track of current setting */
221 tlv320.vol_l = vol_l;
222 tlv320.vol_r = vol_r;
224 if (value_l > HEADPHONE_MUTE || value_r > HEADPHONE_MUTE)
225 value_dap &= ~DAP_DACM;
226 else
227 value_dap |= DAP_DACM;
229 /* update */
230 tlv320_write_reg(REG_LHV, LHV_LZC | value_l);
231 tlv320_write_reg(REG_RHV, RHV_RZC | value_r);
232 if (value_dap != value_dap_last)
233 tlv320_write_reg(REG_DAP, value_dap);
237 * Set recording volume
239 * Line in : 0 .. 31 => Volume -34.5 .. +12 dB
240 * Mic (left): 0 .. 1 => Volume +0, +20 dB
243 #ifdef HAVE_RECORDING
244 void audiohw_set_recvol(int left, int right, int type)
246 if (type == AUDIO_GAIN_MIC)
248 unsigned value_aap = tlv320_regs[REG_AAP];
250 if (left)
251 value_aap |= AAP_MICB; /* Enable mic boost (20dB) */
252 else
253 value_aap &= ~AAP_MICB;
255 tlv320_write_reg(REG_AAP, value_aap);
257 else if (type == AUDIO_GAIN_LINEIN)
259 tlv320_write_reg(REG_LLIV, LLIV_LIV(left));
260 tlv320_write_reg(REG_RLIV, RLIV_RIV(right));
263 #endif
265 /* Nice shutdown of TLV320 codec */
266 void audiohw_close(void)
268 audiohw_mute(true);
269 sleep(HZ/8);
271 tlv320_write_reg(REG_PC, PC_OFF | PC_CLK | PC_OSC | PC_OUT |
272 PC_DAC | PC_ADC | PC_MIC | PC_LINE); /* All OFF */
275 #ifdef HAVE_RECORDING
276 void audiohw_enable_recording(bool source_mic)
278 unsigned value_aap, value_pc;
280 if (source_mic)
282 /* select MIC and enable mic boost (20 dB) */
283 value_aap = AAP_DAC | AAP_INSEL | AAP_MICB;
284 value_pc = PC_LINE; /* power down LINE */
286 else
288 value_aap = AAP_DAC | AAP_MICM;
289 value_pc = PC_MIC; /* power down MIC */
292 tlv320_write_reg(REG_PC, value_pc);
293 tlv320_write_reg(REG_AAP, value_aap);
296 void audiohw_disable_recording(void)
298 unsigned value_pc = tlv320_regs[REG_PC];
299 unsigned value_aap = tlv320_regs[REG_AAP];
301 value_aap |= AAP_MICM; /* mute MIC */
302 tlv320_write_reg(REG_PC, value_aap);
304 value_pc |= PC_ADC | PC_MIC | PC_LINE; /* ADC, MIC and LINE off */
305 tlv320_write_reg(REG_PC, value_pc);
308 void audiohw_set_monitor(bool enable)
310 unsigned value_aap, value_pc;
312 if (enable)
314 /* Keep DAC on to allow mixing of voice with analog audio */
315 value_aap = AAP_DAC | AAP_BYPASS | AAP_MICM;
316 value_pc = PC_ADC | PC_MIC; /* ADC and MIC off */
318 else
320 value_aap = AAP_DAC | AAP_MICM;
321 value_pc = PC_ADC | PC_MIC | PC_LINE; /* ADC, MIC and LINE off */
324 tlv320_write_reg(REG_AAP, value_aap);
325 tlv320_write_reg(REG_PC, value_pc);
327 #endif /* HAVE_RECORDING */