summaryrefslogtreecommitdiff
path: root/sound/pci/es1968.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/es1968.c')
-rw-r--r--sound/pci/es1968.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 7d911a18c08..1bf298d214b 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 */
}