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()
243 if (dev->of_node || params_channels(params) == 2) in mmp_sspa_hw_params()
258 sspa->sp &= ~SSPA_SP_FWID_MASK; in mmp_sspa_hw_params()
259 sspa->sp |= SSPA_SP_FWID(bits - 1); in mmp_sspa_hw_params()
261 sspa->sp &= ~SSPA_TXSP_FPER_MASK; in mmp_sspa_hw_params()
262 sspa->sp |= SSPA_TXSP_FPER(bits * 2 - 1); in mmp_sspa_hw_params()
264 if (dev->of_node) { in mmp_sspa_hw_params()
265 clk_set_rate(sspa->clk, params_rate(params) * in mmp_sspa_hw_params()
269 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in mmp_sspa_hw_params()
270 __raw_writel(sspa_ctrl, sspa->tx_base + SSPA_CTL); in mmp_sspa_hw_params()
271 __raw_writel(0x1, sspa->tx_base + SSPA_FIFO_UL); in mmp_sspa_hw_params()
273 __raw_writel(sspa_ctrl, sspa->rx_base + SSPA_CTL); in mmp_sspa_hw_params()
274 __raw_writel(0x0, sspa->rx_base + SSPA_FIFO_UL); in mmp_sspa_hw_params()
283 struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai); in mmp_sspa_trigger() local
296 if (!sspa->running_cnt) in mmp_sspa_trigger()
297 mmp_sspa_rx_enable(sspa); in mmp_sspa_trigger()
299 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in mmp_sspa_trigger()
300 mmp_sspa_tx_enable(sspa); in mmp_sspa_trigger()
302 sspa->running_cnt++; in mmp_sspa_trigger()
308 sspa->running_cnt--; in mmp_sspa_trigger()
310 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in mmp_sspa_trigger()
311 mmp_sspa_tx_disable(sspa); in mmp_sspa_trigger()
314 if (!sspa->running_cnt) in mmp_sspa_trigger()
315 mmp_sspa_rx_disable(sspa); in mmp_sspa_trigger()
319 ret = -EINVAL; in mmp_sspa_trigger()
327 struct sspa_priv *sspa = dev_get_drvdata(dai->dev); in mmp_sspa_probe() local
330 &sspa->playback_dma_data, in mmp_sspa_probe()
331 &sspa->capture_dma_data); in mmp_sspa_probe()
408 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); in mmp_pcm_mmap()
409 return remap_pfn_range(vma, vma->vm_start, in mmp_pcm_mmap()
410 substream->dma_buffer.addr >> PAGE_SHIFT, in mmp_pcm_mmap()
411 vma->vm_end - vma->vm_start, vma->vm_page_prot); in mmp_pcm_mmap()
417 struct sspa_priv *sspa = snd_soc_component_get_drvdata(component); in mmp_sspa_open() local
419 pm_runtime_get_sync(component->dev); in mmp_sspa_open()
422 if ((__raw_readl(sspa->tx_base + SSPA_SP) & SSPA_SP_S_EN) || in mmp_sspa_open()
423 (__raw_readl(sspa->rx_base + SSPA_SP) & SSPA_SP_S_EN)) { in mmp_sspa_open()
424 dev_err(component->dev, in mmp_sspa_open()
426 return -EBUSY; in mmp_sspa_open()
429 __raw_writel(sspa->sp, sspa->tx_base + SSPA_SP); in mmp_sspa_open()
430 __raw_writel(sspa->sp, sspa->rx_base + SSPA_SP); in mmp_sspa_open()
432 sspa->sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH); in mmp_sspa_open()
433 __raw_writel(sspa->sp, sspa->tx_base + SSPA_SP); in mmp_sspa_open()
434 __raw_writel(sspa->sp, sspa->rx_base + SSPA_SP); in mmp_sspa_open()
443 __raw_writel(sspa->sp & ~SSPA_SP_MSL, sspa->tx_base + SSPA_SP); in mmp_sspa_open()
445 __raw_writel(sspa->ctrl, sspa->tx_base + SSPA_CTL); in mmp_sspa_open()
446 __raw_writel(sspa->ctrl, sspa->rx_base + SSPA_CTL); in mmp_sspa_open()
454 pm_runtime_put_sync(component->dev); in mmp_sspa_close()
459 .name = "mmp-sspa",
468 struct sspa_priv *sspa; in asoc_mmp_sspa_probe() local
471 sspa = devm_kzalloc(&pdev->dev, in asoc_mmp_sspa_probe()
473 if (!sspa) in asoc_mmp_sspa_probe()
474 return -ENOMEM; in asoc_mmp_sspa_probe()
476 if (pdev->dev.of_node) { in asoc_mmp_sspa_probe()
477 sspa->rx_base = devm_platform_ioremap_resource(pdev, 0); in asoc_mmp_sspa_probe()
478 if (IS_ERR(sspa->rx_base)) in asoc_mmp_sspa_probe()
479 return PTR_ERR(sspa->rx_base); in asoc_mmp_sspa_probe()
481 sspa->tx_base = devm_platform_ioremap_resource(pdev, 1); in asoc_mmp_sspa_probe()
482 if (IS_ERR(sspa->tx_base)) in asoc_mmp_sspa_probe()
483 return PTR_ERR(sspa->tx_base); in asoc_mmp_sspa_probe()
485 sspa->clk = devm_clk_get(&pdev->dev, "bitclk"); in asoc_mmp_sspa_probe()
486 if (IS_ERR(sspa->clk)) in asoc_mmp_sspa_probe()
487 return PTR_ERR(sspa->clk); in asoc_mmp_sspa_probe()
489 sspa->audio_clk = devm_clk_get(&pdev->dev, "audio"); in asoc_mmp_sspa_probe()
490 if (IS_ERR(sspa->audio_clk)) in asoc_mmp_sspa_probe()
491 return PTR_ERR(sspa->audio_clk); in asoc_mmp_sspa_probe()
497 return -ENODEV; in asoc_mmp_sspa_probe()
499 sspa->rx_base = devm_ioremap(&pdev->dev, res->start, 0x30); in asoc_mmp_sspa_probe()
500 if (!sspa->rx_base) in asoc_mmp_sspa_probe()
501 return -ENOMEM; in asoc_mmp_sspa_probe()
503 sspa->tx_base = devm_ioremap(&pdev->dev, in asoc_mmp_sspa_probe()
504 res->start + 0x80, 0x30); in asoc_mmp_sspa_probe()
505 if (!sspa->tx_base) in asoc_mmp_sspa_probe()
506 return -ENOMEM; in asoc_mmp_sspa_probe()
508 sspa->clk = devm_clk_get(&pdev->dev, NULL); in asoc_mmp_sspa_probe()
509 if (IS_ERR(sspa->clk)) in asoc_mmp_sspa_probe()
510 return PTR_ERR(sspa->clk); in asoc_mmp_sspa_probe()
512 sspa->audio_clk = clk_get(NULL, "mmp-audio"); in asoc_mmp_sspa_probe()
513 if (IS_ERR(sspa->audio_clk)) in asoc_mmp_sspa_probe()
514 return PTR_ERR(sspa->audio_clk); in asoc_mmp_sspa_probe()
516 sspa->sysclk = clk_get(NULL, "mmp-sysclk"); in asoc_mmp_sspa_probe()
517 if (IS_ERR(sspa->sysclk)) { in asoc_mmp_sspa_probe()
518 clk_put(sspa->audio_clk); in asoc_mmp_sspa_probe()
519 return PTR_ERR(sspa->sysclk); in asoc_mmp_sspa_probe()
522 platform_set_drvdata(pdev, sspa); in asoc_mmp_sspa_probe()
524 sspa->playback_dma_data.maxburst = 4; in asoc_mmp_sspa_probe()
525 sspa->capture_dma_data.maxburst = 4; in asoc_mmp_sspa_probe()
527 sspa->capture_dma_data.addr = SSPA_D; in asoc_mmp_sspa_probe()
528 sspa->playback_dma_data.addr = 0x80 + SSPA_D; in asoc_mmp_sspa_probe()
530 if (pdev->dev.of_node) { in asoc_mmp_sspa_probe()
531 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, in asoc_mmp_sspa_probe()
537 ret = devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component, in asoc_mmp_sspa_probe()
542 pm_runtime_enable(&pdev->dev); in asoc_mmp_sspa_probe()
543 clk_prepare_enable(sspa->audio_clk); in asoc_mmp_sspa_probe()
550 struct sspa_priv *sspa = platform_get_drvdata(pdev); in asoc_mmp_sspa_remove() local
552 clk_disable_unprepare(sspa->audio_clk); in asoc_mmp_sspa_remove()
553 pm_runtime_disable(&pdev->dev); in asoc_mmp_sspa_remove()
555 if (pdev->dev.of_node) in asoc_mmp_sspa_remove()
558 clk_put(sspa->audio_clk); in asoc_mmp_sspa_remove()
559 clk_put(sspa->sysclk); in asoc_mmp_sspa_remove()
564 { .compatible = "marvell,mmp-sspa" },
573 .name = "mmp-sspa-dai",
583 MODULE_DESCRIPTION("MMP SSPA SoC Interface");
585 MODULE_ALIAS("platform:mmp-sspa-dai");