Skip to content

Commit

Permalink
ALSA: hda - Fix DAC assignment for independent HP
Browse files Browse the repository at this point in the history
The generic parser should evaluate the availability of the independent
HP when specified.  Otherwise a DAC without the direct connection to
the corresponding pin may be assigned for the HP, but the driver
doesn't check it at all.  The problem was actually seen on some
machines with VT1708s or equivalent codec, where DAC0 is assigned to
HP although it can be connected only via aamix.

This patch adds the badness evaluation for the independent HP to make
it working properly.

Reported-by: Lydia Wang <LydiaWang@viatech.com.cn>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
tiwai committed Mar 21, 2013
1 parent eb49faa commit 55a63d4
Showing 1 changed file with 46 additions and 0 deletions.
46 changes: 46 additions & 0 deletions sound/pci/hda/hda_generic.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -995,6 +995,8 @@ enum {
BAD_NO_EXTRA_SURR_DAC = 0x101, BAD_NO_EXTRA_SURR_DAC = 0x101,
/* Primary DAC shared with main surrounds */ /* Primary DAC shared with main surrounds */
BAD_SHARED_SURROUND = 0x100, BAD_SHARED_SURROUND = 0x100,
/* No independent HP possible */
BAD_NO_INDEP_HP = 0x40,
/* Primary DAC shared with main CLFE */ /* Primary DAC shared with main CLFE */
BAD_SHARED_CLFE = 0x10, BAD_SHARED_CLFE = 0x10,
/* Primary DAC shared with extra surrounds */ /* Primary DAC shared with extra surrounds */
Expand Down Expand Up @@ -1392,6 +1394,43 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
return snd_hda_get_path_idx(codec, path); return snd_hda_get_path_idx(codec, path);
} }


/* check whether the independent HP is available with the current config */
static bool indep_hp_possible(struct hda_codec *codec)
{
struct hda_gen_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
struct nid_path *path;
int i, idx;

if (cfg->line_out_type == AUTO_PIN_HP_OUT)
idx = spec->out_paths[0];
else
idx = spec->hp_paths[0];
path = snd_hda_get_path_from_idx(codec, idx);
if (!path)
return false;

/* assume no path conflicts unless aamix is involved */
if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
return true;

/* check whether output paths contain aamix */
for (i = 0; i < cfg->line_outs; i++) {
if (spec->out_paths[i] == idx)
break;
path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
if (path && is_nid_contained(path, spec->mixer_nid))
return false;
}
for (i = 0; i < cfg->speaker_outs; i++) {
path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
if (path && is_nid_contained(path, spec->mixer_nid))
return false;
}

return true;
}

/* fill the empty entries in the dac array for speaker/hp with the /* fill the empty entries in the dac array for speaker/hp with the
* shared dac pointed by the paths * shared dac pointed by the paths
*/ */
Expand Down Expand Up @@ -1545,6 +1584,9 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
badness += BAD_MULTI_IO; badness += BAD_MULTI_IO;
} }


if (spec->indep_hp && !indep_hp_possible(codec))
badness += BAD_NO_INDEP_HP;

/* re-fill the shared DAC for speaker / headphone */ /* re-fill the shared DAC for speaker / headphone */
if (cfg->line_out_type != AUTO_PIN_HP_OUT) if (cfg->line_out_type != AUTO_PIN_HP_OUT)
refill_shared_dacs(codec, cfg->hp_outs, refill_shared_dacs(codec, cfg->hp_outs,
Expand Down Expand Up @@ -1758,6 +1800,10 @@ static int parse_output_paths(struct hda_codec *codec)
cfg->speaker_pins, val); cfg->speaker_pins, val);
} }


/* clear indep_hp flag if not available */
if (spec->indep_hp && !indep_hp_possible(codec))
spec->indep_hp = 0;

kfree(best_cfg); kfree(best_cfg);
return 0; return 0;
} }
Expand Down

0 comments on commit 55a63d4

Please sign in to comment.