Lines Matching full:i2s

3 // ALSA SoC Audio Layer - Samsung I2S Controller driver
8 #include <dt-bindings/sound/samsung-i2s.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()
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()
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()
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()
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()
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()
377 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); 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()
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()
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()
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()
536 (any_active(i2s) && in i2s_set_sysclk()
541 dev_err(&i2s->pdev->dev, in i2s_set_sysclk()
550 i2s->rfs = rfs; in i2s_set_sysclk()
563 if (!any_active(i2s)) { 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()
599 dev_err(&i2s->pdev->dev, in i2s_set_sysclk()
612 dev_err(&i2s->pdev->dev, "We don't serve that!\n"); in i2s_set_sysclk()
634 struct i2s_dai *i2s = to_info(dai); in i2s_set_fmt() local
660 dev_err(&i2s->pdev->dev, "Format not supported\n"); in i2s_set_fmt()
678 dev_err(&i2s->pdev->dev, "Polarity not supported\n"); in i2s_set_fmt()
697 dev_err(&i2s->pdev->dev, "master/slave format not supported\n"); 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()
712 dev_err(&i2s->pdev->dev, in i2s_set_fmt()
731 struct i2s_dai *i2s = to_info(dai); in i2s_hw_params() local
738 if (!is_secondary(i2s)) 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()
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()
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()
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()
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()
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()
855 struct i2s_dai *i2s = to_info(dai); in i2s_shutdown() local
856 struct i2s_dai *other = get_other_dai(i2s); in i2s_shutdown()
861 i2s->mode &= ~DAI_OPENED; in i2s_shutdown()
862 i2s->mode &= ~DAI_MANAGER; in i2s_shutdown()
868 i2s->rfs = 0; in i2s_shutdown()
869 i2s->bfs = 0; 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()
894 rfs = i2s->rfs; in config_setup()
900 dev_err(&i2s->pdev->dev, 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()
919 set_bfs(i2s, bfs); in config_setup()
920 set_rfs(i2s, rfs); in config_setup()
927 psr = priv->rclk_srcrate / i2s->frmclk / rfs; in config_setup()
929 dev_dbg(&i2s->pdev->dev, in config_setup()
943 struct i2s_dai *i2s = to_info(asoc_rtd_to_cpu(rtd, 0)); in i2s_trigger() local
957 if (config_setup(i2s)) { in i2s_trigger()
966 i2s_rxctrl(i2s, 1); in i2s_trigger()
968 i2s_txctrl(i2s, 1); 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()
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()
1002 if ((any_active(i2s) && div && (get_bfs(i2s) != div)) in i2s_set_clkdiv()
1005 dev_err(&i2s->pdev->dev, in i2s_set_clkdiv()
1009 i2s->bfs = div; in i2s_set_clkdiv()
1013 dev_err(&i2s->pdev->dev, in i2s_set_clkdiv()
1025 struct i2s_dai *i2s = to_info(dai); in i2s_delay() local
1033 else if (is_secondary(i2s)) in i2s_delay()
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()
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()
1081 i2s->rfs = 0; in samsung_i2s_dai_probe()
1082 i2s->bfs = 0; 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()
1104 struct i2s_dai *i2s = to_info(dai); in samsung_i2s_dai_remove() local
1109 if (!is_secondary(i2s)) { in samsung_i2s_dai_remove()
1153 .name = "samsung-i2s",
1174 static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" }; in i2s_alloc_dais()
1367 pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL); in i2s_create_secondary_device()
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()
1704 .name = "samsung-i2s",
1714 .compatible = "samsung,s3c6410-i2s",
1717 .compatible = "samsung,s5pv210-i2s",
1720 .compatible = "samsung,exynos5420-i2s",
1723 .compatible = "samsung,exynos7-i2s",
1729 .compatible = "tesla,fsd-i2s",
1749 .name = "samsung-i2s",
1759 MODULE_DESCRIPTION("Samsung I2S Interface");
1760 MODULE_ALIAS("platform:samsung-i2s");