From c02bb253b1ebf7293274f4dcc025affe2378c779 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 Aug 2008 11:24:09 -0700 Subject: [PATCH] more .26 patches --- ...alog-digital-mixer-switch-on-audigy2.patch | 89 +++++++ ...da-add-missing-thinkpad-z60m-support.patch | 30 +++ ...alsa-hda-fix-dma-position-inaccuracy.patch | 242 ++++++++++++++++++ ...ng-volumes-in-ad1988-auto-probe-mode.patch | 70 +++++ queue-2.6.26/series | 4 + 5 files changed, 435 insertions(+) create mode 100644 queue-2.6.26/alsa-emu10k1-fix-inverted-analog-digital-mixer-switch-on-audigy2.patch create mode 100644 queue-2.6.26/alsa-hda-add-missing-thinkpad-z60m-support.patch create mode 100644 queue-2.6.26/alsa-hda-fix-dma-position-inaccuracy.patch create mode 100644 queue-2.6.26/alsa-hda-fix-wrong-volumes-in-ad1988-auto-probe-mode.patch 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 index 00000000000..321aeee8c40 --- /dev/null +++ b/queue-2.6.26/alsa-emu10k1-fix-inverted-analog-digital-mixer-switch-on-audigy2.patch @@ -0,0 +1,89 @@ +From d2cd74b158d7214a556226e3312f9fb1de64d7ae Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 2 Jun 2008 11:45:53 +0200 +Subject: ALSA: emu10k1 - Fix inverted Analog/Digital mixer switch on Audigy2 + +From: Takashi Iwai + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0d992cd0c1c --- /dev/null +++ b/queue-2.6.26/alsa-hda-add-missing-thinkpad-z60m-support.patch @@ -0,0 +1,30 @@ +From 470eaf6be78424fc499a5039e5d5fe58bace2bc3 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 30 Jun 2008 16:40:10 +0200 +Subject: ALSA: hda - Add missing Thinkpad Z60m support + +From: Takashi Iwai + +commit 470eaf6be78424fc499a5039e5d5fe58bace2bc3 upstream + +Added the missing SSID of Thinkpad Z60m for model=thinkpad with +AD1981HD. + +Signed-off-by: Takashi Iwai +Signed-off-by: Jaroslav Kysela +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..f03f7086951 --- /dev/null +++ b/queue-2.6.26/alsa-hda-fix-dma-position-inaccuracy.patch @@ -0,0 +1,242 @@ +From 9ad593f6d326e7a4664e3856520f6c042f82a37f Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 16 May 2008 12:34:47 +0200 +Subject: ALSA: hda - Fix DMA position inaccuracy + +From: Takashi Iwai + +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 +Signed-off-by: Jaroslav Kysela +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..6140ee3287b --- /dev/null +++ b/queue-2.6.26/alsa-hda-fix-wrong-volumes-in-ad1988-auto-probe-mode.patch @@ -0,0 +1,70 @@ +From 43785eaeb1cfb8aed3cf8027f298b242f88fdc45 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 16 Jun 2008 15:47:26 +0200 +Subject: ALSA: hda - Fix wrong volumes in AD1988 auto-probe mode + +From: Takashi Iwai + +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 +Signed-off-by: Jaroslav Kysela +Signed-off-by: Greg Kroah-Hartman + +--- + 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, diff --git a/queue-2.6.26/series b/queue-2.6.26/series index 56200b533c4..62fd3ad6f3b 100644 --- a/queue-2.6.26/series +++ b/queue-2.6.26/series @@ -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 -- 2.47.3