80d22d203fb65087d142aa504fc497b702ec5f81
[linux-2.6.git] / sound / soc / tegra / tegra_asoc_utils.c
1 /*
2  * tegra_asoc_utils.c - Harmony machine ASoC driver
3  *
4  * Author: Stephen Warren <swarren@nvidia.com>
5  * Copyright (c) 2010-12, NVIDIA CORPORATION. All rights reserved.
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms 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 that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  *
20  */
21
22 #include <linux/clk.h>
23 #include <linux/device.h>
24 #include <linux/err.h>
25 #include <linux/kernel.h>
26
27 #include <mach/clk.h>
28
29 #include <sound/soc.h>
30
31 #include "tegra_pcm.h"
32 #include "tegra_asoc_utils.h"
33
34 int g_is_call_mode;
35
36 bool tegra_is_voice_call_active(void)
37 {
38         if (g_is_call_mode)
39                 return true;
40         else
41                 return false;
42 }
43 EXPORT_SYMBOL_GPL(tegra_is_voice_call_active);
44
45 static int tegra_get_avp_device(struct snd_kcontrol *kcontrol,
46                                 struct snd_ctl_elem_value *ucontrol)
47 {
48         struct  tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
49
50         ucontrol->value.integer.value[0] = data->avp_device_id;
51         return 0;
52 }
53
54 static int tegra_set_avp_device(struct snd_kcontrol *kcontrol,
55                                 struct snd_ctl_elem_value *ucontrol)
56 {
57         struct  tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
58         struct snd_soc_card *card = data->card;
59         struct snd_soc_pcm_runtime *rtd;
60         struct snd_pcm_substream *substream;
61         struct tegra_runtime_data *prtd;
62         int id, old_id = data->avp_device_id;
63
64         id = ucontrol->value.integer.value[0];
65         if ((id >= card->num_rtd) || (id < 0))
66                 id = -1;
67
68         if (old_id >= 0) {
69                 rtd = &card->rtd[old_id];
70                 substream =
71                         rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
72                 if (substream && substream->runtime) {
73                         prtd = substream->runtime->private_data;
74                         if (prtd->running)
75                                 return -EBUSY;
76                         if (prtd)
77                                 prtd->disable_intr = false;
78                 }
79         }
80
81         if (id >= 0) {
82                 rtd = &card->rtd[id];
83                 substream =
84                         rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
85                 if (substream && substream->runtime) {
86                         prtd = substream->runtime->private_data;
87                         if (prtd->running)
88                                 return -EBUSY;
89                         if (prtd) {
90                                 prtd->disable_intr = true;
91                                 if (data->avp_dma_addr || prtd->avp_dma_addr)
92                                         prtd->avp_dma_addr = data->avp_dma_addr;
93                         }
94                 }
95         }
96         data->avp_device_id = id;
97         return 1;
98 }
99
100 static int tegra_get_dma_ch_id(struct snd_kcontrol *kcontrol,
101                                struct snd_ctl_elem_value *ucontrol)
102 {
103         struct  tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
104         struct snd_soc_card *card = data->card;
105         struct snd_soc_pcm_runtime *rtd;
106         struct snd_pcm_substream *substream;
107         struct tegra_runtime_data *prtd;
108
109         ucontrol->value.integer.value[0] = -1;
110         if (data->avp_device_id < 0)
111                 return 0;
112
113         rtd = &card->rtd[data->avp_device_id];
114         substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
115         if (!substream || !substream->runtime)
116                 return 0;
117
118         prtd = substream->runtime->private_data;
119         if (!prtd || !prtd->dma_chan)
120                 return 0;
121
122         ucontrol->value.integer.value[0] =
123                 tegra_dma_get_channel_id(prtd->dma_chan);
124         return 0;
125 }
126
127 static int tegra_set_dma_addr(struct snd_kcontrol *kcontrol,
128                               struct snd_ctl_elem_value *ucontrol)
129 {
130         struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
131         struct snd_soc_card *card = data->card;
132         struct snd_soc_pcm_runtime *rtd;
133         struct snd_pcm_substream *substream;
134         struct tegra_runtime_data *prtd;
135
136         data->avp_dma_addr = ucontrol->value.integer.value[0];
137
138         rtd = &card->rtd[data->avp_device_id];
139         substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
140         if (!substream || !substream->runtime)
141                 return 0;
142
143         prtd = substream->runtime->private_data;
144         if (!prtd)
145                 return 0;
146
147         prtd->avp_dma_addr = data->avp_dma_addr;
148         return 1;
149 }
150
151 static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
152                               struct snd_ctl_elem_value *ucontrol)
153 {
154         struct  tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
155         struct snd_soc_card *card = data->card;
156         struct snd_soc_pcm_runtime *rtd;
157         struct snd_pcm_substream *substream;
158         struct tegra_runtime_data *prtd;
159
160         ucontrol->value.integer.value[0] = 0;
161         if (data->avp_device_id < 0)
162                 return 0;
163
164         rtd = &card->rtd[data->avp_device_id];
165         substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
166         if (!substream || !substream->runtime)
167                 return 0;
168
169         prtd = substream->runtime->private_data;
170         if (!prtd || !prtd->dma_chan)
171                 return 0;
172
173         ucontrol->value.integer.value[0] = prtd->avp_dma_addr ?
174                                            prtd->avp_dma_addr :
175                                            substream->runtime->dma_addr;
176
177         return 0;
178 }
179
180 struct snd_kcontrol_new tegra_avp_controls[] = {
181         SOC_SINGLE_EXT("AVP alsa device select", 0, 0, TEGRA_ALSA_MAX_DEVICES, \
182                         0, tegra_get_avp_device, tegra_set_avp_device),
183         SOC_SINGLE_EXT("AVP DMA channel id", 0, 0, TEGRA_DMA_MAX_CHANNELS, \
184                         0, tegra_get_dma_ch_id, NULL),
185         SOC_SINGLE_EXT("AVP DMA address", 0, 0, 0xFFFFFFFF, \
186                         0, tegra_get_dma_addr, tegra_set_dma_addr),
187 };
188
189 int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
190                               int mclk)
191 {
192         int new_baseclock;
193         bool clk_change;
194         int err;
195         bool reenable_clock;
196
197         switch (srate) {
198         case 11025:
199         case 22050:
200         case 44100:
201         case 88200:
202 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
203                 new_baseclock = 56448000;
204 #else
205                 new_baseclock = 564480000;
206 #endif
207                 break;
208         case 8000:
209         case 16000:
210         case 32000:
211         case 48000:
212         case 64000:
213         case 96000:
214 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
215                 new_baseclock = 73728000;
216 #else
217                 new_baseclock = 552960000;
218 #endif
219                 break;
220         default:
221                 return -EINVAL;
222         }
223
224         clk_change = ((new_baseclock != data->set_baseclock) ||
225                         (mclk != data->set_mclk));
226         if (!clk_change)
227                 return 0;
228
229         /* Don't change rate if already one dai-link is using it */
230         if (data->lock_count)
231                 return -EINVAL;
232
233         data->set_baseclock = 0;
234         data->set_mclk = 0;
235
236         reenable_clock = false;
237         if(tegra_is_clk_enabled(data->clk_pll_a)) {
238                 clk_disable(data->clk_pll_a);
239                 reenable_clock = true;
240         }
241         err = clk_set_rate(data->clk_pll_a, new_baseclock);
242         if (err) {
243                 dev_err(data->dev, "Can't set pll_a rate: %d\n", err);
244                 return err;
245         }
246         if(reenable_clock)
247                 clk_enable(data->clk_pll_a);
248
249         reenable_clock = false;
250         if(tegra_is_clk_enabled(data->clk_pll_a_out0)) {
251                 clk_disable(data->clk_pll_a_out0);
252                 reenable_clock = true;
253         }
254         err = clk_set_rate(data->clk_pll_a_out0, mclk);
255         if (err) {
256                 dev_err(data->dev, "Can't set clk_pll_a_out0 rate: %d\n", err);
257                 return err;
258         }
259         if(reenable_clock)
260                 clk_enable(data->clk_pll_a_out0);
261
262
263         data->set_baseclock = new_baseclock;
264         data->set_mclk = mclk;
265
266         return 0;
267 }
268 EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate);
269
270 void tegra_asoc_utils_lock_clk_rate(struct tegra_asoc_utils_data *data,
271                                     int lock)
272 {
273         if (lock)
274                 data->lock_count++;
275         else if (data->lock_count)
276                 data->lock_count--;
277 }
278 EXPORT_SYMBOL_GPL(tegra_asoc_utils_lock_clk_rate);
279
280 int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data)
281 {
282         int err;
283
284         err = clk_enable(data->clk_cdev1);
285         if (err) {
286                 dev_err(data->dev, "Can't enable cdev1: %d\n", err);
287                 return err;
288         }
289
290         return 0;
291 }
292 EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_enable);
293
294 int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data)
295 {
296         clk_disable(data->clk_cdev1);
297         return 0;
298 }
299 EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_disable);
300
301 int tegra_asoc_utils_register_ctls(struct tegra_asoc_utils_data *data)
302 {
303         int i;
304         int ret = 0;
305
306         /* Add AVP related alsa controls */
307         data->avp_device_id = -1;
308         for (i = 0; i < ARRAY_SIZE(tegra_avp_controls); i++) {
309                 ret = snd_ctl_add(data->card->snd_card,
310                                 snd_ctl_new1(&tegra_avp_controls[i], data));
311                 if (ret < 0) {
312                         dev_err(data->dev, "Can't add avp alsa controls");
313                         return ret;
314                 }
315         }
316
317         return ret;
318 }
319 EXPORT_SYMBOL_GPL(tegra_asoc_utils_register_ctls);
320
321 int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
322                           struct device *dev, struct snd_soc_card *card)
323 {
324         int ret;
325
326         data->dev = dev;
327         data->card = card;
328
329         data->clk_pll_p_out1 = clk_get_sys(NULL, "pll_p_out1");
330         if (IS_ERR(data->clk_pll_p_out1)) {
331                 dev_err(data->dev, "Can't retrieve clk pll_p_out1\n");
332                 ret = PTR_ERR(data->clk_pll_p_out1);
333                 goto err;
334         }
335
336         data->clk_pll_a = clk_get_sys(NULL, "pll_a");
337         if (IS_ERR(data->clk_pll_a)) {
338                 dev_err(data->dev, "Can't retrieve clk pll_a\n");
339                 ret = PTR_ERR(data->clk_pll_a);
340                 goto err_put_pll_p_out1;
341         }
342
343         data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
344         if (IS_ERR(data->clk_pll_a_out0)) {
345                 dev_err(data->dev, "Can't retrieve clk pll_a_out0\n");
346                 ret = PTR_ERR(data->clk_pll_a_out0);
347                 goto err_put_pll_a;
348         }
349
350         data->clk_m = clk_get_sys(NULL, "clk_m");
351         if (IS_ERR(data->clk_m)) {
352                 dev_err(data->dev, "Can't retrieve clk clk_m\n");
353                 ret = PTR_ERR(data->clk_m);
354                 goto err;
355         }
356
357 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
358         data->clk_cdev1 = clk_get_sys(NULL, "cdev1");
359 #else
360         data->clk_cdev1 = clk_get_sys("extern1", NULL);
361 #endif
362         if (IS_ERR(data->clk_cdev1)) {
363                 dev_err(data->dev, "Can't retrieve clk cdev1\n");
364                 ret = PTR_ERR(data->clk_cdev1);
365                 goto err_put_pll_a_out0;
366         }
367
368 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
369         data->clk_out1 = ERR_PTR(-ENOENT);
370 #else
371         data->clk_out1 = clk_get_sys("clk_out_1", "extern1");
372         if (IS_ERR(data->clk_out1)) {
373                 dev_err(data->dev, "Can't retrieve clk out1\n");
374                 ret = PTR_ERR(data->clk_out1);
375                 goto err_put_cdev1;
376         }
377 #endif
378
379         ret = clk_enable(data->clk_cdev1);
380         if (ret) {
381                 dev_err(data->dev, "Can't enable clk cdev1/extern1");
382                 goto err_put_out1;
383         }
384
385         if (!IS_ERR(data->clk_out1)) {
386                 ret = clk_enable(data->clk_out1);
387                 if (ret) {
388                         dev_err(data->dev, "Can't enable clk out1");
389                         goto err_put_out1;
390                 }
391         }
392
393         ret = tegra_asoc_utils_set_rate(data, 48000, 256 * 48000);
394         if (ret)
395                 goto err_put_out1;
396
397         return 0;
398
399 err_put_out1:
400         if (!IS_ERR(data->clk_out1))
401                 clk_put(data->clk_out1);
402 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
403 err_put_cdev1:
404 #endif
405         clk_put(data->clk_cdev1);
406 err_put_pll_a_out0:
407         clk_put(data->clk_pll_a_out0);
408 err_put_pll_a:
409         clk_put(data->clk_pll_a);
410 err_put_pll_p_out1:
411         clk_put(data->clk_pll_p_out1);
412 err:
413         return ret;
414 }
415 EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
416
417 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
418 int tegra_asoc_utils_set_parent (struct tegra_asoc_utils_data *data,
419                                 int is_i2s_master)
420 {
421         int ret = -ENODEV;
422
423         if (is_i2s_master) {
424                 ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0);
425                 if (ret) {
426                         dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
427                         return ret;
428                 }
429         } else {
430                 if(clk_get_rate(data->clk_m) == 26000000)
431                         clk_set_rate(data->clk_cdev1, 13000000);
432
433                 ret = clk_set_parent(data->clk_cdev1, data->clk_m);
434                 if (ret) {
435                         dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
436                         return ret;
437                 }
438         }
439
440         return 0;
441 }
442 EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_parent);
443 #endif
444
445 void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
446 {
447         if (!IS_ERR(data->clk_out1))
448                 clk_put(data->clk_out1);
449
450         clk_put(data->clk_cdev1);
451         /* Just to make sure that clk_cdev1 should turn off in case if it is
452          * switched on by some codec whose hw switch is not registered.*/
453         if (tegra_is_clk_enabled(data->clk_cdev1))
454                 clk_disable(data->clk_cdev1);
455
456         if (!IS_ERR(data->clk_pll_a_out0))
457                 clk_put(data->clk_pll_a_out0);
458
459         if (!IS_ERR(data->clk_pll_a))
460                 clk_put(data->clk_pll_a);
461
462         if (!IS_ERR(data->clk_pll_p_out1))
463                 clk_put(data->clk_pll_p_out1);
464 }
465 EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini);
466
467 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
468 MODULE_DESCRIPTION("Tegra ASoC utility code");
469 MODULE_LICENSE("GPL");