ASoC: SOF: Intel: Account for compress streams when servicing IRQs
authorCezary Rojewski <cezary.rojewski@intel.com>
Tue, 18 Feb 2020 14:39:18 +0000 (15:39 +0100)
committerMark Brown <broonie@kernel.org>
Tue, 18 Feb 2020 21:52:06 +0000 (21:52 +0000)
Update stream irq handler definition to correctly set hdac_stream
current position when servicing stream interrupts for compress streams.

Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200218143924.10565-4-cezary.rojewski@intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/hdaudio.h
sound/soc/sof/intel/hda-stream.c

index d4299e1..affedc2 100644 (file)
@@ -513,6 +513,7 @@ struct hdac_stream {
        struct snd_pcm_substream *substream;    /* assigned substream,
                                                 * set in PCM open
                                                 */
+       struct snd_compr_stream *cstream;
        unsigned int format_val;        /* format value to be set in the
                                         * controller and the codec
                                         */
@@ -527,6 +528,7 @@ struct hdac_stream {
        bool locked:1;
        bool stripe:1;                  /* apply stripe control */
 
+       u64 curr_pos;
        /* timestamp */
        unsigned long start_wallclk;    /* start + minimum wallclk */
        unsigned long period_wallclk;   /* wallclk for period */
index c0ab9bb..7daa913 100644 (file)
@@ -571,6 +571,22 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev)
        return ret;
 }
 
+static void
+hda_dsp_set_bytes_transferred(struct hdac_stream *hstream, u64 buffer_size)
+{
+       u64 prev_pos, pos, num_bytes;
+
+       div64_u64_rem(hstream->curr_pos, buffer_size, &prev_pos);
+       pos = snd_hdac_stream_get_pos_posbuf(hstream);
+
+       if (pos < prev_pos)
+               num_bytes = (buffer_size - prev_pos) +  pos;
+       else
+               num_bytes = pos - prev_pos;
+
+       hstream->curr_pos += num_bytes;
+}
+
 static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status)
 {
        struct sof_intel_hda_dev *sof_hda = bus_to_sof_hda(bus);
@@ -588,14 +604,19 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status)
                        snd_hdac_stream_writeb(s, SD_STS, sd_status);
 
                        active = true;
-                       if (!s->substream ||
+                       if ((!s->substream && !s->cstream) ||
                            !s->running ||
                            (sd_status & SOF_HDA_CL_DMA_SD_INT_COMPLETE) == 0)
                                continue;
 
                        /* Inform ALSA only in case not do that with IPC */
-                       if (sof_hda->no_ipc_position)
+                       if (s->substream && sof_hda->no_ipc_position) {
                                snd_sof_pcm_period_elapsed(s->substream);
+                       } else if (s->cstream) {
+                               hda_dsp_set_bytes_transferred(s,
+                                       s->cstream->runtime->buffer_size);
+                               snd_compr_fragment_elapsed(s->cstream);
+                       }
                }
        }