mirror of
https://github.com/torvalds/linux.git
synced 2026-05-05 15:02:40 -04:00
Merge tag 'asoc-v5.16' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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");
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user