From patchwork Mon Jun 21 18:09:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335359 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96138C4743C for ; Mon, 21 Jun 2021 18:11:02 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B3CBC6115B for ; Mon, 21 Jun 2021 18:11:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B3CBC6115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 2452116A2; Mon, 21 Jun 2021 20:10:10 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 2452116A2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299060; bh=wPFFXdYca3FG49efhTEHUy21h9Y6mhP2zcat9zpEj/8=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=ifDvYZ4GxeV4rgab0UT6vzd1VElKxirHZUx7yyUQ/9tSgzWxVIXEZxd8PYksRjYrT cbVMK8oIGjqKO2rAOKnxiPglHU7eVAKX/9ZeU+5R8SyznlAjhBMDq0MrmPC28XLZAC D9L6zVRfup/7q1UhnoTotpCjY4ZdPFcvpi2ANqdE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 9E7FBF804D9; Mon, 21 Jun 2021 20:09:22 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 05D2EF804D9; Mon, 21 Jun 2021 20:09:21 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 5F994F80137 for ; Mon, 21 Jun 2021 20:09:14 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 5F994F80137 Received: by m.b4.vu (Postfix, from userid 1000) id CDA9161E2871; Tue, 22 Jun 2021 03:39:06 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:06 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 01/31] ALSA: usb-audio: scarlett2: Add usb_tx/rx functions Message-ID: <720d1d6f227fc8f5d7d6191a8de62db796940235.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Pull out snd_usb_ctl_msg() calls from scarlett2_usb() and put into scarlett2_usb_tx() and scarlett2_usb_rx() functions. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 44 +++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 2e1937b072ee..6b77582d8e3d 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -453,8 +453,8 @@ static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, #define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 /* Commands for sending/receiving requests/responses */ -#define SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ 2 -#define SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP 3 +#define SCARLETT2_USB_CMD_REQ 2 +#define SCARLETT2_USB_CMD_RESP 3 #define SCARLETT2_USB_INIT_SEQ 0x00000000 #define SCARLETT2_USB_GET_METER 0x00001001 @@ -576,12 +576,31 @@ static void scarlett2_fill_request_header(struct scarlett2_data *private, req->pad = 0; } +static int scarlett2_usb_tx(struct usb_device *dev, int interface, + void *buf, u16 size) +{ + return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + SCARLETT2_USB_CMD_REQ, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + 0, interface, buf, size); +} + +static int scarlett2_usb_rx(struct usb_device *dev, int interface, + u32 usb_req, void *buf, u16 size) +{ + return snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), + usb_req, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + 0, interface, buf, size); +} + /* Send a proprietary format request to the Scarlett interface */ static int scarlett2_usb( struct usb_mixer_interface *mixer, u32 cmd, void *req_data, u16 req_size, void *resp_data, u16 resp_size) { struct scarlett2_data *private = mixer->private_data; + struct usb_device *dev = mixer->chip->dev; u16 req_buf_size = sizeof(struct scarlett2_usb_packet) + req_size; u16 resp_buf_size = sizeof(struct scarlett2_usb_packet) + resp_size; struct scarlett2_usb_packet *req, *resp = NULL; @@ -608,14 +627,8 @@ static int scarlett2_usb( if (req_size) memcpy(req->data, req_data, req_size); - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_sndctrlpipe(mixer->chip->dev, 0), - SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - 0, - private->bInterfaceNumber, - req, - req_buf_size); + err = scarlett2_usb_tx(dev, private->bInterfaceNumber, + req, req_buf_size); if (err != req_buf_size) { usb_audio_err( @@ -628,14 +641,9 @@ static int scarlett2_usb( /* send a second message to get the response */ - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_rcvctrlpipe(mixer->chip->dev, 0), - SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - 0, - private->bInterfaceNumber, - resp, - resp_buf_size); + err = scarlett2_usb_rx(dev, private->bInterfaceNumber, + SCARLETT2_USB_CMD_RESP, + resp, resp_buf_size); /* validate the response */ From patchwork Mon Jun 21 18:09:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335361 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3EE03C4743C for ; Mon, 21 Jun 2021 18:11:10 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 93CB56100B for ; Mon, 21 Jun 2021 18:11:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 93CB56100B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 27485168E; Mon, 21 Jun 2021 20:10:18 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 27485168E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299068; bh=8jm3sJdL9sFMHzxRHU7oAIRbMGyqMO7x6C+0pf5xeFs=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=QDW/Y5QS+cd1sVRjb34p4EGeZS8K2ZCqsIde8JL21XwbrANTMYBPIr+R8rcOrq3NM OiOuFNkHVROUDWkReJlE6VXagdFGZXKQMt5no1cdtdlnP3rX6pgax6v2Gy+7enH+0q reFa+vygtLcy8IkdFk3LUf0eYqObnrTA/w+vS3Gk= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id BFAA8F804E0; Mon, 21 Jun 2021 20:09:24 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7463BF804E0; Mon, 21 Jun 2021 20:09:23 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 6860FF80245 for ; Mon, 21 Jun 2021 20:09:16 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 6860FF80245 Received: by m.b4.vu (Postfix, from userid 1000) id E044A61E287C; Tue, 22 Jun 2021 03:39:13 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:13 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 02/31] ALSA: usb-audio: scarlett2: Update initialisation sequence Message-ID: <6e5c4fedb74b813872f6a4b7fba30b6c471fa63a.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The old initialisation code only works with Gen 2 devices. Replace it with an initialisation sequence that works on both Gen 2 and Gen 3 devices. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 56 ++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 6b77582d8e3d..ed89e28548c8 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -453,10 +453,12 @@ static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, #define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 /* Commands for sending/receiving requests/responses */ +#define SCARLETT2_USB_CMD_INIT 0 #define SCARLETT2_USB_CMD_REQ 2 #define SCARLETT2_USB_CMD_RESP 3 -#define SCARLETT2_USB_INIT_SEQ 0x00000000 +#define SCARLETT2_USB_INIT_1 0x00000000 +#define SCARLETT2_USB_INIT_2 0x00000002 #define SCARLETT2_USB_GET_METER 0x00001001 #define SCARLETT2_USB_GET_MIX 0x00002001 #define SCARLETT2_USB_SET_MIX 0x00002002 @@ -650,14 +652,19 @@ static int scarlett2_usb( if (err != resp_buf_size) { usb_audio_err( mixer->chip, - "Scarlett Gen 2 USB response result cmd %x was %d\n", - cmd, err); + "Scarlett Gen 2 USB response result cmd %x was %d " + "expected %d\n", + cmd, err, resp_buf_size); err = -EINVAL; goto unlock; } + /* cmd/seq/size should match except when initialising + * seq sent = 1, response = 0 + */ if (resp->cmd != req->cmd || - resp->seq != req->seq || + (resp->seq != req->seq && + (le16_to_cpu(req->seq) != 1 || resp->seq != 0)) || resp_size != le16_to_cpu(resp->size) || resp->error || resp->pad) { @@ -675,7 +682,7 @@ static int scarlett2_usb( goto unlock; } - if (resp_size > 0) + if (resp_data && resp_size > 0) memcpy(resp_data, resp->data, resp_size); unlock: @@ -1924,13 +1931,12 @@ static int scarlett2_find_fc_interface(struct usb_device *dev, return -EINVAL; } -/* Initialise private data, sequence number, and get the USB data */ +/* Initialise private data */ static int scarlett2_init_private(struct usb_mixer_interface *mixer, const struct scarlett2_device_info *info) { struct scarlett2_data *private = kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL); - int err; if (!private) return -ENOMEM; @@ -1948,12 +1954,35 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer, private->scarlett2_seq = 0; private->mixer = mixer; - err = scarlett2_find_fc_interface(mixer->chip->dev, private); + 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 buf[24]; + 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, buf, sizeof(buf)); if (err < 0) return err; - /* Initialise the sequence number used for the proprietary commands */ - return scarlett2_usb(mixer, SCARLETT2_USB_INIT_SEQ, NULL, 0, NULL, 0); + /* 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; + return scarlett2_usb(mixer, SCARLETT2_USB_INIT_2, NULL, 0, NULL, 84); } /* Read configuration from the interface on start */ @@ -2128,11 +2157,16 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, { int err; - /* Initialise private data, sequence number, and get the USB data */ + /* Initialise private data */ err = scarlett2_init_private(mixer, info); if (err < 0) return err; + /* Send proprietary USB initialisation sequence */ + err = scarlett2_usb_init(mixer); + if (err < 0) + return err; + /* Read volume levels and controls from the interface */ err = scarlett2_read_configs(mixer); if (err < 0) From patchwork Mon Jun 21 18:09:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335365 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8049CC48BC2 for ; Mon, 21 Jun 2021 18:11:54 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0389B61026 for ; Mon, 21 Jun 2021 18:11:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0389B61026 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 7CB7E169E; Mon, 21 Jun 2021 20:11:02 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 7CB7E169E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299112; bh=bJRpZyFmQkLO5CmqXWckuLYfPZKyktg3VI/MnaB1LYo=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Gith3iSTS7MDLEvDOQKb1yM563kdP+nSGwjQ2kmVzTaA86ngU4zwbiNyApMb4FoDH BnSehk0Hb+wV9FjqCJ+mOz5gffQCVVKFco6JLGd44RJPijwMYjYC+aD+QhkhaAKatx Jz15bru+IRDjLSzm248run3669lQ3tHDa5MI6YS0= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id EB7F6F804EB; Mon, 21 Jun 2021 20:09:28 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id E00CAF804E4; Mon, 21 Jun 2021 20:09:26 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 8794EF80111 for ; Mon, 21 Jun 2021 20:09:20 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 8794EF80111 Received: by m.b4.vu (Postfix, from userid 1000) id 111A361E2871; Tue, 22 Jun 2021 03:39:18 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:18 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 03/31] ALSA: usb-audio: scarlett2: Fix 6i6 Gen 2 line out descriptions Message-ID: <205e5e5348f08ded0cc4da5446f604d4b91db5bf.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" There are two headphone outputs, and they map to the four analogue outputs. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index ed89e28548c8..0b1967d93486 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -263,10 +263,10 @@ static const struct scarlett2_device_info s6i6_gen2_info = { .pad_input_count = 2, .line_out_descrs = { - "Monitor L", - "Monitor R", - "Headphones L", - "Headphones R", + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", }, .ports = { From patchwork Mon Jun 21 18:09:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335363 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1F100C4743C for ; Mon, 21 Jun 2021 18:11:41 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 312106100B for ; Mon, 21 Jun 2021 18:11:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 312106100B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id A4D3D1697; Mon, 21 Jun 2021 20:10:48 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A4D3D1697 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299098; bh=Ko1VjfiouISTeJFMoiQMZVjp8g5mp/eGveuhLu/N5e4=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=q9F/8i/CZodGDWE0YRCXIpAxQX24spjvejyoWtBBmQI2uBCw08JGT18Id/YFTA/Ia BDRH748dY7wgHWKEYhyuBmjcz+fEcXRrWA2NPA7XrnH0yWAiiUE9ggBHEBSpa2u5KL 0YymQia7c+6EQQYEgtr37EGMwnMMMx/Lb4OsLa6A= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 53AA1F804E4; Mon, 21 Jun 2021 20:09:28 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 06B1BF804E5; Mon, 21 Jun 2021 20:09:26 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 518F5F804DA for ; Mon, 21 Jun 2021 20:09:23 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 518F5F804DA Received: by m.b4.vu (Postfix, from userid 1000) id D617961E286F; Tue, 22 Jun 2021 03:39:20 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:20 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 04/31] ALSA: usb-audio: scarlett2: Always enable interrupt polling Message-ID: <8f49a6b9a9805ee0db221706193b7bb43b7fff75.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Always enable interrupt polling as every model has some sort of status to report. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 0b1967d93486..620f1e814f0d 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -2059,11 +2059,16 @@ static void scarlett2_notify_monitor( struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + const struct scarlett2_device_info *info = private->info; + const struct scarlett2_ports *ports = info->ports; int num_line_out = ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; int i; + /* if line_out_hw_vol is 0, there are no controls to update */ + if (!info->line_out_hw_vol) + return; + private->vol_updated = 1; snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, @@ -2197,12 +2202,10 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, if (err < 0) return err; - /* Set up the interrupt polling if there are hardware buttons */ - if (info->line_out_hw_vol) { - err = scarlett2_init_notify(mixer); - if (err < 0) - return err; - } + /* Set up the interrupt polling */ + err = scarlett2_init_notify(mixer); + if (err < 0) + return err; return 0; } From patchwork Mon Jun 21 18:09:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335367 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B2557C4743C for ; Mon, 21 Jun 2021 18:12:20 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3B2BD6100B for ; Mon, 21 Jun 2021 18:12:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3B2BD6100B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id D0FE416A0; Mon, 21 Jun 2021 20:11:28 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D0FE416A0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299138; bh=P97SMPViDKVEN44nSuPOSgzrarM9rZ+TQ/Wt8IWnaqs=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=UEr9t+/Yd5EMjtzly9ropg44nfnWHdemh4kdrS3YKZkBvMNt2KUVAyQ7WKEaRxz5u kU0jcrtC3eWpDy9QQB9wpVO++1aE1wkWdjWDFVM6DpbqGYn5fJcYgWqD5ShPCNbMY7 EcQ8pTrz0agpyaLG9gIFayzJUV9HzuKQveOHoECI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 89FC2F804F1; Mon, 21 Jun 2021 20:09:32 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id AC7DFF804F2; Mon, 21 Jun 2021 20:09:29 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 93132F804DA for ; Mon, 21 Jun 2021 20:09:26 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 93132F804DA Received: by m.b4.vu (Postfix, from userid 1000) id 1E5B961E287F; Tue, 22 Jun 2021 03:39:24 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:24 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 05/31] ALSA: usb-audio: scarlett2: Add "Sync Status" control Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add "Sync Status" control to display the sync locked/unlocked status. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 101 +++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 620f1e814f0d..4c2ae81f94a8 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -237,13 +237,16 @@ struct scarlett2_data { int num_mux_srcs; int num_mux_dsts; u16 scarlett2_seq; + u8 sync_updated; u8 vol_updated; + u8 sync; u8 master_vol; u8 vol[SCARLETT2_ANALOGUE_MAX]; u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX]; u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; + struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX]; struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT]; @@ -448,7 +451,8 @@ static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, /*** USB Interactions ***/ -/* Interrupt flags for dim/mute button and monitor changes */ +/* Notifications from the interface */ +#define SCARLETT2_USB_NOTIFY_SYNC 0x00000008 #define SCARLETT2_USB_NOTIFY_DIM_MUTE 0x00200000 #define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 @@ -464,6 +468,7 @@ static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, #define SCARLETT2_USB_SET_MIX 0x00002002 #define SCARLETT2_USB_GET_MUX 0x00003001 #define SCARLETT2_USB_SET_MUX 0x00003002 +#define SCARLETT2_USB_GET_SYNC 0x00006004 #define SCARLETT2_USB_GET_DATA 0x00800000 #define SCARLETT2_USB_SET_DATA 0x00800001 #define SCARLETT2_USB_DATA_CMD 0x00800002 @@ -784,6 +789,23 @@ static int scarlett2_usb_get_config( return scarlett2_usb_get(mixer, config_item->offset, buf, size); } +/* Send a USB message to get sync status; result placed in *sync */ +static int scarlett2_usb_get_sync_status( + struct usb_mixer_interface *mixer, + u8 *sync) +{ + __le32 data; + int err; + + err = scarlett2_usb(mixer, SCARLETT2_USB_GET_SYNC, + NULL, 0, &data, sizeof(data)); + if (err < 0) + return err; + + *sync = !!data; + return 0; +} + /* Send a USB message to get volume status; result placed in *buf */ static int scarlett2_usb_get_volume_status( struct usb_mixer_interface *mixer, @@ -1109,6 +1131,60 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer, return 0; } +/*** Sync Control ***/ + +/* Update sync control after receiving notification that the status + * has changed + */ +static int scarlett2_update_sync(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + + private->sync_updated = 0; + return scarlett2_usb_get_sync_status(mixer, &private->sync); +} + +static int scarlett2_sync_ctl_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + static const char *texts[2] = { + "Unlocked", "Locked" + }; + return snd_ctl_enum_info(uinfo, 1, 2, texts); +} + +static int scarlett2_sync_ctl_get(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; + + mutex_lock(&private->data_mutex); + if (private->sync_updated) + scarlett2_update_sync(mixer); + ucontrol->value.enumerated.item[0] = private->sync; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static const struct snd_kcontrol_new scarlett2_sync_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .name = "", + .info = scarlett2_sync_ctl_info, + .get = scarlett2_sync_ctl_get +}; + +static int scarlett2_add_sync_ctl(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + + return scarlett2_add_new_ctl(mixer, &scarlett2_sync_ctl, + 0, 1, "Sync Status", &private->sync_ctl); +} + /*** Analogue Line Out Volume Controls ***/ /* Update hardware volume controls after receiving notification that @@ -2018,6 +2094,10 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) return err; } + err = scarlett2_update_sync(mixer); + if (err < 0) + return err; + err = scarlett2_usb_get_volume_status(mixer, &volume_status); if (err < 0) return err; @@ -2054,6 +2134,18 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) return scarlett2_usb_get_mux(mixer); } +/* Notify on sync change */ +static void scarlett2_notify_sync( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + + private->sync_updated = 1; + + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->sync_ctl->id); +} + /* Notify on monitor change */ static void scarlett2_notify_monitor( struct usb_mixer_interface *mixer) @@ -2112,6 +2204,8 @@ static void scarlett2_notify(struct urb *urb) goto requeue; data = le32_to_cpu(*(__le32 *)urb->transfer_buffer); + if (data & SCARLETT2_USB_NOTIFY_SYNC) + scarlett2_notify_sync(mixer); if (data & SCARLETT2_USB_NOTIFY_MONITOR) scarlett2_notify_monitor(mixer); if (data & SCARLETT2_USB_NOTIFY_DIM_MUTE) @@ -2202,6 +2296,11 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, if (err < 0) return err; + /* Create the sync control */ + err = scarlett2_add_sync_ctl(mixer); + if (err < 0) + return err; + /* Set up the interrupt polling */ err = scarlett2_init_notify(mixer); if (err < 0) From patchwork Mon Jun 21 18:09:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335379 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E4E4C4743C for ; Mon, 21 Jun 2021 18:12:42 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C4D966115B for ; Mon, 21 Jun 2021 18:12:41 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C4D966115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 61552168E; Mon, 21 Jun 2021 20:11:50 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 61552168E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299160; bh=2NWQdEnBu1Z5wmVVzxXBr7fWOuY3ZhP69ePPnK/7j08=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=dAZ8gK7h7Z55dAEBXb+FUFepgy/ssHNFm/ONDhKptwqwNSU1V+wvFFIpPyuxomuOg /qHtWbAdx0tOH1MuUetF8+qtzB2GnPMX7uib77j919yy7LERJWvr7uKojK+ZEA4hAV AjdZW6JyOXnj0FqxjmCJHDlcDzmIJGtuzKoVZDec= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 1A7ECF804FC; Mon, 21 Jun 2021 20:09:36 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id D2FDCF804F2; Mon, 21 Jun 2021 20:09:31 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 591A3F804E7 for ; Mon, 21 Jun 2021 20:09:29 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 591A3F804E7 Received: by m.b4.vu (Postfix, from userid 1000) id DB0CE61E5F00; Tue, 22 Jun 2021 03:39:26 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:26 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 06/31] ALSA: usb-audio: scarlett2: Merge common line in capture strings Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Use a common sprintf() format for the mixer element names generated in scarlett2_add_line_in_ctls() in preparation for more of them. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 4c2ae81f94a8..c401b7d56408 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -1660,10 +1660,11 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) const struct scarlett2_device_info *info = private->info; int err, i; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + const char *fmt = "Line In %d %s Capture %s"; /* Add input level (line/inst) controls */ for (i = 0; i < info->level_input_count; i++) { - snprintf(s, sizeof(s), "Line In %d Level Capture Enum", i + 1); + snprintf(s, sizeof(s), fmt, i + 1, "Level", "Enum"); err = scarlett2_add_new_ctl(mixer, &scarlett2_level_enum_ctl, i, 1, s, NULL); if (err < 0) @@ -1672,7 +1673,7 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) /* Add input pad controls */ for (i = 0; i < info->pad_input_count; i++) { - snprintf(s, sizeof(s), "Line In %d Pad Capture Switch", i + 1); + snprintf(s, sizeof(s), fmt, i + 1, "Pad", "Switch"); err = scarlett2_add_new_ctl(mixer, &scarlett2_pad_ctl, i, 1, s, NULL); if (err < 0) From patchwork Mon Jun 21 18:09:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335381 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AFB3AC4743C for ; Mon, 21 Jun 2021 18:12:57 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 249A56100B for ; Mon, 21 Jun 2021 18:12:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 249A56100B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id B82701660; Mon, 21 Jun 2021 20:12:05 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz B82701660 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299175; bh=WqQ6pXK+BFyXZEVHYpB+27XWUHVs7abhBKg8jXqk6Gg=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=BKPDVlkK+VavT5NJL//dwb/GIdtwh97yuCNA/fpq+XmvlIEOtO7adHuSVSGObVhGc zm+Sb95YFICxXy+LYAddDcqcY+lBkeEJjwwTT3POHq3AcRNExi58TnAGXOGRnP9D6l iyrxN10GlfUFE8AwO7o7tS8O7AyvtoePlGRcfvKI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B6064F80506; Mon, 21 Jun 2021 20:09:36 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 345F6F804FC; Mon, 21 Jun 2021 20:09:34 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id A729BF804E7 for ; Mon, 21 Jun 2021 20:09:31 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz A729BF804E7 Received: by m.b4.vu (Postfix, from userid 1000) id 3476361E287D; Tue, 22 Jun 2021 03:39:29 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:29 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 07/31] ALSA: usb-audio: scarlett2: Reformat scarlett2_config_items[] Message-ID: <512d14eeb3571a266810c954d0f83140a3af7afc.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Use designated initializers and merge lines in preparation for more configuration items coming soon. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 40 +++++++++------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index c401b7d56408..4a36181e61ab 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -523,40 +523,20 @@ struct scarlett2_config { static const struct scarlett2_config scarlett2_config_items[SCARLETT2_CONFIG_COUNT] = { - /* Dim/Mute Buttons */ - { - .offset = 0x31, - .size = 1, - .activate = 2 - }, + [SCARLETT2_CONFIG_DIM_MUTE] = { + .offset = 0x31, .size = 1, .activate = 2 }, - /* Line Out Volume */ - { - .offset = 0x34, - .size = 2, - .activate = 1 - }, + [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = { + .offset = 0x34, .size = 2, .activate = 1 }, - /* SW/HW Volume Switch */ - { - .offset = 0x66, - .size = 1, - .activate = 3 - }, + [SCARLETT2_CONFIG_SW_HW_SWITCH] = { + .offset = 0x66, .size = 1, .activate = 3 }, - /* Level Switch */ - { - .offset = 0x7c, - .size = 1, - .activate = 7 - }, + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { + .offset = 0x7c, .size = 1, .activate = 7 }, - /* Pad Switch */ - { - .offset = 0x84, - .size = 1, - .activate = 8 - } + [SCARLETT2_CONFIG_PAD_SWITCH] = { + .offset = 0x84, .size = 1, .activate = 8 }, }; /* proprietary request/response format */ From patchwork Mon Jun 21 18:09:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335383 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E383AC4743C for ; Mon, 21 Jun 2021 18:13:33 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6D7F8611BD for ; Mon, 21 Jun 2021 18:13:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6D7F8611BD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 12BB716B4; Mon, 21 Jun 2021 20:12:42 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 12BB716B4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299212; bh=Tf5+DpK3oZ1NE6PDaXsq41h8dJR4xen/+ZWIgzdsPT0=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=FxATUaJZpKQxRKWsnEa6kcDd12eXfurTusuy8vHcIRtKVijUFD+VMuud0u/XhA0zZ JJWRH02a8buX/yDeEixDTEalGmiD3F72I3wY+a9cd1NxTXdMFpYfeix6SIeC1uowgk j2C7dqxDWPfpTOl2DbhPTSYn01uRZi/tIZFTno7o= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id E59C8F80518; Mon, 21 Jun 2021 20:09:41 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 12FF3F8050F; Mon, 21 Jun 2021 20:09:37 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 0D88DF804F2 for ; Mon, 21 Jun 2021 20:09:34 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 0D88DF804F2 Received: by m.b4.vu (Postfix, from userid 1000) id 9000F61E5F01; Tue, 22 Jun 2021 03:39:31 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:31 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 08/31] ALSA: usb-audio: scarlett2: Improve device info lookup Message-ID: <474c408c29fb280a611e47e49e59ca2fb9810d27.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add the USB device ID to the scarlett2_device_info struct so that the switch statement which finds the appropriate struct can be replaced with a loop that looks through an array of pointers to those structs. Suggested-by: Vladimir Sadovnikov Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 37 ++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 4a36181e61ab..481ebdd1a0df 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -217,6 +217,7 @@ struct scarlett2_ports { }; struct scarlett2_device_info { + u32 usb_id; /* USB device identifier */ u8 line_out_hw_vol; /* line out hw volume is sw controlled */ u8 level_input_count; /* inputs with level selectable */ u8 pad_input_count; /* inputs with pad selectable */ @@ -257,6 +258,8 @@ struct scarlett2_data { /*** Model-specific data ***/ static const struct scarlett2_device_info s6i6_gen2_info = { + .usb_id = USB_ID(0x1235, 0x8203), + /* The first two analogue inputs can be switched between line * and instrument levels. */ @@ -310,6 +313,8 @@ static const struct scarlett2_device_info s6i6_gen2_info = { }; static const struct scarlett2_device_info s18i8_gen2_info = { + .usb_id = USB_ID(0x1235, 0x8204), + /* The first two analogue inputs can be switched between line * and instrument levels. */ @@ -371,6 +376,8 @@ static const struct scarlett2_device_info s18i8_gen2_info = { }; static const struct scarlett2_device_info s18i20_gen2_info = { + .usb_id = USB_ID(0x1235, 0x8201), + /* The analogue line outputs on the 18i20 can be switched * between software and hardware volume control */ @@ -437,6 +444,16 @@ static const struct scarlett2_device_info s18i20_gen2_info = { }, }; +static const struct scarlett2_device_info *scarlett2_devices[] = { + /* Supported Gen 2 devices */ + &s6i6_gen2_info, + &s18i8_gen2_info, + &s18i20_gen2_info, + + /* End of list */ + NULL +}; + /* get the starting port index number for a given port type/direction */ static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, int direction, int port_type) @@ -2293,26 +2310,18 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer) { struct snd_usb_audio *chip = mixer->chip; - const struct scarlett2_device_info *info; + const struct scarlett2_device_info **info = scarlett2_devices; int err; /* only use UAC_VERSION_2 */ if (!mixer->protocol) return 0; - switch (chip->usb_id) { - case USB_ID(0x1235, 0x8203): - info = &s6i6_gen2_info; - break; - case USB_ID(0x1235, 0x8204): - info = &s18i8_gen2_info; - break; - case USB_ID(0x1235, 0x8201): - info = &s18i20_gen2_info; - break; - default: /* device not (yet) supported */ + /* find device in scarlett2_devices */ + while (*info && (*info)->usb_id != chip->usb_id) + info++; + if (!*info) return -EINVAL; - } if (!(chip->setup & SCARLETT2_ENABLE)) { usb_audio_info(chip, @@ -2329,7 +2338,7 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer) "Focusrite Scarlett Gen 2 Mixer Driver enabled pid=0x%04x", USB_ID_PRODUCT(chip->usb_id)); - err = snd_scarlett_gen2_controls_create(mixer, info); + err = snd_scarlett_gen2_controls_create(mixer, *info); if (err < 0) usb_audio_err(mixer->chip, "Error initialising Scarlett Mixer Driver: %d", From patchwork Mon Jun 21 18:09:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335385 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7CB68C4743C for ; Mon, 21 Jun 2021 18:13:50 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 097CB6115B for ; Mon, 21 Jun 2021 18:13:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 097CB6115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id A348E16BB; Mon, 21 Jun 2021 20:12:58 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A348E16BB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299228; bh=pM4smZkk7jxPMmhmAWpp27oEyWu3lDjyGnlsW2a14F4=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=gaPP0AlB/IOKkZxsjDQVHQ7gHJ+jL57wDjAjJGIFyPvw2Bkxy7rt84GakUG7kZWyr fntAuKviwXBLF3Gca1Xcbms8pG4yFy7eArX6ES+PlaYOJmj23Yp9HPx6fs9cLinGuS SGEP+ZFtLDi3AVIPcAVaEXad70yIl2q7b4VLB/98= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 9F2A7F8051D; Mon, 21 Jun 2021 20:09:42 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id BD8C0F80516; Mon, 21 Jun 2021 20:09:38 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 38229F80507 for ; Mon, 21 Jun 2021 20:09:36 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 38229F80507 Received: by m.b4.vu (Postfix, from userid 1000) id BCBD461E2871; Tue, 22 Jun 2021 03:39:33 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:33 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 09/31] ALSA: usb-audio: scarlett2: Move info lookup out of init function Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The info variable is not used by snd_scarlett_gen2_init() except to pass it to snd_scarlett_gen2_controls_create(), so move the lookup into that function. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 481ebdd1a0df..5cc4296944f5 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -2249,13 +2249,19 @@ static int scarlett2_init_notify(struct usb_mixer_interface *mixer) return usb_submit_urb(mixer->urb, GFP_KERNEL); } -static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, - const struct scarlett2_device_info *info) +static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer) { + const struct scarlett2_device_info **info = scarlett2_devices; int err; + /* Find device in scarlett2_devices */ + while (*info && (*info)->usb_id != mixer->chip->usb_id) + info++; + if (!*info) + return -EINVAL; + /* Initialise private data */ - err = scarlett2_init_private(mixer, info); + err = scarlett2_init_private(mixer, *info); if (err < 0) return err; @@ -2310,19 +2316,12 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer) { struct snd_usb_audio *chip = mixer->chip; - const struct scarlett2_device_info **info = scarlett2_devices; int err; /* only use UAC_VERSION_2 */ if (!mixer->protocol) return 0; - /* find device in scarlett2_devices */ - while (*info && (*info)->usb_id != chip->usb_id) - info++; - if (!*info) - return -EINVAL; - if (!(chip->setup & SCARLETT2_ENABLE)) { usb_audio_info(chip, "Focusrite Scarlett Gen 2 Mixer Driver disabled; " @@ -2338,7 +2337,7 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer) "Focusrite Scarlett Gen 2 Mixer Driver enabled pid=0x%04x", USB_ID_PRODUCT(chip->usb_id)); - err = snd_scarlett_gen2_controls_create(mixer, *info); + err = snd_scarlett_gen2_controls_create(mixer); if (err < 0) usb_audio_err(mixer->chip, "Error initialising Scarlett Mixer Driver: %d", From patchwork Mon Jun 21 18:09:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335387 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 315F2C48BE5 for ; Mon, 21 Jun 2021 18:14:13 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A5E806115B for ; Mon, 21 Jun 2021 18:14:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A5E806115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 43F3316CC; Mon, 21 Jun 2021 20:13:21 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 43F3316CC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299251; bh=bo8UWv1o7PXNmZigW5otDOyN8WVqD1Gwy3yAQcAcTL8=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Ur6tmQWThtUDlOelgKIhOU0VP0q7vR3ScnXDoYqQMFsYn1m+RTqNjRBhovK9q7acg nXRrBalE2hbXlD3/G4FuiSghnaTRGSfyAy8m/IG6V+72fJmZzp4UhXDC58wubd/0/f LEClYx9ecNaO1H1FuTdNFcLj6FtR1R0aNaTonGa4= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id D0F5CF80524; Mon, 21 Jun 2021 20:09:43 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id D20D7F80519; Mon, 21 Jun 2021 20:09:40 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 252A1F80510 for ; Mon, 21 Jun 2021 20:09:38 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 252A1F80510 Received: by m.b4.vu (Postfix, from userid 1000) id AB4EC61E287C; Tue, 22 Jun 2021 03:39:35 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:35 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 10/31] ALSA: usb-audio: scarlett2: Remove repeated device info comments Message-ID: <3486e4d38973333d4ec38f32578c16a9f97bf6c8.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Document the fields of struct scarlett2_device_info in the definition of the struct, not in each instantiation. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 5cc4296944f5..ded99baa92de 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -218,10 +218,24 @@ struct scarlett2_ports { struct scarlett2_device_info { u32 usb_id; /* USB device identifier */ - u8 line_out_hw_vol; /* line out hw volume is sw controlled */ - u8 level_input_count; /* inputs with level selectable */ - u8 pad_input_count; /* inputs with pad selectable */ + + /* line out hw volume is sw controlled */ + u8 line_out_hw_vol; + + /* the number of analogue inputs with a software switchable + * level control that can be set to line or instrument + */ + u8 level_input_count; + + /* the number of analogue inputs with a software switchable + * 10dB pad control + */ + u8 pad_input_count; + + /* additional description for the line out volume controls */ const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; + + /* port count and type data */ struct scarlett2_ports ports[SCARLETT2_PORT_TYPE_COUNT]; }; @@ -260,12 +274,7 @@ struct scarlett2_data { static const struct scarlett2_device_info s6i6_gen2_info = { .usb_id = USB_ID(0x1235, 0x8203), - /* The first two analogue inputs can be switched between line - * and instrument levels. - */ .level_input_count = 2, - - /* The first two analogue inputs have an optional pad. */ .pad_input_count = 2, .line_out_descrs = { @@ -315,12 +324,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), - /* The first two analogue inputs can be switched between line - * and instrument levels. - */ .level_input_count = 2, - - /* The first four analogue inputs have an optional pad. */ .pad_input_count = 4, .line_out_descrs = { @@ -378,9 +382,6 @@ static const struct scarlett2_device_info s18i8_gen2_info = { static const struct scarlett2_device_info s18i20_gen2_info = { .usb_id = USB_ID(0x1235, 0x8201), - /* The analogue line outputs on the 18i20 can be switched - * between software and hardware volume control - */ .line_out_hw_vol = 1, .line_out_descrs = { From patchwork Mon Jun 21 18:09:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335389 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C500DC4743C for ; Mon, 21 Jun 2021 18:14:30 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4DFF96115B for ; Mon, 21 Jun 2021 18:14:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4DFF96115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id D5633169F; Mon, 21 Jun 2021 20:13:38 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D5633169F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299268; bh=dtlEOrUJ5KamiNiNipdNZPL9MSKWgBExAntofgEvg10=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=L2yfPaU4/tCicGhN1Iitj7S7lfiCLAT23gQZD6JmqU+pq7VaOxJckKY/nz0odwF4l 74XuHZM5xasgqwniBtu/OmFIOfzOrk+jKWC7YcelyqOzAQiV9YF8JLpuAOTtpghEwy qDRWGsc6jLzN6UrJ1avbi/Qvpu7c58ZWRS3TXKMI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id D8B0FF80529; Mon, 21 Jun 2021 20:09:46 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 3E26EF80520; Mon, 21 Jun 2021 20:09:43 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 38F02F80517 for ; Mon, 21 Jun 2021 20:09:40 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 38F02F80517 Received: by m.b4.vu (Postfix, from userid 1000) id BCC0A61E5F02; Tue, 22 Jun 2021 03:39:37 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:37 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 11/31] ALSA: usb-audio: scarlett2: Add scarlett2_vol_ctl_write() helper Message-ID: <00dd57e1abb3fa379fb51d4ac8537dbddc09f0ea.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add helper function for setting the read/write status of a volume control. This will simplify the upcoming mute control support. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index ded99baa92de..e156119a21e8 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -1344,6 +1344,24 @@ static int scarlett2_sw_hw_enum_ctl_get(struct snd_kcontrol *kctl, return 0; } +static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer, + int index, int value) +{ + struct scarlett2_data *private = mixer->private_data; + + /* Set/Clear write bit */ + if (value) + private->vol_ctls[index]->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_WRITE; + else + private->vol_ctls[index]->vd[0].access &= + ~SNDRV_CTL_ELEM_ACCESS_WRITE; + + /* Notify of write bit change */ + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_INFO, + &private->vol_ctls[index]->id); +} + static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { @@ -1367,12 +1385,7 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, /* Change access mode to RO (hardware controlled volume) * or RW (software controlled volume) */ - if (val) - private->vol_ctls[index]->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_WRITE; - else - private->vol_ctls[index]->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_WRITE; + scarlett2_vol_ctl_set_writable(mixer, index, !val); /* Reset volume to master volume */ private->vol[index] = private->master_vol; @@ -1384,10 +1397,6 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, if (err < 0) goto unlock; - /* Notify of RO/RW change */ - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_INFO, - &private->vol_ctls[index]->id); - /* Send SW/HW switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, index, val); @@ -1620,8 +1629,7 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) /* Make the fader read-only if the SW/HW switch is set to HW */ if (private->vol_sw_hw_switch[i]) - private->vol_ctls[i]->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_WRITE; + scarlett2_vol_ctl_set_writable(mixer, i, 0); /* SW/HW Switch */ if (info->line_out_hw_vol) { From patchwork Mon Jun 21 18:09:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335391 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E66DC49EA4 for ; Mon, 21 Jun 2021 18:14:53 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 738056100B for ; Mon, 21 Jun 2021 18:14:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 738056100B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 0BF8F16CA; Mon, 21 Jun 2021 20:14:01 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 0BF8F16CA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299291; bh=12jQKfA443lYWy0sdmIeoGqdkdS/mYMZZ4TQepsCntw=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=lQ8+zVeT/MVoCAhQmrki2D+rN2Fe9WA0utZsi/USj2B/nanSB8l+XcsMtrO5/VDrY D0mbz52ZS8H7UP86FflGebppiTMXlHJTecicXih414OKvHO5FuAK61jiVvtZ37z8JW iDP37vTMNorhlYcqeP9TS8m6+wLV0jJKDwBY9cCU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id D7E43F80535; Mon, 21 Jun 2021 20:09:50 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id A79B2F80535; Mon, 21 Jun 2021 20:09:49 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 34D88F80517 for ; Mon, 21 Jun 2021 20:09:42 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 34D88F80517 Received: by m.b4.vu (Postfix, from userid 1000) id B24B961E287F; Tue, 22 Jun 2021 03:39:39 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:39 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 12/31] ALSA: usb-audio: scarlett2: Add mute support Message-ID: <6fad82174b44633e46cfd96332a038de74d544f2.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" For each analogue output, in addition to the output volume (gain) control, the hardware also has a mute control. Add ALSA mute controls for each analogue output. If the device has the line_out_hw_vol feature, then the mute control is disabled along with the output volume control when the switch is set to HW. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 170 +++++++++++++++++++++++++++----- 1 file changed, 145 insertions(+), 25 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index e156119a21e8..d30f15d580b5 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -39,7 +39,7 @@ * This ALSA mixer gives access to: * - input, output, mixer-matrix muxes * - 18x10 mixer-matrix gain stages - * - gain/volume controls + * - gain/volume/mute controls * - level meters * - line/inst level and pad controls * @@ -195,7 +195,11 @@ enum { }; /* Dim/Mute buttons on the 18i20 */ -#define SCARLETT2_DIM_MUTE_COUNT 2 +enum { + SCARLETT2_BUTTON_MUTE = 0, + SCARLETT2_BUTTON_DIM = 1, + SCARLETT2_DIM_MUTE_COUNT = 2, +}; static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = { "Mute", "Dim" @@ -258,12 +262,14 @@ struct scarlett2_data { u8 master_vol; u8 vol[SCARLETT2_ANALOGUE_MAX]; u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; + u8 mute_switch[SCARLETT2_ANALOGUE_MAX]; u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX]; u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX]; + struct snd_kcontrol *mute_ctls[SCARLETT2_ANALOGUE_MAX]; struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT]; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; @@ -509,7 +515,8 @@ struct scarlett2_usb_volume_status { /* actual volume of output inc. dim (-18dB) */ s16 hw_vol[SCARLETT2_ANALOGUE_MAX]; - u8 pad2[SCARLETT2_ANALOGUE_MAX]; + /* internal mute buttons */ + u8 mute_switch[SCARLETT2_ANALOGUE_MAX]; /* sw (0) or hw (1) controlled */ u8 sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; @@ -524,10 +531,11 @@ struct scarlett2_usb_volume_status { enum { SCARLETT2_CONFIG_DIM_MUTE = 0, SCARLETT2_CONFIG_LINE_OUT_VOLUME = 1, - SCARLETT2_CONFIG_SW_HW_SWITCH = 2, - SCARLETT2_CONFIG_LEVEL_SWITCH = 3, - SCARLETT2_CONFIG_PAD_SWITCH = 4, - SCARLETT2_CONFIG_COUNT = 5 + SCARLETT2_CONFIG_MUTE_SWITCH = 2, + SCARLETT2_CONFIG_SW_HW_SWITCH = 3, + SCARLETT2_CONFIG_LEVEL_SWITCH = 4, + SCARLETT2_CONFIG_PAD_SWITCH = 5, + SCARLETT2_CONFIG_COUNT = 6 }; /* Location, size, and activation command number for the configuration @@ -547,6 +555,9 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = { .offset = 0x34, .size = 2, .activate = 1 }, + [SCARLETT2_CONFIG_MUTE_SWITCH] = { + .offset = 0x5c, .size = 1, .activate = 1 }, + [SCARLETT2_CONFIG_SW_HW_SWITCH] = { .offset = 0x66, .size = 1, .activate = 3 }, @@ -1197,6 +1208,7 @@ static int scarlett2_update_volumes(struct usb_mixer_interface *mixer) int num_line_out = ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; int err, i; + int mute; private->vol_updated = 0; @@ -1208,15 +1220,18 @@ static int scarlett2_update_volumes(struct usb_mixer_interface *mixer) volume_status.master_vol + SCARLETT2_VOLUME_BIAS, 0, SCARLETT2_VOLUME_BIAS); - for (i = 0; i < num_line_out; i++) { - if (private->vol_sw_hw_switch[i]) - private->vol[i] = private->master_vol; - } - if (info->line_out_hw_vol) for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) private->dim_mute[i] = !!volume_status.dim_mute[i]; + mute = private->dim_mute[SCARLETT2_BUTTON_MUTE]; + + for (i = 0; i < num_line_out; i++) + if (private->vol_sw_hw_switch[i]) { + private->vol[i] = private->master_vol; + private->mute_switch[i] = mute; + } + return 0; } @@ -1321,6 +1336,55 @@ static const struct snd_kcontrol_new scarlett2_line_out_volume_ctl = { .tlv = { .p = db_scale_scarlett2_gain } }; +/*** Mute Switch Controls ***/ + +static int scarlett2_mute_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; + int index = elem->control; + + ucontrol->value.integer.value[0] = private->mute_switch[index]; + return 0; +} + +static int scarlett2_mute_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 index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->mute_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->mute_switch[index] = val; + + /* Send mute change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MUTE_SWITCH, + index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_mute_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_mute_ctl_get, + .put = scarlett2_mute_ctl_put, +}; + /*** HW/SW Volume Switch Controls ***/ static int scarlett2_sw_hw_enum_ctl_info(struct snd_kcontrol *kctl, @@ -1348,18 +1412,26 @@ static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer, int index, int value) { struct scarlett2_data *private = mixer->private_data; + struct snd_card *card = mixer->chip->card; - /* Set/Clear write bit */ - if (value) + /* Set/Clear write bits */ + if (value) { private->vol_ctls[index]->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; - else + private->mute_ctls[index]->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_WRITE; + } else { private->vol_ctls[index]->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE; + private->mute_ctls[index]->vd[0].access &= + ~SNDRV_CTL_ELEM_ACCESS_WRITE; + } /* Notify of write bit change */ - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_INFO, + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &private->vol_ctls[index]->id); + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, + &private->mute_ctls[index]->id); } static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, @@ -1387,8 +1459,9 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, */ scarlett2_vol_ctl_set_writable(mixer, index, !val); - /* Reset volume to master volume */ + /* Reset volume/mute to master volume/mute */ private->vol[index] = private->master_vol; + private->mute_switch[index] = private->dim_mute[SCARLETT2_BUTTON_MUTE]; /* Set SW volume to current HW volume */ err = scarlett2_usb_set_config( @@ -1397,6 +1470,13 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, if (err < 0) goto unlock; + /* Set SW mute to current HW mute */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MUTE_SWITCH, + index, private->dim_mute[SCARLETT2_BUTTON_MUTE]); + if (err < 0) + goto unlock; + /* Send SW/HW switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, index, val); @@ -1554,9 +1634,13 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const struct scarlett2_ports *ports = info->ports; + int num_line_out = + ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; int index = elem->control; - int oval, val, err = 0; + int oval, val, err = 0, i; mutex_lock(&private->data_mutex); @@ -1574,6 +1658,15 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl, if (err == 0) err = 1; + if (index == SCARLETT2_BUTTON_MUTE) + for (i = 0; i < num_line_out; i++) + if (private->vol_sw_hw_switch[i]) { + private->mute_switch[i] = val; + snd_ctl_notify(mixer->chip->card, + SNDRV_CTL_EVENT_MASK_INFO, + &private->mute_ctls[i]->id); + } + unlock: mutex_unlock(&private->data_mutex); return err; @@ -1627,7 +1720,20 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) if (err < 0) return err; - /* Make the fader read-only if the SW/HW switch is set to HW */ + /* Mute Switch */ + snprintf(s, sizeof(s), + "Line %02d Mute Playback Switch", + i + 1); + err = scarlett2_add_new_ctl(mixer, + &scarlett2_mute_ctl, + i, 1, s, + &private->mute_ctls[i]); + if (err < 0) + return err; + + /* Make the fader and mute controls read-only if the + * SW/HW switch is set to HW + */ if (private->vol_sw_hw_switch[i]) scarlett2_vol_ctl_set_writable(mixer, i, 0); @@ -2109,12 +2215,16 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) if (err < 0) return err; + if (info->line_out_hw_vol) + for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) + private->dim_mute[i] = !!volume_status.dim_mute[i]; + private->master_vol = clamp( volume_status.master_vol + SCARLETT2_VOLUME_BIAS, 0, SCARLETT2_VOLUME_BIAS); for (i = 0; i < num_line_out; i++) { - int volume; + int volume, mute; private->vol_sw_hw_switch[i] = info->line_out_hw_vol @@ -2126,11 +2236,12 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) volume = clamp(volume + SCARLETT2_VOLUME_BIAS, 0, SCARLETT2_VOLUME_BIAS); private->vol[i] = volume; - } - if (info->line_out_hw_vol) - for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) - private->dim_mute[i] = !!volume_status.dim_mute[i]; + mute = private->vol_sw_hw_switch[i] + ? private->dim_mute[SCARLETT2_BUTTON_MUTE] + : volume_status.mute_switch[i]; + private->mute_switch[i] = mute; + } for (i = 0; i < num_mixer_out; i++) { err = scarlett2_usb_get_mix(mixer, i); @@ -2185,8 +2296,12 @@ static void scarlett2_notify_monitor( static void scarlett2_notify_dim_mute( struct usb_mixer_interface *mixer) { + struct snd_card *card = mixer->chip->card; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; + const struct scarlett2_ports *ports = info->ports; + int num_line_out = + ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; int i; private->vol_updated = 1; @@ -2195,8 +2310,13 @@ static void scarlett2_notify_dim_mute( return; for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &private->dim_mute_ctls[i]->id); + + for (i = 0; i < num_line_out; i++) + if (private->vol_sw_hw_switch[i]) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->mute_ctls[i]->id); } /* Interrupt callback */ From patchwork Mon Jun 21 18:09:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335393 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 74924C49EA2 for ; Mon, 21 Jun 2021 18:15:24 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 85A636124B for ; Mon, 21 Jun 2021 18:15:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 85A636124B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 10E51168D; Mon, 21 Jun 2021 20:14:32 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 10E51168D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299322; bh=TFr6PP1aQjamQGYv+WkBAeDTH8G52dkepUoM6Z8wwvg=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=s7Zs3HFQ1CFkoK/RkeQisr47/9S+swHvqjLtRBg/8ZBUcAkuFEgwEPe3Wg2baRns/ WRV9LID/7OSbJsq2egRrP883cu/w/RcqrzybCXg3PzvrcHur5EXKQ9rF4uHiTdCeFn TAWS7znKMLx1Q78tGCIjmbbbhKGWmGX2jQnEkmaQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 4C599F8053D; Mon, 21 Jun 2021 20:09:54 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 4AE47F80538; Mon, 21 Jun 2021 20:09:51 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 413F4F80526 for ; Mon, 21 Jun 2021 20:09:44 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 413F4F80526 Received: by m.b4.vu (Postfix, from userid 1000) id C3A4361E286F; Tue, 22 Jun 2021 03:39:41 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:41 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 13/31] ALSA: usb-audio: scarlett2: Allow arbitrary ordering of mux entries Message-ID: <08e8d784d78262cb57496d28ef1ad7b6213a90ab.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Some Gen 3 devices do not put all of the mux entries for the same port types together in order in the "set mux" message data. To prepare for this, replace the struct scarlett2_ports num[] array and the assignment_order[] array with mux_assignment[], a list of port types and ranges that is defined in the struct scarlett2_device_info. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 222 ++++++++++++++++++++++---------- 1 file changed, 154 insertions(+), 68 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index d30f15d580b5..b874c0c922d3 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -184,14 +184,11 @@ enum { SCARLETT2_PORT_TYPE_COUNT = 6, }; -/* Count of total I/O and number available at each sample rate */ +/* I/O count of each port type kept in struct scarlett2_ports */ enum { - SCARLETT2_PORT_IN = 0, - SCARLETT2_PORT_OUT = 1, - SCARLETT2_PORT_OUT_44 = 2, - SCARLETT2_PORT_OUT_88 = 3, - SCARLETT2_PORT_OUT_176 = 4, - SCARLETT2_PORT_DIRNS = 5, + SCARLETT2_PORT_IN = 0, + SCARLETT2_PORT_OUT = 1, + SCARLETT2_PORT_DIRNS = 2, }; /* Dim/Mute buttons on the 18i20 */ @@ -220,6 +217,24 @@ struct scarlett2_ports { const char * const dst_descr; }; +/* Number of mux tables: one for each band of sample rates + * (44.1/48kHz, 88.2/96kHz, and 176.4/176kHz) + */ +#define SCARLETT2_MUX_TABLES 3 + +/* Maximum number of entries in a mux table */ +#define SCARLETT2_MAX_MUX_ENTRIES 7 + +/* One entry within mux_assignment defines the port type and range of + * ports to add to the set_mux message. The end of the list is marked + * with count == 0. + */ +struct scarlett2_mux_entry { + u8 port_type; + u8 start; + u8 count; +}; + struct scarlett2_device_info { u32 usb_id; /* USB device identifier */ @@ -241,6 +256,10 @@ struct scarlett2_device_info { /* port count and type data */ struct scarlett2_ports ports[SCARLETT2_PORT_TYPE_COUNT]; + + /* layout/order of the entries in the set_mux message */ + struct scarlett2_mux_entry mux_assignment[SCARLETT2_MUX_TABLES] + [SCARLETT2_MAX_MUX_ENTRIES]; }; struct scarlett2_data { @@ -293,38 +312,61 @@ static const struct scarlett2_device_info s6i6_gen2_info = { .ports = { [SCARLETT2_PORT_TYPE_NONE] = { .id = 0x000, - .num = { 1, 0, 8, 8, 8 }, + .num = { 1, 0 }, .src_descr = "Off", }, [SCARLETT2_PORT_TYPE_ANALOGUE] = { .id = 0x080, - .num = { 4, 4, 4, 4, 4 }, + .num = { 4, 4 }, .src_descr = "Analogue %d", .src_num_offset = 1, .dst_descr = "Analogue Output %02d Playback" }, [SCARLETT2_PORT_TYPE_SPDIF] = { .id = 0x180, - .num = { 2, 2, 2, 2, 2 }, + .num = { 2, 2 }, .src_descr = "S/PDIF %d", .src_num_offset = 1, .dst_descr = "S/PDIF Output %d Playback" }, [SCARLETT2_PORT_TYPE_MIX] = { .id = 0x300, - .num = { 10, 18, 18, 18, 18 }, + .num = { 10, 18 }, .src_descr = "Mix %c", .src_num_offset = 65, .dst_descr = "Mixer Input %02d Capture" }, [SCARLETT2_PORT_TYPE_PCM] = { .id = 0x600, - .num = { 6, 6, 6, 6, 6 }, + .num = { 6, 6 }, .src_descr = "PCM %d", .src_num_offset = 1, .dst_descr = "PCM %02d Capture" }, }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + } }, }; static const struct scarlett2_device_info s18i8_gen2_info = { @@ -345,44 +387,67 @@ static const struct scarlett2_device_info s18i8_gen2_info = { .ports = { [SCARLETT2_PORT_TYPE_NONE] = { .id = 0x000, - .num = { 1, 0, 8, 8, 4 }, + .num = { 1, 0 }, .src_descr = "Off", }, [SCARLETT2_PORT_TYPE_ANALOGUE] = { .id = 0x080, - .num = { 8, 6, 6, 6, 6 }, + .num = { 8, 6 }, .src_descr = "Analogue %d", .src_num_offset = 1, .dst_descr = "Analogue Output %02d Playback" }, [SCARLETT2_PORT_TYPE_SPDIF] = { .id = 0x180, - .num = { 2, 2, 2, 2, 2 }, + .num = { 2, 2 }, .src_descr = "S/PDIF %d", .src_num_offset = 1, .dst_descr = "S/PDIF Output %d Playback" }, [SCARLETT2_PORT_TYPE_ADAT] = { .id = 0x200, - .num = { 8, 0, 0, 0, 0 }, + .num = { 8, 0 }, .src_descr = "ADAT %d", .src_num_offset = 1, }, [SCARLETT2_PORT_TYPE_MIX] = { .id = 0x300, - .num = { 10, 18, 18, 18, 18 }, + .num = { 10, 18 }, .src_descr = "Mix %c", .src_num_offset = 65, .dst_descr = "Mixer Input %02d Capture" }, [SCARLETT2_PORT_TYPE_PCM] = { .id = 0x600, - .num = { 8, 18, 18, 14, 10 }, + .num = { 8, 18 }, .src_descr = "PCM %d", .src_num_offset = 1, .dst_descr = "PCM %02d Capture" }, }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 18 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 14 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 4 }, + { 0, 0, 0 }, + } }, }; static const struct scarlett2_device_info s18i20_gen2_info = { @@ -406,12 +471,12 @@ static const struct scarlett2_device_info s18i20_gen2_info = { .ports = { [SCARLETT2_PORT_TYPE_NONE] = { .id = 0x000, - .num = { 1, 0, 8, 8, 6 }, + .num = { 1, 0 }, .src_descr = "Off", }, [SCARLETT2_PORT_TYPE_ANALOGUE] = { .id = 0x080, - .num = { 8, 10, 10, 10, 10 }, + .num = { 8, 10 }, .src_descr = "Analogue %d", .src_num_offset = 1, .dst_descr = "Analogue Output %02d Playback" @@ -422,33 +487,58 @@ static const struct scarlett2_device_info s18i20_gen2_info = { * assignment message anyway */ .id = 0x180, - .num = { 2, 2, 2, 2, 2 }, + .num = { 2, 2 }, .src_descr = "S/PDIF %d", .src_num_offset = 1, .dst_descr = "S/PDIF Output %d Playback" }, [SCARLETT2_PORT_TYPE_ADAT] = { .id = 0x200, - .num = { 8, 8, 8, 4, 0 }, + .num = { 8, 8 }, .src_descr = "ADAT %d", .src_num_offset = 1, .dst_descr = "ADAT Output %d Playback" }, [SCARLETT2_PORT_TYPE_MIX] = { .id = 0x300, - .num = { 10, 18, 18, 18, 18 }, + .num = { 10, 18 }, .src_descr = "Mix %c", .src_num_offset = 65, .dst_descr = "Mixer Input %02d Capture" }, [SCARLETT2_PORT_TYPE_PCM] = { .id = 0x600, - .num = { 20, 18, 18, 14, 10 }, + .num = { 20, 18 }, .src_descr = "PCM %d", .src_num_offset = 1, .dst_descr = "PCM %02d Capture" }, }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 18 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_ADAT, 0, 8 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 14 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_ADAT, 0, 4 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 6 }, + { 0, 0, 0 }, + } }, }; static const struct scarlett2_device_info *scarlett2_devices[] = { @@ -1009,16 +1099,7 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; const struct scarlett2_ports *ports = info->ports; - int rate, port_dir_rate; - - static const int assignment_order[SCARLETT2_PORT_TYPE_COUNT] = { - SCARLETT2_PORT_TYPE_PCM, - SCARLETT2_PORT_TYPE_ANALOGUE, - SCARLETT2_PORT_TYPE_SPDIF, - SCARLETT2_PORT_TYPE_ADAT, - SCARLETT2_PORT_TYPE_MIX, - SCARLETT2_PORT_TYPE_NONE, - }; + int table; struct { __le16 pad; @@ -1028,39 +1109,44 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) req.pad = 0; - /* mux settings for each rate */ - for (rate = 0, port_dir_rate = SCARLETT2_PORT_OUT_44; - port_dir_rate <= SCARLETT2_PORT_OUT_176; - rate++, port_dir_rate++) { - int order_num, i, err; - - req.num = cpu_to_le16(rate); - - for (order_num = 0, i = 0; - order_num < SCARLETT2_PORT_TYPE_COUNT; - order_num++) { - int port_type = assignment_order[order_num]; - int j = scarlett2_get_port_start_num(ports, - SCARLETT2_PORT_OUT, - port_type); - int port_id = ports[port_type].id; - int channel; - - for (channel = 0; - channel < ports[port_type].num[port_dir_rate]; - channel++, i++, j++) - /* lower 12 bits for the destination and - * next 12 bits for the source - */ - req.data[i] = !port_id - ? 0 - : cpu_to_le32( - port_id | - channel | - scarlett2_mux_src_num_to_id( - ports, private->mux[j] - ) << 12 - ); + /* set mux settings for each rate */ + for (table = 0; table < SCARLETT2_MUX_TABLES; table++) { + const struct scarlett2_mux_entry *entry; + + /* i counts over the output array */ + int i = 0, err; + + req.num = cpu_to_le16(table); + + /* loop through each entry */ + for (entry = info->mux_assignment[table]; + entry->count; + entry++) { + int j; + int port_type = entry->port_type; + int port_idx = entry->start; + int mux_idx = scarlett2_get_port_start_num(ports, + SCARLETT2_PORT_OUT, port_type) + port_idx; + int dst_id = ports[port_type].id + port_idx; + + /* Empty slots */ + if (!dst_id) { + for (j = 0; j < entry->count; j++) + req.data[i++] = 0; + continue; + } + + /* Non-empty mux slots use the lower 12 bits + * for the destination and next 12 bits for + * the source + */ + for (j = 0; j < entry->count; j++) { + int src_id = scarlett2_mux_src_num_to_id( + ports, private->mux[mux_idx++]); + req.data[i++] = cpu_to_le32(dst_id | + src_id << 12); + dst_id++; + } } err = scarlett2_usb(mixer, SCARLETT2_USB_SET_MUX, @@ -2081,7 +2167,7 @@ static void scarlett2_count_mux_io(struct scarlett2_data *private) port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { srcs += ports[port_type].num[SCARLETT2_PORT_IN]; - dsts += ports[port_type].num[SCARLETT2_PORT_OUT_44]; + dsts += ports[port_type].num[SCARLETT2_PORT_OUT]; } private->num_mux_srcs = srcs; From patchwork Mon Jun 21 18:09:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335395 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 094AAC4743C for ; Mon, 21 Jun 2021 18:15:43 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 890AF6115B for ; Mon, 21 Jun 2021 18:15:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 890AF6115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 2415D1683; Mon, 21 Jun 2021 20:14:51 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 2415D1683 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299341; bh=JCK0YUQeGEeLS83MNZzOJqBxhALzogKSm7dqVx8NglI=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=u7NWP2BXk2dUEuJkJn8hjd99sBPgk3DsijTOjqEpqYIN1I9YYHjdYxMEBOgIZ7iAY xJ2zMXxOr0nvsUyCgITl4PTy1KSLz1YUH3hgKOnnlHJ6tgKasTpTwMJVnyKX8kfIJm yLyZcHlF2ekZeJptrV13J9XeOlDPmuyZYFChJvmQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 7C6F8F80544; Mon, 21 Jun 2021 20:09:56 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id B3430F80548; Mon, 21 Jun 2021 20:09:54 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 672EEF80528 for ; Mon, 21 Jun 2021 20:09:46 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 672EEF80528 Received: by m.b4.vu (Postfix, from userid 1000) id E567C61E287D; Tue, 22 Jun 2021 03:39:43 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:43 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 14/31] ALSA: usb-audio: scarlett2: Split struct scarlett2_ports Message-ID: <7a9e57e4e55a482390c692a9e60731d72b664a15.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The scarlett2_ports struct contains both generic (hardware IDs and descriptions) and model-specific (port count) data. Remove the generic data from the scarlett2_device_info struct so it is not repeated for every model. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 303 +++++++++++++------------------- 1 file changed, 124 insertions(+), 179 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index b874c0c922d3..7647b3428093 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -203,20 +203,55 @@ static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = { }; /* Description of each hardware port type: - * - id: hardware ID for this port type - * - num: number of sources/destinations of this port type + * - id: hardware ID of this port type * - src_descr: printf format string for mux input selections * - src_num_offset: added to channel number for the fprintf * - dst_descr: printf format string for mixer controls */ -struct scarlett2_ports { +struct scarlett2_port { u16 id; - int num[SCARLETT2_PORT_DIRNS]; const char * const src_descr; int src_num_offset; const char * const dst_descr; }; +static const struct scarlett2_port scarlett2_ports[SCARLETT2_PORT_TYPE_COUNT] = { + [SCARLETT2_PORT_TYPE_NONE] = { + .id = 0x000, + .src_descr = "Off" + }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { + .id = 0x080, + .src_descr = "Analogue %d", + .src_num_offset = 1, + .dst_descr = "Analogue Output %02d Playback" + }, + [SCARLETT2_PORT_TYPE_SPDIF] = { + .id = 0x180, + .src_descr = "S/PDIF %d", + .src_num_offset = 1, + .dst_descr = "S/PDIF Output %d Playback" + }, + [SCARLETT2_PORT_TYPE_ADAT] = { + .id = 0x200, + .src_descr = "ADAT %d", + .src_num_offset = 1, + .dst_descr = "ADAT Output %d Playback" + }, + [SCARLETT2_PORT_TYPE_MIX] = { + .id = 0x300, + .src_descr = "Mix %c", + .src_num_offset = 'A', + .dst_descr = "Mixer Input %02d Capture" + }, + [SCARLETT2_PORT_TYPE_PCM] = { + .id = 0x600, + .src_descr = "PCM %d", + .src_num_offset = 1, + .dst_descr = "PCM %02d Capture" + }, +}; + /* Number of mux tables: one for each band of sample rates * (44.1/48kHz, 88.2/96kHz, and 176.4/176kHz) */ @@ -254,8 +289,8 @@ struct scarlett2_device_info { /* additional description for the line out volume controls */ const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; - /* port count and type data */ - struct scarlett2_ports ports[SCARLETT2_PORT_TYPE_COUNT]; + /* number of sources/destinations of each port type */ + const int port_count[SCARLETT2_PORT_TYPE_COUNT][SCARLETT2_PORT_DIRNS]; /* layout/order of the entries in the set_mux message */ struct scarlett2_mux_entry mux_assignment[SCARLETT2_MUX_TABLES] @@ -309,40 +344,12 @@ static const struct scarlett2_device_info s6i6_gen2_info = { "Headphones 2 R", }, - .ports = { - [SCARLETT2_PORT_TYPE_NONE] = { - .id = 0x000, - .num = { 1, 0 }, - .src_descr = "Off", - }, - [SCARLETT2_PORT_TYPE_ANALOGUE] = { - .id = 0x080, - .num = { 4, 4 }, - .src_descr = "Analogue %d", - .src_num_offset = 1, - .dst_descr = "Analogue Output %02d Playback" - }, - [SCARLETT2_PORT_TYPE_SPDIF] = { - .id = 0x180, - .num = { 2, 2 }, - .src_descr = "S/PDIF %d", - .src_num_offset = 1, - .dst_descr = "S/PDIF Output %d Playback" - }, - [SCARLETT2_PORT_TYPE_MIX] = { - .id = 0x300, - .num = { 10, 18 }, - .src_descr = "Mix %c", - .src_num_offset = 65, - .dst_descr = "Mixer Input %02d Capture" - }, - [SCARLETT2_PORT_TYPE_PCM] = { - .id = 0x600, - .num = { 6, 6 }, - .src_descr = "PCM %d", - .src_num_offset = 1, - .dst_descr = "PCM %02d Capture" - }, + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 4, 4 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 }, + [SCARLETT2_PORT_TYPE_PCM] = { 6, 6 }, }, .mux_assignment = { { @@ -384,46 +391,13 @@ static const struct scarlett2_device_info s18i8_gen2_info = { "Headphones 2 R", }, - .ports = { - [SCARLETT2_PORT_TYPE_NONE] = { - .id = 0x000, - .num = { 1, 0 }, - .src_descr = "Off", - }, - [SCARLETT2_PORT_TYPE_ANALOGUE] = { - .id = 0x080, - .num = { 8, 6 }, - .src_descr = "Analogue %d", - .src_num_offset = 1, - .dst_descr = "Analogue Output %02d Playback" - }, - [SCARLETT2_PORT_TYPE_SPDIF] = { - .id = 0x180, - .num = { 2, 2 }, - .src_descr = "S/PDIF %d", - .src_num_offset = 1, - .dst_descr = "S/PDIF Output %d Playback" - }, - [SCARLETT2_PORT_TYPE_ADAT] = { - .id = 0x200, - .num = { 8, 0 }, - .src_descr = "ADAT %d", - .src_num_offset = 1, - }, - [SCARLETT2_PORT_TYPE_MIX] = { - .id = 0x300, - .num = { 10, 18 }, - .src_descr = "Mix %c", - .src_num_offset = 65, - .dst_descr = "Mixer Input %02d Capture" - }, - [SCARLETT2_PORT_TYPE_PCM] = { - .id = 0x600, - .num = { 8, 18 }, - .src_descr = "PCM %d", - .src_num_offset = 1, - .dst_descr = "PCM %02d Capture" - }, + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 6 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_ADAT] = { 8, 0 }, + [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 }, + [SCARLETT2_PORT_TYPE_PCM] = { 8, 18 }, }, .mux_assignment = { { @@ -468,51 +442,13 @@ static const struct scarlett2_device_info s18i20_gen2_info = { "Headphones 2 R", }, - .ports = { - [SCARLETT2_PORT_TYPE_NONE] = { - .id = 0x000, - .num = { 1, 0 }, - .src_descr = "Off", - }, - [SCARLETT2_PORT_TYPE_ANALOGUE] = { - .id = 0x080, - .num = { 8, 10 }, - .src_descr = "Analogue %d", - .src_num_offset = 1, - .dst_descr = "Analogue Output %02d Playback" - }, - [SCARLETT2_PORT_TYPE_SPDIF] = { - /* S/PDIF outputs aren't available at 192kHz - * but are included in the USB mux I/O - * assignment message anyway - */ - .id = 0x180, - .num = { 2, 2 }, - .src_descr = "S/PDIF %d", - .src_num_offset = 1, - .dst_descr = "S/PDIF Output %d Playback" - }, - [SCARLETT2_PORT_TYPE_ADAT] = { - .id = 0x200, - .num = { 8, 8 }, - .src_descr = "ADAT %d", - .src_num_offset = 1, - .dst_descr = "ADAT Output %d Playback" - }, - [SCARLETT2_PORT_TYPE_MIX] = { - .id = 0x300, - .num = { 10, 18 }, - .src_descr = "Mix %c", - .src_num_offset = 65, - .dst_descr = "Mixer Input %02d Capture" - }, - [SCARLETT2_PORT_TYPE_PCM] = { - .id = 0x600, - .num = { 20, 18 }, - .src_descr = "PCM %d", - .src_num_offset = 1, - .dst_descr = "PCM %02d Capture" - }, + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 10 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_ADAT] = { 8, 8 }, + [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 }, + [SCARLETT2_PORT_TYPE_PCM] = { 20, 18 }, }, .mux_assignment = { { @@ -552,13 +488,14 @@ static const struct scarlett2_device_info *scarlett2_devices[] = { }; /* get the starting port index number for a given port type/direction */ -static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, - int direction, int port_type) +static int scarlett2_get_port_start_num( + const int port_count[][SCARLETT2_PORT_DIRNS], + int direction, int port_type) { int i, num = 0; for (i = 0; i < port_type; i++) - num += ports[i].num[direction]; + num += port_count[i][direction]; return num; } @@ -924,7 +861,7 @@ static int scarlett2_usb_get_mix(struct usb_mixer_interface *mixer, const struct scarlett2_device_info *info = private->info; int num_mixer_in = - info->ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; + info->port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT]; int err, i, j, k; struct { @@ -973,7 +910,7 @@ static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer, int i, j; int num_mixer_in = - info->ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; + info->port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT]; req.mix_num = cpu_to_le16(mix_num); @@ -987,18 +924,18 @@ static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer, NULL, 0); } -/* Convert a port number index (per info->ports) to a hardware ID */ -static u32 scarlett2_mux_src_num_to_id(const struct scarlett2_ports *ports, - int num) +/* Convert a port number index (per info->port_count) to a hardware ID */ +static u32 scarlett2_mux_src_num_to_id( + const int port_count[][SCARLETT2_PORT_DIRNS], int num) { int port_type; for (port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { - if (num < ports[port_type].num[SCARLETT2_PORT_IN]) - return ports[port_type].id | num; - num -= ports[port_type].num[SCARLETT2_PORT_IN]; + if (num < port_count[port_type][SCARLETT2_PORT_IN]) + return scarlett2_ports[port_type].id | num; + num -= port_count[port_type][SCARLETT2_PORT_IN]; } /* Oops */ @@ -1006,9 +943,8 @@ static u32 scarlett2_mux_src_num_to_id(const struct scarlett2_ports *ports, } /* Convert a hardware ID to a port number index */ -static u32 scarlett2_mux_id_to_num(const struct scarlett2_ports *ports, - int direction, - u32 id) +static u32 scarlett2_mux_id_to_num( + const int port_count[][SCARLETT2_PORT_DIRNS], int direction, u32 id) { int port_type; int port_num = 0; @@ -1016,11 +952,11 @@ static u32 scarlett2_mux_id_to_num(const struct scarlett2_ports *ports, for (port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { - struct scarlett2_ports port = ports[port_type]; - int count = port.num[direction]; + int base = scarlett2_ports[port_type].id; + int count = port_count[port_type][direction]; - if (id >= port.id && id < port.id + count) - return port_num + id - port.id; + if (id >= base && id < base + count) + return port_num + id - base; port_num += count; } @@ -1033,11 +969,11 @@ static void scarlett2_usb_populate_mux(struct scarlett2_data *private, u32 mux_entry) { const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int dst_idx, src_idx; - dst_idx = scarlett2_mux_id_to_num(ports, SCARLETT2_PORT_OUT, + dst_idx = scarlett2_mux_id_to_num(port_count, SCARLETT2_PORT_OUT, mux_entry & 0xFFF); if (dst_idx < 0) return; @@ -1049,7 +985,7 @@ static void scarlett2_usb_populate_mux(struct scarlett2_data *private, return; } - src_idx = scarlett2_mux_id_to_num(ports, SCARLETT2_PORT_IN, + src_idx = scarlett2_mux_id_to_num(port_count, SCARLETT2_PORT_IN, mux_entry >> 12); if (src_idx < 0) return; @@ -1098,7 +1034,7 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int table; struct { @@ -1125,9 +1061,9 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) int j; int port_type = entry->port_type; int port_idx = entry->start; - int mux_idx = scarlett2_get_port_start_num(ports, + int mux_idx = scarlett2_get_port_start_num(port_count, SCARLETT2_PORT_OUT, port_type) + port_idx; - int dst_id = ports[port_type].id + port_idx; + int dst_id = scarlett2_ports[port_type].id + port_idx; /* Empty slots */ if (!dst_id) { @@ -1142,7 +1078,7 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) */ for (j = 0; j < entry->count; j++) { int src_id = scarlett2_mux_src_num_to_id( - ports, private->mux[mux_idx++]); + port_count, private->mux[mux_idx++]); req.data[i++] = cpu_to_le32(dst_id | src_id << 12); dst_id++; @@ -1289,10 +1225,10 @@ static int scarlett2_update_volumes(struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; struct scarlett2_usb_volume_status volume_status; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int err, i; int mute; @@ -1721,9 +1657,9 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int index = elem->control; int oval, val, err = 0, i; @@ -1772,9 +1708,9 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int err, i; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; @@ -1913,7 +1849,7 @@ static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int oval, val, num_mixer_in, mix_num, err = 0; int index = elem->control; @@ -1921,7 +1857,7 @@ static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl, oval = private->mix[index]; val = ucontrol->value.integer.value[0]; - num_mixer_in = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; + num_mixer_in = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT]; mix_num = index / num_mixer_in; if (oval == val) @@ -1958,13 +1894,16 @@ static const struct snd_kcontrol_new scarlett2_mixer_ctl = { static int scarlett2_add_mixer_ctls(struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int err, i, j; int index; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - int num_inputs = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; - int num_outputs = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_IN]; + int num_inputs = + port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT]; + int num_outputs = + port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; for (i = 0, index = 0; i < num_outputs; i++) for (j = 0; j < num_inputs; j++, index++) { @@ -1987,7 +1926,8 @@ static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct scarlett2_data *private = elem->head.mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; unsigned int item = uinfo->value.enumerated.item; int items = private->num_mux_srcs; int port_type; @@ -2002,13 +1942,15 @@ static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl, for (port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { - if (item < ports[port_type].num[SCARLETT2_PORT_IN]) { + if (item < port_count[port_type][SCARLETT2_PORT_IN]) { + const struct scarlett2_port *port = + &scarlett2_ports[port_type]; + sprintf(uinfo->value.enumerated.name, - ports[port_type].src_descr, - item + ports[port_type].src_num_offset); + port->src_descr, item + port->src_num_offset); return 0; } - item -= ports[port_type].num[SCARLETT2_PORT_IN]; + item -= port_count[port_type][SCARLETT2_PORT_IN]; } return -EINVAL; @@ -2063,18 +2005,20 @@ static const struct snd_kcontrol_new scarlett2_mux_src_enum_ctl = { static int scarlett2_add_mux_enums(struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int port_type, channel, i; for (i = 0, port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { for (channel = 0; - channel < ports[port_type].num[SCARLETT2_PORT_OUT]; + channel < port_count[port_type][SCARLETT2_PORT_OUT]; channel++, i++) { int err; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - const char *const descr = ports[port_type].dst_descr; + const char *const descr = + scarlett2_ports[port_type].dst_descr; snprintf(s, sizeof(s) - 5, descr, channel + 1); strcat(s, " Enum"); @@ -2160,14 +2104,15 @@ static void scarlett2_private_suspend(struct usb_mixer_interface *mixer) static void scarlett2_count_mux_io(struct scarlett2_data *private) { - const struct scarlett2_ports *ports = private->info->ports; + 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; for (port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { - srcs += ports[port_type].num[SCARLETT2_PORT_IN]; - dsts += ports[port_type].num[SCARLETT2_PORT_OUT]; + srcs += port_count[port_type][SCARLETT2_PORT_IN]; + dsts += port_count[port_type][SCARLETT2_PORT_OUT]; } private->num_mux_srcs = srcs; @@ -2265,11 +2210,11 @@ 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; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int num_mixer_out = - ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_IN]; + port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; struct scarlett2_usb_volume_status volume_status; int err, i; @@ -2356,9 +2301,9 @@ static void scarlett2_notify_monitor( { struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int i; /* if line_out_hw_vol is 0, there are no controls to update */ @@ -2385,9 +2330,9 @@ static void scarlett2_notify_dim_mute( struct snd_card *card = mixer->chip->card; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int i; private->vol_updated = 1; From patchwork Mon Jun 21 18:09:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335397 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02C16C4743C for ; Mon, 21 Jun 2021 18:16:18 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 79CC5611BD for ; Mon, 21 Jun 2021 18:16:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 79CC5611BD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 214D616E1; Mon, 21 Jun 2021 20:15:26 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 214D616E1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299376; bh=hgF29ZyTwWFBWYeXqBdoOYT0fcwuSIRsnYib6oP90RE=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Y9yDQfMev8ffs/VJOzqe4KRzA4e3weVkT4BjCiur9mO5JgIY+Bz6cTOB1dnw0fkYs FyTzcmaex+7JTOyFPwUStaFhCOnPY0yBHhUrsVgEvcMUIgc8x3zfDNO4956sSuKgRu /rPeb5/WwIMRB1QDRSg1Vou2NTIo6f7/qNfw9mlE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 85289F80559; Mon, 21 Jun 2021 20:09:59 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 578ADF80548; Mon, 21 Jun 2021 20:09:56 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id B2BB8F8052E for ; Mon, 21 Jun 2021 20:09:48 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B2BB8F8052E Received: by m.b4.vu (Postfix, from userid 1000) id 419C461E5F04; Tue, 22 Jun 2021 03:39:46 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:46 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 15/31] ALSA: usb-audio: scarlett2: Fix Level Meter control Message-ID: <5e9a2d5c136270db2d048db53a3b4b6e6d4a63de.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The Level Meter control had a fixed number of channels and therefore only worked with the 18i20 Gen 2. Fix the control to contain the correct number of channels. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 7647b3428093..dde008ea21d7 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -161,10 +161,8 @@ static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = { */ #define SCARLETT2_MUX_MAX 64 -/* Number of meters: - * 18 inputs, 20 outputs, 18 matrix inputs - */ -#define SCARLETT2_NUM_METERS 56 +/* Maximum number of meters (sum of output port counts) */ +#define SCARLETT2_MAX_METERS 56 /* Hardware port types: * - None (no input to mux) @@ -1097,26 +1095,26 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) /* Send USB message to get meter levels */ static int scarlett2_usb_get_meter_levels(struct usb_mixer_interface *mixer, - u16 *levels) + u16 num_meters, u16 *levels) { struct { __le16 pad; __le16 num_meters; __le32 magic; } __packed req; - u32 resp[SCARLETT2_NUM_METERS]; + u32 resp[SCARLETT2_MAX_METERS]; int i, err; req.pad = 0; - req.num_meters = cpu_to_le16(SCARLETT2_NUM_METERS); + req.num_meters = cpu_to_le16(num_meters); req.magic = cpu_to_le32(SCARLETT2_USB_METER_LEVELS_GET_MAGIC); err = scarlett2_usb(mixer, SCARLETT2_USB_GET_METER, - &req, sizeof(req), resp, sizeof(resp)); + &req, sizeof(req), resp, num_meters * sizeof(u32)); if (err < 0) return err; /* copy, convert to u16 */ - for (i = 0; i < SCARLETT2_NUM_METERS; i++) + for (i = 0; i < num_meters; i++) levels[i] = resp[i]; return 0; @@ -2053,10 +2051,11 @@ static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; - u16 meter_levels[SCARLETT2_NUM_METERS]; + u16 meter_levels[SCARLETT2_MAX_METERS]; int i, err; - err = scarlett2_usb_get_meter_levels(elem->head.mixer, meter_levels); + err = scarlett2_usb_get_meter_levels(elem->head.mixer, elem->channels, + meter_levels); if (err < 0) return err; @@ -2076,8 +2075,10 @@ static const struct snd_kcontrol_new scarlett2_meter_ctl = { static int scarlett2_add_meter_ctl(struct usb_mixer_interface *mixer) { + struct scarlett2_data *private = mixer->private_data; + return scarlett2_add_new_ctl(mixer, &scarlett2_meter_ctl, - 0, SCARLETT2_NUM_METERS, + 0, private->num_mux_dsts, "Level Meter", NULL); } From patchwork Mon Jun 21 18:09:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335401 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22456C4743C for ; Mon, 21 Jun 2021 18:16:58 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1827F6115B for ; Mon, 21 Jun 2021 18:16:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1827F6115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 52A8E16C7; Mon, 21 Jun 2021 20:16:05 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 52A8E16C7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299415; bh=6/SLL2sZ3iURVNq9Bz9f1mKSsOKSQI2g1GJoOS2opH8=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=D1ctwh6iuQxe9tECAKsgHFm4rSLze9qJh9t/iOdFqbtvB+FpghJaqcn56w4XKdIr/ QF0Apbxu2czS6tkMazFg4AGJXy+J68NwX5wA9gw9r2C4B/Zxuv6L2mCCvubLMmnchT OL+ABgQ6w2L9CC/hPjGIkRCAxSFqd+Tb6nWP1Tts= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 79422F80571; Mon, 21 Jun 2021 20:10:02 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 19240F80559; Mon, 21 Jun 2021 20:09:58 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C2A72F80536 for ; Mon, 21 Jun 2021 20:09:50 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C2A72F80536 Received: by m.b4.vu (Postfix, from userid 1000) id 51EEE61E5F00; Tue, 22 Jun 2021 03:39:48 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:48 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 16/31] ALSA: usb-audio: scarlett2: Add Gen 3 mixer support Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add mixer support for the Focusrite Scarlett 4i4, 8i6, 18i8, and 18i20 Gen 3 devices. Signed-off-by: Geoffrey D. Bennett Signed-off-by: Takashi Iwai Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 2 +- sound/usb/mixer_quirks.c | 4 + sound/usb/mixer_scarlett_gen2.c | 260 +++++++++++++++++++++++++++++--- 3 files changed, 246 insertions(+), 20 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 428d581f988f..ba4aa1eacb04 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -50,7 +50,7 @@ #include "mixer_quirks.h" #include "power.h" -#define MAX_ID_ELEMS 256 +#define MAX_ID_ELEMS 512 struct usb_audio_term { int id; diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 37ad77524c0b..df7492594e91 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -3060,6 +3060,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x1235, 0x8203): /* Focusrite Scarlett 6i6 2nd Gen */ case USB_ID(0x1235, 0x8204): /* Focusrite Scarlett 18i8 2nd Gen */ case USB_ID(0x1235, 0x8201): /* Focusrite Scarlett 18i20 2nd Gen */ + case USB_ID(0x1235, 0x8212): /* Focusrite Scarlett 4i4 3rd Gen */ + case USB_ID(0x1235, 0x8213): /* Focusrite Scarlett 8i6 3rd Gen */ + case USB_ID(0x1235, 0x8214): /* Focusrite Scarlett 18i8 3rd Gen */ + case USB_ID(0x1235, 0x8215): /* Focusrite Scarlett 18i20 3rd Gen */ err = snd_scarlett_gen2_init(mixer); break; diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index dde008ea21d7..c4bcccb5aecd 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -1,8 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Focusrite Scarlett 6i6/18i8/18i20 Gen 2 Driver for ALSA + * Focusrite Scarlett Gen 2/3 Driver for ALSA * - * Copyright (c) 2018-2019 by Geoffrey D. Bennett + * Supported models: + * - 6i6/18i8/18i20 Gen 2 + * - 4i4/8i6/18i8/18i20 Gen 3 + * + * Copyright (c) 2018-2021 by Geoffrey D. Bennett * * Based on the Scarlett (Gen 1) Driver for ALSA: * @@ -19,10 +23,6 @@ * David Henningsson */ -/* Mixer Interface for the Focusrite Scarlett 6i6/18i8/18i20 Gen 2 audio - * interface. Based on the Gen 1 driver and rewritten. - */ - /* The protocol was reverse engineered by looking at the communication * between Focusrite Control 2.3.4 and the Focusrite(R) Scarlett 18i20 * (firmware 1083) using usbmon in July-August 2018. @@ -32,13 +32,21 @@ * Scarlett 6i6 support added in June 2019 (thanks to Martin Wittmann * for providing usbmon output and testing). * + * Scarlett 4i4/8i6 Gen 3 support added in May 2020 (thanks to Laurent + * Debricon for donating a 4i4 and to Fredrik Unger for providing 8i6 + * usbmon output and testing). + * + * Scarlett 18i8/18i20 Gen 3 support added in June 2020 (thanks to + * Darren Jaeckel, Alex Sedlack, and Clovis Lunel for providing usbmon + * output, protocol traces and testing). + * * Support for loading mixer volume and mux configuration from the * interface during driver initialisation added in May 2021 (thanks to * Vladimir Sadovnikov for figuring out how). * * This ALSA mixer gives access to: * - input, output, mixer-matrix muxes - * - 18x10 mixer-matrix gain stages + * - mixer-matrix gain stages * - gain/volume/mute controls * - level meters * - line/inst level and pad controls @@ -148,21 +156,21 @@ static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = { /* Maximum number of level and pad switches */ #define SCARLETT2_LEVEL_SWITCH_MAX 2 -#define SCARLETT2_PAD_SWITCH_MAX 4 +#define SCARLETT2_PAD_SWITCH_MAX 8 /* Maximum number of inputs to the mixer */ -#define SCARLETT2_INPUT_MIX_MAX 18 +#define SCARLETT2_INPUT_MIX_MAX 25 /* Maximum number of outputs from the mixer */ -#define SCARLETT2_OUTPUT_MIX_MAX 10 +#define SCARLETT2_OUTPUT_MIX_MAX 12 /* Maximum size of the data in the USB mux assignment message: - * 18 inputs, 20 outputs, 18 matrix inputs, 8 spare + * 20 inputs, 20 outputs, 25 matrix inputs, 12 spare */ -#define SCARLETT2_MUX_MAX 64 +#define SCARLETT2_MUX_MAX 77 /* Maximum number of meters (sum of output port counts) */ -#define SCARLETT2_MAX_METERS 56 +#define SCARLETT2_MAX_METERS 65 /* Hardware port types: * - None (no input to mux) @@ -256,7 +264,7 @@ static const struct scarlett2_port scarlett2_ports[SCARLETT2_PORT_TYPE_COUNT] = #define SCARLETT2_MUX_TABLES 3 /* Maximum number of entries in a mux table */ -#define SCARLETT2_MAX_MUX_ENTRIES 7 +#define SCARLETT2_MAX_MUX_ENTRIES 10 /* One entry within mux_assignment defines the port type and range of * ports to add to the set_mux message. The end of the list is marked @@ -475,12 +483,226 @@ static const struct scarlett2_device_info s18i20_gen2_info = { } }, }; +static const struct scarlett2_device_info s4i4_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8212), + + .level_input_count = 2, + .pad_input_count = 2, + + .line_out_descrs = { + "Monitor L", + "Monitor R", + "Headphones L", + "Headphones R", + }, + + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 4, 4 }, + [SCARLETT2_PORT_TYPE_MIX] = { 6, 8 }, + [SCARLETT2_PORT_TYPE_PCM] = { 4, 6 }, + }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 16 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 16 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 16 }, + { 0, 0, 0 }, + } }, +}; + +static const struct scarlett2_device_info s8i6_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8213), + + .level_input_count = 2, + .pad_input_count = 2, + + .line_out_descrs = { + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", + }, + + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 6, 4 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_MIX] = { 8, 8 }, + [SCARLETT2_PORT_TYPE_PCM] = { 6, 10 }, + }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 18 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 18 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 18 }, + { 0, 0, 0 }, + } }, +}; + +static const struct scarlett2_device_info s18i8_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8214), + + .line_out_hw_vol = 1, + .level_input_count = 2, + .pad_input_count = 2, + + .line_out_descrs = { + "Monitor L", + "Monitor R", + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", + "Alt Monitor L", + "Alt Monitor R", + }, + + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 8 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_ADAT] = { 8, 0 }, + [SCARLETT2_PORT_TYPE_MIX] = { 10, 20 }, + [SCARLETT2_PORT_TYPE_PCM] = { 8, 20 }, + }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_PCM, 12, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 10, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 20 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 10 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_PCM, 12, 4 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 10, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 20 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 10 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 20 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 10 }, + { 0, 0, 0 }, + } }, +}; + +static const struct scarlett2_device_info s18i20_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8215), + + .line_out_hw_vol = 1, + .level_input_count = 2, + .pad_input_count = 8, + + .line_out_descrs = { + "Monitor 1 L", + "Monitor 1 R", + "Monitor 2 L", + "Monitor 2 R", + NULL, + NULL, + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", + }, + + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 9, 10 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_ADAT] = { 8, 8 }, + [SCARLETT2_PORT_TYPE_MIX] = { 12, 25 }, + [SCARLETT2_PORT_TYPE_PCM] = { 20, 20 }, + }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_PCM, 10, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_ADAT, 0, 8 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 25 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 12 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_PCM, 10, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_ADAT, 0, 8 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 25 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 10 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 24 }, + { 0, 0, 0 }, + } }, +}; + static const struct scarlett2_device_info *scarlett2_devices[] = { /* Supported Gen 2 devices */ &s6i6_gen2_info, &s18i8_gen2_info, &s18i20_gen2_info, + /* Supported Gen 3 devices */ + &s4i4_gen3_info, + &s8i6_gen3_info, + &s18i8_gen3_info, + &s18i20_gen3_info, + /* End of list */ NULL }; @@ -674,7 +896,7 @@ static int scarlett2_usb( if (err != req_buf_size) { usb_audio_err( mixer->chip, - "Scarlett Gen 2 USB request result cmd %x was %d\n", + "Scarlett Gen 2/3 USB request result cmd %x was %d\n", cmd, err); err = -EINVAL; goto unlock; @@ -691,7 +913,7 @@ static int scarlett2_usb( if (err != resp_buf_size) { usb_audio_err( mixer->chip, - "Scarlett Gen 2 USB response result cmd %x was %d " + "Scarlett Gen 2/3 USB response result cmd %x was %d " "expected %d\n", cmd, err, resp_buf_size); err = -EINVAL; @@ -709,7 +931,7 @@ static int scarlett2_usb( resp->pad) { usb_audio_err( mixer->chip, - "Scarlett Gen 2 USB invalid response; " + "Scarlett Gen 2/3 USB invalid response; " "cmd tx/rx %d/%d seq %d/%d size %d/%d " "error %d pad %d\n", le32_to_cpu(req->cmd), le32_to_cpu(resp->cmd), @@ -2485,7 +2707,7 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer) if (!(chip->setup & SCARLETT2_ENABLE)) { usb_audio_info(chip, - "Focusrite Scarlett Gen 2 Mixer Driver disabled; " + "Focusrite Scarlett Gen 2/3 Mixer Driver disabled; " "use options snd_usb_audio vid=0x%04x pid=0x%04x " "device_setup=1 to enable and report any issues " "to g@b4.vu", @@ -2495,7 +2717,7 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer) } usb_audio_info(chip, - "Focusrite Scarlett Gen 2 Mixer Driver enabled pid=0x%04x", + "Focusrite Scarlett Gen 2/3 Mixer Driver enabled pid=0x%04x", USB_ID_PRODUCT(chip->usb_id)); err = snd_scarlett_gen2_controls_create(mixer); From patchwork Mon Jun 21 18:09:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335399 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 409CDC4743C for ; Mon, 21 Jun 2021 18:16:32 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B8FD96115B for ; Mon, 21 Jun 2021 18:16:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B8FD96115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 4FF1516F8; Mon, 21 Jun 2021 20:15:40 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 4FF1516F8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299390; bh=uJeyzBKQVva5IbwKX18m6y57Gthe/VSbZI5LzDBof3s=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=EopWsqSU6Utq8INSSNJl1jyQp45l4rQwxOCu9B5XYwX9weSbhKniJbjtM4ykm9pSW LrN6gdDWJNy6Y9D8scSBDemolPuhBaI/QS0Nv+ucUJ1CVagdF9oztASHkWcAnulx0Q dAORxKlDdobZcwqyx9+fcdp6H6u5SPDOlr6tTWFM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 387C4F80566; Mon, 21 Jun 2021 20:10:01 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id B65CBF80551; Mon, 21 Jun 2021 20:09:56 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 19EE0F8053E for ; Mon, 21 Jun 2021 20:09:53 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 19EE0F8053E Received: by m.b4.vu (Postfix, from userid 1000) id 95E9961E2871; Tue, 22 Jun 2021 03:39:50 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:50 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 17/31] ALSA: usb-audio: scarlett2: Add support for "input-other" notify Message-ID: <8a845e2e5a45519150aff4446bc910cf80c6f4b3.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Some models allow the level and pad settings to be controlled from the front-panel of the device. For these, the device will send an "input-other" notification to prompt the driver to re-read the status of those settings. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 99 ++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index c4bcccb5aecd..a4f92291b74f 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -318,6 +318,7 @@ struct scarlett2_data { u16 scarlett2_seq; u8 sync_updated; u8 vol_updated; + u8 input_other_updated; u8 sync; u8 master_vol; u8 vol[SCARLETT2_ANALOGUE_MAX]; @@ -331,6 +332,8 @@ struct scarlett2_data { struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX]; struct snd_kcontrol *mute_ctls[SCARLETT2_ANALOGUE_MAX]; struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT]; + struct snd_kcontrol *level_ctls[SCARLETT2_LEVEL_SWITCH_MAX]; + struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX]; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; }; @@ -723,9 +726,10 @@ static int scarlett2_get_port_start_num( /*** USB Interactions ***/ /* Notifications from the interface */ -#define SCARLETT2_USB_NOTIFY_SYNC 0x00000008 -#define SCARLETT2_USB_NOTIFY_DIM_MUTE 0x00200000 -#define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 +#define SCARLETT2_USB_NOTIFY_SYNC 0x00000008 +#define SCARLETT2_USB_NOTIFY_DIM_MUTE 0x00200000 +#define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 +#define SCARLETT2_USB_NOTIFY_INPUT_OTHER 0x00800000 /* Commands for sending/receiving requests/responses */ #define SCARLETT2_USB_CMD_INIT 0 @@ -1740,6 +1744,32 @@ static const struct snd_kcontrol_new scarlett2_sw_hw_enum_ctl = { /*** Line Level/Instrument Level Switch Controls ***/ +static int scarlett2_update_input_other(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + private->input_other_updated = 0; + + if (info->level_input_count) { + int err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_LEVEL_SWITCH, + info->level_input_count, private->level_switch); + if (err < 0) + return err; + } + + if (info->pad_input_count) { + int err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_PAD_SWITCH, + info->pad_input_count, private->pad_switch); + if (err < 0) + return err; + } + + return 0; +} + static int scarlett2_level_enum_ctl_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) { @@ -1754,10 +1784,16 @@ static int scarlett2_level_enum_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; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + mutex_lock(&private->data_mutex); + if (private->input_other_updated) + scarlett2_update_input_other(mixer); ucontrol->value.enumerated.item[0] = private->level_switch[elem->control]; + mutex_unlock(&private->data_mutex); + return 0; } @@ -1806,10 +1842,16 @@ static int scarlett2_pad_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; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + mutex_lock(&private->data_mutex); + if (private->input_other_updated) + scarlett2_update_input_other(mixer); ucontrol->value.integer.value[0] = private->pad_switch[elem->control]; + mutex_unlock(&private->data_mutex); + return 0; } @@ -2020,7 +2062,7 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) for (i = 0; i < info->level_input_count; i++) { snprintf(s, sizeof(s), fmt, i + 1, "Level", "Enum"); err = scarlett2_add_new_ctl(mixer, &scarlett2_level_enum_ctl, - i, 1, s, NULL); + i, 1, s, &private->level_ctls[i]); if (err < 0) return err; } @@ -2029,7 +2071,7 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) for (i = 0; i < info->pad_input_count; i++) { snprintf(s, sizeof(s), fmt, i + 1, "Pad", "Switch"); err = scarlett2_add_new_ctl(mixer, &scarlett2_pad_ctl, - i, 1, s, NULL); + i, 1, s, &private->pad_ctls[i]); if (err < 0) return err; } @@ -2441,25 +2483,9 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) struct scarlett2_usb_volume_status volume_status; int err, i; - if (info->level_input_count) { - err = scarlett2_usb_get_config( - mixer, - SCARLETT2_CONFIG_LEVEL_SWITCH, - info->level_input_count, - private->level_switch); - if (err < 0) - return err; - } - - if (info->pad_input_count) { - err = scarlett2_usb_get_config( - mixer, - SCARLETT2_CONFIG_PAD_SWITCH, - info->pad_input_count, - private->pad_switch); - if (err < 0) - return err; - } + err = scarlett2_update_input_other(mixer); + if (err < 0) + return err; err = scarlett2_update_sync(mixer); if (err < 0) @@ -2573,6 +2599,25 @@ static void scarlett2_notify_dim_mute( &private->mute_ctls[i]->id); } +/* Notify on "input other" change (level/pad) */ +static void scarlett2_notify_input_other( + struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + private->input_other_updated = 1; + + for (i = 0; i < info->level_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->level_ctls[i]->id); + for (i = 0; i < info->pad_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->pad_ctls[i]->id); +} + /* Interrupt callback */ static void scarlett2_notify(struct urb *urb) { @@ -2591,6 +2636,8 @@ static void scarlett2_notify(struct urb *urb) scarlett2_notify_monitor(mixer); if (data & SCARLETT2_USB_NOTIFY_DIM_MUTE) scarlett2_notify_dim_mute(mixer); + if (data & SCARLETT2_USB_NOTIFY_INPUT_OTHER) + scarlett2_notify_input_other(mixer); requeue: if (ustatus != -ENOENT && From patchwork Mon Jun 21 18:09:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335403 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E107EC4743C for ; Mon, 21 Jun 2021 18:17:12 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 14E25611BD for ; Mon, 21 Jun 2021 18:17:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 14E25611BD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id ACE231706; Mon, 21 Jun 2021 20:16:20 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz ACE231706 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299430; bh=25N+hSepopggMZUg+sz4SYSdCvRfnC/IPhhNwEYkWiE=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=JvO63NUof/jUVxY+D6r/YHpVk0k1M08s/Se55YgJkSTo+stxkdE0/X50DpGjoPuk1 8duqn9HYJe0gmCGXEFu0Vt+/PpbIvB93wnCqRce7rnvTp2W7vHuxBw8c81+5X6k9Ii xQgHqxjIB7B3Z6/kc7lH4ccGFVSEdpBMP5vKkZp8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id DF76FF8057B; Mon, 21 Jun 2021 20:10:03 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id B38CAF8055B; Mon, 21 Jun 2021 20:09:58 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 5902FF8052E for ; Mon, 21 Jun 2021 20:09:55 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 5902FF8052E Received: by m.b4.vu (Postfix, from userid 1000) id DC26361E286F; Tue, 22 Jun 2021 03:39:52 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:52 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 18/31] ALSA: usb-audio: scarlett2: Add Gen 3 MSD mode switch Message-ID: <06f41cdc8c843a1c0ab0f7a1c01160ebbe7a7cdb.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add a control to disable the Gen 3 MSD mode so that the full functionality of the device is available. Don't create the other controls until MSD mode is disabled. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 120 +++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 3 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index a4f92291b74f..6995d692c6b2 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -44,12 +44,13 @@ * interface during driver initialisation added in May 2021 (thanks to * Vladimir Sadovnikov for figuring out how). * - * This ALSA mixer gives access to: + * This ALSA mixer gives access to (model-dependent): * - input, output, mixer-matrix muxes * - mixer-matrix gain stages * - gain/volume/mute controls * - level meters * - line/inst level and pad controls + * - disable/enable MSD mode * * * /--------------\ 18chn 20chn /--------------\ @@ -102,6 +103,14 @@ * \--------------/ * * + * Gen 3 devices have a Mass Storage Device (MSD) mode where a small + * disk with registration and driver download information is presented + * to the host. To access the full functionality of the device without + * proprietary software, MSD mode can be disabled by: + * - holding down the 48V button for five seconds while powering on + * the device, or + * - using this driver and alsamixer to change the "MSD Mode" setting + * to Off and power-cycling the device */ #include @@ -120,6 +129,9 @@ /* device_setup value to enable */ #define SCARLETT2_ENABLE 0x01 +/* device_setup value to allow turning MSD mode back on */ +#define SCARLETT2_MSD_ENABLE 0x02 + /* some gui mixers can't handle negative ctl values */ #define SCARLETT2_VOLUME_BIAS 127 @@ -279,6 +291,12 @@ struct scarlett2_mux_entry { struct scarlett2_device_info { u32 usb_id; /* USB device identifier */ + /* Gen 3 devices have an internal MSD mode switch that needs + * to be disabled in order to access the full functionality of + * the device. + */ + u8 has_msd_mode; + /* line out hw volume is sw controlled */ u8 line_out_hw_vol; @@ -327,6 +345,7 @@ struct scarlett2_data { u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX]; u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; + u8 msd_switch; struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX]; @@ -489,6 +508,7 @@ static const struct scarlett2_device_info s18i20_gen2_info = { static const struct scarlett2_device_info s4i4_gen3_info = { .usb_id = USB_ID(0x1235, 0x8212), + .has_msd_mode = 1, .level_input_count = 2, .pad_input_count = 2, @@ -530,6 +550,7 @@ static const struct scarlett2_device_info s4i4_gen3_info = { static const struct scarlett2_device_info s8i6_gen3_info = { .usb_id = USB_ID(0x1235, 0x8213), + .has_msd_mode = 1, .level_input_count = 2, .pad_input_count = 2, @@ -578,6 +599,7 @@ static const struct scarlett2_device_info s8i6_gen3_info = { static const struct scarlett2_device_info s18i8_gen3_info = { .usb_id = USB_ID(0x1235, 0x8214), + .has_msd_mode = 1, .line_out_hw_vol = 1, .level_input_count = 2, .pad_input_count = 2, @@ -639,6 +661,7 @@ static const struct scarlett2_device_info s18i8_gen3_info = { static const struct scarlett2_device_info s18i20_gen3_info = { .usb_id = USB_ID(0x1235, 0x8215), + .has_msd_mode = 1, .line_out_hw_vol = 1, .level_input_count = 2, .pad_input_count = 8, @@ -786,7 +809,8 @@ enum { SCARLETT2_CONFIG_SW_HW_SWITCH = 3, SCARLETT2_CONFIG_LEVEL_SWITCH = 4, SCARLETT2_CONFIG_PAD_SWITCH = 5, - SCARLETT2_CONFIG_COUNT = 6 + SCARLETT2_CONFIG_MSD_SWITCH = 6, + SCARLETT2_CONFIG_COUNT = 7 }; /* Location, size, and activation command number for the configuration @@ -817,6 +841,9 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_PAD_SWITCH] = { .offset = 0x84, .size = 1, .activate = 8 }, + + [SCARLETT2_CONFIG_MSD_SWITCH] = { + .offset = 0x9d, .size = 1, .activate = 6 }, }; /* proprietary request/response format */ @@ -1016,7 +1043,8 @@ static int scarlett2_usb_set_config( return err; /* Schedule the change to be written to NVRAM */ - schedule_delayed_work(&private->work, msecs_to_jiffies(2000)); + if (config_item->activate != SCARLETT2_USB_CONFIG_SAVE) + schedule_delayed_work(&private->work, msecs_to_jiffies(2000)); return 0; } @@ -2346,6 +2374,71 @@ static int scarlett2_add_meter_ctl(struct usb_mixer_interface *mixer) "Level Meter", NULL); } +/*** MSD Controls ***/ + +static int scarlett2_msd_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->msd_switch; + return 0; +} + +static int scarlett2_msd_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->msd_switch; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->msd_switch = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MSD_SWITCH, + 0, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_msd_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_msd_ctl_get, + .put = scarlett2_msd_ctl_put, +}; + +static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + if (!info->has_msd_mode) + return 0; + + /* If MSD mode is off, hide the switch by default */ + if (!private->msd_switch && !(mixer->chip->setup & SCARLETT2_MSD_ENABLE)) + return 0; + + /* Add MSD control */ + return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl, + 0, 1, "MSD Mode", NULL); +} + /*** Cleanup/Suspend Callbacks ***/ static void scarlett2_private_free(struct usb_mixer_interface *mixer) @@ -2483,6 +2576,18 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) struct scarlett2_usb_volume_status volume_status; int err, i; + if (info->has_msd_mode) { + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_MSD_SWITCH, + 1, &private->msd_switch); + if (err < 0) + return err; + + /* no other controls are created if MSD mode is on */ + if (private->msd_switch) + return 0; + } + err = scarlett2_update_input_other(mixer); if (err < 0) return err; @@ -2705,6 +2810,15 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer) if (err < 0) return err; + /* Create the MSD control */ + err = scarlett2_add_msd_ctl(mixer); + if (err < 0) + return err; + + /* If MSD mode is enabled, don't create any other controls */ + if (((struct scarlett2_data *)mixer->private_data)->msd_switch) + return 0; + /* Create the analogue output controls */ err = scarlett2_add_line_out_ctls(mixer); if (err < 0) From patchwork Mon Jun 21 18:09:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335449 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 696B2C4743C for ; Mon, 21 Jun 2021 18:18:03 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E1A226100B for ; Mon, 21 Jun 2021 18:18:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E1A226100B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 791E016BB; Mon, 21 Jun 2021 20:17:11 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 791E016BB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299481; bh=XPXwYis85l+2H3wX2hRoWLPZFiJ4+8VSMwn2dqRDaTc=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=XQS4UF8JjwHvKn7NMrgi1v0Wyubw+ORymgydD7r3d86tNMXU4lOh3Ah1NCq1eGMOY wh57vqQCJax9eDVJVKkbLU3ERE/eUt4ME2KURUL/EtymB9gHCvG5uk18XFbBo1fN/c LFqBr8CbvXdiHHzBhHnRVG2SSmbiEEw+yrX1zFGA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id C134EF805AA; Mon, 21 Jun 2021 20:10:10 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 80F38F8057C; Mon, 21 Jun 2021 20:10:04 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id A8168F8055A for ; Mon, 21 Jun 2021 20:09:57 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz A8168F8055A Received: by m.b4.vu (Postfix, from userid 1000) id 2EEF261E287C; Tue, 22 Jun 2021 03:39:55 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:55 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 19/31] ALSA: usb-audio: scarlett2: Move get config above set config Message-ID: <61337880a0eaec60cb6c15e4882435408528694d.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Move scarlett2_usb_get() and scarlett2_usb_get_config() above the functions relating to updating the configuration so that scarlett2_usb_set_config() can call scarlett2_usb_get() in a subsequent patch. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 6995d692c6b2..87a90cafb175 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -985,6 +985,34 @@ static int scarlett2_usb( return err; } +/* Send a USB message to get data; result placed in *buf */ +static int scarlett2_usb_get( + struct usb_mixer_interface *mixer, + int offset, void *buf, int size) +{ + struct { + __le32 offset; + __le32 size; + } __packed req; + + req.offset = cpu_to_le32(offset); + req.size = cpu_to_le32(size); + return scarlett2_usb(mixer, SCARLETT2_USB_GET_DATA, + &req, sizeof(req), buf, size); +} + +/* Send a USB message to get configuration parameters; result placed in *buf */ +static int scarlett2_usb_get_config( + struct usb_mixer_interface *mixer, + int config_item_num, int count, void *buf) +{ + const struct scarlett2_config *config_item = + &scarlett2_config_items[config_item_num]; + int size = config_item->size * count; + + return scarlett2_usb_get(mixer, config_item->offset, buf, size); +} + /* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */ static void scarlett2_config_save(struct usb_mixer_interface *mixer) { @@ -1049,34 +1077,6 @@ static int scarlett2_usb_set_config( return 0; } -/* Send a USB message to get data; result placed in *buf */ -static int scarlett2_usb_get( - struct usb_mixer_interface *mixer, - int offset, void *buf, int size) -{ - struct { - __le32 offset; - __le32 size; - } __packed req; - - req.offset = cpu_to_le32(offset); - req.size = cpu_to_le32(size); - return scarlett2_usb(mixer, SCARLETT2_USB_GET_DATA, - &req, sizeof(req), buf, size); -} - -/* Send a USB message to get configuration parameters; result placed in *buf */ -static int scarlett2_usb_get_config( - struct usb_mixer_interface *mixer, - int config_item_num, int count, void *buf) -{ - const struct scarlett2_config *config_item = - &scarlett2_config_items[config_item_num]; - int size = config_item->size * count; - - return scarlett2_usb_get(mixer, config_item->offset, buf, size); -} - /* Send a USB message to get sync status; result placed in *sync */ static int scarlett2_usb_get_sync_status( struct usb_mixer_interface *mixer, From patchwork Mon Jun 21 18:09:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335447 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C33CC4743C for ; Mon, 21 Jun 2021 18:17:50 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A6A3D611BD for ; Mon, 21 Jun 2021 18:17:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A6A3D611BD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 3419E16E0; Mon, 21 Jun 2021 20:16:58 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 3419E16E0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299468; bh=nIlZS+hAmltGcDwGCsjqTV0Wf0AoJ8ptIARlhUBlnxU=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=cZuYxiSLB2ROBIAXnI3IqT1uSDsaP3sBs4GUvXZ7Pjz/Zw4ShY1sE5+ncy9R9m69+ uiWgl12c+hcOOQJIh3PuD5r+Uwu1JMSTc8Lw0Hfw3oV/CEv6ZxLG8KM/N0YCFD2GnT DisKgIaOJUjUur+DOjMiXKUQolmw1+7kYkHQ8F2M= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 3C23AF801D5; Mon, 21 Jun 2021 20:10:09 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C2914F80579; Mon, 21 Jun 2021 20:10:03 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id B2B30F80563 for ; Mon, 21 Jun 2021 20:09:59 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B2B30F80563 Received: by m.b4.vu (Postfix, from userid 1000) id 3FB1A61E287D; Tue, 22 Jun 2021 03:39:57 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:57 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 20/31] ALSA: usb-audio: scarlett2: Allow bit-level access to config Message-ID: <162ad60730bae6ff52cc492ab5d442d4b2f4b0b1.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add support for accessing configuration values when multiple values are stored in one byte. Needed by the upcoming Solo and 2i2 Gen 3 support. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 68 ++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 87a90cafb175..45b28585dacb 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -814,7 +814,7 @@ enum { }; /* Location, size, and activation command number for the configuration - * parameters + * parameters. Size is in bits and may be 1, 8, or 16. */ struct scarlett2_config { u8 offset; @@ -825,25 +825,25 @@ struct scarlett2_config { static const struct scarlett2_config scarlett2_config_items[SCARLETT2_CONFIG_COUNT] = { [SCARLETT2_CONFIG_DIM_MUTE] = { - .offset = 0x31, .size = 1, .activate = 2 }, + .offset = 0x31, .size = 8, .activate = 2 }, [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = { - .offset = 0x34, .size = 2, .activate = 1 }, + .offset = 0x34, .size = 16, .activate = 1 }, [SCARLETT2_CONFIG_MUTE_SWITCH] = { - .offset = 0x5c, .size = 1, .activate = 1 }, + .offset = 0x5c, .size = 8, .activate = 1 }, [SCARLETT2_CONFIG_SW_HW_SWITCH] = { - .offset = 0x66, .size = 1, .activate = 3 }, + .offset = 0x66, .size = 8, .activate = 3 }, [SCARLETT2_CONFIG_LEVEL_SWITCH] = { - .offset = 0x7c, .size = 1, .activate = 7 }, + .offset = 0x7c, .size = 8, .activate = 7 }, [SCARLETT2_CONFIG_PAD_SWITCH] = { - .offset = 0x84, .size = 1, .activate = 8 }, + .offset = 0x84, .size = 8, .activate = 8 }, [SCARLETT2_CONFIG_MSD_SWITCH] = { - .offset = 0x9d, .size = 1, .activate = 6 }, + .offset = 0x9d, .size = 8, .activate = 6 }, }; /* proprietary request/response format */ @@ -1008,9 +1008,25 @@ static int scarlett2_usb_get_config( { const struct scarlett2_config *config_item = &scarlett2_config_items[config_item_num]; - int size = config_item->size * count; + int size, err, i; + u8 value; - return scarlett2_usb_get(mixer, config_item->offset, buf, size); + /* For byte-sized parameters, retrieve directly into buf */ + if (config_item->size >= 8) { + size = config_item->size / 8 * count; + return scarlett2_usb_get(mixer, config_item->offset, buf, size); + } + + /* For bit-sized parameters, retrieve into value */ + err = scarlett2_usb_get(mixer, config_item->offset, &value, 1); + if (err < 0) + return err; + + /* then unpack from value into buf[] */ + for (i = 0; i < 8 && i < count; i++, value >>= 1) + *(u8 *)buf++ = value & 1; + + return 0; } /* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */ @@ -1047,18 +1063,44 @@ static int scarlett2_usb_set_config( __le32 value; } __packed req; __le32 req2; + int offset, size; int err; struct scarlett2_data *private = mixer->private_data; /* Cancel any pending NVRAM save */ cancel_delayed_work_sync(&private->work); + /* Convert config_item->size in bits to size in bytes and + * calculate offset + */ + if (config_item->size >= 8) { + size = config_item->size / 8; + offset = config_item->offset + index * size; + + /* If updating a bit, retrieve the old value, set/clear the + * bit as needed, and update value + */ + } else { + u8 tmp; + + size = 1; + offset = config_item->offset; + + scarlett2_usb_get(mixer, offset, &tmp, 1); + if (value) + tmp |= (1 << index); + else + tmp &= ~(1 << index); + + value = tmp; + } + /* Send the configuration parameter data */ - req.offset = cpu_to_le32(config_item->offset + index * config_item->size); - req.bytes = cpu_to_le32(config_item->size); + req.offset = cpu_to_le32(offset); + req.bytes = cpu_to_le32(size); req.value = cpu_to_le32(value); err = scarlett2_usb(mixer, SCARLETT2_USB_SET_DATA, - &req, sizeof(u32) * 2 + config_item->size, + &req, sizeof(u32) * 2 + size, NULL, 0); if (err < 0) return err; From patchwork Mon Jun 21 18:09:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335463 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14646C48BC2 for ; Mon, 21 Jun 2021 18:20:50 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7741C61108 for ; Mon, 21 Jun 2021 18:20:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7741C61108 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 05E031757; Mon, 21 Jun 2021 20:19:58 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 05E031757 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299648; bh=xKvOQGQII0mrhClzRN1dR/lzrnubjvu1R7rMjJEbDpU=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=GHfx+Foq1ROFOx2QCwX/bz8CyyWQ4y/RekC1lbwaSk8fdvbg3CjSTv2zrDQ71Sg5B 06dxMF7MxmQ99QOjdD8d7/vcRN59IYoC5OeEyHKErl90Xz0tWvYhis1Dk+H2aEcNiU smqINXFLGucqQ9R8aTz0+FisNMRmCVL4EWomKWvw= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id F061AF805E0; Mon, 21 Jun 2021 20:10:22 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1410CF805C5; Mon, 21 Jun 2021 20:10:18 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 6D2D6F80570 for ; Mon, 21 Jun 2021 20:10:01 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 6D2D6F80570 Received: by m.b4.vu (Postfix, from userid 1000) id F2E5561E5F01; Tue, 22 Jun 2021 03:39:58 +0930 (ACST) Date: Tue, 22 Jun 2021 03:39:58 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 21/31] ALSA: usb-audio: scarlett2: Add support for Solo and 2i2 Gen 3 Message-ID: <67c4ef3ef9fff1f89a7de60fbeb0fceb2d0b3561.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add initial support for the Focusrite Scarlett Solo and 2i2 devices: - They have no mixer - They don't support reporting sync status or levels - The configuration space is laid out differently to the other models - There is no level (line/inst) switch on input 1 of the Solo Co-developed-by: Vladimir Sadovnikov Signed-off-by: Vladimir Sadovnikov Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_quirks.c | 2 + sound/usb/mixer_scarlett_gen2.c | 94 ++++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 12 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index df7492594e91..0a3cb8fd7d00 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -3060,6 +3060,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x1235, 0x8203): /* Focusrite Scarlett 6i6 2nd Gen */ case USB_ID(0x1235, 0x8204): /* Focusrite Scarlett 18i8 2nd Gen */ case USB_ID(0x1235, 0x8201): /* Focusrite Scarlett 18i20 2nd Gen */ + case USB_ID(0x1235, 0x8211): /* Focusrite Scarlett Solo 3rd Gen */ + case USB_ID(0x1235, 0x8210): /* Focusrite Scarlett 2i2 3rd Gen */ case USB_ID(0x1235, 0x8212): /* Focusrite Scarlett 4i4 3rd Gen */ case USB_ID(0x1235, 0x8213): /* Focusrite Scarlett 8i6 3rd Gen */ case USB_ID(0x1235, 0x8214): /* Focusrite Scarlett 18i8 3rd Gen */ diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 45b28585dacb..50a90693482f 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -4,9 +4,10 @@ * * Supported models: * - 6i6/18i8/18i20 Gen 2 - * - 4i4/8i6/18i8/18i20 Gen 3 + * - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3 * * Copyright (c) 2018-2021 by Geoffrey D. Bennett + * Copyright (c) 2020-2021 by Vladimir Sadovnikov * * Based on the Scarlett (Gen 1) Driver for ALSA: * @@ -44,6 +45,9 @@ * interface during driver initialisation added in May 2021 (thanks to * Vladimir Sadovnikov for figuring out how). * + * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander + * Vorona for 2i2 protocol traces). + * * This ALSA mixer gives access to (model-dependent): * - input, output, mixer-matrix muxes * - mixer-matrix gain stages @@ -297,6 +301,11 @@ struct scarlett2_device_info { */ u8 has_msd_mode; + /* Gen 3 devices without a mixer have a different + * configuration set + */ + u8 has_mixer; + /* line out hw volume is sw controlled */ u8 line_out_hw_vol; @@ -305,6 +314,9 @@ struct scarlett2_device_info { */ u8 level_input_count; + /* the first input with a level control (0-based) */ + u8 level_input_first; + /* the number of analogue inputs with a software switchable * 10dB pad control */ @@ -362,6 +374,7 @@ struct scarlett2_data { static const struct scarlett2_device_info s6i6_gen2_info = { .usb_id = USB_ID(0x1235, 0x8203), + .has_mixer = 1, .level_input_count = 2, .pad_input_count = 2, @@ -407,6 +420,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, .level_input_count = 2, .pad_input_count = 4, @@ -455,6 +469,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, .line_out_hw_vol = 1, .line_out_descrs = { @@ -505,10 +520,26 @@ static const struct scarlett2_device_info s18i20_gen2_info = { } }, }; +static const struct scarlett2_device_info solo_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8211), + + .has_msd_mode = 1, + .level_input_count = 1, + .level_input_first = 1, +}; + +static const struct scarlett2_device_info s2i2_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8210), + + .has_msd_mode = 1, + .level_input_count = 2, +}; + static const struct scarlett2_device_info s4i4_gen3_info = { .usb_id = USB_ID(0x1235, 0x8212), .has_msd_mode = 1, + .has_mixer = 1, .level_input_count = 2, .pad_input_count = 2, @@ -551,6 +582,7 @@ static const struct scarlett2_device_info s8i6_gen3_info = { .usb_id = USB_ID(0x1235, 0x8213), .has_msd_mode = 1, + .has_mixer = 1, .level_input_count = 2, .pad_input_count = 2, @@ -600,6 +632,7 @@ static const struct scarlett2_device_info s18i8_gen3_info = { .usb_id = USB_ID(0x1235, 0x8214), .has_msd_mode = 1, + .has_mixer = 1, .line_out_hw_vol = 1, .level_input_count = 2, .pad_input_count = 2, @@ -662,6 +695,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = { .usb_id = USB_ID(0x1235, 0x8215), .has_msd_mode = 1, + .has_mixer = 1, .line_out_hw_vol = 1, .level_input_count = 2, .pad_input_count = 8, @@ -724,6 +758,8 @@ static const struct scarlett2_device_info *scarlett2_devices[] = { &s18i20_gen2_info, /* Supported Gen 3 devices */ + &solo_gen3_info, + &s2i2_gen3_info, &s4i4_gen3_info, &s8i6_gen3_info, &s18i8_gen3_info, @@ -776,7 +812,7 @@ static int scarlett2_get_port_start_num( #define SCARLETT2_USB_VOLUME_STATUS_OFFSET 0x31 #define SCARLETT2_USB_METER_LEVELS_GET_MAGIC 1 -/* volume status is read together (matches scarlett2_config_items[]) */ +/* volume status is read together (matches scarlett2_config_items[1]) */ struct scarlett2_usb_volume_status { /* dim/mute buttons */ u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; @@ -822,8 +858,22 @@ 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[SCARLETT2_CONFIG_COUNT] = { + scarlett2_config_items[2][SCARLETT2_CONFIG_COUNT] = + +/* Devices without a mixer (Solo and 2i2 Gen 3) */ +{ { + [SCARLETT2_CONFIG_MSD_SWITCH] = { + .offset = 0x04, .size = 8, .activate = 6 }, + + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { + .offset = 0x08, .size = 1, .activate = 7 }, + +/* Devices with a mixer (Gen 2 and all other Gen 3) */ +}, { [SCARLETT2_CONFIG_DIM_MUTE] = { .offset = 0x31, .size = 8, .activate = 2 }, @@ -844,7 +894,7 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_MSD_SWITCH] = { .offset = 0x9d, .size = 8, .activate = 6 }, -}; +} }; /* proprietary request/response format */ struct scarlett2_usb_packet { @@ -1006,8 +1056,10 @@ static int scarlett2_usb_get_config( struct usb_mixer_interface *mixer, int config_item_num, int count, void *buf) { + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; const struct scarlett2_config *config_item = - &scarlett2_config_items[config_item_num]; + &scarlett2_config_items[info->has_mixer][config_item_num]; int size, err, i; u8 value; @@ -1055,8 +1107,10 @@ static int scarlett2_usb_set_config( struct usb_mixer_interface *mixer, int config_item_num, int index, int value) { + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; const struct scarlett2_config *config_item = - &scarlett2_config_items[config_item_num]; + &scarlett2_config_items[info->has_mixer][config_item_num]; struct { __le32 offset; __le32 bytes; @@ -1065,7 +1119,6 @@ static int scarlett2_usb_set_config( __le32 req2; int offset, size; int err; - struct scarlett2_data *private = mixer->private_data; /* Cancel any pending NVRAM save */ cancel_delayed_work_sync(&private->work); @@ -1506,6 +1559,10 @@ 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) + return 0; + return scarlett2_add_new_ctl(mixer, &scarlett2_sync_ctl, 0, 1, "Sync Status", &private->sync_ctl); } @@ -1824,7 +1881,8 @@ static int scarlett2_update_input_other(struct usb_mixer_interface *mixer) if (info->level_input_count) { int err = scarlett2_usb_get_config( mixer, SCARLETT2_CONFIG_LEVEL_SWITCH, - info->level_input_count, private->level_switch); + info->level_input_count + info->level_input_first, + private->level_switch); if (err < 0) return err; } @@ -1856,12 +1914,14 @@ static int scarlett2_level_enum_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + int index = elem->control + info->level_input_first; mutex_lock(&private->data_mutex); if (private->input_other_updated) scarlett2_update_input_other(mixer); - ucontrol->value.enumerated.item[0] = - private->level_switch[elem->control]; + ucontrol->value.enumerated.item[0] = private->level_switch[index]; mutex_unlock(&private->data_mutex); return 0; @@ -1873,8 +1933,9 @@ static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; - int index = elem->control; + int index = elem->control + info->level_input_first; int oval, val, err = 0; mutex_lock(&private->data_mutex); @@ -2130,7 +2191,8 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) /* Add input level (line/inst) controls */ for (i = 0; i < info->level_input_count; i++) { - snprintf(s, sizeof(s), fmt, i + 1, "Level", "Enum"); + snprintf(s, sizeof(s), fmt, i + 1 + info->level_input_first, + "Level", "Enum"); err = scarlett2_add_new_ctl(mixer, &scarlett2_level_enum_ctl, i, 1, s, &private->level_ctls[i]); if (err < 0) @@ -2411,6 +2473,10 @@ 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) + return 0; + return scarlett2_add_new_ctl(mixer, &scarlett2_meter_ctl, 0, private->num_mux_dsts, "Level Meter", NULL); @@ -2634,6 +2700,10 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) if (err < 0) return err; + /* the rest of the configuration is for devices with a mixer */ + if (!info->has_mixer) + return 0; + err = scarlett2_update_sync(mixer); if (err < 0) return err; From patchwork Mon Jun 21 18:10:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335451 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B69FAC48BC2 for ; Mon, 21 Jun 2021 18:18:28 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 424836100B for ; Mon, 21 Jun 2021 18:18:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 424836100B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id BD787170B; Mon, 21 Jun 2021 20:17:36 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz BD787170B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299506; bh=PA0KmEER4peSIDoQEBPGxL4EIkBzwlU8wDEH5/u9qdk=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=BAmyGK/CfWonP27iWzQM4K2nR4rsvx5WjyfPHZNwzIw+iAMRztddGJst+aJhLAIM2 BizcSH6IPaAkx5GVCR9Yn8ty7pH+rGuct42xxI+aAgGh3Qvb0+sW6kjZzoCFPPcEHN lO1/vGnmW+dKmVBb7Y3OS+D9wPidV00trqqqQ1Lk= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 5A201F80137; Mon, 21 Jun 2021 20:10:12 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id B19C2F805A0; Mon, 21 Jun 2021 20:10:06 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 64281F8057A for ; Mon, 21 Jun 2021 20:10:03 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 64281F8057A Received: by m.b4.vu (Postfix, from userid 1000) id BECC461E5F02; Tue, 22 Jun 2021 03:40:00 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:00 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 22/31] ALSA: usb-audio: scarlett2: Add "air" switch support Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Some inputs on Gen 3 models have an "air" feature which can be enabled from the driver or (model-dependent) from the front panel. Add support for getting and setting the state of those switches. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 106 ++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 6 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 50a90693482f..a8c5a28f21c9 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -53,7 +53,7 @@ * - mixer-matrix gain stages * - gain/volume/mute controls * - level meters - * - line/inst level and pad controls + * - line/inst level, pad, and air controls * - disable/enable MSD mode * * @@ -173,6 +173,7 @@ static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = { /* Maximum number of level and pad switches */ #define SCARLETT2_LEVEL_SWITCH_MAX 2 #define SCARLETT2_PAD_SWITCH_MAX 8 +#define SCARLETT2_AIR_SWITCH_MAX 8 /* Maximum number of inputs to the mixer */ #define SCARLETT2_INPUT_MIX_MAX 25 @@ -322,6 +323,11 @@ struct scarlett2_device_info { */ u8 pad_input_count; + /* the number of analogue inputs with a software switchable + * "air" control + */ + u8 air_input_count; + /* additional description for the line out volume controls */ const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; @@ -357,6 +363,7 @@ struct scarlett2_data { u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX]; u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; + u8 air_switch[SCARLETT2_AIR_SWITCH_MAX]; u8 msd_switch; struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; @@ -365,6 +372,7 @@ struct scarlett2_data { struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT]; struct snd_kcontrol *level_ctls[SCARLETT2_LEVEL_SWITCH_MAX]; struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX]; + struct snd_kcontrol *air_ctls[SCARLETT2_AIR_SWITCH_MAX]; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; }; @@ -526,6 +534,7 @@ static const struct scarlett2_device_info solo_gen3_info = { .has_msd_mode = 1, .level_input_count = 1, .level_input_first = 1, + .air_input_count = 1, }; static const struct scarlett2_device_info s2i2_gen3_info = { @@ -533,6 +542,7 @@ static const struct scarlett2_device_info s2i2_gen3_info = { .has_msd_mode = 1, .level_input_count = 2, + .air_input_count = 2, }; static const struct scarlett2_device_info s4i4_gen3_info = { @@ -542,6 +552,7 @@ static const struct scarlett2_device_info s4i4_gen3_info = { .has_mixer = 1, .level_input_count = 2, .pad_input_count = 2, + .air_input_count = 2, .line_out_descrs = { "Monitor L", @@ -585,6 +596,7 @@ static const struct scarlett2_device_info s8i6_gen3_info = { .has_mixer = 1, .level_input_count = 2, .pad_input_count = 2, + .air_input_count = 2, .line_out_descrs = { "Headphones 1 L", @@ -636,6 +648,7 @@ static const struct scarlett2_device_info s18i8_gen3_info = { .line_out_hw_vol = 1, .level_input_count = 2, .pad_input_count = 2, + .air_input_count = 4, .line_out_descrs = { "Monitor L", @@ -699,6 +712,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = { .line_out_hw_vol = 1, .level_input_count = 2, .pad_input_count = 8, + .air_input_count = 8, .line_out_descrs = { "Monitor 1 L", @@ -846,7 +860,8 @@ enum { SCARLETT2_CONFIG_LEVEL_SWITCH = 4, SCARLETT2_CONFIG_PAD_SWITCH = 5, SCARLETT2_CONFIG_MSD_SWITCH = 6, - SCARLETT2_CONFIG_COUNT = 7 + SCARLETT2_CONFIG_AIR_SWITCH = 7, + SCARLETT2_CONFIG_COUNT = 8 }; /* Location, size, and activation command number for the configuration @@ -872,6 +887,9 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_LEVEL_SWITCH] = { .offset = 0x08, .size = 1, .activate = 7 }, + [SCARLETT2_CONFIG_AIR_SWITCH] = { + .offset = 0x09, .size = 1, .activate = 8 }, + /* Devices with a mixer (Gen 2 and all other Gen 3) */ }, { [SCARLETT2_CONFIG_DIM_MUTE] = { @@ -892,6 +910,9 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_PAD_SWITCH] = { .offset = 0x84, .size = 8, .activate = 8 }, + [SCARLETT2_CONFIG_AIR_SWITCH] = { + .offset = 0x8c, .size = 8, .activate = 8 }, + [SCARLETT2_CONFIG_MSD_SWITCH] = { .offset = 0x9d, .size = 8, .activate = 6 }, } }; @@ -1100,9 +1121,7 @@ static void scarlett2_config_save_work(struct work_struct *work) scarlett2_config_save(private->mixer); } -/* Send a USB message to set a configuration parameter (volume level, - * sw/hw volume switch, line/inst level switch, or pad switch) - */ +/* Send a USB message to set a SCARLETT2_CONFIG_* parameter */ static int scarlett2_usb_set_config( struct usb_mixer_interface *mixer, int config_item_num, int index, int value) @@ -1895,6 +1914,14 @@ static int scarlett2_update_input_other(struct usb_mixer_interface *mixer) return err; } + if (info->air_input_count) { + int err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_AIR_SWITCH, + info->air_input_count, private->air_switch); + if (err < 0) + return err; + } + return 0; } @@ -2025,6 +2052,61 @@ static const struct snd_kcontrol_new scarlett2_pad_ctl = { .put = scarlett2_pad_ctl_put, }; +/*** Air Switch Controls ***/ + +static int scarlett2_air_ctl_get(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; + + mutex_lock(&private->data_mutex); + if (private->input_other_updated) + scarlett2_update_input_other(mixer); + ucontrol->value.integer.value[0] = private->air_switch[elem->control]; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static int scarlett2_air_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 index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->air_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->air_switch[index] = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_AIR_SWITCH, + index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_air_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_air_ctl_get, + .put = scarlett2_air_ctl_put, +}; + /*** Dim/Mute Controls ***/ static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl, @@ -2208,6 +2290,15 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) return err; } + /* Add input air controls */ + for (i = 0; i < info->air_input_count; i++) { + snprintf(s, sizeof(s), fmt, i + 1, "Air", "Switch"); + err = scarlett2_add_new_ctl(mixer, &scarlett2_air_ctl, + i, 1, s, &private->air_ctls[i]); + if (err < 0) + return err; + } + return 0; } @@ -2816,7 +2907,7 @@ static void scarlett2_notify_dim_mute( &private->mute_ctls[i]->id); } -/* Notify on "input other" change (level/pad) */ +/* Notify on "input other" change (level/pad/air) */ static void scarlett2_notify_input_other( struct usb_mixer_interface *mixer) { @@ -2833,6 +2924,9 @@ static void scarlett2_notify_input_other( for (i = 0; i < info->pad_input_count; i++) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &private->pad_ctls[i]->id); + for (i = 0; i < info->air_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->air_ctls[i]->id); } /* Interrupt callback */ From patchwork Mon Jun 21 18:10:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335453 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A304FC4743C for ; Mon, 21 Jun 2021 18:18:46 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 29133611BD for ; Mon, 21 Jun 2021 18:18:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 29133611BD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id B79B5172F; Mon, 21 Jun 2021 20:17:54 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz B79B5172F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299524; bh=5l7+hpDk/BP7R3BZ1TcZtAM2Wv6AsnuFtmX3zPYTQQc=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=BbC5IMt8B35wOqtou8/8fAmflpmriQ80b+HBEfQW/2kFMNPoUM1OxI7oGR114pL3L FDfQrbne7K+PX9eEa2Y0N1fGyGa3ww8doVYlxh6pUSiYTcaWoTFinnuPLmsrFyovNe AZ8Oq6AiJLdjsYypECPY8q9YMfq+Ye0cVjWFLyaE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 6984BF805AF; Mon, 21 Jun 2021 20:10:14 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C8662F805A1; Mon, 21 Jun 2021 20:10:08 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id DC70FF8057D for ; Mon, 21 Jun 2021 20:10:04 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz DC70FF8057D Received: by m.b4.vu (Postfix, from userid 1000) id 6344161E286F; Tue, 22 Jun 2021 03:40:02 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:02 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 23/31] ALSA: usb-audio: scarlett2: Add phantom power switch support Message-ID: <7338519d2572359f5c415b8909ed72c91c22af06.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Some inputs on Gen 3 models support software-selectable phantom power. Add support for getting and setting the state of those switches and the "Phantom Power Persistence" switch. Co-developed-by: Vladimir Sadovnikov Signed-off-by: Vladimir Sadovnikov Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 197 +++++++++++++++++++++++++++++++- 1 file changed, 196 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index a8c5a28f21c9..87672e6b4505 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -48,12 +48,15 @@ * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander * Vorona for 2i2 protocol traces). * + * Support for phantom power added in May 2021. + * * This ALSA mixer gives access to (model-dependent): * - input, output, mixer-matrix muxes * - mixer-matrix gain stages * - gain/volume/mute controls * - level meters * - line/inst level, pad, and air controls + * - phantom power controls * - disable/enable MSD mode * * @@ -174,6 +177,7 @@ static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = { #define SCARLETT2_LEVEL_SWITCH_MAX 2 #define SCARLETT2_PAD_SWITCH_MAX 8 #define SCARLETT2_AIR_SWITCH_MAX 8 +#define SCARLETT2_PHANTOM_SWITCH_MAX 2 /* Maximum number of inputs to the mixer */ #define SCARLETT2_INPUT_MIX_MAX 25 @@ -328,6 +332,12 @@ struct scarlett2_device_info { */ u8 air_input_count; + /* the number of phantom (48V) software switchable controls */ + u8 phantom_count; + + /* the number of inputs each phantom switch controls */ + u8 inputs_per_phantom; + /* additional description for the line out volume controls */ const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; @@ -364,6 +374,8 @@ struct scarlett2_data { u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; u8 air_switch[SCARLETT2_AIR_SWITCH_MAX]; + u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX]; + u8 phantom_persistence; u8 msd_switch; struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; @@ -373,6 +385,7 @@ struct scarlett2_data { struct snd_kcontrol *level_ctls[SCARLETT2_LEVEL_SWITCH_MAX]; struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX]; struct snd_kcontrol *air_ctls[SCARLETT2_AIR_SWITCH_MAX]; + struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX]; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; }; @@ -535,6 +548,8 @@ static const struct scarlett2_device_info solo_gen3_info = { .level_input_count = 1, .level_input_first = 1, .air_input_count = 1, + .phantom_count = 1, + .inputs_per_phantom = 1, }; static const struct scarlett2_device_info s2i2_gen3_info = { @@ -543,6 +558,8 @@ static const struct scarlett2_device_info s2i2_gen3_info = { .has_msd_mode = 1, .level_input_count = 2, .air_input_count = 2, + .phantom_count = 1, + .inputs_per_phantom = 2, }; static const struct scarlett2_device_info s4i4_gen3_info = { @@ -553,6 +570,8 @@ static const struct scarlett2_device_info s4i4_gen3_info = { .level_input_count = 2, .pad_input_count = 2, .air_input_count = 2, + .phantom_count = 1, + .inputs_per_phantom = 2, .line_out_descrs = { "Monitor L", @@ -597,6 +616,8 @@ static const struct scarlett2_device_info s8i6_gen3_info = { .level_input_count = 2, .pad_input_count = 2, .air_input_count = 2, + .phantom_count = 1, + .inputs_per_phantom = 2, .line_out_descrs = { "Headphones 1 L", @@ -649,6 +670,8 @@ static const struct scarlett2_device_info s18i8_gen3_info = { .level_input_count = 2, .pad_input_count = 2, .air_input_count = 4, + .phantom_count = 2, + .inputs_per_phantom = 2, .line_out_descrs = { "Monitor L", @@ -713,6 +736,8 @@ static const struct scarlett2_device_info s18i20_gen3_info = { .level_input_count = 2, .pad_input_count = 8, .air_input_count = 8, + .phantom_count = 2, + .inputs_per_phantom = 4, .line_out_descrs = { "Monitor 1 L", @@ -861,7 +886,9 @@ enum { SCARLETT2_CONFIG_PAD_SWITCH = 5, SCARLETT2_CONFIG_MSD_SWITCH = 6, SCARLETT2_CONFIG_AIR_SWITCH = 7, - SCARLETT2_CONFIG_COUNT = 8 + SCARLETT2_CONFIG_PHANTOM_SWITCH = 8, + SCARLETT2_CONFIG_PHANTOM_PERSISTENCE = 9, + SCARLETT2_CONFIG_COUNT = 10 }; /* Location, size, and activation command number for the configuration @@ -884,6 +911,12 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_MSD_SWITCH] = { .offset = 0x04, .size = 8, .activate = 6 }, + [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = { + .offset = 0x05, .size = 8, .activate = 6 }, + + [SCARLETT2_CONFIG_PHANTOM_SWITCH] = { + .offset = 0x06, .size = 8, .activate = 3 }, + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { .offset = 0x08, .size = 1, .activate = 7 }, @@ -913,8 +946,14 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_AIR_SWITCH] = { .offset = 0x8c, .size = 8, .activate = 8 }, + [SCARLETT2_CONFIG_PHANTOM_SWITCH] = { + .offset = 0x9c, .size = 1, .activate = 8 }, + [SCARLETT2_CONFIG_MSD_SWITCH] = { .offset = 0x9d, .size = 8, .activate = 6 }, + + [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = { + .offset = 0x9e, .size = 8, .activate = 6 }, } }; /* proprietary request/response format */ @@ -1922,6 +1961,20 @@ static int scarlett2_update_input_other(struct usb_mixer_interface *mixer) return err; } + if (info->phantom_count) { + int err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH, + info->phantom_count, private->phantom_switch); + if (err < 0) + return err; + + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE, + 1, &private->phantom_persistence); + if (err < 0) + return err; + } + return 0; } @@ -2107,6 +2160,111 @@ static const struct snd_kcontrol_new scarlett2_air_ctl = { .put = scarlett2_air_ctl_put, }; +/*** Phantom Switch Controls ***/ + +static int scarlett2_phantom_ctl_get(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; + + mutex_lock(&private->data_mutex); + if (private->input_other_updated) + scarlett2_update_input_other(mixer); + ucontrol->value.integer.value[0] = + private->phantom_switch[elem->control]; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static int scarlett2_phantom_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 index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->phantom_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->phantom_switch[index] = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH, + index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_phantom_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_phantom_ctl_get, + .put = scarlett2_phantom_ctl_put, +}; + +/*** Phantom Persistence Control ***/ + +static int scarlett2_phantom_persistence_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->phantom_persistence; + return 0; +} + +static int scarlett2_phantom_persistence_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 index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->phantom_persistence; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->phantom_persistence = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE, index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_phantom_persistence_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_phantom_persistence_ctl_get, + .put = scarlett2_phantom_persistence_ctl_put, +}; + /*** Dim/Mute Controls ***/ static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl, @@ -2270,6 +2428,7 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) int err, i; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; const char *fmt = "Line In %d %s Capture %s"; + const char *fmt2 = "Line In %d-%d %s Capture %s"; /* Add input level (line/inst) controls */ for (i = 0; i < info->level_input_count; i++) { @@ -2299,6 +2458,39 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) return err; } + /* Add input phantom controls */ + if (info->inputs_per_phantom == 1) { + for (i = 0; i < info->phantom_count; i++) { + snprintf(s, sizeof(s), fmt, i + 1, + "Phantom Power", "Switch"); + err = scarlett2_add_new_ctl( + mixer, &scarlett2_phantom_ctl, + i, 1, s, &private->phantom_ctls[i]); + if (err < 0) + return err; + } + } else if (info->inputs_per_phantom > 1) { + for (i = 0; i < info->phantom_count; i++) { + int from = i * info->inputs_per_phantom + 1; + int to = (i + 1) * info->inputs_per_phantom; + + snprintf(s, sizeof(s), fmt2, from, to, + "Phantom Power", "Switch"); + err = scarlett2_add_new_ctl( + mixer, &scarlett2_phantom_ctl, + i, 1, s, &private->phantom_ctls[i]); + if (err < 0) + return err; + } + } + if (info->phantom_count) { + err = scarlett2_add_new_ctl( + mixer, &scarlett2_phantom_persistence_ctl, 0, 1, + "Phantom Power Persistence Capture Switch", NULL); + if (err < 0) + return err; + } + return 0; } @@ -2927,6 +3119,9 @@ static void scarlett2_notify_input_other( for (i = 0; i < info->air_input_count; i++) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &private->air_ctls[i]->id); + for (i = 0; i < info->phantom_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->phantom_ctls[i]->id); } /* Interrupt callback */ From patchwork Mon Jun 21 18:10:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335455 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4EEE0C4743C for ; Mon, 21 Jun 2021 18:19:06 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C51EC6115B for ; Mon, 21 Jun 2021 18:19:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C51EC6115B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 5956C1738; Mon, 21 Jun 2021 20:18:14 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 5956C1738 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299544; bh=dPzHDTMWfHbSOcKukk2TtwkMAnGRjod75zKE5qvkBUY=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=hE06CmC+6B+v3Sp3pzMCW3pmBtPJWcisrcJnGigob7rxw7p3Ml6BiAPghVItQ+1PL V9J7TnvrB0hakxOv0ykHZq5cuaeebGkbwk4Gkb1LrTvjEcdBzdLUlXR1nROQRgQgEV xoPQFxBKzPx5k+7uNLCxukX4jRYpQdIps2JVjwcQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id C190CF805AB; Mon, 21 Jun 2021 20:10:15 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 69650F805A8; Mon, 21 Jun 2021 20:10:10 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 6D09AF8016B for ; Mon, 21 Jun 2021 20:10:06 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 6D09AF8016B Received: by m.b4.vu (Postfix, from userid 1000) id EBDA761E287F; Tue, 22 Jun 2021 03:40:03 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:03 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 24/31] ALSA: usb-audio: scarlett2: Add direct monitor support Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The Solo and 2i2 devices don't have a mixer but they do have a "direct monitor" switch. Add support for getting and setting the state of this switch. Co-developed-by: Vladimir Sadovnikov Signed-off-by: Vladimir Sadovnikov Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 161 ++++++++++++++++++++++++++++++-- 1 file changed, 154 insertions(+), 7 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 87672e6b4505..94de63847169 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -48,7 +48,8 @@ * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander * Vorona for 2i2 protocol traces). * - * Support for phantom power added in May 2021. + * Support for phantom power and direct monitoring added in May-June + * 2021. * * This ALSA mixer gives access to (model-dependent): * - input, output, mixer-matrix muxes @@ -56,7 +57,7 @@ * - gain/volume/mute controls * - level meters * - line/inst level, pad, and air controls - * - phantom power controls + * - phantom power and direct monitor controls * - disable/enable MSD mode * * @@ -338,6 +339,11 @@ struct scarlett2_device_info { /* the number of inputs each phantom switch controls */ u8 inputs_per_phantom; + /* the number of direct monitor options + * (0 = none, 1 = mono only, 2 = mono/stereo) + */ + u8 direct_monitor; + /* additional description for the line out volume controls */ const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; @@ -365,6 +371,7 @@ struct scarlett2_data { u8 sync_updated; u8 vol_updated; u8 input_other_updated; + u8 monitor_other_updated; u8 sync; u8 master_vol; u8 vol[SCARLETT2_ANALOGUE_MAX]; @@ -376,6 +383,7 @@ struct scarlett2_data { u8 air_switch[SCARLETT2_AIR_SWITCH_MAX]; u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX]; u8 phantom_persistence; + u8 direct_monitor_switch; u8 msd_switch; struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; @@ -386,6 +394,7 @@ struct scarlett2_data { struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX]; struct snd_kcontrol *air_ctls[SCARLETT2_AIR_SWITCH_MAX]; struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX]; + struct snd_kcontrol *direct_monitor_ctl; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; }; @@ -550,6 +559,7 @@ static const struct scarlett2_device_info solo_gen3_info = { .air_input_count = 1, .phantom_count = 1, .inputs_per_phantom = 1, + .direct_monitor = 1, }; static const struct scarlett2_device_info s2i2_gen3_info = { @@ -560,6 +570,7 @@ static const struct scarlett2_device_info s2i2_gen3_info = { .air_input_count = 2, .phantom_count = 1, .inputs_per_phantom = 2, + .direct_monitor = 2, }; static const struct scarlett2_device_info s4i4_gen3_info = { @@ -824,10 +835,11 @@ static int scarlett2_get_port_start_num( /*** USB Interactions ***/ /* Notifications from the interface */ -#define SCARLETT2_USB_NOTIFY_SYNC 0x00000008 -#define SCARLETT2_USB_NOTIFY_DIM_MUTE 0x00200000 -#define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 -#define SCARLETT2_USB_NOTIFY_INPUT_OTHER 0x00800000 +#define SCARLETT2_USB_NOTIFY_SYNC 0x00000008 +#define SCARLETT2_USB_NOTIFY_DIM_MUTE 0x00200000 +#define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 +#define SCARLETT2_USB_NOTIFY_INPUT_OTHER 0x00800000 +#define SCARLETT2_USB_NOTIFY_MONITOR_OTHER 0x01000000 /* Commands for sending/receiving requests/responses */ #define SCARLETT2_USB_CMD_INIT 0 @@ -888,7 +900,8 @@ enum { SCARLETT2_CONFIG_AIR_SWITCH = 7, SCARLETT2_CONFIG_PHANTOM_SWITCH = 8, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE = 9, - SCARLETT2_CONFIG_COUNT = 10 + SCARLETT2_CONFIG_DIRECT_MONITOR = 10, + SCARLETT2_CONFIG_COUNT = 11 }; /* Location, size, and activation command number for the configuration @@ -917,6 +930,9 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_PHANTOM_SWITCH] = { .offset = 0x06, .size = 8, .activate = 3 }, + [SCARLETT2_CONFIG_DIRECT_MONITOR] = { + .offset = 0x07, .size = 8, .activate = 4 }, + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { .offset = 0x08, .size = 1, .activate = 7 }, @@ -2265,6 +2281,112 @@ static const struct snd_kcontrol_new scarlett2_phantom_persistence_ctl = { .put = scarlett2_phantom_persistence_ctl_put, }; +/*** Direct Monitor Control ***/ + +static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + private->monitor_other_updated = 0; + + if (info->direct_monitor) + return scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, + 1, &private->direct_monitor_switch); + + return 0; +} + +static int scarlett2_direct_monitor_ctl_get( + 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 = elem->head.mixer->private_data; + + mutex_lock(&private->data_mutex); + if (private->monitor_other_updated) + scarlett2_update_monitor_other(mixer); + ucontrol->value.enumerated.item[0] = private->direct_monitor_switch; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static int scarlett2_direct_monitor_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 index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->direct_monitor_switch; + val = min(ucontrol->value.enumerated.item[0], 2U); + + if (oval == val) + goto unlock; + + private->direct_monitor_switch = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, index, val); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static int scarlett2_direct_monitor_stereo_enum_ctl_info( + struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + static const char *const values[3] = { + "Off", "Mono", "Stereo" + }; + + return snd_ctl_enum_info(uinfo, 1, 3, values); +} + +/* Direct Monitor for Solo is mono-only and only needs a boolean control + * Direct Monitor for 2i2 is selectable between Off/Mono/Stereo + */ +static const struct snd_kcontrol_new scarlett2_direct_monitor_ctl[2] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_direct_monitor_ctl_get, + .put = scarlett2_direct_monitor_ctl_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_direct_monitor_stereo_enum_ctl_info, + .get = scarlett2_direct_monitor_ctl_get, + .put = scarlett2_direct_monitor_ctl_put, + } +}; + +static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + if (!info->direct_monitor) + return 0; + + return scarlett2_add_new_ctl( + mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1], + 0, 1, "Direct Monitor Playback Switch", + &private->direct_monitor_ctl); +} + /*** Dim/Mute Controls ***/ static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl, @@ -2983,6 +3105,10 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) if (err < 0) return err; + err = scarlett2_update_monitor_other(mixer); + if (err < 0) + return err; + /* the rest of the configuration is for devices with a mixer */ if (!info->has_mixer) return 0; @@ -3124,6 +3250,20 @@ static void scarlett2_notify_input_other( &private->phantom_ctls[i]->id); } +/* Notify on "monitor other" change (direct monitor) */ +static void scarlett2_notify_monitor_other( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + struct snd_card *card = mixer->chip->card; + + private->monitor_other_updated = 1; + + if (private->info->direct_monitor) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->direct_monitor_ctl->id); +} + /* Interrupt callback */ static void scarlett2_notify(struct urb *urb) { @@ -3144,6 +3284,8 @@ static void scarlett2_notify(struct urb *urb) scarlett2_notify_dim_mute(mixer); if (data & SCARLETT2_USB_NOTIFY_INPUT_OTHER) scarlett2_notify_input_other(mixer); + if (data & SCARLETT2_USB_NOTIFY_MONITOR_OTHER) + scarlett2_notify_monitor_other(mixer); requeue: if (ustatus != -ENOENT && @@ -3250,6 +3392,11 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer) if (err < 0) return err; + /* Create the direct monitor control */ + err = scarlett2_add_direct_monitor_ctl(mixer); + if (err < 0) + return err; + /* Set up the interrupt polling */ err = scarlett2_init_notify(mixer); if (err < 0) From patchwork Mon Jun 21 18:10:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335457 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2FAEC4743C for ; Mon, 21 Jun 2021 18:19:32 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7253A606A5 for ; Mon, 21 Jun 2021 18:19:32 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7253A606A5 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id F0AA9173D; Mon, 21 Jun 2021 20:18:40 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz F0AA9173D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299571; bh=HmvVpvDrAgBwlg2Qs2MYTbEuOf650rSgrn34kUrXohI=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=EOC0W9f9MG88ksDDoR3uXRbVkH6CKBt3NJXQvuvfekz4OGacc2AL8AB8XmtL3PJMN E/Fg0tAeQ9Ioe/PN4Nx9/ywahJPsAWdtwRvjl046wFHPwM9RRGPEaw5s1Esq8xt70V 5SXC8Owd9oOd6EfdeKzc9Dh7CQl6489SjpO93q5Q= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 9B90CF805B6; Mon, 21 Jun 2021 20:10:16 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7175EF805AF; Mon, 21 Jun 2021 20:10:12 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id F244DF8057D for ; Mon, 21 Jun 2021 20:10:07 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz F244DF8057D Received: by m.b4.vu (Postfix, from userid 1000) id 7363E61E5F00; Tue, 22 Jun 2021 03:40:05 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:05 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 25/31] ALSA: usb-audio: scarlett2: Label 18i8 Gen 3 line outputs correctly Message-ID: <2aa653a0b4a18020c50805952676c5c5383cd593.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The 18i8 Gen 3 analogue 7/8 outputs are identified as line 3/4 on the rear of the unit. Add support for remapping the channel numbers to match the labelling. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 82 ++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 94de63847169..03decb35d25e 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -344,6 +344,12 @@ struct scarlett2_device_info { */ u8 direct_monitor; + /* remap analogue outputs; 18i8 Gen 3 has "line 3/4" connected + * internally to the analogue 7/8 outputs + */ + u8 line_out_remap_enable; + u8 line_out_remap[SCARLETT2_ANALOGUE_MAX]; + /* additional description for the line out volume controls */ const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; @@ -684,15 +690,18 @@ static const struct scarlett2_device_info s18i8_gen3_info = { .phantom_count = 2, .inputs_per_phantom = 2, + .line_out_remap_enable = 1, + .line_out_remap = { 0, 1, 6, 7, 2, 3, 4, 5 }, + .line_out_descrs = { "Monitor L", "Monitor R", + "Alt Monitor L", + "Alt Monitor R", "Headphones 1 L", "Headphones 1 R", "Headphones 2 L", "Headphones 2 R", - "Alt Monitor L", - "Alt Monitor R", }, .port_count = { @@ -1711,13 +1720,22 @@ static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl, return 0; } +static int line_out_remap(struct scarlett2_data *private, int index) +{ + const struct scarlett2_device_info *info = private->info; + + if (!info->line_out_remap_enable) + return index; + return info->line_out_remap[index]; +} + static int scarlett2_volume_ctl_get(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 index = elem->control; + int index = line_out_remap(private, elem->control); mutex_lock(&private->data_mutex); if (private->vol_updated) @@ -1734,7 +1752,7 @@ static int scarlett2_volume_ctl_put(struct snd_kcontrol *kctl, 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 index = elem->control; + int index = line_out_remap(private, elem->control); int oval, val, err = 0; mutex_lock(&private->data_mutex); @@ -1790,7 +1808,7 @@ static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct scarlett2_data *private = elem->head.mixer->private_data; - int index = elem->control; + int index = line_out_remap(private, elem->control); ucontrol->value.integer.value[0] = private->mute_switch[index]; return 0; @@ -1802,7 +1820,7 @@ static int scarlett2_mute_ctl_put(struct snd_kcontrol *kctl, 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 index = elem->control; + int index = line_out_remap(private, elem->control); int oval, val, err = 0; mutex_lock(&private->data_mutex); @@ -1849,9 +1867,9 @@ static int scarlett2_sw_hw_enum_ctl_get(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct scarlett2_data *private = elem->head.mixer->private_data; + int index = line_out_remap(private, elem->control); - ucontrol->value.enumerated.item[0] = - private->vol_sw_hw_switch[elem->control]; + ucontrol->value.enumerated.item[0] = private->vol_sw_hw_switch[index]; return 0; } @@ -1887,8 +1905,8 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, 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 index = elem->control; + int ctl_index = elem->control; + int index = line_out_remap(private, ctl_index); int oval, val, err = 0; mutex_lock(&private->data_mutex); @@ -1904,7 +1922,7 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, /* Change access mode to RO (hardware controlled volume) * or RW (software controlled volume) */ - scarlett2_vol_ctl_set_writable(mixer, index, !val); + scarlett2_vol_ctl_set_writable(mixer, ctl_index, !val); /* Reset volume/mute to master volume/mute */ private->vol[index] = private->master_vol; @@ -2436,13 +2454,16 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl, err = 1; if (index == SCARLETT2_BUTTON_MUTE) - for (i = 0; i < num_line_out; i++) - if (private->vol_sw_hw_switch[i]) { - private->mute_switch[i] = val; + for (i = 0; i < num_line_out; i++) { + int line_index = line_out_remap(private, i); + + if (private->vol_sw_hw_switch[line_index]) { + private->mute_switch[line_index] = val; snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_INFO, &private->mute_ctls[i]->id); } + } unlock: mutex_unlock(&private->data_mutex); @@ -2481,6 +2502,7 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) /* Add volume controls */ for (i = 0; i < num_line_out; i++) { + int index = line_out_remap(private, i); /* Fader */ if (info->line_out_descrs[i]) @@ -2511,7 +2533,7 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) /* Make the fader and mute controls read-only if the * SW/HW switch is set to HW */ - if (private->vol_sw_hw_switch[i]) + if (private->vol_sw_hw_switch[index]) scarlett2_vol_ctl_set_writable(mixer, i, 0); /* SW/HW Switch */ @@ -2760,8 +2782,16 @@ static int scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct scarlett2_data *private = elem->head.mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int line_out_count = + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; + int index = elem->control; + + if (index < line_out_count) + index = line_out_remap(private, index); - ucontrol->value.enumerated.item[0] = private->mux[elem->control]; + ucontrol->value.enumerated.item[0] = private->mux[index]; return 0; } @@ -2771,9 +2801,16 @@ static int scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol *kctl, struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int line_out_count = + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int index = elem->control; int oval, val, err = 0; + if (index < line_out_count) + index = line_out_remap(private, index); + mutex_lock(&private->data_mutex); oval = private->mux[index]; @@ -3174,6 +3211,7 @@ static void scarlett2_notify_sync( static void scarlett2_notify_monitor( struct usb_mixer_interface *mixer) { + struct snd_card *card = mixer->chip->card; struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; @@ -3190,12 +3228,10 @@ static void scarlett2_notify_monitor( snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &private->master_vol_ctl->id); - for (i = 0; i < num_line_out; i++) { - if (!private->vol_sw_hw_switch[i]) - continue; - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->vol_ctls[i]->id); - } + for (i = 0; i < num_line_out; i++) + if (private->vol_sw_hw_switch[line_out_remap(private, i)]) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->vol_ctls[i]->id); } /* Notify on dim/mute change */ @@ -3220,7 +3256,7 @@ static void scarlett2_notify_dim_mute( &private->dim_mute_ctls[i]->id); for (i = 0; i < num_line_out; i++) - if (private->vol_sw_hw_switch[i]) + if (private->vol_sw_hw_switch[line_out_remap(private, i)]) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &private->mute_ctls[i]->id); } From patchwork Mon Jun 21 18:10:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335459 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E78E8C4743C for ; Mon, 21 Jun 2021 18:19:48 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6E3526100B for ; Mon, 21 Jun 2021 18:19:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6E3526100B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 0866C1744; Mon, 21 Jun 2021 20:18:57 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 0866C1744 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299587; bh=jzyZ8yWoSbM5HgrfmIuvWH1inzf/5DyVHS4xPFWCUkg=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=AulfGrbU7mdLwZKaqXCjjk9eZWXoDB5VQUXBIvoKuoo3wt4hEBlvL6MUZ9EqFt/8z Na8Mc6hNqMkzZrZPe1lMqCdBbM6lny7/cdOk3XVIRxuD5MTi2GRCBP7kptTgcQgrKE lvLbV4nL9v82rr2gC9cvKZJSha0oh30CqaIK/W4w= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B7BC5F805C1; Mon, 21 Jun 2021 20:10:17 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 286BFF805B0; Mon, 21 Jun 2021 20:10:13 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 7DD11F805A1 for ; Mon, 21 Jun 2021 20:10:09 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 7DD11F805A1 Received: by m.b4.vu (Postfix, from userid 1000) id 055C261E5F04; Tue, 22 Jun 2021 03:40:07 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:06 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 26/31] ALSA: usb-audio: scarlett2: Split up sw_hw_enum_ctl_put() Message-ID: <9f66950730a058480a135ac57fa3e114b78d66ea.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Split part of scarlett2_sw_hw_enum_ctl_put() out into scarlett2_sw_hw_change() so that the code which actually makes the change is available in its own function. This will be used by the speaker switching support which needs to set the SW/HW switch to HW when speaker switching is enabled. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 46 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 03decb35d25e..1b398a06d4b2 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -1899,23 +1899,12 @@ static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer, &private->mute_ctls[index]->id); } -static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *ucontrol) +static int scarlett2_sw_hw_change(struct usb_mixer_interface *mixer, + int ctl_index, int val) { - 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 ctl_index = elem->control; int index = line_out_remap(private, ctl_index); - int oval, val, err = 0; - - mutex_lock(&private->data_mutex); - - oval = private->vol_sw_hw_switch[index]; - val = !!ucontrol->value.enumerated.item[0]; - - if (oval == val) - goto unlock; + int err; private->vol_sw_hw_switch[index] = val; @@ -1933,18 +1922,39 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME, index, private->master_vol - SCARLETT2_VOLUME_BIAS); if (err < 0) - goto unlock; + return err; /* Set SW mute to current HW mute */ err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_MUTE_SWITCH, index, private->dim_mute[SCARLETT2_BUTTON_MUTE]); if (err < 0) - goto unlock; + return err; /* Send SW/HW switch change to the device */ - err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, - index, val); + return scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, + index, val); +} + +static int scarlett2_sw_hw_enum_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 ctl_index = elem->control; + int index = line_out_remap(private, ctl_index); + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->vol_sw_hw_switch[index]; + val = !!ucontrol->value.enumerated.item[0]; + + if (oval == val) + goto unlock; + + err = scarlett2_sw_hw_change(mixer, ctl_index, val); if (err == 0) err = 1; From patchwork Mon Jun 21 18:10:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335461 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D2E5C4743C for ; Mon, 21 Jun 2021 18:20:12 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BEB0561108 for ; Mon, 21 Jun 2021 18:20:11 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BEB0561108 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 507E41749; Mon, 21 Jun 2021 20:19:20 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 507E41749 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299610; bh=UhTZsYzhUdlEliU2/OiZ3hZdAFB95g/ChwcL0/nvWOE=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=N0QY1sAd4dUN3NE3Zd2jivimQSwxCDw4CQUacxKSiSYntrcmsF2G1lse170dyIiwx A8KKBjIXxm90U062RcOa2WyYD2/qkglYo+/zOfE6sbbwCmNmEiwQ0jUhuHdFIDdxKJ ff9ne7ih5halcFcpZCAYau7U74shQ9phohs/SyZI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id AEC63F80245; Mon, 21 Jun 2021 20:10:18 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 2553DF804B0; Mon, 21 Jun 2021 20:10:13 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 20DE0F805AB for ; Mon, 21 Jun 2021 20:10:11 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 20DE0F805AB Received: by m.b4.vu (Postfix, from userid 1000) id 9D55761E5F19; Tue, 22 Jun 2021 03:40:08 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:08 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 27/31] ALSA: usb-audio: scarlett2: Add sw_hw_ctls and mux_ctls Message-ID: <264f1171f618e84d0f3b6f76a6af7e4497c20481.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Save the struct snd_kcontrol pointers for the sw_hw and mux controls. This is in preparation for speaker switching support which needs to be able to update those controls. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 1b398a06d4b2..efa65bdb48c8 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -394,12 +394,14 @@ struct scarlett2_data { struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX]; + struct snd_kcontrol *sw_hw_ctls[SCARLETT2_ANALOGUE_MAX]; struct snd_kcontrol *mute_ctls[SCARLETT2_ANALOGUE_MAX]; struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT]; struct snd_kcontrol *level_ctls[SCARLETT2_LEVEL_SWITCH_MAX]; struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX]; struct snd_kcontrol *air_ctls[SCARLETT2_AIR_SWITCH_MAX]; struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX]; + struct snd_kcontrol *mux_ctls[SCARLETT2_MUX_MAX]; struct snd_kcontrol *direct_monitor_ctl; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; @@ -2553,7 +2555,8 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) i + 1); err = scarlett2_add_new_ctl(mixer, &scarlett2_sw_hw_enum_ctl, - i, 1, s, NULL); + i, 1, s, + &private->sw_hw_ctls[i]); if (err < 0) return err; } @@ -2871,7 +2874,8 @@ static int scarlett2_add_mux_enums(struct usb_mixer_interface *mixer) err = scarlett2_add_new_ctl(mixer, &scarlett2_mux_src_enum_ctl, - i, 1, s, NULL); + i, 1, s, + &private->mux_ctls[i]); if (err < 0) return err; } From patchwork Mon Jun 21 18:10:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335465 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 39ED9C48BC2 for ; Mon, 21 Jun 2021 18:21:07 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AD147611CE for ; Mon, 21 Jun 2021 18:21:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AD147611CE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 36CB5174E; Mon, 21 Jun 2021 20:20:15 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 36CB5174E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299665; bh=wpRxZMuofkDNnw4WeDCTuEGnPy9h5qWxJ39QtcmvWb4=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=NxzaMgoGwEIyqSI2yP3k41SiVFEfNs3D8+6K638/n5fJDOoXiD6VsY2wZhsCsclcq b/KxvJ+jFDw1jeQXwpAkv5NN0tYoF+4u7Xlytk7lvc+MDEdwsh3dwIApT0oOfGEBsW itu+uZ2gCbsuwo8K3N2ge4t7RgbWXOrl8SBN1HHQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id A4810F805E2; Mon, 21 Jun 2021 20:10:24 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 74C15F805C9; Mon, 21 Jun 2021 20:10:19 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id B08BEF8057D for ; Mon, 21 Jun 2021 20:10:12 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B08BEF8057D Received: by m.b4.vu (Postfix, from userid 1000) id 37B8061E2871; Tue, 22 Jun 2021 03:40:10 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:10 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 28/31] ALSA: usb-audio: scarlett2: Update mux controls to allow updates Message-ID: <3aaee481c6aeb5e9005d56fc94b0079ba094c00e.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Enabling/disabling speaker switching will update the mux configuration. To prepare for this, add a private->mux_updated flag and update the scarlett2_mux_src_enum_ctl_get() callback to check it. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index efa65bdb48c8..dce40d2e0ba6 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -378,6 +378,7 @@ struct scarlett2_data { u8 vol_updated; u8 input_other_updated; u8 monitor_other_updated; + u8 mux_updated; u8 sync; u8 master_vol; u8 vol[SCARLETT2_ANALOGUE_MAX]; @@ -1446,6 +1447,8 @@ static int scarlett2_usb_get_mux(struct usb_mixer_interface *mixer) __le32 data[SCARLETT2_MUX_MAX]; + private->mux_updated = 0; + req.num = 0; req.count = cpu_to_le16(count); @@ -2794,7 +2797,8 @@ static int scarlett2_mux_src_enum_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; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int line_out_count = @@ -2804,7 +2808,12 @@ static int scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol *kctl, if (index < line_out_count) index = line_out_remap(private, index); + mutex_lock(&private->data_mutex); + if (private->mux_updated) + scarlett2_usb_get_mux(mixer); ucontrol->value.enumerated.item[0] = private->mux[index]; + mutex_unlock(&private->data_mutex); + return 0; } From patchwork Mon Jun 21 18:10:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335467 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4CE8C48BC2 for ; Mon, 21 Jun 2021 18:21:32 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6394A611BD for ; Mon, 21 Jun 2021 18:21:32 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6394A611BD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id ED33B1712; Mon, 21 Jun 2021 20:20:40 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz ED33B1712 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299691; bh=v/Hbk5hjBYMTeITzbszhTPt/5SAL2MmMm4X5VA7NYDY=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=FKLvdWfg3raxtGonrcD0uIp3M6C/W1PEkpBq7qK2LmcDRXYlxsbfBFODZm8F3632L Ukyd1MdWy/tuTSLAPajj2ZXokevOI/sAfCMiRVszwbXM8xZFLffNYuIsXuk/Hjr7u7 3z3H5/FmCiqeXtxYUsLuCmuV0HZlHy/c/DCn6ZXA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 29DF6F805E7; Mon, 21 Jun 2021 20:10:25 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id D6809F805D9; Mon, 21 Jun 2021 20:10:22 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 70B07F804D2 for ; Mon, 21 Jun 2021 20:10:14 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 70B07F804D2 Received: by m.b4.vu (Postfix, from userid 1000) id C6EAB61E5F1B; Tue, 22 Jun 2021 03:40:11 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:11 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 29/31] ALSA: usb-audio: scarlett2: Add speaker switching support Message-ID: <2eaec0e124f440b1c72817e5cd4a1192ccf67388.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The 18i8 and 18i20 Gen 3 support "speaker switching". Add a Speaker Switch control which can be set to Off/Main/Alt. When speaker switching is enabled or disabled, the interface may change the state of the Analog Outputs 3 and 4 routing and the global mute button, so use a flag private->speaker_switching_switched to note that those should be checked when the next "monitor other" notification is received. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 248 +++++++++++++++++++++++++++++++- 1 file changed, 241 insertions(+), 7 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index dce40d2e0ba6..dc5fd045b2dc 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -48,8 +48,8 @@ * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander * Vorona for 2i2 protocol traces). * - * Support for phantom power and direct monitoring added in May-June - * 2021. + * Support for phantom power, direct monitoring, and speaker switching + * added in May-June 2021. * * This ALSA mixer gives access to (model-dependent): * - input, output, mixer-matrix muxes @@ -57,7 +57,7 @@ * - gain/volume/mute controls * - level meters * - line/inst level, pad, and air controls - * - phantom power and direct monitor controls + * - phantom power, direct monitor, and speaker switching controls * - disable/enable MSD mode * * @@ -315,6 +315,9 @@ struct scarlett2_device_info { /* line out hw volume is sw controlled */ u8 line_out_hw_vol; + /* support for main/alt speaker switching */ + u8 has_speaker_switching; + /* the number of analogue inputs with a software switchable * level control that can be set to line or instrument */ @@ -379,6 +382,7 @@ struct scarlett2_data { u8 input_other_updated; u8 monitor_other_updated; u8 mux_updated; + u8 speaker_switching_switched; u8 sync; u8 master_vol; u8 vol[SCARLETT2_ANALOGUE_MAX]; @@ -391,6 +395,7 @@ struct scarlett2_data { u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX]; u8 phantom_persistence; u8 direct_monitor_switch; + u8 speaker_switching_switch; u8 msd_switch; struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; @@ -404,6 +409,7 @@ struct scarlett2_data { struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX]; struct snd_kcontrol *mux_ctls[SCARLETT2_MUX_MAX]; struct snd_kcontrol *direct_monitor_ctl; + struct snd_kcontrol *speaker_switching_ctl; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; }; @@ -687,6 +693,7 @@ static const struct scarlett2_device_info s18i8_gen3_info = { .has_msd_mode = 1, .has_mixer = 1, .line_out_hw_vol = 1, + .has_speaker_switching = 1, .level_input_count = 2, .pad_input_count = 2, .air_input_count = 4, @@ -756,6 +763,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = { .has_msd_mode = 1, .has_mixer = 1, .line_out_hw_vol = 1, + .has_speaker_switching = 1, .level_input_count = 2, .pad_input_count = 8, .air_input_count = 8, @@ -913,7 +921,9 @@ enum { SCARLETT2_CONFIG_PHANTOM_SWITCH = 8, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE = 9, SCARLETT2_CONFIG_DIRECT_MONITOR = 10, - SCARLETT2_CONFIG_COUNT = 11 + SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH = 11, + SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE = 12, + SCARLETT2_CONFIG_COUNT = 13 }; /* Location, size, and activation command number for the configuration @@ -982,6 +992,12 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = { .offset = 0x9e, .size = 8, .activate = 6 }, + + [SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH] = { + .offset = 0x9f, .size = 1, .activate = 10 }, + + [SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE] = { + .offset = 0xa0, .size = 1, .activate = 10 }, } }; /* proprietary request/response format */ @@ -1857,6 +1873,18 @@ static const struct snd_kcontrol_new scarlett2_mute_ctl = { /*** HW/SW Volume Switch Controls ***/ +static void scarlett2_sw_hw_ctl_ro(struct scarlett2_data *private, int index) +{ + private->sw_hw_ctls[index]->vd[0].access &= + ~SNDRV_CTL_ELEM_ACCESS_WRITE; +} + +static void scarlett2_sw_hw_ctl_rw(struct scarlett2_data *private, int index) +{ + private->sw_hw_ctls[index]->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_WRITE; +} + static int scarlett2_sw_hw_enum_ctl_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) { @@ -2320,6 +2348,13 @@ static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; + int err; + + /* monitor_other_enable[0] enables speaker switching */ + u8 monitor_other_enable[2]; + + /* monitor_other_switch[0] activates the alternate speakers */ + u8 monitor_other_switch[2]; private->monitor_other_updated = 0; @@ -2328,6 +2363,26 @@ static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer) mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, 1, &private->direct_monitor_switch); + if (!info->has_speaker_switching) + return 0; + + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE, + 2, monitor_other_enable); + if (err < 0) + return err; + + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH, + 2, monitor_other_switch); + if (err < 0) + return err; + + if (!monitor_other_enable[0]) + private->speaker_switching_switch = 0; + else + private->speaker_switching_switch = monitor_other_switch[0] + 1; + return 0; } @@ -2420,6 +2475,151 @@ static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer) &private->direct_monitor_ctl); } +/*** Speaker Switching Control ***/ + +static int scarlett2_speaker_switch_enum_ctl_info( + struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + static const char *const values[3] = { + "Off", "Main", "Alt" + }; + + return snd_ctl_enum_info(uinfo, 1, 3, values); +} + +static int scarlett2_speaker_switch_enum_ctl_get( + 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; + + mutex_lock(&private->data_mutex); + if (private->monitor_other_updated) + scarlett2_update_monitor_other(mixer); + ucontrol->value.enumerated.item[0] = private->speaker_switching_switch; + mutex_unlock(&private->data_mutex); + + return 0; +} + +/* when speaker switching gets enabled, switch the main/alt speakers + * to HW volume and disable those controls + */ +static void scarlett2_speaker_switch_enable(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + int i; + + for (i = 0; i < 4; i++) { + int index = line_out_remap(private, i); + + /* switch the main/alt speakers to HW volume */ + if (!private->vol_sw_hw_switch[index]) + scarlett2_sw_hw_change(private->mixer, i, 1); + + /* disable the line out SW/HW switch */ + scarlett2_sw_hw_ctl_ro(private, i); + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, + &private->sw_hw_ctls[i]->id); + } + + /* when the next monitor-other notify comes in, update the mux + * configuration + */ + private->speaker_switching_switched = 1; +} + +/* when speaker switching gets disabled, reenable the hw/sw controls + * and invalidate the routing + */ +static void scarlett2_speaker_switch_disable(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + int i; + + /* enable the line out SW/HW switch */ + for (i = 0; i < 4; i++) { + scarlett2_sw_hw_ctl_rw(private, i); + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, + &private->sw_hw_ctls[i]->id); + } + + /* when the next monitor-other notify comes in, update the mux + * configuration + */ + private->speaker_switching_switched = 1; +} + +static int scarlett2_speaker_switch_enum_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->speaker_switching_switch; + val = min(ucontrol->value.enumerated.item[0], 2U); + + if (oval == val) + goto unlock; + + private->speaker_switching_switch = val; + + /* enable/disable speaker switching */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE, + 0, !!val); + if (err < 0) + goto unlock; + + /* if speaker switching is enabled, select main or alt */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH, + 0, val == 2); + if (err < 0) + goto unlock; + + /* update controls if speaker switching gets enabled or disabled */ + if (!oval && val) + scarlett2_speaker_switch_enable(mixer); + else if (oval && !val) + scarlett2_speaker_switch_disable(mixer); + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_speaker_switch_enum_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_speaker_switch_enum_ctl_info, + .get = scarlett2_speaker_switch_enum_ctl_get, + .put = scarlett2_speaker_switch_enum_ctl_put, +}; + +static int scarlett2_add_speaker_switch_ctl( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + if (!info->has_speaker_switching) + return 0; + + return scarlett2_add_new_ctl( + mixer, &scarlett2_speaker_switch_enum_ctl, + 0, 1, "Speaker Switching Playback Enum", + &private->speaker_switching_ctl); +} + /*** Dim/Mute Controls ***/ static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl, @@ -2562,6 +2762,12 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) &private->sw_hw_ctls[i]); if (err < 0) return err; + + /* Make the switch read-only if the line is + * involved in speaker switching + */ + if (private->speaker_switching_switch && i < 4) + scarlett2_sw_hw_ctl_ro(private, i); } } @@ -3309,18 +3515,41 @@ static void scarlett2_notify_input_other( &private->phantom_ctls[i]->id); } -/* Notify on "monitor other" change (direct monitor) */ +/* Notify on "monitor other" change (direct monitor, speaker switching) */ static void scarlett2_notify_monitor_other( struct usb_mixer_interface *mixer) { - struct scarlett2_data *private = mixer->private_data; struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; private->monitor_other_updated = 1; - if (private->info->direct_monitor) + if (info->direct_monitor) { snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &private->direct_monitor_ctl->id); + return; + } + + if (info->has_speaker_switching) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->speaker_switching_ctl->id); + + /* if speaker switching was recently enabled or disabled, + * invalidate the dim/mute and mux enum controls + */ + if (private->speaker_switching_switched) { + int i; + + scarlett2_notify_dim_mute(mixer); + + private->speaker_switching_switched = 0; + private->mux_updated = 1; + + for (i = 0; i < private->num_mux_dsts; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->mux_ctls[i]->id); + } } /* Interrupt callback */ @@ -3456,6 +3685,11 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer) if (err < 0) return err; + /* Create the speaker switching control */ + err = scarlett2_add_speaker_switch_ctl(mixer); + if (err < 0) + return err; + /* Set up the interrupt polling */ err = scarlett2_init_notify(mixer); if (err < 0) From patchwork Mon Jun 21 18:10:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335469 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7CA4C4743C for ; Mon, 21 Jun 2021 18:22:00 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 56DC2606A5 for ; Mon, 21 Jun 2021 18:22:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 56DC2606A5 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 02F8B1766; Mon, 21 Jun 2021 20:21:09 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 02F8B1766 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299719; bh=UItnPYGUolNuGmYbIDxBXVsFgRh61lrWm3cGWmYIdTQ=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=fBWQPCwY1VtPOzMklwP6lS574pvtncXYsa1bzY5KhyBSxD+JEESGir+lJaCmck9oq ZdjThzPj67QYjo75nUSJqTkQZ5cVL0Aak1D4dGwYziJ28ejdWC89VAtApRrw0QblqK verwQ+8SVgfh/9qciP52yrFPnxkYdoyOrmXZwTjc= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 42159F805EF; Mon, 21 Jun 2021 20:10:42 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 71030F805E3; Mon, 21 Jun 2021 20:10:24 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id EDF4FF805BB for ; Mon, 21 Jun 2021 20:10:15 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz EDF4FF805BB Received: by m.b4.vu (Postfix, from userid 1000) id 789D861E5F02; Tue, 22 Jun 2021 03:40:13 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:13 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 30/31] ALSA: usb-audio: scarlett2: Update get_config to do endian conversion Message-ID: <0d62f5e413be817b89ce7e7fbd18758cfc0306b8.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" For configuration items with a size of 16, scarlett2_usb_get_config() was filling *buf with little-endian data. Update it to convert to CPU endian. This function is not currently used so affects nothing yet; will be used by the upcoming talkback feature. Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index dc5fd045b2dc..8fd850f6aa6e 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -1170,7 +1170,13 @@ static int scarlett2_usb_get_config( /* For byte-sized parameters, retrieve directly into buf */ if (config_item->size >= 8) { size = config_item->size / 8 * count; - return scarlett2_usb_get(mixer, config_item->offset, buf, size); + err = scarlett2_usb_get(mixer, config_item->offset, buf, size); + if (err < 0) + return err; + if (size == 2) + for (i = 0; i < count; i++, (u16 *)buf++) + *(u16 *)buf = le16_to_cpu(*(__le16 *)buf); + return 0; } /* For bit-sized parameters, retrieve into value */ From patchwork Mon Jun 21 18:10:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Geoffrey D. Bennett" X-Patchwork-Id: 12335471 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.4 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B8B06C4743C for ; Mon, 21 Jun 2021 18:22:18 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 455D361108 for ; Mon, 21 Jun 2021 18:22:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 455D361108 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=b4.vu Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id D3029176C; Mon, 21 Jun 2021 20:21:26 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D3029176C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624299736; bh=OEvWopwjkIhEHsKNLBb0VC2BFURD8/1xBSlZpNsS2sg=; h=Date:From:To:Subject:References:In-Reply-To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Vl+lbu8o325iYgYCUfqpmDa5vWzMw/MnUoiM+MQG0/aLCPOtIDzyxC9Z/UjU1/yR5 ktqRASk/z+z5tzu/rqifLrsS/zfGAsGlgJXj+p6E/zL3709irPKYIcmBMq7/CI91de eUjkq8/O+ZZ84T3fl8DJSt2W7cjWer7G67dcSS2U= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B7608F805F3; Mon, 21 Jun 2021 20:10:42 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 3034BF805E9; Mon, 21 Jun 2021 20:10:32 +0200 (CEST) Received: from m.b4.vu (m.b4.vu [203.16.231.148]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 1EAE1F805E3 for ; Mon, 21 Jun 2021 20:10:24 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 1EAE1F805E3 Received: by m.b4.vu (Postfix, from userid 1000) id A631B61E286F; Tue, 22 Jun 2021 03:40:21 +0930 (ACST) Date: Tue, 22 Jun 2021 03:40:21 +0930 From: "Geoffrey D. Bennett" To: alsa-devel@alsa-project.org, Takashi Iwai Subject: [PATCH 31/31] ALSA: usb-audio: scarlett2: Add support for the talkback feature Message-ID: <743454d3ea48bcbdf7e39744a000547133d3c110.1624294591.git.g@b4.vu> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Cc: Hin-Tak Leung , Vladimir Sadovnikov X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add support for the talkback feature of the 18i20 Gen 3. Co-developed-by: Vladimir Sadovnikov Signed-off-by: Vladimir Sadovnikov Signed-off-by: Geoffrey D. Bennett --- sound/usb/mixer_scarlett_gen2.c | 229 +++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 7 deletions(-) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 8fd850f6aa6e..fcf78b06a519 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -48,8 +48,8 @@ * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander * Vorona for 2i2 protocol traces). * - * Support for phantom power, direct monitoring, and speaker switching - * added in May-June 2021. + * Support for phantom power, direct monitoring, speaker switching, + * and talkback added in May-June 2021. * * This ALSA mixer gives access to (model-dependent): * - input, output, mixer-matrix muxes @@ -57,7 +57,8 @@ * - gain/volume/mute controls * - level meters * - line/inst level, pad, and air controls - * - phantom power, direct monitor, and speaker switching controls + * - phantom power, direct monitor, speaker switching, and talkback + * controls * - disable/enable MSD mode * * @@ -318,6 +319,9 @@ struct scarlett2_device_info { /* support for main/alt speaker switching */ u8 has_speaker_switching; + /* support for talkback microphone */ + u8 has_talkback; + /* the number of analogue inputs with a software switchable * level control that can be set to line or instrument */ @@ -396,6 +400,8 @@ struct scarlett2_data { u8 phantom_persistence; u8 direct_monitor_switch; u8 speaker_switching_switch; + u8 talkback_switch; + u8 talkback_map[SCARLETT2_OUTPUT_MIX_MAX]; u8 msd_switch; struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; @@ -410,6 +416,7 @@ struct scarlett2_data { struct snd_kcontrol *mux_ctls[SCARLETT2_MUX_MAX]; struct snd_kcontrol *direct_monitor_ctl; struct snd_kcontrol *speaker_switching_ctl; + struct snd_kcontrol *talkback_ctl; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; }; @@ -764,6 +771,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = { .has_mixer = 1, .line_out_hw_vol = 1, .has_speaker_switching = 1, + .has_talkback = 1, .level_input_count = 2, .pad_input_count = 8, .air_input_count = 8, @@ -923,7 +931,8 @@ enum { SCARLETT2_CONFIG_DIRECT_MONITOR = 10, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH = 11, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE = 12, - SCARLETT2_CONFIG_COUNT = 13 + SCARLETT2_CONFIG_TALKBACK_MAP = 13, + SCARLETT2_CONFIG_COUNT = 14 }; /* Location, size, and activation command number for the configuration @@ -998,6 +1007,9 @@ static const struct scarlett2_config [SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE] = { .offset = 0xa0, .size = 1, .activate = 10 }, + + [SCARLETT2_CONFIG_TALKBACK_MAP] = { + .offset = 0xb0, .size = 16, .activate = 10 }, } }; /* proprietary request/response format */ @@ -2356,10 +2368,14 @@ static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer) const struct scarlett2_device_info *info = private->info; int err; - /* monitor_other_enable[0] enables speaker switching */ + /* monitor_other_enable[0] enables speaker switching + * monitor_other_enable[1] enables talkback + */ u8 monitor_other_enable[2]; - /* monitor_other_switch[0] activates the alternate speakers */ + /* monitor_other_switch[0] activates the alternate speakers + * monitor_other_switch[1] activates talkback + */ u8 monitor_other_switch[2]; private->monitor_other_updated = 0; @@ -2369,6 +2385,9 @@ static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer) mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, 1, &private->direct_monitor_switch); + /* if it doesn't do speaker switching then it also doesn't do + * talkback + */ if (!info->has_speaker_switching) return 0; @@ -2389,6 +2408,26 @@ static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer) else private->speaker_switching_switch = monitor_other_switch[0] + 1; + if (info->has_talkback) { + const int (*port_count)[SCARLETT2_PORT_DIRNS] = + info->port_count; + int num_mixes = + port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; + u16 bitmap; + int i; + + if (!monitor_other_enable[1]) + private->talkback_switch = 0; + else + private->talkback_switch = monitor_other_switch[1] + 1; + + err = scarlett2_usb_get_config(mixer, + SCARLETT2_CONFIG_TALKBACK_MAP, + 1, &bitmap); + for (i = 0; i < num_mixes; i++, bitmap >>= 1) + private->talkback_map[i] = bitmap & 1; + } + return 0; } @@ -2626,6 +2665,171 @@ static int scarlett2_add_speaker_switch_ctl( &private->speaker_switching_ctl); } +/*** Talkback and Talkback Map Controls ***/ + +static int scarlett2_talkback_enum_ctl_info( + struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + static const char *const values[3] = { + "Disabled", "Off", "On" + }; + + return snd_ctl_enum_info(uinfo, 1, 3, values); +} + +static int scarlett2_talkback_enum_ctl_get( + 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; + + mutex_lock(&private->data_mutex); + if (private->monitor_other_updated) + scarlett2_update_monitor_other(mixer); + ucontrol->value.enumerated.item[0] = private->talkback_switch; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static int scarlett2_talkback_enum_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->talkback_switch; + val = min(ucontrol->value.enumerated.item[0], 2U); + + if (oval == val) + goto unlock; + + private->talkback_switch = val; + + /* enable/disable talkback */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE, + 1, !!val); + if (err < 0) + goto unlock; + + /* if talkback is enabled, select main or alt */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH, + 1, val == 2); + if (err < 0) + goto unlock; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_talkback_enum_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_talkback_enum_ctl_info, + .get = scarlett2_talkback_enum_ctl_get, + .put = scarlett2_talkback_enum_ctl_put, +}; + +static int scarlett2_talkback_map_ctl_get( + 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 index = elem->control; + + ucontrol->value.integer.value[0] = private->talkback_map[index]; + + return 0; +} + +static int scarlett2_talkback_map_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; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = + private->info->port_count; + int num_mixes = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; + + int index = elem->control; + int oval, val, err = 0, i; + u16 bitmap = 0; + + mutex_lock(&private->data_mutex); + + oval = private->talkback_map[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->talkback_map[index] = val; + + for (i = 0; i < num_mixes; i++) + bitmap |= private->talkback_map[i] << i; + + /* Send updated bitmap to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_TALKBACK_MAP, + 0, bitmap); + if (err < 0) + goto unlock; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_talkback_map_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_talkback_map_ctl_get, + .put = scarlett2_talkback_map_ctl_put, +}; + +static int scarlett2_add_talkback_ctls( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int num_mixes = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; + int err, i; + char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + + if (!info->has_talkback) + return 0; + + err = scarlett2_add_new_ctl( + mixer, &scarlett2_talkback_enum_ctl, + 0, 1, "Talkback Playback Enum", + &private->talkback_ctl); + if (err < 0) + return err; + + for (i = 0; i < num_mixes; i++) { + snprintf(s, sizeof(s), + "Talkback Mix %c Playback Switch", i + 'A'); + err = scarlett2_add_new_ctl(mixer, &scarlett2_talkback_map_ctl, + i, 1, s, NULL); + if (err < 0) + return err; + } + + return 0; +} + /*** Dim/Mute Controls ***/ static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl, @@ -3521,7 +3725,9 @@ static void scarlett2_notify_input_other( &private->phantom_ctls[i]->id); } -/* Notify on "monitor other" change (direct monitor, speaker switching) */ +/* Notify on "monitor other" change (direct monitor, speaker + * switching, talkback) + */ static void scarlett2_notify_monitor_other( struct usb_mixer_interface *mixer) { @@ -3541,6 +3747,10 @@ static void scarlett2_notify_monitor_other( snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &private->speaker_switching_ctl->id); + if (info->has_talkback) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->talkback_ctl->id); + /* if speaker switching was recently enabled or disabled, * invalidate the dim/mute and mux enum controls */ @@ -3696,6 +3906,11 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer) if (err < 0) return err; + /* Create the talkback controls */ + err = scarlett2_add_talkback_ctls(mixer); + if (err < 0) + return err; + /* Set up the interrupt polling */ err = scarlett2_init_notify(mixer); if (err < 0)