Lines Matching +full:frame +full:- +full:inversion
1 // SPDX-License-Identifier: GPL-2.0+
3 // imx-ssi.c -- ALSA Soc Audio Layer
15 // we receive in our (PCM-) data stream. The only chance we have is to
17 // from 48000Hz not every frame has valid receive data, so the ratio
30 #include <linux/dma-mapping.h>
43 #include <linux/platform_data/asoc-imx-ssi.h>
45 #include "imx-ssi.h"
60 sccr = readl(ssi->base + SSI_STCCR); in imx_ssi_set_dai_tdm_slot()
62 sccr |= SSI_STCCR_DC(slots - 1); in imx_ssi_set_dai_tdm_slot()
63 writel(sccr, ssi->base + SSI_STCCR); in imx_ssi_set_dai_tdm_slot()
65 sccr = readl(ssi->base + SSI_SRCCR); in imx_ssi_set_dai_tdm_slot()
67 sccr |= SSI_STCCR_DC(slots - 1); in imx_ssi_set_dai_tdm_slot()
68 writel(sccr, ssi->base + SSI_SRCCR); in imx_ssi_set_dai_tdm_slot()
70 writel(~tx_mask, ssi->base + SSI_STMSK); in imx_ssi_set_dai_tdm_slot()
71 writel(~rx_mask, ssi->base + SSI_SRMSK); in imx_ssi_set_dai_tdm_slot()
85 scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); in imx_ssi_set_dai_fmt()
90 /* data on rising edge of bclk, frame low 1clk before data */ in imx_ssi_set_dai_fmt()
94 if (ssi->flags & IMX_SSI_USE_I2S_SLAVE) { in imx_ssi_set_dai_fmt()
100 /* data on rising edge of bclk, frame high with data */ in imx_ssi_set_dai_fmt()
104 /* data on rising edge of bclk, frame high with data */ in imx_ssi_set_dai_fmt()
108 /* data on rising edge of bclk, frame high 1clk before data */ in imx_ssi_set_dai_fmt()
114 /* DAI clock inversion */ in imx_ssi_set_dai_fmt()
135 return -EINVAL; in imx_ssi_set_dai_fmt()
140 if (ssi->flags & IMX_SSI_NET) in imx_ssi_set_dai_fmt()
142 if (ssi->flags & IMX_SSI_SYN) in imx_ssi_set_dai_fmt()
145 writel(strcr, ssi->base + SSI_STCR); in imx_ssi_set_dai_fmt()
146 writel(strcr, ssi->base + SSI_SRCR); in imx_ssi_set_dai_fmt()
147 writel(scr, ssi->base + SSI_SCR); in imx_ssi_set_dai_fmt()
162 scr = readl(ssi->base + SSI_SCR); in imx_ssi_set_dai_sysclk()
172 return -EINVAL; in imx_ssi_set_dai_sysclk()
175 writel(scr, ssi->base + SSI_SCR); in imx_ssi_set_dai_sysclk()
190 stccr = readl(ssi->base + SSI_STCCR); in imx_ssi_set_dai_clkdiv()
191 srccr = readl(ssi->base + SSI_SRCCR); in imx_ssi_set_dai_clkdiv()
219 return -EINVAL; in imx_ssi_set_dai_clkdiv()
222 writel(stccr, ssi->base + SSI_STCCR); in imx_ssi_set_dai_clkdiv()
223 writel(srccr, ssi->base + SSI_SRCCR); in imx_ssi_set_dai_clkdiv()
240 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in imx_ssi_hw_params()
245 if (ssi->flags & IMX_SSI_SYN) in imx_ssi_hw_params()
248 sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK; in imx_ssi_hw_params()
263 writel(sccr, ssi->base + reg); in imx_ssi_hw_params()
275 scr = readl(ssi->base + SSI_SCR); in imx_ssi_trigger()
276 sier = readl(ssi->base + SSI_SIER); in imx_ssi_trigger()
278 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in imx_ssi_trigger()
279 if (ssi->flags & IMX_SSI_DMA) in imx_ssi_trigger()
284 if (ssi->flags & IMX_SSI_DMA) in imx_ssi_trigger()
294 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in imx_ssi_trigger()
307 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in imx_ssi_trigger()
318 return -EINVAL; in imx_ssi_trigger()
321 if (!(ssi->flags & IMX_SSI_USE_AC97)) in imx_ssi_trigger()
323 writel(scr, ssi->base + SSI_SCR); in imx_ssi_trigger()
325 writel(sier, ssi->base + SSI_SIER); in imx_ssi_trigger()
341 struct imx_ssi *ssi = dev_get_drvdata(dai->dev); in imx_ssi_dai_probe()
346 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.maxburst) | in imx_ssi_dai_probe()
347 SSI_SFCSR_RFWM0(ssi->dma_params_rx.maxburst); in imx_ssi_dai_probe()
348 writel(val, ssi->base + SSI_SFCSR); in imx_ssi_dai_probe()
351 dai->playback_dma_data = &ssi->dma_params_tx; in imx_ssi_dai_probe()
352 dai->capture_dma_data = &ssi->dma_params_rx; in imx_ssi_dai_probe()
399 void __iomem *base = imx_ssi->base; in setup_channel_to_ac97()
433 void __iomem *base = imx_ssi->base; in imx_ssi_ac97_write()
456 void __iomem *base = imx_ssi->base; in imx_ssi_ac97_read()
458 unsigned short val = -1; in imx_ssi_ac97_read()
478 if (imx_ssi->ac97_reset) in imx_ssi_ac97_reset()
479 imx_ssi->ac97_reset(ac97); in imx_ssi_ac97_reset()
488 if (imx_ssi->ac97_warm_reset) in imx_ssi_ac97_warm_reset()
489 imx_ssi->ac97_warm_reset(ac97); in imx_ssi_ac97_warm_reset()
506 struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; in imx_ssi_probe()
510 ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); in imx_ssi_probe()
512 return -ENOMEM; in imx_ssi_probe()
513 dev_set_drvdata(&pdev->dev, ssi); in imx_ssi_probe()
516 ssi->ac97_reset = pdata->ac97_reset; in imx_ssi_probe()
517 ssi->ac97_warm_reset = pdata->ac97_warm_reset; in imx_ssi_probe()
518 ssi->flags = pdata->flags; in imx_ssi_probe()
521 ssi->irq = platform_get_irq(pdev, 0); in imx_ssi_probe()
522 if (ssi->irq < 0) in imx_ssi_probe()
523 return ssi->irq; in imx_ssi_probe()
525 ssi->clk = devm_clk_get(&pdev->dev, NULL); in imx_ssi_probe()
526 if (IS_ERR(ssi->clk)) { in imx_ssi_probe()
527 ret = PTR_ERR(ssi->clk); in imx_ssi_probe()
528 dev_err(&pdev->dev, "Cannot get the clock: %d\n", in imx_ssi_probe()
532 ret = clk_prepare_enable(ssi->clk); in imx_ssi_probe()
537 ssi->base = devm_ioremap_resource(&pdev->dev, res); in imx_ssi_probe()
538 if (IS_ERR(ssi->base)) { in imx_ssi_probe()
539 ret = PTR_ERR(ssi->base); in imx_ssi_probe()
543 if (ssi->flags & IMX_SSI_USE_AC97) { in imx_ssi_probe()
545 dev_err(&pdev->dev, "AC'97 SSI already registered\n"); in imx_ssi_probe()
546 ret = -EBUSY; in imx_ssi_probe()
555 writel(0x0, ssi->base + SSI_SIER); in imx_ssi_probe()
557 ssi->dma_params_rx.addr = res->start + SSI_SRX0; in imx_ssi_probe()
558 ssi->dma_params_tx.addr = res->start + SSI_STX0; in imx_ssi_probe()
560 ssi->dma_params_tx.maxburst = 6; in imx_ssi_probe()
561 ssi->dma_params_rx.maxburst = 4; in imx_ssi_probe()
563 ssi->dma_params_tx.filter_data = &ssi->filter_data_tx; in imx_ssi_probe()
564 ssi->dma_params_rx.filter_data = &ssi->filter_data_rx; in imx_ssi_probe()
568 imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start, in imx_ssi_probe()
574 imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start, in imx_ssi_probe()
582 dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); in imx_ssi_probe()
586 ret = snd_soc_register_component(&pdev->dev, &imx_component, in imx_ssi_probe()
589 dev_err(&pdev->dev, "register DAI failed\n"); in imx_ssi_probe()
593 ssi->fiq_params.irq = ssi->irq; in imx_ssi_probe()
594 ssi->fiq_params.base = ssi->base; in imx_ssi_probe()
595 ssi->fiq_params.dma_params_rx = &ssi->dma_params_rx; in imx_ssi_probe()
596 ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx; in imx_ssi_probe()
598 ssi->fiq_init = imx_pcm_fiq_init(pdev, &ssi->fiq_params); in imx_ssi_probe()
599 ssi->dma_init = imx_pcm_dma_init(pdev, IMX_SSI_DMABUF_SIZE); in imx_ssi_probe()
601 if (ssi->fiq_init && ssi->dma_init) { in imx_ssi_probe()
602 ret = ssi->fiq_init; in imx_ssi_probe()
609 snd_soc_unregister_component(&pdev->dev); in imx_ssi_probe()
611 clk_disable_unprepare(ssi->clk); in imx_ssi_probe()
622 if (!ssi->fiq_init) in imx_ssi_remove()
625 snd_soc_unregister_component(&pdev->dev); in imx_ssi_remove()
627 if (ssi->flags & IMX_SSI_USE_AC97) in imx_ssi_remove()
630 clk_disable_unprepare(ssi->clk); in imx_ssi_remove()
641 .name = "imx-ssi",
651 MODULE_ALIAS("platform:imx-ssi");