18e8e69d6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2a40e693cSJeeja KP /* 3a40e693cSJeeja KP * skl-pcm.c -ASoC HDA Platform driver file implementing PCM functionality 4a40e693cSJeeja KP * 5a40e693cSJeeja KP * Copyright (C) 2014-2015 Intel Corp 6a40e693cSJeeja KP * Author: Jeeja KP <jeeja.kp@intel.com> 7a40e693cSJeeja KP * 8a40e693cSJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9a40e693cSJeeja KP * 10a40e693cSJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11a40e693cSJeeja KP */ 12a40e693cSJeeja KP 13a40e693cSJeeja KP #include <linux/pci.h> 14a40e693cSJeeja KP #include <linux/pm_runtime.h> 15fdd85a05SHardik T Shah #include <linux/delay.h> 16a40e693cSJeeja KP #include <sound/pcm_params.h> 17a40e693cSJeeja KP #include <sound/soc.h> 18a40e693cSJeeja KP #include "skl.h" 19b663a8c5SJeeja KP #include "skl-topology.h" 20721c3e36SDharageswari.R #include "skl-sst-dsp.h" 21721c3e36SDharageswari.R #include "skl-sst-ipc.h" 22a40e693cSJeeja KP 23a40e693cSJeeja KP #define HDA_MONO 1 24a40e693cSJeeja KP #define HDA_STEREO 2 258f35bf3fSJeeja KP #define HDA_QUAD 4 263d178713SRakesh Ughreja #define HDA_MAX 8 27a40e693cSJeeja KP 288df397ffSBhumika Goyal static const struct snd_pcm_hardware azx_pcm_hw = { 29a40e693cSJeeja KP .info = (SNDRV_PCM_INFO_MMAP | 30a40e693cSJeeja KP SNDRV_PCM_INFO_INTERLEAVED | 31a40e693cSJeeja KP SNDRV_PCM_INFO_BLOCK_TRANSFER | 32a40e693cSJeeja KP SNDRV_PCM_INFO_MMAP_VALID | 33a40e693cSJeeja KP SNDRV_PCM_INFO_PAUSE | 343637976bSJeeja KP SNDRV_PCM_INFO_RESUME | 35a40e693cSJeeja KP SNDRV_PCM_INFO_SYNC_START | 36a40e693cSJeeja KP SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */ 37a40e693cSJeeja KP SNDRV_PCM_INFO_HAS_LINK_ATIME | 38a40e693cSJeeja KP SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), 3906b23d93SJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE | 4006b23d93SJeeja KP SNDRV_PCM_FMTBIT_S32_LE | 4106b23d93SJeeja KP SNDRV_PCM_FMTBIT_S24_LE, 4206b23d93SJeeja KP .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | 4306b23d93SJeeja KP SNDRV_PCM_RATE_8000, 4406b23d93SJeeja KP .rate_min = 8000, 45a40e693cSJeeja KP .rate_max = 48000, 468f35bf3fSJeeja KP .channels_min = 1, 477e12dc87SSubhransu S. Prusty .channels_max = 8, 48a40e693cSJeeja KP .buffer_bytes_max = AZX_MAX_BUF_SIZE, 49a40e693cSJeeja KP .period_bytes_min = 128, 50a40e693cSJeeja KP .period_bytes_max = AZX_MAX_BUF_SIZE / 2, 51a40e693cSJeeja KP .periods_min = 2, 52a40e693cSJeeja KP .periods_max = AZX_MAX_FRAG, 53a40e693cSJeeja KP .fifo_size = 0, 54a40e693cSJeeja KP }; 55a40e693cSJeeja KP 56a40e693cSJeeja KP static inline 57a40e693cSJeeja KP struct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream) 58a40e693cSJeeja KP { 59a40e693cSJeeja KP return substream->runtime->private_data; 60a40e693cSJeeja KP } 61a40e693cSJeeja KP 6276f56faeSRakesh Ughreja static struct hdac_bus *get_bus_ctx(struct snd_pcm_substream *substream) 63a40e693cSJeeja KP { 64a40e693cSJeeja KP struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); 65a40e693cSJeeja KP struct hdac_stream *hstream = hdac_stream(stream); 66a40e693cSJeeja KP struct hdac_bus *bus = hstream->bus; 6776f56faeSRakesh Ughreja return bus; 68a40e693cSJeeja KP } 69a40e693cSJeeja KP 7076f56faeSRakesh Ughreja static int skl_substream_alloc_pages(struct hdac_bus *bus, 71a40e693cSJeeja KP struct snd_pcm_substream *substream, 72a40e693cSJeeja KP size_t size) 73a40e693cSJeeja KP { 74a40e693cSJeeja KP struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); 75a40e693cSJeeja KP 76a40e693cSJeeja KP hdac_stream(stream)->bufsize = 0; 77a40e693cSJeeja KP hdac_stream(stream)->period_bytes = 0; 78a40e693cSJeeja KP hdac_stream(stream)->format_val = 0; 79a40e693cSJeeja KP 80a40e693cSJeeja KP return snd_pcm_lib_malloc_pages(substream, size); 81a40e693cSJeeja KP } 82a40e693cSJeeja KP 83a40e693cSJeeja KP static int skl_substream_free_pages(struct hdac_bus *bus, 84a40e693cSJeeja KP struct snd_pcm_substream *substream) 85a40e693cSJeeja KP { 86a40e693cSJeeja KP return snd_pcm_lib_free_pages(substream); 87a40e693cSJeeja KP } 88a40e693cSJeeja KP 8976f56faeSRakesh Ughreja static void skl_set_pcm_constrains(struct hdac_bus *bus, 90a40e693cSJeeja KP struct snd_pcm_runtime *runtime) 91a40e693cSJeeja KP { 92a40e693cSJeeja KP snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 93a40e693cSJeeja KP 94a40e693cSJeeja KP /* avoid wrap-around with wall-clock */ 95a40e693cSJeeja KP snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 96a40e693cSJeeja KP 20, 178000000); 97a40e693cSJeeja KP } 98a40e693cSJeeja KP 9976f56faeSRakesh Ughreja static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_bus *bus) 10005057001SJeeja KP { 10176f56faeSRakesh Ughreja if (bus->ppcap) 10205057001SJeeja KP return HDAC_EXT_STREAM_TYPE_HOST; 10305057001SJeeja KP else 10405057001SJeeja KP return HDAC_EXT_STREAM_TYPE_COUPLED; 10505057001SJeeja KP } 10605057001SJeeja KP 1074557c305SJeeja KP /* 1084557c305SJeeja KP * check if the stream opened is marked as ignore_suspend by machine, if so 1094557c305SJeeja KP * then enable suspend_active refcount 1104557c305SJeeja KP * 1114557c305SJeeja KP * The count supend_active does not need lock as it is used in open/close 1124557c305SJeeja KP * and suspend context 1134557c305SJeeja KP */ 1144557c305SJeeja KP static void skl_set_suspend_active(struct snd_pcm_substream *substream, 1154557c305SJeeja KP struct snd_soc_dai *dai, bool enable) 1164557c305SJeeja KP { 11776f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dai->dev); 1184557c305SJeeja KP struct snd_soc_dapm_widget *w; 11976f56faeSRakesh Ughreja struct skl *skl = bus_to_skl(bus); 1204557c305SJeeja KP 1214557c305SJeeja KP if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1224557c305SJeeja KP w = dai->playback_widget; 1234557c305SJeeja KP else 1244557c305SJeeja KP w = dai->capture_widget; 1254557c305SJeeja KP 1264557c305SJeeja KP if (w->ignore_suspend && enable) 1274557c305SJeeja KP skl->supend_active++; 1284557c305SJeeja KP else if (w->ignore_suspend && !enable) 1294557c305SJeeja KP skl->supend_active--; 1304557c305SJeeja KP } 1314557c305SJeeja KP 132ad036bdeSJeeja KP int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) 133ad036bdeSJeeja KP { 13476f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dev); 135ad036bdeSJeeja KP unsigned int format_val; 136ad036bdeSJeeja KP struct hdac_stream *hstream; 137ad036bdeSJeeja KP struct hdac_ext_stream *stream; 138ad036bdeSJeeja KP int err; 139ad036bdeSJeeja KP 140ad036bdeSJeeja KP hstream = snd_hdac_get_stream(bus, params->stream, 141ad036bdeSJeeja KP params->host_dma_id + 1); 142ad036bdeSJeeja KP if (!hstream) 143ad036bdeSJeeja KP return -EINVAL; 144ad036bdeSJeeja KP 145ad036bdeSJeeja KP stream = stream_to_hdac_ext_stream(hstream); 14676f56faeSRakesh Ughreja snd_hdac_ext_stream_decouple(bus, stream, true); 147ad036bdeSJeeja KP 148ad036bdeSJeeja KP format_val = snd_hdac_calc_stream_format(params->s_freq, 1497f975a38SJeeja KP params->ch, params->format, params->host_bps, 0); 150ad036bdeSJeeja KP 151ad036bdeSJeeja KP dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", 152ad036bdeSJeeja KP format_val, params->s_freq, params->ch, params->format); 153ad036bdeSJeeja KP 154ad036bdeSJeeja KP snd_hdac_stream_reset(hdac_stream(stream)); 155ad036bdeSJeeja KP err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); 156ad036bdeSJeeja KP if (err < 0) 157ad036bdeSJeeja KP return err; 158ad036bdeSJeeja KP 159ad036bdeSJeeja KP err = snd_hdac_stream_setup(hdac_stream(stream)); 160ad036bdeSJeeja KP if (err < 0) 161ad036bdeSJeeja KP return err; 162ad036bdeSJeeja KP 163ad036bdeSJeeja KP hdac_stream(stream)->prepared = 1; 164ad036bdeSJeeja KP 165ad036bdeSJeeja KP return 0; 166ad036bdeSJeeja KP } 167ad036bdeSJeeja KP 168ad036bdeSJeeja KP int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) 169ad036bdeSJeeja KP { 17076f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dev); 171ad036bdeSJeeja KP unsigned int format_val; 172ad036bdeSJeeja KP struct hdac_stream *hstream; 173ad036bdeSJeeja KP struct hdac_ext_stream *stream; 174ad036bdeSJeeja KP struct hdac_ext_link *link; 175c899df3eSRander Wang unsigned char stream_tag; 176ad036bdeSJeeja KP 177ad036bdeSJeeja KP hstream = snd_hdac_get_stream(bus, params->stream, 178ad036bdeSJeeja KP params->link_dma_id + 1); 179ad036bdeSJeeja KP if (!hstream) 180ad036bdeSJeeja KP return -EINVAL; 181ad036bdeSJeeja KP 182ad036bdeSJeeja KP stream = stream_to_hdac_ext_stream(hstream); 18376f56faeSRakesh Ughreja snd_hdac_ext_stream_decouple(bus, stream, true); 1847f975a38SJeeja KP format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch, 1857f975a38SJeeja KP params->format, params->link_bps, 0); 186ad036bdeSJeeja KP 187ad036bdeSJeeja KP dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", 188ad036bdeSJeeja KP format_val, params->s_freq, params->ch, params->format); 189ad036bdeSJeeja KP 190ad036bdeSJeeja KP snd_hdac_ext_link_stream_reset(stream); 191ad036bdeSJeeja KP 192ad036bdeSJeeja KP snd_hdac_ext_link_stream_setup(stream, format_val); 193ad036bdeSJeeja KP 194c899df3eSRander Wang stream_tag = hstream->stream_tag; 195c899df3eSRander Wang if (stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { 19676f56faeSRakesh Ughreja list_for_each_entry(link, &bus->hlink_list, list) { 197ad036bdeSJeeja KP if (link->index == params->link_index) 198ad036bdeSJeeja KP snd_hdac_ext_link_set_stream_id(link, 199c899df3eSRander Wang stream_tag); 200c899df3eSRander Wang } 201ad036bdeSJeeja KP } 202ad036bdeSJeeja KP 203ad036bdeSJeeja KP stream->link_prepared = 1; 204ad036bdeSJeeja KP 205ad036bdeSJeeja KP return 0; 206ad036bdeSJeeja KP } 207ad036bdeSJeeja KP 208a40e693cSJeeja KP static int skl_pcm_open(struct snd_pcm_substream *substream, 209a40e693cSJeeja KP struct snd_soc_dai *dai) 210a40e693cSJeeja KP { 21176f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dai->dev); 212a40e693cSJeeja KP struct hdac_ext_stream *stream; 213a40e693cSJeeja KP struct snd_pcm_runtime *runtime = substream->runtime; 214a40e693cSJeeja KP struct skl_dma_params *dma_params; 215a83e3b4cSVinod Koul struct skl *skl = get_skl_ctx(dai->dev); 216a83e3b4cSVinod Koul struct skl_module_cfg *mconfig; 217a40e693cSJeeja KP 218a40e693cSJeeja KP dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); 219a40e693cSJeeja KP 22076f56faeSRakesh Ughreja stream = snd_hdac_ext_stream_assign(bus, substream, 22176f56faeSRakesh Ughreja skl_get_host_stream_type(bus)); 222a40e693cSJeeja KP if (stream == NULL) 223a40e693cSJeeja KP return -EBUSY; 224a40e693cSJeeja KP 22576f56faeSRakesh Ughreja skl_set_pcm_constrains(bus, runtime); 226a40e693cSJeeja KP 227a40e693cSJeeja KP /* 228a40e693cSJeeja KP * disable WALLCLOCK timestamps for capture streams 229a40e693cSJeeja KP * until we figure out how to handle digital inputs 230a40e693cSJeeja KP */ 231a40e693cSJeeja KP if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 232a40e693cSJeeja KP runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */ 233a40e693cSJeeja KP runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME; 234a40e693cSJeeja KP } 235a40e693cSJeeja KP 236a40e693cSJeeja KP runtime->private_data = stream; 237a40e693cSJeeja KP 238a40e693cSJeeja KP dma_params = kzalloc(sizeof(*dma_params), GFP_KERNEL); 239a40e693cSJeeja KP if (!dma_params) 240a40e693cSJeeja KP return -ENOMEM; 241a40e693cSJeeja KP 242a40e693cSJeeja KP dma_params->stream_tag = hdac_stream(stream)->stream_tag; 243a40e693cSJeeja KP snd_soc_dai_set_dma_data(dai, substream, dma_params); 244a40e693cSJeeja KP 245a40e693cSJeeja KP dev_dbg(dai->dev, "stream tag set in dma params=%d\n", 246a40e693cSJeeja KP dma_params->stream_tag); 2474557c305SJeeja KP skl_set_suspend_active(substream, dai, true); 248a40e693cSJeeja KP snd_pcm_set_sync(substream); 249a40e693cSJeeja KP 250a83e3b4cSVinod Koul mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); 25191ce5497SG Kranthi if (!mconfig) 25291ce5497SG Kranthi return -EINVAL; 25391ce5497SG Kranthi 254a83e3b4cSVinod Koul skl_tplg_d0i3_get(skl, mconfig->d0i3_caps); 255a83e3b4cSVinod Koul 256a40e693cSJeeja KP return 0; 257a40e693cSJeeja KP } 258a40e693cSJeeja KP 259a40e693cSJeeja KP static int skl_pcm_prepare(struct snd_pcm_substream *substream, 260a40e693cSJeeja KP struct snd_soc_dai *dai) 261a40e693cSJeeja KP { 2622004432fSJeeja KP struct skl *skl = get_skl_ctx(dai->dev); 2632004432fSJeeja KP struct skl_module_cfg *mconfig; 26474e65192SPardha Saradhi K int ret; 265a40e693cSJeeja KP 266a40e693cSJeeja KP dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); 267a40e693cSJeeja KP 2682004432fSJeeja KP mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); 2692004432fSJeeja KP 27074e65192SPardha Saradhi K /* 27174e65192SPardha Saradhi K * In case of XRUN recovery or in the case when the application 27274e65192SPardha Saradhi K * calls prepare another time, reset the FW pipe to clean state 27374e65192SPardha Saradhi K */ 27474e65192SPardha Saradhi K if (mconfig && 27574e65192SPardha Saradhi K (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN || 27674e65192SPardha Saradhi K mconfig->pipe->state == SKL_PIPE_CREATED || 27774e65192SPardha Saradhi K mconfig->pipe->state == SKL_PIPE_PAUSED)) { 27874e65192SPardha Saradhi K 27974e65192SPardha Saradhi K ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe); 28074e65192SPardha Saradhi K 28174e65192SPardha Saradhi K if (ret < 0) 28274e65192SPardha Saradhi K return ret; 28374e65192SPardha Saradhi K 28474e65192SPardha Saradhi K ret = skl_pcm_host_dma_prepare(dai->dev, 28574e65192SPardha Saradhi K mconfig->pipe->p_params); 28674e65192SPardha Saradhi K if (ret < 0) 28774e65192SPardha Saradhi K return ret; 28874e65192SPardha Saradhi K } 2892004432fSJeeja KP 290bb704a73SJeeja KP return 0; 291a40e693cSJeeja KP } 292a40e693cSJeeja KP 293a40e693cSJeeja KP static int skl_pcm_hw_params(struct snd_pcm_substream *substream, 294a40e693cSJeeja KP struct snd_pcm_hw_params *params, 295a40e693cSJeeja KP struct snd_soc_dai *dai) 296a40e693cSJeeja KP { 29776f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dai->dev); 29805057001SJeeja KP struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); 299a40e693cSJeeja KP struct snd_pcm_runtime *runtime = substream->runtime; 300b663a8c5SJeeja KP struct skl_pipe_params p_params = {0}; 301b663a8c5SJeeja KP struct skl_module_cfg *m_cfg; 30205057001SJeeja KP int ret, dma_id; 303a40e693cSJeeja KP 304a40e693cSJeeja KP dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); 30576f56faeSRakesh Ughreja ret = skl_substream_alloc_pages(bus, substream, 306a40e693cSJeeja KP params_buffer_bytes(params)); 307a40e693cSJeeja KP if (ret < 0) 308a40e693cSJeeja KP return ret; 309a40e693cSJeeja KP 310a40e693cSJeeja KP dev_dbg(dai->dev, "format_val, rate=%d, ch=%d, format=%d\n", 311a40e693cSJeeja KP runtime->rate, runtime->channels, runtime->format); 312a40e693cSJeeja KP 31305057001SJeeja KP dma_id = hdac_stream(stream)->stream_tag - 1; 31405057001SJeeja KP dev_dbg(dai->dev, "dma_id=%d\n", dma_id); 31505057001SJeeja KP 316b663a8c5SJeeja KP p_params.s_fmt = snd_pcm_format_width(params_format(params)); 317b663a8c5SJeeja KP p_params.ch = params_channels(params); 318b663a8c5SJeeja KP p_params.s_freq = params_rate(params); 319b663a8c5SJeeja KP p_params.host_dma_id = dma_id; 320b663a8c5SJeeja KP p_params.stream = substream->stream; 32112c3be0eSJeeja KP p_params.format = params_format(params); 3227f975a38SJeeja KP if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 3237f975a38SJeeja KP p_params.host_bps = dai->driver->playback.sig_bits; 3247f975a38SJeeja KP else 3257f975a38SJeeja KP p_params.host_bps = dai->driver->capture.sig_bits; 3267f975a38SJeeja KP 327b663a8c5SJeeja KP 328b663a8c5SJeeja KP m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream); 329b663a8c5SJeeja KP if (m_cfg) 330b663a8c5SJeeja KP skl_tplg_update_pipe_params(dai->dev, m_cfg, &p_params); 331b663a8c5SJeeja KP 332a40e693cSJeeja KP return 0; 333a40e693cSJeeja KP } 334a40e693cSJeeja KP 335a40e693cSJeeja KP static void skl_pcm_close(struct snd_pcm_substream *substream, 336a40e693cSJeeja KP struct snd_soc_dai *dai) 337a40e693cSJeeja KP { 338a40e693cSJeeja KP struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); 33976f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dai->dev); 340a40e693cSJeeja KP struct skl_dma_params *dma_params = NULL; 34176f56faeSRakesh Ughreja struct skl *skl = bus_to_skl(bus); 342a83e3b4cSVinod Koul struct skl_module_cfg *mconfig; 343a40e693cSJeeja KP 344a40e693cSJeeja KP dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); 34505057001SJeeja KP 34676f56faeSRakesh Ughreja snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(bus)); 347a40e693cSJeeja KP 348a40e693cSJeeja KP dma_params = snd_soc_dai_get_dma_data(dai, substream); 349a40e693cSJeeja KP /* 350a40e693cSJeeja KP * now we should set this to NULL as we are freeing by the 351a40e693cSJeeja KP * dma_params 352a40e693cSJeeja KP */ 353a40e693cSJeeja KP snd_soc_dai_set_dma_data(dai, substream, NULL); 3544557c305SJeeja KP skl_set_suspend_active(substream, dai, false); 355a40e693cSJeeja KP 356721c3e36SDharageswari.R /* 357721c3e36SDharageswari.R * check if close is for "Reference Pin" and set back the 358721c3e36SDharageswari.R * CGCTL.MISCBDCGE if disabled by driver 359721c3e36SDharageswari.R */ 360721c3e36SDharageswari.R if (!strncmp(dai->name, "Reference Pin", 13) && 361721c3e36SDharageswari.R skl->skl_sst->miscbdcg_disabled) { 362721c3e36SDharageswari.R skl->skl_sst->enable_miscbdcge(dai->dev, true); 363721c3e36SDharageswari.R skl->skl_sst->miscbdcg_disabled = false; 364721c3e36SDharageswari.R } 365721c3e36SDharageswari.R 366a83e3b4cSVinod Koul mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); 3670265ddd7SPankaj Bharadiya if (mconfig) 368a83e3b4cSVinod Koul skl_tplg_d0i3_put(skl, mconfig->d0i3_caps); 369a83e3b4cSVinod Koul 370a40e693cSJeeja KP kfree(dma_params); 371a40e693cSJeeja KP } 372a40e693cSJeeja KP 373a40e693cSJeeja KP static int skl_pcm_hw_free(struct snd_pcm_substream *substream, 374a40e693cSJeeja KP struct snd_soc_dai *dai) 375a40e693cSJeeja KP { 37676f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dai->dev); 377a40e693cSJeeja KP struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); 378179c2e86SDivya Prakash struct skl *skl = get_skl_ctx(dai->dev); 379179c2e86SDivya Prakash struct skl_module_cfg *mconfig; 380179c2e86SDivya Prakash int ret; 381a40e693cSJeeja KP 382a40e693cSJeeja KP dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); 383a40e693cSJeeja KP 384179c2e86SDivya Prakash mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); 385179c2e86SDivya Prakash 386179c2e86SDivya Prakash if (mconfig) { 387179c2e86SDivya Prakash ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe); 388179c2e86SDivya Prakash if (ret < 0) 389179c2e86SDivya Prakash dev_err(dai->dev, "%s:Reset failed ret =%d", 390179c2e86SDivya Prakash __func__, ret); 391179c2e86SDivya Prakash } 392179c2e86SDivya Prakash 393a40e693cSJeeja KP snd_hdac_stream_cleanup(hdac_stream(stream)); 394a40e693cSJeeja KP hdac_stream(stream)->prepared = 0; 395a40e693cSJeeja KP 39676f56faeSRakesh Ughreja return skl_substream_free_pages(bus, substream); 397a40e693cSJeeja KP } 398a40e693cSJeeja KP 399b663a8c5SJeeja KP static int skl_be_hw_params(struct snd_pcm_substream *substream, 400b663a8c5SJeeja KP struct snd_pcm_hw_params *params, 401b663a8c5SJeeja KP struct snd_soc_dai *dai) 402b663a8c5SJeeja KP { 403b663a8c5SJeeja KP struct skl_pipe_params p_params = {0}; 404b663a8c5SJeeja KP 405b663a8c5SJeeja KP p_params.s_fmt = snd_pcm_format_width(params_format(params)); 406b663a8c5SJeeja KP p_params.ch = params_channels(params); 407b663a8c5SJeeja KP p_params.s_freq = params_rate(params); 408b663a8c5SJeeja KP p_params.stream = substream->stream; 409b663a8c5SJeeja KP 4104bd073f9SJeeja KP return skl_tplg_be_update_params(dai, &p_params); 411b663a8c5SJeeja KP } 412b663a8c5SJeeja KP 413d1730c3dSJeeja KP static int skl_decoupled_trigger(struct snd_pcm_substream *substream, 414d1730c3dSJeeja KP int cmd) 415d1730c3dSJeeja KP { 41676f56faeSRakesh Ughreja struct hdac_bus *bus = get_bus_ctx(substream); 417d1730c3dSJeeja KP struct hdac_ext_stream *stream; 418d1730c3dSJeeja KP int start; 419d1730c3dSJeeja KP unsigned long cookie; 420d1730c3dSJeeja KP struct hdac_stream *hstr; 421d1730c3dSJeeja KP 422d1730c3dSJeeja KP stream = get_hdac_ext_stream(substream); 423d1730c3dSJeeja KP hstr = hdac_stream(stream); 424d1730c3dSJeeja KP 425d1730c3dSJeeja KP if (!hstr->prepared) 426d1730c3dSJeeja KP return -EPIPE; 427d1730c3dSJeeja KP 428d1730c3dSJeeja KP switch (cmd) { 429d1730c3dSJeeja KP case SNDRV_PCM_TRIGGER_START: 430d1730c3dSJeeja KP case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 431d1730c3dSJeeja KP case SNDRV_PCM_TRIGGER_RESUME: 432d1730c3dSJeeja KP start = 1; 433d1730c3dSJeeja KP break; 434d1730c3dSJeeja KP 435d1730c3dSJeeja KP case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 436d1730c3dSJeeja KP case SNDRV_PCM_TRIGGER_SUSPEND: 437d1730c3dSJeeja KP case SNDRV_PCM_TRIGGER_STOP: 438d1730c3dSJeeja KP start = 0; 439d1730c3dSJeeja KP break; 440d1730c3dSJeeja KP 441d1730c3dSJeeja KP default: 442d1730c3dSJeeja KP return -EINVAL; 443d1730c3dSJeeja KP } 444d1730c3dSJeeja KP 445d1730c3dSJeeja KP spin_lock_irqsave(&bus->reg_lock, cookie); 446d1730c3dSJeeja KP 447d1730c3dSJeeja KP if (start) { 448d1730c3dSJeeja KP snd_hdac_stream_start(hdac_stream(stream), true); 449d1730c3dSJeeja KP snd_hdac_stream_timecounter_init(hstr, 0); 450d1730c3dSJeeja KP } else { 451d1730c3dSJeeja KP snd_hdac_stream_stop(hdac_stream(stream)); 452d1730c3dSJeeja KP } 453d1730c3dSJeeja KP 454d1730c3dSJeeja KP spin_unlock_irqrestore(&bus->reg_lock, cookie); 455d1730c3dSJeeja KP 456d1730c3dSJeeja KP return 0; 457d1730c3dSJeeja KP } 458d1730c3dSJeeja KP 459b663a8c5SJeeja KP static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, 460b663a8c5SJeeja KP struct snd_soc_dai *dai) 461b663a8c5SJeeja KP { 462b663a8c5SJeeja KP struct skl *skl = get_skl_ctx(dai->dev); 463b663a8c5SJeeja KP struct skl_sst *ctx = skl->skl_sst; 464b663a8c5SJeeja KP struct skl_module_cfg *mconfig; 46576f56faeSRakesh Ughreja struct hdac_bus *bus = get_bus_ctx(substream); 4667e3a17d3SJeeja KP struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); 4679a655db0SJeeja KP struct snd_soc_dapm_widget *w; 468d1730c3dSJeeja KP int ret; 469b663a8c5SJeeja KP 470b663a8c5SJeeja KP mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); 471b663a8c5SJeeja KP if (!mconfig) 472b663a8c5SJeeja KP return -EIO; 473b663a8c5SJeeja KP 4749a655db0SJeeja KP if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 4759a655db0SJeeja KP w = dai->playback_widget; 4769a655db0SJeeja KP else 4779a655db0SJeeja KP w = dai->capture_widget; 4789a655db0SJeeja KP 479b663a8c5SJeeja KP switch (cmd) { 4807e3a17d3SJeeja KP case SNDRV_PCM_TRIGGER_RESUME: 4819a655db0SJeeja KP if (!w->ignore_suspend) { 482748a1d5aSJeeja KP /* 4839a655db0SJeeja KP * enable DMA Resume enable bit for the stream, set the 4849a655db0SJeeja KP * dpib & lpib position to resume before starting the 4859a655db0SJeeja KP * DMA 486748a1d5aSJeeja KP */ 48776f56faeSRakesh Ughreja snd_hdac_ext_stream_drsm_enable(bus, true, 488748a1d5aSJeeja KP hdac_stream(stream)->index); 48976f56faeSRakesh Ughreja snd_hdac_ext_stream_set_dpibr(bus, stream, 490a700a1e6SJeeja KP stream->lpib); 491748a1d5aSJeeja KP snd_hdac_ext_stream_set_lpib(stream, stream->lpib); 4929a655db0SJeeja KP } 493e4bfd615STakashi Iwai /* fall through */ 494748a1d5aSJeeja KP 495d1730c3dSJeeja KP case SNDRV_PCM_TRIGGER_START: 496b663a8c5SJeeja KP case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 497d1730c3dSJeeja KP /* 498d1730c3dSJeeja KP * Start HOST DMA and Start FE Pipe.This is to make sure that 499d1730c3dSJeeja KP * there are no underrun/overrun in the case when the FE 500d1730c3dSJeeja KP * pipeline is started but there is a delay in starting the 501d1730c3dSJeeja KP * DMA channel on the host. 502d1730c3dSJeeja KP */ 503d1730c3dSJeeja KP ret = skl_decoupled_trigger(substream, cmd); 504d1730c3dSJeeja KP if (ret < 0) 505d1730c3dSJeeja KP return ret; 506b663a8c5SJeeja KP return skl_run_pipe(ctx, mconfig->pipe); 507d1730c3dSJeeja KP break; 508b663a8c5SJeeja KP 509b663a8c5SJeeja KP case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 510b663a8c5SJeeja KP case SNDRV_PCM_TRIGGER_SUSPEND: 511d1730c3dSJeeja KP case SNDRV_PCM_TRIGGER_STOP: 512d1730c3dSJeeja KP /* 513d1730c3dSJeeja KP * Stop FE Pipe first and stop DMA. This is to make sure that 514d1730c3dSJeeja KP * there are no underrun/overrun in the case if there is a delay 515d1730c3dSJeeja KP * between the two operations. 516d1730c3dSJeeja KP */ 517d1730c3dSJeeja KP ret = skl_stop_pipe(ctx, mconfig->pipe); 518d1730c3dSJeeja KP if (ret < 0) 519d1730c3dSJeeja KP return ret; 520d1730c3dSJeeja KP 521d1730c3dSJeeja KP ret = skl_decoupled_trigger(substream, cmd); 5229a655db0SJeeja KP if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) { 523748a1d5aSJeeja KP /* save the dpib and lpib positions */ 52476f56faeSRakesh Ughreja stream->dpib = readl(bus->remap_addr + 525748a1d5aSJeeja KP AZX_REG_VS_SDXDPIB_XBASE + 526748a1d5aSJeeja KP (AZX_REG_VS_SDXDPIB_XINTERVAL * 527748a1d5aSJeeja KP hdac_stream(stream)->index)); 528748a1d5aSJeeja KP 529748a1d5aSJeeja KP stream->lpib = snd_hdac_stream_get_pos_lpib( 530748a1d5aSJeeja KP hdac_stream(stream)); 53176f56faeSRakesh Ughreja snd_hdac_ext_stream_decouple(bus, stream, false); 532748a1d5aSJeeja KP } 533d1730c3dSJeeja KP break; 534b663a8c5SJeeja KP 535b663a8c5SJeeja KP default: 536d1730c3dSJeeja KP return -EINVAL; 537b663a8c5SJeeja KP } 538d1730c3dSJeeja KP 539d1730c3dSJeeja KP return 0; 540b663a8c5SJeeja KP } 541b663a8c5SJeeja KP 54276f56faeSRakesh Ughreja 54305057001SJeeja KP static int skl_link_hw_params(struct snd_pcm_substream *substream, 54405057001SJeeja KP struct snd_pcm_hw_params *params, 54505057001SJeeja KP struct snd_soc_dai *dai) 54605057001SJeeja KP { 54776f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dai->dev); 54805057001SJeeja KP struct hdac_ext_stream *link_dev; 54905057001SJeeja KP struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 55005057001SJeeja KP struct snd_soc_dai *codec_dai = rtd->codec_dai; 551b663a8c5SJeeja KP struct skl_pipe_params p_params = {0}; 55212c3be0eSJeeja KP struct hdac_ext_link *link; 5531011509dSJeeja KP int stream_tag; 55405057001SJeeja KP 55576f56faeSRakesh Ughreja link_dev = snd_hdac_ext_stream_assign(bus, substream, 55605057001SJeeja KP HDAC_EXT_STREAM_TYPE_LINK); 55705057001SJeeja KP if (!link_dev) 55805057001SJeeja KP return -EBUSY; 55905057001SJeeja KP 56005057001SJeeja KP snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); 56105057001SJeeja KP 56276f56faeSRakesh Ughreja link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name); 56312c3be0eSJeeja KP if (!link) 56412c3be0eSJeeja KP return -EINVAL; 56512c3be0eSJeeja KP 5661011509dSJeeja KP stream_tag = hdac_stream(link_dev)->stream_tag; 5671011509dSJeeja KP 56805057001SJeeja KP /* set the stream tag in the codec dai dma params */ 5693d178713SRakesh Ughreja if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 5701011509dSJeeja KP snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0); 5713d178713SRakesh Ughreja else 5723d178713SRakesh Ughreja snd_soc_dai_set_tdm_slot(codec_dai, 0, stream_tag, 0, 0); 573b663a8c5SJeeja KP 574b663a8c5SJeeja KP p_params.s_fmt = snd_pcm_format_width(params_format(params)); 575b663a8c5SJeeja KP p_params.ch = params_channels(params); 576b663a8c5SJeeja KP p_params.s_freq = params_rate(params); 577b663a8c5SJeeja KP p_params.stream = substream->stream; 5781011509dSJeeja KP p_params.link_dma_id = stream_tag - 1; 57912c3be0eSJeeja KP p_params.link_index = link->index; 58012c3be0eSJeeja KP p_params.format = params_format(params); 581b663a8c5SJeeja KP 5827f975a38SJeeja KP if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 5837f975a38SJeeja KP p_params.link_bps = codec_dai->driver->playback.sig_bits; 5847f975a38SJeeja KP else 5857f975a38SJeeja KP p_params.link_bps = codec_dai->driver->capture.sig_bits; 5867f975a38SJeeja KP 5874bd073f9SJeeja KP return skl_tplg_be_update_params(dai, &p_params); 58805057001SJeeja KP } 58905057001SJeeja KP 59005057001SJeeja KP static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, 59105057001SJeeja KP struct snd_soc_dai *dai) 59205057001SJeeja KP { 5932004432fSJeeja KP struct skl *skl = get_skl_ctx(dai->dev); 5942004432fSJeeja KP struct skl_module_cfg *mconfig = NULL; 59505057001SJeeja KP 5962004432fSJeeja KP /* In case of XRUN recovery, reset the FW pipe to clean state */ 5972004432fSJeeja KP mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); 5987cbfdf87SJeeja KP if (mconfig && !mconfig->pipe->passthru && 5997cbfdf87SJeeja KP (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) 6002004432fSJeeja KP skl_reset_pipe(skl->skl_sst, mconfig->pipe); 6012004432fSJeeja KP 60205057001SJeeja KP return 0; 60305057001SJeeja KP } 60405057001SJeeja KP 60505057001SJeeja KP static int skl_link_pcm_trigger(struct snd_pcm_substream *substream, 60605057001SJeeja KP int cmd, struct snd_soc_dai *dai) 60705057001SJeeja KP { 60805057001SJeeja KP struct hdac_ext_stream *link_dev = 60905057001SJeeja KP snd_soc_dai_get_dma_data(dai, substream); 61076f56faeSRakesh Ughreja struct hdac_bus *bus = get_bus_ctx(substream); 611920982c9SJeeja KP struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); 61205057001SJeeja KP 61305057001SJeeja KP dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); 61405057001SJeeja KP switch (cmd) { 615920982c9SJeeja KP case SNDRV_PCM_TRIGGER_RESUME: 61605057001SJeeja KP case SNDRV_PCM_TRIGGER_START: 61705057001SJeeja KP case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 61805057001SJeeja KP snd_hdac_ext_link_stream_start(link_dev); 61905057001SJeeja KP break; 62005057001SJeeja KP 62105057001SJeeja KP case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 62205057001SJeeja KP case SNDRV_PCM_TRIGGER_SUSPEND: 62305057001SJeeja KP case SNDRV_PCM_TRIGGER_STOP: 62405057001SJeeja KP snd_hdac_ext_link_stream_clear(link_dev); 625920982c9SJeeja KP if (cmd == SNDRV_PCM_TRIGGER_SUSPEND) 62676f56faeSRakesh Ughreja snd_hdac_ext_stream_decouple(bus, stream, false); 62705057001SJeeja KP break; 62805057001SJeeja KP 62905057001SJeeja KP default: 63005057001SJeeja KP return -EINVAL; 63105057001SJeeja KP } 63205057001SJeeja KP return 0; 63305057001SJeeja KP } 63405057001SJeeja KP 63505057001SJeeja KP static int skl_link_hw_free(struct snd_pcm_substream *substream, 63605057001SJeeja KP struct snd_soc_dai *dai) 63705057001SJeeja KP { 63876f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dai->dev); 63905057001SJeeja KP struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 64005057001SJeeja KP struct hdac_ext_stream *link_dev = 64105057001SJeeja KP snd_soc_dai_get_dma_data(dai, substream); 64205057001SJeeja KP struct hdac_ext_link *link; 643c899df3eSRander Wang unsigned char stream_tag; 64405057001SJeeja KP 64505057001SJeeja KP dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); 64605057001SJeeja KP 64705057001SJeeja KP link_dev->link_prepared = 0; 64805057001SJeeja KP 64976f56faeSRakesh Ughreja link = snd_hdac_ext_bus_get_link(bus, rtd->codec_dai->component->name); 65005057001SJeeja KP if (!link) 65105057001SJeeja KP return -EINVAL; 65205057001SJeeja KP 653c899df3eSRander Wang if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 654c899df3eSRander Wang stream_tag = hdac_stream(link_dev)->stream_tag; 655c899df3eSRander Wang snd_hdac_ext_link_clear_stream_id(link, stream_tag); 656c899df3eSRander Wang } 657c899df3eSRander Wang 65805057001SJeeja KP snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); 65905057001SJeeja KP return 0; 66005057001SJeeja KP } 66105057001SJeeja KP 66282e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_pcm_dai_ops = { 663a40e693cSJeeja KP .startup = skl_pcm_open, 664a40e693cSJeeja KP .shutdown = skl_pcm_close, 665a40e693cSJeeja KP .prepare = skl_pcm_prepare, 666a40e693cSJeeja KP .hw_params = skl_pcm_hw_params, 667a40e693cSJeeja KP .hw_free = skl_pcm_hw_free, 668b663a8c5SJeeja KP .trigger = skl_pcm_trigger, 669a40e693cSJeeja KP }; 670a40e693cSJeeja KP 67182e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_dmic_dai_ops = { 672b663a8c5SJeeja KP .hw_params = skl_be_hw_params, 673b663a8c5SJeeja KP }; 674b663a8c5SJeeja KP 67582e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = { 676b663a8c5SJeeja KP .hw_params = skl_be_hw_params, 67705057001SJeeja KP }; 67805057001SJeeja KP 67982e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_link_dai_ops = { 68005057001SJeeja KP .prepare = skl_link_pcm_prepare, 68105057001SJeeja KP .hw_params = skl_link_hw_params, 68205057001SJeeja KP .hw_free = skl_link_hw_free, 68305057001SJeeja KP .trigger = skl_link_pcm_trigger, 68405057001SJeeja KP }; 68505057001SJeeja KP 686c3ae22e3SGuneshwor Singh static struct snd_soc_dai_driver skl_fe_dai[] = { 687a40e693cSJeeja KP { 688a40e693cSJeeja KP .name = "System Pin", 689a40e693cSJeeja KP .ops = &skl_pcm_dai_ops, 690a40e693cSJeeja KP .playback = { 691a40e693cSJeeja KP .stream_name = "System Playback", 692a40e693cSJeeja KP .channels_min = HDA_MONO, 693a40e693cSJeeja KP .channels_max = HDA_STEREO, 694a40e693cSJeeja KP .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000, 695dde53bccSSamaga Krishna .formats = SNDRV_PCM_FMTBIT_S16_LE | 696dde53bccSSamaga Krishna SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, 6977f975a38SJeeja KP .sig_bits = 32, 698a40e693cSJeeja KP }, 699a40e693cSJeeja KP .capture = { 700a40e693cSJeeja KP .stream_name = "System Capture", 701a40e693cSJeeja KP .channels_min = HDA_MONO, 702a40e693cSJeeja KP .channels_max = HDA_STEREO, 703a40e693cSJeeja KP .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, 704a40e693cSJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 7057f975a38SJeeja KP .sig_bits = 32, 706a40e693cSJeeja KP }, 707a40e693cSJeeja KP }, 708a40e693cSJeeja KP { 709da3cbb40SNaveen Manohar .name = "System Pin2", 710da3cbb40SNaveen Manohar .ops = &skl_pcm_dai_ops, 711da3cbb40SNaveen Manohar .playback = { 712da3cbb40SNaveen Manohar .stream_name = "Headset Playback", 713da3cbb40SNaveen Manohar .channels_min = HDA_MONO, 714da3cbb40SNaveen Manohar .channels_max = HDA_STEREO, 715da3cbb40SNaveen Manohar .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | 716da3cbb40SNaveen Manohar SNDRV_PCM_RATE_8000, 717da3cbb40SNaveen Manohar .formats = SNDRV_PCM_FMTBIT_S16_LE | 718da3cbb40SNaveen Manohar SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, 719da3cbb40SNaveen Manohar }, 720da3cbb40SNaveen Manohar }, 721da3cbb40SNaveen Manohar { 722da3cbb40SNaveen Manohar .name = "Echoref Pin", 723da3cbb40SNaveen Manohar .ops = &skl_pcm_dai_ops, 724da3cbb40SNaveen Manohar .capture = { 725da3cbb40SNaveen Manohar .stream_name = "Echoreference Capture", 726da3cbb40SNaveen Manohar .channels_min = HDA_STEREO, 727da3cbb40SNaveen Manohar .channels_max = HDA_STEREO, 728da3cbb40SNaveen Manohar .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | 729da3cbb40SNaveen Manohar SNDRV_PCM_RATE_8000, 730da3cbb40SNaveen Manohar .formats = SNDRV_PCM_FMTBIT_S16_LE | 731da3cbb40SNaveen Manohar SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, 732da3cbb40SNaveen Manohar }, 733da3cbb40SNaveen Manohar }, 734da3cbb40SNaveen Manohar { 73505057001SJeeja KP .name = "Reference Pin", 73605057001SJeeja KP .ops = &skl_pcm_dai_ops, 73705057001SJeeja KP .capture = { 73805057001SJeeja KP .stream_name = "Reference Capture", 73905057001SJeeja KP .channels_min = HDA_MONO, 7408f35bf3fSJeeja KP .channels_max = HDA_QUAD, 74105057001SJeeja KP .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, 74205057001SJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 7437f975a38SJeeja KP .sig_bits = 32, 74405057001SJeeja KP }, 74505057001SJeeja KP }, 74605057001SJeeja KP { 747a40e693cSJeeja KP .name = "Deepbuffer Pin", 748a40e693cSJeeja KP .ops = &skl_pcm_dai_ops, 749a40e693cSJeeja KP .playback = { 750a40e693cSJeeja KP .stream_name = "Deepbuffer Playback", 751a40e693cSJeeja KP .channels_min = HDA_STEREO, 752a40e693cSJeeja KP .channels_max = HDA_STEREO, 753a40e693cSJeeja KP .rates = SNDRV_PCM_RATE_48000, 754a40e693cSJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 7557f975a38SJeeja KP .sig_bits = 32, 756a40e693cSJeeja KP }, 757a40e693cSJeeja KP }, 758a40e693cSJeeja KP { 759a40e693cSJeeja KP .name = "LowLatency Pin", 760a40e693cSJeeja KP .ops = &skl_pcm_dai_ops, 761a40e693cSJeeja KP .playback = { 762a40e693cSJeeja KP .stream_name = "Low Latency Playback", 763a40e693cSJeeja KP .channels_min = HDA_STEREO, 764a40e693cSJeeja KP .channels_max = HDA_STEREO, 765a40e693cSJeeja KP .rates = SNDRV_PCM_RATE_48000, 766a40e693cSJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 7677f975a38SJeeja KP .sig_bits = 32, 768a40e693cSJeeja KP }, 769a40e693cSJeeja KP }, 7708f35bf3fSJeeja KP { 7718f35bf3fSJeeja KP .name = "DMIC Pin", 7728f35bf3fSJeeja KP .ops = &skl_pcm_dai_ops, 7738f35bf3fSJeeja KP .capture = { 7748f35bf3fSJeeja KP .stream_name = "DMIC Capture", 7758f35bf3fSJeeja KP .channels_min = HDA_MONO, 7768f35bf3fSJeeja KP .channels_max = HDA_QUAD, 7778f35bf3fSJeeja KP .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, 7788f35bf3fSJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 7797f975a38SJeeja KP .sig_bits = 32, 7808f35bf3fSJeeja KP }, 7818f35bf3fSJeeja KP }, 7828cca87c0SSubhransu S. Prusty { 7838cca87c0SSubhransu S. Prusty .name = "HDMI1 Pin", 7848cca87c0SSubhransu S. Prusty .ops = &skl_pcm_dai_ops, 7858cca87c0SSubhransu S. Prusty .playback = { 7868cca87c0SSubhransu S. Prusty .stream_name = "HDMI1 Playback", 7878cca87c0SSubhransu S. Prusty .channels_min = HDA_STEREO, 7887e12dc87SSubhransu S. Prusty .channels_max = 8, 7898cca87c0SSubhransu S. Prusty .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 7908cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | 7918cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | 7928cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_192000, 7938cca87c0SSubhransu S. Prusty .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 7948cca87c0SSubhransu S. Prusty SNDRV_PCM_FMTBIT_S32_LE, 7957f975a38SJeeja KP .sig_bits = 32, 7968cca87c0SSubhransu S. Prusty }, 7978cca87c0SSubhransu S. Prusty }, 7988cca87c0SSubhransu S. Prusty { 7998cca87c0SSubhransu S. Prusty .name = "HDMI2 Pin", 8008cca87c0SSubhransu S. Prusty .ops = &skl_pcm_dai_ops, 8018cca87c0SSubhransu S. Prusty .playback = { 8028cca87c0SSubhransu S. Prusty .stream_name = "HDMI2 Playback", 8038cca87c0SSubhransu S. Prusty .channels_min = HDA_STEREO, 8047e12dc87SSubhransu S. Prusty .channels_max = 8, 8058cca87c0SSubhransu S. Prusty .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 8068cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | 8078cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | 8088cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_192000, 8098cca87c0SSubhransu S. Prusty .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 8108cca87c0SSubhransu S. Prusty SNDRV_PCM_FMTBIT_S32_LE, 8117f975a38SJeeja KP .sig_bits = 32, 8128cca87c0SSubhransu S. Prusty }, 8138cca87c0SSubhransu S. Prusty }, 8148cca87c0SSubhransu S. Prusty { 8158cca87c0SSubhransu S. Prusty .name = "HDMI3 Pin", 8168cca87c0SSubhransu S. Prusty .ops = &skl_pcm_dai_ops, 8178cca87c0SSubhransu S. Prusty .playback = { 8188cca87c0SSubhransu S. Prusty .stream_name = "HDMI3 Playback", 8198cca87c0SSubhransu S. Prusty .channels_min = HDA_STEREO, 8207e12dc87SSubhransu S. Prusty .channels_max = 8, 8218cca87c0SSubhransu S. Prusty .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 8228cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | 8238cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | 8248cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_192000, 8258cca87c0SSubhransu S. Prusty .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 8268cca87c0SSubhransu S. Prusty SNDRV_PCM_FMTBIT_S32_LE, 8277f975a38SJeeja KP .sig_bits = 32, 8288cca87c0SSubhransu S. Prusty }, 8298cca87c0SSubhransu S. Prusty }, 830c3ae22e3SGuneshwor Singh }; 8318f35bf3fSJeeja KP 83205057001SJeeja KP /* BE CPU Dais */ 833c3ae22e3SGuneshwor Singh static struct snd_soc_dai_driver skl_platform_dai[] = { 83405057001SJeeja KP { 835b663a8c5SJeeja KP .name = "SSP0 Pin", 836b663a8c5SJeeja KP .ops = &skl_be_ssp_dai_ops, 837b663a8c5SJeeja KP .playback = { 838b663a8c5SJeeja KP .stream_name = "ssp0 Tx", 839b663a8c5SJeeja KP .channels_min = HDA_STEREO, 840b663a8c5SJeeja KP .channels_max = HDA_STEREO, 841b663a8c5SJeeja KP .rates = SNDRV_PCM_RATE_48000, 842b663a8c5SJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE, 843b663a8c5SJeeja KP }, 844b663a8c5SJeeja KP .capture = { 845b663a8c5SJeeja KP .stream_name = "ssp0 Rx", 846b663a8c5SJeeja KP .channels_min = HDA_STEREO, 847b663a8c5SJeeja KP .channels_max = HDA_STEREO, 848b663a8c5SJeeja KP .rates = SNDRV_PCM_RATE_48000, 849b663a8c5SJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE, 850b663a8c5SJeeja KP }, 851b663a8c5SJeeja KP }, 852b663a8c5SJeeja KP { 853c80fd4daSJeeja KP .name = "SSP1 Pin", 854c80fd4daSJeeja KP .ops = &skl_be_ssp_dai_ops, 855c80fd4daSJeeja KP .playback = { 856c80fd4daSJeeja KP .stream_name = "ssp1 Tx", 857c80fd4daSJeeja KP .channels_min = HDA_STEREO, 858c80fd4daSJeeja KP .channels_max = HDA_STEREO, 859c80fd4daSJeeja KP .rates = SNDRV_PCM_RATE_48000, 860c80fd4daSJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE, 861c80fd4daSJeeja KP }, 862c80fd4daSJeeja KP .capture = { 863c80fd4daSJeeja KP .stream_name = "ssp1 Rx", 864c80fd4daSJeeja KP .channels_min = HDA_STEREO, 865c80fd4daSJeeja KP .channels_max = HDA_STEREO, 866c80fd4daSJeeja KP .rates = SNDRV_PCM_RATE_48000, 867c80fd4daSJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE, 868c80fd4daSJeeja KP }, 869c80fd4daSJeeja KP }, 870c80fd4daSJeeja KP { 871fcc494afSPardha Saradhi K .name = "SSP2 Pin", 872fcc494afSPardha Saradhi K .ops = &skl_be_ssp_dai_ops, 873fcc494afSPardha Saradhi K .playback = { 874fcc494afSPardha Saradhi K .stream_name = "ssp2 Tx", 875fcc494afSPardha Saradhi K .channels_min = HDA_STEREO, 876fcc494afSPardha Saradhi K .channels_max = HDA_STEREO, 877fcc494afSPardha Saradhi K .rates = SNDRV_PCM_RATE_48000, 878fcc494afSPardha Saradhi K .formats = SNDRV_PCM_FMTBIT_S16_LE, 879fcc494afSPardha Saradhi K }, 880fcc494afSPardha Saradhi K .capture = { 881fcc494afSPardha Saradhi K .stream_name = "ssp2 Rx", 882fcc494afSPardha Saradhi K .channels_min = HDA_STEREO, 883fcc494afSPardha Saradhi K .channels_max = HDA_STEREO, 884fcc494afSPardha Saradhi K .rates = SNDRV_PCM_RATE_48000, 885fcc494afSPardha Saradhi K .formats = SNDRV_PCM_FMTBIT_S16_LE, 886fcc494afSPardha Saradhi K }, 887fcc494afSPardha Saradhi K }, 888fcc494afSPardha Saradhi K { 889fcc494afSPardha Saradhi K .name = "SSP3 Pin", 890fcc494afSPardha Saradhi K .ops = &skl_be_ssp_dai_ops, 891fcc494afSPardha Saradhi K .playback = { 892fcc494afSPardha Saradhi K .stream_name = "ssp3 Tx", 893fcc494afSPardha Saradhi K .channels_min = HDA_STEREO, 894fcc494afSPardha Saradhi K .channels_max = HDA_STEREO, 895fcc494afSPardha Saradhi K .rates = SNDRV_PCM_RATE_48000, 896fcc494afSPardha Saradhi K .formats = SNDRV_PCM_FMTBIT_S16_LE, 897fcc494afSPardha Saradhi K }, 898fcc494afSPardha Saradhi K .capture = { 899fcc494afSPardha Saradhi K .stream_name = "ssp3 Rx", 900fcc494afSPardha Saradhi K .channels_min = HDA_STEREO, 901fcc494afSPardha Saradhi K .channels_max = HDA_STEREO, 902fcc494afSPardha Saradhi K .rates = SNDRV_PCM_RATE_48000, 903fcc494afSPardha Saradhi K .formats = SNDRV_PCM_FMTBIT_S16_LE, 904fcc494afSPardha Saradhi K }, 905fcc494afSPardha Saradhi K }, 906fcc494afSPardha Saradhi K { 907fcc494afSPardha Saradhi K .name = "SSP4 Pin", 908fcc494afSPardha Saradhi K .ops = &skl_be_ssp_dai_ops, 909fcc494afSPardha Saradhi K .playback = { 910fcc494afSPardha Saradhi K .stream_name = "ssp4 Tx", 911fcc494afSPardha Saradhi K .channels_min = HDA_STEREO, 912fcc494afSPardha Saradhi K .channels_max = HDA_STEREO, 913fcc494afSPardha Saradhi K .rates = SNDRV_PCM_RATE_48000, 914fcc494afSPardha Saradhi K .formats = SNDRV_PCM_FMTBIT_S16_LE, 915fcc494afSPardha Saradhi K }, 916fcc494afSPardha Saradhi K .capture = { 917fcc494afSPardha Saradhi K .stream_name = "ssp4 Rx", 918fcc494afSPardha Saradhi K .channels_min = HDA_STEREO, 919fcc494afSPardha Saradhi K .channels_max = HDA_STEREO, 920fcc494afSPardha Saradhi K .rates = SNDRV_PCM_RATE_48000, 921fcc494afSPardha Saradhi K .formats = SNDRV_PCM_FMTBIT_S16_LE, 922fcc494afSPardha Saradhi K }, 923fcc494afSPardha Saradhi K }, 924fcc494afSPardha Saradhi K { 925fcc494afSPardha Saradhi K .name = "SSP5 Pin", 926fcc494afSPardha Saradhi K .ops = &skl_be_ssp_dai_ops, 927fcc494afSPardha Saradhi K .playback = { 928fcc494afSPardha Saradhi K .stream_name = "ssp5 Tx", 929fcc494afSPardha Saradhi K .channels_min = HDA_STEREO, 930fcc494afSPardha Saradhi K .channels_max = HDA_STEREO, 931fcc494afSPardha Saradhi K .rates = SNDRV_PCM_RATE_48000, 932fcc494afSPardha Saradhi K .formats = SNDRV_PCM_FMTBIT_S16_LE, 933fcc494afSPardha Saradhi K }, 934fcc494afSPardha Saradhi K .capture = { 935fcc494afSPardha Saradhi K .stream_name = "ssp5 Rx", 936fcc494afSPardha Saradhi K .channels_min = HDA_STEREO, 937fcc494afSPardha Saradhi K .channels_max = HDA_STEREO, 938fcc494afSPardha Saradhi K .rates = SNDRV_PCM_RATE_48000, 939fcc494afSPardha Saradhi K .formats = SNDRV_PCM_FMTBIT_S16_LE, 940fcc494afSPardha Saradhi K }, 941fcc494afSPardha Saradhi K }, 942fcc494afSPardha Saradhi K { 9438cca87c0SSubhransu S. Prusty .name = "iDisp1 Pin", 94405057001SJeeja KP .ops = &skl_link_dai_ops, 94505057001SJeeja KP .playback = { 9468cca87c0SSubhransu S. Prusty .stream_name = "iDisp1 Tx", 94705057001SJeeja KP .channels_min = HDA_STEREO, 9487e12dc87SSubhransu S. Prusty .channels_max = 8, 94905057001SJeeja KP .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000, 9508cca87c0SSubhransu S. Prusty .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | 9518cca87c0SSubhransu S. Prusty SNDRV_PCM_FMTBIT_S24_LE, 9528cca87c0SSubhransu S. Prusty }, 9538cca87c0SSubhransu S. Prusty }, 9548cca87c0SSubhransu S. Prusty { 9558cca87c0SSubhransu S. Prusty .name = "iDisp2 Pin", 9568cca87c0SSubhransu S. Prusty .ops = &skl_link_dai_ops, 9578cca87c0SSubhransu S. Prusty .playback = { 9588cca87c0SSubhransu S. Prusty .stream_name = "iDisp2 Tx", 9598cca87c0SSubhransu S. Prusty .channels_min = HDA_STEREO, 9607e12dc87SSubhransu S. Prusty .channels_max = 8, 9618cca87c0SSubhransu S. Prusty .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000| 9628cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_48000, 9638cca87c0SSubhransu S. Prusty .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | 9648cca87c0SSubhransu S. Prusty SNDRV_PCM_FMTBIT_S24_LE, 9658cca87c0SSubhransu S. Prusty }, 9668cca87c0SSubhransu S. Prusty }, 9678cca87c0SSubhransu S. Prusty { 9688cca87c0SSubhransu S. Prusty .name = "iDisp3 Pin", 9698cca87c0SSubhransu S. Prusty .ops = &skl_link_dai_ops, 9708cca87c0SSubhransu S. Prusty .playback = { 9718cca87c0SSubhransu S. Prusty .stream_name = "iDisp3 Tx", 9728cca87c0SSubhransu S. Prusty .channels_min = HDA_STEREO, 9737e12dc87SSubhransu S. Prusty .channels_max = 8, 9748cca87c0SSubhransu S. Prusty .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000| 9758cca87c0SSubhransu S. Prusty SNDRV_PCM_RATE_48000, 9768cca87c0SSubhransu S. Prusty .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | 9778cca87c0SSubhransu S. Prusty SNDRV_PCM_FMTBIT_S24_LE, 97805057001SJeeja KP }, 97905057001SJeeja KP }, 98005057001SJeeja KP { 98105057001SJeeja KP .name = "DMIC01 Pin", 98205057001SJeeja KP .ops = &skl_dmic_dai_ops, 98305057001SJeeja KP .capture = { 98405057001SJeeja KP .stream_name = "DMIC01 Rx", 9858f35bf3fSJeeja KP .channels_min = HDA_MONO, 9868f35bf3fSJeeja KP .channels_max = HDA_QUAD, 98705057001SJeeja KP .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, 98805057001SJeeja KP .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 98905057001SJeeja KP }, 99005057001SJeeja KP }, 99105057001SJeeja KP { 99266b48606SPawse, GuruprasadX .name = "DMIC16k Pin", 99366b48606SPawse, GuruprasadX .ops = &skl_dmic_dai_ops, 99466b48606SPawse, GuruprasadX .capture = { 99566b48606SPawse, GuruprasadX .stream_name = "DMIC16k Rx", 99666b48606SPawse, GuruprasadX .channels_min = HDA_MONO, 99766b48606SPawse, GuruprasadX .channels_max = HDA_QUAD, 99866b48606SPawse, GuruprasadX .rates = SNDRV_PCM_RATE_16000, 99966b48606SPawse, GuruprasadX .formats = SNDRV_PCM_FMTBIT_S16_LE, 100066b48606SPawse, GuruprasadX }, 100166b48606SPawse, GuruprasadX }, 100266b48606SPawse, GuruprasadX { 10033d178713SRakesh Ughreja .name = "Analog CPU DAI", 100405057001SJeeja KP .ops = &skl_link_dai_ops, 100505057001SJeeja KP .playback = { 10063d178713SRakesh Ughreja .stream_name = "Analog CPU Playback", 10073d178713SRakesh Ughreja .channels_min = HDA_MONO, 10083d178713SRakesh Ughreja .channels_max = HDA_MAX, 10093d178713SRakesh Ughreja .rates = SNDRV_PCM_RATE_8000_192000, 10103d178713SRakesh Ughreja .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 10113d178713SRakesh Ughreja SNDRV_PCM_FMTBIT_S32_LE, 101205057001SJeeja KP }, 101305057001SJeeja KP .capture = { 10143d178713SRakesh Ughreja .stream_name = "Analog CPU Capture", 10153d178713SRakesh Ughreja .channels_min = HDA_MONO, 10163d178713SRakesh Ughreja .channels_max = HDA_MAX, 10173d178713SRakesh Ughreja .rates = SNDRV_PCM_RATE_8000_192000, 10183d178713SRakesh Ughreja .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 10193d178713SRakesh Ughreja SNDRV_PCM_FMTBIT_S32_LE, 10203d178713SRakesh Ughreja }, 10213d178713SRakesh Ughreja }, 10223d178713SRakesh Ughreja { 10233d178713SRakesh Ughreja .name = "Alt Analog CPU DAI", 10243d178713SRakesh Ughreja .ops = &skl_link_dai_ops, 10253d178713SRakesh Ughreja .playback = { 10263d178713SRakesh Ughreja .stream_name = "Alt Analog CPU Playback", 10273d178713SRakesh Ughreja .channels_min = HDA_MONO, 10283d178713SRakesh Ughreja .channels_max = HDA_MAX, 10293d178713SRakesh Ughreja .rates = SNDRV_PCM_RATE_8000_192000, 10303d178713SRakesh Ughreja .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 10313d178713SRakesh Ughreja SNDRV_PCM_FMTBIT_S32_LE, 10323d178713SRakesh Ughreja }, 10333d178713SRakesh Ughreja .capture = { 10343d178713SRakesh Ughreja .stream_name = "Alt Analog CPU Capture", 10353d178713SRakesh Ughreja .channels_min = HDA_MONO, 10363d178713SRakesh Ughreja .channels_max = HDA_MAX, 10373d178713SRakesh Ughreja .rates = SNDRV_PCM_RATE_8000_192000, 10383d178713SRakesh Ughreja .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 10393d178713SRakesh Ughreja SNDRV_PCM_FMTBIT_S32_LE, 10403d178713SRakesh Ughreja }, 10413d178713SRakesh Ughreja }, 10423d178713SRakesh Ughreja { 10433d178713SRakesh Ughreja .name = "Digital CPU DAI", 10443d178713SRakesh Ughreja .ops = &skl_link_dai_ops, 10453d178713SRakesh Ughreja .playback = { 10463d178713SRakesh Ughreja .stream_name = "Digital CPU Playback", 10473d178713SRakesh Ughreja .channels_min = HDA_MONO, 10483d178713SRakesh Ughreja .channels_max = HDA_MAX, 10493d178713SRakesh Ughreja .rates = SNDRV_PCM_RATE_8000_192000, 10503d178713SRakesh Ughreja .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 10513d178713SRakesh Ughreja SNDRV_PCM_FMTBIT_S32_LE, 10523d178713SRakesh Ughreja }, 10533d178713SRakesh Ughreja .capture = { 10543d178713SRakesh Ughreja .stream_name = "Digital CPU Capture", 10553d178713SRakesh Ughreja .channels_min = HDA_MONO, 10563d178713SRakesh Ughreja .channels_max = HDA_MAX, 10573d178713SRakesh Ughreja .rates = SNDRV_PCM_RATE_8000_192000, 10583d178713SRakesh Ughreja .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 10593d178713SRakesh Ughreja SNDRV_PCM_FMTBIT_S32_LE, 106005057001SJeeja KP }, 106105057001SJeeja KP }, 1062a40e693cSJeeja KP }; 1063a40e693cSJeeja KP 1064c60b613aSLiam Girdwood int skl_dai_load(struct snd_soc_component *cmp, int index, 1065c60b613aSLiam Girdwood struct snd_soc_dai_driver *dai_drv, 1066c60b613aSLiam Girdwood struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai) 1067606e21fdSGuneshwor Singh { 1068c60b613aSLiam Girdwood dai_drv->ops = &skl_pcm_dai_ops; 1069606e21fdSGuneshwor Singh 1070606e21fdSGuneshwor Singh return 0; 1071606e21fdSGuneshwor Singh } 1072606e21fdSGuneshwor Singh 1073a40e693cSJeeja KP static int skl_platform_open(struct snd_pcm_substream *substream) 1074a40e693cSJeeja KP { 1075a40e693cSJeeja KP struct snd_soc_pcm_runtime *rtd = substream->private_data; 1076a40e693cSJeeja KP struct snd_soc_dai_link *dai_link = rtd->dai_link; 1077a40e693cSJeeja KP 1078a40e693cSJeeja KP dev_dbg(rtd->cpu_dai->dev, "In %s:%s\n", __func__, 1079a40e693cSJeeja KP dai_link->cpu_dai_name); 1080a40e693cSJeeja KP 1081a40e693cSJeeja KP snd_soc_set_runtime_hwparams(substream, &azx_pcm_hw); 1082a40e693cSJeeja KP 1083a40e693cSJeeja KP return 0; 1084a40e693cSJeeja KP } 1085a40e693cSJeeja KP 1086b663a8c5SJeeja KP static int skl_coupled_trigger(struct snd_pcm_substream *substream, 1087a40e693cSJeeja KP int cmd) 1088a40e693cSJeeja KP { 108976f56faeSRakesh Ughreja struct hdac_bus *bus = get_bus_ctx(substream); 1090a40e693cSJeeja KP struct hdac_ext_stream *stream; 1091a40e693cSJeeja KP struct snd_pcm_substream *s; 1092a40e693cSJeeja KP bool start; 1093a40e693cSJeeja KP int sbits = 0; 1094a40e693cSJeeja KP unsigned long cookie; 1095a40e693cSJeeja KP struct hdac_stream *hstr; 1096a40e693cSJeeja KP 1097a40e693cSJeeja KP stream = get_hdac_ext_stream(substream); 1098a40e693cSJeeja KP hstr = hdac_stream(stream); 1099a40e693cSJeeja KP 1100a40e693cSJeeja KP dev_dbg(bus->dev, "In %s cmd=%d\n", __func__, cmd); 1101a40e693cSJeeja KP 1102a40e693cSJeeja KP if (!hstr->prepared) 1103a40e693cSJeeja KP return -EPIPE; 1104a40e693cSJeeja KP 1105a40e693cSJeeja KP switch (cmd) { 1106a40e693cSJeeja KP case SNDRV_PCM_TRIGGER_START: 1107a40e693cSJeeja KP case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1108a40e693cSJeeja KP case SNDRV_PCM_TRIGGER_RESUME: 1109a40e693cSJeeja KP start = true; 1110a40e693cSJeeja KP break; 1111a40e693cSJeeja KP 1112a40e693cSJeeja KP case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1113a40e693cSJeeja KP case SNDRV_PCM_TRIGGER_SUSPEND: 1114a40e693cSJeeja KP case SNDRV_PCM_TRIGGER_STOP: 1115a40e693cSJeeja KP start = false; 1116a40e693cSJeeja KP break; 1117a40e693cSJeeja KP 1118a40e693cSJeeja KP default: 1119a40e693cSJeeja KP return -EINVAL; 1120a40e693cSJeeja KP } 1121a40e693cSJeeja KP 1122a40e693cSJeeja KP snd_pcm_group_for_each_entry(s, substream) { 1123a40e693cSJeeja KP if (s->pcm->card != substream->pcm->card) 1124a40e693cSJeeja KP continue; 1125a40e693cSJeeja KP stream = get_hdac_ext_stream(s); 1126a40e693cSJeeja KP sbits |= 1 << hdac_stream(stream)->index; 1127a40e693cSJeeja KP snd_pcm_trigger_done(s, substream); 1128a40e693cSJeeja KP } 1129a40e693cSJeeja KP 1130a40e693cSJeeja KP spin_lock_irqsave(&bus->reg_lock, cookie); 1131a40e693cSJeeja KP 1132a40e693cSJeeja KP /* first, set SYNC bits of corresponding streams */ 1133a40e693cSJeeja KP snd_hdac_stream_sync_trigger(hstr, true, sbits, AZX_REG_SSYNC); 1134a40e693cSJeeja KP 1135a40e693cSJeeja KP snd_pcm_group_for_each_entry(s, substream) { 1136a40e693cSJeeja KP if (s->pcm->card != substream->pcm->card) 1137a40e693cSJeeja KP continue; 1138a40e693cSJeeja KP stream = get_hdac_ext_stream(s); 1139a40e693cSJeeja KP if (start) 1140a40e693cSJeeja KP snd_hdac_stream_start(hdac_stream(stream), true); 1141a40e693cSJeeja KP else 1142a40e693cSJeeja KP snd_hdac_stream_stop(hdac_stream(stream)); 1143a40e693cSJeeja KP } 1144a40e693cSJeeja KP spin_unlock_irqrestore(&bus->reg_lock, cookie); 1145a40e693cSJeeja KP 1146a40e693cSJeeja KP snd_hdac_stream_sync(hstr, start, sbits); 1147a40e693cSJeeja KP 1148a40e693cSJeeja KP spin_lock_irqsave(&bus->reg_lock, cookie); 1149a40e693cSJeeja KP 1150a40e693cSJeeja KP /* reset SYNC bits */ 1151a40e693cSJeeja KP snd_hdac_stream_sync_trigger(hstr, false, sbits, AZX_REG_SSYNC); 1152a40e693cSJeeja KP if (start) 1153a40e693cSJeeja KP snd_hdac_stream_timecounter_init(hstr, sbits); 1154a40e693cSJeeja KP spin_unlock_irqrestore(&bus->reg_lock, cookie); 1155a40e693cSJeeja KP 1156a40e693cSJeeja KP return 0; 1157a40e693cSJeeja KP } 1158a40e693cSJeeja KP 115905057001SJeeja KP static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream, 116005057001SJeeja KP int cmd) 116105057001SJeeja KP { 116276f56faeSRakesh Ughreja struct hdac_bus *bus = get_bus_ctx(substream); 116305057001SJeeja KP 116476f56faeSRakesh Ughreja if (!bus->ppcap) 1165b663a8c5SJeeja KP return skl_coupled_trigger(substream, cmd); 1166d1730c3dSJeeja KP 1167d1730c3dSJeeja KP return 0; 116805057001SJeeja KP } 116905057001SJeeja KP 11707b96144dSJeeja KP static snd_pcm_uframes_t skl_platform_pcm_pointer 11717b96144dSJeeja KP (struct snd_pcm_substream *substream) 1172a40e693cSJeeja KP { 11737b96144dSJeeja KP struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream); 117476f56faeSRakesh Ughreja struct hdac_bus *bus = get_bus_ctx(substream); 1175a40e693cSJeeja KP unsigned int pos; 1176a40e693cSJeeja KP 1177ca590c1cSDharageswari R /* 1178ca590c1cSDharageswari R * Use DPIB for Playback stream as the periodic DMA Position-in- 1179ca590c1cSDharageswari R * Buffer Writes may be scheduled at the same time or later than 1180ca590c1cSDharageswari R * the MSI and does not guarantee to reflect the Position of the 1181ca590c1cSDharageswari R * last buffer that was transferred. Whereas DPIB register in 1182ca590c1cSDharageswari R * HAD space reflects the actual data that is transferred. 1183ca590c1cSDharageswari R * Use the position buffer for capture, as DPIB write gets 1184ca590c1cSDharageswari R * completed earlier than the actual data written to the DDR. 1185fdd85a05SHardik T Shah * 1186fdd85a05SHardik T Shah * For capture stream following workaround is required to fix the 1187fdd85a05SHardik T Shah * incorrect position reporting. 1188fdd85a05SHardik T Shah * 1189fdd85a05SHardik T Shah * 1. Wait for 20us before reading the DMA position in buffer once 1190fdd85a05SHardik T Shah * the interrupt is generated for stream completion as update happens 1191fdd85a05SHardik T Shah * on the HDA frame boundary i.e. 20.833uSec. 1192fdd85a05SHardik T Shah * 2. Read DPIB register to flush the DMA position value. This dummy 1193fdd85a05SHardik T Shah * read is required to flush DMA position value. 1194fdd85a05SHardik T Shah * 3. Read the DMA Position-in-Buffer. This value now will be equal to 1195fdd85a05SHardik T Shah * or greater than period boundary. 1196ca590c1cSDharageswari R */ 1197fdd85a05SHardik T Shah 1198fdd85a05SHardik T Shah if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 119976f56faeSRakesh Ughreja pos = readl(bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE + 1200ca590c1cSDharageswari R (AZX_REG_VS_SDXDPIB_XINTERVAL * 1201ca590c1cSDharageswari R hdac_stream(hstream)->index)); 1202fdd85a05SHardik T Shah } else { 1203fdd85a05SHardik T Shah udelay(20); 120476f56faeSRakesh Ughreja readl(bus->remap_addr + 1205fdd85a05SHardik T Shah AZX_REG_VS_SDXDPIB_XBASE + 1206fdd85a05SHardik T Shah (AZX_REG_VS_SDXDPIB_XINTERVAL * 1207fdd85a05SHardik T Shah hdac_stream(hstream)->index)); 1208a40e693cSJeeja KP pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream)); 1209fdd85a05SHardik T Shah } 1210a40e693cSJeeja KP 1211a40e693cSJeeja KP if (pos >= hdac_stream(hstream)->bufsize) 1212a40e693cSJeeja KP pos = 0; 1213a40e693cSJeeja KP 12147b96144dSJeeja KP return bytes_to_frames(substream->runtime, pos); 1215a40e693cSJeeja KP } 1216a40e693cSJeeja KP 1217a40e693cSJeeja KP static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, 1218a40e693cSJeeja KP u64 nsec) 1219a40e693cSJeeja KP { 1220a40e693cSJeeja KP struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 1221a40e693cSJeeja KP struct snd_soc_dai *codec_dai = rtd->codec_dai; 1222a40e693cSJeeja KP u64 codec_frames, codec_nsecs; 1223a40e693cSJeeja KP 1224a40e693cSJeeja KP if (!codec_dai->driver->ops->delay) 1225a40e693cSJeeja KP return nsec; 1226a40e693cSJeeja KP 1227a40e693cSJeeja KP codec_frames = codec_dai->driver->ops->delay(substream, codec_dai); 1228a40e693cSJeeja KP codec_nsecs = div_u64(codec_frames * 1000000000LL, 1229a40e693cSJeeja KP substream->runtime->rate); 1230a40e693cSJeeja KP 1231a40e693cSJeeja KP if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 1232a40e693cSJeeja KP return nsec + codec_nsecs; 1233a40e693cSJeeja KP 1234a40e693cSJeeja KP return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0; 1235a40e693cSJeeja KP } 1236a40e693cSJeeja KP 1237a40e693cSJeeja KP static int skl_get_time_info(struct snd_pcm_substream *substream, 1238a40e693cSJeeja KP struct timespec *system_ts, struct timespec *audio_ts, 1239a40e693cSJeeja KP struct snd_pcm_audio_tstamp_config *audio_tstamp_config, 1240a40e693cSJeeja KP struct snd_pcm_audio_tstamp_report *audio_tstamp_report) 1241a40e693cSJeeja KP { 1242a40e693cSJeeja KP struct hdac_ext_stream *sstream = get_hdac_ext_stream(substream); 1243a40e693cSJeeja KP struct hdac_stream *hstr = hdac_stream(sstream); 1244a40e693cSJeeja KP u64 nsec; 1245a40e693cSJeeja KP 1246a40e693cSJeeja KP if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) && 1247a40e693cSJeeja KP (audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) { 1248a40e693cSJeeja KP 1249a40e693cSJeeja KP snd_pcm_gettime(substream->runtime, system_ts); 1250a40e693cSJeeja KP 1251a40e693cSJeeja KP nsec = timecounter_read(&hstr->tc); 1252a40e693cSJeeja KP nsec = div_u64(nsec, 3); /* can be optimized */ 1253a40e693cSJeeja KP if (audio_tstamp_config->report_delay) 1254a40e693cSJeeja KP nsec = skl_adjust_codec_delay(substream, nsec); 1255a40e693cSJeeja KP 1256a40e693cSJeeja KP *audio_ts = ns_to_timespec(nsec); 1257a40e693cSJeeja KP 1258a40e693cSJeeja KP audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK; 1259a40e693cSJeeja KP audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */ 1260a40e693cSJeeja KP audio_tstamp_report->accuracy = 42; /* 24MHzWallClk == 42ns resolution */ 1261a40e693cSJeeja KP 1262a40e693cSJeeja KP } else { 1263a40e693cSJeeja KP audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT; 1264a40e693cSJeeja KP } 1265a40e693cSJeeja KP 1266a40e693cSJeeja KP return 0; 1267a40e693cSJeeja KP } 1268a40e693cSJeeja KP 1269115c7254SJulia Lawall static const struct snd_pcm_ops skl_platform_ops = { 1270a40e693cSJeeja KP .open = skl_platform_open, 1271a40e693cSJeeja KP .ioctl = snd_pcm_lib_ioctl, 1272a40e693cSJeeja KP .trigger = skl_platform_pcm_trigger, 1273a40e693cSJeeja KP .pointer = skl_platform_pcm_pointer, 1274a40e693cSJeeja KP .get_time_info = skl_get_time_info, 1275a40e693cSJeeja KP .mmap = snd_pcm_lib_default_mmap, 1276a40e693cSJeeja KP .page = snd_pcm_sgbuf_ops_page, 1277a40e693cSJeeja KP }; 1278a40e693cSJeeja KP 1279a40e693cSJeeja KP static void skl_pcm_free(struct snd_pcm *pcm) 1280a40e693cSJeeja KP { 1281a40e693cSJeeja KP snd_pcm_lib_preallocate_free_for_all(pcm); 1282a40e693cSJeeja KP } 1283a40e693cSJeeja KP 1284a40e693cSJeeja KP #define MAX_PREALLOC_SIZE (32 * 1024 * 1024) 1285a40e693cSJeeja KP 1286a40e693cSJeeja KP static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) 1287a40e693cSJeeja KP { 1288a40e693cSJeeja KP struct snd_soc_dai *dai = rtd->cpu_dai; 128976f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dai->dev); 1290a40e693cSJeeja KP struct snd_pcm *pcm = rtd->pcm; 1291a40e693cSJeeja KP unsigned int size; 129276f56faeSRakesh Ughreja struct skl *skl = bus_to_skl(bus); 1293a40e693cSJeeja KP 1294a40e693cSJeeja KP if (dai->driver->playback.channels_min || 1295a40e693cSJeeja KP dai->driver->capture.channels_min) { 1296a40e693cSJeeja KP /* buffer pre-allocation */ 1297a40e693cSJeeja KP size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; 1298a40e693cSJeeja KP if (size > MAX_PREALLOC_SIZE) 1299a40e693cSJeeja KP size = MAX_PREALLOC_SIZE; 130062961dd5STakashi Iwai snd_pcm_lib_preallocate_pages_for_all(pcm, 1301a40e693cSJeeja KP SNDRV_DMA_TYPE_DEV_SG, 1302a40e693cSJeeja KP snd_dma_pci_data(skl->pci), 1303a40e693cSJeeja KP size, MAX_PREALLOC_SIZE); 1304a40e693cSJeeja KP } 1305a40e693cSJeeja KP 130662961dd5STakashi Iwai return 0; 1307a40e693cSJeeja KP } 1308a40e693cSJeeja KP 1309b26199eaSJeeja KP static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) 1310b26199eaSJeeja KP { 1311b26199eaSJeeja KP struct skl_sst *ctx = skl->skl_sst; 131291fe0e70SJeeja KP struct skl_module_inst_id *pin_id; 131391fe0e70SJeeja KP uuid_le *uuid_mod, *uuid_tplg; 131491fe0e70SJeeja KP struct skl_module *skl_module; 1315b26199eaSJeeja KP struct uuid_module *module; 131691fe0e70SJeeja KP int i, ret = -EIO; 1317b26199eaSJeeja KP 1318b26199eaSJeeja KP uuid_mod = (uuid_le *)mconfig->guid; 1319b26199eaSJeeja KP 1320b26199eaSJeeja KP if (list_empty(&ctx->uuid_list)) { 1321b26199eaSJeeja KP dev_err(ctx->dev, "Module list is empty\n"); 1322b26199eaSJeeja KP return -EIO; 1323b26199eaSJeeja KP } 1324b26199eaSJeeja KP 1325b26199eaSJeeja KP list_for_each_entry(module, &ctx->uuid_list, list) { 1326b26199eaSJeeja KP if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { 1327b26199eaSJeeja KP mconfig->id.module_id = module->id; 1328f6fa56e2SRamesh Babu if (mconfig->module) 1329f6fa56e2SRamesh Babu mconfig->module->loadable = module->is_loadable; 133091fe0e70SJeeja KP ret = 0; 133191fe0e70SJeeja KP break; 1332b26199eaSJeeja KP } 1333b26199eaSJeeja KP } 1334b26199eaSJeeja KP 133591fe0e70SJeeja KP if (ret) 133691fe0e70SJeeja KP return ret; 133791fe0e70SJeeja KP 133891fe0e70SJeeja KP uuid_mod = &module->uuid; 133991fe0e70SJeeja KP ret = -EIO; 134091fe0e70SJeeja KP for (i = 0; i < skl->nr_modules; i++) { 134191fe0e70SJeeja KP skl_module = skl->modules[i]; 134291fe0e70SJeeja KP uuid_tplg = &skl_module->uuid; 134391fe0e70SJeeja KP if (!uuid_le_cmp(*uuid_mod, *uuid_tplg)) { 134491fe0e70SJeeja KP mconfig->module = skl_module; 134591fe0e70SJeeja KP ret = 0; 134691fe0e70SJeeja KP break; 134791fe0e70SJeeja KP } 134891fe0e70SJeeja KP } 134991fe0e70SJeeja KP if (skl->nr_modules && ret) 135091fe0e70SJeeja KP return ret; 135191fe0e70SJeeja KP 135291fe0e70SJeeja KP list_for_each_entry(module, &ctx->uuid_list, list) { 135391fe0e70SJeeja KP for (i = 0; i < MAX_IN_QUEUE; i++) { 135491fe0e70SJeeja KP pin_id = &mconfig->m_in_pin[i].id; 135591fe0e70SJeeja KP if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid)) 135691fe0e70SJeeja KP pin_id->module_id = module->id; 135791fe0e70SJeeja KP } 135891fe0e70SJeeja KP 135991fe0e70SJeeja KP for (i = 0; i < MAX_OUT_QUEUE; i++) { 136091fe0e70SJeeja KP pin_id = &mconfig->m_out_pin[i].id; 136191fe0e70SJeeja KP if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid)) 136291fe0e70SJeeja KP pin_id->module_id = module->id; 136391fe0e70SJeeja KP } 136491fe0e70SJeeja KP } 136591fe0e70SJeeja KP 136691fe0e70SJeeja KP return 0; 1367b26199eaSJeeja KP } 1368b26199eaSJeeja KP 136964cb1d0aSVinod Koul static int skl_populate_modules(struct skl *skl) 137064cb1d0aSVinod Koul { 137164cb1d0aSVinod Koul struct skl_pipeline *p; 137264cb1d0aSVinod Koul struct skl_pipe_module *m; 137364cb1d0aSVinod Koul struct snd_soc_dapm_widget *w; 137464cb1d0aSVinod Koul struct skl_module_cfg *mconfig; 1375b26199eaSJeeja KP int ret = 0; 137664cb1d0aSVinod Koul 137764cb1d0aSVinod Koul list_for_each_entry(p, &skl->ppl_list, node) { 137864cb1d0aSVinod Koul list_for_each_entry(m, &p->pipe->w_list, node) { 137964cb1d0aSVinod Koul w = m->w; 138064cb1d0aSVinod Koul mconfig = w->priv; 138164cb1d0aSVinod Koul 1382b26199eaSJeeja KP ret = skl_get_module_info(skl, mconfig); 138364cb1d0aSVinod Koul if (ret < 0) { 138464cb1d0aSVinod Koul dev_err(skl->skl_sst->dev, 1385b26199eaSJeeja KP "query module info failed\n"); 1386b26199eaSJeeja KP return ret; 138764cb1d0aSVinod Koul } 1388f7a9f772SSriram Periyasamy 1389f7a9f772SSriram Periyasamy skl_tplg_add_moduleid_in_bind_params(skl, w); 139064cb1d0aSVinod Koul } 139164cb1d0aSVinod Koul } 1392b26199eaSJeeja KP 139364cb1d0aSVinod Koul return ret; 139464cb1d0aSVinod Koul } 139564cb1d0aSVinod Koul 139656b03b4cSKuninori Morimoto static int skl_platform_soc_probe(struct snd_soc_component *component) 1397b663a8c5SJeeja KP { 139876f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(component->dev); 139976f56faeSRakesh Ughreja struct skl *skl = bus_to_skl(bus); 140078cdbbdaSVinod Koul const struct skl_dsp_ops *ops; 1401fe3f4442SDharageswari R int ret; 1402b663a8c5SJeeja KP 140356b03b4cSKuninori Morimoto pm_runtime_get_sync(component->dev); 140476f56faeSRakesh Ughreja if (bus->ppcap) { 140556b03b4cSKuninori Morimoto skl->component = component; 14065cdf6c09SVinod Koul 14075cdf6c09SVinod Koul /* init debugfs */ 14085cdf6c09SVinod Koul skl->debugfs = skl_debugfs_init(skl); 14095cdf6c09SVinod Koul 141076f56faeSRakesh Ughreja ret = skl_tplg_init(component, bus); 1411fe3f4442SDharageswari R if (ret < 0) { 141256b03b4cSKuninori Morimoto dev_err(component->dev, "Failed to init topology!\n"); 1413fe3f4442SDharageswari R return ret; 1414fe3f4442SDharageswari R } 141578cdbbdaSVinod Koul 141678cdbbdaSVinod Koul /* load the firmwares, since all is set */ 141778cdbbdaSVinod Koul ops = skl_get_dsp_ops(skl->pci->device); 141878cdbbdaSVinod Koul if (!ops) 141978cdbbdaSVinod Koul return -EIO; 142078cdbbdaSVinod Koul 1421d8747d30SPierre-Louis Bossart if (!skl->skl_sst->is_first_boot) { 142256b03b4cSKuninori Morimoto dev_err(component->dev, "DSP reports first boot done!!!\n"); 142378cdbbdaSVinod Koul return -EIO; 1424fe3f4442SDharageswari R } 1425b663a8c5SJeeja KP 1426fc9fdd61SSanyog Kale /* 1427fc9fdd61SSanyog Kale * Disable dynamic clock and power gating during firmware 1428fc9fdd61SSanyog Kale * and library download 1429fc9fdd61SSanyog Kale */ 143056b03b4cSKuninori Morimoto skl->skl_sst->enable_miscbdcge(component->dev, false); 1431fc9fdd61SSanyog Kale skl->skl_sst->clock_power_gating(component->dev, false); 1432d5cc0a1fSPardha Saradhi K 143356b03b4cSKuninori Morimoto ret = ops->init_fw(component->dev, skl->skl_sst); 143456b03b4cSKuninori Morimoto skl->skl_sst->enable_miscbdcge(component->dev, true); 1435fc9fdd61SSanyog Kale skl->skl_sst->clock_power_gating(component->dev, true); 143678cdbbdaSVinod Koul if (ret < 0) { 143756b03b4cSKuninori Morimoto dev_err(component->dev, "Failed to boot first fw: %d\n", ret); 143878cdbbdaSVinod Koul return ret; 143978cdbbdaSVinod Koul } 144064cb1d0aSVinod Koul skl_populate_modules(skl); 1441a26a3f53SPardha Saradhi K skl->skl_sst->update_d0i3c = skl_update_d0i3c; 1442cb729d80SG Kranthi skl_dsp_enable_notification(skl->skl_sst, false); 14439452314dSPradeep Tewani 14449452314dSPradeep Tewani if (skl->cfg.astate_cfg != NULL) { 14459452314dSPradeep Tewani skl_dsp_set_astate_cfg(skl->skl_sst, 14469452314dSPradeep Tewani skl->cfg.astate_cfg->count, 14479452314dSPradeep Tewani skl->cfg.astate_cfg); 14489452314dSPradeep Tewani } 144978cdbbdaSVinod Koul } 145056b03b4cSKuninori Morimoto pm_runtime_mark_last_busy(component->dev); 145156b03b4cSKuninori Morimoto pm_runtime_put_autosuspend(component->dev); 145278cdbbdaSVinod Koul 1453b663a8c5SJeeja KP return 0; 1454b663a8c5SJeeja KP } 145556b03b4cSKuninori Morimoto 14562e05ddd2SRanjani Sridharan static void skl_pcm_remove(struct snd_soc_component *component) 14572e05ddd2SRanjani Sridharan { 14582e05ddd2SRanjani Sridharan /* remove topology */ 14592e05ddd2SRanjani Sridharan snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); 14602e05ddd2SRanjani Sridharan } 14612e05ddd2SRanjani Sridharan 146256b03b4cSKuninori Morimoto static const struct snd_soc_component_driver skl_component = { 146356b03b4cSKuninori Morimoto .name = "pcm", 1464b663a8c5SJeeja KP .probe = skl_platform_soc_probe, 14652e05ddd2SRanjani Sridharan .remove = skl_pcm_remove, 1466a40e693cSJeeja KP .ops = &skl_platform_ops, 1467a40e693cSJeeja KP .pcm_new = skl_pcm_new, 1468a40e693cSJeeja KP .pcm_free = skl_pcm_free, 1469b4ed6b51SRanjani Sridharan .module_get_upon_open = 1, /* increment refcount when a pcm is opened */ 1470a40e693cSJeeja KP }; 1471a40e693cSJeeja KP 1472a40e693cSJeeja KP int skl_platform_register(struct device *dev) 1473a40e693cSJeeja KP { 1474a40e693cSJeeja KP int ret; 1475c3ae22e3SGuneshwor Singh struct snd_soc_dai_driver *dais; 1476c3ae22e3SGuneshwor Singh int num_dais = ARRAY_SIZE(skl_platform_dai); 147776f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dev); 147876f56faeSRakesh Ughreja struct skl *skl = bus_to_skl(bus); 1479b663a8c5SJeeja KP 1480b663a8c5SJeeja KP INIT_LIST_HEAD(&skl->ppl_list); 1481b8c722ddSJeeja KP INIT_LIST_HEAD(&skl->bind_list); 1482a40e693cSJeeja KP 1483c3ae22e3SGuneshwor Singh skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai), 1484c3ae22e3SGuneshwor Singh GFP_KERNEL); 1485c3ae22e3SGuneshwor Singh if (!skl->dais) { 1486c3ae22e3SGuneshwor Singh ret = -ENOMEM; 1487c3ae22e3SGuneshwor Singh goto err; 1488a40e693cSJeeja KP } 1489a40e693cSJeeja KP 1490c3ae22e3SGuneshwor Singh if (!skl->use_tplg_pcm) { 1491c3ae22e3SGuneshwor Singh dais = krealloc(skl->dais, sizeof(skl_fe_dai) + 1492c3ae22e3SGuneshwor Singh sizeof(skl_platform_dai), GFP_KERNEL); 1493c3ae22e3SGuneshwor Singh if (!dais) { 1494c3ae22e3SGuneshwor Singh ret = -ENOMEM; 1495c3ae22e3SGuneshwor Singh goto err; 1496c3ae22e3SGuneshwor Singh } 1497c3ae22e3SGuneshwor Singh 1498c3ae22e3SGuneshwor Singh skl->dais = dais; 1499c3ae22e3SGuneshwor Singh memcpy(&skl->dais[ARRAY_SIZE(skl_platform_dai)], skl_fe_dai, 1500c3ae22e3SGuneshwor Singh sizeof(skl_fe_dai)); 1501c3ae22e3SGuneshwor Singh num_dais += ARRAY_SIZE(skl_fe_dai); 1502c3ae22e3SGuneshwor Singh } 1503c3ae22e3SGuneshwor Singh 150456b03b4cSKuninori Morimoto ret = devm_snd_soc_register_component(dev, &skl_component, 1505c3ae22e3SGuneshwor Singh skl->dais, num_dais); 150656b03b4cSKuninori Morimoto if (ret) 1507c3ae22e3SGuneshwor Singh dev_err(dev, "soc component registration failed %d\n", ret); 1508c3ae22e3SGuneshwor Singh err: 1509a40e693cSJeeja KP return ret; 1510a40e693cSJeeja KP } 1511a40e693cSJeeja KP 1512a40e693cSJeeja KP int skl_platform_unregister(struct device *dev) 1513a40e693cSJeeja KP { 151476f56faeSRakesh Ughreja struct hdac_bus *bus = dev_get_drvdata(dev); 151576f56faeSRakesh Ughreja struct skl *skl = bus_to_skl(bus); 1516550b349aSDan Carpenter struct skl_module_deferred_bind *modules, *tmp; 1517b8c722ddSJeeja KP 1518b8c722ddSJeeja KP if (!list_empty(&skl->bind_list)) { 1519550b349aSDan Carpenter list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { 1520b8c722ddSJeeja KP list_del(&modules->node); 1521b8c722ddSJeeja KP kfree(modules); 1522b8c722ddSJeeja KP } 1523b8c722ddSJeeja KP } 1524b8c722ddSJeeja KP 1525c3ae22e3SGuneshwor Singh kfree(skl->dais); 1526c3ae22e3SGuneshwor Singh 1527a40e693cSJeeja KP return 0; 1528a40e693cSJeeja KP } 1529