diff mbox series

[1/2] ALSA: usb-audio: scarlett2: Read mixer volumes at init time

Message ID 68f57d71862e1c858e48dd6c0a6c68342ac53fc9.1622974661.git.g@b4.vu (mailing list archive)
State New, archived
Headers show
Series ALSA: usb-audio: scarlett2: Read all configuration at init time | expand

Commit Message

Geoffrey D. Bennett June 6, 2021, 2:16 p.m. UTC
Add support for reading the mixer volumes from the hardware when the
driver is initialising. Previously these ALSA volume controls were
initialised to zero instead of being initialised to match the hardware
state.

Fixes: 9e4d5c1be21f ("ALSA: usb-audio: Scarlett Gen 2 mixer interface")
Suggested-by: Vladimir Sadovnikov <sadko4u@gmail.com>
Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
 sound/usb/mixer_scarlett_gen2.c | 57 +++++++++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 2 deletions(-)

Comments

Markus Schroetter June 6, 2021, 2:32 p.m. UTC | #1
On 06.06.21 16:16, Geoffrey D. Bennett wrote:
> Add support for reading the mixer volumes from the hardware when the
> driver is initialising. Previously these ALSA volume controls were
> initialised to zero instead of being initialised to match the hardware
> state.
>
> Fixes: 9e4d5c1be21f ("ALSA: usb-audio: Scarlett Gen 2 mixer interface")
> Suggested-by: Vladimir Sadovnikov <sadko4u@gmail.com>
> Signed-off-by: Geoffrey D. Bennett <g@b4.vu>

Tested-by: Markus Schroetter <project.m.schroetter@gmail.com>

> ---
>  sound/usb/mixer_scarlett_gen2.c | 57 +++++++++++++++++++++++++++++++--
>  1 file changed, 55 insertions(+), 2 deletions(-)
>
> diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
> index 4caf379d5b99..b0043906c77f 100644
> --- a/sound/usb/mixer_scarlett_gen2.c
> +++ b/sound/usb/mixer_scarlett_gen2.c
> @@ -117,11 +117,12 @@
>  #define SCARLETT2_MIXER_MAX_DB 6
>  #define SCARLETT2_MIXER_MAX_VALUE \
>  	((SCARLETT2_MIXER_MAX_DB - SCARLETT2_MIXER_MIN_DB) * 2)
> +#define SCARLETT2_MIXER_VALUE_COUNT (SCARLETT2_MIXER_MAX_VALUE + 1)
>  
>  /* map from (dB + 80) * 2 to mixer value
>   * for dB in 0 .. 172: int(8192 * pow(10, ((dB - 160) / 2 / 20)))
>   */
> -static const u16 scarlett2_mixer_values[173] = {
> +static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = {
>  	0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
>  	2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
>  	9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
> @@ -465,6 +466,7 @@ static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports,
>  
>  #define SCARLETT2_USB_INIT_SEQ 0x00000000
>  #define SCARLETT2_USB_GET_METER_LEVELS 0x00001001
> +#define SCARLETT2_USB_GET_MIX 0x00002001
>  #define SCARLETT2_USB_SET_MIX 0x00002002
>  #define SCARLETT2_USB_SET_MUX 0x00003002
>  #define SCARLETT2_USB_GET_DATA 0x00800000
> @@ -784,6 +786,49 @@ static int scarlett2_usb_get_volume_status(
>  				 buf, sizeof(*buf));
>  }
>  
> +/* Send a USB message to get the volumes for all inputs of one mix
> + * and put the values into private->mix[]
> + */
> +static int scarlett2_usb_get_mix(struct usb_mixer_interface *mixer,
> +				 int mix_num)
> +{
> +	struct scarlett2_mixer_data *private = mixer->private_data;
> +	const struct scarlett2_device_info *info = private->info;
> +
> +	int num_mixer_in =
> +		info->ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT];
> +	int err, i, j, k;
> +
> +	struct {
> +		__le16 mix_num;
> +		__le16 count;
> +	} __packed req;
> +
> +	__le16 data[SCARLETT2_INPUT_MIX_MAX];
> +
> +	req.mix_num = mix_num;
> +	req.count = num_mixer_in;
> +
> +	err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MIX,
> +			    &req, sizeof(req),
> +			    data, num_mixer_in * sizeof(u16));
> +	if (err < 0)
> +		return err;
> +
> +	for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++) {
> +		u16 mixer_value = le16_to_cpu(data[i]);
> +
> +		for (k = 0; k < SCARLETT2_MIXER_VALUE_COUNT; k++)
> +			if (scarlett2_mixer_values[k] >= mixer_value)
> +				break;
> +		if (k == SCARLETT2_MIXER_VALUE_COUNT)
> +			k = SCARLETT2_MIXER_MAX_VALUE;
> +		private->mix[j] = k;
> +	}
> +
> +	return 0;
> +}
> +
>  /* Send a USB message to set the volumes for all inputs of one mix
>   * (values obtained from private->mix[])
>   */
> @@ -1831,7 +1876,7 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer,
>  	return scarlett2_usb(mixer, SCARLETT2_USB_INIT_SEQ, NULL, 0, NULL, 0);
>  }
>  
> -/* Read line-in config and line-out volume settings on start */
> +/* Read configuration from the interface on start */
>  static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
>  {
>  	struct scarlett2_mixer_data *private = mixer->private_data;
> @@ -1839,6 +1884,8 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
>  	const struct scarlett2_ports *ports = info->ports;
>  	int num_line_out =
>  		ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT];
> +	int num_mixer_out =
> +		ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_IN];
>  	u8 level_switches[SCARLETT2_LEVEL_SWITCH_MAX];
>  	u8 pad_switches[SCARLETT2_PAD_SWITCH_MAX];
>  	struct scarlett2_usb_volume_status volume_status;
> @@ -1894,6 +1941,12 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
>  	for (i = 0; i < info->button_count; i++)
>  		private->buttons[i] = !!volume_status.buttons[i];
>  
> +	for (i = 0; i < num_mixer_out; i++) {
> +		err = scarlett2_usb_get_mix(mixer, i);
> +		if (err < 0)
> +			return err;
> +	}
> +
>  	return 0;
>  }
>
kernel test robot June 7, 2021, 5:23 a.m. UTC | #2
Hi "Geoffrey,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v5.13-rc4]
[also build test WARNING on next-20210604]
[cannot apply to sound/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Geoffrey-D-Bennett/ALSA-usb-audio-scarlett2-Read-all-configuration-at-init-time/20210606-222037
base:    8124c8a6b35386f73523d27eacb71b5364a68c4c
config: xtensa-randconfig-s032-20210607 (attached as .config)
compiler: xtensa-linux-gcc (GCC) 9.3.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/4cd436ec424b3564c2dcf9b3b8fd83c8894051f1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Geoffrey-D-Bennett/ALSA-usb-audio-scarlett2-Read-all-configuration-at-init-time/20210606-222037
        git checkout 4cd436ec424b3564c2dcf9b3b8fd83c8894051f1
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' W=1 ARCH=xtensa 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> sound/usb/mixer_scarlett_gen2.c:809:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] mix_num @@     got int mix_num @@
   sound/usb/mixer_scarlett_gen2.c:809:21: sparse:     expected restricted __le16 [usertype] mix_num
   sound/usb/mixer_scarlett_gen2.c:809:21: sparse:     got int mix_num
>> sound/usb/mixer_scarlett_gen2.c:810:19: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] count @@     got int num_mixer_in @@
   sound/usb/mixer_scarlett_gen2.c:810:19: sparse:     expected restricted __le16 [usertype] count
   sound/usb/mixer_scarlett_gen2.c:810:19: sparse:     got int num_mixer_in

vim +809 sound/usb/mixer_scarlett_gen2.c

   788	
   789	/* Send a USB message to get the volumes for all inputs of one mix
   790	 * and put the values into private->mix[]
   791	 */
   792	static int scarlett2_usb_get_mix(struct usb_mixer_interface *mixer,
   793					 int mix_num)
   794	{
   795		struct scarlett2_mixer_data *private = mixer->private_data;
   796		const struct scarlett2_device_info *info = private->info;
   797	
   798		int num_mixer_in =
   799			info->ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT];
   800		int err, i, j, k;
   801	
   802		struct {
   803			__le16 mix_num;
   804			__le16 count;
   805		} __packed req;
   806	
   807		__le16 data[SCARLETT2_INPUT_MIX_MAX];
   808	
 > 809		req.mix_num = mix_num;
 > 810		req.count = num_mixer_in;
   811	
   812		err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MIX,
   813				    &req, sizeof(req),
   814				    data, num_mixer_in * sizeof(u16));
   815		if (err < 0)
   816			return err;
   817	
   818		for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++) {
   819			u16 mixer_value = le16_to_cpu(data[i]);
   820	
   821			for (k = 0; k < SCARLETT2_MIXER_VALUE_COUNT; k++)
   822				if (scarlett2_mixer_values[k] >= mixer_value)
   823					break;
   824			if (k == SCARLETT2_MIXER_VALUE_COUNT)
   825				k = SCARLETT2_MIXER_MAX_VALUE;
   826			private->mix[j] = k;
   827		}
   828	
   829		return 0;
   830	}
   831	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
index 4caf379d5b99..b0043906c77f 100644
--- a/sound/usb/mixer_scarlett_gen2.c
+++ b/sound/usb/mixer_scarlett_gen2.c
@@ -117,11 +117,12 @@ 
 #define SCARLETT2_MIXER_MAX_DB 6
 #define SCARLETT2_MIXER_MAX_VALUE \
 	((SCARLETT2_MIXER_MAX_DB - SCARLETT2_MIXER_MIN_DB) * 2)
+#define SCARLETT2_MIXER_VALUE_COUNT (SCARLETT2_MIXER_MAX_VALUE + 1)
 
 /* map from (dB + 80) * 2 to mixer value
  * for dB in 0 .. 172: int(8192 * pow(10, ((dB - 160) / 2 / 20)))
  */
-static const u16 scarlett2_mixer_values[173] = {
+static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = {
 	0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
 	2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
 	9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
@@ -465,6 +466,7 @@  static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports,
 
 #define SCARLETT2_USB_INIT_SEQ 0x00000000
 #define SCARLETT2_USB_GET_METER_LEVELS 0x00001001
+#define SCARLETT2_USB_GET_MIX 0x00002001
 #define SCARLETT2_USB_SET_MIX 0x00002002
 #define SCARLETT2_USB_SET_MUX 0x00003002
 #define SCARLETT2_USB_GET_DATA 0x00800000
@@ -784,6 +786,49 @@  static int scarlett2_usb_get_volume_status(
 				 buf, sizeof(*buf));
 }
 
+/* Send a USB message to get the volumes for all inputs of one mix
+ * and put the values into private->mix[]
+ */
+static int scarlett2_usb_get_mix(struct usb_mixer_interface *mixer,
+				 int mix_num)
+{
+	struct scarlett2_mixer_data *private = mixer->private_data;
+	const struct scarlett2_device_info *info = private->info;
+
+	int num_mixer_in =
+		info->ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT];
+	int err, i, j, k;
+
+	struct {
+		__le16 mix_num;
+		__le16 count;
+	} __packed req;
+
+	__le16 data[SCARLETT2_INPUT_MIX_MAX];
+
+	req.mix_num = mix_num;
+	req.count = num_mixer_in;
+
+	err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MIX,
+			    &req, sizeof(req),
+			    data, num_mixer_in * sizeof(u16));
+	if (err < 0)
+		return err;
+
+	for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++) {
+		u16 mixer_value = le16_to_cpu(data[i]);
+
+		for (k = 0; k < SCARLETT2_MIXER_VALUE_COUNT; k++)
+			if (scarlett2_mixer_values[k] >= mixer_value)
+				break;
+		if (k == SCARLETT2_MIXER_VALUE_COUNT)
+			k = SCARLETT2_MIXER_MAX_VALUE;
+		private->mix[j] = k;
+	}
+
+	return 0;
+}
+
 /* Send a USB message to set the volumes for all inputs of one mix
  * (values obtained from private->mix[])
  */
@@ -1831,7 +1876,7 @@  static int scarlett2_init_private(struct usb_mixer_interface *mixer,
 	return scarlett2_usb(mixer, SCARLETT2_USB_INIT_SEQ, NULL, 0, NULL, 0);
 }
 
-/* Read line-in config and line-out volume settings on start */
+/* Read configuration from the interface on start */
 static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
 {
 	struct scarlett2_mixer_data *private = mixer->private_data;
@@ -1839,6 +1884,8 @@  static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
 	const struct scarlett2_ports *ports = info->ports;
 	int num_line_out =
 		ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT];
+	int num_mixer_out =
+		ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_IN];
 	u8 level_switches[SCARLETT2_LEVEL_SWITCH_MAX];
 	u8 pad_switches[SCARLETT2_PAD_SWITCH_MAX];
 	struct scarlett2_usb_volume_status volume_status;
@@ -1894,6 +1941,12 @@  static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
 	for (i = 0; i < info->button_count; i++)
 		private->buttons[i] = !!volume_status.buttons[i];
 
+	for (i = 0; i < num_mixer_out; i++) {
+		err = scarlett2_usb_get_mix(mixer, i);
+		if (err < 0)
+			return err;
+	}
+
 	return 0;
 }