xref: /openbmc/linux/sound/soc/codecs/max98095.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
282a5a936SPeter Hsiang /*
382a5a936SPeter Hsiang  * max98095.c -- MAX98095 ALSA SoC Audio driver
482a5a936SPeter Hsiang  *
582a5a936SPeter Hsiang  * Copyright 2011 Maxim Integrated Products
682a5a936SPeter Hsiang  */
782a5a936SPeter Hsiang 
882a5a936SPeter Hsiang #include <linux/module.h>
982a5a936SPeter Hsiang #include <linux/moduleparam.h>
1082a5a936SPeter Hsiang #include <linux/kernel.h>
1182a5a936SPeter Hsiang #include <linux/init.h>
1282a5a936SPeter Hsiang #include <linux/delay.h>
1382a5a936SPeter Hsiang #include <linux/pm.h>
1482a5a936SPeter Hsiang #include <linux/i2c.h>
15e3048c3dSTushar Behera #include <linux/clk.h>
16210a5faeSLars-Peter Clausen #include <linux/mutex.h>
1782a5a936SPeter Hsiang #include <sound/core.h>
1882a5a936SPeter Hsiang #include <sound/pcm.h>
1982a5a936SPeter Hsiang #include <sound/pcm_params.h>
2082a5a936SPeter Hsiang #include <sound/soc.h>
2182a5a936SPeter Hsiang #include <sound/initval.h>
2282a5a936SPeter Hsiang #include <sound/tlv.h>
2382a5a936SPeter Hsiang #include <linux/slab.h>
2482a5a936SPeter Hsiang #include <asm/div64.h>
2582a5a936SPeter Hsiang #include <sound/max98095.h>
269dd90c5dSRhyland Klein #include <sound/jack.h>
2782a5a936SPeter Hsiang #include "max98095.h"
2882a5a936SPeter Hsiang 
2982a5a936SPeter Hsiang enum max98095_type {
3082a5a936SPeter Hsiang 	MAX98095,
3182a5a936SPeter Hsiang };
3282a5a936SPeter Hsiang 
3382a5a936SPeter Hsiang struct max98095_cdata {
3482a5a936SPeter Hsiang 	unsigned int rate;
3582a5a936SPeter Hsiang 	unsigned int fmt;
36dad31ec1SPeter Hsiang 	int eq_sel;
37dad31ec1SPeter Hsiang 	int bq_sel;
3882a5a936SPeter Hsiang };
3982a5a936SPeter Hsiang 
4082a5a936SPeter Hsiang struct max98095_priv {
4114acbbbbSMark Brown 	struct regmap *regmap;
4282a5a936SPeter Hsiang 	enum max98095_type devtype;
4382a5a936SPeter Hsiang 	struct max98095_pdata *pdata;
44e3048c3dSTushar Behera 	struct clk *mclk;
4582a5a936SPeter Hsiang 	unsigned int sysclk;
4682a5a936SPeter Hsiang 	struct max98095_cdata dai[3];
47dad31ec1SPeter Hsiang 	const char **eq_texts;
48dad31ec1SPeter Hsiang 	const char **bq_texts;
49dad31ec1SPeter Hsiang 	struct soc_enum eq_enum;
50dad31ec1SPeter Hsiang 	struct soc_enum bq_enum;
51dad31ec1SPeter Hsiang 	int eq_textcnt;
52dad31ec1SPeter Hsiang 	int bq_textcnt;
5382a5a936SPeter Hsiang 	u8 lin_state;
5482a5a936SPeter Hsiang 	unsigned int mic1pre;
5582a5a936SPeter Hsiang 	unsigned int mic2pre;
569dd90c5dSRhyland Klein 	struct snd_soc_jack *headphone_jack;
579dd90c5dSRhyland Klein 	struct snd_soc_jack *mic_jack;
58210a5faeSLars-Peter Clausen 	struct mutex lock;
5982a5a936SPeter Hsiang };
6082a5a936SPeter Hsiang 
6114acbbbbSMark Brown static const struct reg_default max98095_reg_def[] = {
6214acbbbbSMark Brown 	{  0xf, 0x00 }, /* 0F */
6314acbbbbSMark Brown 	{ 0x10, 0x00 }, /* 10 */
6414acbbbbSMark Brown 	{ 0x11, 0x00 }, /* 11 */
6514acbbbbSMark Brown 	{ 0x12, 0x00 }, /* 12 */
6614acbbbbSMark Brown 	{ 0x13, 0x00 }, /* 13 */
6714acbbbbSMark Brown 	{ 0x14, 0x00 }, /* 14 */
6814acbbbbSMark Brown 	{ 0x15, 0x00 }, /* 15 */
6914acbbbbSMark Brown 	{ 0x16, 0x00 }, /* 16 */
7014acbbbbSMark Brown 	{ 0x17, 0x00 }, /* 17 */
7114acbbbbSMark Brown 	{ 0x18, 0x00 }, /* 18 */
7214acbbbbSMark Brown 	{ 0x19, 0x00 }, /* 19 */
7314acbbbbSMark Brown 	{ 0x1a, 0x00 }, /* 1A */
7414acbbbbSMark Brown 	{ 0x1b, 0x00 }, /* 1B */
7514acbbbbSMark Brown 	{ 0x1c, 0x00 }, /* 1C */
7614acbbbbSMark Brown 	{ 0x1d, 0x00 }, /* 1D */
7714acbbbbSMark Brown 	{ 0x1e, 0x00 }, /* 1E */
7814acbbbbSMark Brown 	{ 0x1f, 0x00 }, /* 1F */
7914acbbbbSMark Brown 	{ 0x20, 0x00 }, /* 20 */
8014acbbbbSMark Brown 	{ 0x21, 0x00 }, /* 21 */
8114acbbbbSMark Brown 	{ 0x22, 0x00 }, /* 22 */
8214acbbbbSMark Brown 	{ 0x23, 0x00 }, /* 23 */
8314acbbbbSMark Brown 	{ 0x24, 0x00 }, /* 24 */
8414acbbbbSMark Brown 	{ 0x25, 0x00 }, /* 25 */
8514acbbbbSMark Brown 	{ 0x26, 0x00 }, /* 26 */
8614acbbbbSMark Brown 	{ 0x27, 0x00 }, /* 27 */
8714acbbbbSMark Brown 	{ 0x28, 0x00 }, /* 28 */
8814acbbbbSMark Brown 	{ 0x29, 0x00 }, /* 29 */
8914acbbbbSMark Brown 	{ 0x2a, 0x00 }, /* 2A */
9014acbbbbSMark Brown 	{ 0x2b, 0x00 }, /* 2B */
9114acbbbbSMark Brown 	{ 0x2c, 0x00 }, /* 2C */
9214acbbbbSMark Brown 	{ 0x2d, 0x00 }, /* 2D */
9314acbbbbSMark Brown 	{ 0x2e, 0x00 }, /* 2E */
9414acbbbbSMark Brown 	{ 0x2f, 0x00 }, /* 2F */
9514acbbbbSMark Brown 	{ 0x30, 0x00 }, /* 30 */
9614acbbbbSMark Brown 	{ 0x31, 0x00 }, /* 31 */
9714acbbbbSMark Brown 	{ 0x32, 0x00 }, /* 32 */
9814acbbbbSMark Brown 	{ 0x33, 0x00 }, /* 33 */
9914acbbbbSMark Brown 	{ 0x34, 0x00 }, /* 34 */
10014acbbbbSMark Brown 	{ 0x35, 0x00 }, /* 35 */
10114acbbbbSMark Brown 	{ 0x36, 0x00 }, /* 36 */
10214acbbbbSMark Brown 	{ 0x37, 0x00 }, /* 37 */
10314acbbbbSMark Brown 	{ 0x38, 0x00 }, /* 38 */
10414acbbbbSMark Brown 	{ 0x39, 0x00 }, /* 39 */
10514acbbbbSMark Brown 	{ 0x3a, 0x00 }, /* 3A */
10614acbbbbSMark Brown 	{ 0x3b, 0x00 }, /* 3B */
10714acbbbbSMark Brown 	{ 0x3c, 0x00 }, /* 3C */
10814acbbbbSMark Brown 	{ 0x3d, 0x00 }, /* 3D */
10914acbbbbSMark Brown 	{ 0x3e, 0x00 }, /* 3E */
11014acbbbbSMark Brown 	{ 0x3f, 0x00 }, /* 3F */
11114acbbbbSMark Brown 	{ 0x40, 0x00 }, /* 40 */
11214acbbbbSMark Brown 	{ 0x41, 0x00 }, /* 41 */
11314acbbbbSMark Brown 	{ 0x42, 0x00 }, /* 42 */
11414acbbbbSMark Brown 	{ 0x43, 0x00 }, /* 43 */
11514acbbbbSMark Brown 	{ 0x44, 0x00 }, /* 44 */
11614acbbbbSMark Brown 	{ 0x45, 0x00 }, /* 45 */
11714acbbbbSMark Brown 	{ 0x46, 0x00 }, /* 46 */
11814acbbbbSMark Brown 	{ 0x47, 0x00 }, /* 47 */
11914acbbbbSMark Brown 	{ 0x48, 0x00 }, /* 48 */
12014acbbbbSMark Brown 	{ 0x49, 0x00 }, /* 49 */
12114acbbbbSMark Brown 	{ 0x4a, 0x00 }, /* 4A */
12214acbbbbSMark Brown 	{ 0x4b, 0x00 }, /* 4B */
12314acbbbbSMark Brown 	{ 0x4c, 0x00 }, /* 4C */
12414acbbbbSMark Brown 	{ 0x4d, 0x00 }, /* 4D */
12514acbbbbSMark Brown 	{ 0x4e, 0x00 }, /* 4E */
12614acbbbbSMark Brown 	{ 0x4f, 0x00 }, /* 4F */
12714acbbbbSMark Brown 	{ 0x50, 0x00 }, /* 50 */
12814acbbbbSMark Brown 	{ 0x51, 0x00 }, /* 51 */
12914acbbbbSMark Brown 	{ 0x52, 0x00 }, /* 52 */
13014acbbbbSMark Brown 	{ 0x53, 0x00 }, /* 53 */
13114acbbbbSMark Brown 	{ 0x54, 0x00 }, /* 54 */
13214acbbbbSMark Brown 	{ 0x55, 0x00 }, /* 55 */
13314acbbbbSMark Brown 	{ 0x56, 0x00 }, /* 56 */
13414acbbbbSMark Brown 	{ 0x57, 0x00 }, /* 57 */
13514acbbbbSMark Brown 	{ 0x58, 0x00 }, /* 58 */
13614acbbbbSMark Brown 	{ 0x59, 0x00 }, /* 59 */
13714acbbbbSMark Brown 	{ 0x5a, 0x00 }, /* 5A */
13814acbbbbSMark Brown 	{ 0x5b, 0x00 }, /* 5B */
13914acbbbbSMark Brown 	{ 0x5c, 0x00 }, /* 5C */
14014acbbbbSMark Brown 	{ 0x5d, 0x00 }, /* 5D */
14114acbbbbSMark Brown 	{ 0x5e, 0x00 }, /* 5E */
14214acbbbbSMark Brown 	{ 0x5f, 0x00 }, /* 5F */
14314acbbbbSMark Brown 	{ 0x60, 0x00 }, /* 60 */
14414acbbbbSMark Brown 	{ 0x61, 0x00 }, /* 61 */
14514acbbbbSMark Brown 	{ 0x62, 0x00 }, /* 62 */
14614acbbbbSMark Brown 	{ 0x63, 0x00 }, /* 63 */
14714acbbbbSMark Brown 	{ 0x64, 0x00 }, /* 64 */
14814acbbbbSMark Brown 	{ 0x65, 0x00 }, /* 65 */
14914acbbbbSMark Brown 	{ 0x66, 0x00 }, /* 66 */
15014acbbbbSMark Brown 	{ 0x67, 0x00 }, /* 67 */
15114acbbbbSMark Brown 	{ 0x68, 0x00 }, /* 68 */
15214acbbbbSMark Brown 	{ 0x69, 0x00 }, /* 69 */
15314acbbbbSMark Brown 	{ 0x6a, 0x00 }, /* 6A */
15414acbbbbSMark Brown 	{ 0x6b, 0x00 }, /* 6B */
15514acbbbbSMark Brown 	{ 0x6c, 0x00 }, /* 6C */
15614acbbbbSMark Brown 	{ 0x6d, 0x00 }, /* 6D */
15714acbbbbSMark Brown 	{ 0x6e, 0x00 }, /* 6E */
15814acbbbbSMark Brown 	{ 0x6f, 0x00 }, /* 6F */
15914acbbbbSMark Brown 	{ 0x70, 0x00 }, /* 70 */
16014acbbbbSMark Brown 	{ 0x71, 0x00 }, /* 71 */
16114acbbbbSMark Brown 	{ 0x72, 0x00 }, /* 72 */
16214acbbbbSMark Brown 	{ 0x73, 0x00 }, /* 73 */
16314acbbbbSMark Brown 	{ 0x74, 0x00 }, /* 74 */
16414acbbbbSMark Brown 	{ 0x75, 0x00 }, /* 75 */
16514acbbbbSMark Brown 	{ 0x76, 0x00 }, /* 76 */
16614acbbbbSMark Brown 	{ 0x77, 0x00 }, /* 77 */
16714acbbbbSMark Brown 	{ 0x78, 0x00 }, /* 78 */
16814acbbbbSMark Brown 	{ 0x79, 0x00 }, /* 79 */
16914acbbbbSMark Brown 	{ 0x7a, 0x00 }, /* 7A */
17014acbbbbSMark Brown 	{ 0x7b, 0x00 }, /* 7B */
17114acbbbbSMark Brown 	{ 0x7c, 0x00 }, /* 7C */
17214acbbbbSMark Brown 	{ 0x7d, 0x00 }, /* 7D */
17314acbbbbSMark Brown 	{ 0x7e, 0x00 }, /* 7E */
17414acbbbbSMark Brown 	{ 0x7f, 0x00 }, /* 7F */
17514acbbbbSMark Brown 	{ 0x80, 0x00 }, /* 80 */
17614acbbbbSMark Brown 	{ 0x81, 0x00 }, /* 81 */
17714acbbbbSMark Brown 	{ 0x82, 0x00 }, /* 82 */
17814acbbbbSMark Brown 	{ 0x83, 0x00 }, /* 83 */
17914acbbbbSMark Brown 	{ 0x84, 0x00 }, /* 84 */
18014acbbbbSMark Brown 	{ 0x85, 0x00 }, /* 85 */
18114acbbbbSMark Brown 	{ 0x86, 0x00 }, /* 86 */
18214acbbbbSMark Brown 	{ 0x87, 0x00 }, /* 87 */
18314acbbbbSMark Brown 	{ 0x88, 0x00 }, /* 88 */
18414acbbbbSMark Brown 	{ 0x89, 0x00 }, /* 89 */
18514acbbbbSMark Brown 	{ 0x8a, 0x00 }, /* 8A */
18614acbbbbSMark Brown 	{ 0x8b, 0x00 }, /* 8B */
18714acbbbbSMark Brown 	{ 0x8c, 0x00 }, /* 8C */
18814acbbbbSMark Brown 	{ 0x8d, 0x00 }, /* 8D */
18914acbbbbSMark Brown 	{ 0x8e, 0x00 }, /* 8E */
19014acbbbbSMark Brown 	{ 0x8f, 0x00 }, /* 8F */
19114acbbbbSMark Brown 	{ 0x90, 0x00 }, /* 90 */
19214acbbbbSMark Brown 	{ 0x91, 0x00 }, /* 91 */
19314acbbbbSMark Brown 	{ 0x92, 0x30 }, /* 92 */
19414acbbbbSMark Brown 	{ 0x93, 0xF0 }, /* 93 */
19514acbbbbSMark Brown 	{ 0x94, 0x00 }, /* 94 */
19614acbbbbSMark Brown 	{ 0x95, 0x00 }, /* 95 */
19714acbbbbSMark Brown 	{ 0x96, 0x3F }, /* 96 */
19814acbbbbSMark Brown 	{ 0x97, 0x00 }, /* 97 */
19914acbbbbSMark Brown 	{ 0xff, 0x00 }, /* FF */
20082a5a936SPeter Hsiang };
20182a5a936SPeter Hsiang 
max98095_readable(struct device * dev,unsigned int reg)20214acbbbbSMark Brown static bool max98095_readable(struct device *dev, unsigned int reg)
20382a5a936SPeter Hsiang {
2045549ce82SAxel Lin 	switch (reg) {
2055549ce82SAxel Lin 	case M98095_001_HOST_INT_STS ... M98095_097_PWR_SYS:
2065549ce82SAxel Lin 	case M98095_0FF_REV_ID:
2075549ce82SAxel Lin 		return true;
2085549ce82SAxel Lin 	default:
2095549ce82SAxel Lin 		return false;
2105549ce82SAxel Lin 	}
2115549ce82SAxel Lin }
2125549ce82SAxel Lin 
max98095_writeable(struct device * dev,unsigned int reg)2135549ce82SAxel Lin static bool max98095_writeable(struct device *dev, unsigned int reg)
2145549ce82SAxel Lin {
2155549ce82SAxel Lin 	switch (reg) {
2165549ce82SAxel Lin 	case M98095_00F_HOST_CFG ... M98095_097_PWR_SYS:
2175549ce82SAxel Lin 		return true;
2185549ce82SAxel Lin 	default:
2195549ce82SAxel Lin 		return false;
2205549ce82SAxel Lin 	}
22182a5a936SPeter Hsiang }
22282a5a936SPeter Hsiang 
max98095_volatile(struct device * dev,unsigned int reg)22314acbbbbSMark Brown static bool max98095_volatile(struct device *dev, unsigned int reg)
22482a5a936SPeter Hsiang {
22582a5a936SPeter Hsiang 	switch (reg) {
2265549ce82SAxel Lin 	case M98095_000_HOST_DATA ... M98095_00E_TEMP_SENSOR_STS:
2275549ce82SAxel Lin 	case M98095_REG_MAX_CACHED + 1 ... M98095_0FF_REV_ID:
2285549ce82SAxel Lin 		return true;
2295549ce82SAxel Lin 	default:
2305549ce82SAxel Lin 		return false;
23182a5a936SPeter Hsiang 	}
23282a5a936SPeter Hsiang }
23382a5a936SPeter Hsiang 
23414acbbbbSMark Brown static const struct regmap_config max98095_regmap = {
23514acbbbbSMark Brown 	.reg_bits = 8,
23614acbbbbSMark Brown 	.val_bits = 8,
237dad31ec1SPeter Hsiang 
23814acbbbbSMark Brown 	.reg_defaults = max98095_reg_def,
23914acbbbbSMark Brown 	.num_reg_defaults = ARRAY_SIZE(max98095_reg_def),
24014acbbbbSMark Brown 	.max_register = M98095_0FF_REV_ID,
24114acbbbbSMark Brown 	.cache_type = REGCACHE_RBTREE,
2420d8d2938SAxel Lin 
24314acbbbbSMark Brown 	.readable_reg = max98095_readable,
2445549ce82SAxel Lin 	.writeable_reg = max98095_writeable,
24514acbbbbSMark Brown 	.volatile_reg = max98095_volatile,
24614acbbbbSMark Brown };
247dad31ec1SPeter Hsiang 
248dad31ec1SPeter Hsiang /*
249dad31ec1SPeter Hsiang  * Load equalizer DSP coefficient configurations registers
250dad31ec1SPeter Hsiang  */
m98095_eq_band(struct snd_soc_component * component,unsigned int dai,unsigned int band,u16 * coefs)2512dd1637fSKuninori Morimoto static void m98095_eq_band(struct snd_soc_component *component, unsigned int dai,
252dad31ec1SPeter Hsiang 		    unsigned int band, u16 *coefs)
253dad31ec1SPeter Hsiang {
254dad31ec1SPeter Hsiang 	unsigned int eq_reg;
255dad31ec1SPeter Hsiang 	unsigned int i;
256dad31ec1SPeter Hsiang 
257a922cd71STakashi Iwai 	if (WARN_ON(band > 4) ||
258a922cd71STakashi Iwai 	    WARN_ON(dai > 1))
259a922cd71STakashi Iwai 		return;
260dad31ec1SPeter Hsiang 
261dad31ec1SPeter Hsiang 	/* Load the base register address */
262dad31ec1SPeter Hsiang 	eq_reg = dai ? M98095_142_DAI2_EQ_BASE : M98095_110_DAI1_EQ_BASE;
263dad31ec1SPeter Hsiang 
264dad31ec1SPeter Hsiang 	/* Add the band address offset, note adjustment for word address */
265dad31ec1SPeter Hsiang 	eq_reg += band * (M98095_COEFS_PER_BAND << 1);
266dad31ec1SPeter Hsiang 
267dad31ec1SPeter Hsiang 	/* Step through the registers and coefs */
268dad31ec1SPeter Hsiang 	for (i = 0; i < M98095_COEFS_PER_BAND; i++) {
2692dd1637fSKuninori Morimoto 		snd_soc_component_write(component, eq_reg++, M98095_BYTE1(coefs[i]));
2702dd1637fSKuninori Morimoto 		snd_soc_component_write(component, eq_reg++, M98095_BYTE0(coefs[i]));
271dad31ec1SPeter Hsiang 	}
272dad31ec1SPeter Hsiang }
273dad31ec1SPeter Hsiang 
274dad31ec1SPeter Hsiang /*
275dad31ec1SPeter Hsiang  * Load biquad filter coefficient configurations registers
276dad31ec1SPeter Hsiang  */
m98095_biquad_band(struct snd_soc_component * component,unsigned int dai,unsigned int band,u16 * coefs)2772dd1637fSKuninori Morimoto static void m98095_biquad_band(struct snd_soc_component *component, unsigned int dai,
278dad31ec1SPeter Hsiang 		    unsigned int band, u16 *coefs)
279dad31ec1SPeter Hsiang {
280dad31ec1SPeter Hsiang 	unsigned int bq_reg;
281dad31ec1SPeter Hsiang 	unsigned int i;
282dad31ec1SPeter Hsiang 
283a922cd71STakashi Iwai 	if (WARN_ON(band > 1) ||
284a922cd71STakashi Iwai 	    WARN_ON(dai > 1))
285a922cd71STakashi Iwai 		return;
286dad31ec1SPeter Hsiang 
287dad31ec1SPeter Hsiang 	/* Load the base register address */
288dad31ec1SPeter Hsiang 	bq_reg = dai ? M98095_17E_DAI2_BQ_BASE : M98095_174_DAI1_BQ_BASE;
289dad31ec1SPeter Hsiang 
290dad31ec1SPeter Hsiang 	/* Add the band address offset, note adjustment for word address */
291dad31ec1SPeter Hsiang 	bq_reg += band * (M98095_COEFS_PER_BAND << 1);
292dad31ec1SPeter Hsiang 
293dad31ec1SPeter Hsiang 	/* Step through the registers and coefs */
294dad31ec1SPeter Hsiang 	for (i = 0; i < M98095_COEFS_PER_BAND; i++) {
2952dd1637fSKuninori Morimoto 		snd_soc_component_write(component, bq_reg++, M98095_BYTE1(coefs[i]));
2962dd1637fSKuninori Morimoto 		snd_soc_component_write(component, bq_reg++, M98095_BYTE0(coefs[i]));
297dad31ec1SPeter Hsiang 	}
298dad31ec1SPeter Hsiang }
299dad31ec1SPeter Hsiang 
30082a5a936SPeter Hsiang static const char * const max98095_fltr_mode[] = { "Voice", "Music" };
301af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_dai1_filter_mode_enum,
302af1f0a50STakashi Iwai 			    M98095_02E_DAI1_FILTERS, 7,
303af1f0a50STakashi Iwai 			    max98095_fltr_mode);
304af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_dai2_filter_mode_enum,
305af1f0a50STakashi Iwai 			    M98095_038_DAI2_FILTERS, 7,
306af1f0a50STakashi Iwai 			    max98095_fltr_mode);
30782a5a936SPeter Hsiang 
30882a5a936SPeter Hsiang static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" };
30982a5a936SPeter Hsiang 
310af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_extmic_enum,
311af1f0a50STakashi Iwai 			    M98095_087_CFG_MIC, 0,
312af1f0a50STakashi Iwai 			    max98095_extmic_text);
31382a5a936SPeter Hsiang 
31482a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_extmic_mux =
31582a5a936SPeter Hsiang 	SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum);
31682a5a936SPeter Hsiang 
31782a5a936SPeter Hsiang static const char * const max98095_linein_text[] = { "INA", "INB" };
31882a5a936SPeter Hsiang 
319af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_linein_enum,
320af1f0a50STakashi Iwai 			    M98095_086_CFG_LINE, 6,
321af1f0a50STakashi Iwai 			    max98095_linein_text);
32282a5a936SPeter Hsiang 
32382a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_linein_mux =
32482a5a936SPeter Hsiang 	SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum);
32582a5a936SPeter Hsiang 
32682a5a936SPeter Hsiang static const char * const max98095_line_mode_text[] = {
32782a5a936SPeter Hsiang 	"Stereo", "Differential"};
32882a5a936SPeter Hsiang 
329af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_linein_mode_enum,
330af1f0a50STakashi Iwai 			    M98095_086_CFG_LINE, 7,
331af1f0a50STakashi Iwai 			    max98095_line_mode_text);
33282a5a936SPeter Hsiang 
333af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_lineout_mode_enum,
334af1f0a50STakashi Iwai 			    M98095_086_CFG_LINE, 4,
335af1f0a50STakashi Iwai 			    max98095_line_mode_text);
33682a5a936SPeter Hsiang 
33782a5a936SPeter Hsiang static const char * const max98095_dai_fltr[] = {
33882a5a936SPeter Hsiang 	"Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k",
33982a5a936SPeter Hsiang 	"Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"};
340af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_dai1_dac_filter_enum,
341af1f0a50STakashi Iwai 			    M98095_02E_DAI1_FILTERS, 0,
342af1f0a50STakashi Iwai 			    max98095_dai_fltr);
343af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_dai2_dac_filter_enum,
344af1f0a50STakashi Iwai 			    M98095_038_DAI2_FILTERS, 0,
345af1f0a50STakashi Iwai 			    max98095_dai_fltr);
346af1f0a50STakashi Iwai static SOC_ENUM_SINGLE_DECL(max98095_dai3_dac_filter_enum,
347af1f0a50STakashi Iwai 			    M98095_042_DAI3_FILTERS, 0,
348af1f0a50STakashi Iwai 			    max98095_dai_fltr);
34982a5a936SPeter Hsiang 
max98095_mic1pre_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)35082a5a936SPeter Hsiang static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol,
35182a5a936SPeter Hsiang 				struct snd_ctl_elem_value *ucontrol)
35282a5a936SPeter Hsiang {
3532dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3542dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
35582a5a936SPeter Hsiang 	unsigned int sel = ucontrol->value.integer.value[0];
35682a5a936SPeter Hsiang 
35782a5a936SPeter Hsiang 	max98095->mic1pre = sel;
3582dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_05F_LVL_MIC1, M98095_MICPRE_MASK,
35982a5a936SPeter Hsiang 		(1+sel)<<M98095_MICPRE_SHIFT);
36082a5a936SPeter Hsiang 
36182a5a936SPeter Hsiang 	return 0;
36282a5a936SPeter Hsiang }
36382a5a936SPeter Hsiang 
max98095_mic1pre_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)36482a5a936SPeter Hsiang static int max98095_mic1pre_get(struct snd_kcontrol *kcontrol,
36582a5a936SPeter Hsiang 				struct snd_ctl_elem_value *ucontrol)
36682a5a936SPeter Hsiang {
3672dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3682dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
36982a5a936SPeter Hsiang 
37082a5a936SPeter Hsiang 	ucontrol->value.integer.value[0] = max98095->mic1pre;
37182a5a936SPeter Hsiang 	return 0;
37282a5a936SPeter Hsiang }
37382a5a936SPeter Hsiang 
max98095_mic2pre_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)37482a5a936SPeter Hsiang static int max98095_mic2pre_set(struct snd_kcontrol *kcontrol,
37582a5a936SPeter Hsiang 				struct snd_ctl_elem_value *ucontrol)
37682a5a936SPeter Hsiang {
3772dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3782dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
37982a5a936SPeter Hsiang 	unsigned int sel = ucontrol->value.integer.value[0];
38082a5a936SPeter Hsiang 
38182a5a936SPeter Hsiang 	max98095->mic2pre = sel;
3822dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_060_LVL_MIC2, M98095_MICPRE_MASK,
38382a5a936SPeter Hsiang 		(1+sel)<<M98095_MICPRE_SHIFT);
38482a5a936SPeter Hsiang 
38582a5a936SPeter Hsiang 	return 0;
38682a5a936SPeter Hsiang }
38782a5a936SPeter Hsiang 
max98095_mic2pre_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)38882a5a936SPeter Hsiang static int max98095_mic2pre_get(struct snd_kcontrol *kcontrol,
38982a5a936SPeter Hsiang 				struct snd_ctl_elem_value *ucontrol)
39082a5a936SPeter Hsiang {
3912dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3922dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
39382a5a936SPeter Hsiang 
39482a5a936SPeter Hsiang 	ucontrol->value.integer.value[0] = max98095->mic2pre;
39582a5a936SPeter Hsiang 	return 0;
39682a5a936SPeter Hsiang }
39782a5a936SPeter Hsiang 
39854c2011fSLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(max98095_micboost_tlv,
39982a5a936SPeter Hsiang 	0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
40054c2011fSLars-Peter Clausen 	2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0)
40154c2011fSLars-Peter Clausen );
40282a5a936SPeter Hsiang 
40382a5a936SPeter Hsiang static const DECLARE_TLV_DB_SCALE(max98095_mic_tlv, 0, 100, 0);
40482a5a936SPeter Hsiang static const DECLARE_TLV_DB_SCALE(max98095_adc_tlv, -1200, 100, 0);
40582a5a936SPeter Hsiang static const DECLARE_TLV_DB_SCALE(max98095_adcboost_tlv, 0, 600, 0);
40682a5a936SPeter Hsiang 
40754c2011fSLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(max98095_hp_tlv,
40882a5a936SPeter Hsiang 	0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0),
40982a5a936SPeter Hsiang 	7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0),
41082a5a936SPeter Hsiang 	15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0),
41182a5a936SPeter Hsiang 	22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0),
41254c2011fSLars-Peter Clausen 	28, 31, TLV_DB_SCALE_ITEM(150, 50, 0)
41354c2011fSLars-Peter Clausen );
41482a5a936SPeter Hsiang 
41554c2011fSLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(max98095_spk_tlv,
41682a5a936SPeter Hsiang 	0, 10, TLV_DB_SCALE_ITEM(-5900, 400, 0),
41782a5a936SPeter Hsiang 	11, 18, TLV_DB_SCALE_ITEM(-1700, 200, 0),
41882a5a936SPeter Hsiang 	19, 27, TLV_DB_SCALE_ITEM(-200, 100, 0),
41954c2011fSLars-Peter Clausen 	28, 39, TLV_DB_SCALE_ITEM(650, 50, 0)
42054c2011fSLars-Peter Clausen );
42182a5a936SPeter Hsiang 
42254c2011fSLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(max98095_rcv_lout_tlv,
42382a5a936SPeter Hsiang 	0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0),
42482a5a936SPeter Hsiang 	7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0),
42582a5a936SPeter Hsiang 	15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0),
42682a5a936SPeter Hsiang 	22, 27, TLV_DB_SCALE_ITEM(100, 100, 0),
42754c2011fSLars-Peter Clausen 	28, 31, TLV_DB_SCALE_ITEM(650, 50, 0)
42854c2011fSLars-Peter Clausen );
42982a5a936SPeter Hsiang 
43054c2011fSLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(max98095_lin_tlv,
43182a5a936SPeter Hsiang 	0, 2, TLV_DB_SCALE_ITEM(-600, 300, 0),
43282a5a936SPeter Hsiang 	3, 3, TLV_DB_SCALE_ITEM(300, 1100, 0),
43354c2011fSLars-Peter Clausen 	4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0)
43454c2011fSLars-Peter Clausen );
43582a5a936SPeter Hsiang 
43682a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_snd_controls[] = {
43782a5a936SPeter Hsiang 
43882a5a936SPeter Hsiang 	SOC_DOUBLE_R_TLV("Headphone Volume", M98095_064_LVL_HP_L,
43982a5a936SPeter Hsiang 		M98095_065_LVL_HP_R, 0, 31, 0, max98095_hp_tlv),
44082a5a936SPeter Hsiang 
44182a5a936SPeter Hsiang 	SOC_DOUBLE_R_TLV("Speaker Volume", M98095_067_LVL_SPK_L,
44282a5a936SPeter Hsiang 		M98095_068_LVL_SPK_R, 0, 39, 0, max98095_spk_tlv),
44382a5a936SPeter Hsiang 
44482a5a936SPeter Hsiang 	SOC_SINGLE_TLV("Receiver Volume", M98095_066_LVL_RCV,
44582a5a936SPeter Hsiang 		0, 31, 0, max98095_rcv_lout_tlv),
44682a5a936SPeter Hsiang 
44782a5a936SPeter Hsiang 	SOC_DOUBLE_R_TLV("Lineout Volume", M98095_062_LVL_LINEOUT1,
44882a5a936SPeter Hsiang 		M98095_063_LVL_LINEOUT2, 0, 31, 0, max98095_rcv_lout_tlv),
44982a5a936SPeter Hsiang 
45082a5a936SPeter Hsiang 	SOC_DOUBLE_R("Headphone Switch", M98095_064_LVL_HP_L,
45182a5a936SPeter Hsiang 		M98095_065_LVL_HP_R, 7, 1, 1),
45282a5a936SPeter Hsiang 
45382a5a936SPeter Hsiang 	SOC_DOUBLE_R("Speaker Switch", M98095_067_LVL_SPK_L,
45482a5a936SPeter Hsiang 		M98095_068_LVL_SPK_R, 7, 1, 1),
45582a5a936SPeter Hsiang 
45682a5a936SPeter Hsiang 	SOC_SINGLE("Receiver Switch", M98095_066_LVL_RCV, 7, 1, 1),
45782a5a936SPeter Hsiang 
45882a5a936SPeter Hsiang 	SOC_DOUBLE_R("Lineout Switch", M98095_062_LVL_LINEOUT1,
45982a5a936SPeter Hsiang 		M98095_063_LVL_LINEOUT2, 7, 1, 1),
46082a5a936SPeter Hsiang 
46182a5a936SPeter Hsiang 	SOC_SINGLE_TLV("MIC1 Volume", M98095_05F_LVL_MIC1, 0, 20, 1,
46282a5a936SPeter Hsiang 		max98095_mic_tlv),
46382a5a936SPeter Hsiang 
46482a5a936SPeter Hsiang 	SOC_SINGLE_TLV("MIC2 Volume", M98095_060_LVL_MIC2, 0, 20, 1,
46582a5a936SPeter Hsiang 		max98095_mic_tlv),
46682a5a936SPeter Hsiang 
46782a5a936SPeter Hsiang 	SOC_SINGLE_EXT_TLV("MIC1 Boost Volume",
46882a5a936SPeter Hsiang 			M98095_05F_LVL_MIC1, 5, 2, 0,
46982a5a936SPeter Hsiang 			max98095_mic1pre_get, max98095_mic1pre_set,
47082a5a936SPeter Hsiang 			max98095_micboost_tlv),
47182a5a936SPeter Hsiang 	SOC_SINGLE_EXT_TLV("MIC2 Boost Volume",
47282a5a936SPeter Hsiang 			M98095_060_LVL_MIC2, 5, 2, 0,
47382a5a936SPeter Hsiang 			max98095_mic2pre_get, max98095_mic2pre_set,
47482a5a936SPeter Hsiang 			max98095_micboost_tlv),
47582a5a936SPeter Hsiang 
47682a5a936SPeter Hsiang 	SOC_SINGLE_TLV("Linein Volume", M98095_061_LVL_LINEIN, 0, 5, 1,
47782a5a936SPeter Hsiang 		max98095_lin_tlv),
47882a5a936SPeter Hsiang 
47982a5a936SPeter Hsiang 	SOC_SINGLE_TLV("ADCL Volume", M98095_05D_LVL_ADC_L, 0, 15, 1,
48082a5a936SPeter Hsiang 		max98095_adc_tlv),
48182a5a936SPeter Hsiang 	SOC_SINGLE_TLV("ADCR Volume", M98095_05E_LVL_ADC_R, 0, 15, 1,
48282a5a936SPeter Hsiang 		max98095_adc_tlv),
48382a5a936SPeter Hsiang 
48482a5a936SPeter Hsiang 	SOC_SINGLE_TLV("ADCL Boost Volume", M98095_05D_LVL_ADC_L, 4, 3, 0,
48582a5a936SPeter Hsiang 		max98095_adcboost_tlv),
48682a5a936SPeter Hsiang 	SOC_SINGLE_TLV("ADCR Boost Volume", M98095_05E_LVL_ADC_R, 4, 3, 0,
48782a5a936SPeter Hsiang 		max98095_adcboost_tlv),
48882a5a936SPeter Hsiang 
489dad31ec1SPeter Hsiang 	SOC_SINGLE("EQ1 Switch", M98095_088_CFG_LEVEL, 0, 1, 0),
490dad31ec1SPeter Hsiang 	SOC_SINGLE("EQ2 Switch", M98095_088_CFG_LEVEL, 1, 1, 0),
491dad31ec1SPeter Hsiang 
492dad31ec1SPeter Hsiang 	SOC_SINGLE("Biquad1 Switch", M98095_088_CFG_LEVEL, 2, 1, 0),
493dad31ec1SPeter Hsiang 	SOC_SINGLE("Biquad2 Switch", M98095_088_CFG_LEVEL, 3, 1, 0),
494dad31ec1SPeter Hsiang 
49582a5a936SPeter Hsiang 	SOC_ENUM("DAI1 Filter Mode", max98095_dai1_filter_mode_enum),
49682a5a936SPeter Hsiang 	SOC_ENUM("DAI2 Filter Mode", max98095_dai2_filter_mode_enum),
49782a5a936SPeter Hsiang 	SOC_ENUM("DAI1 DAC Filter", max98095_dai1_dac_filter_enum),
49882a5a936SPeter Hsiang 	SOC_ENUM("DAI2 DAC Filter", max98095_dai2_dac_filter_enum),
49982a5a936SPeter Hsiang 	SOC_ENUM("DAI3 DAC Filter", max98095_dai3_dac_filter_enum),
50082a5a936SPeter Hsiang 
50182a5a936SPeter Hsiang 	SOC_ENUM("Linein Mode", max98095_linein_mode_enum),
50282a5a936SPeter Hsiang 	SOC_ENUM("Lineout Mode", max98095_lineout_mode_enum),
50382a5a936SPeter Hsiang };
50482a5a936SPeter Hsiang 
50582a5a936SPeter Hsiang /* Left speaker mixer switch */
50682a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_left_speaker_mixer_controls[] = {
50782a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_050_MIX_SPK_LEFT, 0, 1, 0),
50882a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_050_MIX_SPK_LEFT, 6, 1, 0),
50982a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Mono DAC2 Switch", M98095_050_MIX_SPK_LEFT, 3, 1, 0),
51082a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Mono DAC3 Switch", M98095_050_MIX_SPK_LEFT, 3, 1, 0),
51182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_050_MIX_SPK_LEFT, 4, 1, 0),
51282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_050_MIX_SPK_LEFT, 5, 1, 0),
51382a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_050_MIX_SPK_LEFT, 1, 1, 0),
51482a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_050_MIX_SPK_LEFT, 2, 1, 0),
51582a5a936SPeter Hsiang };
51682a5a936SPeter Hsiang 
51782a5a936SPeter Hsiang /* Right speaker mixer switch */
51882a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_right_speaker_mixer_controls[] = {
51982a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_051_MIX_SPK_RIGHT, 6, 1, 0),
52082a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_051_MIX_SPK_RIGHT, 0, 1, 0),
52182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Mono DAC2 Switch", M98095_051_MIX_SPK_RIGHT, 3, 1, 0),
52282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Mono DAC3 Switch", M98095_051_MIX_SPK_RIGHT, 3, 1, 0),
52382a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_051_MIX_SPK_RIGHT, 5, 1, 0),
52482a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_051_MIX_SPK_RIGHT, 4, 1, 0),
52582a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_051_MIX_SPK_RIGHT, 1, 1, 0),
52682a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_051_MIX_SPK_RIGHT, 2, 1, 0),
52782a5a936SPeter Hsiang };
52882a5a936SPeter Hsiang 
52982a5a936SPeter Hsiang /* Left headphone mixer switch */
53082a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_left_hp_mixer_controls[] = {
53182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04C_MIX_HP_LEFT, 0, 1, 0),
53282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04C_MIX_HP_LEFT, 5, 1, 0),
53382a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_04C_MIX_HP_LEFT, 3, 1, 0),
53482a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_04C_MIX_HP_LEFT, 4, 1, 0),
53582a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_04C_MIX_HP_LEFT, 1, 1, 0),
53682a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_04C_MIX_HP_LEFT, 2, 1, 0),
53782a5a936SPeter Hsiang };
53882a5a936SPeter Hsiang 
53982a5a936SPeter Hsiang /* Right headphone mixer switch */
54082a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_right_hp_mixer_controls[] = {
54182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04D_MIX_HP_RIGHT, 5, 1, 0),
54282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04D_MIX_HP_RIGHT, 0, 1, 0),
54382a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_04D_MIX_HP_RIGHT, 3, 1, 0),
54482a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_04D_MIX_HP_RIGHT, 4, 1, 0),
54582a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_04D_MIX_HP_RIGHT, 1, 1, 0),
54682a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_04D_MIX_HP_RIGHT, 2, 1, 0),
54782a5a936SPeter Hsiang };
54882a5a936SPeter Hsiang 
54982a5a936SPeter Hsiang /* Receiver earpiece mixer switch */
55082a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_mono_rcv_mixer_controls[] = {
55182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04F_MIX_RCV, 0, 1, 0),
55282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04F_MIX_RCV, 5, 1, 0),
55382a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_04F_MIX_RCV, 3, 1, 0),
55482a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_04F_MIX_RCV, 4, 1, 0),
55582a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_04F_MIX_RCV, 1, 1, 0),
55682a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_04F_MIX_RCV, 2, 1, 0),
55782a5a936SPeter Hsiang };
55882a5a936SPeter Hsiang 
55982a5a936SPeter Hsiang /* Left lineout mixer switch */
56082a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_left_lineout_mixer_controls[] = {
56182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_053_MIX_LINEOUT1, 5, 1, 0),
56282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_053_MIX_LINEOUT1, 0, 1, 0),
56382a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_053_MIX_LINEOUT1, 3, 1, 0),
56482a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_053_MIX_LINEOUT1, 4, 1, 0),
56582a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_053_MIX_LINEOUT1, 1, 1, 0),
56682a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_053_MIX_LINEOUT1, 2, 1, 0),
56782a5a936SPeter Hsiang };
56882a5a936SPeter Hsiang 
56982a5a936SPeter Hsiang /* Right lineout mixer switch */
57082a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_right_lineout_mixer_controls[] = {
57182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_054_MIX_LINEOUT2, 0, 1, 0),
57282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_054_MIX_LINEOUT2, 5, 1, 0),
57382a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_054_MIX_LINEOUT2, 3, 1, 0),
57482a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_054_MIX_LINEOUT2, 4, 1, 0),
57582a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_054_MIX_LINEOUT2, 1, 1, 0),
57682a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_054_MIX_LINEOUT2, 2, 1, 0),
57782a5a936SPeter Hsiang };
57882a5a936SPeter Hsiang 
57982a5a936SPeter Hsiang /* Left ADC mixer switch */
58082a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_left_ADC_mixer_controls[] = {
58182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_04A_MIX_ADC_LEFT, 7, 1, 0),
58282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_04A_MIX_ADC_LEFT, 6, 1, 0),
58382a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_04A_MIX_ADC_LEFT, 3, 1, 0),
58482a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_04A_MIX_ADC_LEFT, 2, 1, 0),
58582a5a936SPeter Hsiang };
58682a5a936SPeter Hsiang 
58782a5a936SPeter Hsiang /* Right ADC mixer switch */
58882a5a936SPeter Hsiang static const struct snd_kcontrol_new max98095_right_ADC_mixer_controls[] = {
58982a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC1 Switch", M98095_04B_MIX_ADC_RIGHT, 7, 1, 0),
59082a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("MIC2 Switch", M98095_04B_MIX_ADC_RIGHT, 6, 1, 0),
59182a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN1 Switch", M98095_04B_MIX_ADC_RIGHT, 3, 1, 0),
59282a5a936SPeter Hsiang 	SOC_DAPM_SINGLE("IN2 Switch", M98095_04B_MIX_ADC_RIGHT, 2, 1, 0),
59382a5a936SPeter Hsiang };
59482a5a936SPeter Hsiang 
max98095_mic_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)59582a5a936SPeter Hsiang static int max98095_mic_event(struct snd_soc_dapm_widget *w,
59682a5a936SPeter Hsiang 			     struct snd_kcontrol *kcontrol, int event)
59782a5a936SPeter Hsiang {
5982dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
5992dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
60082a5a936SPeter Hsiang 
60182a5a936SPeter Hsiang 	switch (event) {
60282a5a936SPeter Hsiang 	case SND_SOC_DAPM_POST_PMU:
60382a5a936SPeter Hsiang 		if (w->reg == M98095_05F_LVL_MIC1) {
6042dd1637fSKuninori Morimoto 			snd_soc_component_update_bits(component, w->reg, M98095_MICPRE_MASK,
60582a5a936SPeter Hsiang 				(1+max98095->mic1pre)<<M98095_MICPRE_SHIFT);
60682a5a936SPeter Hsiang 		} else {
6072dd1637fSKuninori Morimoto 			snd_soc_component_update_bits(component, w->reg, M98095_MICPRE_MASK,
60882a5a936SPeter Hsiang 				(1+max98095->mic2pre)<<M98095_MICPRE_SHIFT);
60982a5a936SPeter Hsiang 		}
61082a5a936SPeter Hsiang 		break;
61182a5a936SPeter Hsiang 	case SND_SOC_DAPM_POST_PMD:
6122dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, w->reg, M98095_MICPRE_MASK, 0);
61382a5a936SPeter Hsiang 		break;
61482a5a936SPeter Hsiang 	default:
61582a5a936SPeter Hsiang 		return -EINVAL;
61682a5a936SPeter Hsiang 	}
61782a5a936SPeter Hsiang 
61882a5a936SPeter Hsiang 	return 0;
61982a5a936SPeter Hsiang }
62082a5a936SPeter Hsiang 
62182a5a936SPeter Hsiang /*
62282a5a936SPeter Hsiang  * The line inputs are stereo inputs with the left and right
62382a5a936SPeter Hsiang  * channels sharing a common PGA power control signal.
62482a5a936SPeter Hsiang  */
max98095_line_pga(struct snd_soc_dapm_widget * w,int event,u8 channel)62582a5a936SPeter Hsiang static int max98095_line_pga(struct snd_soc_dapm_widget *w,
62682a5a936SPeter Hsiang 			     int event, u8 channel)
62782a5a936SPeter Hsiang {
6282dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
6292dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
63082a5a936SPeter Hsiang 	u8 *state;
63182a5a936SPeter Hsiang 
632a922cd71STakashi Iwai 	if (WARN_ON(!(channel == 1 || channel == 2)))
633a922cd71STakashi Iwai 		return -EINVAL;
63482a5a936SPeter Hsiang 
63582a5a936SPeter Hsiang 	state = &max98095->lin_state;
63682a5a936SPeter Hsiang 
63782a5a936SPeter Hsiang 	switch (event) {
63882a5a936SPeter Hsiang 	case SND_SOC_DAPM_POST_PMU:
63982a5a936SPeter Hsiang 		*state |= channel;
6402dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, w->reg,
64182a5a936SPeter Hsiang 			(1 << w->shift), (1 << w->shift));
64282a5a936SPeter Hsiang 		break;
64382a5a936SPeter Hsiang 	case SND_SOC_DAPM_POST_PMD:
64482a5a936SPeter Hsiang 		*state &= ~channel;
64582a5a936SPeter Hsiang 		if (*state == 0) {
6462dd1637fSKuninori Morimoto 			snd_soc_component_update_bits(component, w->reg,
64782a5a936SPeter Hsiang 				(1 << w->shift), 0);
64882a5a936SPeter Hsiang 		}
64982a5a936SPeter Hsiang 		break;
65082a5a936SPeter Hsiang 	default:
65182a5a936SPeter Hsiang 		return -EINVAL;
65282a5a936SPeter Hsiang 	}
65382a5a936SPeter Hsiang 
65482a5a936SPeter Hsiang 	return 0;
65582a5a936SPeter Hsiang }
65682a5a936SPeter Hsiang 
max98095_pga_in1_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)65782a5a936SPeter Hsiang static int max98095_pga_in1_event(struct snd_soc_dapm_widget *w,
65882a5a936SPeter Hsiang 				   struct snd_kcontrol *k, int event)
65982a5a936SPeter Hsiang {
66082a5a936SPeter Hsiang 	return max98095_line_pga(w, event, 1);
66182a5a936SPeter Hsiang }
66282a5a936SPeter Hsiang 
max98095_pga_in2_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)66382a5a936SPeter Hsiang static int max98095_pga_in2_event(struct snd_soc_dapm_widget *w,
66482a5a936SPeter Hsiang 				   struct snd_kcontrol *k, int event)
66582a5a936SPeter Hsiang {
66682a5a936SPeter Hsiang 	return max98095_line_pga(w, event, 2);
66782a5a936SPeter Hsiang }
66882a5a936SPeter Hsiang 
66982a5a936SPeter Hsiang /*
67082a5a936SPeter Hsiang  * The stereo line out mixer outputs to two stereo line outs.
67182a5a936SPeter Hsiang  * The 2nd pair has a separate set of enables.
67282a5a936SPeter Hsiang  */
max98095_lineout_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)67382a5a936SPeter Hsiang static int max98095_lineout_event(struct snd_soc_dapm_widget *w,
67482a5a936SPeter Hsiang 			     struct snd_kcontrol *kcontrol, int event)
67582a5a936SPeter Hsiang {
6762dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
67782a5a936SPeter Hsiang 
67882a5a936SPeter Hsiang 	switch (event) {
67982a5a936SPeter Hsiang 	case SND_SOC_DAPM_POST_PMU:
6802dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, w->reg,
68182a5a936SPeter Hsiang 			(1 << (w->shift+2)), (1 << (w->shift+2)));
68282a5a936SPeter Hsiang 		break;
68382a5a936SPeter Hsiang 	case SND_SOC_DAPM_POST_PMD:
6842dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, w->reg,
68582a5a936SPeter Hsiang 			(1 << (w->shift+2)), 0);
68682a5a936SPeter Hsiang 		break;
68782a5a936SPeter Hsiang 	default:
68882a5a936SPeter Hsiang 		return -EINVAL;
68982a5a936SPeter Hsiang 	}
69082a5a936SPeter Hsiang 
69182a5a936SPeter Hsiang 	return 0;
69282a5a936SPeter Hsiang }
69382a5a936SPeter Hsiang 
69482a5a936SPeter Hsiang static const struct snd_soc_dapm_widget max98095_dapm_widgets[] = {
69582a5a936SPeter Hsiang 
69682a5a936SPeter Hsiang 	SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98095_090_PWR_EN_IN, 0, 0),
69782a5a936SPeter Hsiang 	SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98095_090_PWR_EN_IN, 1, 0),
69882a5a936SPeter Hsiang 
69982a5a936SPeter Hsiang 	SND_SOC_DAPM_DAC("DACL1", "HiFi Playback",
70082a5a936SPeter Hsiang 		M98095_091_PWR_EN_OUT, 0, 0),
70182a5a936SPeter Hsiang 	SND_SOC_DAPM_DAC("DACR1", "HiFi Playback",
70282a5a936SPeter Hsiang 		M98095_091_PWR_EN_OUT, 1, 0),
70382a5a936SPeter Hsiang 	SND_SOC_DAPM_DAC("DACM2", "Aux Playback",
70482a5a936SPeter Hsiang 		M98095_091_PWR_EN_OUT, 2, 0),
70582a5a936SPeter Hsiang 	SND_SOC_DAPM_DAC("DACM3", "Voice Playback",
70682a5a936SPeter Hsiang 		M98095_091_PWR_EN_OUT, 2, 0),
70782a5a936SPeter Hsiang 
70882a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA("HP Left Out", M98095_091_PWR_EN_OUT,
70982a5a936SPeter Hsiang 		6, 0, NULL, 0),
71082a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA("HP Right Out", M98095_091_PWR_EN_OUT,
71182a5a936SPeter Hsiang 		7, 0, NULL, 0),
71282a5a936SPeter Hsiang 
71382a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA("SPK Left Out", M98095_091_PWR_EN_OUT,
71482a5a936SPeter Hsiang 		4, 0, NULL, 0),
71582a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA("SPK Right Out", M98095_091_PWR_EN_OUT,
71682a5a936SPeter Hsiang 		5, 0, NULL, 0),
71782a5a936SPeter Hsiang 
71882a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA("RCV Mono Out", M98095_091_PWR_EN_OUT,
71982a5a936SPeter Hsiang 		3, 0, NULL, 0),
72082a5a936SPeter Hsiang 
72182a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA_E("LINE Left Out", M98095_092_PWR_EN_OUT,
72282a5a936SPeter Hsiang 		0, 0, NULL, 0, max98095_lineout_event, SND_SOC_DAPM_PRE_PMD),
72382a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA_E("LINE Right Out", M98095_092_PWR_EN_OUT,
72482a5a936SPeter Hsiang 		1, 0, NULL, 0, max98095_lineout_event, SND_SOC_DAPM_PRE_PMD),
72582a5a936SPeter Hsiang 
72682a5a936SPeter Hsiang 	SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0,
72782a5a936SPeter Hsiang 		&max98095_extmic_mux),
72882a5a936SPeter Hsiang 
72982a5a936SPeter Hsiang 	SND_SOC_DAPM_MUX("Linein Mux", SND_SOC_NOPM, 0, 0,
73082a5a936SPeter Hsiang 		&max98095_linein_mux),
73182a5a936SPeter Hsiang 
73282a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
73382a5a936SPeter Hsiang 		&max98095_left_hp_mixer_controls[0],
73482a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_left_hp_mixer_controls)),
73582a5a936SPeter Hsiang 
73682a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Right Headphone Mixer", SND_SOC_NOPM, 0, 0,
73782a5a936SPeter Hsiang 		&max98095_right_hp_mixer_controls[0],
73882a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_right_hp_mixer_controls)),
73982a5a936SPeter Hsiang 
74082a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Left Speaker Mixer", SND_SOC_NOPM, 0, 0,
74182a5a936SPeter Hsiang 		&max98095_left_speaker_mixer_controls[0],
74282a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_left_speaker_mixer_controls)),
74382a5a936SPeter Hsiang 
74482a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Right Speaker Mixer", SND_SOC_NOPM, 0, 0,
74582a5a936SPeter Hsiang 		&max98095_right_speaker_mixer_controls[0],
74682a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_right_speaker_mixer_controls)),
74782a5a936SPeter Hsiang 
74882a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Receiver Mixer", SND_SOC_NOPM, 0, 0,
74982a5a936SPeter Hsiang 	  &max98095_mono_rcv_mixer_controls[0],
75082a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_mono_rcv_mixer_controls)),
75182a5a936SPeter Hsiang 
75282a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Left Lineout Mixer", SND_SOC_NOPM, 0, 0,
75382a5a936SPeter Hsiang 		&max98095_left_lineout_mixer_controls[0],
75482a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_left_lineout_mixer_controls)),
75582a5a936SPeter Hsiang 
75682a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Right Lineout Mixer", SND_SOC_NOPM, 0, 0,
75782a5a936SPeter Hsiang 		&max98095_right_lineout_mixer_controls[0],
75882a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_right_lineout_mixer_controls)),
75982a5a936SPeter Hsiang 
76082a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
76182a5a936SPeter Hsiang 		&max98095_left_ADC_mixer_controls[0],
76282a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_left_ADC_mixer_controls)),
76382a5a936SPeter Hsiang 
76482a5a936SPeter Hsiang 	SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
76582a5a936SPeter Hsiang 		&max98095_right_ADC_mixer_controls[0],
76682a5a936SPeter Hsiang 		ARRAY_SIZE(max98095_right_ADC_mixer_controls)),
76782a5a936SPeter Hsiang 
76882a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA_E("MIC1 Input", M98095_05F_LVL_MIC1,
76982a5a936SPeter Hsiang 		5, 0, NULL, 0, max98095_mic_event,
77082a5a936SPeter Hsiang 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
77182a5a936SPeter Hsiang 
77282a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA_E("MIC2 Input", M98095_060_LVL_MIC2,
77382a5a936SPeter Hsiang 		5, 0, NULL, 0, max98095_mic_event,
77482a5a936SPeter Hsiang 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
77582a5a936SPeter Hsiang 
77682a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA_E("IN1 Input", M98095_090_PWR_EN_IN,
77782a5a936SPeter Hsiang 		7, 0, NULL, 0, max98095_pga_in1_event,
77882a5a936SPeter Hsiang 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
77982a5a936SPeter Hsiang 
78082a5a936SPeter Hsiang 	SND_SOC_DAPM_PGA_E("IN2 Input", M98095_090_PWR_EN_IN,
78182a5a936SPeter Hsiang 		7, 0, NULL, 0, max98095_pga_in2_event,
78282a5a936SPeter Hsiang 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
78382a5a936SPeter Hsiang 
78482a5a936SPeter Hsiang 	SND_SOC_DAPM_MICBIAS("MICBIAS1", M98095_090_PWR_EN_IN, 2, 0),
78582a5a936SPeter Hsiang 	SND_SOC_DAPM_MICBIAS("MICBIAS2", M98095_090_PWR_EN_IN, 3, 0),
78682a5a936SPeter Hsiang 
78782a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("HPL"),
78882a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("HPR"),
78982a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("SPKL"),
79082a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("SPKR"),
79182a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("RCV"),
79282a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("OUT1"),
79382a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("OUT2"),
79482a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("OUT3"),
79582a5a936SPeter Hsiang 	SND_SOC_DAPM_OUTPUT("OUT4"),
79682a5a936SPeter Hsiang 
79782a5a936SPeter Hsiang 	SND_SOC_DAPM_INPUT("MIC1"),
79882a5a936SPeter Hsiang 	SND_SOC_DAPM_INPUT("MIC2"),
79982a5a936SPeter Hsiang 	SND_SOC_DAPM_INPUT("INA1"),
80082a5a936SPeter Hsiang 	SND_SOC_DAPM_INPUT("INA2"),
80182a5a936SPeter Hsiang 	SND_SOC_DAPM_INPUT("INB1"),
80282a5a936SPeter Hsiang 	SND_SOC_DAPM_INPUT("INB2"),
80382a5a936SPeter Hsiang };
80482a5a936SPeter Hsiang 
80582a5a936SPeter Hsiang static const struct snd_soc_dapm_route max98095_audio_map[] = {
80682a5a936SPeter Hsiang 	/* Left headphone output mixer */
80782a5a936SPeter Hsiang 	{"Left Headphone Mixer", "Left DAC1 Switch", "DACL1"},
80882a5a936SPeter Hsiang 	{"Left Headphone Mixer", "Right DAC1 Switch", "DACR1"},
80982a5a936SPeter Hsiang 	{"Left Headphone Mixer", "MIC1 Switch", "MIC1 Input"},
81082a5a936SPeter Hsiang 	{"Left Headphone Mixer", "MIC2 Switch", "MIC2 Input"},
81182a5a936SPeter Hsiang 	{"Left Headphone Mixer", "IN1 Switch", "IN1 Input"},
81282a5a936SPeter Hsiang 	{"Left Headphone Mixer", "IN2 Switch", "IN2 Input"},
81382a5a936SPeter Hsiang 
81482a5a936SPeter Hsiang 	/* Right headphone output mixer */
81582a5a936SPeter Hsiang 	{"Right Headphone Mixer", "Left DAC1 Switch", "DACL1"},
81682a5a936SPeter Hsiang 	{"Right Headphone Mixer", "Right DAC1 Switch", "DACR1"},
81782a5a936SPeter Hsiang 	{"Right Headphone Mixer", "MIC1 Switch", "MIC1 Input"},
81882a5a936SPeter Hsiang 	{"Right Headphone Mixer", "MIC2 Switch", "MIC2 Input"},
81982a5a936SPeter Hsiang 	{"Right Headphone Mixer", "IN1 Switch", "IN1 Input"},
82082a5a936SPeter Hsiang 	{"Right Headphone Mixer", "IN2 Switch", "IN2 Input"},
82182a5a936SPeter Hsiang 
82282a5a936SPeter Hsiang 	/* Left speaker output mixer */
82382a5a936SPeter Hsiang 	{"Left Speaker Mixer", "Left DAC1 Switch", "DACL1"},
82482a5a936SPeter Hsiang 	{"Left Speaker Mixer", "Right DAC1 Switch", "DACR1"},
82582a5a936SPeter Hsiang 	{"Left Speaker Mixer", "Mono DAC2 Switch", "DACM2"},
82682a5a936SPeter Hsiang 	{"Left Speaker Mixer", "Mono DAC3 Switch", "DACM3"},
82782a5a936SPeter Hsiang 	{"Left Speaker Mixer", "MIC1 Switch", "MIC1 Input"},
82882a5a936SPeter Hsiang 	{"Left Speaker Mixer", "MIC2 Switch", "MIC2 Input"},
82982a5a936SPeter Hsiang 	{"Left Speaker Mixer", "IN1 Switch", "IN1 Input"},
83082a5a936SPeter Hsiang 	{"Left Speaker Mixer", "IN2 Switch", "IN2 Input"},
83182a5a936SPeter Hsiang 
83282a5a936SPeter Hsiang 	/* Right speaker output mixer */
83382a5a936SPeter Hsiang 	{"Right Speaker Mixer", "Left DAC1 Switch", "DACL1"},
83482a5a936SPeter Hsiang 	{"Right Speaker Mixer", "Right DAC1 Switch", "DACR1"},
83582a5a936SPeter Hsiang 	{"Right Speaker Mixer", "Mono DAC2 Switch", "DACM2"},
83682a5a936SPeter Hsiang 	{"Right Speaker Mixer", "Mono DAC3 Switch", "DACM3"},
83782a5a936SPeter Hsiang 	{"Right Speaker Mixer", "MIC1 Switch", "MIC1 Input"},
83882a5a936SPeter Hsiang 	{"Right Speaker Mixer", "MIC2 Switch", "MIC2 Input"},
83982a5a936SPeter Hsiang 	{"Right Speaker Mixer", "IN1 Switch", "IN1 Input"},
84082a5a936SPeter Hsiang 	{"Right Speaker Mixer", "IN2 Switch", "IN2 Input"},
84182a5a936SPeter Hsiang 
84282a5a936SPeter Hsiang 	/* Earpiece/Receiver output mixer */
84382a5a936SPeter Hsiang 	{"Receiver Mixer", "Left DAC1 Switch", "DACL1"},
84482a5a936SPeter Hsiang 	{"Receiver Mixer", "Right DAC1 Switch", "DACR1"},
84582a5a936SPeter Hsiang 	{"Receiver Mixer", "MIC1 Switch", "MIC1 Input"},
84682a5a936SPeter Hsiang 	{"Receiver Mixer", "MIC2 Switch", "MIC2 Input"},
84782a5a936SPeter Hsiang 	{"Receiver Mixer", "IN1 Switch", "IN1 Input"},
84882a5a936SPeter Hsiang 	{"Receiver Mixer", "IN2 Switch", "IN2 Input"},
84982a5a936SPeter Hsiang 
85082a5a936SPeter Hsiang 	/* Left Lineout output mixer */
85182a5a936SPeter Hsiang 	{"Left Lineout Mixer", "Left DAC1 Switch", "DACL1"},
85282a5a936SPeter Hsiang 	{"Left Lineout Mixer", "Right DAC1 Switch", "DACR1"},
85382a5a936SPeter Hsiang 	{"Left Lineout Mixer", "MIC1 Switch", "MIC1 Input"},
85482a5a936SPeter Hsiang 	{"Left Lineout Mixer", "MIC2 Switch", "MIC2 Input"},
85582a5a936SPeter Hsiang 	{"Left Lineout Mixer", "IN1 Switch", "IN1 Input"},
85682a5a936SPeter Hsiang 	{"Left Lineout Mixer", "IN2 Switch", "IN2 Input"},
85782a5a936SPeter Hsiang 
85882a5a936SPeter Hsiang 	/* Right lineout output mixer */
85982a5a936SPeter Hsiang 	{"Right Lineout Mixer", "Left DAC1 Switch", "DACL1"},
86082a5a936SPeter Hsiang 	{"Right Lineout Mixer", "Right DAC1 Switch", "DACR1"},
86182a5a936SPeter Hsiang 	{"Right Lineout Mixer", "MIC1 Switch", "MIC1 Input"},
86282a5a936SPeter Hsiang 	{"Right Lineout Mixer", "MIC2 Switch", "MIC2 Input"},
86382a5a936SPeter Hsiang 	{"Right Lineout Mixer", "IN1 Switch", "IN1 Input"},
86482a5a936SPeter Hsiang 	{"Right Lineout Mixer", "IN2 Switch", "IN2 Input"},
86582a5a936SPeter Hsiang 
86682a5a936SPeter Hsiang 	{"HP Left Out", NULL, "Left Headphone Mixer"},
86782a5a936SPeter Hsiang 	{"HP Right Out", NULL, "Right Headphone Mixer"},
86882a5a936SPeter Hsiang 	{"SPK Left Out", NULL, "Left Speaker Mixer"},
86982a5a936SPeter Hsiang 	{"SPK Right Out", NULL, "Right Speaker Mixer"},
87082a5a936SPeter Hsiang 	{"RCV Mono Out", NULL, "Receiver Mixer"},
87182a5a936SPeter Hsiang 	{"LINE Left Out", NULL, "Left Lineout Mixer"},
87282a5a936SPeter Hsiang 	{"LINE Right Out", NULL, "Right Lineout Mixer"},
87382a5a936SPeter Hsiang 
87482a5a936SPeter Hsiang 	{"HPL", NULL, "HP Left Out"},
87582a5a936SPeter Hsiang 	{"HPR", NULL, "HP Right Out"},
87682a5a936SPeter Hsiang 	{"SPKL", NULL, "SPK Left Out"},
87782a5a936SPeter Hsiang 	{"SPKR", NULL, "SPK Right Out"},
87882a5a936SPeter Hsiang 	{"RCV", NULL, "RCV Mono Out"},
87982a5a936SPeter Hsiang 	{"OUT1", NULL, "LINE Left Out"},
88082a5a936SPeter Hsiang 	{"OUT2", NULL, "LINE Right Out"},
88182a5a936SPeter Hsiang 	{"OUT3", NULL, "LINE Left Out"},
88282a5a936SPeter Hsiang 	{"OUT4", NULL, "LINE Right Out"},
88382a5a936SPeter Hsiang 
88482a5a936SPeter Hsiang 	/* Left ADC input mixer */
88582a5a936SPeter Hsiang 	{"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"},
88682a5a936SPeter Hsiang 	{"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"},
88782a5a936SPeter Hsiang 	{"Left ADC Mixer", "IN1 Switch", "IN1 Input"},
88882a5a936SPeter Hsiang 	{"Left ADC Mixer", "IN2 Switch", "IN2 Input"},
88982a5a936SPeter Hsiang 
89082a5a936SPeter Hsiang 	/* Right ADC input mixer */
89182a5a936SPeter Hsiang 	{"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"},
89282a5a936SPeter Hsiang 	{"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"},
89382a5a936SPeter Hsiang 	{"Right ADC Mixer", "IN1 Switch", "IN1 Input"},
89482a5a936SPeter Hsiang 	{"Right ADC Mixer", "IN2 Switch", "IN2 Input"},
89582a5a936SPeter Hsiang 
89682a5a936SPeter Hsiang 	/* Inputs */
89782a5a936SPeter Hsiang 	{"ADCL", NULL, "Left ADC Mixer"},
89882a5a936SPeter Hsiang 	{"ADCR", NULL, "Right ADC Mixer"},
89982a5a936SPeter Hsiang 
90082a5a936SPeter Hsiang 	{"IN1 Input", NULL, "INA1"},
90182a5a936SPeter Hsiang 	{"IN2 Input", NULL, "INA2"},
90282a5a936SPeter Hsiang 
90382a5a936SPeter Hsiang 	{"MIC1 Input", NULL, "MIC1"},
90482a5a936SPeter Hsiang 	{"MIC2 Input", NULL, "MIC2"},
90582a5a936SPeter Hsiang };
90682a5a936SPeter Hsiang 
90782a5a936SPeter Hsiang /* codec mclk clock divider coefficients */
90882a5a936SPeter Hsiang static const struct {
90982a5a936SPeter Hsiang 	u32 rate;
91082a5a936SPeter Hsiang 	u8  sr;
91182a5a936SPeter Hsiang } rate_table[] = {
91282a5a936SPeter Hsiang 	{8000,  0x01},
91382a5a936SPeter Hsiang 	{11025, 0x02},
91482a5a936SPeter Hsiang 	{16000, 0x03},
91582a5a936SPeter Hsiang 	{22050, 0x04},
91682a5a936SPeter Hsiang 	{24000, 0x05},
91782a5a936SPeter Hsiang 	{32000, 0x06},
91882a5a936SPeter Hsiang 	{44100, 0x07},
91982a5a936SPeter Hsiang 	{48000, 0x08},
92082a5a936SPeter Hsiang 	{88200, 0x09},
92182a5a936SPeter Hsiang 	{96000, 0x0A},
92282a5a936SPeter Hsiang };
92382a5a936SPeter Hsiang 
rate_value(int rate,u8 * value)92482a5a936SPeter Hsiang static int rate_value(int rate, u8 *value)
92582a5a936SPeter Hsiang {
92682a5a936SPeter Hsiang 	int i;
92782a5a936SPeter Hsiang 
92882a5a936SPeter Hsiang 	for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
92982a5a936SPeter Hsiang 		if (rate_table[i].rate >= rate) {
93082a5a936SPeter Hsiang 			*value = rate_table[i].sr;
93182a5a936SPeter Hsiang 			return 0;
93282a5a936SPeter Hsiang 		}
93382a5a936SPeter Hsiang 	}
93482a5a936SPeter Hsiang 	*value = rate_table[0].sr;
93582a5a936SPeter Hsiang 	return -EINVAL;
93682a5a936SPeter Hsiang }
93782a5a936SPeter Hsiang 
max98095_dai1_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)93882a5a936SPeter Hsiang static int max98095_dai1_hw_params(struct snd_pcm_substream *substream,
93982a5a936SPeter Hsiang 				   struct snd_pcm_hw_params *params,
94082a5a936SPeter Hsiang 				   struct snd_soc_dai *dai)
94182a5a936SPeter Hsiang {
9422dd1637fSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
9432dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
94482a5a936SPeter Hsiang 	struct max98095_cdata *cdata;
94582a5a936SPeter Hsiang 	unsigned long long ni;
94682a5a936SPeter Hsiang 	unsigned int rate;
94782a5a936SPeter Hsiang 	u8 regval;
94882a5a936SPeter Hsiang 
94982a5a936SPeter Hsiang 	cdata = &max98095->dai[0];
95082a5a936SPeter Hsiang 
95182a5a936SPeter Hsiang 	rate = params_rate(params);
95282a5a936SPeter Hsiang 
953580ce08dSMark Brown 	switch (params_width(params)) {
954580ce08dSMark Brown 	case 16:
9552dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_02A_DAI1_FORMAT,
95682a5a936SPeter Hsiang 			M98095_DAI_WS, 0);
95782a5a936SPeter Hsiang 		break;
958580ce08dSMark Brown 	case 24:
9592dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_02A_DAI1_FORMAT,
96082a5a936SPeter Hsiang 			M98095_DAI_WS, M98095_DAI_WS);
96182a5a936SPeter Hsiang 		break;
96282a5a936SPeter Hsiang 	default:
96382a5a936SPeter Hsiang 		return -EINVAL;
96482a5a936SPeter Hsiang 	}
96582a5a936SPeter Hsiang 
96682a5a936SPeter Hsiang 	if (rate_value(rate, &regval))
96782a5a936SPeter Hsiang 		return -EINVAL;
96882a5a936SPeter Hsiang 
9692dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_027_DAI1_CLKMODE,
97082a5a936SPeter Hsiang 		M98095_CLKMODE_MASK, regval);
97182a5a936SPeter Hsiang 	cdata->rate = rate;
97282a5a936SPeter Hsiang 
97382a5a936SPeter Hsiang 	/* Configure NI when operating as master */
9741227f601SKuninori Morimoto 	if (snd_soc_component_read(component, M98095_02A_DAI1_FORMAT) & M98095_DAI_MAS) {
97582a5a936SPeter Hsiang 		if (max98095->sysclk == 0) {
9762dd1637fSKuninori Morimoto 			dev_err(component->dev, "Invalid system clock frequency\n");
97782a5a936SPeter Hsiang 			return -EINVAL;
97882a5a936SPeter Hsiang 		}
97982a5a936SPeter Hsiang 		ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
98082a5a936SPeter Hsiang 				* (unsigned long long int)rate;
98182a5a936SPeter Hsiang 		do_div(ni, (unsigned long long int)max98095->sysclk);
9822dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_028_DAI1_CLKCFG_HI,
98382a5a936SPeter Hsiang 			(ni >> 8) & 0x7F);
9842dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_029_DAI1_CLKCFG_LO,
98582a5a936SPeter Hsiang 			ni & 0xFF);
98682a5a936SPeter Hsiang 	}
98782a5a936SPeter Hsiang 
98882a5a936SPeter Hsiang 	/* Update sample rate mode */
98982a5a936SPeter Hsiang 	if (rate < 50000)
9902dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_02E_DAI1_FILTERS,
99182a5a936SPeter Hsiang 			M98095_DAI_DHF, 0);
99282a5a936SPeter Hsiang 	else
9932dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_02E_DAI1_FILTERS,
99482a5a936SPeter Hsiang 			M98095_DAI_DHF, M98095_DAI_DHF);
99582a5a936SPeter Hsiang 
99682a5a936SPeter Hsiang 	return 0;
99782a5a936SPeter Hsiang }
99882a5a936SPeter Hsiang 
max98095_dai2_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)99982a5a936SPeter Hsiang static int max98095_dai2_hw_params(struct snd_pcm_substream *substream,
100082a5a936SPeter Hsiang 				   struct snd_pcm_hw_params *params,
100182a5a936SPeter Hsiang 				   struct snd_soc_dai *dai)
100282a5a936SPeter Hsiang {
10032dd1637fSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
10042dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
100582a5a936SPeter Hsiang 	struct max98095_cdata *cdata;
100682a5a936SPeter Hsiang 	unsigned long long ni;
100782a5a936SPeter Hsiang 	unsigned int rate;
100882a5a936SPeter Hsiang 	u8 regval;
100982a5a936SPeter Hsiang 
101082a5a936SPeter Hsiang 	cdata = &max98095->dai[1];
101182a5a936SPeter Hsiang 
101282a5a936SPeter Hsiang 	rate = params_rate(params);
101382a5a936SPeter Hsiang 
10141ae1f3a2SMark Brown 	switch (params_width(params)) {
10151ae1f3a2SMark Brown 	case 16:
10162dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_034_DAI2_FORMAT,
101782a5a936SPeter Hsiang 			M98095_DAI_WS, 0);
101882a5a936SPeter Hsiang 		break;
10191ae1f3a2SMark Brown 	case 24:
10202dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_034_DAI2_FORMAT,
102182a5a936SPeter Hsiang 			M98095_DAI_WS, M98095_DAI_WS);
102282a5a936SPeter Hsiang 		break;
102382a5a936SPeter Hsiang 	default:
102482a5a936SPeter Hsiang 		return -EINVAL;
102582a5a936SPeter Hsiang 	}
102682a5a936SPeter Hsiang 
102782a5a936SPeter Hsiang 	if (rate_value(rate, &regval))
102882a5a936SPeter Hsiang 		return -EINVAL;
102982a5a936SPeter Hsiang 
10302dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_031_DAI2_CLKMODE,
103182a5a936SPeter Hsiang 		M98095_CLKMODE_MASK, regval);
103282a5a936SPeter Hsiang 	cdata->rate = rate;
103382a5a936SPeter Hsiang 
103482a5a936SPeter Hsiang 	/* Configure NI when operating as master */
10351227f601SKuninori Morimoto 	if (snd_soc_component_read(component, M98095_034_DAI2_FORMAT) & M98095_DAI_MAS) {
103682a5a936SPeter Hsiang 		if (max98095->sysclk == 0) {
10372dd1637fSKuninori Morimoto 			dev_err(component->dev, "Invalid system clock frequency\n");
103882a5a936SPeter Hsiang 			return -EINVAL;
103982a5a936SPeter Hsiang 		}
104082a5a936SPeter Hsiang 		ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
104182a5a936SPeter Hsiang 				* (unsigned long long int)rate;
104282a5a936SPeter Hsiang 		do_div(ni, (unsigned long long int)max98095->sysclk);
10432dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_032_DAI2_CLKCFG_HI,
104482a5a936SPeter Hsiang 			(ni >> 8) & 0x7F);
10452dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_033_DAI2_CLKCFG_LO,
104682a5a936SPeter Hsiang 			ni & 0xFF);
104782a5a936SPeter Hsiang 	}
104882a5a936SPeter Hsiang 
104982a5a936SPeter Hsiang 	/* Update sample rate mode */
105082a5a936SPeter Hsiang 	if (rate < 50000)
10512dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_038_DAI2_FILTERS,
105282a5a936SPeter Hsiang 			M98095_DAI_DHF, 0);
105382a5a936SPeter Hsiang 	else
10542dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_038_DAI2_FILTERS,
105582a5a936SPeter Hsiang 			M98095_DAI_DHF, M98095_DAI_DHF);
105682a5a936SPeter Hsiang 
105782a5a936SPeter Hsiang 	return 0;
105882a5a936SPeter Hsiang }
105982a5a936SPeter Hsiang 
max98095_dai3_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)106082a5a936SPeter Hsiang static int max98095_dai3_hw_params(struct snd_pcm_substream *substream,
106182a5a936SPeter Hsiang 				   struct snd_pcm_hw_params *params,
106282a5a936SPeter Hsiang 				   struct snd_soc_dai *dai)
106382a5a936SPeter Hsiang {
10642dd1637fSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
10652dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
106682a5a936SPeter Hsiang 	struct max98095_cdata *cdata;
106782a5a936SPeter Hsiang 	unsigned long long ni;
106882a5a936SPeter Hsiang 	unsigned int rate;
106982a5a936SPeter Hsiang 	u8 regval;
107082a5a936SPeter Hsiang 
107182a5a936SPeter Hsiang 	cdata = &max98095->dai[2];
107282a5a936SPeter Hsiang 
107382a5a936SPeter Hsiang 	rate = params_rate(params);
107482a5a936SPeter Hsiang 
10751ae1f3a2SMark Brown 	switch (params_width(params)) {
10761ae1f3a2SMark Brown 	case 16:
10772dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_03E_DAI3_FORMAT,
107882a5a936SPeter Hsiang 			M98095_DAI_WS, 0);
107982a5a936SPeter Hsiang 		break;
10801ae1f3a2SMark Brown 	case 24:
10812dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_03E_DAI3_FORMAT,
108282a5a936SPeter Hsiang 			M98095_DAI_WS, M98095_DAI_WS);
108382a5a936SPeter Hsiang 		break;
108482a5a936SPeter Hsiang 	default:
108582a5a936SPeter Hsiang 		return -EINVAL;
108682a5a936SPeter Hsiang 	}
108782a5a936SPeter Hsiang 
108882a5a936SPeter Hsiang 	if (rate_value(rate, &regval))
108982a5a936SPeter Hsiang 		return -EINVAL;
109082a5a936SPeter Hsiang 
10912dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_03B_DAI3_CLKMODE,
109282a5a936SPeter Hsiang 		M98095_CLKMODE_MASK, regval);
109382a5a936SPeter Hsiang 	cdata->rate = rate;
109482a5a936SPeter Hsiang 
109582a5a936SPeter Hsiang 	/* Configure NI when operating as master */
10961227f601SKuninori Morimoto 	if (snd_soc_component_read(component, M98095_03E_DAI3_FORMAT) & M98095_DAI_MAS) {
109782a5a936SPeter Hsiang 		if (max98095->sysclk == 0) {
10982dd1637fSKuninori Morimoto 			dev_err(component->dev, "Invalid system clock frequency\n");
109982a5a936SPeter Hsiang 			return -EINVAL;
110082a5a936SPeter Hsiang 		}
110182a5a936SPeter Hsiang 		ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
110282a5a936SPeter Hsiang 				* (unsigned long long int)rate;
110382a5a936SPeter Hsiang 		do_div(ni, (unsigned long long int)max98095->sysclk);
11042dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_03C_DAI3_CLKCFG_HI,
110582a5a936SPeter Hsiang 			(ni >> 8) & 0x7F);
11062dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_03D_DAI3_CLKCFG_LO,
110782a5a936SPeter Hsiang 			ni & 0xFF);
110882a5a936SPeter Hsiang 	}
110982a5a936SPeter Hsiang 
111082a5a936SPeter Hsiang 	/* Update sample rate mode */
111182a5a936SPeter Hsiang 	if (rate < 50000)
11122dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_042_DAI3_FILTERS,
111382a5a936SPeter Hsiang 			M98095_DAI_DHF, 0);
111482a5a936SPeter Hsiang 	else
11152dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_042_DAI3_FILTERS,
111682a5a936SPeter Hsiang 			M98095_DAI_DHF, M98095_DAI_DHF);
111782a5a936SPeter Hsiang 
111882a5a936SPeter Hsiang 	return 0;
111982a5a936SPeter Hsiang }
112082a5a936SPeter Hsiang 
max98095_dai_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)112182a5a936SPeter Hsiang static int max98095_dai_set_sysclk(struct snd_soc_dai *dai,
112282a5a936SPeter Hsiang 				   int clk_id, unsigned int freq, int dir)
112382a5a936SPeter Hsiang {
11242dd1637fSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
11252dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
112682a5a936SPeter Hsiang 
112782a5a936SPeter Hsiang 	/* Requested clock frequency is already setup */
112882a5a936SPeter Hsiang 	if (freq == max98095->sysclk)
112982a5a936SPeter Hsiang 		return 0;
113082a5a936SPeter Hsiang 
1131e3048c3dSTushar Behera 	if (!IS_ERR(max98095->mclk)) {
1132e3048c3dSTushar Behera 		freq = clk_round_rate(max98095->mclk, freq);
1133e3048c3dSTushar Behera 		clk_set_rate(max98095->mclk, freq);
1134e3048c3dSTushar Behera 	}
1135e3048c3dSTushar Behera 
113682a5a936SPeter Hsiang 	/* Setup clocks for slave mode, and using the PLL
113782a5a936SPeter Hsiang 	 * PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
113882a5a936SPeter Hsiang 	 *         0x02 (when master clk is 20MHz to 40MHz)..
113982a5a936SPeter Hsiang 	 *         0x03 (when master clk is 40MHz to 60MHz)..
114082a5a936SPeter Hsiang 	 */
114182a5a936SPeter Hsiang 	if ((freq >= 10000000) && (freq < 20000000)) {
11422dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_026_SYS_CLK, 0x10);
114382a5a936SPeter Hsiang 	} else if ((freq >= 20000000) && (freq < 40000000)) {
11442dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_026_SYS_CLK, 0x20);
114582a5a936SPeter Hsiang 	} else if ((freq >= 40000000) && (freq < 60000000)) {
11462dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_026_SYS_CLK, 0x30);
114782a5a936SPeter Hsiang 	} else {
11482dd1637fSKuninori Morimoto 		dev_err(component->dev, "Invalid master clock frequency\n");
114982a5a936SPeter Hsiang 		return -EINVAL;
115082a5a936SPeter Hsiang 	}
115182a5a936SPeter Hsiang 
115282a5a936SPeter Hsiang 	dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq);
115382a5a936SPeter Hsiang 
115482a5a936SPeter Hsiang 	max98095->sysclk = freq;
115582a5a936SPeter Hsiang 	return 0;
115682a5a936SPeter Hsiang }
115782a5a936SPeter Hsiang 
max98095_dai1_set_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)115882a5a936SPeter Hsiang static int max98095_dai1_set_fmt(struct snd_soc_dai *codec_dai,
115982a5a936SPeter Hsiang 				 unsigned int fmt)
116082a5a936SPeter Hsiang {
11612dd1637fSKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
11622dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
116382a5a936SPeter Hsiang 	struct max98095_cdata *cdata;
116482a5a936SPeter Hsiang 	u8 regval = 0;
116582a5a936SPeter Hsiang 
116682a5a936SPeter Hsiang 	cdata = &max98095->dai[0];
116782a5a936SPeter Hsiang 
116882a5a936SPeter Hsiang 	if (fmt != cdata->fmt) {
116982a5a936SPeter Hsiang 		cdata->fmt = fmt;
117082a5a936SPeter Hsiang 
11712232314bSMark Brown 		switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
11722232314bSMark Brown 		case SND_SOC_DAIFMT_CBC_CFC:
11732232314bSMark Brown 			/* Consumer mode PLL */
11742dd1637fSKuninori Morimoto 			snd_soc_component_write(component, M98095_028_DAI1_CLKCFG_HI,
117582a5a936SPeter Hsiang 				0x80);
11762dd1637fSKuninori Morimoto 			snd_soc_component_write(component, M98095_029_DAI1_CLKCFG_LO,
117782a5a936SPeter Hsiang 				0x00);
117882a5a936SPeter Hsiang 			break;
11792232314bSMark Brown 		case SND_SOC_DAIFMT_CBP_CFP:
11802232314bSMark Brown 			/* Set to provider mode */
118182a5a936SPeter Hsiang 			regval |= M98095_DAI_MAS;
118282a5a936SPeter Hsiang 			break;
118382a5a936SPeter Hsiang 		default:
11842dd1637fSKuninori Morimoto 			dev_err(component->dev, "Clock mode unsupported");
118582a5a936SPeter Hsiang 			return -EINVAL;
118682a5a936SPeter Hsiang 		}
118782a5a936SPeter Hsiang 
118882a5a936SPeter Hsiang 		switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
118982a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_I2S:
119082a5a936SPeter Hsiang 			regval |= M98095_DAI_DLY;
119182a5a936SPeter Hsiang 			break;
119282a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_LEFT_J:
119382a5a936SPeter Hsiang 			break;
119482a5a936SPeter Hsiang 		default:
119582a5a936SPeter Hsiang 			return -EINVAL;
119682a5a936SPeter Hsiang 		}
119782a5a936SPeter Hsiang 
119882a5a936SPeter Hsiang 		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
119982a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_NB_NF:
120082a5a936SPeter Hsiang 			break;
120182a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_NB_IF:
120282a5a936SPeter Hsiang 			regval |= M98095_DAI_WCI;
120382a5a936SPeter Hsiang 			break;
120482a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_IB_NF:
120582a5a936SPeter Hsiang 			regval |= M98095_DAI_BCI;
120682a5a936SPeter Hsiang 			break;
120782a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_IB_IF:
120882a5a936SPeter Hsiang 			regval |= M98095_DAI_BCI|M98095_DAI_WCI;
120982a5a936SPeter Hsiang 			break;
121082a5a936SPeter Hsiang 		default:
121182a5a936SPeter Hsiang 			return -EINVAL;
121282a5a936SPeter Hsiang 		}
121382a5a936SPeter Hsiang 
12142dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_02A_DAI1_FORMAT,
121582a5a936SPeter Hsiang 			M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI |
121682a5a936SPeter Hsiang 			M98095_DAI_WCI, regval);
121782a5a936SPeter Hsiang 
12182dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_02B_DAI1_CLOCK, M98095_DAI_BSEL64);
121982a5a936SPeter Hsiang 	}
122082a5a936SPeter Hsiang 
122182a5a936SPeter Hsiang 	return 0;
122282a5a936SPeter Hsiang }
122382a5a936SPeter Hsiang 
max98095_dai2_set_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)122482a5a936SPeter Hsiang static int max98095_dai2_set_fmt(struct snd_soc_dai *codec_dai,
122582a5a936SPeter Hsiang 				 unsigned int fmt)
122682a5a936SPeter Hsiang {
12272dd1637fSKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
12282dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
122982a5a936SPeter Hsiang 	struct max98095_cdata *cdata;
123082a5a936SPeter Hsiang 	u8 regval = 0;
123182a5a936SPeter Hsiang 
123282a5a936SPeter Hsiang 	cdata = &max98095->dai[1];
123382a5a936SPeter Hsiang 
123482a5a936SPeter Hsiang 	if (fmt != cdata->fmt) {
123582a5a936SPeter Hsiang 		cdata->fmt = fmt;
123682a5a936SPeter Hsiang 
12372232314bSMark Brown 		switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
12382232314bSMark Brown 		case SND_SOC_DAIFMT_CBC_CFC:
12392232314bSMark Brown 			/* Consumer mode PLL */
12402dd1637fSKuninori Morimoto 			snd_soc_component_write(component, M98095_032_DAI2_CLKCFG_HI,
124182a5a936SPeter Hsiang 				0x80);
12422dd1637fSKuninori Morimoto 			snd_soc_component_write(component, M98095_033_DAI2_CLKCFG_LO,
124382a5a936SPeter Hsiang 				0x00);
124482a5a936SPeter Hsiang 			break;
12452232314bSMark Brown 		case SND_SOC_DAIFMT_CBP_CFP:
12462232314bSMark Brown 			/* Set to provider mode */
124782a5a936SPeter Hsiang 			regval |= M98095_DAI_MAS;
124882a5a936SPeter Hsiang 			break;
124982a5a936SPeter Hsiang 		default:
12502dd1637fSKuninori Morimoto 			dev_err(component->dev, "Clock mode unsupported");
125182a5a936SPeter Hsiang 			return -EINVAL;
125282a5a936SPeter Hsiang 		}
125382a5a936SPeter Hsiang 
125482a5a936SPeter Hsiang 		switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
125582a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_I2S:
125682a5a936SPeter Hsiang 			regval |= M98095_DAI_DLY;
125782a5a936SPeter Hsiang 			break;
125882a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_LEFT_J:
125982a5a936SPeter Hsiang 			break;
126082a5a936SPeter Hsiang 		default:
126182a5a936SPeter Hsiang 			return -EINVAL;
126282a5a936SPeter Hsiang 		}
126382a5a936SPeter Hsiang 
126482a5a936SPeter Hsiang 		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
126582a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_NB_NF:
126682a5a936SPeter Hsiang 			break;
126782a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_NB_IF:
126882a5a936SPeter Hsiang 			regval |= M98095_DAI_WCI;
126982a5a936SPeter Hsiang 			break;
127082a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_IB_NF:
127182a5a936SPeter Hsiang 			regval |= M98095_DAI_BCI;
127282a5a936SPeter Hsiang 			break;
127382a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_IB_IF:
127482a5a936SPeter Hsiang 			regval |= M98095_DAI_BCI|M98095_DAI_WCI;
127582a5a936SPeter Hsiang 			break;
127682a5a936SPeter Hsiang 		default:
127782a5a936SPeter Hsiang 			return -EINVAL;
127882a5a936SPeter Hsiang 		}
127982a5a936SPeter Hsiang 
12802dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_034_DAI2_FORMAT,
128182a5a936SPeter Hsiang 			M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI |
128282a5a936SPeter Hsiang 			M98095_DAI_WCI, regval);
128382a5a936SPeter Hsiang 
12842dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_035_DAI2_CLOCK,
128582a5a936SPeter Hsiang 			M98095_DAI_BSEL64);
128682a5a936SPeter Hsiang 	}
128782a5a936SPeter Hsiang 
128882a5a936SPeter Hsiang 	return 0;
128982a5a936SPeter Hsiang }
129082a5a936SPeter Hsiang 
max98095_dai3_set_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)129182a5a936SPeter Hsiang static int max98095_dai3_set_fmt(struct snd_soc_dai *codec_dai,
129282a5a936SPeter Hsiang 				 unsigned int fmt)
129382a5a936SPeter Hsiang {
12942dd1637fSKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
12952dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
129682a5a936SPeter Hsiang 	struct max98095_cdata *cdata;
129782a5a936SPeter Hsiang 	u8 regval = 0;
129882a5a936SPeter Hsiang 
129982a5a936SPeter Hsiang 	cdata = &max98095->dai[2];
130082a5a936SPeter Hsiang 
130182a5a936SPeter Hsiang 	if (fmt != cdata->fmt) {
130282a5a936SPeter Hsiang 		cdata->fmt = fmt;
130382a5a936SPeter Hsiang 
13042232314bSMark Brown 		switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
13052232314bSMark Brown 		case SND_SOC_DAIFMT_CBC_CFC:
13062232314bSMark Brown 			/* Consumer mode PLL */
13072dd1637fSKuninori Morimoto 			snd_soc_component_write(component, M98095_03C_DAI3_CLKCFG_HI,
130882a5a936SPeter Hsiang 				0x80);
13092dd1637fSKuninori Morimoto 			snd_soc_component_write(component, M98095_03D_DAI3_CLKCFG_LO,
131082a5a936SPeter Hsiang 				0x00);
131182a5a936SPeter Hsiang 			break;
13122232314bSMark Brown 		case SND_SOC_DAIFMT_CBP_CFP:
13132232314bSMark Brown 			/* Set to provider mode */
131482a5a936SPeter Hsiang 			regval |= M98095_DAI_MAS;
131582a5a936SPeter Hsiang 			break;
131682a5a936SPeter Hsiang 		default:
13172dd1637fSKuninori Morimoto 			dev_err(component->dev, "Clock mode unsupported");
131882a5a936SPeter Hsiang 			return -EINVAL;
131982a5a936SPeter Hsiang 		}
132082a5a936SPeter Hsiang 
132182a5a936SPeter Hsiang 		switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
132282a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_I2S:
132382a5a936SPeter Hsiang 			regval |= M98095_DAI_DLY;
132482a5a936SPeter Hsiang 			break;
132582a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_LEFT_J:
132682a5a936SPeter Hsiang 			break;
132782a5a936SPeter Hsiang 		default:
132882a5a936SPeter Hsiang 			return -EINVAL;
132982a5a936SPeter Hsiang 		}
133082a5a936SPeter Hsiang 
133182a5a936SPeter Hsiang 		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
133282a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_NB_NF:
133382a5a936SPeter Hsiang 			break;
133482a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_NB_IF:
133582a5a936SPeter Hsiang 			regval |= M98095_DAI_WCI;
133682a5a936SPeter Hsiang 			break;
133782a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_IB_NF:
133882a5a936SPeter Hsiang 			regval |= M98095_DAI_BCI;
133982a5a936SPeter Hsiang 			break;
134082a5a936SPeter Hsiang 		case SND_SOC_DAIFMT_IB_IF:
134182a5a936SPeter Hsiang 			regval |= M98095_DAI_BCI|M98095_DAI_WCI;
134282a5a936SPeter Hsiang 			break;
134382a5a936SPeter Hsiang 		default:
134482a5a936SPeter Hsiang 			return -EINVAL;
134582a5a936SPeter Hsiang 		}
134682a5a936SPeter Hsiang 
13472dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_03E_DAI3_FORMAT,
134882a5a936SPeter Hsiang 			M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI |
134982a5a936SPeter Hsiang 			M98095_DAI_WCI, regval);
135082a5a936SPeter Hsiang 
13512dd1637fSKuninori Morimoto 		snd_soc_component_write(component, M98095_03F_DAI3_CLOCK,
135282a5a936SPeter Hsiang 			M98095_DAI_BSEL64);
135382a5a936SPeter Hsiang 	}
135482a5a936SPeter Hsiang 
135582a5a936SPeter Hsiang 	return 0;
135682a5a936SPeter Hsiang }
135782a5a936SPeter Hsiang 
max98095_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)13582dd1637fSKuninori Morimoto static int max98095_set_bias_level(struct snd_soc_component *component,
135982a5a936SPeter Hsiang 				   enum snd_soc_bias_level level)
136082a5a936SPeter Hsiang {
13612dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
136282a5a936SPeter Hsiang 	int ret;
136382a5a936SPeter Hsiang 
136482a5a936SPeter Hsiang 	switch (level) {
136582a5a936SPeter Hsiang 	case SND_SOC_BIAS_ON:
136682a5a936SPeter Hsiang 		break;
136782a5a936SPeter Hsiang 
136882a5a936SPeter Hsiang 	case SND_SOC_BIAS_PREPARE:
1369e3048c3dSTushar Behera 		/*
1370e3048c3dSTushar Behera 		 * SND_SOC_BIAS_PREPARE is called while preparing for a
1371e3048c3dSTushar Behera 		 * transition to ON or away from ON. If current bias_level
1372e3048c3dSTushar Behera 		 * is SND_SOC_BIAS_ON, then it is preparing for a transition
1373e3048c3dSTushar Behera 		 * away from ON. Disable the clock in that case, otherwise
1374e3048c3dSTushar Behera 		 * enable it.
1375e3048c3dSTushar Behera 		 */
13761179a368SLars-Peter Clausen 		if (IS_ERR(max98095->mclk))
13771179a368SLars-Peter Clausen 			break;
13781179a368SLars-Peter Clausen 
13792dd1637fSKuninori Morimoto 		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON) {
1380e3048c3dSTushar Behera 			clk_disable_unprepare(max98095->mclk);
1381402f2a4fSFabio Estevam 		} else {
1382402f2a4fSFabio Estevam 			ret = clk_prepare_enable(max98095->mclk);
1383402f2a4fSFabio Estevam 			if (ret)
1384402f2a4fSFabio Estevam 				return ret;
1385402f2a4fSFabio Estevam 		}
138682a5a936SPeter Hsiang 		break;
138782a5a936SPeter Hsiang 
138882a5a936SPeter Hsiang 	case SND_SOC_BIAS_STANDBY:
13892dd1637fSKuninori Morimoto 		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
139014acbbbbSMark Brown 			ret = regcache_sync(max98095->regmap);
139182a5a936SPeter Hsiang 
139282a5a936SPeter Hsiang 			if (ret != 0) {
13932dd1637fSKuninori Morimoto 				dev_err(component->dev, "Failed to sync cache: %d\n", ret);
139482a5a936SPeter Hsiang 				return ret;
139582a5a936SPeter Hsiang 			}
139682a5a936SPeter Hsiang 		}
139782a5a936SPeter Hsiang 
13982dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_090_PWR_EN_IN,
139982a5a936SPeter Hsiang 				M98095_MBEN, M98095_MBEN);
140082a5a936SPeter Hsiang 		break;
140182a5a936SPeter Hsiang 
140282a5a936SPeter Hsiang 	case SND_SOC_BIAS_OFF:
14032dd1637fSKuninori Morimoto 		snd_soc_component_update_bits(component, M98095_090_PWR_EN_IN,
140482a5a936SPeter Hsiang 				M98095_MBEN, 0);
140514acbbbbSMark Brown 		regcache_mark_dirty(max98095->regmap);
140682a5a936SPeter Hsiang 		break;
140782a5a936SPeter Hsiang 	}
140882a5a936SPeter Hsiang 	return 0;
140982a5a936SPeter Hsiang }
141082a5a936SPeter Hsiang 
141182a5a936SPeter Hsiang #define MAX98095_RATES SNDRV_PCM_RATE_8000_96000
141282a5a936SPeter Hsiang #define MAX98095_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
141382a5a936SPeter Hsiang 
141485e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops max98095_dai1_ops = {
141582a5a936SPeter Hsiang 	.set_sysclk = max98095_dai_set_sysclk,
141682a5a936SPeter Hsiang 	.set_fmt = max98095_dai1_set_fmt,
141782a5a936SPeter Hsiang 	.hw_params = max98095_dai1_hw_params,
141882a5a936SPeter Hsiang };
141982a5a936SPeter Hsiang 
142085e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops max98095_dai2_ops = {
142182a5a936SPeter Hsiang 	.set_sysclk = max98095_dai_set_sysclk,
142282a5a936SPeter Hsiang 	.set_fmt = max98095_dai2_set_fmt,
142382a5a936SPeter Hsiang 	.hw_params = max98095_dai2_hw_params,
142482a5a936SPeter Hsiang };
142582a5a936SPeter Hsiang 
142685e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops max98095_dai3_ops = {
142782a5a936SPeter Hsiang 	.set_sysclk = max98095_dai_set_sysclk,
142882a5a936SPeter Hsiang 	.set_fmt = max98095_dai3_set_fmt,
142982a5a936SPeter Hsiang 	.hw_params = max98095_dai3_hw_params,
143082a5a936SPeter Hsiang };
143182a5a936SPeter Hsiang 
143282a5a936SPeter Hsiang static struct snd_soc_dai_driver max98095_dai[] = {
143382a5a936SPeter Hsiang {
143482a5a936SPeter Hsiang 	.name = "HiFi",
143582a5a936SPeter Hsiang 	.playback = {
143682a5a936SPeter Hsiang 		.stream_name = "HiFi Playback",
143782a5a936SPeter Hsiang 		.channels_min = 1,
143882a5a936SPeter Hsiang 		.channels_max = 2,
143982a5a936SPeter Hsiang 		.rates = MAX98095_RATES,
144082a5a936SPeter Hsiang 		.formats = MAX98095_FORMATS,
144182a5a936SPeter Hsiang 	},
144282a5a936SPeter Hsiang 	.capture = {
144382a5a936SPeter Hsiang 		.stream_name = "HiFi Capture",
144482a5a936SPeter Hsiang 		.channels_min = 1,
144582a5a936SPeter Hsiang 		.channels_max = 2,
144682a5a936SPeter Hsiang 		.rates = MAX98095_RATES,
144782a5a936SPeter Hsiang 		.formats = MAX98095_FORMATS,
144882a5a936SPeter Hsiang 	},
144982a5a936SPeter Hsiang 	 .ops = &max98095_dai1_ops,
145082a5a936SPeter Hsiang },
145182a5a936SPeter Hsiang {
145282a5a936SPeter Hsiang 	.name = "Aux",
145382a5a936SPeter Hsiang 	.playback = {
145482a5a936SPeter Hsiang 		.stream_name = "Aux Playback",
145582a5a936SPeter Hsiang 		.channels_min = 1,
145682a5a936SPeter Hsiang 		.channels_max = 1,
145782a5a936SPeter Hsiang 		.rates = MAX98095_RATES,
145882a5a936SPeter Hsiang 		.formats = MAX98095_FORMATS,
145982a5a936SPeter Hsiang 	},
146082a5a936SPeter Hsiang 	.ops = &max98095_dai2_ops,
146182a5a936SPeter Hsiang },
146282a5a936SPeter Hsiang {
146382a5a936SPeter Hsiang 	.name = "Voice",
146482a5a936SPeter Hsiang 	.playback = {
146582a5a936SPeter Hsiang 		.stream_name = "Voice Playback",
146682a5a936SPeter Hsiang 		.channels_min = 1,
146782a5a936SPeter Hsiang 		.channels_max = 1,
146882a5a936SPeter Hsiang 		.rates = MAX98095_RATES,
146982a5a936SPeter Hsiang 		.formats = MAX98095_FORMATS,
147082a5a936SPeter Hsiang 	},
147182a5a936SPeter Hsiang 	.ops = &max98095_dai3_ops,
147282a5a936SPeter Hsiang }
147382a5a936SPeter Hsiang 
147482a5a936SPeter Hsiang };
147582a5a936SPeter Hsiang 
max98095_get_eq_channel(const char * name)1476dad31ec1SPeter Hsiang static int max98095_get_eq_channel(const char *name)
1477dad31ec1SPeter Hsiang {
1478dad31ec1SPeter Hsiang 	if (strcmp(name, "EQ1 Mode") == 0)
1479dad31ec1SPeter Hsiang 		return 0;
1480dad31ec1SPeter Hsiang 	if (strcmp(name, "EQ2 Mode") == 0)
1481dad31ec1SPeter Hsiang 		return 1;
1482dad31ec1SPeter Hsiang 	return -EINVAL;
1483dad31ec1SPeter Hsiang }
1484dad31ec1SPeter Hsiang 
max98095_put_eq_enum(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1485dad31ec1SPeter Hsiang static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
1486dad31ec1SPeter Hsiang 				 struct snd_ctl_elem_value *ucontrol)
1487dad31ec1SPeter Hsiang {
14882dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
14892dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
1490dad31ec1SPeter Hsiang 	struct max98095_pdata *pdata = max98095->pdata;
1491dad31ec1SPeter Hsiang 	int channel = max98095_get_eq_channel(kcontrol->id.name);
1492dad31ec1SPeter Hsiang 	struct max98095_cdata *cdata;
149358c02138STakashi Iwai 	unsigned int sel = ucontrol->value.enumerated.item[0];
1494dad31ec1SPeter Hsiang 	struct max98095_eq_cfg *coef_set;
1495dad31ec1SPeter Hsiang 	int fs, best, best_val, i;
1496dad31ec1SPeter Hsiang 	int regmask, regsave;
1497dad31ec1SPeter Hsiang 
1498a922cd71STakashi Iwai 	if (WARN_ON(channel > 1))
1499a922cd71STakashi Iwai 		return -EINVAL;
1500dad31ec1SPeter Hsiang 
150153949425STaylor Hutt 	if (!pdata || !max98095->eq_textcnt)
150253949425STaylor Hutt 		return 0;
1503dad31ec1SPeter Hsiang 
1504dad31ec1SPeter Hsiang 	if (sel >= pdata->eq_cfgcnt)
1505dad31ec1SPeter Hsiang 		return -EINVAL;
1506dad31ec1SPeter Hsiang 
150753949425STaylor Hutt 	cdata = &max98095->dai[channel];
1508dad31ec1SPeter Hsiang 	cdata->eq_sel = sel;
1509dad31ec1SPeter Hsiang 	fs = cdata->rate;
1510dad31ec1SPeter Hsiang 
1511dad31ec1SPeter Hsiang 	/* Find the selected configuration with nearest sample rate */
1512dad31ec1SPeter Hsiang 	best = 0;
1513dad31ec1SPeter Hsiang 	best_val = INT_MAX;
1514dad31ec1SPeter Hsiang 	for (i = 0; i < pdata->eq_cfgcnt; i++) {
1515dad31ec1SPeter Hsiang 		if (strcmp(pdata->eq_cfg[i].name, max98095->eq_texts[sel]) == 0 &&
1516dad31ec1SPeter Hsiang 			abs(pdata->eq_cfg[i].rate - fs) < best_val) {
1517dad31ec1SPeter Hsiang 			best = i;
1518dad31ec1SPeter Hsiang 			best_val = abs(pdata->eq_cfg[i].rate - fs);
1519dad31ec1SPeter Hsiang 		}
1520dad31ec1SPeter Hsiang 	}
1521dad31ec1SPeter Hsiang 
15222dd1637fSKuninori Morimoto 	dev_dbg(component->dev, "Selected %s/%dHz for %dHz sample rate\n",
1523dad31ec1SPeter Hsiang 		pdata->eq_cfg[best].name,
1524dad31ec1SPeter Hsiang 		pdata->eq_cfg[best].rate, fs);
1525dad31ec1SPeter Hsiang 
1526dad31ec1SPeter Hsiang 	coef_set = &pdata->eq_cfg[best];
1527dad31ec1SPeter Hsiang 
1528dad31ec1SPeter Hsiang 	regmask = (channel == 0) ? M98095_EQ1EN : M98095_EQ2EN;
1529dad31ec1SPeter Hsiang 
1530dad31ec1SPeter Hsiang 	/* Disable filter while configuring, and save current on/off state */
15311227f601SKuninori Morimoto 	regsave = snd_soc_component_read(component, M98095_088_CFG_LEVEL);
15322dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_088_CFG_LEVEL, regmask, 0);
1533dad31ec1SPeter Hsiang 
1534210a5faeSLars-Peter Clausen 	mutex_lock(&max98095->lock);
15352dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG);
15362dd1637fSKuninori Morimoto 	m98095_eq_band(component, channel, 0, coef_set->band1);
15372dd1637fSKuninori Morimoto 	m98095_eq_band(component, channel, 1, coef_set->band2);
15382dd1637fSKuninori Morimoto 	m98095_eq_band(component, channel, 2, coef_set->band3);
15392dd1637fSKuninori Morimoto 	m98095_eq_band(component, channel, 3, coef_set->band4);
15402dd1637fSKuninori Morimoto 	m98095_eq_band(component, channel, 4, coef_set->band5);
15412dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_00F_HOST_CFG, M98095_SEG, 0);
1542210a5faeSLars-Peter Clausen 	mutex_unlock(&max98095->lock);
1543dad31ec1SPeter Hsiang 
1544dad31ec1SPeter Hsiang 	/* Restore the original on/off state */
15452dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_088_CFG_LEVEL, regmask, regsave);
1546dad31ec1SPeter Hsiang 	return 0;
1547dad31ec1SPeter Hsiang }
1548dad31ec1SPeter Hsiang 
max98095_get_eq_enum(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1549dad31ec1SPeter Hsiang static int max98095_get_eq_enum(struct snd_kcontrol *kcontrol,
1550dad31ec1SPeter Hsiang 				 struct snd_ctl_elem_value *ucontrol)
1551dad31ec1SPeter Hsiang {
15522dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
15532dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
1554dad31ec1SPeter Hsiang 	int channel = max98095_get_eq_channel(kcontrol->id.name);
1555dad31ec1SPeter Hsiang 	struct max98095_cdata *cdata;
1556dad31ec1SPeter Hsiang 
1557dad31ec1SPeter Hsiang 	cdata = &max98095->dai[channel];
1558dad31ec1SPeter Hsiang 	ucontrol->value.enumerated.item[0] = cdata->eq_sel;
1559dad31ec1SPeter Hsiang 
1560dad31ec1SPeter Hsiang 	return 0;
1561dad31ec1SPeter Hsiang }
1562dad31ec1SPeter Hsiang 
max98095_handle_eq_pdata(struct snd_soc_component * component)15632dd1637fSKuninori Morimoto static void max98095_handle_eq_pdata(struct snd_soc_component *component)
1564dad31ec1SPeter Hsiang {
15652dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
1566dad31ec1SPeter Hsiang 	struct max98095_pdata *pdata = max98095->pdata;
1567dad31ec1SPeter Hsiang 	struct max98095_eq_cfg *cfg;
1568dad31ec1SPeter Hsiang 	unsigned int cfgcnt;
1569dad31ec1SPeter Hsiang 	int i, j;
1570dad31ec1SPeter Hsiang 	const char **t;
1571dad31ec1SPeter Hsiang 	int ret;
1572dad31ec1SPeter Hsiang 
1573dad31ec1SPeter Hsiang 	struct snd_kcontrol_new controls[] = {
1574dad31ec1SPeter Hsiang 		SOC_ENUM_EXT("EQ1 Mode",
1575dad31ec1SPeter Hsiang 			max98095->eq_enum,
1576dad31ec1SPeter Hsiang 			max98095_get_eq_enum,
1577dad31ec1SPeter Hsiang 			max98095_put_eq_enum),
1578dad31ec1SPeter Hsiang 		SOC_ENUM_EXT("EQ2 Mode",
1579dad31ec1SPeter Hsiang 			max98095->eq_enum,
1580dad31ec1SPeter Hsiang 			max98095_get_eq_enum,
1581dad31ec1SPeter Hsiang 			max98095_put_eq_enum),
1582dad31ec1SPeter Hsiang 	};
1583dad31ec1SPeter Hsiang 
1584dad31ec1SPeter Hsiang 	cfg = pdata->eq_cfg;
1585dad31ec1SPeter Hsiang 	cfgcnt = pdata->eq_cfgcnt;
1586dad31ec1SPeter Hsiang 
1587dad31ec1SPeter Hsiang 	/* Setup an array of texts for the equalizer enum.
1588dad31ec1SPeter Hsiang 	 * This is based on Mark Brown's equalizer driver code.
1589dad31ec1SPeter Hsiang 	 */
1590dad31ec1SPeter Hsiang 	max98095->eq_textcnt = 0;
1591dad31ec1SPeter Hsiang 	max98095->eq_texts = NULL;
1592dad31ec1SPeter Hsiang 	for (i = 0; i < cfgcnt; i++) {
1593dad31ec1SPeter Hsiang 		for (j = 0; j < max98095->eq_textcnt; j++) {
1594dad31ec1SPeter Hsiang 			if (strcmp(cfg[i].name, max98095->eq_texts[j]) == 0)
1595dad31ec1SPeter Hsiang 				break;
1596dad31ec1SPeter Hsiang 		}
1597dad31ec1SPeter Hsiang 
1598dad31ec1SPeter Hsiang 		if (j != max98095->eq_textcnt)
1599dad31ec1SPeter Hsiang 			continue;
1600dad31ec1SPeter Hsiang 
1601dad31ec1SPeter Hsiang 		/* Expand the array */
1602dad31ec1SPeter Hsiang 		t = krealloc(max98095->eq_texts,
1603dad31ec1SPeter Hsiang 			     sizeof(char *) * (max98095->eq_textcnt + 1),
1604dad31ec1SPeter Hsiang 			     GFP_KERNEL);
1605dad31ec1SPeter Hsiang 		if (t == NULL)
1606dad31ec1SPeter Hsiang 			continue;
1607dad31ec1SPeter Hsiang 
1608dad31ec1SPeter Hsiang 		/* Store the new entry */
1609dad31ec1SPeter Hsiang 		t[max98095->eq_textcnt] = cfg[i].name;
1610dad31ec1SPeter Hsiang 		max98095->eq_textcnt++;
1611dad31ec1SPeter Hsiang 		max98095->eq_texts = t;
1612dad31ec1SPeter Hsiang 	}
1613dad31ec1SPeter Hsiang 
1614dad31ec1SPeter Hsiang 	/* Now point the soc_enum to .texts array items */
1615dad31ec1SPeter Hsiang 	max98095->eq_enum.texts = max98095->eq_texts;
16169a8d38dbSTakashi Iwai 	max98095->eq_enum.items = max98095->eq_textcnt;
1617dad31ec1SPeter Hsiang 
16182dd1637fSKuninori Morimoto 	ret = snd_soc_add_component_controls(component, controls, ARRAY_SIZE(controls));
1619dad31ec1SPeter Hsiang 	if (ret != 0)
16202dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failed to add EQ control: %d\n", ret);
1621dad31ec1SPeter Hsiang }
1622dad31ec1SPeter Hsiang 
1623c855a1a7SRyan Mallon static const char *bq_mode_name[] = {"Biquad1 Mode", "Biquad2 Mode"};
1624c855a1a7SRyan Mallon 
max98095_get_bq_channel(struct snd_soc_component * component,const char * name)16252dd1637fSKuninori Morimoto static int max98095_get_bq_channel(struct snd_soc_component *component,
1626c855a1a7SRyan Mallon 				   const char *name)
1627dad31ec1SPeter Hsiang {
16281567062fSXie Yisheng 	int ret;
1629c855a1a7SRyan Mallon 
16301567062fSXie Yisheng 	ret = match_string(bq_mode_name, ARRAY_SIZE(bq_mode_name), name);
16311567062fSXie Yisheng 	if (ret < 0)
16322dd1637fSKuninori Morimoto 		dev_err(component->dev, "Bad biquad channel name '%s'\n", name);
16331567062fSXie Yisheng 	return ret;
1634dad31ec1SPeter Hsiang }
1635dad31ec1SPeter Hsiang 
max98095_put_bq_enum(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1636dad31ec1SPeter Hsiang static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
1637dad31ec1SPeter Hsiang 				 struct snd_ctl_elem_value *ucontrol)
1638dad31ec1SPeter Hsiang {
16392dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
16402dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
1641dad31ec1SPeter Hsiang 	struct max98095_pdata *pdata = max98095->pdata;
16422dd1637fSKuninori Morimoto 	int channel = max98095_get_bq_channel(component, kcontrol->id.name);
1643dad31ec1SPeter Hsiang 	struct max98095_cdata *cdata;
164458c02138STakashi Iwai 	unsigned int sel = ucontrol->value.enumerated.item[0];
1645dad31ec1SPeter Hsiang 	struct max98095_biquad_cfg *coef_set;
1646dad31ec1SPeter Hsiang 	int fs, best, best_val, i;
1647dad31ec1SPeter Hsiang 	int regmask, regsave;
1648dad31ec1SPeter Hsiang 
1649c855a1a7SRyan Mallon 	if (channel < 0)
1650c855a1a7SRyan Mallon 		return channel;
1651dad31ec1SPeter Hsiang 
165253949425STaylor Hutt 	if (!pdata || !max98095->bq_textcnt)
165353949425STaylor Hutt 		return 0;
1654dad31ec1SPeter Hsiang 
1655dad31ec1SPeter Hsiang 	if (sel >= pdata->bq_cfgcnt)
1656dad31ec1SPeter Hsiang 		return -EINVAL;
1657dad31ec1SPeter Hsiang 
165853949425STaylor Hutt 	cdata = &max98095->dai[channel];
1659dad31ec1SPeter Hsiang 	cdata->bq_sel = sel;
1660dad31ec1SPeter Hsiang 	fs = cdata->rate;
1661dad31ec1SPeter Hsiang 
1662dad31ec1SPeter Hsiang 	/* Find the selected configuration with nearest sample rate */
1663dad31ec1SPeter Hsiang 	best = 0;
1664dad31ec1SPeter Hsiang 	best_val = INT_MAX;
1665dad31ec1SPeter Hsiang 	for (i = 0; i < pdata->bq_cfgcnt; i++) {
1666dad31ec1SPeter Hsiang 		if (strcmp(pdata->bq_cfg[i].name, max98095->bq_texts[sel]) == 0 &&
1667dad31ec1SPeter Hsiang 			abs(pdata->bq_cfg[i].rate - fs) < best_val) {
1668dad31ec1SPeter Hsiang 			best = i;
1669dad31ec1SPeter Hsiang 			best_val = abs(pdata->bq_cfg[i].rate - fs);
1670dad31ec1SPeter Hsiang 		}
1671dad31ec1SPeter Hsiang 	}
1672dad31ec1SPeter Hsiang 
16732dd1637fSKuninori Morimoto 	dev_dbg(component->dev, "Selected %s/%dHz for %dHz sample rate\n",
1674dad31ec1SPeter Hsiang 		pdata->bq_cfg[best].name,
1675dad31ec1SPeter Hsiang 		pdata->bq_cfg[best].rate, fs);
1676dad31ec1SPeter Hsiang 
1677dad31ec1SPeter Hsiang 	coef_set = &pdata->bq_cfg[best];
1678dad31ec1SPeter Hsiang 
1679dad31ec1SPeter Hsiang 	regmask = (channel == 0) ? M98095_BQ1EN : M98095_BQ2EN;
1680dad31ec1SPeter Hsiang 
1681dad31ec1SPeter Hsiang 	/* Disable filter while configuring, and save current on/off state */
16821227f601SKuninori Morimoto 	regsave = snd_soc_component_read(component, M98095_088_CFG_LEVEL);
16832dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_088_CFG_LEVEL, regmask, 0);
1684dad31ec1SPeter Hsiang 
1685210a5faeSLars-Peter Clausen 	mutex_lock(&max98095->lock);
16862dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG);
16872dd1637fSKuninori Morimoto 	m98095_biquad_band(component, channel, 0, coef_set->band1);
16882dd1637fSKuninori Morimoto 	m98095_biquad_band(component, channel, 1, coef_set->band2);
16892dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_00F_HOST_CFG, M98095_SEG, 0);
1690210a5faeSLars-Peter Clausen 	mutex_unlock(&max98095->lock);
1691dad31ec1SPeter Hsiang 
1692dad31ec1SPeter Hsiang 	/* Restore the original on/off state */
16932dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_088_CFG_LEVEL, regmask, regsave);
1694dad31ec1SPeter Hsiang 	return 0;
1695dad31ec1SPeter Hsiang }
1696dad31ec1SPeter Hsiang 
max98095_get_bq_enum(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1697dad31ec1SPeter Hsiang static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol,
1698dad31ec1SPeter Hsiang 				 struct snd_ctl_elem_value *ucontrol)
1699dad31ec1SPeter Hsiang {
17002dd1637fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
17012dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
17022dd1637fSKuninori Morimoto 	int channel = max98095_get_bq_channel(component, kcontrol->id.name);
1703dad31ec1SPeter Hsiang 	struct max98095_cdata *cdata;
1704dad31ec1SPeter Hsiang 
1705c855a1a7SRyan Mallon 	if (channel < 0)
1706c855a1a7SRyan Mallon 		return channel;
1707c855a1a7SRyan Mallon 
1708dad31ec1SPeter Hsiang 	cdata = &max98095->dai[channel];
1709dad31ec1SPeter Hsiang 	ucontrol->value.enumerated.item[0] = cdata->bq_sel;
1710dad31ec1SPeter Hsiang 
1711dad31ec1SPeter Hsiang 	return 0;
1712dad31ec1SPeter Hsiang }
1713dad31ec1SPeter Hsiang 
max98095_handle_bq_pdata(struct snd_soc_component * component)17142dd1637fSKuninori Morimoto static void max98095_handle_bq_pdata(struct snd_soc_component *component)
1715dad31ec1SPeter Hsiang {
17162dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
1717dad31ec1SPeter Hsiang 	struct max98095_pdata *pdata = max98095->pdata;
1718dad31ec1SPeter Hsiang 	struct max98095_biquad_cfg *cfg;
1719dad31ec1SPeter Hsiang 	unsigned int cfgcnt;
1720dad31ec1SPeter Hsiang 	int i, j;
1721dad31ec1SPeter Hsiang 	const char **t;
1722dad31ec1SPeter Hsiang 	int ret;
1723dad31ec1SPeter Hsiang 
1724dad31ec1SPeter Hsiang 	struct snd_kcontrol_new controls[] = {
1725c855a1a7SRyan Mallon 		SOC_ENUM_EXT((char *)bq_mode_name[0],
1726dad31ec1SPeter Hsiang 			max98095->bq_enum,
1727dad31ec1SPeter Hsiang 			max98095_get_bq_enum,
1728dad31ec1SPeter Hsiang 			max98095_put_bq_enum),
1729c855a1a7SRyan Mallon 		SOC_ENUM_EXT((char *)bq_mode_name[1],
1730dad31ec1SPeter Hsiang 			max98095->bq_enum,
1731dad31ec1SPeter Hsiang 			max98095_get_bq_enum,
1732dad31ec1SPeter Hsiang 			max98095_put_bq_enum),
1733dad31ec1SPeter Hsiang 	};
1734c855a1a7SRyan Mallon 	BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(bq_mode_name));
1735dad31ec1SPeter Hsiang 
1736dad31ec1SPeter Hsiang 	cfg = pdata->bq_cfg;
1737dad31ec1SPeter Hsiang 	cfgcnt = pdata->bq_cfgcnt;
1738dad31ec1SPeter Hsiang 
1739dad31ec1SPeter Hsiang 	/* Setup an array of texts for the biquad enum.
1740dad31ec1SPeter Hsiang 	 * This is based on Mark Brown's equalizer driver code.
1741dad31ec1SPeter Hsiang 	 */
1742dad31ec1SPeter Hsiang 	max98095->bq_textcnt = 0;
1743dad31ec1SPeter Hsiang 	max98095->bq_texts = NULL;
1744dad31ec1SPeter Hsiang 	for (i = 0; i < cfgcnt; i++) {
1745dad31ec1SPeter Hsiang 		for (j = 0; j < max98095->bq_textcnt; j++) {
1746dad31ec1SPeter Hsiang 			if (strcmp(cfg[i].name, max98095->bq_texts[j]) == 0)
1747dad31ec1SPeter Hsiang 				break;
1748dad31ec1SPeter Hsiang 		}
1749dad31ec1SPeter Hsiang 
1750dad31ec1SPeter Hsiang 		if (j != max98095->bq_textcnt)
1751dad31ec1SPeter Hsiang 			continue;
1752dad31ec1SPeter Hsiang 
1753dad31ec1SPeter Hsiang 		/* Expand the array */
1754dad31ec1SPeter Hsiang 		t = krealloc(max98095->bq_texts,
1755dad31ec1SPeter Hsiang 			     sizeof(char *) * (max98095->bq_textcnt + 1),
1756dad31ec1SPeter Hsiang 			     GFP_KERNEL);
1757dad31ec1SPeter Hsiang 		if (t == NULL)
1758dad31ec1SPeter Hsiang 			continue;
1759dad31ec1SPeter Hsiang 
1760dad31ec1SPeter Hsiang 		/* Store the new entry */
1761dad31ec1SPeter Hsiang 		t[max98095->bq_textcnt] = cfg[i].name;
1762dad31ec1SPeter Hsiang 		max98095->bq_textcnt++;
1763dad31ec1SPeter Hsiang 		max98095->bq_texts = t;
1764dad31ec1SPeter Hsiang 	}
1765dad31ec1SPeter Hsiang 
1766dad31ec1SPeter Hsiang 	/* Now point the soc_enum to .texts array items */
1767dad31ec1SPeter Hsiang 	max98095->bq_enum.texts = max98095->bq_texts;
17689a8d38dbSTakashi Iwai 	max98095->bq_enum.items = max98095->bq_textcnt;
1769dad31ec1SPeter Hsiang 
17702dd1637fSKuninori Morimoto 	ret = snd_soc_add_component_controls(component, controls, ARRAY_SIZE(controls));
1771dad31ec1SPeter Hsiang 	if (ret != 0)
17722dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failed to add Biquad control: %d\n", ret);
1773dad31ec1SPeter Hsiang }
1774dad31ec1SPeter Hsiang 
max98095_handle_pdata(struct snd_soc_component * component)17752dd1637fSKuninori Morimoto static void max98095_handle_pdata(struct snd_soc_component *component)
177682a5a936SPeter Hsiang {
17772dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
177882a5a936SPeter Hsiang 	struct max98095_pdata *pdata = max98095->pdata;
177982a5a936SPeter Hsiang 	u8 regval = 0;
178082a5a936SPeter Hsiang 
178182a5a936SPeter Hsiang 	if (!pdata) {
17822dd1637fSKuninori Morimoto 		dev_dbg(component->dev, "No platform data\n");
178382a5a936SPeter Hsiang 		return;
178482a5a936SPeter Hsiang 	}
178582a5a936SPeter Hsiang 
178682a5a936SPeter Hsiang 	/* Configure mic for analog/digital mic mode */
178782a5a936SPeter Hsiang 	if (pdata->digmic_left_mode)
178882a5a936SPeter Hsiang 		regval |= M98095_DIGMIC_L;
178982a5a936SPeter Hsiang 
179082a5a936SPeter Hsiang 	if (pdata->digmic_right_mode)
179182a5a936SPeter Hsiang 		regval |= M98095_DIGMIC_R;
179282a5a936SPeter Hsiang 
17932dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_087_CFG_MIC, regval);
1794dad31ec1SPeter Hsiang 
1795dad31ec1SPeter Hsiang 	/* Configure equalizers */
1796dad31ec1SPeter Hsiang 	if (pdata->eq_cfgcnt)
17972dd1637fSKuninori Morimoto 		max98095_handle_eq_pdata(component);
1798dad31ec1SPeter Hsiang 
1799dad31ec1SPeter Hsiang 	/* Configure bi-quad filters */
1800dad31ec1SPeter Hsiang 	if (pdata->bq_cfgcnt)
18012dd1637fSKuninori Morimoto 		max98095_handle_bq_pdata(component);
180282a5a936SPeter Hsiang }
180382a5a936SPeter Hsiang 
max98095_report_jack(int irq,void * data)18049dd90c5dSRhyland Klein static irqreturn_t max98095_report_jack(int irq, void *data)
18059dd90c5dSRhyland Klein {
18062dd1637fSKuninori Morimoto 	struct snd_soc_component *component = data;
18072dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
18089dd90c5dSRhyland Klein 	unsigned int value;
18099dd90c5dSRhyland Klein 	int hp_report = 0;
18109dd90c5dSRhyland Klein 	int mic_report = 0;
18119dd90c5dSRhyland Klein 
18129dd90c5dSRhyland Klein 	/* Read the Jack Status Register */
18131227f601SKuninori Morimoto 	value = snd_soc_component_read(component, M98095_007_JACK_AUTO_STS);
18149dd90c5dSRhyland Klein 
18159dd90c5dSRhyland Klein 	/* If ddone is not set, then detection isn't finished yet */
18169dd90c5dSRhyland Klein 	if ((value & M98095_DDONE) == 0)
18179dd90c5dSRhyland Klein 		return IRQ_NONE;
18189dd90c5dSRhyland Klein 
18199dd90c5dSRhyland Klein 	/* if hp, check its bit, and if set, clear it */
18209dd90c5dSRhyland Klein 	if ((value & M98095_HP_IN || value & M98095_LO_IN) &&
18219dd90c5dSRhyland Klein 		max98095->headphone_jack)
18229dd90c5dSRhyland Klein 		hp_report |= SND_JACK_HEADPHONE;
18239dd90c5dSRhyland Klein 
18249dd90c5dSRhyland Klein 	/* if mic, check its bit, and if set, clear it */
18259dd90c5dSRhyland Klein 	if ((value & M98095_MIC_IN) && max98095->mic_jack)
18269dd90c5dSRhyland Klein 		mic_report |= SND_JACK_MICROPHONE;
18279dd90c5dSRhyland Klein 
18289dd90c5dSRhyland Klein 	if (max98095->headphone_jack == max98095->mic_jack) {
18299dd90c5dSRhyland Klein 		snd_soc_jack_report(max98095->headphone_jack,
18309dd90c5dSRhyland Klein 					hp_report | mic_report,
18319dd90c5dSRhyland Klein 					SND_JACK_HEADSET);
18329dd90c5dSRhyland Klein 	} else {
18339dd90c5dSRhyland Klein 		if (max98095->headphone_jack)
18349dd90c5dSRhyland Klein 			snd_soc_jack_report(max98095->headphone_jack,
18359dd90c5dSRhyland Klein 					hp_report, SND_JACK_HEADPHONE);
18369dd90c5dSRhyland Klein 		if (max98095->mic_jack)
18379dd90c5dSRhyland Klein 			snd_soc_jack_report(max98095->mic_jack,
18389dd90c5dSRhyland Klein 					mic_report, SND_JACK_MICROPHONE);
18399dd90c5dSRhyland Klein 	}
18409dd90c5dSRhyland Klein 
18419dd90c5dSRhyland Klein 	return IRQ_HANDLED;
18429dd90c5dSRhyland Klein }
18439dd90c5dSRhyland Klein 
max98095_jack_detect_enable(struct snd_soc_component * component)18442dd1637fSKuninori Morimoto static int max98095_jack_detect_enable(struct snd_soc_component *component)
18459dd90c5dSRhyland Klein {
18462dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
18479dd90c5dSRhyland Klein 	int ret = 0;
18489dd90c5dSRhyland Klein 	int detect_enable = M98095_JDEN;
18499dd90c5dSRhyland Klein 	unsigned int slew = M98095_DEFAULT_SLEW_DELAY;
18509dd90c5dSRhyland Klein 
18519dd90c5dSRhyland Klein 	if (max98095->pdata->jack_detect_pin5en)
18529dd90c5dSRhyland Klein 		detect_enable |= M98095_PIN5EN;
18539dd90c5dSRhyland Klein 
18540841b04aSMark Brown 	if (max98095->pdata->jack_detect_delay)
18550841b04aSMark Brown 		slew = max98095->pdata->jack_detect_delay;
18569dd90c5dSRhyland Klein 
18572dd1637fSKuninori Morimoto 	ret = snd_soc_component_write(component, M98095_08E_JACK_DC_SLEW, slew);
18589dd90c5dSRhyland Klein 	if (ret < 0) {
18592dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failed to cfg auto detect %d\n", ret);
18609dd90c5dSRhyland Klein 		return ret;
18619dd90c5dSRhyland Klein 	}
18629dd90c5dSRhyland Klein 
18639dd90c5dSRhyland Klein 	/* configure auto detection to be enabled */
18642dd1637fSKuninori Morimoto 	ret = snd_soc_component_write(component, M98095_089_JACK_DET_AUTO, detect_enable);
18659dd90c5dSRhyland Klein 	if (ret < 0) {
18662dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failed to cfg auto detect %d\n", ret);
18679dd90c5dSRhyland Klein 		return ret;
18689dd90c5dSRhyland Klein 	}
18699dd90c5dSRhyland Klein 
18709dd90c5dSRhyland Klein 	return ret;
18719dd90c5dSRhyland Klein }
18729dd90c5dSRhyland Klein 
max98095_jack_detect_disable(struct snd_soc_component * component)18732dd1637fSKuninori Morimoto static int max98095_jack_detect_disable(struct snd_soc_component *component)
18749dd90c5dSRhyland Klein {
18759dd90c5dSRhyland Klein 	int ret = 0;
18769dd90c5dSRhyland Klein 
18779dd90c5dSRhyland Klein 	/* configure auto detection to be disabled */
18782dd1637fSKuninori Morimoto 	ret = snd_soc_component_write(component, M98095_089_JACK_DET_AUTO, 0x0);
18799dd90c5dSRhyland Klein 	if (ret < 0) {
18802dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failed to cfg auto detect %d\n", ret);
18819dd90c5dSRhyland Klein 		return ret;
18829dd90c5dSRhyland Klein 	}
18839dd90c5dSRhyland Klein 
18849dd90c5dSRhyland Klein 	return ret;
18859dd90c5dSRhyland Klein }
18869dd90c5dSRhyland Klein 
max98095_jack_detect(struct snd_soc_component * component,struct snd_soc_jack * hp_jack,struct snd_soc_jack * mic_jack)18872dd1637fSKuninori Morimoto int max98095_jack_detect(struct snd_soc_component *component,
18889dd90c5dSRhyland Klein 	struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack)
18899dd90c5dSRhyland Klein {
18902dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
18912dd1637fSKuninori Morimoto 	struct i2c_client *client = to_i2c_client(component->dev);
18929dd90c5dSRhyland Klein 	int ret = 0;
18939dd90c5dSRhyland Klein 
18949dd90c5dSRhyland Klein 	max98095->headphone_jack = hp_jack;
18959dd90c5dSRhyland Klein 	max98095->mic_jack = mic_jack;
18969dd90c5dSRhyland Klein 
18979dd90c5dSRhyland Klein 	/* only progress if we have at least 1 jack pointer */
18989dd90c5dSRhyland Klein 	if (!hp_jack && !mic_jack)
18999dd90c5dSRhyland Klein 		return -EINVAL;
19009dd90c5dSRhyland Klein 
19012dd1637fSKuninori Morimoto 	max98095_jack_detect_enable(component);
19029dd90c5dSRhyland Klein 
19039dd90c5dSRhyland Klein 	/* enable interrupts for headphone jack detection */
19042dd1637fSKuninori Morimoto 	ret = snd_soc_component_update_bits(component, M98095_013_JACK_INT_EN,
19059dd90c5dSRhyland Klein 		M98095_IDDONE, M98095_IDDONE);
19069dd90c5dSRhyland Klein 	if (ret < 0) {
19072dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failed to cfg jack irqs %d\n", ret);
19089dd90c5dSRhyland Klein 		return ret;
19099dd90c5dSRhyland Klein 	}
19109dd90c5dSRhyland Klein 
19112dd1637fSKuninori Morimoto 	max98095_report_jack(client->irq, component);
19129dd90c5dSRhyland Klein 	return 0;
19139dd90c5dSRhyland Klein }
1914a265367cSMark Brown EXPORT_SYMBOL_GPL(max98095_jack_detect);
19159dd90c5dSRhyland Klein 
191682a5a936SPeter Hsiang #ifdef CONFIG_PM
max98095_suspend(struct snd_soc_component * component)19172dd1637fSKuninori Morimoto static int max98095_suspend(struct snd_soc_component *component)
191882a5a936SPeter Hsiang {
19192dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
19209dd90c5dSRhyland Klein 
19219dd90c5dSRhyland Klein 	if (max98095->headphone_jack || max98095->mic_jack)
19222dd1637fSKuninori Morimoto 		max98095_jack_detect_disable(component);
19239dd90c5dSRhyland Klein 
19242dd1637fSKuninori Morimoto 	snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
192582a5a936SPeter Hsiang 
192682a5a936SPeter Hsiang 	return 0;
192782a5a936SPeter Hsiang }
192882a5a936SPeter Hsiang 
max98095_resume(struct snd_soc_component * component)19292dd1637fSKuninori Morimoto static int max98095_resume(struct snd_soc_component *component)
193082a5a936SPeter Hsiang {
19312dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
19322dd1637fSKuninori Morimoto 	struct i2c_client *client = to_i2c_client(component->dev);
19339dd90c5dSRhyland Klein 
19342dd1637fSKuninori Morimoto 	snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
193582a5a936SPeter Hsiang 
19369dd90c5dSRhyland Klein 	if (max98095->headphone_jack || max98095->mic_jack) {
19372dd1637fSKuninori Morimoto 		max98095_jack_detect_enable(component);
19382dd1637fSKuninori Morimoto 		max98095_report_jack(client->irq, component);
19399dd90c5dSRhyland Klein 	}
19409dd90c5dSRhyland Klein 
194182a5a936SPeter Hsiang 	return 0;
194282a5a936SPeter Hsiang }
194382a5a936SPeter Hsiang #else
194482a5a936SPeter Hsiang #define max98095_suspend NULL
194582a5a936SPeter Hsiang #define max98095_resume NULL
194682a5a936SPeter Hsiang #endif
194782a5a936SPeter Hsiang 
max98095_reset(struct snd_soc_component * component)19482dd1637fSKuninori Morimoto static int max98095_reset(struct snd_soc_component *component)
194982a5a936SPeter Hsiang {
195082a5a936SPeter Hsiang 	int i, ret;
195182a5a936SPeter Hsiang 
195282a5a936SPeter Hsiang 	/* Gracefully reset the DSP core and the codec hardware
195382a5a936SPeter Hsiang 	 * in a proper sequence */
19542dd1637fSKuninori Morimoto 	ret = snd_soc_component_write(component, M98095_00F_HOST_CFG, 0);
195582a5a936SPeter Hsiang 	if (ret < 0) {
19562dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failed to reset DSP: %d\n", ret);
195782a5a936SPeter Hsiang 		return ret;
195882a5a936SPeter Hsiang 	}
195982a5a936SPeter Hsiang 
19602dd1637fSKuninori Morimoto 	ret = snd_soc_component_write(component, M98095_097_PWR_SYS, 0);
196182a5a936SPeter Hsiang 	if (ret < 0) {
19622dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failed to reset component: %d\n", ret);
196382a5a936SPeter Hsiang 		return ret;
196482a5a936SPeter Hsiang 	}
196582a5a936SPeter Hsiang 
196682a5a936SPeter Hsiang 	/* Reset to hardware default for registers, as there is not
196782a5a936SPeter Hsiang 	 * a soft reset hardware control register */
196882a5a936SPeter Hsiang 	for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) {
19691227f601SKuninori Morimoto 		ret = snd_soc_component_write(component, i, snd_soc_component_read(component, i));
197082a5a936SPeter Hsiang 		if (ret < 0) {
19712dd1637fSKuninori Morimoto 			dev_err(component->dev, "Failed to reset: %d\n", ret);
197282a5a936SPeter Hsiang 			return ret;
197382a5a936SPeter Hsiang 		}
197482a5a936SPeter Hsiang 	}
197582a5a936SPeter Hsiang 
197682a5a936SPeter Hsiang 	return ret;
197782a5a936SPeter Hsiang }
197882a5a936SPeter Hsiang 
max98095_probe(struct snd_soc_component * component)19792dd1637fSKuninori Morimoto static int max98095_probe(struct snd_soc_component *component)
198082a5a936SPeter Hsiang {
19812dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
198282a5a936SPeter Hsiang 	struct max98095_cdata *cdata;
19839dd90c5dSRhyland Klein 	struct i2c_client *client;
198482a5a936SPeter Hsiang 	int ret = 0;
198582a5a936SPeter Hsiang 
19862dd1637fSKuninori Morimoto 	max98095->mclk = devm_clk_get(component->dev, "mclk");
1987e3048c3dSTushar Behera 	if (PTR_ERR(max98095->mclk) == -EPROBE_DEFER)
1988e3048c3dSTushar Behera 		return -EPROBE_DEFER;
1989e3048c3dSTushar Behera 
199082a5a936SPeter Hsiang 	/* reset the codec, the DSP core, and disable all interrupts */
19912dd1637fSKuninori Morimoto 	max98095_reset(component);
199282a5a936SPeter Hsiang 
19932dd1637fSKuninori Morimoto 	client = to_i2c_client(component->dev);
19949dd90c5dSRhyland Klein 
199582a5a936SPeter Hsiang 	/* initialize private data */
199682a5a936SPeter Hsiang 
199782a5a936SPeter Hsiang 	max98095->sysclk = (unsigned)-1;
1998dad31ec1SPeter Hsiang 	max98095->eq_textcnt = 0;
1999dad31ec1SPeter Hsiang 	max98095->bq_textcnt = 0;
200082a5a936SPeter Hsiang 
200182a5a936SPeter Hsiang 	cdata = &max98095->dai[0];
200282a5a936SPeter Hsiang 	cdata->rate = (unsigned)-1;
200382a5a936SPeter Hsiang 	cdata->fmt  = (unsigned)-1;
2004dad31ec1SPeter Hsiang 	cdata->eq_sel = 0;
2005dad31ec1SPeter Hsiang 	cdata->bq_sel = 0;
200682a5a936SPeter Hsiang 
200782a5a936SPeter Hsiang 	cdata = &max98095->dai[1];
200882a5a936SPeter Hsiang 	cdata->rate = (unsigned)-1;
200982a5a936SPeter Hsiang 	cdata->fmt  = (unsigned)-1;
2010dad31ec1SPeter Hsiang 	cdata->eq_sel = 0;
2011dad31ec1SPeter Hsiang 	cdata->bq_sel = 0;
201282a5a936SPeter Hsiang 
201382a5a936SPeter Hsiang 	cdata = &max98095->dai[2];
201482a5a936SPeter Hsiang 	cdata->rate = (unsigned)-1;
201582a5a936SPeter Hsiang 	cdata->fmt  = (unsigned)-1;
2016dad31ec1SPeter Hsiang 	cdata->eq_sel = 0;
2017dad31ec1SPeter Hsiang 	cdata->bq_sel = 0;
201882a5a936SPeter Hsiang 
201982a5a936SPeter Hsiang 	max98095->lin_state = 0;
202082a5a936SPeter Hsiang 	max98095->mic1pre = 0;
202182a5a936SPeter Hsiang 	max98095->mic2pre = 0;
202282a5a936SPeter Hsiang 
20239dd90c5dSRhyland Klein 	if (client->irq) {
20249dd90c5dSRhyland Klein 		/* register an audio interrupt */
20259dd90c5dSRhyland Klein 		ret = request_threaded_irq(client->irq, NULL,
20269dd90c5dSRhyland Klein 			max98095_report_jack,
202716f0acd0SFabio Estevam 			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
20282dd1637fSKuninori Morimoto 			IRQF_ONESHOT, "max98095", component);
20299dd90c5dSRhyland Klein 		if (ret) {
20302dd1637fSKuninori Morimoto 			dev_err(component->dev, "Failed to request IRQ: %d\n", ret);
20319dd90c5dSRhyland Klein 			goto err_access;
20329dd90c5dSRhyland Klein 		}
20339dd90c5dSRhyland Klein 	}
20349dd90c5dSRhyland Klein 
20351227f601SKuninori Morimoto 	ret = snd_soc_component_read(component, M98095_0FF_REV_ID);
203682a5a936SPeter Hsiang 	if (ret < 0) {
20372dd1637fSKuninori Morimoto 		dev_err(component->dev, "Failure reading hardware revision: %d\n",
203882a5a936SPeter Hsiang 			ret);
20399dd90c5dSRhyland Klein 		goto err_irq;
204082a5a936SPeter Hsiang 	}
20412dd1637fSKuninori Morimoto 	dev_info(component->dev, "Hardware revision: %c\n", ret - 0x40 + 'A');
204282a5a936SPeter Hsiang 
20432dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_097_PWR_SYS, M98095_PWRSV);
204482a5a936SPeter Hsiang 
20452dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_048_MIX_DAC_LR,
204682a5a936SPeter Hsiang 		M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR);
204782a5a936SPeter Hsiang 
20482dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_049_MIX_DAC_M,
204982a5a936SPeter Hsiang 		M98095_DAI2M_TO_DACM|M98095_DAI3M_TO_DACM);
205082a5a936SPeter Hsiang 
20512dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_092_PWR_EN_OUT, M98095_SPK_SPREADSPECTRUM);
20522dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_045_CFG_DSP, M98095_DSPNORMAL);
20532dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_04E_CFG_HP, M98095_HPNORMAL);
205482a5a936SPeter Hsiang 
20552dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_02C_DAI1_IOCFG,
205682a5a936SPeter Hsiang 		M98095_S1NORMAL|M98095_SDATA);
205782a5a936SPeter Hsiang 
20582dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_036_DAI2_IOCFG,
205982a5a936SPeter Hsiang 		M98095_S2NORMAL|M98095_SDATA);
206082a5a936SPeter Hsiang 
20612dd1637fSKuninori Morimoto 	snd_soc_component_write(component, M98095_040_DAI3_IOCFG,
206282a5a936SPeter Hsiang 		M98095_S3NORMAL|M98095_SDATA);
206382a5a936SPeter Hsiang 
20642dd1637fSKuninori Morimoto 	max98095_handle_pdata(component);
206582a5a936SPeter Hsiang 
206682a5a936SPeter Hsiang 	/* take the codec out of the shut down */
20672dd1637fSKuninori Morimoto 	snd_soc_component_update_bits(component, M98095_097_PWR_SYS, M98095_SHDNRUN,
206882a5a936SPeter Hsiang 		M98095_SHDNRUN);
206982a5a936SPeter Hsiang 
20709dd90c5dSRhyland Klein 	return 0;
20719dd90c5dSRhyland Klein 
20729dd90c5dSRhyland Klein err_irq:
20739dd90c5dSRhyland Klein 	if (client->irq)
20742dd1637fSKuninori Morimoto 		free_irq(client->irq, component);
207582a5a936SPeter Hsiang err_access:
207682a5a936SPeter Hsiang 	return ret;
207782a5a936SPeter Hsiang }
207882a5a936SPeter Hsiang 
max98095_remove(struct snd_soc_component * component)20792dd1637fSKuninori Morimoto static void max98095_remove(struct snd_soc_component *component)
208082a5a936SPeter Hsiang {
20812dd1637fSKuninori Morimoto 	struct max98095_priv *max98095 = snd_soc_component_get_drvdata(component);
20822dd1637fSKuninori Morimoto 	struct i2c_client *client = to_i2c_client(component->dev);
20839dd90c5dSRhyland Klein 
20849dd90c5dSRhyland Klein 	if (max98095->headphone_jack || max98095->mic_jack)
20852dd1637fSKuninori Morimoto 		max98095_jack_detect_disable(component);
20869dd90c5dSRhyland Klein 
20879dd90c5dSRhyland Klein 	if (client->irq)
20882dd1637fSKuninori Morimoto 		free_irq(client->irq, component);
208982a5a936SPeter Hsiang }
209082a5a936SPeter Hsiang 
20912dd1637fSKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_max98095 = {
209282a5a936SPeter Hsiang 	.probe			= max98095_probe,
209382a5a936SPeter Hsiang 	.remove			= max98095_remove,
209482a5a936SPeter Hsiang 	.suspend		= max98095_suspend,
209582a5a936SPeter Hsiang 	.resume			= max98095_resume,
209682a5a936SPeter Hsiang 	.set_bias_level		= max98095_set_bias_level,
2097c6b3283fSMark Brown 	.controls		= max98095_snd_controls,
2098c6b3283fSMark Brown 	.num_controls		= ARRAY_SIZE(max98095_snd_controls),
209982a5a936SPeter Hsiang 	.dapm_widgets		= max98095_dapm_widgets,
210082a5a936SPeter Hsiang 	.num_dapm_widgets	= ARRAY_SIZE(max98095_dapm_widgets),
210182a5a936SPeter Hsiang 	.dapm_routes		= max98095_audio_map,
210282a5a936SPeter Hsiang 	.num_dapm_routes	= ARRAY_SIZE(max98095_audio_map),
21032dd1637fSKuninori Morimoto 	.idle_bias_on		= 1,
21042dd1637fSKuninori Morimoto 	.use_pmdown_time	= 1,
21052dd1637fSKuninori Morimoto 	.endianness		= 1,
210682a5a936SPeter Hsiang };
210782a5a936SPeter Hsiang 
21084ac8ebb6SStephen Kitt static const struct i2c_device_id max98095_i2c_id[] = {
21094ac8ebb6SStephen Kitt 	{ "max98095", MAX98095 },
21104ac8ebb6SStephen Kitt 	{ }
21114ac8ebb6SStephen Kitt };
21124ac8ebb6SStephen Kitt MODULE_DEVICE_TABLE(i2c, max98095_i2c_id);
21134ac8ebb6SStephen Kitt 
max98095_i2c_probe(struct i2c_client * i2c)21144ac8ebb6SStephen Kitt static int max98095_i2c_probe(struct i2c_client *i2c)
211582a5a936SPeter Hsiang {
211682a5a936SPeter Hsiang 	struct max98095_priv *max98095;
211782a5a936SPeter Hsiang 	int ret;
21184ac8ebb6SStephen Kitt 	const struct i2c_device_id *id;
211982a5a936SPeter Hsiang 
2120b1b54882SAxel Lin 	max98095 = devm_kzalloc(&i2c->dev, sizeof(struct max98095_priv),
2121b1b54882SAxel Lin 				GFP_KERNEL);
212282a5a936SPeter Hsiang 	if (max98095 == NULL)
212382a5a936SPeter Hsiang 		return -ENOMEM;
212482a5a936SPeter Hsiang 
2125210a5faeSLars-Peter Clausen 	mutex_init(&max98095->lock);
2126210a5faeSLars-Peter Clausen 
212714acbbbbSMark Brown 	max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap);
212814acbbbbSMark Brown 	if (IS_ERR(max98095->regmap)) {
212914acbbbbSMark Brown 		ret = PTR_ERR(max98095->regmap);
213014acbbbbSMark Brown 		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
213114acbbbbSMark Brown 		return ret;
213214acbbbbSMark Brown 	}
213314acbbbbSMark Brown 
21344ac8ebb6SStephen Kitt 	id = i2c_match_id(max98095_i2c_id, i2c);
213582a5a936SPeter Hsiang 	max98095->devtype = id->driver_data;
213682a5a936SPeter Hsiang 	i2c_set_clientdata(i2c, max98095);
213782a5a936SPeter Hsiang 	max98095->pdata = i2c->dev.platform_data;
213882a5a936SPeter Hsiang 
21392dd1637fSKuninori Morimoto 	ret = devm_snd_soc_register_component(&i2c->dev,
21402dd1637fSKuninori Morimoto 				     &soc_component_dev_max98095,
2141bab3b59dSTaylor Hutt 				     max98095_dai, ARRAY_SIZE(max98095_dai));
214282a5a936SPeter Hsiang 	return ret;
214382a5a936SPeter Hsiang }
214482a5a936SPeter Hsiang 
2145a5a196bfSKrzysztof Kozlowski #ifdef CONFIG_OF
2146c4839c87STushar Behera static const struct of_device_id max98095_of_match[] = {
2147c4839c87STushar Behera 	{ .compatible = "maxim,max98095", },
2148c4839c87STushar Behera 	{ }
2149c4839c87STushar Behera };
2150c4839c87STushar Behera MODULE_DEVICE_TABLE(of, max98095_of_match);
2151a5a196bfSKrzysztof Kozlowski #endif
2152c4839c87STushar Behera 
215382a5a936SPeter Hsiang static struct i2c_driver max98095_i2c_driver = {
215482a5a936SPeter Hsiang 	.driver = {
215582a5a936SPeter Hsiang 		.name = "max98095",
2156c4839c87STushar Behera 		.of_match_table = of_match_ptr(max98095_of_match),
215782a5a936SPeter Hsiang 	},
2158*9abcd240SUwe Kleine-König 	.probe = max98095_i2c_probe,
215982a5a936SPeter Hsiang 	.id_table = max98095_i2c_id,
216082a5a936SPeter Hsiang };
216182a5a936SPeter Hsiang 
2162a8af02cfSSachin Kamat module_i2c_driver(max98095_i2c_driver);
216382a5a936SPeter Hsiang 
216482a5a936SPeter Hsiang MODULE_DESCRIPTION("ALSA SoC MAX98095 driver");
216582a5a936SPeter Hsiang MODULE_AUTHOR("Peter Hsiang");
216682a5a936SPeter Hsiang MODULE_LICENSE("GPL");
2167