[alsa-devel] [PATCH v2 1/1] ALSA: usb-audio: Add custom mixer status quirks for RME CC devices

Takashi Iwai tiwai at suse.de
Thu Oct 4 22:34:21 CEST 2018


On Thu, 04 Oct 2018 21:17:43 +0200,
Jussi Laako wrote:
> 
> Adds several vendor specific mixer quirks for RME's Class Compliant
> USB devices. These provide extra status information from the device
> otherwise not available.
> 
> These include AES/SPDIF rate and status information, current system
> sampling rate and measured frequency. This information is especially
> useful in cases where device's clock is slaved to external clock
> source.
> 
> Signed-off-by: Jussi Laako <jussi at sonarnerd.net>

The implementations look mostly OK, but just some nitpicking:

> ---
>  sound/usb/mixer_quirks.c | 349 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 349 insertions(+)
> 
> diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
> index cbfb48bdea51..d75e1f025b3b 100644
> --- a/sound/usb/mixer_quirks.c
> +++ b/sound/usb/mixer_quirks.c
> @@ -27,6 +27,8 @@
>   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
>   */
>  
> +#include <asm/div64.h>
> +

Rather include <linux/math64.h>, and put in the appropriate order.

>  #include <linux/hid.h>
>  #include <linux/init.h>
>  #include <linux/slab.h>
> @@ -1817,6 +1819,347 @@ static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
>  	return 0;
>  }
>  
> +/* RME Class Compliant device quirks */
> +
> +static const u32 snd_rme_rate_table[] = {
> +	32000, 44100, 48000, 50000,
> +	64000, 88200, 96000, 100000,
> +	128000, 176400, 192000, 200000,
> +	256000,	352800, 384000, 400000,
> +	512000, 705600, 768000, 800000
> +};
> +
> +static int snd_rme_get_status1(struct snd_kcontrol *kcontrol,
> +			       u32 *status1)
> +{
> +	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
> +	struct snd_usb_audio *chip = list->mixer->chip;
> +	struct usb_device *dev = chip->dev;
> +	int err;
> +
> +	err = snd_usb_lock_shutdown(chip);
> +	if (err < 0)
> +		return err;
> +
> +	err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
> +			      23,  /* GET_STATUS1 */

This number (and the other later ones) should be defined instead of
putting in each commit.

> +			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> +			      0, 0,
> +			      status1, sizeof(*status1));
> +	if (err < 0) {
> +		dev_err(&dev->dev,
> +			"unable to issue vendor read request (ret = %d)", err);
> +		goto end;
> +	}

Since you're calling in the same pattern, it's better to consider to
provide a helper to call snd_usb_ctl_msg() with the given type (and
shows the error there).  The helper can take snd_usb_lock_shutdown()
and unlock in it, so it'll simplify a lot.

> +
> +end:
> +	snd_usb_unlock_shutdown(chip);
> +	return err;
> +}
> +
> +static int snd_rme_rate_get(struct snd_kcontrol *kcontrol,
> +			    struct snd_ctl_elem_value *ucontrol)
> +{
> +	u32 status1;
> +	u32 rate = 0;
> +	int idx;
> +	int err;
> +
> +	err = snd_rme_get_status1(kcontrol, &status1);
> +	if (err < 0)
> +		return err;
> +
> +	switch (kcontrol->private_value)
> +	{
> +	case 0:  /* System */

Let's use enum.

> +		idx = (status1 >> 16) & 0x1f;

And, define this magic number 16.

> +		if (idx < ARRAY_SIZE(snd_rme_rate_table))
> +			rate = snd_rme_rate_table[idx];
> +		break;
> +	case 1:  /* AES */
> +		idx = (status1 >> 8) & 0xf;

Ditto (also for the rest).

> +static int snd_rme_sync_state_get(struct snd_kcontrol *kcontrol,
> +				  struct snd_ctl_elem_value *ucontrol)
> +{
> +	u32 status1;
> +	int idx = 0;
> +	int err;
> +
> +	err = snd_rme_get_status1(kcontrol, &status1);
> +	if (err < 0)
> +		return err;
> +
> +	switch (kcontrol->private_value)
> +	{
> +	case 1:  /* AES */
> +		if (status1 & 0x4)
> +			idx = 2;
> +		else if (status1 & 0x1)
> +			idx = 1;

All these magic numbers should be defined as well.

> +static int snd_rme_current_freq_get(struct snd_kcontrol *kcontrol,
> +				    struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
> +	struct snd_usb_audio *chip = list->mixer->chip;
> +	struct usb_device *dev = chip->dev;
> +	u32 status1;
> +	const u64 num = 104857600000000;

The 64bit const should be with ULL suffix.

> +static int snd_rme_rate_info(struct snd_kcontrol *kcontrol,
> +			     struct snd_ctl_elem_info *uinfo)
> +{
> +	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
> +	uinfo->count = 1;
> +	uinfo->value.integer.min =
> +		(kcontrol->private_value > 0) ? 0 : 32000;
> +	uinfo->value.integer.max =
> +		(kcontrol->private_value > 0) ? 200000 : 800000;

This better to be like
	switch (kcontrol->private_value) {
	case FOO:
		uinfo->value.integer.min = 0;
		uinfo->value.integer.min = 200000;
		break;
	case BAR:
		uinfo->value.integer.min = 32000;
		uinfo->value.integer.min = 800000;
		break;
	}


thanks,

Takashi


More information about the Alsa-devel mailing list