]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/blob - sound/soc/tegra-alt/tegra210_sfc_alt.c
ASoC: tegra-alt: Fix parent runtime PM handling
[hercules2020/nv-tegra/linux-4.4.git] / sound / soc / tegra-alt / tegra210_sfc_alt.c
1 /*
2  * tegra210_sfc_alt.c - Tegra210 SFC driver
3  *
4  * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 #include <linux/clk.h>
19 #include <linux/device.h>
20 #include <linux/io.h>
21 #include <linux/module.h>
22 #include <linux/of.h>
23 #include <linux/platform_device.h>
24 #include <linux/pm_runtime.h>
25 #include <linux/regmap.h>
26 #include <linux/slab.h>
27 #include <sound/core.h>
28 #include <sound/pcm.h>
29 #include <sound/pcm_params.h>
30 #include <sound/soc.h>
31 #include <linux/pinctrl/consumer.h>
32 #include <linux/of_device.h>
33 #include <linux/delay.h>
34
35 #include "tegra210_xbar_alt.h"
36 #include "tegra210_sfc_alt.h"
37
38 #define DRV_NAME "tegra210-sfc"
39
40 static const struct reg_default tegra210_sfc_reg_defaults[] = {
41         { TEGRA210_SFC_AXBAR_RX_INT_MASK, 0x00000001},
42         { TEGRA210_SFC_AXBAR_RX_CIF_CTRL, 0x00007700},
43         { TEGRA210_SFC_AXBAR_TX_INT_MASK, 0x00000001},
44         { TEGRA210_SFC_AXBAR_TX_CIF_CTRL, 0x00007700},
45         { TEGRA210_SFC_CG, 0x1},
46         { TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL, 0x00004000},
47 };
48
49 static int tegra210_sfc_rates[] = {
50         8000,   /* #define TEGRA210_SFC_FS8                             0       */
51         11025,  /* #define TEGRA210_SFC_FS11_025                1       */
52         16000,  /* #define TEGRA210_SFC_FS16                    2       */
53         22050,  /* #define TEGRA210_SFC_FS22_05                 3       */
54         24000,  /* #define TEGRA210_SFC_FS24                    4       */
55         32000,  /* #define TEGRA210_SFC_FS32                    5       */
56         44100,  /* #define TEGRA210_SFC_FS44_1                  6       */
57         48000,  /* #define TEGRA210_SFC_FS48                    7       */
58         64000,  /* #define TEGRA210_SFC_FS64                    8       */
59         88200,  /* #define TEGRA210_SFC_FS88_2                  9       */
60         96000,  /* #define TEGRA210_SFC_FS96                    10      */
61         176400, /* #define TEGRA210_SFC_FS176_4                 11      */
62         192000, /* #define TEGRA210_SFC_FS192                   12      */
63 };
64
65 static int tegra210_sfc_runtime_suspend(struct device *dev)
66 {
67         struct tegra210_sfc *sfc = dev_get_drvdata(dev);
68
69         regcache_cache_only(sfc->regmap, true);
70         regcache_mark_dirty(sfc->regmap);
71
72         return 0;
73 }
74
75 static int tegra210_sfc_runtime_resume(struct device *dev)
76 {
77         struct tegra210_sfc *sfc = dev_get_drvdata(dev);
78
79         regcache_cache_only(sfc->regmap, false);
80
81         if (!sfc->is_shutdown)
82                 regcache_sync(sfc->regmap);
83
84         return 0;
85 }
86
87 #ifdef CONFIG_PM_SLEEP
88 static int tegra210_sfc_suspend(struct device *dev)
89 {
90         return 0;
91 }
92 #endif
93
94 static int tegra210_sfc_set_dai_sysclk(struct snd_soc_dai *dai,
95                 int clk_id, unsigned int freq, int dir)
96 {
97         struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
98         unsigned int value;
99
100         switch (freq) {
101         case 8000:
102                 value = TEGRA210_SFC_FS8;
103                 break;
104         case 11025:
105                 value = TEGRA210_SFC_FS11_025;
106                 break;
107         case 16000:
108                 value = TEGRA210_SFC_FS16;
109                 break;
110         case 22050:
111                 value = TEGRA210_SFC_FS22_05;
112                 break;
113         case 24000:
114                 value = TEGRA210_SFC_FS24;
115                 break;
116         case 32000:
117                 value = TEGRA210_SFC_FS32;
118                 break;
119         case 44100:
120                 value = TEGRA210_SFC_FS44_1;
121                 break;
122         case 48000:
123                 value = TEGRA210_SFC_FS48;
124                 break;
125         case 64000:
126                 value = TEGRA210_SFC_FS64;
127                 break;
128         case 88200:
129                 value = TEGRA210_SFC_FS88_2;
130                 break;
131         case 96000:
132                 value = TEGRA210_SFC_FS96;
133                 break;
134         case 176400:
135                 value = TEGRA210_SFC_FS176_4;
136                 break;
137         case 192000:
138                 value = TEGRA210_SFC_FS192;
139                 break;
140         default:
141                 value = TEGRA210_SFC_FS8;
142                 break;
143         }
144
145         if (dir == SND_SOC_CLOCK_OUT)
146                 sfc->srate_out = value;
147         else if (dir == SND_SOC_CLOCK_IN)
148                 sfc->srate_in = value;
149
150         return 0;
151 }
152
153 static int tegra210_sfc_write_coeff_ram(struct tegra210_sfc *sfc)
154 {
155         u32 *coeff_ram = NULL;
156
157         switch (sfc->srate_in) {
158         case TEGRA210_SFC_FS8:
159                 if (sfc->srate_out == TEGRA210_SFC_FS48)
160                         coeff_ram = coef_8to48;
161                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
162                         coeff_ram = coef_8to44;
163                 else if (sfc->srate_out == TEGRA210_SFC_FS24)
164                         coeff_ram = coef_8to24;
165                 else if (sfc->srate_out == TEGRA210_SFC_FS16)
166                         coeff_ram = coef_8to16;
167                 break;
168
169         case TEGRA210_SFC_FS16:
170                 if (sfc->srate_out == TEGRA210_SFC_FS48)
171                         coeff_ram = coef_16to48;
172                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
173                         coeff_ram = coef_16to44;
174                 else if (sfc->srate_out == TEGRA210_SFC_FS24)
175                         coeff_ram = coef_16to24;
176                 else if (sfc->srate_out == TEGRA210_SFC_FS8)
177                         coeff_ram = coef_16to8;
178                 break;
179
180         case TEGRA210_SFC_FS44_1:
181                 if (sfc->srate_out == TEGRA210_SFC_FS8)
182                         coeff_ram = coef_44to8;
183                 else if (sfc->srate_out == TEGRA210_SFC_FS16)
184                         coeff_ram = coef_44to16;
185                 else if (sfc->srate_out == TEGRA210_SFC_FS48)
186                         coeff_ram = coef_44to48;
187                 break;
188
189         case TEGRA210_SFC_FS48:
190                 if (sfc->srate_out == TEGRA210_SFC_FS8)
191                         coeff_ram = coef_48to8;
192                 else if (sfc->srate_out == TEGRA210_SFC_FS16)
193                         coeff_ram = coef_48to16;
194                 else if (sfc->srate_out == TEGRA210_SFC_FS24)
195                         coeff_ram = coef_48to24;
196                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
197                         coeff_ram = coef_48to44;
198                 else if (sfc->srate_out == TEGRA210_SFC_FS96)
199                         coeff_ram = coef_48to96;
200                 else if (sfc->srate_out == TEGRA210_SFC_FS192)
201                         coeff_ram = coef_48to192;
202                 break;
203
204         case TEGRA210_SFC_FS11_025:
205                 if (sfc->srate_out == TEGRA210_SFC_FS48)
206                         coeff_ram = coef_11to48;
207                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
208                         coeff_ram = coef_11to44;
209                 break;
210
211         case TEGRA210_SFC_FS22_05:
212                 if (sfc->srate_out == TEGRA210_SFC_FS48)
213                         coeff_ram = coef_22to48;
214                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
215                         coeff_ram = coef_22to44;
216                 break;
217
218         case TEGRA210_SFC_FS24:
219                 if (sfc->srate_out == TEGRA210_SFC_FS48)
220                         coeff_ram = coef_24to48;
221                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
222                         coeff_ram = coef_24to44;
223                 break;
224
225         case TEGRA210_SFC_FS32:
226                 if (sfc->srate_out == TEGRA210_SFC_FS48)
227                         coeff_ram = coef_32to48;
228                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
229                         coeff_ram = coef_32to44;
230                 break;
231
232         case TEGRA210_SFC_FS88_2:
233                 if (sfc->srate_out == TEGRA210_SFC_FS48)
234                         coeff_ram = coef_88to48;
235                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
236                         coeff_ram = coef_88to44;
237                 break;
238
239         case TEGRA210_SFC_FS96:
240                 if (sfc->srate_out == TEGRA210_SFC_FS48)
241                         coeff_ram = coef_96to48;
242                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
243                         coeff_ram = coef_96to44;
244                 break;
245
246         case TEGRA210_SFC_FS176_4:
247                 if (sfc->srate_out == TEGRA210_SFC_FS48)
248                         coeff_ram = coef_176to48;
249                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
250                         coeff_ram = coef_176to44;
251                 break;
252
253         case TEGRA210_SFC_FS192:
254                 if (sfc->srate_out == TEGRA210_SFC_FS48)
255                         coeff_ram = coef_192to48;
256                 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
257                         coeff_ram = coef_192to44;
258                 break;
259
260         default:
261                 pr_err("SFC input rate not supported: %d\n",
262                         -EINVAL);
263                 break;
264         }
265
266         if (coeff_ram) {
267                 tegra210_xbar_write_ahubram(sfc->regmap,
268                         TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL,
269                         TEGRA210_SFC_AHUBRAMCTL_SFC_DATA,
270                         0, coeff_ram, TEGRA210_SFC_COEF_RAM_DEPTH);
271
272                 regmap_update_bits(sfc->regmap,
273                         TEGRA210_SFC_COEF_RAM,
274                         TEGRA210_SFC_COEF_RAM_COEF_RAM_EN,
275                         TEGRA210_SFC_COEF_RAM_COEF_RAM_EN);
276         }
277
278         return 0;
279 }
280
281 static const int tegra210_sfc_fmt_values[] = {
282         0,
283         TEGRA210_AUDIOCIF_BITS_16,
284         TEGRA210_AUDIOCIF_BITS_32,
285 };
286
287 static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
288                                 struct snd_pcm_hw_params *params,
289                                 unsigned int reg)
290 {
291         int channels, audio_bits;
292         struct tegra210_xbar_cif_conf cif_conf;
293
294         memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
295
296         channels = params_channels(params);
297
298         switch (params_format(params)) {
299         case SNDRV_PCM_FORMAT_S16_LE:
300                 audio_bits = TEGRA210_AUDIOCIF_BITS_16;
301                 break;
302         case SNDRV_PCM_FORMAT_S32_LE:
303                 audio_bits = TEGRA210_AUDIOCIF_BITS_32;
304                 break;
305         default:
306                 return -EINVAL;
307         }
308
309         if (sfc->channels_via_control)
310                 channels = sfc->channels_via_control;
311
312         if (sfc->stereo_conv_input > 0 && 2 == channels &&
313                 (reg == TEGRA210_SFC_AXBAR_RX_CIF_CTRL)) {
314                 cif_conf.stereo_conv = sfc->stereo_conv_input - 1;
315                 cif_conf.client_channels = 1;
316         } else if (sfc->mono_conv_output > 0 && 2 == channels &&
317                 (reg == TEGRA210_SFC_AXBAR_TX_CIF_CTRL)) {
318                 cif_conf.mono_conv = sfc->mono_conv_output - 1;
319                 cif_conf.client_channels = 1;
320         } else {
321                 cif_conf.client_channels = channels;
322         }
323
324         cif_conf.audio_channels = channels;
325         cif_conf.audio_bits = audio_bits;
326         if (sfc->format_in && (reg == TEGRA210_SFC_AXBAR_RX_CIF_CTRL))
327                 cif_conf.audio_bits = tegra210_sfc_fmt_values[sfc->format_in];
328         if (sfc->format_out && (reg == TEGRA210_SFC_AXBAR_TX_CIF_CTRL))
329                 cif_conf.audio_bits = tegra210_sfc_fmt_values[sfc->format_out];
330         cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_32;
331
332         sfc->soc_data->set_audio_cif(sfc->regmap, reg, &cif_conf);
333
334         return 0;
335 }
336
337 static int tegra210_sfc_soft_reset(struct tegra210_sfc *sfc)
338 {
339         u32 val;
340         int cnt = 10;
341         int ret = 0;
342
343         regmap_update_bits(sfc->regmap,
344                         TEGRA210_SFC_SOFT_RESET,
345                         TEGRA210_SFC_SOFT_RESET_EN,
346                         1);
347         do {
348                 udelay(100);
349                 regmap_read(sfc->regmap, TEGRA210_SFC_SOFT_RESET, &val);
350         } while ((val & TEGRA210_SFC_SOFT_RESET_EN) && cnt--);
351         if (!cnt)
352                 ret = -ETIMEDOUT;
353         return ret;
354 }
355
356 static int tegra210_sfc_in_hw_params(struct snd_pcm_substream *substream,
357                                  struct snd_pcm_hw_params *params,
358                                  struct snd_soc_dai *dai)
359 {
360         struct device *dev = dai->dev;
361         struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
362         int ret;
363
364         regmap_update_bits(sfc->regmap,
365                         TEGRA210_SFC_COEF_RAM,
366                         TEGRA210_SFC_COEF_RAM_COEF_RAM_EN,
367                         0);
368
369         ret = tegra210_sfc_soft_reset(sfc);
370         if (ret) {
371                 dev_err(dev, "SOFT_RESET error: %d\n", ret);
372                 return ret;
373         }
374
375         ret = tegra210_sfc_set_audio_cif(sfc, params,
376                                 TEGRA210_SFC_AXBAR_RX_CIF_CTRL);
377         if (ret) {
378                 dev_err(dev, "Can't set SFC RX CIF: %d\n", ret);
379                 return ret;
380         }
381         memcpy(&sfc->in_hw_params, params, sizeof(struct snd_pcm_hw_params));
382
383         regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_RX_FREQ, sfc->srate_in);
384
385         if (sfc->srate_in != sfc->srate_out)
386                 tegra210_sfc_write_coeff_ram(sfc);
387
388         return ret;
389 }
390
391 static int tegra210_sfc_out_hw_params(struct snd_pcm_substream *substream,
392                                  struct snd_pcm_hw_params *params,
393                                  struct snd_soc_dai *dai)
394 {
395         struct device *dev = dai->dev;
396         struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
397         int ret;
398
399         ret = tegra210_sfc_set_audio_cif(sfc, params,
400                                 TEGRA210_SFC_AXBAR_TX_CIF_CTRL);
401         if (ret) {
402                 dev_err(dev, "Can't set SFC TX CIF: %d\n", ret);
403                 return ret;
404         }
405         memcpy(&sfc->out_hw_params, params, sizeof(struct snd_pcm_hw_params));
406
407         if (sfc->srate_out < 0) {
408                 dev_err(dev, "SFC%d output rate not set: %d\n",
409                         dev->id, -EINVAL);
410                 return -EINVAL;
411         }
412
413         regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_TX_FREQ, sfc->srate_out);
414         return ret;
415 }
416
417 static int tegra210_sfc_rate_to_index(int rate)
418 {
419         int index;
420         for (index = 0; index < ARRAY_SIZE(tegra210_sfc_rates); index++) {
421                 if (rate == tegra210_sfc_rates[index])
422                         return index;
423         }
424         return -1;
425 }
426
427 static int tegra210_sfc_get_srate(struct snd_kcontrol *kcontrol,
428         struct snd_ctl_elem_value *ucontrol)
429 {
430         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
431         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
432
433         /* get the sfc output rate */
434         if (strstr(kcontrol->id.name, "input"))
435                 ucontrol->value.integer.value[0] = tegra210_sfc_rates[sfc->srate_in];
436         else if (strstr(kcontrol->id.name, "output"))
437                 ucontrol->value.integer.value[0] = tegra210_sfc_rates[sfc->srate_out];
438
439         return 0;
440 }
441
442 static int tegra210_sfc_put_srate(struct snd_kcontrol *kcontrol,
443         struct snd_ctl_elem_value *ucontrol)
444 {
445         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
446         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
447         int srate = tegra210_sfc_rate_to_index(ucontrol->value.integer.value[0]);
448
449         if ((srate < TEGRA210_SFC_FS8) || (srate > TEGRA210_SFC_FS192))
450                 return -EINVAL;
451
452         /* Update the SFC input/output rate */
453         if (strstr(kcontrol->id.name, "input"))
454                 sfc->srate_in = srate;
455         else if (strstr(kcontrol->id.name, "output"))
456                 sfc->srate_out = srate;
457
458         return 0;
459 }
460
461 static int tegra210_sfc_get_format(struct snd_kcontrol *kcontrol,
462         struct snd_ctl_elem_value *ucontrol)
463 {
464         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
465         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
466
467         /* get the format control flag */
468         if (strstr(kcontrol->id.name, "input"))
469                 ucontrol->value.integer.value[0] = sfc->format_in;
470         else if (strstr(kcontrol->id.name, "output"))
471                 ucontrol->value.integer.value[0] = sfc->format_out;
472         else if (strstr(kcontrol->id.name, "Channels"))
473                 ucontrol->value.integer.value[0] = sfc->channels_via_control;
474
475         return 0;
476 }
477
478 static int tegra210_sfc_put_format(struct snd_kcontrol *kcontrol,
479         struct snd_ctl_elem_value *ucontrol)
480 {
481         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
482         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
483         int value = ucontrol->value.integer.value[0];
484
485         /* set the format control flag */
486         if (strstr(kcontrol->id.name, "input"))
487                 sfc->format_in = value;
488         else if (strstr(kcontrol->id.name, "output"))
489                 sfc->format_out = value;
490         else if (strstr(kcontrol->id.name, "Channels")) {
491                 if (value > 0 && value <= 2)
492                         sfc->channels_via_control = value;
493                 else
494                         return -EINVAL;
495         }
496
497         return 0;
498 }
499
500 static int tegra210_sfc_init_get(struct snd_kcontrol *kcontrol,
501         struct snd_ctl_elem_value *ucontrol)
502 {
503         return 0;
504 }
505
506 static int tegra210_sfc_init_put(struct snd_kcontrol *kcontrol,
507         struct snd_ctl_elem_value *ucontrol)
508 {
509         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
510         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
511         int init = ucontrol->value.enumerated.item[0];
512         int ret = 0;
513         int is_enabled = 0;
514
515         if (!init)
516                 return ret;
517
518         dev_dbg(codec->dev, "%s: inrate %d outrate %d\n",
519                 __func__, sfc->srate_in, sfc->srate_out);
520
521         ret = pm_runtime_get_sync(codec->dev->parent);
522         if (ret < 0) {
523                 dev_err(codec->dev, "parent get_sync failed: %d\n", ret);
524                 return ret;
525         }
526
527         regmap_read(sfc->regmap, TEGRA210_SFC_ENABLE, &is_enabled);
528
529         if (is_enabled) {
530                 u32 val;
531                 int cnt = 100;
532
533                 regmap_write(sfc->regmap, TEGRA210_SFC_ENABLE, 0);
534
535                 regmap_read(sfc->regmap, TEGRA210_SFC_STATUS, &val);
536                 while ((val & 1) && cnt--) {
537                         udelay(100);
538                         regmap_read(sfc->regmap, TEGRA210_SFC_STATUS, &val);
539                 }
540
541                 if (!cnt)
542                         dev_warn(codec->dev, "SFC disable timeout\n");
543
544                 regmap_update_bits(sfc->regmap,
545                                 TEGRA210_SFC_COEF_RAM,
546                                 TEGRA210_SFC_COEF_RAM_COEF_RAM_EN,
547                                 0);
548
549                 ret = tegra210_sfc_soft_reset(sfc);
550                 if (ret) {
551                         dev_err(codec->dev, "SOFT_RESET error: %d\n", ret);
552                         return ret;
553                 }
554
555                 ret = tegra210_sfc_set_audio_cif(sfc, &sfc->in_hw_params,
556                                         TEGRA210_SFC_AXBAR_RX_CIF_CTRL);
557                 if (ret) {
558                         dev_err(codec->dev, "Can't set SFC RX CIF: %d\n", ret);
559                         return ret;
560                 }
561
562                 ret = tegra210_sfc_set_audio_cif(sfc, &sfc->out_hw_params,
563                                                 TEGRA210_SFC_AXBAR_TX_CIF_CTRL);
564                 if (ret) {
565                         dev_err(codec->dev, "Can't set SFC TX CIF: %d\n", ret);
566                         return ret;
567                 }
568
569                 regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_RX_FREQ, sfc->srate_in);
570                 regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_TX_FREQ, sfc->srate_out);
571
572                 if (sfc->srate_in != sfc->srate_out)
573                         tegra210_sfc_write_coeff_ram(sfc);
574
575                 regmap_write(sfc->regmap, TEGRA210_SFC_ENABLE, 1);
576         }
577
578         pm_runtime_put(codec->dev->parent);
579
580         return 0;
581 }
582
583 static int tegra210_sfc_get_stereo_conv(struct snd_kcontrol *kcontrol,
584                                          struct snd_ctl_elem_value *ucontrol)
585 {
586         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
587         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
588
589         ucontrol->value.integer.value[0] = sfc->stereo_conv_input;
590         return 0;
591 }
592
593 static int tegra210_sfc_put_stereo_conv(struct snd_kcontrol *kcontrol,
594                                          struct snd_ctl_elem_value *ucontrol)
595 {
596         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
597         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
598
599         sfc->stereo_conv_input = ucontrol->value.integer.value[0];
600         return 0;
601 }
602
603 static int tegra210_sfc_get_mono_conv(struct snd_kcontrol *kcontrol,
604                                          struct snd_ctl_elem_value *ucontrol)
605 {
606         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
607         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
608
609         ucontrol->value.integer.value[0] = sfc->mono_conv_output;
610         return 0;
611 }
612
613 static int tegra210_sfc_put_mono_conv(struct snd_kcontrol *kcontrol,
614                                          struct snd_ctl_elem_value *ucontrol)
615 {
616         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
617         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
618
619         sfc->mono_conv_output = ucontrol->value.integer.value[0];
620         return 0;
621 }
622
623 static int tegra210_sfc_codec_probe(struct snd_soc_codec *codec)
624 {
625         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
626
627         codec->control_data = sfc->regmap;
628
629         return 0;
630 }
631
632 static struct snd_soc_dai_ops tegra210_sfc_in_dai_ops = {
633         .hw_params      = tegra210_sfc_in_hw_params,
634         .set_sysclk     = tegra210_sfc_set_dai_sysclk,
635 };
636
637 static struct snd_soc_dai_ops tegra210_sfc_out_dai_ops = {
638         .hw_params      = tegra210_sfc_out_hw_params,
639 };
640
641 static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
642         {
643                 .name = "CIF",
644                 .playback = {
645                         .stream_name = "SFC Receive",
646                         .channels_min = 1,
647                         .channels_max = 2,
648                         .rates = SNDRV_PCM_RATE_8000_96000,
649                         .formats = SNDRV_PCM_FMTBIT_S8 |
650                                 SNDRV_PCM_FMTBIT_S16_LE |
651                                 SNDRV_PCM_FMTBIT_S24_LE |
652                                 SNDRV_PCM_FMTBIT_S32_LE,
653                 },
654                 .ops = &tegra210_sfc_in_dai_ops,
655         },
656         {
657                 .name = "DAP",
658                 .capture = {
659                         .stream_name = "SFC Transmit",
660                         .channels_min = 1,
661                         .channels_max = 2,
662                         .rates = SNDRV_PCM_RATE_8000_96000,
663                         .formats = SNDRV_PCM_FMTBIT_S8 |
664                                 SNDRV_PCM_FMTBIT_S16_LE |
665                                 SNDRV_PCM_FMTBIT_S24_LE |
666                                 SNDRV_PCM_FMTBIT_S32_LE,
667                 },
668                 .ops = &tegra210_sfc_out_dai_ops,
669         }
670 };
671
672 static const struct snd_soc_dapm_widget tegra210_sfc_widgets[] = {
673         SND_SOC_DAPM_AIF_IN("SFC RX", NULL, 0, SND_SOC_NOPM,
674                                 0, 0),
675         SND_SOC_DAPM_AIF_OUT("SFC TX", NULL, 0, TEGRA210_SFC_ENABLE,
676                                 TEGRA210_SFC_EN_SHIFT, 0),
677 };
678
679 static const struct snd_soc_dapm_route tegra210_sfc_routes[] = {
680         { "SFC RX",       NULL, "SFC Receive" },
681         { "SFC TX",       NULL, "SFC RX" },
682         { "SFC Transmit", NULL, "SFC TX" },
683 };
684
685 static const char * const tegra210_sfc_format_text[] = {
686         "None",
687         "16",
688         "32",
689 };
690
691 static const char * const tegra210_sfc_stereo_conv_text[] = {
692         "None", "CH0", "CH1", "AVG",
693 };
694
695 static const char * const tegra210_sfc_mono_conv_text[] = {
696         "None", "ZERO", "COPY",
697 };
698
699 static const struct soc_enum tegra210_sfc_format_enum =
700         SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
701                 ARRAY_SIZE(tegra210_sfc_format_text),
702                 tegra210_sfc_format_text);
703
704 static const struct soc_enum tegra210_sfc_stereo_conv_enum =
705         SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
706                 ARRAY_SIZE(tegra210_sfc_stereo_conv_text),
707                 tegra210_sfc_stereo_conv_text);
708
709 static const struct soc_enum tegra210_sfc_mono_conv_enum =
710         SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
711                 ARRAY_SIZE(tegra210_sfc_mono_conv_text),
712                 tegra210_sfc_mono_conv_text);
713
714 static const struct snd_kcontrol_new tegra210_sfc_controls[] = {
715         SOC_SINGLE_EXT("input rate", 0, 0, 192000, 0,
716                 tegra210_sfc_get_srate, tegra210_sfc_put_srate),
717         SOC_SINGLE_EXT("output rate", 0, 0, 192000, 0,
718                 tegra210_sfc_get_srate, tegra210_sfc_put_srate),
719         SOC_ENUM_EXT("input bit format", tegra210_sfc_format_enum,
720                 tegra210_sfc_get_format, tegra210_sfc_put_format),
721         SOC_ENUM_EXT("output bit format", tegra210_sfc_format_enum,
722                 tegra210_sfc_get_format, tegra210_sfc_put_format),
723         SOC_SINGLE_EXT("Channels", 0, 0, 2, 0,
724                 tegra210_sfc_get_format, tegra210_sfc_put_format),
725         SOC_SINGLE_EXT("init", 0, 0, 1, 0,
726                 tegra210_sfc_init_get, tegra210_sfc_init_put),
727         SOC_ENUM_EXT("input stereo conv", tegra210_sfc_stereo_conv_enum,
728                 tegra210_sfc_get_stereo_conv, tegra210_sfc_put_stereo_conv),
729         SOC_ENUM_EXT("output mono conv", tegra210_sfc_mono_conv_enum,
730                 tegra210_sfc_get_mono_conv, tegra210_sfc_put_mono_conv),
731 };
732
733 static struct snd_soc_codec_driver tegra210_sfc_codec = {
734         .probe = tegra210_sfc_codec_probe,
735         .dapm_widgets = tegra210_sfc_widgets,
736         .num_dapm_widgets = ARRAY_SIZE(tegra210_sfc_widgets),
737         .dapm_routes = tegra210_sfc_routes,
738         .num_dapm_routes = ARRAY_SIZE(tegra210_sfc_routes),
739         .controls = tegra210_sfc_controls,
740         .num_controls = ARRAY_SIZE(tegra210_sfc_controls),
741         .idle_bias_off = 1,
742 };
743
744 static bool tegra210_sfc_wr_reg(struct device *dev, unsigned int reg)
745 {
746         switch (reg) {
747         case TEGRA210_SFC_AXBAR_RX_INT_MASK:
748         case TEGRA210_SFC_AXBAR_RX_INT_SET:
749         case TEGRA210_SFC_AXBAR_RX_INT_CLEAR:
750         case TEGRA210_SFC_AXBAR_RX_CIF_CTRL:
751         case TEGRA210_SFC_AXBAR_RX_FREQ:
752
753         case TEGRA210_SFC_AXBAR_TX_INT_MASK:
754         case TEGRA210_SFC_AXBAR_TX_INT_SET:
755         case TEGRA210_SFC_AXBAR_TX_INT_CLEAR:
756         case TEGRA210_SFC_AXBAR_TX_CIF_CTRL:
757         case TEGRA210_SFC_AXBAR_TX_FREQ:
758
759         case TEGRA210_SFC_ENABLE:
760         case TEGRA210_SFC_SOFT_RESET:
761         case TEGRA210_SFC_CG:
762         case TEGRA210_SFC_COEF_RAM:
763         case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
764         case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
765                 return true;
766         default:
767                 return false;
768         };
769 }
770
771 static bool tegra210_sfc_rd_reg(struct device *dev, unsigned int reg)
772 {
773         switch (reg) {
774         case TEGRA210_SFC_AXBAR_RX_STATUS:
775         case TEGRA210_SFC_AXBAR_RX_INT_STATUS:
776         case TEGRA210_SFC_AXBAR_RX_INT_MASK:
777         case TEGRA210_SFC_AXBAR_RX_INT_SET:
778         case TEGRA210_SFC_AXBAR_RX_INT_CLEAR:
779         case TEGRA210_SFC_AXBAR_RX_CIF_CTRL:
780         case TEGRA210_SFC_AXBAR_RX_FREQ:
781
782         case TEGRA210_SFC_AXBAR_TX_STATUS:
783         case TEGRA210_SFC_AXBAR_TX_INT_STATUS:
784         case TEGRA210_SFC_AXBAR_TX_INT_MASK:
785         case TEGRA210_SFC_AXBAR_TX_INT_SET:
786         case TEGRA210_SFC_AXBAR_TX_INT_CLEAR:
787         case TEGRA210_SFC_AXBAR_TX_CIF_CTRL:
788         case TEGRA210_SFC_AXBAR_TX_FREQ:
789
790         case TEGRA210_SFC_ENABLE:
791         case TEGRA210_SFC_SOFT_RESET:
792         case TEGRA210_SFC_CG:
793         case TEGRA210_SFC_STATUS:
794         case TEGRA210_SFC_INT_STATUS:
795         case TEGRA210_SFC_COEF_RAM:
796         case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
797         case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
798                 return true;
799         default:
800                 return false;
801         };
802 }
803
804 static bool tegra210_sfc_volatile_reg(struct device *dev, unsigned int reg)
805 {
806         switch (reg) {
807         case TEGRA210_SFC_AXBAR_RX_STATUS:
808         case TEGRA210_SFC_AXBAR_RX_INT_STATUS:
809         case TEGRA210_SFC_AXBAR_RX_INT_SET:
810
811         case TEGRA210_SFC_AXBAR_TX_STATUS:
812         case TEGRA210_SFC_AXBAR_TX_INT_STATUS:
813         case TEGRA210_SFC_AXBAR_TX_INT_SET:
814
815         case TEGRA210_SFC_SOFT_RESET:
816         case TEGRA210_SFC_STATUS:
817         case TEGRA210_SFC_INT_STATUS:
818         case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
819         case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
820                 return true;
821         default:
822                 return false;
823         };
824 }
825
826 static bool tegra210_sfc_precious_reg(struct device *dev, unsigned int reg)
827 {
828         switch (reg) {
829         case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
830                 return true;
831         default:
832                 return false;
833         };
834 }
835
836 static const struct regmap_config tegra210_sfc_regmap_config = {
837         .reg_bits = 32,
838         .reg_stride = 4,
839         .val_bits = 32,
840         .max_register = TEGRA210_SFC_AHUBRAMCTL_SFC_DATA,
841         .writeable_reg = tegra210_sfc_wr_reg,
842         .readable_reg = tegra210_sfc_rd_reg,
843         .volatile_reg = tegra210_sfc_volatile_reg,
844         .precious_reg = tegra210_sfc_precious_reg,
845         .reg_defaults = tegra210_sfc_reg_defaults,
846         .num_reg_defaults = ARRAY_SIZE(tegra210_sfc_reg_defaults),
847         .cache_type = REGCACHE_FLAT,
848 };
849
850 static const struct tegra210_sfc_soc_data soc_data_tegra210 = {
851         .set_audio_cif = tegra210_xbar_set_cif,
852 };
853
854 static const struct of_device_id tegra210_sfc_of_match[] = {
855         { .compatible = "nvidia,tegra210-sfc", .data = &soc_data_tegra210 },
856         {},
857 };
858
859 static int tegra210_sfc_platform_probe(struct platform_device *pdev)
860 {
861         struct tegra210_sfc *sfc;
862         struct resource *mem, *memregion;
863         void __iomem *regs;
864         int ret = 0;
865         const struct of_device_id *match;
866         struct tegra210_sfc_soc_data *soc_data;
867
868         match = of_match_device(tegra210_sfc_of_match, &pdev->dev);
869         if (!match) {
870                 dev_err(&pdev->dev, "Error: No device match found\n");
871                 ret = -ENODEV;
872                 goto err;
873         }
874         soc_data = (struct tegra210_sfc_soc_data *)match->data;
875
876         sfc = devm_kzalloc(&pdev->dev, sizeof(struct tegra210_sfc), GFP_KERNEL);
877         if (!sfc) {
878                 dev_err(&pdev->dev, "Can't allocate sfc\n");
879                 ret = -ENOMEM;
880                 goto err;
881         }
882
883         sfc->soc_data = soc_data;
884         sfc->is_shutdown = false;
885
886         /* initialize default output srate */
887         sfc->srate_out = TEGRA210_SFC_FS48;
888
889         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
890         if (!mem) {
891                 dev_err(&pdev->dev, "No memory resource\n");
892                 ret = -ENODEV;
893                 goto err;
894         }
895
896         memregion = devm_request_mem_region(&pdev->dev, mem->start,
897                                             resource_size(mem), pdev->name);
898         if (!memregion) {
899                 dev_err(&pdev->dev, "Memory region already claimed\n");
900                 ret = -EBUSY;
901                 goto err;
902         }
903
904         regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
905         if (!regs) {
906                 dev_err(&pdev->dev, "ioremap failed\n");
907                 ret = -ENOMEM;
908                 goto err;
909         }
910
911         sfc->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
912                                             &tegra210_sfc_regmap_config);
913         if (IS_ERR(sfc->regmap)) {
914                 dev_err(&pdev->dev, "regmap init failed\n");
915                 ret = PTR_ERR(sfc->regmap);
916                 goto err;
917         }
918         regcache_cache_only(sfc->regmap, true);
919
920         if (of_property_read_u32(pdev->dev.of_node,
921                                 "nvidia,ahub-sfc-id",
922                                 &pdev->dev.id) < 0) {
923                 dev_err(&pdev->dev,
924                         "Missing property nvidia,ahub-sfc-id\n");
925                 ret = -ENODEV;
926                 goto err;
927         }
928
929         pm_runtime_enable(&pdev->dev);
930         if (!pm_runtime_enabled(&pdev->dev)) {
931                 ret = tegra210_sfc_runtime_resume(&pdev->dev);
932                 if (ret)
933                         goto err_pm_disable;
934         }
935
936         ret = snd_soc_register_codec(&pdev->dev, &tegra210_sfc_codec,
937                                      tegra210_sfc_dais,
938                                      ARRAY_SIZE(tegra210_sfc_dais));
939         if (ret != 0) {
940                 dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
941                 goto err_suspend;
942         }
943
944         dev_set_drvdata(&pdev->dev, sfc);
945
946         return 0;
947
948 err_suspend:
949         if (!pm_runtime_status_suspended(&pdev->dev))
950                 tegra210_sfc_runtime_suspend(&pdev->dev);
951 err_pm_disable:
952         pm_runtime_disable(&pdev->dev);
953 err:
954         return ret;
955 }
956
957 static void tegra210_sfc_platform_shutdown(struct platform_device *pdev)
958 {
959         struct tegra210_sfc *sfc = dev_get_drvdata(&pdev->dev);
960
961         sfc->is_shutdown = true;
962 }
963
964 static int tegra210_sfc_platform_remove(struct platform_device *pdev)
965 {
966         snd_soc_unregister_codec(&pdev->dev);
967
968         pm_runtime_disable(&pdev->dev);
969         if (!pm_runtime_status_suspended(&pdev->dev))
970                 tegra210_sfc_runtime_suspend(&pdev->dev);
971
972         return 0;
973 }
974
975 static const struct dev_pm_ops tegra210_sfc_pm_ops = {
976         SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
977                            tegra210_sfc_runtime_resume, NULL)
978         SET_SYSTEM_SLEEP_PM_OPS(tegra210_sfc_suspend, NULL)
979 };
980
981 static struct platform_driver tegra210_sfc_driver = {
982         .driver = {
983                 .name = DRV_NAME,
984                 .owner = THIS_MODULE,
985                 .of_match_table = tegra210_sfc_of_match,
986                 .pm = &tegra210_sfc_pm_ops,
987         },
988         .probe = tegra210_sfc_platform_probe,
989         .remove = tegra210_sfc_platform_remove,
990         .shutdown = tegra210_sfc_platform_shutdown,
991 };
992 module_platform_driver(tegra210_sfc_driver)
993
994 MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
995 MODULE_DESCRIPTION("Tegra210 SFC ASoC driver");
996 MODULE_LICENSE("GPL");
997 MODULE_ALIAS("platform:" DRV_NAME);
998 MODULE_DEVICE_TABLE(of, tegra210_sfc_of_match);