xref: /OK3568_Linux_fs/kernel/sound/soc/atmel/tse850-pcm5142.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // TSE-850 audio - ASoC driver for the Axentia TSE-850 with a PCM5142 codec
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun // Copyright (C) 2016 Axentia Technologies AB
6*4882a593Smuzhiyun //
7*4882a593Smuzhiyun // Author: Peter Rosin <peda@axentia.se>
8*4882a593Smuzhiyun //
9*4882a593Smuzhiyun //               loop1 relays
10*4882a593Smuzhiyun //   IN1 +---o  +------------+  o---+ OUT1
11*4882a593Smuzhiyun //            \                /
12*4882a593Smuzhiyun //             +              +
13*4882a593Smuzhiyun //             |   /          |
14*4882a593Smuzhiyun //             +--o  +--.     |
15*4882a593Smuzhiyun //             |  add   |     |
16*4882a593Smuzhiyun //             |        V     |
17*4882a593Smuzhiyun //             |      .---.   |
18*4882a593Smuzhiyun //   DAC +----------->|Sum|---+
19*4882a593Smuzhiyun //             |      '---'   |
20*4882a593Smuzhiyun //             |              |
21*4882a593Smuzhiyun //             +              +
22*4882a593Smuzhiyun //
23*4882a593Smuzhiyun //   IN2 +---o--+------------+--o---+ OUT2
24*4882a593Smuzhiyun //               loop2 relays
25*4882a593Smuzhiyun //
26*4882a593Smuzhiyun // The 'loop1' gpio pin controlls two relays, which are either in loop
27*4882a593Smuzhiyun // position, meaning that input and output are directly connected, or
28*4882a593Smuzhiyun // they are in mixer position, meaning that the signal is passed through
29*4882a593Smuzhiyun // the 'Sum' mixer. Similarly for 'loop2'.
30*4882a593Smuzhiyun //
31*4882a593Smuzhiyun // In the above, the 'loop1' relays are inactive, thus feeding IN1 to the
32*4882a593Smuzhiyun // mixer (if 'add' is active) and feeding the mixer output to OUT1. The
33*4882a593Smuzhiyun // 'loop2' relays are active, short-cutting the TSE-850 from channel 2.
34*4882a593Smuzhiyun // IN1, IN2, OUT1 and OUT2 are TSE-850 connectors and DAC is the PCB name
35*4882a593Smuzhiyun // of the (filtered) output from the PCM5142 codec.
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #include <linux/clk.h>
38*4882a593Smuzhiyun #include <linux/gpio.h>
39*4882a593Smuzhiyun #include <linux/module.h>
40*4882a593Smuzhiyun #include <linux/of.h>
41*4882a593Smuzhiyun #include <linux/of_device.h>
42*4882a593Smuzhiyun #include <linux/of_gpio.h>
43*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #include <sound/soc.h>
46*4882a593Smuzhiyun #include <sound/pcm_params.h>
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun struct tse850_priv {
49*4882a593Smuzhiyun 	struct gpio_desc *add;
50*4882a593Smuzhiyun 	struct gpio_desc *loop1;
51*4882a593Smuzhiyun 	struct gpio_desc *loop2;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	struct regulator *ana;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	int add_cache;
56*4882a593Smuzhiyun 	int loop1_cache;
57*4882a593Smuzhiyun 	int loop2_cache;
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun 
tse850_get_mux1(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * ucontrol)60*4882a593Smuzhiyun static int tse850_get_mux1(struct snd_kcontrol *kctrl,
61*4882a593Smuzhiyun 			   struct snd_ctl_elem_value *ucontrol)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
64*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
65*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = tse850->loop1_cache;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	return 0;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
tse850_put_mux1(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * ucontrol)72*4882a593Smuzhiyun static int tse850_put_mux1(struct snd_kcontrol *kctrl,
73*4882a593Smuzhiyun 			   struct snd_ctl_elem_value *ucontrol)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
76*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
77*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
78*4882a593Smuzhiyun 	struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
79*4882a593Smuzhiyun 	unsigned int val = ucontrol->value.enumerated.item[0];
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	if (val >= e->items)
82*4882a593Smuzhiyun 		return -EINVAL;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	gpiod_set_value_cansleep(tse850->loop1, val);
85*4882a593Smuzhiyun 	tse850->loop1_cache = val;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
tse850_get_mux2(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * ucontrol)90*4882a593Smuzhiyun static int tse850_get_mux2(struct snd_kcontrol *kctrl,
91*4882a593Smuzhiyun 			   struct snd_ctl_elem_value *ucontrol)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
94*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
95*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = tse850->loop2_cache;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	return 0;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
tse850_put_mux2(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * ucontrol)102*4882a593Smuzhiyun static int tse850_put_mux2(struct snd_kcontrol *kctrl,
103*4882a593Smuzhiyun 			   struct snd_ctl_elem_value *ucontrol)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
106*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
107*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
108*4882a593Smuzhiyun 	struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
109*4882a593Smuzhiyun 	unsigned int val = ucontrol->value.enumerated.item[0];
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	if (val >= e->items)
112*4882a593Smuzhiyun 		return -EINVAL;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	gpiod_set_value_cansleep(tse850->loop2, val);
115*4882a593Smuzhiyun 	tse850->loop2_cache = val;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
tse850_get_mix(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * ucontrol)120*4882a593Smuzhiyun static int tse850_get_mix(struct snd_kcontrol *kctrl,
121*4882a593Smuzhiyun 			  struct snd_ctl_elem_value *ucontrol)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
124*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
125*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = tse850->add_cache;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	return 0;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
tse850_put_mix(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * ucontrol)132*4882a593Smuzhiyun static int tse850_put_mix(struct snd_kcontrol *kctrl,
133*4882a593Smuzhiyun 			  struct snd_ctl_elem_value *ucontrol)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
136*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
137*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
138*4882a593Smuzhiyun 	int connect = !!ucontrol->value.integer.value[0];
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	if (tse850->add_cache == connect)
141*4882a593Smuzhiyun 		return 0;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	/*
144*4882a593Smuzhiyun 	 * Hmmm, this gpiod_set_value_cansleep call should probably happen
145*4882a593Smuzhiyun 	 * inside snd_soc_dapm_mixer_update_power in the loop.
146*4882a593Smuzhiyun 	 */
147*4882a593Smuzhiyun 	gpiod_set_value_cansleep(tse850->add, connect);
148*4882a593Smuzhiyun 	tse850->add_cache = connect;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	snd_soc_dapm_mixer_update_power(dapm, kctrl, connect, NULL);
151*4882a593Smuzhiyun 	return 1;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
tse850_get_ana(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * ucontrol)154*4882a593Smuzhiyun static int tse850_get_ana(struct snd_kcontrol *kctrl,
155*4882a593Smuzhiyun 			  struct snd_ctl_elem_value *ucontrol)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
158*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
159*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
160*4882a593Smuzhiyun 	int ret;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	ret = regulator_get_voltage(tse850->ana);
163*4882a593Smuzhiyun 	if (ret < 0)
164*4882a593Smuzhiyun 		return ret;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	/*
167*4882a593Smuzhiyun 	 * Map regulator output values like so:
168*4882a593Smuzhiyun 	 *      -11.5V to "Low" (enum 0)
169*4882a593Smuzhiyun 	 * 11.5V-12.5V to "12V" (enum 1)
170*4882a593Smuzhiyun 	 * 12.5V-13.5V to "13V" (enum 2)
171*4882a593Smuzhiyun 	 *     ...
172*4882a593Smuzhiyun 	 * 18.5V-19.5V to "19V" (enum 8)
173*4882a593Smuzhiyun 	 * 19.5V-      to "20V" (enum 9)
174*4882a593Smuzhiyun 	 */
175*4882a593Smuzhiyun 	if (ret < 11000000)
176*4882a593Smuzhiyun 		ret = 11000000;
177*4882a593Smuzhiyun 	else if (ret > 20000000)
178*4882a593Smuzhiyun 		ret = 20000000;
179*4882a593Smuzhiyun 	ret -= 11000000;
180*4882a593Smuzhiyun 	ret = (ret + 500000) / 1000000;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = ret;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	return 0;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
tse850_put_ana(struct snd_kcontrol * kctrl,struct snd_ctl_elem_value * ucontrol)187*4882a593Smuzhiyun static int tse850_put_ana(struct snd_kcontrol *kctrl,
188*4882a593Smuzhiyun 			  struct snd_ctl_elem_value *ucontrol)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
191*4882a593Smuzhiyun 	struct snd_soc_card *card = dapm->card;
192*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
193*4882a593Smuzhiyun 	struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
194*4882a593Smuzhiyun 	unsigned int uV = ucontrol->value.enumerated.item[0];
195*4882a593Smuzhiyun 	int ret;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	if (uV >= e->items)
198*4882a593Smuzhiyun 		return -EINVAL;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/*
201*4882a593Smuzhiyun 	 * Map enum zero (Low) to 2 volts on the regulator, do this since
202*4882a593Smuzhiyun 	 * the ana regulator is supplied by the system 12V voltage and
203*4882a593Smuzhiyun 	 * requesting anything below the system voltage causes the system
204*4882a593Smuzhiyun 	 * voltage to be passed through the regulator. Also, the ana
205*4882a593Smuzhiyun 	 * regulator induces noise when requesting voltages near the
206*4882a593Smuzhiyun 	 * system voltage. So, by mapping Low to 2V, that noise is
207*4882a593Smuzhiyun 	 * eliminated when all that is needed is 12V (the system voltage).
208*4882a593Smuzhiyun 	 */
209*4882a593Smuzhiyun 	if (uV)
210*4882a593Smuzhiyun 		uV = 11000000 + (1000000 * uV);
211*4882a593Smuzhiyun 	else
212*4882a593Smuzhiyun 		uV = 2000000;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	ret = regulator_set_voltage(tse850->ana, uV, uV);
215*4882a593Smuzhiyun 	if (ret < 0)
216*4882a593Smuzhiyun 		return ret;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun static const char * const mux_text[] = { "Mixer", "Loop" };
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun static const struct soc_enum mux_enum =
224*4882a593Smuzhiyun 	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(mux_text), mux_text);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun static const struct snd_kcontrol_new mux1 =
227*4882a593Smuzhiyun 	SOC_DAPM_ENUM_EXT("MUX1", mux_enum, tse850_get_mux1, tse850_put_mux1);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun static const struct snd_kcontrol_new mux2 =
230*4882a593Smuzhiyun 	SOC_DAPM_ENUM_EXT("MUX2", mux_enum, tse850_get_mux2, tse850_put_mux2);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun #define TSE850_DAPM_SINGLE_EXT(xname, reg, shift, max, invert, xget, xput) \
233*4882a593Smuzhiyun {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
234*4882a593Smuzhiyun 	.info = snd_soc_info_volsw, \
235*4882a593Smuzhiyun 	.get = xget, \
236*4882a593Smuzhiyun 	.put = xput, \
237*4882a593Smuzhiyun 	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun static const struct snd_kcontrol_new mix[] = {
240*4882a593Smuzhiyun 	TSE850_DAPM_SINGLE_EXT("IN Switch", SND_SOC_NOPM, 0, 1, 0,
241*4882a593Smuzhiyun 			       tse850_get_mix, tse850_put_mix),
242*4882a593Smuzhiyun };
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun static const char * const ana_text[] = {
245*4882a593Smuzhiyun 	"Low", "12V", "13V", "14V", "15V", "16V", "17V", "18V", "19V", "20V"
246*4882a593Smuzhiyun };
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun static const struct soc_enum ana_enum =
249*4882a593Smuzhiyun 	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(ana_text), ana_text);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun static const struct snd_kcontrol_new out =
252*4882a593Smuzhiyun 	SOC_DAPM_ENUM_EXT("ANA", ana_enum, tse850_get_ana, tse850_put_ana);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun static const struct snd_soc_dapm_widget tse850_dapm_widgets[] = {
255*4882a593Smuzhiyun 	SND_SOC_DAPM_LINE("OUT1", NULL),
256*4882a593Smuzhiyun 	SND_SOC_DAPM_LINE("OUT2", NULL),
257*4882a593Smuzhiyun 	SND_SOC_DAPM_LINE("IN1", NULL),
258*4882a593Smuzhiyun 	SND_SOC_DAPM_LINE("IN2", NULL),
259*4882a593Smuzhiyun 	SND_SOC_DAPM_INPUT("DAC"),
260*4882a593Smuzhiyun 	SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0),
261*4882a593Smuzhiyun 	SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0),
262*4882a593Smuzhiyun 	SOC_MIXER_ARRAY("MIX", SND_SOC_NOPM, 0, 0, mix),
263*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("MUX1", SND_SOC_NOPM, 0, 0, &mux1),
264*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("MUX2", SND_SOC_NOPM, 0, 0, &mux2),
265*4882a593Smuzhiyun 	SND_SOC_DAPM_OUT_DRV("OUT", SND_SOC_NOPM, 0, 0, &out, 1),
266*4882a593Smuzhiyun };
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /*
269*4882a593Smuzhiyun  * These connections are not entirely correct, since both IN1 and IN2
270*4882a593Smuzhiyun  * are always fed to MIX (if the "IN switch" is set so), i.e. without
271*4882a593Smuzhiyun  * regard to the loop1 and loop2 relays that according to this only
272*4882a593Smuzhiyun  * control MUX1 and MUX2 but in fact also control how the input signals
273*4882a593Smuzhiyun  * are routed.
274*4882a593Smuzhiyun  * But, 1) I don't know how to do it right, and 2) it doesn't seem to
275*4882a593Smuzhiyun  * matter in practice since nothing is powered in those sections anyway.
276*4882a593Smuzhiyun  */
277*4882a593Smuzhiyun static const struct snd_soc_dapm_route tse850_intercon[] = {
278*4882a593Smuzhiyun 	{ "OUT1", NULL, "MUX1" },
279*4882a593Smuzhiyun 	{ "OUT2", NULL, "MUX2" },
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	{ "MUX1", "Loop",  "IN1" },
282*4882a593Smuzhiyun 	{ "MUX1", "Mixer", "OUT" },
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	{ "MUX2", "Loop",  "IN2" },
285*4882a593Smuzhiyun 	{ "MUX2", "Mixer", "OUT" },
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	{ "OUT", NULL, "MIX" },
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	{ "MIX", NULL, "DAC" },
290*4882a593Smuzhiyun 	{ "MIX", "IN Switch", "IN1" },
291*4882a593Smuzhiyun 	{ "MIX", "IN Switch", "IN2" },
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	/* connect board input to the codec left channel output pin */
294*4882a593Smuzhiyun 	{ "DAC", NULL, "OUTL" },
295*4882a593Smuzhiyun };
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun SND_SOC_DAILINK_DEFS(pcm,
298*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
299*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi")),
300*4882a593Smuzhiyun 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun static struct snd_soc_dai_link tse850_dailink = {
303*4882a593Smuzhiyun 	.name = "TSE-850",
304*4882a593Smuzhiyun 	.stream_name = "TSE-850-PCM",
305*4882a593Smuzhiyun 	.dai_fmt = SND_SOC_DAIFMT_I2S
306*4882a593Smuzhiyun 		 | SND_SOC_DAIFMT_NB_NF
307*4882a593Smuzhiyun 		 | SND_SOC_DAIFMT_CBM_CFS,
308*4882a593Smuzhiyun 	SND_SOC_DAILINK_REG(pcm),
309*4882a593Smuzhiyun };
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun static struct snd_soc_card tse850_card = {
312*4882a593Smuzhiyun 	.name = "TSE-850-ASoC",
313*4882a593Smuzhiyun 	.owner = THIS_MODULE,
314*4882a593Smuzhiyun 	.dai_link = &tse850_dailink,
315*4882a593Smuzhiyun 	.num_links = 1,
316*4882a593Smuzhiyun 	.dapm_widgets = tse850_dapm_widgets,
317*4882a593Smuzhiyun 	.num_dapm_widgets = ARRAY_SIZE(tse850_dapm_widgets),
318*4882a593Smuzhiyun 	.dapm_routes = tse850_intercon,
319*4882a593Smuzhiyun 	.num_dapm_routes = ARRAY_SIZE(tse850_intercon),
320*4882a593Smuzhiyun 	.fully_routed = true,
321*4882a593Smuzhiyun };
322*4882a593Smuzhiyun 
tse850_dt_init(struct platform_device * pdev)323*4882a593Smuzhiyun static int tse850_dt_init(struct platform_device *pdev)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun 	struct device_node *np = pdev->dev.of_node;
326*4882a593Smuzhiyun 	struct device_node *codec_np, *cpu_np;
327*4882a593Smuzhiyun 	struct snd_soc_dai_link *dailink = &tse850_dailink;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	if (!np) {
330*4882a593Smuzhiyun 		dev_err(&pdev->dev, "only device tree supported\n");
331*4882a593Smuzhiyun 		return -EINVAL;
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	cpu_np = of_parse_phandle(np, "axentia,cpu-dai", 0);
335*4882a593Smuzhiyun 	if (!cpu_np) {
336*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to get cpu dai\n");
337*4882a593Smuzhiyun 		return -EINVAL;
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 	dailink->cpus->of_node = cpu_np;
340*4882a593Smuzhiyun 	dailink->platforms->of_node = cpu_np;
341*4882a593Smuzhiyun 	of_node_put(cpu_np);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	codec_np = of_parse_phandle(np, "axentia,audio-codec", 0);
344*4882a593Smuzhiyun 	if (!codec_np) {
345*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to get codec info\n");
346*4882a593Smuzhiyun 		return -EINVAL;
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 	dailink->codecs->of_node = codec_np;
349*4882a593Smuzhiyun 	of_node_put(codec_np);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	return 0;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
tse850_probe(struct platform_device * pdev)354*4882a593Smuzhiyun static int tse850_probe(struct platform_device *pdev)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun 	struct snd_soc_card *card = &tse850_card;
357*4882a593Smuzhiyun 	struct device *dev = card->dev = &pdev->dev;
358*4882a593Smuzhiyun 	struct tse850_priv *tse850;
359*4882a593Smuzhiyun 	int ret;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	tse850 = devm_kzalloc(dev, sizeof(*tse850), GFP_KERNEL);
362*4882a593Smuzhiyun 	if (!tse850)
363*4882a593Smuzhiyun 		return -ENOMEM;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	snd_soc_card_set_drvdata(card, tse850);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	ret = tse850_dt_init(pdev);
368*4882a593Smuzhiyun 	if (ret) {
369*4882a593Smuzhiyun 		dev_err(dev, "failed to init dt info\n");
370*4882a593Smuzhiyun 		return ret;
371*4882a593Smuzhiyun 	}
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	tse850->add = devm_gpiod_get(dev, "axentia,add", GPIOD_OUT_HIGH);
374*4882a593Smuzhiyun 	if (IS_ERR(tse850->add)) {
375*4882a593Smuzhiyun 		if (PTR_ERR(tse850->add) != -EPROBE_DEFER)
376*4882a593Smuzhiyun 			dev_err(dev, "failed to get 'add' gpio\n");
377*4882a593Smuzhiyun 		return PTR_ERR(tse850->add);
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 	tse850->add_cache = 1;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	tse850->loop1 = devm_gpiod_get(dev, "axentia,loop1", GPIOD_OUT_HIGH);
382*4882a593Smuzhiyun 	if (IS_ERR(tse850->loop1)) {
383*4882a593Smuzhiyun 		if (PTR_ERR(tse850->loop1) != -EPROBE_DEFER)
384*4882a593Smuzhiyun 			dev_err(dev, "failed to get 'loop1' gpio\n");
385*4882a593Smuzhiyun 		return PTR_ERR(tse850->loop1);
386*4882a593Smuzhiyun 	}
387*4882a593Smuzhiyun 	tse850->loop1_cache = 1;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	tse850->loop2 = devm_gpiod_get(dev, "axentia,loop2", GPIOD_OUT_HIGH);
390*4882a593Smuzhiyun 	if (IS_ERR(tse850->loop2)) {
391*4882a593Smuzhiyun 		if (PTR_ERR(tse850->loop2) != -EPROBE_DEFER)
392*4882a593Smuzhiyun 			dev_err(dev, "failed to get 'loop2' gpio\n");
393*4882a593Smuzhiyun 		return PTR_ERR(tse850->loop2);
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 	tse850->loop2_cache = 1;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	tse850->ana = devm_regulator_get(dev, "axentia,ana");
398*4882a593Smuzhiyun 	if (IS_ERR(tse850->ana)) {
399*4882a593Smuzhiyun 		if (PTR_ERR(tse850->ana) != -EPROBE_DEFER)
400*4882a593Smuzhiyun 			dev_err(dev, "failed to get 'ana' regulator\n");
401*4882a593Smuzhiyun 		return PTR_ERR(tse850->ana);
402*4882a593Smuzhiyun 	}
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	ret = regulator_enable(tse850->ana);
405*4882a593Smuzhiyun 	if (ret < 0) {
406*4882a593Smuzhiyun 		dev_err(dev, "failed to enable the 'ana' regulator\n");
407*4882a593Smuzhiyun 		return ret;
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	ret = snd_soc_register_card(card);
411*4882a593Smuzhiyun 	if (ret) {
412*4882a593Smuzhiyun 		dev_err(dev, "snd_soc_register_card failed\n");
413*4882a593Smuzhiyun 		goto err_disable_ana;
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	return 0;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun err_disable_ana:
419*4882a593Smuzhiyun 	regulator_disable(tse850->ana);
420*4882a593Smuzhiyun 	return ret;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun 
tse850_remove(struct platform_device * pdev)423*4882a593Smuzhiyun static int tse850_remove(struct platform_device *pdev)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun 	struct snd_soc_card *card = platform_get_drvdata(pdev);
426*4882a593Smuzhiyun 	struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	snd_soc_unregister_card(card);
429*4882a593Smuzhiyun 	regulator_disable(tse850->ana);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	return 0;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun static const struct of_device_id tse850_dt_ids[] = {
435*4882a593Smuzhiyun 	{ .compatible = "axentia,tse850-pcm5142", },
436*4882a593Smuzhiyun 	{ /* sentinel */ }
437*4882a593Smuzhiyun };
438*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, tse850_dt_ids);
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun static struct platform_driver tse850_driver = {
441*4882a593Smuzhiyun 	.driver = {
442*4882a593Smuzhiyun 		.name = "axentia-tse850-pcm5142",
443*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(tse850_dt_ids),
444*4882a593Smuzhiyun 	},
445*4882a593Smuzhiyun 	.probe = tse850_probe,
446*4882a593Smuzhiyun 	.remove = tse850_remove,
447*4882a593Smuzhiyun };
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun module_platform_driver(tse850_driver);
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun /* Module information */
452*4882a593Smuzhiyun MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
453*4882a593Smuzhiyun MODULE_DESCRIPTION("ALSA SoC driver for TSE-850 with PCM5142 codec");
454*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
455