hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/sound/soc/sunxi/sun4i-spdif.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * ALSA SoC SPDIF Audio Layer
34 *
....@@ -5,16 +6,6 @@
56 * Copyright 2015 Marcus Cooper <codekipper@gmail.com>
67 *
78 * Based on the Allwinner SDK driver, released under the GPL.
8
- *
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License as published by
11
- * the Free Software Foundation; either version 2 of the License, or
12
- * (at your option) any later version.
13
- *
14
- * This program is distributed in the hope that it will be useful,
15
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- * GNU General Public License for more details.
189 */
1910
2011 #include <linux/clk.h>
....@@ -74,6 +65,18 @@
7465 #define SUN4I_SPDIF_FCTL_TXIM BIT(2)
7566 #define SUN4I_SPDIF_FCTL_RXOM(v) ((v) << 0)
7667 #define SUN4I_SPDIF_FCTL_RXOM_MASK GENMASK(1, 0)
68
+
69
+#define SUN50I_H6_SPDIF_FCTL (0x14)
70
+ #define SUN50I_H6_SPDIF_FCTL_HUB_EN BIT(31)
71
+ #define SUN50I_H6_SPDIF_FCTL_FTX BIT(30)
72
+ #define SUN50I_H6_SPDIF_FCTL_FRX BIT(29)
73
+ #define SUN50I_H6_SPDIF_FCTL_TXTL(v) ((v) << 12)
74
+ #define SUN50I_H6_SPDIF_FCTL_TXTL_MASK GENMASK(19, 12)
75
+ #define SUN50I_H6_SPDIF_FCTL_RXTL(v) ((v) << 4)
76
+ #define SUN50I_H6_SPDIF_FCTL_RXTL_MASK GENMASK(10, 4)
77
+ #define SUN50I_H6_SPDIF_FCTL_TXIM BIT(2)
78
+ #define SUN50I_H6_SPDIF_FCTL_RXOM(v) ((v) << 0)
79
+ #define SUN50I_H6_SPDIF_FCTL_RXOM_MASK GENMASK(1, 0)
7780
7881 #define SUN4I_SPDIF_FSTA (0x18)
7982 #define SUN4I_SPDIF_FSTA_TXE BIT(14)
....@@ -161,6 +164,19 @@
161164 #define SUN4I_SPDIF_SAMFREQ_176_4KHZ 0xc
162165 #define SUN4I_SPDIF_SAMFREQ_192KHZ 0xe
163166
167
+/**
168
+ * struct sun4i_spdif_quirks - Differences between SoC variants.
169
+ *
170
+ * @reg_dac_txdata: TX FIFO offset for DMA config.
171
+ * @has_reset: SoC needs reset deasserted.
172
+ * @val_fctl_ftx: TX FIFO flush bitmask.
173
+ */
174
+struct sun4i_spdif_quirks {
175
+ unsigned int reg_dac_txdata;
176
+ bool has_reset;
177
+ unsigned int val_fctl_ftx;
178
+};
179
+
164180 struct sun4i_spdif_dev {
165181 struct platform_device *pdev;
166182 struct clk *spdif_clk;
....@@ -169,16 +185,19 @@
169185 struct snd_soc_dai_driver cpu_dai_drv;
170186 struct regmap *regmap;
171187 struct snd_dmaengine_dai_dma_data dma_params_tx;
188
+ const struct sun4i_spdif_quirks *quirks;
172189 };
173190
174191 static void sun4i_spdif_configure(struct sun4i_spdif_dev *host)
175192 {
193
+ const struct sun4i_spdif_quirks *quirks = host->quirks;
194
+
176195 /* soft reset SPDIF */
177196 regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET);
178197
179198 /* flush TX FIFO */
180199 regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL,
181
- SUN4I_SPDIF_FCTL_FTX, SUN4I_SPDIF_FCTL_FTX);
200
+ quirks->val_fctl_ftx, quirks->val_fctl_ftx);
182201
183202 /* clear TX counter */
184203 regmap_write(host->regmap, SUN4I_SPDIF_TXCNT, 0);
....@@ -224,8 +243,8 @@
224243 static int sun4i_spdif_startup(struct snd_pcm_substream *substream,
225244 struct snd_soc_dai *cpu_dai)
226245 {
227
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
228
- struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(rtd->cpu_dai);
246
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
247
+ struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
229248
230249 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
231250 return -EINVAL;
....@@ -405,23 +424,27 @@
405424 .name = "spdif",
406425 };
407426
408
-struct sun4i_spdif_quirks {
409
- unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */
410
- bool has_reset;
411
-};
412
-
413427 static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = {
414428 .reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
429
+ .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
415430 };
416431
417432 static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = {
418433 .reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
434
+ .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
419435 .has_reset = true,
420436 };
421437
422438 static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = {
423439 .reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
440
+ .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX,
424441 .has_reset = true,
442
+};
443
+
444
+static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = {
445
+ .reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
446
+ .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX,
447
+ .has_reset = true,
425448 };
426449
427450 static const struct of_device_id sun4i_spdif_of_match[] = {
....@@ -436,6 +459,10 @@
436459 {
437460 .compatible = "allwinner,sun8i-h3-spdif",
438461 .data = &sun8i_h3_spdif_quirks,
462
+ },
463
+ {
464
+ .compatible = "allwinner,sun50i-h6-spdif",
465
+ .data = &sun50i_h6_spdif_quirks,
439466 },
440467 { /* sentinel */ }
441468 };
....@@ -501,6 +528,7 @@
501528 dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
502529 return -ENODEV;
503530 }
531
+ host->quirks = quirks;
504532
505533 host->regmap = devm_regmap_init_mmio(&pdev->dev, base,
506534 &sun4i_spdif_regmap_config);
....@@ -527,7 +555,7 @@
527555 if (quirks->has_reset) {
528556 host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
529557 NULL);
530
- if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) {
558
+ if (PTR_ERR(host->rst) == -EPROBE_DEFER) {
531559 ret = -EPROBE_DEFER;
532560 dev_err(&pdev->dev, "Failed to get reset: %d\n", ret);
533561 return ret;