Skip to content

Commit

Permalink
ALSA: hda/conexant - Clear unsol events on unused pins
Browse files Browse the repository at this point in the history
It seems that Lenovo machines (or codec chip itself?) leave the unsol
event tags and the enablement-flag from other pins bogusly even on the
unused pins.  Although this shouldn't be too critical, it's better to
clear them up sanely.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed Feb 29, 2012
1 parent 3e93f5e commit 07cafff
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions sound/pci/hda/patch_conexant.c
Original file line number Diff line number Diff line change
Expand Up @@ -3931,6 +3931,50 @@ static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
snd_hda_jack_detect_enable(codec, pins[i], action);
}

static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
{
int i;
for (i = 0; i < nums; i++)
if (list[i] == nid)
return true;
return false;
}

/* is the given NID found in any of autocfg items? */
static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid)
{
int i;

if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) ||
found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs))
return true;
for (i = 0; i < cfg->num_inputs; i++)
if (cfg->inputs[i].pin == nid)
return true;
if (cfg->dig_in_pin == nid)
return true;
return false;
}

/* clear unsol-event tags on unused pins; Conexant codecs seem to leave
* invalid unsol tags by some reason
*/
static void clear_unsol_on_unused_pins(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
int i;

for (i = 0; i < codec->init_pins.used; i++) {
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
if (!found_in_autocfg(cfg, pin->nid))
snd_hda_codec_write(codec, pin->nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE, 0);
}
}

static void cx_auto_init_output(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
Expand Down Expand Up @@ -3971,6 +4015,7 @@ static void cx_auto_init_output(struct hda_codec *codec)
/* turn on all EAPDs if no individual EAPD control is available */
if (!spec->pin_eapd_ctrls)
cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
clear_unsol_on_unused_pins(codec);
}

static void cx_auto_init_input(struct hda_codec *codec)
Expand Down

0 comments on commit 07cafff

Please sign in to comment.