162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci *  compress_driver.h - compress offload driver definations
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2011 Intel Corporation
662306a36Sopenharmony_ci *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
762306a36Sopenharmony_ci *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef __COMPRESS_DRIVER_H
1162306a36Sopenharmony_ci#define __COMPRESS_DRIVER_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci#include <linux/sched.h>
1562306a36Sopenharmony_ci#include <sound/core.h>
1662306a36Sopenharmony_ci#include <sound/compress_offload.h>
1762306a36Sopenharmony_ci#include <sound/asound.h>
1862306a36Sopenharmony_ci#include <sound/pcm.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct snd_compr_ops;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/**
2362306a36Sopenharmony_ci * struct snd_compr_runtime: runtime stream description
2462306a36Sopenharmony_ci * @state: stream state
2562306a36Sopenharmony_ci * @ops: pointer to DSP callbacks
2662306a36Sopenharmony_ci * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
2762306a36Sopenharmony_ci *	DSP doesn't implement copy
2862306a36Sopenharmony_ci * @buffer_size: size of the above buffer
2962306a36Sopenharmony_ci * @fragment_size: size of buffer fragment in bytes
3062306a36Sopenharmony_ci * @fragments: number of such fragments
3162306a36Sopenharmony_ci * @total_bytes_available: cumulative number of bytes made available in
3262306a36Sopenharmony_ci *	the ring buffer
3362306a36Sopenharmony_ci * @total_bytes_transferred: cumulative bytes transferred by offload DSP
3462306a36Sopenharmony_ci * @sleep: poll sleep
3562306a36Sopenharmony_ci * @private_data: driver private data pointer
3662306a36Sopenharmony_ci * @dma_area: virtual buffer address
3762306a36Sopenharmony_ci * @dma_addr: physical buffer address (not accessible from main CPU)
3862306a36Sopenharmony_ci * @dma_bytes: size of DMA area
3962306a36Sopenharmony_ci * @dma_buffer_p: runtime dma buffer pointer
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_cistruct snd_compr_runtime {
4262306a36Sopenharmony_ci	snd_pcm_state_t state;
4362306a36Sopenharmony_ci	struct snd_compr_ops *ops;
4462306a36Sopenharmony_ci	void *buffer;
4562306a36Sopenharmony_ci	u64 buffer_size;
4662306a36Sopenharmony_ci	u32 fragment_size;
4762306a36Sopenharmony_ci	u32 fragments;
4862306a36Sopenharmony_ci	u64 total_bytes_available;
4962306a36Sopenharmony_ci	u64 total_bytes_transferred;
5062306a36Sopenharmony_ci	wait_queue_head_t sleep;
5162306a36Sopenharmony_ci	void *private_data;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	unsigned char *dma_area;
5462306a36Sopenharmony_ci	dma_addr_t dma_addr;
5562306a36Sopenharmony_ci	size_t dma_bytes;
5662306a36Sopenharmony_ci	struct snd_dma_buffer *dma_buffer_p;
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/**
6062306a36Sopenharmony_ci * struct snd_compr_stream: compressed stream
6162306a36Sopenharmony_ci * @name: device name
6262306a36Sopenharmony_ci * @ops: pointer to DSP callbacks
6362306a36Sopenharmony_ci * @runtime: pointer to runtime structure
6462306a36Sopenharmony_ci * @device: device pointer
6562306a36Sopenharmony_ci * @error_work: delayed work used when closing the stream due to an error
6662306a36Sopenharmony_ci * @direction: stream direction, playback/recording
6762306a36Sopenharmony_ci * @metadata_set: metadata set flag, true when set
6862306a36Sopenharmony_ci * @next_track: has userspace signal next track transition, true when set
6962306a36Sopenharmony_ci * @partial_drain: undergoing partial_drain for stream, true when set
7062306a36Sopenharmony_ci * @pause_in_draining: paused during draining state, true when set
7162306a36Sopenharmony_ci * @private_data: pointer to DSP private data
7262306a36Sopenharmony_ci * @dma_buffer: allocated buffer if any
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_cistruct snd_compr_stream {
7562306a36Sopenharmony_ci	const char *name;
7662306a36Sopenharmony_ci	struct snd_compr_ops *ops;
7762306a36Sopenharmony_ci	struct snd_compr_runtime *runtime;
7862306a36Sopenharmony_ci	struct snd_compr *device;
7962306a36Sopenharmony_ci	struct delayed_work error_work;
8062306a36Sopenharmony_ci	enum snd_compr_direction direction;
8162306a36Sopenharmony_ci	bool metadata_set;
8262306a36Sopenharmony_ci	bool next_track;
8362306a36Sopenharmony_ci	bool partial_drain;
8462306a36Sopenharmony_ci	bool pause_in_draining;
8562306a36Sopenharmony_ci	void *private_data;
8662306a36Sopenharmony_ci	struct snd_dma_buffer dma_buffer;
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/**
9062306a36Sopenharmony_ci * struct snd_compr_ops: compressed path DSP operations
9162306a36Sopenharmony_ci * @open: Open the compressed stream
9262306a36Sopenharmony_ci * This callback is mandatory and shall keep dsp ready to receive the stream
9362306a36Sopenharmony_ci * parameter
9462306a36Sopenharmony_ci * @free: Close the compressed stream, mandatory
9562306a36Sopenharmony_ci * @set_params: Sets the compressed stream parameters, mandatory
9662306a36Sopenharmony_ci * This can be called in during stream creation only to set codec params
9762306a36Sopenharmony_ci * and the stream properties
9862306a36Sopenharmony_ci * @get_params: retrieve the codec parameters, mandatory
9962306a36Sopenharmony_ci * @set_metadata: Set the metadata values for a stream
10062306a36Sopenharmony_ci * @get_metadata: retrieves the requested metadata values from stream
10162306a36Sopenharmony_ci * @trigger: Trigger operations like start, pause, resume, drain, stop.
10262306a36Sopenharmony_ci * This callback is mandatory
10362306a36Sopenharmony_ci * @pointer: Retrieve current h/w pointer information. Mandatory
10462306a36Sopenharmony_ci * @copy: Copy the compressed data to/from userspace, Optional
10562306a36Sopenharmony_ci * Can't be implemented if DSP supports mmap
10662306a36Sopenharmony_ci * @mmap: DSP mmap method to mmap DSP memory
10762306a36Sopenharmony_ci * @ack: Ack for DSP when data is written to audio buffer, Optional
10862306a36Sopenharmony_ci * Not valid if copy is implemented
10962306a36Sopenharmony_ci * @get_caps: Retrieve DSP capabilities, mandatory
11062306a36Sopenharmony_ci * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
11162306a36Sopenharmony_ci */
11262306a36Sopenharmony_cistruct snd_compr_ops {
11362306a36Sopenharmony_ci	int (*open)(struct snd_compr_stream *stream);
11462306a36Sopenharmony_ci	int (*free)(struct snd_compr_stream *stream);
11562306a36Sopenharmony_ci	int (*set_params)(struct snd_compr_stream *stream,
11662306a36Sopenharmony_ci			struct snd_compr_params *params);
11762306a36Sopenharmony_ci	int (*get_params)(struct snd_compr_stream *stream,
11862306a36Sopenharmony_ci			struct snd_codec *params);
11962306a36Sopenharmony_ci	int (*set_metadata)(struct snd_compr_stream *stream,
12062306a36Sopenharmony_ci			struct snd_compr_metadata *metadata);
12162306a36Sopenharmony_ci	int (*get_metadata)(struct snd_compr_stream *stream,
12262306a36Sopenharmony_ci			struct snd_compr_metadata *metadata);
12362306a36Sopenharmony_ci	int (*trigger)(struct snd_compr_stream *stream, int cmd);
12462306a36Sopenharmony_ci	int (*pointer)(struct snd_compr_stream *stream,
12562306a36Sopenharmony_ci			struct snd_compr_tstamp *tstamp);
12662306a36Sopenharmony_ci	int (*copy)(struct snd_compr_stream *stream, char __user *buf,
12762306a36Sopenharmony_ci		       size_t count);
12862306a36Sopenharmony_ci	int (*mmap)(struct snd_compr_stream *stream,
12962306a36Sopenharmony_ci			struct vm_area_struct *vma);
13062306a36Sopenharmony_ci	int (*ack)(struct snd_compr_stream *stream, size_t bytes);
13162306a36Sopenharmony_ci	int (*get_caps) (struct snd_compr_stream *stream,
13262306a36Sopenharmony_ci			struct snd_compr_caps *caps);
13362306a36Sopenharmony_ci	int (*get_codec_caps) (struct snd_compr_stream *stream,
13462306a36Sopenharmony_ci			struct snd_compr_codec_caps *codec);
13562306a36Sopenharmony_ci};
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci/**
13862306a36Sopenharmony_ci * struct snd_compr: Compressed device
13962306a36Sopenharmony_ci * @name: DSP device name
14062306a36Sopenharmony_ci * @dev: associated device instance
14162306a36Sopenharmony_ci * @ops: pointer to DSP callbacks
14262306a36Sopenharmony_ci * @private_data: pointer to DSP pvt data
14362306a36Sopenharmony_ci * @card: sound card pointer
14462306a36Sopenharmony_ci * @direction: Playback or capture direction
14562306a36Sopenharmony_ci * @lock: device lock
14662306a36Sopenharmony_ci * @device: device id
14762306a36Sopenharmony_ci * @use_pause_in_draining: allow pause in draining, true when set
14862306a36Sopenharmony_ci */
14962306a36Sopenharmony_cistruct snd_compr {
15062306a36Sopenharmony_ci	const char *name;
15162306a36Sopenharmony_ci	struct device *dev;
15262306a36Sopenharmony_ci	struct snd_compr_ops *ops;
15362306a36Sopenharmony_ci	void *private_data;
15462306a36Sopenharmony_ci	struct snd_card *card;
15562306a36Sopenharmony_ci	unsigned int direction;
15662306a36Sopenharmony_ci	struct mutex lock;
15762306a36Sopenharmony_ci	int device;
15862306a36Sopenharmony_ci	bool use_pause_in_draining;
15962306a36Sopenharmony_ci#ifdef CONFIG_SND_VERBOSE_PROCFS
16062306a36Sopenharmony_ci	/* private: */
16162306a36Sopenharmony_ci	char id[64];
16262306a36Sopenharmony_ci	struct snd_info_entry *proc_root;
16362306a36Sopenharmony_ci	struct snd_info_entry *proc_info_entry;
16462306a36Sopenharmony_ci#endif
16562306a36Sopenharmony_ci};
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci/* compress device register APIs */
16862306a36Sopenharmony_ciint snd_compress_new(struct snd_card *card, int device,
16962306a36Sopenharmony_ci			int type, const char *id, struct snd_compr *compr);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci/**
17262306a36Sopenharmony_ci * snd_compr_use_pause_in_draining - Allow pause and resume in draining state
17362306a36Sopenharmony_ci * @substream: compress substream to set
17462306a36Sopenharmony_ci *
17562306a36Sopenharmony_ci * Allow pause and resume in draining state.
17662306a36Sopenharmony_ci * Only HW driver supports this transition can call this API.
17762306a36Sopenharmony_ci */
17862306a36Sopenharmony_cistatic inline void snd_compr_use_pause_in_draining(struct snd_compr_stream *substream)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	substream->device->use_pause_in_draining = true;
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci/* dsp driver callback apis
18462306a36Sopenharmony_ci * For playback: driver should call snd_compress_fragment_elapsed() to let the
18562306a36Sopenharmony_ci * framework know that a fragment has been consumed from the ring buffer
18662306a36Sopenharmony_ci *
18762306a36Sopenharmony_ci * For recording: we want to know when a frame is available or when
18862306a36Sopenharmony_ci * at least one frame is available so snd_compress_frame_elapsed()
18962306a36Sopenharmony_ci * callback should be called when a encodeded frame is available
19062306a36Sopenharmony_ci */
19162306a36Sopenharmony_cistatic inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	wake_up(&stream->runtime->sleep);
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	if (snd_BUG_ON(!stream))
19962306a36Sopenharmony_ci		return;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	/* for partial_drain case we are back to running state on success */
20262306a36Sopenharmony_ci	if (stream->partial_drain) {
20362306a36Sopenharmony_ci		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
20462306a36Sopenharmony_ci		stream->partial_drain = false; /* clear this flag as well */
20562306a36Sopenharmony_ci	} else {
20662306a36Sopenharmony_ci		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	wake_up(&stream->runtime->sleep);
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci/**
21362306a36Sopenharmony_ci * snd_compr_set_runtime_buffer - Set the Compress runtime buffer
21462306a36Sopenharmony_ci * @stream: compress stream to set
21562306a36Sopenharmony_ci * @bufp: the buffer information, NULL to clear
21662306a36Sopenharmony_ci *
21762306a36Sopenharmony_ci * Copy the buffer information to runtime buffer when @bufp is non-NULL.
21862306a36Sopenharmony_ci * Otherwise it clears the current buffer information.
21962306a36Sopenharmony_ci */
22062306a36Sopenharmony_cistatic inline void
22162306a36Sopenharmony_cisnd_compr_set_runtime_buffer(struct snd_compr_stream *stream,
22262306a36Sopenharmony_ci			     struct snd_dma_buffer *bufp)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	struct snd_compr_runtime *runtime = stream->runtime;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	if (bufp) {
22762306a36Sopenharmony_ci		runtime->dma_buffer_p = bufp;
22862306a36Sopenharmony_ci		runtime->dma_area = bufp->area;
22962306a36Sopenharmony_ci		runtime->dma_addr = bufp->addr;
23062306a36Sopenharmony_ci		runtime->dma_bytes = bufp->bytes;
23162306a36Sopenharmony_ci	} else {
23262306a36Sopenharmony_ci		runtime->dma_buffer_p = NULL;
23362306a36Sopenharmony_ci		runtime->dma_area = NULL;
23462306a36Sopenharmony_ci		runtime->dma_addr = 0;
23562306a36Sopenharmony_ci		runtime->dma_bytes = 0;
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ciint snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size);
24062306a36Sopenharmony_ciint snd_compr_free_pages(struct snd_compr_stream *stream);
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ciint snd_compr_stop_error(struct snd_compr_stream *stream,
24362306a36Sopenharmony_ci			 snd_pcm_state_t state);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci#endif
246