Bring consistency to pcm implementation and samplerate handling. Less low-level dupli...
[kugel-rb.git] / firmware / drivers / audio / wm8978.c
blobd8bf05063f0925a18aa5cbd08ed6447f2b9e5545
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 /* #define to help adjust lower volume limit */
32 #define HW_VOL_MIN 0
33 #define HW_VOL_MUTE 0
34 #define HW_VOL_MAX 96
35 #define HW_VOL_ANA_MIN 0
36 #define HW_VOL_ANA_MAX 63
37 #define HW_VOL_DIG_MAX 255
38 #define HW_VOL_DIG_THRESHOLD (HW_VOL_MAX - HW_VOL_ANA_MAX)
39 #define HW_VOL_DIG_MIN (HW_VOL_DIG_MAX - 2*HW_VOL_DIG_THRESHOLD)
41 /* TODO: Define/refine an API for special hardware steps outside the
42 * main codec driver such as special GPIO handling. */
43 extern void audiohw_enable_headphone_jack(bool enable);
45 const struct sound_settings_info audiohw_settings[] =
47 [SOUND_VOLUME] = {"dB", 0, 1, -90, 6, -25},
48 [SOUND_BASS] = {"dB", 0, 1, -12, 12, 0},
49 [SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 0},
50 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
51 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
52 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
53 #ifdef HAVE_RECORDING
54 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0},
55 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0},
56 #if 0
57 [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16},
58 #endif
59 #endif
60 #if 0
61 [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1},
62 [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1},
63 #endif
66 static uint16_t wmc_regs[WMC_NUM_REGISTERS] =
68 /* Initialized with post-reset default values - the 2-wire interface
69 * cannot be read. Or-in additional bits desired for some registers. */
70 [0 ... WMC_NUM_REGISTERS-1] = 0x8000, /* To ID invalids in gaps */
71 [WMC_SOFTWARE_RESET] = 0x000,
72 [WMC_POWER_MANAGEMENT1] = 0x000,
73 [WMC_POWER_MANAGEMENT2] = 0x000,
74 [WMC_POWER_MANAGEMENT3] = 0x000,
75 [WMC_AUDIO_INTERFACE] = 0x050,
76 [WMC_COMPANDING_CTRL] = 0x000,
77 [WMC_CLOCK_GEN_CTRL] = 0x140,
78 [WMC_ADDITIONAL_CTRL] = 0x000,
79 [WMC_GPIO] = 0x000,
80 [WMC_JACK_DETECT_CONTROL1] = 0x000,
81 [WMC_DAC_CONTROL] = 0x000,
82 [WMC_LEFT_DAC_DIGITAL_VOL] = 0x0ff | WMC_VU,
83 [WMC_RIGHT_DAC_DIGITAL_VOL] = 0x0ff | WMC_VU,
84 [WMC_JACK_DETECT_CONTROL2] = 0x000,
85 [WMC_ADC_CONTROL] = 0x100,
86 [WMC_LEFT_ADC_DIGITAL_VOL] = 0x0ff | WMC_VU,
87 [WMC_RIGHT_ADC_DIGITAL_VOL] = 0x0ff | WMC_VU,
88 [WMC_EQ1_LOW_SHELF] = 0x12c,
89 [WMC_EQ2_PEAK1] = 0x02c,
90 [WMC_EQ3_PEAK2] = 0x02c,
91 [WMC_EQ4_PEAK3] = 0x02c,
92 [WMC_EQ5_HIGH_SHELF] = 0x02c,
93 [WMC_DAC_LIMITER1] = 0x032,
94 [WMC_DAC_LIMITER2] = 0x000,
95 [WMC_NOTCH_FILTER1] = 0x000,
96 [WMC_NOTCH_FILTER2] = 0x000,
97 [WMC_NOTCH_FILTER3] = 0x000,
98 [WMC_NOTCH_FILTER4] = 0x000,
99 [WMC_ALC_CONTROL1] = 0x038,
100 [WMC_ALC_CONTROL2] = 0x00b,
101 [WMC_ALC_CONTROL3] = 0x032,
102 [WMC_NOISE_GATE] = 0x000,
103 [WMC_PLL_N] = 0x008,
104 [WMC_PLL_K1] = 0x00c,
105 [WMC_PLL_K2] = 0x093,
106 [WMC_PLL_K3] = 0x0e9,
107 [WMC_3D_CONTROL] = 0x000,
108 [WMC_BEEP_CONTROL] = 0x000,
109 [WMC_INPUT_CTRL] = 0x033,
110 [WMC_LEFT_INP_PGA_GAIN_CTRL] = 0x010,
111 [WMC_RIGHT_INP_PGA_GAIN_CTRL] = 0x010,
112 [WMC_LEFT_ADC_BOOST_CTRL] = 0x100,
113 [WMC_RIGHT_ADC_BOOST_CTRL] = 0x100,
114 [WMC_OUTPUT_CTRL] = 0x002,
115 [WMC_LEFT_MIXER_CTRL] = 0x001,
116 [WMC_RIGHT_MIXER_CTRL] = 0x001,
117 [WMC_LOUT1_HP_VOLUME_CTRL] = 0x039 | WMC_VU | WMC_ZC,
118 [WMC_ROUT1_HP_VOLUME_CTRL] = 0x039 | WMC_VU | WMC_ZC,
119 [WMC_LOUT2_SPK_VOLUME_CTRL] = 0x039 | WMC_VU | WMC_ZC,
120 [WMC_ROUT2_SPK_VOLUME_CTRL] = 0x039 | WMC_VU | WMC_ZC,
121 [WMC_OUT3_MIXER_CTRL] = 0x001,
122 [WMC_OUT4_MONO_MIXER_CTRL] = 0x001,
125 struct
127 int vol_l;
128 int vol_r;
129 bool ahw_mute;
130 } wmc_vol =
132 HW_VOL_MUTE, HW_VOL_MUTE, false
135 static void wmc_write(unsigned int reg, unsigned int val)
137 if (reg >= WMC_NUM_REGISTERS || (wmc_regs[reg] & 0x8000))
139 logf("wm8978 invalid register: %d", reg);
140 return;
143 wmc_regs[reg] = val & ~0x8000;
144 wmcodec_write(reg, val);
147 void wmc_set(unsigned int reg, unsigned int bits)
149 wmc_write(reg, wmc_regs[reg] | bits);
152 void wmc_clear(unsigned int reg, unsigned int bits)
154 wmc_write(reg, wmc_regs[reg] & ~bits);
157 static void wmc_write_masked(unsigned int reg, unsigned int bits,
158 unsigned int mask)
160 wmc_write(reg, (wmc_regs[reg] & ~mask) | (bits & mask));
163 /* convert tenth of dB volume (-890..60) to master volume register value
164 * (000000...111111) */
165 int tenthdb2master(int db)
167 /* -90dB to +6dB 1dB steps (96 levels) 7bits */
168 /* 1100000 == +6dB (0x60,96) */
169 /* 1101010 == 0dB (0x5a,90) */
170 /* 1000001 == -57dB (0x21,33,DAC) */
171 /* 0000001 == -89dB (0x01,01) */
172 /* 0000000 == -90dB (0x00,00,Mute) */
173 if (db <= VOLUME_MIN)
175 return 0x0;
177 else
179 return (db - VOLUME_MIN) / 10;
183 void audiohw_preinit(void)
185 /* 1. Turn on external power supplies. Wait for supply voltage to settle. */
187 /* Step 1 should be completed already. Reset and return all registers to
188 * defaults */
189 wmcodec_write(WMC_SOFTWARE_RESET, 0xff);
190 sleep(HZ/10);
192 /* 2. Mute all analogue outputs */
193 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE | HW_VOL_ANA_MIN);
194 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE | HW_VOL_ANA_MIN);
195 wmc_set(WMC_LOUT2_SPK_VOLUME_CTRL, WMC_MUTE);
196 wmc_set(WMC_ROUT2_SPK_VOLUME_CTRL, WMC_MUTE);
197 wmc_set(WMC_OUT3_MIXER_CTRL, WMC_MUTE);
198 wmc_set(WMC_OUT4_MONO_MIXER_CTRL, WMC_MUTE);
199 wmc_set(WMC_INPUT_CTRL, 0x000);
201 /* 3. Set L/RMIXEN = 1 and DACENL/R = 1 in register R3. */
202 wmc_write(WMC_POWER_MANAGEMENT3,
203 WMC_RMIXEN | WMC_LMIXEN | WMC_DACENR | WMC_DACENL);
205 /* 4. Set BUFIOEN = 1 and VMIDSEL[1:0] to required value in register
206 * R1. Wait for VMID supply to settle */
207 wmc_write(WMC_POWER_MANAGEMENT1, WMC_BUFIOEN | WMC_VMIDSEL_300K);
208 sleep(HZ/10);
210 /* 5. Set BIASEN = 1 in register R1. */
211 wmc_set(WMC_POWER_MANAGEMENT1, WMC_BIASEN);
214 void audiohw_postinit(void)
216 sleep(HZ);
218 /* 6. Set L/ROUTEN = 1 in register R2. */
219 wmc_write(WMC_POWER_MANAGEMENT2, WMC_LOUT1EN | WMC_ROUT1EN);
221 /* 7. Enable other mixers as required */
223 /* 8. Enable other outputs as required */
225 /* 9. Set remaining registers */
226 wmc_write(WMC_AUDIO_INTERFACE, WMC_WL_16 | WMC_FMT_I2S);
227 wmc_write(WMC_DAC_CONTROL, WMC_DACOSR_128 | WMC_AMUTE);
229 wmc_set(WMC_INPUT_CTRL, WMC_R2_2INPPGA | WMC_L2_2INPPGA);
230 wmc_set(WMC_LEFT_INP_PGA_GAIN_CTRL, 0x3f);
231 wmc_set(WMC_RIGHT_INP_PGA_GAIN_CTRL, 0x3f);
232 wmc_set(WMC_LEFT_INP_PGA_GAIN_CTRL, 1<<8);
233 wmc_set(WMC_RIGHT_INP_PGA_GAIN_CTRL, 1<<8);
234 wmc_set(WMC_LEFT_ADC_BOOST_CTRL, (7<<3));
235 wmc_set(WMC_RIGHT_ADC_BOOST_CTRL, (7<<3));
237 /* Specific to HW clocking */
238 wmc_write_masked(WMC_CLOCK_GEN_CTRL, WMC_BCLKDIV_4 | WMC_MS,
239 WMC_BCLKDIV | WMC_MS | WMC_CLKSEL);
240 audiohw_set_frequency(HW_FREQ_DEFAULT);
242 /* ADC silenced */
243 wmc_write_masked(WMC_LEFT_ADC_DIGITAL_VOL, 0x00, WMC_DVOL);
244 wmc_write_masked(WMC_RIGHT_ADC_DIGITAL_VOL, 0x00, WMC_DVOL);
246 audiohw_enable_headphone_jack(true);
249 void audiohw_set_headphone_vol(int vol_l, int vol_r)
251 int prev_l = wmc_vol.vol_l;
252 int prev_r = wmc_vol.vol_r;
253 int dac_l, dac_r;
255 wmc_vol.vol_l = vol_l;
256 wmc_vol.vol_r = vol_r;
258 /* When analogue volume falls below -57dB (0x00) start attenuating the
259 * DAC volume */
260 if (vol_l >= HW_VOL_DIG_THRESHOLD)
262 if (vol_l > HW_VOL_MAX)
263 vol_l = HW_VOL_MAX;
265 dac_l = HW_VOL_DIG_MAX;
266 vol_l -= HW_VOL_DIG_THRESHOLD;
268 else
270 if (vol_l < HW_VOL_MIN)
271 vol_l = HW_VOL_MIN;
273 dac_l = 2*vol_l + HW_VOL_DIG_MIN;
274 vol_l = HW_VOL_ANA_MIN;
277 if (vol_r >= HW_VOL_DIG_THRESHOLD)
279 if (vol_r > HW_VOL_MAX)
280 vol_r = HW_VOL_MAX;
282 dac_r = HW_VOL_DIG_MAX;
283 vol_r -= HW_VOL_DIG_THRESHOLD;
285 else
287 if (vol_r < HW_VOL_MIN)
288 vol_r = HW_VOL_MIN;
290 dac_r = 2*vol_r + HW_VOL_DIG_MIN;
291 vol_r = HW_VOL_ANA_MIN;
294 /* Have to write both channels always to have the latching work */
295 wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, dac_l, WMC_DVOL);
296 wmc_write_masked(WMC_LOUT1_HP_VOLUME_CTRL, vol_l, WMC_AVOL);
297 wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, dac_r, WMC_DVOL);
298 wmc_write_masked(WMC_ROUT1_HP_VOLUME_CTRL, vol_r, WMC_AVOL);
300 if (wmc_vol.vol_l > HW_VOL_MUTE)
302 /* Not muted and going up from mute level? */
303 if (prev_l <= HW_VOL_MUTE && !wmc_vol.ahw_mute)
304 wmc_clear(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
306 else
308 /* Going to mute level? */
309 if (prev_l > HW_VOL_MUTE)
310 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
313 if (wmc_vol.vol_r > HW_VOL_MUTE)
315 /* Not muted and going up from mute level? */
316 if (prev_r <= HW_VOL_MIN && !wmc_vol.ahw_mute)
317 wmc_clear(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
319 else
321 /* Going to mute level? */
322 if (prev_r > HW_VOL_MUTE)
323 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
327 void audiohw_close(void)
329 /* 1. Mute all analogue outputs */
330 audiohw_mute(true);
331 audiohw_enable_headphone_jack(false);
333 /* 2. Disable power management register 1. R1 = 00 */
334 wmc_write(WMC_POWER_MANAGEMENT1, 0x000);
336 /* 3. Disable power management register 2. R2 = 00 */
337 wmc_write(WMC_POWER_MANAGEMENT2, 0x000);
339 /* 4. Disable power management register 3. R3 = 00 */
340 wmc_write(WMC_POWER_MANAGEMENT3, 0x000);
342 /* 5. Remove external power supplies. */
345 void audiohw_mute(bool mute)
347 wmc_vol.ahw_mute = mute;
349 /* No DAC mute here, please - take care of each enabled output. */
350 if (mute)
352 wmc_set(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
353 wmc_set(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
355 else
357 /* Unmute outputs not at mute level */
358 if (wmc_vol.vol_l > HW_VOL_MUTE)
359 wmc_clear(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
361 if (wmc_vol.vol_r > HW_VOL_MUTE)
362 wmc_clear(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
366 void audiohw_set_frequency(int fsel)
368 /* For 16.9344MHz MCLK, codec as master. */
369 static const struct
371 uint32_t plln : 8;
372 uint32_t pllk1 : 6;
373 uint32_t pllk2 : 9;
374 uint32_t pllk3 : 9;
375 unsigned char mclkdiv;
376 unsigned char filter;
377 } srctrl_table[HW_NUM_FREQ] =
379 [HW_FREQ_8] = /* PLL = 65.536MHz */
381 .plln = WMC_PLLNw(7) | WMC_PLL_PRESCALE,
382 .pllk1 = WMC_PLLK_23_18w(12414886ul >> 18),
383 .pllk2 = WMC_PLLK_17_9w(12414886ul >> 9),
384 .pllk3 = WMC_PLLK_8_0w(12414886ul >> 0),
385 .mclkdiv = WMC_MCLKDIV_8, /* 2.0480 MHz */
386 .filter = WMC_SR_8KHZ,
388 [HW_FREQ_11] = /* PLL = off */
390 .mclkdiv = WMC_MCLKDIV_6, /* 2.8224 MHz */
391 .filter = WMC_SR_12KHZ,
393 [HW_FREQ_12] = /* PLL = 73.728 MHz */
395 .plln = WMC_PLLNw(8) | WMC_PLL_PRESCALE,
396 .pllk1 = WMC_PLLK_23_18w(11869595ul >> 18),
397 .pllk2 = WMC_PLLK_17_9w(11869595ul >> 9),
398 .pllk3 = WMC_PLLK_8_0w(11869595ul >> 0),
399 .mclkdiv = WMC_MCLKDIV_6, /* 3.0720 MHz */
400 .filter = WMC_SR_12KHZ,
402 [HW_FREQ_16] = /* PLL = 65.536MHz */
404 .plln = WMC_PLLNw(7) | WMC_PLL_PRESCALE,
405 .pllk1 = WMC_PLLK_23_18w(12414886ul >> 18),
406 .pllk2 = WMC_PLLK_17_9w(12414886ul >> 9),
407 .pllk3 = WMC_PLLK_8_0w(12414886ul >> 0),
408 .mclkdiv = WMC_MCLKDIV_4, /* 4.0960 MHz */
409 .filter = WMC_SR_16KHZ,
411 [HW_FREQ_22] = /* PLL = off */
413 .mclkdiv = WMC_MCLKDIV_3, /* 5.6448 MHz */
414 .filter = WMC_SR_24KHZ,
416 [HW_FREQ_24] = /* PLL = 73.728 MHz */
418 .plln = WMC_PLLNw(8) | WMC_PLL_PRESCALE,
419 .pllk1 = WMC_PLLK_23_18w(11869595ul >> 18),
420 .pllk2 = WMC_PLLK_17_9w(11869595ul >> 9),
421 .pllk3 = WMC_PLLK_8_0w(11869595ul >> 0),
422 .mclkdiv = WMC_MCLKDIV_3, /* 6.1440 MHz */
423 .filter = WMC_SR_24KHZ,
425 [HW_FREQ_32] = /* PLL = 65.536MHz */
427 .plln = WMC_PLLNw(7) | WMC_PLL_PRESCALE,
428 .pllk1 = WMC_PLLK_23_18w(12414886ul >> 18),
429 .pllk2 = WMC_PLLK_17_9w(12414886ul >> 9),
430 .pllk3 = WMC_PLLK_8_0w(12414886ul >> 0),
431 .mclkdiv = WMC_MCLKDIV_2, /* 8.1920 MHz */
432 .filter = WMC_SR_32KHZ,
434 [HW_FREQ_44] = /* PLL = off */
436 .mclkdiv = WMC_MCLKDIV_1_5, /* 11.2896 MHz */
437 .filter = WMC_SR_48KHZ,
439 [HW_FREQ_48] = /* PLL = 73.728 MHz */
441 .plln = WMC_PLLNw(8) | WMC_PLL_PRESCALE,
442 .pllk1 = WMC_PLLK_23_18w(11869595ul >> 18),
443 .pllk2 = WMC_PLLK_17_9w(11869595ul >> 9),
444 .pllk3 = WMC_PLLK_8_0w(11869595ul >> 0),
445 .mclkdiv = WMC_MCLKDIV_1_5, /* 12.2880 MHz */
446 .filter = WMC_SR_48KHZ,
450 unsigned int plln;
451 unsigned int mclkdiv;
453 if ((unsigned)fsel >= HW_NUM_FREQ)
454 fsel = HW_FREQ_DEFAULT;
456 /* Setup filters. */
457 wmc_write(WMC_ADDITIONAL_CTRL, srctrl_table[fsel].filter);
459 plln = srctrl_table[fsel].plln;
460 mclkdiv = srctrl_table[fsel].mclkdiv;
462 if (plln != 0)
464 /* Using PLL to generate SYSCLK */
466 /* Program PLL. */
467 wmc_write(WMC_PLL_N, plln);
468 wmc_write(WMC_PLL_K1, srctrl_table[fsel].pllk1);
469 wmc_write(WMC_PLL_K2, srctrl_table[fsel].pllk2);
470 wmc_write(WMC_PLL_K3, srctrl_table[fsel].pllk3);
472 /* Turn on PLL. */
473 wmc_set(WMC_POWER_MANAGEMENT1, WMC_PLLEN);
475 /* Switch to PLL and set divider. */
476 wmc_write_masked(WMC_CLOCK_GEN_CTRL, mclkdiv | WMC_CLKSEL,
477 WMC_MCLKDIV | WMC_CLKSEL);
479 else
481 /* Switch away from PLL and set MCLKDIV. */
482 wmc_write_masked(WMC_CLOCK_GEN_CTRL, mclkdiv,
483 WMC_MCLKDIV | WMC_CLKSEL);
485 /* Turn off PLL. */
486 wmc_clear(WMC_POWER_MANAGEMENT1, WMC_PLLEN);
490 #ifdef HAVE_RECORDING
491 /* TODO */
492 void audiohw_set_recvol(int left, int right, int type)
494 (void)left; (void)right; (void)type;
496 #endif