On Sun, 08 Aug 2021 07:09:31 +0200, Damien Zammit wrote: > > This adds a second mixer control to Digidesign Mbox > to select between Analog/SPDIF capture. > > Users will note that selecting the SPDIF input source > automatically switches the clock mode to sync to SPDIF, > which is a feature of the hardware. > > (You can change the clock source back to internal if you want > to capture from spdif but not sync to its clock although this mode > is probably not recommended). > > Unfortunately, starting the stream resets both modes > to Internally clocked and Analog input mode. Please add your Signed-off-by line. It's mandatory. About the code change: > @@ -596,31 +596,53 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) > > /* Digidesign Mbox 1 clock source switch (internal/spdif) */ > > -static int snd_mbox1_switch_get(struct snd_kcontrol *kctl, > - struct snd_ctl_elem_value *ucontrol) > +static int snd_mbox1_clk_switch_get(struct snd_kcontrol *kctl, > + struct snd_ctl_elem_value *ucontrol) > { > + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); > + struct snd_usb_audio *chip = list->mixer->chip; > + unsigned char buff[3]; > + You need to wrap the execution with snd_usb_lock_shutdown() / snd_usb_unlock_shutdown(). > + /* Read clock source */ > + snd_usb_ctl_msg(chip->dev, > + usb_rcvctrlpipe(chip->dev, 0), 0x81, > + USB_DIR_IN | > + USB_TYPE_CLASS | > + USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3); Please try to align the indent level. And, the execution error check is missing. Also, I believe it'd be wise to make it a helper function, as this is used in another place, too. Ditto for other snd_usb_ctl_msg() calls, too. > +static int snd_mbox1_src_switch_get(struct snd_kcontrol *kctl, > + struct snd_ctl_elem_value *ucontrol) > +{ > + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); > + struct snd_usb_audio *chip = list->mixer->chip; > + unsigned char source[1]; Missing snd_usb_lock_shutdown() / *_unlock_*() here, too. > + /* Read input source */ > + snd_usb_ctl_msg(chip->dev, > + usb_rcvctrlpipe(chip->dev, 0), 0x81, > + USB_DIR_IN | > + USB_TYPE_CLASS | > + USB_RECIP_INTERFACE, 0x00, 0x500, source, 1); Check the error. > + kctl->private_value = source[0] - 1; The value returned from the hardware isn't reliable. Check whether it's a valid value. > + ucontrol->value.enumerated.item[0] = kctl->private_value; > + return 0; > +} > + > +static int snd_mbox1_src_switch_update(struct usb_mixer_interface *mixer, int val) > +{ > + struct snd_usb_audio *chip = mixer->chip; > + int err; > + unsigned char buff[3]; > + unsigned char source[1]; > + > + err = snd_usb_lock_shutdown(chip); > + if (err < 0) > + return err; > + > + /* Read input source */ > + err = snd_usb_ctl_msg(chip->dev, > + usb_rcvctrlpipe(chip->dev, 0), 0x81, > + USB_DIR_IN | > + USB_TYPE_CLASS | > + USB_RECIP_INTERFACE, 0x00, 0x500, source, 1); > + if (err < 0) > + goto err; > + > + /* 2 possibilities: ANALOG Source -> 0x01 > + * S/PDIF Source -> 0x02 > + * Setting the input source to S/PDIF resets the clock source to S/PDIF > + */ > + source[0] = (val + 1) & 0xff; Here better to trust private_value is a valid value, and you can drop the superfluous "& 0xff". It's cut down anyway. thanks, Takashi