Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 293123
b: refs/heads/master
c: d2f344b
h: refs/heads/master
i:
  293121: fd6cf85
  293119: 1474199
v: v3
  • Loading branch information
Takashi Iwai committed Mar 13, 2012
1 parent 5c05c26 commit 1de5c30
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 23 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: 527c73bada6f02a35983ddb34db3a0fd4360c88c
refs/heads/master: d2f344b5e0a933b5b1d12f863406ee1d63e5bf8e
94 changes: 94 additions & 0 deletions trunk/sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2450,6 +2450,100 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
}
EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster);

/*
* mute-LED control using vmaster
*/
static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
static const char * const texts[] = {
"Off", "On", "Follow Master"
};
unsigned int index;

uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 3;
index = uinfo->value.enumerated.item;
if (index >= 3)
index = 2;
strcpy(uinfo->value.enumerated.name, texts[index]);
return 0;
}

static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hook->mute_mode;
return 0;
}

static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
unsigned int old_mode = hook->mute_mode;

hook->mute_mode = ucontrol->value.enumerated.item[0];
if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER)
hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
if (old_mode == hook->mute_mode)
return 0;
snd_hda_sync_vmaster_hook(hook);
return 1;
}

static struct snd_kcontrol_new vmaster_mute_mode = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mute-LED Mode",
.info = vmaster_mute_mode_info,
.get = vmaster_mute_mode_get,
.put = vmaster_mute_mode_put,
};

/*
* Add a mute-LED hook with the given vmaster switch kctl
* "Mute-LED Mode" control is automatically created and associated with
* the given hook.
*/
int snd_hda_add_vmaster_hook(struct hda_codec *codec,
struct hda_vmaster_mute_hook *hook)
{
struct snd_kcontrol *kctl;

if (!hook->hook || !hook->sw_kctl)
return 0;
snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec);
hook->codec = codec;
hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
if (!kctl)
return -ENOMEM;
return snd_hda_ctl_add(codec, 0, kctl);
}
EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook);

/*
* Call the hook with the current value for synchronization
* Should be called in init callback
*/
void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
{
if (!hook->hook || !hook->codec)
return;
switch (hook->mute_mode) {
case HDA_VMUTE_FOLLOW_MASTER:
snd_ctl_sync_vmaster_hook(hook->sw_kctl);
break;
default:
hook->hook(hook->codec, hook->mute_mode);
break;
}
}
EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);


/**
* snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
*
Expand Down
21 changes: 21 additions & 0 deletions trunk/sound/pci/hda/hda_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,27 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
__snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL)
int snd_hda_codec_reset(struct hda_codec *codec);

enum {
HDA_VMUTE_OFF,
HDA_VMUTE_ON,
HDA_VMUTE_FOLLOW_MASTER,
};

struct hda_vmaster_mute_hook {
/* below two fields must be filled by the caller of
* snd_hda_add_vmaster_hook() beforehand
*/
struct snd_kcontrol *sw_kctl;
void (*hook)(void *, int);
/* below are initialized automatically */
unsigned int mute_mode; /* HDA_VMUTE_XXX */
struct hda_codec *codec;
};

int snd_hda_add_vmaster_hook(struct hda_codec *codec,
struct hda_vmaster_mute_hook *hook);
void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook);

/* amp value bits */
#define HDA_AMP_MUTE 0x80
#define HDA_AMP_UNMUTE 0x00
Expand Down
17 changes: 8 additions & 9 deletions trunk/sound/pci/hda/patch_conexant.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ struct conexant_spec {
const struct snd_kcontrol_new *mixers[5];
int num_mixers;
hda_nid_t vmaster_nid;
struct snd_kcontrol *vmaster_sw_kctl;
void (*vmaster_hook)(struct snd_kcontrol *, int);
struct hda_vmaster_mute_hook vmaster_mute;

const struct hda_verb *init_verbs[5]; /* initialization verbs
* don't forget NULL
Expand Down Expand Up @@ -518,7 +517,7 @@ static int conexant_build_controls(struct hda_codec *codec)
err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
NULL, slave_pfxs,
"Playback Switch", true,
&spec->vmaster_sw_kctl);
&spec->vmaster_mute.sw_kctl);
if (err < 0)
return err;
}
Expand Down Expand Up @@ -4101,7 +4100,7 @@ static int cx_auto_init(struct hda_codec *codec)
cx_auto_init_input(codec);
cx_auto_init_digital(codec);
snd_hda_jack_report_sync(codec);
snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl);
snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
return 0;
}

Expand Down Expand Up @@ -4347,10 +4346,10 @@ static int cx_auto_build_controls(struct hda_codec *codec)
err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
if (err < 0)
return err;
if (spec->vmaster_hook && spec->vmaster_sw_kctl) {
snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl,
spec->vmaster_hook, codec);
snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl);
if (spec->vmaster_mute.hook && spec->vmaster_mute.sw_kctl) {
err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
if (err < 0)
return err;
}
return 0;
}
Expand Down Expand Up @@ -4481,7 +4480,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
/* NOTE: this should be applied via fixup once when the generic
* fixup code is merged to hda_codec.c
*/
spec->vmaster_hook = cx_auto_vmaster_hook;
spec->vmaster_mute.hook = cx_auto_vmaster_hook;

err = cx_auto_search_adcs(codec);
if (err < 0)
Expand Down
12 changes: 5 additions & 7 deletions trunk/sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ struct alc_spec {

/* for virtual master */
hda_nid_t vmaster_nid;
struct snd_kcontrol *vmaster_sw_kctl;
struct hda_vmaster_mute_hook vmaster_mute;
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
int num_loopbacks;
Expand Down Expand Up @@ -1960,7 +1960,7 @@ static int __alc_build_controls(struct hda_codec *codec)
err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
NULL, alc_slave_pfxs,
"Playback Switch",
true, &spec->vmaster_sw_kctl);
true, &spec->vmaster_mute.sw_kctl);
if (err < 0)
return err;
}
Expand Down Expand Up @@ -5894,13 +5894,11 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec,
struct alc_spec *spec = codec->spec;
switch (action) {
case ALC_FIXUP_ACT_BUILD:
if (!spec->vmaster_sw_kctl)
return;
snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl,
alc269_fixup_mic2_mute_hook, codec);
spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook;
snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
/* fallthru */
case ALC_FIXUP_ACT_INIT:
snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl);
snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
break;
}
}
Expand Down
13 changes: 7 additions & 6 deletions trunk/sound/pci/hda/patch_sigmatel.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ struct sigmatel_spec {
unsigned auto_dmic_cnt;
hda_nid_t auto_dmic_nids[MAX_DMICS_NUM];

struct snd_kcontrol *vmaster_sw_kctl;
struct hda_vmaster_mute_hook vmaster_mute;
};

static const hda_nid_t stac9200_adc_nids[1] = {
Expand Down Expand Up @@ -1160,14 +1160,15 @@ static int stac92xx_build_controls(struct hda_codec *codec)
err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
NULL, slave_pfxs,
"Playback Switch", true,
&spec->vmaster_sw_kctl);
&spec->vmaster_mute.sw_kctl);
if (err < 0)
return err;

if (spec->gpio_led) {
snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl,
stac92xx_vmaster_hook, codec);
snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl);
spec->vmaster_mute.hook = stac92xx_vmaster_hook;
err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
if (err < 0)
return err;
}

if (spec->aloopback_ctl &&
Expand Down Expand Up @@ -4432,7 +4433,7 @@ static int stac92xx_init(struct hda_codec *codec)
snd_hda_jack_report_sync(codec);

/* sync mute LED */
snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl);
snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
if (spec->dac_list)
stac92xx_power_down(codec);
return 0;
Expand Down

0 comments on commit 1de5c30

Please sign in to comment.