Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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#include <linux/module.h>
  8
  9#include "aio.h"
 10
 11static const struct uniphier_aio_spec uniphier_aio_ld11[] = {
 12	/* for HDMI PCM In, Pin:AI1Dx */
 13	{
 14		.name = AUD_NAME_PCMIN1,
 15		.gname = AUD_GNAME_HDMI,
 16		.swm = {
 17			.type  = PORT_TYPE_I2S,
 18			.dir   = PORT_DIR_INPUT,
 19			.rb    = { 21, 14, },
 20			.ch    = { 21, 14, },
 21			.iif   = { 5, 3, },
 22			.iport = { 0, AUD_HW_PCMIN1, },
 23		},
 24	},
 25
 26	/* for SIF In, Pin:AI2Dx */
 27	{
 28		.name = AUD_NAME_PCMIN2,
 29		.swm = {
 30			.type  = PORT_TYPE_I2S,
 31			.dir   = PORT_DIR_INPUT,
 32			.rb    = { 22, 15, },
 33			.ch    = { 22, 15, },
 34			.iif   = { 6, 4, },
 35			.iport = { 1, AUD_HW_PCMIN2, },
 36		},
 37	},
 38
 39	/* for Line In, Pin:AI3Dx */
 40	{
 41		.name = AUD_NAME_PCMIN3,
 42		.gname = AUD_GNAME_LINE,
 43		.swm = {
 44			.type  = PORT_TYPE_EVE,
 45			.dir   = PORT_DIR_INPUT,
 46			.rb    = { 23, 16, },
 47			.ch    = { 23, 16, },
 48			.iif   = { 7, 5, },
 49			.iport = { 2, AUD_HW_PCMIN3, },
 50		},
 51	},
 52
 53	/* for S/PDIF In, Pin:AI1IEC */
 54	{
 55		.name = AUD_NAME_IECIN1,
 56		.gname = AUD_GNAME_IEC,
 57		.swm = {
 58			.type  = PORT_TYPE_SPDIF,
 59			.dir   = PORT_DIR_INPUT,
 60			.rb    = { 26, 17, },
 61			.ch    = { 26, 17, },
 62			.iif   = { 10, 6, },
 63			.iport = { 3, AUD_HW_IECIN1, },
 64		},
 65	},
 66
 67	/* for Speaker, Pin:AO1Dx */
 68	{
 69		.name = AUD_NAME_HPCMOUT1,
 70		.swm = {
 71			.type  = PORT_TYPE_I2S,
 72			.dir   = PORT_DIR_OUTPUT,
 73			.rb    = { 0, 0, },
 74			.ch    = { 0, 0, },
 75			.oif   = { 0, 0, },
 76			.oport = { 0, AUD_HW_HPCMOUT1, },
 77		},
 78	},
 79
 80	/* for HDMI PCM, Pin:AO2Dx */
 81	{
 82		.name = AUD_NAME_PCMOUT1,
 83		.gname = AUD_GNAME_HDMI,
 84		.swm = {
 85			.type  = PORT_TYPE_I2S,
 86			.dir   = PORT_DIR_OUTPUT,
 87			.rb    = { 0, 0, },
 88			.ch    = { 0, 0, },
 89			.oif   = { 0, 0, },
 90			.oport = { 3, AUD_HW_PCMOUT1, },
 91		},
 92	},
 93
 94	/* for Line Out, Pin:LO2_x */
 95	{
 96		.name = AUD_NAME_PCMOUT2,
 97		.gname = AUD_GNAME_LINE,
 98		.swm = {
 99			.type  = PORT_TYPE_EVE,
100			.dir   = PORT_DIR_OUTPUT,
101			.rb    = { 2, 2, },
102			.ch    = { 2, 2, },
103			.oif   = { 2, 2, },
104			.oport = { 1, AUD_HW_PCMOUT2, },
105		},
106	},
107
108	/* for Headphone, Pin:HP1_x */
109	{
110		.name = AUD_NAME_PCMOUT3,
111		.swm = {
112			.type  = PORT_TYPE_EVE,
113			.dir   = PORT_DIR_OUTPUT,
114			.rb    = { 3, 3, },
115			.ch    = { 3, 3, },
116			.oif   = { 3, 3, },
117			.oport = { 2, AUD_HW_PCMOUT3, },
118		},
119	},
120
121	/* for HW Sampling Rate Converter */
122	{
123		.name = AUD_NAME_EPCMOUT2,
124		.swm = {
125			.type  = PORT_TYPE_CONV,
126			.dir   = PORT_DIR_OUTPUT,
127			.rb    = { 7, 5, },
128			.ch    = { 7, 5, },
129			.oif   = { 7, 5, },
130			.oport = { 6, AUD_HW_EPCMOUT2, },
131			.och   = { 17, 12, },
132			.iif   = { 1, 1, },
133		},
134	},
135
136	/* for HW Sampling Rate Converter 2 */
137	{
138		.name = AUD_NAME_EPCMOUT3,
139		.swm = {
140			.type  = PORT_TYPE_CONV,
141			.dir   = PORT_DIR_OUTPUT,
142			.rb    = { 8, 6, },
143			.ch    = { 8, 6, },
144			.oif   = { 8, 6, },
145			.oport = { 7, AUD_HW_EPCMOUT3, },
146			.och   = { 18, 13, },
147			.iif   = { 2, 2, },
148		},
149	},
150
151	/* for S/PDIF Out, Pin:AO1IEC */
152	{
153		.name = AUD_NAME_HIECOUT1,
154		.gname = AUD_GNAME_IEC,
155		.swm = {
156			.type  = PORT_TYPE_SPDIF,
157			.dir   = PORT_DIR_OUTPUT,
158			.rb    = { 1, 1, },
159			.ch    = { 1, 1, },
160			.oif   = { 1, 1, },
161			.oport = { 12, AUD_HW_HIECOUT1, },
162		},
163	},
164
165	/* for S/PDIF Out, Pin:AO1IEC, Compress */
166	{
167		.name = AUD_NAME_HIECCOMPOUT1,
168		.gname = AUD_GNAME_IEC,
169		.swm = {
170			.type  = PORT_TYPE_SPDIF,
171			.dir   = PORT_DIR_OUTPUT,
172			.rb    = { 1, 1, },
173			.ch    = { 1, 1, },
174			.oif   = { 1, 1, },
175			.oport = { 12, AUD_HW_HIECOUT1, },
176		},
177	},
178};
179
180static const struct uniphier_aio_pll uniphier_aio_pll_ld11[] = {
181	[AUD_PLL_A1]   = { .enable = true, },
182	[AUD_PLL_F1]   = { .enable = true, },
183	[AUD_PLL_A2]   = { .enable = true, },
184	[AUD_PLL_F2]   = { .enable = true, },
185	[AUD_PLL_APLL] = { .enable = true, },
186	[AUD_PLL_RX0]  = { .enable = true, },
187	[AUD_PLL_USB0] = { .enable = true, },
188	[AUD_PLL_HSC0] = { .enable = true, },
189};
190
191static int uniphier_aio_ld11_probe(struct snd_soc_dai *dai)
192{
193	int ret;
194
195	ret = uniphier_aio_dai_probe(dai);
196	if (ret < 0)
197		return ret;
198
199	ret = snd_soc_dai_set_pll(dai, AUD_PLL_A1, 0, 0, 36864000);
200	if (ret < 0)
201		return ret;
202	ret = snd_soc_dai_set_pll(dai, AUD_PLL_F1, 0, 0, 36864000);
203	if (ret < 0)
204		return ret;
205
206	ret = snd_soc_dai_set_pll(dai, AUD_PLL_A2, 0, 0, 33868800);
207	if (ret < 0)
208		return ret;
209	ret = snd_soc_dai_set_pll(dai, AUD_PLL_F2, 0, 0, 33868800);
210	if (ret < 0)
211		return ret;
212
213	return 0;
214}
215
216static struct snd_soc_dai_driver uniphier_aio_dai_ld11[] = {
217	{
218		.name    = AUD_GNAME_HDMI,
219		.probe   = uniphier_aio_ld11_probe,
220		.remove  = uniphier_aio_dai_remove,
221		.playback = {
222			.stream_name = AUD_NAME_PCMOUT1,
223			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
224			.rates       = SNDRV_PCM_RATE_48000,
225			.channels_min = 2,
226			.channels_max = 2,
227		},
228		.capture = {
229			.stream_name = AUD_NAME_PCMIN1,
230			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
231			.rates       = SNDRV_PCM_RATE_48000 |
232				SNDRV_PCM_RATE_44100 |
233				SNDRV_PCM_RATE_32000,
234			.channels_min = 2,
235			.channels_max = 2,
236		},
237		.ops = &uniphier_aio_i2s_ops,
238	},
239	{
240		.name    = AUD_NAME_PCMIN2,
241		.probe   = uniphier_aio_ld11_probe,
242		.remove  = uniphier_aio_dai_remove,
243		.capture = {
244			.stream_name = AUD_NAME_PCMIN2,
245			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
246			.rates       = SNDRV_PCM_RATE_48000,
247			.channels_min = 2,
248			.channels_max = 2,
249		},
250		.ops = &uniphier_aio_i2s_ops,
251	},
252	{
253		.name    = AUD_GNAME_LINE,
254		.probe   = uniphier_aio_ld11_probe,
255		.remove  = uniphier_aio_dai_remove,
256		.playback = {
257			.stream_name = AUD_NAME_PCMOUT2,
258			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
259			.rates       = SNDRV_PCM_RATE_48000,
260			.channels_min = 2,
261			.channels_max = 2,
262		},
263		.capture = {
264			.stream_name = AUD_NAME_PCMIN3,
265			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
266			.rates       = SNDRV_PCM_RATE_48000,
267			.channels_min = 2,
268			.channels_max = 2,
269		},
270		.ops = &uniphier_aio_i2s_ops,
271	},
272	{
273		.name    = AUD_NAME_HPCMOUT1,
274		.probe   = uniphier_aio_ld11_probe,
275		.remove  = uniphier_aio_dai_remove,
276		.playback = {
277			.stream_name = AUD_NAME_HPCMOUT1,
278			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
279			.rates       = SNDRV_PCM_RATE_48000,
280			.channels_min = 2,
281			.channels_max = 8,
282		},
283		.ops = &uniphier_aio_i2s_ops,
284	},
285	{
286		.name    = AUD_NAME_PCMOUT3,
287		.probe   = uniphier_aio_ld11_probe,
288		.remove  = uniphier_aio_dai_remove,
289		.playback = {
290			.stream_name = AUD_NAME_PCMOUT3,
291			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
292			.rates       = SNDRV_PCM_RATE_48000,
293			.channels_min = 2,
294			.channels_max = 2,
295		},
296		.ops = &uniphier_aio_i2s_ops,
297	},
298	{
299		.name    = AUD_NAME_HIECOUT1,
300		.probe   = uniphier_aio_ld11_probe,
301		.remove  = uniphier_aio_dai_remove,
302		.playback = {
303			.stream_name = AUD_NAME_HIECOUT1,
304			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
305			.rates       = SNDRV_PCM_RATE_48000,
306			.channels_min = 2,
307			.channels_max = 2,
308		},
309		.ops = &uniphier_aio_spdif_ops,
310	},
311	{
312		.name    = AUD_NAME_EPCMOUT2,
313		.probe   = uniphier_aio_ld11_probe,
314		.remove  = uniphier_aio_dai_remove,
315		.playback = {
316			.stream_name = AUD_NAME_EPCMOUT2,
317			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
318			.rates       = SNDRV_PCM_RATE_48000 |
319				SNDRV_PCM_RATE_44100 |
320				SNDRV_PCM_RATE_32000,
321			.channels_min = 2,
322			.channels_max = 2,
323		},
324		.ops = &uniphier_aio_i2s_ops,
325	},
326	{
327		.name    = AUD_NAME_EPCMOUT3,
328		.probe   = uniphier_aio_ld11_probe,
329		.remove  = uniphier_aio_dai_remove,
330		.playback = {
331			.stream_name = AUD_NAME_EPCMOUT3,
332			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
333			.rates       = SNDRV_PCM_RATE_48000 |
334				SNDRV_PCM_RATE_44100 |
335				SNDRV_PCM_RATE_32000,
336			.channels_min = 2,
337			.channels_max = 2,
338		},
339		.ops = &uniphier_aio_i2s_ops,
340	},
341	{
342		.name    = AUD_NAME_HIECCOMPOUT1,
343		.probe   = uniphier_aio_ld11_probe,
344		.remove  = uniphier_aio_dai_remove,
345		.compress_new = snd_soc_new_compress,
346		.playback = {
347			.stream_name = AUD_NAME_HIECCOMPOUT1,
348			.channels_min = 1,
349			.channels_max = 1,
350		},
351		.ops = &uniphier_aio_spdif_ops,
352	},
353};
354
355static const struct uniphier_aio_chip_spec uniphier_aio_ld11_spec = {
356	.specs     = uniphier_aio_ld11,
357	.num_specs = ARRAY_SIZE(uniphier_aio_ld11),
358	.dais      = uniphier_aio_dai_ld11,
359	.num_dais  = ARRAY_SIZE(uniphier_aio_dai_ld11),
360	.plls      = uniphier_aio_pll_ld11,
361	.num_plls  = ARRAY_SIZE(uniphier_aio_pll_ld11),
362	.addr_ext  = 0,
363};
364
365static const struct uniphier_aio_chip_spec uniphier_aio_ld20_spec = {
366	.specs     = uniphier_aio_ld11,
367	.num_specs = ARRAY_SIZE(uniphier_aio_ld11),
368	.dais      = uniphier_aio_dai_ld11,
369	.num_dais  = ARRAY_SIZE(uniphier_aio_dai_ld11),
370	.plls      = uniphier_aio_pll_ld11,
371	.num_plls  = ARRAY_SIZE(uniphier_aio_pll_ld11),
372	.addr_ext  = 1,
373};
374
375static const struct of_device_id uniphier_aio_of_match[] __maybe_unused = {
376	{
377		.compatible = "socionext,uniphier-ld11-aio",
378		.data = &uniphier_aio_ld11_spec,
379	},
380	{
381		.compatible = "socionext,uniphier-ld20-aio",
382		.data = &uniphier_aio_ld20_spec,
383	},
384	{},
385};
386MODULE_DEVICE_TABLE(of, uniphier_aio_of_match);
387
388static struct platform_driver uniphier_aio_driver = {
389	.driver = {
390		.name = "snd-uniphier-aio-ld11",
391		.of_match_table = of_match_ptr(uniphier_aio_of_match),
392	},
393	.probe    = uniphier_aio_probe,
394	.remove   = uniphier_aio_remove,
395};
396module_platform_driver(uniphier_aio_driver);
397
398MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
399MODULE_DESCRIPTION("UniPhier LD11/LD20 AIO driver.");
400MODULE_LICENSE("GPL v2");