]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/arm/omap-aic23.c
69cc64a63a32feae95dbcd8234f9552a25790337
[linux-2.6-omap-h63xx.git] / sound / arm / omap-aic23.c
1 /*
2  * sound/arm/omap-aic23.c
3  * 
4  * Alsa Driver for AIC23 codec on OSK5912 platform board
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  * Based on sa11xx-uda1341.c, 
11  * Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the
15  * Free Software Foundation; either version 2 of the License, or (at your
16  * option) any later version.
17  *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * You should have received a copy of the  GNU General Public License along
30  * with this program; if not, write  to the Free Software Foundation, Inc.,
31  * 675 Mass Ave, Cambridge, MA 02139, USA.
32  *
33  * History:
34  *
35  * 2005-07-29   INdT Kernel Team - Alsa driver for omap osk. Creation of new 
36  *                                 file omap-aic23.c
37  *
38  * 2005-12-18   Dirk Behme      - Added L/R Channel Interchange fix as proposed by Ajaya Babu
39  */
40
41 #include <linux/config.h>
42 #include <sound/driver.h>
43 #include <linux/module.h>
44 #include <linux/platform_device.h>
45 #include <linux/moduleparam.h>
46 #include <linux/init.h>
47 #include <linux/errno.h>
48 #include <linux/ioctl.h>
49 #include <linux/delay.h>
50 #include <linux/slab.h>
51 #include <linux/clk.h>
52
53 #ifdef CONFIG_PM
54 #include <linux/pm.h>
55 #endif
56
57 #include <asm/hardware.h>
58 #include <asm/mach-types.h>
59 #include <asm/arch/dma.h>
60 #include <asm/arch/aic23.h>
61 #include <asm/arch/mcbsp.h>
62 #include <asm/arch/clock.h>
63
64 #include <sound/core.h>
65 #include <sound/pcm.h>
66 #include <sound/initval.h>
67 #include <sound/memalloc.h>
68
69 #include "omap-alsa-dma.h"
70 #include "omap-aic23.h"
71
72 #undef DEBUG
73
74 #ifdef DEBUG
75 #define ADEBUG() printk("XXX Alsa debug f:%s, l:%d\n", __FUNCTION__, __LINE__)
76 #else
77 #define ADEBUG()                /* nop */
78 #endif
79
80 /* Define to set the AIC23 as the master w.r.t McBSP */
81 #define AIC23_MASTER
82
83 /*
84  * AUDIO related MACROS
85  */
86 #define DEFAULT_BITPERSAMPLE          16
87 #define AUDIO_RATE_DEFAULT            44100
88 #define AUDIO_MCBSP                   OMAP_MCBSP1
89 #define NUMBER_SAMPLE_RATES_SUPPORTED 10
90
91
92 MODULE_AUTHOR("Daniel Petrini, David Cohen, Anderson Briglia - INdT");
93 MODULE_LICENSE("GPL");
94 MODULE_DESCRIPTION("OMAP AIC23 driver for ALSA");
95 MODULE_SUPPORTED_DEVICE("{{AIC23,OMAP AIC23}}");
96 MODULE_ALIAS("omap_mcbsp.1");
97
98 static char *id = NULL; 
99 MODULE_PARM_DESC(id, "OMAP OSK ALSA Driver for AIC23 chip.");
100
101 static struct snd_card_omap_codec *omap_aic23 = NULL;
102
103 static struct clk *aic23_mclk = 0;
104
105 struct sample_rate_rate_reg_info {
106         u8 control;             /* SR3, SR2, SR1, SR0 and BOSR */
107         u8 divider;             /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
108 };
109
110 /*
111  * DAC USB-mode sampling rates (MCLK = 12 MHz)
112  * The rates and rate_reg_into MUST be in the same order
113  */
114 static unsigned int rates[] = {
115         4000, 8000, 16000, 22050,
116         24000, 32000, 44100,
117         48000, 88200, 96000,
118 };
119 static const struct sample_rate_rate_reg_info
120  rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
121         {0x06, 1},              /*  4000 */
122         {0x06, 0},              /*  8000 */
123         {0x0C, 1},              /* 16000 */
124         {0x11, 1},              /* 22050 */
125         {0x00, 1},              /* 24000 */
126         {0x0C, 0},              /* 32000 */
127         {0x11, 0},              /* 44100 */
128         {0x00, 0},              /* 48000 */
129         {0x1F, 0},              /* 88200 */
130         {0x0E, 0},              /* 96000 */
131 };
132
133 /*
134  *  mcbsp configuration structure
135  */
136 static struct omap_mcbsp_reg_cfg initial_config_mcbsp = {
137         .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
138         .spcr1 = RINTM(3) | RRST,
139         .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
140             RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
141         .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
142         .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
143             XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
144         .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
145         .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
146         .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
147 #ifndef AIC23_MASTER
148         /* configure McBSP to be the I2S master */
149         .pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
150 #else
151         /* configure McBSP to be the I2S slave */
152         .pcr0 = CLKXP | CLKRP,
153 #endif                          /* AIC23_MASTER */
154 };
155
156 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
157         .count = ARRAY_SIZE(rates),
158         .list = rates,
159         .mask = 0,
160 };
161
162 /*
163  * HW interface start and stop helper functions
164  */
165 static int audio_ifc_start(void)
166 {
167         omap_mcbsp_start(AUDIO_MCBSP);
168         return 0;
169 }
170
171 static int audio_ifc_stop(void)
172 {
173         omap_mcbsp_stop(AUDIO_MCBSP);
174         return 0;
175 }
176
177 /*
178  * Codec/mcbsp init and configuration section
179  * codec dependent code.
180  */
181
182 /*
183  * Sample rate changing
184  */
185 static void omap_aic23_set_samplerate(struct snd_card_omap_codec
186                                       *omap_aic23, long rate)
187 {
188         u8 count = 0;
189         u16 data = 0;
190
191         /* Fix the rate if it has a wrong value */
192         if (rate >= 96000)
193                 rate = 96000;
194         else if (rate >= 88200)
195                 rate = 88200;
196         else if (rate >= 48000)
197                 rate = 48000;
198         else if (rate >= 44100)
199                 rate = 44100;
200         else if (rate >= 32000)
201                 rate = 32000;
202         else if (rate >= 24000)
203                 rate = 24000;
204         else if (rate >= 22050)
205                 rate = 22050;
206         else if (rate >= 16000)
207                 rate = 16000;
208         else if (rate >= 8000)
209                 rate = 8000;
210         else
211                 rate = 4000;
212
213         /* Search for the right sample rate */
214         /* Verify what happens if the rate is not supported
215          * now it goes to 96Khz */
216         while ((rates[count] != rate) &&
217                (count < (NUMBER_SAMPLE_RATES_SUPPORTED - 1))) {
218                 count++;
219         }
220
221         data = (rate_reg_info[count].divider << CLKIN_SHIFT) |
222             (rate_reg_info[count].control << BOSR_SHIFT) | USB_CLK_ON;
223
224         audio_aic23_write(SAMPLE_RATE_CONTROL_ADDR, data);
225
226         omap_aic23->samplerate = rate;
227 }
228
229 static inline void aic23_configure(void)
230 {
231         /* Reset codec */
232         audio_aic23_write(RESET_CONTROL_ADDR, 0);
233
234         /* Initialize the AIC23 internal state */
235
236         /* Analog audio path control, DAC selected, delete INSEL_MIC for line in */
237         audio_aic23_write(ANALOG_AUDIO_CONTROL_ADDR, DEFAULT_ANALOG_AUDIO_CONTROL);
238
239         /* Digital audio path control, de-emphasis control 44.1kHz */
240         audio_aic23_write(DIGITAL_AUDIO_CONTROL_ADDR, DEEMP_44K);
241
242         /* Digital audio interface, master/slave mode, I2S, 16 bit */
243 #ifdef AIC23_MASTER
244         audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR,
245                           MS_MASTER | IWL_16 | FOR_DSP);
246 #else
247         audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, IWL_16 | FOR_DSP);
248 #endif
249
250         /* Enable digital interface */
251         audio_aic23_write(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
252
253 }
254
255 static void omap_aic23_audio_init(struct snd_card_omap_codec *omap_aic23)
256 {
257         /* Setup DMA stuff */
258         omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK].id = "Alsa AIC23 out";
259         omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id =
260             SNDRV_PCM_STREAM_PLAYBACK;
261         omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev =
262             OMAP_DMA_MCBSP1_TX;
263         omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK].hw_start =
264             audio_ifc_start;
265         omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK].hw_stop =
266             audio_ifc_stop;
267
268         omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE].id = "Alsa AIC23 in";
269         omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE].stream_id =
270             SNDRV_PCM_STREAM_CAPTURE;
271         omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev =
272             OMAP_DMA_MCBSP1_RX;
273         omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE].hw_start =
274             audio_ifc_start;
275         omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE].hw_stop =
276             audio_ifc_stop;
277
278         /* configuring the McBSP */
279         omap_mcbsp_request(AUDIO_MCBSP);
280
281         /* if configured, then stop mcbsp */
282         omap_mcbsp_stop(AUDIO_MCBSP);
283
284         omap_mcbsp_config(AUDIO_MCBSP, &initial_config_mcbsp);
285         omap_mcbsp_start(AUDIO_MCBSP);
286         aic23_configure();
287 }
288
289 /* 
290  * DMA functions 
291  * Depends on omap-aic23-dma.c functions and (omap) dma.c
292  * 
293  */
294 #define DMA_BUF_SIZE    1024 * 8
295
296 static int audio_dma_request(struct audio_stream *s,
297                              void (*callback) (void *))
298 {
299         int err;
300
301         err = omap_request_alsa_sound_dma(s->dma_dev, s->id, s, &s->lch);
302         if (err < 0)
303                 printk(KERN_ERR "unable to grab audio dma 0x%x\n",
304                        s->dma_dev);
305         return err;
306 }
307
308 static int audio_dma_free(struct audio_stream *s)
309 {
310         int err = 0;
311
312         err = omap_free_alsa_sound_dma(s, &s->lch);
313         if (err < 0)
314                 printk(KERN_ERR "Unable to free audio dma channels!\n");
315         return err;
316 }
317
318 /*
319  *  This function should calculate the current position of the dma in the
320  *  buffer. It will help alsa middle layer to continue update the buffer.
321  *  Its correctness is crucial for good functioning.
322  */
323 static u_int audio_get_dma_pos(struct audio_stream *s)
324 {
325         snd_pcm_substream_t *substream = s->stream;
326         snd_pcm_runtime_t *runtime = substream->runtime;
327         unsigned int offset;
328         unsigned long flags;
329         dma_addr_t count;
330         ADEBUG();
331
332         /* this must be called w/ interrupts locked as requested in dma.c */
333         spin_lock_irqsave(&s->dma_lock, flags);
334
335         /* For the current period let's see where we are */
336         count = omap_get_dma_src_addr_counter(s->lch[s->dma_q_head]);
337
338         spin_unlock_irqrestore(&s->dma_lock, flags);
339
340         /* Now, the position related to the end of that period */
341         offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
342
343         if (offset >= runtime->buffer_size || offset < 0)
344                 offset = 0;
345
346         return offset;
347 }
348
349 /*
350  * this stops the dma and clears the dma ptrs
351  */
352 static void audio_stop_dma(struct audio_stream *s)
353 {
354         unsigned long flags;
355         ADEBUG();
356
357         spin_lock_irqsave(&s->dma_lock, flags);
358         s->active = 0;
359         s->period = 0;
360         s->periods = 0;
361
362         /* this stops the dma channel and clears the buffer ptrs */
363         /* this stops the dma channel and clears the buffer ptrs */
364         omap_stop_alsa_sound_dma(s);
365
366         omap_clear_alsa_sound_dma(s);
367
368         spin_unlock_irqrestore(&s->dma_lock, flags);
369 }
370
371 /*
372  *  Main dma routine, requests dma according where you are in main alsa buffer
373  */
374 static void audio_process_dma(struct audio_stream *s)
375 {
376         snd_pcm_substream_t *substream = s->stream;
377         snd_pcm_runtime_t *runtime;
378         unsigned int dma_size;
379         unsigned int offset;
380         int ret;
381
382         runtime = substream->runtime;
383         if (s->active) {
384                 dma_size = frames_to_bytes(runtime, runtime->period_size);
385                 offset = dma_size * s->period;
386                 snd_assert(dma_size <= DMA_BUF_SIZE,);
387                 ret = omap_start_alsa_sound_dma(s,
388                                          (dma_addr_t) runtime->dma_area +
389                                          offset, dma_size);
390                 if (ret) {
391                         printk(KERN_ERR
392                                "audio_process_dma: cannot queue DMA buffer (%i)\n",
393                                ret);
394                         return;
395                 }
396
397                 s->period++;
398                 s->period %= runtime->periods;
399                 s->periods++;
400                 s->offset = offset;
401         }
402 }
403
404 /* 
405  *  This is called when dma IRQ occurs at the end of each transmited block
406  */
407 void callback_omap_alsa_sound_dma(void *data)
408 {
409         struct audio_stream *s = data;
410
411         /* 
412          * If we are getting a callback for an active stream then we inform
413          * the PCM middle layer we've finished a period
414          */
415         if (s->active)
416                 snd_pcm_period_elapsed(s->stream);
417
418         spin_lock(&s->dma_lock);
419         if (s->periods > 0) {
420                 s->periods--;
421         }
422         audio_process_dma(s);
423         spin_unlock(&s->dma_lock);
424 }
425
426
427 /* 
428  * Alsa section
429  * PCM settings and callbacks
430  */
431
432 static int snd_omap_alsa_trigger(snd_pcm_substream_t * substream, int cmd)
433 {
434         struct snd_card_omap_codec *chip =
435             snd_pcm_substream_chip(substream);
436         int stream_id = substream->pstr->stream;
437         struct audio_stream *s = &chip->s[stream_id];
438         int err = 0;
439         ADEBUG();
440
441         /* note local interrupts are already disabled in the midlevel code */
442         spin_lock(&s->dma_lock);
443         switch (cmd) {
444         case SNDRV_PCM_TRIGGER_START:
445                 /* requested stream startup */
446                 s->active = 1;
447                 audio_process_dma(s);
448                 break;
449         case SNDRV_PCM_TRIGGER_STOP:
450                 /* requested stream shutdown */
451                 audio_stop_dma(s);
452                 break;
453         default:
454                 err = -EINVAL;
455                 break;
456         }
457         spin_unlock(&s->dma_lock);
458         
459         return err;
460 }
461
462 static int snd_omap_alsa_prepare(snd_pcm_substream_t * substream)
463 {
464         struct snd_card_omap_codec *chip =
465             snd_pcm_substream_chip(substream);
466         snd_pcm_runtime_t *runtime = substream->runtime;
467         struct audio_stream *s = &chip->s[substream->pstr->stream];
468
469         /* set requested samplerate */
470         omap_aic23_set_samplerate(chip, runtime->rate);
471
472         s->period = 0;
473         s->periods = 0;
474
475         return 0;
476 }
477
478 static snd_pcm_uframes_t snd_omap_alsa_pointer(snd_pcm_substream_t *
479                                                 substream)
480 {
481         struct snd_card_omap_codec *chip =
482             snd_pcm_substream_chip(substream);
483         
484         return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
485 }
486
487 /* Hardware capabilities */
488
489 static snd_pcm_hardware_t snd_omap_alsa_capture = {
490         .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
491                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
492         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
493         .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
494                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
495                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
496                   SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
497                   SNDRV_PCM_RATE_KNOT),
498         .rate_min = 8000,
499         .rate_max = 96000,
500         .channels_min = 2,
501         .channels_max = 2,
502         .buffer_bytes_max = 128 * 1024,
503         .period_bytes_min = 32,
504         .period_bytes_max = 8 * 1024,
505         .periods_min = 16,
506         .periods_max = 255,
507         .fifo_size = 0,
508 };
509
510 static snd_pcm_hardware_t snd_omap_alsa_playback = {
511         .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
512                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),      
513         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
514         .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
515                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
516                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
517                   SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
518                   SNDRV_PCM_RATE_KNOT),
519         .rate_min = 8000,
520         .rate_max = 96000,
521         .channels_min = 2,
522         .channels_max = 2,
523         .buffer_bytes_max = 128 * 1024,
524         .period_bytes_min = 32,
525         .period_bytes_max = 8 * 1024,
526         .periods_min = 16,
527         .periods_max = 255,
528         .fifo_size = 0,
529 };
530
531 static int snd_card_omap_alsa_open(snd_pcm_substream_t * substream)
532 {
533         struct snd_card_omap_codec *chip =
534             snd_pcm_substream_chip(substream);
535         snd_pcm_runtime_t *runtime = substream->runtime;
536         int stream_id = substream->pstr->stream;
537         int err;
538         ADEBUG();
539
540         chip->s[stream_id].stream = substream;
541         
542         omap_aic23_clock_on();
543         
544         if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
545                 runtime->hw = snd_omap_alsa_playback;
546         else
547                 runtime->hw = snd_omap_alsa_capture;
548         if ((err =
549              snd_pcm_hw_constraint_integer(runtime,
550                                            SNDRV_PCM_HW_PARAM_PERIODS)) <
551             0)
552                 return err;
553         if ((err =
554              snd_pcm_hw_constraint_list(runtime, 0,
555                                         SNDRV_PCM_HW_PARAM_RATE,
556                                         &hw_constraints_rates)) < 0)
557                 return err;
558
559         return 0;
560 }
561
562 static int snd_card_omap_alsa_close(snd_pcm_substream_t * substream)
563 {
564         struct snd_card_omap_codec *chip =
565             snd_pcm_substream_chip(substream);
566         ADEBUG();
567         
568         omap_aic23_clock_off();
569         chip->s[substream->pstr->stream].stream = NULL;
570         
571         return 0;
572 }
573
574 /* HW params & free */
575
576 static int snd_omap_alsa_hw_params(snd_pcm_substream_t * substream,
577                                     snd_pcm_hw_params_t * hw_params)
578 {
579         return snd_pcm_lib_malloc_pages(substream,
580                                         params_buffer_bytes(hw_params));
581 }
582
583 static int snd_omap_alsa_hw_free(snd_pcm_substream_t * substream)
584 {
585         return snd_pcm_lib_free_pages(substream);
586 }
587
588 /* pcm operations */
589 static snd_pcm_ops_t snd_card_omap_alsa_playback_ops = {
590         .open =         snd_card_omap_alsa_open,
591         .close =        snd_card_omap_alsa_close,
592         .ioctl =        snd_pcm_lib_ioctl,
593         .hw_params =    snd_omap_alsa_hw_params,
594         .hw_free =      snd_omap_alsa_hw_free,
595         .prepare =      snd_omap_alsa_prepare,
596         .trigger =      snd_omap_alsa_trigger,
597         .pointer =      snd_omap_alsa_pointer,
598 };
599
600 static snd_pcm_ops_t snd_card_omap_alsa_capture_ops = {
601         .open =         snd_card_omap_alsa_open,
602         .close =        snd_card_omap_alsa_close,
603         .ioctl =        snd_pcm_lib_ioctl,
604         .hw_params =    snd_omap_alsa_hw_params,
605         .hw_free =      snd_omap_alsa_hw_free,
606         .prepare =      snd_omap_alsa_prepare,
607         .trigger =      snd_omap_alsa_trigger,
608         .pointer =      snd_omap_alsa_pointer,
609 };
610
611 /*
612  *  Alsa init and exit section
613  *  
614  *  Inits pcm alsa structures, allocate the alsa buffer, suspend, resume
615  */
616 static int __init snd_card_omap_alsa_pcm(struct snd_card_omap_codec *omap_alsa,
617                                         int device)
618 {
619         snd_pcm_t *pcm;
620         int err;
621         ADEBUG();
622
623         if ((err =
624              snd_pcm_new(omap_aic23->card, "AIC23 PCM", device, 1, 1,
625                          &pcm)) < 0)
626                 return err;
627
628         /* sets up initial buffer with continuous allocation */
629         snd_pcm_lib_preallocate_pages_for_all(pcm,
630                                               SNDRV_DMA_TYPE_CONTINUOUS,
631                                               snd_dma_continuous_data
632                                               (GFP_KERNEL),
633                                               128 * 1024, 128 * 1024);
634
635         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
636                         &snd_card_omap_alsa_playback_ops);
637         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
638                         &snd_card_omap_alsa_capture_ops);
639         pcm->private_data = omap_aic23;
640         pcm->info_flags = 0;
641         strcpy(pcm->name, "omap aic23 pcm");
642
643         omap_aic23_audio_init(omap_aic23);
644
645         /* setup DMA controller */
646         audio_dma_request(&omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK],
647                           callback_omap_alsa_sound_dma);
648         audio_dma_request(&omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE],
649                           callback_omap_alsa_sound_dma);
650
651         omap_aic23->pcm = pcm;
652
653         return 0;
654 }
655
656 #ifdef CONFIG_PM
657 /*
658  * Driver suspend/resume - calls alsa functions. Some hints from aaci.c
659  */
660 int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state)
661 {
662         struct snd_card_omap_codec *chip;
663         snd_card_t *card = platform_get_drvdata(pdev);
664         
665         if (card->power_state != SNDRV_CTL_POWER_D3hot) {
666                 chip = card->private_data;
667                 if (chip->card->power_state != SNDRV_CTL_POWER_D3hot) {
668                         snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
669                         snd_pcm_suspend_all(chip->pcm);
670                         /* Mutes and turn clock off */
671                         omap_aic23_clock_off();
672                         snd_omap_suspend_mixer();
673                 }
674         }
675         return 0;
676 }
677
678 int snd_omap_alsa_resume(struct platform_device *pdev)
679 {
680         struct snd_card_omap_codec *chip;
681         snd_card_t *card = platform_get_drvdata(pdev);
682
683         if (card->power_state != SNDRV_CTL_POWER_D0) {
684                 chip = card->private_data;
685                 if (chip->card->power_state != SNDRV_CTL_POWER_D0) {
686                         snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
687                         omap_aic23_clock_on();
688                         snd_omap_resume_mixer();
689                 }
690         }
691         return 0;
692 }
693
694 #else
695 #define snd_omap_alsa_suspend   NULL
696 #define snd_omap_alsa_resume    NULL
697 #endif  /* CONFIG_PM */
698
699 /* 
700  */
701 void snd_omap_alsa_free(snd_card_t * card)
702 {
703         struct snd_card_omap_codec *chip = card->private_data;
704         ADEBUG();
705         
706         /*
707          * Turn off codec after it is done.
708          * Can't do it immediately, since it may still have
709          * buffered data.
710          */
711         set_current_state(TASK_INTERRUPTIBLE);
712         schedule_timeout(2);
713
714         omap_mcbsp_stop(AUDIO_MCBSP);
715         omap_mcbsp_free(AUDIO_MCBSP);
716
717         audio_aic23_write(RESET_CONTROL_ADDR, 0);
718         audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 0xff);
719
720         audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
721         audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
722 }
723
724 /*
725  *  Omap MCBSP clock configuration
726  *  
727  *  Here we have some functions that allows clock to be enabled and
728  *   disabled only when needed. Besides doing clock configuration 
729  *   it allows turn on/turn off audio when necessary. 
730  */
731 #define CODEC_CLOCK                   12000000
732 #define AUDIO_RATE_DEFAULT            44100
733
734 /*
735  * Do clock framework mclk search
736  */
737 static __init void omap_aic23_clock_setup(void)
738 {
739         aic23_mclk = clk_get(0, "mclk");
740 }
741
742 /*
743  * Do some sanity check, set clock rate, starts it and
744  *  turn codec audio on 
745  */
746 int omap_aic23_clock_on(void)
747 {
748         if (clk_get_usecount(aic23_mclk) > 0) {
749                 /* MCLK is already in use */
750                 printk(KERN_WARNING
751                        "MCLK in use at %d Hz. We change it to %d Hz\n",
752                        (uint) clk_get_rate(aic23_mclk),
753                        CODEC_CLOCK);
754         }
755         
756         if (clk_set_rate(aic23_mclk, CODEC_CLOCK)) {
757                 printk(KERN_ERR
758                        "Cannot set MCLK for AIC23 CODEC\n");
759                 return -ECANCELED;
760         }
761
762         clk_enable(aic23_mclk);
763
764         printk(KERN_DEBUG
765                 "MCLK = %d [%d], usecount = %d\n",
766                (uint) clk_get_rate(aic23_mclk), CODEC_CLOCK,
767                clk_get_usecount(aic23_mclk));
768
769         /* Now turn the audio on */
770         audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 
771                           ~DEVICE_POWER_OFF & ~OUT_OFF & ~DAC_OFF &
772                           ~ADC_OFF & ~MIC_OFF & ~LINE_OFF);
773         
774         return 0;
775 }
776 /*
777  * Do some sanity check, turn clock off and then turn
778  *  codec audio off
779  */
780 int omap_aic23_clock_off(void)
781 {
782         if  (clk_get_usecount(aic23_mclk) > 0) { 
783                 if (clk_get_rate(aic23_mclk) != CODEC_CLOCK) {
784                         printk(KERN_WARNING
785                                "MCLK for audio should be %d Hz. But is %d Hz\n",
786                                (uint) clk_get_rate(aic23_mclk),
787                                CODEC_CLOCK);
788                 }
789
790                 clk_disable(aic23_mclk);
791         }
792         
793         audio_aic23_write(POWER_DOWN_CONTROL_ADDR,
794                           DEVICE_POWER_OFF | OUT_OFF | DAC_OFF |
795                           ADC_OFF | MIC_OFF | LINE_OFF);        
796         return 0;
797 }
798
799 /* module init & exit */
800
801 /* 
802  *  Inits alsa soudcard structure
803  */
804 static int __init snd_omap_alsa_aic23_probe(struct platform_device *pdev)
805 {
806         int err = 0;
807         snd_card_t *card;
808         ADEBUG();
809         
810         /* gets clock from clock framework */
811         omap_aic23_clock_setup();
812
813         /* register the soundcard */
814         card = snd_card_new(-1, id, THIS_MODULE, sizeof(omap_aic23));
815         if (card == NULL)
816                 return -ENOMEM;
817
818         omap_aic23 = kcalloc(1, sizeof(*omap_aic23), GFP_KERNEL);
819         if (omap_aic23 == NULL)
820                 return -ENOMEM;
821
822         card->private_data = (void *) omap_aic23;
823         card->private_free = snd_omap_alsa_free;
824
825         omap_aic23->card = card;
826         omap_aic23->samplerate = AUDIO_RATE_DEFAULT;
827
828         spin_lock_init(&omap_aic23->s[0].dma_lock);
829         spin_lock_init(&omap_aic23->s[1].dma_lock);
830
831         /* mixer */
832         if ((err = snd_omap_mixer(omap_aic23)) < 0) 
833                 goto nodev;
834
835         /* PCM */
836         if ((err = snd_card_omap_alsa_pcm(omap_aic23, 0)) < 0)
837                 goto nodev;
838
839         strcpy(card->driver, "AIC23");
840         strcpy(card->shortname, "OSK AIC23");
841         sprintf(card->longname, "OMAP OSK with AIC23");
842
843         snd_omap_init_mixer();
844
845         snd_card_set_dev(card, &pdev->dev);
846         
847         if ((err = snd_card_register(card)) == 0) {
848                 printk(KERN_INFO "OSK audio support initialized\n");
849                 platform_set_drvdata(pdev, card);
850                 return 0;
851         }
852         
853 nodev:
854         snd_card_free(card);
855         
856         return err;
857 }
858
859 static int snd_omap_alsa_remove(struct platform_device *pdev)
860 {
861         snd_card_t *card = platform_get_drvdata(pdev);
862         struct snd_card_omap_codec *chip = card->private_data;
863         
864         snd_card_free(card);
865
866         omap_aic23 = NULL;
867         card->private_data = NULL;
868         kfree(chip);
869         
870         platform_set_drvdata(pdev, NULL);
871         
872         return 0;
873         
874 }
875
876 static struct platform_driver omap_alsa_driver = {
877         .probe          = snd_omap_alsa_aic23_probe,
878         .remove         = snd_omap_alsa_remove,
879         .suspend        = snd_omap_alsa_suspend,
880         .resume         = snd_omap_alsa_resume,
881         .driver = {
882                 .name = "omap_mcbsp",
883         },
884 };
885
886 static int __init omap_alsa_aic23_init(void)
887 {
888         int err;
889         ADEBUG();
890
891         err = platform_driver_register(&omap_alsa_driver);
892
893         return err;
894 }
895
896 static void __exit omap_alsa_aic23_exit(void)
897 {
898         ADEBUG();
899         
900         platform_driver_unregister(&omap_alsa_driver);
901 }
902
903 module_init(omap_alsa_aic23_init);
904 module_exit(omap_alsa_aic23_exit);