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*/
32 /* TODO: Define/refine an API for special hardware steps outside the
33 * main codec driver such as special GPIO handling. */
34 /* NOTE: Much of the volume code is very interdependent and calibrated for
35 * the Gigabeat S. If you change anything for another device that uses this
36 * file it may break things. */
37 extern void audiohw_enable_headphone_jack(bool enable
);
39 const struct sound_settings_info audiohw_settings
[] =
41 [SOUND_VOLUME
] = {"dB", 0, 1, -90, 6, -25},
42 [SOUND_BALANCE
] = {"%", 0, 1,-100, 100, 0},
43 [SOUND_CHANNELS
] = {"", 0, 1, 0, 5, 0},
44 [SOUND_STEREO_WIDTH
] = {"%", 0, 5, 0, 250, 100},
45 [SOUND_EQ_BAND1_GAIN
] = {"dB", 0, 1, -12, 12, 0},
46 [SOUND_EQ_BAND2_GAIN
] = {"dB", 0, 1, -12, 12, 0},
47 [SOUND_EQ_BAND3_GAIN
] = {"dB", 0, 1, -12, 12, 0},
48 [SOUND_EQ_BAND4_GAIN
] = {"dB", 0, 1, -12, 12, 0},
49 [SOUND_EQ_BAND5_GAIN
] = {"dB", 0, 1, -12, 12, 0},
50 [SOUND_EQ_BAND1_FREQUENCY
] = {"", 0, 1, 0, 3, 0},
51 [SOUND_EQ_BAND2_FREQUENCY
] = {"", 0, 1, 0, 3, 0},
52 [SOUND_EQ_BAND3_FREQUENCY
] = {"", 0, 1, 0, 3, 0},
53 [SOUND_EQ_BAND4_FREQUENCY
] = {"", 0, 1, 0, 3, 0},
54 [SOUND_EQ_BAND5_FREQUENCY
] = {"", 0, 1, 0, 3, 0},
55 [SOUND_EQ_BAND2_WIDTH
] = {"", 0, 1, 0, 1, 0},
56 [SOUND_EQ_BAND3_WIDTH
] = {"", 0, 1, 0, 1, 0},
57 [SOUND_EQ_BAND4_WIDTH
] = {"", 0, 1, 0, 1, 0},
58 [SOUND_DEPTH_3D
] = {"%", 0, 1, 0, 15, 0},
60 /* Digital: -119.0dB to +8.0dB in 0.5dB increments
61 * Analog: Relegated to volume control
62 * Circumstances unfortunately do not allow a great deal of positive
64 [SOUND_LEFT_GAIN
] = {"dB", 1, 1,-238, 16, 0},
65 [SOUND_RIGHT_GAIN
] = {"dB", 1, 1,-238, 16, 0},
67 [SOUND_MIC_GAIN
] = {"dB", 1, 1,-238, 16, 0},
72 static uint16_t wmc_regs
[WMC_NUM_REGISTERS
] =
74 /* Initialized with post-reset default values - the 2-wire interface
75 * cannot be read. Or-in additional bits desired for some registers. */
76 [0 ... WMC_NUM_REGISTERS
-1] = 0x8000, /* To ID invalids in gaps */
77 [WMC_SOFTWARE_RESET
] = 0x000,
78 [WMC_POWER_MANAGEMENT1
] = 0x000,
79 [WMC_POWER_MANAGEMENT2
] = 0x000,
80 [WMC_POWER_MANAGEMENT3
] = 0x000,
81 [WMC_AUDIO_INTERFACE
] = 0x050,
82 [WMC_COMPANDING_CTRL
] = 0x000,
83 [WMC_CLOCK_GEN_CTRL
] = 0x140,
84 [WMC_ADDITIONAL_CTRL
] = 0x000,
86 [WMC_JACK_DETECT_CONTROL1
] = 0x000,
87 [WMC_DAC_CONTROL
] = 0x000,
88 [WMC_LEFT_DAC_DIGITAL_VOL
] = 0x0ff, /* Latch left first */
89 [WMC_RIGHT_DAC_DIGITAL_VOL
] = 0x0ff | WMC_VU
,
90 [WMC_JACK_DETECT_CONTROL2
] = 0x000,
91 [WMC_ADC_CONTROL
] = 0x100,
92 [WMC_LEFT_ADC_DIGITAL_VOL
] = 0x0ff, /* Latch left first */
93 [WMC_RIGHT_ADC_DIGITAL_VOL
] = 0x0ff | WMC_VU
,
94 [WMC_EQ1_LOW_SHELF
] = 0x12c,
95 [WMC_EQ2_PEAK1
] = 0x02c,
96 [WMC_EQ3_PEAK2
] = 0x02c,
97 [WMC_EQ4_PEAK3
] = 0x02c,
98 [WMC_EQ5_HIGH_SHELF
] = 0x02c,
99 [WMC_DAC_LIMITER1
] = 0x032,
100 [WMC_DAC_LIMITER2
] = 0x000,
101 [WMC_NOTCH_FILTER1
] = 0x000,
102 [WMC_NOTCH_FILTER2
] = 0x000,
103 [WMC_NOTCH_FILTER3
] = 0x000,
104 [WMC_NOTCH_FILTER4
] = 0x000,
105 [WMC_ALC_CONTROL1
] = 0x038,
106 [WMC_ALC_CONTROL2
] = 0x00b,
107 [WMC_ALC_CONTROL3
] = 0x032,
108 [WMC_NOISE_GATE
] = 0x000,
110 [WMC_PLL_K1
] = 0x00c,
111 [WMC_PLL_K2
] = 0x093,
112 [WMC_PLL_K3
] = 0x0e9,
113 [WMC_3D_CONTROL
] = 0x000,
114 [WMC_BEEP_CONTROL
] = 0x000,
115 [WMC_INPUT_CTRL
] = 0x033,
116 [WMC_LEFT_INP_PGA_GAIN_CTRL
] = 0x010 | WMC_ZC
, /* Latch left first */
117 [WMC_RIGHT_INP_PGA_GAIN_CTRL
] = 0x010 | WMC_VU
| WMC_ZC
,
118 [WMC_LEFT_ADC_BOOST_CTRL
] = 0x100,
119 [WMC_RIGHT_ADC_BOOST_CTRL
] = 0x100,
120 [WMC_OUTPUT_CTRL
] = 0x002,
121 [WMC_LEFT_MIXER_CTRL
] = 0x001,
122 [WMC_RIGHT_MIXER_CTRL
] = 0x001,
123 [WMC_LOUT1_HP_VOLUME_CTRL
] = 0x039 | WMC_ZC
, /* Latch left first */
124 [WMC_ROUT1_HP_VOLUME_CTRL
] = 0x039 | WMC_VU
| WMC_ZC
,
125 [WMC_LOUT2_SPK_VOLUME_CTRL
] = 0x039 | WMC_ZC
, /* Latch left first */
126 [WMC_ROUT2_SPK_VOLUME_CTRL
] = 0x039 | WMC_VU
| WMC_ZC
,
127 [WMC_OUT3_MIXER_CTRL
] = 0x001,
128 [WMC_OUT4_MONO_MIXER_CTRL
] = 0x001,
137 unsigned char ahw_mute
;
138 unsigned char prescaler
; /* Attenuation */
139 unsigned char eq_on
; /* Enabled */
140 signed char band_gain
[5]; /* Setting */
141 unsigned char enh_3d_prescaler
; /* Attenuation */
142 unsigned char enh_3d_on
; /* Enabled */
143 unsigned char enh_3d
; /* Setting */
153 .band_gain
= { 0, 0, 0, 0, 0 },
154 .enh_3d_prescaler
= 0,
159 static void wmc_write(unsigned int reg
, unsigned int val
)
161 if (reg
>= WMC_NUM_REGISTERS
|| (wmc_regs
[reg
] & 0x8000))
163 logf("wm8978 invalid register: %d", reg
);
167 wmc_regs
[reg
] = val
& ~0x8000;
168 wmcodec_write(reg
, val
);
171 void wmc_set(unsigned int reg
, unsigned int bits
)
173 wmc_write(reg
, wmc_regs
[reg
] | bits
);
176 void wmc_clear(unsigned int reg
, unsigned int bits
)
178 wmc_write(reg
, wmc_regs
[reg
] & ~bits
);
181 static void wmc_write_masked(unsigned int reg
, unsigned int bits
,
184 wmc_write(reg
, (wmc_regs
[reg
] & ~mask
) | (bits
& mask
));
187 /* convert tenth of dB volume (-890..60) to master volume register value
188 * (000000...111111) */
189 int tenthdb2master(int db
)
191 /* -90dB to +6dB 1dB steps (96 levels) 7bits */
192 /* 1100000 == +6dB (0x60,96) */
193 /* 1101010 == 0dB (0x5a,90) */
194 /* 1000001 == -57dB (0x21,33,DAC) */
195 /* 0000001 == -89dB (0x01,01) */
196 /* 0000000 == -90dB (0x00,00,Mute) */
197 if (db
<= VOLUME_MIN
)
203 return (db
- VOLUME_MIN
) / 10;
207 int sound_val2phys(int setting
, int value
)
213 #ifdef HAVE_RECORDING
214 case SOUND_LEFT_GAIN
:
215 case SOUND_RIGHT_GAIN
:
221 case SOUND_EQ_BAND1_GAIN
+0x10000:
222 case SOUND_EQ_BAND2_GAIN
+0x10000:
223 case SOUND_EQ_BAND3_GAIN
+0x10000:
224 case SOUND_EQ_BAND4_GAIN
+0x10000:
225 case SOUND_EQ_BAND5_GAIN
+0x10000:
230 result
= (100 * value
+ 8) / 15;
240 void audiohw_preinit(void)
242 /* 1. Turn on external power supplies. Wait for supply voltage to settle. */
244 /* Step 1 should be completed already. Reset and return all registers to
246 wmcodec_write(WMC_SOFTWARE_RESET
, 0xff);
249 /* 2. Mute all analogue outputs */
250 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
251 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
252 wmc_set(WMC_LOUT2_SPK_VOLUME_CTRL
, WMC_MUTE
);
253 wmc_set(WMC_ROUT2_SPK_VOLUME_CTRL
, WMC_MUTE
);
254 wmc_set(WMC_OUT3_MIXER_CTRL
, WMC_MUTE
);
255 wmc_set(WMC_OUT4_MONO_MIXER_CTRL
, WMC_MUTE
);
257 /* 3. Set L/RMIXEN = 1 and DACENL/R = 1 in register R3. */
258 wmc_write(WMC_POWER_MANAGEMENT3
, WMC_RMIXEN
| WMC_LMIXEN
);
260 /* EQ and 3D applied to DAC (Set before DAC enable!) */
261 wmc_set(WMC_EQ1_LOW_SHELF
, WMC_EQ3DMODE
);
263 wmc_set(WMC_POWER_MANAGEMENT3
, WMC_DACENR
| WMC_DACENL
);
265 /* 4. Set BUFIOEN = 1 and VMIDSEL[1:0] to required value in register
266 * R1. Wait for VMID supply to settle */
267 wmc_write(WMC_POWER_MANAGEMENT1
, WMC_BUFIOEN
| WMC_VMIDSEL_300K
);
270 /* 5. Set BIASEN = 1 in register R1. */
271 wmc_set(WMC_POWER_MANAGEMENT1
, WMC_BIASEN
);
273 /* 6. Set L/ROUTEN = 1 in register R2. */
274 wmc_write(WMC_POWER_MANAGEMENT2
, WMC_LOUT1EN
| WMC_ROUT1EN
);
277 void audiohw_postinit(void)
281 /* 7. Enable other mixers as required */
283 /* 8. Enable other outputs as required */
285 /* 9. Set remaining registers */
286 wmc_write(WMC_AUDIO_INTERFACE
, WMC_WL_16
| WMC_FMT_I2S
);
287 wmc_write(WMC_DAC_CONTROL
, WMC_DACOSR_128
);
289 /* No ADC, no HP filter, no popping */
290 wmc_clear(WMC_ADC_CONTROL
, WMC_HPFEN
);
292 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL
, WMC_PGABOOSTL
);
293 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL
, WMC_PGABOOSTR
);
295 /* Specific to HW clocking */
296 wmc_write_masked(WMC_CLOCK_GEN_CTRL
, WMC_BCLKDIV_4
| WMC_MS
,
297 WMC_BCLKDIV
| WMC_MS
| WMC_CLKSEL
);
298 audiohw_set_frequency(HW_FREQ_DEFAULT
);
300 audiohw_enable_headphone_jack(true);
303 static void get_headphone_levels(int val
, int *dac_p
, int *hp_p
,
304 int *mix_p
, int *boost_p
)
306 int dac
, hp
, mix
, boost
;
317 dac
= 189 + val
/ 3 * 6;
320 boost
= (val
- 18) / 3;
324 dac
= 189 + val
/ 3 * 6;
336 static void sync_prescaler(void)
340 /* Combine all prescaling into a single DAC attenuation */
342 prescaler
= wmc_vol
.prescaler
;
344 if (wmc_vol
.enh_3d_on
)
345 prescaler
+= wmc_vol
.enh_3d_prescaler
;
347 wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL
, wmc_vol
.dac_l
- prescaler
,
349 wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL
, wmc_vol
.dac_r
- prescaler
,
353 void audiohw_set_headphone_vol(int vol_l
, int vol_r
)
355 int prev_l
= wmc_vol
.vol_l
;
356 int prev_r
= wmc_vol
.vol_r
;
357 int dac_l
, dac_r
, hp_l
, hp_r
;
358 int mix_l
, mix_r
, boost_l
, boost_r
;
360 wmc_vol
.vol_l
= vol_l
;
361 wmc_vol
.vol_r
= vol_r
;
363 /* Mixers are synced to provide full volume range on both the analogue
364 * and digital pathways */
365 get_headphone_levels(vol_l
, &dac_l
, &hp_l
, &mix_l
, &boost_l
);
366 get_headphone_levels(vol_r
, &dac_r
, &hp_r
, &mix_r
, &boost_r
);
368 wmc_vol
.dac_l
= dac_l
;
369 wmc_vol
.dac_r
= dac_r
;
373 wmc_write_masked(WMC_LEFT_MIXER_CTRL
, mix_l
<< WMC_BYPLMIXVOL_POS
,
375 wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL
,
376 boost_l
<< WMC_L2_2BOOSTVOL_POS
, WMC_L2_2BOOSTVOL
);
377 wmc_write_masked(WMC_LOUT1_HP_VOLUME_CTRL
, hp_l
, WMC_AVOL
);
379 wmc_write_masked(WMC_RIGHT_MIXER_CTRL
, mix_r
<< WMC_BYPRMIXVOL_POS
,
381 wmc_write_masked(WMC_RIGHT_ADC_BOOST_CTRL
,
382 boost_r
<< WMC_R2_2BOOSTVOL_POS
, WMC_R2_2BOOSTVOL
);
383 wmc_write_masked(WMC_ROUT1_HP_VOLUME_CTRL
, hp_r
, WMC_AVOL
);
387 /* Not muted and going up from mute level? */
388 if (prev_l
<= 0 && !wmc_vol
.ahw_mute
)
389 wmc_clear(WMC_LOUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
393 /* Going to mute level? */
395 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
400 /* Not muted and going up from mute level? */
401 if (prev_r
<= 0 && !wmc_vol
.ahw_mute
)
402 wmc_clear(WMC_ROUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
406 /* Going to mute level? */
408 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
412 static void audiohw_mute(bool mute
)
414 wmc_vol
.ahw_mute
= mute
;
416 /* No DAC mute here, please - take care of each enabled output. */
419 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
420 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
424 /* Unmute outputs not at mute level */
425 if (wmc_vol
.vol_l
> 0)
426 wmc_clear(WMC_LOUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
428 if (wmc_vol
.vol_r
> 0)
429 wmc_clear(WMC_ROUT1_HP_VOLUME_CTRL
, WMC_MUTE
);
433 /* Equalizer - set the eq band level -12 to +12 dB. */
434 void audiohw_set_eq_band_gain(unsigned int band
, int val
)
439 wmc_vol
.band_gain
[band
] = val
;
444 wmc_write_masked(band
+ WMC_EQ1_LOW_SHELF
, 12 - val
, WMC_EQG
);
447 /* Equalizer - set the eq band frequency index. */
448 void audiohw_set_eq_band_frequency(unsigned int band
, int val
)
453 wmc_write_masked(band
+ WMC_EQ1_LOW_SHELF
,
454 val
<< WMC_EQC_POS
, WMC_EQC
);
457 /* Equalizer - set bandwidth for peaking filters to wide (!= 0) or
458 * narrow (0); only valid for peaking filter bands 1-3. */
459 void audiohw_set_eq_band_width(unsigned int band
, int val
)
461 if (band
< 1 || band
> 3)
464 wmc_write_masked(band
+ WMC_EQ1_LOW_SHELF
,
465 (val
== 0) ? 0 : WMC_EQBW
, WMC_EQBW
);
468 /* Set prescaler to prevent clipping the output amp when applying positive
469 * gain to EQ bands. */
470 void audiohw_set_prescaler(int val
)
472 wmc_vol
.prescaler
= val
/ 5; /* centibels->semi-decibels */
476 /* Set the depth of the 3D effect */
477 void audiohw_set_depth_3d(int val
)
479 wmc_vol
.enh_3d_prescaler
= 10*val
/ 15; /* -5 dB @ full setting */
480 wmc_vol
.enh_3d
= val
;
482 if (!wmc_vol
.enh_3d_on
)
486 wmc_write_masked(WMC_3D_CONTROL
, val
, WMC_DEPTH3D
);
489 void audiohw_close(void)
491 /* 1. Mute all analogue outputs */
493 audiohw_enable_headphone_jack(false);
495 /* 2. Disable power management register 1. R1 = 00 */
496 wmc_write(WMC_POWER_MANAGEMENT1
, 0x000);
498 /* 3. Disable power management register 2. R2 = 00 */
499 wmc_write(WMC_POWER_MANAGEMENT2
, 0x000);
501 /* 4. Disable power management register 3. R3 = 00 */
502 wmc_write(WMC_POWER_MANAGEMENT3
, 0x000);
504 /* 5. Remove external power supplies. */
507 void audiohw_set_frequency(int fsel
)
509 extern const struct wmc_srctrl_entry wmc_srctrl_table
[HW_NUM_FREQ
];
511 unsigned int mclkdiv
;
513 if ((unsigned)fsel
>= HW_NUM_FREQ
)
514 fsel
= HW_FREQ_DEFAULT
;
517 wmc_write(WMC_ADDITIONAL_CTRL
, wmc_srctrl_table
[fsel
].filter
);
519 plln
= wmc_srctrl_table
[fsel
].plln
;
520 mclkdiv
= wmc_srctrl_table
[fsel
].mclkdiv
;
524 /* Using PLL to generate SYSCLK */
527 wmc_write(WMC_PLL_N
, plln
);
528 wmc_write(WMC_PLL_K1
, wmc_srctrl_table
[fsel
].pllk1
);
529 wmc_write(WMC_PLL_K2
, wmc_srctrl_table
[fsel
].pllk2
);
530 wmc_write(WMC_PLL_K3
, wmc_srctrl_table
[fsel
].pllk3
);
533 wmc_set(WMC_POWER_MANAGEMENT1
, WMC_PLLEN
);
535 /* Switch to PLL and set divider. */
536 wmc_write_masked(WMC_CLOCK_GEN_CTRL
, mclkdiv
| WMC_CLKSEL
,
537 WMC_MCLKDIV
| WMC_CLKSEL
);
541 /* Switch away from PLL and set MCLKDIV. */
542 wmc_write_masked(WMC_CLOCK_GEN_CTRL
, mclkdiv
,
543 WMC_MCLKDIV
| WMC_CLKSEL
);
546 wmc_clear(WMC_POWER_MANAGEMENT1
, WMC_PLLEN
);
550 void audiohw_enable_tone_controls(bool enable
)
553 wmc_vol
.eq_on
= enable
;
554 audiohw_set_prescaler(wmc_vol
.prescaler
);
556 for (i
= 0; i
< 5; i
++)
557 audiohw_set_eq_band_gain(i
, wmc_vol
.band_gain
[i
]);
560 void audiohw_enable_depth_3d(bool enable
)
562 wmc_vol
.enh_3d_on
= enable
;
563 audiohw_set_depth_3d(wmc_vol
.enh_3d
);
566 #ifdef HAVE_RECORDING
567 void audiohw_set_recsrc(int source
, bool recording
)
571 case AUDIO_SRC_PLAYBACK
:
572 /* Disable all audio paths but DAC */
574 wmc_clear(WMC_ADC_CONTROL
, WMC_HPFEN
);
575 wmc_clear(WMC_POWER_MANAGEMENT2
, WMC_ADCENL
| WMC_ADCENR
);
577 wmc_clear(WMC_LEFT_MIXER_CTRL
, WMC_BYPL2LMIX
);
578 wmc_clear(WMC_RIGHT_MIXER_CTRL
, WMC_BYPR2RMIX
);
579 /* Disable IP BOOSTMIX and PGA */
580 wmc_clear(WMC_POWER_MANAGEMENT2
, WMC_INPPGAENL
| WMC_INPPGAENR
|
581 WMC_BOOSTENL
| WMC_BOOSTENR
);
582 wmc_clear(WMC_INPUT_CTRL
, WMC_L2_2INPPGA
| WMC_R2_2INPPGA
|
583 WMC_LIP2INPPGA
| WMC_RIP2INPPGA
|
584 WMC_LIN2INPPGA
| WMC_RIN2INPPGA
);
585 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL
, WMC_PGABOOSTL
);
586 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL
, WMC_PGABOOSTR
);
589 case AUDIO_SRC_FMRADIO
:
593 wmc_clear(WMC_LEFT_MIXER_CTRL
, WMC_BYPL2LMIX
);
594 wmc_clear(WMC_RIGHT_MIXER_CTRL
, WMC_BYPR2RMIX
);
595 /* Enable ADCs, IP BOOSTMIX and PGA, route L/R2 through PGA */
596 wmc_set(WMC_POWER_MANAGEMENT2
, WMC_ADCENL
| WMC_ADCENR
|
597 WMC_BOOSTENL
| WMC_BOOSTENR
| WMC_INPPGAENL
|
599 wmc_set(WMC_ADC_CONTROL
, WMC_ADCOSR
| WMC_HPFEN
);
600 /* PGA at 0dB with +20dB boost */
601 wmc_write_masked(WMC_LEFT_INP_PGA_GAIN_CTRL
, 0x10, WMC_AVOL
);
602 wmc_write_masked(WMC_RIGHT_INP_PGA_GAIN_CTRL
, 0x10, WMC_AVOL
);
603 wmc_set(WMC_LEFT_ADC_BOOST_CTRL
, WMC_PGABOOSTL
);
604 wmc_set(WMC_RIGHT_ADC_BOOST_CTRL
, WMC_PGABOOSTR
);
605 /* Connect L/R2 inputs to PGA */
606 wmc_write_masked(WMC_INPUT_CTRL
, WMC_L2_2INPPGA
| WMC_R2_2INPPGA
|
607 WMC_LIN2INPPGA
| WMC_RIN2INPPGA
,
608 WMC_L2_2INPPGA
| WMC_R2_2INPPGA
|
609 WMC_LIP2INPPGA
| WMC_RIP2INPPGA
|
610 WMC_LIN2INPPGA
| WMC_RIN2INPPGA
);
614 /* Disable PGA and ADC, enable IP BOOSTMIX, route L/R2 directly to
616 wmc_clear(WMC_ADC_CONTROL
, WMC_HPFEN
);
617 wmc_write_masked(WMC_POWER_MANAGEMENT2
, WMC_BOOSTENL
| WMC_BOOSTENR
,
618 WMC_BOOSTENL
| WMC_BOOSTENR
| WMC_INPPGAENL
|
619 WMC_INPPGAENR
| WMC_ADCENL
| WMC_ADCENR
);
620 wmc_clear(WMC_INPUT_CTRL
, WMC_L2_2INPPGA
| WMC_R2_2INPPGA
|
621 WMC_LIP2INPPGA
| WMC_RIP2INPPGA
|
622 WMC_LIN2INPPGA
| WMC_RIN2INPPGA
);
623 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL
, WMC_PGABOOSTL
);
624 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL
, WMC_PGABOOSTR
);
625 /* Enable bypass to L/R mixers */
626 wmc_set(WMC_LEFT_MIXER_CTRL
, WMC_BYPL2LMIX
);
627 wmc_set(WMC_RIGHT_MIXER_CTRL
, WMC_BYPR2RMIX
);
633 void audiohw_set_recvol(int left
, int right
, int type
)
637 case AUDIO_GAIN_LINEIN
:
638 wmc_write_masked(WMC_LEFT_ADC_DIGITAL_VOL
, left
+ 239, WMC_DVOL
);
639 wmc_write_masked(WMC_RIGHT_ADC_DIGITAL_VOL
, right
+ 239, WMC_DVOL
);
643 #endif /* HAVE_RECORDING */