// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
//
// This file is provided under a dual BSD/GPLv2 license. When using or
// redistributing this file, you may do so under either license.
//
// Copyright(c) 2022 Intel Corporation
//
#include <sound/pcm_params.h>
#include <sound/sof/ipc4/header.h>
#include "sof-audio.h"
#include "sof-priv.h"
#include "ops.h"
#include "ipc4-priv.h"
#include "ipc4-topology.h"
#include "ipc4-fw-reg.h"
/**
* struct sof_ipc4_timestamp_info - IPC4 timestamp info
* @host_copier: the host copier of the pcm stream
* @dai_copier: the dai copier of the pcm stream
* @stream_start_offset: reported by fw in memory window (converted to
* frames at host_copier sampling rate)
* @stream_end_offset: reported by fw in memory window (converted to
* frames at host_copier sampling rate)
* @llp_offset: llp offset in memory window
* @delay: Calculated and stored in pointer callback. The stored value is
* returned in the delay callback. Expressed in frames at host copier
* sampling rate.
*/
struct sof_ipc4_timestamp_info {
struct sof_ipc4_copier *host_copier;
struct sof_ipc4_copier *dai_copier;
u64 stream_start_offset;
u64 stream_end_offset;
u32 llp_offset;
snd_pcm_sframes_t delay;
};
/**
* struct sof_ipc4_pcm_stream_priv - IPC4 specific private data
* @time_info: pointer to time info struct if it is supported, otherwise NULL
* @chain_dma_allocated: indicates the ChainDMA allocation state
*/
struct sof_ipc4_pcm_stream_priv {
struct sof_ipc4_timestamp_info *time_info;
bool chain_dma_allocated;
};
/*
* Modulus to use to compare host and link position counters. The sampling
* rates may be different, so the raw hardware counters will wrap
* around at different times. To calculate differences, use
* DELAY_BOUNDARY as a common modulus. This value must be smaller than
* the wrap-around point of any hardware counter, and larger than any
* valid delay measurement.
*/
#define DELAY_BOUNDARY U32_MAX
#define DELAY_MAX (DELAY_BOUNDARY >> 1)
static inline struct sof_ipc4_timestamp_info *
sof_ipc4_sps_to_time_info(struct snd_sof_pcm_stream *sps)
{
struct sof_ipc4_pcm_stream_priv *stream_priv = sps->private;
return stream_priv->time_info;
}
static
char *sof_ipc4_set_multi_pipeline_state_debug(struct snd_sof_dev *sdev, char *buf, size_t size,
struct ipc4_pipeline_set_state_data *trigger_list)
{
int i, offset = 0;
for (i = 0; i < trigger_list->count; i++) {
offset += snprintf(buf + offset, size - offset, " %d",
trigger_list->pipeline_instance_ids[i]);
if (offset >= size - 1) {
buf[size - 1] = '\0';
break;
}
}
return buf;
}
static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state,