#ifdef SUPPORT_JOYSTICK
static int joystick[SNDRV_CARDS];
#endif
-static int boot_devs;
-module_param_array(index, int, boot_devs, 0444);
+module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-module_param_array(id, charp, boot_devs, 0444);
+module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-module_param_array(enable, bool, boot_devs, 0444);
+module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-module_param_array(total_bufsize, int, boot_devs, 0444);
+module_param_array(total_bufsize, int, NULL, 0444);
MODULE_PARM_DESC(total_bufsize, "Total buffer size in kB.");
-module_param_array(pcm_substreams_p, int, boot_devs, 0444);
+module_param_array(pcm_substreams_p, int, NULL, 0444);
MODULE_PARM_DESC(pcm_substreams_p, "PCM Playback substreams for " CARD_NAME " soundcard.");
-module_param_array(pcm_substreams_c, int, boot_devs, 0444);
+module_param_array(pcm_substreams_c, int, NULL, 0444);
MODULE_PARM_DESC(pcm_substreams_c, "PCM Capture substreams for " CARD_NAME " soundcard.");
-module_param_array(clock, int, boot_devs, 0444);
+module_param_array(clock, int, NULL, 0444);
MODULE_PARM_DESC(clock, "Clock on " CARD_NAME " soundcard. (0 = auto-detect)");
-module_param_array(use_pm, int, boot_devs, 0444);
+module_param_array(use_pm, int, NULL, 0444);
MODULE_PARM_DESC(use_pm, "Toggle power-management. (0 = off, 1 = on, 2 = auto)");
-module_param_array(enable_mpu, int, boot_devs, 0444);
+module_param_array(enable_mpu, int, NULL, 0444);
MODULE_PARM_DESC(enable_mpu, "Enable MPU401. (0 = off, 1 = on, 2 = auto)");
#ifdef SUPPORT_JOYSTICK
-module_param_array(joystick, bool, boot_devs, 0444);
+module_param_array(joystick, bool, NULL, 0444);
MODULE_PARM_DESC(joystick, "Enable joystick.");
#endif
int playback_streams, capture_streams;
unsigned int clock; /* clock */
+ /* for clock measurement */
+ unsigned int in_measurement: 1;
+ unsigned int measure_apu;
+ unsigned int measure_lastpos;
+ unsigned int measure_count;
/* buffer */
struct snd_dma_buffer dma;
snd_rawmidi_t *rmidi;
spinlock_t reg_lock;
+ spinlock_t ac97_lock;
struct tasklet_struct hwvol_tq;
/* Maestro Stuff */
while (timeout-- > 0) {
if (!(inb(chip->io_port + ESM_AC97_INDEX) & 1))
return 0;
+ cond_resched();
}
snd_printd("es1968: ac97 timeout\n");
return 1; /* timeout */
es1968_t *chip = ac97->private_data;
unsigned long flags;
- spin_lock_irqsave(&chip->reg_lock, flags);
-
snd_es1968_ac97_wait(chip);
/* Write the bus */
+ spin_lock_irqsave(&chip->ac97_lock, flags);
outw(val, chip->io_port + ESM_AC97_DATA);
- mdelay(1);
+ /*msleep(1);*/
outb(reg, chip->io_port + ESM_AC97_INDEX);
- mdelay(1);
-
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ /*msleep(1);*/
+ spin_unlock_irqrestore(&chip->ac97_lock, flags);
}
static unsigned short snd_es1968_ac97_read(ac97_t *ac97, unsigned short reg)
es1968_t *chip = ac97->private_data;
unsigned long flags;
- spin_lock_irqsave(&chip->reg_lock, flags);
-
snd_es1968_ac97_wait(chip);
+ spin_lock_irqsave(&chip->ac97_lock, flags);
outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX);
- mdelay(1);
+ /*msleep(1);*/
if (! snd_es1968_ac97_wait(chip)) {
data = inw(chip->io_port + ESM_AC97_DATA);
- mdelay(1);
+ /*msleep(1);*/
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock_irqrestore(&chip->ac97_lock, flags);
return data;
}
static void snd_es1968_bob_stop(es1968_t *chip)
{
u16 reg;
- unsigned long flags;
- spin_lock_irqsave(&chip->reg_lock, flags);
reg = __maestro_read(chip, 0x11);
reg &= ~ESM_BOB_ENABLE;
__maestro_write(chip, 0x11, reg);
reg = __maestro_read(chip, 0x17);
reg &= ~ESM_BOB_START;
__maestro_write(chip, 0x17, reg);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
}
static void snd_es1968_bob_start(es1968_t *chip)
{
int prescale;
int divide;
- unsigned long flags;
/* compute ideal interrupt frequency for buffer size & play rate */
/* first, find best prescaler value to match freq */
} else if (divide > 1)
divide--;
- spin_lock_irqsave(&chip->reg_lock, flags);
__maestro_write(chip, 6, 0x9000 | (prescale << 5) | divide); /* set reg */
/* Now set IDR 11/17 */
__maestro_write(chip, 0x11, __maestro_read(chip, 0x11) | 1);
__maestro_write(chip, 0x17, __maestro_read(chip, 0x17) | 1);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
}
/* call with substream spinlock */
snd_es1968_apu_set_freq(chip, apu, ((unsigned int)48000 << 16) / chip->clock); /* 48000 Hz */
+ chip->in_measurement = 1;
+ chip->measure_apu = apu;
spin_lock_irq(&chip->reg_lock);
+ snd_es1968_bob_inc(chip, ESM_BOB_FREQ);
__apu_set_register(chip, apu, 5, pa & 0xffff);
snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR);
do_gettimeofday(&start_time);
spin_unlock_irq(&chip->reg_lock);
-#if 0
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ / 20); /* 50 msec */
-#else
- /* FIXME:
- * schedule() above may be too inaccurate and the pointer can
- * overlap the boundary..
- */
- mdelay(50);
-#endif
spin_lock_irq(&chip->reg_lock);
offset = __apu_get_register(chip, apu, 5);
do_gettimeofday(&stop_time);
snd_es1968_trigger_apu(chip, apu, 0); /* stop */
+ snd_es1968_bob_dec(chip);
+ chip->in_measurement = 0;
spin_unlock_irq(&chip->reg_lock);
/* check the current position */
offset -= (pa & 0xffff);
offset &= 0xfffe;
+ offset += chip->measure_count * (CLOCK_MEASURE_BUFSIZE/2);
t = stop_time.tv_sec - start_time.tv_sec;
t *= 1000000;
{
es1968_t *chip = (es1968_t *) private_data;
int x, val;
+ unsigned long flags;
/* Figure out which volume control button was pushed,
based on differences from the default register
if (! chip->master_switch || ! chip->master_volume)
return;
- /* FIXME: more clean up is needed.. */
+ /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */
+ spin_lock_irqsave(&chip->ac97_lock, flags);
val = chip->ac97->regs[AC97_MASTER];
if (x & 1) {
/* mute */
- snd_ac97_write_cache(chip->ac97, AC97_MASTER, val ^ 0x8000);
+ val ^= 0x8000;
+ chip->ac97->regs[AC97_MASTER] = val;
+ outw(val, chip->io_port + ESM_AC97_DATA);
+ outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX);
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->master_switch->id);
} else {
if ((val & 0xff00) < 0x1f00)
val += 0x0100;
}
- snd_ac97_write_cache(chip->ac97, AC97_MASTER, val);
+ chip->ac97->regs[AC97_MASTER] = val;
+ outw(val, chip->io_port + ESM_AC97_DATA);
+ outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX);
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->master_volume->id);
}
+ spin_unlock_irqrestore(&chip->ac97_lock, flags);
}
/*
snd_es1968_update_pcm(chip, es);
}
spin_unlock(&chip->substream_lock);
+ if (chip->in_measurement) {
+ unsigned int curp = __apu_get_register(chip, chip->measure_apu, 5);
+ if (curp < chip->measure_lastpos)
+ chip->measure_count++;
+ chip->measure_lastpos = curp;
+ }
}
return IRQ_HANDLED;
if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
return err;
+ pbus->no_vra = 1; /* ES1968 doesn't need VRA */
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
snd_ac97_suspend(chip->ac97);
snd_es1968_bob_stop(chip);
snd_es1968_set_acpi(chip, ACPI_D3);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ pci_disable_device(chip->pci);
return 0;
}
/* restore all our config */
pci_enable_device(chip->pci);
+ pci_set_master(chip->pci);
snd_es1968_chip_init(chip);
/* need to restore the base pointers.. */
if (chip->bobclient)
snd_es1968_bob_start(chip);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
chip->master_switch = NULL;
chip->master_volume = NULL;
pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
kfree(chip);
return 0;
}
if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
snd_printk("architecture does not support 28bit PCI busmaster DMA\n");
+ pci_disable_device(pci);
return -ENXIO;
}
chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
- if (! chip)
+ if (! chip) {
+ pci_disable_device(pci);
return -ENOMEM;
+ }
/* Set Vars */
chip->type = chip_type;
spin_lock_init(&chip->substream_lock);
INIT_LIST_HEAD(&chip->buf_list);
INIT_LIST_HEAD(&chip->substream_list);
+ spin_lock_init(&chip->ac97_lock);
init_MUTEX(&chip->memory_mutex);
tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip);
chip->card = card;
if ((err = pci_request_regions(pci, "ESS Maestro")) < 0) {
kfree(chip);
+ pci_disable_device(pci);
return err;
}
chip->io_port = pci_resource_start(pci, 0);