diff options
Diffstat (limited to 'firmware/drivers/tlv320.c')
-rw-r--r-- | firmware/drivers/tlv320.c | 119 |
1 files changed, 82 insertions, 37 deletions
diff --git a/firmware/drivers/tlv320.c b/firmware/drivers/tlv320.c index 8ef32919ce..39cd2a5536 100644 --- a/firmware/drivers/tlv320.c +++ b/firmware/drivers/tlv320.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "string.h" | 28 | #include "string.h" |
29 | #include "file.h" | 29 | #include "file.h" |
30 | #include "buffer.h" | 30 | #include "buffer.h" |
31 | #include "audio.h" | ||
31 | 32 | ||
32 | #include "i2c-coldfire.h" | 33 | #include "i2c-coldfire.h" |
33 | #include "tlv320.h" | 34 | #include "tlv320.h" |
@@ -46,14 +47,13 @@ unsigned tlv320_regs[0xf]; | |||
46 | 47 | ||
47 | void tlv320_write_reg(unsigned reg, unsigned value) | 48 | void tlv320_write_reg(unsigned reg, unsigned value) |
48 | { | 49 | { |
49 | unsigned char data[3]; | 50 | unsigned char data[2]; |
50 | 51 | ||
51 | data[0] = TLV320_ADDR; | ||
52 | /* The register address is the high 7 bits and the data the low 9 bits */ | 52 | /* The register address is the high 7 bits and the data the low 9 bits */ |
53 | data[1] = (reg << 1) | ((value >> 8) & 1); | 53 | data[0] = (reg << 1) | ((value >> 8) & 1); |
54 | data[2] = value & 0xff; | 54 | data[1] = value & 0xff; |
55 | 55 | ||
56 | if (i2c_write(1, data, 3) != 3) | 56 | if (i2c_write(I2C_IFACE_0, TLV320_ADDR, data, 2) != 2) |
57 | { | 57 | { |
58 | logf("tlv320 error reg=0x%x", reg); | 58 | logf("tlv320 error reg=0x%x", reg); |
59 | return; | 59 | return; |
@@ -73,15 +73,16 @@ void tlv320_init(void) | |||
73 | 73 | ||
74 | /* Initialize all registers */ | 74 | /* Initialize all registers */ |
75 | 75 | ||
76 | tlv320_write_reg(REG_PC, 0x00); /* All ON */ | 76 | tlv320_write_reg(REG_PC, PC_ADC|PC_MIC|PC_LINE); /* All ON except ADC, MIC and LINE */ |
77 | tlv320_set_linein_vol(0, 0); | 77 | tlv320_set_recvol(0, 0, AUDIO_GAIN_MIC); |
78 | tlv320_set_recvol(0, 0, AUDIO_GAIN_LINEIN); | ||
78 | tlv320_mute(true); | 79 | tlv320_mute(true); |
79 | tlv320_write_reg(REG_AAP, AAP_DAC|AAP_MICM); | 80 | tlv320_write_reg(REG_AAP, AAP_DAC|AAP_MICM); |
80 | tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */ | 81 | tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */ |
81 | tlv320_write_reg(REG_DAIF, DAIF_IWL_16|DAIF_FOR_I2S); | 82 | tlv320_write_reg(REG_DAIF, DAIF_IWL_16|DAIF_FOR_I2S); |
82 | tlv320_set_headphone_vol(0, 0); | 83 | tlv320_set_headphone_vol(0, 0); |
83 | tlv320_write_reg(REG_DIA, DIA_ACT); | 84 | tlv320_write_reg(REG_DIA, DIA_ACT); |
84 | tlv320_write_reg(REG_SRC, (8 << 2)); /* 44.1kHz */ | 85 | tlv320_write_reg(REG_SRC, (1 << 5)); /* 44.1kHz */ |
85 | } | 86 | } |
86 | 87 | ||
87 | /** | 88 | /** |
@@ -114,18 +115,30 @@ void tlv320_set_headphone_vol(int vol_l, int vol_r) | |||
114 | } | 115 | } |
115 | 116 | ||
116 | /** | 117 | /** |
117 | * Sets left and right linein volume (31(max) to 0(muted)) | 118 | * Set recording volume |
119 | * | ||
120 | * Line in : 0 .. 31 => Volume -34.5 .. 12 dB | ||
121 | * Mic (left): 0 .. 1 => Volume 0 .. 20 dB | ||
122 | * | ||
118 | */ | 123 | */ |
119 | void tlv320_set_linein_vol(int vol_l, int vol_r) | 124 | void tlv320_set_recvol(int left, int right, int type) |
120 | { | 125 | { |
121 | unsigned value_l = tlv320_regs[REG_LLIV]; | 126 | if (type == AUDIO_GAIN_MIC) |
122 | unsigned value_r = tlv320_regs[REG_RLIV]; | 127 | { |
123 | 128 | unsigned value_aap = tlv320_regs[REG_AAP]; | |
124 | value_l |= LLIV_LIV(vol_l); | 129 | |
125 | value_r |= RLIV_RIV(vol_r); | 130 | if (left) |
126 | 131 | value_aap |= AAP_MICB; /* Enable mic boost (20dB) */ | |
127 | tlv320_write_reg(REG_LLIV, value_l); | 132 | else |
128 | tlv320_write_reg(REG_RLIV, value_r); | 133 | value_aap &= ~AAP_MICB; |
134 | |||
135 | tlv320_write_reg(REG_AAP, value_aap); | ||
136 | |||
137 | } else if (type == AUDIO_GAIN_LINEIN) | ||
138 | { | ||
139 | tlv320_write_reg(REG_LLIV, LLIV_LIV(left)); | ||
140 | tlv320_write_reg(REG_RLIV, RLIV_RIV(right)); | ||
141 | } | ||
129 | } | 142 | } |
130 | 143 | ||
131 | /** | 144 | /** |
@@ -148,10 +161,11 @@ void tlv320_mute(bool mute) | |||
148 | value_r = RHV_RHV(tlv320.vol_r); | 161 | value_r = RHV_RHV(tlv320.vol_r); |
149 | } | 162 | } |
150 | 163 | ||
151 | tlv320_write_reg(REG_LHV, value_r); | 164 | tlv320_write_reg(REG_LHV, value_l); |
152 | tlv320_write_reg(REG_RHV, value_r); | 165 | tlv320_write_reg(REG_RHV, value_r); |
153 | } | 166 | } |
154 | 167 | ||
168 | /* Nice shutdown of TLV320 codec */ | ||
155 | void tlv320_close() | 169 | void tlv320_close() |
156 | { | 170 | { |
157 | tlv320_write_reg(REG_PC, 0xFF); /* All OFF */ | 171 | tlv320_write_reg(REG_PC, 0xFF); /* All OFF */ |
@@ -159,35 +173,66 @@ void tlv320_close() | |||
159 | 173 | ||
160 | void tlv320_enable_recording(bool source_mic) | 174 | void tlv320_enable_recording(bool source_mic) |
161 | { | 175 | { |
162 | unsigned value_pc = tlv320_regs[REG_PC]; | 176 | unsigned value_daif = tlv320_regs[REG_DAIF]; |
163 | unsigned value_aap = tlv320_regs[REG_AAP]; | 177 | unsigned value_aap, value_pc; |
164 | 178 | ||
165 | /* select source*/ | ||
166 | if (source_mic) | 179 | if (source_mic) |
167 | { | 180 | { |
168 | value_aap &= ~AAP_INSEL; | 181 | /* select mic and enable mic boost (20 dB) */ |
169 | value_pc |= PC_MIC; | 182 | value_aap = AAP_DAC | AAP_INSEL | AAP_MICB; |
183 | value_pc = PC_LINE; /* power down line-in */ | ||
170 | } | 184 | } |
171 | else | 185 | else |
172 | { | 186 | { |
173 | value_aap |= AAP_INSEL; | 187 | value_aap = AAP_DAC | AAP_MICM; |
174 | value_pc |= PC_LINE; | 188 | value_pc = PC_MIC; /* power down mic */ |
175 | } | 189 | } |
176 | 190 | ||
177 | /* poweron adc */ | 191 | tlv320_write_reg(REG_PC, value_pc); |
178 | value_pc |= PC_ADC; | 192 | sleep(HZ/8); |
179 | 193 | ||
180 | tlv320_write_reg(REG_AAP, value_aap); | 194 | tlv320_write_reg(REG_AAP, value_aap); |
181 | tlv320_write_reg(REG_PC, value_pc); | 195 | sleep(HZ/8); |
196 | |||
197 | /* Enable MASTER mode (start sending I2S data to the CPU) */ | ||
198 | value_daif |= DAIF_MS; | ||
199 | tlv320_write_reg(REG_DAIF, value_daif); | ||
182 | } | 200 | } |
183 | 201 | ||
184 | void tlv320_disable_recording() | 202 | void tlv320_disable_recording() |
185 | { | 203 | { |
186 | unsigned value = tlv320_regs[REG_PC]; | 204 | unsigned value_pc = tlv320_regs[REG_PC]; |
187 | 205 | unsigned value_aap = tlv320_regs[REG_AAP]; | |
188 | /* powerdown mic, linein and adc */ | 206 | unsigned value_daif = tlv320_regs[REG_DAIF]; |
189 | value &= ~(PC_MIC | PC_LINE | PC_ADC); | 207 | |
208 | value_daif &= ~DAIF_MS; /* disable MASTER mode */ | ||
209 | tlv320_write_reg(REG_DAIF, value_daif); | ||
210 | |||
211 | value_aap |= AAP_MICM; /* mute mic */ | ||
212 | tlv320_write_reg(REG_PC, value_aap); | ||
213 | |||
214 | value_pc |= (PC_MIC|PC_LINE|PC_ADC); /* power down mic, line-in and adc */ | ||
215 | tlv320_write_reg(REG_PC, value_pc); | ||
216 | |||
217 | sleep(HZ/8); | ||
218 | } | ||
190 | 219 | ||
191 | /* powerdown mic, linein and adc */ | 220 | void tlv320_set_monitor(bool enable) |
192 | tlv320_write_reg(REG_PC, value); | 221 | { |
222 | unsigned value_aap, value_pc; | ||
223 | if (enable) | ||
224 | { | ||
225 | value_aap = AAP_BYPASS | AAP_MICM; | ||
226 | value_pc = (PC_MIC|PC_DAC|PC_ADC); /* power down mic, dac and adc */ | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | value_aap = AAP_DAC | AAP_MICM; | ||
231 | value_pc = (PC_MIC|PC_LINE|PC_ADC); /* power down mic, line-in and adc */ | ||
232 | } | ||
233 | tlv320_write_reg(REG_AAP, value_aap); | ||
234 | tlv320_write_reg(REG_PC, value_pc); | ||
235 | |||
236 | sleep(HZ/8); | ||
193 | } | 237 | } |
238 | |||