diff options
Diffstat (limited to 'sound/soc/sof/intel/hda-dai-ops.c')
| -rw-r--r-- | sound/soc/sof/intel/hda-dai-ops.c | 151 |
1 files changed, 75 insertions, 76 deletions
diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 494ced2b746e..92681ca7f24d 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -3,10 +3,11 @@ // 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) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation #include <sound/pcm_params.h> #include <sound/hdaudio_ext.h> +#include <sound/hda_register.h> #include <sound/hda-mlink.h> #include <sound/sof/ipc4/header.h> #include <uapi/sound/sof/header.h> @@ -43,7 +44,7 @@ static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd, static struct hdac_ext_stream * hda_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sof_intel_hda_stream *hda_stream; const struct sof_intel_dsp_desc *chip; struct snd_sof_dev *sdev; @@ -145,17 +146,9 @@ static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *dai; struct hdac_ext_stream *hext_stream; - /* only allocate a stream_tag for the first DAI in the dailink */ - dai = asoc_rtd_to_cpu(rtd, 0); - if (dai == cpu_dai) - hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream); - else - hext_stream = snd_soc_dai_get_dma_data(dai, substream); - + hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream); if (!hext_stream) return NULL; @@ -168,14 +161,9 @@ static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai struct snd_pcm_substream *substream) { struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream); - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *dai; - /* only release a stream_tag for the first DAI in the dailink */ - dai = asoc_rtd_to_cpu(rtd, 0); - if (dai == cpu_dai) - snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); + snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); } static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream, @@ -193,8 +181,8 @@ static void hda_codec_dai_set_stream(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct hdac_stream *hstream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); /* set the hdac_stream in the codec dai */ snd_soc_dai_set_stream(codec_dai, hstream, substream->stream); @@ -204,18 +192,20 @@ static unsigned int hda_calc_stream_format(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); unsigned int link_bps; unsigned int format_val; + unsigned int bits; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) link_bps = codec_dai->driver->playback.sig_bits; else link_bps = codec_dai->driver->capture.sig_bits; - format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), - params_format(params), link_bps, 0); + bits = snd_hdac_stream_format_bits(params_format(params), SNDRV_PCM_SUBFORMAT_STD, + link_bps); + format_val = snd_hdac_stream_format(params_channels(params), bits, params_rate(params)); dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, params_rate(params), params_channels(params), params_format(params)); @@ -226,8 +216,8 @@ static unsigned int hda_calc_stream_format(struct snd_sof_dev *sdev, static struct hdac_ext_link *hda_get_hlink(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct hdac_bus *bus = sof_to_bus(sdev); return snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); @@ -238,11 +228,11 @@ static unsigned int generic_calc_stream_format(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params) { unsigned int format_val; + unsigned int bits; - format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), - params_format(params), - params_physical_width(params), - 0); + bits = snd_hdac_stream_format_bits(params_format(params), SNDRV_PCM_SUBFORMAT_STD, + params_physical_width(params)); + format_val = snd_hdac_stream_format(params_channels(params), bits, params_rate(params)); dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, params_rate(params), params_channels(params), params_format(params)); @@ -258,6 +248,7 @@ static unsigned int dmic_calc_stream_format(struct snd_sof_dev *sdev, snd_pcm_format_t format; unsigned int channels; unsigned int width; + unsigned int bits; channels = params_channels(params); format = params_format(params); @@ -269,10 +260,8 @@ static unsigned int dmic_calc_stream_format(struct snd_sof_dev *sdev, width = 32; } - format_val = snd_hdac_calc_stream_format(params_rate(params), channels, - format, - width, - 0); + bits = snd_hdac_stream_format_bits(format, SNDRV_PCM_SUBFORMAT_STD, width); + format_val = snd_hdac_stream_format(channels, bits, params_rate(params)); dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, params_rate(params), channels, format); @@ -357,9 +346,20 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_hdac_ext_stream_start(hext_stream); break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + /* + * Save the LLP registers since in case of PAUSE the LLP + * register are not reset to 0, the delay calculation will use + * the saved offsets for compensating the delay calculation. + */ + hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL); + hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU); + snd_hdac_ext_stream_clear(hext_stream); + break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + hext_stream->pplcllpl = 0; + hext_stream->pplcllpu = 0; snd_hdac_ext_stream_clear(hext_stream); break; default: @@ -434,28 +434,6 @@ out: return ret; } -static struct hdac_ext_stream *sdw_hda_ipc4_get_hext_stream(struct snd_sof_dev *sdev, - struct snd_soc_dai *cpu_dai, - struct snd_pcm_substream *substream) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_sof_dai *dai = swidget->private; - struct sof_ipc4_copier *ipc4_copier = dai->private; - struct sof_ipc4_alh_configuration_blob *blob; - - blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config; - - /* - * Starting with ACE_2_0, re-setting the device_count is mandatory to avoid using - * the multi-gateway firmware configuration. The DMA hardware can take care of - * multiple links without needing any firmware assistance - */ - blob->alh_cfg.device_count = 1; - - return hda_ipc4_get_hext_stream(sdev, cpu_dai, substream); -} - static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { .get_hext_stream = hda_ipc4_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, @@ -497,7 +475,7 @@ static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops = { }; static const struct hda_dai_widget_dma_ops sdw_ipc4_dma_ops = { - .get_hext_stream = sdw_hda_ipc4_get_hext_stream, + .get_hext_stream = hda_ipc4_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, .release_hext_stream = hda_release_hext_stream, .setup_hext_stream = hda_setup_hext_stream, @@ -521,10 +499,20 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = { .get_hlink = hda_get_hlink, }; +static const struct hda_dai_widget_dma_ops sdw_ipc4_chain_dma_ops = { + .get_hext_stream = hda_get_hext_stream, + .assign_hext_stream = hda_assign_hext_stream, + .release_hext_stream = hda_release_hext_stream, + .setup_hext_stream = hda_setup_hext_stream, + .reset_hext_stream = hda_reset_hext_stream, + .trigger = hda_trigger, + .calc_stream_format = generic_calc_stream_format, + .get_hlink = sdw_get_hlink, +}; + static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream, int cmd) { - struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream); struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); switch (cmd) { @@ -539,9 +527,6 @@ static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c if (ret < 0) return ret; - if (cmd == SNDRV_PCM_TRIGGER_STOP) - return hda_link_dma_cleanup(substream, hext_stream, cpu_dai); - break; } case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -595,6 +580,13 @@ static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = { .get_hlink = hda_get_hlink, }; +static const struct hda_dai_widget_dma_ops sdw_dspless_dma_ops = { + .get_hext_stream = hda_dspless_get_hext_stream, + .setup_hext_stream = hda_dspless_setup_hext_stream, + .calc_stream_format = generic_calc_stream_format, + .get_hlink = sdw_get_hlink, +}; + #endif const struct hda_dai_widget_dma_ops * @@ -602,14 +594,26 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) struct snd_sof_dai *sdai; + const struct sof_intel_dsp_desc *chip; - if (sdev->dspless_mode_selected) - return &hda_dspless_dma_ops; - + chip = get_chip_info(sdev->pdata); sdai = swidget->private; + if (sdev->dspless_mode_selected) { + switch (sdai->type) { + case SOF_DAI_INTEL_HDA: + return &hda_dspless_dma_ops; + case SOF_DAI_INTEL_ALH: + if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) + return NULL; + return &sdw_dspless_dma_ops; + default: + return NULL; + } + } + switch (sdev->pdata->ipc_type) { - case SOF_IPC: + case SOF_IPC_TYPE_3: { struct sof_dai_private_data *private = sdai->private; @@ -617,24 +621,17 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg return &hda_ipc3_dma_ops; break; } - case SOF_INTEL_IPC4: + case SOF_IPC_TYPE_4: { - struct sof_ipc4_copier *ipc4_copier = sdai->private; - const struct sof_intel_dsp_desc *chip; - - chip = get_chip_info(sdev->pdata); + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; - switch (ipc4_copier->dai_type) { + switch (sdai->type) { case SOF_DAI_INTEL_HDA: - { - struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; - struct sof_ipc4_pipeline *pipeline = pipe_widget->private; - if (pipeline->use_chain_dma) return &hda_ipc4_chain_dma_ops; return &hda_ipc4_dma_ops; - } case SOF_DAI_INTEL_SSP: if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) return NULL; @@ -646,6 +643,8 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg case SOF_DAI_INTEL_ALH: if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) return NULL; + if (pipeline->use_chain_dma) + return &sdw_ipc4_chain_dma_ops; return &sdw_ipc4_dma_ops; default: |
