From patchwork Wed Mar 9 20:40:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550548 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7ACFBC433F5 for ; Wed, 9 Mar 2022 20:31:37 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id BFB6F16F8; Wed, 9 Mar 2022 21:30:45 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz BFB6F16F8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646857895; bh=X4E26zBkroNegIzEIjaPSfcHUNmeq2dapb2aZCcX6lA=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=sp6L6CEVCyJZ4h7LXdUo+suE5gR+3QASju0Lmr/oO+nVUH4enjCjSPzWjluss7+hR C4M50tRTt6krgkUF7JBXOH7+B+uQ/NdwmBabvX7wENahrgvVikWOJ3iwuUka4FBWqE aAMG9EF54hmWnMRwobM/I870r0Hy6WCC0zsA1+fQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 280BBF804BB; Wed, 9 Mar 2022 21:30:12 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 61B6BF8012F; Wed, 9 Mar 2022 21:30:09 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 43236F80155 for ; Wed, 9 Mar 2022 21:30:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 43236F80155 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="lB5fPVPl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857802; x=1678393802; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=X4E26zBkroNegIzEIjaPSfcHUNmeq2dapb2aZCcX6lA=; b=lB5fPVPlm5/UOW1ylHmedztJluND9tiU9wYZvTO6TfIyBMQg0pWXGRHQ Dn4jg4CU66KC8RN4yDP3oQe6h1pFp/cTLWKlS7g8KqGXTNgGxef5PFl6S q9hsi3AO/K5TKHZCRbXDbsv+CIlFofsjUDwuw5Adzp+grzIS6frU75G6X s+n4W4Z8gdf700mqz3BxDA0sT8MU6PQTfHpH+6uZ1kcOmmpfZeT+K8OEM bi7YzDEwXGQEx7SmrNiGlB3kFZdnIq3b1J3l08cK4jFxcz0WSnqge4N2x II2NFzR5/OtLmouG1KaUkkEVba8J1Sakya4EQptzWd49jv725YzeVstaf Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028659" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028659" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:29:58 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578526920" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:29:55 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 01/17] ALSA: hda: Add helper macros for DSP capable devices Date: Wed, 9 Mar 2022 21:40:13 +0100 Message-Id: <20220309204029.89040-2-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" HDAudio drivers make heavy use of I/O operations. Declare a range of update, read and write helpers similar to those available for HDAudio legacy driver. These macros are used by AVS driver to improve code readability. Signed-off-by: Cezary Rojewski --- include/sound/hdaudio.h | 2 ++ include/sound/hdaudio_ext.h | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 6a90ce405e60..69907260b9ce 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -448,6 +448,8 @@ static inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr) #define snd_hdac_reg_writel(bus, addr, val) writel(val, addr) #define snd_hdac_reg_readl(bus, addr) readl(addr) +#define snd_hdac_reg_writeq(bus, addr, val) writeq(val, addr) +#define snd_hdac_reg_readq(bus, addr) readq(addr) /* * macros for easy use diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index b0c8e4936168..d26234f9ee46 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -2,6 +2,8 @@ #ifndef __SOUND_HDAUDIO_EXT_H #define __SOUND_HDAUDIO_EXT_H +#include +#include #include int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, @@ -144,6 +146,54 @@ void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable); writew(((readw(addr + reg) & ~(mask)) | (val)), \ addr + reg) +#define snd_hdac_adsp_writeb(chip, reg, value) \ + snd_hdac_reg_writeb(chip, (chip)->dsp_ba + (reg), value) +#define snd_hdac_adsp_readb(chip, reg) \ + snd_hdac_reg_readb(chip, (chip)->dsp_ba + (reg)) +#define snd_hdac_adsp_writew(chip, reg, value) \ + snd_hdac_reg_writew(chip, (chip)->dsp_ba + (reg), value) +#define snd_hdac_adsp_readw(chip, reg) \ + snd_hdac_reg_readw(chip, (chip)->dsp_ba + (reg)) +#define snd_hdac_adsp_writel(chip, reg, value) \ + snd_hdac_reg_writel(chip, (chip)->dsp_ba + (reg), value) +#define snd_hdac_adsp_readl(chip, reg) \ + snd_hdac_reg_readl(chip, (chip)->dsp_ba + (reg)) +#define snd_hdac_adsp_writeq(chip, reg, value) \ + snd_hdac_reg_writeq(chip, (chip)->dsp_ba + (reg), value) +#define snd_hdac_adsp_readq(chip, reg) \ + snd_hdac_reg_readq(chip, (chip)->dsp_ba + (reg)) + +#define snd_hdac_adsp_updateb(chip, reg, mask, val) \ + snd_hdac_adsp_writeb(chip, reg, \ + (snd_hdac_adsp_readb(chip, reg) & ~(mask)) | (val)) +#define snd_hdac_adsp_updatew(chip, reg, mask, val) \ + snd_hdac_adsp_writew(chip, reg, \ + (snd_hdac_adsp_readw(chip, reg) & ~(mask)) | (val)) +#define snd_hdac_adsp_updatel(chip, reg, mask, val) \ + snd_hdac_adsp_writel(chip, reg, \ + (snd_hdac_adsp_readl(chip, reg) & ~(mask)) | (val)) +#define snd_hdac_adsp_updateq(chip, reg, mask, val) \ + snd_hdac_adsp_writeq(chip, reg, \ + (snd_hdac_adsp_readq(chip, reg) & ~(mask)) | (val)) + +#define snd_hdac_adsp_readb_poll(chip, reg, val, cond, delay_us, timeout_us) \ + readb_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ + delay_us, timeout_us) +#define snd_hdac_adsp_readw_poll(chip, reg, val, cond, delay_us, timeout_us) \ + readw_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ + delay_us, timeout_us) +#define snd_hdac_adsp_readl_poll(chip, reg, val, cond, delay_us, timeout_us) \ + readl_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ + delay_us, timeout_us) +#define snd_hdac_adsp_readq_poll(chip, reg, val, cond, delay_us, timeout_us) \ + readq_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ + delay_us, timeout_us) +#define snd_hdac_stream_readb_poll(strm, reg, val, cond, delay_us, timeout_us) \ + readb_poll_timeout((strm)->sd_addr + AZX_REG_ ## reg, val, cond, \ + delay_us, timeout_us) +#define snd_hdac_stream_readl_poll(strm, reg, val, cond, delay_us, timeout_us) \ + readl_poll_timeout((strm)->sd_addr + AZX_REG_ ## reg, val, cond, \ + delay_us, timeout_us) struct hdac_ext_device; From patchwork Wed Mar 9 20:40:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 549721 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6DBDDC433F5 for ; Wed, 9 Mar 2022 20:31:54 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 8BFB5173C; Wed, 9 Mar 2022 21:31:02 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 8BFB5173C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646857912; bh=ynmj/SGSLNPS1Axn7evAupAXAYelD/M4rNbpGZupXHM=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=HwfZHwgKNhz+gvgYeRXg3Kv2ks3XWLtN5yJp2y8ZG6DNKT82m5HTafMZ4nU723xxI uM50DmBEoFYBRFjUa9likX/LelV5K52BCDm/tVv3G83uLC/H86nv25bDmN8L/Wz8md MqYuDReAZh7CxANf3or5oOgnzSyvEIzLcz1wek3I= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id CDF6BF800D2; Wed, 9 Mar 2022 21:30:15 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 4C09AF80517; Wed, 9 Mar 2022 21:30:14 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 9198BF800D2 for ; Wed, 9 Mar 2022 21:30:03 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 9198BF800D2 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Qruwpnup" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857804; x=1678393804; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ynmj/SGSLNPS1Axn7evAupAXAYelD/M4rNbpGZupXHM=; b=QruwpnupP41EVnkcy/OmCUQjOHj4MRnMbKnnN+XFtUvUBCHTpeg7KcYC fGh6bdYsM70SBWZuu5fVBjyoN1F2YU8F3KBGcvC0j3OqIlpAMpBsjzvJ+ M5jSJaUVtD+pCf9RcmGw6rjzZ2ThelboX+4cgRhl9PPjnkDHXgYFORp+N NxsmT04DbgTmyBd8puFLCPok4N1VGPKpApWxzZCvxjRSEwKAAWGhG03jb oDwQvihj3Vw97tBaD7j8ZFgNJZVY44WnC6pve1Zbf/Q+hTD3GXwneyK+M VPnZmWrtvj9paw6MA2EqmUfiRL/EXeuiuAkdzZQsar4yVI4Ogn3B6T9dN Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028666" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028666" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:01 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578526949" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:29:58 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 02/17] ASoC: Export DAI register and widget ctor and dctor functions Date: Wed, 9 Mar 2022 21:40:14 +0100 Message-Id: <20220309204029.89040-3-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" To allow for more flexibility i.e. populating component DAIs dynamically during its initialization, without being limited to topology loading procedure, expose snd_soc_register(), snd_soc_dapm_new_dai_widgets() and snd_soc_dapm_free_widget() functions. Allows users to first check available resources e.g. number of PCMs supported by HDAudio codec before allocating the number of DAPM widgets needed. This prevents superfluous objects from being created or allows driver to adjust to situation when resources are limited. Signed-off-by: Cezary Rojewski --- include/sound/soc-dapm.h | 1 + sound/soc/soc-core.c | 1 + sound/soc/soc-dapm.c | 15 +++++++++++++++ 3 files changed, 17 insertions(+) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c3039e97929a..ebb8e7a7fc29 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -429,6 +429,7 @@ struct snd_soc_dapm_widget *snd_soc_dapm_new_control_unlocked( const struct snd_soc_dapm_widget *widget); int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, struct snd_soc_dai *dai); +void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w); int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 259429526c84..1f0564ed3a75 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2465,6 +2465,7 @@ struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); return dai; } +EXPORT_SYMBOL_GPL(snd_soc_register_dai); /** * snd_soc_unregister_dais - Unregister DAIs from the ASoC core diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b06c5682445c..b435b5c4cfb7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2484,6 +2484,12 @@ static void dapm_free_path(struct snd_soc_dapm_path *path) kfree(path); } +/** + * snd_soc_dapm_free_widget - Free specified widget + * @w: widget to free + * + * Removes widget from all paths and frees memory occupied by it. + */ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w) { struct snd_soc_dapm_path *p, *next_p; @@ -2506,6 +2512,7 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w) kfree_const(w->sname); kfree(w); } +EXPORT_SYMBOL_GPL(snd_soc_dapm_free_widget); void snd_soc_dapm_reset_cache(struct snd_soc_dapm_context *dapm) { @@ -4208,6 +4215,13 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, return ERR_PTR(ret); } +/** + * snd_soc_dapm_new_dai_widgets - Create new DAPM widgets + * @dapm: DAPM context + * @dai: parent DAI + * + * Returns 0 on success, error code otherwise. + */ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, struct snd_soc_dai *dai) { @@ -4253,6 +4267,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, return 0; } +EXPORT_SYMBOL_GPL(snd_soc_dapm_new_dai_widgets); int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card) { From patchwork Wed Mar 9 20:40:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550547 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EF041C433EF for ; Wed, 9 Mar 2022 20:32:10 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id E1C3617C1; Wed, 9 Mar 2022 21:31:18 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz E1C3617C1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646857929; bh=JH92R827n/CVp3RUBGl1lJTPFcjU3MsIaHb5C8lNuv4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=CHVc8CO4D1VcgGn+DtnacxBVjBccOdK1OR90wrvRkdVistCCRuCFNg8Wf7SvfaKmo 0zAicG2WELGkhmAdbLuIIEvjoNJOcEv9vhJEkDDkxd71qZLDqTpeFwL9+CR7JDIlbC zK4AgYJci3eD6m7GanTpn9q50URGm7GRvO5ybOYQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id BBA04F8051A; Wed, 9 Mar 2022 21:30:17 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id A409DF80517; Wed, 9 Mar 2022 21:30:15 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 213ABF80236 for ; Wed, 9 Mar 2022 21:30:07 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 213ABF80236 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="IhZHLo0p" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857809; x=1678393809; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JH92R827n/CVp3RUBGl1lJTPFcjU3MsIaHb5C8lNuv4=; b=IhZHLo0pKb2JRWywtjzMgF5xDcSfHWFkkeKUmC9r5s5xFg8HZgEw9CKQ YiXnaNIYdoRwApo/UDF+MBcTlseyCWmaFwykwvsGCPFebGXGqwMXozCAB qnN72i3qI6sV0/VcpkDKRUwfwj2ksNBmLfmR6yZ8R/ulSDHAlRJkmnIXm v/OFg63bAJbUXUVQgApjzgAOnJHRq6cxCZuJOfRCmltAkEUijM8paGMpb oh0taL5khHuq+bAOUTSt9RxyirUY3WRax+Lsl+xDpbvX/jFHZbbDid2n2 517pn1O+KiMgFIU/eBKFJdTdC/vaZ0xltHegBhKjMfwSOjQR+behtIcnq A==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028683" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028683" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:05 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578526991" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:02 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 03/17] ASoC: Intel: Introduce AVS driver Date: Wed, 9 Mar 2022 21:40:15 +0100 Message-Id: <20220309204029.89040-4-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Declare base structures and core DSP operations for the avs solution. The base structures describe PCI HDAudio bus device and platform-type differentiations. First set of operations added controls the lifecycle of any Audio DSP core: (un)powering, (un)resetting and (un)stalling. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/Kconfig | 11 ++++ sound/soc/intel/Makefile | 1 + sound/soc/intel/avs/Makefile | 5 ++ sound/soc/intel/avs/avs.h | 71 +++++++++++++++++++++ sound/soc/intel/avs/dsp.c | 107 ++++++++++++++++++++++++++++++++ sound/soc/intel/avs/registers.h | 22 +++++++ 6 files changed, 217 insertions(+) create mode 100644 sound/soc/intel/avs/Makefile create mode 100644 sound/soc/intel/avs/avs.h create mode 100644 sound/soc/intel/avs/dsp.c create mode 100644 sound/soc/intel/avs/registers.h diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index f3a4a907b29d..e9768c4aa1a9 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -209,5 +209,16 @@ config SND_SOC_INTEL_KEEMBAY If you have a Intel Keembay platform then enable this option by saying Y or m. +config SND_SOC_INTEL_AVS + tristate "Intel AVS driver" + depends on PCI && ACPI + depends on COMMON_CLK + select SND_SOC_ACPI + select SND_HDA_EXT_CORE + help + Enable support for Intel(R) cAVS 1.5 platforms with DSP + capabilities. This includes Skylake, Kabylake, Amberlake and + Apollolake. + # ASoC codec drivers source "sound/soc/intel/boards/Kconfig" diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 7c5038803be7..d44b2652c707 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += atom/ obj-$(CONFIG_SND_SOC_INTEL_CATPT) += catpt/ obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON) += skylake/ obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += keembay/ +obj-$(CONFIG_SND_SOC_INTEL_AVS) += avs/ # Machine support obj-$(CONFIG_SND_SOC) += boards/ diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile new file mode 100644 index 000000000000..5f7976a95fe2 --- /dev/null +++ b/sound/soc/intel/avs/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +snd-soc-avs-objs := dsp.o + +obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h new file mode 100644 index 000000000000..d4e6310e4bf7 --- /dev/null +++ b/sound/soc/intel/avs/avs.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Authors: Cezary Rojewski + * Amadeusz Slawinski + */ + +#ifndef __SOUND_SOC_INTEL_AVS_H +#define __SOUND_SOC_INTEL_AVS_H + +#include +#include + +struct avs_dev; + +struct avs_dsp_ops { + int (* const power)(struct avs_dev *, u32, bool); + int (* const reset)(struct avs_dev *, u32, bool); + int (* const stall)(struct avs_dev *, u32, bool); +}; + +#define avs_dsp_op(adev, op, ...) \ + ((adev)->spec->dsp_ops->op(adev, ## __VA_ARGS__)) + +#define avs_platattr_test(adev, attr) \ + ((adev)->spec->attributes & AVS_PLATATTR_##attr) + +/* Platform specific descriptor */ +struct avs_spec { + const char *name; + + const struct avs_dsp_ops *const dsp_ops; + + const u32 core_init_mask; /* used during DSP boot */ + const u64 attributes; /* bitmask of AVS_PLATATTR_* */ +}; + +/* + * struct avs_dev - Intel HD-Audio driver data + * + * @dev: PCI device + * @dsp_ba: DSP bar address + * @spec: platform-specific descriptor + */ +struct avs_dev { + struct hda_bus base; + struct device *dev; + + void __iomem *dsp_ba; + const struct avs_spec *spec; +}; + +/* from hda_bus to avs_dev */ +#define hda_to_avs(hda) container_of(hda, struct avs_dev, base) +/* from hdac_bus to avs_dev */ +#define hdac_to_avs(hdac) hda_to_avs(to_hda_bus(hdac)) +/* from device to avs_dev */ +#define to_avs_dev(dev) \ +({ \ + struct hdac_bus *__bus = dev_get_drvdata(dev); \ + hdac_to_avs(__bus); \ +}) + +int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power); +int avs_dsp_core_reset(struct avs_dev *adev, u32 core_mask, bool reset); +int avs_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stall); +int avs_dsp_core_enable(struct avs_dev *adev, u32 core_mask); +int avs_dsp_core_disable(struct avs_dev *adev, u32 core_mask); + +#endif /* __SOUND_SOC_INTEL_AVS_H */ diff --git a/sound/soc/intel/avs/dsp.c b/sound/soc/intel/avs/dsp.c new file mode 100644 index 000000000000..eb9d941fe6cf --- /dev/null +++ b/sound/soc/intel/avs/dsp.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include "avs.h" +#include "registers.h" + +#define AVS_ADSPCS_INTERVAL_US 500 +#define AVS_ADSPCS_TIMEOUT_US 50000 + +int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power) +{ + u32 value, mask, reg; + int ret; + + mask = AVS_ADSPCS_SPA_MASK(core_mask); + value = power ? mask : 0; + + snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value); + + mask = AVS_ADSPCS_CPA_MASK(core_mask); + value = power ? mask : 0; + + ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS, + reg, (reg & mask) == value, + AVS_ADSPCS_INTERVAL_US, + AVS_ADSPCS_TIMEOUT_US); + if (ret) + dev_err(adev->dev, "core_mask %d power %s failed: %d\n", + core_mask, power ? "on" : "off", ret); + + return ret; +} + +int avs_dsp_core_reset(struct avs_dev *adev, u32 core_mask, bool reset) +{ + u32 value, mask, reg; + int ret; + + mask = AVS_ADSPCS_CRST_MASK(core_mask); + value = reset ? mask : 0; + + snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value); + + ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS, + reg, (reg & mask) == value, + AVS_ADSPCS_INTERVAL_US, + AVS_ADSPCS_TIMEOUT_US); + if (ret) + dev_err(adev->dev, "core_mask %d %s reset failed: %d\n", + core_mask, reset ? "enter" : "exit", ret); + + return ret; +} + +int avs_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stall) +{ + u32 value, mask, reg; + int ret; + + mask = AVS_ADSPCS_CSTALL_MASK(core_mask); + value = stall ? mask : 0; + + snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value); + + ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS, + reg, (reg & mask) == value, + AVS_ADSPCS_INTERVAL_US, + AVS_ADSPCS_TIMEOUT_US); + if (ret) + dev_err(adev->dev, "core_mask %d %sstall failed: %d\n", + core_mask, stall ? "" : "un", ret); + + return ret; +} + +int avs_dsp_core_enable(struct avs_dev *adev, u32 core_mask) +{ + int ret; + + ret = avs_dsp_op(adev, power, core_mask, true); + if (ret) + return ret; + + ret = avs_dsp_op(adev, reset, core_mask, false); + if (ret) + return ret; + + return avs_dsp_op(adev, stall, core_mask, false); +} + +int avs_dsp_core_disable(struct avs_dev *adev, u32 core_mask) +{ + /* No error checks to allow for complete DSP shutdown. */ + avs_dsp_op(adev, stall, core_mask, true); + avs_dsp_op(adev, reset, core_mask, true); + + return avs_dsp_op(adev, power, core_mask, false); +} + +MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h new file mode 100644 index 000000000000..e0b6c8ffe633 --- /dev/null +++ b/sound/soc/intel/avs/registers.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Authors: Cezary Rojewski + * Amadeusz Slawinski + */ + +#ifndef __SOUND_SOC_INTEL_AVS_REGS_H +#define __SOUND_SOC_INTEL_AVS_REGS_H + +/* Intel HD Audio General DSP Registers */ +#define AVS_ADSP_GEN_BASE 0x0 +#define AVS_ADSP_REG_ADSPCS (AVS_ADSP_GEN_BASE + 0x04) + +#define AVS_ADSPCS_CRST_MASK(cm) (cm) +#define AVS_ADSPCS_CSTALL_MASK(cm) ((cm) << 8) +#define AVS_ADSPCS_SPA_MASK(cm) ((cm) << 16) +#define AVS_ADSPCS_CPA_MASK(cm) ((cm) << 24) +#define AVS_MAIN_CORE_MASK BIT(0) + +#endif /* __SOUND_SOC_INTEL_AVS_REGS_H */ From patchwork Wed Mar 9 20:40:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 549720 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 72C13C433EF for ; Wed, 9 Mar 2022 20:32:34 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id A287717F1; Wed, 9 Mar 2022 21:31:42 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A287717F1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646857952; bh=meBp9QYbXyx70SMR/sIQjoWm4Z3l2LaudwCeUVIYWxY=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=NqQqofCNojxuhclnX7r/ldObwzloAaDKjPPAcrMxjC63FA9OwVGGeHEu9thqtr0Pg jXJ7BAbI8/WYzaApHl9N7bY5bCdV7FQDkorTN87ciI2R2Ino277uJfZQGGWxH8fPVo aBbBP+YqIZT3aZmAEOwChbATerrqvXyb8phyvrDg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id D1D37F80524; Wed, 9 Mar 2022 21:30:20 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5A748F80527; Wed, 9 Mar 2022 21:30:19 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 4B56CF80515 for ; Wed, 9 Mar 2022 21:30:10 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4B56CF80515 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="J3lp3hTI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857812; x=1678393812; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=meBp9QYbXyx70SMR/sIQjoWm4Z3l2LaudwCeUVIYWxY=; b=J3lp3hTIoYqeBRgjWvrLcTpNZoatUO2UkRR4I1degM0gjv/Hnk+IPBDD mkTCuLz+jVvn3+7xn5jl9x/7hUN6z0sY+Bt4JQ9qgLyNsgssYkd+TzJha 4ObDUiJsGqNzus6a/ol+EiTmiW7gfQFfJ/jgzx3BYFjnRtYbnxune7tqR 3FFW9eCbTu6sByChm0oyuJ9znlYHC3dh+dUf7uuykNHc4LHB7zPHWC2WB ghyAicuFrRP6Qc2xu0EKli9PpGGlRxCqkIzj7hdJFi183hDkF/E7I31OQ HGfwNz9yp59ZMzgI5sfqXiCWfEHQetZVJZCuR/Li81Na1JDwbbviVnP2O g==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028696" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028696" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:09 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527046" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:06 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 04/17] ASoC: Intel: avs: Inter process communication Date: Wed, 9 Mar 2022 21:40:16 +0100 Message-Id: <20220309204029.89040-5-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Implement the IPC between Intel audio firmware and kernel driver. The IPC allows transmission of requests, handling of responses as well as unsolicited (i.e. firmware-generated) notifications. A subscription mechanism is added to enable different parts of the driver to register for specific notifications. The part of the DSP boot process that involves sending ROM message requires an extra step - must be followed by unstall operation of MAIN_CORE. All other types of messages do not require such specific handling, so separate set of functions is provided for sending these. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/Makefile | 2 +- sound/soc/intel/avs/avs.h | 100 +++++++++ sound/soc/intel/avs/ipc.c | 387 ++++++++++++++++++++++++++++++++ sound/soc/intel/avs/messages.h | 170 ++++++++++++++ sound/soc/intel/avs/registers.h | 45 ++++ 5 files changed, 703 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/avs/ipc.c create mode 100644 sound/soc/intel/avs/messages.h diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile index 5f7976a95fe2..e243806dd38a 100644 --- a/sound/soc/intel/avs/Makefile +++ b/sound/soc/intel/avs/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-avs-objs := dsp.o +snd-soc-avs-objs := dsp.o ipc.o obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index d4e6310e4bf7..841b8541b101 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -11,13 +11,27 @@ #include #include +#include "messages.h" struct avs_dev; +/* + * struct avs_dsp_ops - Platform-specific DSP operations + * + * @power: Power on or off DSP cores + * @reset: Enter or exit reset state on DSP cores + * @stall: Stall or run DSP cores + * @irq_handler: Top half of IPC servicing + * @irq_thread: Bottom half of IPC servicing + * @int_control: Enable or disable IPC interrupts + */ struct avs_dsp_ops { int (* const power)(struct avs_dev *, u32, bool); int (* const reset)(struct avs_dev *, u32, bool); int (* const stall)(struct avs_dev *, u32, bool); + irqreturn_t (* const irq_handler)(int, void *); + irqreturn_t (* const irq_thread)(int, void *); + void (* const int_control)(struct avs_dev *, bool); }; #define avs_dsp_op(adev, op, ...) \ @@ -34,6 +48,9 @@ struct avs_spec { const u32 core_init_mask; /* used during DSP boot */ const u64 attributes; /* bitmask of AVS_PLATATTR_* */ + const u32 sram_base_offset; + const u32 sram_window_size; + const u32 rom_status; }; /* @@ -49,6 +66,9 @@ struct avs_dev { void __iomem *dsp_ba; const struct avs_spec *spec; + struct avs_ipc *ipc; + + struct completion fw_ready; }; /* from hda_bus to avs_dev */ @@ -68,4 +88,84 @@ int avs_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stall); int avs_dsp_core_enable(struct avs_dev *adev, u32 core_mask); int avs_dsp_core_disable(struct avs_dev *adev, u32 core_mask); +/* Inter Process Communication */ + +struct avs_ipc_msg { + union { + u64 header; + union avs_global_msg glb; + union avs_reply_msg rsp; + }; + void *data; + size_t size; +}; + +/* + * struct avs_ipc - DSP IPC context + * + * @dev: PCI device + * @rx: Reply message cache + * @default_timeout_ms: default message timeout in MS + * @ready: whether firmware is ready and communication is open + * @rx_completed: whether RX for previously sent TX has been received + * @rx_lock: for serializating manipulation of rx_* fields + * @msg_lock: for synchronizing request handling + * @done_completion: DONE-part of IPC i.e. ROM and ACKs from FW + * @busy_completion: BUSY-part of IPC i.e. receiving responses from FW + */ +struct avs_ipc { + struct device *dev; + + struct avs_ipc_msg rx; + u32 default_timeout_ms; + bool ready; + + bool rx_completed; + spinlock_t rx_lock; + struct mutex msg_mutex; + struct completion done_completion; + struct completion busy_completion; +}; + +#define AVS_EIPC EREMOTEIO +/* + * IPC handlers may return positive value (firmware error code) what denotes + * successful HOST <-> DSP communication yet failure to process specific request. + * + * Below macro converts returned value to linux kernel error code. + * All IPC callers MUST use it as soon as firmware error code is consumed. + */ +#define AVS_IPC_RET(ret) \ + (((ret) <= 0) ? (ret) : -AVS_EIPC) + +static inline void avs_ipc_err(struct avs_dev *adev, struct avs_ipc_msg *tx, + const char *name, int error) +{ + /* + * If IPC channel is blocked e.g.: due to ongoing recovery, + * -EPERM error code is expected and thus it's not an actual error. + */ + if (error == -EPERM) + dev_dbg(adev->dev, "%s 0x%08x 0x%08x failed: %d\n", name, + tx->glb.primary, tx->glb.ext.val, error); + else + dev_err(adev->dev, "%s 0x%08x 0x%08x failed: %d\n", name, + tx->glb.primary, tx->glb.ext.val, error); +} + +irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id); +irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id); +void avs_dsp_process_response(struct avs_dev *adev, u64 header); +int avs_dsp_send_msg_timeout(struct avs_dev *adev, + struct avs_ipc_msg *request, + struct avs_ipc_msg *reply, int timeout); +int avs_dsp_send_msg(struct avs_dev *adev, + struct avs_ipc_msg *request, struct avs_ipc_msg *reply); +int avs_dsp_send_rom_msg_timeout(struct avs_dev *adev, + struct avs_ipc_msg *request, int timeout); +int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request); +void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable); +int avs_ipc_init(struct avs_ipc *ipc, struct device *dev); +void avs_ipc_block(struct avs_ipc *ipc); + #endif /* __SOUND_SOC_INTEL_AVS_H */ diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c new file mode 100644 index 000000000000..c0722f8b195f --- /dev/null +++ b/sound/soc/intel/avs/ipc.c @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include "avs.h" +#include "messages.h" +#include "registers.h" + +#define AVS_IPC_TIMEOUT_MS 300 + +static void avs_dsp_receive_rx(struct avs_dev *adev, u64 header) +{ + struct avs_ipc *ipc = adev->ipc; + union avs_reply_msg msg = AVS_MSG(header); + + ipc->rx.header = header; + /* Abort copying payload if request processing was unsuccessful. */ + if (!msg.status) + memcpy_fromio(ipc->rx.data, avs_uplink_addr(adev), + ipc->rx.size); +} + +static void avs_dsp_process_notification(struct avs_dev *adev, u64 header) +{ + struct avs_notify_mod_data mod_data; + union avs_notify_msg msg = AVS_MSG(header); + size_t data_size = 0; + void *data = NULL; + + /* Ignore spurious notifications until handshake is established. */ + if (!adev->ipc->ready && msg.notify_msg_type != AVS_NOTIFY_FW_READY) { + dev_dbg(adev->dev, "FW not ready, skip notification: 0x%08x\n", + msg.primary); + return; + } + + /* Calculate notification payload size. */ + switch (msg.notify_msg_type) { + case AVS_NOTIFY_FW_READY: + break; + + case AVS_NOTIFY_PHRASE_DETECTED: + data_size = sizeof(struct avs_notify_voice_data); + break; + + case AVS_NOTIFY_RESOURCE_EVENT: + data_size = sizeof(struct avs_notify_res_data); + break; + + case AVS_NOTIFY_MODULE_EVENT: + /* To know the total payload size, header needs to be read first. */ + memcpy_fromio(&mod_data, avs_uplink_addr(adev), sizeof(mod_data)); + data_size = sizeof(mod_data) + mod_data.data_size; + break; + + default: + dev_info(adev->dev, "unknown notification: 0x%08x\n", + msg.primary); + break; + } + + if (data_size) { + data = kmalloc(data_size, GFP_KERNEL); + if (!data) + return; + + memcpy_fromio(data, avs_uplink_addr(adev), data_size); + } + + /* Perform notification-specific operations. */ + switch (msg.notify_msg_type) { + case AVS_NOTIFY_FW_READY: + dev_dbg(adev->dev, "FW READY 0x%08x\n", msg.primary); + adev->ipc->ready = true; + complete(&adev->fw_ready); + break; + + default: + break; + } + + kfree(data); +} + +void avs_dsp_process_response(struct avs_dev *adev, u64 header) +{ + struct avs_ipc *ipc = adev->ipc; + + /* + * Response may either be solicited - a reply for a request that has + * been sent beforehand - or unsolicited (notification). + */ + if (avs_msg_is_reply(header)) { + /* Response processing is invoked from IRQ thread. */ + spin_lock_irq(&ipc->rx_lock); + avs_dsp_receive_rx(adev, header); + ipc->rx_completed = true; + spin_unlock_irq(&ipc->rx_lock); + } else { + avs_dsp_process_notification(adev, header); + } + + complete(&ipc->busy_completion); +} + +irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id) +{ + struct avs_dev *adev = dev_id; + struct avs_ipc *ipc = adev->ipc; + u32 adspis, hipc_rsp, hipc_ack; + irqreturn_t ret = IRQ_NONE; + + adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); + if (adspis == UINT_MAX || !(adspis & AVS_ADSP_ADSPIS_IPC)) + return ret; + + hipc_ack = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCIE); + hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); + + /* DSP acked host's request */ + if (hipc_ack & SKL_ADSP_HIPCIE_DONE) { + /* + * As an extra precaution, mask done interrupt. Code executed + * due to complete() found below does not assume any masking. + */ + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, + AVS_ADSP_HIPCCTL_DONE, 0); + + complete(&ipc->done_completion); + + /* tell DSP it has our attention */ + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCIE, + SKL_ADSP_HIPCIE_DONE, + SKL_ADSP_HIPCIE_DONE); + /* unmask done interrupt */ + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, + AVS_ADSP_HIPCCTL_DONE, + AVS_ADSP_HIPCCTL_DONE); + ret = IRQ_HANDLED; + } + + /* DSP sent new response to process */ + if (hipc_rsp & SKL_ADSP_HIPCT_BUSY) { + /* mask busy interrupt */ + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, + AVS_ADSP_HIPCCTL_BUSY, 0); + + ret = IRQ_WAKE_THREAD; + } + + return ret; +} + +irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id) +{ + struct avs_dev *adev = dev_id; + union avs_reply_msg msg; + u32 hipct, hipcte; + + hipct = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); + hipcte = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE); + + /* ensure DSP sent new response to process */ + if (!(hipct & SKL_ADSP_HIPCT_BUSY)) + return IRQ_NONE; + + msg.primary = hipct; + msg.ext.val = hipcte; + avs_dsp_process_response(adev, msg.val); + + /* tell DSP we accepted its message */ + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT, + SKL_ADSP_HIPCT_BUSY, SKL_ADSP_HIPCT_BUSY); + /* unmask busy interrupt */ + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, + AVS_ADSP_HIPCCTL_BUSY, AVS_ADSP_HIPCCTL_BUSY); + + return IRQ_HANDLED; +} + +static bool avs_ipc_is_busy(struct avs_ipc *ipc) +{ + struct avs_dev *adev = to_avs_dev(ipc->dev); + u32 hipc_rsp; + + hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); + return hipc_rsp & SKL_ADSP_HIPCT_BUSY; +} + +static int avs_ipc_wait_busy_completion(struct avs_ipc *ipc, int timeout) +{ + u32 repeats_left = 128; /* to avoid infinite looping */ + int ret; + +again: + ret = wait_for_completion_timeout(&ipc->busy_completion, + msecs_to_jiffies(timeout)); + + /* DSP could be unresponsive at this point. */ + if (!ipc->ready) + return -EPERM; + + if (!ret) { + if (!avs_ipc_is_busy(ipc)) + return -ETIMEDOUT; + /* + * Firmware did its job, either notification or reply + * has been received - now wait until it's processed. + */ + wait_for_completion_killable(&ipc->busy_completion); + } + + /* Ongoing notification's bottom-half may cause early wakeup */ + spin_lock(&ipc->rx_lock); + if (!ipc->rx_completed) { + if (repeats_left) { + /* Reply delayed due to notification. */ + repeats_left--; + reinit_completion(&ipc->busy_completion); + spin_unlock(&ipc->rx_lock); + goto again; + } + + spin_unlock(&ipc->rx_lock); + return -ETIMEDOUT; + } + + spin_unlock(&ipc->rx_lock); + return 0; +} + +static void avs_ipc_msg_init(struct avs_ipc *ipc, struct avs_ipc_msg *reply) +{ + lockdep_assert_held(&ipc->rx_lock); + + ipc->rx.header = 0; + ipc->rx.size = reply ? reply->size : 0; + ipc->rx_completed = false; + + reinit_completion(&ipc->done_completion); + reinit_completion(&ipc->busy_completion); +} + +static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx) +{ + tx->header |= SKL_ADSP_HIPCI_BUSY; + + if (tx->size) + memcpy_toio(avs_downlink_addr(adev), tx->data, tx->size); + snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCIE, tx->header >> 32); + snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCI, tx->header & UINT_MAX); +} + +static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request, + struct avs_ipc_msg *reply, int timeout) +{ + struct avs_ipc *ipc = adev->ipc; + int ret; + + if (!ipc->ready) + return -EPERM; + + mutex_lock(&ipc->msg_mutex); + + spin_lock(&ipc->rx_lock); + avs_ipc_msg_init(ipc, reply); + avs_dsp_send_tx(adev, request); + spin_unlock(&ipc->rx_lock); + + ret = avs_ipc_wait_busy_completion(ipc, timeout); + if (ret) { + if (ret == -ETIMEDOUT) { + dev_crit(adev->dev, "communication severed: %d, rebooting dsp..\n", + ret); + + avs_ipc_block(ipc); + } + goto exit; + } + + ret = ipc->rx.rsp.status; + if (reply) { + reply->header = ipc->rx.header; + if (reply->data && ipc->rx.size) + memcpy(reply->data, ipc->rx.data, reply->size); + } + +exit: + mutex_unlock(&ipc->msg_mutex); + return ret; +} + +int avs_dsp_send_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, + struct avs_ipc_msg *reply, int timeout) +{ + return avs_dsp_do_send_msg(adev, request, reply, timeout); +} + +int avs_dsp_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request, + struct avs_ipc_msg *reply) +{ + return avs_dsp_send_msg_timeout(adev, request, reply, + adev->ipc->default_timeout_ms); +} + +static int avs_dsp_do_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, + int timeout) +{ + struct avs_ipc *ipc = adev->ipc; + int ret; + + mutex_lock(&ipc->msg_mutex); + + spin_lock(&ipc->rx_lock); + avs_ipc_msg_init(ipc, NULL); + avs_dsp_send_tx(adev, request); + spin_unlock(&ipc->rx_lock); + + /* ROM messages must be sent before main core is unstalled */ + ret = avs_dsp_op(adev, stall, AVS_MAIN_CORE_MASK, false); + if (!ret) { + ret = wait_for_completion_timeout(&ipc->done_completion, + msecs_to_jiffies(timeout)); + ret = ret ? 0 : -ETIMEDOUT; + } + + mutex_unlock(&ipc->msg_mutex); + + return ret; +} + +int avs_dsp_send_rom_msg_timeout(struct avs_dev *adev, + struct avs_ipc_msg *request, int timeout) +{ + return avs_dsp_do_send_rom_msg(adev, request, timeout); +} + +int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request) +{ + return avs_dsp_send_rom_msg_timeout(adev, request, + adev->ipc->default_timeout_ms); +} + +void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable) +{ + u32 value, mask; + + /* + * No particular bit setting order. All of these are required + * to have a functional SW <-> FW communication. + */ + value = enable ? AVS_ADSP_ADSPIC_IPC : 0; + snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPIC, + AVS_ADSP_ADSPIC_IPC, value); + + mask = AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY; + value = enable ? mask : 0; + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, mask, value); +} + +int avs_ipc_init(struct avs_ipc *ipc, struct device *dev) +{ + ipc->rx.data = devm_kzalloc(dev, AVS_MAILBOX_SIZE, GFP_KERNEL); + if (!ipc->rx.data) + return -ENOMEM; + + ipc->dev = dev; + ipc->ready = false; + ipc->default_timeout_ms = AVS_IPC_TIMEOUT_MS; + init_completion(&ipc->done_completion); + init_completion(&ipc->busy_completion); + spin_lock_init(&ipc->rx_lock); + mutex_init(&ipc->msg_mutex); + + return 0; +} + +void avs_ipc_block(struct avs_ipc *ipc) +{ + ipc->ready = false; +} diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h new file mode 100644 index 000000000000..003e634f5547 --- /dev/null +++ b/sound/soc/intel/avs/messages.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Authors: Cezary Rojewski + * Amadeusz Slawinski + */ + +#ifndef __SOUND_SOC_INTEL_AVS_MSGS_H +#define __SOUND_SOC_INTEL_AVS_MSGS_H + +struct avs_dev; + +#define AVS_MAILBOX_SIZE 4096 + +enum avs_msg_target { + AVS_FW_GEN_MSG = 0, + AVS_MOD_MSG = 1 +}; + +enum avs_msg_direction { + AVS_MSG_REQUEST = 0, + AVS_MSG_REPLY = 1 +}; + +enum avs_global_msg_type { + AVS_GLB_NOTIFICATION = 27, +}; + +union avs_global_msg { + u64 val; + struct { + union { + u32 primary; + struct { + u32 rsvd:24; + u32 global_msg_type:5; + u32 msg_direction:1; + u32 msg_target:1; + }; + }; + union { + u32 val; + } ext; + }; +} __packed; + +struct avs_tlv { + u32 type; + u32 length; + u32 value[]; +} __packed; + +union avs_module_msg { + u64 val; + struct { + union { + u32 primary; + struct { + u32 module_id:16; + u32 instance_id:8; + u32 module_msg_type:5; + u32 msg_direction:1; + u32 msg_target:1; + }; + }; + union { + u32 val; + } ext; + }; +} __packed; + +union avs_reply_msg { + u64 val; + struct { + union { + u32 primary; + struct { + u32 status:24; + u32 global_msg_type:5; + u32 msg_direction:1; + u32 msg_target:1; + }; + }; + union { + u32 val; + } ext; + }; +} __packed; + +enum avs_notify_msg_type { + AVS_NOTIFY_PHRASE_DETECTED = 4, + AVS_NOTIFY_RESOURCE_EVENT = 5, + AVS_NOTIFY_FW_READY = 8, + AVS_NOTIFY_MODULE_EVENT = 12, +}; + +union avs_notify_msg { + u64 val; + struct { + union { + u32 primary; + struct { + u32 rsvd:16; + u32 notify_msg_type:8; + u32 global_msg_type:5; + u32 msg_direction:1; + u32 msg_target:1; + }; + }; + union { + u32 val; + } ext; + }; +} __packed; + +#define AVS_MSG(hdr) { .val = hdr } + +#define AVS_GLOBAL_REQUEST(msg_type) \ +{ \ + .global_msg_type = AVS_GLB_##msg_type, \ + .msg_direction = AVS_MSG_REQUEST, \ + .msg_target = AVS_FW_GEN_MSG, \ +} + +#define AVS_MODULE_REQUEST(msg_type) \ +{ \ + .module_msg_type = AVS_MOD_##msg_type, \ + .msg_direction = AVS_MSG_REQUEST, \ + .msg_target = AVS_MOD_MSG, \ +} + +#define AVS_NOTIFICATION(msg_type) \ +{ \ + .notify_msg_type = AVS_NOTIFY_##msg_type,\ + .global_msg_type = AVS_GLB_NOTIFICATION,\ + .msg_direction = AVS_MSG_REPLY, \ + .msg_target = AVS_FW_GEN_MSG, \ +} + +#define avs_msg_is_reply(hdr) \ +({ \ + union avs_reply_msg __msg = AVS_MSG(hdr); \ + __msg.msg_direction == AVS_MSG_REPLY && \ + __msg.global_msg_type != AVS_GLB_NOTIFICATION; \ +}) + +/* Notification types */ + +struct avs_notify_voice_data { + u16 kpd_score; + u16 reserved; +} __packed; + +struct avs_notify_res_data { + u32 resource_type; + u32 resource_id; + u32 event_type; + u32 reserved; + u32 data[6]; +} __packed; + +struct avs_notify_mod_data { + u32 module_instance_id; + u32 event_id; + u32 data_size; + u32 data[]; +} __packed; + +#endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */ diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h index e0b6c8ffe633..4bb10ca46a1e 100644 --- a/sound/soc/intel/avs/registers.h +++ b/sound/soc/intel/avs/registers.h @@ -12,6 +12,11 @@ /* Intel HD Audio General DSP Registers */ #define AVS_ADSP_GEN_BASE 0x0 #define AVS_ADSP_REG_ADSPCS (AVS_ADSP_GEN_BASE + 0x04) +#define AVS_ADSP_REG_ADSPIC (AVS_ADSP_GEN_BASE + 0x08) +#define AVS_ADSP_REG_ADSPIS (AVS_ADSP_GEN_BASE + 0x0C) + +#define AVS_ADSP_ADSPIC_IPC BIT(0) +#define AVS_ADSP_ADSPIS_IPC BIT(0) #define AVS_ADSPCS_CRST_MASK(cm) (cm) #define AVS_ADSPCS_CSTALL_MASK(cm) ((cm) << 8) @@ -19,4 +24,44 @@ #define AVS_ADSPCS_CPA_MASK(cm) ((cm) << 24) #define AVS_MAIN_CORE_MASK BIT(0) +#define AVS_ADSP_HIPCCTL_BUSY BIT(0) +#define AVS_ADSP_HIPCCTL_DONE BIT(1) + +/* SKL Intel HD Audio Inter-Processor Communication Registers */ +#define SKL_ADSP_IPC_BASE 0x40 +#define SKL_ADSP_REG_HIPCT (SKL_ADSP_IPC_BASE + 0x00) +#define SKL_ADSP_REG_HIPCTE (SKL_ADSP_IPC_BASE + 0x04) +#define SKL_ADSP_REG_HIPCI (SKL_ADSP_IPC_BASE + 0x08) +#define SKL_ADSP_REG_HIPCIE (SKL_ADSP_IPC_BASE + 0x0C) +#define SKL_ADSP_REG_HIPCCTL (SKL_ADSP_IPC_BASE + 0x10) + +#define SKL_ADSP_HIPCI_BUSY BIT(31) +#define SKL_ADSP_HIPCIE_DONE BIT(30) +#define SKL_ADSP_HIPCT_BUSY BIT(31) + +/* Constants used when accessing SRAM, space shared with firmware */ +#define AVS_FW_REG_BASE(adev) ((adev)->spec->sram_base_offset) +#define AVS_FW_REG_STATUS(adev) (AVS_FW_REG_BASE(adev) + 0x0) +#define AVS_FW_REG_ERROR_CODE(adev) (AVS_FW_REG_BASE(adev) + 0x4) + +#define AVS_FW_REGS_SIZE PAGE_SIZE +#define AVS_FW_REGS_WINDOW 0 +/* DSP -> HOST communication window */ +#define AVS_UPLINK_WINDOW AVS_FW_REGS_WINDOW +/* HOST -> DSP communication window */ +#define AVS_DOWNLINK_WINDOW 1 + +/* registry I/O helpers */ +#define avs_sram_offset(adev, window_idx) \ + ((adev)->spec->sram_base_offset + \ + (adev)->spec->sram_window_size * (window_idx)) + +#define avs_sram_addr(adev, window_idx) \ + ((adev)->dsp_ba + avs_sram_offset(adev, window_idx)) + +#define avs_uplink_addr(adev) \ + (avs_sram_addr(adev, AVS_UPLINK_WINDOW) + AVS_FW_REGS_SIZE) +#define avs_downlink_addr(adev) \ + avs_sram_addr(adev, AVS_DOWNLINK_WINDOW) + #endif /* __SOUND_SOC_INTEL_AVS_REGS_H */ From patchwork Wed Mar 9 20:40:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550546 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 19329C433F5 for ; Wed, 9 Mar 2022 20:32:46 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 4BCC11820; Wed, 9 Mar 2022 21:31:54 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 4BCC11820 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646857964; bh=vaPzYEB7L7CIdqbBj7U2NZYc5LKyieDBmBwrNYNQBWE=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=oQB/edihMeebE6o5SBnfeKuNOgQmUBWxWQZyOLo95hm0k0E6G6DhmK/lGPeY7ZOHv be5+WGcfzucTPiNW5lrlaiBI9OTStKKnONZd2M/GcT5OdhHIq1icadiZqy3TDjI2X1 xfb9ymPTLNCUHWNA0nMxbINmBRAztwosZuZ6nuBY= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 99329F80527; Wed, 9 Mar 2022 21:30:21 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 69205F8012F; Wed, 9 Mar 2022 21:30:19 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id D275FF8012F for ; Wed, 9 Mar 2022 21:30:13 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz D275FF8012F Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ihws9Ihu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857815; x=1678393815; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vaPzYEB7L7CIdqbBj7U2NZYc5LKyieDBmBwrNYNQBWE=; b=ihws9IhuYWNXTdDsbTTMvtBUxwdUY4FuKHfPUSXRvVK0iFaQbYnqjNfs LkmgGJE5QoRvM9nke7BqOnESXn/GJEC0R3z0kM9wnEZzpeCeo5fZ4wiqe UKu/3CJTvxNXEaBxG4phLy6En3usfwk5PZueoE8E/yofuP+2CFTdElP3N iLPu7IHH75A2j3u58geasJPYv1VvyWN6aMaaewiwS7fsXCz3u3OMe/JBB hN40Ewp5JP9mDJuwy7ridCW7kKiV67P5kTYMI1lJaAujut4jKn2FrfjpE dqnf5/yj/yDgDROiZfq3M6lRdx7FL/za06ybVY04fwJateXtvVy+gu3Gj g==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028705" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028705" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:13 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527093" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:09 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 05/17] ASoC: Intel: avs: Add code loading requests Date: Wed, 9 Mar 2022 21:40:17 +0100 Message-Id: <20220309204029.89040-6-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Before firmware and its modules can be used, they have to be loaded. Code loading process is complex and is a combination of DMA and IPC operations. Here, IPC part is being added and accounts for CLDMA and HDA mechanisms both. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/Makefile | 2 +- sound/soc/intel/avs/messages.c | 65 ++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/messages.h | 22 ++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/avs/messages.c diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile index e243806dd38a..c0824f30fd3b 100644 --- a/sound/soc/intel/avs/Makefile +++ b/sound/soc/intel/avs/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-avs-objs := dsp.o ipc.o +snd-soc-avs-objs := dsp.o ipc.o messages.o obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c new file mode 100644 index 000000000000..d568338b0737 --- /dev/null +++ b/sound/soc/intel/avs/messages.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include "avs.h" +#include "messages.h" + +#define AVS_CL_TIMEOUT_MS 5000 + +int avs_ipc_load_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids) +{ + union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_MULTIPLE_MODULES); + struct avs_ipc_msg request; + int ret; + + msg.load_multi_mods.mod_cnt = num_mod_ids; + request.header = msg.val; + request.data = mod_ids; + request.size = sizeof(*mod_ids) * num_mod_ids; + + ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS); + if (ret) + avs_ipc_err(adev, &request, "load multiple modules", ret); + + return ret; +} + +int avs_ipc_unload_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids) +{ + union avs_global_msg msg = AVS_GLOBAL_REQUEST(UNLOAD_MULTIPLE_MODULES); + struct avs_ipc_msg request; + int ret; + + msg.load_multi_mods.mod_cnt = num_mod_ids; + request.header = msg.val; + request.data = mod_ids; + request.size = sizeof(*mod_ids) * num_mod_ids; + + ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS); + if (ret) + avs_ipc_err(adev, &request, "unload multiple modules", ret); + + return ret; +} + +int avs_ipc_load_library(struct avs_dev *adev, u32 dma_id, u32 lib_id) +{ + union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_LIBRARY); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.load_lib.dma_id = dma_id; + msg.load_lib.lib_id = lib_id; + request.header = msg.val; + + ret = avs_dsp_send_msg_timeout(adev, &request, NULL, AVS_CL_TIMEOUT_MS); + if (ret) + avs_ipc_err(adev, &request, "load library", ret); + + return ret; +} diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 003e634f5547..b9ec1c64179b 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -24,6 +24,9 @@ enum avs_msg_direction { }; enum avs_global_msg_type { + AVS_GLB_LOAD_MULTIPLE_MODULES = 15, + AVS_GLB_UNLOAD_MULTIPLE_MODULES = 16, + AVS_GLB_LOAD_LIBRARY = 24, AVS_GLB_NOTIFICATION = 27, }; @@ -38,6 +41,16 @@ union avs_global_msg { u32 msg_direction:1; u32 msg_target:1; }; + /* module loading */ + struct { + u32 mod_cnt:8; + } load_multi_mods; + /* library loading */ + struct { + u32 dma_id:5; + u32 rsvd:11; + u32 lib_id:4; + } load_lib; }; union { u32 val; @@ -84,6 +97,10 @@ union avs_reply_msg { }; union { u32 val; + /* module loading */ + struct { + u32 err_mod_id:16; + } load_multi_mods; } ext; }; } __packed; @@ -167,4 +184,9 @@ struct avs_notify_mod_data { u32 data[]; } __packed; +/* Code loading messages */ +int avs_ipc_load_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids); +int avs_ipc_unload_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids); +int avs_ipc_load_library(struct avs_dev *adev, u32 dma_id, u32 lib_id); + #endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */ From patchwork Wed Mar 9 20:40:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 549719 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 530AFC433F5 for ; Wed, 9 Mar 2022 20:33:09 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 8AB8C1848; Wed, 9 Mar 2022 21:32:17 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 8AB8C1848 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646857987; bh=NW4Vr6GV+hAJk6wRexIspcQ2CBD/XFUIx1VWqhD+exU=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=QiDqkysIimBCwbhc316zJETmYw7MEqYjj5vG1oJIBeDzzku6Mnox6BGGGiHsWzhNv y3xDdpPk+9e3gCdIHIk1WJsP19xIddVNQIaR9ufsdzxEihKyVImKIT3Li8PaUtF6Aa JukXr2wJZmzed9xtFiNpPqn8x/BNA4wEqsUzBJgw= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 3CEB3F8053A; Wed, 9 Mar 2022 21:30:28 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5B89EF80537; Wed, 9 Mar 2022 21:30:26 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 67406F8012F for ; Wed, 9 Mar 2022 21:30:19 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 67406F8012F Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="mfGyUyZc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857820; x=1678393820; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NW4Vr6GV+hAJk6wRexIspcQ2CBD/XFUIx1VWqhD+exU=; b=mfGyUyZcF7eRcSmgFbvNx8Xp9ZZQ9fGrHsaJx8vdzQylANsTu8xlmC9q Vy8SDpp2IIQaeLVNjSFnIA3tVL0rZ1TIqIiCLyESlKBtgTFk+vGn0rleN XToHUwffUg4Q1Anmb7vql4WUapb3DlAcoCa95d2p5c2SYIsoAdIZ0uixt EBfTEHTKctaOhgntr45XtK2GTrgni6qBo41+y/HteilEnaHtD+dsoN/gT RKkktlSUfUksUdMtQqqCaw8cMpbqHxYuaY34KzTCpUFBczAOPYglwgm9m UpYEYgfBR9yreXxsM47zavc/SM1CVcM+TjDPVMB/cywtw9RQMKx4/IJSp g==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028720" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028720" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:17 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527117" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:13 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 06/17] ASoC: Intel: avs: Add pipeline management requests Date: Wed, 9 Mar 2022 21:40:18 +0100 Message-Id: <20220309204029.89040-7-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Pipeline represents a scheduling entity. Their existence as well as their state machine is controlled through CREATE_PIPELINE, DELETE_PIPELINE and SET_PIPELINE_STATE IPCs. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/messages.c | 76 ++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/messages.h | 48 +++++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index d568338b0737..de2d50f8c6b4 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -63,3 +63,79 @@ int avs_ipc_load_library(struct avs_dev *adev, u32 dma_id, u32 lib_id) return ret; } + +int avs_ipc_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, + u8 instance_id, bool lp, u16 attributes) +{ + union avs_global_msg msg = AVS_GLOBAL_REQUEST(CREATE_PIPELINE); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.create_ppl.ppl_mem_size = req_size; + msg.create_ppl.ppl_priority = priority; + msg.create_ppl.instance_id = instance_id; + msg.ext.create_ppl.lp = lp; + msg.ext.create_ppl.attributes = attributes; + request.header = msg.val; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "create pipeline", ret); + + return ret; +} + +int avs_ipc_delete_pipeline(struct avs_dev *adev, u8 instance_id) +{ + union avs_global_msg msg = AVS_GLOBAL_REQUEST(DELETE_PIPELINE); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.ppl.instance_id = instance_id; + request.header = msg.val; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "delete pipeline", ret); + + return ret; +} + +int avs_ipc_set_pipeline_state(struct avs_dev *adev, u8 instance_id, + enum avs_pipeline_state state) +{ + union avs_global_msg msg = AVS_GLOBAL_REQUEST(SET_PIPELINE_STATE); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.set_ppl_state.ppl_id = instance_id; + msg.set_ppl_state.state = state; + request.header = msg.val; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "set pipeline state", ret); + + return ret; +} + +int avs_ipc_get_pipeline_state(struct avs_dev *adev, u8 instance_id, + enum avs_pipeline_state *state) +{ + union avs_global_msg msg = AVS_GLOBAL_REQUEST(GET_PIPELINE_STATE); + struct avs_ipc_msg request = {{0}}; + struct avs_ipc_msg reply = {{0}}; + int ret; + + msg.get_ppl_state.ppl_id = instance_id; + request.header = msg.val; + + ret = avs_dsp_send_msg(adev, &request, &reply); + if (ret) { + avs_ipc_err(adev, &request, "get pipeline state", ret); + return ret; + } + + *state = reply.rsp.ext.get_ppl_state.state; + return ret; +} diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index b9ec1c64179b..c1bf1cff54d9 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -26,6 +26,10 @@ enum avs_msg_direction { enum avs_global_msg_type { AVS_GLB_LOAD_MULTIPLE_MODULES = 15, AVS_GLB_UNLOAD_MULTIPLE_MODULES = 16, + AVS_GLB_CREATE_PIPELINE = 17, + AVS_GLB_DELETE_PIPELINE = 18, + AVS_GLB_SET_PIPELINE_STATE = 19, + AVS_GLB_GET_PIPELINE_STATE = 20, AVS_GLB_LOAD_LIBRARY = 24, AVS_GLB_NOTIFICATION = 27, }; @@ -45,6 +49,23 @@ union avs_global_msg { struct { u32 mod_cnt:8; } load_multi_mods; + /* pipeline management */ + struct { + u32 ppl_mem_size:11; + u32 ppl_priority:5; + u32 instance_id:8; + } create_ppl; + struct { + u32 rsvd:16; + u32 instance_id:8; + } ppl; /* generic ppl request */ + struct { + u32 state:16; + u32 ppl_id:8; + } set_ppl_state; + struct { + u32 ppl_id:8; + } get_ppl_state; /* library loading */ struct { u32 dma_id:5; @@ -54,6 +75,12 @@ union avs_global_msg { }; union { u32 val; + /* pipeline management */ + struct { + u32 lp:1; /* low power flag */ + u32 rsvd:3; + u32 attributes:16; /* additional scheduling flags */ + } create_ppl; } ext; }; } __packed; @@ -101,6 +128,10 @@ union avs_reply_msg { struct { u32 err_mod_id:16; } load_multi_mods; + /* pipeline management */ + struct { + u32 state:5; + } get_ppl_state; } ext; }; } __packed; @@ -189,4 +220,21 @@ int avs_ipc_load_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids); int avs_ipc_unload_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids); int avs_ipc_load_library(struct avs_dev *adev, u32 dma_id, u32 lib_id); +/* Pipeline management messages */ +enum avs_pipeline_state { + AVS_PPL_STATE_INVALID, + AVS_PPL_STATE_UNINITIALIZED, + AVS_PPL_STATE_RESET, + AVS_PPL_STATE_PAUSED, + AVS_PPL_STATE_RUNNING, +}; + +int avs_ipc_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, + u8 instance_id, bool lp, u16 attributes); +int avs_ipc_delete_pipeline(struct avs_dev *adev, u8 instance_id); +int avs_ipc_set_pipeline_state(struct avs_dev *adev, u8 instance_id, + enum avs_pipeline_state state); +int avs_ipc_get_pipeline_state(struct avs_dev *adev, u8 instance_id, + enum avs_pipeline_state *state); + #endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */ From patchwork Wed Mar 9 20:40:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550545 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BF969C433EF for ; Wed, 9 Mar 2022 20:33:25 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id D1AEC1838; Wed, 9 Mar 2022 21:32:33 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D1AEC1838 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858003; bh=XVfyHb7RlPHyZggCeZLFehkULiJIemg9v9tvdbZ7kfg=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=PemGC5Uta51co+taNcfKshIytDsWGXuIHowO75StRly5oBFs5GuS5uEMpOEoJeKiW 5bY+jTWgQKWvShYwiP4i/65ZtAnN02l+aqtGuHM2rr4Lvbp93xt2DHWmldh3MB/ijd BZbyqseSaC/974JoVCGa3VQ9mcwpjem0HiFuyvh4= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B571EF8053C; Wed, 9 Mar 2022 21:30:29 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 418E8F8053B; Wed, 9 Mar 2022 21:30:28 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 5B9D1F80529 for ; Wed, 9 Mar 2022 21:30:21 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 5B9D1F80529 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UlAXj9yc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857822; x=1678393822; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XVfyHb7RlPHyZggCeZLFehkULiJIemg9v9tvdbZ7kfg=; b=UlAXj9ycx2YiUQwQcg69CTlWnXBYiTy2vJGc3+iRni/3yUrO5qdos4rC 4LZgPeOHzJVxHbb/ItweRvjHqtj56in2IlBw+ZqLeQ+MKVXJsSOY8m19z WkdvA/J3F7Q5x3KxpBbo8PwUzWf2dW1HnYWtRvgB6CQPwEBZg7+9KggOD Kw53w8BrrvnB7dHIS1UjolJIODi2T2NE8J2LhhdlGCJQDvqzgo9dyeJew zXmaxZDpf60Kh7BJq5Q6FDx5Zivnq1wujtjbHS/jYibMD0Bwh1SBpK5Ch 7Y9l+o/YL8UkQLVJ7iuSjSneD/9rAqRFneFx830zPs8gFS0gyY2Y/zE3y A==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028731" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028731" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:20 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527148" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:17 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 07/17] ASoC: Intel: avs: Add module management requests Date: Wed, 9 Mar 2022 21:40:19 +0100 Message-Id: <20220309204029.89040-8-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Firmware modules implement processing algorithms. Their lifecycle, similarly to pipelines is being controlled by IPCs: initialization, deletion and (un)binding. Modules can be configured at runtime - runtime parameters. This is done with help of LARGE_CONFIG IPCs: getter and setter. Due to firmware limitations, LARGE_CONFIG_GET handler implementation does not support retrieving payload with size larger than IPC inbox window size. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/ipc.c | 8 +- sound/soc/intel/avs/messages.c | 262 +++++++++++++++++++++++++++++++++ sound/soc/intel/avs/messages.h | 53 +++++++ 3 files changed, 322 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c index c0722f8b195f..9770368a898e 100644 --- a/sound/soc/intel/avs/ipc.c +++ b/sound/soc/intel/avs/ipc.c @@ -21,9 +21,15 @@ static void avs_dsp_receive_rx(struct avs_dev *adev, u64 header) ipc->rx.header = header; /* Abort copying payload if request processing was unsuccessful. */ - if (!msg.status) + if (!msg.status) { + /* update size in case of LARGE_CONFIG_GET */ + if (msg.msg_target == AVS_MOD_MSG && + msg.global_msg_type == AVS_MOD_LARGE_CONFIG_GET) + ipc->rx.size = msg.ext.large_config.data_off_size; + memcpy_fromio(ipc->rx.data, avs_uplink_addr(adev), ipc->rx.size); + } } static void avs_dsp_process_notification(struct avs_dev *adev, u64 header) diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index de2d50f8c6b4..613c9452226d 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -6,6 +6,7 @@ // Amadeusz Slawinski // +#include #include "avs.h" #include "messages.h" @@ -139,3 +140,264 @@ int avs_ipc_get_pipeline_state(struct avs_dev *adev, u8 instance_id, *state = reply.rsp.ext.get_ppl_state.state; return ret; } + +/* + * avs_ipc_init_instance - Initialize module instance + * + * @adev: Driver context + * @module_id: Module-type id + * @instance_id: Unique module instance id + * @ppl_id: Parent pipeline id + * @core_id: DSP core to allocate module on + * @domain: Processing domain (low latency or data processing) + * @param: Module-type specific configuration + * @param_size: Size of @param in bytes + * + * Argument verification, as well as pipeline state checks are done by the + * firmware. + * + * Note: @ppl_id and @core_id are independent of each other as single pipeline + * can be composed of module instances located on different DSP cores. + */ +int avs_ipc_init_instance(struct avs_dev *adev, u16 module_id, u8 instance_id, + u8 ppl_id, u8 core_id, u8 domain, + void *param, u32 param_size) +{ + union avs_module_msg msg = AVS_MODULE_REQUEST(INIT_INSTANCE); + struct avs_ipc_msg request; + int ret; + + msg.module_id = module_id; + msg.instance_id = instance_id; + /* firmware expects size provided in dwords */ + msg.ext.init_instance.param_block_size = + DIV_ROUND_UP(param_size, sizeof(u32)); + msg.ext.init_instance.ppl_instance_id = ppl_id; + msg.ext.init_instance.core_id = core_id; + msg.ext.init_instance.proc_domain = domain; + + request.header = msg.val; + request.data = param; + request.size = param_size; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "init instance", ret); + + return ret; +} + +/* + * avs_ipc_delete_instance - Delete module instance + * + * @adev: Driver context + * @module_id: Module-type id + * @instance_id: Unique module instance id + * + * Argument verification, as well as pipeline state checks are done by the + * firmware. + * + * Note: only standalone modules i.e. without a parent pipeline shall be + * deleted using this IPC message. In all other cases, pipeline owning the + * modules peforms cleanup automatically when it is deleted. + */ +int avs_ipc_delete_instance(struct avs_dev *adev, u16 module_id, u8 instance_id) +{ + union avs_module_msg msg = AVS_MODULE_REQUEST(DELETE_INSTANCE); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.module_id = module_id; + msg.instance_id = instance_id; + request.header = msg.val; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "delete instance", ret); + + return ret; +} + +/* + * avs_ipc_bind - Bind two module instances + * + * @adev: Driver context + * @module_id: Source module-type id + * @instance_id: Source module instance id + * @dst_module_id: Sink module-type id + * @dst_instance_id: Sink module instance id + * @dst_queue: Sink module pin to bind @src_queue with + * @src_queue: Source module pin to bind @dst_queue with + */ +int avs_ipc_bind(struct avs_dev *adev, u16 module_id, u8 instance_id, + u16 dst_module_id, u8 dst_instance_id, + u8 dst_queue, u8 src_queue) +{ + union avs_module_msg msg = AVS_MODULE_REQUEST(BIND); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.module_id = module_id; + msg.instance_id = instance_id; + msg.ext.bind_unbind.dst_module_id = dst_module_id; + msg.ext.bind_unbind.dst_instance_id = dst_instance_id; + msg.ext.bind_unbind.dst_queue = dst_queue; + msg.ext.bind_unbind.src_queue = src_queue; + request.header = msg.val; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "bind modules", ret); + + return ret; +} + +/* + * avs_ipc_unbind - Unbind two module instances + * + * @adev: Driver context + * @module_id: Source module-type id + * @instance_id: Source module instance id + * @dst_module_id: Sink module-type id + * @dst_instance_id: Sink module instance id + * @dst_queue: Sink module pin to unbind @src_queue from + * @src_queue: Source module pin to unbind @dst_queue from + */ +int avs_ipc_unbind(struct avs_dev *adev, u16 module_id, u8 instance_id, + u16 dst_module_id, u8 dst_instance_id, + u8 dst_queue, u8 src_queue) +{ + union avs_module_msg msg = AVS_MODULE_REQUEST(UNBIND); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.module_id = module_id; + msg.instance_id = instance_id; + msg.ext.bind_unbind.dst_module_id = dst_module_id; + msg.ext.bind_unbind.dst_instance_id = dst_instance_id; + msg.ext.bind_unbind.dst_queue = dst_queue; + msg.ext.bind_unbind.src_queue = src_queue; + request.header = msg.val; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "unbind modules", ret); + + return ret; +} + +static int __avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id, + u8 param_id, bool init_block, bool final_block, + u8 *request_data, size_t request_size, size_t off_size) +{ + union avs_module_msg msg = AVS_MODULE_REQUEST(LARGE_CONFIG_SET); + struct avs_ipc_msg request; + int ret; + + msg.module_id = module_id; + msg.instance_id = instance_id; + msg.ext.large_config.data_off_size = off_size; + msg.ext.large_config.large_param_id = param_id; + msg.ext.large_config.final_block = final_block; + msg.ext.large_config.init_block = init_block; + + request.header = msg.val; + request.data = request_data; + request.size = request_size; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "large config set", ret); + + return ret; +} + +int avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, + u8 instance_id, u8 param_id, + u8 *request, size_t request_size) +{ + size_t remaining, tx_size; + bool final; + int ret; + + remaining = request_size; + tx_size = min_t(size_t, AVS_MAILBOX_SIZE, remaining); + final = (tx_size == remaining); + + /* Initial request states total payload size. */ + ret = __avs_ipc_set_large_config(adev, module_id, instance_id, + param_id, 1, final, request, tx_size, + request_size); + if (ret) + return ret; + + remaining -= tx_size; + + /* Loop the rest only when payload exceeds mailbox's size. */ + while (remaining) { + size_t offset; + + offset = request_size - remaining; + tx_size = min_t(size_t, AVS_MAILBOX_SIZE, remaining); + final = (tx_size == remaining); + + ret = __avs_ipc_set_large_config(adev, module_id, instance_id, + param_id, 0, final, + request + offset, tx_size, + offset); + if (ret) + return ret; + + remaining -= tx_size; + } + + return 0; +} + +int avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id, + u8 param_id, u8 *request_data, size_t request_size, + u8 **reply_data, size_t *reply_size) +{ + union avs_module_msg msg = AVS_MODULE_REQUEST(LARGE_CONFIG_GET); + struct avs_ipc_msg request; + struct avs_ipc_msg reply = {{0}}; + size_t size; + void *buf; + int ret; + + reply.data = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL); + if (!reply.data) + return -ENOMEM; + + msg.module_id = module_id; + msg.instance_id = instance_id; + msg.ext.large_config.data_off_size = request_size; + msg.ext.large_config.large_param_id = param_id; + /* final_block is always 0 on request. Updated by fw on reply. */ + msg.ext.large_config.final_block = 0; + msg.ext.large_config.init_block = 1; + + request.header = msg.val; + request.data = request_data; + request.size = request_size; + reply.size = AVS_MAILBOX_SIZE; + + ret = avs_dsp_send_msg(adev, &request, &reply); + if (ret) { + avs_ipc_err(adev, &request, "large config get", ret); + kfree(reply.data); + return ret; + } + + size = reply.rsp.ext.large_config.data_off_size; + buf = krealloc(reply.data, size, GFP_KERNEL); + if (!buf) { + kfree(reply.data); + return -ENOMEM; + } + + *reply_data = buf; + *reply_size = size; + + return 0; +} diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index c1bf1cff54d9..e4b95b066d70 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -91,6 +91,15 @@ struct avs_tlv { u32 value[]; } __packed; +enum avs_module_msg_type { + AVS_MOD_INIT_INSTANCE = 0, + AVS_MOD_LARGE_CONFIG_GET = 3, + AVS_MOD_LARGE_CONFIG_SET = 4, + AVS_MOD_BIND = 5, + AVS_MOD_UNBIND = 6, + AVS_MOD_DELETE_INSTANCE = 11, +}; + union avs_module_msg { u64 val; struct { @@ -106,6 +115,24 @@ union avs_module_msg { }; union { u32 val; + struct { + u32 param_block_size:16; + u32 ppl_instance_id:8; + u32 core_id:4; + u32 proc_domain:1; + } init_instance; + struct { + u32 data_off_size:20; + u32 large_param_id:8; + u32 final_block:1; + u32 init_block:1; + } large_config; + struct { + u32 dst_module_id:16; + u32 dst_instance_id:8; + u32 dst_queue:3; + u32 src_queue:3; + } bind_unbind; } ext; }; } __packed; @@ -132,6 +159,13 @@ union avs_reply_msg { struct { u32 state:5; } get_ppl_state; + /* module management */ + struct { + u32 data_off_size:20; + u32 large_param_id:8; + u32 final_block:1; + u32 init_block:1; + } large_config; } ext; }; } __packed; @@ -237,4 +271,23 @@ int avs_ipc_set_pipeline_state(struct avs_dev *adev, u8 instance_id, int avs_ipc_get_pipeline_state(struct avs_dev *adev, u8 instance_id, enum avs_pipeline_state *state); +/* Module management messages */ +int avs_ipc_init_instance(struct avs_dev *adev, u16 module_id, u8 instance_id, + u8 ppl_id, u8 core_id, u8 domain, + void *param, u32 param_size); +int avs_ipc_delete_instance(struct avs_dev *adev, u16 module_id, + u8 instance_id); +int avs_ipc_bind(struct avs_dev *adev, u16 module_id, u8 instance_id, + u16 dst_module_id, u8 dst_instance_id, + u8 dst_queue, u8 src_queue); +int avs_ipc_unbind(struct avs_dev *adev, u16 module_id, u8 instance_id, + u16 dst_module_id, u8 dst_instance_id, + u8 dst_queue, u8 src_queue); +int avs_ipc_set_large_config(struct avs_dev *adev, u16 module_id, + u8 instance_id, u8 param_id, + u8 *request, size_t request_size); +int avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id, + u8 param_id, u8 *request_data, size_t request_size, + u8 **reply_data, size_t *reply_size); + #endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */ From patchwork Wed Mar 9 20:40:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 549718 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6A025C433EF for ; Wed, 9 Mar 2022 20:33:39 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id A49221728; Wed, 9 Mar 2022 21:32:47 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A49221728 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858017; bh=yeOvXcDrBIA28P9BIlssBcxGaEk4JyYQIy/Spx2+50o=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=tSpKZHIreA9AkEO6soGnsy7l+VTCurYh4hW3dguohWkv06Z/kE19xaEmSkkCWbSWc oaxP+qz7cy8WougE13mUAFe/vZg3dnKWeOXTi1Jdm5rFlIWu2Xokm28kVfs353Qy4v OcEangIkCQYACBJ2LDz1+ZkgxNn/Dne4YuAi4c2E= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 5BE7DF80548; Wed, 9 Mar 2022 21:30:35 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 695B9F80544; Wed, 9 Mar 2022 21:30:33 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id CCD2BF80537 for ; Wed, 9 Mar 2022 21:30:26 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz CCD2BF80537 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="eKRN1USz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857828; x=1678393828; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yeOvXcDrBIA28P9BIlssBcxGaEk4JyYQIy/Spx2+50o=; b=eKRN1USzbeR3ttAD+p5jeq54GE6rZa5Pn9OVEV9+NGwk7lH5+5NfLp2y bmgQF6DBxuRO/e/fu7F6dVuKxEOOjZzkAhlIKPY2f+zEZsZXNlx3zNRMc pwTDc4582BxtorevE4VE3OKBP5zUQBtNuosCS4EEAOKYODUPxwNozMokv FsTZP+LqPbSb2L3uvXjBNKGG9fGB3VyxyjPxAjkuk/K9jCRXZzu4/Ie0H SfqBLjX/45fTnGWFpNo/esTt7fO0mnNgu6eYWypNlKhxLXJl0rMIOfnqo hCNB5ueoXM5hZeHXp7e6StGPJfc3tDGqdDJb9nshuQSyVNyXHeSyUnhup g==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028743" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028743" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:24 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527164" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:20 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 08/17] ASoC: Intel: avs: Add power management requests Date: Wed, 9 Mar 2022 21:40:20 +0100 Message-Id: <20220309204029.89040-9-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Audio DSP supports low power states i.e.: transitions between D0 and D3 and D0-substates in form of D0i0 and D0i3. That process is a combination of core and IPC operations. Here, Dx and D0ix IPC handlers are added. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/messages.c | 44 ++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/messages.h | 15 ++++++++++++ 2 files changed, 59 insertions(+) diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index 613c9452226d..e8f441b28d71 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -401,3 +401,47 @@ int avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id return 0; } + +int avs_ipc_set_dx(struct avs_dev *adev, u32 core_mask, bool powerup) +{ + union avs_module_msg msg = AVS_MODULE_REQUEST(SET_DX); + struct avs_ipc_msg request; + struct avs_dxstate_info dx; + int ret; + + dx.core_mask = core_mask; + dx.dx_mask = powerup ? core_mask : 0; + request.header = msg.val; + request.data = &dx; + request.size = sizeof(dx); + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "set dx", ret); + + return ret; +} + +/* + * avs_ipc_set_d0ix - Set power gating policy (entering D0IX substates) + * + * @enable_pg: Whether to enable or disable power gating + * @streaming: Whether a stream is running when transitioning + */ +int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming) +{ + union avs_module_msg msg = AVS_MODULE_REQUEST(SET_D0IX); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.ext.set_d0ix.wake = enable_pg; + msg.ext.set_d0ix.streaming = streaming; + + request.header = msg.val; + + ret = avs_dsp_send_msg(adev, &request, NULL); + if (ret) + avs_ipc_err(adev, &request, "set d0ix", ret); + + return ret; +} diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index e4b95b066d70..69920f5e802b 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -97,6 +97,8 @@ enum avs_module_msg_type { AVS_MOD_LARGE_CONFIG_SET = 4, AVS_MOD_BIND = 5, AVS_MOD_UNBIND = 6, + AVS_MOD_SET_DX = 7, + AVS_MOD_SET_D0IX = 8, AVS_MOD_DELETE_INSTANCE = 11, }; @@ -133,6 +135,10 @@ union avs_module_msg { u32 dst_queue:3; u32 src_queue:3; } bind_unbind; + struct { + u32 wake:1; + u32 streaming:1; + } set_d0ix; } ext; }; } __packed; @@ -290,4 +296,13 @@ int avs_ipc_get_large_config(struct avs_dev *adev, u16 module_id, u8 instance_id u8 param_id, u8 *request_data, size_t request_size, u8 **reply_data, size_t *reply_size); +/* DSP cores and domains power management messages */ +struct avs_dxstate_info { + u32 core_mask; /* which cores are subject for power transition */ + u32 dx_mask; /* bit[n]=1 core n goes to D0, bit[n]=0 it goes to D3 */ +} __packed; + +int avs_ipc_set_dx(struct avs_dev *adev, u32 core_mask, bool powerup); +int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming); + #endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */ From patchwork Wed Mar 9 20:40:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550544 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0D06BC433FE for ; Wed, 9 Mar 2022 20:34:02 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 859EF1866; Wed, 9 Mar 2022 21:33:10 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 859EF1866 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858040; bh=qaTyULVfHaLm3NVsFZ3HMvVFK2rbsy3kPt3ceZY5Hj4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=tjx93CfeeWNI9boxySmCPpEBcK6x+DndTFzKVoE/uTtJWC/wW83tcIe5OjFKOjOnR SFxLPQ7fjyZxfC6GwDsMg0CsDfclBPELavHcWkjZ3ps8lz44W5erVYXuAZfjsid4bR KRdispuaj6G6KjFHTtFeJTv8mWCnA21Kxxa2HTyo= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 6D781F80559; Wed, 9 Mar 2022 21:30:37 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5DF32F80549; Wed, 9 Mar 2022 21:30:35 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C7C8BF8053B for ; Wed, 9 Mar 2022 21:30:28 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C7C8BF8053B Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="TA6gW6Oh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857830; x=1678393830; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qaTyULVfHaLm3NVsFZ3HMvVFK2rbsy3kPt3ceZY5Hj4=; b=TA6gW6OhrG8JkfLV1eu7xzIoQB/HB6W3Hon+jWtdVFuktlfNKXJBeJf/ bTmhZOcJi+UPqdWenHJ6x0AIDHU0YePckuhXrD3nsVrnSf8/wqFGcZLvJ jSi6ATOYDsayw1L+iWUDs2Uh/WQFWxPV+ZBA61j4rrzvInE7mhbpFTKbz LSKQS7LYuCdnCTvPGaJVghbfmQCrqs4feCoAYml9nzgeeNNg2sOLeGnmK mbpz3PWZznETMnc7ixRMeCzgGkVCpuJAHNgFeAFcUo1MJLm47VOq0gSut eKiRIghiMBJFzQxICtGtJuVbpEeiuhGaDvKRv30/7JEJtzozeaVgqjq8o g==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028758" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028758" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527179" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:24 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 09/17] ASoC: Intel: avs: Add ROM requests Date: Wed, 9 Mar 2022 21:40:21 +0100 Message-Id: <20220309204029.89040-10-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" ROM requests are messages initiated by Host to alter firmware early boot process. They specify whether the next boot should be a fresh start or if IMR can be used to speed things up. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/messages.c | 18 ++++++++++++++++++ sound/soc/intel/avs/messages.h | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index e8f441b28d71..f7d00e541323 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -12,6 +12,24 @@ #define AVS_CL_TIMEOUT_MS 5000 +int avs_ipc_set_boot_config(struct avs_dev *adev, u32 dma_id, u32 purge) +{ + union avs_global_msg msg = AVS_GLOBAL_REQUEST(ROM_CONTROL); + struct avs_ipc_msg request = {{0}}; + int ret; + + msg.boot_cfg.rom_ctrl_msg_type = AVS_ROM_SET_BOOT_CONFIG; + msg.boot_cfg.dma_id = dma_id; + msg.boot_cfg.purge_request = purge; + request.header = msg.val; + + ret = avs_dsp_send_rom_msg(adev, &request); + if (ret) + avs_ipc_err(adev, &request, "set boot config", ret); + + return ret; +} + int avs_ipc_load_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids) { union avs_global_msg msg = AVS_GLOBAL_REQUEST(LOAD_MULTIPLE_MODULES); diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 69920f5e802b..615a61cef4f6 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -24,6 +24,7 @@ enum avs_msg_direction { }; enum avs_global_msg_type { + AVS_GLB_ROM_CONTROL = 1, AVS_GLB_LOAD_MULTIPLE_MODULES = 15, AVS_GLB_UNLOAD_MULTIPLE_MODULES = 16, AVS_GLB_CREATE_PIPELINE = 17, @@ -45,6 +46,12 @@ union avs_global_msg { u32 msg_direction:1; u32 msg_target:1; }; + /* set boot config */ + struct { + u32 rom_ctrl_msg_type:9; + u32 dma_id:5; + u32 purge_request:1; + } boot_cfg; /* module loading */ struct { u32 mod_cnt:8; @@ -255,6 +262,13 @@ struct avs_notify_mod_data { u32 data[]; } __packed; +/* ROM messages */ +enum avs_rom_control_msg_type { + AVS_ROM_SET_BOOT_CONFIG = 0, +}; + +int avs_ipc_set_boot_config(struct avs_dev *adev, u32 dma_id, u32 purge); + /* Code loading messages */ int avs_ipc_load_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids); int avs_ipc_unload_modules(struct avs_dev *adev, u16 *mod_ids, u32 num_mod_ids); From patchwork Wed Mar 9 20:40:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 549717 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 15BD2C433F5 for ; Wed, 9 Mar 2022 20:34:17 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 45D8E1883; Wed, 9 Mar 2022 21:33:25 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 45D8E1883 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858055; bh=0+N1ilnf8neFiUTYhT1Kshru1VH5zRQ3ejxJH+DUhQ0=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=fSla6+xBdyacH7qDIjeZtoLVV7ktoUwDhCStR6ggBxSUK+jJIg0FabSBAGOBtdTbL 5XfDzflyqvBD+J+V+bAEjauWBtZb1JUMYI3IEoPPiKIDLRv4iXXWCPRqWa/S/hBrcv hpfNYt7VKZULYDvznB50x+CaH+YXRQ1XwvoiIoG0= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 26B3DF8053D; Wed, 9 Mar 2022 21:30:41 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id BD036F80563; Wed, 9 Mar 2022 21:30:39 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 2B78AF8053D for ; Wed, 9 Mar 2022 21:30:32 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 2B78AF8053D Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="gol5jWhT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857834; x=1678393834; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0+N1ilnf8neFiUTYhT1Kshru1VH5zRQ3ejxJH+DUhQ0=; b=gol5jWhTMzGmHstkT1QXpUlkmbMGwOlZDDAmkxcu8xP4jkiylMySyg92 /4xoVWNztaYFGz/4h20fXk3WwFt4NXrvLJNIqQwzV0XHVL/4dtDYv6IgZ vsBLwZSlzqtCDsQ0h7gFMYTg0TvZsQAx6F7AT7/03ouvjS+cTvxbioV2l C9A7OeCENBe2AHEX7BX4gYuoWar6ax9W67IR/a04E2P2dp+T0J0+3FPFV isR4B49S3wQWwTf0EEKrVIWGFBwc4rILYkdIe+S+dTrqBv8RhipOG/wR6 9gBtFEYGmBkmiQW7DLoGkHe/+vPMXyx6XdGMtYR952KUvfuHols9vvUWm Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028773" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028773" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:31 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527202" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:27 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 10/17] ASoC: Intel: avs: Add basefw runtime-parameter requests Date: Wed, 9 Mar 2022 21:40:22 +0100 Message-Id: <20220309204029.89040-11-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Each module may expose a range of runtime parameters. For basefw, implement handlers for: FIRMWARE_CONFIG, HARDWARE_CONFIG and MODULES_INFO. These are used by driver to dynamically allocate resources in respect to platform details, reducing number of hardcodes and code duplications that would otherwise be needed to be defined within the driver code. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/messages.c | 217 +++++++++++++++++++++++++++++++++ sound/soc/intel/avs/messages.h | 179 +++++++++++++++++++++++++++ 2 files changed, 396 insertions(+) diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index f7d00e541323..4e7a2972da6d 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -463,3 +463,220 @@ int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming) return ret; } + +int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg) +{ + struct avs_tlv *tlv; + size_t payload_size; + size_t offset = 0; + u8 *payload; + int ret; + + ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, + AVS_BASEFW_FIRMWARE_CONFIG, NULL, 0, + &payload, &payload_size); + if (ret) + return ret; + + while (offset < payload_size) { + tlv = (struct avs_tlv *)(payload + offset); + + switch (tlv->type) { + case AVS_FW_CFG_FW_VERSION: + memcpy(&cfg->fw_version, tlv->value, + sizeof(cfg->fw_version)); + break; + + case AVS_FW_CFG_MEMORY_RECLAIMED: + cfg->memory_reclaimed = *tlv->value; + break; + + case AVS_FW_CFG_SLOW_CLOCK_FREQ_HZ: + cfg->slow_clock_freq_hz = *tlv->value; + break; + + case AVS_FW_CFG_FAST_CLOCK_FREQ_HZ: + cfg->fast_clock_freq_hz = *tlv->value; + break; + + case AVS_FW_CFG_ALH_SUPPORT_LEVEL: + cfg->alh_support = *tlv->value; + break; + + case AVS_FW_CFG_IPC_DL_MAILBOX_BYTES: + cfg->ipc_dl_mailbox_bytes = *tlv->value; + break; + + case AVS_FW_CFG_IPC_UL_MAILBOX_BYTES: + cfg->ipc_ul_mailbox_bytes = *tlv->value; + break; + + case AVS_FW_CFG_TRACE_LOG_BYTES: + cfg->trace_log_bytes = *tlv->value; + break; + + case AVS_FW_CFG_MAX_PPL_COUNT: + cfg->max_ppl_count = *tlv->value; + break; + + case AVS_FW_CFG_MAX_ASTATE_COUNT: + cfg->max_astate_count = *tlv->value; + break; + + case AVS_FW_CFG_MAX_MODULE_PIN_COUNT: + cfg->max_module_pin_count = *tlv->value; + break; + + case AVS_FW_CFG_MODULES_COUNT: + cfg->modules_count = *tlv->value; + break; + + case AVS_FW_CFG_MAX_MOD_INST_COUNT: + cfg->max_mod_inst_count = *tlv->value; + break; + + case AVS_FW_CFG_MAX_LL_TASKS_PER_PRI_COUNT: + cfg->max_ll_tasks_per_pri_count = *tlv->value; + break; + + case AVS_FW_CFG_LL_PRI_COUNT: + cfg->ll_pri_count = *tlv->value; + break; + + case AVS_FW_CFG_MAX_DP_TASKS_COUNT: + cfg->max_dp_tasks_count = *tlv->value; + break; + + case AVS_FW_CFG_MAX_LIBS_COUNT: + cfg->max_libs_count = *tlv->value; + break; + + case AVS_FW_CFG_XTAL_FREQ_HZ: + cfg->xtal_freq_hz = *tlv->value; + break; + + case AVS_FW_CFG_POWER_GATING_POLICY: + cfg->power_gating_policy = *tlv->value; + break; + + /* Known but not useful to us. */ + case AVS_FW_CFG_DMA_BUFFER_CONFIG: + case AVS_FW_CFG_SCHEDULER_CONFIG: + case AVS_FW_CFG_CLOCKS_CONFIG: + break; + + default: + dev_info(adev->dev, "Unrecognized fw param: %d\n", + tlv->type); + break; + } + + offset += sizeof(*tlv) + tlv->length; + } + + /* No longer needed, free it as it's owned by the get_large_config() caller. */ + kfree(payload); + return ret; +} + +int avs_ipc_get_hw_config(struct avs_dev *adev, struct avs_hw_cfg *cfg) +{ + struct avs_tlv *tlv; + size_t payload_size; + size_t size, offset = 0; + u8 *payload; + int ret; + + ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, + AVS_BASEFW_HARDWARE_CONFIG, NULL, 0, + &payload, &payload_size); + if (ret) + return ret; + + while (offset < payload_size) { + tlv = (struct avs_tlv *)(payload + offset); + + switch (tlv->type) { + case AVS_HW_CFG_AVS_VER: + cfg->avs_version = *tlv->value; + break; + + case AVS_HW_CFG_DSP_CORES: + cfg->dsp_cores = *tlv->value; + break; + + case AVS_HW_CFG_MEM_PAGE_BYTES: + cfg->mem_page_bytes = *tlv->value; + break; + + case AVS_HW_CFG_TOTAL_PHYS_MEM_PAGES: + cfg->total_phys_mem_pages = *tlv->value; + break; + + case AVS_HW_CFG_I2S_CAPS: + cfg->i2s_caps.i2s_version = tlv->value[0]; + size = tlv->value[1]; + cfg->i2s_caps.ctrl_count = size; + if (!size) + break; + + /* Multiply to get entire array size. */ + size *= sizeof(*cfg->i2s_caps.ctrl_base_addr); + cfg->i2s_caps.ctrl_base_addr = devm_kmemdup(adev->dev, + &tlv->value[2], + size, GFP_KERNEL); + if (!cfg->i2s_caps.ctrl_base_addr) { + ret = -ENOMEM; + goto exit; + } + break; + + case AVS_HW_CFG_GATEWAY_COUNT: + cfg->gateway_count = *tlv->value; + break; + + case AVS_HW_CFG_HP_EBB_COUNT: + cfg->hp_ebb_count = *tlv->value; + break; + + case AVS_HW_CFG_LP_EBB_COUNT: + cfg->lp_ebb_count = *tlv->value; + break; + + case AVS_HW_CFG_EBB_SIZE_BYTES: + cfg->ebb_size_bytes = *tlv->value; + break; + + case AVS_HW_CFG_GPDMA_CAPS: + break; + + default: + dev_info(adev->dev, "Unrecognized hw config: %d\n", + tlv->type); + break; + } + + offset += sizeof(*tlv) + tlv->length; + } + +exit: + /* No longer needed, free it as it's owned by the get_large_config() caller. */ + kfree(payload); + return ret; +} + +int avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info) +{ + size_t payload_size; + u8 *payload; + int ret; + + ret = avs_ipc_get_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, + AVS_BASEFW_MODULES_INFO, NULL, 0, + &payload, &payload_size); + if (ret) + return ret; + + *info = (struct avs_mods_info *)payload; + return 0; +} diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 615a61cef4f6..67ba0a6347a1 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -319,4 +319,183 @@ struct avs_dxstate_info { int avs_ipc_set_dx(struct avs_dev *adev, u32 core_mask, bool powerup); int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming); +/* Base-firmware runtime parameters */ + +#define AVS_BASEFW_MOD_ID 0 +#define AVS_BASEFW_INST_ID 0 + +enum avs_basefw_runtime_param { + AVS_BASEFW_FIRMWARE_CONFIG = 7, + AVS_BASEFW_HARDWARE_CONFIG = 8, + AVS_BASEFW_MODULES_INFO = 9, + AVS_BASEFW_LIBRARIES_INFO = 16, +}; + +struct avs_fw_version { + u16 major; + u16 minor; + u16 hotfix; + u16 build; +}; + +enum avs_fw_cfg_params { + AVS_FW_CFG_FW_VERSION = 0, + AVS_FW_CFG_MEMORY_RECLAIMED, + AVS_FW_CFG_SLOW_CLOCK_FREQ_HZ, + AVS_FW_CFG_FAST_CLOCK_FREQ_HZ, + AVS_FW_CFG_DMA_BUFFER_CONFIG, + AVS_FW_CFG_ALH_SUPPORT_LEVEL, + AVS_FW_CFG_IPC_DL_MAILBOX_BYTES, + AVS_FW_CFG_IPC_UL_MAILBOX_BYTES, + AVS_FW_CFG_TRACE_LOG_BYTES, + AVS_FW_CFG_MAX_PPL_COUNT, + AVS_FW_CFG_MAX_ASTATE_COUNT, + AVS_FW_CFG_MAX_MODULE_PIN_COUNT, + AVS_FW_CFG_MODULES_COUNT, + AVS_FW_CFG_MAX_MOD_INST_COUNT, + AVS_FW_CFG_MAX_LL_TASKS_PER_PRI_COUNT, + AVS_FW_CFG_LL_PRI_COUNT, + AVS_FW_CFG_MAX_DP_TASKS_COUNT, + AVS_FW_CFG_MAX_LIBS_COUNT, + AVS_FW_CFG_SCHEDULER_CONFIG, + AVS_FW_CFG_XTAL_FREQ_HZ, + AVS_FW_CFG_CLOCKS_CONFIG, + AVS_FW_CFG_RESERVED, + AVS_FW_CFG_POWER_GATING_POLICY, + AVS_FW_CFG_ASSERT_MODE, +}; + +struct avs_fw_cfg { + struct avs_fw_version fw_version; + u32 memory_reclaimed; + u32 slow_clock_freq_hz; + u32 fast_clock_freq_hz; + u32 alh_support; + u32 ipc_dl_mailbox_bytes; + u32 ipc_ul_mailbox_bytes; + u32 trace_log_bytes; + u32 max_ppl_count; + u32 max_astate_count; + u32 max_module_pin_count; + u32 modules_count; + u32 max_mod_inst_count; + u32 max_ll_tasks_per_pri_count; + u32 ll_pri_count; + u32 max_dp_tasks_count; + u32 max_libs_count; + u32 xtal_freq_hz; + u32 power_gating_policy; +}; + +int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg); + +enum avs_hw_cfg_params { + AVS_HW_CFG_AVS_VER, + AVS_HW_CFG_DSP_CORES, + AVS_HW_CFG_MEM_PAGE_BYTES, + AVS_HW_CFG_TOTAL_PHYS_MEM_PAGES, + AVS_HW_CFG_I2S_CAPS, + AVS_HW_CFG_GPDMA_CAPS, + AVS_HW_CFG_GATEWAY_COUNT, + AVS_HW_CFG_HP_EBB_COUNT, + AVS_HW_CFG_LP_EBB_COUNT, + AVS_HW_CFG_EBB_SIZE_BYTES, +}; + +enum avs_iface_version { + AVS_AVS_VER_1_5 = 0x10005, + AVS_AVS_VER_1_8 = 0x10008, +}; + +enum avs_i2s_version { + AVS_I2S_VER_15_SKYLAKE = 0x00000, + AVS_I2S_VER_15_BROXTON = 0x10000, + AVS_I2S_VER_15_BROXTON_P = 0x20000, + AVS_I2S_VER_18_KBL_CNL = 0x30000, +}; + +struct avs_i2s_caps { + u32 i2s_version; + u32 ctrl_count; + u32 *ctrl_base_addr; +}; + +struct avs_hw_cfg { + u32 avs_version; + u32 dsp_cores; + u32 mem_page_bytes; + u32 total_phys_mem_pages; + struct avs_i2s_caps i2s_caps; + u32 gateway_count; + u32 hp_ebb_count; + u32 lp_ebb_count; + u32 ebb_size_bytes; +}; + +int avs_ipc_get_hw_config(struct avs_dev *adev, struct avs_hw_cfg *cfg); + +#define AVS_MODULE_LOAD_TYPE_BUILTIN 0 +#define AVS_MODULE_LOAD_TYPE_LOADABLE 1 +#define AVS_MODULE_STATE_LOADED BIT(0) + +struct avs_module_type { + u32 load_type:4; + u32 auto_start:1; + u32 domain_ll:1; + u32 domain_dp:1; + u32 lib_code:1; + u32 rsvd:24; +} __packed; + +union avs_segment_flags { + u32 ul; + struct { + u32 contents:1; + u32 alloc:1; + u32 load:1; + u32 readonly:1; + u32 code:1; + u32 data:1; + u32 rsvd_1:2; + u32 type:4; + u32 rsvd_2:4; + u32 length:16; + }; +} __packed; + +struct avs_segment_desc { + union avs_segment_flags flags; + u32 v_base_addr; + u32 file_offset; +} __packed; + +struct avs_module_entry { + u16 module_id; + u16 state_flags; + u8 name[8]; + guid_t uuid; + struct avs_module_type type; + u8 hash[32]; + u32 entry_point; + u16 cfg_offset; + u16 cfg_count; + u32 affinity_mask; + u16 instance_max_count; + u16 instance_bss_size; + struct avs_segment_desc segments[3]; +} __packed; + +struct avs_mods_info { + u32 count; + struct avs_module_entry entries[]; +} __packed; + +static inline bool avs_module_entry_is_loaded(struct avs_module_entry *mentry) +{ + return mentry->type.load_type == AVS_MODULE_LOAD_TYPE_BUILTIN || + mentry->state_flags & AVS_MODULE_STATE_LOADED; +} + +int avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info); + #endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */ From patchwork Wed Mar 9 20:40:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550543 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id ADB39C433F5 for ; Wed, 9 Mar 2022 20:34:32 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id EABE81899; Wed, 9 Mar 2022 21:33:40 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz EABE81899 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858071; bh=igP4IbkxiRcR4CtjK9wm55OF+HvFd8aeJ2uD3T+LoqQ=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=CH1cBSC8wUyJcjVTPwM/GRse+PQ2880KEj5F+DuISOiI0Px+SN94GYmBGZUbbQ0kX BkMjLgQGlZ997AKUhuZXTwt77q3IezVuyKB2tOOhltT7r5D2tCg32OYhI3OAi1OagS Gw2ClnV9O9ns92XFw0E7hrqJol8XIa70os9RGazU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id E822DF80566; Wed, 9 Mar 2022 21:30:43 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id E3DA9F80567; Wed, 9 Mar 2022 21:30:42 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id CF3CBF80557 for ; Wed, 9 Mar 2022 21:30:35 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz CF3CBF80557 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="T2IUCiM7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857837; x=1678393837; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=igP4IbkxiRcR4CtjK9wm55OF+HvFd8aeJ2uD3T+LoqQ=; b=T2IUCiM7vI3mgwB0/10VALxADTLVh9+KjLLagWDhivPDtf2dnck9zzd1 TMAer6ZAOw2pVsfG3KKO/adq7UU8qUWUZbymiWRAjNNdWq8pfvo70tpmt IiSoKWcoFG0D2CehmWCNBS/Y/kqu9l7E9YMkg4YOqbkf2jfdN5ZGsQx31 uhNz/rjUL4/GLj8UG7g8PUQnISc28p4lx07O6iBdCRYaYf0ovEwNa0gSy R8fqOTWVLqCmvJlEFD8NMms0sMvlE/Ow62BmfbSArVuui7nHLkqBHlki5 3SlTTEaRPJZf278lDiuWBEGS4wHFzmto+HUz5BrObdjHucwlVoY+MTVEW Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028790" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028790" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527220" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:31 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 11/17] ASoC: Intel: avs: Firmware resources management utilities Date: Wed, 9 Mar 2022 21:40:23 +0100 Message-Id: <20220309204029.89040-12-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" With basefw runtime parameter handlers added, implement utility functions to ease pipelines and modules allocation. IDA is enlisted to help with that. As firmware is modular and multiple binaries can be loaded on-demand depending on the streaming scenario, custom firmware caching mechanism is added. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/Makefile | 2 +- sound/soc/intel/avs/avs.h | 37 +++++ sound/soc/intel/avs/utils.c | 301 +++++++++++++++++++++++++++++++++++ 3 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/avs/utils.c diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile index c0824f30fd3b..d9f92c5f5407 100644 --- a/sound/soc/intel/avs/Makefile +++ b/sound/soc/intel/avs/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-avs-objs := dsp.o ipc.o messages.o +snd-soc-avs-objs := dsp.o ipc.o messages.o utils.o obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 841b8541b101..02d7591d0eac 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -53,12 +53,26 @@ struct avs_spec { const u32 rom_status; }; +struct avs_fw_entry { + char *name; + const struct firmware *fw; + + struct list_head node; +}; + /* * struct avs_dev - Intel HD-Audio driver data * * @dev: PCI device * @dsp_ba: DSP bar address * @spec: platform-specific descriptor + * @fw_cfg: Firmware configuration, obtained through FW_CONFIG message + * @hw_cfg: Hardware configuration, obtained through HW_CONFIG message + * @mods_info: Available module-types, obtained through MODULES_INFO message + * @mod_idas: Module instance ID pool, one per module-type + * @modres_mutex: For synchronizing any @mods_info updates + * @ppl_ida: Pipeline instance ID pool + * @fw_list: List of libraries loaded, including base firmware */ struct avs_dev { struct hda_bus base; @@ -68,6 +82,14 @@ struct avs_dev { const struct avs_spec *spec; struct avs_ipc *ipc; + struct avs_fw_cfg fw_cfg; + struct avs_hw_cfg hw_cfg; + struct avs_mods_info *mods_info; + struct ida **mod_idas; + struct mutex modres_mutex; + struct ida ppl_ida; + struct list_head fw_list; + struct completion fw_ready; }; @@ -168,4 +190,19 @@ void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable); int avs_ipc_init(struct avs_ipc *ipc, struct device *dev); void avs_ipc_block(struct avs_ipc *ipc); +/* Firmware resources management */ + +int avs_get_module_entry(struct avs_dev *adev, const guid_t *uuid, struct avs_module_entry *entry); +int avs_get_module_id_entry(struct avs_dev *adev, u32 module_id, struct avs_module_entry *entry); +int avs_get_module_id(struct avs_dev *adev, const guid_t *uuid); +bool avs_is_module_ida_empty(struct avs_dev *adev, u32 module_id); + +int avs_module_info_init(struct avs_dev *adev, bool purge); +void avs_module_info_free(struct avs_dev *adev); +int avs_module_id_alloc(struct avs_dev *adev, u16 module_id); +void avs_module_id_free(struct avs_dev *adev, u16 module_id, u8 instance_id); +int avs_request_firmware(struct avs_dev *adev, const struct firmware **fw_p, const char *name); +void avs_release_last_firmware(struct avs_dev *adev); +void avs_release_firmwares(struct avs_dev *adev); + #endif /* __SOUND_SOC_INTEL_AVS_H */ diff --git a/sound/soc/intel/avs/utils.c b/sound/soc/intel/avs/utils.c new file mode 100644 index 000000000000..580f3e43fa12 --- /dev/null +++ b/sound/soc/intel/avs/utils.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include "avs.h" +#include "messages.h" + +/* Caller responsible for holding adev->modres_mutex. */ +static int avs_module_entry_index(struct avs_dev *adev, const guid_t *uuid) +{ + int i; + + for (i = 0; i < adev->mods_info->count; i++) { + struct avs_module_entry *module; + + module = &adev->mods_info->entries[i]; + if (guid_equal(&module->uuid, uuid)) + return i; + } + + return -ENOENT; +} + +/* Caller responsible for holding adev->modres_mutex. */ +static int avs_module_id_entry_index(struct avs_dev *adev, u32 module_id) +{ + int i; + + for (i = 0; i < adev->mods_info->count; i++) { + struct avs_module_entry *module; + + module = &adev->mods_info->entries[i]; + if (module->module_id == module_id) + return i; + } + + return -ENOENT; +} + +int avs_get_module_entry(struct avs_dev *adev, const guid_t *uuid, struct avs_module_entry *entry) +{ + int idx; + + mutex_lock(&adev->modres_mutex); + + idx = avs_module_entry_index(adev, uuid); + if (idx >= 0) + memcpy(entry, &adev->mods_info->entries[idx], sizeof(*entry)); + + mutex_unlock(&adev->modres_mutex); + return (idx < 0) ? idx : 0; +} + +int avs_get_module_id_entry(struct avs_dev *adev, u32 module_id, struct avs_module_entry *entry) +{ + int idx; + + mutex_lock(&adev->modres_mutex); + + idx = avs_module_id_entry_index(adev, module_id); + if (idx >= 0) + memcpy(entry, &adev->mods_info->entries[idx], sizeof(*entry)); + + mutex_unlock(&adev->modres_mutex); + return (idx < 0) ? idx : 0; +} + +int avs_get_module_id(struct avs_dev *adev, const guid_t *uuid) +{ + struct avs_module_entry module; + int ret; + + ret = avs_get_module_entry(adev, uuid, &module); + return !ret ? module.module_id : -ENOENT; +} + +bool avs_is_module_ida_empty(struct avs_dev *adev, u32 module_id) +{ + bool ret = false; + int idx; + + mutex_lock(&adev->modres_mutex); + + idx = avs_module_id_entry_index(adev, module_id); + if (idx >= 0) + ret = ida_is_empty(adev->mod_idas[idx]); + + mutex_unlock(&adev->modres_mutex); + return ret; +} + +/* Caller responsible for holding adev->modres_mutex. */ +static void avs_module_ida_destroy(struct avs_dev *adev) +{ + int i = adev->mods_info ? adev->mods_info->count : 0; + + while (i--) { + ida_destroy(adev->mod_idas[i]); + kfree(adev->mod_idas[i]); + } + kfree(adev->mod_idas); +} + +/* Caller responsible for holding adev->modres_mutex. */ +static int +avs_module_ida_alloc(struct avs_dev *adev, struct avs_mods_info *newinfo, bool purge) +{ + struct avs_mods_info *oldinfo = adev->mods_info; + struct ida **ida_ptrs; + u32 tocopy_count = 0; + int i; + + if (!purge && oldinfo) { + if (oldinfo->count >= newinfo->count) + dev_warn(adev->dev, "refreshing %d modules info with %d\n", + oldinfo->count, newinfo->count); + tocopy_count = oldinfo->count; + } + + ida_ptrs = kcalloc(newinfo->count, sizeof(*ida_ptrs), GFP_KERNEL); + if (!ida_ptrs) + return -ENOMEM; + + if (tocopy_count) + memcpy(ida_ptrs, adev->mod_idas, tocopy_count * sizeof(*ida_ptrs)); + + for (i = tocopy_count; i < newinfo->count; i++) { + ida_ptrs[i] = kzalloc(sizeof(**ida_ptrs), GFP_KERNEL); + if (!ida_ptrs[i]) { + while (i--) + kfree(ida_ptrs[i]); + + kfree(ida_ptrs); + return -ENOMEM; + } + + ida_init(ida_ptrs[i]); + } + + /* If old elements have been reused, don't wipe them. */ + if (tocopy_count) + kfree(adev->mod_idas); + else + avs_module_ida_destroy(adev); + + adev->mod_idas = ida_ptrs; + return 0; +} + +int avs_module_info_init(struct avs_dev *adev, bool purge) +{ + struct avs_mods_info *info; + int ret; + + ret = avs_ipc_get_modules_info(adev, &info); + if (ret) + return AVS_IPC_RET(ret); + + mutex_lock(&adev->modres_mutex); + + ret = avs_module_ida_alloc(adev, info, purge); + if (ret < 0) { + dev_err(adev->dev, "initialize module idas failed: %d\n", ret); + goto exit; + } + + /* Refresh current information with newly received table. */ + kfree(adev->mods_info); + adev->mods_info = info; + +exit: + mutex_unlock(&adev->modres_mutex); + return ret; +} + +void avs_module_info_free(struct avs_dev *adev) +{ + mutex_lock(&adev->modres_mutex); + + avs_module_ida_destroy(adev); + kfree(adev->mods_info); + adev->mods_info = NULL; + + mutex_unlock(&adev->modres_mutex); +} + +int avs_module_id_alloc(struct avs_dev *adev, u16 module_id) +{ + int ret, idx, max_id; + + mutex_lock(&adev->modres_mutex); + + idx = avs_module_id_entry_index(adev, module_id); + if (idx == -ENOENT) { + WARN(1, "invalid module id: %d", module_id); + ret = -EINVAL; + goto exit; + } + max_id = adev->mods_info->entries[idx].instance_max_count - 1; + ret = ida_alloc_max(adev->mod_idas[idx], max_id, GFP_KERNEL); +exit: + mutex_unlock(&adev->modres_mutex); + return ret; +} + +void avs_module_id_free(struct avs_dev *adev, u16 module_id, u8 instance_id) +{ + int idx; + + mutex_lock(&adev->modres_mutex); + + idx = avs_module_id_entry_index(adev, module_id); + if (idx == -ENOENT) { + WARN(1, "invalid module id: %d", module_id); + goto exit; + } + + ida_free(adev->mod_idas[idx], instance_id); +exit: + mutex_unlock(&adev->modres_mutex); +} + +/* + * Once driver loads FW it should keep it in memory, so we are not affected + * by FW removal from filesystem or even worse by loading different FW at + * runtime suspend/resume. + */ +int avs_request_firmware(struct avs_dev *adev, const struct firmware **fw_p, const char *name) +{ + struct avs_fw_entry *entry; + int ret; + + /* first check in list if it is not already loaded */ + list_for_each_entry(entry, &adev->fw_list, node) { + if (!strcmp(name, entry->name)) { + *fw_p = entry->fw; + return 0; + } + } + + /* FW is not loaded, let's load it now and add to the list */ + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->name = kstrdup(name, GFP_KERNEL); + if (!entry->name) { + kfree(entry); + return -ENOMEM; + } + + ret = request_firmware(&entry->fw, name, adev->dev); + if (ret < 0) { + kfree(entry->name); + kfree(entry); + return ret; + } + + *fw_p = entry->fw; + + list_add_tail(&entry->node, &adev->fw_list); + + return 0; +} + +/* + * Release single FW entry, used to handle errors in functions calling + * avs_request_firmware() + */ +void avs_release_last_firmware(struct avs_dev *adev) +{ + struct avs_fw_entry *entry; + + entry = list_last_entry(&adev->fw_list, typeof(*entry), node); + + list_del(&entry->node); + release_firmware(entry->fw); + kfree(entry->name); + kfree(entry); +} + +/* + * Release all FW entries, used on driver removal + */ +void avs_release_firmwares(struct avs_dev *adev) +{ + struct avs_fw_entry *entry, *tmp; + + list_for_each_entry_safe(entry, tmp, &adev->fw_list, node) { + list_del(&entry->node); + release_firmware(entry->fw); + kfree(entry->name); + kfree(entry); + } +} From patchwork Wed Mar 9 20:40:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 549716 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 81A71C433EF for ; Wed, 9 Mar 2022 20:34:52 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id BE8A0184E; Wed, 9 Mar 2022 21:34:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz BE8A0184E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858090; bh=aborTyJbTZ+EgyNWBBI/mtktpY9K8kFDpj13SBU1n0c=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=VuN3v4J8kcNa10oKf8tpDOaC5+EiZX5Sjs3SyrfB0XCRRyLVNEq3z59Y5rg9sFyik pdVtdoIjCkwuzRX0FW97NJp11lKhHTwtLYO+K20riHu2sAri6sPE2vHhw5FlppdqNX 84ggeZYv+HxevCZY74O2W9Jr4rVacTuhC2sAtpTM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 677EEF80568; Wed, 9 Mar 2022 21:30:44 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5F8A4F80567; Wed, 9 Mar 2022 21:30:43 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 63C9BF8055B for ; Wed, 9 Mar 2022 21:30:39 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 63C9BF8055B Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="e5nZkrxn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857840; x=1678393840; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aborTyJbTZ+EgyNWBBI/mtktpY9K8kFDpj13SBU1n0c=; b=e5nZkrxniNpJVX11oufRLyCZ1pSfB5J7cbsbXm86Vm8RZmWExfxTlome 5t1WXUID4iNWV4ooWVxJkdmg2FLXtDzoUrpt9i078loOlq9zfx8LWJhXi QuV5PREeRZTUjuUaJajckrremLr7jarqfaGZIPlxD57zdRK/tj6dtocFx bu9Ixc18gEnu4/qICgzFk3bt2Yg9mgmTP4PZFrHmSgBuECPw1VT5eOpXW ku4v6Ar+AzH3VlC2HGW2MZ4q8nFF0Wxm04+TRK1aEpS2lmIuSmLNZYzSp bvvWdTXUO8w9moL5oSUvLG3AR11RlcPLetkstb0QCQ0csKI8p24MgwqNV g==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028807" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028807" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:38 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527246" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:35 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 12/17] ASoC: Intel: avs: Declare module configuration types Date: Wed, 9 Mar 2022 21:40:24 +0100 Message-Id: <20220309204029.89040-13-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Declare structures and constants for all modules being part of basefw binary. These are used in streaming operations to communicate the needs of software to firmware side. While adding module types, append handler for SET_SINK_FORMAT runtime for COPIER module which allows for configuration of output pin other than the default one (0). Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/messages.c | 17 +++ sound/soc/intel/avs/messages.h | 252 +++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index 4e7a2972da6d..9eaaf717cb54 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -680,3 +680,20 @@ int avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info) *info = (struct avs_mods_info *)payload; return 0; } + +int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id, + u8 instance_id, u32 sink_id, + const struct avs_audio_format *src_fmt, + const struct avs_audio_format *sink_fmt) +{ + struct avs_copier_sink_format cpr_fmt; + + cpr_fmt.sink_id = sink_id; + /* Firmware expects driver to resend copier's input format. */ + cpr_fmt.src_fmt = *src_fmt; + cpr_fmt.sink_fmt = *sink_fmt; + + return avs_ipc_set_large_config(adev, module_id, instance_id, + AVS_COPIER_SET_SINK_FORMAT, + (u8 *)&cpr_fmt, sizeof(cpr_fmt)); +} diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 67ba0a6347a1..966139e9663d 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -498,4 +498,256 @@ static inline bool avs_module_entry_is_loaded(struct avs_module_entry *mentry) int avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info); +/* Module configuration */ + +#define AVS_MIXIN_MOD_UUID \ + GUID_INIT(0x39656EB2, 0x3B71, 0x4049, 0x8D, 0x3F, 0xF9, 0x2C, 0xD5, 0xC4, 0x3C, 0x09) + +#define AVS_MIXOUT_MOD_UUID \ + GUID_INIT(0x3C56505A, 0x24D7, 0x418F, 0xBD, 0xDC, 0xC1, 0xF5, 0xA3, 0xAC, 0x2A, 0xE0) + +#define AVS_COPIER_MOD_UUID \ + GUID_INIT(0x9BA00C83, 0xCA12, 0x4A83, 0x94, 0x3C, 0x1F, 0xA2, 0xE8, 0x2F, 0x9D, 0xDA) + +#define AVS_KPBUFF_MOD_UUID \ + GUID_INIT(0xA8A0CB32, 0x4A77, 0x4DB1, 0x85, 0xC7, 0x53, 0xD7, 0xEE, 0x07, 0xBC, 0xE6) + +#define AVS_MICSEL_MOD_UUID \ + GUID_INIT(0x32FE92C1, 0x1E17, 0x4FC2, 0x97, 0x58, 0xC7, 0xF3, 0x54, 0x2E, 0x98, 0x0A) + +#define AVS_MUX_MOD_UUID \ + GUID_INIT(0x64CE6E35, 0x857A, 0x4878, 0xAC, 0xE8, 0xE2, 0xA2, 0xF4, 0x2e, 0x30, 0x69) + +#define AVS_UPDWMIX_MOD_UUID \ + GUID_INIT(0x42F8060C, 0x832F, 0x4DBF, 0xB2, 0x47, 0x51, 0xE9, 0x61, 0x99, 0x7b, 0x35) + +#define AVS_SRCINTC_MOD_UUID \ + GUID_INIT(0xE61BB28D, 0x149A, 0x4C1F, 0xB7, 0x09, 0x46, 0x82, 0x3E, 0xF5, 0xF5, 0xAE) + +#define AVS_PROBE_MOD_UUID \ + GUID_INIT(0x7CAD0808, 0xAB10, 0xCD23, 0xEF, 0x45, 0x12, 0xAB, 0x34, 0xCD, 0x56, 0xEF) + +#define AVS_AEC_MOD_UUID \ + GUID_INIT(0x46CB87FB, 0xD2C9, 0x4970, 0x96, 0xD2, 0x6D, 0x7E, 0x61, 0x4B, 0xB6, 0x05) + +#define AVS_ASRC_MOD_UUID \ + GUID_INIT(0x66B4402D, 0xB468, 0x42F2, 0x81, 0xA7, 0xB3, 0x71, 0x21, 0x86, 0x3D, 0xD4) + +#define AVS_INTELWOV_MOD_UUID \ + GUID_INIT(0xEC774FA9, 0x28D3, 0x424A, 0x90, 0xE4, 0x69, 0xF9, 0x84, 0xF1, 0xEE, 0xB7) + +/* channel map */ +enum avs_channel_index { + AVS_CHANNEL_LEFT = 0, + AVS_CHANNEL_RIGHT = 1, + AVS_CHANNEL_CENTER = 2, + AVS_CHANNEL_LEFT_SURROUND = 3, + AVS_CHANNEL_CENTER_SURROUND = 3, + AVS_CHANNEL_RIGHT_SURROUND = 4, + AVS_CHANNEL_LFE = 7, + AVS_CHANNEL_INVALID = 0xF, +}; + +enum avs_channel_config { + AVS_CHANNEL_CONFIG_MONO = 0, + AVS_CHANNEL_CONFIG_STEREO = 1, + AVS_CHANNEL_CONFIG_2_1 = 2, + AVS_CHANNEL_CONFIG_3_0 = 3, + AVS_CHANNEL_CONFIG_3_1 = 4, + AVS_CHANNEL_CONFIG_QUATRO = 5, + AVS_CHANNEL_CONFIG_4_0 = 6, + AVS_CHANNEL_CONFIG_5_0 = 7, + AVS_CHANNEL_CONFIG_5_1 = 8, + AVS_CHANNEL_CONFIG_DUAL_MONO = 9, + AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10, + AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11, + AVS_CHANNEL_CONFIG_4_CHANNEL = 12, + AVS_CHANNEL_CONFIG_INVALID +}; + +enum avs_interleaving { + AVS_INTERLEAVING_PER_CHANNEL = 0, + AVS_INTERLEAVING_PER_SAMPLE = 1, +}; + +enum avs_sample_type { + AVS_SAMPLE_TYPE_INT_MSB = 0, + AVS_SAMPLE_TYPE_INT_LSB = 1, + AVS_SAMPLE_TYPE_INT_SIGNED = 2, + AVS_SAMPLE_TYPE_INT_UNSIGNED = 3, + AVS_SAMPLE_TYPE_FLOAT = 4, +}; + +#define AVS_CHANNELS_MAX 8 +#define AVS_ALL_CHANNELS_MASK UINT_MAX + +struct avs_audio_format { + u32 sampling_freq; + u32 bit_depth; + u32 channel_map; + u32 channel_config; + u32 interleaving; + u32 num_channels:8; + u32 valid_bit_depth:8; + u32 sample_type:8; + u32 reserved:8; +} __packed; + +struct avs_modcfg_base { + u32 cpc; + u32 ibs; + u32 obs; + u32 is_pages; + struct avs_audio_format audio_fmt; +} __packed; + +struct avs_pin_format { + u32 pin_index; + u32 iobs; + struct avs_audio_format audio_fmt; +} __packed; + +struct avs_modcfg_ext { + struct avs_modcfg_base base; + u16 num_input_pins; + u16 num_output_pins; + u8 reserved[12]; + /* input pin formats followed by output ones */ + struct avs_pin_format pin_fmts[]; +} __packed; + +enum avs_dma_type { + AVS_DMA_HDA_HOST_OUTPUT = 0, + AVS_DMA_HDA_HOST_INPUT = 1, + AVS_DMA_HDA_LINK_OUTPUT = 8, + AVS_DMA_HDA_LINK_INPUT = 9, + AVS_DMA_DMIC_LINK_INPUT = 11, + AVS_DMA_I2S_LINK_OUTPUT = 12, + AVS_DMA_I2S_LINK_INPUT = 13, +}; + +union avs_virtual_index { + u8 val; + struct { + u8 time_slot:4; + u8 instance:4; + } i2s; + struct { + u8 queue_id:3; + u8 time_slot:2; + u8 instance:3; + } dmic; +} __packed; + +union avs_connector_node_id { + u32 val; + struct { + u32 vindex:8; + u32 dma_type:5; + u32 rsvd:19; + }; +} __packed; + +#define INVALID_PIPELINE_ID 0xFF +#define INVALID_NODE_ID \ + ((union avs_connector_node_id) { UINT_MAX }) + +union avs_gtw_attributes { + u32 val; + struct { + u32 lp_buffer_alloc:1; + u32 rsvd:31; + }; +} __packed; + +struct avs_copier_gtw_cfg { + union avs_connector_node_id node_id; + u32 dma_buffer_size; + u32 config_length; + struct { + union avs_gtw_attributes attrs; + u32 blob[]; + } config; +} __packed; + +struct avs_copier_cfg { + struct avs_modcfg_base base; + struct avs_audio_format out_fmt; + u32 feature_mask; + struct avs_copier_gtw_cfg gtw_cfg; +} __packed; + +struct avs_micsel_cfg { + struct avs_modcfg_base base; + struct avs_audio_format out_fmt; +} __packed; + +struct avs_mux_cfg { + struct avs_modcfg_base base; + struct avs_audio_format ref_fmt; + struct avs_audio_format out_fmt; +} __packed; + +struct avs_updown_mixer_cfg { + struct avs_modcfg_base base; + u32 out_channel_config; + u32 coefficients_select; + s32 coefficients[AVS_CHANNELS_MAX]; + u32 channel_map; +} __packed; + +struct avs_src_cfg { + struct avs_modcfg_base base; + u32 out_freq; +} __packed; + +struct avs_probe_gtw_cfg { + union avs_connector_node_id node_id; + u32 dma_buffer_size; +} __packed; + +struct avs_probe_cfg { + struct avs_modcfg_base base; + struct avs_probe_gtw_cfg gtw_cfg; +} __packed; + +struct avs_aec_cfg { + struct avs_modcfg_base base; + struct avs_audio_format ref_fmt; + struct avs_audio_format out_fmt; + u32 cpc_lp_mode; +} __packed; + +struct avs_asrc_cfg { + struct avs_modcfg_base base; + u32 out_freq; + u32 rsvd0:1; + u32 mode:1; + u32 rsvd2:2; + u32 disable_jitter_buffer:1; + u32 rsvd3:27; +} __packed; + +struct avs_wov_cfg { + struct avs_modcfg_base base; + u32 cpc_lp_mode; +} __packed; + +/* Module runtime parameters */ + +enum avs_copier_runtime_param { + AVS_COPIER_SET_SINK_FORMAT = 2, +}; + +struct avs_copier_sink_format { + u32 sink_id; + struct avs_audio_format src_fmt; + struct avs_audio_format sink_fmt; +} __packed; + +int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id, + u8 instance_id, u32 sink_id, + const struct avs_audio_format *src_fmt, + const struct avs_audio_format *sink_fmt); + #endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */ From patchwork Wed Mar 9 20:40:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550542 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id ABC98C433F5 for ; Wed, 9 Mar 2022 20:35:11 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id ECC211813; Wed, 9 Mar 2022 21:34:19 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz ECC211813 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858110; bh=RRmsMWm+Qv4JSWnHec79tr7y0iNFf2EWz9GuB/AgvTk=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=k1O9X+zQ+2mHTOm+4Gdu8L9UQ0w8h9DoRKxaSnN+zk3GA1W14rT5sJTV4paB+/x28 yDpScuw2ZsBmDzcSpJGCYHE3AaWTyPEILYiRByrvOJsvOdPuyBngVTRyw+0OD5KwKE 2rsXdNXi19mhwQsm7b+/WaoTisNy0xFTUAGZV26A= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 8731AF8056F; Wed, 9 Mar 2022 21:30:48 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 8791DF80589; Wed, 9 Mar 2022 21:30:46 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3B75EF8056F for ; Wed, 9 Mar 2022 21:30:43 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3B75EF8056F Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="BzeAYv+4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857844; x=1678393844; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RRmsMWm+Qv4JSWnHec79tr7y0iNFf2EWz9GuB/AgvTk=; b=BzeAYv+4y2M4xlcRlNldYEVEGXn4p/J9A8zLf51IaXdgqZt9IoHDZRBZ NYy+bJfSr+VXfRet387mv3E9py9EQJp92lK3VuhMa3NmmDsYylBu2k9tc Ma8sBAiDzNuQWGzVmxBHKdyBH5rjPIpGIvONF9fCRTUtz2WqySrmLTHRB wnsDrnKzqwjlnajgtdmAtmQ7G3zalUdSu9KUMPQaKTa8NjdHprVmCrtXT dxxZqNiJVMTw98XauQOhbp+gSvWhKqHCcHmgspTwx9ebkQo2M+Kb8kW62 nBwqcvMpV1Z1J1u5cKdB2vgXC4pUytbSyJTFkfcvlcEakc0041b0A9jSe g==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028819" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028819" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:42 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527258" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:39 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 13/17] ASoC: Intel: avs: Dynamic firmware resources management Date: Wed, 9 Mar 2022 21:40:25 +0100 Message-Id: <20220309204029.89040-14-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Wrap elementary DSP-core operations and resource control into more complex handlers. This is done to reduce the number of invocations of wrapped operations throughout the driver as order of operations matters - most flows involve register manipulation and IPCs combined. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/avs.h | 10 +++ sound/soc/intel/avs/dsp.c | 170 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 02d7591d0eac..2f9d6347ab0f 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -89,6 +89,7 @@ struct avs_dev { struct mutex modres_mutex; struct ida ppl_ida; struct list_head fw_list; + int *core_refs; /* reference count per core */ struct completion fw_ready; }; @@ -205,4 +206,13 @@ int avs_request_firmware(struct avs_dev *adev, const struct firmware **fw_p, con void avs_release_last_firmware(struct avs_dev *adev); void avs_release_firmwares(struct avs_dev *adev); +int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id, + u8 core_id, u8 domain, void *param, u32 param_size, + u16 *instance_id); +void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id, + u8 ppl_instance_id, u8 core_id); +int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, + bool lp, u16 attributes, u8 *instance_id); +int avs_dsp_delete_pipeline(struct avs_dev *adev, u8 instance_id); + #endif /* __SOUND_SOC_INTEL_AVS_H */ diff --git a/sound/soc/intel/avs/dsp.c b/sound/soc/intel/avs/dsp.c index eb9d941fe6cf..5994d64d2468 100644 --- a/sound/soc/intel/avs/dsp.c +++ b/sound/soc/intel/avs/dsp.c @@ -104,4 +104,174 @@ int avs_dsp_core_disable(struct avs_dev *adev, u32 core_mask) return avs_dsp_op(adev, power, core_mask, false); } +static int avs_dsp_enable(struct avs_dev *adev, u32 core_mask) +{ + u32 mask; + int ret; + + ret = avs_dsp_core_enable(adev, core_mask); + if (ret < 0) + return ret; + + mask = core_mask & ~AVS_MAIN_CORE_MASK; + if (!mask) + /* + * without main core, fw is dead anyway + * so setting D0 for it is futile. + */ + return 0; + + ret = avs_ipc_set_dx(adev, mask, true); + return AVS_IPC_RET(ret); +} + +static int avs_dsp_disable(struct avs_dev *adev, u32 core_mask) +{ + int ret; + + ret = avs_ipc_set_dx(adev, core_mask, false); + if (ret) + return AVS_IPC_RET(ret); + + return avs_dsp_core_disable(adev, core_mask); +} + +static int avs_dsp_get_core(struct avs_dev *adev, u32 core_id) +{ + u32 mask; + int ret; + + mask = BIT_MASK(core_id); + if (mask == AVS_MAIN_CORE_MASK) + /* nothing to do for main core */ + return 0; + if (core_id >= adev->hw_cfg.dsp_cores) { + ret = -EINVAL; + goto err; + } + + adev->core_refs[core_id]++; + if (adev->core_refs[core_id] == 1) { + ret = avs_dsp_enable(adev, mask); + if (ret) + goto err_enable_dsp; + } + + return 0; + +err_enable_dsp: + adev->core_refs[core_id]--; +err: + dev_err(adev->dev, "get core %d failed: %d\n", core_id, ret); + return ret; +} + +static int avs_dsp_put_core(struct avs_dev *adev, u32 core_id) +{ + u32 mask; + int ret; + + mask = BIT_MASK(core_id); + if (mask == AVS_MAIN_CORE_MASK) + /* nothing to do for main core */ + return 0; + if (core_id >= adev->hw_cfg.dsp_cores) { + ret = -EINVAL; + goto err; + } + + adev->core_refs[core_id]--; + if (!adev->core_refs[core_id]) { + ret = avs_dsp_disable(adev, mask); + if (ret) + goto err; + } + + return 0; +err: + dev_err(adev->dev, "put core %d failed: %d\n", core_id, ret); + return ret; +} + +int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id, + u8 core_id, u8 domain, void *param, u32 param_size, + u16 *instance_id) +{ + struct avs_module_entry mentry; + int ret, id; + + id = avs_module_id_alloc(adev, module_id); + if (id < 0) + return id; + + ret = avs_get_module_id_entry(adev, module_id, &mentry); + if (ret) + goto err_mod_entry; + + ret = avs_dsp_get_core(adev, core_id); + if (ret) + goto err_mod_entry; + + ret = avs_ipc_init_instance(adev, module_id, id, ppl_instance_id, + core_id, domain, param, param_size); + if (ret) { + ret = AVS_IPC_RET(ret); + goto err_ipc; + } + + *instance_id = id; + return 0; + +err_ipc: + avs_dsp_put_core(adev, core_id); +err_mod_entry: + avs_module_id_free(adev, module_id, id); + return ret; +} + +void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id, + u8 ppl_instance_id, u8 core_id) +{ + /* Modules not owned by any pipeline need to be freed explicitly. */ + if (ppl_instance_id == INVALID_PIPELINE_ID) + avs_ipc_delete_instance(adev, module_id, instance_id); + + avs_module_id_free(adev, module_id, instance_id); + + avs_dsp_put_core(adev, core_id); +} + +int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, + bool lp, u16 attributes, u8 *instance_id) +{ + struct avs_fw_cfg *fw_cfg = &adev->fw_cfg; + int ret, id; + + id = ida_alloc_max(&adev->ppl_ida, fw_cfg->max_ppl_count - 1, GFP_KERNEL); + if (id < 0) + return id; + + ret = avs_ipc_create_pipeline(adev, req_size, priority, id, lp, + attributes); + if (ret) { + ida_free(&adev->ppl_ida, id); + return AVS_IPC_RET(ret); + } + + *instance_id = id; + return 0; +} + +int avs_dsp_delete_pipeline(struct avs_dev *adev, u8 instance_id) +{ + int ret; + + ret = avs_ipc_delete_pipeline(adev, instance_id); + if (ret) + ret = AVS_IPC_RET(ret); + + ida_free(&adev->ppl_ida, instance_id); + return ret; +} + MODULE_LICENSE("GPL"); From patchwork Wed Mar 9 20:40:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 549715 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6772CC433EF for ; Wed, 9 Mar 2022 20:35:24 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 9BD7618B2; Wed, 9 Mar 2022 21:34:32 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 9BD7618B2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858122; bh=w8MCgofBZ0qvLyGl1bASCUsTs173v7s+eTmU/BrNtQ4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=cSmCHKl+xM2k1t+00xlE7R2hECWISWN39U7zKXEH1ApyUMKJZ3u67Jb+Y18R9Vhiy z5/Em29W6Ij49f+EnnkytsI4A7PpXAF5678fqSSFd0kBDTD9NbqxZcd0s4syNsx/rY lAi0NE7tFZ3C2CTlg73UDyB4D7tPtfyzy+5GGK9k= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 21C74F805A0; Wed, 9 Mar 2022 21:30:55 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1C11CF805A1; Wed, 9 Mar 2022 21:30:54 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C260BF8057D for ; Wed, 9 Mar 2022 21:30:46 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C260BF8057D Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="W00BvxXN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857847; x=1678393847; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=w8MCgofBZ0qvLyGl1bASCUsTs173v7s+eTmU/BrNtQ4=; b=W00BvxXNyam1RN7sT9oMGOs+NldUYeoyDYF5wGqDlpSsw9zvy551rc64 2Me6NojSuLJrjHE2ki8L7dlaPdK4qBMdpLe8zWpM2cWB6qj405cL2M+dg kWHgliuhcYi6ao1qIbB43dBd3rX0rEuEAlZ1CRWOBhD4gXP7m06AVAv0r mhhkrqDWTWt/CEcqchXR+AE8rLrKUdbUUPXNjrbDh2By7jDF62XrHqmBT mvAaDvA2WUS3D6+/0Augu1zLIrnTkaegP6QcgQV3sDXj1aup7HIzfhd/t 6bOJwuSabV0yrMMa9jb0wkFkHdqd//ZWyHp+tpBKZIDRkF8NtY5sXa6Kk Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028828" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028828" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:46 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527282" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:42 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 14/17] ASoC: Intel: avs: General code loading flow Date: Wed, 9 Mar 2022 21:40:26 +0100 Message-Id: <20220309204029.89040-15-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Code loading is a complex procedure and requires combined effort of DMA and IPCs. With IPCs already in place, lay out ground for specific DMA transfer operations. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/Makefile | 2 +- sound/soc/intel/avs/avs.h | 18 +++ sound/soc/intel/avs/core.c | 62 +++++++++ sound/soc/intel/avs/dsp.c | 26 ++++ sound/soc/intel/avs/loader.c | 237 ++++++++++++++++++++++++++++++++ sound/soc/intel/avs/registers.h | 6 + 6 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/avs/core.c create mode 100644 sound/soc/intel/avs/loader.c diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile index d9f92c5f5407..d9c793160612 100644 --- a/sound/soc/intel/avs/Makefile +++ b/sound/soc/intel/avs/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-avs-objs := dsp.o ipc.o messages.o utils.o +snd-soc-avs-objs := dsp.o ipc.o messages.o utils.o core.o loader.o obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 2f9d6347ab0f..21a161c2443d 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -10,8 +10,11 @@ #define __SOUND_SOC_INTEL_AVS_H #include +#include #include +#include #include "messages.h" +#include "registers.h" struct avs_dev; @@ -32,6 +35,10 @@ struct avs_dsp_ops { irqreturn_t (* const irq_handler)(int, void *); irqreturn_t (* const irq_thread)(int, void *); void (* const int_control)(struct avs_dev *, bool); + int (* const load_basefw)(struct avs_dev *, struct firmware *); + int (* const load_lib)(struct avs_dev *, struct firmware *, u32); + int (* const transfer_mods)(struct avs_dev *, bool, + struct avs_module_entry *, u32); }; #define avs_dsp_op(adev, op, ...) \ @@ -45,6 +52,7 @@ struct avs_spec { const char *name; const struct avs_dsp_ops *const dsp_ops; + struct avs_fw_version min_fw_version; /* anything below is rejected */ const u32 core_init_mask; /* used during DSP boot */ const u64 attributes; /* bitmask of AVS_PLATATTR_* */ @@ -90,6 +98,7 @@ struct avs_dev { struct ida ppl_ida; struct list_head fw_list; int *core_refs; /* reference count per core */ + char **lib_names; struct completion fw_ready; }; @@ -215,4 +224,13 @@ int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, bool lp, u16 attributes, u8 *instance_id); int avs_dsp_delete_pipeline(struct avs_dev *adev, u8 instance_id); +/* Firmware loading */ + +void avs_hda_clock_gating_enable(struct avs_dev *adev, bool enable); +void avs_hda_power_gating_enable(struct avs_dev *adev, bool enable); +void avs_hda_l1sen_enable(struct avs_dev *adev, bool enable); + +int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge); +int avs_dsp_first_boot_firmware(struct avs_dev *adev); + #endif /* __SOUND_SOC_INTEL_AVS_H */ diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c new file mode 100644 index 000000000000..117b31ef9cd0 --- /dev/null +++ b/sound/soc/intel/avs/core.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// +// Special thanks to: +// Krzysztof Hejmowski +// Michal Sienkiewicz +// Filip Proborszcz +// +// for sharing Intel AudioDSP expertise and helping shape the very +// foundation of this driver +// + +#include +#include +#include "avs.h" + +static void +avs_hda_update_config_dword(struct hdac_bus *bus, u32 reg, u32 mask, u32 value) +{ + struct pci_dev *pci = to_pci_dev(bus->dev); + u32 data; + + pci_read_config_dword(pci, reg, &data); + data &= ~mask; + data |= (value & mask); + pci_write_config_dword(pci, reg, data); +} + +void avs_hda_power_gating_enable(struct avs_dev *adev, bool enable) +{ + u32 value; + + value = enable ? 0 : AZX_PGCTL_LSRMD_MASK; + avs_hda_update_config_dword(&adev->base.core, AZX_PCIREG_PGCTL, + AZX_PGCTL_LSRMD_MASK, value); +} + +static void avs_hdac_clock_gating_enable(struct hdac_bus *bus, bool enable) +{ + u32 value; + + value = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0; + avs_hda_update_config_dword(bus, AZX_PCIREG_CGCTL, + AZX_CGCTL_MISCBDCGE_MASK, value); +} + +void avs_hda_clock_gating_enable(struct avs_dev *adev, bool enable) +{ + avs_hdac_clock_gating_enable(&adev->base.core, enable); +} + +void avs_hda_l1sen_enable(struct avs_dev *adev, bool enable) +{ + u32 value; + + value = enable ? AZX_VS_EM2_L1SEN : 0; + snd_hdac_chip_updatel(&adev->base.core, VS_EM2, AZX_VS_EM2_L1SEN, value); +} diff --git a/sound/soc/intel/avs/dsp.c b/sound/soc/intel/avs/dsp.c index 5994d64d2468..a434e9918c51 100644 --- a/sound/soc/intel/avs/dsp.c +++ b/sound/soc/intel/avs/dsp.c @@ -198,6 +198,7 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id, u16 *instance_id) { struct avs_module_entry mentry; + bool was_loaded = false; int ret, id; id = avs_module_id_alloc(adev, module_id); @@ -212,6 +213,16 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id, if (ret) goto err_mod_entry; + /* Load code into memory if this is the first instance. */ + if (!id && !avs_module_entry_is_loaded(&mentry)) { + ret = avs_dsp_op(adev, transfer_mods, true, &mentry, 1); + if (ret) { + dev_err(adev->dev, "load modules failed: %d\n", ret); + goto err_mod_entry; + } + was_loaded = true; + } + ret = avs_ipc_init_instance(adev, module_id, id, ppl_instance_id, core_id, domain, param, param_size); if (ret) { @@ -223,6 +234,8 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id, return 0; err_ipc: + if (was_loaded) + avs_dsp_op(adev, transfer_mods, false, &mentry, 1); avs_dsp_put_core(adev, core_id); err_mod_entry: avs_module_id_free(adev, module_id, id); @@ -232,12 +245,25 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id, void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id, u8 ppl_instance_id, u8 core_id) { + struct avs_module_entry mentry; + int ret; + /* Modules not owned by any pipeline need to be freed explicitly. */ if (ppl_instance_id == INVALID_PIPELINE_ID) avs_ipc_delete_instance(adev, module_id, instance_id); avs_module_id_free(adev, module_id, instance_id); + ret = avs_get_module_id_entry(adev, module_id, &mentry); + /* Unload occupied memory if this was the last instance. */ + if (!ret && mentry.type.load_type == AVS_MODULE_LOAD_TYPE_LOADABLE) { + if (avs_is_module_ida_empty(adev, module_id)) { + ret = avs_dsp_op(adev, transfer_mods, false, &mentry, 1); + if (ret) + dev_err(adev->dev, "unload modules failed: %d\n", ret); + } + } + avs_dsp_put_core(adev, core_id); } diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c new file mode 100644 index 000000000000..47e1f9a21e43 --- /dev/null +++ b/sound/soc/intel/avs/loader.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include "avs.h" +#include "messages.h" +#include "registers.h" + +#define AVS_FW_INIT_TIMEOUT_MS 3000 + +#define AVS_ROOT_DIR "intel/avs" +#define AVS_BASEFW_FILENAME "dsp_basefw.bin" +#define AVS_EXT_MANIFEST_MAGIC 0x31454124 +#define SKL_MANIFEST_MAGIC 0x00000006 +#define SKL_ADSPFW_OFFSET 0x284 + +/* Occasionally, engineering (release candidate) firmware is provided for testing. */ +static bool debug_ignore_fw_version; +module_param_named(ignore_fw_version, debug_ignore_fw_version, bool, 0444); +MODULE_PARM_DESC(ignore_fw_version, "Verify FW version 0=yes (default), 1=no"); + +#define AVS_LIB_NAME_SIZE 8 + +struct avs_fw_manifest { + u32 id; + u32 len; + char name[AVS_LIB_NAME_SIZE]; + u32 preload_page_count; + u32 img_flags; + u32 feature_mask; + struct avs_fw_version version; +} __packed; + +struct avs_fw_ext_manifest { + u32 id; + u32 len; + u16 version_major; + u16 version_minor; + u32 entries; +} __packed; + +static int avs_fw_ext_manifest_strip(struct firmware *fw) +{ + struct avs_fw_ext_manifest *man; + + if (fw->size < sizeof(*man)) + return -EINVAL; + + man = (struct avs_fw_ext_manifest *)fw->data; + if (man->id == AVS_EXT_MANIFEST_MAGIC) { + fw->data += man->len; + fw->size -= man->len; + } + + return 0; +} + +static int avs_fw_manifest_offset(struct firmware *fw) +{ + /* Header type found in first DWORD of fw binary. */ + u32 magic = *(u32 *)fw->data; + + switch (magic) { + case SKL_MANIFEST_MAGIC: + return SKL_ADSPFW_OFFSET; + default: + return -EINVAL; + } +} + +static int avs_fw_manifest_strip_verify(struct avs_dev *adev, struct firmware *fw, + const struct avs_fw_version *min) +{ + struct avs_fw_manifest *man; + int offset, ret; + + ret = avs_fw_ext_manifest_strip(fw); + if (ret) + return ret; + + offset = avs_fw_manifest_offset(fw); + if (offset < 0) + return offset; + + if (fw->size < offset + sizeof(*man)) + return -EINVAL; + if (!min) + return 0; + + man = (struct avs_fw_manifest *)(fw->data + offset); + if (man->version.major != min->major || + man->version.minor != min->minor || + man->version.hotfix != min->hotfix || + man->version.build < min->build) { + dev_warn(adev->dev, "bad FW version %d.%d.%d.%d, expected %d.%d.%d.%d or newer\n", + man->version.major, man->version.minor, + man->version.hotfix, man->version.build, + min->major, min->minor, min->hotfix, min->build); + + if (!debug_ignore_fw_version) + return -EINVAL; + } + + return 0; +} + +static int avs_dsp_load_basefw(struct avs_dev *adev) +{ + const struct avs_fw_version *min_req; + const struct avs_spec *const spec = adev->spec; + const struct firmware *fw; + struct firmware stripped_fw; + char *filename; + int ret; + + filename = kasprintf(GFP_KERNEL, "%s/%s/%s", AVS_ROOT_DIR, spec->name, + AVS_BASEFW_FILENAME); + if (!filename) + return -ENOMEM; + + ret = avs_request_firmware(adev, &fw, filename); + kfree(filename); + if (ret < 0) { + dev_err(adev->dev, "request firmware failed: %d\n", ret); + return ret; + } + + stripped_fw = *fw; + min_req = &adev->spec->min_fw_version; + + ret = avs_fw_manifest_strip_verify(adev, &stripped_fw, min_req); + if (ret < 0) { + dev_err(adev->dev, "invalid firmware data: %d\n", ret); + goto release_fw; + } + + ret = avs_dsp_op(adev, load_basefw, &stripped_fw); + if (ret < 0) { + dev_err(adev->dev, "basefw load failed: %d\n", ret); + goto release_fw; + } + + ret = wait_for_completion_timeout(&adev->fw_ready, + msecs_to_jiffies(AVS_FW_INIT_TIMEOUT_MS)); + if (!ret) { + dev_err(adev->dev, "firmware ready timeout\n"); + avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK); + ret = -ETIMEDOUT; + goto release_fw; + } + + return 0; + +release_fw: + avs_release_last_firmware(adev); + return ret; +} + +int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge) +{ + int ret, i; + + /* Full boot, clear cached data except for basefw (slot 0). */ + for (i = 1; i < adev->fw_cfg.max_libs_count; i++) + memset(adev->lib_names[i], 0, AVS_LIB_NAME_SIZE); + + avs_hda_clock_gating_enable(adev, false); + avs_hda_l1sen_enable(adev, false); + + ret = avs_dsp_load_basefw(adev); + + avs_hda_l1sen_enable(adev, true); + avs_hda_clock_gating_enable(adev, true); + + if (ret < 0) + return ret; + + /* With all code loaded, refresh module information. */ + ret = avs_module_info_init(adev, true); + if (ret) { + dev_err(adev->dev, "init module info failed: %d\n", ret); + return ret; + } + + return 0; +} + +int avs_dsp_first_boot_firmware(struct avs_dev *adev) +{ + int ret, i; + + ret = avs_dsp_boot_firmware(adev, true); + if (ret < 0) { + dev_err(adev->dev, "firmware boot failed: %d\n", ret); + return ret; + } + + ret = avs_ipc_get_hw_config(adev, &adev->hw_cfg); + if (ret) { + dev_err(adev->dev, "get hw cfg failed: %d\n", ret); + return AVS_IPC_RET(ret); + } + + ret = avs_ipc_get_fw_config(adev, &adev->fw_cfg); + if (ret) { + dev_err(adev->dev, "get fw cfg failed: %d\n", ret); + return AVS_IPC_RET(ret); + } + + adev->core_refs = devm_kcalloc(adev->dev, adev->hw_cfg.dsp_cores, + sizeof(*adev->core_refs), GFP_KERNEL); + adev->lib_names = devm_kcalloc(adev->dev, adev->fw_cfg.max_libs_count, + sizeof(*adev->lib_names), GFP_KERNEL); + if (!adev->core_refs || !adev->lib_names) + return -ENOMEM; + + for (i = 0; i < adev->fw_cfg.max_libs_count; i++) { + adev->lib_names[i] = devm_kzalloc(adev->dev, AVS_LIB_NAME_SIZE, + GFP_KERNEL); + if (!adev->lib_names[i]) + return -ENOMEM; + } + + /* basefw always occupies slot 0 */ + strcpy(&adev->lib_names[0][0], "BASEFW"); + + ida_init(&adev->ppl_ida); + + return 0; +} diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h index 4bb10ca46a1e..a05465bac6d0 100644 --- a/sound/soc/intel/avs/registers.h +++ b/sound/soc/intel/avs/registers.h @@ -9,6 +9,12 @@ #ifndef __SOUND_SOC_INTEL_AVS_REGS_H #define __SOUND_SOC_INTEL_AVS_REGS_H +#define AZX_PCIREG_PGCTL 0x44 +#define AZX_PCIREG_CGCTL 0x48 +#define AZX_PGCTL_LSRMD_MASK BIT(4) +#define AZX_CGCTL_MISCBDCGE_MASK BIT(6) +#define AZX_VS_EM2_L1SEN BIT(13) + /* Intel HD Audio General DSP Registers */ #define AVS_ADSP_GEN_BASE 0x0 #define AVS_ADSP_REG_ADSPCS (AVS_ADSP_GEN_BASE + 0x04) From patchwork Wed Mar 9 20:40:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550541 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 90833C433EF for ; Wed, 9 Mar 2022 20:35:43 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id D5EEF18A6; Wed, 9 Mar 2022 21:34:51 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D5EEF18A6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858141; bh=WCF9NrVZo0B5xH0Td5xaoK094c6E8aFuFIJq8S3PZoU=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=CCJfMzcDjSfQfn07igxTijnn1wEp5MIqVuf7YS5+pa046geCHaoaf/TO9KixEnIlF fGyN0tM/V30+5gyLGwDEuDDGxHvxkxEjCTLb9Rp7rVWKMkBjKFOb9oWc8Rtwf7x+rp TvO9AAlKiOl1lODx+b0x13FHzT6sv+GvgsNeWX94= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 96A4FF805AB; Wed, 9 Mar 2022 21:30:55 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 3082FF805A0; Wed, 9 Mar 2022 21:30:54 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 7F151F80589 for ; Wed, 9 Mar 2022 21:30:50 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 7F151F80589 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="eLJtmZqJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857851; x=1678393851; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WCF9NrVZo0B5xH0Td5xaoK094c6E8aFuFIJq8S3PZoU=; b=eLJtmZqJ8VfbLEFl/nspIJuDp0EPdl0V+ZDWYlJ+LLmZV81//Z1M3klm e/66GMDUpFn1nFziEnk2bLmc27TX+uj/pdnrjxbUic1RXkMZlhGQghGfZ LvMQoj0L5xS3DFxZGjCyfXeAUKb+ygW5sDCDNeXph/yI9pm7u9p6VIsU2 NCXXupnDB4+siuSpUBAq+20M+qJPgmU/cqZAwrPGfyKs5dX5L73kspmaO QMrGeH3EUL5Gkq5eAxOrtvdiHAidjAcfnNak7xUDWjD4Rk6HW48Du7Ykx CQNYlcLZAaLKgOs3yOeU82FXSzzvbdsr907YSJ1gA3MiujORXu+UhKhmo A==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028838" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028838" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:50 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527317" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:46 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 15/17] ASoC: Intel: avs: Implement CLDMA transfer Date: Wed, 9 Mar 2022 21:40:27 +0100 Message-Id: <20220309204029.89040-16-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" SKL and KBL rely on a dedicated HDAudio DMA stream for code loading and authentication. The implementation of this specific mechanism for SKL-based platforms re-uses HDAudio DMA (streaming) functions found in HDA library to avoid duplication of functionality. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/Makefile | 1 + sound/soc/intel/avs/cldma.c | 317 ++++++++++++++++++++++++++++++++ sound/soc/intel/avs/cldma.h | 29 +++ sound/soc/intel/avs/registers.h | 2 + 4 files changed, 349 insertions(+) create mode 100644 sound/soc/intel/avs/cldma.c create mode 100644 sound/soc/intel/avs/cldma.h diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile index d9c793160612..f842bfc5e97e 100644 --- a/sound/soc/intel/avs/Makefile +++ b/sound/soc/intel/avs/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only snd-soc-avs-objs := dsp.o ipc.o messages.o utils.o core.o loader.o +snd-soc-avs-objs += cldma.o obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o diff --git a/sound/soc/intel/avs/cldma.c b/sound/soc/intel/avs/cldma.c new file mode 100644 index 000000000000..8a1c59b5d7d0 --- /dev/null +++ b/sound/soc/intel/avs/cldma.c @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Cezary Rojewski +// + +#include +#include +#include +#include "cldma.h" +#include "registers.h" + +/* Stream Registers */ +#define AZX_CL_SD_BASE 0x80 +#define AZX_SD_CTL_STRM_MASK GENMASK(23, 20) +#define AZX_SD_CTL_STRM(s) \ + (((s)->stream_tag << 20) & AZX_SD_CTL_STRM_MASK) +#define AZX_SD_BDLPL_BDLPLBA_MASK GENMASK(31, 7) +#define AZX_SD_BDLPL_BDLPLBA(lb) ((lb) & AZX_SD_BDLPL_BDLPLBA_MASK) + +/* Software Position Based FIFO Capability Registers */ +#define AZX_CL_SPBFCS 0x20 +#define AZX_REG_CL_SPBFCTL (AZX_CL_SPBFCS + 0x4) +#define AZX_REG_CL_SD_SPIB (AZX_CL_SPBFCS + 0x8) + +#define AVS_CL_OP_INTERVAL_US 3 +#define AVS_CL_OP_TIMEOUT_US 300 +#define AVS_CL_IOC_TIMEOUT_MS 300 +#define AVS_CL_STREAM_INDEX 0 + +struct hda_cldma { + struct device *dev; + struct hdac_bus *bus; + void __iomem *dsp_ba; + + unsigned int buffer_size; + unsigned int num_periods; + unsigned int stream_tag; + void __iomem *sd_addr; + + struct snd_dma_buffer dmab_data; + struct snd_dma_buffer dmab_bdl; + struct delayed_work memcpy_work; + struct completion completion; + + /* runtime */ + void *position; + unsigned int remaining; + unsigned int sd_status; +}; + +static void cldma_memcpy_work(struct work_struct *work); + +struct hda_cldma code_loader = { + .stream_tag = AVS_CL_STREAM_INDEX + 1, + .memcpy_work = __DELAYED_WORK_INITIALIZER(code_loader.memcpy_work, cldma_memcpy_work, 0), + .completion = COMPLETION_INITIALIZER(code_loader.completion), +}; + +void hda_cldma_fill(struct hda_cldma *cl) +{ + unsigned int size, offset; + + if (cl->remaining > cl->buffer_size) + size = cl->buffer_size; + else + size = cl->remaining; + + offset = snd_hdac_stream_readl(cl, CL_SD_SPIB); + if (offset + size > cl->buffer_size) { + unsigned int ss; + + ss = cl->buffer_size - offset; + memcpy(cl->dmab_data.area + offset, cl->position, ss); + offset = 0; + size -= ss; + cl->position += ss; + cl->remaining -= ss; + } + + memcpy(cl->dmab_data.area + offset, cl->position, size); + cl->position += size; + cl->remaining -= size; + + snd_hdac_stream_writel(cl, CL_SD_SPIB, offset + size); +} + +static void cldma_memcpy_work(struct work_struct *work) +{ + struct hda_cldma *cl = container_of(work, struct hda_cldma, memcpy_work.work); + int ret; + + ret = hda_cldma_start(cl); + if (ret < 0) { + dev_err(cl->dev, "cldma set RUN failed: %d\n", ret); + return; + } + + while (true) { + ret = wait_for_completion_timeout(&cl->completion, + msecs_to_jiffies(AVS_CL_IOC_TIMEOUT_MS)); + if (!ret) { + dev_err(cl->dev, "cldma IOC timeout\n"); + break; + } + + if (!(cl->sd_status & SD_INT_COMPLETE)) { + dev_err(cl->dev, "cldma transfer error, SD status: 0x%08x\n", + cl->sd_status); + break; + } + + if (!cl->remaining) + break; + + reinit_completion(&cl->completion); + hda_cldma_fill(cl); + /* enable CLDMA interrupt */ + snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, + AVS_ADSP_ADSPIC_CLDMA); + } +} + +void hda_cldma_transfer(struct hda_cldma *cl, unsigned long start_delay) +{ + if (!cl->remaining) + return; + + reinit_completion(&cl->completion); + /* fill buffer with the first chunk before scheduling run */ + hda_cldma_fill(cl); + + schedule_delayed_work(&cl->memcpy_work, start_delay); +} + +int hda_cldma_start(struct hda_cldma *cl) +{ + unsigned int reg; + + /* enable interrupts */ + snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, + AVS_ADSP_ADSPIC_CLDMA); + snd_hdac_stream_updateb(cl, SD_CTL, SD_INT_MASK | SD_CTL_DMA_START, + SD_INT_MASK | SD_CTL_DMA_START); + + /* await DMA engine start */ + return snd_hdac_stream_readb_poll(cl, SD_CTL, reg, reg & SD_CTL_DMA_START, + AVS_CL_OP_INTERVAL_US, AVS_CL_OP_TIMEOUT_US); +} + +int hda_cldma_stop(struct hda_cldma *cl) +{ + unsigned int reg; + int ret; + + /* disable interrupts */ + snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, 0); + snd_hdac_stream_updateb(cl, SD_CTL, SD_INT_MASK | SD_CTL_DMA_START, 0); + + /* await DMA engine stop */ + ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, !(reg & SD_CTL_DMA_START), + AVS_CL_OP_INTERVAL_US, AVS_CL_OP_TIMEOUT_US); + cancel_delayed_work_sync(&cl->memcpy_work); + + return ret; +} + +int hda_cldma_reset(struct hda_cldma *cl) +{ + unsigned int reg; + int ret; + + ret = hda_cldma_stop(cl); + if (ret < 0) { + dev_err(cl->dev, "cldma stop failed: %d\n", ret); + return ret; + } + + snd_hdac_stream_updateb(cl, SD_CTL, 1, 1); + ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, (reg & 1), AVS_CL_OP_INTERVAL_US, + AVS_CL_OP_TIMEOUT_US); + if (ret < 0) { + dev_err(cl->dev, "cldma set SRST failed: %d\n", ret); + return ret; + } + + snd_hdac_stream_updateb(cl, SD_CTL, 1, 0); + ret = snd_hdac_stream_readb_poll(cl, SD_CTL, reg, !(reg & 1), AVS_CL_OP_INTERVAL_US, + AVS_CL_OP_TIMEOUT_US); + if (ret < 0) { + dev_err(cl->dev, "cldma unset SRST failed: %d\n", ret); + return ret; + } + + return 0; +} + +void hda_cldma_set_data(struct hda_cldma *cl, void *data, unsigned int size) +{ + /* setup runtime */ + cl->position = data; + cl->remaining = size; +} + +static void cldma_setup_bdle(struct hda_cldma *cl, u32 bdle_size) +{ + struct snd_dma_buffer *dmab = &cl->dmab_data; + __le32 *bdl = (__le32 *)cl->dmab_bdl.area; + int remaining = cl->buffer_size; + int offset = 0; + + cl->num_periods = 0; + + while (remaining > 0) { + phys_addr_t addr; + int chunk; + + addr = snd_sgbuf_get_addr(dmab, offset); + bdl[0] = cpu_to_le32(lower_32_bits(addr)); + bdl[1] = cpu_to_le32(upper_32_bits(addr)); + chunk = snd_sgbuf_get_chunk_size(dmab, offset, bdle_size); + bdl[2] = cpu_to_le32(chunk); + + remaining -= chunk; + /* set IOC only for the last entry */ + bdl[3] = (remaining > 0) ? 0 : cpu_to_le32(0x01); + + bdl += 4; + offset += chunk; + cl->num_periods++; + } +} + +void hda_cldma_setup(struct hda_cldma *cl) +{ + dma_addr_t bdl_addr = cl->dmab_bdl.addr; + + cldma_setup_bdle(cl, cl->buffer_size / 2); + + snd_hdac_stream_writel(cl, SD_BDLPL, AZX_SD_BDLPL_BDLPLBA(lower_32_bits(bdl_addr))); + snd_hdac_stream_writel(cl, SD_BDLPU, upper_32_bits(bdl_addr)); + + snd_hdac_stream_writel(cl, SD_CBL, cl->buffer_size); + snd_hdac_stream_writeb(cl, SD_LVI, cl->num_periods - 1); + + snd_hdac_stream_updatel(cl, SD_CTL, AZX_SD_CTL_STRM_MASK, AZX_SD_CTL_STRM(cl)); + /* enable spib */ + snd_hdac_stream_writel(cl, CL_SPBFCTL, 1); +} + +static irqreturn_t cldma_irq_handler(int irq, void *dev_id) +{ + struct hda_cldma *cl = dev_id; + u32 adspis; + + adspis = snd_hdac_adsp_readl(cl, AVS_ADSP_REG_ADSPIS); + if (adspis == UINT_MAX) + return IRQ_NONE; + if (!(adspis & AVS_ADSP_ADSPIS_CLDMA)) + return IRQ_NONE; + + cl->sd_status = snd_hdac_stream_readb(cl, SD_STS); + dev_warn(cl->dev, "%s sd_status: 0x%08x\n", __func__, cl->sd_status); + + /* disable CLDMA interrupt */ + snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, 0); + + complete(&cl->completion); + + return IRQ_HANDLED; +} + +int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp_ba, + unsigned int buffer_size) +{ + struct pci_dev *pci = to_pci_dev(bus->dev); + int ret; + + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, buffer_size, &cl->dmab_data); + if (ret < 0) + return ret; + + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, bus->dev, BDL_SIZE, &cl->dmab_bdl); + if (ret < 0) + goto alloc_err; + + cl->dev = bus->dev; + cl->bus = bus; + cl->dsp_ba = dsp_ba; + cl->buffer_size = buffer_size; + cl->sd_addr = dsp_ba + AZX_CL_SD_BASE; + + ret = pci_request_irq(pci, 0, cldma_irq_handler, NULL, cl, "CLDMA"); + if (ret < 0) { + dev_err(cl->dev, "Failed to request CLDMA IRQ handler: %d\n", ret); + goto req_err; + } + + return 0; + +req_err: + snd_dma_free_pages(&cl->dmab_bdl); +alloc_err: + snd_dma_free_pages(&cl->dmab_data); + + return ret; +} + +void hda_cldma_free(struct hda_cldma *cl) +{ + struct pci_dev *pci = to_pci_dev(cl->dev); + + pci_free_irq(pci, 0, cl); + snd_dma_free_pages(&cl->dmab_data); + snd_dma_free_pages(&cl->dmab_bdl); +} diff --git a/sound/soc/intel/avs/cldma.h b/sound/soc/intel/avs/cldma.h new file mode 100644 index 000000000000..cad81f03095a --- /dev/null +++ b/sound/soc/intel/avs/cldma.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Cezary Rojewski + */ + +#ifndef __SOUND_SOC_INTEL_AVS_CLDMA_H +#define __SOUND_SOC_INTEL_AVS_CLDMA_H + +#define AVS_CL_DEFAULT_BUFFER_SIZE (32 * PAGE_SIZE) + +struct hda_cldma; +extern struct hda_cldma code_loader; + +void hda_cldma_fill(struct hda_cldma *cl); +void hda_cldma_transfer(struct hda_cldma *cl, unsigned long start_delay); + +int hda_cldma_start(struct hda_cldma *cl); +int hda_cldma_stop(struct hda_cldma *cl); +int hda_cldma_reset(struct hda_cldma *cl); + +void hda_cldma_set_data(struct hda_cldma *cl, void *data, unsigned int size); +void hda_cldma_setup(struct hda_cldma *cl); +int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp_ba, + unsigned int buffer_size); +void hda_cldma_free(struct hda_cldma *cl); + +#endif diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h index a05465bac6d0..0f55f526d962 100644 --- a/sound/soc/intel/avs/registers.h +++ b/sound/soc/intel/avs/registers.h @@ -22,7 +22,9 @@ #define AVS_ADSP_REG_ADSPIS (AVS_ADSP_GEN_BASE + 0x0C) #define AVS_ADSP_ADSPIC_IPC BIT(0) +#define AVS_ADSP_ADSPIC_CLDMA BIT(1) #define AVS_ADSP_ADSPIS_IPC BIT(0) +#define AVS_ADSP_ADSPIS_CLDMA BIT(1) #define AVS_ADSPCS_CRST_MASK(cm) (cm) #define AVS_ADSPCS_CSTALL_MASK(cm) ((cm) << 8) From patchwork Wed Mar 9 20:40:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 549714 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 10B30C4332F for ; Wed, 9 Mar 2022 20:36:06 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 5A09318BE; Wed, 9 Mar 2022 21:35:14 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 5A09318BE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858164; bh=R6Q6CBXI7ejZXNn610ld6z4ulmE+OqX+mu2P11aNx8M=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=ImQgCRCHAOFZArfOqPWV/TFn5/vKMSpgI/uCZHVRhFA3rEy/BfmB9yL38IgllHcDQ 6+OghOQ1LghsdAm0emeIS2eCP+L5qH/jCuhnf777dJaNEEDwmYLLDCqi7LszyaTvX7 sOblZpLU9tuxRoba6qH6TWZYTyk1mAINjYcFZvxM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id A462FF805B6; Wed, 9 Mar 2022 21:31:01 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 3727AF805B6; Wed, 9 Mar 2022 21:30:57 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 1C0B5F80589 for ; Wed, 9 Mar 2022 21:30:53 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 1C0B5F80589 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LX77aUWr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857855; x=1678393855; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=R6Q6CBXI7ejZXNn610ld6z4ulmE+OqX+mu2P11aNx8M=; b=LX77aUWrcAIhwreLu8G6rtthOhUfUzZcdX+K6xg1b8UZLPHLmj7N1DXZ dnTzR+EHs+Rc6FoA5m6FPiJRhftGMalUg7p2lolNWb1kvn9HxRejRkiYL k1tDSpJPXsKIVA8bau33cZ9IJHw/tRTtR4pNaXXHj8bLndz/A1Da3gzI5 3LbNlVMDH4ZQ7kMmwe/zHHOC92r+UXK9gIkLqSeA+dSlb3SQBKOqozlaT C11z5zKFFo0E5cGu2HhumfKh18PmbXSmHjMgdwdrq2AaSVeXSGK89oL2R neGWQOfIYzSDXBIacKZHIOcVJtZKRx4VDrENMTbXarwgTzLvauRC2drc4 A==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028859" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028859" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:53 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527339" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:50 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 16/17] ASoC: Intel: avs: Code loading over CLDMA Date: Wed, 9 Mar 2022 21:40:28 +0100 Message-Id: <20220309204029.89040-17-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" With CLDMA transfer implemented, make use of it to shape firmware, library and module loading routines for SKL and KBL platforms. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/avs/avs.h | 7 ++ sound/soc/intel/avs/loader.c | 159 +++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 21a161c2443d..2531b383e1e7 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -44,6 +44,8 @@ struct avs_dsp_ops { #define avs_dsp_op(adev, op, ...) \ ((adev)->spec->dsp_ops->op(adev, ## __VA_ARGS__)) +#define AVS_PLATATTR_CLDMA BIT_ULL(0) + #define avs_platattr_test(adev, attr) \ ((adev)->spec->attributes & AVS_PLATATTR_##attr) @@ -233,4 +235,9 @@ void avs_hda_l1sen_enable(struct avs_dev *adev, bool enable); int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge); int avs_dsp_first_boot_firmware(struct avs_dev *adev); +int avs_cldma_load_basefw(struct avs_dev *adev, struct firmware *fw); +int avs_cldma_load_library(struct avs_dev *adev, struct firmware *lib, u32 id); +int avs_cldma_transfer_modules(struct avs_dev *adev, bool load, + struct avs_module_entry *mods, u32 num_mods); + #endif /* __SOUND_SOC_INTEL_AVS_H */ diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index 47e1f9a21e43..2134aaabe2c6 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -9,12 +9,24 @@ #include #include #include +#include #include "avs.h" +#include "cldma.h" #include "messages.h" #include "registers.h" +#define AVS_ROM_STS_MASK 0xFF +#define AVS_ROM_INIT_DONE 0x1 +#define SKL_ROM_BASEFW_ENTERED 0xF +#define AVS_ROM_INIT_POLLING_US 5 +#define SKL_ROM_INIT_TIMEOUT_US 1000000 + +#define AVS_FW_INIT_POLLING_US 500 +#define AVS_FW_INIT_TIMEOUT_US 3000000 #define AVS_FW_INIT_TIMEOUT_MS 3000 +#define AVS_CLDMA_START_DELAY_MS 100 + #define AVS_ROOT_DIR "intel/avs" #define AVS_BASEFW_FILENAME "dsp_basefw.bin" #define AVS_EXT_MANIFEST_MAGIC 0x31454124 @@ -111,6 +123,144 @@ static int avs_fw_manifest_strip_verify(struct avs_dev *adev, struct firmware *f return 0; } +int avs_cldma_load_basefw(struct avs_dev *adev, struct firmware *fw) +{ + struct hda_cldma *cl = &code_loader; + unsigned int reg; + int ret; + + ret = avs_dsp_op(adev, power, AVS_MAIN_CORE_MASK, true); + if (ret < 0) + return ret; + + ret = avs_dsp_op(adev, reset, AVS_MAIN_CORE_MASK, false); + if (ret < 0) + return ret; + + ret = hda_cldma_reset(cl); + if (ret < 0) { + dev_err(adev->dev, "cldma reset failed: %d\n", ret); + return ret; + } + hda_cldma_setup(cl); + + ret = avs_dsp_op(adev, stall, AVS_MAIN_CORE_MASK, false); + if (ret < 0) + return ret; + + reinit_completion(&adev->fw_ready); + avs_dsp_op(adev, int_control, true); + + /* await ROM init */ + ret = snd_hdac_adsp_readl_poll(adev, AVS_FW_REG_STATUS(adev), reg, + (reg & AVS_ROM_INIT_DONE) == AVS_ROM_INIT_DONE, + AVS_ROM_INIT_POLLING_US, SKL_ROM_INIT_TIMEOUT_US); + if (ret < 0) { + dev_err(adev->dev, "rom init timeout: %d\n", ret); + avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK); + return ret; + } + + hda_cldma_set_data(cl, (void *)fw->data, fw->size); + /* transfer firmware */ + hda_cldma_transfer(cl, 0); + ret = snd_hdac_adsp_readl_poll(adev, AVS_FW_REG_STATUS(adev), reg, + (reg & AVS_ROM_STS_MASK) == SKL_ROM_BASEFW_ENTERED, + AVS_FW_INIT_POLLING_US, AVS_FW_INIT_TIMEOUT_US); + hda_cldma_stop(cl); + if (ret < 0) { + dev_err(adev->dev, "transfer fw failed: %d\n", ret); + avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK); + return ret; + } + + return 0; +} + +int avs_cldma_load_library(struct avs_dev *adev, struct firmware *lib, u32 id) +{ + struct hda_cldma *cl = &code_loader; + int ret; + + hda_cldma_set_data(cl, (void *)lib->data, lib->size); + /* transfer modules manifest */ + hda_cldma_transfer(cl, msecs_to_jiffies(AVS_CLDMA_START_DELAY_MS)); + + /* DMA id ignored as there is only ever one code-loader DMA */ + ret = avs_ipc_load_library(adev, 0, id); + hda_cldma_stop(cl); + + if (ret) { + ret = AVS_IPC_RET(ret); + dev_err(adev->dev, "transfer lib %d failed: %d\n", id, ret); + } + + return ret; +} + +static int avs_cldma_load_module(struct avs_dev *adev, struct avs_module_entry *mentry) +{ + struct hda_cldma *cl = &code_loader; + const struct firmware *mod; + char *mod_name; + int ret; + + mod_name = kasprintf(GFP_KERNEL, "%s/%s/dsp_mod_%pUL.bin", AVS_ROOT_DIR, + adev->spec->name, mentry->uuid.b); + if (!mod_name) + return -ENOMEM; + + ret = avs_request_firmware(adev, &mod, mod_name); + kfree(mod_name); + if (ret < 0) + return ret; + + hda_cldma_set_data(cl, (void *)mod->data, mod->size); + hda_cldma_transfer(cl, msecs_to_jiffies(AVS_CLDMA_START_DELAY_MS)); + ret = avs_ipc_load_modules(adev, &mentry->module_id, 1); + hda_cldma_stop(cl); + + if (ret) { + dev_err(adev->dev, "load module %d failed: %d\n", mentry->module_id, ret); + avs_release_last_firmware(adev); + return AVS_IPC_RET(ret); + } + + return 0; +} + +int avs_cldma_transfer_modules(struct avs_dev *adev, bool load, + struct avs_module_entry *mods, u32 num_mods) +{ + u16 *mod_ids; + int ret, i; + + /* Either load to DSP or unload them to free space. */ + if (load) { + for (i = 0; i < num_mods; i++) { + ret = avs_cldma_load_module(adev, &mods[i]); + if (ret) + return ret; + } + + return 0; + } + + mod_ids = kcalloc(num_mods, sizeof(u16), GFP_KERNEL); + if (!mod_ids) + return -ENOMEM; + + for (i = 0; i < num_mods; i++) + mod_ids[i] = mods[i].module_id; + + ret = avs_ipc_unload_modules(adev, mod_ids, num_mods); + kfree(mod_ids); + if (ret) + return AVS_IPC_RET(ret); + + return 0; +} + static int avs_dsp_load_basefw(struct avs_dev *adev) { const struct avs_fw_version *min_req; @@ -196,6 +346,15 @@ int avs_dsp_first_boot_firmware(struct avs_dev *adev) { int ret, i; + if (avs_platattr_test(adev, CLDMA)) { + ret = hda_cldma_init(&code_loader, &adev->base.core, + adev->dsp_ba, AVS_CL_DEFAULT_BUFFER_SIZE); + if (ret < 0) { + dev_err(adev->dev, "cldma init failed: %d\n", ret); + return ret; + } + } + ret = avs_dsp_boot_firmware(adev, true); if (ret < 0) { dev_err(adev->dev, "firmware boot failed: %d\n", ret); From patchwork Wed Mar 9 20:40:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cezary Rojewski X-Patchwork-Id: 550540 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 545E3C433EF for ; Wed, 9 Mar 2022 20:36:19 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 6F1AA18CF; Wed, 9 Mar 2022 21:35:27 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 6F1AA18CF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1646858177; bh=wQc6V2LxKmF9YrHCWeStpBNhRFghLBUjMoxHgmlSANc=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=c95X3GsVikJLAh4uqj6enBJqD2As9l7Pu9Ahe4cKpdv1+Dy2XWqwe+z9Un3TxJPsp CkHxxFSznc+QuAfS6AYmsbKQRvOhsqcityev2VY4Y9knP2cwIzkaWDdZMxo0RV/R+j Ne2n3MEB6FiRDewrQkC2+2vTH+Se349YiSyZdgOQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 3E248F80236; Wed, 9 Mar 2022 21:31:06 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 6BB2CF80236; Wed, 9 Mar 2022 21:31:05 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id D7AAFF805B2 for ; Wed, 9 Mar 2022 21:30:57 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz D7AAFF805B2 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="bLAMjgKr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646857859; x=1678393859; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wQc6V2LxKmF9YrHCWeStpBNhRFghLBUjMoxHgmlSANc=; b=bLAMjgKrr3ITFfGThwod4J2dWQO+2feIUo/Z7pAnW+cSwqVolQXCURVm I9GHk5GloVEeDeh4GFaKZZFX3l7WkQBCxdI/8tu5HGiXi0en0TFIKASD7 e6bFHD02GMO/fkA9Q7agg4EoPwo3aaRvVZnVYf0ezuJHXXSVRNwtUyG9w tzpBLmxeHR5Sg01nGeixhioK9JZOHUX1RhpWELVYFD8XgPWQoAfVQNm9H QelADA5JZRcobeho5s7E01zop0BWY9PU5C8IZmKCAlqrbbuVoI+OAZieb ZoUdXk/j+aTiwYpL75yKiOo3rFeOovD8kF/zEsrOgUJ3qLnDt32uUInhU w==; X-IronPort-AV: E=McAfee;i="6200,9189,10281"; a="255028879" X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="255028879" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Mar 2022 12:30:57 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,168,1643702400"; d="scan'208";a="578527364" Received: from crojewsk-ctrl.igk.intel.com ([10.102.9.28]) by orsmga001.jf.intel.com with ESMTP; 09 Mar 2022 12:30:53 -0800 From: Cezary Rojewski To: alsa-devel@alsa-project.org Subject: [PATCH v4 17/17] ASoC: Intel: avs: Code loading over HDA Date: Wed, 9 Mar 2022 21:40:29 +0100 Message-Id: <20220309204029.89040-18-cezary.rojewski@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220309204029.89040-1-cezary.rojewski@intel.com> References: <20220309204029.89040-1-cezary.rojewski@intel.com> MIME-Version: 1.0 Cc: Cezary Rojewski , rad@semihalf.com, upstream@semihalf.com, harshapriya.n@intel.com, tiwai@suse.com, pierre-louis.bossart@linux.intel.com, hdegoede@redhat.com, broonie@kernel.org, ranjani.sridharan@linux.intel.com, amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org, lma@semihalf.com X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Compared to SKL and KBL, more recent cAVS platforms are meant to re-use one of HDAudio streams during boot procedure causing CLDMA to become obsolete. Once transferred, given stream is returned to pool available for audio streaming. Module loading handler is stub as library and module code became inseparable in later firmware generations. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski --- sound/soc/intel/Kconfig | 1 + sound/soc/intel/avs/avs.h | 5 + sound/soc/intel/avs/loader.c | 214 +++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index e9768c4aa1a9..d025ca0c77fa 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -215,6 +215,7 @@ config SND_SOC_INTEL_AVS depends on COMMON_CLK select SND_SOC_ACPI select SND_HDA_EXT_CORE + select SND_HDA_DSP_LOADER help Enable support for Intel(R) cAVS 1.5 platforms with DSP capabilities. This includes Skylake, Kabylake, Amberlake and diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 2531b383e1e7..2451b676704c 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -45,6 +45,7 @@ struct avs_dsp_ops { ((adev)->spec->dsp_ops->op(adev, ## __VA_ARGS__)) #define AVS_PLATATTR_CLDMA BIT_ULL(0) +#define AVS_PLATATTR_IMR BIT_ULL(1) #define avs_platattr_test(adev, attr) \ ((adev)->spec->attributes & AVS_PLATATTR_##attr) @@ -239,5 +240,9 @@ int avs_cldma_load_basefw(struct avs_dev *adev, struct firmware *fw); int avs_cldma_load_library(struct avs_dev *adev, struct firmware *lib, u32 id); int avs_cldma_transfer_modules(struct avs_dev *adev, bool load, struct avs_module_entry *mods, u32 num_mods); +int avs_hda_load_basefw(struct avs_dev *adev, struct firmware *fw); +int avs_hda_load_library(struct avs_dev *adev, struct firmware *lib, u32 id); +int avs_hda_transfer_modules(struct avs_dev *adev, bool load, + struct avs_module_entry *mods, u32 num_mods); #endif /* __SOUND_SOC_INTEL_AVS_H */ diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index 2134aaabe2c6..531ec5689ebf 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "avs.h" #include "cldma.h" @@ -18,8 +19,11 @@ #define AVS_ROM_STS_MASK 0xFF #define AVS_ROM_INIT_DONE 0x1 #define SKL_ROM_BASEFW_ENTERED 0xF +#define APL_ROM_FW_ENTERED 0x5 #define AVS_ROM_INIT_POLLING_US 5 #define SKL_ROM_INIT_TIMEOUT_US 1000000 +#define APL_ROM_INIT_TIMEOUT_US 300000 +#define APL_ROM_INIT_RETRIES 3 #define AVS_FW_INIT_POLLING_US 500 #define AVS_FW_INIT_TIMEOUT_US 3000000 @@ -261,6 +265,207 @@ int avs_cldma_transfer_modules(struct avs_dev *adev, bool load, return 0; } +static int +avs_hda_init_rom(struct avs_dev *adev, unsigned int dma_id, bool purge) +{ + const struct avs_spec *const spec = adev->spec; + unsigned int corex_mask, reg; + int ret; + + corex_mask = spec->core_init_mask & ~AVS_MAIN_CORE_MASK; + + ret = avs_dsp_op(adev, power, spec->core_init_mask, true); + if (ret < 0) + goto err; + + ret = avs_dsp_op(adev, reset, AVS_MAIN_CORE_MASK, false); + if (ret < 0) + goto err; + + reinit_completion(&adev->fw_ready); + avs_dsp_op(adev, int_control, true); + + /* set boot config */ + ret = avs_ipc_set_boot_config(adev, dma_id, purge); + if (ret) { + ret = AVS_IPC_RET(ret); + goto err; + } + + /* await ROM init */ + ret = snd_hdac_adsp_readq_poll(adev, spec->rom_status, reg, + (reg & 0xF) == AVS_ROM_INIT_DONE || + (reg & 0xF) == APL_ROM_FW_ENTERED, + AVS_ROM_INIT_POLLING_US, APL_ROM_INIT_TIMEOUT_US); + if (ret < 0) { + dev_err(adev->dev, "rom init timeout: %d\n", ret); + goto err; + } + + /* power down non-main cores */ + if (corex_mask) { + ret = avs_dsp_op(adev, power, corex_mask, false); + if (ret < 0) + goto err; + } + + return 0; + +err: + avs_dsp_core_disable(adev, spec->core_init_mask); + return ret; +} + +static int avs_imr_load_basefw(struct avs_dev *adev) +{ + int ret; + + /* DMA id ignored when flashing from IMR as no transfer occurs. */ + ret = avs_hda_init_rom(adev, 0, false); + if (ret < 0) { + dev_err(adev->dev, "rom init failed: %d\n", ret); + return ret; + } + + ret = wait_for_completion_timeout(&adev->fw_ready, + msecs_to_jiffies(AVS_FW_INIT_TIMEOUT_MS)); + if (!ret) { + dev_err(adev->dev, "firmware ready timeout\n"); + avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK); + return -ETIMEDOUT; + } + + return 0; +} + +int avs_hda_load_basefw(struct avs_dev *adev, struct firmware *fw) +{ + struct snd_pcm_substream substream; + struct snd_dma_buffer dmab; + struct hdac_ext_stream *estream; + struct hdac_stream *hstream; + struct hdac_bus *bus = &adev->base.core; + unsigned int sdfmt, reg; + int ret, i; + + /* configure hda dma */ + memset(&substream, 0, sizeof(substream)); + substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + estream = snd_hdac_ext_stream_assign(bus, &substream, + HDAC_EXT_STREAM_TYPE_HOST); + if (!estream) + return -ENODEV; + hstream = hdac_stream(estream); + + /* code loading performed with default format */ + sdfmt = snd_hdac_calc_stream_format(48000, 1, SNDRV_PCM_FORMAT_S32_LE, 32, 0); + ret = snd_hdac_dsp_prepare(hstream, sdfmt, fw->size, &dmab); + if (ret < 0) + goto release_stream; + + /* enable SPIB for hda stream */ + snd_hdac_ext_stream_spbcap_enable(bus, true, hstream->index); + ret = snd_hdac_ext_stream_set_spib(bus, estream, fw->size); + if (ret) + goto cleanup_resources; + + memcpy(dmab.area, fw->data, fw->size); + + for (i = 0; i < APL_ROM_INIT_RETRIES; i++) { + unsigned int dma_id = hstream->stream_tag - 1; + + ret = avs_hda_init_rom(adev, dma_id, true); + if (!ret) + break; + dev_info(adev->dev, "#%d rom init fail: %d\n", i + 1, ret); + } + if (ret < 0) + goto cleanup_resources; + + /* transfer firmware */ + snd_hdac_dsp_trigger(hstream, true); + ret = snd_hdac_adsp_readl_poll(adev, AVS_FW_REG_STATUS(adev), reg, + (reg & AVS_ROM_STS_MASK) == APL_ROM_FW_ENTERED, + AVS_FW_INIT_POLLING_US, AVS_FW_INIT_TIMEOUT_US); + snd_hdac_dsp_trigger(hstream, false); + if (ret < 0) { + dev_err(adev->dev, "transfer fw failed: %d\n", ret); + avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK); + } + +cleanup_resources: + /* disable SPIB for hda stream */ + snd_hdac_ext_stream_spbcap_enable(bus, false, hstream->index); + snd_hdac_ext_stream_set_spib(bus, estream, 0); + + snd_hdac_dsp_cleanup(hstream, &dmab); +release_stream: + snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST); + + return ret; +} + +int avs_hda_load_library(struct avs_dev *adev, struct firmware *lib, u32 id) +{ + struct snd_pcm_substream substream; + struct snd_dma_buffer dmab; + struct hdac_ext_stream *estream; + struct hdac_stream *stream; + struct hdac_bus *bus = &adev->base.core; + unsigned int sdfmt; + int ret; + + /* configure hda dma */ + memset(&substream, 0, sizeof(substream)); + substream.stream = SNDRV_PCM_STREAM_PLAYBACK; + estream = snd_hdac_ext_stream_assign(bus, &substream, + HDAC_EXT_STREAM_TYPE_HOST); + if (!estream) + return -ENODEV; + stream = hdac_stream(estream); + + /* code loading performed with default format */ + sdfmt = snd_hdac_calc_stream_format(48000, 1, SNDRV_PCM_FORMAT_S32_LE, 32, 0); + ret = snd_hdac_dsp_prepare(stream, sdfmt, lib->size, &dmab); + if (ret < 0) + goto release_stream; + + /* enable SPIB for hda stream */ + snd_hdac_ext_stream_spbcap_enable(bus, true, stream->index); + snd_hdac_ext_stream_set_spib(bus, estream, lib->size); + + memcpy(dmab.area, lib->data, lib->size); + + /* transfer firmware */ + snd_hdac_dsp_trigger(stream, true); + ret = avs_ipc_load_library(adev, stream->stream_tag - 1, id); + snd_hdac_dsp_trigger(stream, false); + if (ret) { + dev_err(adev->dev, "transfer lib %d failed: %d\n", id, ret); + ret = AVS_IPC_RET(ret); + } + + /* disable SPIB for hda stream */ + snd_hdac_ext_stream_spbcap_enable(bus, false, stream->index); + snd_hdac_ext_stream_set_spib(bus, estream, 0); + + snd_hdac_dsp_cleanup(stream, &dmab); +release_stream: + snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST); + + return ret; +} + +int avs_hda_transfer_modules(struct avs_dev *adev, bool load, + struct avs_module_entry *mods, u32 num_mods) +{ + /* + * All platforms without CLDMA are equipped with IMR, + * and thus the module transferring is offloaded to DSP. + */ + return 0; +} + static int avs_dsp_load_basefw(struct avs_dev *adev) { const struct avs_fw_version *min_req; @@ -317,6 +522,15 @@ int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge) { int ret, i; + /* Forgo full boot if flash from IMR succeeds. */ + if (!purge && avs_platattr_test(adev, IMR)) { + ret = avs_imr_load_basefw(adev); + if (!ret) + return 0; + + dev_dbg(adev->dev, "firmware flash from imr failed: %d\n", ret); + } + /* Full boot, clear cached data except for basefw (slot 0). */ for (i = 1; i < adev->fw_cfg.max_libs_count; i++) memset(adev->lib_names[i], 0, AVS_LIB_NAME_SIZE);