]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/arm/omap/omap-alsa.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.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/driver.h>
50 #include <sound/core.h>
51 #include <sound/pcm.h>
52
53 #include <asm/arch/omap-alsa.h>
54 #include "omap-alsa-dma.h"
55
56 MODULE_AUTHOR("Mika Laitio, Daniel Petrini, David Cohen, Anderson Briglia - INdT");
57 MODULE_LICENSE("GPL");
58 MODULE_DESCRIPTION("OMAP driver for ALSA");
59 MODULE_ALIAS("omap_alsa_mcbsp.1");
60
61 static char *id = NULL; 
62 static struct snd_card_omap_codec       *alsa_codec             = NULL;
63 static struct omap_alsa_codec_config    *alsa_codec_config      = NULL;
64
65 /*
66  * HW interface start and stop helper functions
67  */
68 static int audio_ifc_start(void)
69 {
70         omap_mcbsp_start(AUDIO_MCBSP);
71         return 0;
72 }
73
74 static int audio_ifc_stop(void)
75 {
76         omap_mcbsp_stop(AUDIO_MCBSP);
77         return 0;
78 }
79
80 static void omap_alsa_audio_init(struct snd_card_omap_codec *omap_alsa)
81 {
82         /* Setup DMA stuff */
83         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].id = "Alsa omap out";
84         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id =
85             SNDRV_PCM_STREAM_PLAYBACK;
86         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev =
87             OMAP_DMA_MCBSP1_TX;
88         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].hw_start =
89             audio_ifc_start;
90         omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK].hw_stop =
91             audio_ifc_stop;
92
93         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].id = "Alsa omap in";
94         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].stream_id =
95             SNDRV_PCM_STREAM_CAPTURE;
96         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev =
97             OMAP_DMA_MCBSP1_RX;
98         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].hw_start =
99             audio_ifc_start;
100         omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE].hw_stop =
101             audio_ifc_stop;
102 }
103
104 /* 
105  * DMA functions 
106  * Depends on omap-alsa-dma.c functions and (omap) dma.c
107  * 
108  */
109 static int audio_dma_request(struct audio_stream *s,
110                              void (*callback) (void *))
111 {
112         int err;
113         ADEBUG();
114
115         err = omap_request_alsa_sound_dma(s->dma_dev, s->id, s, &s->lch);
116         if (err < 0)
117                 printk(KERN_ERR "Unable to grab audio dma 0x%x\n", s->dma_dev);
118         return err;
119 }
120
121 static int audio_dma_free(struct audio_stream *s)
122 {
123         int err = 0;
124         ADEBUG();
125
126         err = omap_free_alsa_sound_dma(s, &s->lch);
127         if (err < 0)
128                 printk(KERN_ERR "Unable to free audio dma channels!\n");
129         return err;
130 }
131
132 /*
133  *  This function should calculate the current position of the dma in the
134  *  buffer. It will help alsa middle layer to continue update the buffer.
135  *  Its correctness is crucial for good functioning.
136  */
137 static u_int audio_get_dma_pos(struct audio_stream *s)
138 {
139         struct snd_pcm_substream *substream = s->stream;
140         struct snd_pcm_runtime *runtime = substream->runtime;
141         unsigned int offset;
142         unsigned long flags;
143         dma_addr_t count;
144         ADEBUG();
145
146         /* this must be called w/ interrupts locked as requested in dma.c */
147         spin_lock_irqsave(&s->dma_lock, flags);
148
149         /* For the current period let's see where we are */
150         count = omap_get_dma_src_addr_counter(s->lch[s->dma_q_head]);
151
152         spin_unlock_irqrestore(&s->dma_lock, flags);
153
154         /* Now, the position related to the end of that period */
155         offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
156
157         if (offset >= runtime->buffer_size)
158                 offset = 0;
159
160         return offset;
161 }
162
163 /*
164  * this stops the dma and clears the dma ptrs
165  */
166 static void audio_stop_dma(struct audio_stream *s)
167 {
168         unsigned long flags;
169         ADEBUG();
170
171         spin_lock_irqsave(&s->dma_lock, flags);
172         s->active = 0;
173         s->period = 0;
174         s->periods = 0;
175
176         /* this stops the dma channel and clears the buffer ptrs */
177         omap_stop_alsa_sound_dma(s);
178
179         omap_clear_alsa_sound_dma(s);
180
181         spin_unlock_irqrestore(&s->dma_lock, flags);
182 }
183
184 /*
185  *  Main dma routine, requests dma according where you are in main alsa buffer
186  */
187 static void audio_process_dma(struct audio_stream *s)
188 {
189         struct snd_pcm_substream *substream = s->stream;
190         struct snd_pcm_runtime *runtime;
191         unsigned int dma_size;
192         unsigned int offset;
193         int ret;
194         
195         ADEBUG();
196         runtime = substream->runtime;
197         if (s->active) {
198                 dma_size = frames_to_bytes(runtime, runtime->period_size);
199                 offset = dma_size * s->period;
200                 snd_assert(dma_size <= DMA_BUF_SIZE,);
201                 /*
202                  * On omap1510 based devices, we need to call the stop_dma
203                  * before calling the start_dma or we will not receive the
204                  * irq from DMA after the first transfered/played buffer.
205                  * (invocation of callback_omap_alsa_sound_dma() method).
206                  */
207                 if (cpu_is_omap1510()) {
208                         omap_stop_alsa_sound_dma(s);
209                 }
210                 ret = omap_start_alsa_sound_dma(s,
211                                 (dma_addr_t)runtime->dma_area + offset,
212                                 dma_size);
213                 if (ret) {
214                         printk(KERN_ERR
215                                "audio_process_dma: cannot queue DMA buffer (%i)\n",
216                                ret);
217                         return;
218                 }
219
220                 s->period++;
221                 s->period %= runtime->periods;
222                 s->periods++;
223                 s->offset = offset;
224         }
225 }
226
227 /* 
228  *  This is called when dma IRQ occurs at the end of each transmited block
229  */
230 void callback_omap_alsa_sound_dma(void *data)
231 {
232         struct audio_stream *s = data;
233         
234         ADEBUG();
235         /* 
236          * If we are getting a callback for an active stream then we inform
237          * the PCM middle layer we've finished a period
238          */
239         if (s->active)
240                 snd_pcm_period_elapsed(s->stream);
241
242         spin_lock(&s->dma_lock);
243         if (s->periods > 0) 
244                 s->periods--;
245         
246         audio_process_dma(s);
247         spin_unlock(&s->dma_lock);
248 }
249
250 /* 
251  * Alsa section
252  * PCM settings and callbacks
253  */
254 static int snd_omap_alsa_trigger(struct snd_pcm_substream * substream, int cmd)
255 {
256         struct snd_card_omap_codec *chip =
257             snd_pcm_substream_chip(substream);
258         int stream_id = substream->pstr->stream;
259         struct audio_stream *s = &chip->s[stream_id];
260         int err = 0;
261         
262         ADEBUG();
263         /* note local interrupts are already disabled in the midlevel code */
264         spin_lock(&s->dma_lock);
265         switch (cmd) {
266         case SNDRV_PCM_TRIGGER_START:
267                 /* requested stream startup */
268                 s->active = 1;
269                 audio_process_dma(s);
270                 break;
271         case SNDRV_PCM_TRIGGER_STOP:
272                 /* requested stream shutdown */
273                 audio_stop_dma(s);
274                 break;
275         default:
276                 err = -EINVAL;
277                 break;
278         }
279         spin_unlock(&s->dma_lock);
280         
281         return err;
282 }
283
284 static int snd_omap_alsa_prepare(struct snd_pcm_substream * substream)
285 {
286         struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
287         struct snd_pcm_runtime *runtime = substream->runtime;
288         struct audio_stream *s = &chip->s[substream->pstr->stream];
289         
290         ADEBUG();
291         /* set requested samplerate */
292         alsa_codec_config->codec_set_samplerate(runtime->rate);
293         chip->samplerate = runtime->rate;
294
295         s->period = 0;
296         s->periods = 0;
297
298         return 0;
299 }
300
301 static snd_pcm_uframes_t snd_omap_alsa_pointer(struct snd_pcm_substream *substream)
302 {
303         struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
304
305         ADEBUG();       
306         return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
307 }
308
309 static int snd_card_omap_alsa_open(struct snd_pcm_substream * substream)
310 {
311         struct snd_card_omap_codec *chip =
312             snd_pcm_substream_chip(substream);
313         struct snd_pcm_runtime *runtime = substream->runtime;
314         int stream_id = substream->pstr->stream;
315         int err;
316         
317         ADEBUG();
318         chip->s[stream_id].stream = substream;
319         alsa_codec_config->codec_clock_on();
320         if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) 
321                 runtime->hw = *(alsa_codec_config->snd_omap_alsa_playback);
322         else 
323                 runtime->hw = *(alsa_codec_config->snd_omap_alsa_capture);
324         
325         if ((err = snd_pcm_hw_constraint_integer(runtime,
326                                            SNDRV_PCM_HW_PARAM_PERIODS)) < 0) 
327                 return err;
328         
329         if ((err = snd_pcm_hw_constraint_list(runtime,
330                                         0,
331                                         SNDRV_PCM_HW_PARAM_RATE,
332                                         alsa_codec_config->hw_constraints_rates)) < 0) 
333                 return err;
334         
335         return 0;
336 }
337
338 static int snd_card_omap_alsa_close(struct snd_pcm_substream * substream)
339 {
340         struct snd_card_omap_codec *chip = snd_pcm_substream_chip(substream);
341         
342         ADEBUG();
343         alsa_codec_config->codec_clock_off();
344         chip->s[substream->pstr->stream].stream = NULL;
345         
346         return 0;
347 }
348
349 /* HW params & free */
350 static int snd_omap_alsa_hw_params(struct snd_pcm_substream * substream,
351                                    struct snd_pcm_hw_params * hw_params)
352 {
353         return snd_pcm_lib_malloc_pages(substream,
354                                         params_buffer_bytes(hw_params));
355 }
356
357 static int snd_omap_alsa_hw_free(struct snd_pcm_substream * substream)
358 {
359         return snd_pcm_lib_free_pages(substream);
360 }
361
362 /* pcm operations */
363 static struct snd_pcm_ops snd_card_omap_alsa_playback_ops = {
364         .open =         snd_card_omap_alsa_open,
365         .close =        snd_card_omap_alsa_close,
366         .ioctl =        snd_pcm_lib_ioctl,
367         .hw_params =    snd_omap_alsa_hw_params,
368         .hw_free =      snd_omap_alsa_hw_free,
369         .prepare =      snd_omap_alsa_prepare,
370         .trigger =      snd_omap_alsa_trigger,
371         .pointer =      snd_omap_alsa_pointer,
372 };
373
374 static struct snd_pcm_ops snd_card_omap_alsa_capture_ops = {
375         .open =         snd_card_omap_alsa_open,
376         .close =        snd_card_omap_alsa_close,
377         .ioctl =        snd_pcm_lib_ioctl,
378         .hw_params =    snd_omap_alsa_hw_params,
379         .hw_free =      snd_omap_alsa_hw_free,
380         .prepare =      snd_omap_alsa_prepare,
381         .trigger =      snd_omap_alsa_trigger,
382         .pointer =      snd_omap_alsa_pointer,
383 };
384
385 /*
386  *  Alsa init and exit section
387  *  
388  *  Inits pcm alsa structures, allocate the alsa buffer, suspend, resume
389  */
390 static int __init snd_card_omap_alsa_pcm(struct snd_card_omap_codec *omap_alsa, 
391                                         int device)
392 {
393         struct snd_pcm *pcm;
394         int err;
395         
396         ADEBUG();
397         if ((err = snd_pcm_new(omap_alsa->card, "OMAP PCM", device, 1, 1, &pcm)) < 0)
398                 return err;
399
400         /* sets up initial buffer with continuous allocation */
401         snd_pcm_lib_preallocate_pages_for_all(pcm,
402                                               SNDRV_DMA_TYPE_CONTINUOUS,
403                                               snd_dma_continuous_data
404                                               (GFP_KERNEL),
405                                               128 * 1024, 128 * 1024);
406
407         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
408                         &snd_card_omap_alsa_playback_ops);
409         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
410                         &snd_card_omap_alsa_capture_ops);
411         pcm->private_data = omap_alsa;
412         pcm->info_flags = 0;
413         strcpy(pcm->name, "omap alsa pcm");
414
415         omap_alsa_audio_init(omap_alsa);
416
417         /* setup DMA controller */
418         audio_dma_request(&omap_alsa->s[SNDRV_PCM_STREAM_PLAYBACK],
419                           callback_omap_alsa_sound_dma);
420         audio_dma_request(&omap_alsa->s[SNDRV_PCM_STREAM_CAPTURE],
421                           callback_omap_alsa_sound_dma);
422
423         omap_alsa->pcm = pcm;
424
425         return 0;
426 }
427
428
429 #ifdef CONFIG_PM
430 /*
431  * Driver suspend/resume - calls alsa functions. Some hints from aaci.c
432  */
433 int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state)
434 {
435         struct snd_card_omap_codec *chip;
436         struct snd_card *card = platform_get_drvdata(pdev);
437         
438         if (card->power_state != SNDRV_CTL_POWER_D3hot) {
439                 chip = card->private_data;
440                 if (chip->card->power_state != SNDRV_CTL_POWER_D3hot) {
441                         snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
442                         snd_pcm_suspend_all(chip->pcm);
443                         /* Mutes and turn clock off */
444                         alsa_codec_config->codec_clock_off();
445                         snd_omap_suspend_mixer();
446                 }
447         }
448         return 0;
449 }
450
451 int snd_omap_alsa_resume(struct platform_device *pdev)
452 {
453         struct snd_card_omap_codec *chip;
454         struct snd_card *card = platform_get_drvdata(pdev);
455
456         if (card->power_state != SNDRV_CTL_POWER_D0) {                          
457                 chip = card->private_data;
458                 if (chip->card->power_state != SNDRV_CTL_POWER_D0) {
459                         snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
460                         alsa_codec_config->codec_clock_on();
461                         snd_omap_resume_mixer();
462                 }
463         }
464         return 0;
465 }
466
467 #endif  /* CONFIG_PM */
468
469 void snd_omap_alsa_free(struct snd_card * card)
470 {
471         struct snd_card_omap_codec *chip = card->private_data;
472         ADEBUG();
473         
474         /*
475          * Turn off codec after it is done.
476          * Can't do it immediately, since it may still have
477          * buffered data.
478          */
479         schedule_timeout_interruptible(2);
480
481         omap_mcbsp_stop(AUDIO_MCBSP);
482         omap_mcbsp_free(AUDIO_MCBSP);
483
484         audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
485         audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
486 }
487
488 /* module init & exit */
489
490 /* 
491  * Inits alsa soudcard structure.
492  * Called by the probe method in codec after function pointers has been set.
493  */
494 int snd_omap_alsa_post_probe(struct platform_device *pdev, struct omap_alsa_codec_config *config)
495 {
496         int err = 0;
497         int def_rate;
498         struct snd_card *card;
499         
500         ADEBUG();
501         alsa_codec_config       = config;
502
503         alsa_codec_config->codec_clock_setup();
504         alsa_codec_config->codec_clock_on(); 
505
506         omap_mcbsp_request(AUDIO_MCBSP);
507         omap_mcbsp_stop(AUDIO_MCBSP);
508         omap_mcbsp_config(AUDIO_MCBSP, alsa_codec_config->mcbsp_regs_alsa);
509         omap_mcbsp_start(AUDIO_MCBSP);
510         
511         if (alsa_codec_config && alsa_codec_config->codec_configure_dev)
512                 alsa_codec_config->codec_configure_dev();
513
514         alsa_codec_config->codec_clock_off();
515
516         /* register the soundcard */
517         card = snd_card_new(-1, id, THIS_MODULE, sizeof(alsa_codec));
518         if (card == NULL)
519                 goto nodev1;
520
521         alsa_codec = kcalloc(1, sizeof(*alsa_codec), GFP_KERNEL);
522         if (alsa_codec == NULL)
523                 goto nodev2;
524
525         card->private_data = (void *)alsa_codec;
526         card->private_free = snd_omap_alsa_free;
527
528         alsa_codec->card        = card;
529         def_rate                = alsa_codec_config->get_default_samplerate(); 
530         alsa_codec->samplerate  = def_rate;
531
532         spin_lock_init(&alsa_codec->s[0].dma_lock);
533         spin_lock_init(&alsa_codec->s[1].dma_lock);
534
535         /* mixer */
536         if ((err = snd_omap_mixer(alsa_codec)) < 0)
537                 goto nodev3;
538
539         /* PCM */
540         if ((err = snd_card_omap_alsa_pcm(alsa_codec, 0)) < 0)
541                 goto nodev3;
542
543         strcpy(card->driver, "OMAP_ALSA");
544         strcpy(card->shortname, alsa_codec_config->name);
545         sprintf(card->longname, alsa_codec_config->name);
546
547         snd_omap_init_mixer();
548         snd_card_set_dev(card, &pdev->dev);
549         
550         if ((err = snd_card_register(card)) == 0) {
551                 printk(KERN_INFO "audio support initialized\n");
552                 platform_set_drvdata(pdev, card);
553                 return 0;
554         }
555         
556 nodev3:
557         kfree(alsa_codec);      
558 nodev2: 
559         snd_card_free(card);
560 nodev1:
561         omap_mcbsp_stop(AUDIO_MCBSP);
562         omap_mcbsp_free(AUDIO_MCBSP);
563
564         return err;
565 }
566
567 int snd_omap_alsa_remove(struct platform_device *pdev)
568 {
569         struct snd_card *card = platform_get_drvdata(pdev);
570         struct snd_card_omap_codec *chip = card->private_data;
571         
572         snd_card_free(card);
573
574         alsa_codec = NULL;
575         card->private_data = NULL;
576         kfree(chip);
577         
578         platform_set_drvdata(pdev, NULL);
579         
580         return 0;
581 }