mirror of https://gitee.com/openkylin/linux.git
ALSA: hda - Fix the connection selection of ADCs on Cirrus codecs
spec->cur_adc isn't set until cs_capture_pcm_prepare() is called although the driver tries to select the connection at init time and at auto-mic switch. This results in the access to the widget NID 0, which is obviously invalid, also a wrong capture source. This patch fixes the issue by issuing the connect-select verb conditionally at appropriate places. Reported-and-tested-by: Dylan Reid <dgreid@chromium.org> Cc: <stable@kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
25d7d59d1f
commit
05ee7964a4
|
@ -237,6 +237,15 @@ static int cs_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
|
|||
return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
|
||||
}
|
||||
|
||||
static void cs_update_input_select(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
if (spec->cur_adc)
|
||||
snd_hda_codec_write(codec, spec->cur_adc, 0,
|
||||
AC_VERB_SET_CONNECT_SEL,
|
||||
spec->adc_idx[spec->cur_input]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Analog capture
|
||||
*/
|
||||
|
@ -250,6 +259,7 @@ static int cs_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|||
spec->cur_adc = spec->adc_nid[spec->cur_input];
|
||||
spec->cur_adc_stream_tag = stream_tag;
|
||||
spec->cur_adc_format = format;
|
||||
cs_update_input_select(codec);
|
||||
snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
|
||||
return 0;
|
||||
}
|
||||
|
@ -689,10 +699,8 @@ static int change_cur_input(struct hda_codec *codec, unsigned int idx,
|
|||
spec->cur_adc_stream_tag, 0,
|
||||
spec->cur_adc_format);
|
||||
}
|
||||
snd_hda_codec_write(codec, spec->cur_adc, 0,
|
||||
AC_VERB_SET_CONNECT_SEL,
|
||||
spec->adc_idx[idx]);
|
||||
spec->cur_input = idx;
|
||||
cs_update_input_select(codec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -973,10 +981,7 @@ static void cs_automic(struct hda_codec *codec)
|
|||
} else {
|
||||
spec->cur_input = spec->last_input;
|
||||
}
|
||||
|
||||
snd_hda_codec_write_cache(codec, spec->cur_adc, 0,
|
||||
AC_VERB_SET_CONNECT_SEL,
|
||||
spec->adc_idx[spec->cur_input]);
|
||||
cs_update_input_select(codec);
|
||||
} else {
|
||||
if (present)
|
||||
change_cur_input(codec, spec->automic_idx, 0);
|
||||
|
@ -1073,9 +1078,7 @@ static void init_input(struct hda_codec *codec)
|
|||
cs_automic(codec);
|
||||
else {
|
||||
spec->cur_adc = spec->adc_nid[spec->cur_input];
|
||||
snd_hda_codec_write(codec, spec->cur_adc, 0,
|
||||
AC_VERB_SET_CONNECT_SEL,
|
||||
spec->adc_idx[spec->cur_input]);
|
||||
cs_update_input_select(codec);
|
||||
}
|
||||
} else {
|
||||
change_cur_input(codec, spec->cur_input, 1);
|
||||
|
|
Loading…
Reference in New Issue