Received: by 2002:a05:7412:1e0b:b0:fc:a2b0:25d7 with SMTP id kr11csp1432338rdb; Fri, 16 Feb 2024 16:25:40 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCW98u9Sc1N6svzR5t2QCW1EC0U+eI+WA3145RW+FeUrfHVRGYrf6eK6AeR0jVMJiv31luVs2ypbusw19ffa4CZSO+gHfVJfqElEby/z5w== X-Google-Smtp-Source: AGHT+IEtHG+EEBW/oSpYZHlAd6nzMzX7Aae9ckyhroxvlnflsMgvAVbyRsOKGg1gGhPAbbU0oFst X-Received: by 2002:a05:6870:cb8c:b0:21e:8fc6:325b with SMTP id ov12-20020a056870cb8c00b0021e8fc6325bmr59423oab.54.1708129539941; Fri, 16 Feb 2024 16:25:39 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708129539; cv=pass; d=google.com; s=arc-20160816; b=DrqtHTbQeDzr5nU2n8GSC1vlzi2QZHVp8JRpfUXPlYAZ0q+XV8M0D4qiWiZj/psb7a paGlY1yS9hxFdWz7s3lnKjZP842/oKxQTHfHsV4vT7oOMCsEPxGByXSQ7JxK4hcz9gqZ Tz+zZcGGWLJ7Q6p93r7t9BBfSTzsAky4TDsINfFtOx/5wRnaGOxx5Zm792MmRIBx1Edv BfsQedYPFYlv47fHieeNDAaRftWgJ4l4pZdAD51dhuwtJm6O+ZsavCKfP3xnSQ2EtLHT qrCQxudR2Q31T9+DaNb+wAt2glzDR6kictZJ4DQC1hshnq0VRt1JKWA6N6imUdI+DljO uUhw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:list-unsubscribe:list-subscribe:list-id:precedence :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=8WSJ8FulDBKQfYgUGO7D0IPBKMSABhMchwkTts6ZjaY=; fh=VKrp0Y7I/+wT36BfKZ6oI/4N9BIwFCn9zerObkOrgGw=; b=Khxl2+qCx0O80wYXJPxbc7CzB92WYpXE6aHPE5eMTMe0+2ydllEsaFcRMo4WnrmGPO vxmz59UWZM8VqMH8nY0MU7Zz8gY6LZ+hdEmCU+WdOXl4MJ1qkGuKAiBe35q3pHHlkX/b fP1Hq9aI+yNLyhl7PQbNb36w/YeoIXJtenR0ZzARIryp3dluS06UxhX25n56o7NtY1Gh +lBPbfiamWkO7rfqeidLF0yYyvIC623/zh8MSEV7xYam+jQAHmvxZFTbOGvvXmuan3Q9 X/cg7fdxREwhJXZaFc+vTl93jRQwaGShe1ROa/OFOnliKgQxBrSrhwl8QEDii6LKo7xG jEGw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=FljXZe8p; arc=pass (i=1 spf=pass spfdomain=quicinc.com dkim=pass dkdomain=quicinc.com dmarc=pass fromdomain=quicinc.com); spf=pass (google.com: domain of linux-kernel+bounces-69568-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-69568-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id e2-20020ac86702000000b0042c4ccf6635si976934qtp.340.2024.02.16.16.25.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Feb 2024 16:25:39 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-69568-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=FljXZe8p; arc=pass (i=1 spf=pass spfdomain=quicinc.com dkim=pass dkdomain=quicinc.com dmarc=pass fromdomain=quicinc.com); spf=pass (google.com: domain of linux-kernel+bounces-69568-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-69568-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 920531C208A1 for ; Sat, 17 Feb 2024 00:25:39 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0A6C1148FFF; Sat, 17 Feb 2024 00:11:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="FljXZe8p" Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 08A8267E82; Sat, 17 Feb 2024 00:11:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708128667; cv=none; b=fLCZ3UbpeJx1GzGGZso97CFcsS/blaCFkhzvXV5Qk5jadDaJ607miyMeJfmcGEx9w4lh/N8GzqTk3dxqw+ePVnq35pjHdQi5X025gN+qxFSnXBtFMubGb7HS+qzGI/QpgQjxFdwbGHIOamgKzP3kTdSX2KnySdD+4NE93gETjxo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708128667; c=relaxed/simple; bh=hk7In+ww81z4Qk7+BraCCdvs1dyXyuUDvjG/d3CCxYY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eNsz1YwxyaPntxEIjzhHg1YTCk+BlZTkFHsVbbSU/pWAmd6Rk9L5I/BbncTl6vzBrH0e6vjShJVv8YuKtoVONrLhlCXcVjEbDMrbvNYpC44wf1Azs8wDJiLQK9pLa984NkJKqKRmJaTFS4wuKm5OPqhPacXgSJ1fN4YDwVQCZ+Y= 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=FljXZe8p; arc=none smtp.client-ip=205.220.180.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 Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 41GNfKZU025501; Sat, 17 Feb 2024 00:10:42 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=8WSJ8FulDBKQfYgUGO7D 0IPBKMSABhMchwkTts6ZjaY=; b=FljXZe8pNsnrpTjt06h2zx7tRUBLYHmYnZgk IsOcEV/sOhSUkLpQZJi1QFYHttGtMPi8WhL0FlZKShvyi+7CQ4p3ddn7kXMkiZN2 n0PBc1iH0ZAAYedwq9hEEcbYE8DAK2icx0LFRanZmLeHuIkBrBJQwLe/DCkhmYhw Zizhr2Dl3P+xdIhbv+Mv58WXSemTG++8rbd62O/vY14rZpj2BbT6Atlc6xZ/YHUw gwmECIoU9yqQsuvX+OpgcjSLgqIv1EUA6Epw4Hr8L3ihuEZpIpZ7sT0i35yoaX/j cFlclZzv3wTuTPxK8BtgNe+KT0CDOFAPZ9l/tN8jtFTBm0Ogiw== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3w9fkfcv5c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sat, 17 Feb 2024 00:10:42 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 41H0AfLH025793 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sat, 17 Feb 2024 00:10:41 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.40; Fri, 16 Feb 2024 16:10:40 -0800 From: Wesley Cheng To: , , , , , , , , , , , , , , CC: , , , , , , , Wesley Cheng Subject: [PATCH v17 40/51] ASoC: qcom: qdsp6: Add SOC USB offload select get/put callbacks Date: Fri, 16 Feb 2024 16:10:06 -0800 Message-ID: <20240217001017.29969-41-quic_wcheng@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20240217001017.29969-1-quic_wcheng@quicinc.com> References: <20240217001017.29969-1-quic_wcheng@quicinc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain 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-ORIG-GUID: aWDbpRiCMMtcpsd-DKiZyVIVREWfG4_9 X-Proofpoint-GUID: aWDbpRiCMMtcpsd-DKiZyVIVREWfG4_9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-02-16_23,2024-02-16_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 malwarescore=0 adultscore=0 lowpriorityscore=0 impostorscore=0 mlxlogscore=999 spamscore=0 bulkscore=0 suspectscore=0 mlxscore=0 phishscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2401310000 definitions=main-2402160189 In order for device selection to be supported, the Q6USB backend DAI link will need to be notified about the device to start the offloading session on. 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 | 115 +++++++++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 4 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c index e539b411c35e..72ec7d45f916 100644 --- a/sound/soc/qcom/qdsp6/q6usb.c +++ b/sound/soc/qcom/qdsp6/q6usb.c @@ -36,9 +36,12 @@ struct q6usb_port_data { struct q6afe_usb_cfg usb_cfg; struct snd_soc_usb *usb; struct q6usb_offload priv; - int active_usb_chip_idx; + struct mutex mutex; unsigned long available_card_slot; struct q6usb_status status[SNDRV_CARDS]; + bool idx_valid; + int sel_card_idx; + int sel_pcm_idx; }; static const struct snd_soc_dapm_widget q6usb_dai_widgets[] = { @@ -54,10 +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 = snd_soc_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].sdev->chip_idx; + + 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_usb_chip_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 = { @@ -88,6 +115,70 @@ 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, + enum snd_soc_usb_kctl type) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + int idx; + + mutex_lock(&data->mutex); + + if (!data->available_card_slot) { + idx = -1; + } else { + if (type == SND_SOC_USB_KCTL_CARD_ROUTE) + idx = data->sel_card_idx; + else + idx = data->sel_pcm_idx; + } + + ucontrol->value.integer.value[0] = idx; + mutex_unlock(&data->mutex); + + return 0; +} + +static int q6usb_put_offload_dev(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + enum snd_soc_usb_kctl type) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct q6usb_port_data *data = dev_get_drvdata(component->dev); + int changed = 0; + int idx; + + idx = ucontrol->value.integer.value[0]; + + mutex_lock(&data->mutex); + switch (type) { + case SND_SOC_USB_KCTL_CARD_ROUTE: + if (idx >= 0 && test_bit(idx, &data->available_card_slot)) { + data->sel_card_idx = idx; + changed = 1; + } + break; + case SND_SOC_USB_KCTL_PCM_ROUTE: + if (idx >= 0 && data->sel_card_idx >= 0 && + idx < data->status[data->sel_card_idx].sdev->num_playback) { + data->sel_pcm_idx = idx; + changed = 1; + } + break; + default: + break; + } + + if (changed) + data->idx_valid = true; + +out: + mutex_unlock(&data->mutex); + + return changed; +} + static int q6usb_audio_ports_of_xlate_dai_name(struct snd_soc_component *component, const struct of_phandle_args *args, const char **dai_name) @@ -117,16 +208,28 @@ 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_usb_chip_idx = sdev->card_idx; + if (!data->idx_valid) { + data->sel_card_idx = sdev->card_idx; + data->sel_pcm_idx = 0; + } set_bit(sdev->card_idx, &data->available_card_slot); data->status[sdev->card_idx].sdev = sdev; } else { clear_bit(sdev->card_idx, &data->available_card_slot); data->status[sdev->card_idx].sdev = NULL; + + if (data->sel_card_idx == sdev->card_idx) { + data->idx_valid = false; + data->sel_card_idx = data->available_card_slot ? + ffs(data->available_card_slot) - 1 : 0; + data->sel_pcm_idx = 0; + } } + mutex_unlock(&data->mutex); return 0; } @@ -142,6 +245,8 @@ static int q6usb_component_probe(struct snd_soc_component *component) return -ENOMEM; usb->connection_status_cb = q6usb_alsa_connection_cb; + usb->put_offload_dev = q6usb_put_offload_dev; + usb->get_offload_dev = q6usb_get_offload_dev; ret = snd_soc_usb_add_port(usb); if (ret < 0) { @@ -205,6 +310,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);