1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // soc-dai.c 4 // 5 // Copyright (C) 2019 Renesas Electronics Corp. 6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 7 // 8 9 #include <sound/soc.h> 10 #include <sound/soc-dai.h> 11 #include <sound/soc-link.h> 12 13 #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret) 14 static inline int _soc_dai_ret(struct snd_soc_dai *dai, 15 const char *func, int ret) 16 { 17 /* Positive, Zero values are not errors */ 18 if (ret >= 0) 19 return ret; 20 21 /* Negative values might be errors */ 22 switch (ret) { 23 case -EPROBE_DEFER: 24 case -ENOTSUPP: 25 break; 26 default: 27 dev_err(dai->dev, 28 "ASoC: error at %s on %s: %d\n", 29 func, dai->name, ret); 30 } 31 32 return ret; 33 } 34 35 /* 36 * We might want to check substream by using list. 37 * In such case, we can update these macros. 38 */ 39 #define soc_dai_mark_push(dai, substream, tgt) ((dai)->mark_##tgt = substream) 40 #define soc_dai_mark_pop(dai, substream, tgt) ((dai)->mark_##tgt = NULL) 41 #define soc_dai_mark_match(dai, substream, tgt) ((dai)->mark_##tgt == substream) 42 43 /** 44 * snd_soc_dai_set_sysclk - configure DAI system or master clock. 45 * @dai: DAI 46 * @clk_id: DAI specific clock ID 47 * @freq: new clock frequency in Hz 48 * @dir: new clock direction - input/output. 49 * 50 * Configures the DAI master (MCLK) or system (SYSCLK) clocking. 51 */ 52 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 53 unsigned int freq, int dir) 54 { 55 int ret; 56 57 if (dai->driver->ops && 58 dai->driver->ops->set_sysclk) 59 ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); 60 else 61 ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0, 62 freq, dir); 63 64 return soc_dai_ret(dai, ret); 65 } 66 EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); 67 68 /** 69 * snd_soc_dai_set_clkdiv - configure DAI clock dividers. 70 * @dai: DAI 71 * @div_id: DAI specific clock divider ID 72 * @div: new clock divisor. 73 * 74 * Configures the clock dividers. This is used to derive the best DAI bit and 75 * frame clocks from the system or master clock. It's best to set the DAI bit 76 * and frame clocks as low as possible to save system power. 77 */ 78 int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, 79 int div_id, int div) 80 { 81 int ret = -EINVAL; 82 83 if (dai->driver->ops && 84 dai->driver->ops->set_clkdiv) 85 ret = dai->driver->ops->set_clkdiv(dai, div_id, div); 86 87 return soc_dai_ret(dai, ret); 88 } 89 EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); 90 91 /** 92 * snd_soc_dai_set_pll - configure DAI PLL. 93 * @dai: DAI 94 * @pll_id: DAI specific PLL ID 95 * @source: DAI specific source for the PLL 96 * @freq_in: PLL input clock frequency in Hz 97 * @freq_out: requested PLL output clock frequency in Hz 98 * 99 * Configures and enables PLL to generate output clock based on input clock. 100 */ 101 int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, 102 unsigned int freq_in, unsigned int freq_out) 103 { 104 int ret; 105 106 if (dai->driver->ops && 107 dai->driver->ops->set_pll) 108 ret = dai->driver->ops->set_pll(dai, pll_id, source, 109 freq_in, freq_out); 110 else 111 ret = snd_soc_component_set_pll(dai->component, pll_id, source, 112 freq_in, freq_out); 113 114 return soc_dai_ret(dai, ret); 115 } 116 EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); 117 118 /** 119 * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. 120 * @dai: DAI 121 * @ratio: Ratio of BCLK to Sample rate. 122 * 123 * Configures the DAI for a preset BCLK to sample rate ratio. 124 */ 125 int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) 126 { 127 int ret = -EINVAL; 128 129 if (dai->driver->ops && 130 dai->driver->ops->set_bclk_ratio) 131 ret = dai->driver->ops->set_bclk_ratio(dai, ratio); 132 133 return soc_dai_ret(dai, ret); 134 } 135 EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); 136 137 int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd) 138 { 139 struct snd_soc_dai *dai; 140 int i, max = 0; 141 142 /* 143 * return max num if *ALL* DAIs have .auto_selectable_formats 144 */ 145 for_each_rtd_dais(rtd, i, dai) { 146 if (dai->driver->ops && 147 dai->driver->ops->num_auto_selectable_formats) 148 max = max(max, dai->driver->ops->num_auto_selectable_formats); 149 else 150 return 0; 151 } 152 153 return max; 154 } 155 156 /** 157 * snd_soc_dai_get_fmt - get supported audio format. 158 * @dai: DAI 159 * @priority: priority level of supported audio format. 160 * 161 * This should return only formats implemented with high 162 * quality by the DAI so that the core can configure a 163 * format which will work well with other devices. 164 * For example devices which don't support both edges of the 165 * LRCLK signal in I2S style formats should only list DSP 166 * modes. This will mean that sometimes fewer formats 167 * are reported here than are supported by set_fmt(). 168 */ 169 u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority) 170 { 171 const struct snd_soc_dai_ops *ops = dai->driver->ops; 172 u64 fmt = 0; 173 int i, max = 0, until = priority; 174 175 /* 176 * Collect auto_selectable_formats until priority 177 * 178 * ex) 179 * auto_selectable_formats[] = { A, B, C }; 180 * (A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx) 181 * 182 * priority = 1 : A 183 * priority = 2 : A | B 184 * priority = 3 : A | B | C 185 * priority = 4 : A | B | C 186 * ... 187 */ 188 if (ops) 189 max = ops->num_auto_selectable_formats; 190 191 if (max < until) 192 until = max; 193 194 for (i = 0; i < until; i++) 195 fmt |= ops->auto_selectable_formats[i]; 196 197 return fmt; 198 } 199 200 /** 201 * snd_soc_dai_set_fmt - configure DAI hardware audio format. 202 * @dai: DAI 203 * @fmt: SND_SOC_DAIFMT_* format value. 204 * 205 * Configures the DAI hardware format and clocking. 206 */ 207 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 208 { 209 int ret = -ENOTSUPP; 210 211 if (dai->driver->ops && 212 dai->driver->ops->set_fmt) 213 ret = dai->driver->ops->set_fmt(dai, fmt); 214 215 return soc_dai_ret(dai, ret); 216 } 217 EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); 218 219 /** 220 * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask. 221 * @slots: Number of slots in use. 222 * @tx_mask: bitmask representing active TX slots. 223 * @rx_mask: bitmask representing active RX slots. 224 * 225 * Generates the TDM tx and rx slot default masks for DAI. 226 */ 227 static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, 228 unsigned int *tx_mask, 229 unsigned int *rx_mask) 230 { 231 if (*tx_mask || *rx_mask) 232 return 0; 233 234 if (!slots) 235 return -EINVAL; 236 237 *tx_mask = (1 << slots) - 1; 238 *rx_mask = (1 << slots) - 1; 239 240 return 0; 241 } 242 243 /** 244 * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation 245 * @dai: The DAI to configure 246 * @tx_mask: bitmask representing active TX slots. 247 * @rx_mask: bitmask representing active RX slots. 248 * @slots: Number of slots in use. 249 * @slot_width: Width in bits for each slot. 250 * 251 * This function configures the specified DAI for TDM operation. @slot contains 252 * the total number of slots of the TDM stream and @slot_with the width of each 253 * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the 254 * active slots of the TDM stream for the specified DAI, i.e. which slots the 255 * DAI should write to or read from. If a bit is set the corresponding slot is 256 * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to 257 * the first slot, bit 1 to the second slot and so on. The first active slot 258 * maps to the first channel of the DAI, the second active slot to the second 259 * channel and so on. 260 * 261 * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask, 262 * @rx_mask and @slot_width will be ignored. 263 * 264 * Returns 0 on success, a negative error code otherwise. 265 */ 266 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 267 unsigned int tx_mask, unsigned int rx_mask, 268 int slots, int slot_width) 269 { 270 int ret = -ENOTSUPP; 271 272 if (dai->driver->ops && 273 dai->driver->ops->xlate_tdm_slot_mask) 274 dai->driver->ops->xlate_tdm_slot_mask(slots, 275 &tx_mask, &rx_mask); 276 else 277 snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); 278 279 dai->tx_mask = tx_mask; 280 dai->rx_mask = rx_mask; 281 282 if (dai->driver->ops && 283 dai->driver->ops->set_tdm_slot) 284 ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, 285 slots, slot_width); 286 return soc_dai_ret(dai, ret); 287 } 288 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); 289 290 /** 291 * snd_soc_dai_set_channel_map - configure DAI audio channel map 292 * @dai: DAI 293 * @tx_num: how many TX channels 294 * @tx_slot: pointer to an array which imply the TX slot number channel 295 * 0~num-1 uses 296 * @rx_num: how many RX channels 297 * @rx_slot: pointer to an array which imply the RX slot number channel 298 * 0~num-1 uses 299 * 300 * configure the relationship between channel number and TDM slot number. 301 */ 302 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, 303 unsigned int tx_num, unsigned int *tx_slot, 304 unsigned int rx_num, unsigned int *rx_slot) 305 { 306 int ret = -ENOTSUPP; 307 308 if (dai->driver->ops && 309 dai->driver->ops->set_channel_map) 310 ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, 311 rx_num, rx_slot); 312 return soc_dai_ret(dai, ret); 313 } 314 EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); 315 316 /** 317 * snd_soc_dai_get_channel_map - Get DAI audio channel map 318 * @dai: DAI 319 * @tx_num: how many TX channels 320 * @tx_slot: pointer to an array which imply the TX slot number channel 321 * 0~num-1 uses 322 * @rx_num: how many RX channels 323 * @rx_slot: pointer to an array which imply the RX slot number channel 324 * 0~num-1 uses 325 */ 326 int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, 327 unsigned int *tx_num, unsigned int *tx_slot, 328 unsigned int *rx_num, unsigned int *rx_slot) 329 { 330 int ret = -ENOTSUPP; 331 332 if (dai->driver->ops && 333 dai->driver->ops->get_channel_map) 334 ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, 335 rx_num, rx_slot); 336 return soc_dai_ret(dai, ret); 337 } 338 EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); 339 340 /** 341 * snd_soc_dai_set_tristate - configure DAI system or master clock. 342 * @dai: DAI 343 * @tristate: tristate enable 344 * 345 * Tristates the DAI so that others can use it. 346 */ 347 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 348 { 349 int ret = -EINVAL; 350 351 if (dai->driver->ops && 352 dai->driver->ops->set_tristate) 353 ret = dai->driver->ops->set_tristate(dai, tristate); 354 355 return soc_dai_ret(dai, ret); 356 } 357 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); 358 359 /** 360 * snd_soc_dai_digital_mute - configure DAI system or master clock. 361 * @dai: DAI 362 * @mute: mute enable 363 * @direction: stream to mute 364 * 365 * Mutes the DAI DAC. 366 */ 367 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, 368 int direction) 369 { 370 int ret = -ENOTSUPP; 371 372 /* 373 * ignore if direction was CAPTURE 374 * and it had .no_capture_mute flag 375 */ 376 if (dai->driver->ops && 377 dai->driver->ops->mute_stream && 378 (direction == SNDRV_PCM_STREAM_PLAYBACK || 379 !dai->driver->ops->no_capture_mute)) 380 ret = dai->driver->ops->mute_stream(dai, mute, direction); 381 382 return soc_dai_ret(dai, ret); 383 } 384 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); 385 386 int snd_soc_dai_hw_params(struct snd_soc_dai *dai, 387 struct snd_pcm_substream *substream, 388 struct snd_pcm_hw_params *params) 389 { 390 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 391 int ret = 0; 392 393 if (dai->driver->ops && 394 dai->driver->ops->hw_params) { 395 /* perform any topology hw_params fixups before DAI */ 396 ret = snd_soc_link_be_hw_params_fixup(rtd, params); 397 if (ret < 0) 398 goto end; 399 400 ret = dai->driver->ops->hw_params(substream, params, dai); 401 } 402 403 /* mark substream if succeeded */ 404 if (ret == 0) 405 soc_dai_mark_push(dai, substream, hw_params); 406 end: 407 return soc_dai_ret(dai, ret); 408 } 409 410 void snd_soc_dai_hw_free(struct snd_soc_dai *dai, 411 struct snd_pcm_substream *substream, 412 int rollback) 413 { 414 if (rollback && !soc_dai_mark_match(dai, substream, hw_params)) 415 return; 416 417 if (dai->driver->ops && 418 dai->driver->ops->hw_free) 419 dai->driver->ops->hw_free(substream, dai); 420 421 /* remove marked substream */ 422 soc_dai_mark_pop(dai, substream, hw_params); 423 } 424 425 int snd_soc_dai_startup(struct snd_soc_dai *dai, 426 struct snd_pcm_substream *substream) 427 { 428 int ret = 0; 429 430 if (dai->driver->ops && 431 dai->driver->ops->startup) 432 ret = dai->driver->ops->startup(substream, dai); 433 434 /* mark substream if succeeded */ 435 if (ret == 0) 436 soc_dai_mark_push(dai, substream, startup); 437 438 return soc_dai_ret(dai, ret); 439 } 440 441 void snd_soc_dai_shutdown(struct snd_soc_dai *dai, 442 struct snd_pcm_substream *substream, 443 int rollback) 444 { 445 if (rollback && !soc_dai_mark_match(dai, substream, startup)) 446 return; 447 448 if (dai->driver->ops && 449 dai->driver->ops->shutdown) 450 dai->driver->ops->shutdown(substream, dai); 451 452 /* remove marked substream */ 453 soc_dai_mark_pop(dai, substream, startup); 454 } 455 456 snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, 457 struct snd_pcm_substream *substream) 458 { 459 int delay = 0; 460 461 if (dai->driver->ops && 462 dai->driver->ops->delay) 463 delay = dai->driver->ops->delay(substream, dai); 464 465 return delay; 466 } 467 468 int snd_soc_dai_compress_new(struct snd_soc_dai *dai, 469 struct snd_soc_pcm_runtime *rtd, int num) 470 { 471 int ret = -ENOTSUPP; 472 if (dai->driver->compress_new) 473 ret = dai->driver->compress_new(rtd, num); 474 return soc_dai_ret(dai, ret); 475 } 476 477 /* 478 * snd_soc_dai_stream_valid() - check if a DAI supports the given stream 479 * 480 * Returns true if the DAI supports the indicated stream type. 481 */ 482 bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) 483 { 484 struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir); 485 486 /* If the codec specifies any channels at all, it supports the stream */ 487 return stream->channels_min; 488 } 489 490 /* 491 * snd_soc_dai_link_set_capabilities() - set dai_link properties based on its DAIs 492 */ 493 void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link) 494 { 495 bool supported[SNDRV_PCM_STREAM_LAST + 1]; 496 int direction; 497 498 for_each_pcm_streams(direction) { 499 struct snd_soc_dai_link_component *cpu; 500 struct snd_soc_dai_link_component *codec; 501 struct snd_soc_dai *dai; 502 bool supported_cpu = false; 503 bool supported_codec = false; 504 int i; 505 506 for_each_link_cpus(dai_link, i, cpu) { 507 dai = snd_soc_find_dai_with_mutex(cpu); 508 if (dai && snd_soc_dai_stream_valid(dai, direction)) { 509 supported_cpu = true; 510 break; 511 } 512 } 513 for_each_link_codecs(dai_link, i, codec) { 514 dai = snd_soc_find_dai_with_mutex(codec); 515 if (dai && snd_soc_dai_stream_valid(dai, direction)) { 516 supported_codec = true; 517 break; 518 } 519 } 520 supported[direction] = supported_cpu && supported_codec; 521 } 522 523 dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK]; 524 dai_link->dpcm_capture = supported[SNDRV_PCM_STREAM_CAPTURE]; 525 } 526 EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities); 527 528 void snd_soc_dai_action(struct snd_soc_dai *dai, 529 int stream, int action) 530 { 531 /* see snd_soc_dai_stream_active() */ 532 dai->stream_active[stream] += action; 533 534 /* see snd_soc_component_active() */ 535 dai->component->active += action; 536 } 537 EXPORT_SYMBOL_GPL(snd_soc_dai_action); 538 539 int snd_soc_dai_active(struct snd_soc_dai *dai) 540 { 541 int stream, active; 542 543 active = 0; 544 for_each_pcm_streams(stream) 545 active += dai->stream_active[stream]; 546 547 return active; 548 } 549 EXPORT_SYMBOL_GPL(snd_soc_dai_active); 550 551 int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) 552 { 553 struct snd_soc_dai *dai; 554 int i; 555 556 for_each_rtd_dais(rtd, i, dai) { 557 if (dai->driver->probe_order != order) 558 continue; 559 560 if (dai->driver->probe) { 561 int ret = dai->driver->probe(dai); 562 563 if (ret < 0) 564 return soc_dai_ret(dai, ret); 565 } 566 567 dai->probed = 1; 568 } 569 570 return 0; 571 } 572 573 int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order) 574 { 575 struct snd_soc_dai *dai; 576 int i, r, ret = 0; 577 578 for_each_rtd_dais(rtd, i, dai) { 579 if (dai->driver->remove_order != order) 580 continue; 581 582 if (dai->probed && 583 dai->driver->remove) { 584 r = dai->driver->remove(dai); 585 if (r < 0) 586 ret = r; /* use last error */ 587 } 588 589 dai->probed = 0; 590 } 591 592 return ret; 593 } 594 595 int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) 596 { 597 struct snd_soc_dai *dai; 598 int i; 599 600 for_each_rtd_dais(rtd, i, dai) { 601 if (dai->driver->pcm_new) { 602 int ret = dai->driver->pcm_new(rtd, dai); 603 if (ret < 0) 604 return soc_dai_ret(dai, ret); 605 } 606 } 607 608 return 0; 609 } 610 611 int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) 612 { 613 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 614 struct snd_soc_dai *dai; 615 int i, ret; 616 617 for_each_rtd_dais(rtd, i, dai) { 618 if (dai->driver->ops && 619 dai->driver->ops->prepare) { 620 ret = dai->driver->ops->prepare(substream, dai); 621 if (ret < 0) 622 return soc_dai_ret(dai, ret); 623 } 624 } 625 626 return 0; 627 } 628 629 static int soc_dai_trigger(struct snd_soc_dai *dai, 630 struct snd_pcm_substream *substream, int cmd) 631 { 632 int ret = 0; 633 634 if (dai->driver->ops && 635 dai->driver->ops->trigger) 636 ret = dai->driver->ops->trigger(substream, cmd, dai); 637 638 return soc_dai_ret(dai, ret); 639 } 640 641 int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, 642 int cmd, int rollback) 643 { 644 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 645 struct snd_soc_dai *dai; 646 int i, r, ret = 0; 647 648 switch (cmd) { 649 case SNDRV_PCM_TRIGGER_START: 650 case SNDRV_PCM_TRIGGER_RESUME: 651 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 652 for_each_rtd_dais(rtd, i, dai) { 653 ret = soc_dai_trigger(dai, substream, cmd); 654 if (ret < 0) 655 break; 656 soc_dai_mark_push(dai, substream, trigger); 657 } 658 break; 659 case SNDRV_PCM_TRIGGER_STOP: 660 case SNDRV_PCM_TRIGGER_SUSPEND: 661 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 662 for_each_rtd_dais(rtd, i, dai) { 663 if (rollback && !soc_dai_mark_match(dai, substream, trigger)) 664 continue; 665 666 r = soc_dai_trigger(dai, substream, cmd); 667 if (r < 0) 668 ret = r; /* use last ret */ 669 soc_dai_mark_pop(dai, substream, trigger); 670 } 671 } 672 673 return ret; 674 } 675 676 int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, 677 int cmd) 678 { 679 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 680 struct snd_soc_dai *dai; 681 int i, ret; 682 683 for_each_rtd_dais(rtd, i, dai) { 684 if (dai->driver->ops && 685 dai->driver->ops->bespoke_trigger) { 686 ret = dai->driver->ops->bespoke_trigger(substream, 687 cmd, dai); 688 if (ret < 0) 689 return soc_dai_ret(dai, ret); 690 } 691 } 692 693 return 0; 694 } 695 696 int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, 697 struct snd_compr_stream *cstream) 698 { 699 int ret = 0; 700 701 if (dai->driver->cops && 702 dai->driver->cops->startup) 703 ret = dai->driver->cops->startup(cstream, dai); 704 705 /* mark cstream if succeeded */ 706 if (ret == 0) 707 soc_dai_mark_push(dai, cstream, compr_startup); 708 709 return soc_dai_ret(dai, ret); 710 } 711 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup); 712 713 void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, 714 struct snd_compr_stream *cstream, 715 int rollback) 716 { 717 if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup)) 718 return; 719 720 if (dai->driver->cops && 721 dai->driver->cops->shutdown) 722 dai->driver->cops->shutdown(cstream, dai); 723 724 /* remove marked cstream */ 725 soc_dai_mark_pop(dai, cstream, compr_startup); 726 } 727 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); 728 729 int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, 730 struct snd_compr_stream *cstream, int cmd) 731 { 732 int ret = 0; 733 734 if (dai->driver->cops && 735 dai->driver->cops->trigger) 736 ret = dai->driver->cops->trigger(cstream, cmd, dai); 737 738 return soc_dai_ret(dai, ret); 739 } 740 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger); 741 742 int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, 743 struct snd_compr_stream *cstream, 744 struct snd_compr_params *params) 745 { 746 int ret = 0; 747 748 if (dai->driver->cops && 749 dai->driver->cops->set_params) 750 ret = dai->driver->cops->set_params(cstream, params, dai); 751 752 return soc_dai_ret(dai, ret); 753 } 754 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params); 755 756 int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, 757 struct snd_compr_stream *cstream, 758 struct snd_codec *params) 759 { 760 int ret = 0; 761 762 if (dai->driver->cops && 763 dai->driver->cops->get_params) 764 ret = dai->driver->cops->get_params(cstream, params, dai); 765 766 return soc_dai_ret(dai, ret); 767 } 768 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params); 769 770 int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, 771 struct snd_compr_stream *cstream, 772 size_t bytes) 773 { 774 int ret = 0; 775 776 if (dai->driver->cops && 777 dai->driver->cops->ack) 778 ret = dai->driver->cops->ack(cstream, bytes, dai); 779 780 return soc_dai_ret(dai, ret); 781 } 782 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); 783 784 int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, 785 struct snd_compr_stream *cstream, 786 struct snd_compr_tstamp *tstamp) 787 { 788 int ret = 0; 789 790 if (dai->driver->cops && 791 dai->driver->cops->pointer) 792 ret = dai->driver->cops->pointer(cstream, tstamp, dai); 793 794 return soc_dai_ret(dai, ret); 795 } 796 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer); 797 798 int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, 799 struct snd_compr_stream *cstream, 800 struct snd_compr_metadata *metadata) 801 { 802 int ret = 0; 803 804 if (dai->driver->cops && 805 dai->driver->cops->set_metadata) 806 ret = dai->driver->cops->set_metadata(cstream, metadata, dai); 807 808 return soc_dai_ret(dai, ret); 809 } 810 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata); 811 812 int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, 813 struct snd_compr_stream *cstream, 814 struct snd_compr_metadata *metadata) 815 { 816 int ret = 0; 817 818 if (dai->driver->cops && 819 dai->driver->cops->get_metadata) 820 ret = dai->driver->cops->get_metadata(cstream, metadata, dai); 821 822 return soc_dai_ret(dai, ret); 823 } 824 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata); 825