Lines Matching +full:pcm +full:- +full:sync +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
10 #include <linux/clk-provider.h>
41 #define STM_SAI_IS_PLAYBACK(ip) ((ip)->dir == SNDRV_PCM_STREAM_PLAYBACK)
42 #define STM_SAI_IS_CAPTURE(ip) ((ip)->dir == SNDRV_PCM_STREAM_CAPTURE)
47 #define STM_SAI_IS_SUB_A(x) ((x)->id == STM_SAI_A_ID)
53 #define STM_SAI_PROTOCOL_IS_SPDIF(ip) ((ip)->spdif)
54 #define STM_SAI_HAS_SPDIF(x) ((x)->pdata->conf.has_spdif_pdm)
55 #define STM_SAI_HAS_PDM(x) ((x)->pdata->conf.has_spdif_pdm)
56 #define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4((x)->pdata))
68 * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
75 * @substream: PCM substream data pointer
82 * @id: SAI sub block id corresponding to sub-block A or B
84 * @master: SAI block mode flag. (true=master, false=slave) set at init
85 * @spdif: SAI S/PDIF iec60958 mode flag. set at init
88 * @sync: SAI block synchronization mode. (none, internal or external)
89 * @synco: SAI block ext sync source (provider setting). (none, sub-block A/B)
90 * @synci: SAI block ext sync source (client setting). (SAI sync provider index)
95 * @data_size: PCM data width. corresponds to PCM substream width.
123 int sync;
201 ret = clk_enable(sai->pdata->pclk);
205 ret = regmap_update_bits(sai->regmap, reg, mask, val);
207 clk_disable(sai->pdata->pclk);
218 ret = clk_enable(sai->pdata->pclk);
222 ret = regmap_write_bits(sai->regmap, reg, mask, val);
224 clk_disable(sai->pdata->pclk);
234 ret = clk_enable(sai->pdata->pclk);
238 ret = regmap_read(sai->regmap, reg, val);
240 clk_disable(sai->pdata->pclk);
272 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
273 uinfo->count = 1;
283 mutex_lock(&sai->ctrl_lock);
284 memcpy(uctl->value.iec958.status, sai->iec958.status, 4);
285 mutex_unlock(&sai->ctrl_lock);
295 mutex_lock(&sai->ctrl_lock);
296 memcpy(sai->iec958.status, uctl->value.iec958.status, 4);
297 mutex_unlock(&sai->ctrl_lock);
325 int version = sai->pdata->conf.version;
330 dev_err(&sai->pdev->dev, "Divider %d out of range\n", div);
331 return -EINVAL;
333 dev_dbg(&sai->pdev->dev, "SAI divider %d\n", div);
336 dev_dbg(&sai->pdev->dev,
346 int version = sai->pdata->conf.version;
350 dev_err(&sai->pdev->dev, "Divider %d out of range\n", div);
351 return -EINVAL;
358 dev_err(&sai->pdev->dev, "Failed to update CR1 register\n");
372 dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate)));
384 struct platform_device *pdev = sai->pdev;
385 struct clk *parent_clk = sai->pdata->clk_x8k;
389 parent_clk = sai->pdata->clk_x11k;
391 ret = clk_set_parent(sai->sai_ck, parent_clk);
393 dev_err(&pdev->dev, " Error %d setting sai_ck parent clock. %s",
394 ret, ret == -EBUSY ?
402 if (sai->sai_ck_used) {
403 sai->sai_ck_used = false;
404 clk_rate_exclusive_put(sai->sai_ck);
411 struct platform_device *pdev = sai->pdev;
417 * - mclk on or spdif:
418 * f_sai_ck = MCKDIV * mclk-fs * fs
419 * Here typical 256 ratio is assumed for mclk-fs
420 * - mclk off:
432 if (!sai->sai_mclk && !STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
433 sai_ck_min_rate = rate * sai->fs_length;
434 sai_ck_max_rate /= DIV_ROUND_CLOSEST(256, roundup_pow_of_two(sai->fs_length));
438 * Request exclusivity, as the clock is shared by SAI sub-blocks and by
442 clk_rate_exclusive_get(sai->sai_ck);
443 sai->sai_ck_used = true;
449 sai_curr_rate = clk_get_rate(sai->sai_ck);
450 dev_dbg(&pdev->dev, "kernel clock rate: min [%u], max [%u], current [%u]",
465 sai_new_rate = clk_round_rate(sai->sai_ck, sai_ck_rate);
467 ret = clk_set_rate(sai->sai_ck, sai_ck_rate);
469 dev_err(&pdev->dev, "Error %d setting sai_ck rate. %s",
470 ret, ret == -EBUSY ?
484 dev_err(&pdev->dev, "Failed to find an accurate rate");
489 return -EINVAL;
496 struct stm32_sai_sub_data *sai = mclk->sai_data;
499 div = stm32_sai_get_clk_div(sai, req->best_parent_rate, req->rate);
501 return -EINVAL;
503 mclk->freq = req->best_parent_rate / div;
505 req->rate = mclk->freq;
515 return mclk->freq;
522 struct stm32_sai_sub_data *sai = mclk->sai_data;
533 mclk->freq = rate;
541 struct stm32_sai_sub_data *sai = mclk->sai_data;
543 dev_dbg(&sai->pdev->dev, "Enable master clock\n");
552 struct stm32_sai_sub_data *sai = mclk->sai_data;
554 dev_dbg(&sai->pdev->dev, "Disable master clock\n");
571 struct device *dev = &sai->pdev->dev;
572 const char *pname = __clk_get_name(sai->sai_ck);
578 return -ENOMEM;
583 return -ENOMEM;
590 while (*s && *s != '_' && (i < (SAI_MCLK_NAME_LEN - 7))) {
596 mclk->hw.init = CLK_HW_INIT(mclk_name, pname, &mclk_ops, 0);
597 mclk->sai_data = sai;
598 hw = &mclk->hw;
601 ret = devm_clk_hw_register(&sai->pdev->dev, hw);
606 sai->sai_mclk = hw->clk;
615 struct platform_device *pdev = sai->pdev;
629 if (!sai->substream) {
630 dev_err(&pdev->dev, "Device stopped. Spurious IRQ 0x%x\n", sr);
635 dev_err(&pdev->dev, "IRQ %s\n",
641 dev_dbg(&pdev->dev, "IRQ mute detected\n");
644 dev_err(&pdev->dev, "IRQ wrong clock configuration\n");
649 dev_err(&pdev->dev, "IRQ Codec not ready\n");
652 dev_err(&pdev->dev, "IRQ Anticipated frame synchro\n");
657 dev_err(&pdev->dev, "IRQ Late frame synchro\n");
661 spin_lock(&sai->irq_lock);
662 if (status != SNDRV_PCM_STATE_RUNNING && sai->substream)
663 snd_pcm_stop_xrun(sai->substream);
664 spin_unlock(&sai->irq_lock);
680 if (!snd_soc_card_is_instantiated(cpu_dai->component->card))
683 if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) {
693 if (sai->mclk_rate) {
694 clk_rate_exclusive_put(sai->sai_mclk);
695 sai->mclk_rate = 0;
698 if (sai->put_sai_ck_rate)
699 sai->put_sai_ck_rate(sai);
705 ret = sai->set_sai_ck_rate(sai, freq);
709 ret = clk_set_rate_exclusive(sai->sai_mclk, freq);
711 dev_err(cpu_dai->dev,
712 ret == -EBUSY ?
718 dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
719 sai->mclk_rate = freq;
732 dev_warn(cpu_dai->dev, "Slot setting relevant only for TDM\n");
736 dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n",
752 SAI_XSLOTR_NBSLOT_SET(slots - 1);
757 sai->slot_mask = tx_mask;
762 sai->slot_mask = rx_mask;
770 sai->slot_width = slot_width;
771 sai->slots = slots;
783 dev_dbg(cpu_dai->dev, "fmt %x\n", fmt);
818 dev_err(cpu_dai->dev, "Unsupported protocol %#x\n",
820 return -EINVAL;
843 dev_err(cpu_dai->dev, "Unsupported strobing %#x\n",
845 return -EINVAL;
857 sai->master = false;
860 sai->master = true;
863 dev_err(cpu_dai->dev, "Unsupported mode %#x\n",
865 return -EINVAL;
868 /* Set slave mode if sub-block is synchronized with another SAI */
869 if (sai->sync) {
870 dev_dbg(cpu_dai->dev, "Synchronized SAI configured as slave\n");
872 sai->master = false;
880 dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
884 sai->fmt = fmt;
896 spin_lock_irqsave(&sai->irq_lock, flags);
897 sai->substream = substream;
898 spin_unlock_irqrestore(&sai->irq_lock, flags);
901 snd_pcm_hw_constraint_mask64(substream->runtime,
904 snd_pcm_hw_constraint_single(substream->runtime,
908 ret = clk_prepare_enable(sai->sai_ck);
910 dev_err(cpu_dai->dev, "Failed to enable clock: %d\n", ret);
925 if (sai->master)
955 sai->spdif_frm_cnt = 0;
959 /* Mode, data format and channel config */
972 dev_err(cpu_dai->dev, "Data format not supported\n");
973 return -EINVAL;
977 if ((sai->slots == 2) && (params_channels(params) == 1))
982 dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
1002 sai->slot_width = sai->data_size;
1004 if (sai->slot_width < sai->data_size) {
1005 dev_err(cpu_dai->dev,
1007 sai->data_size);
1008 return -EINVAL;
1012 if (!sai->slots)
1013 sai->slots = 2;
1018 SAI_XSLOTR_NBSLOT_SET((sai->slots - 1)));
1022 sai->slot_mask = (1 << sai->slots) - 1;
1025 SAI_XSLOTR_SLOTEN_SET(sai->slot_mask));
1028 dev_dbg(cpu_dai->dev, "Slots %d, slot width %d\n",
1029 sai->slots, sai->slot_width);
1040 format = sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
1041 sai->fs_length = sai->slot_width * sai->slots;
1043 fs_active = sai->fs_length / 2;
1048 frcr = SAI_XFRCR_FRL_SET((sai->fs_length - 1));
1049 frcr |= SAI_XFRCR_FSALL_SET((fs_active - 1));
1052 dev_dbg(cpu_dai->dev, "Frame length %d, frame active %d\n",
1053 sai->fs_length, fs_active);
1057 if ((sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_LSB) {
1058 offset = sai->slot_width - sai->data_size;
1068 unsigned char *cs = sai->iec958.status;
1083 mutex_lock(&sai->ctrl_lock);
1084 switch (runtime->rate) {
1086 sai->iec958.status[3] = IEC958_AES3_CON_FS_22050;
1089 sai->iec958.status[3] = IEC958_AES3_CON_FS_44100;
1092 sai->iec958.status[3] = IEC958_AES3_CON_FS_88200;
1095 sai->iec958.status[3] = IEC958_AES3_CON_FS_176400;
1098 sai->iec958.status[3] = IEC958_AES3_CON_FS_24000;
1101 sai->iec958.status[3] = IEC958_AES3_CON_FS_48000;
1104 sai->iec958.status[3] = IEC958_AES3_CON_FS_96000;
1107 sai->iec958.status[3] = IEC958_AES3_CON_FS_192000;
1110 sai->iec958.status[3] = IEC958_AES3_CON_FS_32000;
1113 sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID;
1116 mutex_unlock(&sai->ctrl_lock);
1128 if (!sai->sai_mclk) {
1129 ret = sai->set_sai_ck_rate(sai, rate);
1133 sai_clk_rate = clk_get_rate(sai->sai_ck);
1135 if (STM_SAI_IS_F4(sai->pdata)) {
1143 if (!sai->mclk_rate)
1146 if (2 * sai_clk_rate >= 3 * sai->mclk_rate) {
1148 2 * sai->mclk_rate);
1154 * TDM mode :
1168 if (sai->mclk_rate) {
1169 mclk_ratio = sai->mclk_rate / rate;
1173 dev_err(cpu_dai->dev,
1176 return -EINVAL;
1184 sai->mclk_rate);
1188 /* mclk-fs not set, master clock not active */
1189 den = sai->fs_length * params_rate(params);
1208 sai->data_size = params_width(params);
1212 substream->runtime->rate = params_rate(params);
1213 stm32_sai_set_iec958_status(sai, substream->runtime);
1225 if (sai->master)
1241 dev_dbg(cpu_dai->dev, "Enable DMA and SAI\n");
1250 dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
1255 dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n");
1268 dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
1271 sai->spdif_frm_cnt = 0;
1274 return -EINVAL;
1288 clk_disable_unprepare(sai->sai_ck);
1292 * - Master clock is not used. Kernel clock won't be released trough sysclk
1293 * - Put handler is defined. Involve that clock is managed exclusively
1295 if (!sai->sai_mclk && sai->put_sai_ck_rate)
1296 sai->put_sai_ck_rate(sai);
1298 spin_lock_irqsave(&sai->irq_lock, flags);
1299 sai->substream = NULL;
1300 spin_unlock_irqrestore(&sai->irq_lock, flags);
1306 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
1310 dev_dbg(&sai->pdev->dev, "%s: register iec controls", __func__);
1311 knew.device = rtd->pcm->device;
1312 return snd_ctl_add(rtd->pcm->card, snd_ctl_new1(&knew, sai));
1320 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
1323 sai->cpu_dai = cpu_dai;
1325 sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX);
1328 * as it allows bytes, half-word and words transfers. (See DMA fifos
1331 sai->dma_params.maxburst = 4;
1332 if (sai->pdata->conf.fifo_size < 8 || sai->pdata->conf.no_dma_burst)
1333 sai->dma_params.maxburst = 1;
1335 sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
1338 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params, NULL);
1340 snd_soc_dai_init_dma_data(cpu_dai, NULL, &sai->dma_params);
1342 /* Next settings are not relevant for spdif mode */
1351 if (sai->sync == SAI_SYNC_EXTERNAL) {
1353 ret = sai->pdata->set_sync(sai->pdata, sai->np_sync_provider,
1354 sai->synco, sai->synci);
1360 cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync);
1392 struct snd_pcm_runtime *runtime = substream->runtime;
1395 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
1396 int *ptr = (int *)(runtime->dma_area + hwoff +
1397 channel * (runtime->dma_bytes / runtime->channels));
1399 unsigned int frm_cnt = sai->spdif_frm_cnt;
1408 mask = 1 << (frm_cnt - (byte << 3));
1409 if (sai->iec958.status[byte] & mask)
1418 } while (--cnt);
1419 sai->spdif_frm_cnt = frm_cnt;
1424 /* No support of mmap in S/PDIF mode */
1489 .name = "stm32-sai",
1494 { .compatible = "st,stm32-sai-sub-a",
1496 { .compatible = "st,stm32-sai-sub-b",
1505 struct device_node *np = pdev->dev.of_node;
1512 return -ENODEV;
1518 sai->phys_addr = res->start;
1520 sai->regmap_config = &stm32_sai_sub_regmap_config_f4;
1521 /* Note: PDM registers not available for sub-block B */
1523 sai->regmap_config = &stm32_sai_sub_regmap_config_h7;
1530 sai->regmap = devm_regmap_init_mmio(&pdev->dev, base,
1531 sai->regmap_config);
1532 if (IS_ERR(sai->regmap))
1533 return dev_err_probe(&pdev->dev, PTR_ERR(sai->regmap),
1537 if (of_property_match_string(np, "dma-names", "tx") >= 0) {
1538 sai->dir = SNDRV_PCM_STREAM_PLAYBACK;
1539 } else if (of_property_match_string(np, "dma-names", "rx") >= 0) {
1540 sai->dir = SNDRV_PCM_STREAM_CAPTURE;
1542 dev_err(&pdev->dev, "Unsupported direction\n");
1543 return -EINVAL;
1547 sai->spdif = false;
1550 sai->dir == SNDRV_PCM_STREAM_CAPTURE) {
1551 dev_err(&pdev->dev, "S/PDIF IEC60958 not supported\n");
1552 return -EINVAL;
1555 sai->spdif = true;
1556 sai->master = true;
1561 ret = of_parse_phandle_with_fixed_args(np, "st,sync", 1, 0, &args);
1562 if (ret < 0 && ret != -ENOENT) {
1563 dev_err(&pdev->dev, "Failed to get st,sync property\n");
1567 sai->sync = SAI_SYNC_NONE;
1570 dev_err(&pdev->dev, "%pOFn sync own reference\n", np);
1572 return -EINVAL;
1575 sai->np_sync_provider = of_get_parent(args.np);
1576 if (!sai->np_sync_provider) {
1577 dev_err(&pdev->dev, "%pOFn parent node not found\n",
1580 return -ENODEV;
1583 sai->sync = SAI_SYNC_INTERNAL;
1584 if (sai->np_sync_provider != sai->pdata->pdev->dev.of_node) {
1586 dev_err(&pdev->dev,
1589 return -EINVAL;
1591 sai->sync = SAI_SYNC_EXTERNAL;
1593 sai->synci = args.args[0];
1594 if (sai->synci < 1 ||
1595 (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {
1596 dev_err(&pdev->dev, "Wrong SAI index\n");
1598 return -EINVAL;
1602 "st,stm32-sai-sub-a") >= 0)
1603 sai->synco = STM_SAI_SYNC_OUT_A;
1606 "st,stm32-sai-sub-b") >= 0)
1607 sai->synco = STM_SAI_SYNC_OUT_B;
1609 if (!sai->synco) {
1610 dev_err(&pdev->dev, "Unknown SAI sub-block\n");
1612 return -EINVAL;
1616 dev_dbg(&pdev->dev, "%s synchronized with %s\n",
1617 pdev->name, args.np->full_name);
1621 sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
1622 if (IS_ERR(sai->sai_ck))
1623 return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
1626 ret = clk_prepare(sai->pdata->pclk);
1630 if (STM_SAI_IS_F4(sai->pdata))
1634 if (of_property_present(np, "#clock-cells")) {
1639 sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
1640 if (IS_ERR(sai->sai_mclk))
1641 return PTR_ERR(sai->sai_mclk);
1653 sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
1655 return -ENOMEM;
1657 sai->id = (uintptr_t)device_get_match_data(&pdev->dev);
1659 sai->pdev = pdev;
1660 mutex_init(&sai->ctrl_lock);
1661 spin_lock_init(&sai->irq_lock);
1664 sai->pdata = dev_get_drvdata(pdev->dev.parent);
1665 if (!sai->pdata) {
1666 dev_err(&pdev->dev, "Parent device data not available\n");
1667 return -EINVAL;
1670 if (sai->pdata->conf.get_sai_ck_parent) {
1671 sai->set_sai_ck_rate = stm32_sai_set_parent_clk;
1673 sai->set_sai_ck_rate = stm32_sai_set_parent_rate;
1674 sai->put_sai_ck_rate = stm32_sai_put_parent_rate;
1682 sai->cpu_dai_drv = stm32_sai_playback_dai;
1684 sai->cpu_dai_drv = stm32_sai_capture_dai;
1685 sai->cpu_dai_drv.name = dev_name(&pdev->dev);
1687 ret = devm_request_irq(&pdev->dev, sai->pdata->irq, stm32_sai_isr,
1688 IRQF_SHARED, dev_name(&pdev->dev), sai);
1690 dev_err(&pdev->dev, "IRQ request returned %d\n", ret);
1697 ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
1699 return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
1701 ret = snd_soc_register_component(&pdev->dev, &stm32_component,
1702 &sai->cpu_dai_drv, 1);
1704 snd_dmaengine_pcm_unregister(&pdev->dev);
1708 pm_runtime_enable(&pdev->dev);
1715 struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev);
1717 clk_unprepare(sai->pdata->pclk);
1718 snd_dmaengine_pcm_unregister(&pdev->dev);
1719 snd_soc_unregister_component(&pdev->dev);
1720 pm_runtime_disable(&pdev->dev);
1728 ret = clk_enable(sai->pdata->pclk);
1732 regcache_cache_only(sai->regmap, true);
1733 regcache_mark_dirty(sai->regmap);
1735 clk_disable(sai->pdata->pclk);
1745 ret = clk_enable(sai->pdata->pclk);
1749 regcache_cache_only(sai->regmap, false);
1750 ret = regcache_sync(sai->regmap);
1752 clk_disable(sai->pdata->pclk);
1763 .name = "st,stm32-sai-sub",
1773 MODULE_DESCRIPTION("STM32 Soc SAI sub-block Interface");
1775 MODULE_ALIAS("platform:st,stm32-sai-sub");