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