ASoC: Updates for v5.16

This is an unusually large set of updates, mostly a large crop of
unusually big drivers coupled with extensive overhauls of existing code.
There's a SH change here for the DAI format terminology, the change is
straightforward and the SH maintainers don't seem very active.

 - A new version of the audio graph card which supports a wider range of
   systems.
 - Move of the Cirrus DSP framework into drivers/firmware to allow for
   future use by non-audio DSPs.
 - Several conversions to YAML DT bindings.
 - Continuing cleanups to the SOF and Intel code.
 - A very big overhaul of the cs42l42 driver, correcting many problems.
 - Support for AMD Vangogh and Yelow Cap, Cirrus CS35L41, Maxim
   MAX98520 and MAX98360A, Mediatek MT8195, Nuvoton NAU8821, nVidia
   Tegra210, NXP i.MX8ULP, Qualcomm AudioReach, Realtek ALC5682I-VS,
   RT5682S, and RT9120 and Rockchip RV1126 and RK3568
This commit is contained in:
Takashi Iwai
2021-11-01 16:58:27 +01:00
1901 changed files with 63339 additions and 17371 deletions

View File

@@ -3,13 +3,11 @@
snd-sof-acpi-intel-byt-objs := byt.o
snd-sof-acpi-intel-bdw-objs := bdw.o
snd-sof-intel-ipc-objs := intel-ipc.o
snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \
hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \
hda-dai.o hda-bus.o \
apl.o cnl.o tgl.o icl.o
snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-compress.o
snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-probes.o
snd-sof-intel-hda-objs := hda-codec.o
@@ -18,7 +16,6 @@ snd-sof-intel-atom-objs := atom.o
obj-$(CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP) += snd-sof-intel-atom.o
obj-$(CONFIG_SND_SOC_SOF_BAYTRAIL) += snd-sof-acpi-intel-byt.o
obj-$(CONFIG_SND_SOC_SOF_BROADWELL) += snd-sof-acpi-intel-bdw.o
obj-$(CONFIG_SND_SOC_SOF_INTEL_HIFI_EP_IPC) += snd-sof-intel-ipc.o
obj-$(CONFIG_SND_SOC_SOF_HDA_COMMON) += snd-sof-intel-hda-common.o
obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o

View File

@@ -42,6 +42,10 @@ const struct snd_sof_dsp_ops sof_apl_ops = {
.block_read = sof_block_read,
.block_write = sof_block_write,
/* Mailbox IO */
.mailbox_read = sof_mailbox_read,
.mailbox_write = sof_mailbox_write,
/* doorbell */
.irq_thread = hda_dsp_ipc_irq_thread,
@@ -65,6 +69,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = {
.debug_map_count = ARRAY_SIZE(apl_dsp_debugfs),
.dbg_dump = hda_dsp_dump,
.ipc_dump = hda_ipc_dump,
.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
/* stream callbacks */
.pcm_open = hda_dsp_pcm_open,
@@ -125,7 +130,7 @@ const struct snd_sof_dsp_ops sof_apl_ops = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
.arch_ops = &sof_xtensa_arch_ops,
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
EXPORT_SYMBOL_NS(sof_apl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);

View File

@@ -283,11 +283,8 @@ int atom_run(struct snd_sof_dev *sdev)
break;
msleep(100);
}
if (tries < 0) {
dev_err(sdev->dev, "error: unable to run DSP firmware\n");
atom_dump(sdev, SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);
if (tries < 0)
return -ENODEV;
}
/* return init core mask */
return 1;

View File

@@ -535,8 +535,8 @@ static int bdw_probe(struct snd_sof_dev *sdev)
return ret;
}
/* set default mailbox */
snd_sof_dsp_mailbox_init(sdev, MBOX_OFFSET, MBOX_SIZE, 0, 0);
/* set default mailbox offset for FW ready message */
sdev->dsp_box.offset = MBOX_OFFSET;
return ret;
}
@@ -616,14 +616,18 @@ static const struct snd_sof_dsp_ops sof_bdw_ops = {
.block_read = sof_block_read,
.block_write = sof_block_write,
/* Mailbox IO */
.mailbox_read = sof_mailbox_read,
.mailbox_write = sof_mailbox_write,
/* ipc */
.send_msg = bdw_send_msg,
.fw_ready = sof_fw_ready,
.get_mailbox_offset = bdw_get_mailbox_offset,
.get_window_offset = bdw_get_window_offset,
.ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params,
.ipc_msg_data = sof_ipc_msg_data,
.ipc_pcm_params = sof_ipc_pcm_params,
/* machine driver */
.machine_select = bdw_machine_select,
@@ -635,10 +639,11 @@ static const struct snd_sof_dsp_ops sof_bdw_ops = {
.debug_map = bdw_debugfs,
.debug_map_count = ARRAY_SIZE(bdw_debugfs),
.dbg_dump = bdw_dump,
.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
/* stream callbacks */
.pcm_open = intel_pcm_open,
.pcm_close = intel_pcm_close,
.pcm_open = sof_stream_pcm_open,
.pcm_close = sof_stream_pcm_close,
/* Module loading */
.load_module = snd_sof_parse_module_memcpy,
@@ -657,7 +662,7 @@ static const struct snd_sof_dsp_ops sof_bdw_ops = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_BATCH,
.arch_ops = &sof_xtensa_arch_ops,
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
static const struct sof_intel_dsp_desc bdw_chip_info = {

View File

@@ -226,6 +226,10 @@ static const struct snd_sof_dsp_ops sof_byt_ops = {
.block_read = sof_block_read,
.block_write = sof_block_write,
/* Mailbox IO */
.mailbox_read = sof_mailbox_read,
.mailbox_write = sof_mailbox_write,
/* doorbell */
.irq_handler = atom_irq_handler,
.irq_thread = atom_irq_thread,
@@ -236,8 +240,8 @@ static const struct snd_sof_dsp_ops sof_byt_ops = {
.get_mailbox_offset = atom_get_mailbox_offset,
.get_window_offset = atom_get_window_offset,
.ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params,
.ipc_msg_data = sof_ipc_msg_data,
.ipc_pcm_params = sof_ipc_pcm_params,
/* machine driver */
.machine_select = atom_machine_select,
@@ -249,10 +253,11 @@ static const struct snd_sof_dsp_ops sof_byt_ops = {
.debug_map = byt_debugfs,
.debug_map_count = ARRAY_SIZE(byt_debugfs),
.dbg_dump = atom_dump,
.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
/* stream callbacks */
.pcm_open = intel_pcm_open,
.pcm_close = intel_pcm_close,
.pcm_open = sof_stream_pcm_open,
.pcm_close = sof_stream_pcm_close,
/* module loading */
.load_module = snd_sof_parse_module_memcpy,
@@ -275,7 +280,7 @@ static const struct snd_sof_dsp_ops sof_byt_ops = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_BATCH,
.arch_ops = &sof_xtensa_arch_ops,
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
static const struct sof_intel_dsp_desc byt_chip_info = {
@@ -303,6 +308,10 @@ static const struct snd_sof_dsp_ops sof_cht_ops = {
.block_read = sof_block_read,
.block_write = sof_block_write,
/* Mailbox IO */
.mailbox_read = sof_mailbox_read,
.mailbox_write = sof_mailbox_write,
/* doorbell */
.irq_handler = atom_irq_handler,
.irq_thread = atom_irq_thread,
@@ -313,8 +322,8 @@ static const struct snd_sof_dsp_ops sof_cht_ops = {
.get_mailbox_offset = atom_get_mailbox_offset,
.get_window_offset = atom_get_window_offset,
.ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params,
.ipc_msg_data = sof_ipc_msg_data,
.ipc_pcm_params = sof_ipc_pcm_params,
/* machine driver */
.machine_select = atom_machine_select,
@@ -326,10 +335,11 @@ static const struct snd_sof_dsp_ops sof_cht_ops = {
.debug_map = cht_debugfs,
.debug_map_count = ARRAY_SIZE(cht_debugfs),
.dbg_dump = atom_dump,
.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
/* stream callbacks */
.pcm_open = intel_pcm_open,
.pcm_close = intel_pcm_close,
.pcm_open = sof_stream_pcm_open,
.pcm_close = sof_stream_pcm_close,
/* module loading */
.load_module = snd_sof_parse_module_memcpy,
@@ -353,7 +363,7 @@ static const struct snd_sof_dsp_ops sof_cht_ops = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_BATCH,
.arch_ops = &sof_xtensa_arch_ops,
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
static const struct sof_intel_dsp_desc cht_chip_info = {

View File

@@ -247,6 +247,10 @@ const struct snd_sof_dsp_ops sof_cnl_ops = {
.block_read = sof_block_read,
.block_write = sof_block_write,
/* Mailbox IO */
.mailbox_read = sof_mailbox_read,
.mailbox_write = sof_mailbox_write,
/* doorbell */
.irq_thread = cnl_ipc_irq_thread,
@@ -270,6 +274,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = {
.debug_map_count = ARRAY_SIZE(cnl_dsp_debugfs),
.dbg_dump = hda_dsp_dump,
.ipc_dump = cnl_ipc_dump,
.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
/* stream callbacks */
.pcm_open = hda_dsp_pcm_open,
@@ -330,7 +335,7 @@ const struct snd_sof_dsp_ops sof_cnl_ops = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
.arch_ops = &sof_xtensa_arch_ops,
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);

View File

@@ -16,6 +16,10 @@
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
#include "../sof-probes.h"
#endif
struct hda_pipe_params {
u8 host_dma_id;
u8 link_dma_id;
@@ -152,49 +156,68 @@ static int hda_link_dma_params(struct hdac_ext_stream *stream,
return 0;
}
/* Send DAI_CONFIG IPC to the DAI that matches the dai_name and direction */
static int hda_link_config_ipc(struct sof_intel_hda_stream *hda_stream,
const char *dai_name, int channel, int dir)
/* Update config for the DAI widget */
static struct sof_ipc_dai_config *hda_dai_update_config(struct snd_soc_dapm_widget *w,
int channel)
{
struct snd_sof_widget *swidget = w->dobj.private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
int ret = 0;
list_for_each_entry(sof_dai, &hda_stream->sdev->dai_list, list) {
if (!sof_dai->cpu_dai_name)
continue;
if (!swidget)
return NULL;
if (!strcmp(dai_name, sof_dai->cpu_dai_name) &&
dir == sof_dai->comp_dai.direction) {
config = sof_dai->dai_config;
sof_dai = swidget->private;
if (!config) {
dev_err(hda_stream->sdev->dev,
"error: no config for DAI %s\n",
sof_dai->name);
return -EINVAL;
}
/* update config with stream tag */
config->hda.link_dma_ch = channel;
/* send IPC */
ret = sof_ipc_tx_message(hda_stream->sdev->ipc,
config->hdr.cmd,
config,
config->hdr.size,
&reply, sizeof(reply));
if (ret < 0)
dev_err(hda_stream->sdev->dev,
"error: failed to set dai config for %s\n",
sof_dai->name);
return ret;
}
if (!sof_dai || !sof_dai->dai_config) {
dev_err(swidget->scomp->dev, "error: No config for DAI %s\n", w->name);
return NULL;
}
return -EINVAL;
config = &sof_dai->dai_config[sof_dai->current_config];
/* update config with stream tag */
config->hda.link_dma_ch = channel;
return config;
}
static int hda_link_config_ipc(struct sof_intel_hda_stream *hda_stream,
struct snd_soc_dapm_widget *w, int channel)
{
struct snd_sof_dev *sdev = hda_stream->sdev;
struct sof_ipc_dai_config *config;
struct sof_ipc_reply reply;
config = hda_dai_update_config(w, channel);
if (!config) {
dev_err(sdev->dev, "error: no config for DAI %s\n", w->name);
return -ENOENT;
}
/* send DAI_CONFIG IPC */
return sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size,
&reply, sizeof(reply));
}
static int hda_link_dai_widget_update(struct sof_intel_hda_stream *hda_stream,
struct snd_soc_dapm_widget *w,
int channel, bool widget_setup)
{
struct snd_sof_dev *sdev = hda_stream->sdev;
struct sof_ipc_dai_config *config;
config = hda_dai_update_config(w, channel);
if (!config) {
dev_err(sdev->dev, "error: no config for DAI %s\n", w->name);
return -ENOENT;
}
/* set up/free DAI widget and send DAI_CONFIG IPC */
if (widget_setup)
return hda_ctrl_dai_widget_setup(w);
return hda_ctrl_dai_widget_free(w);
}
static int hda_link_hw_params(struct snd_pcm_substream *substream,
@@ -208,6 +231,7 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct sof_intel_hda_stream *hda_stream;
struct hda_pipe_params p_params = {0};
struct snd_soc_dapm_widget *w;
struct hdac_ext_link *link;
int stream_tag;
int ret;
@@ -226,9 +250,13 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
hda_stream = hstream_to_sof_hda_stream(link_dev);
/* update the DSP with the new tag */
ret = hda_link_config_ipc(hda_stream, dai->name, stream_tag - 1,
substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
w = dai->playback_widget;
else
w = dai->capture_widget;
/* set up the DAI widget and send the DAI_CONFIG with the new tag */
ret = hda_link_dai_widget_update(hda_stream, w, stream_tag - 1, true);
if (ret < 0)
return ret;
@@ -284,6 +312,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
snd_soc_dai_get_dma_data(dai, substream);
struct sof_intel_hda_stream *hda_stream;
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_dapm_widget *w;
struct hdac_ext_link *link;
struct hdac_stream *hstream;
struct hdac_bus *bus;
@@ -318,12 +347,16 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
w = dai->playback_widget;
else
w = dai->capture_widget;
/*
* clear link DMA channel. It will be assigned when
* hw_params is set up again after resume.
*/
ret = hda_link_config_ipc(hda_stream, dai->name,
DMA_CHAN_INVALID, substream->stream);
ret = hda_link_config_ipc(hda_stream, w, DMA_CHAN_INVALID);
if (ret < 0)
return ret;
@@ -354,6 +387,7 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,
struct hdac_stream *hstream;
struct snd_soc_pcm_runtime *rtd;
struct hdac_ext_stream *link_dev;
struct snd_soc_dapm_widget *w;
int ret;
hstream = substream->runtime->private_data;
@@ -369,9 +403,13 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,
hda_stream = hstream_to_sof_hda_stream(link_dev);
/* free the link DMA channel in the FW */
ret = hda_link_config_ipc(hda_stream, dai->name, DMA_CHAN_INVALID,
substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
w = dai->playback_widget;
else
w = dai->capture_widget;
/* free the link DMA channel in the FW and the DAI widget */
ret = hda_link_dai_widget_update(hda_stream, w, DMA_CHAN_INVALID, false);
if (ret < 0)
return ret;
@@ -401,61 +439,131 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = {
.prepare = hda_link_pcm_prepare,
};
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES)
#include "../compress.h"
#endif
static struct snd_soc_cdai_ops sof_probe_compr_ops = {
.startup = sof_probe_compr_open,
.shutdown = sof_probe_compr_free,
.set_params = sof_probe_compr_set_params,
.trigger = sof_probe_compr_trigger,
.pointer = sof_probe_compr_pointer,
/* only one flag used so far to harden hw_params/hw_free/trigger/prepare */
struct ssp_dai_dma_data {
bool setup;
};
#endif
#endif
static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai,
bool setup)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
int ret;
struct snd_soc_component *component;
struct snd_sof_widget *swidget;
struct snd_soc_dapm_widget *w;
struct sof_ipc_fw_version *v;
struct snd_sof_dev *sdev;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
w = dai->playback_widget;
else
w = dai->capture_widget;
swidget = w->dobj.private;
component = swidget->scomp;
sdev = snd_soc_component_get_drvdata(component);
v = &sdev->fw_ready.version;
/* DAI_CONFIG IPC during hw_params is not supported in older firmware */
if (v->abi_version < SOF_ABI_VER(3, 18, 0))
return 0;
list_for_each_entry(sof_dai, &sdev->dai_list, list) {
if (!sof_dai->cpu_dai_name || !sof_dai->dai_config)
continue;
if (setup)
return hda_ctrl_dai_widget_setup(w);
if (!strcmp(dai->name, sof_dai->cpu_dai_name) &&
substream->stream == sof_dai->comp_dai.direction) {
config = &sof_dai->dai_config[sof_dai->current_config];
return hda_ctrl_dai_widget_free(w);
}
/* send IPC */
ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config,
config->hdr.size, &reply, sizeof(reply));
static int ssp_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct ssp_dai_dma_data *dma_data;
if (ret < 0)
dev_err(sdev->dev, "error: failed to set DAI config for %s\n",
sof_dai->name);
return ret;
}
}
dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
if (!dma_data)
return -ENOMEM;
snd_soc_dai_set_dma_data(dai, substream, dma_data);
return 0;
}
static int ssp_dai_setup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai,
bool setup)
{
struct ssp_dai_dma_data *dma_data;
int ret = 0;
dma_data = snd_soc_dai_get_dma_data(dai, substream);
if (!dma_data) {
dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
return -EIO;
}
if (dma_data->setup != setup) {
ret = ssp_dai_setup_or_free(substream, dai, setup);
if (!ret)
dma_data->setup = setup;
}
return ret;
}
static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
/* params are ignored for now */
return ssp_dai_setup(substream, dai, true);
}
static int ssp_dai_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
/*
* the SSP will only be reconfigured during resume operations and
* not in case of xruns
*/
return ssp_dai_setup(substream, dai, true);
}
static int ssp_dai_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
if (cmd != SNDRV_PCM_TRIGGER_SUSPEND)
return 0;
return ssp_dai_setup(substream, dai, false);
}
static int ssp_dai_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
return ssp_dai_setup(substream, dai, false);
}
static void ssp_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct ssp_dai_dma_data *dma_data;
dma_data = snd_soc_dai_get_dma_data(dai, substream);
if (!dma_data) {
dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
return;
}
snd_soc_dai_set_dma_data(dai, substream, NULL);
kfree(dma_data);
}
static const struct snd_soc_dai_ops ssp_dai_ops = {
.startup = ssp_dai_startup,
.hw_params = ssp_dai_hw_params,
.prepare = ssp_dai_prepare,
.trigger = ssp_dai_trigger,
.hw_free = ssp_dai_hw_free,
.shutdown = ssp_dai_shutdown,
};
/*

View File

@@ -34,7 +34,7 @@ MODULE_PARM_DESC(enable_trace_D0I3_S0,
* DSP Core control.
*/
int hda_dsp_core_reset_enter(struct snd_sof_dev *sdev, unsigned int core_mask)
static int hda_dsp_core_reset_enter(struct snd_sof_dev *sdev, unsigned int core_mask)
{
u32 adspcs;
u32 reset;
@@ -73,7 +73,7 @@ int hda_dsp_core_reset_enter(struct snd_sof_dev *sdev, unsigned int core_mask)
return ret;
}
int hda_dsp_core_reset_leave(struct snd_sof_dev *sdev, unsigned int core_mask)
static int hda_dsp_core_reset_leave(struct snd_sof_dev *sdev, unsigned int core_mask)
{
unsigned int crst;
u32 adspcs;
@@ -113,7 +113,7 @@ int hda_dsp_core_reset_leave(struct snd_sof_dev *sdev, unsigned int core_mask)
return ret;
}
int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask)
static int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask)
{
/* stall core */
snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
@@ -125,6 +125,31 @@ int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask)
return hda_dsp_core_reset_enter(sdev, core_mask);
}
static bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask)
{
int val;
bool is_enable;
val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS);
#define MASK_IS_EQUAL(v, m, field) ({ \
u32 _m = field(m); \
((v) & _m) == _m; \
})
is_enable = MASK_IS_EQUAL(val, core_mask, HDA_DSP_ADSPCS_CPA_MASK) &&
MASK_IS_EQUAL(val, core_mask, HDA_DSP_ADSPCS_SPA_MASK) &&
!(val & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) &&
!(val & HDA_DSP_ADSPCS_CSTALL_MASK(core_mask));
#undef MASK_IS_EQUAL
dev_dbg(sdev->dev, "DSP core(s) enabled? %d : core_mask %x\n",
is_enable, core_mask);
return is_enable;
}
int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask)
{
int ret;
@@ -156,7 +181,7 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask)
* Power Management.
*/
int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask)
static int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask)
{
unsigned int cpa;
u32 adspcs;
@@ -195,7 +220,7 @@ int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask)
return ret;
}
int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask)
static int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask)
{
u32 adspcs;
int ret;
@@ -218,32 +243,6 @@ int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask)
return ret;
}
bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev,
unsigned int core_mask)
{
int val;
bool is_enable;
val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS);
#define MASK_IS_EQUAL(v, m, field) ({ \
u32 _m = field(m); \
((v) & _m) == _m; \
})
is_enable = MASK_IS_EQUAL(val, core_mask, HDA_DSP_ADSPCS_CPA_MASK) &&
MASK_IS_EQUAL(val, core_mask, HDA_DSP_ADSPCS_SPA_MASK) &&
!(val & HDA_DSP_ADSPCS_CRST_MASK(core_mask)) &&
!(val & HDA_DSP_ADSPCS_CSTALL_MASK(core_mask));
#undef MASK_IS_EQUAL
dev_dbg(sdev->dev, "DSP core(s) enabled? %d : core_mask %x\n",
is_enable, core_mask);
return is_enable;
}
int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;

View File

@@ -253,9 +253,9 @@ int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
return SRAM_WINDOW_OFFSET(id);
}
void hda_ipc_msg_data(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
void *p, size_t sz)
int hda_ipc_msg_data(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
void *p, size_t sz)
{
if (!substream || !sdev->stream_box.size) {
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
@@ -268,10 +268,13 @@ void hda_ipc_msg_data(struct snd_sof_dev *sdev,
hda_stream.hstream);
/* The stream might already be closed */
if (hstream)
sof_mailbox_read(sdev, hda_stream->stream.posn_offset,
p, sz);
if (!hstream)
return -ESTRPIPE;
sof_mailbox_read(sdev, hda_stream->stream.posn_offset, p, sz);
}
return 0;
}
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,

View File

@@ -177,13 +177,13 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag)
__func__);
err:
flags = SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX;
flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL;
/* force error log level after max boot attempts */
/* after max boot attempts make sure that the dump is printed */
if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
flags |= SOF_DBG_DUMP_FORCE_ERR_LEVEL;
flags &= ~SOF_DBG_DUMP_OPTIONAL;
hda_dsp_dump(sdev, flags);
snd_sof_dsp_dbg_dump(sdev, flags);
snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask);
return ret;
@@ -414,8 +414,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
if (!ret) {
dev_dbg(sdev->dev, "Firmware download successful, booting...\n");
} else {
hda_dsp_dump(sdev, SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX |
SOF_DBG_DUMP_FORCE_ERR_LEVEL);
snd_sof_dsp_dbg_dump(sdev, SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX);
dev_err(sdev->dev, "error: load fw failed ret: %d\n", ret);
}

View File

@@ -25,6 +25,33 @@
#define HDA_LTRP_GB_VALUE_US 95
static inline const char *hda_hstream_direction_str(struct hdac_stream *hstream)
{
if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK)
return "Playback";
else
return "Capture";
}
static char *hda_hstream_dbg_get_stream_info_str(struct hdac_stream *hstream)
{
struct snd_soc_pcm_runtime *rtd;
if (hstream->substream)
rtd = asoc_substream_to_rtd(hstream->substream);
else if (hstream->cstream)
rtd = hstream->cstream->private_data;
else
/* Non audio DMA user, like dma-trace */
return kasprintf(GFP_KERNEL, "-- (%s, stream_tag: %u)",
hda_hstream_direction_str(hstream),
hstream->stream_tag);
return kasprintf(GFP_KERNEL, "dai_link \"%s\" (%s, stream_tag: %u)",
rtd->dai_link->name, hda_hstream_direction_str(hstream),
hstream->stream_tag);
}
/*
* set up one of BDL entries for a stream
*/
@@ -89,13 +116,13 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev,
int remain, ioc;
period_bytes = stream->period_bytes;
dev_dbg(sdev->dev, "period_bytes:0x%x\n", period_bytes);
dev_dbg(sdev->dev, "%s: period_bytes:0x%x\n", __func__, period_bytes);
if (!period_bytes)
period_bytes = stream->bufsize;
periods = stream->bufsize / period_bytes;
dev_dbg(sdev->dev, "periods:%d\n", periods);
dev_dbg(sdev->dev, "%s: periods:%d\n", __func__, periods);
remain = stream->bufsize % period_bytes;
if (remain)
@@ -244,7 +271,8 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);
if (!found) {
dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
dev_dbg(sdev->dev, "%s: stream_tag %d not opened!\n",
__func__, stream_tag);
return -ENODEV;
}
@@ -257,7 +285,7 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
struct hdac_stream *hstream = &stream->hstream;
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
u32 dma_start = SOF_HDA_SD_CTL_DMA_START;
int ret;
int ret = 0;
u32 run;
/* cmd must be for audio stream */
@@ -283,14 +311,9 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_STREAM_RUN_TIMEOUT);
if (ret < 0) {
dev_err(sdev->dev,
"error: %s: cmd %d: timeout on STREAM_SD_OFFSET read\n",
__func__, cmd);
return ret;
}
if (ret >= 0)
hstream->running = true;
hstream->running = true;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -306,27 +329,32 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_STREAM_RUN_TIMEOUT);
if (ret < 0) {
dev_err(sdev->dev,
"error: %s: cmd %d: timeout on STREAM_SD_OFFSET read\n",
__func__, cmd);
return ret;
if (ret >= 0) {
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS,
SOF_HDA_CL_DMA_SD_INT_MASK);
hstream->running = false;
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
SOF_HDA_INTCTL,
1 << hstream->index, 0x0);
}
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset +
SOF_HDA_ADSP_REG_CL_SD_STS,
SOF_HDA_CL_DMA_SD_INT_MASK);
hstream->running = false;
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
1 << hstream->index, 0x0);
break;
default:
dev_err(sdev->dev, "error: unknown command: %d\n", cmd);
return -EINVAL;
}
return 0;
if (ret < 0) {
char *stream_name = hda_hstream_dbg_get_stream_info_str(hstream);
dev_err(sdev->dev,
"%s: cmd %d on %s: timeout on STREAM_SD_OFFSET read\n",
__func__, cmd, stream_name ? stream_name : "unknown stream");
kfree(stream_name);
}
return ret;
}
/* minimal recommended programming for ICCMAX stream */
@@ -440,9 +468,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev,
HDA_DSP_STREAM_RUN_TIMEOUT);
if (ret < 0) {
char *stream_name = hda_hstream_dbg_get_stream_info_str(hstream);
dev_err(sdev->dev,
"error: %s: timeout on STREAM_SD_OFFSET read1\n",
__func__);
"%s: on %s: timeout on STREAM_SD_OFFSET read1\n",
__func__, stream_name ? stream_name : "unknown stream");
kfree(stream_name);
return ret;
}
@@ -506,9 +537,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev,
HDA_DSP_STREAM_RUN_TIMEOUT);
if (ret < 0) {
char *stream_name = hda_hstream_dbg_get_stream_info_str(hstream);
dev_err(sdev->dev,
"error: %s: timeout on STREAM_SD_OFFSET read2\n",
__func__);
"%s: on %s: timeout on STREAM_SD_OFFSET read1\n",
__func__, stream_name ? stream_name : "unknown stream");
kfree(stream_name);
return ret;
}

View File

@@ -41,6 +41,92 @@
#define EXCEPT_MAX_HDR_SIZE 0x400
#define HDA_EXT_ROM_STATUS_SIZE 8
int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w)
{
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_soc_component *component = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
int ret;
sof_dai = swidget->private;
if (!sof_dai || !sof_dai->dai_config) {
dev_err(sdev->dev, "No config for DAI %s\n", w->name);
return -EINVAL;
}
config = &sof_dai->dai_config[sof_dai->current_config];
/*
* For static pipelines, the DAI widget would already be set up and calling
* sof_widget_setup() simply returns without doing anything.
* For dynamic pipelines, the DAI widget will be set up now.
*/
ret = sof_widget_setup(sdev, swidget);
if (ret < 0) {
dev_err(sdev->dev, "error: failed setting up DAI widget %s\n", w->name);
return ret;
}
/* set HW_PARAMS flag */
config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_MASK, SOF_DAI_CONFIG_FLAGS_HW_PARAMS);
/* send DAI_CONFIG IPC */
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 setting DAI config for %s\n", w->name);
return ret;
}
sof_dai->configured = true;
return 0;
}
int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w)
{
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_soc_component *component = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
struct sof_ipc_reply reply;
int ret;
sof_dai = swidget->private;
if (!sof_dai || !sof_dai->dai_config) {
dev_err(sdev->dev, "error: No config to free DAI %s\n", w->name);
return -EINVAL;
}
/* nothing to do if hw_free() is called without restarting the stream after resume. */
if (!sof_dai->configured)
return 0;
config = &sof_dai->dai_config[sof_dai->current_config];
/* set HW_FREE flag */
config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_MASK, SOF_DAI_CONFIG_FLAGS_HW_FREE);
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 resetting DAI config for %s\n", w->name);
/*
* Reset the configured_flag and free the widget even if the IPC fails to keep
* the widget use_count balanced
*/
sof_dai->configured = false;
return sof_widget_free(sdev, swidget);
}
static const struct sof_intel_dsp_desc
*get_chip_info(struct snd_sof_pdata *pdata)
{
@@ -64,67 +150,70 @@ static int sdw_clock_stop_quirks = SDW_INTEL_CLK_STOP_BUS_RESET;
module_param(sdw_clock_stop_quirks, int, 0444);
MODULE_PARM_DESC(sdw_clock_stop_quirks, "SOF SoundWire clock stop quirks");
static int sdw_dai_config_ipc(struct snd_sof_dev *sdev,
struct snd_soc_dapm_widget *w,
int link_id, int alh_stream_id, int dai_id, bool setup)
{
struct snd_sof_widget *swidget = w->dobj.private;
struct sof_ipc_dai_config *config;
struct snd_sof_dai *sof_dai;
if (!swidget) {
dev_err(sdev->dev, "error: No private data for widget %s\n", w->name);
return -EINVAL;
}
sof_dai = swidget->private;
if (!sof_dai || !sof_dai->dai_config) {
dev_err(sdev->dev, "error: No config for DAI %s\n", w->name);
return -EINVAL;
}
config = &sof_dai->dai_config[sof_dai->current_config];
/* update config with link and stream ID */
config->dai_index = (link_id << 8) | dai_id;
config->alh.stream_id = alh_stream_id;
if (setup)
return hda_ctrl_dai_widget_setup(w);
return hda_ctrl_dai_widget_free(w);
}
static int sdw_params_stream(struct device *dev,
struct sdw_intel_stream_params_data *params_data)
{
struct snd_pcm_substream *substream = params_data->substream;
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_soc_dai *d = params_data->dai;
struct sof_ipc_dai_config config;
struct sof_ipc_reply reply;
int link_id = params_data->link_id;
int alh_stream_id = params_data->alh_stream_id;
int ret;
u32 size = sizeof(config);
struct snd_soc_dapm_widget *w;
memset(&config, 0, size);
config.hdr.size = size;
config.hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG;
config.type = SOF_DAI_INTEL_ALH;
config.dai_index = (link_id << 8) | (d->id);
config.alh.stream_id = alh_stream_id;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
w = d->playback_widget;
else
w = d->capture_widget;
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc,
config.hdr.cmd, &config, size, &reply,
sizeof(reply));
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to set DAI hw_params for link %d dai->id %d ALH %d\n",
link_id, d->id, alh_stream_id);
}
return ret;
return sdw_dai_config_ipc(sdev, w, params_data->link_id, params_data->alh_stream_id,
d->id, true);
}
static int sdw_free_stream(struct device *dev,
struct sdw_intel_stream_free_data *free_data)
{
struct snd_pcm_substream *substream = free_data->substream;
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_soc_dai *d = free_data->dai;
struct sof_ipc_dai_config config;
struct sof_ipc_reply reply;
int link_id = free_data->link_id;
int ret;
u32 size = sizeof(config);
struct snd_soc_dapm_widget *w;
memset(&config, 0, size);
config.hdr.size = size;
config.hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG;
config.type = SOF_DAI_INTEL_ALH;
config.dai_index = (link_id << 8) | d->id;
config.alh.stream_id = 0xFFFF; /* invalid value on purpose */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
w = d->playback_widget;
else
w = d->capture_widget;
/* send message to DSP */
ret = sof_ipc_tx_message(sdev->ipc,
config.hdr.cmd, &config, size, &reply,
sizeof(reply));
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to free stream for link %d dai->id %d\n",
link_id, d->id);
}
return ret;
/* send invalid stream_id */
return sdw_dai_config_ipc(sdev, w, free_data->link_id, 0xFFFF, d->id, false);
}
static const struct sdw_intel_ops sdw_callback = {
@@ -294,7 +383,38 @@ void hda_sdw_process_wakeen(struct snd_sof_dev *sdev)
sdw_intel_process_wakeen_event(hdev->sdw);
}
#endif
#else /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */
static inline int hda_sdw_acpi_scan(struct snd_sof_dev *sdev)
{
return 0;
}
static inline int hda_sdw_probe(struct snd_sof_dev *sdev)
{
return 0;
}
static inline int hda_sdw_exit(struct snd_sof_dev *sdev)
{
return 0;
}
static inline bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
{
return false;
}
static inline irqreturn_t hda_dsp_sdw_thread(int irq, void *context)
{
return IRQ_HANDLED;
}
static inline bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
{
return false;
}
#endif /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */
/*
* Debug
@@ -412,8 +532,7 @@ static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, u32 flags)
len += snprintf(msg + len, sizeof(msg) - len, " 0x%x", value);
}
sof_dev_dbg_or_err(sdev->dev, flags & SOF_DBG_DUMP_FORCE_ERR_LEVEL,
"extended rom status: %s", msg);
dev_err(sdev->dev, "extended rom status: %s", msg);
}
@@ -426,8 +545,7 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
/* print ROM/FW status */
hda_dsp_get_status(sdev);
/* print panic info if FW boot is complete. Otherwise, print the extended ROM status */
if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) {
if (flags & SOF_DBG_DUMP_REGS) {
u32 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_STATUS);
u32 panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_TRACEP);
@@ -456,12 +574,9 @@ void hda_ipc_irq_dump(struct snd_sof_dev *sdev)
ppsts = snd_sof_dsp_read(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPSTS);
rirbsts = snd_hdac_chip_readb(bus, RIRBSTS);
dev_err(sdev->dev,
"error: hda irq intsts 0x%8.8x intlctl 0x%8.8x rirb %2.2x\n",
dev_err(sdev->dev, "hda irq intsts 0x%8.8x intlctl 0x%8.8x rirb %2.2x\n",
intsts, intctl, rirbsts);
dev_err(sdev->dev,
"error: dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n",
ppsts, adspis);
dev_err(sdev->dev, "dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n", ppsts, adspis);
}
void hda_ipc_dump(struct snd_sof_dev *sdev)
@@ -479,8 +594,7 @@ void hda_ipc_dump(struct snd_sof_dev *sdev)
/* dump the IPC regs */
/* TODO: parse the raw msg */
dev_err(sdev->dev,
"error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
dev_err(sdev->dev, "host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
hipcie, hipct, hipcctl);
}

View File

@@ -492,17 +492,8 @@ struct sof_intel_hda_stream {
*/
int hda_dsp_probe(struct snd_sof_dev *sdev);
int hda_dsp_remove(struct snd_sof_dev *sdev);
int hda_dsp_core_reset_enter(struct snd_sof_dev *sdev,
unsigned int core_mask);
int hda_dsp_core_reset_leave(struct snd_sof_dev *sdev,
unsigned int core_mask);
int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask);
int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask);
int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask);
int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask);
int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask);
bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev,
unsigned int core_mask);
int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
unsigned int core_mask);
void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev);
@@ -572,9 +563,9 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
struct hdac_ext_stream *stream,
int enable, u32 size);
void hda_ipc_msg_data(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
void *p, size_t sz);
int hda_ipc_msg_data(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
void *p, size_t sz);
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
const struct sof_ipc_pcm_params_reply *reply);
@@ -619,8 +610,6 @@ int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir);
*/
int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev);
int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev);
int hda_dsp_cl_boot_firmware_iccmax_icl(struct snd_sof_dev *sdev);
int hda_dsp_cl_boot_firmware_skl(struct snd_sof_dev *sdev);
/* pre and post fw run ops */
int hda_dsp_pre_fw_run(struct snd_sof_dev *sdev);
@@ -695,45 +684,15 @@ bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev);
#else
static inline int hda_sdw_acpi_scan(struct snd_sof_dev *sdev)
{
return 0;
}
static inline int hda_sdw_probe(struct snd_sof_dev *sdev)
{
return 0;
}
static inline int hda_sdw_startup(struct snd_sof_dev *sdev)
{
return 0;
}
static inline int hda_sdw_exit(struct snd_sof_dev *sdev)
{
return 0;
}
static inline void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable)
{
}
static inline bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
{
return false;
}
static inline irqreturn_t hda_dsp_sdw_thread(int irq, void *context)
{
return IRQ_HANDLED;
}
static inline bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
{
return false;
}
static inline void hda_sdw_process_wakeen(struct snd_sof_dev *sdev)
{
}
@@ -774,4 +733,9 @@ void hda_set_mach_params(const struct snd_soc_acpi_mach *mach,
/* PCI driver selection and probe */
int hda_pci_intel_probe(struct pci_dev *pci, const struct pci_device_id *pci_id);
struct snd_sof_dai;
struct sof_ipc_dai_config;
int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w);
int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w);
#endif

View File

@@ -41,6 +41,10 @@ const struct snd_sof_dsp_ops sof_icl_ops = {
.block_read = sof_block_read,
.block_write = sof_block_write,
/* Mailbox IO */
.mailbox_read = sof_mailbox_read,
.mailbox_write = sof_mailbox_write,
/* doorbell */
.irq_thread = cnl_ipc_irq_thread,
@@ -64,6 +68,7 @@ const struct snd_sof_dsp_ops sof_icl_ops = {
.debug_map_count = ARRAY_SIZE(icl_dsp_debugfs),
.dbg_dump = hda_dsp_dump,
.ipc_dump = cnl_ipc_dump,
.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
/* stream callbacks */
.pcm_open = hda_dsp_pcm_open,
@@ -125,7 +130,7 @@ const struct snd_sof_dsp_ops sof_icl_ops = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
.arch_ops = &sof_xtensa_arch_ops,
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
EXPORT_SYMBOL_NS(sof_icl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);

View File

@@ -1,99 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0-only 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.
//
// Authors: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
/* Intel-specific SOF IPC code */
#include <linux/device.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/types.h>
#include <sound/pcm.h>
#include <sound/sof/stream.h>
#include "../ops.h"
#include "../sof-priv.h"
struct intel_stream {
size_t posn_offset;
};
/* Mailbox-based Intel IPC implementation */
void intel_ipc_msg_data(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
void *p, size_t sz)
{
if (!substream || !sdev->stream_box.size) {
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
} else {
struct intel_stream *stream = substream->runtime->private_data;
/* The stream might already be closed */
if (stream)
sof_mailbox_read(sdev, stream->posn_offset, p, sz);
}
}
EXPORT_SYMBOL_NS(intel_ipc_msg_data, SND_SOC_SOF_INTEL_HIFI_EP_IPC);
int intel_ipc_pcm_params(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
const struct sof_ipc_pcm_params_reply *reply)
{
struct intel_stream *stream = substream->runtime->private_data;
size_t posn_offset = reply->posn_offset;
/* check if offset is overflow or it is not aligned */
if (posn_offset > sdev->stream_box.size ||
posn_offset % sizeof(struct sof_ipc_stream_posn) != 0)
return -EINVAL;
stream->posn_offset = sdev->stream_box.offset + posn_offset;
dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
substream->stream, stream->posn_offset);
return 0;
}
EXPORT_SYMBOL_NS(intel_ipc_pcm_params, SND_SOC_SOF_INTEL_HIFI_EP_IPC);
int intel_pcm_open(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
{
struct intel_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
if (!stream)
return -ENOMEM;
/* binding pcm substream to hda stream */
substream->runtime->private_data = stream;
/* align to DMA minimum transfer size */
snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
/* avoid circular buffer wrap in middle of period */
snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
return 0;
}
EXPORT_SYMBOL_NS(intel_pcm_open, SND_SOC_SOF_INTEL_HIFI_EP_IPC);
int intel_pcm_close(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
{
struct intel_stream *stream = substream->runtime->private_data;
substream->runtime->private_data = NULL;
kfree(stream);
return 0;
}
EXPORT_SYMBOL_NS(intel_pcm_close, SND_SOC_SOF_INTEL_HIFI_EP_IPC);
MODULE_LICENSE("Dual BSD/GPL");

View File

@@ -26,7 +26,6 @@ static const struct sof_dev_desc bxt_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &apl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
@@ -42,7 +41,6 @@ static const struct sof_dev_desc glk_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &apl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",

View File

@@ -27,7 +27,6 @@ static const struct sof_dev_desc cnl_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &cnl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
@@ -44,7 +43,6 @@ static const struct sof_dev_desc cfl_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &cnl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
@@ -61,7 +59,6 @@ static const struct sof_dev_desc cml_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &cnl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",

View File

@@ -27,7 +27,6 @@ static const struct sof_dev_desc icl_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &icl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
@@ -43,7 +42,6 @@ static const struct sof_dev_desc jsl_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &jsl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",

View File

@@ -27,7 +27,6 @@ static const struct sof_dev_desc tgl_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &tgl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
@@ -44,7 +43,6 @@ static const struct sof_dev_desc tglh_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &tglh_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
@@ -60,7 +58,6 @@ static const struct sof_dev_desc ehl_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &ehl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
@@ -77,7 +74,6 @@ static const struct sof_dev_desc adls_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &adls_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
@@ -94,7 +90,6 @@ static const struct sof_dev_desc adl_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &tgl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",

View File

@@ -142,6 +142,10 @@ const struct snd_sof_dsp_ops sof_tng_ops = {
.block_read = sof_block_read,
.block_write = sof_block_write,
/* Mailbox IO */
.mailbox_read = sof_mailbox_read,
.mailbox_write = sof_mailbox_write,
/* doorbell */
.irq_handler = atom_irq_handler,
.irq_thread = atom_irq_thread,
@@ -152,8 +156,8 @@ const struct snd_sof_dsp_ops sof_tng_ops = {
.get_mailbox_offset = atom_get_mailbox_offset,
.get_window_offset = atom_get_window_offset,
.ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params,
.ipc_msg_data = sof_ipc_msg_data,
.ipc_pcm_params = sof_ipc_pcm_params,
/* machine driver */
.machine_select = atom_machine_select,
@@ -165,10 +169,11 @@ const struct snd_sof_dsp_ops sof_tng_ops = {
.debug_map = tng_debugfs,
.debug_map_count = ARRAY_SIZE(tng_debugfs),
.dbg_dump = atom_dump,
.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
/* stream callbacks */
.pcm_open = intel_pcm_open,
.pcm_close = intel_pcm_close,
.pcm_open = sof_stream_pcm_open,
.pcm_close = sof_stream_pcm_close,
/* module loading */
.load_module = snd_sof_parse_module_memcpy,
@@ -187,7 +192,7 @@ const struct snd_sof_dsp_ops sof_tng_ops = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_BATCH,
.arch_ops = &sof_xtensa_arch_ops,
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
const struct sof_intel_dsp_desc tng_chip_info = {
@@ -201,7 +206,6 @@ static const struct sof_dev_desc tng_desc = {
.resindex_pcicfg_base = -1,
.resindex_imr_base = 0,
.irqindex_host_ipc = -1,
.resindex_dma_base = -1,
.chip_info = &tng_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",

View File

@@ -37,6 +37,10 @@ const struct snd_sof_dsp_ops sof_tgl_ops = {
.block_read = sof_block_read,
.block_write = sof_block_write,
/* Mailbox IO */
.mailbox_read = sof_mailbox_read,
.mailbox_write = sof_mailbox_write,
/* doorbell */
.irq_thread = cnl_ipc_irq_thread,
@@ -60,6 +64,7 @@ const struct snd_sof_dsp_ops sof_tgl_ops = {
.debug_map_count = ARRAY_SIZE(tgl_dsp_debugfs),
.dbg_dump = hda_dsp_dump,
.ipc_dump = cnl_ipc_dump,
.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
/* stream callbacks */
.pcm_open = hda_dsp_pcm_open,
@@ -120,7 +125,7 @@ const struct snd_sof_dsp_ops sof_tgl_ops = {
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
.arch_ops = &sof_xtensa_arch_ops,
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
EXPORT_SYMBOL_NS(sof_tgl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);