Lines Matching +full:sync +full:- +full:update +full:- +full:mask
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)
82 * @id: SAI sub block id corresponding to sub-block A or B
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)
94 * @slot_mask: rx or tx active slots mask. set at init or at runtime
123 int sync; member
196 unsigned int reg, unsigned int mask, in stm32_sai_sub_reg_up() argument
201 ret = clk_enable(sai->pdata->pclk); in stm32_sai_sub_reg_up()
205 ret = regmap_update_bits(sai->regmap, reg, mask, val); in stm32_sai_sub_reg_up()
207 clk_disable(sai->pdata->pclk); in stm32_sai_sub_reg_up()
213 unsigned int reg, unsigned int mask, in stm32_sai_sub_reg_wr() argument
218 ret = clk_enable(sai->pdata->pclk); in stm32_sai_sub_reg_wr()
222 ret = regmap_write_bits(sai->regmap, reg, mask, val); in stm32_sai_sub_reg_wr()
224 clk_disable(sai->pdata->pclk); in stm32_sai_sub_reg_wr()
234 ret = clk_enable(sai->pdata->pclk); in stm32_sai_sub_reg_rd()
238 ret = regmap_read(sai->regmap, reg, val); in stm32_sai_sub_reg_rd()
240 clk_disable(sai->pdata->pclk); in stm32_sai_sub_reg_rd()
272 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; in snd_pcm_iec958_info()
273 uinfo->count = 1; in snd_pcm_iec958_info()
283 mutex_lock(&sai->ctrl_lock); in snd_pcm_iec958_get()
284 memcpy(uctl->value.iec958.status, sai->iec958.status, 4); in snd_pcm_iec958_get()
285 mutex_unlock(&sai->ctrl_lock); in snd_pcm_iec958_get()
295 mutex_lock(&sai->ctrl_lock); in snd_pcm_iec958_put()
296 memcpy(sai->iec958.status, uctl->value.iec958.status, 4); in snd_pcm_iec958_put()
297 mutex_unlock(&sai->ctrl_lock); in snd_pcm_iec958_put()
325 int version = sai->pdata->conf.version; in stm32_sai_get_clk_div()
330 dev_err(&sai->pdev->dev, "Divider %d out of range\n", div); in stm32_sai_get_clk_div()
331 return -EINVAL; in stm32_sai_get_clk_div()
333 dev_dbg(&sai->pdev->dev, "SAI divider %d\n", div); in stm32_sai_get_clk_div()
336 dev_dbg(&sai->pdev->dev, in stm32_sai_get_clk_div()
346 int version = sai->pdata->conf.version; in stm32_sai_set_clk_div()
347 int ret, cr1, mask; in stm32_sai_set_clk_div() local
350 dev_err(&sai->pdev->dev, "Divider %d out of range\n", div); in stm32_sai_set_clk_div()
351 return -EINVAL; in stm32_sai_set_clk_div()
354 mask = SAI_XCR1_MCKDIV_MASK(SAI_XCR1_MCKDIV_WIDTH(version)); in stm32_sai_set_clk_div()
356 ret = stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, mask, cr1); in stm32_sai_set_clk_div()
358 dev_err(&sai->pdev->dev, "Failed to update CR1 register\n"); in stm32_sai_set_clk_div()
372 dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate))); in stm32_sai_rate_accurate()
384 struct platform_device *pdev = sai->pdev; in stm32_sai_set_parent_clk()
385 struct clk *parent_clk = sai->pdata->clk_x8k; in stm32_sai_set_parent_clk()
389 parent_clk = sai->pdata->clk_x11k; in stm32_sai_set_parent_clk()
391 ret = clk_set_parent(sai->sai_ck, parent_clk); in stm32_sai_set_parent_clk()
393 dev_err(&pdev->dev, " Error %d setting sai_ck parent clock. %s", in stm32_sai_set_parent_clk()
394 ret, ret == -EBUSY ? in stm32_sai_set_parent_clk()
402 if (sai->sai_ck_used) { in stm32_sai_put_parent_rate()
403 sai->sai_ck_used = false; in stm32_sai_put_parent_rate()
404 clk_rate_exclusive_put(sai->sai_ck); in stm32_sai_put_parent_rate()
411 struct platform_device *pdev = sai->pdev; in stm32_sai_set_parent_rate()
417 * - mclk on or spdif: in stm32_sai_set_parent_rate()
418 * f_sai_ck = MCKDIV * mclk-fs * fs in stm32_sai_set_parent_rate()
419 * Here typical 256 ratio is assumed for mclk-fs in stm32_sai_set_parent_rate()
420 * - mclk off: in stm32_sai_set_parent_rate()
432 if (!sai->sai_mclk && !STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_set_parent_rate()
433 sai_ck_min_rate = rate * sai->fs_length; in stm32_sai_set_parent_rate()
434 sai_ck_max_rate /= DIV_ROUND_CLOSEST(256, roundup_pow_of_two(sai->fs_length)); in stm32_sai_set_parent_rate()
438 * Request exclusivity, as the clock is shared by SAI sub-blocks and by in stm32_sai_set_parent_rate()
442 clk_rate_exclusive_get(sai->sai_ck); in stm32_sai_set_parent_rate()
443 sai->sai_ck_used = true; in stm32_sai_set_parent_rate()
449 sai_curr_rate = clk_get_rate(sai->sai_ck); in stm32_sai_set_parent_rate()
450 dev_dbg(&pdev->dev, "kernel clock rate: min [%u], max [%u], current [%u]", in stm32_sai_set_parent_rate()
465 sai_new_rate = clk_round_rate(sai->sai_ck, sai_ck_rate); in stm32_sai_set_parent_rate()
467 ret = clk_set_rate(sai->sai_ck, sai_ck_rate); in stm32_sai_set_parent_rate()
469 dev_err(&pdev->dev, "Error %d setting sai_ck rate. %s", in stm32_sai_set_parent_rate()
470 ret, ret == -EBUSY ? in stm32_sai_set_parent_rate()
484 dev_err(&pdev->dev, "Failed to find an accurate rate"); in stm32_sai_set_parent_rate()
489 return -EINVAL; in stm32_sai_set_parent_rate()
496 struct stm32_sai_sub_data *sai = mclk->sai_data; in stm32_sai_mclk_round_rate()
501 return -EINVAL; in stm32_sai_mclk_round_rate()
503 mclk->freq = *prate / div; in stm32_sai_mclk_round_rate()
505 return mclk->freq; in stm32_sai_mclk_round_rate()
513 return mclk->freq; in stm32_sai_mclk_recalc_rate()
520 struct stm32_sai_sub_data *sai = mclk->sai_data; in stm32_sai_mclk_set_rate()
531 mclk->freq = rate; in stm32_sai_mclk_set_rate()
539 struct stm32_sai_sub_data *sai = mclk->sai_data; in stm32_sai_mclk_enable()
541 dev_dbg(&sai->pdev->dev, "Enable master clock\n"); in stm32_sai_mclk_enable()
550 struct stm32_sai_sub_data *sai = mclk->sai_data; in stm32_sai_mclk_disable()
552 dev_dbg(&sai->pdev->dev, "Disable master clock\n"); in stm32_sai_mclk_disable()
569 struct device *dev = &sai->pdev->dev; in stm32_sai_add_mclk_provider()
570 const char *pname = __clk_get_name(sai->sai_ck); in stm32_sai_add_mclk_provider()
576 return -ENOMEM; in stm32_sai_add_mclk_provider()
581 return -ENOMEM; in stm32_sai_add_mclk_provider()
588 while (*s && *s != '_' && (i < (SAI_MCLK_NAME_LEN - 7))) { in stm32_sai_add_mclk_provider()
594 mclk->hw.init = CLK_HW_INIT(mclk_name, pname, &mclk_ops, 0); in stm32_sai_add_mclk_provider()
595 mclk->sai_data = sai; in stm32_sai_add_mclk_provider()
596 hw = &mclk->hw; in stm32_sai_add_mclk_provider()
599 ret = devm_clk_hw_register(&sai->pdev->dev, hw); in stm32_sai_add_mclk_provider()
604 sai->sai_mclk = hw->clk; in stm32_sai_add_mclk_provider()
613 struct platform_device *pdev = sai->pdev; in stm32_sai_isr()
627 if (!sai->substream) { in stm32_sai_isr()
628 dev_err(&pdev->dev, "Device stopped. Spurious IRQ 0x%x\n", sr); in stm32_sai_isr()
633 dev_err(&pdev->dev, "IRQ %s\n", in stm32_sai_isr()
639 dev_dbg(&pdev->dev, "IRQ mute detected\n"); in stm32_sai_isr()
642 dev_err(&pdev->dev, "IRQ wrong clock configuration\n"); in stm32_sai_isr()
647 dev_err(&pdev->dev, "IRQ Codec not ready\n"); in stm32_sai_isr()
650 dev_err(&pdev->dev, "IRQ Anticipated frame synchro\n"); in stm32_sai_isr()
655 dev_err(&pdev->dev, "IRQ Late frame synchro\n"); in stm32_sai_isr()
659 spin_lock(&sai->irq_lock); in stm32_sai_isr()
660 if (status != SNDRV_PCM_STATE_RUNNING && sai->substream) in stm32_sai_isr()
661 snd_pcm_stop_xrun(sai->substream); in stm32_sai_isr()
662 spin_unlock(&sai->irq_lock); in stm32_sai_isr()
673 if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) { in stm32_sai_set_sysclk()
683 if (sai->mclk_rate) { in stm32_sai_set_sysclk()
684 clk_rate_exclusive_put(sai->sai_mclk); in stm32_sai_set_sysclk()
685 sai->mclk_rate = 0; in stm32_sai_set_sysclk()
688 if (sai->put_sai_ck_rate) in stm32_sai_set_sysclk()
689 sai->put_sai_ck_rate(sai); in stm32_sai_set_sysclk()
695 ret = sai->set_sai_ck_rate(sai, freq); in stm32_sai_set_sysclk()
699 ret = clk_set_rate_exclusive(sai->sai_mclk, freq); in stm32_sai_set_sysclk()
701 dev_err(cpu_dai->dev, in stm32_sai_set_sysclk()
702 ret == -EBUSY ? in stm32_sai_set_sysclk()
708 dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); in stm32_sai_set_sysclk()
709 sai->mclk_rate = freq; in stm32_sai_set_sysclk()
722 dev_warn(cpu_dai->dev, "Slot setting relevant only for TDM\n"); in stm32_sai_set_dai_tdm_slot()
726 dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n", in stm32_sai_set_dai_tdm_slot()
742 SAI_XSLOTR_NBSLOT_SET(slots - 1); in stm32_sai_set_dai_tdm_slot()
745 /* tx/rx mask set in machine init, if slot number defined in DT */ in stm32_sai_set_dai_tdm_slot()
747 sai->slot_mask = tx_mask; in stm32_sai_set_dai_tdm_slot()
752 sai->slot_mask = rx_mask; in stm32_sai_set_dai_tdm_slot()
760 sai->slot_width = slot_width; in stm32_sai_set_dai_tdm_slot()
761 sai->slots = slots; in stm32_sai_set_dai_tdm_slot()
773 dev_dbg(cpu_dai->dev, "fmt %x\n", fmt); in stm32_sai_set_dai_fmt()
808 dev_err(cpu_dai->dev, "Unsupported protocol %#x\n", in stm32_sai_set_dai_fmt()
810 return -EINVAL; in stm32_sai_set_dai_fmt()
833 dev_err(cpu_dai->dev, "Unsupported strobing %#x\n", in stm32_sai_set_dai_fmt()
835 return -EINVAL; in stm32_sai_set_dai_fmt()
847 sai->master = false; in stm32_sai_set_dai_fmt()
850 sai->master = true; in stm32_sai_set_dai_fmt()
853 dev_err(cpu_dai->dev, "Unsupported mode %#x\n", in stm32_sai_set_dai_fmt()
855 return -EINVAL; in stm32_sai_set_dai_fmt()
858 /* Set slave mode if sub-block is synchronized with another SAI */ in stm32_sai_set_dai_fmt()
859 if (sai->sync) { in stm32_sai_set_dai_fmt()
860 dev_dbg(cpu_dai->dev, "Synchronized SAI configured as slave\n"); in stm32_sai_set_dai_fmt()
862 sai->master = false; in stm32_sai_set_dai_fmt()
870 dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); in stm32_sai_set_dai_fmt()
874 sai->fmt = fmt; in stm32_sai_set_dai_fmt()
886 spin_lock_irqsave(&sai->irq_lock, flags); in stm32_sai_startup()
887 sai->substream = substream; in stm32_sai_startup()
888 spin_unlock_irqrestore(&sai->irq_lock, flags); in stm32_sai_startup()
891 snd_pcm_hw_constraint_mask64(substream->runtime, in stm32_sai_startup()
894 snd_pcm_hw_constraint_single(substream->runtime, in stm32_sai_startup()
898 ret = clk_prepare_enable(sai->sai_ck); in stm32_sai_startup()
900 dev_err(cpu_dai->dev, "Failed to enable clock: %d\n", ret); in stm32_sai_startup()
915 if (sai->master) in stm32_sai_startup()
945 sai->spdif_frm_cnt = 0; in stm32_sai_set_config()
962 dev_err(cpu_dai->dev, "Data format not supported\n"); in stm32_sai_set_config()
963 return -EINVAL; in stm32_sai_set_config()
967 if ((sai->slots == 2) && (params_channels(params) == 1)) in stm32_sai_set_config()
972 dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); in stm32_sai_set_config()
992 sai->slot_width = sai->data_size; in stm32_sai_set_slots()
994 if (sai->slot_width < sai->data_size) { in stm32_sai_set_slots()
995 dev_err(cpu_dai->dev, in stm32_sai_set_slots()
997 sai->data_size); in stm32_sai_set_slots()
998 return -EINVAL; in stm32_sai_set_slots()
1002 if (!sai->slots) in stm32_sai_set_slots()
1003 sai->slots = 2; in stm32_sai_set_slots()
1008 SAI_XSLOTR_NBSLOT_SET((sai->slots - 1))); in stm32_sai_set_slots()
1010 /* Set default slots mask if not already set from DT */ in stm32_sai_set_slots()
1012 sai->slot_mask = (1 << sai->slots) - 1; in stm32_sai_set_slots()
1015 SAI_XSLOTR_SLOTEN_SET(sai->slot_mask)); in stm32_sai_set_slots()
1018 dev_dbg(cpu_dai->dev, "Slots %d, slot width %d\n", in stm32_sai_set_slots()
1019 sai->slots, sai->slot_width); in stm32_sai_set_slots()
1030 format = sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK; in stm32_sai_set_frame()
1031 sai->fs_length = sai->slot_width * sai->slots; in stm32_sai_set_frame()
1033 fs_active = sai->fs_length / 2; in stm32_sai_set_frame()
1038 frcr = SAI_XFRCR_FRL_SET((sai->fs_length - 1)); in stm32_sai_set_frame()
1039 frcr |= SAI_XFRCR_FSALL_SET((fs_active - 1)); in stm32_sai_set_frame()
1042 dev_dbg(cpu_dai->dev, "Frame length %d, frame active %d\n", in stm32_sai_set_frame()
1043 sai->fs_length, fs_active); in stm32_sai_set_frame()
1047 if ((sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_LSB) { in stm32_sai_set_frame()
1048 offset = sai->slot_width - sai->data_size; in stm32_sai_set_frame()
1058 unsigned char *cs = sai->iec958.status; in stm32_sai_init_iec958_status()
1073 mutex_lock(&sai->ctrl_lock); in stm32_sai_set_iec958_status()
1074 switch (runtime->rate) { in stm32_sai_set_iec958_status()
1076 sai->iec958.status[3] = IEC958_AES3_CON_FS_22050; in stm32_sai_set_iec958_status()
1079 sai->iec958.status[3] = IEC958_AES3_CON_FS_44100; in stm32_sai_set_iec958_status()
1082 sai->iec958.status[3] = IEC958_AES3_CON_FS_88200; in stm32_sai_set_iec958_status()
1085 sai->iec958.status[3] = IEC958_AES3_CON_FS_176400; in stm32_sai_set_iec958_status()
1088 sai->iec958.status[3] = IEC958_AES3_CON_FS_24000; in stm32_sai_set_iec958_status()
1091 sai->iec958.status[3] = IEC958_AES3_CON_FS_48000; in stm32_sai_set_iec958_status()
1094 sai->iec958.status[3] = IEC958_AES3_CON_FS_96000; in stm32_sai_set_iec958_status()
1097 sai->iec958.status[3] = IEC958_AES3_CON_FS_192000; in stm32_sai_set_iec958_status()
1100 sai->iec958.status[3] = IEC958_AES3_CON_FS_32000; in stm32_sai_set_iec958_status()
1103 sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID; in stm32_sai_set_iec958_status()
1106 mutex_unlock(&sai->ctrl_lock); in stm32_sai_set_iec958_status()
1118 if (!sai->sai_mclk) { in stm32_sai_configure_clock()
1119 ret = sai->set_sai_ck_rate(sai, rate); in stm32_sai_configure_clock()
1123 sai_clk_rate = clk_get_rate(sai->sai_ck); in stm32_sai_configure_clock()
1125 if (STM_SAI_IS_F4(sai->pdata)) { in stm32_sai_configure_clock()
1133 if (!sai->mclk_rate) in stm32_sai_configure_clock()
1136 if (2 * sai_clk_rate >= 3 * sai->mclk_rate) { in stm32_sai_configure_clock()
1138 2 * sai->mclk_rate); in stm32_sai_configure_clock()
1158 if (sai->mclk_rate) { in stm32_sai_configure_clock()
1159 mclk_ratio = sai->mclk_rate / rate; in stm32_sai_configure_clock()
1163 dev_err(cpu_dai->dev, in stm32_sai_configure_clock()
1166 return -EINVAL; in stm32_sai_configure_clock()
1174 sai->mclk_rate); in stm32_sai_configure_clock()
1178 /* mclk-fs not set, master clock not active */ in stm32_sai_configure_clock()
1179 den = sai->fs_length * params_rate(params); in stm32_sai_configure_clock()
1198 sai->data_size = params_width(params); in stm32_sai_hw_params()
1202 substream->runtime->rate = params_rate(params); in stm32_sai_hw_params()
1203 stm32_sai_set_iec958_status(sai, substream->runtime); in stm32_sai_hw_params()
1215 if (sai->master) in stm32_sai_hw_params()
1231 dev_dbg(cpu_dai->dev, "Enable DMA and SAI\n"); in stm32_sai_trigger()
1240 dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); in stm32_sai_trigger()
1245 dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n"); in stm32_sai_trigger()
1258 dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); in stm32_sai_trigger()
1261 sai->spdif_frm_cnt = 0; in stm32_sai_trigger()
1264 return -EINVAL; in stm32_sai_trigger()
1278 clk_disable_unprepare(sai->sai_ck); in stm32_sai_shutdown()
1282 * - Master clock is not used. Kernel clock won't be released trough sysclk in stm32_sai_shutdown()
1283 * - Put handler is defined. Involve that clock is managed exclusively in stm32_sai_shutdown()
1285 if (!sai->sai_mclk && sai->put_sai_ck_rate) in stm32_sai_shutdown()
1286 sai->put_sai_ck_rate(sai); in stm32_sai_shutdown()
1288 spin_lock_irqsave(&sai->irq_lock, flags); in stm32_sai_shutdown()
1289 sai->substream = NULL; in stm32_sai_shutdown()
1290 spin_unlock_irqrestore(&sai->irq_lock, flags); in stm32_sai_shutdown()
1296 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_pcm_new()
1300 dev_dbg(&sai->pdev->dev, "%s: register iec controls", __func__); in stm32_sai_pcm_new()
1301 knew.device = rtd->pcm->device; in stm32_sai_pcm_new()
1302 return snd_ctl_add(rtd->pcm->card, snd_ctl_new1(&knew, sai)); in stm32_sai_pcm_new()
1310 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_dai_probe()
1313 sai->cpu_dai = cpu_dai; in stm32_sai_dai_probe()
1315 sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX); in stm32_sai_dai_probe()
1318 * as it allows bytes, half-word and words transfers. (See DMA fifos in stm32_sai_dai_probe()
1321 sai->dma_params.maxburst = 4; in stm32_sai_dai_probe()
1322 if (sai->pdata->conf.fifo_size < 8 || sai->pdata->conf.no_dma_burst) in stm32_sai_dai_probe()
1323 sai->dma_params.maxburst = 1; in stm32_sai_dai_probe()
1325 sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; in stm32_sai_dai_probe()
1328 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params, NULL); in stm32_sai_dai_probe()
1330 snd_soc_dai_init_dma_data(cpu_dai, NULL, &sai->dma_params); in stm32_sai_dai_probe()
1341 if (sai->sync == SAI_SYNC_EXTERNAL) { in stm32_sai_dai_probe()
1343 ret = sai->pdata->set_sync(sai->pdata, sai->np_sync_provider, in stm32_sai_dai_probe()
1344 sai->synco, sai->synci); in stm32_sai_dai_probe()
1350 cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync); in stm32_sai_dai_probe()
1382 struct snd_pcm_runtime *runtime = substream->runtime; in stm32_sai_pcm_process_spdif()
1385 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_pcm_process_spdif()
1386 int *ptr = (int *)(runtime->dma_area + hwoff + in stm32_sai_pcm_process_spdif()
1387 channel * (runtime->dma_bytes / runtime->channels)); in stm32_sai_pcm_process_spdif()
1389 unsigned int frm_cnt = sai->spdif_frm_cnt; in stm32_sai_pcm_process_spdif()
1391 unsigned int mask; in stm32_sai_pcm_process_spdif() local
1398 mask = 1 << (frm_cnt - (byte << 3)); in stm32_sai_pcm_process_spdif()
1399 if (sai->iec958.status[byte] & mask) in stm32_sai_pcm_process_spdif()
1408 } while (--cnt); in stm32_sai_pcm_process_spdif()
1409 sai->spdif_frm_cnt = frm_cnt; in stm32_sai_pcm_process_spdif()
1479 .name = "stm32-sai",
1484 { .compatible = "st,stm32-sai-sub-a",
1486 { .compatible = "st,stm32-sai-sub-b",
1495 struct device_node *np = pdev->dev.of_node; in stm32_sai_sub_parse_of()
1502 return -ENODEV; in stm32_sai_sub_parse_of()
1508 sai->phys_addr = res->start; in stm32_sai_sub_parse_of()
1510 sai->regmap_config = &stm32_sai_sub_regmap_config_f4; in stm32_sai_sub_parse_of()
1511 /* Note: PDM registers not available for sub-block B */ in stm32_sai_sub_parse_of()
1513 sai->regmap_config = &stm32_sai_sub_regmap_config_h7; in stm32_sai_sub_parse_of()
1520 sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, in stm32_sai_sub_parse_of()
1521 sai->regmap_config); in stm32_sai_sub_parse_of()
1522 if (IS_ERR(sai->regmap)) in stm32_sai_sub_parse_of()
1523 return dev_err_probe(&pdev->dev, PTR_ERR(sai->regmap), in stm32_sai_sub_parse_of()
1527 if (of_property_match_string(np, "dma-names", "tx") >= 0) { in stm32_sai_sub_parse_of()
1528 sai->dir = SNDRV_PCM_STREAM_PLAYBACK; in stm32_sai_sub_parse_of()
1529 } else if (of_property_match_string(np, "dma-names", "rx") >= 0) { in stm32_sai_sub_parse_of()
1530 sai->dir = SNDRV_PCM_STREAM_CAPTURE; in stm32_sai_sub_parse_of()
1532 dev_err(&pdev->dev, "Unsupported direction\n"); in stm32_sai_sub_parse_of()
1533 return -EINVAL; in stm32_sai_sub_parse_of()
1537 sai->spdif = false; in stm32_sai_sub_parse_of()
1540 sai->dir == SNDRV_PCM_STREAM_CAPTURE) { in stm32_sai_sub_parse_of()
1541 dev_err(&pdev->dev, "S/PDIF IEC60958 not supported\n"); in stm32_sai_sub_parse_of()
1542 return -EINVAL; in stm32_sai_sub_parse_of()
1545 sai->spdif = true; in stm32_sai_sub_parse_of()
1546 sai->master = true; in stm32_sai_sub_parse_of()
1551 ret = of_parse_phandle_with_fixed_args(np, "st,sync", 1, 0, &args); in stm32_sai_sub_parse_of()
1552 if (ret < 0 && ret != -ENOENT) { in stm32_sai_sub_parse_of()
1553 dev_err(&pdev->dev, "Failed to get st,sync property\n"); in stm32_sai_sub_parse_of()
1557 sai->sync = SAI_SYNC_NONE; in stm32_sai_sub_parse_of()
1560 dev_err(&pdev->dev, "%pOFn sync own reference\n", np); in stm32_sai_sub_parse_of()
1562 return -EINVAL; in stm32_sai_sub_parse_of()
1565 sai->np_sync_provider = of_get_parent(args.np); in stm32_sai_sub_parse_of()
1566 if (!sai->np_sync_provider) { in stm32_sai_sub_parse_of()
1567 dev_err(&pdev->dev, "%pOFn parent node not found\n", in stm32_sai_sub_parse_of()
1570 return -ENODEV; in stm32_sai_sub_parse_of()
1573 sai->sync = SAI_SYNC_INTERNAL; in stm32_sai_sub_parse_of()
1574 if (sai->np_sync_provider != sai->pdata->pdev->dev.of_node) { in stm32_sai_sub_parse_of()
1576 dev_err(&pdev->dev, in stm32_sai_sub_parse_of()
1579 return -EINVAL; in stm32_sai_sub_parse_of()
1581 sai->sync = SAI_SYNC_EXTERNAL; in stm32_sai_sub_parse_of()
1583 sai->synci = args.args[0]; in stm32_sai_sub_parse_of()
1584 if (sai->synci < 1 || in stm32_sai_sub_parse_of()
1585 (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) { in stm32_sai_sub_parse_of()
1586 dev_err(&pdev->dev, "Wrong SAI index\n"); in stm32_sai_sub_parse_of()
1588 return -EINVAL; in stm32_sai_sub_parse_of()
1592 "st,stm32-sai-sub-a") >= 0) in stm32_sai_sub_parse_of()
1593 sai->synco = STM_SAI_SYNC_OUT_A; in stm32_sai_sub_parse_of()
1596 "st,stm32-sai-sub-b") >= 0) in stm32_sai_sub_parse_of()
1597 sai->synco = STM_SAI_SYNC_OUT_B; in stm32_sai_sub_parse_of()
1599 if (!sai->synco) { in stm32_sai_sub_parse_of()
1600 dev_err(&pdev->dev, "Unknown SAI sub-block\n"); in stm32_sai_sub_parse_of()
1602 return -EINVAL; in stm32_sai_sub_parse_of()
1606 dev_dbg(&pdev->dev, "%s synchronized with %s\n", in stm32_sai_sub_parse_of()
1607 pdev->name, args.np->full_name); in stm32_sai_sub_parse_of()
1611 sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); in stm32_sai_sub_parse_of()
1612 if (IS_ERR(sai->sai_ck)) in stm32_sai_sub_parse_of()
1613 return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck), in stm32_sai_sub_parse_of()
1616 ret = clk_prepare(sai->pdata->pclk); in stm32_sai_sub_parse_of()
1620 if (STM_SAI_IS_F4(sai->pdata)) in stm32_sai_sub_parse_of()
1624 if (of_property_present(np, "#clock-cells")) { in stm32_sai_sub_parse_of()
1629 sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK"); in stm32_sai_sub_parse_of()
1630 if (IS_ERR(sai->sai_mclk)) in stm32_sai_sub_parse_of()
1631 return PTR_ERR(sai->sai_mclk); in stm32_sai_sub_parse_of()
1643 sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); in stm32_sai_sub_probe()
1645 return -ENOMEM; in stm32_sai_sub_probe()
1647 sai->id = (uintptr_t)device_get_match_data(&pdev->dev); in stm32_sai_sub_probe()
1649 sai->pdev = pdev; in stm32_sai_sub_probe()
1650 mutex_init(&sai->ctrl_lock); in stm32_sai_sub_probe()
1651 spin_lock_init(&sai->irq_lock); in stm32_sai_sub_probe()
1654 sai->pdata = dev_get_drvdata(pdev->dev.parent); in stm32_sai_sub_probe()
1655 if (!sai->pdata) { in stm32_sai_sub_probe()
1656 dev_err(&pdev->dev, "Parent device data not available\n"); in stm32_sai_sub_probe()
1657 return -EINVAL; in stm32_sai_sub_probe()
1660 if (sai->pdata->conf.get_sai_ck_parent) { in stm32_sai_sub_probe()
1661 sai->set_sai_ck_rate = stm32_sai_set_parent_clk; in stm32_sai_sub_probe()
1663 sai->set_sai_ck_rate = stm32_sai_set_parent_rate; in stm32_sai_sub_probe()
1664 sai->put_sai_ck_rate = stm32_sai_put_parent_rate; in stm32_sai_sub_probe()
1672 sai->cpu_dai_drv = stm32_sai_playback_dai; in stm32_sai_sub_probe()
1674 sai->cpu_dai_drv = stm32_sai_capture_dai; in stm32_sai_sub_probe()
1675 sai->cpu_dai_drv.name = dev_name(&pdev->dev); in stm32_sai_sub_probe()
1677 ret = devm_request_irq(&pdev->dev, sai->pdata->irq, stm32_sai_isr, in stm32_sai_sub_probe()
1678 IRQF_SHARED, dev_name(&pdev->dev), sai); in stm32_sai_sub_probe()
1680 dev_err(&pdev->dev, "IRQ request returned %d\n", ret); in stm32_sai_sub_probe()
1687 ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0); in stm32_sai_sub_probe()
1689 return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n"); in stm32_sai_sub_probe()
1691 ret = snd_soc_register_component(&pdev->dev, &stm32_component, in stm32_sai_sub_probe()
1692 &sai->cpu_dai_drv, 1); in stm32_sai_sub_probe()
1694 snd_dmaengine_pcm_unregister(&pdev->dev); in stm32_sai_sub_probe()
1698 pm_runtime_enable(&pdev->dev); in stm32_sai_sub_probe()
1705 struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev); in stm32_sai_sub_remove()
1707 clk_unprepare(sai->pdata->pclk); in stm32_sai_sub_remove()
1708 snd_dmaengine_pcm_unregister(&pdev->dev); in stm32_sai_sub_remove()
1709 snd_soc_unregister_component(&pdev->dev); in stm32_sai_sub_remove()
1710 pm_runtime_disable(&pdev->dev); in stm32_sai_sub_remove()
1718 ret = clk_enable(sai->pdata->pclk); in stm32_sai_sub_suspend()
1722 regcache_cache_only(sai->regmap, true); in stm32_sai_sub_suspend()
1723 regcache_mark_dirty(sai->regmap); in stm32_sai_sub_suspend()
1725 clk_disable(sai->pdata->pclk); in stm32_sai_sub_suspend()
1735 ret = clk_enable(sai->pdata->pclk); in stm32_sai_sub_resume()
1739 regcache_cache_only(sai->regmap, false); in stm32_sai_sub_resume()
1740 ret = regcache_sync(sai->regmap); in stm32_sai_sub_resume()
1742 clk_disable(sai->pdata->pclk); in stm32_sai_sub_resume()
1753 .name = "st,stm32-sai-sub",
1763 MODULE_DESCRIPTION("STM32 Soc SAI sub-block Interface");
1765 MODULE_ALIAS("platform:st,stm32-sai-sub");