summaryrefslogtreecommitdiff
path: root/sound/soc/sunxi/sun4i-spdif.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sunxi/sun4i-spdif.c')
-rw-r--r--sound/soc/sunxi/sun4i-spdif.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
index 88fbb3a1e660..eaefd07a5ed0 100644
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -103,6 +103,8 @@
#define SUN4I_SPDIF_ISTA_RXOSTA BIT(1)
#define SUN4I_SPDIF_ISTA_RXASTA BIT(0)
+#define SUN8I_SPDIF_TXFIFO (0x20)
+
#define SUN4I_SPDIF_TXCNT (0x24)
#define SUN4I_SPDIF_RXCNT (0x28)
@@ -403,17 +405,38 @@ static struct snd_soc_dai_driver sun4i_spdif_dai = {
.name = "spdif",
};
-static const struct snd_soc_dapm_widget dit_widgets[] = {
- SND_SOC_DAPM_OUTPUT("spdif-out"),
+struct sun4i_spdif_quirks {
+ unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */
+ bool has_reset;
+};
+
+static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = {
+ .reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
};
-static const struct snd_soc_dapm_route dit_routes[] = {
- { "spdif-out", NULL, "Playback" },
+static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = {
+ .reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
+ .has_reset = true,
+};
+
+static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = {
+ .reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
+ .has_reset = true,
};
static const struct of_device_id sun4i_spdif_of_match[] = {
- { .compatible = "allwinner,sun4i-a10-spdif", },
- { .compatible = "allwinner,sun6i-a31-spdif", },
+ {
+ .compatible = "allwinner,sun4i-a10-spdif",
+ .data = &sun4i_a10_spdif_quirks,
+ },
+ {
+ .compatible = "allwinner,sun6i-a31-spdif",
+ .data = &sun6i_a31_spdif_quirks,
+ },
+ {
+ .compatible = "allwinner,sun8i-h3-spdif",
+ .data = &sun8i_h3_spdif_quirks,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match);
@@ -446,6 +469,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev)
{
struct sun4i_spdif_dev *host;
struct resource *res;
+ const struct sun4i_spdif_quirks *quirks;
int ret;
void __iomem *base;
@@ -467,6 +491,12 @@ static int sun4i_spdif_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
+ quirks = of_device_get_match_data(&pdev->dev);
+ if (quirks == NULL) {
+ dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
+ return -ENODEV;
+ }
+
host->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&sun4i_spdif_regmap_config);
@@ -480,23 +510,21 @@ static int sun4i_spdif_probe(struct platform_device *pdev)
host->spdif_clk = devm_clk_get(&pdev->dev, "spdif");
if (IS_ERR(host->spdif_clk)) {
dev_err(&pdev->dev, "failed to get a spdif clock.\n");
- ret = PTR_ERR(host->spdif_clk);
- goto err_disable_apb_clk;
+ return PTR_ERR(host->spdif_clk);
}
- host->dma_params_tx.addr = res->start + SUN4I_SPDIF_TXFIFO;
+ host->dma_params_tx.addr = res->start + quirks->reg_dac_txdata;
host->dma_params_tx.maxburst = 8;
host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
platform_set_drvdata(pdev, host);
- if (of_device_is_compatible(pdev->dev.of_node,
- "allwinner,sun6i-a31-spdif")) {
+ if (quirks->has_reset) {
host->rst = devm_reset_control_get_optional(&pdev->dev, NULL);
if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
dev_err(&pdev->dev, "Failed to get reset: %d\n", ret);
- goto err_disable_apb_clk;
+ return ret;
}
if (!IS_ERR(host->rst))
reset_control_deassert(host->rst);
@@ -505,7 +533,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_component(&pdev->dev,
&sun4i_spdif_component, &sun4i_spdif_dai, 1);
if (ret)
- goto err_disable_apb_clk;
+ return ret;
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
@@ -523,9 +551,6 @@ err_suspend:
sun4i_spdif_runtime_suspend(&pdev->dev);
err_unregister:
pm_runtime_disable(&pdev->dev);
- snd_soc_unregister_component(&pdev->dev);
-err_disable_apb_clk:
- clk_disable_unprepare(host->apb_clk);
return ret;
}
@@ -535,9 +560,6 @@ static int sun4i_spdif_remove(struct platform_device *pdev)
if (!pm_runtime_status_suspended(&pdev->dev))
sun4i_spdif_runtime_suspend(&pdev->dev);
- snd_soc_unregister_platform(&pdev->dev);
- snd_soc_unregister_component(&pdev->dev);
-
return 0;
}