unsigned int no_pin_power_ctl;
enum VIA_HDA_CODEC codec_type;
+ /* analog low-power control */
+ bool alc_mode;
+
/* smart51 setup */
unsigned int smart51_nums;
hda_nid_t smart51_pins[2];
/* init input-src */
for (i = 0; i < spec->num_adc_nids; i++) {
int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx;
+ /* secondary ADCs must have the unique MUX */
+ if (i > 0 && !spec->mux_nids[i])
+ break;
if (spec->mux_nids[adc_idx]) {
int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx;
snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
return 0;
spec->no_pin_power_ctl = val;
set_widgets_power_state(codec);
+ analog_low_current_mode(codec);
return 1;
}
}
/* enter/exit analog low-current mode */
-static void analog_low_current_mode(struct hda_codec *codec)
+static void __analog_low_current_mode(struct hda_codec *codec, bool force)
{
struct via_spec *spec = codec->spec;
bool enable;
unsigned int verb, parm;
- enable = is_aa_path_mute(codec) && (spec->opened_streams != 0);
+ if (spec->no_pin_power_ctl)
+ enable = false;
+ else
+ enable = is_aa_path_mute(codec) && !spec->opened_streams;
+ if (enable == spec->alc_mode && !force)
+ return;
+ spec->alc_mode = enable;
/* decide low current mode's verb & parameter */
switch (spec->codec_type) {
snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
}
+static void analog_low_current_mode(struct hda_codec *codec)
+{
+ return __analog_low_current_mode(codec, false);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
struct snd_kcontrol *kctl;
int err, i;
+ spec->no_pin_power_ctl = 1;
if (spec->set_widgets_power_state)
if (!via_clone_control(spec, &via_pin_power_ctl_enum))
return -ENOMEM;
return err;
}
- /* init power states */
- set_widgets_power_state(codec);
- analog_low_current_mode(codec);
-
via_free_kctls(codec); /* no longer needed */
return 0;
}
{
struct via_spec *spec = codec->spec;
const struct auto_pin_cfg *cfg = &spec->autocfg;
- int i, dac_num;
+ int i;
hda_nid_t nid;
+ spec->multiout.num_dacs = 0;
spec->multiout.dac_nids = spec->private_dac_nids;
- dac_num = 0;
for (i = 0; i < cfg->line_outs; i++) {
hda_nid_t dac = 0;
nid = cfg->line_out_pins[i];
if (!i && parse_output_path(codec, nid, dac, 1,
&spec->out_mix_path))
dac = spec->out_mix_path.path[0];
- if (dac) {
- spec->private_dac_nids[i] = dac;
- dac_num++;
- }
+ if (dac)
+ spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
}
if (!spec->out_path[0].depth && spec->out_mix_path.depth) {
spec->out_path[0] = spec->out_mix_path;
spec->out_mix_path.depth = 0;
}
- spec->multiout.num_dacs = dac_num;
return 0;
}
{
struct via_spec *spec = codec->spec;
- if (!spec->aa_mix_nid || !spec->out_mix_path.depth)
+ if (!spec->aa_mix_nid)
+ return 0; /* no loopback switching available */
+ if (!(spec->out_mix_path.depth || spec->hp_mix_path.depth ||
+ spec->speaker_path.depth))
return 0; /* no loopback switching available */
if (!via_clone_control(spec, &via_aamix_ctl_enum))
return -ENOMEM;
for (i = 0; i < spec->num_iverbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
+ /* init power states */
+ set_widgets_power_state(codec);
+ __analog_low_current_mode(codec, true);
+
via_auto_init_multi_out(codec);
via_auto_init_hp_out(codec);
via_auto_init_speaker_out(codec);
{
struct via_spec *spec = codec->spec;
int imux_is_smixer;
- unsigned int parm;
+ unsigned int parm, parm2;
/* MUX6 (1eh) = stereo mixer */
imux_is_smixer =
snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x27, &parm);
snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
+ parm2 = parm; /* for pin 0x0b */
/* PW2 (26h), AOW2 (ah) */
parm = AC_PWRST_D3;
if (!spec->hp_independent_mode) /* check for redirected HP */
set_pin_power_state(codec, 0x28, &parm);
snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ if (!spec->hp_independent_mode && parm2 != AC_PWRST_D3)
+ parm = parm2;
+ snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
imux_is_smixer ? AC_PWRST_D0 : parm);
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
}
+/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
+ * Replace this with mixer NID 0x1c
+ */
+static void fix_vt1802_connections(struct hda_codec *codec)
+{
+ static hda_nid_t conn_24[] = { 0x14, 0x1c };
+ static hda_nid_t conn_33[] = { 0x1c };
+
+ snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
+ snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
+}
+
/* patch for vt2002P */
static int patch_vt2002P(struct hda_codec *codec)
{
spec->aa_mix_nid = 0x21;
override_mic_boost(codec, 0x2b, 0, 3, 40);
override_mic_boost(codec, 0x29, 0, 3, 40);
+ if (spec->codec_type == VT1802)
+ fix_vt1802_connections(codec);
add_secret_dac_path(codec);
/* automatic parse from the BIOS config */