diff options
Diffstat (limited to 'sound/pci/es1968.c')
-rw-r--r-- | sound/pci/es1968.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 7d911a18c082..1bf298d214b9 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -1827,6 +1827,22 @@ snd_es1968_pcm(struct es1968 *chip, int device) return 0; } +/* + * suppress jitter on some maestros when playing stereo + */ +static void snd_es1968_suppress_jitter(struct es1968 *chip, struct esschan *es) +{ + unsigned int cp1; + unsigned int cp2; + unsigned int diff; + + cp1 = __apu_get_register(chip, 0, 5); + cp2 = __apu_get_register(chip, 1, 5); + diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1); + + if (diff > 1) + __maestro_write(chip, IDR0_DATA_PORT, cp1); +} /* * update pointer @@ -1948,8 +1964,11 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id) struct esschan *es; spin_lock(&chip->substream_lock); list_for_each_entry(es, &chip->substream_list, list) { - if (es->running) + if (es->running) { snd_es1968_update_pcm(chip, es); + if (es->fmt & ESS_FMT_STEREO) + snd_es1968_suppress_jitter(chip, es); + } } spin_unlock(&chip->substream_lock); if (chip->in_measurement) { @@ -1972,7 +1991,7 @@ snd_es1968_mixer(struct es1968 *chip) { struct snd_ac97_bus *pbus; struct snd_ac97_template ac97; - struct snd_ctl_elem_id id; + struct snd_ctl_elem_id elem_id; int err; static struct snd_ac97_bus_ops ops = { .write = snd_es1968_ac97_write, @@ -1989,14 +2008,14 @@ snd_es1968_mixer(struct es1968 *chip) return err; /* attach master switch / volumes for h/w volume control */ - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, "Master Playback Switch"); - chip->master_switch = snd_ctl_find_id(chip->card, &id); - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, "Master Playback Volume"); - chip->master_volume = snd_ctl_find_id(chip->card, &id); + memset(&elem_id, 0, sizeof(elem_id)); + elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + strcpy(elem_id.name, "Master Playback Switch"); + chip->master_switch = snd_ctl_find_id(chip->card, &elem_id); + memset(&elem_id, 0, sizeof(elem_id)); + elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + strcpy(elem_id.name, "Master Playback Volume"); + chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); return 0; } @@ -2456,7 +2475,8 @@ static inline void snd_es1968_free_gameport(struct es1968 *chip) { } static int snd_es1968_free(struct es1968 *chip) { if (chip->io_port) { - synchronize_irq(chip->irq); + if (chip->irq >= 0) + synchronize_irq(chip->irq); outw(1, chip->io_port + 0x04); /* clear WP interrupts */ outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */ } |