diff options
Diffstat (limited to 'sound/pci/via82xx.c')
-rw-r--r-- | sound/pci/via82xx.c | 375 |
1 files changed, 254 insertions, 121 deletions
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 3c0205b91e10..523eace250f7 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> |
@@ -73,36 +76,37 @@ MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}"); | |||
73 | #define SUPPORT_JOYSTICK 1 | 76 | #define SUPPORT_JOYSTICK 1 |
74 | #endif | 77 | #endif |
75 | 78 | ||
76 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 79 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ |
77 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 80 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ |
78 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 81 | static long mpu_port; |
79 | static long mpu_port[SNDRV_CARDS]; | ||
80 | #ifdef SUPPORT_JOYSTICK | 82 | #ifdef SUPPORT_JOYSTICK |
81 | static int joystick[SNDRV_CARDS]; | 83 | static int joystick; |
82 | #endif | 84 | #endif |
83 | static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; | 85 | static int ac97_clock = 48000; |
84 | static char *ac97_quirk[SNDRV_CARDS]; | 86 | static char *ac97_quirk; |
85 | static int dxs_support[SNDRV_CARDS]; | 87 | static int dxs_support; |
86 | 88 | ||
87 | module_param_array(index, int, NULL, 0444); | 89 | module_param(index, int, 0444); |
88 | MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge."); | 90 | MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge."); |
89 | module_param_array(id, charp, NULL, 0444); | 91 | module_param(id, charp, 0444); |
90 | MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge."); | 92 | MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge."); |
91 | module_param_array(enable, bool, NULL, 0444); | 93 | module_param(mpu_port, long, 0444); |
92 | MODULE_PARM_DESC(enable, "Enable audio part of VIA 82xx bridge."); | ||
93 | module_param_array(mpu_port, long, NULL, 0444); | ||
94 | MODULE_PARM_DESC(mpu_port, "MPU-401 port. (VT82C686x only)"); | 94 | MODULE_PARM_DESC(mpu_port, "MPU-401 port. (VT82C686x only)"); |
95 | #ifdef SUPPORT_JOYSTICK | 95 | #ifdef SUPPORT_JOYSTICK |
96 | module_param_array(joystick, bool, NULL, 0444); | 96 | module_param(joystick, bool, 0444); |
97 | MODULE_PARM_DESC(joystick, "Enable joystick. (VT82C686x only)"); | 97 | MODULE_PARM_DESC(joystick, "Enable joystick. (VT82C686x only)"); |
98 | #endif | 98 | #endif |
99 | module_param_array(ac97_clock, int, NULL, 0444); | 99 | module_param(ac97_clock, int, 0444); |
100 | MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); | 100 | MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); |
101 | module_param_array(ac97_quirk, charp, NULL, 0444); | 101 | module_param(ac97_quirk, charp, 0444); |
102 | MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); | 102 | MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); |
103 | module_param_array(dxs_support, int, NULL, 0444); | 103 | module_param(dxs_support, int, 0444); |
104 | MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); | 104 | MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); |
105 | 105 | ||
106 | /* just for backward compatibility */ | ||
107 | static int enable; | ||
108 | module_param(enable, bool, 0444); | ||
109 | |||
106 | 110 | ||
107 | /* revision numbers for via686 */ | 111 | /* revision numbers for via686 */ |
108 | #define VIA_REV_686_A 0x10 | 112 | #define VIA_REV_686_A 0x10 |
@@ -130,6 +134,7 @@ MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 | |||
130 | /* common offsets */ | 134 | /* common offsets */ |
131 | #define VIA_REG_OFFSET_STATUS 0x00 /* byte - channel status */ | 135 | #define VIA_REG_OFFSET_STATUS 0x00 /* byte - channel status */ |
132 | #define VIA_REG_STAT_ACTIVE 0x80 /* RO */ | 136 | #define VIA_REG_STAT_ACTIVE 0x80 /* RO */ |
137 | #define VIA8233_SHADOW_STAT_ACTIVE 0x08 /* RO */ | ||
133 | #define VIA_REG_STAT_PAUSED 0x40 /* RO */ | 138 | #define VIA_REG_STAT_PAUSED 0x40 /* RO */ |
134 | #define VIA_REG_STAT_TRIGGER_QUEUED 0x08 /* RO */ | 139 | #define VIA_REG_STAT_TRIGGER_QUEUED 0x08 /* RO */ |
135 | #define VIA_REG_STAT_STOPPED 0x04 /* RWC */ | 140 | #define VIA_REG_STAT_STOPPED 0x04 /* RWC */ |
@@ -328,6 +333,9 @@ struct via_dev { | |||
328 | unsigned int fragsize; | 333 | unsigned int fragsize; |
329 | unsigned int bufsize; | 334 | unsigned int bufsize; |
330 | 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; | ||
331 | }; | 339 | }; |
332 | 340 | ||
333 | 341 | ||
@@ -360,7 +368,8 @@ struct _snd_via82xx { | |||
360 | unsigned int mpu_port_saved; | 368 | unsigned int mpu_port_saved; |
361 | #endif | 369 | #endif |
362 | 370 | ||
363 | unsigned char playback_volume[2]; /* for VIA8233/C/8235; default = 0 */ | 371 | unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */ |
372 | unsigned char playback_volume_c[2]; /* for VIA8233/C/8235; default = 0 */ | ||
364 | 373 | ||
365 | unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */ | 374 | unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */ |
366 | 375 | ||
@@ -393,8 +402,10 @@ struct _snd_via82xx { | |||
393 | }; | 402 | }; |
394 | 403 | ||
395 | static struct pci_device_id snd_via82xx_ids[] = { | 404 | static struct pci_device_id snd_via82xx_ids[] = { |
396 | { 0x1106, 0x3058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */ | 405 | /* 0x1106, 0x3058 */ |
397 | { 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 */ | ||
398 | { 0, } | 409 | { 0, } |
399 | }; | 410 | }; |
400 | 411 | ||
@@ -548,7 +559,7 @@ static void snd_via82xx_codec_write(ac97_t *ac97, | |||
548 | { | 559 | { |
549 | via82xx_t *chip = ac97->private_data; | 560 | via82xx_t *chip = ac97->private_data; |
550 | unsigned int xval; | 561 | unsigned int xval; |
551 | 562 | ||
552 | 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; |
553 | xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; | 564 | xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; |
554 | xval |= reg << VIA_REG_AC97_CMD_SHIFT; | 565 | xval |= reg << VIA_REG_AC97_CMD_SHIFT; |
@@ -596,14 +607,15 @@ static void snd_via82xx_channel_reset(via82xx_t *chip, viadev_t *viadev) | |||
596 | outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ | 607 | outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ |
597 | // outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); | 608 | // outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); |
598 | viadev->lastpos = 0; | 609 | viadev->lastpos = 0; |
610 | viadev->hwptr_done = 0; | ||
599 | } | 611 | } |
600 | 612 | ||
601 | 613 | ||
602 | /* | 614 | /* |
603 | * Interrupt handler | 615 | * Interrupt handler |
616 | * Used for 686 and 8233A | ||
604 | */ | 617 | */ |
605 | 618 | static irqreturn_t snd_via686_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |
606 | static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
607 | { | 619 | { |
608 | via82xx_t *chip = dev_id; | 620 | via82xx_t *chip = dev_id; |
609 | unsigned int status; | 621 | unsigned int status; |
@@ -622,13 +634,23 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs * | |||
622 | for (i = 0; i < chip->num_devs; i++) { | 634 | for (i = 0; i < chip->num_devs; i++) { |
623 | viadev_t *viadev = &chip->devs[i]; | 635 | viadev_t *viadev = &chip->devs[i]; |
624 | unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); | 636 | unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); |
625 | 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))) |
626 | if (! c_status) | ||
627 | continue; | 638 | continue; |
628 | 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; | ||
629 | spin_unlock(&chip->reg_lock); | 650 | spin_unlock(&chip->reg_lock); |
630 | snd_pcm_period_elapsed(viadev->substream); | 651 | snd_pcm_period_elapsed(viadev->substream); |
631 | spin_lock(&chip->reg_lock); | 652 | spin_lock(&chip->reg_lock); |
653 | viadev->in_interrupt = 0; | ||
632 | } | 654 | } |
633 | outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ | 655 | outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ |
634 | } | 656 | } |
@@ -637,6 +659,60 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs * | |||
637 | } | 659 | } |
638 | 660 | ||
639 | /* | 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 | /* | ||
640 | * PCM callbacks | 716 | * PCM callbacks |
641 | */ | 717 | */ |
642 | 718 | ||
@@ -699,6 +775,8 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u | |||
699 | size = viadev->idx_table[idx].size; | 775 | size = viadev->idx_table[idx].size; |
700 | base = viadev->idx_table[idx].offset; | 776 | base = viadev->idx_table[idx].offset; |
701 | res = base + size - count; | 777 | res = base + size - count; |
778 | if (res >= viadev->bufsize) | ||
779 | res -= viadev->bufsize; | ||
702 | 780 | ||
703 | /* check the validity of the calculated position */ | 781 | /* check the validity of the calculated position */ |
704 | if (size < count) { | 782 | if (size < count) { |
@@ -728,9 +806,6 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u | |||
728 | } | 806 | } |
729 | } | 807 | } |
730 | } | 808 | } |
731 | viadev->lastpos = res; /* remember the last position */ | ||
732 | if (res >= viadev->bufsize) | ||
733 | res -= viadev->bufsize; | ||
734 | return res; | 809 | return res; |
735 | } | 810 | } |
736 | 811 | ||
@@ -758,6 +833,7 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(snd_pcm_substream_t *substream) | |||
758 | else /* CURR_PTR holds the address + 8 */ | 833 | else /* CURR_PTR holds the address + 8 */ |
759 | 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; |
760 | res = calc_linear_pos(viadev, idx, count); | 835 | res = calc_linear_pos(viadev, idx, count); |
836 | viadev->lastpos = res; /* remember the last position */ | ||
761 | spin_unlock(&chip->reg_lock); | 837 | spin_unlock(&chip->reg_lock); |
762 | 838 | ||
763 | return bytes_to_frames(substream->runtime, res); | 839 | return bytes_to_frames(substream->runtime, res); |
@@ -771,30 +847,44 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(snd_pcm_substream_t *substream) | |||
771 | via82xx_t *chip = snd_pcm_substream_chip(substream); | 847 | via82xx_t *chip = snd_pcm_substream_chip(substream); |
772 | viadev_t *viadev = (viadev_t *)substream->runtime->private_data; | 848 | viadev_t *viadev = (viadev_t *)substream->runtime->private_data; |
773 | unsigned int idx, count, res; | 849 | unsigned int idx, count, res; |
774 | int timeout = 5000; | 850 | int status; |
775 | 851 | ||
776 | snd_assert(viadev->tbl_entries, return 0); | 852 | snd_assert(viadev->tbl_entries, return 0); |
777 | if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) | 853 | |
778 | return 0; | ||
779 | spin_lock(&chip->reg_lock); | 854 | spin_lock(&chip->reg_lock); |
780 | do { | 855 | count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); |
781 | count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); | 856 | status = viadev->in_interrupt; |
782 | /* some mobos read 0 count */ | 857 | if (!status) |
783 | if ((count & 0xffffff) || ! viadev->running) | 858 | status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); |
784 | break; | 859 | |
785 | } while (--timeout); | 860 | if (!(status & VIA_REG_STAT_ACTIVE)) { |
786 | if (! timeout) | 861 | res = 0; |
787 | snd_printd(KERN_ERR "zero position is read\n"); | 862 | goto unlock; |
788 | idx = count >> 24; | 863 | } |
789 | if (idx >= viadev->tbl_entries) { | 864 | if (count & 0xffffff) { |
865 | idx = count >> 24; | ||
866 | if (idx >= viadev->tbl_entries) { | ||
790 | #ifdef POINTER_DEBUG | 867 | #ifdef POINTER_DEBUG |
791 | printk("fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); | 868 | printk(KERN_DEBUG "fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); |
792 | #endif | 869 | #endif |
793 | res = viadev->lastpos; | 870 | res = viadev->lastpos; |
871 | } else { | ||
872 | count &= 0xffffff; | ||
873 | res = calc_linear_pos(viadev, idx, count); | ||
874 | } | ||
794 | } else { | 875 | } else { |
795 | count &= 0xffffff; | 876 | res = viadev->hwptr_done; |
796 | res = calc_linear_pos(viadev, idx, count); | 877 | if (!viadev->in_interrupt) { |
797 | } | 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; | ||
798 | spin_unlock(&chip->reg_lock); | 888 | spin_unlock(&chip->reg_lock); |
799 | 889 | ||
800 | return bytes_to_frames(substream->runtime, res); | 890 | return bytes_to_frames(substream->runtime, res); |
@@ -936,8 +1026,8 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream) | |||
936 | snd_assert((rbits & ~0xfffff) == 0, return -EINVAL); | 1026 | snd_assert((rbits & ~0xfffff) == 0, return -EINVAL); |
937 | snd_via82xx_channel_reset(chip, viadev); | 1027 | snd_via82xx_channel_reset(chip, viadev); |
938 | snd_via82xx_set_table_ptr(chip, viadev); | 1028 | snd_via82xx_set_table_ptr(chip, viadev); |
939 | outb(chip->playback_volume[0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); | 1029 | outb(chip->playback_volume[viadev->reg_offset / 0x10][0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); |
940 | outb(chip->playback_volume[1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); | 1030 | outb(chip->playback_volume[viadev->reg_offset / 0x10][1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); |
941 | outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */ | 1031 | outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */ |
942 | (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */ | 1032 | (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */ |
943 | rbits | /* rate */ | 1033 | rbits | /* rate */ |
@@ -1239,9 +1329,10 @@ static snd_pcm_ops_t snd_via8233_capture_ops = { | |||
1239 | }; | 1329 | }; |
1240 | 1330 | ||
1241 | 1331 | ||
1242 | 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) |
1243 | { | 1333 | { |
1244 | chip->devs[idx].reg_offset = reg_offset; | 1334 | chip->devs[idx].reg_offset = reg_offset; |
1335 | chip->devs[idx].shadow_shift = shadow_pos * 4; | ||
1245 | chip->devs[idx].direction = direction; | 1336 | chip->devs[idx].direction = direction; |
1246 | chip->devs[idx].port = chip->port + reg_offset; | 1337 | chip->devs[idx].port = chip->port + reg_offset; |
1247 | } | 1338 | } |
@@ -1271,9 +1362,9 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip) | |||
1271 | chip->pcms[0] = pcm; | 1362 | chip->pcms[0] = pcm; |
1272 | /* set up playbacks */ | 1363 | /* set up playbacks */ |
1273 | for (i = 0; i < 4; i++) | 1364 | for (i = 0; i < 4; i++) |
1274 | init_viadev(chip, i, 0x10 * i, 0); | 1365 | init_viadev(chip, i, 0x10 * i, i, 0); |
1275 | /* capture */ | 1366 | /* capture */ |
1276 | 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); |
1277 | 1368 | ||
1278 | 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, |
1279 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1370 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1289,9 +1380,9 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip) | |||
1289 | strcpy(pcm->name, chip->card->shortname); | 1380 | strcpy(pcm->name, chip->card->shortname); |
1290 | chip->pcms[1] = pcm; | 1381 | chip->pcms[1] = pcm; |
1291 | /* set up playback */ | 1382 | /* set up playback */ |
1292 | init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 0); | 1383 | init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0); |
1293 | /* set up capture */ | 1384 | /* set up capture */ |
1294 | 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); |
1295 | 1386 | ||
1296 | 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, |
1297 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1388 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1324,9 +1415,9 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip) | |||
1324 | strcpy(pcm->name, chip->card->shortname); | 1415 | strcpy(pcm->name, chip->card->shortname); |
1325 | chip->pcms[0] = pcm; | 1416 | chip->pcms[0] = pcm; |
1326 | /* set up playback */ | 1417 | /* set up playback */ |
1327 | init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 0); | 1418 | init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0); |
1328 | /* capture */ | 1419 | /* capture */ |
1329 | 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); |
1330 | 1421 | ||
1331 | 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, |
1332 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1423 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1345,7 +1436,7 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip) | |||
1345 | strcpy(pcm->name, chip->card->shortname); | 1436 | strcpy(pcm->name, chip->card->shortname); |
1346 | chip->pcms[1] = pcm; | 1437 | chip->pcms[1] = pcm; |
1347 | /* set up playback */ | 1438 | /* set up playback */ |
1348 | init_viadev(chip, chip->playback_devno, 0x30, 0); | 1439 | init_viadev(chip, chip->playback_devno, 0x30, 3, 0); |
1349 | 1440 | ||
1350 | 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, |
1351 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1442 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1375,8 +1466,8 @@ static int __devinit snd_via686_pcm_new(via82xx_t *chip) | |||
1375 | pcm->private_data = chip; | 1466 | pcm->private_data = chip; |
1376 | strcpy(pcm->name, chip->card->shortname); | 1467 | strcpy(pcm->name, chip->card->shortname); |
1377 | chip->pcms[0] = pcm; | 1468 | chip->pcms[0] = pcm; |
1378 | init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0); | 1469 | init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0, 0); |
1379 | init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 1); | 1470 | init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 0, 1); |
1380 | 1471 | ||
1381 | 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, |
1382 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) | 1473 | snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) |
@@ -1497,14 +1588,46 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in | |||
1497 | static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 1588 | static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
1498 | { | 1589 | { |
1499 | via82xx_t *chip = snd_kcontrol_chip(kcontrol); | 1590 | via82xx_t *chip = snd_kcontrol_chip(kcontrol); |
1500 | ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[0]; | 1591 | unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id); |
1501 | ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[1]; | 1592 | |
1593 | ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0]; | ||
1594 | ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1]; | ||
1595 | return 0; | ||
1596 | } | ||
1597 | |||
1598 | static int snd_via8233_pcmdxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1599 | { | ||
1600 | via82xx_t *chip = snd_kcontrol_chip(kcontrol); | ||
1601 | ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[0]; | ||
1602 | ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[1]; | ||
1502 | return 0; | 1603 | return 0; |
1503 | } | 1604 | } |
1504 | 1605 | ||
1505 | static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 1606 | static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
1506 | { | 1607 | { |
1507 | via82xx_t *chip = snd_kcontrol_chip(kcontrol); | 1608 | via82xx_t *chip = snd_kcontrol_chip(kcontrol); |
1609 | unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id); | ||
1610 | unsigned long port = chip->port + 0x10 * idx; | ||
1611 | unsigned char val; | ||
1612 | int i, change = 0; | ||
1613 | |||
1614 | for (i = 0; i < 2; i++) { | ||
1615 | val = ucontrol->value.integer.value[i]; | ||
1616 | if (val > VIA_DXS_MAX_VOLUME) | ||
1617 | val = VIA_DXS_MAX_VOLUME; | ||
1618 | val = VIA_DXS_MAX_VOLUME - val; | ||
1619 | change |= val != chip->playback_volume[idx][i]; | ||
1620 | if (change) { | ||
1621 | chip->playback_volume[idx][i] = val; | ||
1622 | outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); | ||
1623 | } | ||
1624 | } | ||
1625 | return change; | ||
1626 | } | ||
1627 | |||
1628 | static int snd_via8233_pcmdxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1629 | { | ||
1630 | via82xx_t *chip = snd_kcontrol_chip(kcontrol); | ||
1508 | unsigned int idx; | 1631 | unsigned int idx; |
1509 | unsigned char val; | 1632 | unsigned char val; |
1510 | int i, change = 0; | 1633 | int i, change = 0; |
@@ -1514,11 +1637,12 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val | |||
1514 | if (val > VIA_DXS_MAX_VOLUME) | 1637 | if (val > VIA_DXS_MAX_VOLUME) |
1515 | val = VIA_DXS_MAX_VOLUME; | 1638 | val = VIA_DXS_MAX_VOLUME; |
1516 | val = VIA_DXS_MAX_VOLUME - val; | 1639 | val = VIA_DXS_MAX_VOLUME - val; |
1517 | if (val != chip->playback_volume[i]) { | 1640 | if (val != chip->playback_volume_c[i]) { |
1518 | change = 1; | 1641 | change = 1; |
1519 | chip->playback_volume[i] = val; | 1642 | chip->playback_volume_c[i] = val; |
1520 | for (idx = 0; idx < 4; idx++) { | 1643 | for (idx = 0; idx < 4; idx++) { |
1521 | unsigned long port = chip->port + 0x10 * idx; | 1644 | unsigned long port = chip->port + 0x10 * idx; |
1645 | chip->playback_volume[idx][i] = val; | ||
1522 | outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); | 1646 | outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); |
1523 | } | 1647 | } |
1524 | } | 1648 | } |
@@ -1526,10 +1650,19 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val | |||
1526 | return change; | 1650 | return change; |
1527 | } | 1651 | } |
1528 | 1652 | ||
1529 | static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = { | 1653 | static snd_kcontrol_new_t snd_via8233_pcmdxs_volume_control __devinitdata = { |
1530 | .name = "PCM Playback Volume", | 1654 | .name = "PCM Playback Volume", |
1531 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1655 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1532 | .info = snd_via8233_dxs_volume_info, | 1656 | .info = snd_via8233_dxs_volume_info, |
1657 | .get = snd_via8233_pcmdxs_volume_get, | ||
1658 | .put = snd_via8233_pcmdxs_volume_put, | ||
1659 | }; | ||
1660 | |||
1661 | static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = { | ||
1662 | .name = "VIA DXS Playback Volume", | ||
1663 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1664 | .count = 4, | ||
1665 | .info = snd_via8233_dxs_volume_info, | ||
1533 | .get = snd_via8233_dxs_volume_get, | 1666 | .get = snd_via8233_dxs_volume_get, |
1534 | .put = snd_via8233_dxs_volume_put, | 1667 | .put = snd_via8233_dxs_volume_put, |
1535 | }; | 1668 | }; |
@@ -1616,12 +1749,12 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_ov | |||
1616 | return err; | 1749 | return err; |
1617 | chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; | 1750 | chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; |
1618 | chip->ac97_bus->clock = chip->ac97_clock; | 1751 | chip->ac97_bus->clock = chip->ac97_clock; |
1619 | chip->ac97_bus->shared_type = AC97_SHARED_TYPE_VIA; | ||
1620 | 1752 | ||
1621 | memset(&ac97, 0, sizeof(ac97)); | 1753 | memset(&ac97, 0, sizeof(ac97)); |
1622 | ac97.private_data = chip; | 1754 | ac97.private_data = chip; |
1623 | ac97.private_free = snd_via82xx_mixer_free_ac97; | 1755 | ac97.private_free = snd_via82xx_mixer_free_ac97; |
1624 | ac97.pci = chip->pci; | 1756 | ac97.pci = chip->pci; |
1757 | ac97.scaps = AC97_SCAP_SKIP_MODEM; | ||
1625 | if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) | 1758 | if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) |
1626 | return err; | 1759 | return err; |
1627 | 1760 | ||
@@ -1637,12 +1770,12 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_ov | |||
1637 | 1770 | ||
1638 | #ifdef SUPPORT_JOYSTICK | 1771 | #ifdef SUPPORT_JOYSTICK |
1639 | #define JOYSTICK_ADDR 0x200 | 1772 | #define JOYSTICK_ADDR 0x200 |
1640 | static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy) | 1773 | static int __devinit snd_via686_create_gameport(via82xx_t *chip, unsigned char *legacy) |
1641 | { | 1774 | { |
1642 | struct gameport *gp; | 1775 | struct gameport *gp; |
1643 | struct resource *r; | 1776 | struct resource *r; |
1644 | 1777 | ||
1645 | if (!joystick[dev]) | 1778 | if (!joystick) |
1646 | return -ENODEV; | 1779 | return -ENODEV; |
1647 | 1780 | ||
1648 | r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport"); | 1781 | r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport"); |
@@ -1654,8 +1787,7 @@ static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsign | |||
1654 | chip->gameport = gp = gameport_allocate_port(); | 1787 | chip->gameport = gp = gameport_allocate_port(); |
1655 | if (!gp) { | 1788 | if (!gp) { |
1656 | printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n"); | 1789 | printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n"); |
1657 | release_resource(r); | 1790 | release_and_free_resource(r); |
1658 | kfree_nocheck(r); | ||
1659 | return -ENOMEM; | 1791 | return -ENOMEM; |
1660 | } | 1792 | } |
1661 | 1793 | ||
@@ -1681,12 +1813,11 @@ static void snd_via686_free_gameport(via82xx_t *chip) | |||
1681 | 1813 | ||
1682 | gameport_unregister_port(chip->gameport); | 1814 | gameport_unregister_port(chip->gameport); |
1683 | chip->gameport = NULL; | 1815 | chip->gameport = NULL; |
1684 | release_resource(r); | 1816 | release_and_free_resource(r); |
1685 | kfree_nocheck(r); | ||
1686 | } | 1817 | } |
1687 | } | 1818 | } |
1688 | #else | 1819 | #else |
1689 | static inline int snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy) | 1820 | static inline int snd_via686_create_gameport(via82xx_t *chip, unsigned char *legacy) |
1690 | { | 1821 | { |
1691 | return -ENOSYS; | 1822 | return -ENOSYS; |
1692 | } | 1823 | } |
@@ -1698,7 +1829,7 @@ static inline void snd_via686_free_gameport(via82xx_t *chip) { } | |||
1698 | * | 1829 | * |
1699 | */ | 1830 | */ |
1700 | 1831 | ||
1701 | static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev) | 1832 | static int __devinit snd_via8233_init_misc(via82xx_t *chip) |
1702 | { | 1833 | { |
1703 | int i, err, caps; | 1834 | int i, err, caps; |
1704 | unsigned char val; | 1835 | unsigned char val; |
@@ -1724,12 +1855,19 @@ static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev) | |||
1724 | strcpy(sid.name, "PCM Playback Volume"); | 1855 | strcpy(sid.name, "PCM Playback Volume"); |
1725 | sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 1856 | sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
1726 | if (! snd_ctl_find_id(chip->card, &sid)) { | 1857 | if (! snd_ctl_find_id(chip->card, &sid)) { |
1858 | snd_printd(KERN_INFO "Using DXS as PCM Playback\n"); | ||
1859 | err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_pcmdxs_volume_control, chip)); | ||
1860 | if (err < 0) | ||
1861 | return err; | ||
1862 | } | ||
1863 | else /* Using DXS when PCM emulation is enabled is really weird */ | ||
1864 | { | ||
1865 | /* Standalone DXS controls */ | ||
1727 | err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip)); | 1866 | err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip)); |
1728 | if (err < 0) | 1867 | if (err < 0) |
1729 | return err; | 1868 | return err; |
1730 | } | 1869 | } |
1731 | } | 1870 | } |
1732 | |||
1733 | /* select spdif data slot 10/11 */ | 1871 | /* select spdif data slot 10/11 */ |
1734 | pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val); | 1872 | pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val); |
1735 | val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011; | 1873 | val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011; |
@@ -1739,7 +1877,7 @@ static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev) | |||
1739 | return 0; | 1877 | return 0; |
1740 | } | 1878 | } |
1741 | 1879 | ||
1742 | static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) | 1880 | static int __devinit snd_via686_init_misc(via82xx_t *chip) |
1743 | { | 1881 | { |
1744 | unsigned char legacy, legacy_cfg; | 1882 | unsigned char legacy, legacy_cfg; |
1745 | int rev_h = 0; | 1883 | int rev_h = 0; |
@@ -1750,32 +1888,33 @@ static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) | |||
1750 | legacy &= ~VIA_FUNC_ENABLE_GAME; /* disable joystick */ | 1888 | legacy &= ~VIA_FUNC_ENABLE_GAME; /* disable joystick */ |
1751 | if (chip->revision >= VIA_REV_686_H) { | 1889 | if (chip->revision >= VIA_REV_686_H) { |
1752 | rev_h = 1; | 1890 | rev_h = 1; |
1753 | if (mpu_port[dev] >= 0x200) { /* force MIDI */ | 1891 | if (mpu_port >= 0x200) { /* force MIDI */ |
1754 | mpu_port[dev] &= 0xfffc; | 1892 | mpu_port &= 0xfffc; |
1755 | pci_write_config_dword(chip->pci, 0x18, mpu_port[dev] | 0x01); | 1893 | pci_write_config_dword(chip->pci, 0x18, mpu_port | 0x01); |
1756 | #ifdef CONFIG_PM | 1894 | #ifdef CONFIG_PM |
1757 | chip->mpu_port_saved = mpu_port[dev]; | 1895 | chip->mpu_port_saved = mpu_port; |
1758 | #endif | 1896 | #endif |
1759 | } else { | 1897 | } else { |
1760 | mpu_port[dev] = pci_resource_start(chip->pci, 2); | 1898 | mpu_port = pci_resource_start(chip->pci, 2); |
1761 | } | 1899 | } |
1762 | } else { | 1900 | } else { |
1763 | switch (mpu_port[dev]) { /* force MIDI */ | 1901 | switch (mpu_port) { /* force MIDI */ |
1764 | case 0x300: | 1902 | case 0x300: |
1765 | case 0x310: | 1903 | case 0x310: |
1766 | case 0x320: | 1904 | case 0x320: |
1767 | case 0x330: | 1905 | case 0x330: |
1768 | legacy_cfg &= ~(3 << 2); | 1906 | legacy_cfg &= ~(3 << 2); |
1769 | legacy_cfg |= (mpu_port[dev] & 0x0030) >> 2; | 1907 | legacy_cfg |= (mpu_port & 0x0030) >> 2; |
1770 | break; | 1908 | break; |
1771 | default: /* no, use BIOS settings */ | 1909 | default: /* no, use BIOS settings */ |
1772 | if (legacy & VIA_FUNC_ENABLE_MIDI) | 1910 | if (legacy & VIA_FUNC_ENABLE_MIDI) |
1773 | mpu_port[dev] = 0x300 + ((legacy_cfg & 0x000c) << 2); | 1911 | mpu_port = 0x300 + ((legacy_cfg & 0x000c) << 2); |
1774 | break; | 1912 | break; |
1775 | } | 1913 | } |
1776 | } | 1914 | } |
1777 | if (mpu_port[dev] >= 0x200 && | 1915 | if (mpu_port >= 0x200 && |
1778 | (chip->mpu_res = request_region(mpu_port[dev], 2, "VIA82xx MPU401")) != NULL) { | 1916 | (chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401")) |
1917 | != NULL) { | ||
1779 | if (rev_h) | 1918 | if (rev_h) |
1780 | legacy |= VIA_FUNC_MIDI_PNP; /* enable PCI I/O 2 */ | 1919 | legacy |= VIA_FUNC_MIDI_PNP; /* enable PCI I/O 2 */ |
1781 | legacy |= VIA_FUNC_ENABLE_MIDI; | 1920 | legacy |= VIA_FUNC_ENABLE_MIDI; |
@@ -1783,16 +1922,17 @@ static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) | |||
1783 | if (rev_h) | 1922 | if (rev_h) |
1784 | legacy &= ~VIA_FUNC_MIDI_PNP; /* disable PCI I/O 2 */ | 1923 | legacy &= ~VIA_FUNC_MIDI_PNP; /* disable PCI I/O 2 */ |
1785 | legacy &= ~VIA_FUNC_ENABLE_MIDI; | 1924 | legacy &= ~VIA_FUNC_ENABLE_MIDI; |
1786 | mpu_port[dev] = 0; | 1925 | mpu_port = 0; |
1787 | } | 1926 | } |
1788 | 1927 | ||
1789 | pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); | 1928 | pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); |
1790 | pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); | 1929 | pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); |
1791 | if (chip->mpu_res) { | 1930 | if (chip->mpu_res) { |
1792 | if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, | 1931 | if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, |
1793 | mpu_port[dev], 1, | 1932 | mpu_port, 1, |
1794 | chip->irq, 0, &chip->rmidi) < 0) { | 1933 | chip->irq, 0, &chip->rmidi) < 0) { |
1795 | printk(KERN_WARNING "unable to initialize MPU-401 at 0x%lx, skipping\n", mpu_port[dev]); | 1934 | printk(KERN_WARNING "unable to initialize MPU-401" |
1935 | " at 0x%lx, skipping\n", mpu_port); | ||
1796 | legacy &= ~VIA_FUNC_ENABLE_MIDI; | 1936 | legacy &= ~VIA_FUNC_ENABLE_MIDI; |
1797 | } else { | 1937 | } else { |
1798 | legacy &= ~VIA_FUNC_MIDI_IRQMASK; /* enable MIDI interrupt */ | 1938 | legacy &= ~VIA_FUNC_MIDI_IRQMASK; /* enable MIDI interrupt */ |
@@ -1800,7 +1940,7 @@ static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) | |||
1800 | pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); | 1940 | pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); |
1801 | } | 1941 | } |
1802 | 1942 | ||
1803 | snd_via686_create_gameport(chip, dev, &legacy); | 1943 | snd_via686_create_gameport(chip, &legacy); |
1804 | 1944 | ||
1805 | #ifdef CONFIG_PM | 1945 | #ifdef CONFIG_PM |
1806 | chip->legacy_saved = legacy; | 1946 | chip->legacy_saved = legacy; |
@@ -1887,12 +2027,11 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1887 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 2027 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
1888 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 2028 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
1889 | break; | 2029 | break; |
1890 | set_current_state(TASK_UNINTERRUPTIBLE); | 2030 | schedule_timeout_uninterruptible(1); |
1891 | schedule_timeout(1); | ||
1892 | } while (time_before(jiffies, end_time)); | 2031 | } while (time_before(jiffies, end_time)); |
1893 | 2032 | ||
1894 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 2033 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
1895 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); | 2034 | snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); |
1896 | 2035 | ||
1897 | #if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */ | 2036 | #if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */ |
1898 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 2037 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
@@ -1907,8 +2046,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1907 | chip->ac97_secondary = 1; | 2046 | chip->ac97_secondary = 1; |
1908 | goto __ac97_ok2; | 2047 | goto __ac97_ok2; |
1909 | } | 2048 | } |
1910 | set_current_state(TASK_INTERRUPTIBLE); | 2049 | schedule_timeout_interruptible(1); |
1911 | schedule_timeout(1); | ||
1912 | } while (time_before(jiffies, end_time)); | 2050 | } while (time_before(jiffies, end_time)); |
1913 | /* This is ok, the most of motherboards have only one codec */ | 2051 | /* This is ok, the most of motherboards have only one codec */ |
1914 | 2052 | ||
@@ -1940,8 +2078,10 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1940 | int i, idx; | 2078 | int i, idx; |
1941 | for (idx = 0; idx < 4; idx++) { | 2079 | for (idx = 0; idx < 4; idx++) { |
1942 | unsigned long port = chip->port + 0x10 * idx; | 2080 | unsigned long port = chip->port + 0x10 * idx; |
1943 | for (i = 0; i < 2; i++) | 2081 | for (i = 0; i < 2; i++) { |
1944 | outb(chip->playback_volume[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); | 2082 | chip->playback_volume[idx][i]=chip->playback_volume_c[i]; |
2083 | outb(chip->playback_volume_c[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); | ||
2084 | } | ||
1945 | } | 2085 | } |
1946 | } | 2086 | } |
1947 | 2087 | ||
@@ -2020,10 +2160,7 @@ static int snd_via82xx_free(via82xx_t *chip) | |||
2020 | __end_hw: | 2160 | __end_hw: |
2021 | if (chip->irq >= 0) | 2161 | if (chip->irq >= 0) |
2022 | free_irq(chip->irq, (void *)chip); | 2162 | free_irq(chip->irq, (void *)chip); |
2023 | if (chip->mpu_res) { | 2163 | release_and_free_resource(chip->mpu_res); |
2024 | release_resource(chip->mpu_res); | ||
2025 | kfree_nocheck(chip->mpu_res); | ||
2026 | } | ||
2027 | pci_release_regions(chip->pci); | 2164 | pci_release_regions(chip->pci); |
2028 | 2165 | ||
2029 | if (chip->chip_type == TYPE_VIA686) { | 2166 | if (chip->chip_type == TYPE_VIA686) { |
@@ -2084,9 +2221,12 @@ static int __devinit snd_via82xx_create(snd_card_t * card, | |||
2084 | return err; | 2221 | return err; |
2085 | } | 2222 | } |
2086 | chip->port = pci_resource_start(pci, 0); | 2223 | chip->port = pci_resource_start(pci, 0); |
2087 | if (request_irq(pci->irq, snd_via82xx_interrupt, SA_INTERRUPT|SA_SHIRQ, | 2224 | if (request_irq(pci->irq, |
2225 | chip_type == TYPE_VIA8233 ? | ||
2226 | snd_via8233_interrupt : snd_via686_interrupt, | ||
2227 | SA_INTERRUPT|SA_SHIRQ, | ||
2088 | card->driver, (void *)chip)) { | 2228 | card->driver, (void *)chip)) { |
2089 | snd_printk("unable to grab IRQ %d\n", pci->irq); | 2229 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2090 | snd_via82xx_free(chip); | 2230 | snd_via82xx_free(chip); |
2091 | return -EBUSY; | 2231 | return -EBUSY; |
2092 | } | 2232 | } |
@@ -2178,6 +2318,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2178 | { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ | 2318 | { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ |
2179 | { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ | 2319 | { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ |
2180 | { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_SRC }, /* Twinhead laptop */ | 2320 | { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_SRC }, /* Twinhead laptop */ |
2321 | { .subvendor = 0x1558, .subdevice = 0x4701, .action = VIA_DXS_SRC }, /* Clevo D470 */ | ||
2181 | { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ | 2322 | { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ |
2182 | { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ | 2323 | { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ |
2183 | { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ | 2324 | { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ |
@@ -2221,7 +2362,6 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2221 | static int __devinit snd_via82xx_probe(struct pci_dev *pci, | 2362 | static int __devinit snd_via82xx_probe(struct pci_dev *pci, |
2222 | const struct pci_device_id *pci_id) | 2363 | const struct pci_device_id *pci_id) |
2223 | { | 2364 | { |
2224 | static int dev; | ||
2225 | snd_card_t *card; | 2365 | snd_card_t *card; |
2226 | via82xx_t *chip; | 2366 | via82xx_t *chip; |
2227 | unsigned char revision; | 2367 | unsigned char revision; |
@@ -2229,14 +2369,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
2229 | unsigned int i; | 2369 | unsigned int i; |
2230 | int err; | 2370 | int err; |
2231 | 2371 | ||
2232 | if (dev >= SNDRV_CARDS) | 2372 | card = snd_card_new(index, id, THIS_MODULE, 0); |
2233 | return -ENODEV; | ||
2234 | if (!enable[dev]) { | ||
2235 | dev++; | ||
2236 | return -ENOENT; | ||
2237 | } | ||
2238 | |||
2239 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | ||
2240 | if (card == NULL) | 2373 | if (card == NULL) |
2241 | return -ENOMEM; | 2374 | return -ENOMEM; |
2242 | 2375 | ||
@@ -2259,12 +2392,12 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
2259 | } | 2392 | } |
2260 | } | 2393 | } |
2261 | if (chip_type != TYPE_VIA8233A) { | 2394 | if (chip_type != TYPE_VIA8233A) { |
2262 | if (dxs_support[dev] == VIA_DXS_AUTO) | 2395 | if (dxs_support == VIA_DXS_AUTO) |
2263 | dxs_support[dev] = check_dxs_list(pci); | 2396 | dxs_support = check_dxs_list(pci); |
2264 | /* force to use VIA8233 or 8233A model according to | 2397 | /* force to use VIA8233 or 8233A model according to |
2265 | * dxs_support module option | 2398 | * dxs_support module option |
2266 | */ | 2399 | */ |
2267 | if (dxs_support[dev] == VIA_DXS_DISABLE) | 2400 | if (dxs_support == VIA_DXS_DISABLE) |
2268 | chip_type = TYPE_VIA8233A; | 2401 | chip_type = TYPE_VIA8233A; |
2269 | else | 2402 | else |
2270 | chip_type = TYPE_VIA8233; | 2403 | chip_type = TYPE_VIA8233; |
@@ -2282,14 +2415,15 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
2282 | goto __error; | 2415 | goto __error; |
2283 | } | 2416 | } |
2284 | 2417 | ||
2285 | if ((err = snd_via82xx_create(card, pci, chip_type, revision, ac97_clock[dev], &chip)) < 0) | 2418 | if ((err = snd_via82xx_create(card, pci, chip_type, revision, |
2419 | ac97_clock, &chip)) < 0) | ||
2286 | goto __error; | 2420 | goto __error; |
2287 | if ((err = snd_via82xx_mixer_new(chip, ac97_quirk[dev])) < 0) | 2421 | if ((err = snd_via82xx_mixer_new(chip, ac97_quirk)) < 0) |
2288 | goto __error; | 2422 | goto __error; |
2289 | 2423 | ||
2290 | if (chip_type == TYPE_VIA686) { | 2424 | if (chip_type == TYPE_VIA686) { |
2291 | if ((err = snd_via686_pcm_new(chip)) < 0 || | 2425 | if ((err = snd_via686_pcm_new(chip)) < 0 || |
2292 | (err = snd_via686_init_misc(chip, dev)) < 0) | 2426 | (err = snd_via686_init_misc(chip)) < 0) |
2293 | goto __error; | 2427 | goto __error; |
2294 | } else { | 2428 | } else { |
2295 | if (chip_type == TYPE_VIA8233A) { | 2429 | if (chip_type == TYPE_VIA8233A) { |
@@ -2299,16 +2433,16 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
2299 | } else { | 2433 | } else { |
2300 | if ((err = snd_via8233_pcm_new(chip)) < 0) | 2434 | if ((err = snd_via8233_pcm_new(chip)) < 0) |
2301 | goto __error; | 2435 | goto __error; |
2302 | if (dxs_support[dev] == VIA_DXS_48K) | 2436 | if (dxs_support == VIA_DXS_48K) |
2303 | chip->dxs_fixed = 1; | 2437 | chip->dxs_fixed = 1; |
2304 | else if (dxs_support[dev] == VIA_DXS_NO_VRA) | 2438 | else if (dxs_support == VIA_DXS_NO_VRA) |
2305 | chip->no_vra = 1; | 2439 | chip->no_vra = 1; |
2306 | else if (dxs_support[dev] == VIA_DXS_SRC) { | 2440 | else if (dxs_support == VIA_DXS_SRC) { |
2307 | chip->no_vra = 1; | 2441 | chip->no_vra = 1; |
2308 | chip->dxs_src = 1; | 2442 | chip->dxs_src = 1; |
2309 | } | 2443 | } |
2310 | } | 2444 | } |
2311 | if ((err = snd_via8233_init_misc(chip, dev)) < 0) | 2445 | if ((err = snd_via8233_init_misc(chip)) < 0) |
2312 | goto __error; | 2446 | goto __error; |
2313 | } | 2447 | } |
2314 | 2448 | ||
@@ -2329,7 +2463,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
2329 | return err; | 2463 | return err; |
2330 | } | 2464 | } |
2331 | pci_set_drvdata(pci, card); | 2465 | pci_set_drvdata(pci, card); |
2332 | dev++; | ||
2333 | return 0; | 2466 | return 0; |
2334 | 2467 | ||
2335 | __error: | 2468 | __error: |