xref: /linux/sound/soc/codecs/wm8990.c (revision f10485e79882bf09cf442a673511154987b43e3b)
1*f10485e7SMark Brown /*
2*f10485e7SMark Brown  * wm8990.c  --  WM8990 ALSA Soc Audio driver
3*f10485e7SMark Brown  *
4*f10485e7SMark Brown  * Copyright 2008 Wolfson Microelectronics PLC.
5*f10485e7SMark Brown  * Author: Liam Girdwood
6*f10485e7SMark Brown  *         lg@opensource.wolfsonmicro.com or linux@wolfsonmicro.com
7*f10485e7SMark Brown  *
8*f10485e7SMark Brown  *  This program is free software; you can redistribute  it and/or modify it
9*f10485e7SMark Brown  *  under  the terms of  the GNU General  Public License as published by the
10*f10485e7SMark Brown  *  Free Software Foundation;  either version 2 of the  License, or (at your
11*f10485e7SMark Brown  *  option) any later version.
12*f10485e7SMark Brown  */
13*f10485e7SMark Brown 
14*f10485e7SMark Brown #include <linux/module.h>
15*f10485e7SMark Brown #include <linux/moduleparam.h>
16*f10485e7SMark Brown #include <linux/kernel.h>
17*f10485e7SMark Brown #include <linux/init.h>
18*f10485e7SMark Brown #include <linux/delay.h>
19*f10485e7SMark Brown #include <linux/pm.h>
20*f10485e7SMark Brown #include <linux/i2c.h>
21*f10485e7SMark Brown #include <linux/platform_device.h>
22*f10485e7SMark Brown #include <sound/core.h>
23*f10485e7SMark Brown #include <sound/pcm.h>
24*f10485e7SMark Brown #include <sound/pcm_params.h>
25*f10485e7SMark Brown #include <sound/soc.h>
26*f10485e7SMark Brown #include <sound/soc-dapm.h>
27*f10485e7SMark Brown #include <sound/initval.h>
28*f10485e7SMark Brown #include <sound/tlv.h>
29*f10485e7SMark Brown #include <asm/div64.h>
30*f10485e7SMark Brown 
31*f10485e7SMark Brown #include "wm8990.h"
32*f10485e7SMark Brown 
33*f10485e7SMark Brown #define AUDIO_NAME "wm8990"
34*f10485e7SMark Brown #define WM8990_VERSION "0.2"
35*f10485e7SMark Brown 
36*f10485e7SMark Brown /*
37*f10485e7SMark Brown  * Debug
38*f10485e7SMark Brown  */
39*f10485e7SMark Brown 
40*f10485e7SMark Brown #define WM8990_DEBUG 0
41*f10485e7SMark Brown 
42*f10485e7SMark Brown #ifdef WM8990_DEBUG
43*f10485e7SMark Brown #define dbg(format, arg...) \
44*f10485e7SMark Brown 	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
45*f10485e7SMark Brown #else
46*f10485e7SMark Brown #define dbg(format, arg...) do {} while (0)
47*f10485e7SMark Brown #endif
48*f10485e7SMark Brown #define err(format, arg...) \
49*f10485e7SMark Brown 	printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
50*f10485e7SMark Brown #define info(format, arg...) \
51*f10485e7SMark Brown 	printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
52*f10485e7SMark Brown #define warn(format, arg...) \
53*f10485e7SMark Brown 	printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
54*f10485e7SMark Brown 
55*f10485e7SMark Brown /* codec private data */
56*f10485e7SMark Brown struct wm8990_priv {
57*f10485e7SMark Brown 	unsigned int sysclk;
58*f10485e7SMark Brown 	unsigned int pcmclk;
59*f10485e7SMark Brown };
60*f10485e7SMark Brown 
61*f10485e7SMark Brown /*
62*f10485e7SMark Brown  * wm8990 register cache.  Note that register 0 is not included in the
63*f10485e7SMark Brown  * cache.
64*f10485e7SMark Brown  */
65*f10485e7SMark Brown static const u16 wm8990_reg[] = {
66*f10485e7SMark Brown 	0x8990,     /* R0  - Reset */
67*f10485e7SMark Brown 	0x0000,     /* R1  - Power Management (1) */
68*f10485e7SMark Brown 	0x6000,     /* R2  - Power Management (2) */
69*f10485e7SMark Brown 	0x0000,     /* R3  - Power Management (3) */
70*f10485e7SMark Brown 	0x4050,     /* R4  - Audio Interface (1) */
71*f10485e7SMark Brown 	0x4000,     /* R5  - Audio Interface (2) */
72*f10485e7SMark Brown 	0x01C8,     /* R6  - Clocking (1) */
73*f10485e7SMark Brown 	0x0000,     /* R7  - Clocking (2) */
74*f10485e7SMark Brown 	0x0040,     /* R8  - Audio Interface (3) */
75*f10485e7SMark Brown 	0x0040,     /* R9  - Audio Interface (4) */
76*f10485e7SMark Brown 	0x0004,     /* R10 - DAC CTRL */
77*f10485e7SMark Brown 	0x00C0,     /* R11 - Left DAC Digital Volume */
78*f10485e7SMark Brown 	0x00C0,     /* R12 - Right DAC Digital Volume */
79*f10485e7SMark Brown 	0x0000,     /* R13 - Digital Side Tone */
80*f10485e7SMark Brown 	0x0100,     /* R14 - ADC CTRL */
81*f10485e7SMark Brown 	0x00C0,     /* R15 - Left ADC Digital Volume */
82*f10485e7SMark Brown 	0x00C0,     /* R16 - Right ADC Digital Volume */
83*f10485e7SMark Brown 	0x0000,     /* R17 */
84*f10485e7SMark Brown 	0x0000,     /* R18 - GPIO CTRL 1 */
85*f10485e7SMark Brown 	0x1000,     /* R19 - GPIO1 & GPIO2 */
86*f10485e7SMark Brown 	0x1010,     /* R20 - GPIO3 & GPIO4 */
87*f10485e7SMark Brown 	0x1010,     /* R21 - GPIO5 & GPIO6 */
88*f10485e7SMark Brown 	0x8000,     /* R22 - GPIOCTRL 2 */
89*f10485e7SMark Brown 	0x0800,     /* R23 - GPIO_POL */
90*f10485e7SMark Brown 	0x008B,     /* R24 - Left Line Input 1&2 Volume */
91*f10485e7SMark Brown 	0x008B,     /* R25 - Left Line Input 3&4 Volume */
92*f10485e7SMark Brown 	0x008B,     /* R26 - Right Line Input 1&2 Volume */
93*f10485e7SMark Brown 	0x008B,     /* R27 - Right Line Input 3&4 Volume */
94*f10485e7SMark Brown 	0x0000,     /* R28 - Left Output Volume */
95*f10485e7SMark Brown 	0x0000,     /* R29 - Right Output Volume */
96*f10485e7SMark Brown 	0x0066,     /* R30 - Line Outputs Volume */
97*f10485e7SMark Brown 	0x0022,     /* R31 - Out3/4 Volume */
98*f10485e7SMark Brown 	0x0079,     /* R32 - Left OPGA Volume */
99*f10485e7SMark Brown 	0x0079,     /* R33 - Right OPGA Volume */
100*f10485e7SMark Brown 	0x0003,     /* R34 - Speaker Volume */
101*f10485e7SMark Brown 	0x0003,     /* R35 - ClassD1 */
102*f10485e7SMark Brown 	0x0000,     /* R36 */
103*f10485e7SMark Brown 	0x0100,     /* R37 - ClassD3 */
104*f10485e7SMark Brown 	0x0000,     /* R38 */
105*f10485e7SMark Brown 	0x0000,     /* R39 - Input Mixer1 */
106*f10485e7SMark Brown 	0x0000,     /* R40 - Input Mixer2 */
107*f10485e7SMark Brown 	0x0000,     /* R41 - Input Mixer3 */
108*f10485e7SMark Brown 	0x0000,     /* R42 - Input Mixer4 */
109*f10485e7SMark Brown 	0x0000,     /* R43 - Input Mixer5 */
110*f10485e7SMark Brown 	0x0000,     /* R44 - Input Mixer6 */
111*f10485e7SMark Brown 	0x0000,     /* R45 - Output Mixer1 */
112*f10485e7SMark Brown 	0x0000,     /* R46 - Output Mixer2 */
113*f10485e7SMark Brown 	0x0000,     /* R47 - Output Mixer3 */
114*f10485e7SMark Brown 	0x0000,     /* R48 - Output Mixer4 */
115*f10485e7SMark Brown 	0x0000,     /* R49 - Output Mixer5 */
116*f10485e7SMark Brown 	0x0000,     /* R50 - Output Mixer6 */
117*f10485e7SMark Brown 	0x0180,     /* R51 - Out3/4 Mixer */
118*f10485e7SMark Brown 	0x0000,     /* R52 - Line Mixer1 */
119*f10485e7SMark Brown 	0x0000,     /* R53 - Line Mixer2 */
120*f10485e7SMark Brown 	0x0000,     /* R54 - Speaker Mixer */
121*f10485e7SMark Brown 	0x0000,     /* R55 - Additional Control */
122*f10485e7SMark Brown 	0x0000,     /* R56 - AntiPOP1 */
123*f10485e7SMark Brown 	0x0000,     /* R57 - AntiPOP2 */
124*f10485e7SMark Brown 	0x0000,     /* R58 - MICBIAS */
125*f10485e7SMark Brown 	0x0000,     /* R59 */
126*f10485e7SMark Brown 	0x0008,     /* R60 - PLL1 */
127*f10485e7SMark Brown 	0x0031,     /* R61 - PLL2 */
128*f10485e7SMark Brown 	0x0026,     /* R62 - PLL3 */
129*f10485e7SMark Brown };
130*f10485e7SMark Brown 
131*f10485e7SMark Brown /*
132*f10485e7SMark Brown  * read wm8990 register cache
133*f10485e7SMark Brown  */
134*f10485e7SMark Brown static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec,
135*f10485e7SMark Brown 	unsigned int reg)
136*f10485e7SMark Brown {
137*f10485e7SMark Brown 	u16 *cache = codec->reg_cache;
138*f10485e7SMark Brown 	BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
139*f10485e7SMark Brown 	return cache[reg];
140*f10485e7SMark Brown }
141*f10485e7SMark Brown 
142*f10485e7SMark Brown /*
143*f10485e7SMark Brown  * write wm8990 register cache
144*f10485e7SMark Brown  */
145*f10485e7SMark Brown static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
146*f10485e7SMark Brown 	unsigned int reg, unsigned int value)
147*f10485e7SMark Brown {
148*f10485e7SMark Brown 	u16 *cache = codec->reg_cache;
149*f10485e7SMark Brown 	BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
150*f10485e7SMark Brown 
151*f10485e7SMark Brown 	/* Reset register is uncached */
152*f10485e7SMark Brown 	if (reg == 0)
153*f10485e7SMark Brown 		return;
154*f10485e7SMark Brown 
155*f10485e7SMark Brown 	cache[reg] = value;
156*f10485e7SMark Brown }
157*f10485e7SMark Brown 
158*f10485e7SMark Brown /*
159*f10485e7SMark Brown  * write to the wm8990 register space
160*f10485e7SMark Brown  */
161*f10485e7SMark Brown static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg,
162*f10485e7SMark Brown 	unsigned int value)
163*f10485e7SMark Brown {
164*f10485e7SMark Brown 	u8 data[3];
165*f10485e7SMark Brown 
166*f10485e7SMark Brown 	data[0] = reg & 0xFF;
167*f10485e7SMark Brown 	data[1] = (value >> 8) & 0xFF;
168*f10485e7SMark Brown 	data[2] = value & 0xFF;
169*f10485e7SMark Brown 
170*f10485e7SMark Brown 	wm8990_write_reg_cache(codec, reg, value);
171*f10485e7SMark Brown 
172*f10485e7SMark Brown 	if (codec->hw_write(codec->control_data, data, 3) == 2)
173*f10485e7SMark Brown 		return 0;
174*f10485e7SMark Brown 	else
175*f10485e7SMark Brown 		return -EIO;
176*f10485e7SMark Brown }
177*f10485e7SMark Brown 
178*f10485e7SMark Brown #define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0)
179*f10485e7SMark Brown 
180*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
181*f10485e7SMark Brown 
182*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000);
183*f10485e7SMark Brown 
184*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100);
185*f10485e7SMark Brown 
186*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600);
187*f10485e7SMark Brown 
188*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0);
189*f10485e7SMark Brown 
190*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0);
191*f10485e7SMark Brown 
192*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763);
193*f10485e7SMark Brown 
194*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0);
195*f10485e7SMark Brown 
196*f10485e7SMark Brown static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
197*f10485e7SMark Brown 	struct snd_ctl_elem_value *ucontrol)
198*f10485e7SMark Brown {
199*f10485e7SMark Brown 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
200*f10485e7SMark Brown 	int reg = kcontrol->private_value & 0xff;
201*f10485e7SMark Brown 	int ret;
202*f10485e7SMark Brown 	u16 val;
203*f10485e7SMark Brown 
204*f10485e7SMark Brown 	ret = snd_soc_put_volsw(kcontrol, ucontrol);
205*f10485e7SMark Brown 	if (ret < 0)
206*f10485e7SMark Brown 		return ret;
207*f10485e7SMark Brown 
208*f10485e7SMark Brown 	/* now hit the volume update bits (always bit 8) */
209*f10485e7SMark Brown 	val = wm8990_read_reg_cache(codec, reg);
210*f10485e7SMark Brown 	return wm8990_write(codec, reg, val | 0x0100);
211*f10485e7SMark Brown }
212*f10485e7SMark Brown 
213*f10485e7SMark Brown #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
214*f10485e7SMark Brown 	 tlv_array) {\
215*f10485e7SMark Brown 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
216*f10485e7SMark Brown 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
217*f10485e7SMark Brown 		  SNDRV_CTL_ELEM_ACCESS_READWRITE,\
218*f10485e7SMark Brown 	.tlv.p = (tlv_array), \
219*f10485e7SMark Brown 	.info = snd_soc_info_volsw, \
220*f10485e7SMark Brown 	.get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \
221*f10485e7SMark Brown 	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
222*f10485e7SMark Brown 
223*f10485e7SMark Brown 
224*f10485e7SMark Brown static const char *wm8990_digital_sidetone[] =
225*f10485e7SMark Brown 	{"None", "Left ADC", "Right ADC", "Reserved"};
226*f10485e7SMark Brown 
227*f10485e7SMark Brown static const struct soc_enum wm8990_left_digital_sidetone_enum =
228*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE,
229*f10485e7SMark Brown 	WM8990_ADC_TO_DACL_SHIFT,
230*f10485e7SMark Brown 	WM8990_ADC_TO_DACL_MASK,
231*f10485e7SMark Brown 	wm8990_digital_sidetone);
232*f10485e7SMark Brown 
233*f10485e7SMark Brown static const struct soc_enum wm8990_right_digital_sidetone_enum =
234*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE,
235*f10485e7SMark Brown 	WM8990_ADC_TO_DACR_SHIFT,
236*f10485e7SMark Brown 	WM8990_ADC_TO_DACR_MASK,
237*f10485e7SMark Brown 	wm8990_digital_sidetone);
238*f10485e7SMark Brown 
239*f10485e7SMark Brown static const char *wm8990_adcmode[] =
240*f10485e7SMark Brown 	{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
241*f10485e7SMark Brown 
242*f10485e7SMark Brown static const struct soc_enum wm8990_right_adcmode_enum =
243*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_ADC_CTRL,
244*f10485e7SMark Brown 	WM8990_ADC_HPF_CUT_SHIFT,
245*f10485e7SMark Brown 	WM8990_ADC_HPF_CUT_MASK,
246*f10485e7SMark Brown 	wm8990_adcmode);
247*f10485e7SMark Brown 
248*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_snd_controls[] = {
249*f10485e7SMark Brown /* INMIXL */
250*f10485e7SMark Brown SOC_SINGLE("LIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L12MNBST_BIT, 1, 0),
251*f10485e7SMark Brown SOC_SINGLE("LIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L34MNBST_BIT, 1, 0),
252*f10485e7SMark Brown /* INMIXR */
253*f10485e7SMark Brown SOC_SINGLE("RIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R12MNBST_BIT, 1, 0),
254*f10485e7SMark Brown SOC_SINGLE("RIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R34MNBST_BIT, 1, 0),
255*f10485e7SMark Brown 
256*f10485e7SMark Brown /* LOMIX */
257*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER3,
258*f10485e7SMark Brown 	WM8990_LLI3LOVOL_SHIFT, WM8990_LLI3LOVOL_MASK, 1, out_mix_tlv),
259*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3,
260*f10485e7SMark Brown 	WM8990_LR12LOVOL_SHIFT, WM8990_LR12LOVOL_MASK, 1, out_mix_tlv),
261*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3,
262*f10485e7SMark Brown 	WM8990_LL12LOVOL_SHIFT, WM8990_LL12LOVOL_MASK, 1, out_mix_tlv),
263*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER5,
264*f10485e7SMark Brown 	WM8990_LRI3LOVOL_SHIFT, WM8990_LRI3LOVOL_MASK, 1, out_mix_tlv),
265*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER5,
266*f10485e7SMark Brown 	WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv),
267*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER5,
268*f10485e7SMark Brown 	WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv),
269*f10485e7SMark Brown 
270*f10485e7SMark Brown /* ROMIX */
271*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER4,
272*f10485e7SMark Brown 	WM8990_RRI3ROVOL_SHIFT, WM8990_RRI3ROVOL_MASK, 1, out_mix_tlv),
273*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4,
274*f10485e7SMark Brown 	WM8990_RL12ROVOL_SHIFT, WM8990_RL12ROVOL_MASK, 1, out_mix_tlv),
275*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4,
276*f10485e7SMark Brown 	WM8990_RR12ROVOL_SHIFT, WM8990_RR12ROVOL_MASK, 1, out_mix_tlv),
277*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER6,
278*f10485e7SMark Brown 	WM8990_RLI3ROVOL_SHIFT, WM8990_RLI3ROVOL_MASK, 1, out_mix_tlv),
279*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER6,
280*f10485e7SMark Brown 	WM8990_RLBROVOL_SHIFT, WM8990_RLBROVOL_MASK, 1, out_mix_tlv),
281*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER6,
282*f10485e7SMark Brown 	WM8990_RRBROVOL_SHIFT, WM8990_RRBROVOL_MASK, 1, out_mix_tlv),
283*f10485e7SMark Brown 
284*f10485e7SMark Brown /* LOUT */
285*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8990_LEFT_OUTPUT_VOLUME,
286*f10485e7SMark Brown 	WM8990_LOUTVOL_SHIFT, WM8990_LOUTVOL_MASK, 0, out_pga_tlv),
287*f10485e7SMark Brown SOC_SINGLE("LOUT ZC", WM8990_LEFT_OUTPUT_VOLUME, WM8990_LOZC_BIT, 1, 0),
288*f10485e7SMark Brown 
289*f10485e7SMark Brown /* ROUT */
290*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8990_RIGHT_OUTPUT_VOLUME,
291*f10485e7SMark Brown 	WM8990_ROUTVOL_SHIFT, WM8990_ROUTVOL_MASK, 0, out_pga_tlv),
292*f10485e7SMark Brown SOC_SINGLE("ROUT ZC", WM8990_RIGHT_OUTPUT_VOLUME, WM8990_ROZC_BIT, 1, 0),
293*f10485e7SMark Brown 
294*f10485e7SMark Brown /* LOPGA */
295*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8990_LEFT_OPGA_VOLUME,
296*f10485e7SMark Brown 	WM8990_LOPGAVOL_SHIFT, WM8990_LOPGAVOL_MASK, 0, out_pga_tlv),
297*f10485e7SMark Brown SOC_SINGLE("LOPGA ZC Switch", WM8990_LEFT_OPGA_VOLUME,
298*f10485e7SMark Brown 	WM8990_LOPGAZC_BIT, 1, 0),
299*f10485e7SMark Brown 
300*f10485e7SMark Brown /* ROPGA */
301*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8990_RIGHT_OPGA_VOLUME,
302*f10485e7SMark Brown 	WM8990_ROPGAVOL_SHIFT, WM8990_ROPGAVOL_MASK, 0, out_pga_tlv),
303*f10485e7SMark Brown SOC_SINGLE("ROPGA ZC Switch", WM8990_RIGHT_OPGA_VOLUME,
304*f10485e7SMark Brown 	WM8990_ROPGAZC_BIT, 1, 0),
305*f10485e7SMark Brown 
306*f10485e7SMark Brown SOC_SINGLE("LON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
307*f10485e7SMark Brown 	WM8990_LONMUTE_BIT, 1, 0),
308*f10485e7SMark Brown SOC_SINGLE("LOP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
309*f10485e7SMark Brown 	WM8990_LOPMUTE_BIT, 1, 0),
310*f10485e7SMark Brown SOC_SINGLE("LOP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME,
311*f10485e7SMark Brown 	WM8990_LOATTN_BIT, 1, 0),
312*f10485e7SMark Brown SOC_SINGLE("RON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
313*f10485e7SMark Brown 	WM8990_RONMUTE_BIT, 1, 0),
314*f10485e7SMark Brown SOC_SINGLE("ROP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
315*f10485e7SMark Brown 	WM8990_ROPMUTE_BIT, 1, 0),
316*f10485e7SMark Brown SOC_SINGLE("ROP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME,
317*f10485e7SMark Brown 	WM8990_ROATTN_BIT, 1, 0),
318*f10485e7SMark Brown 
319*f10485e7SMark Brown SOC_SINGLE("OUT3 Mute Switch", WM8990_OUT3_4_VOLUME,
320*f10485e7SMark Brown 	WM8990_OUT3MUTE_BIT, 1, 0),
321*f10485e7SMark Brown SOC_SINGLE("OUT3 Attenuation Switch", WM8990_OUT3_4_VOLUME,
322*f10485e7SMark Brown 	WM8990_OUT3ATTN_BIT, 1, 0),
323*f10485e7SMark Brown 
324*f10485e7SMark Brown SOC_SINGLE("OUT4 Mute Switch", WM8990_OUT3_4_VOLUME,
325*f10485e7SMark Brown 	WM8990_OUT4MUTE_BIT, 1, 0),
326*f10485e7SMark Brown SOC_SINGLE("OUT4 Attenuation Switch", WM8990_OUT3_4_VOLUME,
327*f10485e7SMark Brown 	WM8990_OUT4ATTN_BIT, 1, 0),
328*f10485e7SMark Brown 
329*f10485e7SMark Brown SOC_SINGLE("Speaker Mode Switch", WM8990_CLASSD1,
330*f10485e7SMark Brown 	WM8990_CDMODE_BIT, 1, 0),
331*f10485e7SMark Brown 
332*f10485e7SMark Brown SOC_SINGLE("Speaker Output Attenuation Volume", WM8990_SPEAKER_VOLUME,
333*f10485e7SMark Brown 	WM8990_SPKVOL_SHIFT, WM8990_SPKVOL_MASK, 0),
334*f10485e7SMark Brown SOC_SINGLE("Speaker DC Boost Volume", WM8990_CLASSD3,
335*f10485e7SMark Brown 	WM8990_DCGAIN_SHIFT, WM8990_DCGAIN_MASK, 0),
336*f10485e7SMark Brown SOC_SINGLE("Speaker AC Boost Volume", WM8990_CLASSD3,
337*f10485e7SMark Brown 	WM8990_ACGAIN_SHIFT, WM8990_ACGAIN_MASK, 0),
338*f10485e7SMark Brown 
339*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume",
340*f10485e7SMark Brown 	WM8990_LEFT_DAC_DIGITAL_VOLUME,
341*f10485e7SMark Brown 	WM8990_DACL_VOL_SHIFT,
342*f10485e7SMark Brown 	WM8990_DACL_VOL_MASK,
343*f10485e7SMark Brown 	0,
344*f10485e7SMark Brown 	out_dac_tlv),
345*f10485e7SMark Brown 
346*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume",
347*f10485e7SMark Brown 	WM8990_RIGHT_DAC_DIGITAL_VOLUME,
348*f10485e7SMark Brown 	WM8990_DACR_VOL_SHIFT,
349*f10485e7SMark Brown 	WM8990_DACR_VOL_MASK,
350*f10485e7SMark Brown 	0,
351*f10485e7SMark Brown 	out_dac_tlv),
352*f10485e7SMark Brown 
353*f10485e7SMark Brown SOC_ENUM("Left Digital Sidetone", wm8990_left_digital_sidetone_enum),
354*f10485e7SMark Brown SOC_ENUM("Right Digital Sidetone", wm8990_right_digital_sidetone_enum),
355*f10485e7SMark Brown 
356*f10485e7SMark Brown SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE,
357*f10485e7SMark Brown 	WM8990_ADCL_DAC_SVOL_SHIFT, WM8990_ADCL_DAC_SVOL_MASK, 0,
358*f10485e7SMark Brown 	out_sidetone_tlv),
359*f10485e7SMark Brown SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE,
360*f10485e7SMark Brown 	WM8990_ADCR_DAC_SVOL_SHIFT, WM8990_ADCR_DAC_SVOL_MASK, 0,
361*f10485e7SMark Brown 	out_sidetone_tlv),
362*f10485e7SMark Brown 
363*f10485e7SMark Brown SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8990_ADC_CTRL,
364*f10485e7SMark Brown 	WM8990_ADC_HPF_ENA_BIT, 1, 0),
365*f10485e7SMark Brown 
366*f10485e7SMark Brown SOC_ENUM("ADC HPF Mode", wm8990_right_adcmode_enum),
367*f10485e7SMark Brown 
368*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume",
369*f10485e7SMark Brown 	WM8990_LEFT_ADC_DIGITAL_VOLUME,
370*f10485e7SMark Brown 	WM8990_ADCL_VOL_SHIFT,
371*f10485e7SMark Brown 	WM8990_ADCL_VOL_MASK,
372*f10485e7SMark Brown 	0,
373*f10485e7SMark Brown 	in_adc_tlv),
374*f10485e7SMark Brown 
375*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume",
376*f10485e7SMark Brown 	WM8990_RIGHT_ADC_DIGITAL_VOLUME,
377*f10485e7SMark Brown 	WM8990_ADCR_VOL_SHIFT,
378*f10485e7SMark Brown 	WM8990_ADCR_VOL_MASK,
379*f10485e7SMark Brown 	0,
380*f10485e7SMark Brown 	in_adc_tlv),
381*f10485e7SMark Brown 
382*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume",
383*f10485e7SMark Brown 	WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
384*f10485e7SMark Brown 	WM8990_LIN12VOL_SHIFT,
385*f10485e7SMark Brown 	WM8990_LIN12VOL_MASK,
386*f10485e7SMark Brown 	0,
387*f10485e7SMark Brown 	in_pga_tlv),
388*f10485e7SMark Brown 
389*f10485e7SMark Brown SOC_SINGLE("LIN12 ZC Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
390*f10485e7SMark Brown 	WM8990_LI12ZC_BIT, 1, 0),
391*f10485e7SMark Brown 
392*f10485e7SMark Brown SOC_SINGLE("LIN12 Mute Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
393*f10485e7SMark Brown 	WM8990_LI12MUTE_BIT, 1, 0),
394*f10485e7SMark Brown 
395*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume",
396*f10485e7SMark Brown 	WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
397*f10485e7SMark Brown 	WM8990_LIN34VOL_SHIFT,
398*f10485e7SMark Brown 	WM8990_LIN34VOL_MASK,
399*f10485e7SMark Brown 	0,
400*f10485e7SMark Brown 	in_pga_tlv),
401*f10485e7SMark Brown 
402*f10485e7SMark Brown SOC_SINGLE("LIN34 ZC Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
403*f10485e7SMark Brown 	WM8990_LI34ZC_BIT, 1, 0),
404*f10485e7SMark Brown 
405*f10485e7SMark Brown SOC_SINGLE("LIN34 Mute Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
406*f10485e7SMark Brown 	WM8990_LI34MUTE_BIT, 1, 0),
407*f10485e7SMark Brown 
408*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume",
409*f10485e7SMark Brown 	WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
410*f10485e7SMark Brown 	WM8990_RIN12VOL_SHIFT,
411*f10485e7SMark Brown 	WM8990_RIN12VOL_MASK,
412*f10485e7SMark Brown 	0,
413*f10485e7SMark Brown 	in_pga_tlv),
414*f10485e7SMark Brown 
415*f10485e7SMark Brown SOC_SINGLE("RIN12 ZC Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
416*f10485e7SMark Brown 	WM8990_RI12ZC_BIT, 1, 0),
417*f10485e7SMark Brown 
418*f10485e7SMark Brown SOC_SINGLE("RIN12 Mute Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
419*f10485e7SMark Brown 	WM8990_RI12MUTE_BIT, 1, 0),
420*f10485e7SMark Brown 
421*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume",
422*f10485e7SMark Brown 	WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
423*f10485e7SMark Brown 	WM8990_RIN34VOL_SHIFT,
424*f10485e7SMark Brown 	WM8990_RIN34VOL_MASK,
425*f10485e7SMark Brown 	0,
426*f10485e7SMark Brown 	in_pga_tlv),
427*f10485e7SMark Brown 
428*f10485e7SMark Brown SOC_SINGLE("RIN34 ZC Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
429*f10485e7SMark Brown 	WM8990_RI34ZC_BIT, 1, 0),
430*f10485e7SMark Brown 
431*f10485e7SMark Brown SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
432*f10485e7SMark Brown 	WM8990_RI34MUTE_BIT, 1, 0),
433*f10485e7SMark Brown 
434*f10485e7SMark Brown };
435*f10485e7SMark Brown 
436*f10485e7SMark Brown /* add non dapm controls */
437*f10485e7SMark Brown static int wm8990_add_controls(struct snd_soc_codec *codec)
438*f10485e7SMark Brown {
439*f10485e7SMark Brown 	int err, i;
440*f10485e7SMark Brown 
441*f10485e7SMark Brown 	for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) {
442*f10485e7SMark Brown 		err = snd_ctl_add(codec->card,
443*f10485e7SMark Brown 				snd_soc_cnew(&wm8990_snd_controls[i], codec,
444*f10485e7SMark Brown 					NULL));
445*f10485e7SMark Brown 		if (err < 0)
446*f10485e7SMark Brown 			return err;
447*f10485e7SMark Brown 	}
448*f10485e7SMark Brown 	return 0;
449*f10485e7SMark Brown }
450*f10485e7SMark Brown 
451*f10485e7SMark Brown /*
452*f10485e7SMark Brown  * _DAPM_ Controls
453*f10485e7SMark Brown  */
454*f10485e7SMark Brown 
455*f10485e7SMark Brown static int inmixer_event(struct snd_soc_dapm_widget *w,
456*f10485e7SMark Brown 	struct snd_kcontrol *kcontrol, int event)
457*f10485e7SMark Brown {
458*f10485e7SMark Brown 	u16 reg, fakepower;
459*f10485e7SMark Brown 
460*f10485e7SMark Brown 	reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2);
461*f10485e7SMark Brown 	fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS);
462*f10485e7SMark Brown 
463*f10485e7SMark Brown 	if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
464*f10485e7SMark Brown 		(1 << WM8990_AINLMUX_PWR_BIT))) {
465*f10485e7SMark Brown 		reg |= WM8990_AINL_ENA;
466*f10485e7SMark Brown 	} else {
467*f10485e7SMark Brown 		reg &= ~WM8990_AINL_ENA;
468*f10485e7SMark Brown 	}
469*f10485e7SMark Brown 
470*f10485e7SMark Brown 	if (fakepower & ((1 << WM8990_INMIXR_PWR_BIT) |
471*f10485e7SMark Brown 		(1 << WM8990_AINRMUX_PWR_BIT))) {
472*f10485e7SMark Brown 		reg |= WM8990_AINR_ENA;
473*f10485e7SMark Brown 	} else {
474*f10485e7SMark Brown 		reg &= ~WM8990_AINL_ENA;
475*f10485e7SMark Brown 	}
476*f10485e7SMark Brown 	wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
477*f10485e7SMark Brown 
478*f10485e7SMark Brown 	return 0;
479*f10485e7SMark Brown }
480*f10485e7SMark Brown 
481*f10485e7SMark Brown static int outmixer_event(struct snd_soc_dapm_widget *w,
482*f10485e7SMark Brown 	struct snd_kcontrol *kcontrol, int event)
483*f10485e7SMark Brown {
484*f10485e7SMark Brown 	u32 reg_shift = kcontrol->private_value & 0xfff;
485*f10485e7SMark Brown 	int ret = 0;
486*f10485e7SMark Brown 	u16 reg;
487*f10485e7SMark Brown 
488*f10485e7SMark Brown 	switch (reg_shift) {
489*f10485e7SMark Brown 	case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) :
490*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1);
491*f10485e7SMark Brown 		if (reg & WM8990_LDLO) {
492*f10485e7SMark Brown 			printk(KERN_WARNING
493*f10485e7SMark Brown 			"Cannot set as Output Mixer 1 LDLO Set\n");
494*f10485e7SMark Brown 			ret = -1;
495*f10485e7SMark Brown 		}
496*f10485e7SMark Brown 		break;
497*f10485e7SMark Brown 	case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8):
498*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2);
499*f10485e7SMark Brown 		if (reg & WM8990_RDRO) {
500*f10485e7SMark Brown 			printk(KERN_WARNING
501*f10485e7SMark Brown 			"Cannot set as Output Mixer 2 RDRO Set\n");
502*f10485e7SMark Brown 			ret = -1;
503*f10485e7SMark Brown 		}
504*f10485e7SMark Brown 		break;
505*f10485e7SMark Brown 	case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8):
506*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
507*f10485e7SMark Brown 		if (reg & WM8990_LDSPK) {
508*f10485e7SMark Brown 			printk(KERN_WARNING
509*f10485e7SMark Brown 			"Cannot set as Speaker Mixer LDSPK Set\n");
510*f10485e7SMark Brown 			ret = -1;
511*f10485e7SMark Brown 		}
512*f10485e7SMark Brown 		break;
513*f10485e7SMark Brown 	case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8):
514*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
515*f10485e7SMark Brown 		if (reg & WM8990_RDSPK) {
516*f10485e7SMark Brown 			printk(KERN_WARNING
517*f10485e7SMark Brown 			"Cannot set as Speaker Mixer RDSPK Set\n");
518*f10485e7SMark Brown 			ret = -1;
519*f10485e7SMark Brown 		}
520*f10485e7SMark Brown 		break;
521*f10485e7SMark Brown 	}
522*f10485e7SMark Brown 
523*f10485e7SMark Brown 	return ret;
524*f10485e7SMark Brown }
525*f10485e7SMark Brown 
526*f10485e7SMark Brown /* INMIX dB values */
527*f10485e7SMark Brown static const unsigned int in_mix_tlv[] = {
528*f10485e7SMark Brown 	TLV_DB_RANGE_HEAD(1),
529*f10485e7SMark Brown 	0, 7, TLV_DB_LINEAR_ITEM(-1200, 600),
530*f10485e7SMark Brown };
531*f10485e7SMark Brown 
532*f10485e7SMark Brown /* Left In PGA Connections */
533*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lin12_pga_controls[] = {
534*f10485e7SMark Brown SOC_DAPM_SINGLE("LIN1 Switch", WM8990_INPUT_MIXER2, WM8990_LMN1_BIT, 1, 0),
535*f10485e7SMark Brown SOC_DAPM_SINGLE("LIN2 Switch", WM8990_INPUT_MIXER2, WM8990_LMP2_BIT, 1, 0),
536*f10485e7SMark Brown };
537*f10485e7SMark Brown 
538*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lin34_pga_controls[] = {
539*f10485e7SMark Brown SOC_DAPM_SINGLE("LIN3 Switch", WM8990_INPUT_MIXER2, WM8990_LMN3_BIT, 1, 0),
540*f10485e7SMark Brown SOC_DAPM_SINGLE("LIN4 Switch", WM8990_INPUT_MIXER2, WM8990_LMP4_BIT, 1, 0),
541*f10485e7SMark Brown };
542*f10485e7SMark Brown 
543*f10485e7SMark Brown /* Right In PGA Connections */
544*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_rin12_pga_controls[] = {
545*f10485e7SMark Brown SOC_DAPM_SINGLE("RIN1 Switch", WM8990_INPUT_MIXER2, WM8990_RMN1_BIT, 1, 0),
546*f10485e7SMark Brown SOC_DAPM_SINGLE("RIN2 Switch", WM8990_INPUT_MIXER2, WM8990_RMP2_BIT, 1, 0),
547*f10485e7SMark Brown };
548*f10485e7SMark Brown 
549*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_rin34_pga_controls[] = {
550*f10485e7SMark Brown SOC_DAPM_SINGLE("RIN3 Switch", WM8990_INPUT_MIXER2, WM8990_RMN3_BIT, 1, 0),
551*f10485e7SMark Brown SOC_DAPM_SINGLE("RIN4 Switch", WM8990_INPUT_MIXER2, WM8990_RMP4_BIT, 1, 0),
552*f10485e7SMark Brown };
553*f10485e7SMark Brown 
554*f10485e7SMark Brown /* INMIXL */
555*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_inmixl_controls[] = {
556*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8990_INPUT_MIXER3,
557*f10485e7SMark Brown 	WM8990_LDBVOL_SHIFT, WM8990_LDBVOL_MASK, 0, in_mix_tlv),
558*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8990_INPUT_MIXER5, WM8990_LI2BVOL_SHIFT,
559*f10485e7SMark Brown 	7, 0, in_mix_tlv),
560*f10485e7SMark Brown SOC_DAPM_SINGLE("LINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT,
561*f10485e7SMark Brown 	1, 0),
562*f10485e7SMark Brown SOC_DAPM_SINGLE("LINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT,
563*f10485e7SMark Brown 	1, 0),
564*f10485e7SMark Brown };
565*f10485e7SMark Brown 
566*f10485e7SMark Brown /* INMIXR */
567*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_inmixr_controls[] = {
568*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8990_INPUT_MIXER4,
569*f10485e7SMark Brown 	WM8990_RDBVOL_SHIFT, WM8990_RDBVOL_MASK, 0, in_mix_tlv),
570*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8990_INPUT_MIXER6, WM8990_RI2BVOL_SHIFT,
571*f10485e7SMark Brown 	7, 0, in_mix_tlv),
572*f10485e7SMark Brown SOC_DAPM_SINGLE("RINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT,
573*f10485e7SMark Brown 	1, 0),
574*f10485e7SMark Brown SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT,
575*f10485e7SMark Brown 	1, 0),
576*f10485e7SMark Brown };
577*f10485e7SMark Brown 
578*f10485e7SMark Brown /* AINLMUX */
579*f10485e7SMark Brown static const char *wm8990_ainlmux[] =
580*f10485e7SMark Brown 	{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
581*f10485e7SMark Brown 
582*f10485e7SMark Brown static const struct soc_enum wm8990_ainlmux_enum =
583*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT,
584*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux);
585*f10485e7SMark Brown 
586*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls =
587*f10485e7SMark Brown SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum);
588*f10485e7SMark Brown 
589*f10485e7SMark Brown /* DIFFINL */
590*f10485e7SMark Brown 
591*f10485e7SMark Brown /* AINRMUX */
592*f10485e7SMark Brown static const char *wm8990_ainrmux[] =
593*f10485e7SMark Brown 	{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
594*f10485e7SMark Brown 
595*f10485e7SMark Brown static const struct soc_enum wm8990_ainrmux_enum =
596*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT,
597*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux);
598*f10485e7SMark Brown 
599*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls =
600*f10485e7SMark Brown SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum);
601*f10485e7SMark Brown 
602*f10485e7SMark Brown /* RXVOICE */
603*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_rxvoice_controls[] = {
604*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8990_INPUT_MIXER5, WM8990_LR4BVOL_SHIFT,
605*f10485e7SMark Brown 			WM8990_LR4BVOL_MASK, 0, in_mix_tlv),
606*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8990_INPUT_MIXER6, WM8990_RL4BVOL_SHIFT,
607*f10485e7SMark Brown 			WM8990_RL4BVOL_MASK, 0, in_mix_tlv),
608*f10485e7SMark Brown };
609*f10485e7SMark Brown 
610*f10485e7SMark Brown /* LOMIX */
611*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lomix_controls[] = {
612*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER1,
613*f10485e7SMark Brown 	WM8990_LRBLO_BIT, 1, 0),
614*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER1,
615*f10485e7SMark Brown 	WM8990_LLBLO_BIT, 1, 0),
616*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER1,
617*f10485e7SMark Brown 	WM8990_LRI3LO_BIT, 1, 0),
618*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER1,
619*f10485e7SMark Brown 	WM8990_LLI3LO_BIT, 1, 0),
620*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1,
621*f10485e7SMark Brown 	WM8990_LR12LO_BIT, 1, 0),
622*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1,
623*f10485e7SMark Brown 	WM8990_LL12LO_BIT, 1, 0),
624*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8990_OUTPUT_MIXER1,
625*f10485e7SMark Brown 	WM8990_LDLO_BIT, 1, 0),
626*f10485e7SMark Brown };
627*f10485e7SMark Brown 
628*f10485e7SMark Brown /* ROMIX */
629*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_romix_controls[] = {
630*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER2,
631*f10485e7SMark Brown 	WM8990_RLBRO_BIT, 1, 0),
632*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER2,
633*f10485e7SMark Brown 	WM8990_RRBRO_BIT, 1, 0),
634*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER2,
635*f10485e7SMark Brown 	WM8990_RLI3RO_BIT, 1, 0),
636*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER2,
637*f10485e7SMark Brown 	WM8990_RRI3RO_BIT, 1, 0),
638*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2,
639*f10485e7SMark Brown 	WM8990_RL12RO_BIT, 1, 0),
640*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2,
641*f10485e7SMark Brown 	WM8990_RR12RO_BIT, 1, 0),
642*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8990_OUTPUT_MIXER2,
643*f10485e7SMark Brown 	WM8990_RDRO_BIT, 1, 0),
644*f10485e7SMark Brown };
645*f10485e7SMark Brown 
646*f10485e7SMark Brown /* LONMIX */
647*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lonmix_controls[] = {
648*f10485e7SMark Brown SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1,
649*f10485e7SMark Brown 	WM8990_LLOPGALON_BIT, 1, 0),
650*f10485e7SMark Brown SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER1,
651*f10485e7SMark Brown 	WM8990_LROPGALON_BIT, 1, 0),
652*f10485e7SMark Brown SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8990_LINE_MIXER1,
653*f10485e7SMark Brown 	WM8990_LOPLON_BIT, 1, 0),
654*f10485e7SMark Brown };
655*f10485e7SMark Brown 
656*f10485e7SMark Brown /* LOPMIX */
657*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lopmix_controls[] = {
658*f10485e7SMark Brown SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER1,
659*f10485e7SMark Brown 	WM8990_LR12LOP_BIT, 1, 0),
660*f10485e7SMark Brown SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER1,
661*f10485e7SMark Brown 	WM8990_LL12LOP_BIT, 1, 0),
662*f10485e7SMark Brown SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1,
663*f10485e7SMark Brown 	WM8990_LLOPGALOP_BIT, 1, 0),
664*f10485e7SMark Brown };
665*f10485e7SMark Brown 
666*f10485e7SMark Brown /* RONMIX */
667*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_ronmix_controls[] = {
668*f10485e7SMark Brown SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2,
669*f10485e7SMark Brown 	WM8990_RROPGARON_BIT, 1, 0),
670*f10485e7SMark Brown SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER2,
671*f10485e7SMark Brown 	WM8990_RLOPGARON_BIT, 1, 0),
672*f10485e7SMark Brown SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8990_LINE_MIXER2,
673*f10485e7SMark Brown 	WM8990_ROPRON_BIT, 1, 0),
674*f10485e7SMark Brown };
675*f10485e7SMark Brown 
676*f10485e7SMark Brown /* ROPMIX */
677*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_ropmix_controls[] = {
678*f10485e7SMark Brown SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER2,
679*f10485e7SMark Brown 	WM8990_RL12ROP_BIT, 1, 0),
680*f10485e7SMark Brown SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER2,
681*f10485e7SMark Brown 	WM8990_RR12ROP_BIT, 1, 0),
682*f10485e7SMark Brown SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2,
683*f10485e7SMark Brown 	WM8990_RROPGAROP_BIT, 1, 0),
684*f10485e7SMark Brown };
685*f10485e7SMark Brown 
686*f10485e7SMark Brown /* OUT3MIX */
687*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_out3mix_controls[] = {
688*f10485e7SMark Brown SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER,
689*f10485e7SMark Brown 	WM8990_LI4O3_BIT, 1, 0),
690*f10485e7SMark Brown SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8990_OUT3_4_MIXER,
691*f10485e7SMark Brown 	WM8990_LPGAO3_BIT, 1, 0),
692*f10485e7SMark Brown };
693*f10485e7SMark Brown 
694*f10485e7SMark Brown /* OUT4MIX */
695*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_out4mix_controls[] = {
696*f10485e7SMark Brown SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8990_OUT3_4_MIXER,
697*f10485e7SMark Brown 	WM8990_RPGAO4_BIT, 1, 0),
698*f10485e7SMark Brown SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER,
699*f10485e7SMark Brown 	WM8990_RI4O4_BIT, 1, 0),
700*f10485e7SMark Brown };
701*f10485e7SMark Brown 
702*f10485e7SMark Brown /* SPKMIX */
703*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_spkmix_controls[] = {
704*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8990_SPEAKER_MIXER,
705*f10485e7SMark Brown 	WM8990_LI2SPK_BIT, 1, 0),
706*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8990_SPEAKER_MIXER,
707*f10485e7SMark Brown 	WM8990_LB2SPK_BIT, 1, 0),
708*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8990_SPEAKER_MIXER,
709*f10485e7SMark Brown 	WM8990_LOPGASPK_BIT, 1, 0),
710*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8990_SPEAKER_MIXER,
711*f10485e7SMark Brown 	WM8990_LDSPK_BIT, 1, 0),
712*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8990_SPEAKER_MIXER,
713*f10485e7SMark Brown 	WM8990_RDSPK_BIT, 1, 0),
714*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8990_SPEAKER_MIXER,
715*f10485e7SMark Brown 	WM8990_ROPGASPK_BIT, 1, 0),
716*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8990_SPEAKER_MIXER,
717*f10485e7SMark Brown 	WM8990_RL12ROP_BIT, 1, 0),
718*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8990_SPEAKER_MIXER,
719*f10485e7SMark Brown 	WM8990_RI2SPK_BIT, 1, 0),
720*f10485e7SMark Brown };
721*f10485e7SMark Brown 
722*f10485e7SMark Brown static const struct snd_soc_dapm_widget wm8990_dapm_widgets[] = {
723*f10485e7SMark Brown /* Input Side */
724*f10485e7SMark Brown /* Input Lines */
725*f10485e7SMark Brown SND_SOC_DAPM_INPUT("LIN1"),
726*f10485e7SMark Brown SND_SOC_DAPM_INPUT("LIN2"),
727*f10485e7SMark Brown SND_SOC_DAPM_INPUT("LIN3"),
728*f10485e7SMark Brown SND_SOC_DAPM_INPUT("LIN4/RXN"),
729*f10485e7SMark Brown SND_SOC_DAPM_INPUT("RIN3"),
730*f10485e7SMark Brown SND_SOC_DAPM_INPUT("RIN4/RXP"),
731*f10485e7SMark Brown SND_SOC_DAPM_INPUT("RIN1"),
732*f10485e7SMark Brown SND_SOC_DAPM_INPUT("RIN2"),
733*f10485e7SMark Brown SND_SOC_DAPM_INPUT("Internal ADC Source"),
734*f10485e7SMark Brown 
735*f10485e7SMark Brown /* DACs */
736*f10485e7SMark Brown SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2,
737*f10485e7SMark Brown 	WM8990_ADCL_ENA_BIT, 0),
738*f10485e7SMark Brown SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8990_POWER_MANAGEMENT_2,
739*f10485e7SMark Brown 	WM8990_ADCR_ENA_BIT, 0),
740*f10485e7SMark Brown 
741*f10485e7SMark Brown /* Input PGAs */
742*f10485e7SMark Brown SND_SOC_DAPM_MIXER("LIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN12_ENA_BIT,
743*f10485e7SMark Brown 	0, &wm8990_dapm_lin12_pga_controls[0],
744*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_lin12_pga_controls)),
745*f10485e7SMark Brown SND_SOC_DAPM_MIXER("LIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN34_ENA_BIT,
746*f10485e7SMark Brown 	0, &wm8990_dapm_lin34_pga_controls[0],
747*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_lin34_pga_controls)),
748*f10485e7SMark Brown SND_SOC_DAPM_MIXER("RIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN12_ENA_BIT,
749*f10485e7SMark Brown 	0, &wm8990_dapm_rin12_pga_controls[0],
750*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_rin12_pga_controls)),
751*f10485e7SMark Brown SND_SOC_DAPM_MIXER("RIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN34_ENA_BIT,
752*f10485e7SMark Brown 	0, &wm8990_dapm_rin34_pga_controls[0],
753*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)),
754*f10485e7SMark Brown 
755*f10485e7SMark Brown /* INMIXL */
756*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0,
757*f10485e7SMark Brown 	&wm8990_dapm_inmixl_controls[0],
758*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_inmixl_controls),
759*f10485e7SMark Brown 	inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
760*f10485e7SMark Brown 
761*f10485e7SMark Brown /* AINLMUX */
762*f10485e7SMark Brown SND_SOC_DAPM_MUX_E("AILNMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
763*f10485e7SMark Brown 	&wm8990_dapm_ainlmux_controls, inmixer_event,
764*f10485e7SMark Brown 	SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
765*f10485e7SMark Brown 
766*f10485e7SMark Brown /* INMIXR */
767*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0,
768*f10485e7SMark Brown 	&wm8990_dapm_inmixr_controls[0],
769*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_inmixr_controls),
770*f10485e7SMark Brown 	inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
771*f10485e7SMark Brown 
772*f10485e7SMark Brown /* AINRMUX */
773*f10485e7SMark Brown SND_SOC_DAPM_MUX_E("AIRNMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
774*f10485e7SMark Brown 	&wm8990_dapm_ainrmux_controls, inmixer_event,
775*f10485e7SMark Brown 	SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
776*f10485e7SMark Brown 
777*f10485e7SMark Brown /* Output Side */
778*f10485e7SMark Brown /* DACs */
779*f10485e7SMark Brown SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8990_POWER_MANAGEMENT_3,
780*f10485e7SMark Brown 	WM8990_DACL_ENA_BIT, 0),
781*f10485e7SMark Brown SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8990_POWER_MANAGEMENT_3,
782*f10485e7SMark Brown 	WM8990_DACR_ENA_BIT, 0),
783*f10485e7SMark Brown 
784*f10485e7SMark Brown /* LOMIX */
785*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("LOMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOMIX_ENA_BIT,
786*f10485e7SMark Brown 	0, &wm8990_dapm_lomix_controls[0],
787*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_lomix_controls),
788*f10485e7SMark Brown 	outmixer_event, SND_SOC_DAPM_PRE_REG),
789*f10485e7SMark Brown 
790*f10485e7SMark Brown /* LONMIX */
791*f10485e7SMark Brown SND_SOC_DAPM_MIXER("LONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LON_ENA_BIT, 0,
792*f10485e7SMark Brown 	&wm8990_dapm_lonmix_controls[0],
793*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_lonmix_controls)),
794*f10485e7SMark Brown 
795*f10485e7SMark Brown /* LOPMIX */
796*f10485e7SMark Brown SND_SOC_DAPM_MIXER("LOPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOP_ENA_BIT, 0,
797*f10485e7SMark Brown 	&wm8990_dapm_lopmix_controls[0],
798*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_lopmix_controls)),
799*f10485e7SMark Brown 
800*f10485e7SMark Brown /* OUT3MIX */
801*f10485e7SMark Brown SND_SOC_DAPM_MIXER("OUT3MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT3_ENA_BIT, 0,
802*f10485e7SMark Brown 	&wm8990_dapm_out3mix_controls[0],
803*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_out3mix_controls)),
804*f10485e7SMark Brown 
805*f10485e7SMark Brown /* SPKMIX */
806*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("SPKMIX", WM8990_POWER_MANAGEMENT_1, WM8990_SPK_ENA_BIT, 0,
807*f10485e7SMark Brown 	&wm8990_dapm_spkmix_controls[0],
808*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_spkmix_controls), outmixer_event,
809*f10485e7SMark Brown 	SND_SOC_DAPM_PRE_REG),
810*f10485e7SMark Brown 
811*f10485e7SMark Brown /* OUT4MIX */
812*f10485e7SMark Brown SND_SOC_DAPM_MIXER("OUT4MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT4_ENA_BIT, 0,
813*f10485e7SMark Brown 	&wm8990_dapm_out4mix_controls[0],
814*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_out4mix_controls)),
815*f10485e7SMark Brown 
816*f10485e7SMark Brown /* ROPMIX */
817*f10485e7SMark Brown SND_SOC_DAPM_MIXER("ROPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROP_ENA_BIT, 0,
818*f10485e7SMark Brown 	&wm8990_dapm_ropmix_controls[0],
819*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_ropmix_controls)),
820*f10485e7SMark Brown 
821*f10485e7SMark Brown /* RONMIX */
822*f10485e7SMark Brown SND_SOC_DAPM_MIXER("RONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_RON_ENA_BIT, 0,
823*f10485e7SMark Brown 	&wm8990_dapm_ronmix_controls[0],
824*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_ronmix_controls)),
825*f10485e7SMark Brown 
826*f10485e7SMark Brown /* ROMIX */
827*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("ROMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROMIX_ENA_BIT,
828*f10485e7SMark Brown 	0, &wm8990_dapm_romix_controls[0],
829*f10485e7SMark Brown 	ARRAY_SIZE(wm8990_dapm_romix_controls),
830*f10485e7SMark Brown 	outmixer_event, SND_SOC_DAPM_PRE_REG),
831*f10485e7SMark Brown 
832*f10485e7SMark Brown /* LOUT PGA */
833*f10485e7SMark Brown SND_SOC_DAPM_PGA("LOUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_LOUT_ENA_BIT, 0,
834*f10485e7SMark Brown 	NULL, 0),
835*f10485e7SMark Brown 
836*f10485e7SMark Brown /* ROUT PGA */
837*f10485e7SMark Brown SND_SOC_DAPM_PGA("ROUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_ROUT_ENA_BIT, 0,
838*f10485e7SMark Brown 	NULL, 0),
839*f10485e7SMark Brown 
840*f10485e7SMark Brown /* LOPGA */
841*f10485e7SMark Brown SND_SOC_DAPM_PGA("LOPGA", WM8990_POWER_MANAGEMENT_3, WM8990_LOPGA_ENA_BIT, 0,
842*f10485e7SMark Brown 	NULL, 0),
843*f10485e7SMark Brown 
844*f10485e7SMark Brown /* ROPGA */
845*f10485e7SMark Brown SND_SOC_DAPM_PGA("ROPGA", WM8990_POWER_MANAGEMENT_3, WM8990_ROPGA_ENA_BIT, 0,
846*f10485e7SMark Brown 	NULL, 0),
847*f10485e7SMark Brown 
848*f10485e7SMark Brown /* MICBIAS */
849*f10485e7SMark Brown SND_SOC_DAPM_MICBIAS("MICBIAS", WM8990_POWER_MANAGEMENT_1,
850*f10485e7SMark Brown 	WM8990_MICBIAS_ENA_BIT, 0),
851*f10485e7SMark Brown 
852*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("LON"),
853*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("LOP"),
854*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("OUT3"),
855*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("LOUT"),
856*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("SPKN"),
857*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("SPKP"),
858*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("ROUT"),
859*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("OUT4"),
860*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("ROP"),
861*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("RON"),
862*f10485e7SMark Brown 
863*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
864*f10485e7SMark Brown };
865*f10485e7SMark Brown 
866*f10485e7SMark Brown static const struct snd_soc_dapm_route audio_map[] = {
867*f10485e7SMark Brown 	/* Make DACs turn on when playing even if not mixed into any outputs */
868*f10485e7SMark Brown 	{"Internal DAC Sink", NULL, "Left DAC"},
869*f10485e7SMark Brown 	{"Internal DAC Sink", NULL, "Right DAC"},
870*f10485e7SMark Brown 
871*f10485e7SMark Brown 	/* Make ADCs turn on when recording even if not mixed from any inputs */
872*f10485e7SMark Brown 	{"Left ADC", NULL, "Internal ADC Source"},
873*f10485e7SMark Brown 	{"Right ADC", NULL, "Internal ADC Source"},
874*f10485e7SMark Brown 
875*f10485e7SMark Brown 	/* Input Side */
876*f10485e7SMark Brown 	/* LIN12 PGA */
877*f10485e7SMark Brown 	{"LIN12 PGA", "LIN1 Switch", "LIN1"},
878*f10485e7SMark Brown 	{"LIN12 PGA", "LIN2 Switch", "LIN2"},
879*f10485e7SMark Brown 	/* LIN34 PGA */
880*f10485e7SMark Brown 	{"LIN34 PGA", "LIN3 Switch", "LIN3"},
881*f10485e7SMark Brown 	{"LIN34 PGA", "LIN4 Switch", "LIN4"},
882*f10485e7SMark Brown 	/* INMIXL */
883*f10485e7SMark Brown 	{"INMIXL", "Record Left Volume", "LOMIX"},
884*f10485e7SMark Brown 	{"INMIXL", "LIN2 Volume", "LIN2"},
885*f10485e7SMark Brown 	{"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
886*f10485e7SMark Brown 	{"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
887*f10485e7SMark Brown 	/* AILNMUX */
888*f10485e7SMark Brown 	{"AILNMUX", "INMIXL Mix", "INMIXL"},
889*f10485e7SMark Brown 	{"AILNMUX", "DIFFINL Mix", "LIN12PGA"},
890*f10485e7SMark Brown 	{"AILNMUX", "DIFFINL Mix", "LIN34PGA"},
891*f10485e7SMark Brown 	{"AILNMUX", "RXVOICE Mix", "LIN4/RXN"},
892*f10485e7SMark Brown 	{"AILNMUX", "RXVOICE Mix", "RIN4/RXP"},
893*f10485e7SMark Brown 	/* ADC */
894*f10485e7SMark Brown 	{"Left ADC", NULL, "AILNMUX"},
895*f10485e7SMark Brown 
896*f10485e7SMark Brown 	/* RIN12 PGA */
897*f10485e7SMark Brown 	{"RIN12 PGA", "RIN1 Switch", "RIN1"},
898*f10485e7SMark Brown 	{"RIN12 PGA", "RIN2 Switch", "RIN2"},
899*f10485e7SMark Brown 	/* RIN34 PGA */
900*f10485e7SMark Brown 	{"RIN34 PGA", "RIN3 Switch", "RIN3"},
901*f10485e7SMark Brown 	{"RIN34 PGA", "RIN4 Switch", "RIN4"},
902*f10485e7SMark Brown 	/* INMIXL */
903*f10485e7SMark Brown 	{"INMIXR", "Record Right Volume", "ROMIX"},
904*f10485e7SMark Brown 	{"INMIXR", "RIN2 Volume", "RIN2"},
905*f10485e7SMark Brown 	{"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
906*f10485e7SMark Brown 	{"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
907*f10485e7SMark Brown 	/* AIRNMUX */
908*f10485e7SMark Brown 	{"AIRNMUX", "INMIXR Mix", "INMIXR"},
909*f10485e7SMark Brown 	{"AIRNMUX", "DIFFINR Mix", "RIN12PGA"},
910*f10485e7SMark Brown 	{"AIRNMUX", "DIFFINR Mix", "RIN34PGA"},
911*f10485e7SMark Brown 	{"AIRNMUX", "RXVOICE Mix", "RIN4/RXN"},
912*f10485e7SMark Brown 	{"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"},
913*f10485e7SMark Brown 	/* ADC */
914*f10485e7SMark Brown 	{"Right ADC", NULL, "AIRNMUX"},
915*f10485e7SMark Brown 
916*f10485e7SMark Brown 	/* LOMIX */
917*f10485e7SMark Brown 	{"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
918*f10485e7SMark Brown 	{"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"},
919*f10485e7SMark Brown 	{"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
920*f10485e7SMark Brown 	{"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
921*f10485e7SMark Brown 	{"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"},
922*f10485e7SMark Brown 	{"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"},
923*f10485e7SMark Brown 	{"LOMIX", "LOMIX Left DAC Switch", "Left DAC"},
924*f10485e7SMark Brown 
925*f10485e7SMark Brown 	/* ROMIX */
926*f10485e7SMark Brown 	{"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"},
927*f10485e7SMark Brown 	{"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"},
928*f10485e7SMark Brown 	{"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
929*f10485e7SMark Brown 	{"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
930*f10485e7SMark Brown 	{"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"},
931*f10485e7SMark Brown 	{"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"},
932*f10485e7SMark Brown 	{"ROMIX", "ROMIX Right DAC Switch", "Right DAC"},
933*f10485e7SMark Brown 
934*f10485e7SMark Brown 	/* SPKMIX */
935*f10485e7SMark Brown 	{"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"},
936*f10485e7SMark Brown 	{"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"},
937*f10485e7SMark Brown 	{"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"},
938*f10485e7SMark Brown 	{"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"},
939*f10485e7SMark Brown 	{"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"},
940*f10485e7SMark Brown 	{"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"},
941*f10485e7SMark Brown 	{"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"},
942*f10485e7SMark Brown 	{"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"},
943*f10485e7SMark Brown 
944*f10485e7SMark Brown 	/* LONMIX */
945*f10485e7SMark Brown 	{"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"},
946*f10485e7SMark Brown 	{"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"},
947*f10485e7SMark Brown 	{"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"},
948*f10485e7SMark Brown 
949*f10485e7SMark Brown 	/* LOPMIX */
950*f10485e7SMark Brown 	{"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"},
951*f10485e7SMark Brown 	{"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"},
952*f10485e7SMark Brown 	{"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
953*f10485e7SMark Brown 
954*f10485e7SMark Brown 	/* OUT3MIX */
955*f10485e7SMark Brown 	{"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXP"},
956*f10485e7SMark Brown 	{"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
957*f10485e7SMark Brown 
958*f10485e7SMark Brown 	/* OUT4MIX */
959*f10485e7SMark Brown 	{"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"},
960*f10485e7SMark Brown 	{"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"},
961*f10485e7SMark Brown 
962*f10485e7SMark Brown 	/* RONMIX */
963*f10485e7SMark Brown 	{"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"},
964*f10485e7SMark Brown 	{"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"},
965*f10485e7SMark Brown 	{"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"},
966*f10485e7SMark Brown 
967*f10485e7SMark Brown 	/* ROPMIX */
968*f10485e7SMark Brown 	{"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"},
969*f10485e7SMark Brown 	{"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"},
970*f10485e7SMark Brown 	{"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"},
971*f10485e7SMark Brown 
972*f10485e7SMark Brown 	/* Out Mixer PGAs */
973*f10485e7SMark Brown 	{"LOPGA", NULL, "LOMIX"},
974*f10485e7SMark Brown 	{"ROPGA", NULL, "ROMIX"},
975*f10485e7SMark Brown 
976*f10485e7SMark Brown 	{"LOUT PGA", NULL, "LOMIX"},
977*f10485e7SMark Brown 	{"ROUT PGA", NULL, "ROMIX"},
978*f10485e7SMark Brown 
979*f10485e7SMark Brown 	/* Output Pins */
980*f10485e7SMark Brown 	{"LON", NULL, "LONMIX"},
981*f10485e7SMark Brown 	{"LOP", NULL, "LOPMIX"},
982*f10485e7SMark Brown 	{"OUT", NULL, "OUT3MIX"},
983*f10485e7SMark Brown 	{"LOUT", NULL, "LOUT PGA"},
984*f10485e7SMark Brown 	{"SPKN", NULL, "SPKMIX"},
985*f10485e7SMark Brown 	{"ROUT", NULL, "ROUT PGA"},
986*f10485e7SMark Brown 	{"OUT4", NULL, "OUT4MIX"},
987*f10485e7SMark Brown 	{"ROP", NULL, "ROPMIX"},
988*f10485e7SMark Brown 	{"RON", NULL, "RONMIX"},
989*f10485e7SMark Brown };
990*f10485e7SMark Brown 
991*f10485e7SMark Brown static int wm8990_add_widgets(struct snd_soc_codec *codec)
992*f10485e7SMark Brown {
993*f10485e7SMark Brown 	snd_soc_dapm_new_controls(codec, wm8990_dapm_widgets,
994*f10485e7SMark Brown 				  ARRAY_SIZE(wm8990_dapm_widgets));
995*f10485e7SMark Brown 
996*f10485e7SMark Brown 	/* set up the WM8990 audio map */
997*f10485e7SMark Brown 	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
998*f10485e7SMark Brown 
999*f10485e7SMark Brown 	snd_soc_dapm_new_widgets(codec);
1000*f10485e7SMark Brown 	return 0;
1001*f10485e7SMark Brown }
1002*f10485e7SMark Brown 
1003*f10485e7SMark Brown /* PLL divisors */
1004*f10485e7SMark Brown struct _pll_div {
1005*f10485e7SMark Brown 	u32 div2;
1006*f10485e7SMark Brown 	u32 n;
1007*f10485e7SMark Brown 	u32 k;
1008*f10485e7SMark Brown };
1009*f10485e7SMark Brown 
1010*f10485e7SMark Brown /* The size in bits of the pll divide multiplied by 10
1011*f10485e7SMark Brown  * to allow rounding later */
1012*f10485e7SMark Brown #define FIXED_PLL_SIZE ((1 << 16) * 10)
1013*f10485e7SMark Brown 
1014*f10485e7SMark Brown static void pll_factors(struct _pll_div *pll_div, unsigned int target,
1015*f10485e7SMark Brown 	unsigned int source)
1016*f10485e7SMark Brown {
1017*f10485e7SMark Brown 	u64 Kpart;
1018*f10485e7SMark Brown 	unsigned int K, Ndiv, Nmod;
1019*f10485e7SMark Brown 
1020*f10485e7SMark Brown 
1021*f10485e7SMark Brown 	Ndiv = target / source;
1022*f10485e7SMark Brown 	if (Ndiv < 6) {
1023*f10485e7SMark Brown 		source >>= 1;
1024*f10485e7SMark Brown 		pll_div->div2 = 1;
1025*f10485e7SMark Brown 		Ndiv = target / source;
1026*f10485e7SMark Brown 	} else
1027*f10485e7SMark Brown 		pll_div->div2 = 0;
1028*f10485e7SMark Brown 
1029*f10485e7SMark Brown 	if ((Ndiv < 6) || (Ndiv > 12))
1030*f10485e7SMark Brown 		printk(KERN_WARNING
1031*f10485e7SMark Brown 		"WM8990 N value outwith recommended range! N = %d\n", Ndiv);
1032*f10485e7SMark Brown 
1033*f10485e7SMark Brown 	pll_div->n = Ndiv;
1034*f10485e7SMark Brown 	Nmod = target % source;
1035*f10485e7SMark Brown 	Kpart = FIXED_PLL_SIZE * (long long)Nmod;
1036*f10485e7SMark Brown 
1037*f10485e7SMark Brown 	do_div(Kpart, source);
1038*f10485e7SMark Brown 
1039*f10485e7SMark Brown 	K = Kpart & 0xFFFFFFFF;
1040*f10485e7SMark Brown 
1041*f10485e7SMark Brown 	/* Check if we need to round */
1042*f10485e7SMark Brown 	if ((K % 10) >= 5)
1043*f10485e7SMark Brown 		K += 5;
1044*f10485e7SMark Brown 
1045*f10485e7SMark Brown 	/* Move down to proper range now rounding is done */
1046*f10485e7SMark Brown 	K /= 10;
1047*f10485e7SMark Brown 
1048*f10485e7SMark Brown 	pll_div->k = K;
1049*f10485e7SMark Brown }
1050*f10485e7SMark Brown 
1051*f10485e7SMark Brown static int wm8990_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
1052*f10485e7SMark Brown 		int pll_id, unsigned int freq_in, unsigned int freq_out)
1053*f10485e7SMark Brown {
1054*f10485e7SMark Brown 	u16 reg;
1055*f10485e7SMark Brown 	struct snd_soc_codec *codec = codec_dai->codec;
1056*f10485e7SMark Brown 	struct _pll_div pll_div;
1057*f10485e7SMark Brown 
1058*f10485e7SMark Brown 	if (freq_in && freq_out) {
1059*f10485e7SMark Brown 		pll_factors(&pll_div, freq_out * 4, freq_in);
1060*f10485e7SMark Brown 
1061*f10485e7SMark Brown 		/* Turn on PLL */
1062*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
1063*f10485e7SMark Brown 		reg |= WM8990_PLL_ENA;
1064*f10485e7SMark Brown 		wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
1065*f10485e7SMark Brown 
1066*f10485e7SMark Brown 		/* sysclk comes from PLL */
1067*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2);
1068*f10485e7SMark Brown 		wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
1069*f10485e7SMark Brown 
1070*f10485e7SMark Brown 		/* set up N , fractional mode and pre-divisor if neccessary */
1071*f10485e7SMark Brown 		wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
1072*f10485e7SMark Brown 			(pll_div.div2?WM8990_PRESCALE:0));
1073*f10485e7SMark Brown 		wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
1074*f10485e7SMark Brown 		wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
1075*f10485e7SMark Brown 	} else {
1076*f10485e7SMark Brown 		/* Turn on PLL */
1077*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
1078*f10485e7SMark Brown 		reg &= ~WM8990_PLL_ENA;
1079*f10485e7SMark Brown 		wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
1080*f10485e7SMark Brown 	}
1081*f10485e7SMark Brown 	return 0;
1082*f10485e7SMark Brown }
1083*f10485e7SMark Brown 
1084*f10485e7SMark Brown /*
1085*f10485e7SMark Brown  * Clock after PLL and dividers
1086*f10485e7SMark Brown  */
1087*f10485e7SMark Brown static int wm8990_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
1088*f10485e7SMark Brown 		int clk_id, unsigned int freq, int dir)
1089*f10485e7SMark Brown {
1090*f10485e7SMark Brown 	struct snd_soc_codec *codec = codec_dai->codec;
1091*f10485e7SMark Brown 	struct wm8990_priv *wm8990 = codec->private_data;
1092*f10485e7SMark Brown 
1093*f10485e7SMark Brown 	wm8990->sysclk = freq;
1094*f10485e7SMark Brown 	return 0;
1095*f10485e7SMark Brown }
1096*f10485e7SMark Brown 
1097*f10485e7SMark Brown /*
1098*f10485e7SMark Brown  * Set's ADC and Voice DAC format.
1099*f10485e7SMark Brown  */
1100*f10485e7SMark Brown static int wm8990_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1101*f10485e7SMark Brown 		unsigned int fmt)
1102*f10485e7SMark Brown {
1103*f10485e7SMark Brown 	struct snd_soc_codec *codec = codec_dai->codec;
1104*f10485e7SMark Brown 	u16 audio1, audio3;
1105*f10485e7SMark Brown 
1106*f10485e7SMark Brown 	audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
1107*f10485e7SMark Brown 	audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3);
1108*f10485e7SMark Brown 
1109*f10485e7SMark Brown 	/* set master/slave audio interface */
1110*f10485e7SMark Brown 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1111*f10485e7SMark Brown 	case SND_SOC_DAIFMT_CBS_CFS:
1112*f10485e7SMark Brown 		audio3 &= ~WM8990_AIF_MSTR1;
1113*f10485e7SMark Brown 		break;
1114*f10485e7SMark Brown 	case SND_SOC_DAIFMT_CBM_CFM:
1115*f10485e7SMark Brown 		audio3 |= WM8990_AIF_MSTR1;
1116*f10485e7SMark Brown 		break;
1117*f10485e7SMark Brown 	default:
1118*f10485e7SMark Brown 		return -EINVAL;
1119*f10485e7SMark Brown 	}
1120*f10485e7SMark Brown 
1121*f10485e7SMark Brown 	audio1 &= ~WM8990_AIF_FMT_MASK;
1122*f10485e7SMark Brown 
1123*f10485e7SMark Brown 	/* interface format */
1124*f10485e7SMark Brown 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1125*f10485e7SMark Brown 	case SND_SOC_DAIFMT_I2S:
1126*f10485e7SMark Brown 		audio1 |= WM8990_AIF_TMF_I2S;
1127*f10485e7SMark Brown 		audio1 &= ~WM8990_AIF_LRCLK_INV;
1128*f10485e7SMark Brown 		break;
1129*f10485e7SMark Brown 	case SND_SOC_DAIFMT_RIGHT_J:
1130*f10485e7SMark Brown 		audio1 |= WM8990_AIF_TMF_RIGHTJ;
1131*f10485e7SMark Brown 		audio1 &= ~WM8990_AIF_LRCLK_INV;
1132*f10485e7SMark Brown 		break;
1133*f10485e7SMark Brown 	case SND_SOC_DAIFMT_LEFT_J:
1134*f10485e7SMark Brown 		audio1 |= WM8990_AIF_TMF_LEFTJ;
1135*f10485e7SMark Brown 		audio1 &= ~WM8990_AIF_LRCLK_INV;
1136*f10485e7SMark Brown 		break;
1137*f10485e7SMark Brown 	case SND_SOC_DAIFMT_DSP_A:
1138*f10485e7SMark Brown 		audio1 |= WM8990_AIF_TMF_DSP;
1139*f10485e7SMark Brown 		audio1 &= ~WM8990_AIF_LRCLK_INV;
1140*f10485e7SMark Brown 		break;
1141*f10485e7SMark Brown 	case SND_SOC_DAIFMT_DSP_B:
1142*f10485e7SMark Brown 		audio1 |= WM8990_AIF_TMF_DSP | WM8990_AIF_LRCLK_INV;
1143*f10485e7SMark Brown 		break;
1144*f10485e7SMark Brown 	default:
1145*f10485e7SMark Brown 		return -EINVAL;
1146*f10485e7SMark Brown 	}
1147*f10485e7SMark Brown 
1148*f10485e7SMark Brown 	wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
1149*f10485e7SMark Brown 	wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
1150*f10485e7SMark Brown 	return 0;
1151*f10485e7SMark Brown }
1152*f10485e7SMark Brown 
1153*f10485e7SMark Brown static int wm8990_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
1154*f10485e7SMark Brown 		int div_id, int div)
1155*f10485e7SMark Brown {
1156*f10485e7SMark Brown 	struct snd_soc_codec *codec = codec_dai->codec;
1157*f10485e7SMark Brown 	u16 reg;
1158*f10485e7SMark Brown 
1159*f10485e7SMark Brown 	switch (div_id) {
1160*f10485e7SMark Brown 	case WM8990_MCLK_DIV:
1161*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
1162*f10485e7SMark Brown 			~WM8990_MCLK_DIV_MASK;
1163*f10485e7SMark Brown 		wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
1164*f10485e7SMark Brown 		break;
1165*f10485e7SMark Brown 	case WM8990_DACCLK_DIV:
1166*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
1167*f10485e7SMark Brown 			~WM8990_DAC_CLKDIV_MASK;
1168*f10485e7SMark Brown 		wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
1169*f10485e7SMark Brown 		break;
1170*f10485e7SMark Brown 	case WM8990_ADCCLK_DIV:
1171*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
1172*f10485e7SMark Brown 			~WM8990_ADC_CLKDIV_MASK;
1173*f10485e7SMark Brown 		wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
1174*f10485e7SMark Brown 		break;
1175*f10485e7SMark Brown 	case WM8990_BCLK_DIV:
1176*f10485e7SMark Brown 		reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) &
1177*f10485e7SMark Brown 			~WM8990_BCLK_DIV_MASK;
1178*f10485e7SMark Brown 		wm8990_write(codec, WM8990_CLOCKING_1, reg | div);
1179*f10485e7SMark Brown 		break;
1180*f10485e7SMark Brown 	default:
1181*f10485e7SMark Brown 		return -EINVAL;
1182*f10485e7SMark Brown 	}
1183*f10485e7SMark Brown 
1184*f10485e7SMark Brown 	return 0;
1185*f10485e7SMark Brown }
1186*f10485e7SMark Brown 
1187*f10485e7SMark Brown /*
1188*f10485e7SMark Brown  * Set PCM DAI bit size and sample rate.
1189*f10485e7SMark Brown  */
1190*f10485e7SMark Brown static int wm8990_hw_params(struct snd_pcm_substream *substream,
1191*f10485e7SMark Brown 	struct snd_pcm_hw_params *params)
1192*f10485e7SMark Brown {
1193*f10485e7SMark Brown 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
1194*f10485e7SMark Brown 	struct snd_soc_device *socdev = rtd->socdev;
1195*f10485e7SMark Brown 	struct snd_soc_codec *codec = socdev->codec;
1196*f10485e7SMark Brown 	u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
1197*f10485e7SMark Brown 
1198*f10485e7SMark Brown 	audio1 &= ~WM8990_AIF_WL_MASK;
1199*f10485e7SMark Brown 	/* bit size */
1200*f10485e7SMark Brown 	switch (params_format(params)) {
1201*f10485e7SMark Brown 	case SNDRV_PCM_FORMAT_S16_LE:
1202*f10485e7SMark Brown 		break;
1203*f10485e7SMark Brown 	case SNDRV_PCM_FORMAT_S20_3LE:
1204*f10485e7SMark Brown 		audio1 |= WM8990_AIF_WL_20BITS;
1205*f10485e7SMark Brown 		break;
1206*f10485e7SMark Brown 	case SNDRV_PCM_FORMAT_S24_LE:
1207*f10485e7SMark Brown 		audio1 |= WM8990_AIF_WL_24BITS;
1208*f10485e7SMark Brown 		break;
1209*f10485e7SMark Brown 	case SNDRV_PCM_FORMAT_S32_LE:
1210*f10485e7SMark Brown 		audio1 |= WM8990_AIF_WL_32BITS;
1211*f10485e7SMark Brown 		break;
1212*f10485e7SMark Brown 	}
1213*f10485e7SMark Brown 
1214*f10485e7SMark Brown 	wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
1215*f10485e7SMark Brown 	return 0;
1216*f10485e7SMark Brown }
1217*f10485e7SMark Brown 
1218*f10485e7SMark Brown static int wm8990_mute(struct snd_soc_codec_dai *dai, int mute)
1219*f10485e7SMark Brown {
1220*f10485e7SMark Brown 	struct snd_soc_codec *codec = dai->codec;
1221*f10485e7SMark Brown 	u16 val;
1222*f10485e7SMark Brown 
1223*f10485e7SMark Brown 	val  = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
1224*f10485e7SMark Brown 
1225*f10485e7SMark Brown 	if (mute)
1226*f10485e7SMark Brown 		wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
1227*f10485e7SMark Brown 	else
1228*f10485e7SMark Brown 		wm8990_write(codec, WM8990_DAC_CTRL, val);
1229*f10485e7SMark Brown 
1230*f10485e7SMark Brown 	return 0;
1231*f10485e7SMark Brown }
1232*f10485e7SMark Brown 
1233*f10485e7SMark Brown static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1234*f10485e7SMark Brown 	enum snd_soc_bias_level level)
1235*f10485e7SMark Brown {
1236*f10485e7SMark Brown 	u16 val;
1237*f10485e7SMark Brown 
1238*f10485e7SMark Brown 	switch (level) {
1239*f10485e7SMark Brown 	case SND_SOC_BIAS_ON:
1240*f10485e7SMark Brown 		break;
1241*f10485e7SMark Brown 	case SND_SOC_BIAS_PREPARE:
1242*f10485e7SMark Brown 		break;
1243*f10485e7SMark Brown 	case SND_SOC_BIAS_STANDBY:
1244*f10485e7SMark Brown 		if (codec->bias_level == SND_SOC_BIAS_OFF) {
1245*f10485e7SMark Brown 			/* Enable all output discharge bits */
1246*f10485e7SMark Brown 			wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
1247*f10485e7SMark Brown 				WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
1248*f10485e7SMark Brown 				WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
1249*f10485e7SMark Brown 				WM8990_DIS_ROUT);
1250*f10485e7SMark Brown 
1251*f10485e7SMark Brown 			/* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
1252*f10485e7SMark Brown 			wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1253*f10485e7SMark Brown 				     WM8990_BUFDCOPEN | WM8990_POBCTRL |
1254*f10485e7SMark Brown 				     WM8990_VMIDTOG);
1255*f10485e7SMark Brown 
1256*f10485e7SMark Brown 			/* Delay to allow output caps to discharge */
1257*f10485e7SMark Brown 			msleep(msecs_to_jiffies(300));
1258*f10485e7SMark Brown 
1259*f10485e7SMark Brown 			/* Disable VMIDTOG */
1260*f10485e7SMark Brown 			wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1261*f10485e7SMark Brown 				     WM8990_BUFDCOPEN | WM8990_POBCTRL);
1262*f10485e7SMark Brown 
1263*f10485e7SMark Brown 			/* disable all output discharge bits */
1264*f10485e7SMark Brown 			wm8990_write(codec, WM8990_ANTIPOP1, 0);
1265*f10485e7SMark Brown 
1266*f10485e7SMark Brown 			/* Enable outputs */
1267*f10485e7SMark Brown 			wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
1268*f10485e7SMark Brown 
1269*f10485e7SMark Brown 			msleep(msecs_to_jiffies(50));
1270*f10485e7SMark Brown 
1271*f10485e7SMark Brown 			/* Enable VMID at 2x50k */
1272*f10485e7SMark Brown 			wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
1273*f10485e7SMark Brown 
1274*f10485e7SMark Brown 			msleep(msecs_to_jiffies(100));
1275*f10485e7SMark Brown 
1276*f10485e7SMark Brown 			/* Enable VREF */
1277*f10485e7SMark Brown 			wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
1278*f10485e7SMark Brown 
1279*f10485e7SMark Brown 			msleep(msecs_to_jiffies(600));
1280*f10485e7SMark Brown 
1281*f10485e7SMark Brown 			/* Enable BUFIOEN */
1282*f10485e7SMark Brown 			wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1283*f10485e7SMark Brown 				     WM8990_BUFDCOPEN | WM8990_POBCTRL |
1284*f10485e7SMark Brown 				     WM8990_BUFIOEN);
1285*f10485e7SMark Brown 
1286*f10485e7SMark Brown 			/* Disable outputs */
1287*f10485e7SMark Brown 			wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
1288*f10485e7SMark Brown 
1289*f10485e7SMark Brown 			/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1290*f10485e7SMark Brown 			wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
1291*f10485e7SMark Brown 		} else {
1292*f10485e7SMark Brown 			/* ON -> standby */
1293*f10485e7SMark Brown 
1294*f10485e7SMark Brown 		}
1295*f10485e7SMark Brown 		break;
1296*f10485e7SMark Brown 
1297*f10485e7SMark Brown 	case SND_SOC_BIAS_OFF:
1298*f10485e7SMark Brown 		/* Enable POBCTRL and SOFT_ST */
1299*f10485e7SMark Brown 		wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1300*f10485e7SMark Brown 			WM8990_POBCTRL | WM8990_BUFIOEN);
1301*f10485e7SMark Brown 
1302*f10485e7SMark Brown 		/* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
1303*f10485e7SMark Brown 		wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1304*f10485e7SMark Brown 			WM8990_BUFDCOPEN | WM8990_POBCTRL |
1305*f10485e7SMark Brown 			WM8990_BUFIOEN);
1306*f10485e7SMark Brown 
1307*f10485e7SMark Brown 		/* mute DAC */
1308*f10485e7SMark Brown 		val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL);
1309*f10485e7SMark Brown 		wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
1310*f10485e7SMark Brown 
1311*f10485e7SMark Brown 		/* Enable any disabled outputs */
1312*f10485e7SMark Brown 		wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
1313*f10485e7SMark Brown 
1314*f10485e7SMark Brown 		/* Disable VMID */
1315*f10485e7SMark Brown 		wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
1316*f10485e7SMark Brown 
1317*f10485e7SMark Brown 		msleep(msecs_to_jiffies(300));
1318*f10485e7SMark Brown 
1319*f10485e7SMark Brown 		/* Enable all output discharge bits */
1320*f10485e7SMark Brown 		wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
1321*f10485e7SMark Brown 			WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
1322*f10485e7SMark Brown 			WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
1323*f10485e7SMark Brown 			WM8990_DIS_ROUT);
1324*f10485e7SMark Brown 
1325*f10485e7SMark Brown 		/* Disable VREF */
1326*f10485e7SMark Brown 		wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
1327*f10485e7SMark Brown 
1328*f10485e7SMark Brown 		/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1329*f10485e7SMark Brown 		wm8990_write(codec, WM8990_ANTIPOP2, 0x0);
1330*f10485e7SMark Brown 		break;
1331*f10485e7SMark Brown 	}
1332*f10485e7SMark Brown 
1333*f10485e7SMark Brown 	codec->bias_level = level;
1334*f10485e7SMark Brown 	return 0;
1335*f10485e7SMark Brown }
1336*f10485e7SMark Brown 
1337*f10485e7SMark Brown #define WM8990_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
1338*f10485e7SMark Brown 	SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
1339*f10485e7SMark Brown 	SNDRV_PCM_RATE_48000)
1340*f10485e7SMark Brown 
1341*f10485e7SMark Brown #define WM8990_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1342*f10485e7SMark Brown 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1343*f10485e7SMark Brown 
1344*f10485e7SMark Brown /*
1345*f10485e7SMark Brown  * The WM8990 supports 2 different and mutually exclusive DAI
1346*f10485e7SMark Brown  * configurations.
1347*f10485e7SMark Brown  *
1348*f10485e7SMark Brown  * 1. ADC/DAC on Primary Interface
1349*f10485e7SMark Brown  * 2. ADC on Primary Interface/DAC on secondary
1350*f10485e7SMark Brown  */
1351*f10485e7SMark Brown struct snd_soc_codec_dai wm8990_dai = {
1352*f10485e7SMark Brown /* ADC/DAC on primary */
1353*f10485e7SMark Brown 	.name = "WM8990 ADC/DAC Primary",
1354*f10485e7SMark Brown 	.id = 1,
1355*f10485e7SMark Brown 	.playback = {
1356*f10485e7SMark Brown 		.stream_name = "Playback",
1357*f10485e7SMark Brown 		.channels_min = 1,
1358*f10485e7SMark Brown 		.channels_max = 2,
1359*f10485e7SMark Brown 		.rates = WM8990_RATES,
1360*f10485e7SMark Brown 		.formats = WM8990_FORMATS,},
1361*f10485e7SMark Brown 	.capture = {
1362*f10485e7SMark Brown 		.stream_name = "Capture",
1363*f10485e7SMark Brown 		.channels_min = 1,
1364*f10485e7SMark Brown 		.channels_max = 2,
1365*f10485e7SMark Brown 		.rates = WM8990_RATES,
1366*f10485e7SMark Brown 		.formats = WM8990_FORMATS,},
1367*f10485e7SMark Brown 	.ops = {
1368*f10485e7SMark Brown 		.hw_params = wm8990_hw_params,},
1369*f10485e7SMark Brown 	.dai_ops = {
1370*f10485e7SMark Brown 		.digital_mute = wm8990_mute,
1371*f10485e7SMark Brown 		.set_fmt = wm8990_set_dai_fmt,
1372*f10485e7SMark Brown 		.set_clkdiv = wm8990_set_dai_clkdiv,
1373*f10485e7SMark Brown 		.set_pll = wm8990_set_dai_pll,
1374*f10485e7SMark Brown 		.set_sysclk = wm8990_set_dai_sysclk,
1375*f10485e7SMark Brown 	},
1376*f10485e7SMark Brown };
1377*f10485e7SMark Brown EXPORT_SYMBOL_GPL(wm8990_dai);
1378*f10485e7SMark Brown 
1379*f10485e7SMark Brown static int wm8990_suspend(struct platform_device *pdev, pm_message_t state)
1380*f10485e7SMark Brown {
1381*f10485e7SMark Brown 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1382*f10485e7SMark Brown 	struct snd_soc_codec *codec = socdev->codec;
1383*f10485e7SMark Brown 
1384*f10485e7SMark Brown 	/* we only need to suspend if we are a valid card */
1385*f10485e7SMark Brown 	if (!codec->card)
1386*f10485e7SMark Brown 		return 0;
1387*f10485e7SMark Brown 
1388*f10485e7SMark Brown 	wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
1389*f10485e7SMark Brown 	return 0;
1390*f10485e7SMark Brown }
1391*f10485e7SMark Brown 
1392*f10485e7SMark Brown static int wm8990_resume(struct platform_device *pdev)
1393*f10485e7SMark Brown {
1394*f10485e7SMark Brown 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1395*f10485e7SMark Brown 	struct snd_soc_codec *codec = socdev->codec;
1396*f10485e7SMark Brown 	int i;
1397*f10485e7SMark Brown 	u8 data[2];
1398*f10485e7SMark Brown 	u16 *cache = codec->reg_cache;
1399*f10485e7SMark Brown 
1400*f10485e7SMark Brown 	/* we only need to resume if we are a valid card */
1401*f10485e7SMark Brown 	if (!codec->card)
1402*f10485e7SMark Brown 		return 0;
1403*f10485e7SMark Brown 
1404*f10485e7SMark Brown 	/* Sync reg_cache with the hardware */
1405*f10485e7SMark Brown 	for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) {
1406*f10485e7SMark Brown 		if (i + 1 == WM8990_RESET)
1407*f10485e7SMark Brown 			continue;
1408*f10485e7SMark Brown 		data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
1409*f10485e7SMark Brown 		data[1] = cache[i] & 0x00ff;
1410*f10485e7SMark Brown 		codec->hw_write(codec->control_data, data, 2);
1411*f10485e7SMark Brown 	}
1412*f10485e7SMark Brown 
1413*f10485e7SMark Brown 	wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1414*f10485e7SMark Brown 	return 0;
1415*f10485e7SMark Brown }
1416*f10485e7SMark Brown 
1417*f10485e7SMark Brown /*
1418*f10485e7SMark Brown  * initialise the WM8990 driver
1419*f10485e7SMark Brown  * register the mixer and dsp interfaces with the kernel
1420*f10485e7SMark Brown  */
1421*f10485e7SMark Brown static int wm8990_init(struct snd_soc_device *socdev)
1422*f10485e7SMark Brown {
1423*f10485e7SMark Brown 	struct snd_soc_codec *codec = socdev->codec;
1424*f10485e7SMark Brown 	u16 reg;
1425*f10485e7SMark Brown 	int ret = 0;
1426*f10485e7SMark Brown 
1427*f10485e7SMark Brown 	codec->name = "WM8990";
1428*f10485e7SMark Brown 	codec->owner = THIS_MODULE;
1429*f10485e7SMark Brown 	codec->read = wm8990_read_reg_cache;
1430*f10485e7SMark Brown 	codec->write = wm8990_write;
1431*f10485e7SMark Brown 	codec->set_bias_level = wm8990_set_bias_level;
1432*f10485e7SMark Brown 	codec->dai = &wm8990_dai;
1433*f10485e7SMark Brown 	codec->num_dai = 2;
1434*f10485e7SMark Brown 	codec->reg_cache_size = ARRAY_SIZE(wm8990_reg);
1435*f10485e7SMark Brown 	codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL);
1436*f10485e7SMark Brown 
1437*f10485e7SMark Brown 	if (codec->reg_cache == NULL)
1438*f10485e7SMark Brown 		return -ENOMEM;
1439*f10485e7SMark Brown 
1440*f10485e7SMark Brown 	wm8990_reset(codec);
1441*f10485e7SMark Brown 
1442*f10485e7SMark Brown 	/* register pcms */
1443*f10485e7SMark Brown 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1444*f10485e7SMark Brown 	if (ret < 0) {
1445*f10485e7SMark Brown 		printk(KERN_ERR "wm8990: failed to create pcms\n");
1446*f10485e7SMark Brown 		goto pcm_err;
1447*f10485e7SMark Brown 	}
1448*f10485e7SMark Brown 
1449*f10485e7SMark Brown 	/* charge output caps */
1450*f10485e7SMark Brown 	codec->bias_level = SND_SOC_BIAS_OFF;
1451*f10485e7SMark Brown 	wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1452*f10485e7SMark Brown 
1453*f10485e7SMark Brown 	reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4);
1454*f10485e7SMark Brown 	wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
1455*f10485e7SMark Brown 
1456*f10485e7SMark Brown 	reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) &
1457*f10485e7SMark Brown 		~WM8990_GPIO1_SEL_MASK;
1458*f10485e7SMark Brown 	wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
1459*f10485e7SMark Brown 
1460*f10485e7SMark Brown 	reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
1461*f10485e7SMark Brown 	wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
1462*f10485e7SMark Brown 
1463*f10485e7SMark Brown 	wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
1464*f10485e7SMark Brown 	wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
1465*f10485e7SMark Brown 
1466*f10485e7SMark Brown 	wm8990_add_controls(codec);
1467*f10485e7SMark Brown 	wm8990_add_widgets(codec);
1468*f10485e7SMark Brown 	ret = snd_soc_register_card(socdev);
1469*f10485e7SMark Brown 	if (ret < 0) {
1470*f10485e7SMark Brown 		printk(KERN_ERR "wm8990: failed to register card\n");
1471*f10485e7SMark Brown 		goto card_err;
1472*f10485e7SMark Brown 	}
1473*f10485e7SMark Brown 	return ret;
1474*f10485e7SMark Brown 
1475*f10485e7SMark Brown card_err:
1476*f10485e7SMark Brown 	snd_soc_free_pcms(socdev);
1477*f10485e7SMark Brown 	snd_soc_dapm_free(socdev);
1478*f10485e7SMark Brown pcm_err:
1479*f10485e7SMark Brown 	kfree(codec->reg_cache);
1480*f10485e7SMark Brown 	return ret;
1481*f10485e7SMark Brown }
1482*f10485e7SMark Brown 
1483*f10485e7SMark Brown /* If the i2c layer weren't so broken, we could pass this kind of data
1484*f10485e7SMark Brown    around */
1485*f10485e7SMark Brown static struct snd_soc_device *wm8990_socdev;
1486*f10485e7SMark Brown 
1487*f10485e7SMark Brown #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1488*f10485e7SMark Brown 
1489*f10485e7SMark Brown /*
1490*f10485e7SMark Brown  * WM891 2 wire address is determined by GPIO5
1491*f10485e7SMark Brown  * state during powerup.
1492*f10485e7SMark Brown  *    low  = 0x34
1493*f10485e7SMark Brown  *    high = 0x36
1494*f10485e7SMark Brown  */
1495*f10485e7SMark Brown static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
1496*f10485e7SMark Brown 
1497*f10485e7SMark Brown /* Magic definition of all other variables and things */
1498*f10485e7SMark Brown I2C_CLIENT_INSMOD;
1499*f10485e7SMark Brown 
1500*f10485e7SMark Brown static struct i2c_driver wm8990_i2c_driver;
1501*f10485e7SMark Brown static struct i2c_client client_template;
1502*f10485e7SMark Brown 
1503*f10485e7SMark Brown static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1504*f10485e7SMark Brown {
1505*f10485e7SMark Brown 	struct snd_soc_device *socdev = wm8990_socdev;
1506*f10485e7SMark Brown 	struct wm8990_setup_data *setup = socdev->codec_data;
1507*f10485e7SMark Brown 	struct snd_soc_codec *codec = socdev->codec;
1508*f10485e7SMark Brown 	struct i2c_client *i2c;
1509*f10485e7SMark Brown 	int ret;
1510*f10485e7SMark Brown 
1511*f10485e7SMark Brown 	if (addr != setup->i2c_address)
1512*f10485e7SMark Brown 		return -ENODEV;
1513*f10485e7SMark Brown 
1514*f10485e7SMark Brown 	client_template.adapter = adap;
1515*f10485e7SMark Brown 	client_template.addr = addr;
1516*f10485e7SMark Brown 
1517*f10485e7SMark Brown 	i2c =  kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
1518*f10485e7SMark Brown 	if (i2c == NULL) {
1519*f10485e7SMark Brown 		kfree(codec);
1520*f10485e7SMark Brown 		return -ENOMEM;
1521*f10485e7SMark Brown 	}
1522*f10485e7SMark Brown 	i2c_set_clientdata(i2c, codec);
1523*f10485e7SMark Brown 	codec->control_data = i2c;
1524*f10485e7SMark Brown 
1525*f10485e7SMark Brown 	ret = i2c_attach_client(i2c);
1526*f10485e7SMark Brown 	if (ret < 0) {
1527*f10485e7SMark Brown 		err("failed to attach codec at addr %x\n", addr);
1528*f10485e7SMark Brown 		goto err;
1529*f10485e7SMark Brown 	}
1530*f10485e7SMark Brown 
1531*f10485e7SMark Brown 	ret = wm8990_init(socdev);
1532*f10485e7SMark Brown 	if (ret < 0) {
1533*f10485e7SMark Brown 		err("failed to initialise WM8990\n");
1534*f10485e7SMark Brown 		goto err;
1535*f10485e7SMark Brown 	}
1536*f10485e7SMark Brown 	return ret;
1537*f10485e7SMark Brown 
1538*f10485e7SMark Brown err:
1539*f10485e7SMark Brown 	kfree(codec);
1540*f10485e7SMark Brown 	kfree(i2c);
1541*f10485e7SMark Brown 	return ret;
1542*f10485e7SMark Brown }
1543*f10485e7SMark Brown 
1544*f10485e7SMark Brown static int wm8990_i2c_detach(struct i2c_client *client)
1545*f10485e7SMark Brown {
1546*f10485e7SMark Brown 	struct snd_soc_codec *codec = i2c_get_clientdata(client);
1547*f10485e7SMark Brown 	i2c_detach_client(client);
1548*f10485e7SMark Brown 	kfree(codec->reg_cache);
1549*f10485e7SMark Brown 	kfree(client);
1550*f10485e7SMark Brown 	return 0;
1551*f10485e7SMark Brown }
1552*f10485e7SMark Brown 
1553*f10485e7SMark Brown static int wm8990_i2c_attach(struct i2c_adapter *adap)
1554*f10485e7SMark Brown {
1555*f10485e7SMark Brown 	return i2c_probe(adap, &addr_data, wm8990_codec_probe);
1556*f10485e7SMark Brown }
1557*f10485e7SMark Brown 
1558*f10485e7SMark Brown static struct i2c_driver wm8990_i2c_driver = {
1559*f10485e7SMark Brown 	.driver = {
1560*f10485e7SMark Brown 		.name = "WM8990 I2C Codec",
1561*f10485e7SMark Brown 		.owner = THIS_MODULE,
1562*f10485e7SMark Brown 	},
1563*f10485e7SMark Brown 	.attach_adapter = wm8990_i2c_attach,
1564*f10485e7SMark Brown 	.detach_client =  wm8990_i2c_detach,
1565*f10485e7SMark Brown 	.command =        NULL,
1566*f10485e7SMark Brown };
1567*f10485e7SMark Brown 
1568*f10485e7SMark Brown static struct i2c_client client_template = {
1569*f10485e7SMark Brown 	.name =   "WM8990",
1570*f10485e7SMark Brown 	.driver = &wm8990_i2c_driver,
1571*f10485e7SMark Brown };
1572*f10485e7SMark Brown #endif
1573*f10485e7SMark Brown 
1574*f10485e7SMark Brown static int wm8990_probe(struct platform_device *pdev)
1575*f10485e7SMark Brown {
1576*f10485e7SMark Brown 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1577*f10485e7SMark Brown 	struct wm8990_setup_data *setup;
1578*f10485e7SMark Brown 	struct snd_soc_codec *codec;
1579*f10485e7SMark Brown 	struct wm8990_priv *wm8990;
1580*f10485e7SMark Brown 	int ret = 0;
1581*f10485e7SMark Brown 
1582*f10485e7SMark Brown 	info("WM8990 Audio Codec %s\n", WM8990_VERSION);
1583*f10485e7SMark Brown 
1584*f10485e7SMark Brown 	setup = socdev->codec_data;
1585*f10485e7SMark Brown 	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1586*f10485e7SMark Brown 	if (codec == NULL)
1587*f10485e7SMark Brown 		return -ENOMEM;
1588*f10485e7SMark Brown 
1589*f10485e7SMark Brown 	wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
1590*f10485e7SMark Brown 	if (wm8990 == NULL) {
1591*f10485e7SMark Brown 		kfree(codec);
1592*f10485e7SMark Brown 		return -ENOMEM;
1593*f10485e7SMark Brown 	}
1594*f10485e7SMark Brown 
1595*f10485e7SMark Brown 	codec->private_data = wm8990;
1596*f10485e7SMark Brown 	socdev->codec = codec;
1597*f10485e7SMark Brown 	mutex_init(&codec->mutex);
1598*f10485e7SMark Brown 	INIT_LIST_HEAD(&codec->dapm_widgets);
1599*f10485e7SMark Brown 	INIT_LIST_HEAD(&codec->dapm_paths);
1600*f10485e7SMark Brown 	wm8990_socdev = socdev;
1601*f10485e7SMark Brown 
1602*f10485e7SMark Brown #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1603*f10485e7SMark Brown 	if (setup->i2c_address) {
1604*f10485e7SMark Brown 		normal_i2c[0] = setup->i2c_address;
1605*f10485e7SMark Brown 		codec->hw_write = (hw_write_t)i2c_master_send;
1606*f10485e7SMark Brown 		ret = i2c_add_driver(&wm8990_i2c_driver);
1607*f10485e7SMark Brown 		if (ret != 0)
1608*f10485e7SMark Brown 			printk(KERN_ERR "can't add i2c driver");
1609*f10485e7SMark Brown 	}
1610*f10485e7SMark Brown #else
1611*f10485e7SMark Brown 		/* Add other interfaces here */
1612*f10485e7SMark Brown #endif
1613*f10485e7SMark Brown 	return ret;
1614*f10485e7SMark Brown }
1615*f10485e7SMark Brown 
1616*f10485e7SMark Brown /* power down chip */
1617*f10485e7SMark Brown static int wm8990_remove(struct platform_device *pdev)
1618*f10485e7SMark Brown {
1619*f10485e7SMark Brown 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1620*f10485e7SMark Brown 	struct snd_soc_codec *codec = socdev->codec;
1621*f10485e7SMark Brown 
1622*f10485e7SMark Brown 	if (codec->control_data)
1623*f10485e7SMark Brown 		wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
1624*f10485e7SMark Brown 	snd_soc_free_pcms(socdev);
1625*f10485e7SMark Brown 	snd_soc_dapm_free(socdev);
1626*f10485e7SMark Brown #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1627*f10485e7SMark Brown 	i2c_del_driver(&wm8990_i2c_driver);
1628*f10485e7SMark Brown #endif
1629*f10485e7SMark Brown 	kfree(codec->private_data);
1630*f10485e7SMark Brown 	kfree(codec);
1631*f10485e7SMark Brown 
1632*f10485e7SMark Brown 	return 0;
1633*f10485e7SMark Brown }
1634*f10485e7SMark Brown 
1635*f10485e7SMark Brown struct snd_soc_codec_device soc_codec_dev_wm8990 = {
1636*f10485e7SMark Brown 	.probe =	wm8990_probe,
1637*f10485e7SMark Brown 	.remove =	wm8990_remove,
1638*f10485e7SMark Brown 	.suspend =	wm8990_suspend,
1639*f10485e7SMark Brown 	.resume =	wm8990_resume,
1640*f10485e7SMark Brown };
1641*f10485e7SMark Brown EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
1642*f10485e7SMark Brown 
1643*f10485e7SMark Brown MODULE_DESCRIPTION("ASoC WM8990 driver");
1644*f10485e7SMark Brown MODULE_AUTHOR("Liam Girdwood");
1645*f10485e7SMark Brown MODULE_LICENSE("GPL");
1646