diff mbox series

[04/20] ALSA: scarlett2: Add support for Gen 4 style parameters

Message ID 1624e6d8a0c629c3bdfe53825b16e8b589724fc4.1703612638.git.g@b4.vu (mailing list archive)
State Accepted
Commit 4fa07ff7b625e5578dd974d5c43d701cb3624d84
Headers show
Series ALSA: scarlett2: Add support for Scarlett 4th Gen | expand

Commit Message

Geoffrey D. Bennett Dec. 26, 2023, 6:06 p.m. UTC
Writing Scarlett Gen 4 parameters differs from Gen 2 and Gen 3:
- the values are written into a shared write location
- the values are only byte-sized
- the read locations now extend beyond 0xFF
- a separate NVRAM save step is no longer required

This patch implements that alternate write style, triggered by setting
the config item size field to zero.

The write address is specified through a new config set field
gen4_write_addr.

Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
 sound/usb/mixer_scarlett2.c | 53 +++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 5c5198bb224a..09cd09799588 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -320,16 +320,21 @@  enum {
 };
 
 /* Location, size, and activation command number for the configuration
- * parameters. Size is in bits and may be 1, 8, or 16.
+ * parameters. Size is in bits and may be 0, 1, 8, or 16.
+ *
+ * A size of 0 indicates that the parameter is a byte-sized Scarlett
+ * Gen 4 configuration which is written through the gen4_write_addr
+ * location (but still read through the given offset location).
  */
 struct scarlett2_config {
-	u8 offset;
+	u16 offset;
 	u8 size;
 	u8 activate;
 };
 
 struct scarlett2_config_set {
 	const struct scarlett2_notification *notifications;
+	u16 gen4_write_addr;
 	const struct scarlett2_config items[SCARLETT2_CONFIG_COUNT];
 };
 
@@ -1612,9 +1617,12 @@  static int scarlett2_usb_get_config(
 	if (!config_item->offset)
 		return -EFAULT;
 
+	/* Gen 4 style parameters are always 1 byte */
+	size = config_item->size ? config_item->size : 8;
+
 	/* For byte-sized parameters, retrieve directly into buf */
-	if (config_item->size >= 8) {
-		size = config_item->size / 8 * count;
+	if (size >= 8) {
+		size = size / 8 * count;
 		err = scarlett2_usb_get(mixer, config_item->offset, buf, size);
 		if (err < 0)
 			return err;
@@ -1684,8 +1692,9 @@  static int scarlett2_usb_set_config(
 	int config_item_num, int index, int value)
 {
 	struct scarlett2_data *private = mixer->private_data;
+	const struct scarlett2_config_set *config_set = private->config_set;
 	const struct scarlett2_config *config_item =
-		&private->config_set->items[config_item_num];
+		&config_set->items[config_item_num];
 	int offset, size;
 	int err;
 
@@ -1695,6 +1704,36 @@  static int scarlett2_usb_set_config(
 	if (!config_item->offset)
 		return -EFAULT;
 
+	/* Gen 4 style writes are selected with size = 0;
+	 * these are only byte-sized values written through a shared
+	 * location, different to the read address
+	 */
+	if (!config_item->size) {
+		if (!config_set->gen4_write_addr)
+			return -EFAULT;
+
+		/* Place index in gen4_write_addr + 1 */
+		err = scarlett2_usb_set_data(
+			mixer, config_set->gen4_write_addr + 1, 1, index);
+		if (err < 0)
+			return err;
+
+		/* Place value in gen4_write_addr */
+		err = scarlett2_usb_set_data(
+			mixer, config_set->gen4_write_addr, 1, value);
+		if (err < 0)
+			return err;
+
+		/* Request the interface do the write */
+		return scarlett2_usb_activate_config(
+			mixer, config_item->activate);
+	}
+
+	/* Not-Gen 4 style needs NVRAM save, supports
+	 * bit-modification, and writing is done to the same place
+	 * that the value can be read from
+	 */
+
 	/* Cancel any pending NVRAM save */
 	cancel_delayed_work_sync(&private->work);
 
@@ -1736,6 +1775,10 @@  static int scarlett2_usb_set_config(
 	if (err < 0)
 		return err;
 
+	/* Gen 2 style writes to Gen 4 devices don't need saving */
+	if (config_set->gen4_write_addr)
+		return 0;
+
 	/* Schedule the change to be written to NVRAM */
 	if (config_item->activate != SCARLETT2_USB_CONFIG_SAVE)
 		schedule_delayed_work(&private->work, msecs_to_jiffies(2000));