From patchwork Thu Apr 26 09:45: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: 134439 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2029261lji; Thu, 26 Apr 2018 02:49:47 -0700 (PDT) X-Google-Smtp-Source: AIpwx482hejb38eujLDGdwyizAVF3wUfg/EqbNere1Tv3S3OMUhid42uq1g52PwVd2fHdcY8T7j9 X-Received: by 10.99.94.197 with SMTP id s188mr26723505pgb.21.1524736187077; Thu, 26 Apr 2018 02:49:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524736187; cv=none; d=google.com; s=arc-20160816; b=fTINL+CMfOQxdKLk+z+7cgx8xXtEZZ2KecNCXBl61M8ArKwjXQ2JHISpfxZJMbzzdx PHxkAX3K61RRss52YwT2VwpeZojFvTrMAYFJNVhcsYy6HP2sQsUoytx6YDiW/TyE3dFT 7aDKoo3pDUvidqKVbAFzV6w4dED08OuahHhFvl1cGNw1mU4ebMWZqtXc0WkIERNrEvll neP6Ccxq6FCTp6ev+DDLKKyygSBwBEsWbjpy9IfE56lKQxnQgPYM4qo/viOOHvmJtDg3 WnIuWGMyyg9n/rWYupr7sN9CWPX8iNbVU71K72tPwC4iDWEgoaiszcAPe6NffiR4ndKJ AzZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=tqTFapJ2qQlR8S7lWTeZwDvcUE+0oDcw/DCkAOj638k=; b=XH4qD9ReBQMDc9hjvISxu/KWCcHHEkr7XaSNCqoLNgw0PdZrAKU6i6jHKfpm9hW9RG rADL38qOb0R/CvKVCn2w2qEVwY72HoJJu7Cmdg14j1EvIsFj05MNh+bkuCjop+twsflU j5UwbkxeIG63JaPDcRisaDyYKP/OzC/XB0H5w2JweREVAydN+5zaHBtHcrPllYaI6V/k IMizQCxWs49wGJmJ9IiJ4Xvk/01/QAt1oA2ESYZGdI10vl1iLqUeF/3b7oiZQuKSoqKI rTHxBGaOxR8np9gNZt58RnkJSsl83cyqS37JMRWGistEJxaepBHK8jsvcXP+rRXN5DI+ cWww== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=F9b4iRdZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b10-v6si3053856pll.116.2018.04.26.02.49.46; Thu, 26 Apr 2018 02:49:47 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=F9b4iRdZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754968AbeDZJto (ORCPT + 29 others); Thu, 26 Apr 2018 05:49:44 -0400 Received: from mail-wr0-f195.google.com ([209.85.128.195]:44956 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753487AbeDZJtd (ORCPT ); Thu, 26 Apr 2018 05:49:33 -0400 Received: by mail-wr0-f195.google.com with SMTP id o15-v6so56099560wro.11 for ; Thu, 26 Apr 2018 02:49:32 -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=tqTFapJ2qQlR8S7lWTeZwDvcUE+0oDcw/DCkAOj638k=; b=F9b4iRdZGT2kMmcxYIdVjuuNMsFcVnnvcnHT4xJrDpGFrGuTKIoRnRyfgkfe4lCTe5 kPXMhk2+ikN4kXx+bEBrr0Z8tz2+Ycd6BwxW6MnaiM/HTyme/pHOCCaan3SmAluhLnFm am57b8o0l+fZme1PrYPDMT508KwcoNaSuWnVc= 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=tqTFapJ2qQlR8S7lWTeZwDvcUE+0oDcw/DCkAOj638k=; b=dmt2WEevvBPpbQCdu7609uE0n9k5bunhLb8i+xG1dtndbwcan1lfpG/fm1IYUigchy 105oaQ36h/jgOyQirEQzo2qnSNV4ImXxEuY0HEb79uh19cZdrCBG9qa8dFXFP/J8lf6A r2h+GPnnv/ww1xHdRTbsJCCrdYHvL+Mtwr/IkD7iDIQufMUkymq0/m2THdIjbhQhMnQk Re8mFVCbLYA2sk3GBxUFezHL2OYWY5J+yGvhM01jYB6RTEJ7g4gpfjO4dhtsaUCI3yJd SYEdZK74/is7YpzdMTqVukh4I7/2tA1omKhpNr90JBtsUMC7nEl9DDA+qARfYvU4zowR 87sQ== X-Gm-Message-State: ALQs6tAcX0PBCWlp0LY/VD4SB4eY480bGQ9cV3Kee+oPT/NwqHIZmPBM OG1IhxLbKCV6GVn6EpUaVRHKTA== X-Received: by 2002:adf:acae:: with SMTP id o43-v6mr17876628wrc.132.1524736171884; Thu, 26 Apr 2018 02:49:31 -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 a79sm5287289wme.48.2018.04.26.02.49.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Apr 2018 02:49:31 -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, bgoswami@codeaurora.org Cc: gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com, Srinivas Kandagatla Subject: [PATCH v6 02/24] soc: qcom: Add APR bus driver Date: Thu, 26 Apr 2018 10:45:44 +0100 Message-Id: <20180426094606.4775-3-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.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 | 384 ++++++++++++++++++++++++++++++++++++++++ include/linux/mod_devicetable.h | 11 ++ include/linux/soc/qcom/apr.h | 130 ++++++++++++++ 5 files changed, 535 insertions(+) create mode 100644 drivers/soc/qcom/apr.c create mode 100644 include/linux/soc/qcom/apr.h -- 2.16.2 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..7c60bf6f9798 --- /dev/null +++ b/drivers/soc/qcom/apr.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +// 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_trysend(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 = { + .name = "aprbus", + .match = apr_device_match, + .probe = apr_device_probe, + .uevent = apr_uevent, + .remove = apr_device_remove, +}; +EXPORT_SYMBOL_GPL(aprbus); + +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; + 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, "reg", &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; + 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); + if (!ret) + ret = register_rpmsg_driver(&apr_driver); + + return ret; +} + +static void __exit apr_exit(void) +{ + bus_unregister(&aprbus); + 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..3c17846a16c1 --- /dev/null +++ b/include/linux/soc/qcom/apr.h @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __QCOM_APR_H_ +#define __QCOM_APR_H_ + +#include +#include +#include +#include + +extern struct bus_type aprbus; + +#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 Thu Apr 26 09:45:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 134440 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2029428lji; Thu, 26 Apr 2018 02:49:57 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+CEe7iHLL+k0u2nW+xF2vlcSyr9UO1dCD3aaCTvKQSXwtXjtrzxwgIrctnQnjx38ksch9S X-Received: by 10.101.83.139 with SMTP id x11mr27324511pgq.15.1524736197606; Thu, 26 Apr 2018 02:49:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524736197; cv=none; d=google.com; s=arc-20160816; b=uKF6Xx/4gI5+vZXwP7Ki0VmEIOAi6wvqjTbN7b2NErz7BcH8fa1Wu6Gwhi012Hoy7t l53x28fPJnIX+LeqyETFY89KpgHWQJJdmzRWLh0VrOZCh6XEIEynLFNniOZpf1/RRlO6 M/dvEwHmcPjzm7A3Qy0LAn3YltCdbQdxpUuPG1jBlpJiIjQepk3z4QFAZoDQ5uweI8xB rBjJRWnuG09jV8FO7IW36G/AoYjLhT8cWQ7Dw2FcES6bcUIpx8vc7Ssej2113Yhl3Rfm dCLlnew+JF4TI5JXqp/qp7KA8nLVGVBtSHzivBNzeS9AuYazSQuDqlOJ4qL6LnJBKkQI vWwQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=W7skse7fw+3bX6Qx0P+a8B8guzYohzn3Es2McL3471E=; b=vhLSSxyqcnwGq4HC47XoUUlteIg96tk1j8wfWA6nGzrU0BUHmYYg192NNvFahkjedL UA/wbnCTdXtFp3rMbDHqiSI4Fpch0EN2UaJEhPqbwBM4udGOf1A/WmWjxnZfRhhCuMzX Xzhx6LHQ2jGcRy3CkRk1K0BJCEETCogQ9+/UgKn5tXaDkAfX7gFbeGr23pLL2zI3OWN5 GSmZjJIvCpPFdW+xvx3piRaPPfZEr8t1SLHpWM3lmv1PQWbCITTF/x/JnpIMCIwuFj9t O06or8bV8SZIwOX9jnaZqbwt5tnONitZKAeYjxvE00h9EOwiciZ+I8Wu9GZwxj1mii+S wZYg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bzdndPpD; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j11si4146049pgq.347.2018.04.26.02.49.57; Thu, 26 Apr 2018 02:49:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bzdndPpD; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755118AbeDZJtx (ORCPT + 29 others); Thu, 26 Apr 2018 05:49:53 -0400 Received: from mail-wr0-f193.google.com ([209.85.128.193]:39264 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753882AbeDZJte (ORCPT ); Thu, 26 Apr 2018 05:49:34 -0400 Received: by mail-wr0-f193.google.com with SMTP id q3-v6so46096577wrj.6 for ; Thu, 26 Apr 2018 02:49:34 -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=W7skse7fw+3bX6Qx0P+a8B8guzYohzn3Es2McL3471E=; b=bzdndPpDcZGZgEdamsZZ+LI9ScErSDvW2nb+sREkPX3H/Lw+u+vFhDqIsxz8PLY9wL pipkiK3qtnxyCJzvbsc4ECFYWoX73+F1WXkFNGFxRBncPZIkt/8Z8lG5ZWnGCgQxrBfA wqnxW8jL+quqi4xdypyjBHMo+Xx2NyGmqYVbQ= 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=W7skse7fw+3bX6Qx0P+a8B8guzYohzn3Es2McL3471E=; b=Nl5gTb+wv9Ao+8IE/cwNoMITO29AUlXBVuqLk+vDbVEj6TLv9lGhGjFhQg/HkSlDn4 Gv03CTSchiwIik6VK3XEzWTK1EItjMC6urbTnViF1o+z3Ygw5SNIu1dEz9WizAfSYh2A +xJmnHmhwGMtf1Q3PPjuFzSAiFlgaooLlizy1N6y1VzfRCMHBk//5stjVoEEyak73vCv 8Uc9BM5C3ygvdUMxTlIwD8elDz9+AfkwnkJagZoi1Ja/nUik+EcJBd0yKKwX7zcCGCaa xvh/qEgxijo9YMCSgEqo5f03rrOglBuz+GqGBSc/dTesmc8XAIcfIswfDdmsA4hEvZUh D+/w== X-Gm-Message-State: ALQs6tDKJr4nDg9v+EhMdUdNN9ZS2HLtNz0azJAmN+ELlnHjmBTfiMkL kZoHoh6wut6EWYCGfb9VSyIFkg== X-Received: by 2002:adf:9d8b:: with SMTP id p11-v6mr16169678wre.74.1524736173422; Thu, 26 Apr 2018 02:49:33 -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 a79sm5287289wme.48.2018.04.26.02.49.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Apr 2018 02:49:32 -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, bgoswami@codeaurora.org Cc: gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com, Srinivas Kandagatla Subject: [PATCH v6 03/24] ASoC: qdsp6: dt-bindings: Add q6core dt bindings Date: Thu, 26 Apr 2018 10:45:45 +0100 Message-Id: <20180426094606.4775-4-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Srinivas Kandagatla This patch add DT bindings for Q6CORE DSP module. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- .../devicetree/bindings/sound/qcom,q6core.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,q6core.txt -- 2.16.2 diff --git a/Documentation/devicetree/bindings/sound/qcom,q6core.txt b/Documentation/devicetree/bindings/sound/qcom,q6core.txt new file mode 100644 index 000000000000..bd14e9a93490 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,q6core.txt @@ -0,0 +1,21 @@ +Qualcomm ADSP Core service binding + +Q6CORE 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,q6core-v.". + Or "qcom,q6core" where the version number can be queried + from DSP. + example "qcom,q6core-v2.0" + += EXAMPLE +q6core@3 { + compatible = "qcom,q6core"; + reg = ; +}; From patchwork Thu Apr 26 09:45:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 134444 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2029801lji; Thu, 26 Apr 2018 02:50:19 -0700 (PDT) X-Google-Smtp-Source: AIpwx48FxD1M+UFBXywSR1VhbukWNwHGLJO/FehiYgRyfTS3DUuryGNQncwM8ddW6PBWjaFdf4gJ X-Received: by 10.98.245.139 with SMTP id b11mr31377551pfm.113.1524736219536; Thu, 26 Apr 2018 02:50:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524736219; cv=none; d=google.com; s=arc-20160816; b=dMXHKXpLrdA5Jj9ikdc27FrNNVT5DXfDKI1wuWn6nelBiM6D9WlvzuBbRT1BSep4GB W/NEM3owF2MYFXcNoFLECC30Sulj5WKplninRDLv9cT+l0Mnbcvdr+VrV4ELdADFHw7k MtVJDSktAQM7rDDSpN9KUhezA1m5h17uMUg5M7YnyCzvv9PZCCGqIBgFc0kziDam9q6/ 0D0WC/7R1+CG/ufGdkbZqIuX/N6ca1CLU5oQBPo3xVBNCiU4bWA9Dk+jju51OqvhcLNZ gZgWBA/xM5cu7CWxC+cexgnJ0QUm4fk4gG3NWs3v590LAFXvihl66iL+yyig6QqKsxA2 myfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=1m0sBr5KCcsYwf4a36GaJAwryyYeV5tnqdpg1xvJcEA=; b=ij/AyV+UO0MGekYBjOFfUrTVY8A3X5Zq2QVb8YHl177VJPp2xlvKMr0g8rS9c+qOXr rvnUFFHcKqpdjcIFasmZCAxUj7Hcpc420xNi5aO8KQsgWkfz2vHTUoex5eDjk9+tKUUH yTal1CnhC2Q03vo8fMjPUi6UBsCT4wjBs2j81VDEtIV8FyOg8EZ+avOBud1ct5cTGsP4 dfMssavwUJnrtTrRr5chA6kMaYom5t3HnjyMvXpCDSC4IyuT/JkLly5zatSgqv2qhkpy v0l9RXt75M6zFxzSiMLliyoOTHZpNuS3uxvLmrp9rztuyIsZMPHRt1XV76vy28mAudee WaPg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=TXG1KWwS; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 73si17765129pfb.204.2018.04.26.02.50.19; Thu, 26 Apr 2018 02:50:19 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=TXG1KWwS; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755294AbeDZJuP (ORCPT + 29 others); Thu, 26 Apr 2018 05:50:15 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:50451 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754977AbeDZJtp (ORCPT ); Thu, 26 Apr 2018 05:49:45 -0400 Received: by mail-wm0-f67.google.com with SMTP id t11so4948787wmt.0 for ; Thu, 26 Apr 2018 02:49:45 -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=1m0sBr5KCcsYwf4a36GaJAwryyYeV5tnqdpg1xvJcEA=; b=TXG1KWwSsA0VOh13ousQBpjiG3v7TkGrUqQRQZiFpZFiWu49A9XnoRnoo1WrYG+iMi 1mFeE9IE0piwDF0veNKRcyTZRct4VKj2SFbsMfsqbMTe5FEFTPBCOdKQ+q3eKDELnyJd RS9TG/BATc4uFQbvnCFb9LH0k/rtAXp760Vlk= 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=1m0sBr5KCcsYwf4a36GaJAwryyYeV5tnqdpg1xvJcEA=; b=uCQIGn94nxYwiX1aOrIIu7IPXQNPTJBmJRLnhU/1WZe18Jai2qsNoNNK+9g1SkbTTb X8JSls2UcpJ3VRZSOFFPkwrfjF07WhESJIH83FfCUUTLlzkqLoVpARVLq3F3txvwWK8F u/NzRWGCE1dgt+KMOYXjiDPELb8hwLbG3Ds4MoyBmPIeW2eL3rmtNgbpXgNhTnLm1glT W/y8zFMh+GoE1mworHWEu+zPzXll6LX5cYECeKjRRaOTCuqah4E6sI7+1U5FljNE3hK7 aMRXICYlMluJdTTKyBooS+xkeRDdcKBATCtJjzVYUtwM2hkhDbOE/4zJ0wiGpmFCOhQn IgPQ== X-Gm-Message-State: ALQs6tAqgILWW/JlruIOmadSsuz6rUa8WkWDGTOX0JPVDYEyecRTX9xT 89rgkPz84K2FOroYjg2sVB9oLg== X-Received: by 10.28.47.5 with SMTP id v5mr18338702wmv.93.1524736184306; Thu, 26 Apr 2018 02:49:44 -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 a79sm5287289wme.48.2018.04.26.02.49.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Apr 2018 02:49:43 -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, bgoswami@codeaurora.org Cc: gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com, Srinivas Kandagatla Subject: [PATCH v6 11/24] ASoC: qdsp6: q6afe: Add support to MI2S ports Date: Thu, 26 Apr 2018 10:45:53 +0100 Message-Id: <20180426094606.4775-12-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.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 diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index d8ba2d5dc724..6a81fc7fd576 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 { @@ -211,6 +268,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}, }; @@ -452,6 +525,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 * @@ -533,6 +750,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 5659966c6b1e..3cb3bb4985a9 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 Thu Apr 26 09:45:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 134460 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2031035lji; Thu, 26 Apr 2018 02:51:38 -0700 (PDT) X-Google-Smtp-Source: AB8JxZr1YYTUGPadiJvRo9xXpS8i8Y3AtFDqeEvaT00WHJyXLvphJfI9ruz7eUnZS+8VlKsrGiPq X-Received: by 10.101.82.4 with SMTP id o4mr9434168pgp.126.1524736298249; Thu, 26 Apr 2018 02:51:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524736298; cv=none; d=google.com; s=arc-20160816; b=IkenbASaBfKCiGdaOBniDGP7MmgjxrSmak4v9t4cBDfBCzPVjMaBRxEnsRATPeoQJx qLSVzXSjLQtXvBQy6zRE9khOd/wxQt17YzaFb1TU6TJnP65dHgaM+y6WSLmizewo8bRS AUd6jTNkQdqLzVbvrjbreehCyxxkXFMFtQlbNAHzYQxUPeNnQfg/cRil9Qs78ALVbEAd wwVvuMKm6hg/cMWLVG6esYIJjCPlCGHQ7qeNMfWzz5WYyhq+y7zG2Ni4HXv5d0FDSq2X xtGaFUV255rVqLJ2+TG9sgjum/IW6kf3HtEnj1C6rRQdyTVj0vqE7iS7oh6Tot+FVV56 xKnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=T6o2ZI5JeF/XSk2dvKCDCRMbQP7SjL0A0HhMrxxykQ4=; b=AKzVUAstBo13SZ14TMWDd7UPvu7FVauQL8qTYPdZvPxgeLX+BVS18vgh5G40/6vfhf bvUNuCxxJprNaVY1yYe1OgDlg+vnOSGFUZSCGiCB+muaeTW2U86G1G7rZsbbAx5VUX0o elEC+y0MrKVZzqi4y0poVOVboO4aZe55K6Nz3r2SsuJ7Rc8yW3YaCkikIQFaMU532xWJ t7U9ZuBRQJrJM+i4DWo1usBzZ/j+C4JfVs6ms2o5rRP+itGmDje4V18iWwlZONBV3Uf1 DT28YQOPESpQGevsR7BtO3+1uu+sGmaIkHY+5YvZwuhndy+fjxd2LgcaboeHa4LgUzkQ GFJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=g4ix/8mz; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v31-v6si19205779plg.157.2018.04.26.02.51.37; Thu, 26 Apr 2018 02:51:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=g4ix/8mz; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755498AbeDZJve (ORCPT + 29 others); Thu, 26 Apr 2018 05:51:34 -0400 Received: from mail-wr0-f194.google.com ([209.85.128.194]:43465 "EHLO mail-wr0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755126AbeDZJty (ORCPT ); Thu, 26 Apr 2018 05:49:54 -0400 Received: by mail-wr0-f194.google.com with SMTP id v15-v6so37998096wrm.10 for ; Thu, 26 Apr 2018 02:49:54 -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=T6o2ZI5JeF/XSk2dvKCDCRMbQP7SjL0A0HhMrxxykQ4=; b=g4ix/8mzYlv3sjp140pJHR/Ry626dyC7tKE7lIxPdv+crsgn7RrDpX3j6fYTWPchHJ 44S+NFT2OOVOZXO1bHksmdO0nMoMWaGVxhqOLFPenPzlxJUV08YfGDxwcB4EKB0dC7vY 3boF6lNm8Kad0kZLN3KvAkacn4uMc0moEPMb8= 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=T6o2ZI5JeF/XSk2dvKCDCRMbQP7SjL0A0HhMrxxykQ4=; b=n+vZHVanh85v1/3yzd8enfJ+/0S4WJMruRHY8sWz3DNchqv424SoWv30Wlauw8gdyl ulWHiXORwTbR85fy7bHlxvr6vRDbjD0T70YYWXmasngM7hflcUqlm2qq2sBh1rbDm4m1 WgFIqgslOYjRJs7XPHrwBapQ7lkAsqbLh8gO+/oSM0AEwGfxtxAVnR/xmB1hKycyfWIm k7L3pi1eyAgQSZHAXVPGkdJJLyQdlyMxi+fRCWMHj3Hvj2moWJHYOy2kn6KnbLjcNkDi qPDuNTZBBmTJEzFNivrNBQV4K58IrmPrTdI42jyIC0BSlECt8sSZDJ26+SpDuvoBGWuh 36Kg== X-Gm-Message-State: ALQs6tCEU+K+gVuA4NmI9CJiikmU1wx8NVjpRU/4gaDU7aRjMc78v3VF abvlAVYGWzfjirA0MMKkzLxXbw== X-Received: by 2002:adf:b859:: with SMTP id u25-v6mr27189584wrf.162.1524736193145; Thu, 26 Apr 2018 02:49:53 -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 a79sm5287289wme.48.2018.04.26.02.49.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Apr 2018 02:49:52 -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, bgoswami@codeaurora.org Cc: gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com, Srinivas Kandagatla Subject: [PATCH v6 17/24] ASoC: qdsp6: q6routing: Add q6routing driver Date: Thu, 26 Apr 2018 10:45:59 +0100 Message-Id: <20180426094606.4775-18-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.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 diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index ad8aa113f6df..5353004cdcf4 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -56,6 +56,9 @@ config SND_SOC_QDSP6_AFE config SND_SOC_QDSP6_ADM tristate +config SND_SOC_QDSP6_ROUTING + tristate + config SND_SOC_QDSP6_ASM tristate @@ -66,6 +69,7 @@ config SND_SOC_QDSP6 select SND_SOC_QDSP6_CORE select SND_SOC_QDSP6_AFE select SND_SOC_QDSP6_ADM + select SND_SOC_QDSP6_ROUTING select SND_SOC_QDSP6_ASM help To add support for MSM QDSP6 Soc Audio. diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 01d9dcf3375c..0e8e2febb7ec 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -2,4 +2,5 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.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 diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c new file mode 100644 index 000000000000..fe7d28f7e555 --- /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. All rights reserved. +// 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..35514e651130 --- /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 */ From patchwork Thu Apr 26 09:46:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 134457 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2030890lji; Thu, 26 Apr 2018 02:51:29 -0700 (PDT) X-Google-Smtp-Source: AIpwx49S89Pq4M4yMtDxFTBl+WUGam1dhEBAGjUjXVfdlgF4ai39eTOLgjaixRTipAe5diy+MI6j X-Received: by 2002:a17:902:683:: with SMTP id 3-v6mr33059551plh.206.1524736289426; Thu, 26 Apr 2018 02:51:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524736289; cv=none; d=google.com; s=arc-20160816; b=IgugakZ4JmJEZPEVDavkyfnQ6d4rPEZvY1SGREd11k97vOI0EloSaG8WwVLWQEShtF aR673dy/ylkbAAch/J+LdJE1MI5DkN46ag07IJaM4osOYgxhyVTbXbfuWi1KihopeNq1 hTyQiHM7tj8HPPp9RLkHW8qNiJnELHSM0Kmzokp2me6vGQrZB1A9WtTDvIzuNfY6F1qT XrZ7qod3cB00/UjfdoSCP1Gn3JsqZamqxZhB6eT00ms+dZlpmmlQFxCc8TWq4Cc2Ogfh bICZ+DWd1csUzjgV2M48S2NA77tq1KlRtbTEQg+I3FzzMU4Du0YPJoYHZIf8Z8pZzN3Z rLjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=MJhvNWabYzx7L+m0naohE7bV07BMIV9Guxy6wN0kMQc=; b=ZmNLggcGOrW6fRcCdCpRg6tvA6PJZXrpZogUxre4OCKmJek8wpEQii3kTwD3LQSW4M 93udmCQa1aJ+PtJnxajpXR3/3QoY/XA182tHgCNkViNTEgHmxlXV6kBHWygYhwIPyaRj SGISAlFZgr7TFW6q9SCoEJcfCRslD3OrfxFC+xHrcWxRHfUW5LjnTkhmo5+mwXytt6dw aGAfPKquH9HvvF27sJOciO4NDnBUtTAc9KZ3u5/NViwpKuO4YbDNGl5ZPrWwAQ4+GpQL 9KPdce+aW5HyP1xpyDeHZDUirkhqXkk9XsLJmx2swLoBxx+C5KM3rLkdIt3o3flEJiOg ISjA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bVHtGAtB; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q9si2546775pgt.5.2018.04.26.02.51.29; Thu, 26 Apr 2018 02:51:29 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bVHtGAtB; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755175AbeDZJv1 (ORCPT + 29 others); Thu, 26 Apr 2018 05:51:27 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:36004 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755150AbeDZJt5 (ORCPT ); Thu, 26 Apr 2018 05:49:57 -0400 Received: by mail-wm0-f66.google.com with SMTP id n10so11965969wmc.1 for ; Thu, 26 Apr 2018 02:49:56 -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=MJhvNWabYzx7L+m0naohE7bV07BMIV9Guxy6wN0kMQc=; b=bVHtGAtBLR9FAi5kK+HnxduTZk1ZZGo5ObchvaVDc2FarlbWjIRJ1v0m5i0QnqzrMG zy4TV1pUEAjJhn4qzqgIAm1hrRwOwhsl4XorpnWmI0hbM0NUvqV8V/DrUfGXLdiVaq0l DdYj1RndsDnmlccOJIQmuZ4uQD0hz5a3aHpQQ= 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=MJhvNWabYzx7L+m0naohE7bV07BMIV9Guxy6wN0kMQc=; b=mrRly6c6XSXaKZyL63Kgxo3HNbjnZebSmjnshJ3JOmsY3XADtq72K7GRrO0D0WcY63 ndnf/rhQ83v9/LzxdN6ew0Z7+4bgwQWdDXsjM7BDBws7G8DIndChidth93xpEwjQGieD t11FUm09C6DNf3FTaHXEHSsQDZrJtzVWK+YS2Ecqag33eXEp9/9Rn+m3DRwNj2YBH7BZ hzVN0XZHXWlcnSkJB0JXRo69TQPlbUODoXWw1yufipjveZ/leFjD/34VIrwwB9W3CxPq MWVSo/KY8+lPDL9NAWEwjwTga6/rJnQe86pwyddS3ZzMNaKdOZOTWYQCywRao0aTPEEg VxgQ== X-Gm-Message-State: ALQs6tCmI7WudZ0REE03trBiwLilcKZJiEWLr53T43s8rC2ADy+9lGAV tS2tpo+ofI/0TdG4uV/EKPzxE6wMaAo= X-Received: by 10.28.94.210 with SMTP id s201mr18851478wmb.140.1524736195853; Thu, 26 Apr 2018 02:49:55 -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 a79sm5287289wme.48.2018.04.26.02.49.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Apr 2018 02:49:55 -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, bgoswami@codeaurora.org Cc: gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com, Srinivas Kandagatla Subject: [PATCH v6 19/24] ASoC: qdsp6: q6routing: Add support to MI2S Mixers Date: Thu, 26 Apr 2018 10:46:01 +0100 Message-Id: <20180426094606.4775-20-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Srinivas Kandagatla This patch add support to MI2S mixers required to select path between ASM stream and AFE ports. Signed-off-by: Srinivas Kandagatla Reviewed-and-tested-by: Rohit kumar --- sound/soc/qcom/qdsp6/q6routing.c | 329 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) -- 2.16.2 diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index a72651a6343e..164b26eb3519 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -232,6 +232,103 @@ static const struct snd_kcontrol_new hdmi_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", PRIMARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", PRIMARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", PRIMARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", PRIMARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", PRIMARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", PRIMARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", PRIMARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", PRIMARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", SECONDARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", QUATERNARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", TERTIARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", TERTIARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", TERTIARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", TERTIARY_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + + static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", SLIMBUS_0_RX, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, @@ -406,6 +503,126 @@ static const struct snd_kcontrol_new slimbus_6_rx_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new mmul1_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new mmul2_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new mmul3_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new mmul4_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new mmul5_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new mmul6_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new mmul7_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new mmul8_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, + 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), @@ -451,6 +668,35 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("SLIMBUS_6_RX Audio Mixer", SND_SOC_NOPM, 0, 0, slimbus_6_rx_mixer_controls, ARRAY_SIZE(slimbus_6_rx_mixer_controls)), + SND_SOC_DAPM_MIXER("PRI_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, + primary_mi2s_rx_mixer_controls, + ARRAY_SIZE(primary_mi2s_rx_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, + secondary_mi2s_rx_mixer_controls, + ARRAY_SIZE(secondary_mi2s_rx_mixer_controls)), + SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, + quaternary_mi2s_rx_mixer_controls, + ARRAY_SIZE(quaternary_mi2s_rx_mixer_controls)), + SND_SOC_DAPM_MIXER("TERT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, + tertiary_mi2s_rx_mixer_controls, + ARRAY_SIZE(tertiary_mi2s_rx_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0, + mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0, + mmul2_mixer_controls, ARRAY_SIZE(mmul2_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia3 Mixer", SND_SOC_NOPM, 0, 0, + mmul3_mixer_controls, ARRAY_SIZE(mmul3_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia4 Mixer", SND_SOC_NOPM, 0, 0, + mmul4_mixer_controls, ARRAY_SIZE(mmul4_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia5 Mixer", SND_SOC_NOPM, 0, 0, + mmul5_mixer_controls, ARRAY_SIZE(mmul5_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia6 Mixer", SND_SOC_NOPM, 0, 0, + mmul6_mixer_controls, ARRAY_SIZE(mmul6_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia7 Mixer", SND_SOC_NOPM, 0, 0, + mmul7_mixer_controls, ARRAY_SIZE(mmul7_mixer_controls)), + SND_SOC_DAPM_MIXER("MultiMedia8 Mixer", SND_SOC_NOPM, 0, 0, + mmul8_mixer_controls, ARRAY_SIZE(mmul8_mixer_controls)), + }; static const struct snd_soc_dapm_route intercon[] = { @@ -528,6 +774,89 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_6_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, {"SLIMBUS_6_RX Audio Mixer", "MultiMedia8", "MM_DL8"}, {"SLIMBUS_6_RX", NULL, "SLIMBUS_6_RX Audio Mixer"}, + + {"QUAT_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"QUAT_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"QUAT_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"QUAT_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"QUAT_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"QUAT_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"QUAT_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"QUAT_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Audio Mixer"}, + + {"TERT_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"TERT_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"TERT_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"TERT_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"TERT_MI2S_RX", NULL, "TERT_MI2S_RX Audio Mixer"}, + + {"SEC_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL5"}, + {"SEC_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL7"}, + {"SEC_MI2S_RX", NULL, "SEC_MI2S_RX Audio Mixer"}, + + {"PRI_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"PRI_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"PRI_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"PRI_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"PRI_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"PRI_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Audio Mixer"}, + + {"MultiMedia1 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia1 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"MultiMedia1 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia1 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + + {"MultiMedia2 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia2 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"MultiMedia2 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia2 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + + {"MultiMedia3 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia3 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"MultiMedia3 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia3 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + + {"MultiMedia4 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia4 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"MultiMedia4 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia4 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + + {"MultiMedia5 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia5 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"MultiMedia5 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia5 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + + {"MultiMedia6 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia6 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"MultiMedia6 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia6 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + + {"MultiMedia7 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia7 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"MultiMedia7 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia7 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + + {"MultiMedia8 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"MultiMedia8 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"MultiMedia8 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia8 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + + {"MM_UL1", NULL, "MultiMedia1 Mixer"}, + {"MM_UL2", NULL, "MultiMedia2 Mixer"}, + {"MM_UL3", NULL, "MultiMedia3 Mixer"}, + {"MM_UL4", NULL, "MultiMedia4 Mixer"}, + {"MM_UL5", NULL, "MultiMedia5 Mixer"}, + {"MM_UL6", NULL, "MultiMedia6 Mixer"}, + {"MM_UL7", NULL, "MultiMedia7 Mixer"}, + {"MM_UL8", NULL, "MultiMedia8 Mixer"}, }; static int routing_hw_params(struct snd_pcm_substream *substream, From patchwork Thu Apr 26 09:46:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 134456 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2030823lji; Thu, 26 Apr 2018 02:51:25 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/uEcGuRZIvVw/3Ou72ucFLxCaa59xelgHIH8Hkp8599XF3/8HV5KR+n8SRd/zpVGaEV+/s X-Received: by 10.101.99.6 with SMTP id g6mr26687552pgv.173.1524736284958; Thu, 26 Apr 2018 02:51:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524736284; cv=none; d=google.com; s=arc-20160816; b=sKtYdPB9ga1JaYvymZeLkcfDoHsZE+g1oTY3ipa/ZvCQqKboYjglUbNkR6fN4aTpYU Li0O3vivf3z10UChoQ15nSIofvf4bBbKBZQ4r4L1qTH0uiuD4HEIZuM7S4lUoC/4wf+M Cu94WTdpKfGU9FatbNlNwvUe2oSGCSi8xLecV0Z3PeXVOKUbO3EXK5h+UEWHpJQhxrN2 TjbQqSf00nTko3eNPaYqFcKOub6+3IGdIsLX0L836ScD12My+NjI+ja/MhBawAeMP4q2 YBDWxf1TEM3BgFSjrrhMnorfwZbRTbocyuUdpqxaBpveSUuKbLdArxW5lPnRioFt8/um 2hXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=qVMSg5TnG/kUZHteKQNqkrCpT+Dbe6M8mdE8vclEpFI=; b=lyDJ2Ckt1J+2mkoHBvr5xKvTanlfM+YIGI95HUG6DXgCcK4qXSP6YNpdkR7gQtZ001 xqfwPnyGJuGvtVXOEA7MoZoBL1cKCthUg75xG1oYzjkXwYLS/+c5lzfexKL2IPmmLF3P sr9nWs1n64mXx8f+EQnHR18SKxTuN2v8eSqbpXBhgYSh6eezZu8dkPY2oREFBuTir3/p bYo0+VTqNuD+yG20+C1HDFq5SlMamfLz70msNaG8Hlrifz7BwERGQ/lQ/hvq/KH1+Kl+ kSHlzV0JDpuuAziX9VHh1VTWHZ9/aUJR69HOfizuC+2mogJKuw9jn6lf0nuZM/h4hbzk LuVw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bmhhtQj5; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q9si2546775pgt.5.2018.04.26.02.51.24; Thu, 26 Apr 2018 02:51:24 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bmhhtQj5; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755438AbeDZJvV (ORCPT + 29 others); Thu, 26 Apr 2018 05:51:21 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:38900 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755158AbeDZJt7 (ORCPT ); Thu, 26 Apr 2018 05:49:59 -0400 Received: by mail-wm0-f68.google.com with SMTP id i3so11973418wmf.3 for ; Thu, 26 Apr 2018 02:49:58 -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=qVMSg5TnG/kUZHteKQNqkrCpT+Dbe6M8mdE8vclEpFI=; b=bmhhtQj5S4gp9xl12qqkB0JEmjskBImIRoXrgRlUjZ38Zj66ulbi1AiPA9HdizEgUv dpaoasJS6SQz2wWETA/9yYPzHMPPeFPgAuEYQmDxHkPC9KVMoyrfSX3CKBGADfDkHrJO /KsuXI29/l0yTSrfN3ia3N1WJ5+YP9KvPYFBw= 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=qVMSg5TnG/kUZHteKQNqkrCpT+Dbe6M8mdE8vclEpFI=; b=l/DAkvN0sibBQEkCYtl/daMQemq12rkv5yp2V3zHAwYYH2gmH/AWeQgUm+E4+Iuxj0 acKQPRAYYo9zwsPOq8lKjw4McqSIoxT0XRf6ENDOWzHV9zaDzeRCc4B+3X7brg+RP4vJ kIC2r8WvUA1JcDC0Sf67WXSrOiTHGvm0RS7LowDvV7iSglEr+5FRiGs/Z0jZsa7VrENY 7SmsEx7/f20ansR0zMntpuO8fqhEYytISuhAGZzjdqfcxlbcIZq09SRo4kqVhEs/rOmp xmKVczbRvZWGE6J9tbZyd2NyX5GHrOra/EH3q0gufHIoCUqCnS5Zrgsj5xkV9cwqihhy ufjw== X-Gm-Message-State: ALQs6tATBcLr+OovjKli+3Mx400YaUdd2B3Cysx6/wxI5zyvY7z/ieUm 9qkYI26TFcUvf+MNk4TXf5GLLQ== X-Received: by 10.28.150.211 with SMTP id y202mr6652982wmd.106.1524736197365; Thu, 26 Apr 2018 02:49: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 a79sm5287289wme.48.2018.04.26.02.49.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Apr 2018 02:49: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, bgoswami@codeaurora.org Cc: gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com, Srinivas Kandagatla Subject: [PATCH v6 20/24] ASoC: qdsp6: q6afe: Add q6afe dai driver Date: Thu, 26 Apr 2018 10:46:02 +0100 Message-Id: <20180426094606.4775-21-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Srinivas Kandagatla This patch adds support to q6afe backend dais driver. 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/q6afe-dai.c | 752 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 757 insertions(+) create mode 100644 sound/soc/qcom/qdsp6/q6afe-dai.c -- 2.16.2 diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 5353004cdcf4..8d36f419e0f8 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -53,6 +53,9 @@ config SND_SOC_QDSP6_CORE config SND_SOC_QDSP6_AFE tristate +config SND_SOC_QDSP6_AFE_DAI + tristate + config SND_SOC_QDSP6_ADM tristate @@ -68,6 +71,7 @@ config SND_SOC_QDSP6 select SND_SOC_QDSP6_COMMON select SND_SOC_QDSP6_CORE select SND_SOC_QDSP6_AFE + select SND_SOC_QDSP6_AFE_DAI select SND_SOC_QDSP6_ADM select SND_SOC_QDSP6_ROUTING select SND_SOC_QDSP6_ASM diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 0e8e2febb7ec..bada1aa303c2 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o +obj-$(CONFIG_SND_SOC_QDSP6_AFE_DAI) += q6afe-dai.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 diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c new file mode 100644 index 000000000000..eccced580bd5 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -0,0 +1,752 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +// Copyright (c) 2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6afe.h" + +struct q6afe_dai_priv_data { + uint32_t sd_line_mask; +}; + +struct q6afe_dai_data { + struct q6afe_port *port[AFE_PORT_MAX]; + struct q6afe_port_config port_config[AFE_PORT_MAX]; + bool is_port_started[AFE_PORT_MAX]; + struct q6afe_dai_priv_data priv[AFE_PORT_MAX]; +}; + +static int q6slim_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct q6afe_slim_cfg *slim = &dai_data->port_config[dai->id].slim; + + slim->num_channels = params_channels(params); + slim->sample_rate = params_rate(params); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_SPECIAL: + slim->bit_width = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + slim->bit_width = 24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + slim->bit_width = 32; + break; + default: + pr_err("%s: format %d\n", + __func__, params_format(params)); + return -EINVAL; + } + + return 0; +} + +static int q6hdmi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + int channels = params_channels(params); + struct q6afe_hdmi_cfg *hdmi = &dai_data->port_config[dai->id].hdmi; + + hdmi->sample_rate = params_rate(params); + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + hdmi->bit_width = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + hdmi->bit_width = 24; + break; + } + + /* HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4 */ + switch (channels) { + case 2: + hdmi->channel_allocation = 0; + break; + case 3: + hdmi->channel_allocation = 0x02; + break; + case 4: + hdmi->channel_allocation = 0x06; + break; + case 5: + hdmi->channel_allocation = 0x0A; + break; + case 6: + hdmi->channel_allocation = 0x0B; + break; + case 7: + hdmi->channel_allocation = 0x12; + break; + case 8: + hdmi->channel_allocation = 0x13; + break; + default: + dev_err(dai->dev, "invalid Channels = %u\n", channels); + return -EINVAL; + } + + return 0; +} + +static int q6i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg; + + i2s->sample_rate = params_rate(params); + i2s->bit_width = params_width(params); + i2s->num_channels = params_channels(params); + i2s->sd_line_mask = dai_data->priv[dai->id].sd_line_mask; + + return 0; +} + +static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg; + + i2s->fmt = fmt; + + return 0; +} + +static void q6afe_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + int rc; + + rc = q6afe_port_stop(dai_data->port[dai->id]); + if (rc < 0) + dev_err(dai->dev, "fail to close AFE port (%d)\n", rc); + + dai_data->is_port_started[dai->id] = false; + +} + +static int q6afe_mi2s_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + int rc; + + if (dai_data->is_port_started[dai->id]) { + /* stop the port and restart with new port config */ + rc = q6afe_port_stop(dai_data->port[dai->id]); + if (rc < 0) { + dev_err(dai->dev, "fail to close AFE port (%d)\n", rc); + return rc; + } + } + + rc = q6afe_i2s_port_prepare(dai_data->port[dai->id], + &dai_data->port_config[dai->id].i2s_cfg); + if (rc < 0) { + dev_err(dai->dev, "fail to prepare AFE port %x\n", dai->id); + return rc; + } + + rc = q6afe_port_start(dai_data->port[dai->id]); + if (rc < 0) { + dev_err(dai->dev, "fail to start AFE port %x\n", dai->id); + return rc; + } + dai_data->is_port_started[dai->id] = true; + + return 0; +} + +static int q6afe_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + int rc; + + if (dai_data->is_port_started[dai->id]) { + /* stop the port and restart with new port config */ + rc = q6afe_port_stop(dai_data->port[dai->id]); + if (rc < 0) { + dev_err(dai->dev, "fail to close AFE port (%d)\n", rc); + return rc; + } + } + + if (dai->id == HDMI_RX) + q6afe_hdmi_port_prepare(dai_data->port[dai->id], + &dai_data->port_config[dai->id].hdmi); + else if (dai->id >= SLIMBUS_0_RX && dai->id <= SLIMBUS_6_TX) + q6afe_slim_port_prepare(dai_data->port[dai->id], + &dai_data->port_config[dai->id].slim); + + rc = q6afe_port_start(dai_data->port[dai->id]); + if (rc < 0) { + dev_err(dai->dev, "fail to start AFE port %x\n", dai->id); + return rc; + } + dai_data->is_port_started[dai->id] = true; + + return 0; +} + +static int q6slim_set_channel_map(struct snd_soc_dai *dai, + unsigned int tx_num, unsigned int *tx_slot, + unsigned int rx_num, unsigned int *rx_slot) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct q6afe_port_config *pcfg = &dai_data->port_config[dai->id]; + int i; + + if (!rx_slot) { + pr_err("%s: rx slot not found\n", __func__); + return -EINVAL; + } + + for (i = 0; i < rx_num; i++) { + pcfg->slim.ch_mapping[i] = rx_slot[i]; + pr_debug("%s: find number of channels[%d] ch[%d]\n", + __func__, i, rx_slot[i]); + } + + pcfg->slim.num_channels = rx_num; + + pr_debug("%s: SLIMBUS_%d_RX cnt[%d] ch[%d %d]\n", __func__, + (dai->id - SLIMBUS_0_RX) / 2, rx_num, + pcfg->slim.ch_mapping[0], + pcfg->slim.ch_mapping[1]); + + return 0; +} + +static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct q6afe_port *port = dai_data->port[dai->id]; + + switch (clk_id) { + case LPAIF_DIG_CLK: + return q6afe_port_set_sysclk(port, clk_id, 0, 5, freq, dir); + case LPAIF_BIT_CLK: + case LPAIF_OSR_CLK: + return q6afe_port_set_sysclk(port, clk_id, + Q6AFE_LPASS_CLK_SRC_INTERNAL, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + freq, dir); + case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1: + return q6afe_port_set_sysclk(port, clk_id, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + freq, dir); + } + + return 0; +} + +static const struct snd_soc_dapm_route q6afe_dapm_routes[] = { + {"HDMI Playback", NULL, "HDMI_RX"}, + {"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"}, + {"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"}, + {"Slimbus3 Playback", NULL, "SLIMBUS_3_RX"}, + {"Slimbus4 Playback", NULL, "SLIMBUS_4_RX"}, + {"Slimbus5 Playback", NULL, "SLIMBUS_5_RX"}, + {"Slimbus6 Playback", NULL, "SLIMBUS_6_RX"}, + + {"Primary MI2S Playback", NULL, "PRI_MI2S_RX"}, + {"Secondary MI2S Playback", NULL, "SEC_MI2S_RX"}, + {"Tertiary MI2S Playback", NULL, "TERT_MI2S_RX"}, + {"Quaternary MI2S Playback", NULL, "QUAT_MI2S_RX"}, + + {"TERT_MI2S_TX", NULL, "Tertiary MI2S Capture"}, + {"PRI_MI2S_TX", NULL, "Primary MI2S Capture"}, + {"SEC_MI2S_TX", NULL, "Secondary MI2S Capture"}, + {"QUAT_MI2S_TX", NULL, "Quaternary MI2S Capture"}, +}; + +static struct snd_soc_dai_ops q6hdmi_ops = { + .prepare = q6afe_dai_prepare, + .hw_params = q6hdmi_hw_params, + .shutdown = q6afe_dai_shutdown, +}; + +static struct snd_soc_dai_ops q6i2s_ops = { + .prepare = q6afe_mi2s_prepare, + .hw_params = q6i2s_hw_params, + .set_fmt = q6i2s_set_fmt, + .shutdown = q6afe_dai_shutdown, + .set_sysclk = q6afe_mi2s_set_sysclk, +}; + +static struct snd_soc_dai_ops q6slim_ops = { + .prepare = q6afe_dai_prepare, + .hw_params = q6slim_hw_params, + .shutdown = q6afe_dai_shutdown, + .set_channel_map = q6slim_set_channel_map, +}; + +static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct snd_soc_dapm_context *dapm; + struct q6afe_port *port; + + dapm = snd_soc_component_get_dapm(dai->component); + + port = q6afe_port_get_from_id(dai->dev, dai->id); + if (IS_ERR(port)) { + dev_err(dai->dev, "Unable to get afe port\n"); + return -EINVAL; + } + dai_data->port[dai->id] = port; + + return 0; +} + +static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); + + q6afe_port_put(dai_data->port[dai->id]); + dai_data->port[dai->id] = NULL; + + return 0; +} + +static struct snd_soc_dai_driver q6afe_dais[] = { + { + .playback = { + .stream_name = "HDMI Playback", + .rates = SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 2, + .channels_max = 8, + .rate_max = 192000, + .rate_min = 48000, + }, + .ops = &q6hdmi_ops, + .id = HDMI_RX, + .name = "HDMI", + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .name = "SLIMBUS_0_RX", + .ops = &q6slim_ops, + .id = SLIMBUS_0_RX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + .playback = { + .stream_name = "Slimbus Playback", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 192000, + }, + }, { + .playback = { + .stream_name = "Slimbus1 Playback", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 192000, + }, + .name = "SLIMBUS_1_RX", + .ops = &q6slim_ops, + .id = SLIMBUS_1_RX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Slimbus2 Playback", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 192000, + }, + .name = "SLIMBUS_2_RX", + .ops = &q6slim_ops, + .id = SLIMBUS_2_RX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Slimbus3 Playback", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 192000, + }, + .name = "SLIMBUS_3_RX", + .ops = &q6slim_ops, + .id = SLIMBUS_3_RX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Slimbus4 Playback", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 192000, + }, + .name = "SLIMBUS_4_RX", + .ops = &q6slim_ops, + .id = SLIMBUS_4_RX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Slimbus5 Playback", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 192000, + }, + .name = "SLIMBUS_5_RX", + .ops = &q6slim_ops, + .id = SLIMBUS_5_RX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Slimbus6 Playback", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &q6slim_ops, + .name = "SLIMBUS_6_RX", + .id = SLIMBUS_6_RX, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Primary MI2S Playback", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .id = PRIMARY_MI2S_RX, + .name = "PRI_MI2S_RX", + .ops = &q6i2s_ops, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .capture = { + .stream_name = "Primary MI2S Capture", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .id = PRIMARY_MI2S_TX, + .name = "PRI_MI2S_TX", + .ops = &q6i2s_ops, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Secondary MI2S Playback", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .name = "SEC_MI2S_RX", + .id = SECONDARY_MI2S_RX, + .ops = &q6i2s_ops, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .capture = { + .stream_name = "Secondary MI2S Capture", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .id = SECONDARY_MI2S_TX, + .name = "SEC_MI2S_TX", + .ops = &q6i2s_ops, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Tertiary MI2S Playback", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .name = "TERT_MI2S_RX", + .id = TERTIARY_MI2S_RX, + .ops = &q6i2s_ops, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .capture = { + .stream_name = "Tertiary MI2S Capture", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .id = TERTIARY_MI2S_TX, + .name = "TERT_MI2S_TX", + .ops = &q6i2s_ops, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .playback = { + .stream_name = "Quaternary MI2S Playback", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .name = "QUAT_MI2S_RX", + .id = QUATERNARY_MI2S_RX, + .ops = &q6i2s_ops, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, { + .capture = { + .stream_name = "Quaternary MI2S Capture", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .id = QUATERNARY_MI2S_TX, + .name = "QUAT_MI2S_TX", + .ops = &q6i2s_ops, + .probe = msm_dai_q6_dai_probe, + .remove = msm_dai_q6_dai_remove, + }, +}; + +static int q6afe_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name) +{ + int id = args->args[0]; + int ret = -EINVAL; + int i; + + for (i = 0; i < ARRAY_SIZE(q6afe_dais); i++) { + if (q6afe_dais[i].id == id) { + *dai_name = q6afe_dais[i].name; + ret = 0; + break; + } + } + + return ret; +} + +static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = { + SND_SOC_DAPM_AIF_OUT("HDMI_RX", "HDMI Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_RX", "Slimbus2 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_RX", "Slimbus5 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_RX", "Slimbus6 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX", "Tertiary MI2S Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX", "Tertiary MI2S Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_SD1", + "Secondary MI2S Playback SD1", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("PRI_MI2S_TX", "Primary MI2S Capture", + 0, 0, 0, 0), +}; + +static const struct snd_soc_component_driver q6afe_dai_component = { + .name = "q6afe-dai-component", + .dapm_widgets = q6afe_dai_widgets, + .num_dapm_widgets = ARRAY_SIZE(q6afe_dai_widgets), + .dapm_routes = q6afe_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(q6afe_dapm_routes), + .of_xlate_dai_name = q6afe_of_xlate_dai_name, + +}; + +static void of_q6afe_parse_dai_data(struct device *dev, + struct q6afe_dai_data *data) +{ + struct device_node *node; + int ret; + + for_each_child_of_node(dev->of_node, node) { + unsigned int lines[Q6AFE_MAX_MI2S_LINES]; + struct q6afe_dai_priv_data *priv; + int id, i, num_lines; + + ret = of_property_read_u32(node, "reg", &id); + if (ret || id > AFE_PORT_MAX) { + dev_err(dev, "valid dai id not found:%d\n", ret); + continue; + } + + switch (id) { + /* MI2S specific properties */ + case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: + priv = &data->priv[id]; + ret = of_property_read_variable_u32_array(node, + "qcom,sd-lines", + lines, 0, + Q6AFE_MAX_MI2S_LINES); + if (ret < 0) + num_lines = 0; + else + num_lines = ret; + + priv->sd_line_mask = 0; + + for (i = 0; i < num_lines; i++) + priv->sd_line_mask |= BIT(lines[i]); + + break; + default: + break; + } + } +} + +static int q6afe_dai_bind(struct device *dev, struct device *master, void *data) +{ + struct q6afe_dai_data *dai_data; + int rc = 0; + + dai_data = kzalloc(sizeof(*dai_data), GFP_KERNEL); + if (!dai_data) + rc = -ENOMEM; + + dev_set_drvdata(dev, dai_data); + + of_q6afe_parse_dai_data(dev, dai_data); + + return snd_soc_register_component(dev, &q6afe_dai_component, + q6afe_dais, ARRAY_SIZE(q6afe_dais)); +} + +static void q6afe_dai_unbind(struct device *dev, struct device *master, + void *data) +{ + struct q6afe_dai_data *dai_data = dev_get_drvdata(dev); + + snd_soc_unregister_component(dev); + kfree(dai_data); +} + +static const struct component_ops q6afe_dai_comp_ops = { + .bind = q6afe_dai_bind, + .unbind = q6afe_dai_unbind, +}; + +static int q6afe_dai_dev_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &q6afe_dai_comp_ops); +} + +static int q6afe_dai_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &q6afe_dai_comp_ops); + return 0; +} + +static struct platform_driver q6afe_dai_platform_driver = { + .driver = { + .name = "q6afe-dai", + }, + .probe = q6afe_dai_dev_probe, + .remove = q6afe_dai_dev_remove, +}; +module_platform_driver(q6afe_dai_platform_driver); + +MODULE_DESCRIPTION("Q6 Audio Fronend dai driver"); +MODULE_LICENSE("GPL v2"); From patchwork Thu Apr 26 09:46:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 134455 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2030794lji; Thu, 26 Apr 2018 02:51:23 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqVtTEK73nMxL6qtw1dqhC/IkoejH3nM8sSXJp6gAi8mZM4O5rRWHxT9xs2zPBIazT+urX+ X-Received: by 2002:a17:902:5502:: with SMTP id f2-v6mr8367439pli.108.1524736283039; Thu, 26 Apr 2018 02:51:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524736283; cv=none; d=google.com; s=arc-20160816; b=vlbMey/iSNt5aRWepecYtMG+nLkVmEYmAEETVcpVvwP5whxwDDd2dBU3/w85sXcyn2 7P6avW9Vh8OZcjgZLWbFkuGr4597YG6+40SDceGf316e5LoTY/dWRJcOa9nhlypclkuy RYH1MDtUTrHF4Q2D38Ydi+ydMUkVuqRQP+A3FdlsPVWTLq2VrQBfK47Xgck69+Vi/Yih l/9ure7l/+t9idyMoM+3iFLt9jWUbGnMAJH/XTHKkDJrOC1o/4G84Dv+N0o4vsnFj4qf TssBIdkvnpwsd6pIx0VWV1L8huoFpvLV503vEaiAc7FnNTt/l2xmu9+Y4MlJPBlKStJ8 Plew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=lgAAcUnwwyv2F8A9Civvds3e8cTfrEvTztK14NRt67E=; b=SIGBsqx33MCdDWJT/PZYicXTsNDXfn4fiBBj4LMFVlQozGYHWUm72rPv7sL6JwgXrS pgfnOva+nnEacDTtR629InuSTpVxfNZf1s4TuO3RhMNyrTyS+C6n33tWAamNt2HmvOWN wjZOjddNpnrm4ezdKFfU/cte2pY0zSQzuLU30zv2XTkyhchbUq7CqvRl1KGgQeFCC+qH ffqpyzFXc0Ymw/QDk8VjM3/6jeoPLzpVn4BFYjCvTfeK5c/3qc6ZFq0MK8a34xVsll85 KRGE04D7uRM1PA8V780s3eRC2qi6Ao4CvOfZGCgzD+OlFXCCAgTCyyrsLFxLTWlH4Z34 dKZw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CChbfFux; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z4si7261932pff.159.2018.04.26.02.51.22; Thu, 26 Apr 2018 02:51:23 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CChbfFux; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755415AbeDZJvP (ORCPT + 29 others); Thu, 26 Apr 2018 05:51:15 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:51424 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755166AbeDZJuA (ORCPT ); Thu, 26 Apr 2018 05:50:00 -0400 Received: by mail-wm0-f68.google.com with SMTP id j4so11836234wme.1 for ; Thu, 26 Apr 2018 02:49: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=lgAAcUnwwyv2F8A9Civvds3e8cTfrEvTztK14NRt67E=; b=CChbfFuxW3AmuRm/SvJapoi2IYsiyCpoj5MK3UkHTp6cmkwnvkIz01vQMd2jntsUko 1Wc6zRYWPOl54H8s7fZ0l1n4RAUnNMeLV8Zf3wFw6oA2NlUJ6GEn1MFApThK75vPfADF hIYaxzCr7IRumuNOQh4/T58oDjB3GHsvnPN8E= 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=lgAAcUnwwyv2F8A9Civvds3e8cTfrEvTztK14NRt67E=; b=rgx54JOMjlbcVaewGJdxLQOTxhoQohFAzgEH2IA2N5+kRnRuTTAbXlIXv1vKCE94MB e0UJ2d+hxQKmbpoTUwgiw8XuI8W/jTzF5pKyz4Zl39/8Di28GNPhJdYDTVxRrvJx0iAj Xo+btM/UUiFyZDr4CT0Xhi1rzxElLSTwe12kTRGzkNlvJ0sLXGPGCOWgbmwvKpoyexQ3 xXhPvmgRxesqIJUIAlBbcq0FP88eRWSK7oudNy0/T2eu0s2DWK89CHv3ua/AfSNBjUHt 1fIIfKaIY77rQkYOqPmRuvh6GpvhtwuyqSJUnP9s3zNSlXtHvuuUn2UnTC/N6J1ewdbX ryUQ== X-Gm-Message-State: ALQs6tAt7+rPKN/4B+3hVOSQ3zSz/jC1Z0GYx9R69em0gZSxIDaQlOL0 5kapAlzk9ayQnMAdW/JDumsIWw== X-Received: by 10.28.105.82 with SMTP id e79mr11685503wmc.76.1524736198902; Thu, 26 Apr 2018 02:49: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 a79sm5287289wme.48.2018.04.26.02.49.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Apr 2018 02:49:58 -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, bgoswami@codeaurora.org Cc: gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com, Srinivas Kandagatla Subject: [PATCH v6 21/24] ASoC: qdsp6: q6asm: Add q6asm dai driver Date: Thu, 26 Apr 2018 10:46:03 +0100 Message-Id: <20180426094606.4775-22-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Srinivas Kandagatla This patch adds support to q6asm dai driver which configures Q6ASM streams to pass pcm data. 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/q6asm-dai.c | 632 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 637 insertions(+) create mode 100644 sound/soc/qcom/qdsp6/q6asm-dai.c -- 2.16.2 diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 8d36f419e0f8..a424430af391 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -65,6 +65,9 @@ config SND_SOC_QDSP6_ROUTING config SND_SOC_QDSP6_ASM tristate +config SND_SOC_QDSP6_ASM_DAI + tristate + config SND_SOC_QDSP6 tristate "SoC ALSA audio driver for QDSP6" depends on QCOM_APR && HAS_DMA @@ -75,6 +78,7 @@ config SND_SOC_QDSP6 select SND_SOC_QDSP6_ADM select SND_SOC_QDSP6_ROUTING select SND_SOC_QDSP6_ASM + select SND_SOC_QDSP6_ASM_DAI 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 bada1aa303c2..c33b3cacbea1 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_QDSP6_AFE_DAI) += q6afe-dai.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_ASM_DAI) += q6asm-dai.o diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c new file mode 100644 index 000000000000..73d0c76933b4 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -0,0 +1,632 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +// Copyright (c) 2018, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6asm.h" +#include "q6routing.h" +#include "q6dsp-errno.h" + +#define PLAYBACK_MIN_NUM_PERIODS 2 +#define PLAYBACK_MAX_NUM_PERIODS 8 +#define PLAYBACK_MAX_PERIOD_SIZE 65536 +#define PLAYBACK_MIN_PERIOD_SIZE 128 +#define CAPTURE_MIN_NUM_PERIODS 2 +#define CAPTURE_MAX_NUM_PERIODS 8 +#define CAPTURE_MAX_PERIOD_SIZE 4096 +#define CAPTURE_MIN_PERIOD_SIZE 320 +#define SID_MASK_DEFAULT 0xF + +enum stream_state { + Q6ASM_STREAM_IDLE = 0, + Q6ASM_STREAM_STOPPED, + Q6ASM_STREAM_RUNNING, +}; + +struct q6asm_dai_rtd { + struct snd_pcm_substream *substream; + phys_addr_t phys; + unsigned int pcm_size; + unsigned int pcm_count; + unsigned int pcm_irq_pos; /* IRQ position */ + unsigned int periods; + uint16_t bits_per_sample; + uint16_t source; /* Encoding source bit mask */ + struct audio_client *audio_client; + uint16_t session_id; + enum stream_state state; +}; + +struct q6asm_dai_data { + long long int sid; +}; + +static struct snd_pcm_hardware q6asm_dai_hardware_capture = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 4, + .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * + CAPTURE_MAX_PERIOD_SIZE, + .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, + .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, + .periods_min = CAPTURE_MIN_NUM_PERIODS, + .periods_max = CAPTURE_MAX_NUM_PERIODS, + .fifo_size = 0, +}; + +static struct snd_pcm_hardware q6asm_dai_hardware_playback = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = (PLAYBACK_MAX_NUM_PERIODS * + PLAYBACK_MAX_PERIOD_SIZE), + .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, + .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, + .periods_min = PLAYBACK_MIN_NUM_PERIODS, + .periods_max = PLAYBACK_MAX_NUM_PERIODS, + .fifo_size = 0, +}; + +#define Q6ASM_FEDAI_DRIVER(num) { \ + .playback = { \ + .stream_name = "MultiMedia"#num" Playback", \ + .rates = (SNDRV_PCM_RATE_8000_192000| \ + SNDRV_PCM_RATE_KNOT), \ + .formats = (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE), \ + .channels_min = 1, \ + .channels_max = 8, \ + .rate_min = 8000, \ + .rate_max = 192000, \ + }, \ + .capture = { \ + .stream_name = "MultiMedia"#num" Capture", \ + .rates = (SNDRV_PCM_RATE_8000_48000| \ + SNDRV_PCM_RATE_KNOT), \ + .formats = (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE), \ + .channels_min = 1, \ + .channels_max = 4, \ + .rate_min = 8000, \ + .rate_max = 48000, \ + }, \ + .name = "MultiMedia"#num, \ + .probe = fe_dai_probe, \ + .id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \ + } + +/* Conventional and unconventional sample rate supported */ +static unsigned int supported_sample_rates[] = { + 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, + 88200, 96000, 176400, 192000 +}; + +static struct snd_pcm_hw_constraint_list constraints_sample_rates = { + .count = ARRAY_SIZE(supported_sample_rates), + .list = supported_sample_rates, + .mask = 0, +}; + +static void event_handler(uint32_t opcode, uint32_t token, + uint32_t *payload, void *priv) +{ + struct q6asm_dai_rtd *prtd = priv; + struct snd_pcm_substream *substream = prtd->substream; + + switch (opcode) { + case ASM_CLIENT_EVENT_CMD_RUN_DONE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + q6asm_write_async(prtd->audio_client, + prtd->pcm_count, 0, 0, NO_TIMESTAMP); + break; + case ASM_CLIENT_EVENT_CMD_EOS_DONE: + prtd->state = Q6ASM_STREAM_STOPPED; + break; + case ASM_CLIENT_EVENT_DATA_WRITE_DONE: { + prtd->pcm_irq_pos += prtd->pcm_count; + snd_pcm_period_elapsed(substream); + if (prtd->state == Q6ASM_STREAM_RUNNING) + q6asm_write_async(prtd->audio_client, + prtd->pcm_count, 0, 0, NO_TIMESTAMP); + + break; + } + case ASM_CLIENT_EVENT_DATA_READ_DONE: + prtd->pcm_irq_pos += prtd->pcm_count; + snd_pcm_period_elapsed(substream); + if (prtd->state == Q6ASM_STREAM_RUNNING) + q6asm_read(prtd->audio_client); + + break; + default: + break; + } +} + +static int q6asm_dai_prepare(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct q6asm_dai_rtd *prtd = runtime->private_data; + struct q6asm_dai_data *pdata; + int ret, i; + + pdata = snd_soc_platform_get_drvdata(soc_prtd->platform); + if (!pdata) + return -EINVAL; + + if (!prtd || !prtd->audio_client) { + pr_err("%s: private data null or audio client freed\n", + __func__); + return -EINVAL; + } + + prtd->pcm_count = snd_pcm_lib_period_bytes(substream); + prtd->pcm_irq_pos = 0; + /* rate and channels are sent to audio driver */ + if (prtd->state) { + /* clear the previous setup if any */ + q6asm_cmd(prtd->audio_client, CMD_CLOSE); + q6asm_unmap_memory_regions(substream->stream, + prtd->audio_client); + q6routing_stream_close(soc_prtd->dai_link->id, + substream->stream); + } + + ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client, + prtd->phys, + (prtd->pcm_size / prtd->periods), + prtd->periods); + + if (ret < 0) { + pr_err("Audio Start: Buffer Allocation failed rc = %d\n", + ret); + return -ENOMEM; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM, + prtd->bits_per_sample); + } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM, + prtd->bits_per_sample); + } + + if (ret < 0) { + pr_err("%s: q6asm_open_write failed\n", __func__); + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + return -ENOMEM; + } + + prtd->session_id = q6asm_get_session_id(prtd->audio_client); + ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE, + prtd->session_id, substream->stream); + if (ret) { + pr_err("%s: stream reg failed ret:%d\n", __func__, ret); + return ret; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = q6asm_media_format_block_multi_ch_pcm( + prtd->audio_client, runtime->rate, + runtime->channels, NULL, + prtd->bits_per_sample); + } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client, + runtime->rate, runtime->channels, + prtd->bits_per_sample); + + /* Queue the buffers */ + for (i = 0; i < runtime->periods; i++) + q6asm_read(prtd->audio_client); + + } + if (ret < 0) + pr_info("%s: CMD Format block failed\n", __func__); + + prtd->state = Q6ASM_STREAM_RUNNING; + + return 0; +} + +static int q6asm_dai_trigger(struct snd_pcm_substream *substream, int cmd) +{ + int ret = 0; + struct snd_pcm_runtime *runtime = substream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0); + break; + case SNDRV_PCM_TRIGGER_STOP: + prtd->state = Q6ASM_STREAM_STOPPED; + ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int q6asm_dai_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct snd_soc_dai *cpu_dai = soc_prtd->cpu_dai; + + struct q6asm_dai_rtd *prtd; + struct q6asm_dai_data *pdata; + struct device *dev = soc_prtd->platform->dev; + int ret = 0; + int stream_id; + + stream_id = cpu_dai->driver->id; + + pdata = snd_soc_platform_get_drvdata(soc_prtd->platform); + if (!pdata) { + pr_err("Platform data not found ..\n"); + return -EINVAL; + } + + prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL); + if (prtd == NULL) + return -ENOMEM; + + prtd->substream = substream; + prtd->audio_client = q6asm_audio_client_alloc(dev, + (q6asm_cb)event_handler, prtd, stream_id, + LEGACY_PCM_MODE); + if (!prtd->audio_client) { + pr_info("%s: Could not allocate memory\n", __func__); + kfree(prtd); + return -ENOMEM; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = q6asm_dai_hardware_playback; + else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + runtime->hw = q6asm_dai_hardware_capture; + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_sample_rates); + if (ret < 0) + pr_info("snd_pcm_hw_constraint_list failed\n"); + /* Ensure that buffer size is a multiple of period size */ + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + pr_info("snd_pcm_hw_constraint_integer failed\n"); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, + PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE, + PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE); + if (ret < 0) { + pr_err("constraint for buffer bytes min max ret = %d\n", + ret); + } + } + + ret = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); + if (ret < 0) { + pr_err("constraint for period bytes step ret = %d\n", + ret); + } + ret = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); + if (ret < 0) { + pr_err("constraint for buffer bytes step ret = %d\n", + ret); + } + + runtime->private_data = prtd; + + snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback); + + runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max; + + + if (pdata->sid < 0) + prtd->phys = substream->dma_buffer.addr; + else + prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32); + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + + return 0; +} + +static int q6asm_dai_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct q6asm_dai_rtd *prtd = runtime->private_data; + + if (prtd->audio_client) { + q6asm_cmd(prtd->audio_client, CMD_CLOSE); + q6asm_unmap_memory_regions(substream->stream, + prtd->audio_client); + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + } + q6routing_stream_close(soc_prtd->dai_link->id, + substream->stream); + kfree(prtd); + return 0; +} + +static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_pcm_substream *substream) +{ + + struct snd_pcm_runtime *runtime = substream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + + if (prtd->pcm_irq_pos >= prtd->pcm_size) + prtd->pcm_irq_pos = 0; + + return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); +} + +static int q6asm_dai_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct device *dev = soc_prtd->platform->dev; + + return dma_mmap_coherent(dev, vma, + runtime->dma_area, runtime->dma_addr, + runtime->dma_bytes); +} + +static int q6asm_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + + prtd->pcm_size = params_buffer_bytes(params); + prtd->periods = params_periods(params); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + prtd->bits_per_sample = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + prtd->bits_per_sample = 24; + break; + } + + return 0; +} + +static struct snd_pcm_ops q6asm_dai_ops = { + .open = q6asm_dai_open, + .hw_params = q6asm_dai_hw_params, + .close = q6asm_dai_close, + .ioctl = snd_pcm_lib_ioctl, + .prepare = q6asm_dai_prepare, + .trigger = q6asm_dai_trigger, + .pointer = q6asm_dai_pointer, + .mmap = q6asm_dai_mmap, +}; + +static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm_substream *psubstream, *csubstream; + struct q6asm_dai_data *pdata; + struct snd_pcm *pcm = rtd->pcm; + struct device *dev; + int size, ret; + + dev = rtd->platform->dev; + pdata = snd_soc_platform_get_drvdata(rtd->platform); + + size = q6asm_dai_hardware_playback.buffer_bytes_max; + + psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (psubstream) { + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, + &psubstream->dma_buffer); + if (ret) { + dev_err(dev, "Cannot allocate buffer(s)\n"); + return ret; + } + } + + csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; + if (csubstream) { + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, + &csubstream->dma_buffer); + if (ret) { + dev_err(dev, "Cannot allocate buffer(s)\n"); + if (psubstream) + snd_dma_free_pages(&psubstream->dma_buffer); + return ret; + } + } + + return ret; +} + +static void q6asm_dai_pcm_free(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + int i; + + for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { + substream = pcm->streams[i].substream; + if (substream) { + snd_dma_free_pages(&substream->dma_buffer); + substream->dma_buffer.area = NULL; + substream->dma_buffer.addr = 0; + } + } +} + +static struct snd_soc_platform_driver q6asm_soc_platform = { + .ops = &q6asm_dai_ops, + .pcm_new = q6asm_dai_pcm_new, + .pcm_free = q6asm_dai_pcm_free, + +}; + +static const struct snd_soc_dapm_route afe_pcm_routes[] = { + {"MM_DL1", NULL, "MultiMedia1 Playback" }, + {"MM_DL2", NULL, "MultiMedia2 Playback" }, + {"MM_DL3", NULL, "MultiMedia3 Playback" }, + {"MM_DL4", NULL, "MultiMedia4 Playback" }, + {"MM_DL5", NULL, "MultiMedia5 Playback" }, + {"MM_DL6", NULL, "MultiMedia6 Playback" }, + {"MM_DL7", NULL, "MultiMedia7 Playback" }, + {"MM_DL7", NULL, "MultiMedia8 Playback" }, + {"MultiMedia1 Capture", NULL, "MM_UL1"}, + {"MultiMedia2 Capture", NULL, "MM_UL2"}, + {"MultiMedia3 Capture", NULL, "MM_UL3"}, + {"MultiMedia4 Capture", NULL, "MM_UL4"}, + {"MultiMedia5 Capture", NULL, "MM_UL5"}, + {"MultiMedia6 Capture", NULL, "MM_UL6"}, + {"MultiMedia7 Capture", NULL, "MM_UL7"}, + {"MultiMedia8 Capture", NULL, "MM_UL8"}, + +}; + +static int fe_dai_probe(struct snd_soc_dai *dai) +{ + struct snd_soc_dapm_context *dapm; + + dapm = snd_soc_component_get_dapm(dai->component); + snd_soc_dapm_add_routes(dapm, afe_pcm_routes, + ARRAY_SIZE(afe_pcm_routes)); + + return 0; +} + +static const struct snd_soc_component_driver q6asm_fe_dai_component = { + .name = "q6asm-fe-dai", +}; + +static struct snd_soc_dai_driver q6asm_fe_dais[] = { + Q6ASM_FEDAI_DRIVER(1), + Q6ASM_FEDAI_DRIVER(2), + Q6ASM_FEDAI_DRIVER(3), + Q6ASM_FEDAI_DRIVER(4), + Q6ASM_FEDAI_DRIVER(5), + Q6ASM_FEDAI_DRIVER(6), + Q6ASM_FEDAI_DRIVER(7), + Q6ASM_FEDAI_DRIVER(8), +}; + +static int q6asm_dai_bind(struct device *dev, struct device *master, void *data) +{ + struct device_node *node = dev->of_node; + struct of_phandle_args args; + struct q6asm_dai_data *pdata; + int rc; + + pdata = kzalloc(sizeof(struct q6asm_dai_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args); + if (rc < 0) + pdata->sid = -1; + else + pdata->sid = args.args[0] & SID_MASK_DEFAULT; + + dev_set_drvdata(dev, pdata); + + rc = snd_soc_register_platform(dev, &q6asm_soc_platform); + if (rc) { + dev_err(dev, "err_dai_platform\n"); + return rc; + } + + return snd_soc_register_component(dev, &q6asm_fe_dai_component, + q6asm_fe_dais, + ARRAY_SIZE(q6asm_fe_dais)); +} +static void q6asm_dai_unbind(struct device *dev, struct device *master, + void *data) +{ + struct q6asm_dai_data *pdata = dev_get_drvdata(dev); + + snd_soc_unregister_platform(dev); + snd_soc_unregister_component(dev); + + kfree(pdata); + +} + +static const struct component_ops q6asm_dai_comp_ops = { + .bind = q6asm_dai_bind, + .unbind = q6asm_dai_unbind, +}; + +static int q6asm_dai_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &q6asm_dai_comp_ops); +} + +static int q6asm_dai_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &q6asm_dai_comp_ops); + return 0; +} + +static struct platform_driver q6asm_dai_platform_driver = { + .driver = { + .name = "q6asm-dai", + }, + .probe = q6asm_dai_probe, + .remove = q6asm_dai_dev_remove, +}; +module_platform_driver(q6asm_dai_platform_driver); + +MODULE_DESCRIPTION("Q6ASM dai driver"); +MODULE_LICENSE("GPL v2"); From patchwork Thu Apr 26 09:46:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 134452 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp2030556lji; Thu, 26 Apr 2018 02:51:07 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+9upm/orcpeprUjq1VnHPWh+FmF4nksO9PFZI7FEmoT/W1AZHNteI8BnZRB9ng83my3zPY X-Received: by 2002:a17:902:24e:: with SMTP id 72-v6mr32341587plc.87.1524736267134; Thu, 26 Apr 2018 02:51:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524736267; cv=none; d=google.com; s=arc-20160816; b=Ivyc5WQRGPQnhQj0mznCbhgIsYHT6Dt3Tx2fXRDg1G9DJftNFoSSiUD2pH6ru39JZb tXq5QzqVF7WoioL9OSK1/KvPU2ddksDmlgMCxSbPoutfc35klMwBFrZgju8tRr3XmDfh 4u/bTtFO1VtCzjz5EfjvtPA/ZJD6h5QCAFO2jxHVzYLqIRC4OM2XF1K3O+vZsAXFeYJX p7G9HCgtH/CIU1k1RAV2BidnTIy2z7cH90P+nHPWeDvr3GwWjRjmJkd9U/Ciu7ls94HK VOZIHJ1Ji0sz5DqK2UCn3HfwbWU1hpmAB6TqqStf8Flwm0MIyKEEFMGnSgLjEQDw79Ep glRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=uqhhZQ4sy+9siQY10dvdgb7PKlafLRjTMC8XUNrvQpY=; b=CGVL9Sd3w5F/Dm5eCoVG1I7gbqYmEJqXVAxZLTUT+6GGktcVJLyz3IPFhRLIOocWtL WAtdhnnGrTnEGewWbcXGpdgP/Q2AS8Hlr9sgNBru+hmfJ5VhqwMK68N9U3lqHNSM18K5 WJDL8o5YgO6czB5Ipo4KqcEddJMFgeTCiy+IpFJbZw/rg+AtyyfiJLCZ9GWxU++vN4xJ Qhj87zA30EF54uFsM2T+X148DhBveyyA8Onm2LK36QF/FLxEuQeEX106LHAyPwA2qXV9 orrsHvjGx8K/NetVLAyz3S/GE/Az/ZYCNqOwksDXfJCCRiFkX1Gt8J8jltmblYScIMJz sjTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=U5I7AsOQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w14si16059684pgc.633.2018.04.26.02.51.06; Thu, 26 Apr 2018 02:51:07 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=U5I7AsOQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755352AbeDZJvD (ORCPT + 29 others); Thu, 26 Apr 2018 05:51:03 -0400 Received: from mail-wr0-f193.google.com ([209.85.128.193]:46420 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755197AbeDZJuE (ORCPT ); Thu, 26 Apr 2018 05:50:04 -0400 Received: by mail-wr0-f193.google.com with SMTP id d1-v6so56066666wrj.13 for ; Thu, 26 Apr 2018 02:50:04 -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=uqhhZQ4sy+9siQY10dvdgb7PKlafLRjTMC8XUNrvQpY=; b=U5I7AsOQCGA/QKeJy5L53/LE6F9gZcaSgE70IvxI4VhU2rlm4V9WFfl2Rj6PrWVtDM kbqAwwo+GitL5r9n2VTXuQUW/MRk9rqhKQVzyan5akzaGi7lcJ29Fcy74doR/JjUOc5q Rd4bfO06wLjRsf5shsHK1sj0uXkl4HVpHjubc= 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=uqhhZQ4sy+9siQY10dvdgb7PKlafLRjTMC8XUNrvQpY=; b=sBVuW38FyKB4WahkS76VCcRNdFCFrEUnVXCeKexY9GPBPmhMfhQonItJAu2U09jVTm IE9zatybW2aO0ynmTu1f3hQGo/8zvqLibexmzWYsrAJbiEglZ9QsXULCjTdPtgpl/Clj YYD5ATIoEd1bGShCgdkKxBLkaR6fNaHQLMM7FUsYqqoBl+/9HtWhGCCNYoBOmeW46vAj H46mk6whLV47DpYtNHIZ6LxLTT7WrFNZ1W5gquGU7CkU1tBkttyM9RbIbqyGmlGYaqcs gNj4qoGJumRS3Aj4x+tmn2ZtVWQ1fbyhRVbUGfq2Ix9wI2Ye3bOXqbrMofGB4yKTjUs4 lZhA== X-Gm-Message-State: ALQs6tB3n0TZkD8T9K4Wzj8MRL/Uy+YttqScga2JWKi2X6K0Yx4IiqQs 20p6b/9OfAkJ96NNDiAPwQx2vA== X-Received: by 2002:adf:af28:: with SMTP id z37-v6mr27006411wrc.72.1524736203804; Thu, 26 Apr 2018 02:50:03 -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 a79sm5287289wme.48.2018.04.26.02.50.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Apr 2018 02:50: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, bgoswami@codeaurora.org Cc: gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com, Srinivas Kandagatla Subject: [PATCH v6 24/24] MAINTAINERS: Add myself as co-maintainer of qcom audio Date: Thu, 26 Apr 2018 10:46:06 +0100 Message-Id: <20180426094606.4775-25-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Srinivas Kandagatla Add myself as co-maintainer of qcom audio drivers Signed-off-by: Srinivas Kandagatla --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) -- 2.16.2 diff --git a/MAINTAINERS b/MAINTAINERS index dd66ae9a847e..8a67b0c61bad 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11531,6 +11531,7 @@ F: drivers/crypto/qat/ QCOM AUDIO (ASoC) DRIVERS M: Patrick Lai M: Banajit Goswami +M: Srinivas Kandagatla L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported F: sound/soc/qcom/