aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcus Cooper <codekipper@gmail.com>2016-02-08 12:09:21 -0500
committerMark Brown <broonie@kernel.org>2016-02-19 11:25:51 -0500
commitf8260afa444b670016f22f2ba1440d9d2e74dcb6 (patch)
tree47ce83c423ad037fe08d1da08f297dc82d044104
parent8020e1bbaa5e8d8340ab78c71a69ccdd362ab203 (diff)
ASoC: sunxi: Add support for the SPDIF block
The sun4i, sun5i and sun7i SoC families have an SPDIF block which is capable of playback and capture. This patch enables the playback of this block for the sun4i families. Signed-off-by: Marcus Cooper <codekipper@gmail.com> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/sunxi/Kconfig8
-rw-r--r--sound/soc/sunxi/Makefile1
-rw-r--r--sound/soc/sunxi/sun4i-spdif.c550
3 files changed, 559 insertions, 0 deletions
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig
index 84c72ec6ad73..ae42294ef688 100644
--- a/sound/soc/sunxi/Kconfig
+++ b/sound/soc/sunxi/Kconfig
@@ -8,4 +8,12 @@ config SND_SUN4I_CODEC
8 Select Y or M to add support for the Codec embedded in the Allwinner 8 Select Y or M to add support for the Codec embedded in the Allwinner
9 A10 and affiliated SoCs. 9 A10 and affiliated SoCs.
10 10
11config SND_SUN4I_SPDIF
12 tristate "Allwinner A10 SPDIF Support"
13 depends on OF
14 select SND_SOC_GENERIC_DMAENGINE_PCM
15 select REGMAP_MMIO
16 help
17 Say Y or M to add support for the S/PDIF audio block in the Allwinner
18 A10 and affiliated SoCs.
11endmenu 19endmenu
diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile
index ea8a08c881d6..8f5e889667f1 100644
--- a/sound/soc/sunxi/Makefile
+++ b/sound/soc/sunxi/Makefile
@@ -1,2 +1,3 @@
1obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o 1obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o
2 2
3obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o
diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
new file mode 100644
index 000000000000..0b04fb02125c
--- /dev/null
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -0,0 +1,550 @@
1/*
2 * ALSA SoC SPDIF Audio Layer
3 *
4 * Copyright 2015 Andrea Venturi <be17068@iperbole.bo.it>
5 * Copyright 2015 Marcus Cooper <codekipper@gmail.com>
6 *
7 * 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.
18 */
19
20#include <linux/clk.h>
21#include <linux/delay.h>
22#include <linux/device.h>
23#include <linux/kernel.h>
24#include <linux/init.h>
25#include <linux/regmap.h>
26#include <linux/of_address.h>
27#include <linux/of_device.h>
28#include <linux/ioport.h>
29#include <linux/module.h>
30#include <linux/platform_device.h>
31#include <linux/pm_runtime.h>
32#include <sound/dmaengine_pcm.h>
33#include <sound/pcm_params.h>
34#include <sound/soc.h>
35
36#define SUN4I_SPDIF_CTL (0x00)
37 #define SUN4I_SPDIF_CTL_MCLKDIV(v) ((v) << 4) /* v even */
38 #define SUN4I_SPDIF_CTL_MCLKOUTEN BIT(2)
39 #define SUN4I_SPDIF_CTL_GEN BIT(1)
40 #define SUN4I_SPDIF_CTL_RESET BIT(0)
41
42#define SUN4I_SPDIF_TXCFG (0x04)
43 #define SUN4I_SPDIF_TXCFG_SINGLEMOD BIT(31)
44 #define SUN4I_SPDIF_TXCFG_ASS BIT(17)
45 #define SUN4I_SPDIF_TXCFG_NONAUDIO BIT(16)
46 #define SUN4I_SPDIF_TXCFG_TXRATIO(v) ((v) << 4)
47 #define SUN4I_SPDIF_TXCFG_TXRATIO_MASK GENMASK(8, 4)
48 #define SUN4I_SPDIF_TXCFG_FMTRVD GENMASK(3, 2)
49 #define SUN4I_SPDIF_TXCFG_FMT16BIT (0 << 2)
50 #define SUN4I_SPDIF_TXCFG_FMT20BIT (1 << 2)
51 #define SUN4I_SPDIF_TXCFG_FMT24BIT (2 << 2)
52 #define SUN4I_SPDIF_TXCFG_CHSTMODE BIT(1)
53 #define SUN4I_SPDIF_TXCFG_TXEN BIT(0)
54
55#define SUN4I_SPDIF_RXCFG (0x08)
56 #define SUN4I_SPDIF_RXCFG_LOCKFLAG BIT(4)
57 #define SUN4I_SPDIF_RXCFG_CHSTSRC BIT(3)
58 #define SUN4I_SPDIF_RXCFG_CHSTCP BIT(1)
59 #define SUN4I_SPDIF_RXCFG_RXEN BIT(0)
60
61#define SUN4I_SPDIF_TXFIFO (0x0C)
62
63#define SUN4I_SPDIF_RXFIFO (0x10)
64
65#define SUN4I_SPDIF_FCTL (0x14)
66 #define SUN4I_SPDIF_FCTL_FIFOSRC BIT(31)
67 #define SUN4I_SPDIF_FCTL_FTX BIT(17)
68 #define SUN4I_SPDIF_FCTL_FRX BIT(16)
69 #define SUN4I_SPDIF_FCTL_TXTL(v) ((v) << 8)
70 #define SUN4I_SPDIF_FCTL_TXTL_MASK GENMASK(12, 8)
71 #define SUN4I_SPDIF_FCTL_RXTL(v) ((v) << 3)
72 #define SUN4I_SPDIF_FCTL_RXTL_MASK GENMASK(7, 3)
73 #define SUN4I_SPDIF_FCTL_TXIM BIT(2)
74 #define SUN4I_SPDIF_FCTL_RXOM(v) ((v) << 0)
75 #define SUN4I_SPDIF_FCTL_RXOM_MASK GENMASK(1, 0)
76
77#define SUN4I_SPDIF_FSTA (0x18)
78 #define SUN4I_SPDIF_FSTA_TXE BIT(14)
79 #define SUN4I_SPDIF_FSTA_TXECNTSHT (8)
80 #define SUN4I_SPDIF_FSTA_RXA BIT(6)
81 #define SUN4I_SPDIF_FSTA_RXACNTSHT (0)
82
83#define SUN4I_SPDIF_INT (0x1C)
84 #define SUN4I_SPDIF_INT_RXLOCKEN BIT(18)
85 #define SUN4I_SPDIF_INT_RXUNLOCKEN BIT(17)
86 #define SUN4I_SPDIF_INT_RXPARERREN BIT(16)
87 #define SUN4I_SPDIF_INT_TXDRQEN BIT(7)
88 #define SUN4I_SPDIF_INT_TXUIEN BIT(6)
89 #define SUN4I_SPDIF_INT_TXOIEN BIT(5)
90 #define SUN4I_SPDIF_INT_TXEIEN BIT(4)
91 #define SUN4I_SPDIF_INT_RXDRQEN BIT(2)
92 #define SUN4I_SPDIF_INT_RXOIEN BIT(1)
93 #define SUN4I_SPDIF_INT_RXAIEN BIT(0)
94
95#define SUN4I_SPDIF_ISTA (0x20)
96 #define SUN4I_SPDIF_ISTA_RXLOCKSTA BIT(18)
97 #define SUN4I_SPDIF_ISTA_RXUNLOCKSTA BIT(17)
98 #define SUN4I_SPDIF_ISTA_RXPARERRSTA BIT(16)
99 #define SUN4I_SPDIF_ISTA_TXUSTA BIT(6)
100 #define SUN4I_SPDIF_ISTA_TXOSTA BIT(5)
101 #define SUN4I_SPDIF_ISTA_TXESTA BIT(4)
102 #define SUN4I_SPDIF_ISTA_RXOSTA BIT(1)
103 #define SUN4I_SPDIF_ISTA_RXASTA BIT(0)
104
105#define SUN4I_SPDIF_TXCNT (0x24)
106
107#define SUN4I_SPDIF_RXCNT (0x28)
108
109#define SUN4I_SPDIF_TXCHSTA0 (0x2C)
110 #define SUN4I_SPDIF_TXCHSTA0_CLK(v) ((v) << 28)
111 #define SUN4I_SPDIF_TXCHSTA0_SAMFREQ(v) ((v) << 24)
112 #define SUN4I_SPDIF_TXCHSTA0_SAMFREQ_MASK GENMASK(27, 24)
113 #define SUN4I_SPDIF_TXCHSTA0_CHNUM(v) ((v) << 20)
114 #define SUN4I_SPDIF_TXCHSTA0_CHNUM_MASK GENMASK(23, 20)
115 #define SUN4I_SPDIF_TXCHSTA0_SRCNUM(v) ((v) << 16)
116 #define SUN4I_SPDIF_TXCHSTA0_CATACOD(v) ((v) << 8)
117 #define SUN4I_SPDIF_TXCHSTA0_MODE(v) ((v) << 6)
118 #define SUN4I_SPDIF_TXCHSTA0_EMPHASIS(v) ((v) << 3)
119 #define SUN4I_SPDIF_TXCHSTA0_CP BIT(2)
120 #define SUN4I_SPDIF_TXCHSTA0_AUDIO BIT(1)
121 #define SUN4I_SPDIF_TXCHSTA0_PRO BIT(0)
122
123#define SUN4I_SPDIF_TXCHSTA1 (0x30)
124 #define SUN4I_SPDIF_TXCHSTA1_CGMSA(v) ((v) << 8)
125 #define SUN4I_SPDIF_TXCHSTA1_ORISAMFREQ(v) ((v) << 4)
126 #define SUN4I_SPDIF_TXCHSTA1_ORISAMFREQ_MASK GENMASK(7, 4)
127 #define SUN4I_SPDIF_TXCHSTA1_SAMWORDLEN(v) ((v) << 1)
128 #define SUN4I_SPDIF_TXCHSTA1_MAXWORDLEN BIT(0)
129
130#define SUN4I_SPDIF_RXCHSTA0 (0x34)
131 #define SUN4I_SPDIF_RXCHSTA0_CLK(v) ((v) << 28)
132 #define SUN4I_SPDIF_RXCHSTA0_SAMFREQ(v) ((v) << 24)
133 #define SUN4I_SPDIF_RXCHSTA0_CHNUM(v) ((v) << 20)
134 #define SUN4I_SPDIF_RXCHSTA0_SRCNUM(v) ((v) << 16)
135 #define SUN4I_SPDIF_RXCHSTA0_CATACOD(v) ((v) << 8)
136 #define SUN4I_SPDIF_RXCHSTA0_MODE(v) ((v) << 6)
137 #define SUN4I_SPDIF_RXCHSTA0_EMPHASIS(v) ((v) << 3)
138 #define SUN4I_SPDIF_RXCHSTA0_CP BIT(2)
139 #define SUN4I_SPDIF_RXCHSTA0_AUDIO BIT(1)
140 #define SUN4I_SPDIF_RXCHSTA0_PRO BIT(0)
141
142#define SUN4I_SPDIF_RXCHSTA1 (0x38)
143 #define SUN4I_SPDIF_RXCHSTA1_CGMSA(v) ((v) << 8)
144 #define SUN4I_SPDIF_RXCHSTA1_ORISAMFREQ(v) ((v) << 4)
145 #define SUN4I_SPDIF_RXCHSTA1_SAMWORDLEN(v) ((v) << 1)
146 #define SUN4I_SPDIF_RXCHSTA1_MAXWORDLEN BIT(0)
147
148/* Defines for Sampling Frequency */
149#define SUN4I_SPDIF_SAMFREQ_44_1KHZ 0x0
150#define SUN4I_SPDIF_SAMFREQ_NOT_INDICATED 0x1
151#define SUN4I_SPDIF_SAMFREQ_48KHZ 0x2
152#define SUN4I_SPDIF_SAMFREQ_32KHZ 0x3
153#define SUN4I_SPDIF_SAMFREQ_22_05KHZ 0x4
154#define SUN4I_SPDIF_SAMFREQ_24KHZ 0x6
155#define SUN4I_SPDIF_SAMFREQ_88_2KHZ 0x8
156#define SUN4I_SPDIF_SAMFREQ_76_8KHZ 0x9
157#define SUN4I_SPDIF_SAMFREQ_96KHZ 0xa
158#define SUN4I_SPDIF_SAMFREQ_176_4KHZ 0xc
159#define SUN4I_SPDIF_SAMFREQ_192KHZ 0xe
160
161struct sun4i_spdif_dev {
162 struct platform_device *pdev;
163 struct clk *spdif_clk;
164 struct clk *apb_clk;
165 struct snd_soc_dai_driver cpu_dai_drv;
166 struct regmap *regmap;
167 struct snd_dmaengine_dai_dma_data dma_params_tx;
168};
169
170static void sun4i_spdif_configure(struct sun4i_spdif_dev *host)
171{
172 /* soft reset SPDIF */
173 regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET);
174
175 /* flush TX FIFO */