Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel...
[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         /* 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 }