Merge branch 'x86-rdrand-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / sound / soc / soc-pcm.c
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 }