Commit ba811127 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda/realtek - Manage mixer controls in out_path list

As we parse the output paths more precisely now, we can use this path
list for parsing the widgets for volume and mute mixer controls.
The spec->vol_ctls[] and sw_ctls[] bitmasks are replaced with the
ctls[] in each output path instance.

Interestingly, this move alone automagically fixes some bugs that the
conflicting volume or mute NIDs weren't properly detected.
Also, by parsing the whole path, there are more chances to get a free
widget for volume/mute controls.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 30dcd3b4
...@@ -116,6 +116,8 @@ struct nid_path { ...@@ -116,6 +116,8 @@ struct nid_path {
unsigned int ctls[2]; /* 0 = volume, 1 = mute */ unsigned int ctls[2]; /* 0 = volume, 1 = mute */
}; };
enum { NID_PATH_VOL_CTL = 0, NID_PATH_MUTE_CTL = 1 };
struct alc_spec { struct alc_spec {
struct hda_gen_spec gen; struct hda_gen_spec gen;
...@@ -150,8 +152,6 @@ struct alc_spec { ...@@ -150,8 +152,6 @@ struct alc_spec {
const hda_nid_t *capsrc_nids; const hda_nid_t *capsrc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */ hda_nid_t dig_in_nid; /* digital-in NID; optional */
hda_nid_t mixer_nid; /* analog-mixer NID */ hda_nid_t mixer_nid; /* analog-mixer NID */
DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1);
DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1);
/* capture setup for dynamic dual-adc switch */ /* capture setup for dynamic dual-adc switch */
hda_nid_t cur_adc; hda_nid_t cur_adc;
...@@ -2886,22 +2886,6 @@ static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin) ...@@ -2886,22 +2886,6 @@ static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
return srcs[0]; return srcs[0];
} }
/* get MIX nid connected to the given pin targeted to DAC */
static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac)
{
hda_nid_t mix[5];
int i, num;
pin = alc_go_down_to_selector(codec, pin);
num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
for (i = 0; i < num; i++) {
if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
return mix[i];
}
return 0;
}
/* select the connection from pin to DAC if needed */ /* select the connection from pin to DAC if needed */
static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin, static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac) hda_nid_t dac)
...@@ -3049,29 +3033,28 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) ...@@ -3049,29 +3033,28 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
return nid_found; return nid_found;
} }
/* mark up volume and mute control NIDs: used during badness parsing and static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
* at creating actual controls
*/
static inline unsigned int get_ctl_pos(unsigned int data)
{ {
hda_nid_t nid = get_amp_nid_(data); struct alc_spec *spec = codec->spec;
unsigned int dir; int i;
if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
return 0;
dir = get_amp_direction_(data);
return (nid << 1) | dir;
}
#define is_ctl_used(bits, data) \ for (i = 0; i < spec->out_path.used; i++) {
test_bit(get_ctl_pos(data), bits) struct nid_path *path = snd_array_elem(&spec->out_path, i);
#define mark_ctl_usage(bits, data) \ if (path->ctls[type] == val)
set_bit(get_ctl_pos(data), bits) return true;
}
return false;
}
static void clear_vol_marks(struct hda_codec *codec) static void clear_vol_marks(struct hda_codec *codec)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls)); int i;
memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls));
for (i = 0; i < spec->out_path.used; i++) {
struct nid_path *path = snd_array_elem(&spec->out_path, i);
path->ctls[0] = path->ctls[1] = 0;
}
} }
/* badness definition */ /* badness definition */
...@@ -3097,9 +3080,9 @@ enum { ...@@ -3097,9 +3080,9 @@ enum {
}; };
static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
hda_nid_t pin, hda_nid_t dac); struct nid_path *path);
static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
hda_nid_t pin, hda_nid_t dac); struct nid_path *path);
static bool add_new_out_path(struct hda_codec *codec, hda_nid_t pin, static bool add_new_out_path(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac) hda_nid_t dac)
...@@ -3118,34 +3101,56 @@ static bool add_new_out_path(struct hda_codec *codec, hda_nid_t pin, ...@@ -3118,34 +3101,56 @@ static bool add_new_out_path(struct hda_codec *codec, hda_nid_t pin,
return false; return false;
} }
/* get the path pointing from the given dac to pin;
* passing 0 to either @pin or @dac behaves as a wildcard
*/
static struct nid_path *get_out_path(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac)
{
struct alc_spec *spec = codec->spec;
int i;
for (i = 0; i < spec->out_path.used; i++) {
struct nid_path *path = snd_array_elem(&spec->out_path, i);
if (path->depth <= 0)
continue;
if ((!dac || path->path[0] == dac) &&
(!pin || path->path[path->depth - 1] == pin))
return path;
}
return NULL;
}
static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin, static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac) hda_nid_t dac)
{ {
struct alc_spec *spec = codec->spec; struct nid_path *path = get_out_path(codec, pin, dac);
hda_nid_t nid; hda_nid_t nid;
unsigned int val; unsigned int val;
int badness = 0; int badness = 0;
nid = alc_look_for_out_vol_nid(codec, pin, dac); if (!path)
return BAD_SHARED_VOL * 2;
nid = alc_look_for_out_vol_nid(codec, path);
if (nid) { if (nid) {
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
if (is_ctl_used(spec->vol_ctls, nid)) if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
badness += BAD_SHARED_VOL; badness += BAD_SHARED_VOL;
else else
mark_ctl_usage(spec->vol_ctls, val); path->ctls[NID_PATH_VOL_CTL] = val;
} else } else
badness += BAD_SHARED_VOL; badness += BAD_SHARED_VOL;
nid = alc_look_for_out_mute_nid(codec, pin, dac); nid = alc_look_for_out_mute_nid(codec, path);
if (nid) { if (nid) {
unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid)); unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT)
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
else else
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT); val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
if (is_ctl_used(spec->sw_ctls, val)) if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
badness += BAD_SHARED_VOL; badness += BAD_SHARED_VOL;
else else
mark_ctl_usage(spec->sw_ctls, val); path->ctls[NID_PATH_MUTE_CTL] = val;
} else } else
badness += BAD_SHARED_VOL; badness += BAD_SHARED_VOL;
return badness; return badness;
...@@ -3279,7 +3284,6 @@ static int fill_and_eval_dacs(struct hda_codec *codec, ...@@ -3279,7 +3284,6 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid)); memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
spec->multi_ios = 0; spec->multi_ios = 0;
snd_array_free(&spec->out_path); snd_array_free(&spec->out_path);
clear_vol_marks(codec);
badness = 0; badness = 0;
/* fill hard-wired DACs first */ /* fill hard-wired DACs first */
...@@ -3521,10 +3525,13 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) ...@@ -3521,10 +3525,13 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
cfg->line_out_type, best_wired, best_mio); cfg->line_out_type, best_wired, best_mio);
debug_show_configs(spec, cfg); debug_show_configs(spec, cfg);
if (cfg->line_out_pins[0]) if (cfg->line_out_pins[0]) {
spec->vmaster_nid = struct nid_path *path = get_out_path(codec,
alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0], cfg->line_out_pins[0],
spec->multiout.dac_nids[0]); spec->multiout.dac_nids[0]);
if (path)
spec->vmaster_nid = alc_look_for_out_vol_nid(codec, path);
}
/* clear the bitmap flags for creating controls */ /* clear the bitmap flags for creating controls */
clear_vol_marks(codec); clear_vol_marks(codec);
...@@ -3533,43 +3540,43 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) ...@@ -3533,43 +3540,43 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
} }
static int alc_auto_add_vol_ctl(struct hda_codec *codec, static int alc_auto_add_vol_ctl(struct hda_codec *codec,
const char *pfx, int cidx, const char *pfx, int cidx,
hda_nid_t nid, unsigned int chs) hda_nid_t nid, unsigned int chs,
struct nid_path *path)
{ {
struct alc_spec *spec = codec->spec;
unsigned int val; unsigned int val;
if (!nid) if (!nid || !path)
return 0; return 0;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT); val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
if (is_ctl_used(spec->vol_ctls, val) && chs != 2) /* exclude LFE */ if (is_ctl_used(codec, val, NID_PATH_VOL_CTL) && chs != 2) /* exclude LFE */
return 0; return 0;
mark_ctl_usage(spec->vol_ctls, val); path->ctls[NID_PATH_VOL_CTL] = val;
return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx, return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
val); val);
} }
static int alc_auto_add_stereo_vol(struct hda_codec *codec, static int alc_auto_add_stereo_vol(struct hda_codec *codec,
const char *pfx, int cidx, const char *pfx, int cidx,
hda_nid_t nid) hda_nid_t nid, struct nid_path *path)
{ {
int chs = 1; int chs = 1;
if (get_wcaps(codec, nid) & AC_WCAP_STEREO) if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
chs = 3; chs = 3;
return alc_auto_add_vol_ctl(codec, pfx, cidx, nid, chs); return alc_auto_add_vol_ctl(codec, pfx, cidx, nid, chs, path);
} }
/* create a mute-switch for the given mixer widget; /* create a mute-switch for the given mixer widget;
* if it has multiple sources (e.g. DAC and loopback), create a bind-mute * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
*/ */
static int alc_auto_add_sw_ctl(struct hda_codec *codec, static int alc_auto_add_sw_ctl(struct hda_codec *codec,
const char *pfx, int cidx, const char *pfx, int cidx,
hda_nid_t nid, unsigned int chs) hda_nid_t nid, unsigned int chs,
struct nid_path *path)
{ {
struct alc_spec *spec = codec->spec;
int wid_type; int wid_type;
int type; int type;
unsigned long val; unsigned long val;
if (!nid) if (!nid || !path)
return 0; return 0;
wid_type = get_wcaps_type(get_wcaps(codec, nid)); wid_type = get_wcaps_type(get_wcaps(codec, nid));
if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) { if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
...@@ -3582,44 +3589,46 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec, ...@@ -3582,44 +3589,46 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec,
type = ALC_CTL_BIND_MUTE; type = ALC_CTL_BIND_MUTE;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT); val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
} }
if (is_ctl_used(spec->sw_ctls, val) && chs != 2) /* exclude LFE */ if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL) && chs != 2) /* exclude LFE */
return 0; return 0;
mark_ctl_usage(spec->sw_ctls, val); path->ctls[NID_PATH_MUTE_CTL] = val;
return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val); return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
} }
static int alc_auto_add_stereo_sw(struct hda_codec *codec, const char *pfx, static int alc_auto_add_stereo_sw(struct hda_codec *codec, const char *pfx,
int cidx, hda_nid_t nid) int cidx, hda_nid_t nid,
struct nid_path *path)
{ {
int chs = 1; int chs = 1;
if (get_wcaps(codec, nid) & AC_WCAP_STEREO) if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
chs = 3; chs = 3;
return alc_auto_add_sw_ctl(codec, pfx, cidx, nid, chs); return alc_auto_add_sw_ctl(codec, pfx, cidx, nid, chs, path);
} }
static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
hda_nid_t pin, hda_nid_t dac) struct nid_path *path)
{ {
hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac); int i;
if (nid_has_mute(codec, pin, HDA_OUTPUT))
return pin; for (i = path->depth - 1; i >= 0; i--) {
else if (mix && nid_has_mute(codec, mix, HDA_INPUT)) if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
return mix; return path->path[i];
else if (nid_has_mute(codec, dac, HDA_OUTPUT)) if (i != path->depth - 1 && i != 0 &&
return dac; nid_has_mute(codec, path->path[i], HDA_INPUT))
return path->path[i];
}
return 0; return 0;
} }
static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
hda_nid_t pin, hda_nid_t dac) struct nid_path *path)
{ {
hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac); int i;
if (nid_has_volume(codec, dac, HDA_OUTPUT))
return dac; for (i = path->depth - 1; i >= 0; i--) {
else if (nid_has_volume(codec, mix, HDA_OUTPUT)) if (nid_has_volume(codec, path->path[i], HDA_OUTPUT))
return mix; return path->path[i];
else if (nid_has_volume(codec, pin, HDA_OUTPUT)) }
return pin;
return 0; return 0;
} }
...@@ -3639,6 +3648,7 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, ...@@ -3639,6 +3648,7 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
int index; int index;
hda_nid_t dac, pin; hda_nid_t dac, pin;
hda_nid_t sw, vol; hda_nid_t sw, vol;
struct nid_path *path;
dac = spec->multiout.dac_nids[i]; dac = spec->multiout.dac_nids[i];
if (!dac) if (!dac)
...@@ -3652,27 +3662,36 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, ...@@ -3652,27 +3662,36 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
name = alc_get_line_out_pfx(spec, i, true, &index); name = alc_get_line_out_pfx(spec, i, true, &index);
} }
sw = alc_look_for_out_mute_nid(codec, pin, dac); path = get_out_path(codec, pin, dac);
vol = alc_look_for_out_vol_nid(codec, pin, dac); if (!path)
continue;
sw = alc_look_for_out_mute_nid(codec, path);
vol = alc_look_for_out_vol_nid(codec, path);
if (!name || !strcmp(name, "CLFE")) { if (!name || !strcmp(name, "CLFE")) {
/* Center/LFE */ /* Center/LFE */
err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1); err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1,
path);
if (err < 0) if (err < 0)
return err; return err;
err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2); err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2,
path);
if (err < 0) if (err < 0)
return err; return err;
err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1); err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1,
path);
if (err < 0) if (err < 0)
return err; return err;
err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2); err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2,
path);
if (err < 0) if (err < 0)
return err; return err;
} else { } else {
err = alc_auto_add_stereo_vol(codec, name, index, vol); err = alc_auto_add_stereo_vol(codec, name, index, vol,
path);
if (err < 0) if (err < 0)
return err; return err;
err = alc_auto_add_stereo_sw(codec, name, index, sw); err = alc_auto_add_stereo_sw(codec, name, index, sw,
path);
if (err < 0) if (err < 0)
return err; return err;
} }
...@@ -3685,9 +3704,14 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, ...@@ -3685,9 +3704,14 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
int cidx) int cidx)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
struct nid_path *path;
hda_nid_t sw, vol; hda_nid_t sw, vol;
int err; int err;
path = get_out_path(codec, pin, dac);
if (!path)
return 0;
if (!dac) { if (!dac) {
unsigned int val; unsigned int val;
/* the corresponding DAC is already occupied */ /* the corresponding DAC is already occupied */
...@@ -3695,18 +3719,18 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, ...@@ -3695,18 +3719,18 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
return 0; /* no way */ return 0; /* no way */
/* create a switch only */ /* create a switch only */
val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT); val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT);
if (is_ctl_used(spec->sw_ctls, val)) if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
return 0; /* already created */ return 0; /* already created */
mark_ctl_usage(spec->sw_ctls, val); path->ctls[NID_PATH_MUTE_CTL] = val;
return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val); return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val);
} }
sw = alc_look_for_out_mute_nid(codec, pin, dac); sw = alc_look_for_out_mute_nid(codec, path);
vol = alc_look_for_out_vol_nid(codec, pin, dac); vol = alc_look_for_out_vol_nid(codec, path);
err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol); err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol, path);
if (err < 0) if (err < 0)
return err; return err;
err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw); err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw, path);
if (err < 0) if (err < 0)
return err; return err;
return 0; return 0;
...@@ -3780,9 +3804,13 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, ...@@ -3780,9 +3804,13 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
n = 0; n = 0;
for (i = 0; i < num_pins; i++) { for (i = 0; i < num_pins; i++) {
hda_nid_t vol; hda_nid_t vol;
struct nid_path *path;
if (!pins[i] || !dacs[i]) if (!pins[i] || !dacs[i])
continue; continue;
vol = alc_look_for_out_vol_nid(codec, pins[i], dacs[i]); path = get_out_path(codec, pins[i], dacs[i]);
if (!path)
continue;
vol = alc_look_for_out_vol_nid(codec, path);
if (vol) if (vol)
ctl->values[n++] = ctl->values[n++] =
HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT); HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT);
...@@ -3821,6 +3849,7 @@ static void alc_auto_set_output_and_unmute(struct hda_codec *codec, ...@@ -3821,6 +3849,7 @@ static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
int i, num; int i, num;
hda_nid_t nid, mix = 0; hda_nid_t nid, mix = 0;
hda_nid_t srcs[HDA_MAX_CONNECTIONS]; hda_nid_t srcs[HDA_MAX_CONNECTIONS];
struct nid_path *path;
alc_set_pin_output(codec, pin, pin_type); alc_set_pin_output(codec, pin, pin_type);
nid = alc_go_down_to_selector(codec, pin); nid = alc_go_down_to_selector(codec, pin);
...@@ -3845,13 +3874,16 @@ static void alc_auto_set_output_and_unmute(struct hda_codec *codec, ...@@ -3845,13 +3874,16 @@ static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
AMP_IN_UNMUTE(1)); AMP_IN_UNMUTE(1));
} }
/* initialize volume */ /* initialize volume */
nid = alc_look_for_out_vol_nid(codec, pin, dac); path = get_out_path(codec, pin, dac);
if (!path)
return;
nid = alc_look_for_out_vol_nid(codec, path);
if (nid) if (nid)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_ZERO); AMP_OUT_ZERO);
/* unmute DAC if it's not assigned to a mixer */ /* unmute DAC if it's not assigned to a mixer */
nid = alc_look_for_out_mute_nid(codec, pin, dac); nid = alc_look_for_out_mute_nid(codec, path);
if (nid == mix && nid_has_mute(codec, dac, HDA_OUTPUT)) if (nid == mix && nid_has_mute(codec, dac, HDA_OUTPUT))
snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE, snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_ZERO); AMP_OUT_ZERO);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment