[alsa-devel] [PATCH] ALSA: hda/via - Add beep controls to VIA codecs

W. Trevor King wking at tremily.us
Wed Mar 25 08:01:04 CET 2015


My codec has a beep-generating node:

  $ cat /proc/asound/card1/codec#0
  Codec: VIA VT1802
  ...
  Vendor Id: 0x11068446
  Subsystem Id: 0x15587410
  Revision Id: 0x100000
  ...
  Node 0x22 [Beep Generator Widget] wcaps 0x70040c: Mono Amp-Out
    Amp-Out caps: ofs=0x0a, nsteps=0x12, stepsize=0x05, mute=1
    Amp-Out vals:  [0x0a]
    Power states:  D0 D1 D2 D3
    Power: setting=D0, actual=D0
  ...

But I was missing the:

  Control: name=...

entries that I need to manage this widget from alsamixer.  With this
patch (based on the similar Mono Amp-Out handling in
patch_conexant.c), I get a new:

  input: HDA Digital PCBeep as /devices/pci0000:00/0000:00:1b.0/sound/card1/hdaudioC1D0/input15

entry in dmesg and controls to manage that beep:

  $ cat /proc/asound/card1/codec#0 | grep -A5 Beep
  Node 0x22 [Beep Generator Widget] wcaps 0x70040c: Mono Amp-Out
    Control: name="Beep Playback Volume", index=0, device=0
      ControlAmp: chs=1, dir=Out, idx=0, ofs=0
    Control: name="Beep Playback Switch", index=0, device=0
      ControlAmp: chs=1, dir=Out, idx=0, ofs=0
    Amp-Out caps: ofs=0x0a, nsteps=0x12, stepsize=0x05, mute=1
    Amp-Out vals:  [0x12]
    Power states:  D0 D1 D2 D3
    Power: setting=D0, actual=D0

Signed-off-by: W. Trevor King <wking at tremily.us>
---
On Sun, Mar 22, 2015 at 09:27:24PM +0800, Raymond Yau wrote:
> Why beep generator cannot automically found by auto parser  ?
>> end_nid = codec->start_nid + codec->num_nodes;
> for (nid = codec->start_nid; nid < end_nid; nid++) {
> unsigned int wid_caps = get_wcaps(codec, nid);
> unsigned int wid_type = get_wcaps_type(wid_caps);
> if (wid_type == AC_WID_BEEP)
>              spec->gen.beep_nid = nid;
>   }

This is pretty much what patch_conexant.c's cx_auto_parse_beep() does,
so I've just shifted that code over here to handle beeps in VIA
codecs.  It works on my VT1802, but I don't have any other VIA codecs
around to check that it works on all of the VIA codecs (Takashi
pointed out that they can be buggy [1]).  Do I need to shift the
auto_parse_beep() check into the VT1802-specific portion of
patch_vt2002P(), or can I leave it here in the generic
via_parse_auto_config()?  Alternatively, we could wedge it into
via_new_spec(), which would give the per-codec patches time to clear
spec->gen.beep_nid for broken codecs before via_parse_auto_config()
calls snd_hda_gen_parse_auto_config() which consumes beep_nid.

Cheers,
Trevor

[1]: id:s5hpp813vva.wl-tiwai at suse.de
     http://thread.gmane.org/gmane.linux.alsa.devel/135819/focus=135823

 sound/pci/hda/patch_via.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 3de6d3d..e4919f8 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -109,6 +109,8 @@ struct via_spec {
 	int hp_work_active;
 	int vt1708_jack_detect;
 
+	unsigned int beep_amp;
+
 	void (*set_widgets_power_state)(struct hda_codec *codec);
 	unsigned int dac_stream_tag[4];
 };
@@ -355,6 +357,59 @@ static const struct snd_kcontrol_new via_pin_power_ctl_enum[] = {
 	{} /* terminator */
 };
 
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+static inline void set_beep_amp(struct via_spec *spec, hda_nid_t nid,
+				int idx, int dir)
+{
+	spec->gen.beep_nid = nid;
+	spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
+}
+/* additional beep mixers; the actual parameters are overwritten at build */
+static const struct snd_kcontrol_new cxt_beep_mixer[] = {
+	HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+/* create beep controls if needed */
+static int add_beep_ctls(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int err;
+
+	if (spec->beep_amp) {
+		const struct snd_kcontrol_new *knew;
+		for (knew = cxt_beep_mixer; knew->name; knew++) {
+			struct snd_kcontrol *kctl;
+			kctl = snd_ctl_new1(knew, codec);
+			if (!kctl)
+				return -ENOMEM;
+			kctl->private_value = spec->beep_amp;
+			err = snd_hda_ctl_add(codec, 0, kctl);
+			if (err < 0)
+				return err;
+		}
+	}
+	return 0;
+}
+
+static void auto_parse_beep(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	hda_nid_t nid, end_nid;
+
+	end_nid = codec->start_nid + codec->num_nodes;
+	for (nid = codec->start_nid; nid < end_nid; nid++)
+		if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) {
+			set_beep_amp(spec, nid, 0, HDA_OUTPUT);
+			break;
+		}
+}
+#else
+#define set_beep_amp(spec, nid, idx, dir) /* NOP */
+#define add_beep_ctls(codec)	0
+#define auto_parse_beep(codec)
+#endif
 
 /* check AA path's mute status */
 static bool is_aa_path_mute(struct hda_codec *codec)
@@ -441,6 +496,10 @@ static int via_build_controls(struct hda_codec *codec)
 	if (err < 0)
 		return err;
 
+	err = add_beep_ctls(codec);
+	if (err < 0)
+		return err;
+
 	if (spec->set_widgets_power_state)
 		spec->mixers[spec->num_mixers++] = via_pin_power_ctl_enum;
 
@@ -631,6 +690,8 @@ static int via_parse_auto_config(struct hda_codec *codec)
 	if (err < 0)
 		return err;
 
+	auto_parse_beep(codec);
+
 	err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
 	if (err < 0)
 		return err;
-- 
2.1.0.60.g85f0837



More information about the Alsa-devel mailing list