From patchwork Sat Sep 16 00:10:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 140922 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:172:b0:3f2:4152:657d with SMTP id h50csp1462207vqi; Fri, 15 Sep 2023 20:52:31 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGlis8rFhn6lHx4e25KOmRJSVhotrCREfaVjb2RP/0vC7DHi+loRHU1dYNkZMske1/uk4Qw X-Received: by 2002:a05:620a:394e:b0:770:df33:58b6 with SMTP id qs14-20020a05620a394e00b00770df3358b6mr3726282qkn.22.1694836350998; Fri, 15 Sep 2023 20:52:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694836350; cv=none; d=google.com; s=arc-20160816; b=xJ6JYHa39djLR6Qzt+2b8mipCwAJ0cttvFkXHwEoCze7JRtmMVcWwNMxToCM570De7 l4IMKBYgeVmepsFvjZDMWQiwnN5cYLZAFH89nrNPaxohygG6OJalsySSH/+SHg+zoVVJ Jw2tdS85BgmUY89aj1Y7aA87/W4uDEYuvXS4PiWiGLAirfw05w2NLO68iVPd+tXKIVpZ OUBheFdDyGHN2OUmnyh8DOAiSCQYdfBqGmlHDBHYkxC5Y0Cr7qIMKXLoD89IzdwQZ/Uk 4Aai/KQ0D5YtuUToLIOOuHVqt5wSvn4+0lqgJ+dsJyr5tNVx8ytGFhLjSIED4zDxDvpz /ZAA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=QKsOM7x+HZQK52D1pGKB5Fw52wDOVcZsbU8lkxr85aU=; fh=MhCCCRx4c0AeUz43uLzZOKA4YzcBN2mk3tAWrRRVvW4=; b=R0iYi7s0vTItEnokaHkkkPIny33sLMsuaJLYAEJjIG60RLak5uI01uk23BUG1fQPTD Mzf9i9EX4N1AyKA7+p2fXqaP7LdZ5xRhUWrC6OH/2lNqIL3FIYLmjFbHz+pko910sUmZ +S/4RhUGTqSnqNwBtSt+unBKJmGC3H3r4tu1Qi+hDTvUlaxGeZj+7XoXyl2B5LI+kpYJ qtSRaVdTnh2WPdedDJGst9WBJVTqSLnv6T7Xf6FNYv86xD4T3h1ZbywtewqhpqVfjKR/ XnC+HZc4V3vt+0kvxm14gxnLeRASfNKshkPRrIhOs3wB7sf1T6JKROI0+GsaVXq/4kQ/ +wqQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=hXhwjqah; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from howler.vger.email (howler.vger.email. [23.128.96.34]) by mx.google.com with ESMTPS id n7-20020a635c47000000b0056566687e59si4147693pgm.343.2023.09.15.20.52.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Sep 2023 20:52:30 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) client-ip=23.128.96.34; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=hXhwjqah; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id B0B7380E227B; Fri, 15 Sep 2023 17:14:51 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231487AbjIPAME (ORCPT + 28 others); Fri, 15 Sep 2023 20:12:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53444 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238123AbjIPALJ (ORCPT ); Fri, 15 Sep 2023 20:11:09 -0400 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E79522708; Fri, 15 Sep 2023 17:11:00 -0700 (PDT) Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38G0Akvn002981; Sat, 16 Sep 2023 00:10:46 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=qcppdkim1; bh=QKsOM7x+HZQK52D1pGKB5Fw52wDOVcZsbU8lkxr85aU=; b=hXhwjqahQ7QYDJ8R2JmGH6dr8S0D8jFuUZv2e7IY6xg2aDrblju9/Tw6nDHxCocwwoS/ 9KW+swZnpTlg/k/1pM9ICF78LF9CVicSnpOKEkk9x4usQSsV/IULbgSrT0AU+XAfnI0o EPectWUCZwj5lbKEUF4AdT3iy35tk001Yak74T7+RajfdKhpCKRyVIk97dl+9Ty/0oFG Y9RKFK6NKT4dc79/w85bSpU/49PeTwSkXrpqqy+k53GT7ng1N/aQeYgwvccXqzs3LPCK wMQs/NWkQeXW9g77F/9I/AOnHalBxslm9XlmsVQuAOCKUP5cVHjm3b1qXiZN0G09LK8E dQ== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3t4fwn2dhj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sat, 16 Sep 2023 00:10:46 +0000 Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA03.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 38G0AjMj026033 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sat, 16 Sep 2023 00:10:45 GMT Received: from hu-wcheng-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.36; Fri, 15 Sep 2023 17:10:45 -0700 From: Wesley Cheng To: , , , , , , , , , , , , , , CC: , , , , , Wesley Cheng Subject: [PATCH v6 28/33] ASoC: qcom: qdsp6: Add SND kcontrol to select offload device Date: Fri, 15 Sep 2023 17:10:21 -0700 Message-ID: <20230916001026.315-29-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230916001026.315-1-quic_wcheng@quicinc.com> References: <20230916001026.315-1-quic_wcheng@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01a.na.qualcomm.com (10.47.209.196) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: DY67SOPa5zn_W44eCjYGmQr4rTj7UTAV X-Proofpoint-ORIG-GUID: DY67SOPa5zn_W44eCjYGmQr4rTj7UTAV X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-09-15_20,2023-09-15_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 clxscore=1015 mlxscore=0 phishscore=0 malwarescore=0 priorityscore=1501 impostorscore=0 spamscore=0 mlxlogscore=999 bulkscore=0 suspectscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2308100000 definitions=main-2309160000 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Fri, 15 Sep 2023 17:14:51 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1777164721130731636 X-GMAIL-MSGID: 1777164721130731636 Expose a kcontrol on the platform sound card, which will allow for userspace to determine which USB card number and PCM device to offload. This allows for userspace to potentially tag an alternate path for a specific USB SND card and PCM device. Previously, control was absent, and the offload path would be enabled on the last USB SND device which was connected. This logic will continue to be applicable if no mixer input is received for specific device selection. An example to configure the offload device using tinymix: tinymix -D 0 set 'Q6USB offload SND device select' 1 0 The above will set the Q6AFE device token to choose offload on card#1 and pcm#0. Device selection is made possible by setting the Q6AFE device token. The audio DSP utilizes this parameter, and will pass this field back to the USB offload driver within the QMI stream requests. Signed-off-by: Wesley Cheng --- sound/soc/qcom/qdsp6/q6usb.c | 125 ++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 3 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c index 2c0d482de3ab..2c720eff1866 100644 --- a/sound/soc/qcom/qdsp6/q6usb.c +++ b/sound/soc/qcom/qdsp6/q6usb.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -35,9 +36,12 @@ struct q6usb_port_data { struct q6afe_usb_cfg usb_cfg; struct snd_soc_usb *usb; struct q6usb_offload priv; + struct mutex mutex; unsigned long available_card_slot; struct q6usb_status status[SNDRV_CARDS]; - int active_idx; + bool idx_valid; + int sel_card_idx; + int sel_pcm_idx; }; static const struct snd_soc_dapm_widget q6usb_dai_widgets[] = { @@ -53,9 +57,34 @@ static int q6usb_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct q6usb_port_data *data = dev_get_drvdata(dai->dev); + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct q6afe_port *q6usb_afe; int direction = substream->stream; + int chip_idx; + int ret; + + mutex_lock(&data->mutex); + chip_idx = data->status[data->sel_card_idx].chip_index; + + ret = snd_soc_usb_find_format(chip_idx, params, direction); + if (ret < 0) + goto out; + + q6usb_afe = q6afe_port_get_from_id(cpu_dai->dev, USB_RX); + if (IS_ERR(q6usb_afe)) + goto out; - return snd_soc_usb_find_format(data->active_idx, params, direction); + ret = afe_port_send_usb_dev_param(q6usb_afe, data->sel_card_idx, + data->sel_pcm_idx); + if (ret < 0) + goto out; + + data->status[data->sel_card_idx].pcm_index = data->sel_pcm_idx; +out: + mutex_unlock(&data->mutex); + + return ret; } static const struct snd_soc_dai_ops q6usb_ops = { @@ -86,6 +115,89 @@ static struct snd_soc_dai_driver q6usb_be_dais[] = { }, }; +static int q6usb_get_offload_dev(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + int pcm_idx; + int card_idx; + + mutex_lock(&data->mutex); + if (!data->idx_valid) { + card_idx = -1; + pcm_idx = -1; + } else { + card_idx = data->sel_card_idx; + pcm_idx = data->sel_pcm_idx; + } + + ucontrol->value.integer.value[0] = card_idx; + ucontrol->value.integer.value[1] = pcm_idx; + mutex_unlock(&data->mutex); + + return 0; +} + +static int q6usb_put_offload_dev(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + int changed = 0; + int pcmidx; + int cardidx; + + cardidx = ucontrol->value.integer.value[0]; + pcmidx = ucontrol->value.integer.value[1]; + + mutex_lock(&data->mutex); + if ((cardidx >= 0 && test_bit(cardidx, &data->available_card_slot))) { + data->sel_card_idx = cardidx; + changed = 1; + } + + if ((pcmidx >= 0 && pcmidx < data->status[cardidx].num_pcm)) { + data->sel_pcm_idx = pcmidx; + data->idx_valid = true; + changed = 1; + } + mutex_unlock(&data->mutex); + + return changed; +} + +static int q6usb_offload_dev_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = -1; + uinfo->value.integer.max = SNDRV_CARDS; + + return 0; +} + +static const struct snd_kcontrol_new q6usb_offload_dev_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .name = "Q6USB offload SND device select", + .info = q6usb_offload_dev_info, + .get = q6usb_get_offload_dev, + .put = q6usb_put_offload_dev, +}; + +/* Build a mixer control for a UAC connector control (jack-detect) */ +static void q6usb_connector_control_init(struct snd_soc_component *component) +{ + int ret; + + ret = snd_ctl_add(component->card->snd_card, + snd_ctl_new1(&q6usb_offload_dev_ctrl, component)); + if (ret < 0) + return; +} + static int q6usb_audio_ports_of_xlate_dai_name(struct snd_soc_component *component, const struct of_phandle_args *args, const char **dai_name) @@ -115,9 +227,11 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, data = dev_get_drvdata(usb->component->dev); + mutex_lock(&data->mutex); if (connected) { /* We only track the latest USB headset plugged in */ - data->active_idx = sdev->card_idx; + if (!data->idx_valid || data->sel_card_idx < 0) + data->sel_card_idx = sdev->card_idx; set_bit(sdev->card_idx, &data->available_card_slot); data->status[sdev->card_idx].num_pcm = sdev->num_playback; @@ -127,6 +241,7 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, data->status[sdev->card_idx].num_pcm = 0; data->status[sdev->card_idx].chip_index = 0; } + mutex_unlock(&data->mutex); return 0; } @@ -135,6 +250,8 @@ static int q6usb_component_probe(struct snd_soc_component *component) { struct q6usb_port_data *data = dev_get_drvdata(component->dev); + q6usb_connector_control_init(component); + data->usb = snd_soc_usb_add_port(component->dev, &data->priv, q6usb_alsa_connection_cb); if (IS_ERR(data->usb)) { dev_err(component->dev, "failed to add usb port\n"); @@ -189,6 +306,8 @@ static int q6usb_dai_dev_probe(struct platform_device *pdev) data->priv.domain = iommu_get_domain_for_dev(&pdev->dev); + mutex_init(&data->mutex); + data->priv.dev = dev; dev_set_drvdata(dev, data);