xref: /linux/sound/soc/samsung/tm2_wm5110.c (revision 3ad0876554cafa368f574d4d408468510543e9ff)
1 /*
2  * Copyright (C) 2015 - 2016 Samsung Electronics Co., Ltd.
3  *
4  * Authors: Inha Song <ideal.song@samsung.com>
5  *          Sylwester Nawrocki <s.nawrocki@samsung.com>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  */
12 
13 #include <linux/clk.h>
14 #include <linux/gpio.h>
15 #include <linux/gpio/consumer.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 
21 #include "i2s.h"
22 #include "../codecs/wm5110.h"
23 
24 /*
25  * The source clock is XCLKOUT with its mux set to the external fixed rate
26  * oscillator (XXTI).
27  */
28 #define MCLK_RATE	24000000U
29 
30 #define TM2_DAI_AIF1	0
31 #define TM2_DAI_AIF2	1
32 
33 struct tm2_machine_priv {
34 	struct snd_soc_component *component;
35 	unsigned int sysclk_rate;
36 	struct gpio_desc *gpio_mic_bias;
37 };
38 
39 static int tm2_start_sysclk(struct snd_soc_card *card)
40 {
41 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
42 	struct snd_soc_component *component = priv->component;
43 	int ret;
44 
45 	ret = snd_soc_component_set_pll(component, WM5110_FLL1_REFCLK,
46 				    ARIZONA_FLL_SRC_MCLK1,
47 				    MCLK_RATE,
48 				    priv->sysclk_rate);
49 	if (ret < 0) {
50 		dev_err(component->dev, "Failed to set FLL1 source: %d\n", ret);
51 		return ret;
52 	}
53 
54 	ret = snd_soc_component_set_pll(component, WM5110_FLL1,
55 				    ARIZONA_FLL_SRC_MCLK1,
56 				    MCLK_RATE,
57 				    priv->sysclk_rate);
58 	if (ret < 0) {
59 		dev_err(component->dev, "Failed to start FLL1: %d\n", ret);
60 		return ret;
61 	}
62 
63 	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
64 				       ARIZONA_CLK_SRC_FLL1,
65 				       priv->sysclk_rate,
66 				       SND_SOC_CLOCK_IN);
67 	if (ret < 0) {
68 		dev_err(component->dev, "Failed to set SYSCLK source: %d\n", ret);
69 		return ret;
70 	}
71 
72 	return 0;
73 }
74 
75 static int tm2_stop_sysclk(struct snd_soc_card *card)
76 {
77 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
78 	struct snd_soc_component *component = priv->component;
79 	int ret;
80 
81 	ret = snd_soc_component_set_pll(component, WM5110_FLL1, 0, 0, 0);
82 	if (ret < 0) {
83 		dev_err(component->dev, "Failed to stop FLL1: %d\n", ret);
84 		return ret;
85 	}
86 
87 	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
88 				       ARIZONA_CLK_SRC_FLL1, 0, 0);
89 	if (ret < 0) {
90 		dev_err(component->dev, "Failed to stop SYSCLK: %d\n", ret);
91 		return ret;
92 	}
93 
94 	return 0;
95 }
96 
97 static int tm2_aif1_hw_params(struct snd_pcm_substream *substream,
98 				struct snd_pcm_hw_params *params)
99 {
100 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
101 	struct snd_soc_component *component = rtd->codec_dai->component;
102 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(rtd->card);
103 
104 	switch (params_rate(params)) {
105 	case 4000:
106 	case 8000:
107 	case 12000:
108 	case 16000:
109 	case 24000:
110 	case 32000:
111 	case 48000:
112 	case 96000:
113 	case 192000:
114 		/* Highest possible SYSCLK frequency: 147.456MHz */
115 		priv->sysclk_rate = 147456000U;
116 		break;
117 	case 11025:
118 	case 22050:
119 	case 44100:
120 	case 88200:
121 	case 176400:
122 		/* Highest possible SYSCLK frequency: 135.4752 MHz */
123 		priv->sysclk_rate = 135475200U;
124 		break;
125 	default:
126 		dev_err(component->dev, "Not supported sample rate: %d\n",
127 			params_rate(params));
128 		return -EINVAL;
129 	}
130 
131 	return tm2_start_sysclk(rtd->card);
132 }
133 
134 static struct snd_soc_ops tm2_aif1_ops = {
135 	.hw_params = tm2_aif1_hw_params,
136 };
137 
138 static int tm2_aif2_hw_params(struct snd_pcm_substream *substream,
139 				struct snd_pcm_hw_params *params)
140 {
141 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
142 	struct snd_soc_component *component = rtd->codec_dai->component;
143 	unsigned int asyncclk_rate;
144 	int ret;
145 
146 	switch (params_rate(params)) {
147 	case 8000:
148 	case 12000:
149 	case 16000:
150 		/* Highest possible ASYNCCLK frequency: 49.152MHz */
151 		asyncclk_rate = 49152000U;
152 		break;
153 	case 11025:
154 		/* Highest possible ASYNCCLK frequency: 45.1584 MHz */
155 		asyncclk_rate = 45158400U;
156 		break;
157 	default:
158 		dev_err(component->dev, "Not supported sample rate: %d\n",
159 			params_rate(params));
160 		return -EINVAL;
161 	}
162 
163 	ret = snd_soc_component_set_pll(component, WM5110_FLL2_REFCLK,
164 				    ARIZONA_FLL_SRC_MCLK1,
165 				    MCLK_RATE,
166 				    asyncclk_rate);
167 	if (ret < 0) {
168 		dev_err(component->dev, "Failed to set FLL2 source: %d\n", ret);
169 		return ret;
170 	}
171 
172 	ret = snd_soc_component_set_pll(component, WM5110_FLL2,
173 				    ARIZONA_FLL_SRC_MCLK1,
174 				    MCLK_RATE,
175 				    asyncclk_rate);
176 	if (ret < 0) {
177 		dev_err(component->dev, "Failed to start FLL2: %d\n", ret);
178 		return ret;
179 	}
180 
181 	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_ASYNCCLK,
182 				       ARIZONA_CLK_SRC_FLL2,
183 				       asyncclk_rate,
184 				       SND_SOC_CLOCK_IN);
185 	if (ret < 0) {
186 		dev_err(component->dev, "Failed to set ASYNCCLK source: %d\n", ret);
187 		return ret;
188 	}
189 
190 	return 0;
191 }
192 
193 static int tm2_aif2_hw_free(struct snd_pcm_substream *substream)
194 {
195 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
196 	struct snd_soc_component *component = rtd->codec_dai->component;
197 	int ret;
198 
199 	/* disable FLL2 */
200 	ret = snd_soc_component_set_pll(component, WM5110_FLL2, ARIZONA_FLL_SRC_MCLK1,
201 				    0, 0);
202 	if (ret < 0)
203 		dev_err(component->dev, "Failed to stop FLL2: %d\n", ret);
204 
205 	return ret;
206 }
207 
208 static struct snd_soc_ops tm2_aif2_ops = {
209 	.hw_params = tm2_aif2_hw_params,
210 	.hw_free = tm2_aif2_hw_free,
211 };
212 
213 static int tm2_hdmi_hw_params(struct snd_pcm_substream *substream,
214 			      struct snd_pcm_hw_params *params)
215 {
216 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
217 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
218 	unsigned int bfs;
219 	int bitwidth, ret;
220 
221 	bitwidth = snd_pcm_format_width(params_format(params));
222 	if (bitwidth < 0) {
223 		dev_err(rtd->card->dev, "Invalid bit-width: %d\n", bitwidth);
224 		return bitwidth;
225 	}
226 
227 	switch (bitwidth) {
228 	case 48:
229 		bfs = 64;
230 		break;
231 	case 16:
232 		bfs = 32;
233 		break;
234 	default:
235 		dev_err(rtd->card->dev, "Unsupported bit-width: %d\n", bitwidth);
236 		return -EINVAL;
237 	}
238 
239 	switch (params_rate(params)) {
240 	case 48000:
241 	case 96000:
242 	case 192000:
243 		break;
244 	default:
245 		dev_err(rtd->card->dev, "Unsupported sample rate: %d\n",
246 			params_rate(params));
247 		return -EINVAL;
248 	}
249 
250 	ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK,
251 					0, SAMSUNG_I2S_OPCLK_PCLK);
252 	if (ret < 0)
253 		return ret;
254 
255 	ret = snd_soc_dai_set_clkdiv(cpu_dai, SAMSUNG_I2S_DIV_BCLK, bfs);
256 	if (ret < 0)
257 		return ret;
258 
259 	return 0;
260 }
261 
262 static struct snd_soc_ops tm2_hdmi_ops = {
263 	.hw_params = tm2_hdmi_hw_params,
264 };
265 
266 static int tm2_mic_bias(struct snd_soc_dapm_widget *w,
267 				struct snd_kcontrol *kcontrol, int event)
268 {
269 	struct snd_soc_card *card = w->dapm->card;
270 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
271 
272 	switch (event) {
273 	case SND_SOC_DAPM_PRE_PMU:
274 		gpiod_set_value_cansleep(priv->gpio_mic_bias,  1);
275 		break;
276 	case SND_SOC_DAPM_POST_PMD:
277 		gpiod_set_value_cansleep(priv->gpio_mic_bias,  0);
278 		break;
279 	}
280 
281 	return 0;
282 }
283 
284 static int tm2_set_bias_level(struct snd_soc_card *card,
285 				struct snd_soc_dapm_context *dapm,
286 				enum snd_soc_bias_level level)
287 {
288 	struct snd_soc_pcm_runtime *rtd;
289 
290 	rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
291 
292 	if (dapm->dev != rtd->codec_dai->dev)
293 		return 0;
294 
295 	switch (level) {
296 	case SND_SOC_BIAS_STANDBY:
297 		if (card->dapm.bias_level == SND_SOC_BIAS_OFF)
298 			tm2_start_sysclk(card);
299 		break;
300 	case SND_SOC_BIAS_OFF:
301 		tm2_stop_sysclk(card);
302 		break;
303 	default:
304 		break;
305 	}
306 
307 	return 0;
308 }
309 
310 static struct snd_soc_aux_dev tm2_speaker_amp_dev;
311 
312 static int tm2_late_probe(struct snd_soc_card *card)
313 {
314 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
315 	struct snd_soc_dai_link_component dlc = { 0 };
316 	unsigned int ch_map[] = { 0, 1 };
317 	struct snd_soc_dai *amp_pdm_dai;
318 	struct snd_soc_pcm_runtime *rtd;
319 	struct snd_soc_dai *aif1_dai;
320 	struct snd_soc_dai *aif2_dai;
321 	int ret;
322 
323 	rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF1].name);
324 	aif1_dai = rtd->codec_dai;
325 	priv->component = rtd->codec_dai->component;
326 
327 	ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
328 	if (ret < 0) {
329 		dev_err(aif1_dai->dev, "Failed to set SYSCLK: %d\n", ret);
330 		return ret;
331 	}
332 
333 	rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF2].name);
334 	aif2_dai = rtd->codec_dai;
335 
336 	ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
337 	if (ret < 0) {
338 		dev_err(aif2_dai->dev, "Failed to set ASYNCCLK: %d\n", ret);
339 		return ret;
340 	}
341 
342 	dlc.of_node = tm2_speaker_amp_dev.codec_of_node;
343 	amp_pdm_dai = snd_soc_find_dai(&dlc);
344 	if (!amp_pdm_dai)
345 		return -ENODEV;
346 
347 	/* Set the MAX98504 V/I sense PDM Tx DAI channel mapping */
348 	ret = snd_soc_dai_set_channel_map(amp_pdm_dai, ARRAY_SIZE(ch_map),
349 					  ch_map, 0, NULL);
350 	if (ret < 0)
351 		return ret;
352 
353 	ret = snd_soc_dai_set_tdm_slot(amp_pdm_dai, 0x3, 0x0, 2, 16);
354 	if (ret < 0)
355 		return ret;
356 
357 	return 0;
358 }
359 
360 static const struct snd_kcontrol_new tm2_controls[] = {
361 	SOC_DAPM_PIN_SWITCH("HP"),
362 	SOC_DAPM_PIN_SWITCH("SPK"),
363 	SOC_DAPM_PIN_SWITCH("RCV"),
364 	SOC_DAPM_PIN_SWITCH("VPS"),
365 	SOC_DAPM_PIN_SWITCH("HDMI"),
366 
367 	SOC_DAPM_PIN_SWITCH("Main Mic"),
368 	SOC_DAPM_PIN_SWITCH("Sub Mic"),
369 	SOC_DAPM_PIN_SWITCH("Third Mic"),
370 
371 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
372 };
373 
374 static const struct snd_soc_dapm_widget tm2_dapm_widgets[] = {
375 	SND_SOC_DAPM_HP("HP", NULL),
376 	SND_SOC_DAPM_SPK("SPK", NULL),
377 	SND_SOC_DAPM_SPK("RCV", NULL),
378 	SND_SOC_DAPM_LINE("VPS", NULL),
379 	SND_SOC_DAPM_LINE("HDMI", NULL),
380 
381 	SND_SOC_DAPM_MIC("Main Mic", tm2_mic_bias),
382 	SND_SOC_DAPM_MIC("Sub Mic", NULL),
383 	SND_SOC_DAPM_MIC("Third Mic", NULL),
384 
385 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
386 };
387 
388 static const struct snd_soc_component_driver tm2_component = {
389 	.name	= "tm2-audio",
390 };
391 
392 static struct snd_soc_dai_driver tm2_ext_dai[] = {
393 	{
394 		.name = "Voice call",
395 		.playback = {
396 			.channels_min = 1,
397 			.channels_max = 4,
398 			.rate_min = 8000,
399 			.rate_max = 48000,
400 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
401 					SNDRV_PCM_RATE_48000),
402 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
403 		},
404 		.capture = {
405 			.channels_min = 1,
406 			.channels_max = 4,
407 			.rate_min = 8000,
408 			.rate_max = 48000,
409 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
410 					SNDRV_PCM_RATE_48000),
411 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
412 		},
413 	},
414 	{
415 		.name = "Bluetooth",
416 		.playback = {
417 			.channels_min = 1,
418 			.channels_max = 4,
419 			.rate_min = 8000,
420 			.rate_max = 16000,
421 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
422 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
423 		},
424 		.capture = {
425 			.channels_min = 1,
426 			.channels_max = 2,
427 			.rate_min = 8000,
428 			.rate_max = 16000,
429 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
430 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
431 		},
432 	},
433 };
434 
435 static struct snd_soc_dai_link tm2_dai_links[] = {
436 	{
437 		.name		= "WM5110 AIF1",
438 		.stream_name	= "HiFi Primary",
439 		.cpu_dai_name   = SAMSUNG_I2S_DAI,
440 		.codec_dai_name = "wm5110-aif1",
441 		.ops		= &tm2_aif1_ops,
442 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
443 				  SND_SOC_DAIFMT_CBM_CFM,
444 	}, {
445 		.name		= "WM5110 Voice",
446 		.stream_name	= "Voice call",
447 		.cpu_dai_name   = SAMSUNG_I2S_DAI,
448 		.codec_dai_name = "wm5110-aif2",
449 		.ops		= &tm2_aif2_ops,
450 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
451 				  SND_SOC_DAIFMT_CBM_CFM,
452 		.ignore_suspend = 1,
453 	}, {
454 		.name		= "WM5110 BT",
455 		.stream_name	= "Bluetooth",
456 		.cpu_dai_name   = SAMSUNG_I2S_DAI,
457 		.codec_dai_name = "wm5110-aif3",
458 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
459 				  SND_SOC_DAIFMT_CBM_CFM,
460 		.ignore_suspend = 1,
461 	}, {
462 		.name		= "HDMI",
463 		.stream_name	= "i2s1",
464 		.ops		= &tm2_hdmi_ops,
465 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
466 				  SND_SOC_DAIFMT_CBS_CFS,
467 	}
468 };
469 
470 static struct snd_soc_card tm2_card = {
471 	.owner			= THIS_MODULE,
472 
473 	.dai_link		= tm2_dai_links,
474 	.controls		= tm2_controls,
475 	.num_controls		= ARRAY_SIZE(tm2_controls),
476 	.dapm_widgets		= tm2_dapm_widgets,
477 	.num_dapm_widgets	= ARRAY_SIZE(tm2_dapm_widgets),
478 	.aux_dev		= &tm2_speaker_amp_dev,
479 	.num_aux_devs		= 1,
480 
481 	.late_probe		= tm2_late_probe,
482 	.set_bias_level		= tm2_set_bias_level,
483 };
484 
485 static int tm2_probe(struct platform_device *pdev)
486 {
487 	struct device_node *cpu_dai_node[2] = {};
488 	struct device_node *codec_dai_node[2] = {};
489 	const char *cells_name = NULL;
490 	struct device *dev = &pdev->dev;
491 	struct snd_soc_card *card = &tm2_card;
492 	struct tm2_machine_priv *priv;
493 	struct of_phandle_args args;
494 	int num_codecs, ret, i;
495 
496 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
497 	if (!priv)
498 		return -ENOMEM;
499 
500 	snd_soc_card_set_drvdata(card, priv);
501 	card->dev = dev;
502 
503 	priv->gpio_mic_bias = devm_gpiod_get(dev, "mic-bias", GPIOD_OUT_HIGH);
504 	if (IS_ERR(priv->gpio_mic_bias)) {
505 		dev_err(dev, "Failed to get mic bias gpio\n");
506 		return PTR_ERR(priv->gpio_mic_bias);
507 	}
508 
509 	ret = snd_soc_of_parse_card_name(card, "model");
510 	if (ret < 0) {
511 		dev_err(dev, "Card name is not specified\n");
512 		return ret;
513 	}
514 
515 	ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
516 	if (ret < 0) {
517 		dev_err(dev, "Audio routing is not specified or invalid\n");
518 		return ret;
519 	}
520 
521 	card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node,
522 							"audio-amplifier", 0);
523 	if (!card->aux_dev[0].codec_of_node) {
524 		dev_err(dev, "audio-amplifier property invalid or missing\n");
525 		return -EINVAL;
526 	}
527 
528 	num_codecs = of_count_phandle_with_args(dev->of_node, "audio-codec",
529 						 NULL);
530 
531 	/* Skip the HDMI link if not specified in DT */
532 	if (num_codecs > 1) {
533 		card->num_links = ARRAY_SIZE(tm2_dai_links);
534 		cells_name = "#sound-dai-cells";
535 	} else {
536 		card->num_links = ARRAY_SIZE(tm2_dai_links) - 1;
537 	}
538 
539 	for (i = 0; i < num_codecs; i++) {
540 		struct of_phandle_args args;
541 
542 		ret = of_parse_phandle_with_args(dev->of_node, "i2s-controller",
543 						 cells_name, i, &args);
544 		if (!args.np) {
545 			dev_err(dev, "i2s-controller property parse error: %d\n", i);
546 			ret = -EINVAL;
547 			goto dai_node_put;
548 		}
549 		cpu_dai_node[i] = args.np;
550 
551 		codec_dai_node[i] = of_parse_phandle(dev->of_node,
552 						     "audio-codec", i);
553 		if (!codec_dai_node[i]) {
554 			dev_err(dev, "audio-codec property parse error\n");
555 			ret = -EINVAL;
556 			goto dai_node_put;
557 		}
558 	}
559 
560 	/* Initialize WM5110 - I2S and HDMI - I2S1 DAI links */
561 	for (i = 0; i < card->num_links; i++) {
562 		unsigned int dai_index = 0; /* WM5110 */
563 
564 		card->dai_link[i].cpu_name = NULL;
565 		card->dai_link[i].platform_name = NULL;
566 
567 		if (num_codecs > 1 && i == card->num_links - 1)
568 			dai_index = 1; /* HDMI */
569 
570 		card->dai_link[i].codec_of_node = codec_dai_node[dai_index];
571 		card->dai_link[i].cpu_of_node = cpu_dai_node[dai_index];
572 		card->dai_link[i].platform_of_node = cpu_dai_node[dai_index];
573 	}
574 
575 	if (num_codecs > 1) {
576 		/* HDMI DAI link (I2S1) */
577 		i = card->num_links - 1;
578 
579 		ret = of_parse_phandle_with_fixed_args(dev->of_node,
580 						"audio-codec", 0, 1, &args);
581 		if (ret) {
582 			dev_err(dev, "audio-codec property parse error\n");
583 			goto dai_node_put;
584 		}
585 
586 		ret = snd_soc_get_dai_name(&args, &card->dai_link[i].codec_dai_name);
587 		if (ret) {
588 			dev_err(dev, "Unable to get codec_dai_name\n");
589 			goto dai_node_put;
590 		}
591 	}
592 
593 	ret = devm_snd_soc_register_component(dev, &tm2_component,
594 				tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai));
595 	if (ret < 0) {
596 		dev_err(dev, "Failed to register component: %d\n", ret);
597 		goto dai_node_put;
598 	}
599 
600 	ret = devm_snd_soc_register_card(dev, card);
601 	if (ret < 0) {
602 		dev_err(dev, "Failed to register card: %d\n", ret);
603 		goto dai_node_put;
604 	}
605 
606 dai_node_put:
607 	for (i = 0; i < num_codecs; i++) {
608 		of_node_put(codec_dai_node[i]);
609 		of_node_put(cpu_dai_node[i]);
610 	}
611 
612 	of_node_put(card->aux_dev[0].codec_of_node);
613 
614 	return ret;
615 }
616 
617 static int tm2_pm_prepare(struct device *dev)
618 {
619 	struct snd_soc_card *card = dev_get_drvdata(dev);
620 
621 	return tm2_stop_sysclk(card);
622 }
623 
624 static void tm2_pm_complete(struct device *dev)
625 {
626 	struct snd_soc_card *card = dev_get_drvdata(dev);
627 
628 	tm2_start_sysclk(card);
629 }
630 
631 static const struct dev_pm_ops tm2_pm_ops = {
632 	.prepare	= tm2_pm_prepare,
633 	.suspend	= snd_soc_suspend,
634 	.resume		= snd_soc_resume,
635 	.complete	= tm2_pm_complete,
636 	.freeze		= snd_soc_suspend,
637 	.thaw		= snd_soc_resume,
638 	.poweroff	= snd_soc_poweroff,
639 	.restore	= snd_soc_resume,
640 };
641 
642 static const struct of_device_id tm2_of_match[] = {
643 	{ .compatible = "samsung,tm2-audio" },
644 	{ },
645 };
646 MODULE_DEVICE_TABLE(of, tm2_of_match);
647 
648 static struct platform_driver tm2_driver = {
649 	.driver = {
650 		.name		= "tm2-audio",
651 		.pm		= &tm2_pm_ops,
652 		.of_match_table	= tm2_of_match,
653 	},
654 	.probe	= tm2_probe,
655 };
656 module_platform_driver(tm2_driver);
657 
658 MODULE_AUTHOR("Inha Song <ideal.song@samsung.com>");
659 MODULE_DESCRIPTION("ALSA SoC Exynos TM2 Audio Support");
660 MODULE_LICENSE("GPL v2");
661