From nobody Mon Jun 8 06:38:15 2026 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 E8B2A3FAE0D; Fri, 5 Jun 2026 10:37:53 +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=1780655875; cv=none; b=L+mdr+C8sEUMr6D9lEeLR81hCSVmGsqEB1k+JICF4i4dg3085V4cWMeAiF0GSu5TAEh7TrnN30x24DNnbCFw1lMhrGLTLSbQk+7YWj9ocJrRy2o8b3b0z3FTARpxcf73EUNg2dU/Ghohs622E/rHaNi95XaBL3WPsBELNW10n0w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655875; c=relaxed/simple; bh=xLBsme/Ea4oMRLJLKcTPHkyOiT08PdUw9WlQvI5WHhM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=BOjA4Nv5AfBab0mUmexcggOnAw/ZxSslEEvtdjZ/4cMeb6iccG+SNEeB30K66pBOBqcmYgu8rKhBoVMZ6bIbAI3zjuhlFD3Nezj4ndGwVBfkzHSZXwBtxljDnb3p6sm2wTmVexWk8fW4mHatnDDYcwB9kCGc1pBopH8zPOaHkeU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=cTIan2iI; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="cTIan2iI" Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6559mDT93016242; Fri, 5 Jun 2026 10:37:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=RIVwUJVZcPN 1G/p+YHx/6pmQFMGEdXIrdWEcjNOBQ80=; b=cTIan2iIOFx++eZLrgoOig0Keje nM8XLKcJNOEHGOviuHdR1iWVGPwisngKnfIVp4QuYqkIHuZNYch128TTI+0dZgtj GdOMJno58efduA3bmFYBw8WHfU1YICuKk3mjlaejRuFS6H8TBlbu02RRUMe2JPDh PABW29wCx1mCjH/WowGQTVqv2KgqKRdseUgroizr5MaD5gY6aC5Q3Z6k1R8GQTBz o3+2th7xsyjvQCSjqsXNRfcrXWLDFcJeklKwjOhM5I/TM8vMKzqMUztN8iYQtMuQ TjWjJB2JzFNTkwnoyrlu9pk5Hdr8f13tIYc9zEO+AbRUrKGmIdA2VoFnGwA== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekv56g6hd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:37:50 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6m011714; Fri, 5 Jun 2026 10:37:47 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/13] dt-bindings: sound: Add Qualcomm QAIF DAI ID header Date: Fri, 5 Jun 2026 16:07:27 +0530 Message-Id: <20260605103739.3557573-2-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfX4EhBkmCBtwGC eBCNppk5nn/JzpSIo58Saw7jRw1uDwcHDSwGg0gG0uhIp6GOyuBHEPGRlBaB7KGNcH+24BVzRBL xjkc4WkmOM4Wct3e8D8igGI4tLB1UL13Dxi7FOPLfSaEf1jGzqXbAtMb7AmHMsxq3Wu9H2nzAXF sRhs1UAzv+Xv96Oj26OdKmVOVt6dSplgUk23VnGv5OkEXie5Jal2g36ZspEyCoMf11MMMtjf1HD nf+M8dz7NpjT/CY/WsvV4ybfmTILJ2yeGXoyL04TUBF+scKOpG1LKMHsA1iZr0xjoNbOpYVDCOo DktKNvZuy9thtXGUb8JT+jWwwUYKbqB3SVkzBn6/BCtZAAzJeWedFXmVDXZd/JX/N1qAdYIk47j 1Spo5NeDi7zBvMB+dzntJWHbvCuw9asnUvkAZLZfmz9w5sbvm9WIVkRmoVAac+FJKf95qQr29rJ 7N0EmCPdJM9MXwBlbTA== X-Authority-Analysis: v=2.4 cv=eJsjSnp1 c=1 sm=1 tr=0 ts=6a22a6ff cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=_glEPmIy2e8OvE2BGh3C:22 a=EUspDBNiAAAA:8 a=OsoMfA4h_Qp2qOXqBcMA:9 X-Proofpoint-ORIG-GUID: 5uD3dJG6nEtM2gNOaVexCrQf6vSFebWb X-Proofpoint-GUID: 5uD3dJG6nEtM2gNOaVexCrQf6vSFebWb X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 impostorscore=0 bulkscore=0 clxscore=1011 spamscore=0 adultscore=0 suspectscore=0 lowpriorityscore=0 priorityscore=1501 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Add a dt-bindings header for the Qualcomm Audio Interface (QAIF) controller DAI IDs. This provides shared constants for devicetree sound-dai references and QAIF aif-interface reg values instead of using raw numeric IDs. Signed-off-by: Harendra Gautam --- include/dt-bindings/sound/qcom,qaif.h | 92 +++++++++++++++++++++++++++++++= +++++ 1 file changed, 76 insertions(+) create mode 100644 include/dt-bindings/sound/qcom,qaif.h diff --git a/include/dt-bindings/sound/qcom,qaif.h b/include/dt-bindings/so= und/qcom,qaif.h new file mode 100644 index 000000000000..72030838c26b --- /dev/null +++ b/include/dt-bindings/sound/qcom,qaif.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * DAI IDs for the Qualcomm Audio Interface (QAIF) controller. + * These values are used in devicetree sound-dai references and as + * the reg value of aif-interface child nodes. + */ +#ifndef __DT_QCOM_QAIF_H +#define __DT_QCOM_QAIF_H + +/* qcom,qaif-aif-sync-mode values */ +#define QAIF_AIF_SYNC_MODE_SHORT 0 /* Short (pulse) sync */ +#define QAIF_AIF_SYNC_MODE_LONG 1 /* Long (level) sync */ + +/* qcom,qaif-aif-sync-src values */ +#define QAIF_AIF_SYNC_SRC_SLAVE 0 /* Sync slave -- clock from external */ +#define QAIF_AIF_SYNC_SRC_MASTER 1 /* Sync master -- drive clock/frame */ + +/* qcom,qaif-aif-lane-config enable values */ +#define QAIF_AIF_LANE_DISABLE 0 +#define QAIF_AIF_LANE_ENABLE 1 + +/* qcom,qaif-aif-lane-config direction values */ +#define QAIF_AIF_LANE_DIR_TX 0 /* TX (playback, speaker) */ +#define QAIF_AIF_LANE_DIR_RX 1 /* RX (capture, mic) */ + +/* + * AIF (Unified Audio Interface) DAI IDs -- AIF0 through AIF12. + * Each AIF supports PCM, TDM and MI2S serial protocols over up to + * 8 independent data lanes sharing a single bit clock and frame sync. + */ +#define QAIF_MI2S_TDM_AIF0 0 +#define QAIF_MI2S_TDM_AIF1 1 +#define QAIF_MI2S_TDM_AIF2 2 +#define QAIF_MI2S_TDM_AIF3 3 +#define QAIF_MI2S_TDM_AIF4 4 +#define QAIF_MI2S_TDM_AIF5 5 +#define QAIF_MI2S_TDM_AIF6 6 +#define QAIF_MI2S_TDM_AIF7 7 +#define QAIF_MI2S_TDM_AIF8 8 +#define QAIF_MI2S_TDM_AIF9 9 +#define QAIF_MI2S_TDM_AIF10 10 +#define QAIF_MI2S_TDM_AIF11 11 +#define QAIF_MI2S_TDM_AIF12 12 + +/* + * CIF (Codec Interface) RX DAI IDs -- playback to internal codec. + * RDDMA channels fetch audio from memory and drain it to the codec. + */ +#define QAIF_CDC_DMA_RX0 13 +#define QAIF_CDC_DMA_RX1 14 +#define QAIF_CDC_DMA_RX2 15 +#define QAIF_CDC_DMA_RX3 16 +#define QAIF_CDC_DMA_RX4 17 +#define QAIF_CDC_DMA_RX5 18 +#define QAIF_CDC_DMA_RX6 19 +#define QAIF_CDC_DMA_RX7 20 +#define QAIF_CDC_DMA_RX8 21 +#define QAIF_CDC_DMA_RX9 22 + +/* + * CIF (Codec Interface) TX DAI IDs -- capture from internal codec. + * WRDMA channels collect audio from the codec and write it to memory. + */ +#define QAIF_CDC_DMA_TX0 23 +#define QAIF_CDC_DMA_TX1 24 +#define QAIF_CDC_DMA_TX2 25 +#define QAIF_CDC_DMA_TX3 26 +#define QAIF_CDC_DMA_TX4 27 +#define QAIF_CDC_DMA_TX5 28 +#define QAIF_CDC_DMA_TX6 29 +#define QAIF_CDC_DMA_TX7 30 +#define QAIF_CDC_DMA_TX8 31 +#define QAIF_CDC_DMA_TX9 32 + +/* + * CIF (Codec Interface) VA TX DAI IDs -- capture from voice activity code= c. + * WRDMA channels collect audio from the VA codec and write it to memory. + */ +#define QAIF_CDC_DMA_VA_TX0 33 +#define QAIF_CDC_DMA_VA_TX1 34 +#define QAIF_CDC_DMA_VA_TX2 35 +#define QAIF_CDC_DMA_VA_TX3 36 +#define QAIF_CDC_DMA_VA_TX4 37 +#define QAIF_CDC_DMA_VA_TX5 38 +#define QAIF_CDC_DMA_VA_TX6 39 +#define QAIF_CDC_DMA_VA_TX7 40 +#define QAIF_CDC_DMA_VA_TX8 41 +#define QAIF_CDC_DMA_VA_TX9 42 + +#endif /* __DT_QCOM_QAIF_H */ -- 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 B776D4183CD; Fri, 5 Jun 2026 10:37:55 +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=1780655877; cv=none; b=c8lPHVA+jK0ZgTsDyNHlPGpBtxu1tS/0NyWzFIq1s0GCTkrh0Y4H5MZoyWtM1j7fbhG9TUYee/MjLaW7tylrGdFExzUdSh2jF8MwzzksYMpqBeB8tOnrfWDSEr9HVALa88xTd3MrFWYN4vuzO6zi5kfq5jX265NIfDBDoI6gOG8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655877; c=relaxed/simple; bh=zuk8XiQNs/JAyL1uFTnxn+zjPUc0+Kg3ZQeCk8+o4vg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=YR+VbIlwJ213AYFZqXm1MjJLG6K8LG6YSBZpfhVGfu1hV1LqNYLSkS/voJ8oHwpyJ7MviXCJUMZxcMlVD6fzwWmBfEyLb6YaYZ5E/phjAe8/jh0A2hRnn1gjS5lhYjPMQTc9KVyqjSe0wgni14vt7WvzweSkErUiW0InlKXTja0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=kgkDNREx; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="kgkDNREx" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6556Oawe3112461; Fri, 5 Jun 2026 10:37:53 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= jgzmhYHrpG0Ff/CL+iSKnmwN0NIEacRz4ArN4DDbdOs=; b=kgkDNREx46XTKlj6 g1SxXDfzBww7r+EMzEPInzbt+cnOnjJICml6n3DlyWqMtLqK+0avNvMYDGS2CQvn 1cc46DaeAAOvcdleIBUWf+W5+qf4bEYBX8HYkM90Z7W6v12Ieyoeq1oa0wZ6/1pK VqlmlQNUQxFjKqS+cb4Ol42kxzsOxbaYrlpqiZDnx2FDysmPJ01chV9UVoZbNDcN YMlExU86Q2Zv7BAdgpKvWuLrBMRws3dODpvaPb5+3HNWj3gK/hioRC9HyDumc7ro hxWyF6jCkXeRZSpIAQksOypX6xXxx0giiXNDi4GKpMWqqAkTZGxHmZVaWJsBsw73 sEainA== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekfv732yj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:37:52 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6n011714; Fri, 5 Jun 2026 10:37:49 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/13] dt-bindings: sound: Add Qualcomm QAIF binding Date: Fri, 5 Jun 2026 16:07:28 +0530 Message-Id: <20260605103739.3557573-3-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.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; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-GUID: DXrFP0_MecdF69zEtYd5ECu5HvHTBAsm X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfX62PK47UggQK0 lkTwntA5sAIAahrySXlHRjHxccWawLhxNRzwPJ2UrxBZvKQZVEI3ZVhjBWfM1VLZy+zWQlbseAn BWETxjS39j0mqq+hI1L0JK5HzVcrIQvtFHs5vYAYu23dK2ERJKjRPkWXdqSnoqDH7MsqHZklvtq xoB9/EYgTs5MdBL77s7jfSf2D0ArOMRYkIMk1+Sx3kITn7B23gX43rR9DsiEuYsdzobdOdkPQtG 3IAHGzmqQ9beMvOFvebIdmzBxuDFaoH54bGulukCYW+irC5mgEF0nePagD+gPNGZ7kCbcft+RsQ uRMdzeAJ/JlClsBO+RR2uSDTcPqraoiJJhtTXq3EuOOgyfgmy6iN1b2MUyZG9XraefeFxVMzMp4 1bEsaSlykmkjxdMjZ30fkOTZBte6oJPOJ12pm1dFhT7V7MK8eGa5bbHQrJQ6bbZqkpojZSweCAk 9T5GBTq1d/oqNNQ96hA== X-Authority-Analysis: v=2.4 cv=JNULdcKb c=1 sm=1 tr=0 ts=6a22a700 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=IkcTkHD0fZMA:10 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=DJpcGTmdVt4CTyJn9g5Z:22 a=gEfo2CItAAAA:8 a=EUspDBNiAAAA:8 a=2W7YXHVdVEJxzfH0i0IA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=sptkURWiP4Gy88Gu7hUp:22 X-Proofpoint-ORIG-GUID: DXrFP0_MecdF69zEtYd5ECu5HvHTBAsm X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 lowpriorityscore=0 impostorscore=0 suspectscore=0 spamscore=0 clxscore=1015 adultscore=0 priorityscore=1501 malwarescore=0 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Add a Devicetree binding for the Qualcomm Audio Interface (QAIF) CPU DAI controller used on the Shikra audio platform. QAIF moves PCM data between system memory and external serial audio interfaces through the AIF path, and between memory and the internal Bolero digital codec through the CIF path. The controller needs a binding so platform Devicetree files can describe its MMIO region, DMA IOMMU stream, clocks, interrupt, DAI cells and per-interface AIF configuration. Describe the single register region, one EE interrupt, the required GCC LPASS and audio core clocks, the DMA IOMMU mapping, and 'aif-interface@N' child nodes used for static PCM, TDM or MI2S configuration. Signed-off-by: Harendra Gautam --- .../devicetree/bindings/sound/qcom,qaif.yaml | 353 ++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,qaif.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,qaif.yaml b/Docum= entation/devicetree/bindings/sound/qcom,qaif.yaml new file mode 100644 index 000000000000..5b385e05a650 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,qaif.yaml @@ -0,0 +1,361 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,qaif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Audio Interface (QAIF) CPU DAI Controller + +maintainers: + - Harendra Gautam + +description: + | + The Qualcomm Audio Interface (QAIF) is a fully configurable DMA-based + audio subsystem controller. It serialises and deserialises PCM audio + between system memory and external serial audio peripherals (PCM, TDM, + I2S, MI2S) through the AIF path, and transfers parallel audio between + memory and an internal WCD codec through the CIF path. + + AIF (Audio Interface): up to 13 multi-lane Unified Audio Interfaces, + each supporting up to 8 independent data lanes. Each lane is individually + configurable as TX (output/speaker) or RX (input/mic). All lanes of an + interface share a single bit clock and frame sync. Supported modes are + PCM (short/long sync), TDM, and MI2S (stereo/mono). Per-interface + configuration includes sync source (master/slave), sync mode, sync delay, + sync inversion, slot width (8/16/24/32-bit), sample width, active slot + masks (up to 32 slots), bits-per-lane frame size, lane enable/direction + masks, loopback, output-enable control, and full-cycle path support for + long chip-to-chip connections. + + CIF (Codec Interface): up to 32 RDDMA (playback) and 32 WRDMA (capture) + channels connecting to an internal codec over a parallel bus. Each chann= el + supports active-channel enable mask (up to 16 channels), frame-sync + selection, frame-sync delay, frame-sync output gating, dynamic clock + gating, and 16-bit packing/unpacking. + + Note on RX/TX naming convention: in QAIF, RX refers to the capture path + (audio received from the interface into memory) and TX refers to the + playback path (audio transmitted from memory to the interface). This + applies to both AIF lane directions and CIF slot/mask properties. + + DMA engine: RDDMA fetches audio from DDR/TCM/LPM into a shared SRAM + latency buffer (SHRAM) and drains it to the interface. WRDMA collects + data from the interface into SHRAM and writes it to memory. Each DMA + owns a private SHRAM region defined by start address and length register= s. + Burst sizes of 1/2/4/8/16 beats (64-bit) are supported with up to 4 + outstanding transactions per DMA. Two QSB master ports (QXM0 for TCM, + QXM1 for DDR/LPM) provide the memory interface. + + Resources are partitioned among up to 5 Execution Engines (EEs) via + EE map registers. Each EE owns a set of DMAs, audio interfaces, and + interface groups, and receives its own independent interrupt output. + The interrupt hierarchy has a two-level structure: a summary register + identifies the event class (DMA period, underflow/overflow, error + response, audio interface underflow/overflow, group done, rate detector, + VFR), and per-resource status registers identify the specific channel. + + Interface grouping (bonding) allows up to 6 groups of audio and codec + interfaces to start synchronously and align their DMA period interrupts + within half a frame duration using the RDDMA padding feature. + + Two rate detector blocks measure the frequency of incoming frame sync or + word select signals and generate interrupts on rate change, undetected + rate, or sync timeout. + + Block diagram:: + + System Memory (DDR / LPM / TCM) + +---------------------------------+ + | Circular Buffers (ping-pong) | + +----------+----------+-----------+ + | ^ + 64-bit AXI 64-bit AXI + | | + +----------v----------+-----------+ + | QSB Master Ports | + | +----------+ +----------+ | + | | QXM0 | | QXM1 | | + | +----+-----+ +-----+----+ | + +-------|--------------|----------+ + | | + +-------v--------------v----------+ + | Shared RAM (SHRAM) | + | +------------+ +------------+ | + | | QXM0 Read | | QXM0 Write | | + | | SHRAM | | SHRAM | | + | +------------+ +------------+ | + | +------------+ +------------+ | + | | QXM1 Read | | QXM1 Write | | + | | SHRAM | | SHRAM | | + | +------------+ +------------+ | + +---+--------+--------+-------+---+ + | | | | + +---v--+ +--v---+ +--v---+ +-v----+ + |RDDMA | |RDDMA | |WRDMA | |WRDMA | + | AIF | | CIF | | AIF | | CIF | + |[0..n]| |[0..n]| |[0..n]| |[0..n]| + +--+---+ +--+---+ +--+---+ +-+----+ + | | ^ ^ + | TX | TX | RX | RX + v v | | + +--+--------------------+ +----+----------+ + | Unified Audio Intf | | Codec DMA | + | (AIF 0..12) | | Interface | + | | | (CIF) | + | AUD_INTFa block: | | | + | - Serializer (TX) | | RDDMA: DDR -> | + | - De-serializer (RX) | | internal | + | - Sync gen/detect | | codec | + | - Up to 8 data lanes | | WRDMA: codec | + | - PCM / TDM / MI2S | | -> DDR | + | - Near Pad Logic | | Up to 16 ch | + +--+--------------------+ +----+----------+ + | Lane 0..7 (TX/RX) | Parallel bus + | Bit clk + Frame sync | + Frame sync + v v + +--+--------+ +------+------+ + | External | | Internal | + | Serial | | Digital | + | Peripherals| | Codec | + | (PCM/TDM/ | | (Bolero/ | + | MI2S) | | WCD) | + +-----------+ +-------------+ + +properties: + compatible: + enum: + - qcom,shikra-qaif-cpu + + reg: + maxItems: 1 + + iommus: + maxItems: 1 + + clocks: + minItems: 15 + maxItems: 15 + + clock-names: + items: + - const: lpass_config_clk + - const: lpass_core_axim_clk + - const: aud_dma_clk + - const: aud_dma_mem_clk + - const: bus_clk + - const: aif_if0_ebit_clk + - const: aif_if0_ibit_clk + - const: aif_if1_ebit_clk + - const: aif_if1_ibit_clk + - const: aif_if2_ebit_clk + - const: aif_if2_ibit_clk + - const: aif_if3_ebit_clk + - const: aif_if3_ibit_clk + - const: ext_mclka_clk + - const: ext_mclkb_clk + + interrupts: + maxItems: 1 + + '#sound-dai-cells': + const: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + status: true + +patternProperties: + "^aif-interface@[0-9a-f]+$": + type: object + description: + AIF interface configuration child node. The compatible string + identifies the serial protocol the interface is wired for on the + board. The unit address matches the hardware AIF interface index. + properties: + compatible: + enum: + - qcom,qaif-pcm-dai + - qcom,qaif-tdm-dai + - qcom,qaif-mi2s-dai + reg: + maxItems: 1 + description: | + Hardware AIF interface index (AUD_INTFa block index). This value + also serves as the ALSA DAI ID; it corresponds directly to the + QAIF_MI2S_TDM_AIFn constants in + (e.g. reg =3D <2> selects QAIF_MI2S_TDM_AIF2). + qcom,qaif-aif-sync-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Sync mode. Use QAIF_AIF_SYNC_MODE_SHORT (0) for short (pulse) + sync or QAIF_AIF_SYNC_MODE_LONG (1) for long (level) sync. + qcom,qaif-aif-sync-src: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Sync source. Use QAIF_AIF_SYNC_SRC_SLAVE (0) for slave mode + or QAIF_AIF_SYNC_SRC_MASTER (1) for master mode. + qcom,qaif-aif-invert-sync: + type: boolean + description: Invert the frame sync polarity. + qcom,qaif-aif-sync-delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Number of bit-clock cycles to delay the data relative= to sync. + qcom,qaif-aif-slot-width-rx: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + RX slot width in bits. This is a board-specific hardware constra= int + determined by the wiring of the serial audio interface. + qcom,qaif-aif-slot-width-tx: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + TX slot width in bits. This is a board-specific hardware constra= int + determined by the wiring of the serial audio interface. + qcom,qaif-aif-slot-en-rx-mask: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Bitmask of active RX slots. Board-specific =E2=80=94 determined = by which + TDM slots the codec is wired to on this board. + qcom,qaif-aif-slot-en-tx-mask: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Bitmask of active TX slots. Board-specific =E2=80=94 determined = by which + TDM slots the codec is wired to on this board. + qcom,qaif-aif-loopback: + type: boolean + description: Enable loopback mode (presence enables loopback). + qcom,qaif-aif-ctrl-data-oe: + type: boolean + description: Enable output drive on the control/data line. + qcom,qaif-aif-lane-config: + $ref: /schemas/types.yaml#/definitions/uint32-matrix + description: + Lane configuration matrix. Each row is a pair + for one lane starting from lane 0, up to 8 lanes. Use + QAIF_AIF_LANE_ENABLE (1) or QAIF_AIF_LANE_DISABLE (0) for enable. + Use QAIF_AIF_LANE_DIR_TX (0) for TX (speaker) or QAIF_AIF_LANE_D= IR_RX + (1) for RX (mic). TX and RX lanes should each be grouped contigu= ously. + maxItems: 8 + items: + items: + - description: Lane enable (0 =3D disabled, 1 =3D enabled) + enum: [0, 1] + - description: Lane direction (0 =3D TX/speaker, 1 =3D RX/mic) + enum: [0, 1] + qcom,qaif-aif-full-cycle-en: + type: boolean + description: Enable full-cycle sync (effective in sync master mode= ). + qcom,qaif-aif-bits-per-lane: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Number of slots per lane. The frame length is computed as + slot-width multiplied by bits-per-lane. + if: + properties: + compatible: + const: qcom,qaif-mi2s-dai + then: + description: + MI2S interface. Sync mode and slot-enable masks are fixed by the + MI2S protocol and must not be set in DT. Mono/stereo mode is + determined at runtime from the stream channel count. + properties: + qcom,qaif-aif-sync-mode: false + qcom,qaif-aif-slot-en-rx-mask: false + qcom,qaif-aif-slot-en-tx-mask: false + else: + description: + PCM or TDM interface. Sync mode and slot-enable masks are + board-specific and must be provided. Mono mode does not apply. + required: + - qcom,qaif-aif-sync-mode + - qcom,qaif-aif-slot-en-rx-mask + - qcom,qaif-aif-slot-en-tx-mask + + required: + - compatible + - reg + additionalProperties: false + +required: + - compatible + - reg + - iommus + - clocks + - clock-names + - interrupts + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + /* Shikra platform example */ + #include + #include + #include + #include + #include + + qaif_cpu: audio@a000000 { + compatible =3D "qcom,shikra-qaif-cpu"; + reg =3D <0x0 0x0a000000 0x0 0x20000>; + iommus =3D <&apps_smmu 0x1c0 0x0>; + clocks =3D <&gcc GCC_LPASS_CONFIG_CLK>, + <&gcc GCC_LPASS_CORE_AXIM_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_MEM_CLK>, + <&audiocorecc AUDIO_CORE_CC_BUS_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK>; + clock-names =3D "lpass_config_clk", + "lpass_core_axim_clk", + "aud_dma_clk", + "aud_dma_mem_clk", + "bus_clk", + "aif_if0_ebit_clk", + "aif_if0_ibit_clk", + "aif_if1_ebit_clk", + "aif_if1_ibit_clk", + "aif_if2_ebit_clk", + "aif_if2_ibit_clk", + "aif_if3_ebit_clk", + "aif_if3_ibit_clk", + "ext_mclka_clk", + "ext_mclkb_clk"; + #sound-dai-cells =3D <1>; + #address-cells =3D <1>; + #size-cells =3D <0>; + interrupts =3D ; + status =3D "okay"; + + qaif_aif_if2: aif-interface@2 { + compatible =3D "qcom,qaif-tdm-dai"; + reg =3D ; + qcom,qaif-aif-sync-mode =3D ; + qcom,qaif-aif-sync-src =3D ; + qcom,qaif-aif-sync-delay =3D <1>; + qcom,qaif-aif-slot-width-rx =3D <32>; + qcom,qaif-aif-slot-width-tx =3D <32>; + qcom,qaif-aif-slot-en-rx-mask =3D <0x3>; + qcom,qaif-aif-slot-en-tx-mask =3D <0x3>; + qcom,qaif-aif-ctrl-data-oe; + /* Lane 0: RX (mic); Lane 1: TX (speaker) */ + qcom,qaif-aif-lane-config =3D , + ; + /* frame length =3D slot-width (32) * bits-per-lane (2) =3D 64= bits */ + qcom,qaif-aif-bits-per-lane =3D <2>; + }; + }; --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 4D27947DD4D; Fri, 5 Jun 2026 10:37:56 +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=1780655877; cv=none; b=OxmcKkdN1DRL4P2xAvQd0SDCrYsxcC6Rgbyn7tyYnZetnyu2XSW2XfJJ5hz3Q4fd7FyB0MmxoCrp5Z97KZuq3meVA3CTbWB0Gv3mmp076vAAgkAzrIo4AAudftd/HN4r/ykSUp82r/d4ZN1qz7zoIMv2+2IW7NzRYLJ4b9ZvllQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655877; c=relaxed/simple; bh=S+zkRagjBtegqBMgsgui4iIZplI9wRsbjfCBDj8tPzs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UhFxKFDSVycOBlgbZZ2vssAE+Yg8IxmBg0PAqVkOWGUFMDlEukFUKgyHbBu5DzxIlAUkoIwOTeSYStfI5TUuYNUq/zr2tzrWmG961XJvRGjKELlUv4wukfAkJF+GODqVIRI+M5LgB/nlm0EN/ONcrQkmCSqdH/UX4zS4LCDaHsw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=eByTKZ3V; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="eByTKZ3V" Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 655757lM3529086; Fri, 5 Jun 2026 10:37:54 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=oL5PHBGnrYW std8r84qxXLacC3Z6sAdPjyiNdFMVLb4=; b=eByTKZ3VEmaNXRkR3wnoFKGJHxT AYLEpOmcZ3ND0esEbNmert7vE9XdlUOK2KZNu6c1+APm2s9K1YQRlvqTAxCMLMCW EtU1WBvgM9bb+Q0EufHCnIzfOuWtVlfRxgcTx8V984ItOmYKs52x1cDrLM7EnFWr r/3RhANEetVCXjsa+61lYMNH+NNWEZ8WvMiiY6l0mISVlA4qkhE6lh3gyPafLU87 UPHosirOIBbbEHyg2P3Q+JMlSUbYhiaV2qYk6UwI2lWLtUo2/wRBL0t/V0VlkZ7K mEq3Agvbjp3ISa124hk3beTznrpsivi6qS3WcIifZjn8C7qYJQeMqNR5lEA== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4eksrp8tmn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:37:53 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6o011714; Fri, 5 Jun 2026 10:37:50 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/13] MAINTAINERS: Add Qualcomm QAIF driver entry Date: Fri, 5 Jun 2026 16:07:29 +0530 Message-Id: <20260605103739.3557573-4-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-GUID: e39XlA5FrT11Zej7XoSr7udHXQMF_0oN X-Proofpoint-ORIG-GUID: e39XlA5FrT11Zej7XoSr7udHXQMF_0oN X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfXzpEDS8QrjiaB yxRhQh5245Eakky+fBazfy0IQ1Kqlkns8id8E24baeC14LVtxcrxcqaiTJb/UgPIFOyXI/7+Lxg Hlv3vqnbJ01OqSiZLTisjQWpQJWNs3FWFb3dNnV3VWyPYzmPT/6lGsVWdrXT9hfTuZkCv3ruKP2 /7E/10M6Z5KkX0J+Wby/UQefelpi74YZUX/VUuyTGs25Wu4XV0VOBel+EHyGuTEWv6g5SBlweOx pIBFC44XB7s4e+CRFXsNMC2AoiKMAqYt33ybLmiGdrMf04o2E7bEd0vOxS4ZYw9Kw3xxIjAdMoQ GkeAvaFs3oHV6eivL6mVd3HJtqFBCtK0YYgcsK0UmmWwWP71bAM2gHVA+fF/bytt1uESzYOdApK BL4ZMLkpgTquXWUg8E/aTTUgmD5PxEGYhuJGi7tHu/hRkSG1kX2ByZuoeHsCw23oUJA6T3SupvC wJ7yTxCk7nYXZhGVuBA== X-Authority-Analysis: v=2.4 cv=bJEm5v+Z c=1 sm=1 tr=0 ts=6a22a702 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=YMgV9FUhrdKAYTUUvYB2:22 a=EUspDBNiAAAA:8 a=VwQbUJbxAAAA:8 a=COk6AnOGAAAA:8 a=5TfRDjBtmgYofzZU2EMA:9 a=TjNXssC_j7lpFel5tvFf:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 lowpriorityscore=0 bulkscore=0 priorityscore=1501 spamscore=0 impostorscore=0 adultscore=0 clxscore=1011 malwarescore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Add MAINTAINERS coverage for the Qualcomm Audio Interface (QAIF) driver so changes to its devicetree binding, CPU DAI driver, and PCM platform driver are routed to the Qualcomm ASoC maintainers and lists. Signed-off-by: Harendra Gautam --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f877e5aaf2c7..b38f03680ef3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21707,6 +21707,16 @@ F: sound/soc/codecs/wcd93*.* F: sound/soc/codecs/wsa88*.* F: sound/soc/qcom/ =20 +QCOM AUDIO INTERFACE (QAIF) DRIVER +M: Harendra Gautam +M: Srinivas Kandagatla +L: linux-sound@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/sound/qcom,qaif.yaml +F: include/dt-bindings/sound/qcom,qaif.h +F: sound/soc/qcom/qaif* + QCOM EMBEDDED USB DEBUGGER (EUD) M: Souradeep Chowdhury L: linux-arm-msm@vger.kernel.org -- 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 D5E7C4BC012; Fri, 5 Jun 2026 10:37:58 +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=1780655881; cv=none; b=bewW/IKB7SM74lJGXlRjQhAimp8NC+jzQ2lb9F1aNftbp3q1yx2HX9LCt4Yx5B00yqRbniL1Pp2QSEemn0zG8n7XIObYcf7tLup1hJGhid4ZFwoUdocqDqXHUF1rpjkezrgdbxouBIOGWhCASbZNpbDwayczWE7dF398y32gJt8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655881; c=relaxed/simple; bh=6Bau6eWF3OGZbph4DhBnNqwUvTGQCcIfsMmBpA4jPbU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=s0XE2ferCnZCPNIiEM22QSaFGyHcTuGAB3Xygkj596P8lSs9FDua3CuLVQ38MNHgZAK9m/6ASvjP38WlcQ0JGAAuKQgqmmHPvuOdsKta4KoKFmWks8Qh4ObdnzZHAega7Wyg0Clj4HNpgCtsCXKIhbcO28QA/pnCQsJfLVhgdM4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=a+/SXAiZ; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="a+/SXAiZ" Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 655A4KC82975103; Fri, 5 Jun 2026 10:37:55 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=FJ9WJrzJB+H GT0aua/Hyv4If1KBHQbm8D8NXwMK4R14=; b=a+/SXAiZbwPCz8uAyh2znQ7ukSl ZGcR057e8tlZeKDcDTP+t2SYgOUOn277qmdmjkWpXUv8fLyJL6W5va2Qu5/4Zyqt fptrmmdxy6z9G/n3cuf/bHC0wCmSvTAC5Z8YDuriiKoMm2qiDAKIPA67fcPZRywe 9InirxmuHMdTqrz5BAMO8KVibUmf1BDKH31VAVBMxva6Myk50RhLo78yJNABewcg eHhoe1Q8Z6i0AgvG4Xax3hz83lwHI1Cv5sknGtDux1yVYCw2nwUCpYUpVnkMnBJW KHPNilVJirEfYhSkkJjI/4+/iC0JCOzTRcVuQYcaakdn5G0v/odmwYUdIEQ== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekpnu9hcm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:37:54 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6p011714; Fri, 5 Jun 2026 10:37:51 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/13] ASoC: qcom: Add QAIF hardware register map Date: Fri, 5 Jun 2026 16:07:30 +0530 Message-Id: <20260605103739.3557573-5-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-GUID: H8DTCX_OFun0ds8cmRJPFzlTsv4_np-F X-Authority-Analysis: v=2.4 cv=Ksl9H2WN c=1 sm=1 tr=0 ts=6a22a703 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=3WHJM1ZQz_JShphwDgj5:22 a=EUspDBNiAAAA:8 a=WaxOdm7N1IIUbwD4DyAA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfX27Lgy26aXFeI IDlF2xXlsByQ2DUuvDcxOAbkCRVEw6ERYb8H8ClIQH6xo6gzhi/uc7OiKfgEcR6u1ih8G4abEOb FLbv2DGcIjX2KvTvDtqSXmKelaWHRWt12/1qqtxGai+YfG5OKkC7EPx2GVP3q8WWHHh1u2ehMop HrXC2Z6hSTbYNlPeYcIhuHe2CriSDpZ2CKdEs7MbiQ889OOlhy/Eyg+dmmcjXhctPFNA9/tFrPN 1RzA7T4Sz/cmOu+YWFURv+YzZsVoH4Rc5sDmDORPkg0dp/pl27WMkucsKYSMNGHFTr13mzck3pz DOi9aCn7618h2qmNtOchI6aQqD1sMgpry6Zqt3tYLW/uukALKtu3sCaJkODL8tRNO2RwS5DY/Ce MxdW2XclVwpjCeptdFVDkKREJ3H/qGY+ZwuKqjyYwaF/v2q4qvizMJgS577s6cKNb/hs4a8TA4i iFPo0Ke3EocuYsJTs1Q== X-Proofpoint-ORIG-GUID: H8DTCX_OFun0ds8cmRJPFzlTsv4_np-F X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 phishscore=0 clxscore=1015 priorityscore=1501 adultscore=0 lowpriorityscore=0 spamscore=0 malwarescore=0 bulkscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Add qaif-reg.h with the MMIO register definitions for the Qualcomm Audio Interface (QAIF) hardware block. The QAIF driver needs these definitions to program the core registers, audio interfaces, AIF/CIF DMA channels, interrupt registers, SHRAM/QXM routing, and SID maps. Also add common accessor macros so the driver can select the appropriate AIF or CIF DMA register set based on the DAI ID. Signed-off-by: Harendra Gautam --- sound/soc/qcom/qaif-reg.h | 405 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100644 sound/soc/qcom/qaif-reg.h diff --git a/sound/soc/qcom/qaif-reg.h b/sound/soc/qcom/qaif-reg.h new file mode 100644 index 000000000000..1034b50b431a --- /dev/null +++ b/sound/soc/qcom/qaif-reg.h @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-reg.h -- ALSA SoC CPU-Platform DAI driver register header file for= QTi QAIF + */ +#ifndef __QAIF_REG_H__ +#define __QAIF_REG_H__ + +#include "qaif.h" + +#define QAIF_SUMMARY_IRQSTAT_REG(v) (0x19188 + (0x1000 * (v->ee))) + + +/* Core HW info */ +#define QAIF_HW_VERSION_REG (0x0000) +#define QAIF_HW_INFO_REG (0x0004) +#define QAIF_HW_INFO2_REG (0x0008) + +/* Interface lane and channel info */ +#define QAIF_AUD_INTF_LANE_INFO_REG (0x0020) +#define QAIF_AUD_INTF_LANE_INFO2_REG (0x0024) +#define QAIF_CODEC_TX_INTF_CH_INFO_REG(n) (0x0028 + (0x4= * (n))) +#define QAIF_CODEC_RX_INTF_CH_INFO_REG(n) (0x0068 + (0x4= * (n))) +#define QAIF_QXM1_SHRAM_LENGTH_INFO_REG (0x0088) +#define QAIF_QXM0_SHRAM_LENGTH_INFO_REG (0x008C) +#define QAIF_NUM_AUD_INTF_TO_RAIL_INFO_REG (0x0090) + +/* Debug/control and status */ +#define QAIF_DEBUG_CTL_REG (0x0200) +#define QAIF_WRDMA_LOOPBACK_EN_REG (0x0204) +#define QAIF_WRDMA_LOOPBACK_SEL_REG (0x0208) +#define QAIF_SHRAM_DYNAMIC_CLK_GATING_EN_REG (0x0300) +#define QAIF_AXI_STATUS_REG (0x0304) +#define QAIF_QSB_DYNAMIC_CLK_GATING_EN_REG (0x0308) +#define QAIF_START_STOP_CTRL_BYPASS_EN_REG (0x030C) +#define QAIF_QXM0_AXI_ATTR_CFG_REG (0x040C) + +/* QXM request/grant debug */ +#define QAIF_QXM0_AUD_WR_REQ_GNT_DBG_STAT_REG (0x0500) +#define QAIF_QXM1_AUD_WR_REQ_GNT_DBG_STAT_REG (0x0504) +#define QAIF_QXM0_CODEC_RX_WR_REQ_DBG_STAT_REG (0x0508) +#define QAIF_QXM0_CODEC_RX_WR_GNT_DBG_STAT_REG (0x050C) +#define QAIF_QXM1_CODEC_RX_WR_REQ_DBG_STAT_REG (0x0510) +#define QAIF_QXM1_CODEC_RX_WR_GNT_DBG_STAT_REG (0x0514) +#define QAIF_QXM0_AUD_RD_REQ_GNT_DBG_STAT_REG (0x0518) +#define QAIF_QXM1_AUD_RD_REQ_GNT_DBG_STAT_REG (0x051C) +#define QAIF_QXM0_CODEC_TX_RD_REQ_DBG_STAT_REG (0x0520) +#define QAIF_QXM0_CODEC_TX_RD_GNT_DBG_STAT_REG (0x0524) +#define QAIF_QXM1_CODEC_TX_RD_REQ_DBG_STAT_REG (0x0528) +#define QAIF_QXM1_CODEC_TX_RD_GNT_DBG_STAT_REG (0x052C) +#define QAIF_QXM0_EXT_RDDMA_RD_REQ_GNT_DBG_STAT_REG (0x0530) +#define QAIF_QXM1_EXT_RDDMA_RD_REQ_GNT_DBG_STAT_REG (0x0534) + +/* QSB transaction debug */ +#define QAIF_QSB_AUD_WR_TXN_DBG_STAT_REG (0x0538) +#define QAIF_QSB_CODEC_RX_WR_TXN_ERR_DBG_STAT_REG (0x053C) +#define QAIF_QSB_CODEC_RX_WR_TXN_OKAY_DBG_STAT_REG (0x0540) +#define QAIF_QSB_AUD_ADDR_SENT_DBG_STAT_REG (0x0544) +#define QAIF_QSB_CODEC_TX_RD_ADDR_SENT_DBG_STAT_REG (0x0548) +#define QAIF_QSB_EXT_RDDMA_RD_ADDR_SENT_DBG_STAT_REG (0x054C) +#define QAIF_QSB_CODEC_RX_WR_ADDR_SENT_DBG_STAT_REG (0x0550) +#define QAIF_QSB_AUD_RD_TXN_DBG_STAT_REG (0x0554) +#define QAIF_QSB_CODEC_TX_RD_TXN_ERR_DBG_STAT_REG (0x0558) +#define QAIF_QSB_CODEC_TX_RD_TXN_RCVD_DBG_STAT_REG (0x055C) +#define QAIF_QSB_EXT_RDDMA_RD_TXN_DBG_STAT_REG (0x0560) +#define QAIF_QSB_MISC_DBG_STATUS_REG (0x0564) + +/* Global spare and HWE */ +#define QAIF_GLOBAL_SPARE_IN_REG (0x0B00) +#define QAIF_GLOBAL_SPARE_OUT_REG (0x0B04) +#define QAIF_HWE_CFG_REG (0x0B08) + +/* SID maps */ +#define QAIF_WRDMA_SID_MAP_REG (0x1B00) +#define QAIF_CODEC_WRDMA_SID_MAP_REG (0x1B40) +#define QAIF_RDDMA_SID_MAP_REG (0x1C00) +#define QAIF_CODEC_RDDMA_SID_MAP_REG (0x1C40) + +/* EE overlap interrupts */ +#define QAIF_EE_OVERLAP_IRQ_EN_REG (0x1D00) +#define QAIF_EE_OVERLAP_IRQ_RAW_STATUS_REG (0x1D04) +#define QAIF_EE_OVERLAP_IRQ_CLEAR_REG (0x1D08) +#define QAIF_EE_OVERLAP_IRQ_FORCE_REG (0x1D0C) + +/* EE assignments and maps */ +#define QAIF_EE_RDDMA_ASSIGNMENT_REG(v) (0x19148 + (0x= 1000 * (v->ee))) +#define QAIF_EE_WRDMA_ASSIGNMENT_REG(v) (0x19150 + (0x= 1000 * (v->ee))) +#define QAIF_EE_INTF_ASSIGNMENT_REG(v) (0x19158 + (0x= 1000 * (v->ee))) +#define QAIF_EE_CODEC_RDDMA_ASSIGNMENT_REG(v) (0x19308 + (0x= 1000 * (v->ee))) +#define QAIF_EE_CODEC_WRDMA_ASSIGNMENT_REG(v) (0x19318 + (0x= 1000 * (v->ee))) +#define QAIF_EE_RDDMA_MAP_REG(v) (0x1920 + (0x1= 000 * (v->ee))) +#define QAIF_EE_WRDMA_MAP_REG(v) (0x1940 + (0x1= 000 * (v->ee))) +#define QAIF_EE_INTF_MAP_REG(v) (0x1960 + (0x1= 000 * (v->ee))) +#define QAIF_EE_CODEC_RDDMA_MAP_REG(v) (0x1980 + (0x1= 000 * (v->ee))) +#define QAIF_EE_CODEC_WRDMA_MAP_REG(v) (0x1A00 + (0x1= 000 * (v->ee))) + +/* EE rate-detection and VFR interrupts */ +#define QAIF_EE_RATE_DET_IRQ_EN_REG(v) (0x190F0 + (0x= 1000 * (v->ee))) +#define QAIF_EE_RATE_DET_IRQ_STATUS_REG(v) (0x190F4 + (0x= 1000 * (v->ee))) +#define QAIF_EE_RATE_DET_IRQ_RAW_STATUS_REG(v) (0x190F8 + (0x= 1000 * (v->ee))) +#define QAIF_EE_RATE_DET_IRQ_CLEAR_REG(v) (0x190FC + (0x= 1000 * (v->ee))) +#define QAIF_EE_RATE_DET_IRQ_FORCE_REG(v) (0x19100 + (0x= 1000 * (v->ee))) + +#define QAIF_EE_VFR_IRQ_EN_REG(v) (0x19104 + (0x= 1000 * (v->ee))) +#define QAIF_EE_VFR_IRQ_STATUS_REG(v) (0x19108 + (0x= 1000 * (v->ee))) +#define QAIF_EE_VFR_IRQ_RAW_STATUS_REG(v) (0x1910C + (0x= 1000 * (v->ee))) +#define QAIF_EE_VFR_IRQ_CLEAR_REG(v) (0x19110 + (0x= 1000 * (v->ee))) +#define QAIF_EE_VFR_IRQ_FORCE_REG(v) (0x19114 + (0x= 1000 * (v->ee))) + +/* EE AUD_INTF underflow/overflow interrupts */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_EN_REG(v) (0x19160 + (0x= 1000 * (v->ee))) +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_STATUS_REG(v) (0x19164 + (0x= 1000 * (v->ee))) +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_RAW_STATUS_REG(v) (0x19168 + (0x= 1000 * (v->ee))) +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_CLEAR_REG(v) (0x1916C + (0x= 1000 * (v->ee))) +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_FORCE_REG(v) (0x19170 + (0x= 1000 * (v->ee))) + +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_EN_REG(v) (0x19174 + (0x= 1000 * (v->ee))) +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_STATUS_REG(v) (0x19178 + (0x= 1000 * (v->ee))) +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_RAW_STATUS_REG(v) (0x1917C + (0x= 1000 * (v->ee))) +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_CLEAR_REG(v) (0x19180 + (0x= 1000 * (v->ee))) +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_FORCE_REG(v) (0x19184 + (0x= 1000 * (v->ee))) + +/* EE L2 Period IRQ mux selection */ +#define QAIF_EE_L2_PERIOD_IRQ_0_3_MUX_SEL_REG(v) (0x19F00 + (0x= 1000 * (v->ee))) +#define QAIF_EE_L2_PERIOD_IRQ_4_7_MUX_SEL_REG(v) (0x19F04 + (0x= 1000 * (v->ee))) + +/* AUD_INTF block (per interface, stride 0x1000 starting at 0x4000) */ +#define QAIF_AUD_INTF_REG_ADDR(offset, intf) (0x4000 + (off= set) + (0x1000 * (intf))) + +#define QAIF_AUD_INTF_CTL_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0000, (intf)) +#define QAIF_AUD_INTF_SYNC_CFG_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0004, (intf)) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0008, (intf)) +#define QAIF_AUD_INTF_FRAME_CFG_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x000C, (intf)) +#define QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0010, (intf)) +#define QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0030, (intf)) +#define QAIF_AUD_INTF_LANE_CFG_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0050, (intf)) +#define QAIF_AUD_INTF_MI2S_CFG_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0054, (intf)) +#define QAIF_AUD_INTF_CFG_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0058, (intf)) +#define QAIF_AUD_INTF_CHAR_CTL_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x005C, (intf)) +#define QAIF_AUD_INTF_CHAR_CFG_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0060, (intf)) +#define QAIF_AUD_INTF_CHAR_DATA_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0064, (intf)) +#define QAIF_AUD_INTF_CHAR_DATA_EXT_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0068, (intf)) +#define QAIF_AUD_INTF_CHAR_SYNC_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x006C, (intf)) +#define QAIF_AUD_INTF_INIT_DBG_STATUS_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0FF0, (intf)) +#define QAIF_AUD_INTF_TX_DBG_STATUS_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0FF4, (intf)) +#define QAIF_AUD_INTF_RX_DBG_STATUS_REG(intf) QAIF_AUD_INTF= _REG_ADDR(0x0FF8, (intf)) + +/* RATE_DET block (per detector, stride 0x1000 starting at 0x1E000) */ +#define QAIF_RATE_DET_REG_ADDR(offset, det) (0x1E000 + (o= ffset) + (0x1000 * (det))) + +#define QAIF_RATE_DET_CONFIG_REG(det) QAIF_RATE_DET= _REG_ADDR(0x0000, (det)) +#define QAIF_RATE_DET_TARGET1_CONFIG_REG(det) QAIF_RATE_DET= _REG_ADDR(0x0004, (det)) +#define QAIF_RATE_DET_TARGET2_CONFIG_REG(det) QAIF_RATE_DET= _REG_ADDR(0x0008, (det)) +#define QAIF_RATE_DET_BIN_REG(det) QAIF_RATE_DET= _REG_ADDR(0x000C, (det)) +#define QAIF_RATE_DET_STC_DIFF_REG(det) QAIF_RATE_DET= _REG_ADDR(0x0010, (det)) +#define QAIF_RATE_DET_SEL_REG(det) QAIF_RATE_DET= _REG_ADDR(0x0014, (det)) +#define QAIF_RATE_DET_TIMEOUT_CFG_REG(det) QAIF_RATE_DET= _REG_ADDR(0x0018, (det)) + +#define QAIF_WRDMA_MAP_QXM (0X1000) +#define QAIF_CODEC_WRDMA_MAP_QXM (0X1004) +#define QAIF_RDDMA_MAP_QXM (0X1010) +#define QAIF_CODEC_RDDMA_MAP_QXM (0X1014) +#define QAIF_RDDMA_QXM1_SHRAM_ST_ADDR(i) (0X1100 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM1_SHRAM_ST_ADDR(i) (0X1140 + (0x4 * (i))) +#define QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i) (0X1200 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i) (0X1240 + (0x4 * (i))) +#define QAIF_RDDMA_QXM1_SHRAM_LEN(i) (0x1300 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM1_SHRAM_LEN(i) (0x1340 + (0x4 * (i))) +#define QAIF_RDDMA_QXM0_SHRAM_LEN(i) (0x1400 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i) (0x1440 + (0x4 * (i))) +#define QAIF_WRDMA_QXM1_SHRAM_ST_ADDR(i) (0x1500 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM1_SHRAM_ST_ADDR(i) (0x1540 + (0x4 * (i))) +#define QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i) (0x1600 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i) (0x1640 + (0x4 * (i))) +#define QAIF_WRDMA_QXM1_SHRAM_LEN(i) (0x1700 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM1_SHRAM_LEN(i) (0x1740 + (0x4 * (i))) +#define QAIF_WRDMA_QXM0_SHRAM_LEN(i) (0x1800 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i) (0x1840 + (0x4 * (i))) + +/* RDDMA + * v : ptr to qaif_variant + */ +#define QAIF_RDDMA_REG_ADDR(v, offset, chan) \ + (v->rddma_reg_base + (offset) + v->rddma_stride * (chan)) +#define QAIF_RDDMA_CTL_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x00, (ch= an)) +#define QAIF_RDDMA_CFG_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x04, (ch= an)) +#define QAIF_RDDMA_BASE_ADDR_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x08,= (chan)) +#define QAIF_RDDMA_BUFF_LEN_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x10, = (chan)) +#define QAIF_RDDMA_CURR_ADDR_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x14,= (chan)) +#define QAIF_RDDMA_PERIOD_LEN_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x1C= , (chan)) +#define QAIF_RDDMA_PERIOD_CNT_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x20= , (chan)) +#define QAIF_RDDMA_SHRAM_WORDCNT_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x= 24, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x2= 8, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_EXTN_REG(v, chan) QAIF_RDDMA_REG_ADDR(v,= 0x2C, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_CLR_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, = 0x30, (chan)) +#define QAIF_RDDMA_SET_BUFF_CNT_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x3= 4, (chan)) +#define QAIF_RDDMA_SET_PERIOD_CNT_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0= x38, (chan)) +#define QAIF_RDDMA_STC_LSB_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x3C, = (chan)) +#define QAIF_RDDMA_STC_MSB_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x40, = (chan)) +#define QAIF_RDDMA_PERIOD_DET_STAT_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, = 0x44, (chan)) +#define QAIF_RDDMA_PERIOD_DET_CLR_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0= x48, (chan)) +#define QAIF_RDDMA_FORMAT_ERR_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x4C= , (chan)) +#define QAIF_RDDMA_AHB_BYPASS_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x50= , (chan)) +#define QAIF_RDDMA_SHUTDOWN_STAT_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x= 54, (chan)) +#define QAIF_RDDMA_PADDING_CFG_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x5= 8, (chan)) +#define QAIF_RDDMA_STATUS_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0x60, (= chan)) +#define QAIF_RDDMA_DBG_STATUS_REG(v, chan) QAIF_RDDMA_REG_ADDR(v, 0xFF= 0, (chan)) + +#define QAIF_CODEC_RDDMA_REG_ADDR(v, offset, chan) \ + (v->codec_rddma_reg_base + (offset) + v->codec_rddma_stride * (chan)) +#define QAIF_CODEC_RDDMA_CTL_REG(v, chan) QAIF_CODEC_RDDMA_REG_ADDR(v,= 0x00, (chan)) +#define QAIF_CODEC_RDDMA_CFG_REG(v, chan) QAIF_CODEC_RDDMA_REG_ADDR(v,= 0x04, (chan)) +#define QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, chan) QAIF_CODEC_RDDMA_REG_AD= DR(v, 0x08, (chan)) +#define QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, chan) QAIF_CODEC_RDDMA_REG_ADD= R(v, 0x10, (chan)) +#define QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, chan) QAIF_CODEC_RDDMA_REG_AD= DR(v, 0x14, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, chan) QAIF_CODEC_RDDMA_REG_AD= DR(v, 0x1C, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_CNT_REG(v, chan) QAIF_CODEC_RDDMA_REG_AD= DR(v, 0x20, (chan)) +#define QAIF_CODEC_RDDMA_SHRAM_WORDCNT_REG(v, chan) QAIF_CODEC_RDDMA_REG= _ADDR(v, 0x24, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_REG(v, chan) QAIF_CODEC_RDDMA_REG_= ADDR(v, 0x28, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_EXTN_REG(v, chan) QAIF_CODEC_RDDMA_= REG_ADDR(v, 0x2C, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_CLR_REG(v, chan) QAIF_CODEC_RDDMA_R= EG_ADDR(v, 0x30, (chan)) +#define QAIF_CODEC_RDDMA_SET_BUFF_CNT_REG(v, chan) QAIF_CODEC_RDDMA_REG_= ADDR(v, 0x34, (chan)) +#define QAIF_CODEC_RDDMA_SET_PERIOD_CNT_REG(v, chan) QAIF_CODEC_RDDMA_REG= _ADDR(v, 0x38, (chan)) +#define QAIF_CODEC_RDDMA_STC_LSB_REG(v, chan) QAIF_CODEC_RDDMA_REG_ADDR= (v, 0x3C, (chan)) +#define QAIF_CODEC_RDDMA_STC_MSB_REG(v, chan) QAIF_CODEC_RDDMA_REG_ADDR= (v, 0x40, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_DET_STAT_REG(v, chan) QAIF_CODEC_RDDMA_RE= G_ADDR(v, 0x44, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_DET_CLR_REG(v, chan) QAIF_CODEC_RDDMA_REG= _ADDR(v, 0x48, (chan)) +#define QAIF_CODEC_RDDMA_FORMAT_ERR_REG(v, chan) QAIF_CODEC_RDDMA_REG_AD= DR(v, 0x4C, (chan)) +#define QAIF_CODEC_RDDMA_AHB_BYPASS_REG(v, chan) QAIF_CODEC_RDDMA_REG_AD= DR(v, 0x50, (chan)) +#define QAIF_CODEC_RDDMA_SHUTDOWN_STAT_REG(v, chan) QAIF_CODEC_RDDMA_REG= _ADDR(v, 0x54, (chan)) +#define QAIF_CODEC_RDDMA_PADDING_CFG_REG(v, chan) QAIF_CODEC_RDDMA_REG_A= DDR(v, 0x58, (chan)) +#define QAIF_CODEC_RDDMA_INTF_CFG_REG(v, chan) QAIF_CODEC_RDDMA_REG_ADD= R(v, 0x5C, (chan)) +#define QAIF_CODEC_RDDMA_STATUS_REG(v, chan) QAIF_CODEC_RDDMA_REG_ADDR(= v, 0x60, (chan)) +#define QAIF_CODEC_RDDMA_DBG_STATUS_REG(v, chan) QAIF_CODEC_RDDMA_REG_AD= DR(v, 0xFF0, (chan)) +#define QAIF_CODEC_RDDMA_INTF_DBG_STATUS_REG(v, chan) QAIF_CODEC_RDDMA_RE= G_ADDR(v, 0xFF4, (chan)) + +/* WRDMA + * v : ptr to qaif_variant + */ +#define QAIF_WRDMA_REG_ADDR(v, offset, chan) \ + (v->wrdma_reg_base + (offset) + v->wrdma_stride * (chan)) +#define QAIF_WRDMA_CTL_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x00, (ch= an)) +#define QAIF_WRDMA_CFG_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x04, (ch= an)) +#define QAIF_WRDMA_BASE_ADDR_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x08,= (chan)) +#define QAIF_WRDMA_BUFF_LEN_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x10, = (chan)) +#define QAIF_WRDMA_CURR_ADDR_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x14,= (chan)) +#define QAIF_WRDMA_PERIOD_LEN_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x1C= , (chan)) +#define QAIF_WRDMA_PERIOD_CNT_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x20= , (chan)) +#define QAIF_WRDMA_SHRAM_WORDCNT_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x= 24, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x2= 8, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_EXTN_REG(v, chan) QAIF_WRDMA_REG_ADDR(v,= 0x2C, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_CLR_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, = 0x30, (chan)) +#define QAIF_WRDMA_SET_BUFF_CNT_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x3= 4, (chan)) +#define QAIF_WRDMA_SET_PERIOD_CNT_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0= x38, (chan)) +#define QAIF_WRDMA_STC_LSB_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x3C, = (chan)) +#define QAIF_WRDMA_STC_MSB_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x40, = (chan)) +#define QAIF_WRDMA_PERIOD_DET_STAT_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, = 0x44, (chan)) +#define QAIF_WRDMA_PERIOD_DET_CLR_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0= x48, (chan)) +#define QAIF_WRDMA_FORMAT_ERR_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x4C= , (chan)) +#define QAIF_WRDMA_AHB_BYPASS_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x50= , (chan)) +#define QAIF_WRDMA_SHUTDOWN_STAT_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0x= 54, (chan)) +#define QAIF_WRDMA_DBG_STATUS_REG(v, chan) QAIF_WRDMA_REG_ADDR(v, 0xFF= 0, (chan)) + +#define QAIF_CODEC_WRDMA_REG_ADDR(v, offset, chan) \ + (v->codec_wrdma_reg_base + (offset) + v->codec_wrdma_stride * (chan)) +#define QAIF_CODEC_WRDMA_CTL_REG(v, chan) QAIF_CODEC_WRDMA_REG_ADDR(v,= 0x00, (chan)) +#define QAIF_CODEC_WRDMA_CFG_REG(v, chan) QAIF_CODEC_WRDMA_REG_ADDR(v,= 0x04, (chan)) +#define QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, chan) QAIF_CODEC_WRDMA_REG_AD= DR(v, 0x08, (chan)) +#define QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, chan) QAIF_CODEC_WRDMA_REG_ADD= R(v, 0x10, (chan)) +#define QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, chan) QAIF_CODEC_WRDMA_REG_AD= DR(v, 0x14, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, chan) QAIF_CODEC_WRDMA_REG_AD= DR(v, 0x1C, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_CNT_REG(v, chan) QAIF_CODEC_WRDMA_REG_AD= DR(v, 0x20, (chan)) +#define QAIF_CODEC_WRDMA_SHRAM_WORDCNT_REG(v, chan) QAIF_CODEC_WRDMA_REG= _ADDR(v, 0x24, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_REG(v, chan) QAIF_CODEC_WRDMA_REG_= ADDR(v, 0x28, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_EXTN_REG(v, chan) QAIF_CODEC_WRDMA_= REG_ADDR(v, 0x2C, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_CLR_REG(v, chan) QAIF_CODEC_WRDMA_R= EG_ADDR(v, 0x30, (chan)) +#define QAIF_CODEC_WRDMA_SET_BUFF_CNT_REG(v, chan) QAIF_CODEC_WRDMA_REG_= ADDR(v, 0x34, (chan)) +#define QAIF_CODEC_WRDMA_SET_PERIOD_CNT_REG(v, chan) QAIF_CODEC_WRDMA_REG= _ADDR(v, 0x38, (chan)) +#define QAIF_CODEC_WRDMA_STC_LSB_REG(v, chan) QAIF_CODEC_WRDMA_REG_ADDR= (v, 0x3C, (chan)) +#define QAIF_CODEC_WRDMA_STC_MSB_REG(v, chan) QAIF_CODEC_WRDMA_REG_ADDR= (v, 0x40, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_DET_STAT_REG(v, chan) QAIF_CODEC_WRDMA_RE= G_ADDR(v, 0x44, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_DET_CLR_REG(v, chan) QAIF_CODEC_WRDMA_REG= _ADDR(v, 0x48, (chan)) +#define QAIF_CODEC_WRDMA_FORMAT_ERR_REG(v, chan) QAIF_CODEC_WRDMA_REG_AD= DR(v, 0x4C, (chan)) +#define QAIF_CODEC_WRDMA_AHB_BYPASS_REG(v, chan) QAIF_CODEC_WRDMA_REG_AD= DR(v, 0x50, (chan)) +#define QAIF_CODEC_WRDMA_SHUTDOWN_STAT_REG(v, chan) QAIF_CODEC_WRDMA_REG= _ADDR(v, 0x54, (chan)) +#define QAIF_CODEC_WRDMA_INTF_CFG_REG(v, chan) QAIF_CODEC_WRDMA_REG_ADD= R(v, 0x58, (chan)) +#define QAIF_CODEC_WRDMA_DBG_STATUS_REG(v, chan) QAIF_CODEC_WRDMA_REG_AD= DR(v, 0xFF0, (chan)) +#define QAIF_CODEC_WRDMA_INTF_DBG_STATUS_REG(v, chan) QAIF_CODEC_WRDMA_RE= G_ADDR(v, 0xFF4, (chan)) + + +#define QAIF_EE_RDDMA_IRQ_REG_ADDR(v, dma_type, offset) \ + (dma_type =3D=3D QAIF_AIF_IRQ ? (v->rddma_irq_reg_base + (offset) + v->rd= dma_irq_stride * (v->ee)) : \ + (v->codec_rddma_irq_reg_base + (offset) + v->codec_rddma_irq_stride * (v-= >ee))) + +/* RDDMA Period Interrupts */ +#define QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_ADD= R(v, i, 0x00) +#define QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_A= DDR(v, i, 0x08) +#define QAIF_EE_RDDMA_PERIOD_IRQ_RAW_STAT_REG(v, i) QAIF_EE_RDDMA_IRQ_RE= G_ADDR(v, i, 0x10) +#define QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_AD= DR(v, i, 0x18) +#define QAIF_EE_RDDMA_PERIOD_IRQ_FORCE_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_A= DDR(v, i, 0x20) +/* RDDMA Underflow Interrupts */ +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_A= DDR(v, i, 0x28) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i) QAIF_EE_RDDMA_IRQ_REG= _ADDR(v, i, 0x30) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_RAW_STAT_REG(v, i) QAIF_EE_RDDMA_IRQ_= REG_ADDR(v, i, 0x38) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_= ADDR(v, i, 0x40) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_FORCE_REG(v, i) QAIF_EE_RDDMA_IRQ_RE= G_ADDR(v, i, 0x48) +/* RDDMA Error Response Interrupts */ +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_AD= DR(v, i, 0x50) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_A= DDR(v, i, 0x58) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i) QAIF_EE_RDDMA_IRQ_RE= G_ADDR(v, i, 0x60) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_A= DDR(v, i, 0x68) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_FORCE_REG(v, i) QAIF_EE_RDDMA_IRQ_REG_= ADDR(v, i, 0x70) + +#define QAIF_EE_WRDMA_IRQ_REG_ADDR(v, dma_type, offset) \ + (dma_type =3D=3D QAIF_AIF_IRQ ? (v->wrdma_irq_reg_base + (offset) + v->wr= dma_irq_stride * (v->ee)) : \ + (v->codec_wrdma_irq_reg_base + (offset) + v->codec_wrdma_irq_stride * (v-= >ee))) + +/* WRDMA Period Interrupts */ +#define QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_ADD= R(v, i, 0x00) +#define QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_A= DDR(v, i, 0x08) +#define QAIF_EE_WRDMA_PERIOD_IRQ_RAW_STAT_REG(v, i) QAIF_EE_WRDMA_IRQ_RE= G_ADDR(v, i, 0x10) +#define QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_AD= DR(v, i, 0x18) +#define QAIF_EE_WRDMA_PERIOD_IRQ_FORCE_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_A= DDR(v, i, 0x20) +/* WRDMA Overflow Interrupts */ +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_A= DDR(v, i, 0x28) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_= ADDR(v, i, 0x30) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_RAW_STAT_REG(v, i) QAIF_EE_WRDMA_IRQ_R= EG_ADDR(v, i, 0x38) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_A= DDR(v, i, 0x40) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_FORCE_REG(v, i) QAIF_EE_WRDMA_IRQ_REG= _ADDR(v, i, 0x48) +/* WRDMA Error Response Interrupts */ +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_AD= DR(v, i, 0x50) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_A= DDR(v, i, 0x58) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i) QAIF_EE_WRDMA_IRQ_RE= G_ADDR(v, i, 0x60) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_A= DDR(v, i, 0x68) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_FORCE_REG(v, i) QAIF_EE_WRDMA_IRQ_REG_= ADDR(v, i, 0x70) + + +#define QAIF_DMACFG_REG(v, chan, dir, dai_id) \ + (is_cif_dma_port(dai_id) ? \ + __QAIF_CDC_DMA_REG(v, chan, dir, CFG) : \ + __QAIF_DMA_REG(v, chan, dir, CFG)) + +#define QAIF_DMACTL_REG(v, chan, dir, dai_id) \ + (is_cif_dma_port(dai_id) ? \ + __QAIF_CDC_DMA_REG(v, chan, dir, CTL) : \ + __QAIF_DMA_REG(v, chan, dir, CTL)) + +#define QAIF_DMABUFF_REG(v, chan, dir, dai_id) \ + (is_cif_dma_port(dai_id) ? \ + __QAIF_CDC_DMA_REG(v, chan, dir, BUFF_LEN) : \ + __QAIF_DMA_REG(v, chan, dir, BUFF_LEN)) + +#define QAIF_DMACURR_REG(v, chan, dir, dai_id) \ + (is_cif_dma_port(dai_id) ? \ + __QAIF_CDC_DMA_REG(v, chan, dir, CURR_ADDR) : \ + __QAIF_DMA_REG(v, chan, dir, CURR_ADDR)) + +#define QAIF_DMAPER_REG(v, chan, dir, dai_id) \ + (is_cif_dma_port(dai_id) ? \ + __QAIF_CDC_DMA_REG(v, chan, dir, PERIOD_CNT) : \ + __QAIF_DMA_REG(v, chan, dir, PERIOD_CNT)) + +#define QAIF_DMAPER_LEN_REG(v, chan, dir, dai_id) \ + (is_cif_dma_port(dai_id) ? \ + __QAIF_CDC_DMA_REG(v, chan, dir, PERIOD_LEN) : \ + __QAIF_DMA_REG(v, chan, dir, PERIOD_LEN)) + +#define QAIF_DMABASE_REG(v, chan, dir, dai_id) \ + (is_cif_dma_port(dai_id) ? \ + __QAIF_CDC_DMA_REG(v, chan, dir, BASE_ADDR) : \ + __QAIF_DMA_REG(v, chan, dir, BASE_ADDR)) + +#define __QAIF_CDC_DMA_REG(v, chan, dir, reg) \ + (((dir) =3D=3D SNDRV_PCM_STREAM_PLAYBACK) ? \ + __QAIF_CDC_RDDMA_REG(v, chan, reg) : \ + __QAIF_CDC_WRDMA_REG(v, chan, reg)) + +#define __QAIF_DMA_REG(v, chan, dir, reg) \ + (((dir) =3D=3D SNDRV_PCM_STREAM_PLAYBACK) ? \ + (QAIF_RDDMA_##reg##_REG(v, chan)) : \ + QAIF_WRDMA_##reg##_REG(v, chan)) + +#define __QAIF_CDC_RDDMA_REG(v, chan, reg) \ + QAIF_CODEC_RDDMA_##reg##_REG(v, chan) + +#define __QAIF_CDC_WRDMA_REG(v, chan, reg) \ + QAIF_CODEC_WRDMA_##reg##_REG(v, chan) + +#define QAIF_SID_MAP_REG(dir, dai_id) \ + (is_cif_dma_port(dai_id) ? \ + __QAIF_CDC_SID_MAP_REG(dir) : \ + __QAIF_SID_MAP_REG(dir)) + +#define __QAIF_SID_MAP_REG(dir) \ + (((dir) =3D=3D SNDRV_PCM_STREAM_PLAYBACK) ? \ + QAIF_RDDMA_SID_MAP_REG : \ + QAIF_WRDMA_SID_MAP_REG) + +#define __QAIF_CDC_SID_MAP_REG(dir) \ + (((dir) =3D=3D SNDRV_PCM_STREAM_PLAYBACK) ? \ + QAIF_CODEC_RDDMA_SID_MAP_REG : \ + QAIF_CODEC_WRDMA_SID_MAP_REG) + +#endif /* __QAIF_REG_H__ */ --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 B69664183C3; Fri, 5 Jun 2026 10:38:00 +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=1780655885; cv=none; b=Ax9LxSYRyfjhCUgwJckpi+GZWShHpxnqu7w4l91A1QBbBlM0GATPfeGMBzEa1BToMq+eZMIzcwWaIXQARdwtbx68Kj2DHRE/ynfLfLYpgUnyyph79+wxd8L8qGXc1fF5o0CmGAbnqiYX/2iFdNG/AjTsahcOLogTLSobR90tJN4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655885; c=relaxed/simple; bh=4Z7me4J/DDAGKGX0gt2vmiGPvI838ugTDe0IO+FeGHA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=koz9uBD91DRxhTdhZ9rYoQIjxHZPfjnunUH+00Uea2FYSdDtYbDaj83umMltxmVDpvO2pGxaKzz/MppzLXMLQzZZB5RR/kE3Gxqev5P4trbhIEP32M04GBTIrQWeSPGtL/YHQIMNPuTpe38KyM7GYv5RcN56t1hcJNSqzSVQNu0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=nQN05VIW; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="nQN05VIW" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6555FOm12667169; Fri, 5 Jun 2026 10:37:57 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= YinKR5VNYyydaG2eV/tnaw6AAiWFm7Vn2JaKordDy1k=; b=nQN05VIWXwoPpp0o kC5TmCJNCez7qAc0MUI39DQbiPqZrMI/EB2C9i0CjUpnqnQNyTpqiIPLpofVyUkK /p14uZB0AyQGsTrThwZWfR0yeXKolxgGAcJuKpJzou2XgKZSMhT4s3Ydz9jhL9YT Z1rjhuiaERtfZodE/wv7ZS8OWfP4YC1dMk6PGDZ9elaVRrrEUqYEFatOyC88oiVJ pAXh9EcEymM3pItmUnn6rNtAGKXFmY9ZsC106TbfianpqQOcuyW02fBk8g5KPE2o QQgmSHg3k3DBduWRCETKZ6zD2dmhG+stMQp0a1IzYWNc0RhBGUDLirH47KDj3Wri NEAvnA== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekemyuhcd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:37:56 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6q011714; Fri, 5 Jun 2026 10:37:52 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/13] ASoC: qcom: Add QAIF shared data structures and variant interface Date: Fri, 5 Jun 2026 16:07:31 +0530 Message-Id: <20260605103739.3557573-6-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.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; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-GUID: PSM8Uir_xTH9VwSMZ3LcsV-xozpt36iu X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfX8Onje41zPx3k gxqkEp61m6I3R/T+hIz5b/s3IBI2Mm8RShkMgaLUNzDs2NbbYd3scVuijdhjK/uIDGKmPDLpBnK jdFZOGV046isjzH4C379VZ1VEG6vYisjCJVbmmyikRV0QKEQbh3fnKyRUd/6D7rafoz2CT+Nf/L OYK9QPUU/cOnofCZDEnOzNpIkXLzUdKsQhawjGur/ZhfNVLcv2DpEWK6YR4VCP+Z+vV+1AT/hPK nhsEzhoAtf5f1MrqQLz3zmVsvuY9G8Q5AqRnhsGXiCqiKC8opShllTjxmalyWl0DhaIpDekEL63 PVpgsDr4j7xxqKIscPx45mA//4uavarhr22FNBQWU3RGTmBO7QV56ASzW+Px7tOtAXpevTNYoSk P7QHmWlF/UA0T30nF/MyuNAl/397T6x3faXhmjQ4/8al8eeSFEraB3c2IJIqBReaqvxlIKc0tx8 exjSeuA+Piq2sQq/F5A== X-Authority-Analysis: v=2.4 cv=K/wS2SWI c=1 sm=1 tr=0 ts=6a22a705 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=IkcTkHD0fZMA:10 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22 a=EUspDBNiAAAA:8 a=rLYuY30HX_6YGujqi8oA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 X-Proofpoint-ORIG-GUID: PSM8Uir_xTH9VwSMZ3LcsV-xozpt36iu X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 adultscore=0 suspectscore=0 impostorscore=0 spamscore=0 bulkscore=0 clxscore=1015 priorityscore=1501 malwarescore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Add qaif.h to define the common data structures used by the QAIF CPU DAI and PCM platform drivers. QAIF exposes AIF DMA paths for external audio interfaces and CIF DMA paths for the internal codec interface. Both paths need shared state for DMA channel allocation, regmap fields, interrupt dispatch, SHRAM buffer tracking and per-stream runtime data. Introduce the common QAIF driver data, AIF and CIF register-field descriptions, IRQ mapping helpers and the SoC variant descriptor. The variant descriptor provides the register layout, DMA channel counts, clock names, DAI table and platform callbacks needed by later QAIF driver code. Also define the QAIF-private MI2S port IDs used for the senary and septenary interfaces. Signed-off-by: Harendra Gautam --- sound/soc/qcom/qaif.h | 505 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 sound/soc/qcom/qaif.h diff --git a/sound/soc/qcom/qaif.h b/sound/soc/qcom/qaif.h new file mode 100644 index 000000000000..ded885a680e9 --- /dev/null +++ b/sound/soc/qcom/qaif.h @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif.h -- Shared data structures and definitions for the Qualcomm Audio= Interface (QAIF) + */ +#ifndef __QAIF_H__ +#define __QAIF_H__ + +#include +#include +#include +#include +#include + +#define LPASS_MAX_MI2S_PORTS (8) +#define LPASS_MAX_AIF_DMA_IDX (8) +#define LPASS_MAX_CIF_DMA_IDX (8) +#define QAIF_CIF_DMA_INTF_ONE_CHANNEL (0x01) +#define QAIF_CIF_DMA_INTF_TWO_CHANNEL (0x03) +#define QAIF_CIF_DMA_INTF_FOUR_CHANNEL (0x0F) +#define QAIF_CIF_DMA_INTF_SIX_CHANNEL (0x3F) +#define QAIF_CIF_DMA_INTF_EIGHT_CHANNEL (0xFF) + +#define QAIF_DMACTL_ENABLE_ON 1 +#define QAIF_DMACTL_ENABLE_OFF 0 + +#define QAIF_DMACTL_DYNCLK_ON 1 +#define QAIF_DMACTL_DYNCLK_OFF 0 + +#define QAIF_AIF_CTL_ENABLE_ON 1 +#define QAIF_AIF_CTL_ENABLE_OFF 0 + +#define QAIF_CIF_16BIT_UNPACK_ENABLE 1 +#define QAIF_CIF_16BIT_UNPACK_DISABLE 0 + +#define QAIF_CIF_DMA_FS_SEL_DEFAULT 0 + +#define QAIF_DMA_DEFAULT_BIT_WIDTH 32 + +#define QAIF_DMA_BYTES_TO_WORDS_SHIFT 3 + +#define QAIF_MAX_VARIANT_CLKS 32 + +#define QAIF_DMA_CLK_RATE_MULTIPLIER 100 + +#define QAIF_MAX_AIF_CFG_CNT (LPASS_MAX_AIF_DMA_IDX/2) + +#define QAIF_AUD_INTF_CTL_MONO 1 /* Mono Mode True */ +#define QAIF_AUD_INTF_CTL_STEREO 0 /* Mono Mode False */ + +#define QAIF_AIF_SAMPLE_WIDTH(bits) ((bits) - 1) +#define QAIF_AIF_SLOT_WIDTH(bits) ((bits) - 1) + +#define QAIF_DMACTL_WM_5 4 +#define QAIF_DMACTL_WM_8 7 +#define QAIF_DMACTL_BURSTEN 1 + +#define QAIF_MAX_LANES 8 + + +enum qxm_sel { + QXM0 =3D 0, + QXM1 =3D 1, + MAX_QXM_TYPE, +}; + +static inline bool is_cif_dma_port(int dai_id) +{ + switch (dai_id) { + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + return true; + } + return false; +} + +enum qaif_type_t { + QAIF_INVALID =3D -1, + QAIF =3D 0, + QAIF_VA, + QAIF_MAX_TYPES +}; + +enum qaif_irq_type { + QAIF_AIF_IRQ =3D 0, + QAIF_CIF_IRQ =3D 1, + QAIF_AUD_INTF_IRQ =3D 2, + QAIF_IRQ_MAX =3D 3 +}; + +enum qaif_dma_type { + QAIF_AIF_DMA =3D 0, + QAIF_CIF_DMA =3D 1, + DMA_TYPE_MAX +}; + +struct qaif_dmactl { + /* AUDIO_CORE_QAIF_CODEC_xDMAa_CTL */ + struct regmap_field *enable; + struct regmap_field *reset; + + /* AUDIO_CORE_QAIF_CODEC_xDMAa_CFG */ + struct regmap_field *num_ot; /* outstanding transactions */ + struct regmap_field *dma_dyncclk; + struct regmap_field *burst16; + struct regmap_field *burst8; + struct regmap_field *burst4; + struct regmap_field *burst2; + struct regmap_field *burst1; + struct regmap_field *shram_wm; /* SHRAM watermark */ + +}; + +struct qaif_cdc_intfctl { + /* AUDIO_CORE_QAIF_CODEC_xDMAa_INTF_CFG */ + struct regmap_field *active_ch_en; + struct regmap_field *fs_sel; + struct regmap_field *fs_delay; + struct regmap_field *fs_out_gate; + struct regmap_field *intf_dyncclk; + struct regmap_field *en_16bit_unpack; +}; + +struct qaif_aud_intfctl { + /* AUDIO_CORE_QAIF_AUD_INTFa_SYNC_CFG */ + struct regmap_field *inv_sync; + struct regmap_field *sync_delay; + struct regmap_field *sync_mode; + struct regmap_field *sync_src; + + /* AUDIO_CORE_QAIF_AUD_INTFa_BIT_WIDTH_CFG */ + struct regmap_field *slot_width_rx; + struct regmap_field *slot_width_tx; + struct regmap_field *sample_width_rx; + struct regmap_field *sample_width_tx; + + /* AUDIO_CORE_QAIF_AUD_INTFa_MI2S_CFG */ + struct regmap_field *mono_mode_rx; + struct regmap_field *mono_mode_tx; + + /* AUDIO_CORE_QAIF_AUD_INTFa_LANE_CFG */ + struct regmap_field *lane_en; /* Lane enable mask (bits 8-15) */ + struct regmap_field *lane_dir; /* Lane direction mask (bits 0-7,= 0=3DTX, 1=3DRX) */ + struct regmap_field *loopback_en; + struct regmap_field *ctrl_data_oe; + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_RX */ + struct regmap_field *slot_en_rx_mask; + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_TX */ + struct regmap_field *slot_en_tx_mask; + + /* AUDIO_CORE_QAIF_AUD_INTFa_CFG */ + struct regmap_field *full_cycle_en; + /* AUDIO_CORE_QAIF_AUD_INTFa_FRAME_CFG */ + struct regmap_field *bits_per_lane; + + /* AUDIO_CORE_QAIF_AUD_INTFa_CTL */ + struct regmap_field *enable; + struct regmap_field *enable_tx; + struct regmap_field *enable_rx; + struct regmap_field *reset; + struct regmap_field *reset_tx; + struct regmap_field *reset_rx; +}; + +/* Lane configuration structure */ +struct qaif_lane_config { + u32 enable; /* 1 =3D enabled, 0 =3D disabled */ + u32 direction; /* 0 =3D TX_SPKR, 1 =3D RX_MIC */ +}; + +/* + * AIF interface protocol mode =E2=80=94 set by the DT compatible string a= nd + * used to select mode-specific register defaults and property parsing. + */ +enum qaif_aif_mode { + QAIF_AIF_MODE_PCM, + QAIF_AIF_MODE_TDM, + QAIF_AIF_MODE_MI2S, +}; + +/* QAIF Audio Interface Configuration Structure */ +struct qaif_aif_config { + /* Interface protocol mode derived from DT compatible */ + enum qaif_aif_mode mode; + /* Sync configuration */ + u32 sync_mode; + u32 sync_src; + u32 invert_sync; + u32 sync_delay; + /* Slot and sample width configuration */ + u32 slot_width_rx; + u32 slot_width_tx; + u32 sample_width_rx; + u32 sample_width_tx; + /* Slot enable masks (32-bit masks for 32 slots) */ + u32 slot_en_rx_mask; + u32 slot_en_tx_mask; + /* Control configuration */ + u32 loopback_en; + u32 ctrl_data_oe; + /* Lane configuration */ + u32 num_lanes; /* Number of lanes configured */ + struct qaif_lane_config lane_cfg[QAIF_MAX_LANES]; + u32 lane_en_mask; + u32 lane_dir_mask; + /* Frame configuration */ + u32 full_cycle_en; + u32 bits_per_lane; +}; + +struct qaif_pcm_data { + int stream_dma_idx; +}; + +struct qaif_dma_mem_info { + dma_addr_t dma_addr; + size_t alloc_size; + void *vaddr; +}; + +struct qaif_dmaidx_dai_map { + unsigned int dai_id; +}; + +/* Both the CPU DAI and platform drivers will access this data */ +struct qaif_drv_data { + + /* MI2S bit clock (derived from system clock by a divider) */ + struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS]; + + /* SOC specific clock list */ + struct clk_bulk_data *clks; + int num_clks; + + struct clk *aud_dma_clk; + struct clk *aud_dma_mem_clk; + + /* Qualcomm audio interface (QAIF) registers */ + void __iomem *audio_qaif; + + /* regmap backed by the Qualcomm audio interface (QAIF) registers */ + struct regmap *audio_qaif_map; + + /* interrupts from the Qualcomm audio interface (QAIF) */ + int audio_qaif_irq; + + /* QAIF init config refcount*/ + unsigned int qaif_init_ref_cnt; + + /* SOC specific variations in the QAIF IP integration */ + const struct qaif_variant *variant; + + /* Runtime-allocated regmap field handles (populated at probe) */ + struct qaif_dmactl *aif_rd_dmactl; + struct qaif_dmactl *aif_wr_dmactl; + struct qaif_dmactl *cif_rd_dmactl; + struct qaif_dmactl *cif_wr_dmactl; + struct qaif_aud_intfctl *aif_intfctl; + struct qaif_cdc_intfctl *cif_rddma_intfctl; + struct qaif_cdc_intfctl *cif_wrdma_intfctl; + struct qaif_aif_config aif_intf_cfg[QAIF_MAX_AIF_CFG_CNT]; + + /* bit map to keep track of dma idx allocations */ + unsigned long aif_dma_idx_bit_map; + unsigned long cif_dma_idx_bit_map; + + /* used it for handling interrupt per dma channel */ + struct snd_pcm_substream *aif_substream[LPASS_MAX_AIF_DMA_IDX]; + struct snd_pcm_substream *cif_substream[LPASS_MAX_CIF_DMA_IDX]; + + u32 smmu_csid_bits; + + /* DMA info handle per stream/dma idx */ + struct qaif_dma_mem_info *aif_dma_heap[LPASS_MAX_AIF_DMA_IDX]; + struct qaif_dma_mem_info *cif_dma_heap[LPASS_MAX_CIF_DMA_IDX]; + +}; + +enum qaif_summary_irq_bitmask { + QAIF_SUMMARY_BITMASK_AIF_PERIOD_RDDMA =3D BIT(0), + QAIF_SUMMARY_BITMASK_AIF_UNDERFLOW_RDDMA =3D BIT(1), + QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_RDDMA =3D BIT(2), + QAIF_SUMMARY_BITMASK_AIF_PERIOD_WRDMA =3D BIT(3), + QAIF_SUMMARY_BITMASK_AIF_OVERFLOW_WRDMA =3D BIT(4), + QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_WRDMA =3D BIT(5), + + QAIF_SUMMARY_BITMASK_AUD_OVERFLOW =3D BIT(6), + QAIF_SUMMARY_BITMASK_AUD_UNDERFLOW =3D BIT(7), + + QAIF_SUMMARY_BITMASK_RATE_DET =3D BIT(8), + QAIF_SUMMARY_BITMASK_VFR =3D BIT(9), + QAIF_SUMMARY_BITMASK_GRP =3D BIT(10), + QAIF_SUMMARY_BITMASK_RDDMA_OVERLAP =3D BIT(11), + QAIF_SUMMARY_BITMASK_WRDMA_OVERLAP =3D BIT(12), + QAIF_SUMMARY_BITMASK_INTF_OVERLAP =3D BIT(13), + QAIF_SUMMARY_BITMASK_GRP_OVERLAP =3D BIT(14), + + QAIF_SUMMARY_BITMASK_CIF_OVERLAP_RDDMA =3D BIT(15), + QAIF_SUMMARY_BITMASK_CIF_OVERLAP_WRDMA =3D BIT(17), + QAIF_SUMMARY_BITMASK_CIF_PERIOD_RDDMA =3D BIT(18), + QAIF_SUMMARY_BITMASK_CIF_UNDERFLOW_RDDMA =3D BIT(19), + QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_RDDMA =3D BIT(20), + QAIF_SUMMARY_BITMASK_CIF_PERIOD_WRDMA =3D BIT(24), + QAIF_SUMMARY_BITMASK_CIF_OVERFLOW_WRDMA =3D BIT(25), + QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_WRDMA =3D BIT(26) + +}; + +enum qaif_client_status_register_bitmask_info { + QAIF_BITMASK_GROUP_INF =3D 0x400, + QAIF_BITMASK_AIF_RDDMA_WRDMA =3D 0x3F, + QAIF_BITMASK_CIF_RDDMA_WRDMA =3D 0x71c0000, + QAIF_BITMASK_DP_RDDMA =3D 0xe00000, + QAIF_BITMASK_AUD_INF =3D 0xC0, +}; + +struct qaif_irq_map { + int client_id; + u32 mask; + irqreturn_t (*client_irq_handler)(struct qaif_drv_data *drvdata, u32 irq_= status); +}; + +enum dma_type { + DMA_TYPE_RDDMA, + DMA_TYPE_WRDMA +}; + +enum qaif_irq { + QAIF_IRQ_PERIOD, + QAIF_IRQ_OVERFLOW, + QAIF_IRQ_UNDERFLOW, + QAIF_IRQ_ERROR +}; + +enum qaif_client_info { + QAIF_CLIENT_ID_GROUP_INF =3D 0, + QAIF_CLIENT_ID_AIF_DMA =3D 1, + QAIF_CLIENT_ID_CIF_DMA =3D 2, + QAIF_CLIENT_ID_DP_DMA =3D 3, + QAIF_CLIENT_ID_AUD_INF =3D 4, + QAIF_CLIENT_ID_MAX +}; + +struct qaif_variant { + u32 ee; + u32 qaif_type; + + u32 num_rddma; + u32 num_wrdma; + u32 wrdma_start; + + u32 num_codec_rddma; /* RX */ + u32 num_codec_wrdma; /* TX */ + u32 codec_wrdma_start; + u32 num_intf; + + u32 rddma_reg_base; + u32 rddma_stride; + u32 codec_rddma_reg_base; + u32 codec_rddma_stride; + + u32 wrdma_reg_base; + u32 wrdma_stride; + u32 codec_wrdma_reg_base; + u32 codec_wrdma_stride; + + u32 rddma_irq_reg_base; + u32 rddma_irq_stride; + u32 codec_rddma_irq_reg_base; + u32 codec_rddma_irq_stride; + + u32 wrdma_irq_reg_base; + u32 wrdma_irq_stride; + u32 codec_wrdma_irq_reg_base; + u32 codec_wrdma_irq_stride; + + u32 qxm_type; + u32 rd_len; + u32 rddma_shram_len; + u32 rddma_shram_start_addr[DMA_TYPE_MAX]; + u32 wr_len; + u32 wrdma_shram_len; + u32 wrdma_shram_start_addr[DMA_TYPE_MAX]; + + /* AIF RDDMA register fields */ + struct reg_field rddma_enable; + struct reg_field rddma_reset; + struct reg_field rddma_num_ot; + struct reg_field rddma_dma_dyncclk; + struct reg_field rddma_burst16; + struct reg_field rddma_burst8; + struct reg_field rddma_burst4; + struct reg_field rddma_burst2; + struct reg_field rddma_burst1; + struct reg_field rddma_shram_wm; + + /* AIF WRDMA register fields */ + struct reg_field wrdma_enable; + struct reg_field wrdma_reset; + struct reg_field wrdma_num_ot; + struct reg_field wrdma_dma_dyncclk; + struct reg_field wrdma_burst16; + struct reg_field wrdma_burst8; + struct reg_field wrdma_burst4; + struct reg_field wrdma_burst2; + struct reg_field wrdma_burst1; + struct reg_field wrdma_shram_wm; + + /* CODEC RDDMA register fields */ + struct reg_field cif_rddma_enable; + struct reg_field cif_rddma_reset; + struct reg_field cif_rddma_num_ot; + struct reg_field cif_rddma_dma_dyncclk; + struct reg_field cif_rddma_burst16; + struct reg_field cif_rddma_burst8; + struct reg_field cif_rddma_burst4; + struct reg_field cif_rddma_burst2; + struct reg_field cif_rddma_burst1; + struct reg_field cif_rddma_shram_wm; + struct reg_field cif_rddma_active_ch_en; + struct reg_field cif_rddma_fs_sel; + struct reg_field cif_rddma_fs_delay; + struct reg_field cif_rddma_fs_out_gate; + struct reg_field cif_rddma_intf_dyncclk; + struct reg_field cif_rddma_en_16bit_unpack; + + /* CODEC WRDMA register fields */ + struct reg_field cif_wrdma_enable; + struct reg_field cif_wrdma_reset; + struct reg_field cif_wrdma_num_ot; + struct reg_field cif_wrdma_dma_dyncclk; + struct reg_field cif_wrdma_burst16; + struct reg_field cif_wrdma_burst8; + struct reg_field cif_wrdma_burst4; + struct reg_field cif_wrdma_burst2; + struct reg_field cif_wrdma_burst1; + struct reg_field cif_wrdma_shram_wm; + struct reg_field cif_wrdma_active_ch_en; + struct reg_field cif_wrdma_fs_sel; + struct reg_field cif_wrdma_fs_delay; + struct reg_field cif_wrdma_fs_out_gate; + struct reg_field cif_wrdma_intf_dyncclk; + struct reg_field cif_wrdma_en_16bit_unpack; + + /* Regmap fields of AIF interface registers bitfields */ + struct reg_field aif_inv_sync; + struct reg_field aif_sync_delay; + struct reg_field aif_sync_mode; + struct reg_field aif_sync_src; + struct reg_field aif_sample_width_rx; + struct reg_field aif_sample_width_tx; + struct reg_field aif_slot_width_rx; + struct reg_field aif_slot_width_tx; + struct reg_field aif_bits_per_lane; + struct reg_field aif_slot_en_tx_mask; + struct reg_field aif_slot_en_rx_mask; + struct reg_field aif_loopback_en; + struct reg_field aif_ctrl_data_oe; + struct reg_field aif_lane_en; + struct reg_field aif_lane_dir; + struct reg_field aif_mono_mode_rx; + struct reg_field aif_mono_mode_tx; + struct reg_field aif_full_cycle_en; + + /* AUDIO_CORE_QAIF_AUD_INTFa_CTL bitfields */ + struct reg_field aif_enable; + struct reg_field aif_enable_tx; + struct reg_field aif_enable_rx; + struct reg_field aif_reset; + struct reg_field aif_reset_tx; + struct reg_field aif_reset_rx; + + /* Platform-specific data */ + const char **clk_name; + int num_clks; + struct snd_soc_dai_driver *dai_driver; + int num_dai; + const char **dai_osr_clk_names; + const char **dai_bit_clk_names; + + /* Platform-specific function pointers */ + int (*init)(struct platform_device *pdev); + int (*exit)(struct platform_device *pdev); + int (*alloc_stream_dma_idx)(struct qaif_drv_data *data, int direction, un= signed int dai_id); + int (*free_stream_dma_idx)(struct qaif_drv_data *data, int chan, unsigned= int dai_id); + int (*get_dma_idx)(unsigned int dai_id); + +}; + +/* External DAI ops structures defined in qaif-cpu.c */ +extern const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_ops; +extern const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops; + +/* Platform driver functions defined in qaif-cpu.c */ +int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev); +int asoc_qcom_qaif_platform_register(struct platform_device *pdev); +void asoc_qcom_qaif_cpu_platform_remove(struct platform_device *pdev); +void asoc_qcom_qaif_cpu_platform_shutdown(struct platform_device *pdev); + +#endif /* __QAIF_H__ */ --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 3509F4C043F; Fri, 5 Jun 2026 10:37:59 +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=1780655884; cv=none; b=YWAnY+KnbuGZDqHOYdBaqUoTQ3A+cW9odeUZ0V79NaB/7jwdihC3QkTxueyvE+e0rAvblHKYV3tg3AXbZOuPpzbJtAYdHaaLNZJq6iiGX4Ijy9vPpudE4sE4PbOUhOTe43zTMk/ly8ODeznRb4rAFymG8R2PyCIJnQX4zGCePIs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655884; c=relaxed/simple; bh=tgPLGgEL1WIVqyIUWygbIykv+8YCLINwZtrCrgU5Tf8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=LSH2sG4jihJDiyXs6t395girmvJ/uP6XVOg8p/o+PoqsdT/leu0Elb90fsWRp2Ff0KOD776Fee7+4Om0gfg86UBKC8HYrylemePcr9YLIWg2o5DzF9kstJ2rZd9N1UTFl/yjxuOSPUk6TKFn3ie5uMqQ7UHN8TsGccLVeyN1ZZE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=E4f1e7iZ; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="E4f1e7iZ" Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6555qPj72428829; Fri, 5 Jun 2026 10:37:57 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=BmF+aXXZbqh Vw67+TZaXy17m4bxIpW8WFDWoHX9fzZE=; b=E4f1e7iZxsIx7ubTQDusu/iTIJP jwZtslK4V32CSw88bY/TezJNmmPw7jtfljAsR7a1+PvuSMWMibvGrO+4JfrWPuTG J5aCuAO4wk2rM6F68TIpum5UOzKd2PLn1LYthpRmchEgSW1a6i1BASuSHxcOoj7R awFPjYnMEHNNhktx1IKeK7rtc/qNYdd9l9X5zIWLvZl1YW1e71IYOMamKq9k/x85 ypmwKmdy0jphze6aDU5ZGiiCH2fWsV6AhTBpTXUdFUoenMmaBh0RZJ7cQlsQJ/D2 PfLuXrVxBLZbjSfBKvr/Vm+RG+c0+5VP0wbXDxCfw4uveIkLzMnFJNeYlwA== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekrphh43q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:37:57 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6r011714; Fri, 5 Jun 2026 10:37:53 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 6/13] ASoC: qcom: Add QAIF CIF (CDC DMA) DAI ops Date: Fri, 5 Jun 2026 16:07:32 +0530 Message-Id: <20260605103739.3557573-7-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-ORIG-GUID: 7nzNKJ343RlZnlTbSxsNhKRf6P5sgiIf X-Proofpoint-GUID: 7nzNKJ343RlZnlTbSxsNhKRf6P5sgiIf X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfXy9OIh0IdsDVI OB3xbh6slyvxvQGxDDmG4XwuNxtXUkS4CZsiaFBP2hLo5QyvhGu3dQdtI6QR+63LO480ieEHMt0 i/rJ3Bc3FedlLHjsKiDd6IiSm3Jgcgp/5k4WwG+VAFbg0fVeO8qCQHPiV3349bhXnl4Pvr1Hy6T 2e1qIe8GIksnlGpUqK6y8avnhVKCNVpo4g9es/tuhHGPzIK8x9xiYHcdnS6586fitCD1+PbW8v6 dASeEkdT0XzzelEY2Ln2j+Hi5laLdu5drbursScSpULymAck3EFlLmpp5MPEER0cjG2/eK3lU5p 85iM82yZt3jfRhv8sBGnlOL+Zym2y1vrcxVxZTYuD+j074b0tYRYZzyX3Cwaz6eA9OGYPRsOov/ 9lO7Zu1zjVJIM6rLtYg3NF6wFtVl3D/gWNOqoY7vZtp3n1KI4i4L92s8LRApYppodq23kq447Lh z1xHU1NnWcczvJ7I7UQ== X-Authority-Analysis: v=2.4 cv=T9a8ifKQ c=1 sm=1 tr=0 ts=6a22a705 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yOCtJkima9RkubShWh1s:22 a=EUspDBNiAAAA:8 a=Pf6h_ZWO9tHXqwoccAgA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 suspectscore=0 clxscore=1015 bulkscore=0 adultscore=0 priorityscore=1501 phishscore=0 spamscore=0 lowpriorityscore=0 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Add DAI operations for the QAIF Codec Interface (CIF), which connects the QAIF DMA engine to the internal Bolero digital codec. The CIF CDC DMA DAIs need to program the interface configuration for each allocated RDDMA or WRDMA channel. Without these ops, the driver cannot configure the active channel mask or enable the interface control bits required when starting a playback or capture stream. Initialize the CIF DMA and interface regmap fields, program the active channel mask from hw_params(), and update the CIF interface controls from trigger() for stream start, stop, suspend, resume and pause transitions. Signed-off-by: Harendra Gautam --- sound/soc/qcom/qaif-cpu.c | 315 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 sound/soc/qcom/qaif-cpu.c diff --git a/sound/soc/qcom/qaif-cpu.c b/sound/soc/qcom/qaif-cpu.c new file mode 100644 index 000000000000..8eedbccd8805 --- /dev/null +++ b/sound/soc/qcom/qaif-cpu.c @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-cpu.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qaif-reg.h" +#include "qaif.h" +#include "common.h" + + +static int qaif_cif_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata =3D dev_get_drvdata(dev); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_dmactl *rd_dmactl; + struct qaif_dmactl *wr_dmactl; + struct qaif_cdc_intfctl *rd_intfctl; + struct qaif_cdc_intfctl *wr_intfctl; + + rd_dmactl =3D devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!rd_dmactl) + return -ENOMEM; + + wr_dmactl =3D devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!wr_dmactl) + return -ENOMEM; + + rd_intfctl =3D devm_kzalloc(dev, sizeof(struct qaif_cdc_intfctl), GFP_KER= NEL); + if (!rd_intfctl) + return -ENOMEM; + + wr_intfctl =3D devm_kzalloc(dev, sizeof(struct qaif_cdc_intfctl), GFP_KER= NEL); + if (!wr_intfctl) + return -ENOMEM; + + /* + * Bulk-allocate CIF RDDMA dmactl fields. + * Order must match struct qaif_dmactl member order: + * enable, reset, num_ot, dma_dyncclk, burst16, burst8, burst4, burst2, b= urst1, shram_wm + */ + { + const struct reg_field cif_rd_dmactl_fields[] =3D { + v->cif_rddma_enable, + v->cif_rddma_reset, + v->cif_rddma_num_ot, + v->cif_rddma_dma_dyncclk, + v->cif_rddma_burst16, + v->cif_rddma_burst8, + v->cif_rddma_burst4, + v->cif_rddma_burst2, + v->cif_rddma_burst1, + v->cif_rddma_shram_wm, + }; + int ret =3D devm_regmap_field_bulk_alloc(dev, map, + &rd_dmactl->enable, + cif_rd_dmactl_fields, + ARRAY_SIZE(cif_rd_dmactl_fields)); + if (ret) { + dev_err(dev, "error allocating CIF RDDMA dmactl regmap fields: %d\n", r= et); + return ret; + } + } + + /* + * Bulk-allocate CIF RDDMA intfctl fields. + * Order must match struct qaif_cdc_intfctl member order: + * active_ch_en, fs_sel, fs_delay, fs_out_gate, intf_dyncclk, en_16bit_un= pack + */ + { + const struct reg_field cif_rd_intfctl_fields[] =3D { + v->cif_rddma_active_ch_en, + v->cif_rddma_fs_sel, + v->cif_rddma_fs_delay, + v->cif_rddma_fs_out_gate, + v->cif_rddma_intf_dyncclk, + v->cif_rddma_en_16bit_unpack, + }; + int ret =3D devm_regmap_field_bulk_alloc(dev, map, + &rd_intfctl->active_ch_en, + cif_rd_intfctl_fields, + ARRAY_SIZE(cif_rd_intfctl_fields)); + if (ret) { + dev_err(dev, "error allocating CIF RDDMA intfctl regmap fields: %d\n", = ret); + return ret; + } + } + + /* + * Bulk-allocate CIF WRDMA dmactl fields. + * Order must match struct qaif_dmactl member order: + * enable, reset, num_ot, dma_dyncclk, burst16, burst8, burst4, burst2, b= urst1, shram_wm + */ + { + const struct reg_field cif_wr_dmactl_fields[] =3D { + v->cif_wrdma_enable, + v->cif_wrdma_reset, + v->cif_wrdma_num_ot, + v->cif_wrdma_dma_dyncclk, + v->cif_wrdma_burst16, + v->cif_wrdma_burst8, + v->cif_wrdma_burst4, + v->cif_wrdma_burst2, + v->cif_wrdma_burst1, + v->cif_wrdma_shram_wm, + }; + int ret =3D devm_regmap_field_bulk_alloc(dev, map, + &wr_dmactl->enable, + cif_wr_dmactl_fields, + ARRAY_SIZE(cif_wr_dmactl_fields)); + if (ret) { + dev_err(dev, "error allocating CIF WRDMA dmactl regmap fields: %d\n", r= et); + return ret; + } + } + + /* + * Bulk-allocate CIF WRDMA intfctl fields. + * Order must match struct qaif_cdc_intfctl member order: + * active_ch_en, fs_sel, fs_delay, fs_out_gate, intf_dyncclk, en_16bit_un= pack + */ + { + const struct reg_field cif_wr_intfctl_fields[] =3D { + v->cif_wrdma_active_ch_en, + v->cif_wrdma_fs_sel, + v->cif_wrdma_fs_delay, + v->cif_wrdma_fs_out_gate, + v->cif_wrdma_intf_dyncclk, + v->cif_wrdma_en_16bit_unpack, + }; + int ret =3D devm_regmap_field_bulk_alloc(dev, map, + &wr_intfctl->active_ch_en, + cif_wr_intfctl_fields, + ARRAY_SIZE(cif_wr_intfctl_fields)); + if (ret) { + dev_err(dev, "error allocating CIF WRDMA intfctl regmap fields: %d\n", = ret); + return ret; + } + } + + drvdata->cif_rd_dmactl =3D rd_dmactl; + drvdata->cif_wr_dmactl =3D wr_dmactl; + drvdata->cif_rddma_intfctl =3D rd_intfctl; + drvdata->cif_wrdma_intfctl =3D wr_intfctl; + + return 0; +} + +static struct qaif_cdc_intfctl *qaif_get_cif_intfctl_handle(struct snd_pcm= _substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v =3D drvdata->variant; + unsigned int dai_id =3D cpu_dai->driver->id; + struct qaif_cdc_intfctl *intfctl =3D NULL; + + if (!v) { + dev_err(soc_runtime->dev, "No variant data\n"); + return intfctl; + } + + switch (dai_id) { + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + intfctl =3D drvdata->cif_rddma_intfctl; + break; + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + intfctl =3D drvdata->cif_wrdma_intfctl; + break; + default: + dev_err(soc_runtime->dev, "invalid dai id for dma ctl: %d\n", dai_id); + break; + } + return intfctl; +} + +static int qaif_cif_daiops_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_cdc_intfctl *intfctl =3D NULL; + unsigned int dai_id =3D cpu_dai->driver->id; + int ret; + unsigned int regval; + unsigned int channels =3D params_channels(params); + int idx; + + switch (channels) { + case 1: + regval =3D QAIF_CIF_DMA_INTF_ONE_CHANNEL; + break; + case 2: + regval =3D QAIF_CIF_DMA_INTF_TWO_CHANNEL; + break; + case 4: + regval =3D QAIF_CIF_DMA_INTF_FOUR_CHANNEL; + break; + case 6: + regval =3D QAIF_CIF_DMA_INTF_SIX_CHANNEL; + break; + case 8: + regval =3D QAIF_CIF_DMA_INTF_EIGHT_CHANNEL; + break; + default: + dev_err(soc_runtime->dev, "invalid PCM config\n"); + return -EINVAL; + } + + intfctl =3D qaif_get_cif_intfctl_handle(substream, dai); + if (!intfctl) { + dev_err(soc_runtime->dev, "Invalid intfctl: %d\n", dai_id); + return -EINVAL; + } + idx =3D v->get_dma_idx(dai_id); + if (idx < 0) { + dev_err(soc_runtime->dev, "Invalid DMA index: %d\n", idx); + return -EINVAL; + } + ret =3D regmap_fields_write(intfctl->active_ch_en, idx, regval); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to intfctl active_ch_en reg field: %d\n", ret); + return ret; + } + + return 0; +} + +static int qaif_cif_daiops_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v =3D drvdata->variant; + unsigned int dai_id =3D cpu_dai->driver->id; + struct qaif_cdc_intfctl *intfctl =3D NULL; + int ret =3D 0, idx; + + intfctl =3D qaif_get_cif_intfctl_handle(substream, dai); + if (!intfctl) { + dev_err(soc_runtime->dev, "Invalid intfctl: %d\n", dai_id); + return -EINVAL; + } + idx =3D v->get_dma_idx(dai_id); + if (idx < 0) { + dev_err(soc_runtime->dev, "Invalid DMA index: %d\n", idx); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret =3D regmap_fields_write(intfctl->intf_dyncclk, idx, QAIF_DMACTL_DYNC= LK_ON); + if (ret) { + dev_err(soc_runtime->dev, "error writing to dmactl intf_dyncclk reg fie= ld: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(intfctl->fs_sel, idx, QAIF_CIF_DMA_FS_SEL_DE= FAULT); + if (ret) { + dev_err(soc_runtime->dev, "error writing to dmactl codec_fs_sel reg fie= ld: %d\n", ret); + return ret; + } + + ret =3D regmap_fields_write(intfctl->en_16bit_unpack, idx, QAIF_CIF_16BI= T_UNPACK_ENABLE); + if (ret) { + dev_err(soc_runtime->dev, "error writing to dmactl en_16bit_unpack reg = field: %d\n", ret); + return ret; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret =3D regmap_fields_write(intfctl->intf_dyncclk, idx, QAIF_DMACTL_DYNC= LK_OFF); + if (ret) { + dev_err(soc_runtime->dev, "error writing to dmactl intf_dyncclk reg fie= ld: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(intfctl->en_16bit_unpack, idx, QAIF_CIF_16BI= T_UNPACK_DISABLE); + if (ret) { + dev_err(soc_runtime->dev, "error writing to dmactl en_16bit_unpack reg = field: %d\n", ret); + return ret; + } + break; + default: + ret =3D -EINVAL; + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, cmd); + break; + } + return ret; +} + +const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_ops =3D { + .hw_params =3D qaif_cif_daiops_hw_params, + .trigger =3D qaif_cif_daiops_trigger, +}; +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cif_dai_ops); --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 8CB494183B0; Fri, 5 Jun 2026 10:38:01 +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=1780655885; cv=none; b=Cim0LU2D+JWPjZSjF+q0xF+ClYi1vdHD/CMW9AAQCSKVJjMvu+z67ndG1GkwwUyk5S3S6omrhD97ZXzQQJzPh+jQpQo2QzZkLfq68ZkyOigaxsoCjQGZXhmYsZ2iTDX3VjHAa1HKE1B+4+mjek/JyBexAlXcETXOqvXxMoUd4bs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655885; c=relaxed/simple; bh=wc4CIVW98UZE61WGCPjyswWUNJEop6Met5BFfq7+0W4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=oTrceavExYrX8BpBv8ZSUB3Z/ebMIVO7R71YipjNM8TLHqeRo2c0aUmj693VIq+HjBMjsI+vnNRln8jx6zXfAAlMvonBtuCdxx+tTTxsRgTBRj8i5eUxa/5fZCBD9gndnvg3aRkzmbKjKB9fl071/hMdZ/rIItE00FVhaQDsstE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=cY+lST0H; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="cY+lST0H" Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6559mDpA3016236; Fri, 5 Jun 2026 10:37:58 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=Dlvu/8qpr2v aZYFITvsUYVQ3VriRRYBDbs3PIm9LI/E=; b=cY+lST0HhdRtMI8u2nnyhNCHHp2 3LZEsgzxn0vjBGXHT8NlRpTcTJp9hJWqmb5JH9UEwd/5GcIi7zZcaRw7qjGEYskX S9a0iropXKL09ID79/J7u8x3vgUhAPJoLIdYcGY0zVKY/gX5tx2kjZpbq5ymc2Qd bOfXv/VhC0jCJCkbt6rSolSER7/4lw6uqLKt0VJahFeTrzpWRyioXaJ7sh5lhX0C N9jiN9RIlsiPIuRFUXbojbsvZ/MaYGCOExZ7qsULtbLWJCQXwsRNHFyakfT8eNO3 veCU3Mp/xUTiPzqphhlSqqZzrj3K+B8EJTaQpJjSj4hvH5suwejcaPBsfdg== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekv56g6hy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:37:58 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6s011714; Fri, 5 Jun 2026 10:37:54 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 7/13] ASoC: qcom: Add QAIF AIF DAI ops Date: Fri, 5 Jun 2026 16:07:33 +0530 Message-Id: <20260605103739.3557573-8-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfX7AHvJKzGihcF Y4ujDhZvxDSKeYGnN81kod3WFyBXETeuTmwcS8DecStVF2wE+sf+57CCGdhD2BVHSeb1U/19ORv GhPimcWkUM1Y61Je043z29jX5m6hqQI8xlmYVLM7ZeSYoEALV8JDT00xSGYy1vlP0qLpaVrIOGQ CLHGlubzC+tV7ETb4AkkiI0mZ7HBcvCi92E43adolq3lJx9j8hkm3dzrs1+M/FqS5ZKvPSOwqZB jnFqD7zDGUWfXYMOhLNvvPUALHI+P/cCTX9WoOODlPT9oqMdFQWmJUP3Mt0XOFUz58v5ejJvJA4 gDwCxyHSaN/gFQeM2OkIC5LQkUgf54Vvrav6i0jU06eKL+9t5MJkNV8LDVuOnJF5o2nEc1rEgCj SSFbSMFnZkxdu8gvB/nZDh+WgqOqtUSEi1f8ylru4xIpC0r/sMgsWp3nCvlZY/KWi6I5ThZb5I0 6jBpqFJ/e6POR7bFE8Q== X-Authority-Analysis: v=2.4 cv=eJsjSnp1 c=1 sm=1 tr=0 ts=6a22a706 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=_glEPmIy2e8OvE2BGh3C:22 a=EUspDBNiAAAA:8 a=MYsBvJ0p-XDPe8fRrhQA:9 X-Proofpoint-ORIG-GUID: 7nKJmq6ieIPCUKbtsJHQH2dquG0dDVq4 X-Proofpoint-GUID: 7nKJmq6ieIPCUKbtsJHQH2dquG0dDVq4 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 impostorscore=0 bulkscore=0 clxscore=1011 spamscore=0 adultscore=0 suspectscore=0 lowpriorityscore=0 priorityscore=1501 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Add the CPU DAI operations and regmap field setup needed to use the QAIF AIF (MI2S) path. The existing QAIF CPU support does not provide the AIF callbacks needed to configure and control MI2S playback and capture streams. Add the AIF- specific register field allocation and DAI callbacks to program the AUD_INTF configuration, set the MI2S bit clock, configure the codec DAI TDM format, and enable or disable the interface during stream triggers. This allows QAIF to route playback through RDDMA channels and capture through WRDMA channels to external serial audio devices over MI2S. Signed-off-by: Harendra Gautam --- sound/soc/qcom/qaif-cpu.c | 451 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 451 insertions(+) diff --git a/sound/soc/qcom/qaif-cpu.c b/sound/soc/qcom/qaif-cpu.c index 8eedbccd8805..a455c6ded243 100644 --- a/sound/soc/qcom/qaif-cpu.c +++ b/sound/soc/qcom/qaif-cpu.c @@ -313,3 +313,471 @@ const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_o= ps =3D { .trigger =3D qaif_cif_daiops_trigger, }; EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cif_dai_ops); + +static int qaif_aif_cfg_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata =3D dev_get_drvdata(dev); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_aud_intfctl *aif_intfctl; + + aif_intfctl =3D devm_kzalloc(dev, sizeof(struct qaif_aud_intfctl), GFP_KE= RNEL); + if (!aif_intfctl) + return -ENOMEM; + + /* + * Bulk-allocate all AIF intfctl fields in one call. + * Order must match struct qaif_aud_intfctl member order: + * inv_sync, sync_delay, sync_mode, sync_src, + * slot_width_rx, slot_width_tx, sample_width_rx, sample_width_tx, + * mono_mode_rx, mono_mode_tx, + * lane_en, lane_dir, loopback_en, ctrl_data_oe, + * slot_en_rx_mask, slot_en_tx_mask, + * full_cycle_en, bits_per_lane, + * enable, enable_tx, enable_rx, + * reset, reset_tx, reset_rx + */ + { + const struct reg_field aif_intfctl_fields[] =3D { + v->aif_inv_sync, + v->aif_sync_delay, + v->aif_sync_mode, + v->aif_sync_src, + v->aif_slot_width_rx, + v->aif_slot_width_tx, + v->aif_sample_width_rx, + v->aif_sample_width_tx, + v->aif_mono_mode_rx, + v->aif_mono_mode_tx, + v->aif_lane_en, + v->aif_lane_dir, + v->aif_loopback_en, + v->aif_ctrl_data_oe, + v->aif_slot_en_rx_mask, + v->aif_slot_en_tx_mask, + v->aif_full_cycle_en, + v->aif_bits_per_lane, + v->aif_enable, + v->aif_enable_tx, + v->aif_enable_rx, + v->aif_reset, + v->aif_reset_tx, + v->aif_reset_rx, + }; + int ret =3D devm_regmap_field_bulk_alloc(dev, map, + &aif_intfctl->inv_sync, + aif_intfctl_fields, + ARRAY_SIZE(aif_intfctl_fields)); + if (ret) { + dev_err(dev, "error allocating AIF interface regmap fields: %d\n", ret); + return ret; + } + } + + drvdata->aif_intfctl =3D aif_intfctl; + + return 0; +} + +static int qaif_aif_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata =3D dev_get_drvdata(dev); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_dmactl *rd_dmactl; + struct qaif_dmactl *wr_dmactl; + + rd_dmactl =3D devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!rd_dmactl) + return -ENOMEM; + + wr_dmactl =3D devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!wr_dmactl) + return -ENOMEM; + + /* + * Bulk-allocate AIF RDDMA dmactl fields. + * Order must match struct qaif_dmactl member order: + * enable, reset, num_ot, dma_dyncclk, burst16, burst8, burst4, burst2, b= urst1, shram_wm + */ + { + const struct reg_field aif_rd_dmactl_fields[] =3D { + v->rddma_enable, + v->rddma_reset, + v->rddma_num_ot, + v->rddma_dma_dyncclk, + v->rddma_burst16, + v->rddma_burst8, + v->rddma_burst4, + v->rddma_burst2, + v->rddma_burst1, + v->rddma_shram_wm, + }; + int ret =3D devm_regmap_field_bulk_alloc(dev, map, + &rd_dmactl->enable, + aif_rd_dmactl_fields, + ARRAY_SIZE(aif_rd_dmactl_fields)); + if (ret) { + dev_err(dev, "error allocating AIF RDDMA dmactl regmap fields: %d\n", r= et); + return ret; + } + } + + /* + * Bulk-allocate AIF WRDMA dmactl fields. + * Order must match struct qaif_dmactl member order: + * enable, reset, num_ot, dma_dyncclk, burst16, burst8, burst4, burst2, b= urst1, shram_wm + */ + { + const struct reg_field aif_wr_dmactl_fields[] =3D { + v->wrdma_enable, + v->wrdma_reset, + v->wrdma_num_ot, + v->wrdma_dma_dyncclk, + v->wrdma_burst16, + v->wrdma_burst8, + v->wrdma_burst4, + v->wrdma_burst2, + v->wrdma_burst1, + v->wrdma_shram_wm, + }; + int ret =3D devm_regmap_field_bulk_alloc(dev, map, + &wr_dmactl->enable, + aif_wr_dmactl_fields, + ARRAY_SIZE(aif_wr_dmactl_fields)); + if (ret) { + dev_err(dev, "error allocating AIF WRDMA dmactl regmap fields: %d\n", r= et); + return ret; + } + } + + drvdata->aif_rd_dmactl =3D rd_dmactl; + drvdata->aif_wr_dmactl =3D wr_dmactl; + + return 0; +} + +static int qaif_aif_cpu_daiops_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata =3D snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v =3D drvdata->variant; + int idx, ret =3D 0; + + idx =3D v->get_dma_idx(dai->driver->id); + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret =3D clk_prepare(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + return 0; +} + +static void qaif_aif_cpu_daiops_shutdown(struct snd_pcm_substream *substre= am, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata =3D snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_aud_intfctl *aif_intfctl =3D drvdata->aif_intfctl; + const struct qaif_aif_config *aif_intf_cfg; + int idx =3D v->get_dma_idx(dai->driver->id); + + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return; + } + + aif_intf_cfg =3D &drvdata->aif_intf_cfg[idx]; + + if (aif_intf_cfg->loopback_en) + regmap_fields_write(aif_intfctl->enable, idx, QAIF_AIF_CTL_ENABLE_OFF); + else if (substream->stream =3D=3D SNDRV_PCM_STREAM_PLAYBACK) + regmap_fields_write(aif_intfctl->enable_tx, idx, QAIF_AIF_CTL_ENABLE_OFF= ); + else + regmap_fields_write(aif_intfctl->enable_rx, idx, QAIF_AIF_CTL_ENABLE_OFF= ); + + clk_unprepare(drvdata->mi2s_bit_clk[idx]); +} + +static int qaif_aif_cpu_daiops_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata =3D snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v =3D drvdata->variant; + int idx =3D v->get_dma_idx(dai->driver->id); + + if (idx < 0) + return 0; + + clk_disable(drvdata->mi2s_bit_clk[idx]); + return 0; +} + +static int qaif_aif_cpu_daiops_hw_params(struct snd_pcm_substream *substre= am, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata =3D snd_soc_dai_get_drvdata(dai); + struct snd_soc_pcm_runtime *rtd =3D substream->private_data; + struct snd_soc_dai *codec_dai =3D snd_soc_rtd_to_codec(rtd, 0); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_aud_intfctl *aif_intfctl =3D drvdata->aif_intfctl; + const struct qaif_aif_config *aif_intf_cfg =3D NULL; + int idx; + snd_pcm_format_t format =3D params_format(params); + unsigned int channels =3D params_channels(params); + unsigned int rate =3D params_rate(params); + unsigned int slot_width =3D 32; + int bitwidth, ret; + + if (!aif_intfctl) { + dev_err(dai->dev, "AIF interface control not initialized\n"); + return -EINVAL; + } + + idx =3D v->get_dma_idx(dai->driver->id); + + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + aif_intf_cfg =3D &drvdata->aif_intf_cfg[idx]; + + if (!aif_intf_cfg) { + dev_err(dai->dev, "AIF interface config not found\n"); + return -EINVAL; + } + bitwidth =3D snd_pcm_format_width(format); + if (bitwidth < 0) { + dev_err(dai->dev, "invalid bit width given: %d\n", bitwidth); + return bitwidth; + } + + /* SYNC_CFG: write all four sync fields */ + ret =3D regmap_fields_write(aif_intfctl->inv_sync, idx, aif_intf_cfg->inv= ert_sync); + if (ret) { + dev_err(dai->dev, "Failed to write inv_sync: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(aif_intfctl->sync_delay, idx, aif_intf_cfg->s= ync_delay); + if (ret) { + dev_err(dai->dev, "Failed to write sync_delay: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(aif_intfctl->sync_mode, idx, aif_intf_cfg->sy= nc_mode); + if (ret) { + dev_err(dai->dev, "Failed to write sync_mode: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(aif_intfctl->sync_src, idx, aif_intf_cfg->syn= c_src); + if (ret) { + dev_err(dai->dev, "Failed to write sync_src: %d\n", ret); + return ret; + } + + /* LANE_CFG: write all four lane fields */ + ret =3D regmap_fields_write(aif_intfctl->loopback_en, idx, aif_intf_cfg->= loopback_en); + if (ret) { + dev_err(dai->dev, "Failed to write loopback_en: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(aif_intfctl->ctrl_data_oe, idx, aif_intf_cfg-= >ctrl_data_oe); + if (ret) { + dev_err(dai->dev, "Failed to write ctrl_data_oe: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(aif_intfctl->lane_en, idx, aif_intf_cfg->lane= _en_mask); + if (ret) { + dev_err(dai->dev, "Failed to write lane_en (mask=3D0x%02X): %d\n", + aif_intf_cfg->lane_en_mask, ret); + return ret; + } + ret =3D regmap_fields_write(aif_intfctl->lane_dir, idx, aif_intf_cfg->lan= e_dir_mask); + if (ret) { + dev_err(dai->dev, "Failed to write lane_dir (mask=3D0x%02X): %d\n", + aif_intf_cfg->lane_dir_mask, ret); + return ret; + } + + /* CFG: full_cycle_en */ + ret =3D regmap_fields_write(aif_intfctl->full_cycle_en, idx, aif_intf_cfg= ->full_cycle_en); + if (ret) { + dev_err(dai->dev, "Failed to write full_cycle_en: %d\n", ret); + return ret; + } + + if (substream->stream =3D=3D SNDRV_PCM_STREAM_PLAYBACK) { + slot_width =3D aif_intf_cfg->slot_width_tx; + /* BIT_WIDTH_CFG: TX slot width and sample width */ + ret =3D regmap_fields_write(aif_intfctl->slot_width_tx, idx, + QAIF_AIF_SLOT_WIDTH(slot_width)); + if (ret) { + dev_err(dai->dev, "Failed to write slot_width_tx: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(aif_intfctl->sample_width_tx, idx, + QAIF_AIF_SAMPLE_WIDTH(bitwidth)); + if (ret) { + dev_err(dai->dev, "Failed to write sample_width_tx: %d\n", ret); + return ret; + } + + /* ACTV_SLOT_EN_TX */ + ret =3D regmap_fields_write(aif_intfctl->slot_en_tx_mask, idx, + aif_intf_cfg->slot_en_tx_mask); + if (ret) { + dev_err(dai->dev, "Failed to write slot_en_tx_mask (0x%08X): %d\n", + aif_intf_cfg->slot_en_tx_mask, ret); + return ret; + } + + /* FRAME_CFG: bits_per_lane */ + ret =3D regmap_fields_write(aif_intfctl->bits_per_lane, idx, + (slot_width * aif_intf_cfg->bits_per_lane) - 1); + if (ret) { + dev_err(dai->dev, "Failed to write bits_per_lane: %d\n", ret); + return ret; + } + + /* MI2S_CFG: TX mono mode */ + ret =3D regmap_fields_write(aif_intfctl->mono_mode_tx, idx, + (channels >=3D 2) ? QAIF_AUD_INTF_CTL_STEREO + : QAIF_AUD_INTF_CTL_MONO); + if (ret) { + dev_err(dai->dev, "Failed to write mono_mode_tx: %d\n", ret); + return ret; + } + } else { + slot_width =3D aif_intf_cfg->slot_width_rx; + /* BIT_WIDTH_CFG: RX slot width and sample width */ + ret =3D regmap_fields_write(aif_intfctl->slot_width_rx, idx, + QAIF_AIF_SLOT_WIDTH(slot_width)); + if (ret) { + dev_err(dai->dev, "Failed to write slot_width_rx: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(aif_intfctl->sample_width_rx, idx, + QAIF_AIF_SAMPLE_WIDTH(bitwidth)); + if (ret) { + dev_err(dai->dev, "Failed to write sample_width_rx: %d\n", ret); + return ret; + } + + /* ACTV_SLOT_EN_RX */ + ret =3D regmap_fields_write(aif_intfctl->slot_en_rx_mask, idx, + aif_intf_cfg->slot_en_rx_mask); + if (ret) { + dev_err(dai->dev, "Failed to write slot_en_rx_mask (0x%08X): %d\n", + aif_intf_cfg->slot_en_rx_mask, ret); + return ret; + } + + /* FRAME_CFG: bits_per_lane */ + ret =3D regmap_fields_write(aif_intfctl->bits_per_lane, idx, + (slot_width * aif_intf_cfg->bits_per_lane) - 1); + if (ret) { + dev_err(dai->dev, "Failed to write bits_per_lane: %d\n", ret); + return ret; + } + + /* MI2S_CFG: RX mono mode */ + ret =3D regmap_fields_write(aif_intfctl->mono_mode_rx, idx, + (channels >=3D 2) ? QAIF_AUD_INTF_CTL_STEREO + : QAIF_AUD_INTF_CTL_MONO); + if (ret) { + dev_err(dai->dev, "Failed to write mono_mode_rx: %d\n", ret); + return ret; + } + } + + ret =3D clk_set_rate(drvdata->mi2s_bit_clk[idx], + rate * slot_width * aif_intf_cfg->bits_per_lane); + if (ret) { + dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n", + rate * slot_width * aif_intf_cfg->bits_per_lane, ret); + return ret; + } + dev_dbg(dai->dev, "setting IBIT clock to %u\n", + rate * slot_width * aif_intf_cfg->bits_per_lane); + + ret =3D clk_enable(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + snd_soc_dai_set_tdm_slot(codec_dai, 0x0f, 0b11, aif_intf_cfg->bits_per_la= ne, slot_width); + snd_soc_dai_set_sysclk(codec_dai, 0, rate * aif_intf_cfg->bits_per_lane *= slot_width, 0); + + return 0; +} + +static int qaif_aif_cpu_daiops_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata =3D snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v =3D drvdata->variant; + int idx, ret =3D -EINVAL; + const struct qaif_aif_config *aif_intf_cfg; + + idx =3D v->get_dma_idx(dai->driver->id); + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + aif_intf_cfg =3D &drvdata->aif_intf_cfg[idx]; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (aif_intf_cfg->loopback_en) + ret =3D regmap_fields_write(drvdata->aif_intfctl->enable, idx, QAIF_AIF= _CTL_ENABLE_ON); + else if (substream->stream =3D=3D SNDRV_PCM_STREAM_PLAYBACK) + ret =3D regmap_fields_write(drvdata->aif_intfctl->enable_tx, idx, QAIF_= AIF_CTL_ENABLE_ON); + else + ret =3D regmap_fields_write(drvdata->aif_intfctl->enable_rx, idx, QAIF_= AIF_CTL_ENABLE_ON); + if (ret) + dev_err(dai->dev, "error writing to AIF CTL reg: %d\n", ret); + + ret =3D clk_enable(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + + if (aif_intf_cfg->loopback_en) + ret =3D regmap_fields_write(drvdata->aif_intfctl->enable, idx, QAIF_AIF= _CTL_ENABLE_OFF); + else if (substream->stream =3D=3D SNDRV_PCM_STREAM_PLAYBACK) + ret =3D regmap_fields_write(drvdata->aif_intfctl->enable_tx, idx, QAIF_= AIF_CTL_ENABLE_OFF); + else + ret =3D regmap_fields_write(drvdata->aif_intfctl->enable_rx, idx, QAIF_= AIF_CTL_ENABLE_OFF); + if (ret) + dev_err(dai->dev, "error writing to AIF CTL reg: %d\n", ret); + + clk_disable(drvdata->mi2s_bit_clk[idx]); + + break; + } + + return ret; +} + +const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops =3D { + .startup =3D qaif_aif_cpu_daiops_startup, + .shutdown =3D qaif_aif_cpu_daiops_shutdown, + .hw_free =3D qaif_aif_cpu_daiops_hw_free, + .hw_params =3D qaif_aif_cpu_daiops_hw_params, + .trigger =3D qaif_aif_cpu_daiops_trigger, +}; +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_aif_cpu_dai_ops); --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 D15524183C7; Fri, 5 Jun 2026 10:38:01 +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=1780655884; cv=none; b=jWwyQma11VU+QxIJ5ThIye86zFHHG4edns+yNurw7xbdxwY2xoNygS0URyU8VMdH+1vUc5WTlONF7VBb8mJaElHWC1mStYdwumzPaobFHKdPN0W/ZF/NqMPCWfWoCDN1+sA2nlBbxaoGbIB6nYdAuP13JAN51nMvBkKIaTIdOAM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655884; c=relaxed/simple; bh=g8AbOkSXcU/8GItxMeSd2As/AfiC03vjCGKOW/TEu6w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=aMzkcJ8DhtT1WVt8f52EU4CPUZWSCS/sr0szBMZc+z4t01rvTUpkU9Kv1e/PNm8px3YGMauhN9+MF8VhJqDfRpVRbEBqszkT7apMk8NO2We26HDO7CF7724sw+40W7GGhSIaxJa5eXB55na4372f/I2o39oOPgv9wIJcJ0R4L0k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=j5dYgnQQ; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="j5dYgnQQ" Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6555qLrF2428783; Fri, 5 Jun 2026 10:37:59 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=dxvZiMITXar Y2Wg7jDIvSuF9WeIimNknXWUyES4VKvQ=; b=j5dYgnQQcv2p1GiJ/NMjDMSS5dA k3439/lgNsYV0ko86/N9unRGihZQ5H2gjNgKyV+ZySY9zFB2grhREqlxfzJJw7Oe Lbrf63A2dbDrDS6C1hhY7hG/jEB/HnssaQ6iDDqPGOf5wCeMZQligBuHzxx0yg8P eDly2V16mofcefqkaiAgD1JLcNZup740cS5TuAbt48kjTW44oNMMzCXAw3xlevry X331jqFbX475GCbZ/cZqjjm7/Hpx4qmNIOSnoJj70paeNfCXJCTkEOolaNRtjMKm nF66DTyrN+n7kJBpsW7T0dKBw0iZkLXgaSQ4m7JM4R805s/olUuagMTo9uA== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekrphh43w-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:37:59 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6t011714; Fri, 5 Jun 2026 10:37:56 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 8/13] ASoC: qcom: Add generic of_xlate_dai_name helper to common Date: Fri, 5 Jun 2026 16:07:34 +0530 Message-Id: <20260605103739.3557573-9-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-ORIG-GUID: J7OGugiKoen5ox8BXGG3Fwm9rxFwhiqP X-Proofpoint-GUID: J7OGugiKoen5ox8BXGG3Fwm9rxFwhiqP X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfX2rO8JyAc0dUt vjPO47Owy1NNOllwHHSPz6cUfrErLEYWqm1c5xA62wy0utZ0OiLa69y4pEgzc7bjkPQ9g4O4jyf orc+5bUPTka0rzBmgux28QQegcC/+qXP8DD1pKiV0O9PvGvdiazNcHuz/t/p5FijNDJ/DSAEKjX 9OLSzSyjoTpzb4JilSXftv56yp1cqK+TMDZp0p4wPginY4rUsUwzdqtgzitDKKOHNxfTxbyqnWs feJlu66kJYJK+ie+pRgyavgg80yQxd5hjGBUlJxrDBxov45o8d6Lc6zWrcrDfGVs2LgS5BLxa2k Kcu5B+3WIJckBjxLa6wnFHfA9o5fzvwv7vWWBZUwOu/q30oboW6JhKm7coRhLhdZIny/5yin8hk uEDepDe0ngX8is7LYT/Noh5QdMRz+N+lYCWJ22zMsZzcrohUvIktMHCJ0xECKkIP9W2W3zK8a5H USQM0rnurm6jcLAbYPQ== X-Authority-Analysis: v=2.4 cv=T9a8ifKQ c=1 sm=1 tr=0 ts=6a22a707 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yOCtJkima9RkubShWh1s:22 a=EUspDBNiAAAA:8 a=oUFy9JDnOWMlxJQm5LIA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 suspectscore=0 clxscore=1011 bulkscore=0 adultscore=0 priorityscore=1501 phishscore=0 spamscore=0 lowpriorityscore=0 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Multiple Qualcomm ASoC CPU DAI drivers need to resolve a sound-dai phandle argument to a DAI name by searching the component's DAI driver array by ID. Each driver currently implements this identically. Extract the common logic into asoc_qcom_of_xlate_dai_name() in common.c so it can be shared across drivers without duplication. Signed-off-by: Harendra Gautam --- sound/soc/qcom/common.c | 34 ++++++++++++++++++++++++++++++++++ sound/soc/qcom/common.h | 5 +++++ 2 files changed, 39 insertions(+) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index cf1f3a767cee..46569290d44c 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -23,6 +23,40 @@ static const struct snd_soc_dapm_widget qcom_jack_snd_wi= dgets[] =3D { SND_SOC_DAPM_SPK("DP7 Jack", NULL), }; =20 +/** + * asoc_qcom_of_xlate_dai_name - Resolve a sound-dai phandle argument to a + * DAI name by searching the DAI driver arra= y. + * @dai_drv: Array of DAI drivers registered by the component. + * @num_dai: Number of entries in @dai_drv. + * @args: Phandle arguments from the sound-dai property; args[0] is the + * DAI ID. + * @dai_name: Output pointer set to the matched DAI name on success. + * + * Returns 0 on success, -EINVAL if args_count !=3D 1 or no match is found. + */ +int asoc_qcom_of_xlate_dai_name(const struct snd_soc_dai_driver *dai_drv, + int num_dai, + const struct of_phandle_args *args, + const char **dai_name) +{ + int id, i; + + if (args->args_count !=3D 1) + return -EINVAL; + + id =3D args->args[0]; + + for (i =3D 0; i < num_dai; i++) { + if (dai_drv[i].id =3D=3D id) { + *dai_name =3D dai_drv[i].name; + return 0; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(asoc_qcom_of_xlate_dai_name); + int qcom_snd_parse_of(struct snd_soc_card *card) { struct device_node *np; diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h index ee6662885593..5baf51a39c97 100644 --- a/sound/soc/qcom/common.h +++ b/sound/soc/qcom/common.h @@ -6,6 +6,7 @@ =20 #include #include +#include =20 #define LPASS_MAX_PORT (SENARY_MI2S_TX + 1) =20 @@ -15,5 +16,9 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *r= td, int qcom_snd_dp_jack_setup(struct snd_soc_pcm_runtime *rtd, struct snd_soc_jack *dp_jack, int id); =20 +int asoc_qcom_of_xlate_dai_name(const struct snd_soc_dai_driver *dai_drv, + int num_dai, + const struct of_phandle_args *args, + const char **dai_name); =20 #endif --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 DBEA04C77AB; Fri, 5 Jun 2026 10:38:04 +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=1780655886; cv=none; b=evLH9W7Oihv4YKxgar0zLk4yQLW44DA+LlIHmDeTdik2vdrcIqemEz2yF/OtaSzUiqmPzts8DdIRPYHCvBMrDueGrU9OuM/asVtVYck6gHJjWD0tOamFfg9MFkGIuJ2GMDJ431Dn+/VLN7E7XUhVFjEhCI7Bl761pZutbTuiPBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655886; c=relaxed/simple; bh=nF1bRL+0i+sdOb4OP2N9xnfU/mirbjvsHliu1OlK+mg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Ixeeo/GekdsTs/o1O8dWXCHoiJ4paTfkAOjB9fiaKHELjCU1GyFc4MBn4Gs+9nuycWIcOW0nrumh8fqdXttcdSspNYub49+85Am/zsOiOV/vezVzREdZG21PbFTEltNGJphL7bkQpwWVVVsSRCZRlzwqXsAEhG3rAly98mGj4MI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=Hj8jE5GL; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="Hj8jE5GL" Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 655A5sBh2974958; Fri, 5 Jun 2026 10:38:02 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=pkfnQ/nPGko XdiZ9aGhJnWQ3C2t7kl778gfFKiG53m0=; b=Hj8jE5GL4ieyQxqPnRQGnPHLXcA DyOymz2CNjTwt3SFma4PNglo4j2HNorO+DkpfnkVvjyjZc+hfXeVtfuYJJP8oF5D wVnIbW+qm7rc6kqbPb3QDQ81/Dbj49T+t69sU0zBm9AAK53TI4ey/Lv/TO5iImwT O9Frh7w0mZuzJUqg5T2OPpmxAzKbUDX7Uaov/1tnrTOkMevBmGJ/hzTM07rIFz0f e0YSRYzrxaT+PTEld6PFtriCkZCIX+4T84NjN6LOS2UdsuDOV3ncMBs4KqNw4Mym XDhkGsgtzKrCRJZsCe1/QiBtMuQuysrya+AC286O1ibsT+8+qRBdHOBtcHA== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekpnu9hd3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:38:02 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6u011714; Fri, 5 Jun 2026 10:37:58 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 9/13] ASoC: qcom: lpass-cpu: Use asoc_qcom_of_xlate_dai_name helper Date: Fri, 5 Jun 2026 16:07:35 +0530 Message-Id: <20260605103739.3557573-10-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-GUID: kW4k7W0KTxswYaIy9eosMol04mRNgCM6 X-Authority-Analysis: v=2.4 cv=Ksl9H2WN c=1 sm=1 tr=0 ts=6a22a70a cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=3WHJM1ZQz_JShphwDgj5:22 a=EUspDBNiAAAA:8 a=Hfps_RfwFyUEpd0PCboA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfXxH0sPpyV1B2V 9kGhnkhhz77MI8jvYEnk8xyJk9W1xi0HseuRzjtK5+jg8Fnlm33ZTaNwhWUB6/TIOHLxGXLGzIw PF0UAl4hkJKBP7GGo848YOql7R3bSPCZQKOtZqUKv1YwlLfuZOnxVO5xTzrO3KSKtwoJAP4bTo/ 1xNTiJFF2+LTUINLnpl/ViyXqf7jtC4hj74AHD04ai9+GIOk49pIzTUS6rCUm/e/9NFgRJWUbm2 +IUjipqEUix6TVYmW/tNjcKwqWw6MJkIU1U6zXhsy9kPB5bA47WAr3ex3hjjD7s5C+FUP2cvyTI cQihUD12cxzPRVUoJQYpoH1UDz9smItuKrJa6WwVttOYn09s9W54q1EjeVanYn8EqVi1KWE37FO V2myGWA0iiIUIwULuq3jvoHJU1gR4Pv+cSB1Wh0d9zGzoWnZqqc6Ck33j1m9IcH31mTFi2j65Ug SJKQSjc0OIrMH14oJgw== X-Proofpoint-ORIG-GUID: kW4k7W0KTxswYaIy9eosMol04mRNgCM6 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 phishscore=0 clxscore=1015 priorityscore=1501 adultscore=0 lowpriorityscore=0 spamscore=0 malwarescore=0 bulkscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Replace the private static asoc_qcom_of_xlate_dai_name() implementation in lpass-cpu.c with a thin wrapper that calls the new shared helper from common.c. This removes the duplicate implementation. Signed-off-by: Harendra Gautam --- sound/soc/qcom/lpass-cpu.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 242bc16da36d..35c2c8030024 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -18,6 +18,7 @@ #include #include "lpass-lpaif-reg.h" #include "lpass.h" +#include "common.h" =20 #define LPASS_CPU_MAX_MI2S_LINES 4 #define LPASS_CPU_I2S_SD0_MASK BIT(0) @@ -458,30 +459,20 @@ const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_= ops2 =3D { }; EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops2); =20 -static int asoc_qcom_of_xlate_dai_name(struct snd_soc_component *component, +static int lpass_cpu_of_xlate_dai_name(struct snd_soc_component *component, const struct of_phandle_args *args, const char **dai_name) { struct lpass_data *drvdata =3D snd_soc_component_get_drvdata(component); const struct lpass_variant *variant =3D drvdata->variant; - int id =3D args->args[0]; - int ret =3D -EINVAL; - int i; =20 - for (i =3D 0; i < variant->num_dai; i++) { - if (variant->dai_driver[i].id =3D=3D id) { - *dai_name =3D variant->dai_driver[i].name; - ret =3D 0; - break; - } - } - - return ret; + return asoc_qcom_of_xlate_dai_name(variant->dai_driver, + variant->num_dai, args, dai_name); } =20 static const struct snd_soc_component_driver lpass_cpu_comp_driver =3D { .name =3D "lpass-cpu", - .of_xlate_dai_name =3D asoc_qcom_of_xlate_dai_name, + .of_xlate_dai_name =3D lpass_cpu_of_xlate_dai_name, .legacy_dai_naming =3D 1, }; =20 --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 8C9B04C9569; Fri, 5 Jun 2026 10:38:08 +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=1780655892; cv=none; b=b0NMXrS/caxz0yGM9yftrcu7szWPUjLVYLW0izxScNjpODQV/RvlEtJWs53MAB2TrHt7jbN2mhqEL8ZsfuN6KLEronhqjhPAsIGqU5WldxJK+ueYgR/L2cAbLEKW2nlRIk2ZnQXm2pWLf5PgPWLzUJyKm0prvuVouzuw6h9qSKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655892; c=relaxed/simple; bh=U+eBHVCuWC2PcDEROpFkgtbXqpmjsuxiGh+NIZYmK+8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=UlstR1GSjCbUNOyau3zmvUfA7jtK+slc0s9HiVXGLpRu0p0B4yXPjnpPAj1HsEMCLhUV44EFKLlbYITOcwTfQdnSJ0wcv47xxscmqr3b8hBlvfOt6FVsnYzhxmywxa8BBfozZKgXWvyWXhUGFtvt7MY8jxkjNxL8oWX95oZRWe0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=bCde6dHL; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="bCde6dHL" Received: from pps.filterd (m0279862.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6559MGc1821374; Fri, 5 Jun 2026 10:38:05 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= PG+s4wrOhvGK3NYUoGGV2+vR+cYzBVIugGNuy9LnIPw=; b=bCde6dHLewBjS7Go k5x5Zyj7zg0ANzRDRR9XAwmJirpzIdrRQMQ2qaMxz8iOuVpxZgporgPQpFKNe4PU 3petn7fouUKxkKB7tTmQ9gtikQ5zH9O9DmSe3Ap9IKj/a7I2MB1ghiMS8yf2FmDZ mq/0XF6dZUfYqYUThMlOsIXzTQPy7RNoI1XaWRbx9BKc1662p8Lfi6p2ofzVTXon lnS4IgAEyY6kFxa+ApstiXbjUMjwNPdBQcSHljHCRcRe29pmmudt3Tzy0TCfAMmM YZggJobIBoF8qlE5OoW4SqImo6WxPEh+OscXyj/Lx0nxjwlhcikBcm5/gEfuEmGF GRJwXQ== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekncbhtfe-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:38:04 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6v011714; Fri, 5 Jun 2026 10:38:01 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 10/13] ASoC: qcom: Add QAIF regmap, DT parsing and platform init Date: Fri, 5 Jun 2026 16:07:36 +0530 Message-Id: <20260605103739.3557573-11-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.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; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Authority-Analysis: v=2.4 cv=OauoyBTY c=1 sm=1 tr=0 ts=6a22a70d cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=IkcTkHD0fZMA:10 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=_K5XuSEh1TEqbUxoQ0s3:22 a=EUspDBNiAAAA:8 a=1Fgo0t1f-OoWx1_SSeUA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfX7kp58377liAG zC2/Kk6eLqGCuJO/IpDNvnC3mqNxGff9uRZOM2wC8LzLqNQ4HqJN8mmmxIHjoZhThvxPcD5Wbwo q5iZfexz7FwaJREtqI6QuGQa0hKiHtQfiykhqXTZHEzPk31FI2QTO5ggHiY2LXAfwmvIVh5tF18 LVFN7lPP8ftTyMzZeBSzqgN8BmyyDYOD5SmhdHyYbAyU1c1Qy94OB37Q/BjeX64pWi7kxtFU09C xi1pyjVJ89xD/ytR8nljrt5AYvC/w4HrrDLtWMVhTksxQ6sDf41UTOHqrOPsNviP/8IAMTZn57b BEvbEXf6NEkyf31f0pDKEsykGHQI34eISiMHvz4pYQa2sGJlAK2GB9xphvWbuG34h0dbsuYz3/1 rYeOwlnK/yiPbPRM3Gr9dNiTVOjLD23jd+da2tqSfx/E36Z3ews98KFBqlvqMIvWMUljLa0gZ85 mFEewL+x8b+WC1W1xoA== X-Proofpoint-GUID: F7eGnW9v1gny2lKcrVM0UhAmTUiX0gmR X-Proofpoint-ORIG-GUID: F7eGnW9v1gny2lKcrVM0UhAmTUiX0gmR X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 spamscore=0 priorityscore=1501 phishscore=0 impostorscore=0 malwarescore=0 suspectscore=0 bulkscore=0 lowpriorityscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Add the core CPU and platform bring-up needed for the Qualcomm Audio Interface driver. The existing QAIF DAI code needs device-level infrastructure before it can configure interfaces or run PCM streams. Add the MMIO regmap setup, including readable, writable and volatile register tables, so the driver can safely access QAIF control, DMA, interrupt and SHRAM registers. Parse the QAIF AIF child nodes from devicetree and store the per-interface PCM, TDM or MI2S configuration for use when programming the AUD_INTF registers. Add the platform probe, remove and shutdown entry points to map the device registers, initialize variant-specific resources, allocate regmap fields, acquire clocks and register the CPU DAI component. Add the QAIF PCM platform support needed for DMA streams, including PCM hardware constraints, coherent DMA buffer allocation using dma_alloc_coherent(), EE resource mapping, QXM DMA routing and SHRAM partitioning for AIF and CIF DMA channels. Signed-off-by: Harendra Gautam --- sound/soc/qcom/qaif-cpu.c | 808 +++++++++++++++++++++++++++++++++ sound/soc/qcom/qaif-platform.c | 276 +++++++++++ 2 files changed, 1084 insertions(+) create mode 100644 sound/soc/qcom/qaif-platform.c diff --git a/sound/soc/qcom/qaif-cpu.c b/sound/soc/qcom/qaif-cpu.c index a455c6ded243..62a78b30744c 100644 --- a/sound/soc/qcom/qaif-cpu.c +++ b/sound/soc/qcom/qaif-cpu.c @@ -779,3 +779,804 @@ const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_d= ai_ops =3D { .trigger =3D qaif_aif_cpu_daiops_trigger, }; EXPORT_SYMBOL_GPL(asoc_qcom_qaif_aif_cpu_dai_ops); + +static int qaif_cpu_of_xlate_dai_name(struct snd_soc_component *component, + const struct of_phandle_args *args, + const char **dai_name) +{ + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + const struct qaif_variant *v =3D drvdata->variant; + + return asoc_qcom_of_xlate_dai_name(v->dai_driver, + v->num_dai, args, dai_name); +} + +static const struct snd_soc_component_driver qaif_cpu_comp_driver =3D { + .name =3D "qaif-cpu", + .of_xlate_dai_name =3D qaif_cpu_of_xlate_dai_name, +}; + +static bool audio_qaif_regmap_writeable(struct device *dev, unsigned int r= eg) +{ + struct qaif_drv_data *drvdata =3D dev_get_drvdata(dev); + const struct qaif_variant *v =3D drvdata->variant; + int i; + + /* EE maps */ + if (reg =3D=3D QAIF_EE_RDDMA_MAP_REG(v)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_MAP_REG(v)) + return true; + if (reg =3D=3D QAIF_EE_INTF_MAP_REG(v)) + return true; + if (reg =3D=3D QAIF_EE_CODEC_RDDMA_MAP_REG(v)) + return true; + if (reg =3D=3D QAIF_EE_CODEC_WRDMA_MAP_REG(v)) + return true; + + /* QXM DMA path mapping */ + if (reg =3D=3D QAIF_RDDMA_MAP_QXM) + return true; + if (reg =3D=3D QAIF_WRDMA_MAP_QXM) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_MAP_QXM) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_MAP_QXM) + return true; + + /* SID maps */ + if (reg =3D=3D QAIF_WRDMA_SID_MAP_REG) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_SID_MAP_REG) + return true; + if (reg =3D=3D QAIF_RDDMA_SID_MAP_REG) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_SID_MAP_REG) + return true; + + /* SHRAM QXM0 start address and length */ + for (i =3D 0; i < v->num_rddma; i++) { + if (reg =3D=3D QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i)) + return true; + if (reg =3D=3D QAIF_RDDMA_QXM0_SHRAM_LEN(i)) + return true; + } + for (i =3D 0; i < v->num_codec_rddma; i++) { + if (reg =3D=3D QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i)) + return true; + } + for (i =3D 0; i < v->num_wrdma; i++) { + if (reg =3D=3D QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i)) + return true; + if (reg =3D=3D QAIF_WRDMA_QXM0_SHRAM_LEN(i)) + return true; + } + for (i =3D 0; i < v->num_codec_wrdma; i++) { + if (reg =3D=3D QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i)) + return true; + } + + /* EE IRQ EN and CLR */ + for (i =3D 0; i < DMA_TYPE_MAX; i++) { + if (reg =3D=3D QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i)) + return true; + } + + /* AUD_INTF control and configuration */ + for (i =3D 0; i < v->num_intf; i++) { + if (reg =3D=3D QAIF_AUD_INTF_CTL_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_SYNC_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_FRAME_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_LANE_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_MI2S_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_CFG_REG(i)) + return true; + } + + /* RDDMA control and configuration */ + for (i =3D 0; i < v->num_rddma; i++) { + if (reg =3D=3D QAIF_RDDMA_CTL_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_CFG_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_PERIOD_LEN_REG(v, i)) + return true; + } + + /* CODEC RDDMA control and configuration */ + for (i =3D 0; i < v->num_codec_rddma; i++) { + if (reg =3D=3D QAIF_CODEC_RDDMA_CTL_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_CFG_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_INTF_CFG_REG(v, i)) + return true; + } + + /* WRDMA control and configuration */ + for (i =3D 0; i < v->num_wrdma; i++) { + if (reg =3D=3D QAIF_WRDMA_CTL_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_CFG_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_PERIOD_LEN_REG(v, i)) + return true; + } + + /* CODEC WRDMA control and configuration */ + for (i =3D 0; i < v->num_codec_wrdma; i++) { + if (reg =3D=3D QAIF_CODEC_WRDMA_CTL_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_CFG_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_INTF_CFG_REG(v, i)) + return true; + } + + return false; +} + +static bool audio_qaif_regmap_readable(struct device *dev, unsigned int re= g) +{ + struct qaif_drv_data *drvdata =3D dev_get_drvdata(dev); + const struct qaif_variant *v =3D drvdata->variant; + int i; + + /* Summary IRQ status */ + if (reg =3D=3D QAIF_SUMMARY_IRQSTAT_REG(v)) + return true; + + /* EE maps */ + if (reg =3D=3D QAIF_EE_RDDMA_MAP_REG(v)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_MAP_REG(v)) + return true; + if (reg =3D=3D QAIF_EE_INTF_MAP_REG(v)) + return true; + if (reg =3D=3D QAIF_EE_CODEC_RDDMA_MAP_REG(v)) + return true; + if (reg =3D=3D QAIF_EE_CODEC_WRDMA_MAP_REG(v)) + return true; + + /* QXM DMA path mapping */ + if (reg =3D=3D QAIF_RDDMA_MAP_QXM) + return true; + if (reg =3D=3D QAIF_WRDMA_MAP_QXM) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_MAP_QXM) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_MAP_QXM) + return true; + + /* SID maps */ + if (reg =3D=3D QAIF_WRDMA_SID_MAP_REG) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_SID_MAP_REG) + return true; + if (reg =3D=3D QAIF_RDDMA_SID_MAP_REG) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_SID_MAP_REG) + return true; + + /* SHRAM QXM0 start address and length */ + for (i =3D 0; i < v->num_rddma; i++) { + if (reg =3D=3D QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i)) + return true; + if (reg =3D=3D QAIF_RDDMA_QXM0_SHRAM_LEN(i)) + return true; + } + for (i =3D 0; i < v->num_codec_rddma; i++) { + if (reg =3D=3D QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i)) + return true; + } + for (i =3D 0; i < v->num_wrdma; i++) { + if (reg =3D=3D QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i)) + return true; + if (reg =3D=3D QAIF_WRDMA_QXM0_SHRAM_LEN(i)) + return true; + } + for (i =3D 0; i < v->num_codec_wrdma; i++) { + if (reg =3D=3D QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i)) + return true; + } + + /* EE IRQ EN, CLR and STATUS */ + for (i =3D 0; i < DMA_TYPE_MAX; i++) { + if (reg =3D=3D QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i)) + return true; + } + + /* AUD_INTF control and configuration */ + for (i =3D 0; i < v->num_intf; i++) { + if (reg =3D=3D QAIF_AUD_INTF_CTL_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_SYNC_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_FRAME_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_LANE_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_MI2S_CFG_REG(i)) + return true; + if (reg =3D=3D QAIF_AUD_INTF_CFG_REG(i)) + return true; + } + + /* RDDMA control, configuration and current address */ + for (i =3D 0; i < v->num_rddma; i++) { + if (reg =3D=3D QAIF_RDDMA_CTL_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_CFG_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_RDDMA_PERIOD_LEN_REG(v, i)) + return true; + } + + /* CODEC RDDMA control, configuration and current address */ + for (i =3D 0; i < v->num_codec_rddma; i++) { + if (reg =3D=3D QAIF_CODEC_RDDMA_CTL_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_CFG_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_RDDMA_INTF_CFG_REG(v, i)) + return true; + } + + /* WRDMA control, configuration and current address */ + for (i =3D 0; i < v->num_wrdma; i++) { + if (reg =3D=3D QAIF_WRDMA_CTL_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_CFG_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_WRDMA_PERIOD_LEN_REG(v, i)) + return true; + } + + /* CODEC WRDMA control, configuration and current address */ + for (i =3D 0; i < v->num_codec_wrdma; i++) { + if (reg =3D=3D QAIF_CODEC_WRDMA_CTL_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_CFG_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, i)) + return true; + if (reg =3D=3D QAIF_CODEC_WRDMA_INTF_CFG_REG(v, i)) + return true; + } + + return false; +} + +static bool audio_qaif_regmap_volatile(struct device *dev, unsigned int re= g) +{ + struct qaif_drv_data *drvdata =3D dev_get_drvdata(dev); + const struct qaif_variant *v =3D drvdata->variant; + int i; + + /* Summary IRQ status - hardware updated on any interrupt */ + if (reg =3D=3D QAIF_SUMMARY_IRQSTAT_REG(v)) + return true; + + /* EE IRQ status - hardware updated on interrupt */ + for (i =3D 0; i < DMA_TYPE_MAX; i++) { + if (reg =3D=3D QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i)) + return true; + if (reg =3D=3D QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i)) + return true; + } + + /* DMA current address - hardware updated during streaming */ + for (i =3D 0; i < v->num_rddma; i++) { + if (reg =3D=3D QAIF_RDDMA_CURR_ADDR_REG(v, i)) + return true; + } + for (i =3D 0; i < v->num_wrdma; i++) { + if (reg =3D=3D QAIF_WRDMA_CURR_ADDR_REG(v, i)) + return true; + } + for (i =3D 0; i < v->num_codec_rddma; i++) { + if (reg =3D=3D QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, i)) + return true; + } + for (i =3D 0; i < v->num_codec_wrdma; i++) { + if (reg =3D=3D QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, i)) + return true; + } + + return false; +} + +static struct regmap_config audio_qaif_regmap_config =3D { + .name =3D "audio_qaif_cpu", + .reg_bits =3D 32, + .reg_stride =3D 4, + .val_bits =3D 32, + .writeable_reg =3D audio_qaif_regmap_writeable, + .readable_reg =3D audio_qaif_regmap_readable, + .volatile_reg =3D audio_qaif_regmap_volatile, + .cache_type =3D REGCACHE_FLAT, +}; + +static int of_qaif_parse_aif_intf_cfg(struct device *dev, + struct qaif_drv_data *data) +{ + const struct qaif_variant *v =3D data->variant; + struct device_node *np =3D dev->of_node; + struct device_node *intf_np; + struct qaif_aif_config *cfg; + const __be32 *lane_cfg_prop; + int ret, j; + int lane_cfg_len; + u32 dai_id, intf_idx; + int num_interfaces =3D 0; + + if (!v) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + + /* + * Iterate over all child nodes of qaif_cpu and process only those + * with a recognised AIF interface compatible. The compatible string + * identifies the serial protocol the interface is wired for on the + * board: qcom,qaif-pcm-dai, qcom,qaif-tdm-dai or qcom,qaif-mi2s-dai. + * Other child nodes are silently skipped. + */ + for_each_child_of_node(np, intf_np) { + enum qaif_aif_mode mode; + + if (of_device_is_compatible(intf_np, "qcom,qaif-pcm-dai")) + mode =3D QAIF_AIF_MODE_PCM; + else if (of_device_is_compatible(intf_np, "qcom,qaif-tdm-dai")) + mode =3D QAIF_AIF_MODE_TDM; + else if (of_device_is_compatible(intf_np, "qcom,qaif-mi2s-dai")) + mode =3D QAIF_AIF_MODE_MI2S; + else + continue; + + if (num_interfaces >=3D QAIF_MAX_AIF_CFG_CNT) { + dev_warn(dev, "Too many AIF interfaces, limiting to %d\n", + QAIF_MAX_AIF_CFG_CNT); + of_node_put(intf_np); + break; + } + + + ret =3D of_property_read_u32(intf_np, "reg", &dai_id); + if (ret) { + dev_err(dev, "Missing reg for interface %d: %s\n", num_interfaces, intf= _np->name); + continue; + } + + if (v->get_dma_idx) { + intf_idx =3D v->get_dma_idx(dai_id); + if (intf_idx < 0) { + dev_err(dev, "Invalid DAI ID %d for interface '%s' (node %d)\n", + dai_id, intf_np->name, num_interfaces); + continue; + } + if (intf_idx >=3D ARRAY_SIZE(data->aif_intf_cfg)) { + dev_err(dev, "DAI ID %d maps to out-of-range intf_idx %d\n", + dai_id, intf_idx); + continue; + } + } else { + dev_err(dev, "can not get intf idx for : %d: %s\n", num_interfaces, int= f_np->name); + of_node_put(intf_np); + return -EINVAL; + } + cfg =3D &data->aif_intf_cfg[intf_idx]; + cfg->mode =3D mode; + + /* Parse sync configuration =E2=80=94 mode-specific */ + if (mode =3D=3D QAIF_AIF_MODE_MI2S) { + /* MI2S: sync mode is fixed (long sync =3D 1, WS-based) */ + cfg->sync_mode =3D 1; + } else { + /* PCM/TDM: sync mode comes from DT (0=3Dshort, 1=3Dlong) */ + ret =3D of_property_read_u32(intf_np, "qcom,qaif-aif-sync-mode", + &cfg->sync_mode); + if (ret) { + dev_err(dev, "Missing sync-mode for interface %d\n", + num_interfaces); + of_node_put(intf_np); + return -EINVAL; + } + } + + ret =3D of_property_read_u32(intf_np, "qcom,qaif-aif-sync-src", &cfg->sy= nc_src); + if (ret) { + dev_warn(dev, "Missing sync-src for interface %d\n", num_interfaces); + cfg->sync_src =3D 0; + } + + cfg->invert_sync =3D of_property_read_bool(intf_np, "qcom,qaif-aif-inver= t-sync"); + + ret =3D of_property_read_u32(intf_np, "qcom,qaif-aif-sync-delay", &cfg->= sync_delay); + if (ret) { + dev_warn(dev, "Missing sync-delay for interface %d\n", num_interfaces); + cfg->sync_delay =3D 0; + } + + /* Parse slot and sample width configuration */ + ret =3D of_property_read_u32(intf_np, "qcom,qaif-aif-slot-width-rx", &cf= g->slot_width_rx); + if (ret) { + dev_warn(dev, "Missing slot-width-rx for interface %d\n", num_interface= s); + cfg->slot_width_rx =3D 0; + } + + ret =3D of_property_read_u32(intf_np, "qcom,qaif-aif-slot-width-tx", &cf= g->slot_width_tx); + if (ret) { + dev_warn(dev, "Missing slot-width-tx for interface %d\n", num_interface= s); + cfg->slot_width_tx =3D 0; + } + + /* Parse slot enable masks =E2=80=94 mode-specific */ + if (mode =3D=3D QAIF_AIF_MODE_MI2S) { + /* MI2S: always 2 active slots (left + right) */ + cfg->slot_en_rx_mask =3D 0x3; + cfg->slot_en_tx_mask =3D 0x3; + } else { + /* PCM/TDM: active slot mask comes from DT */ + ret =3D of_property_read_u32(intf_np, "qcom,qaif-aif-slot-en-rx-mask", + &cfg->slot_en_rx_mask); + if (ret) { + dev_warn(dev, "Missing slot-en-rx-mask for interface %d\n", + num_interfaces); + cfg->slot_en_rx_mask =3D 0; + } + ret =3D of_property_read_u32(intf_np, "qcom,qaif-aif-slot-en-tx-mask", + &cfg->slot_en_tx_mask); + if (ret) { + dev_warn(dev, "Missing slot-en-tx-mask for interface %d\n", + num_interfaces); + cfg->slot_en_tx_mask =3D 0; + } + } + + /* Parse control configuration */ + cfg->loopback_en =3D of_property_read_bool(intf_np, "qcom,qaif-aif-loopb= ack"); + + cfg->ctrl_data_oe =3D of_property_read_bool(intf_np, "qcom,qaif-aif-ctrl= -data-oe"); + + /* Parse lane configuration */ + lane_cfg_prop =3D of_get_property(intf_np, "qcom,qaif-aif-lane-config", = &lane_cfg_len); + if (lane_cfg_prop) { + /* Each lane config has 2 u32 values: enable and direction */ + cfg->num_lanes =3D lane_cfg_len / (2 * sizeof(u32)); + if (cfg->num_lanes > QAIF_MAX_LANES) { + dev_warn(dev, "Too many lanes (%d), limiting to %d\n", + cfg->num_lanes, QAIF_MAX_LANES); + cfg->num_lanes =3D QAIF_MAX_LANES; + } + + for (j =3D 0; j < cfg->num_lanes; j++) { + cfg->lane_cfg[j].enable =3D be32_to_cpup(lane_cfg_prop + (j * 2)); + if (cfg->lane_cfg[j].enable) + cfg->lane_en_mask |=3D BIT(j); + + cfg->lane_cfg[j].direction =3D be32_to_cpup(lane_cfg_prop + (j * 2 + 1= )); + if (cfg->lane_cfg[j].direction) + cfg->lane_dir_mask |=3D BIT(j); + } + + } else { + dev_warn(dev, "Missing lane-config for interface %d\n", num_interfaces); + cfg->num_lanes =3D 0; + } + + /* Mono/stereo mode is written directly from params_channels() in hw_par= ams */ + + /* Parse frame configuration */ + cfg->full_cycle_en =3D of_property_read_bool(intf_np, "qcom,qaif-aif-ful= l-cycle-en"); + + ret =3D of_property_read_u32(intf_np, "qcom,qaif-aif-bits-per-lane", &cf= g->bits_per_lane); + if (ret) { + dev_warn(dev, "Missing bits-per-lane for interface %d\n", num_interface= s); + cfg->bits_per_lane =3D 0; + } + + num_interfaces++; + } + + if (num_interfaces =3D=3D 0) { + dev_err(dev, "No AIF child nodes with qcom,qaif-{pcm,tdm,mi2s}-dai compa= tible found\n"); + return -EINVAL; + } + + return 0; +} + +static int of_qaif_cdc_dma_clks_parse(struct device *dev, + struct qaif_drv_data *data) +{ + data->aud_dma_clk =3D devm_clk_get(dev, "aud_dma_clk"); + if (IS_ERR(data->aud_dma_clk)) + return PTR_ERR(data->aud_dma_clk); + + data->aud_dma_mem_clk =3D devm_clk_get(dev, "aud_dma_mem_clk"); + if (IS_ERR(data->aud_dma_mem_clk)) + return PTR_ERR(data->aud_dma_mem_clk); + + return 0; +} + +int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata; + struct resource *res; + const struct qaif_variant *variant; + struct device *dev =3D &pdev->dev; + const struct of_device_id *match; + int ret, i, dai_id, idx; + bool variant_init_done =3D false; + + dev_dbg(dev, "%s\n", __func__); + drvdata =3D devm_kzalloc(dev, sizeof(struct qaif_drv_data), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + platform_set_drvdata(pdev, drvdata); + + match =3D of_match_device(dev->driver->of_match_table, dev); + if (!match || !match->data) + return -EINVAL; + + drvdata->variant =3D (const struct qaif_variant *)match->data; + variant =3D drvdata->variant; + if (!variant) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + + ret =3D of_qaif_parse_aif_intf_cfg(dev, drvdata); + if (ret) { + dev_err(dev, "Failed to parse aif interfaces: %d\n", ret); + return -EINVAL; + } + + drvdata->audio_qaif =3D + devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(drvdata->audio_qaif)) + return PTR_ERR(drvdata->audio_qaif); + + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + audio_qaif_regmap_config.max_register =3D resource_size(res); + + drvdata->audio_qaif_map =3D devm_regmap_init_mmio(dev, drvdata->audio_qai= f, + &audio_qaif_regmap_config); + if (IS_ERR(drvdata->audio_qaif_map)) + return PTR_ERR(drvdata->audio_qaif_map); + + ret =3D of_qaif_cdc_dma_clks_parse(dev, drvdata); + if (ret) { + dev_err(dev, "failed to get cdc dma clocks %d\n", ret); + return ret; + } + + if (variant->init) { + ret =3D variant->init(pdev); + if (ret) { + dev_err(dev, "error initializing variant: %d\n", ret); + return ret; + } + variant_init_done =3D true; + } + + for (i =3D 0; i < variant->num_dai; i++) { + dai_id =3D variant->dai_driver[i].id; + if (is_cif_dma_port(dai_id)) + continue; + idx =3D variant->get_dma_idx(dai_id); + if (idx < 0) + continue; + + drvdata->mi2s_bit_clk[idx] =3D devm_clk_get(dev, + variant->dai_bit_clk_names[idx]); + if (IS_ERR(drvdata->mi2s_bit_clk[idx])) { + dev_err(dev, + "error getting %s: %ld\n", + variant->dai_bit_clk_names[idx], + PTR_ERR(drvdata->mi2s_bit_clk[idx])); + ret =3D PTR_ERR(drvdata->mi2s_bit_clk[idx]); + goto err; + } + } + + ret =3D qaif_aif_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init cif bitfield: %d\n", ret); + goto err; + } + + ret =3D qaif_aif_cfg_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init aif_intfctl field: %d\n", ret); + goto err; + } + + ret =3D qaif_cif_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init cif bitfield: %d\n", ret); + goto err; + } + + ret =3D devm_snd_soc_register_component(dev, &qaif_cpu_comp_driver, + variant->dai_driver, + variant->num_dai); + if (ret) { + dev_err(dev, "error registering cpu driver: %d\n", ret); + goto err; + } + + ret =3D asoc_qcom_qaif_platform_register(pdev); + if (ret) { + dev_err(dev, "error registering platform driver: %d\n", ret); + goto err; + } + dev_dbg(&pdev->dev, "%s: QAIF CPU-Platform Driver Registered Successfully= \n", __func__); +err: + if (ret && variant_init_done && variant->exit) + variant->exit(pdev); + return ret; +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_probe); + +void asoc_qcom_qaif_cpu_platform_remove(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata =3D platform_get_drvdata(pdev); + + if (drvdata->variant->exit) + drvdata->variant->exit(pdev); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_remove); + +void asoc_qcom_qaif_cpu_platform_shutdown(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata =3D platform_get_drvdata(pdev); + + if (drvdata->variant->exit) + drvdata->variant->exit(pdev); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_shutdown); + +MODULE_DESCRIPTION("Qualcomm Audio Interface (QAIF) CPU DAI driver"); +MODULE_AUTHOR("Harendra Gautam "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c new file mode 100644 index 000000000000..14e3379ca560 --- /dev/null +++ b/sound/soc/qcom/qaif-platform.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-platform.c -- ALSA SoC PCM platform driver for the Qualcomm Audio = Interface (QAIF) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qaif-reg.h" +#include "qaif.h" + +#define DRV_NAME "qaif-platform" + +/* 20 ms period at 48 kHz S16 stereo =3D 3840 bytes */ +#define QAIF_PLATFORM_BUFFER_MIN_SIZE (960 * 2 * 2) +#define QAIF_PLATFORM_PERIOD_BYTES_MIN (960 * 2 * 2) +#define QAIF_PLATFORM_BUFFER_SIZE (4 * QAIF_PLATFORM_BUFFER_MIN_SIZE) +#define QAIF_PLATFORM_PERIODS_MIN 2 +#define QAIF_PLATFORM_PERIODS_MAX 4 + + +static const struct snd_pcm_hardware qaif_platform_aif_hardware =3D { + .info =3D SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats =3D SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates =3D SNDRV_PCM_RATE_8000_192000, + .rate_min =3D 8000, + .rate_max =3D 192000, + .channels_min =3D 1, + .channels_max =3D 8, + .buffer_bytes_max =3D QAIF_PLATFORM_BUFFER_SIZE, + .period_bytes_min =3D QAIF_PLATFORM_PERIOD_BYTES_MIN, + .period_bytes_max =3D QAIF_PLATFORM_BUFFER_SIZE / QAIF_PLATFORM_PERIODS_M= IN, + .periods_min =3D QAIF_PLATFORM_PERIODS_MIN, + .periods_max =3D QAIF_PLATFORM_PERIODS_MAX, + .fifo_size =3D 0, +}; + +static const struct snd_pcm_hardware qaif_platform_cif_hardware =3D { + .info =3D SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats =3D SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates =3D SNDRV_PCM_RATE_8000_192000, + .rate_min =3D 8000, + .rate_max =3D 192000, + .channels_min =3D 1, + .channels_max =3D 8, + .buffer_bytes_max =3D QAIF_PLATFORM_BUFFER_SIZE, + .period_bytes_min =3D QAIF_PLATFORM_PERIOD_BYTES_MIN, + .period_bytes_max =3D QAIF_PLATFORM_BUFFER_SIZE / QAIF_PLATFORM_PERIODS_M= IN, + .periods_min =3D QAIF_PLATFORM_PERIODS_MIN, + .periods_max =3D QAIF_PLATFORM_PERIODS_MAX, + .fifo_size =3D 0, +}; + +static struct qaif_dma_mem_info *qaif_mem_alloc_attach( + struct snd_soc_component *component, size_t alloc_size) +{ + struct device *dev =3D component->dev; + struct qaif_dma_mem_info *dma_mem_info; + + dma_mem_info =3D kzalloc(sizeof(*dma_mem_info), GFP_KERNEL); + if (!dma_mem_info) + return NULL; + + dma_mem_info->alloc_size =3D alloc_size; + + dma_mem_info->vaddr =3D dma_alloc_coherent(dev, alloc_size, + &dma_mem_info->dma_addr, + GFP_KERNEL); + if (!dma_mem_info->vaddr) { + dev_err(dev, "dma_alloc_coherent failed for %zu bytes\n", alloc_size); + kfree(dma_mem_info); + return NULL; + } + + dev_dbg(dev, "%s: dma_addr=3D%pad vaddr=3D%p\n", __func__, + &dma_mem_info->dma_addr, dma_mem_info->vaddr); + return dma_mem_info; +} + +static void qaif_mem_dealloc_detach(struct device *dev, + struct qaif_dma_mem_info *dma_info) +{ + if (!dma_info) + return; + + if (dma_info->vaddr) + dma_free_coherent(dev, dma_info->alloc_size, + dma_info->vaddr, dma_info->dma_addr); + + kfree(dma_info); +} + +static struct qaif_dmactl *qaif_get_dmactl_handle(const struct snd_pcm_sub= stream *substream, + struct snd_soc_component *component) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + struct qaif_dmactl *dmactl =3D NULL; + + switch (cpu_dai->driver->id) { + case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12: + if (substream->stream =3D=3D SNDRV_PCM_STREAM_PLAYBACK) + dmactl =3D drvdata->aif_rd_dmactl; + else + dmactl =3D drvdata->aif_wr_dmactl; + break; + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + dmactl =3D drvdata->cif_rd_dmactl; + break; + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + dmactl =3D drvdata->cif_wr_dmactl; + break; + } + + return dmactl; +} + + +static int qaif_map_ee_resource(struct qaif_drv_data *drvdata) +{ + const struct qaif_variant *v =3D drvdata->variant; + struct regmap *map =3D drvdata->audio_qaif_map; + int ret =3D 0; + u32 mask; + + mask =3D GENMASK(v->num_rddma - 1, 0); + ret |=3D regmap_write(map, QAIF_EE_RDDMA_MAP_REG(v), mask); + + mask =3D GENMASK(v->num_wrdma - 1, 0); + ret |=3D regmap_write(map, QAIF_EE_WRDMA_MAP_REG(v), mask); + + if (v->num_intf > 0) { + mask =3D GENMASK(v->num_intf - 1, 0); + ret |=3D regmap_write(map, QAIF_EE_INTF_MAP_REG(v), mask); + } + + mask =3D GENMASK(v->num_codec_rddma - 1, 0); + ret |=3D regmap_write(map, QAIF_EE_CODEC_RDDMA_MAP_REG(v), mask); + + mask =3D GENMASK(v->num_codec_wrdma - 1, 0); + ret |=3D regmap_write(map, QAIF_EE_CODEC_WRDMA_MAP_REG(v), mask); + + if (ret) + return ret; + return 0; +} + +static int qaif_map_dma_path(struct qaif_drv_data *drvdata) +{ + struct regmap *map =3D drvdata->audio_qaif_map; + const struct qaif_variant *v =3D drvdata->variant; + int ret =3D 0; + int qxm_sel =3D v->qxm_type; + + if (qxm_sel !=3D QXM0) { + dev_err(regmap_get_device(map), + "%s: only QXM0 is supported, qxm_type=3D%d\n", + __func__, qxm_sel); + return -EINVAL; + } + + ret |=3D regmap_write(map, QAIF_RDDMA_MAP_QXM, qxm_sel); + ret |=3D regmap_write(map, QAIF_WRDMA_MAP_QXM, qxm_sel); + ret |=3D regmap_write(map, QAIF_CODEC_RDDMA_MAP_QXM, qxm_sel); + ret |=3D regmap_write(map, QAIF_CODEC_WRDMA_MAP_QXM, qxm_sel); + + if (ret) + return ret; + + return 0; +} + +static int qaif_config_shram(struct qaif_drv_data *drvdata) +{ + const struct qaif_variant *v =3D drvdata->variant; + u32 start_addr, shram_len; + int ret =3D 0, i =3D 0; + struct regmap *map =3D drvdata->audio_qaif_map; + + if (v->qxm_type !=3D QXM0) { + dev_err(regmap_get_device(map), + "%s: only QXM0 is supported, qxm_type=3D%d\n", + __func__, v->qxm_type); + return -EINVAL; + } + start_addr =3D v->rddma_shram_start_addr[QAIF_AIF_DMA]; + shram_len =3D v->rddma_shram_len; + for (i =3D 0; i < v->num_rddma; i++) { + ret =3D regmap_write(map, QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i), start_addr += (shram_len * i)); + if (ret) + return ret; + ret =3D regmap_write(map, QAIF_RDDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + start_addr =3D v->wrdma_shram_start_addr[QAIF_AIF_DMA]; + shram_len =3D v->wrdma_shram_len; + for (i =3D 0; i < v->num_wrdma; i++) { + ret =3D regmap_write(map, QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i), start_addr += (shram_len * i)); + if (ret) + return ret; + ret =3D regmap_write(map, QAIF_WRDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + start_addr =3D v->rddma_shram_start_addr[QAIF_CIF_DMA]; + shram_len =3D v->rddma_shram_len; + for (i =3D 0; i < v->num_codec_rddma; i++) { + ret =3D regmap_write(map, QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i), start_= addr + (shram_len * i)); + if (ret) + return ret; + ret =3D regmap_write(map, QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + start_addr =3D v->wrdma_shram_start_addr[QAIF_CIF_DMA]; + shram_len =3D v->wrdma_shram_len; + for (i =3D 0; i < v->num_codec_wrdma; i++) { + ret =3D regmap_write(map, QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i), start_= addr + (shram_len * i)); + if (ret) + return ret; + ret =3D regmap_write(map, QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i), shram_len); + + if (ret) + return ret; + } + return 0; +} + +static int qaif_init(struct snd_soc_component *component) +{ + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + int ret =3D 0; + + if (drvdata->qaif_init_ref_cnt) { + dev_dbg(component->dev, "%s: QAIF init is done already: ref cnt: %d\n", + __func__, drvdata->qaif_init_ref_cnt); + return 0; + } + + ret =3D qaif_config_shram(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to config shram: %d\n", ret); + return ret; + } + + ret =3D qaif_map_ee_resource(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to map EE resources: %d\n", ret); + return ret; + } + + ret =3D qaif_map_dma_path(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to map DMA path: %d\n", ret); + return ret; + } + dev_dbg(component->dev, "%s: QAIF init is done ref cnt: %d\n", + __func__, drvdata->qaif_init_ref_cnt); + return 0; +} --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 6952E4CA266; Fri, 5 Jun 2026 10:38:10 +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=1780655892; cv=none; b=cjlQm52GeV6/3w5MJsJ/Coivkceob16dnD4coYKfXvy1M8Or0F/RxcaCPMZjchEwLaViPL1zFd5uLrWbcVoNBM3iYZkBWP+jpEhusUfkvuW4fa3ZANKBFkGJCBg2N8AALQFiYwu9IcR2YwBmcZc2syZV2IdIQrXnEeReWprr1J0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655892; c=relaxed/simple; bh=rKthpZe6YSSa1k1J4VjiTD5l0MwlvGmzAXgyGXAg0FU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=so3PPgYOaoM0O1/lbemdQVd/gZ8fEXb8FNhPEKHF64TG0NruxqAf45wcgM4q/CJ4P1ERAUhnKlPh38wW/J+CA44fyFvo2UxSTHY9g76ywTRe2NKFK5+s3b/f8lhKxyUJ59mS/SRO5qCTnklyC62xDNNwELbTcxH96xa6pFalGB8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=VpmZzJcu; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="VpmZzJcu" Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6559mEvp3016263; Fri, 5 Jun 2026 10:38:07 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=MPakLEaSjQJ LUoqs7MQ/imImcPC5PpstPB42jmtI2t0=; b=VpmZzJcuYX71iqXrjHdGa/fPsP4 FM6bdX6Rij46Q8ep2YtASqzKTv5SlaBZkN1P3WI/pnxd9o78xQkaSSWw0ND+IMoq VhNI9zt4tOKULBg+QCLGqQtO6qKf5npHS/CPz9NyaHrW3/1rHzw61AkqFyufYz8t fwubZIPOKSmPts0XQkvMUCEb4F6fRS3GjgnzT1h5k98LsZvM0iSoV5H5wgNHPhLk ckRg2fDxF3p+4njI4IkBYSFhgNcH0jagAuULZheFwDB11nENILCyGMzV7EHKFvxL p9Uq9EEgPVGJF8MzcC0e+HeQQUE2SMJ/2RwVBEtvmdMMuM0Z56+nY5mttxw== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekv56g6je-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:38:06 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6w011714; Fri, 5 Jun 2026 10:38:03 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 11/13] ASoC: qcom: Add QAIF PCM operations Date: Fri, 5 Jun 2026 16:07:37 +0530 Message-Id: <20260605103739.3557573-12-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfXwCZFD80VNmTx EgmDI9zT6FF55nP1qlD2w+Ql6QmFaTIZ9Nu72rvcplICyEW4a55mZfjCXBrunPkCaZyO8WC6wxL RMzJdayKXDiGQYUi1VioRZokaTgxpYYlJrGdIxwIhxzzGRpkGxwsY/i1sWVczHrij+jHTlMeG2Y WcecY/1HJU+7IH3m3WaaZzpC06AZJT1I7Y7droKHDLIq2O69p/D/CRPxtRaDoOHXqEd/evtfKMJ RDJgjqN5UEuaXuaSINEYxv0ZXZP+MZovybX6IUY/XiXsJxtfXCGlFDiyw1bb9eNnFSmNnDcMQ8R 9aUTi2nU58aWrjnuJmk02LfErz/oEmjjzaCIvvNMfm+GIjOzPAyCnUF0RjT9woDwMlFc/eZNGYa bEmvZzEF+p/4FwwntcU1aNg7F4vQmGmwLqZ7E9RLCyPEdggliKjWREOB/2nYJoqce5YgV1n8Eb2 M69y1lbiSjd+7IdWwnw== X-Authority-Analysis: v=2.4 cv=eJsjSnp1 c=1 sm=1 tr=0 ts=6a22a70f cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=_glEPmIy2e8OvE2BGh3C:22 a=EUspDBNiAAAA:8 a=QYQMLAkjsb5kLBzSReQA:9 X-Proofpoint-ORIG-GUID: yFDH87x0H6Kff8Tkssfhk4FR_Nnz_uIq X-Proofpoint-GUID: yFDH87x0H6Kff8Tkssfhk4FR_Nnz_uIq X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 impostorscore=0 bulkscore=0 clxscore=1015 spamscore=0 adultscore=0 suspectscore=0 lowpriorityscore=0 priorityscore=1501 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Add PCM operation callbacks for the QAIF platform driver so AIF and CIF DAIs can manage the DMA stream lifecycle. The callbacks allocate and release stream DMA channels, set the ALSA hardware constraints, manage the stream buffer, program the DMA registers during prepare, enable or disable DMA and interrupts on trigger, report the current DMA position to ALSA, and provide mmap support for userspace audio buffers. This completes the platform-side PCM support needed for QAIF playback and capture streams. Signed-off-by: Harendra Gautam --- sound/soc/qcom/qaif-platform.c | 561 +++++++++++++++++++++++++++++++++ 1 file changed, 534 insertions(+) diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c index 14e3379ca560..03d390705d4d 100644 --- a/sound/soc/qcom/qaif-platform.c +++ b/sound/soc/qcom/qaif-platform.c @@ -274,3 +274,570 @@ static int qaif_init(struct snd_soc_component *compon= ent) __func__, drvdata->qaif_init_ref_cnt); return 0; } + + +static int qaif_platform_pcmops_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime =3D substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct snd_dma_buffer *buf; + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + const struct qaif_variant *v =3D drvdata->variant; + int ret, stream_dma_idx, dir =3D substream->stream; + struct qaif_pcm_data *data; + struct qaif_dmactl *dmactl; + struct qaif_dma_mem_info *dma_mem_info; + struct regmap *map; + unsigned int dai_id =3D cpu_dai->driver->id; + + if (v->alloc_stream_dma_idx) + stream_dma_idx =3D v->alloc_stream_dma_idx(drvdata, dir, dai_id); + else + return -EINVAL; + + if (stream_dma_idx < 0) + return stream_dma_idx; + data =3D kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, stream_dma_idx, dai_id); + return -ENOMEM; + } + + data->stream_dma_idx =3D stream_dma_idx; + + runtime->private_data =3D data; + map =3D drvdata->audio_qaif_map; + dmactl =3D qaif_get_dmactl_handle(substream, component); + if (!dmactl) { + kfree(data); + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, stream_dma_idx, dai_id); + return -EINVAL; + } + buf =3D &substream->dma_buffer; + buf->dev.dev =3D component->dev; + buf->private_data =3D NULL; + buf->dev.type =3D SNDRV_DMA_TYPE_CONTINUOUS; + + dma_mem_info =3D qaif_mem_alloc_attach(component, + qaif_platform_aif_hardware.buffer_bytes_max); + if (!dma_mem_info) { + kfree(data); + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, stream_dma_idx, dai_id); + return -ENOMEM; + } + + ret =3D clk_prepare_enable(drvdata->aud_dma_clk); + if (ret) { + dev_err(soc_runtime->dev, "failed to enable aud_dma_clk: %d\n", ret); + qaif_mem_dealloc_detach(component->dev, dma_mem_info); + kfree(data); + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, stream_dma_idx, dai_id); + return ret; + } + ret =3D clk_prepare_enable(drvdata->aud_dma_mem_clk); + if (ret) { + dev_err(soc_runtime->dev, "failed to enable aud_dma_mem_clk: %d\n", ret); + clk_disable_unprepare(drvdata->aud_dma_clk); + qaif_mem_dealloc_detach(component->dev, dma_mem_info); + kfree(data); + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, stream_dma_idx, dai_id); + return ret; + } + + ret =3D qaif_init(component); + if (ret) { + dev_err(soc_runtime->dev, "qaif_init failed: %d\n", ret); + clk_disable_unprepare(drvdata->aud_dma_mem_clk); + clk_disable_unprepare(drvdata->aud_dma_clk); + qaif_mem_dealloc_detach(component->dev, dma_mem_info); + kfree(data); + return -EINVAL; + } + drvdata->qaif_init_ref_cnt++; + + switch (dai_id) { + case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12: + drvdata->aif_substream[stream_dma_idx] =3D substream; + drvdata->aif_dma_heap[stream_dma_idx] =3D dma_mem_info; + buf->bytes =3D qaif_platform_aif_hardware.buffer_bytes_max; + buf->addr =3D drvdata->aif_dma_heap[stream_dma_idx]->dma_addr; + buf->area =3D (unsigned char *)drvdata->aif_dma_heap[stream_dma_idx]->va= ddr; + + snd_soc_set_runtime_hwparams(substream, &qaif_platform_aif_hardware); + runtime->dma_bytes =3D qaif_platform_aif_hardware.buffer_bytes_max; + break; + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + drvdata->cif_substream[stream_dma_idx] =3D substream; + drvdata->cif_dma_heap[stream_dma_idx] =3D dma_mem_info; + buf->bytes =3D qaif_platform_cif_hardware.buffer_bytes_max; + buf->addr =3D drvdata->cif_dma_heap[stream_dma_idx]->dma_addr; + buf->area =3D (unsigned char *)drvdata->cif_dma_heap[stream_dma_idx]->va= ddr; + + snd_soc_set_runtime_hwparams(substream, &qaif_platform_cif_hardware); + runtime->dma_bytes =3D qaif_platform_cif_hardware.buffer_bytes_max; + break; + default: + break; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + ret =3D snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS= ); + if (ret < 0) { + dev_err(soc_runtime->dev, "setting constraints failed: %d\n", ret); + if (is_cif_dma_port(dai_id)) { + drvdata->cif_substream[stream_dma_idx] =3D NULL; + drvdata->cif_dma_heap[stream_dma_idx] =3D NULL; + } else { + drvdata->aif_substream[stream_dma_idx] =3D NULL; + drvdata->aif_dma_heap[stream_dma_idx] =3D NULL; + } + drvdata->qaif_init_ref_cnt--; + clk_disable_unprepare(drvdata->aud_dma_mem_clk); + clk_disable_unprepare(drvdata->aud_dma_clk); + qaif_mem_dealloc_detach(component->dev, dma_mem_info); + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, stream_dma_idx, dai_id); + kfree(data); + return ret; + } + + return 0; +} + +static int qaif_platform_pcmops_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime =3D substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_pcm_data *data; + unsigned int dai_id =3D cpu_dai->driver->id; + + data =3D runtime->private_data; + + switch (dai_id) { + case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12: + drvdata->aif_substream[data->stream_dma_idx] =3D NULL; + qaif_mem_dealloc_detach(component->dev, + drvdata->aif_dma_heap[data->stream_dma_idx]); + drvdata->aif_dma_heap[data->stream_dma_idx] =3D NULL; + break; + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + drvdata->cif_substream[data->stream_dma_idx] =3D NULL; + qaif_mem_dealloc_detach(component->dev, + drvdata->cif_dma_heap[data->stream_dma_idx]); + drvdata->cif_dma_heap[data->stream_dma_idx] =3D NULL; + break; + default: + break; + } + + if (drvdata->qaif_init_ref_cnt > 0) + drvdata->qaif_init_ref_cnt--; + else + dev_dbg(component->dev, "%s: QAIF init ref cnt: %d, skipping decrement\n= ", + __func__, drvdata->qaif_init_ref_cnt); + + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, data->stream_dma_idx, dai_id); + clk_disable_unprepare(drvdata->aud_dma_clk); + clk_disable_unprepare(drvdata->aud_dma_mem_clk); + kfree(data); + return 0; +} + +static int qaif_platform_pcmops_hw_params(struct snd_soc_component *compon= ent, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_dmactl *dmactl; + unsigned int dai_id =3D cpu_dai->driver->id; + int idx; + int ret; + + dmactl =3D qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx =3D v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret =3D regmap_fields_write(dmactl->burst4, idx, QAIF_DMACTL_BURSTEN); + if (ret) { + dev_err(soc_runtime->dev, "error updating burst4 field: %d\n", ret); + return ret; + } + + ret =3D regmap_fields_write(dmactl->shram_wm, idx, QAIF_DMACTL_WM_5); + if (ret) { + dev_err(soc_runtime->dev, "error updating shram_wm field: %d\n", ret); + return ret; + } + + return 0; +} + +static int qaif_platform_pcmops_hw_free(struct snd_soc_component *componen= t, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + const struct qaif_variant *v =3D drvdata->variant; + unsigned int reg; + int ret, idx; + unsigned int dai_id =3D cpu_dai->driver->id; + struct regmap *map =3D drvdata->audio_qaif_map; + struct qaif_dmactl *dmactl; + + dmactl =3D qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx =3D v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret =3D regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_OFF); + if (ret) + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); + + reg =3D QAIF_DMACFG_REG(v, idx, substream->stream, dai_id); + ret =3D regmap_write(map, reg, 0); + if (ret) + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); + + return ret; +} + +static int qaif_platform_pcmops_prepare(struct snd_soc_component *componen= t, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime =3D substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_dmactl *dmactl; + struct regmap *map; + int bitwidth =3D QAIF_DMA_DEFAULT_BIT_WIDTH; + unsigned int channels =3D runtime->channels; + unsigned int rate =3D runtime->rate; + int ret, idx, dir =3D substream->stream; + unsigned int dai_id =3D cpu_dai->driver->id; + + dmactl =3D qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx =3D v->get_dma_idx(dai_id); + map =3D drvdata->audio_qaif_map; + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + clk_set_rate(drvdata->aud_dma_clk, rate * bitwidth * channels * QAIF_DMA_= CLK_RATE_MULTIPLIER); + clk_set_rate(drvdata->aud_dma_mem_clk, rate * bitwidth * channels * QAIF_= DMA_CLK_RATE_MULTIPLIER); + + ret =3D regmap_write(map, QAIF_SID_MAP_REG(dir, dai_id), + drvdata->smmu_csid_bits); + if (ret) { + dev_err(soc_runtime->dev, "error writing to SID MAP reg: %d\n", + ret); + return ret; + } + + ret =3D regmap_write(map, QAIF_DMABASE_REG(v, idx, dir, dai_id), + runtime->dma_addr); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n", + ret); + return ret; + } + + ret =3D regmap_write(map, QAIF_DMABUFF_REG(v, idx, dir, dai_id), + (snd_pcm_lib_buffer_bytes(substream) >> QAIF_DMA_BYTES_TO_WORDS_SHIFT) = - 1); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n", + ret); + return ret; + } + + ret =3D regmap_write(map, QAIF_DMAPER_LEN_REG(v, idx, dir, dai_id), + (snd_pcm_lib_period_bytes(substream) >> QAIF_DMA_BYTES_TO_WORDS_SHIFT) = - 1); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n", + ret); + return ret; + } + + return 0; +} + +static int qaif_platform_irq_clear(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type irq_type, int idx) +{ + int ret =3D 0; + const struct qaif_variant *v =3D drvdata->variant; + struct regmap *map =3D drvdata->audio_qaif_map; + unsigned int val_irqclr =3D BIT(idx); + + if (dir =3D=3D SNDRV_PCM_STREAM_PLAYBACK) { + ret |=3D regmap_write(map, QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, irq_type)= , val_irqclr); + ret |=3D regmap_write(map, QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, irq_ty= pe), val_irqclr); + ret |=3D regmap_write(map, QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, irq_type= ), val_irqclr); + } else { + ret |=3D regmap_write(map, QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, irq_type)= , val_irqclr); + ret |=3D regmap_write(map, QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, irq_typ= e), val_irqclr); + ret |=3D regmap_write(map, QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, irq_type= ), val_irqclr); + } + return ret; +} + +static int qaif_platform_irq_enable(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type irq_type, int idx) +{ + int ret =3D 0; + const struct qaif_variant *v =3D drvdata->variant; + struct regmap *map =3D drvdata->audio_qaif_map; + unsigned int val_irqen =3D BIT(idx); + + if (dir =3D=3D SNDRV_PCM_STREAM_PLAYBACK) { + ret |=3D regmap_write_bits(map, QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, irq_t= ype), val_irqen, val_irqen); + ret |=3D regmap_write_bits(map, QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, ir= q_type), val_irqen, val_irqen); + ret |=3D regmap_write_bits(map, QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, irq_= type), val_irqen, val_irqen); + } else { + ret |=3D regmap_write_bits(map, QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, irq_t= ype), val_irqen, val_irqen); + ret |=3D regmap_write_bits(map, QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, irq= _type), val_irqen, val_irqen); + ret |=3D regmap_write_bits(map, QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, irq_= type), val_irqen, val_irqen); + } + return ret; +} + +static int qaif_platform_irq_disable(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type irq_type, int idx) +{ + int ret =3D 0; + const struct qaif_variant *v =3D drvdata->variant; + struct regmap *map =3D drvdata->audio_qaif_map; + unsigned int val_irq_disable =3D BIT(idx); + + if (dir =3D=3D SNDRV_PCM_STREAM_PLAYBACK) { + ret |=3D regmap_write_bits(map, QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, irq_t= ype), val_irq_disable, 0); + ret |=3D regmap_write_bits(map, QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, ir= q_type), val_irq_disable, 0); + ret |=3D regmap_write_bits(map, QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, irq_= type), val_irq_disable, 0); + } else { + ret |=3D regmap_write_bits(map, QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, irq_t= ype), val_irq_disable, 0); + ret |=3D regmap_write_bits(map, QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, irq= _type), val_irq_disable, 0); + ret |=3D regmap_write_bits(map, QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, irq_= type), val_irq_disable, 0); + } + return ret; +} + +static int qaif_platform_pcmops_trigger(struct snd_soc_component *componen= t, + struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + const struct qaif_variant *v =3D drvdata->variant; + struct qaif_dmactl *dmactl; + struct regmap *map; + int ret, idx; + unsigned int dai_id =3D cpu_dai->driver->id; + + dmactl =3D qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx =3D v->get_dma_idx(dai_id); + map =3D drvdata->audio_qaif_map; + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret =3D regmap_fields_write(dmactl->dma_dyncclk, idx, QAIF_DMACTL_DYNCLK= _ON); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma_dyncclk reg field: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_ON); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma enable reg: %d\n", ret); + return ret; + } + switch (dai_id) { + case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12: + ret =3D qaif_platform_irq_clear(drvdata, substream->stream, QAIF_AIF_IR= Q, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to clear irq reg: %d\n", ret); + return ret; + } + ret =3D qaif_platform_irq_enable(drvdata, substream->stream, QAIF_AIF_I= RQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + ret =3D qaif_platform_irq_clear(drvdata, substream->stream, QAIF_CIF_IR= Q, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to clear irq reg: %d\n", ret); + return ret; + } + ret =3D qaif_platform_irq_enable(drvdata, substream->stream, QAIF_CIF_I= RQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + default: + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_i= d); + return -EINVAL; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret =3D regmap_fields_write(dmactl->dma_dyncclk, idx, QAIF_DMACTL_DYNCLK= _OFF); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma_dyncclk reg field: %d\n", ret); + return ret; + } + ret =3D regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_OFF); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma enable reg: %d\n", ret); + return ret; + } + switch (dai_id) { + case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12: + ret =3D qaif_platform_irq_disable(drvdata, substream->stream, QAIF_AIF_= IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + ret =3D qaif_platform_irq_disable(drvdata, substream->stream, QAIF_CIF_= IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + default: + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_i= d); + return -EINVAL; + } + break; + default: + return -EINVAL; + } + return 0; +} + +static snd_pcm_uframes_t qaif_platform_pcmops_pointer( + struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + const struct qaif_variant *v =3D drvdata->variant; + unsigned int base_addr, curr_addr; + int ret, idx, dir =3D substream->stream; + struct regmap *map; + unsigned int dai_id =3D cpu_dai->driver->id; + + map =3D drvdata->audio_qaif_map; + idx =3D v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret =3D regmap_read(map, + QAIF_DMABASE_REG(v, idx, dir, dai_id), &base_addr); + if (ret) { + dev_err(soc_runtime->dev, + "error reading from rdmabase reg: %d\n", ret); + return ret; + } + + ret =3D regmap_read(map, + QAIF_DMACURR_REG(v, idx, dir, dai_id), &curr_addr); + if (ret) { + dev_err(soc_runtime->dev, + "error reading from rdmacurr reg: %d\n", ret); + return ret; + } + + return bytes_to_frames(substream->runtime, curr_addr - base_addr); +} + +static int qaif_platform_cdc_dma_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime =3D substream->runtime; + + return dma_mmap_coherent(substream->pcm->card->dev, vma, + runtime->dma_area, runtime->dma_addr, + runtime->dma_bytes); +} + +static int qaif_platform_pcmops_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_soc_pcm_runtime *soc_runtime =3D snd_soc_substream_to_rtd(subs= tream); + struct snd_soc_dai *cpu_dai =3D snd_soc_rtd_to_cpu(soc_runtime, 0); + unsigned int dai_id =3D cpu_dai->driver->id; + + if (is_cif_dma_port(dai_id)) + return qaif_platform_cdc_dma_mmap(substream, vma); + + return snd_pcm_lib_default_mmap(substream, vma); +} --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 BB2444CA291; Fri, 5 Jun 2026 10:38:12 +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=1780655894; cv=none; b=hh+5qOgXn9mqs7mjYEvrL7PK4FKaMNw0ePEDikROdWcvIohqT/YawVrGoFYZls1OUhSvwoSCZpT27P5LOJDRntPkYPwq2IUtStLPOxQGPpUosFQfxWrQzlsjC0J8vSWagz8aw9dHjzrldU7/CxmCbs5VwXvIoXhE3kgZxFnZtTo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655894; c=relaxed/simple; bh=NCX5b2PWnYcFFo4oMMpi4qpMwuLqcQ8g8wnkXqpsvOY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Zoy51VF8Pb7d4nHUiYAcevcl/nt7Qsp1MetTlXJIXkKxBzmSMZ7sZG7UWtpESnzuF74LlgbsomFuDuAy4kpV1IFJO1ac5J6INaL4Ng9CL5/JpQ/LyVMB3Hohn4W4Yj73GXugsNzVqZi3PvRcmzF0KlA7US5yWnsPg6xWq/DvOwI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=X7St4Fj7; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="X7St4Fj7" Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 655AADio2975373; Fri, 5 Jun 2026 10:38:09 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=VIrp6qfRXim 6BlSHc5lkUiCh14qEpxqKogBP4mUjPUA=; b=X7St4Fj7NkZcUZQG4Z3XrSh7lex Vs3AQN5yuTJjUmuPtoJcsHPCxcUu73BTAcfvxTLajVSf/unJOc08+4JLWQyLLuAt /dsTCPc5P+0xI019PzHouy8w4t2niS+Enk+ChMP/bluAQiRW1sHi9kncvGIrKrjs GzJI0mczvso9XDH1GipVgGsSJDuBOUI/WxjX3SPH89PqWx2IaDPBsgFxzxmLsM+1 6JImJRGKBHlyDYGpwXbwGrxlCsf7Grd9yMViWcx6URR9HOq/ppxVmOYID9a9TeRR M9M/dqhi+vTYFB0WMee7Bk2DigNWylwUjB6XYMq7bhlJEGMT4BJtEQoHs/w== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekpnu9hds-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:38:09 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk6x011714; Fri, 5 Jun 2026 10:38:06 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 12/13] ASoC: qcom: Add QAIF IRQ handling, suspend/resume and platform register Date: Fri, 5 Jun 2026 16:07:38 +0530 Message-Id: <20260605103739.3557573-13-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-GUID: rpjgNc0aegFxDyU0kXcG3ziDHjTQWMlt X-Authority-Analysis: v=2.4 cv=Ksl9H2WN c=1 sm=1 tr=0 ts=6a22a711 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=3WHJM1ZQz_JShphwDgj5:22 a=EUspDBNiAAAA:8 a=TYwhyaZNSizj3SvGGcAA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfXybN5ioQuYvmp A1ymJcvVlmUBzqTP3mc37YNqqu5MI5+wvkbu13mNf+vXTB4lSk4skBis0rHB7Pswk8P3+6Bxj7w FnVt+/VMwRwA3iNAhfX+CaPoB6Jbd2IyeVkU+nU8CI2NcH19d/cXyUcWe2dBVqsbEiaIsp8H0Ig 1/ulfcIfJByv8JbkDH+1JtIcyGCA/Tx/bqi8yZ8M3uD3D+2slLAmO0PLZFzz9B+VlS9fjxAwUdY Ry5x+ne4r9Y0F+BqKGUOPoD7h32kKQ2fhwFC6ox+dW4NGyth5HI9X45s5Ce6M7DpxNUgXSjBVkw EkFPbMlvFpjqgXu3fEIRs5gUqdvdUGTl7FSTzc70xfhADxnOsN4osvyO0OeonyWdCn9vg+MUWXD COjKdinnq6zIQ9T0wvsex5D48DgqJbFaMx2xSyxAtj5Jp/t8kM0yNsx/ESOlCKnqm/WaUUX2D0j KgLhgWnEFNH6eJnsBRA== X-Proofpoint-ORIG-GUID: rpjgNc0aegFxDyU0kXcG3ziDHjTQWMlt X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 phishscore=0 clxscore=1011 priorityscore=1501 adultscore=0 lowpriorityscore=0 spamscore=0 malwarescore=0 bulkscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Complete the QAIF PCM platform support by registering the component, requesting the QAIF interrupt, and handling DMA interrupt events. The QAIF hardware reports DMA events through a summary interrupt register and per-DMA status registers. Add the top-level IRQ handler and AIF/CIF DMA handlers so period interrupts notify ALSA with snd_pcm_period_elapsed(), xrun conditions are reported, and bus errors stop the affected stream. Add suspend and resume callbacks to put the QAIF regmap into cache-only mode while the clocks are disabled, then re-enable the clocks and sync the cached register state on resume. Read the SMMU stream ID from the iommus property during platform registration so the existing resource setup code can program the SID mapping correctly. Also add the component copy callback for transferring PCM data through the runtime DMA buffer. Signed-off-by: Harendra Gautam --- sound/soc/qcom/qaif-platform.c | 309 +++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c index 03d390705d4d..38130ee89930 100644 --- a/sound/soc/qcom/qaif-platform.c +++ b/sound/soc/qcom/qaif-platform.c @@ -808,3 +808,323 @@ static int qaif_platform_pcmops_mmap(struct snd_soc_c= omponent *component, =20 return snd_pcm_lib_default_mmap(substream, vma); } + +static irqreturn_t qaif_process_dma_irq(struct qaif_drv_data *drvdata, + u32 stat_reg_addr, + u32 clr_reg_addr, + enum qaif_irq_type irq_type, + enum dma_type dma_type, + enum qaif_irq irq, + struct snd_pcm_substream **substream) +{ + const struct qaif_variant *v =3D drvdata->variant; + struct snd_pcm_substream *stream =3D NULL; + unsigned int reg =3D 0; + int dma_idx, stream_dma_idx, rv, num_dma =3D 0; + int stream_offset; + irqreturn_t ret =3D IRQ_NONE; + u32 mask =3D 0; + + if (dma_type =3D=3D DMA_TYPE_WRDMA) + stream_offset =3D (irq_type =3D=3D QAIF_AIF_IRQ) ? v->wrdma_start + : v->codec_wrdma_start; + else + stream_offset =3D 0; + + if (dma_type =3D=3D DMA_TYPE_WRDMA) + num_dma =3D (irq_type =3D=3D QAIF_AIF_IRQ) ? v->num_wrdma : v->num_codec= _wrdma; + else + num_dma =3D (irq_type =3D=3D QAIF_AIF_IRQ) ? v->num_rddma : v->num_codec= _rddma; + mask =3D GENMASK(num_dma-1, 0); + rv =3D regmap_read(drvdata->audio_qaif_map, stat_reg_addr, ®); + if (rv) { + dev_err(regmap_get_device(drvdata->audio_qaif_map), + "error reading stat reg 0x%x: %d\n", stat_reg_addr, rv); + return IRQ_NONE; + } + + regmap_write(drvdata->audio_qaif_map, clr_reg_addr, reg & mask); + + for (dma_idx =3D 0; dma_idx < num_dma; dma_idx++) { + stream_dma_idx =3D dma_idx + stream_offset; + if ((reg & BIT(dma_idx)) && substream[stream_dma_idx]) { + stream =3D substream[stream_dma_idx]; + switch (irq) { + case QAIF_IRQ_PERIOD: + snd_pcm_period_elapsed(stream); + ret =3D IRQ_HANDLED; + break; + + case QAIF_IRQ_OVERFLOW: + case QAIF_IRQ_UNDERFLOW: + dev_warn_ratelimited(regmap_get_device(drvdata->audio_qaif_map), + "QAIF DMA xRun\n"); + ret =3D IRQ_HANDLED; + break; + + case QAIF_IRQ_ERROR: + snd_pcm_stop(stream, SNDRV_PCM_STATE_DISCONNECTED); + dev_err(regmap_get_device(drvdata->audio_qaif_map), + "QAIF bus error\n"); + ret =3D IRQ_HANDLED; + break; + } + } + } + return ret; +} + +static irqreturn_t qaif_aif_irq_handler(struct qaif_drv_data *drvdata, u32= summary_irq_status) +{ + const struct qaif_variant *v =3D drvdata->variant; + irqreturn_t ret =3D IRQ_NONE; + struct snd_pcm_substream **substream =3D drvdata->aif_substream; + + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_PERIOD_RDDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_PERIOD, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_PERIOD_WRDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_PERIOD, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_OVERFLOW_WRDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_OVERFLOW, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_UNDERFLOW_RDDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_UNDERFLOW, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_RDDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_ERROR, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_WRDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_ERROR, substream); + } + return ret; +} + +static irqreturn_t qaif_cif_irq_handler(struct qaif_drv_data *drvdata, u32= summary_irq_status) +{ + const struct qaif_variant *v =3D drvdata->variant; + irqreturn_t ret =3D IRQ_NONE; + struct snd_pcm_substream **substream =3D drvdata->cif_substream; + + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_PERIOD_RDDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_PERIOD, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_PERIOD_WRDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_PERIOD, substream); + } + + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_OVERFLOW_WRDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_OVERFLOW, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_UNDERFLOW_RDDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_UNDERFLOW, substream); + } + + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_RDDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_ERROR, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_WRDMA) { + ret |=3D qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_ERROR, substream); + } + + return ret; +} + + +#define QAIF_ALL_CLIENTS_MASK (QAIF_BITMASK_AIF_RDDMA_WRDMA | QAIF_BITMASK= _CIF_RDDMA_WRDMA) + +static const struct qaif_irq_map qaif_irq_clients[] =3D { + { QAIF_CLIENT_ID_AIF_DMA, QAIF_BITMASK_AIF_RDDMA_WRDMA, qaif_aif_irq_hand= ler}, + { QAIF_CLIENT_ID_CIF_DMA, QAIF_BITMASK_CIF_RDDMA_WRDMA, qaif_cif_irq_hand= ler}, +}; + +static irqreturn_t asoc_platform_qaif_irq(int irq, void *data) +{ + struct qaif_drv_data *drvdata =3D data; + const struct qaif_variant *v =3D drvdata->variant; + u32 summary_irq_status; + int rv, client; + irqreturn_t ret =3D IRQ_NONE; + + rv =3D regmap_read(drvdata->audio_qaif_map, + QAIF_SUMMARY_IRQSTAT_REG(v), &summary_irq_status); + if (rv) { + dev_err(regmap_get_device(drvdata->audio_qaif_map), + "error reading from irqstat reg: %d\n", rv); + return IRQ_NONE; + } + if (!(summary_irq_status & QAIF_ALL_CLIENTS_MASK)) + return IRQ_NONE; + for (client =3D 0; client < ARRAY_SIZE(qaif_irq_clients); client++) { + if (summary_irq_status & qaif_irq_clients[client].mask) + ret |=3D qaif_irq_clients[client].client_irq_handler(drvdata, summary_i= rq_status); + } + return ret; +} + +static int qaif_platform_pcmops_suspend(struct snd_soc_component *componen= t) +{ + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + struct regmap *map; + + map =3D drvdata->audio_qaif_map; + + regcache_cache_only(map, true); + regcache_mark_dirty(map); + if (drvdata->qaif_init_ref_cnt > 0) { + clk_disable(drvdata->aud_dma_clk); + clk_disable(drvdata->aud_dma_mem_clk); + } + return 0; +} + +static int qaif_platform_pcmops_resume(struct snd_soc_component *component) +{ + struct qaif_drv_data *drvdata =3D snd_soc_component_get_drvdata(component= ); + struct regmap *map =3D drvdata->audio_qaif_map; + int ret; + + if (drvdata->qaif_init_ref_cnt > 0) { + ret =3D clk_enable(drvdata->aud_dma_clk); + if (ret) + return ret; + ret =3D clk_enable(drvdata->aud_dma_mem_clk); + if (ret) { + clk_disable(drvdata->aud_dma_clk); + return ret; + } + } + regcache_cache_only(map, false); + return regcache_sync(map); +} + +static int qaif_platform_copy(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int channel, + unsigned long pos, struct iov_iter *buf, + unsigned long bytes) +{ + struct snd_pcm_runtime *rt =3D substream->runtime; + size_t copied; + void *dma_buf; + + dma_buf =3D (void *)(rt->dma_area + pos + + channel * (rt->dma_bytes / rt->channels)); + + if (substream->stream =3D=3D SNDRV_PCM_STREAM_PLAYBACK) { + copied =3D copy_from_iter(dma_buf, bytes, buf); + if (copied !=3D bytes) + return -EFAULT; + } else { + copied =3D copy_to_iter(dma_buf, bytes, buf); + if (copied !=3D bytes) + return -EFAULT; + } + + return 0; +} + +static const struct snd_soc_component_driver qaif_component_driver =3D { + .name =3D DRV_NAME, + .open =3D qaif_platform_pcmops_open, + .close =3D qaif_platform_pcmops_close, + .hw_params =3D qaif_platform_pcmops_hw_params, + .hw_free =3D qaif_platform_pcmops_hw_free, + .prepare =3D qaif_platform_pcmops_prepare, + .trigger =3D qaif_platform_pcmops_trigger, + .pointer =3D qaif_platform_pcmops_pointer, + .mmap =3D qaif_platform_pcmops_mmap, + .suspend =3D qaif_platform_pcmops_suspend, + .resume =3D qaif_platform_pcmops_resume, + .copy =3D qaif_platform_copy, +}; +static int qaif_parse_smmu_sid(struct platform_device *pdev, + struct qaif_drv_data *drvdata) +{ + struct device_node *np =3D pdev->dev.of_node; + int ret; + u32 sid; + + ret =3D of_property_read_u32_index(np, "iommus", 1, &sid); + if (ret) { + dev_err(&pdev->dev, "failed to read SMMU SID from iommus property: %d\n"= , ret); + return ret; + } + + drvdata->smmu_csid_bits =3D sid & 0x1; + dev_dbg(&pdev->dev, "sid=3D0x%x csid=3D0x%x\n", sid, drvdata->smmu_csid_b= its); + return 0; +} + +int asoc_qcom_qaif_platform_register(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata =3D platform_get_drvdata(pdev); + int ret =3D 0; + + dev_dbg(&pdev->dev, "%s\n", __func__); + if (!drvdata || !drvdata->variant) { + dev_err(&pdev->dev, "Invalid drvdata or variant\n"); + return -EINVAL; + } + + ret =3D qaif_parse_smmu_sid(pdev, drvdata); + if (ret) + return ret; + + drvdata->audio_qaif_irq =3D platform_get_irq(pdev, 0); + if (drvdata->audio_qaif_irq < 0) + return drvdata->audio_qaif_irq; + + ret =3D devm_request_irq(&pdev->dev, drvdata->audio_qaif_irq, + asoc_platform_qaif_irq, IRQF_TRIGGER_HIGH, + "qaif-irq-audio-core", drvdata); + if (ret) { + dev_err(&pdev->dev, "irq request failed: %d\n", ret); + return ret; + } + drvdata->qaif_init_ref_cnt =3D 0; + dev_dbg(&pdev->dev, "%s: Register QAIF Platform\n", __func__); + return devm_snd_soc_register_component(&pdev->dev, + &qaif_component_driver, NULL, 0); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_platform_register); + +MODULE_DESCRIPTION("Qualcomm Audio Interface (QAIF) PCM platform driver"); +MODULE_AUTHOR("Harendra Gautam "); +MODULE_LICENSE("GPL"); --=20 2.34.1 From nobody Mon Jun 8 06:38:15 2026 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 55CFE4D2ECB; Fri, 5 Jun 2026 10:38:15 +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=1780655897; cv=none; b=Obt94J6a/Zu22dpcj8V6CI/YCKNef/bOp6TUHUBBvBNxCdm9IWCvd8teoNMcDlXcrZAbkTP9yQqXTGWniWOgqdjOB4vpKMlUTAK9wlh8Jj5cl4vsHKzxQrCnVbQPAYVzW4XyFNBKrFw8myI6c6eIaOGXgE8+1s52JaZxLef4hLY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780655897; c=relaxed/simple; bh=H8rGZ3yNybqBJBxxGIBM3YM9b8+tlwzUmmqSqBOgG2c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dDxIDsPWQJtKTrsiZCI2HGNAlvHT1wqlu1K9kprQoaVqMTDi5bxzRu/T/rEz0FKxNmTd7dnuShyw78+ucNQfWBcGeLkmHxqL0JhSiYs1R86j24Z6trup4snKxXj/B2JDFxFuBPg65Q7S2sh64imfe5GYrdtxJkkVXRs1MBXfkRw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=mF2M6UGQ; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="mF2M6UGQ" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6558nXUJ1957488; Fri, 5 Jun 2026 10:38:12 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=YlUj89zQv1z Yv0lyYj7V8q5ErTAibhjcillqMYZNRm4=; b=mF2M6UGQAT28Mkb1c3hLX9eT6IX t3RlMIfIFjupJTeNO6Om6iQfj4lNL9Mhormy8XdifoIal/XfYkNCkaixD2og+806 9emo1NB+GqGViTZbU00NllXCJYxOyevan7/hi6bli4Tf8tkGKC0p/T8TDsAgTNCa uY6oZ8S2F87Di/JbbNVhAKaPl3J1CXhkQ/1J71rWViGtEuwnxsIoAk52b/3rpwJM y3QDy7fsT/Pt8xB0xi5CJzIurvzoH8+YiJZPmXPHvYIWRzlsXECMCfhroFs0ld9G 02b8xB7Bv2SQdLwAFhPqTFHl+xfy3oSPUYssLy6waDCbIlZLoTdAuBGOArA== Received: from apblrppmta01.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com [103.229.18.19]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ekckpv7ac-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 05 Jun 2026 10:38:11 +0000 (GMT) Received: from hu-hgautam-hyd.qualcomm.com (hu-hgautam-hyd.qualcomm.com [10.147.247.91]) by APBLRPPMTA01.qualcomm.com (8.18.1.7/8.18.1.7) with ESMTP id 655Abk70011714; Fri, 5 Jun 2026 10:38:08 GMT From: Harendra Gautam To: Srinivas Kandagatla Cc: Mark Brown , Liam Girdwood , Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-sound@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 13/13] ASoC: qcom: Add Shikra QAIF support Date: Fri, 5 Jun 2026 16:07:39 +0530 Message-Id: <20260605103739.3557573-14-harendra.gautam@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> References: <20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QCInternal: smtphost X-Proofpoint-GUID: X2dl4WA4lQdx9XkJc80dF57YId1mVOyK X-Proofpoint-ORIG-GUID: X2dl4WA4lQdx9XkJc80dF57YId1mVOyK X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjA1MDEwMyBTYWx0ZWRfX01l/33eaI+V/ PXbGoW20M6Di3a2LaxmhHbM7QzX3eJkSGzZoPN1aeZS6XtrpP+0MyYuCEtuo6bv6BlB/g/IXOnw FqU6SnGeDibZMemKhprj8/Pm2UMNNoMQPVia3JJ/zQey3Q+96LKa9xrL9CD93a5zmCdZMkV95m+ JYqISWJjdtAU6zgzsCFXdUX7PCasunzxfRT6eFWgjon6ZLcfShcCNEEsq8E4WXrJELyzoa9e+y6 Wcdqf9F434M3HjMI+3jheKJKsdB3ydowXH7Gjw5baa64WLPkMB/6jWH7sEjhWsk8tBbQ9brVtMA kNgJPRzDC+P8coQOa2FAVUqO7Wf9wJyN6dZh83J+uV1uj6IweP7iJOcUba7BtdsSpFUdu4L1cX3 zm9aBqVO4VsYBqr3/B+E7XNc6fHiMs6CUEYsDd1NBQV4TwvITgkat5EA83ePHcuJKystQDdYyAS meXrlilzs+lxxxFXV8g== X-Authority-Analysis: v=2.4 cv=H9jrBeYi c=1 sm=1 tr=0 ts=6a22a714 cx=c_pps a=Ou0eQOY4+eZoSc0qltEV5Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=rJkE3RaqiGZ5pbrm-msn:22 a=EUspDBNiAAAA:8 a=sd0t3XC7S1sX9aJXo7sA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-05_01,2026-05-28_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 adultscore=0 phishscore=0 bulkscore=0 lowpriorityscore=0 spamscore=0 clxscore=1015 impostorscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605210000 definitions=main-2606050103 Content-Type: text/plain; charset="utf-8" Add the Shikra variant data for the Qualcomm Audio Interface driver and hook it up to Kconfig and the qcom ASoC Makefile. Shikra uses QAIF to move PCM data between memory, MI2S interfaces and the Bolero codec CDC DMA paths. Without the SoC-specific register layout, DMA- to-DAI mappings, clock list and DAI descriptors, Shikra-based platforms cannot enable playback or capture through this block. Provide the Shikra QAIF register field definitions, DMA mappings, DAI descriptors, clock configuration and platform match data, and build them as part of the snd-soc-qcom-qaif module. Signed-off-by: Harendra Gautam --- sound/soc/qcom/Kconfig | 11 + sound/soc/qcom/Makefile | 2 + sound/soc/qcom/qaif-shikra.c | 585 +++++++++++++++++++++++++++++++++++ 3 files changed, 598 insertions(+) create mode 100644 sound/soc/qcom/qaif-shikra.c diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index e6e24f3b9922..2eca25478fd4 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -71,6 +71,17 @@ config SND_SOC_QCOM_COMMON config SND_SOC_QCOM_SDW tristate =20 +config SND_SOC_QCOM_QAIF + tristate "Qualcomm QAIF audio interface support" + depends on COMMON_CLK + select REGMAP_MMIO + help + Say Y or M to enable the Qualcomm Audio Interface (QAIF) driver + used on the Shikra audio platform. QAIF is the DMA controller + that moves PCM data between the codec and memory over AIF (MI2S) + and CIF (CDC DMA) paths. Required for audio playback and capture + on Shikra-based platforms. + config SND_SOC_QDSP6_COMMON tristate =20 diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index 985ce2ae286b..857bb2a032a2 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -31,6 +31,7 @@ snd-soc-qcom-common-y :=3D common.o snd-soc-qcom-sdw-y :=3D sdw.o snd-soc-x1e80100-y :=3D x1e80100.o snd-soc-qcom-offload-utils-objs :=3D usb_offload_utils.o +snd-soc-qcom-qaif-y :=3D qaif-cpu.o qaif-platform.o qaif-shikra.o =20 obj-$(CONFIG_SND_SOC_STORM) +=3D snd-soc-storm.o obj-$(CONFIG_SND_SOC_APQ8016_SBC) +=3D snd-soc-apq8016-sbc.o @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_QCOM_COMMON) +=3D snd-soc-qcom-commo= n.o obj-$(CONFIG_SND_SOC_QCOM_SDW) +=3D snd-soc-qcom-sdw.o obj-$(CONFIG_SND_SOC_X1E80100) +=3D snd-soc-x1e80100.o obj-$(CONFIG_SND_SOC_QCOM_OFFLOAD_UTILS) +=3D snd-soc-qcom-offload-utils.o +obj-$(CONFIG_SND_SOC_QCOM_QAIF) +=3D snd-soc-qcom-qaif.o =20 #DSP lib obj-$(CONFIG_SND_SOC_QDSP6) +=3D qdsp6/ diff --git a/sound/soc/qcom/qaif-shikra.c b/sound/soc/qcom/qaif-shikra.c new file mode 100644 index 000000000000..e83564503087 --- /dev/null +++ b/sound/soc/qcom/qaif-shikra.c @@ -0,0 +1,585 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-shikra.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF + */ + +#include +#include +#include +#include +#include "qaif.h" + +struct qaif_dmaidx_dai_map shikra_aif_dma_dai_map[] =3D { + { QAIF_MI2S_TDM_AIF0 }, + { QAIF_MI2S_TDM_AIF1 }, + { QAIF_MI2S_TDM_AIF2 }, + { QAIF_MI2S_TDM_AIF3 } +}; + +struct qaif_dmaidx_dai_map shikra_cif_rx_dma_dai_map[] =3D { + { QAIF_CDC_DMA_RX0 }, + { QAIF_CDC_DMA_RX1 }, + { QAIF_CDC_DMA_RX2 }, + { QAIF_CDC_DMA_RX3 } +}; + +struct qaif_dmaidx_dai_map shikra_cif_tx_dma_dai_map[] =3D { + { QAIF_CDC_DMA_TX0 }, + { QAIF_CDC_DMA_TX1 }, + { QAIF_CDC_DMA_TX2 }, + { QAIF_CDC_DMA_TX3 } +}; + +struct qaif_dmaidx_dai_map shikra_cif_va_dma_dai_map[] =3D { + { QAIF_CDC_DMA_VA_TX0 }, + { QAIF_CDC_DMA_VA_TX1 }, + { QAIF_CDC_DMA_VA_TX2 }, + { QAIF_CDC_DMA_VA_TX3 } +}; + +static struct snd_soc_dai_driver shikra_qaif_cpu_dai_driver[] =3D { + { + .id =3D QAIF_MI2S_TDM_AIF0, + .name =3D "Audio Interface Zero", + .playback =3D { + .stream_name =3D "AIF Zero Playback", + .formats =3D SNDRV_PCM_FMTBIT_S16, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 2, + .channels_max =3D 2, + }, + .capture =3D { + .stream_name =3D "AIF Zero Capture", + .formats =3D SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 2, + .channels_max =3D 2, + }, + .ops =3D &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id =3D QAIF_MI2S_TDM_AIF1, + .name =3D "Audio Interface One", + .playback =3D { + .stream_name =3D "AIF One Playback", + .formats =3D SNDRV_PCM_FMTBIT_S16, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 2, + .channels_max =3D 2, + }, + .capture =3D { + .stream_name =3D "AIF One Capture", + .formats =3D SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 2, + .channels_max =3D 2, + }, + .ops =3D &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id =3D QAIF_MI2S_TDM_AIF2, + .name =3D "Audio Interface Two", + .playback =3D { + .stream_name =3D "AIF Two Playback", + .formats =3D SNDRV_PCM_FMTBIT_S16, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 2, + .channels_max =3D 2, + }, + .capture =3D { + .stream_name =3D "AIF Two Capture", + .formats =3D SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 2, + .channels_max =3D 2, + }, + .ops =3D &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id =3D QAIF_MI2S_TDM_AIF3, + .name =3D "Audio Interface Three", + .playback =3D { + .stream_name =3D "AIF Three Playback", + .formats =3D SNDRV_PCM_FMTBIT_S16, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 2, + .channels_max =3D 2, + }, + .capture =3D { + .stream_name =3D "AIF Three Capture", + .formats =3D SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 2, + .channels_max =3D 2, + }, + .ops =3D &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id =3D QAIF_CDC_DMA_RX0, + .name =3D "CDC DMA RX0", + .playback =3D { + .stream_name =3D "WCD Playback0", + .formats =3D SNDRV_PCM_FMTBIT_S16, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 1, + .channels_max =3D 2, + }, + .ops =3D &asoc_qcom_qaif_cif_dai_ops, + }, { + .id =3D QAIF_CDC_DMA_RX1, + .name =3D "CDC DMA RX1", + .playback =3D { + .stream_name =3D "WCD Playback1", + .formats =3D SNDRV_PCM_FMTBIT_S16, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 1, + .channels_max =3D 2, + }, + .ops =3D &asoc_qcom_qaif_cif_dai_ops, + }, { + .id =3D QAIF_CDC_DMA_VA_TX0, + .name =3D "CDC DMA VA0", + .capture =3D { + .stream_name =3D "DMIC Capture0", + .formats =3D SNDRV_PCM_FMTBIT_S16, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 1, + .channels_max =3D 4, + }, + .ops =3D &asoc_qcom_qaif_cif_dai_ops, + }, { + .id =3D QAIF_CDC_DMA_VA_TX1, + .name =3D "CDC DMA VA1", + .capture =3D { + .stream_name =3D "DMIC Capture1", + .formats =3D SNDRV_PCM_FMTBIT_S16, + .rates =3D SNDRV_PCM_RATE_48000, + .rate_min =3D 48000, + .rate_max =3D 48000, + .channels_min =3D 1, + .channels_max =3D 4, + }, + .ops =3D &asoc_qcom_qaif_cif_dai_ops, + }, +}; + +static int shikra_qaif_get_dma_idx(unsigned int dai_id) +{ + int i; + + switch (dai_id) { + case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12: + for (i =3D 0; i < ARRAY_SIZE(shikra_aif_dma_dai_map); i++) { + if (shikra_aif_dma_dai_map[i].dai_id =3D=3D dai_id) + return i; + } + break; + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + for (i =3D 0; i < ARRAY_SIZE(shikra_cif_rx_dma_dai_map); i++) { + if (shikra_cif_rx_dma_dai_map[i].dai_id =3D=3D dai_id) + return i; + } + break; + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + for (i =3D 0; i < ARRAY_SIZE(shikra_cif_tx_dma_dai_map); i++) { + if (shikra_cif_tx_dma_dai_map[i].dai_id =3D=3D dai_id) + return i; + } + break; + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + for (i =3D 0; i < ARRAY_SIZE(shikra_cif_va_dma_dai_map); i++) { + if (shikra_cif_va_dma_dai_map[i].dai_id =3D=3D dai_id) + return i; + } + break; + default: + pr_debug("DAI ID not Supported\n"); + break; + } + + pr_debug("DAI ID %u not found in map\n", dai_id); + return -EINVAL; +} + +static int shikra_qaif_alloc_stream_dma_idx(struct qaif_drv_data *drvdata, + int direction, unsigned int dai_id) +{ + const struct qaif_variant *v =3D drvdata->variant; + int dma_idx; + int index =3D 0; + + if (!v) + return -EINVAL; + + switch (dai_id) { + case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12: + dma_idx =3D shikra_qaif_get_dma_idx(dai_id); + if (dma_idx < 0) + return dma_idx; + + if (direction =3D=3D SNDRV_PCM_STREAM_PLAYBACK) { + index =3D dma_idx; + if (index >=3D v->num_rddma) + return -EBUSY; + } else { + index =3D v->wrdma_start + dma_idx; + if (index >=3D v->wrdma_start + v->num_wrdma) + return -EBUSY; + } + if (test_bit(index, &drvdata->aif_dma_idx_bit_map)) + return -EBUSY; + + set_bit(index, &drvdata->aif_dma_idx_bit_map); + break; + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + dma_idx =3D shikra_qaif_get_dma_idx(dai_id); + if (dma_idx < 0) + return dma_idx; + + if (direction =3D=3D SNDRV_PCM_STREAM_PLAYBACK) { + index =3D dma_idx; + if (index >=3D v->num_codec_rddma) + return -EBUSY; + } else { + index =3D v->codec_wrdma_start + dma_idx; + if (index >=3D v->codec_wrdma_start + v->num_codec_wrdma) + return -EBUSY; + } + if (test_bit(index, &drvdata->cif_dma_idx_bit_map)) + return -EBUSY; + + set_bit(index, &drvdata->cif_dma_idx_bit_map); + break; + default: + return -EINVAL; + } + + return index; +} + +static int shikra_qaif_free_stream_dma_idx(struct qaif_drv_data *drvdata, + int index, unsigned int dai_id) +{ + switch (dai_id) { + case QAIF_MI2S_TDM_AIF0 ... QAIF_MI2S_TDM_AIF12: + clear_bit(index, &drvdata->aif_dma_idx_bit_map); + break; + case QAIF_CDC_DMA_RX0 ... QAIF_CDC_DMA_RX9: + case QAIF_CDC_DMA_TX0 ... QAIF_CDC_DMA_TX9: + case QAIF_CDC_DMA_VA_TX0 ... QAIF_CDC_DMA_VA_TX9: + clear_bit(index, &drvdata->cif_dma_idx_bit_map); + break; + default: + break; + } + + return 0; +} + +static int shikra_qaif_init(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata =3D platform_get_drvdata(pdev); + const struct qaif_variant *v =3D drvdata->variant; + struct device *dev =3D &pdev->dev; + int ret, i; + + if (!v) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + if (v->num_clks =3D=3D 0 || v->num_clks > QAIF_MAX_VARIANT_CLKS) { + dev_err(dev, "Invalid clock count: %d\n", v->num_clks); + return -EINVAL; + } + drvdata->clks =3D devm_kcalloc(dev, v->num_clks, + sizeof(*drvdata->clks), GFP_KERNEL); + if (!drvdata->clks) + return -ENOMEM; + + drvdata->num_clks =3D v->num_clks; + + for (i =3D 0; i < drvdata->num_clks; i++) + drvdata->clks[i].id =3D v->clk_name[i]; + + ret =3D devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "Failed to get clocks %d\n", ret); + return ret; + } + + ret =3D clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "shikra clk_enable failed\n"); + return ret; + } + + return 0; +} + +static int shikra_qaif_exit(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata =3D platform_get_drvdata(pdev); + + if (!drvdata || !drvdata->clks) + return -EINVAL; + + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + return 0; +} + +static int __maybe_unused shikra_qaif_dev_resume(struct device *dev) +{ + struct qaif_drv_data *drvdata =3D dev_get_drvdata(dev); + + if (!drvdata || !drvdata->clks) { + dev_err(dev, "Invalid drvdata in resume\n"); + return -EINVAL; + } + return clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); +} + +static int __maybe_unused shikra_qaif_dev_suspend(struct device *dev) +{ + struct qaif_drv_data *drvdata =3D dev_get_drvdata(dev); + + if (!drvdata || !drvdata->clks) { + dev_err(dev, "Invalid drvdata in suspend\n"); + return -EINVAL; + } + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + return 0; +} + +static const struct dev_pm_ops shikra_qaif_pm_ops =3D { + SET_SYSTEM_SLEEP_PM_OPS(shikra_qaif_dev_suspend, + shikra_qaif_dev_resume) +}; + +static const struct qaif_variant shikra_qaif_data =3D { + .ee =3D 0, + .qaif_type =3D QAIF, + + .num_rddma =3D 4, + .num_wrdma =3D 4, + .wrdma_start =3D 4, + + .num_codec_rddma =3D 4, + .num_codec_wrdma =3D 4, + .codec_wrdma_start =3D 4, + .num_intf =3D 4, + + .rddma_reg_base =3D 0x8000, + .rddma_stride =3D 0x1000, + .codec_rddma_reg_base =3D 0xC000, + .codec_rddma_stride =3D 0x1000, + + .wrdma_reg_base =3D 0x11000, + .wrdma_stride =3D 0x1000, + .codec_wrdma_reg_base =3D 0x15000, + .codec_wrdma_stride =3D 0x1000, + + .rddma_irq_reg_base =3D 0x19000, + .rddma_irq_stride =3D 0x1000, + .codec_rddma_irq_reg_base =3D 0x191A0, + .codec_rddma_irq_stride =3D 0x1000, + + .wrdma_irq_reg_base =3D 0x19078, + .wrdma_irq_stride =3D 0x1000, + .codec_wrdma_irq_reg_base =3D 0x19290, + .codec_wrdma_irq_stride =3D 0x1000, + + .qxm_type =3D QXM0, + .rd_len =3D 512, + .rddma_shram_len =3D 64, + .rddma_shram_start_addr =3D {0, 256}, + .wr_len =3D 512, + .wrdma_shram_len =3D 64, + .wrdma_shram_start_addr =3D {0, 256}, + + /* AUDIO_CORE_QAIF_RDDMAa_CTL (0x8000 + 0x1000*a) */ + .rddma_enable =3D REG_FIELD_ID(0x8000, 0, 0, 4, 0x1000), + .rddma_reset =3D REG_FIELD_ID(0x8000, 4, 4, 4, 0x1000), + + /* AUDIO_CORE_QAIF_RDDMAa_CFG (0x8004 + 0x1000*a) */ + .rddma_shram_wm =3D REG_FIELD_ID(0x8004, 0, 11, 4, 0x1000), + .rddma_burst1 =3D REG_FIELD_ID(0x8004, 16, 16, 4, 0x1000), + .rddma_burst2 =3D REG_FIELD_ID(0x8004, 17, 17, 4, 0x1000), + .rddma_burst4 =3D REG_FIELD_ID(0x8004, 18, 18, 4, 0x1000), + .rddma_burst8 =3D REG_FIELD_ID(0x8004, 19, 19, 4, 0x1000), + .rddma_burst16 =3D REG_FIELD_ID(0x8004, 20, 20, 4, 0x1000), + .rddma_dma_dyncclk =3D REG_FIELD_ID(0x8004, 24, 24, 4, 0x1000), + .rddma_num_ot =3D REG_FIELD_ID(0x8004, 28, 29, 4, 0x1000), + + /* AUDIO_CORE_QAIF_WRDMAa_CTL (0x11000 + 0x1000*a) */ + .wrdma_enable =3D REG_FIELD_ID(0x11000, 0, 0, 4, 0x1000), + .wrdma_reset =3D REG_FIELD_ID(0x11000, 4, 4, 4, 0x1000), + + /* AUDIO_CORE_QAIF_WRDMAa_CFG (0x11004 + 0x1000*a) */ + .wrdma_shram_wm =3D REG_FIELD_ID(0x11004, 0, 11, 4, 0x1000), + .wrdma_burst1 =3D REG_FIELD_ID(0x11004, 16, 16, 4, 0x1000), + .wrdma_burst2 =3D REG_FIELD_ID(0x11004, 17, 17, 4, 0x1000), + .wrdma_burst4 =3D REG_FIELD_ID(0x11004, 18, 18, 4, 0x1000), + .wrdma_burst8 =3D REG_FIELD_ID(0x11004, 19, 19, 4, 0x1000), + .wrdma_burst16 =3D REG_FIELD_ID(0x11004, 20, 20, 4, 0x1000), + .wrdma_dma_dyncclk =3D REG_FIELD_ID(0x11004, 24, 24, 4, 0x1000), + .wrdma_num_ot =3D REG_FIELD_ID(0x11004, 28, 29, 4, 0x1000), + + /* AUDIO_CORE_QAIF_CODEC_RDDMAa_CTL (0xC000 + 0x1000*a) */ + .cif_rddma_enable =3D REG_FIELD_ID(0xC000, 0, 0, 4, 0x1000), + .cif_rddma_reset =3D REG_FIELD_ID(0xC000, 4, 4, 4, 0x1000), + + /* AUDIO_CORE_QAIF_CODEC_RDDMAa_CFG (0xC004 + 0x1000*a) */ + .cif_rddma_shram_wm =3D REG_FIELD_ID(0xC004, 0, 11, 4, 0x1000), + .cif_rddma_burst1 =3D REG_FIELD_ID(0xC004, 16, 16, 4, 0x1000), + .cif_rddma_burst2 =3D REG_FIELD_ID(0xC004, 17, 17, 4, 0x1000), + .cif_rddma_burst4 =3D REG_FIELD_ID(0xC004, 18, 18, 4, 0x1000), + .cif_rddma_burst8 =3D REG_FIELD_ID(0xC004, 19, 19, 4, 0x1000), + .cif_rddma_burst16 =3D REG_FIELD_ID(0xC004, 20, 20, 4, 0x1000), + .cif_rddma_dma_dyncclk =3D REG_FIELD_ID(0xC004, 24, 24, 4, 0x1000), + .cif_rddma_num_ot =3D REG_FIELD_ID(0xC004, 28, 29, 4, 0x1000), + + /* AUDIO_CORE_QAIF_CODEC_RDDMAa_INTF_CFG (0xC05C + 0x1000*a) */ + .cif_rddma_en_16bit_unpack =3D REG_FIELD_ID(0xC05C, 0, 0, 4, 0x1000), + .cif_rddma_intf_dyncclk =3D REG_FIELD_ID(0xC05C, 2, 2, 4, 0x1000), + .cif_rddma_fs_out_gate =3D REG_FIELD_ID(0xC05C, 3, 3, 4, 0x1000), + .cif_rddma_fs_sel =3D REG_FIELD_ID(0xC05C, 4, 7, 4, 0x1000), + .cif_rddma_fs_delay =3D REG_FIELD_ID(0xC05C, 8, 11, 4, 0x1000), + .cif_rddma_active_ch_en =3D REG_FIELD_ID(0xC05C, 12, 27, 4, 0x1000), + + /* AUDIO_CORE_QAIF_CODEC_WRDMAa_CTL (0x15000 + 0x1000*a) */ + .cif_wrdma_enable =3D REG_FIELD_ID(0x15000, 0, 0, 4, 0x1000), + .cif_wrdma_reset =3D REG_FIELD_ID(0x15000, 4, 4, 4, 0x1000), + + /* AUDIO_CORE_QAIF_CODEC_WRDMAa_CFG (0x15004 + 0x1000*a) */ + .cif_wrdma_shram_wm =3D REG_FIELD_ID(0x15004, 0, 11, 4, 0x1000), + .cif_wrdma_burst1 =3D REG_FIELD_ID(0x15004, 16, 16, 4, 0x1000), + .cif_wrdma_burst2 =3D REG_FIELD_ID(0x15004, 17, 17, 4, 0x1000), + .cif_wrdma_burst4 =3D REG_FIELD_ID(0x15004, 18, 18, 4, 0x1000), + .cif_wrdma_burst8 =3D REG_FIELD_ID(0x15004, 19, 19, 4, 0x1000), + .cif_wrdma_burst16 =3D REG_FIELD_ID(0x15004, 20, 20, 4, 0x1000), + .cif_wrdma_dma_dyncclk =3D REG_FIELD_ID(0x15004, 24, 24, 4, 0x1000), + .cif_wrdma_num_ot =3D REG_FIELD_ID(0x15004, 28, 29, 4, 0x1000), + + /* AUDIO_CORE_QAIF_CODEC_WRDMAa_INTF_CFG (0x15058 + 0x1000*a) */ + .cif_wrdma_en_16bit_unpack =3D REG_FIELD_ID(0x15058, 0, 0, 4, 0x1000), + .cif_wrdma_intf_dyncclk =3D REG_FIELD_ID(0x15058, 2, 2, 4, 0x1000), + .cif_wrdma_fs_out_gate =3D REG_FIELD_ID(0x15058, 3, 3, 4, 0x1000), + .cif_wrdma_fs_sel =3D REG_FIELD_ID(0x15058, 4, 7, 4, 0x1000), + .cif_wrdma_fs_delay =3D REG_FIELD_ID(0x15058, 8, 11, 4, 0x1000), + .cif_wrdma_active_ch_en =3D REG_FIELD_ID(0x15058, 12, 27, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_CTL (0x4000 + 0x1000*a) */ + .aif_enable =3D REG_FIELD_ID(0x4000, 0, 0, 4, 0x1000), + .aif_enable_tx =3D REG_FIELD_ID(0x4000, 4, 4, 4, 0x1000), + .aif_enable_rx =3D REG_FIELD_ID(0x4000, 8, 8, 4, 0x1000), + .aif_reset =3D REG_FIELD_ID(0x4000, 12, 12, 4, 0x1000), + .aif_reset_tx =3D REG_FIELD_ID(0x4000, 16, 16, 4, 0x1000), + .aif_reset_rx =3D REG_FIELD_ID(0x4000, 20, 20, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_SYNC_CFG (0x4004 + 0x1000*a) */ + .aif_inv_sync =3D REG_FIELD_ID(0x4004, 12, 12, 4, 0x1000), + .aif_sync_delay =3D REG_FIELD_ID(0x4004, 8, 9, 4, 0x1000), + .aif_sync_mode =3D REG_FIELD_ID(0x4004, 4, 5, 4, 0x1000), + .aif_sync_src =3D REG_FIELD_ID(0x4004, 0, 0, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_BIT_WIDTH_CFG (0x4008 + 0x1000*a) */ + .aif_sample_width_rx =3D REG_FIELD_ID(0x4008, 24, 28, 4, 0x1000), + .aif_sample_width_tx =3D REG_FIELD_ID(0x4008, 16, 20, 4, 0x1000), + .aif_slot_width_rx =3D REG_FIELD_ID(0x4008, 8, 12, 4, 0x1000), + .aif_slot_width_tx =3D REG_FIELD_ID(0x4008, 0, 4, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_FRAME_CFG (0x400C + 0x1000*a) */ + .aif_bits_per_lane =3D REG_FIELD_ID(0x400C, 0, 9, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_TX (0x4010 + 0x1000*a) */ + .aif_slot_en_tx_mask =3D REG_FIELD_ID(0x4010, 0, 31, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_RX (0x4030 + 0x1000*a) */ + .aif_slot_en_rx_mask =3D REG_FIELD_ID(0x4030, 0, 31, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_LANE_CFG (0x4050 + 0x1000*a) */ + .aif_loopback_en =3D REG_FIELD_ID(0x4050, 31, 31, 4, 0x1000), + .aif_ctrl_data_oe =3D REG_FIELD_ID(0x4050, 16, 16, 4, 0x1000), + .aif_lane_en =3D REG_FIELD_ID(0x4050, 8, 15, 4, 0x1000), + .aif_lane_dir =3D REG_FIELD_ID(0x4050, 0, 7, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_MI2S_CFG (0x4054 + 0x1000*a) */ + .aif_mono_mode_rx =3D REG_FIELD_ID(0x4054, 1, 1, 4, 0x1000), + .aif_mono_mode_tx =3D REG_FIELD_ID(0x4054, 0, 0, 4, 0x1000), + + /* AUDIO_CORE_QAIF_AUD_INTFa_CFG (0x4058 + 0x1000*a) */ + .aif_full_cycle_en =3D REG_FIELD_ID(0x4058, 0, 0, 4, 0x1000), + + .clk_name =3D (const char*[]) { + "lpass_config_clk", + "lpass_core_axim_clk", + "bus_clk" + }, + .num_clks =3D 3, + + .dai_driver =3D shikra_qaif_cpu_dai_driver, + .num_dai =3D ARRAY_SIZE(shikra_qaif_cpu_dai_driver), + + .dai_osr_clk_names =3D (const char *[]) { + "null" + }, + .dai_bit_clk_names =3D (const char *[]) { + "aif_if0_ibit_clk", + "aif_if1_ibit_clk", + "aif_if2_ibit_clk", + "aif_if3_ibit_clk" + }, + .init =3D shikra_qaif_init, + .exit =3D shikra_qaif_exit, + .alloc_stream_dma_idx =3D shikra_qaif_alloc_stream_dma_idx, + .free_stream_dma_idx =3D shikra_qaif_free_stream_dma_idx, + .get_dma_idx =3D shikra_qaif_get_dma_idx, +}; + +static const struct of_device_id shikra_qaif_cpu_device_id[] =3D { + {.compatible =3D "qcom,shikra-qaif-cpu", .data =3D &shikra_qaif_data}, + {} +}; +MODULE_DEVICE_TABLE(of, shikra_qaif_cpu_device_id); + +static struct platform_driver shikra_qaif_cpu_platform_driver =3D { + .driver =3D { + .name =3D "shikra-qaif-cpu", + .of_match_table =3D of_match_ptr(shikra_qaif_cpu_device_id), + .pm =3D &shikra_qaif_pm_ops, + }, + .probe =3D asoc_qcom_qaif_cpu_platform_probe, + .remove =3D asoc_qcom_qaif_cpu_platform_remove, + .shutdown =3D asoc_qcom_qaif_cpu_platform_shutdown, +}; +module_platform_driver(shikra_qaif_cpu_platform_driver); + +MODULE_DESCRIPTION("Qualcomm Audio Interface (QAIF) Shikra variant driver"= ); +MODULE_AUTHOR("Harendra Gautam "); +MODULE_LICENSE("GPL"); --=20 2.34.1