Lines Matching +full:sun4i +full:- +full:a10 +full:- +full:cpu +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0-or-later
11 #include <linux/clk.h>
168 * struct sun4i_spdif_quirks - Differences between SoC variants.
182 struct clk *spdif_clk;
183 struct clk *apb_clk;
193 const struct sun4i_spdif_quirks *quirks = host->quirks; in sun4i_spdif_configure()
196 regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET); in sun4i_spdif_configure()
199 regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, in sun4i_spdif_configure()
200 quirks->val_fctl_ftx, quirks->val_fctl_ftx); in sun4i_spdif_configure()
203 regmap_write(host->regmap, SUN4I_SPDIF_TXCNT, 0); in sun4i_spdif_configure()
209 if (substream->runtime->channels == 1) in sun4i_snd_txctrl_on()
210 regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG, in sun4i_snd_txctrl_on()
215 regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG, in sun4i_snd_txctrl_on()
219 regmap_update_bits(host->regmap, SUN4I_SPDIF_INT, in sun4i_snd_txctrl_on()
223 regmap_update_bits(host->regmap, SUN4I_SPDIF_CTL, in sun4i_snd_txctrl_on()
231 regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG, in sun4i_snd_txctrl_off()
235 regmap_update_bits(host->regmap, SUN4I_SPDIF_INT, in sun4i_snd_txctrl_off()
239 regmap_update_bits(host->regmap, SUN4I_SPDIF_CTL, in sun4i_snd_txctrl_off()
249 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) in sun4i_spdif_startup()
250 return -EINVAL; in sun4i_spdif_startup()
268 struct platform_device *pdev = host->pdev; in sun4i_spdif_hw_params()
280 return -EINVAL; in sun4i_spdif_hw_params()
294 return -EINVAL; in sun4i_spdif_hw_params()
312 return -EINVAL; in sun4i_spdif_hw_params()
315 ret = clk_set_rate(host->spdif_clk, mclk); in sun4i_spdif_hw_params()
317 dev_err(&pdev->dev, in sun4i_spdif_hw_params()
322 regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, in sun4i_spdif_hw_params()
346 return -EINVAL; in sun4i_spdif_hw_params()
353 reg_val |= SUN4I_SPDIF_TXCFG_TXRATIO(mclk_div - 1); in sun4i_spdif_hw_params()
354 regmap_write(host->regmap, SUN4I_SPDIF_TXCFG, reg_val); in sun4i_spdif_hw_params()
365 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) in sun4i_spdif_trigger()
366 return -EINVAL; in sun4i_spdif_trigger()
382 ret = -EINVAL; in sun4i_spdif_trigger()
392 snd_soc_dai_init_dma_data(dai, &host->dma_params_tx, NULL); in sun4i_spdif_soc_dai_probe()
452 .compatible = "allwinner,sun4i-a10-spdif",
456 .compatible = "allwinner,sun6i-a31-spdif",
460 .compatible = "allwinner,sun8i-h3-spdif",
464 .compatible = "allwinner,sun50i-h6-spdif",
472 .name = "sun4i-spdif",
479 clk_disable_unprepare(host->spdif_clk); in sun4i_spdif_runtime_suspend()
480 clk_disable_unprepare(host->apb_clk); in sun4i_spdif_runtime_suspend()
490 ret = clk_prepare_enable(host->spdif_clk); in sun4i_spdif_runtime_resume()
493 ret = clk_prepare_enable(host->apb_clk); in sun4i_spdif_runtime_resume()
495 clk_disable_unprepare(host->spdif_clk); in sun4i_spdif_runtime_resume()
508 dev_dbg(&pdev->dev, "Entered %s\n", __func__); in sun4i_spdif_probe()
510 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); in sun4i_spdif_probe()
512 return -ENOMEM; in sun4i_spdif_probe()
514 host->pdev = pdev; in sun4i_spdif_probe()
516 /* Initialize this copy of the CPU DAI driver structure */ in sun4i_spdif_probe()
517 memcpy(&host->cpu_dai_drv, &sun4i_spdif_dai, sizeof(sun4i_spdif_dai)); in sun4i_spdif_probe()
518 host->cpu_dai_drv.name = dev_name(&pdev->dev); in sun4i_spdif_probe()
522 base = devm_ioremap_resource(&pdev->dev, res); in sun4i_spdif_probe()
526 quirks = of_device_get_match_data(&pdev->dev); in sun4i_spdif_probe()
528 dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); in sun4i_spdif_probe()
529 return -ENODEV; in sun4i_spdif_probe()
531 host->quirks = quirks; in sun4i_spdif_probe()
533 host->regmap = devm_regmap_init_mmio(&pdev->dev, base, in sun4i_spdif_probe()
537 host->apb_clk = devm_clk_get(&pdev->dev, "apb"); in sun4i_spdif_probe()
538 if (IS_ERR(host->apb_clk)) { in sun4i_spdif_probe()
539 dev_err(&pdev->dev, "failed to get a apb clock.\n"); in sun4i_spdif_probe()
540 return PTR_ERR(host->apb_clk); in sun4i_spdif_probe()
543 host->spdif_clk = devm_clk_get(&pdev->dev, "spdif"); in sun4i_spdif_probe()
544 if (IS_ERR(host->spdif_clk)) { in sun4i_spdif_probe()
545 dev_err(&pdev->dev, "failed to get a spdif clock.\n"); in sun4i_spdif_probe()
546 return PTR_ERR(host->spdif_clk); in sun4i_spdif_probe()
549 host->dma_params_tx.addr = res->start + quirks->reg_dac_txdata; in sun4i_spdif_probe()
550 host->dma_params_tx.maxburst = 8; in sun4i_spdif_probe()
551 host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; in sun4i_spdif_probe()
555 if (quirks->has_reset) { in sun4i_spdif_probe()
556 host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, in sun4i_spdif_probe()
558 if (PTR_ERR(host->rst) == -EPROBE_DEFER) { in sun4i_spdif_probe()
559 ret = -EPROBE_DEFER; in sun4i_spdif_probe()
560 dev_err(&pdev->dev, "Failed to get reset: %d\n", ret); in sun4i_spdif_probe()
563 if (!IS_ERR(host->rst)) in sun4i_spdif_probe()
564 reset_control_deassert(host->rst); in sun4i_spdif_probe()
567 ret = devm_snd_soc_register_component(&pdev->dev, in sun4i_spdif_probe()
572 pm_runtime_enable(&pdev->dev); in sun4i_spdif_probe()
573 if (!pm_runtime_enabled(&pdev->dev)) { in sun4i_spdif_probe()
574 ret = sun4i_spdif_runtime_resume(&pdev->dev); in sun4i_spdif_probe()
579 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); in sun4i_spdif_probe()
584 if (!pm_runtime_status_suspended(&pdev->dev)) in sun4i_spdif_probe()
585 sun4i_spdif_runtime_suspend(&pdev->dev); in sun4i_spdif_probe()
587 pm_runtime_disable(&pdev->dev); in sun4i_spdif_probe()
593 pm_runtime_disable(&pdev->dev); in sun4i_spdif_remove()
594 if (!pm_runtime_status_suspended(&pdev->dev)) in sun4i_spdif_remove()
595 sun4i_spdif_runtime_suspend(&pdev->dev); in sun4i_spdif_remove()
607 .name = "sun4i-spdif",
619 MODULE_DESCRIPTION("Allwinner sun4i SPDIF SoC Interface");
621 MODULE_ALIAS("platform:sun4i-spdif");