val = snd_cs46xx_codec_read(chip, reg, codec_index);
- /* HACK: voyetra uses EAPD bit in the reverse way.
- * we flip the bit to show the mixer status correctly
- */
- if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
- val ^= 0x8000;
-
return val;
}
codec_index == CS46XX_SECONDARY_CODEC_INDEX,
return);
- /* HACK: voyetra uses EAPD bit in the reverse way.
- * we flip the bit to show the mixer status correctly
- */
- if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
- val ^= 0x8000;
-
snd_cs46xx_codec_write(chip, reg, val, codec_index);
}
unsigned long offset,
unsigned long len)
{
- unsigned long dst;
+ void __iomem *dst;
unsigned int bank = offset >> 16;
offset = offset & 0xffff;
unsigned long offset,
unsigned long len)
{
- unsigned long dst;
+ void __iomem *dst;
unsigned int bank = offset >> 16;
offset = offset & 0xffff;
{
unsigned long end_time;
int err;
- cs46xx_t * chip = ac97->private_data;
/* reset to defaults */
snd_ac97_write(ac97, AC97_RESET, 0);
/* set the desired CODEC mode */
- if (chip->nr_ac97_codecs == 0) {
+ if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) {
snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0);
snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0);
- } else if (chip->nr_ac97_codecs == 1) {
+ } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) {
snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3);
snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3);
} else {
}
#endif
+static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec)
+{
+ int idx, err;
+ ac97_template_t ac97;
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+ ac97.private_free = snd_cs46xx_mixer_free_ac97;
+ ac97.num = codec;
+ if (chip->amplifier_ctrl == amp_voyetra)
+ ac97.scaps = AC97_SCAP_INV_EAPD;
+
+ if (codec == CS46XX_SECONDARY_CODEC_INDEX) {
+ snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec);
+ udelay(10);
+ if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) {
+ snd_printdd("snd_cs46xx: seconadry codec not present\n");
+ return -ENXIO;
+ }
+ }
+
+ snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec);
+ for (idx = 0; idx < 100; ++idx) {
+ if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) {
+ err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]);
+ return err;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/100);
+ }
+ snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec);
+ return -ENXIO;
+}
+
int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
{
snd_card_t *card = chip->card;
- ac97_template_t ac97;
snd_ctl_elem_id_t id;
int err;
unsigned int idx;
return err;
chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
- memset(&ac97, 0, sizeof(ac97));
- ac97.private_data = chip;
- ac97.private_free = snd_cs46xx_mixer_free_ac97;
-
- snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
- CS46XX_PRIMARY_CODEC_INDEX);
- for (idx = 0; idx < 100; ++idx) {
- if (snd_cs46xx_codec_read(chip, AC97_MASTER,
- CS46XX_PRIMARY_CODEC_INDEX) == 0x8000)
- goto _ok;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/100);
- }
- return -ENXIO;
-
- _ok:
- if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[CS46XX_PRIMARY_CODEC_INDEX])) < 0)
- return err;
- snd_printdd("snd_cs46xx: primary codec phase one\n");
+ if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
+ return -ENXIO;
chip->nr_ac97_codecs = 1;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
snd_printdd("snd_cs46xx: detecting seconadry codec\n");
/* try detect a secondary codec */
- memset(&ac97, 0, sizeof(ac97));
- ac97.private_data = chip;
- ac97.private_free = snd_cs46xx_mixer_free_ac97;
- ac97.num = CS46XX_SECONDARY_CODEC_INDEX;
-
- snd_cs46xx_codec_write(chip, AC97_RESET, 0,
- CS46XX_SECONDARY_CODEC_INDEX);
- udelay(10);
-
- if (snd_cs46xx_codec_read(chip, AC97_RESET,
- CS46XX_SECONDARY_CODEC_INDEX) & 0x8000) {
- snd_printdd("snd_cs46xx: seconadry codec not present\n");
- goto _no_sec_codec;
- }
-
- snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
- CS46XX_SECONDARY_CODEC_INDEX);
- for (idx = 0; idx < 100; ++idx) {
- if (snd_cs46xx_codec_read(chip, AC97_MASTER,
- CS46XX_SECONDARY_CODEC_INDEX) == 0x8000) {
- goto _ok2;
- }
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/100);
- }
-
- _no_sec_codec:
- snd_printdd("snd_cs46xx: secondary codec did not respond ...\n");
-
- chip->nr_ac97_codecs = 1;
-
- /* well, one codec only ... */
- goto _end;
- _ok2:
- if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])) < 0)
- return err;
- chip->nr_ac97_codecs = 2;
-
- _end:
-
+ if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX))
+ chip->nr_ac97_codecs = 2;
#endif /* CONFIG_SND_CS46XX_NEW_DSP */
/* add cs4630 mixer controls */
chip->eapd_switch = snd_ctl_find_id(chip->card, &id);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
- if (chip->nr_ac97_codecs == 1 &&
- (snd_cs46xx_codec_read(chip, AC97_VENDOR_ID2,
- CS46XX_PRIMARY_CODEC_INDEX) == 0x592b ||
- snd_cs46xx_codec_read(chip, AC97_VENDOR_ID2,
- CS46XX_PRIMARY_CODEC_INDEX) == 0x592d)) {
- /* set primary cs4294 codec into Extended Audio Mode */
- snd_printdd("setting EAM bit on cs4294 CODEC\n");
- snd_cs46xx_codec_write(chip, AC97_CSR_ACMODE, 0x200,
- CS46XX_PRIMARY_CODEC_INDEX);
+ if (chip->nr_ac97_codecs == 1) {
+ unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff;
+ if (id2 == 0x592b || id2 == 0x592d) {
+ /* set primary cs4294 codec into Extended Audio Mode */
+ snd_printdd("setting EAM bit on cs4294 CODEC\n");
+ snd_cs46xx_codec_write(chip, AC97_CSR_ACMODE, 0x200,
+ CS46XX_PRIMARY_CODEC_INDEX);
+ }
}
/* do soundcard specific mixer setup */
if (chip->mixer_init) {
for (idx = 0; idx < 5; idx++) {
snd_cs46xx_region_t *region = &chip->region.idx[idx];
if (region->remap_addr)
- iounmap((void *) region->remap_addr);
+ iounmap(region->remap_addr);
if (region->resource) {
release_resource(region->resource);
kfree_nocheck(region->resource);
}
#endif
+ pci_disable_device(chip->pci);
kfree(chip);
return 0;
}
/* disable CLKRUN */
chip->active_ctrl(chip, -chip->amplifier);
chip->amplifier = amp_saved; /* restore the status */
+ pci_disable_device(chip->pci);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return 0;
}
int amp_saved;
pci_enable_device(chip->pci);
+ pci_set_master(chip->pci);
amp_saved = chip->amplifier;
chip->amplifier = 0;
chip->active_ctrl(chip, 1); /* force to on */
return err;
chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
+ if (chip == NULL) {
+ pci_disable_device(pci);
return -ENOMEM;
+ }
spin_lock_init(&chip->reg_lock);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
init_MUTEX(&chip->spos_mutex);
snd_cs46xx_free(chip);
return -EBUSY;
}
- region->remap_addr = (unsigned long) ioremap_nocache(region->base, region->size);
- if (region->remap_addr == 0) {
+ region->remap_addr = ioremap_nocache(region->base, region->size);
+ if (region->remap_addr == NULL) {
snd_printk("%s ioremap problem\n", region->name);
snd_cs46xx_free(chip);
return -ENOMEM;
return err;
}
- snd_cs46xx_proc_init(card, chip);
-
- snd_card_set_pm_callback(card, snd_cs46xx_suspend, snd_cs46xx_resume, chip);
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_cs46xx_free(chip);
return err;
}
+ snd_cs46xx_proc_init(card, chip);
+
+ snd_card_set_pm_callback(card, snd_cs46xx_suspend, snd_cs46xx_resume, chip);
+
chip->active_ctrl(chip, -1); /* disable CLKRUN */
snd_card_set_dev(card, &pci->dev);