xref: /linux/sound/soc/amd/acp3x-rt5682-max9836.c (revision 6b8e4e7db3cd236a2cbb720360fb135087a2ac1d)
1*6b8e4e7dSAkshu Agrawal // SPDX-License-Identifier: GPL-2.0+
2*6b8e4e7dSAkshu Agrawal //
3*6b8e4e7dSAkshu Agrawal // Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec.
4*6b8e4e7dSAkshu Agrawal //
5*6b8e4e7dSAkshu Agrawal //Copyright 2016 Advanced Micro Devices, Inc.
6*6b8e4e7dSAkshu Agrawal 
7*6b8e4e7dSAkshu Agrawal #include <sound/core.h>
8*6b8e4e7dSAkshu Agrawal #include <sound/soc.h>
9*6b8e4e7dSAkshu Agrawal #include <sound/pcm.h>
10*6b8e4e7dSAkshu Agrawal #include <sound/pcm_params.h>
11*6b8e4e7dSAkshu Agrawal #include <sound/soc-dapm.h>
12*6b8e4e7dSAkshu Agrawal #include <sound/jack.h>
13*6b8e4e7dSAkshu Agrawal #include <linux/clk.h>
14*6b8e4e7dSAkshu Agrawal #include <linux/gpio.h>
15*6b8e4e7dSAkshu Agrawal #include <linux/module.h>
16*6b8e4e7dSAkshu Agrawal #include <linux/i2c.h>
17*6b8e4e7dSAkshu Agrawal #include <linux/input.h>
18*6b8e4e7dSAkshu Agrawal #include <linux/acpi.h>
19*6b8e4e7dSAkshu Agrawal 
20*6b8e4e7dSAkshu Agrawal #include "raven/acp3x.h"
21*6b8e4e7dSAkshu Agrawal #include "../codecs/rt5682.h"
22*6b8e4e7dSAkshu Agrawal 
23*6b8e4e7dSAkshu Agrawal #define PCO_PLAT_CLK 48000000
24*6b8e4e7dSAkshu Agrawal #define RT5682_PLL_FREQ (48000 * 512)
25*6b8e4e7dSAkshu Agrawal #define DUAL_CHANNEL		2
26*6b8e4e7dSAkshu Agrawal 
27*6b8e4e7dSAkshu Agrawal static struct snd_soc_jack pco_jack;
28*6b8e4e7dSAkshu Agrawal static struct clk *rt5682_dai_wclk;
29*6b8e4e7dSAkshu Agrawal static struct clk *rt5682_dai_bclk;
30*6b8e4e7dSAkshu Agrawal 
31*6b8e4e7dSAkshu Agrawal static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd)
32*6b8e4e7dSAkshu Agrawal {
33*6b8e4e7dSAkshu Agrawal 	int ret;
34*6b8e4e7dSAkshu Agrawal 	struct snd_soc_card *card = rtd->card;
35*6b8e4e7dSAkshu Agrawal 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
36*6b8e4e7dSAkshu Agrawal 	struct snd_soc_component *component = codec_dai->component;
37*6b8e4e7dSAkshu Agrawal 
38*6b8e4e7dSAkshu Agrawal 	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
39*6b8e4e7dSAkshu Agrawal 
40*6b8e4e7dSAkshu Agrawal 	/* set rt5682 dai fmt */
41*6b8e4e7dSAkshu Agrawal 	ret =  snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
42*6b8e4e7dSAkshu Agrawal 			| SND_SOC_DAIFMT_NB_NF
43*6b8e4e7dSAkshu Agrawal 			| SND_SOC_DAIFMT_CBM_CFM);
44*6b8e4e7dSAkshu Agrawal 	if (ret < 0) {
45*6b8e4e7dSAkshu Agrawal 		dev_err(rtd->card->dev,
46*6b8e4e7dSAkshu Agrawal 				"Failed to set rt5682 dai fmt: %d\n", ret);
47*6b8e4e7dSAkshu Agrawal 		return ret;
48*6b8e4e7dSAkshu Agrawal 	}
49*6b8e4e7dSAkshu Agrawal 
50*6b8e4e7dSAkshu Agrawal 	/* set codec PLL */
51*6b8e4e7dSAkshu Agrawal 	ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
52*6b8e4e7dSAkshu Agrawal 				  PCO_PLAT_CLK, RT5682_PLL_FREQ);
53*6b8e4e7dSAkshu Agrawal 	if (ret < 0) {
54*6b8e4e7dSAkshu Agrawal 		dev_err(rtd->dev, "can't set rt5682 PLL: %d\n", ret);
55*6b8e4e7dSAkshu Agrawal 		return ret;
56*6b8e4e7dSAkshu Agrawal 	}
57*6b8e4e7dSAkshu Agrawal 
58*6b8e4e7dSAkshu Agrawal 	/* Set codec sysclk */
59*6b8e4e7dSAkshu Agrawal 	ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
60*6b8e4e7dSAkshu Agrawal 			RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
61*6b8e4e7dSAkshu Agrawal 	if (ret < 0) {
62*6b8e4e7dSAkshu Agrawal 		dev_err(rtd->dev,
63*6b8e4e7dSAkshu Agrawal 			"Failed to set rt5682 SYSCLK: %d\n", ret);
64*6b8e4e7dSAkshu Agrawal 		return ret;
65*6b8e4e7dSAkshu Agrawal 	}
66*6b8e4e7dSAkshu Agrawal 
67*6b8e4e7dSAkshu Agrawal 	/* Set tdm/i2s1 master bclk ratio */
68*6b8e4e7dSAkshu Agrawal 	ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
69*6b8e4e7dSAkshu Agrawal 	if (ret < 0) {
70*6b8e4e7dSAkshu Agrawal 		dev_err(rtd->dev,
71*6b8e4e7dSAkshu Agrawal 			"Failed to set rt5682 tdm bclk ratio: %d\n", ret);
72*6b8e4e7dSAkshu Agrawal 		return ret;
73*6b8e4e7dSAkshu Agrawal 	}
74*6b8e4e7dSAkshu Agrawal 
75*6b8e4e7dSAkshu Agrawal 	rt5682_dai_wclk = clk_get(component->dev, "rt5682-dai-wclk");
76*6b8e4e7dSAkshu Agrawal 	rt5682_dai_bclk = clk_get(component->dev, "rt5682-dai-bclk");
77*6b8e4e7dSAkshu Agrawal 
78*6b8e4e7dSAkshu Agrawal 	ret = snd_soc_card_jack_new(card, "Headset Jack",
79*6b8e4e7dSAkshu Agrawal 				SND_JACK_HEADSET | SND_JACK_LINEOUT |
80*6b8e4e7dSAkshu Agrawal 				SND_JACK_BTN_0 | SND_JACK_BTN_1 |
81*6b8e4e7dSAkshu Agrawal 				SND_JACK_BTN_2 | SND_JACK_BTN_3,
82*6b8e4e7dSAkshu Agrawal 				&pco_jack, NULL, 0);
83*6b8e4e7dSAkshu Agrawal 	if (ret) {
84*6b8e4e7dSAkshu Agrawal 		dev_err(card->dev, "HP jack creation failed %d\n", ret);
85*6b8e4e7dSAkshu Agrawal 		return ret;
86*6b8e4e7dSAkshu Agrawal 	}
87*6b8e4e7dSAkshu Agrawal 
88*6b8e4e7dSAkshu Agrawal 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
89*6b8e4e7dSAkshu Agrawal 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
90*6b8e4e7dSAkshu Agrawal 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
91*6b8e4e7dSAkshu Agrawal 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
92*6b8e4e7dSAkshu Agrawal 
93*6b8e4e7dSAkshu Agrawal 	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
94*6b8e4e7dSAkshu Agrawal 	if (ret) {
95*6b8e4e7dSAkshu Agrawal 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
96*6b8e4e7dSAkshu Agrawal 		return ret;
97*6b8e4e7dSAkshu Agrawal 	}
98*6b8e4e7dSAkshu Agrawal 
99*6b8e4e7dSAkshu Agrawal 	return ret;
100*6b8e4e7dSAkshu Agrawal }
101*6b8e4e7dSAkshu Agrawal 
102*6b8e4e7dSAkshu Agrawal static int rt5682_clk_enable(struct snd_pcm_substream *substream)
103*6b8e4e7dSAkshu Agrawal {
104*6b8e4e7dSAkshu Agrawal 	int ret = 0;
105*6b8e4e7dSAkshu Agrawal 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
106*6b8e4e7dSAkshu Agrawal 
107*6b8e4e7dSAkshu Agrawal 	/* RT5682 will support only 48K output with 48M mclk */
108*6b8e4e7dSAkshu Agrawal 	clk_set_rate(rt5682_dai_wclk, 48000);
109*6b8e4e7dSAkshu Agrawal 	clk_set_rate(rt5682_dai_bclk, 48000 * 64);
110*6b8e4e7dSAkshu Agrawal 	ret = clk_prepare_enable(rt5682_dai_wclk);
111*6b8e4e7dSAkshu Agrawal 	if (ret < 0) {
112*6b8e4e7dSAkshu Agrawal 		dev_err(rtd->dev, "can't enable wclk %d\n", ret);
113*6b8e4e7dSAkshu Agrawal 		return ret;
114*6b8e4e7dSAkshu Agrawal 	}
115*6b8e4e7dSAkshu Agrawal 
116*6b8e4e7dSAkshu Agrawal 	return ret;
117*6b8e4e7dSAkshu Agrawal }
118*6b8e4e7dSAkshu Agrawal 
119*6b8e4e7dSAkshu Agrawal static void rt5682_clk_disable(void)
120*6b8e4e7dSAkshu Agrawal {
121*6b8e4e7dSAkshu Agrawal 	clk_disable_unprepare(rt5682_dai_wclk);
122*6b8e4e7dSAkshu Agrawal }
123*6b8e4e7dSAkshu Agrawal 
124*6b8e4e7dSAkshu Agrawal static const unsigned int channels[] = {
125*6b8e4e7dSAkshu Agrawal 	DUAL_CHANNEL,
126*6b8e4e7dSAkshu Agrawal };
127*6b8e4e7dSAkshu Agrawal 
128*6b8e4e7dSAkshu Agrawal static const unsigned int rates[] = {
129*6b8e4e7dSAkshu Agrawal 	48000,
130*6b8e4e7dSAkshu Agrawal };
131*6b8e4e7dSAkshu Agrawal 
132*6b8e4e7dSAkshu Agrawal static const struct snd_pcm_hw_constraint_list constraints_rates = {
133*6b8e4e7dSAkshu Agrawal 	.count = ARRAY_SIZE(rates),
134*6b8e4e7dSAkshu Agrawal 	.list  = rates,
135*6b8e4e7dSAkshu Agrawal 	.mask = 0,
136*6b8e4e7dSAkshu Agrawal };
137*6b8e4e7dSAkshu Agrawal 
138*6b8e4e7dSAkshu Agrawal static const struct snd_pcm_hw_constraint_list constraints_channels = {
139*6b8e4e7dSAkshu Agrawal 	.count = ARRAY_SIZE(channels),
140*6b8e4e7dSAkshu Agrawal 	.list = channels,
141*6b8e4e7dSAkshu Agrawal 	.mask = 0,
142*6b8e4e7dSAkshu Agrawal };
143*6b8e4e7dSAkshu Agrawal 
144*6b8e4e7dSAkshu Agrawal static int acp3x_5682_startup(struct snd_pcm_substream *substream)
145*6b8e4e7dSAkshu Agrawal {
146*6b8e4e7dSAkshu Agrawal 	struct snd_pcm_runtime *runtime = substream->runtime;
147*6b8e4e7dSAkshu Agrawal 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
148*6b8e4e7dSAkshu Agrawal 	struct snd_soc_card *card = rtd->card;
149*6b8e4e7dSAkshu Agrawal 	struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
150*6b8e4e7dSAkshu Agrawal 
151*6b8e4e7dSAkshu Agrawal 	machine->play_i2s_instance = I2S_SP_INSTANCE;
152*6b8e4e7dSAkshu Agrawal 	machine->cap_i2s_instance = I2S_SP_INSTANCE;
153*6b8e4e7dSAkshu Agrawal 
154*6b8e4e7dSAkshu Agrawal 	runtime->hw.channels_max = DUAL_CHANNEL;
155*6b8e4e7dSAkshu Agrawal 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
156*6b8e4e7dSAkshu Agrawal 				   &constraints_channels);
157*6b8e4e7dSAkshu Agrawal 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
158*6b8e4e7dSAkshu Agrawal 				   &constraints_rates);
159*6b8e4e7dSAkshu Agrawal 	return rt5682_clk_enable(substream);
160*6b8e4e7dSAkshu Agrawal }
161*6b8e4e7dSAkshu Agrawal 
162*6b8e4e7dSAkshu Agrawal static int acp3x_max_startup(struct snd_pcm_substream *substream)
163*6b8e4e7dSAkshu Agrawal {
164*6b8e4e7dSAkshu Agrawal 	struct snd_pcm_runtime *runtime = substream->runtime;
165*6b8e4e7dSAkshu Agrawal 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
166*6b8e4e7dSAkshu Agrawal 	struct snd_soc_card *card = rtd->card;
167*6b8e4e7dSAkshu Agrawal 	struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
168*6b8e4e7dSAkshu Agrawal 
169*6b8e4e7dSAkshu Agrawal 	machine->play_i2s_instance = I2S_BT_INSTANCE;
170*6b8e4e7dSAkshu Agrawal 
171*6b8e4e7dSAkshu Agrawal 	runtime->hw.channels_max = DUAL_CHANNEL;
172*6b8e4e7dSAkshu Agrawal 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
173*6b8e4e7dSAkshu Agrawal 				   &constraints_channels);
174*6b8e4e7dSAkshu Agrawal 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
175*6b8e4e7dSAkshu Agrawal 				   &constraints_rates);
176*6b8e4e7dSAkshu Agrawal 	return rt5682_clk_enable(substream);
177*6b8e4e7dSAkshu Agrawal }
178*6b8e4e7dSAkshu Agrawal 
179*6b8e4e7dSAkshu Agrawal static int acp3x_ec_startup(struct snd_pcm_substream *substream)
180*6b8e4e7dSAkshu Agrawal {
181*6b8e4e7dSAkshu Agrawal 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
182*6b8e4e7dSAkshu Agrawal 	struct snd_soc_card *card = rtd->card;
183*6b8e4e7dSAkshu Agrawal 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
184*6b8e4e7dSAkshu Agrawal 	struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
185*6b8e4e7dSAkshu Agrawal 
186*6b8e4e7dSAkshu Agrawal 	machine->cap_i2s_instance = I2S_BT_INSTANCE;
187*6b8e4e7dSAkshu Agrawal 	snd_soc_dai_set_bclk_ratio(codec_dai, 64);
188*6b8e4e7dSAkshu Agrawal 
189*6b8e4e7dSAkshu Agrawal 	return rt5682_clk_enable(substream);
190*6b8e4e7dSAkshu Agrawal }
191*6b8e4e7dSAkshu Agrawal 
192*6b8e4e7dSAkshu Agrawal static void rt5682_shutdown(struct snd_pcm_substream *substream)
193*6b8e4e7dSAkshu Agrawal {
194*6b8e4e7dSAkshu Agrawal 	rt5682_clk_disable();
195*6b8e4e7dSAkshu Agrawal }
196*6b8e4e7dSAkshu Agrawal 
197*6b8e4e7dSAkshu Agrawal static const struct snd_soc_ops acp3x_5682_ops = {
198*6b8e4e7dSAkshu Agrawal 	.startup = acp3x_5682_startup,
199*6b8e4e7dSAkshu Agrawal 	.shutdown = rt5682_shutdown,
200*6b8e4e7dSAkshu Agrawal };
201*6b8e4e7dSAkshu Agrawal 
202*6b8e4e7dSAkshu Agrawal static const struct snd_soc_ops acp3x_max_play_ops = {
203*6b8e4e7dSAkshu Agrawal 	.startup = acp3x_max_startup,
204*6b8e4e7dSAkshu Agrawal 	.shutdown = rt5682_shutdown,
205*6b8e4e7dSAkshu Agrawal };
206*6b8e4e7dSAkshu Agrawal 
207*6b8e4e7dSAkshu Agrawal static const struct snd_soc_ops acp3x_ec_cap_ops = {
208*6b8e4e7dSAkshu Agrawal 	.startup = acp3x_ec_startup,
209*6b8e4e7dSAkshu Agrawal 	.shutdown = rt5682_shutdown,
210*6b8e4e7dSAkshu Agrawal };
211*6b8e4e7dSAkshu Agrawal 
212*6b8e4e7dSAkshu Agrawal SND_SOC_DAILINK_DEF(acp3x_i2s,
213*6b8e4e7dSAkshu Agrawal 	DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0")));
214*6b8e4e7dSAkshu Agrawal SND_SOC_DAILINK_DEF(acp3x_bt,
215*6b8e4e7dSAkshu Agrawal 	DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.2")));
216*6b8e4e7dSAkshu Agrawal 
217*6b8e4e7dSAkshu Agrawal SND_SOC_DAILINK_DEF(rt5682,
218*6b8e4e7dSAkshu Agrawal 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
219*6b8e4e7dSAkshu Agrawal SND_SOC_DAILINK_DEF(max,
220*6b8e4e7dSAkshu Agrawal 	DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi")));
221*6b8e4e7dSAkshu Agrawal SND_SOC_DAILINK_DEF(cros_ec,
222*6b8e4e7dSAkshu Agrawal 	DAILINK_COMP_ARRAY(COMP_CODEC("GOOG0013:00", "EC Codec I2S RX")));
223*6b8e4e7dSAkshu Agrawal 
224*6b8e4e7dSAkshu Agrawal SND_SOC_DAILINK_DEF(platform,
225*6b8e4e7dSAkshu Agrawal 	DAILINK_COMP_ARRAY(COMP_PLATFORM("acp3x_rv_i2s_dma.0")));
226*6b8e4e7dSAkshu Agrawal 
227*6b8e4e7dSAkshu Agrawal static struct snd_soc_dai_link acp3x_dai_5682_98357[] = {
228*6b8e4e7dSAkshu Agrawal 	{
229*6b8e4e7dSAkshu Agrawal 		.name = "acp3x-5682-play",
230*6b8e4e7dSAkshu Agrawal 		.stream_name = "Playback",
231*6b8e4e7dSAkshu Agrawal 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
232*6b8e4e7dSAkshu Agrawal 				| SND_SOC_DAIFMT_CBM_CFM,
233*6b8e4e7dSAkshu Agrawal 		.init = acp3x_5682_init,
234*6b8e4e7dSAkshu Agrawal 		.dpcm_playback = 1,
235*6b8e4e7dSAkshu Agrawal 		.dpcm_capture = 1,
236*6b8e4e7dSAkshu Agrawal 		.ops = &acp3x_5682_ops,
237*6b8e4e7dSAkshu Agrawal 		SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform),
238*6b8e4e7dSAkshu Agrawal 	},
239*6b8e4e7dSAkshu Agrawal 	{
240*6b8e4e7dSAkshu Agrawal 		.name = "acp3x-max98357-play",
241*6b8e4e7dSAkshu Agrawal 		.stream_name = "HiFi Playback",
242*6b8e4e7dSAkshu Agrawal 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
243*6b8e4e7dSAkshu Agrawal 				| SND_SOC_DAIFMT_CBM_CFM,
244*6b8e4e7dSAkshu Agrawal 		.dpcm_playback = 1,
245*6b8e4e7dSAkshu Agrawal 		.ops = &acp3x_max_play_ops,
246*6b8e4e7dSAkshu Agrawal 		SND_SOC_DAILINK_REG(acp3x_bt, max, platform),
247*6b8e4e7dSAkshu Agrawal 	},
248*6b8e4e7dSAkshu Agrawal 	{
249*6b8e4e7dSAkshu Agrawal 		.name = "acp3x-ec-capture",
250*6b8e4e7dSAkshu Agrawal 		.stream_name = "Capture",
251*6b8e4e7dSAkshu Agrawal 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
252*6b8e4e7dSAkshu Agrawal 				| SND_SOC_DAIFMT_CBS_CFS,
253*6b8e4e7dSAkshu Agrawal 		.dpcm_capture = 1,
254*6b8e4e7dSAkshu Agrawal 		.ops = &acp3x_ec_cap_ops,
255*6b8e4e7dSAkshu Agrawal 		SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
256*6b8e4e7dSAkshu Agrawal 	},
257*6b8e4e7dSAkshu Agrawal };
258*6b8e4e7dSAkshu Agrawal 
259*6b8e4e7dSAkshu Agrawal static const struct snd_soc_dapm_widget acp3x_widgets[] = {
260*6b8e4e7dSAkshu Agrawal 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
261*6b8e4e7dSAkshu Agrawal 	SND_SOC_DAPM_SPK("Spk", NULL),
262*6b8e4e7dSAkshu Agrawal 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
263*6b8e4e7dSAkshu Agrawal };
264*6b8e4e7dSAkshu Agrawal 
265*6b8e4e7dSAkshu Agrawal static const struct snd_soc_dapm_route acp3x_audio_route[] = {
266*6b8e4e7dSAkshu Agrawal 	{"Headphone Jack", NULL, "HPOL"},
267*6b8e4e7dSAkshu Agrawal 	{"Headphone Jack", NULL, "HPOR"},
268*6b8e4e7dSAkshu Agrawal 	{"IN1P", NULL, "Headset Mic"},
269*6b8e4e7dSAkshu Agrawal 	{"Spk", NULL, "Speaker"},
270*6b8e4e7dSAkshu Agrawal };
271*6b8e4e7dSAkshu Agrawal 
272*6b8e4e7dSAkshu Agrawal static const struct snd_kcontrol_new acp3x_mc_controls[] = {
273*6b8e4e7dSAkshu Agrawal 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
274*6b8e4e7dSAkshu Agrawal 	SOC_DAPM_PIN_SWITCH("Spk"),
275*6b8e4e7dSAkshu Agrawal 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
276*6b8e4e7dSAkshu Agrawal };
277*6b8e4e7dSAkshu Agrawal 
278*6b8e4e7dSAkshu Agrawal static struct snd_soc_card acp3x_card = {
279*6b8e4e7dSAkshu Agrawal 	.name = "acp3xalc5682m98357",
280*6b8e4e7dSAkshu Agrawal 	.owner = THIS_MODULE,
281*6b8e4e7dSAkshu Agrawal 	.dai_link = acp3x_dai_5682_98357,
282*6b8e4e7dSAkshu Agrawal 	.num_links = ARRAY_SIZE(acp3x_dai_5682_98357),
283*6b8e4e7dSAkshu Agrawal 	.dapm_widgets = acp3x_widgets,
284*6b8e4e7dSAkshu Agrawal 	.num_dapm_widgets = ARRAY_SIZE(acp3x_widgets),
285*6b8e4e7dSAkshu Agrawal 	.dapm_routes = acp3x_audio_route,
286*6b8e4e7dSAkshu Agrawal 	.num_dapm_routes = ARRAY_SIZE(acp3x_audio_route),
287*6b8e4e7dSAkshu Agrawal 	.controls = acp3x_mc_controls,
288*6b8e4e7dSAkshu Agrawal 	.num_controls = ARRAY_SIZE(acp3x_mc_controls),
289*6b8e4e7dSAkshu Agrawal };
290*6b8e4e7dSAkshu Agrawal 
291*6b8e4e7dSAkshu Agrawal static int acp3x_probe(struct platform_device *pdev)
292*6b8e4e7dSAkshu Agrawal {
293*6b8e4e7dSAkshu Agrawal 	int ret;
294*6b8e4e7dSAkshu Agrawal 	struct snd_soc_card *card;
295*6b8e4e7dSAkshu Agrawal 	struct acp3x_platform_info *machine;
296*6b8e4e7dSAkshu Agrawal 
297*6b8e4e7dSAkshu Agrawal 	machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL);
298*6b8e4e7dSAkshu Agrawal 	if (!machine)
299*6b8e4e7dSAkshu Agrawal 		return -ENOMEM;
300*6b8e4e7dSAkshu Agrawal 
301*6b8e4e7dSAkshu Agrawal 	card = &acp3x_card;
302*6b8e4e7dSAkshu Agrawal 	acp3x_card.dev = &pdev->dev;
303*6b8e4e7dSAkshu Agrawal 	platform_set_drvdata(pdev, card);
304*6b8e4e7dSAkshu Agrawal 	snd_soc_card_set_drvdata(card, machine);
305*6b8e4e7dSAkshu Agrawal 	ret = devm_snd_soc_register_card(&pdev->dev, &acp3x_card);
306*6b8e4e7dSAkshu Agrawal 	if (ret) {
307*6b8e4e7dSAkshu Agrawal 		dev_err(&pdev->dev,
308*6b8e4e7dSAkshu Agrawal 				"devm_snd_soc_register_card(%s) failed: %d\n",
309*6b8e4e7dSAkshu Agrawal 				acp3x_card.name, ret);
310*6b8e4e7dSAkshu Agrawal 		return ret;
311*6b8e4e7dSAkshu Agrawal 	}
312*6b8e4e7dSAkshu Agrawal 	return 0;
313*6b8e4e7dSAkshu Agrawal }
314*6b8e4e7dSAkshu Agrawal 
315*6b8e4e7dSAkshu Agrawal static const struct acpi_device_id acp3x_audio_acpi_match[] = {
316*6b8e4e7dSAkshu Agrawal 	{ "AMDI5682", 0 },
317*6b8e4e7dSAkshu Agrawal 	{},
318*6b8e4e7dSAkshu Agrawal };
319*6b8e4e7dSAkshu Agrawal MODULE_DEVICE_TABLE(acpi, acp3x_audio_acpi_match);
320*6b8e4e7dSAkshu Agrawal 
321*6b8e4e7dSAkshu Agrawal static struct platform_driver acp3x_audio = {
322*6b8e4e7dSAkshu Agrawal 	.driver = {
323*6b8e4e7dSAkshu Agrawal 		.name = "acp3x-alc5682-max98357",
324*6b8e4e7dSAkshu Agrawal 		.acpi_match_table = ACPI_PTR(acp3x_audio_acpi_match),
325*6b8e4e7dSAkshu Agrawal 		.pm = &snd_soc_pm_ops,
326*6b8e4e7dSAkshu Agrawal 	},
327*6b8e4e7dSAkshu Agrawal 	.probe = acp3x_probe,
328*6b8e4e7dSAkshu Agrawal };
329*6b8e4e7dSAkshu Agrawal 
330*6b8e4e7dSAkshu Agrawal module_platform_driver(acp3x_audio);
331*6b8e4e7dSAkshu Agrawal 
332*6b8e4e7dSAkshu Agrawal MODULE_AUTHOR("akshu.agrawal@amd.com");
333*6b8e4e7dSAkshu Agrawal MODULE_DESCRIPTION("ALC5682 & MAX98357 audio support");
334*6b8e4e7dSAkshu Agrawal MODULE_LICENSE("GPL v2");
335