From patchwork Tue Feb 13 16:58:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128285 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4465790ljc; Tue, 13 Feb 2018 09:09:17 -0800 (PST) X-Google-Smtp-Source: AH8x2242s5QCCFBmMhNCojRtufgLt0LNtLxQNgG3LJpStIZKxEMx1FOO5O4OTa/9s/KRPjcLThBp X-Received: by 10.98.100.209 with SMTP id y200mr1890951pfb.117.1518541757147; Tue, 13 Feb 2018 09:09:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541757; cv=none; d=google.com; s=arc-20160816; b=0bRVShG2MYx7S7y4KLeEyBAAmEGyOvTx5FXUy0MmLDGrlvhzZ3lDm0YtuFESc+VKzK fp2ADcIskW54ZdZ9cBrisVJ5Byp0kej6ft2HAS+xqry/z6xdemBwaixMkADS0+s++tNa 14qtwqil0Ie5xswZOtkfejzOiroGCU3+ruMbWjt8J5Ax7DlXXG0GRW7lu8C+UOOwTEcY uDRcCqxnZI/GQUm//Yusnq/w0o2mgbPYtVwWF9n9uDwUeHT5nv57sLp7tyAAsBRcOT9J RIOtEVZ64puA7QkOZX8u/p59fznShtARbEn+pkcvyUAEuLJb+nzv0rVuRmahmRzbVjHS VOrw== 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=NikVY7pkf9LdxNZG+O4cIC6tzUFiMdF9b/3xLgnhnpk=; b=hA1y+vJWerEfTJlVjJKZMYW5PZtu89/7X2fwl/hmH9ShLgzIseYu8OZxYgfK55HnCC l/0atMmerRi0UF9z3KNo/SVk5veiB3snE5J/e+w0irXn3kqo+NeCD2a03z6V9W0XTRz+ URWT7erWti8qgiAPdmmqlAbxLpfInc9Jbse6tALOwZrqzS/kydzf8FUrdhwUTCKwOkgq 5BmhbwvV9HzngGy7GtlLihLbkHLPzhOPzB8Qa1sbFcVi0CVVbz2DcTjmY5sVYgMewwVj Ie42K65UrOLEh5t0cTLf6wudQfLWTJKImGdMWzj4WIw9Lh1+mj0YfQtrYR1Q7Dry2MhS FcQw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Y3AacGyZ; 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 z23-v6si7732488pll.4.2018.02.13.09.09.16; Tue, 13 Feb 2018 09:09:17 -0800 (PST) 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=Y3AacGyZ; 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 S965516AbeBMRJM (ORCPT + 28 others); Tue, 13 Feb 2018 12:09:12 -0500 Received: from mail-wr0-f195.google.com ([209.85.128.195]:41311 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965424AbeBMRBX (ORCPT ); Tue, 13 Feb 2018 12:01:23 -0500 Received: by mail-wr0-f195.google.com with SMTP id q11so7515784wre.8 for ; Tue, 13 Feb 2018 09:01:22 -0800 (PST) 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=NikVY7pkf9LdxNZG+O4cIC6tzUFiMdF9b/3xLgnhnpk=; b=Y3AacGyZX98fZ7WB1vysGkOwTbZJRKsJMnHgGfGQhTUgYyhmwcyDKT7DXza5Rb1Hwc ywvbSJ16ODPcVO1AZ1O8Q3thzpgQi1GVG9XJnZE9t4Aux09yBv8iQejqEwg1sBLS0mBi XdSH20DQhfkYzxmNomGTpr3zbnr8KbsFxEAYM= 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=NikVY7pkf9LdxNZG+O4cIC6tzUFiMdF9b/3xLgnhnpk=; b=dZtlElIJxI9yQ6a/tql24s1FfV8WSCOub93b/GRW3yVA/q0wMvn2K0WemuPceQU8XP L32on7v35b7yFvSK4AI+znE3JgsS7KMawEryb9xLBHvggzTRI/hMqfm2waW4KHmD7S08 qOt1lldIQx9SiLO3QZu4VljFhAebFlWPn9oyyx/oEVsEvUtJAGzIujzNZk2rS66Y8KK+ UrW7s4jh91hvOalOM+TSVJ8maNME52T5J8ueKNeqZF7MGDCObKFK7495jHOuk+L/8AmK Aa/sWST2od+s4MJh0KkDkn8RrFRWcaLgF7nYMCmevJOZ8yTAxmUxaRQZXey5IMKvCy6u 1XQQ== X-Gm-Message-State: APf1xPAaO2tTLVbtWhqrnJV9lv3vLYOdEvM5dKO53Bxz9PYyn2Jz7FW8 o5ekJ2KfD3FkOHB01I+fc+wVhg== X-Received: by 10.223.133.70 with SMTP id 64mr1689728wrh.219.1518541281394; Tue, 13 Feb 2018 09:01:21 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:20 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 05/25] ASoC: qcom: qdsp6: Add support to Q6AFE Date: Tue, 13 Feb 2018 16:58:17 +0000 Message-Id: <20180213165837.1620-6-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 (Audio Front End) module on Q6DSP. AFE module sits right at the other end of cpu where the codec/audio devices are connected. AFE provides abstraced interfaces to both hardware and virtual devices. Each AFE tx/rx port can be configured to connect to one of the hardware devices like codec, hdmi, slimbus, i2s and so on. AFE services include starting, stopping, and if needed, any configurations of the ports. Signed-off-by: Srinivas Kandagatla --- include/dt-bindings/sound/qcom,q6afe.h | 9 + sound/soc/qcom/Kconfig | 5 + sound/soc/qcom/Makefile | 5 + sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6afe.c | 520 +++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6afe.h | 37 +++ 6 files changed, 577 insertions(+) create mode 100644 include/dt-bindings/sound/qcom,q6afe.h create mode 100644 sound/soc/qcom/qdsp6/q6afe.c create mode 100644 sound/soc/qcom/qdsp6/q6afe.h -- 2.15.1 diff --git a/include/dt-bindings/sound/qcom,q6afe.h b/include/dt-bindings/sound/qcom,q6afe.h new file mode 100644 index 000000000000..b4d82cccdc86 --- /dev/null +++ b/include/dt-bindings/sound/qcom,q6afe.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef __DT_BINDINGS_Q6_AFE_H__ +#define __DT_BINDINGS_Q6_AFE_H__ + +/* Audio Front End (AFE) Ports */ +#define AFE_PORT_HDMI_RX 8 + +#endif /* __DT_BINDINGS_Q6_AFE_H__ */ + diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index b01f347b427d..caeaf8b1b561 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -48,10 +48,15 @@ config SND_SOC_QDSP6_COMMON tristate default n +config SND_SOC_QDSP6_AFE + tristate + default n + config SND_SOC_QDSP6 tristate "SoC ALSA audio driver for QDSP6" depends on QCOM_APR && HAS_DMA select SND_SOC_QDSP6_COMMON + select SND_SOC_QDSP6_AFE help To add support for MSM QDSP6 Soc Audio. This will enable sound soc platform specific diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index d5280355c24f..748f5e891dcf 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -13,6 +13,11 @@ obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o # Machine snd-soc-storm-objs := storm.o snd-soc-apq8016-sbc-objs := apq8016_sbc.o +snd-soc-msm8996-objs := apq8096.o obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o +obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-msm8996.o + +#DSP lib +obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/ diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index accebdb49306..9ec951e0833b 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o +obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c new file mode 100644 index 000000000000..0a5af06bb50e --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -0,0 +1,520 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2011-2017, The Linux Foundation + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6dsp-errno.h" +#include "q6afe.h" + +/* AFE CMDs */ +#define AFE_PORT_CMD_DEVICE_START 0x000100E5 +#define AFE_PORT_CMD_DEVICE_STOP 0x000100E6 +#define AFE_PORT_CMD_SET_PARAM_V2 0x000100EF +#define AFE_PORT_CMDRSP_GET_PARAM_V2 0x00010106 +#define AFE_PARAM_ID_HDMI_CONFIG 0x00010210 +#define AFE_MODULE_AUDIO_DEV_INTERFACE 0x0001020C + +/* Port IDs */ +#define AFE_API_VERSION_HDMI_CONFIG 0x1 +#define AFE_PORT_ID_MULTICHAN_HDMI_RX 0x100E +#define TIMEOUT_MS 1000 +#define AFE_CMD_RESP_AVAIL 0 +#define AFE_CMD_RESP_NONE 1 + +struct q6afe { + struct apr_device *apr; + struct device *dev; + int state; + int status; + + struct mutex lock; + struct list_head port_list; + spinlock_t port_list_lock; + struct list_head node; + void *dai_data; +}; + +struct afe_port_cmd_device_start { + struct apr_hdr hdr; + u16 port_id; + u16 reserved; +} __packed; + +struct afe_port_cmd_device_stop { + struct apr_hdr hdr; + u16 port_id; + u16 reserved; +/* Reserved for 32-bit alignment. This field must be set to 0.*/ +} __packed; + +struct afe_port_param_data_v2 { + u32 module_id; + u32 param_id; + u16 param_size; + u16 reserved; +} __packed; + +struct afe_port_cmd_set_param_v2 { + u16 port_id; + u16 payload_size; + u32 payload_address_lsw; + u32 payload_address_msw; + u32 mem_map_handle; +} __packed; + +struct afe_param_id_hdmi_multi_chan_audio_cfg { + u32 hdmi_cfg_minor_version; + u16 datatype; + u16 channel_allocation; + u32 sample_rate; + u16 bit_width; + u16 reserved; +} __packed; + +union afe_port_config { + struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch; +} __packed; + +struct q6afe_port { + wait_queue_head_t wait; + union afe_port_config port_cfg; + int token; + int id; + int cfg_type; + struct q6afe *afe; + struct list_head node; +}; + +struct afe_audioif_config_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; + union afe_port_config port; +} __packed; + +struct afe_port_map { + int port_id; + int token; + int is_rx; + int is_dig_pcm; +}; + +/* Port map of index vs real hw port ids */ +static struct afe_port_map port_maps[AFE_PORT_MAX] = { + [AFE_PORT_HDMI_RX] = { AFE_PORT_ID_MULTICHAN_HDMI_RX, + AFE_PORT_HDMI_RX, 1, 1}, +}; + +static struct q6afe_port *afe_find_port(struct q6afe *afe, int token) +{ + struct q6afe_port *p = NULL; + + spin_lock(&afe->port_list_lock); + list_for_each_entry(p, &afe->port_list, node) + if (p->token == token) + break; + + spin_unlock(&afe->port_list_lock); + return p; +} + +static int afe_callback(struct apr_device *adev, + struct apr_client_message *data) +{ + struct q6afe *afe = dev_get_drvdata(&adev->dev); + struct aprv2_ibasic_rsp_result_t *res; + struct q6afe_port *port; + + if (!data->payload_size) + return 0; + + res = data->payload; + if (data->opcode == APR_BASIC_RSP_RESULT) { + if (res->status) { + afe->status = res->status; + dev_err(afe->dev, "cmd = 0x%x returned error = 0x%x\n", + res->opcode, res->status); + } + + switch (res->opcode) { + case AFE_PORT_CMD_SET_PARAM_V2: + case AFE_PORT_CMD_DEVICE_STOP: + case AFE_PORT_CMD_DEVICE_START: + afe->state = AFE_CMD_RESP_AVAIL; + port = afe_find_port(afe, data->token); + if (port) + wake_up(&port->wait); + + break; + default: + dev_err(afe->dev, "Unknown cmd 0x%x\n", res->opcode); + break; + } + } + + return 0; +} +/** + * q6afe_get_port_id() - Get port id from a given port index + * + * @index: port index + * + * Return: Will be an negative on error or valid port_id on success + */ +int q6afe_get_port_id(int index) +{ + if (index < 0 || index > AFE_PORT_MAX) + return -EINVAL; + + return port_maps[index].port_id; +} +EXPORT_SYMBOL_GPL(q6afe_get_port_id); + +static int afe_apr_send_pkt(struct q6afe *afe, void *data, + wait_queue_head_t *wait) +{ + int ret; + + mutex_lock(&afe->lock); + afe->status = 0; + afe->state = AFE_CMD_RESP_NONE; + + ret = apr_send_pkt(afe->apr, data); + if (ret < 0) { + dev_err(afe->dev, "packet not transmitted\n"); + ret = -EINVAL; + goto err; + } + + ret = wait_event_timeout(*wait, (afe->state == AFE_CMD_RESP_AVAIL), + msecs_to_jiffies(TIMEOUT_MS)); + if (!ret) { + ret = -ETIMEDOUT; + } else if (afe->status > 0) { + dev_err(afe->dev, "DSP returned error[%s]\n", + q6dsp_strerror(afe->status)); + ret = q6dsp_errno(afe->status); + } else { + ret = 0; + } + +err: + mutex_unlock(&afe->lock); + + return ret; +} + +static int afe_send_cmd_port_start(struct q6afe_port *port) +{ + u16 port_id = port->id; + struct afe_port_cmd_device_start start; + struct q6afe *afe = port->afe; + int ret; + + start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + start.hdr.pkt_size = sizeof(start); + start.hdr.src_port = 0; + start.hdr.dest_port = 0; + start.hdr.token = port->token; + start.hdr.opcode = AFE_PORT_CMD_DEVICE_START; + start.port_id = port_id; + + ret = afe_apr_send_pkt(afe, &start, &port->wait); + if (ret) + dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", + port_id, ret); + + return ret; +} + +static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data, + int param_id, int psize) +{ + struct apr_hdr *hdr; + struct afe_port_cmd_set_param_v2 *param; + struct afe_port_param_data_v2 *pdata; + struct q6afe *afe = port->afe; + u16 port_id = port->id; + int ret; + + hdr = data; + param = data + sizeof(*hdr); + pdata = data + sizeof(*hdr) + sizeof(*param); + + hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + hdr->pkt_size = sizeof(*hdr) + sizeof(*param) + + sizeof(*pdata) + psize; + hdr->src_port = 0; + hdr->dest_port = 0; + hdr->token = port->token; + hdr->opcode = AFE_PORT_CMD_SET_PARAM_V2; + param->port_id = port_id; + param->payload_size = sizeof(*pdata) + psize; + param->payload_address_lsw = 0x00; + param->payload_address_msw = 0x00; + param->mem_map_handle = 0x00; + pdata->module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; + pdata->param_id = param_id; + pdata->param_size = psize; + + ret = afe_apr_send_pkt(afe, data, &port->wait); + if (ret) + dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", + port_id, ret); + + + return ret; +} + +static int afe_port_start(struct q6afe_port *port, + union afe_port_config *afe_config) +{ + struct afe_audioif_config_command config = {0,}; + struct q6afe *afe = port->afe; + int port_id = port->id; + int ret, param_id = port->cfg_type; + + config.port = *afe_config; + + ret = q6afe_port_set_param_v2(port, &config, param_id, + sizeof(*afe_config)); + if (ret) { + dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", + port_id, ret); + return ret; + } + return afe_send_cmd_port_start(port); +} + +/** + * q6afe_port_stop() - Stop a afe port + * + * @port: Instance of port to stop + * + * Return: Will be an negative on packet size on success. + */ +int q6afe_port_stop(struct q6afe_port *port) +{ + int port_id = port->id; + struct afe_port_cmd_device_stop stop; + struct q6afe *afe = port->afe; + int ret = 0; + int index = 0; + + port_id = port->id; + index = port->token; + if (index < 0 || index > AFE_PORT_MAX) { + dev_err(afe->dev, "AFE port index[%d] invalid!\n", index); + return -EINVAL; + } + + stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + stop.hdr.pkt_size = sizeof(stop); + stop.hdr.src_port = 0; + stop.hdr.dest_port = 0; + stop.hdr.token = index; + stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP; + stop.port_id = port_id; + stop.reserved = 0; + + ret = afe_apr_send_pkt(afe, &stop, &port->wait); + if (ret) + dev_err(afe->dev, "AFE close failed %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(q6afe_port_stop); + +/** + * q6afe_set_dai_data() - set dai private data + * + * @dev: Pointer to afe device. + * @data: dai private data + * + */ +void q6afe_set_dai_data(struct device *dev, void *data) +{ + struct q6afe *afe = dev_get_drvdata(dev); + + afe->dai_data = data; +} +EXPORT_SYMBOL_GPL(q6afe_set_dai_data); + +/** + * q6afe_get_dai_data() - get dai private data + * + * @dev: Pointer to afe device. + * + * Return: pointer to dai private data + */ +void *q6afe_get_dai_data(struct device *dev) +{ + struct q6afe *afe = dev_get_drvdata(dev); + + return afe->dai_data; +} +EXPORT_SYMBOL_GPL(q6afe_get_dai_data); + +/** + * q6afe_hdmi_port_prepare() - Prepare hdmi afe port. + * + * @port: Instance of afe port + * @cfg: HDMI configuration for the afe port + * + */ +void q6afe_hdmi_port_prepare(struct q6afe_port *port, + struct q6afe_hdmi_cfg *cfg) +{ + union afe_port_config *pcfg = &port->port_cfg; + + pcfg->hdmi_multi_ch.hdmi_cfg_minor_version = + AFE_API_VERSION_HDMI_CONFIG; + pcfg->hdmi_multi_ch.datatype = cfg->datatype; + pcfg->hdmi_multi_ch.channel_allocation = cfg->channel_allocation; + pcfg->hdmi_multi_ch.sample_rate = cfg->sample_rate; + pcfg->hdmi_multi_ch.bit_width = cfg->bit_width; +} +EXPORT_SYMBOL_GPL(q6afe_hdmi_port_prepare); + +/** + * q6afe_port_start() - Start a afe port + * + * @port: Instance of port to start + * + * Return: Will be an negative on packet size on success. + */ +int q6afe_port_start(struct q6afe_port *port) +{ + return afe_port_start(port, &port->port_cfg); +} +EXPORT_SYMBOL_GPL(q6afe_port_start); + +/** + * q6afe_port_get_from_id() - Get port instance from a port id + * + * @dev: Pointer to afe child device. + * @id: port id + * + * Return: Will be an error pointer on error or a valid afe port + * on success. + */ +struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id) +{ + int port_id; + struct q6afe *afe = dev_get_drvdata(dev); + struct q6afe_port *port; + int cfg_type; + + if (id < 0 || id > AFE_PORT_MAX) { + dev_err(dev, "AFE port token[%d] invalid!\n", id); + return ERR_PTR(-EINVAL); + } + + port_id = port_maps[id].port_id; + + switch (port_id) { + case AFE_PORT_ID_MULTICHAN_HDMI_RX: + cfg_type = AFE_PARAM_ID_HDMI_CONFIG; + break; + default: + dev_err(dev, "Invalid port id 0x%x\n", port_id); + return ERR_PTR(-EINVAL); + } + + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); + if (!port) + return ERR_PTR(-ENOMEM); + + init_waitqueue_head(&port->wait); + + port->token = id; + port->id = port_id; + port->afe = afe; + port->cfg_type = cfg_type; + + spin_lock(&afe->port_list_lock); + list_add_tail(&port->node, &afe->port_list); + spin_unlock(&afe->port_list_lock); + + return port; + +} +EXPORT_SYMBOL_GPL(q6afe_port_get_from_id); + +/** + * q6afe_port_put() - Release port reference + * + * @port: Instance of port to put + */ +void q6afe_port_put(struct q6afe_port *port) +{ + struct q6afe *afe = port->afe; + + spin_lock(&afe->port_list_lock); + list_del(&port->node); + spin_unlock(&afe->port_list_lock); +} +EXPORT_SYMBOL_GPL(q6afe_port_put); + +static int q6afev2_probe(struct apr_device *adev) +{ + struct q6afe *afe; + struct device *dev = &adev->dev; + + afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL); + if (!afe) + return -ENOMEM; + + afe->apr = adev; + mutex_init(&afe->lock); + afe->dev = dev; + INIT_LIST_HEAD(&afe->port_list); + spin_lock_init(&afe->port_list_lock); + + dev_set_drvdata(dev, afe); + + return q6afe_dai_dev_probe(dev); +} + +static int q6afev2_remove(struct apr_device *adev) +{ + return q6afe_dai_dev_remove(&adev->dev); +} + +static const struct of_device_id q6afe_device_id[] = { + { .compatible = "qcom,q6afe" }, + {}, +}; +MODULE_DEVICE_TABLE(of, q6afe_device_id); + +static struct apr_driver qcom_q6afe_driver = { + .probe = q6afev2_probe, + .remove = q6afev2_remove, + .callback = afe_callback, + .driver = { + .name = "qcom-q6afe", + .of_match_table = of_match_ptr(q6afe_device_id), + + }, +}; + +module_apr_driver(qcom_q6afe_driver); +MODULE_DESCRIPTION("Q6 Audio Front End"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h new file mode 100644 index 000000000000..43df524f01bb --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef __Q6AFE_H__ +#define __Q6AFE_H__ + +#include + +#define AFE_PORT_MAX 9 + +#define MSM_AFE_PORT_TYPE_RX 0 +#define MSM_AFE_PORT_TYPE_TX 1 +#define AFE_MAX_PORTS AFE_PORT_MAX + +struct q6afe_hdmi_cfg { + u16 datatype; + u16 channel_allocation; + u32 sample_rate; + u16 bit_width; +}; + +struct q6afe_port_config { + struct q6afe_hdmi_cfg hdmi; +}; + +struct q6afe_port; +void q6afe_set_dai_data(struct device *dev, void *data); +void *q6afe_get_dai_data(struct device *dev); + +struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id); +int q6afe_port_start(struct q6afe_port *port); +int q6afe_port_stop(struct q6afe_port *port); +void q6afe_port_put(struct q6afe_port *port); +int q6afe_get_port_id(int index); +void q6afe_hdmi_port_prepare(struct q6afe_port *port, + struct q6afe_hdmi_cfg *cfg); + +#endif /* __Q6AFE_H__ */ From patchwork Tue Feb 13 16:58:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128284 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4464412ljc; Tue, 13 Feb 2018 09:07:52 -0800 (PST) X-Google-Smtp-Source: AH8x2253oLAoKSsrBtHaAFlvhGceWmsdOx3s26sckHezCuKhP7oi0mdKf+qyP9SMW5qabRCIinDb X-Received: by 10.98.70.20 with SMTP id t20mr1881685pfa.201.1518541671990; Tue, 13 Feb 2018 09:07:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541671; cv=none; d=google.com; s=arc-20160816; b=DMkh8d3Pb+Y+lbNBA55juk9XZ6dfhBQDXKyvorNtSlvkUxSyCWWePCkJwOkH7OEuYC g/tJ8/RQIvDrDaqG6z8EIVjZanvIO1g9nuI4wgjsHMKnf0Dj6BgUTDx3KL4rIWHRBWL6 pcoqqp9yrWX0gT5BApRb30kfa05j+LQRdgN+z397Zs6mrtvxstgKjIaIdDfpms14B2Wd sEvhIM+fNXoxF9KX1MF9MSjDhJ+kcQCsM9nUdjeLjlTJaLgncZfgzsUSkIebKh+HcZc0 SMyA5qDZSoS7h4ngvQrYZu89WDfBC0CX9cJ1vDMb3eb1ei8cuK3+cOjm/xHzeub00xQT lxxQ== 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=ZFGa4P79N3sqHH4WCReDWhZvRjroAHsLP7+C7x7wntI=; b=LcadZNaNMWDll1hDEblaG+50/o6CJc0ekIrQgIotMP0pMLA4nLzQbUIQX+vlOTSa7w z4I4EOrA5U3XwIu5hr4sXyrWj0pfSUDh5cneFjGhhi1yg/4qBTEIEAblkDlBOVCw9e+m TEyS8KA8jlYs38EFYFcSeSFm2ChVpf5YfWWM3jcjXO63Wj1hqLwE5EIlcw3537yq983h GXGoElz5jucdx9JTris/dkiRCt4bbrbVtObKwMnZ5qfccs2FRyKao4fcJvx5awescltm Ll8tt9rHzMbvEsxsPv/JUf9kvtVfl/C2CDh0VlV0LhRRLuItbYADLq75DIvnHcl1fSkN PAEw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=brByQCDc; 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 k6-v6si149409plt.103.2018.02.13.09.07.51; Tue, 13 Feb 2018 09:07:51 -0800 (PST) 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=brByQCDc; 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 S965441AbeBMRHs (ORCPT + 28 others); Tue, 13 Feb 2018 12:07:48 -0500 Received: from mail-wm0-f65.google.com ([74.125.82.65]:51383 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965444AbeBMRB3 (ORCPT ); Tue, 13 Feb 2018 12:01:29 -0500 Received: by mail-wm0-f65.google.com with SMTP id r71so17416708wmd.1 for ; Tue, 13 Feb 2018 09:01:28 -0800 (PST) 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=ZFGa4P79N3sqHH4WCReDWhZvRjroAHsLP7+C7x7wntI=; b=brByQCDc/b+fFpXKwI0FNstSuFtAB8nuO2ti3yGlmhHzseYr/LHx+cM84G35aDbO2/ eRMRqvMHgvV1Jm/5ShZl/Jv0dyTS5TwZwSuEIpnaLuHuUlV/aRcAMq3R2XHbPsZ4j7yo VsVUCR28VBsFAVxIwX3/EI21WYCYTPvJtjci8= 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=ZFGa4P79N3sqHH4WCReDWhZvRjroAHsLP7+C7x7wntI=; b=QeAzZCjDOy7+RUwoVpCOKbA8yl7NWOXbaii+taKSs/SgLL7VUC6OZMZO559u6dL5FU sgN5pfRoEym3XLbP2q0ALXFz8PqaRgSCD1rx/W6dLKV0prjKFkQmVmLjS0KkS+Y0gkct 3/bMnBwIIazrY87JC7e774rFVwjgoT3GKfj3LzLRlCfZfT1AdFpoZn+miQsfVY09yczp KI468x0mG8MD5C+OKGUHebFo7xR2OYsfpTHnBSPN0Ea9Wfyq2dSegrJvyhZLTl0Cw7pw bVrekbyWi2zSYGRBINUPlIMcmW7Ldw5vABJDxK4PSHqCEinPNEax44rDr7FZrXjIhfW7 Wnnw== X-Gm-Message-State: APf1xPAVpMJvXOlDXs/xg1o58ayjekZBKMK0aL1Q2zZkbuWEZ0YUId3B g4bbExVdsCsZ+dIVHGIoSU528g== X-Received: by 10.28.137.85 with SMTP id l82mr1934894wmd.109.1518541287919; Tue, 13 Feb 2018 09:01:27 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:27 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 10/25] ASoC: qcom: q6asm: Add support to memory map and unmap Date: Tue, 13 Feb 2018 16:58:22 +0000 Message-Id: <20180213165837.1620-11-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 memory map and unmap regions commands in q6asm module. Signed-off-by: Srinivas Kandagatla --- sound/soc/qcom/qdsp6/q6asm.c | 312 +++++++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6asm.h | 5 + 2 files changed, 317 insertions(+) -- 2.15.1 diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index 768d9b446da9..412275edb15c 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -17,10 +17,47 @@ #include "q6dsp-errno.h" #include "q6dsp-common.h" +#define ASM_CMD_SHARED_MEM_MAP_REGIONS 0x00010D92 +#define ASM_CMDRSP_SHARED_MEM_MAP_REGIONS 0x00010D93 +#define ASM_CMD_SHARED_MEM_UNMAP_REGIONS 0x00010D94 + #define ASM_SYNC_IO_MODE 0x0001 #define ASM_ASYNC_IO_MODE 0x0002 #define ASM_TUN_READ_IO_MODE 0x0004 /* tunnel read write mode */ #define ASM_TUN_WRITE_IO_MODE 0x0008 /* tunnel read write mode */ +#define ASM_SHIFT_GAPLESS_MODE_FLAG 31 +#define ADSP_MEMORY_MAP_SHMEM8_4K_POOL 3 + +struct avs_cmd_shared_mem_map_regions { + struct apr_hdr hdr; + u16 mem_pool_id; + u16 num_regions; + u32 property_flag; +} __packed; + +struct avs_shared_map_region_payload { + u32 shm_addr_lsw; + u32 shm_addr_msw; + u32 mem_size_bytes; +} __packed; + +struct avs_cmd_shared_mem_unmap_regions { + struct apr_hdr hdr; + u32 mem_map_handle; +} __packed; + +struct audio_buffer { + phys_addr_t phys; + uint32_t used; + uint32_t size; /* size of buffer */ +}; + +struct audio_port_data { + struct audio_buffer *buf; + uint32_t num_periods; + uint32_t dsp_buf; + uint32_t mem_map_handle; +}; struct audio_client { int session; @@ -30,6 +67,8 @@ struct audio_client { uint32_t io_mode; struct apr_device *adev; struct mutex lock; + /* idx:1 out port, 0: in port */ + struct audio_port_data port[2]; wait_queue_head_t cmd_wait; int perf_mode; int stream_id; @@ -63,6 +102,237 @@ static bool q6asm_is_valid_audio_client(struct audio_client *ac) return false; } +static inline void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, + uint32_t pkt_size, bool cmd_flg, + uint32_t stream_id) +{ + hdr->hdr_field = APR_SEQ_CMD_HDR_FIELD; + hdr->src_svc = ac->adev->svc_id; + hdr->src_domain = APR_DOMAIN_APPS; + hdr->dest_svc = APR_SVC_ASM; + hdr->dest_domain = APR_DOMAIN_ADSP; + hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id); + hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id); + hdr->pkt_size = pkt_size; + if (cmd_flg) + hdr->token = ac->session; +} + +static int q6asm_apr_send_session_pkt(struct q6asm *a, struct audio_client *ac, + void *data) +{ + int rc; + + mutex_lock(&a->session_lock); + a->mem_state = 1; + rc = apr_send_pkt(a->adev, data); + if (rc < 0) + goto err; + + rc = wait_event_timeout(a->mem_wait, (a->mem_state <= 0), 5 * HZ); + if (!rc) { + dev_err(a->dev, "CMD timeout \n"); + rc = -ETIMEDOUT; + } else if (a->mem_state < 0) { + rc = q6dsp_errno(a->mem_state); + } + +err: + mutex_unlock(&a->session_lock); + return rc; +} + +static int __q6asm_memory_unmap(struct audio_client *ac, + phys_addr_t buf_add, int dir) +{ + struct avs_cmd_shared_mem_unmap_regions mem_unmap; + struct q6asm *a = dev_get_drvdata(ac->dev); + int rc; + + if (ac->port[dir].mem_map_handle == 0) { + dev_err(ac->dev, "invalid mem handle\n"); + return -EINVAL; + } + + mem_unmap.hdr.hdr_field = APR_SEQ_CMD_HDR_FIELD; + mem_unmap.hdr.src_port = 0; + mem_unmap.hdr.dest_port = 0; + mem_unmap.hdr.pkt_size = sizeof(mem_unmap); + mem_unmap.hdr.token = ((ac->session << 8) | dir); + + mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS; + mem_unmap.mem_map_handle = ac->port[dir].mem_map_handle; + + rc = q6asm_apr_send_session_pkt(a, ac, &mem_unmap); + if (rc < 0) + return rc; + + ac->port[dir].mem_map_handle = 0; + + return 0; +} + +/** + * q6asm_unmap_memory_regions() - unmap memory regions in the dsp. + * + * @dir: direction of audio stream + * @ac: audio client instanace + * + * Return: Will be an negative value on failure or zero on success + */ +int q6asm_unmap_memory_regions(unsigned int dir, struct audio_client *ac) +{ + struct audio_port_data *port; + int cnt = 0; + int rc = 0; + + mutex_lock(&ac->lock); + port = &ac->port[dir]; + if (!port->buf) { + rc = -EINVAL; + goto err; + } + cnt = port->num_periods - 1; + if (cnt >= 0) { + rc = __q6asm_memory_unmap(ac, port->buf[dir].phys, dir); + if (rc < 0) { + dev_err(ac->dev, "%s: Memory_unmap_regions failed %d\n", + __func__, rc); + goto err; + } + } + + port->num_periods = 0; + kfree(port->buf); + port->buf = NULL; + +err: + mutex_unlock(&ac->lock); + return rc; +} +EXPORT_SYMBOL_GPL(q6asm_unmap_memory_regions); + +static int __q6asm_memory_map_regions(struct audio_client *ac, int dir, + size_t period_sz, unsigned int periods, + bool is_contiguous) +{ + struct avs_cmd_shared_mem_map_regions *cmd = NULL; + struct avs_shared_map_region_payload *mregions = NULL; + struct q6asm *a = dev_get_drvdata(ac->dev); + struct audio_port_data *port = NULL; + struct audio_buffer *ab = NULL; + void *mmap_region_cmd = NULL; + uint32_t num_regions, buf_sz; + int rc, i, cmd_size; + + num_regions = is_contiguous ? 1 : periods; + buf_sz = is_contiguous ? (period_sz * periods) : period_sz; + buf_sz = PAGE_ALIGN(buf_sz); + + cmd_size = sizeof(*cmd) + (sizeof(*mregions) * num_regions); + mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL); + if (!mmap_region_cmd) + return -ENOMEM; + + cmd = mmap_region_cmd; + + cmd->hdr.hdr_field = APR_SEQ_CMD_HDR_FIELD; + cmd->hdr.src_port = 0; + cmd->hdr.dest_port = 0; + cmd->hdr.pkt_size = cmd_size; + cmd->hdr.token = ((ac->session << 8) | dir); + + + cmd->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS; + cmd->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL; + cmd->num_regions = num_regions; + cmd->property_flag = 0x00; + + mregions = mmap_region_cmd + sizeof(*cmd); + + port = &ac->port[dir]; + + for (i = 0; i < num_regions; i++) { + ab = &port->buf[i]; + mregions->shm_addr_lsw = lower_32_bits(ab->phys); + mregions->shm_addr_msw = upper_32_bits(ab->phys); + mregions->mem_size_bytes = buf_sz; + ++mregions; + } + + rc = q6asm_apr_send_session_pkt(a, ac, mmap_region_cmd); + + kfree(mmap_region_cmd); + + return rc; +} + +/** + * q6asm_map_memory_regions() - map memory regions in the dsp. + * + * @dir: direction of audio stream + * @ac: audio client instanace + * @phys: physcial address that needs mapping. + * @period_sz: audio period size + * @periods: number of periods + * + * Return: Will be an negative value on failure or zero on success + */ +int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac, + phys_addr_t phys, + size_t period_sz, unsigned int periods) +{ + struct audio_buffer *buf; + int cnt; + int rc; + + mutex_lock(&ac->lock); + + if (ac->port[dir].buf) { + dev_err(ac->dev, "Buffer already allocated\n"); + rc = 0; + goto err; + } + + + buf = kzalloc(((sizeof(struct audio_buffer)) * periods), GFP_KERNEL); + if (!buf) { + rc = -ENOMEM; + goto err; + } + + + ac->port[dir].buf = buf; + + buf[0].phys = phys; + buf[0].used = !!dir; + buf[0].size = period_sz; + + for (cnt = 1; cnt < periods; cnt++) { + if (period_sz > 0) { + buf[cnt].phys = buf[0].phys + (cnt * period_sz); + buf[cnt].used = dir ^ 1; + buf[cnt].size = period_sz; + } + } + + ac->port[dir].num_periods = periods; + + rc = __q6asm_memory_map_regions(ac, dir, period_sz, periods, 1); + if (rc < 0) { + dev_err(ac->dev, "Memory_map_regions failed\n"); + ac->port[dir].num_periods = 0; + kfree(buf); + ac->port[dir].buf = NULL; + goto err; + } + +err: + mutex_unlock(&ac->lock); + return rc; +} +EXPORT_SYMBOL_GPL(q6asm_map_memory_regions); + /** * q6asm_audio_client_free() - Freee allocated audio client * @@ -143,6 +413,48 @@ static int q6asm_srvc_callback(struct apr_device *adev, return 0; } + a = dev_get_drvdata(ac->dev); + dir = (data->token & 0x0F); + port = &ac->port[dir]; + + switch (data->opcode) + case APR_BASIC_RSP_RESULT: { + switch (result->opcode) { + case ASM_CMD_SHARED_MEM_MAP_REGIONS: + case ASM_CMD_SHARED_MEM_UNMAP_REGIONS: + if (result->status != 0) { + dev_err(ac->dev, + "cmd = 0x%x retur err= 0x%x sid:%d\n", + result->opcode, result->status, sid); + a->mem_state = -result->status; + } else { + a->mem_state = 0; + } + + wake_up(&a->mem_wait); + break; + default: + dev_err(&adev->dev, "command[0x%x] not expecting rsp\n", + result->opcode); + break; + } + return 0; + case ASM_CMDRSP_SHARED_MEM_MAP_REGIONS: + a->mem_state = 0; + ac->port[dir].mem_map_handle = result->opcode; + wake_up(&a->mem_wait); + break; + case ASM_CMD_SHARED_MEM_UNMAP_REGIONS: + a->mem_state = 0; + ac->port[dir].mem_map_handle = 0; + wake_up(&a->mem_wait); + break; + default: + dev_dbg(&adev->dev, "command[0x%x]success [0x%x]\n", + result->opcode, result->status); + break; + } + if (ac->cb) ac->cb(data->opcode, data->token, data->payload, ac->priv); diff --git a/sound/soc/qcom/qdsp6/q6asm.h b/sound/soc/qcom/qdsp6/q6asm.h index b13fe0d2ea61..a4f9fe636b7e 100644 --- a/sound/soc/qcom/qdsp6/q6asm.h +++ b/sound/soc/qcom/qdsp6/q6asm.h @@ -15,4 +15,9 @@ struct audio_client *q6asm_audio_client_alloc(struct device *dev, int session_id); void q6asm_audio_client_free(struct audio_client *ac); int q6asm_get_session_id(struct audio_client *ac); +int q6asm_map_memory_regions(unsigned int dir, + struct audio_client *ac, + phys_addr_t phys, + size_t bufsz, unsigned int bufcnt); +int q6asm_unmap_memory_regions(unsigned int dir, struct audio_client *ac); #endif /* __Q6_ASM_H__ */ From patchwork Tue Feb 13 16:58:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128266 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4457916ljc; Tue, 13 Feb 2018 09:02:04 -0800 (PST) X-Google-Smtp-Source: AH8x226IvJg3rC+ddtGOrpbO4KcvaoHGma0Pm2k1R8Rk0njyjrZuRMWKszsgfZE491Bzb2QDY28H X-Received: by 10.98.162.25 with SMTP id m25mr1866873pff.136.1518541324426; Tue, 13 Feb 2018 09:02:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541324; cv=none; d=google.com; s=arc-20160816; b=l922e706NKCNYpFd1lB7Lxwy3ryxWUUhKs2t2oP0oLM8Qqs7ovlxStflGOdJi+MJGA 9FT1BvWpSiz/RMv1qvDrfFuc3mBvbxxzGTqziTZJfs0ti9nF3iqRyXnOpibUwtXlCVRk gKJbOPiPnumUEGLWZsAdxvqqXSTocu7MrQoZM4wVhcz3TR3OdAv4l48bgRMvaGHblj0I Xvxqc7NJNM7Ml5IU470j6SuKk17QJBnL0vhDkOlMkdfjSDeSP8i3TVAyVq4b+7lORopw IvtPniCuHkItakaXCtMhBkaweO30BlnrJ/YzHurCFJxwD32oQz0JpPfLrjR+aScv6Yk4 +VTA== 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=O22S+/sN4zhFl5xFb510eNeXdKwH0X5GjboXgQ77iE4=; b=XMU7V9fIq+cMRvg4yAYqJ+mpeZhJn9ojrR7HWFud01XTs8N0bbHWuLj8ZdISnGKM6I Ca/DG3n70KA+26GDHtwkSWDEi30EooQPblHaRBsk+eUEIXTuBBBbP7W24pig6c2Pk8re 9JBgY04qr9lirJfLxEKDNVuAwjsGZzF9hpZRVFqR4JAXzMtolmkQVnBWqw9osQhCkRex oub0SjyrjKg3RHpunamqdZrZk9m86xcnwTPe/nRTxmNuJAbknCGbsmNYdv4ba1/S+mgP RRqQLEZKFAH/lrZ6f/+pMZR+B9qF9pff9ZaVeWHW8z0sLsTs3m/thII5wmNqutZxBiCd MLxQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=MiEtodRn; 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 bc11-v6si7528083plb.688.2018.02.13.09.02.04; Tue, 13 Feb 2018 09:02:04 -0800 (PST) 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=MiEtodRn; 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 S965531AbeBMRBr (ORCPT + 28 others); Tue, 13 Feb 2018 12:01:47 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:34412 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965452AbeBMRBb (ORCPT ); Tue, 13 Feb 2018 12:01:31 -0500 Received: by mail-wm0-f68.google.com with SMTP id j21so14097853wmh.1 for ; Tue, 13 Feb 2018 09:01:30 -0800 (PST) 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=O22S+/sN4zhFl5xFb510eNeXdKwH0X5GjboXgQ77iE4=; b=MiEtodRn9iq0AVhPWuOfTYf6XykD2xu0X9L50s2HfLj5p5g6LCpsQU+w3MOnEpTnF8 3lfDLSzWFf8cZZnm7iphzoYF+YHk1vx5lB6asZMP3ua1e60714hepzzh+QBz93OMcHac wsRW56M5jyAuthC1ZeILWVgbMfhVuz6Qn4ATE= 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=O22S+/sN4zhFl5xFb510eNeXdKwH0X5GjboXgQ77iE4=; b=IcLfUcAPTifnD6W42RVyCR2EpkewDtS7zTDhA6Vlf7zgUY5SJpFTvZC6bU8bU7H1++ /yJemHv2yqezQOgZVblSWHBZh+aoMvQOcRqLHs9rOa7yaqGlsOdBw9paR9XFlPyMHRJE yHiaV49wvKZre5S4MveCsUKSJ70vVORJmCiVJ1sIHkB6nPbEamgIoczotI3Gg/1/d5+f cYEcLlncmz3CUugJewSe5ynLuZ2KXJYbU/Oo+qtIZJ5PrPZsIIoDiRXYf8nI38tSkPdz xtockEGmickKhAwWJdeojfpRxCKhtGl6H76Cj/CpNY9CV2xzAX3d9nrICfkyZ5wJ97r9 aheA== X-Gm-Message-State: APf1xPCm/BMTmGJlemb2u1+gjexxkazIOwBAae0Q+Rygv+0/BAOa02h2 IwBFQqQylIGStT8uhIbsgM/Dkg== X-Received: by 10.28.249.22 with SMTP id x22mr1753470wmh.135.1518541289215; Tue, 13 Feb 2018 09:01:29 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:28 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 11/25] ASoC: qcom: q6asm: add support to audio stream apis Date: Tue, 13 Feb 2018 16:58:23 +0000 Message-Id: <20180213165837.1620-12-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 open, write and media format commands in the q6asm module. Signed-off-by: Srinivas Kandagatla --- include/dt-bindings/sound/qcom,q6asm.h | 22 ++ sound/soc/qcom/qdsp6/q6asm.c | 503 ++++++++++++++++++++++++++++++++- sound/soc/qcom/qdsp6/q6asm.h | 41 +++ 3 files changed, 564 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/sound/qcom,q6asm.h -- 2.15.1 diff --git a/include/dt-bindings/sound/qcom,q6asm.h b/include/dt-bindings/sound/qcom,q6asm.h new file mode 100644 index 000000000000..4e85bf804cec --- /dev/null +++ b/include/dt-bindings/sound/qcom,q6asm.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef __DT_BINDINGS_Q6_ASM_H__ +#define __DT_BINDINGS_Q6_ASM_H__ + +#define MSM_FRONTEND_DAI_MULTIMEDIA1 0 +#define MSM_FRONTEND_DAI_MULTIMEDIA2 1 +#define MSM_FRONTEND_DAI_MULTIMEDIA3 2 +#define MSM_FRONTEND_DAI_MULTIMEDIA4 3 +#define MSM_FRONTEND_DAI_MULTIMEDIA5 4 +#define MSM_FRONTEND_DAI_MULTIMEDIA6 5 +#define MSM_FRONTEND_DAI_MULTIMEDIA7 6 +#define MSM_FRONTEND_DAI_MULTIMEDIA8 7 +#define MSM_FRONTEND_DAI_MULTIMEDIA9 8 +#define MSM_FRONTEND_DAI_MULTIMEDIA10 9 +#define MSM_FRONTEND_DAI_MULTIMEDIA11 10 +#define MSM_FRONTEND_DAI_MULTIMEDIA12 11 +#define MSM_FRONTEND_DAI_MULTIMEDIA13 12 +#define MSM_FRONTEND_DAI_MULTIMEDIA14 13 +#define MSM_FRONTEND_DAI_MULTIMEDIA15 14 +#define MSM_FRONTEND_DAI_MULTIMEDIA16 15 + +#endif /* __DT_BINDINGS_Q6_ASM_H__ */ diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index 412275edb15c..0ee1e30a8d8e 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -17,10 +18,26 @@ #include "q6dsp-errno.h" #include "q6dsp-common.h" +#define ASM_STREAM_CMD_CLOSE 0x00010BCD +#define ASM_STREAM_CMD_FLUSH 0x00010BCE +#define ASM_SESSION_CMD_PAUSE 0x00010BD3 +#define ASM_DATA_CMD_EOS 0x00010BDB +#define ASM_DEFAULT_POPP_TOPOLOGY 0x00010BE4 +#define ASM_STREAM_CMD_FLUSH_READBUFS 0x00010C09 #define ASM_CMD_SHARED_MEM_MAP_REGIONS 0x00010D92 #define ASM_CMDRSP_SHARED_MEM_MAP_REGIONS 0x00010D93 #define ASM_CMD_SHARED_MEM_UNMAP_REGIONS 0x00010D94 - +#define ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2 0x00010D98 +#define ASM_DATA_EVENT_WRITE_DONE_V2 0x00010D99 +#define ASM_SESSION_CMD_RUN_V2 0x00010DAA +#define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 0x00010DA5 +#define ASM_DATA_CMD_WRITE_V2 0x00010DAB +#define ASM_SESSION_CMD_SUSPEND 0x00010DEC +#define ASM_STREAM_CMD_OPEN_WRITE_V3 0x00010DB3 + +#define ASM_LEGACY_STREAM_SESSION 0 +#define ASM_END_POINT_DEVICE_MATRIX 0 +#define ASM_DEFAULT_APP_TYPE 0 #define ASM_SYNC_IO_MODE 0x0001 #define ASM_ASYNC_IO_MODE 0x0002 #define ASM_TUN_READ_IO_MODE 0x0004 /* tunnel read write mode */ @@ -46,6 +63,49 @@ struct avs_cmd_shared_mem_unmap_regions { u32 mem_map_handle; } __packed; +struct asm_data_cmd_media_fmt_update_v2 { + u32 fmt_blk_size; +} __packed; + +struct asm_multi_channel_pcm_fmt_blk_v2 { + struct apr_hdr hdr; + struct asm_data_cmd_media_fmt_update_v2 fmt_blk; + u16 num_channels; + u16 bits_per_sample; + u32 sample_rate; + u16 is_signed; + u16 reserved; + u8 channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL]; +} __packed; + +struct asm_data_cmd_write_v2 { + struct apr_hdr hdr; + u32 buf_addr_lsw; + u32 buf_addr_msw; + u32 mem_map_handle; + u32 buf_size; + u32 seq_id; + u32 timestamp_lsw; + u32 timestamp_msw; + u32 flags; +} __packed; + +struct asm_stream_cmd_open_write_v3 { + struct apr_hdr hdr; + uint32_t mode_flags; + uint16_t sink_endpointype; + uint16_t bits_per_sample; + uint32_t postprocopo_id; + uint32_t dec_fmt_id; +} __packed; + +struct asm_session_cmd_run_v2 { + struct apr_hdr hdr; + u32 flags; + u32 time_lsw; + u32 time_msw; +} __packed; + struct audio_buffer { phys_addr_t phys; uint32_t used; @@ -131,7 +191,7 @@ static int q6asm_apr_send_session_pkt(struct q6asm *a, struct audio_client *ac, rc = wait_event_timeout(a->mem_wait, (a->mem_state <= 0), 5 * HZ); if (!rc) { - dev_err(a->dev, "CMD timeout \n"); + dev_err(a->dev, "CMD timeout\n"); rc = -ETIMEDOUT; } else if (a->mem_state < 0) { rc = q6dsp_errno(a->mem_state); @@ -395,6 +455,108 @@ void *q6asm_get_dai_data(struct device *dev) } EXPORT_SYMBOL_GPL(q6asm_get_dai_data); +static int32_t q6asm_stream_callback(struct apr_device *adev, + struct apr_client_message *data, + int session_id) +{ + struct q6asm *q6asm = dev_get_drvdata(&adev->dev); + struct aprv2_ibasic_rsp_result_t *result; + struct audio_port_data *port; + struct audio_client *ac; + uint32_t token; + uint32_t client_event = 0; + + ac = q6asm_get_audio_client(q6asm, session_id); + if (!ac)/* Audio client might already be freed by now */ + return 0; + + if (!q6asm_is_valid_audio_client(ac)) + return -EINVAL; + + result = data->payload; + + switch (data->opcode) { + case APR_BASIC_RSP_RESULT: + token = data->token; + switch (result->opcode) { + case ASM_SESSION_CMD_PAUSE: + client_event = ASM_CLIENT_EVENT_CMD_PAUSE_DONE; + break; + case ASM_SESSION_CMD_SUSPEND: + client_event = ASM_CLIENT_EVENT_CMD_SUSPEND_DONE; + break; + case ASM_DATA_CMD_EOS: + client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE; + break; + break; + case ASM_STREAM_CMD_FLUSH: + client_event = ASM_CLIENT_EVENT_CMD_FLUSH_DONE; + break; + case ASM_SESSION_CMD_RUN_V2: + client_event = ASM_CLIENT_EVENT_CMD_RUN_DONE; + break; + + case ASM_STREAM_CMD_FLUSH_READBUFS: + if (token != ac->session) { + dev_err(ac->dev, "session invalid\n"); + return -EINVAL; + } + case ASM_STREAM_CMD_CLOSE: + client_event = ASM_CLIENT_EVENT_CMD_CLOSE_DONE; + break; + case ASM_STREAM_CMD_OPEN_WRITE_V3: + case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: + if (result->status != 0) { + dev_err(ac->dev, + "cmd = 0x%x returned error = 0x%x\n", + result->opcode, result->status); + ac->cmd_state = -result->status; + wake_up(&ac->cmd_wait); + return 0; + } + break; + default: + dev_err(ac->dev, "command[0x%x] not expecting rsp\n", + result->opcode); + break; + } + + if (ac->cmd_state) { + ac->cmd_state = 0; + wake_up(&ac->cmd_wait); + } + if (ac->cb) + ac->cb(client_event, data->token, + data->payload, ac->priv); + + return 0; + + case ASM_DATA_EVENT_WRITE_DONE_V2: + port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; + + client_event = ASM_CLIENT_EVENT_DATA_WRITE_DONE; + + if (ac->io_mode & ASM_SYNC_IO_MODE) { + phys_addr_t phys = port->buf[data->token].phys; + + if (lower_32_bits(phys) != result->opcode || + upper_32_bits(phys) != result->status) { + dev_err(ac->dev, "Expected addr %pa\n", + &port->buf[data->token].phys); + return -EINVAL; + } + token = data->token; + port->buf[token].used = 1; + } + break; + } + + if (ac->cb) + ac->cb(client_event, data->token, data->payload, ac->priv); + + return 0; +} + static int q6asm_srvc_callback(struct apr_device *adev, struct apr_client_message *data) { @@ -404,6 +566,11 @@ static int q6asm_srvc_callback(struct apr_device *adev, struct audio_port_data *port; uint32_t dir = 0; uint32_t sid = 0; + int session_id; + + session_id = (data->dest_port >> 8) & 0xFF; + if (session_id) + return q6asm_stream_callback(adev, data, session_id); result = data->payload; sid = (data->token >> 8) & 0x0F; @@ -519,6 +686,338 @@ struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb, } EXPORT_SYMBOL_GPL(q6asm_audio_client_alloc); +static int q6asm_ac_send_cmd_sync(struct audio_client *ac, void *cmd) +{ + int rc; + + mutex_lock(&ac->lock); + ac->cmd_state = 1; + + rc = apr_send_pkt(ac->adev, cmd); + if (rc < 0) + goto err; + + rc = wait_event_timeout(ac->cmd_wait, (ac->cmd_state <= 0), 5 * HZ); + if (!rc) { + dev_err(ac->dev, "CMD timeout\n"); + rc = -ETIMEDOUT; + goto err; + } + + if (ac->cmd_state > 0) + rc = q6dsp_errno(ac->cmd_state); + +err: + mutex_unlock(&ac->lock); + return rc; +} + +/** + * q6asm_open_write() - Open audio client for writing + * + * @ac: audio client pointer + * @format: audio sample format + * @bits_per_sample: bits per sample + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_open_write(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample) +{ + struct asm_stream_cmd_open_write_v3 open; + int rc; + + q6asm_add_hdr(ac, &open.hdr, sizeof(open), true, ac->stream_id); + + open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3; + open.mode_flags = 0x00; + open.mode_flags |= ASM_LEGACY_STREAM_SESSION; + + /* source endpoint : matrix */ + open.sink_endpointype = ASM_END_POINT_DEVICE_MATRIX; + open.bits_per_sample = bits_per_sample; + open.postprocopo_id = ASM_DEFAULT_POPP_TOPOLOGY; + + switch (format) { + case FORMAT_LINEAR_PCM: + open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; + break; + default: + dev_err(ac->dev, "Invalid format 0x%x\n", format); + return -EINVAL; + } + + rc = q6asm_ac_send_cmd_sync(ac, &open); + if (rc < 0) + return rc; + + ac->io_mode |= ASM_TUN_WRITE_IO_MODE; + + return 0; +} +EXPORT_SYMBOL_GPL(q6asm_open_write); + +static int __q6asm_run(struct audio_client *ac, uint32_t flags, + uint32_t msw_ts, uint32_t lsw_ts, bool wait) +{ + struct asm_session_cmd_run_v2 run; + + q6asm_add_hdr(ac, &run.hdr, sizeof(run), true, ac->stream_id); + + run.hdr.opcode = ASM_SESSION_CMD_RUN_V2; + run.flags = flags; + run.time_lsw = lsw_ts; + run.time_msw = msw_ts; + if (wait) + return q6asm_ac_send_cmd_sync(ac, &run); + else + return apr_send_pkt(ac->adev, &run); + +} + +/** + * q6asm_run() - start the audio client + * + * @ac: audio client pointer + * @flags: flags associated with write + * @msw_ts: timestamp msw + * @lsw_ts: timestamp lsw + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_run(struct audio_client *ac, uint32_t flags, + uint32_t msw_ts, uint32_t lsw_ts) +{ + return __q6asm_run(ac, flags, msw_ts, lsw_ts, true); +} +EXPORT_SYMBOL_GPL(q6asm_run); + +/** + * q6asm_run_nowait() - start the audio client withou blocking + * + * @ac: audio client pointer + * @flags: flags associated with write + * @msw_ts: timestamp msw + * @lsw_ts: timestamp lsw + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, + uint32_t msw_ts, uint32_t lsw_ts) +{ + return __q6asm_run(ac, flags, msw_ts, lsw_ts, false); +} +EXPORT_SYMBOL_GPL(q6asm_run_nowait); + +/** + * q6asm_media_format_block_multi_ch_pcm() - setup pcm configuration + * + * @ac: audio client pointer + * @rate: audio sample rate + * @channels: number of audio channels. + * @use_default_chmap: flag to use default ch map. + * @channel_map: channel map pointer + * @bits_per_sample: bits per sample + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, + uint32_t rate, uint32_t channels, + u8 channel_map[PCM_FORMAT_MAX_NUM_CHANNEL], + uint16_t bits_per_sample) +{ + struct asm_multi_channel_pcm_fmt_blk_v2 fmt; + u8 *channel_mapping; + int rc; + + q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), true, ac->stream_id); + + fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; + fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) - + sizeof(fmt.fmt_blk); + fmt.num_channels = channels; + fmt.bits_per_sample = bits_per_sample; + fmt.sample_rate = rate; + fmt.is_signed = 1; + + channel_mapping = fmt.channel_mapping; + + if (channel_map) { + memcpy(channel_mapping, channel_map, + PCM_FORMAT_MAX_NUM_CHANNEL); + } else { + if (q6dsp_map_channels(channel_mapping, channels)) { + dev_err(ac->dev, " map channels failed %d\n", channels); + return -EINVAL; + } + } + + rc = q6asm_ac_send_cmd_sync(ac, &fmt); + if (rc < 0) + goto fail_cmd; + + return 0; +fail_cmd: + return rc; +} +EXPORT_SYMBOL_GPL(q6asm_media_format_block_multi_ch_pcm); + +/** + * q6asm_write_async() - non blocking write + * + * @ac: audio client pointer + * @len: lenght in bytes + * @msw_ts: timestamp msw + * @lsw_ts: timestamp lsw + * @flags: flags associated with write + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, + uint32_t lsw_ts, uint32_t flags) +{ + struct asm_data_cmd_write_v2 write; + struct audio_port_data *port; + struct audio_buffer *ab; + int rc = 0; + + if (!(ac->io_mode & ASM_SYNC_IO_MODE)) + return 0; + + port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; + q6asm_add_hdr(ac, &write.hdr, sizeof(write), false, + ac->stream_id); + + ab = &port->buf[port->dsp_buf]; + + write.hdr.token = port->dsp_buf; + write.hdr.opcode = ASM_DATA_CMD_WRITE_V2; + write.buf_addr_lsw = lower_32_bits(ab->phys); + write.buf_addr_msw = upper_32_bits(ab->phys); + write.buf_size = len; + write.seq_id = port->dsp_buf; + write.timestamp_lsw = lsw_ts; + write.timestamp_msw = msw_ts; + write.mem_map_handle = + ac->port[SNDRV_PCM_STREAM_PLAYBACK].mem_map_handle; + + if (flags == NO_TIMESTAMP) + write.flags = (flags & 0x800000FF); + else + write.flags = (0x80000000 | flags); + + port->dsp_buf++; + + if (port->dsp_buf >= port->num_periods) + port->dsp_buf = 0; + + rc = apr_send_pkt(ac->adev, &write); + if (rc < 0) + return rc; + + return 0; +} +EXPORT_SYMBOL_GPL(q6asm_write_async); + +static void q6asm_reset_buf_state(struct audio_client *ac) +{ + int cnt = 0; + int loopcnt = 0; + int used; + struct audio_port_data *port = NULL; + + if (!(ac->io_mode & ASM_SYNC_IO_MODE)) + return; + + used = (ac->io_mode & ASM_TUN_WRITE_IO_MODE ? 1 : 0); + mutex_lock(&ac->lock); + for (loopcnt = 0; loopcnt <= SNDRV_PCM_STREAM_CAPTURE; + loopcnt++) { + port = &ac->port[loopcnt]; + cnt = port->num_periods - 1; + port->dsp_buf = 0; + while (cnt >= 0) { + if (!port->buf) + continue; + port->buf[cnt].used = used; + cnt--; + } + } + mutex_unlock(&ac->lock); +} + +static int __q6asm_cmd(struct audio_client *ac, int cmd, bool wait) +{ + int stream_id = ac->stream_id; + struct apr_hdr hdr; + int rc; + + q6asm_add_hdr(ac, &hdr, sizeof(hdr), true, stream_id); + + switch (cmd) { + case CMD_PAUSE: + hdr.opcode = ASM_SESSION_CMD_PAUSE; + break; + case CMD_SUSPEND: + hdr.opcode = ASM_SESSION_CMD_SUSPEND; + break; + case CMD_FLUSH: + hdr.opcode = ASM_STREAM_CMD_FLUSH; + break; + case CMD_OUT_FLUSH: + hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS; + break; + case CMD_EOS: + hdr.opcode = ASM_DATA_CMD_EOS; + break; + case CMD_CLOSE: + hdr.opcode = ASM_STREAM_CMD_CLOSE; + break; + default: + return -EINVAL; + } + + if (wait) + rc = q6asm_ac_send_cmd_sync(ac, &hdr); + else + return apr_send_pkt(ac->adev, &hdr); + + if (rc < 0) + return rc; + + if (cmd == CMD_FLUSH) + q6asm_reset_buf_state(ac); + + return 0; +} + +/** + * q6asm_cmd() - run cmd on audio client + * + * @ac: audio client pointer + * @cmd: command to run on audio client. + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_cmd(struct audio_client *ac, int cmd) +{ + return __q6asm_cmd(ac, cmd, true); +} +EXPORT_SYMBOL_GPL(q6asm_cmd); + +/** + * q6asm_cmd_nowait() - non blocking, run cmd on audio client + * + * @ac: audio client pointer + * @cmd: command to run on audio client. + * + * Return: Will be an negative value on error or zero on success + */ +int q6asm_cmd_nowait(struct audio_client *ac, int cmd) +{ + return __q6asm_cmd(ac, cmd, false); +} +EXPORT_SYMBOL_GPL(q6asm_cmd_nowait); static int q6asm_probe(struct apr_device *adev) { diff --git a/sound/soc/qcom/qdsp6/q6asm.h b/sound/soc/qcom/qdsp6/q6asm.h index a4f9fe636b7e..b5ef90bb724b 100644 --- a/sound/soc/qcom/qdsp6/q6asm.h +++ b/sound/soc/qcom/qdsp6/q6asm.h @@ -1,8 +1,35 @@ // SPDX-License-Identifier: GPL-2.0 #ifndef __Q6_ASM_H__ #define __Q6_ASM_H__ +#include "q6dsp-common.h" +#include + +/* ASM client callback events */ +#define CMD_PAUSE 0x0001 +#define ASM_CLIENT_EVENT_CMD_PAUSE_DONE 0x1001 +#define CMD_FLUSH 0x0002 +#define ASM_CLIENT_EVENT_CMD_FLUSH_DONE 0x1002 +#define CMD_EOS 0x0003 +#define ASM_CLIENT_EVENT_CMD_EOS_DONE 0x1003 +#define CMD_CLOSE 0x0004 +#define ASM_CLIENT_EVENT_CMD_CLOSE_DONE 0x1004 +#define CMD_OUT_FLUSH 0x0005 +#define ASM_CLIENT_EVENT_CMD_OUT_FLUSH_DONE 0x1005 +#define CMD_SUSPEND 0x0006 +#define ASM_CLIENT_EVENT_CMD_SUSPEND_DONE 0x1006 +#define ASM_CLIENT_EVENT_CMD_RUN_DONE 0x1008 +#define ASM_CLIENT_EVENT_DATA_WRITE_DONE 0x1009 + +enum { + LEGACY_PCM_MODE = 0, + LOW_LATENCY_PCM_MODE, + ULTRA_LOW_LATENCY_PCM_MODE, + ULL_POST_PROCESSING_PCM_MODE, +}; #define MAX_SESSIONS 16 +#define NO_TIMESTAMP 0xFF00 +#define FORMAT_LINEAR_PCM 0x0000 void q6asm_set_dai_data(struct device *dev, void *data); void *q6asm_get_dai_data(struct device *dev); @@ -14,6 +41,20 @@ struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb, void *priv, int session_id); void q6asm_audio_client_free(struct audio_client *ac); +int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, + uint32_t lsw_ts, uint32_t flags); +int q6asm_open_write(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample); +int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, + uint32_t rate, uint32_t channels, + u8 channel_map[PCM_FORMAT_MAX_NUM_CHANNEL], + uint16_t bits_per_sample); +int q6asm_run(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, + uint32_t lsw_ts); +int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, + uint32_t lsw_ts); +int q6asm_cmd(struct audio_client *ac, int cmd); +int q6asm_cmd_nowait(struct audio_client *ac, int cmd); int q6asm_get_session_id(struct audio_client *ac); int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac, From patchwork Tue Feb 13 16:58:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128272 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4459839ljc; Tue, 13 Feb 2018 09:03:35 -0800 (PST) X-Google-Smtp-Source: AH8x225ZBdjB4b3v2lfBrBoRRlQ6I2OZW63WPWMfhzHSakavpcrIYX9TPQL5hHQQbkAAlQKrpuXn X-Received: by 10.101.89.6 with SMTP id f6mr1530825pgu.22.1518541415421; Tue, 13 Feb 2018 09:03:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541415; cv=none; d=google.com; s=arc-20160816; b=hcnk2fg7yw5y4vYHKNev4VKVf9L/Ah3Yhk088LySyZ4WHwLO62A+apvABJZ1Ckpvqn 4T8GA9MJcdwHa4MaUQyZFTCadch7sZZ1yNuIDH8oFTaNLMzzxZBLSUaqEJLC+UCGfPMI kF6r4u8zeplBzDfxol0yXn5nKnwXJqJS32ARCafOd32E8di89t42mkhDjXV1okTCzsV4 Nwqy9pKXlOeGMFGpcyM7vnXr/ov68DbK616xIWM43bqU0fMy1OimpSHzDA2Ed1yqh7UK SKwRKzt9UKyibdJQYFH+prygSiqgSf2QTy/N9Pjmk2/ovyltHA+4OrJYNVzsA6ZnJu4l G9ZA== 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=ubU4NA3gnjL1OFpQ6vKR45QNVGR2PTsWF+aeTHJ02dU=; b=rTT4Ea90k6zQvNpDz5DKiB02lZLMAIOcFmCoeVPZ/FFbM1tJ56K19a1XPLCrED/Hmz CTC28TI1sUGoa3sSFg1OAzSq5keM7zgt1YBW2w0k7iSewXB9zDHh/M2r7fltsEKFXkp2 eL3DBmHzWmcqoRNZkfW+clwrNucMtmml1J7g54tkWqCo94xNwkW1b39iG6PeUsMKDbtM w5tqLllX/b00MAI2nzhN2d8ov44WOH6rH7DQsGZ/nT3uKdXQrc4sDpoo+iGgnHqRObZH /gTdsA/KutUut0N4sw2wWsPEyaG3UxWWfLQRmLCDhluQSv+HXm5DUcW4fXuqA6iCiHJf q29Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=WsUc6b7K; 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 a20-v6si1545721plm.683.2018.02.13.09.03.35; Tue, 13 Feb 2018 09:03:35 -0800 (PST) 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=WsUc6b7K; 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 S965510AbeBMRBo (ORCPT + 28 others); Tue, 13 Feb 2018 12:01:44 -0500 Received: from mail-wr0-f194.google.com ([209.85.128.194]:47083 "EHLO mail-wr0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965467AbeBMRBd (ORCPT ); Tue, 13 Feb 2018 12:01:33 -0500 Received: by mail-wr0-f194.google.com with SMTP id 34so9042800wre.13 for ; Tue, 13 Feb 2018 09:01:32 -0800 (PST) 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=ubU4NA3gnjL1OFpQ6vKR45QNVGR2PTsWF+aeTHJ02dU=; b=WsUc6b7KxV0kyj/0zrykS8DZ0A5i+QegJvJql+sbmRwQlG85QuMPmmc2UbcjcbfAPc x4n5XIQzPoas8GeFYmWQH4iKV0dMnMbBkJmjV1Jh4lRTSN/IvwU+4qPcXTsKbGa2eQbZ b6LUvRHyN7zDC9RzEwiGR1BX8NIiWArttgKl4= 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=ubU4NA3gnjL1OFpQ6vKR45QNVGR2PTsWF+aeTHJ02dU=; b=gAPWQa+NC14UKw7L+eEywO/3qrNrT1yXxv654oAkQazP3x3sR3sZAxnr0t3p9jniR+ nKXQC4s7Zeb/Kl+xXSluDa2R9xN664+kQQ0GYcOX1u+KDOYHe5/RUxCZ7pe9pD+P+Khb XFHzmwqVDgnKf72rOO62XDBKzJ9EtGnXBiS2G2ei/BlTltyuOqPTULtBwM4EtRqZODSl AseSIHCCKf5y9oyuZ6/deWN72yoBtK7yT8BQLdUg9o0PQe4ixLd5qh/giSLxVT42WGtt ifte+w2MF1Q9Glv0NwvVnhDn1GaWIVjFyp8rn7sYVsG0uYzukkELuQvtwTntnOoTgVGr YFPg== X-Gm-Message-State: APf1xPAz6F0NiLYg9Ukn7tjWQjnL3IdZHKhGrkeN7dgF5UcGLzoG3oyp 4w54ApyWNjnmxvzm0DUtQUgfhg== X-Received: by 10.223.134.104 with SMTP id 37mr1713553wrw.150.1518541290701; Tue, 13 Feb 2018 09:01:30 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:29 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 12/25] ASoC: qcom: qdsp6: Add support to Q6CORE Date: Tue, 13 Feb 2018 16:58:24 +0000 Message-Id: <20180213165837.1620-13-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 core apr service, which is used to query status of other static and dynamic services on the dsp. Signed-off-by: Srinivas Kandagatla --- sound/soc/qcom/Kconfig | 5 + sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6core.c | 235 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6core.h | 9 ++ 4 files changed, 250 insertions(+) create mode 100644 sound/soc/qcom/qdsp6/q6core.c create mode 100644 sound/soc/qcom/qdsp6/q6core.h -- 2.15.1 diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index a14d960b8fe4..8c2d65e0a28e 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -60,6 +60,10 @@ config SND_SOC_QDSP6_ASM tristate default n +config SND_SOC_QDSP6_CORE + tristate + default n + config SND_SOC_QDSP6 tristate "SoC ALSA audio driver for QDSP6" depends on QCOM_APR && HAS_DMA @@ -67,6 +71,7 @@ config SND_SOC_QDSP6 select SND_SOC_QDSP6_AFE select SND_SOC_QDSP6_ADM select SND_SOC_QDSP6_ASM + select SND_SOC_QDSP6_CORE help To add support for MSM QDSP6 Soc Audio. This will enable sound soc platform specific diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index eea962315ab3..61f089bc0d25 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o obj-$(CONFIG_SND_SOC_QDSP6_ADM) += q6adm.o obj-$(CONFIG_SND_SOC_QDSP6_ASM) += q6asm.o +obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o diff --git a/sound/soc/qcom/qdsp6/q6core.c b/sound/soc/qcom/qdsp6/q6core.c new file mode 100644 index 000000000000..d4a3ff409a34 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6core.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2011-2017, The Linux Foundation + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6dsp-errno.h" + +#define ADSP_STATE_READY_TIMEOUT_MS 3000 +#define Q6_READY_TIMEOUT_MS 100 +#define AVCS_CMD_ADSP_EVENT_GET_STATE 0x0001290C +#define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D +#define AVCS_GET_VERSIONS 0x00012905 +#define AVCS_GET_VERSIONS_RSP 0x00012906 + +struct avcs_svc_info { + uint32_t service_id; + uint32_t version; +} __packed; + +struct q6core { + struct apr_device *adev; + wait_queue_head_t wait; + uint32_t avcs_state; + bool resp_received; + uint32_t num_services; + struct avcs_svc_info *svcs_info; +}; + +struct q6core *core; + +static int q6core_callback(struct apr_device *adev, + struct apr_client_message *data) +{ + struct q6core *core = dev_get_drvdata(&adev->dev); + struct aprv2_ibasic_rsp_result_t *result; + + result = data->payload; + switch (data->opcode) { + case AVCS_GET_VERSIONS_RSP: + core->num_services = result->status; + + core->svcs_info = kcalloc(core->num_services, + sizeof(*core->svcs_info), + GFP_ATOMIC); + if (!core->svcs_info) + return -ENOMEM; + + /* svc info is after apr result */ + memcpy(core->svcs_info, result + sizeof(*result), + core->num_services * sizeof(*core->svcs_info)); + + core->resp_received = true; + wake_up(&core->wait); + + break; + case AVCS_CMDRSP_ADSP_EVENT_GET_STATE: + core->avcs_state = result->opcode; + + core->resp_received = true; + wake_up(&core->wait); + break; + default: + dev_err(&adev->dev, "Message id from adsp core svc: 0x%x\n", + data->opcode); + break; + } + + return 0; +} + +static int q6core_get_svc_versions(struct q6core *core) +{ + struct apr_device *adev = core->adev; + struct apr_hdr hdr = {0}; + int rc; + + hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + hdr.pkt_size = APR_HDR_SIZE; + hdr.opcode = AVCS_GET_VERSIONS; + + rc = apr_send_pkt(adev, &hdr); + if (rc < 0) + return rc; + + rc = wait_event_timeout(core->wait, (core->resp_received), + msecs_to_jiffies(Q6_READY_TIMEOUT_MS)); + if (rc > 0 && core->resp_received) { + core->resp_received = false; + return 0; + } + + return rc; +} + +static bool __q6core_is_adsp_ready(struct q6core *core) +{ + struct apr_device *adev = core->adev; + struct apr_hdr hdr = {0}; + int rc; + + hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + hdr.pkt_size = APR_HDR_SIZE; + hdr.opcode = AVCS_CMD_ADSP_EVENT_GET_STATE; + + rc = apr_send_pkt(adev, &hdr); + if (rc < 0) + return false; + + rc = wait_event_timeout(core->wait, (core->resp_received), + msecs_to_jiffies(Q6_READY_TIMEOUT_MS)); + if (rc > 0 && core->resp_received) { + core->resp_received = false; + if (core->avcs_state == 0x1) + return true; + } + + return false; +} + +/** + * q6core_get_svc_version() - Get version number of a service. + * + * @svc_id: service id of the service. + * + * Return: Will be a valid version number on success and zero on failure. + * version number returned contains bits 0 to 15 as Minor version number + * Bits 16 to 31 as Major version number + */ +uint32_t q6core_get_svc_version(int svc_id) +{ + struct apr_device *adev; + struct avcs_svc_info *svcs_info; + int i, ret; + + if (!core) + return 0; + + if (!core->svcs_info) { + ret = q6core_get_svc_versions(core); + if (ret) + return ret; + } + + adev = core->adev; + svcs_info = core->svcs_info; + + for (i = 0; i < core->num_services; i++) + if (svcs_info[i].service_id == svc_id) + return svcs_info[i].version; + + return 0; +} +EXPORT_SYMBOL_GPL(q6core_get_svc_version); + +/** + * q6core_is_adsp_ready() - Get status of adsp + * + * Return: Will be an true if adsp is ready and false if not. + */ +bool q6core_is_adsp_ready(void) +{ + unsigned long timeout; + + if (!core) + return false; + + timeout = jiffies + msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS); + for (;;) { + if (__q6core_is_adsp_ready(core)) + return true; + + if (!time_after(timeout, jiffies)) + return false; + } + + return false; +} +EXPORT_SYMBOL_GPL(q6core_is_adsp_ready); + +static int q6core_probe(struct apr_device *adev) +{ + core = kzalloc(sizeof(*core), GFP_KERNEL); + if (!core) + return -ENOMEM; + + dev_set_drvdata(&adev->dev, core); + + core->adev = adev; + init_waitqueue_head(&core->wait); + + return 0; +} + +static int q6core_exit(struct apr_device *adev) +{ + if (core->svcs_info) + kfree(core->svcs_info); + + kfree(core); + core = NULL; + + return 0; +} + +static const struct of_device_id q6core_device_id[] = { + { .compatible = "qcom,q6core" }, + {}, +}; +MODULE_DEVICE_TABLE(of, q6core_device_id); + +static struct apr_driver qcom_q6core_driver = { + .probe = q6core_probe, + .remove = q6core_exit, + .callback = q6core_callback, + .driver = { + .name = "qcom-q6core", + .of_match_table = of_match_ptr(q6core_device_id), + }, +}; + +module_apr_driver(qcom_q6core_driver); +MODULE_DESCRIPTION("q6 core"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/qdsp6/q6core.h b/sound/soc/qcom/qdsp6/q6core.h new file mode 100644 index 000000000000..2852fbb7756e --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6core.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef __Q6CORE_H__ +#define __Q6CORE_H__ + +bool q6core_is_adsp_ready(void); +uint32_t q6core_get_svc_version(int svc_id); + +#endif /* __Q6CORE_H__ */ From patchwork Tue Feb 13 16:58:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128283 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4463052ljc; Tue, 13 Feb 2018 09:06:38 -0800 (PST) X-Google-Smtp-Source: AH8x226vfza3Z+LL9ulfy3G3jy5Fh0+3WrC94znVRszGI2f9SuF73w4jd+/lkotCBbg6Wykr04Di X-Received: by 10.101.69.202 with SMTP id m10mr1536874pgr.198.1518541598027; Tue, 13 Feb 2018 09:06:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541598; cv=none; d=google.com; s=arc-20160816; b=uuT5etGn//7ggZlql8ZsuaqfcYoZaCaMoRjEYPw8Pn4zuVkesz2zY+YjL/6F6To4tP k7gKc/uBFGoTlu5k2fxLrsswk3OW1E1Gg3xLylcISWhHR08zcCtC4ZXBaDT6xtRR5g2E yKda6V/MCllBKvFerK304j9yoq23EtX+pcwcHgRN0ZZcDx9GEgiupmrfGLOevCHL0Ems MkvFqK4pD/LkKUtOtuQHzsp1dIT++5oRtsMnN5t7WOM302bO6tTmvfi3D7y6G8B1an8K 8PdynDMkXGDPsyF0OKQm0sHD7XuEQNyev/3E/x3NowaTQ7+9ziqsysRAtabTIdyWr+bi 3VQQ== 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=NzXx/7xx90cj4vNHdnWI3nyfy1k7UcSOr4DBdxOe+ko=; b=KCksY4NC6fvMXCfySAaH4N/r0sQM6zlqyb14kZsMqaRfUu8UJFDdxz1uOa2zcmupVc Uo93e0zk4j0gudI/qD9/lhC35jmHyYikBQhU7z9z3RklgbO3p4yIjAxNPDgelVTRz+HS ku+lbiSM4mdv84hWCW5kS8kDapHGwqXvkFFlU5iOkebm+vqC1kWMgZ8hrxlp+nlzy7jX P9lZCES0iOiQ/jQjsbxljUcruTAa3dhqifNgqRLZ8dHURqXnZc3qhFuU362RNsOJ3Qkn rK3rfryCvbcAI/RS1nawCoS8R1gsjXiQlmHqlUS6A5rbj0qRSIxcyEUItx1mYRHEgnHM htGQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=e4irG1zK; 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 h15-v6si4159652pli.212.2018.02.13.09.06.37; Tue, 13 Feb 2018 09:06:38 -0800 (PST) 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=e4irG1zK; 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 S965563AbeBMRFg (ORCPT + 28 others); Tue, 13 Feb 2018 12:05:36 -0500 Received: from mail-wr0-f195.google.com ([209.85.128.195]:36713 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965167AbeBMRBf (ORCPT ); Tue, 13 Feb 2018 12:01:35 -0500 Received: by mail-wr0-f195.google.com with SMTP id y3so19304691wrh.3 for ; Tue, 13 Feb 2018 09:01:34 -0800 (PST) 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=NzXx/7xx90cj4vNHdnWI3nyfy1k7UcSOr4DBdxOe+ko=; b=e4irG1zKtc36AuFORVQr+ldB6ny6cwxhQtzPm4Dr35RW2FEo40viZtQNLY10hkQULs JRKCIiai+gcxOTWRjjlDF9PuEk+M0Zqi8p1zLJCAmOqrtkNrAfHPyYUhRQpcLpAsHdt5 rxk5YC7b6o5tpuAGMxenH0JiZfRMsCf0Nq8AQ= 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=NzXx/7xx90cj4vNHdnWI3nyfy1k7UcSOr4DBdxOe+ko=; b=YBXg8/F+QCyJ7rnLHSlbucIf8O7dsVB1glF0xtKKt9mDMk2z/stI8N48PjqUCLgALs VFTZcDtEFoagPK1iVJNTRBZ+/QJ2Fn0Jy5rDp9ptARTAMUu33i1CAIBi3BJOFMQdbJe2 l3d2XNGjz8eot7+5q757MTX+YPe4X8g3QYK+oMWWndXoFnk30w0O9o/K3CHfKhjEQYHI E25qGFVWe06YbIOAuTv4LHUIx2Zt9GW4cuEbSL2yb2lwDLiZkKPDuVZde5jf+P4uuXVO U7c9qT9yYSOAlzpo6zq4QvdQDmrOqyYjXdCyiZvfnuS7UnP4ryaI74bGWarjyn22+xmc gUNA== X-Gm-Message-State: APf1xPC/OFO1H/5k9kzwhvwxLKLvOmBmx7cUPnCHcFWcZ5aTCgcKzPzO PfyJAtmVWHNGb52gAEN2C1Mw7Q== X-Received: by 10.223.160.82 with SMTP id l18mr1820874wrl.76.1518541293363; Tue, 13 Feb 2018 09:01:33 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:32 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 14/25] ASoC: qcom: qdsp6: Add support to q6afe dai driver Date: Tue, 13 Feb 2018 16:58:26 +0000 Message-Id: <20180213165837.1620-15-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 --- sound/soc/qcom/qdsp6/Makefile | 2 +- sound/soc/qcom/qdsp6/q6afe-dai.c | 280 +++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6afe.h | 3 + 3 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 sound/soc/qcom/qdsp6/q6afe-dai.c -- 2.15.1 diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 660afcab98fd..c7833842b878 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o -obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o +obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o q6afe-dai.o obj-$(CONFIG_SND_SOC_QDSP6_ADM) += q6adm.o q6routing.o obj-$(CONFIG_SND_SOC_QDSP6_ASM) += q6asm.o obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c new file mode 100644 index 000000000000..f6a618e9db9e --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2011-2016, The Linux Foundation + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6afe.h" + +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]; +}; + +static int q6hdmi_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct q6afe_dai_data *dai_data = kcontrol->private_data; + int value = ucontrol->value.integer.value[0]; + + dai_data->port_config[AFE_PORT_HDMI_RX].hdmi.datatype = value; + + return 0; +} + +static int q6hdmi_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + struct q6afe_dai_data *dai_data = kcontrol->private_data; + + ucontrol->value.integer.value[0] = + dai_data->port_config[AFE_PORT_HDMI_RX].hdmi.datatype; + + return 0; +} + +static const char * const hdmi_format[] = { + "LPCM", + "Compr" +}; + +static const struct soc_enum hdmi_config_enum[] = { + SOC_ENUM_SINGLE_EXT(2, hdmi_format), +}; + +static const struct snd_kcontrol_new q6afe_config_controls[] = { + SOC_ENUM_EXT("HDMI RX Format", hdmi_config_enum[0], + q6hdmi_format_get, + q6hdmi_format_put), +}; + +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 = q6afe_get_dai_data(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; + } + + /*refer to 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 q6afe_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = q6afe_get_dai_data(dai->dev); + + dai_data->is_port_started[dai->id] = false; + + return 0; +} + +static void q6afe_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = q6afe_get_dai_data(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\n"); + + dai_data->is_port_started[dai->id] = false; + +} + +static int q6afe_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = q6afe_get_dai_data(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\n"); + return rc; + } + } + + if (dai->id == AFE_PORT_HDMI_RX) + q6afe_hdmi_port_prepare(dai_data->port[dai->id], + &dai_data->port_config[dai->id].hdmi); + + 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 const struct snd_soc_dapm_route q6afe_dapm_routes[] = { + {"HDMI Playback", NULL, "HDMI_RX"}, +}; + +static struct snd_soc_dai_ops q6hdmi_ops = { + .prepare = q6afe_dai_prepare, + .hw_params = q6hdmi_hw_params, + .shutdown = q6afe_dai_shutdown, + .startup = q6afe_dai_startup, +}; + +static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = q6afe_get_dai_data(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 = q6afe_get_dai_data(dai->dev); + + q6afe_port_put(dai_data->port[dai->id]); + + 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 = AFE_PORT_HDMI_RX, + .name = "HDMI", + .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 i, ret = -EINVAL; + + 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), +}; + +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), + .controls = q6afe_config_controls, + .num_controls = ARRAY_SIZE(q6afe_config_controls), + .dapm_routes = q6afe_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(q6afe_dapm_routes), + .of_xlate_dai_name = q6afe_of_xlate_dai_name, + +}; + +int q6afe_dai_dev_probe(struct device *dev) +{ + int rc = 0; + struct q6afe_dai_data *dai_data; + + dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL); + if (!dai_data) + rc = -ENOMEM; + + q6afe_set_dai_data(dev, dai_data); + + return devm_snd_soc_register_component(dev, &q6afe_dai_component, + q6afe_dais, ARRAY_SIZE(q6afe_dais)); +} +EXPORT_SYMBOL_GPL(q6afe_dai_dev_probe); + +int q6afe_dai_dev_remove(struct device *dev) +{ + return 0; +} +EXPORT_SYMBOL_GPL(q6afe_dai_dev_remove); +MODULE_DESCRIPTION("Q6 Audio Fronend dai driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 43df524f01bb..647ed2d15545 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -26,6 +26,9 @@ struct q6afe_port; void q6afe_set_dai_data(struct device *dev, void *data); void *q6afe_get_dai_data(struct device *dev); +int q6afe_dai_dev_probe(struct device *dev); +int q6afe_dai_dev_remove(struct device *dev); + struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id); int q6afe_port_start(struct q6afe_port *port); int q6afe_port_stop(struct q6afe_port *port); From patchwork Tue Feb 13 16:58:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128277 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4460732ljc; Tue, 13 Feb 2018 09:04:21 -0800 (PST) X-Google-Smtp-Source: AH8x2240aqs63+T46YNtrF80+NnrA9Ogb76nwoNuUkb99G0klxd/tEqZKxZQmvG5p4isiHT3hCfX X-Received: by 10.99.120.199 with SMTP id t190mr248937pgc.72.1518541460962; Tue, 13 Feb 2018 09:04:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541460; cv=none; d=google.com; s=arc-20160816; b=cLsH80VvylbJ4Rx+t+Ypmuc0C7rxxoKirJZqOSr1TuKDxn3hBW8BAckFGHb1NJXQId DbQ7ZD9zVhqeheNp09sbvnX44iN2p54KtvdpGu3oZs7M7GPLkhl9BM5m5Mwiqrn/U8A7 3kYUPXX/eL4zdM2tR4FDsm6h4ARLh10vcM6QBmCdRV48rmx/hRS1pnB/4KfEXNvQnFSW Yz2mowsv0PDJU5Dsf7TydHcEeBxMBNA/4TuLXZ+C2cidKUvfKb/NvhI4wml0cwG5doHv VpSyHbnIUtZYBgaLI299OKSl/HVeUF3uOvwub/InBgfNQgUt6IBXu5/BQVQtJLXmjlij YRpw== 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=BA7amHDIKknaujBvB3KOcdzGNeIdDsT8b1j5zA+gGvM=; b=CYUahr/mR49wMK72X9DicFBKhh8Bibi5WIoksr0WaVwzjgyb2PhGqX+fYq+v1Ttiq6 VMDBOyvppUpPRUsH6WHzO8RG4kkahjm5Jr6LpBVX78+LdPJA6r70eqlKsbEsylalS7ux FqE2twzTwogdQCpTRPUCkj8ukB+EOFh/NLmsBvmYBCQJ4sxe4MnENM9WVEtGMkTUv+hZ o92pwhTCuSHivNa9WKYRhOGI0jRJOlrFRlNl1+n9L02ek8XpWOmhJl48z+bshBijGih1 a0XMRMFFAxMRtOGfiGcIldRUDj/UYrr+PJJVScW65ZYAMPVsaLj3mBcj65BVZnhS2EMN iGwg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=NGOUwxEs; 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 z3-v6si6045419plo.815.2018.02.13.09.04.20; Tue, 13 Feb 2018 09:04:20 -0800 (PST) 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=NGOUwxEs; 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 S965410AbeBMREC (ORCPT + 28 others); Tue, 13 Feb 2018 12:04:02 -0500 Received: from mail-wm0-f67.google.com ([74.125.82.67]:54924 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965492AbeBMRBn (ORCPT ); Tue, 13 Feb 2018 12:01:43 -0500 Received: by mail-wm0-f67.google.com with SMTP id i186so17317304wmi.4 for ; Tue, 13 Feb 2018 09:01:42 -0800 (PST) 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=BA7amHDIKknaujBvB3KOcdzGNeIdDsT8b1j5zA+gGvM=; b=NGOUwxEsnRKO/hGpSI9eMuSZ1fIrr0jl9KbTCygsake9iMDb61rVklPgtMbyhhWo5u INi462cC9VbfozpAruHH/GmEUnHeWICsLvEOjg6ON5YY+DZ+B7StfFBRPSU0HsX4KqX5 xTFgSioCJ8Oz3RxRGVa9nRER6faVNHFY0nNIE= 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=BA7amHDIKknaujBvB3KOcdzGNeIdDsT8b1j5zA+gGvM=; b=FY39ZNf57csXwSUWhSKyYLCnTMz/SwQkh322Joo92nbxvEZDWPGjLwkKEnsVMSxL7u RpM8lGfbr8dxZY83cN1SjI8JoSMtEPYYELHctl11KqS1BLVntgd09F1512G7rQuLUa2N fDoxdIvmytoZldvZh9YsoJgpLBOytG0vMqzrzW4RpSEIi32Pum1ukA0x9pv6t7Lvg+Dl USPlLZ6fAUNKwrcsXXbxMJzKMVyyqcd1Uf00kXqO+HfrY6lCxtx/igdgenLp32rdA1gx HegkXrATMqs4ONfolM2kmjeFK6k2tJMEk6Mv3BdZ0OtQjaCSA/m74ju/Zy3pFuAyxqrm xW1Q== X-Gm-Message-State: APf1xPCPIXi81UnycZEhoXBvPZ6fewl+OeS4RL7DNOz3IP8yZlk1Q08W 9NP+6tvPuZuHET/aY7bEozmZIw== X-Received: by 10.28.138.146 with SMTP id m140mr2013901wmd.85.1518541301950; Tue, 13 Feb 2018 09:01:41 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:41 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 20/25] ASoC: qcom: q6afe: add support to MI2S sysclks Date: Tue, 13 Feb 2018 16:58:32 +0000 Message-Id: <20180213165837.1620-21-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 LPASS Bit clock, LPASS Digital core clock and OSR clock. These clocks are required for both MI2S and PCM setup. Signed-off-by: Srinivas Kandagatla --- sound/soc/qcom/qdsp6/q6afe.c | 115 +++++++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/qdsp6/q6afe.h | 10 ++++ 2 files changed, 125 insertions(+) -- 2.15.1 diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index c04caea5481c..ea6fa3848007 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -31,6 +31,9 @@ #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 @@ -94,6 +97,11 @@ #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 #define AFE_CMD_RESP_NONE 1 @@ -191,6 +199,23 @@ struct afe_param_id_slimbus_cfg { */ } __packed; +struct afe_clk_cfg { + u32 i2s_cfg_minor_version; + u32 clk_val1; + u32 clk_val2; + u16 clk_src; + u16 clk_root; + u16 clk_set_mode; + u16 reserved; +} __packed; + +struct afe_digital_clk_cfg { + u32 i2s_cfg_minor_version; + u32 clk_val; + u16 clk_root; + u16 reserved; +} __packed; + struct afe_param_id_i2s_cfg { u32 i2s_cfg_minor_version; u16 bit_width; @@ -208,6 +233,21 @@ union afe_port_config { struct afe_param_id_i2s_cfg i2s_cfg; } __packed; +struct afe_lpass_clk_config_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; + struct afe_clk_cfg clk_cfg; +} __packed; + +struct afe_lpass_digital_clk_config_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; + struct afe_digital_clk_cfg clk_cfg; +} __packed; + +/* This param id is used to configure internal clk */ struct q6afe_port { wait_queue_head_t wait; union afe_port_config port_cfg; @@ -425,6 +465,81 @@ static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data, return ret; } +static int q6afe_set_lpass_clock(struct q6afe_port *port, + struct afe_clk_cfg *cfg) +{ + struct afe_lpass_clk_config_command clk_cfg = {0}; + int param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG; + struct q6afe *afe = port->afe; + + if (!cfg) { + dev_err(afe->dev, "clock cfg is NULL\n"); + return -EINVAL; + } + + clk_cfg.clk_cfg = *cfg; + + return q6afe_port_set_param_v2(port, &clk_cfg, param_id, sizeof(*cfg)); +} + +static int q6afe_set_digital_codec_core_clock(struct q6afe_port *port, + struct afe_digital_clk_cfg *cfg) +{ + struct afe_lpass_digital_clk_config_command clk_cfg = {0}; + int param_id = AFE_PARAM_ID_INTERNAL_DIGITAL_CDC_CLK_CONFIG; + struct q6afe *afe = port->afe; + + if (!cfg) { + dev_err(afe->dev, "clock cfg is NULL\n"); + return -EINVAL; + } + + clk_cfg.clk_cfg = *cfg; + + return q6afe_port_set_param_v2(port, &clk_cfg, param_id, sizeof(*cfg)); +} + +int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id, + int clk_src, int clk_root, + unsigned int freq, int dir) +{ + struct afe_clk_cfg ccfg = {0,}; + struct afe_digital_clk_cfg dcfg = {0,}; + int ret; + + switch (clk_id) { + case LPAIF_DIG_CLK: + dcfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; + dcfg.clk_val = freq; + dcfg.clk_root = clk_root; + ret = q6afe_set_digital_codec_core_clock(port, &dcfg); + break; + case LPAIF_BIT_CLK: + ccfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; + ccfg.clk_val1 = freq; + ccfg.clk_src = clk_src; + ccfg.clk_root = clk_root; + ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK1_VALID; + ret = q6afe_set_lpass_clock(port, &ccfg); + break; + + case LPAIF_OSR_CLK: + ccfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG; + ccfg.clk_val2 = freq; + ccfg.clk_src = clk_src; + ccfg.clk_root = clk_root; + ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID; + ret = q6afe_set_lpass_clock(port, &ccfg); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +EXPORT_SYMBOL_GPL(q6afe_port_set_sysclk); + static int afe_port_start(struct q6afe_port *port, union afe_port_config *afe_config) { diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 9114d68a79cb..c469f6de38d2 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -14,6 +14,13 @@ #define AFE_MAX_CHAN_COUNT 8 #define AFE_PORT_MAX_AUDIO_CHAN_CNT 0x8 +#define Q6AFE_LPASS_CLK_SRC_INTERNAL 1 +#define Q6AFE_LPASS_CLK_ROOT_DEFAULT 0 + +#define LPAIF_DIG_CLK 1 +#define LPAIF_BIT_CLK 2 +#define LPAIF_OSR_CLK 3 + struct q6afe_hdmi_cfg { u16 datatype; u16 channel_allocation; @@ -61,4 +68,7 @@ void q6afe_slim_port_prepare(struct q6afe_port *port, struct q6afe_slim_cfg *cfg); void q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg); +int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id, + int clk_src, int clk_root, + unsigned int freq, int dir); #endif /* __Q6AFE_H__ */ From patchwork Tue Feb 13 16:58:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128273 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4459911ljc; Tue, 13 Feb 2018 09:03:39 -0800 (PST) X-Google-Smtp-Source: AH8x227NUABUfcnwbu/zseUjrwWrDxvhL9YKbfkw9OBvcM7+WYdcEloOcE1lb3OVjNlRe0ZYuKN8 X-Received: by 10.98.34.139 with SMTP id p11mr1903660pfj.119.1518541419392; Tue, 13 Feb 2018 09:03:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541419; cv=none; d=google.com; s=arc-20160816; b=yty7qlZxM723VMBa5PTMtFcKEsXSsqLK1281KnL9GYHB1hT/Xquh0Xhnxv49dNJR5R ybXlqJQcDAX8RiY+I9pc3nTdpxpSzbHvhpwieYBsbCNDRwlUwSKGRNjHIV+VFgkYgpGg Uzs9Ud9nnaA80WNoQAtouDAq7ossTzHPBiSWcSnLfutAgkDpmvtxAaq7KWDzy64KNJut +WCHfXtkpwks7PS7NhF1MqJuUrNvaEnN/KXkJbe+CQmyUnx8drdEGQhQ5T8WdE1OoqZN A+4LivfL/EBixzHAHIwJ9IIaUL2g6m20BTdg0Rdo9oxHE6PHGjDLLTcrnVa9sRekzO7J i6nw== 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=4Cif7NSMj1tJeZC9NVKtYwWyChTOSNNGYgcUkU/6x50=; b=KCvNU5XKe7j3Vg85sLI6tILuvNKLyrIha4kbfawajLS1R9APZC+UtqqrKUktkzqGsg mheu6fuFZR5+wCyueYr6ehg4rkY7c70XPr1e9z4FBTmmf06KPg985yqkez0pJB+oEqk9 QdPACgh5ZEjCCrbu30Yv7zcu/mPA9u65ZC8Sj0luCcF2oeQpfKsDmMIg1/BEdxmfhN+L leqPShroI29SCZr/FWQHOHMNKmyvCLIZsBKAp3xiOArbmrKXNYi6xElCarI9hu6Hgzjj FqsZ3r34v2poFTZBH4bGzCN0bcFnhHKrymmh7RfsgrYw6VjTxNNOj7B33D0zQk6IQhoj qPeg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kl0Io3WJ; 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 k131si1167293pgc.101.2018.02.13.09.03.39; Tue, 13 Feb 2018 09:03:39 -0800 (PST) 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=kl0Io3WJ; 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 S965395AbeBMRDf (ORCPT + 28 others); Tue, 13 Feb 2018 12:03:35 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:36780 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965497AbeBMRBo (ORCPT ); Tue, 13 Feb 2018 12:01:44 -0500 Received: by mail-wm0-f68.google.com with SMTP id f3so17294458wmc.1 for ; Tue, 13 Feb 2018 09:01:44 -0800 (PST) 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=4Cif7NSMj1tJeZC9NVKtYwWyChTOSNNGYgcUkU/6x50=; b=kl0Io3WJ6sPI5cainvDkq9Ngwge3kXpkIhTm4lcFitZaKEu0IvLOt9/i/QvPJb7Jio TYzQBQUG7izAHuRrata3+tLDRqV+T4BqDUcUu6OClu+Oq5EzrmfsuScww3uMLZQaRr5c 7uoq/1VVe0v107pL0m1/E0+3tkYD8U8GEmLW8= 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=4Cif7NSMj1tJeZC9NVKtYwWyChTOSNNGYgcUkU/6x50=; b=O74g2/1uGmjMFDVSqP4F+w/6Nt7LZPd0xBNpIboUBB9w6AFiyMckkDLwg3jTNeY6rc 8p35x9ijS47JehxkE/akkhh5IqGCeBEEEa0PuFvcZrVzDoIyh8xWSYp6NobkQoBUw2dp 9PqExHbqeAwLTgM4dwBL32VtoSqsTUn49Qex19EaKNttNYVNiccAZsIroqjei7rnQvvz DMxG9xmI3mj9Wo+rGDVFqluesPpFfzmUao2nR1cqVF3+tE5pVAa8TPsJhDi56m2Tc6Ar gerjAO2fabwG2TB8wyxomuYya1qrL+JMm+kIK/QB4JWxo8cZkapCKEH1eVAkfZwbtPYX rxTA== X-Gm-Message-State: APf1xPA9XMCuh3w6eUMmSWuy6YkhHXZsT8dWzubK2gc12v5sdEVwUu4m bSd0DmAejPRZbVcR2Ik133JQbA== X-Received: by 10.28.137.85 with SMTP id l82mr1935818wmd.109.1518541303194; Tue, 13 Feb 2018 09:01:43 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:42 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 21/25] ASoC: qcom: q6afe-dai: add support to 4 MI2S ports Date: Tue, 13 Feb 2018 16:58:33 +0000 Message-Id: <20180213165837.1620-22-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 dais supported on LPASS IP. Signed-off-by: Srinivas Kandagatla --- sound/soc/qcom/qdsp6/q6afe-dai.c | 154 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) -- 2.15.1 diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index 39badb701be0..b6db1ae654e8 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -139,6 +139,31 @@ static int q6hdmi_hw_params(struct snd_pcm_substream *substream, 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 = q6afe_get_dai_data(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); + + return 0; +} + +static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct q6afe_dai_data *dai_data = q6afe_get_dai_data(dai->dev); + struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg; + + i2s->fmt = fmt; + + return 0; +} + static int q6afe_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -163,6 +188,34 @@ static void q6afe_dai_shutdown(struct snd_pcm_substream *substream, } +static int q6afe_mi2s_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6afe_dai_data *dai_data = q6afe_get_dai_data(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\n"); + return rc; + } + } + + q6afe_i2s_port_prepare(dai_data->port[dai->id], + &dai_data->port_config[dai->id].i2s_cfg); + + 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) { @@ -224,6 +277,26 @@ static int q6slim_set_channel_map(struct snd_soc_dai *dai, 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 = q6afe_get_dai_data(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); + } + + return 0; +} + static const struct snd_soc_dapm_route q6afe_dapm_routes[] = { {"HDMI Playback", NULL, "HDMI_RX"}, {"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"}, @@ -233,6 +306,10 @@ static const struct snd_soc_dapm_route q6afe_dapm_routes[] = { {"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"}, }; static struct snd_soc_dai_ops q6hdmi_ops = { @@ -242,6 +319,15 @@ static struct snd_soc_dai_ops q6hdmi_ops = { .startup = q6afe_dai_startup, }; +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, + .startup = q6afe_dai_startup, + .set_sysclk = q6afe_mi2s_set_sysclk, +}; + static struct snd_soc_dai_ops q6slim_ops = { .prepare = q6afe_dai_prepare, .hw_params = q6slim_hw_params, @@ -422,6 +508,63 @@ static struct snd_soc_dai_driver q6afe_dais[] = { .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, + }, { + .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, + }, { + .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, + }, { + .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, }, }; @@ -452,6 +595,17 @@ static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = { 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_OUT("TERT_MI2S_RX", "Tertiary MI2S Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback", + 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), }; static const struct snd_soc_component_driver q6afe_dai_component = { From patchwork Tue Feb 13 16:58:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128265 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4457930ljc; Tue, 13 Feb 2018 09:02:05 -0800 (PST) X-Google-Smtp-Source: AH8x225wyfhlW6lrcTkYirg6z5MDBZNchbeCn39Ed4rPNS+z8EypzbHAQoAY3JrjMpB0HDwsxKLe X-Received: by 10.99.105.74 with SMTP id e71mr1525699pgc.342.1518541324903; Tue, 13 Feb 2018 09:02:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541324; cv=none; d=google.com; s=arc-20160816; b=BnDvFezAuu+p2O5Et/tgMAL0f3rIZni3bBS4G83s01+n4lzZBbpCdqO+91UEXQHwoL +BjsNzHVQgsabcBD4MB+0YSt4RZ7UNVXrIVgYGg7dO2BLR2cdtNpDxtISJNdpRU2NX6u /EHa74JQUiJgC/DMgnJR26wcQrJ44Wn9fybnKr+wM2XS9cNByPeX04tLqGVU2wnlqUna 8elXTKmqSOKPVCHFt9lYMxkDCJHwpL0eBUOwiO4a3LrnsGMRFiHoC+fGZpdy6rA+PWbU Fhj9i3G6bEpV2zmP7bsgB39DwEABCwMk31GEpIyh3lVBat6jfRU92Ua5zfkgQCqbgs7t dcMA== 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=8aAeQGSakBMD1Yfzda5ic+gh1tQCzFgU1wdmbqROgPY=; b=Shpb5xlvNDvwDiPrVwK/qRIjzfCT+9vWiNTYEPnt3NVaVkhkpz/5afxlToDq/spOIB wIJHsKakzdCwx4mwe7Z6DFdYwJfrjgU1Up2Ulb+81zlAw4dd/Iay36AsbtCUkBO4WwSc KRqT3tYQCbVljLWd5OeGNt3MDRvnXL1kGpO6OAAh3wSKxpGinYtmexvoA4f9NWi0WHUz 9cW7r8GtANs0Ugu/cdXXhMslyW9MolS21Jhg3050LZ6Pc1NbbbaP90p1DymXsf4KhaCi 2HF/hk7B4RgMWST2taB1E6tn//RzxAywXIPUX8vjqrk9DXGDTvrEIUu9fPeZ8lKlO/DL 2OtQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Zz8F9f1W; 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 bc11-v6si7528083plb.688.2018.02.13.09.02.04; Tue, 13 Feb 2018 09:02:04 -0800 (PST) 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=Zz8F9f1W; 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 S965545AbeBMRCA (ORCPT + 28 others); Tue, 13 Feb 2018 12:02:00 -0500 Received: from mail-wm0-f67.google.com ([74.125.82.67]:55589 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965521AbeBMRBq (ORCPT ); Tue, 13 Feb 2018 12:01:46 -0500 Received: by mail-wm0-f67.google.com with SMTP id a84so6052161wmi.5 for ; Tue, 13 Feb 2018 09:01:46 -0800 (PST) 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=8aAeQGSakBMD1Yfzda5ic+gh1tQCzFgU1wdmbqROgPY=; b=Zz8F9f1Waq/kPBv8PO/qtPMIQnwUko0FKkLY/8q8lmLl++l/WrPbVHhqDbXRNpEUpP whjF6fMCDvrmsGUIo7sa2XcMW1MdSoR+2B5DpUgBDg3z3Fs+qgkvgITgYiTmjndKQVCj q1Yg4leZNXCSBcUIndfzd4PSEw5a/m0ohHuyI= 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=8aAeQGSakBMD1Yfzda5ic+gh1tQCzFgU1wdmbqROgPY=; b=F/owpJDVRlqK/iTPwTAFK15o3T5/lKCVAfWq1/GWLmDHQhbqvx8E/NFD/q8G3//nw3 REuuilcbdbGJBny5TqMu40gRia6k/1/t6VbOC3APCBDB9RlkjBt+dTtw1aFmI7kEBXch YzjKn5RvP1x55/gga5HjA0p1OrOHK9D25vyUXMoKH9v+Bxp9/rmuLnxEIqZ8C7Zjmh1x 8sooQttO4J68b7W5PbOESlqroiGylAwTN5XbYvm1cD4ifP8I8W5llKk/WSb/1110jdOU Mr7SiOKCDUPvtQNLK/epnRvshzvvw8wIzFfoHdD/SYsWlNnJqfyu31P2sJJa0MHTjuBD Kg8Q== X-Gm-Message-State: APf1xPC8PJ8CJYTgEa8I3rAgHA+YtIcmtk24ICtIYEMK7t3j5SPnRasP 1jr7Np4gAGkpLIiksTAOipcOdQ== X-Received: by 10.28.249.22 with SMTP id x22mr1754400wmh.135.1518541305723; Tue, 13 Feb 2018 09:01:45 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:45 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 23/25] dt-bindings: sound: qcom: Add devicetree bindings for apq8096 Date: Tue, 13 Feb 2018 16:58:35 +0000 Message-Id: <20180213165837.1620-24-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 devicetree bindings documentation file for Qualcomm apq8096 sound card. Signed-off-by: Srinivas Kandagatla --- .../devicetree/bindings/sound/qcom,apq8096.txt | 89 ++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,apq8096.txt -- 2.15.1 diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8096.txt b/Documentation/devicetree/bindings/sound/qcom,apq8096.txt new file mode 100644 index 000000000000..58cd506477c0 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,apq8096.txt @@ -0,0 +1,89 @@ +* Qualcomm Technologies APQ8096 ASoC sound card driver + +This binding describes the APQ8096 sound card, which uses qdsp for audio. + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,apq8096-sndcard" + +- qcom,audio-routing: + Usage: Optional + Value type: + Definition: A list of the connections between audio components. + Each entry is a pair of strings, the first being the + connection's sink, the second being the connection's + source. Valid names could be power supplies, MicBias + of codec and the jacks on the board: + += FRONTEND and BACKEND dailinks +Each subnode of sndcard represents either frontend or backend dailink, +and subnodes of each backend/frontend dailinks would be +cpu/codec/platform dais. + +- link-name: + Usage: required + Value type: + Definition: User friendly name for dai link + +- is-fe: + Usage: optional + Value type: + Definition: present if the dailink is frontend + + += CPU, PLATFORM, CODEC dais subnodes +- cpu: + Usage: required + Value type: + Definition: cpu dai sub-node + +- codec: + Usage: required + Value type: + Definition: codec dai sub-node + +- platform: + Usage: opional + Value type: + Definition: platform dai sub-node + +- sound-dai: + Usage: required + Value type: + Definition: dai phandle/s and port of CPU/CODEC/PLATFORM node. + +Example: + +audio { + compatible = "qcom,apq8096-sndcard"; + qcom,model = "DB820c"; + qcom,audio-routing = + "RX_BIAS", "MCLK"; + + fedai1 { + is-fe; + link-name = "MultiMedia1 Playback"; + cpu { + sound-dai = <&q6asm MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + platform { + sound-dai = <&q6asm MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + }; + + bedai1 { + link-name = "HDMI Playback"; + cpu { + sound-dai = <&q6afe AFE_PORT_HDMI_RX>; + }; + + platform { + sound-dai = <&q6adm>; + }; + + codec { + sound-dai = <&hdmi 0>; + }; + }; +}; From patchwork Tue Feb 13 16:58:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 128267 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4458417ljc; Tue, 13 Feb 2018 09:02:27 -0800 (PST) X-Google-Smtp-Source: AH8x2244+i/6+LBtHpdsNx+7B5Fkk7g/oDyVyVo0HRiPjJhe4X18uWh/0Q7xvYjxtM/tlT5tSmFp X-Received: by 2002:a17:902:d68a:: with SMTP id v10-v6mr1707158ply.206.1518541347249; Tue, 13 Feb 2018 09:02:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541347; cv=none; d=google.com; s=arc-20160816; b=VzsyKGnJNFq4X2bVeRm0a2AH727SbBgl1rCEmhlj++g2FoTq9HV1DhUFjwSu438GsX OcRAsHLM03RtaV1JlrmASTdYURQmQUFq8IC/TVLeWC6Fk1hzc3MkbKZajuz/jjkdpTmM xXn1Ss0eJlpsVV5zcro8Vm93XmRCm+d3OnviI35JhozKZ+aeO7QBydDUs4x80NQawsYE diX2QwiUniHfc7yruJ0AyFSpM882FSUNuy8JVPJIhZaPdQcPQXF4UuBNeridNlbFqvx6 Mbl5fGxyhBWfJsAtiIeR1WpgAAeLcmaZYac31BbzySqApNX23ejrQdnB1OY5tr0d8oiN wKww== 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=4gSyMnZu0jAokTqfgezSMJZSoMNWyk9PtERXGo4ALSY=; b=BS3h8RqWU4AZT1LZ5HmkuTISc1XmI+Qz4M09FuZLIx1KJQ3W7F6BsMsFbYXWN5eWGS +M1FCHGk83SHX43+IScR1uzx7mqdopehQuGS18qoq0APlJVgC4B+BkydURJT/c/3Yubk yIQWcC5w9GPhaCRrJBRR0nRmAY5+ugn/TG4y76Zz8NJ5Kandmzinuh5E8jMUQRUdO1I2 qPGgIKUxVn4lAw5+GfAUvISgD3aY7mwBUdtMt0VdhF9aDudGZc04TJPOJTs1jSeILjQt JXcKJDYp9oKsOt+3pymfIjhHCcnOieQNndsW9zP0EvLE3NRLuotufQ7LjFUQua901xB9 2HwQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BYy+aPgu; 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 z5si1403465pgo.514.2018.02.13.09.02.26; Tue, 13 Feb 2018 09:02:27 -0800 (PST) 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=BYy+aPgu; 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 S965554AbeBMRCY (ORCPT + 28 others); Tue, 13 Feb 2018 12:02:24 -0500 Received: from mail-wm0-f66.google.com ([74.125.82.66]:39834 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965534AbeBMRBs (ORCPT ); Tue, 13 Feb 2018 12:01:48 -0500 Received: by mail-wm0-f66.google.com with SMTP id b21so17276170wme.4 for ; Tue, 13 Feb 2018 09:01:48 -0800 (PST) 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=4gSyMnZu0jAokTqfgezSMJZSoMNWyk9PtERXGo4ALSY=; b=BYy+aPguNwQl15SwsGsTzTsHZbTIqxH/9b6plpAXipn6cR1hBTPE+UuNN4PSxZ05bw xW67ac2uTwluyKlvGgYbhtFso3n36NYbcJp+c595YAVmd6bdM2dsnYtI86GgT0nIX+Ap MFEzuWbRJ7Jid47J+YHY/CdKAml9q13h35Pdg= 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=4gSyMnZu0jAokTqfgezSMJZSoMNWyk9PtERXGo4ALSY=; b=pKiWG29XP1pahVSK9Dz68L7DvThcViHjWTCeU49XxKaRWLgc7Cd2Vujg9OFrLwIQ4L 4X2/DId80YdIIribcSDIwCtLFVZGAnPXWN6ZCK3ETVTFyssvfUW1lV2xZLzM/fIci+Oq UNUZ4DIHbWur2LNgiY1P7CKqaWCIeeTipINLDgZ+XbwQyNGcajCLCMhyjqglhE6LJIyM 2Kni2y0PhLyfreLYEMqvx5bT/QlorPalnQ1qRSZzUWp5IeGOnPJKQlyeQLKJwsTznFwg mr9+Bqvi5uVJdfMTT5dQlowP3d8H+Y40d9xv4HgVz5+6kKaVuAF4Yknw7dKB7zVctDOi LvPg== X-Gm-Message-State: APf1xPBK1/e8pSo58fYFJ0vVvcSZdKBqe+Vy7DUVXYNNbvCxGStjivfs T9WFqsTe36wVlrA/7Tok0bglbg== X-Received: by 10.28.110.3 with SMTP id j3mr2024042wmc.97.1518541306929; Tue, 13 Feb 2018 09:01:46 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:46 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 24/25] ASoC: qcom: apq8096: Add db820c machine driver Date: Tue, 13 Feb 2018 16:58:36 +0000 Message-Id: <20180213165837.1620-25-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 DB820c machine driver. Signed-off-by: Srinivas Kandagatla --- sound/soc/qcom/Kconfig | 8 +++ sound/soc/qcom/apq8096.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 sound/soc/qcom/apq8096.c -- 2.15.1 diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 8c2d65e0a28e..fa4b575c086c 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -77,3 +77,11 @@ config SND_SOC_QDSP6 This will enable sound soc platform specific audio drivers. This includes q6asm, q6adm, q6afe interfaces to DSP using apr. + +config SND_SOC_MSM8996 + tristate "SoC Machine driver for MSM8996 and APQ8096 boards" + depends on QCOM_APR + select SND_SOC_QDSP6V2 + default n + help + To add support for SoC audio on MSM8996 and APQ8096 boards diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c new file mode 100644 index 000000000000..b12d2398557a --- /dev/null +++ b/sound/soc/qcom/apq8096.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +static int msm8996_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + return 0; +} + +static int apq8096_sbc_parse_of(struct snd_soc_card *card) +{ + struct device *dev = card->dev; + struct snd_soc_dai_link *link; + struct device_node *np, *codec, *platform, *cpu, *node = dev->of_node; + int ret, num_links; + bool is_fe; + + + ret = snd_soc_of_parse_card_name(card, "qcom,model"); + if (ret) + dev_err(dev, "Error parsing card name: %d\n", ret); + + if (of_property_read_bool(dev->of_node, "qcom,audio-routing")) + ret = snd_soc_of_parse_audio_routing(card, + "qcom,audio-routing"); + + /* Populate links */ + num_links = of_get_child_count(node); + + dev_info(dev, "Found %d child audio dai links..\n", num_links); + /* Allocate the private data and the DAI link array */ + card->dai_link = devm_kzalloc(dev, sizeof(*link) * num_links, + GFP_KERNEL); + if (!card->dai_link) + return -ENOMEM; + + card->num_links = num_links; + + link = card->dai_link; + + for_each_child_of_node(node, np) { + is_fe = false; + if (of_property_read_bool(np, "is-fe")) + is_fe = true; + + if (is_fe) { + /* BE is dummy */ + link->codec_of_node = NULL; + link->codec_dai_name = "snd-soc-dummy-dai"; + link->codec_name = "snd-soc-dummy"; + + /* FE settings */ + link->dynamic = 1; + link->dpcm_playback = 1; + + } else { + link->no_pcm = 1; + link->dpcm_playback = 1; + link->ignore_suspend = 1; + link->ignore_pmdown_time = 1; + link->be_hw_params_fixup = msm8996_be_hw_params_fixup; + } + + cpu = of_get_child_by_name(np, "cpu"); + platform = of_get_child_by_name(np, "platform"); + codec = of_get_child_by_name(np, "codec"); + + if (!cpu) { + dev_err(dev, "Can't find cpu DT node\n"); + return -EINVAL; + } + + link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); + if (!link->cpu_of_node) { + dev_err(card->dev, "error getting cpu phandle\n"); + return -EINVAL; + } + + link->platform_of_node = of_parse_phandle(platform, + "sound-dai", 0); + if (!link->platform_of_node) { + dev_err(card->dev, "error getting platform phandle\n"); + return -EINVAL; + } + + ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); + if (ret) { + dev_err(card->dev, "error getting cpu dai name\n"); + return ret; + } + + if (codec) { + ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); + + if (ret < 0) { + dev_err(card->dev, "error getting codec dai name\n"); + return ret; + } + } + + ret = of_property_read_string(np, "link-name", &link->name); + if (ret) { + dev_err(card->dev, "error getting codec dai_link name\n"); + return ret; + } + + link->stream_name = link->name; + link++; + } + + return ret; +} + +static int msm_snd_apq8096_probe(struct apr_device *adev) +{ + int ret; + struct snd_soc_card *card; + + card = devm_kzalloc(&adev->dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->dev = &adev->dev; + + ret = apq8096_sbc_parse_of(card); + if (ret) { + dev_err(&adev->dev, "Error parsing OF data\n"); + return ret; + } + + ret = devm_snd_soc_register_card(&adev->dev, card); + if (ret) + dev_err(&adev->dev, "sound card register failed (%d)!\n", ret); + else + dev_err(&adev->dev, "sound card register Sucessfull\n"); + + return ret; +} + +static const struct of_device_id msm_snd_apq8096_dt_match[] = { + {.compatible = "qcom,apq8096-sndcard"}, + {} +}; + +static struct apr_driver msm_snd_apq8096_driver = { + .probe = msm_snd_apq8096_probe, + .driver = { + .name = "msm-snd-apq8096", + .owner = THIS_MODULE, + .of_match_table = msm_snd_apq8096_dt_match, + }, +}; +module_apr_driver(msm_snd_apq8096_driver); +MODULE_AUTHOR("Srinivas Kandagatla X-Patchwork-Id: 128269 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp4459127ljc; Tue, 13 Feb 2018 09:02:59 -0800 (PST) X-Google-Smtp-Source: AH8x225PRcVCujbN9pY1v/iFvuBgdj8O12CzEAAEOoIm46AJNrqYEiEmDvnu6zN9kFXDf7FTLTpM X-Received: by 10.99.113.11 with SMTP id m11mr1509022pgc.57.1518541379552; Tue, 13 Feb 2018 09:02:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518541379; cv=none; d=google.com; s=arc-20160816; b=WwZUcRHmk+R7sOQwgo1t13Hg+QTE6KCsOR2yawiwnOc/Pb4mMOCBS9o2/g4A4RJKkw n7kt+X6Xci9mbObpyacZmebCFGJ3DXh/eK+zYWK3M+nMu80D/Gif8zJqsWOo4z4g16Bd NgfnTZqD++qnSWBIH5+vjdCJkBbixiWPt+ykefEQ1AwzgmU/AxJF3MtXRGg2yvWS6ar6 ge5AHYvgb3yU9WxnZxlTdB0oq7fdKEW1PtnEGYgmhu3r71Lci2sOCYMDIZ/bkuMckZsR ApMdS4BOKWvfcfGBB0ufaIpDtVzsSInGdr688y+YiykIWGAthRsSHgbtrqAHKu08FlGN 4zxw== 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=CQdpazCSHoVUUwqGM9fnZ88nd+tej68/aeXmfDC3h8s=; b=WadqxsIpcOv5o28ZB1zskdsnuYg3rU6EoWwARf2ECABPGiCvB7TCulwat+Q5q5FxMJ wyLMvRKBesabBeItA/bo2k+XalQBFUat/FMyVhKmVo8+jxaQpjvSFxBr1dMWyEgqXIQC cp3ehCdSc0bi2KlhG2kh3E/JrU8dlPIdUSLt2l8G7ASxqyeT1P7dm0RhXzs66d34zgl7 5ESM5zwUQSAXemCNcB0cqKcuIZJuvAfkiRWzCAreXNOqTMB3oFbIghjSrrL0+EyZUvox qvMznvYnJc5udh0DGJl60LEDohNZpJNLVWkJb6JXv9zCszoSTPkTsp6fYSGDolyHnCCH 8sgg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=iubqN9hK; 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 59-v6si1832586pla.203.2018.02.13.09.02.59; Tue, 13 Feb 2018 09:02:59 -0800 (PST) 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=iubqN9hK; 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 S965335AbeBMRCX (ORCPT + 28 others); Tue, 13 Feb 2018 12:02:23 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:36798 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965535AbeBMRBu (ORCPT ); Tue, 13 Feb 2018 12:01:50 -0500 Received: by mail-wm0-f68.google.com with SMTP id f3so17295095wmc.1 for ; Tue, 13 Feb 2018 09:01:49 -0800 (PST) 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=CQdpazCSHoVUUwqGM9fnZ88nd+tej68/aeXmfDC3h8s=; b=iubqN9hKNB+fatP1urFTYEa9Dz7Z+qT8Ya6J5pF3NDWRc/kyO9hLFpiZ0WxTquT2Va PFCSRZU1vDpg1Dmg0laDcufTq+a/WQR25INnlYjfg+nODs0zIx/qXHe7PWXY4wHDjC1p WQj4TUub974x0gKQxe98arYp6u3KMDdzYBWJc= 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=CQdpazCSHoVUUwqGM9fnZ88nd+tej68/aeXmfDC3h8s=; b=BrFetJeTZwFFjZvfHztXkvv9j+Z1eohdeol1E4FkbQAayn7aUted2skyn7VTQazyPT 2HYKnsQeuxGTHpoE2MCtXEGV9oRM+63bRrArwUl37evhNJBGzBrq3B7an439mHZYg4vM aKoVw8pdL8sFkVysIFNdfRL/L4YR8+HL65b+pnR7E8dKyGliTsZ2hIB6SGLLhqgZkwn4 Ay0Oq4RYwjii/s9z3iwyn1a4qcB5G5xbFLJMqSQ62UM8+1raNOa/E0Qwqy7KQVAsdetq toXZSQL+2Yg/K57AA1G7OZvnAgMTyHufw+sdjJQ7KD3NxZpH01AX3/aak8p/EescQcyG Ni0Q== X-Gm-Message-State: APf1xPB6dUvULiJufIqaX0eydiMSN7J28iH1QdwkOiupglmcQJsftIOj udUaob45KtULThlFoO+IbMHjEg== X-Received: by 10.28.5.10 with SMTP id 10mr1866413wmf.126.1518541308319; Tue, 13 Feb 2018 09:01:48 -0800 (PST) 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 y145sm7432723wmd.43.2018.02.13.09.01.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Feb 2018 09:01:47 -0800 (PST) From: srinivas.kandagatla@linaro.org To: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org Cc: david.brown@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, bgoswami@codeaurora.org, perex@perex.cz, tiwai@suse.com, linux-soc@vger.kernel.org, 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 v3 25/25] arm64: dts: msm8996: db820c: Add sound card support Date: Tue, 13 Feb 2018 16:58:37 +0000 Message-Id: <20180213165837.1620-26-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180213165837.1620-1-srinivas.kandagatla@linaro.org> References: <20180213165837.1620-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 hdmi sound card support to db820c via qdsp. Signed-off-by: Srinivas Kandagatla --- arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi | 44 +++++++++++++++++++- arch/arm64/boot/dts/qcom/msm8996.dtsi | 62 ++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) -- 2.15.1 diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi index 9769053957af..6f6f21501ee9 100644 --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi @@ -18,7 +18,8 @@ #include "apq8096-db820c-pmic-pins.dtsi" #include #include - +#include +#include / { aliases { serial0 = &blsp2_uart1; @@ -186,6 +187,7 @@ core-vdda-supply = <&pm8994_l12>; core-vcc-supply = <&pm8994_s4>; + #sound-dai-cells = <1>; }; }; }; @@ -360,4 +362,44 @@ }; }; }; + adsp-pil { + power-domains = <&gcc HLOS1_VOTE_LPASS_ADSP_GDSC>; + smd-edge { + apr { + iommus = <&lpass_q6_smmu 1>; + audio { + compatible = "qcom,apq8096-sndcard"; + qcom,model = "DB820c"; + qcom,audio-routing = + "RX_BIAS", "MCLK"; + + fe@1 { + is-fe; + link-name = "MultiMedia1 Playback"; + cpu { + sound-dai = <&q6asm MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + platform { + sound-dai = <&q6asm MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + }; + + be@1 { + link-name = "HDMI Playback"; + cpu { + sound-dai = <&q6afe AFE_PORT_HDMI_RX>; + }; + + platform { + sound-dai = <&q6adm>; + }; + + codec { + sound-dai = <&hdmi 0>; + }; + }; + }; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index c93bbae645bd..75cb055b0c55 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -14,6 +14,7 @@ #include #include #include +#include / { model = "Qualcomm Technologies, Inc. MSM8996"; @@ -1287,6 +1288,34 @@ "ref_clk"; }; }; + + lpass_q6_smmu: arm,smmu-lpass_q6@1600000 { + compatible = "qcom,msm8996-smmu-v2"; + reg = <0x1600000 0x20000>; + #iommu-cells = <1>; + power-domains = <&gcc HLOS1_VOTE_LPASS_CORE_GDSC>; + + #global-interrupts = <1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + ; + + clocks = <&gcc GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK>, + <&gcc GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK>; + clock-names = "iface", "bus"; + status = "okay"; + }; + }; adsp-pil { @@ -1315,6 +1344,39 @@ qcom,ipc = <&apcs 16 8>; qcom,smd-edge = <1>; qcom,remote-pid = <2>; + apr { + compatible = "qcom,apr-v2"; + qcom,smd-channels = "apr_audio_svc"; + qcom,apr-dest-domain-id = ; + + q6core { + qcom,apr-svc-name = "CORE"; + qcom,apr-svc-id = ; + compatible = "qcom,q6core"; + }; + + q6afe: q6afe { + compatible = "qcom,q6afe"; + qcom,apr-svc-name = "AFE"; + qcom,apr-svc-id = ; + #sound-dai-cells = <1>; + }; + + q6asm: q6asm { + compatible = "qcom,q6asm"; + qcom,apr-svc-name = "ASM"; + qcom,apr-svc-id = ; + #sound-dai-cells = <1>; + }; + + q6adm: q6adm { + compatible = "qcom,q6adm"; + qcom,apr-svc-name = "ADM"; + qcom,apr-svc-id = ; + #sound-dai-cells = <0>; + }; + + }; }; };