xref: /linux/sound/soc/qcom/sc7180.c (revision d30c1683aaecb93d2ab95685dc4300a33d3cea7a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright (c) 2020, The Linux Foundation. All rights reserved.
4 //
5 // sc7180.c -- ALSA SoC Machine driver for SC7180
6 
7 #include <dt-bindings/sound/sc7180-lpass.h>
8 #include <dt-bindings/sound/qcom,q6afe.h>
9 #include <linux/gpio/consumer.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <sound/core.h>
14 #include <sound/jack.h>
15 #include <sound/pcm.h>
16 #include <sound/soc.h>
17 #include <uapi/linux/input-event-codes.h>
18 
19 #include "../codecs/rt5682.h"
20 #include "../codecs/rt5682s.h"
21 #include "common.h"
22 #include "qdsp6/q6afe.h"
23 
24 #define DEFAULT_MCLK_RATE		19200000
25 #define MI2S_BCLK_RATE			1536000
26 #define RT5682_PLL1_FREQ (48000 * 512)
27 
28 #define DRIVER_NAME "SC7180"
29 
30 struct sc7180_snd_data {
31 	struct snd_soc_card card;
32 	u32 pri_mi2s_clk_count;
33 	struct snd_soc_jack hs_jack;
34 	struct snd_soc_jack hdmi_jack;
35 	struct gpio_desc *dmic_sel;
36 	int dmic_switch;
37 };
38 
39 static void sc7180_jack_free(struct snd_jack *jack)
40 {
41 	struct snd_soc_component *component = jack->private_data;
42 
43 	snd_soc_component_set_jack(component, NULL, NULL);
44 }
45 
46 static struct snd_soc_jack_pin sc7180_jack_pins[] = {
47 	{
48 		.pin = "Headphone Jack",
49 		.mask = SND_JACK_HEADPHONE,
50 	},
51 	{
52 		.pin = "Headset Mic",
53 		.mask = SND_JACK_MICROPHONE,
54 	},
55 };
56 
57 static int sc7180_headset_init(struct snd_soc_pcm_runtime *rtd)
58 {
59 	struct snd_soc_card *card = rtd->card;
60 	struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
61 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
62 	struct snd_soc_component *component = codec_dai->component;
63 	struct snd_jack *jack;
64 	int rval;
65 
66 	rval = snd_soc_card_jack_new_pins(card, "Headset Jack",
67 					  SND_JACK_HEADSET |
68 					  SND_JACK_HEADPHONE |
69 					  SND_JACK_BTN_0 | SND_JACK_BTN_1 |
70 					  SND_JACK_BTN_2 | SND_JACK_BTN_3,
71 					  &pdata->hs_jack,
72 					  sc7180_jack_pins,
73 					  ARRAY_SIZE(sc7180_jack_pins));
74 
75 	if (rval < 0) {
76 		dev_err(card->dev, "Unable to add Headset Jack\n");
77 		return rval;
78 	}
79 
80 	jack = pdata->hs_jack.jack;
81 
82 	snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
83 	snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
84 	snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
85 	snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
86 
87 	jack->private_data = component;
88 	jack->private_free = sc7180_jack_free;
89 
90 	return snd_soc_component_set_jack(component, &pdata->hs_jack, NULL);
91 }
92 
93 static int sc7180_hdmi_init(struct snd_soc_pcm_runtime *rtd)
94 {
95 	struct snd_soc_card *card = rtd->card;
96 	struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
97 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
98 	struct snd_soc_component *component = codec_dai->component;
99 	struct snd_jack *jack;
100 	int rval;
101 
102 	rval = snd_soc_card_jack_new(
103 			card, "HDMI Jack",
104 			SND_JACK_LINEOUT,
105 			&pdata->hdmi_jack);
106 
107 	if (rval < 0) {
108 		dev_err(card->dev, "Unable to add HDMI Jack\n");
109 		return rval;
110 	}
111 
112 	jack = pdata->hdmi_jack.jack;
113 	jack->private_data = component;
114 	jack->private_free = sc7180_jack_free;
115 
116 	return snd_soc_component_set_jack(component, &pdata->hdmi_jack, NULL);
117 }
118 
119 static int sc7180_init(struct snd_soc_pcm_runtime *rtd)
120 {
121 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
122 
123 	switch (cpu_dai->id) {
124 	case MI2S_PRIMARY:
125 		return sc7180_headset_init(rtd);
126 	case MI2S_SECONDARY:
127 		return 0;
128 	case LPASS_DP_RX:
129 		return sc7180_hdmi_init(rtd);
130 	default:
131 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
132 			cpu_dai->id);
133 		return -EINVAL;
134 	}
135 	return 0;
136 }
137 
138 static int sc7180_qdsp_init(struct snd_soc_pcm_runtime *rtd)
139 {
140 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
141 
142 	switch (cpu_dai->id) {
143 	case PRIMARY_MI2S_RX:
144 		return sc7180_headset_init(rtd);
145 	case PRIMARY_MI2S_TX:
146 	case TERTIARY_MI2S_RX:
147 		return 0;
148 	case DISPLAY_PORT_RX:
149 		return sc7180_hdmi_init(rtd);
150 	default:
151 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
152 			cpu_dai->id);
153 		return -EINVAL;
154 	}
155 	return 0;
156 }
157 
158 static int sc7180_startup_realtek_codec(struct snd_soc_pcm_runtime *rtd)
159 {
160 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
161 	int pll_id, pll_source, pll_in, pll_out, clk_id, ret;
162 
163 	if (!strcmp(codec_dai->name, "rt5682-aif1")) {
164 		pll_source = RT5682_PLL1_S_MCLK;
165 		pll_id = 0;
166 		clk_id = RT5682_SCLK_S_PLL1;
167 		pll_out = RT5682_PLL1_FREQ;
168 		pll_in = DEFAULT_MCLK_RATE;
169 	} else if (!strcmp(codec_dai->name, "rt5682s-aif1")) {
170 		pll_source = RT5682S_PLL_S_MCLK;
171 		pll_id = RT5682S_PLL2;
172 		clk_id = RT5682S_SCLK_S_PLL2;
173 		pll_out = RT5682_PLL1_FREQ;
174 		pll_in = DEFAULT_MCLK_RATE;
175 	} else {
176 		return 0;
177 	}
178 	snd_soc_dai_set_fmt(codec_dai,
179 			    SND_SOC_DAIFMT_BC_FC |
180 			    SND_SOC_DAIFMT_NB_NF |
181 			    SND_SOC_DAIFMT_I2S);
182 
183 	/* Configure PLL1 for codec */
184 	ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source,
185 				  pll_in, pll_out);
186 	if (ret) {
187 		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
188 		return ret;
189 	}
190 
191 	/* Configure sysclk for codec */
192 	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, pll_out,
193 				     SND_SOC_CLOCK_IN);
194 	if (ret)
195 		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
196 			ret);
197 
198 	return ret;
199 }
200 
201 static int sc7180_snd_startup(struct snd_pcm_substream *substream)
202 {
203 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
204 	struct snd_soc_card *card = rtd->card;
205 	struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
206 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
207 	int ret;
208 
209 	switch (cpu_dai->id) {
210 	case MI2S_PRIMARY:
211 		if (++data->pri_mi2s_clk_count == 1) {
212 			snd_soc_dai_set_sysclk(cpu_dai,
213 					       LPASS_MCLK0,
214 					       DEFAULT_MCLK_RATE,
215 					       SNDRV_PCM_STREAM_PLAYBACK);
216 		}
217 
218 		ret = sc7180_startup_realtek_codec(rtd);
219 		if (ret)
220 			return ret;
221 
222 		break;
223 	case MI2S_SECONDARY:
224 		break;
225 	case LPASS_DP_RX:
226 		break;
227 	default:
228 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
229 			cpu_dai->id);
230 		return -EINVAL;
231 	}
232 	return 0;
233 }
234 
235 static int sc7180_qdsp_snd_startup(struct snd_pcm_substream *substream)
236 {
237 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
238 	struct snd_soc_card *card = rtd->card;
239 	struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
240 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
241 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
242 	int ret;
243 
244 	switch (cpu_dai->id) {
245 	case PRIMARY_MI2S_RX:
246 	case PRIMARY_MI2S_TX:
247 		if (++data->pri_mi2s_clk_count == 1) {
248 			snd_soc_dai_set_sysclk(cpu_dai,
249 					       Q6AFE_LPASS_CLK_ID_MCLK_1,
250 					       DEFAULT_MCLK_RATE,
251 					       SNDRV_PCM_STREAM_PLAYBACK);
252 			snd_soc_dai_set_sysclk(cpu_dai,
253 					       Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
254 					       MI2S_BCLK_RATE,
255 					       SNDRV_PCM_STREAM_PLAYBACK);
256 		}
257 
258 		snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP);
259 
260 		ret = sc7180_startup_realtek_codec(rtd);
261 		if (ret)
262 			return ret;
263 
264 		break;
265 	case TERTIARY_MI2S_RX:
266 		snd_soc_dai_set_sysclk(cpu_dai,
267 				       Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
268 				       MI2S_BCLK_RATE,
269 				       SNDRV_PCM_STREAM_PLAYBACK);
270 
271 		snd_soc_dai_set_fmt(codec_dai,
272 				SND_SOC_DAIFMT_BC_FC |
273 				SND_SOC_DAIFMT_NB_NF |
274 				SND_SOC_DAIFMT_I2S);
275 		snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP);
276 		break;
277 	case DISPLAY_PORT_RX:
278 		break;
279 	default:
280 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
281 			cpu_dai->id);
282 		return -EINVAL;
283 	}
284 	return 0;
285 }
286 
287 static int dmic_get(struct snd_kcontrol *kcontrol,
288 		    struct snd_ctl_elem_value *ucontrol)
289 {
290 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
291 	struct snd_soc_card *card = snd_soc_dapm_to_card(dapm);
292 	struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
293 
294 	ucontrol->value.integer.value[0] = data->dmic_switch;
295 	return 0;
296 }
297 
298 static int dmic_set(struct snd_kcontrol *kcontrol,
299 		    struct snd_ctl_elem_value *ucontrol)
300 {
301 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
302 	struct snd_soc_card *card = snd_soc_dapm_to_card(dapm);
303 	struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
304 
305 	data->dmic_switch = ucontrol->value.integer.value[0];
306 	gpiod_set_value(data->dmic_sel, data->dmic_switch);
307 	return 0;
308 }
309 
310 static void sc7180_snd_shutdown(struct snd_pcm_substream *substream)
311 {
312 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
313 	struct snd_soc_card *card = rtd->card;
314 	struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
315 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
316 
317 	switch (cpu_dai->id) {
318 	case MI2S_PRIMARY:
319 		if (--data->pri_mi2s_clk_count == 0) {
320 			snd_soc_dai_set_sysclk(cpu_dai,
321 					       LPASS_MCLK0,
322 					       0,
323 					       SNDRV_PCM_STREAM_PLAYBACK);
324 		}
325 		break;
326 	case MI2S_SECONDARY:
327 		break;
328 	case LPASS_DP_RX:
329 		break;
330 	default:
331 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
332 			cpu_dai->id);
333 		break;
334 	}
335 }
336 
337 static void sc7180_qdsp_snd_shutdown(struct snd_pcm_substream *substream)
338 {
339 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
340 	struct snd_soc_card *card = rtd->card;
341 	struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
342 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
343 
344 	switch (cpu_dai->id) {
345 	case PRIMARY_MI2S_RX:
346 	case PRIMARY_MI2S_TX:
347 		if (--data->pri_mi2s_clk_count == 0) {
348 			snd_soc_dai_set_sysclk(cpu_dai,
349 					       Q6AFE_LPASS_CLK_ID_MCLK_1,
350 					       0,
351 					       SNDRV_PCM_STREAM_PLAYBACK);
352 			snd_soc_dai_set_sysclk(cpu_dai,
353 					       Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
354 					       0,
355 					       SNDRV_PCM_STREAM_PLAYBACK);
356 		}
357 		break;
358 	case TERTIARY_MI2S_RX:
359 		snd_soc_dai_set_sysclk(cpu_dai,
360 				       Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
361 				       0,
362 				       SNDRV_PCM_STREAM_PLAYBACK);
363 		break;
364 	case DISPLAY_PORT_RX:
365 		break;
366 	default:
367 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
368 			cpu_dai->id);
369 		break;
370 	}
371 }
372 
373 static int sc7180_adau7002_init(struct snd_soc_pcm_runtime *rtd)
374 {
375 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
376 
377 	switch (cpu_dai->id) {
378 	case MI2S_PRIMARY:
379 		return 0;
380 	case MI2S_SECONDARY:
381 		return 0;
382 	case LPASS_DP_RX:
383 		return sc7180_hdmi_init(rtd);
384 	default:
385 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
386 			cpu_dai->id);
387 		return -EINVAL;
388 	}
389 	return 0;
390 }
391 
392 static int sc7180_adau7002_snd_startup(struct snd_pcm_substream *substream)
393 {
394 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
395 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
396 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
397 	struct snd_pcm_runtime *runtime = substream->runtime;
398 
399 	switch (cpu_dai->id) {
400 	case MI2S_PRIMARY:
401 		snd_soc_dai_set_fmt(codec_dai,
402 				    SND_SOC_DAIFMT_CBC_CFC |
403 				    SND_SOC_DAIFMT_NB_NF |
404 				    SND_SOC_DAIFMT_I2S);
405 		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
406 		snd_pcm_hw_constraint_msbits(runtime, 0, 32, 32);
407 
408 		break;
409 	case MI2S_SECONDARY:
410 		break;
411 	case LPASS_DP_RX:
412 		break;
413 	default:
414 		dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
415 			cpu_dai->id);
416 		return -EINVAL;
417 	}
418 	return 0;
419 }
420 
421 static int sc7180_qdsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
422 				     struct snd_pcm_hw_params *params)
423 {
424 	struct snd_interval *rate = hw_param_interval(params,
425 					SNDRV_PCM_HW_PARAM_RATE);
426 	struct snd_interval *channels = hw_param_interval(params,
427 					SNDRV_PCM_HW_PARAM_CHANNELS);
428 
429 	rate->min = rate->max = 48000;
430 	channels->min = channels->max = 2;
431 
432 	return 0;
433 }
434 
435 static const struct snd_soc_ops sc7180_ops = {
436 	.startup = sc7180_snd_startup,
437 	.shutdown = sc7180_snd_shutdown,
438 };
439 
440 static const struct snd_soc_ops sc7180_qdsp_ops = {
441 	.startup = sc7180_qdsp_snd_startup,
442 	.shutdown = sc7180_qdsp_snd_shutdown,
443 };
444 
445 static const struct snd_soc_ops sc7180_adau7002_ops = {
446 	.startup = sc7180_adau7002_snd_startup,
447 };
448 
449 static const struct snd_soc_dapm_widget sc7180_snd_widgets[] = {
450 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
451 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
452 };
453 
454 static const struct snd_kcontrol_new sc7180_snd_controls[] = {
455 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
456 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
457 };
458 
459 static const struct snd_soc_dapm_widget sc7180_adau7002_snd_widgets[] = {
460 	SND_SOC_DAPM_MIC("DMIC", NULL),
461 };
462 
463 static const char * const dmic_mux_text[] = {
464 	"Front Mic",
465 	"Rear Mic",
466 };
467 
468 static SOC_ENUM_SINGLE_DECL(sc7180_dmic_enum,
469 			    SND_SOC_NOPM, 0, dmic_mux_text);
470 
471 static const struct snd_kcontrol_new sc7180_dmic_mux_control =
472 	SOC_DAPM_ENUM_EXT("DMIC Select Mux", sc7180_dmic_enum,
473 			  dmic_get, dmic_set);
474 
475 static const struct snd_soc_dapm_widget sc7180_snd_dual_mic_widgets[] = {
476 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
477 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
478 	SND_SOC_DAPM_MIC("DMIC", NULL),
479 	SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, &sc7180_dmic_mux_control),
480 };
481 
482 static const struct snd_kcontrol_new sc7180_snd_dual_mic_controls[] = {
483 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
484 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
485 };
486 
487 static const struct snd_soc_dapm_route sc7180_snd_dual_mic_audio_route[] = {
488 	{"Dmic Mux", "Front Mic", "DMIC"},
489 	{"Dmic Mux", "Rear Mic", "DMIC"},
490 };
491 
492 static int sc7180_snd_platform_probe(struct platform_device *pdev)
493 {
494 	struct snd_soc_card *card;
495 	struct sc7180_snd_data *data;
496 	struct device *dev = &pdev->dev;
497 	struct snd_soc_dai_link *link;
498 	int ret;
499 	int i;
500 	bool qdsp = false, no_headphone = false;
501 
502 	/* Allocate the private data */
503 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
504 	if (!data)
505 		return -ENOMEM;
506 
507 	card = &data->card;
508 	snd_soc_card_set_drvdata(card, data);
509 
510 	card->owner = THIS_MODULE;
511 	card->driver_name = DRIVER_NAME;
512 	card->dev = dev;
513 	card->dapm_widgets = sc7180_snd_widgets;
514 	card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_widgets);
515 	card->controls = sc7180_snd_controls;
516 	card->num_controls = ARRAY_SIZE(sc7180_snd_controls);
517 
518 	if (of_property_present(dev->of_node, "dmic-gpios")) {
519 		card->dapm_widgets = sc7180_snd_dual_mic_widgets,
520 		card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_dual_mic_widgets),
521 		card->controls = sc7180_snd_dual_mic_controls,
522 		card->num_controls = ARRAY_SIZE(sc7180_snd_dual_mic_controls),
523 		card->dapm_routes = sc7180_snd_dual_mic_audio_route,
524 		card->num_dapm_routes = ARRAY_SIZE(sc7180_snd_dual_mic_audio_route),
525 		data->dmic_sel = devm_gpiod_get(&pdev->dev, "dmic", GPIOD_OUT_LOW);
526 		if (IS_ERR(data->dmic_sel)) {
527 			dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n", PTR_ERR(data->dmic_sel));
528 			return PTR_ERR(data->dmic_sel);
529 		}
530 	}
531 
532 	if (of_device_is_compatible(dev->of_node, "google,sc7180-coachz")) {
533 		no_headphone = true;
534 		card->dapm_widgets = sc7180_adau7002_snd_widgets;
535 		card->num_dapm_widgets = ARRAY_SIZE(sc7180_adau7002_snd_widgets);
536 	} else if (of_device_is_compatible(dev->of_node, "qcom,sc7180-qdsp6-sndcard")) {
537 		qdsp = true;
538 	}
539 
540 	ret = qcom_snd_parse_of(card);
541 	if (ret)
542 		return ret;
543 
544 	for_each_card_prelinks(card, i, link) {
545 		if (no_headphone) {
546 			link->ops = &sc7180_adau7002_ops;
547 			link->init = sc7180_adau7002_init;
548 		} else if (qdsp) {
549 			if (link->no_pcm == 1) {
550 				link->ops = &sc7180_qdsp_ops;
551 				link->be_hw_params_fixup = sc7180_qdsp_be_hw_params_fixup;
552 				link->init = sc7180_qdsp_init;
553 			}
554 		} else {
555 			link->ops = &sc7180_ops;
556 			link->init = sc7180_init;
557 		}
558 	}
559 
560 	return devm_snd_soc_register_card(dev, card);
561 }
562 
563 static const struct of_device_id sc7180_snd_device_id[]  = {
564 	{.compatible = "google,sc7180-trogdor"},
565 	{.compatible = "google,sc7180-coachz"},
566 	{.compatible = "qcom,sc7180-qdsp6-sndcard"},
567 	{},
568 };
569 MODULE_DEVICE_TABLE(of, sc7180_snd_device_id);
570 
571 static struct platform_driver sc7180_snd_driver = {
572 	.probe = sc7180_snd_platform_probe,
573 	.driver = {
574 		.name = "msm-snd-sc7180",
575 		.of_match_table = sc7180_snd_device_id,
576 		.pm = &snd_soc_pm_ops,
577 	},
578 };
579 module_platform_driver(sc7180_snd_driver);
580 
581 MODULE_DESCRIPTION("sc7180 ASoC Machine Driver");
582 MODULE_LICENSE("GPL");
583