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