aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-11-12 10:45:04 -0500
committerTakashi Iwai <tiwai@suse.de>2008-11-13 08:37:14 -0500
commit4d4e9bb339cfcde7811af10859ba1ce2fe3d46b4 (patch)
treebf9bbfdc9e6c0a9d912013edfba83924d50b6eda /sound/pci/hda/patch_sigmatel.c
parentd7a8943635485597ae7c6d554a8ccf3ce5a42d2d (diff)
ALSA: hda - Add digital beep playback switch for STAC/IDT codecs
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>
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c69
1 files changed, 63 insertions, 6 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 4300a679cd86..1633ef2c654a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2587,8 +2587,10 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
2587}; 2587};
2588 2588
2589/* add dynamic controls */ 2589/* add dynamic controls */
2590static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, 2590static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
2591 int idx, const char *name, unsigned long val) 2591 struct snd_kcontrol_new *ktemp,
2592 int idx, const char *name,
2593 unsigned long val)
2592{ 2594{
2593 struct snd_kcontrol_new *knew; 2595 struct snd_kcontrol_new *knew;
2594 2596
@@ -2607,20 +2609,29 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type,
2607 } 2609 }
2608 2610
2609 knew = &spec->kctl_alloc[spec->num_kctl_used]; 2611 knew = &spec->kctl_alloc[spec->num_kctl_used];
2610 *knew = stac92xx_control_templates[type]; 2612 *knew = *ktemp;
2611 knew->index = idx; 2613 knew->index = idx;
2612 knew->name = kstrdup(name, GFP_KERNEL); 2614 knew->name = kstrdup(name, GFP_KERNEL);
2613 if (! knew->name) 2615 if (!knew->name)
2614 return -ENOMEM; 2616 return -ENOMEM;
2615 knew->private_value = val; 2617 knew->private_value = val;
2616 spec->num_kctl_used++; 2618 spec->num_kctl_used++;
2617 return 0; 2619 return 0;
2618} 2620}
2619 2621
2622static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec,
2623 int type, int idx, const char *name,
2624 unsigned long val)
2625{
2626 return stac92xx_add_control_temp(spec,
2627 &stac92xx_control_templates[type],
2628 idx, name, val);
2629}
2630
2620 2631
2621/* add dynamic controls */ 2632/* add dynamic controls */
2622static int stac92xx_add_control(struct sigmatel_spec *spec, int type, 2633static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type,
2623 const char *name, unsigned long val) 2634 const char *name, unsigned long val)
2624{ 2635{
2625 return stac92xx_add_control_idx(spec, type, 0, name, val); 2636 return stac92xx_add_control_idx(spec, type, 0, name, val);
2626} 2637}
@@ -3062,6 +3073,43 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec,
3062 return 0; 3073 return 0;
3063} 3074}
3064 3075
3076#ifdef CONFIG_SND_HDA_INPUT_BEEP
3077#define stac92xx_dig_beep_switch_info snd_ctl_boolean_mono_info
3078
3079static int stac92xx_dig_beep_switch_get(struct snd_kcontrol *kcontrol,
3080 struct snd_ctl_elem_value *ucontrol)
3081{
3082 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3083 ucontrol->value.integer.value[0] = codec->beep->enabled;
3084 return 0;
3085}
3086
3087static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
3088 struct snd_ctl_elem_value *ucontrol)
3089{
3090 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3091 int enabled = !!ucontrol->value.integer.value[0];
3092 if (codec->beep->enabled != enabled) {
3093 codec->beep->enabled = enabled;
3094 return 1;
3095 }
3096 return 0;
3097}
3098
3099static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
3100 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3101 .info = stac92xx_dig_beep_switch_info,
3102 .get = stac92xx_dig_beep_switch_get,
3103 .put = stac92xx_dig_beep_switch_put,
3104};
3105
3106static int stac92xx_beep_switch_ctl(struct hda_codec *codec)
3107{
3108 return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl,
3109 0, "PC Beep Playback Switch", 0);
3110}
3111#endif
3112
3065static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec) 3113static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec)
3066{ 3114{
3067 struct sigmatel_spec *spec = codec->spec; 3115 struct sigmatel_spec *spec = codec->spec;
@@ -3368,6 +3416,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
3368#ifdef CONFIG_SND_HDA_INPUT_BEEP 3416#ifdef CONFIG_SND_HDA_INPUT_BEEP
3369 if (spec->digbeep_nid > 0) { 3417 if (spec->digbeep_nid > 0) {
3370 hda_nid_t nid = spec->digbeep_nid; 3418 hda_nid_t nid = spec->digbeep_nid;
3419 unsigned int caps;
3371 3420
3372 err = stac92xx_auto_create_beep_ctls(codec, nid); 3421 err = stac92xx_auto_create_beep_ctls(codec, nid);
3373 if (err < 0) 3422 if (err < 0)
@@ -3375,6 +3424,14 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
3375 err = snd_hda_attach_beep_device(codec, nid); 3424 err = snd_hda_attach_beep_device(codec, nid);
3376 if (err < 0) 3425 if (err < 0)
3377 return err; 3426 return err;
3427 /* if no beep switch is available, make its own one */
3428 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
3429 if (codec->beep &&
3430 !((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) {
3431 err = stac92xx_beep_switch_ctl(codec);
3432 if (err < 0)
3433 return err;
3434 }
3378 } 3435 }
3379#endif 3436#endif
3380 3437