diff options
author | Karsten Wiese <annabellesgarden@yahoo.de> | 2005-10-18 08:31:07 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2005-11-04 07:19:00 -0500 |
commit | 4f550df58f4758ea023704b409830ad9c3b47771 (patch) | |
tree | 83f935c11032a2a4099e0996717482ddcce945ca /sound/pci/via82xx.c | |
parent | f0597a416dc44e3afe25090e9af9d42bad62547d (diff) |
[ALSA] Reduce interrupt latency in sound/pci/via82xx.c
Modules: VIA82xx driver
The change only affects the via823x kind of chips.
Here the via8233_pcm_pointer_hw() function
(named snd_via8233_pcm_pointer() before)
needed to loop until a non zero position is red from the chip.
Measurements have shown that more than 200 loops are typically needed on
an Athlon64.
As io-reads cost many cycles, those loops sum up huge.
via8233_pcm_pointer_hw() runs either in interrupt or with interrupts
disabled. So it introduces significant interrupt latency.
The patch introduces a calculated position value hwptr_done,
that is updated by the interrupt routine when a period is completed.
It is only used, if the 823x chip returns a zero position, which can't
be interpreted reliably.
Further optimisation is applied on the 8233 chip's interrupt routine:
Only the SGD_SHADOW is read, as it contains all infos needed.
We ommit ~5 more register reads that way.
Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/via82xx.c')
-rw-r--r-- | sound/pci/via82xx.c | 170 |
1 files changed, 131 insertions, 39 deletions
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 7d46bee828c7..eb35b446235c 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -41,6 +41,9 @@ | |||
41 | * device for applications. | 41 | * device for applications. |
42 | * - clean up the code, separate low-level initialization | 42 | * - clean up the code, separate low-level initialization |
43 | * routines for each chipset. | 43 | * routines for each chipset. |
44 | * | ||
45 | * Sep. 26, 2005 Karsten Wiese <annabellesgarden@yahoo.de> | ||
46 | * - Optimize position calculation for the 823x chips. | ||
44 | */ | 47 | */ |
45 | 48 | ||
46 | #include <sound/driver.h> | 49 | #include <sound/driver.h> |
@@ -131,6 +134,7 @@ module_param(enable, int, 0444); | |||
131 | /* common offsets */ | 134 | /* common offsets */ |
132 | #define VIA_REG_OFFSET_STATUS 0x00 /* byte - channel status */ | 135 | #define VIA_REG_OFFSET_STATUS 0x00 /* byte - channel status */ |
133 | #define VIA_REG_STAT_ACTIVE 0x80 /* RO */ | 136 | #define VIA_REG_STAT_ACTIVE 0x80 /* RO */ |
137 | #define VIA8233_SHADOW_STAT_ACTIVE 0x08 /* RO */ | ||
134 | #define VIA_REG_STAT_PAUSED 0x40 /* RO */ | 138 | #define VIA_REG_STAT_PAUSED 0x40 /* RO */ |
135 | #define VIA_REG_STAT_TRIGGER_QUEUED 0x08 /* RO */ | 139 | #define VIA_REG_STAT_TRIGGER_QUEUED 0x08 /* RO */ |
136 | #define VIA_REG_STAT_STOPPED 0x04 /* RWC */ | 140 | #define VIA_REG_STAT_STOPPED 0x04 /* RWC */ |
@@ -329,6 +333,9 @@ struct via_dev { | |||
329 | unsigned int fragsize; | 333 | unsigned int fragsize; |
330 | unsigned int bufsize; | 334 | unsigned int bufsize; |
331 | unsigned int bufsize2; | 335 | unsigned int bufsize2; |
336 | int hwptr_done; /* processed frame position in the buffer */ | ||
337 | int in_interrupt; | ||
338 | int shadow_shift; | ||
332 | }; | 339 | }; |
333 | 340 | ||
334 | 341 | ||
@@ -395,8 +402,10 @@ struct _snd_via82xx { | |||
395 | }; | 402 | }; |
396 | 403 | ||
397 | static struct pci_device_id snd_via82xx_ids[] = { | 404 | static struct pci_device_id snd_via82xx_ids[] = { |
398 | { 0x1106, 0x3058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */ | 405 | /* 0x1106, 0x3058 */ |
399 | { 0x1106, 0x3059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA8233, }, /* VT8233 */ | 406 | { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */ |
407 | /* 0x1106, 0x3059 */ | ||
408 | { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA8233, }, /* VT8233 */ | ||
400 | { 0, } | 409 | { 0, } |
401 | }; | 410 | }; |
402 | 411 | ||
@@ -550,7 +559,7 @@ static void snd_via82xx_codec_write(ac97_t *ac97, | |||
550 | { | 559 | { |
551 | via82xx_t *chip = ac97->private_data; | 560 | via82xx_t *chip = ac97->private_data; |
552 | unsigned int xval; | 561 | unsigned int xval; |
553 | 562 | ||
554 | xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; | 563 | xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; |
555 | xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; | 564 | xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; |
556 | xval |= reg << VIA_REG_AC97_CMD_SHIFT; | 565 | xval |= reg << VIA_REG_AC97_CMD_SHIFT; |
@@ -598,14 +607,15 @@ static void snd_via82xx_channel_reset(via82xx_t *chip, viadev_t *viadev) | |||
598 | outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ | 607 | outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ |
599 | // outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); | 608 | // outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); |
600 | viadev->lastpos = 0; | 609 | viadev->lastpos = 0; |
610 | viadev->hwptr_done = 0; | ||
601 | } | 611 | } |
602 | 612 | ||
603 | 613 | ||
604 | /* | 614 | /* |
605 | * Interrupt handler | 615 | * Interrupt handler |
616 | * Used for 686 and 8233A | ||
606 | */ | 617 | */ |
607 | 618 | static irqreturn_t snd_via686_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |
608 | static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
609 | { | 619 | { |
610 | via82xx_t *chip = dev_id; | 620 | via82xx_t *chip = dev_id; |
611 | unsigned int status; | 621 | unsigned int status; |
@@ -624,13 +634,23 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs * | |||
624 | for (i = 0; i < chip->num_devs; i++) { | 634 | for (i = 0; i < chip->num_devs; i++) { |
625 | viadev_t *viadev = &chip->devs[i]; | 635 | viadev_t *viadev = &chip->devs[i]; |
626 | unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); | 636 | unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); |
627 | c_status &= (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED); | 637 | if (! (c_status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED))) |
628 | if (! c_status) | ||
629 | continue; | 638 | continue; |
630 | if (viadev->substream && viadev->running) { | 639 | if (viadev->substream && viadev->running) { |
640 | /* | ||
641 | * Update hwptr_done based on 'period elapsed' | ||
642 | * interrupts. We'll use it, when the chip returns 0 | ||
643 | * for OFFSET_CURR_COUNT. | ||
644 | */ | ||
645 | if (c_status & VIA_REG_STAT_EOL) | ||
646 | viadev->hwptr_done = 0; | ||
647 | else | ||
648 | viadev->hwptr_done += viadev->fragsize; | ||
649 | viadev->in_interrupt = c_status; | ||
631 | spin_unlock(&chip->reg_lock); | 650 | spin_unlock(&chip->reg_lock); |
632 | snd_pcm_period_elapsed(viadev->substream); | 651 | snd_pcm_period_elapsed(viadev->substream); |
633 | spin_lock(&chip->reg_lock); | 652 | spin_lock(&chip->reg_lock); |
653 | viadev->in_interrupt = 0; | ||
634 | } | 654 | } |
635 | outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ | 655 | outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ |
636 | } | 656 | } |
@@ -639,6 +659,60 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs * | |||
639 | } | 659 | } |
640 | 660 | ||
641 | /* | 661 | /* |
662 | * Interrupt handler | ||
663 | */ | ||
664 | static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
665 | { | ||
666 | via82xx_t *chip = dev_id; | ||
667 | unsigned int status; | ||
668 | unsigned int i; | ||
669 | int irqreturn = 0; | ||
670 | |||
671 | /* check status for each stream */ | ||
672 | spin_lock(&chip->reg_lock); | ||
673 | status = inl(VIAREG(chip, SGD_SHADOW)); | ||
674 | |||
675 | for (i = 0; i < chip->num_devs; i++) { | ||
676 | viadev_t *viadev = &chip->devs[i]; | ||
677 | snd_pcm_substream_t *substream; | ||
678 | unsigned char c_status, shadow_status; | ||
679 | |||
680 | shadow_status = (status >> viadev->shadow_shift) & | ||
681 | (VIA8233_SHADOW_STAT_ACTIVE|VIA_REG_STAT_EOL| | ||
682 | VIA_REG_STAT_FLAG); | ||
683 | c_status = shadow_status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG); | ||
684 | if (!c_status) | ||
685 | continue; | ||
686 | |||
687 | substream = viadev->substream; | ||
688 | if (substream && viadev->running) { | ||
689 | /* | ||
690 | * Update hwptr_done based on 'period elapsed' | ||
691 | * interrupts. We'll use it, when the chip returns 0 | ||
692 | * for OFFSET_CURR_COUNT. | ||
693 | */ | ||
694 | if (c_status & VIA_REG_STAT_EOL) | ||
695 | viadev->hwptr_done = 0; | ||
696 | else | ||
697 | viadev->hwptr_done += viadev->fragsize; | ||
698 | viadev->in_interrupt = c_status; | ||
699 | if (shadow_status & VIA8233_SHADOW_STAT_ACTIVE) | ||
700 | viadev->in_interrupt |= VIA_REG_STAT_ACTIVE; | ||
701 | spin_unlock(&chip->reg_lock); | ||
702 | |||
703 | snd_pcm_period_elapsed(substream); | ||
704 | |||
705 | spin_lock(&chip->reg_lock); | ||
706 | viadev->in_interrupt = 0; | ||
707 | } | ||
708 | outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ | ||
709 | irqreturn = 1; | ||
710 | } | ||
711 | spin_unlock(&chip->reg_lock); | ||
712 | return IRQ_RETVAL(irqreturn); | ||
713 | } | ||
714 | |||
715 | /* | ||
642 | * PCM callbacks | 716 | * PCM callbacks |
643 | */ | 717 | */ |
644 | 718 | ||
@@ -701,6 +775,8 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u | |||
701 | size = viadev->idx_table[idx].size; | 775 | size = viadev->idx_table[idx].size; |
702 | base = viadev->idx_table[idx].offset; | 776 | base = viadev->idx_table[idx].offset; |
703 | res = base + size - count; | 777 | res = base + size - count; |
778 | if (res >= viadev->bufsize) | ||
779 | res -= viadev->bufsize; | ||
704 | 780 | ||
705 | /* check the validity of the calculated position */ | 781 | /* check the validity of the calculated position */ |
706 | if (size < count) { | 782 | if (size < count) { |
@@ -730,9 +806,6 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u | |||
730 | } | 806 | } |
731 | } | 807 | } |
732 | } | 808 | } |
733 | viadev->lastpos = res; /* remember the last position */ | ||
734 | if (res >= viadev->bufsize) | ||
735 | res -= viadev->bufsize; | ||
736 | return res; | 809 | return res; |
737 | } | 810 | } |
738 | 811 | ||
@@ -760,6 +833,7 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(snd_pcm_substream_t *substream) | |||
760 | else /* CURR_PTR holds the address + 8 */ | 833 | else /* CURR_PTR holds the address + 8 */ |
761 | idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; | 834 | idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; |
762 | res = calc_linear_pos(viadev, idx, count); | 835 | res = calc_linear_pos(viadev, idx, count); |
836 | viadev->lastpos = res; /* remember the last position */ | ||
763 | spin_unlock(&chip->reg_lock); | 837 | spin_unlock(&chip->reg_lock); |
764 | 838 | ||
765 | return bytes_to_frames(substream->runtime, res); | 839 | return bytes_to_frames(substream->runtime, res); |
@@ -773,30 +847,44 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(snd_pcm_substream_t *substream) | |||
773 | via82xx_t *chip = snd_pcm_substream_chip(substream); | 847 | via82xx_t *chip = snd_pcm_substream_chip(substream); |
774 | viadev_t *viadev = (viadev_t *)substream->runtime->private_data; | 848 | viadev_t *viadev = (viadev_t *)substream->runtime->private_data; |
775 | unsigned int idx, count, res; | 849 | unsigned int idx, count, res; |
776 | int timeout = 5000; | 850 | int status; |
777 | 851 | ||
778 | snd_assert(viadev->tbl_entries, return 0); | 852 | snd_assert(viadev->tbl_entries, return 0); |
779 | if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) | 853 | |
780 | return 0; | ||
781 | spin_lock(&chip->reg_lock); | 854 | spin_lock(&chip->reg_lock); |
782 | do { | 855 | count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); |
783 | count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); | 856 | status = viadev->in_interrupt; |
784 | /* some mobos read 0 count */ | 857 | if (!status) |
785 | if ((count & 0xffffff) || ! viadev->running) | 858 | status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); |
786 | break; | 859 | |
787 | } while (--timeout); | 860 | if (!(status & VIA_REG_STAT_ACTIVE)) { |
788 | if (! timeout) | 861 | res = 0; |
789 | snd_printd(KERN_ERR "zero position is read\n"); | 862 | goto unlock; |
790 | idx = count >> 24; | 863 | } |
791 | if (idx >= viadev->tbl_entries) { | 864 | if (count & 0xffffff) { |
865 | idx = count >> 24; | ||
866 | if (idx >= viadev->tbl_entries) { | ||
792 | #ifdef POINTER_DEBUG | 867 | #ifdef POINTER_DEBUG |
793 | printk("fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); | 868 | printk("fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); |
794 | #endif | 869 | #endif |
795 | res = viadev->lastpos; | 870 | res = viadev->lastpos; |
871 | } else { | ||
872 | count &= 0xffffff; | ||
873 | res = calc_linear_pos(viadev, idx, count); | ||
874 | } | ||
796 | } else { | 875 | } else { |
797 | count &= 0xffffff; | 876 | res = viadev->hwptr_done; |
798 | res = calc_linear_pos(viadev, idx, count); | 877 | if (!viadev->in_interrupt) { |
799 | } | 878 | if (status & VIA_REG_STAT_EOL) { |
879 | res = 0; | ||
880 | } else | ||
881 | if (status & VIA_REG_STAT_FLAG) { | ||
882 | res += viadev->fragsize; | ||
883 | } | ||
884 | } | ||
885 | } | ||
886 | unlock: | ||
887 | viadev->lastpos = res; | ||
800 | spin_unlock(&chip->reg_lock); | 888 | spin_unlock(&chip->reg_lock); |
801 | 889 | ||
802 | return bytes_to_frames(substream->runtime, res); | 890 | return bytes_to_frames(substream->runtime, res); |
@@ -1241,9 +1329,10 @@ static snd_pcm_ops_t snd_via8233_capture_ops = { | |||
1241 | }; | 1329 | }; |
1242 | 1330 | ||
1243 | 1331 | ||
1244 | static void init_viadev(via82xx_t *chip, int idx, unsigned int reg_offset, int direction) | 1332 | static void init_viadev(via82xx_t *chip, int idx, unsigned int reg_offset, int shadow_pos, int direction) |
1245 | { | 1333 | { |
1246 | chip->devs[idx].reg_offset = reg_offset; | 1334 | chip->devs[idx].reg_offset = reg_offset; |
1335 | chip->devs[idx].shadow_shift = shadow_pos * 4; | ||
1247 | chip->devs[idx].direction = direction; | 1336 | chip->devs[idx].direction = direction; |
1248 | chip->devs[idx].port = chip->port + reg_offset; | 1337 | chip->devs[idx].port = chip->port + reg_offset; |
1249 | } | 1338 | } |
@@ -1273,9 +1362,9 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip) | |||
1273 | chip->pcms[0] = pcm; | 1362 | chip->pcms[0] = pcm; |
1274 | /* set up playbacks */ | 1363 | /* set up playbacks */ |
1275 | for (i = 0; i < 4; i++) | 1364 | for (i = 0; i < 4; i++) |
1276 | init_viadev(chip, i, 0x10 * i, 0); | 1365 | init_viadev(chip, i, 0x10 * i, i, 0); |
1277 | /* capture */ | 1366 | /* capture */ |
1278 | init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 1); | 1367 | init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1); |
1279 | 1368 | ||
1280 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1369 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1281 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1370 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1291,9 +1380,9 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip) | |||
1291 | strcpy(pcm->name, chip->card->shortname); | 1380 | strcpy(pcm->name, chip->card->shortname); |
1292 | chip->pcms[1] = pcm; | 1381 | chip->pcms[1] = pcm; |
1293 | /* set up playback */ | 1382 | /* set up playback */ |
1294 | init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 0); | 1383 | init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0); |
1295 | /* set up capture */ | 1384 | /* set up capture */ |
1296 | init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 1); | 1385 | init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 7, 1); |
1297 | 1386 | ||
1298 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1387 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1299 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1388 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1326,9 +1415,9 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip) | |||
1326 | strcpy(pcm->name, chip->card->shortname); | 1415 | strcpy(pcm->name, chip->card->shortname); |
1327 | chip->pcms[0] = pcm; | 1416 | chip->pcms[0] = pcm; |
1328 | /* set up playback */ | 1417 | /* set up playback */ |
1329 | init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 0); | 1418 | init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0); |
1330 | /* capture */ | 1419 | /* capture */ |
1331 | init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 1); | 1420 | init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1); |
1332 | 1421 | ||
1333 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1422 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1334 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1423 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1347,7 +1436,7 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip) | |||
1347 | strcpy(pcm->name, chip->card->shortname); | 1436 | strcpy(pcm->name, chip->card->shortname); |
1348 | chip->pcms[1] = pcm; | 1437 | chip->pcms[1] = pcm; |
1349 | /* set up playback */ | 1438 | /* set up playback */ |
1350 | init_viadev(chip, chip->playback_devno, 0x30, 0); | 1439 | init_viadev(chip, chip->playback_devno, 0x30, 3, 0); |
1351 | 1440 | ||
1352 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1441 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1353 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1442 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1377,8 +1466,8 @@ static int __devinit snd_via686_pcm_new(via82xx_t *chip) | |||
1377 | pcm->private_data = chip; | 1466 | pcm->private_data = chip; |
1378 | strcpy(pcm->name, chip->card->shortname); | 1467 | strcpy(pcm->name, chip->card->shortname); |
1379 | chip->pcms[0] = pcm; | 1468 | chip->pcms[0] = pcm; |
1380 | init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0); | 1469 | init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0, 0); |
1381 | init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 1); | 1470 | init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 0, 1); |
1382 | 1471 | ||
1383 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1472 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1384 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1473 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -2134,7 +2223,10 @@ static int __devinit snd_via82xx_create(snd_card_t * card, | |||
2134 | return err; | 2223 | return err; |
2135 | } | 2224 | } |
2136 | chip->port = pci_resource_start(pci, 0); | 2225 | chip->port = pci_resource_start(pci, 0); |
2137 | if (request_irq(pci->irq, snd_via82xx_interrupt, SA_INTERRUPT|SA_SHIRQ, | 2226 | if (request_irq(pci->irq, |
2227 | chip_type == TYPE_VIA8233 ? | ||
2228 | snd_via8233_interrupt : snd_via686_interrupt, | ||
2229 | SA_INTERRUPT|SA_SHIRQ, | ||
2138 | card->driver, (void *)chip)) { | 2230 | card->driver, (void *)chip)) { |
2139 | snd_printk("unable to grab IRQ %d\n", pci->irq); | 2231 | snd_printk("unable to grab IRQ %d\n", pci->irq); |
2140 | snd_via82xx_free(chip); | 2232 | snd_via82xx_free(chip); |