1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec.
4 //
5 //Copyright 2016 Advanced Micro Devices, Inc.
6
7 #include <sound/core.h>
8 #include <sound/soc.h>
9 #include <sound/pcm.h>
10 #include <sound/pcm_params.h>
11 #include <sound/soc-dapm.h>
12 #include <sound/jack.h>
13 #include <linux/clk.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/module.h>
16 #include <linux/i2c.h>
17 #include <linux/input.h>
18 #include <linux/io.h>
19 #include <linux/acpi.h>
20
21 #include "raven/acp3x.h"
22 #include "../codecs/rt5682.h"
23 #include "../codecs/rt1015.h"
24
25 #define PCO_PLAT_CLK 48000000
26 #define RT5682_PLL_FREQ (48000 * 512)
27 #define DUAL_CHANNEL 2
28
29 static struct snd_soc_jack pco_jack;
30 static struct snd_soc_jack_pin pco_jack_pins[] = {
31 {
32 .pin = "Headphone Jack",
33 .mask = SND_JACK_HEADPHONE,
34 },
35 {
36 .pin = "Headset Mic",
37 .mask = SND_JACK_MICROPHONE,
38 },
39 };
40
41 static struct clk *rt5682_dai_wclk;
42 static struct clk *rt5682_dai_bclk;
43 static struct gpio_desc *dmic_sel;
44 void *soc_is_rltk_max(struct device *dev);
45
46 enum {
47 RT5682 = 0,
48 MAX,
49 EC,
50 };
51
acp3x_5682_init(struct snd_soc_pcm_runtime * rtd)52 static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd)
53 {
54 int ret;
55 struct snd_soc_card *card = rtd->card;
56 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
57 struct snd_soc_component *component = codec_dai->component;
58
59 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
60
61 /* set rt5682 dai fmt */
62 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
63 | SND_SOC_DAIFMT_NB_NF
64 | SND_SOC_DAIFMT_CBP_CFP);
65 if (ret < 0) {
66 dev_err(rtd->card->dev,
67 "Failed to set rt5682 dai fmt: %d\n", ret);
68 return ret;
69 }
70
71 /* set codec PLL */
72 ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
73 PCO_PLAT_CLK, RT5682_PLL_FREQ);
74 if (ret < 0) {
75 dev_err(rtd->dev, "can't set rt5682 PLL: %d\n", ret);
76 return ret;
77 }
78
79 /* Set codec sysclk */
80 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
81 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
82 if (ret < 0) {
83 dev_err(rtd->dev,
84 "Failed to set rt5682 SYSCLK: %d\n", ret);
85 return ret;
86 }
87
88 /* Set tdm/i2s1 master bclk ratio */
89 ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
90 if (ret < 0) {
91 dev_err(rtd->dev,
92 "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
93 return ret;
94 }
95
96 rt5682_dai_wclk = devm_clk_get(component->dev, "rt5682-dai-wclk");
97 if (IS_ERR(rt5682_dai_wclk))
98 return PTR_ERR(rt5682_dai_wclk);
99
100 rt5682_dai_bclk = devm_clk_get(component->dev, "rt5682-dai-bclk");
101 if (IS_ERR(rt5682_dai_bclk))
102 return PTR_ERR(rt5682_dai_bclk);
103
104 ret = snd_soc_card_jack_new_pins(card, "Headset Jack",
105 SND_JACK_HEADSET |
106 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
107 SND_JACK_BTN_2 | SND_JACK_BTN_3,
108 &pco_jack,
109 pco_jack_pins,
110 ARRAY_SIZE(pco_jack_pins));
111 if (ret) {
112 dev_err(card->dev, "HP jack creation failed %d\n", ret);
113 return ret;
114 }
115
116 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
117 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
118 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
119 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
120
121 ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
122 if (ret) {
123 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
124 return ret;
125 }
126
127 return ret;
128 }
129
rt5682_clk_enable(struct snd_pcm_substream * substream)130 static int rt5682_clk_enable(struct snd_pcm_substream *substream)
131 {
132 int ret = 0;
133 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
134
135 /* RT5682 will support only 48K output with 48M mclk */
136 clk_set_rate(rt5682_dai_wclk, 48000);
137 clk_set_rate(rt5682_dai_bclk, 48000 * 64);
138 ret = clk_prepare_enable(rt5682_dai_wclk);
139 if (ret < 0) {
140 dev_err(rtd->dev, "can't enable wclk %d\n", ret);
141 return ret;
142 }
143
144 return ret;
145 }
146
acp3x_1015_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)147 static int acp3x_1015_hw_params(struct snd_pcm_substream *substream,
148 struct snd_pcm_hw_params *params)
149 {
150 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
151 struct snd_soc_dai *codec_dai;
152 int srate, i, ret;
153
154 ret = 0;
155 srate = params_rate(params);
156
157 for_each_rtd_codec_dais(rtd, i, codec_dai) {
158 if (strcmp(codec_dai->name, "rt1015-aif"))
159 continue;
160
161 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
162 64 * srate, 256 * srate);
163 if (ret < 0)
164 return ret;
165 ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
166 256 * srate, SND_SOC_CLOCK_IN);
167 if (ret < 0)
168 return ret;
169 }
170 return ret;
171 }
172
rt5682_clk_disable(void)173 static void rt5682_clk_disable(void)
174 {
175 clk_disable_unprepare(rt5682_dai_wclk);
176 }
177
178 static const unsigned int channels[] = {
179 DUAL_CHANNEL,
180 };
181
182 static const unsigned int rates[] = {
183 48000,
184 };
185
186 static const struct snd_pcm_hw_constraint_list constraints_rates = {
187 .count = ARRAY_SIZE(rates),
188 .list = rates,
189 .mask = 0,
190 };
191
192 static const struct snd_pcm_hw_constraint_list constraints_channels = {
193 .count = ARRAY_SIZE(channels),
194 .list = channels,
195 .mask = 0,
196 };
197
acp3x_5682_startup(struct snd_pcm_substream * substream)198 static int acp3x_5682_startup(struct snd_pcm_substream *substream)
199 {
200 struct snd_pcm_runtime *runtime = substream->runtime;
201 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
202 struct snd_soc_card *card = rtd->card;
203 struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
204
205 machine->play_i2s_instance = I2S_SP_INSTANCE;
206 machine->cap_i2s_instance = I2S_SP_INSTANCE;
207
208 runtime->hw.channels_max = DUAL_CHANNEL;
209 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
210 &constraints_channels);
211 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
212 &constraints_rates);
213 return rt5682_clk_enable(substream);
214 }
215
acp3x_max_startup(struct snd_pcm_substream * substream)216 static int acp3x_max_startup(struct snd_pcm_substream *substream)
217 {
218 struct snd_pcm_runtime *runtime = substream->runtime;
219 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
220 struct snd_soc_card *card = rtd->card;
221 struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
222
223 machine->play_i2s_instance = I2S_BT_INSTANCE;
224
225 runtime->hw.channels_max = DUAL_CHANNEL;
226 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
227 &constraints_channels);
228 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
229 &constraints_rates);
230 return rt5682_clk_enable(substream);
231 }
232
acp3x_ec_dmic0_startup(struct snd_pcm_substream * substream)233 static int acp3x_ec_dmic0_startup(struct snd_pcm_substream *substream)
234 {
235 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
236 struct snd_soc_card *card = rtd->card;
237 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
238 struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
239
240 machine->cap_i2s_instance = I2S_BT_INSTANCE;
241 snd_soc_dai_set_bclk_ratio(codec_dai, 64);
242
243 return rt5682_clk_enable(substream);
244 }
245
246 static int dmic_switch;
247
dmic_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)248 static int dmic_get(struct snd_kcontrol *kcontrol,
249 struct snd_ctl_elem_value *ucontrol)
250 {
251 ucontrol->value.integer.value[0] = dmic_switch;
252 return 0;
253 }
254
dmic_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)255 static int dmic_set(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_value *ucontrol)
257 {
258 if (dmic_sel) {
259 dmic_switch = ucontrol->value.integer.value[0];
260 gpiod_set_value(dmic_sel, dmic_switch);
261 }
262 return 0;
263 }
264
rt5682_shutdown(struct snd_pcm_substream * substream)265 static void rt5682_shutdown(struct snd_pcm_substream *substream)
266 {
267 rt5682_clk_disable();
268 }
269
270 static const struct snd_soc_ops acp3x_5682_ops = {
271 .startup = acp3x_5682_startup,
272 .shutdown = rt5682_shutdown,
273 };
274
275 static const struct snd_soc_ops acp3x_max_play_ops = {
276 .startup = acp3x_max_startup,
277 .shutdown = rt5682_shutdown,
278 .hw_params = acp3x_1015_hw_params,
279 };
280
281 static const struct snd_soc_ops acp3x_ec_cap0_ops = {
282 .startup = acp3x_ec_dmic0_startup,
283 .shutdown = rt5682_shutdown,
284 };
285
286 SND_SOC_DAILINK_DEF(acp3x_i2s,
287 DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0")));
288 SND_SOC_DAILINK_DEF(acp3x_bt,
289 DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.2")));
290
291 SND_SOC_DAILINK_DEF(rt5682,
292 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
293 SND_SOC_DAILINK_DEF(max,
294 DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi")));
295 SND_SOC_DAILINK_DEF(rt1015p,
296 DAILINK_COMP_ARRAY(COMP_CODEC("RTL1015:00", "HiFi")));
297 SND_SOC_DAILINK_DEF(rt1015,
298 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1015:00", "rt1015-aif"),
299 COMP_CODEC("i2c-10EC1015:01", "rt1015-aif")));
300 SND_SOC_DAILINK_DEF(cros_ec,
301 DAILINK_COMP_ARRAY(COMP_CODEC("GOOG0013:00", "EC Codec I2S RX")));
302
303 SND_SOC_DAILINK_DEF(platform,
304 DAILINK_COMP_ARRAY(COMP_PLATFORM("acp3x_rv_i2s_dma.0")));
305
306 static struct snd_soc_codec_conf rt1015_conf[] = {
307 {
308 .dlc = COMP_CODEC_CONF("i2c-10EC1015:00"),
309 .name_prefix = "Left",
310 },
311 {
312 .dlc = COMP_CODEC_CONF("i2c-10EC1015:01"),
313 .name_prefix = "Right",
314 },
315 };
316
317 static struct snd_soc_dai_link acp3x_dai[] = {
318 [RT5682] = {
319 .name = "acp3x-5682-play",
320 .stream_name = "Playback",
321 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
322 | SND_SOC_DAIFMT_CBP_CFP,
323 .init = acp3x_5682_init,
324 .ops = &acp3x_5682_ops,
325 SND_SOC_DAILINK_REG(acp3x_i2s, rt5682, platform),
326 },
327 [MAX] = {
328 .name = "acp3x-max98357-play",
329 .stream_name = "HiFi Playback",
330 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
331 | SND_SOC_DAIFMT_CBC_CFC,
332 .playback_only = 1,
333 .ops = &acp3x_max_play_ops,
334 .cpus = acp3x_bt,
335 .num_cpus = ARRAY_SIZE(acp3x_bt),
336 .platforms = platform,
337 .num_platforms = ARRAY_SIZE(platform),
338 },
339 [EC] = {
340 .name = "acp3x-ec-dmic0-capture",
341 .stream_name = "Capture DMIC0",
342 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
343 | SND_SOC_DAIFMT_CBC_CFC,
344 .capture_only = 1,
345 .ops = &acp3x_ec_cap0_ops,
346 SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
347 },
348 };
349
350 static const char * const dmic_mux_text[] = {
351 "Front Mic",
352 "Rear Mic",
353 };
354
355 static SOC_ENUM_SINGLE_DECL(
356 acp3x_dmic_enum, SND_SOC_NOPM, 0, dmic_mux_text);
357
358 static const struct snd_kcontrol_new acp3x_dmic_mux_control =
359 SOC_DAPM_ENUM_EXT("DMIC Select Mux", acp3x_dmic_enum,
360 dmic_get, dmic_set);
361
362 static const struct snd_soc_dapm_widget acp3x_5682_widgets[] = {
363 SND_SOC_DAPM_HP("Headphone Jack", NULL),
364 SND_SOC_DAPM_SPK("Spk", NULL),
365 SND_SOC_DAPM_MIC("Headset Mic", NULL),
366 SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0,
367 &acp3x_dmic_mux_control),
368 };
369
370 static const struct snd_soc_dapm_route acp3x_5682_audio_route[] = {
371 {"Headphone Jack", NULL, "HPOL"},
372 {"Headphone Jack", NULL, "HPOR"},
373 {"IN1P", NULL, "Headset Mic"},
374 {"Spk", NULL, "Speaker"},
375 {"Dmic Mux", "Front Mic", "DMIC"},
376 {"Dmic Mux", "Rear Mic", "DMIC"},
377 };
378
379 static const struct snd_kcontrol_new acp3x_5682_mc_controls[] = {
380 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
381 SOC_DAPM_PIN_SWITCH("Spk"),
382 SOC_DAPM_PIN_SWITCH("Headset Mic"),
383 };
384
385 static struct snd_soc_card acp3x_5682 = {
386 .name = "acp3xalc5682m98357",
387 .owner = THIS_MODULE,
388 .dai_link = acp3x_dai,
389 .num_links = ARRAY_SIZE(acp3x_dai),
390 .dapm_widgets = acp3x_5682_widgets,
391 .num_dapm_widgets = ARRAY_SIZE(acp3x_5682_widgets),
392 .dapm_routes = acp3x_5682_audio_route,
393 .num_dapm_routes = ARRAY_SIZE(acp3x_5682_audio_route),
394 .controls = acp3x_5682_mc_controls,
395 .num_controls = ARRAY_SIZE(acp3x_5682_mc_controls),
396 };
397
398 static const struct snd_soc_dapm_widget acp3x_1015_widgets[] = {
399 SND_SOC_DAPM_HP("Headphone Jack", NULL),
400 SND_SOC_DAPM_MIC("Headset Mic", NULL),
401 SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0,
402 &acp3x_dmic_mux_control),
403 SND_SOC_DAPM_SPK("Left Spk", NULL),
404 SND_SOC_DAPM_SPK("Right Spk", NULL),
405 };
406
407 static const struct snd_soc_dapm_route acp3x_1015_route[] = {
408 {"Headphone Jack", NULL, "HPOL"},
409 {"Headphone Jack", NULL, "HPOR"},
410 {"IN1P", NULL, "Headset Mic"},
411 {"Dmic Mux", "Front Mic", "DMIC"},
412 {"Dmic Mux", "Rear Mic", "DMIC"},
413 {"Left Spk", NULL, "Left SPO"},
414 {"Right Spk", NULL, "Right SPO"},
415 };
416
417 static const struct snd_kcontrol_new acp3x_mc_1015_controls[] = {
418 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
419 SOC_DAPM_PIN_SWITCH("Headset Mic"),
420 SOC_DAPM_PIN_SWITCH("Left Spk"),
421 SOC_DAPM_PIN_SWITCH("Right Spk"),
422 };
423
424 static struct snd_soc_card acp3x_1015 = {
425 .name = "acp3xalc56821015",
426 .owner = THIS_MODULE,
427 .dai_link = acp3x_dai,
428 .num_links = ARRAY_SIZE(acp3x_dai),
429 .dapm_widgets = acp3x_1015_widgets,
430 .num_dapm_widgets = ARRAY_SIZE(acp3x_1015_widgets),
431 .dapm_routes = acp3x_1015_route,
432 .num_dapm_routes = ARRAY_SIZE(acp3x_1015_route),
433 .codec_conf = rt1015_conf,
434 .num_configs = ARRAY_SIZE(rt1015_conf),
435 .controls = acp3x_mc_1015_controls,
436 .num_controls = ARRAY_SIZE(acp3x_mc_1015_controls),
437 };
438
439 static const struct snd_soc_dapm_widget acp3x_1015p_widgets[] = {
440 SND_SOC_DAPM_HP("Headphone Jack", NULL),
441 SND_SOC_DAPM_MIC("Headset Mic", NULL),
442 SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0,
443 &acp3x_dmic_mux_control),
444 SND_SOC_DAPM_SPK("Speakers", NULL),
445 };
446
447 static const struct snd_soc_dapm_route acp3x_1015p_route[] = {
448 {"Headphone Jack", NULL, "HPOL"},
449 {"Headphone Jack", NULL, "HPOR"},
450 {"IN1P", NULL, "Headset Mic"},
451 {"Dmic Mux", "Front Mic", "DMIC"},
452 {"Dmic Mux", "Rear Mic", "DMIC"},
453 /* speaker */
454 { "Speakers", NULL, "Speaker" },
455 };
456
457 static const struct snd_kcontrol_new acp3x_mc_1015p_controls[] = {
458 SOC_DAPM_PIN_SWITCH("Speakers"),
459 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
460 SOC_DAPM_PIN_SWITCH("Headset Mic"),
461 };
462
463 static struct snd_soc_card acp3x_1015p = {
464 .name = "acp3xalc56821015p",
465 .owner = THIS_MODULE,
466 .dai_link = acp3x_dai,
467 .num_links = ARRAY_SIZE(acp3x_dai),
468 .dapm_widgets = acp3x_1015p_widgets,
469 .num_dapm_widgets = ARRAY_SIZE(acp3x_1015p_widgets),
470 .dapm_routes = acp3x_1015p_route,
471 .num_dapm_routes = ARRAY_SIZE(acp3x_1015p_route),
472 .controls = acp3x_mc_1015p_controls,
473 .num_controls = ARRAY_SIZE(acp3x_mc_1015p_controls),
474 };
475
soc_is_rltk_max(struct device * dev)476 void *soc_is_rltk_max(struct device *dev)
477 {
478 const struct acpi_device_id *match;
479
480 match = acpi_match_device(dev->driver->acpi_match_table, dev);
481 if (!match)
482 return NULL;
483 return (void *)match->driver_data;
484 }
485
card_spk_dai_link_present(struct snd_soc_dai_link * links,const char * card_name)486 static void card_spk_dai_link_present(struct snd_soc_dai_link *links,
487 const char *card_name)
488 {
489 if (!strcmp(card_name, "acp3xalc56821015")) {
490 links[1].codecs = rt1015;
491 links[1].num_codecs = ARRAY_SIZE(rt1015);
492 } else if (!strcmp(card_name, "acp3xalc56821015p")) {
493 links[1].codecs = rt1015p;
494 links[1].num_codecs = ARRAY_SIZE(rt1015p);
495 } else {
496 links[1].codecs = max;
497 links[1].num_codecs = ARRAY_SIZE(max);
498 }
499 }
500
acp3x_probe(struct platform_device * pdev)501 static int acp3x_probe(struct platform_device *pdev)
502 {
503 int ret;
504 struct snd_soc_card *card;
505 struct acp3x_platform_info *machine;
506 struct device *dev = &pdev->dev;
507
508 card = (struct snd_soc_card *)soc_is_rltk_max(dev);
509 if (!card)
510 return -ENODEV;
511
512 machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL);
513 if (!machine)
514 return -ENOMEM;
515
516 card_spk_dai_link_present(card->dai_link, card->name);
517 card->dev = &pdev->dev;
518 platform_set_drvdata(pdev, card);
519 snd_soc_card_set_drvdata(card, machine);
520
521 dmic_sel = devm_gpiod_get(&pdev->dev, "dmic", GPIOD_OUT_LOW);
522 if (IS_ERR(dmic_sel)) {
523 dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n",
524 PTR_ERR(dmic_sel));
525 return PTR_ERR(dmic_sel);
526 }
527
528 ret = devm_snd_soc_register_card(&pdev->dev, card);
529 if (ret) {
530 return dev_err_probe(&pdev->dev, ret,
531 "devm_snd_soc_register_card(%s) failed\n",
532 card->name);
533 }
534 return 0;
535 }
536
537 static const struct acpi_device_id acp3x_audio_acpi_match[] = {
538 { "AMDI5682", (unsigned long)&acp3x_5682},
539 { "AMDI1015", (unsigned long)&acp3x_1015},
540 { "10021015", (unsigned long)&acp3x_1015p},
541 {},
542 };
543 MODULE_DEVICE_TABLE(acpi, acp3x_audio_acpi_match);
544
545 static struct platform_driver acp3x_audio = {
546 .driver = {
547 .name = "acp3x-alc5682-max98357",
548 .acpi_match_table = ACPI_PTR(acp3x_audio_acpi_match),
549 .pm = &snd_soc_pm_ops,
550 },
551 .probe = acp3x_probe,
552 };
553
554 module_platform_driver(acp3x_audio);
555
556 MODULE_AUTHOR("akshu.agrawal@amd.com");
557 MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
558 MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
559 MODULE_DESCRIPTION("ALC5682 ALC1015, ALC1015P & MAX98357 audio support");
560 MODULE_LICENSE("GPL v2");
561