From patchwork Thu Aug 1 01:17:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wesley Cheng X-Patchwork-Id: 13749403 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A77C6153BC7; Thu, 1 Aug 2024 01:18:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722475105; cv=none; b=nlC8AddM4le9AB/HEv/bcnxHuRkl6BcGKa/aytwBbr2SKAMfZD8+ktGZH+k8SO6jFgCm5+TloIKr4IDwdax+EMLPVWWVRDrS8imSvwL7BoTcGKGjnAs7bPQqzuJB3TeijbAeWW+64OATzRzg3ik526eqAJUphQppzbH+59hgsxg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722475105; c=relaxed/simple; bh=GkOcfRPuVtcPZZxjCBEX4Nz7K2f39TOd1oJDrcqkdt8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pRHu1KeTdBbhVQk2LZrbUXoqVpuGItfcFVovCxrFyeebYtqFGisEJwGW69bE7OfWSWk9FoOELrPEXxwxJaAm1oesr/Wj81AClfsjxhNaQbW6qbTyixkIbfumI3r7hwISX+Zgo+TTKtBVKagv9x56Rvl24Jy+lKlrhvacHw5ut68= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=ZeOH7Lca; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="ZeOH7Lca" Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 46VMm9OF027260; Thu, 1 Aug 2024 01:17:47 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-type:date:from:in-reply-to:message-id:mime-version :references:subject:to; s=qcppdkim1; bh=MM8GjTWZDgBPukRc0Uhodgfi 3cbt6Pmy1ylBMrLBLVU=; b=ZeOH7LcaUSf2NyAtiSzCNdshk463a30AiuMOcl2K OrNDE95eseNWikSn3lp7zhhwAo4DiZn2MgnTICQCQKHjry17EezBmG6uNr79bG4N nENBhjHdKa0zU0HjCdY/t2/swahTXiyqMt3SgR37IIc7Eo1SInZTN638f1HWV4NK i81iUE67Hy8Lklopx8y3jAYJKkHEuua6pmLcJcqe6JCypapXUoAfZX40XfmneMYn Swd3Pu0mja3CbmyrOkHbplvQCUhGS2/Rh7jfWr2uEW2b8c7cbzQ+4FHPYjvJGVYt tgpx2boFlDzQC36cGxXfeuAi/tIiTuRatP2DLt/mDrDLjg== Received: from nalasppmta05.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 40q232wce6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 01 Aug 2024 01:17:47 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA05.qualcomm.com (8.17.1.19/8.17.1.19) with ESMTPS id 4711Hk8P030363 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 1 Aug 2024 01:17:47 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.1544.9; Wed, 31 Jul 2024 18:17:46 -0700 From: Wesley Cheng To: , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v24 19/34] ASoC: qcom: qdsp6: Fetch USB offload mapped card and PCM device Date: Wed, 31 Jul 2024 18:17:15 -0700 Message-ID: <20240801011730.4797-20-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20240801011730.4797-1-quic_wcheng@quicinc.com> References: <20240801011730.4797-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) 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: v13_PYpfh4T9fu0z2ioVEcVKXnWzps_j X-Proofpoint-ORIG-GUID: v13_PYpfh4T9fu0z2ioVEcVKXnWzps_j X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-07-31_11,2024-07-31_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 impostorscore=0 malwarescore=0 bulkscore=0 priorityscore=1501 spamscore=0 adultscore=0 mlxscore=0 mlxlogscore=999 clxscore=1015 suspectscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2407110000 definitions=main-2408010005 The USB SND path may need to know how the USB offload path is routed, so that applications can open the proper sound card and PCM device. The implementation for the QC ASoC design has a "USB Mixer" kcontrol for each possible FE (Q6ASM) DAI, which can be utilized to know which front end link is enabled. When an application/userspace queries for the mapped offload devices, the logic will lookup the USB mixer status though the following path: MultiMedia* <-> MM_DL* <-> USB Mixer* The "USB Mixer" is a DAPM widget, and the q6routing entity will set the DAPM connect status accordingly if the USB mixer is enabled. If enabled, the Q6USB backend link can fetch the PCM device number from the FE DAI link (Multimedia*). With respects to the card number, that is straightfoward, as the ASoC components have direct references to the ASoC platform sound card. An example output can be shown below: Number of controls: 9 name value Capture Channel Map 0, 0 (range 0->36) Playback Channel Map 0, 0 (range 0->36) Headset Capture Switch On Headset Capture Volume 1 (range 0->4) Sidetone Playback Switch On Sidetone Playback Volume 4096 (range 0->8192) Headset Playback Switch On Headset Playback Volume 20, 20 (range 0->24) USB Offload Playback Route PCM#0 0, 1 (range -1->255) The "USB Offload Playback Route PCM#*" kcontrol will signify the corresponding card and pcm device it is offload to. (card#0 pcm - device#1) If the USB SND device supports multiple audio interfaces, then it will contain several PCM streams, hence in those situations, it is expected that there will be multiple playback route kcontrols created. Signed-off-by: Wesley Cheng --- sound/soc/qcom/qdsp6/q6usb.c | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c index 36c441d621fb..d8f1bb4ec497 100644 --- a/sound/soc/qcom/qdsp6/q6usb.c +++ b/sound/soc/qcom/qdsp6/q6usb.c @@ -124,6 +124,94 @@ static int q6usb_audio_ports_of_xlate_dai_name(struct snd_soc_component *compone return ret; } +static int q6usb_get_pcm_id_from_widget(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_dai *dai; + + for_each_card_rtds(w->dapm->card, rtd) { + dai = snd_soc_rtd_to_cpu(rtd, 0); + /* + * Only look for playback widget. RTD number carries the assigned + * PCM index. + */ + if (dai->stream[0].widget == w) + return rtd->num; + } + + return -1; +} + +static int q6usb_usb_mixer_enabled(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_path *p; + + /* Checks to ensure USB path is enabled/connected */ + snd_soc_dapm_widget_for_each_sink_path(w, p) + if (!strcmp(p->sink->name, "USB Mixer") && p->connect) + return 1; + + return 0; +} + +static int q6usb_get_pcm_id(struct snd_soc_component *component) +{ + struct snd_soc_dapm_widget *w; + struct snd_soc_dapm_path *p; + int pidx; + + /* + * Traverse widgets to find corresponding FE widget. The DAI links are + * built like the following: + * MultiMedia* <-> MM_DL* <-> USB Mixer* + */ + for_each_card_widgets(component->card, w) { + + if (!strncmp(w->name, "MultiMedia", 10)) { + /* + * Look up all paths associated with the FE widget to see if + * the USB BE is enabled. The sink widget is responsible to + * link with the USB mixers. + */ + snd_soc_dapm_widget_for_each_sink_path(w, p) { + if (q6usb_usb_mixer_enabled(p->sink)) { + pidx = q6usb_get_pcm_id_from_widget(w); + return pidx; + } + } + } + } + + return -1; +} + +static int q6usb_get_offload_dev(struct snd_soc_component *component, + int card, int pcm, enum snd_soc_usb_kctl route) +{ + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + struct snd_soc_usb_device *sdev; + int ret = -1; + + mutex_lock(&data->mutex); + + if (list_empty(&data->devices)) + goto out; + + sdev = list_last_entry(&data->devices, struct snd_soc_usb_device, list); + + if ((card == sdev->card_idx) && (pcm == sdev->pcm_idx)) { + if (route == SND_SOC_USB_KCTL_CARD_ROUTE) + ret = component->card->snd_card->number; + else if (route == SND_SOC_USB_KCTL_PCM_ROUTE) + ret = q6usb_get_pcm_id(component); + } + +out: + mutex_unlock(&data->mutex); + + return ret; +} + static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, struct snd_soc_usb_device *sdev, bool connected) { @@ -193,6 +281,7 @@ static int q6usb_component_probe(struct snd_soc_component *component) return -ENOMEM; usb->connection_status_cb = q6usb_alsa_connection_cb; + usb->get_offload_dev = q6usb_get_offload_dev; snd_soc_usb_add_port(usb); data->usb = usb;