2019-03-29 14:12:17 +08:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
2018-10-16 02:05:43 +08:00
|
|
|
From: Ramesh Babu <ramesh.babu@intel.com>
|
|
|
|
Date: Mon, 23 May 2016 11:39:19 +0530
|
2019-03-29 14:12:17 +08:00
|
|
|
Subject: [PATCH] ASoC: Intel: Skylake: add support for spib mode
|
2018-10-16 02:05:43 +08:00
|
|
|
|
|
|
|
Skylake audio controller sports SPIB capability, which can be
|
|
|
|
used to inform position of appl pointer to host DMA controller.
|
|
|
|
When SPIB mode is enabled, driver could write the appl pointer
|
|
|
|
position in SPIB register. Host DMA will make sure it won't
|
|
|
|
read/write beyond bytes specified in SPIB register.
|
|
|
|
|
|
|
|
SPIB mode will be useful in low power use cases, where DSP could
|
|
|
|
pre-fetch large buffers to avoid frequent wakes due to
|
|
|
|
interrupts.
|
|
|
|
|
|
|
|
Skylake driver makes use of no_rewind flag and appl_ptr_update
|
|
|
|
callback to enable and update SPIB register respectively.
|
|
|
|
|
|
|
|
Signed-off-by: Ramesh Babu <ramesh.babu@intel.com>
|
|
|
|
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
|
|
|
|
---
|
|
|
|
sound/soc/intel/skylake/skl-pcm.c | 46 +++++++++++++++++++++++++++++--
|
|
|
|
1 file changed, 44 insertions(+), 2 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
|
2020-10-27 02:14:06 +08:00
|
|
|
index c82ab7071c15..97617b9ab5a0 100644
|
2018-10-16 02:05:43 +08:00
|
|
|
--- a/sound/soc/intel/skylake/skl-pcm.c
|
|
|
|
+++ b/sound/soc/intel/skylake/skl-pcm.c
|
|
|
|
@@ -46,7 +46,8 @@ static const struct snd_pcm_hardware azx_pcm_hw = {
|
|
|
|
SNDRV_PCM_INFO_SYNC_START |
|
|
|
|
SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
|
|
|
|
SNDRV_PCM_INFO_HAS_LINK_ATIME |
|
|
|
|
- SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
|
|
|
|
+ SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
|
|
|
|
+ SNDRV_PCM_INFO_NO_STATUS_MMAP),
|
|
|
|
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
|
|
|
SNDRV_PCM_FMTBIT_S32_LE |
|
|
|
|
SNDRV_PCM_FMTBIT_S24_LE,
|
|
|
|
@@ -154,6 +155,7 @@ int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params)
|
|
|
|
unsigned int format_val;
|
|
|
|
struct hdac_stream *hstream;
|
|
|
|
struct hdac_ext_stream *stream;
|
|
|
|
+ struct snd_pcm_runtime *runtime;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
hstream = snd_hdac_get_stream(bus, params->stream,
|
|
|
|
@@ -179,6 +181,11 @@ int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params)
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
+ runtime = hdac_stream(stream)->substream->runtime;
|
|
|
|
+ /* enable SPIB if no_rewinds flag is set */
|
|
|
|
+ if (runtime->no_rewinds)
|
|
|
|
+ snd_hdac_ext_stream_spbcap_enable(ebus, 1, hstream->index);
|
|
|
|
+
|
|
|
|
hdac_stream(stream)->prepared = 1;
|
|
|
|
|
|
|
|
return 0;
|
2019-05-23 10:08:33 +08:00
|
|
|
@@ -394,6 +401,8 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream,
|
2018-10-16 02:05:43 +08:00
|
|
|
{
|
|
|
|
struct hdac_bus *bus = dev_get_drvdata(dai->dev);
|
|
|
|
struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
|
|
|
|
+ struct hdac_stream *hstream = hdac_stream(stream);
|
|
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
|
|
struct skl *skl = get_skl_ctx(dai->dev);
|
|
|
|
struct skl_module_cfg *mconfig;
|
|
|
|
int ret;
|
2019-05-23 10:08:33 +08:00
|
|
|
@@ -402,6 +411,10 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream,
|
2018-10-16 02:05:43 +08:00
|
|
|
|
|
|
|
mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
|
|
|
|
|
|
|
|
+ if (runtime->no_rewinds) {
|
|
|
|
+ snd_hdac_ext_stream_set_spib(ebus, stream, 0);
|
|
|
|
+ snd_hdac_ext_stream_spbcap_enable(ebus, 0, hstream->index);
|
|
|
|
+ }
|
|
|
|
if (mconfig) {
|
|
|
|
ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe);
|
|
|
|
if (ret < 0)
|
2019-05-23 10:08:33 +08:00
|
|
|
@@ -483,6 +496,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
|
2018-10-16 02:05:43 +08:00
|
|
|
struct skl_module_cfg *mconfig;
|
|
|
|
struct hdac_bus *bus = get_bus_ctx(substream);
|
|
|
|
struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
|
|
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
|
|
struct snd_soc_dapm_widget *w;
|
|
|
|
int ret;
|
|
|
|
|
2019-05-23 10:08:33 +08:00
|
|
|
@@ -508,8 +522,10 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
|
2018-10-16 02:05:43 +08:00
|
|
|
snd_hdac_ext_stream_set_dpibr(bus, stream,
|
|
|
|
stream->lpib);
|
|
|
|
snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
|
|
|
|
+ if (runtime->no_rewinds)
|
|
|
|
+ snd_hdac_ext_stream_set_spib(ebus,
|
|
|
|
+ stream, stream->spib);
|
|
|
|
}
|
|
|
|
-
|
|
|
|
case SNDRV_PCM_TRIGGER_START:
|
|
|
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
|
|
|
/*
|
2019-05-23 10:08:33 +08:00
|
|
|
@@ -1501,6 +1517,31 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
|
2018-10-16 02:05:43 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
+/* update SPIB register with appl position */
|
|
|
|
+static int skl_platform_ack(struct snd_pcm_substream *substream)
|
|
|
|
+{
|
|
|
|
+ struct hdac_ext_bus *ebus = get_bus_ctx(substream);
|
|
|
|
+ struct hdac_ext_stream *estream = get_hdac_ext_stream(substream);
|
|
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
|
|
+ ssize_t appl_pos, buf_size;
|
|
|
|
+ u32 spib;
|
|
|
|
+
|
|
|
|
+ /* Use spib mode only if no_rewind mode is set */
|
|
|
|
+ if (runtime->no_rewinds == 0)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ appl_pos = frames_to_bytes(runtime, runtime->control->appl_ptr);
|
|
|
|
+ buf_size = frames_to_bytes(runtime, runtime->buffer_size);
|
|
|
|
+
|
|
|
|
+ spib = appl_pos % buf_size;
|
|
|
|
+
|
|
|
|
+ /* Allowable value for SPIB is 1 byte to max buffer size */
|
|
|
|
+ spib = (spib == 0) ? buf_size : spib;
|
|
|
|
+ snd_hdac_ext_stream_set_spib(ebus, estream, spib);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static snd_pcm_uframes_t skl_platform_pcm_pointer
|
|
|
|
(struct snd_pcm_substream *substream)
|
|
|
|
{
|
2019-05-23 10:08:33 +08:00
|
|
|
@@ -1608,6 +1649,7 @@ static const struct snd_pcm_ops skl_platform_ops = {
|
2018-10-16 02:05:43 +08:00
|
|
|
.get_time_info = skl_get_time_info,
|
|
|
|
.mmap = snd_pcm_lib_default_mmap,
|
|
|
|
.page = snd_pcm_sgbuf_ops_page,
|
|
|
|
+ .ack = skl_platform_ack,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void skl_pcm_free(struct snd_pcm *pcm)
|
|
|
|
--
|
2019-04-08 18:08:36 +08:00
|
|
|
https://clearlinux.org
|
2018-10-16 02:05:43 +08:00
|
|
|
|