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 (slots) { 263 if (dai->driver->ops && 264 dai->driver->ops->xlate_tdm_slot_mask) 265 ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); 266 else 267 ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); 268 if (ret) 269 goto err; 270 } 271 272 for_each_pcm_streams(stream) 273 snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]); 274 275 if (dai->driver->ops && 276 dai->driver->ops->set_tdm_slot) 277 ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, 278 slots, slot_width); 279 err: 280 return soc_dai_ret(dai, ret); 281 } 282 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); 283 284 /** 285 * snd_soc_dai_set_channel_map - configure DAI audio channel map 286 * @dai: DAI 287 * @tx_num: how many TX channels 288 * @tx_slot: pointer to an array which imply the TX slot number channel 289 * 0~num-1 uses 290 * @rx_num: how many RX channels 291 * @rx_slot: pointer to an array which imply the RX slot number channel 292 * 0~num-1 uses 293 * 294 * configure the relationship between channel number and TDM slot number. 295 */ 296 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, 297 unsigned int tx_num, const unsigned int *tx_slot, 298 unsigned int rx_num, const unsigned int *rx_slot) 299 { 300 int ret = -ENOTSUPP; 301 302 if (dai->driver->ops && 303 dai->driver->ops->set_channel_map) 304 ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, 305 rx_num, rx_slot); 306 return soc_dai_ret(dai, ret); 307 } 308 EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); 309 310 /** 311 * snd_soc_dai_get_channel_map - Get DAI audio channel map 312 * @dai: DAI 313 * @tx_num: how many TX channels 314 * @tx_slot: pointer to an array which imply the TX slot number channel 315 * 0~num-1 uses 316 * @rx_num: how many RX channels 317 * @rx_slot: pointer to an array which imply the RX slot number channel 318 * 0~num-1 uses 319 */ 320 int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai, 321 unsigned int *tx_num, unsigned int *tx_slot, 322 unsigned int *rx_num, unsigned int *rx_slot) 323 { 324 int ret = -ENOTSUPP; 325 326 if (dai->driver->ops && 327 dai->driver->ops->get_channel_map) 328 ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, 329 rx_num, rx_slot); 330 return soc_dai_ret(dai, ret); 331 } 332 EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); 333 334 /** 335 * snd_soc_dai_set_tristate - configure DAI system or master clock. 336 * @dai: DAI 337 * @tristate: tristate enable 338 * 339 * Tristates the DAI so that others can use it. 340 */ 341 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 342 { 343 int ret = -EINVAL; 344 345 if (dai->driver->ops && 346 dai->driver->ops->set_tristate) 347 ret = dai->driver->ops->set_tristate(dai, tristate); 348 349 return soc_dai_ret(dai, ret); 350 } 351 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); 352 353 int snd_soc_dai_prepare(struct snd_soc_dai *dai, 354 struct snd_pcm_substream *substream) 355 { 356 int ret = 0; 357 358 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 359 return 0; 360 361 if (dai->driver->ops && 362 dai->driver->ops->prepare) 363 ret = dai->driver->ops->prepare(substream, dai); 364 365 return soc_dai_ret(dai, ret); 366 } 367 EXPORT_SYMBOL_GPL(snd_soc_dai_prepare); 368 369 int snd_soc_dai_mute_is_ctrled_at_trigger(struct snd_soc_dai *dai) 370 { 371 if (dai->driver->ops) 372 return dai->driver->ops->mute_unmute_on_trigger; 373 374 return 0; 375 } 376 377 /** 378 * snd_soc_dai_digital_mute - configure DAI system or master clock. 379 * @dai: DAI 380 * @mute: mute enable 381 * @direction: stream to mute 382 * 383 * Mutes the DAI DAC. 384 */ 385 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, 386 int direction) 387 { 388 int ret = -ENOTSUPP; 389 390 /* 391 * ignore if direction was CAPTURE 392 * and it had .no_capture_mute flag 393 */ 394 if (dai->driver->ops && 395 dai->driver->ops->mute_stream && 396 (direction == SNDRV_PCM_STREAM_PLAYBACK || 397 !dai->driver->ops->no_capture_mute)) 398 ret = dai->driver->ops->mute_stream(dai, mute, direction); 399 400 return soc_dai_ret(dai, ret); 401 } 402 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); 403 404 int snd_soc_dai_hw_params(struct snd_soc_dai *dai, 405 struct snd_pcm_substream *substream, 406 struct snd_pcm_hw_params *params) 407 { 408 int ret = 0; 409 410 if (dai->driver->ops && 411 dai->driver->ops->hw_params) 412 ret = dai->driver->ops->hw_params(substream, params, dai); 413 414 /* mark substream if succeeded */ 415 if (ret == 0) 416 soc_dai_mark_push(dai, substream, hw_params); 417 418 return soc_dai_ret(dai, ret); 419 } 420 421 void snd_soc_dai_hw_free(struct snd_soc_dai *dai, 422 struct snd_pcm_substream *substream, 423 int rollback) 424 { 425 if (rollback && !soc_dai_mark_match(dai, substream, hw_params)) 426 return; 427 428 if (dai->driver->ops && 429 dai->driver->ops->hw_free) 430 dai->driver->ops->hw_free(substream, dai); 431 432 /* remove marked substream */ 433 soc_dai_mark_pop(dai, hw_params); 434 } 435 436 int snd_soc_dai_startup(struct snd_soc_dai *dai, 437 struct snd_pcm_substream *substream) 438 { 439 int ret = 0; 440 441 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 442 return 0; 443 444 if (dai->driver->ops && 445 dai->driver->ops->startup) 446 ret = dai->driver->ops->startup(substream, dai); 447 448 /* mark substream if succeeded */ 449 if (ret == 0) 450 soc_dai_mark_push(dai, substream, startup); 451 452 return soc_dai_ret(dai, ret); 453 } 454 455 void snd_soc_dai_shutdown(struct snd_soc_dai *dai, 456 struct snd_pcm_substream *substream, 457 int rollback) 458 { 459 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 460 return; 461 462 if (rollback && !soc_dai_mark_match(dai, substream, startup)) 463 return; 464 465 if (dai->driver->ops && 466 dai->driver->ops->shutdown) 467 dai->driver->ops->shutdown(substream, dai); 468 469 /* remove marked substream */ 470 soc_dai_mark_pop(dai, startup); 471 } 472 473 int snd_soc_dai_compress_new(struct snd_soc_dai *dai, 474 struct snd_soc_pcm_runtime *rtd) 475 { 476 int ret = -ENOTSUPP; 477 if (dai->driver->ops && 478 dai->driver->ops->compress_new) 479 ret = dai->driver->ops->compress_new(rtd); 480 return soc_dai_ret(dai, ret); 481 } 482 483 /* 484 * snd_soc_dai_stream_valid() - check if a DAI supports the given stream 485 * 486 * Returns true if the DAI supports the indicated stream type. 487 */ 488 bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir) 489 { 490 const struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir); 491 492 /* If the codec specifies any channels at all, it supports the stream */ 493 return stream->channels_min; 494 } 495 496 void snd_soc_dai_action(struct snd_soc_dai *dai, 497 int stream, int action) 498 { 499 /* see snd_soc_dai_stream_active() */ 500 dai->stream[stream].active += action; 501 502 /* see snd_soc_component_active() */ 503 dai->component->active += action; 504 } 505 EXPORT_SYMBOL_GPL(snd_soc_dai_action); 506 507 int snd_soc_dai_active(const struct snd_soc_dai *dai) 508 { 509 int stream, active; 510 511 active = 0; 512 for_each_pcm_streams(stream) 513 active += dai->stream[stream].active; 514 515 return active; 516 } 517 EXPORT_SYMBOL_GPL(snd_soc_dai_active); 518 519 int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) 520 { 521 struct snd_soc_dai *dai; 522 int i; 523 524 for_each_rtd_dais(rtd, i, dai) { 525 if (dai->probed) 526 continue; 527 528 if (dai->driver->ops) { 529 if (dai->driver->ops->probe_order != order) 530 continue; 531 532 if (dai->driver->ops->probe) { 533 int ret = dai->driver->ops->probe(dai); 534 535 if (ret < 0) 536 return soc_dai_ret(dai, ret); 537 } 538 } 539 dai->probed = 1; 540 } 541 542 return 0; 543 } 544 545 int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order) 546 { 547 struct snd_soc_dai *dai; 548 int i, r, ret = 0; 549 550 for_each_rtd_dais(rtd, i, dai) { 551 if (!dai->probed) 552 continue; 553 554 if (dai->driver->ops) { 555 if (dai->driver->ops->remove_order != order) 556 continue; 557 558 if (dai->driver->ops->remove) { 559 r = dai->driver->ops->remove(dai); 560 if (r < 0) 561 ret = r; /* use last error */ 562 } 563 } 564 dai->probed = 0; 565 } 566 567 return ret; 568 } 569 570 int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) 571 { 572 struct snd_soc_dai *dai; 573 int i; 574 575 for_each_rtd_dais(rtd, i, dai) { 576 if (dai->driver->ops && 577 dai->driver->ops->pcm_new) { 578 int ret = dai->driver->ops->pcm_new(rtd, dai); 579 if (ret < 0) 580 return soc_dai_ret(dai, ret); 581 } 582 } 583 584 return 0; 585 } 586 587 int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) 588 { 589 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 590 struct snd_soc_dai *dai; 591 int i, ret; 592 593 for_each_rtd_dais(rtd, i, dai) { 594 ret = snd_soc_dai_prepare(dai, substream); 595 if (ret < 0) 596 return ret; 597 } 598 599 return 0; 600 } 601 602 static int soc_dai_trigger(struct snd_soc_dai *dai, 603 struct snd_pcm_substream *substream, int cmd) 604 { 605 int ret = 0; 606 607 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 608 return 0; 609 610 if (dai->driver->ops && 611 dai->driver->ops->trigger) 612 ret = dai->driver->ops->trigger(substream, cmd, dai); 613 614 return soc_dai_ret(dai, ret); 615 } 616 617 int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, 618 int cmd, int rollback) 619 { 620 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 621 struct snd_soc_dai *dai; 622 int i, r, ret = 0; 623 624 switch (cmd) { 625 case SNDRV_PCM_TRIGGER_START: 626 case SNDRV_PCM_TRIGGER_RESUME: 627 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 628 for_each_rtd_dais(rtd, i, dai) { 629 ret = soc_dai_trigger(dai, substream, cmd); 630 if (ret < 0) 631 break; 632 633 if (snd_soc_dai_mute_is_ctrled_at_trigger(dai)) 634 snd_soc_dai_digital_mute(dai, 0, substream->stream); 635 636 soc_dai_mark_push(dai, substream, trigger); 637 } 638 break; 639 case SNDRV_PCM_TRIGGER_STOP: 640 case SNDRV_PCM_TRIGGER_SUSPEND: 641 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 642 for_each_rtd_dais(rtd, i, dai) { 643 if (rollback && !soc_dai_mark_match(dai, substream, trigger)) 644 continue; 645 646 if (snd_soc_dai_mute_is_ctrled_at_trigger(dai)) 647 snd_soc_dai_digital_mute(dai, 1, substream->stream); 648 649 r = soc_dai_trigger(dai, substream, cmd); 650 if (r < 0) 651 ret = r; /* use last ret */ 652 soc_dai_mark_pop(dai, trigger); 653 } 654 } 655 656 return ret; 657 } 658 659 void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, 660 snd_pcm_sframes_t *cpu_delay, 661 snd_pcm_sframes_t *codec_delay) 662 { 663 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 664 struct snd_soc_dai *dai; 665 int i; 666 667 /* 668 * We're looking for the delay through the full audio path so it needs to 669 * be the maximum of the DAIs doing transmit and the maximum of the DAIs 670 * doing receive (ie, all CPUs and all CODECs) rather than just the maximum 671 * of all DAIs. 672 */ 673 674 /* for CPU */ 675 for_each_rtd_cpu_dais(rtd, i, dai) 676 if (dai->driver->ops && 677 dai->driver->ops->delay) 678 *cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai)); 679 680 /* for Codec */ 681 for_each_rtd_codec_dais(rtd, i, dai) 682 if (dai->driver->ops && 683 dai->driver->ops->delay) 684 *codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai)); 685 } 686 687 int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, 688 struct snd_compr_stream *cstream) 689 { 690 int ret = 0; 691 692 if (dai->driver->cops && 693 dai->driver->cops->startup) 694 ret = dai->driver->cops->startup(cstream, dai); 695 696 /* mark cstream if succeeded */ 697 if (ret == 0) 698 soc_dai_mark_push(dai, cstream, compr_startup); 699 700 return soc_dai_ret(dai, ret); 701 } 702 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup); 703 704 void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, 705 struct snd_compr_stream *cstream, 706 int rollback) 707 { 708 if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup)) 709 return; 710 711 if (dai->driver->cops && 712 dai->driver->cops->shutdown) 713 dai->driver->cops->shutdown(cstream, dai); 714 715 /* remove marked cstream */ 716 soc_dai_mark_pop(dai, compr_startup); 717 } 718 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); 719 720 int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, 721 struct snd_compr_stream *cstream, int cmd) 722 { 723 int ret = 0; 724 725 if (dai->driver->cops && 726 dai->driver->cops->trigger) 727 ret = dai->driver->cops->trigger(cstream, cmd, dai); 728 729 return soc_dai_ret(dai, ret); 730 } 731 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger); 732 733 int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, 734 struct snd_compr_stream *cstream, 735 struct snd_compr_params *params) 736 { 737 int ret = 0; 738 739 if (dai->driver->cops && 740 dai->driver->cops->set_params) 741 ret = dai->driver->cops->set_params(cstream, params, dai); 742 743 return soc_dai_ret(dai, ret); 744 } 745 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params); 746 747 int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, 748 struct snd_compr_stream *cstream, 749 struct snd_codec *params) 750 { 751 int ret = 0; 752 753 if (dai->driver->cops && 754 dai->driver->cops->get_params) 755 ret = dai->driver->cops->get_params(cstream, params, dai); 756 757 return soc_dai_ret(dai, ret); 758 } 759 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params); 760 761 int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, 762 struct snd_compr_stream *cstream, 763 size_t bytes) 764 { 765 int ret = 0; 766 767 if (dai->driver->cops && 768 dai->driver->cops->ack) 769 ret = dai->driver->cops->ack(cstream, bytes, dai); 770 771 return soc_dai_ret(dai, ret); 772 } 773 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); 774 775 int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, 776 struct snd_compr_stream *cstream, 777 struct snd_compr_tstamp64 *tstamp) 778 { 779 int ret = 0; 780 781 if (dai->driver->cops && 782 dai->driver->cops->pointer) 783 ret = dai->driver->cops->pointer(cstream, tstamp, dai); 784 785 return soc_dai_ret(dai, ret); 786 } 787 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer); 788 789 int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, 790 struct snd_compr_stream *cstream, 791 struct snd_compr_metadata *metadata) 792 { 793 int ret = 0; 794 795 if (dai->driver->cops && 796 dai->driver->cops->set_metadata) 797 ret = dai->driver->cops->set_metadata(cstream, metadata, dai); 798 799 return soc_dai_ret(dai, ret); 800 } 801 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata); 802 803 int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, 804 struct snd_compr_stream *cstream, 805 struct snd_compr_metadata *metadata) 806 { 807 int ret = 0; 808 809 if (dai->driver->cops && 810 dai->driver->cops->get_metadata) 811 ret = dai->driver->cops->get_metadata(cstream, metadata, dai); 812 813 return soc_dai_ret(dai, ret); 814 } 815 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata); 816