GNU Linux-libre 4.19.286-gnu1
[releases.git] / sound / soc / uniphier / aio-ld11.c
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 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
216 static 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                 .suspend = uniphier_aio_dai_suspend,
222                 .resume  = uniphier_aio_dai_resume,
223                 .playback = {
224                         .stream_name = AUD_NAME_PCMOUT1,
225                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
226                         .rates       = SNDRV_PCM_RATE_48000,
227                         .channels_min = 2,
228                         .channels_max = 2,
229                 },
230                 .capture = {
231                         .stream_name = AUD_NAME_PCMIN1,
232                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
233                         .rates       = SNDRV_PCM_RATE_48000 |
234                                 SNDRV_PCM_RATE_44100 |
235                                 SNDRV_PCM_RATE_32000,
236                         .channels_min = 2,
237                         .channels_max = 2,
238                 },
239                 .ops = &uniphier_aio_i2s_ops,
240         },
241         {
242                 .name    = AUD_NAME_PCMIN2,
243                 .probe   = uniphier_aio_ld11_probe,
244                 .remove  = uniphier_aio_dai_remove,
245                 .suspend = uniphier_aio_dai_suspend,
246                 .resume  = uniphier_aio_dai_resume,
247                 .capture = {
248                         .stream_name = AUD_NAME_PCMIN2,
249                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
250                         .rates       = SNDRV_PCM_RATE_48000,
251                         .channels_min = 2,
252                         .channels_max = 2,
253                 },
254                 .ops = &uniphier_aio_i2s_ops,
255         },
256         {
257                 .name    = AUD_GNAME_LINE,
258                 .probe   = uniphier_aio_ld11_probe,
259                 .remove  = uniphier_aio_dai_remove,
260                 .suspend = uniphier_aio_dai_suspend,
261                 .resume  = uniphier_aio_dai_resume,
262                 .playback = {
263                         .stream_name = AUD_NAME_PCMOUT2,
264                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
265                         .rates       = SNDRV_PCM_RATE_48000,
266                         .channels_min = 2,
267                         .channels_max = 2,
268                 },
269                 .capture = {
270                         .stream_name = AUD_NAME_PCMIN3,
271                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
272                         .rates       = SNDRV_PCM_RATE_48000,
273                         .channels_min = 2,
274                         .channels_max = 2,
275                 },
276                 .ops = &uniphier_aio_i2s_ops,
277         },
278         {
279                 .name    = AUD_NAME_HPCMOUT1,
280                 .probe   = uniphier_aio_ld11_probe,
281                 .remove  = uniphier_aio_dai_remove,
282                 .suspend = uniphier_aio_dai_suspend,
283                 .resume  = uniphier_aio_dai_resume,
284                 .playback = {
285                         .stream_name = AUD_NAME_HPCMOUT1,
286                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
287                         .rates       = SNDRV_PCM_RATE_48000,
288                         .channels_min = 2,
289                         .channels_max = 8,
290                 },
291                 .ops = &uniphier_aio_i2s_ops,
292         },
293         {
294                 .name    = AUD_NAME_PCMOUT3,
295                 .probe   = uniphier_aio_ld11_probe,
296                 .remove  = uniphier_aio_dai_remove,
297                 .suspend = uniphier_aio_dai_suspend,
298                 .resume  = uniphier_aio_dai_resume,
299                 .playback = {
300                         .stream_name = AUD_NAME_PCMOUT3,
301                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
302                         .rates       = SNDRV_PCM_RATE_48000,
303                         .channels_min = 2,
304                         .channels_max = 2,
305                 },
306                 .ops = &uniphier_aio_i2s_ops,
307         },
308         {
309                 .name    = AUD_NAME_HIECOUT1,
310                 .probe   = uniphier_aio_ld11_probe,
311                 .remove  = uniphier_aio_dai_remove,
312                 .suspend = uniphier_aio_dai_suspend,
313                 .resume  = uniphier_aio_dai_resume,
314                 .playback = {
315                         .stream_name = AUD_NAME_HIECOUT1,
316                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
317                         .rates       = SNDRV_PCM_RATE_48000,
318                         .channels_min = 2,
319                         .channels_max = 2,
320                 },
321                 .ops = &uniphier_aio_spdif_ops,
322         },
323         {
324                 .name    = AUD_NAME_EPCMOUT2,
325                 .probe   = uniphier_aio_ld11_probe,
326                 .remove  = uniphier_aio_dai_remove,
327                 .suspend = uniphier_aio_dai_suspend,
328                 .resume  = uniphier_aio_dai_resume,
329                 .playback = {
330                         .stream_name = AUD_NAME_EPCMOUT2,
331                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
332                         .rates       = SNDRV_PCM_RATE_48000 |
333                                 SNDRV_PCM_RATE_44100 |
334                                 SNDRV_PCM_RATE_32000,
335                         .channels_min = 2,
336                         .channels_max = 2,
337                 },
338                 .ops = &uniphier_aio_i2s_ops,
339         },
340         {
341                 .name    = AUD_NAME_EPCMOUT3,
342                 .probe   = uniphier_aio_ld11_probe,
343                 .remove  = uniphier_aio_dai_remove,
344                 .suspend = uniphier_aio_dai_suspend,
345                 .resume  = uniphier_aio_dai_resume,
346                 .playback = {
347                         .stream_name = AUD_NAME_EPCMOUT3,
348                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
349                         .rates       = SNDRV_PCM_RATE_48000 |
350                                 SNDRV_PCM_RATE_44100 |
351                                 SNDRV_PCM_RATE_32000,
352                         .channels_min = 2,
353                         .channels_max = 2,
354                 },
355                 .ops = &uniphier_aio_i2s_ops,
356         },
357         {
358                 .name    = AUD_NAME_HIECCOMPOUT1,
359                 .probe   = uniphier_aio_ld11_probe,
360                 .remove  = uniphier_aio_dai_remove,
361                 .suspend = uniphier_aio_dai_suspend,
362                 .resume  = uniphier_aio_dai_resume,
363                 .compress_new = snd_soc_new_compress,
364                 .playback = {
365                         .stream_name = AUD_NAME_HIECCOMPOUT1,
366                         .channels_min = 1,
367                         .channels_max = 1,
368                 },
369                 .ops = &uniphier_aio_spdif_ops,
370         },
371 };
372
373 static const struct uniphier_aio_chip_spec uniphier_aio_ld11_spec = {
374         .specs     = uniphier_aio_ld11,
375         .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
376         .dais      = uniphier_aio_dai_ld11,
377         .num_dais  = ARRAY_SIZE(uniphier_aio_dai_ld11),
378         .plls      = uniphier_aio_pll_ld11,
379         .num_plls  = ARRAY_SIZE(uniphier_aio_pll_ld11),
380         .addr_ext  = 0,
381 };
382
383 static const struct uniphier_aio_chip_spec uniphier_aio_ld20_spec = {
384         .specs     = uniphier_aio_ld11,
385         .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
386         .dais      = uniphier_aio_dai_ld11,
387         .num_dais  = ARRAY_SIZE(uniphier_aio_dai_ld11),
388         .plls      = uniphier_aio_pll_ld11,
389         .num_plls  = ARRAY_SIZE(uniphier_aio_pll_ld11),
390         .addr_ext  = 1,
391 };
392
393 static const struct of_device_id uniphier_aio_of_match[] = {
394         {
395                 .compatible = "socionext,uniphier-ld11-aio",
396                 .data = &uniphier_aio_ld11_spec,
397         },
398         {
399                 .compatible = "socionext,uniphier-ld20-aio",
400                 .data = &uniphier_aio_ld20_spec,
401         },
402         {},
403 };
404 MODULE_DEVICE_TABLE(of, uniphier_aio_of_match);
405
406 static struct platform_driver uniphier_aio_driver = {
407         .driver = {
408                 .name = "snd-uniphier-aio-ld11",
409                 .of_match_table = of_match_ptr(uniphier_aio_of_match),
410         },
411         .probe    = uniphier_aio_probe,
412         .remove   = uniphier_aio_remove,
413 };
414 module_platform_driver(uniphier_aio_driver);
415
416 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
417 MODULE_DESCRIPTION("UniPhier LD11/LD20 AIO driver.");
418 MODULE_LICENSE("GPL v2");