Revert "TEMP: asoc: tegra-alt: disable SLGC"
[linux-3.10.git] / sound / soc / tegra-alt / tegra210_sfc_alt.c
1 /*
2  * tegra210_sfc_alt.c - Tegra210 SFC driver
3  *
4  * Copyright (c) 2014 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
34 #include "tegra210_xbar_alt.h"
35 #include "tegra210_sfc_alt.h"
36
37 #define DRV_NAME "tegra210-sfc"
38
39 static int tegra210_sfc_runtime_suspend(struct device *dev)
40 {
41         struct tegra210_sfc *sfc = dev_get_drvdata(dev);
42
43         regcache_cache_only(sfc->regmap, true);
44
45         clk_disable_unprepare(sfc->clk_sfc);
46
47         return 0;
48 }
49
50 static int tegra210_sfc_runtime_resume(struct device *dev)
51 {
52         struct tegra210_sfc *sfc = dev_get_drvdata(dev);
53
54         int ret;
55
56         ret = clk_prepare_enable(sfc->clk_sfc);
57         if (ret) {
58                 dev_err(dev, "clk_enable failed: %d\n", ret);
59                 return ret;
60         }
61
62         regcache_cache_only(sfc->regmap, false);
63
64         return 0;
65 }
66
67 static int tegra210_sfc_set_dai_sysclk(struct snd_soc_dai *dai,
68                 int clk_id, unsigned int freq, int dir)
69 {
70         struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
71         unsigned int value;
72
73         switch (freq) {
74         case 8000:
75                 value = TEGRA210_SFC_FS8;
76                 break;
77         case 11025:
78                 value = TEGRA210_SFC_FS11_025;
79                 break;
80         case 16000:
81                 value = TEGRA210_SFC_FS16;
82                 break;
83         case 22050:
84                 value = TEGRA210_SFC_FS22_05;
85                 break;
86         case 24000:
87                 value = TEGRA210_SFC_FS24;
88                 break;
89         case 32000:
90                 value = TEGRA210_SFC_FS32;
91                 break;
92         case 44100:
93                 value = TEGRA210_SFC_FS44_1;
94                 break;
95         case 48000:
96                 value = TEGRA210_SFC_FS48;
97                 break;
98         case 64000:
99                 value = TEGRA210_SFC_FS64;
100                 break;
101         case 88200:
102                 value = TEGRA210_SFC_FS88_2;
103                 break;
104         case 96000:
105                 value = TEGRA210_SFC_FS96;
106                 break;
107         case 176400:
108                 value = TEGRA210_SFC_FS176_4;
109                 break;
110         case 192000:
111                 value = TEGRA210_SFC_FS192;
112                 break;
113         default:
114                 value = TEGRA210_SFC_FS8;
115                 break;
116         }
117
118         if (dir == SND_SOC_CLOCK_OUT)
119                 sfc->srate_out = value;
120         else if (dir == SND_SOC_CLOCK_IN)
121                 sfc->srate_in = value;
122
123         return 0;
124 }
125
126 static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
127                                 struct snd_pcm_hw_params *params,
128                                 unsigned int reg)
129 {
130         int channels, audio_bits;
131         struct tegra210_xbar_cif_conf cif_conf;
132
133         channels = params_channels(params);
134         if (channels < 2)
135                 return -EINVAL;
136
137         switch (params_format(params)) {
138         case SNDRV_PCM_FORMAT_S16_LE:
139                 audio_bits = TEGRA210_AUDIOCIF_BITS_16;
140                 break;
141         case SNDRV_PCM_FORMAT_S32_LE:
142                 audio_bits = TEGRA210_AUDIOCIF_BITS_32;
143                 break;
144         default:
145                 return -EINVAL;
146         }
147
148         cif_conf.threshold = 0;
149         cif_conf.audio_channels = channels;
150         cif_conf.client_channels = channels;
151         cif_conf.audio_bits = audio_bits;
152         cif_conf.client_bits = audio_bits;
153         cif_conf.expand = 0;
154         cif_conf.stereo_conv = 0;
155         cif_conf.replicate = 0;
156         cif_conf.truncate = 0;
157         cif_conf.mono_conv = 0;
158
159         sfc->soc_data->set_audio_cif(sfc->regmap, reg, &cif_conf);
160
161         return 0;
162 }
163
164 static int tegra210_sfc_in_hw_params(struct snd_pcm_substream *substream,
165                                  struct snd_pcm_hw_params *params,
166                                  struct snd_soc_dai *dai)
167 {
168         struct device *dev = dai->dev;
169         struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
170         int ret;
171
172         ret = tegra210_sfc_set_audio_cif(sfc, params,
173                                 TEGRA210_SFC_AXBAR_RX_CIF_CTRL);
174         if (ret) {
175                 dev_err(dev, "Can't set SFC RX CIF: %d\n", ret);
176                 return ret;
177         }
178
179         regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_RX_FREQ, sfc->srate_in);
180         return ret;
181 }
182
183 static int tegra210_sfc_out_hw_params(struct snd_pcm_substream *substream,
184                                  struct snd_pcm_hw_params *params,
185                                  struct snd_soc_dai *dai)
186 {
187         struct device *dev = dai->dev;
188         struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
189         int ret;
190
191         ret = tegra210_sfc_set_audio_cif(sfc, params,
192                                 TEGRA210_SFC_AXBAR_TX_CIF_CTRL);
193         if (ret) {
194                 dev_err(dev, "Can't set SFC TX CIF: %d\n", ret);
195                 return ret;
196         }
197
198         if (sfc->srate_out < 0) {
199                 dev_err(dev, "SFC%d output rate not set: %d\n",
200                         dev->id, -EINVAL);
201                 return -EINVAL;
202         }
203
204         regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_TX_FREQ, sfc->srate_out);
205         return ret;
206 }
207
208 static int tegra210_sfc_get_srate(struct snd_kcontrol *kcontrol,
209         struct snd_ctl_elem_value *ucontrol)
210 {
211         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
212         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
213
214         /* get the sfc output rate */
215         ucontrol->value.integer.value[0] = sfc->srate_out + 1;
216
217         return 0;
218 }
219
220 static int tegra210_sfc_put_srate(struct snd_kcontrol *kcontrol,
221         struct snd_ctl_elem_value *ucontrol)
222 {
223         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
224         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
225
226         /* update the sfc output rate */
227         sfc->srate_out = ucontrol->value.integer.value[0] - 1;
228
229         return 0;
230 }
231
232 static int tegra210_sfc_codec_probe(struct snd_soc_codec *codec)
233 {
234         struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
235         int ret;
236
237         codec->control_data = sfc->regmap;
238         ret = snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP);
239         if (ret != 0) {
240                 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
241                 return ret;
242         }
243
244         return 0;
245 }
246
247 static struct snd_soc_dai_ops tegra210_sfc_in_dai_ops = {
248         .hw_params      = tegra210_sfc_in_hw_params,
249         .set_sysclk     = tegra210_sfc_set_dai_sysclk,
250 };
251
252 static struct snd_soc_dai_ops tegra210_sfc_out_dai_ops = {
253         .hw_params      = tegra210_sfc_out_hw_params,
254 };
255
256 static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
257         {
258                 .name = "CIF",
259                 .playback = {
260                         .stream_name = "SFC Receive",
261                         .channels_min = 1,
262                         .channels_max = 2,
263                         .rates = SNDRV_PCM_RATE_8000_96000,
264                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
265                 },
266                 .ops = &tegra210_sfc_in_dai_ops,
267         },
268         {
269                 .name = "DAP",
270                 .capture = {
271                         .stream_name = "SFC Transmit",
272                         .channels_min = 1,
273                         .channels_max = 16,
274                         .rates = SNDRV_PCM_RATE_8000_96000,
275                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
276                 },
277                 .ops = &tegra210_sfc_out_dai_ops,
278         }
279 };
280
281 static const struct snd_soc_dapm_widget tegra210_sfc_widgets[] = {
282         SND_SOC_DAPM_AIF_IN("SFC RX", NULL, 0, SND_SOC_NOPM,
283                                 0, 0),
284         SND_SOC_DAPM_AIF_OUT("SFC TX", NULL, 0, TEGRA210_SFC_ENABLE,
285                                 TEGRA210_SFC_EN_SHIFT, 0),
286 };
287
288 static const struct snd_soc_dapm_route tegra210_sfc_routes[] = {
289         { "SFC RX",       NULL, "SFC Receive" },
290         { "SFC TX",       NULL, "SFC RX" },
291         { "SFC Transmit", NULL, "SFC TX" },
292 };
293
294 static const char * const tegra210_sfc_srate_text[] = {
295         "None",
296         "8kHz",
297         "11kHz",
298         "16kHz",
299         "22kHz",
300         "24kHz",
301         "32kHz",
302         "44kHz",
303         "48kHz",
304         "64kHz",
305         "88kHz",
306         "96kHz",
307         "176kHz",
308         "192kHz",
309 };
310
311 static const struct soc_enum tegra210_sfc_srate =
312         SOC_ENUM_SINGLE_EXT(14, tegra210_sfc_srate_text);
313
314 static const struct snd_kcontrol_new tegra210_sfc_controls[] = {
315         SOC_ENUM_EXT("output rate", tegra210_sfc_srate,
316                 tegra210_sfc_get_srate, tegra210_sfc_put_srate),
317 };
318
319 static struct snd_soc_codec_driver tegra210_sfc_codec = {
320         .probe = tegra210_sfc_codec_probe,
321         .dapm_widgets = tegra210_sfc_widgets,
322         .num_dapm_widgets = ARRAY_SIZE(tegra210_sfc_widgets),
323         .dapm_routes = tegra210_sfc_routes,
324         .num_dapm_routes = ARRAY_SIZE(tegra210_sfc_routes),
325         .controls = tegra210_sfc_controls,
326         .num_controls = ARRAY_SIZE(tegra210_sfc_controls),
327 };
328
329 static bool tegra210_sfc_wr_reg(struct device *dev, unsigned int reg)
330 {
331         switch (reg) {
332         case TEGRA210_SFC_AXBAR_RX_INT_MASK:
333         case TEGRA210_SFC_AXBAR_RX_INT_SET:
334         case TEGRA210_SFC_AXBAR_RX_INT_CLEAR:
335         case TEGRA210_SFC_AXBAR_RX_CIF_CTRL:
336         case TEGRA210_SFC_AXBAR_RX_FREQ:
337
338         case TEGRA210_SFC_AXBAR_TX_INT_MASK:
339         case TEGRA210_SFC_AXBAR_TX_INT_SET:
340         case TEGRA210_SFC_AXBAR_TX_INT_CLEAR:
341         case TEGRA210_SFC_AXBAR_TX_CIF_CTRL:
342         case TEGRA210_SFC_AXBAR_TX_FREQ:
343
344         case TEGRA210_SFC_ENABLE:
345         case TEGRA210_SFC_SOFT_RESET:
346         case TEGRA210_SFC_CG:
347         case TEGRA210_SFC_COEF_RAM:
348         case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
349         case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
350                 return true;
351         default:
352                 return false;
353         };
354 }
355
356 static bool tegra210_sfc_rd_reg(struct device *dev, unsigned int reg)
357 {
358         switch (reg) {
359         case TEGRA210_SFC_AXBAR_RX_STATUS:
360         case TEGRA210_SFC_AXBAR_RX_INT_STATUS:
361         case TEGRA210_SFC_AXBAR_RX_INT_MASK:
362         case TEGRA210_SFC_AXBAR_RX_INT_SET:
363         case TEGRA210_SFC_AXBAR_RX_INT_CLEAR:
364         case TEGRA210_SFC_AXBAR_RX_CIF_CTRL:
365         case TEGRA210_SFC_AXBAR_RX_FREQ:
366
367         case TEGRA210_SFC_AXBAR_TX_STATUS:
368         case TEGRA210_SFC_AXBAR_TX_INT_STATUS:
369         case TEGRA210_SFC_AXBAR_TX_INT_MASK:
370         case TEGRA210_SFC_AXBAR_TX_INT_SET:
371         case TEGRA210_SFC_AXBAR_TX_INT_CLEAR:
372         case TEGRA210_SFC_AXBAR_TX_CIF_CTRL:
373         case TEGRA210_SFC_AXBAR_TX_FREQ:
374
375         case TEGRA210_SFC_ENABLE:
376         case TEGRA210_SFC_SOFT_RESET:
377         case TEGRA210_SFC_CG:
378         case TEGRA210_SFC_STATUS:
379         case TEGRA210_SFC_INT_STATUS:
380         case TEGRA210_SFC_COEF_RAM:
381         case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
382         case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
383                 return true;
384         default:
385                 return false;
386         };
387 }
388
389 static bool tegra210_sfc_volatile_reg(struct device *dev, unsigned int reg)
390 {
391         switch (reg) {
392         case TEGRA210_SFC_AXBAR_RX_STATUS:
393         case TEGRA210_SFC_AXBAR_RX_INT_STATUS:
394         case TEGRA210_SFC_AXBAR_RX_INT_SET:
395
396         case TEGRA210_SFC_AXBAR_TX_STATUS:
397         case TEGRA210_SFC_AXBAR_TX_INT_STATUS:
398         case TEGRA210_SFC_AXBAR_TX_INT_SET:
399
400         case TEGRA210_SFC_SOFT_RESET:
401         case TEGRA210_SFC_STATUS:
402         case TEGRA210_SFC_INT_STATUS:
403         case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
404         case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
405                 return true;
406         default:
407                 return false;
408         };
409 }
410
411 static bool tegra210_sfc_precious_reg(struct device *dev, unsigned int reg)
412 {
413         switch (reg) {
414         case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
415                 return true;
416         default:
417                 return false;
418         };
419 }
420
421 static const struct regmap_config tegra210_sfc_regmap_config = {
422         .reg_bits = 32,
423         .reg_stride = 4,
424         .val_bits = 32,
425         .max_register = TEGRA210_SFC_AHUBRAMCTL_SFC_DATA,
426         .writeable_reg = tegra210_sfc_wr_reg,
427         .readable_reg = tegra210_sfc_rd_reg,
428         .volatile_reg = tegra210_sfc_volatile_reg,
429         .precious_reg = tegra210_sfc_precious_reg,
430         .cache_type = REGCACHE_RBTREE,
431 };
432
433 static const struct tegra210_sfc_soc_data soc_data_tegra210 = {
434         .set_audio_cif = tegra210_xbar_set_cif,
435 };
436
437 static const struct of_device_id tegra210_sfc_of_match[] = {
438         { .compatible = "nvidia,tegra210-sfc", .data = &soc_data_tegra210 },
439         {},
440 };
441
442 static int tegra210_sfc_platform_probe(struct platform_device *pdev)
443 {
444         struct tegra210_sfc *sfc;
445         struct resource *mem, *memregion;
446         void __iomem *regs;
447         int ret = 0;
448         const struct of_device_id *match;
449         struct tegra210_sfc_soc_data *soc_data;
450
451         match = of_match_device(tegra210_sfc_of_match, &pdev->dev);
452         if (!match) {
453                 dev_err(&pdev->dev, "Error: No device match found\n");
454                 ret = -ENODEV;
455                 goto err;
456         }
457         soc_data = (struct tegra210_sfc_soc_data *)match->data;
458
459         sfc = devm_kzalloc(&pdev->dev, sizeof(struct tegra210_sfc), GFP_KERNEL);
460         if (!sfc) {
461                 dev_err(&pdev->dev, "Can't allocate sfc\n");
462                 ret = -ENOMEM;
463                 goto err;
464         }
465         dev_set_drvdata(&pdev->dev, sfc);
466
467         sfc->soc_data = soc_data;
468
469         /* initialize default output srate */
470         sfc->srate_out = TEGRA210_SFC_FS48;
471
472         sfc->clk_sfc = devm_clk_get(&pdev->dev, NULL);
473         if (IS_ERR(sfc->clk_sfc)) {
474                 dev_err(&pdev->dev, "Can't retrieve sfc clock\n");
475                 ret = PTR_ERR(sfc->clk_sfc);
476                 goto err;
477         }
478
479         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
480         if (!mem) {
481                 dev_err(&pdev->dev, "No memory resource\n");
482                 ret = -ENODEV;
483                 goto err_clk_put;
484         }
485
486         memregion = devm_request_mem_region(&pdev->dev, mem->start,
487                                             resource_size(mem), pdev->name);
488         if (!memregion) {
489                 dev_err(&pdev->dev, "Memory region already claimed\n");
490                 ret = -EBUSY;
491                 goto err_clk_put;
492         }
493
494         regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
495         if (!regs) {
496                 dev_err(&pdev->dev, "ioremap failed\n");
497                 ret = -ENOMEM;
498                 goto err_clk_put;
499         }
500
501         sfc->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
502                                             &tegra210_sfc_regmap_config);
503         if (IS_ERR(sfc->regmap)) {
504                 dev_err(&pdev->dev, "regmap init failed\n");
505                 ret = PTR_ERR(sfc->regmap);
506                 goto err_clk_put;
507         }
508         regcache_cache_only(sfc->regmap, true);
509
510         if (of_property_read_u32(pdev->dev.of_node,
511                                 "nvidia,ahub-sfc-id",
512                                 &pdev->dev.id) < 0) {
513                 dev_err(&pdev->dev,
514                         "Missing property nvidia,ahub-sfc-id\n");
515                 ret = -ENODEV;
516                 goto err_clk_put;
517         }
518
519         pm_runtime_enable(&pdev->dev);
520         if (!pm_runtime_enabled(&pdev->dev)) {
521                 ret = tegra210_sfc_runtime_resume(&pdev->dev);
522                 if (ret)
523                         goto err_pm_disable;
524         }
525
526         ret = snd_soc_register_codec(&pdev->dev, &tegra210_sfc_codec,
527                                      tegra210_sfc_dais,
528                                      ARRAY_SIZE(tegra210_sfc_dais));
529         if (ret != 0) {
530                 dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
531                 goto err_suspend;
532         }
533
534         return 0;
535
536 err_suspend:
537         if (!pm_runtime_status_suspended(&pdev->dev))
538                 tegra210_sfc_runtime_suspend(&pdev->dev);
539 err_pm_disable:
540         pm_runtime_disable(&pdev->dev);
541 err_clk_put:
542         devm_clk_put(&pdev->dev, sfc->clk_sfc);
543 err:
544         return ret;
545 }
546
547 static int tegra210_sfc_platform_remove(struct platform_device *pdev)
548 {
549         struct tegra210_sfc *sfc = dev_get_drvdata(&pdev->dev);
550
551         snd_soc_unregister_codec(&pdev->dev);
552
553         pm_runtime_disable(&pdev->dev);
554         if (!pm_runtime_status_suspended(&pdev->dev))
555                 tegra210_sfc_runtime_suspend(&pdev->dev);
556
557         devm_clk_put(&pdev->dev, sfc->clk_sfc);
558
559         return 0;
560 }
561
562 static const struct dev_pm_ops tegra210_sfc_pm_ops = {
563         SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
564                            tegra210_sfc_runtime_resume, NULL)
565 };
566
567 static struct platform_driver tegra210_sfc_driver = {
568         .driver = {
569                 .name = DRV_NAME,
570                 .owner = THIS_MODULE,
571                 .of_match_table = tegra210_sfc_of_match,
572                 .pm = &tegra210_sfc_pm_ops,
573         },
574         .probe = tegra210_sfc_platform_probe,
575         .remove = tegra210_sfc_platform_remove,
576 };
577 module_platform_driver(tegra210_sfc_driver)
578
579 MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
580 MODULE_DESCRIPTION("Tegra210 SFC ASoC driver");
581 MODULE_LICENSE("GPL");
582 MODULE_ALIAS("platform:" DRV_NAME);
583 MODULE_DEVICE_TABLE(of, tegra210_sfc_of_match);