xref: /openbmc/linux/sound/soc/soc-pcm.c (revision 81d67439)
1 /*
2  * soc-pcm.c  --  ALSA SoC PCM
3  *
4  * Copyright 2005 Wolfson Microelectronics PLC.
5  * Copyright 2005 Openedhand Ltd.
6  * Copyright (C) 2010 Slimlogic Ltd.
7  * Copyright (C) 2010 Texas Instruments Inc.
8  *
9  * Authors: Liam Girdwood <lrg@ti.com>
10  *          Mark Brown <broonie@opensource.wolfsonmicro.com>
11  *
12  *  This program is free software; you can redistribute  it and/or modify it
13  *  under  the terms of  the GNU General  Public License as published by the
14  *  Free Software Foundation;  either version 2 of the  License, or (at your
15  *  option) any later version.
16  *
17  */
18 
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/delay.h>
22 #include <linux/slab.h>
23 #include <linux/workqueue.h>
24 #include <sound/core.h>
25 #include <sound/pcm.h>
26 #include <sound/pcm_params.h>
27 #include <sound/soc.h>
28 #include <sound/initval.h>
29 
30 static DEFINE_MUTEX(pcm_mutex);
31 
32 static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
33 {
34 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
35 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
36 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
37 	int ret;
38 
39 	if (!codec_dai->driver->symmetric_rates &&
40 	    !cpu_dai->driver->symmetric_rates &&
41 	    !rtd->dai_link->symmetric_rates)
42 		return 0;
43 
44 	/* This can happen if multiple streams are starting simultaneously -
45 	 * the second can need to get its constraints before the first has
46 	 * picked a rate.  Complain and allow the application to carry on.
47 	 */
48 	if (!rtd->rate) {
49 		dev_warn(&rtd->dev,
50 			 "Not enforcing symmetric_rates due to race\n");
51 		return 0;
52 	}
53 
54 	dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
55 
56 	ret = snd_pcm_hw_constraint_minmax(substream->runtime,
57 					   SNDRV_PCM_HW_PARAM_RATE,
58 					   rtd->rate, rtd->rate);
59 	if (ret < 0) {
60 		dev_err(&rtd->dev,
61 			"Unable to apply rate symmetry constraint: %d\n", ret);
62 		return ret;
63 	}
64 
65 	return 0;
66 }
67 
68 /*
69  * Called by ALSA when a PCM substream is opened, the runtime->hw record is
70  * then initialized and any private data can be allocated. This also calls
71  * startup for the cpu DAI, platform, machine and codec DAI.
72  */
73 static int soc_pcm_open(struct snd_pcm_substream *substream)
74 {
75 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
76 	struct snd_pcm_runtime *runtime = substream->runtime;
77 	struct snd_soc_platform *platform = rtd->platform;
78 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
79 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
80 	struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
81 	struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
82 	int ret = 0;
83 
84 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
85 
86 	/* startup the audio subsystem */
87 	if (cpu_dai->driver->ops->startup) {
88 		ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
89 		if (ret < 0) {
90 			printk(KERN_ERR "asoc: can't open interface %s\n",
91 				cpu_dai->name);
92 			goto out;
93 		}
94 	}
95 
96 	if (platform->driver->ops && platform->driver->ops->open) {
97 		ret = platform->driver->ops->open(substream);
98 		if (ret < 0) {
99 			printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
100 			goto platform_err;
101 		}
102 	}
103 
104 	if (codec_dai->driver->ops->startup) {
105 		ret = codec_dai->driver->ops->startup(substream, codec_dai);
106 		if (ret < 0) {
107 			printk(KERN_ERR "asoc: can't open codec %s\n",
108 				codec_dai->name);
109 			goto codec_dai_err;
110 		}
111 	}
112 
113 	if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
114 		ret = rtd->dai_link->ops->startup(substream);
115 		if (ret < 0) {
116 			printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
117 			goto machine_err;
118 		}
119 	}
120 
121 	/* Check that the codec and cpu DAIs are compatible */
122 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
123 		runtime->hw.rate_min =
124 			max(codec_dai_drv->playback.rate_min,
125 			    cpu_dai_drv->playback.rate_min);
126 		runtime->hw.rate_max =
127 			min(codec_dai_drv->playback.rate_max,
128 			    cpu_dai_drv->playback.rate_max);
129 		runtime->hw.channels_min =
130 			max(codec_dai_drv->playback.channels_min,
131 				cpu_dai_drv->playback.channels_min);
132 		runtime->hw.channels_max =
133 			min(codec_dai_drv->playback.channels_max,
134 				cpu_dai_drv->playback.channels_max);
135 		runtime->hw.formats =
136 			codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
137 		runtime->hw.rates =
138 			codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
139 		if (codec_dai_drv->playback.rates
140 			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
141 			runtime->hw.rates |= cpu_dai_drv->playback.rates;
142 		if (cpu_dai_drv->playback.rates
143 			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
144 			runtime->hw.rates |= codec_dai_drv->playback.rates;
145 	} else {
146 		runtime->hw.rate_min =
147 			max(codec_dai_drv->capture.rate_min,
148 			    cpu_dai_drv->capture.rate_min);
149 		runtime->hw.rate_max =
150 			min(codec_dai_drv->capture.rate_max,
151 			    cpu_dai_drv->capture.rate_max);
152 		runtime->hw.channels_min =
153 			max(codec_dai_drv->capture.channels_min,
154 				cpu_dai_drv->capture.channels_min);
155 		runtime->hw.channels_max =
156 			min(codec_dai_drv->capture.channels_max,
157 				cpu_dai_drv->capture.channels_max);
158 		runtime->hw.formats =
159 			codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
160 		runtime->hw.rates =
161 			codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
162 		if (codec_dai_drv->capture.rates
163 			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
164 			runtime->hw.rates |= cpu_dai_drv->capture.rates;
165 		if (cpu_dai_drv->capture.rates
166 			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
167 			runtime->hw.rates |= codec_dai_drv->capture.rates;
168 	}
169 
170 	ret = -EINVAL;
171 	snd_pcm_limit_hw_rates(runtime);
172 	if (!runtime->hw.rates) {
173 		printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
174 			codec_dai->name, cpu_dai->name);
175 		goto config_err;
176 	}
177 	if (!runtime->hw.formats) {
178 		printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
179 			codec_dai->name, cpu_dai->name);
180 		goto config_err;
181 	}
182 	if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
183 	    runtime->hw.channels_min > runtime->hw.channels_max) {
184 		printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
185 				codec_dai->name, cpu_dai->name);
186 		goto config_err;
187 	}
188 
189 	/* Symmetry only applies if we've already got an active stream. */
190 	if (cpu_dai->active || codec_dai->active) {
191 		ret = soc_pcm_apply_symmetry(substream);
192 		if (ret != 0)
193 			goto config_err;
194 	}
195 
196 	pr_debug("asoc: %s <-> %s info:\n",
197 			codec_dai->name, cpu_dai->name);
198 	pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
199 	pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
200 		 runtime->hw.channels_max);
201 	pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
202 		 runtime->hw.rate_max);
203 
204 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
205 		cpu_dai->playback_active++;
206 		codec_dai->playback_active++;
207 	} else {
208 		cpu_dai->capture_active++;
209 		codec_dai->capture_active++;
210 	}
211 	cpu_dai->active++;
212 	codec_dai->active++;
213 	rtd->codec->active++;
214 	mutex_unlock(&rtd->pcm_mutex);
215 	return 0;
216 
217 config_err:
218 	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
219 		rtd->dai_link->ops->shutdown(substream);
220 
221 machine_err:
222 	if (codec_dai->driver->ops->shutdown)
223 		codec_dai->driver->ops->shutdown(substream, codec_dai);
224 
225 codec_dai_err:
226 	if (platform->driver->ops && platform->driver->ops->close)
227 		platform->driver->ops->close(substream);
228 
229 platform_err:
230 	if (cpu_dai->driver->ops->shutdown)
231 		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
232 out:
233 	mutex_unlock(&rtd->pcm_mutex);
234 	return ret;
235 }
236 
237 /*
238  * Power down the audio subsystem pmdown_time msecs after close is called.
239  * This is to ensure there are no pops or clicks in between any music tracks
240  * due to DAPM power cycling.
241  */
242 static void close_delayed_work(struct work_struct *work)
243 {
244 	struct snd_soc_pcm_runtime *rtd =
245 			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
246 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
247 
248 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
249 
250 	pr_debug("pop wq checking: %s status: %s waiting: %s\n",
251 		 codec_dai->driver->playback.stream_name,
252 		 codec_dai->playback_active ? "active" : "inactive",
253 		 codec_dai->pop_wait ? "yes" : "no");
254 
255 	/* are we waiting on this codec DAI stream */
256 	if (codec_dai->pop_wait == 1) {
257 		codec_dai->pop_wait = 0;
258 		snd_soc_dapm_stream_event(rtd,
259 			codec_dai->driver->playback.stream_name,
260 			SND_SOC_DAPM_STREAM_STOP);
261 	}
262 
263 	mutex_unlock(&rtd->pcm_mutex);
264 }
265 
266 /*
267  * Called by ALSA when a PCM substream is closed. Private data can be
268  * freed here. The cpu DAI, codec DAI, machine and platform are also
269  * shutdown.
270  */
271 static int soc_pcm_close(struct snd_pcm_substream *substream)
272 {
273 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
274 	struct snd_soc_platform *platform = rtd->platform;
275 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
276 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
277 	struct snd_soc_codec *codec = rtd->codec;
278 
279 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
280 
281 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
282 		cpu_dai->playback_active--;
283 		codec_dai->playback_active--;
284 	} else {
285 		cpu_dai->capture_active--;
286 		codec_dai->capture_active--;
287 	}
288 
289 	cpu_dai->active--;
290 	codec_dai->active--;
291 	codec->active--;
292 
293 	/* Muting the DAC suppresses artifacts caused during digital
294 	 * shutdown, for example from stopping clocks.
295 	 */
296 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
297 		snd_soc_dai_digital_mute(codec_dai, 1);
298 
299 	if (cpu_dai->driver->ops->shutdown)
300 		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
301 
302 	if (codec_dai->driver->ops->shutdown)
303 		codec_dai->driver->ops->shutdown(substream, codec_dai);
304 
305 	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
306 		rtd->dai_link->ops->shutdown(substream);
307 
308 	if (platform->driver->ops && platform->driver->ops->close)
309 		platform->driver->ops->close(substream);
310 	cpu_dai->runtime = NULL;
311 
312 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
313 		/* start delayed pop wq here for playback streams */
314 		codec_dai->pop_wait = 1;
315 		schedule_delayed_work(&rtd->delayed_work,
316 			msecs_to_jiffies(rtd->pmdown_time));
317 	} else {
318 		/* capture streams can be powered down now */
319 		snd_soc_dapm_stream_event(rtd,
320 			codec_dai->driver->capture.stream_name,
321 			SND_SOC_DAPM_STREAM_STOP);
322 	}
323 
324 	mutex_unlock(&rtd->pcm_mutex);
325 	return 0;
326 }
327 
328 /*
329  * Called by ALSA when the PCM substream is prepared, can set format, sample
330  * rate, etc.  This function is non atomic and can be called multiple times,
331  * it can refer to the runtime info.
332  */
333 static int soc_pcm_prepare(struct snd_pcm_substream *substream)
334 {
335 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
336 	struct snd_soc_platform *platform = rtd->platform;
337 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
338 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
339 	int ret = 0;
340 
341 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
342 
343 	if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
344 		ret = rtd->dai_link->ops->prepare(substream);
345 		if (ret < 0) {
346 			printk(KERN_ERR "asoc: machine prepare error\n");
347 			goto out;
348 		}
349 	}
350 
351 	if (platform->driver->ops && platform->driver->ops->prepare) {
352 		ret = platform->driver->ops->prepare(substream);
353 		if (ret < 0) {
354 			printk(KERN_ERR "asoc: platform prepare error\n");
355 			goto out;
356 		}
357 	}
358 
359 	if (codec_dai->driver->ops->prepare) {
360 		ret = codec_dai->driver->ops->prepare(substream, codec_dai);
361 		if (ret < 0) {
362 			printk(KERN_ERR "asoc: codec DAI prepare error\n");
363 			goto out;
364 		}
365 	}
366 
367 	if (cpu_dai->driver->ops->prepare) {
368 		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
369 		if (ret < 0) {
370 			printk(KERN_ERR "asoc: cpu DAI prepare error\n");
371 			goto out;
372 		}
373 	}
374 
375 	/* cancel any delayed stream shutdown that is pending */
376 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
377 	    codec_dai->pop_wait) {
378 		codec_dai->pop_wait = 0;
379 		cancel_delayed_work(&rtd->delayed_work);
380 	}
381 
382 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
383 		snd_soc_dapm_stream_event(rtd,
384 					  codec_dai->driver->playback.stream_name,
385 					  SND_SOC_DAPM_STREAM_START);
386 	else
387 		snd_soc_dapm_stream_event(rtd,
388 					  codec_dai->driver->capture.stream_name,
389 					  SND_SOC_DAPM_STREAM_START);
390 
391 	snd_soc_dai_digital_mute(codec_dai, 0);
392 
393 out:
394 	mutex_unlock(&rtd->pcm_mutex);
395 	return ret;
396 }
397 
398 /*
399  * Called by ALSA when the hardware params are set by application. This
400  * function can also be called multiple times and can allocate buffers
401  * (using snd_pcm_lib_* ). It's non-atomic.
402  */
403 static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
404 				struct snd_pcm_hw_params *params)
405 {
406 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
407 	struct snd_soc_platform *platform = rtd->platform;
408 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
409 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
410 	int ret = 0;
411 
412 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
413 
414 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
415 		ret = rtd->dai_link->ops->hw_params(substream, params);
416 		if (ret < 0) {
417 			printk(KERN_ERR "asoc: machine hw_params failed\n");
418 			goto out;
419 		}
420 	}
421 
422 	if (codec_dai->driver->ops->hw_params) {
423 		ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
424 		if (ret < 0) {
425 			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
426 				codec_dai->name);
427 			goto codec_err;
428 		}
429 	}
430 
431 	if (cpu_dai->driver->ops->hw_params) {
432 		ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
433 		if (ret < 0) {
434 			printk(KERN_ERR "asoc: interface %s hw params failed\n",
435 				cpu_dai->name);
436 			goto interface_err;
437 		}
438 	}
439 
440 	if (platform->driver->ops && platform->driver->ops->hw_params) {
441 		ret = platform->driver->ops->hw_params(substream, params);
442 		if (ret < 0) {
443 			printk(KERN_ERR "asoc: platform %s hw params failed\n",
444 				platform->name);
445 			goto platform_err;
446 		}
447 	}
448 
449 	rtd->rate = params_rate(params);
450 
451 out:
452 	mutex_unlock(&rtd->pcm_mutex);
453 	return ret;
454 
455 platform_err:
456 	if (cpu_dai->driver->ops->hw_free)
457 		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
458 
459 interface_err:
460 	if (codec_dai->driver->ops->hw_free)
461 		codec_dai->driver->ops->hw_free(substream, codec_dai);
462 
463 codec_err:
464 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
465 		rtd->dai_link->ops->hw_free(substream);
466 
467 	mutex_unlock(&rtd->pcm_mutex);
468 	return ret;
469 }
470 
471 /*
472  * Frees resources allocated by hw_params, can be called multiple times
473  */
474 static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
475 {
476 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
477 	struct snd_soc_platform *platform = rtd->platform;
478 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
479 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
480 	struct snd_soc_codec *codec = rtd->codec;
481 
482 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
483 
484 	/* apply codec digital mute */
485 	if (!codec->active)
486 		snd_soc_dai_digital_mute(codec_dai, 1);
487 
488 	/* free any machine hw params */
489 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
490 		rtd->dai_link->ops->hw_free(substream);
491 
492 	/* free any DMA resources */
493 	if (platform->driver->ops && platform->driver->ops->hw_free)
494 		platform->driver->ops->hw_free(substream);
495 
496 	/* now free hw params for the DAIs  */
497 	if (codec_dai->driver->ops->hw_free)
498 		codec_dai->driver->ops->hw_free(substream, codec_dai);
499 
500 	if (cpu_dai->driver->ops->hw_free)
501 		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
502 
503 	mutex_unlock(&rtd->pcm_mutex);
504 	return 0;
505 }
506 
507 static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
508 {
509 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
510 	struct snd_soc_platform *platform = rtd->platform;
511 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
512 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
513 	int ret;
514 
515 	if (codec_dai->driver->ops->trigger) {
516 		ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
517 		if (ret < 0)
518 			return ret;
519 	}
520 
521 	if (platform->driver->ops && platform->driver->ops->trigger) {
522 		ret = platform->driver->ops->trigger(substream, cmd);
523 		if (ret < 0)
524 			return ret;
525 	}
526 
527 	if (cpu_dai->driver->ops->trigger) {
528 		ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
529 		if (ret < 0)
530 			return ret;
531 	}
532 	return 0;
533 }
534 
535 /*
536  * soc level wrapper for pointer callback
537  * If cpu_dai, codec_dai, platform driver has the delay callback, than
538  * the runtime->delay will be updated accordingly.
539  */
540 static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
541 {
542 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
543 	struct snd_soc_platform *platform = rtd->platform;
544 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
545 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
546 	struct snd_pcm_runtime *runtime = substream->runtime;
547 	snd_pcm_uframes_t offset = 0;
548 	snd_pcm_sframes_t delay = 0;
549 
550 	if (platform->driver->ops && platform->driver->ops->pointer)
551 		offset = platform->driver->ops->pointer(substream);
552 
553 	if (cpu_dai->driver->ops->delay)
554 		delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
555 
556 	if (codec_dai->driver->ops->delay)
557 		delay += codec_dai->driver->ops->delay(substream, codec_dai);
558 
559 	if (platform->driver->delay)
560 		delay += platform->driver->delay(substream, codec_dai);
561 
562 	runtime->delay = delay;
563 
564 	return offset;
565 }
566 
567 /* ASoC PCM operations */
568 static struct snd_pcm_ops soc_pcm_ops = {
569 	.open		= soc_pcm_open,
570 	.close		= soc_pcm_close,
571 	.hw_params	= soc_pcm_hw_params,
572 	.hw_free	= soc_pcm_hw_free,
573 	.prepare	= soc_pcm_prepare,
574 	.trigger	= soc_pcm_trigger,
575 	.pointer	= soc_pcm_pointer,
576 };
577 
578 /* create a new pcm */
579 int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
580 {
581 	struct snd_soc_codec *codec = rtd->codec;
582 	struct snd_soc_platform *platform = rtd->platform;
583 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
584 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
585 	struct snd_pcm *pcm;
586 	char new_name[64];
587 	int ret = 0, playback = 0, capture = 0;
588 
589 	/* check client and interface hw capabilities */
590 	snprintf(new_name, sizeof(new_name), "%s %s-%d",
591 			rtd->dai_link->stream_name, codec_dai->name, num);
592 
593 	if (codec_dai->driver->playback.channels_min)
594 		playback = 1;
595 	if (codec_dai->driver->capture.channels_min)
596 		capture = 1;
597 
598 	dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
599 	ret = snd_pcm_new(rtd->card->snd_card, new_name,
600 			num, playback, capture, &pcm);
601 	if (ret < 0) {
602 		printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
603 		return ret;
604 	}
605 
606 	/* DAPM dai link stream work */
607 	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
608 
609 	rtd->pcm = pcm;
610 	pcm->private_data = rtd;
611 	if (platform->driver->ops) {
612 		soc_pcm_ops.mmap = platform->driver->ops->mmap;
613 		soc_pcm_ops.pointer = platform->driver->ops->pointer;
614 		soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
615 		soc_pcm_ops.copy = platform->driver->ops->copy;
616 		soc_pcm_ops.silence = platform->driver->ops->silence;
617 		soc_pcm_ops.ack = platform->driver->ops->ack;
618 		soc_pcm_ops.page = platform->driver->ops->page;
619 	}
620 
621 	if (playback)
622 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
623 
624 	if (capture)
625 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
626 
627 	if (platform->driver->pcm_new) {
628 		ret = platform->driver->pcm_new(rtd);
629 		if (ret < 0) {
630 			pr_err("asoc: platform pcm constructor failed\n");
631 			return ret;
632 		}
633 	}
634 
635 	pcm->private_free = platform->driver->pcm_free;
636 	printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
637 		cpu_dai->name);
638 	return ret;
639 }
640