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