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

Takashi Iwai tiwai at suse.de
Wed Mar 25 08:15:51 CET 2015


At Wed, 25 Mar 2015 00:01:04 -0700,
W. Trevor King wrote:
> 
> 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.

I guess it's OK as is.  Not all VIA codecs seem to have the beep
widget, and the codecs with the beep widget have all the same
functionality (digital beep with the output amp).

Care to brush up your patch as a formal form to be merged to upstream?
There are a few conflicts with the latest sound.git tree code, but I
can manage to resolve them.

Later on, we can move the common code to the generic parser (with yet
some behavior flag), but it can be done by another patch.


thanks,

Takashi

> 
> 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