2
* Purpose: Driver for the VIA8233/8235 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_via823x_cfg.h"
22
static void feed_sgd (via8233_devc * devc, dmap_t * dmap, engine_desc * eng);
25
ac97_read (void *devc_, int wIndex)
27
oss_native_word flags;
28
unsigned int dwWriteValue = 0, dwTmpValue, i = 0;
29
via8233_devc *devc = devc_;
32
/* Index has only 7 bit */
36
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
37
dwWriteValue = ((unsigned int) wIndex << 16) + CODEC_RD;
38
OUTL (devc->osdev, dwWriteValue, devc->base + AC97CODEC);
40
/* Check AC CODEC access time out */
41
for (i = 0; i < CODEC_TIMEOUT_COUNT; i++)
43
/* if send command over, break */
44
if (INL (devc->osdev, devc->base + AC97CODEC) & STA_VALID)
48
if (i == CODEC_TIMEOUT_COUNT)
50
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
54
/* Check if Index still ours? If yes, return data, else return FAIL */
55
dwTmpValue = INL (devc->osdev, devc->base + AC97CODEC);
56
OUTB (devc->osdev, 0x02, devc->base + AC97CODEC + 3);
57
if (((dwTmpValue & CODEC_INDEX) >> 16) == wIndex)
59
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
60
return ((int) dwTmpValue & CODEC_DATA);
62
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
68
ac97_write (void *devc_, int wIndex, int wData)
70
oss_native_word flags;
71
unsigned int dwWriteValue = 0, i = 0;
72
via8233_devc *devc = devc_;
74
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
75
dwWriteValue = ((unsigned int) wIndex << 16) + wData;
76
OUTL (devc->osdev, dwWriteValue, devc->base + AC97CODEC);
79
/* Check AC CODEC access time out */
80
for (i = 0; i < CODEC_TIMEOUT_COUNT; i++)
82
/* if send command over, break */
83
if (!(INL (devc->osdev, devc->base + AC97CODEC) & IN_CMD))
87
if (i == CODEC_TIMEOUT_COUNT)
89
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
92
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
97
via8233intr (oss_device_t * osdev)
100
via8233_devc *devc = osdev->devc;
101
via8233_portc *portc;
103
unsigned int engine_stat;
104
unsigned int status = 0;
105
oss_native_word flags;
107
MUTEX_ENTER (devc->mutex, flags);
108
status = INL (devc->osdev, devc->base + 0x84);
110
// This is reported to cause hang because some status register bits
111
// may be turned on even ehen the device is not interrupting.
115
* No interrupts are pending so we can stop without
116
* polling all the individual status registers.
118
MUTEX_EXIT (devc->mutex, flags);
123
for (i = 0; i < MAX_PORTC; i++)
125
portc = &devc->portc[i];
126
eng = portc->play_engine;
129
if ((eng->mode & OPEN_WRITE)
130
&& (portc->trigger_bits & PCM_ENABLE_OUTPUT))
132
engine_stat = INB (devc->osdev, eng->base + 0x00);
133
if (engine_stat & 0x01)
135
oss_audio_outputintr (portc->audiodev, 1);
136
feed_sgd (devc, audio_engines[portc->audiodev]->dmap_out,
140
OUTB (devc->osdev, engine_stat, eng->base + 0x00);
143
eng = portc->rec_engine;
145
if ((eng->mode & OPEN_READ)
146
&& (portc->trigger_bits & PCM_ENABLE_INPUT))
148
engine_stat = INB (devc->osdev, eng->base + 0x00);
149
if (engine_stat & 0x01)
151
oss_audio_inputintr (portc->audiodev, 0);
152
feed_sgd (devc, audio_engines[portc->audiodev]->dmap_in, eng);
155
OUTB (devc->osdev, engine_stat, eng->base + 0x00);
158
MUTEX_EXIT (devc->mutex, flags);
168
via8233_audio_set_rate (int dev, int arg)
170
via8233_portc *portc = audio_engines[dev]->portc;
175
if (audio_engines[dev]->flags & ADEV_FIXEDRATE)
187
via8233_audio_set_channels (int dev, short arg)
189
via8233_portc *portc = audio_engines[dev]->portc;
194
if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6))
195
return portc->channels;
196
portc->channels = arg;
198
return portc->channels;
202
via8233_audio_set_format (int dev, unsigned int arg)
204
via8233_portc *portc = audio_engines[dev]->portc;
209
if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3)))
218
via8233_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
223
static void via8233_audio_trigger (int dev, int state);
226
via8233_audio_reset (int dev)
228
via8233_audio_trigger (dev, 0);
232
via8233_audio_reset_input (int dev)
234
via8233_portc *portc = audio_engines[dev]->portc;
235
via8233_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT);
239
via8233_audio_reset_output (int dev)
241
via8233_portc *portc = audio_engines[dev]->portc;
242
via8233_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT);
247
via8233_audio_open (int dev, int mode, int open_flags)
249
via8233_portc *portc = audio_engines[dev]->portc;
250
via8233_devc *devc = audio_engines[dev]->devc;
251
oss_native_word flags;
253
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
254
if (portc->open_mode)
256
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
260
if (devc->open_mode & mode)
262
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
266
devc->open_mode |= mode;
268
portc->open_mode = mode;
269
portc->audio_enabled &= ~mode;
270
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
276
via8233_audio_close (int dev, int mode)
278
via8233_portc *portc = audio_engines[dev]->portc;
279
via8233_devc *devc = audio_engines[dev]->devc;
281
via8233_audio_reset (dev);
282
portc->open_mode = 0;
283
devc->open_mode &= ~mode;
284
portc->audio_enabled &= ~mode;
289
via8233_audio_output_block (int dev, oss_native_word buf, int count,
290
int fragsize, int intrflag)
292
via8233_portc *portc = audio_engines[dev]->portc;
294
portc->audio_enabled |= PCM_ENABLE_OUTPUT;
295
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
302
via8233_audio_start_input (int dev, oss_native_word buf, int count,
303
int fragsize, int intrflag)
305
via8233_portc *portc = audio_engines[dev]->portc;
307
portc->audio_enabled |= PCM_ENABLE_INPUT;
308
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
313
via8233_audio_trigger (int dev, int state)
315
via8233_portc *portc = audio_engines[dev]->portc;
316
via8233_devc *devc = audio_engines[dev]->devc;
318
oss_native_word flags;
320
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
321
if ((portc->open_mode & OPEN_WRITE) && portc->play_engine != NULL)
323
eng = portc->play_engine;
325
if (state & PCM_ENABLE_OUTPUT)
327
if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
328
!(portc->trigger_bits & PCM_ENABLE_OUTPUT))
330
/* Start with autoinit and SGD flag interrupts enabled */
331
OUTB (devc->osdev, 0xa1, eng->base + 0x01);
332
portc->trigger_bits |= PCM_ENABLE_OUTPUT;
337
if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
338
(portc->trigger_bits & PCM_ENABLE_OUTPUT))
340
OUTB (devc->osdev, 0x40, eng->base + 0x01); /* Stop */
341
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
346
if ((portc->open_mode & OPEN_READ) && portc->rec_engine != NULL)
348
eng = portc->rec_engine;
350
if (state & PCM_ENABLE_INPUT)
352
if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
353
!(portc->trigger_bits & PCM_ENABLE_INPUT))
355
/* Start with autoinit and SGD flag interrupts enabled */
356
OUTB (devc->osdev, 0xa1, eng->base + 0x01);
357
portc->trigger_bits |= PCM_ENABLE_INPUT;
362
if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
363
(portc->trigger_bits & PCM_ENABLE_INPUT))
365
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
366
OUTB (devc->osdev, 0x40, eng->base + 0x01); /* Stop */
370
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
374
feed_sgd (via8233_devc * devc, dmap_t * dmap, engine_desc * eng)
376
unsigned int addr, p, tmp;
377
oss_native_word flags;
379
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
380
addr = dmap->dmabuf_phys + eng->cfrag * dmap->fragment_size;
383
eng->sgd[p].phaddr = addr;
384
eng->sgd[p].flags = dmap->fragment_size | SGD_FLAG;
385
if (p == (SGD_SIZE - 1))
386
eng->sgd[p].flags |= SGD_EOL;
388
/* Update the last entry ptr */
389
tmp = INL (devc->osdev, eng->base + 0x08);
392
OUTL (devc->osdev, tmp, eng->base + 0x08);
395
eng->frags[p] = eng->cfrag;
396
eng->cfrag = (eng->cfrag + 1) % dmap->nfrags;
397
eng->sgd_ptr = (eng->sgd_ptr + 1) % SGD_SIZE;
398
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
403
via8233_audio_prepare_for_input (int dev, int bsize, int bcount)
405
via8233_devc *devc = audio_engines[dev]->devc;
406
via8233_portc *portc = audio_engines[dev]->portc;
407
dmap_t *dmap = audio_engines[dev]->dmap_in;
411
oss_native_word flags;
413
if (portc->rec_engine == NULL)
415
cmn_err (CE_WARN, "No rec engine (dev=%d)\n", dev);
419
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
420
eng = portc->rec_engine;
422
OUTB (devc->osdev, 0x40, eng->base + 0x01); /* Stop */
426
eng->prevpos = 0xffffffff;
428
for (i = 0; i < 2; i++)
429
feed_sgd (devc, dmap, eng);
431
OUTL (devc->osdev, eng->sgd_phys, eng->base + 0x04);
434
if (portc->bits == AFMT_S16_LE)
436
if (portc->channels == 2)
439
if (devc->chip_type != CHIP_8233A)
441
if (portc->speed == 48000)
442
fmt |= (1 << 20) - 1;
444
fmt |= ((1024 * portc->speed + 24000) / 48000) * 1024;
447
fmt |= (eng->prev_sgd << 24);
448
OUTL (devc->osdev, fmt, eng->base + 0x08);
449
ac97_recrate (&devc->ac97devc, portc->speed);
451
portc->audio_enabled &= ~PCM_ENABLE_INPUT;
452
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
453
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
459
via8233_audio_prepare_for_output (int dev, int bsize, int bcount)
461
via8233_devc *devc = audio_engines[dev]->devc;
462
via8233_portc *portc = audio_engines[dev]->portc;
463
dmap_p dmap = audio_engines[dev]->dmap_out;
467
oss_native_word flags;
469
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
470
eng = portc->play_engine;
472
OUTB (devc->osdev, 0x40, eng->base + 0x01); /* Stop */
476
eng->prevpos = 0xffffffff;
478
for (i = 0; i < 2; i++)
479
feed_sgd (devc, dmap, eng);
481
OUTL (devc->osdev, eng->sgd_phys, eng->base + 0x4);
483
ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_AUDIO, SNDCTL_MIX_WRITE, 0);
485
if (portc->bits == AFMT_AC3)
490
ac97_spdif_setup (devc->mixer_dev, portc->speed, portc->bits);
492
tmp = (portc->bits == AFMT_U8) ? 0 : 0x80;
493
tmp |= portc->channels << 4;
494
OUTB (devc->osdev, tmp, eng->base + 0x02);
496
/* Select channel assignment - not valid for 8233A */
498
if (devc->chip_type != CHIP_8233A)
500
switch (portc->channels)
503
tmp = (1 << 0) | (1 << 4);
506
tmp = (1 << 0) | (2 << 4);
509
tmp = (1 << 0) | (2 << 4) | (3 << 8) | (4 << 12);
513
(1 << 0) | (2 << 4) | (5 << 8) | (6 << 12) | (3 << 16) | (4 <<
522
OUTL (devc->osdev, tmp, eng->base + 0x08);
523
/* need to set the speed twice - for some odd reason */
524
ac97_playrate (&devc->ac97devc, portc->speed);
525
ac97_playrate (&devc->ac97devc, portc->speed);
527
portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
528
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
529
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
536
via8233_alloc_buffer (int dev, dmap_t * dmap, int direction)
539
via8233_devc *devc = audio_engines[dev]->devc;
540
via8233_portc *portc = audio_engines[dev]->portc;
543
if (dmap->dmabuf != NULL)
546
if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0)
550
if (direction == PCM_ENABLE_INPUT)
552
eng = &devc->engines[REC_SGD_NUM];
553
eng->mode = OPEN_READ;
554
portc->rec_engine = eng;
558
eng = &devc->engines[PLAY_SGD_NUM];
559
eng->mode = OPEN_WRITE;
560
portc->play_engine = eng;
569
via8233_free_buffer (int dev, dmap_t * dmap, int direction)
571
via8233_portc *portc = audio_engines[dev]->portc;
573
if (dmap->dmabuf == NULL)
575
oss_free_dmabuf (dev, dmap);
578
dmap->dmabuf_phys = 0;
580
if (direction == PCM_ENABLE_OUTPUT)
581
portc->play_engine = NULL;
583
if (direction == PCM_ENABLE_INPUT)
584
portc->rec_engine = NULL;
590
via8233_get_buffer_pointer (int dev, dmap_t * dmap, int direction)
592
via8233_portc *portc = audio_engines[dev]->portc;
593
via8233_devc *devc = audio_engines[dev]->devc;
594
unsigned int ptr, pos, tmp;
596
oss_native_word flags;
598
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
599
if (direction == PCM_ENABLE_OUTPUT)
602
/* int this_sgd, prev_sgd */ ;
604
if (portc->play_engine == NULL
605
|| !(portc->trigger_bits & PCM_ENABLE_OUTPUT))
607
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
611
eng = portc->play_engine;
613
ptr = INL (devc->osdev, eng->base + 0x0c);
614
status = INB (devc->osdev, eng->base + 0x00);
615
if (!(status & 0x80)) /* SGD not triggered */
617
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
622
oss_timing_printf ("rawpos=%d", ptr);
625
this_sgd = ptr >> 24;
626
prev_sgd = eng->prevpos >> 24;
627
prev_sgd = (prev_sgd + 1) % SGD_SIZE; /* Increment */
628
/* Chip bug catcher */
629
if (((ptr & 0xffffff) == 0) &&
630
((eng->prevpos & 0xffffff) == 0) && (this_sgd == prev_sgd))
636
tmp = ptr & 0xffffff;
639
pos = eng->frags[ptr] * dmap->fragment_size;
640
pos += (dmap->fragment_size - tmp) & ~3;
643
oss_timing_printf ("Playpos=%d", pos);
645
pos = pos % dmap->bytes_in_use;
646
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
650
if (direction == PCM_ENABLE_INPUT)
653
/* int this_sgd, prev_sgd; */
655
if (portc->rec_engine == NULL
656
|| !(portc->trigger_bits & PCM_ENABLE_INPUT))
658
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
662
eng = portc->rec_engine;
664
ptr = INL (devc->osdev, eng->base + 0x0c);
665
status = INB (devc->osdev, eng->base + 0x00);
666
if (!(status & 0x80)) /* SGD not triggered */
668
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
673
this_sgd = ptr >> 24;
674
prev_sgd = eng->prevpos >> 24;
675
prev_sgd = (prev_sgd + 1) % SGD_SIZE; /* Increment */
677
/* Chip bug catcher */
678
if (((ptr & 0xffffff) == 0) &&
679
((eng->prevpos & 0xffffff) == 0) && (this_sgd == prev_sgd))
685
tmp = ptr & 0xffffff;
688
pos = eng->frags[ptr] * dmap->fragment_size;
689
pos += (dmap->fragment_size - tmp) & ~3;
692
oss_timing_printf ("Recpos=%d", pos);
694
pos = pos % dmap->bytes_in_use;
695
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
698
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
702
static const audiodrv_t via8233_audio_driver = {
705
via8233_audio_output_block,
706
via8233_audio_start_input,
708
via8233_audio_prepare_for_input,
709
via8233_audio_prepare_for_output,
713
via8233_audio_reset_input,
714
via8233_audio_reset_output,
715
via8233_audio_trigger,
716
via8233_audio_set_rate,
717
via8233_audio_set_format,
718
via8233_audio_set_channels,
721
NULL, /* via8233_check_input, */
722
NULL, /* via8233_check_output, */
723
via8233_alloc_buffer,
727
via8233_get_buffer_pointer
731
via8233_alloc_engines (via8233_devc * devc)
734
oss_native_word phaddr;
737
for (i = 0; i < MAX_ENGINES; i++)
741
eng = &devc->engines[REC_SGD_NUM];
742
eng->base = devc->base + 0x60;
746
eng = &devc->engines[PLAY_SGD_NUM];
747
eng->base = devc->base + 0x40;
750
if (eng->sgd == NULL)
753
CONTIG_MALLOC (devc->osdev, SGD_ALLOC, MEMLIMIT_32BITS, &phaddr, eng->sgd_dma_handle);
755
if (eng->sgd == NULL)
757
cmn_err (CE_WARN, "can't allocate SGD table\n");
760
eng->sgd_phys = phaddr;
767
via8233_init (via8233_devc * devc)
769
int my_mixer, adev, opts;
770
via8233_portc *portc;
775
/* allocate the Scatter Gather Engine buffers */
776
if (via8233_alloc_engines (devc) < 0)
778
cmn_err (CE_WARN, "Unable to allocate engines\n");
786
ac97_install (&devc->ac97devc, "VIA823x AC97 Mixer", ac97_read,
787
ac97_write, devc, devc->osdev);
791
cmn_err (CE_WARN, "AC97 mixer installation failed\n");
792
return 0; /* No mixer */
795
devc->mixer_dev = my_mixer;
796
mixer_devs[my_mixer]->priority = 10; /* Known motherboard device */
799
devc->ac97devc.spdif_slot = SPDIF_SLOT34;
800
ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 1);
802
for (i = 0; i < MAX_PORTC; i++)
804
opts = ADEV_AUTOMODE;
806
if (!ac97_varrate (&devc->ac97devc))
808
opts |= ADEV_FIXEDRATE;
811
portc = &devc->portc[i];
815
strcpy (tmp_name, devc->chip_name);
819
opts |= ADEV_DUPLEX | ADEV_SHADOW;
820
strcpy (tmp_name, devc->chip_name);
823
if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
827
&via8233_audio_driver,
830
AFMT_U8 | AFMT_S16_LE | AFMT_AC3,
840
audio_engines[adev]->portc = portc;
841
audio_engines[adev]->rate_source = first_dev;
842
audio_engines[adev]->mixer_dev = my_mixer;
843
audio_engines[adev]->min_rate = 8000;
844
audio_engines[adev]->max_rate = 48000;
845
audio_engines[adev]->caps |= PCM_CAP_FREERATE;
846
audio_engines[adev]->min_channels = 2;
847
audio_engines[adev]->max_channels = 6;
848
if (opts & ADEV_FIXEDRATE)
850
audio_engines[adev]->fixed_rate = 48000;
851
audio_engines[adev]->min_rate = 48000;
852
audio_engines[adev]->max_rate = 48000;
855
portc->open_mode = 0;
856
portc->audio_enabled = 0;
857
portc->audiodev = adev;
858
#ifdef CONFIG_OSS_VMIX
860
vmix_attach_audiodev(devc->osdev, adev, -1, 0);
869
oss_via823x_attach (oss_device_t * osdev)
871
unsigned char pci_irq_line, pci_revision, bTmp /*, pci_latency */ ;
872
unsigned short pci_command, vendor, device;
873
unsigned int pci_ioaddr;
876
pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
877
pci_read_config_word (osdev, PCI_DEVICE_ID, &device);
880
(CE_CONT, "oss_via823x_attach(Vendor %x, device %x)\n", vendor, device));
881
if ((vendor != VIA_VENDOR_ID)
882
|| (device != VIA_8233_ID && device != VIA_8233A_ID))
885
cmn_err (CE_WARN, "Hardware not recognized (vendor=%x, dev=%x)\n",
890
pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision);
891
pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
892
pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
893
pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr);
897
cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n");
901
if (pci_irq_line == 0)
903
cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d).\n", pci_irq_line);
907
if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
909
cmn_err (CE_WARN, "Out of memory\n");
917
devc->chip_type = CHIP_8233;
918
devc->chip_name = "VIA VT8233";
920
if (pci_revision == 0x50)
921
devc->chip_name = "VIA VT8235";
923
if (pci_revision == 0x60)
924
devc->chip_name = "VIA VT8237";
926
if ((device == VIA_8233A_ID) ||
927
(device == VIA_8233_ID && pci_revision == 0x40))
929
devc->chip_type = CHIP_8233A;
930
devc->chip_name = "VIA VT8233A";
933
pci_write_config_byte (osdev, 0x41, 0xc0); /*ENAC97 & deassert RESET */
936
pci_read_config_byte (osdev, 0x41, &bTmp);
938
if (devc->chip_type == CHIP_8233A)
939
bTmp |= 0x0C; /* Enable var rate support */
941
bTmp |= 0x0f; /* enable VRA,SB,DX */
942
pci_write_config_byte (osdev, 0x41, bTmp);
945
if (devc->chip_type == CHIP_8233A)
947
pci_read_config_byte (osdev, 0x49, &bTmp);
949
pci_write_config_byte (osdev, 0x49, 0x0);
953
/* set slot 3,4 as SPDIF on VIA8235 - AC3 passthrough magic! */
954
pci_write_config_byte (osdev, 0x49, 0x1);
957
devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr);
958
/* Remove I/O space marker in bit 0. */
961
pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
962
pci_write_config_word (osdev, PCI_COMMAND, pci_command);
964
devc->irq = pci_irq_line;
966
MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
967
MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1);
969
oss_register_device (osdev, devc->chip_name);
971
if (oss_register_interrupts (devc->osdev, 0, via8233intr, NULL) < 0)
973
cmn_err (CE_WARN, "Unable to register interrupts\n");
977
return via8233_init (devc); /* Detected */
981
oss_via823x_detach (oss_device_t * osdev)
983
via8233_devc *devc = (via8233_devc *) osdev->devc;
987
if (oss_disable_device (devc->osdev) < 0)
992
if (devc->mixer_dev > 0)
993
ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 0);
995
oss_unregister_interrupts (devc->osdev);
997
for (i = 0; i < MAX_ENGINES; i++)
999
eng = &devc->engines[i];
1000
if (eng->sgd != NULL)
1002
CONTIG_FREE (devc->osdev, eng->sgd, SGD_ALLOC, eng->sgd_dma_handle);
1007
MUTEX_CLEANUP (devc->mutex);
1008
MUTEX_CLEANUP (devc->low_mutex);
1009
UNMAP_PCI_IOADDR (devc->osdev, 0);
1011
oss_unregister_device (devc->osdev);