xref: /openbmc/linux/sound/soc/codecs/rt5616.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b1d15059SBard Liao /*
3b1d15059SBard Liao  * rt5616.c  --  RT5616 ALSA SoC audio codec driver
4b1d15059SBard Liao  *
5b1d15059SBard Liao  * Copyright 2015 Realtek Semiconductor Corp.
6b1d15059SBard Liao  * Author: Bard Liao <bardliao@realtek.com>
7b1d15059SBard Liao  */
8b1d15059SBard Liao 
9b1d15059SBard Liao #include <linux/module.h>
10b1d15059SBard Liao #include <linux/moduleparam.h>
11b1d15059SBard Liao #include <linux/init.h>
1276d3204eSCaesar Wang #include <linux/clk.h>
13b1d15059SBard Liao #include <linux/delay.h>
14b1d15059SBard Liao #include <linux/pm.h>
15b1d15059SBard Liao #include <linux/i2c.h>
16b1d15059SBard Liao #include <linux/platform_device.h>
17b1d15059SBard Liao #include <linux/spi/spi.h>
18b1d15059SBard Liao #include <sound/core.h>
19b1d15059SBard Liao #include <sound/pcm.h>
20b1d15059SBard Liao #include <sound/pcm_params.h>
21b1d15059SBard Liao #include <sound/soc.h>
22b1d15059SBard Liao #include <sound/soc-dapm.h>
23b1d15059SBard Liao #include <sound/initval.h>
24b1d15059SBard Liao #include <sound/tlv.h>
25b1d15059SBard Liao 
26b1d15059SBard Liao #include "rl6231.h"
27b1d15059SBard Liao #include "rt5616.h"
28b1d15059SBard Liao 
29b1d15059SBard Liao #define RT5616_PR_RANGE_BASE (0xff + 1)
30b1d15059SBard Liao #define RT5616_PR_SPACING 0x100
31b1d15059SBard Liao 
32b1d15059SBard Liao #define RT5616_PR_BASE (RT5616_PR_RANGE_BASE + (0 * RT5616_PR_SPACING))
33b1d15059SBard Liao 
34b1d15059SBard Liao static const struct regmap_range_cfg rt5616_ranges[] = {
35b1d15059SBard Liao 	{
36b1d15059SBard Liao 		.name = "PR",
37b1d15059SBard Liao 		.range_min = RT5616_PR_BASE,
38b1d15059SBard Liao 		.range_max = RT5616_PR_BASE + 0xf8,
39b1d15059SBard Liao 		.selector_reg = RT5616_PRIV_INDEX,
40b1d15059SBard Liao 		.selector_mask = 0xff,
41b1d15059SBard Liao 		.selector_shift = 0x0,
42b1d15059SBard Liao 		.window_start = RT5616_PRIV_DATA,
43b1d15059SBard Liao 		.window_len = 0x1,
44b1d15059SBard Liao 	},
45b1d15059SBard Liao };
46b1d15059SBard Liao 
47b1d15059SBard Liao static const struct reg_sequence init_list[] = {
48b1d15059SBard Liao 	{RT5616_PR_BASE + 0x3d,	0x3e00},
49b1d15059SBard Liao 	{RT5616_PR_BASE + 0x25,	0x6110},
50b1d15059SBard Liao 	{RT5616_PR_BASE + 0x20,	0x611f},
51b1d15059SBard Liao 	{RT5616_PR_BASE + 0x21,	0x4040},
52b1d15059SBard Liao 	{RT5616_PR_BASE + 0x23,	0x0004},
53b1d15059SBard Liao };
5499081589SCaesar Wang 
55b1d15059SBard Liao #define RT5616_INIT_REG_LEN ARRAY_SIZE(init_list)
56b1d15059SBard Liao 
57b1d15059SBard Liao static const struct reg_default rt5616_reg[] = {
58b1d15059SBard Liao 	{ 0x00, 0x0021 },
59b1d15059SBard Liao 	{ 0x02, 0xc8c8 },
60b1d15059SBard Liao 	{ 0x03, 0xc8c8 },
61b1d15059SBard Liao 	{ 0x05, 0x0000 },
62b1d15059SBard Liao 	{ 0x0d, 0x0000 },
63b1d15059SBard Liao 	{ 0x0f, 0x0808 },
64b1d15059SBard Liao 	{ 0x19, 0xafaf },
65b1d15059SBard Liao 	{ 0x1c, 0x2f2f },
66b1d15059SBard Liao 	{ 0x1e, 0x0000 },
67b1d15059SBard Liao 	{ 0x27, 0x7860 },
68b1d15059SBard Liao 	{ 0x29, 0x8080 },
69b1d15059SBard Liao 	{ 0x2a, 0x5252 },
70b1d15059SBard Liao 	{ 0x3b, 0x0000 },
71b1d15059SBard Liao 	{ 0x3c, 0x006f },
72b1d15059SBard Liao 	{ 0x3d, 0x0000 },
73b1d15059SBard Liao 	{ 0x3e, 0x006f },
74b1d15059SBard Liao 	{ 0x45, 0x6000 },
75b1d15059SBard Liao 	{ 0x4d, 0x0000 },
76b1d15059SBard Liao 	{ 0x4e, 0x0000 },
77b1d15059SBard Liao 	{ 0x4f, 0x0279 },
78b1d15059SBard Liao 	{ 0x50, 0x0000 },
79b1d15059SBard Liao 	{ 0x51, 0x0000 },
80b1d15059SBard Liao 	{ 0x52, 0x0279 },
81b1d15059SBard Liao 	{ 0x53, 0xf000 },
82b1d15059SBard Liao 	{ 0x61, 0x0000 },
83b1d15059SBard Liao 	{ 0x62, 0x0000 },
84b1d15059SBard Liao 	{ 0x63, 0x00c0 },
85b1d15059SBard Liao 	{ 0x64, 0x0000 },
86b1d15059SBard Liao 	{ 0x65, 0x0000 },
87b1d15059SBard Liao 	{ 0x66, 0x0000 },
88b1d15059SBard Liao 	{ 0x70, 0x8000 },
89b1d15059SBard Liao 	{ 0x73, 0x1104 },
90b1d15059SBard Liao 	{ 0x74, 0x0c00 },
91b1d15059SBard Liao 	{ 0x80, 0x0000 },
92b1d15059SBard Liao 	{ 0x81, 0x0000 },
93b1d15059SBard Liao 	{ 0x82, 0x0000 },
94b1d15059SBard Liao 	{ 0x8b, 0x0600 },
95b1d15059SBard Liao 	{ 0x8e, 0x0004 },
96b1d15059SBard Liao 	{ 0x8f, 0x1100 },
97b1d15059SBard Liao 	{ 0x90, 0x0000 },
98ea968da7SBard Liao 	{ 0x91, 0x0c00 },
99b1d15059SBard Liao 	{ 0x92, 0x0000 },
100b1d15059SBard Liao 	{ 0x93, 0x2000 },
101b1d15059SBard Liao 	{ 0x94, 0x0200 },
102b1d15059SBard Liao 	{ 0x95, 0x0000 },
103b1d15059SBard Liao 	{ 0xb0, 0x2080 },
104b1d15059SBard Liao 	{ 0xb1, 0x0000 },
105b1d15059SBard Liao 	{ 0xb2, 0x0000 },
106b1d15059SBard Liao 	{ 0xb4, 0x2206 },
107b1d15059SBard Liao 	{ 0xb5, 0x1f00 },
108b1d15059SBard Liao 	{ 0xb6, 0x0000 },
109b1d15059SBard Liao 	{ 0xb7, 0x0000 },
110b1d15059SBard Liao 	{ 0xbb, 0x0000 },
111b1d15059SBard Liao 	{ 0xbc, 0x0000 },
112b1d15059SBard Liao 	{ 0xbd, 0x0000 },
113b1d15059SBard Liao 	{ 0xbe, 0x0000 },
114b1d15059SBard Liao 	{ 0xbf, 0x0000 },
115b1d15059SBard Liao 	{ 0xc0, 0x0100 },
116b1d15059SBard Liao 	{ 0xc1, 0x0000 },
117b1d15059SBard Liao 	{ 0xc2, 0x0000 },
118b1d15059SBard Liao 	{ 0xc8, 0x0000 },
119b1d15059SBard Liao 	{ 0xc9, 0x0000 },
120b1d15059SBard Liao 	{ 0xca, 0x0000 },
121b1d15059SBard Liao 	{ 0xcb, 0x0000 },
122b1d15059SBard Liao 	{ 0xcc, 0x0000 },
123b1d15059SBard Liao 	{ 0xcd, 0x0000 },
124b1d15059SBard Liao 	{ 0xce, 0x0000 },
125b1d15059SBard Liao 	{ 0xcf, 0x0013 },
126b1d15059SBard Liao 	{ 0xd0, 0x0680 },
127b1d15059SBard Liao 	{ 0xd1, 0x1c17 },
128b1d15059SBard Liao 	{ 0xd3, 0xb320 },
129b1d15059SBard Liao 	{ 0xd4, 0x0000 },
130b1d15059SBard Liao 	{ 0xd6, 0x0000 },
131b1d15059SBard Liao 	{ 0xd7, 0x0000 },
132b1d15059SBard Liao 	{ 0xd9, 0x0809 },
133b1d15059SBard Liao 	{ 0xda, 0x0000 },
134b1d15059SBard Liao 	{ 0xfa, 0x0010 },
135b1d15059SBard Liao 	{ 0xfb, 0x0000 },
136b1d15059SBard Liao 	{ 0xfc, 0x0000 },
137b1d15059SBard Liao 	{ 0xfe, 0x10ec },
138b1d15059SBard Liao 	{ 0xff, 0x6281 },
139b1d15059SBard Liao };
140b1d15059SBard Liao 
141b1d15059SBard Liao struct rt5616_priv {
14201f8902fSKuninori Morimoto 	struct snd_soc_component *component;
143b1d15059SBard Liao 	struct delayed_work patch_work;
144b1d15059SBard Liao 	struct regmap *regmap;
14576d3204eSCaesar Wang 	struct clk *mclk;
146b1d15059SBard Liao 
147b1d15059SBard Liao 	int sysclk;
148b1d15059SBard Liao 	int sysclk_src;
149b1d15059SBard Liao 	int lrck[RT5616_AIFS];
150b1d15059SBard Liao 	int bclk[RT5616_AIFS];
151b1d15059SBard Liao 	int master[RT5616_AIFS];
152b1d15059SBard Liao 
153b1d15059SBard Liao 	int pll_src;
154b1d15059SBard Liao 	int pll_in;
155b1d15059SBard Liao 	int pll_out;
156b1d15059SBard Liao 
157b1d15059SBard Liao };
158b1d15059SBard Liao 
rt5616_volatile_register(struct device * dev,unsigned int reg)159b1d15059SBard Liao static bool rt5616_volatile_register(struct device *dev, unsigned int reg)
160b1d15059SBard Liao {
161b1d15059SBard Liao 	int i;
162b1d15059SBard Liao 
163b1d15059SBard Liao 	for (i = 0; i < ARRAY_SIZE(rt5616_ranges); i++) {
164b1d15059SBard Liao 		if (reg >= rt5616_ranges[i].range_min &&
16599081589SCaesar Wang 		    reg <= rt5616_ranges[i].range_max)
166b1d15059SBard Liao 			return true;
167b1d15059SBard Liao 	}
168b1d15059SBard Liao 
169b1d15059SBard Liao 	switch (reg) {
170b1d15059SBard Liao 	case RT5616_RESET:
171b1d15059SBard Liao 	case RT5616_PRIV_DATA:
172b1d15059SBard Liao 	case RT5616_EQ_CTRL1:
173b1d15059SBard Liao 	case RT5616_DRC_AGC_1:
174b1d15059SBard Liao 	case RT5616_IRQ_CTRL2:
175b1d15059SBard Liao 	case RT5616_INT_IRQ_ST:
176b1d15059SBard Liao 	case RT5616_PGM_REG_ARR1:
177b1d15059SBard Liao 	case RT5616_PGM_REG_ARR3:
178b1d15059SBard Liao 	case RT5616_VENDOR_ID:
179b1d15059SBard Liao 	case RT5616_DEVICE_ID:
180b1d15059SBard Liao 		return true;
181b1d15059SBard Liao 	default:
182b1d15059SBard Liao 		return false;
183b1d15059SBard Liao 	}
184b1d15059SBard Liao }
185b1d15059SBard Liao 
rt5616_readable_register(struct device * dev,unsigned int reg)186b1d15059SBard Liao static bool rt5616_readable_register(struct device *dev, unsigned int reg)
187b1d15059SBard Liao {
188b1d15059SBard Liao 	int i;
189b1d15059SBard Liao 
190b1d15059SBard Liao 	for (i = 0; i < ARRAY_SIZE(rt5616_ranges); i++) {
191b1d15059SBard Liao 		if (reg >= rt5616_ranges[i].range_min &&
19299081589SCaesar Wang 		    reg <= rt5616_ranges[i].range_max)
193b1d15059SBard Liao 			return true;
194b1d15059SBard Liao 	}
195b1d15059SBard Liao 
196b1d15059SBard Liao 	switch (reg) {
197b1d15059SBard Liao 	case RT5616_RESET:
198b1d15059SBard Liao 	case RT5616_VERSION_ID:
199b1d15059SBard Liao 	case RT5616_VENDOR_ID:
200b1d15059SBard Liao 	case RT5616_DEVICE_ID:
201b1d15059SBard Liao 	case RT5616_HP_VOL:
202b1d15059SBard Liao 	case RT5616_LOUT_CTRL1:
203b1d15059SBard Liao 	case RT5616_LOUT_CTRL2:
204b1d15059SBard Liao 	case RT5616_IN1_IN2:
205b1d15059SBard Liao 	case RT5616_INL1_INR1_VOL:
206b1d15059SBard Liao 	case RT5616_DAC1_DIG_VOL:
207b1d15059SBard Liao 	case RT5616_ADC_DIG_VOL:
208b1d15059SBard Liao 	case RT5616_ADC_BST_VOL:
209b1d15059SBard Liao 	case RT5616_STO1_ADC_MIXER:
210b1d15059SBard Liao 	case RT5616_AD_DA_MIXER:
211b1d15059SBard Liao 	case RT5616_STO_DAC_MIXER:
212b1d15059SBard Liao 	case RT5616_REC_L1_MIXER:
213b1d15059SBard Liao 	case RT5616_REC_L2_MIXER:
214b1d15059SBard Liao 	case RT5616_REC_R1_MIXER:
215b1d15059SBard Liao 	case RT5616_REC_R2_MIXER:
216b1d15059SBard Liao 	case RT5616_HPO_MIXER:
217b1d15059SBard Liao 	case RT5616_OUT_L1_MIXER:
218b1d15059SBard Liao 	case RT5616_OUT_L2_MIXER:
219b1d15059SBard Liao 	case RT5616_OUT_L3_MIXER:
220b1d15059SBard Liao 	case RT5616_OUT_R1_MIXER:
221b1d15059SBard Liao 	case RT5616_OUT_R2_MIXER:
222b1d15059SBard Liao 	case RT5616_OUT_R3_MIXER:
223b1d15059SBard Liao 	case RT5616_LOUT_MIXER:
224b1d15059SBard Liao 	case RT5616_PWR_DIG1:
225b1d15059SBard Liao 	case RT5616_PWR_DIG2:
226b1d15059SBard Liao 	case RT5616_PWR_ANLG1:
227b1d15059SBard Liao 	case RT5616_PWR_ANLG2:
228b1d15059SBard Liao 	case RT5616_PWR_MIXER:
229b1d15059SBard Liao 	case RT5616_PWR_VOL:
230b1d15059SBard Liao 	case RT5616_PRIV_INDEX:
231b1d15059SBard Liao 	case RT5616_PRIV_DATA:
232b1d15059SBard Liao 	case RT5616_I2S1_SDP:
233b1d15059SBard Liao 	case RT5616_ADDA_CLK1:
234b1d15059SBard Liao 	case RT5616_ADDA_CLK2:
235b1d15059SBard Liao 	case RT5616_GLB_CLK:
236b1d15059SBard Liao 	case RT5616_PLL_CTRL1:
237b1d15059SBard Liao 	case RT5616_PLL_CTRL2:
238b1d15059SBard Liao 	case RT5616_HP_OVCD:
239b1d15059SBard Liao 	case RT5616_DEPOP_M1:
240b1d15059SBard Liao 	case RT5616_DEPOP_M2:
241b1d15059SBard Liao 	case RT5616_DEPOP_M3:
242b1d15059SBard Liao 	case RT5616_CHARGE_PUMP:
243b1d15059SBard Liao 	case RT5616_PV_DET_SPK_G:
244b1d15059SBard Liao 	case RT5616_MICBIAS:
245b1d15059SBard Liao 	case RT5616_A_JD_CTL1:
246b1d15059SBard Liao 	case RT5616_A_JD_CTL2:
247b1d15059SBard Liao 	case RT5616_EQ_CTRL1:
248b1d15059SBard Liao 	case RT5616_EQ_CTRL2:
249b1d15059SBard Liao 	case RT5616_WIND_FILTER:
250b1d15059SBard Liao 	case RT5616_DRC_AGC_1:
251b1d15059SBard Liao 	case RT5616_DRC_AGC_2:
252b1d15059SBard Liao 	case RT5616_DRC_AGC_3:
253b1d15059SBard Liao 	case RT5616_SVOL_ZC:
254b1d15059SBard Liao 	case RT5616_JD_CTRL1:
255b1d15059SBard Liao 	case RT5616_JD_CTRL2:
256b1d15059SBard Liao 	case RT5616_IRQ_CTRL1:
257b1d15059SBard Liao 	case RT5616_IRQ_CTRL2:
258b1d15059SBard Liao 	case RT5616_INT_IRQ_ST:
259b1d15059SBard Liao 	case RT5616_GPIO_CTRL1:
260b1d15059SBard Liao 	case RT5616_GPIO_CTRL2:
261b1d15059SBard Liao 	case RT5616_GPIO_CTRL3:
262b1d15059SBard Liao 	case RT5616_PGM_REG_ARR1:
263b1d15059SBard Liao 	case RT5616_PGM_REG_ARR2:
264b1d15059SBard Liao 	case RT5616_PGM_REG_ARR3:
265b1d15059SBard Liao 	case RT5616_PGM_REG_ARR4:
266b1d15059SBard Liao 	case RT5616_PGM_REG_ARR5:
267b1d15059SBard Liao 	case RT5616_SCB_FUNC:
268b1d15059SBard Liao 	case RT5616_SCB_CTRL:
269b1d15059SBard Liao 	case RT5616_BASE_BACK:
270b1d15059SBard Liao 	case RT5616_MP3_PLUS1:
271b1d15059SBard Liao 	case RT5616_MP3_PLUS2:
272b1d15059SBard Liao 	case RT5616_ADJ_HPF_CTRL1:
273b1d15059SBard Liao 	case RT5616_ADJ_HPF_CTRL2:
274b1d15059SBard Liao 	case RT5616_HP_CALIB_AMP_DET:
275b1d15059SBard Liao 	case RT5616_HP_CALIB2:
276b1d15059SBard Liao 	case RT5616_SV_ZCD1:
277b1d15059SBard Liao 	case RT5616_SV_ZCD2:
278b1d15059SBard Liao 	case RT5616_D_MISC:
279b1d15059SBard Liao 	case RT5616_DUMMY2:
280b1d15059SBard Liao 	case RT5616_DUMMY3:
281b1d15059SBard Liao 		return true;
282b1d15059SBard Liao 	default:
283b1d15059SBard Liao 		return false;
284b1d15059SBard Liao 	}
285b1d15059SBard Liao }
286b1d15059SBard Liao 
287b1d15059SBard Liao static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
288b1d15059SBard Liao static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
289b1d15059SBard Liao static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
290b1d15059SBard Liao static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
291b1d15059SBard Liao static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
292b1d15059SBard Liao 
293b1d15059SBard Liao /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
29451a57640STakashi Sakamoto static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(bst_tlv,
295b1d15059SBard Liao 	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
296b1d15059SBard Liao 	1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
297b1d15059SBard Liao 	2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
298b1d15059SBard Liao 	3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
299b1d15059SBard Liao 	6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
300b1d15059SBard Liao 	7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
301b1d15059SBard Liao 	8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
30251a57640STakashi Sakamoto );
303b1d15059SBard Liao 
304b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_snd_controls[] = {
305b1d15059SBard Liao 	/* Headphone Output Volume */
306b1d15059SBard Liao 	SOC_DOUBLE("HP Playback Switch", RT5616_HP_VOL,
307b1d15059SBard Liao 		   RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
308d7fcd136SJohn Lin 	SOC_DOUBLE("HPVOL Playback Switch", RT5616_HP_VOL,
309d7fcd136SJohn Lin 		   RT5616_VOL_L_SFT, RT5616_VOL_R_SFT, 1, 1),
310b1d15059SBard Liao 	SOC_DOUBLE_TLV("HP Playback Volume", RT5616_HP_VOL,
311b1d15059SBard Liao 		       RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv),
312b1d15059SBard Liao 	/* OUTPUT Control */
313b1d15059SBard Liao 	SOC_DOUBLE("OUT Playback Switch", RT5616_LOUT_CTRL1,
314b1d15059SBard Liao 		   RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
315b1d15059SBard Liao 	SOC_DOUBLE("OUT Channel Switch", RT5616_LOUT_CTRL1,
316b1d15059SBard Liao 		   RT5616_VOL_L_SFT, RT5616_VOL_R_SFT, 1, 1),
317b1d15059SBard Liao 	SOC_DOUBLE_TLV("OUT Playback Volume", RT5616_LOUT_CTRL1,
318b1d15059SBard Liao 		       RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv),
319b1d15059SBard Liao 
320b1d15059SBard Liao 	/* DAC Digital Volume */
321b1d15059SBard Liao 	SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5616_DAC1_DIG_VOL,
322b1d15059SBard Liao 		       RT5616_L_VOL_SFT, RT5616_R_VOL_SFT,
323b1d15059SBard Liao 		       175, 0, dac_vol_tlv),
324b1d15059SBard Liao 	/* IN1/IN2 Control */
325e2133b64SBard Liao 	SOC_SINGLE_TLV("IN1 Boost Volume", RT5616_IN1_IN2,
326b1d15059SBard Liao 		       RT5616_BST_SFT1, 8, 0, bst_tlv),
327e2133b64SBard Liao 	SOC_SINGLE_TLV("IN2 Boost Volume", RT5616_IN1_IN2,
328b1d15059SBard Liao 		       RT5616_BST_SFT2, 8, 0, bst_tlv),
329b1d15059SBard Liao 	/* INL/INR Volume Control */
330b1d15059SBard Liao 	SOC_DOUBLE_TLV("IN Capture Volume", RT5616_INL1_INR1_VOL,
331b1d15059SBard Liao 		       RT5616_INL_VOL_SFT, RT5616_INR_VOL_SFT,
332b1d15059SBard Liao 		       31, 1, in_vol_tlv),
333b1d15059SBard Liao 	/* ADC Digital Volume Control */
334b1d15059SBard Liao 	SOC_DOUBLE("ADC Capture Switch", RT5616_ADC_DIG_VOL,
335b1d15059SBard Liao 		   RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
336b1d15059SBard Liao 	SOC_DOUBLE_TLV("ADC Capture Volume", RT5616_ADC_DIG_VOL,
337b1d15059SBard Liao 		       RT5616_L_VOL_SFT, RT5616_R_VOL_SFT,
338b1d15059SBard Liao 		       127, 0, adc_vol_tlv),
339b1d15059SBard Liao 
340b1d15059SBard Liao 	/* ADC Boost Volume Control */
341e2133b64SBard Liao 	SOC_DOUBLE_TLV("ADC Boost Volume", RT5616_ADC_BST_VOL,
342b1d15059SBard Liao 		       RT5616_ADC_L_BST_SFT, RT5616_ADC_R_BST_SFT,
343b1d15059SBard Liao 		       3, 0, adc_bst_tlv),
344b1d15059SBard Liao };
345b1d15059SBard Liao 
is_sys_clk_from_pll(struct snd_soc_dapm_widget * source,struct snd_soc_dapm_widget * sink)346b1d15059SBard Liao static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
347b1d15059SBard Liao 			       struct snd_soc_dapm_widget *sink)
348b1d15059SBard Liao {
349b1d15059SBard Liao 	unsigned int val;
350b1d15059SBard Liao 
351467a2553SKuninori Morimoto 	val = snd_soc_component_read(snd_soc_dapm_to_component(source->dapm), RT5616_GLB_CLK);
352b1d15059SBard Liao 	val &= RT5616_SCLK_SRC_MASK;
353b1d15059SBard Liao 	if (val == RT5616_SCLK_SRC_PLL1)
354b1d15059SBard Liao 		return 1;
355b1d15059SBard Liao 	else
356b1d15059SBard Liao 		return 0;
357b1d15059SBard Liao }
358b1d15059SBard Liao 
359b1d15059SBard Liao /* Digital Mixer */
360b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_sto1_adc_l_mix[] = {
361b1d15059SBard Liao 	SOC_DAPM_SINGLE("ADC1 Switch", RT5616_STO1_ADC_MIXER,
362b1d15059SBard Liao 			RT5616_M_STO1_ADC_L1_SFT, 1, 1),
363b1d15059SBard Liao };
364b1d15059SBard Liao 
365b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_sto1_adc_r_mix[] = {
366b1d15059SBard Liao 	SOC_DAPM_SINGLE("ADC1 Switch", RT5616_STO1_ADC_MIXER,
367b1d15059SBard Liao 			RT5616_M_STO1_ADC_R1_SFT, 1, 1),
368b1d15059SBard Liao };
369b1d15059SBard Liao 
370b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_dac_l_mix[] = {
371b1d15059SBard Liao 	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5616_AD_DA_MIXER,
372b1d15059SBard Liao 			RT5616_M_ADCMIX_L_SFT, 1, 1),
373b1d15059SBard Liao 	SOC_DAPM_SINGLE("INF1 Switch", RT5616_AD_DA_MIXER,
374b1d15059SBard Liao 			RT5616_M_IF1_DAC_L_SFT, 1, 1),
375b1d15059SBard Liao };
376b1d15059SBard Liao 
377b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_dac_r_mix[] = {
378b1d15059SBard Liao 	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5616_AD_DA_MIXER,
379b1d15059SBard Liao 			RT5616_M_ADCMIX_R_SFT, 1, 1),
380b1d15059SBard Liao 	SOC_DAPM_SINGLE("INF1 Switch", RT5616_AD_DA_MIXER,
381b1d15059SBard Liao 			RT5616_M_IF1_DAC_R_SFT, 1, 1),
382b1d15059SBard Liao };
383b1d15059SBard Liao 
384b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_sto_dac_l_mix[] = {
385b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_STO_DAC_MIXER,
386b1d15059SBard Liao 			RT5616_M_DAC_L1_MIXL_SFT, 1, 1),
387b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_STO_DAC_MIXER,
388b1d15059SBard Liao 			RT5616_M_DAC_R1_MIXL_SFT, 1, 1),
389b1d15059SBard Liao };
390b1d15059SBard Liao 
391b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_sto_dac_r_mix[] = {
392b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_STO_DAC_MIXER,
393b1d15059SBard Liao 			RT5616_M_DAC_R1_MIXR_SFT, 1, 1),
394b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_STO_DAC_MIXER,
395b1d15059SBard Liao 			RT5616_M_DAC_L1_MIXR_SFT, 1, 1),
396b1d15059SBard Liao };
397b1d15059SBard Liao 
398b1d15059SBard Liao /* Analog Input Mixer */
399b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_rec_l_mix[] = {
400b1d15059SBard Liao 	SOC_DAPM_SINGLE("INL1 Switch", RT5616_REC_L2_MIXER,
401b1d15059SBard Liao 			RT5616_M_IN1_L_RM_L_SFT, 1, 1),
402b1d15059SBard Liao 	SOC_DAPM_SINGLE("BST2 Switch", RT5616_REC_L2_MIXER,
403b1d15059SBard Liao 			RT5616_M_BST2_RM_L_SFT, 1, 1),
404b1d15059SBard Liao 	SOC_DAPM_SINGLE("BST1 Switch", RT5616_REC_L2_MIXER,
405b1d15059SBard Liao 			RT5616_M_BST1_RM_L_SFT, 1, 1),
406b1d15059SBard Liao };
407b1d15059SBard Liao 
408b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_rec_r_mix[] = {
409b1d15059SBard Liao 	SOC_DAPM_SINGLE("INR1 Switch", RT5616_REC_R2_MIXER,
410b1d15059SBard Liao 			RT5616_M_IN1_R_RM_R_SFT, 1, 1),
411b1d15059SBard Liao 	SOC_DAPM_SINGLE("BST2 Switch", RT5616_REC_R2_MIXER,
412b1d15059SBard Liao 			RT5616_M_BST2_RM_R_SFT, 1, 1),
413b1d15059SBard Liao 	SOC_DAPM_SINGLE("BST1 Switch", RT5616_REC_R2_MIXER,
414b1d15059SBard Liao 			RT5616_M_BST1_RM_R_SFT, 1, 1),
415b1d15059SBard Liao };
416b1d15059SBard Liao 
417b1d15059SBard Liao /* Analog Output Mixer */
418b1d15059SBard Liao 
419b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_out_l_mix[] = {
420b1d15059SBard Liao 	SOC_DAPM_SINGLE("BST1 Switch", RT5616_OUT_L3_MIXER,
421b1d15059SBard Liao 			RT5616_M_BST1_OM_L_SFT, 1, 1),
422b1d15059SBard Liao 	SOC_DAPM_SINGLE("BST2 Switch", RT5616_OUT_L3_MIXER,
423b1d15059SBard Liao 			RT5616_M_BST2_OM_L_SFT, 1, 1),
424b1d15059SBard Liao 	SOC_DAPM_SINGLE("INL1 Switch", RT5616_OUT_L3_MIXER,
425b1d15059SBard Liao 			RT5616_M_IN1_L_OM_L_SFT, 1, 1),
426b1d15059SBard Liao 	SOC_DAPM_SINGLE("REC MIXL Switch", RT5616_OUT_L3_MIXER,
427b1d15059SBard Liao 			RT5616_M_RM_L_OM_L_SFT, 1, 1),
428b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_OUT_L3_MIXER,
429b1d15059SBard Liao 			RT5616_M_DAC_L1_OM_L_SFT, 1, 1),
430b1d15059SBard Liao };
431b1d15059SBard Liao 
432b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_out_r_mix[] = {
433b1d15059SBard Liao 	SOC_DAPM_SINGLE("BST2 Switch", RT5616_OUT_R3_MIXER,
434b1d15059SBard Liao 			RT5616_M_BST2_OM_R_SFT, 1, 1),
435b1d15059SBard Liao 	SOC_DAPM_SINGLE("BST1 Switch", RT5616_OUT_R3_MIXER,
436b1d15059SBard Liao 			RT5616_M_BST1_OM_R_SFT, 1, 1),
437b1d15059SBard Liao 	SOC_DAPM_SINGLE("INR1 Switch", RT5616_OUT_R3_MIXER,
438b1d15059SBard Liao 			RT5616_M_IN1_R_OM_R_SFT, 1, 1),
439b1d15059SBard Liao 	SOC_DAPM_SINGLE("REC MIXR Switch", RT5616_OUT_R3_MIXER,
440b1d15059SBard Liao 			RT5616_M_RM_R_OM_R_SFT, 1, 1),
441b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_OUT_R3_MIXER,
442b1d15059SBard Liao 			RT5616_M_DAC_R1_OM_R_SFT, 1, 1),
443b1d15059SBard Liao };
444b1d15059SBard Liao 
445b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_hpo_mix[] = {
446b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC1 Switch", RT5616_HPO_MIXER,
447b1d15059SBard Liao 			RT5616_M_DAC1_HM_SFT, 1, 1),
448b1d15059SBard Liao 	SOC_DAPM_SINGLE("HPVOL Switch", RT5616_HPO_MIXER,
449b1d15059SBard Liao 			RT5616_M_HPVOL_HM_SFT, 1, 1),
450b1d15059SBard Liao };
451b1d15059SBard Liao 
452b1d15059SBard Liao static const struct snd_kcontrol_new rt5616_lout_mix[] = {
453b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_LOUT_MIXER,
454b1d15059SBard Liao 			RT5616_M_DAC_L1_LM_SFT, 1, 1),
455b1d15059SBard Liao 	SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_LOUT_MIXER,
456b1d15059SBard Liao 			RT5616_M_DAC_R1_LM_SFT, 1, 1),
457b1d15059SBard Liao 	SOC_DAPM_SINGLE("OUTVOL L Switch", RT5616_LOUT_MIXER,
458b1d15059SBard Liao 			RT5616_M_OV_L_LM_SFT, 1, 1),
459b1d15059SBard Liao 	SOC_DAPM_SINGLE("OUTVOL R Switch", RT5616_LOUT_MIXER,
460b1d15059SBard Liao 			RT5616_M_OV_R_LM_SFT, 1, 1),
461b1d15059SBard Liao };
462b1d15059SBard Liao 
rt5616_adc_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)463b1d15059SBard Liao static int rt5616_adc_event(struct snd_soc_dapm_widget *w,
464b1d15059SBard Liao 			    struct snd_kcontrol *kcontrol, int event)
465b1d15059SBard Liao {
46601f8902fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
467b1d15059SBard Liao 
468b1d15059SBard Liao 	switch (event) {
469b1d15059SBard Liao 	case SND_SOC_DAPM_POST_PMU:
47001f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_ADC_DIG_VOL,
471b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE, 0);
472b1d15059SBard Liao 		break;
473b1d15059SBard Liao 
474b1d15059SBard Liao 	case SND_SOC_DAPM_POST_PMD:
47501f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_ADC_DIG_VOL,
476b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE,
477b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE);
478b1d15059SBard Liao 		break;
479b1d15059SBard Liao 
480b1d15059SBard Liao 	default:
481b1d15059SBard Liao 		return 0;
482b1d15059SBard Liao 	}
483b1d15059SBard Liao 
484b1d15059SBard Liao 	return 0;
485b1d15059SBard Liao }
486b1d15059SBard Liao 
rt5616_charge_pump_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)487b1d15059SBard Liao static int rt5616_charge_pump_event(struct snd_soc_dapm_widget *w,
488b1d15059SBard Liao 				    struct snd_kcontrol *kcontrol, int event)
489b1d15059SBard Liao {
49001f8902fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
491b1d15059SBard Liao 
492b1d15059SBard Liao 	switch (event) {
493b1d15059SBard Liao 	case SND_SOC_DAPM_POST_PMU:
494b1d15059SBard Liao 		/* depop parameters */
49501f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M2,
496b1d15059SBard Liao 				    RT5616_DEPOP_MASK, RT5616_DEPOP_MAN);
49701f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
498b1d15059SBard Liao 				    RT5616_HP_CP_MASK | RT5616_HP_SG_MASK |
499b1d15059SBard Liao 				    RT5616_HP_CB_MASK, RT5616_HP_CP_PU |
500b1d15059SBard Liao 				    RT5616_HP_SG_DIS | RT5616_HP_CB_PU);
50101f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PR_BASE +
502b1d15059SBard Liao 			      RT5616_HP_DCC_INT1, 0x9f00);
503b1d15059SBard Liao 		/* headphone amp power on */
50401f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG1,
505b1d15059SBard Liao 				    RT5616_PWR_FV1 | RT5616_PWR_FV2, 0);
50601f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_VOL,
507b1d15059SBard Liao 				    RT5616_PWR_HV_L | RT5616_PWR_HV_R,
508b1d15059SBard Liao 				    RT5616_PWR_HV_L | RT5616_PWR_HV_R);
50901f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG1,
510b1d15059SBard Liao 				    RT5616_PWR_HP_L | RT5616_PWR_HP_R |
511b1d15059SBard Liao 				    RT5616_PWR_HA, RT5616_PWR_HP_L |
512b1d15059SBard Liao 				    RT5616_PWR_HP_R | RT5616_PWR_HA);
513b1d15059SBard Liao 		msleep(50);
51401f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG1,
515b1d15059SBard Liao 				    RT5616_PWR_FV1 | RT5616_PWR_FV2,
516b1d15059SBard Liao 				    RT5616_PWR_FV1 | RT5616_PWR_FV2);
517b1d15059SBard Liao 
51801f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_CHARGE_PUMP,
519b1d15059SBard Liao 				    RT5616_PM_HP_MASK, RT5616_PM_HP_HV);
52001f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PR_BASE +
521b1d15059SBard Liao 				    RT5616_CHOP_DAC_ADC, 0x0200, 0x0200);
52201f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
523b1d15059SBard Liao 				    RT5616_HP_CO_MASK | RT5616_HP_SG_MASK,
524b1d15059SBard Liao 				    RT5616_HP_CO_EN | RT5616_HP_SG_EN);
525b1d15059SBard Liao 		break;
526b1d15059SBard Liao 	case SND_SOC_DAPM_PRE_PMD:
52701f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PR_BASE +
528b1d15059SBard Liao 				    RT5616_CHOP_DAC_ADC, 0x0200, 0x0);
52901f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
530b1d15059SBard Liao 				    RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK |
531b1d15059SBard Liao 				    RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS |
532b1d15059SBard Liao 				    RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS);
533b1d15059SBard Liao 		/* headphone amp power down */
53401f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
53599081589SCaesar Wang 				    RT5616_SMT_TRIG_MASK |
53699081589SCaesar Wang 				    RT5616_HP_CD_PD_MASK | RT5616_HP_CO_MASK |
53799081589SCaesar Wang 				    RT5616_HP_CP_MASK | RT5616_HP_SG_MASK |
53899081589SCaesar Wang 				    RT5616_HP_CB_MASK,
539b1d15059SBard Liao 				    RT5616_SMT_TRIG_DIS | RT5616_HP_CD_PD_EN |
540b1d15059SBard Liao 				    RT5616_HP_CO_DIS | RT5616_HP_CP_PD |
541b1d15059SBard Liao 				    RT5616_HP_SG_EN | RT5616_HP_CB_PD);
54201f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG1,
543b1d15059SBard Liao 				    RT5616_PWR_HP_L | RT5616_PWR_HP_R |
544b1d15059SBard Liao 				    RT5616_PWR_HA, 0);
545b1d15059SBard Liao 		break;
546b1d15059SBard Liao 	default:
547b1d15059SBard Liao 		return 0;
548b1d15059SBard Liao 	}
549b1d15059SBard Liao 
550b1d15059SBard Liao 	return 0;
551b1d15059SBard Liao }
552b1d15059SBard Liao 
rt5616_hp_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)553b1d15059SBard Liao static int rt5616_hp_event(struct snd_soc_dapm_widget *w,
554b1d15059SBard Liao 			   struct snd_kcontrol *kcontrol, int event)
555b1d15059SBard Liao {
55601f8902fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
557b1d15059SBard Liao 
558b1d15059SBard Liao 	switch (event) {
559b1d15059SBard Liao 	case SND_SOC_DAPM_POST_PMU:
560b1d15059SBard Liao 		/* headphone unmute sequence */
56101f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M3,
562b1d15059SBard Liao 				    RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK |
563b1d15059SBard Liao 				    RT5616_CP_FQ3_MASK,
56499081589SCaesar Wang 				    RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ1_SFT |
56599081589SCaesar Wang 				    RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT |
56699081589SCaesar Wang 				    RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ3_SFT);
56701f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PR_BASE +
568b1d15059SBard Liao 			      RT5616_MAMP_INT_REG2, 0xfc00);
56901f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
570b1d15059SBard Liao 				    RT5616_SMT_TRIG_MASK, RT5616_SMT_TRIG_EN);
57101f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
572b1d15059SBard Liao 				    RT5616_RSTN_MASK, RT5616_RSTN_EN);
57301f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
574b1d15059SBard Liao 				    RT5616_RSTN_MASK | RT5616_HP_L_SMT_MASK |
575b1d15059SBard Liao 				    RT5616_HP_R_SMT_MASK, RT5616_RSTN_DIS |
576b1d15059SBard Liao 				    RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN);
57701f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_HP_VOL,
578b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE, 0);
579b1d15059SBard Liao 		msleep(100);
58001f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
581b1d15059SBard Liao 				    RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK |
582b1d15059SBard Liao 				    RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS |
583b1d15059SBard Liao 				    RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS);
584b1d15059SBard Liao 		msleep(20);
58501f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_HP_CALIB_AMP_DET,
586b1d15059SBard Liao 				    RT5616_HPD_PS_MASK, RT5616_HPD_PS_EN);
587b1d15059SBard Liao 		break;
588b1d15059SBard Liao 
589b1d15059SBard Liao 	case SND_SOC_DAPM_PRE_PMD:
590b1d15059SBard Liao 		/* headphone mute sequence */
59101f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M3,
592b1d15059SBard Liao 				    RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK |
593b1d15059SBard Liao 				    RT5616_CP_FQ3_MASK,
59499081589SCaesar Wang 				    RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ1_SFT |
59599081589SCaesar Wang 				    RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT |
59699081589SCaesar Wang 				    RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ3_SFT);
59701f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PR_BASE +
598b1d15059SBard Liao 			      RT5616_MAMP_INT_REG2, 0xfc00);
59901f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
600b1d15059SBard Liao 				    RT5616_HP_SG_MASK, RT5616_HP_SG_EN);
60101f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
602b1d15059SBard Liao 				    RT5616_RSTP_MASK, RT5616_RSTP_EN);
60301f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_DEPOP_M1,
604b1d15059SBard Liao 				    RT5616_RSTP_MASK | RT5616_HP_L_SMT_MASK |
605b1d15059SBard Liao 				    RT5616_HP_R_SMT_MASK, RT5616_RSTP_DIS |
606b1d15059SBard Liao 				    RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN);
60701f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_HP_CALIB_AMP_DET,
608b1d15059SBard Liao 				    RT5616_HPD_PS_MASK, RT5616_HPD_PS_DIS);
609b1d15059SBard Liao 		msleep(90);
61001f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_HP_VOL,
611b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE,
612b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE);
613b1d15059SBard Liao 		msleep(30);
614b1d15059SBard Liao 		break;
615b1d15059SBard Liao 
616b1d15059SBard Liao 	default:
617b1d15059SBard Liao 		return 0;
618b1d15059SBard Liao 	}
619b1d15059SBard Liao 
620b1d15059SBard Liao 	return 0;
621b1d15059SBard Liao }
622b1d15059SBard Liao 
rt5616_lout_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)623b1d15059SBard Liao static int rt5616_lout_event(struct snd_soc_dapm_widget *w,
624b1d15059SBard Liao 			     struct snd_kcontrol *kcontrol, int event)
625b1d15059SBard Liao {
62601f8902fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
627b1d15059SBard Liao 
628b1d15059SBard Liao 	switch (event) {
629b1d15059SBard Liao 	case SND_SOC_DAPM_POST_PMU:
63001f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG1,
631b1d15059SBard Liao 				    RT5616_PWR_LM, RT5616_PWR_LM);
63201f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_LOUT_CTRL1,
633b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE, 0);
634b1d15059SBard Liao 		break;
635b1d15059SBard Liao 
636b1d15059SBard Liao 	case SND_SOC_DAPM_PRE_PMD:
63701f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_LOUT_CTRL1,
638b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE,
639b1d15059SBard Liao 				    RT5616_L_MUTE | RT5616_R_MUTE);
64001f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG1,
641b1d15059SBard Liao 				    RT5616_PWR_LM, 0);
642b1d15059SBard Liao 		break;
643b1d15059SBard Liao 
644b1d15059SBard Liao 	default:
645b1d15059SBard Liao 		return 0;
646b1d15059SBard Liao 	}
647b1d15059SBard Liao 
648b1d15059SBard Liao 	return 0;
649b1d15059SBard Liao }
650b1d15059SBard Liao 
rt5616_bst1_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)651b1d15059SBard Liao static int rt5616_bst1_event(struct snd_soc_dapm_widget *w,
652b1d15059SBard Liao 			     struct snd_kcontrol *kcontrol, int event)
653b1d15059SBard Liao {
65401f8902fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
655b1d15059SBard Liao 
656b1d15059SBard Liao 	switch (event) {
657b1d15059SBard Liao 	case SND_SOC_DAPM_POST_PMU:
65801f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG2,
659b1d15059SBard Liao 				    RT5616_PWR_BST1_OP2, RT5616_PWR_BST1_OP2);
660b1d15059SBard Liao 		break;
661b1d15059SBard Liao 
662b1d15059SBard Liao 	case SND_SOC_DAPM_PRE_PMD:
66301f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG2,
664b1d15059SBard Liao 				    RT5616_PWR_BST1_OP2, 0);
665b1d15059SBard Liao 		break;
666b1d15059SBard Liao 
667b1d15059SBard Liao 	default:
668b1d15059SBard Liao 		return 0;
669b1d15059SBard Liao 	}
670b1d15059SBard Liao 
671b1d15059SBard Liao 	return 0;
672b1d15059SBard Liao }
673b1d15059SBard Liao 
rt5616_bst2_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)674b1d15059SBard Liao static int rt5616_bst2_event(struct snd_soc_dapm_widget *w,
675b1d15059SBard Liao 			     struct snd_kcontrol *kcontrol, int event)
676b1d15059SBard Liao {
67701f8902fSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
678b1d15059SBard Liao 
679b1d15059SBard Liao 	switch (event) {
680b1d15059SBard Liao 	case SND_SOC_DAPM_POST_PMU:
68101f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG2,
682b1d15059SBard Liao 				    RT5616_PWR_BST2_OP2, RT5616_PWR_BST2_OP2);
683b1d15059SBard Liao 		break;
684b1d15059SBard Liao 
685b1d15059SBard Liao 	case SND_SOC_DAPM_PRE_PMD:
68601f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_PWR_ANLG2,
687b1d15059SBard Liao 				    RT5616_PWR_BST2_OP2, 0);
688b1d15059SBard Liao 		break;
689b1d15059SBard Liao 
690b1d15059SBard Liao 	default:
691b1d15059SBard Liao 		return 0;
692b1d15059SBard Liao 	}
693b1d15059SBard Liao 
694b1d15059SBard Liao 	return 0;
695b1d15059SBard Liao }
696b1d15059SBard Liao 
697b1d15059SBard Liao static const struct snd_soc_dapm_widget rt5616_dapm_widgets[] = {
698b1d15059SBard Liao 	SND_SOC_DAPM_SUPPLY("PLL1", RT5616_PWR_ANLG2,
699b1d15059SBard Liao 			    RT5616_PWR_PLL_BIT, 0, NULL, 0),
700b1d15059SBard Liao 	/* Input Side */
701b1d15059SBard Liao 	/* micbias */
702b1d15059SBard Liao 	SND_SOC_DAPM_SUPPLY("LDO", RT5616_PWR_ANLG1,
703b1d15059SBard Liao 			    RT5616_PWR_LDO_BIT, 0, NULL, 0),
704b1d15059SBard Liao 	SND_SOC_DAPM_SUPPLY("micbias1", RT5616_PWR_ANLG2,
705b1d15059SBard Liao 			    RT5616_PWR_MB1_BIT, 0, NULL, 0),
706b1d15059SBard Liao 
707b1d15059SBard Liao 	/* Input Lines */
708b1d15059SBard Liao 	SND_SOC_DAPM_INPUT("MIC1"),
709b1d15059SBard Liao 	SND_SOC_DAPM_INPUT("MIC2"),
710b1d15059SBard Liao 
711b1d15059SBard Liao 	SND_SOC_DAPM_INPUT("IN1P"),
712b1d15059SBard Liao 	SND_SOC_DAPM_INPUT("IN2P"),
713b1d15059SBard Liao 	SND_SOC_DAPM_INPUT("IN2N"),
714b1d15059SBard Liao 
715b1d15059SBard Liao 	/* Boost */
716b1d15059SBard Liao 	SND_SOC_DAPM_PGA_E("BST1", RT5616_PWR_ANLG2,
717b1d15059SBard Liao 			   RT5616_PWR_BST1_BIT, 0, NULL, 0, rt5616_bst1_event,
718b1d15059SBard Liao 			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
719b1d15059SBard Liao 	SND_SOC_DAPM_PGA_E("BST2", RT5616_PWR_ANLG2,
720b1d15059SBard Liao 			   RT5616_PWR_BST2_BIT, 0, NULL, 0, rt5616_bst2_event,
721b1d15059SBard Liao 			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
722b1d15059SBard Liao 	/* Input Volume */
723b1d15059SBard Liao 	SND_SOC_DAPM_PGA("INL1 VOL", RT5616_PWR_VOL,
724b1d15059SBard Liao 			 RT5616_PWR_IN1_L_BIT, 0, NULL, 0),
725b1d15059SBard Liao 	SND_SOC_DAPM_PGA("INR1 VOL", RT5616_PWR_VOL,
726b1d15059SBard Liao 			 RT5616_PWR_IN1_R_BIT, 0, NULL, 0),
727b1d15059SBard Liao 	SND_SOC_DAPM_PGA("INL2 VOL", RT5616_PWR_VOL,
728b1d15059SBard Liao 			 RT5616_PWR_IN2_L_BIT, 0, NULL, 0),
729b1d15059SBard Liao 	SND_SOC_DAPM_PGA("INR2 VOL", RT5616_PWR_VOL,
730b1d15059SBard Liao 			 RT5616_PWR_IN2_R_BIT, 0, NULL, 0),
731b1d15059SBard Liao 
732b1d15059SBard Liao 	/* REC Mixer */
733b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("RECMIXL", RT5616_PWR_MIXER, RT5616_PWR_RM_L_BIT, 0,
734b1d15059SBard Liao 			   rt5616_rec_l_mix, ARRAY_SIZE(rt5616_rec_l_mix)),
735b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("RECMIXR", RT5616_PWR_MIXER, RT5616_PWR_RM_R_BIT, 0,
736b1d15059SBard Liao 			   rt5616_rec_r_mix, ARRAY_SIZE(rt5616_rec_r_mix)),
737b1d15059SBard Liao 	/* ADCs */
738b1d15059SBard Liao 	SND_SOC_DAPM_ADC_E("ADC L", NULL, RT5616_PWR_DIG1,
739b1d15059SBard Liao 			   RT5616_PWR_ADC_L_BIT, 0, rt5616_adc_event,
740b1d15059SBard Liao 			   SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
741b1d15059SBard Liao 	SND_SOC_DAPM_ADC_E("ADC R", NULL, RT5616_PWR_DIG1,
742b1d15059SBard Liao 			   RT5616_PWR_ADC_R_BIT, 0, rt5616_adc_event,
743b1d15059SBard Liao 			   SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
744b1d15059SBard Liao 
745b1d15059SBard Liao 	/* ADC Mixer */
746b1d15059SBard Liao 	SND_SOC_DAPM_SUPPLY("stereo1 filter", RT5616_PWR_DIG2,
747b1d15059SBard Liao 			    RT5616_PWR_ADC_STO1_F_BIT, 0, NULL, 0),
748b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0,
74999081589SCaesar Wang 			   rt5616_sto1_adc_l_mix,
75099081589SCaesar Wang 			   ARRAY_SIZE(rt5616_sto1_adc_l_mix)),
751b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0,
75299081589SCaesar Wang 			   rt5616_sto1_adc_r_mix,
75399081589SCaesar Wang 			   ARRAY_SIZE(rt5616_sto1_adc_r_mix)),
754b1d15059SBard Liao 
755b1d15059SBard Liao 	/* Digital Interface */
756b1d15059SBard Liao 	SND_SOC_DAPM_SUPPLY("I2S1", RT5616_PWR_DIG1,
757b1d15059SBard Liao 			    RT5616_PWR_I2S1_BIT, 0, NULL, 0),
758b1d15059SBard Liao 	SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
759b1d15059SBard Liao 	SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
760b1d15059SBard Liao 	SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
761b1d15059SBard Liao 	SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
762b1d15059SBard Liao 
763b1d15059SBard Liao 	/* Digital Interface Select */
764b1d15059SBard Liao 
765b1d15059SBard Liao 	/* Audio Interface */
766b1d15059SBard Liao 	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
767b1d15059SBard Liao 	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
768b1d15059SBard Liao 
769b1d15059SBard Liao 	/* Audio DSP */
770b1d15059SBard Liao 	SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
771b1d15059SBard Liao 
772b1d15059SBard Liao 	/* Output Side */
773b1d15059SBard Liao 	/* DAC mixer before sound effect  */
774b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
775b1d15059SBard Liao 			   rt5616_dac_l_mix, ARRAY_SIZE(rt5616_dac_l_mix)),
776b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
777b1d15059SBard Liao 			   rt5616_dac_r_mix, ARRAY_SIZE(rt5616_dac_r_mix)),
778b1d15059SBard Liao 
779b1d15059SBard Liao 	SND_SOC_DAPM_SUPPLY("Stero1 DAC Power", RT5616_PWR_DIG2,
780b1d15059SBard Liao 			    RT5616_PWR_DAC_STO1_F_BIT, 0, NULL, 0),
781b1d15059SBard Liao 
782b1d15059SBard Liao 	/* DAC Mixer */
783b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
78499081589SCaesar Wang 			   rt5616_sto_dac_l_mix,
78599081589SCaesar Wang 			   ARRAY_SIZE(rt5616_sto_dac_l_mix)),
786b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
78799081589SCaesar Wang 			   rt5616_sto_dac_r_mix,
78899081589SCaesar Wang 			   ARRAY_SIZE(rt5616_sto_dac_r_mix)),
789b1d15059SBard Liao 
790b1d15059SBard Liao 	/* DACs */
791b1d15059SBard Liao 	SND_SOC_DAPM_DAC("DAC L1", NULL, RT5616_PWR_DIG1,
792b1d15059SBard Liao 			 RT5616_PWR_DAC_L1_BIT, 0),
793b1d15059SBard Liao 	SND_SOC_DAPM_DAC("DAC R1", NULL, RT5616_PWR_DIG1,
794b1d15059SBard Liao 			 RT5616_PWR_DAC_R1_BIT, 0),
795b1d15059SBard Liao 	/* OUT Mixer */
796b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("OUT MIXL", RT5616_PWR_MIXER, RT5616_PWR_OM_L_BIT,
797b1d15059SBard Liao 			   0, rt5616_out_l_mix, ARRAY_SIZE(rt5616_out_l_mix)),
798b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("OUT MIXR", RT5616_PWR_MIXER, RT5616_PWR_OM_R_BIT,
799b1d15059SBard Liao 			   0, rt5616_out_r_mix, ARRAY_SIZE(rt5616_out_r_mix)),
800b1d15059SBard Liao 	/* Output Volume */
801b1d15059SBard Liao 	SND_SOC_DAPM_PGA("OUTVOL L", RT5616_PWR_VOL,
802b1d15059SBard Liao 			 RT5616_PWR_OV_L_BIT, 0, NULL, 0),
803b1d15059SBard Liao 	SND_SOC_DAPM_PGA("OUTVOL R", RT5616_PWR_VOL,
804b1d15059SBard Liao 			 RT5616_PWR_OV_R_BIT, 0, NULL, 0),
805b1d15059SBard Liao 	SND_SOC_DAPM_PGA("HPOVOL L", RT5616_PWR_VOL,
806b1d15059SBard Liao 			 RT5616_PWR_HV_L_BIT, 0, NULL, 0),
807b1d15059SBard Liao 	SND_SOC_DAPM_PGA("HPOVOL R", RT5616_PWR_VOL,
808b1d15059SBard Liao 			 RT5616_PWR_HV_R_BIT, 0, NULL, 0),
809b1d15059SBard Liao 	SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM,
810b1d15059SBard Liao 			 0, 0, NULL, 0),
811b1d15059SBard Liao 	SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM,
812b1d15059SBard Liao 			 0, 0, NULL, 0),
813b1d15059SBard Liao 	SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM,
814b1d15059SBard Liao 			 0, 0, NULL, 0),
815b1d15059SBard Liao 	SND_SOC_DAPM_PGA("INL1", RT5616_PWR_VOL,
816b1d15059SBard Liao 			 RT5616_PWR_IN1_L_BIT, 0, NULL, 0),
817b1d15059SBard Liao 	SND_SOC_DAPM_PGA("INR1", RT5616_PWR_VOL,
818b1d15059SBard Liao 			 RT5616_PWR_IN1_R_BIT, 0, NULL, 0),
819b1d15059SBard Liao 	SND_SOC_DAPM_PGA("INL2", RT5616_PWR_VOL,
820b1d15059SBard Liao 			 RT5616_PWR_IN2_L_BIT, 0, NULL, 0),
821b1d15059SBard Liao 	SND_SOC_DAPM_PGA("INR2", RT5616_PWR_VOL,
822b1d15059SBard Liao 			 RT5616_PWR_IN2_R_BIT, 0, NULL, 0),
823b1d15059SBard Liao 	/* HPO/LOUT/Mono Mixer */
824b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0,
825b1d15059SBard Liao 			   rt5616_hpo_mix, ARRAY_SIZE(rt5616_hpo_mix)),
826b1d15059SBard Liao 	SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0,
827b1d15059SBard Liao 			   rt5616_lout_mix, ARRAY_SIZE(rt5616_lout_mix)),
828b1d15059SBard Liao 
829b1d15059SBard Liao 	SND_SOC_DAPM_PGA_S("HP amp", 1, SND_SOC_NOPM, 0, 0,
830b1d15059SBard Liao 			   rt5616_hp_event, SND_SOC_DAPM_PRE_PMD |
831b1d15059SBard Liao 			   SND_SOC_DAPM_POST_PMU),
832b1d15059SBard Liao 	SND_SOC_DAPM_PGA_S("LOUT amp", 1, SND_SOC_NOPM, 0, 0,
833b1d15059SBard Liao 			   rt5616_lout_event, SND_SOC_DAPM_PRE_PMD |
834b1d15059SBard Liao 			   SND_SOC_DAPM_POST_PMU),
835b1d15059SBard Liao 
836b1d15059SBard Liao 	SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, SND_SOC_NOPM, 0, 0,
837b1d15059SBard Liao 			      rt5616_charge_pump_event, SND_SOC_DAPM_POST_PMU |
838b1d15059SBard Liao 			      SND_SOC_DAPM_PRE_PMD),
839b1d15059SBard Liao 
840b1d15059SBard Liao 	/* Output Lines */
841b1d15059SBard Liao 	SND_SOC_DAPM_OUTPUT("HPOL"),
842b1d15059SBard Liao 	SND_SOC_DAPM_OUTPUT("HPOR"),
843b1d15059SBard Liao 	SND_SOC_DAPM_OUTPUT("LOUTL"),
844b1d15059SBard Liao 	SND_SOC_DAPM_OUTPUT("LOUTR"),
845b1d15059SBard Liao };
846b1d15059SBard Liao 
847b1d15059SBard Liao static const struct snd_soc_dapm_route rt5616_dapm_routes[] = {
848b1d15059SBard Liao 	{"IN1P", NULL, "LDO"},
849b1d15059SBard Liao 	{"IN2P", NULL, "LDO"},
850b1d15059SBard Liao 
851b1d15059SBard Liao 	{"IN1P", NULL, "MIC1"},
852b1d15059SBard Liao 	{"IN2P", NULL, "MIC2"},
853b1d15059SBard Liao 	{"IN2N", NULL, "MIC2"},
854b1d15059SBard Liao 
855b1d15059SBard Liao 	{"BST1", NULL, "IN1P"},
856b1d15059SBard Liao 	{"BST2", NULL, "IN2P"},
857b1d15059SBard Liao 	{"BST2", NULL, "IN2N"},
858b1d15059SBard Liao 	{"BST1", NULL, "micbias1"},
859b1d15059SBard Liao 	{"BST2", NULL, "micbias1"},
860b1d15059SBard Liao 
861b1d15059SBard Liao 	{"INL1 VOL", NULL, "IN2P"},
862b1d15059SBard Liao 	{"INR1 VOL", NULL, "IN2N"},
863b1d15059SBard Liao 
864b1d15059SBard Liao 	{"RECMIXL", "INL1 Switch", "INL1 VOL"},
865b1d15059SBard Liao 	{"RECMIXL", "BST2 Switch", "BST2"},
866b1d15059SBard Liao 	{"RECMIXL", "BST1 Switch", "BST1"},
867b1d15059SBard Liao 
868b1d15059SBard Liao 	{"RECMIXR", "INR1 Switch", "INR1 VOL"},
869b1d15059SBard Liao 	{"RECMIXR", "BST2 Switch", "BST2"},
870b1d15059SBard Liao 	{"RECMIXR", "BST1 Switch", "BST1"},
871b1d15059SBard Liao 
872b1d15059SBard Liao 	{"ADC L", NULL, "RECMIXL"},
873b1d15059SBard Liao 	{"ADC R", NULL, "RECMIXR"},
874b1d15059SBard Liao 
875b1d15059SBard Liao 	{"Stereo1 ADC MIXL", "ADC1 Switch", "ADC L"},
876b1d15059SBard Liao 	{"Stereo1 ADC MIXL", NULL, "stereo1 filter"},
877b1d15059SBard Liao 	{"stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll},
878b1d15059SBard Liao 
879b1d15059SBard Liao 	{"Stereo1 ADC MIXR", "ADC1 Switch", "ADC R"},
880b1d15059SBard Liao 	{"Stereo1 ADC MIXR", NULL, "stereo1 filter"},
881b1d15059SBard Liao 	{"stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll},
882b1d15059SBard Liao 
883b1d15059SBard Liao 	{"IF1 ADC1", NULL, "Stereo1 ADC MIXL"},
884b1d15059SBard Liao 	{"IF1 ADC1", NULL, "Stereo1 ADC MIXR"},
885b1d15059SBard Liao 	{"IF1 ADC1", NULL, "I2S1"},
886b1d15059SBard Liao 
887b1d15059SBard Liao 	{"AIF1TX", NULL, "IF1 ADC1"},
888b1d15059SBard Liao 
889b1d15059SBard Liao 	{"IF1 DAC", NULL, "AIF1RX"},
890b1d15059SBard Liao 	{"IF1 DAC", NULL, "I2S1"},
891b1d15059SBard Liao 
892b1d15059SBard Liao 	{"IF1 DAC1 L", NULL, "IF1 DAC"},
893b1d15059SBard Liao 	{"IF1 DAC1 R", NULL, "IF1 DAC"},
894b1d15059SBard Liao 
895b1d15059SBard Liao 	{"DAC MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"},
896b1d15059SBard Liao 	{"DAC MIXL", "INF1 Switch", "IF1 DAC1 L"},
897b1d15059SBard Liao 	{"DAC MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"},
898b1d15059SBard Liao 	{"DAC MIXR", "INF1 Switch", "IF1 DAC1 R"},
899b1d15059SBard Liao 
900b1d15059SBard Liao 	{"Audio DSP", NULL, "DAC MIXL"},
901b1d15059SBard Liao 	{"Audio DSP", NULL, "DAC MIXR"},
902b1d15059SBard Liao 
903b1d15059SBard Liao 	{"Stereo DAC MIXL", "DAC L1 Switch", "Audio DSP"},
904b1d15059SBard Liao 	{"Stereo DAC MIXL", "DAC R1 Switch", "DAC MIXR"},
905b1d15059SBard Liao 	{"Stereo DAC MIXL", NULL, "Stero1 DAC Power"},
906b1d15059SBard Liao 	{"Stereo DAC MIXR", "DAC R1 Switch", "Audio DSP"},
907b1d15059SBard Liao 	{"Stereo DAC MIXR", "DAC L1 Switch", "DAC MIXL"},
908b1d15059SBard Liao 	{"Stereo DAC MIXR", NULL, "Stero1 DAC Power"},
909b1d15059SBard Liao 
910b1d15059SBard Liao 	{"DAC L1", NULL, "Stereo DAC MIXL"},
911b1d15059SBard Liao 	{"DAC L1", NULL, "PLL1", is_sys_clk_from_pll},
912b1d15059SBard Liao 	{"DAC R1", NULL, "Stereo DAC MIXR"},
913b1d15059SBard Liao 	{"DAC R1", NULL, "PLL1", is_sys_clk_from_pll},
914b1d15059SBard Liao 
915b1d15059SBard Liao 	{"OUT MIXL", "BST1 Switch", "BST1"},
916b1d15059SBard Liao 	{"OUT MIXL", "BST2 Switch", "BST2"},
917b1d15059SBard Liao 	{"OUT MIXL", "INL1 Switch", "INL1 VOL"},
918b1d15059SBard Liao 	{"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
919b1d15059SBard Liao 	{"OUT MIXL", "DAC L1 Switch", "DAC L1"},
920b1d15059SBard Liao 
921b1d15059SBard Liao 	{"OUT MIXR", "BST2 Switch", "BST2"},
922b1d15059SBard Liao 	{"OUT MIXR", "BST1 Switch", "BST1"},
923b1d15059SBard Liao 	{"OUT MIXR", "INR1 Switch", "INR1 VOL"},
924b1d15059SBard Liao 	{"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
925b1d15059SBard Liao 	{"OUT MIXR", "DAC R1 Switch", "DAC R1"},
926b1d15059SBard Liao 
927b1d15059SBard Liao 	{"HPOVOL L", NULL, "OUT MIXL"},
928b1d15059SBard Liao 	{"HPOVOL R", NULL, "OUT MIXR"},
929b1d15059SBard Liao 	{"OUTVOL L", NULL, "OUT MIXL"},
930b1d15059SBard Liao 	{"OUTVOL R", NULL, "OUT MIXR"},
931b1d15059SBard Liao 
932b1d15059SBard Liao 	{"DAC 1", NULL, "DAC L1"},
933b1d15059SBard Liao 	{"DAC 1", NULL, "DAC R1"},
934b1d15059SBard Liao 	{"HPOVOL", NULL, "HPOVOL L"},
935b1d15059SBard Liao 	{"HPOVOL", NULL, "HPOVOL R"},
936b1d15059SBard Liao 	{"HPO MIX", "DAC1 Switch", "DAC 1"},
937b1d15059SBard Liao 	{"HPO MIX", "HPVOL Switch", "HPOVOL"},
938b1d15059SBard Liao 
939b1d15059SBard Liao 	{"LOUT MIX", "DAC L1 Switch", "DAC L1"},
940b1d15059SBard Liao 	{"LOUT MIX", "DAC R1 Switch", "DAC R1"},
941b1d15059SBard Liao 	{"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
942b1d15059SBard Liao 	{"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
943b1d15059SBard Liao 
944b1d15059SBard Liao 	{"HP amp", NULL, "HPO MIX"},
945b1d15059SBard Liao 	{"HP amp", NULL, "Charge Pump"},
946b1d15059SBard Liao 	{"HPOL", NULL, "HP amp"},
947b1d15059SBard Liao 	{"HPOR", NULL, "HP amp"},
948b1d15059SBard Liao 
949b1d15059SBard Liao 	{"LOUT amp", NULL, "LOUT MIX"},
950b1d15059SBard Liao 	{"LOUT amp", NULL, "Charge Pump"},
951b1d15059SBard Liao 	{"LOUTL", NULL, "LOUT amp"},
952b1d15059SBard Liao 	{"LOUTR", NULL, "LOUT amp"},
953b1d15059SBard Liao 
954b1d15059SBard Liao };
955b1d15059SBard Liao 
rt5616_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)956b1d15059SBard Liao static int rt5616_hw_params(struct snd_pcm_substream *substream,
95799081589SCaesar Wang 			    struct snd_pcm_hw_params *params,
95899081589SCaesar Wang 			    struct snd_soc_dai *dai)
959b1d15059SBard Liao {
96001f8902fSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
96101f8902fSKuninori Morimoto 	struct rt5616_priv *rt5616 = snd_soc_component_get_drvdata(component);
962b1d15059SBard Liao 	unsigned int val_len = 0, val_clk, mask_clk;
963b1d15059SBard Liao 	int pre_div, bclk_ms, frame_size;
964b1d15059SBard Liao 
965b1d15059SBard Liao 	rt5616->lrck[dai->id] = params_rate(params);
966b1d15059SBard Liao 
967b1d15059SBard Liao 	pre_div = rl6231_get_clk_info(rt5616->sysclk, rt5616->lrck[dai->id]);
968b1d15059SBard Liao 
969b1d15059SBard Liao 	if (pre_div < 0) {
97001f8902fSKuninori Morimoto 		dev_err(component->dev, "Unsupported clock setting\n");
971b1d15059SBard Liao 		return -EINVAL;
972b1d15059SBard Liao 	}
973b1d15059SBard Liao 	frame_size = snd_soc_params_to_frame_size(params);
974b1d15059SBard Liao 	if (frame_size < 0) {
97501f8902fSKuninori Morimoto 		dev_err(component->dev, "Unsupported frame size: %d\n", frame_size);
976b1d15059SBard Liao 		return -EINVAL;
977b1d15059SBard Liao 	}
978b1d15059SBard Liao 	bclk_ms = frame_size > 32 ? 1 : 0;
979b1d15059SBard Liao 	rt5616->bclk[dai->id] = rt5616->lrck[dai->id] * (32 << bclk_ms);
980b1d15059SBard Liao 
981b1d15059SBard Liao 	dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
982b1d15059SBard Liao 		rt5616->bclk[dai->id], rt5616->lrck[dai->id]);
983b1d15059SBard Liao 	dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
984b1d15059SBard Liao 		bclk_ms, pre_div, dai->id);
985b1d15059SBard Liao 
986b1d15059SBard Liao 	switch (params_format(params)) {
987b1d15059SBard Liao 	case SNDRV_PCM_FORMAT_S16_LE:
988b1d15059SBard Liao 		break;
989b1d15059SBard Liao 	case SNDRV_PCM_FORMAT_S20_3LE:
990b1d15059SBard Liao 		val_len |= RT5616_I2S_DL_20;
991b1d15059SBard Liao 		break;
992b1d15059SBard Liao 	case SNDRV_PCM_FORMAT_S24_LE:
993b1d15059SBard Liao 		val_len |= RT5616_I2S_DL_24;
994b1d15059SBard Liao 		break;
995b1d15059SBard Liao 	case SNDRV_PCM_FORMAT_S8:
996b1d15059SBard Liao 		val_len |= RT5616_I2S_DL_8;
997b1d15059SBard Liao 		break;
998b1d15059SBard Liao 	default:
999b1d15059SBard Liao 		return -EINVAL;
1000b1d15059SBard Liao 	}
1001b1d15059SBard Liao 
1002b1d15059SBard Liao 	mask_clk = RT5616_I2S_PD1_MASK;
1003b1d15059SBard Liao 	val_clk = pre_div << RT5616_I2S_PD1_SFT;
100401f8902fSKuninori Morimoto 	snd_soc_component_update_bits(component, RT5616_I2S1_SDP,
1005b1d15059SBard Liao 			    RT5616_I2S_DL_MASK, val_len);
100601f8902fSKuninori Morimoto 	snd_soc_component_update_bits(component, RT5616_ADDA_CLK1, mask_clk, val_clk);
1007b1d15059SBard Liao 
1008b1d15059SBard Liao 	return 0;
1009b1d15059SBard Liao }
1010b1d15059SBard Liao 
rt5616_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)1011b1d15059SBard Liao static int rt5616_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1012b1d15059SBard Liao {
101301f8902fSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
101401f8902fSKuninori Morimoto 	struct rt5616_priv *rt5616 = snd_soc_component_get_drvdata(component);
1015b1d15059SBard Liao 	unsigned int reg_val = 0;
1016b1d15059SBard Liao 
1017b1d15059SBard Liao 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1018b1d15059SBard Liao 	case SND_SOC_DAIFMT_CBM_CFM:
1019b1d15059SBard Liao 		rt5616->master[dai->id] = 1;
1020b1d15059SBard Liao 		break;
1021b1d15059SBard Liao 	case SND_SOC_DAIFMT_CBS_CFS:
1022b1d15059SBard Liao 		reg_val |= RT5616_I2S_MS_S;
1023b1d15059SBard Liao 		rt5616->master[dai->id] = 0;
1024b1d15059SBard Liao 		break;
1025b1d15059SBard Liao 	default:
1026b1d15059SBard Liao 		return -EINVAL;
1027b1d15059SBard Liao 	}
1028b1d15059SBard Liao 
1029b1d15059SBard Liao 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1030b1d15059SBard Liao 	case SND_SOC_DAIFMT_NB_NF:
1031b1d15059SBard Liao 		break;
1032b1d15059SBard Liao 	case SND_SOC_DAIFMT_IB_NF:
1033b1d15059SBard Liao 		reg_val |= RT5616_I2S_BP_INV;
1034b1d15059SBard Liao 		break;
1035b1d15059SBard Liao 	default:
1036b1d15059SBard Liao 		return -EINVAL;
1037b1d15059SBard Liao 	}
1038b1d15059SBard Liao 
1039b1d15059SBard Liao 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1040b1d15059SBard Liao 	case SND_SOC_DAIFMT_I2S:
1041b1d15059SBard Liao 		break;
1042b1d15059SBard Liao 	case SND_SOC_DAIFMT_LEFT_J:
1043b1d15059SBard Liao 		reg_val |= RT5616_I2S_DF_LEFT;
1044b1d15059SBard Liao 		break;
1045b1d15059SBard Liao 	case SND_SOC_DAIFMT_DSP_A:
1046b1d15059SBard Liao 		reg_val |= RT5616_I2S_DF_PCM_A;
1047b1d15059SBard Liao 		break;
1048b1d15059SBard Liao 	case SND_SOC_DAIFMT_DSP_B:
1049b1d15059SBard Liao 		reg_val |= RT5616_I2S_DF_PCM_B;
1050b1d15059SBard Liao 		break;
1051b1d15059SBard Liao 	default:
1052b1d15059SBard Liao 		return -EINVAL;
1053b1d15059SBard Liao 	}
1054b1d15059SBard Liao 
105501f8902fSKuninori Morimoto 	snd_soc_component_update_bits(component, RT5616_I2S1_SDP,
1056b1d15059SBard Liao 			    RT5616_I2S_MS_MASK | RT5616_I2S_BP_MASK |
1057b1d15059SBard Liao 			    RT5616_I2S_DF_MASK, reg_val);
1058b1d15059SBard Liao 
1059b1d15059SBard Liao 	return 0;
1060b1d15059SBard Liao }
1061b1d15059SBard Liao 
rt5616_set_dai_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)1062b1d15059SBard Liao static int rt5616_set_dai_sysclk(struct snd_soc_dai *dai,
1063b1d15059SBard Liao 				 int clk_id, unsigned int freq, int dir)
1064b1d15059SBard Liao {
106501f8902fSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
106601f8902fSKuninori Morimoto 	struct rt5616_priv *rt5616 = snd_soc_component_get_drvdata(component);
1067b1d15059SBard Liao 	unsigned int reg_val = 0;
1068b1d15059SBard Liao 
1069b1d15059SBard Liao 	if (freq == rt5616->sysclk && clk_id == rt5616->sysclk_src)
1070b1d15059SBard Liao 		return 0;
1071b1d15059SBard Liao 
1072b1d15059SBard Liao 	switch (clk_id) {
1073b1d15059SBard Liao 	case RT5616_SCLK_S_MCLK:
1074b1d15059SBard Liao 		reg_val |= RT5616_SCLK_SRC_MCLK;
1075b1d15059SBard Liao 		break;
1076b1d15059SBard Liao 	case RT5616_SCLK_S_PLL1:
1077b1d15059SBard Liao 		reg_val |= RT5616_SCLK_SRC_PLL1;
1078b1d15059SBard Liao 		break;
1079b1d15059SBard Liao 	default:
108001f8902fSKuninori Morimoto 		dev_err(component->dev, "Invalid clock id (%d)\n", clk_id);
1081b1d15059SBard Liao 		return -EINVAL;
1082b1d15059SBard Liao 	}
108399081589SCaesar Wang 
108401f8902fSKuninori Morimoto 	snd_soc_component_update_bits(component, RT5616_GLB_CLK,
1085b1d15059SBard Liao 			    RT5616_SCLK_SRC_MASK, reg_val);
1086b1d15059SBard Liao 	rt5616->sysclk = freq;
1087b1d15059SBard Liao 	rt5616->sysclk_src = clk_id;
1088b1d15059SBard Liao 
1089b1d15059SBard Liao 	dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
1090b1d15059SBard Liao 
1091b1d15059SBard Liao 	return 0;
1092b1d15059SBard Liao }
1093b1d15059SBard Liao 
rt5616_set_dai_pll(struct snd_soc_dai * dai,int pll_id,int source,unsigned int freq_in,unsigned int freq_out)1094b1d15059SBard Liao static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
1095b1d15059SBard Liao 			      unsigned int freq_in, unsigned int freq_out)
1096b1d15059SBard Liao {
109701f8902fSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
109801f8902fSKuninori Morimoto 	struct rt5616_priv *rt5616 = snd_soc_component_get_drvdata(component);
1099b1d15059SBard Liao 	struct rl6231_pll_code pll_code;
1100b1d15059SBard Liao 	int ret;
1101b1d15059SBard Liao 
1102b1d15059SBard Liao 	if (source == rt5616->pll_src && freq_in == rt5616->pll_in &&
1103b1d15059SBard Liao 	    freq_out == rt5616->pll_out)
1104b1d15059SBard Liao 		return 0;
1105b1d15059SBard Liao 
1106b1d15059SBard Liao 	if (!freq_in || !freq_out) {
110701f8902fSKuninori Morimoto 		dev_dbg(component->dev, "PLL disabled\n");
1108b1d15059SBard Liao 
1109b1d15059SBard Liao 		rt5616->pll_in = 0;
1110b1d15059SBard Liao 		rt5616->pll_out = 0;
111101f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_GLB_CLK,
111299081589SCaesar Wang 				    RT5616_SCLK_SRC_MASK,
111399081589SCaesar Wang 				    RT5616_SCLK_SRC_MCLK);
1114b1d15059SBard Liao 		return 0;
1115b1d15059SBard Liao 	}
1116b1d15059SBard Liao 
1117b1d15059SBard Liao 	switch (source) {
1118b1d15059SBard Liao 	case RT5616_PLL1_S_MCLK:
111901f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_GLB_CLK,
112099081589SCaesar Wang 				    RT5616_PLL1_SRC_MASK,
112199081589SCaesar Wang 				    RT5616_PLL1_SRC_MCLK);
1122b1d15059SBard Liao 		break;
1123b1d15059SBard Liao 	case RT5616_PLL1_S_BCLK1:
1124b1d15059SBard Liao 	case RT5616_PLL1_S_BCLK2:
112501f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_GLB_CLK,
112699081589SCaesar Wang 				    RT5616_PLL1_SRC_MASK,
112799081589SCaesar Wang 				    RT5616_PLL1_SRC_BCLK1);
1128b1d15059SBard Liao 		break;
1129b1d15059SBard Liao 	default:
113001f8902fSKuninori Morimoto 		dev_err(component->dev, "Unknown PLL source %d\n", source);
1131b1d15059SBard Liao 		return -EINVAL;
1132b1d15059SBard Liao 	}
1133b1d15059SBard Liao 
1134b1d15059SBard Liao 	ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
1135b1d15059SBard Liao 	if (ret < 0) {
1136a4db95b2SColin Ian King 		dev_err(component->dev, "Unsupported input clock %d\n", freq_in);
1137b1d15059SBard Liao 		return ret;
1138b1d15059SBard Liao 	}
1139b1d15059SBard Liao 
114001f8902fSKuninori Morimoto 	dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n",
1141b1d15059SBard Liao 		pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
1142b1d15059SBard Liao 		pll_code.n_code, pll_code.k_code);
1143b1d15059SBard Liao 
114401f8902fSKuninori Morimoto 	snd_soc_component_write(component, RT5616_PLL_CTRL1,
1145b1d15059SBard Liao 		      pll_code.n_code << RT5616_PLL_N_SFT | pll_code.k_code);
114601f8902fSKuninori Morimoto 	snd_soc_component_write(component, RT5616_PLL_CTRL2,
114799081589SCaesar Wang 		      (pll_code.m_bp ? 0 : pll_code.m_code) <<
114899081589SCaesar Wang 		      RT5616_PLL_M_SFT |
1149b1d15059SBard Liao 		      pll_code.m_bp << RT5616_PLL_M_BP_SFT);
1150b1d15059SBard Liao 
1151b1d15059SBard Liao 	rt5616->pll_in = freq_in;
1152b1d15059SBard Liao 	rt5616->pll_out = freq_out;
1153b1d15059SBard Liao 	rt5616->pll_src = source;
1154b1d15059SBard Liao 
1155b1d15059SBard Liao 	return 0;
1156b1d15059SBard Liao }
1157b1d15059SBard Liao 
rt5616_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)115801f8902fSKuninori Morimoto static int rt5616_set_bias_level(struct snd_soc_component *component,
1159b1d15059SBard Liao 				 enum snd_soc_bias_level level)
1160b1d15059SBard Liao {
116101f8902fSKuninori Morimoto 	struct rt5616_priv *rt5616 = snd_soc_component_get_drvdata(component);
116276d3204eSCaesar Wang 	int ret;
116376d3204eSCaesar Wang 
1164b1d15059SBard Liao 	switch (level) {
116576d3204eSCaesar Wang 
116676d3204eSCaesar Wang 	case SND_SOC_BIAS_ON:
116776d3204eSCaesar Wang 		break;
116876d3204eSCaesar Wang 
116976d3204eSCaesar Wang 	case SND_SOC_BIAS_PREPARE:
117076d3204eSCaesar Wang 		/*
117176d3204eSCaesar Wang 		 * SND_SOC_BIAS_PREPARE is called while preparing for a
117276d3204eSCaesar Wang 		 * transition to ON or away from ON. If current bias_level
117376d3204eSCaesar Wang 		 * is SND_SOC_BIAS_ON, then it is preparing for a transition
117476d3204eSCaesar Wang 		 * away from ON. Disable the clock in that case, otherwise
117576d3204eSCaesar Wang 		 * enable it.
117676d3204eSCaesar Wang 		 */
117776d3204eSCaesar Wang 		if (IS_ERR(rt5616->mclk))
117876d3204eSCaesar Wang 			break;
117976d3204eSCaesar Wang 
118001f8902fSKuninori Morimoto 		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON) {
118176d3204eSCaesar Wang 			clk_disable_unprepare(rt5616->mclk);
118276d3204eSCaesar Wang 		} else {
118376d3204eSCaesar Wang 			ret = clk_prepare_enable(rt5616->mclk);
118476d3204eSCaesar Wang 			if (ret)
118576d3204eSCaesar Wang 				return ret;
118676d3204eSCaesar Wang 		}
118776d3204eSCaesar Wang 		break;
118876d3204eSCaesar Wang 
1189b1d15059SBard Liao 	case SND_SOC_BIAS_STANDBY:
119001f8902fSKuninori Morimoto 		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
119101f8902fSKuninori Morimoto 			snd_soc_component_update_bits(component, RT5616_PWR_ANLG1,
1192b1d15059SBard Liao 					    RT5616_PWR_VREF1 | RT5616_PWR_MB |
1193b1d15059SBard Liao 					    RT5616_PWR_BG | RT5616_PWR_VREF2,
1194b1d15059SBard Liao 					    RT5616_PWR_VREF1 | RT5616_PWR_MB |
1195b1d15059SBard Liao 					    RT5616_PWR_BG | RT5616_PWR_VREF2);
1196b1d15059SBard Liao 			mdelay(10);
119701f8902fSKuninori Morimoto 			snd_soc_component_update_bits(component, RT5616_PWR_ANLG1,
1198b1d15059SBard Liao 					    RT5616_PWR_FV1 | RT5616_PWR_FV2,
1199b1d15059SBard Liao 					    RT5616_PWR_FV1 | RT5616_PWR_FV2);
120001f8902fSKuninori Morimoto 			snd_soc_component_update_bits(component, RT5616_D_MISC,
120199081589SCaesar Wang 					    RT5616_D_GATE_EN,
120299081589SCaesar Wang 					    RT5616_D_GATE_EN);
1203b1d15059SBard Liao 		}
1204b1d15059SBard Liao 		break;
1205b1d15059SBard Liao 
1206b1d15059SBard Liao 	case SND_SOC_BIAS_OFF:
120701f8902fSKuninori Morimoto 		snd_soc_component_update_bits(component, RT5616_D_MISC, RT5616_D_GATE_EN, 0);
120801f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PWR_DIG1, 0x0000);
120901f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PWR_DIG2, 0x0000);
121001f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PWR_VOL, 0x0000);
121101f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PWR_MIXER, 0x0000);
121201f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PWR_ANLG1, 0x0000);
121301f8902fSKuninori Morimoto 		snd_soc_component_write(component, RT5616_PWR_ANLG2, 0x0000);
1214b1d15059SBard Liao 		break;
1215b1d15059SBard Liao 
1216b1d15059SBard Liao 	default:
1217b1d15059SBard Liao 		break;
1218b1d15059SBard Liao 	}
1219b1d15059SBard Liao 
1220b1d15059SBard Liao 	return 0;
1221b1d15059SBard Liao }
1222b1d15059SBard Liao 
rt5616_probe(struct snd_soc_component * component)122301f8902fSKuninori Morimoto static int rt5616_probe(struct snd_soc_component *component)
1224b1d15059SBard Liao {
122501f8902fSKuninori Morimoto 	struct rt5616_priv *rt5616 = snd_soc_component_get_drvdata(component);
1226b1d15059SBard Liao 
122776d3204eSCaesar Wang 	/* Check if MCLK provided */
122801f8902fSKuninori Morimoto 	rt5616->mclk = devm_clk_get(component->dev, "mclk");
122976d3204eSCaesar Wang 	if (PTR_ERR(rt5616->mclk) == -EPROBE_DEFER)
123076d3204eSCaesar Wang 		return -EPROBE_DEFER;
123176d3204eSCaesar Wang 
123201f8902fSKuninori Morimoto 	rt5616->component = component;
1233b1d15059SBard Liao 
1234b1d15059SBard Liao 	return 0;
1235b1d15059SBard Liao }
1236b1d15059SBard Liao 
1237b1d15059SBard Liao #ifdef CONFIG_PM
rt5616_suspend(struct snd_soc_component * component)123801f8902fSKuninori Morimoto static int rt5616_suspend(struct snd_soc_component *component)
1239b1d15059SBard Liao {
124001f8902fSKuninori Morimoto 	struct rt5616_priv *rt5616 = snd_soc_component_get_drvdata(component);
1241b1d15059SBard Liao 
1242b1d15059SBard Liao 	regcache_cache_only(rt5616->regmap, true);
1243b1d15059SBard Liao 	regcache_mark_dirty(rt5616->regmap);
1244b1d15059SBard Liao 
1245b1d15059SBard Liao 	return 0;
1246b1d15059SBard Liao }
1247b1d15059SBard Liao 
rt5616_resume(struct snd_soc_component * component)124801f8902fSKuninori Morimoto static int rt5616_resume(struct snd_soc_component *component)
1249b1d15059SBard Liao {
125001f8902fSKuninori Morimoto 	struct rt5616_priv *rt5616 = snd_soc_component_get_drvdata(component);
1251b1d15059SBard Liao 
1252b1d15059SBard Liao 	regcache_cache_only(rt5616->regmap, false);
1253b1d15059SBard Liao 	regcache_sync(rt5616->regmap);
1254b1d15059SBard Liao 	return 0;
1255b1d15059SBard Liao }
1256b1d15059SBard Liao #else
1257b1d15059SBard Liao #define rt5616_suspend NULL
1258b1d15059SBard Liao #define rt5616_resume NULL
1259b1d15059SBard Liao #endif
1260b1d15059SBard Liao 
12614e26ad80SXing Zheng #define RT5616_STEREO_RATES SNDRV_PCM_RATE_8000_192000
1262b1d15059SBard Liao #define RT5616_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1263b1d15059SBard Liao 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
1264b1d15059SBard Liao 
1265eb59d73cSArvind Yadav static const struct snd_soc_dai_ops rt5616_aif_dai_ops = {
1266b1d15059SBard Liao 	.hw_params = rt5616_hw_params,
1267b1d15059SBard Liao 	.set_fmt = rt5616_set_dai_fmt,
1268b1d15059SBard Liao 	.set_sysclk = rt5616_set_dai_sysclk,
1269b1d15059SBard Liao 	.set_pll = rt5616_set_dai_pll,
1270b1d15059SBard Liao };
1271b1d15059SBard Liao 
1272b74e7a26STakashi Sakamoto static struct snd_soc_dai_driver rt5616_dai[] = {
1273b1d15059SBard Liao 	{
1274b1d15059SBard Liao 		.name = "rt5616-aif1",
1275b1d15059SBard Liao 		.id = RT5616_AIF1,
1276b1d15059SBard Liao 		.playback = {
1277b1d15059SBard Liao 			.stream_name = "AIF1 Playback",
1278b1d15059SBard Liao 			.channels_min = 1,
1279b1d15059SBard Liao 			.channels_max = 2,
1280b1d15059SBard Liao 			.rates = RT5616_STEREO_RATES,
1281b1d15059SBard Liao 			.formats = RT5616_FORMATS,
1282b1d15059SBard Liao 		},
1283b1d15059SBard Liao 		.capture = {
1284b1d15059SBard Liao 			.stream_name = "AIF1 Capture",
1285b1d15059SBard Liao 			.channels_min = 1,
1286b1d15059SBard Liao 			.channels_max = 2,
1287b1d15059SBard Liao 			.rates = RT5616_STEREO_RATES,
1288b1d15059SBard Liao 			.formats = RT5616_FORMATS,
1289b1d15059SBard Liao 		},
1290b1d15059SBard Liao 		.ops = &rt5616_aif_dai_ops,
1291b1d15059SBard Liao 	},
1292b1d15059SBard Liao };
1293b1d15059SBard Liao 
129401f8902fSKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_rt5616 = {
1295b1d15059SBard Liao 	.probe			= rt5616_probe,
1296b1d15059SBard Liao 	.suspend		= rt5616_suspend,
1297b1d15059SBard Liao 	.resume			= rt5616_resume,
1298b1d15059SBard Liao 	.set_bias_level		= rt5616_set_bias_level,
1299b1d15059SBard Liao 	.controls		= rt5616_snd_controls,
1300b1d15059SBard Liao 	.num_controls		= ARRAY_SIZE(rt5616_snd_controls),
1301b1d15059SBard Liao 	.dapm_widgets		= rt5616_dapm_widgets,
1302b1d15059SBard Liao 	.num_dapm_widgets	= ARRAY_SIZE(rt5616_dapm_widgets),
1303b1d15059SBard Liao 	.dapm_routes		= rt5616_dapm_routes,
1304b1d15059SBard Liao 	.num_dapm_routes	= ARRAY_SIZE(rt5616_dapm_routes),
130501f8902fSKuninori Morimoto 	.use_pmdown_time	= 1,
130601f8902fSKuninori Morimoto 	.endianness		= 1,
1307b1d15059SBard Liao };
1308b1d15059SBard Liao 
1309b1d15059SBard Liao static const struct regmap_config rt5616_regmap = {
1310b1d15059SBard Liao 	.reg_bits = 8,
1311b1d15059SBard Liao 	.val_bits = 16,
13121c96a2f6SDavid Frey 	.use_single_read = true,
13131c96a2f6SDavid Frey 	.use_single_write = true,
1314b1d15059SBard Liao 	.max_register = RT5616_DEVICE_ID + 1 + (ARRAY_SIZE(rt5616_ranges) *
1315b1d15059SBard Liao 					       RT5616_PR_SPACING),
1316b1d15059SBard Liao 	.volatile_reg = rt5616_volatile_register,
1317b1d15059SBard Liao 	.readable_reg = rt5616_readable_register,
1318*eef0d85dSMark Brown 	.cache_type = REGCACHE_MAPLE,
1319b1d15059SBard Liao 	.reg_defaults = rt5616_reg,
1320b1d15059SBard Liao 	.num_reg_defaults = ARRAY_SIZE(rt5616_reg),
1321b1d15059SBard Liao 	.ranges = rt5616_ranges,
1322b1d15059SBard Liao 	.num_ranges = ARRAY_SIZE(rt5616_ranges),
1323b1d15059SBard Liao };
1324b1d15059SBard Liao 
1325b1d15059SBard Liao static const struct i2c_device_id rt5616_i2c_id[] = {
1326b1d15059SBard Liao 	{ "rt5616", 0 },
1327b1d15059SBard Liao 	{ }
1328b1d15059SBard Liao };
1329b1d15059SBard Liao MODULE_DEVICE_TABLE(i2c, rt5616_i2c_id);
1330b1d15059SBard Liao 
1331e17ff2deSCaesar Wang #if defined(CONFIG_OF)
1332e17ff2deSCaesar Wang static const struct of_device_id rt5616_of_match[] = {
1333e17ff2deSCaesar Wang 	{ .compatible = "realtek,rt5616", },
1334e17ff2deSCaesar Wang 	{},
1335e17ff2deSCaesar Wang };
1336e17ff2deSCaesar Wang MODULE_DEVICE_TABLE(of, rt5616_of_match);
1337e17ff2deSCaesar Wang #endif
1338e17ff2deSCaesar Wang 
rt5616_i2c_probe(struct i2c_client * i2c)133935b88858SStephen Kitt static int rt5616_i2c_probe(struct i2c_client *i2c)
1340b1d15059SBard Liao {
1341b1d15059SBard Liao 	struct rt5616_priv *rt5616;
1342b1d15059SBard Liao 	unsigned int val;
1343b1d15059SBard Liao 	int ret;
1344b1d15059SBard Liao 
1345b1d15059SBard Liao 	rt5616 = devm_kzalloc(&i2c->dev, sizeof(struct rt5616_priv),
1346b1d15059SBard Liao 			      GFP_KERNEL);
134799081589SCaesar Wang 	if (!rt5616)
1348b1d15059SBard Liao 		return -ENOMEM;
1349b1d15059SBard Liao 
1350b1d15059SBard Liao 	i2c_set_clientdata(i2c, rt5616);
1351b1d15059SBard Liao 
1352b1d15059SBard Liao 	rt5616->regmap = devm_regmap_init_i2c(i2c, &rt5616_regmap);
1353b1d15059SBard Liao 	if (IS_ERR(rt5616->regmap)) {
1354b1d15059SBard Liao 		ret = PTR_ERR(rt5616->regmap);
1355b1d15059SBard Liao 		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
1356b1d15059SBard Liao 			ret);
1357b1d15059SBard Liao 		return ret;
1358b1d15059SBard Liao 	}
1359b1d15059SBard Liao 
1360b1d15059SBard Liao 	regmap_read(rt5616->regmap, RT5616_DEVICE_ID, &val);
1361b1d15059SBard Liao 	if (val != 0x6281) {
1362b1d15059SBard Liao 		dev_err(&i2c->dev,
1363b1d15059SBard Liao 			"Device with ID register %#x is not rt5616\n",
1364b1d15059SBard Liao 			val);
136536ddd489SAxel Lin 		return -ENODEV;
1366b1d15059SBard Liao 	}
1367b1d15059SBard Liao 	regmap_write(rt5616->regmap, RT5616_RESET, 0);
1368b1d15059SBard Liao 	regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
1369b1d15059SBard Liao 			   RT5616_PWR_VREF1 | RT5616_PWR_MB |
1370b1d15059SBard Liao 			   RT5616_PWR_BG | RT5616_PWR_VREF2,
1371b1d15059SBard Liao 			   RT5616_PWR_VREF1 | RT5616_PWR_MB |
1372b1d15059SBard Liao 			   RT5616_PWR_BG | RT5616_PWR_VREF2);
1373b1d15059SBard Liao 	mdelay(10);
1374b1d15059SBard Liao 	regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
1375b1d15059SBard Liao 			   RT5616_PWR_FV1 | RT5616_PWR_FV2,
1376b1d15059SBard Liao 			   RT5616_PWR_FV1 | RT5616_PWR_FV2);
1377b1d15059SBard Liao 
1378b1d15059SBard Liao 	ret = regmap_register_patch(rt5616->regmap, init_list,
1379b1d15059SBard Liao 				    ARRAY_SIZE(init_list));
1380b1d15059SBard Liao 	if (ret != 0)
1381b1d15059SBard Liao 		dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
1382b1d15059SBard Liao 
1383b1d15059SBard Liao 	regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
1384b1d15059SBard Liao 			   RT5616_PWR_LDO_DVO_MASK, RT5616_PWR_LDO_DVO_1_2V);
1385b1d15059SBard Liao 
138601f8902fSKuninori Morimoto 	return devm_snd_soc_register_component(&i2c->dev,
138701f8902fSKuninori Morimoto 				      &soc_component_dev_rt5616,
1388b1d15059SBard Liao 				      rt5616_dai, ARRAY_SIZE(rt5616_dai));
1389b1d15059SBard Liao }
1390b1d15059SBard Liao 
rt5616_i2c_remove(struct i2c_client * i2c)1391ed5c2f5fSUwe Kleine-König static void rt5616_i2c_remove(struct i2c_client *i2c)
1392ed5c2f5fSUwe Kleine-König {}
1393b1d15059SBard Liao 
rt5616_i2c_shutdown(struct i2c_client * client)1394b1d15059SBard Liao static void rt5616_i2c_shutdown(struct i2c_client *client)
1395b1d15059SBard Liao {
1396b1d15059SBard Liao 	struct rt5616_priv *rt5616 = i2c_get_clientdata(client);
1397b1d15059SBard Liao 
1398b1d15059SBard Liao 	regmap_write(rt5616->regmap, RT5616_HP_VOL, 0xc8c8);
1399b1d15059SBard Liao 	regmap_write(rt5616->regmap, RT5616_LOUT_CTRL1, 0xc8c8);
1400b1d15059SBard Liao }
1401b1d15059SBard Liao 
1402b1d15059SBard Liao static struct i2c_driver rt5616_i2c_driver = {
1403b1d15059SBard Liao 	.driver = {
1404b1d15059SBard Liao 		.name = "rt5616",
1405e17ff2deSCaesar Wang 		.of_match_table = of_match_ptr(rt5616_of_match),
1406b1d15059SBard Liao 	},
14079abcd240SUwe Kleine-König 	.probe = rt5616_i2c_probe,
1408b1d15059SBard Liao 	.remove = rt5616_i2c_remove,
1409b1d15059SBard Liao 	.shutdown = rt5616_i2c_shutdown,
1410b1d15059SBard Liao 	.id_table = rt5616_i2c_id,
1411b1d15059SBard Liao };
1412b1d15059SBard Liao module_i2c_driver(rt5616_i2c_driver);
1413b1d15059SBard Liao 
1414b1d15059SBard Liao MODULE_DESCRIPTION("ASoC RT5616 driver");
1415b1d15059SBard Liao MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
1416b1d15059SBard Liao MODULE_LICENSE("GPL");
1417