• Home
  • Raw
  • Download

Lines Matching full:sai

2  * STM32 ALSA SoC Digital Audio Interface (SAI) driver.
66 #define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4(sai->pdata))
72 * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
74 * @regmap: SAI register map pointer
75 * @regmap_config: SAI sub block register map configuration pointer
80 * @pdata: SAI block parent data pointer
82 * @sai_ck: kernel clock feeding the SAI clock generator
83 * @phys_addr: SAI registers physical base address
84 * @mclk_rate: SAI block master clock frequency (Hz). set at init
85 * @id: SAI sub block id corresponding to sub-block A or B
86 * @dir: SAI block direction (playback or capture). set at init
87 * @master: SAI block mode flag. (true=master, false=slave) set at init
88 * @spdif: SAI S/PDIF iec60958 mode flag. set at init
89 * @fmt: SAI block format. relevant only for custom protocols. set at init
90 * @sync: SAI block synchronization mode. (none, internal or external)
91 * @synco: SAI block ext sync source (provider setting). (none, sub-block A/B)
92 * @synci: SAI block ext sync source (client setting). (SAI sync provider index)
223 struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol); in snd_pcm_iec958_get() local
225 mutex_lock(&sai->ctrl_lock); in snd_pcm_iec958_get()
226 memcpy(uctl->value.iec958.status, sai->iec958.status, 4); in snd_pcm_iec958_get()
227 mutex_unlock(&sai->ctrl_lock); in snd_pcm_iec958_get()
235 struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol); in snd_pcm_iec958_put() local
237 mutex_lock(&sai->ctrl_lock); in snd_pcm_iec958_put()
238 memcpy(sai->iec958.status, uctl->value.iec958.status, 4); in snd_pcm_iec958_put()
239 mutex_unlock(&sai->ctrl_lock); in snd_pcm_iec958_put()
256 struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid; in stm32_sai_isr() local
257 struct platform_device *pdev = sai->pdev; in stm32_sai_isr()
261 regmap_read(sai->regmap, STM_SAI_IMR_REGX, &imr); in stm32_sai_isr()
262 regmap_read(sai->regmap, STM_SAI_SR_REGX, &sr); in stm32_sai_isr()
268 regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX, SAI_XCLRFR_MASK, in stm32_sai_isr()
271 if (!sai->substream) { in stm32_sai_isr()
278 STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun"); in stm32_sai_isr()
304 snd_pcm_stop_xrun(sai->substream); in stm32_sai_isr()
312 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_sysclk() local
315 if ((dir == SND_SOC_CLOCK_OUT) && sai->master) { in stm32_sai_set_sysclk()
316 ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, in stm32_sai_set_sysclk()
322 sai->mclk_rate = freq; in stm32_sai_set_sysclk()
323 dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); in stm32_sai_set_sysclk()
332 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_dai_tdm_slot() local
335 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_set_dai_tdm_slot()
360 if (STM_SAI_IS_PLAYBACK(sai)) { in stm32_sai_set_dai_tdm_slot()
361 sai->slot_mask = tx_mask; in stm32_sai_set_dai_tdm_slot()
365 if (STM_SAI_IS_CAPTURE(sai)) { in stm32_sai_set_dai_tdm_slot()
366 sai->slot_mask = rx_mask; in stm32_sai_set_dai_tdm_slot()
372 regmap_update_bits(sai->regmap, STM_SAI_SLOTR_REGX, slotr_mask, slotr); in stm32_sai_set_dai_tdm_slot()
374 sai->slot_width = slot_width; in stm32_sai_set_dai_tdm_slot()
375 sai->slots = slots; in stm32_sai_set_dai_tdm_slot()
382 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_dai_fmt() local
394 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_set_dai_fmt()
454 regmap_update_bits(sai->regmap, STM_SAI_FRCR_REGX, frcr_mask, frcr); in stm32_sai_set_dai_fmt()
461 sai->master = false; in stm32_sai_set_dai_fmt()
464 sai->master = true; in stm32_sai_set_dai_fmt()
472 /* Set slave mode if sub-block is synchronized with another SAI */ in stm32_sai_set_dai_fmt()
473 if (sai->sync) { in stm32_sai_set_dai_fmt()
474 dev_dbg(cpu_dai->dev, "Synchronized SAI configured as slave\n"); in stm32_sai_set_dai_fmt()
476 sai->master = false; in stm32_sai_set_dai_fmt()
482 ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1); in stm32_sai_set_dai_fmt()
488 sai->fmt = fmt; in stm32_sai_set_dai_fmt()
496 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_startup() local
499 sai->substream = substream; in stm32_sai_startup()
501 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_startup()
509 ret = clk_prepare_enable(sai->sai_ck); in stm32_sai_startup()
517 regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX, in stm32_sai_startup()
521 if (STM_SAI_IS_CAPTURE(sai)) { in stm32_sai_startup()
522 regmap_read(sai->regmap, STM_SAI_CR2_REGX, &cr2); in stm32_sai_startup()
527 if (sai->master) in stm32_sai_startup()
532 regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, in stm32_sai_startup()
542 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_config() local
547 * SAI fifo threshold is set to half fifo, to keep enough space in stm32_sai_set_config()
550 regmap_update_bits(sai->regmap, STM_SAI_CR2_REGX, in stm32_sai_set_config()
556 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_set_config()
557 sai->spdif_frm_cnt = 0; in stm32_sai_set_config()
579 if ((sai->slots == 2) && (params_channels(params) == 1)) in stm32_sai_set_config()
582 ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1); in stm32_sai_set_config()
593 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_slots() local
596 regmap_read(sai->regmap, STM_SAI_SLOTR_REGX, &slotr); in stm32_sai_set_slots()
604 sai->slot_width = sai->data_size; in stm32_sai_set_slots()
606 if (sai->slot_width < sai->data_size) { in stm32_sai_set_slots()
609 sai->data_size); in stm32_sai_set_slots()
614 if (!sai->slots) in stm32_sai_set_slots()
615 sai->slots = 2; in stm32_sai_set_slots()
618 regmap_update_bits(sai->regmap, STM_SAI_SLOTR_REGX, in stm32_sai_set_slots()
620 SAI_XSLOTR_NBSLOT_SET((sai->slots - 1))); in stm32_sai_set_slots()
624 sai->slot_mask = (1 << sai->slots) - 1; in stm32_sai_set_slots()
625 regmap_update_bits(sai->regmap, in stm32_sai_set_slots()
627 SAI_XSLOTR_SLOTEN_SET(sai->slot_mask)); in stm32_sai_set_slots()
631 sai->slots, sai->slot_width); in stm32_sai_set_slots()
638 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_frame() local
642 format = sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK; in stm32_sai_set_frame()
643 sai->fs_length = sai->slot_width * sai->slots; in stm32_sai_set_frame()
645 fs_active = sai->fs_length / 2; in stm32_sai_set_frame()
650 frcr = SAI_XFRCR_FRL_SET((sai->fs_length - 1)); in stm32_sai_set_frame()
655 sai->fs_length, fs_active); in stm32_sai_set_frame()
657 regmap_update_bits(sai->regmap, STM_SAI_FRCR_REGX, frcr_mask, frcr); in stm32_sai_set_frame()
659 if ((sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_LSB) { in stm32_sai_set_frame()
660 offset = sai->slot_width - sai->data_size; in stm32_sai_set_frame()
662 regmap_update_bits(sai->regmap, STM_SAI_SLOTR_REGX, in stm32_sai_set_frame()
668 static void stm32_sai_init_iec958_status(struct stm32_sai_sub_data *sai) in stm32_sai_init_iec958_status() argument
670 unsigned char *cs = sai->iec958.status; in stm32_sai_init_iec958_status()
678 static void stm32_sai_set_iec958_status(struct stm32_sai_sub_data *sai, in stm32_sai_set_iec958_status() argument
685 mutex_lock(&sai->ctrl_lock); in stm32_sai_set_iec958_status()
688 sai->iec958.status[3] = IEC958_AES3_CON_FS_22050; in stm32_sai_set_iec958_status()
691 sai->iec958.status[3] = IEC958_AES3_CON_FS_44100; in stm32_sai_set_iec958_status()
694 sai->iec958.status[3] = IEC958_AES3_CON_FS_88200; in stm32_sai_set_iec958_status()
697 sai->iec958.status[3] = IEC958_AES3_CON_FS_176400; in stm32_sai_set_iec958_status()
700 sai->iec958.status[3] = IEC958_AES3_CON_FS_24000; in stm32_sai_set_iec958_status()
703 sai->iec958.status[3] = IEC958_AES3_CON_FS_48000; in stm32_sai_set_iec958_status()
706 sai->iec958.status[3] = IEC958_AES3_CON_FS_96000; in stm32_sai_set_iec958_status()
709 sai->iec958.status[3] = IEC958_AES3_CON_FS_192000; in stm32_sai_set_iec958_status()
712 sai->iec958.status[3] = IEC958_AES3_CON_FS_32000; in stm32_sai_set_iec958_status()
715 sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID; in stm32_sai_set_iec958_status()
718 mutex_unlock(&sai->ctrl_lock); in stm32_sai_set_iec958_status()
724 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_configure_clock() local
727 int version = sai->pdata->conf->version; in stm32_sai_configure_clock()
730 if (!sai->mclk_rate) { in stm32_sai_configure_clock()
736 clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k); in stm32_sai_configure_clock()
738 clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k); in stm32_sai_configure_clock()
739 sai_clk_rate = clk_get_rate(sai->sai_ck); in stm32_sai_configure_clock()
741 if (STM_SAI_IS_F4(sai->pdata)) { in stm32_sai_configure_clock()
747 if (2 * sai_clk_rate >= 3 * sai->mclk_rate) in stm32_sai_configure_clock()
749 2 * sai->mclk_rate); in stm32_sai_configure_clock()
760 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_configure_clock()
764 if (sai->mclk_rate) { in stm32_sai_configure_clock()
765 mclk_ratio = sai->mclk_rate / rate; in stm32_sai_configure_clock()
776 sai->mclk_rate); in stm32_sai_configure_clock()
779 den = sai->fs_length * params_rate(params); in stm32_sai_configure_clock()
789 dev_dbg(cpu_dai->dev, "SAI clock %d, divider %d\n", sai_clk_rate, div); in stm32_sai_configure_clock()
793 ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1); in stm32_sai_configure_clock()
806 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_hw_params() local
809 sai->data_size = params_width(params); in stm32_sai_hw_params()
811 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_hw_params()
814 stm32_sai_set_iec958_status(sai, substream->runtime); in stm32_sai_hw_params()
826 if (sai->master) in stm32_sai_hw_params()
835 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_trigger() local
842 dev_dbg(cpu_dai->dev, "Enable DMA and SAI\n"); in stm32_sai_trigger()
844 regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, in stm32_sai_trigger()
847 /* Enable SAI */ in stm32_sai_trigger()
848 ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, in stm32_sai_trigger()
856 dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n"); in stm32_sai_trigger()
858 regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, in stm32_sai_trigger()
861 regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, in stm32_sai_trigger()
865 ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, in stm32_sai_trigger()
871 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) in stm32_sai_trigger()
872 sai->spdif_frm_cnt = 0; in stm32_sai_trigger()
884 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_shutdown() local
886 regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0); in stm32_sai_shutdown()
888 regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV, in stm32_sai_shutdown()
891 clk_disable_unprepare(sai->sai_ck); in stm32_sai_shutdown()
892 sai->substream = NULL; in stm32_sai_shutdown()
898 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_pcm_new() local
901 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_pcm_new()
902 dev_dbg(&sai->pdev->dev, "%s: register iec controls", __func__); in stm32_sai_pcm_new()
904 return snd_ctl_add(rtd->pcm->card, snd_ctl_new1(&knew, sai)); in stm32_sai_pcm_new()
912 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_dai_probe() local
915 sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX); in stm32_sai_dai_probe()
921 sai->dma_params.maxburst = 4; in stm32_sai_dai_probe()
923 sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; in stm32_sai_dai_probe()
925 if (STM_SAI_IS_PLAYBACK(sai)) in stm32_sai_dai_probe()
926 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params, NULL); in stm32_sai_dai_probe()
928 snd_soc_dai_init_dma_data(cpu_dai, NULL, &sai->dma_params); in stm32_sai_dai_probe()
931 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) in stm32_sai_dai_probe()
935 if (STM_SAI_IS_CAPTURE(sai)) in stm32_sai_dai_probe()
939 if (sai->sync == SAI_SYNC_EXTERNAL) { in stm32_sai_dai_probe()
941 sai->pdata->set_sync(sai->pdata, sai->np_sync_provider, in stm32_sai_dai_probe()
942 sai->synco, sai->synci); in stm32_sai_dai_probe()
946 cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync); in stm32_sai_dai_probe()
948 return regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1); in stm32_sai_dai_probe()
968 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_pcm_process_spdif() local
972 unsigned int frm_cnt = sai->spdif_frm_cnt; in stm32_sai_pcm_process_spdif()
982 if (sai->iec958.status[byte] & mask) in stm32_sai_pcm_process_spdif()
992 sai->spdif_frm_cnt = frm_cnt; in stm32_sai_pcm_process_spdif()
1069 .name = "stm32-sai",
1073 { .compatible = "st,stm32-sai-sub-a",
1075 { .compatible = "st,stm32-sai-sub-b",
1082 struct stm32_sai_sub_data *sai) in stm32_sai_sub_parse_of() argument
1098 sai->phys_addr = res->start; in stm32_sai_sub_parse_of()
1100 sai->regmap_config = &stm32_sai_sub_regmap_config_f4; in stm32_sai_sub_parse_of()
1102 if (STM_SAI_IS_H7(sai->pdata) && STM_SAI_IS_SUB_A(sai)) in stm32_sai_sub_parse_of()
1103 sai->regmap_config = &stm32_sai_sub_regmap_config_h7; in stm32_sai_sub_parse_of()
1105 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "sai_ck", in stm32_sai_sub_parse_of()
1106 base, sai->regmap_config); in stm32_sai_sub_parse_of()
1107 if (IS_ERR(sai->regmap)) { in stm32_sai_sub_parse_of()
1109 return PTR_ERR(sai->regmap); in stm32_sai_sub_parse_of()
1114 sai->dir = SNDRV_PCM_STREAM_PLAYBACK; in stm32_sai_sub_parse_of()
1116 sai->dir = SNDRV_PCM_STREAM_CAPTURE; in stm32_sai_sub_parse_of()
1123 sai->spdif = false; in stm32_sai_sub_parse_of()
1125 if (!STM_SAI_HAS_SPDIF(sai) || in stm32_sai_sub_parse_of()
1126 sai->dir == SNDRV_PCM_STREAM_CAPTURE) { in stm32_sai_sub_parse_of()
1130 stm32_sai_init_iec958_status(sai); in stm32_sai_sub_parse_of()
1131 sai->spdif = true; in stm32_sai_sub_parse_of()
1132 sai->master = true; in stm32_sai_sub_parse_of()
1143 sai->sync = SAI_SYNC_NONE; in stm32_sai_sub_parse_of()
1152 sai->np_sync_provider = of_get_parent(args.np); in stm32_sai_sub_parse_of()
1153 if (!sai->np_sync_provider) { in stm32_sai_sub_parse_of()
1160 sai->sync = SAI_SYNC_INTERNAL; in stm32_sai_sub_parse_of()
1161 if (sai->np_sync_provider != sai->pdata->pdev->dev.of_node) { in stm32_sai_sub_parse_of()
1162 if (!STM_SAI_HAS_EXT_SYNC(sai)) { in stm32_sai_sub_parse_of()
1168 sai->sync = SAI_SYNC_EXTERNAL; in stm32_sai_sub_parse_of()
1170 sai->synci = args.args[0]; in stm32_sai_sub_parse_of()
1171 if (sai->synci < 1 || in stm32_sai_sub_parse_of()
1172 (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) { in stm32_sai_sub_parse_of()
1173 dev_err(&pdev->dev, "Wrong SAI index\n"); in stm32_sai_sub_parse_of()
1179 "st,stm32-sai-sub-a") >= 0) in stm32_sai_sub_parse_of()
1180 sai->synco = STM_SAI_SYNC_OUT_A; in stm32_sai_sub_parse_of()
1183 "st,stm32-sai-sub-b") >= 0) in stm32_sai_sub_parse_of()
1184 sai->synco = STM_SAI_SYNC_OUT_B; in stm32_sai_sub_parse_of()
1186 if (!sai->synco) { in stm32_sai_sub_parse_of()
1187 dev_err(&pdev->dev, "Unknown SAI sub-block\n"); in stm32_sai_sub_parse_of()
1198 sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); in stm32_sai_sub_parse_of()
1199 if (IS_ERR(sai->sai_ck)) { in stm32_sai_sub_parse_of()
1201 return PTR_ERR(sai->sai_ck); in stm32_sai_sub_parse_of()
1208 struct stm32_sai_sub_data *sai) in stm32_sai_sub_dais_init() argument
1210 sai->cpu_dai_drv = devm_kzalloc(&pdev->dev, in stm32_sai_sub_dais_init()
1213 if (!sai->cpu_dai_drv) in stm32_sai_sub_dais_init()
1216 if (STM_SAI_IS_PLAYBACK(sai)) { in stm32_sai_sub_dais_init()
1217 memcpy(sai->cpu_dai_drv, &stm32_sai_playback_dai, in stm32_sai_sub_dais_init()
1219 sai->cpu_dai_drv->playback.stream_name = sai->cpu_dai_drv->name; in stm32_sai_sub_dais_init()
1221 memcpy(sai->cpu_dai_drv, &stm32_sai_capture_dai, in stm32_sai_sub_dais_init()
1223 sai->cpu_dai_drv->capture.stream_name = sai->cpu_dai_drv->name; in stm32_sai_sub_dais_init()
1225 sai->cpu_dai_drv->name = dev_name(&pdev->dev); in stm32_sai_sub_dais_init()
1232 struct stm32_sai_sub_data *sai; in stm32_sai_sub_probe() local
1237 sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); in stm32_sai_sub_probe()
1238 if (!sai) in stm32_sai_sub_probe()
1244 sai->id = (uintptr_t)of_id->data; in stm32_sai_sub_probe()
1246 sai->pdev = pdev; in stm32_sai_sub_probe()
1247 mutex_init(&sai->ctrl_lock); in stm32_sai_sub_probe()
1248 platform_set_drvdata(pdev, sai); in stm32_sai_sub_probe()
1250 sai->pdata = dev_get_drvdata(pdev->dev.parent); in stm32_sai_sub_probe()
1251 if (!sai->pdata) { in stm32_sai_sub_probe()
1256 ret = stm32_sai_sub_parse_of(pdev, sai); in stm32_sai_sub_probe()
1260 ret = stm32_sai_sub_dais_init(pdev, sai); in stm32_sai_sub_probe()
1264 ret = devm_request_irq(&pdev->dev, sai->pdata->irq, stm32_sai_isr, in stm32_sai_sub_probe()
1265 IRQF_SHARED, dev_name(&pdev->dev), sai); in stm32_sai_sub_probe()
1272 sai->cpu_dai_drv, 1); in stm32_sai_sub_probe()
1276 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) in stm32_sai_sub_probe()
1290 .name = "st,stm32-sai-sub",
1298 MODULE_DESCRIPTION("STM32 Soc SAI sub-block Interface");
1300 MODULE_ALIAS("platform:st,stm32-sai-sub");