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

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.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 03eec9b4
# 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
......
......@@ -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;
......
......@@ -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.
*/
......
......@@ -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)
......
......@@ -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);
......
......@@ -20,6 +20,7 @@
#include <sound/hda_register.h>
#include <sound/sof.h>
#include "../ops.h"
#include "../sof-audio.h"
#include "hda.h"
/*
......
......@@ -15,6 +15,7 @@
#include <linux/types.h>
#include "sof-priv.h"
#include "sof-audio.h"
#include "ops.h"
static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_id);
......@@ -412,12 +413,13 @@ static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_id)
static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
{
struct snd_soc_component *scomp = sdev->component;
struct snd_sof_pcm_stream *stream;
struct sof_ipc_stream_posn posn;
struct snd_sof_pcm *spcm;
int direction;
spcm = snd_sof_find_spcm_comp(sdev, msg_id, &direction);
spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
if (!spcm) {
dev_err(sdev->dev,
"error: period elapsed for unknown stream, msg_id %d\n",
......@@ -441,12 +443,13 @@ static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
/* DSP notifies host of an XRUN within FW */
static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id)
{
struct snd_soc_component *scomp = sdev->component;
struct snd_sof_pcm_stream *stream;
struct sof_ipc_stream_posn posn;
struct snd_sof_pcm *spcm;
int direction;
spcm = snd_sof_find_spcm_comp(sdev, msg_id, &direction);
spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
if (!spcm) {
dev_err(sdev->dev, "error: XRUN for unknown stream, msg_id %d\n",
msg_id);
......@@ -488,10 +491,11 @@ static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd)
}
/* get stream position IPC - use faster MMIO method if available on platform */
int snd_sof_ipc_stream_posn(struct snd_sof_dev *sdev,
int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
struct snd_sof_pcm *spcm, int direction,
struct sof_ipc_stream_posn *posn)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc_stream stream;
int err;
......@@ -620,15 +624,15 @@ static int sof_set_get_large_ctrl_data(struct snd_sof_dev *sdev,
/*
* IPC get()/set() for kcontrols.
*/
int snd_sof_ipc_set_get_comp_data(struct snd_sof_ipc *ipc,
struct snd_sof_control *scontrol,
int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol,
u32 ipc_cmd,
enum sof_ipc_ctrl_type ctrl_type,
enum sof_ipc_ctrl_cmd ctrl_cmd,
bool send)
{
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
struct snd_sof_dev *sdev = ipc->sdev;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &ready->version;
struct sof_ipc_ctrl_data_params sparams;
......
This diff is collapsed.
......@@ -10,192 +10,7 @@
#include "ops.h"
#include "sof-priv.h"
static int sof_restore_kcontrols(struct snd_sof_dev *sdev)
{
struct snd_sof_control *scontrol;
int ipc_cmd, ctrl_type;
int ret = 0;
/* restore kcontrol values */
list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
/* reset readback offset for scontrol after resuming */
scontrol->readback_offset = 0;
/* notify DSP of kcontrol values */
switch (scontrol->cmd) {
case SOF_CTRL_CMD_VOLUME:
case SOF_CTRL_CMD_ENUM:
case SOF_CTRL_CMD_SWITCH:
ipc_cmd = SOF_IPC_COMP_SET_VALUE;
ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET;
ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
ipc_cmd, ctrl_type,
scontrol->cmd,
true);
break;
case SOF_CTRL_CMD_BINARY:
ipc_cmd = SOF_IPC_COMP_SET_DATA;
ctrl_type = SOF_CTRL_TYPE_DATA_SET;
ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
ipc_cmd, ctrl_type,
scontrol->cmd,
true);
break;
default:
break;
}
if (ret < 0) {
dev_err(sdev->dev,
"error: failed kcontrol value set for widget: %d\n",
scontrol->comp_id);
return ret;
}
}
return 0;
}
static int sof_restore_pipelines(struct snd_sof_dev *sdev)
{
struct snd_sof_widget *swidget;
struct snd_sof_route *sroute;
struct sof_ipc_pipe_new *pipeline;
struct snd_sof_dai *dai;
struct sof_ipc_comp_dai *comp_dai;
struct sof_ipc_cmd_hdr *hdr;
int ret;
/* restore pipeline components */
list_for_each_entry_reverse(swidget, &sdev->widget_list, list) {
struct sof_ipc_comp_reply r;
/* skip if there is no private data */
if (!swidget->private)
continue;
switch (swidget->id) {
case snd_soc_dapm_dai_in:
case snd_soc_dapm_dai_out:
dai = swidget->private;
comp_dai = &dai->comp_dai;
ret = sof_ipc_tx_message(sdev->ipc,
comp_dai->comp.hdr.cmd,
comp_dai, sizeof(*comp_dai),
&r, sizeof(r));
break;
case snd_soc_dapm_scheduler:
/*
* During suspend, all DSP cores are powered off.
* Therefore upon resume, create the pipeline comp
* and power up the core that the pipeline is
* scheduled on.
*/
pipeline = swidget->private;
ret = sof_load_pipeline_ipc(sdev, pipeline, &r);
break;
default:
hdr = swidget->private;
ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd,
swidget->private, hdr->size,
&r, sizeof(r));
break;
}
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to load widget type %d with ID: %d\n",
swidget->widget->id, swidget->comp_id);
return ret;
}
}
/* restore pipeline connections */
list_for_each_entry_reverse(sroute, &sdev->route_list, list) {
struct sof_ipc_pipe_comp_connect *connect;
struct sof_ipc_reply reply;
/* skip if there's no private data */
if (!sroute->private)
continue;
connect = sroute->private;
/* send ipc */
ret = sof_ipc_tx_message(sdev->ipc,
connect->hdr.cmd,
connect, sizeof(*connect),
&reply, sizeof(reply));
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to load route sink %s control %s source %s\n",
sroute->route->sink,
sroute->route->control ? sroute->route->control
: "none",
sroute->route->source);
return ret;
}
}
/* restore dai links */
list_for_each_entry_reverse(dai, &sdev->dai_list, list) {
struct sof_ipc_reply reply;
struct sof_ipc_dai_config *config = dai->dai_config;
if (!config) {
dev_err(sdev->dev, "error: no config for DAI %s\n",
dai->name);
continue;
}
/*
* The link DMA channel would be invalidated for running
* streams but not for streams that were in the PAUSED
* state during suspend. So invalidate it here before setting
* the dai config in the DSP.
*/
if (config->type == SOF_DAI_INTEL_HDA)
config->hda.link_dma_ch = DMA_CHAN_INVALID;
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config,
config->hdr.size,
&reply, sizeof(reply));
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to set dai config for %s\n",
dai->name);
return ret;
}
}
/* complete pipeline */
list_for_each_entry(swidget, &sdev->widget_list, list) {
switch (swidget->id) {
case snd_soc_dapm_scheduler:
swidget->complete =
snd_sof_complete_pipeline(sdev, swidget);
break;
default:
break;
}
}
/* restore pipeline kcontrols */
ret = sof_restore_kcontrols(sdev);
if (ret < 0)
dev_err(sdev->dev,
"error: restoring kcontrols after resume\n");
return ret;
}
#include "sof-audio.h"
static int sof_send_pm_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
{
......@@ -213,34 +28,6 @@ static int sof_send_pm_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
sizeof(pm_ctx), &reply, sizeof(reply));
}
static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
{
struct snd_pcm_substream *substream;
struct snd_sof_pcm *spcm;
snd_pcm_state_t state;
int dir;
/*
* SOF requires hw_params to be set-up internally upon resume.
* So, set the flag to indicate this for those streams that
* have been suspended.
*/
list_for_each_entry(spcm, &sdev->pcm_list, list) {
for (dir = 0; dir <= SNDRV_PCM_STREAM_CAPTURE; dir++) {
substream = spcm->stream[dir].substream;
if (!substream || !substream->runtime)
continue;
state = substream->runtime->status->state;
if (state == SNDRV_PCM_STATE_SUSPENDED)
spcm->prepared[dir] = false;
}
}
/* set internal flag for BE */
return snd_sof_dsp_hw_params_upon_resume(sdev);
}
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
static void sof_cache_debugfs(struct snd_sof_dev *sdev)
{
......@@ -311,7 +98,7 @@ static int sof_resume(struct device *dev, bool runtime_resume)
}
/* restore pipelines */
ret = sof_restore_pipelines(sdev);
ret = sof_restore_pipelines(sdev->dev);
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to restore pipeline after resume %d\n",
......@@ -346,7 +133,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
/* set restore_stream for all streams during system suspend */
if (!runtime_suspend) {
ret = sof_set_hw_params_upon_resume(sdev);
ret = sof_set_hw_params_upon_resume(sdev->dev);
if (ret < 0) {
dev_err(sdev->dev,
"error: setting hw_params flag during suspend %d\n",
......
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
//
// This file is provided under a dual BSD/GPLv2 license. When using or
// redistributing this file, you may do so under either license.
//
// Copyright(c) 2019 Intel Corporation. All rights reserved.
//
// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
//
#include "sof-audio.h"
#include "ops.h"
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;
}
int sof_set_hw_params_upon_resume(struct device *dev)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_pcm_substream *substream;
struct snd_sof_pcm *spcm;
snd_pcm_state_t state;
int dir;
/*
* SOF requires hw_params to be set-up internally upon resume.
* So, set the flag to indicate this for those streams that
* have been suspended.
*/
list_for_each_entry(spcm, &sdev->pcm_list, list) {
for (dir = 0; dir <= SNDRV_PCM_STREAM_CAPTURE; dir++) {
substream = spcm->stream[dir].substream;
if (!substream || !substream->runtime)
continue;
state = substream->runtime->status->state;
if (state == SNDRV_PCM_STATE_SUSPENDED)
spcm->prepared[dir] = false;
}
}
/* set internal flag for BE */
return snd_sof_dsp_hw_params_upon_resume(sdev);
}
static int sof_restore_kcontrols(struct device *dev)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_sof_control *scontrol;
int ipc_cmd, ctrl_type;
int ret = 0;
/* restore kcontrol values */
list_for_each_entry(scontrol, &sdev->kcontrol_list, list) {
/* reset readback offset for scontrol after resuming */
scontrol->readback_offset = 0;
/* notify DSP of kcontrol values */
switch (scontrol->cmd) {
case SOF_CTRL_CMD_VOLUME:
case SOF_CTRL_CMD_ENUM:
case SOF_CTRL_CMD_SWITCH:
ipc_cmd = SOF_IPC_COMP_SET_VALUE;
ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET;
ret = snd_sof_ipc_set_get_comp_data(scontrol,
ipc_cmd, ctrl_type,
scontrol->cmd,
true);
break;
case SOF_CTRL_CMD_BINARY:
ipc_cmd = SOF_IPC_COMP_SET_DATA;
ctrl_type = SOF_CTRL_TYPE_DATA_SET;
ret = snd_sof_ipc_set_get_comp_data(scontrol,
ipc_cmd, ctrl_type,
scontrol->cmd,
true);
break;
default:
break;
}
if (ret < 0) {
dev_err(dev,
"error: failed kcontrol value set for widget: %d\n",
scontrol->comp_id);
return ret;
}
}
return 0;
}
int sof_restore_pipelines(struct device *dev)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_sof_widget *swidget;
struct snd_sof_route *sroute;
struct sof_ipc_pipe_new *pipeline;
struct snd_sof_dai *dai;
struct sof_ipc_comp_dai *comp_dai;
struct sof_ipc_cmd_hdr *hdr;
int ret;
/* restore pipeline components */
list_for_each_entry_reverse(swidget, &sdev->widget_list, list) {
struct sof_ipc_comp_reply r;
/* skip if there is no private data */
if (!swidget->private)
continue;
switch (swidget->id) {
case snd_soc_dapm_dai_in:
case snd_soc_dapm_dai_out:
dai = swidget->private;
comp_dai = &dai->comp_dai;
ret = sof_ipc_tx_message(sdev->ipc,
comp_dai->comp.hdr.cmd,
comp_dai, sizeof(*comp_dai),
&r, sizeof(r));
break;
case snd_soc_dapm_scheduler:
/*
* During suspend, all DSP cores are powered off.
* Therefore upon resume, create the pipeline comp
* and power up the core that the pipeline is
* scheduled on.
*/
pipeline = swidget->private;
ret = sof_load_pipeline_ipc(dev, pipeline, &r);
break;
default:
hdr = swidget->private;
ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd,
swidget->private, hdr->size,
&r, sizeof(r));
break;
}
if (ret < 0) {
dev_err(dev,
"error: failed to load widget type %d with ID: %d\n",
swidget->widget->id, swidget->comp_id);
return ret;
}
}
/* restore pipeline connections */
list_for_each_entry_reverse(sroute, &sdev->route_list, list) {
struct sof_ipc_pipe_comp_connect *connect;
struct sof_ipc_reply reply;
/* skip if there's no private data */
if (!sroute->private)
continue;
connect = sroute->private;
/* send ipc */
ret = sof_ipc_tx_message(sdev->ipc,
connect->hdr.cmd,
connect, sizeof(*connect),
&reply, sizeof(reply));
if (ret < 0) {
dev_err(dev,
"error: failed to load route sink %s control %s source %s\n",
sroute->route->sink,
sroute->route->control ? sroute->route->control
: "none",
sroute->route->source);
return ret;
}
}
/* restore dai links */
list_for_each_entry_reverse(dai, &sdev->dai_list, list) {
struct sof_ipc_reply reply;
struct sof_ipc_dai_config *config = dai->dai_config;
if (!config) {
dev_err(dev, "error: no config for DAI %s\n",
dai->name);
continue;
}
/*
* The link DMA channel would be invalidated for running
* streams but not for streams that were in the PAUSED
* state during suspend. So invalidate it here before setting
* the dai config in the DSP.
*/
if (config->type == SOF_DAI_INTEL_HDA)
config->hda.link_dma_ch = DMA_CHAN_INVALID;
ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config,
config->hdr.size,
&reply, sizeof(reply));
if (ret < 0) {
dev_err(dev,
"error: failed to set dai config for %s\n",
dai->name);
return ret;
}
}
/* complete pipeline */
list_for_each_entry(swidget, &sdev->widget_list, list) {
switch (swidget->id) {
case snd_soc_dapm_scheduler:
swidget->complete =
snd_sof_complete_pipeline(dev, swidget);
break;
default:
break;
}
}
/* restore pipeline kcontrols */
ret = sof_restore_kcontrols(dev);
if (ret < 0)
dev_err(dev,
"error: restoring kcontrols after resume\n");
return ret;
}
/*
* Generic object lookup APIs.
*/
struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp,
const char *name)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
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_soc_component *scomp,
unsigned int comp_id,
int *direction)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct snd_sof_pcm *spcm;
int dir;
list_for_each_entry(spcm, &sdev->pcm_list, list) {
dir = SNDRV_PCM_STREAM_PLAYBACK;
if (spcm->stream[dir].comp_id == comp_id) {
*direction = dir;
return spcm;
}
dir = SNDRV_PCM_STREAM_CAPTURE;
if (spcm->stream[dir].comp_id == comp_id) {
*direction = dir;
return spcm;
}
}
return NULL;
}
struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp,
unsigned int pcm_id)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
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_soc_component *scomp,
const char *name)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
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_soc_component *scomp,
const char *pcm_name, int dir)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
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_soc_component *scomp,
const char *name)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
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;
}
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2019 Intel Corporation. All rights reserved.
*
* Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
*/
#ifndef __SOUND_SOC_SOF_AUDIO_H
#define __SOUND_SOC_SOF_AUDIO_H
#include <sound/soc.h>
#include <sound/control.h>
#include <sound/sof/stream.h> /* needs to be included before control.h */
#include <sound/sof/control.h>
#include <sound/sof/dai.h>
#include <sound/sof/topology.h>
#include "sof-priv.h"
#define SOF_AUDIO_PCM_DRV_NAME "sof-audio-component"
/* max number of FE PCMs before BEs */
#define SOF_BE_PCM_BASE 16
#define DMA_CHAN_INVALID 0xFFFFFFFF
/* PCM stream, mapped to FW component */
struct snd_sof_pcm_stream {
u32 comp_id;
struct snd_dma_buffer page_table;
struct sof_ipc_stream_posn posn;
struct snd_pcm_substream *substream;
struct work_struct period_elapsed_work;
bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
/*
* flag to indicate that the DSP pipelines should be kept
* active or not while suspending the stream
*/
bool suspend_ignored;
};
/* ALSA SOF PCM device */
struct snd_sof_pcm {
struct snd_soc_component *scomp;
struct snd_soc_tplg_pcm pcm;
struct snd_sof_pcm_stream stream[2];
struct list_head list; /* list in sdev pcm list */
struct snd_pcm_hw_params params[2];
bool prepared[2]; /* PCM_PARAMS set successfully */
};
struct snd_sof_led_control {
unsigned int use_led;
unsigned int direction;
unsigned int led_value;
};
/* ALSA SOF Kcontrol device */
struct snd_sof_control {
struct snd_soc_component *scomp;
int comp_id;
int min_volume_step; /* min volume step for volume_table */
int max_volume_step; /* max volume step for volume_table */
int num_channels;
u32 readback_offset; /* offset to mmapped data if used */
struct sof_ipc_ctrl_data *control_data;
u32 size; /* cdata size */
enum sof_ipc_ctrl_cmd cmd;
u32 *volume_table; /* volume table computed from tlv data*/
struct list_head list; /* list in sdev control list */
struct snd_sof_led_control led_ctl;
};
/* ASoC SOF DAPM widget */
struct snd_sof_widget {
struct snd_soc_component *scomp;
int comp_id;
int pipeline_id;
int complete;
int id;
struct snd_soc_dapm_widget *widget;
struct list_head list; /* list in sdev widget list */
void *private; /* core does not touch this */
};
/* ASoC SOF DAPM route */
struct snd_sof_route {
struct snd_soc_component *scomp;
struct snd_soc_dapm_route *route;
struct list_head list; /* list in sdev route list */
void *private;
};
/* ASoC DAI device */
struct snd_sof_dai {
struct snd_soc_component *scomp;
const char *name;
const char *cpu_dai_name;
struct sof_ipc_comp_dai comp_dai;
struct sof_ipc_dai_config *dai_config;
struct list_head list; /* list in sdev dai list */
};
/*
* Kcontrols.
*/
int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
const unsigned int __user *binary_data,
unsigned int size);
int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
unsigned int __user *binary_data,
unsigned int size);
/*
* Topology.
* There is no snd_sof_free_topology since topology components will
* be freed by snd_soc_unregister_component,
*/
int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file);
int snd_sof_complete_pipeline(struct device *dev,
struct snd_sof_widget *swidget);
int sof_load_pipeline_ipc(struct device *dev,
struct sof_ipc_pipe_new *pipeline,
struct sof_ipc_comp_reply *r);
/*
* Stream IPC
*/
int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
struct snd_sof_pcm *spcm, int direction,
struct sof_ipc_stream_posn *posn);
struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp,
const char *name);
struct snd_sof_widget *
snd_sof_find_swidget_sname(struct snd_soc_component *scomp,
const char *pcm_name, int dir);
struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp,
const char *name);
static inline
struct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_soc_component *scomp,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct snd_sof_pcm *spcm = NULL;
list_for_each_entry(spcm, &sdev->pcm_list, list) {
if (le32_to_cpu(spcm->pcm.dai_id) == rtd->dai_link->id)
return spcm;
}
return NULL;
}
struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp,
const char *name);
struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp,
unsigned int comp_id,
int *direction);
struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp,
unsigned int pcm_id);
void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream);
/*
* Mixer IPC
*/
int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol,
u32 ipc_cmd,
enum sof_ipc_ctrl_type ctrl_type,
enum sof_ipc_ctrl_cmd ctrl_cmd,
bool send);
/* PM */
int sof_restore_pipelines(struct device *dev);
int sof_set_hw_params_upon_resume(struct device *dev);
bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev);
#endif
......@@ -12,20 +12,11 @@
#define __SOUND_SOC_SOF_PRIV_H
#include <linux/device.h>
#include <sound/hdaudio.h>
#include <sound/soc.h>
#include <sound/control.h>
#include <sound/sof.h>
#include <sound/sof/stream.h> /* needs to be included before control.h */
#include <sound/sof/control.h>
#include <sound/sof/dai.h>
#include <sound/sof/info.h>
#include <sound/sof/pm.h>
#include <sound/sof/topology.h>
#include <sound/sof/trace.h>
#include <uapi/sound/sof/fw.h>
/* debug flags */
......@@ -48,9 +39,6 @@ extern int sof_core_debug;
/* DMA buffer size for trace */
#define DMA_BUF_SIZE_FOR_TRACE (PAGE_SIZE * 16)
/* max number of FE PCMs before BEs */
#define SOF_BE_PCM_BASE 16
#define SOF_IPC_DSP_REPLY 0
#define SOF_IPC_HOST_REPLY 1
......@@ -66,8 +54,6 @@ extern int sof_core_debug;
(IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) || \
IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST))
#define DMA_CHAN_INVALID 0xFFFFFFFF
/* DSP D0ix sub-state */
enum sof_d0_substate {
SOF_DSP_D0I0 = 0, /* DSP default D0 substate */
......@@ -303,90 +289,6 @@ struct snd_sof_ipc_msg {
bool ipc_complete;
};
/* PCM stream, mapped to FW component */
struct snd_sof_pcm_stream {
u32 comp_id;
struct snd_dma_buffer page_table;
struct sof_ipc_stream_posn posn;
struct snd_pcm_substream *substream;
struct work_struct period_elapsed_work;
bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
/*
* flag to indicate that the DSP pipelines should be kept
* active or not while suspending the stream
*/
bool suspend_ignored;
};
/* ALSA SOF PCM device */
struct snd_sof_pcm {
struct snd_sof_dev *sdev;
struct snd_soc_tplg_pcm pcm;
struct snd_sof_pcm_stream stream[2];
struct list_head list; /* list in sdev pcm list */
struct snd_pcm_hw_params params[2];
bool prepared[2]; /* PCM_PARAMS set successfully */
};
struct snd_sof_led_control {
unsigned int use_led;
unsigned int direction;
unsigned int led_value;
};
/* ALSA SOF Kcontrol device */
struct snd_sof_control {
struct snd_sof_dev *sdev;
int comp_id;
int min_volume_step; /* min volume step for volume_table */
int max_volume_step; /* max volume step for volume_table */
int num_channels;
u32 readback_offset; /* offset to mmaped data if used */
struct sof_ipc_ctrl_data *control_data;
u32 size; /* cdata size */
enum sof_ipc_ctrl_cmd cmd;
u32 *volume_table; /* volume table computed from tlv data*/
struct list_head list; /* list in sdev control list */
struct snd_sof_led_control led_ctl;
};
/* ASoC SOF DAPM widget */
struct snd_sof_widget {
struct snd_sof_dev *sdev;
int comp_id;
int pipeline_id;
int complete;
int id;
struct snd_soc_dapm_widget *widget;
struct list_head list; /* list in sdev widget list */
void *private; /* core does not touch this */
};
/* ASoC SOF DAPM route */
struct snd_sof_route {
struct snd_sof_dev *sdev;
struct snd_soc_dapm_route *route;
struct list_head list; /* list in sdev route list */
void *private;
};
/* ASoC DAI device */
struct snd_sof_dai {
struct snd_sof_dev *sdev;
const char *name;
const char *cpu_dai_name;
struct sof_ipc_comp_dai comp_dai;
struct sof_ipc_dai_config *dai_config;
struct list_head list; /* list in sdev dai list */
};
/*
* SOF Device Level.
*/
......@@ -531,67 +433,6 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev);
int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
void *msg_data, size_t msg_bytes, void *reply_data,
size_t reply_bytes);
struct snd_sof_widget *snd_sof_find_swidget(struct snd_sof_dev *sdev,
const char *name);
struct snd_sof_widget *snd_sof_find_swidget_sname(struct snd_sof_dev *sdev,
const char *pcm_name,
int dir);
struct snd_sof_dai *snd_sof_find_dai(struct snd_sof_dev *sdev,
const char *name);
static inline
struct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_sof_dev *sdev,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_sof_pcm *spcm = NULL;
list_for_each_entry(spcm, &sdev->pcm_list, list) {
if (le32_to_cpu(spcm->pcm.dai_id) == rtd->dai_link->id)
return spcm;
}
return NULL;
}
bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev);
struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_sof_dev *sdev,
const char *name);
struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_sof_dev *sdev,
unsigned int comp_id,
int *direction);
struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_sof_dev *sdev,
unsigned int pcm_id);
void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream);
/*
* Stream IPC
*/
int snd_sof_ipc_stream_posn(struct snd_sof_dev *sdev,
struct snd_sof_pcm *spcm, int direction,
struct sof_ipc_stream_posn *posn);
/*
* Mixer IPC
*/
int snd_sof_ipc_set_get_comp_data(struct snd_sof_ipc *ipc,
struct snd_sof_control *scontrol, u32 ipc_cmd,
enum sof_ipc_ctrl_type ctrl_type,
enum sof_ipc_ctrl_cmd ctrl_cmd,
bool send);
/*
* Topology.
* There is no snd_sof_free_topology since topology components will
* be freed by snd_soc_unregister_component,
*/
int snd_sof_load_topology(struct snd_sof_dev *sdev, const char *file);
int snd_sof_complete_pipeline(struct snd_sof_dev *sdev,
struct snd_sof_widget *swidget);
int sof_load_pipeline_ipc(struct snd_sof_dev *sdev,
struct sof_ipc_pipe_new *pipeline,
struct sof_ipc_comp_reply *r);
/*
* Trace/debug
......@@ -623,40 +464,12 @@ void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev);
*/
extern struct snd_compr_ops sof_compressed_ops;
/*
* Kcontrols.
*/
int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
const unsigned int __user *binary_data,
unsigned int size);
int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
unsigned int __user *binary_data,
unsigned int size);
/*
* DSP Architectures.
*/
static inline void sof_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack,
u32 stack_words)
{
if (sof_arch_ops(sdev)->dsp_stack)
sof_arch_ops(sdev)->dsp_stack(sdev, oops, stack, stack_words);
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment