Skip to content

Commit

Permalink
ALSA: hda - Add digital beep playback switch for STAC/IDT codecs
Browse files Browse the repository at this point in the history
The digital beep widget may have no mute control, and always enabling
the beep is ofen pretty annoying, especially on laptops.

This patch adds a mixer control "PC Beep Playback Switch" when there
is no mixer amp mute is found, and controls it on software.

Reference: Novell bnc#444572
	https://bugzilla.novell.com/show_bug.cgi?id=444572

Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed Nov 13, 2008
1 parent d7a8943 commit 4d4e9bb
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 6 deletions.
4 changes: 4 additions & 0 deletions sound/pci/hda/hda_beep.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ static void snd_hda_generate_beep(struct work_struct *work)
container_of(work, struct hda_beep, beep_work);
struct hda_codec *codec = beep->codec;

if (!beep->enabled)
return;

/* generate tone */
snd_hda_codec_write_cache(codec, beep->nid, 0,
AC_VERB_SET_BEEP_CONTROL, beep->tone);
Expand Down Expand Up @@ -115,6 +118,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
beep->nid = nid;
beep->dev = input_dev;
beep->codec = codec;
beep->enabled = 1;
codec->beep = beep;

INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
Expand Down
1 change: 1 addition & 0 deletions sound/pci/hda/hda_beep.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct hda_beep {
char phys[32];
int tone;
int nid;
int enabled;
struct work_struct beep_work; /* scheduled task for beep event */
};

Expand Down
69 changes: 63 additions & 6 deletions sound/pci/hda/patch_sigmatel.c
Original file line number Diff line number Diff line change
Expand Up @@ -2587,8 +2587,10 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
};

/* add dynamic controls */
static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type,
int idx, const char *name, unsigned long val)
static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
struct snd_kcontrol_new *ktemp,
int idx, const char *name,
unsigned long val)
{
struct snd_kcontrol_new *knew;

Expand All @@ -2607,20 +2609,29 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type,
}

knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = stac92xx_control_templates[type];
*knew = *ktemp;
knew->index = idx;
knew->name = kstrdup(name, GFP_KERNEL);
if (! knew->name)
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
spec->num_kctl_used++;
return 0;
}

static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec,
int type, int idx, const char *name,
unsigned long val)
{
return stac92xx_add_control_temp(spec,
&stac92xx_control_templates[type],
idx, name, val);
}


/* add dynamic controls */
static int stac92xx_add_control(struct sigmatel_spec *spec, int type,
const char *name, unsigned long val)
static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type,
const char *name, unsigned long val)
{
return stac92xx_add_control_idx(spec, type, 0, name, val);
}
Expand Down Expand Up @@ -3062,6 +3073,43 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec,
return 0;
}

#ifdef CONFIG_SND_HDA_INPUT_BEEP
#define stac92xx_dig_beep_switch_info snd_ctl_boolean_mono_info

static int stac92xx_dig_beep_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = codec->beep->enabled;
return 0;
}

static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
int enabled = !!ucontrol->value.integer.value[0];
if (codec->beep->enabled != enabled) {
codec->beep->enabled = enabled;
return 1;
}
return 0;
}

static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = stac92xx_dig_beep_switch_info,
.get = stac92xx_dig_beep_switch_get,
.put = stac92xx_dig_beep_switch_put,
};

static int stac92xx_beep_switch_ctl(struct hda_codec *codec)
{
return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl,
0, "PC Beep Playback Switch", 0);
}
#endif

static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
Expand Down Expand Up @@ -3368,13 +3416,22 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
#ifdef CONFIG_SND_HDA_INPUT_BEEP
if (spec->digbeep_nid > 0) {
hda_nid_t nid = spec->digbeep_nid;
unsigned int caps;

err = stac92xx_auto_create_beep_ctls(codec, nid);
if (err < 0)
return err;
err = snd_hda_attach_beep_device(codec, nid);
if (err < 0)
return err;
/* if no beep switch is available, make its own one */
caps = query_amp_caps(codec, nid, HDA_OUTPUT);
if (codec->beep &&
!((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) {
err = stac92xx_beep_switch_ctl(codec);
if (err < 0)
return err;
}
}
#endif

Expand Down

0 comments on commit 4d4e9bb

Please sign in to comment.