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