ALSA: compress_offload: Add 64-bit safe timestamp infrastructure

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
This commit is contained in:
Joris Verhaegen 2025-09-05 10:12:54 +01:00 committed by Takashi Iwai
parent cbd676874e
commit 2c92e2fbe9
24 changed files with 125 additions and 72 deletions

View 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,

View 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,

View 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 *);
};

View 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

View 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;
}

View 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;

View 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);

View 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;
}

View 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);

View 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;
}

View 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;

View 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) {

View 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) {

View 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;

View 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;

View 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;

View 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;

View 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;

View 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);

View 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);

View 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);
};

View 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;

View 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);
};

View 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;