All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch
@ 2022-03-06 15:20 Geoffrey D. Bennett
  2022-03-06 15:21 ` [PATCH 1/2] ALSA: scarlett2: Split scarlett2_config_items[] into 3 sections Geoffrey D. Bennett
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Geoffrey D. Bennett @ 2022-03-06 15:20 UTC (permalink / raw)
  To: alsa-devel, Takashi Iwai; +Cc: Hin-Tak Leung, Vladimir Sadovnikov

Hi Takashi,

I discovered an internal "standalone" switch on all the Scarlett Gen
2/3 interfaces with internal mixers. After enabling this switch, the
interface will act as a standalone mixer (according to its previous
configuration) when not connected to a USB host. The interfaces come
from the factory with the switch off, and the vendor driver enables it
without question. This patch adds a new ALSA control to set the switch
on or off.

This is the first configuration item that is common between the Gen 2
and 3 interfaces but with a different offset, so the patch is in two
parts. The first patch allows for the same configuration item to have
a different offset between Gen 2/3 and the second patch adds the new
switch.

Regards,
Geoffrey.

Geoffrey D. Bennett (2):
  ALSA: scarlett2: Split scarlett2_config_items[] into 3 sections
  ALSA: scarlett2: Add support for the internal "standalone" switch

 sound/usb/mixer_scarlett_gen2.c | 171 ++++++++++++++++++++++++++------
 1 file changed, 141 insertions(+), 30 deletions(-)

-- 
2.35.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] ALSA: scarlett2: Split scarlett2_config_items[] into 3 sections
  2022-03-06 15:20 [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch Geoffrey D. Bennett
@ 2022-03-06 15:21 ` Geoffrey D. Bennett
  2022-03-06 15:21 ` [PATCH 2/2] ALSA: scarlett2: Add support for the internal "standalone" switch Geoffrey D. Bennett
  2022-03-08  9:06 ` [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: Geoffrey D. Bennett @ 2022-03-06 15:21 UTC (permalink / raw)
  To: alsa-devel, Takashi Iwai; +Cc: Hin-Tak Leung, Vladimir Sadovnikov

scarlett2_config_items[] contains the parameters for the configuration
items. The driver previously had two sets of configurations items; one
for devices with no mixer, and one for devices with a mixer. This
patch splits the latter into two (one set for Gen 2 devices and one
set for Gen 3 devices) in preparation for a new item (standalone)
which is present in both but with a different offset.

Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
 sound/usb/mixer_scarlett_gen2.c | 74 +++++++++++++++++++++++----------
 1 file changed, 51 insertions(+), 23 deletions(-)

diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
index 53ebabf42472..22e442208550 100644
--- a/sound/usb/mixer_scarlett_gen2.c
+++ b/sound/usb/mixer_scarlett_gen2.c
@@ -6,7 +6,7 @@
  *   - 6i6/18i8/18i20 Gen 2
  *   - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3
  *
- *   Copyright (c) 2018-2021 by Geoffrey D. Bennett <g at b4.vu>
+ *   Copyright (c) 2018-2022 by Geoffrey D. Bennett <g at b4.vu>
  *   Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com>
  *
  *   Based on the Scarlett (Gen 1) Driver for ALSA:
@@ -195,6 +195,16 @@ static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = {
 /* Maximum number of meters (sum of output port counts) */
 #define SCARLETT2_MAX_METERS 65
 
+/* There are three different sets of configuration parameters across
+ * the devices
+ */
+enum {
+	SCARLETT2_CONFIG_SET_NO_MIXER = 0,
+	SCARLETT2_CONFIG_SET_GEN_2 = 1,
+	SCARLETT2_CONFIG_SET_GEN_3 = 2,
+	SCARLETT2_CONFIG_SET_COUNT = 3
+};
+
 /* Hardware port types:
  * - None (no input to mux)
  * - Analogue I/O
@@ -308,10 +318,8 @@ struct scarlett2_device_info {
 	 */
 	u8 has_msd_mode;
 
-	/* Gen 3 devices without a mixer have a different
-	 * configuration set
-	 */
-	u8 has_mixer;
+	/* which set of configuration parameters the device uses */
+	u8 config_set;
 
 	/* line out hw volume is sw controlled */
 	u8 line_out_hw_vol;
@@ -426,7 +434,7 @@ struct scarlett2_data {
 static const struct scarlett2_device_info s6i6_gen2_info = {
 	.usb_id = USB_ID(0x1235, 0x8203),
 
-	.has_mixer = 1,
+	.config_set = SCARLETT2_CONFIG_SET_GEN_2,
 	.level_input_count = 2,
 	.pad_input_count = 2,
 
@@ -472,7 +480,7 @@ static const struct scarlett2_device_info s6i6_gen2_info = {
 static const struct scarlett2_device_info s18i8_gen2_info = {
 	.usb_id = USB_ID(0x1235, 0x8204),
 
-	.has_mixer = 1,
+	.config_set = SCARLETT2_CONFIG_SET_GEN_2,
 	.level_input_count = 2,
 	.pad_input_count = 4,
 
@@ -521,7 +529,7 @@ static const struct scarlett2_device_info s18i8_gen2_info = {
 static const struct scarlett2_device_info s18i20_gen2_info = {
 	.usb_id = USB_ID(0x1235, 0x8201),
 
-	.has_mixer = 1,
+	.config_set = SCARLETT2_CONFIG_SET_GEN_2,
 	.line_out_hw_vol = 1,
 
 	.line_out_descrs = {
@@ -576,6 +584,7 @@ static const struct scarlett2_device_info solo_gen3_info = {
 	.usb_id = USB_ID(0x1235, 0x8211),
 
 	.has_msd_mode = 1,
+	.config_set = SCARLETT2_CONFIG_SET_NO_MIXER,
 	.level_input_count = 1,
 	.level_input_first = 1,
 	.air_input_count = 1,
@@ -588,6 +597,7 @@ static const struct scarlett2_device_info s2i2_gen3_info = {
 	.usb_id = USB_ID(0x1235, 0x8210),
 
 	.has_msd_mode = 1,
+	.config_set = SCARLETT2_CONFIG_SET_NO_MIXER,
 	.level_input_count = 2,
 	.air_input_count = 2,
 	.phantom_count = 1,
@@ -599,7 +609,7 @@ static const struct scarlett2_device_info s4i4_gen3_info = {
 	.usb_id = USB_ID(0x1235, 0x8212),
 
 	.has_msd_mode = 1,
-	.has_mixer = 1,
+	.config_set = SCARLETT2_CONFIG_SET_GEN_3,
 	.level_input_count = 2,
 	.pad_input_count = 2,
 	.air_input_count = 2,
@@ -645,7 +655,7 @@ static const struct scarlett2_device_info s8i6_gen3_info = {
 	.usb_id = USB_ID(0x1235, 0x8213),
 
 	.has_msd_mode = 1,
-	.has_mixer = 1,
+	.config_set = SCARLETT2_CONFIG_SET_GEN_3,
 	.level_input_count = 2,
 	.pad_input_count = 2,
 	.air_input_count = 2,
@@ -698,7 +708,7 @@ static const struct scarlett2_device_info s18i8_gen3_info = {
 	.usb_id = USB_ID(0x1235, 0x8214),
 
 	.has_msd_mode = 1,
-	.has_mixer = 1,
+	.config_set = SCARLETT2_CONFIG_SET_GEN_3,
 	.line_out_hw_vol = 1,
 	.has_speaker_switching = 1,
 	.level_input_count = 2,
@@ -768,7 +778,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
 	.usb_id = USB_ID(0x1235, 0x8215),
 
 	.has_msd_mode = 1,
-	.has_mixer = 1,
+	.config_set = SCARLETT2_CONFIG_SET_GEN_3,
 	.line_out_hw_vol = 1,
 	.has_speaker_switching = 1,
 	.has_talkback = 1,
@@ -944,13 +954,11 @@ struct scarlett2_config {
 	u8 activate;
 };
 
-/* scarlett2_config_items[0] is for devices without a mixer
- * scarlett2_config_items[1] is for devices with a mixer
- */
 static const struct scarlett2_config
-	scarlett2_config_items[2][SCARLETT2_CONFIG_COUNT] =
+	scarlett2_config_items[SCARLETT2_CONFIG_SET_COUNT]
+			      [SCARLETT2_CONFIG_COUNT] =
 
-/* Devices without a mixer (Solo and 2i2 Gen 3) */
+/* Devices without a mixer (Gen 3 Solo and 2i2) */
 { {
 	[SCARLETT2_CONFIG_MSD_SWITCH] = {
 		.offset = 0x04, .size = 8, .activate = 6 },
@@ -970,7 +978,27 @@ static const struct scarlett2_config
 	[SCARLETT2_CONFIG_AIR_SWITCH] = {
 		.offset = 0x09, .size = 1, .activate = 8 },
 
-/* Devices with a mixer (Gen 2 and all other Gen 3) */
+/* Gen 2 devices: 6i6, 18i8, 18i20 */
+}, {
+	[SCARLETT2_CONFIG_DIM_MUTE] = {
+		.offset = 0x31, .size = 8, .activate = 2 },
+
+	[SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
+		.offset = 0x34, .size = 16, .activate = 1 },
+
+	[SCARLETT2_CONFIG_MUTE_SWITCH] = {
+		.offset = 0x5c, .size = 8, .activate = 1 },
+
+	[SCARLETT2_CONFIG_SW_HW_SWITCH] = {
+		.offset = 0x66, .size = 8, .activate = 3 },
+
+	[SCARLETT2_CONFIG_LEVEL_SWITCH] = {
+		.offset = 0x7c, .size = 8, .activate = 7 },
+
+	[SCARLETT2_CONFIG_PAD_SWITCH] = {
+		.offset = 0x84, .size = 8, .activate = 8 },
+
+/* Gen 3 devices: 4i4, 8i6, 18i8, 18i20 */
 }, {
 	[SCARLETT2_CONFIG_DIM_MUTE] = {
 		.offset = 0x31, .size = 8, .activate = 2 },
@@ -1175,7 +1203,7 @@ static int scarlett2_usb_get_config(
 	struct scarlett2_data *private = mixer->private_data;
 	const struct scarlett2_device_info *info = private->info;
 	const struct scarlett2_config *config_item =
-		&scarlett2_config_items[info->has_mixer][config_item_num];
+		&scarlett2_config_items[info->config_set][config_item_num];
 	int size, err, i;
 	u8 *buf_8;
 	u8 value;
@@ -1235,7 +1263,7 @@ static int scarlett2_usb_set_config(
 	struct scarlett2_data *private = mixer->private_data;
 	const struct scarlett2_device_info *info = private->info;
 	const struct scarlett2_config *config_item =
-	       &scarlett2_config_items[info->has_mixer][config_item_num];
+	       &scarlett2_config_items[info->config_set][config_item_num];
 	struct {
 		__le32 offset;
 		__le32 bytes;
@@ -1692,7 +1720,7 @@ static int scarlett2_add_sync_ctl(struct usb_mixer_interface *mixer)
 	struct scarlett2_data *private = mixer->private_data;
 
 	/* devices without a mixer also don't support reporting sync status */
-	if (!private->info->has_mixer)
+	if (private->info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
 		return 0;
 
 	return scarlett2_add_new_ctl(mixer, &scarlett2_sync_ctl,
@@ -3399,7 +3427,7 @@ static int scarlett2_add_meter_ctl(struct usb_mixer_interface *mixer)
 	struct scarlett2_data *private = mixer->private_data;
 
 	/* devices without a mixer also don't support reporting levels */
-	if (!private->info->has_mixer)
+	if (private->info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
 		return 0;
 
 	return scarlett2_add_new_ctl(mixer, &scarlett2_meter_ctl,
@@ -3632,7 +3660,7 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
 		return err;
 
 	/* the rest of the configuration is for devices with a mixer */
-	if (!info->has_mixer)
+	if (info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
 		return 0;
 
 	err = scarlett2_update_sync(mixer);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] ALSA: scarlett2: Add support for the internal "standalone" switch
  2022-03-06 15:20 [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch Geoffrey D. Bennett
  2022-03-06 15:21 ` [PATCH 1/2] ALSA: scarlett2: Split scarlett2_config_items[] into 3 sections Geoffrey D. Bennett
@ 2022-03-06 15:21 ` Geoffrey D. Bennett
  2022-03-08  9:06 ` [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: Geoffrey D. Bennett @ 2022-03-06 15:21 UTC (permalink / raw)
  To: alsa-devel, Takashi Iwai; +Cc: Hin-Tak Leung, Vladimir Sadovnikov

The Focusrite Scarlett Gen 2/3 interfaces with internal mixers have a
"standalone" mode. When the interface is not connected to a USB host
and standalone mode is enabled, the interface will pass audio as
previously configured. This patch adds an ALSA control to allow
enabling/disabling that mode.

Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
 sound/usb/mixer_scarlett_gen2.c | 97 ++++++++++++++++++++++++++++++---
 1 file changed, 90 insertions(+), 7 deletions(-)

diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
index 22e442208550..710586c8dedc 100644
--- a/sound/usb/mixer_scarlett_gen2.c
+++ b/sound/usb/mixer_scarlett_gen2.c
@@ -60,6 +60,7 @@
  *  - phantom power, direct monitor, speaker switching, and talkback
  *    controls
  *  - disable/enable MSD mode
+ *  - disable/enable standalone mode
  *
  * <ditaa>
  *    /--------------\    18chn            20chn     /--------------\
@@ -411,6 +412,7 @@ struct scarlett2_data {
 	u8 talkback_switch;
 	u8 talkback_map[SCARLETT2_OUTPUT_MIX_MAX];
 	u8 msd_switch;
+	u8 standalone_switch;
 	struct snd_kcontrol *sync_ctl;
 	struct snd_kcontrol *master_vol_ctl;
 	struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX];
@@ -936,13 +938,14 @@ enum {
 	SCARLETT2_CONFIG_PAD_SWITCH = 5,
 	SCARLETT2_CONFIG_MSD_SWITCH = 6,
 	SCARLETT2_CONFIG_AIR_SWITCH = 7,
-	SCARLETT2_CONFIG_PHANTOM_SWITCH = 8,
-	SCARLETT2_CONFIG_PHANTOM_PERSISTENCE = 9,
-	SCARLETT2_CONFIG_DIRECT_MONITOR = 10,
-	SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH = 11,
-	SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE = 12,
-	SCARLETT2_CONFIG_TALKBACK_MAP = 13,
-	SCARLETT2_CONFIG_COUNT = 14
+	SCARLETT2_CONFIG_STANDALONE_SWITCH = 8,
+	SCARLETT2_CONFIG_PHANTOM_SWITCH = 9,
+	SCARLETT2_CONFIG_PHANTOM_PERSISTENCE = 10,
+	SCARLETT2_CONFIG_DIRECT_MONITOR = 11,
+	SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH = 12,
+	SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE = 13,
+	SCARLETT2_CONFIG_TALKBACK_MAP = 14,
+	SCARLETT2_CONFIG_COUNT = 15
 };
 
 /* Location, size, and activation command number for the configuration
@@ -998,6 +1001,9 @@ static const struct scarlett2_config
 	[SCARLETT2_CONFIG_PAD_SWITCH] = {
 		.offset = 0x84, .size = 8, .activate = 8 },
 
+	[SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
+		.offset = 0x8d, .size = 8, .activate = 6 },
+
 /* Gen 3 devices: 4i4, 8i6, 18i8, 18i20 */
 }, {
 	[SCARLETT2_CONFIG_DIM_MUTE] = {
@@ -1021,6 +1027,9 @@ static const struct scarlett2_config
 	[SCARLETT2_CONFIG_AIR_SWITCH] = {
 		.offset = 0x8c, .size = 8, .activate = 8 },
 
+	[SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
+		.offset = 0x95, .size = 8, .activate = 6 },
+
 	[SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
 		.offset = 0x9c, .size = 1, .activate = 8 },
 
@@ -3502,6 +3511,69 @@ static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer)
 				     0, 1, "MSD Mode Switch", NULL);
 }
 
+/*** Standalone Control ***/
+
+static int scarlett2_standalone_ctl_get(struct snd_kcontrol *kctl,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct usb_mixer_elem_info *elem = kctl->private_data;
+	struct scarlett2_data *private = elem->head.mixer->private_data;
+
+	ucontrol->value.integer.value[0] = private->standalone_switch;
+	return 0;
+}
+
+static int scarlett2_standalone_ctl_put(struct snd_kcontrol *kctl,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct usb_mixer_elem_info *elem = kctl->private_data;
+	struct usb_mixer_interface *mixer = elem->head.mixer;
+	struct scarlett2_data *private = mixer->private_data;
+
+	int oval, val, err = 0;
+
+	mutex_lock(&private->data_mutex);
+
+	oval = private->standalone_switch;
+	val = !!ucontrol->value.integer.value[0];
+
+	if (oval == val)
+		goto unlock;
+
+	private->standalone_switch = val;
+
+	/* Send switch change to the device */
+	err = scarlett2_usb_set_config(mixer,
+				       SCARLETT2_CONFIG_STANDALONE_SWITCH,
+				       0, val);
+	if (err == 0)
+		err = 1;
+
+unlock:
+	mutex_unlock(&private->data_mutex);
+	return err;
+}
+
+static const struct snd_kcontrol_new scarlett2_standalone_ctl = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "",
+	.info = snd_ctl_boolean_mono_info,
+	.get  = scarlett2_standalone_ctl_get,
+	.put  = scarlett2_standalone_ctl_put,
+};
+
+static int scarlett2_add_standalone_ctl(struct usb_mixer_interface *mixer)
+{
+	struct scarlett2_data *private = mixer->private_data;
+
+	if (private->info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
+		return 0;
+
+	/* Add standalone control */
+	return scarlett2_add_new_ctl(mixer, &scarlett2_standalone_ctl,
+				     0, 1, "Standalone Switch", NULL);
+}
+
 /*** Cleanup/Suspend Callbacks ***/
 
 static void scarlett2_private_free(struct usb_mixer_interface *mixer)
@@ -3663,6 +3735,12 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
 	if (info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
 		return 0;
 
+	err = scarlett2_usb_get_config(
+		mixer, SCARLETT2_CONFIG_STANDALONE_SWITCH,
+		1, &private->standalone_switch);
+	if (err < 0)
+		return err;
+
 	err = scarlett2_update_sync(mixer);
 	if (err < 0)
 		return err;
@@ -3985,6 +4063,11 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
 	if (err < 0)
 		return err;
 
+	/* Create the standalone control */
+	err = scarlett2_add_standalone_ctl(mixer);
+	if (err < 0)
+		return err;
+
 	/* Set up the interrupt polling */
 	err = scarlett2_init_notify(mixer);
 	if (err < 0)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch
  2022-03-06 15:20 [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch Geoffrey D. Bennett
  2022-03-06 15:21 ` [PATCH 1/2] ALSA: scarlett2: Split scarlett2_config_items[] into 3 sections Geoffrey D. Bennett
  2022-03-06 15:21 ` [PATCH 2/2] ALSA: scarlett2: Add support for the internal "standalone" switch Geoffrey D. Bennett
@ 2022-03-08  9:06 ` Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: Takashi Iwai @ 2022-03-08  9:06 UTC (permalink / raw)
  To: Geoffrey D. Bennett; +Cc: Hin-Tak Leung, alsa-devel, Vladimir Sadovnikov

On Sun, 06 Mar 2022 16:20:40 +0100,
Geoffrey D. Bennett wrote:
> 
> Hi Takashi,
> 
> I discovered an internal "standalone" switch on all the Scarlett Gen
> 2/3 interfaces with internal mixers. After enabling this switch, the
> interface will act as a standalone mixer (according to its previous
> configuration) when not connected to a USB host. The interfaces come
> from the factory with the switch off, and the vendor driver enables it
> without question. This patch adds a new ALSA control to set the switch
> on or off.
> 
> This is the first configuration item that is common between the Gen 2
> and 3 interfaces but with a different offset, so the patch is in two
> parts. The first patch allows for the same configuration item to have
> a different offset between Gen 2/3 and the second patch adds the new
> switch.
> 
> Regards,
> Geoffrey.
> 
> Geoffrey D. Bennett (2):
>   ALSA: scarlett2: Split scarlett2_config_items[] into 3 sections
>   ALSA: scarlett2: Add support for the internal "standalone" switch

Thanks, applied both patches now.


Takashi

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-03-08  9:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-06 15:20 [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch Geoffrey D. Bennett
2022-03-06 15:21 ` [PATCH 1/2] ALSA: scarlett2: Split scarlett2_config_items[] into 3 sections Geoffrey D. Bennett
2022-03-06 15:21 ` [PATCH 2/2] ALSA: scarlett2: Add support for the internal "standalone" switch Geoffrey D. Bennett
2022-03-08  9:06 ` [PATCH 0/2] ALSA: scarlett2: Add "Standalone" switch Takashi Iwai

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.