xref: /linux/sound/soc/soc-pcm.c (revision 60e13231561b3a4c5269bfa1ef6c0569ad6f28ec)
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 	if (!cpu_dai->active && !codec_dai->active)
294 		rtd->rate = 0;
295 
296 	/* Muting the DAC suppresses artifacts caused during digital
297 	 * shutdown, for example from stopping clocks.
298 	 */
299 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
300 		snd_soc_dai_digital_mute(codec_dai, 1);
301 
302 	if (cpu_dai->driver->ops->shutdown)
303 		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
304 
305 	if (codec_dai->driver->ops->shutdown)
306 		codec_dai->driver->ops->shutdown(substream, codec_dai);
307 
308 	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
309 		rtd->dai_link->ops->shutdown(substream);
310 
311 	if (platform->driver->ops && platform->driver->ops->close)
312 		platform->driver->ops->close(substream);
313 	cpu_dai->runtime = NULL;
314 
315 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
316 		/* start delayed pop wq here for playback streams */
317 		codec_dai->pop_wait = 1;
318 		schedule_delayed_work(&rtd->delayed_work,
319 			msecs_to_jiffies(rtd->pmdown_time));
320 	} else {
321 		/* capture streams can be powered down now */
322 		snd_soc_dapm_stream_event(rtd,
323 			codec_dai->driver->capture.stream_name,
324 			SND_SOC_DAPM_STREAM_STOP);
325 	}
326 
327 	mutex_unlock(&rtd->pcm_mutex);
328 	return 0;
329 }
330 
331 /*
332  * Called by ALSA when the PCM substream is prepared, can set format, sample
333  * rate, etc.  This function is non atomic and can be called multiple times,
334  * it can refer to the runtime info.
335  */
336 static int soc_pcm_prepare(struct snd_pcm_substream *substream)
337 {
338 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
339 	struct snd_soc_platform *platform = rtd->platform;
340 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
341 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
342 	int ret = 0;
343 
344 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
345 
346 	if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
347 		ret = rtd->dai_link->ops->prepare(substream);
348 		if (ret < 0) {
349 			printk(KERN_ERR "asoc: machine prepare error\n");
350 			goto out;
351 		}
352 	}
353 
354 	if (platform->driver->ops && platform->driver->ops->prepare) {
355 		ret = platform->driver->ops->prepare(substream);
356 		if (ret < 0) {
357 			printk(KERN_ERR "asoc: platform prepare error\n");
358 			goto out;
359 		}
360 	}
361 
362 	if (codec_dai->driver->ops->prepare) {
363 		ret = codec_dai->driver->ops->prepare(substream, codec_dai);
364 		if (ret < 0) {
365 			printk(KERN_ERR "asoc: codec DAI prepare error\n");
366 			goto out;
367 		}
368 	}
369 
370 	if (cpu_dai->driver->ops->prepare) {
371 		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
372 		if (ret < 0) {
373 			printk(KERN_ERR "asoc: cpu DAI prepare error\n");
374 			goto out;
375 		}
376 	}
377 
378 	/* cancel any delayed stream shutdown that is pending */
379 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
380 	    codec_dai->pop_wait) {
381 		codec_dai->pop_wait = 0;
382 		cancel_delayed_work(&rtd->delayed_work);
383 	}
384 
385 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
386 		snd_soc_dapm_stream_event(rtd,
387 					  codec_dai->driver->playback.stream_name,
388 					  SND_SOC_DAPM_STREAM_START);
389 	else
390 		snd_soc_dapm_stream_event(rtd,
391 					  codec_dai->driver->capture.stream_name,
392 					  SND_SOC_DAPM_STREAM_START);
393 
394 	snd_soc_dai_digital_mute(codec_dai, 0);
395 
396 out:
397 	mutex_unlock(&rtd->pcm_mutex);
398 	return ret;
399 }
400 
401 /*
402  * Called by ALSA when the hardware params are set by application. This
403  * function can also be called multiple times and can allocate buffers
404  * (using snd_pcm_lib_* ). It's non-atomic.
405  */
406 static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
407 				struct snd_pcm_hw_params *params)
408 {
409 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
410 	struct snd_soc_platform *platform = rtd->platform;
411 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
412 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
413 	int ret = 0;
414 
415 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
416 
417 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
418 		ret = rtd->dai_link->ops->hw_params(substream, params);
419 		if (ret < 0) {
420 			printk(KERN_ERR "asoc: machine hw_params failed\n");
421 			goto out;
422 		}
423 	}
424 
425 	if (codec_dai->driver->ops->hw_params) {
426 		ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
427 		if (ret < 0) {
428 			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
429 				codec_dai->name);
430 			goto codec_err;
431 		}
432 	}
433 
434 	if (cpu_dai->driver->ops->hw_params) {
435 		ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
436 		if (ret < 0) {
437 			printk(KERN_ERR "asoc: interface %s hw params failed\n",
438 				cpu_dai->name);
439 			goto interface_err;
440 		}
441 	}
442 
443 	if (platform->driver->ops && platform->driver->ops->hw_params) {
444 		ret = platform->driver->ops->hw_params(substream, params);
445 		if (ret < 0) {
446 			printk(KERN_ERR "asoc: platform %s hw params failed\n",
447 				platform->name);
448 			goto platform_err;
449 		}
450 	}
451 
452 	rtd->rate = params_rate(params);
453 
454 out:
455 	mutex_unlock(&rtd->pcm_mutex);
456 	return ret;
457 
458 platform_err:
459 	if (cpu_dai->driver->ops->hw_free)
460 		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
461 
462 interface_err:
463 	if (codec_dai->driver->ops->hw_free)
464 		codec_dai->driver->ops->hw_free(substream, codec_dai);
465 
466 codec_err:
467 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
468 		rtd->dai_link->ops->hw_free(substream);
469 
470 	mutex_unlock(&rtd->pcm_mutex);
471 	return ret;
472 }
473 
474 /*
475  * Frees resources allocated by hw_params, can be called multiple times
476  */
477 static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
478 {
479 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
480 	struct snd_soc_platform *platform = rtd->platform;
481 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
482 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
483 	struct snd_soc_codec *codec = rtd->codec;
484 
485 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
486 
487 	/* apply codec digital mute */
488 	if (!codec->active)
489 		snd_soc_dai_digital_mute(codec_dai, 1);
490 
491 	/* free any machine hw params */
492 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
493 		rtd->dai_link->ops->hw_free(substream);
494 
495 	/* free any DMA resources */
496 	if (platform->driver->ops && platform->driver->ops->hw_free)
497 		platform->driver->ops->hw_free(substream);
498 
499 	/* now free hw params for the DAIs  */
500 	if (codec_dai->driver->ops->hw_free)
501 		codec_dai->driver->ops->hw_free(substream, codec_dai);
502 
503 	if (cpu_dai->driver->ops->hw_free)
504 		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
505 
506 	mutex_unlock(&rtd->pcm_mutex);
507 	return 0;
508 }
509 
510 static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
511 {
512 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
513 	struct snd_soc_platform *platform = rtd->platform;
514 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
515 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
516 	int ret;
517 
518 	if (codec_dai->driver->ops->trigger) {
519 		ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
520 		if (ret < 0)
521 			return ret;
522 	}
523 
524 	if (platform->driver->ops && platform->driver->ops->trigger) {
525 		ret = platform->driver->ops->trigger(substream, cmd);
526 		if (ret < 0)
527 			return ret;
528 	}
529 
530 	if (cpu_dai->driver->ops->trigger) {
531 		ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
532 		if (ret < 0)
533 			return ret;
534 	}
535 	return 0;
536 }
537 
538 /*
539  * soc level wrapper for pointer callback
540  * If cpu_dai, codec_dai, platform driver has the delay callback, than
541  * the runtime->delay will be updated accordingly.
542  */
543 static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
544 {
545 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
546 	struct snd_soc_platform *platform = rtd->platform;
547 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
548 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
549 	struct snd_pcm_runtime *runtime = substream->runtime;
550 	snd_pcm_uframes_t offset = 0;
551 	snd_pcm_sframes_t delay = 0;
552 
553 	if (platform->driver->ops && platform->driver->ops->pointer)
554 		offset = platform->driver->ops->pointer(substream);
555 
556 	if (cpu_dai->driver->ops->delay)
557 		delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
558 
559 	if (codec_dai->driver->ops->delay)
560 		delay += codec_dai->driver->ops->delay(substream, codec_dai);
561 
562 	if (platform->driver->delay)
563 		delay += platform->driver->delay(substream, codec_dai);
564 
565 	runtime->delay = delay;
566 
567 	return offset;
568 }
569 
570 /* ASoC PCM operations */
571 static struct snd_pcm_ops soc_pcm_ops = {
572 	.open		= soc_pcm_open,
573 	.close		= soc_pcm_close,
574 	.hw_params	= soc_pcm_hw_params,
575 	.hw_free	= soc_pcm_hw_free,
576 	.prepare	= soc_pcm_prepare,
577 	.trigger	= soc_pcm_trigger,
578 	.pointer	= soc_pcm_pointer,
579 };
580 
581 /* create a new pcm */
582 int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
583 {
584 	struct snd_soc_codec *codec = rtd->codec;
585 	struct snd_soc_platform *platform = rtd->platform;
586 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
587 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
588 	struct snd_pcm *pcm;
589 	char new_name[64];
590 	int ret = 0, playback = 0, capture = 0;
591 
592 	/* check client and interface hw capabilities */
593 	snprintf(new_name, sizeof(new_name), "%s %s-%d",
594 			rtd->dai_link->stream_name, codec_dai->name, num);
595 
596 	if (codec_dai->driver->playback.channels_min)
597 		playback = 1;
598 	if (codec_dai->driver->capture.channels_min)
599 		capture = 1;
600 
601 	dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
602 	ret = snd_pcm_new(rtd->card->snd_card, new_name,
603 			num, playback, capture, &pcm);
604 	if (ret < 0) {
605 		printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
606 		return ret;
607 	}
608 
609 	/* DAPM dai link stream work */
610 	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
611 
612 	rtd->pcm = pcm;
613 	pcm->private_data = rtd;
614 	if (platform->driver->ops) {
615 		soc_pcm_ops.mmap = platform->driver->ops->mmap;
616 		soc_pcm_ops.pointer = platform->driver->ops->pointer;
617 		soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
618 		soc_pcm_ops.copy = platform->driver->ops->copy;
619 		soc_pcm_ops.silence = platform->driver->ops->silence;
620 		soc_pcm_ops.ack = platform->driver->ops->ack;
621 		soc_pcm_ops.page = platform->driver->ops->page;
622 	}
623 
624 	if (playback)
625 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
626 
627 	if (capture)
628 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
629 
630 	if (platform->driver->pcm_new) {
631 		ret = platform->driver->pcm_new(rtd);
632 		if (ret < 0) {
633 			pr_err("asoc: platform pcm constructor failed\n");
634 			return ret;
635 		}
636 	}
637 
638 	pcm->private_free = platform->driver->pcm_free;
639 	printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
640 		cpu_dai->name);
641 	return ret;
642 }
643