Lines Matching +full:mmp +full:- +full:sspa
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * linux/sound/soc/pxa/mmp-sspa.c
4 * Base on pxa2xx-ssp.c
23 #include <sound/pxa2xx-lib.h>
25 #include "mmp-sspa.h"
28 * SSPA audio private data
45 static void mmp_sspa_tx_enable(struct sspa_priv *sspa) in mmp_sspa_tx_enable() argument
47 unsigned int sspa_sp = sspa->sp; in mmp_sspa_tx_enable()
52 __raw_writel(sspa_sp, sspa->tx_base + SSPA_SP); in mmp_sspa_tx_enable()
55 static void mmp_sspa_tx_disable(struct sspa_priv *sspa) in mmp_sspa_tx_disable() argument
57 unsigned int sspa_sp = sspa->sp; in mmp_sspa_tx_disable()
62 __raw_writel(sspa_sp, sspa->tx_base + SSPA_SP); in mmp_sspa_tx_disable()
65 static void mmp_sspa_rx_enable(struct sspa_priv *sspa) in mmp_sspa_rx_enable() argument
67 unsigned int sspa_sp = sspa->sp; in mmp_sspa_rx_enable()
71 __raw_writel(sspa_sp, sspa->rx_base + SSPA_SP); in mmp_sspa_rx_enable()
74 static void mmp_sspa_rx_disable(struct sspa_priv *sspa) in mmp_sspa_rx_disable() argument
76 unsigned int sspa_sp = sspa->sp; in mmp_sspa_rx_disable()
80 __raw_writel(sspa_sp, sspa->rx_base + SSPA_SP); in mmp_sspa_rx_disable()
86 struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); in mmp_sspa_startup() local
88 clk_prepare_enable(sspa->sysclk); in mmp_sspa_startup()
89 clk_prepare_enable(sspa->clk); in mmp_sspa_startup()
97 struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); in mmp_sspa_shutdown() local
99 clk_disable_unprepare(sspa->clk); in mmp_sspa_shutdown()
100 clk_disable_unprepare(sspa->sysclk); in mmp_sspa_shutdown()
109 struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); in mmp_sspa_set_dai_sysclk() local
110 struct device *dev = cpu_dai->component->dev; in mmp_sspa_set_dai_sysclk()
113 if (dev->of_node) in mmp_sspa_set_dai_sysclk()
114 return -ENOTSUPP; in mmp_sspa_set_dai_sysclk()
118 ret = clk_set_rate(sspa->audio_clk, freq); in mmp_sspa_set_dai_sysclk()
125 return -EINVAL; in mmp_sspa_set_dai_sysclk()
127 return -EINVAL; in mmp_sspa_set_dai_sysclk()
137 struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); in mmp_sspa_set_dai_pll() local
138 struct device *dev = cpu_dai->component->dev; in mmp_sspa_set_dai_pll()
141 if (dev->of_node) in mmp_sspa_set_dai_pll()
142 return -ENOTSUPP; in mmp_sspa_set_dai_pll()
146 ret = clk_set_rate(sspa->sysclk, freq_out); in mmp_sspa_set_dai_pll()
151 ret = clk_set_rate(sspa->clk, freq_out); in mmp_sspa_set_dai_pll()
156 return -ENODEV; in mmp_sspa_set_dai_pll()
163 * Set up the sspa dai format.
168 struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai); in mmp_sspa_set_dai_fmt() local
171 sspa->sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH; in mmp_sspa_set_dai_fmt()
172 sspa->ctrl = 0; in mmp_sspa_set_dai_fmt()
176 sspa->sp |= SSPA_SP_MSL; in mmp_sspa_set_dai_fmt()
181 return -EINVAL; in mmp_sspa_set_dai_fmt()
186 sspa->sp |= SSPA_SP_FSP; in mmp_sspa_set_dai_fmt()
189 return -EINVAL; in mmp_sspa_set_dai_fmt()
194 sspa->ctrl |= SSPA_CTL_XDATDLY(1); in mmp_sspa_set_dai_fmt()
197 return -EINVAL; in mmp_sspa_set_dai_fmt()
208 * Set the SSPA audio DMA parameters and sample size.
215 struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); in mmp_sspa_hw_params() local
216 struct device *dev = dai->component->dev; in mmp_sspa_hw_params()
217 u32 sspa_ctrl = sspa->ctrl; in mmp_sspa_hw_params()
239 return -EINVAL; in mmp_sspa_hw_params()
242 if (dev->of_node || params_channels(params) == 2) in mmp_sspa_hw_params()
254 sspa->sp &= ~SSPA_SP_FWID_MASK; in mmp_sspa_hw_params()
255 sspa->sp |= SSPA_SP_FWID(bits - 1); in mmp_sspa_hw_params()
257 sspa->sp &= ~SSPA_TXSP_FPER_MASK; in mmp_sspa_hw_params()
258 sspa->sp |= SSPA_TXSP_FPER(bits * 2 - 1); in mmp_sspa_hw_params()
260 if (dev->of_node) { in mmp_sspa_hw_params()
261 clk_set_rate(sspa->clk, params_rate(params) * in mmp_sspa_hw_params()
265 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in mmp_sspa_hw_params()
266 __raw_writel(sspa_ctrl, sspa->tx_base + SSPA_CTL); in mmp_sspa_hw_params()
267 __raw_writel(0x1, sspa->tx_base + SSPA_FIFO_UL); in mmp_sspa_hw_params()
269 __raw_writel(sspa_ctrl, sspa->rx_base + SSPA_CTL); in mmp_sspa_hw_params()
270 __raw_writel(0x0, sspa->rx_base + SSPA_FIFO_UL); in mmp_sspa_hw_params()
279 struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); in mmp_sspa_trigger() local
292 if (!sspa->running_cnt) in mmp_sspa_trigger()
293 mmp_sspa_rx_enable(sspa); in mmp_sspa_trigger()
295 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in mmp_sspa_trigger()
296 mmp_sspa_tx_enable(sspa); in mmp_sspa_trigger()
298 sspa->running_cnt++; in mmp_sspa_trigger()
304 sspa->running_cnt--; in mmp_sspa_trigger()
306 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in mmp_sspa_trigger()
307 mmp_sspa_tx_disable(sspa); in mmp_sspa_trigger()
310 if (!sspa->running_cnt) in mmp_sspa_trigger()
311 mmp_sspa_rx_disable(sspa); in mmp_sspa_trigger()
315 ret = -EINVAL; in mmp_sspa_trigger()
323 struct sspa_priv *sspa = dev_get_drvdata(dai->dev); in mmp_sspa_probe() local
326 &sspa->playback_dma_data, in mmp_sspa_probe()
327 &sspa->capture_dma_data); in mmp_sspa_probe()
329 snd_soc_dai_set_drvdata(dai, sspa); in mmp_sspa_probe()
404 vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; in mmp_pcm_mmap()
405 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); in mmp_pcm_mmap()
406 return remap_pfn_range(vma, vma->vm_start, in mmp_pcm_mmap()
407 substream->dma_buffer.addr >> PAGE_SHIFT, in mmp_pcm_mmap()
408 vma->vm_end - vma->vm_start, vma->vm_page_prot); in mmp_pcm_mmap()
414 struct sspa_priv *sspa = snd_soc_component_get_drvdata(component); in mmp_sspa_open() local
416 pm_runtime_get_sync(component->dev); in mmp_sspa_open()
419 if ((__raw_readl(sspa->tx_base + SSPA_SP) & SSPA_SP_S_EN) || in mmp_sspa_open()
420 (__raw_readl(sspa->rx_base + SSPA_SP) & SSPA_SP_S_EN)) { in mmp_sspa_open()
421 dev_err(component->dev, in mmp_sspa_open()
423 return -EBUSY; in mmp_sspa_open()
426 __raw_writel(sspa->sp, sspa->tx_base + SSPA_SP); in mmp_sspa_open()
427 __raw_writel(sspa->sp, sspa->rx_base + SSPA_SP); in mmp_sspa_open()
429 sspa->sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH); in mmp_sspa_open()
430 __raw_writel(sspa->sp, sspa->tx_base + SSPA_SP); in mmp_sspa_open()
431 __raw_writel(sspa->sp, sspa->rx_base + SSPA_SP); in mmp_sspa_open()
440 __raw_writel(sspa->sp & ~SSPA_SP_MSL, sspa->tx_base + SSPA_SP); in mmp_sspa_open()
442 __raw_writel(sspa->ctrl, sspa->tx_base + SSPA_CTL); in mmp_sspa_open()
443 __raw_writel(sspa->ctrl, sspa->rx_base + SSPA_CTL); in mmp_sspa_open()
451 pm_runtime_put_sync(component->dev); in mmp_sspa_close()
456 .name = "mmp-sspa",
464 struct sspa_priv *sspa; in asoc_mmp_sspa_probe() local
467 sspa = devm_kzalloc(&pdev->dev, in asoc_mmp_sspa_probe()
469 if (!sspa) in asoc_mmp_sspa_probe()
470 return -ENOMEM; in asoc_mmp_sspa_probe()
472 if (pdev->dev.of_node) { in asoc_mmp_sspa_probe()
473 sspa->rx_base = devm_platform_ioremap_resource(pdev, 0); in asoc_mmp_sspa_probe()
474 if (IS_ERR(sspa->rx_base)) in asoc_mmp_sspa_probe()
475 return PTR_ERR(sspa->rx_base); in asoc_mmp_sspa_probe()
477 sspa->tx_base = devm_platform_ioremap_resource(pdev, 1); in asoc_mmp_sspa_probe()
478 if (IS_ERR(sspa->tx_base)) in asoc_mmp_sspa_probe()
479 return PTR_ERR(sspa->tx_base); in asoc_mmp_sspa_probe()
481 sspa->clk = devm_clk_get(&pdev->dev, "bitclk"); in asoc_mmp_sspa_probe()
482 if (IS_ERR(sspa->clk)) in asoc_mmp_sspa_probe()
483 return PTR_ERR(sspa->clk); in asoc_mmp_sspa_probe()
485 sspa->audio_clk = devm_clk_get(&pdev->dev, "audio"); in asoc_mmp_sspa_probe()
486 if (IS_ERR(sspa->audio_clk)) in asoc_mmp_sspa_probe()
487 return PTR_ERR(sspa->audio_clk); in asoc_mmp_sspa_probe()
493 return -ENODEV; in asoc_mmp_sspa_probe()
495 sspa->rx_base = devm_ioremap(&pdev->dev, res->start, 0x30); in asoc_mmp_sspa_probe()
496 if (!sspa->rx_base) in asoc_mmp_sspa_probe()
497 return -ENOMEM; in asoc_mmp_sspa_probe()
499 sspa->tx_base = devm_ioremap(&pdev->dev, in asoc_mmp_sspa_probe()
500 res->start + 0x80, 0x30); in asoc_mmp_sspa_probe()
501 if (!sspa->tx_base) in asoc_mmp_sspa_probe()
502 return -ENOMEM; in asoc_mmp_sspa_probe()
504 sspa->clk = devm_clk_get(&pdev->dev, NULL); in asoc_mmp_sspa_probe()
505 if (IS_ERR(sspa->clk)) in asoc_mmp_sspa_probe()
506 return PTR_ERR(sspa->clk); in asoc_mmp_sspa_probe()
508 sspa->audio_clk = clk_get(NULL, "mmp-audio"); in asoc_mmp_sspa_probe()
509 if (IS_ERR(sspa->audio_clk)) in asoc_mmp_sspa_probe()
510 return PTR_ERR(sspa->audio_clk); in asoc_mmp_sspa_probe()
512 sspa->sysclk = clk_get(NULL, "mmp-sysclk"); in asoc_mmp_sspa_probe()
513 if (IS_ERR(sspa->sysclk)) { in asoc_mmp_sspa_probe()
514 clk_put(sspa->audio_clk); in asoc_mmp_sspa_probe()
515 return PTR_ERR(sspa->sysclk); in asoc_mmp_sspa_probe()
518 platform_set_drvdata(pdev, sspa); in asoc_mmp_sspa_probe()
520 sspa->playback_dma_data.maxburst = 4; in asoc_mmp_sspa_probe()
521 sspa->capture_dma_data.maxburst = 4; in asoc_mmp_sspa_probe()
523 sspa->capture_dma_data.addr = SSPA_D; in asoc_mmp_sspa_probe()
524 sspa->playback_dma_data.addr = 0x80 + SSPA_D; in asoc_mmp_sspa_probe()
526 if (pdev->dev.of_node) { in asoc_mmp_sspa_probe()
527 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, in asoc_mmp_sspa_probe()
533 ret = devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component, in asoc_mmp_sspa_probe()
538 pm_runtime_enable(&pdev->dev); in asoc_mmp_sspa_probe()
539 clk_prepare_enable(sspa->audio_clk); in asoc_mmp_sspa_probe()
546 struct sspa_priv *sspa = platform_get_drvdata(pdev); in asoc_mmp_sspa_remove() local
548 clk_disable_unprepare(sspa->audio_clk); in asoc_mmp_sspa_remove()
549 pm_runtime_disable(&pdev->dev); in asoc_mmp_sspa_remove()
551 if (pdev->dev.of_node) in asoc_mmp_sspa_remove()
554 clk_put(sspa->audio_clk); in asoc_mmp_sspa_remove()
555 clk_put(sspa->sysclk); in asoc_mmp_sspa_remove()
561 { .compatible = "marvell,mmp-sspa" },
570 .name = "mmp-sspa-dai",
580 MODULE_DESCRIPTION("MMP SSPA SoC Interface");
582 MODULE_ALIAS("platform:mmp-sspa-dai");