From patchwork Wed Apr 18 15:31:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133639 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp35542ljf; Wed, 18 Apr 2018 08:36:12 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+3l5oNfRh7CcnVVDU0Ri30INSE7mNLgKAk0Ym4C2xHCLWI8kQxKVHZbMd7c3EqsnNO3QRA X-Received: by 10.28.18.136 with SMTP id 130mr1876091wms.74.1524065772246; Wed, 18 Apr 2018 08:36:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065772; cv=none; d=google.com; s=arc-20160816; b=WsSai4jocOKV6l8dZeTfz9sHEfMQOXvk7VdqlFpqLj1ZagG/CJjVKa7cmCU751Lsp6 mFJa+eX0wLzI/d1GMT5XCe0rBs1dSOTSVLIRjvZRCwcj0SGVdjJg4dvjRcqjoYp9IeNZ sGpPoW/pbWmtTjCD/SLdq3chqVsigjH+is3B5gxQkNMMfkzb23SYiM+RnIo+VTcV6qm3 PPHVyB3Azj68dCpvtHcO2vZ0WZQI1PBdXFC9M6aXdsow4ObX0fJjXPb0aIA2bOBpWXjh nJd99Ta6iBQS6dxWHsr0XvHnPm/HNBqsyp5JD8F6fHhr+ZY3RBprzgU7EnqeiQ/oFIyC sC9A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=2eKZVT0IIj6OwLsR3IWkpwkqGiHSfsxEMgIfxjHjiZw=; b=mm0KHvW1R/67JEDAGb6NJORn2FYG6vnKclwSR6KR5Lmy9SFcKw7XYuYY337rNt3Zj+ 69fGvzNIrd1oRbd85eSa5AvRPy6uOsFsW1V7qLSfcfozIHAovzoVKW6rnSjKZnQooDub p0uhoKkZBm/Phff6TTPz16rdAK6iXfglOlIsw+p1BW2FqkoMhDKFjGB4F++9hoE6XT7V 9jlaPiQpKSHFdBau+aNMKJucso50otmteonaMzO/l9tJ8t7oZUjOGVZ+Ls+zKRCJvgtL y9m7IqYbkqbHCt4Lr9zFMKm4lmQ2dtiR+wButIS0QqtoF9te2tUw2eMoe+33I2ut4NN8 OvLg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=dJtciRAg; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id 5-v6si1264254wrj.387.2018.04.18.08.36.12; Wed, 18 Apr 2018 08:36:12 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=dJtciRAg; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 7B9C226768E; Wed, 18 Apr 2018 17:36:03 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id C5CF126767D; Wed, 18 Apr 2018 17:35:59 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f193.google.com (mail-wr0-f193.google.com [209.85.128.193]) by alsa0.perex.cz (Postfix) with ESMTP id C4EE3267673 for ; Wed, 18 Apr 2018 17:35:57 +0200 (CEST) Received: by mail-wr0-f193.google.com with SMTP id s18-v6so6035095wrg.9 for ; Wed, 18 Apr 2018 08:35:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=LBRPzXi/wCJOj3nCVSQrwiBw4648hk1YspqG/sDt3FM=; b=dJtciRAg5EXaJ6DZSKSfec1HKSHO5Op5wLb+2iziIu+dDAZVMQaadVK/RF9ulMKYQF s9cIOy1Invbv8NPB55308JIulS7ATqGXK5GNN2qqwM6n60Uqr7ox0hVwmCw2jF1F83pW nxAju83vZzc/rYzhiqaKj6IOyccGpBQxHv5Cc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=LBRPzXi/wCJOj3nCVSQrwiBw4648hk1YspqG/sDt3FM=; b=HvQtY/1Iti5HXCtpSU3hbt1H3VNzqvVw9/0/lnTjBz/EOx8Dz5RCQLaF25u9SA7zDC U6tGMdEB2HN86KfTycc/d1+fN0eiGvpEXxmDRKcVfbQHYvrG+A01GN4X1AIbjm87Ek4Z aDYgM4G+GSka3oR8rbkDE+vRsrjgUu/vW3aRC0jNIMtFcLF5oql6VZ/3FJDNCWc4Fz1X Fk3M4z5XzsMe3mLRDCoeLbiwj001LsKrS7pi8GuA4IrCJ5GSb5MBb0yzEiZf/blUgzLd G36ywplQeOVWT7Wtv+9rsewhYXyoHptXe/4Daj66HYAEluhGWPp/WV91S5vXMsxJLNks mAhQ== X-Gm-Message-State: ALQs6tDFOOnUZS8nkizoVmsprgQWeEFrDX6QcoBTPvXVL5gxGhhAmzj1 Ev7//5xBS0dBVVyOsrMqBg2eOw== X-Received: by 10.28.140.204 with SMTP id o195mr2197279wmd.35.1524065757117; Wed, 18 Apr 2018 08:35:57 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.35.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:35:56 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:35 +0100 Message-Id: <20180418153157.1960-2-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 01/23] soc: qcom dt-bindings: Add APR bus bindings X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch add dt bindings for Qualcomm APR (Asynchronous Packet Router) bus driver. This bus is used for communicating with DSP which provides audio and various other services to cpu. Signed-off-by: Srinivas Kandagatla --- .../devicetree/bindings/soc/qcom/qcom,apr.txt | 85 ++++++++++++++++++++++ include/dt-bindings/soc/qcom,apr.h | 27 +++++++ 2 files changed, 112 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt create mode 100644 include/dt-bindings/soc/qcom,apr.h -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt new file mode 100644 index 000000000000..85cc0433fb00 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt @@ -0,0 +1,85 @@ +Qualcomm APR (Asynchronous Packet Router) binding + +This binding describes the Qualcomm APR. APR is a IPC protocol for +communication between Application processor and QDSP. APR is mainly +used for audio/voice services on the QDSP. + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,apr-v", example "qcom,apr-v2" + +- qcom,dest-domain-id + Usage: required + Value type: + Definition: Destination processor ID. + Possible values are : + 1 - APR simulator + 2 - PC + 3 - MODEM + 4 - ADSP + 5 - APPS + 6 - MODEM2 + 7 - APPS2 + += APR SERVICES +Each subnode of the APR node represents service tied to this apr. The name +of the nodes are not important. The properties of these nodes are defined +by the individual bindings for the specific service +- All APR services MUST contain the following property: + +- reg + Usage: required + Value type: + Definition: APR Service ID + Possible values are : + 3 - DSP Core Service + 4 - Audio Front End Service. + 5 - Voice Stream Manager Service. + 6 - Voice processing manager. + 7 - Audio Stream Manager Service. + 8 - Audio Device Manager Service. + 9 - Multimode voice manager. + 10 - Core voice stream. + 11 - Core voice processor. + 12 - Ultrasound stream manager. + 13 - Listen stream manager. + += EXAMPLE +The following example represents a QDSP based sound card on a MSM8996 device +which uses apr as communication between Apps and QDSP. + + apr { + compatible = "qcom,apr-v2"; + qcom,smd-channels = "apr_audio_svc"; + qcom,dest-domain-id = ; + + q6core { + compatible = "qcom,q6core"; + reg = ; + }; + + q6afe { + compatible = "qcom,q6afe"; + reg = ; + + dais { + #sound-dai-cells = <1>; + hdmi@1 { + reg = <1>; + }; + }; + }; + + q6asm { + compatible = "qcom,q6asm"; + reg = ; + ... + }; + + q6adm { + compatible = "qcom,q6adm"; + reg = ; + ... + }; + }; diff --git a/include/dt-bindings/soc/qcom,apr.h b/include/dt-bindings/soc/qcom,apr.h new file mode 100644 index 000000000000..905503f81885 --- /dev/null +++ b/include/dt-bindings/soc/qcom,apr.h @@ -0,0 +1,27 @@ +#ifndef __DT_BINDINGS_QCOM_APR_H +#define __DT_BINDINGS_QCOM_APR_H + +/* Domain IDs */ +#define APR_DOMAIN_SIM 0x1 +#define APR_DOMAIN_PC 0x2 +#define APR_DOMAIN_MODEM 0x3 +#define APR_DOMAIN_ADSP 0x4 +#define APR_DOMAIN_APPS 0x5 +#define APR_DOMAIN_MAX 0x6 + +/* ADSP service IDs */ +#define APR_SVC_ADSP_CORE 0x3 +#define APR_SVC_AFE 0x4 +#define APR_SVC_VSM 0x5 +#define APR_SVC_VPM 0x6 +#define APR_SVC_ASM 0x7 +#define APR_SVC_ADM 0x8 +#define APR_SVC_ADSP_MVM 0x09 +#define APR_SVC_ADSP_CVS 0x0A +#define APR_SVC_ADSP_CVP 0x0B +#define APR_SVC_USM 0x0C +#define APR_SVC_LSM 0x0D +#define APR_SVC_VIDC 0x16 +#define APR_SVC_MAX 0x17 + +#endif /* __DT_BINDINGS_QCOM_APR_H */ From patchwork Wed Apr 18 15:31:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133644 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp35777ljf; Wed, 18 Apr 2018 08:36:24 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+Pg1hzFzZT2ZlJCIlbey4tDuKf4gTYc6rjCkm1mC4fNqCm0sjTh8xnUnggUnBGBXDjN9Xo X-Received: by 2002:adf:8b44:: with SMTP id v4-v6mr1918719wra.99.1524065784892; Wed, 18 Apr 2018 08:36:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065784; cv=none; d=google.com; s=arc-20160816; b=NK0Phe9TBHV53gfJwioWA5rYnKrLneRqKOC8CJqp2wDM2lRP2UxpXsy6lSe1OFuKwK 1biE7nus6lEGEVWaMDYMhi7Bbm9scdqZZpA4o7HcguD0DkUwQjEUuGd408Xjq5PbFF7k 7qg99UAzPkTa3M/jse1IkJ0nWl1QfW+er1ZMGFSDKDvReDrCDri0JhypR4uD33vhFQjI 6VrUt5JdPCzPkZMaAvTvnpux3linxoBLW67NSVp4cWUMu4trzQ+kLqRPfuQ2hoQkR0hu K7JHGj4YX93FC3HMFAyjTSkJiy7JSe1oWBBdeZMLI0IjMzjsvJVYTGKeQxj7v5i/EjSO aWAw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=yd5fWm5URAyx/oi1EG6A4oLFxOMJWV4MDx0DagOqis0=; b=JmUqJfvLPh+3fzYO7Lr9WyrOnpzrFnrkhU9iDGrIAkNfjbWy/eyIWZdThfHn0udYvP mMSWJfLwVG4hRHx3O+wyccQEj/DYy+lpoFJcqPSJ3has3uSJrK5PHR34IbF5kg6iKDRs iggUW09Vgg5ZTEkgHWBZGIqIp+YGBjPbccH2vKV6Yn7m4nmy34mIpj61MZ/KkBota7UV Ywvxfd7irJCNTbxk2PkYvWAkEdaCx/cxQVESLlfXXuieHiY05YYZPq+BDybFA4CWhZ3z uK/p16qYh1gA1GHCzGkCkc73eg1jpZC/3ma3ceL0BMR6ASLOAYFJ/wq0GHFVl4yfPYQN pDBQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=gHG53y4i; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id q4si824154wma.210.2018.04.18.08.36.24; Wed, 18 Apr 2018 08:36:24 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=gHG53y4i; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 6BB1B2676AC; Wed, 18 Apr 2018 17:36:07 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id F08B2267680; Wed, 18 Apr 2018 17:36:01 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f195.google.com (mail-wr0-f195.google.com [209.85.128.195]) by alsa0.perex.cz (Postfix) with ESMTP id 7006E266E30 for ; Wed, 18 Apr 2018 17:35:59 +0200 (CEST) Received: by mail-wr0-f195.google.com with SMTP id w3-v6so6050303wrg.2 for ; Wed, 18 Apr 2018 08:35:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5D/DJy1uqjOS4U4AJ0LfzalSNcqifyYxRFwRNivGeqQ=; b=gHG53y4iufpvfZhwbQVgehQMLwEUfd9+0LmPY45t6TLMQc8zM8fYaTGC9ekI4oLHMW b9zMtWY1DscAKCYCYtV0/5p+qN2ROPDYhnypzdhRBDS5xbFjEiha5GHDwxa1Dgq78QCP ZzkZJMjbX7CArtRLPPpC6qIjWBeKQLfRRZLdo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5D/DJy1uqjOS4U4AJ0LfzalSNcqifyYxRFwRNivGeqQ=; b=Myj45MwIswLJe8jQlXiGm9TdZ7R16aSTvIgQFItffsydRsFGx+iZWjrs9fLt8uYuC6 7/xXKlEIDr5AmiddUIdfYR1/4IioqaSQXYoK5FFGS40dkodRlmj3PuJLZ6qeWL05mm3N kEwPS9OL8Jl/ToqC1nBHbGgV377aqdkkTaKtR/KJlplM1QjvMP4I/FIXfv5bs6LjXvfN R6JY9Zz+lhw7Ht1qILdYij4171SnehU1LnIpDmxpTYnx64ukFoqtGmvgG/g1qAS4cpdj i1IJCXziqp5JFMYmU+hbHbOT12LrrKTROYS7PyyPpsJi3tW1iw5T1ZPyH2q4QfI/M36u eU6A== X-Gm-Message-State: ALQs6tCyuzYUQ5iTEaK8tebF+n5qQjUiul/E49JaaJYtRINmK1Nt5N1Y Vk5PXuK2kZEEefSI8JocXJmaWA== X-Received: by 10.28.230.28 with SMTP id d28mr2206694wmh.92.1524065758588; Wed, 18 Apr 2018 08:35:58 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.35.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:35:57 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:36 +0100 Message-Id: <20180418153157.1960-3-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 02/23] soc: qcom: Add APR bus driver X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch adds support toi APR bus (Asynchronous Packet Router) driver. ARP driver is made as a bus driver so that the apr devices can added removed more dynamically depending on the state of the services on the dsp. APR is used for communication between application processor and QDSP to use services on QDSP like Audio and others. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- drivers/soc/qcom/Kconfig | 9 + drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/apr.c | 385 ++++++++++++++++++++++++++++++++++++++++ include/linux/mod_devicetable.h | 11 ++ include/linux/soc/qcom/apr.h | 132 ++++++++++++++ 5 files changed, 538 insertions(+) create mode 100644 drivers/soc/qcom/apr.c create mode 100644 include/linux/soc/qcom/apr.h -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 5c4535b545cc..d053f2634c67 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -108,4 +108,13 @@ config QCOM_WCNSS_CTRL Client driver for the WCNSS_CTRL SMD channel, used to download nv firmware to a newly booted WCNSS chip. +config QCOM_APR + tristate "Qualcomm APR Bus (Asynchronous Packet Router)" + depends on ARCH_QCOM + depends on RPMSG + help + Enable APR IPC protocol support between + application processor and QDSP6. APR is + used by audio driver to configure QDSP6 + ASM, ADM and AFE modules. endmenu diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index dcebf2814e6d..39de5dee55d9 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o obj-$(CONFIG_QCOM_SMP2P) += smp2p.o obj-$(CONFIG_QCOM_SMSM) += smsm.o obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o +obj-$(CONFIG_QCOM_APR) += apr.o diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c new file mode 100644 index 000000000000..6c449e350ddf --- /dev/null +++ b/drivers/soc/qcom/apr.c @@ -0,0 +1,385 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation +// Copyright (c) 2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct apr { + struct rpmsg_endpoint *ch; + struct device *dev; + spinlock_t svcs_lock; + struct list_head svcs; + int dest_domain_id; +}; + +/** + * apr_send_pkt() - Send a apr message from apr device + * + * @adev: Pointer to previously registered apr device. + * @buf: Pointer to buffer to send + * + * Return: Will be an negative on packet size on success. + */ +int apr_send_pkt(struct apr_device *adev, void *buf) +{ + struct apr *apr = dev_get_drvdata(adev->dev.parent); + struct apr_hdr *hdr; + unsigned long flags; + int ret; + + spin_lock_irqsave(&adev->lock, flags); + + hdr = (struct apr_hdr *)buf; + hdr->src_domain = APR_DOMAIN_APPS; + hdr->src_svc = adev->svc_id; + hdr->dest_domain = adev->domain_id; + hdr->dest_svc = adev->svc_id; + + ret = rpmsg_send(apr->ch, buf, hdr->pkt_size); + if (ret) { + dev_err(&adev->dev, "Unable to send APR pkt %d\n", + hdr->pkt_size); + } else { + ret = hdr->pkt_size; + } + + spin_unlock_irqrestore(&adev->lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(apr_send_pkt); + +static void apr_dev_release(struct device *dev) +{ + struct apr_device *adev = to_apr_device(dev); + + kfree(adev); +} + +static int apr_callback(struct rpmsg_device *rpdev, void *buf, + int len, void *priv, u32 addr) +{ + struct apr *apr = dev_get_drvdata(&rpdev->dev); + struct apr_client_message data; + struct apr_device *p, *c_svc = NULL; + struct apr_driver *adrv = NULL; + struct apr_hdr *hdr; + unsigned long flags; + uint16_t hdr_size; + uint16_t msg_type; + uint16_t ver; + uint16_t svc; + + if (len <= APR_HDR_SIZE) { + dev_err(apr->dev, "APR: Improper apr pkt received:%p %d\n", + buf, len); + return -EINVAL; + } + + hdr = buf; + ver = APR_HDR_FIELD_VER(hdr->hdr_field); + if (ver > APR_PKT_VER + 1) + return -EINVAL; + + hdr_size = APR_HDR_FIELD_SIZE_BYTES(hdr->hdr_field); + if (hdr_size < APR_HDR_SIZE) { + dev_err(apr->dev, "APR: Wrong hdr size:%d\n", hdr_size); + return -EINVAL; + } + + if (hdr->pkt_size < APR_HDR_SIZE) { + dev_err(apr->dev, "APR: Wrong paket size\n"); + return -EINVAL; + } + + msg_type = APR_HDR_FIELD_MT(hdr->hdr_field); + if (msg_type >= APR_MSG_TYPE_MAX && msg_type != APR_BASIC_RSP_RESULT) { + dev_err(apr->dev, "APR: Wrong message type: %d\n", msg_type); + return -EINVAL; + } + + if (hdr->src_domain >= APR_DOMAIN_MAX || + hdr->dest_domain >= APR_DOMAIN_MAX || + hdr->src_svc >= APR_SVC_MAX || + hdr->dest_svc >= APR_SVC_MAX) { + dev_err(apr->dev, "APR: Wrong APR header\n"); + return -EINVAL; + } + + svc = hdr->dest_svc; + spin_lock_irqsave(&apr->svcs_lock, flags); + list_for_each_entry(p, &apr->svcs, node) { + if (svc == p->svc_id) { + c_svc = p; + if (c_svc->dev.driver) + adrv = to_apr_driver(c_svc->dev.driver); + break; + } + } + spin_unlock_irqrestore(&apr->svcs_lock, flags); + + if (!adrv) { + dev_err(apr->dev, "APR: service is not registered\n"); + return -EINVAL; + } + + data.payload_size = hdr->pkt_size - hdr_size; + data.opcode = hdr->opcode; + data.src_port = hdr->src_port; + data.dest_port = hdr->dest_port; + data.token = hdr->token; + data.msg_type = msg_type; + + if (data.payload_size > 0) + data.payload = buf + hdr_size; + + adrv->callback(c_svc, &data); + + return 0; +} + +static int apr_device_match(struct device *dev, struct device_driver *drv) +{ + struct apr_device *adev = to_apr_device(dev); + struct apr_driver *adrv = to_apr_driver(drv); + const struct apr_device_id *id = adrv->id_table; + + /* Attempt an OF style match first */ + if (of_driver_match_device(dev, drv)) + return 1; + + if (!id) + return 0; + + while (id->domain_id != 0 || id->svc_id != 0) { + if (id->domain_id == adev->domain_id && + id->svc_id == adev->svc_id) + return 1; + id++; + } + + return 0; +} + +static int apr_device_probe(struct device *dev) +{ + struct apr_device *adev = to_apr_device(dev); + struct apr_driver *adrv = to_apr_driver(dev->driver); + + return adrv->probe(adev); +} + +static int apr_device_remove(struct device *dev) +{ + struct apr_device *adev = to_apr_device(dev); + struct apr_driver *adrv; + struct apr *apr = dev_get_drvdata(adev->dev.parent); + + if (dev->driver) { + adrv = to_apr_driver(dev->driver); + if (adrv->remove) + adrv->remove(adev); + spin_lock(&apr->svcs_lock); + list_del(&adev->node); + spin_unlock(&apr->svcs_lock); + } + + return 0; +} + +static int apr_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct apr_device *adev = to_apr_device(dev); + int ret; + + ret = of_device_uevent_modalias(dev, env); + if (ret != -ENODEV) + return ret; + + return add_uevent_var(env, "MODALIAS= apr:%s", adev->name); +} + +struct bus_type aprbus_type = { + .name = "aprbus", + .match = apr_device_match, + .probe = apr_device_probe, + .uevent = apr_uevent, + .remove = apr_device_remove, +}; +EXPORT_SYMBOL_GPL(aprbus_type); + +static int apr_add_device(struct device *dev, struct device_node *np, + const struct apr_device_id *id) +{ + struct apr *apr = dev_get_drvdata(dev); + struct apr_device *adev = NULL; + + adev = kzalloc(sizeof(*adev), GFP_KERNEL); + if (!adev) + return -ENOMEM; + + spin_lock_init(&adev->lock); + + adev->svc_id = id->svc_id; + adev->domain_id = id->domain_id; + adev->version = id->svc_version; + if (np) + strncpy(adev->name, np->name, APR_NAME_SIZE); + else + strncpy(adev->name, id->name, APR_NAME_SIZE); + + dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, + id->domain_id, id->svc_id); + + adev->dev.bus = &aprbus_type; + adev->dev.parent = dev; + adev->dev.of_node = np; + adev->dev.release = apr_dev_release; + adev->dev.driver = NULL; + + spin_lock(&apr->svcs_lock); + list_add_tail(&adev->node, &apr->svcs); + spin_unlock(&apr->svcs_lock); + + dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev)); + + return device_register(&adev->dev); +} + +static void of_register_apr_devices(struct device *dev) +{ + struct apr *apr = dev_get_drvdata(dev); + struct device_node *node; + + for_each_child_of_node(dev->of_node, node) { + struct apr_device_id id = { {0} }; + + if (of_property_read_u32(node, "reg", &id.svc_id)) + continue; + + id.domain_id = apr->dest_domain_id; + + if (apr_add_device(dev, node, &id)) + dev_err(dev, "Failed to add arp %d svc\n", id.svc_id); + } +} + +static int apr_probe(struct rpmsg_device *rpdev) +{ + struct device *dev = &rpdev->dev; + struct apr *apr; + int ret; + + apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL); + if (!apr) + return -ENOMEM; + + ret = of_property_read_u32(dev->of_node, "qcom,dest-domain-id", + &apr->dest_domain_id); + if (ret) { + dev_err(dev, "APR Domain ID not specified in DT\n"); + return ret; + } + + dev_set_drvdata(dev, apr); + apr->ch = rpdev->ept; + apr->dev = dev; + spin_lock_init(&apr->svcs_lock); + INIT_LIST_HEAD(&apr->svcs); + + of_register_apr_devices(dev); + + return 0; +} + +static int apr_remove_device(struct device *dev, void *null) +{ + struct apr_device *adev = to_apr_device(dev); + + device_unregister(&adev->dev); + + return 0; +} + +static void apr_remove(struct rpmsg_device *rpdev) +{ + device_for_each_child(&rpdev->dev, NULL, apr_remove_device); +} + +/* + * __apr_driver_register() - Client driver registration with aprbus + * + * @drv:Client driver to be associated with client-device. + * @owner: owning module/driver + * + * This API will register the client driver with the aprbus + * It is called from the driver's module-init function. + */ +int __apr_driver_register(struct apr_driver *drv, struct module *owner) +{ + drv->driver.bus = &aprbus_type; + drv->driver.owner = owner; + + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(__apr_driver_register); + +/* + * apr_driver_unregister() - Undo effect of apr_driver_register + * + * @drv: Client driver to be unregistered + */ +void apr_driver_unregister(struct apr_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL_GPL(apr_driver_unregister); + +static const struct of_device_id apr_of_match[] = { + { .compatible = "qcom,apr"}, + { .compatible = "qcom,apr-v2"}, + {} +}; +MODULE_DEVICE_TABLE(of, apr_of_match); + +static struct rpmsg_driver apr_driver = { + .probe = apr_probe, + .remove = apr_remove, + .callback = apr_callback, + .drv = { + .name = "qcom,apr", + .of_match_table = apr_of_match, + }, +}; + +static int __init apr_init(void) +{ + int ret; + + ret = bus_register(&aprbus_type); + if (!ret) + ret = register_rpmsg_driver(&apr_driver); + + return ret; +} + +static void __exit apr_exit(void) +{ + bus_unregister(&aprbus_type); + unregister_rpmsg_driver(&apr_driver); +} + +subsys_initcall(apr_init); +module_exit(apr_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Qualcomm APR Bus"); diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 7d361be2e24f..2014bd19f28e 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -471,6 +471,17 @@ struct slim_device_id { kernel_ulong_t driver_data; }; +#define APR_NAME_SIZE 32 +#define APR_MODULE_PREFIX "apr:" + +struct apr_device_id { + char name[APR_NAME_SIZE]; + __u32 domain_id; + __u32 svc_id; + __u32 svc_version; + kernel_ulong_t driver_data; /* Data private to the driver */ +}; + #define SPMI_NAME_SIZE 32 #define SPMI_MODULE_PREFIX "spmi:" diff --git a/include/linux/soc/qcom/apr.h b/include/linux/soc/qcom/apr.h new file mode 100644 index 000000000000..604ea7f36a69 --- /dev/null +++ b/include/linux/soc/qcom/apr.h @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2011-2017, The Linux Foundation + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef __QCOM_APR_H_ +#define __QCOM_APR_H_ + +#include +#include +#include +#include + +#define APR_HDR_LEN(hdr_len) ((hdr_len)/4) + +/* + * HEADER field + * version:0:3 + * header_size : 4:7 + * message_type : 8:9 + * reserved: 10:15 + */ +#define APR_HDR_FIELD(msg_type, hdr_len, ver)\ + (((msg_type & 0x3) << 8) | ((hdr_len & 0xF) << 4) | (ver & 0xF)) + +#define APR_HDR_SIZE sizeof(struct apr_hdr) +#define APR_SEQ_CMD_HDR_FIELD APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \ + APR_HDR_LEN(APR_HDR_SIZE), \ + APR_PKT_VER) +/* Version */ +#define APR_PKT_VER 0x0 + +/* Command and Response Types */ +#define APR_MSG_TYPE_EVENT 0x0 +#define APR_MSG_TYPE_CMD_RSP 0x1 +#define APR_MSG_TYPE_SEQ_CMD 0x2 +#define APR_MSG_TYPE_NSEQ_CMD 0x3 +#define APR_MSG_TYPE_MAX 0x04 + +/* APR Basic Response Message */ +#define APR_BASIC_RSP_RESULT 0x000110E8 +#define APR_RSP_ACCEPTED 0x000100BE + +struct aprv2_ibasic_rsp_result_t { + uint32_t opcode; + uint32_t status; +}; + +/* hdr field Ver [0:3], Size [4:7], Message type [8:10] */ +#define APR_HDR_FIELD_VER(h) (h & 0x000F) +#define APR_HDR_FIELD_SIZE(h) ((h & 0x00F0) >> 4) +#define APR_HDR_FIELD_SIZE_BYTES(h) (((h & 0x00F0) >> 4) * 4) +#define APR_HDR_FIELD_MT(h) ((h & 0x0300) >> 8) + +struct apr_hdr { + uint16_t hdr_field; + uint16_t pkt_size; + uint8_t src_svc; + uint8_t src_domain; + uint16_t src_port; + uint8_t dest_svc; + uint8_t dest_domain; + uint16_t dest_port; + uint32_t token; + uint32_t opcode; +}; + +struct apr_client_message { + uint16_t payload_size; + uint16_t hdr_len; + uint16_t msg_type; + uint16_t src; + uint16_t dest_svc; + uint16_t src_port; + uint16_t dest_port; + uint32_t token; + uint32_t opcode; + void *payload; +}; + +/* Bits 0 to 15 -- Minor version, Bits 16 to 31 -- Major version */ +#define APR_SVC_MAJOR_VERSION(v) ((v >> 16) & 0xFF) +#define APR_SVC_MINOR_VERSION(v) (v & 0xFF) + +struct apr_device { + struct device dev; + uint16_t svc_id; + uint16_t domain_id; + uint32_t version; + char name[APR_NAME_SIZE]; + spinlock_t lock; + struct list_head node; +}; + +#define to_apr_device(d) container_of(d, struct apr_device, dev) + +struct apr_driver { + int (*probe)(struct apr_device *sl); + int (*remove)(struct apr_device *sl); + int (*callback)(struct apr_device *a, + struct apr_client_message *d); + struct device_driver driver; + const struct apr_device_id *id_table; +}; + +#define to_apr_driver(d) container_of(d, struct apr_driver, driver) + +/* + * use a macro to avoid include chaining to get THIS_MODULE + */ +#define apr_driver_register(drv) __apr_driver_register(drv, THIS_MODULE) + +int __apr_driver_register(struct apr_driver *drv, struct module *owner); +void apr_driver_unregister(struct apr_driver *drv); + +/** + * module_apr_driver() - Helper macro for registering a aprbus driver + * @__aprbus_driver: aprbus_driver struct + * + * Helper macro for aprbus drivers which do not do anything special in + * module init/exit. This eliminates a lot of boilerplate. Each module + * may only use this macro once, and calling it replaces module_init() + * and module_exit() + */ +#define module_apr_driver(__apr_driver) \ + module_driver(__apr_driver, apr_driver_register, \ + apr_driver_unregister) + +int apr_send_pkt(struct apr_device *adev, void *buf); + +#endif /* __QCOM_APR_H_ */ From patchwork Wed Apr 18 15:31:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133646 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp35987ljf; Wed, 18 Apr 2018 08:36:36 -0700 (PDT) X-Google-Smtp-Source: AIpwx48KDRSp+7DkCuAM4DFH9SiMqRBMlAJDbCHhHc/GaxX5lo5pww6df0qRaCu8odfciB+Cn7UO X-Received: by 10.28.72.67 with SMTP id v64mr2169134wma.159.1524065796203; Wed, 18 Apr 2018 08:36:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065796; cv=none; d=google.com; s=arc-20160816; b=onQz7OEwAIQk2AnBX90yraejhvfbKFaDJwJsMXPvF0Ng9PIf8rk7O2apLdCgITgnRD pJlBFeyT3llFKzwTjZSwEUBqZozmhnByMUTKvwc9st8uWOhxY0W3ek2WaJu6s0hYl3WY BeTzAD3bU8MXzWpsn7X2ntSVdR2EoGKRqM+45ebH7Exxid1cQS/GCVtixjvoCd/1XU5p sFyFWetwQGfF/KoowOd5NnIGk8Udl9MAW1fmaarGWUyx+0Q9OKX6hQ9sfe1avPDDgx0i fp97I7nPaoowTqVvoTCLGVbQ/nXeatbCs1RBnqEImew20pkt2e0Btt1sXEUdNLUSQah3 yJzg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=DWPyW2qbPMGf3IOyPqyRmeqCM4kz00LDZSsFJe4Q9EM=; b=maaeSttbkIdEgF67aAQbKsQ6zpeCnjE/2pyEIPgKnkqFCvXvSvEjI8pd1EP1FNphER I1Ou2+20BqucCDxI1BqRyz4CCo1WmPT5kbzXHKk8OJsUQEWMP7o3UZIikhasN/w03cIf A+0Lomno7Tbc9O8cqN20fBcruFTB29B8wdlcXqHhTYUDOYzgZb3HekioHoKdAP8REA+g xcq6U4cVixboojHZMz4Ewgi8zQOFdHzsWci1wWoOws3LMJGvazJt60rasG8RuGICL/E4 LdKOmDvcErh8VZEneIUGQq4e1R+2vaR0OOjjtrtfzJBAN/pcsBZ/8DMblyUjlyL9e6+A ISQw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=cxocTNwQ; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id j67-v6si1160982wrj.91.2018.04.18.08.36.36; Wed, 18 Apr 2018 08:36:36 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=cxocTNwQ; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id D84DD2676B8; Wed, 18 Apr 2018 17:36:08 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 8FC4D26768E; Wed, 18 Apr 2018 17:36:02 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f193.google.com (mail-wr0-f193.google.com [209.85.128.193]) by alsa0.perex.cz (Postfix) with ESMTP id 4D419267673 for ; Wed, 18 Apr 2018 17:36:00 +0200 (CEST) Received: by mail-wr0-f193.google.com with SMTP id u11-v6so6022876wri.12 for ; Wed, 18 Apr 2018 08:36:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=kP/L6rAg1fnSJtUlVDy+9AkvTYppSghZt3Q5chAsIrY=; b=cxocTNwQM+CR5RmekJBJbkKaJeWAf1i1RTTUtbWDh3Xz3UrABuwOhYPbvM4b2g41En 42OTa0R0DkFtUNuX/fY7/RZSL5IvTEy/TzhfUkjs3fWZqQGAECkEMQnhXNgRxAnp52NH +caVutoC1qWm+HzSxn8xDYAgMKWJH6Pt8AvHQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=kP/L6rAg1fnSJtUlVDy+9AkvTYppSghZt3Q5chAsIrY=; b=aiNvhM9ekeNyVqX6/i73LpYSPb/Qkn7UjPWIPOfeOmZXq3IOwyaARxZKWyF6F+vSqj 9r0NSdozc9ySdwSC1wexa4XtZK2St9tq9eyF2c/o9YKDGILHQupO2vxDF0Dyy2F+eflK U9LkdFxUUyfMy3Rzc+ndDoh8IsDEBajIsJUQ/i02c3G79ccFiaxMRPoiqueD5JId5GCG snCbrE+t/rcCD0xiJTaTbpqGNb+5235Tw+mBVWVS+yveazatS3v8dasCux8EuAz+ze1q KDY/FxgG5+/TDPQmoHUco/LZE0EVrHAdeduGxSIhAIiBC7vylsIOMWcI6Kblyy2wRxzD CRKw== X-Gm-Message-State: ALQs6tBeFK+clrm4HYTRPdwg4O0ZbInYoQrkg5qy8wjQYlTHfHCchaPW E4g5u22c2+n/jFzlyi59iVn2Dw== X-Received: by 10.28.241.18 with SMTP id p18mr2260974wmh.40.1524065759914; Wed, 18 Apr 2018 08:35:59 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.35.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:35:59 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:37 +0100 Message-Id: <20180418153157.1960-4-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 03/23] ASoC: qdsp6: q6common: Add qdsp6 helper functions X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch adds some common helper functions like translating dsp error to linux error codes and channel mappings etc. These functions are used in all the following qdsp6 drivers. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- sound/soc/qcom/Kconfig | 13 ++++++++ sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6dsp-common.c | 66 +++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6dsp-common.h | 24 ++++++++++++++ sound/soc/qcom/qdsp6/q6dsp-errno.h | 51 ++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+) create mode 100644 sound/soc/qcom/qdsp6/Makefile create mode 100644 sound/soc/qcom/qdsp6/q6dsp-common.c create mode 100644 sound/soc/qcom/qdsp6/q6dsp-common.h create mode 100644 sound/soc/qcom/qdsp6/q6dsp-errno.h -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 8ec9a074b38b..8247ade16dbe 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -43,3 +43,16 @@ config SND_SOC_APQ8016_SBC Support for Qualcomm Technologies LPASS audio block in APQ8016 SOC-based systems. Say Y if you want to use audio devices on MI2S. + +config SND_SOC_QDSP6_COMMON + tristate + +config SND_SOC_QDSP6 + tristate "SoC ALSA audio driver for QDSP6" + depends on QCOM_APR && HAS_DMA + select SND_SOC_QDSP6_COMMON + help + To add support for MSM QDSP6 Soc Audio. + This will enable sound soc platform specific + audio drivers. This includes q6asm, q6adm, + q6afe interfaces to DSP using apr. diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile new file mode 100644 index 000000000000..accebdb49306 --- /dev/null +++ b/sound/soc/qcom/qdsp6/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o diff --git a/sound/soc/qcom/qdsp6/q6dsp-common.c b/sound/soc/qcom/qdsp6/q6dsp-common.c new file mode 100644 index 000000000000..c342a073144c --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6dsp-common.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation +// Copyright (c) 2018, Linaro Limited + +#include "q6dsp-common.h" +#include +#include +#include +#include + +int q6dsp_map_channels(u8 ch_map[PCM_FORMAT_MAX_NUM_CHANNEL], int ch) +{ + memset(ch_map, 0, PCM_FORMAT_MAX_NUM_CHANNEL); + + switch (ch) { + case 1: + ch_map[0] = PCM_CHANNEL_FC; + break; + case 2: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_FR; + break; + case 3: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_FR; + ch_map[2] = PCM_CHANNEL_FC; + break; + case 4: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_FR; + ch_map[2] = PCM_CHANNEL_LS; + ch_map[3] = PCM_CHANNEL_RS; + break; + case 5: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_FR; + ch_map[2] = PCM_CHANNEL_FC; + ch_map[3] = PCM_CHANNEL_LS; + ch_map[4] = PCM_CHANNEL_RS; + break; + case 6: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_FR; + ch_map[2] = PCM_CHANNEL_LFE; + ch_map[3] = PCM_CHANNEL_FC; + ch_map[4] = PCM_CHANNEL_LS; + ch_map[5] = PCM_CHANNEL_RS; + break; + case 8: + ch_map[0] = PCM_CHANNEL_FL; + ch_map[1] = PCM_CHANNEL_FR; + ch_map[2] = PCM_CHANNEL_LFE; + ch_map[3] = PCM_CHANNEL_FC; + ch_map[4] = PCM_CHANNEL_LS; + ch_map[5] = PCM_CHANNEL_RS; + ch_map[6] = PCM_CHANNEL_LB; + ch_map[7] = PCM_CHANNEL_RB; + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(q6dsp_map_channels); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/qdsp6/q6dsp-common.h b/sound/soc/qcom/qdsp6/q6dsp-common.h new file mode 100644 index 000000000000..32386f4a6432 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6dsp-common.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef __Q6DSP_COMMON_H__ +#define __Q6DSP_COMMON_H__ + +#include + +#define PCM_FORMAT_MAX_NUM_CHANNEL 8 +#define PCM_CHANNEL_NULL 0 + +#define PCM_CHANNEL_FL 1 /* Front left channel. */ +#define PCM_CHANNEL_FR 2 /* Front right channel. */ +#define PCM_CHANNEL_FC 3 /* Front center channel. */ +#define PCM_CHANNEL_LS 4 /* Left surround channel. */ +#define PCM_CHANNEL_RS 5 /* Right surround channel. */ +#define PCM_CHANNEL_LFE 6 /* Low frequency effect channel. */ +#define PCM_CHANNEL_CS 7 /* Center surround channel; Rear center ch */ +#define PCM_CHANNEL_LB 8 /* Left back channel; Rear left channel. */ +#define PCM_CHANNEL_RB 9 /* Right back channel; Rear right channel. */ +#define PCM_CHANNELS 10 /* Top surround channel. */ + +int q6dsp_map_channels(u8 ch_map[PCM_FORMAT_MAX_NUM_CHANNEL], int ch); + +#endif /* __Q6DSP_COMMON_H__ */ diff --git a/sound/soc/qcom/qdsp6/q6dsp-errno.h b/sound/soc/qcom/qdsp6/q6dsp-errno.h new file mode 100644 index 000000000000..6285e1782824 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6dsp-errno.h @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef __Q6DSP_ERR_NO_H__ +#define __Q6DSP_ERR_NO_H__ +#include + +/* Success. The operation completed with no errors. */ +#define ADSP_EOK 0x00000000 +/* General failure. */ +#define ADSP_EFAILED 0x00000001 +/* Bad operation parameter. */ +#define ADSP_EBADPARAM 0x00000002 +/* Unsupported routine or operation. */ +#define ADSP_EUNSUPPORTED 0x00000003 +/* Unsupported version. */ +#define ADSP_EVERSION 0x00000004 +/* Unexpected problem encountered. */ +#define ADSP_EUNEXPECTED 0x00000005 +/* Unhandled problem occurred. */ +#define ADSP_EPANIC 0x00000006 +/* Unable to allocate resource. */ +#define ADSP_ENORESOURCE 0x00000007 +/* Invalid handle. */ +#define ADSP_EHANDLE 0x00000008 +/* Operation is already processed. */ +#define ADSP_EALREADY 0x00000009 +/* Operation is not ready to be processed. */ +#define ADSP_ENOTREADY 0x0000000A +/* Operation is pending completion. */ +#define ADSP_EPENDING 0x0000000B +/* Operation could not be accepted or processed. */ +#define ADSP_EBUSY 0x0000000C +/* Operation aborted due to an error. */ +#define ADSP_EABORTED 0x0000000D +/* Operation preempted by a higher priority. */ +#define ADSP_EPREEMPTED 0x0000000E +/* Operation requests intervention to complete. */ +#define ADSP_ECONTINUE 0x0000000F +/* Operation requests immediate intervention to complete. */ +#define ADSP_EIMMEDIATE 0x00000010 +/* Operation is not implemented. */ +#define ADSP_ENOTIMPL 0x00000011 +/* Operation needs more data or resources. */ +#define ADSP_ENEEDMORE 0x00000012 +/* Operation does not have memory. */ +#define ADSP_ENOMEMORY 0x00000014 +/* Item does not exist. */ +#define ADSP_ENOTEXIST 0x00000015 +/* Max count for adsp error code sent to HLOS*/ + +#endif /*__Q6DSP_ERR_NO_H__ */ From patchwork Wed Apr 18 15:31:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133649 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp36194ljf; Wed, 18 Apr 2018 08:36:47 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/WJagqht8nSVJ+X0+hEAF5ZeL4ve3S8roWG23gtYIlOCuI8oW8eOLY94TQnLzhouILdmrj X-Received: by 10.28.215.136 with SMTP id o130mr2284302wmg.41.1524065807385; Wed, 18 Apr 2018 08:36:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065807; cv=none; d=google.com; s=arc-20160816; b=ye+wxKfQ5W9Ys1AHHgcAAsFmLUcOjhlAnXvMkxZmP0r5YweX4HSXc6LDPy6vmZ0HFo EBuftDglDrm+qQdPgGyjT38xNAbp+j90A3PBNQIVaj9bqGSrP8Cgn0GpP67Ju4KZv/e8 u2q8+4OFpAZiGab4/kkAhS9QShigz85oXEEC+LkOTDauJG5Y9W0idt1MOVYXw3a1wWhC dSRXo88xvYJYxx6GSalHqLbxNspGZ+oSYhqiGqlaM0CVLJ5611sI408QhwRMIVkQ04qt QYFzAxilwHwvg0Vj8T3mKs/efMuCPbnq0GzrxjSYW9NXeSmRjN6caEEJzMd+z5MgBrXB esMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=IAoQyFeD/vD6ewJ3hIjWXks2KdTWIzBQLd/uLdPZQA4=; b=loNAPE/Nx4VeQ9COgef3KhZaoqhZUQgNmIMPEw2Z4D26hqXXqgfqMe+MgFzc0ysYqh 4pxdaeYfHXNySNzrZJsesTY0jSwpLioVKq25o6kftD+AqDouCBKkqv86nmyiirrIfGy+ Eu4BtnlLcYIZLhYujc18o6aBk1XiepAOKMuBdUCE0PqllMvPDMzt+rkV7tVrjWopMBb4 wn9tkyurSQcd13V/mpW/yiUJgxVv7NsD+bb4OIEMEFtfG5FYvDPH7xdrO5h7/blEZDWT 8/o4VipGnSD5x7jbTeWxRWtCODT5EvXXi1ieqiBMiTvazz69o85FCJGyRJoQ1SoPt4RS 6/5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=jK8vVqOP; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id a20si1297923wma.36.2018.04.18.08.36.47; Wed, 18 Apr 2018 08:36:47 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=jK8vVqOP; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 53F4A2676A9; Wed, 18 Apr 2018 17:36:10 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 27F262676A1; Wed, 18 Apr 2018 17:36:04 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f194.google.com (mail-wr0-f194.google.com [209.85.128.194]) by alsa0.perex.cz (Postfix) with ESMTP id 65E72267673 for ; Wed, 18 Apr 2018 17:36:01 +0200 (CEST) Received: by mail-wr0-f194.google.com with SMTP id f14-v6so6044044wre.4 for ; Wed, 18 Apr 2018 08:36:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uWOPYaQGfbjAQXVVVC6kkZny6WY+Ma8pi7H5YCtdQWM=; b=jK8vVqOPmP4Q0Tl1jofiRmdoJTEDSFGXogedht8x7SWs/edx/W2/gY0au9v2/xz4K2 n5g0RTYhAa5EAOoS8SdEyDrHrUVTe8LA/ANyugQc7/n+XNlYBGe3sO/6iM9QI/JUtz4v fruRXU++C/BySkk+eDtCjUiF5sgt08XVIG8U0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uWOPYaQGfbjAQXVVVC6kkZny6WY+Ma8pi7H5YCtdQWM=; b=ONkV3/Z8I2tC4zD4lHj+RG6lgZR/v6fjwR/yqW4/iFcMar5D1ws/3USRfNcltyUMdR OjLWPSKNFH4I1oFJzEmEiFQBc56bbEIPN8TSYy4t3s9ti3nYCe0RYZmBNZf6ryEFHtE2 5+zZtZdjxiTMvF0MCpZRDOMLPcHN4eMFE0Q1FIMV728lAtPVJpyOh8g2wR5VehHuI0xY eyL0kHsuqkLpIevufx82IDlVN6zR27A/YB0Ee6lcf9UaTkeBCXaFZ3a+mozBM2jWLwk2 2ZgnXTEUCCLmJ3eU7gFdudhqDjPXZlF0eDL6YCmHbG80YgoqGyJMVklsb5eoDprwAxU7 E0zQ== X-Gm-Message-State: ALQs6tBRiYxVGDgteg4z1RWiVIhlxO4Xrx+1kzBzhJgdhzmrbDMAhZEK kY16O46MVZttgXtHQVWjBnbhiQ== X-Received: by 10.28.18.2 with SMTP id 2mr2147274wms.143.1524065761363; Wed, 18 Apr 2018 08:36:01 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.35.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:36:00 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:38 +0100 Message-Id: <20180418153157.1960-5-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 04/23] ASoC: qdsp6: dt-bindings: Add q6afe dt bindings X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch add DT bindings for AFE (Audio Frontend) DSP module. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- .../devicetree/bindings/sound/qcom,q6afe.txt | 88 ++++++++++++++++++++++ include/dt-bindings/sound/qcom,q6afe.h | 31 ++++++++ 2 files changed, 119 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,q6afe.txt create mode 100644 include/dt-bindings/sound/qcom,q6afe.h -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/Documentation/devicetree/bindings/sound/qcom,q6afe.txt b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt new file mode 100644 index 000000000000..3925726a3319 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt @@ -0,0 +1,88 @@ +Qualcomm Audio Front End (Q6AFE) binding + +AFE is one of the APR audio service on Q6DSP +Please refer to qcom,apr.txt for details of the common apr service bindings +used by all apr services. + +- but must contain the following property: + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,afe-v." + Or "qcom,afe" where the version number can be queried + from DSP. + example "qcom,afe-v2.0" + += AFE DAIs (Digial Audio Interface) +"dais" subnode of the AFE node represents dai specific configuration + +- #sound-dai-cells + Usage: required + Value type: + Definition: Must be 1 + +- reg + Usage: required + Value type: + Definition: Must be dai id + +- qcom,sd-lines + Usage: required for mi2s interface + Value type: + Definition: Must be list of serial data lines used by this dai. + should be one or more of the 1-4 sd lines. + += EXAMPLE + +q6afe { + compatible = "qcom,q6afe"; + reg = ; + + dais { + #sound-dai-cells = <1>; + hdmi@1 { + reg = <1>; + }; + + prim-mi2s-rx@16 { + reg = <16>; + qcom,sd-lines = <1 3>; + }; + + prim-mi2s-tx@17 { + reg = <17>; + qcom,sd-lines = <2>; + }; + + sec-mi2s-rx@18 { + reg = <18>; + qcom,sd-lines = <1 4>; + }; + + sec-mi2s-tx@19 { + reg = <19>; + qcom,sd-lines = <2>; + }; + + tert-mi2s-rx@20 { + reg = <20>; + qcom,sd-lines = <2 4>; + }; + + tert-mi2s-tx@21 { + reg = <21>; + qcom,sd-lines = <1>; + }; + + quat-mi2s-rx@22 { + reg = <22>; + qcom,sd-lines = <1>; + }; + + quat-mi2s-tx@23 { + reg = <23>; + qcom,sd-lines = <2>; + }; + }; +}; diff --git a/include/dt-bindings/sound/qcom,q6afe.h b/include/dt-bindings/sound/qcom,q6afe.h new file mode 100644 index 000000000000..3c7868394889 --- /dev/null +++ b/include/dt-bindings/sound/qcom,q6afe.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef __DT_BINDINGS_Q6_AFE_H__ +#define __DT_BINDINGS_Q6_AFE_H__ + +/* Audio Front End (AFE) virtual ports IDs */ +#define HDMI_RX 1 +#define SLIMBUS_0_RX 2 +#define SLIMBUS_0_TX 3 +#define SLIMBUS_1_RX 4 +#define SLIMBUS_1_TX 5 +#define SLIMBUS_2_RX 6 +#define SLIMBUS_2_TX 7 +#define SLIMBUS_3_RX 8 +#define SLIMBUS_3_TX 9 +#define SLIMBUS_4_RX 10 +#define SLIMBUS_4_TX 11 +#define SLIMBUS_5_RX 12 +#define SLIMBUS_5_TX 13 +#define SLIMBUS_6_RX 14 +#define SLIMBUS_6_TX 15 +#define PRIMARY_MI2S_RX 16 +#define PRIMARY_MI2S_TX 17 +#define SECONDARY_MI2S_RX 18 +#define SECONDARY_MI2S_TX 19 +#define TERTIARY_MI2S_RX 20 +#define TERTIARY_MI2S_TX 21 +#define QUATERNARY_MI2S_RX 22 +#define QUATERNARY_MI2S_TX 23 + +#endif /* __DT_BINDINGS_Q6_AFE_H__ */ + From patchwork Wed Apr 18 15:31:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133650 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp36408ljf; Wed, 18 Apr 2018 08:36:59 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+3Sm9kifWBTC0PY6aBD7KTecg8VXUKFiuHIEHn/n1O7SWD1AYBhMscqDyEIg2mCnGI1Tvc X-Received: by 2002:adf:b1cd:: with SMTP id r13-v6mr820726wra.221.1524065819650; Wed, 18 Apr 2018 08:36:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065819; cv=none; d=google.com; s=arc-20160816; b=jGdPWiJ0nDCRVw38aiYKHQ0ZS8I8UPnTiEtwRUsmfjmPEt6rixIoQLcewHn87fL9RP eA7X7ZVA+iY++ccMlidjWYZwararfT+GQOR1Omfdv1gBueJf6ziB/pXNAMJhvDAdYu54 ecmG18c3TkoNi9m0b5Kp6kxL9PxycVSp0UWZjfg2U9/wwjwbJbbERHlp/9eIiRb+12Y2 /HOQ/QL8YiT0aP1yPl0+8gizpRNQpP1wSLTTz14hn8MHGn24NTa+Sd/WwLGy1L9ebWXA gmvkf131GteRPOs4a2cVcE2tSqsJVnvewvOnqXOeHPZLRGwzSGtmG2JoQmFkaJTtAzsW /Kpw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=RI8UIshAc/Lfdj4OTOWLDk1xKpTddZQYDMh6tr+U8mI=; b=M+Oy5MvmtLkYSBthDKAIO1lFkSROheF0RLrJbwA6h3IQbkXKzK+aLG5kXaRqG8LX8v b+b1vB9oWi8+blczgYtyUM34/+VlbP8Obuygw8CUa3RcDJbjwoliJALSTkocNoCnUjhy mKTTkGJ4iIUgc7EvmW/jarHSQaYztKSXjmJ/bhLBh4xwHe6B8B6P+ch+S6SlWa65dAaS wpbMWwBBLdxybsNfGXPdBpsEy95V8cF5VJZOr+DeB9udD1wr3i+l/RrF3CzK3bVyOZma CSTWBtpJICJ8M5H0MelKTOP3evU9rcakz06fbejdRKhZBMhNeFAR2ydf3NCy28GANC7U Y8hQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=PO0yyAel; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id l73si1394315wma.7.2018.04.18.08.36.59; Wed, 18 Apr 2018 08:36:59 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=PO0yyAel; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id CB15B2676CE; Wed, 18 Apr 2018 17:36:13 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 173B52676A5; Wed, 18 Apr 2018 17:36:05 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f195.google.com (mail-wr0-f195.google.com [209.85.128.195]) by alsa0.perex.cz (Postfix) with ESMTP id 7E611267673 for ; Wed, 18 Apr 2018 17:36:03 +0200 (CEST) Received: by mail-wr0-f195.google.com with SMTP id z73-v6so6063608wrb.0 for ; Wed, 18 Apr 2018 08:36:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zDiIYZe9YgJwUztyp9RS8IzxicvfUrBoFsHgDcnHlNQ=; b=PO0yyAelhl9uZMi1ZP8xnDu8s2ChPIIumltWkLB2nxhcuNupo/txKy9PAZa2gXr6Ix BkuKw2NNKROtlJ21E9YS4utdwlJ6ReXUO54qJe34apUbKRx5XtgpAlNu7JDo7bwEMJWT pnNmEgAvFIciWPiUqvLGFKXhJM/l5LzZC/H2g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zDiIYZe9YgJwUztyp9RS8IzxicvfUrBoFsHgDcnHlNQ=; b=dXOkWpFpUkpJlV/Pa0bxfYSrzvL7ttLtPymse9Z16DObldl1Sb7U/b+sLTxy2B7/gE DatA774m7lgtTTJuFLN8G1xwe8HY5EJY95r5lBb/JN9MCsqEgFccKmyBkWnWu9m/RAq5 H30H6lVv41YzvIIKe+NihBAGTXCl4mO1lHkMTsZxWvQZTwd/pn5N+Q/0ZGgcJb3bNF5O dVOUQcg653cg0D80B2qOrs22861RO5FN442Ahv/9GPN3kzvUopQBOPSWjpAUb0OVpMlJ oBx2YnUXDomoNcYbsMCja4ozW2adssrsQAAasJJO3eWj6IR6jiM72Gh9NG4IF86gZ6bC Ksjw== X-Gm-Message-State: ALQs6tCb3duQRIcXwbQkSBoWACkKewyXz7ZZDu4/ujI2nLR3odOzfiZ8 wzYJEMG4fKDjsA3oGszjH97nFA== X-Received: by 10.28.53.6 with SMTP id c6mr2160608wma.10.1524065762643; Wed, 18 Apr 2018 08:36:02 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.36.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:36:02 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:39 +0100 Message-Id: <20180418153157.1960-6-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 05/23] ASoC: qdsp6: dt-bindings: Add q6adm dt bindings X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch add DT bindings for ADM (Audio Device Manager) DSP module. This module implements mixer controls to setup the connections between AFE ports and ASM streams. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- .../devicetree/bindings/sound/qcom,q6adm.txt | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,q6adm.txt -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/Documentation/devicetree/bindings/sound/qcom,q6adm.txt b/Documentation/devicetree/bindings/sound/qcom,q6adm.txt new file mode 100644 index 000000000000..f1e2df8d2ea8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,q6adm.txt @@ -0,0 +1,33 @@ +Qualcomm Audio Device Manager (Q6ADM) binding + +Q6ADM is one of the APR audio service on Q6DSP. +Please refer to qcom,apr.txt for details of the coommon apr service bindings +used by the apr service device. + +- but must contain the following property: + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,adm-v.". + Or "qcom,adm" where the version number can be queried + from DSP. + example "qcom,adm-v2.0" + + += ADM routing +"routing" subnode of the ADM node represents adm routing specific configuration + +- #sound-dai-cells + Usage: required + Value type: + Definition: Must be 0 + += EXAMPLE +q6adm { + compatible = "qcom,q6adm"; + reg = ; + q6routing: routing { + #sound-dai-cells = <0>; + }; +}; From patchwork Wed Apr 18 15:31:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133653 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp36890ljf; Wed, 18 Apr 2018 08:37:29 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+Nt+TYhYsx4FWBjdPbHF+awdNbHTYBhSniNAHaVEToHtT5OmiIUpl+W8kQDZXIzYjOjXf0 X-Received: by 2002:adf:e1ce:: with SMTP id l14-v6mr1933162wri.148.1524065849012; Wed, 18 Apr 2018 08:37:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065849; cv=none; d=google.com; s=arc-20160816; b=cQJdQ0KLugGmtOP7lGTJSc6UoVw6e+1A4mlGfc/VQOpoaB7CdPgtQ4jxVLT5OfOWr8 C679u+a8mlD9CxgdBxAxdDgWjBLHTZcXoeBJe9nLVugg8QtGDAqvPW2xp3MMYMwcCHrF jjCIbsPI2YUzmZ+aqVl3Qmk5UQr3LB8VkCH1kHbVKNCybokYvPAdL8kve+q+khZIb9kw jc5K28IMqYlM+u0c9DyTaGluenaF8mS+n9x4k+s5LglqDzXlkVqPghUknXSAtgUNs8JC TFywtRpbhISjXcoRF0X9fECR9IJrUiYL2+3VSSNMG/Ec5fQ3ZRP2UkFF5uB6tf39v9wX Tn3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=WoekuGll6AJoU4e09n9fglw+zUPQNu70HYuZdOBYRm4=; b=wxezVMqzYwv76PEkOCsgpxt1jObUd7jFGz+xptVPjeN2UgPx2isfn5OEXZugL/T7/Y iO1ddhKshCinuDO8kIVN/Av0dx56rxemHJRda0XAxUXMMog//CcQnxT8omLmnKH0uckC qfKjb04UGWg0nx68p1wnat71z11LQZPfM4uOQka20EJiT1P+vOZd9JYZhMP+86oYs/rZ s+9l94t4M9jyhrYDwJ3zvB/JKLwJTB1fkFLgxga6BVZYv7rul4p74KY3CW4OVJTqzzWo /TsmHkgN+jDqJRAP2CRGDGrTGZCvIbRhi1+lJHoLOXqM+Fn7eBYoAdUl4PhCTR/ikwEz Wx2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=ZvYXAg7T; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id 142si1370184wme.14.2018.04.18.08.37.28; Wed, 18 Apr 2018 08:37:28 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=ZvYXAg7T; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id B43862676E3; Wed, 18 Apr 2018 17:36:19 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id ACE6D2676CC; Wed, 18 Apr 2018 17:36:11 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f196.google.com (mail-wr0-f196.google.com [209.85.128.196]) by alsa0.perex.cz (Postfix) with ESMTP id EB0F32676AA for ; Wed, 18 Apr 2018 17:36:05 +0200 (CEST) Received: by mail-wr0-f196.google.com with SMTP id w3-v6so6051271wrg.2 for ; Wed, 18 Apr 2018 08:36:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=k+PmEZg2t3/rUgsUwlUw/fqM4fJLgw0uHZE79Hn9l14=; b=ZvYXAg7TD0kmbwxl54BsJ5dlbBEvcq7XVMuHKXf689jpxMqxacbDi3aYXjPsO4tx6t ng7lYT+zpAqV+phFqmAt5dSiI4RC1zghhf+1l4Z1oaiXP32kgaa588iztO3qX6OsNkRZ 7L+4iZb/0eNj1n9wIkae/B81yw6FWoEa5I7Go= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=k+PmEZg2t3/rUgsUwlUw/fqM4fJLgw0uHZE79Hn9l14=; b=jHmgRQnLuHwN2o5tGuqyx17altxM3oKlL0hMOiC9Pnssnr8HmNPG01rUSUyb6jep4R 9M84gBVhBmi41kZCsOQ2E6m1LaQuTj4wUbe0T5HVHpFJ6fiBWawL2FOTP20QIUOijH2v 69Q7H0rq7SI0sBtPCpt84cEWGOdJ3V3EDu/FrTo53Ti5/hmML5JgnADNEgXIYxFzAYY6 gHV/UnSOMd/icqIVasBxg0g7FHNCxmesxHhelklaJbHnqFL45ix4kTVOOpflZfUs65hL JBFuk1jsRF5fDK0P7l2bqa0VYDi5PkB8QAhsi3Z7jMCf/FBumCcO67GEftAUA6FWSM0Y 5LCQ== X-Gm-Message-State: ALQs6tAKCxHKFK3Py72kFJ7ZLOtzIteRK3Jx0iLvLLLmCbclR8ikA3sy 6wyQCsPf6UQD8dKHCMb24uI10g== X-Received: by 10.28.90.138 with SMTP id o132mr2039660wmb.32.1524065765279; Wed, 18 Apr 2018 08:36:05 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.36.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:36:04 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:41 +0100 Message-Id: <20180418153157.1960-8-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 07/23] ASoC: qdsp6: q6afe: Add q6afe driver X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch adds support to Q6AFE (Audio Front End) module on Q6DSP. AFE module sits right at the other end of cpu where the codec/audio devices are connected. AFE provides abstraced interfaces to both hardware and virtual devices. Each AFE tx/rx port can be configured to connect to one of the hardware devices like codec, hdmi, slimbus, i2s and so on. AFE services include starting, stopping, and if needed, any configurations of the ports. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- sound/soc/qcom/Kconfig | 4 + sound/soc/qcom/Makefile | 3 + sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6afe.c | 503 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6afe.h | 35 +++ 5 files changed, 546 insertions(+) create mode 100644 sound/soc/qcom/qdsp6/q6afe.c create mode 100644 sound/soc/qcom/qdsp6/q6afe.h -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 8247ade16dbe..f50c76d712c0 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -47,10 +47,14 @@ config SND_SOC_APQ8016_SBC config SND_SOC_QDSP6_COMMON tristate +config SND_SOC_QDSP6_AFE + tristate + config SND_SOC_QDSP6 tristate "SoC ALSA audio driver for QDSP6" depends on QCOM_APR && HAS_DMA select SND_SOC_QDSP6_COMMON + select SND_SOC_QDSP6_AFE help To add support for MSM QDSP6 Soc Audio. This will enable sound soc platform specific diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index d5280355c24f..0276717917c0 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -16,3 +16,6 @@ snd-soc-apq8016-sbc-objs := apq8016_sbc.o obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o + +#DSP lib +obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/ diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index accebdb49306..9ec951e0833b 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o +obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c new file mode 100644 index 000000000000..ec328fa7dd1e --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -0,0 +1,503 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation +// Copyright (c) 2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6dsp-errno.h" +#include "q6core.h" +#include "q6afe.h" + +/* AFE CMDs */ +#define AFE_PORT_CMD_DEVICE_START 0x000100E5 +#define AFE_PORT_CMD_DEVICE_STOP 0x000100E6 +#define AFE_PORT_CMD_SET_PARAM_V2 0x000100EF +#define AFE_PORT_CMDRSP_GET_PARAM_V2 0x00010106 +#define AFE_PARAM_ID_HDMI_CONFIG 0x00010210 +#define AFE_MODULE_AUDIO_DEV_INTERFACE 0x0001020C + +/* Port IDs */ +#define AFE_API_VERSION_HDMI_CONFIG 0x1 +#define AFE_PORT_ID_MULTICHAN_HDMI_RX 0x100E +#define TIMEOUT_MS 1000 +#define AFE_CMD_RESP_AVAIL 0 +#define AFE_CMD_RESP_NONE 1 + +struct q6afe { + struct apr_device *apr; + struct device *dev; + struct q6core_svc_api_info ainfo; + struct mutex lock; + struct list_head port_list; + spinlock_t port_list_lock; + struct list_head node; + struct platform_device *pdev_dais; +}; + +struct afe_port_cmd_device_start { + struct apr_hdr hdr; + u16 port_id; + u16 reserved; +} __packed; + +struct afe_port_cmd_device_stop { + struct apr_hdr hdr; + u16 port_id; + u16 reserved; +/* Reserved for 32-bit alignment. This field must be set to 0.*/ +} __packed; + +struct afe_port_param_data_v2 { + u32 module_id; + u32 param_id; + u16 param_size; + u16 reserved; +} __packed; + +struct afe_port_cmd_set_param_v2 { + u16 port_id; + u16 payload_size; + u32 payload_address_lsw; + u32 payload_address_msw; + u32 mem_map_handle; +} __packed; + +struct afe_param_id_hdmi_multi_chan_audio_cfg { + u32 hdmi_cfg_minor_version; + u16 datatype; + u16 channel_allocation; + u32 sample_rate; + u16 bit_width; + u16 reserved; +} __packed; + +union afe_port_config { + struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch; +} __packed; + +struct q6afe_port { + wait_queue_head_t wait; + union afe_port_config port_cfg; + int token; + int id; + int cfg_type; + struct q6afe *afe; + struct list_head node; +}; + +struct afe_audioif_config_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; + union afe_port_config pcfg; +} __packed; + +struct afe_port_map { + int port_id; + int token; + int is_rx; + int is_dig_pcm; +}; + +/** + * Mapping between Virtual Port IDs to DSP AFE Port ID + * On B Family SoCs DSP Port IDs are consistent across multiple SoCs + * on A Family SoCs DSP port IDs are same as virtual Port IDs. + **/ + +static struct afe_port_map port_maps[AFE_PORT_MAX] = { + [HDMI_RX] = { AFE_PORT_ID_MULTICHAN_HDMI_RX, HDMI_RX, 1, 1}, +}; + +static struct q6afe_port *afe_find_port(struct q6afe *afe, int token) +{ + struct q6afe_port *p = NULL; + unsigned long flags; + + spin_lock_irqsave(&afe->port_list_lock, flags); + list_for_each_entry(p, &afe->port_list, node) + if (p->token == token) + break; + + spin_unlock_irqrestore(&afe->port_list_lock, flags); + return p; +} + +static int q6afe_callback(struct apr_device *adev, + struct apr_client_message *data) +{ + struct q6afe *afe = dev_get_drvdata(&adev->dev); + struct aprv2_ibasic_rsp_result_t *res; + struct q6afe_port *port; + + if (!data->payload_size) + return 0; + + res = data->payload; + switch (data->opcode) { + case APR_BASIC_RSP_RESULT: { + if (res->status) { + dev_err(afe->dev, "cmd = 0x%x returned error = 0x%x\n", + res->opcode, res->status); + } + switch (res->opcode) { + case AFE_PORT_CMD_SET_PARAM_V2: + case AFE_PORT_CMD_DEVICE_STOP: + case AFE_PORT_CMD_DEVICE_START: + port = afe_find_port(afe, data->token); + if (port) { + port->result = *res; + wake_up(&port->wait); + } + break; + default: + dev_err(afe->dev, "Unknown cmd 0x%x\n", res->opcode); + break; + } + } + break; + default: + break; + } + + return 0; +} + +/** + * q6afe_get_port_id() - Get port id from a given port index + * + * @index: port index + * + * Return: Will be an negative on error or valid port_id on success + */ +int q6afe_get_port_id(int index) +{ + if (index < 0 || index > AFE_PORT_MAX) + return -EINVAL; + + return port_maps[index].port_id; +} +EXPORT_SYMBOL_GPL(q6afe_get_port_id); + +static int afe_apr_send_pkt(struct q6afe *afe, void *data, + struct q6afe_port *port) +{ + wait_queue_head_t *wait = &port->wait; + struct apr_hdr *hdr = data; + int ret; + + mutex_lock(&afe->lock); + port->result.opcode = 0; + port->result.status = 0; + + ret = apr_send_pkt(afe->apr, data); + if (ret < 0) { + dev_err(afe->dev, "packet not transmitted (%d)\n", ret); + ret = -EINVAL; + goto err; + } + + ret = wait_event_timeout(*wait, (port->result.opcode == hdr->opcode), + msecs_to_jiffies(TIMEOUT_MS)); + if (!ret) { + ret = -ETIMEDOUT; + } else if (port->result.status > 0) { + dev_err(afe->dev, "DSP returned error[%x]\n", + port->result.status); + ret = -EINVAL; + } else { + ret = 0; + } + +err: + mutex_unlock(&afe->lock); + + return ret; +} + +static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data, + int param_id, int psize) +{ + struct apr_hdr *hdr; + struct afe_port_cmd_set_param_v2 *param; + struct afe_port_param_data_v2 *pdata; + struct q6afe *afe = port->afe; + u16 port_id = port->id; + int ret; + + hdr = data; + param = data + sizeof(*hdr); + pdata = data + sizeof(*hdr) + sizeof(*param); + + hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + hdr->pkt_size = sizeof(*hdr) + sizeof(*param) + + sizeof(*pdata) + psize; + hdr->src_port = 0; + hdr->dest_port = 0; + hdr->token = port->token; + hdr->opcode = AFE_PORT_CMD_SET_PARAM_V2; + param->port_id = port_id; + param->payload_size = sizeof(*pdata) + psize; + param->payload_address_lsw = 0x00; + param->payload_address_msw = 0x00; + param->mem_map_handle = 0x00; + pdata->module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; + pdata->param_id = param_id; + pdata->param_size = psize; + + ret = afe_apr_send_pkt(afe, data, port); + if (ret) + dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", + port_id, ret); + + + return ret; +} + +/** + * q6afe_port_stop() - Stop a afe port + * + * @port: Instance of port to stop + * + * Return: Will be an negative on packet size on success. + */ +int q6afe_port_stop(struct q6afe_port *port) +{ + int port_id = port->id; + struct afe_port_cmd_device_stop stop; + struct q6afe *afe = port->afe; + int ret = 0; + int index; + + port_id = port->id; + index = port->token; + if (index < 0 || index > AFE_PORT_MAX) { + dev_err(afe->dev, "AFE port index[%d] invalid!\n", index); + return -EINVAL; + } + + stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + stop.hdr.pkt_size = sizeof(stop); + stop.hdr.src_port = 0; + stop.hdr.dest_port = 0; + stop.hdr.token = index; + stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP; + stop.port_id = port_id; + stop.reserved = 0; + + ret = afe_apr_send_pkt(afe, &stop, port); + if (ret) + dev_err(afe->dev, "AFE close failed %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(q6afe_port_stop); + +/** + * q6afe_hdmi_port_prepare() - Prepare hdmi afe port. + * + * @port: Instance of afe port + * @cfg: HDMI configuration for the afe port + * + */ +void q6afe_hdmi_port_prepare(struct q6afe_port *port, + struct q6afe_hdmi_cfg *cfg) +{ + union afe_port_config *pcfg = &port->port_cfg; + + pcfg->hdmi_multi_ch.hdmi_cfg_minor_version = + AFE_API_VERSION_HDMI_CONFIG; + pcfg->hdmi_multi_ch.datatype = cfg->datatype; + pcfg->hdmi_multi_ch.channel_allocation = cfg->channel_allocation; + pcfg->hdmi_multi_ch.sample_rate = cfg->sample_rate; + pcfg->hdmi_multi_ch.bit_width = cfg->bit_width; +} +EXPORT_SYMBOL_GPL(q6afe_hdmi_port_prepare); + +/** + * q6afe_port_start() - Start a afe port + * + * @port: Instance of port to start + * + * Return: Will be an negative on packet size on success. + */ +int q6afe_port_start(struct q6afe_port *port) +{ + struct afe_audioif_config_command config = { {0} }; + struct afe_port_cmd_device_start start; + struct q6afe *afe = port->afe; + int port_id = port->id; + int ret, param_id = port->cfg_type; + + config.pcfg = port->port_cfg; + + ret = q6afe_port_set_param_v2(port, &config, param_id, + sizeof(config.pcfg)); + if (ret) { + dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", + port_id, ret); + return ret; + } + + start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + start.hdr.pkt_size = sizeof(start); + start.hdr.src_port = 0; + start.hdr.dest_port = 0; + start.hdr.token = port->token; + start.hdr.opcode = AFE_PORT_CMD_DEVICE_START; + start.port_id = port_id; + + ret = afe_apr_send_pkt(afe, &start, port); + if (ret) + dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", + port_id, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(q6afe_port_start); + +/** + * q6afe_port_get_from_id() - Get port instance from a port id + * + * @dev: Pointer to afe child device. + * @id: port id + * + * Return: Will be an error pointer on error or a valid afe port + * on success. + */ +struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id) +{ + int port_id; + struct q6afe *afe = dev_get_drvdata(dev->parent); + struct q6afe_port *port; + unsigned long flags; + int cfg_type; + + if (id < 0 || id > AFE_PORT_MAX) { + dev_err(dev, "AFE port token[%d] invalid!\n", id); + return ERR_PTR(-EINVAL); + } + + port_id = port_maps[id].port_id; + + switch (port_id) { + case AFE_PORT_ID_MULTICHAN_HDMI_RX: + cfg_type = AFE_PARAM_ID_HDMI_CONFIG; + break; + default: + dev_err(dev, "Invalid port id 0x%x\n", port_id); + return ERR_PTR(-EINVAL); + } + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + return ERR_PTR(-ENOMEM); + + init_waitqueue_head(&port->wait); + + port->token = id; + port->id = port_id; + port->afe = afe; + port->cfg_type = cfg_type; + + spin_lock_irqsave(&afe->port_list_lock, flags); + list_add_tail(&port->node, &afe->port_list); + spin_unlock_irqrestore(&afe->port_list_lock, flags); + + return port; + +} +EXPORT_SYMBOL_GPL(q6afe_port_get_from_id); + +/** + * q6afe_port_put() - Release port reference + * + * @port: Instance of port to put + */ +void q6afe_port_put(struct q6afe_port *port) +{ + struct q6afe *afe = port->afe; + unsigned long flags; + + spin_lock_irqsave(&afe->port_list_lock, flags); + list_del(&port->node); + spin_unlock_irqrestore(&afe->port_list_lock, flags); + kfree(port); +} +EXPORT_SYMBOL_GPL(q6afe_port_put); + +static int q6afe_probe(struct apr_device *adev) +{ + struct q6afe *afe; + struct device *dev = &adev->dev; + struct device_node *dais_np; + + afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL); + if (!afe) + return -ENOMEM; + + q6core_get_svc_api_info(adev->svc_id, &afe->ainfo); + afe->apr = adev; + mutex_init(&afe->lock); + afe->dev = dev; + INIT_LIST_HEAD(&afe->port_list); + spin_lock_init(&afe->port_list_lock); + + dev_set_drvdata(dev, afe); + + dais_np = of_get_child_by_name(dev->of_node, "dais"); + if (dais_np) { + afe->pdev_dais = of_platform_device_create(dais_np, + "q6afe-dai", dev); + of_node_put(dais_np); + } + + return 0; +} + +static int q6afe_remove(struct apr_device *adev) +{ + struct q6afe *afe = dev_get_drvdata(&adev->dev); + + if (afe->pdev_dais) + of_platform_device_destroy(&afe->pdev_dais->dev, NULL); + + return 0; +} + +static const struct of_device_id q6afe_device_id[] = { + { .compatible = "qcom,q6afe" }, + {}, +}; +MODULE_DEVICE_TABLE(of, q6afe_device_id); + +static struct apr_driver qcom_q6afe_driver = { + .probe = q6afe_probe, + .remove = q6afe_remove, + .callback = q6afe_callback, + .driver = { + .name = "qcom-q6afe", + .of_match_table = of_match_ptr(q6afe_device_id), + + }, +}; + +module_apr_driver(qcom_q6afe_driver); +MODULE_DESCRIPTION("Q6 Audio Front End"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h new file mode 100644 index 000000000000..63250f118df8 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef __Q6AFE_H__ +#define __Q6AFE_H__ + +#include + +#define AFE_PORT_MAX 48 + +#define MSM_AFE_PORT_TYPE_RX 0 +#define MSM_AFE_PORT_TYPE_TX 1 +#define AFE_MAX_PORTS AFE_PORT_MAX + +struct q6afe_hdmi_cfg { + u16 datatype; + u16 channel_allocation; + u32 sample_rate; + u16 bit_width; +}; + +struct q6afe_port_config { + struct q6afe_hdmi_cfg hdmi; +}; + +struct q6afe_port; + +struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id); +int q6afe_port_start(struct q6afe_port *port); +int q6afe_port_stop(struct q6afe_port *port); +void q6afe_port_put(struct q6afe_port *port); +int q6afe_get_port_id(int index); +void q6afe_hdmi_port_prepare(struct q6afe_port *port, + struct q6afe_hdmi_cfg *cfg); + +#endif /* __Q6AFE_H__ */ From patchwork Wed Apr 18 15:31:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133654 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp37061ljf; Wed, 18 Apr 2018 08:37:39 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+1P22j6ukgQWrq7xZqOY3lC8Sa4w+a5hvbScyZDxwxjAEOqwo7bKFZsWaa8A8XYo3biFTL X-Received: by 2002:adf:e147:: with SMTP id f7-v6mr1934277wri.172.1524065859701; Wed, 18 Apr 2018 08:37:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065859; cv=none; d=google.com; s=arc-20160816; b=HCiZuRjxpAArpas3+bIPOyaLYIpeyYyK2x+FK3IiEtWnhBpxkOpNEnpnEZy1mNAUkp +R6cKX2Qrzv+m2DAV59JOrrW71CIfC3bra6p8SLFIDlQ1LJ4gjQB7jauWiiccG7j8qR6 czZ297v8q6xfICbOc0WkAW0OhXSR998WffDvvm47aN2eaa36XH96C13KxLMNchGC8IcQ Qp5HkNLP3+zIfL0k7lvnr4J95+J6z8HToEdctGVgSEboWu4ANxyw7q27CJh+7ZUSyzwM teHnDdDPn7ysQSK9aFB/7SlICKV1XUhAreWMjT0LbxhY6leM4FAIRNnllcclsm9D7Hyv +9Sw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=J1yYK6Nra4ytDbww3abNZRTU3VYRPFu+b8nJklDiLpE=; b=MYF9goI9ixI38OkWsUv2Okkb2uWODINQmxvHwGk1utLFtx6k5iIDS8tWs+3AcvdQwC 2ISB95aPnr6Z98Dr1SRxg3NHu8dgwRi/lK6nyKdCD4EhWVpxHbbVkMuUOLHWSLsehFwH fjWgNchv98RlCkakxeJFax7+gg1W/ZQNoL1GSQHN4y6HEOYifgb+JY8c3v20c+4dNkX4 XrjLN/dwv9KCJGXn7z3W+0JEr16qtG9TfbuhUBXys/LY9IunnZCWgJs5fWgYq95HoqbG vmPOObZtV3HW9QpvQQHBFqlKWsZZvTNCbBftMGixHVvILBLQ5cbUNpRNZwGBj/d0QfmY zDsQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=DY6nIy/W; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id i92-v6si1252907wri.161.2018.04.18.08.37.39; Wed, 18 Apr 2018 08:37:39 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=DY6nIy/W; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 5B7D22676ED; Wed, 18 Apr 2018 17:36:23 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id AC80A2676CF; Wed, 18 Apr 2018 17:36:13 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f193.google.com (mail-wr0-f193.google.com [209.85.128.193]) by alsa0.perex.cz (Postfix) with ESMTP id 6E29B2676BF for ; Wed, 18 Apr 2018 17:36:08 +0200 (CEST) Received: by mail-wr0-f193.google.com with SMTP id v60-v6so6041018wrc.7 for ; Wed, 18 Apr 2018 08:36:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=11nDLJnS0vzad0AfX8L//0Uz+cYUGiCO2RuA0Z6tjjU=; b=DY6nIy/W3q+9lIn5PaxrhfjJgLDonzP89o/uHvJF18F1BakLmVbUI0jV1vQMUmd4qf S7I8altdMGxTs738aVgkN1grTqF+CRljP02pntpAyIVnEXz/Axv0CSV/+xN26Sc4SRCz WLc5XnCQk6sGXKEihEd3hQKqqTCblD5aiJgtY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=11nDLJnS0vzad0AfX8L//0Uz+cYUGiCO2RuA0Z6tjjU=; b=T+nJdDMxpZ6Eha31idd0IZR0Dl/KQMM1vBYgb2WMrf2BVRx1j+LwcYCcLLuIje+er1 Ycp2JD+1BLJnQSCJ1f4XDkR/87kpTo3DBJ9zhHGb2mDKAttdMgM/zTgZ97yelY3CMo3E wYP64m4ob3dZREJKEVjQcE6IBbyyqscgHQ2AskCYYaReKa+0z0rAT9RnADG/ePB9xnAh eSmYa/52+HaVic/kNeC3pwVkhZAz+Ek5VtbE7p77TqsRONcNSU9s76M4PhYyGNfUlpE7 faeS9Vby8yCOyXZEnhVbkDnKgjJEwT4Pml9H0Egt7Hj2B18iwZM2VMt3BTiyJa7taRGk Z0rw== X-Gm-Message-State: ALQs6tCGStDYnqfQHBuIAwY0w4zXDyZ0a4BZd0ZiFXw21/MIsxGuR+7j nOmyLoNlM6cAwbcUi+NdWJByUA== X-Received: by 2002:adf:ace2:: with SMTP id o89-v6mr2001979wrc.264.1524065767848; Wed, 18 Apr 2018 08:36:07 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.36.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:36:07 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:43 +0100 Message-Id: <20180418153157.1960-10-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 09/23] ASoC: qdsp6: q6afe: Add support to MI2S ports X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch adds support to 4 MI2S ports on LPASS. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- sound/soc/qcom/qdsp6/q6afe.c | 228 +++++++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6afe.h | 13 +++ 2 files changed, 241 insertions(+) -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index 27c1055ac791..fe936d415178 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -14,6 +14,10 @@ #include #include #include +#include +#include +#include +#include #include "q6dsp-errno.h" #include "q6core.h" #include "q6afe.h" @@ -28,7 +32,36 @@ #define AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG 0x00010235 +#define AFE_PARAM_ID_LPAIF_CLK_CONFIG 0x00010238 +#define AFE_PARAM_ID_INTERNAL_DIGITAL_CDC_CLK_CONFIG 0x00010239 + #define AFE_PARAM_ID_SLIMBUS_CONFIG 0x00010212 +#define AFE_PARAM_ID_I2S_CONFIG 0x0001020D + +/* I2S config specific */ +#define AFE_API_VERSION_I2S_CONFIG 0x1 +#define AFE_PORT_I2S_SD0 0x1 +#define AFE_PORT_I2S_SD1 0x2 +#define AFE_PORT_I2S_SD2 0x3 +#define AFE_PORT_I2S_SD3 0x4 +#define AFE_PORT_I2S_SD0_MASK BIT(0x1) +#define AFE_PORT_I2S_SD1_MASK BIT(0x2) +#define AFE_PORT_I2S_SD2_MASK BIT(0x3) +#define AFE_PORT_I2S_SD3_MASK BIT(0x4) +#define AFE_PORT_I2S_SD0_1_MASK GENMASK(2, 1) +#define AFE_PORT_I2S_SD2_3_MASK GENMASK(4, 3) +#define AFE_PORT_I2S_SD0_1_2_MASK GENMASK(3, 1) +#define AFE_PORT_I2S_SD0_1_2_3_MASK GENMASK(4, 1) +#define AFE_PORT_I2S_QUAD01 0x5 +#define AFE_PORT_I2S_QUAD23 0x6 +#define AFE_PORT_I2S_6CHS 0x7 +#define AFE_PORT_I2S_8CHS 0x8 +#define AFE_PORT_I2S_MONO 0x0 +#define AFE_PORT_I2S_STEREO 0x1 +#define AFE_PORT_CONFIG_I2S_WS_SRC_EXTERNAL 0x0 +#define AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL 0x1 +#define AFE_LINEAR_PCM_DATA 0x0 + /* Port IDs */ #define AFE_API_VERSION_HDMI_CONFIG 0x1 @@ -64,6 +97,19 @@ #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX 0x400c /* SLIMbus Tx port on channel 6. */ #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_TX 0x400d +#define AFE_PORT_ID_PRIMARY_MI2S_RX 0x1000 +#define AFE_PORT_ID_PRIMARY_MI2S_TX 0x1001 +#define AFE_PORT_ID_SECONDARY_MI2S_RX 0x1002 +#define AFE_PORT_ID_SECONDARY_MI2S_TX 0x1003 +#define AFE_PORT_ID_TERTIARY_MI2S_RX 0x1004 +#define AFE_PORT_ID_TERTIARY_MI2S_TX 0x1005 +#define AFE_PORT_ID_QUATERNARY_MI2S_RX 0x1006 +#define AFE_PORT_ID_QUATERNARY_MI2S_TX 0x1007 + +#define Q6AFE_LPASS_MODE_CLK1_VALID 1 +#define Q6AFE_LPASS_MODE_CLK2_VALID 2 +#define Q6AFE_LPASS_CLK_SRC_INTERNAL 1 +#define Q6AFE_LPASS_CLK_ROOT_DEFAULT 0 #define TIMEOUT_MS 1000 #define AFE_CMD_RESP_AVAIL 0 @@ -160,10 +206,21 @@ struct afe_param_id_slimbus_cfg { */ } __packed; +struct afe_param_id_i2s_cfg { + u32 i2s_cfg_minor_version; + u16 bit_width; + u16 channel_mode; + u16 mono_stereo; + u16 ws_src; + u32 sample_rate; + u16 data_format; + u16 reserved; +} __packed; union afe_port_config { struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch; struct afe_param_id_slimbus_cfg slim_cfg; + struct afe_param_id_i2s_cfg i2s_cfg; } __packed; struct q6afe_port { @@ -210,6 +267,22 @@ static struct afe_port_map port_maps[AFE_PORT_MAX] = { SLIMBUS_4_RX, 1, 1}, [SLIMBUS_5_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX, SLIMBUS_5_RX, 1, 1}, + [QUATERNARY_MI2S_RX] = { AFE_PORT_ID_QUATERNARY_MI2S_RX, + QUATERNARY_MI2S_RX, 1, 1}, + [QUATERNARY_MI2S_TX] = { AFE_PORT_ID_QUATERNARY_MI2S_TX, + QUATERNARY_MI2S_TX, 0, 1}, + [SECONDARY_MI2S_RX] = { AFE_PORT_ID_SECONDARY_MI2S_RX, + SECONDARY_MI2S_RX, 1, 1}, + [SECONDARY_MI2S_TX] = { AFE_PORT_ID_SECONDARY_MI2S_TX, + SECONDARY_MI2S_TX, 0, 1}, + [TERTIARY_MI2S_RX] = { AFE_PORT_ID_TERTIARY_MI2S_RX, + TERTIARY_MI2S_RX, 1, 1}, + [TERTIARY_MI2S_TX] = { AFE_PORT_ID_TERTIARY_MI2S_TX, + TERTIARY_MI2S_TX, 0, 1}, + [PRIMARY_MI2S_RX] = { AFE_PORT_ID_PRIMARY_MI2S_RX, + PRIMARY_MI2S_RX, 1, 1}, + [PRIMARY_MI2S_TX] = { AFE_PORT_ID_PRIMARY_MI2S_TX, + PRIMARY_MI2S_RX, 0, 1}, [SLIMBUS_6_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX, SLIMBUS_6_RX, 1, 1}, }; @@ -448,6 +521,150 @@ void q6afe_hdmi_port_prepare(struct q6afe_port *port, } EXPORT_SYMBOL_GPL(q6afe_hdmi_port_prepare); +/** + * q6afe_i2s_port_prepare() - Prepare i2s afe port. + * + * @port: Instance of afe port + * @cfg: I2S configuration for the afe port + * + Return: Will be an negative on error and zero on success. + */ +int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg) +{ + union afe_port_config *pcfg = &port->port_cfg; + struct device *dev = port->afe->dev; + int num_sd_lines; + + pcfg->i2s_cfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; + pcfg->i2s_cfg.sample_rate = cfg->sample_rate; + pcfg->i2s_cfg.bit_width = cfg->bit_width; + pcfg->i2s_cfg.data_format = AFE_LINEAR_PCM_DATA; + + switch (cfg->fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + pcfg->i2s_cfg.ws_src = AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL; + break; + case SND_SOC_DAIFMT_CBM_CFM: + /* CPU is slave */ + pcfg->i2s_cfg.ws_src = AFE_PORT_CONFIG_I2S_WS_SRC_EXTERNAL; + break; + default: + break; + } + + num_sd_lines = hweight_long(cfg->sd_line_mask); + + switch (num_sd_lines) { + case 0: + dev_err(dev, "no line is assigned\n"); + return -EINVAL; + case 1: + switch (cfg->sd_line_mask) { + case AFE_PORT_I2S_SD0_MASK: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD0; + break; + case AFE_PORT_I2S_SD1_MASK: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD1; + break; + case AFE_PORT_I2S_SD2_MASK: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD2; + break; + case AFE_PORT_I2S_SD3_MASK: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD3; + break; + default: + dev_err(dev, "Invalid SD lines\n"); + return -EINVAL; + } + break; + case 2: + switch (cfg->sd_line_mask) { + case AFE_PORT_I2S_SD0_1_MASK: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_QUAD01; + break; + case AFE_PORT_I2S_SD2_3_MASK: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_QUAD23; + break; + default: + dev_err(dev, "Invalid SD lines\n"); + return -EINVAL; + } + break; + case 3: + switch (cfg->sd_line_mask) { + case AFE_PORT_I2S_SD0_1_2_MASK: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_6CHS; + break; + default: + dev_err(dev, "Invalid SD lines\n"); + return -EINVAL; + } + break; + case 4: + switch (cfg->sd_line_mask) { + case AFE_PORT_I2S_SD0_1_2_3_MASK: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_8CHS; + + break; + default: + dev_err(dev, "Invalid SD lines\n"); + return -EINVAL; + } + break; + default: + dev_err(dev, "Invalid SD lines\n"); + return -EINVAL; + } + + switch (cfg->num_channels) { + case 1: + case 2: + switch (pcfg->i2s_cfg.channel_mode) { + case AFE_PORT_I2S_QUAD01: + case AFE_PORT_I2S_6CHS: + case AFE_PORT_I2S_8CHS: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD0; + break; + case AFE_PORT_I2S_QUAD23: + pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD2; + break; + } + + if (cfg->num_channels == 2) + pcfg->i2s_cfg.mono_stereo = AFE_PORT_I2S_STEREO; + else + pcfg->i2s_cfg.mono_stereo = AFE_PORT_I2S_MONO; + + break; + case 3: + case 4: + if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_QUAD01) { + dev_err(dev, "Invalid Channel mode\n"); + return -EINVAL; + } + break; + case 5: + case 6: + if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_6CHS) { + dev_err(dev, "Invalid Channel mode\n"); + return -EINVAL; + } + break; + case 7: + case 8: + if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_8CHS) { + dev_err(dev, "Invalid Channel mode\n"); + return -EINVAL; + } + break; + default: + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(q6afe_i2s_port_prepare); + /** * q6afe_port_start() - Start a afe port * @@ -529,6 +746,17 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id) case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX: cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG; break; + + case AFE_PORT_ID_PRIMARY_MI2S_RX: + case AFE_PORT_ID_PRIMARY_MI2S_TX: + case AFE_PORT_ID_SECONDARY_MI2S_RX: + case AFE_PORT_ID_SECONDARY_MI2S_TX: + case AFE_PORT_ID_TERTIARY_MI2S_RX: + case AFE_PORT_ID_TERTIARY_MI2S_TX: + case AFE_PORT_ID_QUATERNARY_MI2S_RX: + case AFE_PORT_ID_QUATERNARY_MI2S_TX: + cfg_type = AFE_PARAM_ID_I2S_CONFIG; + break; default: dev_err(dev, "Invalid port id 0x%x\n", port_id); return ERR_PTR(-EINVAL); diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 155d6e47d7ce..05c61014abea 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -11,6 +11,8 @@ #define MSM_AFE_PORT_TYPE_TX 1 #define AFE_MAX_PORTS AFE_PORT_MAX +#define Q6AFE_MAX_MI2S_LINES 4 + #define AFE_MAX_CHAN_COUNT 8 #define AFE_PORT_MAX_AUDIO_CHAN_CNT 0x8 @@ -29,9 +31,19 @@ struct q6afe_slim_cfg { u8 ch_mapping[AFE_MAX_CHAN_COUNT]; }; +struct q6afe_i2s_cfg { + u32 sample_rate; + u16 bit_width; + u16 data_format; + u16 num_channels; + u32 sd_line_mask; + int fmt; +}; + struct q6afe_port_config { struct q6afe_hdmi_cfg hdmi; struct q6afe_slim_cfg slim; + struct q6afe_i2s_cfg i2s_cfg; }; struct q6afe_port; @@ -45,5 +57,6 @@ void q6afe_hdmi_port_prepare(struct q6afe_port *port, struct q6afe_hdmi_cfg *cfg); void q6afe_slim_port_prepare(struct q6afe_port *port, struct q6afe_slim_cfg *cfg); +int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg); #endif /* __Q6AFE_H__ */ From patchwork Wed Apr 18 15:31:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133655 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp37163ljf; Wed, 18 Apr 2018 08:37:47 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/L33eTnsxmMiopK1SIlmEvbYPjW+Tror15S3yq88sazrGZ2PscwZU2VBWOzP2QgIdWPeSX X-Received: by 10.28.5.198 with SMTP id 189mr1991254wmf.155.1524065867296; Wed, 18 Apr 2018 08:37:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065867; cv=none; d=google.com; s=arc-20160816; b=n0Tz/ElS2XAbSZgh89wCy26DOAqIXy2Cro5vrHxQ/bdM0W+FNev7ITemk22nYOGbKj +NqD1XgDauPXJ+Id3iT8JXc5ctXAgjCzwR5kk7pMv+5Pwpta81g5NA1Z67A8P2HDkkuW Q8lwVJxfb8ZNTFWml/Ewr6SPeWj3p5RMIqUxJEtnjE20nhWs7TW/gBbZ+aAegCZ2gbgG po0ij6ZMVAygiBnVZojxtzOHcTVaZdmLq5GIK5x7N6Zqcu+5wvaaChqBRyrXd5xeZjsw FktvI+HMPp1p1lrXxoP+YsWYi8AjyhKnDDuoNZllO8a8GbG+P8WC4nOz/MdzizY9eGoM UoXQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=WxWP+ykyEcSRP5K4BlG4gqvFkHSVCvX+e/yKM6wMC3o=; b=YuYDZC6Lsq5MvjnOaDH5IbbUhAHhxXAz/xRVeXMBdmrGxlJqHzvIxqB2zsxEE2LWWv BWOYF9t1gS1umg1sU6HqY3XlzmOX5GOLs6KSWDl4PIcWVWtsbVyoGQwckkpBTOOnO8sg rJ+1cfg8+TIUENhiY3Mdnm3kriLZMzj6mzwqDJxk9/pwWL88EOKT57Lti2cKRZlLmhks KT+jQOuFR49LntZ8TPRn5enHDW2/YhmskdFBltUrO4ttNoV8Puy/rDtRGjBWadaJb708 aFoe2Qk2BwDAqYC4hdvLc0DNaz9CI+CU6pY+f4uprEQfT3iIW1gSyuuYLHN0QZ24wbSb 1bAA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=SzNuq6Lm; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id h34-v6si1336671wrf.259.2018.04.18.08.37.47; Wed, 18 Apr 2018 08:37:47 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=SzNuq6Lm; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id A2A632676FB; Wed, 18 Apr 2018 17:36:24 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 9B6ED2676D6; Wed, 18 Apr 2018 17:36:15 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f196.google.com (mail-wr0-f196.google.com [209.85.128.196]) by alsa0.perex.cz (Postfix) with ESMTP id B5A762676C7 for ; Wed, 18 Apr 2018 17:36:09 +0200 (CEST) Received: by mail-wr0-f196.google.com with SMTP id f14-v6so6045269wre.4 for ; Wed, 18 Apr 2018 08:36:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WRhqIl6z4t/LxTXrBsgSAvNaW1NPilNDwhRjDYvAfEE=; b=SzNuq6LmmpRUO/7PW2gm1QcDT+gf/kag1YlhU/PN+rjpED/0F7HWRW2qBrcoPy9jyS ef/EQgoMRmMm9mYymei4lmQG91TpK3PRzU7AY4tLOCai7tD8VVdkt0byCH6bj0m2zj5y GUPcKDBFW8TOdXtoV4K3v0HsIHreqS9zyZSog= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WRhqIl6z4t/LxTXrBsgSAvNaW1NPilNDwhRjDYvAfEE=; b=KYOn5bXu5IpgCxGEfooljAahiCj7wJuv4TeXMADKEFirTEMf29H5EZ7qcupdURGC0j m+As3Kwq+hccHNizwtidzXyCqtjBlVbbzxdQJdJEchb13OlrC2JOz1/R7xrYtxf7Fhib /o7xbZMHD2L9vif74qBb8rR6ySzwgdQr5gbCUfse5UxRG2rFiXjkF1iOm7THUNbST+Ua p82qqJY0O2FB/31l0OfAoo0yBixGb9+QLiID0w2dVf8VKXdQ8eSdVcb6tJ6nVihg/TE9 4RnVW8yERNy5DdjTKv8UByfel9UxXA0u/aQRzNWEJsTKdSgeUMHWAM5FkzuEoRxOxwbg Dyzg== X-Gm-Message-State: ALQs6tDbqPlxv956RfIkpDmZDHHsI0n1+J+X9/D+gzagaBFQZlFiKVy1 r/D9xeMUt2fzEQsSsj7bUYfyow== X-Received: by 2002:adf:b01d:: with SMTP id f29-v6mr2103841wra.39.1524065769151; Wed, 18 Apr 2018 08:36:09 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.36.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:36:08 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:44 +0100 Message-Id: <20180418153157.1960-11-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 10/23] ASoC: qdsp6: q6afe: Add support to MI2S sysclks X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch adds support to LPASS Bit clock, LPASS Digital core clock and OSR clock. These clocks are required for both MI2S and PCM setup. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- sound/soc/qcom/qdsp6/q6afe.c | 212 ++++++++++++++++++++++++++++++++++++++++++- sound/soc/qcom/qdsp6/q6afe.h | 131 ++++++++++++++++++++++++++ 2 files changed, 341 insertions(+), 2 deletions(-) -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index fe936d415178..7c7e30e34781 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -26,6 +26,7 @@ #define AFE_PORT_CMD_DEVICE_START 0x000100E5 #define AFE_PORT_CMD_DEVICE_STOP 0x000100E6 #define AFE_PORT_CMD_SET_PARAM_V2 0x000100EF +#define AFE_SVC_CMD_SET_PARAM 0x000100f3 #define AFE_PORT_CMDRSP_GET_PARAM_V2 0x00010106 #define AFE_PARAM_ID_HDMI_CONFIG 0x00010210 #define AFE_MODULE_AUDIO_DEV_INTERFACE 0x0001020C @@ -68,6 +69,11 @@ #define AFE_PORT_ID_MULTICHAN_HDMI_RX 0x100E #define AFE_API_VERSION_SLIMBUS_CONFIG 0x1 +/* Clock set API version */ +#define AFE_API_VERSION_CLOCK_SET 1 +#define Q6AFE_LPASS_CLK_CONFIG_API_VERSION 0x1 +#define AFE_MODULE_CLOCK_SET 0x0001028F +#define AFE_PARAM_ID_CLOCK_SET 0x00010290 /* SLIMbus Rx port on channel 0. */ #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX 0x4000 @@ -146,6 +152,13 @@ struct afe_port_param_data_v2 { u16 reserved; } __packed; +struct afe_svc_cmd_set_param { + uint32_t payload_size; + uint32_t payload_address_lsw; + uint32_t payload_address_msw; + uint32_t mem_map_handle; +} __packed; + struct afe_port_cmd_set_param_v2 { u16 port_id; u16 payload_size; @@ -206,6 +219,23 @@ struct afe_param_id_slimbus_cfg { */ } __packed; +struct afe_clk_cfg { + u32 i2s_cfg_minor_version; + u32 clk_val1; + u32 clk_val2; + u16 clk_src; + u16 clk_root; + u16 clk_set_mode; + u16 reserved; +} __packed; + +struct afe_digital_clk_cfg { + u32 i2s_cfg_minor_version; + u32 clk_val; + u16 clk_root; + u16 reserved; +} __packed; + struct afe_param_id_i2s_cfg { u32 i2s_cfg_minor_version; u16 bit_width; @@ -223,9 +253,43 @@ union afe_port_config { struct afe_param_id_i2s_cfg i2s_cfg; } __packed; + +struct afe_clk_set { + uint32_t clk_set_minor_version; + uint32_t clk_id; + uint32_t clk_freq_in_hz; + uint16_t clk_attri; + uint16_t clk_root; + uint32_t enable; +}; + +struct afe_lpass_clk_config_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; + struct afe_clk_cfg clk_cfg; +} __packed; + +struct afe_lpass_clk_config_command_v2 { + struct apr_hdr hdr; + struct afe_svc_cmd_set_param param; + struct afe_port_param_data_v2 pdata; + struct afe_clk_set clk_cfg; +} __packed; + + + +struct afe_lpass_digital_clk_config_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; + struct afe_digital_clk_cfg clk_cfg; +} __packed; + struct q6afe_port { wait_queue_head_t wait; union afe_port_config port_cfg; + struct aprv2_ibasic_rsp_result_t result; int token; int id; int cfg_type; @@ -322,6 +386,7 @@ static int q6afe_callback(struct apr_device *adev, case AFE_PORT_CMD_SET_PARAM_V2: case AFE_PORT_CMD_DEVICE_STOP: case AFE_PORT_CMD_DEVICE_START: + case AFE_SVC_CMD_SET_PARAM: port = afe_find_port(afe, data->token); if (port) { port->result = *res; @@ -393,6 +458,46 @@ static int afe_apr_send_pkt(struct q6afe *afe, void *data, return ret; } +static int q6afe_port_set_param(struct q6afe_port *port, void *data, + int param_id, int module_id, int psize) +{ + struct apr_hdr *hdr; + struct afe_svc_cmd_set_param *param; + struct afe_port_param_data_v2 *pdata; + struct q6afe *afe = port->afe; + u16 port_id = port->id; + int ret; + + hdr = data; + param = data + sizeof(*hdr); + pdata = data + sizeof(*hdr) + sizeof(*param); + + hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + hdr->pkt_size = sizeof(*hdr) + sizeof(*param) + + sizeof(*pdata) + psize; + hdr->src_port = 0; + hdr->dest_port = 0; + hdr->token = port->token; + hdr->opcode = AFE_SVC_CMD_SET_PARAM; + + param->payload_size = sizeof(*pdata) + psize; + param->payload_address_lsw = 0x00; + param->payload_address_msw = 0x00; + param->mem_map_handle = 0x00; + pdata->module_id = module_id; + pdata->param_id = param_id; + pdata->param_size = psize; + + ret = afe_apr_send_pkt(afe, data, port); + if (ret) + dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", + port_id, ret); + + return ret; +} + static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data, int param_id, int psize) { @@ -434,6 +539,110 @@ static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data, return ret; } +static int q6afe_set_lpass_clock(struct q6afe_port *port, + struct afe_clk_cfg *cfg) +{ + struct afe_lpass_clk_config_command clk_cfg = { {0} }; + int param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG; + struct q6afe *afe = port->afe; + + if (!cfg) { + dev_err(afe->dev, "clock cfg is NULL\n"); + return -EINVAL; + } + + clk_cfg.clk_cfg = *cfg; + + return q6afe_port_set_param_v2(port, &clk_cfg, param_id, sizeof(*cfg)); +} + +static int q6afe_set_lpass_clock_v2(struct q6afe_port *port, + struct afe_clk_set *cfg) +{ + struct afe_lpass_clk_config_command_v2 clk_cfg = { {0} }; + int param_id = AFE_PARAM_ID_CLOCK_SET; + int module_id = AFE_MODULE_CLOCK_SET; + struct q6afe *afe = port->afe; + + if (!cfg) { + dev_err(afe->dev, "clock cfg is NULL\n"); + return -EINVAL; + } + + clk_cfg.clk_cfg = *cfg; + + return q6afe_port_set_param(port, &clk_cfg, param_id, + module_id, sizeof(*cfg)); +} + +static int q6afe_set_digital_codec_core_clock(struct q6afe_port *port, + struct afe_digital_clk_cfg *cfg) +{ + struct afe_lpass_digital_clk_config_command clk_cfg = { {0} }; + int param_id = AFE_PARAM_ID_INTERNAL_DIGITAL_CDC_CLK_CONFIG; + struct q6afe *afe = port->afe; + + if (!cfg) { + dev_err(afe->dev, "clock cfg is NULL\n"); + return -EINVAL; + } + + clk_cfg.clk_cfg = *cfg; + + return q6afe_port_set_param_v2(port, &clk_cfg, param_id, sizeof(*cfg)); +} + +int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id, + int clk_src, int clk_root, + unsigned int freq, int dir) +{ + struct afe_clk_cfg ccfg = {0,}; + struct afe_clk_set cset = {0,}; + struct afe_digital_clk_cfg dcfg = {0,}; + int ret; + + switch (clk_id) { + case LPAIF_DIG_CLK: + dcfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; + dcfg.clk_val = freq; + dcfg.clk_root = clk_root; + ret = q6afe_set_digital_codec_core_clock(port, &dcfg); + break; + case LPAIF_BIT_CLK: + ccfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; + ccfg.clk_val1 = freq; + ccfg.clk_src = clk_src; + ccfg.clk_root = clk_root; + ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK1_VALID; + ret = q6afe_set_lpass_clock(port, &ccfg); + break; + + case LPAIF_OSR_CLK: + ccfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; + ccfg.clk_val2 = freq; + ccfg.clk_src = clk_src; + ccfg.clk_root = clk_root; + ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID; + ret = q6afe_set_lpass_clock(port, &ccfg); + break; + case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1: + cset.clk_set_minor_version = AFE_API_VERSION_CLOCK_SET; + cset.clk_id = clk_id; + cset.clk_freq_in_hz = freq; + cset.clk_attri = clk_src; + cset.clk_root = clk_root; + cset.enable = !!freq; + ret = q6afe_set_lpass_clock_v2(port, &cset); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +EXPORT_SYMBOL_GPL(q6afe_port_set_sysclk); + /** * q6afe_port_stop() - Stop a afe port * @@ -526,8 +735,7 @@ EXPORT_SYMBOL_GPL(q6afe_hdmi_port_prepare); * * @port: Instance of afe port * @cfg: I2S configuration for the afe port - * - Return: Will be an negative on error and zero on success. + * Return: Will be an negative on error and zero on success. */ int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg) { diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 05c61014abea..f21c89a25c29 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -16,6 +16,134 @@ #define AFE_MAX_CHAN_COUNT 8 #define AFE_PORT_MAX_AUDIO_CHAN_CNT 0x8 +#define Q6AFE_LPASS_CLK_SRC_INTERNAL 1 +#define Q6AFE_LPASS_CLK_ROOT_DEFAULT 0 + +#define LPAIF_DIG_CLK 1 +#define LPAIF_BIT_CLK 2 +#define LPAIF_OSR_CLK 3 + +/* Clock ID for Primary I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT 0x100 +/* Clock ID for Primary I2S EBIT */ +#define Q6AFE_LPASS_CLK_ID_PRI_MI2S_EBIT 0x101 +/* Clock ID for Secondary I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT 0x102 +/* Clock ID for Secondary I2S EBIT */ +#define Q6AFE_LPASS_CLK_ID_SEC_MI2S_EBIT 0x103 +/* Clock ID for Tertiary I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT 0x104 +/* Clock ID for Tertiary I2S EBIT */ +#define Q6AFE_LPASS_CLK_ID_TER_MI2S_EBIT 0x105 +/* Clock ID for Quartnery I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT 0x106 +/* Clock ID for Quartnery I2S EBIT */ +#define Q6AFE_LPASS_CLK_ID_QUAD_MI2S_EBIT 0x107 +/* Clock ID for Speaker I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_IBIT 0x108 +/* Clock ID for Speaker I2S EBIT */ +#define Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_EBIT 0x109 +/* Clock ID for Speaker I2S OSR */ +#define Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR 0x10A + +/* Clock ID for QUINARY I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT 0x10B +/* Clock ID for QUINARY I2S EBIT */ +#define Q6AFE_LPASS_CLK_ID_QUI_MI2S_EBIT 0x10C +/* Clock ID for SENARY I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT 0x10D +/* Clock ID for SENARY I2S EBIT */ +#define Q6AFE_LPASS_CLK_ID_SEN_MI2S_EBIT 0x10E +/* Clock ID for INT0 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT0_MI2S_IBIT 0x10F +/* Clock ID for INT1 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT1_MI2S_IBIT 0x110 +/* Clock ID for INT2 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT2_MI2S_IBIT 0x111 +/* Clock ID for INT3 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT3_MI2S_IBIT 0x112 +/* Clock ID for INT4 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT4_MI2S_IBIT 0x113 +/* Clock ID for INT5 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT5_MI2S_IBIT 0x114 +/* Clock ID for INT6 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT6_MI2S_IBIT 0x115 + +/* Clock ID for QUINARY MI2S OSR CLK */ +#define Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR 0x116 + +/* Clock ID for Primary PCM IBIT */ +#define Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT 0x200 +/* Clock ID for Primary PCM EBIT */ +#define Q6AFE_LPASS_CLK_ID_PRI_PCM_EBIT 0x201 +/* Clock ID for Secondary PCM IBIT */ +#define Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT 0x202 +/* Clock ID for Secondary PCM EBIT */ +#define Q6AFE_LPASS_CLK_ID_SEC_PCM_EBIT 0x203 +/* Clock ID for Tertiary PCM IBIT */ +#define Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT 0x204 +/* Clock ID for Tertiary PCM EBIT */ +#define Q6AFE_LPASS_CLK_ID_TER_PCM_EBIT 0x205 +/* Clock ID for Quartery PCM IBIT */ +#define Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT 0x206 +/* Clock ID for Quartery PCM EBIT */ +#define Q6AFE_LPASS_CLK_ID_QUAD_PCM_EBIT 0x207 +/* Clock ID for Quinary PCM IBIT */ +#define Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT 0x208 +/* Clock ID for Quinary PCM EBIT */ +#define Q6AFE_LPASS_CLK_ID_QUIN_PCM_EBIT 0x209 +/* Clock ID for QUINARY PCM OSR */ +#define Q6AFE_LPASS_CLK_ID_QUI_PCM_OSR 0x20A + +/** Clock ID for Primary TDM IBIT */ +#define Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT 0x200 +/** Clock ID for Primary TDM EBIT */ +#define Q6AFE_LPASS_CLK_ID_PRI_TDM_EBIT 0x201 +/** Clock ID for Secondary TDM IBIT */ +#define Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT 0x202 +/** Clock ID for Secondary TDM EBIT */ +#define Q6AFE_LPASS_CLK_ID_SEC_TDM_EBIT 0x203 +/** Clock ID for Tertiary TDM IBIT */ +#define Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT 0x204 +/** Clock ID for Tertiary TDM EBIT */ +#define Q6AFE_LPASS_CLK_ID_TER_TDM_EBIT 0x205 +/** Clock ID for Quartery TDM IBIT */ +#define Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT 0x206 +/** Clock ID for Quartery TDM EBIT */ +#define Q6AFE_LPASS_CLK_ID_QUAD_TDM_EBIT 0x207 +/** Clock ID for Quinary TDM IBIT */ +#define Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT 0x208 +/** Clock ID for Quinary TDM EBIT */ +#define Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT 0x209 +/** Clock ID for Quinary TDM OSR */ +#define Q6AFE_LPASS_CLK_ID_QUIN_TDM_OSR 0x20A + +/* Clock ID for MCLK1 */ +#define Q6AFE_LPASS_CLK_ID_MCLK_1 0x300 +/* Clock ID for MCLK2 */ +#define Q6AFE_LPASS_CLK_ID_MCLK_2 0x301 +/* Clock ID for MCLK3 */ +#define Q6AFE_LPASS_CLK_ID_MCLK_3 0x302 +/* Clock ID for MCLK4 */ +#define Q6AFE_LPASS_CLK_ID_MCLK_4 0x304 +/* Clock ID for Internal Digital Codec Core */ +#define Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE 0x303 +/* Clock ID for INT MCLK0 */ +#define Q6AFE_LPASS_CLK_ID_INT_MCLK_0 0x305 +/* Clock ID for INT MCLK1 */ +#define Q6AFE_LPASS_CLK_ID_INT_MCLK_1 0x306 + +/* Clock attribute for invalid use (reserved for internal usage) */ +#define Q6AFE_LPASS_CLK_ATTRIBUTE_INVALID 0x0 +/* Clock attribute for no couple case */ +#define Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO 0x1 +/* Clock attribute for dividend couple case */ +#define Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_DIVIDEND 0x2 +/* Clock attribute for divisor couple case */ +#define Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR 0x3 +/* Clock attribute for invert and no couple case */ +#define Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO 0x4 + struct q6afe_hdmi_cfg { u16 datatype; u16 channel_allocation; @@ -59,4 +187,7 @@ void q6afe_slim_port_prepare(struct q6afe_port *port, struct q6afe_slim_cfg *cfg); int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg); +int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id, + int clk_src, int clk_root, + unsigned int freq, int dir); #endif /* __Q6AFE_H__ */ From patchwork Wed Apr 18 15:31:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133658 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp37747ljf; Wed, 18 Apr 2018 08:38:24 -0700 (PDT) X-Google-Smtp-Source: AIpwx48tJ7tN2yD5qcozohe/qsdvvrFSQ5RBAYcRD3bGkMm3nOIf5xjf6FncFONqOwkC54CpBcl+ X-Received: by 2002:adf:c362:: with SMTP id e31-v6mr2081756wrg.257.1524065903987; Wed, 18 Apr 2018 08:38:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065903; cv=none; d=google.com; s=arc-20160816; b=q1YI3EelJiMQHozsu6NhYxhY9yd+izR7jILJzbUuFT1W96bGRR92jdsKLsa+0h8Nyg 5pHjWv4OPRIGFm+4R04pxHWBxK7JP1t+g/37ivOq+HzLGJgmIfeIiJv64g0yX34fy5dj qR1BFgOO7d00wp+1knWB4kCDOAPbydAjFivP5D32wt4cdvASyFuItEJqVAt8PDZScfmB rcWtWgE5rjHXff2IB1f1SqlEDK/K3DITmRQKiKGq90w8Xs6SrzLuudEUwj37KyqTSVMo iqGV6ZU3r40cRFsar3cU29AZ4x3Ut1e03vTReZsXpNLZqYlpUFoqV2f/2vVjDLlCr2Dj Rw6Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=yhvK6c1ISQHq/gdcWoNsSP4b+Z9S5ffOOH4/MjImpas=; b=bq9rCxghHUMDsWrXSwVAAnDRZT6Y1rVD6YNgsxP4N10kjyX5ww1D77F+QUgrcI18T5 nR8nt0e+B9swXWNCYsQsHBdUhghOlFDbGWKvFOL2CwZRCpROmcHg/hoKwMvyLaAAeshG SyhOukknWtdhhT6Fad3aUyC9BY6NwGhksaukKm0vMINAEaEn+Vdf4uVWQx5tz7mo0JtS hc10kmeRzQe7Ji9TeSml0PEKNuEF6aboWfJLVZfc5/AVDernPFLRmHayLTRzeFZgBMRt lQmSzi1PN1w+jtulm5xQO72UDphDxZzRjVF7XioC8FFQU3fzodH68msak4OyklYP/513 4NDQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=gZi8kA2W; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id f66si1311076wme.100.2018.04.18.08.38.23; Wed, 18 Apr 2018 08:38:23 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=gZi8kA2W; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 78C812676F6; Wed, 18 Apr 2018 17:36:36 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 091EA2676A7; Wed, 18 Apr 2018 17:36:25 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f194.google.com (mail-wr0-f194.google.com [209.85.128.194]) by alsa0.perex.cz (Postfix) with ESMTP id A96E22676C7 for ; Wed, 18 Apr 2018 17:36:15 +0200 (CEST) Received: by mail-wr0-f194.google.com with SMTP id w3-v6so6052803wrg.2 for ; Wed, 18 Apr 2018 08:36:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+3h7SJBqIMe1cMNQozgUeiShrNemAj4cXuBStQ3XgQM=; b=gZi8kA2W7lbDyOuRLPNkssXiMY44M7ngHnTg+IjhIi6Xgz7AXhAoNGQaSC8/3gBcH1 L1Az3yCdRoJP3DefnGHr24zYBBVRheNkXVoXfOA2epijNpY2guxf+xqutOjxsKlF1J3x FV6MLwGKShmc3l6pGMgt6DxBEpZpRB7AWB5Tg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+3h7SJBqIMe1cMNQozgUeiShrNemAj4cXuBStQ3XgQM=; b=XKyqreFGGhrwiINrWumYQyxU5Pjk+EQRrpPI7HUTFw91XaqHmYupnlnS6w76rd1+OR 0VNwSldfBtkBul3D526u60HEU4CfvlFuMQ5wsBcVei+l35QDm2gVxel3fKqkNyOmQQw0 ZSEiu7E73iFLMGU4GGGfEwsF4nFcQLDFWnV3Tt5hHN4/0BqB5E11A3O+TPAD6h9f3zXB p+rDJqP8J+Umaa6XP1wHsQkorHlD23ttj504nPKQQPQBKDiPvWoK5OV7ucZC/VPkMTyL 87EnMrPPxBeWP+WZdjlc8K0SKR6D1vMgNAkiPiUBKMt9qvVYuXijfvJO1mD39SD9XkVx N2YA== X-Gm-Message-State: ALQs6tB82Xc+v3Yklwof5xS5ZvibQPimqn1TQ8xQ1NEtb77f6dALR3dL A9UU86ivlcO7AukQmTf68C2LYg== X-Received: by 2002:adf:b2f4:: with SMTP id g107-v6mr2076567wrd.205.1524065774777; Wed, 18 Apr 2018 08:36:14 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.36.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:36:14 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:48 +0100 Message-Id: <20180418153157.1960-15-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 14/23] ASoC: qdsp6: q6asm: Add support to audio stream apis X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch adds support to open, write and media format commands in the q6asm module. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- sound/soc/qcom/qdsp6/q6asm.c | 744 ++++++++++++++++++++++++++++++++++++++++++- sound/soc/qcom/qdsp6/q6asm.h | 49 +++ 2 files changed, 792 insertions(+), 1 deletion(-) -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index 51a5681dd61f..7f10d5f3c58b 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -17,10 +19,36 @@ #include "q6dsp-errno.h" #include "q6dsp-common.h" +#define ASM_STREAM_CMD_CLOSE 0x00010BCD +#define ASM_STREAM_CMD_FLUSH 0x00010BCE +#define ASM_SESSION_CMD_PAUSE 0x00010BD3 +#define ASM_DATA_CMD_EOS 0x00010BDB +#define ASM_NULL_POPP_TOPOLOGY 0x00010C68 +#define ASM_STREAM_CMD_FLUSH_READBUFS 0x00010C09 +#define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10 +#define ASM_STREAM_POSTPROC_TOPO_ID_NONE 0x00010C68 #define ASM_CMD_SHARED_MEM_MAP_REGIONS 0x00010D92 #define ASM_CMDRSP_SHARED_MEM_MAP_REGIONS 0x00010D93 #define ASM_CMD_SHARED_MEM_UNMAP_REGIONS 0x00010D94 - +#define ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2 0x00010D98 +#define ASM_DATA_EVENT_WRITE_DONE_V2 0x00010D99 +#define ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2 0x00010DA3 +#define ASM_SESSION_CMD_RUN_V2 0x00010DAA +#define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 0x00010DA5 +#define ASM_DATA_CMD_WRITE_V2 0x00010DAB +#define ASM_DATA_CMD_READ_V2 0x00010DAC +#define ASM_SESSION_CMD_SUSPEND 0x00010DEC +#define ASM_STREAM_CMD_OPEN_WRITE_V3 0x00010DB3 +#define ASM_STREAM_CMD_OPEN_READ_V3 0x00010DB4 +#define ASM_DATA_EVENT_READ_DONE_V2 0x00010D9A +#define ASM_STREAM_CMD_OPEN_READWRITE_V2 0x00010D8D + + +#define ASM_LEGACY_STREAM_SESSION 0 +/* Bit shift for the stream_perf_mode subfield. */ +#define ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ 29 +#define ASM_END_POINT_DEVICE_MATRIX 0 +#define ASM_DEFAULT_APP_TYPE 0 #define ASM_SYNC_IO_MODE 0x0001 #define ASM_ASYNC_IO_MODE 0x0002 #define ASM_TUN_READ_IO_MODE 0x0004 /* tunnel read write mode */ @@ -46,6 +74,96 @@ struct avs_cmd_shared_mem_unmap_regions { u32 mem_map_handle; } __packed; +struct asm_data_cmd_media_fmt_update_v2 { + u32 fmt_blk_size; +} __packed; + +struct asm_multi_channel_pcm_fmt_blk_v2 { + struct apr_hdr hdr; + struct asm_data_cmd_media_fmt_update_v2 fmt_blk; + u16 num_channels; + u16 bits_per_sample; + u32 sample_rate; + u16 is_signed; + u16 reserved; + u8 channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL]; +} __packed; + +struct asm_stream_cmd_set_encdec_param { + u32 param_id; + u32 param_size; +} __packed; + +struct asm_enc_cfg_blk_param_v2 { + u32 frames_per_buf; + u32 enc_cfg_blk_size; +} __packed; + +struct asm_multi_channel_pcm_enc_cfg_v2 { + struct apr_hdr hdr; + struct asm_stream_cmd_set_encdec_param encdec; + struct asm_enc_cfg_blk_param_v2 encblk; + uint16_t num_channels; + uint16_t bits_per_sample; + uint32_t sample_rate; + uint16_t is_signed; + uint16_t reserved; + uint8_t channel_mapping[8]; +} __packed; + +struct asm_data_cmd_read_v2 { + struct apr_hdr hdr; + u32 buf_addr_lsw; + u32 buf_addr_msw; + u32 mem_map_handle; + u32 buf_size; + u32 seq_id; +} __packed; + +struct asm_data_cmd_read_v2_done { + u32 status; + u32 buf_addr_lsw; + u32 buf_addr_msw; +}; + +struct asm_stream_cmd_open_read_v3 { + struct apr_hdr hdr; + u32 mode_flags; + u32 src_endpointype; + u32 preprocopo_id; + u32 enc_cfg_id; + u16 bits_per_sample; + u16 reserved; +} __packed; + +struct asm_data_cmd_write_v2 { + struct apr_hdr hdr; + u32 buf_addr_lsw; + u32 buf_addr_msw; + u32 mem_map_handle; + u32 buf_size; + u32 seq_id; + u32 timestamp_lsw; + u32 timestamp_msw; + u32 flags; +} __packed; + +struct asm_stream_cmd_open_write_v3 { + struct apr_hdr hdr; + uint32_t mode_flags; + uint16_t sink_endpointype; + uint16_t bits_per_sample; + uint32_t postprocopo_id; + uint32_t dec_fmt_id; +} __packed; + +struct asm_session_cmd_run_v2 { + struct apr_hdr hdr; + u32 flags; + u32 time_lsw; + u32 time_msw; +} __packed; + struct audio_buffer { phys_addr_t phys; uint32_t used; @@ -394,6 +512,153 @@ static struct audio_client *q6asm_get_audio_client(struct q6asm *a, return a->session[session_id]; } +static int32_t q6asm_stream_callback(struct apr_device *adev, + struct apr_client_message *data, + int session_id) +{ + struct q6asm *q6asm = dev_get_drvdata(&adev->dev); + struct aprv2_ibasic_rsp_result_t *result; + struct audio_port_data *port; + struct audio_client *ac; + uint32_t token; + uint32_t client_event = 0; + + ac = q6asm_get_audio_client(q6asm, session_id); + if (!ac)/* Audio client might already be freed by now */ + return 0; + + if (!q6asm_is_valid_audio_client(ac)) + return -EINVAL; + + result = data->payload; + + switch (data->opcode) { + case APR_BASIC_RSP_RESULT: + token = data->token; + switch (result->opcode) { + case ASM_SESSION_CMD_PAUSE: + client_event = ASM_CLIENT_EVENT_CMD_PAUSE_DONE; + break; + case ASM_SESSION_CMD_SUSPEND: + client_event = ASM_CLIENT_EVENT_CMD_SUSPEND_DONE; + break; + case ASM_DATA_CMD_EOS: + client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE; + break; + break; + case ASM_STREAM_CMD_FLUSH: + client_event = ASM_CLIENT_EVENT_CMD_FLUSH_DONE; + break; + case ASM_SESSION_CMD_RUN_V2: + client_event = ASM_CLIENT_EVENT_CMD_RUN_DONE; + break; + + case ASM_STREAM_CMD_FLUSH_READBUFS: + if (token != ac->session) { + dev_err(ac->dev, "session invalid\n"); + return -EINVAL; + } + case ASM_STREAM_CMD_CLOSE: + client_event = ASM_CLIENT_EVENT_CMD_CLOSE_DONE; + break; + case ASM_STREAM_CMD_OPEN_WRITE_V3: + case ASM_STREAM_CMD_OPEN_READ_V3: + case ASM_STREAM_CMD_OPEN_READWRITE_V2: + case ASM_STREAM_CMD_SET_ENCDEC_PARAM: + case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: + if (result->status != 0) { + dev_err(ac->dev, + "cmd = 0x%x returned error = 0x%x\n", + result->opcode, result->status); + ac->result = *result; + wake_up(&ac->cmd_wait); + return 0; + } + break; + default: + dev_err(ac->dev, "command[0x%x] not expecting rsp\n", + result->opcode); + break; + } + + ac->result = *result; + wake_up(&ac->cmd_wait); + + if (ac->cb) + ac->cb(client_event, data->token, + data->payload, ac->priv); + + return 0; + + case ASM_DATA_EVENT_WRITE_DONE_V2: + port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; + + client_event = ASM_CLIENT_EVENT_DATA_WRITE_DONE; + + if (ac->io_mode & ASM_SYNC_IO_MODE) { + phys_addr_t phys; + unsigned long flags; + + spin_lock_irqsave(&ac->buf_lock, flags); + if (!port->buf) { + spin_unlock_irqrestore(&ac->buf_lock, flags); + return 0; + } + + phys = port->buf[data->token].phys; + + if (lower_32_bits(phys) != result->opcode || + upper_32_bits(phys) != result->status) { + dev_err(ac->dev, "Expected addr %pa\n", + &port->buf[data->token].phys); + spin_unlock_irqrestore(&ac->buf_lock, flags); + return -EINVAL; + } + token = data->token; + port->buf[token].used = 1; + spin_unlock_irqrestore(&ac->buf_lock, flags); + } + break; + case ASM_DATA_EVENT_READ_DONE_V2: + port = &ac->port[SNDRV_PCM_STREAM_CAPTURE]; + client_event = ASM_CLIENT_EVENT_DATA_READ_DONE; + + if (ac->io_mode & ASM_SYNC_IO_MODE) { + struct asm_data_cmd_read_v2_done *done = data->payload; + unsigned long flags; + phys_addr_t phys; + + spin_lock_irqsave(&ac->buf_lock, flags); + if (!port->buf) { + spin_unlock_irqrestore(&ac->buf_lock, flags); + return 0; + } + + phys = port->buf[data->token].phys; + token = data->token; + port->buf[token].used = 0; + + if (upper_32_bits(phys) != done->buf_addr_msw || + lower_32_bits(phys) != done->buf_addr_lsw) { + dev_err(ac->dev, "Expected addr %pa %08x-%08x\n", + &port->buf[data->token].phys, + done->buf_addr_lsw, + done->buf_addr_msw); + spin_unlock_irqrestore(&ac->buf_lock, flags); + return -EINVAL; + } + spin_unlock_irqrestore(&ac->buf_lock, flags); + } + + break; + } + + if (ac->cb) + ac->cb(client_event, data->token, data->payload, ac->priv); + + return 0; +} + static int q6asm_srvc_callback(struct apr_device *adev, struct apr_client_message *data) { @@ -403,6 +668,11 @@ static int q6asm_srvc_callback(struct apr_device *adev, struct audio_port_data *port; uint32_t dir = 0; uint32_t sid = 0; + int session_id; + + session_id = (data->dest_port >> 8) & 0xFF; + if (session_id) + return q6asm_stream_callback(adev, data, session_id); result = data->payload; sid = (data->token >> 8) & 0x0F; @@ -510,6 +780,478 @@ struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb, } EXPORT_SYMBOL_GPL(q6asm_audio_client_alloc); +static int q6asm_ac_send_cmd_sync(struct audio_client *ac, void *cmd) +{ + struct apr_hdr *hdr = cmd; + int rc; + + mutex_lock(&ac->lock); + ac->result.opcode = 0; + ac->result.status = 0; + + rc = apr_send_pkt(ac->adev, cmd); + if (rc < 0) + goto err; + + rc = wait_event_timeout(ac->cmd_wait, + (ac->result.opcode == hdr->opcode), 5 * HZ); + if (!rc) { + dev_err(ac->dev, "CMD timeout\n"); + rc = -ETIMEDOUT; + goto err; + } + + if (ac->result.status > 0) { + dev_err(ac->dev, "DSP returned error[%x]\n", + ac->result.status); + rc = -EINVAL; + } + + +err: + mutex_unlock(&ac->lock); + return rc; +} + +/** + * q6asm_open_write() - Open audio client for writing + * + * @ac: audio client pointer + * @format: audio sample format + * @bits_per_sample: bits per sample + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_open_write(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample) +{ + struct asm_stream_cmd_open_write_v3 open; + int rc; + + q6asm_add_hdr(ac, &open.hdr, sizeof(open), true, ac->stream_id); + + open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3; + open.mode_flags = 0x00; + open.mode_flags |= ASM_LEGACY_STREAM_SESSION; + + /* source endpoint : matrix */ + open.sink_endpointype = ASM_END_POINT_DEVICE_MATRIX; + open.bits_per_sample = bits_per_sample; + open.postprocopo_id = ASM_NULL_POPP_TOPOLOGY; + + switch (format) { + case FORMAT_LINEAR_PCM: + open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; + break; + default: + dev_err(ac->dev, "Invalid format 0x%x\n", format); + return -EINVAL; + } + + rc = q6asm_ac_send_cmd_sync(ac, &open); + if (rc < 0) + return rc; + + ac->io_mode |= ASM_TUN_WRITE_IO_MODE; + + return 0; +} +EXPORT_SYMBOL_GPL(q6asm_open_write); + +static int __q6asm_run(struct audio_client *ac, uint32_t flags, + uint32_t msw_ts, uint32_t lsw_ts, bool wait) +{ + struct asm_session_cmd_run_v2 run; + + q6asm_add_hdr(ac, &run.hdr, sizeof(run), true, ac->stream_id); + + run.hdr.opcode = ASM_SESSION_CMD_RUN_V2; + run.flags = flags; + run.time_lsw = lsw_ts; + run.time_msw = msw_ts; + if (wait) + return q6asm_ac_send_cmd_sync(ac, &run); + else + return apr_send_pkt(ac->adev, &run); + +} + +/** + * q6asm_run() - start the audio client + * + * @ac: audio client pointer + * @flags: flags associated with write + * @msw_ts: timestamp msw + * @lsw_ts: timestamp lsw + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_run(struct audio_client *ac, uint32_t flags, + uint32_t msw_ts, uint32_t lsw_ts) +{ + return __q6asm_run(ac, flags, msw_ts, lsw_ts, true); +} +EXPORT_SYMBOL_GPL(q6asm_run); + +/** + * q6asm_run_nowait() - start the audio client withou blocking + * + * @ac: audio client pointer + * @flags: flags associated with write + * @msw_ts: timestamp msw + * @lsw_ts: timestamp lsw + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, + uint32_t msw_ts, uint32_t lsw_ts) +{ + return __q6asm_run(ac, flags, msw_ts, lsw_ts, false); +} +EXPORT_SYMBOL_GPL(q6asm_run_nowait); + +/** + * q6asm_media_format_block_multi_ch_pcm() - setup pcm configuration + * + * @ac: audio client pointer + * @rate: audio sample rate + * @channels: number of audio channels. + * @use_default_chmap: flag to use default ch map. + * @channel_map: channel map pointer + * @bits_per_sample: bits per sample + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, + uint32_t rate, uint32_t channels, + u8 channel_map[PCM_FORMAT_MAX_NUM_CHANNEL], + uint16_t bits_per_sample) +{ + struct asm_multi_channel_pcm_fmt_blk_v2 fmt; + u8 *channel_mapping; + int rc; + + q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), true, ac->stream_id); + + fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; + fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) - + sizeof(fmt.fmt_blk); + fmt.num_channels = channels; + fmt.bits_per_sample = bits_per_sample; + fmt.sample_rate = rate; + fmt.is_signed = 1; + + channel_mapping = fmt.channel_mapping; + + if (channel_map) { + memcpy(channel_mapping, channel_map, + PCM_FORMAT_MAX_NUM_CHANNEL); + } else { + if (q6dsp_map_channels(channel_mapping, channels)) { + dev_err(ac->dev, " map channels failed %d\n", channels); + return -EINVAL; + } + } + + rc = q6asm_ac_send_cmd_sync(ac, &fmt); + if (rc < 0) + goto fail_cmd; + + return 0; +fail_cmd: + return rc; +} +EXPORT_SYMBOL_GPL(q6asm_media_format_block_multi_ch_pcm); + +/** + * q6asm_enc_cfg_blk_pcm_format_support() - setup pcm configuration for capture + * + * @ac: audio client pointer + * @rate: audio sample rate + * @channels: number of audio channels. + * @use_default_chmap: flag to use default ch map. + * @channel_map: channel map pointer + * @bits_per_sample: bits per sample + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, + uint32_t rate, uint32_t channels, uint16_t bits_per_sample) +{ + struct asm_multi_channel_pcm_enc_cfg_v2 enc_cfg; + u8 *channel_mapping; + u32 frames_per_buf = 0; + + q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), true, ac->stream_id); + enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM; + enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2; + enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) - + sizeof(enc_cfg.encdec); + enc_cfg.encblk.frames_per_buf = frames_per_buf; + enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size - + sizeof(struct asm_enc_cfg_blk_param_v2); + + enc_cfg.num_channels = channels; + enc_cfg.bits_per_sample = bits_per_sample; + enc_cfg.sample_rate = rate; + enc_cfg.is_signed = 1; + channel_mapping = enc_cfg.channel_mapping; + + memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL); + + if (q6dsp_map_channels(channel_mapping, channels)) + return -EINVAL; + + + return q6asm_ac_send_cmd_sync(ac, &enc_cfg); +} +EXPORT_SYMBOL_GPL(q6asm_enc_cfg_blk_pcm_format_support); + +/** + * q6asm_read() - read data of period size from audio client + * + * @ac: audio client pointer + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_read(struct audio_client *ac) +{ + struct asm_data_cmd_read_v2 read; + struct audio_port_data *port; + struct audio_buffer *ab; + int rc; + + if (!(ac->io_mode & ASM_SYNC_IO_MODE)) + return 0; + + port = &ac->port[SNDRV_PCM_STREAM_CAPTURE]; + q6asm_add_hdr(ac, &read.hdr, sizeof(read), false, ac->stream_id); + ab = &port->buf[port->dsp_buf]; + read.hdr.opcode = ASM_DATA_CMD_READ_V2; + read.buf_addr_lsw = lower_32_bits(ab->phys); + read.buf_addr_msw = upper_32_bits(ab->phys); + read.mem_map_handle = ac->port[SNDRV_PCM_STREAM_CAPTURE].mem_map_handle; + + read.buf_size = ab->size; + read.seq_id = port->dsp_buf; + read.hdr.token = port->dsp_buf; + + port->dsp_buf++; + + if (port->dsp_buf >= port->num_periods) + port->dsp_buf = 0; + + rc = apr_send_pkt(ac->adev, &read); + if (rc < 0) { + pr_err("read op[0x%x]rc[%d]\n", read.hdr.opcode, rc); + return rc; + } + + return 0; +} +EXPORT_SYMBOL_GPL(q6asm_read); + +static int __q6asm_open_read(struct audio_client *ac, + uint32_t format, uint16_t bits_per_sample) +{ + struct asm_stream_cmd_open_read_v3 open; + + q6asm_add_hdr(ac, &open.hdr, sizeof(open), true, ac->stream_id); + open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V3; + /* Stream prio : High, provide meta info with encoded frames */ + open.src_endpointype = ASM_END_POINT_DEVICE_MATRIX; + + open.preprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_NONE; + open.bits_per_sample = bits_per_sample; + open.mode_flags = 0x0; + + open.mode_flags |= ASM_LEGACY_STREAM_SESSION << + ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ; + + switch (format) { + case FORMAT_LINEAR_PCM: + open.mode_flags |= 0x00; + open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; + break; + default: + pr_err("Invalid format[%d]\n", format); + } + + return q6asm_ac_send_cmd_sync(ac, &open); +} + +/** + * q6asm_open_read() - Open audio client for reading + * + * @ac: audio client pointer + * @format: audio sample format + * @bits_per_sample: bits per sample + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_open_read(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample) +{ + return __q6asm_open_read(ac, format, bits_per_sample); +} +EXPORT_SYMBOL_GPL(q6asm_open_read); + +/** + * q6asm_write_async() - non blocking write + * + * @ac: audio client pointer + * @len: lenght in bytes + * @msw_ts: timestamp msw + * @lsw_ts: timestamp lsw + * @flags: flags associated with write + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, + uint32_t lsw_ts, uint32_t flags) +{ + struct asm_data_cmd_write_v2 write; + struct audio_port_data *port; + struct audio_buffer *ab; + int rc = 0; + + if (!(ac->io_mode & ASM_SYNC_IO_MODE)) + return 0; + + port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; + q6asm_add_hdr(ac, &write.hdr, sizeof(write), false, + ac->stream_id); + + ab = &port->buf[port->dsp_buf]; + + write.hdr.token = port->dsp_buf; + write.hdr.opcode = ASM_DATA_CMD_WRITE_V2; + write.buf_addr_lsw = lower_32_bits(ab->phys); + write.buf_addr_msw = upper_32_bits(ab->phys); + write.buf_size = len; + write.seq_id = port->dsp_buf; + write.timestamp_lsw = lsw_ts; + write.timestamp_msw = msw_ts; + write.mem_map_handle = + ac->port[SNDRV_PCM_STREAM_PLAYBACK].mem_map_handle; + + if (flags == NO_TIMESTAMP) + write.flags = (flags & 0x800000FF); + else + write.flags = (0x80000000 | flags); + + port->dsp_buf++; + + if (port->dsp_buf >= port->num_periods) + port->dsp_buf = 0; + + rc = apr_send_pkt(ac->adev, &write); + if (rc < 0) + return rc; + + return 0; +} +EXPORT_SYMBOL_GPL(q6asm_write_async); + +static void q6asm_reset_buf_state(struct audio_client *ac) +{ + struct audio_port_data *port = NULL; + unsigned long flags; + int loopcnt = 0; + int cnt = 0; + int used; + + if (!(ac->io_mode & ASM_SYNC_IO_MODE)) + return; + + used = (ac->io_mode & ASM_TUN_WRITE_IO_MODE ? 1 : 0); + spin_lock_irqsave(&ac->buf_lock, flags); + for (loopcnt = 0; loopcnt <= SNDRV_PCM_STREAM_CAPTURE; loopcnt++) { + port = &ac->port[loopcnt]; + cnt = port->num_periods - 1; + port->dsp_buf = 0; + while (cnt >= 0) { + if (!port->buf) + continue; + port->buf[cnt].used = used; + cnt--; + } + } + spin_unlock_irqrestore(&ac->buf_lock, flags); +} + +static int __q6asm_cmd(struct audio_client *ac, int cmd, bool wait) +{ + int stream_id = ac->stream_id; + struct apr_hdr hdr; + int rc; + + q6asm_add_hdr(ac, &hdr, sizeof(hdr), true, stream_id); + + switch (cmd) { + case CMD_PAUSE: + hdr.opcode = ASM_SESSION_CMD_PAUSE; + break; + case CMD_SUSPEND: + hdr.opcode = ASM_SESSION_CMD_SUSPEND; + break; + case CMD_FLUSH: + hdr.opcode = ASM_STREAM_CMD_FLUSH; + break; + case CMD_OUT_FLUSH: + hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS; + break; + case CMD_EOS: + hdr.opcode = ASM_DATA_CMD_EOS; + break; + case CMD_CLOSE: + hdr.opcode = ASM_STREAM_CMD_CLOSE; + break; + default: + return -EINVAL; + } + + if (wait) + rc = q6asm_ac_send_cmd_sync(ac, &hdr); + else + return apr_send_pkt(ac->adev, &hdr); + + if (rc < 0) + return rc; + + if (cmd == CMD_FLUSH) + q6asm_reset_buf_state(ac); + + return 0; +} + +/** + * q6asm_cmd() - run cmd on audio client + * + * @ac: audio client pointer + * @cmd: command to run on audio client. + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_cmd(struct audio_client *ac, int cmd) +{ + return __q6asm_cmd(ac, cmd, true); +} +EXPORT_SYMBOL_GPL(q6asm_cmd); + +/** + * q6asm_cmd_nowait() - non blocking, run cmd on audio client + * + * @ac: audio client pointer + * @cmd: command to run on audio client. + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_cmd_nowait(struct audio_client *ac, int cmd) +{ + return __q6asm_cmd(ac, cmd, false); +} +EXPORT_SYMBOL_GPL(q6asm_cmd_nowait); static int q6asm_probe(struct apr_device *adev) { diff --git a/sound/soc/qcom/qdsp6/q6asm.h b/sound/soc/qcom/qdsp6/q6asm.h index faa49ca1cde6..9ed15e0edaf0 100644 --- a/sound/soc/qcom/qdsp6/q6asm.h +++ b/sound/soc/qcom/qdsp6/q6asm.h @@ -1,8 +1,36 @@ // SPDX-License-Identifier: GPL-2.0 #ifndef __Q6_ASM_H__ #define __Q6_ASM_H__ +#include "q6dsp-common.h" +#include + +/* ASM client callback events */ +#define CMD_PAUSE 0x0001 +#define ASM_CLIENT_EVENT_CMD_PAUSE_DONE 0x1001 +#define CMD_FLUSH 0x0002 +#define ASM_CLIENT_EVENT_CMD_FLUSH_DONE 0x1002 +#define CMD_EOS 0x0003 +#define ASM_CLIENT_EVENT_CMD_EOS_DONE 0x1003 +#define CMD_CLOSE 0x0004 +#define ASM_CLIENT_EVENT_CMD_CLOSE_DONE 0x1004 +#define CMD_OUT_FLUSH 0x0005 +#define ASM_CLIENT_EVENT_CMD_OUT_FLUSH_DONE 0x1005 +#define CMD_SUSPEND 0x0006 +#define ASM_CLIENT_EVENT_CMD_SUSPEND_DONE 0x1006 +#define ASM_CLIENT_EVENT_CMD_RUN_DONE 0x1008 +#define ASM_CLIENT_EVENT_DATA_WRITE_DONE 0x1009 +#define ASM_CLIENT_EVENT_DATA_READ_DONE 0x100a + +enum { + LEGACY_PCM_MODE = 0, + LOW_LATENCY_PCM_MODE, + ULTRA_LOW_LATENCY_PCM_MODE, + ULL_POST_PROCESSING_PCM_MODE, +}; #define MAX_SESSIONS 16 +#define NO_TIMESTAMP 0xFF00 +#define FORMAT_LINEAR_PCM 0x0000 typedef void (*q6asm_cb) (uint32_t opcode, uint32_t token, void *payload, void *priv); @@ -11,6 +39,27 @@ struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb, void *priv, int session_id, int perf_mode); void q6asm_audio_client_free(struct audio_client *ac); +int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, + uint32_t lsw_ts, uint32_t flags); +int q6asm_open_write(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample); + +int q6asm_open_read(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample); +int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, + uint32_t rate, uint32_t channels, uint16_t bits_per_sample); +int q6asm_read(struct audio_client *ac); + +int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, + uint32_t rate, uint32_t channels, + u8 channel_map[PCM_FORMAT_MAX_NUM_CHANNEL], + uint16_t bits_per_sample); +int q6asm_run(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, + uint32_t lsw_ts); +int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, + uint32_t lsw_ts); +int q6asm_cmd(struct audio_client *ac, int cmd); +int q6asm_cmd_nowait(struct audio_client *ac, int cmd); int q6asm_get_session_id(struct audio_client *ac); int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac, From patchwork Wed Apr 18 15:31:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133659 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp37881ljf; Wed, 18 Apr 2018 08:38:31 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/I00OWeRFIMhIYiaIp0+lklnV5kz1g03mIp6MpR247Vy5fsbWRClYo/LIHHaFELJ/ZqDV9 X-Received: by 2002:adf:a690:: with SMTP id t16-v6mr2068826wrc.1.1524065911765; Wed, 18 Apr 2018 08:38:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065911; cv=none; d=google.com; s=arc-20160816; b=oPskqU44V6uW3AgrnRN1+d8DZi/KdT3/80Jr05DW65v0n/RjWXSMD8TNlKf0z9Nl1/ Aj4AQuEvxFYOLxMbmywcAtZT1W3gx1F8Ol91RXKEIBdpW6R/Pvrfe2kwYLn7E3W5jWs5 vhZ3NPI1a0RHZgB9t7B7xMIwlv9z3mjaaRh0asI/T+qUvGHzX7SFvG1IpzDIW1NNXGlW b/r+exW4iZtTwJJkfWMR1x9OgPuA416lNX+UQ2LJavPWt/9q0o8zl0tiM2WtVkbpuaJh bTrKuFdpdokKunYrV9AegUmrVW33UQ3eGS4gIG+GYVa1xOpKiz4hOGVWHJnCqZx8ky1l tTDg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=JQ6n1WiWaxOIfI/JdqRGmBDVONacRFX4s0h9q7Wpuh4=; b=WyRMbPeFBht1ervBucy2FuPGnMxheUozA2U6NcjTURxz8waBmS5kLsuWgj5IFAvbjb UyHgodoZA9pp0ihyrvARTUxubVDGn82XVqRQAuQ1Id/csRwEPpziXPz4mkq+Y9gnZQzl NVvm6GP1VcaCA7fojgva5SNGG7NmJTg0Fmujwdyf56Ph+C5TO0M3yN8/AJNsuzn0mCnC hM8D/6AiXMrmCbnDmpvrBz7mdQcLH5OEQf6GCPCZdV3YHcWY59EOkjc2dSUayGrpVARN 71B1/FLE0jeiZAt8SUSluEj7Alc9z4hTyNxqvj+N2IWFjMp+q6CS2ot6uStoNpmoGFv5 x9dA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=OWV156Su; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id a26-v6si1195328wrd.390.2018.04.18.08.38.31; Wed, 18 Apr 2018 08:38:31 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=OWV156Su; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id C1EF02676F7; Wed, 18 Apr 2018 17:36:37 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id A2D412676A7; Wed, 18 Apr 2018 17:36:25 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f195.google.com (mail-wr0-f195.google.com [209.85.128.195]) by alsa0.perex.cz (Postfix) with ESMTP id CB6252676DC for ; Wed, 18 Apr 2018 17:36:16 +0200 (CEST) Received: by mail-wr0-f195.google.com with SMTP id v24-v6so6035088wra.8 for ; Wed, 18 Apr 2018 08:36:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=tcrUhGU2hqiOTPUnPLrCmG7DDVfGqr+/70PZmphgcfs=; b=OWV156SuE4pHsFOVI162Y5ZJL3V4vOhCqtGBRUPmRcG+/eF9/08G4/jmdFIEWpWOWp 2hWPv2cP+3tmo1ON4p5PJjS3VJMFwx8Q3t4T9D3ikpOdms5ueyFv6ZXz6E9pLvSVC+dy JgmFB/jzYqrA/0E7GkOgKlpqbmhmmU8UGKQcY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tcrUhGU2hqiOTPUnPLrCmG7DDVfGqr+/70PZmphgcfs=; b=BCo4CGtG0Csn4Q8XxqcnHOhfH2Dy06Xh8Er+ffYWXz1XQ3mUVIsxDxP1ZXXVPwECx8 UVsmV+bwjC4diy/NhJdu7e7KzkIuYF/DMPdn+vpwmHb4zlP4+1WJ00XwRvL90ikR606P Vo3rG2X2d26FZBryQHFx81uy33vE6MqEMZ0ozTdCpyYr6sOe+sRNZ+KoS8PWiQNmrZtp tSqt3QSF+Q9ytFEORPIOap6//UVi+s6UGQcKzp2dl3YxQHjHYMxXMTNlmleJKnjfChZi tNU06YlvSAAFcKSWQgqTzY0e+qHR/MiS6MYc/9tHsWyWRdAcLvV9+1z5rVNeHIXUGt03 5GAQ== X-Gm-Message-State: ALQs6tAFiJ/g0rTfJaTri6cxEDpnhr1r5MyMG7+zaQ4LnSotPhRmpQpJ 3SGrQy40NjypwMA+JBh7FhoWIw== X-Received: by 2002:adf:b3c3:: with SMTP id x3-v6mr2097816wrd.94.1524065776220; Wed, 18 Apr 2018 08:36:16 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.36.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:36:15 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:49 +0100 Message-Id: <20180418153157.1960-16-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 15/23] ASoC: qdsp6: q6core: Add q6core driver X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch adds support to core apr service, which is used to query status of other static and dynamic services on the dsp. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- sound/soc/qcom/Kconfig | 4 + sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6core.c | 380 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6core.h | 15 ++ 4 files changed, 400 insertions(+) create mode 100644 sound/soc/qcom/qdsp6/q6core.c create mode 100644 sound/soc/qcom/qdsp6/q6core.h -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index a07181290624..488ee93ee084 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -56,6 +56,9 @@ config SND_SOC_QDSP6_ADM config SND_SOC_QDSP6_ASM tristate +config SND_SOC_QDSP6_CORE + tristate + config SND_SOC_QDSP6 tristate "SoC ALSA audio driver for QDSP6" depends on QCOM_APR && HAS_DMA @@ -63,6 +66,7 @@ config SND_SOC_QDSP6 select SND_SOC_QDSP6_AFE select SND_SOC_QDSP6_ADM select SND_SOC_QDSP6_ASM + select SND_SOC_QDSP6_CORE help To add support for MSM QDSP6 Soc Audio. This will enable sound soc platform specific diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index eea962315ab3..61f089bc0d25 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o obj-$(CONFIG_SND_SOC_QDSP6_ADM) += q6adm.o obj-$(CONFIG_SND_SOC_QDSP6_ASM) += q6asm.o +obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o diff --git a/sound/soc/qcom/qdsp6/q6core.c b/sound/soc/qcom/qdsp6/q6core.c new file mode 100644 index 000000000000..244ec153ab71 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6core.c @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation +// Copyright (c) 2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6core.h" +#include "q6dsp-errno.h" + +#define ADSP_STATE_READY_TIMEOUT_MS 3000 +#define Q6_READY_TIMEOUT_MS 100 +#define AVCS_CMD_ADSP_EVENT_GET_STATE 0x0001290C +#define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D +#define AVCS_GET_VERSIONS 0x00012905 +#define AVCS_GET_VERSIONS_RSP 0x00012906 +#define AVCS_CMD_GET_FWK_VERSION 0x001292c +#define AVCS_CMDRSP_GET_FWK_VERSION 0x001292d + +struct avcs_svc_info { + uint32_t service_id; + uint32_t version; +} __packed; + +struct avcs_cmdrsp_get_version { + uint32_t build_id; + uint32_t num_services; + struct avcs_svc_info svc_api_info[]; +} __packed; + +/* for ADSP2.8 and above */ +struct avcs_svc_api_info { + uint32_t service_id; + uint32_t api_version; + uint32_t api_branch_version; +} __packed; + +struct avcs_cmdrsp_get_fwk_version { + uint32_t build_major_version; + uint32_t build_minor_version; + uint32_t build_branch_version; + uint32_t build_subbranch_version; + uint32_t num_services; + struct avcs_svc_api_info svc_api_info[]; +} __packed; + +struct q6core { + struct apr_device *adev; + wait_queue_head_t wait; + uint32_t avcs_state; + struct mutex lock; + bool resp_received; + uint32_t num_services; + struct avcs_cmdrsp_get_fwk_version *fwk_version; + struct avcs_cmdrsp_get_version *svc_version; + bool fwk_version_supported; + bool get_state_supported; + bool get_version_supported; + bool is_version_requested; +}; + +static struct q6core *g_core; + +static int q6core_callback(struct apr_device *adev, + struct apr_client_message *data) +{ + struct q6core *core = dev_get_drvdata(&adev->dev); + struct aprv2_ibasic_rsp_result_t *result; + + result = data->payload; + switch (data->opcode) { + case APR_BASIC_RSP_RESULT:{ + result = data->payload; + switch (result->opcode) { + case AVCS_GET_VERSIONS: + if (result->status == ADSP_EUNSUPPORTED) + core->get_version_supported = false; + core->resp_received = true; + break; + case AVCS_CMD_GET_FWK_VERSION: + if (result->status == ADSP_EUNSUPPORTED) + core->fwk_version_supported = false; + core->resp_received = true; + break; + case AVCS_CMD_ADSP_EVENT_GET_STATE: + if (result->status == ADSP_EUNSUPPORTED) + core->get_state_supported = false; + core->resp_received = true; + break; + } + break; + } + case AVCS_CMDRSP_GET_FWK_VERSION: { + struct avcs_cmdrsp_get_fwk_version *fwk; + int bytes; + + fwk = data->payload; + core->fwk_version_supported = true; + bytes = sizeof(*fwk) + fwk->num_services * + sizeof(fwk->svc_api_info[0]); + + core->fwk_version = kzalloc(bytes, GFP_ATOMIC); + if (!core->fwk_version) + return -ENOMEM; + + memcpy(core->fwk_version, data->payload, bytes); + + core->resp_received = true; + + break; + } + case AVCS_GET_VERSIONS_RSP: { + struct avcs_cmdrsp_get_version *v; + int len; + + v = data->payload; + core->get_version_supported = true; + + len = sizeof(*v) + v->num_services * sizeof(v->svc_api_info[0]); + + core->svc_version = kzalloc(len, GFP_ATOMIC); + if (!core->svc_version) + return -ENOMEM; + + memcpy(core->svc_version, data->payload, len); + + core->resp_received = true; + + break; + } + case AVCS_CMDRSP_ADSP_EVENT_GET_STATE: + core->get_state_supported = true; + core->avcs_state = result->opcode; + + core->resp_received = true; + break; + default: + dev_err(&adev->dev, "Message id from adsp core svc: 0x%x\n", + data->opcode); + break; + } + + if (core->resp_received) + wake_up(&core->wait); + + return 0; +} + +static int q6core_get_fwk_versions(struct q6core *core) +{ + struct apr_device *adev = core->adev; + struct apr_hdr hdr = {0}; + int rc; + + hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + hdr.pkt_size = APR_HDR_SIZE; + hdr.opcode = AVCS_CMD_GET_FWK_VERSION; + + rc = apr_send_pkt(adev, &hdr); + if (rc < 0) + return rc; + + rc = wait_event_timeout(core->wait, (core->resp_received), + msecs_to_jiffies(Q6_READY_TIMEOUT_MS)); + if (rc > 0 && core->resp_received) { + core->resp_received = false; + + if (!core->fwk_version_supported) + return -ENOTSUPP; + else + return 0; + } + + + return rc; +} + +static int q6core_get_svc_versions(struct q6core *core) +{ + struct apr_device *adev = core->adev; + struct apr_hdr hdr = {0}; + int rc; + + hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + hdr.pkt_size = APR_HDR_SIZE; + hdr.opcode = AVCS_GET_VERSIONS; + + rc = apr_send_pkt(adev, &hdr); + if (rc < 0) + return rc; + + rc = wait_event_timeout(core->wait, (core->resp_received), + msecs_to_jiffies(Q6_READY_TIMEOUT_MS)); + if (rc > 0 && core->resp_received) { + core->resp_received = false; + return 0; + } + + return rc; +} + +static bool __q6core_is_adsp_ready(struct q6core *core) +{ + struct apr_device *adev = core->adev; + struct apr_hdr hdr = {0}; + int rc; + + core->get_state_supported = false; + + hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + hdr.pkt_size = APR_HDR_SIZE; + hdr.opcode = AVCS_CMD_ADSP_EVENT_GET_STATE; + + rc = apr_send_pkt(adev, &hdr); + if (rc < 0) + return false; + + rc = wait_event_timeout(core->wait, (core->resp_received), + msecs_to_jiffies(Q6_READY_TIMEOUT_MS)); + if (rc > 0 && core->resp_received) { + core->resp_received = false; + + if (core->avcs_state == 0x1) + return true; + } + + /* assume that the adsp is up if we not support this command */ + if (!core->get_state_supported) + return true; + + return false; +} + +/** + * q6core_get_svc_api_info() - Get version number of a service. + * + * @svc_id: service id of the service. + * @info: Valid struct pointer to fill svc api information. + * + * Return: zero on success and error code on failure or unsupported + */ +int q6core_get_svc_api_info(int svc_id, struct q6core_svc_api_info *ainfo) +{ + int i; + int ret = -ENOTSUPP; + + if (!g_core || !ainfo) + return 0; + + mutex_lock(&g_core->lock); + if (!g_core->is_version_requested) { + if (q6core_get_fwk_versions(g_core) == -ENOTSUPP) + q6core_get_svc_versions(g_core); + g_core->is_version_requested = true; + } + + if (g_core->fwk_version_supported) { + for (i = 0; i < g_core->fwk_version->num_services; i++) { + struct avcs_svc_api_info *info; + + info = &g_core->fwk_version->svc_api_info[i]; + if (svc_id != info->service_id) + continue; + + ainfo->api_version = info->api_version; + ainfo->api_branch_version = info->api_branch_version; + ret = 0; + break; + } + } else if (g_core->get_version_supported) { + for (i = 0; i < g_core->svc_version->num_services; i++) { + struct avcs_svc_info *info; + + info = &g_core->svc_version->svc_api_info[i]; + if (svc_id != info->service_id) + continue; + + ainfo->api_version = info->version; + ainfo->api_branch_version = 0; + ret = 0; + break; + } + } + + mutex_unlock(&g_core->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(q6core_get_svc_api_info); + +/** + * q6core_is_adsp_ready() - Get status of adsp + * + * Return: Will be an true if adsp is ready and false if not. + */ +bool q6core_is_adsp_ready(void) +{ + unsigned long timeout; + bool ret = false; + + if (!g_core) + return false; + + mutex_lock(&g_core->lock); + timeout = jiffies + msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS); + for (;;) { + if (__q6core_is_adsp_ready(g_core)) { + ret = true; + break; + } + + if (!time_after(timeout, jiffies)) { + ret = false; + break; + } + } + + mutex_unlock(&g_core->lock); + return ret; +} +EXPORT_SYMBOL_GPL(q6core_is_adsp_ready); + +static int q6core_probe(struct apr_device *adev) +{ + g_core = kzalloc(sizeof(*g_core), GFP_KERNEL); + if (!g_core) + return -ENOMEM; + + dev_set_drvdata(&adev->dev, g_core); + + mutex_init(&g_core->lock); + g_core->adev = adev; + init_waitqueue_head(&g_core->wait); + return 0; +} + +static int q6core_exit(struct apr_device *adev) +{ + struct q6core *core = dev_get_drvdata(&adev->dev); + + if (core->fwk_version_supported) + kfree(core->fwk_version); + if (core->get_version_supported) + kfree(core->svc_version); + + kfree(core); + g_core = NULL; + + return 0; +} + +static const struct of_device_id q6core_device_id[] = { + { .compatible = "qcom,q6core" }, + {}, +}; +MODULE_DEVICE_TABLE(of, q6core_device_id); + +static struct apr_driver qcom_q6core_driver = { + .probe = q6core_probe, + .remove = q6core_exit, + .callback = q6core_callback, + .driver = { + .name = "qcom-q6core", + .of_match_table = of_match_ptr(q6core_device_id), + }, +}; + +module_apr_driver(qcom_q6core_driver); +MODULE_DESCRIPTION("q6 core"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/qdsp6/q6core.h b/sound/soc/qcom/qdsp6/q6core.h new file mode 100644 index 000000000000..7678abd8fd46 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6core.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef __Q6CORE_H__ +#define __Q6CORE_H__ + +struct q6core_svc_api_info { + uint32_t service_id; + uint32_t api_version; + uint32_t api_branch_version; +}; + +bool q6core_is_adsp_ready(void); +int q6core_get_svc_api_info(int svc_id, struct q6core_svc_api_info *ainfo); + +#endif /* __Q6CORE_H__ */ From patchwork Wed Apr 18 15:31:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 133660 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp38010ljf; Wed, 18 Apr 2018 08:38:40 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+VqTKjZGaUjUMSz+Xzn1UGREIJGn3/xUEOGBRQcYJtv3ABaqB6KqDMdSWY0VnPeLs+5JbT X-Received: by 2002:adf:b722:: with SMTP id l34-v6mr2158175wre.85.1524065920271; Wed, 18 Apr 2018 08:38:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524065920; cv=none; d=google.com; s=arc-20160816; b=I16Jj+/gpmU4zPQ4Hm3XEWVntAnvTE4jeNxGZ0WGur6z1N7lF9Tmx0U6y4e8CflNfV pkTV9iX/9YXO95FPD9OYmUXGaBrVxoYLQvU1W8sOOVwxkj7/trWvrH7ULBqNDlvq24Ee xRahNo5m5rlZhrg4pSeDIOhfKxYn19cduS1dLADcPDTlX5DC9dzs9RWT8nByW0/Xec+T Y424H3r0tkFppv6xpSmly3OmrkxH31gqscaR+/BdiD8ApBaT7WIhpvZH53VyD7zJRiGM 3mfjW5UKWdcuuAms6Wypzw41AU2XfmAmndefIkJk4ahK9hVuRDq/ZBBcipRcbybsXNM3 0O6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=DIF75FHUj5uxA8Hf0jUoWGqnWCANMB8lo+cqZCcHbjI=; b=p3V0JKDcPcgyRSOHHyEx+gCGf2a0cyVBSK2K/wqGSHkYsdG1+HVKgXof9o4hMlWETb mmOp9R+SWQrpxmErxLEzzCI2Qx5YXg2T9S0iGRLbkPxd5HoKWQKWNEU8SFLxGmgAvU1N 0XZxqGyMeXrwIszI/DfgD//cFoyFlLa0J5oYkVMnLVLmOVXGHi+peCoErgZckfhrgpVs rhqCOPTRVGnCwT3T1DMNuoH2q3xMIKmVH9a7XudAfcdRNFZQ+HbluxUmVTH1rgITR5Wd d2xPbX5ygECZS9EYP954vcDcePHOtB/kIKGfoRET+lZDhbTYS+2o1zx5uS8f+7kSzG18 xifw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=j4AFTiHe; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id c4si1399512wmi.121.2018.04.18.08.38.40; Wed, 18 Apr 2018 08:38:40 -0700 (PDT) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=j4AFTiHe; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 66F81267730; Wed, 18 Apr 2018 17:36:41 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 4D7042676FA; Wed, 18 Apr 2018 17:36:29 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wr0-f194.google.com (mail-wr0-f194.google.com [209.85.128.194]) by alsa0.perex.cz (Postfix) with ESMTP id 1C0152676A2 for ; Wed, 18 Apr 2018 17:36:18 +0200 (CEST) Received: by mail-wr0-f194.google.com with SMTP id d19-v6so6063657wre.1 for ; Wed, 18 Apr 2018 08:36:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=939XqZSukR5YqfxnRE7xajvMmMoSvO/JjJJ0qIvIWWA=; b=j4AFTiHeRzEYAyXplwnATPhYrE3XTVEmSYzbEYllaoP/ANokgXjBaE6xorNS9nMC/M xIKdrvZULMYHxuAePeJaIyW//It87TcHl/jxscOa+YIHCTZoUpp3Af7709I9vmsh5oQ+ fzM/pm7IYog5rxATLUBQNIn2KjJ/Y6jfMczYs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=939XqZSukR5YqfxnRE7xajvMmMoSvO/JjJJ0qIvIWWA=; b=byr3vZp40q897fDmY3Rher6xugFp0vAv3E71CWgG38GrFA7ita4ELApIcZhO2qqnJC cY/N9HTMlKHJyHoFwKzjHlc7MBJeuAnqejFlnU5qYWtg/PB9BaELzF7o8KVTQxok1Yfn CSePSzkYZbmeEW/7KeVgFiHcDm2+gmlX0ZOfWXd61AXCEbxwCmRpVVuxdiu+RcvwLa8U vTbERmhI9y0+sHJu6e6PNEBQ4+gbq9wjGL4jp3L1mlW8D2FX2XMcUhYg1KCObGg81oE1 ADRNBMr8YidzrJyzWVv7Bza1F476FANLOAgNlqstmCZ2qmVZkIOxnRnPWGutGQI9yveO /smA== X-Gm-Message-State: ALQs6tCKCfzLSti6LputVsbE8lGrj1S25R4/DQZhzlHSeexwWzm07Qo8 xjvDp8affMCMxtRojJdqmnw0wA== X-Received: by 2002:adf:c358:: with SMTP id e24-v6mr2124994wrg.86.1524065777553; Wed, 18 Apr 2018 08:36:17 -0700 (PDT) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id x67sm2529314wma.23.2018.04.18.08.36.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 08:36:16 -0700 (PDT) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org Date: Wed, 18 Apr 2018 16:31:50 +0100 Message-Id: <20180418153157.1960-17-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> References: <20180418153157.1960-1-srinivas.kandagatla@linaro.org> Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, bgoswami@codeaurora.org, rohkumar@qti.qualcomm.com, gregkh@linuxfoundation.org, plai@codeaurora.org, lgirdwood@gmail.com, tiwai@suse.com, david.brown@linaro.org, Srinivas Kandagatla , linux-arm-kernel@lists.infradead.org, spatakok@qti.qualcomm.com, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH v5 16/23] ASoC: qdsp6: q6routing: Add q6routing driver X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Srinivas Kandagatla This patch adds support to q6 routing driver which configures route between ASM and AFE module using ADM apis. This driver uses dapm widgets to setup the matrix between AFE ports and ASM streams. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- sound/soc/qcom/Kconfig | 4 + sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6routing.c | 392 +++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6routing.h | 9 + 4 files changed, 406 insertions(+) create mode 100644 sound/soc/qcom/qdsp6/q6routing.c create mode 100644 sound/soc/qcom/qdsp6/q6routing.h -- 2.16.2 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 488ee93ee084..7a868a6fac1b 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -53,6 +53,9 @@ config SND_SOC_QDSP6_AFE config SND_SOC_QDSP6_ADM tristate +config SND_SOC_QDSP6_ROUTING + tristate + config SND_SOC_QDSP6_ASM tristate @@ -65,6 +68,7 @@ config SND_SOC_QDSP6 select SND_SOC_QDSP6_COMMON select SND_SOC_QDSP6_AFE select SND_SOC_QDSP6_ADM + select SND_SOC_QDSP6_ROUTING select SND_SOC_QDSP6_ASM select SND_SOC_QDSP6_CORE help diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 61f089bc0d25..6640bceccc18 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o obj-$(CONFIG_SND_SOC_QDSP6_ADM) += q6adm.o +obj-$(CONFIG_SND_SOC_QDSP6_ROUTING) += q6routing.o obj-$(CONFIG_SND_SOC_QDSP6_ASM) += q6asm.o obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c new file mode 100644 index 000000000000..b72bd9045fea --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation +// Copyright (c) 2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6afe.h" +#include "q6asm.h" +#include "q6adm.h" +#include "q6routing.h" + +struct session_data { + int state; + int port_id; + int path_type; + int app_type; + int acdb_id; + int sample_rate; + int bits_per_sample; + int channels; + int perf_mode; + int numcopps; + int fedai_id; + unsigned long copp_map; +}; + +struct msm_routing_data { + struct session_data sessions[MAX_SESSIONS]; + struct session_data port_data[AFE_MAX_PORTS]; + struct device *dev; + struct mutex lock; +}; + +static struct msm_routing_data *routing_data; + +/** + * q6routing_stream_open() - Register a new stream for route setup + * + * @fedai_id: Frontend dai id. + * @perf_mode: Performance mode. + * @stream_id: ASM stream id to map. + * @stream_type: Direction of stream + * + * Return: Will be an negative on error or a zero on success. + */ +int q6routing_stream_open(int fedai_id, int perf_mode, + int stream_id, int stream_type) +{ + int j, topology, num_copps = 0; + struct route_payload payload; + int copp_idx; + struct session_data *session, *pdata; + + if (!routing_data) { + pr_err("Routing driver not yet ready\n"); + return -EINVAL; + } + + session = &routing_data->sessions[stream_id - 1]; + pdata = &routing_data->port_data[session->port_id]; + + mutex_lock(&routing_data->lock); + session->fedai_id = fedai_id; + + session->path_type = pdata->path_type; + session->sample_rate = pdata->sample_rate; + session->channels = pdata->channels; + session->bits_per_sample = pdata->bits_per_sample; + + payload.num_copps = 0; /* only RX needs to use payload */ + topology = NULL_COPP_TOPOLOGY; + copp_idx = q6adm_open(routing_data->dev, session->port_id, + session->path_type, session->sample_rate, + session->channels, topology, perf_mode, + session->bits_per_sample, 0, 0); + + if (copp_idx < 0) { + mutex_unlock(&routing_data->lock); + return -EINVAL; + } + + set_bit(copp_idx, &session->copp_map); + + for_each_set_bit(j, &session->copp_map, MAX_COPPS_PER_PORT) { + payload.port_id[num_copps] = session->port_id; + payload.copp_idx[num_copps] = j; + num_copps++; + } + + if (num_copps) { + payload.num_copps = num_copps; + payload.session_id = stream_id; + q6adm_matrix_map(routing_data->dev, session->path_type, + payload, perf_mode); + } + mutex_unlock(&routing_data->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(q6routing_stream_open); + +static struct session_data *get_session_from_id(struct msm_routing_data *data, + int fedai_id) +{ + int i; + + for (i = 0; i < MAX_SESSIONS; i++) { + if (fedai_id == data->sessions[i].fedai_id) + return &data->sessions[i]; + } + + return NULL; +} +/** + * q6routing_stream_close() - Deregister a stream + * + * @fedai_id: Frontend dai id. + * @stream_type: Direction of stream + * + * Return: Will be an negative on error or a zero on success. + */ +void q6routing_stream_close(int fedai_id, int stream_type) +{ + struct session_data *session; + int idx; + + session = get_session_from_id(routing_data, fedai_id); + if (!session) + return; + + for_each_set_bit(idx, &session->copp_map, MAX_COPPS_PER_PORT) + q6adm_close(routing_data->dev, session->port_id, + session->perf_mode, idx); + + session->fedai_id = -1; + session->copp_map = 0; +} +EXPORT_SYMBOL_GPL(q6routing_stream_close); + +static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int session_id = mc->shift; + struct snd_soc_platform *platform = snd_soc_dapm_to_platform(dapm); + struct msm_routing_data *priv = dev_get_drvdata(platform->dev); + struct session_data *session = &priv->sessions[session_id]; + + if (session->port_id == mc->reg) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + + return 0; +} + +static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct snd_soc_platform *platform = snd_soc_dapm_to_platform(dapm); + struct msm_routing_data *data = dev_get_drvdata(platform->dev); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_dapm_update *update = NULL; + int be_id = mc->reg; + int session_id = mc->shift; + struct session_data *session = &data->sessions[session_id]; + + if (ucontrol->value.integer.value[0]) { + session->port_id = be_id; + snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update); + } else { + session->port_id = -1; + snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update); + } + + return 1; +} + +static const struct snd_kcontrol_new hdmi_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, + msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, + msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, + msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, + msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, + msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, + msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, + msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, + msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { + /* Frontend AIF */ + SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, 0, 0, 0), + + /* Mixer definitions */ + SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, + hdmi_mixer_controls, + ARRAY_SIZE(hdmi_mixer_controls)), +}; + +static const struct snd_soc_dapm_route intercon[] = { + {"HDMI Mixer", "MultiMedia1", "MM_DL1"}, + {"HDMI Mixer", "MultiMedia2", "MM_DL2"}, + {"HDMI Mixer", "MultiMedia3", "MM_DL3"}, + {"HDMI Mixer", "MultiMedia4", "MM_DL4"}, + {"HDMI Mixer", "MultiMedia5", "MM_DL5"}, + {"HDMI Mixer", "MultiMedia6", "MM_DL6"}, + {"HDMI Mixer", "MultiMedia7", "MM_DL7"}, + {"HDMI Mixer", "MultiMedia8", "MM_DL8"}, + {"HDMI_RX", NULL, "HDMI Mixer"}, +}; + +static int routing_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int be_id = rtd->cpu_dai->id; + struct snd_soc_platform *platform = rtd->platform; + struct msm_routing_data *data = dev_get_drvdata(platform->dev); + struct session_data *session; + int path_type; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + path_type = ADM_PATH_PLAYBACK; + else + path_type = ADM_PATH_LIVE_REC; + + if (be_id > AFE_MAX_PORTS) + return -EINVAL; + + session = &data->port_data[be_id]; + + mutex_lock(&data->lock); + + session->path_type = path_type; + session->sample_rate = params_rate(params); + session->channels = params_channels(params); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + session->bits_per_sample = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + session->bits_per_sample = 24; + break; + default: + break; + } + + mutex_unlock(&data->lock); + return 0; +} + +static struct snd_pcm_ops q6pcm_routing_ops = { + .hw_params = routing_hw_params, +}; + +static int msm_routing_probe(struct snd_soc_platform *platform) +{ + int i; + + for (i = 0; i < MAX_SESSIONS; i++) + routing_data->sessions[i].port_id = -1; + + return 0; +} + +static struct snd_soc_platform_driver msm_soc_routing_platform = { + .ops = &q6pcm_routing_ops, + .probe = msm_routing_probe, + .component_driver = { + .name = "q6routing-component", + .dapm_widgets = msm_qdsp6_widgets, + .num_dapm_widgets = ARRAY_SIZE(msm_qdsp6_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, +}; + +static int q6routing_dai_bind(struct device *dev, struct device *master, + void *data) +{ + routing_data = kzalloc(sizeof(*routing_data), GFP_KERNEL); + if (!routing_data) + return -ENOMEM; + + routing_data->dev = dev; + + mutex_init(&routing_data->lock); + dev_set_drvdata(dev, routing_data); + + return snd_soc_register_platform(dev, + &msm_soc_routing_platform); +} +static void q6routing_dai_unbind(struct device *dev, struct device *master, + void *d) +{ + struct msm_routing_data *data = dev_get_drvdata(dev); + + snd_soc_unregister_platform(dev); + + kfree(data); + + routing_data = NULL; +} + +static const struct component_ops q6routing_dai_comp_ops = { + .bind = q6routing_dai_bind, + .unbind = q6routing_dai_unbind, +}; + +static int q6pcm_routing_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &q6routing_dai_comp_ops); +} + +static int q6pcm_routing_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &q6routing_dai_comp_ops); + return 0; +} + +static struct platform_driver q6pcm_routing_platform_driver = { + .driver = { + .name = "q6routing", + }, + .probe = q6pcm_routing_probe, + .remove = q6pcm_routing_remove, +}; +module_platform_driver(q6pcm_routing_platform_driver); + +MODULE_DESCRIPTION("Q6 Routing platform"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/qdsp6/q6routing.h b/sound/soc/qcom/qdsp6/q6routing.h new file mode 100644 index 000000000000..aa41e4f45742 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6routing.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef _Q6_PCM_ROUTING_H +#define _Q6_PCM_ROUTING_H + +int q6routing_stream_open(int fedai_id, int perf_mode, + int stream_id, int stream_type); +void q6routing_stream_close(int fedai_id, int stream_type); + +#endif /*_Q6_PCM_ROUTING_H */