diff options
-rw-r--r-- | sound/isa/opti9xx/miro.c | 203 |
1 files changed, 192 insertions, 11 deletions
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index c67bc3cd2c65..6123c7531110 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/err.h> | 26 | #include <linux/err.h> |
27 | #include <linux/isa.h> | 27 | #include <linux/isa.h> |
28 | #include <linux/pnp.h> | ||
28 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
@@ -60,6 +61,9 @@ static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ | |||
60 | static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ | 61 | static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ |
61 | static int wss; | 62 | static int wss; |
62 | static int ide; | 63 | static int ide; |
64 | #ifdef CONFIG_PNP | ||
65 | static int isapnp = 1; /* Enable ISA PnP detection */ | ||
66 | #endif | ||
63 | 67 | ||
64 | module_param(index, int, 0444); | 68 | module_param(index, int, 0444); |
65 | MODULE_PARM_DESC(index, "Index value for miro soundcard."); | 69 | MODULE_PARM_DESC(index, "Index value for miro soundcard."); |
@@ -83,6 +87,10 @@ module_param(wss, int, 0444); | |||
83 | MODULE_PARM_DESC(wss, "wss mode"); | 87 | MODULE_PARM_DESC(wss, "wss mode"); |
84 | module_param(ide, int, 0444); | 88 | module_param(ide, int, 0444); |
85 | MODULE_PARM_DESC(ide, "enable ide port"); | 89 | MODULE_PARM_DESC(ide, "enable ide port"); |
90 | #ifdef CONFIG_PNP | ||
91 | module_param(isapnp, bool, 0444); | ||
92 | MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard."); | ||
93 | #endif | ||
86 | 94 | ||
87 | #define OPTi9XX_HW_DETECT 0 | 95 | #define OPTi9XX_HW_DETECT 0 |
88 | #define OPTi9XX_HW_82C928 1 | 96 | #define OPTi9XX_HW_82C928 1 |
@@ -131,6 +139,21 @@ static char * snd_opti9xx_names[] = { | |||
131 | "82C930", "82C931", "82C933" | 139 | "82C930", "82C931", "82C933" |
132 | }; | 140 | }; |
133 | 141 | ||
142 | static int snd_miro_pnp_is_probed; | ||
143 | |||
144 | #ifdef CONFIG_PNP | ||
145 | |||
146 | static struct pnp_card_device_id snd_miro_pnpids[] = { | ||
147 | /* PCM20 and PCM12 in PnP mode */ | ||
148 | { .id = "MIR0924", | ||
149 | .devs = { { "MIR0000" }, { "MIR0002" }, { "MIR0005" } }, }, | ||
150 | { .id = "" } | ||
151 | }; | ||
152 | |||
153 | MODULE_DEVICE_TABLE(pnp_card, snd_miro_pnpids); | ||
154 | |||
155 | #endif /* CONFIG_PNP */ | ||
156 | |||
134 | /* | 157 | /* |
135 | * ACI control | 158 | * ACI control |
136 | */ | 159 | */ |
@@ -781,17 +804,23 @@ static int __devinit snd_miro_init(struct snd_miro *chip, | |||
781 | chip->mpu_port = -1; | 804 | chip->mpu_port = -1; |
782 | chip->mpu_irq = -1; | 805 | chip->mpu_irq = -1; |
783 | 806 | ||
807 | chip->pwd_reg = 3; | ||
808 | |||
809 | #ifdef CONFIG_PNP | ||
810 | if (isapnp && chip->mc_base) | ||
811 | /* PnP resource gives the least 10 bits */ | ||
812 | chip->mc_base |= 0xc00; | ||
813 | else | ||
814 | #endif | ||
815 | chip->mc_base = 0xf8c; | ||
816 | |||
784 | switch (hardware) { | 817 | switch (hardware) { |
785 | case OPTi9XX_HW_82C929: | 818 | case OPTi9XX_HW_82C929: |
786 | chip->mc_base = 0xf8c; | ||
787 | chip->password = 0xe3; | 819 | chip->password = 0xe3; |
788 | chip->pwd_reg = 3; | ||
789 | break; | 820 | break; |
790 | 821 | ||
791 | case OPTi9XX_HW_82C924: | 822 | case OPTi9XX_HW_82C924: |
792 | chip->mc_base = 0xf8c; | ||
793 | chip->password = 0xe5; | 823 | chip->password = 0xe5; |
794 | chip->pwd_reg = 3; | ||
795 | break; | 824 | break; |
796 | 825 | ||
797 | default: | 826 | default: |
@@ -1014,17 +1043,22 @@ static int __devinit snd_miro_configure(struct snd_miro *chip) | |||
1014 | return -EINVAL; | 1043 | return -EINVAL; |
1015 | } | 1044 | } |
1016 | 1045 | ||
1017 | switch (chip->wss_base) { | 1046 | /* PnP resource says it decodes only 10 bits of address */ |
1018 | case 0x530: | 1047 | switch (chip->wss_base & 0x3ff) { |
1048 | case 0x130: | ||
1049 | chip->wss_base = 0x530; | ||
1019 | wss_base_bits = 0x00; | 1050 | wss_base_bits = 0x00; |
1020 | break; | 1051 | break; |
1021 | case 0x604: | 1052 | case 0x204: |
1053 | chip->wss_base = 0x604; | ||
1022 | wss_base_bits = 0x03; | 1054 | wss_base_bits = 0x03; |
1023 | break; | 1055 | break; |
1024 | case 0xe80: | 1056 | case 0x280: |
1057 | chip->wss_base = 0xe80; | ||
1025 | wss_base_bits = 0x01; | 1058 | wss_base_bits = 0x01; |
1026 | break; | 1059 | break; |
1027 | case 0xf40: | 1060 | case 0x340: |
1061 | chip->wss_base = 0xf40; | ||
1028 | wss_base_bits = 0x02; | 1062 | wss_base_bits = 0x02; |
1029 | break; | 1063 | break; |
1030 | default: | 1064 | default: |
@@ -1238,7 +1272,7 @@ static int __devinit snd_card_miro_aci_detect(struct snd_card *card, | |||
1238 | static void snd_card_miro_free(struct snd_card *card) | 1272 | static void snd_card_miro_free(struct snd_card *card) |
1239 | { | 1273 | { |
1240 | struct snd_miro *miro = card->private_data; | 1274 | struct snd_miro *miro = card->private_data; |
1241 | 1275 | ||
1242 | release_and_free_resource(miro->res_aci_port); | 1276 | release_and_free_resource(miro->res_aci_port); |
1243 | if (miro->aci) | 1277 | if (miro->aci) |
1244 | miro->aci->aci_port = 0; | 1278 | miro->aci->aci_port = 0; |
@@ -1370,6 +1404,12 @@ static int __devinit snd_miro_probe(struct snd_card *card) | |||
1370 | 1404 | ||
1371 | static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n) | 1405 | static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n) |
1372 | { | 1406 | { |
1407 | #ifdef CONFIG_PNP | ||
1408 | if (snd_miro_pnp_is_probed) | ||
1409 | return 0; | ||
1410 | if (isapnp) | ||
1411 | return 0; | ||
1412 | #endif | ||
1373 | return 1; | 1413 | return 1; |
1374 | } | 1414 | } |
1375 | 1415 | ||
@@ -1487,14 +1527,155 @@ static struct isa_driver snd_miro_driver = { | |||
1487 | }, | 1527 | }, |
1488 | }; | 1528 | }; |
1489 | 1529 | ||
1530 | #ifdef CONFIG_PNP | ||
1531 | |||
1532 | static int __devinit snd_card_miro_pnp(struct snd_miro *chip, | ||
1533 | struct pnp_card_link *card, | ||
1534 | const struct pnp_card_device_id *pid) | ||
1535 | { | ||
1536 | struct pnp_dev *pdev; | ||
1537 | int err; | ||
1538 | struct pnp_dev *devmpu; | ||
1539 | struct pnp_dev *devmc; | ||
1540 | |||
1541 | pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); | ||
1542 | if (pdev == NULL) | ||
1543 | return -EBUSY; | ||
1544 | |||
1545 | devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); | ||
1546 | if (devmpu == NULL) | ||
1547 | return -EBUSY; | ||
1548 | |||
1549 | devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); | ||
1550 | if (devmc == NULL) | ||
1551 | return -EBUSY; | ||
1552 | |||
1553 | err = pnp_activate_dev(pdev); | ||
1554 | if (err < 0) { | ||
1555 | snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); | ||
1556 | return err; | ||
1557 | } | ||
1558 | |||
1559 | err = pnp_activate_dev(devmc); | ||
1560 | if (err < 0) { | ||
1561 | snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n", | ||
1562 | err); | ||
1563 | return err; | ||
1564 | } | ||
1565 | |||
1566 | port = pnp_port_start(pdev, 1); | ||
1567 | fm_port = pnp_port_start(pdev, 2) + 8; | ||
1568 | |||
1569 | /* | ||
1570 | * The MC(0) is never accessed and the miroSOUND PCM20 card does not | ||
1571 | * include it in the PnP resource range. OPTI93x include it. | ||
1572 | */ | ||
1573 | chip->mc_base = pnp_port_start(devmc, 0) - 1; | ||
1574 | chip->mc_base_size = pnp_port_len(devmc, 0) + 1; | ||
1575 | |||
1576 | irq = pnp_irq(pdev, 0); | ||
1577 | dma1 = pnp_dma(pdev, 0); | ||
1578 | dma2 = pnp_dma(pdev, 1); | ||
1579 | |||
1580 | if (mpu_port > 0) { | ||
1581 | err = pnp_activate_dev(devmpu); | ||
1582 | if (err < 0) { | ||
1583 | snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); | ||
1584 | mpu_port = -1; | ||
1585 | return err; | ||
1586 | } | ||
1587 | mpu_port = pnp_port_start(devmpu, 0); | ||
1588 | mpu_irq = pnp_irq(devmpu, 0); | ||
1589 | } | ||
1590 | return 0; | ||
1591 | } | ||
1592 | |||
1593 | static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard, | ||
1594 | const struct pnp_card_device_id *pid) | ||
1595 | { | ||
1596 | struct snd_card *card; | ||
1597 | int err; | ||
1598 | struct snd_miro *miro; | ||
1599 | |||
1600 | if (snd_miro_pnp_is_probed) | ||
1601 | return -EBUSY; | ||
1602 | if (!isapnp) | ||
1603 | return -ENODEV; | ||
1604 | err = snd_card_create(index, id, THIS_MODULE, | ||
1605 | sizeof(struct snd_miro), &card); | ||
1606 | if (err < 0) | ||
1607 | return err; | ||
1608 | |||
1609 | card->private_free = snd_card_miro_free; | ||
1610 | miro = card->private_data; | ||
1611 | |||
1612 | err = snd_card_miro_pnp(miro, pcard, pid); | ||
1613 | if (err) { | ||
1614 | snd_card_free(card); | ||
1615 | return err; | ||
1616 | } | ||
1617 | |||
1618 | /* only miroSOUND PCM20 and PCM12 == OPTi924 */ | ||
1619 | err = snd_miro_init(miro, OPTi9XX_HW_82C924); | ||
1620 | if (err) { | ||
1621 | snd_card_free(card); | ||
1622 | return err; | ||
1623 | } | ||
1624 | |||
1625 | err = snd_miro_opti_check(miro); | ||
1626 | if (err) { | ||
1627 | snd_printk(KERN_ERR "OPTI chip not found\n"); | ||
1628 | snd_card_free(card); | ||
1629 | return err; | ||
1630 | } | ||
1631 | |||
1632 | snd_card_set_dev(card, &pcard->card->dev); | ||
1633 | err = snd_miro_probe(card); | ||
1634 | if (err < 0) { | ||
1635 | snd_card_free(card); | ||
1636 | return err; | ||
1637 | } | ||
1638 | pnp_set_card_drvdata(pcard, card); | ||
1639 | snd_miro_pnp_is_probed = 1; | ||
1640 | return 0; | ||
1641 | } | ||
1642 | |||
1643 | static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard) | ||
1644 | { | ||
1645 | snd_card_free(pnp_get_card_drvdata(pcard)); | ||
1646 | pnp_set_card_drvdata(pcard, NULL); | ||
1647 | snd_miro_pnp_is_probed = 0; | ||
1648 | } | ||
1649 | |||
1650 | static struct pnp_card_driver miro_pnpc_driver = { | ||
1651 | .flags = PNP_DRIVER_RES_DISABLE, | ||
1652 | .name = "miro", | ||
1653 | .id_table = snd_miro_pnpids, | ||
1654 | .probe = snd_miro_pnp_probe, | ||
1655 | .remove = __devexit_p(snd_miro_pnp_remove), | ||
1656 | }; | ||
1657 | #endif | ||
1658 | |||
1490 | static int __init alsa_card_miro_init(void) | 1659 | static int __init alsa_card_miro_init(void) |
1491 | { | 1660 | { |
1661 | #ifdef CONFIG_PNP | ||
1662 | pnp_register_card_driver(&miro_pnpc_driver); | ||
1663 | if (snd_miro_pnp_is_probed) | ||
1664 | return 0; | ||
1665 | pnp_unregister_card_driver(&miro_pnpc_driver); | ||
1666 | #endif | ||
1492 | return isa_register_driver(&snd_miro_driver, 1); | 1667 | return isa_register_driver(&snd_miro_driver, 1); |
1493 | } | 1668 | } |
1494 | 1669 | ||
1495 | static void __exit alsa_card_miro_exit(void) | 1670 | static void __exit alsa_card_miro_exit(void) |
1496 | { | 1671 | { |
1497 | isa_unregister_driver(&snd_miro_driver); | 1672 | if (!snd_miro_pnp_is_probed) { |
1673 | isa_unregister_driver(&snd_miro_driver); | ||
1674 | return; | ||
1675 | } | ||
1676 | #ifdef CONFIG_PNP | ||
1677 | pnp_unregister_card_driver(&miro_pnpc_driver); | ||
1678 | #endif | ||
1498 | } | 1679 | } |
1499 | 1680 | ||
1500 | module_init(alsa_card_miro_init) | 1681 | module_init(alsa_card_miro_init) |