wm8978: Clean out silly macros. Use 'POS' convention instead for shifted bitfields...
[kugel-rb.git] / firmware / drivers / audio / wm8978.c
bloba2dbf5a8fb9b166d52e3c82810c6400b05499ea8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Michael Sevakis
12 * Driver for WM8978 audio codec
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include "config.h"
24 #include "system.h"
25 #include "audiohw.h"
26 #include "wmcodec.h"
27 #include "audio.h"
28 /*#define LOGF_ENABLE*/
29 #include "logf.h"
31 /* TODO: Define/refine an API for special hardware steps outside the
32 * main codec driver such as special GPIO handling. */
33 /* NOTE: Much of the volume code is very interdependent and calibrated for
34 * the Gigabeat S. If you change anything for another device that uses this
35 * file it may break things. */
36 extern void audiohw_enable_headphone_jack(bool enable);
38 const struct sound_settings_info audiohw_settings[] =
40 [SOUND_VOLUME] = {"dB", 0, 1, -90, 6, -25},
41 [SOUND_BASS] = {"dB", 0, 1, -12, 12, 0},
42 [SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 0},
43 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
44 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
45 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
46 #ifdef HAVE_RECORDING
47 /* Digital: -119.0dB to +8.0dB in 0.5dB increments
48 * Analog: Relegated to volume control
49 * Circumstances unfortunately do not allow a great deal of positive
50 * gain. */
51 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-238, 16, 0},
52 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-238, 16, 0},
53 #if 0
54 [SOUND_MIC_GAIN] = {"dB", 1, 1,-238, 16, 0},
55 #endif
56 #endif
57 #if 0
58 [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1},
59 [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1},
60 #endif
63 static uint16_t wmc_regs[WMC_NUM_REGISTERS] =
65 /* Initialized with post-reset default values - the 2-wire interface
66 * cannot be read. Or-in additional bits desired for some registers. */
67 [0 ... WMC_NUM_REGISTERS-1] = 0x8000, /* To ID invalids in gaps */
68 [WMC_SOFTWARE_RESET] = 0x000,
69 [WMC_POWER_MANAGEMENT1] = 0x000,
70 [WMC_POWER_MANAGEMENT2] = 0x000,
71 [WMC_POWER_MANAGEMENT3] = 0x000,
72 [WMC_AUDIO_INTERFACE] = 0x050,
73 [WMC_COMPANDING_CTRL] = 0x000,
74 [WMC_CLOCK_GEN_CTRL] = 0x140,
75 [WMC_ADDITIONAL_CTRL] = 0x000,
76 [WMC_GPIO] = 0x000,
77 [WMC_JACK_DETECT_CONTROL1] = 0x000,
78 [WMC_DAC_CONTROL] = 0x000,
79 [WMC_LEFT_DAC_DIGITAL_VOL] = 0x0ff, /* Latch left first */
80 [WMC_RIGHT_DAC_DIGITAL_VOL] = 0x0ff | WMC_VU,
81 [WMC_JACK_DETECT_CONTROL2] = 0x000,
82 [WMC_ADC_CONTROL] = 0x100,
83 [WMC_LEFT_ADC_DIGITAL_VOL] = 0x0ff, /* Latch left first */
84 [WMC_RIGHT_ADC_DIGITAL_VOL] = 0x0ff | WMC_VU,
85 [WMC_EQ1_LOW_SHELF] = 0x12c,
86 [WMC_EQ2_PEAK1] = 0x02c,
87 [WMC_EQ3_PEAK2] = 0x02c,
88 [WMC_EQ4_PEAK3] = 0x02c,
89 [WMC_EQ5_HIGH_SHELF] = 0x02c,
90 [WMC_DAC_LIMITER1] = 0x032,
91 [WMC_DAC_LIMITER2] = 0x000,
92 [WMC_NOTCH_FILTER1] = 0x000,
93 [WMC_NOTCH_FILTER2] = 0x000,
94 [WMC_NOTCH_FILTER3] = 0x000,
95 [WMC_NOTCH_FILTER4] = 0x000,
96 [WMC_ALC_CONTROL1] = 0x038,
97 [WMC_ALC_CONTROL2] = 0x00b,
98 [WMC_ALC_CONTROL3] = 0x032,
99 [WMC_NOISE_GATE] = 0x000,
100 [WMC_PLL_N] = 0x008,
101 [WMC_PLL_K1] = 0x00c,
102 [WMC_PLL_K2] = 0x093,
103 [WMC_PLL_K3] = 0x0e9,
104 [WMC_3D_CONTROL] = 0x000,
105 [WMC_BEEP_CONTROL] = 0x000,
106 [WMC_INPUT_CTRL] = 0x033,
107 [WMC_LEFT_INP_PGA_GAIN_CTRL] = 0x010 | WMC_ZC, /* Latch left first */
108 [WMC_RIGHT_INP_PGA_GAIN_CTRL] = 0x010 | WMC_VU | WMC_ZC,
109 [WMC_LEFT_ADC_BOOST_CTRL] = 0x100,
110 [WMC_RIGHT_ADC_BOOST_CTRL] = 0x100,
111 [WMC_OUTPUT_CTRL] = 0x002,
112 [WMC_LEFT_MIXER_CTRL] = 0x001,
113 [WMC_RIGHT_MIXER_CTRL] = 0x001,
114 [WMC_LOUT1_HP_VOLUME_CTRL] = 0x039 | WMC_ZC, /* Latch left first */
115 [WMC_ROUT1_HP_VOLUME_CTRL] = 0x039 | WMC_VU | WMC_ZC,
116 [WMC_LOUT2_SPK_VOLUME_CTRL] = 0x039 | WMC_ZC, /* Latch left first */
117 [WMC_ROUT2_SPK_VOLUME_CTRL] = 0x039 | WMC_VU | WMC_ZC,
118 [WMC_OUT3_MIXER_CTRL] = 0x001,
119 [WMC_OUT4_MONO_MIXER_CTRL] = 0x001,
122 struct
124 int vol_l;
125 int vol_r;
126 bool ahw_mute;
127 } wmc_vol =
129 0, 0, false
132 static void wmc_write(unsigned int reg, unsigned int val)
134 if (reg >= WMC_NUM_REGISTERS || (wmc_regs[reg] & 0x8000))
136 logf("wm8978 invalid register: %d", reg);
137 return;
140 wmc_regs[reg] = val & ~0x8000;
141 wmcodec_write(reg, val);
144 void wmc_set(unsigned int reg, unsigned int bits)
146 wmc_write(reg, wmc_regs[reg] | bits);
149 void wmc_clear(unsigned int reg, unsigned int bits)
151 wmc_write(reg, wmc_regs[reg] & ~bits);
154 static void wmc_write_masked(unsigned int reg, unsigned int bits,
155 unsigned int mask)
157 wmc_write(reg, (wmc_regs[reg] & ~mask) | (bits & mask));
160 /* convert tenth of dB volume (-890..60) to master volume register value
161 * (000000...111111) */
162 int tenthdb2master(int db)
164 /* -90dB to +6dB 1dB steps (96 levels) 7bits */
165 /* 1100000 == +6dB (0x60,96) */
166 /* 1101010 == 0dB (0x5a,90) */
167 /* 1000001 == -57dB (0x21,33,DAC) */
168 /* 0000001 == -89dB (0x01,01) */
169 /* 0000000 == -90dB (0x00,00,Mute) */
170 if (db <= VOLUME_MIN)
172 return 0x0;
174 else
176 return (db - VOLUME_MIN) / 10;
180 int sound_val2phys(int setting, int value)
182 int result;
184 switch (setting)
186 #ifdef HAVE_RECORDING
187 case SOUND_LEFT_GAIN:
188 case SOUND_RIGHT_GAIN:
189 case SOUND_MIC_GAIN:
190 result = value * 5;
191 break;
192 #endif
194 default:
195 result = value;
198 return result;
201 void audiohw_preinit(void)
203 /* 1. Turn on external power supplies. Wait for supply voltage to settle. */
205 /* Step 1 should be completed already. Reset and return all registers to
206 * defaults */
207 wmcodec_write(WMC_SOFTWARE_RESET, 0xff);
208 sleep(HZ/10);
210 /* 2. Mute all analogue outputs */
211 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
212 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
213 wmc_set(WMC_LOUT2_SPK_VOLUME_CTRL, WMC_MUTE);
214 wmc_set(WMC_ROUT2_SPK_VOLUME_CTRL, WMC_MUTE);
215 wmc_set(WMC_OUT3_MIXER_CTRL, WMC_MUTE);
216 wmc_set(WMC_OUT4_MONO_MIXER_CTRL, WMC_MUTE);
218 /* 3. Set L/RMIXEN = 1 and DACENL/R = 1 in register R3. */
219 wmc_write(WMC_POWER_MANAGEMENT3,
220 WMC_RMIXEN | WMC_LMIXEN | WMC_DACENR | WMC_DACENL);
222 /* 4. Set BUFIOEN = 1 and VMIDSEL[1:0] to required value in register
223 * R1. Wait for VMID supply to settle */
224 wmc_write(WMC_POWER_MANAGEMENT1, WMC_BUFIOEN | WMC_VMIDSEL_300K);
225 sleep(HZ/10);
227 /* 5. Set BIASEN = 1 in register R1. */
228 wmc_set(WMC_POWER_MANAGEMENT1, WMC_BIASEN);
231 void audiohw_postinit(void)
233 sleep(HZ);
235 /* 6. Set L/ROUTEN = 1 in register R2. */
236 wmc_write(WMC_POWER_MANAGEMENT2, WMC_LOUT1EN | WMC_ROUT1EN);
238 /* 7. Enable other mixers as required */
240 /* 8. Enable other outputs as required */
242 /* 9. Set remaining registers */
243 wmc_write(WMC_AUDIO_INTERFACE, WMC_WL_16 | WMC_FMT_I2S);
244 wmc_write(WMC_DAC_CONTROL, WMC_DACOSR_128 | WMC_AMUTE);
246 /* No ADC, no HP filter, no popping */
247 wmc_clear(WMC_ADC_CONTROL, WMC_HPFEN);
249 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
250 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
252 /* Specific to HW clocking */
253 wmc_write_masked(WMC_CLOCK_GEN_CTRL, WMC_BCLKDIV_4 | WMC_MS,
254 WMC_BCLKDIV | WMC_MS | WMC_CLKSEL);
255 audiohw_set_frequency(HW_FREQ_DEFAULT);
257 audiohw_enable_headphone_jack(true);
260 static void get_headphone_levels(int val, int *dac_p, int *hp_p,
261 int *mix_p, int *boost_p)
263 int dac, hp, mix, boost;
265 if (val >= 33)
267 dac = 255;
268 hp = val - 33;
269 mix = 7;
270 boost = 5;
272 else if (val >= 21)
274 dac = 189 + val / 3 * 6;
275 hp = val % 3;
276 mix = 7;
277 boost = (val - 18) / 3;
279 else
281 dac = 189 + val / 3 * 6;
282 hp = val % 3;
283 mix = val / 3;
284 boost = 1;
287 *dac_p = dac;
288 *hp_p = hp;
289 *mix_p = mix;
290 *boost_p = boost;
293 void audiohw_set_headphone_vol(int vol_l, int vol_r)
295 int prev_l = wmc_vol.vol_l;
296 int prev_r = wmc_vol.vol_r;
297 int dac_l, dac_r, hp_l, hp_r;
298 int mix_l, mix_r, boost_l, boost_r;
300 wmc_vol.vol_l = vol_l;
301 wmc_vol.vol_r = vol_r;
303 /* Mixers are synced to provide full volume range on both the analogue
304 * and digital pathways */
305 get_headphone_levels(vol_l, &dac_l, &hp_l, &mix_l, &boost_l);
306 get_headphone_levels(vol_r, &dac_r, &hp_r, &mix_r, &boost_r);
308 wmc_write_masked(WMC_LEFT_MIXER_CTRL, mix_l << WMC_BYPLMIXVOL_POS,
309 WMC_BYPLMIXVOL);
310 wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL,
311 boost_l << WMC_L2_2BOOSTVOL_POS, WMC_L2_2BOOSTVOL);
312 wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, dac_l, WMC_DVOL);
313 wmc_write_masked(WMC_LOUT1_HP_VOLUME_CTRL, hp_l, WMC_AVOL);
315 wmc_write_masked(WMC_RIGHT_MIXER_CTRL, mix_r << WMC_BYPRMIXVOL_POS,
316 WMC_BYPRMIXVOL);
317 wmc_write_masked(WMC_RIGHT_ADC_BOOST_CTRL,
318 boost_r << WMC_R2_2BOOSTVOL_POS, WMC_R2_2BOOSTVOL);
319 wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, dac_r, WMC_DVOL);
320 wmc_write_masked(WMC_ROUT1_HP_VOLUME_CTRL, hp_r, WMC_AVOL);
322 if (vol_l > 0)
324 /* Not muted and going up from mute level? */
325 if (prev_l <= 0 && !wmc_vol.ahw_mute)
326 wmc_clear(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
328 else
330 /* Going to mute level? */
331 if (prev_l > 0)
332 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
335 if (vol_r > 0)
337 /* Not muted and going up from mute level? */
338 if (prev_r <= 0 && !wmc_vol.ahw_mute)
339 wmc_clear(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
341 else
343 /* Going to mute level? */
344 if (prev_r > 0)
345 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
349 static void audiohw_mute(bool mute)
351 wmc_vol.ahw_mute = mute;
353 /* No DAC mute here, please - take care of each enabled output. */
354 if (mute)
356 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
357 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
359 else
361 /* Unmute outputs not at mute level */
362 if (wmc_vol.vol_l > 0)
363 wmc_clear(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
365 if (wmc_vol.vol_r > 0)
366 wmc_clear(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
370 void audiohw_close(void)
372 /* 1. Mute all analogue outputs */
373 audiohw_mute(true);
374 audiohw_enable_headphone_jack(false);
376 /* 2. Disable power management register 1. R1 = 00 */
377 wmc_write(WMC_POWER_MANAGEMENT1, 0x000);
379 /* 3. Disable power management register 2. R2 = 00 */
380 wmc_write(WMC_POWER_MANAGEMENT2, 0x000);
382 /* 4. Disable power management register 3. R3 = 00 */
383 wmc_write(WMC_POWER_MANAGEMENT3, 0x000);
385 /* 5. Remove external power supplies. */
388 void audiohw_set_frequency(int fsel)
390 /* For 16.9344MHz MCLK, codec as master. */
391 static const struct
393 uint32_t plln : 8;
394 uint32_t pllk1 : 6;
395 uint32_t pllk2 : 9;
396 uint32_t pllk3 : 9;
397 unsigned char mclkdiv;
398 unsigned char filter;
399 } srctrl_table[HW_NUM_FREQ] =
401 [HW_FREQ_8] = /* PLL = 65.536MHz */
403 .plln = 7 | WMC_PLL_PRESCALE,
404 .pllk1 = 0x2f, /* 12414886 */
405 .pllk2 = 0x0b7,
406 .pllk3 = 0x1a6,
407 .mclkdiv = WMC_MCLKDIV_8, /* 2.0480 MHz */
408 .filter = WMC_SR_8KHZ,
410 [HW_FREQ_11] = /* PLL = off */
412 .mclkdiv = WMC_MCLKDIV_6, /* 2.8224 MHz */
413 .filter = WMC_SR_12KHZ,
415 [HW_FREQ_12] = /* PLL = 73.728 MHz */
417 .plln = 8 | WMC_PLL_PRESCALE,
418 .pllk1 = 0x2d, /* 11869595 */
419 .pllk2 = 0x08e,
420 .pllk3 = 0x19b,
421 .mclkdiv = WMC_MCLKDIV_6, /* 3.0720 MHz */
422 .filter = WMC_SR_12KHZ,
424 [HW_FREQ_16] = /* PLL = 65.536MHz */
426 .plln = 7 | WMC_PLL_PRESCALE,
427 .pllk1 = 0x2f, /* 12414886 */
428 .pllk2 = 0x0b7,
429 .pllk3 = 0x1a6,
430 .mclkdiv = WMC_MCLKDIV_4, /* 4.0960 MHz */
431 .filter = WMC_SR_16KHZ,
433 [HW_FREQ_22] = /* PLL = off */
435 .mclkdiv = WMC_MCLKDIV_3, /* 5.6448 MHz */
436 .filter = WMC_SR_24KHZ,
438 [HW_FREQ_24] = /* PLL = 73.728 MHz */
440 .plln = 8 | WMC_PLL_PRESCALE,
441 .pllk1 = 0x2d, /* 11869595 */
442 .pllk2 = 0x08e,
443 .pllk3 = 0x19b,
444 .mclkdiv = WMC_MCLKDIV_3, /* 6.1440 MHz */
445 .filter = WMC_SR_24KHZ,
447 [HW_FREQ_32] = /* PLL = 65.536MHz */
449 .plln = 7 | WMC_PLL_PRESCALE,
450 .pllk1 = 0x2f, /* 12414886 */
451 .pllk2 = 0x0b7,
452 .pllk3 = 0x1a6,
453 .mclkdiv = WMC_MCLKDIV_2, /* 8.1920 MHz */
454 .filter = WMC_SR_32KHZ,
456 [HW_FREQ_44] = /* PLL = off */
458 .mclkdiv = WMC_MCLKDIV_1_5, /* 11.2896 MHz */
459 .filter = WMC_SR_48KHZ,
461 [HW_FREQ_48] = /* PLL = 73.728 MHz */
463 .plln = 8 | WMC_PLL_PRESCALE,
464 .pllk1 = 0x2d, /* 11869595 */
465 .pllk2 = 0x08e,
466 .pllk3 = 0x19b,
467 .mclkdiv = WMC_MCLKDIV_1_5, /* 12.2880 MHz */
468 .filter = WMC_SR_48KHZ,
472 unsigned int plln;
473 unsigned int mclkdiv;
475 if ((unsigned)fsel >= HW_NUM_FREQ)
476 fsel = HW_FREQ_DEFAULT;
478 /* Setup filters. */
479 wmc_write(WMC_ADDITIONAL_CTRL, srctrl_table[fsel].filter);
481 plln = srctrl_table[fsel].plln;
482 mclkdiv = srctrl_table[fsel].mclkdiv;
484 if (plln != 0)
486 /* Using PLL to generate SYSCLK */
488 /* Program PLL. */
489 wmc_write(WMC_PLL_N, plln);
490 wmc_write(WMC_PLL_K1, srctrl_table[fsel].pllk1);
491 wmc_write(WMC_PLL_K2, srctrl_table[fsel].pllk2);
492 wmc_write(WMC_PLL_K3, srctrl_table[fsel].pllk3);
494 /* Turn on PLL. */
495 wmc_set(WMC_POWER_MANAGEMENT1, WMC_PLLEN);
497 /* Switch to PLL and set divider. */
498 wmc_write_masked(WMC_CLOCK_GEN_CTRL, mclkdiv | WMC_CLKSEL,
499 WMC_MCLKDIV | WMC_CLKSEL);
501 else
503 /* Switch away from PLL and set MCLKDIV. */
504 wmc_write_masked(WMC_CLOCK_GEN_CTRL, mclkdiv,
505 WMC_MCLKDIV | WMC_CLKSEL);
507 /* Turn off PLL. */
508 wmc_clear(WMC_POWER_MANAGEMENT1, WMC_PLLEN);
512 #ifdef HAVE_RECORDING
513 void audiohw_set_recsrc(int source, bool recording)
515 switch (source)
517 case AUDIO_SRC_PLAYBACK:
518 /* Disable all audio paths but DAC */
519 /* Disable ADCs */
520 wmc_clear(WMC_ADC_CONTROL, WMC_HPFEN);
521 wmc_clear(WMC_POWER_MANAGEMENT2, WMC_ADCENL | WMC_ADCENR);
522 /* Disable bypass */
523 wmc_clear(WMC_LEFT_MIXER_CTRL, WMC_BYPL2LMIX);
524 wmc_clear(WMC_RIGHT_MIXER_CTRL, WMC_BYPR2RMIX);
525 /* Disable IP BOOSTMIX and PGA */
526 wmc_clear(WMC_POWER_MANAGEMENT2, WMC_INPPGAENL | WMC_INPPGAENR |
527 WMC_BOOSTENL | WMC_BOOSTENR);
528 wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA);
529 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
530 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
531 break;
533 case AUDIO_SRC_FMRADIO:
534 if (recording)
536 /* Disable bypass */
537 wmc_clear(WMC_LEFT_MIXER_CTRL, WMC_BYPL2LMIX);
538 wmc_clear(WMC_RIGHT_MIXER_CTRL, WMC_BYPR2RMIX);
539 /* Enable ADCs, IP BOOSTMIX and PGA, route L/R2 through PGA */
540 wmc_set(WMC_POWER_MANAGEMENT2, WMC_ADCENL | WMC_ADCENR |
541 WMC_BOOSTENL | WMC_BOOSTENR | WMC_INPPGAENL |
542 WMC_INPPGAENR);
543 wmc_set(WMC_ADC_CONTROL, WMC_ADCOSR | WMC_HPFEN);
544 /* PGA at 0dB with +20dB boost */
545 wmc_write_masked(WMC_LEFT_INP_PGA_GAIN_CTRL, 0x10, WMC_AVOL);
546 wmc_write_masked(WMC_RIGHT_INP_PGA_GAIN_CTRL, 0x10, WMC_AVOL);
547 wmc_set(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
548 wmc_set(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
549 /* Connect L/R2 inputs to PGA */
550 wmc_set(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA);
552 else
554 /* Disable PGA and ADC, enable IP BOOSTMIX, route L/R2 directly to
555 * IP BOOSTMIX */
556 wmc_clear(WMC_ADC_CONTROL, WMC_HPFEN);
557 wmc_write_masked(WMC_POWER_MANAGEMENT2, WMC_BOOSTENL | WMC_BOOSTENR,
558 WMC_BOOSTENL | WMC_BOOSTENR | WMC_INPPGAENL |
559 WMC_INPPGAENR | WMC_ADCENL | WMC_ADCENR);
560 wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA);
561 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
562 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
563 /* Enable bypass to L/R mixers */
564 wmc_set(WMC_LEFT_MIXER_CTRL, WMC_BYPL2LMIX);
565 wmc_set(WMC_RIGHT_MIXER_CTRL, WMC_BYPR2RMIX);
567 break;
571 void audiohw_set_recvol(int left, int right, int type)
573 switch (type)
575 case AUDIO_GAIN_LINEIN:
576 wmc_write_masked(WMC_LEFT_ADC_DIGITAL_VOL, left + 239, WMC_DVOL);
577 wmc_write_masked(WMC_RIGHT_ADC_DIGITAL_VOL, right + 239, WMC_DVOL);
578 return;
581 #endif /* HAVE_RECORDING */