diff options
author | Takashi Iwai | 2013-01-16 16:25:24 +0100 |
---|---|---|
committer | Takashi Iwai | 2013-01-16 16:25:24 +0100 |
commit | ae127005fcebc13ad7c2ed48a8d46360f5cf0819 (patch) | |
tree | fe2046f657240f17a755ecefec34cc713b69a2cf /sound/pci/hda | |
parent | 9b473e8516c0d6745dd4c0ec69f9c17f14df0469 (diff) | |
parent | 6fc4cb97cbf5bf1ccfac821072e3927d21b3e0e9 (diff) |
Merge branch 'test/hda-gen-parser' into test/hda-migrate
* test/hda-gen-parser:
ALSA: hda - Make sure fill_all_dac_nids is called for digital only codecs
ALSA: hda - force different capture controls if amp caps differ
ALSA: hda - do not add non-existing Mic boost controls
ALSA: hda - initialize channel counts correctly
ALSA: hda - fix wrong adc_idx in generic parser
ALSA: hda - Check array bounds in get_input_path
ALSA: hda - Add prefer_hp_amp flag to hda_gen_spec
ALSA: hda - fix OOPS in hda_mark_cmd_cache_dirty
ALSA: hda - Check pincap while parsing the configuration
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_auto_parser.c | 25 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 61 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 7 |
5 files changed, 80 insertions, 16 deletions
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 33b3ece224c6..a4810c7437bd 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -97,6 +97,28 @@ static void reorder_outputs(unsigned int nums, hda_nid_t *pins) } } +/* check whether the given pin has a proper pin I/O capability bit */ +static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin, + unsigned int dev) +{ + unsigned int pincap = snd_hda_query_pin_caps(codec, pin); + + /* some old hardware don't return the proper pincaps */ + if (!pincap) + return true; + + switch (dev) { + case AC_JACK_LINE_OUT: + case AC_JACK_SPEAKER: + case AC_JACK_HP_OUT: + case AC_JACK_SPDIF_OUT: + case AC_JACK_DIG_OTHER_OUT: + return !!(pincap & AC_PINCAP_OUT); + default: + return !!(pincap & AC_PINCAP_IN); + } +} + /* * Parse all pin widgets and store the useful pin nids to cfg * @@ -164,6 +186,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, dev = AC_JACK_SPEAKER; } + if (!check_pincap_validity(codec, nid, dev)) + continue; + switch (dev) { case AC_JACK_LINE_OUT: seq = get_defcfg_sequence(def_conf); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b28e4031b8a1..e6cdad713734 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3794,7 +3794,7 @@ static void hda_mark_cmd_cache_dirty(struct hda_codec *codec) } for (i = 0; i < codec->amp_cache.buf.used; i++) { struct hda_amp_info *amp; - amp = snd_array_elem(&codec->cmd_cache.buf, i); + amp = snd_array_elem(&codec->amp_cache.buf, i); amp->head.dirty = 1; } } diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 932e6a133f3d..73900d935681 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -484,6 +484,15 @@ static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, return false; } +static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1, + hda_nid_t nid2, int dir) +{ + if (!(get_wcaps(codec, nid1) & (1 << (dir + 1)))) + return !(get_wcaps(codec, nid2) & (1 << (dir + 1))); + return (query_amp_caps(codec, nid1, dir) == + query_amp_caps(codec, nid2, dir)); +} + #define nid_has_mute(codec, nid, dir) \ check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE) #define nid_has_volume(codec, nid, dir) \ @@ -1284,6 +1293,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec, struct hda_gen_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; int i, err, badness; + unsigned int val; /* set num_dacs once to full for look_for_dac() */ spec->multiout.num_dacs = cfg->line_outs; @@ -1399,7 +1409,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec, } spec->ext_channel_count = spec->min_channel_count = - spec->multiout.num_dacs; + spec->multiout.num_dacs * 2; if (spec->multi_ios == 2) { for (i = 0; i < 2; i++) @@ -1421,13 +1431,18 @@ static int fill_and_eval_dacs(struct hda_codec *codec, spec->speaker_paths); /* set initial pinctl targets */ - set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, - cfg->line_out_type == AUTO_PIN_HP_OUT ? PIN_HP : PIN_OUT); + if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT) + val = PIN_HP; + else + val = PIN_OUT; + set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val); if (cfg->line_out_type != AUTO_PIN_HP_OUT) set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP); - if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) + if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { + val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT; set_pin_targets(codec, cfg->speaker_outs, - cfg->speaker_pins, PIN_OUT); + cfg->speaker_pins, val); + } return badness; } @@ -1501,8 +1516,6 @@ static int parse_output_paths(struct hda_codec *codec) bool best_wired = true, best_mio = true; bool hp_spk_swapped = false; - fill_all_dac_nids(codec); - best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL); if (!best_cfg) return -ENOMEM; @@ -2397,8 +2410,16 @@ static int create_input_ctls(struct hda_codec *codec) static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx) { struct hda_gen_spec *spec = codec->spec; + if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) { + snd_BUG(); + return NULL; + } if (spec->dyn_adc_switch) adc_idx = spec->dyn_adc_idx[imux_idx]; + if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_OUTS) { + snd_BUG(); + return NULL; + } return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]); } @@ -2418,7 +2439,7 @@ static int mux_enum_get(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_gen_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + unsigned int adc_idx = kcontrol->id.index; ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; return 0; @@ -2428,7 +2449,7 @@ static int mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + unsigned int adc_idx = kcontrol->id.index; return mux_select(codec, adc_idx, ucontrol->value.enumerated.item[0]); } @@ -2460,7 +2481,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol, int i, adc_idx, err = 0; imux = &spec->input_mux; - adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + adc_idx = kcontrol->id.index; mutex_lock(&codec->control_mutex); /* we use the cache-only update at first since multiple input paths * may shared the same amp; by updating only caches, the redundant @@ -2754,6 +2775,7 @@ static int create_capture_mixers(struct hda_codec *codec) for (n = 0; n < nums; n++) { bool multi = false; + bool multi_cap_vol = spec->multi_cap_vol; bool inv_dmic = false; int vol, sw; @@ -2766,12 +2788,20 @@ static int create_capture_mixers(struct hda_codec *codec) parse_capvol_in_path(codec, path); if (!vol) vol = path->ctls[NID_PATH_VOL_CTL]; - else if (vol != path->ctls[NID_PATH_VOL_CTL]) + else if (vol != path->ctls[NID_PATH_VOL_CTL]) { multi = true; + if (!same_amp_caps(codec, vol, + path->ctls[NID_PATH_VOL_CTL], HDA_INPUT)) + multi_cap_vol = true; + } if (!sw) sw = path->ctls[NID_PATH_MUTE_CTL]; - else if (sw != path->ctls[NID_PATH_MUTE_CTL]) + else if (sw != path->ctls[NID_PATH_MUTE_CTL]) { multi = true; + if (!same_amp_caps(codec, sw, + path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT)) + multi_cap_vol = true; + } if (is_inv_dmic_pin(codec, spec->imux_pins[i])) inv_dmic = true; } @@ -2779,7 +2809,7 @@ static int create_capture_mixers(struct hda_codec *codec) if (!multi) err = create_single_cap_vol_ctl(codec, n, vol, sw, inv_dmic); - else if (!spec->multi_cap_vol) + else if (!multi_cap_vol) err = create_bind_cap_vol_ctl(codec, n, vol, sw); else err = create_multi_cap_vol_ctl(codec); @@ -2812,6 +2842,9 @@ static int parse_mic_boost(struct hda_codec *codec) struct nid_path *path; unsigned int val; + if (!nid_has_volume(codec, nid, HDA_INPUT)) + continue; + label = hda_get_autocfg_input_label(codec, cfg, i); if (prev_label && !strcmp(label, prev_label)) type_idx++; @@ -3393,6 +3426,8 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, cfg = &spec->autocfg; } + fill_all_dac_nids(codec); + if (!cfg->line_outs) { if (cfg->dig_outs || cfg->dig_in_pin) { spec->multiout.max_channels = 2; diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 1ceaacd1b775..6ba580540081 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -190,6 +190,7 @@ struct hda_gen_spec { unsigned int vmaster_mute_enum:1; /* add vmaster mute mode enum */ unsigned int indep_hp:1; /* independent HP supported */ unsigned int indep_hp_enabled:1; /* independent HP enabled */ + unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */ unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */ unsigned int add_out_jack_modes:1; /* add output jack mode enum ctls */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index fab31d29fa23..71a8894438ab 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1506,8 +1506,6 @@ static void alc260_fixup_fsc_s7020(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) spec->gen.add_out_jack_modes = 1; - else if (action == HDA_FIXUP_ACT_PROBE) - snd_hda_set_pin_ctl_cache(codec, 0x10, PIN_HP); } static const struct hda_fixup alc260_fixups[] = { @@ -1597,6 +1595,11 @@ static int patch_alc260(struct hda_codec *codec) return err; spec = codec->spec; + /* as quite a few machines require HP amp for speaker outputs, + * it's easier to enable it unconditionally; even if it's unneeded, + * it's almost harmless. + */ + spec->gen.prefer_hp_amp = 1; snd_hda_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |