All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Stefan Stistrup <sstistrup@gmail.com>
Cc: linux-sound@vger.kernel.org, tiwai@suse.de
Subject: Re: [PATCH v2] ALSA: usb-audio: Add input gain and master output mixer elements for RME Babyface Pro
Date: Thu, 08 Aug 2024 07:40:07 +0200	[thread overview]
Message-ID: <875xsb6094.wl-tiwai@suse.de> (raw)
In-Reply-To: <20240807191121.68614-1-sstistrup@gmail.com>

On Wed, 07 Aug 2024 21:11:21 +0200,
Stefan Stistrup wrote:
> 
> Add missing input gain and master output mixer controls for RME Babyface Pro
> 
> This patch implements:
> 
> 1. Input gain controls for 2 mic and 2 line inputs
> 2. Master output volume controls for all 12 output channels
> 
> These additions allow for more complete control of the Babyface Pro under Linux.
> 
> Signed-off-by: Stefan Stistrup <sstistrup@gmail.com>
> ---
> Changes in v2:
>  - Check invalid negative values in snd_bbfpro_gain_put
>  - Coding style fixes, blank line in snd_bbfpro_gain_update and checkpatch.pl errors

There are a few other errors and warnings detected by checkpatch.pl.
Please fix those and resubmit.


thanks,

Takashi

> 
>  sound/usb/mixer_quirks.c | 164 ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 163 insertions(+), 1 deletion(-)
> 
> diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
> index 065a4be0d771..4c050110004b 100644
> --- a/sound/usb/mixer_quirks.c
> +++ b/sound/usb/mixer_quirks.c
> @@ -2541,14 +2541,23 @@ enum {
>  #define SND_BBFPRO_CTL_REG2_PAD_AN1 4
>  #define SND_BBFPRO_CTL_REG2_PAD_AN2 5
> 
> -#define SND_BBFPRO_MIXER_IDX_MASK 0x1ff
> +#define SND_BBFPRO_MIXER_MAIN_OUT_CH_OFFSET 992
> +#define SND_BBFPRO_MIXER_IDX_MASK 0x3ff
>  #define SND_BBFPRO_MIXER_VAL_MASK 0x3ffff
>  #define SND_BBFPRO_MIXER_VAL_SHIFT 9
>  #define SND_BBFPRO_MIXER_VAL_MIN 0 // -inf
>  #define SND_BBFPRO_MIXER_VAL_MAX 65536 // +6dB
> 
> +#define SND_BBFPRO_GAIN_CHANNEL_MASK 0x03
> +#define SND_BBFPRO_GAIN_CHANNEL_SHIFT 7
> +#define SND_BBFPRO_GAIN_VAL_MASK 0x7f
> +#define SND_BBFPRO_GAIN_VAL_MIN 0
> +#define SND_BBFPRO_GAIN_VAL_MIC_MAX 65
> +#define SND_BBFPRO_GAIN_VAL_LINE_MAX 18 // 9db in 0.5db incraments
> +
>  #define SND_BBFPRO_USBREQ_CTL_REG1 0x10
>  #define SND_BBFPRO_USBREQ_CTL_REG2 0x17
> +#define SND_BBFPRO_USBREQ_GAIN 0x1a
>  #define SND_BBFPRO_USBREQ_MIXER 0x12
> 
>  static int snd_bbfpro_ctl_update(struct usb_mixer_interface *mixer, u8 reg,
> @@ -2695,6 +2704,115 @@ static int snd_bbfpro_ctl_resume(struct usb_mixer_elem_list *list)
>  	return snd_bbfpro_ctl_update(list->mixer, reg, idx, value);
>  }
> 
> +static int snd_bbfpro_gain_update(struct usb_mixer_interface *mixer,
> +				  u8 channel, u8 gain)
> +{
> +	int err;
> +	struct snd_usb_audio *chip = mixer->chip;
> +
> +	if (channel < 2) {
> +		// XLR preamp: 3-bit fine, 5-bit coarse; special case >60
> +		if (gain < 60)
> +			gain = ((gain % 3) << 5) | (gain / 3);
> +		else
> +			gain = ((gain % 6) << 5) | (60 / 3);
> +	}
> +
> +	err = snd_usb_lock_shutdown(chip);
> +	if (err < 0)
> +		return err;
> +
> +	err = snd_usb_ctl_msg(chip->dev,
> +				usb_sndctrlpipe(chip->dev, 0),
> +				SND_BBFPRO_USBREQ_GAIN,
> +				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> +				gain, channel, NULL, 0);
> +
> +	snd_usb_unlock_shutdown(chip);
> +	return err;
> +}
> +
> +static int snd_bbfpro_gain_get(struct snd_kcontrol *kcontrol,
> +                               struct snd_ctl_elem_value *ucontrol)
> +{
> +	int value = kcontrol->private_value & SND_BBFPRO_GAIN_VAL_MASK;
> +	ucontrol->value.integer.value[0] = value;
> +	return 0;
> +}
> +
> +static int snd_bbfpro_gain_info(struct snd_kcontrol *kcontrol,
> +                                struct snd_ctl_elem_info *uinfo)
> +{
> +	int pv, channel;
> +
> +	pv = kcontrol->private_value;
> +	channel = (pv >> SND_BBFPRO_GAIN_CHANNEL_SHIFT) &
> +		  SND_BBFPRO_GAIN_CHANNEL_MASK;
> +
> +	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
> +	uinfo->count = 1;
> +	uinfo->value.integer.min = SND_BBFPRO_GAIN_VAL_MIN;
> +
> +	if (channel < 2) {
> +		uinfo->value.integer.max = SND_BBFPRO_GAIN_VAL_MIC_MAX;
> +	} else {
> +		uinfo->value.integer.max = SND_BBFPRO_GAIN_VAL_LINE_MAX;
> +	}
> +
> +	return 0;
> +}
> +
> +static int snd_bbfpro_gain_put(struct snd_kcontrol *kcontrol,
> +                               struct snd_ctl_elem_value *ucontrol)
> +{
> +	int pv, channel, old_value, value, err;
> +
> +	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
> +	struct usb_mixer_interface *mixer = list->mixer;
> +
> +	pv = kcontrol->private_value;
> +	channel = (pv >> SND_BBFPRO_GAIN_CHANNEL_SHIFT) &
> +		  SND_BBFPRO_GAIN_CHANNEL_MASK;
> +	old_value = pv & SND_BBFPRO_GAIN_VAL_MASK;
> +	value = ucontrol->value.integer.value[0];
> +
> +	if (value < SND_BBFPRO_GAIN_VAL_MIN)
> +		return -EINVAL;
> +
> +	if (channel < 2) {
> +		if (value > SND_BBFPRO_GAIN_VAL_MIC_MAX)
> +			return -EINVAL;
> +	} else {
> +		if (value > SND_BBFPRO_GAIN_VAL_LINE_MAX)
> +			return -EINVAL;
> +	}
> +
> +	if (value == old_value)
> +		return 0;
> +
> +	err = snd_bbfpro_gain_update(mixer, channel, value);
> +	if (err < 0)
> +		return err;
> +
> +	kcontrol->private_value =
> +		  (channel << SND_BBFPRO_GAIN_CHANNEL_SHIFT) | value;
> +	return 1;
> +}
> +
> +static int snd_bbfpro_gain_resume(struct usb_mixer_elem_list *list)
> +{
> +	int pv, channel, value;
> +
> +	struct snd_kcontrol *kctl = list->kctl;
> +
> +	pv = kctl->private_value;
> +	channel = (pv >> SND_BBFPRO_GAIN_CHANNEL_SHIFT) &
> +		  SND_BBFPRO_GAIN_CHANNEL_MASK;
> +	value = pv & SND_BBFPRO_GAIN_VAL_MASK;
> +
> +	return snd_bbfpro_gain_update(list->mixer, channel, value);
> +}
> +
>  static int snd_bbfpro_vol_update(struct usb_mixer_interface *mixer, u16 index,
>  				 u32 value)
>  {
> @@ -2790,6 +2908,15 @@ static const struct snd_kcontrol_new snd_bbfpro_ctl_control = {
>  	.put = snd_bbfpro_ctl_put
>  };
> 
> +static const struct snd_kcontrol_new snd_bbfpro_gain_control = {
> +	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
> +	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
> +	.index = 0,
> +	.info = snd_bbfpro_gain_info,
> +	.get = snd_bbfpro_gain_get,
> +	.put = snd_bbfpro_gain_put
> +};
> +
>  static const struct snd_kcontrol_new snd_bbfpro_vol_control = {
>  	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
>  	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
> @@ -2813,6 +2940,18 @@ static int snd_bbfpro_ctl_add(struct usb_mixer_interface *mixer, u8 reg,
>  		&knew, NULL);
>  }
> 
> +static int snd_bbfpro_gain_add(struct usb_mixer_interface *mixer, u8 channel,
> +                               char *name)
> +{
> +	struct snd_kcontrol_new knew = snd_bbfpro_gain_control;
> +
> +	knew.name = name;
> +	knew.private_value = channel << SND_BBFPRO_GAIN_CHANNEL_SHIFT;
> +
> +	return add_single_ctl_with_resume(mixer, 0, snd_bbfpro_gain_resume,
> +		&knew, NULL);
> +}
> +
>  static int snd_bbfpro_vol_add(struct usb_mixer_interface *mixer, u16 index,
>  			      char *name)
>  {
> @@ -2860,6 +2999,29 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
>  		}
>  	}
> 
> +	// Main out volume
> +	for (i = 0 ; i < 12 ; ++i) {
> +		snprintf(name, sizeof(name), "Main-Out %s", output[i]);
> +		// Main outs are offset to 992
> +		err = snd_bbfpro_vol_add(mixer,
> +					 i + SND_BBFPRO_MIXER_MAIN_OUT_CH_OFFSET,
> +					 name);
> +		if (err < 0)
> +			return err;
> +	}
> +
> +	// Input gain
> +	for (i = 0 ; i < 4 ; ++i) {
> +		if (i < 2) {
> +			snprintf(name, sizeof(name), "Mic-%s Gain", input[i]);
> +		} else {
> +			snprintf(name, sizeof(name), "Line-%s Gain", input[i]);
> +		}
> +		err = snd_bbfpro_gain_add(mixer, i, name);
> +		if (err < 0)
> +			return err;
> +	}
> +
>  	// Control Reg 1
>  	err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1,
>  				 SND_BBFPRO_CTL_REG1_CLK_OPTICAL,
> --
> 2.45.2
> 

      reply	other threads:[~2024-08-08  5:39 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-07 19:11 [PATCH v2] ALSA: usb-audio: Add input gain and master output mixer elements for RME Babyface Pro Stefan Stistrup
2024-08-08  5:40 ` Takashi Iwai [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=875xsb6094.wl-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=linux-sound@vger.kernel.org \
    --cc=sstistrup@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.