Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 353001
b: refs/heads/master
c: 792cf2f
h: refs/heads/master
i:
  352999: 4330721
v: v3
  • Loading branch information
Takashi Iwai committed Jan 10, 2013
1 parent 03083ee commit 104edd0
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 91 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2f179721c4a2d1035a93e9c908740d87ac9952e2
refs/heads/master: 792cf2fa2ea926c0c07277c0b67ab60745e8f898
168 changes: 78 additions & 90 deletions trunk/sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -3046,17 +3046,6 @@ static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
return false;
}

static void clear_vol_marks(struct hda_codec *codec)
{
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);
path->ctls[0] = path->ctls[1] = 0;
}
}

/* badness definition */
enum {
/* No primary DAC is found for the main output */
Expand Down Expand Up @@ -3121,8 +3110,15 @@ static struct nid_path *get_out_path(struct hda_codec *codec, hda_nid_t pin,
return NULL;
}

static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac)
/* look for widgets in the path between the given NIDs appropriate for
* volume and mute controls, and assign the values to ctls[].
*
* When no appropriate widget is found in the path, the badness value
* is incremented depending on the situation. The function returns the
* total badness for both volume and mute controls.
*/
static int assign_out_path_ctls(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac)
{
struct nid_path *path = get_out_path(codec, pin, dac);
hda_nid_t nid;
Expand All @@ -3143,7 +3139,8 @@ static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
nid = alc_look_for_out_mute_nid(codec, path);
if (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 ||
nid_has_mute(codec, nid, HDA_OUTPUT))
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
else
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
Expand Down Expand Up @@ -3237,7 +3234,7 @@ static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs,
if (!add_new_out_path(codec, pin, dac))
dac = dacs[i] = 0;
if (dac)
badness += eval_shared_vol_badness(codec, pin, dac);
badness += assign_out_path_ctls(codec, pin, dac);
}

return badness;
Expand Down Expand Up @@ -3533,76 +3530,86 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
spec->vmaster_nid = alc_look_for_out_vol_nid(codec, path);
}

/* clear the bitmap flags for creating controls */
clear_vol_marks(codec);
kfree(best_cfg);
return 0;
}

/* replace the channels in the composed amp value with the given number */
static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
{
val &= ~(0x3U << 16);
val |= chs << 16;
return val;
}

static int alc_auto_add_vol_ctl(struct hda_codec *codec,
const char *pfx, int cidx,
hda_nid_t nid, unsigned int chs,
unsigned int chs,
struct nid_path *path)
{
unsigned int val;
if (!nid || !path)
if (!path)
return 0;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
if (is_ctl_used(codec, val, NID_PATH_VOL_CTL) && chs != 2) /* exclude LFE */
val = path->ctls[NID_PATH_VOL_CTL];
if (!val)
return 0;
path->ctls[NID_PATH_VOL_CTL] = val;
return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
val);
val = amp_val_replace_channels(val, chs);
return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx, val);
}

/* return the channel bits suitable for the given path->ctls[] */
static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
int type)
{
int chs = 1; /* mono (left only) */
if (path) {
hda_nid_t nid = get_amp_nid_(path->ctls[type]);
if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
chs = 3; /* stereo */
}
return chs;
}

static int alc_auto_add_stereo_vol(struct hda_codec *codec,
const char *pfx, int cidx,
hda_nid_t nid, struct nid_path *path)
struct nid_path *path)
{
int chs = 1;
if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
chs = 3;
return alc_auto_add_vol_ctl(codec, pfx, cidx, nid, chs, path);
int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
return alc_auto_add_vol_ctl(codec, pfx, cidx, chs, path);
}

/* create a mute-switch for the given mixer widget;
* 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,
const char *pfx, int cidx,
hda_nid_t nid, unsigned int chs,
unsigned int chs,
struct nid_path *path)
{
int wid_type;
int type;
unsigned long val;
if (!nid || !path)
unsigned int val;
int type = ALC_CTL_WIDGET_MUTE;

if (!path)
return 0;
wid_type = get_wcaps_type(get_wcaps(codec, nid));
if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
type = ALC_CTL_WIDGET_MUTE;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
} else if (snd_hda_get_num_conns(codec, nid) == 1) {
type = ALC_CTL_WIDGET_MUTE;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
} else {
type = ALC_CTL_BIND_MUTE;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
}
if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL) && chs != 2) /* exclude LFE */
val = path->ctls[NID_PATH_MUTE_CTL];
if (!val)
return 0;
path->ctls[NID_PATH_MUTE_CTL] = val;
val = amp_val_replace_channels(val, chs);
if (get_amp_direction_(val) == HDA_INPUT) {
hda_nid_t nid = get_amp_nid_(val);
if (snd_hda_get_num_conns(codec, nid) > 1) {
type = ALC_CTL_BIND_MUTE;
val |= 2 << 19; /* FIXME: fixed two widgets, so far */
}
}
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,
int cidx, hda_nid_t nid,
struct nid_path *path)
int cidx, struct nid_path *path)
{
int chs = 1;
if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
chs = 3;
return alc_auto_add_sw_ctl(codec, pfx, cidx, nid, chs, path);
int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
return alc_auto_add_sw_ctl(codec, pfx, cidx, chs, path);
}

static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
Expand Down Expand Up @@ -3647,7 +3654,6 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
const char *name;
int index;
hda_nid_t dac, pin;
hda_nid_t sw, vol;
struct nid_path *path;

dac = spec->multiout.dac_nids[i];
Expand All @@ -3665,33 +3671,25 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
path = get_out_path(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")) {
/* Center/LFE */
err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1,
path);
err = alc_auto_add_vol_ctl(codec, "Center", 0, 1, path);
if (err < 0)
return err;
err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2,
path);
err = alc_auto_add_vol_ctl(codec, "LFE", 0, 2, path);
if (err < 0)
return err;
err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1,
path);
err = alc_auto_add_sw_ctl(codec, "Center", 0, 1, path);
if (err < 0)
return err;
err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2,
path);
err = alc_auto_add_sw_ctl(codec, "LFE", 0, 2, path);
if (err < 0)
return err;
} else {
err = alc_auto_add_stereo_vol(codec, name, index, vol,
path);
err = alc_auto_add_stereo_vol(codec, name, index, path);
if (err < 0)
return err;
err = alc_auto_add_stereo_sw(codec, name, index, sw,
path);
err = alc_auto_add_stereo_sw(codec, name, index, path);
if (err < 0)
return err;
}
Expand All @@ -3703,34 +3701,19 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac, const char *pfx,
int cidx)
{
struct alc_spec *spec = codec->spec;
struct nid_path *path;
hda_nid_t sw, vol;
int err;

path = get_out_path(codec, pin, dac);
if (!path)
return 0;

if (!dac) {
unsigned int val;
/* the corresponding DAC is already occupied */
if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
return 0; /* no way */
/* create a switch only */
val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT);
if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
return 0; /* already created */
path->ctls[NID_PATH_MUTE_CTL] = val;
return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val);
/* bind volume control will be created in the case of dac = 0 */
if (dac) {
err = alc_auto_add_stereo_vol(codec, pfx, cidx, path);
if (err < 0)
return err;
}

sw = alc_look_for_out_mute_nid(codec, path);
vol = alc_look_for_out_vol_nid(codec, path);
err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol, path);
if (err < 0)
return err;
err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw, path);
err = alc_auto_add_stereo_sw(codec, pfx, cidx, path);
if (err < 0)
return err;
return 0;
Expand Down Expand Up @@ -4051,7 +4034,12 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
return badness;
}

return 0;
/* assign volume and mute controls */
for (i = old_pins; i < spec->multi_ios; i++)
badness += assign_out_path_ctls(codec, spec->multi_io[i].pin,
spec->multi_io[i].dac);

return badness;
}

static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
Expand Down

0 comments on commit 104edd0

Please sign in to comment.