aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatsuhiro Suzuki <suzuki.katsuhiro@socionext.com>2018-01-19 04:25:33 -0500
committerMark Brown <broonie@kernel.org>2018-02-12 07:49:54 -0500
commitdb4cb3d04eba91db48da0032c44b83ed7185973c (patch)
tree70e204cda2ad8fdd7e10b735c2450b4e7242e144
parente98131222ff931a670739cede00d1fb9d6f83763 (diff)
ASoC: uniphier: add support for UniPhier LD11/LD20 AIO driver
This patch adds support for UniPhier AIO sound driver which is included in UniPhier LD11/LD20 SoCs. Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/uniphier/Kconfig11
-rw-r--r--sound/soc/uniphier/Makefile2
-rw-r--r--sound/soc/uniphier/aio-ld11.c431
3 files changed, 444 insertions, 0 deletions
diff --git a/sound/soc/uniphier/Kconfig b/sound/soc/uniphier/Kconfig
index 1a55ccebd8f5..5da545b9bf2a 100644
--- a/sound/soc/uniphier/Kconfig
+++ b/sound/soc/uniphier/Kconfig
@@ -19,6 +19,17 @@ config SND_SOC_UNIPHIER_AIO
19 Select Y if you use such device. 19 Select Y if you use such device.
20 If unsure select "N". 20 If unsure select "N".
21 21
22config SND_SOC_UNIPHIER_LD11
23 tristate "UniPhier LD11/LD20 Device Driver"
24 depends on SND_SOC_UNIPHIER
25 select SND_SOC_UNIPHIER_AIO
26 select SND_SOC_UNIPHIER_AIO_DMA
27 help
28 This adds ASoC driver for Socionext UniPhier LD11/LD20
29 input and output that can be used with other codecs.
30 Select Y if you use such device.
31 If unsure select "N".
32
22config SND_SOC_UNIPHIER_EVEA_CODEC 33config SND_SOC_UNIPHIER_EVEA_CODEC
23 tristate "UniPhier SoC internal audio codec" 34 tristate "UniPhier SoC internal audio codec"
24 depends on SND_SOC_UNIPHIER 35 depends on SND_SOC_UNIPHIER
diff --git a/sound/soc/uniphier/Makefile b/sound/soc/uniphier/Makefile
index 4448175c70ab..587a89700950 100644
--- a/sound/soc/uniphier/Makefile
+++ b/sound/soc/uniphier/Makefile
@@ -1,7 +1,9 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2snd-soc-uniphier-aio-cpu-objs := aio-core.o aio-dma.o aio-cpu.o aio-compress.o 2snd-soc-uniphier-aio-cpu-objs := aio-core.o aio-dma.o aio-cpu.o aio-compress.o
3snd-soc-uniphier-aio-ld11-objs := aio-ld11.o
3 4
4obj-$(CONFIG_SND_SOC_UNIPHIER_AIO) += snd-soc-uniphier-aio-cpu.o 5obj-$(CONFIG_SND_SOC_UNIPHIER_AIO) += snd-soc-uniphier-aio-cpu.o
6obj-$(CONFIG_SND_SOC_UNIPHIER_LD11) += snd-soc-uniphier-aio-ld11.o
5 7
6snd-soc-uniphier-evea-objs := evea.o 8snd-soc-uniphier-evea-objs := evea.o
7obj-$(CONFIG_SND_SOC_UNIPHIER_EVEA_CODEC) += snd-soc-uniphier-evea.o 9obj-$(CONFIG_SND_SOC_UNIPHIER_EVEA_CODEC) += snd-soc-uniphier-evea.o
diff --git a/sound/soc/uniphier/aio-ld11.c b/sound/soc/uniphier/aio-ld11.c
new file mode 100644
index 000000000000..8e40e6c2e42f
--- /dev/null
+++ b/sound/soc/uniphier/aio-ld11.c
@@ -0,0 +1,431 @@
1// SPDX-License-Identifier: GPL-2.0
2//
3// Socionext UniPhier AIO ALSA driver for LD11/LD20.
4//
5// Copyright (c) 2016-2018 Socionext Inc.
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License
9// as published by the Free Software Foundation; version 2
10// of the License.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, see <http://www.gnu.org/licenses/>.
19
20#include <linux/module.h>
21
22#include "aio.h"
23
24static const struct uniphier_aio_spec uniphier_aio_ld11[] = {
25 /* for HDMI PCM In, Pin:AI1Dx */
26 {
27 .name = AUD_NAME_PCMIN1,
28 .gname = AUD_GNAME_HDMI,
29 .swm = {
30 .type = PORT_TYPE_I2S,
31 .dir = PORT_DIR_INPUT,
32 .rb = { 21, 14, },
33 .ch = { 21, 14, },
34 .iif = { 5, 3, },
35 .iport = { 0, AUD_HW_PCMIN1, },
36 },
37 },
38
39 /* for SIF In, Pin:AI2Dx */
40 {
41 .name = AUD_NAME_PCMIN2,
42 .swm = {
43 .type = PORT_TYPE_I2S,
44 .dir = PORT_DIR_INPUT,
45 .rb = { 22, 15, },
46 .ch = { 22, 15, },
47 .iif = { 6, 4, },
48 .iport = { 1, AUD_HW_PCMIN2, },
49 },
50 },
51
52 /* for Line In, Pin:AI3Dx */
53 {
54 .name = AUD_NAME_PCMIN3,
55 .gname = AUD_GNAME_LINE,
56 .swm = {
57 .type = PORT_TYPE_EVE,
58 .dir = PORT_DIR_INPUT,
59 .rb = { 23, 16, },
60 .ch = { 23, 16, },
61 .iif = { 7, 5, },
62 .iport = { 2, AUD_HW_PCMIN3, },
63 },
64 },
65
66 /* for S/PDIF In, Pin:AI1IEC */
67 {
68 .name = AUD_NAME_IECIN1,
69 .gname = AUD_GNAME_IEC,
70 .swm = {
71 .type = PORT_TYPE_SPDIF,
72 .dir = PORT_DIR_INPUT,
73 .rb = { 26, 17, },
74 .ch = { 26, 17, },
75 .iif = { 10, 6, },
76 .iport = { 3, AUD_HW_IECIN1, },
77 },
78 },
79
80 /* for Speaker, Pin:AO1Dx */
81 {
82 .name = AUD_NAME_HPCMOUT1,
83 .swm = {
84 .type = PORT_TYPE_I2S,
85 .dir = PORT_DIR_OUTPUT,
86 .rb = { 0, 0, },
87 .ch = { 0, 0, },
88 .oif = { 0, 0, },
89 .oport = { 0, AUD_HW_HPCMOUT1, },
90 },
91 },
92
93 /* for HDMI PCM, Pin:AO2Dx */
94 {
95 .name = AUD_NAME_PCMOUT1,
96 .gname = AUD_GNAME_HDMI,
97 .swm = {
98 .type = PORT_TYPE_I2S,
99 .dir = PORT_DIR_OUTPUT,
100 .rb = { 0, 0, },
101 .ch = { 0, 0, },
102 .oif = { 0, 0, },
103 .oport = { 3, AUD_HW_PCMOUT1, },
104 },
105 },
106
107 /* for Line Out, Pin:LO2_x */
108 {
109 .name = AUD_NAME_PCMOUT2,
110 .gname = AUD_GNAME_LINE,
111 .swm = {
112 .type = PORT_TYPE_EVE,
113 .dir = PORT_DIR_OUTPUT,
114 .rb = { 2, 2, },
115 .ch = { 2, 2, },
116 .oif = { 2, 2, },
117 .oport = { 1, AUD_HW_PCMOUT2, },
118 },
119 },
120
121 /* for Headphone, Pin:HP1_x */
122 {
123 .name = AUD_NAME_PCMOUT3,
124 .swm = {
125 .type = PORT_TYPE_EVE,
126 .dir = PORT_DIR_OUTPUT,
127 .rb = { 3, 3, },
128 .ch = { 3, 3, },
129 .oif = { 3, 3, },
130 .oport = { 2, AUD_HW_PCMOUT3, },
131 },
132 },
133
134 /* for HW Sampling Rate Converter */
135 {
136 .name = AUD_NAME_EPCMOUT2,
137 .swm = {
138 .type = PORT_TYPE_CONV,
139 .dir = PORT_DIR_OUTPUT,
140 .rb = { 7, 5, },
141 .ch = { 7, 5, },
142 .oif = { 7, 5, },
143 .oport = { 6, AUD_HW_EPCMOUT2, },
144 .och = { 17, 12, },
145 .iif = { 1, 1, },
146 },
147 },
148
149 /* for HW Sampling Rate Converter 2 */
150 {
151 .name = AUD_NAME_EPCMOUT3,
152 .swm = {
153 .type = PORT_TYPE_CONV,
154 .dir = PORT_DIR_OUTPUT,
155 .rb = { 8, 6, },
156 .ch = { 8, 6, },
157 .oif = { 8, 6, },
158 .oport = { 7, AUD_HW_EPCMOUT3, },
159 .och = { 18, 13, },
160 .iif = { 2, 2, },
161 },
162 },
163
164 /* for S/PDIF Out, Pin:AO1IEC */
165 {
166 .name = AUD_NAME_HIECOUT1,
167 .gname = AUD_GNAME_IEC,
168 .swm = {
169 .type = PORT_TYPE_SPDIF,
170 .dir = PORT_DIR_OUTPUT,
171 .rb = { 1, 1, },
172 .ch = { 1, 1, },
173 .oif = { 1, 1, },
174 .oport = { 12, AUD_HW_HIECOUT1, },
175 },
176 },
177
178 /* for S/PDIF Out, Pin:AO1IEC, Compress */
179 {
180 .name = AUD_NAME_HIECCOMPOUT1,
181 .gname = AUD_GNAME_IEC,
182 .swm = {
183 .type = PORT_TYPE_SPDIF,
184 .dir = PORT_DIR_OUTPUT,
185 .rb = { 1, 1, },
186 .ch = { 1, 1, },
187 .oif = { 1, 1, },
188 .oport = { 12, AUD_HW_HIECOUT1, },
189 },
190 },
191};
192
193static const struct uniphier_aio_pll uniphier_aio_pll_ld11[] = {
194 [AUD_PLL_A1] = { .enable = true, },
195 [AUD_PLL_F1] = { .enable = true, },
196 [AUD_PLL_A2] = { .enable = true, },
197 [AUD_PLL_F2] = { .enable = true, },
198 [AUD_PLL_APLL] = { .enable = true, },
199 [AUD_PLL_RX0] = { .enable = true, },
200 [AUD_PLL_USB0] = { .enable = true, },
201 [AUD_PLL_HSC0] = { .enable = true, },
202};
203
204static int uniphier_aio_ld11_probe(struct snd_soc_dai *dai)
205{
206 int ret;
207
208 ret = uniphier_aio_dai_probe(dai);
209 if (ret < 0)
210 return ret;
211
212 ret = snd_soc_dai_set_pll(dai, AUD_PLL_A1, 0, 0, 36864000);
213 if (ret < 0)
214 return ret;
215 ret = snd_soc_dai_set_pll(dai, AUD_PLL_F1, 0, 0, 36864000);
216 if (ret < 0)
217 return ret;
218
219 ret = snd_soc_dai_set_pll(dai, AUD_PLL_A2, 0, 0, 33868800);
220 if (ret < 0)
221 return ret;
222 ret = snd_soc_dai_set_pll(dai, AUD_PLL_F2, 0, 0, 33868800);
223 if (ret < 0)
224 return ret;
225
226 return 0;
227}
228
229static struct snd_soc_dai_driver uniphier_aio_dai_ld11[] = {
230 {
231 .name = AUD_GNAME_HDMI,
232 .probe = uniphier_aio_ld11_probe,
233 .remove = uniphier_aio_dai_remove,
234 .suspend = uniphier_aio_dai_suspend,
235 .resume = uniphier_aio_dai_resume,
236 .playback = {
237 .stream_name = AUD_NAME_PCMOUT1,
238 .formats = SNDRV_PCM_FMTBIT_S32_LE,
239 .rates = SNDRV_PCM_RATE_48000,
240 .channels_min = 2,
241 .channels_max = 2,
242 },
243 .capture = {
244 .stream_name = AUD_NAME_PCMIN1,
245 .formats = SNDRV_PCM_FMTBIT_S32_LE,
246 .rates = SNDRV_PCM_RATE_48000 |
247 SNDRV_PCM_RATE_44100 |
248 SNDRV_PCM_RATE_32000,
249 .channels_min = 2,
250 .channels_max = 2,
251 },
252 .ops = &uniphier_aio_i2s_ops,
253 },
254 {
255 .name = AUD_NAME_PCMIN2,
256 .probe = uniphier_aio_ld11_probe,
257 .remove = uniphier_aio_dai_remove,
258 .suspend = uniphier_aio_dai_suspend,
259 .resume = uniphier_aio_dai_resume,
260 .capture = {
261 .stream_name = AUD_NAME_PCMIN2,
262 .formats = SNDRV_PCM_FMTBIT_S32_LE,
263 .rates = SNDRV_PCM_RATE_48000,
264 .channels_min = 2,
265 .channels_max = 2,
266 },
267 .ops = &uniphier_aio_i2s_ops,
268 },
269 {
270 .name = AUD_GNAME_LINE,
271 .probe = uniphier_aio_ld11_probe,
272 .remove = uniphier_aio_dai_remove,
273 .suspend = uniphier_aio_dai_suspend,
274 .resume = uniphier_aio_dai_resume,
275 .playback = {
276 .stream_name = AUD_NAME_PCMOUT2,
277 .formats = SNDRV_PCM_FMTBIT_S32_LE,
278 .rates = SNDRV_PCM_RATE_48000,
279 .channels_min = 2,
280 .channels_max = 2,
281 },
282 .capture = {
283 .stream_name = AUD_NAME_PCMIN3,
284 .formats = SNDRV_PCM_FMTBIT_S32_LE,
285 .rates = SNDRV_PCM_RATE_48000,
286 .channels_min = 2,
287 .channels_max = 2,
288 },
289 .ops = &uniphier_aio_i2s_ops,
290 },
291 {
292 .name = AUD_NAME_HPCMOUT1,
293 .probe = uniphier_aio_ld11_probe,
294 .remove = uniphier_aio_dai_remove,
295 .suspend = uniphier_aio_dai_suspend,
296 .resume = uniphier_aio_dai_resume,
297 .playback = {
298 .stream_name = AUD_NAME_HPCMOUT1,
299 .formats = SNDRV_PCM_FMTBIT_S32_LE,
300 .rates = SNDRV_PCM_RATE_48000,
301 .channels_min = 2,
302 .channels_max = 2,
303 },
304 .ops = &uniphier_aio_i2s_ops,
305 },
306 {
307 .name = AUD_NAME_PCMOUT3,
308 .probe = uniphier_aio_ld11_probe,
309 .remove = uniphier_aio_dai_remove,
310 .suspend = uniphier_aio_dai_suspend,
311 .resume = uniphier_aio_dai_resume,
312 .playback = {
313 .stream_name = AUD_NAME_PCMOUT3,
314 .formats = SNDRV_PCM_FMTBIT_S32_LE,
315 .rates = SNDRV_PCM_RATE_48000,
316 .channels_min = 2,
317 .channels_max = 2,
318 },
319 .ops = &uniphier_aio_i2s_ops,
320 },
321 {
322 .name = AUD_NAME_HIECOUT1,
323 .probe = uniphier_aio_ld11_probe,
324 .remove = uniphier_aio_dai_remove,
325 .suspend = uniphier_aio_dai_suspend,
326 .resume = uniphier_aio_dai_resume,
327 .playback = {
328 .stream_name = AUD_NAME_HIECOUT1,
329 .formats = SNDRV_PCM_FMTBIT_S32_LE,
330 .rates = SNDRV_PCM_RATE_48000,
331 .channels_min = 2,
332 .channels_max = 2,
333 },
334 .ops = &uniphier_aio_spdif_ops,
335 },
336 {
337 .name = AUD_NAME_EPCMOUT2,
338 .probe = uniphier_aio_ld11_probe,
339 .remove = uniphier_aio_dai_remove,
340 .suspend = uniphier_aio_dai_suspend,
341 .resume = uniphier_aio_dai_resume,
342 .playback = {
343 .stream_name = AUD_NAME_EPCMOUT2,
344 .formats = SNDRV_PCM_FMTBIT_S32_LE,
345 .rates = SNDRV_PCM_RATE_48000 |
346 SNDRV_PCM_RATE_44100 |
347 SNDRV_PCM_RATE_32000,
348 .channels_min = 2,
349 .channels_max = 2,
350 },
351 .ops = &uniphier_aio_i2s_ops,
352 },
353 {
354 .name = AUD_NAME_EPCMOUT3,
355 .probe = uniphier_aio_ld11_probe,
356 .remove = uniphier_aio_dai_remove,
357 .suspend = uniphier_aio_dai_suspend,
358 .resume = uniphier_aio_dai_resume,
359 .playback = {
360 .stream_name = AUD_NAME_EPCMOUT3,
361 .formats = SNDRV_PCM_FMTBIT_S32_LE,
362 .rates = SNDRV_PCM_RATE_48000 |
363 SNDRV_PCM_RATE_44100 |
364 SNDRV_PCM_RATE_32000,
365 .channels_min = 2,
366 .channels_max = 2,
367 },
368 .ops = &uniphier_aio_i2s_ops,
369 },
370 {
371 .name = AUD_NAME_HIECCOMPOUT1,
372 .probe = uniphier_aio_ld11_probe,
373 .remove = uniphier_aio_dai_remove,
374 .suspend = uniphier_aio_dai_suspend,
375 .resume = uniphier_aio_dai_resume,
376 .compress_new = snd_soc_new_compress,
377 .playback = {
378 .stream_name = AUD_NAME_HIECCOMPOUT1,
379 .channels_min = 1,
380 .channels_max = 1,
381 },
382 .ops = &uniphier_aio_spdif_ops,
383 },
384};
385
386static const struct uniphier_aio_chip_spec uniphier_aio_ld11_spec = {
387 .specs = uniphier_aio_ld11,
388 .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
389 .dais = uniphier_aio_dai_ld11,
390 .num_dais = ARRAY_SIZE(uniphier_aio_dai_ld11),
391 .plls = uniphier_aio_pll_ld11,
392 .num_plls = ARRAY_SIZE(uniphier_aio_pll_ld11),
393 .addr_ext = 0,
394};
395
396static const struct uniphier_aio_chip_spec uniphier_aio_ld20_spec = {
397 .specs = uniphier_aio_ld11,
398 .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
399 .dais = uniphier_aio_dai_ld11,
400 .num_dais = ARRAY_SIZE(uniphier_aio_dai_ld11),
401 .plls = uniphier_aio_pll_ld11,
402 .num_plls = ARRAY_SIZE(uniphier_aio_pll_ld11),
403 .addr_ext = 1,
404};
405
406static const struct of_device_id uniphier_aio_of_match[] = {
407 {
408 .compatible = "socionext,uniphier-ld11-aio",
409 .data = &uniphier_aio_ld11_spec,
410 },
411 {
412 .compatible = "socionext,uniphier-ld20-aio",
413 .data = &uniphier_aio_ld20_spec,
414 },
415 {},
416};
417MODULE_DEVICE_TABLE(of, uniphier_aio_of_match);
418
419static struct platform_driver uniphier_aio_driver = {
420 .driver = {
421 .name = "snd-uniphier-aio",
422 .of_match_table = of_match_ptr(uniphier_aio_of_match),
423 },
424 .probe = uniphier_aio_probe,
425 .remove = uniphier_aio_remove,
426};
427module_platform_driver(uniphier_aio_driver);
428
429MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
430MODULE_DESCRIPTION("UniPhier LD11/LD20 AIO driver.");
431MODULE_LICENSE("GPL v2");