Unverified Commit ee1e79b7 authored by Ranjani Sridharan's avatar Ranjani Sridharan Committed by Mark Brown
Browse files

ASoC: SOF: partition audio-related parts from SOF core



Move all the audio-specific code in the core,
audio-specific logic in the top-level PM callbacks
and the core header files into a separate file
(sof-audio.*) in preparation for adding an
audio client device.

In the process of moving all structure definitions
for widget, routes, pcm's etc, the snd_sof_dev
member in all these structs is replaced with
the snd_soc_component member. Also, use the component
device instead of the snd_sof_dev device wherever
possible in the PCM component driver,
control IO functions and the topology parser as the
component device will be moved over to the client
device later on.

Signed-off-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20191204211556.12671-9-pierre-louis.bossart@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 03eec9b4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)

snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
		control.o trace.o utils.o
		control.o trace.o utils.o sof-audio.o

snd-sof-pci-objs := sof-pci-dev.o
snd-sof-acpi-objs := sof-acpi-dev.o
+28 −27
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/pm_runtime.h>
#include <linux/leds.h>
#include "sof-priv.h"
#include "sof-audio.h"

static void update_mute_led(struct snd_sof_control *scontrol,
			    struct snd_kcontrol *kcontrol,
@@ -88,7 +89,7 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
	struct soc_mixer_control *sm =
		(struct soc_mixer_control *)kcontrol->private_value;
	struct snd_sof_control *scontrol = sm->dobj.private;
	struct snd_sof_dev *sdev = scontrol->sdev;
	struct snd_soc_component *scomp = scontrol->scomp;
	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
	unsigned int i, channels = scontrol->num_channels;
	bool change = false;
@@ -104,8 +105,8 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
	}

	/* notify DSP of mixer updates */
	if (pm_runtime_active(sdev->dev))
		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
	if (pm_runtime_active(scomp->dev))
		snd_sof_ipc_set_get_comp_data(scontrol,
					      SOF_IPC_COMP_SET_VALUE,
					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
					      SOF_CTRL_CMD_VOLUME,
@@ -135,7 +136,7 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
	struct soc_mixer_control *sm =
		(struct soc_mixer_control *)kcontrol->private_value;
	struct snd_sof_control *scontrol = sm->dobj.private;
	struct snd_sof_dev *sdev = scontrol->sdev;
	struct snd_soc_component *scomp = scontrol->scomp;
	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
	unsigned int i, channels = scontrol->num_channels;
	bool change = false;
@@ -153,8 +154,8 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
		update_mute_led(scontrol, kcontrol, ucontrol);

	/* notify DSP of mixer updates */
	if (pm_runtime_active(sdev->dev))
		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
	if (pm_runtime_active(scomp->dev))
		snd_sof_ipc_set_get_comp_data(scontrol,
					      SOF_IPC_COMP_SET_VALUE,
					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
					      SOF_CTRL_CMD_SWITCH,
@@ -185,7 +186,7 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
	struct soc_enum *se =
		(struct soc_enum *)kcontrol->private_value;
	struct snd_sof_control *scontrol = se->dobj.private;
	struct snd_sof_dev *sdev = scontrol->sdev;
	struct snd_soc_component *scomp = scontrol->scomp;
	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
	unsigned int i, channels = scontrol->num_channels;
	bool change = false;
@@ -200,8 +201,8 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
	}

	/* notify DSP of enum updates */
	if (pm_runtime_active(sdev->dev))
		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
	if (pm_runtime_active(scomp->dev))
		snd_sof_ipc_set_get_comp_data(scontrol,
					      SOF_IPC_COMP_SET_VALUE,
					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
					      SOF_CTRL_CMD_ENUM,
@@ -216,14 +217,14 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
	struct soc_bytes_ext *be =
		(struct soc_bytes_ext *)kcontrol->private_value;
	struct snd_sof_control *scontrol = be->dobj.private;
	struct snd_sof_dev *sdev = scontrol->sdev;
	struct snd_soc_component *scomp = scontrol->scomp;
	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
	struct sof_abi_hdr *data = cdata->data;
	size_t size;
	int ret = 0;

	if (be->max > sizeof(ucontrol->value.bytes.data)) {
		dev_err_ratelimited(sdev->dev,
		dev_err_ratelimited(scomp->dev,
				    "error: data max %d exceeds ucontrol data array size\n",
				    be->max);
		return -EINVAL;
@@ -231,7 +232,7 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,

	size = data->size + sizeof(*data);
	if (size > be->max) {
		dev_err_ratelimited(sdev->dev,
		dev_err_ratelimited(scomp->dev,
				    "error: DSP sent %zu bytes max is %d\n",
				    size, be->max);
		ret = -EINVAL;
@@ -251,20 +252,20 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
	struct soc_bytes_ext *be =
		(struct soc_bytes_ext *)kcontrol->private_value;
	struct snd_sof_control *scontrol = be->dobj.private;
	struct snd_sof_dev *sdev = scontrol->sdev;
	struct snd_soc_component *scomp = scontrol->scomp;
	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
	struct sof_abi_hdr *data = cdata->data;
	size_t size = data->size + sizeof(*data);

	if (be->max > sizeof(ucontrol->value.bytes.data)) {
		dev_err_ratelimited(sdev->dev,
		dev_err_ratelimited(scomp->dev,
				    "error: data max %d exceeds ucontrol data array size\n",
				    be->max);
		return -EINVAL;
	}

	if (size > be->max) {
		dev_err_ratelimited(sdev->dev,
		dev_err_ratelimited(scomp->dev,
				    "error: size too big %zu bytes max is %d\n",
				    size, be->max);
		return -EINVAL;
@@ -274,8 +275,8 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
	memcpy(data, ucontrol->value.bytes.data, size);

	/* notify DSP of byte control updates */
	if (pm_runtime_active(sdev->dev))
		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
	if (pm_runtime_active(scomp->dev))
		snd_sof_ipc_set_get_comp_data(scontrol,
					      SOF_IPC_COMP_SET_DATA,
					      SOF_CTRL_TYPE_DATA_SET,
					      scontrol->cmd,
@@ -291,7 +292,7 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
	struct soc_bytes_ext *be =
		(struct soc_bytes_ext *)kcontrol->private_value;
	struct snd_sof_control *scontrol = be->dobj.private;
	struct snd_sof_dev *sdev = scontrol->sdev;
	struct snd_soc_component *scomp = scontrol->scomp;
	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
	struct snd_ctl_tlv header;
	const struct snd_ctl_tlv __user *tlvd =
@@ -307,14 +308,14 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,

	/* be->max is coming from topology */
	if (header.length > be->max) {
		dev_err_ratelimited(sdev->dev, "error: Bytes data size %d exceeds max %d.\n",
		dev_err_ratelimited(scomp->dev, "error: Bytes data size %d exceeds max %d.\n",
				    header.length, be->max);
		return -EINVAL;
	}

	/* Check that header id matches the command */
	if (header.numid != scontrol->cmd) {
		dev_err_ratelimited(sdev->dev,
		dev_err_ratelimited(scomp->dev,
				    "error: incorrect numid %d\n",
				    header.numid);
		return -EINVAL;
@@ -324,26 +325,26 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
		return -EFAULT;

	if (cdata->data->magic != SOF_ABI_MAGIC) {
		dev_err_ratelimited(sdev->dev,
		dev_err_ratelimited(scomp->dev,
				    "error: Wrong ABI magic 0x%08x.\n",
				    cdata->data->magic);
		return -EINVAL;
	}

	if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
		dev_err_ratelimited(sdev->dev, "error: Incompatible ABI version 0x%08x.\n",
		dev_err_ratelimited(scomp->dev, "error: Incompatible ABI version 0x%08x.\n",
				    cdata->data->abi);
		return -EINVAL;
	}

	if (cdata->data->size + sizeof(const struct sof_abi_hdr) > be->max) {
		dev_err_ratelimited(sdev->dev, "error: Mismatch in ABI data size (truncated?).\n");
		dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n");
		return -EINVAL;
	}

	/* notify DSP of byte control updates */
	if (pm_runtime_active(sdev->dev))
		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
	if (pm_runtime_active(scomp->dev))
		snd_sof_ipc_set_get_comp_data(scontrol,
					      SOF_IPC_COMP_SET_DATA,
					      SOF_CTRL_TYPE_DATA_SET,
					      scontrol->cmd,
@@ -359,7 +360,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
	struct soc_bytes_ext *be =
		(struct soc_bytes_ext *)kcontrol->private_value;
	struct snd_sof_control *scontrol = be->dobj.private;
	struct snd_sof_dev *sdev = scontrol->sdev;
	struct snd_soc_component *scomp = scontrol->scomp;
	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
	struct snd_ctl_tlv header;
	struct snd_ctl_tlv __user *tlvd =
@@ -382,7 +383,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,

	/* check data size doesn't exceed max coming from topology */
	if (data_size > be->max) {
		dev_err_ratelimited(sdev->dev, "error: user data size %d exceeds max size %d.\n",
		dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %d.\n",
				    data_size, be->max);
		ret = -EINVAL;
		goto out;
+0 −120
Original line number Diff line number Diff line
@@ -24,126 +24,6 @@ MODULE_PARM_DESC(sof_debug, "SOF core debug options (0x0 all off)");
#define TIMEOUT_DEFAULT_IPC_MS  500
#define TIMEOUT_DEFAULT_BOOT_MS 2000

/*
 * Generic object lookup APIs.
 */

struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_sof_dev *sdev,
					   const char *name)
{
	struct snd_sof_pcm *spcm;

	list_for_each_entry(spcm, &sdev->pcm_list, list) {
		/* match with PCM dai name */
		if (strcmp(spcm->pcm.dai_name, name) == 0)
			return spcm;

		/* match with playback caps name if set */
		if (*spcm->pcm.caps[0].name &&
		    !strcmp(spcm->pcm.caps[0].name, name))
			return spcm;

		/* match with capture caps name if set */
		if (*spcm->pcm.caps[1].name &&
		    !strcmp(spcm->pcm.caps[1].name, name))
			return spcm;
	}

	return NULL;
}

struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_sof_dev *sdev,
					   unsigned int comp_id,
					   int *direction)
{
	struct snd_sof_pcm *spcm;

	list_for_each_entry(spcm, &sdev->pcm_list, list) {
		if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].comp_id == comp_id) {
			*direction = SNDRV_PCM_STREAM_PLAYBACK;
			return spcm;
		}
		if (spcm->stream[SNDRV_PCM_STREAM_CAPTURE].comp_id == comp_id) {
			*direction = SNDRV_PCM_STREAM_CAPTURE;
			return spcm;
		}
	}

	return NULL;
}

struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_sof_dev *sdev,
					     unsigned int pcm_id)
{
	struct snd_sof_pcm *spcm;

	list_for_each_entry(spcm, &sdev->pcm_list, list) {
		if (le32_to_cpu(spcm->pcm.pcm_id) == pcm_id)
			return spcm;
	}

	return NULL;
}

struct snd_sof_widget *snd_sof_find_swidget(struct snd_sof_dev *sdev,
					    const char *name)
{
	struct snd_sof_widget *swidget;

	list_for_each_entry(swidget, &sdev->widget_list, list) {
		if (strcmp(name, swidget->widget->name) == 0)
			return swidget;
	}

	return NULL;
}

/* find widget by stream name and direction */
struct snd_sof_widget *snd_sof_find_swidget_sname(struct snd_sof_dev *sdev,
						  const char *pcm_name, int dir)
{
	struct snd_sof_widget *swidget;
	enum snd_soc_dapm_type type;

	if (dir == SNDRV_PCM_STREAM_PLAYBACK)
		type = snd_soc_dapm_aif_in;
	else
		type = snd_soc_dapm_aif_out;

	list_for_each_entry(swidget, &sdev->widget_list, list) {
		if (!strcmp(pcm_name, swidget->widget->sname) && swidget->id == type)
			return swidget;
	}

	return NULL;
}

struct snd_sof_dai *snd_sof_find_dai(struct snd_sof_dev *sdev,
				     const char *name)
{
	struct snd_sof_dai *dai;

	list_for_each_entry(dai, &sdev->dai_list, list) {
		if (dai->name && (strcmp(name, dai->name) == 0))
			return dai;
	}

	return NULL;
}

bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev)
{
	struct snd_sof_pcm *spcm;

	list_for_each_entry(spcm, &sdev->pcm_list, list) {
		if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].suspend_ignored ||
		    spcm->stream[SNDRV_PCM_STREAM_CAPTURE].suspend_ignored)
			return true;
	}

	return false;
}

/*
 * FW Panic/fault handling.
 */
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <sound/pcm_params.h>
#include <sound/hdaudio_ext.h>
#include "../sof-priv.h"
#include "../sof-audio.h"
#include "hda.h"

#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+3 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

#include <sound/hda_register.h>
#include <sound/pcm_params.h>
#include "../sof-audio.h"
#include "../ops.h"
#include "hda.h"

@@ -147,12 +148,13 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
				      struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_component *scomp = sdev->component;
	struct hdac_stream *hstream = substream->runtime->private_data;
	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
	struct snd_sof_pcm *spcm;
	snd_pcm_uframes_t pos;

	spcm = snd_sof_find_spcm_dai(sdev, rtd);
	spcm = snd_sof_find_spcm_dai(scomp, rtd);
	if (!spcm) {
		dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
				     rtd->dai_link->id);
Loading