Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 170118
b: refs/heads/master
c: 306ecee
h: refs/heads/master
v: v3
  • Loading branch information
Krzysztof Helt authored and Takashi Iwai committed Nov 30, 2009
1 parent 79ee8b9 commit a5be3d5
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 70a5f1187bcb3fac93a7d5c5fcfc5fc76b9c3f55
refs/heads/master: 306ecee926cf79f1b3b5f6035be09ef3d83f1b76
203 changes: 192 additions & 11 deletions trunk/sound/isa/opti9xx/miro.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/err.h>
#include <linux/isa.h>
#include <linux/pnp.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/ioport.h>
Expand Down Expand Up @@ -60,6 +61,9 @@ static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
static int wss;
static int ide;
#ifdef CONFIG_PNP
static int isapnp = 1; /* Enable ISA PnP detection */
#endif

module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for miro soundcard.");
Expand All @@ -83,6 +87,10 @@ module_param(wss, int, 0444);
MODULE_PARM_DESC(wss, "wss mode");
module_param(ide, int, 0444);
MODULE_PARM_DESC(ide, "enable ide port");
#ifdef CONFIG_PNP
module_param(isapnp, bool, 0444);
MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
#endif

#define OPTi9XX_HW_DETECT 0
#define OPTi9XX_HW_82C928 1
Expand Down Expand Up @@ -131,6 +139,21 @@ static char * snd_opti9xx_names[] = {
"82C930", "82C931", "82C933"
};

static int snd_miro_pnp_is_probed;

#ifdef CONFIG_PNP

static struct pnp_card_device_id snd_miro_pnpids[] = {
/* PCM20 and PCM12 in PnP mode */
{ .id = "MIR0924",
.devs = { { "MIR0000" }, { "MIR0002" }, { "MIR0005" } }, },
{ .id = "" }
};

MODULE_DEVICE_TABLE(pnp_card, snd_miro_pnpids);

#endif /* CONFIG_PNP */

/*
* ACI control
*/
Expand Down Expand Up @@ -781,17 +804,23 @@ static int __devinit snd_miro_init(struct snd_miro *chip,
chip->mpu_port = -1;
chip->mpu_irq = -1;

chip->pwd_reg = 3;

#ifdef CONFIG_PNP
if (isapnp && chip->mc_base)
/* PnP resource gives the least 10 bits */
chip->mc_base |= 0xc00;
else
#endif
chip->mc_base = 0xf8c;

switch (hardware) {
case OPTi9XX_HW_82C929:
chip->mc_base = 0xf8c;
chip->password = 0xe3;
chip->pwd_reg = 3;
break;

case OPTi9XX_HW_82C924:
chip->mc_base = 0xf8c;
chip->password = 0xe5;
chip->pwd_reg = 3;
break;

default:
Expand Down Expand Up @@ -1014,17 +1043,22 @@ static int __devinit snd_miro_configure(struct snd_miro *chip)
return -EINVAL;
}

switch (chip->wss_base) {
case 0x530:
/* PnP resource says it decodes only 10 bits of address */
switch (chip->wss_base & 0x3ff) {
case 0x130:
chip->wss_base = 0x530;
wss_base_bits = 0x00;
break;
case 0x604:
case 0x204:
chip->wss_base = 0x604;
wss_base_bits = 0x03;
break;
case 0xe80:
case 0x280:
chip->wss_base = 0xe80;
wss_base_bits = 0x01;
break;
case 0xf40:
case 0x340:
chip->wss_base = 0xf40;
wss_base_bits = 0x02;
break;
default:
Expand Down Expand Up @@ -1238,7 +1272,7 @@ static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
static void snd_card_miro_free(struct snd_card *card)
{
struct snd_miro *miro = card->private_data;

release_and_free_resource(miro->res_aci_port);
if (miro->aci)
miro->aci->aci_port = 0;
Expand Down Expand Up @@ -1370,6 +1404,12 @@ static int __devinit snd_miro_probe(struct snd_card *card)

static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n)
{
#ifdef CONFIG_PNP
if (snd_miro_pnp_is_probed)
return 0;
if (isapnp)
return 0;
#endif
return 1;
}

Expand Down Expand Up @@ -1487,14 +1527,155 @@ static struct isa_driver snd_miro_driver = {
},
};

#ifdef CONFIG_PNP

static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
struct pnp_card_link *card,
const struct pnp_card_device_id *pid)
{
struct pnp_dev *pdev;
int err;
struct pnp_dev *devmpu;
struct pnp_dev *devmc;

pdev = pnp_request_card_device(card, pid->devs[0].id, NULL);
if (pdev == NULL)
return -EBUSY;

devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
if (devmpu == NULL)
return -EBUSY;

devmc = pnp_request_card_device(card, pid->devs[2].id, NULL);
if (devmc == NULL)
return -EBUSY;

err = pnp_activate_dev(pdev);
if (err < 0) {
snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
return err;
}

err = pnp_activate_dev(devmc);
if (err < 0) {
snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n",
err);
return err;
}

port = pnp_port_start(pdev, 1);
fm_port = pnp_port_start(pdev, 2) + 8;

/*
* The MC(0) is never accessed and the miroSOUND PCM20 card does not
* include it in the PnP resource range. OPTI93x include it.
*/
chip->mc_base = pnp_port_start(devmc, 0) - 1;
chip->mc_base_size = pnp_port_len(devmc, 0) + 1;

irq = pnp_irq(pdev, 0);
dma1 = pnp_dma(pdev, 0);
dma2 = pnp_dma(pdev, 1);

if (mpu_port > 0) {
err = pnp_activate_dev(devmpu);
if (err < 0) {
snd_printk(KERN_ERR "MPU401 pnp configure failure\n");
mpu_port = -1;
return err;
}
mpu_port = pnp_port_start(devmpu, 0);
mpu_irq = pnp_irq(devmpu, 0);
}
return 0;
}

static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
struct snd_card *card;
int err;
struct snd_miro *miro;

if (snd_miro_pnp_is_probed)
return -EBUSY;
if (!isapnp)
return -ENODEV;
err = snd_card_create(index, id, THIS_MODULE,
sizeof(struct snd_miro), &card);
if (err < 0)
return err;

card->private_free = snd_card_miro_free;
miro = card->private_data;

err = snd_card_miro_pnp(miro, pcard, pid);
if (err) {
snd_card_free(card);
return err;
}

/* only miroSOUND PCM20 and PCM12 == OPTi924 */
err = snd_miro_init(miro, OPTi9XX_HW_82C924);
if (err) {
snd_card_free(card);
return err;
}

err = snd_miro_opti_check(miro);
if (err) {
snd_printk(KERN_ERR "OPTI chip not found\n");
snd_card_free(card);
return err;
}

snd_card_set_dev(card, &pcard->card->dev);
err = snd_miro_probe(card);
if (err < 0) {
snd_card_free(card);
return err;
}
pnp_set_card_drvdata(pcard, card);
snd_miro_pnp_is_probed = 1;
return 0;
}

static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard)
{
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
snd_miro_pnp_is_probed = 0;
}

static struct pnp_card_driver miro_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "miro",
.id_table = snd_miro_pnpids,
.probe = snd_miro_pnp_probe,
.remove = __devexit_p(snd_miro_pnp_remove),
};
#endif

static int __init alsa_card_miro_init(void)
{
#ifdef CONFIG_PNP
pnp_register_card_driver(&miro_pnpc_driver);
if (snd_miro_pnp_is_probed)
return 0;
pnp_unregister_card_driver(&miro_pnpc_driver);
#endif
return isa_register_driver(&snd_miro_driver, 1);
}

static void __exit alsa_card_miro_exit(void)
{
isa_unregister_driver(&snd_miro_driver);
if (!snd_miro_pnp_is_probed) {
isa_unregister_driver(&snd_miro_driver);
return;
}
#ifdef CONFIG_PNP
pnp_unregister_card_driver(&miro_pnpc_driver);
#endif
}

module_init(alsa_card_miro_init)
Expand Down

0 comments on commit a5be3d5

Please sign in to comment.