Lines Matching +full:sun4i +full:- +full:a10 +full:- +full:spdif
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * ALSA SoC SPDIF Audio Layer
169 * struct sun4i_spdif_quirks - Differences between SoC variants.
195 const struct sun4i_spdif_quirks *quirks = host->quirks; in sun4i_spdif_configure()
197 /* soft reset SPDIF */ in sun4i_spdif_configure()
198 regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET); in sun4i_spdif_configure()
201 regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, in sun4i_spdif_configure()
202 quirks->val_fctl_ftx, quirks->val_fctl_ftx); in sun4i_spdif_configure()
205 regmap_write(host->regmap, SUN4I_SPDIF_TXCNT, 0); in sun4i_spdif_configure()
211 if (substream->runtime->channels == 1) in sun4i_snd_txctrl_on()
212 regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG, in sun4i_snd_txctrl_on()
216 /* SPDIF TX ENABLE */ in sun4i_snd_txctrl_on()
217 regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG, in sun4i_snd_txctrl_on()
221 regmap_update_bits(host->regmap, SUN4I_SPDIF_INT, in sun4i_snd_txctrl_on()
225 regmap_update_bits(host->regmap, SUN4I_SPDIF_CTL, in sun4i_snd_txctrl_on()
232 /* SPDIF TX DISABLE */ in sun4i_snd_txctrl_off()
233 regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG, in sun4i_snd_txctrl_off()
237 regmap_update_bits(host->regmap, SUN4I_SPDIF_INT, in sun4i_snd_txctrl_off()
241 regmap_update_bits(host->regmap, SUN4I_SPDIF_CTL, in sun4i_snd_txctrl_off()
251 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) in sun4i_spdif_startup()
252 return -EINVAL; in sun4i_spdif_startup()
270 struct platform_device *pdev = host->pdev; in sun4i_spdif_hw_params()
282 return -EINVAL; in sun4i_spdif_hw_params()
296 return -EINVAL; in sun4i_spdif_hw_params()
314 return -EINVAL; in sun4i_spdif_hw_params()
317 ret = clk_set_rate(host->spdif_clk, mclk); in sun4i_spdif_hw_params()
319 dev_err(&pdev->dev, in sun4i_spdif_hw_params()
320 "Setting SPDIF clock rate for %d Hz failed!\n", mclk); in sun4i_spdif_hw_params()
324 regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, in sun4i_spdif_hw_params()
348 return -EINVAL; in sun4i_spdif_hw_params()
355 reg_val |= SUN4I_SPDIF_TXCFG_TXRATIO(mclk_div - 1); in sun4i_spdif_hw_params()
356 regmap_write(host->regmap, SUN4I_SPDIF_TXCFG, reg_val); in sun4i_spdif_hw_params()
367 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) in sun4i_spdif_trigger()
368 return -EINVAL; in sun4i_spdif_trigger()
384 ret = -EINVAL; in sun4i_spdif_trigger()
393 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; in sun4i_spdif_info()
394 uinfo->count = 1; in sun4i_spdif_info()
402 u8 *status = ucontrol->value.iec958.status; in sun4i_spdif_get_status_mask()
419 u8 *status = ucontrol->value.iec958.status; in sun4i_spdif_get_status()
423 spin_lock_irqsave(&host->lock, flags); in sun4i_spdif_get_status()
425 regmap_read(host->regmap, SUN4I_SPDIF_TXCHSTA0, ®); in sun4i_spdif_get_status()
432 regmap_read(host->regmap, SUN4I_SPDIF_TXCHSTA1, ®); in sun4i_spdif_get_status()
437 spin_unlock_irqrestore(&host->lock, flags); in sun4i_spdif_get_status()
447 u8 *status = ucontrol->value.iec958.status; in sun4i_spdif_set_status()
452 spin_lock_irqsave(&host->lock, flags); in sun4i_spdif_set_status()
459 regmap_update_bits_check(host->regmap, SUN4I_SPDIF_TXCHSTA0, in sun4i_spdif_set_status()
465 regmap_update_bits_check(host->regmap, SUN4I_SPDIF_TXCHSTA1, in sun4i_spdif_set_status()
472 regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG, in sun4i_spdif_set_status()
476 spin_unlock_irqrestore(&host->lock, flags); in sun4i_spdif_set_status()
502 snd_soc_dai_init_dma_data(dai, &host->dma_params_tx, NULL); in sun4i_spdif_soc_dai_probe()
537 .name = "spdif",
565 .compatible = "allwinner,sun4i-a10-spdif",
569 .compatible = "allwinner,sun6i-a31-spdif",
573 .compatible = "allwinner,sun8i-h3-spdif",
577 .compatible = "allwinner,sun50i-h6-spdif",
581 .compatible = "allwinner,sun50i-h616-spdif",
590 .name = "sun4i-spdif",
598 clk_disable_unprepare(host->spdif_clk); in sun4i_spdif_runtime_suspend()
599 clk_disable_unprepare(host->apb_clk); in sun4i_spdif_runtime_suspend()
609 ret = clk_prepare_enable(host->spdif_clk); in sun4i_spdif_runtime_resume()
612 ret = clk_prepare_enable(host->apb_clk); in sun4i_spdif_runtime_resume()
614 clk_disable_unprepare(host->spdif_clk); in sun4i_spdif_runtime_resume()
627 dev_dbg(&pdev->dev, "Entered %s\n", __func__); in sun4i_spdif_probe()
629 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); in sun4i_spdif_probe()
631 return -ENOMEM; in sun4i_spdif_probe()
633 host->pdev = pdev; in sun4i_spdif_probe()
634 spin_lock_init(&host->lock); in sun4i_spdif_probe()
637 memcpy(&host->cpu_dai_drv, &sun4i_spdif_dai, sizeof(sun4i_spdif_dai)); in sun4i_spdif_probe()
638 host->cpu_dai_drv.name = dev_name(&pdev->dev); in sun4i_spdif_probe()
645 quirks = of_device_get_match_data(&pdev->dev); in sun4i_spdif_probe()
647 dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); in sun4i_spdif_probe()
648 return -ENODEV; in sun4i_spdif_probe()
650 host->quirks = quirks; in sun4i_spdif_probe()
652 host->regmap = devm_regmap_init_mmio(&pdev->dev, base, in sun4i_spdif_probe()
656 host->apb_clk = devm_clk_get(&pdev->dev, "apb"); in sun4i_spdif_probe()
657 if (IS_ERR(host->apb_clk)) { in sun4i_spdif_probe()
658 dev_err(&pdev->dev, "failed to get a apb clock.\n"); in sun4i_spdif_probe()
659 return PTR_ERR(host->apb_clk); in sun4i_spdif_probe()
662 host->spdif_clk = devm_clk_get(&pdev->dev, "spdif"); in sun4i_spdif_probe()
663 if (IS_ERR(host->spdif_clk)) { in sun4i_spdif_probe()
664 dev_err(&pdev->dev, "failed to get a spdif clock.\n"); in sun4i_spdif_probe()
665 return PTR_ERR(host->spdif_clk); in sun4i_spdif_probe()
668 host->dma_params_tx.addr = res->start + quirks->reg_dac_txdata; in sun4i_spdif_probe()
669 host->dma_params_tx.maxburst = 8; in sun4i_spdif_probe()
670 host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; in sun4i_spdif_probe()
674 if (quirks->has_reset) { in sun4i_spdif_probe()
675 host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, in sun4i_spdif_probe()
677 if (PTR_ERR(host->rst) == -EPROBE_DEFER) { in sun4i_spdif_probe()
678 ret = -EPROBE_DEFER; in sun4i_spdif_probe()
679 dev_err(&pdev->dev, "Failed to get reset: %d\n", ret); in sun4i_spdif_probe()
682 if (!IS_ERR(host->rst)) in sun4i_spdif_probe()
683 reset_control_deassert(host->rst); in sun4i_spdif_probe()
686 ret = devm_snd_soc_register_component(&pdev->dev, in sun4i_spdif_probe()
691 pm_runtime_enable(&pdev->dev); in sun4i_spdif_probe()
692 if (!pm_runtime_enabled(&pdev->dev)) { in sun4i_spdif_probe()
693 ret = sun4i_spdif_runtime_resume(&pdev->dev); in sun4i_spdif_probe()
698 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); in sun4i_spdif_probe()
703 if (!pm_runtime_status_suspended(&pdev->dev)) in sun4i_spdif_probe()
704 sun4i_spdif_runtime_suspend(&pdev->dev); in sun4i_spdif_probe()
706 pm_runtime_disable(&pdev->dev); in sun4i_spdif_probe()
712 pm_runtime_disable(&pdev->dev); in sun4i_spdif_remove()
713 if (!pm_runtime_status_suspended(&pdev->dev)) in sun4i_spdif_remove()
714 sun4i_spdif_runtime_suspend(&pdev->dev); in sun4i_spdif_remove()
724 .name = "sun4i-spdif",
736 MODULE_DESCRIPTION("Allwinner sun4i SPDIF SoC Interface");
738 MODULE_ALIAS("platform:sun4i-spdif");