OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [mips/] [au1x00.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
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/pcm_params.h>
47
#include <sound/ac97_codec.h>
48
#include <asm/mach-au1x00/au1000.h>
49
#include <asm/mach-au1x00/au1000_dma.h>
50
 
51
MODULE_AUTHOR("Charles Eidsness <charles@cooper-street.com>");
52
MODULE_DESCRIPTION("Au1000 AC'97 ALSA Driver");
53
MODULE_LICENSE("GPL");
54
MODULE_SUPPORTED_DEVICE("{{AMD,Au1000 AC'97}}");
55
 
56
#define PLAYBACK 0
57
#define CAPTURE 1
58
#define AC97_SLOT_3 0x01
59
#define AC97_SLOT_4 0x02
60
#define AC97_SLOT_6 0x08
61
#define AC97_CMD_IRQ 31
62
#define READ 0
63
#define WRITE 1
64
#define READ_WAIT 2
65
#define RW_DONE 3
66
 
67
struct au1000_period
68
{
69
        u32 start;
70
        u32 relative_end;       /*realtive to start of buffer*/
71
        struct au1000_period * next;
72
};
73
 
74
/*Au1000 AC97 Port Control Reisters*/
75
struct au1000_ac97_reg {
76
        u32 volatile config;
77
        u32 volatile status;
78
        u32 volatile data;
79
        u32 volatile cmd;
80
        u32 volatile cntrl;
81
};
82
 
83
struct audio_stream {
84
        struct snd_pcm_substream *substream;
85
        int dma;
86
        spinlock_t dma_lock;
87
        struct au1000_period * buffer;
88
        unsigned int period_size;
89
        unsigned int periods;
90
};
91
 
92
struct snd_au1000 {
93
        struct snd_card *card;
94
        struct au1000_ac97_reg volatile *ac97_ioport;
95
 
96
        struct resource *ac97_res_port;
97
        spinlock_t ac97_lock;
98
        struct snd_ac97 *ac97;
99
 
100
        struct snd_pcm *pcm;
101
        struct audio_stream *stream[2]; /* playback & capture */
102
};
103
 
104
/*--------------------------- Local Functions --------------------------------*/
105
static void
106
au1000_set_ac97_xmit_slots(struct snd_au1000 *au1000, long xmit_slots)
107
{
108
        u32 volatile ac97_config;
109
 
110
        spin_lock(&au1000->ac97_lock);
111
        ac97_config = au1000->ac97_ioport->config;
112
        ac97_config = ac97_config & ~AC97C_XMIT_SLOTS_MASK;
113
        ac97_config |= (xmit_slots << AC97C_XMIT_SLOTS_BIT);
114
        au1000->ac97_ioport->config = ac97_config;
115
        spin_unlock(&au1000->ac97_lock);
116
}
117
 
118
static void
119
au1000_set_ac97_recv_slots(struct snd_au1000 *au1000, long recv_slots)
120
{
121
        u32 volatile ac97_config;
122
 
123
        spin_lock(&au1000->ac97_lock);
124
        ac97_config = au1000->ac97_ioport->config;
125
        ac97_config = ac97_config & ~AC97C_RECV_SLOTS_MASK;
126
        ac97_config |= (recv_slots << AC97C_RECV_SLOTS_BIT);
127
        au1000->ac97_ioport->config = ac97_config;
128
        spin_unlock(&au1000->ac97_lock);
129
}
130
 
131
 
132
static void
133
au1000_release_dma_link(struct audio_stream *stream)
134
{
135
        struct au1000_period * pointer;
136
        struct au1000_period * pointer_next;
137
 
138
        stream->period_size = 0;
139
        stream->periods = 0;
140
        pointer = stream->buffer;
141
        if (! pointer)
142
                return;
143
        do {
144
                pointer_next = pointer->next;
145
                kfree(pointer);
146
                pointer = pointer_next;
147
        } while (pointer != stream->buffer);
148
        stream->buffer = NULL;
149
}
150
 
151
static int
152
au1000_setup_dma_link(struct audio_stream *stream, unsigned int period_bytes,
153
                      unsigned int periods)
154
{
155
        struct snd_pcm_substream *substream = stream->substream;
156
        struct snd_pcm_runtime *runtime = substream->runtime;
157
        struct au1000_period *pointer;
158
        unsigned long dma_start;
159
        int i;
160
 
161
        dma_start = virt_to_phys(runtime->dma_area);
162
 
163
        if (stream->period_size == period_bytes &&
164
            stream->periods == periods)
165
                return 0; /* not changed */
166
 
167
        au1000_release_dma_link(stream);
168
 
169
        stream->period_size = period_bytes;
170
        stream->periods = periods;
171
 
172
        stream->buffer = kmalloc(sizeof(struct au1000_period), GFP_KERNEL);
173
        if (! stream->buffer)
174
                return -ENOMEM;
175
        pointer = stream->buffer;
176
        for (i = 0; i < periods; i++) {
177
                pointer->start = (u32)(dma_start + (i * period_bytes));
178
                pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1);
179
                if (i < periods - 1) {
180
                        pointer->next = kmalloc(sizeof(struct au1000_period), GFP_KERNEL);
181
                        if (! pointer->next) {
182
                                au1000_release_dma_link(stream);
183
                                return -ENOMEM;
184
                        }
185
                        pointer = pointer->next;
186
                }
187
        }
188
        pointer->next = stream->buffer;
189
        return 0;
190
}
191
 
192
static void
193
au1000_dma_stop(struct audio_stream *stream)
194
{
195
        snd_assert(stream->buffer, return);
196
        disable_dma(stream->dma);
197
}
198
 
199
static void
200
au1000_dma_start(struct audio_stream *stream)
201
{
202
        snd_assert(stream->buffer, return);
203
 
204
        init_dma(stream->dma);
205
        if (get_dma_active_buffer(stream->dma) == 0) {
206
                clear_dma_done0(stream->dma);
207
                set_dma_addr0(stream->dma, stream->buffer->start);
208
                set_dma_count0(stream->dma, stream->period_size >> 1);
209
                set_dma_addr1(stream->dma, stream->buffer->next->start);
210
                set_dma_count1(stream->dma, stream->period_size >> 1);
211
        } else {
212
                clear_dma_done1(stream->dma);
213
                set_dma_addr1(stream->dma, stream->buffer->start);
214
                set_dma_count1(stream->dma, stream->period_size >> 1);
215
                set_dma_addr0(stream->dma, stream->buffer->next->start);
216
                set_dma_count0(stream->dma, stream->period_size >> 1);
217
        }
218
        enable_dma_buffers(stream->dma);
219
        start_dma(stream->dma);
220
}
221
 
222
static irqreturn_t
223
au1000_dma_interrupt(int irq, void *dev_id)
224
{
225
        struct audio_stream *stream = (struct audio_stream *) dev_id;
226
        struct snd_pcm_substream *substream = stream->substream;
227
 
228
        spin_lock(&stream->dma_lock);
229
        switch (get_dma_buffer_done(stream->dma)) {
230
        case DMA_D0:
231
                stream->buffer = stream->buffer->next;
232
                clear_dma_done0(stream->dma);
233
                set_dma_addr0(stream->dma, stream->buffer->next->start);
234
                set_dma_count0(stream->dma, stream->period_size >> 1);
235
                enable_dma_buffer0(stream->dma);
236
                break;
237
        case DMA_D1:
238
                stream->buffer = stream->buffer->next;
239
                clear_dma_done1(stream->dma);
240
                set_dma_addr1(stream->dma, stream->buffer->next->start);
241
                set_dma_count1(stream->dma, stream->period_size >> 1);
242
                enable_dma_buffer1(stream->dma);
243
                break;
244
        case (DMA_D0 | DMA_D1):
245
                printk(KERN_ERR "DMA %d missed interrupt.\n",stream->dma);
246
                au1000_dma_stop(stream);
247
                au1000_dma_start(stream);
248
                break;
249
        case (~DMA_D0 & ~DMA_D1):
250
                printk(KERN_ERR "DMA %d empty irq.\n",stream->dma);
251
        }
252
        spin_unlock(&stream->dma_lock);
253
        snd_pcm_period_elapsed(substream);
254
        return IRQ_HANDLED;
255
}
256
 
257
/*-------------------------- PCM Audio Streams -------------------------------*/
258
 
259
static unsigned int rates[] = {8000, 11025, 16000, 22050};
260
static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
261
        .count  = ARRAY_SIZE(rates),
262
        .list   = rates,
263
        .mask   = 0,
264
};
265
 
266
static struct snd_pcm_hardware snd_au1000_hw =
267
{
268
        .info                   = (SNDRV_PCM_INFO_INTERLEAVED | \
269
                                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
270
        .formats                = SNDRV_PCM_FMTBIT_S16_LE,
271
        .rates                  = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
272
                                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050),
273
        .rate_min               = 8000,
274
        .rate_max               = 22050,
275
        .channels_min           = 1,
276
        .channels_max           = 2,
277
        .buffer_bytes_max       = 128*1024,
278
        .period_bytes_min       = 32,
279
        .period_bytes_max       = 16*1024,
280
        .periods_min            = 8,
281
        .periods_max            = 255,
282
        .fifo_size              = 16,
283
};
284
 
285
static int
286
snd_au1000_playback_open(struct snd_pcm_substream *substream)
287
{
288
        struct snd_au1000 *au1000 = substream->pcm->private_data;
289
 
290
        au1000->stream[PLAYBACK]->substream = substream;
291
        au1000->stream[PLAYBACK]->buffer = NULL;
292
        substream->private_data = au1000->stream[PLAYBACK];
293
        substream->runtime->hw = snd_au1000_hw;
294
        return (snd_pcm_hw_constraint_list(substream->runtime, 0,
295
                SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
296
}
297
 
298
static int
299
snd_au1000_capture_open(struct snd_pcm_substream *substream)
300
{
301
        struct snd_au1000 *au1000 = substream->pcm->private_data;
302
 
303
        au1000->stream[CAPTURE]->substream = substream;
304
        au1000->stream[CAPTURE]->buffer = NULL;
305
        substream->private_data = au1000->stream[CAPTURE];
306
        substream->runtime->hw = snd_au1000_hw;
307
        return (snd_pcm_hw_constraint_list(substream->runtime, 0,
308
                SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
309
}
310
 
311
static int
312
snd_au1000_playback_close(struct snd_pcm_substream *substream)
313
{
314
        struct snd_au1000 *au1000 = substream->pcm->private_data;
315
 
316
        au1000->stream[PLAYBACK]->substream = NULL;
317
        return 0;
318
}
319
 
320
static int
321
snd_au1000_capture_close(struct snd_pcm_substream *substream)
322
{
323
        struct snd_au1000 *au1000 = substream->pcm->private_data;
324
 
325
        au1000->stream[CAPTURE]->substream = NULL;
326
        return 0;
327
}
328
 
329
static int
330
snd_au1000_hw_params(struct snd_pcm_substream *substream,
331
                                        struct snd_pcm_hw_params *hw_params)
332
{
333
        struct audio_stream *stream = substream->private_data;
334
        int err;
335
 
336
        err = snd_pcm_lib_malloc_pages(substream,
337
                                       params_buffer_bytes(hw_params));
338
        if (err < 0)
339
                return err;
340
        return au1000_setup_dma_link(stream,
341
                                     params_period_bytes(hw_params),
342
                                     params_periods(hw_params));
343
}
344
 
345
static int
346
snd_au1000_hw_free(struct snd_pcm_substream *substream)
347
{
348
        struct audio_stream *stream = substream->private_data;
349
        au1000_release_dma_link(stream);
350
        return snd_pcm_lib_free_pages(substream);
351
}
352
 
353
static int
354
snd_au1000_playback_prepare(struct snd_pcm_substream *substream)
355
{
356
        struct snd_au1000 *au1000 = substream->pcm->private_data;
357
        struct snd_pcm_runtime *runtime = substream->runtime;
358
 
359
        if (runtime->channels == 1)
360
                au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_4);
361
        else
362
                au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4);
363
        snd_ac97_set_rate(au1000->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
364
        return 0;
365
}
366
 
367
static int
368
snd_au1000_capture_prepare(struct snd_pcm_substream *substream)
369
{
370
        struct snd_au1000 *au1000 = substream->pcm->private_data;
371
        struct snd_pcm_runtime *runtime = substream->runtime;
372
 
373
        if (runtime->channels == 1)
374
                au1000_set_ac97_recv_slots(au1000, AC97_SLOT_4);
375
        else
376
                au1000_set_ac97_recv_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4);
377
        snd_ac97_set_rate(au1000->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
378
        return 0;
379
}
380
 
381
static int
382
snd_au1000_trigger(struct snd_pcm_substream *substream, int cmd)
383
{
384
        struct audio_stream *stream = substream->private_data;
385
        int err = 0;
386
 
387
        spin_lock(&stream->dma_lock);
388
        switch (cmd) {
389
        case SNDRV_PCM_TRIGGER_START:
390
                au1000_dma_start(stream);
391
                break;
392
        case SNDRV_PCM_TRIGGER_STOP:
393
                au1000_dma_stop(stream);
394
                break;
395
        default:
396
                err = -EINVAL;
397
                break;
398
        }
399
        spin_unlock(&stream->dma_lock);
400
        return err;
401
}
402
 
403
static snd_pcm_uframes_t
404
snd_au1000_pointer(struct snd_pcm_substream *substream)
405
{
406
        struct audio_stream *stream = substream->private_data;
407
        struct snd_pcm_runtime *runtime = substream->runtime;
408
        long location;
409
 
410
        spin_lock(&stream->dma_lock);
411
        location = get_dma_residue(stream->dma);
412
        spin_unlock(&stream->dma_lock);
413
        location = stream->buffer->relative_end - location;
414
        if (location == -1)
415
                location = 0;
416
        return bytes_to_frames(runtime,location);
417
}
418
 
419
static struct snd_pcm_ops snd_card_au1000_playback_ops = {
420
        .open                   = snd_au1000_playback_open,
421
        .close                  = snd_au1000_playback_close,
422
        .ioctl                  = snd_pcm_lib_ioctl,
423
        .hw_params              = snd_au1000_hw_params,
424
        .hw_free                = snd_au1000_hw_free,
425
        .prepare                = snd_au1000_playback_prepare,
426
        .trigger                = snd_au1000_trigger,
427
        .pointer                = snd_au1000_pointer,
428
};
429
 
430
static struct snd_pcm_ops snd_card_au1000_capture_ops = {
431
        .open                   = snd_au1000_capture_open,
432
        .close                  = snd_au1000_capture_close,
433
        .ioctl                  = snd_pcm_lib_ioctl,
434
        .hw_params              = snd_au1000_hw_params,
435
        .hw_free                = snd_au1000_hw_free,
436
        .prepare                = snd_au1000_capture_prepare,
437
        .trigger                = snd_au1000_trigger,
438
        .pointer                = snd_au1000_pointer,
439
};
440
 
441
static int __devinit
442
snd_au1000_pcm_new(struct snd_au1000 *au1000)
443
{
444
        struct snd_pcm *pcm;
445
        int err;
446
        unsigned long flags;
447
 
448
        if ((err = snd_pcm_new(au1000->card, "AU1000 AC97 PCM", 0, 1, 1, &pcm)) < 0)
449
                return err;
450
 
451
        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
452
                snd_dma_continuous_data(GFP_KERNEL), 128*1024, 128*1024);
453
 
454
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
455
                &snd_card_au1000_playback_ops);
456
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
457
                &snd_card_au1000_capture_ops);
458
 
459
        pcm->private_data = au1000;
460
        pcm->info_flags = 0;
461
        strcpy(pcm->name, "Au1000 AC97 PCM");
462
 
463
        spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock);
464
        spin_lock_init(&au1000->stream[CAPTURE]->dma_lock);
465
 
466
        flags = claim_dma_lock();
467
        if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX,
468
                        "AC97 TX", au1000_dma_interrupt, IRQF_DISABLED,
469
                        au1000->stream[PLAYBACK])) < 0) {
470
                release_dma_lock(flags);
471
                return -EBUSY;
472
        }
473
        if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX,
474
                        "AC97 RX", au1000_dma_interrupt, IRQF_DISABLED,
475
                        au1000->stream[CAPTURE])) < 0){
476
                release_dma_lock(flags);
477
                return -EBUSY;
478
        }
479
        /* enable DMA coherency in read/write DMA channels */
480
        set_dma_mode(au1000->stream[PLAYBACK]->dma,
481
                     get_dma_mode(au1000->stream[PLAYBACK]->dma) & ~DMA_NC);
482
        set_dma_mode(au1000->stream[CAPTURE]->dma,
483
                     get_dma_mode(au1000->stream[CAPTURE]->dma) & ~DMA_NC);
484
        release_dma_lock(flags);
485
        au1000->pcm = pcm;
486
        return 0;
487
}
488
 
489
 
490
/*-------------------------- AC97 CODEC Control ------------------------------*/
491
 
492
static unsigned short
493
snd_au1000_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
494
{
495
        struct snd_au1000 *au1000 = ac97->private_data;
496
        u32 volatile cmd;
497
        u16 volatile data;
498
        int             i;
499
 
500
        spin_lock(&au1000->ac97_lock);
501
/* would rather use the interrupt than this polling but it works and I can't
502
get the interrupt driven case to work efficiently */
503
        for (i = 0; i < 0x5000; i++)
504
                if (!(au1000->ac97_ioport->status & AC97C_CP))
505
                        break;
506
        if (i == 0x5000)
507
                printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n");
508
 
509
        cmd = (u32) reg & AC97C_INDEX_MASK;
510
        cmd |= AC97C_READ;
511
        au1000->ac97_ioport->cmd = cmd;
512
 
513
        /* now wait for the data */
514
        for (i = 0; i < 0x5000; i++)
515
                if (!(au1000->ac97_ioport->status & AC97C_CP))
516
                        break;
517
        if (i == 0x5000) {
518
                printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n");
519
                return 0;
520
        }
521
 
522
        data = au1000->ac97_ioport->cmd & 0xffff;
523
        spin_unlock(&au1000->ac97_lock);
524
 
525
        return data;
526
 
527
}
528
 
529
 
530
static void
531
snd_au1000_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
532
{
533
        struct snd_au1000 *au1000 = ac97->private_data;
534
        u32 cmd;
535
        int i;
536
 
537
        spin_lock(&au1000->ac97_lock);
538
/* would rather use the interrupt than this polling but it works and I can't
539
get the interrupt driven case to work efficiently */
540
        for (i = 0; i < 0x5000; i++)
541
                if (!(au1000->ac97_ioport->status & AC97C_CP))
542
                        break;
543
        if (i == 0x5000)
544
                printk(KERN_ERR "au1000 AC97: AC97 command write timeout\n");
545
 
546
        cmd = (u32) reg & AC97C_INDEX_MASK;
547
        cmd &= ~AC97C_READ;
548
        cmd |= ((u32) val << AC97C_WD_BIT);
549
        au1000->ac97_ioport->cmd = cmd;
550
        spin_unlock(&au1000->ac97_lock);
551
}
552
 
553
static int __devinit
554
snd_au1000_ac97_new(struct snd_au1000 *au1000)
555
{
556
        int err;
557
        struct snd_ac97_bus *pbus;
558
        struct snd_ac97_template ac97;
559
        static struct snd_ac97_bus_ops ops = {
560
                .write = snd_au1000_ac97_write,
561
                .read = snd_au1000_ac97_read,
562
        };
563
 
564
        if ((au1000->ac97_res_port = request_mem_region(CPHYSADDR(AC97C_CONFIG),
565
                        0x100000, "Au1x00 AC97")) == NULL) {
566
                snd_printk(KERN_ERR "ALSA AC97: can't grap AC97 port\n");
567
                return -EBUSY;
568
        }
569
        au1000->ac97_ioport = (struct au1000_ac97_reg *)
570
                KSEG1ADDR(au1000->ac97_res_port->start);
571
 
572
        spin_lock_init(&au1000->ac97_lock);
573
 
574
        /* configure pins for AC'97
575
        TODO: move to board_setup.c */
576
        au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC);
577
 
578
        /* Initialise Au1000's AC'97 Control Block */
579
        au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE;
580
        udelay(10);
581
        au1000->ac97_ioport->cntrl = AC97C_CE;
582
        udelay(10);
583
 
584
        /* Initialise External CODEC -- cold reset */
585
        au1000->ac97_ioport->config = AC97C_RESET;
586
        udelay(10);
587
        au1000->ac97_ioport->config = 0x0;
588
        mdelay(5);
589
 
590
        /* Initialise AC97 middle-layer */
591
        if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0)
592
                return err;
593
 
594
        memset(&ac97, 0, sizeof(ac97));
595
        ac97.private_data = au1000;
596
        if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0)
597
                return err;
598
 
599
        return 0;
600
}
601
 
602
/*------------------------------ Setup / Destroy ----------------------------*/
603
 
604
void
605
snd_au1000_free(struct snd_card *card)
606
{
607
        struct snd_au1000 *au1000 = card->private_data;
608
 
609
        if (au1000->ac97_res_port) {
610
                /* put internal AC97 block into reset */
611
                au1000->ac97_ioport->cntrl = AC97C_RS;
612
                au1000->ac97_ioport = NULL;
613
                release_and_free_resource(au1000->ac97_res_port);
614
        }
615
 
616
        if (au1000->stream[PLAYBACK]) {
617
                if (au1000->stream[PLAYBACK]->dma >= 0)
618
                        free_au1000_dma(au1000->stream[PLAYBACK]->dma);
619
                kfree(au1000->stream[PLAYBACK]);
620
        }
621
 
622
        if (au1000->stream[CAPTURE]) {
623
                if (au1000->stream[CAPTURE]->dma >= 0)
624
                        free_au1000_dma(au1000->stream[CAPTURE]->dma);
625
                kfree(au1000->stream[CAPTURE]);
626
        }
627
}
628
 
629
 
630
static struct snd_card *au1000_card;
631
 
632
static int __init
633
au1000_init(void)
634
{
635
        int err;
636
        struct snd_card *card;
637
        struct snd_au1000 *au1000;
638
 
639
        card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(struct snd_au1000));
640
        if (card == NULL)
641
                return -ENOMEM;
642
 
643
        card->private_free = snd_au1000_free;
644
        au1000 = card->private_data;
645
        au1000->card = card;
646
 
647
        au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL);
648
        au1000->stream[CAPTURE ] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL);
649
        /* so that snd_au1000_free will work as intended */
650
        au1000->ac97_res_port = NULL;
651
        if (au1000->stream[PLAYBACK])
652
                au1000->stream[PLAYBACK]->dma = -1;
653
        if (au1000->stream[CAPTURE ])
654
                au1000->stream[CAPTURE ]->dma = -1;
655
 
656
        if (au1000->stream[PLAYBACK] == NULL ||
657
            au1000->stream[CAPTURE ] == NULL) {
658
                snd_card_free(card);
659
                return -ENOMEM;
660
        }
661
 
662
        if ((err = snd_au1000_ac97_new(au1000)) < 0 ) {
663
                snd_card_free(card);
664
                return err;
665
        }
666
 
667
        if ((err = snd_au1000_pcm_new(au1000)) < 0) {
668
                snd_card_free(card);
669
                return err;
670
        }
671
 
672
        strcpy(card->driver, "Au1000-AC97");
673
        strcpy(card->shortname, "AMD Au1000-AC97");
674
        sprintf(card->longname, "AMD Au1000--AC97 ALSA Driver");
675
 
676
        if ((err = snd_card_register(card)) < 0) {
677
                snd_card_free(card);
678
                return err;
679
        }
680
 
681
        printk( KERN_INFO "ALSA AC97: Driver Initialized\n" );
682
        au1000_card = card;
683
        return 0;
684
}
685
 
686
static void __exit au1000_exit(void)
687
{
688
        snd_card_free(au1000_card);
689
}
690
 
691
module_init(au1000_init);
692
module_exit(au1000_exit);
693
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.