^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // This file is provided under a dual BSD/GPLv2 license. When using or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // redistributing this file, you may do so under either license.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Copyright(c) 2018 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // Rander Wang <rander.wang@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // Keyon Jie <yang.jie@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Hardware interface for generic Intel audio DSP HDA IP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/hda_register.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "../sof-audio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "../ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "hda.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SDnFMT_BASE(x) ((x) << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SDnFMT_MULT(x) (((x) - 1) << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SDnFMT_DIV(x) (((x) - 1) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SDnFMT_BITS(x) ((x) << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SDnFMT_CHAN(x) ((x) << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u32 hda_dsp_get_mult_div(struct snd_sof_dev *sdev, int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) case 8000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return SDnFMT_DIV(6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) case 9600:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return SDnFMT_DIV(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) case 11025:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return SDnFMT_BASE(1) | SDnFMT_DIV(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) case 16000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return SDnFMT_DIV(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) case 22050:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return SDnFMT_BASE(1) | SDnFMT_DIV(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) case 32000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return SDnFMT_DIV(3) | SDnFMT_MULT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case 44100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return SDnFMT_BASE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case 48000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case 88200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return SDnFMT_BASE(1) | SDnFMT_MULT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case 96000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return SDnFMT_MULT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case 176400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return SDnFMT_BASE(1) | SDnFMT_MULT(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case 192000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return SDnFMT_MULT(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) dev_warn(sdev->dev, "can't find div rate %d using 48kHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0; /* use 48KHz if not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 hda_dsp_get_bits(struct snd_sof_dev *sdev, int sample_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) switch (sample_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return SDnFMT_BITS(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return SDnFMT_BITS(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case 20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return SDnFMT_BITS(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return SDnFMT_BITS(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return SDnFMT_BITS(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) dev_warn(sdev->dev, "can't find %d bits using 16bit\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) sample_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return SDnFMT_BITS(1); /* use 16bits format if not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct sof_ipc_stream_params *ipc_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct hdac_stream *hstream = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct hdac_ext_stream *stream = stream_to_hdac_ext_stream(hstream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct snd_dma_buffer *dmab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u32 size, rate, bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) size = params_buffer_bytes(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) rate = hda_dsp_get_mult_div(sdev, params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) bits = hda_dsp_get_bits(sdev, params_width(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) hstream->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dmab = substream->runtime->dma_buffer_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) hstream->format_val = rate | bits | (params_channels(params) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) hstream->bufsize = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) hstream->period_bytes = params_period_bytes(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) hstream->no_period_wakeup =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) (params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret = hda_dsp_stream_hw_params(sdev, stream, dmab, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* disable SPIB, to enable buffer wrap for stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* update no_stream_position flag for ipc params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (hda && hda->no_ipc_position) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* For older ABIs set host_period_bytes to zero to inform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * FW we don't want position updates. Newer versions use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * no_stream_position for this purpose.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (v->abi_version < SOF_ABI_VER(3, 10, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ipc_params->host_period_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ipc_params->no_stream_position = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ipc_params->stream_tag = hstream->stream_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct hdac_stream *hstream = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct hdac_ext_stream *stream = stream_to_hdac_ext_stream(hstream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return hda_dsp_stream_trigger(sdev, stream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct snd_soc_component *scomp = sdev->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct hdac_stream *hstream = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct snd_sof_pcm *spcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) snd_pcm_uframes_t pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) spcm = snd_sof_find_spcm_dai(scomp, rtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (!spcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) rtd->dai_link->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (hda && !hda->no_ipc_position) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* read position from IPC position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) pos = spcm->stream[substream->stream].posn.host_posn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * DPIB/posbuf position mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * For Playback, Use DPIB register from HDA space which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * reflects the actual data transferred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * For Capture, Use the position buffer for pointer, as DPIB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * is not accurate enough, its update may be completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * earlier than the data written to DDR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) AZX_REG_VS_SDXDPIB_XBASE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) (AZX_REG_VS_SDXDPIB_XINTERVAL *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) hstream->index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * For capture stream, we need more workaround to fix the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * position incorrect issue:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * 1. Wait at least 20us before reading position buffer after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * the interrupt generated(IOC), to make sure position update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * happens on frame boundary i.e. 20.833uSec for 48KHz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * 2. Perform a dummy Read to DPIB register to flush DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * position value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * 3. Read the DMA Position from posbuf. Now the readback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * value should be >= period boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) usleep_range(20, 21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) AZX_REG_VS_SDXDPIB_XBASE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) (AZX_REG_VS_SDXDPIB_XINTERVAL *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) hstream->index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pos = snd_hdac_stream_get_pos_posbuf(hstream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (pos >= hstream->bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) pos = bytes_to_frames(substream->runtime, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) dev_vdbg(sdev->dev, "PCM: stream %d dir %d position %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) hstream->index, substream->stream, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct hdac_ext_stream *dsp_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int direction = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) dsp_stream = hda_dsp_stream_get(sdev, direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!dsp_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) dev_err(sdev->dev, "error: no stream available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* binding pcm substream to hda stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) substream->runtime->private_data = &dsp_stream->hstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int hda_dsp_pcm_close(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct hdac_stream *hstream = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int direction = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ret = hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dev_dbg(sdev->dev, "stream %s not opened!\n", substream->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* unbinding pcm substream to hda stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) substream->runtime->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }