xref: /openbmc/linux/sound/soc/uniphier/aio-ld11.c (revision 479965a2)
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 
11 static 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 
180 static 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 
191 static struct snd_soc_dai_driver uniphier_aio_dai_ld11[] = {
192 	{
193 		.name    = AUD_GNAME_HDMI,
194 		.playback = {
195 			.stream_name = AUD_NAME_PCMOUT1,
196 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
197 			.rates       = SNDRV_PCM_RATE_48000,
198 			.channels_min = 2,
199 			.channels_max = 2,
200 		},
201 		.capture = {
202 			.stream_name = AUD_NAME_PCMIN1,
203 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
204 			.rates       = SNDRV_PCM_RATE_48000 |
205 				SNDRV_PCM_RATE_44100 |
206 				SNDRV_PCM_RATE_32000,
207 			.channels_min = 2,
208 			.channels_max = 2,
209 		},
210 		.ops = &uniphier_aio_i2s_ld11_ops,
211 	},
212 	{
213 		.name    = AUD_NAME_PCMIN2,
214 		.capture = {
215 			.stream_name = AUD_NAME_PCMIN2,
216 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
217 			.rates       = SNDRV_PCM_RATE_48000,
218 			.channels_min = 2,
219 			.channels_max = 2,
220 		},
221 		.ops = &uniphier_aio_i2s_ld11_ops,
222 	},
223 	{
224 		.name    = AUD_GNAME_LINE,
225 		.playback = {
226 			.stream_name = AUD_NAME_PCMOUT2,
227 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
228 			.rates       = SNDRV_PCM_RATE_48000,
229 			.channels_min = 2,
230 			.channels_max = 2,
231 		},
232 		.capture = {
233 			.stream_name = AUD_NAME_PCMIN3,
234 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
235 			.rates       = SNDRV_PCM_RATE_48000,
236 			.channels_min = 2,
237 			.channels_max = 2,
238 		},
239 		.ops = &uniphier_aio_i2s_ld11_ops,
240 	},
241 	{
242 		.name    = AUD_NAME_HPCMOUT1,
243 		.playback = {
244 			.stream_name = AUD_NAME_HPCMOUT1,
245 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
246 			.rates       = SNDRV_PCM_RATE_48000,
247 			.channels_min = 2,
248 			.channels_max = 8,
249 		},
250 		.ops = &uniphier_aio_i2s_ld11_ops,
251 	},
252 	{
253 		.name    = AUD_NAME_PCMOUT3,
254 		.playback = {
255 			.stream_name = AUD_NAME_PCMOUT3,
256 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
257 			.rates       = SNDRV_PCM_RATE_48000,
258 			.channels_min = 2,
259 			.channels_max = 2,
260 		},
261 		.ops = &uniphier_aio_i2s_ld11_ops,
262 	},
263 	{
264 		.name    = AUD_NAME_HIECOUT1,
265 		.playback = {
266 			.stream_name = AUD_NAME_HIECOUT1,
267 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
268 			.rates       = SNDRV_PCM_RATE_48000,
269 			.channels_min = 2,
270 			.channels_max = 2,
271 		},
272 		.ops = &uniphier_aio_spdif_ld11_ops,
273 	},
274 	{
275 		.name    = AUD_NAME_EPCMOUT2,
276 		.playback = {
277 			.stream_name = AUD_NAME_EPCMOUT2,
278 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
279 			.rates       = SNDRV_PCM_RATE_48000 |
280 				SNDRV_PCM_RATE_44100 |
281 				SNDRV_PCM_RATE_32000,
282 			.channels_min = 2,
283 			.channels_max = 2,
284 		},
285 		.ops = &uniphier_aio_i2s_ld11_ops,
286 	},
287 	{
288 		.name    = AUD_NAME_EPCMOUT3,
289 		.playback = {
290 			.stream_name = AUD_NAME_EPCMOUT3,
291 			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
292 			.rates       = SNDRV_PCM_RATE_48000 |
293 				SNDRV_PCM_RATE_44100 |
294 				SNDRV_PCM_RATE_32000,
295 			.channels_min = 2,
296 			.channels_max = 2,
297 		},
298 		.ops = &uniphier_aio_i2s_ld11_ops,
299 	},
300 	{
301 		.name    = AUD_NAME_HIECCOMPOUT1,
302 		.playback = {
303 			.stream_name = AUD_NAME_HIECCOMPOUT1,
304 			.channels_min = 1,
305 			.channels_max = 1,
306 		},
307 		.ops = &uniphier_aio_spdif_ld11_ops2,
308 	},
309 };
310 
311 static const struct uniphier_aio_chip_spec uniphier_aio_ld11_spec = {
312 	.specs     = uniphier_aio_ld11,
313 	.num_specs = ARRAY_SIZE(uniphier_aio_ld11),
314 	.dais      = uniphier_aio_dai_ld11,
315 	.num_dais  = ARRAY_SIZE(uniphier_aio_dai_ld11),
316 	.plls      = uniphier_aio_pll_ld11,
317 	.num_plls  = ARRAY_SIZE(uniphier_aio_pll_ld11),
318 	.addr_ext  = 0,
319 };
320 
321 static const struct uniphier_aio_chip_spec uniphier_aio_ld20_spec = {
322 	.specs     = uniphier_aio_ld11,
323 	.num_specs = ARRAY_SIZE(uniphier_aio_ld11),
324 	.dais      = uniphier_aio_dai_ld11,
325 	.num_dais  = ARRAY_SIZE(uniphier_aio_dai_ld11),
326 	.plls      = uniphier_aio_pll_ld11,
327 	.num_plls  = ARRAY_SIZE(uniphier_aio_pll_ld11),
328 	.addr_ext  = 1,
329 };
330 
331 static const struct of_device_id uniphier_aio_of_match[] __maybe_unused = {
332 	{
333 		.compatible = "socionext,uniphier-ld11-aio",
334 		.data = &uniphier_aio_ld11_spec,
335 	},
336 	{
337 		.compatible = "socionext,uniphier-ld20-aio",
338 		.data = &uniphier_aio_ld20_spec,
339 	},
340 	{},
341 };
342 MODULE_DEVICE_TABLE(of, uniphier_aio_of_match);
343 
344 static struct platform_driver uniphier_aio_driver = {
345 	.driver = {
346 		.name = "snd-uniphier-aio-ld11",
347 		.of_match_table = of_match_ptr(uniphier_aio_of_match),
348 	},
349 	.probe    = uniphier_aio_probe,
350 	.remove   = uniphier_aio_remove,
351 };
352 module_platform_driver(uniphier_aio_driver);
353 
354 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
355 MODULE_DESCRIPTION("UniPhier LD11/LD20 AIO driver.");
356 MODULE_LICENSE("GPL v2");
357