Lines Matching full:i2s

3 // ALSA SoC Audio Layer - Samsung I2S Controller driver
8 #include <dt-bindings/sound/samsung-i2s.h>
25 #include "i2s.h"
26 #include "i2s-regs.h"
101 /* The I2S controller's core clock */
104 /* Clock for generating I2S signals */
110 /* Cache of selected I2S registers for system suspend */
132 /* A flag indicating the I2S slave mode operation */
137 static inline bool is_secondary(struct i2s_dai *i2s) in is_secondary() argument
139 return i2s->drv->id == SAMSUNG_I2S_ID_SECONDARY; in is_secondary()
143 static inline bool tx_active(struct i2s_dai *i2s) in tx_active() argument
147 if (!i2s) in tx_active()
150 active = readl(i2s->priv->addr + I2SCON); in tx_active()
152 if (is_secondary(i2s)) in tx_active()
161 static inline struct i2s_dai *get_other_dai(struct i2s_dai *i2s) in get_other_dai() argument
163 return i2s->pri_dai ? : i2s->sec_dai; in get_other_dai()
167 static inline bool other_tx_active(struct i2s_dai *i2s) in other_tx_active() argument
169 struct i2s_dai *other = get_other_dai(i2s); in other_tx_active()
175 static inline bool any_tx_active(struct i2s_dai *i2s) in any_tx_active() argument
177 return tx_active(i2s) || other_tx_active(i2s); in any_tx_active()
181 static inline bool rx_active(struct i2s_dai *i2s) in rx_active() argument
185 if (!i2s) in rx_active()
188 active = readl(i2s->priv->addr + I2SCON) & CON_RXDMA_ACTIVE; in rx_active()
194 static inline bool other_rx_active(struct i2s_dai *i2s) in other_rx_active() argument
196 struct i2s_dai *other = get_other_dai(i2s); in other_rx_active()
202 static inline bool any_rx_active(struct i2s_dai *i2s) in any_rx_active() argument
204 return rx_active(i2s) || other_rx_active(i2s); in any_rx_active()
208 static inline bool other_active(struct i2s_dai *i2s) in other_active() argument
210 return other_rx_active(i2s) || other_tx_active(i2s); in other_active()
214 static inline bool this_active(struct i2s_dai *i2s) in this_active() argument
216 return tx_active(i2s) || rx_active(i2s); in this_active()
220 static inline bool any_active(struct i2s_dai *i2s) in any_active() argument
222 return this_active(i2s) || other_active(i2s); in any_active()
232 static inline bool is_opened(struct i2s_dai *i2s) in is_opened() argument
234 if (i2s && (i2s->mode & DAI_OPENED)) in is_opened()
240 static inline bool is_manager(struct i2s_dai *i2s) in is_manager() argument
242 if (is_opened(i2s) && (i2s->mode & DAI_MANAGER)) in is_manager()
248 /* Read RCLK of I2S (in multiples of LRCLK) */
249 static inline unsigned get_rfs(struct i2s_dai *i2s) in get_rfs() argument
251 struct samsung_i2s_priv *priv = i2s->priv; in get_rfs()
269 /* Write RCLK of I2S (in multiples of LRCLK) */
270 static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) in set_rfs() argument
272 struct samsung_i2s_priv *priv = i2s->priv; in set_rfs()
308 /* Read bit-clock of I2S (in multiples of LRCLK) */
309 static inline unsigned get_bfs(struct i2s_dai *i2s) in get_bfs() argument
311 struct samsung_i2s_priv *priv = i2s->priv; in get_bfs()
330 /* Write bit-clock of I2S (in multiples of LRCLK) */
331 static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) in set_bfs() argument
333 struct samsung_i2s_priv *priv = i2s->priv; 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()
375 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); in set_bfs()
383 static inline int get_blc(struct i2s_dai *i2s) in get_blc() argument
385 int blc = readl(i2s->priv->addr + I2SMOD); in get_blc()
397 static void i2s_txctrl(struct i2s_dai *i2s, int on) in i2s_txctrl() argument
399 struct samsung_i2s_priv *priv = i2s->priv; in i2s_txctrl()
409 if (is_secondary(i2s)) { in i2s_txctrl()
417 if (any_rx_active(i2s)) in i2s_txctrl()
422 if (is_secondary(i2s)) { in i2s_txctrl()
430 if (other_tx_active(i2s)) { in i2s_txctrl()
437 if (any_rx_active(i2s)) in i2s_txctrl()
448 static void i2s_rxctrl(struct i2s_dai *i2s, int on) in i2s_rxctrl() argument
450 struct samsung_i2s_priv *priv = i2s->priv; in i2s_rxctrl()
460 if (any_tx_active(i2s)) in i2s_rxctrl()
468 if (any_tx_active(i2s)) in i2s_rxctrl()
479 static inline void i2s_fifo(struct i2s_dai *i2s, u32 flush) in i2s_fifo() argument
484 if (!i2s) in i2s_fifo()
487 if (is_secondary(i2s)) in i2s_fifo()
488 fic = i2s->priv->addr + I2SFICS; in i2s_fifo()
490 fic = i2s->priv->addr + I2SFIC; in i2s_fifo()
507 struct i2s_dai *i2s = to_info(dai); in i2s_set_sysclk() local
508 struct i2s_dai *other = get_other_dai(i2s); in i2s_set_sysclk()
534 (any_active(i2s) && in i2s_set_sysclk()
539 dev_err(&i2s->pdev->dev, in i2s_set_sysclk()
548 i2s->rfs = rfs; in i2s_set_sysclk()
561 if (!any_active(i2s)) { 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()
597 dev_err(&i2s->pdev->dev, in i2s_set_sysclk()
610 dev_err(&i2s->pdev->dev, "We don't serve that!\n"); in i2s_set_sysclk()
632 struct i2s_dai *i2s = to_info(dai); in i2s_set_fmt() local
658 dev_err(&i2s->pdev->dev, "Format not supported\n"); in i2s_set_fmt()
676 dev_err(&i2s->pdev->dev, "Polarity not supported\n"); in i2s_set_fmt()
695 dev_err(&i2s->pdev->dev, "master/slave format not supported\n"); in i2s_set_fmt()
703 * Don't change the I2S mode if any controller is active on this in i2s_set_fmt()
706 if (any_active(i2s) && in i2s_set_fmt()
710 dev_err(&i2s->pdev->dev, in i2s_set_fmt()
729 struct i2s_dai *i2s = to_info(dai); in i2s_hw_params() local
736 if (!is_secondary(i2s)) 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()
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()
765 if (is_secondary(i2s)) in i2s_hw_params()
770 if (is_manager(i2s)) in i2s_hw_params()
775 if (is_secondary(i2s)) in i2s_hw_params()
779 if (is_manager(i2s)) in i2s_hw_params()
783 if (is_secondary(i2s)) in i2s_hw_params()
787 if (is_manager(i2s)) in i2s_hw_params()
791 if (is_secondary(i2s)) in i2s_hw_params()
795 if (is_manager(i2s)) in i2s_hw_params()
799 dev_err(&i2s->pdev->dev, "Format(%d) not supported\n", 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()
821 /* We set constraints on the substream according to the version of I2S */
826 struct i2s_dai *i2s = to_info(dai); in i2s_startup() local
827 struct i2s_dai *other = get_other_dai(i2s); 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()
853 struct i2s_dai *i2s = to_info(dai); in i2s_shutdown() local
854 struct i2s_dai *other = get_other_dai(i2s); in i2s_shutdown()
859 i2s->mode &= ~DAI_OPENED; in i2s_shutdown()
860 i2s->mode &= ~DAI_MANAGER; in i2s_shutdown()
866 i2s->rfs = 0; in i2s_shutdown()
867 i2s->bfs = 0; in i2s_shutdown()
874 static int config_setup(struct i2s_dai *i2s) in config_setup() argument
876 struct samsung_i2s_priv *priv = i2s->priv; in config_setup()
877 struct i2s_dai *other = get_other_dai(i2s); in config_setup()
881 blc = get_blc(i2s); in config_setup()
883 bfs = i2s->bfs; in config_setup()
892 rfs = i2s->rfs; in config_setup()
898 dev_err(&i2s->pdev->dev, in config_setup()
911 if (any_active(i2s) && (get_rfs(i2s) != rfs || get_bfs(i2s) != bfs)) { in config_setup()
912 dev_err(&i2s->pdev->dev, in config_setup()
917 set_bfs(i2s, bfs); in config_setup()
918 set_rfs(i2s, rfs); in config_setup()
925 psr = priv->rclk_srcrate / i2s->frmclk / rfs; in config_setup()
927 dev_dbg(&i2s->pdev->dev, in config_setup()
941 struct i2s_dai *i2s = to_info(snd_soc_rtd_to_cpu(rtd, 0)); in i2s_trigger() local
955 if (config_setup(i2s)) { in i2s_trigger()
964 i2s_rxctrl(i2s, 1); in i2s_trigger()
966 i2s_txctrl(i2s, 1); in i2s_trigger()
976 i2s_rxctrl(i2s, 0); in i2s_trigger()
977 i2s_fifo(i2s, FIC_RXFLUSH); in i2s_trigger()
979 i2s_txctrl(i2s, 0); in i2s_trigger()
980 i2s_fifo(i2s, FIC_TXFLUSH); in i2s_trigger()
994 struct i2s_dai *i2s = to_info(dai); in i2s_set_clkdiv() local
995 struct i2s_dai *other = get_other_dai(i2s); in i2s_set_clkdiv()
1000 if ((any_active(i2s) && div && (get_bfs(i2s) != div)) in i2s_set_clkdiv()
1003 dev_err(&i2s->pdev->dev, in i2s_set_clkdiv()
1007 i2s->bfs = div; in i2s_set_clkdiv()
1011 dev_err(&i2s->pdev->dev, in i2s_set_clkdiv()
1023 struct i2s_dai *i2s = to_info(dai); in i2s_delay() local
1031 else if (is_secondary(i2s)) in i2s_delay()
1057 struct i2s_dai *i2s = to_info(dai); in samsung_i2s_dai_probe() local
1058 struct i2s_dai *other = get_other_dai(i2s); in samsung_i2s_dai_probe()
1063 if (is_secondary(i2s)) { 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()
1079 i2s->rfs = 0; in samsung_i2s_dai_probe()
1080 i2s->bfs = 0; in samsung_i2s_dai_probe()
1083 i2s_txctrl(i2s, 0); in samsung_i2s_dai_probe()
1084 i2s_rxctrl(i2s, 0); in samsung_i2s_dai_probe()
1085 i2s_fifo(i2s, FIC_TXFLUSH); in samsung_i2s_dai_probe()
1087 i2s_fifo(i2s, FIC_RXFLUSH); in samsung_i2s_dai_probe()
1102 struct i2s_dai *i2s = to_info(dai); in samsung_i2s_dai_remove() local
1107 if (!is_secondary(i2s)) { in samsung_i2s_dai_remove()
1151 .name = "samsung-i2s",
1172 static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" }; in i2s_alloc_dais()
1365 pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL); in i2s_create_secondary_device()
1582 struct i2s_dai *i2s = to_info(snd_soc_rtd_to_cpu(rtd, 0)); in fsd_i2s_fixup_early() local
1583 struct i2s_dai *other = get_other_dai(i2s); in fsd_i2s_fixup_early()
1596 struct i2s_dai *i2s = to_info(snd_soc_rtd_to_cpu(rtd, 0)); in fsd_i2s_fixup_late() local
1597 struct i2s_dai *other = get_other_dai(i2s); 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",
1727 .compatible = "tesla,fsd-i2s",
1747 .name = "samsung-i2s",
1757 MODULE_DESCRIPTION("Samsung I2S Interface");