[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