1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
28 /*#define LOGF_ENABLE*/
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},
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
51 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-238, 16, 0},
52 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-238, 16, 0},
54 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-238, 16, 0},
58 [SOUND_BASS_CUTOFF
] = {"", 0, 1, 1, 4, 1},
59 [SOUND_TREBLE_CUTOFF
] = {"", 0, 1, 1, 4, 1},
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,
77 [WMC_JACK_DETECT_CONTROL1
] = 0x000,
78 [WMC_DAC_CONTROL
] = 0x000,
79 [WMC_LEFT_DAC_DIGITAL_VOL
] = 0x0ff | WMC_VU
,
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 | WMC_VU
,
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,
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_VU
| WMC_ZC
,
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_VU
| WMC_ZC
,
115 [WMC_ROUT1_HP_VOLUME_CTRL
] = 0x039 | WMC_VU
| WMC_ZC
,
116 [WMC_LOUT2_SPK_VOLUME_CTRL
] = 0x039 | WMC_VU
| WMC_ZC
,
117 [WMC_ROUT2_SPK_VOLUME_CTRL
] = 0x039 | WMC_VU
| WMC_ZC
,
118 [WMC_OUT3_MIXER_CTRL
] = 0x001,
119 [WMC_OUT4_MONO_MIXER_CTRL
] = 0x001,
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
);
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
,
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
)
176 return (db
- VOLUME_MIN
) / 10;
180 int sound_val2phys(int setting
, int value
)
186 #ifdef HAVE_RECORDING
187 case SOUND_LEFT_GAIN
:
188 case SOUND_RIGHT_GAIN
:
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
207 wmcodec_write(WMC_SOFTWARE_RESET
, 0xff);
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
);
227 /* 5. Set BIASEN = 1 in register R1. */
228 wmc_set(WMC_POWER_MANAGEMENT1
, WMC_BIASEN
);
231 void audiohw_postinit(void)
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
;
274 dac
= 189 + val
/ 3 * 6;
277 boost
= (val
- 18) / 3;
281 dac
= 189 + val
/ 3 * 6;
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
, WMC_BYPLMIXVOLw(mix_l
),
310 wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL
,
311 WMC_L2_2BOOSTVOLw(boost_l
), 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
, WMC_BYPRMIXVOLw(mix_r
),
317 wmc_write_masked(WMC_RIGHT_ADC_BOOST_CTRL
,
318 WMC_R2_2BOOSTVOLw(boost_r
), 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
);
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
);
330 /* Going to mute level? */
332 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
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
);
343 /* Going to mute level? */
345 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
349 void audiohw_close(void)
351 /* 1. Mute all analogue outputs */
353 audiohw_enable_headphone_jack(false);
355 /* 2. Disable power management register 1. R1 = 00 */
356 wmc_write(WMC_POWER_MANAGEMENT1
, 0x000);
358 /* 3. Disable power management register 2. R2 = 00 */
359 wmc_write(WMC_POWER_MANAGEMENT2
, 0x000);
361 /* 4. Disable power management register 3. R3 = 00 */
362 wmc_write(WMC_POWER_MANAGEMENT3
, 0x000);
364 /* 5. Remove external power supplies. */
367 void audiohw_mute(bool mute
)
369 wmc_vol
.ahw_mute
= mute
;
371 /* No DAC mute here, please - take care of each enabled output. */
374 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
375 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
379 /* Unmute outputs not at mute level */
380 if (wmc_vol
.vol_l
> 0)
381 wmc_clear(WMC_LOUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
383 if (wmc_vol
.vol_r
> 0)
384 wmc_clear(WMC_ROUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
388 void audiohw_set_frequency(int fsel
)
390 /* For 16.9344MHz MCLK, codec as master. */
397 unsigned char mclkdiv
;
398 unsigned char filter
;
399 } srctrl_table
[HW_NUM_FREQ
] =
401 [HW_FREQ_8
] = /* PLL = 65.536MHz */
403 .plln
= WMC_PLLNw(7) | WMC_PLL_PRESCALE
,
404 .pllk1
= WMC_PLLK_23_18w(12414886ul >> 18),
405 .pllk2
= WMC_PLLK_17_9w(12414886ul >> 9),
406 .pllk3
= WMC_PLLK_8_0w(12414886ul >> 0),
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
= WMC_PLLNw(8) | WMC_PLL_PRESCALE
,
418 .pllk1
= WMC_PLLK_23_18w(11869595ul >> 18),
419 .pllk2
= WMC_PLLK_17_9w(11869595ul >> 9),
420 .pllk3
= WMC_PLLK_8_0w(11869595ul >> 0),
421 .mclkdiv
= WMC_MCLKDIV_6
, /* 3.0720 MHz */
422 .filter
= WMC_SR_12KHZ
,
424 [HW_FREQ_16
] = /* PLL = 65.536MHz */
426 .plln
= WMC_PLLNw(7) | WMC_PLL_PRESCALE
,
427 .pllk1
= WMC_PLLK_23_18w(12414886ul >> 18),
428 .pllk2
= WMC_PLLK_17_9w(12414886ul >> 9),
429 .pllk3
= WMC_PLLK_8_0w(12414886ul >> 0),
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
= WMC_PLLNw(8) | WMC_PLL_PRESCALE
,
441 .pllk1
= WMC_PLLK_23_18w(11869595ul >> 18),
442 .pllk2
= WMC_PLLK_17_9w(11869595ul >> 9),
443 .pllk3
= WMC_PLLK_8_0w(11869595ul >> 0),
444 .mclkdiv
= WMC_MCLKDIV_3
, /* 6.1440 MHz */
445 .filter
= WMC_SR_24KHZ
,
447 [HW_FREQ_32
] = /* PLL = 65.536MHz */
449 .plln
= WMC_PLLNw(7) | WMC_PLL_PRESCALE
,
450 .pllk1
= WMC_PLLK_23_18w(12414886ul >> 18),
451 .pllk2
= WMC_PLLK_17_9w(12414886ul >> 9),
452 .pllk3
= WMC_PLLK_8_0w(12414886ul >> 0),
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
= WMC_PLLNw(8) | WMC_PLL_PRESCALE
,
464 .pllk1
= WMC_PLLK_23_18w(11869595ul >> 18),
465 .pllk2
= WMC_PLLK_17_9w(11869595ul >> 9),
466 .pllk3
= WMC_PLLK_8_0w(11869595ul >> 0),
467 .mclkdiv
= WMC_MCLKDIV_1_5
, /* 12.2880 MHz */
468 .filter
= WMC_SR_48KHZ
,
473 unsigned int mclkdiv
;
475 if ((unsigned)fsel
>= HW_NUM_FREQ
)
476 fsel
= HW_FREQ_DEFAULT
;
479 wmc_write(WMC_ADDITIONAL_CTRL
, srctrl_table
[fsel
].filter
);
481 plln
= srctrl_table
[fsel
].plln
;
482 mclkdiv
= srctrl_table
[fsel
].mclkdiv
;
486 /* Using PLL to generate SYSCLK */
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
);
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
);
503 /* Switch away from PLL and set MCLKDIV. */
504 wmc_write_masked(WMC_CLOCK_GEN_CTRL
, mclkdiv
,
505 WMC_MCLKDIV
| WMC_CLKSEL
);
508 wmc_clear(WMC_POWER_MANAGEMENT1
, WMC_PLLEN
);
512 #ifdef HAVE_RECORDING
513 void audiohw_set_recsrc(int source
, bool recording
)
517 case AUDIO_SRC_PLAYBACK
:
518 /* Disable all audio paths but DAC */
520 wmc_clear(WMC_ADC_CONTROL
, WMC_HPFEN
);
521 wmc_clear(WMC_POWER_MANAGEMENT2
, WMC_ADCENL
| WMC_ADCENR
);
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
);
533 case AUDIO_SRC_FMRADIO
:
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
|
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
);
554 /* Disable PGA and ADC, enable IP BOOSTMIX, route L/R2 directly to
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
);
571 void audiohw_set_recvol(int left
, int right
, int 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
);
581 #endif /* HAVE_RECORDING */