All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cezary Rojewski <cezary.rojewski@intel.com>
To: alsa-devel@alsa-project.org
Cc: Cezary Rojewski <cezary.rojewski@intel.com>,
	upstream@semihalf.com, harshapriya.n@intel.com,
	yung-chuan.liao@linux.intel.com, rad@semihalf.com,
	pierre-louis.bossart@linux.intel.com, tiwai@suse.com,
	hdegoede@redhat.com, broonie@kernel.org,
	ranjani.sridharan@linux.intel.com,
	amadeuszx.slawinski@linux.intel.com, cujomalainey@chromium.org,
	peter.ujfalusi@linux.intel.com, lma@semihalf.com
Subject: [RFC 25/37] ASoC: Intel: avs: Generic soc component driver
Date: Wed,  8 Dec 2021 12:12:49 +0100	[thread overview]
Message-ID: <20211208111301.1817725-26-cezary.rojewski@intel.com> (raw)
In-Reply-To: <20211208111301.1817725-1-cezary.rojewski@intel.com>

Prepare for concrete PCM operations over HDA, DMIC and I2S interfaces by
providing generic soc component implementation. Interface-specific
components re-use this code as majority of flow is shared.

Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 include/sound/soc-acpi.h     |   2 +
 sound/soc/intel/avs/Makefile |   2 +-
 sound/soc/intel/avs/pcm.c    | 281 +++++++++++++++++++++++++++++++++++
 3 files changed, 284 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/intel/avs/pcm.c

diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
index ac0893df9c76..1f785f0e9843 100644
--- a/include/sound/soc-acpi.h
+++ b/include/sound/soc-acpi.h
@@ -135,6 +135,7 @@ struct snd_soc_acpi_link_adr {
  * @links: array of link _ADR descriptors, null terminated.
  * @drv_name: machine driver name
  * @fw_filename: firmware file name. Used when SOF is not enabled.
+ * @tplg_filename: topology file name. Used when SOF is not enabled.
  * @board: board name
  * @machine_quirk: pointer to quirk, usually based on DMI information when
  * ACPI ID alone is not sufficient, wrong or misleading
@@ -153,6 +154,7 @@ struct snd_soc_acpi_mach {
 	const struct snd_soc_acpi_link_adr *links;
 	const char *drv_name;
 	const char *fw_filename;
+	const char *tplg_filename;
 	const char *board;
 	struct snd_soc_acpi_mach * (*machine_quirk)(void *arg);
 	const void *quirk_data;
diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile
index 53b14d901e2f..427b92fad4ef 100644
--- a/sound/soc/intel/avs/Makefile
+++ b/sound/soc/intel/avs/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 snd-soc-avs-objs := dsp.o ipc.o messages.o utils.o topology.o path.o \
-		    core.o loader.o
+		    core.o loader.o pcm.o
 snd-soc-avs-objs += cldma.o
 
 obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o
diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c
new file mode 100644
index 000000000000..9c6b3938c542
--- /dev/null
+++ b/sound/soc/intel/avs/pcm.c
@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2021 Intel Corporation. All rights reserved.
+//
+// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+//          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+//
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <sound/hda_register.h>
+#include <sound/hdaudio_ext.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-acpi-intel-match.h>
+#include <sound/soc-component.h>
+#include "avs.h"
+#include "path.h"
+#include "topology.h"
+
+struct avs_pcm_dma_data {
+	struct avs_tplg_path_template *template;
+	struct avs_path *path;
+	/*
+	 * link stream is stored within substream's runtime
+	 * private_data to fulfill the needs of codec BE path
+	 *
+	 * host stream assigned
+	 */
+	struct hdac_ext_stream *host_stream;
+};
+
+static ssize_t topology_name_read(struct file *file, char __user *user_buf,
+				  size_t count, loff_t *ppos)
+{
+	struct snd_soc_component *component = file->private_data;
+	struct snd_soc_card *card = component->card;
+	struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
+	char buf[64];
+	size_t len;
+
+	len = snprintf(buf, sizeof(buf), "%s/%s\n",
+		       component->driver->topology_name_prefix,
+		       mach->tplg_filename);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations topology_name_fops = {
+	.open = simple_open,
+	.read = topology_name_read,
+	.llseek = default_llseek,
+};
+
+static int avs_component_load_libraries(struct avs_soc_component *acomp)
+{
+	struct avs_tplg *tplg = acomp->tplg;
+	struct avs_dev *adev = to_avs_dev(acomp->base.dev);
+	int ret;
+
+	if (!tplg->num_libs)
+		return 0;
+
+	/* Parent device may be asleep and library loading involves IPCs. */
+	ret = pm_runtime_get_sync(adev->dev);
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put_noidle(adev->dev);
+		return ret;
+	}
+
+	avs_hda_clock_gating_enable(adev, false);
+	avs_hda_l1sen_enable(adev, false);
+
+	ret = avs_dsp_load_libraries(adev, tplg->libs, tplg->num_libs);
+
+	avs_hda_l1sen_enable(adev, true);
+	avs_hda_clock_gating_enable(adev, true);
+
+	if (!ret)
+		ret = avs_module_info_init(adev, false);
+
+	pm_runtime_mark_last_busy(adev->dev);
+	pm_runtime_put_autosuspend(adev->dev);
+
+	return ret;
+}
+
+static int avs_component_probe(struct snd_soc_component *component)
+{
+	struct snd_soc_card *card = component->card;
+	struct snd_soc_acpi_mach *mach;
+	struct avs_soc_component *acomp;
+	struct avs_dev *adev;
+	char *filename;
+	int ret;
+
+	dev_dbg(card->dev, "probing %s card %s\n", component->name, card->name);
+	mach = dev_get_platdata(card->dev);
+	acomp = to_avs_soc_component(component);
+	adev = to_avs_dev(component->dev);
+
+	acomp->tplg = avs_tplg_new(component);
+	if (!acomp->tplg)
+		return -ENOMEM;
+
+	if (!mach->tplg_filename)
+		goto finalize;
+
+	/* Load specified topology and create sysfs for it. */
+	filename = kasprintf(GFP_KERNEL, "%s/%s",
+			     component->driver->topology_name_prefix,
+			     mach->tplg_filename);
+	if (!filename)
+		return -ENOMEM;
+
+	ret = avs_load_topology(component, filename);
+	kfree(filename);
+	if (ret < 0)
+		return ret;
+
+	ret = avs_component_load_libraries(acomp);
+	if (ret < 0) {
+		dev_err(card->dev, "libraries loading failed: %d\n", ret);
+		goto err_load_libs;
+	}
+
+finalize:
+	debugfs_create_file("topology_name", 0444, component->debugfs_root,
+			    component, &topology_name_fops);
+
+	mutex_lock(&adev->comp_list_mutex);
+	list_add_tail(&acomp->node, &adev->comp_list);
+	mutex_unlock(&adev->comp_list_mutex);
+
+	return 0;
+
+err_load_libs:
+	avs_remove_topology(component);
+	return ret;
+}
+
+static void avs_component_remove(struct snd_soc_component *component)
+{
+	struct avs_soc_component *acomp = to_avs_soc_component(component);
+	struct snd_soc_acpi_mach *mach;
+	struct avs_dev *adev = to_avs_dev(component->dev);
+	int ret;
+
+	mach = dev_get_platdata(component->card->dev);
+
+	mutex_lock(&adev->comp_list_mutex);
+	list_del(&acomp->node);
+	mutex_unlock(&adev->comp_list_mutex);
+
+	if (mach->tplg_filename) {
+		ret = avs_remove_topology(component);
+		if (ret < 0)
+			dev_err(component->dev, "unload topology failed: %d\n", ret);
+	}
+}
+
+static int avs_component_open(struct snd_soc_component *component,
+			      struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+	struct snd_pcm_hardware hwparams;
+
+	/* nothing to do for BE */
+	if (rtd->dai_link->no_pcm)
+		return 0;
+
+	hwparams.info = SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_INTERLEAVED |
+			SNDRV_PCM_INFO_PAUSE |
+			SNDRV_PCM_INFO_NO_PERIOD_WAKEUP;
+
+	hwparams.formats = SNDRV_PCM_FMTBIT_S16_LE |
+			   SNDRV_PCM_FMTBIT_S24_LE |
+			   SNDRV_PCM_FMTBIT_S32_LE;
+	hwparams.period_bytes_min = 128;
+	hwparams.period_bytes_max = AZX_MAX_BUF_SIZE / 2;
+	hwparams.periods_min = 2;
+	hwparams.periods_max = AZX_MAX_FRAG;
+	hwparams.buffer_bytes_max = AZX_MAX_BUF_SIZE;
+	hwparams.fifo_size = 0;
+
+	return snd_soc_set_runtime_hwparams(substream, &hwparams);
+}
+
+static unsigned int avs_hstream_dpib_read(struct hdac_stream *hstream)
+{
+	return readl(hstream->bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
+		     (AZX_REG_VS_SDXDPIB_XINTERVAL * hstream->index));
+}
+
+static snd_pcm_uframes_t
+avs_component_pointer(struct snd_soc_component *component,
+		      struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+	struct avs_pcm_dma_data *data;
+	struct hdac_stream *hstream;
+	unsigned int pos;
+
+	data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
+	if (!data->host_stream)
+		return 0;
+
+	hstream = hdac_stream(data->host_stream);
+	pos = avs_hstream_dpib_read(hstream);
+
+	if (pos >= hstream->bufsize)
+		pos = 0;
+
+	return bytes_to_frames(substream->runtime, pos);
+}
+
+static int avs_component_mmap(struct snd_soc_component *component,
+			      struct snd_pcm_substream *substream,
+			      struct vm_area_struct *vma)
+{
+	return snd_pcm_lib_default_mmap(substream, vma);
+}
+
+#define MAX_PREALLOC_SIZE	(32 * 1024 * 1024)
+
+static int avs_component_construct(struct snd_soc_component *component,
+				   struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
+	struct snd_pcm *pcm = rtd->pcm;
+
+	if (dai->driver->playback.channels_min)
+		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+					   SNDRV_DMA_TYPE_DEV_SG, component->dev,
+					   0, MAX_PREALLOC_SIZE);
+
+	if (dai->driver->capture.channels_min)
+		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+					   SNDRV_DMA_TYPE_DEV_SG, component->dev,
+					   0, MAX_PREALLOC_SIZE);
+
+	return 0;
+}
+
+static const struct snd_soc_component_driver avs_component_driver = {
+	.name			= "avs-pcm",
+	.probe			= avs_component_probe,
+	.remove			= avs_component_remove,
+	.open			= avs_component_open,
+	.pointer		= avs_component_pointer,
+	.mmap			= avs_component_mmap,
+	.pcm_construct		= avs_component_construct,
+	.module_get_upon_open	= 1, /* increment refcount when a pcm is opened */
+	.topology_name_prefix	= "intel/avs",
+	.non_legacy_dai_naming	= true,
+};
+
+__maybe_unused
+static int avs_soc_component_register(struct device *dev, const char *name,
+				      const struct snd_soc_component_driver *drv,
+				      struct snd_soc_dai_driver *cpu_dais,
+				      int num_cpu_dais)
+{
+	struct avs_soc_component *acomp;
+	int ret;
+
+	acomp = devm_kzalloc(dev, sizeof(*acomp), GFP_KERNEL);
+	if (!acomp)
+		return -ENOMEM;
+
+	ret = snd_soc_component_initialize(&acomp->base, drv, dev);
+	if (ret < 0)
+		return ret;
+
+	/* force name change after ASoC is done with its init */
+	acomp->base.name = name;
+	INIT_LIST_HEAD(&acomp->node);
+
+	return snd_soc_add_component(&acomp->base, cpu_dais, num_cpu_dais);
+}
-- 
2.25.1


  parent reply	other threads:[~2021-12-08 11:21 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-08 11:12 [RFC 00/37] ASoC: Intel: AVS - Audio DSP for cAVS Cezary Rojewski
2021-12-08 11:12 ` [RFC 01/37] ALSA: hda: Add snd_hdac_ext_bus_link_at() helper Cezary Rojewski
2021-12-08 11:12 ` [RFC 02/37] ALSA: hda: Update and expose snd_hda_codec_device_init() Cezary Rojewski
2021-12-08 11:12 ` [RFC 03/37] ALSA: hda: Update and expose codec register procedures Cezary Rojewski
2021-12-08 11:12 ` [RFC 04/37] ALSA: hda: Expose codec cleanup and power-save functions Cezary Rojewski
2021-12-08 11:12 ` [RFC 05/37] ALSA: hda: Add helper macros for DSP capable devices Cezary Rojewski
2021-12-08 11:12 ` [RFC 06/37] ASoC: Export DAI register and widget ctor and dctor functions Cezary Rojewski
2021-12-21 13:41   ` Mark Brown
2021-12-21 16:40     ` Cezary Rojewski
2021-12-08 11:12 ` [RFC 07/37] ASoC: Intel: Introduce AVS driver Cezary Rojewski
2021-12-08 11:12 ` [RFC 08/37] ASoC: Intel: avs: Inter process communication Cezary Rojewski
2021-12-08 11:12 ` [RFC 09/37] ASoC: Intel: avs: Add code loading requests Cezary Rojewski
2021-12-08 11:12 ` [RFC 10/37] ASoC: Intel: avs: Add pipeline management requests Cezary Rojewski
2021-12-08 11:12 ` [RFC 11/37] ASoC: Intel: avs: Add module " Cezary Rojewski
2021-12-08 11:12 ` [RFC 12/37] ASoC: Intel: avs: Add power " Cezary Rojewski
2021-12-08 11:12 ` [RFC 13/37] ASoC: Intel: avs: Add ROM requests Cezary Rojewski
2021-12-08 11:12 ` [RFC 14/37] ASoC: Intel: avs: Add basefw runtime-parameter requests Cezary Rojewski
2021-12-08 11:12 ` [RFC 15/37] ASoC: Intel: avs: Firmware resources management utilities Cezary Rojewski
2021-12-08 11:12 ` [RFC 16/37] ASoC: Intel: avs: Declare module configuration types Cezary Rojewski
2021-12-08 11:12 ` [RFC 17/37] ASoC: Intel: avs: Dynamic firmware resources management Cezary Rojewski
2021-12-21 14:40   ` Mark Brown
2021-12-21 17:07     ` Cezary Rojewski
2021-12-08 11:12 ` [RFC 18/37] ASoC: Intel: avs: Topology parsing Cezary Rojewski
2021-12-21 17:39   ` Mark Brown
2021-12-22 14:21     ` Cezary Rojewski
2021-12-08 11:12 ` [RFC 19/37] ASoC: Intel: avs: Path management Cezary Rojewski
2021-12-08 11:12 ` [RFC 20/37] ASoC: Intel: avs: Conditional-path support Cezary Rojewski
2021-12-08 11:12 ` [RFC 21/37] ASoC: Intel: avs: General code loading flow Cezary Rojewski
2021-12-08 11:12 ` [RFC 22/37] ASoC: Intel: avs: Implement CLDMA transfer Cezary Rojewski
2021-12-08 11:12 ` [RFC 23/37] ASoC: Intel: avs: Code loading over CLDMA Cezary Rojewski
2021-12-08 11:12 ` [RFC 24/37] ASoC: Intel: avs: Code loading over HDA Cezary Rojewski
2021-12-08 11:12 ` Cezary Rojewski [this message]
2021-12-08 11:12 ` [RFC 26/37] ASoC: Intel: avs: Generic PCM FE operations Cezary Rojewski
2021-12-08 11:12 ` [RFC 27/37] ASoC: Intel: avs: non-HDA PCM BE operations Cezary Rojewski
2021-12-08 11:12 ` [RFC 28/37] ASoC: Intel: avs: HDA " Cezary Rojewski
2021-12-08 11:12 ` [RFC 29/37] ASoC: Intel: avs: Coredump and recovery flow Cezary Rojewski
2021-12-08 11:12 ` [RFC 30/37] ASoC: Intel: avs: Prepare for firmware tracing Cezary Rojewski
2021-12-08 11:12 ` [RFC 31/37] ASoC: Intel: avs: D0ix power state support Cezary Rojewski
2021-12-08 11:12 ` [RFC 32/37] ASoC: Intel: avs: Event tracing Cezary Rojewski
2021-12-08 11:12 ` [RFC 33/37] ASoC: Intel: avs: Machine board registration Cezary Rojewski
2021-12-08 11:12 ` [RFC 34/37] ASoC: Intel: avs: PCI driver implementation Cezary Rojewski
2021-12-08 11:12 ` [RFC 35/37] ASoC: Intel: avs: Power management Cezary Rojewski
2021-12-08 11:13 ` [RFC 36/37] ASoC: Intel: avs: SKL-based platforms support Cezary Rojewski
2021-12-08 11:13 ` [RFC 37/37] ASoC: Intel: avs: APL-based " Cezary Rojewski
2021-12-08 16:27 ` [RFC 00/37] ASoC: Intel: AVS - Audio DSP for cAVS Pierre-Louis Bossart
2021-12-08 17:51   ` Mark Brown
2021-12-09  9:59   ` Cezary Rojewski
2021-12-24 13:06 ` Mark Brown
2022-01-06 13:39   ` Cezary Rojewski
2022-01-18  9:42     ` Cezary Rojewski
2022-01-25 13:25       ` Mark Brown
2022-01-28 17:00     ` Mark Brown
2022-01-30 19:15       ` Cezary Rojewski
2022-02-02 13:26         ` Amadeusz Sławiński
2022-02-02 16:08           ` Mark Brown
2022-02-02 14:41         ` Mark Brown
2022-02-07 13:42           ` Cezary Rojewski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211208111301.1817725-26-cezary.rojewski@intel.com \
    --to=cezary.rojewski@intel.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=amadeuszx.slawinski@linux.intel.com \
    --cc=broonie@kernel.org \
    --cc=cujomalainey@chromium.org \
    --cc=harshapriya.n@intel.com \
    --cc=hdegoede@redhat.com \
    --cc=lma@semihalf.com \
    --cc=peter.ujfalusi@linux.intel.com \
    --cc=pierre-louis.bossart@linux.intel.com \
    --cc=rad@semihalf.com \
    --cc=ranjani.sridharan@linux.intel.com \
    --cc=tiwai@suse.com \
    --cc=upstream@semihalf.com \
    --cc=yung-chuan.liao@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.