]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more .26 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Mon, 4 Aug 2008 18:24:09 +0000 (11:24 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 4 Aug 2008 18:24:09 +0000 (11:24 -0700)
queue-2.6.26/alsa-emu10k1-fix-inverted-analog-digital-mixer-switch-on-audigy2.patch [new file with mode: 0644]
queue-2.6.26/alsa-hda-add-missing-thinkpad-z60m-support.patch [new file with mode: 0644]
queue-2.6.26/alsa-hda-fix-dma-position-inaccuracy.patch [new file with mode: 0644]
queue-2.6.26/alsa-hda-fix-wrong-volumes-in-ad1988-auto-probe-mode.patch [new file with mode: 0644]
queue-2.6.26/series

diff --git a/queue-2.6.26/alsa-emu10k1-fix-inverted-analog-digital-mixer-switch-on-audigy2.patch b/queue-2.6.26/alsa-emu10k1-fix-inverted-analog-digital-mixer-switch-on-audigy2.patch
new file mode 100644 (file)
index 0000000..321aeee
--- /dev/null
@@ -0,0 +1,89 @@
+From d2cd74b158d7214a556226e3312f9fb1de64d7ae Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 2 Jun 2008 11:45:53 +0200
+Subject: ALSA: emu10k1 - Fix inverted Analog/Digital mixer switch on Audigy2
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit d2cd74b158d7214a556226e3312f9fb1de64d7ae upstream
+
+On Audigy2 Platinum, the Analog/Digital mixer switch is inverted.
+       https://bugzilla.novell.com/show_bug.cgi?id=396204
+
+The patch adds a simple workaround.
+
+There might be another device requiring a similar fix, too (or fix for
+audigy2 generically), but right now I fix only the known broken one.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/sound/emu10k1.h          |    1 +
+ sound/pci/emu10k1/emu10k1_main.c |    1 +
+ sound/pci/emu10k1/emumixer.c     |   13 ++++++++++---
+ 3 files changed, 12 insertions(+), 3 deletions(-)
+
+--- a/include/sound/emu10k1.h
++++ b/include/sound/emu10k1.h
+@@ -1670,6 +1670,7 @@ struct snd_emu_chip_details {
+       unsigned char spi_dac;      /* SPI interface for DAC */
+       unsigned char i2c_adc;      /* I2C interface for ADC */
+       unsigned char adc_1361t;    /* Use Philips 1361T ADC */
++      unsigned char invert_shared_spdif; /* analog/digital switch inverted */
+       const char *driver;
+       const char *name;
+       const char *id;         /* for backward compatibility - can be NULL if not needed */
+--- a/sound/pci/emu10k1/emu10k1_main.c
++++ b/sound/pci/emu10k1/emu10k1_main.c
+@@ -1528,6 +1528,7 @@ static struct snd_emu_chip_details emu_c
+        .ca0151_chip = 1,
+        .spk71 = 1,
+        .spdif_bug = 1,
++       .invert_shared_spdif = 1,      /* digital/analog switch swapped */
+        .adc_1361t = 1,  /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */
+        .ac97_chip = 1} ,
+       {.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
+--- a/sound/pci/emu10k1/emumixer.c
++++ b/sound/pci/emu10k1/emumixer.c
+@@ -1578,6 +1578,10 @@ static int snd_emu10k1_shared_spdif_get(
+               ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
+       else
+               ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
++      if (emu->card_capabilities->invert_shared_spdif)
++              ucontrol->value.integer.value[0] =
++                      !ucontrol->value.integer.value[0];
++
+       return 0;
+ }
+@@ -1586,15 +1590,18 @@ static int snd_emu10k1_shared_spdif_put(
+ {
+       unsigned long flags;
+       struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+-      unsigned int reg, val;
++      unsigned int reg, val, sw;
+       int change = 0;
++      sw = ucontrol->value.integer.value[0];
++      if (emu->card_capabilities->invert_shared_spdif)
++              sw = !sw;
+       spin_lock_irqsave(&emu->reg_lock, flags);
+       if ( emu->card_capabilities->i2c_adc) {
+               /* Do nothing for Audigy 2 ZS Notebook */
+       } else if (emu->audigy) {
+               reg = inl(emu->port + A_IOCFG);
+-              val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
++              val = sw ? A_IOCFG_GPOUT0 : 0;
+               change = (reg & A_IOCFG_GPOUT0) != val;
+               if (change) {
+                       reg &= ~A_IOCFG_GPOUT0;
+@@ -1603,7 +1610,7 @@ static int snd_emu10k1_shared_spdif_put(
+               }
+       }
+       reg = inl(emu->port + HCFG);
+-      val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
++      val = sw ? HCFG_GPOUT0 : 0;
+       change |= (reg & HCFG_GPOUT0) != val;
+       if (change) {
+               reg &= ~HCFG_GPOUT0;
diff --git a/queue-2.6.26/alsa-hda-add-missing-thinkpad-z60m-support.patch b/queue-2.6.26/alsa-hda-add-missing-thinkpad-z60m-support.patch
new file mode 100644 (file)
index 0000000..0d992cd
--- /dev/null
@@ -0,0 +1,30 @@
+From 470eaf6be78424fc499a5039e5d5fe58bace2bc3 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 30 Jun 2008 16:40:10 +0200
+Subject: ALSA: hda - Add missing Thinkpad Z60m support
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 470eaf6be78424fc499a5039e5d5fe58bace2bc3 upstream
+
+Added the missing SSID of Thinkpad Z60m for model=thinkpad with
+AD1981HD.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/patch_analog.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_analog.c
++++ b/sound/pci/hda/patch_analog.c
+@@ -1618,6 +1618,7 @@ static const char *ad1981_models[AD1981_
+ static struct snd_pci_quirk ad1981_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
++      SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
+       /* All HP models */
+       SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
+       SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
diff --git a/queue-2.6.26/alsa-hda-fix-dma-position-inaccuracy.patch b/queue-2.6.26/alsa-hda-fix-dma-position-inaccuracy.patch
new file mode 100644 (file)
index 0000000..f03f708
--- /dev/null
@@ -0,0 +1,242 @@
+From 9ad593f6d326e7a4664e3856520f6c042f82a37f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 16 May 2008 12:34:47 +0200
+Subject: ALSA: hda - Fix DMA position inaccuracy
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 9ad593f6d326e7a4664e3856520f6c042f82a37f upstream
+
+Many HD-audio controllers seem inaccurate about the IRQ timing of
+PCM period updates.  This has caused problems on audio quality; e.g.
+JACK doesn't work with two periods.
+
+This patch fixes the problem by checking the current DMA position
+at IRQ handler and delays the period-update via a workq if it's
+inaccurate.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/hda_intel.c |  124 +++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 106 insertions(+), 18 deletions(-)
+
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -285,6 +285,7 @@ struct azx_dev {
+       u32 *posbuf;            /* position buffer pointer */
+       unsigned int bufsize;   /* size of the play buffer in bytes */
++      unsigned int period_bytes; /* size of the period in bytes */
+       unsigned int frags;     /* number for period in the play buffer */
+       unsigned int fifo_size; /* FIFO size */
+@@ -301,11 +302,10 @@ struct azx_dev {
+                                        */
+       unsigned char stream_tag;       /* assigned stream */
+       unsigned char index;            /* stream index */
+-      /* for sanity check of position buffer */
+-      unsigned int period_intr;
+       unsigned int opened :1;
+       unsigned int running :1;
++      unsigned int irq_pending: 1;
+ };
+ /* CORB/RIRB */
+@@ -369,6 +369,9 @@ struct azx {
+       /* for debugging */
+       unsigned int last_cmd;  /* last issued command (to sync) */
++
++      /* for pending irqs */
++      struct work_struct irq_pending_work;
+ };
+ /* driver types */
+@@ -908,6 +911,8 @@ static void azx_init_pci(struct azx *chi
+ }
++static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
++
+ /*
+  * interrupt handler
+  */
+@@ -930,11 +935,18 @@ static irqreturn_t azx_interrupt(int irq
+               azx_dev = &chip->azx_dev[i];
+               if (status & azx_dev->sd_int_sta_mask) {
+                       azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
+-                      if (azx_dev->substream && azx_dev->running) {
+-                              azx_dev->period_intr++;
++                      if (!azx_dev->substream || !azx_dev->running)
++                              continue;
++                      /* check whether this IRQ is really acceptable */
++                      if (azx_position_ok(chip, azx_dev)) {
++                              azx_dev->irq_pending = 0;
+                               spin_unlock(&chip->reg_lock);
+                               snd_pcm_period_elapsed(azx_dev->substream);
+                               spin_lock(&chip->reg_lock);
++                      } else {
++                              /* bogus IRQ, process it later */
++                              azx_dev->irq_pending = 1;
++                              schedule_work(&chip->irq_pending_work);
+                       }
+               }
+       }
+@@ -973,6 +985,7 @@ static int azx_setup_periods(struct snd_
+       azx_sd_writel(azx_dev, SD_BDLPU, 0);
+       period_bytes = snd_pcm_lib_period_bytes(substream);
++      azx_dev->period_bytes = period_bytes;
+       periods = azx_dev->bufsize / period_bytes;
+       /* program the initial BDL entries */
+@@ -1421,27 +1434,16 @@ static int azx_pcm_trigger(struct snd_pc
+       return 0;
+ }
+-static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
++static unsigned int azx_get_position(struct azx *chip,
++                                   struct azx_dev *azx_dev)
+ {
+-      struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+-      struct azx *chip = apcm->chip;
+-      struct azx_dev *azx_dev = get_azx_dev(substream);
+       unsigned int pos;
+       if (chip->position_fix == POS_FIX_POSBUF ||
+           chip->position_fix == POS_FIX_AUTO) {
+               /* use the position buffer */
+               pos = le32_to_cpu(*azx_dev->posbuf);
+-              if (chip->position_fix == POS_FIX_AUTO &&
+-                  azx_dev->period_intr == 1 && !pos) {
+-                      printk(KERN_WARNING
+-                             "hda-intel: Invalid position buffer, "
+-                             "using LPIB read method instead.\n");
+-                      chip->position_fix = POS_FIX_NONE;
+-                      goto read_lpib;
+-              }
+       } else {
+-      read_lpib:
+               /* read LPIB */
+               pos = azx_sd_readl(azx_dev, SD_LPIB);
+               if (chip->position_fix == POS_FIX_FIFO)
+@@ -1449,7 +1451,90 @@ static snd_pcm_uframes_t azx_pcm_pointer
+       }
+       if (pos >= azx_dev->bufsize)
+               pos = 0;
+-      return bytes_to_frames(substream->runtime, pos);
++      return pos;
++}
++
++static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
++{
++      struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
++      struct azx *chip = apcm->chip;
++      struct azx_dev *azx_dev = get_azx_dev(substream);
++      return bytes_to_frames(substream->runtime,
++                             azx_get_position(chip, azx_dev));
++}
++
++/*
++ * Check whether the current DMA position is acceptable for updating
++ * periods.  Returns non-zero if it's OK.
++ *
++ * Many HD-audio controllers appear pretty inaccurate about
++ * the update-IRQ timing.  The IRQ is issued before actually the
++ * data is processed.  So, we need to process it afterwords in a
++ * workqueue.
++ */
++static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
++{
++      unsigned int pos;
++
++      pos = azx_get_position(chip, azx_dev);
++      if (chip->position_fix == POS_FIX_AUTO) {
++              if (!pos) {
++                      printk(KERN_WARNING
++                             "hda-intel: Invalid position buffer, "
++                             "using LPIB read method instead.\n");
++                      chip->position_fix = POS_FIX_NONE;
++                      pos = azx_get_position(chip, azx_dev);
++              } else
++                      chip->position_fix = POS_FIX_POSBUF;
++      }
++
++      if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
++              return 0; /* NG - it's below the period boundary */
++      return 1; /* OK, it's fine */
++}
++
++/*
++ * The work for pending PCM period updates.
++ */
++static void azx_irq_pending_work(struct work_struct *work)
++{
++      struct azx *chip = container_of(work, struct azx, irq_pending_work);
++      int i, pending;
++
++      for (;;) {
++              pending = 0;
++              spin_lock_irq(&chip->reg_lock);
++              for (i = 0; i < chip->num_streams; i++) {
++                      struct azx_dev *azx_dev = &chip->azx_dev[i];
++                      if (!azx_dev->irq_pending ||
++                          !azx_dev->substream ||
++                          !azx_dev->running)
++                              continue;
++                      if (azx_position_ok(chip, azx_dev)) {
++                              azx_dev->irq_pending = 0;
++                              spin_unlock(&chip->reg_lock);
++                              snd_pcm_period_elapsed(azx_dev->substream);
++                              spin_lock(&chip->reg_lock);
++                      } else
++                              pending++;
++              }
++              spin_unlock_irq(&chip->reg_lock);
++              if (!pending)
++                      return;
++              cond_resched();
++      }
++}
++
++/* clear irq_pending flags and assure no on-going workq */
++static void azx_clear_irq_pending(struct azx *chip)
++{
++      int i;
++
++      spin_lock_irq(&chip->reg_lock);
++      for (i = 0; i < chip->num_streams; i++)
++              chip->azx_dev[i].irq_pending = 0;
++      spin_unlock_irq(&chip->reg_lock);
++      flush_scheduled_work();
+ }
+ static struct snd_pcm_ops azx_pcm_ops = {
+@@ -1676,6 +1761,7 @@ static int azx_suspend(struct pci_dev *p
+       int i;
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
++      azx_clear_irq_pending(chip);
+       for (i = 0; i < AZX_MAX_PCMS; i++)
+               snd_pcm_suspend_all(chip->pcm[i]);
+       if (chip->initialized)
+@@ -1732,6 +1818,7 @@ static int azx_free(struct azx *chip)
+       int i;
+       if (chip->initialized) {
++              azx_clear_irq_pending(chip);
+               for (i = 0; i < chip->num_streams; i++)
+                       azx_stream_stop(chip, &chip->azx_dev[i]);
+               azx_stop_chip(chip);
+@@ -1857,6 +1944,7 @@ static int __devinit azx_create(struct s
+       chip->irq = -1;
+       chip->driver_type = driver_type;
+       chip->msi = enable_msi;
++      INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
+       chip->position_fix = check_position_fix(chip, position_fix[dev]);
+       check_probe_mask(chip, dev);
diff --git a/queue-2.6.26/alsa-hda-fix-wrong-volumes-in-ad1988-auto-probe-mode.patch b/queue-2.6.26/alsa-hda-fix-wrong-volumes-in-ad1988-auto-probe-mode.patch
new file mode 100644 (file)
index 0000000..6140ee3
--- /dev/null
@@ -0,0 +1,70 @@
+From 43785eaeb1cfb8aed3cf8027f298b242f88fdc45 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 16 Jun 2008 15:47:26 +0200
+Subject: ALSA: hda - Fix wrong volumes in AD1988 auto-probe mode
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 43785eaeb1cfb8aed3cf8027f298b242f88fdc45 upstream
+
+Don't create mixer volume elements for Headphone and Speaker if they
+use the same DAC as normal line-outs on AD1988.  Otherwise the amp
+value gets screwed up, e.g.
+       https://bugzilla.novell.com/show_bug.cgi?id=398255
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ sound/pci/hda/patch_analog.c |   32 +++++++++++++++++++++-----------
+ 1 file changed, 21 insertions(+), 11 deletions(-)
+
+--- a/sound/pci/hda/patch_analog.c
++++ b/sound/pci/hda/patch_analog.c
+@@ -2623,7 +2623,7 @@ static int ad1988_auto_create_extra_out(
+ {
+       struct ad198x_spec *spec = codec->spec;
+       hda_nid_t nid;
+-      int idx, err;
++      int i, idx, err;
+       char name[32];
+       if (! pin)
+@@ -2631,16 +2631,26 @@ static int ad1988_auto_create_extra_out(
+       idx = ad1988_pin_idx(pin);
+       nid = ad1988_idx_to_dac(codec, idx);
+-      /* specify the DAC as the extra output */
+-      if (! spec->multiout.hp_nid)
+-              spec->multiout.hp_nid = nid;
+-      else
+-              spec->multiout.extra_out_nid[0] = nid;
+-      /* control HP volume/switch on the output mixer amp */
+-      sprintf(name, "%s Playback Volume", pfx);
+-      if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
+-                             HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+-              return err;
++      /* check whether the corresponding DAC was already taken */
++      for (i = 0; i < spec->autocfg.line_outs; i++) {
++              hda_nid_t pin = spec->autocfg.line_out_pins[i];
++              hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
++              if (dac == nid)
++                      break;
++      }
++      if (i >= spec->autocfg.line_outs) {
++              /* specify the DAC as the extra output */
++              if (!spec->multiout.hp_nid)
++                      spec->multiout.hp_nid = nid;
++              else
++                      spec->multiout.extra_out_nid[0] = nid;
++              /* control HP volume/switch on the output mixer amp */
++              sprintf(name, "%s Playback Volume", pfx);
++              err = add_control(spec, AD_CTL_WIDGET_VOL, name,
++                                HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
++              if (err < 0)
++                      return err;
++      }
+       nid = ad1988_mixer_nids[idx];
+       sprintf(name, "%s Playback Switch", pfx);
+       if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
index 56200b533c41873a4c4d434d07b053bfd7605bf8..62fd3ad6f3bbbf2312c87c8babd469346e113863 100644 (file)
@@ -16,3 +16,7 @@ input-i8042-add-gericom-bellagio-to-nomux-blacklist.patch
 input-i8042-add-acer-aspire-1360-to-nomux-blacklist.patch
 bluetooth-signal-user-space-for-hidp-and-bnep-socket-errors.patch
 add-compat-handler-for-ptrace_getsiginfo.patch
+alsa-hda-fix-wrong-volumes-in-ad1988-auto-probe-mode.patch
+alsa-hda-fix-dma-position-inaccuracy.patch
+alsa-hda-add-missing-thinkpad-z60m-support.patch
+alsa-emu10k1-fix-inverted-analog-digital-mixer-switch-on-audigy2.patch