summaryrefslogtreecommitdiff
path: root/firmware/drivers/tlv320.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/tlv320.c')
-rw-r--r--firmware/drivers/tlv320.c119
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
47void tlv320_write_reg(unsigned reg, unsigned value) 48void 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 */
119void tlv320_set_linein_vol(int vol_l, int vol_r) 124void 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 */
155void tlv320_close() 169void 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
160void tlv320_enable_recording(bool source_mic) 174void 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
184void tlv320_disable_recording() 202void 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 */ 220void 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