]> www.infradead.org Git - users/hch/misc.git/commitdiff
ALSA: compress_offload: Add 64-bit safe timestamp infrastructure
authorJoris Verhaegen <verhaegen@google.com>
Fri, 5 Sep 2025 09:12:54 +0000 (10:12 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 8 Sep 2025 07:33:24 +0000 (09:33 +0200)
The copied_total field in struct snd_compr_tstamp is a 32-bit
value that can overflow on long-running high-bitrate streams,
leading to incorrect calculations for buffer availablility.

This patch adds a 64-bit safe timestamping mechanism.
A new UAPI struct, snd_compr_tstamp64, is added which uses 64-bit
types for byte counters. The relevant ops structures across the
ASoC and core compress code are updated to use this new struct.
ASoC drivers are updated to use u64 counters.

Internal timestamps being u64 now, a compatibility function is added
to convert the 64-bit timestamp back to the 32-bit format for legacy
ioctl callers.

Reviewed-by: Miller Liang <millerliang@google.com>
Tested-by: Joris Verhaegen <verhaegen@google.com>
Signed-off-by: Joris Verhaegen <verhaegen@google.com>
Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Acked-by: Mark Brown <broonie@kernel.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20250905091301.2711705-2-verhaegen@google.com
24 files changed:
include/sound/compress_driver.h
include/sound/soc-component.h
include/sound/soc-dai.h
include/uapi/sound/compress_offload.h
sound/core/compress_offload.c
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wm_adsp.h
sound/soc/intel/atom/sst-mfld-platform-compress.c
sound/soc/intel/atom/sst-mfld-platform.h
sound/soc/intel/atom/sst/sst_drv_interface.c
sound/soc/intel/avs/probes.c
sound/soc/qcom/qdsp6/q6apm-dai.c
sound/soc/qcom/qdsp6/q6asm-dai.c
sound/soc/soc-component.c
sound/soc/soc-compress.c
sound/soc/soc-dai.c
sound/soc/sof/amd/acp-probes.c
sound/soc/sof/compress.c
sound/soc/sof/intel/hda-probes.c
sound/soc/sof/sof-client-probes.c
sound/soc/sof/sof-client-probes.h
sound/soc/sprd/sprd-pcm-compress.c
sound/soc/sprd/sprd-pcm-dma.h
sound/soc/uniphier/aio-compress.c

index b55c9eeb2b54caf6c7644f14cfc36079423a0cff..9e3d801e45ecd5183e5217d4240a3726db992cd2 100644 (file)
@@ -161,7 +161,7 @@ struct snd_compr_ops {
                        struct snd_compr_metadata *metadata);
        int (*trigger)(struct snd_compr_stream *stream, int cmd);
        int (*pointer)(struct snd_compr_stream *stream,
-                       struct snd_compr_tstamp *tstamp);
+                      struct snd_compr_tstamp64 *tstamp);
        int (*copy)(struct snd_compr_stream *stream, char __user *buf,
                       size_t count);
        int (*mmap)(struct snd_compr_stream *stream,
index 2caa807c6249c4d7c7fb16b95c6deab665d54159..cdb536c4ab2be7679edae7718d53a7cd2c9e423c 100644 (file)
@@ -47,7 +47,7 @@ struct snd_compress_ops {
                       struct snd_compr_stream *stream, int cmd);
        int (*pointer)(struct snd_soc_component *component,
                       struct snd_compr_stream *stream,
-                      struct snd_compr_tstamp *tstamp);
+                      struct snd_compr_tstamp64 *tstamp);
        int (*copy)(struct snd_soc_component *component,
                    struct snd_compr_stream *stream, char __user *buf,
                    size_t count);
@@ -498,7 +498,7 @@ int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream,
                                           struct snd_compr_codec_caps *codec);
 int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes);
 int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream,
-                                   struct snd_compr_tstamp *tstamp);
+                                   struct snd_compr_tstamp64 *tstamp);
 int snd_soc_component_compr_copy(struct snd_compr_stream *cstream,
                                 char __user *buf, size_t count);
 int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream,
index 166c29557e9d7c89720d418ec0cc5610207c4b43..224396927aef35f66c653bb4d57127f7fecd6741 100644 (file)
@@ -256,7 +256,7 @@ int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
                          size_t bytes);
 int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
                              struct snd_compr_stream *cstream,
-                             struct snd_compr_tstamp *tstamp);
+                             struct snd_compr_tstamp64 *tstamp);
 int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
                                   struct snd_compr_stream *cstream,
                                   struct snd_compr_metadata *metadata);
@@ -383,8 +383,9 @@ struct snd_soc_cdai_ops {
                        struct snd_compr_metadata *, struct snd_soc_dai *);
        int (*trigger)(struct snd_compr_stream *, int,
                        struct snd_soc_dai *);
-       int (*pointer)(struct snd_compr_stream *,
-                       struct snd_compr_tstamp *, struct snd_soc_dai *);
+       int (*pointer)(struct snd_compr_stream *stream,
+                      struct snd_compr_tstamp64 *tstamp,
+                      struct snd_soc_dai *dai);
        int (*ack)(struct snd_compr_stream *, size_t,
                        struct snd_soc_dai *);
 };
index d62eb93af0edb7d1e5fb77941ca7c7376e9912b4..abd0ea3f86eedcc5f79218f836b2967919fc374b 100644 (file)
@@ -56,6 +56,25 @@ struct snd_compr_tstamp {
        __u32 sampling_rate;
 } __attribute__((packed, aligned(4)));
 
+/**
+ * struct snd_compr_tstamp64 - timestamp descriptor with fields in 64 bit
+ * @byte_offset: Byte offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
+ * @pcm_frames: Frames decoded or encoded by DSP. This field will evolve by
+ *     large steps and should only be used to monitor encoding/decoding
+ *     progress. It shall not be used for timing estimates.
+ * @pcm_io_frames: Frames rendered or received by DSP into a mixer or an audio
+ * output/input. This field should be used for A/V sync or time estimates.
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp64 {
+       __u32 byte_offset;
+       __u64 copied_total;
+       __u64 pcm_frames;
+       __u64 pcm_io_frames;
+       __u32 sampling_rate;
+} __attribute__((packed, aligned(4)));
+
 /**
  * struct snd_compr_avail - avail descriptor
  * @avail: Number of bytes available in ring buffer for writing/reading
index a66f258cafaa877dfd0e40958499bd360f877a17..d3164aa07158dc786d8acf3384bb81511c43964e 100644 (file)
@@ -176,14 +176,25 @@ static int snd_compr_free(struct inode *inode, struct file *f)
        return 0;
 }
 
+static void
+snd_compr_tstamp32_from_64(struct snd_compr_tstamp *tstamp32,
+                          const struct snd_compr_tstamp64 *tstamp64)
+{
+       tstamp32->byte_offset = tstamp64->byte_offset;
+       tstamp32->copied_total = (u32)tstamp64->copied_total;
+       tstamp32->pcm_frames = (u32)tstamp64->pcm_frames;
+       tstamp32->pcm_io_frames = (u32)tstamp64->pcm_io_frames;
+       tstamp32->sampling_rate = tstamp64->sampling_rate;
+}
+
 static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
-               struct snd_compr_tstamp *tstamp)
+                                  struct snd_compr_tstamp64 *tstamp)
 {
        if (!stream->ops->pointer)
                return -ENOTSUPP;
        stream->ops->pointer(stream, tstamp);
-       pr_debug("dsp consumed till %d total %d bytes\n",
-               tstamp->byte_offset, tstamp->copied_total);
+       pr_debug("dsp consumed till %u total %llu bytes\n", tstamp->byte_offset,
+                tstamp->copied_total);
        if (stream->direction == SND_COMPRESS_PLAYBACK)
                stream->runtime->total_bytes_transferred = tstamp->copied_total;
        else
@@ -194,8 +205,11 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
 static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
                struct snd_compr_avail *avail)
 {
+       struct snd_compr_tstamp64 tstamp64 = { 0 };
+
        memset(avail, 0, sizeof(*avail));
-       snd_compr_update_tstamp(stream, &avail->tstamp);
+       snd_compr_update_tstamp(stream, &tstamp64);
+       snd_compr_tstamp32_from_64(&avail->tstamp, &tstamp64);
        /* Still need to return avail even if tstamp can't be filled in */
 
        if (stream->runtime->total_bytes_available == 0 &&
@@ -204,9 +218,9 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
                pr_debug("detected init and someone forgot to do a write\n");
                return stream->runtime->buffer_size;
        }
-       pr_debug("app wrote %lld, DSP consumed %lld\n",
-                       stream->runtime->total_bytes_available,
-                       stream->runtime->total_bytes_transferred);
+       pr_debug("app wrote %llu, DSP consumed %llu\n",
+                stream->runtime->total_bytes_available,
+                stream->runtime->total_bytes_transferred);
        if (stream->runtime->total_bytes_available ==
                                stream->runtime->total_bytes_transferred) {
                if (stream->direction == SND_COMPRESS_PLAYBACK) {
@@ -223,7 +237,7 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
        if (stream->direction == SND_COMPRESS_PLAYBACK)
                avail->avail = stream->runtime->buffer_size - avail->avail;
 
-       pr_debug("ret avail as %lld\n", avail->avail);
+       pr_debug("ret avail as %llu\n", avail->avail);
        return avail->avail;
 }
 
@@ -274,8 +288,7 @@ static int snd_compr_write_data(struct snd_compr_stream *stream,
                      (app_pointer * runtime->buffer_size);
 
        dstn = runtime->buffer + app_pointer;
-       pr_debug("copying %ld at %lld\n",
-                       (unsigned long)count, app_pointer);
+       pr_debug("copying %lu at %llu\n", (unsigned long)count, app_pointer);
        if (count < runtime->buffer_size - app_pointer) {
                if (copy_from_user(dstn, buf, count))
                        return -EFAULT;
@@ -318,7 +331,7 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
        }
 
        avail = snd_compr_get_avail(stream);
-       pr_debug("avail returned %ld\n", (unsigned long)avail);
+       pr_debug("avail returned %lu\n", (unsigned long)avail);
        /* calculate how much we can write to buffer */
        if (avail > count)
                avail = count;
@@ -374,7 +387,7 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf,
        }
 
        avail = snd_compr_get_avail(stream);
-       pr_debug("avail returned %ld\n", (unsigned long)avail);
+       pr_debug("avail returned %lu\n", (unsigned long)avail);
        /* calculate how much we can read from buffer */
        if (avail > count)
                avail = count;
@@ -443,7 +456,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait)
 #endif
 
        avail = snd_compr_get_avail(stream);
-       pr_debug("avail is %ld\n", (unsigned long)avail);
+       pr_debug("avail is %lu\n", (unsigned long)avail);
        /* check if we have at least one fragment to fill */
        switch (runtime->state) {
        case SNDRV_PCM_STATE_DRAINING:
@@ -726,13 +739,18 @@ snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg)
 static inline int
 snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
 {
-       struct snd_compr_tstamp tstamp = {0};
+       struct snd_compr_tstamp64 tstamp64 = { 0 };
+       struct snd_compr_tstamp tstamp32 = { 0 };
        int ret;
 
-       ret = snd_compr_update_tstamp(stream, &tstamp);
-       if (ret == 0)
+       ret = snd_compr_update_tstamp(stream, &tstamp64);
+       if (ret == 0) {
+               snd_compr_tstamp32_from_64(&tstamp32, &tstamp64);
                ret = copy_to_user((struct snd_compr_tstamp __user *)arg,
-                       &tstamp, sizeof(tstamp)) ? -EFAULT : 0;
+                                  &tstamp32, sizeof(tstamp32)) ?
+                             -EFAULT :
+                             0;
+       }
        return ret;
 }
 
index 8a1d5cc75d6c23bea3c41738318bcf6ec6aed30c..f197034fd594fa1c8b16b0bb7cc069dfdf9091f2 100644 (file)
@@ -173,7 +173,7 @@ struct wm_adsp_compr {
        struct snd_compressed_buffer size;
 
        u32 *raw_buf;
-       unsigned int copied_total;
+       u64 copied_total;
 
        unsigned int sample_rate;
 
@@ -1860,7 +1860,7 @@ static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
 
 int wm_adsp_compr_pointer(struct snd_soc_component *component,
                          struct snd_compr_stream *stream,
-                         struct snd_compr_tstamp *tstamp)
+                         struct snd_compr_tstamp64 *tstamp)
 {
        struct wm_adsp_compr *compr = stream->runtime->private_data;
        struct wm_adsp *dsp = compr->dsp;
index 25210d404bf14147bcac4d39c134ca0ae57571fe..8035fda71f8db45bc9df7cb552c161b26b1b3d75 100644 (file)
@@ -131,7 +131,7 @@ int wm_adsp_compr_trigger(struct snd_soc_component *component,
 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp);
 int wm_adsp_compr_pointer(struct snd_soc_component *component,
                          struct snd_compr_stream *stream,
-                         struct snd_compr_tstamp *tstamp);
+                         struct snd_compr_tstamp64 *tstamp);
 int wm_adsp_compr_copy(struct snd_soc_component *component,
                       struct snd_compr_stream *stream,
                       char __user *buf, size_t count);
index 89c9c5ad6b2193edf0de8460bf413728af7fdd66..9dfb0a814b941ee24453e0aa703f7218b5976f57 100644 (file)
@@ -18,6 +18,7 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/compress_driver.h>
+#include <asm/div64.h>
 #include "sst-mfld-platform.h"
 
 /* compress stream operations */
@@ -202,15 +203,16 @@ static int sst_platform_compr_trigger(struct snd_soc_component *component,
 
 static int sst_platform_compr_pointer(struct snd_soc_component *component,
                                      struct snd_compr_stream *cstream,
-                                     struct snd_compr_tstamp *tstamp)
+                                     struct snd_compr_tstamp64 *tstamp)
 {
        struct sst_runtime_stream *stream;
+       u64 temp_copied_total = tstamp->copied_total;
 
-       stream  = cstream->runtime->private_data;
+       stream = cstream->runtime->private_data;
        stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
-       tstamp->byte_offset = tstamp->copied_total %
-                                (u32)cstream->runtime->buffer_size;
-       pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
+       tstamp->byte_offset =
+               do_div(temp_copied_total, cstream->runtime->buffer_size);
+       pr_debug("calc bytes offset/copied bytes as %u\n", tstamp->byte_offset);
        return 0;
 }
 
index 8b5777d3229a7c11f142cba10e4d4264f49a4f99..a0e33f7f01c5172b960be1434309536f09942de9 100644 (file)
@@ -105,7 +105,7 @@ struct compress_sst_ops {
        int (*stream_pause_release)(struct device *dev, unsigned int str_id);
 
        int (*tstamp)(struct device *dev, unsigned int str_id,
-                       struct snd_compr_tstamp *tstamp);
+                     struct snd_compr_tstamp64 *tstamp);
        int (*ack)(struct device *dev, unsigned int str_id,
                        unsigned long bytes);
        int (*close)(struct device *dev, unsigned int str_id);
index 8bb27f86eb65368958b10a4e8e48e1eb3aac57e3..2646c4632ca1cad6ab42854fd80b2cbd448fd3fe 100644 (file)
@@ -326,7 +326,7 @@ static int sst_cdev_stream_partial_drain(struct device *dev,
 }
 
 static int sst_cdev_tstamp(struct device *dev, unsigned int str_id,
-               struct snd_compr_tstamp *tstamp)
+                          struct snd_compr_tstamp64 *tstamp)
 {
        struct snd_sst_tstamp fw_tstamp = {0,};
        struct stream_info *stream;
@@ -349,10 +349,11 @@ static int sst_cdev_tstamp(struct device *dev, unsigned int str_id,
                        (u64)stream->num_ch * SST_GET_BYTES_PER_SAMPLE(24));
        tstamp->sampling_rate = fw_tstamp.sampling_frequency;
 
-       dev_dbg(dev, "PCM  = %u\n", tstamp->pcm_io_frames);
-       dev_dbg(dev, "Ptr Query on strid = %d  copied_total %d, decodec %d\n",
+       dev_dbg(dev, "PCM  = %llu\n", tstamp->pcm_io_frames);
+       dev_dbg(dev,
+               "Ptr Query on strid = %d  copied_total %llu, decodec %llu\n",
                str_id, tstamp->copied_total, tstamp->pcm_frames);
-       dev_dbg(dev, "rendered %d\n", tstamp->pcm_io_frames);
+       dev_dbg(dev, "rendered %llu\n", tstamp->pcm_io_frames);
 
        return 0;
 }
index a42736b9aa55b7b41fce0011898d112b66d31c8e..b5b4b0754b716a2762964cc83c8eaffd1dd2d21f 100644 (file)
@@ -213,7 +213,7 @@ static int avs_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd,
 }
 
 static int avs_probe_compr_pointer(struct snd_compr_stream *cstream,
-                                  struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai)
+                                  struct snd_compr_tstamp64 *tstamp, struct snd_soc_dai *dai)
 {
        struct hdac_ext_stream *host_stream = avs_compr_get_host_stream(cstream);
        struct snd_soc_pcm_stream *pstream;
index 2cd522108221a2ec5c7bbbb63f7d4ae4f8001cf6..09da26f712a6ada97196090d760b91bc2dc2a732 100644 (file)
@@ -11,6 +11,7 @@
 #include <sound/soc-dapm.h>
 #include <linux/spinlock.h>
 #include <sound/pcm.h>
+#include <asm/div64.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <sound/pcm_params.h>
@@ -65,9 +66,9 @@ struct q6apm_dai_rtd {
        unsigned int pcm_size;
        unsigned int pcm_count;
        unsigned int periods;
-       unsigned int bytes_sent;
-       unsigned int bytes_received;
-       unsigned int copied_total;
+       uint64_t bytes_sent;
+       uint64_t bytes_received;
+       uint64_t copied_total;
        uint16_t bits_per_sample;
        snd_pcm_uframes_t queue_ptr;
        bool next_track;
@@ -575,15 +576,17 @@ static int q6apm_dai_compr_get_codec_caps(struct snd_soc_component *component,
 
 static int q6apm_dai_compr_pointer(struct snd_soc_component *component,
                                   struct snd_compr_stream *stream,
-                                  struct snd_compr_tstamp *tstamp)
+                                  struct snd_compr_tstamp64 *tstamp)
 {
        struct snd_compr_runtime *runtime = stream->runtime;
        struct q6apm_dai_rtd *prtd = runtime->private_data;
        unsigned long flags;
+       uint64_t temp_copied_total;
 
        spin_lock_irqsave(&prtd->lock, flags);
        tstamp->copied_total = prtd->copied_total;
-       tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
+       temp_copied_total = tstamp->copied_total;
+       tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size);
        spin_unlock_irqrestore(&prtd->lock, flags);
 
        return 0;
@@ -760,21 +763,24 @@ static int q6apm_compr_copy(struct snd_soc_component *component,
        size_t copy;
        u32 wflags = 0;
        u32 app_pointer;
-       u32 bytes_received;
+       uint64_t bytes_received;
+       uint64_t temp_bytes_received;
        uint32_t bytes_to_write;
-       int avail, bytes_in_flight = 0;
+       uint64_t avail, bytes_in_flight = 0;
 
        bytes_received = prtd->bytes_received;
+       temp_bytes_received = bytes_received;
 
        /**
         * Make sure that next track data pointer is aligned at 32 bit boundary
         * This is a Mandatory requirement from DSP data buffers alignment
         */
-       if (prtd->next_track)
+       if (prtd->next_track) {
                bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count);
+               temp_bytes_received = bytes_received;
+       }
 
-       app_pointer = bytes_received/prtd->pcm_size;
-       app_pointer = bytes_received -  (app_pointer * prtd->pcm_size);
+       app_pointer = do_div(temp_bytes_received, prtd->pcm_size);
        dstn = prtd->dma_buffer.area + app_pointer;
 
        if (count < prtd->pcm_size - app_pointer) {
index a400c9a31fead57608d46ed6125edf91bebcd995..b616ce316d2f137fe3ea1346281e1274576f7d1a 100644 (file)
@@ -14,6 +14,7 @@
 #include <sound/pcm.h>
 #include <linux/spinlock.h>
 #include <sound/compress_driver.h>
+#include <asm/div64.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <sound/pcm_params.h>
@@ -59,9 +60,9 @@ struct q6asm_dai_rtd {
        unsigned int pcm_count;
        unsigned int pcm_irq_pos;       /* IRQ position */
        unsigned int periods;
-       unsigned int bytes_sent;
-       unsigned int bytes_received;
-       unsigned int copied_total;
+       uint64_t bytes_sent;
+       uint64_t bytes_received;
+       uint64_t copied_total;
        uint16_t bits_per_sample;
        uint16_t source; /* Encoding source bit mask */
        struct audio_client *audio_client;
@@ -1026,16 +1027,18 @@ static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
 
 static int q6asm_dai_compr_pointer(struct snd_soc_component *component,
                                   struct snd_compr_stream *stream,
-                                  struct snd_compr_tstamp *tstamp)
+                                  struct snd_compr_tstamp64 *tstamp)
 {
        struct snd_compr_runtime *runtime = stream->runtime;
        struct q6asm_dai_rtd *prtd = runtime->private_data;
        unsigned long flags;
+       uint64_t temp_copied_total;
 
        spin_lock_irqsave(&prtd->lock, flags);
 
        tstamp->copied_total = prtd->copied_total;
-       tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
+       temp_copied_total = tstamp->copied_total;
+       tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size);
 
        spin_unlock_irqrestore(&prtd->lock, flags);
 
@@ -1050,23 +1053,26 @@ static int q6asm_compr_copy(struct snd_soc_component *component,
        struct q6asm_dai_rtd *prtd = runtime->private_data;
        unsigned long flags;
        u32 wflags = 0;
-       int avail, bytes_in_flight = 0;
+       uint64_t avail, bytes_in_flight = 0;
        void *dstn;
        size_t copy;
        u32 app_pointer;
-       u32 bytes_received;
+       uint64_t bytes_received;
+       uint64_t temp_bytes_received;
 
        bytes_received = prtd->bytes_received;
+       temp_bytes_received = bytes_received;
 
        /**
         * Make sure that next track data pointer is aligned at 32 bit boundary
         * This is a Mandatory requirement from DSP data buffers alignment
         */
-       if (prtd->next_track)
+       if (prtd->next_track) {
                bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count);
+               temp_bytes_received = bytes_received;
+       }
 
-       app_pointer = bytes_received/prtd->pcm_size;
-       app_pointer = bytes_received -  (app_pointer * prtd->pcm_size);
+       app_pointer = do_div(temp_bytes_received, prtd->pcm_size);
        dstn = prtd->dma_buffer.area + app_pointer;
 
        if (count < prtd->pcm_size - app_pointer) {
index 65c4950940244c0becd5901f3749ad98e61ca646..c815fd1b3fd19a1edecdc6d120d98552a7772f61 100644 (file)
@@ -637,7 +637,7 @@ int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
 EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack);
 
 int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream,
-                                   struct snd_compr_tstamp *tstamp)
+                                   struct snd_compr_tstamp64 *tstamp)
 {
        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
        struct snd_soc_component *component;
index 01d1d6bee28cf6d5000ca81b58abedc081edf11b..7b81dffc6a935ac5ad2a56dc15e372c670d6fd7e 100644 (file)
@@ -457,7 +457,7 @@ err:
 }
 
 static int soc_compr_pointer(struct snd_compr_stream *cstream,
-                            struct snd_compr_tstamp *tstamp)
+                            struct snd_compr_tstamp64 *tstamp)
 {
        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
        int ret;
index 32f46a38682b798931702e88bc1738ad23e64769..f231b4174b5fcbfd9b723e7a9d3fee237f3c5b68 100644 (file)
@@ -774,7 +774,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack);
 
 int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
                              struct snd_compr_stream *cstream,
-                             struct snd_compr_tstamp *tstamp)
+                             struct snd_compr_tstamp64 *tstamp)
 {
        int ret = 0;
 
index 0d0f8ec4aed838b1fbde652126e9e653d7b952f9..ce51ed108a47b7102c9dc65ed0ae25988d145cfd 100644 (file)
@@ -108,7 +108,7 @@ static int acp_probes_compr_trigger(struct sof_client_dev *cdev,
 
 static int acp_probes_compr_pointer(struct sof_client_dev *cdev,
                                    struct snd_compr_stream *cstream,
-                                   struct snd_compr_tstamp *tstamp,
+                                   struct snd_compr_tstamp64 *tstamp,
                                    struct snd_soc_dai *dai)
 {
        struct acp_dsp_stream *stream = cstream->runtime->private_data;
index d7b044f33d79633afa2f3a3d8f58602a6c7565dc..90b932ae3bab2c9483610e6c65a3ef3db239c104 100644 (file)
@@ -361,7 +361,7 @@ static int sof_compr_copy(struct snd_soc_component *component,
 
 static int sof_compr_pointer(struct snd_soc_component *component,
                             struct snd_compr_stream *cstream,
-                            struct snd_compr_tstamp *tstamp)
+                            struct snd_compr_tstamp64 *tstamp)
 {
        struct snd_sof_pcm *spcm;
        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
index c645346c2c847c437763c11b25732ee0173ee6aa..b06933cebc454792a6ffd4042483ae1818890b6e 100644 (file)
@@ -112,7 +112,7 @@ static int hda_probes_compr_trigger(struct sof_client_dev *cdev,
 
 static int hda_probes_compr_pointer(struct sof_client_dev *cdev,
                                    struct snd_compr_stream *cstream,
-                                   struct snd_compr_tstamp *tstamp,
+                                   struct snd_compr_tstamp64 *tstamp,
                                    struct snd_soc_dai *dai)
 {
        struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
index 663c0d3c314c668507d133a171276e6260fef83b..1353e911501a2e66ae77647d986ed7ed9fbcd2a4 100644 (file)
@@ -137,7 +137,7 @@ static int sof_probes_compr_trigger(struct snd_compr_stream *cstream, int cmd,
 }
 
 static int sof_probes_compr_pointer(struct snd_compr_stream *cstream,
-                                   struct snd_compr_tstamp *tstamp,
+                                   struct snd_compr_tstamp64 *tstamp,
                                    struct snd_soc_dai *dai)
 {
        struct snd_soc_card *card = snd_soc_component_get_drvdata(dai->component);
index da04d65b8d995e5cfb2e5c5ab1610475957868b4..8713b69cda4b22b506d659d9c904afb529c3026d 100644 (file)
@@ -4,7 +4,7 @@
 #define __SOF_CLIENT_PROBES_H
 
 struct snd_compr_stream;
-struct snd_compr_tstamp;
+struct snd_compr_tstamp64;
 struct snd_compr_params;
 struct sof_client_dev;
 struct snd_soc_dai;
@@ -24,7 +24,7 @@ struct sof_probes_host_ops {
        int (*trigger)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
                       int cmd, struct snd_soc_dai *dai);
        int (*pointer)(struct sof_client_dev *cdev, struct snd_compr_stream *cstream,
-                      struct snd_compr_tstamp *tstamp,
+                      struct snd_compr_tstamp64 *tstamp,
                       struct snd_soc_dai *dai);
 };
 
index 57bd1a0728ac25cb9dc53c3f0702b83316c20fe6..4b6ebfa5b0339188e70af108ed688e866278d359 100644 (file)
@@ -85,9 +85,9 @@ struct sprd_compr_stream {
        int info_size;
 
        /* Data size copied to IRAM buffer */
-       int copied_total;
+       u64 copied_total;
        /* Total received data size from userspace */
-       int received_total;
+       u64 received_total;
        /* Stage 0 IRAM buffer received data size */
        int received_stage0;
        /* Stage 1 DDR buffer received data size */
@@ -513,7 +513,7 @@ static int sprd_platform_compr_trigger(struct snd_soc_component *component,
 
 static int sprd_platform_compr_pointer(struct snd_soc_component *component,
                                       struct snd_compr_stream *cstream,
-                                      struct snd_compr_tstamp *tstamp)
+                                      struct snd_compr_tstamp64 *tstamp)
 {
        struct snd_compr_runtime *runtime = cstream->runtime;
        struct sprd_compr_stream *stream = runtime->private_data;
index be5e385f5e4286a5321891318dfbba5b8b34d3d8..c5935a1367e6295b421eebcf0e240f94ef5d04a5 100644 (file)
@@ -19,7 +19,7 @@ struct sprd_compr_playinfo {
        int total_time;
        int current_time;
        int total_data_length;
-       int current_data_offset;
+       u64 current_data_offset;
 };
 
 struct sprd_compr_params {
@@ -46,7 +46,7 @@ struct sprd_compr_ops {
        int (*stop)(int str_id);
        int (*pause)(int str_id);
        int (*pause_release)(int str_id);
-       int (*drain)(int received_total);
+       int (*drain)(u64 received_total);
        int (*set_params)(int str_id, struct sprd_compr_params *params);
 };
 
index 4a19d4908ffd64223cd0daf166e4a5c49f0101a7..b18af98a552b752140035418b7bf95de161e34de 100644 (file)
@@ -249,7 +249,7 @@ static int uniphier_aio_compr_trigger(struct snd_soc_component *component,
 
 static int uniphier_aio_compr_pointer(struct snd_soc_component *component,
                                      struct snd_compr_stream *cstream,
-                                     struct snd_compr_tstamp *tstamp)
+                                     struct snd_compr_tstamp64 *tstamp)
 {
        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
        struct snd_compr_runtime *runtime = cstream->runtime;