Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 312320 Details for
Bug 456215
RHEL 5.3 HDA ALSA driver update from upstream 2008-07-22 (fixes and support for new hw)
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
HDA update3 patch
rhel-5.3-hda-update3.patch (text/plain), 40.00 KB, created by
Jaroslav Kysela
on 2008-07-22 09:33:56 UTC
(
hide
)
Description:
HDA update3 patch
Filename:
MIME Type:
Creator:
Jaroslav Kysela
Created:
2008-07-22 09:33:56 UTC
Size:
40.00 KB
patch
obsolete
>From 2cf6d8f7540c170984c57b33c8c5b39962a8ac59 Mon Sep 17 00:00:00 2001 >From: Jaroslav Kysela <perex@perex.cz> >Date: Tue, 22 Jul 2008 11:22:06 +0200 >Subject: [PATCH] [RHEL 5.3 PATCH] ALSA HDA driver update from upstream 2008-07-22 > >This patch adds fixes (mainly DMA position fixes) and support for new >hardware from ALSA upstream. Also, documentation for snd-hda-module >was corrected. >--- > Documentation/sound/alsa/ALSA-Configuration.txt | 14 ++ > sound/pci/hda/hda_codec.h | 2 +- > sound/pci/hda/hda_intel.c | 165 ++++++++++++++----- > sound/pci/hda/hda_proc.c | 5 +- > sound/pci/hda/patch_analog.c | 38 +++-- > sound/pci/hda/patch_conexant.c | 33 ++-- > sound/pci/hda/patch_realtek.c | 199 +++++++++++++++++++++-- > sound/pci/hda/patch_sigmatel.c | 70 +++++--- > 8 files changed, 409 insertions(+), 117 deletions(-) > >diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt >index 10da45c..a5dbd59 100644 >--- a/Documentation/sound/alsa/ALSA-Configuration.txt >+++ b/Documentation/sound/alsa/ALSA-Configuration.txt >@@ -754,10 +754,24 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. > VIA VT8251/VT8237A, > SIS966, ULI M5461 > >+ [Multiple options for each card instance] > model - force the model name > position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) > single_cmd - Use single immediate commands to communicate with > codecs (for debugging only) >+ probe_mask - Bitmask to probe codecs (default = -1, meaning all slots) >+ bdl_pos_adj - Specifies the DMA IRQ timing delay in samples. >+ Passing -1 will make the driver to choose the appropriate >+ value based on the controller chip. >+ >+ [Single (global) options] >+ single_cmd - Use single immediate commands to communicate with >+ codecs (for debugging only) >+ enable_msi - Enable Message Signaled Interrupt (MSI) (default = off) >+ power_save - Automatic power-saving timtout (in second, 0 = >+ disable) >+ power_save_controller - Reset HD-audio controller in power-saving mode >+ (default = on) > > This module supports one card and autoprobe. > >diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h >index 9f523fa..456a280 100644 >--- a/sound/pci/hda/hda_codec.h >+++ b/sound/pci/hda/hda_codec.h >@@ -78,7 +78,7 @@ enum { > #define AC_VERB_GET_BEEP_CONTROL 0x0f0a > #define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c > #define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d >-#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e >+#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e /* unused */ > #define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f > /* f10-f1a: GPIO */ > #define AC_VERB_GET_GPIO_DATA 0x0f15 >diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c >index a56bb69..b008ad3 100644 >--- a/sound/pci/hda/hda_intel.c >+++ b/sound/pci/hda/hda_intel.c >@@ -56,6 +56,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; > static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; > static char *model[SNDRV_CARDS]; > static int position_fix[SNDRV_CARDS]; >+static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; > static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; > static int single_cmd; > static int enable_msi; >@@ -70,7 +71,9 @@ module_param_array(model, charp, NULL, 0444); > MODULE_PARM_DESC(model, "Use the given board model."); > module_param_array(position_fix, int, NULL, 0444); > MODULE_PARM_DESC(position_fix, "Fix DMA pointer " >- "(0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); >+ "(0 = auto, 1 = none, 2 = POSBUF)."); >+module_param_array(bdl_pos_adj, int, NULL, 0644); >+MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); > module_param_array(probe_mask, int, NULL, 0444); > MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); > module_param(single_cmd, bool, 0444); >@@ -264,9 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; > /* position fix mode */ > enum { > POS_FIX_AUTO, >- POS_FIX_NONE, >+ POS_FIX_LPIB, > POS_FIX_POSBUF, >- POS_FIX_FIFO, > }; > > /* Defines for ATI HD Audio support in SB450 south bridge */ >@@ -310,7 +312,8 @@ struct azx_dev { > > unsigned int opened :1; > unsigned int running :1; >- unsigned int irq_pending: 1; >+ unsigned int irq_pending :1; >+ unsigned int irq_ignore :1; > }; > > /* CORB/RIRB */ >@@ -328,6 +331,7 @@ struct azx_rb { > struct azx { > struct snd_card *card; > struct pci_dev *pci; >+ int dev_index; > > /* chip type specific */ > int driver_type; >@@ -371,6 +375,7 @@ struct azx { > unsigned int single_cmd :1; > unsigned int polling_mode :1; > unsigned int msi :1; >+ unsigned int irq_pending_warned :1; > > /* for debugging */ > unsigned int last_cmd; /* last issued command (to sync) */ >@@ -944,6 +949,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id, struct pt_regs *regs) > azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); > if (!azx_dev->substream || !azx_dev->running) > continue; >+ /* ignore the first dummy IRQ (due to pos_adj) */ >+ if (azx_dev->irq_ignore) { >+ azx_dev->irq_ignore = 0; >+ continue; >+ } > /* check whether this IRQ is really acceptable */ > if (azx_position_ok(chip, azx_dev)) { > azx_dev->irq_pending = 0; >@@ -978,14 +988,54 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id, struct pt_regs *regs) > > > /* >+ * set up a BDL entry >+ */ >+static int setup_bdle(struct snd_pcm_substream *substream, >+ struct azx_dev *azx_dev, u32 **bdlp, >+ int ofs, int size, int with_ioc) >+{ >+ struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream); >+ u32 *bdl = *bdlp; >+ >+ while (size > 0) { >+ dma_addr_t addr; >+ int chunk; >+ >+ if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) >+ return -EINVAL; >+ >+ addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs); >+ /* program the address field of the BDL entry */ >+ bdl[0] = cpu_to_le32((u32)addr); >+ bdl[1] = cpu_to_le32(upper_32bit(addr)); >+ /* program the size field of the BDL entry */ >+ chunk = PAGE_SIZE - (ofs % PAGE_SIZE); >+ if (size < chunk) >+ chunk = size; >+ bdl[2] = cpu_to_le32(chunk); >+ /* program the IOC to enable interrupt >+ * only when the whole fragment is processed >+ */ >+ size -= chunk; >+ bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); >+ bdl += 4; >+ azx_dev->frags++; >+ ofs += chunk; >+ } >+ *bdlp = bdl; >+ return ofs; >+} >+ >+/* > * set up BDL entries > */ >-static int azx_setup_periods(struct snd_pcm_substream *substream, >+static int azx_setup_periods(struct azx *chip, >+ struct snd_pcm_substream *substream, > struct azx_dev *azx_dev) > { >- struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream); > u32 *bdl; > int i, ofs, periods, period_bytes; >+ int pos_adj; > > /* reset BDL address */ > azx_sd_writel(azx_dev, SD_BDLPL, 0); >@@ -999,39 +1049,50 @@ static int azx_setup_periods(struct snd_pcm_substream *substream, > bdl = (u32 *)azx_dev->bdl.area; > ofs = 0; > azx_dev->frags = 0; >- for (i = 0; i < periods; i++) { >- int size, rest; >- if (i >= AZX_MAX_BDL_ENTRIES) { >- snd_printk(KERN_ERR "Too many BDL entries: " >- "buffer=%d, period=%d\n", >- azx_dev->bufsize, period_bytes); >- /* reset */ >- azx_sd_writel(azx_dev, SD_BDLPL, 0); >- azx_sd_writel(azx_dev, SD_BDLPU, 0); >- return -EINVAL; >+ azx_dev->irq_ignore = 0; >+ pos_adj = bdl_pos_adj[chip->dev_index]; >+ if (pos_adj > 0) { >+ struct snd_pcm_runtime *runtime = substream->runtime; >+ int pos_align = pos_adj; >+ pos_adj = (pos_adj * runtime->rate + 47999) / 48000; >+ if (!pos_adj) >+ pos_adj = pos_align; >+ else >+ pos_adj = ((pos_adj + pos_align - 1) / pos_align) * >+ pos_align; >+ pos_adj = frames_to_bytes(runtime, pos_adj); >+ if (pos_adj >= period_bytes) { >+ snd_printk(KERN_WARNING "Too big adjustment %d\n", >+ bdl_pos_adj[chip->dev_index]); >+ pos_adj = 0; >+ } else { >+ ofs = setup_bdle(substream, azx_dev, >+ &bdl, ofs, pos_adj, 1); >+ if (ofs < 0) >+ goto error; >+ azx_dev->irq_ignore = 1; > } >- rest = period_bytes; >- do { >- dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs); >- /* program the address field of the BDL entry */ >- bdl[0] = cpu_to_le32((u32)addr); >- bdl[1] = cpu_to_le32(upper_32bit(addr)); >- /* program the size field of the BDL entry */ >- size = PAGE_SIZE - (ofs % PAGE_SIZE); >- if (rest < size) >- size = rest; >- bdl[2] = cpu_to_le32(size); >- /* program the IOC to enable interrupt >- * only when the whole fragment is processed >- */ >- rest -= size; >- bdl[3] = rest ? 0 : cpu_to_le32(0x01); >- bdl += 4; >- azx_dev->frags++; >- ofs += size; >- } while (rest > 0); >+ } else >+ pos_adj = 0; >+ for (i = 0; i < periods; i++) { >+ if (i == periods - 1 && pos_adj) >+ ofs = setup_bdle(substream, azx_dev, &bdl, ofs, >+ period_bytes - pos_adj, 0); >+ else >+ ofs = setup_bdle(substream, azx_dev, &bdl, ofs, >+ period_bytes, 1); >+ if (ofs < 0) >+ goto error; > } > return 0; >+ >+ error: >+ snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", >+ azx_dev->bufsize, period_bytes); >+ /* reset */ >+ azx_sd_writel(azx_dev, SD_BDLPL, 0); >+ azx_sd_writel(azx_dev, SD_BDLPU, 0); >+ return -EINVAL; > } > > /* >@@ -1337,7 +1398,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) > > snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", > azx_dev->bufsize, azx_dev->format_val); >- if (azx_setup_periods(substream, azx_dev) < 0) >+ if (azx_setup_periods(chip, substream, azx_dev) < 0) > return -EINVAL; > azx_setup_controller(chip, azx_dev); > if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) >@@ -1454,8 +1515,6 @@ static unsigned int azx_get_position(struct azx *chip, > } else { > /* read LPIB */ > pos = azx_sd_readl(azx_dev, SD_LPIB); >- if (chip->position_fix == POS_FIX_FIFO) >- pos += azx_dev->fifo_size; > } > if (pos >= azx_dev->bufsize) > pos = 0; >@@ -1490,7 +1549,7 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) > printk(KERN_WARNING > "hda-intel: Invalid position buffer, " > "using LPIB read method instead.\n"); >- chip->position_fix = POS_FIX_NONE; >+ chip->position_fix = POS_FIX_LPIB; > pos = azx_get_position(chip, azx_dev); > } else > chip->position_fix = POS_FIX_POSBUF; >@@ -1510,6 +1569,14 @@ static void azx_irq_pending_work(void *data) > struct azx *chip = container_of(work, struct azx, irq_pending_work); > int i, pending; > >+ if (!chip->irq_pending_warned) { >+ printk(KERN_WARNING >+ "hda-intel: IRQ timing workaround is activated " >+ "for card #%d. Suggest a bigger bdl_pos_adj.\n", >+ chip->card->number); >+ chip->irq_pending_warned = 1; >+ } >+ > for (;;) { > pending = 0; > spin_lock_irq(&chip->reg_lock); >@@ -1866,9 +1933,9 @@ static int azx_dev_free(struct snd_device *device) > * white/black-listing for position_fix > */ > static struct snd_pci_quirk position_fix_list[] __devinitdata = { >- SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE), >- SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE), >- SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_NONE), >+ SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), >+ SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), >+ SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), > {} > }; > >@@ -1953,6 +2020,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, > chip->irq = -1; > chip->driver_type = driver_type; > chip->msi = enable_msi; >+ chip->dev_index = dev; > INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work, &chip->irq_pending_work); > > chip->position_fix = check_position_fix(chip, position_fix[dev]); >@@ -1960,6 +2028,17 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, > > chip->single_cmd = single_cmd; > >+ if (bdl_pos_adj[dev] < 0) { >+ switch (chip->driver_type) { >+ case AZX_DRIVER_ICH: >+ bdl_pos_adj[dev] = 1; >+ break; >+ default: >+ bdl_pos_adj[dev] = 32; >+ break; >+ } >+ } >+ > #if BITS_PER_LONG != 64 > /* Fix up base address on ULI M5461 */ > if (chip->driver_type == AZX_DRIVER_ULI) { >diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c >index aa8fade..a184a5c 100644 >--- a/sound/pci/hda/hda_proc.c >+++ b/sound/pci/hda/hda_proc.c >@@ -367,8 +367,6 @@ static void print_digital_conv(struct snd_info_buffer *buffer, > { > unsigned int digi1 = snd_hda_codec_read(codec, nid, 0, > AC_VERB_GET_DIGI_CONVERT_1, 0); >- unsigned int digi2 = snd_hda_codec_read(codec, nid, 0, >- AC_VERB_GET_DIGI_CONVERT_2, 0); > snd_iprintf(buffer, " Digital:"); > if (digi1 & AC_DIG1_ENABLE) > snd_iprintf(buffer, " Enabled"); >@@ -387,7 +385,8 @@ static void print_digital_conv(struct snd_info_buffer *buffer, > if (digi1 & AC_DIG1_LEVEL) > snd_iprintf(buffer, " GenLevel"); > snd_iprintf(buffer, "\n"); >- snd_iprintf(buffer, " Digital category: 0x%x\n", digi2 & AC_DIG2_CC); >+ snd_iprintf(buffer, " Digital category: 0x%x\n", >+ (digi1 >> 8) & AC_DIG2_CC); > } > > static const char *get_pwr_state(u32 state) >diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c >index 809a2a9..bc7faaf 100644 >--- a/sound/pci/hda/patch_analog.c >+++ b/sound/pci/hda/patch_analog.c >@@ -24,7 +24,6 @@ > #include <linux/delay.h> > #include <linux/slab.h> > #include <linux/pci.h> >-#include <linux/mutex.h> > > #include <sound/core.h> > #include "hda_codec.h" >@@ -65,7 +64,6 @@ struct ad198x_spec { > /* PCM information */ > struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ > >- struct mutex amp_mutex; /* PCM volume/mute control mutex */ > unsigned int spdif_route; > > /* dynamic controls, init_verbs and input_mux */ >@@ -1619,6 +1617,7 @@ static const char *ad1981_models[AD1981_MODELS] = { > > 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), >@@ -2624,7 +2623,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, > { > struct ad198x_spec *spec = codec->spec; > hda_nid_t nid; >- int idx, err; >+ int i, idx, err; > char name[32]; > > if (! pin) >@@ -2632,16 +2631,26 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, > > 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, >@@ -3178,7 +3187,6 @@ static int patch_ad1884(struct hda_codec *codec) > if (spec == NULL) > return -ENOMEM; > >- mutex_init(&spec->amp_mutex); > codec->spec = spec; > > spec->multiout.max_channels = 2; >@@ -3848,7 +3856,6 @@ static int patch_ad1884a(struct hda_codec *codec) > if (spec == NULL) > return -ENOMEM; > >- mutex_init(&spec->amp_mutex); > codec->spec = spec; > > spec->multiout.max_channels = 2; >@@ -4153,7 +4160,6 @@ static int patch_ad1882(struct hda_codec *codec) > if (spec == NULL) > return -ENOMEM; > >- mutex_init(&spec->amp_mutex); > codec->spec = spec; > > spec->multiout.max_channels = 6; >diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c >index c15088b..a6ab917 100644 >--- a/sound/pci/hda/patch_conexant.c >+++ b/sound/pci/hda/patch_conexant.c >@@ -83,7 +83,6 @@ struct conexant_spec { > /* PCM information */ > struct hda_pcm pcm_rec[2]; /* used in build_pcms() */ > >- struct mutex amp_mutex; /* PCM volume/mute control mutex */ > unsigned int spdif_route; > > /* dynamic controls, init_verbs and input_mux */ >@@ -688,7 +687,7 @@ static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { > > static struct hda_verb cxt5045_init_verbs[] = { > /* Line in, Mic */ >- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, >+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, > {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, > /* HP, Amp */ > {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, >@@ -908,10 +907,12 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = { > SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE), > SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), > SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE), >+ SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), > SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), > SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), > SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE), >- SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", CXT5045_LAPTOP_HPSENSE), >+ SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", >+ CXT5045_LAPTOP_HPMICSENSE), > SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), > SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), > SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), >@@ -929,7 +930,6 @@ static int patch_cxt5045(struct hda_codec *codec) > spec = kzalloc(sizeof(*spec), GFP_KERNEL); > if (!spec) > return -ENOMEM; >- mutex_init(&spec->amp_mutex); > codec->spec = spec; > > spec->multiout.max_channels = 2; >@@ -964,6 +964,7 @@ static int patch_cxt5045(struct hda_codec *codec) > codec->patch_ops.init = cxt5045_init; > break; > case CXT5045_LAPTOP_MICSENSE: >+ codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; > spec->input_mux = &cxt5045_capture_source; > spec->num_init_verbs = 2; > spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; >@@ -1008,15 +1009,19 @@ static int patch_cxt5045(struct hda_codec *codec) > #endif > } > >- /* >- * Fix max PCM level to 0 dB >- * (originall it has 0x2b steps with 0dB offset 0x14) >- */ >- snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, >- (0x14 << AC_AMPCAP_OFFSET_SHIFT) | >- (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) | >- (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | >- (1 << AC_AMPCAP_MUTE_SHIFT)); >+ switch (codec->subsystem_id >> 16) { >+ case 0x103c: >+ /* HP laptop has a really bad sound over 0dB on NID 0x17. >+ * Fix max PCM level to 0 dB >+ * (originall it has 0x2b steps with 0dB offset 0x14) >+ */ >+ snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, >+ (0x14 << AC_AMPCAP_OFFSET_SHIFT) | >+ (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) | >+ (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | >+ (1 << AC_AMPCAP_MUTE_SHIFT)); >+ break; >+ } > > return 0; > } >@@ -1478,7 +1483,6 @@ static int patch_cxt5047(struct hda_codec *codec) > spec = kzalloc(sizeof(*spec), GFP_KERNEL); > if (!spec) > return -ENOMEM; >- mutex_init(&spec->amp_mutex); > codec->spec = spec; > > spec->multiout.max_channels = 2; >@@ -1737,7 +1741,6 @@ static int patch_cxt5051(struct hda_codec *codec) > spec = kzalloc(sizeof(*spec), GFP_KERNEL); > if (!spec) > return -ENOMEM; >- mutex_init(&spec->amp_mutex); > codec->spec = spec; > > codec->patch_ops = conexant_patch_ops; >diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c >index 7613e37..ca89812 100644 >--- a/sound/pci/hda/patch_realtek.c >+++ b/sound/pci/hda/patch_realtek.c >@@ -123,6 +123,8 @@ enum { > /* ALC269 models */ > enum { > ALC269_BASIC, >+ ALC269_ASUS_EEEPC_P703, >+ ALC269_ASUS_EEEPC_P901, > ALC269_AUTO, > ALC269_MODEL_LAST /* last tag */ > }; >@@ -3075,6 +3077,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { > SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), > SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), > SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), >+ SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), > SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL), > SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), > SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), >@@ -5167,7 +5170,7 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = { > SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), > SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013), > SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013), >- SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP), >+ SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013), > SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013), > SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013), > SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP), >@@ -6193,6 +6196,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { > SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), > SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), > SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG), >+ SND_PCI_QUIRK(0x106b, 0x00a0, "Apple iMac 24''", ALC885_IMAC24), > SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG), > SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ > SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), >@@ -6518,8 +6522,9 @@ static int patch_alc882(struct hda_codec *codec) > case 0x106b1000: /* iMac 24 */ > board_config = ALC885_IMAC24; > break; >- case 0x106b00a1: /* Macbook */ >+ case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */ > case 0x106b2c00: /* Macbook Pro rev3 */ >+ case 0x106b3600: /* Macbook 3.1 */ > board_config = ALC885_MBP3; > break; > default: >@@ -7048,13 +7053,13 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = { > > static struct snd_kcontrol_new alc883_fivestack_mixer[] = { > HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), >- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), >+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), > HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), >- HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), >+ HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), > HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), > HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), >- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), >- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), >+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), >+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), > HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), > HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), > HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), >@@ -8840,6 +8845,7 @@ static struct hda_verb alc262_sony_unsol_verbs[] = { > > {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, > {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, >+ {} > }; > > /* mute/unmute internal speaker according to the hp jack and mute state */ >@@ -9719,6 +9725,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { > SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), > SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), > SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), >+ SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", >+ ALC262_SONY_ASSAMD), > SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), > SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), > SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), >@@ -10941,7 +10949,23 @@ static int patch_alc268(struct hda_codec *codec) > > static hda_nid_t alc269_adc_nids[1] = { > /* ADC1 */ >- 0x07, >+ 0x08, >+}; >+ >+static struct hda_input_mux alc269_eeepc_dmic_capture_source = { >+ .num_items = 2, >+ .items = { >+ { "i-Mic", 0x5 }, >+ { "e-Mic", 0x0 }, >+ }, >+}; >+ >+static struct hda_input_mux alc269_eeepc_amic_capture_source = { >+ .num_items = 2, >+ .items = { >+ { "i-Mic", 0x1 }, >+ { "e-Mic", 0x0 }, >+ }, > }; > > #define alc269_modes alc260_modes >@@ -10963,10 +10987,27 @@ static struct snd_kcontrol_new alc269_base_mixer[] = { > { } /* end */ > }; > >+/* bind volumes of both NID 0x0c and 0x0d */ >+static struct hda_bind_ctls alc269_epc_bind_vol = { >+ .ops = &snd_hda_bind_vol, >+ .values = { >+ HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), >+ HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT), >+ 0 >+ }, >+}; >+ >+static struct snd_kcontrol_new alc269_eeepc_mixer[] = { >+ HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), >+ HDA_BIND_VOL("LineOut Playback Volume", &alc269_epc_bind_vol), >+ HDA_CODEC_MUTE("LineOut Playback Switch", 0x15, 0x0, HDA_OUTPUT), >+ { } /* end */ >+}; >+ > /* capture mixer elements */ > static struct snd_kcontrol_new alc269_capture_mixer[] = { >- HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), >- HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), >+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), >+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), > { > .iface = SNDRV_CTL_ELEM_IFACE_MIXER, > /* The multiple "Capture Source" controls confuse alsamixer >@@ -10982,6 +11023,13 @@ static struct snd_kcontrol_new alc269_capture_mixer[] = { > { } /* end */ > }; > >+/* capture mixer elements */ >+static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { >+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), >+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), >+ { } /* end */ >+}; >+ > /* > * generic initialization of ADC, input mixers and output mixers > */ >@@ -10989,7 +11037,7 @@ static struct hda_verb alc269_init_verbs[] = { > /* > * Unmute ADC0 and set the default input to mic-in > */ >- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, >+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, > > /* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the > * analog-loopback mixer widget >@@ -11052,6 +11100,98 @@ static struct hda_verb alc269_init_verbs[] = { > { } > }; > >+static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { >+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, >+ {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, >+ {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, >+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))}, >+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, >+ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, >+ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, >+ {} >+}; >+ >+static struct hda_verb alc269_eeepc_amic_init_verbs[] = { >+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, >+ {0x23, AC_VERB_SET_CONNECT_SEL, 0x01}, >+ {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, >+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))}, >+ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, >+ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, >+ {} >+}; >+ >+/* toggle speaker-output according to the hp-jack state */ >+static void alc269_speaker_automute(struct hda_codec *codec) >+{ >+ unsigned int present; >+ unsigned int bits; >+ >+ present = snd_hda_codec_read(codec, 0x15, 0, >+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; >+ bits = present ? AMP_IN_MUTE(0) : 0; >+ snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, >+ AMP_IN_MUTE(0), bits); >+ snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, >+ AMP_IN_MUTE(0), bits); >+} >+ >+static void alc269_eeepc_dmic_automute(struct hda_codec *codec) >+{ >+ unsigned int present; >+ >+ present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0) >+ & AC_PINSENSE_PRESENCE; >+ snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_CONNECT_SEL, >+ present ? 0 : 5); >+} >+ >+static void alc269_eeepc_amic_automute(struct hda_codec *codec) >+{ >+ unsigned int present; >+ >+ present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0) >+ & AC_PINSENSE_PRESENCE; >+ snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE, >+ present ? AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0)); >+ snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE, >+ present ? AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1)); >+} >+ >+/* unsolicited event for HP jack sensing */ >+static void alc269_eeepc_dmic_unsol_event(struct hda_codec *codec, >+ unsigned int res) >+{ >+ if ((res >> 26) == ALC880_HP_EVENT) >+ alc269_speaker_automute(codec); >+ >+ if ((res >> 26) == ALC880_MIC_EVENT) >+ alc269_eeepc_dmic_automute(codec); >+} >+ >+static void alc269_eeepc_dmic_inithook(struct hda_codec *codec) >+{ >+ alc269_speaker_automute(codec); >+ alc269_eeepc_dmic_automute(codec); >+} >+ >+/* unsolicited event for HP jack sensing */ >+static void alc269_eeepc_amic_unsol_event(struct hda_codec *codec, >+ unsigned int res) >+{ >+ if ((res >> 26) == ALC880_HP_EVENT) >+ alc269_speaker_automute(codec); >+ >+ if ((res >> 26) == ALC880_MIC_EVENT) >+ alc269_eeepc_amic_automute(codec); >+} >+ >+static void alc269_eeepc_amic_inithook(struct hda_codec *codec) >+{ >+ alc269_speaker_automute(codec); >+ alc269_eeepc_amic_automute(codec); >+} >+ > /* add playback controls from the parsed DAC table */ > static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec, > const struct auto_pin_cfg *cfg) >@@ -11183,6 +11323,9 @@ static int alc269_parse_auto_config(struct hda_codec *codec) > if (err < 0) > return err; > >+ spec->mixers[spec->num_mixers] = alc269_capture_mixer; >+ spec->num_mixers++; >+ > return 1; > } > >@@ -11210,12 +11353,16 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { > }; > > static struct snd_pci_quirk alc269_cfg_tbl[] = { >+ SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", >+ ALC269_ASUS_EEEPC_P703), >+ SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", >+ ALC269_ASUS_EEEPC_P901), > {} > }; > > static struct alc_config_preset alc269_presets[] = { > [ALC269_BASIC] = { >- .mixers = { alc269_base_mixer }, >+ .mixers = { alc269_base_mixer, alc269_capture_mixer }, > .init_verbs = { alc269_init_verbs }, > .num_dacs = ARRAY_SIZE(alc269_dac_nids), > .dac_nids = alc269_dac_nids, >@@ -11224,6 +11371,32 @@ static struct alc_config_preset alc269_presets[] = { > .channel_mode = alc269_modes, > .input_mux = &alc269_capture_source, > }, >+ [ALC269_ASUS_EEEPC_P703] = { >+ .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer }, >+ .init_verbs = { alc269_init_verbs, >+ alc269_eeepc_amic_init_verbs }, >+ .num_dacs = ARRAY_SIZE(alc269_dac_nids), >+ .dac_nids = alc269_dac_nids, >+ .hp_nid = 0x03, >+ .num_channel_mode = ARRAY_SIZE(alc269_modes), >+ .channel_mode = alc269_modes, >+ .input_mux = &alc269_eeepc_amic_capture_source, >+ .unsol_event = alc269_eeepc_amic_unsol_event, >+ .init_hook = alc269_eeepc_amic_inithook, >+ }, >+ [ALC269_ASUS_EEEPC_P901] = { >+ .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer}, >+ .init_verbs = { alc269_init_verbs, >+ alc269_eeepc_dmic_init_verbs }, >+ .num_dacs = ARRAY_SIZE(alc269_dac_nids), >+ .dac_nids = alc269_dac_nids, >+ .hp_nid = 0x03, >+ .num_channel_mode = ARRAY_SIZE(alc269_modes), >+ .channel_mode = alc269_modes, >+ .input_mux = &alc269_eeepc_dmic_capture_source, >+ .unsol_event = alc269_eeepc_dmic_unsol_event, >+ .init_hook = alc269_eeepc_dmic_inithook, >+ }, > }; > > static int patch_alc269(struct hda_codec *codec) >@@ -11277,8 +11450,6 @@ static int patch_alc269(struct hda_codec *codec) > > spec->adc_nids = alc269_adc_nids; > spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); >- spec->mixers[spec->num_mixers] = alc269_capture_mixer; >- spec->num_mixers++; > > codec->patch_ops = alc_patch_ops; > if (board_config == ALC269_AUTO) >@@ -12989,6 +13160,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { > SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP), > SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), > SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), >+ SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC861VD_LENOVO), > SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), > SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), > SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), >@@ -12999,6 +13171,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { > SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), > SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), > SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), >+ SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 N200", ALC861VD_LENOVO), > SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), > {} > }; >diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c >index f713e1b..777588a 100644 >--- a/sound/pci/hda/patch_sigmatel.c >+++ b/sound/pci/hda/patch_sigmatel.c >@@ -637,21 +637,28 @@ static struct hda_verb stac92hd71bxx_core_init[] = { > { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, > }; > >+#define HD_DISABLE_PORTF 3 > static struct hda_verb stac92hd71bxx_analog_core_init[] = { >+ /* start of config #1 */ >+ >+ /* connect port 0f to audio mixer */ >+ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, >+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */ >+ /* unmute right and left channels for node 0x0f */ >+ { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, >+ /* start of config #2 */ >+ > /* set master volume and direct control */ > { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, > /* connect headphone jack to dac1 */ > { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, >- /* connect ports 0d and 0f to audio mixer */ >+ /* connect port 0d to audio mixer */ > { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x2}, >- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, >- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */ > /* unmute dac0 input in audio mixer */ > { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f}, >- /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ >+ /* unmute right and left channels for nodes 0x0a, 0xd */ > { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, > { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, >- { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, > {} > }; > >@@ -819,6 +826,9 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { > HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), > HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x1, 0x1b, 0x0, HDA_OUTPUT), > >+ HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT), >+ HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT), >+ > HDA_CODEC_MUTE("Analog Loopback 1", 0x17, 0x3, HDA_INPUT), > HDA_CODEC_MUTE("Analog Loopback 2", 0x17, 0x4, HDA_INPUT), > { } /* end */ >@@ -1318,13 +1328,13 @@ static unsigned int ref92hd71bxx_pin_configs[10] = { > 0x90a000f0, 0x01452050, > }; > >-static unsigned int dell_m4_1_pin_configs[13] = { >+static unsigned int dell_m4_1_pin_configs[10] = { > 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110, > 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0, > 0x40f000f0, 0x4f0000f0, > }; > >-static unsigned int dell_m4_2_pin_configs[13] = { >+static unsigned int dell_m4_2_pin_configs[10] = { > 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, > 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0, > 0x40f000f0, 0x044413b0, >@@ -1755,12 +1765,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { > "unknown Dell", STAC_9205_DELL_M42), > SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8, > "Dell Precision", STAC_9205_DELL_M43), >- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c, >- "Dell Precision", STAC_9205_DELL_M43), > SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9, > "Dell Precision", STAC_9205_DELL_M43), >- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b, >- "Dell Precision", STAC_9205_DELL_M43), > SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa, > "Dell Precision", STAC_9205_DELL_M43), > SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, >@@ -1771,18 +1777,14 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { > "Dell Precision", STAC_9205_DELL_M43), > SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff, > "Dell Precision M4300", STAC_9205_DELL_M43), >- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206, >- "Dell Precision", STAC_9205_DELL_M43), >- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, >- "Dell Inspiron", STAC_9205_DELL_M44), >- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, >- "Dell Inspiron", STAC_9205_DELL_M44), >- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, >- "Dell Inspiron", STAC_9205_DELL_M44), >- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, >- "Dell Inspiron", STAC_9205_DELL_M44), > SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204, > "unknown Dell", STAC_9205_DELL_M42), >+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206, >+ "Dell Precision", STAC_9205_DELL_M43), >+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b, >+ "Dell Precision", STAC_9205_DELL_M43), >+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c, >+ "Dell Precision", STAC_9205_DELL_M43), > SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, > "Dell Inspiron", STAC_9205_DELL_M44), > SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, >@@ -3104,13 +3106,16 @@ static int stac92xx_init(struct hda_codec *codec) > 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); > int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i], > 0, AC_VERB_GET_CONFIG_DEFAULT, 0); >+ def_conf = get_defcfg_connect(def_conf); > /* outputs are only ports capable of power management > * any attempts on powering down a input port cause the > * referenced VREF to act quirky. > */ > if (pinctl & AC_PINCTL_IN_EN) > continue; >- if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) >+ /* skip any ports that don't have jacks since presence >+ * detection is useless */ >+ if (def_conf && def_conf != AC_JACK_PORT_FIXED) > continue; > enable_pin_detect(codec, spec->pwr_nids[i], event | i); > codec->patch_ops.unsol_event(codec, (event | i) << 26); >@@ -3615,6 +3620,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) > > codec->spec = spec; > spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); >+ spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); > spec->pin_nids = stac92hd71bxx_pin_nids; > spec->board_config = snd_hda_check_board_config(codec, > STAC_92HD71BXX_MODELS, >@@ -3643,6 +3649,19 @@ again: > spec->mixer = stac92hd71bxx_mixer; > spec->init = stac92hd71bxx_core_init; > break; >+ case 0x111d7608: /* 5 Port with Analog Mixer */ >+ /* no output amps */ >+ spec->num_pwrs = 0; >+ spec->mixer = stac92hd71bxx_analog_mixer; >+ >+ /* disable VSW */ >+ spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; >+ stac92xx_set_config_reg(codec, 0xf, 0x40f000f0); >+ break; >+ case 0x111d7603: /* 6 Port with Analog Mixer */ >+ /* no output amps */ >+ spec->num_pwrs = 0; >+ /* fallthru */ > default: > spec->mixer = stac92hd71bxx_analog_mixer; > spec->init = stac92hd71bxx_analog_core_init; >@@ -3661,15 +3680,13 @@ again: > spec->adc_nids = stac92hd71bxx_adc_nids; > spec->dmic_nids = stac92hd71bxx_dmic_nids; > spec->dmux_nids = stac92hd71bxx_dmux_nids; >+ spec->pwr_nids = stac92hd71bxx_pwr_nids; > > spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); > spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); > spec->num_dmics = STAC92HD71BXX_NUM_DMICS; > spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); > >- spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); >- spec->pwr_nids = stac92hd71bxx_pwr_nids; >- > spec->multiout.num_dacs = 1; > spec->multiout.hp_nid = 0x11; > spec->multiout.dac_nids = stac92hd71bxx_dac_nids; >@@ -4307,10 +4324,11 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { > { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, > { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, > { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, >+ { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, >+ { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, > { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, > { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, > { .id = 0x111d7676, .name = "92HD73E1X5", .patch = patch_stac92hd73xx }, >- { .id = 0x111d7608, .name = "92HD71BXX", .patch = patch_stac92hd71bxx }, > { .id = 0x111d76b0, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, > { .id = 0x111d76b1, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, > { .id = 0x111d76b2, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, >-- >1.5.5.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 456215
: 312320