Unverified Commit 8e378ea1 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: Intel: avs: Data probing and fw logging

Merge series from Cezary Rojewski <cezary.rojewski@intel.com>:

The patchset focuses on debug functionality for the avs-driver.
Two major blocks are covered here: data probing and AudioDSP firmware
logging. Both are configured and controlled through debugfs.

Data probing is a AudioDSP debug functionality which allows for
gathering the actual data that is being routed to or from a module.
Helps in debugging its processing capabilities - navigate to a specific
module which may have caused a glitch within a pipeline (set of modules
bound together).

First few allow for assigning compress stream to a HDAudio stream, what
is currently limited to pcm substreams only. These patches were already
present on this list and reviewed in the past [1].

The next few tidy existing debug-related code up so it's ready for
addition of new functionalities and make it clear which part of the avs
is debug related and which is not. These also simplify the existing
locking around the trace fifo.

Afterward, debug-related IPCs are defined along with stub soc-component
and compress DAI operations. Not much is done there as it's not a
standard PCM streaming scenario. Most code found in compress operations
is inherited from the HOST side of HDAudio streaming found in pcm.c
file of the driver.

Finally, a debugfs file operations are defined. These facilitate
connecting to DSP modules from which the data shall be gathered as well
as control and configuration of firmware logging. Additionally, entries
are added to allow for dumping snapshots of key memory windows.
parents 1b41beaa 85ac9c8c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -75,6 +75,8 @@ struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
					   struct snd_pcm_substream *substream,
					   int type);
void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type);
struct hdac_ext_stream *snd_hdac_ext_cstream_assign(struct hdac_bus *bus,
						    struct snd_compr_stream *cstream);
void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus,
					 struct hdac_ext_stream *hext_stream, bool decouple);
void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
+41 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <sound/pcm.h>
#include <sound/hda_register.h>
#include <sound/hdaudio_ext.h>
#include <sound/compress_driver.h>

/**
 * snd_hdac_ext_stream_init - initialize each stream (aka device)
@@ -367,3 +368,43 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type)

}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_release);

/**
 * snd_hdac_ext_cstream_assign - assign a host stream for compress
 * @bus: HD-audio core bus
 * @cstream: Compress stream to assign
 *
 * Assign an unused host stream for the given compress stream.
 * If no stream is free, NULL is returned. Stream is decoupled
 * before assignment.
 */
struct hdac_ext_stream *snd_hdac_ext_cstream_assign(struct hdac_bus *bus,
						    struct snd_compr_stream *cstream)
{
	struct hdac_ext_stream *res = NULL;
	struct hdac_stream *hstream;

	spin_lock_irq(&bus->reg_lock);
	list_for_each_entry(hstream, &bus->stream_list, list) {
		struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);

		if (hstream->direction != cstream->direction)
			continue;

		if (!hstream->opened) {
			res = hext_stream;
			break;
		}
	}

	if (res) {
		snd_hdac_ext_stream_decouple_locked(bus, res, true);
		res->hstream.opened = 1;
		res->hstream.running = 0;
		res->hstream.cstream = cstream;
	}
	spin_unlock_irq(&bus->reg_lock);

	return res;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_cstream_assign);
+2 −2
Original line number Diff line number Diff line
@@ -578,8 +578,8 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
			sd_status = snd_hdac_stream_readb(azx_dev, SD_STS);
			snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
			handled |= 1 << azx_dev->index;
			if (!azx_dev->substream || !azx_dev->running ||
			    !(sd_status & SD_INT_COMPLETE))
			if ((!azx_dev->substream && !azx_dev->cstream) ||
			    !azx_dev->running || !(sd_status & SD_INT_COMPLETE))
				continue;
			if (ack)
				ack(bus, azx_dev);
+32 −19
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/clocksource.h>
#include <sound/compress_driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/hdaudio.h>
@@ -487,11 +488,20 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
{
	struct hdac_bus *bus = azx_dev->bus;
	struct snd_pcm_substream *substream = azx_dev->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_compr_stream *cstream = azx_dev->cstream;
	struct snd_pcm_runtime *runtime = NULL;
	struct snd_dma_buffer *dmab;
	__le32 *bdl;
	int i, ofs, periods, period_bytes;
	int pos_adj, pos_align;

	if (substream) {
		runtime = substream->runtime;
		dmab = snd_pcm_get_dma_buf(substream);
	} else if (cstream) {
		dmab = snd_pcm_get_dma_buf(cstream);
	}

	/* reset BDL address */
	snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0);
	snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0);
@@ -505,7 +515,7 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
	azx_dev->frags = 0;

	pos_adj = bus->bdl_pos_adj;
	if (!azx_dev->no_period_wakeup && pos_adj > 0) {
	if (runtime && !azx_dev->no_period_wakeup && pos_adj > 0) {
		pos_align = pos_adj;
		pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000);
		if (!pos_adj)
@@ -518,8 +528,7 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
				 pos_adj);
			pos_adj = 0;
		} else {
			ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
					 azx_dev,
			ofs = setup_bdle(bus, dmab, azx_dev,
					 &bdl, ofs, pos_adj, true);
			if (ofs < 0)
				goto error;
@@ -529,13 +538,11 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)

	for (i = 0; i < periods; i++) {
		if (i == periods - 1 && pos_adj)
			ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
					 azx_dev, &bdl, ofs,
					 period_bytes - pos_adj, 0);
			ofs = setup_bdle(bus, dmab, azx_dev,
					 &bdl, ofs, period_bytes - pos_adj, 0);
		else
			ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
					 azx_dev, &bdl, ofs,
					 period_bytes,
			ofs = setup_bdle(bus, dmab, azx_dev,
					 &bdl, ofs, period_bytes,
					 !azx_dev->no_period_wakeup);
		if (ofs < 0)
			goto error;
@@ -560,26 +567,32 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_setup_periods);
int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
				 unsigned int format_val)
{

	unsigned int bufsize, period_bytes;
	struct snd_pcm_substream *substream = azx_dev->substream;
	struct snd_pcm_runtime *runtime;
	struct snd_compr_stream *cstream = azx_dev->cstream;
	unsigned int bufsize, period_bytes;
	unsigned int no_period_wakeup;
	int err;

	if (!substream)
		return -EINVAL;
	runtime = substream->runtime;
	if (substream) {
		bufsize = snd_pcm_lib_buffer_bytes(substream);
		period_bytes = snd_pcm_lib_period_bytes(substream);
		no_period_wakeup = substream->runtime->no_period_wakeup;
	} else if (cstream) {
		bufsize = cstream->runtime->buffer_size;
		period_bytes = cstream->runtime->fragment_size;
		no_period_wakeup = 0;
	} else {
		return -EINVAL;
	}

	if (bufsize != azx_dev->bufsize ||
	    period_bytes != azx_dev->period_bytes ||
	    format_val != azx_dev->format_val ||
	    runtime->no_period_wakeup != azx_dev->no_period_wakeup) {
	    no_period_wakeup != azx_dev->no_period_wakeup) {
		azx_dev->bufsize = bufsize;
		azx_dev->period_bytes = period_bytes;
		azx_dev->format_val = format_val;
		azx_dev->no_period_wakeup = runtime->no_period_wakeup;
		azx_dev->no_period_wakeup = no_period_wakeup;
		err = snd_hdac_stream_setup_periods(azx_dev);
		if (err < 0)
			return err;
+1 −0
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ config SND_SOC_INTEL_AVS
	select SND_SOC_ACPI if ACPI
	select SND_SOC_TOPOLOGY
	select SND_SOC_HDA
	select SND_SOC_COMPRESS if DEBUG_FS
	select SND_HDA_EXT_CORE
	select SND_HDA_DSP_LOADER
	select SND_INTEL_DSP_CONFIG
Loading