18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci *  compress_driver.h - compress offload driver definations
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (C) 2011 Intel Corporation
68c2ecf20Sopenharmony_ci *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
78c2ecf20Sopenharmony_ci *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#ifndef __COMPRESS_DRIVER_H
118c2ecf20Sopenharmony_ci#define __COMPRESS_DRIVER_H
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/types.h>
148c2ecf20Sopenharmony_ci#include <linux/sched.h>
158c2ecf20Sopenharmony_ci#include <sound/core.h>
168c2ecf20Sopenharmony_ci#include <sound/compress_offload.h>
178c2ecf20Sopenharmony_ci#include <sound/asound.h>
188c2ecf20Sopenharmony_ci#include <sound/pcm.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistruct snd_compr_ops;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/**
238c2ecf20Sopenharmony_ci * struct snd_compr_runtime: runtime stream description
248c2ecf20Sopenharmony_ci * @state: stream state
258c2ecf20Sopenharmony_ci * @ops: pointer to DSP callbacks
268c2ecf20Sopenharmony_ci * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
278c2ecf20Sopenharmony_ci *	DSP doesn't implement copy
288c2ecf20Sopenharmony_ci * @buffer_size: size of the above buffer
298c2ecf20Sopenharmony_ci * @fragment_size: size of buffer fragment in bytes
308c2ecf20Sopenharmony_ci * @fragments: number of such fragments
318c2ecf20Sopenharmony_ci * @total_bytes_available: cumulative number of bytes made available in
328c2ecf20Sopenharmony_ci *	the ring buffer
338c2ecf20Sopenharmony_ci * @total_bytes_transferred: cumulative bytes transferred by offload DSP
348c2ecf20Sopenharmony_ci * @sleep: poll sleep
358c2ecf20Sopenharmony_ci * @private_data: driver private data pointer
368c2ecf20Sopenharmony_ci * @dma_area: virtual buffer address
378c2ecf20Sopenharmony_ci * @dma_addr: physical buffer address (not accessible from main CPU)
388c2ecf20Sopenharmony_ci * @dma_bytes: size of DMA area
398c2ecf20Sopenharmony_ci * @dma_buffer_p: runtime dma buffer pointer
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_cistruct snd_compr_runtime {
428c2ecf20Sopenharmony_ci	snd_pcm_state_t state;
438c2ecf20Sopenharmony_ci	struct snd_compr_ops *ops;
448c2ecf20Sopenharmony_ci	void *buffer;
458c2ecf20Sopenharmony_ci	u64 buffer_size;
468c2ecf20Sopenharmony_ci	u32 fragment_size;
478c2ecf20Sopenharmony_ci	u32 fragments;
488c2ecf20Sopenharmony_ci	u64 total_bytes_available;
498c2ecf20Sopenharmony_ci	u64 total_bytes_transferred;
508c2ecf20Sopenharmony_ci	wait_queue_head_t sleep;
518c2ecf20Sopenharmony_ci	void *private_data;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	unsigned char *dma_area;
548c2ecf20Sopenharmony_ci	dma_addr_t dma_addr;
558c2ecf20Sopenharmony_ci	size_t dma_bytes;
568c2ecf20Sopenharmony_ci	struct snd_dma_buffer *dma_buffer_p;
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci/**
608c2ecf20Sopenharmony_ci * struct snd_compr_stream: compressed stream
618c2ecf20Sopenharmony_ci * @name: device name
628c2ecf20Sopenharmony_ci * @ops: pointer to DSP callbacks
638c2ecf20Sopenharmony_ci * @runtime: pointer to runtime structure
648c2ecf20Sopenharmony_ci * @device: device pointer
658c2ecf20Sopenharmony_ci * @error_work: delayed work used when closing the stream due to an error
668c2ecf20Sopenharmony_ci * @direction: stream direction, playback/recording
678c2ecf20Sopenharmony_ci * @metadata_set: metadata set flag, true when set
688c2ecf20Sopenharmony_ci * @next_track: has userspace signal next track transition, true when set
698c2ecf20Sopenharmony_ci * @partial_drain: undergoing partial_drain for stream, true when set
708c2ecf20Sopenharmony_ci * @private_data: pointer to DSP private data
718c2ecf20Sopenharmony_ci * @dma_buffer: allocated buffer if any
728c2ecf20Sopenharmony_ci */
738c2ecf20Sopenharmony_cistruct snd_compr_stream {
748c2ecf20Sopenharmony_ci	const char *name;
758c2ecf20Sopenharmony_ci	struct snd_compr_ops *ops;
768c2ecf20Sopenharmony_ci	struct snd_compr_runtime *runtime;
778c2ecf20Sopenharmony_ci	struct snd_compr *device;
788c2ecf20Sopenharmony_ci	struct delayed_work error_work;
798c2ecf20Sopenharmony_ci	enum snd_compr_direction direction;
808c2ecf20Sopenharmony_ci	bool metadata_set;
818c2ecf20Sopenharmony_ci	bool next_track;
828c2ecf20Sopenharmony_ci	bool partial_drain;
838c2ecf20Sopenharmony_ci	void *private_data;
848c2ecf20Sopenharmony_ci	struct snd_dma_buffer dma_buffer;
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/**
888c2ecf20Sopenharmony_ci * struct snd_compr_ops: compressed path DSP operations
898c2ecf20Sopenharmony_ci * @open: Open the compressed stream
908c2ecf20Sopenharmony_ci * This callback is mandatory and shall keep dsp ready to receive the stream
918c2ecf20Sopenharmony_ci * parameter
928c2ecf20Sopenharmony_ci * @free: Close the compressed stream, mandatory
938c2ecf20Sopenharmony_ci * @set_params: Sets the compressed stream parameters, mandatory
948c2ecf20Sopenharmony_ci * This can be called in during stream creation only to set codec params
958c2ecf20Sopenharmony_ci * and the stream properties
968c2ecf20Sopenharmony_ci * @get_params: retrieve the codec parameters, mandatory
978c2ecf20Sopenharmony_ci * @set_metadata: Set the metadata values for a stream
988c2ecf20Sopenharmony_ci * @get_metadata: retrieves the requested metadata values from stream
998c2ecf20Sopenharmony_ci * @trigger: Trigger operations like start, pause, resume, drain, stop.
1008c2ecf20Sopenharmony_ci * This callback is mandatory
1018c2ecf20Sopenharmony_ci * @pointer: Retrieve current h/w pointer information. Mandatory
1028c2ecf20Sopenharmony_ci * @copy: Copy the compressed data to/from userspace, Optional
1038c2ecf20Sopenharmony_ci * Can't be implemented if DSP supports mmap
1048c2ecf20Sopenharmony_ci * @mmap: DSP mmap method to mmap DSP memory
1058c2ecf20Sopenharmony_ci * @ack: Ack for DSP when data is written to audio buffer, Optional
1068c2ecf20Sopenharmony_ci * Not valid if copy is implemented
1078c2ecf20Sopenharmony_ci * @get_caps: Retrieve DSP capabilities, mandatory
1088c2ecf20Sopenharmony_ci * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
1098c2ecf20Sopenharmony_ci */
1108c2ecf20Sopenharmony_cistruct snd_compr_ops {
1118c2ecf20Sopenharmony_ci	int (*open)(struct snd_compr_stream *stream);
1128c2ecf20Sopenharmony_ci	int (*free)(struct snd_compr_stream *stream);
1138c2ecf20Sopenharmony_ci	int (*set_params)(struct snd_compr_stream *stream,
1148c2ecf20Sopenharmony_ci			struct snd_compr_params *params);
1158c2ecf20Sopenharmony_ci	int (*get_params)(struct snd_compr_stream *stream,
1168c2ecf20Sopenharmony_ci			struct snd_codec *params);
1178c2ecf20Sopenharmony_ci	int (*set_metadata)(struct snd_compr_stream *stream,
1188c2ecf20Sopenharmony_ci			struct snd_compr_metadata *metadata);
1198c2ecf20Sopenharmony_ci	int (*get_metadata)(struct snd_compr_stream *stream,
1208c2ecf20Sopenharmony_ci			struct snd_compr_metadata *metadata);
1218c2ecf20Sopenharmony_ci	int (*trigger)(struct snd_compr_stream *stream, int cmd);
1228c2ecf20Sopenharmony_ci	int (*pointer)(struct snd_compr_stream *stream,
1238c2ecf20Sopenharmony_ci			struct snd_compr_tstamp *tstamp);
1248c2ecf20Sopenharmony_ci	int (*copy)(struct snd_compr_stream *stream, char __user *buf,
1258c2ecf20Sopenharmony_ci		       size_t count);
1268c2ecf20Sopenharmony_ci	int (*mmap)(struct snd_compr_stream *stream,
1278c2ecf20Sopenharmony_ci			struct vm_area_struct *vma);
1288c2ecf20Sopenharmony_ci	int (*ack)(struct snd_compr_stream *stream, size_t bytes);
1298c2ecf20Sopenharmony_ci	int (*get_caps) (struct snd_compr_stream *stream,
1308c2ecf20Sopenharmony_ci			struct snd_compr_caps *caps);
1318c2ecf20Sopenharmony_ci	int (*get_codec_caps) (struct snd_compr_stream *stream,
1328c2ecf20Sopenharmony_ci			struct snd_compr_codec_caps *codec);
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci/**
1368c2ecf20Sopenharmony_ci * struct snd_compr: Compressed device
1378c2ecf20Sopenharmony_ci * @name: DSP device name
1388c2ecf20Sopenharmony_ci * @dev: associated device instance
1398c2ecf20Sopenharmony_ci * @ops: pointer to DSP callbacks
1408c2ecf20Sopenharmony_ci * @private_data: pointer to DSP pvt data
1418c2ecf20Sopenharmony_ci * @card: sound card pointer
1428c2ecf20Sopenharmony_ci * @direction: Playback or capture direction
1438c2ecf20Sopenharmony_ci * @lock: device lock
1448c2ecf20Sopenharmony_ci * @device: device id
1458c2ecf20Sopenharmony_ci */
1468c2ecf20Sopenharmony_cistruct snd_compr {
1478c2ecf20Sopenharmony_ci	const char *name;
1488c2ecf20Sopenharmony_ci	struct device dev;
1498c2ecf20Sopenharmony_ci	struct snd_compr_ops *ops;
1508c2ecf20Sopenharmony_ci	void *private_data;
1518c2ecf20Sopenharmony_ci	struct snd_card *card;
1528c2ecf20Sopenharmony_ci	unsigned int direction;
1538c2ecf20Sopenharmony_ci	struct mutex lock;
1548c2ecf20Sopenharmony_ci	int device;
1558c2ecf20Sopenharmony_ci#ifdef CONFIG_SND_VERBOSE_PROCFS
1568c2ecf20Sopenharmony_ci	/* private: */
1578c2ecf20Sopenharmony_ci	char id[64];
1588c2ecf20Sopenharmony_ci	struct snd_info_entry *proc_root;
1598c2ecf20Sopenharmony_ci	struct snd_info_entry *proc_info_entry;
1608c2ecf20Sopenharmony_ci#endif
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci/* compress device register APIs */
1648c2ecf20Sopenharmony_ciint snd_compress_register(struct snd_compr *device);
1658c2ecf20Sopenharmony_ciint snd_compress_deregister(struct snd_compr *device);
1668c2ecf20Sopenharmony_ciint snd_compress_new(struct snd_card *card, int device,
1678c2ecf20Sopenharmony_ci			int type, const char *id, struct snd_compr *compr);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci/* dsp driver callback apis
1708c2ecf20Sopenharmony_ci * For playback: driver should call snd_compress_fragment_elapsed() to let the
1718c2ecf20Sopenharmony_ci * framework know that a fragment has been consumed from the ring buffer
1728c2ecf20Sopenharmony_ci *
1738c2ecf20Sopenharmony_ci * For recording: we want to know when a frame is available or when
1748c2ecf20Sopenharmony_ci * at least one frame is available so snd_compress_frame_elapsed()
1758c2ecf20Sopenharmony_ci * callback should be called when a encodeded frame is available
1768c2ecf20Sopenharmony_ci */
1778c2ecf20Sopenharmony_cistatic inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	wake_up(&stream->runtime->sleep);
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	if (snd_BUG_ON(!stream))
1858c2ecf20Sopenharmony_ci		return;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	/* for partial_drain case we are back to running state on success */
1888c2ecf20Sopenharmony_ci	if (stream->partial_drain) {
1898c2ecf20Sopenharmony_ci		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
1908c2ecf20Sopenharmony_ci		stream->partial_drain = false; /* clear this flag as well */
1918c2ecf20Sopenharmony_ci	} else {
1928c2ecf20Sopenharmony_ci		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	wake_up(&stream->runtime->sleep);
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci/**
1998c2ecf20Sopenharmony_ci * snd_compr_set_runtime_buffer - Set the Compress runtime buffer
2008c2ecf20Sopenharmony_ci * @stream: compress stream to set
2018c2ecf20Sopenharmony_ci * @bufp: the buffer information, NULL to clear
2028c2ecf20Sopenharmony_ci *
2038c2ecf20Sopenharmony_ci * Copy the buffer information to runtime buffer when @bufp is non-NULL.
2048c2ecf20Sopenharmony_ci * Otherwise it clears the current buffer information.
2058c2ecf20Sopenharmony_ci */
2068c2ecf20Sopenharmony_cistatic inline void
2078c2ecf20Sopenharmony_cisnd_compr_set_runtime_buffer(struct snd_compr_stream *stream,
2088c2ecf20Sopenharmony_ci			     struct snd_dma_buffer *bufp)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	struct snd_compr_runtime *runtime = stream->runtime;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	if (bufp) {
2138c2ecf20Sopenharmony_ci		runtime->dma_buffer_p = bufp;
2148c2ecf20Sopenharmony_ci		runtime->dma_area = bufp->area;
2158c2ecf20Sopenharmony_ci		runtime->dma_addr = bufp->addr;
2168c2ecf20Sopenharmony_ci		runtime->dma_bytes = bufp->bytes;
2178c2ecf20Sopenharmony_ci	} else {
2188c2ecf20Sopenharmony_ci		runtime->dma_buffer_p = NULL;
2198c2ecf20Sopenharmony_ci		runtime->dma_area = NULL;
2208c2ecf20Sopenharmony_ci		runtime->dma_addr = 0;
2218c2ecf20Sopenharmony_ci		runtime->dma_bytes = 0;
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ciint snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size);
2268c2ecf20Sopenharmony_ciint snd_compr_free_pages(struct snd_compr_stream *stream);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ciint snd_compr_stop_error(struct snd_compr_stream *stream,
2298c2ecf20Sopenharmony_ci			 snd_pcm_state_t state);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci#endif
232