Skip to content

Commit

Permalink
ALSA: opti93x: set MC indirect registers base from PnP data
Browse files Browse the repository at this point in the history
The PnP data on the OPTI931 and OPTI933 contains io port
range for the MC indirect registers. Use the PnP range
instead of hardwired value 0xE0E.

Also, request region of MC indirect registers so it is
marked as used to other drivers (this was missing previously).

Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Krzysztof-H authored and tiwai committed Dec 8, 2009
1 parent 86e1d57 commit e6960e1
Showing 1 changed file with 67 additions and 45 deletions.
112 changes: 67 additions & 45 deletions sound/isa/opti9xx/opti92x-ad1848.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ struct snd_opti9xx {
unsigned long mc_base_size;
#ifdef OPTi93X
unsigned long mc_indir_index;
unsigned long mc_indir_size;
struct resource *res_mc_indir;
struct snd_wss *codec;
#endif /* OPTi93X */
unsigned long pwd_reg;
Expand Down Expand Up @@ -231,7 +233,10 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
case OPTi9XX_HW_82C931:
case OPTi9XX_HW_82C933:
chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d;
chip->mc_indir_index = 0xe0e;
if (!chip->mc_indir_index) {
chip->mc_indir_index = 0xe0e;
chip->mc_indir_size = 2;
}
chip->password = 0xe4;
chip->pwd_reg = 0;
break;
Expand Down Expand Up @@ -560,57 +565,69 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)

#endif /* OPTi93X */

static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
struct snd_opti9xx *chip)
static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip)
{
int i, err;
unsigned char value;
#ifdef OPTi93X
unsigned long flags;
#endif

chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
"OPTi9xx MC");
if (chip->res_mc_base == NULL)
return -EBUSY;
#ifndef OPTi93X
for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) {
unsigned char value;
value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1)))
if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
return 0;
#else /* OPTi93X */
chip->res_mc_indir = request_region(chip->mc_indir_index,
chip->mc_indir_size,
"OPTi93x MC");
if (chip->res_mc_indir == NULL)
return -EBUSY;

if ((err = snd_opti9xx_init(chip, i)) < 0)
return err;
spin_lock_irqsave(&chip->lock, flags);
outb(chip->password, chip->mc_base + chip->pwd_reg);
outb(((chip->mc_indir_index & 0x1f0) >> 4), chip->mc_base);
spin_unlock_irqrestore(&chip->lock, flags);

if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
continue;
value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7));
snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value);
if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
return 0;

value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
return 1;
release_and_free_resource(chip->res_mc_indir);
chip->res_mc_indir = NULL;
#endif /* OPTi93X */
release_and_free_resource(chip->res_mc_base);
chip->res_mc_base = NULL;

release_and_free_resource(chip->res_mc_base);
chip->res_mc_base = NULL;
return -ENODEV;
}

}
#else /* OPTi93X */
for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) {
unsigned long flags;
unsigned char value;
static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
struct snd_opti9xx *chip)
{
int i, err;

if ((err = snd_opti9xx_init(chip, i)) < 0)
#ifndef OPTi93X
for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) {
#else
for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) {
#endif
err = snd_opti9xx_init(chip, i);
if (err < 0)
return err;

if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
continue;

spin_lock_irqsave(&chip->lock, flags);
outb(chip->password, chip->mc_base + chip->pwd_reg);
outb(((chip->mc_indir_index & (1 << 8)) >> 4) |
((chip->mc_indir_index & 0xf0) >> 4), chip->mc_base);
spin_unlock_irqrestore(&chip->lock, flags);

value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7));
snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value);
if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
err = snd_opti9xx_read_check(chip);
if (err == 0)
return 1;

release_and_free_resource(chip->res_mc_base);
chip->res_mc_base = NULL;
#ifdef OPTi93X
chip->mc_indir_index = 0;
#endif
}
#endif /* OPTi93X */

return -ENODEV;
}

Expand Down Expand Up @@ -639,6 +656,8 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
#ifdef OPTi93X
port = pnp_port_start(pdev, 0) - 4;
fm_port = pnp_port_start(pdev, 1) + 8;
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);
Expand Down Expand Up @@ -669,14 +688,15 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
static void snd_card_opti9xx_free(struct snd_card *card)
{
struct snd_opti9xx *chip = card->private_data;

if (chip) {
#ifdef OPTi93X
struct snd_wss *codec = chip->codec;
if (codec && codec->irq > 0) {
disable_irq(codec->irq);
free_irq(codec->irq, codec);
}
release_and_free_resource(chip->res_mc_indir);
#endif
release_and_free_resource(chip->res_mc_base);
}
Expand All @@ -696,11 +716,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
struct snd_rawmidi *rmidi;
struct snd_hwdep *synth;

if (! chip->res_mc_base &&
(chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
"OPTi9xx MC")) == NULL)
return -ENOMEM;

#if defined(CS4231) || defined(OPTi93X)
xdma2 = dma2;
#else
Expand Down Expand Up @@ -954,6 +969,13 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
}
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");
snd_card_free(card);
return error;
}
snd_card_set_dev(card, &pcard->card->dev);
if ((error = snd_opti9xx_probe(card)) < 0) {
snd_card_free(card);
Expand Down

0 comments on commit e6960e1

Please sign in to comment.