aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/opti9xx/opti92x-ad1848.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa/opti9xx/opti92x-ad1848.c')
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c114
1 files changed, 68 insertions, 46 deletions
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index d08c38906449..106be6e471f7 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;
@@ -177,7 +179,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
177#endif 179#endif
178 180
179static char * snd_opti9xx_names[] = { 181static char * snd_opti9xx_names[] = {
180 "unkown", 182 "unknown",
181 "82C928", "82C929", 183 "82C928", "82C929",
182 "82C924", "82C925", 184 "82C924", "82C925",
183 "82C930", "82C931", "82C933" 185 "82C930", "82C931", "82C933"
@@ -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
563static int __devinit snd_card_opti9xx_detect(struct snd_card *card, 568static 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 } 610static 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,
669static void snd_card_opti9xx_free(struct snd_card *card) 688static 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);