Lines Matching +full:dai +full:- +full:controller

1 // SPDX-License-Identifier: GPL-2.0
3 // ALSA SoC Audio Layer - Samsung I2S Controller driver
8 #include <dt-bindings/sound/samsung-i2s.h>
12 #include <linux/clk-provider.h>
21 #include <linux/platform_data/asoc-s3c.h>
26 #include "i2s-regs.h"
52 struct snd_soc_dai *dai);
54 struct snd_soc_dai *dai);
58 /* Platform device for this DAI */
73 #define DAI_OPENED (1 << 0) /* DAI is opened */
74 #define DAI_MANAGER (1 << 1) /* DAI is the manager */
77 /* Driver for this DAI */
97 struct i2s_dai *dai; member
101 /* The I2S controller's core clock */
117 struct snd_soc_dai *dai);
119 struct snd_soc_dai *dai);
136 /* Returns true if this is the 'overlay' stereo DAI */
139 return i2s->drv->id == SAMSUNG_I2S_ID_SECONDARY; in is_secondary()
142 /* If this interface of the controller is transmitting data */
150 active = readl(i2s->priv->addr + I2SCON); in tx_active()
160 /* Return pointer to the other DAI */
163 return i2s->pri_dai ? : i2s->sec_dai; in get_other_dai()
166 /* If the other interface of the controller is transmitting data */
174 /* If any interface of the controller is transmitting data */
180 /* If this interface of the controller is receiving data */
188 active = readl(i2s->priv->addr + I2SCON) & CON_RXDMA_ACTIVE; in rx_active()
193 /* If the other interface of the controller is receiving data */
201 /* If any interface of the controller is receiving data */
207 /* If the other DAI is transmitting or receiving data */
213 /* If this DAI is transmitting or receiving data */
219 /* If the controller is active anyway */
225 static inline struct i2s_dai *to_info(struct snd_soc_dai *dai) in to_info() argument
227 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in to_info()
229 return &priv->dai[dai->id - 1]; in to_info()
234 if (i2s && (i2s->mode & DAI_OPENED)) in is_opened()
242 if (is_opened(i2s) && (i2s->mode & DAI_MANAGER)) in is_manager()
251 struct samsung_i2s_priv *priv = i2s->priv; in get_rfs()
254 rfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->rfs_off; in get_rfs()
255 rfs &= priv->variant_regs->rfs_mask; in get_rfs()
272 struct samsung_i2s_priv *priv = i2s->priv; in set_rfs()
273 u32 mod = readl(priv->addr + I2SMOD); in set_rfs()
274 int rfs_shift = priv->variant_regs->rfs_off; in set_rfs()
276 mod &= ~(priv->variant_regs->rfs_mask << rfs_shift); in set_rfs()
305 writel(mod, priv->addr + I2SMOD); in set_rfs()
308 /* Read bit-clock of I2S (in multiples of LRCLK) */
311 struct samsung_i2s_priv *priv = i2s->priv; in get_bfs()
314 bfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->bfs_off; in get_bfs()
315 bfs &= priv->variant_regs->bfs_mask; in get_bfs()
330 /* Write bit-clock of I2S (in multiples of LRCLK) */
333 struct samsung_i2s_priv *priv = i2s->priv; in set_bfs()
334 u32 mod = readl(priv->addr + I2SMOD); in set_bfs()
335 int tdm = priv->quirks & QUIRK_SUPPORTS_TDM; in set_bfs()
336 int bfs_shift = priv->variant_regs->bfs_off; in set_bfs()
338 /* Non-TDM I2S controllers do not support BCLK > 48 * FS */ in set_bfs()
340 dev_err(&i2s->pdev->dev, "Unsupported BCLK divider\n"); in set_bfs()
344 mod &= ~(priv->variant_regs->bfs_mask << bfs_shift); in set_bfs()
375 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); in set_bfs()
379 writel(mod, priv->addr + I2SMOD); in set_bfs()
385 int blc = readl(i2s->priv->addr + I2SMOD); in get_blc()
399 struct samsung_i2s_priv *priv = i2s->priv; in i2s_txctrl()
400 void __iomem *addr = priv->addr; in i2s_txctrl()
401 int txr_off = priv->variant_regs->txr_off; in i2s_txctrl()
450 struct samsung_i2s_priv *priv = i2s->priv; in i2s_rxctrl()
451 void __iomem *addr = priv->addr; in i2s_rxctrl()
452 int txr_off = priv->variant_regs->txr_off; in i2s_rxctrl()
488 fic = i2s->priv->addr + I2SFICS; in i2s_fifo()
490 fic = i2s->priv->addr + I2SFIC; in i2s_fifo()
497 while (--val) in i2s_fifo()
503 static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, in i2s_set_sysclk() argument
506 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in i2s_set_sysclk()
507 struct i2s_dai *i2s = to_info(dai); in i2s_set_sysclk()
509 const struct samsung_i2s_variant_regs *i2s_regs = priv->variant_regs; in i2s_set_sysclk()
510 unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off; in i2s_set_sysclk()
511 unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; in i2s_set_sysclk()
516 pm_runtime_get_sync(dai->dev); in i2s_set_sysclk()
518 spin_lock_irqsave(&priv->lock, flags); in i2s_set_sysclk()
519 mod = readl(priv->addr + I2SMOD); in i2s_set_sysclk()
520 spin_unlock_irqrestore(&priv->lock, flags); in i2s_set_sysclk()
528 mask = 1 << i2s_regs->cdclkcon_off; in i2s_set_sysclk()
533 if ((rfs && other && other->rfs && (other->rfs != rfs)) || in i2s_set_sysclk()
539 dev_err(&i2s->pdev->dev, in i2s_set_sysclk()
540 "%s:%d Other DAI busy\n", __func__, __LINE__); in i2s_set_sysclk()
541 ret = -EAGAIN; in i2s_set_sysclk()
546 val = 1 << i2s_regs->cdclkcon_off; in i2s_set_sysclk()
548 i2s->rfs = rfs; in i2s_set_sysclk()
553 mask = 1 << i2s_regs->rclksrc_off; in i2s_set_sysclk()
555 if ((priv->quirks & QUIRK_NO_MUXPSR) in i2s_set_sysclk()
562 if (priv->op_clk && !IS_ERR(priv->op_clk)) { in i2s_set_sysclk()
565 clk_disable_unprepare(priv->op_clk); in i2s_set_sysclk()
566 clk_put(priv->op_clk); in i2s_set_sysclk()
568 priv->rclk_srcrate = in i2s_set_sysclk()
569 clk_get_rate(priv->op_clk); in i2s_set_sysclk()
575 priv->op_clk = clk_get(&i2s->pdev->dev, in i2s_set_sysclk()
578 priv->op_clk = clk_get(&i2s->pdev->dev, in i2s_set_sysclk()
581 if (WARN_ON(IS_ERR(priv->op_clk))) { in i2s_set_sysclk()
582 ret = PTR_ERR(priv->op_clk); in i2s_set_sysclk()
583 priv->op_clk = NULL; in i2s_set_sysclk()
587 ret = clk_prepare_enable(priv->op_clk); in i2s_set_sysclk()
589 clk_put(priv->op_clk); in i2s_set_sysclk()
590 priv->op_clk = NULL; in i2s_set_sysclk()
593 priv->rclk_srcrate = clk_get_rate(priv->op_clk); in i2s_set_sysclk()
597 dev_err(&i2s->pdev->dev, in i2s_set_sysclk()
598 "%s:%d Other DAI busy\n", __func__, __LINE__); in i2s_set_sysclk()
599 ret = -EAGAIN; in i2s_set_sysclk()
602 /* Call can't be on the active DAI */ in i2s_set_sysclk()
607 val = 1 << i2s_regs->rclksrc_off; in i2s_set_sysclk()
610 dev_err(&i2s->pdev->dev, "We don't serve that!\n"); in i2s_set_sysclk()
611 ret = -EINVAL; in i2s_set_sysclk()
615 spin_lock_irqsave(&priv->lock, flags); in i2s_set_sysclk()
616 mod = readl(priv->addr + I2SMOD); in i2s_set_sysclk()
618 writel(mod, priv->addr + I2SMOD); in i2s_set_sysclk()
619 spin_unlock_irqrestore(&priv->lock, flags); in i2s_set_sysclk()
621 pm_runtime_put(dai->dev); in i2s_set_sysclk()
625 pm_runtime_put(dai->dev); in i2s_set_sysclk()
629 static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) in i2s_set_fmt() argument
631 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in i2s_set_fmt()
632 struct i2s_dai *i2s = to_info(dai); in i2s_set_fmt()
637 lrp_shift = priv->variant_regs->lrp_off; in i2s_set_fmt()
638 sdf_shift = priv->variant_regs->sdf_off; in i2s_set_fmt()
639 mod_slave = 1 << priv->variant_regs->mss_off; in i2s_set_fmt()
658 dev_err(&i2s->pdev->dev, "Format not supported\n"); in i2s_set_fmt()
659 return -EINVAL; in i2s_set_fmt()
663 * INV flag is relative to the FORMAT flag - if set it simply in i2s_set_fmt()
676 dev_err(&i2s->pdev->dev, "Polarity not supported\n"); in i2s_set_fmt()
677 return -EINVAL; in i2s_set_fmt()
690 if (priv->rclk_srcrate == 0 && priv->clk_data.clks == NULL) in i2s_set_fmt()
691 i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0, in i2s_set_fmt()
695 dev_err(&i2s->pdev->dev, "master/slave format not supported\n"); in i2s_set_fmt()
696 return -EINVAL; in i2s_set_fmt()
699 pm_runtime_get_sync(dai->dev); in i2s_set_fmt()
700 spin_lock_irqsave(&priv->lock, flags); in i2s_set_fmt()
701 mod = readl(priv->addr + I2SMOD); in i2s_set_fmt()
703 * Don't change the I2S mode if any controller is active on this in i2s_set_fmt()
708 spin_unlock_irqrestore(&priv->lock, flags); in i2s_set_fmt()
709 pm_runtime_put(dai->dev); in i2s_set_fmt()
710 dev_err(&i2s->pdev->dev, in i2s_set_fmt()
711 "%s:%d Other DAI busy\n", __func__, __LINE__); in i2s_set_fmt()
712 return -EAGAIN; in i2s_set_fmt()
717 writel(mod, priv->addr + I2SMOD); in i2s_set_fmt()
718 priv->slave_mode = (mod & mod_slave); in i2s_set_fmt()
719 spin_unlock_irqrestore(&priv->lock, flags); in i2s_set_fmt()
720 pm_runtime_put(dai->dev); in i2s_set_fmt()
726 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) in i2s_hw_params() argument
728 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in i2s_hw_params()
729 struct i2s_dai *i2s = to_info(dai); in i2s_hw_params()
734 WARN_ON(!pm_runtime_active(dai->dev)); in i2s_hw_params()
747 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in i2s_hw_params()
748 i2s->dma_playback.addr_width = 4; in i2s_hw_params()
750 i2s->dma_capture.addr_width = 4; in i2s_hw_params()
753 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in i2s_hw_params()
754 i2s->dma_playback.addr_width = 2; in i2s_hw_params()
756 i2s->dma_capture.addr_width = 2; in i2s_hw_params()
760 dev_err(&i2s->pdev->dev, "%d channels not supported\n", in i2s_hw_params()
762 return -EINVAL; in i2s_hw_params()
799 dev_err(&i2s->pdev->dev, "Format(%d) not supported\n", in i2s_hw_params()
801 return -EINVAL; in i2s_hw_params()
804 spin_lock_irqsave(&priv->lock, flags); in i2s_hw_params()
805 mod = readl(priv->addr + I2SMOD); in i2s_hw_params()
807 writel(mod, priv->addr + I2SMOD); in i2s_hw_params()
808 spin_unlock_irqrestore(&priv->lock, flags); in i2s_hw_params()
810 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); in i2s_hw_params()
812 i2s->frmclk = params_rate(params); in i2s_hw_params()
814 rclksrc = priv->clk_table[CLK_I2S_RCLK_SRC]; in i2s_hw_params()
816 priv->rclk_srcrate = clk_get_rate(rclksrc); in i2s_hw_params()
823 struct snd_soc_dai *dai) in i2s_startup() argument
825 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in i2s_startup()
826 struct i2s_dai *i2s = to_info(dai); in i2s_startup()
830 pm_runtime_get_sync(dai->dev); in i2s_startup()
832 spin_lock_irqsave(&priv->pcm_lock, flags); in i2s_startup()
834 i2s->mode |= DAI_OPENED; in i2s_startup()
837 i2s->mode &= ~DAI_MANAGER; in i2s_startup()
839 i2s->mode |= DAI_MANAGER; in i2s_startup()
841 if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR)) in i2s_startup()
842 writel(CON_RSTCLR, i2s->priv->addr + I2SCON); in i2s_startup()
844 spin_unlock_irqrestore(&priv->pcm_lock, flags); in i2s_startup()
850 struct snd_soc_dai *dai) in i2s_shutdown() argument
852 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in i2s_shutdown()
853 struct i2s_dai *i2s = to_info(dai); in i2s_shutdown()
857 spin_lock_irqsave(&priv->pcm_lock, flags); in i2s_shutdown()
859 i2s->mode &= ~DAI_OPENED; in i2s_shutdown()
860 i2s->mode &= ~DAI_MANAGER; in i2s_shutdown()
863 other->mode |= DAI_MANAGER; in i2s_shutdown()
866 i2s->rfs = 0; in i2s_shutdown()
867 i2s->bfs = 0; in i2s_shutdown()
869 spin_unlock_irqrestore(&priv->pcm_lock, flags); in i2s_shutdown()
871 pm_runtime_put(dai->dev); in i2s_shutdown()
876 struct samsung_i2s_priv *priv = i2s->priv; in config_setup()
883 bfs = i2s->bfs; in config_setup()
886 bfs = other->bfs; in config_setup()
892 rfs = i2s->rfs; in config_setup()
895 rfs = other->rfs; in config_setup()
898 dev_err(&i2s->pdev->dev, in config_setup()
899 "%d-RFS not supported for 24-blc\n", rfs); in config_setup()
900 return -EINVAL; in config_setup()
912 dev_err(&i2s->pdev->dev, in config_setup()
913 "%s:%d Other DAI busy\n", __func__, __LINE__); in config_setup()
914 return -EAGAIN; in config_setup()
921 if (priv->slave_mode) in config_setup()
924 if (!(priv->quirks & QUIRK_NO_MUXPSR)) { in config_setup()
925 psr = priv->rclk_srcrate / i2s->frmclk / rfs; in config_setup()
926 writel(((psr - 1) << 8) | PSR_PSREN, priv->addr + I2SPSR); in config_setup()
927 dev_dbg(&i2s->pdev->dev, in config_setup()
929 priv->rclk_srcrate, psr, rfs, bfs); in config_setup()
936 int cmd, struct snd_soc_dai *dai) in i2s_trigger() argument
938 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in i2s_trigger()
939 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); in i2s_trigger()
948 pm_runtime_get_sync(dai->dev); in i2s_trigger()
950 if (priv->fixup_early) in i2s_trigger()
951 priv->fixup_early(substream, dai); in i2s_trigger()
953 spin_lock_irqsave(&priv->lock, flags); in i2s_trigger()
956 spin_unlock_irqrestore(&priv->lock, flags); in i2s_trigger()
957 return -EINVAL; in i2s_trigger()
960 if (priv->fixup_late) in i2s_trigger()
961 priv->fixup_late(substream, dai); in i2s_trigger()
968 spin_unlock_irqrestore(&priv->lock, flags); in i2s_trigger()
973 spin_lock_irqsave(&priv->lock, flags); in i2s_trigger()
983 spin_unlock_irqrestore(&priv->lock, flags); in i2s_trigger()
984 pm_runtime_put(dai->dev); in i2s_trigger()
991 static int i2s_set_clkdiv(struct snd_soc_dai *dai, in i2s_set_clkdiv() argument
994 struct i2s_dai *i2s = to_info(dai); in i2s_set_clkdiv()
999 pm_runtime_get_sync(dai->dev); in i2s_set_clkdiv()
1001 || (other && other->bfs && (other->bfs != div))) { in i2s_set_clkdiv()
1002 pm_runtime_put(dai->dev); in i2s_set_clkdiv()
1003 dev_err(&i2s->pdev->dev, in i2s_set_clkdiv()
1004 "%s:%d Other DAI busy\n", __func__, __LINE__); in i2s_set_clkdiv()
1005 return -EAGAIN; in i2s_set_clkdiv()
1007 i2s->bfs = div; in i2s_set_clkdiv()
1008 pm_runtime_put(dai->dev); in i2s_set_clkdiv()
1011 dev_err(&i2s->pdev->dev, in i2s_set_clkdiv()
1013 return -EINVAL; in i2s_set_clkdiv()
1020 i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) in i2s_delay() argument
1022 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in i2s_delay()
1023 struct i2s_dai *i2s = to_info(dai); in i2s_delay()
1024 u32 reg = readl(priv->addr + I2SFIC); in i2s_delay()
1027 WARN_ON(!pm_runtime_active(dai->dev)); in i2s_delay()
1029 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) in i2s_delay()
1032 delay = FICS_TXCOUNT(readl(priv->addr + I2SFICS)); in i2s_delay()
1034 delay = (reg >> priv->variant_regs->ftx0cnt_off) & 0x7f; in i2s_delay()
1042 return pm_runtime_force_suspend(component->dev); in i2s_suspend()
1047 return pm_runtime_force_resume(component->dev); in i2s_resume()
1054 static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) in samsung_i2s_dai_probe() argument
1056 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in samsung_i2s_dai_probe()
1057 struct i2s_dai *i2s = to_info(dai); in samsung_i2s_dai_probe()
1061 pm_runtime_get_sync(dai->dev); in samsung_i2s_dai_probe()
1064 /* If this is probe on the secondary DAI */ in samsung_i2s_dai_probe()
1065 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, NULL); in samsung_i2s_dai_probe()
1067 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, in samsung_i2s_dai_probe()
1068 &i2s->dma_capture); in samsung_i2s_dai_probe()
1070 if (priv->quirks & QUIRK_NEED_RSTCLR) in samsung_i2s_dai_probe()
1071 writel(CON_RSTCLR, priv->addr + I2SCON); in samsung_i2s_dai_probe()
1073 if (priv->quirks & QUIRK_SUPPORTS_IDMA) in samsung_i2s_dai_probe()
1074 idma_reg_addr_init(priv->addr, in samsung_i2s_dai_probe()
1075 other->idma_playback.addr); in samsung_i2s_dai_probe()
1079 i2s->rfs = 0; in samsung_i2s_dai_probe()
1080 i2s->bfs = 0; in samsung_i2s_dai_probe()
1082 spin_lock_irqsave(&priv->lock, flags); in samsung_i2s_dai_probe()
1088 spin_unlock_irqrestore(&priv->lock, flags); in samsung_i2s_dai_probe()
1092 i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, in samsung_i2s_dai_probe()
1094 pm_runtime_put(dai->dev); in samsung_i2s_dai_probe()
1099 static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) in samsung_i2s_dai_remove() argument
1101 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in samsung_i2s_dai_remove()
1102 struct i2s_dai *i2s = to_info(dai); in samsung_i2s_dai_remove()
1105 pm_runtime_get_sync(dai->dev); in samsung_i2s_dai_remove()
1108 if (priv->quirks & QUIRK_NEED_RSTCLR) { in samsung_i2s_dai_remove()
1109 spin_lock_irqsave(&priv->lock, flags); in samsung_i2s_dai_remove()
1110 writel(0, priv->addr + I2SCON); in samsung_i2s_dai_remove()
1111 spin_unlock_irqrestore(&priv->lock, flags); in samsung_i2s_dai_remove()
1115 pm_runtime_put(dai->dev); in samsung_i2s_dai_remove()
1134 /* Backend DAI */
1135 SND_SOC_DAPM_AIF_OUT("Mixer DAI TX", NULL, 0, SND_SOC_NOPM, 0, 0),
1136 SND_SOC_DAPM_AIF_IN("Mixer DAI RX", NULL, 0, SND_SOC_NOPM, 0, 0),
1146 { "Mixer DAI TX", NULL, "Playback Mixer" },
1147 { "Primary Capture", NULL, "Mixer DAI RX" },
1151 .name = "samsung-i2s",
1172 static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" }; in i2s_alloc_dais()
1178 priv->dai = devm_kcalloc(&priv->pdev->dev, num_dais, in i2s_alloc_dais()
1180 if (!priv->dai) in i2s_alloc_dais()
1181 return -ENOMEM; in i2s_alloc_dais()
1183 priv->dai_drv = devm_kcalloc(&priv->pdev->dev, num_dais, in i2s_alloc_dais()
1185 if (!priv->dai_drv) in i2s_alloc_dais()
1186 return -ENOMEM; in i2s_alloc_dais()
1189 dai_drv = &priv->dai_drv[i]; in i2s_alloc_dais()
1191 dai_drv->symmetric_rate = 1; in i2s_alloc_dais()
1192 dai_drv->ops = &samsung_i2s_dai_ops; in i2s_alloc_dais()
1194 dai_drv->playback.channels_min = 1; in i2s_alloc_dais()
1195 dai_drv->playback.channels_max = 2; in i2s_alloc_dais()
1196 dai_drv->playback.rates = i2s_dai_data->pcm_rates; in i2s_alloc_dais()
1197 dai_drv->playback.formats = SAMSUNG_I2S_FMTS; in i2s_alloc_dais()
1198 dai_drv->playback.stream_name = stream_names[i]; in i2s_alloc_dais()
1200 dai_drv->id = i + 1; in i2s_alloc_dais()
1201 dai_drv->name = dai_names[i]; in i2s_alloc_dais()
1203 priv->dai[i].drv = &priv->dai_drv[i]; in i2s_alloc_dais()
1204 priv->dai[i].pdev = priv->pdev; in i2s_alloc_dais()
1207 /* Initialize capture only for the primary DAI */ in i2s_alloc_dais()
1208 dai_drv = &priv->dai_drv[SAMSUNG_I2S_ID_PRIMARY - 1]; in i2s_alloc_dais()
1210 dai_drv->capture.channels_min = 1; in i2s_alloc_dais()
1211 dai_drv->capture.channels_max = 2; in i2s_alloc_dais()
1212 dai_drv->capture.rates = i2s_dai_data->pcm_rates; in i2s_alloc_dais()
1213 dai_drv->capture.formats = SAMSUNG_I2S_FMTS; in i2s_alloc_dais()
1214 dai_drv->capture.stream_name = "Primary Capture"; in i2s_alloc_dais()
1224 priv->suspend_i2smod = readl(priv->addr + I2SMOD); in i2s_runtime_suspend()
1225 priv->suspend_i2scon = readl(priv->addr + I2SCON); in i2s_runtime_suspend()
1226 priv->suspend_i2spsr = readl(priv->addr + I2SPSR); in i2s_runtime_suspend()
1228 clk_disable_unprepare(priv->op_clk); in i2s_runtime_suspend()
1229 clk_disable_unprepare(priv->clk); in i2s_runtime_suspend()
1239 ret = clk_prepare_enable(priv->clk); in i2s_runtime_resume()
1243 if (priv->op_clk) { in i2s_runtime_resume()
1244 ret = clk_prepare_enable(priv->op_clk); in i2s_runtime_resume()
1246 clk_disable_unprepare(priv->clk); in i2s_runtime_resume()
1251 writel(priv->suspend_i2scon, priv->addr + I2SCON); in i2s_runtime_resume()
1252 writel(priv->suspend_i2smod, priv->addr + I2SMOD); in i2s_runtime_resume()
1253 writel(priv->suspend_i2spsr, priv->addr + I2SPSR); in i2s_runtime_resume()
1263 for (i = 0; i < priv->clk_data.clk_num; i++) { in i2s_unregister_clocks()
1264 if (!IS_ERR(priv->clk_table[i])) in i2s_unregister_clocks()
1265 clk_unregister(priv->clk_table[i]); in i2s_unregister_clocks()
1271 of_clk_del_provider(priv->pdev->dev.of_node); in i2s_unregister_clock_provider()
1282 struct device *dev = &priv->pdev->dev; in i2s_register_clock_provider()
1283 const struct samsung_i2s_variant_regs *reg_info = priv->variant_regs; in i2s_register_clock_provider()
1289 if (!of_property_present(dev->of_node, "#clock-cells")) in i2s_register_clock_provider()
1305 return -ENOMEM; in i2s_register_clock_provider()
1308 if (!(priv->quirks & QUIRK_NO_MUXPSR)) { in i2s_register_clock_provider()
1310 u32 val = readl(priv->addr + I2SPSR); in i2s_register_clock_provider()
1311 writel(val | PSR_PSREN, priv->addr + I2SPSR); in i2s_register_clock_provider()
1313 priv->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev, in i2s_register_clock_provider()
1317 priv->addr + I2SMOD, reg_info->rclksrc_off, in i2s_register_clock_provider()
1318 1, 0, &priv->lock); in i2s_register_clock_provider()
1320 priv->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev, in i2s_register_clock_provider()
1324 priv->addr + I2SPSR, 8, 6, 0, &priv->lock); in i2s_register_clock_provider()
1327 priv->clk_data.clk_num = 2; in i2s_register_clock_provider()
1330 priv->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev, in i2s_register_clock_provider()
1333 priv->addr + I2SMOD, reg_info->cdclkcon_off, in i2s_register_clock_provider()
1334 CLK_GATE_SET_TO_DISABLE, &priv->lock); in i2s_register_clock_provider()
1336 priv->clk_data.clk_num += 1; in i2s_register_clock_provider()
1337 priv->clk_data.clks = priv->clk_table; in i2s_register_clock_provider()
1339 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, in i2s_register_clock_provider()
1340 &priv->clk_data); in i2s_register_clock_provider()
1356 devname = devm_kasprintf(&priv->pdev->dev, GFP_KERNEL, "%s-sec", in i2s_create_secondary_device()
1357 dev_name(&priv->pdev->dev)); in i2s_create_secondary_device()
1359 return -ENOMEM; in i2s_create_secondary_device()
1361 pdev_sec = platform_device_alloc(devname, -1); in i2s_create_secondary_device()
1363 return -ENOMEM; in i2s_create_secondary_device()
1365 pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL); in i2s_create_secondary_device()
1366 if (!pdev_sec->driver_override) { in i2s_create_secondary_device()
1368 return -ENOMEM; in i2s_create_secondary_device()
1377 ret = device_attach(&pdev_sec->dev); in i2s_create_secondary_device()
1379 platform_device_unregister(priv->pdev_sec); in i2s_create_secondary_device()
1380 dev_info(&pdev_sec->dev, "device_attach() failed\n"); in i2s_create_secondary_device()
1384 priv->pdev_sec = pdev_sec; in i2s_create_secondary_device()
1391 platform_device_unregister(priv->pdev_sec); in i2s_delete_secondary_device()
1392 priv->pdev_sec = NULL; in i2s_delete_secondary_device()
1398 struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; in samsung_i2s_probe()
1400 struct device_node *np = pdev->dev.of_node; in samsung_i2s_probe()
1407 if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { in samsung_i2s_probe()
1408 i2s_dai_data = of_device_get_match_data(&pdev->dev); in samsung_i2s_probe()
1416 i2s_dai_data = (struct samsung_i2s_dai_data *)id->driver_data; in samsung_i2s_probe()
1419 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in samsung_i2s_probe()
1421 return -ENOMEM; in samsung_i2s_probe()
1424 priv->quirks = i2s_dai_data->quirks; in samsung_i2s_probe()
1425 priv->fixup_early = i2s_dai_data->fixup_early; in samsung_i2s_probe()
1426 priv->fixup_late = i2s_dai_data->fixup_late; in samsung_i2s_probe()
1429 dev_err(&pdev->dev, "Missing platform data\n"); in samsung_i2s_probe()
1430 return -EINVAL; in samsung_i2s_probe()
1432 priv->quirks = i2s_pdata->type.quirks; in samsung_i2s_probe()
1435 num_dais = (priv->quirks & QUIRK_SEC_DAI) ? 2 : 1; in samsung_i2s_probe()
1436 priv->pdev = pdev; in samsung_i2s_probe()
1437 priv->variant_regs = i2s_dai_data->i2s_variant_regs; in samsung_i2s_probe()
1443 pri_dai = &priv->dai[SAMSUNG_I2S_ID_PRIMARY - 1]; in samsung_i2s_probe()
1445 spin_lock_init(&priv->lock); in samsung_i2s_probe()
1446 spin_lock_init(&priv->pcm_lock); in samsung_i2s_probe()
1449 pri_dai->dma_playback.filter_data = i2s_pdata->dma_playback; in samsung_i2s_probe()
1450 pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture; in samsung_i2s_probe()
1451 pri_dai->filter = i2s_pdata->dma_filter; in samsung_i2s_probe()
1453 idma_addr = i2s_pdata->type.idma_addr; in samsung_i2s_probe()
1455 if (of_property_read_u32(np, "samsung,idma-addr", in samsung_i2s_probe()
1457 if (priv->quirks & QUIRK_SUPPORTS_IDMA) { in samsung_i2s_probe()
1458 dev_info(&pdev->dev, "idma address is not"\ in samsung_i2s_probe()
1464 priv->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in samsung_i2s_probe()
1465 if (IS_ERR(priv->addr)) in samsung_i2s_probe()
1466 return PTR_ERR(priv->addr); in samsung_i2s_probe()
1468 regs_base = res->start; in samsung_i2s_probe()
1470 priv->clk = devm_clk_get(&pdev->dev, "iis"); in samsung_i2s_probe()
1471 if (IS_ERR(priv->clk)) { in samsung_i2s_probe()
1472 dev_err(&pdev->dev, "Failed to get iis clock\n"); in samsung_i2s_probe()
1473 return PTR_ERR(priv->clk); in samsung_i2s_probe()
1476 ret = clk_prepare_enable(priv->clk); in samsung_i2s_probe()
1478 dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); in samsung_i2s_probe()
1481 pri_dai->dma_playback.addr = regs_base + I2STXD; in samsung_i2s_probe()
1482 pri_dai->dma_capture.addr = regs_base + I2SRXD; in samsung_i2s_probe()
1483 pri_dai->dma_playback.chan_name = "tx"; in samsung_i2s_probe()
1484 pri_dai->dma_capture.chan_name = "rx"; in samsung_i2s_probe()
1485 pri_dai->dma_playback.addr_width = 4; in samsung_i2s_probe()
1486 pri_dai->dma_capture.addr_width = 4; in samsung_i2s_probe()
1487 pri_dai->priv = priv; in samsung_i2s_probe()
1489 if (priv->quirks & QUIRK_PRI_6CHAN) in samsung_i2s_probe()
1490 pri_dai->drv->playback.channels_max = 6; in samsung_i2s_probe()
1492 ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter, in samsung_i2s_probe()
1497 if (priv->quirks & QUIRK_SEC_DAI) { in samsung_i2s_probe()
1498 sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1]; in samsung_i2s_probe()
1500 sec_dai->dma_playback.addr = regs_base + I2STXDS; in samsung_i2s_probe()
1501 sec_dai->dma_playback.chan_name = "tx-sec"; in samsung_i2s_probe()
1504 sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec; in samsung_i2s_probe()
1505 sec_dai->filter = i2s_pdata->dma_filter; in samsung_i2s_probe()
1508 sec_dai->dma_playback.addr_width = 4; in samsung_i2s_probe()
1509 sec_dai->idma_playback.addr = idma_addr; in samsung_i2s_probe()
1510 sec_dai->pri_dai = pri_dai; in samsung_i2s_probe()
1511 sec_dai->priv = priv; in samsung_i2s_probe()
1512 pri_dai->sec_dai = sec_dai; in samsung_i2s_probe()
1518 ret = samsung_asoc_dma_platform_register(&priv->pdev_sec->dev, in samsung_i2s_probe()
1519 sec_dai->filter, "tx-sec", NULL, in samsung_i2s_probe()
1520 &pdev->dev); in samsung_i2s_probe()
1526 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { in samsung_i2s_probe()
1527 dev_err(&pdev->dev, "Unable to configure gpio\n"); in samsung_i2s_probe()
1528 ret = -EINVAL; in samsung_i2s_probe()
1532 dev_set_drvdata(&pdev->dev, priv); in samsung_i2s_probe()
1534 ret = devm_snd_soc_register_component(&pdev->dev, in samsung_i2s_probe()
1536 priv->dai_drv, num_dais); in samsung_i2s_probe()
1540 pm_runtime_set_active(&pdev->dev); in samsung_i2s_probe()
1541 pm_runtime_enable(&pdev->dev); in samsung_i2s_probe()
1547 priv->op_clk = clk_get_parent(priv->clk_table[CLK_I2S_RCLK_SRC]); in samsung_i2s_probe()
1552 pm_runtime_disable(&pdev->dev); in samsung_i2s_probe()
1556 clk_disable_unprepare(priv->clk); in samsung_i2s_probe()
1562 struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev); in samsung_i2s_remove()
1568 pm_runtime_get_sync(&pdev->dev); in samsung_i2s_remove()
1569 pm_runtime_disable(&pdev->dev); in samsung_i2s_remove()
1573 clk_disable_unprepare(priv->clk); in samsung_i2s_remove()
1575 pm_runtime_put_noidle(&pdev->dev); in samsung_i2s_remove()
1579 struct snd_soc_dai *dai) in fsd_i2s_fixup_early() argument
1586 i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, 0, SND_SOC_CLOCK_OUT); in fsd_i2s_fixup_early()
1587 i2s_set_sysclk(dai, SAMSUNG_I2S_OPCLK, 0, MOD_OPCLK_PCLK); in fsd_i2s_fixup_early()
1592 struct snd_soc_dai *dai) in fsd_i2s_fixup_late() argument
1595 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); in fsd_i2s_fixup_late()
1600 writel(PSR_PSVAL(2) | PSR_PSREN, priv->addr + I2SPSR); in fsd_i2s_fixup_late()
1702 .name = "samsung-i2s",
1712 .compatible = "samsung,s3c6410-i2s",
1715 .compatible = "samsung,s5pv210-i2s",
1718 .compatible = "samsung,exynos5420-i2s",
1721 .compatible = "samsung,exynos7-i2s",
1724 .compatible = "samsung,exynos7-i2s1",
1727 .compatible = "tesla,fsd-i2s",
1747 .name = "samsung-i2s",