ARM: OMAP: Remove broken DMA function omap_get_dma_src_addr_counter
[pandora-kernel.git] / sound / arm / omap / omap-alsa.c
1 /*
2  * sound/arm/omap-alsa.c
3  *
4  * Alsa Driver for OMAP
5  *
6  * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
7  * Written by Daniel Petrini, David Cohen, Anderson Briglia
8  *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
9  *
10  * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
11  *
12  * Based on sa11xx-uda1341.c,
13  * Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
14  *
15  * This program is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the
17  * Free Software Foundation; either version 2 of the License, or (at your
18  * option) any later version.
19  *
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
21  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
23  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * You should have received a copy of the  GNU General Public License along
32  * with this program; if not, write  to the Free Software Foundation, Inc.,
33  * 675 Mass Ave, Cambridge, MA 02139, USA.
34  *
35  * History:
36  *
37  * 2005-07-29   INdT Kernel Team - Alsa driver for omap osk. Creation of new
38  *                                 file omap-aic23.c
39  *
40  * 2005-12-18   Dirk Behme       - Added L/R Channel Interchange fix as proposed
41  *                                 by Ajaya Babu
42  *
43  */
44
45 #include <linux/platform_device.h>
46 #ifdef CONFIG_PM
47 #include <linux/pm.h>
48 #endif
49 #include <sound/core.h>
50 #include <sound/pcm.h>
51
52 #include <asm/arch/omap-alsa.h>
53 #include "omap-alsa-dma.h"
54
55 MODULE_AUTHOR("Mika Laitio");
56 MODULE_AUTHOR("Daniel Petrini");
57 MODULE_AUTHOR("David Cohen");
58 MODULE_AUTHOR("Anderson Briglia");
59
60 MODULE_LICENSE("GPL");
61 MODULE_DESCRIPTION("OMAP driver for ALSA");
62 MODULE_ALIAS("omap_alsa_mcbsp.1");
63
64 static char *id;
65 static struct snd_card_omap_codec       *alsa_codec;
66 static struct omap_alsa_codec_config    *alsa_codec_config;
67
68 /* FIXME: Please change to use omap asoc framework instead, this can be racy */
69 static dma_addr_t dma_start_pos;
70
71 /*
72  * HW interface start and stop helper functions
73  */
74 static int audio_ifc_start(void)
75 {
76         omap_mcbsp_start(AUDIO_MCBSP);
77         return 0;
78 }
79
80 static int audio_ifc_stop(void)
81 {
82         omap_mcbsp_stop(AUDIO_MCBSP);
83         return 0;
84 }
85
86 static void omap_alsa_audio_init(struct snd_card_omap_codec *omap_alsa)
87 {
88         /* Setup DMA stuff */
89         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].id = "Alsa omap out";
90         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id =
91             SNDRV_PCM_STREAM_PLAYBACK;
92         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev =
93             OMAP_DMA_MCBSP1_TX;
94         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].hw_start =
95             audio_ifc_start;
96         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].hw_stop =
97             audio_ifc_stop;
98
99         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].id = "Alsa omap in";
100         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].stream_id =
101             SNDRV_PCM_STREAM_CAPTURE;
102         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev =
103             OMAP_DMA_MCBSP1_RX;
104         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].hw_start =
105             audio_ifc_start;
106         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].hw_stop =
107             audio_ifc_stop;
108 }
109
110 /*
111  * DMA functions
112  * Depends on omap-alsa-dma.c functions and (omap) dma.c
113  */
114 static int audio_dma_request(struct audio_stream *s,
115                              void (*callback) (void *))
116 {
117         int err;
118         ADEBUG();
119
120         err = omap_request_alsa_sound_dma(s->dma_dev, s->id, s, &s->lch);
121         if (err < 0)
122                 printk(KERN_ERR "Unable to grab audio dma 0x%x\n", s->dma_dev);
123         return err;
124 }
125
126 static int audio_dma_free(struct audio_stream *s)
127 {
128         int err = 0;
129         ADEBUG();
130
131         err = omap_free_alsa_sound_dma(s, &s->lch);
132         if (err < 0)
133                 printk(KERN_ERR "Unable to free audio dma channels!\n");
134         return err;
135 }
136
137 /*
138  *  This function should calculate the current position of the dma in the
139  *  buffer. It will help alsa middle layer to continue update the buffer.
140  *  Its correctness is crucial for good functioning.
141  */
142 static u_int audio_get_dma_pos(struct audio_stream *s)
143 {
144         struct snd_pcm_substream *substream = s->stream;
145         struct snd_pcm_runtime *runtime = substream->runtime;
146         unsigned int offset;
147         unsigned long flags;
148         dma_addr_t count;
149         ADEBUG();
150
151         /* this must be called w/ interrupts locked as requested in dma.c */
152         spin_lock_irqsave(&s->dma_lock, flags);
153
154         /* For the current period let's see where we are */
155         count = omap_get_dma_src_pos(s->lch[s->dma_q_head]) - dma_start_pos;
156
157         spin_unlock_irqrestore(&s->dma_lock, flags);
158
159         /* Now, the position related to the end of that period */
160         offset = bytes_to_frames(runtime, s->offset) -
161                         bytes_to_frames(runtime, count);
162
163         if (offset >= runtime->buffer_size)
164                 offset = 0;
165
166         return offset;
167 }
168
169 /*
170  * this stops the dma and clears the dma ptrs
171  */
172 static void audio_stop_dma(struct audio_stream *s)
173 {
174         unsigned long flags;
175         ADEBUG();
176
177         spin_lock_irqsave(&s->dma_lock, flags);
178         s->active = 0;
179         s->period = 0;
180         s->periods = 0;
181
182         /* this stops the dma channel and clears the buffer ptrs */
183         omap_stop_alsa_sound_dma(s);
184
185         omap_clear_alsa_sound_dma(s);
186
187         spin_unlock_irqrestore(&s->dma_lock, flags);
188 }
189
190 /*
191  *  Main dma routine, requests dma according where you are in main alsa buffer
192  */
193 static void audio_process_dma(struct audio_stream *s)
194 {
195         struct snd_pcm_substream *substream = s->stream;
196         struct snd_pcm_runtime *runtime;
197         unsigned int dma_size;
198         unsigned int offset;
199         int ret;
200
201         ADEBUG();
202         runtime = substream->runtime;
203         if (s->active) {
204                 dma_size = frames_to_bytes(runtime, runtime->period_size);
205                 offset = dma_size * s->period;
206                 snd_assert(dma_size <= DMA_BUF_SIZE, return);
207                 /*
208                  * On omap1510 based devices, we need to call the stop_dma
209                  * before calling the start_dma or we will not receive the
210                  * irq from DMA after the first transfered/played buffer.
211                  * (invocation of callback_omap_alsa_sound_dma() method).
212                  */
213                 if (cpu_is_omap1510())
214                         omap_stop_alsa_sound_dma(s);
215
216                 dma_start_pos = (dma_addr_t)runtime->dma_area + offset;
217                 ret = omap_start_alsa_sound_dma(s, dma_start_pos, dma_size);
218                 if (ret) {
219                         printk(KERN_ERR "audio_process_dma: cannot"
220                                         " queue DMA buffer (%i)\n", ret);
221                         return;
222                 }
223
224                 s->period++;
225                 s->period %= runtime->periods;
226                 s->periods++;
227                 s->offset = offset;
228         }
229 }
230
231 /*
232  *  This is called when dma IRQ occurs at the end of each transmited block
233  */
234 void callback_omap_alsa_sound_dma(void *data)
235 {
236         struct audio_stream *s = data;
237
238         ADEBUG();
239         /*
240          * If we are getting a callback for an active stream then we inform
241          * the PCM middle layer we've finished a period
242          */
243         if (s->active)
244                 snd_pcm_period_elapsed(s->stream);
245
246         spin_lock(&s->dma_lock);
247         if (s->periods > 0)
248                 s->periods--;
249
250         audio_process_dma(s);
251         spin_unlock(&s->dma_lock);
252 }
253
254 /*
255  * Alsa section
256  * PCM settings and callbacks
257  */
258 static int snd_omap_alsa_trigger(struct snd_pcm_substream *substream, int cmd)
259 {
260         struct snd_card_omap_codec *chip =
261             snd_pcm_substream_chip(substream);
262         int stream_id = substream->pstr->stream;
263         struct audio_stream *s = &chip->s[stream_id];
264         int err = 0;
265
266         ADEBUG();
267         /* note local interrupts are already disabled in the midlevel code */
268         spin_lock(&s->dma_lock);
269         switch (cmd) {
270         case SNDRV_PCM_TRIGGER_START:
271                 /* requested stream startup */
272                 s->active = 1;
273                 audio_process_dma(s);
274                 break;
275         case SNDRV_PCM_TRIGGER_STOP:
276                 /* requested stream shutdown */
277                 audio_stop_dma(s);
278                 break;
279         default:
280                 err = -EINVAL;
281                 break;
282         }
283         spin_unlock(&s->dma_lock);
284
285         return err;
286 }
287
288 static int snd_omap_alsa_prepare(struct snd_pcm_substream *substream)
289 {
290         struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
291         struct snd_pcm_runtime *runtime = substream->runtime;
292         struct audio_stream *s = &chip->s[substream->pstr->stream];
293
294         ADEBUG();
295         /* set requested samplerate */
296         alsa_codec_config->codec_set_samplerate(runtime->rate);
297         chip->samplerate = runtime->rate;
298
299         s->period = 0;
300         s->periods = 0;
301
302         return 0;
303 }
304
305 static snd_pcm_uframes_t
306 snd_omap_alsa_pointer(struct snd_pcm_substream *substream)
307 {
308         struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
309
310         ADEBUG();
311         return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
312 }
313
314 static int snd_card_omap_alsa_open(struct snd_pcm_substream *substream)
315 {
316         struct snd_card_omap_codec *chip =
317             snd_pcm_substream_chip(substream);
318         struct snd_pcm_runtime *runtime = substream->runtime;
319         int stream_id = substream->pstr->stream;
320         int err;
321
322         ADEBUG();
323         chip->s[stream_id].stream = substream;
324         alsa_codec_config->codec_clock_on();
325         if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
326                 runtime->hw = *(alsa_codec_config->snd_omap_alsa_playback);
327         else
328                 runtime->hw = *(alsa_codec_config->snd_omap_alsa_capture);
329
330         err = snd_pcm_hw_constraint_integer(runtime,
331                                                 SNDRV_PCM_HW_PARAM_PERIODS);
332         if (err < 0)
333                 return err;
334
335         err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
336                                 alsa_codec_config->hw_constraints_rates);
337         if (err < 0)
338                 return err;
339
340         return 0;
341 }
342
343 static int snd_card_omap_alsa_close(struct snd_pcm_substream *substream)
344 {
345         struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
346
347         ADEBUG();
348         alsa_codec_config->codec_clock_off();
349         chip->s[substream->pstr->stream].stream = NULL;
350
351         return 0;
352 }
353
354 /* HW params & free */
355 static int snd_omap_alsa_hw_params(struct snd_pcm_substream *substream,
356                                         struct snd_pcm_hw_params *hw_params)
357 {
358         return snd_pcm_lib_malloc_pages(substream,
359                                         params_buffer_bytes(hw_params));
360 }
361
362 static int snd_omap_alsa_hw_free(struct snd_pcm_substream *substream)
363 {
364         return snd_pcm_lib_free_pages(substream);
365 }
366
367 /* pcm operations */
368 static struct snd_pcm_ops snd_card_omap_alsa_playback_ops = {
369         .open =         snd_card_omap_alsa_open,
370         .close =        snd_card_omap_alsa_close,
371         .ioctl =        snd_pcm_lib_ioctl,
372         .hw_params =    snd_omap_alsa_hw_params,
373         .hw_free =      snd_omap_alsa_hw_free,
374         .prepare =      snd_omap_alsa_prepare,
375         .trigger =      snd_omap_alsa_trigger,
376         .pointer =      snd_omap_alsa_pointer,
377 };
378
379 static struct snd_pcm_ops snd_card_omap_alsa_capture_ops = {
380         .open =         snd_card_omap_alsa_open,
381         .close =        snd_card_omap_alsa_close,
382         .ioctl =        snd_pcm_lib_ioctl,
383         .hw_params =    snd_omap_alsa_hw_params,
384         .hw_free =      snd_omap_alsa_hw_free,
385         .prepare =      snd_omap_alsa_prepare,
386         .trigger =      snd_omap_alsa_trigger,
387         .pointer =      snd_omap_alsa_pointer,
388 };
389
390 /*
391  *  Alsa init and exit section
392  *  Inits pcm alsa structures, allocate the alsa buffer, suspend, resume
393  */
394 static int __init snd_card_omap_alsa_pcm(struct snd_card_omap_codec *omap_alsa,
395                                         int device)
396 {
397         struct snd_pcm *pcm;
398         int err;
399
400         ADEBUG();
401         err = snd_pcm_new(omap_alsa->card, "OMAP PCM", device, 1, 1, &pcm);
402         if (err < 0)
403                 return err;
404
405         /* sets up initial buffer with continuous allocation */
406         snd_pcm_lib_preallocate_pages_for_all(pcm,
407                                               SNDRV_DMA_TYPE_CONTINUOUS,
408                                               snd_dma_continuous_data
409                                               (GFP_KERNEL),
410                                               128 * 1024, 128 * 1024);
411
412         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
413                         &snd_card_omap_alsa_playback_ops);
414         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
415                         &snd_card_omap_alsa_capture_ops);
416         pcm->private_data = omap_alsa;
417         pcm->info_flags = 0;
418         strcpy(pcm->name, "omap alsa pcm");
419
420         omap_alsa_audio_init(omap_alsa);
421
422         /* setup DMA controller */
423         audio_dma_request(&omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK],
424                           callback_omap_alsa_sound_dma);
425         audio_dma_request(&omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE],
426                           callback_omap_alsa_sound_dma);
427
428         omap_alsa->pcm = pcm;
429
430         return 0;
431 }
432
433
434 #ifdef CONFIG_PM
435 /*
436  * Driver suspend/resume - calls alsa functions. Some hints from aaci.c
437  */
438 int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state)
439 {
440         struct snd_card_omap_codec *chip;
441         struct snd_card *card = platform_get_drvdata(pdev);
442
443         if (card->power_state != SNDRV_CTL_POWER_D3hot) {
444                 chip = card->private_data;
445                 if (chip->card->power_state != SNDRV_CTL_POWER_D3hot) {
446                         snd_power_change_state(chip->card,
447                                                 SNDRV_CTL_POWER_D3hot);
448                         snd_pcm_suspend_all(chip->pcm);
449                         /* Mutes and turn clock off */
450                         alsa_codec_config->codec_clock_off();
451                         snd_omap_suspend_mixer();
452                 }
453         }
454         return 0;
455 }
456
457 int snd_omap_alsa_resume(struct platform_device *pdev)
458 {
459         struct snd_card_omap_codec *chip;
460         struct snd_card *card = platform_get_drvdata(pdev);
461
462         if (card->power_state != SNDRV_CTL_POWER_D0) {
463                 chip = card->private_data;
464                 if (chip->card->power_state != SNDRV_CTL_POWER_D0) {
465                         snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
466                         alsa_codec_config->codec_clock_on();
467                         snd_omap_resume_mixer();
468                 }
469         }
470         return 0;
471 }
472
473 #endif  /* CONFIG_PM */
474
475 void snd_omap_alsa_free(struct snd_card *card)
476 {
477         struct snd_card_omap_codec *chip = card->private_data;
478         ADEBUG();
479
480         /*
481          * Turn off codec after it is done.
482          * Can't do it immediately, since it may still have
483          * buffered data.
484          */
485         schedule_timeout_interruptible(2);
486
487         omap_mcbsp_stop(AUDIO_MCBSP);
488         omap_mcbsp_free(AUDIO_MCBSP);
489
490         audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
491         audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
492 }
493
494 /* module init & exit */
495
496 /*
497  * Inits alsa soudcard structure.
498  * Called by the probe method in codec after function pointers has been set.
499  */
500 int snd_omap_alsa_post_probe(struct platform_device *pdev,
501                                 struct omap_alsa_codec_config *config)
502 {
503         int err = 0;
504         int def_rate;
505         struct snd_card *card;
506
507         ADEBUG();
508         alsa_codec_config       = config;
509
510         alsa_codec_config->codec_clock_setup();
511         alsa_codec_config->codec_clock_on();
512
513         omap_mcbsp_request(AUDIO_MCBSP);
514         omap_mcbsp_stop(AUDIO_MCBSP);
515         omap_mcbsp_config(AUDIO_MCBSP, alsa_codec_config->mcbsp_regs_alsa);
516         omap_mcbsp_start(AUDIO_MCBSP);
517
518         if (alsa_codec_config && alsa_codec_config->codec_configure_dev)
519                 alsa_codec_config->codec_configure_dev();
520
521         alsa_codec_config->codec_clock_off();
522
523         /* register the soundcard */
524         card = snd_card_new(-1, id, THIS_MODULE, sizeof(alsa_codec));
525         if (card == NULL)
526                 goto nodev1;
527
528         alsa_codec = kcalloc(1, sizeof(*alsa_codec), GFP_KERNEL);
529         if (alsa_codec == NULL)
530                 goto nodev2;
531
532         card->private_data = (void *)alsa_codec;
533         card->private_free = snd_omap_alsa_free;
534
535         alsa_codec->card        = card;
536         def_rate                = alsa_codec_config->get_default_samplerate();
537         alsa_codec->samplerate  = def_rate;
538
539         spin_lock_init(&alsa_codec->s[0].dma_lock);
540         spin_lock_init(&alsa_codec->s[1].dma_lock);
541
542         /* mixer */
543         err = snd_omap_mixer(alsa_codec);
544         if (err < 0)
545                 goto nodev3;
546
547         /* PCM */
548         err = snd_card_omap_alsa_pcm(alsa_codec, 0);
549         if (err < 0)
550                 goto nodev3;
551
552         strcpy(card->driver, "OMAP_ALSA");
553         strcpy(card->shortname, alsa_codec_config->name);
554         sprintf(card->longname, alsa_codec_config->name);
555
556         snd_omap_init_mixer();
557         snd_card_set_dev(card, &pdev->dev);
558
559         err = snd_card_register(card);
560         if (err == 0) {
561                 printk(KERN_INFO "audio support initialized\n");
562                 platform_set_drvdata(pdev, card);
563                 return 0;
564         }
565
566 nodev3:
567         kfree(alsa_codec);
568 nodev2:
569         snd_card_free(card);
570 nodev1:
571         omap_mcbsp_stop(AUDIO_MCBSP);
572         omap_mcbsp_free(AUDIO_MCBSP);
573
574         return err;
575 }
576
577 int snd_omap_alsa_remove(struct platform_device *pdev)
578 {
579         struct snd_card *card = platform_get_drvdata(pdev);
580         struct snd_card_omap_codec *chip = card->private_data;
581
582         snd_card_free(card);
583
584         alsa_codec = NULL;
585         card->private_data = NULL;
586         kfree(chip);
587
588         platform_set_drvdata(pdev, NULL);
589
590         return 0;
591 }