Lines Matching full:sai
3 * STM32 ALSA SoC Digital Audio Interface (SAI) driver.
68 * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
70 * @regmap: SAI register map pointer
71 * @regmap_config: SAI sub block register map configuration pointer
76 * @pdata: SAI block parent data pointer
78 * @sai_ck: kernel clock feeding the SAI clock generator
79 * @sai_mclk: master clock from SAI mclk provider
80 * @phys_addr: SAI registers physical base address
81 * @mclk_rate: SAI block master clock frequency (Hz). set at init
82 * @id: SAI sub block id corresponding to sub-block A or B
83 * @dir: SAI block direction (playback or capture). set at init
84 * @master: SAI block mode flag. (true=master, false=slave) set at init
85 * @spdif: SAI S/PDIF iec60958 mode flag. set at init
86 * @sai_ck_used: flag set while exclusivity on SAI kernel clock is active
87 * @fmt: SAI block format. relevant only for custom protocols. 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)
100 * @set_sai_ck_rate: set SAI kernel clock rate
101 * @put_sai_ck_rate: put SAI kernel clock rate
135 int (*set_sai_ck_rate)(struct stm32_sai_sub_data *sai, unsigned int rate);
136 void (*put_sai_ck_rate)(struct stm32_sai_sub_data *sai);
195 static int stm32_sai_sub_reg_up(struct stm32_sai_sub_data *sai, 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()
212 static int stm32_sai_sub_reg_wr(struct stm32_sai_sub_data *sai, 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()
229 static int stm32_sai_sub_reg_rd(struct stm32_sai_sub_data *sai, in stm32_sai_sub_reg_rd() argument
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()
281 struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol); in snd_pcm_iec958_get() local
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()
293 struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol); in snd_pcm_iec958_put() local
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()
321 static int stm32_sai_get_clk_div(struct stm32_sai_sub_data *sai, in stm32_sai_get_clk_div() argument
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()
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()
343 static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai, in stm32_sai_set_clk_div() argument
346 int version = sai->pdata->conf.version; in stm32_sai_set_clk_div()
350 dev_err(&sai->pdev->dev, "Divider %d out of range\n", div); 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()
381 static int stm32_sai_set_parent_clk(struct stm32_sai_sub_data *sai, in stm32_sai_set_parent_clk() argument
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()
400 static void stm32_sai_put_parent_rate(struct stm32_sai_sub_data *sai) in stm32_sai_put_parent_rate() argument
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()
408 static int stm32_sai_set_parent_rate(struct stm32_sai_sub_data *sai, in stm32_sai_set_parent_rate() argument
411 struct platform_device *pdev = sai->pdev; in stm32_sai_set_parent_rate()
422 * Where FRL=[8..256], MCKDIV=[1..n] (n depends on SAI version) in stm32_sai_set_parent_rate()
431 if (!sai->sai_mclk && !STM_SAI_PROTOCOL_IS_SPDIF(sai)) in stm32_sai_set_parent_rate()
432 sai_ck_max_rate /= DIV_ROUND_CLOSEST(256, roundup_pow_of_two(sai->fs_length)); in stm32_sai_set_parent_rate()
435 * Request exclusivity, as the clock is shared by SAI sub-blocks and by in stm32_sai_set_parent_rate()
436 * some SAI instances. This allows to ensure that the rate cannot be in stm32_sai_set_parent_rate()
439 clk_rate_exclusive_get(sai->sai_ck); in stm32_sai_set_parent_rate()
440 sai->sai_ck_used = true; in stm32_sai_set_parent_rate()
446 sai_curr_rate = clk_get_rate(sai->sai_ck); in stm32_sai_set_parent_rate()
459 sai_new_rate = clk_round_rate(sai->sai_ck, sai_ck_rate); in stm32_sai_set_parent_rate()
461 ret = clk_set_rate(sai->sai_ck, sai_ck_rate); in stm32_sai_set_parent_rate()
481 stm32_sai_put_parent_rate(sai); in stm32_sai_set_parent_rate()
490 struct stm32_sai_sub_data *sai = mclk->sai_data; in stm32_sai_mclk_round_rate() local
493 div = stm32_sai_get_clk_div(sai, *prate, rate); in stm32_sai_mclk_round_rate()
514 struct stm32_sai_sub_data *sai = mclk->sai_data; in stm32_sai_mclk_set_rate() local
517 div = stm32_sai_get_clk_div(sai, parent_rate, rate); in stm32_sai_mclk_set_rate()
521 ret = stm32_sai_set_clk_div(sai, div); in stm32_sai_mclk_set_rate()
533 struct stm32_sai_sub_data *sai = mclk->sai_data; in stm32_sai_mclk_enable() local
535 dev_dbg(&sai->pdev->dev, "Enable master clock\n"); in stm32_sai_mclk_enable()
537 return stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, in stm32_sai_mclk_enable()
544 struct stm32_sai_sub_data *sai = mclk->sai_data; in stm32_sai_mclk_disable() local
546 dev_dbg(&sai->pdev->dev, "Disable master clock\n"); in stm32_sai_mclk_disable()
548 stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, SAI_XCR1_MCKEN, 0); in stm32_sai_mclk_disable()
559 static int stm32_sai_add_mclk_provider(struct stm32_sai_sub_data *sai) in stm32_sai_add_mclk_provider() argument
563 struct device *dev = &sai->pdev->dev; in stm32_sai_add_mclk_provider()
564 const char *pname = __clk_get_name(sai->sai_ck); in stm32_sai_add_mclk_provider()
586 STM_SAI_IS_SUB_A(sai) ? strcat(p, "a_mclk") : strcat(p, "b_mclk"); in stm32_sai_add_mclk_provider()
589 mclk->sai_data = sai; in stm32_sai_add_mclk_provider()
593 ret = devm_clk_hw_register(&sai->pdev->dev, hw); in stm32_sai_add_mclk_provider()
598 sai->sai_mclk = hw->clk; in stm32_sai_add_mclk_provider()
606 struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid; in stm32_sai_isr() local
607 struct platform_device *pdev = sai->pdev; in stm32_sai_isr()
611 stm32_sai_sub_reg_rd(sai, STM_SAI_IMR_REGX, &imr); in stm32_sai_isr()
612 stm32_sai_sub_reg_rd(sai, STM_SAI_SR_REGX, &sr); in stm32_sai_isr()
618 stm32_sai_sub_reg_wr(sai, STM_SAI_CLRFR_REGX, SAI_XCLRFR_MASK, in stm32_sai_isr()
621 if (!sai->substream) { in stm32_sai_isr()
628 STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun"); in stm32_sai_isr()
653 spin_lock(&sai->irq_lock); in stm32_sai_isr()
654 if (status != SNDRV_PCM_STATE_RUNNING && sai->substream) in stm32_sai_isr()
655 snd_pcm_stop_xrun(sai->substream); in stm32_sai_isr()
656 spin_unlock(&sai->irq_lock); in stm32_sai_isr()
664 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_sysclk() local
667 if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) { in stm32_sai_set_sysclk()
668 ret = stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, in stm32_sai_set_sysclk()
677 if (sai->mclk_rate) { in stm32_sai_set_sysclk()
678 clk_rate_exclusive_put(sai->sai_mclk); in stm32_sai_set_sysclk()
679 sai->mclk_rate = 0; in stm32_sai_set_sysclk()
682 if (sai->put_sai_ck_rate) in stm32_sai_set_sysclk()
683 sai->put_sai_ck_rate(sai); in stm32_sai_set_sysclk()
688 /* If master clock is used, configure SAI kernel clock now */ in stm32_sai_set_sysclk()
689 ret = sai->set_sai_ck_rate(sai, freq); in stm32_sai_set_sysclk()
693 ret = clk_set_rate_exclusive(sai->sai_mclk, freq); in stm32_sai_set_sysclk()
702 dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); in stm32_sai_set_sysclk()
703 sai->mclk_rate = freq; in stm32_sai_set_sysclk()
712 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_dai_tdm_slot() local
715 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_set_dai_tdm_slot()
740 if (STM_SAI_IS_PLAYBACK(sai)) { in stm32_sai_set_dai_tdm_slot()
741 sai->slot_mask = tx_mask; in stm32_sai_set_dai_tdm_slot()
745 if (STM_SAI_IS_CAPTURE(sai)) { in stm32_sai_set_dai_tdm_slot()
746 sai->slot_mask = rx_mask; in stm32_sai_set_dai_tdm_slot()
752 stm32_sai_sub_reg_up(sai, STM_SAI_SLOTR_REGX, slotr_mask, slotr); in stm32_sai_set_dai_tdm_slot()
754 sai->slot_width = slot_width; in stm32_sai_set_dai_tdm_slot()
755 sai->slots = slots; in stm32_sai_set_dai_tdm_slot()
762 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_dai_fmt() local
774 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_set_dai_fmt()
834 stm32_sai_sub_reg_up(sai, STM_SAI_FRCR_REGX, frcr_mask, frcr); in stm32_sai_set_dai_fmt()
841 sai->master = false; in stm32_sai_set_dai_fmt()
844 sai->master = true; in stm32_sai_set_dai_fmt()
852 /* Set slave mode if sub-block is synchronized with another SAI */ in stm32_sai_set_dai_fmt()
853 if (sai->sync) { in stm32_sai_set_dai_fmt()
854 dev_dbg(cpu_dai->dev, "Synchronized SAI configured as slave\n"); in stm32_sai_set_dai_fmt()
856 sai->master = false; in stm32_sai_set_dai_fmt()
862 ret = stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, cr1_mask, cr1); in stm32_sai_set_dai_fmt()
868 sai->fmt = fmt; in stm32_sai_set_dai_fmt()
876 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_startup() local
880 spin_lock_irqsave(&sai->irq_lock, flags); in stm32_sai_startup()
881 sai->substream = substream; in stm32_sai_startup()
882 spin_unlock_irqrestore(&sai->irq_lock, flags); in stm32_sai_startup()
884 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_startup()
892 ret = clk_prepare_enable(sai->sai_ck); in stm32_sai_startup()
899 stm32_sai_sub_reg_wr(sai, STM_SAI_CLRFR_REGX, in stm32_sai_startup()
903 if (STM_SAI_IS_CAPTURE(sai)) { in stm32_sai_startup()
904 stm32_sai_sub_reg_rd(sai, STM_SAI_CR2_REGX, &cr2); in stm32_sai_startup()
909 if (sai->master) in stm32_sai_startup()
914 stm32_sai_sub_reg_up(sai, STM_SAI_IMR_REGX, in stm32_sai_startup()
924 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_config() local
929 * SAI fifo threshold is set to half fifo, to keep enough space in stm32_sai_set_config()
932 stm32_sai_sub_reg_wr(sai, STM_SAI_CR2_REGX, in stm32_sai_set_config()
938 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_set_config()
939 sai->spdif_frm_cnt = 0; in stm32_sai_set_config()
961 if ((sai->slots == 2) && (params_channels(params) == 1)) in stm32_sai_set_config()
964 ret = stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, cr1_mask, cr1); in stm32_sai_set_config()
975 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_slots() local
978 stm32_sai_sub_reg_rd(sai, STM_SAI_SLOTR_REGX, &slotr); in stm32_sai_set_slots()
986 sai->slot_width = sai->data_size; in stm32_sai_set_slots()
988 if (sai->slot_width < sai->data_size) { in stm32_sai_set_slots()
991 sai->data_size); in stm32_sai_set_slots()
996 if (!sai->slots) in stm32_sai_set_slots()
997 sai->slots = 2; in stm32_sai_set_slots()
1000 stm32_sai_sub_reg_up(sai, STM_SAI_SLOTR_REGX, in stm32_sai_set_slots()
1002 SAI_XSLOTR_NBSLOT_SET((sai->slots - 1))); in stm32_sai_set_slots()
1006 sai->slot_mask = (1 << sai->slots) - 1; in stm32_sai_set_slots()
1007 stm32_sai_sub_reg_up(sai, in stm32_sai_set_slots()
1009 SAI_XSLOTR_SLOTEN_SET(sai->slot_mask)); in stm32_sai_set_slots()
1013 sai->slots, sai->slot_width); in stm32_sai_set_slots()
1020 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_set_frame() local
1024 format = sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK; in stm32_sai_set_frame()
1025 sai->fs_length = sai->slot_width * sai->slots; in stm32_sai_set_frame()
1027 fs_active = sai->fs_length / 2; in stm32_sai_set_frame()
1032 frcr = SAI_XFRCR_FRL_SET((sai->fs_length - 1)); in stm32_sai_set_frame()
1037 sai->fs_length, fs_active); in stm32_sai_set_frame()
1039 stm32_sai_sub_reg_up(sai, STM_SAI_FRCR_REGX, frcr_mask, frcr); in stm32_sai_set_frame()
1041 if ((sai->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_LSB) { in stm32_sai_set_frame()
1042 offset = sai->slot_width - sai->data_size; in stm32_sai_set_frame()
1044 stm32_sai_sub_reg_up(sai, STM_SAI_SLOTR_REGX, in stm32_sai_set_frame()
1050 static void stm32_sai_init_iec958_status(struct stm32_sai_sub_data *sai) in stm32_sai_init_iec958_status() argument
1052 unsigned char *cs = sai->iec958.status; in stm32_sai_init_iec958_status()
1060 static void stm32_sai_set_iec958_status(struct stm32_sai_sub_data *sai, in stm32_sai_set_iec958_status() argument
1067 mutex_lock(&sai->ctrl_lock); in stm32_sai_set_iec958_status()
1070 sai->iec958.status[3] = IEC958_AES3_CON_FS_22050; in stm32_sai_set_iec958_status()
1073 sai->iec958.status[3] = IEC958_AES3_CON_FS_44100; in stm32_sai_set_iec958_status()
1076 sai->iec958.status[3] = IEC958_AES3_CON_FS_88200; in stm32_sai_set_iec958_status()
1079 sai->iec958.status[3] = IEC958_AES3_CON_FS_176400; in stm32_sai_set_iec958_status()
1082 sai->iec958.status[3] = IEC958_AES3_CON_FS_24000; in stm32_sai_set_iec958_status()
1085 sai->iec958.status[3] = IEC958_AES3_CON_FS_48000; in stm32_sai_set_iec958_status()
1088 sai->iec958.status[3] = IEC958_AES3_CON_FS_96000; in stm32_sai_set_iec958_status()
1091 sai->iec958.status[3] = IEC958_AES3_CON_FS_192000; in stm32_sai_set_iec958_status()
1094 sai->iec958.status[3] = IEC958_AES3_CON_FS_32000; in stm32_sai_set_iec958_status()
1097 sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID; in stm32_sai_set_iec958_status()
1100 mutex_unlock(&sai->ctrl_lock); in stm32_sai_set_iec958_status()
1106 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_configure_clock() local
1112 if (!sai->sai_mclk) { in stm32_sai_configure_clock()
1113 ret = sai->set_sai_ck_rate(sai, rate); in stm32_sai_configure_clock()
1117 sai_clk_rate = clk_get_rate(sai->sai_ck); in stm32_sai_configure_clock()
1119 if (STM_SAI_IS_F4(sai->pdata)) { in stm32_sai_configure_clock()
1127 if (!sai->mclk_rate) in stm32_sai_configure_clock()
1130 if (2 * sai_clk_rate >= 3 * sai->mclk_rate) { in stm32_sai_configure_clock()
1131 div = stm32_sai_get_clk_div(sai, sai_clk_rate, in stm32_sai_configure_clock()
1132 2 * sai->mclk_rate); in stm32_sai_configure_clock()
1146 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_configure_clock()
1147 div = stm32_sai_get_clk_div(sai, sai_clk_rate, in stm32_sai_configure_clock()
1152 if (sai->mclk_rate) { in stm32_sai_configure_clock()
1153 mclk_ratio = sai->mclk_rate / rate; in stm32_sai_configure_clock()
1163 stm32_sai_sub_reg_up(sai, in stm32_sai_configure_clock()
1167 div = stm32_sai_get_clk_div(sai, sai_clk_rate, in stm32_sai_configure_clock()
1168 sai->mclk_rate); in stm32_sai_configure_clock()
1173 den = sai->fs_length * params_rate(params); in stm32_sai_configure_clock()
1174 div = stm32_sai_get_clk_div(sai, sai_clk_rate, in stm32_sai_configure_clock()
1182 return stm32_sai_set_clk_div(sai, div); in stm32_sai_configure_clock()
1189 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_hw_params() local
1192 sai->data_size = params_width(params); in stm32_sai_hw_params()
1194 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_hw_params()
1197 stm32_sai_set_iec958_status(sai, substream->runtime); in stm32_sai_hw_params()
1209 if (sai->master) in stm32_sai_hw_params()
1218 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_trigger() local
1225 dev_dbg(cpu_dai->dev, "Enable DMA and SAI\n"); in stm32_sai_trigger()
1227 stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, in stm32_sai_trigger()
1230 /* Enable SAI */ in stm32_sai_trigger()
1231 ret = stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, in stm32_sai_trigger()
1239 dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n"); in stm32_sai_trigger()
1241 stm32_sai_sub_reg_up(sai, STM_SAI_IMR_REGX, in stm32_sai_trigger()
1244 stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, in stm32_sai_trigger()
1248 ret = stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, in stm32_sai_trigger()
1254 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) in stm32_sai_trigger()
1255 sai->spdif_frm_cnt = 0; in stm32_sai_trigger()
1267 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); in stm32_sai_shutdown() local
1270 stm32_sai_sub_reg_up(sai, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0); in stm32_sai_shutdown()
1272 clk_disable_unprepare(sai->sai_ck); in stm32_sai_shutdown()
1279 if (!sai->sai_mclk && sai->put_sai_ck_rate) in stm32_sai_shutdown()
1280 sai->put_sai_ck_rate(sai); in stm32_sai_shutdown()
1282 spin_lock_irqsave(&sai->irq_lock, flags); in stm32_sai_shutdown()
1283 sai->substream = NULL; in stm32_sai_shutdown()
1284 spin_unlock_irqrestore(&sai->irq_lock, flags); in stm32_sai_shutdown()
1290 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_pcm_new() local
1293 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { in stm32_sai_pcm_new()
1294 dev_dbg(&sai->pdev->dev, "%s: register iec controls", __func__); in stm32_sai_pcm_new()
1296 return snd_ctl_add(rtd->pcm->card, snd_ctl_new1(&knew, sai)); in stm32_sai_pcm_new()
1304 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_dai_probe() local
1307 sai->cpu_dai = cpu_dai; in stm32_sai_dai_probe()
1309 sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX); in stm32_sai_dai_probe()
1315 sai->dma_params.maxburst = 4; in stm32_sai_dai_probe()
1316 if (sai->pdata->conf.fifo_size < 8 || sai->pdata->conf.no_dma_burst) in stm32_sai_dai_probe()
1317 sai->dma_params.maxburst = 1; in stm32_sai_dai_probe()
1319 sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; in stm32_sai_dai_probe()
1321 if (STM_SAI_IS_PLAYBACK(sai)) in stm32_sai_dai_probe()
1322 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params, NULL); in stm32_sai_dai_probe()
1324 snd_soc_dai_init_dma_data(cpu_dai, NULL, &sai->dma_params); in stm32_sai_dai_probe()
1327 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) in stm32_sai_dai_probe()
1331 if (STM_SAI_IS_CAPTURE(sai)) in stm32_sai_dai_probe()
1335 if (sai->sync == SAI_SYNC_EXTERNAL) { in stm32_sai_dai_probe()
1337 ret = sai->pdata->set_sync(sai->pdata, sai->np_sync_provider, in stm32_sai_dai_probe()
1338 sai->synco, sai->synci); in stm32_sai_dai_probe()
1344 cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync); in stm32_sai_dai_probe()
1346 return stm32_sai_sub_reg_up(sai, STM_SAI_CR1_REGX, cr1_mask, cr1); in stm32_sai_dai_probe()
1379 struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); in stm32_sai_pcm_process_spdif() local
1383 unsigned int frm_cnt = sai->spdif_frm_cnt; in stm32_sai_pcm_process_spdif()
1393 if (sai->iec958.status[byte] & mask) in stm32_sai_pcm_process_spdif()
1403 sai->spdif_frm_cnt = frm_cnt; in stm32_sai_pcm_process_spdif()
1473 .name = "stm32-sai",
1478 { .compatible = "st,stm32-sai-sub-a",
1480 { .compatible = "st,stm32-sai-sub-b",
1487 struct stm32_sai_sub_data *sai) in stm32_sai_sub_parse_of() argument
1502 sai->phys_addr = res->start; in stm32_sai_sub_parse_of()
1504 sai->regmap_config = &stm32_sai_sub_regmap_config_f4; in stm32_sai_sub_parse_of()
1506 if (STM_SAI_HAS_PDM(sai) && STM_SAI_IS_SUB_A(sai)) in stm32_sai_sub_parse_of()
1507 sai->regmap_config = &stm32_sai_sub_regmap_config_h7; in stm32_sai_sub_parse_of()
1511 * can lead to circular locking issue with sai master clock provider. in stm32_sai_sub_parse_of()
1514 sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, in stm32_sai_sub_parse_of()
1515 sai->regmap_config); in stm32_sai_sub_parse_of()
1516 if (IS_ERR(sai->regmap)) in stm32_sai_sub_parse_of()
1517 return dev_err_probe(&pdev->dev, PTR_ERR(sai->regmap), in stm32_sai_sub_parse_of()
1522 sai->dir = SNDRV_PCM_STREAM_PLAYBACK; in stm32_sai_sub_parse_of()
1524 sai->dir = SNDRV_PCM_STREAM_CAPTURE; in stm32_sai_sub_parse_of()
1531 sai->spdif = false; in stm32_sai_sub_parse_of()
1533 if (!STM_SAI_HAS_SPDIF(sai) || in stm32_sai_sub_parse_of()
1534 sai->dir == SNDRV_PCM_STREAM_CAPTURE) { in stm32_sai_sub_parse_of()
1538 stm32_sai_init_iec958_status(sai); in stm32_sai_sub_parse_of()
1539 sai->spdif = true; in stm32_sai_sub_parse_of()
1540 sai->master = true; in stm32_sai_sub_parse_of()
1551 sai->sync = SAI_SYNC_NONE; in stm32_sai_sub_parse_of()
1559 sai->np_sync_provider = of_get_parent(args.np); in stm32_sai_sub_parse_of()
1560 if (!sai->np_sync_provider) { in stm32_sai_sub_parse_of()
1567 sai->sync = SAI_SYNC_INTERNAL; in stm32_sai_sub_parse_of()
1568 if (sai->np_sync_provider != sai->pdata->pdev->dev.of_node) { in stm32_sai_sub_parse_of()
1569 if (!STM_SAI_HAS_EXT_SYNC(sai)) { in stm32_sai_sub_parse_of()
1575 sai->sync = SAI_SYNC_EXTERNAL; in stm32_sai_sub_parse_of()
1577 sai->synci = args.args[0]; in stm32_sai_sub_parse_of()
1578 if (sai->synci < 1 || in stm32_sai_sub_parse_of()
1579 (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) { in stm32_sai_sub_parse_of()
1580 dev_err(&pdev->dev, "Wrong SAI index\n"); in stm32_sai_sub_parse_of()
1586 "st,stm32-sai-sub-a") >= 0) in stm32_sai_sub_parse_of()
1587 sai->synco = STM_SAI_SYNC_OUT_A; in stm32_sai_sub_parse_of()
1590 "st,stm32-sai-sub-b") >= 0) in stm32_sai_sub_parse_of()
1591 sai->synco = STM_SAI_SYNC_OUT_B; in stm32_sai_sub_parse_of()
1593 if (!sai->synco) { in stm32_sai_sub_parse_of()
1594 dev_err(&pdev->dev, "Unknown SAI sub-block\n"); in stm32_sai_sub_parse_of()
1605 sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); in stm32_sai_sub_parse_of()
1606 if (IS_ERR(sai->sai_ck)) in stm32_sai_sub_parse_of()
1607 return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck), in stm32_sai_sub_parse_of()
1610 ret = clk_prepare(sai->pdata->pclk); in stm32_sai_sub_parse_of()
1614 if (STM_SAI_IS_F4(sai->pdata)) in stm32_sai_sub_parse_of()
1619 ret = stm32_sai_add_mclk_provider(sai); in stm32_sai_sub_parse_of()
1623 sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK"); in stm32_sai_sub_parse_of()
1624 if (IS_ERR(sai->sai_mclk)) in stm32_sai_sub_parse_of()
1625 return PTR_ERR(sai->sai_mclk); in stm32_sai_sub_parse_of()
1633 struct stm32_sai_sub_data *sai; in stm32_sai_sub_probe() local
1637 sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); in stm32_sai_sub_probe()
1638 if (!sai) in stm32_sai_sub_probe()
1641 sai->id = (uintptr_t)device_get_match_data(&pdev->dev); in stm32_sai_sub_probe()
1643 sai->pdev = pdev; in stm32_sai_sub_probe()
1644 mutex_init(&sai->ctrl_lock); in stm32_sai_sub_probe()
1645 spin_lock_init(&sai->irq_lock); in stm32_sai_sub_probe()
1646 platform_set_drvdata(pdev, sai); in stm32_sai_sub_probe()
1648 sai->pdata = dev_get_drvdata(pdev->dev.parent); in stm32_sai_sub_probe()
1649 if (!sai->pdata) { in stm32_sai_sub_probe()
1654 if (sai->pdata->conf.get_sai_ck_parent) { in stm32_sai_sub_probe()
1655 sai->set_sai_ck_rate = stm32_sai_set_parent_clk; in stm32_sai_sub_probe()
1657 sai->set_sai_ck_rate = stm32_sai_set_parent_rate; in stm32_sai_sub_probe()
1658 sai->put_sai_ck_rate = stm32_sai_put_parent_rate; in stm32_sai_sub_probe()
1661 ret = stm32_sai_sub_parse_of(pdev, sai); in stm32_sai_sub_probe()
1665 if (STM_SAI_IS_PLAYBACK(sai)) in stm32_sai_sub_probe()
1666 sai->cpu_dai_drv = stm32_sai_playback_dai; in stm32_sai_sub_probe()
1668 sai->cpu_dai_drv = stm32_sai_capture_dai; in stm32_sai_sub_probe()
1669 sai->cpu_dai_drv.name = dev_name(&pdev->dev); in stm32_sai_sub_probe()
1671 ret = devm_request_irq(&pdev->dev, sai->pdata->irq, stm32_sai_isr, in stm32_sai_sub_probe()
1672 IRQF_SHARED, dev_name(&pdev->dev), sai); in stm32_sai_sub_probe()
1678 if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) in stm32_sai_sub_probe()
1686 &sai->cpu_dai_drv, 1); in stm32_sai_sub_probe()
1699 struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev); in stm32_sai_sub_remove() local
1701 clk_unprepare(sai->pdata->pclk); in stm32_sai_sub_remove()
1710 struct stm32_sai_sub_data *sai = dev_get_drvdata(dev); in stm32_sai_sub_suspend() local
1713 ret = clk_enable(sai->pdata->pclk); in stm32_sai_sub_suspend()
1717 regcache_cache_only(sai->regmap, true); in stm32_sai_sub_suspend()
1718 regcache_mark_dirty(sai->regmap); in stm32_sai_sub_suspend()
1720 clk_disable(sai->pdata->pclk); in stm32_sai_sub_suspend()
1727 struct stm32_sai_sub_data *sai = dev_get_drvdata(dev); in stm32_sai_sub_resume() local
1730 ret = clk_enable(sai->pdata->pclk); in stm32_sai_sub_resume()
1734 regcache_cache_only(sai->regmap, false); in stm32_sai_sub_resume()
1735 ret = regcache_sync(sai->regmap); in stm32_sai_sub_resume()
1737 clk_disable(sai->pdata->pclk); in stm32_sai_sub_resume()
1749 .name = "st,stm32-sai-sub",
1759 MODULE_DESCRIPTION("STM32 Soc SAI sub-block Interface");
1761 MODULE_ALIAS("platform:st,stm32-sai-sub");