xref: /OK3568_Linux_fs/kernel/sound/soc/codecs/rt715.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * rt715.c -- rt715 ALSA SoC audio driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright(c) 2019 Realtek Semiconductor Corp.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * ALC715 ASoC Codec Driver based Intel Dummy SdW codec driver
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/delay.h>
15*4882a593Smuzhiyun #include <linux/i2c.h>
16*4882a593Smuzhiyun #include <linux/pm_runtime.h>
17*4882a593Smuzhiyun #include <linux/pm.h>
18*4882a593Smuzhiyun #include <linux/soundwire/sdw.h>
19*4882a593Smuzhiyun #include <linux/gpio.h>
20*4882a593Smuzhiyun #include <linux/regmap.h>
21*4882a593Smuzhiyun #include <linux/slab.h>
22*4882a593Smuzhiyun #include <linux/platform_device.h>
23*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
24*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
25*4882a593Smuzhiyun #include <linux/of.h>
26*4882a593Smuzhiyun #include <linux/of_gpio.h>
27*4882a593Smuzhiyun #include <linux/of_device.h>
28*4882a593Smuzhiyun #include <sound/core.h>
29*4882a593Smuzhiyun #include <sound/pcm.h>
30*4882a593Smuzhiyun #include <sound/pcm_params.h>
31*4882a593Smuzhiyun #include <sound/soc.h>
32*4882a593Smuzhiyun #include <sound/soc-dapm.h>
33*4882a593Smuzhiyun #include <sound/initval.h>
34*4882a593Smuzhiyun #include <sound/tlv.h>
35*4882a593Smuzhiyun #include <sound/hda_verbs.h>
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #include "rt715.h"
38*4882a593Smuzhiyun 
rt715_index_write(struct regmap * regmap,unsigned int reg,unsigned int value)39*4882a593Smuzhiyun static int rt715_index_write(struct regmap *regmap, unsigned int reg,
40*4882a593Smuzhiyun 		unsigned int value)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	int ret;
43*4882a593Smuzhiyun 	unsigned int addr = ((RT715_PRIV_INDEX_W_H) << 8) | reg;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	ret = regmap_write(regmap, addr, value);
46*4882a593Smuzhiyun 	if (ret < 0) {
47*4882a593Smuzhiyun 		pr_err("Failed to set private value: %08x <= %04x %d\n", ret,
48*4882a593Smuzhiyun 			addr, value);
49*4882a593Smuzhiyun 	}
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	return ret;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
rt715_get_gain(struct rt715_priv * rt715,unsigned int addr_h,unsigned int addr_l,unsigned int val_h,unsigned int * r_val,unsigned int * l_val)54*4882a593Smuzhiyun static void rt715_get_gain(struct rt715_priv *rt715, unsigned int addr_h,
55*4882a593Smuzhiyun 				unsigned int addr_l, unsigned int val_h,
56*4882a593Smuzhiyun 				unsigned int *r_val, unsigned int *l_val)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	int ret;
59*4882a593Smuzhiyun 	/* R Channel */
60*4882a593Smuzhiyun 	*r_val = (val_h << 8);
61*4882a593Smuzhiyun 	ret = regmap_read(rt715->regmap, addr_l, r_val);
62*4882a593Smuzhiyun 	if (ret < 0)
63*4882a593Smuzhiyun 		pr_err("Failed to get R channel gain.\n");
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	/* L Channel */
66*4882a593Smuzhiyun 	val_h |= 0x20;
67*4882a593Smuzhiyun 	*l_val = (val_h << 8);
68*4882a593Smuzhiyun 	ret = regmap_read(rt715->regmap, addr_h, l_val);
69*4882a593Smuzhiyun 	if (ret < 0)
70*4882a593Smuzhiyun 		pr_err("Failed to get L channel gain.\n");
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /* For Verb-Set Amplifier Gain (Verb ID = 3h) */
rt715_set_amp_gain_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)74*4882a593Smuzhiyun static int rt715_set_amp_gain_put(struct snd_kcontrol *kcontrol,
75*4882a593Smuzhiyun 					struct snd_ctl_elem_value *ucontrol)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
78*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm =
79*4882a593Smuzhiyun 		snd_soc_component_get_dapm(component);
80*4882a593Smuzhiyun 	struct soc_mixer_control *mc =
81*4882a593Smuzhiyun 		(struct soc_mixer_control *)kcontrol->private_value;
82*4882a593Smuzhiyun 	struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component);
83*4882a593Smuzhiyun 	unsigned int addr_h, addr_l, val_h, val_ll, val_lr;
84*4882a593Smuzhiyun 	unsigned int read_ll, read_rl;
85*4882a593Smuzhiyun 	int i;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	/* Can't use update bit function, so read the original value first */
88*4882a593Smuzhiyun 	addr_h = mc->reg;
89*4882a593Smuzhiyun 	addr_l = mc->rreg;
90*4882a593Smuzhiyun 	if (mc->shift == RT715_DIR_OUT_SFT) /* output */
91*4882a593Smuzhiyun 		val_h = 0x80;
92*4882a593Smuzhiyun 	else /* input */
93*4882a593Smuzhiyun 		val_h = 0x0;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll);
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	/* L Channel */
98*4882a593Smuzhiyun 	if (mc->invert) {
99*4882a593Smuzhiyun 		/* for mute */
100*4882a593Smuzhiyun 		val_ll = (mc->max - ucontrol->value.integer.value[0]) << 7;
101*4882a593Smuzhiyun 		/* keep gain */
102*4882a593Smuzhiyun 		read_ll = read_ll & 0x7f;
103*4882a593Smuzhiyun 		val_ll |= read_ll;
104*4882a593Smuzhiyun 	} else {
105*4882a593Smuzhiyun 		/* for gain */
106*4882a593Smuzhiyun 		val_ll = ((ucontrol->value.integer.value[0]) & 0x7f);
107*4882a593Smuzhiyun 		if (val_ll > mc->max)
108*4882a593Smuzhiyun 			val_ll = mc->max;
109*4882a593Smuzhiyun 		/* keep mute status */
110*4882a593Smuzhiyun 		read_ll = read_ll & 0x80;
111*4882a593Smuzhiyun 		val_ll |= read_ll;
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/* R Channel */
115*4882a593Smuzhiyun 	if (mc->invert) {
116*4882a593Smuzhiyun 		regmap_write(rt715->regmap,
117*4882a593Smuzhiyun 			     RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
118*4882a593Smuzhiyun 		/* for mute */
119*4882a593Smuzhiyun 		val_lr = (mc->max - ucontrol->value.integer.value[1]) << 7;
120*4882a593Smuzhiyun 		/* keep gain */
121*4882a593Smuzhiyun 		read_rl = read_rl & 0x7f;
122*4882a593Smuzhiyun 		val_lr |= read_rl;
123*4882a593Smuzhiyun 	} else {
124*4882a593Smuzhiyun 		/* for gain */
125*4882a593Smuzhiyun 		val_lr = ((ucontrol->value.integer.value[1]) & 0x7f);
126*4882a593Smuzhiyun 		if (val_lr > mc->max)
127*4882a593Smuzhiyun 			val_lr = mc->max;
128*4882a593Smuzhiyun 		/* keep mute status */
129*4882a593Smuzhiyun 		read_rl = read_rl & 0x80;
130*4882a593Smuzhiyun 		val_lr |= read_rl;
131*4882a593Smuzhiyun 	}
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	for (i = 0; i < 3; i++) { /* retry 3 times at most */
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 		if (val_ll == val_lr) {
136*4882a593Smuzhiyun 			/* Set both L/R channels at the same time */
137*4882a593Smuzhiyun 			val_h = (1 << mc->shift) | (3 << 4);
138*4882a593Smuzhiyun 			regmap_write(rt715->regmap, addr_h,
139*4882a593Smuzhiyun 				(val_h << 8 | val_ll));
140*4882a593Smuzhiyun 			regmap_write(rt715->regmap, addr_l,
141*4882a593Smuzhiyun 				(val_h << 8 | val_ll));
142*4882a593Smuzhiyun 		} else {
143*4882a593Smuzhiyun 			/* Lch*/
144*4882a593Smuzhiyun 			val_h = (1 << mc->shift) | (1 << 5);
145*4882a593Smuzhiyun 			regmap_write(rt715->regmap, addr_h,
146*4882a593Smuzhiyun 				(val_h << 8 | val_ll));
147*4882a593Smuzhiyun 			/* Rch */
148*4882a593Smuzhiyun 			val_h = (1 << mc->shift) | (1 << 4);
149*4882a593Smuzhiyun 			regmap_write(rt715->regmap, addr_l,
150*4882a593Smuzhiyun 				(val_h << 8 | val_lr));
151*4882a593Smuzhiyun 		}
152*4882a593Smuzhiyun 		/* check result */
153*4882a593Smuzhiyun 		if (mc->shift == RT715_DIR_OUT_SFT) /* output */
154*4882a593Smuzhiyun 			val_h = 0x80;
155*4882a593Smuzhiyun 		else /* input */
156*4882a593Smuzhiyun 			val_h = 0x0;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 		rt715_get_gain(rt715, addr_h, addr_l, val_h,
159*4882a593Smuzhiyun 			       &read_rl, &read_ll);
160*4882a593Smuzhiyun 		if (read_rl == val_lr && read_ll == val_ll)
161*4882a593Smuzhiyun 			break;
162*4882a593Smuzhiyun 	}
163*4882a593Smuzhiyun 	/* D0:power on state, D3: power saving mode */
164*4882a593Smuzhiyun 	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
165*4882a593Smuzhiyun 		regmap_write(rt715->regmap,
166*4882a593Smuzhiyun 				RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
167*4882a593Smuzhiyun 	return 0;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
rt715_set_amp_gain_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)170*4882a593Smuzhiyun static int rt715_set_amp_gain_get(struct snd_kcontrol *kcontrol,
171*4882a593Smuzhiyun 				  struct snd_ctl_elem_value *ucontrol)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
174*4882a593Smuzhiyun 	struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component);
175*4882a593Smuzhiyun 	struct soc_mixer_control *mc =
176*4882a593Smuzhiyun 		(struct soc_mixer_control *)kcontrol->private_value;
177*4882a593Smuzhiyun 	unsigned int addr_h, addr_l, val_h;
178*4882a593Smuzhiyun 	unsigned int read_ll, read_rl;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	addr_h = mc->reg;
181*4882a593Smuzhiyun 	addr_l = mc->rreg;
182*4882a593Smuzhiyun 	if (mc->shift == RT715_DIR_OUT_SFT) /* output */
183*4882a593Smuzhiyun 		val_h = 0x80;
184*4882a593Smuzhiyun 	else /* input */
185*4882a593Smuzhiyun 		val_h = 0x0;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	if (mc->invert) {
190*4882a593Smuzhiyun 		/* for mute status */
191*4882a593Smuzhiyun 		read_ll = !((read_ll & 0x80) >> RT715_MUTE_SFT);
192*4882a593Smuzhiyun 		read_rl = !((read_rl & 0x80) >> RT715_MUTE_SFT);
193*4882a593Smuzhiyun 	} else {
194*4882a593Smuzhiyun 		/* for gain */
195*4882a593Smuzhiyun 		read_ll = read_ll & 0x7f;
196*4882a593Smuzhiyun 		read_rl = read_rl & 0x7f;
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = read_ll;
199*4882a593Smuzhiyun 	ucontrol->value.integer.value[1] = read_rl;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	return 0;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
205*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun #define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\
208*4882a593Smuzhiyun 	 xhandler_get, xhandler_put) \
209*4882a593Smuzhiyun {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
210*4882a593Smuzhiyun 	.info = snd_soc_info_volsw, \
211*4882a593Smuzhiyun 	.get = xhandler_get, .put = xhandler_put, \
212*4882a593Smuzhiyun 	.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
213*4882a593Smuzhiyun 					    xmax, xinvert) }
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun static const struct snd_kcontrol_new rt715_snd_controls[] = {
216*4882a593Smuzhiyun 	/* Capture switch */
217*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT("ADC 07 Capture Switch", RT715_SET_GAIN_MIC_ADC_H,
218*4882a593Smuzhiyun 			RT715_SET_GAIN_MIC_ADC_L, RT715_DIR_IN_SFT, 1, 1,
219*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put),
220*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT("ADC 08 Capture Switch", RT715_SET_GAIN_LINE_ADC_H,
221*4882a593Smuzhiyun 			RT715_SET_GAIN_LINE_ADC_L, RT715_DIR_IN_SFT, 1, 1,
222*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put),
223*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT("ADC 09 Capture Switch", RT715_SET_GAIN_MIX_ADC_H,
224*4882a593Smuzhiyun 			RT715_SET_GAIN_MIX_ADC_L, RT715_DIR_IN_SFT, 1, 1,
225*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put),
226*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT("ADC 27 Capture Switch", RT715_SET_GAIN_MIX_ADC2_H,
227*4882a593Smuzhiyun 			RT715_SET_GAIN_MIX_ADC2_L, RT715_DIR_IN_SFT, 1, 1,
228*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put),
229*4882a593Smuzhiyun 	/* Volume Control */
230*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("ADC 07 Capture Volume", RT715_SET_GAIN_MIC_ADC_H,
231*4882a593Smuzhiyun 			RT715_SET_GAIN_MIC_ADC_L, RT715_DIR_IN_SFT, 0x3f, 0,
232*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
233*4882a593Smuzhiyun 			in_vol_tlv),
234*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("ADC 08 Capture Volume", RT715_SET_GAIN_LINE_ADC_H,
235*4882a593Smuzhiyun 			RT715_SET_GAIN_LINE_ADC_L, RT715_DIR_IN_SFT, 0x3f, 0,
236*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
237*4882a593Smuzhiyun 			in_vol_tlv),
238*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("ADC 09 Capture Volume", RT715_SET_GAIN_MIX_ADC_H,
239*4882a593Smuzhiyun 			RT715_SET_GAIN_MIX_ADC_L, RT715_DIR_IN_SFT, 0x3f, 0,
240*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
241*4882a593Smuzhiyun 			in_vol_tlv),
242*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("ADC 27 Capture Volume", RT715_SET_GAIN_MIX_ADC2_H,
243*4882a593Smuzhiyun 			RT715_SET_GAIN_MIX_ADC2_L, RT715_DIR_IN_SFT, 0x3f, 0,
244*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
245*4882a593Smuzhiyun 			in_vol_tlv),
246*4882a593Smuzhiyun 	/* MIC Boost Control */
247*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("DMIC1 Boost", RT715_SET_GAIN_DMIC1_H,
248*4882a593Smuzhiyun 			RT715_SET_GAIN_DMIC1_L, RT715_DIR_IN_SFT, 3, 0,
249*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
250*4882a593Smuzhiyun 			mic_vol_tlv),
251*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("DMIC2 Boost", RT715_SET_GAIN_DMIC2_H,
252*4882a593Smuzhiyun 			RT715_SET_GAIN_DMIC2_L, RT715_DIR_IN_SFT, 3, 0,
253*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
254*4882a593Smuzhiyun 			mic_vol_tlv),
255*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("DMIC3 Boost", RT715_SET_GAIN_DMIC3_H,
256*4882a593Smuzhiyun 			RT715_SET_GAIN_DMIC3_L, RT715_DIR_IN_SFT, 3, 0,
257*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
258*4882a593Smuzhiyun 			mic_vol_tlv),
259*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("DMIC4 Boost", RT715_SET_GAIN_DMIC4_H,
260*4882a593Smuzhiyun 			RT715_SET_GAIN_DMIC4_L, RT715_DIR_IN_SFT, 3, 0,
261*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
262*4882a593Smuzhiyun 			mic_vol_tlv),
263*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("MIC1 Boost", RT715_SET_GAIN_MIC1_H,
264*4882a593Smuzhiyun 			RT715_SET_GAIN_MIC1_L, RT715_DIR_IN_SFT, 3, 0,
265*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
266*4882a593Smuzhiyun 			mic_vol_tlv),
267*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("MIC2 Boost", RT715_SET_GAIN_MIC2_H,
268*4882a593Smuzhiyun 			RT715_SET_GAIN_MIC2_L, RT715_DIR_IN_SFT, 3, 0,
269*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
270*4882a593Smuzhiyun 			mic_vol_tlv),
271*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("LINE1 Boost", RT715_SET_GAIN_LINE1_H,
272*4882a593Smuzhiyun 			RT715_SET_GAIN_LINE1_L, RT715_DIR_IN_SFT, 3, 0,
273*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
274*4882a593Smuzhiyun 			mic_vol_tlv),
275*4882a593Smuzhiyun 	SOC_DOUBLE_R_EXT_TLV("LINE2 Boost", RT715_SET_GAIN_LINE2_H,
276*4882a593Smuzhiyun 			RT715_SET_GAIN_LINE2_L, RT715_DIR_IN_SFT, 3, 0,
277*4882a593Smuzhiyun 			rt715_set_amp_gain_get, rt715_set_amp_gain_put,
278*4882a593Smuzhiyun 			mic_vol_tlv),
279*4882a593Smuzhiyun };
280*4882a593Smuzhiyun 
rt715_mux_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)281*4882a593Smuzhiyun static int rt715_mux_get(struct snd_kcontrol *kcontrol,
282*4882a593Smuzhiyun 			struct snd_ctl_elem_value *ucontrol)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun 	struct snd_soc_component *component =
285*4882a593Smuzhiyun 		snd_soc_dapm_kcontrol_component(kcontrol);
286*4882a593Smuzhiyun 	struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component);
287*4882a593Smuzhiyun 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
288*4882a593Smuzhiyun 	unsigned int reg, val;
289*4882a593Smuzhiyun 	int ret;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	/* nid = e->reg, vid = 0xf01 */
292*4882a593Smuzhiyun 	reg = RT715_VERB_SET_CONNECT_SEL | e->reg;
293*4882a593Smuzhiyun 	ret = regmap_read(rt715->regmap, reg, &val);
294*4882a593Smuzhiyun 	if (ret < 0) {
295*4882a593Smuzhiyun 		dev_err(component->dev, "%s: sdw read failed: %d\n",
296*4882a593Smuzhiyun 			__func__, ret);
297*4882a593Smuzhiyun 		return ret;
298*4882a593Smuzhiyun 	}
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	/*
301*4882a593Smuzhiyun 	 * The first two indices of ADC Mux 24/25 are routed to the same
302*4882a593Smuzhiyun 	 * hardware source. ie, ADC Mux 24 0/1 will both connect to MIC2.
303*4882a593Smuzhiyun 	 * To have a unique set of inputs, we skip the index1 of the muxes.
304*4882a593Smuzhiyun 	 */
305*4882a593Smuzhiyun 	if ((e->reg == RT715_MUX_IN3 || e->reg == RT715_MUX_IN4) && (val > 0))
306*4882a593Smuzhiyun 		val -= 1;
307*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = val;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	return 0;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
rt715_mux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)312*4882a593Smuzhiyun static int rt715_mux_put(struct snd_kcontrol *kcontrol,
313*4882a593Smuzhiyun 			struct snd_ctl_elem_value *ucontrol)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	struct snd_soc_component *component =
316*4882a593Smuzhiyun 		snd_soc_dapm_kcontrol_component(kcontrol);
317*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm =
318*4882a593Smuzhiyun 				snd_soc_dapm_kcontrol_dapm(kcontrol);
319*4882a593Smuzhiyun 	struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component);
320*4882a593Smuzhiyun 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
321*4882a593Smuzhiyun 	unsigned int *item = ucontrol->value.enumerated.item;
322*4882a593Smuzhiyun 	unsigned int val, val2 = 0, change, reg;
323*4882a593Smuzhiyun 	int ret;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	if (item[0] >= e->items)
326*4882a593Smuzhiyun 		return -EINVAL;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	/* Verb ID = 0x701h, nid = e->reg */
329*4882a593Smuzhiyun 	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	reg = RT715_VERB_SET_CONNECT_SEL | e->reg;
332*4882a593Smuzhiyun 	ret = regmap_read(rt715->regmap, reg, &val2);
333*4882a593Smuzhiyun 	if (ret < 0) {
334*4882a593Smuzhiyun 		dev_err(component->dev, "%s: sdw read failed: %d\n",
335*4882a593Smuzhiyun 			__func__, ret);
336*4882a593Smuzhiyun 		return ret;
337*4882a593Smuzhiyun 	}
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	if (val == val2)
340*4882a593Smuzhiyun 		change = 0;
341*4882a593Smuzhiyun 	else
342*4882a593Smuzhiyun 		change = 1;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	if (change) {
345*4882a593Smuzhiyun 		reg = RT715_VERB_SET_CONNECT_SEL | e->reg;
346*4882a593Smuzhiyun 		regmap_write(rt715->regmap, reg, val);
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	snd_soc_dapm_mux_update_power(dapm, kcontrol,
350*4882a593Smuzhiyun 						item[0], e, NULL);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	return change;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun static const char * const adc_22_23_mux_text[] = {
356*4882a593Smuzhiyun 	"MIC1",
357*4882a593Smuzhiyun 	"MIC2",
358*4882a593Smuzhiyun 	"LINE1",
359*4882a593Smuzhiyun 	"LINE2",
360*4882a593Smuzhiyun 	"DMIC1",
361*4882a593Smuzhiyun 	"DMIC2",
362*4882a593Smuzhiyun 	"DMIC3",
363*4882a593Smuzhiyun 	"DMIC4",
364*4882a593Smuzhiyun };
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun /*
367*4882a593Smuzhiyun  * Due to mux design for nid 24 (MUX_IN3)/25 (MUX_IN4), connection index 0 and
368*4882a593Smuzhiyun  * 1 will be connected to the same dmic source, therefore we skip index 1 to
369*4882a593Smuzhiyun  * avoid misunderstanding on usage of dapm routing.
370*4882a593Smuzhiyun  */
371*4882a593Smuzhiyun static const unsigned int rt715_adc_24_25_values[] = {
372*4882a593Smuzhiyun 	0,
373*4882a593Smuzhiyun 	2,
374*4882a593Smuzhiyun 	3,
375*4882a593Smuzhiyun 	4,
376*4882a593Smuzhiyun 	5,
377*4882a593Smuzhiyun };
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun static const char * const adc_24_mux_text[] = {
380*4882a593Smuzhiyun 	"MIC2",
381*4882a593Smuzhiyun 	"DMIC1",
382*4882a593Smuzhiyun 	"DMIC2",
383*4882a593Smuzhiyun 	"DMIC3",
384*4882a593Smuzhiyun 	"DMIC4",
385*4882a593Smuzhiyun };
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun static const char * const adc_25_mux_text[] = {
388*4882a593Smuzhiyun 	"MIC1",
389*4882a593Smuzhiyun 	"DMIC1",
390*4882a593Smuzhiyun 	"DMIC2",
391*4882a593Smuzhiyun 	"DMIC3",
392*4882a593Smuzhiyun 	"DMIC4",
393*4882a593Smuzhiyun };
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(
396*4882a593Smuzhiyun 	rt715_adc22_enum, RT715_MUX_IN1, 0, adc_22_23_mux_text);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(
399*4882a593Smuzhiyun 	rt715_adc23_enum, RT715_MUX_IN2, 0, adc_22_23_mux_text);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(rt715_adc24_enum,
402*4882a593Smuzhiyun 	RT715_MUX_IN3, 0, 0xf,
403*4882a593Smuzhiyun 	adc_24_mux_text, rt715_adc_24_25_values);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(rt715_adc25_enum,
406*4882a593Smuzhiyun 	RT715_MUX_IN4, 0, 0xf,
407*4882a593Smuzhiyun 	adc_25_mux_text, rt715_adc_24_25_values);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun static const struct snd_kcontrol_new rt715_adc22_mux =
410*4882a593Smuzhiyun 	SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt715_adc22_enum,
411*4882a593Smuzhiyun 			rt715_mux_get, rt715_mux_put);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun static const struct snd_kcontrol_new rt715_adc23_mux =
414*4882a593Smuzhiyun 	SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt715_adc23_enum,
415*4882a593Smuzhiyun 			rt715_mux_get, rt715_mux_put);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun static const struct snd_kcontrol_new rt715_adc24_mux =
418*4882a593Smuzhiyun 	SOC_DAPM_ENUM_EXT("ADC 24 Mux", rt715_adc24_enum,
419*4882a593Smuzhiyun 			rt715_mux_get, rt715_mux_put);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun static const struct snd_kcontrol_new rt715_adc25_mux =
422*4882a593Smuzhiyun 	SOC_DAPM_ENUM_EXT("ADC 25 Mux", rt715_adc25_enum,
423*4882a593Smuzhiyun 			rt715_mux_get, rt715_mux_put);
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun static const struct snd_soc_dapm_widget rt715_dapm_widgets[] = {
426*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("DMIC1"),
427*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("DMIC2"),
428*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("DMIC3"),
429*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("DMIC4"),
430*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("MIC1"),
431*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("MIC2"),
432*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("LINE1"),
433*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("LINE2"),
434*4882a593Smuzhiyun 	SND_SOC_DAPM_ADC("ADC 07", NULL, RT715_SET_STREAMID_MIC_ADC, 4, 0),
435*4882a593Smuzhiyun 	SND_SOC_DAPM_ADC("ADC 08", NULL, RT715_SET_STREAMID_LINE_ADC, 4, 0),
436*4882a593Smuzhiyun 	SND_SOC_DAPM_ADC("ADC 09", NULL, RT715_SET_STREAMID_MIX_ADC, 4, 0),
437*4882a593Smuzhiyun 	SND_SOC_DAPM_ADC("ADC 27", NULL, RT715_SET_STREAMID_MIX_ADC2, 4, 0),
438*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0,
439*4882a593Smuzhiyun 		&rt715_adc22_mux),
440*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0,
441*4882a593Smuzhiyun 		&rt715_adc23_mux),
442*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("ADC 24 Mux", SND_SOC_NOPM, 0, 0,
443*4882a593Smuzhiyun 		&rt715_adc24_mux),
444*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("ADC 25 Mux", SND_SOC_NOPM, 0, 0,
445*4882a593Smuzhiyun 		&rt715_adc25_mux),
446*4882a593Smuzhiyun 	SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0),
447*4882a593Smuzhiyun 	SND_SOC_DAPM_AIF_OUT("DP6TX", "DP6 Capture", 0, SND_SOC_NOPM, 0, 0),
448*4882a593Smuzhiyun };
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun static const struct snd_soc_dapm_route rt715_audio_map[] = {
451*4882a593Smuzhiyun 	{"DP6TX", NULL, "ADC 09"},
452*4882a593Smuzhiyun 	{"DP6TX", NULL, "ADC 08"},
453*4882a593Smuzhiyun 	{"DP4TX", NULL, "ADC 07"},
454*4882a593Smuzhiyun 	{"DP4TX", NULL, "ADC 27"},
455*4882a593Smuzhiyun 	{"ADC 09", NULL, "ADC 22 Mux"},
456*4882a593Smuzhiyun 	{"ADC 08", NULL, "ADC 23 Mux"},
457*4882a593Smuzhiyun 	{"ADC 07", NULL, "ADC 24 Mux"},
458*4882a593Smuzhiyun 	{"ADC 27", NULL, "ADC 25 Mux"},
459*4882a593Smuzhiyun 	{"ADC 22 Mux", "MIC1", "MIC1"},
460*4882a593Smuzhiyun 	{"ADC 22 Mux", "MIC2", "MIC2"},
461*4882a593Smuzhiyun 	{"ADC 22 Mux", "LINE1", "LINE1"},
462*4882a593Smuzhiyun 	{"ADC 22 Mux", "LINE2", "LINE2"},
463*4882a593Smuzhiyun 	{"ADC 22 Mux", "DMIC1", "DMIC1"},
464*4882a593Smuzhiyun 	{"ADC 22 Mux", "DMIC2", "DMIC2"},
465*4882a593Smuzhiyun 	{"ADC 22 Mux", "DMIC3", "DMIC3"},
466*4882a593Smuzhiyun 	{"ADC 22 Mux", "DMIC4", "DMIC4"},
467*4882a593Smuzhiyun 	{"ADC 23 Mux", "MIC1", "MIC1"},
468*4882a593Smuzhiyun 	{"ADC 23 Mux", "MIC2", "MIC2"},
469*4882a593Smuzhiyun 	{"ADC 23 Mux", "LINE1", "LINE1"},
470*4882a593Smuzhiyun 	{"ADC 23 Mux", "LINE2", "LINE2"},
471*4882a593Smuzhiyun 	{"ADC 23 Mux", "DMIC1", "DMIC1"},
472*4882a593Smuzhiyun 	{"ADC 23 Mux", "DMIC2", "DMIC2"},
473*4882a593Smuzhiyun 	{"ADC 23 Mux", "DMIC3", "DMIC3"},
474*4882a593Smuzhiyun 	{"ADC 23 Mux", "DMIC4", "DMIC4"},
475*4882a593Smuzhiyun 	{"ADC 24 Mux", "MIC2", "MIC2"},
476*4882a593Smuzhiyun 	{"ADC 24 Mux", "DMIC1", "DMIC1"},
477*4882a593Smuzhiyun 	{"ADC 24 Mux", "DMIC2", "DMIC2"},
478*4882a593Smuzhiyun 	{"ADC 24 Mux", "DMIC3", "DMIC3"},
479*4882a593Smuzhiyun 	{"ADC 24 Mux", "DMIC4", "DMIC4"},
480*4882a593Smuzhiyun 	{"ADC 25 Mux", "MIC1", "MIC1"},
481*4882a593Smuzhiyun 	{"ADC 25 Mux", "DMIC1", "DMIC1"},
482*4882a593Smuzhiyun 	{"ADC 25 Mux", "DMIC2", "DMIC2"},
483*4882a593Smuzhiyun 	{"ADC 25 Mux", "DMIC3", "DMIC3"},
484*4882a593Smuzhiyun 	{"ADC 25 Mux", "DMIC4", "DMIC4"},
485*4882a593Smuzhiyun };
486*4882a593Smuzhiyun 
rt715_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)487*4882a593Smuzhiyun static int rt715_set_bias_level(struct snd_soc_component *component,
488*4882a593Smuzhiyun 				enum snd_soc_bias_level level)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm =
491*4882a593Smuzhiyun 		snd_soc_component_get_dapm(component);
492*4882a593Smuzhiyun 	struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component);
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	switch (level) {
495*4882a593Smuzhiyun 	case SND_SOC_BIAS_PREPARE:
496*4882a593Smuzhiyun 		if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
497*4882a593Smuzhiyun 			regmap_write(rt715->regmap,
498*4882a593Smuzhiyun 						RT715_SET_AUDIO_POWER_STATE,
499*4882a593Smuzhiyun 						AC_PWRST_D0);
500*4882a593Smuzhiyun 			msleep(RT715_POWER_UP_DELAY_MS);
501*4882a593Smuzhiyun 		}
502*4882a593Smuzhiyun 		break;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	case SND_SOC_BIAS_STANDBY:
505*4882a593Smuzhiyun 		regmap_write(rt715->regmap,
506*4882a593Smuzhiyun 					RT715_SET_AUDIO_POWER_STATE,
507*4882a593Smuzhiyun 					AC_PWRST_D3);
508*4882a593Smuzhiyun 		break;
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	default:
511*4882a593Smuzhiyun 		break;
512*4882a593Smuzhiyun 	}
513*4882a593Smuzhiyun 	dapm->bias_level = level;
514*4882a593Smuzhiyun 	return 0;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_codec_dev_rt715 = {
518*4882a593Smuzhiyun 	.set_bias_level = rt715_set_bias_level,
519*4882a593Smuzhiyun 	.controls = rt715_snd_controls,
520*4882a593Smuzhiyun 	.num_controls = ARRAY_SIZE(rt715_snd_controls),
521*4882a593Smuzhiyun 	.dapm_widgets = rt715_dapm_widgets,
522*4882a593Smuzhiyun 	.num_dapm_widgets = ARRAY_SIZE(rt715_dapm_widgets),
523*4882a593Smuzhiyun 	.dapm_routes = rt715_audio_map,
524*4882a593Smuzhiyun 	.num_dapm_routes = ARRAY_SIZE(rt715_audio_map),
525*4882a593Smuzhiyun };
526*4882a593Smuzhiyun 
rt715_set_sdw_stream(struct snd_soc_dai * dai,void * sdw_stream,int direction)527*4882a593Smuzhiyun static int rt715_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
528*4882a593Smuzhiyun 				int direction)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	struct sdw_stream_data *stream;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	if (!sdw_stream)
534*4882a593Smuzhiyun 		return 0;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
537*4882a593Smuzhiyun 	if (!stream)
538*4882a593Smuzhiyun 		return -ENOMEM;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	/* Use tx_mask or rx_mask to configure stream tag and set dma_data */
543*4882a593Smuzhiyun 	if (direction == SNDRV_PCM_STREAM_PLAYBACK)
544*4882a593Smuzhiyun 		dai->playback_dma_data = stream;
545*4882a593Smuzhiyun 	else
546*4882a593Smuzhiyun 		dai->capture_dma_data = stream;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	return 0;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun 
rt715_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)551*4882a593Smuzhiyun static void rt715_shutdown(struct snd_pcm_substream *substream,
552*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun 	struct sdw_stream_data *stream;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	stream = snd_soc_dai_get_dma_data(dai, substream);
558*4882a593Smuzhiyun 	snd_soc_dai_set_dma_data(dai, substream, NULL);
559*4882a593Smuzhiyun 	kfree(stream);
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun 
rt715_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)562*4882a593Smuzhiyun static int rt715_pcm_hw_params(struct snd_pcm_substream *substream,
563*4882a593Smuzhiyun 				struct snd_pcm_hw_params *params,
564*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
567*4882a593Smuzhiyun 	struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component);
568*4882a593Smuzhiyun 	struct sdw_stream_config stream_config;
569*4882a593Smuzhiyun 	struct sdw_port_config port_config;
570*4882a593Smuzhiyun 	enum sdw_data_direction direction;
571*4882a593Smuzhiyun 	struct sdw_stream_data *stream;
572*4882a593Smuzhiyun 	int retval, port, num_channels;
573*4882a593Smuzhiyun 	unsigned int val = 0;
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	stream = snd_soc_dai_get_dma_data(dai, substream);
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	if (!stream)
578*4882a593Smuzhiyun 		return -EINVAL;
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	if (!rt715->slave)
581*4882a593Smuzhiyun 		return -EINVAL;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	switch (dai->id) {
584*4882a593Smuzhiyun 	case RT715_AIF1:
585*4882a593Smuzhiyun 		direction = SDW_DATA_DIR_TX;
586*4882a593Smuzhiyun 		port = 6;
587*4882a593Smuzhiyun 		rt715_index_write(rt715->regmap, RT715_SDW_INPUT_SEL, 0xa500);
588*4882a593Smuzhiyun 		break;
589*4882a593Smuzhiyun 	case RT715_AIF2:
590*4882a593Smuzhiyun 		direction = SDW_DATA_DIR_TX;
591*4882a593Smuzhiyun 		port = 4;
592*4882a593Smuzhiyun 		rt715_index_write(rt715->regmap, RT715_SDW_INPUT_SEL, 0xa000);
593*4882a593Smuzhiyun 		break;
594*4882a593Smuzhiyun 	default:
595*4882a593Smuzhiyun 		dev_err(component->dev, "Invalid DAI id %d\n", dai->id);
596*4882a593Smuzhiyun 		return -EINVAL;
597*4882a593Smuzhiyun 	}
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	stream_config.frame_rate =  params_rate(params);
600*4882a593Smuzhiyun 	stream_config.ch_count = params_channels(params);
601*4882a593Smuzhiyun 	stream_config.bps = snd_pcm_format_width(params_format(params));
602*4882a593Smuzhiyun 	stream_config.direction = direction;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	num_channels = params_channels(params);
605*4882a593Smuzhiyun 	port_config.ch_mask = (1 << (num_channels)) - 1;
606*4882a593Smuzhiyun 	port_config.num = port;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	retval = sdw_stream_add_slave(rt715->slave, &stream_config,
609*4882a593Smuzhiyun 					&port_config, 1, stream->sdw_stream);
610*4882a593Smuzhiyun 	if (retval) {
611*4882a593Smuzhiyun 		dev_err(dai->dev, "Unable to configure port\n");
612*4882a593Smuzhiyun 		return retval;
613*4882a593Smuzhiyun 	}
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	switch (params_rate(params)) {
616*4882a593Smuzhiyun 	/* bit 14 0:48K 1:44.1K */
617*4882a593Smuzhiyun 	/* bit 15 Stream Type 0:PCM 1:Non-PCM, should always be PCM */
618*4882a593Smuzhiyun 	case 44100:
619*4882a593Smuzhiyun 		val |= 0x40 << 8;
620*4882a593Smuzhiyun 		break;
621*4882a593Smuzhiyun 	case 48000:
622*4882a593Smuzhiyun 		val |= 0x0 << 8;
623*4882a593Smuzhiyun 		break;
624*4882a593Smuzhiyun 	default:
625*4882a593Smuzhiyun 		dev_err(component->dev, "Unsupported sample rate %d\n",
626*4882a593Smuzhiyun 			params_rate(params));
627*4882a593Smuzhiyun 		return -EINVAL;
628*4882a593Smuzhiyun 	}
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	if (params_channels(params) <= 16) {
631*4882a593Smuzhiyun 		/* bit 3:0 Number of Channel */
632*4882a593Smuzhiyun 		val |= (params_channels(params) - 1);
633*4882a593Smuzhiyun 	} else {
634*4882a593Smuzhiyun 		dev_err(component->dev, "Unsupported channels %d\n",
635*4882a593Smuzhiyun 			params_channels(params));
636*4882a593Smuzhiyun 		return -EINVAL;
637*4882a593Smuzhiyun 	}
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	switch (params_width(params)) {
640*4882a593Smuzhiyun 	/* bit 6:4 Bits per Sample */
641*4882a593Smuzhiyun 	case 8:
642*4882a593Smuzhiyun 		break;
643*4882a593Smuzhiyun 	case 16:
644*4882a593Smuzhiyun 		val |= (0x1 << 4);
645*4882a593Smuzhiyun 		break;
646*4882a593Smuzhiyun 	case 20:
647*4882a593Smuzhiyun 		val |= (0x2 << 4);
648*4882a593Smuzhiyun 		break;
649*4882a593Smuzhiyun 	case 24:
650*4882a593Smuzhiyun 		val |= (0x3 << 4);
651*4882a593Smuzhiyun 		break;
652*4882a593Smuzhiyun 	case 32:
653*4882a593Smuzhiyun 		val |= (0x4 << 4);
654*4882a593Smuzhiyun 		break;
655*4882a593Smuzhiyun 	default:
656*4882a593Smuzhiyun 		return -EINVAL;
657*4882a593Smuzhiyun 	}
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_MIC_ADC_FORMAT_H, val);
660*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_MIC_LINE_FORMAT_H, val);
661*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_MIX_ADC_FORMAT_H, val);
662*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_MIX_ADC2_FORMAT_H, val);
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	return retval;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun 
rt715_pcm_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)667*4882a593Smuzhiyun static int rt715_pcm_hw_free(struct snd_pcm_substream *substream,
668*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
671*4882a593Smuzhiyun 	struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component);
672*4882a593Smuzhiyun 	struct sdw_stream_data *stream =
673*4882a593Smuzhiyun 		snd_soc_dai_get_dma_data(dai, substream);
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	if (!rt715->slave)
676*4882a593Smuzhiyun 		return -EINVAL;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	sdw_stream_remove_slave(rt715->slave, stream->sdw_stream);
679*4882a593Smuzhiyun 	return 0;
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun #define RT715_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
683*4882a593Smuzhiyun #define RT715_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
684*4882a593Smuzhiyun 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun static struct snd_soc_dai_ops rt715_ops = {
687*4882a593Smuzhiyun 	.hw_params	= rt715_pcm_hw_params,
688*4882a593Smuzhiyun 	.hw_free	= rt715_pcm_hw_free,
689*4882a593Smuzhiyun 	.set_sdw_stream	= rt715_set_sdw_stream,
690*4882a593Smuzhiyun 	.shutdown	= rt715_shutdown,
691*4882a593Smuzhiyun };
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun static struct snd_soc_dai_driver rt715_dai[] = {
694*4882a593Smuzhiyun 	{
695*4882a593Smuzhiyun 		.name = "rt715-aif1",
696*4882a593Smuzhiyun 		.id = RT715_AIF1,
697*4882a593Smuzhiyun 		.capture = {
698*4882a593Smuzhiyun 			.stream_name = "DP6 Capture",
699*4882a593Smuzhiyun 			.channels_min = 1,
700*4882a593Smuzhiyun 			.channels_max = 2,
701*4882a593Smuzhiyun 			.rates = RT715_STEREO_RATES,
702*4882a593Smuzhiyun 			.formats = RT715_FORMATS,
703*4882a593Smuzhiyun 		},
704*4882a593Smuzhiyun 		.ops = &rt715_ops,
705*4882a593Smuzhiyun 	},
706*4882a593Smuzhiyun 	{
707*4882a593Smuzhiyun 		.name = "rt715-aif2",
708*4882a593Smuzhiyun 		.id = RT715_AIF2,
709*4882a593Smuzhiyun 		.capture = {
710*4882a593Smuzhiyun 			.stream_name = "DP4 Capture",
711*4882a593Smuzhiyun 			.channels_min = 1,
712*4882a593Smuzhiyun 			.channels_max = 2,
713*4882a593Smuzhiyun 			.rates = RT715_STEREO_RATES,
714*4882a593Smuzhiyun 			.formats = RT715_FORMATS,
715*4882a593Smuzhiyun 		},
716*4882a593Smuzhiyun 		.ops = &rt715_ops,
717*4882a593Smuzhiyun 	},
718*4882a593Smuzhiyun };
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun /* Bus clock frequency */
721*4882a593Smuzhiyun #define RT715_CLK_FREQ_9600000HZ 9600000
722*4882a593Smuzhiyun #define RT715_CLK_FREQ_12000000HZ 12000000
723*4882a593Smuzhiyun #define RT715_CLK_FREQ_6000000HZ 6000000
724*4882a593Smuzhiyun #define RT715_CLK_FREQ_4800000HZ 4800000
725*4882a593Smuzhiyun #define RT715_CLK_FREQ_2400000HZ 2400000
726*4882a593Smuzhiyun #define RT715_CLK_FREQ_12288000HZ 12288000
727*4882a593Smuzhiyun 
rt715_clock_config(struct device * dev)728*4882a593Smuzhiyun int rt715_clock_config(struct device *dev)
729*4882a593Smuzhiyun {
730*4882a593Smuzhiyun 	struct rt715_priv *rt715 = dev_get_drvdata(dev);
731*4882a593Smuzhiyun 	unsigned int clk_freq, value;
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	clk_freq = (rt715->params.curr_dr_freq >> 1);
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	switch (clk_freq) {
736*4882a593Smuzhiyun 	case RT715_CLK_FREQ_12000000HZ:
737*4882a593Smuzhiyun 		value = 0x0;
738*4882a593Smuzhiyun 		break;
739*4882a593Smuzhiyun 	case RT715_CLK_FREQ_6000000HZ:
740*4882a593Smuzhiyun 		value = 0x1;
741*4882a593Smuzhiyun 		break;
742*4882a593Smuzhiyun 	case RT715_CLK_FREQ_9600000HZ:
743*4882a593Smuzhiyun 		value = 0x2;
744*4882a593Smuzhiyun 		break;
745*4882a593Smuzhiyun 	case RT715_CLK_FREQ_4800000HZ:
746*4882a593Smuzhiyun 		value = 0x3;
747*4882a593Smuzhiyun 		break;
748*4882a593Smuzhiyun 	case RT715_CLK_FREQ_2400000HZ:
749*4882a593Smuzhiyun 		value = 0x4;
750*4882a593Smuzhiyun 		break;
751*4882a593Smuzhiyun 	case RT715_CLK_FREQ_12288000HZ:
752*4882a593Smuzhiyun 		value = 0x5;
753*4882a593Smuzhiyun 		break;
754*4882a593Smuzhiyun 	default:
755*4882a593Smuzhiyun 		return -EINVAL;
756*4882a593Smuzhiyun 	}
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	regmap_write(rt715->regmap, 0xe0, value);
759*4882a593Smuzhiyun 	regmap_write(rt715->regmap, 0xf0, value);
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 	return 0;
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun 
rt715_init(struct device * dev,struct regmap * sdw_regmap,struct regmap * regmap,struct sdw_slave * slave)764*4882a593Smuzhiyun int rt715_init(struct device *dev, struct regmap *sdw_regmap,
765*4882a593Smuzhiyun 	struct regmap *regmap, struct sdw_slave *slave)
766*4882a593Smuzhiyun {
767*4882a593Smuzhiyun 	struct rt715_priv *rt715;
768*4882a593Smuzhiyun 	int ret;
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	rt715 = devm_kzalloc(dev, sizeof(*rt715), GFP_KERNEL);
771*4882a593Smuzhiyun 	if (!rt715)
772*4882a593Smuzhiyun 		return -ENOMEM;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	dev_set_drvdata(dev, rt715);
775*4882a593Smuzhiyun 	rt715->slave = slave;
776*4882a593Smuzhiyun 	rt715->regmap = regmap;
777*4882a593Smuzhiyun 	rt715->sdw_regmap = sdw_regmap;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	/*
780*4882a593Smuzhiyun 	 * Mark hw_init to false
781*4882a593Smuzhiyun 	 * HW init will be performed when device reports present
782*4882a593Smuzhiyun 	 */
783*4882a593Smuzhiyun 	rt715->hw_init = false;
784*4882a593Smuzhiyun 	rt715->first_hw_init = false;
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	ret = devm_snd_soc_register_component(dev,
787*4882a593Smuzhiyun 						&soc_codec_dev_rt715,
788*4882a593Smuzhiyun 						rt715_dai,
789*4882a593Smuzhiyun 						ARRAY_SIZE(rt715_dai));
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	return ret;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun 
rt715_io_init(struct device * dev,struct sdw_slave * slave)794*4882a593Smuzhiyun int rt715_io_init(struct device *dev, struct sdw_slave *slave)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun 	struct rt715_priv *rt715 = dev_get_drvdata(dev);
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	if (rt715->hw_init)
799*4882a593Smuzhiyun 		return 0;
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	/*
802*4882a593Smuzhiyun 	 * PM runtime is only enabled when a Slave reports as Attached
803*4882a593Smuzhiyun 	 */
804*4882a593Smuzhiyun 	if (!rt715->first_hw_init) {
805*4882a593Smuzhiyun 		/* set autosuspend parameters */
806*4882a593Smuzhiyun 		pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
807*4882a593Smuzhiyun 		pm_runtime_use_autosuspend(&slave->dev);
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 		/* update count of parent 'active' children */
810*4882a593Smuzhiyun 		pm_runtime_set_active(&slave->dev);
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 		/* make sure the device does not suspend immediately */
813*4882a593Smuzhiyun 		pm_runtime_mark_last_busy(&slave->dev);
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 		pm_runtime_enable(&slave->dev);
816*4882a593Smuzhiyun 	}
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun 	pm_runtime_get_noresume(&slave->dev);
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	/* Mute nid=08h/09h */
821*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_GAIN_LINE_ADC_H, 0xb080);
822*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_GAIN_MIX_ADC_H, 0xb080);
823*4882a593Smuzhiyun 	/* Mute nid=07h/27h */
824*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_GAIN_MIC_ADC_H, 0xb080);
825*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_GAIN_MIX_ADC2_H, 0xb080);
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	/* Set Pin Widget */
828*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_PIN_DMIC1, 0x20);
829*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_PIN_DMIC2, 0x20);
830*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_PIN_DMIC3, 0x20);
831*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_PIN_DMIC4, 0x20);
832*4882a593Smuzhiyun 	/* Set Converter Stream */
833*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_STREAMID_LINE_ADC, 0x10);
834*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_STREAMID_MIX_ADC, 0x10);
835*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_STREAMID_MIC_ADC, 0x10);
836*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_STREAMID_MIX_ADC2, 0x10);
837*4882a593Smuzhiyun 	/* Set Configuration Default */
838*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC1_CONFIG_DEFAULT1, 0xd0);
839*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC1_CONFIG_DEFAULT2, 0x11);
840*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC1_CONFIG_DEFAULT3, 0xa1);
841*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC1_CONFIG_DEFAULT4, 0x81);
842*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC2_CONFIG_DEFAULT1, 0xd1);
843*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC2_CONFIG_DEFAULT2, 0x11);
844*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC2_CONFIG_DEFAULT3, 0xa1);
845*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC2_CONFIG_DEFAULT4, 0x81);
846*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC3_CONFIG_DEFAULT1, 0xd0);
847*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC3_CONFIG_DEFAULT2, 0x11);
848*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC3_CONFIG_DEFAULT3, 0xa1);
849*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC3_CONFIG_DEFAULT4, 0x81);
850*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC4_CONFIG_DEFAULT1, 0xd1);
851*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC4_CONFIG_DEFAULT2, 0x11);
852*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC4_CONFIG_DEFAULT3, 0xa1);
853*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_DMIC4_CONFIG_DEFAULT4, 0x81);
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	/* Finish Initial Settings, set power to D3 */
856*4882a593Smuzhiyun 	regmap_write(rt715->regmap, RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 	if (rt715->first_hw_init)
859*4882a593Smuzhiyun 		regcache_mark_dirty(rt715->regmap);
860*4882a593Smuzhiyun 	else
861*4882a593Smuzhiyun 		rt715->first_hw_init = true;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	/* Mark Slave initialization complete */
864*4882a593Smuzhiyun 	rt715->hw_init = true;
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	pm_runtime_mark_last_busy(&slave->dev);
867*4882a593Smuzhiyun 	pm_runtime_put_autosuspend(&slave->dev);
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun 	return 0;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC rt715 driver");
873*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC rt715 driver SDW");
874*4882a593Smuzhiyun MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>");
875*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
876