2
* Purpose: Driver for the ALI 5455 (AC97) audio controller
6
* This file is part of Open Sound System.
8
* Copyright (C) 4Front Technologies 1996-2008.
10
* This this source file is released under GPL v2 license (no other versions).
11
* See the COPYING file included in the main directory of this source
12
* distribution for the license terms and conditions.
16
#include "oss_ali5455_cfg.h"
20
#define ALI_VENDOR_ID 0x10b9
21
#define ALI_DEVICE_5455 0x5455
28
static __inline__ unsigned int
29
swap32 (unsigned int x)
31
return ((x & 0x000000ff) << 24) |
32
((x & 0x0000ff00) << 8) |
33
((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
36
static __inline__ unsigned short
37
swap16 (unsigned short x)
39
return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
42
#define SWAP32(x) swap32(x)
43
#define SWAP16(x) swap16(x)
52
int speed, bits, channels;
70
typedef struct ALI_devc
76
oss_mutex_t low_mutex;
82
/* Audio parameters */
85
/* Buffer Descriptor List */
87
bdl_t *playBDL, *recBDL, *spdifBDL;
88
oss_native_word playBDL_phys, recBDL_phys, spdifBDL_phys;
89
oss_dma_handle_t bdl_dma_handle;
91
int play_currbuf, play_currfrag;
92
int spdif_currbuf, spdif_currfrag;
93
int rec_currbuf, rec_currfrag;
95
ALI_portc portc[MAX_PORTC];
96
int play_frag_index[BDL_SIZE];
97
int rec_frag_index[BDL_SIZE];
98
int spdif_frag_index[BDL_SIZE];
103
ac97_read (void *devc_, int reg)
105
ALI_devc *devc = devc_;
108
unsigned int data = 0;
109
unsigned short read_reg = 0;
110
oss_native_word flags;
112
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
113
status = INB (devc->osdev, devc->base + 0x34);
115
/* wait for the Codec Access Semaphore bit to be set */
116
while (i-- && (INL (devc->osdev, devc->base + 0x3c) & 0x80000000))
119
for (i = 0; i < 100; i++)
121
status = INB (devc->osdev, devc->base + 0x38);
127
cmn_err (CE_WARN, "AC97 not ready for read\n");
128
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
132
OUTW (devc->osdev, reg | 0x80, devc->base + 0x22);
134
for (i = 0; i < 100; i++)
136
status = INB (devc->osdev, devc->base + 0x38);
141
data = INW (devc->osdev, devc->base + 0x24);
142
read_reg = INW (devc->osdev, devc->base + 0x26);
149
cmn_err (CE_WARN, "AC97 read timed out \n");
150
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
156
cmn_err (CE_WARN, "AC97 invalid reg read %x (%x)\n", read_reg, reg);
157
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
161
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
166
ac97_write (void *devc_, int reg, int data)
168
ALI_devc *devc = devc_;
170
oss_native_word flags;
172
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
173
/* wait for the Codec Access Semaphore bit to be set */
174
while (i-- && (INL (devc->osdev, devc->base + 0x3c) & 0x80000000))
177
/* wait until command port is ready for write */
178
for (i = 0; i < 100; i++)
180
status = INB (devc->osdev, devc->base + 0x38);
187
cmn_err (CE_WARN, "AC97 timed out for write\n");
188
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
192
OUTL (devc->osdev, reg << 16 | data, devc->base + 0x20);
194
for (i = 0; i < 100; i++)
196
status = INB (devc->osdev, devc->base + 0x38);
201
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
206
ALIintr (oss_device_t * osdev)
208
int status, global_status, p, f, i;
210
ALI_devc *devc = (ALI_devc *) osdev->devc;
212
/* oss_native_word flags; */
214
/* Handle playback */
216
* TODO: Fix mutexes and move the inputintr/outputintr calls outside the
220
/* MUTEX_ENTER (devc->mutex, flags); */
221
/* Handle Global Interrupts */
222
global_status = INL (devc->osdev, devc->base + 0x18);
223
OUTL (devc->osdev, global_status, devc->base + 0x18);
225
if (!(global_status & (0x10000 | 0x20000 | 0x80000 | 0x100000 | 0x200000)))
227
/* MUTEX_EXIT (devc->mutex, flags); */
231
/* Handle Playback Interrupts */
233
status = INB (devc->osdev, devc->base + 0x56);
235
if ((status & 0x08) && (global_status & 0x20000))
236
for (i = 0; i < MAX_PORTC - 1; i++)
238
portc = &devc->portc[i];
240
if ((portc->trigger_bits & PCM_ENABLE_OUTPUT)) /* IOC interrupt */
242
dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out;
243
p = INB (devc->osdev, devc->base + 0x54);
245
if (p != devc->play_currbuf)
247
p = devc->play_currbuf;
248
f = devc->play_currfrag;
249
devc->playBDL[p].addr =
250
SWAP32 (dmap->dmabuf_phys + (f * dmap->fragment_size));
252
devc->playBDL[p].size = SWAP16 (dmap->fragment_size / 2);
253
devc->playBDL[p].flags = SWAP16 (0xc000); /* IOC interrupts */
255
OUTB (devc->osdev, p, devc->base + 0x55); /* Set LVD */
256
devc->play_frag_index[p] = f;
257
devc->play_currbuf = (p + 1) % BDL_SIZE;
258
devc->play_currfrag = (f + 1) % dmap->nfrags;
260
oss_audio_outputintr (portc->audiodev, 1);
263
OUTB (devc->osdev, status, devc->base + 0x56); /* Clear interrupts */
265
/*--------------------------------------------------------------------------*/
266
/* handle SPDIF interrupts */
268
status = INB (devc->osdev, devc->base + 0x76);
269
if ((status & 0x08) && (global_status & 0x80000))
271
portc = &devc->portc[2];
273
if ((portc->trigger_bits & PCM_ENABLE_OUTPUT)) /* IOC interrupt */
275
dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out;
276
p = INB (devc->osdev, devc->base + 0x74);
278
if (p != devc->spdif_currbuf)
280
p = devc->spdif_currbuf;
281
f = devc->spdif_currfrag;
282
devc->spdifBDL[p].addr =
283
SWAP32 (dmap->dmabuf_phys + (f * dmap->fragment_size));
285
devc->spdifBDL[p].size = SWAP16 (dmap->fragment_size / 2);
286
devc->spdifBDL[p].flags = SWAP16 (0xc000); /* IOC interrupts */
288
OUTB (devc->osdev, p, devc->base + 0x75); /* Set LVD */
289
devc->spdif_frag_index[p] = f;
290
devc->spdif_currbuf = (p + 1) % BDL_SIZE;
291
devc->spdif_currfrag = (f + 1) % dmap->nfrags;
293
oss_audio_outputintr (portc->audiodev, 1);
296
OUTB (devc->osdev, status, devc->base + 0x76); /* Clear interrupts */
297
/*---------------------------------------------------------------------------*/
299
/* Handle Recording Interrupts */
300
status = INB (devc->osdev, devc->base + 0x46);
302
if ((status & 0x08) && (global_status & 0x10000))
303
for (i = 0; i < MAX_PORTC - 1; i++)
305
portc = &devc->portc[i];
307
if ((portc->trigger_bits & PCM_ENABLE_INPUT)) /* IOC interrupt */
309
dmap_t *dmap = audio_engines[portc->audiodev]->dmap_in;
310
p = INB (devc->osdev, devc->base + 0x44);
312
if (p != devc->rec_currbuf)
314
p = devc->rec_currbuf;
315
f = devc->rec_currfrag;
316
devc->recBDL[p].addr =
317
SWAP32 (dmap->dmabuf_phys + (f * dmap->fragment_size));
319
/* SIS uses bytes, ali5455 uses samples */
320
devc->recBDL[p].size = SWAP16 (dmap->fragment_size / 2);
322
devc->recBDL[p].flags = SWAP16 (0xc000); /* IOC interrupts */
324
OUTB (devc->osdev, p, devc->base + 0x45); /* Set LVD */
325
devc->rec_frag_index[p] = f;
326
devc->rec_currbuf = (p + 1) % BDL_SIZE;
327
devc->rec_currfrag = (f + 1) % dmap->nfrags;
329
oss_audio_inputintr (portc->audiodev, 0);
332
OUTB (devc->osdev, status, devc->base + 0x46); /* Clear int */
334
/* MUTEX_EXIT (devc->mutex, flags); */
343
ALI_audio_set_rate (int dev, int arg)
345
ALI_portc *portc = audio_engines[dev]->portc;
350
if (audio_engines[dev]->flags & ADEV_FIXEDRATE)
362
ALI_audio_set_channels (int dev, short arg)
364
ALI_portc *portc = audio_engines[dev]->portc;
366
if ((arg == 1) || (arg == 2))
368
audio_engines[dev]->flags |= ADEV_STEREOONLY;
372
audio_engines[dev]->flags &= ~ADEV_STEREOONLY;
377
if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6))
378
return portc->channels;
379
portc->channels = arg;
381
return portc->channels;
385
ALI_audio_set_format (int dev, unsigned int arg)
387
ALI_portc *portc = audio_engines[dev]->portc;
392
if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3)))
401
ALI_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
406
static void ALI_audio_trigger (int dev, int state);
409
ALI_audio_reset (int dev)
411
ALI_audio_trigger (dev, 0);
415
ALI_audio_reset_input (int dev)
417
ALI_portc *portc = audio_engines[dev]->portc;
418
ALI_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT);
422
ALI_audio_reset_output (int dev)
424
ALI_portc *portc = audio_engines[dev]->portc;
425
ALI_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT);
430
ALI_audio_open (int dev, int mode, int openflags)
432
ALI_portc *portc = audio_engines[dev]->portc;
433
ALI_devc *devc = audio_engines[dev]->devc;
434
oss_native_word flags;
436
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
437
if (portc->open_mode)
439
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
443
if (portc->port_type == DF_SPDIF)
445
if (mode & OPEN_READ)
448
"ICH: The S/PDIF device supports only playback\n");
449
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
455
if (devc->open_mode & mode)
457
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
461
devc->open_mode |= mode;
465
portc->open_mode = mode;
466
portc->audio_enabled &= ~mode;
467
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
473
ALI_audio_close (int dev, int mode)
475
ALI_portc *portc = audio_engines[dev]->portc;
476
ALI_devc *devc = audio_engines[dev]->devc;
478
ALI_audio_reset (dev);
479
portc->open_mode = 0;
481
if (portc->port_type != DF_SPDIF)
482
devc->open_mode &= ~mode;
485
portc->audio_enabled &= ~mode;
490
ALI_audio_output_block (int dev, oss_native_word buf, int count,
491
int fragsize, int intrflag)
493
ALI_portc *portc = audio_engines[dev]->portc;
495
portc->audio_enabled |= PCM_ENABLE_OUTPUT;
496
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
501
ALI_audio_start_input (int dev, oss_native_word buf, int count,
502
int fragsize, int intrflag)
504
ALI_portc *portc = audio_engines[dev]->portc;
506
portc->audio_enabled |= PCM_ENABLE_INPUT;
507
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
511
ALI_audio_trigger (int dev, int state)
513
ALI_devc *devc = audio_engines[dev]->devc;
514
ALI_portc *portc = audio_engines[dev]->portc;
515
oss_native_word flags;
517
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
519
if (portc->open_mode & OPEN_WRITE)
521
if (state & PCM_ENABLE_OUTPUT)
523
if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
524
!(portc->trigger_bits & PCM_ENABLE_OUTPUT))
526
if (portc->port_type == DF_SPDIF)
528
OUTB (devc->osdev, 0x1d, devc->base + 0x7b); /* Setup intr */
529
OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) | 0x08, devc->base + 0x08); /* start DMA */
532
if (portc->port_type == DF_PCM)
534
OUTB (devc->osdev, 0x1d, devc->base + 0x5b); /* setup intr */
535
OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) | 0x02, devc->base + 0x08); /* start DMA */
537
portc->trigger_bits |= PCM_ENABLE_OUTPUT;
542
if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
543
(portc->trigger_bits & PCM_ENABLE_OUTPUT))
545
portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
546
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
547
if (portc->port_type == DF_SPDIF)
549
OUTB (devc->osdev, 0x00, devc->base + 0x7b); /* reset */
550
OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) & ~0x08, devc->base + 0x08); /* stop DMA */
553
if (portc->port_type == DF_PCM)
555
OUTB (devc->osdev, 0x00, devc->base + 0x5b); /* reset */
556
OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) & ~0x02, devc->base + 0x08); /* stop DMA */
562
if (portc->open_mode & OPEN_READ)
564
if (state & PCM_ENABLE_INPUT)
566
if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
567
!(portc->trigger_bits & PCM_ENABLE_INPUT))
569
OUTB (devc->osdev, 0x1d, devc->base + 0x4b); /* Kickstart */
570
OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) | 0x01, devc->base + 0x08); /* stop DMA */
571
portc->trigger_bits |= PCM_ENABLE_INPUT;
576
if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
577
(portc->trigger_bits & PCM_ENABLE_INPUT))
579
portc->audio_enabled &= ~PCM_ENABLE_INPUT;
580
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
581
OUTB (devc->osdev, 0x00, devc->base + 0x4b); /* reset */
582
OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) & ~0x01, devc->base + 0x08); /* stop DMA */
586
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
591
ALI_audio_prepare_for_input (int dev, int bsize, int bcount)
593
ALI_devc *devc = audio_engines[dev]->devc;
594
ALI_portc *portc = audio_engines[dev]->portc;
595
dmap_t *dmap = audio_engines[dev]->dmap_in;
597
oss_native_word flags;
599
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
601
OUTB (devc->osdev, 0x02, devc->base + 0x4b); /* Reset */
602
OUTL (devc->osdev, devc->recBDL_phys, devc->base + 0x40); /* BDL base */
604
ac97_recrate (&devc->ac97devc, portc->speed);
610
for (i = 0; i < n; i++)
612
devc->recBDL[i].addr =
613
SWAP32 (dmap->dmabuf_phys + (i * dmap->fragment_size));
614
devc->recBDL[i].size = SWAP16 (dmap->fragment_size / 2);
615
devc->recBDL[i].flags = SWAP16 (0xc000); /* IOC interrupts */
616
devc->rec_frag_index[i] = i;
618
OUTB (devc->osdev, n - 1, devc->base + 0x45); /* Set last valid descriptor */
620
devc->rec_currbuf = n % BDL_SIZE;
621
devc->rec_currfrag = n;
622
if (devc->rec_currfrag >= dmap->nfrags)
623
devc->rec_currfrag = 0;
625
portc->audio_enabled &= ~PCM_ENABLE_INPUT;
626
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
628
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
634
ALI_audio_prepare_for_output (int dev, int bsize, int bcount)
636
ALI_devc *devc = audio_engines[dev]->devc;
637
ALI_portc *portc = audio_engines[dev]->portc;
638
dmap_t *dmap = audio_engines[dev]->dmap_out;
640
oss_native_word flags;
642
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
644
ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_AUDIO, SNDCTL_MIX_WRITE, 0);
645
ac97_spdif_setup (devc->mixer_dev, portc->speed, portc->bits);
647
if (portc->bits == AFMT_AC3)
654
if (portc->port_type == DF_SPDIF)
656
ac97_playrate (&devc->ac97devc, portc->speed);
657
OUTB (devc->osdev, 0x02, devc->base + 0x7b); /* Reset */
658
OUTL (devc->osdev, devc->spdifBDL_phys, devc->base + 0x70);
664
for (i = 0; i < n; i++)
666
devc->spdifBDL[i].addr =
667
SWAP32 (dmap->dmabuf_phys + (i * dmap->fragment_size));
668
devc->spdifBDL[i].size = SWAP16 (dmap->fragment_size / 2);
669
devc->spdifBDL[i].flags = SWAP16 (0xc000); /* IOC interrupts */
670
devc->spdif_frag_index[i] = i;
672
OUTB (devc->osdev, n - 1, devc->base + 0x75); /* Set LVI descriptor */
673
devc->spdif_currbuf = n % BDL_SIZE;
674
devc->spdif_currfrag = n;
675
if (devc->spdif_currfrag >= dmap->nfrags)
676
devc->spdif_currfrag = 0;
678
portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
679
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
681
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
686
OUTB (devc->osdev, 0x02, devc->base + 0x5b); /* Reset */
687
OUTL (devc->osdev, devc->playBDL_phys, devc->base + 0x50);
689
ac97_playrate (&devc->ac97devc, portc->speed);
691
/* set default to 2 channel mode */
692
if (portc->channels == 2)
693
OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x00) & ~0x300,
695
if (portc->channels == 4)
697
(INW (devc->osdev, devc->base + 0x00) & ~0x300) | 0x100,
699
if (portc->channels == 6)
701
(INW (devc->osdev, devc->base + 0x00) & ~0x300) | 0x200,
709
for (i = 0; i < n; i++)
711
devc->playBDL[i].addr =
712
SWAP32 (dmap->dmabuf_phys + (i * dmap->fragment_size));
713
devc->playBDL[i].size = SWAP16 (dmap->fragment_size / 2);
714
devc->playBDL[i].flags = SWAP16 (0xc000); /* IOC interrupts */
715
devc->play_frag_index[i] = i;
717
OUTB (devc->osdev, n - 1, devc->base + 0x55); /* Set last valid descriptor */
719
devc->play_currbuf = n % BDL_SIZE;
720
devc->play_currfrag = n;
721
if (devc->play_currfrag >= dmap->nfrags)
722
devc->play_currfrag = 0;
724
portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
725
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
726
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
730
static const audiodrv_t ALI_audio_driver = {
733
ALI_audio_output_block,
734
ALI_audio_start_input,
736
ALI_audio_prepare_for_input,
737
ALI_audio_prepare_for_output,
741
ALI_audio_reset_input,
742
ALI_audio_reset_output,
745
ALI_audio_set_format,
746
ALI_audio_set_channels
750
init_ALI (ALI_devc * devc)
752
int my_mixer, my_dev, opts;
753
oss_native_word phaddr;
756
/* ACLink on, warm reset */
757
OUTL (devc->osdev, 0x80008003, devc->base + 0x00); /*reset SCR */
758
OUTL (devc->osdev, 0x83838383, devc->base + 0x0c); /*reset pcm in/out FIFO */
759
OUTL (devc->osdev, 0x83838383, devc->base + 0x1c); /*reset SPDIF/LFEr FIFO */
760
OUTL (devc->osdev, 0x0028000a, devc->base + 0x10); /*set spdif/pcm in/out */
761
OUTL (devc->osdev, INL (devc->osdev, devc->base + 0xFC) | 0x3,
764
/* set up Codec SPDIFOUT slot to 10/11 */
765
OUTL (devc->osdev, INL (devc->osdev, devc->base + 0x00) | 0x300000,
767
/* disable interrupts */
768
OUTL (devc->osdev, 0x00, devc->base + 0x14);
769
OUTL (devc->osdev, 0x00, devc->base + 0x18);
772
CONTIG_MALLOC (devc->osdev, 4 * 32 * 32, MEMLIMIT_32BITS, &phaddr, devc->bdl_dma_handle);
773
if (devc->bdlBuffer == NULL)
775
cmn_err (CE_WARN, "Failed to allocate BDL\n");
779
devc->playBDL = (bdl_t *) devc->bdlBuffer;
780
devc->playBDL_phys = phaddr;
781
devc->recBDL = (bdl_t *) (devc->bdlBuffer + (1 * 32 * 32));
782
devc->recBDL_phys = phaddr + (1 * 32 * 32);
783
devc->spdifBDL = (bdl_t *) (devc->bdlBuffer + (2 * 32 * 32));
784
devc->spdifBDL_phys = phaddr + (2 * 32 * 32);
790
ac97_install (&devc->ac97devc, "AC97 Mixer", ac97_read, ac97_write, devc,
794
return 0; /* No mixer */
796
devc->mixer_dev = my_mixer;
799
devc->ac97devc.spdif_slot = SPDIF_SLOT1011;
800
ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 1);
803
/* enable variable rate mode */
804
ac97_write (devc, 0x2a, ac97_read (devc, 0x2a) | 9);
805
if (!(ac97_read (devc, 0x2a) & 1))
806
DDB (cmn_err (CE_WARN, "VRA not supported...using GRC\n"));
809
for (i = 0; i < MAX_PORTC; i++)
811
ALI_portc *portc = &devc->portc[i];
813
int port_fmt = DF_PCM;
814
int formats = AFMT_S16_LE | AFMT_AC3;
815
strcpy (tmp_name, devc->chip_name);
816
opts = ADEV_AUTOMODE | ADEV_16BITONLY | ADEV_STEREOONLY;
817
portc->port_type = DF_PCM;
819
if (!ac97_varrate (&devc->ac97devc))
821
opts |= ADEV_FIXEDRATE;
827
strcpy (tmp_name, devc->chip_name);
831
opts |= ADEV_DUPLEX | ADEV_SHADOW;
832
strcpy (tmp_name, devc->chip_name);
837
sprintf (tmp_name, "%s (S/PDIF)", devc->chip_name);
838
opts |= ADEV_NOINPUT | ADEV_SPECIAL | ADEV_FIXEDRATE;
842
if ((my_dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
847
sizeof (audiodrv_t), opts,
848
formats, devc, -1)) < 0)
855
audio_engines[my_dev]->portc = portc;
856
audio_engines[my_dev]->mixer_dev = my_mixer;
857
audio_engines[my_dev]->min_rate =
858
(opts & ADEV_FIXEDRATE) ? 48000 : 5000;
859
audio_engines[my_dev]->max_rate = 48000;
860
audio_engines[my_dev]->caps |= PCM_CAP_FREERATE;
861
/*audio_engines[my_dev]->min_block = 4096; */
862
/*audio_engines[my_dev]->max_block = 4096; */
863
audio_engines[my_dev]->min_channels = 2;
864
audio_engines[my_dev]->max_channels = 6;
865
portc->open_mode = 0;
866
portc->audio_enabled = 0;
867
portc->audiodev = my_dev;
868
portc->port_type = port_fmt;
869
if (audio_engines[my_dev]->flags & ADEV_FIXEDRATE)
870
audio_engines[my_dev]->fixed_rate = 48000;
871
#ifdef CONFIG_OSS_VMIX
873
vmix_attach_audiodev(devc->osdev, my_dev, -1, 0);
882
oss_ali5455_attach (oss_device_t * osdev)
884
unsigned char pci_irq_line, pci_revision /*, pci_latency */ ;
885
unsigned short pci_command, vendor, device;
886
unsigned int pci_ioaddr0;
889
DDB (cmn_err (CE_WARN, "Entered ALI AC97 probe routine\n"));
891
pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
892
pci_read_config_word (osdev, PCI_DEVICE_ID, &device);
894
if ((vendor != ALI_VENDOR_ID) || (device != ALI_DEVICE_5455))
897
pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision);
898
pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
899
pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
900
pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr0);
902
if (pci_ioaddr0 == 0)
904
cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n");
908
if (pci_irq_line == 0)
910
cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d).\n", pci_irq_line);
914
if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
916
cmn_err (CE_WARN, "Out of memory\n");
924
/* Remove I/O space marker in bit 0. */
925
devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr0);
928
pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
929
pci_write_config_word (osdev, PCI_COMMAND, pci_command);
931
devc->chip_name = "ALI M5455";
932
devc->irq = pci_irq_line;
934
MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
935
MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1);
937
oss_register_device (osdev, devc->chip_name);
939
if (oss_register_interrupts (devc->osdev, 0, ALIintr, NULL) < 0)
941
cmn_err (CE_WARN, "Unable to install interrupt handler\n");
945
return init_ALI (devc); /* Detected */
950
oss_ali5455_detach (oss_device_t * osdev)
952
ALI_devc *devc = (ALI_devc *) osdev->devc;
955
if (oss_disable_device (osdev) < 0)
960
ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 0);
961
/* disable interrupts */
962
OUTL (devc->osdev, 0x00, devc->base + 0x14);
963
OUTL (devc->osdev, 0x00, devc->base + 0x18);
965
oss_unregister_interrupts (devc->osdev);
969
CONTIG_FREE (devc->osdev, devc->bdlBuffer, 4 * 32 * 32, devc->bdl_dma_handle);
970
devc->bdlBuffer = NULL;
973
MUTEX_CLEANUP (devc->mutex);
974
MUTEX_CLEANUP (devc->low_mutex);
975
UNMAP_PCI_IOADDR (devc->osdev, 0);
977
oss_unregister_device (osdev);