aboutsummaryrefslogtreecommitdiff
path: root/sound/isa/opti9xx
diff options
context:
space:
mode:
authorKrzysztof Helt2010-03-03 19:41:44 +0100
committerTakashi Iwai2010-03-03 22:36:18 +0100
commitfd8d47351d2e241f3168eeb697ce55cc28c75b78 (patch)
treebdba27bec2d326277f0454c8cd155f47c03bc069 /sound/isa/opti9xx
parent864c11080cf365720103042444534a1e94d42bac (diff)
ALSA: opti92x: use PnP data to select Master Control port
The Master Control port (MC) is available as the last PnP resource (OPT005). Use this value instead fo guessing. Also, add some comments to the code. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/isa/opti9xx')
-rw-r--r--sound/isa/opti9xx/miro.c2
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c120
2 files changed, 79 insertions, 43 deletions
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index b865e45a8f9b..5913717c1be6 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -1558,7 +1558,7 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
err = pnp_activate_dev(devmc);
if (err < 0) {
- snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n",
+ snd_printk(KERN_ERR "MC pnp configure failure: %d\n",
err);
return err;
}
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index a4af53b5c1cf..becd90d7536d 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -144,12 +144,8 @@ struct snd_opti9xx {
spinlock_t lock;
+ long wss_base;
int irq;
-
-#ifdef CONFIG_PNP
- struct pnp_dev *dev;
- struct pnp_dev *devmpu;
-#endif /* CONFIG_PNP */
};
static int snd_opti9xx_pnp_is_probed;
@@ -159,12 +155,17 @@ static int snd_opti9xx_pnp_is_probed;
static struct pnp_card_device_id snd_opti9xx_pnpids[] = {
#ifndef OPTi93X
/* OPTi 82C924 */
- { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 },
+ { .id = "OPT0924",
+ .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } },
+ .driver_data = 0x0924 },
/* OPTi 82C925 */
- { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 },
+ { .id = "OPT0925",
+ .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } },
+ .driver_data = 0x0925 },
#else
/* OPTi 82C931/3 */
- { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 },
+ { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } },
+ .driver_data = 0x0931 },
#endif /* OPTi93X */
{ .id = "" }
};
@@ -207,24 +208,34 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
chip->hardware = hardware;
strcpy(chip->name, snd_opti9xx_names[hardware]);
- chip->mc_base_size = opti9xx_mc_size[hardware];
-
spin_lock_init(&chip->lock);
chip->irq = -1;
+#ifndef OPTi93X
+#ifdef CONFIG_PNP
+ if (isapnp && chip->mc_base)
+ /* PnP resource gives the least 10 bits */
+ chip->mc_base |= 0xc00;
+#endif /* CONFIG_PNP */
+ else {
+ chip->mc_base = 0xf8c;
+ chip->mc_base_size = opti9xx_mc_size[hardware];
+ }
+#else
+ chip->mc_base_size = opti9xx_mc_size[hardware];
+#endif
+
switch (hardware) {
#ifndef OPTi93X
case OPTi9XX_HW_82C928:
case OPTi9XX_HW_82C929:
- chip->mc_base = 0xf8c;
chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3;
chip->pwd_reg = 3;
break;
case OPTi9XX_HW_82C924:
case OPTi9XX_HW_82C925:
- chip->mc_base = 0xf8c;
chip->password = 0xe5;
chip->pwd_reg = 3;
break;
@@ -292,7 +303,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip,
spin_unlock_irqrestore(&chip->lock, flags);
return retval;
}
-
+
static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
unsigned char value)
{
@@ -341,7 +352,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
- long wss_base,
+ long port,
int irq, int dma1, int dma2,
long mpu_port, int mpu_irq)
{
@@ -354,16 +365,23 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
switch (chip->hardware) {
#ifndef OPTi93X
case OPTi9XX_HW_82C924:
+ /* opti 929 mode (?), OPL3 clock output, audio enable */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc);
+ /* enable wave audio */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
case OPTi9XX_HW_82C925:
+ /* enable WSS mode */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+ /* OPL3 FM synthesis */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
+ /* disable Sound Blaster IRQ and DMA */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
#ifdef CS4231
+ /* cs4231/4248 fix enabled */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
#else
+ /* cs4231/4248 fix disabled */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
#endif /* CS4231 */
break;
@@ -411,21 +429,26 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
return -EINVAL;
}
- switch (wss_base) {
- case 0x530:
+ /* PnP resource says it decodes only 10 bits of address */
+ switch (port & 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:
- snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base);
+ snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port);
goto __skip_base;
}
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
@@ -487,7 +510,7 @@ __skip_base:
#endif /* CS4231 || OPTi93X */
#ifndef OPTi93X
- outb(irq_bits << 3 | dma_bits, wss_base);
+ outb(irq_bits << 3 | dma_bits, chip->wss_base);
#else /* OPTi93X */
snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
#endif /* OPTi93X */
@@ -729,15 +752,15 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
{
struct pnp_dev *pdev;
int err;
+ struct pnp_dev *devmpu;
+#ifndef OPTi93X
+ struct pnp_dev *devmc;
+#endif
- chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
- if (chip->dev == NULL)
+ pdev = pnp_request_card_device(card, pid->devs[0].id, NULL);
+ if (pdev == NULL)
return -EBUSY;
- chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
-
- pdev = chip->dev;
-
err = pnp_activate_dev(pdev);
if (err < 0) {
snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
@@ -750,9 +773,24 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
chip->mc_indir_index = pnp_port_start(pdev, 3) + 2;
chip->mc_indir_size = pnp_port_len(pdev, 3) - 2;
#else
- if (pid->driver_data != 0x0924)
- port = pnp_port_start(pdev, 1);
+ devmc = pnp_request_card_device(card, pid->devs[2].id, NULL);
+ if (devmc == NULL)
+ return -EBUSY;
+
+ err = pnp_activate_dev(devmc);
+ if (err < 0) {
+ snd_printk(KERN_ERR "MC 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 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;
#endif /* OPTi93X */
irq = pnp_irq(pdev, 0);
dma1 = pnp_dma(pdev, 0);
@@ -760,16 +798,16 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
dma2 = pnp_dma(pdev, 1);
#endif /* CS4231 || OPTi93X */
- pdev = chip->devmpu;
- if (pdev && mpu_port > 0) {
- err = pnp_activate_dev(pdev);
+ devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
+
+ if (devmpu && mpu_port > 0) {
+ err = pnp_activate_dev(devmpu);
if (err < 0) {
- snd_printk(KERN_ERR "AUDIO pnp configure failure\n");
+ snd_printk(KERN_ERR "MPU401 pnp configure failure\n");
mpu_port = -1;
- chip->devmpu = NULL;
} else {
- mpu_port = pnp_port_start(pdev, 0);
- mpu_irq = pnp_irq(pdev, 0);
+ mpu_port = pnp_port_start(devmpu, 0);
+ mpu_irq = pnp_irq(devmpu, 0);
}
}
return pid->driver_data;
@@ -824,7 +862,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
if (error)
return error;
- error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2,
+ error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2,
#ifdef OPTi93X
WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
#else
@@ -865,10 +903,11 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
sprintf(card->shortname, "OPTi %s", card->driver);
#if defined(CS4231) || defined(OPTi93X)
sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
- card->shortname, pcm->name, port + 4, irq, dma1, xdma2);
+ card->shortname, pcm->name,
+ chip->wss_base + 4, irq, dma1, xdma2);
#else
sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
- card->shortname, pcm->name, port + 4, irq, dma1);
+ card->shortname, pcm->name, chip->wss_base + 4, irq, dma1);
#endif /* CS4231 || OPTi93X */
if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
@@ -1062,9 +1101,6 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
snd_card_free(card);
return error;
}
- if (hw <= OPTi9XX_HW_82C930)
- chip->mc_base -= 0x80;
-
error = snd_opti9xx_read_check(chip);
if (error) {
snd_printk(KERN_ERR "OPTI chip not found\n");