Merge branch 'dmi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvar...
[linux-2.6-microblaze.git] / sound / soc / uniphier / aio-pxs2.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Socionext UniPhier AIO ALSA driver for PXs2.
4 //
5 // Copyright (c) 2018 Socionext Inc.
6
7 #include <linux/module.h>
8
9 #include "aio.h"
10
11 static const struct uniphier_aio_spec uniphier_aio_pxs2[] = {
12         /* for Line PCM In, Pin:AI1Dx */
13         {
14                 .name = AUD_NAME_PCMIN1,
15                 .gname = AUD_GNAME_LINE,
16                 .swm = {
17                         .type  = PORT_TYPE_I2S,
18                         .dir   = PORT_DIR_INPUT,
19                         .rb    = { 16, 11, },
20                         .ch    = { 16, 11, },
21                         .iif   = { 0, 0, },
22                         .iport = { 0, AUD_HW_PCMIN1, },
23                 },
24         },
25
26         /* for Speaker/Headphone/Mic PCM In, Pin:AI2Dx */
27         {
28                 .name = AUD_NAME_PCMIN2,
29                 .gname = AUD_GNAME_AUX,
30                 .swm = {
31                         .type  = PORT_TYPE_I2S,
32                         .dir   = PORT_DIR_INPUT,
33                         .rb    = { 17, 12, },
34                         .ch    = { 17, 12, },
35                         .iif   = { 1, 1, },
36                         .iport = { 1, AUD_HW_PCMIN2, },
37                 },
38         },
39
40         /* for HDMI PCM Out, Pin:AO1Dx (inner) */
41         {
42                 .name = AUD_NAME_HPCMOUT1,
43                 .gname = AUD_GNAME_HDMI,
44                 .swm = {
45                         .type  = PORT_TYPE_I2S,
46                         .dir   = PORT_DIR_OUTPUT,
47                         .rb    = { 0, 0, },
48                         .ch    = { 0, 0, },
49                         .oif   = { 0, 0, },
50                         .oport = { 3, AUD_HW_HPCMOUT1, },
51                 },
52         },
53
54         /* for Line PCM Out, Pin:AO2Dx */
55         {
56                 .name = AUD_NAME_PCMOUT1,
57                 .gname = AUD_GNAME_LINE,
58                 .swm = {
59                         .type  = PORT_TYPE_I2S,
60                         .dir   = PORT_DIR_OUTPUT,
61                         .rb    = { 1, 1, },
62                         .ch    = { 1, 1, },
63                         .oif   = { 1, 1, },
64                         .oport = { 0, AUD_HW_PCMOUT1, },
65                 },
66         },
67
68         /* for Speaker/Headphone/Mic PCM Out, Pin:AO3Dx */
69         {
70                 .name = AUD_NAME_PCMOUT2,
71                 .gname = AUD_GNAME_AUX,
72                 .swm = {
73                         .type  = PORT_TYPE_I2S,
74                         .dir   = PORT_DIR_OUTPUT,
75                         .rb    = { 2, 2, },
76                         .ch    = { 2, 2, },
77                         .oif   = { 2, 2, },
78                         .oport = { 1, AUD_HW_PCMOUT2, },
79                 },
80         },
81
82         /* for HDMI Out, Pin:AO1IEC */
83         {
84                 .name = AUD_NAME_HIECOUT1,
85                 .swm = {
86                         .type  = PORT_TYPE_SPDIF,
87                         .dir   = PORT_DIR_OUTPUT,
88                         .rb    = { 6, 4, },
89                         .ch    = { 6, 4, },
90                         .oif   = { 6, 4, },
91                         .oport = { 12, AUD_HW_HIECOUT1, },
92                 },
93         },
94
95         /* for HDMI Out, Pin:AO1IEC, Compress */
96         {
97                 .name = AUD_NAME_HIECCOMPOUT1,
98                 .swm = {
99                         .type  = PORT_TYPE_SPDIF,
100                         .dir   = PORT_DIR_OUTPUT,
101                         .rb    = { 6, 4, },
102                         .ch    = { 6, 4, },
103                         .oif   = { 6, 4, },
104                         .oport = { 12, AUD_HW_HIECOUT1, },
105                 },
106         },
107
108         /* for S/PDIF Out, Pin:AO2IEC */
109         {
110                 .name = AUD_NAME_IECOUT1,
111                 .swm = {
112                         .type  = PORT_TYPE_SPDIF,
113                         .dir   = PORT_DIR_OUTPUT,
114                         .rb    = { 7, 5, },
115                         .ch    = { 7, 5, },
116                         .oif   = { 7, 5, },
117                         .oport = { 13, AUD_HW_IECOUT1, },
118                 },
119         },
120
121         /* for S/PDIF Out, Pin:AO2IEC */
122         {
123                 .name = AUD_NAME_IECCOMPOUT1,
124                 .swm = {
125                         .type  = PORT_TYPE_SPDIF,
126                         .dir   = PORT_DIR_OUTPUT,
127                         .rb    = { 7, 5, },
128                         .ch    = { 7, 5, },
129                         .oif   = { 7, 5, },
130                         .oport = { 13, AUD_HW_IECOUT1, },
131                 },
132         },
133 };
134
135 static const struct uniphier_aio_pll uniphier_aio_pll_pxs2[] = {
136         [AUD_PLL_A1]   = { .enable = true, },
137         [AUD_PLL_F1]   = { .enable = true, },
138         [AUD_PLL_A2]   = { .enable = true, },
139         [AUD_PLL_F2]   = { .enable = true, },
140         [AUD_PLL_APLL] = { .enable = true, },
141         [AUD_PLL_HSC0] = { .enable = true, },
142 };
143
144 static int uniphier_aio_pxs2_probe(struct snd_soc_dai *dai)
145 {
146         int ret;
147
148         ret = uniphier_aio_dai_probe(dai);
149         if (ret < 0)
150                 return ret;
151
152         ret = snd_soc_dai_set_pll(dai, AUD_PLL_A1, 0, 0, 36864000);
153         if (ret < 0)
154                 return ret;
155         ret = snd_soc_dai_set_pll(dai, AUD_PLL_F1, 0, 0, 36864000);
156         if (ret < 0)
157                 return ret;
158
159         ret = snd_soc_dai_set_pll(dai, AUD_PLL_A2, 0, 0, 33868800);
160         if (ret < 0)
161                 return ret;
162         ret = snd_soc_dai_set_pll(dai, AUD_PLL_F2, 0, 0, 33868800);
163         if (ret < 0)
164                 return ret;
165
166         return 0;
167 }
168
169 static struct snd_soc_dai_driver uniphier_aio_dai_pxs2[] = {
170         {
171                 .name    = AUD_GNAME_HDMI,
172                 .probe   = uniphier_aio_pxs2_probe,
173                 .remove  = uniphier_aio_dai_remove,
174                 .playback = {
175                         .stream_name = AUD_NAME_HPCMOUT1,
176                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
177                         .rates       = SNDRV_PCM_RATE_48000,
178                         .channels_min = 2,
179                         .channels_max = 2,
180                 },
181                 .ops = &uniphier_aio_i2s_ops,
182         },
183         {
184                 .name    = AUD_GNAME_LINE,
185                 .probe   = uniphier_aio_pxs2_probe,
186                 .remove  = uniphier_aio_dai_remove,
187                 .playback = {
188                         .stream_name = AUD_NAME_PCMOUT1,
189                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
190                         .rates       = SNDRV_PCM_RATE_48000,
191                         .channels_min = 2,
192                         .channels_max = 2,
193                 },
194                 .capture = {
195                         .stream_name = AUD_NAME_PCMIN1,
196                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
197                         .rates       = SNDRV_PCM_RATE_48000,
198                         .channels_min = 2,
199                         .channels_max = 2,
200                 },
201                 .ops = &uniphier_aio_i2s_ops,
202         },
203         {
204                 .name    = AUD_GNAME_AUX,
205                 .probe   = uniphier_aio_pxs2_probe,
206                 .remove  = uniphier_aio_dai_remove,
207                 .playback = {
208                         .stream_name = AUD_NAME_PCMOUT2,
209                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
210                         .rates       = SNDRV_PCM_RATE_48000,
211                         .channels_min = 2,
212                         .channels_max = 2,
213                 },
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_ops,
222         },
223         {
224                 .name    = AUD_NAME_HIECOUT1,
225                 .probe   = uniphier_aio_pxs2_probe,
226                 .remove  = uniphier_aio_dai_remove,
227                 .playback = {
228                         .stream_name = AUD_NAME_HIECOUT1,
229                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
230                         .rates       = SNDRV_PCM_RATE_48000,
231                         .channels_min = 2,
232                         .channels_max = 2,
233                 },
234                 .ops = &uniphier_aio_spdif_ops,
235         },
236         {
237                 .name    = AUD_NAME_IECOUT1,
238                 .probe   = uniphier_aio_pxs2_probe,
239                 .remove  = uniphier_aio_dai_remove,
240                 .playback = {
241                         .stream_name = AUD_NAME_IECOUT1,
242                         .formats     = SNDRV_PCM_FMTBIT_S32_LE,
243                         .rates       = SNDRV_PCM_RATE_48000,
244                         .channels_min = 2,
245                         .channels_max = 2,
246                 },
247                 .ops = &uniphier_aio_spdif_ops,
248         },
249         {
250                 .name    = AUD_NAME_HIECCOMPOUT1,
251                 .probe   = uniphier_aio_pxs2_probe,
252                 .remove  = uniphier_aio_dai_remove,
253                 .compress_new = snd_soc_new_compress,
254                 .playback = {
255                         .stream_name = AUD_NAME_HIECCOMPOUT1,
256                         .channels_min = 1,
257                         .channels_max = 1,
258                 },
259                 .ops = &uniphier_aio_spdif_ops,
260         },
261         {
262                 .name    = AUD_NAME_IECCOMPOUT1,
263                 .probe   = uniphier_aio_pxs2_probe,
264                 .remove  = uniphier_aio_dai_remove,
265                 .compress_new = snd_soc_new_compress,
266                 .playback = {
267                         .stream_name = AUD_NAME_IECCOMPOUT1,
268                         .channels_min = 1,
269                         .channels_max = 1,
270                 },
271                 .ops = &uniphier_aio_spdif_ops,
272         },
273 };
274
275 static const struct uniphier_aio_chip_spec uniphier_aio_pxs2_spec = {
276         .specs     = uniphier_aio_pxs2,
277         .num_specs = ARRAY_SIZE(uniphier_aio_pxs2),
278         .dais      = uniphier_aio_dai_pxs2,
279         .num_dais  = ARRAY_SIZE(uniphier_aio_dai_pxs2),
280         .plls      = uniphier_aio_pll_pxs2,
281         .num_plls  = ARRAY_SIZE(uniphier_aio_pll_pxs2),
282         .addr_ext  = 0,
283 };
284
285 static const struct of_device_id uniphier_aio_of_match[] __maybe_unused = {
286         {
287                 .compatible = "socionext,uniphier-pxs2-aio",
288                 .data = &uniphier_aio_pxs2_spec,
289         },
290         {},
291 };
292 MODULE_DEVICE_TABLE(of, uniphier_aio_of_match);
293
294 static struct platform_driver uniphier_aio_driver = {
295         .driver = {
296                 .name = "snd-uniphier-aio-pxs2",
297                 .of_match_table = of_match_ptr(uniphier_aio_of_match),
298         },
299         .probe    = uniphier_aio_probe,
300         .remove   = uniphier_aio_remove,
301 };
302 module_platform_driver(uniphier_aio_driver);
303
304 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
305 MODULE_DESCRIPTION("UniPhier PXs2 AIO driver.");
306 MODULE_LICENSE("GPL v2");