Lines Matching +full:dai +full:- +full:format
1 // SPDX-License-Identifier: GPL-2.0
10 #include <linux/dma-mapping.h>
49 struct snd_card *card = rtd->card->snd_card; in qmc_audio_pcm_construct()
52 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); in qmc_audio_pcm_construct()
56 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, in qmc_audio_pcm_construct()
65 struct snd_pcm_runtime *runtime = substream->runtime; in qmc_audio_pcm_hw_params()
66 struct qmc_dai_prtd *prtd = substream->runtime->private_data; in qmc_audio_pcm_hw_params()
68 prtd->dma_buffer_start = runtime->dma_addr; in qmc_audio_pcm_hw_params()
69 prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params); in qmc_audio_pcm_hw_params()
70 prtd->period_size = params_period_bytes(params); in qmc_audio_pcm_hw_params()
71 prtd->period_ptr_submitted = prtd->dma_buffer_start; in qmc_audio_pcm_hw_params()
72 prtd->period_ptr_ended = prtd->dma_buffer_start; in qmc_audio_pcm_hw_params()
73 prtd->substream = substream; in qmc_audio_pcm_hw_params()
83 prtd->period_ptr_ended += prtd->period_size; in qmc_audio_pcm_write_complete()
84 if (prtd->period_ptr_ended >= prtd->dma_buffer_end) in qmc_audio_pcm_write_complete()
85 prtd->period_ptr_ended = prtd->dma_buffer_start; in qmc_audio_pcm_write_complete()
87 prtd->period_ptr_submitted += prtd->period_size; in qmc_audio_pcm_write_complete()
88 if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) in qmc_audio_pcm_write_complete()
89 prtd->period_ptr_submitted = prtd->dma_buffer_start; in qmc_audio_pcm_write_complete()
91 ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, in qmc_audio_pcm_write_complete()
92 prtd->period_ptr_submitted, prtd->period_size, in qmc_audio_pcm_write_complete()
95 dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", in qmc_audio_pcm_write_complete()
99 snd_pcm_period_elapsed(prtd->substream); in qmc_audio_pcm_write_complete()
107 if (length != prtd->period_size) { in qmc_audio_pcm_read_complete()
108 dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", in qmc_audio_pcm_read_complete()
109 length, prtd->period_size); in qmc_audio_pcm_read_complete()
112 prtd->period_ptr_ended += prtd->period_size; in qmc_audio_pcm_read_complete()
113 if (prtd->period_ptr_ended >= prtd->dma_buffer_end) in qmc_audio_pcm_read_complete()
114 prtd->period_ptr_ended = prtd->dma_buffer_start; in qmc_audio_pcm_read_complete()
116 prtd->period_ptr_submitted += prtd->period_size; in qmc_audio_pcm_read_complete()
117 if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) in qmc_audio_pcm_read_complete()
118 prtd->period_ptr_submitted = prtd->dma_buffer_start; in qmc_audio_pcm_read_complete()
120 ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, in qmc_audio_pcm_read_complete()
121 prtd->period_ptr_submitted, prtd->period_size, in qmc_audio_pcm_read_complete()
124 dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", in qmc_audio_pcm_read_complete()
128 snd_pcm_period_elapsed(prtd->substream); in qmc_audio_pcm_read_complete()
134 struct qmc_dai_prtd *prtd = substream->runtime->private_data; in qmc_audio_pcm_trigger()
137 if (!prtd->qmc_dai) { in qmc_audio_pcm_trigger()
138 dev_err(component->dev, "qmc_dai is not set\n"); in qmc_audio_pcm_trigger()
139 return -EINVAL; in qmc_audio_pcm_trigger()
144 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in qmc_audio_pcm_trigger()
146 ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, in qmc_audio_pcm_trigger()
147 prtd->period_ptr_submitted, prtd->period_size, in qmc_audio_pcm_trigger()
150 dev_err(component->dev, "write_submit failed %d\n", in qmc_audio_pcm_trigger()
156 prtd->period_ptr_submitted += prtd->period_size; in qmc_audio_pcm_trigger()
157 if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) in qmc_audio_pcm_trigger()
158 prtd->period_ptr_submitted = prtd->dma_buffer_start; in qmc_audio_pcm_trigger()
161 ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, in qmc_audio_pcm_trigger()
162 prtd->period_ptr_submitted, prtd->period_size, in qmc_audio_pcm_trigger()
165 dev_err(component->dev, "write_submit failed %d\n", in qmc_audio_pcm_trigger()
171 ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, in qmc_audio_pcm_trigger()
172 prtd->period_ptr_submitted, prtd->period_size, in qmc_audio_pcm_trigger()
175 dev_err(component->dev, "read_submit failed %d\n", in qmc_audio_pcm_trigger()
181 prtd->period_ptr_submitted += prtd->period_size; in qmc_audio_pcm_trigger()
182 if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) in qmc_audio_pcm_trigger()
183 prtd->period_ptr_submitted = prtd->dma_buffer_start; in qmc_audio_pcm_trigger()
186 ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, in qmc_audio_pcm_trigger()
187 prtd->period_ptr_submitted, prtd->period_size, in qmc_audio_pcm_trigger()
190 dev_err(component->dev, "write_submit failed %d\n", in qmc_audio_pcm_trigger()
207 return -EINVAL; in qmc_audio_pcm_trigger()
216 struct qmc_dai_prtd *prtd = substream->runtime->private_data; in qmc_audio_pcm_pointer()
218 return bytes_to_frames(substream->runtime, in qmc_audio_pcm_pointer()
219 prtd->period_ptr_ended - prtd->dma_buffer_start); in qmc_audio_pcm_pointer()
226 struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev); in qmc_audio_of_xlate_dai_name()
228 int id = args->args[0]; in qmc_audio_of_xlate_dai_name()
231 for (i = 0; i < qmc_audio->num_dais; i++) { in qmc_audio_of_xlate_dai_name()
232 dai_driver = qmc_audio->dai_drivers + i; in qmc_audio_of_xlate_dai_name()
233 if (dai_driver->id == id) { in qmc_audio_of_xlate_dai_name()
234 *dai_name = dai_driver->name; in qmc_audio_of_xlate_dai_name()
239 return -EINVAL; in qmc_audio_of_xlate_dai_name()
257 struct snd_pcm_runtime *runtime = substream->runtime; in qmc_audio_pcm_open()
270 return -ENOMEM; in qmc_audio_pcm_open()
272 runtime->private_data = prtd; in qmc_audio_pcm_open()
280 struct qmc_dai_prtd *prtd = substream->runtime->private_data; in qmc_audio_pcm_close()
296 static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai) in qmc_dai_get_index() argument
298 struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); in qmc_dai_get_index()
300 return dai->driver - qmc_audio->dai_drivers; in qmc_dai_get_index()
303 static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai) in qmc_dai_get_data() argument
305 struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai); in qmc_dai_get_data()
308 index = qmc_dai_get_index(dai); in qmc_dai_get_data()
309 if (index > qmc_audio->num_dais) in qmc_dai_get_data()
312 return qmc_audio->dais + index; in qmc_dai_get_data()
316 * The constraints for format/channel is to match with the number of 8bit
317 * time-slots available.
324 snd_pcm_format_t format = params_format(params); in qmc_dai_hw_rule_channels_by_format() local
327 switch (snd_pcm_format_physical_width(format)) { in qmc_dai_hw_rule_channels_by_format()
341 dev_err(qmc_dai->dev, "format physical width %u not supported\n", in qmc_dai_hw_rule_channels_by_format()
342 snd_pcm_format_physical_width(format)); in qmc_dai_hw_rule_channels_by_format()
343 return -EINVAL; in qmc_dai_hw_rule_channels_by_format()
354 struct qmc_dai *qmc_dai = rule->private; in qmc_dai_hw_rule_playback_channels_by_format()
356 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts); in qmc_dai_hw_rule_playback_channels_by_format()
363 struct qmc_dai *qmc_dai = rule->private; in qmc_dai_hw_rule_capture_channels_by_format()
365 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts); in qmc_dai_hw_rule_capture_channels_by_format()
375 snd_pcm_format_t format; in qmc_dai_hw_rule_format_by_channels() local
379 dev_err(qmc_dai->dev, "channels %u not supported\n", in qmc_dai_hw_rule_format_by_channels()
381 return -EINVAL; in qmc_dai_hw_rule_format_by_channels()
387 pcm_for_each_format(format) { in qmc_dai_hw_rule_format_by_channels()
388 if (snd_mask_test_format(f_old, format)) { in qmc_dai_hw_rule_format_by_channels()
389 if (snd_pcm_format_physical_width(format) <= slot_width) in qmc_dai_hw_rule_format_by_channels()
390 snd_mask_set_format(&f_new, format); in qmc_dai_hw_rule_format_by_channels()
401 struct qmc_dai *qmc_dai = rule->private; in qmc_dai_hw_rule_playback_format_by_channels()
403 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts); in qmc_dai_hw_rule_playback_format_by_channels()
410 struct qmc_dai *qmc_dai = rule->private; in qmc_dai_hw_rule_capture_format_by_channels()
412 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts); in qmc_dai_hw_rule_capture_format_by_channels()
416 struct snd_soc_dai *dai) in qmc_dai_startup() argument
418 struct qmc_dai_prtd *prtd = substream->runtime->private_data; in qmc_dai_startup()
425 qmc_dai = qmc_dai_get_data(dai); in qmc_dai_startup()
427 dev_err(dai->dev, "Invalid dai\n"); in qmc_dai_startup()
428 return -EINVAL; in qmc_dai_startup()
431 prtd->qmc_dai = qmc_dai; in qmc_dai_startup()
433 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { in qmc_dai_startup()
436 frame_bits = qmc_dai->nb_rx_ts * 8; in qmc_dai_startup()
440 frame_bits = qmc_dai->nb_tx_ts * 8; in qmc_dai_startup()
443 ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, in qmc_dai_startup()
445 SNDRV_PCM_HW_PARAM_FORMAT, -1); in qmc_dai_startup()
447 dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); in qmc_dai_startup()
451 ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, in qmc_dai_startup()
453 SNDRV_PCM_HW_PARAM_CHANNELS, -1); in qmc_dai_startup()
455 dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); in qmc_dai_startup()
459 ret = snd_pcm_hw_constraint_single(substream->runtime, in qmc_dai_startup()
463 dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); in qmc_dai_startup()
472 struct snd_soc_dai *dai) in qmc_dai_hw_params() argument
478 qmc_dai = qmc_dai_get_data(dai); in qmc_dai_hw_params()
480 dev_err(dai->dev, "Invalid dai\n"); in qmc_dai_hw_params()
481 return -EINVAL; in qmc_dai_hw_params()
484 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { in qmc_dai_hw_params()
487 ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param); in qmc_dai_hw_params()
489 dev_err(dai->dev, "set param failed %d\n", in qmc_dai_hw_params()
499 struct snd_soc_dai *dai) in qmc_dai_trigger() argument
505 qmc_dai = qmc_dai_get_data(dai); in qmc_dai_trigger()
507 dev_err(dai->dev, "Invalid dai\n"); in qmc_dai_trigger()
508 return -EINVAL; in qmc_dai_trigger()
511 direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? in qmc_dai_trigger()
518 ret = qmc_chan_start(qmc_dai->qmc_chan, direction); in qmc_dai_trigger()
524 ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); in qmc_dai_trigger()
527 ret = qmc_chan_reset(qmc_dai->qmc_chan, direction); in qmc_dai_trigger()
534 ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); in qmc_dai_trigger()
540 return -EINVAL; in qmc_dai_trigger()
556 snd_pcm_format_t format; in qmc_audio_formats() local
564 pcm_for_each_format(format) { in qmc_audio_formats()
566 * Support format other than little-endian (ie big-endian or in qmc_audio_formats()
569 if (snd_pcm_format_little_endian(format) == 1) in qmc_audio_formats()
573 format_width = snd_pcm_format_physical_width(format); in qmc_audio_formats()
584 formats_mask |= pcm_format_to_bits(format); in qmc_audio_formats()
596 qmc_dai->dev = qmc_audio->dev; in qmc_audio_dai_parse()
600 dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np); in qmc_audio_dai_parse()
603 qmc_dai->id = val; in qmc_audio_dai_parse()
605 qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d", in qmc_audio_dai_parse()
606 np->parent->name, qmc_dai->id); in qmc_audio_dai_parse()
607 if (!qmc_dai->name) in qmc_audio_dai_parse()
608 return -ENOMEM; in qmc_audio_dai_parse()
610 qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, in qmc_audio_dai_parse()
611 "fsl,qmc-chan"); in qmc_audio_dai_parse()
612 if (IS_ERR(qmc_dai->qmc_chan)) { in qmc_audio_dai_parse()
613 ret = PTR_ERR(qmc_dai->qmc_chan); in qmc_audio_dai_parse()
614 return dev_err_probe(qmc_audio->dev, ret, in qmc_audio_dai_parse()
615 "dai %d get QMC channel failed\n", qmc_dai->id); in qmc_audio_dai_parse()
618 qmc_soc_dai_driver->id = qmc_dai->id; in qmc_audio_dai_parse()
619 qmc_soc_dai_driver->name = qmc_dai->name; in qmc_audio_dai_parse()
621 ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info); in qmc_audio_dai_parse()
623 dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", in qmc_audio_dai_parse()
624 qmc_dai->id, ret); in qmc_audio_dai_parse()
627 dev_info(qmc_audio->dev, "dai %d QMC channel mode %d, nb_tx_ts %u, nb_rx_ts %u\n", in qmc_audio_dai_parse()
628 qmc_dai->id, info.mode, info.nb_tx_ts, info.nb_rx_ts); in qmc_audio_dai_parse()
631 dev_err(qmc_audio->dev, "dai %d QMC chan mode %d is not QMC_TRANSPARENT\n", in qmc_audio_dai_parse()
632 qmc_dai->id, info.mode); in qmc_audio_dai_parse()
633 return -EINVAL; in qmc_audio_dai_parse()
635 qmc_dai->nb_tx_ts = info.nb_tx_ts; in qmc_audio_dai_parse()
636 qmc_dai->nb_rx_ts = info.nb_rx_ts; in qmc_audio_dai_parse()
638 qmc_soc_dai_driver->playback.channels_min = 0; in qmc_audio_dai_parse()
639 qmc_soc_dai_driver->playback.channels_max = 0; in qmc_audio_dai_parse()
640 if (qmc_dai->nb_tx_ts) { in qmc_audio_dai_parse()
641 qmc_soc_dai_driver->playback.channels_min = 1; in qmc_audio_dai_parse()
642 qmc_soc_dai_driver->playback.channels_max = qmc_dai->nb_tx_ts; in qmc_audio_dai_parse()
644 qmc_soc_dai_driver->playback.formats = qmc_audio_formats(qmc_dai->nb_tx_ts); in qmc_audio_dai_parse()
646 qmc_soc_dai_driver->capture.channels_min = 0; in qmc_audio_dai_parse()
647 qmc_soc_dai_driver->capture.channels_max = 0; in qmc_audio_dai_parse()
648 if (qmc_dai->nb_rx_ts) { in qmc_audio_dai_parse()
649 qmc_soc_dai_driver->capture.channels_min = 1; in qmc_audio_dai_parse()
650 qmc_soc_dai_driver->capture.channels_max = qmc_dai->nb_rx_ts; in qmc_audio_dai_parse()
652 qmc_soc_dai_driver->capture.formats = qmc_audio_formats(qmc_dai->nb_rx_ts); in qmc_audio_dai_parse()
654 qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(info.tx_fs_rate); in qmc_audio_dai_parse()
655 qmc_soc_dai_driver->playback.rate_min = info.tx_fs_rate; in qmc_audio_dai_parse()
656 qmc_soc_dai_driver->playback.rate_max = info.tx_fs_rate; in qmc_audio_dai_parse()
657 qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(info.rx_fs_rate); in qmc_audio_dai_parse()
658 qmc_soc_dai_driver->capture.rate_min = info.rx_fs_rate; in qmc_audio_dai_parse()
659 qmc_soc_dai_driver->capture.rate_max = info.rx_fs_rate; in qmc_audio_dai_parse()
661 qmc_soc_dai_driver->ops = &qmc_dai_ops; in qmc_audio_dai_parse()
668 struct device_node *np = pdev->dev.of_node; in qmc_audio_probe()
674 qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL); in qmc_audio_probe()
676 return -ENOMEM; in qmc_audio_probe()
678 qmc_audio->dev = &pdev->dev; in qmc_audio_probe()
680 qmc_audio->num_dais = of_get_available_child_count(np); in qmc_audio_probe()
681 if (qmc_audio->num_dais) { in qmc_audio_probe()
682 qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, in qmc_audio_probe()
683 sizeof(*qmc_audio->dais), in qmc_audio_probe()
685 if (!qmc_audio->dais) in qmc_audio_probe()
686 return -ENOMEM; in qmc_audio_probe()
688 qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais, in qmc_audio_probe()
689 sizeof(*qmc_audio->dai_drivers), in qmc_audio_probe()
691 if (!qmc_audio->dai_drivers) in qmc_audio_probe()
692 return -ENOMEM; in qmc_audio_probe()
698 qmc_audio->dais + i, in qmc_audio_probe()
699 qmc_audio->dai_drivers + i); in qmc_audio_probe()
710 ret = devm_snd_soc_register_component(qmc_audio->dev, in qmc_audio_probe()
712 qmc_audio->dai_drivers, in qmc_audio_probe()
713 qmc_audio->num_dais); in qmc_audio_probe()
721 { .compatible = "fsl,qmc-audio" },
728 .name = "fsl-qmc-audio",