Lines Matching +full:dma +full:- +full:maxburst
1 // SPDX-License-Identifier: GPL-2.0+
5 // Copyright 2012-2015 Freescale Semiconductor, Inc.
22 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
26 #include "imx-pcm.h"
44 * fsl_sai_dir_is_synced - Check if stream is synced by the opposite stream
58 return !sai->synchronous[dir] && sai->synchronous[adir]; in fsl_sai_dir_is_synced()
65 if (sai->is_pdm_mode) { in fsl_sai_get_pins_state()
68 state = pinctrl_lookup_state(sai->pinctrl, "dsd512"); in fsl_sai_get_pins_state()
72 state = pinctrl_lookup_state(sai->pinctrl, "dsd"); in fsl_sai_get_pins_state()
76 state = pinctrl_lookup_state(sai->pinctrl, "pcm_b2m"); in fsl_sai_get_pins_state()
81 state = pinctrl_lookup_state(sai->pinctrl, "default"); in fsl_sai_get_pins_state()
89 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_isr()
90 struct device *dev = &sai->pdev->dev; in fsl_sai_isr()
102 regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr); in fsl_sai_isr()
129 regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr); in fsl_sai_isr()
133 regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr); in fsl_sai_isr()
160 regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr); in fsl_sai_isr()
172 sai->slots[tx] = slots; in fsl_sai_set_dai_tdm_slot_tx()
173 sai->slot_width[tx] = slot_width; in fsl_sai_set_dai_tdm_slot_tx()
184 sai->slots[tx] = slots; in fsl_sai_set_dai_tdm_slot_rx()
185 sai->slot_width[tx] = slot_width; in fsl_sai_set_dai_tdm_slot_rx()
214 sai->bclk_ratio = ratio; in fsl_sai_set_dai_bclk_ratio()
223 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_set_dai_sysclk_tr()
240 return -EINVAL; in fsl_sai_set_dai_sysclk_tr()
243 regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), in fsl_sai_set_dai_sysclk_tr()
254 fsl_asoc_reparent_pll_clocks(dai->dev, sai->mclk_clk[clk_id], in fsl_sai_set_mclk_rate()
255 sai->pll8k_clk, sai->pll11k_clk, freq); in fsl_sai_set_mclk_rate()
257 ret = clk_set_rate(sai->mclk_clk[clk_id], freq); in fsl_sai_set_mclk_rate()
259 dev_err(dai->dev, "failed to set clock rate (%u): %d\n", freq, ret); in fsl_sai_set_mclk_rate()
274 dev_err(cpu_dai->dev, "Unknown clock id: %d\n", clk_id); in fsl_sai_set_dai_sysclk()
275 return -EINVAL; in fsl_sai_set_dai_sysclk()
278 if (IS_ERR_OR_NULL(sai->mclk_clk[clk_id])) { in fsl_sai_set_dai_sysclk()
279 dev_err(cpu_dai->dev, "Unassigned clock: %d\n", clk_id); in fsl_sai_set_dai_sysclk()
280 return -EINVAL; in fsl_sai_set_dai_sysclk()
283 if (sai->mclk_streams == 0 && freq > 0) { in fsl_sai_set_dai_sysclk()
293 dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret); in fsl_sai_set_dai_sysclk()
299 dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret); in fsl_sai_set_dai_sysclk()
308 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_set_dai_fmt_tr()
311 if (!sai->is_lsb_first) in fsl_sai_set_dai_fmt_tr()
314 sai->is_pdm_mode = false; in fsl_sai_set_dai_fmt_tr()
315 sai->is_dsp_mode[tx] = false; in fsl_sai_set_dai_fmt_tr()
344 sai->is_dsp_mode[tx] = true; in fsl_sai_set_dai_fmt_tr()
352 sai->is_dsp_mode[tx] = true; in fsl_sai_set_dai_fmt_tr()
357 sai->is_pdm_mode = true; in fsl_sai_set_dai_fmt_tr()
362 return -EINVAL; in fsl_sai_set_dai_fmt_tr()
384 return -EINVAL; in fsl_sai_set_dai_fmt_tr()
392 sai->is_consumer_mode[tx] = false; in fsl_sai_set_dai_fmt_tr()
395 sai->is_consumer_mode[tx] = true; in fsl_sai_set_dai_fmt_tr()
399 sai->is_consumer_mode[tx] = false; in fsl_sai_set_dai_fmt_tr()
403 sai->is_consumer_mode[tx] = true; in fsl_sai_set_dai_fmt_tr()
406 return -EINVAL; in fsl_sai_set_dai_fmt_tr()
409 regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), in fsl_sai_set_dai_fmt_tr()
411 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), in fsl_sai_set_dai_fmt_tr()
424 dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret); in fsl_sai_set_dai_fmt()
430 dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret); in fsl_sai_set_dai_fmt()
448 unsigned int reg, ofs = sai->soc_data->reg_offset; in fsl_sai_set_bclk()
454 bool support_1_1_ratio = sai->verid.version >= 0x0301; in fsl_sai_set_bclk()
457 if (sai->is_consumer_mode[tx]) in fsl_sai_set_bclk()
465 id = sai->soc_data->mclk0_is_mclk1 ? 1 : 0; in fsl_sai_set_bclk()
470 clk_rate = clk_get_rate(sai->mclk_clk[id]); in fsl_sai_set_bclk()
482 diff = abs((long)clk_rate - ratio * freq); in fsl_sai_set_bclk()
491 dev_dbg(dai->dev, in fsl_sai_set_bclk()
498 sai->mclk_id[tx] = id; in fsl_sai_set_bclk()
507 dev_err(dai->dev, "failed to derive required %cx rate: %d\n", in fsl_sai_set_bclk()
509 return -EINVAL; in fsl_sai_set_bclk()
512 dev_dbg(dai->dev, "best fit: clock id=%d, div=%d, deviation =%d\n", in fsl_sai_set_bclk()
513 sai->mclk_id[tx], savediv, bestdiff); in fsl_sai_set_bclk()
527 else if (!sai->synchronous[dir]) in fsl_sai_set_bclk()
532 regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_MSEL_MASK, in fsl_sai_set_bclk()
533 FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); in fsl_sai_set_bclk()
536 regmap_update_bits(sai->regmap, reg, in fsl_sai_set_bclk()
540 regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), in fsl_sai_set_bclk()
543 regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), in fsl_sai_set_bclk()
546 regmap_update_bits(sai->regmap, reg, in fsl_sai_set_bclk()
548 savediv / 2 - 1); in fsl_sai_set_bclk()
559 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_hw_params()
560 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; in fsl_sai_hw_params()
563 struct fsl_sai_dl_cfg *dl_cfg = sai->dl_cfg; in fsl_sai_hw_params()
566 int dl_cfg_cnt = sai->dl_cfg_cnt; in fsl_sai_hw_params()
576 if (sai->slot_width[tx]) in fsl_sai_hw_params()
577 slot_width = sai->slot_width[tx]; in fsl_sai_hw_params()
579 if (sai->slots[tx]) in fsl_sai_hw_params()
580 slots = sai->slots[tx]; in fsl_sai_hw_params()
581 else if (sai->bclk_ratio) in fsl_sai_hw_params()
582 slots = sai->bclk_ratio / slot_width; in fsl_sai_hw_params()
590 if (sai->is_pdm_mode) { in fsl_sai_hw_params()
603 dev_err(cpu_dai->dev, "channel not supported\n"); in fsl_sai_hw_params()
604 return -EINVAL; in fsl_sai_hw_params()
607 bclk = params_rate(params) * (sai->bclk_ratio ? sai->bclk_ratio : slots * slot_width); in fsl_sai_hw_params()
609 if (!IS_ERR_OR_NULL(sai->pinctrl)) { in fsl_sai_hw_params()
610 sai->pins_state = fsl_sai_get_pins_state(sai, bclk); in fsl_sai_hw_params()
611 if (!IS_ERR_OR_NULL(sai->pins_state)) { in fsl_sai_hw_params()
612 ret = pinctrl_select_state(sai->pinctrl, sai->pins_state); in fsl_sai_hw_params()
614 dev_err(cpu_dai->dev, "failed to set proper pins state: %d\n", ret); in fsl_sai_hw_params()
620 if (!sai->is_consumer_mode[tx]) { in fsl_sai_hw_params()
626 if (!(sai->mclk_streams & BIT(substream->stream))) { in fsl_sai_hw_params()
627 ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[tx]]); in fsl_sai_hw_params()
631 sai->mclk_streams |= BIT(substream->stream); in fsl_sai_hw_params()
635 if (!sai->is_dsp_mode[tx] && !sai->is_pdm_mode) in fsl_sai_hw_params()
641 if (sai->is_lsb_first || sai->is_pdm_mode) in fsl_sai_hw_params()
644 val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1); in fsl_sai_hw_params()
651 /* Set to output mode to avoid tri-stated data pins */ in fsl_sai_hw_params()
661 if (!sai->is_consumer_mode[tx] && fsl_sai_dir_is_synced(sai, adir)) { in fsl_sai_hw_params()
662 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(!tx, ofs), in fsl_sai_hw_params()
666 regmap_update_bits(sai->regmap, FSL_SAI_xCR5(!tx, ofs), in fsl_sai_hw_params()
673 * - Can't used for singel dataline/FIFO case except the FIFO0 in fsl_sai_hw_params()
674 * - Can't used for multi dataline/FIFO case except the enabled FIFOs in fsl_sai_hw_params()
679 if (hweight8(dl_cfg[dl_cfg_idx].mask[tx]) <= 1 || sai->is_multi_fifo_dma) in fsl_sai_hw_params()
680 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), in fsl_sai_hw_params()
683 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), in fsl_sai_hw_params()
686 dma_params = tx ? &sai->dma_params_tx : &sai->dma_params_rx; in fsl_sai_hw_params()
687 dma_params->addr = sai->res->start + FSL_SAI_xDR0(tx) + in fsl_sai_hw_params()
690 if (sai->is_multi_fifo_dma) { in fsl_sai_hw_params()
691 sai->audio_config[tx].words_per_fifo = min(slots, channels); in fsl_sai_hw_params()
693 sai->audio_config[tx].n_fifos_dst = pins; in fsl_sai_hw_params()
694 sai->audio_config[tx].stride_fifos_dst = dl_cfg[dl_cfg_idx].next_off[tx]; in fsl_sai_hw_params()
696 sai->audio_config[tx].n_fifos_src = pins; in fsl_sai_hw_params()
697 sai->audio_config[tx].stride_fifos_src = dl_cfg[dl_cfg_idx].next_off[tx]; in fsl_sai_hw_params()
699 dma_params->maxburst = sai->audio_config[tx].words_per_fifo * pins; in fsl_sai_hw_params()
700 dma_params->peripheral_config = &sai->audio_config[tx]; in fsl_sai_hw_params()
701 dma_params->peripheral_size = sizeof(sai->audio_config[tx]); in fsl_sai_hw_params()
703 watermark = tx ? (sai->soc_data->fifo_depth - dma_params->maxburst) : in fsl_sai_hw_params()
704 (dma_params->maxburst - 1); in fsl_sai_hw_params()
705 regmap_update_bits(sai->regmap, FSL_SAI_xCR1(tx, ofs), in fsl_sai_hw_params()
706 FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth), in fsl_sai_hw_params()
711 for (i = 0; i < sai->soc_data->pins; i++) { in fsl_sai_hw_params()
712 trce_mask = (1 << (i + 1)) - 1; in fsl_sai_hw_params()
717 regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs), in fsl_sai_hw_params()
730 if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output && in fsl_sai_hw_params()
731 !sai->is_consumer_mode[tx]) in fsl_sai_hw_params()
732 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), in fsl_sai_hw_params()
735 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), in fsl_sai_hw_params()
739 regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs), in fsl_sai_hw_params()
744 if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output && in fsl_sai_hw_params()
745 !sai->is_consumer_mode[tx]) in fsl_sai_hw_params()
746 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), in fsl_sai_hw_params()
749 regmap_write(sai->regmap, FSL_SAI_xMR(tx), in fsl_sai_hw_params()
750 ~0UL - ((1 << min(channels, slots)) - 1)); in fsl_sai_hw_params()
759 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; in fsl_sai_hw_free()
760 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_hw_free()
763 regmap_write(sai->regmap, FSL_SAI_xMR(tx), 0); in fsl_sai_hw_free()
765 regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs), in fsl_sai_hw_free()
768 if (!sai->is_consumer_mode[tx] && in fsl_sai_hw_free()
769 sai->mclk_streams & BIT(substream->stream)) { in fsl_sai_hw_free()
770 clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]); in fsl_sai_hw_free()
771 sai->mclk_streams &= ~BIT(substream->stream); in fsl_sai_hw_free()
779 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_config_disable()
783 if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output) in fsl_sai_config_disable()
788 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), in fsl_sai_config_disable()
794 regmap_read(sai->regmap, FSL_SAI_xCSR(tx, ofs), &xcsr); in fsl_sai_config_disable()
795 } while (--count && xcsr & FSL_SAI_CSR_TERE); in fsl_sai_config_disable()
797 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), in fsl_sai_config_disable()
812 regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR); in fsl_sai_config_disable()
814 regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0); in fsl_sai_config_disable()
821 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_trigger()
823 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; in fsl_sai_trigger()
833 regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC, in fsl_sai_trigger()
834 sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0); in fsl_sai_trigger()
835 regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC, in fsl_sai_trigger()
836 sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0); in fsl_sai_trigger()
846 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), in fsl_sai_trigger()
849 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), in fsl_sai_trigger()
863 regmap_update_bits(sai->regmap, FSL_SAI_xCSR((!tx), ofs), in fsl_sai_trigger()
866 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), in fsl_sai_trigger()
872 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), in fsl_sai_trigger()
874 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), in fsl_sai_trigger()
878 regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr); in fsl_sai_trigger()
898 return -EINVAL; in fsl_sai_trigger()
908 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; in fsl_sai_startup()
913 * tx/rx maxburst in fsl_sai_startup()
915 if (sai->soc_data->use_edma) in fsl_sai_startup()
916 snd_pcm_hw_constraint_step(substream->runtime, 0, in fsl_sai_startup()
918 tx ? sai->dma_params_tx.maxburst : in fsl_sai_startup()
919 sai->dma_params_rx.maxburst); in fsl_sai_startup()
921 ret = snd_pcm_hw_constraint_list(substream->runtime, 0, in fsl_sai_startup()
922 SNDRV_PCM_HW_PARAM_RATE, &sai->constraint_rates); in fsl_sai_startup()
929 struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); in fsl_sai_dai_probe()
930 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_dai_probe()
933 regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); in fsl_sai_dai_probe()
934 regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); in fsl_sai_dai_probe()
936 regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); in fsl_sai_dai_probe()
937 regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); in fsl_sai_dai_probe()
939 regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs), in fsl_sai_dai_probe()
940 FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth), in fsl_sai_dai_probe()
941 sai->soc_data->fifo_depth - sai->dma_params_tx.maxburst); in fsl_sai_dai_probe()
942 regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs), in fsl_sai_dai_probe()
943 FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth), in fsl_sai_dai_probe()
944 sai->dma_params_rx.maxburst - 1); in fsl_sai_dai_probe()
946 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, in fsl_sai_dai_probe()
947 &sai->dma_params_rx); in fsl_sai_dai_probe()
993 struct device *dev = &sai->pdev->dev; in fsl_sai_dai_resume()
996 if (!IS_ERR_OR_NULL(sai->pinctrl) && !IS_ERR_OR_NULL(sai->pins_state)) { in fsl_sai_dai_resume()
997 ret = pinctrl_select_state(sai->pinctrl, sai->pins_state); in fsl_sai_dai_resume()
1009 .name = "sai-tx-rx",
1011 .stream_name = "CPU-Playback",
1020 .stream_name = "CPU-Capture",
1031 .name = "sai-tx",
1033 .stream_name = "SAI-Playback",
1044 .name = "sai-rx",
1046 .stream_name = "SAI-Capture",
1059 .name = "fsl-sai",
1115 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_readable_reg()
1171 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_volatile_reg()
1214 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_writeable_reg()
1261 unsigned char ofs = sai->soc_data->reg_offset; in fsl_sai_check_version()
1268 ret = regmap_read(sai->regmap, FSL_SAI_VERID, &val); in fsl_sai_check_version()
1274 sai->verid.version = val & in fsl_sai_check_version()
1276 sai->verid.version >>= FSL_SAI_VERID_MINOR_SHIFT; in fsl_sai_check_version()
1277 sai->verid.feature = val & FSL_SAI_VERID_FEATURE_MASK; in fsl_sai_check_version()
1279 ret = regmap_read(sai->regmap, FSL_SAI_PARAM, &val); in fsl_sai_check_version()
1286 sai->param.slot_num = 1 << in fsl_sai_check_version()
1290 sai->param.fifo_depth = 1 << in fsl_sai_check_version()
1294 sai->param.dataline = val & FSL_SAI_PARAM_DLN_MASK; in fsl_sai_check_version()
1309 offset = nbidx - fbidx - 1; in fsl_sai_calc_dl_off()
1311 return (offset < 0 || offset >= (FSL_SAI_DL_NUM - 1) ? 0 : offset); in fsl_sai_calc_dl_off()
1328 struct platform_device *pdev = sai->pdev; in fsl_sai_read_dlcfg()
1329 struct device_node *np = pdev->dev.of_node; in fsl_sai_read_dlcfg()
1330 struct device *dev = &pdev->dev; in fsl_sai_read_dlcfg()
1344 return -EINVAL; in fsl_sai_read_dlcfg()
1349 cfg = devm_kzalloc(&pdev->dev, (num_cfg + 1) * sizeof(*cfg), GFP_KERNEL); in fsl_sai_read_dlcfg()
1351 return -ENOMEM; in fsl_sai_read_dlcfg()
1354 soc_dl = BIT(sai->soc_data->pins) - 1; in fsl_sai_read_dlcfg()
1356 cfg[0].pins[0] = sai->soc_data->pins; in fsl_sai_read_dlcfg()
1361 cfg[0].pins[1] = sai->soc_data->pins; in fsl_sai_read_dlcfg()
1374 return -EINVAL; in fsl_sai_read_dlcfg()
1378 return -EINVAL; in fsl_sai_read_dlcfg()
1382 return -EINVAL; in fsl_sai_read_dlcfg()
1386 return -EINVAL; in fsl_sai_read_dlcfg()
1406 sai->dl_cfg = cfg; in fsl_sai_read_dlcfg()
1407 sai->dl_cfg_cnt = num_cfg + 1; in fsl_sai_read_dlcfg()
1416 struct device_node *np = pdev->dev.of_node; in fsl_sai_probe()
1417 struct device *dev = &pdev->dev; in fsl_sai_probe()
1428 return -ENOMEM; in fsl_sai_probe()
1430 sai->pdev = pdev; in fsl_sai_probe()
1431 sai->soc_data = of_device_get_match_data(dev); in fsl_sai_probe()
1433 sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); in fsl_sai_probe()
1435 base = devm_platform_get_and_ioremap_resource(pdev, 0, &sai->res); in fsl_sai_probe()
1439 if (sai->soc_data->reg_offset == 8) { in fsl_sai_probe()
1446 sai->regmap = devm_regmap_init_mmio(dev, base, &fsl_sai_regmap_config); in fsl_sai_probe()
1447 if (IS_ERR(sai->regmap)) { in fsl_sai_probe()
1449 return PTR_ERR(sai->regmap); in fsl_sai_probe()
1452 sai->bus_clk = devm_clk_get(dev, "bus"); in fsl_sai_probe()
1454 if (IS_ERR(sai->bus_clk) && PTR_ERR(sai->bus_clk) != -EPROBE_DEFER) in fsl_sai_probe()
1455 sai->bus_clk = devm_clk_get(dev, "sai"); in fsl_sai_probe()
1456 if (IS_ERR(sai->bus_clk)) { in fsl_sai_probe()
1458 PTR_ERR(sai->bus_clk)); in fsl_sai_probe()
1459 /* -EPROBE_DEFER */ in fsl_sai_probe()
1460 return PTR_ERR(sai->bus_clk); in fsl_sai_probe()
1465 sai->mclk_clk[i] = devm_clk_get(dev, tmp); in fsl_sai_probe()
1466 if (IS_ERR(sai->mclk_clk[i])) { in fsl_sai_probe()
1468 i, PTR_ERR(sai->mclk_clk[i])); in fsl_sai_probe()
1469 sai->mclk_clk[i] = NULL; in fsl_sai_probe()
1473 if (sai->soc_data->mclk0_is_mclk1) in fsl_sai_probe()
1474 sai->mclk_clk[0] = sai->mclk_clk[1]; in fsl_sai_probe()
1476 sai->mclk_clk[0] = sai->bus_clk; in fsl_sai_probe()
1478 fsl_asoc_get_pll_clocks(&pdev->dev, &sai->pll8k_clk, in fsl_sai_probe()
1479 &sai->pll11k_clk); in fsl_sai_probe()
1481 fsl_asoc_constrain_rates(&sai->constraint_rates, in fsl_sai_probe()
1483 sai->pll8k_clk, sai->pll11k_clk, NULL, in fsl_sai_probe()
1484 sai->constraint_rates_list); in fsl_sai_probe()
1488 if (!sai->soc_data->use_edma && !ret && dmas[2] == IMX_DMATYPE_MULTI_SAI) in fsl_sai_probe()
1489 sai->is_multi_fifo_dma = true; in fsl_sai_probe()
1503 np->name, sai); in fsl_sai_probe()
1509 memcpy(&sai->cpu_dai_drv, fsl_sai_dai_template, in fsl_sai_probe()
1513 sai->synchronous[RX] = true; in fsl_sai_probe()
1514 sai->synchronous[TX] = false; in fsl_sai_probe()
1515 sai->cpu_dai_drv[0].symmetric_rate = 1; in fsl_sai_probe()
1516 sai->cpu_dai_drv[0].symmetric_channels = 1; in fsl_sai_probe()
1517 sai->cpu_dai_drv[0].symmetric_sample_bits = 1; in fsl_sai_probe()
1519 if (of_property_read_bool(np, "fsl,sai-synchronous-rx") && in fsl_sai_probe()
1520 of_property_read_bool(np, "fsl,sai-asynchronous")) { in fsl_sai_probe()
1523 return -EINVAL; in fsl_sai_probe()
1526 if (of_property_read_bool(np, "fsl,sai-synchronous-rx")) { in fsl_sai_probe()
1528 sai->synchronous[RX] = false; in fsl_sai_probe()
1529 sai->synchronous[TX] = true; in fsl_sai_probe()
1530 } else if (of_property_read_bool(np, "fsl,sai-asynchronous")) { in fsl_sai_probe()
1532 sai->synchronous[RX] = false; in fsl_sai_probe()
1533 sai->synchronous[TX] = false; in fsl_sai_probe()
1534 sai->cpu_dai_drv[0].symmetric_rate = 0; in fsl_sai_probe()
1535 sai->cpu_dai_drv[0].symmetric_channels = 0; in fsl_sai_probe()
1536 sai->cpu_dai_drv[0].symmetric_sample_bits = 0; in fsl_sai_probe()
1539 sai->mclk_direction_output = of_property_read_bool(np, "fsl,sai-mclk-direction-output"); in fsl_sai_probe()
1541 if (sai->mclk_direction_output && in fsl_sai_probe()
1542 of_device_is_compatible(np, "fsl,imx6ul-sai")) { in fsl_sai_probe()
1543 gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr"); in fsl_sai_probe()
1557 sai->dma_params_rx.addr = sai->res->start + FSL_SAI_RDR0; in fsl_sai_probe()
1558 sai->dma_params_tx.addr = sai->res->start + FSL_SAI_TDR0; in fsl_sai_probe()
1559 sai->dma_params_rx.maxburst = in fsl_sai_probe()
1560 sai->soc_data->max_burst[RX] ? sai->soc_data->max_burst[RX] : FSL_SAI_MAXBURST_RX; in fsl_sai_probe()
1561 sai->dma_params_tx.maxburst = in fsl_sai_probe()
1562 sai->soc_data->max_burst[TX] ? sai->soc_data->max_burst[TX] : FSL_SAI_MAXBURST_TX; in fsl_sai_probe()
1564 sai->pinctrl = devm_pinctrl_get(&pdev->dev); in fsl_sai_probe()
1584 if (sai->mclk_direction_output && in fsl_sai_probe()
1585 sai->soc_data->max_register >= FSL_SAI_MCTL) { in fsl_sai_probe()
1586 regmap_update_bits(sai->regmap, FSL_SAI_MCTL, in fsl_sai_probe()
1591 if (ret < 0 && ret != -ENOSYS) in fsl_sai_probe()
1598 if (sai->soc_data->use_imx_pcm) { in fsl_sai_probe()
1601 dev_err_probe(dev, ret, "PCM DMA init failed\n"); in fsl_sai_probe()
1603 dev_err(dev, "Error: You must enable the imx-pcm-dma support!\n"); in fsl_sai_probe()
1615 sai->cpu_dai_drv, ARRAY_SIZE(fsl_sai_dai_template)); in fsl_sai_probe()
1632 pm_runtime_disable(&pdev->dev); in fsl_sai_remove()
1633 if (!pm_runtime_status_suspended(&pdev->dev)) in fsl_sai_remove()
1634 fsl_sai_runtime_suspend(&pdev->dev); in fsl_sai_remove()
1762 { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data },
1763 { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data },
1764 { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data },
1765 { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data },
1766 { .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data },
1767 { .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data },
1768 { .compatible = "fsl,imx8mm-sai", .data = &fsl_sai_imx8mm_data },
1769 { .compatible = "fsl,imx8mp-sai", .data = &fsl_sai_imx8mp_data },
1770 { .compatible = "fsl,imx8ulp-sai", .data = &fsl_sai_imx8ulp_data },
1771 { .compatible = "fsl,imx8mn-sai", .data = &fsl_sai_imx8mn_data },
1772 { .compatible = "fsl,imx93-sai", .data = &fsl_sai_imx93_data },
1773 { .compatible = "fsl,imx95-sai", .data = &fsl_sai_imx95_data },
1782 if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) in fsl_sai_runtime_suspend()
1783 clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]); in fsl_sai_runtime_suspend()
1785 if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) in fsl_sai_runtime_suspend()
1786 clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]); in fsl_sai_runtime_suspend()
1788 clk_disable_unprepare(sai->bus_clk); in fsl_sai_runtime_suspend()
1790 if (sai->soc_data->flags & PMQOS_CPU_LATENCY) in fsl_sai_runtime_suspend()
1791 cpu_latency_qos_remove_request(&sai->pm_qos_req); in fsl_sai_runtime_suspend()
1793 regcache_cache_only(sai->regmap, true); in fsl_sai_runtime_suspend()
1801 unsigned int ofs = sai->soc_data->reg_offset; in fsl_sai_runtime_resume()
1804 ret = clk_prepare_enable(sai->bus_clk); in fsl_sai_runtime_resume()
1810 if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) { in fsl_sai_runtime_resume()
1811 ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]); in fsl_sai_runtime_resume()
1816 if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) { in fsl_sai_runtime_resume()
1817 ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]); in fsl_sai_runtime_resume()
1822 if (sai->soc_data->flags & PMQOS_CPU_LATENCY) in fsl_sai_runtime_resume()
1823 cpu_latency_qos_add_request(&sai->pm_qos_req, 0); in fsl_sai_runtime_resume()
1825 regcache_cache_only(sai->regmap, false); in fsl_sai_runtime_resume()
1826 regcache_mark_dirty(sai->regmap); in fsl_sai_runtime_resume()
1827 regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); in fsl_sai_runtime_resume()
1828 regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); in fsl_sai_runtime_resume()
1830 regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); in fsl_sai_runtime_resume()
1831 regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); in fsl_sai_runtime_resume()
1833 ret = regcache_sync(sai->regmap); in fsl_sai_runtime_resume()
1837 if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output) in fsl_sai_runtime_resume()
1838 regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), in fsl_sai_runtime_resume()
1844 if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) in fsl_sai_runtime_resume()
1845 clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]); in fsl_sai_runtime_resume()
1847 if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) in fsl_sai_runtime_resume()
1848 clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]); in fsl_sai_runtime_resume()
1850 clk_disable_unprepare(sai->bus_clk); in fsl_sai_runtime_resume()
1864 .name = "fsl-sai",
1873 MODULE_ALIAS("platform:fsl-sai");