diff options
Diffstat (limited to 'firmware/drivers/audio')
-rw-r--r-- | firmware/drivers/audio/wm8751.c | 576 |
1 files changed, 299 insertions, 277 deletions
diff --git a/firmware/drivers/audio/wm8751.c b/firmware/drivers/audio/wm8751.c index a0e42a9392..b9d41c7b32 100644 --- a/firmware/drivers/audio/wm8751.c +++ b/firmware/drivers/audio/wm8751.c | |||
@@ -42,34 +42,96 @@ const struct sound_settings_info audiohw_settings[] = { | |||
42 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, | 42 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, |
43 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, | 43 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, |
44 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, | 44 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, |
45 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
46 | [SOUND_DEPTH_3D] = {"", 0, 1, 0, 15, 0}, | ||
47 | #endif | ||
48 | #ifdef HAVE_RECORDING | 45 | #ifdef HAVE_RECORDING |
49 | [SOUND_LEFT_GAIN] = {"dB", 1, 1,-172, 300, 0}, | 46 | [SOUND_LEFT_GAIN] = {"dB", 1, 50,-970, 300, 0}, |
50 | [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-172, 300, 0}, | 47 | [SOUND_RIGHT_GAIN] = {"dB", 1, 50,-970, 300, 0}, |
51 | [SOUND_MIC_GAIN] = {"dB", 1, 1,-172, 300, 0}, | 48 | [SOUND_MIC_GAIN] = {"dB", 1, 50,-970, 300, 0}, |
49 | #endif | ||
50 | #ifdef AUDIOHW_HAVE_BASS_CUTOFF | ||
51 | [SOUND_BASS_CUTOFF] = {"Hz", 0, 70, 130, 200, 200}, | ||
52 | #endif | ||
53 | #ifdef AUDIOHW_HAVE_TREBLE_CUTOFF | ||
54 | [SOUND_TREBLE_CUTOFF] = {"kHz",0, 4, 4, 8, 4}, | ||
55 | #endif | ||
56 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
57 | [SOUND_DEPTH_3D] = {"", 0, 1, -1, 15, -1}, | ||
52 | #endif | 58 | #endif |
53 | }; | 59 | }; |
54 | 60 | ||
55 | /* Flags used in combination with settings */ | 61 | static int prescaler = 0; |
56 | 62 | ||
57 | /* use zero crossing to reduce clicks during volume changes */ | 63 | static uint16_t wmcodec_regs[WM_NUM_REGS] = |
58 | #define LOUT1_BITS (LOUT1_LO1ZC) | 64 | { |
59 | /* latch left volume first then update left+right together */ | 65 | [0 ... WM_NUM_REGS-1] = 0x200, /* set invalid data in gaps */ |
60 | #define ROUT1_BITS (ROUT1_RO1ZC | ROUT1_RO1VU) | 66 | #ifdef HAVE_WM8750 |
61 | #define LOUT2_BITS (LOUT2_LO2ZC) | 67 | [LINVOL] = 0x097, |
62 | #define ROUT2_BITS (ROUT2_RO2ZC | ROUT2_RO2VU) | 68 | [RINVOL] = 0x097, |
63 | /* We use linear bass control with 200 Hz cutoff */ | 69 | #endif |
64 | #ifdef USE_ADAPTIVE_BASE | 70 | [LOUT1] = 0x079, |
65 | #define BASSCTRL_BITS (BASSCTRL_BC | BASSCTRL_BB) | 71 | [ROUT1] = 0x079, |
66 | #else | 72 | [DACCTRL] = 0x008, |
67 | #define BASSCTRL_BITS (BASSCTRL_BC) | 73 | [AINTFCE] = 0x00a, |
74 | [CLOCKING] = 0x000, | ||
75 | [LEFTGAIN] = 0x0ff, | ||
76 | [RIGHTGAIN] = 0x0ff, | ||
77 | [BASSCTRL] = 0x00f, | ||
78 | [TREBCTRL] = 0x00f, | ||
79 | /* [RESET] */ | ||
80 | #ifdef HAVE_WM8750 | ||
81 | [ENHANCE_3D] = 0x000, | ||
82 | [ALC1] = 0x07b, | ||
83 | [ALC2] = 0x000, | ||
84 | [ALC3] = 0x032, | ||
85 | [NGAT] = 0x000, | ||
86 | [LADCVOL] = 0x0c3, | ||
87 | [RADCVOL] = 0x0c3, | ||
88 | #endif | ||
89 | [ADDITIONAL1] = 0x0c0, | ||
90 | [ADDITIONAL2] = 0x000, | ||
91 | [PWRMGMT1] = 0x000, | ||
92 | [PWRMGMT2] = 0x000, | ||
93 | [ADDITIONAL3] = 0x000, | ||
94 | #ifdef HAVE_WM8750 | ||
95 | [ADCIM] = 0x000, | ||
96 | [ADCL] = 0x000, | ||
97 | [ADCR] = 0x000, | ||
68 | #endif | 98 | #endif |
69 | /* We use linear treble control with 4 kHz cutoff */ | 99 | [LEFTMIX1] = 0x050, |
70 | #define TREBCTRL_BITS (TREBCTRL_TC) | 100 | [LEFTMIX2] = 0x050, |
101 | [RIGHTMIX1] = 0x050, | ||
102 | [RIGHTMIX2] = 0x050, | ||
103 | [MONOMIX1] = 0x050, | ||
104 | [MONOMIX2] = 0x050, | ||
105 | [LOUT2] = 0x079, | ||
106 | [ROUT2] = 0x079, | ||
107 | [MONOOUT] = 0x079 | ||
108 | }; | ||
71 | 109 | ||
72 | static int prescaler = 0; | 110 | static void wmcodec_set_reg(unsigned int reg, unsigned int val) |
111 | { | ||
112 | if (reg >= WM_NUM_REGS || (wmcodec_regs[reg] & 0x200)) | ||
113 | /* invalid register */ | ||
114 | return; | ||
115 | |||
116 | wmcodec_regs[reg] = val & 0x1ff; | ||
117 | wmcodec_write(reg, wmcodec_regs[reg]); | ||
118 | } | ||
119 | |||
120 | static void wmcodec_set_bits(unsigned int reg, unsigned int bits) | ||
121 | { | ||
122 | wmcodec_set_reg(reg, wmcodec_regs[reg] | bits); | ||
123 | } | ||
124 | |||
125 | static void wmcodec_clear_bits(unsigned int reg, unsigned int bits) | ||
126 | { | ||
127 | wmcodec_set_reg(reg, wmcodec_regs[reg] & ~bits); | ||
128 | } | ||
129 | |||
130 | static void wmcodec_set_masked(unsigned int reg, unsigned int val, | ||
131 | unsigned int mask ) | ||
132 | { | ||
133 | wmcodec_set_reg(reg, (wmcodec_regs[reg] & ~mask) | val); | ||
134 | } | ||
73 | 135 | ||
74 | /* convert tenth of dB volume (-730..60) to master volume register value */ | 136 | /* convert tenth of dB volume (-730..60) to master volume register value */ |
75 | int tenthdb2master(int db) | 137 | int tenthdb2master(int db) |
@@ -98,51 +160,6 @@ static int tone_tenthdb2hw(int value) | |||
98 | return value; | 160 | return value; |
99 | } | 161 | } |
100 | 162 | ||
101 | #if 0 | ||
102 | static int alc_tenthdb2hw(int value) | ||
103 | { | ||
104 | /* -28.5dB - -6dB step 1.5dB - translate -285 - -60 step 15 | ||
105 | to 0 - 15 step 1 | ||
106 | */ | ||
107 | |||
108 | value = 15 - (value + 60)/15; | ||
109 | } | ||
110 | |||
111 | |||
112 | static int alc_hldus2hw(unsigned int value) | ||
113 | { | ||
114 | /* 0000 - 0us | ||
115 | * 0001 - 2670us | ||
116 | * 0010 - 5330us | ||
117 | * | ||
118 | * 1111 - 43691000us | ||
119 | */ | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int alc_dcyms2hw(int value) | ||
124 | { | ||
125 | /* 0000 - 24ms | ||
126 | * 0001 - 48ms | ||
127 | * 0010 - 96ms | ||
128 | * | ||
129 | * 1010 or higher 24580ms | ||
130 | */ | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int alc_atkms2hw(int value) | ||
135 | { | ||
136 | /* 0000 - 6ms | ||
137 | * 0001 - 12ms | ||
138 | * 0010 - 24ms | ||
139 | * | ||
140 | * 1010 or higher 6140ms | ||
141 | */ | ||
142 | return 0; | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | #ifdef USE_ADAPTIVE_BASS | 163 | #ifdef USE_ADAPTIVE_BASS |
147 | static int adaptivebass2hw(int value) | 164 | static int adaptivebass2hw(int value) |
148 | { | 165 | { |
@@ -153,31 +170,44 @@ static int adaptivebass2hw(int value) | |||
153 | } | 170 | } |
154 | #endif | 171 | #endif |
155 | 172 | ||
156 | #if defined(HAVE_WM8750) | 173 | #ifdef AUDIOHW_HAVE_BASS_CUTOFF |
157 | #if 0 | 174 | void audiohw_set_bass_cutoff(int val) |
158 | static int ngath_tenthdb2hw(int value) | ||
159 | { | 175 | { |
160 | /* -76.5dB - -30dB in 1.5db steps -765 - -300 in 15 steps */ | 176 | if ( val == 130 ) |
161 | value = 31 - (value + 300)/15; | 177 | wmcodec_clear_bits(BASSCTRL, BASSCTRL_BC); |
162 | return value; | 178 | else |
179 | wmcodec_set_bits(BASSCTRL, BASSCTRL_BC); | ||
180 | |||
181 | } | ||
182 | #endif | ||
183 | |||
184 | #ifdef AUDIOHW_HAVE_TREBLE_CUTOFF | ||
185 | void audiohw_set_treble_cutoff(int val) | ||
186 | { | ||
187 | if ( val == 8 ) | ||
188 | wmcodec_clear_bits(TREBCTRL, TREBCTRL_TC); | ||
189 | else | ||
190 | wmcodec_set_bits(TREBCTRL, TREBCTRL_TC); | ||
163 | } | 191 | } |
164 | #endif | 192 | #endif |
193 | |||
194 | #if defined(HAVE_WM8750) && defined(HAVE_RECORDING) | ||
165 | static int recvol2hw(int value) | 195 | static int recvol2hw(int value) |
166 | { | 196 | { |
167 | /* convert tenth of dB of input volume (-172...300) to input register value */ | 197 | /* -970...300 to input register value */ |
168 | /* +30dB to -17.25 0.75dB step 6 bits */ | ||
169 | /* 111111 == +30dB (0x3f) */ | ||
170 | /* 010111 == 0dB (0x17) */ | ||
171 | /* 000000 == -17.25dB */ | ||
172 | 198 | ||
173 | return ((4*(value))/30 + 0x17); | 199 | return ((2*value)/10 + 0xc3); |
174 | } | 200 | } |
175 | #endif | 201 | #endif |
202 | |||
176 | static void audiohw_mute(bool mute) | 203 | static void audiohw_mute(bool mute) |
177 | { | 204 | { |
178 | /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */ | 205 | /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */ |
179 | /* Unmute: Set DACMU = 0 to soft-un-mute the audio DACs. */ | 206 | /* Unmute: Set DACMU = 0 to soft-un-mute the audio DACs. */ |
180 | wmcodec_write(DACCTRL, mute ? DACCTRL_DACMU : 0); | 207 | if (mute) |
208 | wmcodec_set_bits(DACCTRL,DACCTRL_DACMU); | ||
209 | else | ||
210 | wmcodec_clear_bits(DACCTRL,DACCTRL_DACMU); | ||
181 | } | 211 | } |
182 | 212 | ||
183 | /* Reset and power up the WM8751 */ | 213 | /* Reset and power up the WM8751 */ |
@@ -210,14 +240,14 @@ void audiohw_preinit(void) | |||
210 | wmcodec_write(RESET, RESET_RESET); /*Reset*/ | 240 | wmcodec_write(RESET, RESET_RESET); /*Reset*/ |
211 | 241 | ||
212 | /* 2. Enable Vmid and VREF. */ | 242 | /* 2. Enable Vmid and VREF. */ |
213 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_5K); | 243 | wmcodec_set_bits(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_5K); |
214 | 244 | ||
215 | #ifdef CODEC_SLAVE | 245 | #ifdef CODEC_SLAVE |
216 | wmcodec_write(AINTFCE,AINTFCE_WL_16|AINTFCE_FORMAT_I2S); | 246 | wmcodec_set_bits(AINTFCE,AINTFCE_WL_16|AINTFCE_FORMAT_I2S); |
217 | #else | 247 | #else |
218 | /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ | 248 | /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ |
219 | /* IWL=00(16 bit) FORMAT=10(I2S format) */ | 249 | /* IWL=00(16 bit) FORMAT=10(I2S format) */ |
220 | wmcodec_write(AINTFCE, AINTFCE_MS | AINTFCE_WL_16 | | 250 | wmcodec_set_bits(AINTFCE, AINTFCE_MS | AINTFCE_WL_16 | |
221 | AINTFCE_FORMAT_I2S); | 251 | AINTFCE_FORMAT_I2S); |
222 | #endif | 252 | #endif |
223 | /* Set default samplerate */ | 253 | /* Set default samplerate */ |
@@ -231,50 +261,62 @@ void audiohw_postinit(void) | |||
231 | /* From app notes: allow Vref to stabilize to reduce clicks */ | 261 | /* From app notes: allow Vref to stabilize to reduce clicks */ |
232 | sleep(HZ); | 262 | sleep(HZ); |
233 | 263 | ||
264 | |||
265 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
266 | wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_MODE3D_PLAYBACK); | ||
267 | #endif | ||
268 | |||
269 | #ifdef USE_ADAPTIVE_BASS | ||
270 | wmcodec_set_bits(BASSCTRL, BASSCTRL_BB); | ||
271 | #endif | ||
272 | |||
234 | /* 3. Enable DACs as required. */ | 273 | /* 3. Enable DACs as required. */ |
235 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR); | 274 | wmcodec_set_bits(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR); |
236 | 275 | ||
237 | /* 4. Enable line and / or headphone output buffers as required. */ | 276 | /* 4. Enable line and / or headphone output buffers as required. */ |
238 | #if defined(MROBE_100) || defined(MPIO_HD200) | 277 | #if defined(MROBE_100) || defined(MPIO_HD200) |
239 | /* fix for high pitch noise after power-up on HD200 | 278 | /* power-up output stage */ |
240 | * it is *NOT* required step according to the | 279 | wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); |
241 | * Datasheet for WM8750L but real life is different :-) | ||
242 | */ | ||
243 | wmcodec_write(LOUT1, LOUT1_BITS); | ||
244 | wmcodec_write(ROUT1, ROUT1_BITS); | ||
245 | |||
246 | /* power-up output stage */ | ||
247 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | ||
248 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | ||
249 | #else | 280 | #else |
250 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 281 | wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1 | |
251 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1 | PWRMGMT2_LOUT2 | | 282 | PWRMGMT2_LOUT2 | PWRMGMT2_ROUT2); |
252 | PWRMGMT2_ROUT2); | ||
253 | #endif | 283 | #endif |
254 | 284 | ||
255 | /* Full -0dB on the DACS */ | 285 | /* Full -0dB on the DACS */ |
256 | wmcodec_write(LEFTGAIN, 0xff); | 286 | wmcodec_set_bits(LEFTGAIN, 0xff); |
257 | wmcodec_write(RIGHTGAIN, RIGHTGAIN_RDVU | 0xff); | 287 | wmcodec_set_bits(RIGHTGAIN, RIGHTGAIN_RDVU | 0xff); |
258 | 288 | ||
259 | wmcodec_write(ADDITIONAL1, ADDITIONAL1_TSDEN | ADDITIONAL1_TOEN | | 289 | /* Enable Thermal shutdown, Timeout when zero-crossing in use, |
290 | * set analog bias for 3.3V, monomix to DACR | ||
291 | */ | ||
292 | wmcodec_set_reg(ADDITIONAL1, ADDITIONAL1_TSDEN | ADDITIONAL1_TOEN | | ||
260 | ADDITIONAL1_DMONOMIX_LLRR | ADDITIONAL1_VSEL_DEFAULT); | 293 | ADDITIONAL1_DMONOMIX_LLRR | ADDITIONAL1_VSEL_DEFAULT); |
261 | 294 | ||
262 | wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO | LEFTMIX1_LI2LO_DEFAULT); | 295 | |
263 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO | RIGHTMIX2_RI2RO_DEFAULT); | 296 | /* Enable zero-crossing in out stage */ |
297 | wmcodec_set_bits(LOUT1, LOUT1_LO1ZC); | ||
298 | wmcodec_set_bits(ROUT1, ROUT1_RO1ZC); | ||
299 | wmcodec_set_bits(LOUT2, LOUT2_LO2ZC); | ||
300 | wmcodec_set_bits(ROUT2, ROUT2_RO2ZC); | ||
301 | |||
302 | /* route signal from DAC to mixers */ | ||
303 | wmcodec_set_bits(LEFTMIX1, LEFTMIX1_LD2LO); | ||
304 | wmcodec_set_bits(RIGHTMIX2, RIGHTMIX2_RD2RO); | ||
264 | 305 | ||
265 | #ifdef TOSHIBA_GIGABEAT_F | 306 | #ifdef TOSHIBA_GIGABEAT_F |
266 | #ifdef HAVE_HARDWARE_BEEP | 307 | #ifdef HAVE_HARDWARE_BEEP |
267 | /* Single-ended mono input */ | 308 | /* Single-ended mono input */ |
268 | wmcodec_write(MONOMIX1, 0); | 309 | wmcodec_set_reg(MONOMIX1, 0x00); |
269 | 310 | ||
270 | /* Route mono input to both outputs at 0dB */ | 311 | /* Route mono input to both outputs at 0dB */ |
271 | wmcodec_write(LEFTMIX2, LEFTMIX2_MI2LO | LEFTMIX2_MI2LOVOL(2)); | 312 | wmcodec_set_reg(LEFTMIX2, LEFTMIX2_MI2LO | LEFTMIX2_MI2LOVOL(2)); |
272 | wmcodec_write(RIGHTMIX1, RIGHTMIX1_MI2RO | RIGHTMIX1_MI2ROVOL(2)); | 313 | wmcodec_set_reg(RIGHTMIX1, RIGHTMIX1_MI2RO | RIGHTMIX1_MI2ROVOL(2)); |
273 | #endif | 314 | #endif |
274 | #endif | 315 | #endif |
275 | 316 | ||
276 | /* lower power consumption */ | 317 | /* lower power consumption */ |
277 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | 318 | wmcodec_set_masked(PWRMGMT1, PWRMGMT1_VMIDSEL_50K, |
319 | PWRMGMT1_VMIDSEL_MASK); | ||
278 | 320 | ||
279 | audiohw_mute(false); | 321 | audiohw_mute(false); |
280 | 322 | ||
@@ -298,41 +340,45 @@ void audiohw_set_master_vol(int vol_l, int vol_r) | |||
298 | /* 0110000 == -73dB */ | 340 | /* 0110000 == -73dB */ |
299 | /* 0101111 == mute (0x2f) */ | 341 | /* 0101111 == mute (0x2f) */ |
300 | 342 | ||
301 | wmcodec_write(LOUT1, LOUT1_BITS | LOUT1_LOUT1VOL(vol_l)); | 343 | wmcodec_set_masked(LOUT1, LOUT1_LOUT1VOL(vol_l), |
302 | wmcodec_write(ROUT1, ROUT1_BITS | ROUT1_ROUT1VOL(vol_r)); | 344 | LOUT1_LOUT1VOL_MASK); |
345 | wmcodec_set_masked(ROUT1, ROUT1_RO1VU | ROUT1_ROUT1VOL(vol_r), | ||
346 | ROUT1_ROUT1VOL_MASK); | ||
303 | } | 347 | } |
304 | 348 | ||
305 | #ifndef MROBE_100 | 349 | #ifdef TOSHIBA_GIGABEAT_F |
306 | void audiohw_set_lineout_vol(int vol_l, int vol_r) | 350 | void audiohw_set_lineout_vol(int vol_l, int vol_r) |
307 | { | 351 | { |
308 | wmcodec_write(LOUT2, LOUT2_BITS | LOUT2_LOUT2VOL(vol_l)); | 352 | wmcodec_set_masked(LOUT2, LOUT2_LOUT2VOL(vol_l), |
309 | wmcodec_write(ROUT2, ROUT2_BITS | ROUT2_ROUT2VOL(vol_r)); | 353 | LOUT2_LOUT2VOL_MASK); |
354 | wmcodec_set_masked(ROUT2, ROUT2_RO2VU | ROUT2_ROUT2VOL(vol_r), | ||
355 | ROUT2_ROUT2VOL_MASK); | ||
310 | } | 356 | } |
311 | #endif | 357 | #endif |
312 | 358 | ||
313 | void audiohw_set_bass(int value) | 359 | void audiohw_set_bass(int value) |
314 | { | 360 | { |
315 | wmcodec_write(BASSCTRL, BASSCTRL_BITS | | 361 | wmcodec_set_masked(BASSCTRL, |
316 | 362 | ||
317 | #ifdef USE_ADAPTIVE_BASS | 363 | #ifdef USE_ADAPTIVE_BASS |
318 | BASSCTRL_BASS(adaptivebass2hw(value))); | 364 | BASSCTRL_BASS(adaptivebass2hw(value)),BASSCTRL_BASS_MASK); |
319 | #else | 365 | #else |
320 | BASSCTRL_BASS(tone_tenthdb2hw(value))); | 366 | BASSCTRL_BASS(tone_tenthdb2hw(value)),BASSCTRL_BASS_MASK); |
321 | #endif | 367 | #endif |
322 | } | 368 | } |
323 | 369 | ||
324 | void audiohw_set_treble(int value) | 370 | void audiohw_set_treble(int value) |
325 | { | 371 | { |
326 | wmcodec_write(TREBCTRL, TREBCTRL_BITS | | 372 | wmcodec_set_masked(TREBCTRL, TREBCTRL_TREB(tone_tenthdb2hw(value)), |
327 | TREBCTRL_TREB(tone_tenthdb2hw(value))); | 373 | TREBCTRL_TREB_MASK); |
328 | } | 374 | } |
329 | 375 | ||
330 | void audiohw_set_prescaler(int value) | 376 | void audiohw_set_prescaler(int value) |
331 | { | 377 | { |
332 | prescaler = 3 * value / 15; | 378 | prescaler = 3 * value / 15; |
333 | wmcodec_write(LEFTGAIN, 0xff - (prescaler & LEFTGAIN_LDACVOL)); | 379 | wmcodec_set_reg(LEFTGAIN, 0xff - (prescaler & LEFTGAIN_LDACVOL)); |
334 | wmcodec_write(RIGHTGAIN, RIGHTGAIN_RDVU | | 380 | wmcodec_set_reg(RIGHTGAIN, RIGHTGAIN_RDVU | |
335 | (0xff - (prescaler & RIGHTGAIN_RDACVOL))); | 381 | (0xff - (prescaler & RIGHTGAIN_RDACVOL))); |
336 | } | 382 | } |
337 | 383 | ||
338 | /* Nice shutdown of WM8751 codec */ | 384 | /* Nice shutdown of WM8751 codec */ |
@@ -347,10 +393,10 @@ void audiohw_close(void) | |||
347 | #endif | 393 | #endif |
348 | 394 | ||
349 | /* 2. Disable all output buffers. */ | 395 | /* 2. Disable all output buffers. */ |
350 | wmcodec_write(PWRMGMT2, 0x0); | 396 | wmcodec_set_reg(PWRMGMT2, 0x0); |
351 | 397 | ||
352 | /* 3. Switch off the power supplies. */ | 398 | /* 3. Switch off the power supplies. */ |
353 | wmcodec_write(PWRMGMT1, 0x0); | 399 | wmcodec_set_reg(PWRMGMT1, 0x0); |
354 | } | 400 | } |
355 | 401 | ||
356 | /* According to datasheet of WM8750 | 402 | /* According to datasheet of WM8750 |
@@ -370,26 +416,31 @@ void audiohw_set_frequency(int fsel) | |||
370 | if ((unsigned)fsel >= HW_NUM_FREQ) | 416 | if ((unsigned)fsel >= HW_NUM_FREQ) |
371 | fsel = HW_FREQ_DEFAULT; | 417 | fsel = HW_FREQ_DEFAULT; |
372 | 418 | ||
373 | wmcodec_write(CLOCKING, srctrl_table[fsel]); | 419 | wmcodec_set_reg(CLOCKING, srctrl_table[fsel]); |
374 | } | 420 | } |
375 | 421 | ||
376 | #if defined(HAVE_WM8750) | 422 | #ifdef HAVE_WM8750 |
377 | #ifdef AUDIOHW_HAVE_DEPTH_3D | 423 | #ifdef AUDIOHW_HAVE_DEPTH_3D |
378 | /* Set the depth of the 3D effect */ | 424 | /* Set the depth of the 3D effect */ |
379 | void audiohw_set_depth_3d(int val) | 425 | void audiohw_set_depth_3d(int val) |
380 | { | 426 | { |
381 | if (val) | 427 | if (val >= 0) |
382 | wmcodec_write(ENHANCE_3D, | 428 | { |
383 | ENHANCE_3D_MODE3D_PLAYBACK | ENHANCE_3D_DEPTH(val) | | 429 | if ( !(wmcodec_regs[ENHANCE_3D] & ENHANCE_3D_3DEN) ) |
384 | ENHANCE_3D_3DEN); | 430 | wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_3DEN); |
431 | |||
432 | wmcodec_set_masked(ENHANCE_3D, ENHANCE_3D_DEPTH(val), | ||
433 | ENHANCE_3D_DEPTH_MASK); | ||
434 | } | ||
385 | else | 435 | else |
386 | wmcodec_write(ENHANCE_3D,ENHANCE_3D_MODE3D_PLAYBACK); | 436 | { |
437 | wmcodec_clear_bits(ENHANCE_3D, ENHANCE_3D_3DEN); | ||
438 | } | ||
387 | } | 439 | } |
388 | #endif | 440 | #endif |
389 | 441 | ||
390 | #ifdef HAVE_RECORDING | 442 | #ifdef HAVE_RECORDING |
391 | #if 0 | 443 | static void audiohw_set_ngat(int ngath, int type, bool enable) |
392 | void audiohw_set_ngath(int ngath, int type, bool enable) | ||
393 | { | 444 | { |
394 | /* This function controls Noise gate function | 445 | /* This function controls Noise gate function |
395 | * of the codec. This can only run in conjunction | 446 | * of the codec. This can only run in conjunction |
@@ -397,63 +448,33 @@ void audiohw_set_ngath(int ngath, int type, bool enable) | |||
397 | */ | 448 | */ |
398 | 449 | ||
399 | if(enable) | 450 | if(enable) |
400 | wmcodec_write(NGAT, NGAT_NGG(type)|NGAT_NGTH(ngath)|NGAT_NGAT); | 451 | wmcodec_set_reg(NGAT, NGAT_NGG(type) | |
452 | NGAT_NGTH(ngath) | NGAT_NGAT); | ||
401 | else | 453 | else |
402 | wmcodec_write(NGAT, NGAT_NGG(type)|NGAT_NGTH(ngath_tenthdb2hw(ngath))); | 454 | wmcodec_clear_bits(NGAT, NGAT_NGAT); |
403 | } | 455 | } |
404 | 456 | ||
405 | 457 | ||
406 | void audiohw_set_alc(int level, unsigned int hold, int decay, int attack, bool enable) | 458 | static void audiohw_set_alc(unsigned char level, /* signal level at ADC */ |
459 | bool zc, /* zero cross detection */ | ||
460 | unsigned char hold, /* hold time */ | ||
461 | unsigned char decay, /* decay time */ | ||
462 | unsigned char attack, /* attack time */ | ||
463 | bool enable) /* hw function on/off */ | ||
407 | { | 464 | { |
408 | /* level in thenth of dB -28.5dB - -6dB in 1.5dB steps | ||
409 | * hold time in us 0us - 43691000us | ||
410 | * decay time in ms 24ms - 24580ms | ||
411 | * attack time in ms 6ms - 6140ms | ||
412 | */ | ||
413 | |||
414 | if(enable) | 465 | if(enable) |
415 | { | 466 | { |
416 | wmcodec_write(ALC1, ALC1_ALCSEL_STEREO|ALC1_MAXGAIN(0x07)| | 467 | wmcodec_set_reg(ALC1, ALC1_ALCSEL_STEREO | ALC1_MAXGAIN(0x07) | |
417 | ALC1_ALCL(alc_tenthdb2hw(level))); | 468 | ALC1_ALCL(level)); |
418 | wmcodec_write(ALC2, ALC2_ALCZ|ALC2_HLD(alc_hldus2hw(hold))); | 469 | wmcodec_set_reg(ALC2, zc?ALC2_ALCZC:0 | ALC2_HLD(hold)); |
419 | wmcodec_write(ALC3, ALC3_DCY(alc_dcyms2hw(decay))| | 470 | wmcodec_set_reg(ALC3, ALC3_DCY(decay) | ALC3_ATK(attack)); |
420 | ALC3_ATK(alc_atkms2hw(attack))); | ||
421 | } | 471 | } |
422 | else | 472 | else |
423 | { | 473 | { |
424 | wmcodec_write(ALC1, ALC1_ALCSEL_DISABLED|ALC1_MAXGAIN(0x07)|ALC1_ALCL(alc_tenthdb2hw(level))); | 474 | wmcodec_set_masked(ALC1, ALC1_ALCSEL_DISABLED, ALC1_ALCSEL_MASK); |
425 | } | 475 | } |
426 | } | 476 | } |
427 | 477 | ||
428 | void audiohw_set_alc(int level, unsigned int hold, int decay, int attack, bool enable) | ||
429 | { | ||
430 | /* level in thenth of dB -28.5dB - -6dB in 1.5dB steps | ||
431 | * hold time in 15 steps 0ms,2.67ms,5.33ms,...,43691ms | ||
432 | * decay time in 10 steps 24ms,48ms,96ms,...,24580ms | ||
433 | * attack time in 10 steps 6ms,12ms,24ms,...,6140ms | ||
434 | */ | ||
435 | |||
436 | if(enable) | ||
437 | { | ||
438 | wmcodec_write(ALC1, ALC1_ALCSEL_STEREO|ALC1_MAXGAIN(0x07)| | ||
439 | ALC1_ALCL(alc_tenthdb2hw(level))); | ||
440 | wmcodec_write(ALC2, ALC2_ALCZ|ALC2_HLD(hold)); | ||
441 | wmcodec_write(ALC3, ALC3_DCY(decay)| | ||
442 | ALC3_ATK(attack)); | ||
443 | } | ||
444 | else | ||
445 | { | ||
446 | wmcodec_write(ALC1, ALC1_ALCSEL_DISABLED|ALC1_MAXGAIN(0x07)| | ||
447 | ALC1_ALCL(alc_tenthdb2hw(level))); | ||
448 | } | ||
449 | } | ||
450 | |||
451 | void audiohw_set_alc_level(int level) | ||
452 | { | ||
453 | wmcodec_write(ALC1, ALC1_ALCSEL_STEREO|ALC1_MAXGAIN(0x07)| | ||
454 | ALC1_ALCL(alc_tenthdb2hw(level))); | ||
455 | } | ||
456 | #endif | ||
457 | void audiohw_set_recsrc(int source, bool recording) | 478 | void audiohw_set_recsrc(int source, bool recording) |
458 | { | 479 | { |
459 | /* INPUT1 - FM radio | 480 | /* INPUT1 - FM radio |
@@ -472,29 +493,20 @@ void audiohw_set_recsrc(int source, bool recording) | |||
472 | switch(source) | 493 | switch(source) |
473 | { | 494 | { |
474 | case AUDIO_SRC_PLAYBACK: | 495 | case AUDIO_SRC_PLAYBACK: |
475 | /* turn off DAC and ADC in order to setup Enchance 3D function | 496 | audiohw_mute(true); |
476 | * for playback. This does not turn on enchancement but | ||
477 | * the switch between playback/record has to be done with | ||
478 | * DAC and ADC off | ||
479 | */ | ||
480 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
481 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | ||
482 | wmcodec_write(PWRMGMT2, 0x00); | ||
483 | wmcodec_write(ENHANCE_3D, ENHANCE_3D_MODE3D_PLAYBACK); | ||
484 | #endif | ||
485 | /* mute PGA, disable all audio paths but DAC and output stage*/ | ||
486 | wmcodec_write(LINVOL, LINVOL_LINMUTE | LINVOL_LINVOL(0x17)); /* 0dB */ | ||
487 | wmcodec_write(RINVOL, RINVOL_RINMUTE | RINVOL_RINVOL(0x17)); /* 0dB */ | ||
488 | 497 | ||
489 | wmcodec_write(LOUT1, LOUT1_BITS); | 498 | /* mute PGA, disable all audio paths but DAC and output stage*/ |
490 | wmcodec_write(ROUT1, ROUT1_BITS); | 499 | wmcodec_set_bits(LINVOL, LINVOL_LINMUTE); /* Mute */ |
500 | wmcodec_set_bits(RINVOL, RINVOL_RINMUTE); /* Mute */ | ||
491 | 501 | ||
492 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 502 | wmcodec_clear_bits(PWRMGMT2, PWRMGMT2_OUT3 | PWRMGMT2_MOUT | |
493 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 503 | PWRMGMT2_ROUT2 | PWRMGMT2_LOUT2); |
494 | 504 | ||
495 | /* route DAC signal to output mixer */ | 505 | /* route DAC signal to output mixer, disable INPUT routing */ |
496 | wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO); | 506 | wmcodec_clear_bits(LEFTMIX1, LEFTMIX1_LI2LO); |
497 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO); | 507 | wmcodec_set_bits(LEFTMIX1, LEFTMIX1_LD2LO); |
508 | wmcodec_clear_bits(RIGHTMIX2, RIGHTMIX2_RI2RO); | ||
509 | wmcodec_set_bits(RIGHTMIX2, RIGHTMIX2_RD2RO); | ||
498 | 510 | ||
499 | /* unmute DAC */ | 511 | /* unmute DAC */ |
500 | audiohw_mute(false); | 512 | audiohw_mute(false); |
@@ -503,136 +515,141 @@ void audiohw_set_recsrc(int source, bool recording) | |||
503 | case AUDIO_SRC_FMRADIO: | 515 | case AUDIO_SRC_FMRADIO: |
504 | if(recording) | 516 | if(recording) |
505 | { | 517 | { |
506 | /* turn off DAC and ADC in order to setup Enchance 3D function | 518 | audiohw_mute(true); |
507 | * for playback. This does not turn on enchancement but | ||
508 | * the switch between playback/record has to be done with | ||
509 | * DAC and ADC off | ||
510 | */ | ||
511 | #ifdef AUDIOHW_HAVE_DEPTH_3D | ||
512 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | ||
513 | wmcodec_write(PWRMGMT2, 0x00); | ||
514 | wmcodec_write(ENHANCE_3D, ENHANCE_3D_MODE3D_RECORD); | ||
515 | #endif | ||
516 | |||
517 | /* Turn on PGA and ADC */ | 519 | /* Turn on PGA and ADC */ |
518 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | | 520 | wmcodec_set_bits(PWRMGMT1, PWRMGMT1_AINL | PWRMGMT1_AINR | |
519 | PWRMGMT1_AINL | PWRMGMT1_AINR | | 521 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); |
520 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); | ||
521 | 522 | ||
522 | /* Set input volume to PGA 0dB*/ | 523 | /* Set input volume to PGA 0dB*/ |
523 | wmcodec_write(LINVOL, LINVOL_LIVU|LINVOL_LINVOL(0x17)); | 524 | wmcodec_set_reg(LINVOL, LINVOL_LIVU | LINVOL_LINVOL(0x17)); |
524 | wmcodec_write(RINVOL, RINVOL_RIVU|RINVOL_RINVOL(0x17)); | 525 | wmcodec_set_reg(RINVOL, RINVOL_RIVU | RINVOL_RINVOL(0x17)); |
525 | 526 | ||
526 | /* Setup input source for PGA as INPUT1 | 527 | /* Setup input source for PGA as INPUT1 */ |
527 | * MICBOOST disabled | 528 | wmcodec_set_masked(ADCL, ADCL_LINSEL_LINPUT1, ADCL_LINSEL_MASK); |
528 | */ | 529 | wmcodec_set_masked(ADCR, ADCR_RINSEL_RINPUT1, ADCR_RINSEL_MASK); |
529 | wmcodec_write(ADCL, ADCL_LINSEL_LINPUT1 | ADCL_LMICBOOST_DISABLED); | 530 | |
530 | wmcodec_write(ADCR, ADCR_RINSEL_RINPUT1 | ADCR_RMICBOOST_DISABLED); | 531 | /* turn off ALC and NGAT as OF do */ |
532 | audiohw_set_alc(0x00, false, 0x00, 0x00, 0x00, false); | ||
533 | audiohw_set_ngat(0x00, 0x00, false); | ||
531 | 534 | ||
532 | /* setup output digital data | 535 | /* setup output digital data |
533 | * default is LADC -> LDATA, RADC -> RDATA | 536 | * default is LADC -> LDATA, RADC -> RDATA |
534 | * so we don't touch this | 537 | * so we don't touch this |
535 | */ | 538 | */ |
536 | 539 | ||
537 | /* power up DAC and output stage */ | 540 | /* skip: power up DAC and output stage as its never powered down |
538 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 541 | wmcodec_set_bits(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | |
539 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 542 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); |
543 | */ | ||
540 | 544 | ||
541 | /* route DAC signal to output mixer */ | 545 | /* route DAC signal to output mixer, disable INPUT routing */ |
542 | wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO); | 546 | wmcodec_clear_bits(LEFTMIX1, LEFTMIX1_LI2LO); |
543 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO); | 547 | wmcodec_set_bits(LEFTMIX1, LEFTMIX1_LD2LO); |
548 | wmcodec_clear_bits(RIGHTMIX2, RIGHTMIX2_RI2RO); | ||
549 | wmcodec_set_bits(RIGHTMIX2, RIGHTMIX2_RD2RO); | ||
550 | |||
551 | audiohw_mute(false); | ||
544 | } | 552 | } |
545 | else | 553 | else |
546 | { | 554 | { |
547 | /* turn off ADC, PGA */ | 555 | audiohw_mute(true); |
548 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | ||
549 | 556 | ||
550 | /* turn on DAC and output stage */ | 557 | /* turn off ADC, PGA */ |
551 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 558 | wmcodec_clear_bits(PWRMGMT1, PWRMGMT1_AINL | PWRMGMT1_AINR | |
552 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 559 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); |
553 | 560 | ||
554 | /* setup monitor mode by routing input signal to outmix | 561 | /* setup monitor mode by routing input signal to outmix |
555 | * at 0dB volume | 562 | * at 0dB volume |
556 | */ | 563 | */ |
557 | wmcodec_write(LEFTMIX1, LEFTMIX1_LI2LO | LEFTMIX1_LMIXSEL_LINPUT1 | | 564 | wmcodec_set_masked(LEFTMIX1, LEFTMIX1_LI2LOVOL(0x20), |
558 | LEFTMIX1_LI2LOVOL(0x20) | LEFTMIX1_LD2LO); | 565 | LEFTMIX1_LI2LOVOL_MASK); |
559 | wmcodec_write(RIGHTMIX1, RIGHTMIX1_RMIXSEL_RINPUT1); | 566 | wmcodec_set_bits(LEFTMIX1, LEFTMIX1_LI2LO | |
560 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RI2RO | | 567 | LEFTMIX1_LMIXSEL_LINPUT1 | |
561 | RIGHTMIX2_RI2ROVOL(0x20) | RIGHTMIX2_RD2RO); | 568 | LEFTMIX1_LD2LO); |
569 | wmcodec_set_masked(RIGHTMIX2, RIGHTMIX2_RI2ROVOL(0x20), | ||
570 | RIGHTMIX2_RI2ROVOL_MASK); | ||
571 | wmcodec_set_bits(RIGHTMIX1, RIGHTMIX1_RMIXSEL_RINPUT1); | ||
572 | wmcodec_set_bits(RIGHTMIX2, RIGHTMIX2_RI2RO | | ||
573 | RIGHTMIX2_RD2RO); | ||
574 | |||
575 | audiohw_mute(false); | ||
562 | } | 576 | } |
563 | break; | 577 | break; |
564 | 578 | ||
565 | #if (INPUT_SRC_CAPS & SRC_CAP_LINEIN) | 579 | #if (INPUT_SRC_CAPS & SRC_CAP_LINEIN) |
566 | case AUDIO_SRC_LINEIN: | 580 | case AUDIO_SRC_LINEIN: |
567 | #ifdef AUDIOHW_HAVE_DEPTH_3D | 581 | audiohw_mute(true); |
568 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | ||
569 | wmcodec_write(PWRMGMT2, 0x00); | ||
570 | wmcodec_write(ENHANCE_3D, ENHANCE_3D_MODE3D_RECORD); | ||
571 | #endif | ||
572 | |||
573 | /* Set input volume to PGA */ | ||
574 | wmcodec_write(LINVOL, LINVOL_LIVU | LINVOL_LINVOL(23)); | ||
575 | wmcodec_write(RINVOL, RINVOL_RIVU | RINVOL_RINVOL(23)); | ||
576 | 582 | ||
577 | /* Turn on PGA, ADC */ | 583 | /* Turn on PGA, ADC */ |
578 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | | 584 | wmcodec_set_bits(PWRMGMT1, PWRMGMT1_AINL | PWRMGMT1_AINR | |
579 | PWRMGMT1_AINL | PWRMGMT1_AINR | | 585 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); |
580 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); | ||
581 | 586 | ||
582 | /* turn on DAC and output stage */ | 587 | /* Set input volume to PGA 0dB*/ |
583 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 588 | wmcodec_set_reg(LINVOL, LINVOL_LIVU | LINVOL_LINVOL(0x17)); |
584 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 589 | wmcodec_set_reg(RINVOL, RINVOL_RIVU | RINVOL_RINVOL(0x17)); |
585 | 590 | ||
586 | /* Setup input source for PGA as INPUT2 | 591 | /* Setup input source for PGA as INPUT2 |
587 | * MICBOOST disabled | 592 | * MICBOOST disabled |
588 | */ | 593 | */ |
589 | wmcodec_write(ADCL, ADCL_LINSEL_LINPUT2 | ADCL_LMICBOOST_DISABLED); | 594 | wmcodec_set_masked(ADCL, ADCL_LINSEL_LINPUT2, ADCL_LINSEL_MASK); |
590 | wmcodec_write(ADCR, ADCR_RINSEL_RINPUT2 | ADCR_RMICBOOST_DISABLED); | 595 | wmcodec_set_masked(ADCR, ADCR_RINSEL_RINPUT2, ADCR_RINSEL_MASK); |
596 | |||
597 | /* setup ALC and NGAT as OF do */ | ||
598 | /* level, zc, hold, decay, attack, enable */ | ||
599 | audiohw_set_alc(0x0b, true, 0x00, 0x03, 0x02, true); | ||
600 | /* ngath, type, enable */ | ||
601 | audiohw_set_ngat(0x08, 0x02, true); | ||
591 | 602 | ||
592 | /* setup output digital data | 603 | /* setup output digital data |
593 | * default is LADC -> LDATA, RADC -> RDATA | 604 | * default is LADC -> LDATA, RADC -> RDATA |
594 | * so we don't touch this | 605 | * so we don't touch this |
595 | */ | 606 | */ |
596 | /* route DAC signal to output mixer */ | 607 | |
597 | wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO); | 608 | /* route DAC signal to output mixer, disable INPUT routing */ |
598 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO); | 609 | wmcodec_clear_bits(LEFTMIX1, LEFTMIX1_LI2LO); |
610 | wmcodec_set_bits(LEFTMIX1, LEFTMIX1_LD2LO); | ||
611 | wmcodec_clear_bits(RIGHTMIX2, RIGHTMIX2_RI2RO); | ||
612 | wmcodec_set_bits(RIGHTMIX2, RIGHTMIX2_RD2RO); | ||
613 | |||
614 | audiohw_mute(false); | ||
599 | break; | 615 | break; |
600 | #endif | 616 | #endif |
601 | #if (INPUT_SRC_CAPS & SRC_CAP_MIC) | 617 | #if (INPUT_SRC_CAPS & SRC_CAP_MIC) |
602 | case AUDIO_SRC_MIC: | 618 | case AUDIO_SRC_MIC: |
603 | #ifdef AUDIOHW_HAVE_DEPTH_3D | 619 | audiohw_mute(true); |
604 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K); | ||
605 | wmcodec_write(PWRMGMT2, 0x00); | ||
606 | wmcodec_write(ENHANCE_3D, ENHANCE_3D_MODE3D_RECORD); | ||
607 | #endif | ||
608 | |||
609 | /* Set input volume to PGA */ | ||
610 | wmcodec_write(LINVOL, LINVOL_LIVU | LINVOL_LINVOL(23)); | ||
611 | wmcodec_write(RINVOL, RINVOL_RIVU | RINVOL_RINVOL(23)); | ||
612 | 620 | ||
613 | /* Turn on PGA and ADC, turn off DAC */ | 621 | /* Turn on PGA and ADC */ |
614 | wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K | | 622 | wmcodec_set_bits(PWRMGMT1, PWRMGMT1_AINL | PWRMGMT1_AINR | |
615 | PWRMGMT1_AINL | PWRMGMT1_AINR | | 623 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); |
616 | PWRMGMT1_ADCL | PWRMGMT1_ADCR); | ||
617 | 624 | ||
618 | /* turn on DAC and output stage */ | 625 | /* Set input volume to PGA 0dB*/ |
619 | wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR | | 626 | wmcodec_set_reg(LINVOL, LINVOL_LIVU | LINVOL_LINVOL(0x17)); |
620 | PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1); | 627 | wmcodec_set_reg(RINVOL, RINVOL_RIVU | RINVOL_RINVOL(0x17)); |
621 | 628 | ||
622 | /* Setup input source for PGA as INPUT3 | 629 | /* Setup input source for PGA as INPUT3 |
623 | * MICBOOST disabled | 630 | * MICBOOST disabled |
624 | */ | 631 | */ |
625 | wmcodec_write(ADCL, ADCL_LINSEL_LINPUT3 | ADCL_LMICBOOST_DISABLED); | 632 | wmcodec_set_masked(ADCL, ADCL_LINSEL_LINPUT3, ADCL_LINSEL_MASK); |
626 | wmcodec_write(ADCR, ADCR_RINSEL_RINPUT3 | ADCR_RMICBOOST_DISABLED); | 633 | wmcodec_set_masked(ADCR, ADCR_RINSEL_RINPUT3, ADCR_RINSEL_MASK); |
634 | |||
635 | /* setup ALC and NGAT as OF do */ | ||
636 | /* level, zc, hold, decay, attack, enable */ | ||
637 | audiohw_set_alc(0x0f, false, 0x00, 0x05, 0x02, true); | ||
638 | /* ngath, type, enable */ | ||
639 | audiohw_set_ngat(0x1f, 0x00, true); | ||
627 | 640 | ||
628 | /* setup output digital data | 641 | /* setup output digital data |
629 | * default is LADC -> LDATA, RADC -> RDATA | 642 | * default is LADC -> LDATA, RADC -> RDATA |
630 | * so we don't touch this | 643 | * so we don't touch this |
631 | */ | 644 | */ |
632 | 645 | ||
633 | /* route DAC signal to output mixer */ | 646 | /* route DAC signal to output mixer, disable INPUT routing */ |
634 | wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO); | 647 | wmcodec_clear_bits(LEFTMIX1, LEFTMIX1_LI2LO); |
635 | wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO); | 648 | wmcodec_set_bits(LEFTMIX1, LEFTMIX1_LD2LO); |
649 | wmcodec_clear_bits(RIGHTMIX2, RIGHTMIX2_RI2RO); | ||
650 | wmcodec_set_bits(RIGHTMIX2, RIGHTMIX2_RD2RO); | ||
651 | |||
652 | audiohw_mute(false); | ||
636 | break; | 653 | break; |
637 | #endif | 654 | #endif |
638 | } /* switch(source) */ | 655 | } /* switch(source) */ |
@@ -641,9 +658,14 @@ void audiohw_set_recsrc(int source, bool recording) | |||
641 | /* Setup PGA gain */ | 658 | /* Setup PGA gain */ |
642 | void audiohw_set_recvol(int vol_l, int vol_r, int type) | 659 | void audiohw_set_recvol(int vol_l, int vol_r, int type) |
643 | { | 660 | { |
644 | (void)type; | 661 | wmcodec_set_reg(LADCVOL, LADCVOL_LADCVOL(recvol2hw(vol_l))); |
645 | wmcodec_write(LINVOL, LINVOL_LIZC|LINVOL_LINVOL(recvol2hw(vol_l))); | 662 | |
646 | wmcodec_write(RINVOL, RINVOL_RIZC|RINVOL_RIVU|RINVOL_RINVOL(recvol2hw(vol_r))); | 663 | if (type == AUDIO_GAIN_MIC) |
664 | wmcodec_set_reg(RADCVOL, RADCVOL_RAVU | | ||
665 | RADCVOL_RADCVOL(recvol2hw(vol_l))); | ||
666 | else | ||
667 | wmcodec_set_reg(RADCVOL, RADCVOL_RAVU | | ||
668 | RADCVOL_RADCVOL(recvol2hw(vol_r))); | ||
647 | } | 669 | } |
648 | #endif /* HAVE_RECORDING */ | 670 | #endif /* HAVE_RECORDING */ |
649 | #endif /* HAVE_WM8750 */ | 671 | #endif /* HAVE_WM8750 */ |