diff options
| -rw-r--r-- | sound/isa/opti9xx/opti92x-ad1848.c | 112 |
1 files changed, 67 insertions, 45 deletions
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index d08c38906449..8c88401c79bc 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
| @@ -135,6 +135,8 @@ struct snd_opti9xx { | |||
| 135 | unsigned long mc_base_size; | 135 | unsigned long mc_base_size; |
| 136 | #ifdef OPTi93X | 136 | #ifdef OPTi93X |
| 137 | unsigned long mc_indir_index; | 137 | unsigned long mc_indir_index; |
| 138 | unsigned long mc_indir_size; | ||
| 139 | struct resource *res_mc_indir; | ||
| 138 | struct snd_wss *codec; | 140 | struct snd_wss *codec; |
| 139 | #endif /* OPTi93X */ | 141 | #endif /* OPTi93X */ |
| 140 | unsigned long pwd_reg; | 142 | unsigned long pwd_reg; |
| @@ -231,7 +233,10 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, | |||
| 231 | case OPTi9XX_HW_82C931: | 233 | case OPTi9XX_HW_82C931: |
| 232 | case OPTi9XX_HW_82C933: | 234 | case OPTi9XX_HW_82C933: |
| 233 | chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; | 235 | chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; |
| 234 | chip->mc_indir_index = 0xe0e; | 236 | if (!chip->mc_indir_index) { |
| 237 | chip->mc_indir_index = 0xe0e; | ||
| 238 | chip->mc_indir_size = 2; | ||
| 239 | } | ||
| 235 | chip->password = 0xe4; | 240 | chip->password = 0xe4; |
| 236 | chip->pwd_reg = 0; | 241 | chip->pwd_reg = 0; |
| 237 | break; | 242 | break; |
| @@ -560,57 +565,69 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) | |||
| 560 | 565 | ||
| 561 | #endif /* OPTi93X */ | 566 | #endif /* OPTi93X */ |
| 562 | 567 | ||
| 563 | static int __devinit snd_card_opti9xx_detect(struct snd_card *card, | 568 | static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) |
| 564 | struct snd_opti9xx *chip) | ||
| 565 | { | 569 | { |
| 566 | int i, err; | 570 | unsigned char value; |
| 571 | #ifdef OPTi93X | ||
| 572 | unsigned long flags; | ||
| 573 | #endif | ||
| 567 | 574 | ||
| 575 | chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, | ||
| 576 | "OPTi9xx MC"); | ||
| 577 | if (chip->res_mc_base == NULL) | ||
| 578 | return -EBUSY; | ||
| 568 | #ifndef OPTi93X | 579 | #ifndef OPTi93X |
| 569 | for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) { | 580 | value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)); |
| 570 | unsigned char value; | 581 | if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1))) |
| 582 | if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) | ||
| 583 | return 0; | ||
| 584 | #else /* OPTi93X */ | ||
| 585 | chip->res_mc_indir = request_region(chip->mc_indir_index, | ||
| 586 | chip->mc_indir_size, | ||
| 587 | "OPTi93x MC"); | ||
| 588 | if (chip->res_mc_indir == NULL) | ||
| 589 | return -EBUSY; | ||
| 571 | 590 | ||
| 572 | if ((err = snd_opti9xx_init(chip, i)) < 0) | 591 | spin_lock_irqsave(&chip->lock, flags); |
| 573 | return err; | 592 | outb(chip->password, chip->mc_base + chip->pwd_reg); |
| 593 | outb(((chip->mc_indir_index & 0x1f0) >> 4), chip->mc_base); | ||
| 594 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 574 | 595 | ||
| 575 | if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL) | 596 | value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)); |
| 576 | continue; | 597 | snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value); |
| 598 | if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value) | ||
| 599 | return 0; | ||
| 577 | 600 | ||
| 578 | value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)); | 601 | release_and_free_resource(chip->res_mc_indir); |
| 579 | if ((value != 0xff) && (value != inb(chip->mc_base + 1))) | 602 | chip->res_mc_indir = NULL; |
| 580 | if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) | 603 | #endif /* OPTi93X */ |
| 581 | return 1; | 604 | release_and_free_resource(chip->res_mc_base); |
| 605 | chip->res_mc_base = NULL; | ||
| 582 | 606 | ||
| 583 | release_and_free_resource(chip->res_mc_base); | 607 | return -ENODEV; |
| 584 | chip->res_mc_base = NULL; | 608 | } |
| 585 | 609 | ||
| 586 | } | 610 | static int __devinit snd_card_opti9xx_detect(struct snd_card *card, |
| 587 | #else /* OPTi93X */ | 611 | struct snd_opti9xx *chip) |
| 588 | for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) { | 612 | { |
| 589 | unsigned long flags; | 613 | int i, err; |
| 590 | unsigned char value; | ||
| 591 | 614 | ||
| 592 | if ((err = snd_opti9xx_init(chip, i)) < 0) | 615 | #ifndef OPTi93X |
| 616 | for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) { | ||
| 617 | #else | ||
| 618 | for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) { | ||
| 619 | #endif | ||
| 620 | err = snd_opti9xx_init(chip, i); | ||
| 621 | if (err < 0) | ||
| 593 | return err; | 622 | return err; |
| 594 | 623 | ||
| 595 | if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL) | 624 | err = snd_opti9xx_read_check(chip); |
| 596 | continue; | 625 | if (err == 0) |
| 597 | |||
| 598 | spin_lock_irqsave(&chip->lock, flags); | ||
| 599 | outb(chip->password, chip->mc_base + chip->pwd_reg); | ||
| 600 | outb(((chip->mc_indir_index & (1 << 8)) >> 4) | | ||
| 601 | ((chip->mc_indir_index & 0xf0) >> 4), chip->mc_base); | ||
| 602 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 603 | |||
| 604 | value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)); | ||
| 605 | snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value); | ||
| 606 | if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value) | ||
| 607 | return 1; | 626 | return 1; |
| 608 | 627 | #ifdef OPTi93X | |
| 609 | release_and_free_resource(chip->res_mc_base); | 628 | chip->mc_indir_index = 0; |
| 610 | chip->res_mc_base = NULL; | 629 | #endif |
| 611 | } | 630 | } |
| 612 | #endif /* OPTi93X */ | ||
| 613 | |||
| 614 | return -ENODEV; | 631 | return -ENODEV; |
| 615 | } | 632 | } |
| 616 | 633 | ||
| @@ -639,6 +656,8 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, | |||
| 639 | #ifdef OPTi93X | 656 | #ifdef OPTi93X |
| 640 | port = pnp_port_start(pdev, 0) - 4; | 657 | port = pnp_port_start(pdev, 0) - 4; |
| 641 | fm_port = pnp_port_start(pdev, 1) + 8; | 658 | fm_port = pnp_port_start(pdev, 1) + 8; |
| 659 | chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; | ||
| 660 | chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; | ||
| 642 | #else | 661 | #else |
| 643 | if (pid->driver_data != 0x0924) | 662 | if (pid->driver_data != 0x0924) |
| 644 | port = pnp_port_start(pdev, 1); | 663 | port = pnp_port_start(pdev, 1); |
| @@ -669,7 +688,7 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, | |||
| 669 | static void snd_card_opti9xx_free(struct snd_card *card) | 688 | static void snd_card_opti9xx_free(struct snd_card *card) |
| 670 | { | 689 | { |
| 671 | struct snd_opti9xx *chip = card->private_data; | 690 | struct snd_opti9xx *chip = card->private_data; |
| 672 | 691 | ||
| 673 | if (chip) { | 692 | if (chip) { |
| 674 | #ifdef OPTi93X | 693 | #ifdef OPTi93X |
| 675 | struct snd_wss *codec = chip->codec; | 694 | struct snd_wss *codec = chip->codec; |
| @@ -677,6 +696,7 @@ static void snd_card_opti9xx_free(struct snd_card *card) | |||
| 677 | disable_irq(codec->irq); | 696 | disable_irq(codec->irq); |
| 678 | free_irq(codec->irq, codec); | 697 | free_irq(codec->irq, codec); |
| 679 | } | 698 | } |
| 699 | release_and_free_resource(chip->res_mc_indir); | ||
| 680 | #endif | 700 | #endif |
| 681 | release_and_free_resource(chip->res_mc_base); | 701 | release_and_free_resource(chip->res_mc_base); |
| 682 | } | 702 | } |
| @@ -696,11 +716,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
| 696 | struct snd_rawmidi *rmidi; | 716 | struct snd_rawmidi *rmidi; |
| 697 | struct snd_hwdep *synth; | 717 | struct snd_hwdep *synth; |
| 698 | 718 | ||
| 699 | if (! chip->res_mc_base && | ||
| 700 | (chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, | ||
| 701 | "OPTi9xx MC")) == NULL) | ||
| 702 | return -ENOMEM; | ||
| 703 | |||
| 704 | #if defined(CS4231) || defined(OPTi93X) | 719 | #if defined(CS4231) || defined(OPTi93X) |
| 705 | xdma2 = dma2; | 720 | xdma2 = dma2; |
| 706 | #else | 721 | #else |
| @@ -954,6 +969,13 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, | |||
| 954 | } | 969 | } |
| 955 | if (hw <= OPTi9XX_HW_82C930) | 970 | if (hw <= OPTi9XX_HW_82C930) |
| 956 | chip->mc_base -= 0x80; | 971 | chip->mc_base -= 0x80; |
| 972 | |||
| 973 | error = snd_opti9xx_read_check(chip); | ||
| 974 | if (error) { | ||
| 975 | snd_printk(KERN_ERR "OPTI chip not found\n"); | ||
| 976 | snd_card_free(card); | ||
| 977 | return error; | ||
| 978 | } | ||
| 957 | snd_card_set_dev(card, &pcard->card->dev); | 979 | snd_card_set_dev(card, &pcard->card->dev); |
| 958 | if ((error = snd_opti9xx_probe(card)) < 0) { | 980 | if ((error = snd_opti9xx_probe(card)) < 0) { |
| 959 | snd_card_free(card); | 981 | snd_card_free(card); |
