diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 35 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_eld.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 50 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 61 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 21 | ||||
-rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 8 | ||||
-rw-r--r-- | sound/pci/hda/patch_nvhdmi.c | 10 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 210 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 17 |
12 files changed, 330 insertions, 92 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index dd8fb86c842b..14829210ef0b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -589,6 +589,7 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card, bus->ops = temp->ops; mutex_init(&bus->cmd_mutex); + mutex_init(&bus->prepare_mutex); INIT_LIST_HEAD(&bus->codec_list); snprintf(bus->workq_name, sizeof(bus->workq_name), @@ -1068,7 +1069,6 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, codec->addr = codec_addr; mutex_init(&codec->spdif_mutex); mutex_init(&codec->control_mutex); - mutex_init(&codec->prepare_mutex); init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); @@ -1213,6 +1213,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, int channel_id, int format) { + struct hda_codec *c; struct hda_cvt_setup *p; unsigned int oldval, newval; int i; @@ -1253,10 +1254,12 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, p->dirty = 0; /* make other inactive cvts with the same stream-tag dirty */ - for (i = 0; i < codec->cvt_setups.used; i++) { - p = snd_array_elem(&codec->cvt_setups, i); - if (!p->active && p->stream_tag == stream_tag) - p->dirty = 1; + list_for_each_entry(c, &codec->bus->codec_list, list) { + for (i = 0; i < c->cvt_setups.used; i++) { + p = snd_array_elem(&c->cvt_setups, i); + if (!p->active && p->stream_tag == stream_tag) + p->dirty = 1; + } } } EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); @@ -1306,12 +1309,16 @@ static void really_cleanup_stream(struct hda_codec *codec, /* clean up the all conflicting obsolete streams */ static void purify_inactive_streams(struct hda_codec *codec) { + struct hda_codec *c; int i; - for (i = 0; i < codec->cvt_setups.used; i++) { - struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i); - if (p->dirty) - really_cleanup_stream(codec, p); + list_for_each_entry(c, &codec->bus->codec_list, list) { + for (i = 0; i < c->cvt_setups.used; i++) { + struct hda_cvt_setup *p; + p = snd_array_elem(&c->cvt_setups, i); + if (p->dirty) + really_cleanup_stream(c, p); + } } } @@ -3502,11 +3509,11 @@ int snd_hda_codec_prepare(struct hda_codec *codec, struct snd_pcm_substream *substream) { int ret; - mutex_lock(&codec->prepare_mutex); + mutex_lock(&codec->bus->prepare_mutex); ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream); if (ret >= 0) purify_inactive_streams(codec); - mutex_unlock(&codec->prepare_mutex); + mutex_unlock(&codec->bus->prepare_mutex); return ret; } EXPORT_SYMBOL_HDA(snd_hda_codec_prepare); @@ -3515,9 +3522,9 @@ void snd_hda_codec_cleanup(struct hda_codec *codec, struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { - mutex_lock(&codec->prepare_mutex); + mutex_lock(&codec->bus->prepare_mutex); hinfo->ops.cleanup(hinfo, codec, substream); - mutex_unlock(&codec->prepare_mutex); + mutex_unlock(&codec->bus->prepare_mutex); } EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup); @@ -4529,7 +4536,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->hp_outs--; memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1, sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i)); - memmove(sequences_hp + i - 1, sequences_hp + i, + memmove(sequences_hp + i, sequences_hp + i + 1, sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); } } diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 4303353feda9..62c702240108 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -648,6 +648,7 @@ struct hda_bus { struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; struct mutex cmd_mutex; + struct mutex prepare_mutex; /* unsolicited event queue */ struct hda_bus_unsolicited *unsol; @@ -826,7 +827,6 @@ struct hda_codec { struct mutex spdif_mutex; struct mutex control_mutex; - struct mutex prepare_mutex; unsigned int spdif_status; /* IEC958 status bits */ unsigned short spdif_ctls; /* SPDIF control bits */ unsigned int spdif_in_enable; /* SPDIF input enable? */ diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 803b298f7411..26c3ade73583 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -596,6 +596,8 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) } EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); +#endif /* CONFIG_PROC_FS */ + /* update PCM info based on ELD */ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm, struct hda_pcm_stream *codec_pars) @@ -644,5 +646,3 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm, pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps); } EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info); - -#endif /* CONFIG_PROC_FS */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1053fff4bd0a..34940a079051 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -126,6 +126,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, ICH10}," "{Intel, PCH}," "{Intel, CPT}," + "{Intel, PBG}," "{Intel, SCH}," "{ATI, SB450}," "{ATI, SB600}," @@ -2749,6 +2750,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH }, /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, + /* PBG */ + { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, /* ATI SB 450/600 */ diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index b697fd2a6f8b..10bbbaf6ebc3 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3641,6 +3641,7 @@ static struct snd_pci_quirk ad1984_cfg_tbl[] = { /* Lenovo Thinkpad T61/X61 */ SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), + SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP), {} }; diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 4ef5efaaaef1..488fd9ade1ba 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -972,6 +972,53 @@ static struct hda_verb cs_coef_init_verbs[] = { {} /* terminator */ }; +/* Errata: CS4207 rev C0/C1/C2 Silicon + * + * http://www.cirrus.com/en/pubs/errata/ER880C3.pdf + * + * 6. At high temperature (TA > +85°C), the digital supply current (IVD) + * may be excessive (up to an additional 200 μA), which is most easily + * observed while the part is being held in reset (RESET# active low). + * + * Root Cause: At initial powerup of the device, the logic that drives + * the clock and write enable to the S/PDIF SRC RAMs is not properly + * initialized. + * Certain random patterns will cause a steady leakage current in those + * RAM cells. The issue will resolve once the SRCs are used (turned on). + * + * Workaround: The following verb sequence briefly turns on the S/PDIF SRC + * blocks, which will alleviate the issue. + */ + +static struct hda_verb cs_errata_init_verbs[] = { + {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */ + {0x11, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */ + + {0x11, AC_VERB_SET_COEF_INDEX, 0x0008}, + {0x11, AC_VERB_SET_PROC_COEF, 0x9999}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0017}, + {0x11, AC_VERB_SET_PROC_COEF, 0xa412}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, + {0x11, AC_VERB_SET_PROC_COEF, 0x0009}, + + {0x07, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Rx: D0 */ + {0x08, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Tx: D0 */ + + {0x11, AC_VERB_SET_COEF_INDEX, 0x0017}, + {0x11, AC_VERB_SET_PROC_COEF, 0x2412}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0008}, + {0x11, AC_VERB_SET_PROC_COEF, 0x0000}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, + {0x11, AC_VERB_SET_PROC_COEF, 0x0008}, + {0x11, AC_VERB_SET_PROC_STATE, 0x00}, + + {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */ + {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */ + /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */ + + {} /* terminator */ +}; + /* SPDIF setup */ static void init_digital(struct hda_codec *codec) { @@ -991,6 +1038,9 @@ static int cs_init(struct hda_codec *codec) { struct cs_spec *spec = codec->spec; + /* init_verb sequence for C0/C1/C2 errata*/ + snd_hda_sequence_write(codec, cs_errata_init_verbs); + snd_hda_sequence_write(codec, cs_coef_init_verbs); if (spec->gpio_mask) { diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 31b5d9eeba68..972e7c453b3d 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -116,6 +116,7 @@ struct conexant_spec { unsigned int dell_vostro:1; unsigned int ideapad:1; unsigned int thinkpad:1; + unsigned int hp_laptop:1; unsigned int ext_mic_present; unsigned int recording; @@ -2299,6 +2300,18 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec) } } +/* toggle input of built-in digital mic and mic jack appropriately */ +static void cxt5066_hp_laptop_automic(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_jack_detect(codec, 0x1b); + snd_printdd("CXT5066: external microphone present=%d\n", present); + snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, + present ? 1 : 3); +} + + /* toggle input of built-in digital mic and mic jack appropriately order is: external mic -> dock mic -> interal mic */ static void cxt5066_thinkpad_automic(struct hda_codec *codec) @@ -2408,6 +2421,20 @@ static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res) } /* unsolicited event for jack sensing */ +static void cxt5066_hp_laptop_event(struct hda_codec *codec, unsigned int res) +{ + snd_printdd("CXT5066_hp_laptop: unsol event %x (%x)\n", res, res >> 26); + switch (res >> 26) { + case CONEXANT_HP_EVENT: + cxt5066_hp_automute(codec); + break; + case CONEXANT_MIC_EVENT: + cxt5066_hp_laptop_automic(codec); + break; + } +} + +/* unsolicited event for jack sensing */ static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res) { snd_printdd("CXT5066_thinkpad: unsol event %x (%x)\n", res, res >> 26); @@ -2989,6 +3016,14 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = { { } /* end */ }; + +static struct hda_verb cxt5066_init_verbs_hp_laptop[] = { + {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, + {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, + { } /* end */ +}; + /* initialize jack-sensing, too */ static int cxt5066_init(struct hda_codec *codec) { @@ -3004,6 +3039,8 @@ static int cxt5066_init(struct hda_codec *codec) cxt5066_ideapad_automic(codec); else if (spec->thinkpad) cxt5066_thinkpad_automic(codec); + else if (spec->hp_laptop) + cxt5066_hp_laptop_automic(codec); } cxt5066_set_mic_boost(codec); return 0; @@ -3031,6 +3068,7 @@ enum { CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ + CXT5066_HP_LAPTOP, /* HP Laptop */ CXT5066_MODELS }; @@ -3041,6 +3079,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = { [CXT5066_DELL_VOSTO] = "dell-vostro", [CXT5066_IDEAPAD] = "ideapad", [CXT5066_THINKPAD] = "thinkpad", + [CXT5066_HP_LAPTOP] = "hp-laptop", }; static struct snd_pci_quirk cxt5066_cfg_tbl[] = { @@ -3049,15 +3088,20 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", CXT5066_DELL_LAPTOP), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), + SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), + SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), + SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x390a, "Lenovo S10-3t", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G series (AMD)", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), {} @@ -3114,6 +3158,23 @@ static int patch_cxt5066(struct hda_codec *codec) spec->num_init_verbs++; spec->dell_automute = 1; break; + case CXT5066_HP_LAPTOP: + codec->patch_ops.init = cxt5066_init; + codec->patch_ops.unsol_event = cxt5066_hp_laptop_event; + spec->init_verbs[spec->num_init_verbs] = + cxt5066_init_verbs_hp_laptop; + spec->num_init_verbs++; + spec->hp_laptop = 1; + spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; + spec->mixers[spec->num_mixers++] = cxt5066_mixers; + /* no S/PDIF out */ + spec->multiout.dig_out_nid = 0; + /* input source automatically selected */ + spec->input_mux = NULL; + spec->port_d_mode = 0; + spec->mic_boost = 3; /* default 30dB gain */ + break; + case CXT5066_OLPC_XO_1_5: codec->patch_ops.init = cxt5066_olpc_init; codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 2bc0f07cf33f..afd6022a96a7 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -707,8 +707,6 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, int format) { struct hdmi_spec *spec = codec->spec; - int tag; - int fmt; int pinctl; int new_pinctl = 0; int i; @@ -745,24 +743,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, return -EINVAL; } - tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; - fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); - - snd_printdd("hdmi_setup_stream: " - "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", - nid, - tag == stream_tag ? "" : "new-", - stream_tag, - fmt == format ? "" : "new-", - format); - - if (tag != stream_tag) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - stream_tag << 4); - if (fmt != format) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, format); + snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); return 0; } diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index d382d3c81c0f..36a9b83a6174 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c @@ -69,20 +69,12 @@ static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); } -static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - return 0; -} - static struct hda_pcm_stream intel_hdmi_pcm_playback = { .substreams = 1, .channels_min = 2, .ops = { .open = hdmi_pcm_open, .prepare = intel_hdmi_playback_pcm_prepare, - .cleanup = intel_hdmi_playback_pcm_cleanup, }, }; diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index f636870dc718..baa108b9d6aa 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c @@ -84,7 +84,7 @@ static struct hda_verb nvhdmi_basic_init_7x[] = { #else /* support all rates and formats */ #define SUPPORTED_RATES \ - (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ + (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ SNDRV_PCM_RATE_192000) #define SUPPORTED_MAXBPS 24 @@ -326,13 +326,6 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, return 0; } -static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - return 0; -} - static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -350,7 +343,6 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { .ops = { .open = hdmi_pcm_open, .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, - .cleanup = nvhdmi_playback_pcm_cleanup, }, }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2cd1ae809e46..a432e6efd19b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1594,12 +1594,22 @@ static void alc_auto_parse_digital(struct hda_codec *codec) } if (spec->autocfg.dig_in_pin) { - hda_nid_t dig_nid; - err = snd_hda_get_connections(codec, - spec->autocfg.dig_in_pin, - &dig_nid, 1); - if (err > 0) - spec->dig_in_nid = dig_nid; + dig_nid = codec->start_nid; + for (i = 0; i < codec->num_nodes; i++, dig_nid++) { + unsigned int wcaps = get_wcaps(codec, dig_nid); + if (get_wcaps_type(wcaps) != AC_WID_AUD_IN) + continue; + if (!(wcaps & AC_WCAP_DIGITAL)) + continue; + if (!(wcaps & AC_WCAP_CONN_LIST)) + continue; + err = get_connection_index(codec, dig_nid, + spec->autocfg.dig_in_pin); + if (err >= 0) { + spec->dig_in_nid = dig_nid; + break; + } + } } } @@ -5334,6 +5344,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, static struct snd_pci_quirk beep_white_list[] = { SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), + SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), {} }; @@ -14452,6 +14463,7 @@ static void alc269_auto_init(struct hda_codec *codec) enum { ALC269_FIXUP_SONY_VAIO, + ALC269_FIXUP_DELL_M101Z, }; static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { @@ -14463,10 +14475,20 @@ static const struct alc_fixup alc269_fixups[] = { [ALC269_FIXUP_SONY_VAIO] = { .verbs = alc269_sony_vaio_fixup_verbs }, + [ALC269_FIXUP_DELL_M101Z] = { + .verbs = (const struct hda_verb[]) { + /* Enables internal speaker */ + {0x20, AC_VERB_SET_COEF_INDEX, 13}, + {0x20, AC_VERB_SET_PROC_COEF, 0x4040}, + {} + } + }, }; static struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), {} }; @@ -19030,6 +19052,7 @@ static int patch_alc888(struct hda_codec *codec) /* * ALC680 support */ +#define ALC680_DIGIN_NID ALC880_DIGIN_NID #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID #define alc680_modes alc260_modes @@ -19044,23 +19067,93 @@ static hda_nid_t alc680_adc_nids[3] = { 0x07, 0x08, 0x09 }; +/* + * Analog capture ADC cgange + */ +static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; + unsigned int pre_mic, pre_line; + + pre_mic = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); + pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]); + + spec->cur_adc_stream_tag = stream_tag; + spec->cur_adc_format = format; + + if (pre_mic || pre_line) { + if (pre_mic) + snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0, + format); + else + snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0, + format); + } else + snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format); + return 0; +} + +static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + snd_hda_codec_cleanup_stream(codec, 0x07); + snd_hda_codec_cleanup_stream(codec, 0x08); + snd_hda_codec_cleanup_stream(codec, 0x09); + return 0; +} + +static struct hda_pcm_stream alc680_pcm_analog_auto_capture = { + .substreams = 1, /* can be overridden */ + .channels_min = 2, + .channels_max = 2, + /* NID is set in alc_build_pcms */ + .ops = { + .prepare = alc680_capture_pcm_prepare, + .cleanup = alc680_capture_pcm_cleanup + }, +}; + static struct snd_kcontrol_new alc680_base_mixer[] = { /* output mixer control */ HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Int Mic Boost", 0x12, 0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_VOLUME("Line In Boost", 0x19, 0, HDA_INPUT), { } }; -static struct snd_kcontrol_new alc680_capture_mixer[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), +static struct hda_bind_ctls alc680_bind_cap_vol = { + .ops = &snd_hda_bind_vol, + .values = { + HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT), + HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT), + HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), + 0 + }, +}; + +static struct hda_bind_ctls alc680_bind_cap_switch = { + .ops = &snd_hda_bind_sw, + .values = { + HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT), + HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT), + HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), + 0 + }, +}; + +static struct snd_kcontrol_new alc680_master_capture_mixer[] = { + HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol), + HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch), { } /* end */ }; @@ -19068,25 +19161,73 @@ static struct snd_kcontrol_new alc680_capture_mixer[] = { * generic initialization of ADC, input mixers and output mixers */ static struct hda_verb alc680_init_verbs[] = { - /* Unmute DAC0-1 and set vol = 0 */ - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + + {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, + { } }; +/* toggle speaker-output according to the hp-jack state */ +static void alc680_base_setup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + spec->autocfg.hp_pins[0] = 0x16; + spec->autocfg.speaker_pins[0] = 0x14; + spec->autocfg.speaker_pins[1] = 0x15; + spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18; + spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19; +} + +static void alc680_rec_autoswitch(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; + unsigned int present; + hda_nid_t new_adc; + + present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); + + new_adc = present ? 0x8 : 0x7; + __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1); + snd_hda_codec_setup_stream(codec, new_adc, + spec->cur_adc_stream_tag, 0, + spec->cur_adc_format); + +} + +static void alc680_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) == ALC880_HP_EVENT) + alc_automute_amp(codec); + if ((res >> 26) == ALC880_MIC_EVENT) + alc680_rec_autoswitch(codec); +} + +static void alc680_inithook(struct hda_codec *codec) +{ + alc_automute_amp(codec); + alc680_rec_autoswitch(codec); +} + /* create input playback/capture controls for the given pin */ static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, const char *ctlname, int idx) @@ -19197,13 +19338,7 @@ static void alc680_auto_init_hp_out(struct hda_codec *codec) #define alc680_pcm_analog_capture alc880_pcm_analog_capture #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture #define alc680_pcm_digital_playback alc880_pcm_digital_playback - -static struct hda_input_mux alc680_capture_source = { - .num_items = 1, - .items = { - { "Mic", 0x0 }, - }, -}; +#define alc680_pcm_digital_capture alc880_pcm_digital_capture /* * BIOS auto configuration @@ -19218,6 +19353,7 @@ static int alc680_parse_auto_config(struct hda_codec *codec) alc680_ignore); if (err < 0) return err; + if (!spec->autocfg.line_outs) { if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { spec->multiout.max_channels = 2; @@ -19239,8 +19375,6 @@ static int alc680_parse_auto_config(struct hda_codec *codec) add_mixer(spec, spec->kctls.list); add_verb(spec, alc680_init_verbs); - spec->num_mux_defs = 1; - spec->input_mux = &alc680_capture_source; err = alc_auto_add_mic_boost(codec); if (err < 0) @@ -19279,17 +19413,17 @@ static struct snd_pci_quirk alc680_cfg_tbl[] = { static struct alc_config_preset alc680_presets[] = { [ALC680_BASE] = { .mixers = { alc680_base_mixer }, - .cap_mixer = alc680_capture_mixer, + .cap_mixer = alc680_master_capture_mixer, .init_verbs = { alc680_init_verbs }, .num_dacs = ARRAY_SIZE(alc680_dac_nids), .dac_nids = alc680_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc680_adc_nids), - .adc_nids = alc680_adc_nids, - .hp_nid = 0x04, .dig_out_nid = ALC680_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc680_modes), .channel_mode = alc680_modes, - .input_mux = &alc680_capture_source, + .unsol_event = alc680_unsol_event, + .setup = alc680_base_setup, + .init_hook = alc680_inithook, + }, }; @@ -19333,9 +19467,9 @@ static int patch_alc680(struct hda_codec *codec) setup_preset(codec, &alc680_presets[board_config]); spec->stream_analog_playback = &alc680_pcm_analog_playback; - spec->stream_analog_capture = &alc680_pcm_analog_capture; - spec->stream_analog_alt_capture = &alc680_pcm_analog_alt_capture; + spec->stream_analog_capture = &alc680_pcm_analog_auto_capture; spec->stream_digital_playback = &alc680_pcm_digital_playback; + spec->stream_digital_capture = &alc680_pcm_digital_capture; if (!spec->adc_nids) { spec->adc_nids = alc680_adc_nids; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f3f861bd1bf8..c16c5ba0fda0 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1747,6 +1747,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "HP dv6", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061, "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */ + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x363e, + "HP DV6", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, "HP", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, @@ -6303,6 +6305,21 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { { .id = 0x111d76b5, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, { .id = 0x111d76b6, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, + { .id = 0x111d76c0, .name = "92HD89C3", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c1, .name = "92HD89C2", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c2, .name = "92HD89C1", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c3, .name = "92HD89B3", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c4, .name = "92HD89B2", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c5, .name = "92HD89B1", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c6, .name = "92HD89E3", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c7, .name = "92HD89E2", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c8, .name = "92HD89E1", .patch = patch_stac92hd73xx }, + { .id = 0x111d76c9, .name = "92HD89D3", .patch = patch_stac92hd73xx }, + { .id = 0x111d76ca, .name = "92HD89D2", .patch = patch_stac92hd73xx }, + { .id = 0x111d76cb, .name = "92HD89D1", .patch = patch_stac92hd73xx }, + { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, + { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, + { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, {} /* terminator */ }; |