mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 06:04:23 +08:00
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
Block a user