All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Geoffrey D. Bennett" <g@b4.vu>
To: Takashi Iwai <tiwai@suse.de>
Cc: Takashi Iwai <tiwai@suse.com>, linux-sound@vger.kernel.org
Subject: [PATCH 01/14] ALSA: scarlett2: Move initialisation code lower in the source
Date: Wed, 13 Mar 2024 05:03:14 +1030	[thread overview]
Message-ID: <0922071cb8be99a2394705de27b917d1e4e46f3f.1710264833.git.g@b4.vu> (raw)
In-Reply-To: <cover.1710264833.git.g@b4.vu>

So that more forward declarations won't be required when we add
handling of the ACK notification, move the initialisation functions to
after the notification functions.

Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
 sound/usb/mixer_scarlett2.c | 815 ++++++++++++++++++------------------
 1 file changed, 409 insertions(+), 406 deletions(-)

diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index bd114be537d7..8390b646c0ae 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -6383,412 +6383,7 @@ static int scarlett2_add_power_status_ctl(struct usb_mixer_interface *mixer)
 				     &private->power_status_ctl);
 }
 
-/*** Cleanup/Suspend Callbacks ***/
-
-static void scarlett2_private_free(struct usb_mixer_interface *mixer)
-{
-	struct scarlett2_data *private = mixer->private_data;
-
-	cancel_delayed_work_sync(&private->work);
-	kfree(private);
-	mixer->private_data = NULL;
-}
-
-static void scarlett2_private_suspend(struct usb_mixer_interface *mixer)
-{
-	struct scarlett2_data *private = mixer->private_data;
-
-	if (cancel_delayed_work_sync(&private->work))
-		scarlett2_config_save(private->mixer);
-}
-
-/*** Initialisation ***/
-
-static void scarlett2_count_io(struct scarlett2_data *private)
-{
-	const struct scarlett2_device_info *info = private->info;
-	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
-	int port_type, srcs = 0, dsts = 0;
-
-	/* Count the number of mux sources and destinations */
-	for (port_type = 0;
-	     port_type < SCARLETT2_PORT_TYPE_COUNT;
-	     port_type++) {
-		srcs += port_count[port_type][SCARLETT2_PORT_IN];
-		dsts += port_count[port_type][SCARLETT2_PORT_OUT];
-	}
-
-	private->num_mux_srcs = srcs;
-	private->num_mux_dsts = dsts;
-
-	/* Mixer inputs are mux outputs and vice versa.
-	 * Scarlett Gen 4 DSP I/O uses SCARLETT2_PORT_TYPE_MIX but
-	 * doesn't have mixer controls.
-	 */
-	private->num_mix_in =
-		port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT] -
-			info->dsp_count;
-
-	private->num_mix_out =
-		port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN] -
-			info->dsp_count;
-
-	/* Number of analogue line outputs */
-	private->num_line_out =
-		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
-
-	/* Number of monitor mix controls */
-	private->num_monitor_mix_ctls =
-		info->direct_monitor * 2 * private->num_mix_in;
-}
-
-/* Look through the interface descriptors for the Focusrite Control
- * interface (bInterfaceClass = 255 Vendor Specific Class) and set
- * bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval
- * in private
- */
-static int scarlett2_find_fc_interface(struct usb_device *dev,
-				       struct scarlett2_data *private)
-{
-	struct usb_host_config *config = dev->actconfig;
-	int i;
-
-	for (i = 0; i < config->desc.bNumInterfaces; i++) {
-		struct usb_interface *intf = config->interface[i];
-		struct usb_interface_descriptor *desc =
-			&intf->altsetting[0].desc;
-		struct usb_endpoint_descriptor *epd;
-
-		if (desc->bInterfaceClass != 255)
-			continue;
-
-		epd = get_endpoint(intf->altsetting, 0);
-		private->bInterfaceNumber = desc->bInterfaceNumber;
-		private->bEndpointAddress = epd->bEndpointAddress &
-			USB_ENDPOINT_NUMBER_MASK;
-		private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize);
-		private->bInterval = epd->bInterval;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-/* Initialise private data */
-static int scarlett2_init_private(struct usb_mixer_interface *mixer,
-				  const struct scarlett2_device_entry *entry)
-{
-	struct scarlett2_data *private =
-		kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL);
-
-	if (!private)
-		return -ENOMEM;
-
-	mutex_init(&private->usb_mutex);
-	mutex_init(&private->data_mutex);
-	INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work);
-
-	mixer->private_data = private;
-	mixer->private_free = scarlett2_private_free;
-	mixer->private_suspend = scarlett2_private_suspend;
-
-	private->info = entry->info;
-	private->config_set = entry->info->config_set;
-	private->series_name = entry->series_name;
-	scarlett2_count_io(private);
-	private->scarlett2_seq = 0;
-	private->mixer = mixer;
-
-	return scarlett2_find_fc_interface(mixer->chip->dev, private);
-}
-
-/* Cargo cult proprietary initialisation sequence */
-static int scarlett2_usb_init(struct usb_mixer_interface *mixer)
-{
-	struct usb_device *dev = mixer->chip->dev;
-	struct scarlett2_data *private = mixer->private_data;
-	u8 step0_buf[24];
-	u8 step2_buf[84];
-	int err;
-
-	if (usb_pipe_type_check(dev, usb_sndctrlpipe(dev, 0)))
-		return -EINVAL;
-
-	/* step 0 */
-	err = scarlett2_usb_rx(dev, private->bInterfaceNumber,
-			       SCARLETT2_USB_CMD_INIT,
-			       step0_buf, sizeof(step0_buf));
-	if (err < 0)
-		return err;
-
-	/* step 1 */
-	private->scarlett2_seq = 1;
-	err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_1, NULL, 0, NULL, 0);
-	if (err < 0)
-		return err;
-
-	/* step 2 */
-	private->scarlett2_seq = 1;
-	err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_2,
-			    NULL, 0,
-			    step2_buf, sizeof(step2_buf));
-	if (err < 0)
-		return err;
-
-	/* extract 4-byte firmware version from step2_buf[8] */
-	private->firmware_version = le32_to_cpu(*(__le32 *)(step2_buf + 8));
-	usb_audio_info(mixer->chip,
-		       "Firmware version %d\n",
-		       private->firmware_version);
-
-	return 0;
-}
-
-/* Get the flash segment numbers for the App_Settings and App_Upgrade
- * segments and put them in the private data
- */
-static int scarlett2_get_flash_segment_nums(struct usb_mixer_interface *mixer)
-{
-	struct scarlett2_data *private = mixer->private_data;
-	int err, count, i;
-
-	struct {
-		__le32 size;
-		__le32 count;
-		u8 unknown[8];
-	} __packed flash_info;
-
-	struct {
-		__le32 size;
-		__le32 flags;
-		char name[16];
-	} __packed segment_info;
-
-	err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_FLASH,
-			    NULL, 0,
-			    &flash_info, sizeof(flash_info));
-	if (err < 0)
-		return err;
-
-	count = le32_to_cpu(flash_info.count);
-
-	/* sanity check count */
-	if (count < SCARLETT2_SEGMENT_NUM_MIN ||
-	    count > SCARLETT2_SEGMENT_NUM_MAX + 1) {
-		usb_audio_err(mixer->chip,
-			      "invalid flash segment count: %d\n", count);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < count; i++) {
-		__le32 segment_num_req = cpu_to_le32(i);
-		int flash_segment_id;
-
-		err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_SEGMENT,
-				    &segment_num_req, sizeof(segment_num_req),
-				    &segment_info, sizeof(segment_info));
-		if (err < 0) {
-			usb_audio_err(mixer->chip,
-				"failed to get flash segment info %d: %d\n",
-				i, err);
-			return err;
-		}
-
-		if (!strncmp(segment_info.name,
-			     SCARLETT2_SEGMENT_SETTINGS_NAME, 16))
-			flash_segment_id = SCARLETT2_SEGMENT_ID_SETTINGS;
-		else if (!strncmp(segment_info.name,
-				  SCARLETT2_SEGMENT_FIRMWARE_NAME, 16))
-			flash_segment_id = SCARLETT2_SEGMENT_ID_FIRMWARE;
-		else
-			continue;
-
-		private->flash_segment_nums[flash_segment_id] = i;
-		private->flash_segment_blocks[flash_segment_id] =
-			le32_to_cpu(segment_info.size) /
-				SCARLETT2_FLASH_BLOCK_SIZE;
-	}
-
-	/* segment 0 is App_Gold and we never want to touch that, so
-	 * use 0 as the "not-found" value
-	 */
-	if (!private->flash_segment_nums[SCARLETT2_SEGMENT_ID_SETTINGS]) {
-		usb_audio_err(mixer->chip,
-			      "failed to find flash segment %s\n",
-			      SCARLETT2_SEGMENT_SETTINGS_NAME);
-		return -EINVAL;
-	}
-	if (!private->flash_segment_nums[SCARLETT2_SEGMENT_ID_FIRMWARE]) {
-		usb_audio_err(mixer->chip,
-			      "failed to find flash segment %s\n",
-			      SCARLETT2_SEGMENT_FIRMWARE_NAME);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* Read configuration from the interface on start */
-static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
-{
-	struct scarlett2_data *private = mixer->private_data;
-	const struct scarlett2_device_info *info = private->info;
-	int err, i;
-
-	if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_MSD_SWITCH)) {
-		err = scarlett2_usb_get_config(
-			mixer, SCARLETT2_CONFIG_MSD_SWITCH,
-			1, &private->msd_switch);
-		if (err < 0)
-			return err;
-	}
-
-	if (private->firmware_version < info->min_firmware_version) {
-		usb_audio_err(mixer->chip,
-			      "Focusrite %s firmware version %d is too old; "
-			      "need %d",
-			      private->series_name,
-			      private->firmware_version,
-			      info->min_firmware_version);
-		return 0;
-	}
-
-	/* no other controls are created if MSD mode is on */
-	if (private->msd_switch)
-		return 0;
-
-	err = scarlett2_update_input_level(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_input_pad(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_input_air(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_input_phantom(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_direct_monitor(mixer);
-	if (err < 0)
-		return err;
-
-	/* the rest of the configuration is for devices with a mixer */
-	if (!scarlett2_has_mixer(private))
-		return 0;
-
-	err = scarlett2_update_monitor_mix(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_monitor_other(mixer);
-	if (err < 0)
-		return err;
-
-	if (scarlett2_has_config_item(private,
-				      SCARLETT2_CONFIG_STANDALONE_SWITCH)) {
-		err = scarlett2_usb_get_config(
-			mixer, SCARLETT2_CONFIG_STANDALONE_SWITCH,
-			1, &private->standalone_switch);
-		if (err < 0)
-			return err;
-	}
-
-	if (scarlett2_has_config_item(private,
-				      SCARLETT2_CONFIG_POWER_EXT)) {
-		err = scarlett2_update_power_status(mixer);
-		if (err < 0)
-			return err;
-	}
-
-	err = scarlett2_update_sync(mixer);
-	if (err < 0)
-		return err;
-
-	if (scarlett2_has_config_item(private,
-				      SCARLETT2_CONFIG_LINE_OUT_VOLUME)) {
-		s16 sw_vol[SCARLETT2_ANALOGUE_MAX];
-
-		/* read SW line out volume */
-		err = scarlett2_usb_get_config(
-			mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME,
-			private->num_line_out, &sw_vol);
-		if (err < 0)
-			return err;
-
-		for (i = 0; i < private->num_line_out; i++)
-			private->vol[i] = clamp(
-				sw_vol[i] + SCARLETT2_VOLUME_BIAS,
-				0, SCARLETT2_VOLUME_BIAS);
-
-		/* read SW mute */
-		err = scarlett2_usb_get_config(
-			mixer, SCARLETT2_CONFIG_MUTE_SWITCH,
-			private->num_line_out, &private->mute_switch);
-		if (err < 0)
-			return err;
-
-		for (i = 0; i < private->num_line_out; i++)
-			private->mute_switch[i] =
-				!!private->mute_switch[i];
-
-		/* read SW/HW switches */
-		if (scarlett2_has_config_item(private,
-					      SCARLETT2_CONFIG_SW_HW_SWITCH)) {
-			err = scarlett2_usb_get_config(
-				mixer, SCARLETT2_CONFIG_SW_HW_SWITCH,
-				private->num_line_out,
-				&private->vol_sw_hw_switch);
-			if (err < 0)
-				return err;
-
-			for (i = 0; i < private->num_line_out; i++)
-				private->vol_sw_hw_switch[i] =
-					!!private->vol_sw_hw_switch[i];
-		}
-	}
-
-	err = scarlett2_update_volumes(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_dim_mute(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_input_select(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_input_gain(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_autogain(mixer);
-	if (err < 0)
-		return err;
-
-	err = scarlett2_update_input_safe(mixer);
-	if (err < 0)
-		return err;
-
-	if (scarlett2_has_config_item(private,
-				      SCARLETT2_CONFIG_PCM_INPUT_SWITCH)) {
-		err = scarlett2_update_pcm_input_switch(mixer);
-		if (err < 0)
-			return err;
-	}
-
-	err = scarlett2_update_mix(mixer);
-	if (err < 0)
-		return err;
-
-	return scarlett2_usb_get_mux(mixer);
-}
+/*** Notification Handlers ***/
 
 /* Notify on sync change */
 static void scarlett2_notify_sync(struct usb_mixer_interface *mixer)
@@ -7146,6 +6741,126 @@ static void scarlett2_notify(struct urb *urb)
 	}
 }
 
+/*** Cleanup/Suspend Callbacks ***/
+
+static void scarlett2_private_free(struct usb_mixer_interface *mixer)
+{
+	struct scarlett2_data *private = mixer->private_data;
+
+	cancel_delayed_work_sync(&private->work);
+	kfree(private);
+	mixer->private_data = NULL;
+}
+
+static void scarlett2_private_suspend(struct usb_mixer_interface *mixer)
+{
+	struct scarlett2_data *private = mixer->private_data;
+
+	if (cancel_delayed_work_sync(&private->work))
+		scarlett2_config_save(private->mixer);
+}
+
+/*** Initialisation ***/
+
+static void scarlett2_count_io(struct scarlett2_data *private)
+{
+	const struct scarlett2_device_info *info = private->info;
+	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
+	int port_type, srcs = 0, dsts = 0;
+
+	/* Count the number of mux sources and destinations */
+	for (port_type = 0;
+	     port_type < SCARLETT2_PORT_TYPE_COUNT;
+	     port_type++) {
+		srcs += port_count[port_type][SCARLETT2_PORT_IN];
+		dsts += port_count[port_type][SCARLETT2_PORT_OUT];
+	}
+
+	private->num_mux_srcs = srcs;
+	private->num_mux_dsts = dsts;
+
+	/* Mixer inputs are mux outputs and vice versa.
+	 * Scarlett Gen 4 DSP I/O uses SCARLETT2_PORT_TYPE_MIX but
+	 * doesn't have mixer controls.
+	 */
+	private->num_mix_in =
+		port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT] -
+			info->dsp_count;
+
+	private->num_mix_out =
+		port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN] -
+			info->dsp_count;
+
+	/* Number of analogue line outputs */
+	private->num_line_out =
+		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
+
+	/* Number of monitor mix controls */
+	private->num_monitor_mix_ctls =
+		info->direct_monitor * 2 * private->num_mix_in;
+}
+
+/* Look through the interface descriptors for the Focusrite Control
+ * interface (bInterfaceClass = 255 Vendor Specific Class) and set
+ * bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval
+ * in private
+ */
+static int scarlett2_find_fc_interface(struct usb_device *dev,
+				       struct scarlett2_data *private)
+{
+	struct usb_host_config *config = dev->actconfig;
+	int i;
+
+	for (i = 0; i < config->desc.bNumInterfaces; i++) {
+		struct usb_interface *intf = config->interface[i];
+		struct usb_interface_descriptor *desc =
+			&intf->altsetting[0].desc;
+		struct usb_endpoint_descriptor *epd;
+
+		if (desc->bInterfaceClass != 255)
+			continue;
+
+		epd = get_endpoint(intf->altsetting, 0);
+		private->bInterfaceNumber = desc->bInterfaceNumber;
+		private->bEndpointAddress = epd->bEndpointAddress &
+			USB_ENDPOINT_NUMBER_MASK;
+		private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize);
+		private->bInterval = epd->bInterval;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/* Initialise private data */
+static int scarlett2_init_private(struct usb_mixer_interface *mixer,
+				  const struct scarlett2_device_entry *entry)
+{
+	struct scarlett2_data *private =
+		kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL);
+
+	if (!private)
+		return -ENOMEM;
+
+	mutex_init(&private->usb_mutex);
+	mutex_init(&private->data_mutex);
+	INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work);
+
+	mixer->private_data = private;
+	mixer->private_free = scarlett2_private_free;
+	mixer->private_suspend = scarlett2_private_suspend;
+
+	private->info = entry->info;
+	private->config_set = entry->info->config_set;
+	private->series_name = entry->series_name;
+	scarlett2_count_io(private);
+	private->scarlett2_seq = 0;
+	private->mixer = mixer;
+
+	return scarlett2_find_fc_interface(mixer->chip->dev, private);
+}
+
+/* Submit a URB to receive notifications from the device */
 static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
 {
 	struct usb_device *dev = mixer->chip->dev;
@@ -7177,6 +6892,294 @@ static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
 	return usb_submit_urb(mixer->urb, GFP_KERNEL);
 }
 
+/* Cargo cult proprietary initialisation sequence */
+static int scarlett2_usb_init(struct usb_mixer_interface *mixer)
+{
+	struct usb_device *dev = mixer->chip->dev;
+	struct scarlett2_data *private = mixer->private_data;
+	u8 step0_buf[24];
+	u8 step2_buf[84];
+	int err;
+
+	if (usb_pipe_type_check(dev, usb_sndctrlpipe(dev, 0)))
+		return -EINVAL;
+
+	/* step 0 */
+	err = scarlett2_usb_rx(dev, private->bInterfaceNumber,
+			       SCARLETT2_USB_CMD_INIT,
+			       step0_buf, sizeof(step0_buf));
+	if (err < 0)
+		return err;
+
+	/* step 1 */
+	private->scarlett2_seq = 1;
+	err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_1, NULL, 0, NULL, 0);
+	if (err < 0)
+		return err;
+
+	/* step 2 */
+	private->scarlett2_seq = 1;
+	err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_2,
+			    NULL, 0,
+			    step2_buf, sizeof(step2_buf));
+	if (err < 0)
+		return err;
+
+	/* extract 4-byte firmware version from step2_buf[8] */
+	private->firmware_version = le32_to_cpu(*(__le32 *)(step2_buf + 8));
+	usb_audio_info(mixer->chip,
+		       "Firmware version %d\n",
+		       private->firmware_version);
+
+	return 0;
+}
+
+/* Get the flash segment numbers for the App_Settings and App_Upgrade
+ * segments and put them in the private data
+ */
+static int scarlett2_get_flash_segment_nums(struct usb_mixer_interface *mixer)
+{
+	struct scarlett2_data *private = mixer->private_data;
+	int err, count, i;
+
+	struct {
+		__le32 size;
+		__le32 count;
+		u8 unknown[8];
+	} __packed flash_info;
+
+	struct {
+		__le32 size;
+		__le32 flags;
+		char name[16];
+	} __packed segment_info;
+
+	err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_FLASH,
+			    NULL, 0,
+			    &flash_info, sizeof(flash_info));
+	if (err < 0)
+		return err;
+
+	count = le32_to_cpu(flash_info.count);
+
+	/* sanity check count */
+	if (count < SCARLETT2_SEGMENT_NUM_MIN ||
+	    count > SCARLETT2_SEGMENT_NUM_MAX + 1) {
+		usb_audio_err(mixer->chip,
+			      "invalid flash segment count: %d\n", count);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < count; i++) {
+		__le32 segment_num_req = cpu_to_le32(i);
+		int flash_segment_id;
+
+		err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_SEGMENT,
+				    &segment_num_req, sizeof(segment_num_req),
+				    &segment_info, sizeof(segment_info));
+		if (err < 0) {
+			usb_audio_err(mixer->chip,
+				"failed to get flash segment info %d: %d\n",
+				i, err);
+			return err;
+		}
+
+		if (!strncmp(segment_info.name,
+			     SCARLETT2_SEGMENT_SETTINGS_NAME, 16))
+			flash_segment_id = SCARLETT2_SEGMENT_ID_SETTINGS;
+		else if (!strncmp(segment_info.name,
+				  SCARLETT2_SEGMENT_FIRMWARE_NAME, 16))
+			flash_segment_id = SCARLETT2_SEGMENT_ID_FIRMWARE;
+		else
+			continue;
+
+		private->flash_segment_nums[flash_segment_id] = i;
+		private->flash_segment_blocks[flash_segment_id] =
+			le32_to_cpu(segment_info.size) /
+				SCARLETT2_FLASH_BLOCK_SIZE;
+	}
+
+	/* segment 0 is App_Gold and we never want to touch that, so
+	 * use 0 as the "not-found" value
+	 */
+	if (!private->flash_segment_nums[SCARLETT2_SEGMENT_ID_SETTINGS]) {
+		usb_audio_err(mixer->chip,
+			      "failed to find flash segment %s\n",
+			      SCARLETT2_SEGMENT_SETTINGS_NAME);
+		return -EINVAL;
+	}
+	if (!private->flash_segment_nums[SCARLETT2_SEGMENT_ID_FIRMWARE]) {
+		usb_audio_err(mixer->chip,
+			      "failed to find flash segment %s\n",
+			      SCARLETT2_SEGMENT_FIRMWARE_NAME);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Read configuration from the interface on start */
+static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
+{
+	struct scarlett2_data *private = mixer->private_data;
+	const struct scarlett2_device_info *info = private->info;
+	int err, i;
+
+	if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_MSD_SWITCH)) {
+		err = scarlett2_usb_get_config(
+			mixer, SCARLETT2_CONFIG_MSD_SWITCH,
+			1, &private->msd_switch);
+		if (err < 0)
+			return err;
+	}
+
+	if (private->firmware_version < info->min_firmware_version) {
+		usb_audio_err(mixer->chip,
+			      "Focusrite %s firmware version %d is too old; "
+			      "need %d",
+			      private->series_name,
+			      private->firmware_version,
+			      info->min_firmware_version);
+		return 0;
+	}
+
+	/* no other controls are created if MSD mode is on */
+	if (private->msd_switch)
+		return 0;
+
+	err = scarlett2_update_input_level(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_input_pad(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_input_air(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_input_phantom(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_direct_monitor(mixer);
+	if (err < 0)
+		return err;
+
+	/* the rest of the configuration is for devices with a mixer */
+	if (!scarlett2_has_mixer(private))
+		return 0;
+
+	err = scarlett2_update_monitor_mix(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_monitor_other(mixer);
+	if (err < 0)
+		return err;
+
+	if (scarlett2_has_config_item(private,
+				      SCARLETT2_CONFIG_STANDALONE_SWITCH)) {
+		err = scarlett2_usb_get_config(
+			mixer, SCARLETT2_CONFIG_STANDALONE_SWITCH,
+			1, &private->standalone_switch);
+		if (err < 0)
+			return err;
+	}
+
+	if (scarlett2_has_config_item(private,
+				      SCARLETT2_CONFIG_POWER_EXT)) {
+		err = scarlett2_update_power_status(mixer);
+		if (err < 0)
+			return err;
+	}
+
+	err = scarlett2_update_sync(mixer);
+	if (err < 0)
+		return err;
+
+	if (scarlett2_has_config_item(private,
+				      SCARLETT2_CONFIG_LINE_OUT_VOLUME)) {
+		s16 sw_vol[SCARLETT2_ANALOGUE_MAX];
+
+		/* read SW line out volume */
+		err = scarlett2_usb_get_config(
+			mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME,
+			private->num_line_out, &sw_vol);
+		if (err < 0)
+			return err;
+
+		for (i = 0; i < private->num_line_out; i++)
+			private->vol[i] = clamp(
+				sw_vol[i] + SCARLETT2_VOLUME_BIAS,
+				0, SCARLETT2_VOLUME_BIAS);
+
+		/* read SW mute */
+		err = scarlett2_usb_get_config(
+			mixer, SCARLETT2_CONFIG_MUTE_SWITCH,
+			private->num_line_out, &private->mute_switch);
+		if (err < 0)
+			return err;
+
+		for (i = 0; i < private->num_line_out; i++)
+			private->mute_switch[i] =
+				!!private->mute_switch[i];
+
+		/* read SW/HW switches */
+		if (scarlett2_has_config_item(private,
+					      SCARLETT2_CONFIG_SW_HW_SWITCH)) {
+			err = scarlett2_usb_get_config(
+				mixer, SCARLETT2_CONFIG_SW_HW_SWITCH,
+				private->num_line_out,
+				&private->vol_sw_hw_switch);
+			if (err < 0)
+				return err;
+
+			for (i = 0; i < private->num_line_out; i++)
+				private->vol_sw_hw_switch[i] =
+					!!private->vol_sw_hw_switch[i];
+		}
+	}
+
+	err = scarlett2_update_volumes(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_dim_mute(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_input_select(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_input_gain(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_autogain(mixer);
+	if (err < 0)
+		return err;
+
+	err = scarlett2_update_input_safe(mixer);
+	if (err < 0)
+		return err;
+
+	if (scarlett2_has_config_item(private,
+				      SCARLETT2_CONFIG_PCM_INPUT_SWITCH)) {
+		err = scarlett2_update_pcm_input_switch(mixer);
+		if (err < 0)
+			return err;
+	}
+
+	err = scarlett2_update_mix(mixer);
+	if (err < 0)
+		return err;
+
+	return scarlett2_usb_get_mux(mixer);
+}
+
 static const struct scarlett2_device_entry *get_scarlett2_device_entry(
 	struct usb_mixer_interface *mixer)
 {
-- 
2.43.0


  reply	other threads:[~2024-03-12 18:33 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-12 18:28 [PATCH 00/14] ALSA: scarlett2: Add support for Vocaster Geoffrey D. Bennett
2024-03-12 18:33 ` Geoffrey D. Bennett [this message]
2024-03-12 18:34 ` [PATCH 02/14] ALSA: scarlett2: Implement handling of the ACK notification Geoffrey D. Bennett
2024-03-12 18:34 ` [PATCH 03/14] ALSA: scarlett2: Add support for reading from flash Geoffrey D. Bennett
2024-03-12 18:34 ` [PATCH 04/14] ALSA: scarlett2: Rename gen4_write_addr to param_buf_addr Geoffrey D. Bennett
2024-03-12 18:35 ` [PATCH 05/14] ALSA: scarlett2: Add pbuf field to struct scarlett2_config Geoffrey D. Bennett
2024-03-12 18:35 ` [PATCH 06/14] ALSA: scarlett2: Add support for config items with size = 32 Geoffrey D. Bennett
2024-03-12 18:35 ` [PATCH 07/14] ALSA: scarlett2: Add additional input configuration parameters Geoffrey D. Bennett
2024-03-12 18:35 ` [PATCH 08/14] ALSA: scarlett2: Define the maximum preamp input gain per-config-set Geoffrey D. Bennett
2024-03-12 18:36 ` [PATCH 09/14] ALSA: scarlett2: Define autogain status texts per-config-set Geoffrey D. Bennett
2024-03-12 18:36 ` [PATCH 10/14] ALSA: scarlett2: Add input mute controls Geoffrey D. Bennett
2024-03-12 18:37 ` [PATCH 11/14] ALSA: scarlett2: Add DSP controls Geoffrey D. Bennett
2024-03-12 18:37 ` [PATCH 12/14] ALSA: scarlett2: Add support for Focusrite Vocaster One and Two Geoffrey D. Bennett
2024-03-12 18:37 ` [PATCH 13/14] ALSA: scarlett2: Add autogain target controls Geoffrey D. Bennett
2024-03-12 18:38 ` [PATCH 14/14] ALSA: scarlett2: Add Bluetooth volume control for Vocaster Two Geoffrey D. Bennett
2024-03-12 19:00 ` [PATCH 00/14] ALSA: scarlett2: Add support for Vocaster Takashi Iwai
2024-03-14 17:41   ` Geoffrey D. Bennett
2024-04-18  6:35 ` Takashi Iwai

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=0922071cb8be99a2394705de27b917d1e4e46f3f.1710264833.git.g@b4.vu \
    --to=g@b4.vu \
    --cc=linux-sound@vger.kernel.org \
    --cc=tiwai@suse.com \
    --cc=tiwai@suse.de \
    /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.