]> nv-tegra.nvidia Code Review - linux-3.10.git/blob - sound/mips/au1x00.c
Merge git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.14+advapi-fix/
[linux-3.10.git] / sound / mips / au1x00.c
1 /*
2  * BRIEF MODULE DESCRIPTION
3  *  Driver for AMD Au1000 MIPS Processor, AC'97 Sound Port
4  *
5  * Copyright 2004 Cooper Street Innovations Inc.
6  * Author: Charles Eidsness     <charles@cooper-street.com>
7  *
8  *  This program is free software; you can redistribute  it and/or modify it
9  *  under  the terms of  the GNU General  Public License as published by the
10  *  Free Software Foundation;  either version 2 of the  License, or (at your
11  *  option) any later version.
12  *
13  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
14  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
15  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
16  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
17  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
19  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
21  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  *  You should have received a copy of the  GNU General Public License along
25  *  with this program; if not, write  to the Free Software Foundation, Inc.,
26  *  675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  * History:
29  *
30  * 2004-09-09 Charles Eidsness  -- Original verion -- based on
31  *                                sa11xx-uda1341.c ALSA driver and the
32  *                                au1000.c OSS driver.
33  * 2004-09-09 Matt Porter       -- Added support for ALSA 1.0.6
34  *
35  */
36
37 #include <linux/ioport.h>
38 #include <linux/interrupt.h>
39 #include <sound/driver.h>
40 #include <linux/init.h>
41 #include <linux/slab.h>
42 #include <linux/version.h>
43 #include <sound/core.h>
44 #include <sound/initval.h>
45 #include <sound/pcm.h>
46 #include <sound/ac97_codec.h>
47 #include <asm/mach-au1x00/au1000.h>
48 #include <asm/mach-au1x00/au1000_dma.h>
49
50 MODULE_AUTHOR("Charles Eidsness <charles@cooper-street.com>");
51 MODULE_DESCRIPTION("Au1000 AC'97 ALSA Driver");
52 MODULE_LICENSE("GPL");
53 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
54 MODULE_SUPPORTED_DEVICE("{{AMD,Au1000 AC'97}}");
55 #else
56 MODULE_CLASSES("{sound}");
57 MODULE_DEVICES("{{AMD,Au1000 AC'97}}");
58 #endif
59
60 #define PLAYBACK 0
61 #define CAPTURE 1
62 #define AC97_SLOT_3 0x01
63 #define AC97_SLOT_4 0x02
64 #define AC97_SLOT_6 0x08
65 #define AC97_CMD_IRQ 31
66 #define READ 0
67 #define WRITE 1
68 #define READ_WAIT 2
69 #define RW_DONE 3
70
71 DECLARE_WAIT_QUEUE_HEAD(ac97_command_wq);
72
73 typedef struct au1000_period au1000_period_t;
74 struct au1000_period
75 {
76         u32 start;
77         u32 relative_end;       /*realtive to start of buffer*/
78         au1000_period_t * next;
79 };
80
81 /*Au1000 AC97 Port Control Reisters*/
82 typedef struct au1000_ac97_reg au1000_ac97_reg_t;
83 struct au1000_ac97_reg {
84         u32 volatile config;
85         u32 volatile status;
86         u32 volatile data;
87         u32 volatile cmd;
88         u32 volatile cntrl;
89 };
90
91 typedef struct audio_stream audio_stream_t;
92 struct audio_stream {
93         snd_pcm_substream_t * substream;
94         int dma;
95         spinlock_t dma_lock;
96         au1000_period_t * buffer;
97         unsigned long period_size;
98 };
99
100 typedef struct snd_card_au1000 {
101         snd_card_t *card;
102         au1000_ac97_reg_t volatile *ac97_ioport;
103
104         struct resource *ac97_res_port;
105         spinlock_t ac97_lock;
106         ac97_t *ac97;
107
108         snd_pcm_t *pcm;
109         audio_stream_t *stream[2];      /* playback & capture */
110 } au1000_t;
111
112 static au1000_t *au1000 = NULL;
113
114 /*--------------------------- Local Functions --------------------------------*/
115 static void
116 au1000_set_ac97_xmit_slots(long xmit_slots)
117 {
118         u32 volatile ac97_config;
119
120         spin_lock(&au1000->ac97_lock);
121         ac97_config = au1000->ac97_ioport->config;
122         ac97_config = ac97_config & ~AC97C_XMIT_SLOTS_MASK;
123         ac97_config |= (xmit_slots << AC97C_XMIT_SLOTS_BIT);
124         au1000->ac97_ioport->config = ac97_config;
125         spin_unlock(&au1000->ac97_lock);
126 }
127
128 static void
129 au1000_set_ac97_recv_slots(long recv_slots)
130 {
131         u32 volatile ac97_config;
132
133         spin_lock(&au1000->ac97_lock);
134         ac97_config = au1000->ac97_ioport->config;
135         ac97_config = ac97_config & ~AC97C_RECV_SLOTS_MASK;
136         ac97_config |= (recv_slots << AC97C_RECV_SLOTS_BIT);
137         au1000->ac97_ioport->config = ac97_config;
138         spin_unlock(&au1000->ac97_lock);
139 }
140
141
142 static void
143 au1000_dma_stop(audio_stream_t *stream)
144 {
145         unsigned long   flags;
146         au1000_period_t * pointer;
147         au1000_period_t * pointer_next;
148
149         if (stream->buffer != NULL) {
150                 spin_lock_irqsave(&stream->dma_lock, flags);
151                 disable_dma(stream->dma);
152                 spin_unlock_irqrestore(&stream->dma_lock, flags);
153
154                 pointer = stream->buffer;
155                 pointer_next = stream->buffer->next;
156
157                 do {
158                         kfree(pointer);
159                         pointer = pointer_next;
160                         pointer_next = pointer->next;
161                 } while (pointer != stream->buffer);
162
163                 stream->buffer = NULL;
164         }
165 }
166
167 static void
168 au1000_dma_start(audio_stream_t *stream)
169 {
170         snd_pcm_substream_t *substream = stream->substream;
171         snd_pcm_runtime_t *runtime = substream->runtime;
172
173         unsigned long flags, dma_start;
174         int i;
175         au1000_period_t * pointer;
176
177         if (stream->buffer == NULL) {
178                 dma_start = virt_to_phys(runtime->dma_area);
179
180                 stream->period_size = frames_to_bytes(runtime,
181                         runtime->period_size);
182                 stream->buffer = kmalloc(sizeof(au1000_period_t), GFP_KERNEL);
183                 pointer = stream->buffer;
184                 for (i = 0 ; i < runtime->periods ; i++) {
185                         pointer->start = (u32)(dma_start +
186                                 (i * stream->period_size));
187                         pointer->relative_end = (u32)
188                                 (((i+1) * stream->period_size) - 0x1);
189                         if ( i < runtime->periods - 1) {
190                                 pointer->next = kmalloc(sizeof(au1000_period_t)
191                                         , GFP_KERNEL);
192                                 pointer = pointer->next;
193                         }
194                 }
195                 pointer->next = stream->buffer;
196
197                 spin_lock_irqsave(&stream->dma_lock, flags);
198                 init_dma(stream->dma);
199                 if (get_dma_active_buffer(stream->dma) == 0) {
200                         clear_dma_done0(stream->dma);
201                         set_dma_addr0(stream->dma, stream->buffer->start);
202                         set_dma_count0(stream->dma, stream->period_size >> 1);
203                         set_dma_addr1(stream->dma, stream->buffer->next->start);
204                         set_dma_count1(stream->dma, stream->period_size >> 1);
205                 } else {
206                         clear_dma_done1(stream->dma);
207                         set_dma_addr1(stream->dma, stream->buffer->start);
208                         set_dma_count1(stream->dma, stream->period_size >> 1);
209                         set_dma_addr0(stream->dma, stream->buffer->next->start);
210                         set_dma_count0(stream->dma, stream->period_size >> 1);
211                 }
212                 enable_dma_buffers(stream->dma);
213                 start_dma(stream->dma);
214                 spin_unlock_irqrestore(&stream->dma_lock, flags);
215         }
216 }
217
218 static irqreturn_t
219 au1000_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
220 {
221         audio_stream_t *stream = (audio_stream_t *) dev_id;
222         snd_pcm_substream_t *substream = stream->substream;
223
224         spin_lock(&stream->dma_lock);
225         switch (get_dma_buffer_done(stream->dma)) {
226         case DMA_D0:
227                 stream->buffer = stream->buffer->next;
228                 clear_dma_done0(stream->dma);
229                 set_dma_addr0(stream->dma, stream->buffer->next->start);
230                 set_dma_count0(stream->dma, stream->period_size >> 1);
231                 enable_dma_buffer0(stream->dma);
232                 break;
233         case DMA_D1:
234                 stream->buffer = stream->buffer->next;
235                 clear_dma_done1(stream->dma);
236                 set_dma_addr1(stream->dma, stream->buffer->next->start);
237                 set_dma_count1(stream->dma, stream->period_size >> 1);
238                 enable_dma_buffer1(stream->dma);
239                 break;
240         case (DMA_D0 | DMA_D1):
241                 spin_unlock(&stream->dma_lock);
242                 printk(KERN_ERR "DMA %d missed interrupt.\n",stream->dma);
243                 au1000_dma_stop(stream);
244                 au1000_dma_start(stream);
245                 spin_lock(&stream->dma_lock);
246                 break;
247         case (~DMA_D0 & ~DMA_D1):
248                 printk(KERN_ERR "DMA %d empty irq.\n",stream->dma);
249         }
250         spin_unlock(&stream->dma_lock);
251         snd_pcm_period_elapsed(substream);
252         return IRQ_HANDLED;
253 }
254
255 /*-------------------------- PCM Audio Streams -------------------------------*/
256
257 static unsigned int rates[] = {8000, 11025, 16000, 22050};
258 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
259         .count  =  sizeof(rates) / sizeof(rates[0]),
260         .list   = rates,
261         .mask   = 0,
262 };
263
264 static snd_pcm_hardware_t snd_au1000 =
265 {
266         .info                   = (SNDRV_PCM_INFO_INTERLEAVED | \
267                                 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
268         .formats                = SNDRV_PCM_FMTBIT_S16_LE,
269         .rates                  = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
270                                 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050),
271         .rate_min               = 8000,
272         .rate_max               = 22050,
273         .channels_min           = 1,
274         .channels_max           = 2,
275         .buffer_bytes_max       = 128*1024,
276         .period_bytes_min       = 32,
277         .period_bytes_max       = 16*1024,
278         .periods_min            = 8,
279         .periods_max            = 255,
280         .fifo_size              = 16,
281 };
282
283 static int
284 snd_au1000_playback_open(snd_pcm_substream_t * substream)
285 {
286         au1000->stream[PLAYBACK]->substream = substream;
287         au1000->stream[PLAYBACK]->buffer = NULL;
288         substream->private_data = au1000->stream[PLAYBACK];
289         substream->runtime->hw = snd_au1000;
290         return (snd_pcm_hw_constraint_list(substream->runtime, 0,
291                 SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
292 }
293
294 static int
295 snd_au1000_capture_open(snd_pcm_substream_t * substream)
296 {
297         au1000->stream[CAPTURE]->substream = substream;
298         au1000->stream[CAPTURE]->buffer = NULL;
299         substream->private_data = au1000->stream[CAPTURE];
300         substream->runtime->hw = snd_au1000;
301         return (snd_pcm_hw_constraint_list(substream->runtime, 0,
302                 SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
303
304 }
305
306 static int
307 snd_au1000_playback_close(snd_pcm_substream_t * substream)
308 {
309         au1000->stream[PLAYBACK]->substream = NULL;
310         return 0;
311 }
312
313 static int
314 snd_au1000_capture_close(snd_pcm_substream_t * substream)
315 {
316         au1000->stream[CAPTURE]->substream = NULL;
317         return 0;
318 }
319
320 static int
321 snd_au1000_hw_params(snd_pcm_substream_t * substream,
322                                         snd_pcm_hw_params_t * hw_params)
323 {
324         return snd_pcm_lib_malloc_pages(substream,
325                                         params_buffer_bytes(hw_params));
326 }
327
328 static int
329 snd_au1000_hw_free(snd_pcm_substream_t * substream)
330 {
331         return snd_pcm_lib_free_pages(substream);
332 }
333
334 static int
335 snd_au1000_playback_prepare(snd_pcm_substream_t * substream)
336 {
337         snd_pcm_runtime_t *runtime = substream->runtime;
338
339         if (runtime->channels == 1 )
340                 au1000_set_ac97_xmit_slots(AC97_SLOT_4);
341         else
342                 au1000_set_ac97_xmit_slots(AC97_SLOT_3 | AC97_SLOT_4);
343         snd_ac97_set_rate(au1000->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
344         return 0;
345 }
346
347 static int
348 snd_au1000_capture_prepare(snd_pcm_substream_t * substream)
349 {
350         snd_pcm_runtime_t *runtime = substream->runtime;
351
352         if (runtime->channels == 1 )
353                 au1000_set_ac97_recv_slots(AC97_SLOT_4);
354         else
355                 au1000_set_ac97_recv_slots(AC97_SLOT_3 | AC97_SLOT_4);
356         snd_ac97_set_rate(au1000->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
357         return 0;
358 }
359
360 static int
361 snd_au1000_trigger(snd_pcm_substream_t * substream, int cmd)
362 {
363         audio_stream_t *stream = substream->private_data;
364         int err = 0;
365
366         switch (cmd) {
367         case SNDRV_PCM_TRIGGER_START:
368                 au1000_dma_start(stream);
369                 break;
370         case SNDRV_PCM_TRIGGER_STOP:
371                 au1000_dma_stop(stream);
372                 break;
373         default:
374                 err = -EINVAL;
375                 break;
376         }
377         return err;
378 }
379
380 static snd_pcm_uframes_t
381 snd_au1000_pointer(snd_pcm_substream_t * substream)
382 {
383         audio_stream_t *stream = substream->private_data;
384         snd_pcm_runtime_t *runtime = substream->runtime;
385         unsigned long flags;
386         long location;
387
388         spin_lock_irqsave(&stream->dma_lock, flags);
389         location = get_dma_residue(stream->dma);
390         spin_unlock_irqrestore(&stream->dma_lock, flags);
391         location = stream->buffer->relative_end - location;
392         if (location == -1)
393                 location = 0;
394         return bytes_to_frames(runtime,location);
395 }
396
397 static snd_pcm_ops_t snd_card_au1000_playback_ops = {
398         .open                   = snd_au1000_playback_open,
399         .close                  = snd_au1000_playback_close,
400         .ioctl                  = snd_pcm_lib_ioctl,
401         .hw_params              = snd_au1000_hw_params,
402         .hw_free                = snd_au1000_hw_free,
403         .prepare                = snd_au1000_playback_prepare,
404         .trigger                = snd_au1000_trigger,
405         .pointer                = snd_au1000_pointer,
406 };
407
408 static snd_pcm_ops_t snd_card_au1000_capture_ops = {
409         .open                   = snd_au1000_capture_open,
410         .close                  = snd_au1000_capture_close,
411         .ioctl                  = snd_pcm_lib_ioctl,
412         .hw_params              = snd_au1000_hw_params,
413         .hw_free                = snd_au1000_hw_free,
414         .prepare                = snd_au1000_capture_prepare,
415         .trigger                = snd_au1000_trigger,
416         .pointer                = snd_au1000_pointer,
417 };
418
419 static int __devinit
420 snd_au1000_pcm_new(void)
421 {
422         snd_pcm_t *pcm;
423         int err;
424         unsigned long flags;
425
426         if ((err = snd_pcm_new(au1000->card, "AU1000 AC97 PCM", 0, 1, 1, &pcm)) < 0)
427                 return err;
428
429         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
430                 snd_dma_continuous_data(GFP_KERNEL), 128*1024, 128*1024);
431
432         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
433                 &snd_card_au1000_playback_ops);
434         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
435                 &snd_card_au1000_capture_ops);
436
437         pcm->private_data = au1000;
438         pcm->info_flags = 0;
439         strcpy(pcm->name, "Au1000 AC97 PCM");
440
441         flags = claim_dma_lock();
442         if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX,
443                         "AC97 TX", au1000_dma_interrupt, SA_INTERRUPT,
444                         au1000->stream[PLAYBACK])) < 0) {
445                 release_dma_lock(flags);
446                 return -EBUSY;
447         }
448         if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX,
449                         "AC97 RX", au1000_dma_interrupt, SA_INTERRUPT,
450                         au1000->stream[CAPTURE])) < 0){
451                 release_dma_lock(flags);
452                 return -EBUSY;
453         }
454         /* enable DMA coherency in read/write DMA channels */
455         set_dma_mode(au1000->stream[PLAYBACK]->dma,
456                      get_dma_mode(au1000->stream[PLAYBACK]->dma) & ~DMA_NC);
457         set_dma_mode(au1000->stream[CAPTURE]->dma,
458                      get_dma_mode(au1000->stream[CAPTURE]->dma) & ~DMA_NC);
459         release_dma_lock(flags);
460         spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock);
461         spin_lock_init(&au1000->stream[CAPTURE]->dma_lock);
462         au1000->pcm = pcm;
463         return 0;
464 }
465
466
467 /*-------------------------- AC97 CODEC Control ------------------------------*/
468
469 static unsigned short
470 snd_au1000_ac97_read(ac97_t *ac97, unsigned short reg)
471 {
472         u32 volatile cmd;
473         u16 volatile data;
474         int             i;
475         spin_lock(&au1000->ac97_lock);
476 /* would rather use the interupt than this polling but it works and I can't
477 get the interupt driven case to work efficiently */
478         for (i = 0; i < 0x5000; i++)
479                 if (!(au1000->ac97_ioport->status & AC97C_CP))
480                         break;
481         if (i == 0x5000)
482                 printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n");
483
484         cmd = (u32) reg & AC97C_INDEX_MASK;
485         cmd |= AC97C_READ;
486         au1000->ac97_ioport->cmd = cmd;
487
488         /* now wait for the data */
489         for (i = 0; i < 0x5000; i++)
490                 if (!(au1000->ac97_ioport->status & AC97C_CP))
491                         break;
492         if (i == 0x5000) {
493                 printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n");
494                 return 0;
495         }
496
497         data = au1000->ac97_ioport->cmd & 0xffff;
498         spin_unlock(&au1000->ac97_lock);
499
500         return data;
501
502 }
503
504
505 static void
506 snd_au1000_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
507 {
508         u32 cmd;
509         int i;
510         spin_lock(&au1000->ac97_lock);
511 /* would rather use the interupt than this polling but it works and I can't
512 get the interupt driven case to work efficiently */
513         for (i = 0; i < 0x5000; i++)
514                 if (!(au1000->ac97_ioport->status & AC97C_CP))
515                         break;
516         if (i == 0x5000)
517                 printk(KERN_ERR "au1000 AC97: AC97 command write timeout\n");
518
519         cmd = (u32) reg & AC97C_INDEX_MASK;
520         cmd &= ~AC97C_READ;
521         cmd |= ((u32) val << AC97C_WD_BIT);
522         au1000->ac97_ioport->cmd = cmd;
523         spin_unlock(&au1000->ac97_lock);
524 }
525 static void
526 snd_au1000_ac97_free(ac97_t *ac97)
527 {
528         au1000->ac97 = NULL;
529 }
530
531 static int __devinit
532 snd_au1000_ac97_new(void)
533 {
534         int err;
535
536 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
537         ac97_bus_t *pbus;
538         ac97_template_t ac97;
539         static ac97_bus_ops_t ops = {
540                 .write = snd_au1000_ac97_write,
541                 .read = snd_au1000_ac97_read,
542         };
543 #else
544         ac97_bus_t bus, *pbus;
545         ac97_t ac97;
546 #endif
547
548         if ((au1000->ac97_res_port = request_region(AC97C_CONFIG,
549                         sizeof(au1000_ac97_reg_t), "Au1x00 AC97")) == NULL) {
550                 snd_printk(KERN_ERR "ALSA AC97: can't grap AC97 port\n");
551                 return -EBUSY;
552         }
553         au1000->ac97_ioport = (au1000_ac97_reg_t *) au1000->ac97_res_port->start;
554
555         spin_lock_init(&au1000->ac97_lock);
556
557         spin_lock(&au1000->ac97_lock);
558
559         /* configure pins for AC'97
560         TODO: move to board_setup.c */
561         au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC);
562
563         /* Initialise Au1000's AC'97 Control Block */
564         au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE;
565         udelay(10);
566         au1000->ac97_ioport->cntrl = AC97C_CE;
567         udelay(10);
568
569         /* Initialise External CODEC -- cold reset */
570         au1000->ac97_ioport->config = AC97C_RESET;
571         udelay(10);
572         au1000->ac97_ioport->config = 0x0;
573         mdelay(5);
574
575         spin_unlock(&au1000->ac97_lock);
576
577         /* Initialise AC97 middle-layer */
578 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
579         if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0)
580                 return err;
581 #else
582         memset(&bus, 0, sizeof(bus));
583         bus.write = snd_au1000_ac97_write;
584         bus.read = snd_au1000_ac97_read;
585         if ((err = snd_ac97_bus(au1000->card, &bus, &pbus)) < 0)
586                 return err;
587 #endif
588         memset(&ac97, 0, sizeof(ac97));
589         ac97.private_data = au1000;
590         ac97.private_free = snd_au1000_ac97_free;
591         if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0)
592                 return err;
593         return 0;
594
595 }
596
597 /*------------------------------ Setup / Destroy ----------------------------*/
598
599 void
600 snd_au1000_free(snd_card_t *card)
601 {
602
603         if (au1000->ac97_res_port) {
604                 /* put internal AC97 block into reset */
605                 au1000->ac97_ioport->cntrl = AC97C_RS;
606                 au1000->ac97_ioport = NULL;
607                 release_and_free_resource(au1000->ac97_res_port);
608         }
609
610         if (au1000->stream[PLAYBACK]->dma >= 0)
611                 free_au1000_dma(au1000->stream[PLAYBACK]->dma);
612
613         if (au1000->stream[CAPTURE]->dma >= 0)
614                 free_au1000_dma(au1000->stream[CAPTURE]->dma);
615
616         kfree(au1000->stream[PLAYBACK]);
617         au1000->stream[PLAYBACK] = NULL;
618         kfree(au1000->stream[CAPTURE]);
619         au1000->stream[CAPTURE] = NULL;
620         kfree(au1000);
621         au1000 = NULL;
622
623 }
624
625 static int __init
626 au1000_init(void)
627 {
628         int err;
629
630         au1000 = kmalloc(sizeof(au1000_t), GFP_KERNEL);
631         if (au1000 == NULL)
632                 return -ENOMEM;
633         au1000->stream[PLAYBACK] = kmalloc(sizeof(audio_stream_t), GFP_KERNEL);
634         if (au1000->stream[PLAYBACK] == NULL)
635                 return -ENOMEM;
636         au1000->stream[CAPTURE] = kmalloc(sizeof(audio_stream_t), GFP_KERNEL);
637         if (au1000->stream[CAPTURE] == NULL)
638                 return -ENOMEM;
639         /* so that snd_au1000_free will work as intended */
640         au1000->stream[PLAYBACK]->dma = -1;
641         au1000->stream[CAPTURE]->dma = -1;
642         au1000->ac97_res_port = NULL;
643
644         au1000->card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(au1000_t));
645         if (au1000->card == NULL) {
646                 snd_au1000_free(au1000->card);
647                 return -ENOMEM;
648         }
649
650         au1000->card->private_data = (au1000_t *)au1000;
651         au1000->card->private_free = snd_au1000_free;
652
653         if ((err = snd_au1000_ac97_new()) < 0 ) {
654                 snd_card_free(au1000->card);
655                 return err;
656         }
657
658         if ((err = snd_au1000_pcm_new()) < 0) {
659                 snd_card_free(au1000->card);
660                 return err;
661         }
662
663         strcpy(au1000->card->driver, "AMD-Au1000-AC97");
664         strcpy(au1000->card->shortname, "Au1000-AC97");
665         sprintf(au1000->card->longname, "AMD Au1000--AC97 ALSA Driver");
666
667         if ((err = snd_card_set_generic_dev(au1000->card)) < 0) {
668                 snd_card_free(au1000->card);
669                 return err;
670         }
671
672         if ((err = snd_card_register(au1000->card)) < 0) {
673                 snd_card_free(au1000->card);
674                 return err;
675         }
676
677         printk( KERN_INFO "ALSA AC97: Driver Initialized\n" );
678         return 0;
679 }
680
681 static void __exit au1000_exit(void)
682 {
683         snd_card_free(au1000->card);
684 }
685
686 module_init(au1000_init);
687 module_exit(au1000_exit);
688