X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fpci%2Fes1968.c;h=12ac754801a6b677063b4b06e3a7dc49bcb748cb;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=e97a7e8d7a371f4428f359db3159ebf94e6a910f;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index e97a7e8d7..12ac75480 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -135,28 +135,27 @@ static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; #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 @@ -556,6 +555,11 @@ struct snd_es1968 { 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; @@ -580,6 +584,7 @@ struct snd_es1968 { snd_rawmidi_t *rmidi; spinlock_t reg_lock; + spinlock_t ac97_lock; struct tasklet_struct hwvol_tq; /* Maestro Stuff */ @@ -672,6 +677,7 @@ static int snd_es1968_ac97_wait(es1968_t *chip) 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 */ @@ -682,17 +688,15 @@ static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned sho 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) @@ -701,18 +705,17 @@ 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; } @@ -835,23 +838,19 @@ static u16 wave_get_register(es1968_t *chip, u16 reg) 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 */ @@ -880,13 +879,11 @@ static void snd_es1968_bob_start(es1968_t *chip) } 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 */ @@ -1804,30 +1801,28 @@ static void __devinit es1968_measure_clock(es1968_t *chip) 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; @@ -1931,6 +1926,7 @@ static void es1968_update_hw_volume(unsigned long private_data) { 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 @@ -1945,11 +1941,15 @@ static void es1968_update_hw_volume(unsigned long private_data) 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 { @@ -1967,10 +1967,13 @@ static void es1968_update_hw_volume(unsigned long private_data) 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); } /* @@ -2005,6 +2008,12 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *r 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; @@ -2028,6 +2037,7 @@ snd_es1968_mixer(es1968_t *chip) 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; @@ -2405,7 +2415,7 @@ static int es1968_suspend(snd_card_t *card, unsigned int state) 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; } @@ -2418,6 +2428,7 @@ static int es1968_resume(snd_card_t *card, unsigned int state) /* 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.. */ @@ -2435,7 +2446,6 @@ static int es1968_resume(snd_card_t *card, unsigned int state) if (chip->bobclient) snd_es1968_bob_start(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ @@ -2461,6 +2471,7 @@ static int snd_es1968_free(es1968_t *chip) chip->master_switch = NULL; chip->master_volume = NULL; pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -2512,12 +2523,15 @@ static int __devinit snd_es1968_create(snd_card_t * card, 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; @@ -2525,6 +2539,7 @@ static int __devinit snd_es1968_create(snd_card_t * card, 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; @@ -2536,6 +2551,7 @@ static int __devinit snd_es1968_create(snd_card_t * 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);