Lines Matching +full:exynos7 +full:- +full:i2s
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>
23 #include <linux/platform_data/asoc-s3c.h>
27 #include "i2s.h"
28 #include "i2s-regs.h"
103 /* The I2S controller's core clock */
106 /* Clock for generating I2S signals */
112 /* Cache of selected I2S registers for system suspend */
134 /* A flag indicating the I2S slave mode operation */
139 static inline bool is_secondary(struct i2s_dai *i2s) in is_secondary() argument
141 return i2s->drv->id == SAMSUNG_I2S_ID_SECONDARY; in is_secondary()
145 static inline bool tx_active(struct i2s_dai *i2s) in tx_active() argument
149 if (!i2s) in tx_active()
152 active = readl(i2s->priv->addr + I2SCON); in tx_active()
154 if (is_secondary(i2s)) in tx_active()
163 static inline struct i2s_dai *get_other_dai(struct i2s_dai *i2s) in get_other_dai() argument
165 return i2s->pri_dai ? : i2s->sec_dai; in get_other_dai()
169 static inline bool other_tx_active(struct i2s_dai *i2s) in other_tx_active() argument
171 struct i2s_dai *other = get_other_dai(i2s); in other_tx_active()
177 static inline bool any_tx_active(struct i2s_dai *i2s) in any_tx_active() argument
179 return tx_active(i2s) || other_tx_active(i2s); in any_tx_active()
183 static inline bool rx_active(struct i2s_dai *i2s) in rx_active() argument
187 if (!i2s) in rx_active()
190 active = readl(i2s->priv->addr + I2SCON) & CON_RXDMA_ACTIVE; in rx_active()
196 static inline bool other_rx_active(struct i2s_dai *i2s) in other_rx_active() argument
198 struct i2s_dai *other = get_other_dai(i2s); in other_rx_active()
204 static inline bool any_rx_active(struct i2s_dai *i2s) in any_rx_active() argument
206 return rx_active(i2s) || other_rx_active(i2s); in any_rx_active()
210 static inline bool other_active(struct i2s_dai *i2s) in other_active() argument
212 return other_rx_active(i2s) || other_tx_active(i2s); in other_active()
216 static inline bool this_active(struct i2s_dai *i2s) in this_active() argument
218 return tx_active(i2s) || rx_active(i2s); in this_active()
222 static inline bool any_active(struct i2s_dai *i2s) in any_active() argument
224 return this_active(i2s) || other_active(i2s); in any_active()
231 return &priv->dai[dai->id - 1]; in to_info()
234 static inline bool is_opened(struct i2s_dai *i2s) in is_opened() argument
236 if (i2s && (i2s->mode & DAI_OPENED)) in is_opened()
242 static inline bool is_manager(struct i2s_dai *i2s) in is_manager() argument
244 if (is_opened(i2s) && (i2s->mode & DAI_MANAGER)) in is_manager()
250 /* Read RCLK of I2S (in multiples of LRCLK) */
251 static inline unsigned get_rfs(struct i2s_dai *i2s) in get_rfs() argument
253 struct samsung_i2s_priv *priv = i2s->priv; in get_rfs()
256 rfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->rfs_off; in get_rfs()
257 rfs &= priv->variant_regs->rfs_mask; in get_rfs()
271 /* Write RCLK of I2S (in multiples of LRCLK) */
272 static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) in set_rfs() argument
274 struct samsung_i2s_priv *priv = i2s->priv; in set_rfs()
275 u32 mod = readl(priv->addr + I2SMOD); in set_rfs()
276 int rfs_shift = priv->variant_regs->rfs_off; in set_rfs()
278 mod &= ~(priv->variant_regs->rfs_mask << rfs_shift); in set_rfs()
307 writel(mod, priv->addr + I2SMOD); in set_rfs()
310 /* Read bit-clock of I2S (in multiples of LRCLK) */
311 static inline unsigned get_bfs(struct i2s_dai *i2s) in get_bfs() argument
313 struct samsung_i2s_priv *priv = i2s->priv; in get_bfs()
316 bfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->bfs_off; in get_bfs()
317 bfs &= priv->variant_regs->bfs_mask; in get_bfs()
332 /* Write bit-clock of I2S (in multiples of LRCLK) */
333 static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) in set_bfs() argument
335 struct samsung_i2s_priv *priv = i2s->priv; in set_bfs()
336 u32 mod = readl(priv->addr + I2SMOD); in set_bfs()
337 int tdm = priv->quirks & QUIRK_SUPPORTS_TDM; in set_bfs()
338 int bfs_shift = priv->variant_regs->bfs_off; in set_bfs()
340 /* Non-TDM I2S controllers do not support BCLK > 48 * FS */ in set_bfs()
342 dev_err(&i2s->pdev->dev, "Unsupported BCLK divider\n"); in set_bfs()
346 mod &= ~(priv->variant_regs->bfs_mask << bfs_shift); in set_bfs()
377 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); in set_bfs()
381 writel(mod, priv->addr + I2SMOD); in set_bfs()
385 static inline int get_blc(struct i2s_dai *i2s) in get_blc() argument
387 int blc = readl(i2s->priv->addr + I2SMOD); in get_blc()
399 static void i2s_txctrl(struct i2s_dai *i2s, int on) in i2s_txctrl() argument
401 struct samsung_i2s_priv *priv = i2s->priv; in i2s_txctrl()
402 void __iomem *addr = priv->addr; in i2s_txctrl()
403 int txr_off = priv->variant_regs->txr_off; in i2s_txctrl()
411 if (is_secondary(i2s)) { in i2s_txctrl()
419 if (any_rx_active(i2s)) in i2s_txctrl()
424 if (is_secondary(i2s)) { in i2s_txctrl()
432 if (other_tx_active(i2s)) { in i2s_txctrl()
439 if (any_rx_active(i2s)) in i2s_txctrl()
450 static void i2s_rxctrl(struct i2s_dai *i2s, int on) in i2s_rxctrl() argument
452 struct samsung_i2s_priv *priv = i2s->priv; in i2s_rxctrl()
453 void __iomem *addr = priv->addr; in i2s_rxctrl()
454 int txr_off = priv->variant_regs->txr_off; in i2s_rxctrl()
462 if (any_tx_active(i2s)) in i2s_rxctrl()
470 if (any_tx_active(i2s)) in i2s_rxctrl()
481 static inline void i2s_fifo(struct i2s_dai *i2s, u32 flush) in i2s_fifo() argument
486 if (!i2s) in i2s_fifo()
489 if (is_secondary(i2s)) in i2s_fifo()
490 fic = i2s->priv->addr + I2SFICS; in i2s_fifo()
492 fic = i2s->priv->addr + I2SFIC; in i2s_fifo()
499 while (--val) in i2s_fifo()
509 struct i2s_dai *i2s = to_info(dai); in i2s_set_sysclk() local
510 struct i2s_dai *other = get_other_dai(i2s); in i2s_set_sysclk()
511 const struct samsung_i2s_variant_regs *i2s_regs = priv->variant_regs; in i2s_set_sysclk()
512 unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off; in i2s_set_sysclk()
513 unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; in i2s_set_sysclk()
518 pm_runtime_get_sync(dai->dev); in i2s_set_sysclk()
520 spin_lock_irqsave(&priv->lock, flags); in i2s_set_sysclk()
521 mod = readl(priv->addr + I2SMOD); in i2s_set_sysclk()
522 spin_unlock_irqrestore(&priv->lock, flags); in i2s_set_sysclk()
530 mask = 1 << i2s_regs->cdclkcon_off; in i2s_set_sysclk()
535 if ((rfs && other && other->rfs && (other->rfs != rfs)) || in i2s_set_sysclk()
536 (any_active(i2s) && in i2s_set_sysclk()
541 dev_err(&i2s->pdev->dev, in i2s_set_sysclk()
543 ret = -EAGAIN; in i2s_set_sysclk()
548 val = 1 << i2s_regs->cdclkcon_off; in i2s_set_sysclk()
550 i2s->rfs = rfs; in i2s_set_sysclk()
555 mask = 1 << i2s_regs->rclksrc_off; in i2s_set_sysclk()
557 if ((priv->quirks & QUIRK_NO_MUXPSR) in i2s_set_sysclk()
563 if (!any_active(i2s)) { in i2s_set_sysclk()
564 if (priv->op_clk && !IS_ERR(priv->op_clk)) { in i2s_set_sysclk()
567 clk_disable_unprepare(priv->op_clk); in i2s_set_sysclk()
568 clk_put(priv->op_clk); in i2s_set_sysclk()
570 priv->rclk_srcrate = in i2s_set_sysclk()
571 clk_get_rate(priv->op_clk); in i2s_set_sysclk()
577 priv->op_clk = clk_get(&i2s->pdev->dev, in i2s_set_sysclk()
580 priv->op_clk = clk_get(&i2s->pdev->dev, in i2s_set_sysclk()
583 if (WARN_ON(IS_ERR(priv->op_clk))) { in i2s_set_sysclk()
584 ret = PTR_ERR(priv->op_clk); in i2s_set_sysclk()
585 priv->op_clk = NULL; in i2s_set_sysclk()
589 ret = clk_prepare_enable(priv->op_clk); in i2s_set_sysclk()
591 clk_put(priv->op_clk); in i2s_set_sysclk()
592 priv->op_clk = NULL; in i2s_set_sysclk()
595 priv->rclk_srcrate = clk_get_rate(priv->op_clk); in i2s_set_sysclk()
599 dev_err(&i2s->pdev->dev, in i2s_set_sysclk()
601 ret = -EAGAIN; in i2s_set_sysclk()
609 val = 1 << i2s_regs->rclksrc_off; in i2s_set_sysclk()
612 dev_err(&i2s->pdev->dev, "We don't serve that!\n"); in i2s_set_sysclk()
613 ret = -EINVAL; in i2s_set_sysclk()
617 spin_lock_irqsave(&priv->lock, flags); in i2s_set_sysclk()
618 mod = readl(priv->addr + I2SMOD); in i2s_set_sysclk()
620 writel(mod, priv->addr + I2SMOD); in i2s_set_sysclk()
621 spin_unlock_irqrestore(&priv->lock, flags); in i2s_set_sysclk()
623 pm_runtime_put(dai->dev); in i2s_set_sysclk()
627 pm_runtime_put(dai->dev); in i2s_set_sysclk()
634 struct i2s_dai *i2s = to_info(dai); in i2s_set_fmt() local
639 lrp_shift = priv->variant_regs->lrp_off; in i2s_set_fmt()
640 sdf_shift = priv->variant_regs->sdf_off; in i2s_set_fmt()
641 mod_slave = 1 << priv->variant_regs->mss_off; in i2s_set_fmt()
660 dev_err(&i2s->pdev->dev, "Format not supported\n"); in i2s_set_fmt()
661 return -EINVAL; in i2s_set_fmt()
665 * INV flag is relative to the FORMAT flag - if set it simply in i2s_set_fmt()
678 dev_err(&i2s->pdev->dev, "Polarity not supported\n"); in i2s_set_fmt()
679 return -EINVAL; in i2s_set_fmt()
692 if (priv->rclk_srcrate == 0 && priv->clk_data.clks == NULL) in i2s_set_fmt()
697 dev_err(&i2s->pdev->dev, "master/slave format not supported\n"); in i2s_set_fmt()
698 return -EINVAL; in i2s_set_fmt()
701 pm_runtime_get_sync(dai->dev); in i2s_set_fmt()
702 spin_lock_irqsave(&priv->lock, flags); in i2s_set_fmt()
703 mod = readl(priv->addr + I2SMOD); in i2s_set_fmt()
705 * Don't change the I2S mode if any controller is active on this in i2s_set_fmt()
708 if (any_active(i2s) && in i2s_set_fmt()
710 spin_unlock_irqrestore(&priv->lock, flags); in i2s_set_fmt()
711 pm_runtime_put(dai->dev); in i2s_set_fmt()
712 dev_err(&i2s->pdev->dev, in i2s_set_fmt()
714 return -EAGAIN; in i2s_set_fmt()
719 writel(mod, priv->addr + I2SMOD); in i2s_set_fmt()
720 priv->slave_mode = (mod & mod_slave); in i2s_set_fmt()
721 spin_unlock_irqrestore(&priv->lock, flags); in i2s_set_fmt()
722 pm_runtime_put(dai->dev); in i2s_set_fmt()
731 struct i2s_dai *i2s = to_info(dai); in i2s_hw_params() local
736 WARN_ON(!pm_runtime_active(dai->dev)); in i2s_hw_params()
738 if (!is_secondary(i2s)) in i2s_hw_params()
749 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in i2s_hw_params()
750 i2s->dma_playback.addr_width = 4; in i2s_hw_params()
752 i2s->dma_capture.addr_width = 4; in i2s_hw_params()
755 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in i2s_hw_params()
756 i2s->dma_playback.addr_width = 2; in i2s_hw_params()
758 i2s->dma_capture.addr_width = 2; in i2s_hw_params()
762 dev_err(&i2s->pdev->dev, "%d channels not supported\n", in i2s_hw_params()
764 return -EINVAL; in i2s_hw_params()
767 if (is_secondary(i2s)) in i2s_hw_params()
772 if (is_manager(i2s)) in i2s_hw_params()
777 if (is_secondary(i2s)) in i2s_hw_params()
781 if (is_manager(i2s)) in i2s_hw_params()
785 if (is_secondary(i2s)) in i2s_hw_params()
789 if (is_manager(i2s)) in i2s_hw_params()
793 if (is_secondary(i2s)) in i2s_hw_params()
797 if (is_manager(i2s)) in i2s_hw_params()
801 dev_err(&i2s->pdev->dev, "Format(%d) not supported\n", in i2s_hw_params()
803 return -EINVAL; in i2s_hw_params()
806 spin_lock_irqsave(&priv->lock, flags); in i2s_hw_params()
807 mod = readl(priv->addr + I2SMOD); in i2s_hw_params()
809 writel(mod, priv->addr + I2SMOD); in i2s_hw_params()
810 spin_unlock_irqrestore(&priv->lock, flags); in i2s_hw_params()
812 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); in i2s_hw_params()
814 i2s->frmclk = params_rate(params); in i2s_hw_params()
816 rclksrc = priv->clk_table[CLK_I2S_RCLK_SRC]; in i2s_hw_params()
818 priv->rclk_srcrate = clk_get_rate(rclksrc); in i2s_hw_params()
823 /* We set constraints on the substream according to the version of I2S */
828 struct i2s_dai *i2s = to_info(dai); in i2s_startup() local
829 struct i2s_dai *other = get_other_dai(i2s); in i2s_startup()
832 pm_runtime_get_sync(dai->dev); in i2s_startup()
834 spin_lock_irqsave(&priv->pcm_lock, flags); in i2s_startup()
836 i2s->mode |= DAI_OPENED; in i2s_startup()
839 i2s->mode &= ~DAI_MANAGER; in i2s_startup()
841 i2s->mode |= DAI_MANAGER; in i2s_startup()
843 if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR)) in i2s_startup()
844 writel(CON_RSTCLR, i2s->priv->addr + I2SCON); in i2s_startup()
846 spin_unlock_irqrestore(&priv->pcm_lock, flags); in i2s_startup()
855 struct i2s_dai *i2s = to_info(dai); in i2s_shutdown() local
856 struct i2s_dai *other = get_other_dai(i2s); in i2s_shutdown()
859 spin_lock_irqsave(&priv->pcm_lock, flags); in i2s_shutdown()
861 i2s->mode &= ~DAI_OPENED; in i2s_shutdown()
862 i2s->mode &= ~DAI_MANAGER; in i2s_shutdown()
865 other->mode |= DAI_MANAGER; in i2s_shutdown()
868 i2s->rfs = 0; in i2s_shutdown()
869 i2s->bfs = 0; in i2s_shutdown()
871 spin_unlock_irqrestore(&priv->pcm_lock, flags); in i2s_shutdown()
873 pm_runtime_put(dai->dev); in i2s_shutdown()
876 static int config_setup(struct i2s_dai *i2s) in config_setup() argument
878 struct samsung_i2s_priv *priv = i2s->priv; in config_setup()
879 struct i2s_dai *other = get_other_dai(i2s); in config_setup()
883 blc = get_blc(i2s); in config_setup()
885 bfs = i2s->bfs; in config_setup()
888 bfs = other->bfs; in config_setup()
894 rfs = i2s->rfs; in config_setup()
897 rfs = other->rfs; in config_setup()
900 dev_err(&i2s->pdev->dev, in config_setup()
901 "%d-RFS not supported for 24-blc\n", rfs); in config_setup()
902 return -EINVAL; in config_setup()
913 if (any_active(i2s) && (get_rfs(i2s) != rfs || get_bfs(i2s) != bfs)) { in config_setup()
914 dev_err(&i2s->pdev->dev, in config_setup()
916 return -EAGAIN; in config_setup()
919 set_bfs(i2s, bfs); in config_setup()
920 set_rfs(i2s, rfs); in config_setup()
923 if (priv->slave_mode) in config_setup()
926 if (!(priv->quirks & QUIRK_NO_MUXPSR)) { in config_setup()
927 psr = priv->rclk_srcrate / i2s->frmclk / rfs; in config_setup()
928 writel(((psr - 1) << 8) | PSR_PSREN, priv->addr + I2SPSR); in config_setup()
929 dev_dbg(&i2s->pdev->dev, in config_setup()
931 priv->rclk_srcrate, psr, rfs, bfs); in config_setup()
941 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); in i2s_trigger()
943 struct i2s_dai *i2s = to_info(asoc_rtd_to_cpu(rtd, 0)); in i2s_trigger() local
950 pm_runtime_get_sync(dai->dev); in i2s_trigger()
952 if (priv->fixup_early) in i2s_trigger()
953 priv->fixup_early(substream, dai); in i2s_trigger()
955 spin_lock_irqsave(&priv->lock, flags); in i2s_trigger()
957 if (config_setup(i2s)) { in i2s_trigger()
958 spin_unlock_irqrestore(&priv->lock, flags); in i2s_trigger()
959 return -EINVAL; in i2s_trigger()
962 if (priv->fixup_late) in i2s_trigger()
963 priv->fixup_late(substream, dai); in i2s_trigger()
966 i2s_rxctrl(i2s, 1); in i2s_trigger()
968 i2s_txctrl(i2s, 1); in i2s_trigger()
970 spin_unlock_irqrestore(&priv->lock, flags); in i2s_trigger()
975 spin_lock_irqsave(&priv->lock, flags); in i2s_trigger()
978 i2s_rxctrl(i2s, 0); in i2s_trigger()
979 i2s_fifo(i2s, FIC_RXFLUSH); in i2s_trigger()
981 i2s_txctrl(i2s, 0); in i2s_trigger()
982 i2s_fifo(i2s, FIC_TXFLUSH); in i2s_trigger()
985 spin_unlock_irqrestore(&priv->lock, flags); in i2s_trigger()
986 pm_runtime_put(dai->dev); in i2s_trigger()
996 struct i2s_dai *i2s = to_info(dai); in i2s_set_clkdiv() local
997 struct i2s_dai *other = get_other_dai(i2s); in i2s_set_clkdiv()
1001 pm_runtime_get_sync(dai->dev); in i2s_set_clkdiv()
1002 if ((any_active(i2s) && div && (get_bfs(i2s) != div)) in i2s_set_clkdiv()
1003 || (other && other->bfs && (other->bfs != div))) { in i2s_set_clkdiv()
1004 pm_runtime_put(dai->dev); in i2s_set_clkdiv()
1005 dev_err(&i2s->pdev->dev, in i2s_set_clkdiv()
1007 return -EAGAIN; in i2s_set_clkdiv()
1009 i2s->bfs = div; in i2s_set_clkdiv()
1010 pm_runtime_put(dai->dev); in i2s_set_clkdiv()
1013 dev_err(&i2s->pdev->dev, in i2s_set_clkdiv()
1015 return -EINVAL; in i2s_set_clkdiv()
1025 struct i2s_dai *i2s = to_info(dai); in i2s_delay() local
1026 u32 reg = readl(priv->addr + I2SFIC); in i2s_delay()
1029 WARN_ON(!pm_runtime_active(dai->dev)); in i2s_delay()
1031 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) in i2s_delay()
1033 else if (is_secondary(i2s)) in i2s_delay()
1034 delay = FICS_TXCOUNT(readl(priv->addr + I2SFICS)); in i2s_delay()
1036 delay = (reg >> priv->variant_regs->ftx0cnt_off) & 0x7f; in i2s_delay()
1044 return pm_runtime_force_suspend(component->dev); in i2s_suspend()
1049 return pm_runtime_force_resume(component->dev); in i2s_resume()
1059 struct i2s_dai *i2s = to_info(dai); in samsung_i2s_dai_probe() local
1060 struct i2s_dai *other = get_other_dai(i2s); in samsung_i2s_dai_probe()
1063 pm_runtime_get_sync(dai->dev); in samsung_i2s_dai_probe()
1065 if (is_secondary(i2s)) { in samsung_i2s_dai_probe()
1067 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, NULL); in samsung_i2s_dai_probe()
1069 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, in samsung_i2s_dai_probe()
1070 &i2s->dma_capture); in samsung_i2s_dai_probe()
1072 if (priv->quirks & QUIRK_NEED_RSTCLR) in samsung_i2s_dai_probe()
1073 writel(CON_RSTCLR, priv->addr + I2SCON); in samsung_i2s_dai_probe()
1075 if (priv->quirks & QUIRK_SUPPORTS_IDMA) in samsung_i2s_dai_probe()
1076 idma_reg_addr_init(priv->addr, in samsung_i2s_dai_probe()
1077 other->idma_playback.addr); in samsung_i2s_dai_probe()
1081 i2s->rfs = 0; in samsung_i2s_dai_probe()
1082 i2s->bfs = 0; in samsung_i2s_dai_probe()
1084 spin_lock_irqsave(&priv->lock, flags); in samsung_i2s_dai_probe()
1085 i2s_txctrl(i2s, 0); in samsung_i2s_dai_probe()
1086 i2s_rxctrl(i2s, 0); in samsung_i2s_dai_probe()
1087 i2s_fifo(i2s, FIC_TXFLUSH); in samsung_i2s_dai_probe()
1089 i2s_fifo(i2s, FIC_RXFLUSH); in samsung_i2s_dai_probe()
1090 spin_unlock_irqrestore(&priv->lock, flags); in samsung_i2s_dai_probe()
1096 pm_runtime_put(dai->dev); in samsung_i2s_dai_probe()
1104 struct i2s_dai *i2s = to_info(dai); in samsung_i2s_dai_remove() local
1107 pm_runtime_get_sync(dai->dev); in samsung_i2s_dai_remove()
1109 if (!is_secondary(i2s)) { in samsung_i2s_dai_remove()
1110 if (priv->quirks & QUIRK_NEED_RSTCLR) { in samsung_i2s_dai_remove()
1111 spin_lock_irqsave(&priv->lock, flags); in samsung_i2s_dai_remove()
1112 writel(0, priv->addr + I2SCON); in samsung_i2s_dai_remove()
1113 spin_unlock_irqrestore(&priv->lock, flags); in samsung_i2s_dai_remove()
1117 pm_runtime_put(dai->dev); in samsung_i2s_dai_remove()
1153 .name = "samsung-i2s",
1174 static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" }; in i2s_alloc_dais()
1180 priv->dai = devm_kcalloc(&priv->pdev->dev, num_dais, in i2s_alloc_dais()
1182 if (!priv->dai) in i2s_alloc_dais()
1183 return -ENOMEM; in i2s_alloc_dais()
1185 priv->dai_drv = devm_kcalloc(&priv->pdev->dev, num_dais, in i2s_alloc_dais()
1187 if (!priv->dai_drv) in i2s_alloc_dais()
1188 return -ENOMEM; in i2s_alloc_dais()
1191 dai_drv = &priv->dai_drv[i]; in i2s_alloc_dais()
1193 dai_drv->symmetric_rate = 1; in i2s_alloc_dais()
1194 dai_drv->ops = &samsung_i2s_dai_ops; in i2s_alloc_dais()
1196 dai_drv->playback.channels_min = 1; in i2s_alloc_dais()
1197 dai_drv->playback.channels_max = 2; in i2s_alloc_dais()
1198 dai_drv->playback.rates = i2s_dai_data->pcm_rates; in i2s_alloc_dais()
1199 dai_drv->playback.formats = SAMSUNG_I2S_FMTS; in i2s_alloc_dais()
1200 dai_drv->playback.stream_name = stream_names[i]; in i2s_alloc_dais()
1202 dai_drv->id = i + 1; in i2s_alloc_dais()
1203 dai_drv->name = dai_names[i]; in i2s_alloc_dais()
1205 priv->dai[i].drv = &priv->dai_drv[i]; in i2s_alloc_dais()
1206 priv->dai[i].pdev = priv->pdev; in i2s_alloc_dais()
1210 dai_drv = &priv->dai_drv[SAMSUNG_I2S_ID_PRIMARY - 1]; in i2s_alloc_dais()
1212 dai_drv->capture.channels_min = 1; in i2s_alloc_dais()
1213 dai_drv->capture.channels_max = 2; in i2s_alloc_dais()
1214 dai_drv->capture.rates = i2s_dai_data->pcm_rates; in i2s_alloc_dais()
1215 dai_drv->capture.formats = SAMSUNG_I2S_FMTS; in i2s_alloc_dais()
1216 dai_drv->capture.stream_name = "Primary Capture"; in i2s_alloc_dais()
1226 priv->suspend_i2smod = readl(priv->addr + I2SMOD); in i2s_runtime_suspend()
1227 priv->suspend_i2scon = readl(priv->addr + I2SCON); in i2s_runtime_suspend()
1228 priv->suspend_i2spsr = readl(priv->addr + I2SPSR); in i2s_runtime_suspend()
1230 clk_disable_unprepare(priv->op_clk); in i2s_runtime_suspend()
1231 clk_disable_unprepare(priv->clk); in i2s_runtime_suspend()
1241 ret = clk_prepare_enable(priv->clk); in i2s_runtime_resume()
1245 if (priv->op_clk) { in i2s_runtime_resume()
1246 ret = clk_prepare_enable(priv->op_clk); in i2s_runtime_resume()
1248 clk_disable_unprepare(priv->clk); in i2s_runtime_resume()
1253 writel(priv->suspend_i2scon, priv->addr + I2SCON); in i2s_runtime_resume()
1254 writel(priv->suspend_i2smod, priv->addr + I2SMOD); in i2s_runtime_resume()
1255 writel(priv->suspend_i2spsr, priv->addr + I2SPSR); in i2s_runtime_resume()
1265 for (i = 0; i < priv->clk_data.clk_num; i++) { in i2s_unregister_clocks()
1266 if (!IS_ERR(priv->clk_table[i])) in i2s_unregister_clocks()
1267 clk_unregister(priv->clk_table[i]); in i2s_unregister_clocks()
1273 of_clk_del_provider(priv->pdev->dev.of_node); in i2s_unregister_clock_provider()
1284 struct device *dev = &priv->pdev->dev; in i2s_register_clock_provider()
1285 const struct samsung_i2s_variant_regs *reg_info = priv->variant_regs; in i2s_register_clock_provider()
1291 if (!of_property_present(dev->of_node, "#clock-cells")) in i2s_register_clock_provider()
1307 return -ENOMEM; in i2s_register_clock_provider()
1310 if (!(priv->quirks & QUIRK_NO_MUXPSR)) { in i2s_register_clock_provider()
1312 u32 val = readl(priv->addr + I2SPSR); in i2s_register_clock_provider()
1313 writel(val | PSR_PSREN, priv->addr + I2SPSR); in i2s_register_clock_provider()
1315 priv->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev, in i2s_register_clock_provider()
1319 priv->addr + I2SMOD, reg_info->rclksrc_off, in i2s_register_clock_provider()
1320 1, 0, &priv->lock); in i2s_register_clock_provider()
1322 priv->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev, in i2s_register_clock_provider()
1326 priv->addr + I2SPSR, 8, 6, 0, &priv->lock); in i2s_register_clock_provider()
1329 priv->clk_data.clk_num = 2; in i2s_register_clock_provider()
1332 priv->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev, in i2s_register_clock_provider()
1335 priv->addr + I2SMOD, reg_info->cdclkcon_off, in i2s_register_clock_provider()
1336 CLK_GATE_SET_TO_DISABLE, &priv->lock); in i2s_register_clock_provider()
1338 priv->clk_data.clk_num += 1; in i2s_register_clock_provider()
1339 priv->clk_data.clks = priv->clk_table; in i2s_register_clock_provider()
1341 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, in i2s_register_clock_provider()
1342 &priv->clk_data); in i2s_register_clock_provider()
1358 devname = devm_kasprintf(&priv->pdev->dev, GFP_KERNEL, "%s-sec", in i2s_create_secondary_device()
1359 dev_name(&priv->pdev->dev)); in i2s_create_secondary_device()
1361 return -ENOMEM; in i2s_create_secondary_device()
1363 pdev_sec = platform_device_alloc(devname, -1); in i2s_create_secondary_device()
1365 return -ENOMEM; in i2s_create_secondary_device()
1367 pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL); in i2s_create_secondary_device()
1368 if (!pdev_sec->driver_override) { in i2s_create_secondary_device()
1370 return -ENOMEM; in i2s_create_secondary_device()
1379 ret = device_attach(&pdev_sec->dev); in i2s_create_secondary_device()
1381 platform_device_unregister(priv->pdev_sec); in i2s_create_secondary_device()
1382 dev_info(&pdev_sec->dev, "device_attach() failed\n"); in i2s_create_secondary_device()
1386 priv->pdev_sec = pdev_sec; in i2s_create_secondary_device()
1393 platform_device_unregister(priv->pdev_sec); in i2s_delete_secondary_device()
1394 priv->pdev_sec = NULL; in i2s_delete_secondary_device()
1400 struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; in samsung_i2s_probe()
1402 struct device_node *np = pdev->dev.of_node; in samsung_i2s_probe()
1409 if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { in samsung_i2s_probe()
1410 i2s_dai_data = of_device_get_match_data(&pdev->dev); in samsung_i2s_probe()
1418 i2s_dai_data = (struct samsung_i2s_dai_data *)id->driver_data; in samsung_i2s_probe()
1421 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in samsung_i2s_probe()
1423 return -ENOMEM; in samsung_i2s_probe()
1426 priv->quirks = i2s_dai_data->quirks; in samsung_i2s_probe()
1427 priv->fixup_early = i2s_dai_data->fixup_early; in samsung_i2s_probe()
1428 priv->fixup_late = i2s_dai_data->fixup_late; in samsung_i2s_probe()
1431 dev_err(&pdev->dev, "Missing platform data\n"); in samsung_i2s_probe()
1432 return -EINVAL; in samsung_i2s_probe()
1434 priv->quirks = i2s_pdata->type.quirks; in samsung_i2s_probe()
1437 num_dais = (priv->quirks & QUIRK_SEC_DAI) ? 2 : 1; in samsung_i2s_probe()
1438 priv->pdev = pdev; in samsung_i2s_probe()
1439 priv->variant_regs = i2s_dai_data->i2s_variant_regs; in samsung_i2s_probe()
1445 pri_dai = &priv->dai[SAMSUNG_I2S_ID_PRIMARY - 1]; in samsung_i2s_probe()
1447 spin_lock_init(&priv->lock); in samsung_i2s_probe()
1448 spin_lock_init(&priv->pcm_lock); in samsung_i2s_probe()
1451 pri_dai->dma_playback.filter_data = i2s_pdata->dma_playback; in samsung_i2s_probe()
1452 pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture; in samsung_i2s_probe()
1453 pri_dai->filter = i2s_pdata->dma_filter; in samsung_i2s_probe()
1455 idma_addr = i2s_pdata->type.idma_addr; in samsung_i2s_probe()
1457 if (of_property_read_u32(np, "samsung,idma-addr", in samsung_i2s_probe()
1459 if (priv->quirks & QUIRK_SUPPORTS_IDMA) { in samsung_i2s_probe()
1460 dev_info(&pdev->dev, "idma address is not"\ in samsung_i2s_probe()
1466 priv->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in samsung_i2s_probe()
1467 if (IS_ERR(priv->addr)) in samsung_i2s_probe()
1468 return PTR_ERR(priv->addr); in samsung_i2s_probe()
1470 regs_base = res->start; in samsung_i2s_probe()
1472 priv->clk = devm_clk_get(&pdev->dev, "iis"); in samsung_i2s_probe()
1473 if (IS_ERR(priv->clk)) { in samsung_i2s_probe()
1474 dev_err(&pdev->dev, "Failed to get iis clock\n"); in samsung_i2s_probe()
1475 return PTR_ERR(priv->clk); in samsung_i2s_probe()
1478 ret = clk_prepare_enable(priv->clk); in samsung_i2s_probe()
1480 dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); in samsung_i2s_probe()
1483 pri_dai->dma_playback.addr = regs_base + I2STXD; in samsung_i2s_probe()
1484 pri_dai->dma_capture.addr = regs_base + I2SRXD; in samsung_i2s_probe()
1485 pri_dai->dma_playback.chan_name = "tx"; in samsung_i2s_probe()
1486 pri_dai->dma_capture.chan_name = "rx"; in samsung_i2s_probe()
1487 pri_dai->dma_playback.addr_width = 4; in samsung_i2s_probe()
1488 pri_dai->dma_capture.addr_width = 4; in samsung_i2s_probe()
1489 pri_dai->priv = priv; in samsung_i2s_probe()
1491 if (priv->quirks & QUIRK_PRI_6CHAN) in samsung_i2s_probe()
1492 pri_dai->drv->playback.channels_max = 6; in samsung_i2s_probe()
1494 ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter, in samsung_i2s_probe()
1499 if (priv->quirks & QUIRK_SEC_DAI) { in samsung_i2s_probe()
1500 sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1]; in samsung_i2s_probe()
1502 sec_dai->dma_playback.addr = regs_base + I2STXDS; in samsung_i2s_probe()
1503 sec_dai->dma_playback.chan_name = "tx-sec"; in samsung_i2s_probe()
1506 sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec; in samsung_i2s_probe()
1507 sec_dai->filter = i2s_pdata->dma_filter; in samsung_i2s_probe()
1510 sec_dai->dma_playback.addr_width = 4; in samsung_i2s_probe()
1511 sec_dai->idma_playback.addr = idma_addr; in samsung_i2s_probe()
1512 sec_dai->pri_dai = pri_dai; in samsung_i2s_probe()
1513 sec_dai->priv = priv; in samsung_i2s_probe()
1514 pri_dai->sec_dai = sec_dai; in samsung_i2s_probe()
1520 ret = samsung_asoc_dma_platform_register(&priv->pdev_sec->dev, in samsung_i2s_probe()
1521 sec_dai->filter, "tx-sec", NULL, in samsung_i2s_probe()
1522 &pdev->dev); in samsung_i2s_probe()
1528 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { in samsung_i2s_probe()
1529 dev_err(&pdev->dev, "Unable to configure gpio\n"); in samsung_i2s_probe()
1530 ret = -EINVAL; in samsung_i2s_probe()
1534 dev_set_drvdata(&pdev->dev, priv); in samsung_i2s_probe()
1536 ret = devm_snd_soc_register_component(&pdev->dev, in samsung_i2s_probe()
1538 priv->dai_drv, num_dais); in samsung_i2s_probe()
1542 pm_runtime_set_active(&pdev->dev); in samsung_i2s_probe()
1543 pm_runtime_enable(&pdev->dev); in samsung_i2s_probe()
1549 priv->op_clk = clk_get_parent(priv->clk_table[CLK_I2S_RCLK_SRC]); in samsung_i2s_probe()
1554 pm_runtime_disable(&pdev->dev); in samsung_i2s_probe()
1558 clk_disable_unprepare(priv->clk); in samsung_i2s_probe()
1564 struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev); in samsung_i2s_remove()
1570 pm_runtime_get_sync(&pdev->dev); in samsung_i2s_remove()
1571 pm_runtime_disable(&pdev->dev); in samsung_i2s_remove()
1575 clk_disable_unprepare(priv->clk); in samsung_i2s_remove()
1577 pm_runtime_put_noidle(&pdev->dev); in samsung_i2s_remove()
1584 struct i2s_dai *i2s = to_info(asoc_rtd_to_cpu(rtd, 0)); in fsd_i2s_fixup_early() local
1585 struct i2s_dai *other = get_other_dai(i2s); in fsd_i2s_fixup_early()
1598 struct i2s_dai *i2s = to_info(asoc_rtd_to_cpu(rtd, 0)); in fsd_i2s_fixup_late() local
1599 struct i2s_dai *other = get_other_dai(i2s); in fsd_i2s_fixup_late()
1602 writel(PSR_PSVAL(2) | PSR_PSREN, priv->addr + I2SPSR); in fsd_i2s_fixup_late()
1704 .name = "samsung-i2s",
1714 .compatible = "samsung,s3c6410-i2s",
1717 .compatible = "samsung,s5pv210-i2s",
1720 .compatible = "samsung,exynos5420-i2s",
1723 .compatible = "samsung,exynos7-i2s",
1726 .compatible = "samsung,exynos7-i2s1",
1729 .compatible = "tesla,fsd-i2s",
1749 .name = "samsung-i2s",
1759 MODULE_DESCRIPTION("Samsung I2S Interface");
1760 MODULE_ALIAS("platform:samsung-i2s");