Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 856 lines 22 kB view raw
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) 14static 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 */ 38int 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} 52EXPORT_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 */ 64int 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} 75EXPORT_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 */ 87int 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} 102EXPORT_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 */ 111int 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} 121EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); 122 123int 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 */ 155u64 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 if (ops && ops->auto_selectable_formats) 181 for (i = 0; i < until; i++) 182 fmt |= ops->auto_selectable_formats[i]; 183 184 return fmt; 185} 186 187/** 188 * snd_soc_dai_set_fmt - configure DAI hardware audio format. 189 * @dai: DAI 190 * @fmt: SND_SOC_DAIFMT_* format value. 191 * 192 * Configures the DAI hardware format and clocking. 193 */ 194int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 195{ 196 int ret = -ENOTSUPP; 197 198 if (dai->driver->ops && dai->driver->ops->set_fmt) 199 ret = dai->driver->ops->set_fmt(dai, fmt); 200 201 return soc_dai_ret(dai, ret); 202} 203EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); 204 205/** 206 * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask. 207 * @slots: Number of slots in use. 208 * @tx_mask: bitmask representing active TX slots. 209 * @rx_mask: bitmask representing active RX slots. 210 * 211 * Generates the TDM tx and rx slot default masks for DAI. 212 */ 213static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, 214 unsigned int *tx_mask, 215 unsigned int *rx_mask) 216{ 217 if (*tx_mask || *rx_mask) 218 return 0; 219 220 if (!slots) 221 return -EINVAL; 222 223 *tx_mask = (1 << slots) - 1; 224 *rx_mask = (1 << slots) - 1; 225 226 return 0; 227} 228 229/** 230 * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation 231 * @dai: The DAI to configure 232 * @tx_mask: bitmask representing active TX slots. 233 * @rx_mask: bitmask representing active RX slots. 234 * @slots: Number of slots in use. 235 * @slot_width: Width in bits for each slot. 236 * 237 * This function configures the specified DAI for TDM operation. @slot contains 238 * the total number of slots of the TDM stream and @slot_with the width of each 239 * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the 240 * active slots of the TDM stream for the specified DAI, i.e. which slots the 241 * DAI should write to or read from. If a bit is set the corresponding slot is 242 * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to 243 * the first slot, bit 1 to the second slot and so on. The first active slot 244 * maps to the first channel of the DAI, the second active slot to the second 245 * channel and so on. 246 * 247 * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask, 248 * @rx_mask and @slot_width will be ignored. 249 * 250 * Returns 0 on success, a negative error code otherwise. 251 */ 252int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 253 unsigned int tx_mask, unsigned int rx_mask, 254 int slots, int slot_width) 255{ 256 int ret = -ENOTSUPP; 257 int stream; 258 unsigned int *tdm_mask[] = { 259 &tx_mask, 260 &rx_mask, 261 }; 262 263 if (slots) { 264 if (dai->driver->ops && 265 dai->driver->ops->xlate_tdm_slot_mask) 266 ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); 267 else 268 ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); 269 if (ret) 270 goto err; 271 } 272 273 for_each_pcm_streams(stream) 274 snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]); 275 276 if (dai->driver->ops && 277 dai->driver->ops->set_tdm_slot) 278 ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, 279 slots, slot_width); 280err: 281 return soc_dai_ret(dai, ret); 282} 283EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); 284 285/** 286 * snd_soc_dai_set_tdm_idle() - Configure a DAI's TDM idle mode 287 * @dai: The DAI to configure 288 * @tx_mask: bitmask representing idle TX slots. 289 * @rx_mask: bitmask representing idle RX slots. 290 * @tx_mode: idle mode to set for TX slots. 291 * @rx_mode: idle mode to set for RX slots. 292 * 293 * This function configures the DAI to handle idle TDM slots in the 294 * specified manner. @tx_mode and @rx_mode can be one of 295 * SND_SOC_DAI_TDM_IDLE_NONE, SND_SOC_DAI_TDM_IDLE_ZERO, 296 * SND_SOC_DAI_TDM_IDLE_PULLDOWN, or SND_SOC_DAI_TDM_IDLE_HIZ. 297 * SND_SOC_TDM_IDLE_NONE represents the DAI's default/unset idle slot 298 * handling state and could be any of the other modes depending on the 299 * hardware behind the DAI. It is therefore undefined behaviour when set 300 * explicitly. 301 * 302 * Mode and mask can be set independently for both the TX and RX direction. 303 * Some hardware may ignore both TX and RX masks depending on its 304 * capabilities. 305 */ 306int snd_soc_dai_set_tdm_idle(struct snd_soc_dai *dai, 307 unsigned int tx_mask, unsigned int rx_mask, 308 int tx_mode, int rx_mode) 309{ 310 int ret = -EOPNOTSUPP; 311 312 /* You can't write to the RX line */ 313 if (rx_mode == SND_SOC_DAI_TDM_IDLE_ZERO) 314 return soc_dai_ret(dai, -EINVAL); 315 316 if (dai->driver->ops && 317 dai->driver->ops->set_tdm_idle) 318 ret = dai->driver->ops->set_tdm_idle(dai, tx_mask, rx_mask, 319 tx_mode, rx_mode); 320 321 return soc_dai_ret(dai, ret); 322} 323EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_idle); 324 325/** 326 * snd_soc_dai_set_channel_map - configure DAI audio channel map 327 * @dai: DAI 328 * @tx_num: how many TX channels 329 * @tx_slot: pointer to an array which imply the TX slot number channel 330 * 0~num-1 uses 331 * @rx_num: how many RX channels 332 * @rx_slot: pointer to an array which imply the RX slot number channel 333 * 0~num-1 uses 334 * 335 * configure the relationship between channel number and TDM slot number. 336 */ 337int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, 338 unsigned int tx_num, const unsigned int *tx_slot, 339 unsigned int rx_num, const unsigned int *rx_slot) 340{ 341 int ret = -ENOTSUPP; 342 343 if (dai->driver->ops && 344 dai->driver->ops->set_channel_map) 345 ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, 346 rx_num, rx_slot); 347 return soc_dai_ret(dai, ret); 348} 349EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); 350 351/** 352 * snd_soc_dai_get_channel_map - Get DAI audio channel map 353 * @dai: DAI 354 * @tx_num: how many TX channels 355 * @tx_slot: pointer to an array which imply the TX slot number channel 356 * 0~num-1 uses 357 * @rx_num: how many RX channels 358 * @rx_slot: pointer to an array which imply the RX slot number channel 359 * 0~num-1 uses 360 */ 361int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai, 362 unsigned int *tx_num, unsigned int *tx_slot, 363 unsigned int *rx_num, unsigned int *rx_slot) 364{ 365 int ret = -ENOTSUPP; 366 367 if (dai->driver->ops && 368 dai->driver->ops->get_channel_map) 369 ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, 370 rx_num, rx_slot); 371 return soc_dai_ret(dai, ret); 372} 373EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); 374 375/** 376 * snd_soc_dai_set_tristate - configure DAI system or master clock. 377 * @dai: DAI 378 * @tristate: tristate enable 379 * 380 * Tristates the DAI so that others can use it. 381 */ 382int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 383{ 384 int ret = -EINVAL; 385 386 if (dai->driver->ops && 387 dai->driver->ops->set_tristate) 388 ret = dai->driver->ops->set_tristate(dai, tristate); 389 390 return soc_dai_ret(dai, ret); 391} 392EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); 393 394int snd_soc_dai_prepare(struct snd_soc_dai *dai, 395 struct snd_pcm_substream *substream) 396{ 397 int ret = 0; 398 399 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 400 return 0; 401 402 if (dai->driver->ops && 403 dai->driver->ops->prepare) 404 ret = dai->driver->ops->prepare(substream, dai); 405 406 return soc_dai_ret(dai, ret); 407} 408EXPORT_SYMBOL_GPL(snd_soc_dai_prepare); 409 410int snd_soc_dai_mute_is_ctrled_at_trigger(struct snd_soc_dai *dai) 411{ 412 if (dai->driver->ops) 413 return dai->driver->ops->mute_unmute_on_trigger; 414 415 return 0; 416} 417 418/** 419 * snd_soc_dai_digital_mute - configure DAI system or master clock. 420 * @dai: DAI 421 * @mute: mute enable 422 * @direction: stream to mute 423 * 424 * Mutes the DAI DAC. 425 */ 426int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, 427 int direction) 428{ 429 int ret = -ENOTSUPP; 430 431 /* 432 * ignore if direction was CAPTURE 433 * and it had .no_capture_mute flag 434 */ 435 if (dai->driver->ops && 436 dai->driver->ops->mute_stream && 437 (direction == SNDRV_PCM_STREAM_PLAYBACK || 438 !dai->driver->ops->no_capture_mute)) 439 ret = dai->driver->ops->mute_stream(dai, mute, direction); 440 441 return soc_dai_ret(dai, ret); 442} 443EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); 444 445int snd_soc_dai_hw_params(struct snd_soc_dai *dai, 446 struct snd_pcm_substream *substream, 447 struct snd_pcm_hw_params *params) 448{ 449 int ret = 0; 450 451 if (dai->driver->ops && 452 dai->driver->ops->hw_params) 453 ret = dai->driver->ops->hw_params(substream, params, dai); 454 455 /* mark substream if succeeded */ 456 if (ret == 0) 457 soc_dai_mark_push(dai, substream, hw_params); 458 459 return soc_dai_ret(dai, ret); 460} 461 462void snd_soc_dai_hw_free(struct snd_soc_dai *dai, 463 struct snd_pcm_substream *substream, 464 int rollback) 465{ 466 if (rollback && !soc_dai_mark_match(dai, substream, hw_params)) 467 return; 468 469 if (dai->driver->ops && 470 dai->driver->ops->hw_free) 471 dai->driver->ops->hw_free(substream, dai); 472 473 /* remove marked substream */ 474 soc_dai_mark_pop(dai, hw_params); 475} 476 477int snd_soc_dai_startup(struct snd_soc_dai *dai, 478 struct snd_pcm_substream *substream) 479{ 480 int ret = 0; 481 482 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 483 return 0; 484 485 if (dai->driver->ops && 486 dai->driver->ops->startup) 487 ret = dai->driver->ops->startup(substream, dai); 488 489 /* mark substream if succeeded */ 490 if (ret == 0) 491 soc_dai_mark_push(dai, substream, startup); 492 493 return soc_dai_ret(dai, ret); 494} 495 496void snd_soc_dai_shutdown(struct snd_soc_dai *dai, 497 struct snd_pcm_substream *substream, 498 int rollback) 499{ 500 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 501 return; 502 503 if (rollback && !soc_dai_mark_match(dai, substream, startup)) 504 return; 505 506 if (dai->driver->ops && 507 dai->driver->ops->shutdown) 508 dai->driver->ops->shutdown(substream, dai); 509 510 /* remove marked substream */ 511 soc_dai_mark_pop(dai, startup); 512} 513 514int snd_soc_dai_compress_new(struct snd_soc_dai *dai, 515 struct snd_soc_pcm_runtime *rtd) 516{ 517 int ret = -ENOTSUPP; 518 if (dai->driver->ops && 519 dai->driver->ops->compress_new) 520 ret = dai->driver->ops->compress_new(rtd); 521 return soc_dai_ret(dai, ret); 522} 523 524/* 525 * snd_soc_dai_stream_valid() - check if a DAI supports the given stream 526 * 527 * Returns true if the DAI supports the indicated stream type. 528 */ 529bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir) 530{ 531 const struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir); 532 533 /* If the codec specifies any channels at all, it supports the stream */ 534 return stream->channels_min; 535} 536 537void snd_soc_dai_action(struct snd_soc_dai *dai, 538 int stream, int action) 539{ 540 /* see snd_soc_dai_stream_active() */ 541 dai->stream[stream].active += action; 542 543 /* see snd_soc_component_active() */ 544 dai->component->active += action; 545} 546EXPORT_SYMBOL_GPL(snd_soc_dai_action); 547 548int snd_soc_dai_active(const struct snd_soc_dai *dai) 549{ 550 int stream, active; 551 552 active = 0; 553 for_each_pcm_streams(stream) 554 active += dai->stream[stream].active; 555 556 return active; 557} 558EXPORT_SYMBOL_GPL(snd_soc_dai_active); 559 560int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) 561{ 562 struct snd_soc_dai *dai; 563 int i; 564 565 for_each_rtd_dais(rtd, i, dai) { 566 if (dai->probed) 567 continue; 568 569 if (dai->driver->ops) { 570 if (dai->driver->ops->probe_order != order) 571 continue; 572 573 if (dai->driver->ops->probe) { 574 int ret = dai->driver->ops->probe(dai); 575 576 if (ret < 0) 577 return soc_dai_ret(dai, ret); 578 } 579 } 580 dai->probed = 1; 581 } 582 583 return 0; 584} 585 586int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order) 587{ 588 struct snd_soc_dai *dai; 589 int i, r, ret = 0; 590 591 for_each_rtd_dais(rtd, i, dai) { 592 if (!dai->probed) 593 continue; 594 595 if (dai->driver->ops) { 596 if (dai->driver->ops->remove_order != order) 597 continue; 598 599 if (dai->driver->ops->remove) { 600 r = dai->driver->ops->remove(dai); 601 if (r < 0) 602 ret = r; /* use last error */ 603 } 604 } 605 dai->probed = 0; 606 } 607 608 return ret; 609} 610 611int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) 612{ 613 struct snd_soc_dai *dai; 614 int i; 615 616 for_each_rtd_dais(rtd, i, dai) { 617 if (dai->driver->ops && 618 dai->driver->ops->pcm_new) { 619 int ret = dai->driver->ops->pcm_new(rtd, dai); 620 if (ret < 0) 621 return soc_dai_ret(dai, ret); 622 } 623 } 624 625 return 0; 626} 627 628int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) 629{ 630 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 631 struct snd_soc_dai *dai; 632 int i, ret; 633 634 for_each_rtd_dais(rtd, i, dai) { 635 ret = snd_soc_dai_prepare(dai, substream); 636 if (ret < 0) 637 return ret; 638 } 639 640 return 0; 641} 642 643static int soc_dai_trigger(struct snd_soc_dai *dai, 644 struct snd_pcm_substream *substream, int cmd) 645{ 646 int ret = 0; 647 648 if (!snd_soc_dai_stream_valid(dai, substream->stream)) 649 return 0; 650 651 if (dai->driver->ops && 652 dai->driver->ops->trigger) 653 ret = dai->driver->ops->trigger(substream, cmd, dai); 654 655 return soc_dai_ret(dai, ret); 656} 657 658int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, 659 int cmd, int rollback) 660{ 661 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 662 struct snd_soc_dai *dai; 663 int i, r, ret = 0; 664 665 switch (cmd) { 666 case SNDRV_PCM_TRIGGER_START: 667 case SNDRV_PCM_TRIGGER_RESUME: 668 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 669 for_each_rtd_dais(rtd, i, dai) { 670 ret = soc_dai_trigger(dai, substream, cmd); 671 if (ret < 0) 672 break; 673 674 if (snd_soc_dai_mute_is_ctrled_at_trigger(dai)) 675 snd_soc_dai_digital_mute(dai, 0, substream->stream); 676 677 soc_dai_mark_push(dai, substream, trigger); 678 } 679 break; 680 case SNDRV_PCM_TRIGGER_STOP: 681 case SNDRV_PCM_TRIGGER_SUSPEND: 682 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 683 for_each_rtd_dais(rtd, i, dai) { 684 if (rollback && !soc_dai_mark_match(dai, substream, trigger)) 685 continue; 686 687 if (snd_soc_dai_mute_is_ctrled_at_trigger(dai)) 688 snd_soc_dai_digital_mute(dai, 1, substream->stream); 689 690 r = soc_dai_trigger(dai, substream, cmd); 691 if (r < 0) 692 ret = r; /* use last ret */ 693 soc_dai_mark_pop(dai, trigger); 694 } 695 } 696 697 return ret; 698} 699 700void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, 701 snd_pcm_sframes_t *cpu_delay, 702 snd_pcm_sframes_t *codec_delay) 703{ 704 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 705 struct snd_soc_dai *dai; 706 int i; 707 708 /* 709 * We're looking for the delay through the full audio path so it needs to 710 * be the maximum of the DAIs doing transmit and the maximum of the DAIs 711 * doing receive (ie, all CPUs and all CODECs) rather than just the maximum 712 * of all DAIs. 713 */ 714 715 /* for CPU */ 716 for_each_rtd_cpu_dais(rtd, i, dai) 717 if (dai->driver->ops && 718 dai->driver->ops->delay) 719 *cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai)); 720 721 /* for Codec */ 722 for_each_rtd_codec_dais(rtd, i, dai) 723 if (dai->driver->ops && 724 dai->driver->ops->delay) 725 *codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai)); 726} 727 728int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, 729 struct snd_compr_stream *cstream) 730{ 731 int ret = 0; 732 733 if (dai->driver->cops && 734 dai->driver->cops->startup) 735 ret = dai->driver->cops->startup(cstream, dai); 736 737 /* mark cstream if succeeded */ 738 if (ret == 0) 739 soc_dai_mark_push(dai, cstream, compr_startup); 740 741 return soc_dai_ret(dai, ret); 742} 743EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup); 744 745void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, 746 struct snd_compr_stream *cstream, 747 int rollback) 748{ 749 if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup)) 750 return; 751 752 if (dai->driver->cops && 753 dai->driver->cops->shutdown) 754 dai->driver->cops->shutdown(cstream, dai); 755 756 /* remove marked cstream */ 757 soc_dai_mark_pop(dai, compr_startup); 758} 759EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); 760 761int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, 762 struct snd_compr_stream *cstream, int cmd) 763{ 764 int ret = 0; 765 766 if (dai->driver->cops && 767 dai->driver->cops->trigger) 768 ret = dai->driver->cops->trigger(cstream, cmd, dai); 769 770 return soc_dai_ret(dai, ret); 771} 772EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger); 773 774int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, 775 struct snd_compr_stream *cstream, 776 struct snd_compr_params *params) 777{ 778 int ret = 0; 779 780 if (dai->driver->cops && 781 dai->driver->cops->set_params) 782 ret = dai->driver->cops->set_params(cstream, params, dai); 783 784 return soc_dai_ret(dai, ret); 785} 786EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params); 787 788int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, 789 struct snd_compr_stream *cstream, 790 struct snd_codec *params) 791{ 792 int ret = 0; 793 794 if (dai->driver->cops && 795 dai->driver->cops->get_params) 796 ret = dai->driver->cops->get_params(cstream, params, dai); 797 798 return soc_dai_ret(dai, ret); 799} 800EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params); 801 802int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, 803 struct snd_compr_stream *cstream, 804 size_t bytes) 805{ 806 int ret = 0; 807 808 if (dai->driver->cops && 809 dai->driver->cops->ack) 810 ret = dai->driver->cops->ack(cstream, bytes, dai); 811 812 return soc_dai_ret(dai, ret); 813} 814EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); 815 816int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, 817 struct snd_compr_stream *cstream, 818 struct snd_compr_tstamp64 *tstamp) 819{ 820 int ret = 0; 821 822 if (dai->driver->cops && 823 dai->driver->cops->pointer) 824 ret = dai->driver->cops->pointer(cstream, tstamp, dai); 825 826 return soc_dai_ret(dai, ret); 827} 828EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer); 829 830int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, 831 struct snd_compr_stream *cstream, 832 struct snd_compr_metadata *metadata) 833{ 834 int ret = 0; 835 836 if (dai->driver->cops && 837 dai->driver->cops->set_metadata) 838 ret = dai->driver->cops->set_metadata(cstream, metadata, dai); 839 840 return soc_dai_ret(dai, ret); 841} 842EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata); 843 844int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, 845 struct snd_compr_stream *cstream, 846 struct snd_compr_metadata *metadata) 847{ 848 int ret = 0; 849 850 if (dai->driver->cops && 851 dai->driver->cops->get_metadata) 852 ret = dai->driver->cops->get_metadata(cstream, metadata, dai); 853 854 return soc_dai_ret(dai, ret); 855} 856EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata);