linux/sound/usb/pcm.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 */

#include <linux/init.h>
#include <linux/slab.h>
#include <linux/bitrev.h>
#include <linux/ratelimit.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>

#include "usbaudio.h"
#include "card.h"
#include "quirks.h"
#include "endpoint.h"
#include "helper.h"
#include "pcm.h"
#include "clock.h"
#include "power.h"
#include "media.h"
#include "implicit.h"

#define SUBSTREAM_FLAG_DATA_EP_STARTED
#define SUBSTREAM_FLAG_SYNC_EP_STARTED

/* return the estimated delay based on USB frame counters */
static snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
					   struct snd_pcm_runtime *runtime)
{}

/*
 * return the current pcm pointer.  just based on the hwptr_done value.
 */
static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream)
{}

/*
 * find a matching audio format
 */
static const struct audioformat *
find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
	    unsigned int rate, unsigned int channels, bool strict_match,
	    struct snd_usb_substream *subs)
{}

static const struct audioformat *
find_substream_format(struct snd_usb_substream *subs,
		      const struct snd_pcm_hw_params *params)
{}

bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
{}

static int init_pitch_v1(struct snd_usb_audio *chip, int ep)
{}

static int init_pitch_v2(struct snd_usb_audio *chip, int ep)
{}

/*
 * initialize the pitch control and sample rate
 */
int snd_usb_init_pitch(struct snd_usb_audio *chip,
		       const struct audioformat *fmt)
{}

static bool stop_endpoints(struct snd_usb_substream *subs, bool keep_pending)
{}

static int start_endpoints(struct snd_usb_substream *subs)
{}

static void sync_pending_stops(struct snd_usb_substream *subs)
{}

/* PCM sync_stop callback */
static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
{}

/* Set up sync endpoint */
int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
				    struct audioformat *fmt)
{}

static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state)
{}

int snd_usb_pcm_suspend(struct snd_usb_stream *as)
{}

int snd_usb_pcm_resume(struct snd_usb_stream *as)
{}

static void close_endpoints(struct snd_usb_audio *chip,
			    struct snd_usb_substream *subs)
{}

/*
 * hw_params callback
 *
 * allocate a buffer and set the given audio format.
 *
 * so far we use a physically linear buffer although packetize transfer
 * doesn't need a continuous area.
 * if sg buffer is supported on the later version of alsa, we'll follow
 * that.
 */
static int snd_usb_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *hw_params)
{}

/*
 * hw_free callback
 *
 * reset the audio format and release the buffer
 */
static int snd_usb_hw_free(struct snd_pcm_substream *substream)
{}

/* free-wheeling mode? (e.g. dmix) */
static int in_free_wheeling_mode(struct snd_pcm_runtime *runtime)
{}

/* check whether early start is needed for playback stream */
static int lowlatency_playback_available(struct snd_pcm_runtime *runtime,
					 struct snd_usb_substream *subs)
{}

/*
 * prepare callback
 *
 * only a few subtle things...
 */
static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
{}

/*
 * h/w constraints
 */

#ifdef HW_CONST_DEBUG
#define hwc_debug
#else
#define hwc_debug(fmt, args...)
#endif

static const struct snd_pcm_hardware snd_usb_hardware =;

static int hw_check_valid_format(struct snd_usb_substream *subs,
				 struct snd_pcm_hw_params *params,
				 const struct audioformat *fp)
{}

static int apply_hw_params_minmax(struct snd_interval *it, unsigned int rmin,
				  unsigned int rmax)
{}

/* get the specified endpoint object that is being used by other streams
 * (i.e. the parameter is locked)
 */
static const struct snd_usb_endpoint *
get_endpoint_in_use(struct snd_usb_audio *chip, int endpoint,
		    const struct snd_usb_endpoint *ref_ep)
{}

static int hw_rule_rate(struct snd_pcm_hw_params *params,
			struct snd_pcm_hw_rule *rule)
{}


static int hw_rule_channels(struct snd_pcm_hw_params *params,
			    struct snd_pcm_hw_rule *rule)
{}

static int apply_hw_params_format_bits(struct snd_mask *fmt, u64 fbits)
{}

static int hw_rule_format(struct snd_pcm_hw_params *params,
			  struct snd_pcm_hw_rule *rule)
{}

static int hw_rule_period_time(struct snd_pcm_hw_params *params,
			       struct snd_pcm_hw_rule *rule)
{}

/* additional hw constraints for implicit feedback mode */
static int hw_rule_period_size_implicit_fb(struct snd_pcm_hw_params *params,
					   struct snd_pcm_hw_rule *rule)
{}

static int hw_rule_periods_implicit_fb(struct snd_pcm_hw_params *params,
				       struct snd_pcm_hw_rule *rule)
{}

/*
 * set up the runtime hardware information.
 */

static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
{}

static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
{}

static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
{}

/* Since a URB can handle only a single linear buffer, we must use double
 * buffering when the data to be transferred overflows the buffer boundary.
 * To avoid inconsistencies when updating hwptr_done, we use double buffering
 * for all URBs.
 */
static void retire_capture_urb(struct snd_usb_substream *subs,
			       struct urb *urb)
{}

static void urb_ctx_queue_advance(struct snd_usb_substream *subs,
				  struct urb *urb, unsigned int bytes)
{}

static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs,
					     struct urb *urb, unsigned int bytes)
{}

/* copy bit-reversed bytes onto transfer buffer */
static void fill_playback_urb_dsd_bitrev(struct snd_usb_substream *subs,
					 struct urb *urb, unsigned int bytes)
{}

static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb,
			int offset, int stride, unsigned int bytes)
{}

static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs,
				      struct urb *urb, int stride,
				      unsigned int bytes)
{}

static int prepare_playback_urb(struct snd_usb_substream *subs,
				struct urb *urb,
				bool in_stream_lock)
{}

/*
 * process after playback data complete
 * - decrease the delay count again
 */
static void retire_playback_urb(struct snd_usb_substream *subs,
			       struct urb *urb)
{}

/* PCM ack callback for the playback stream;
 * this plays a role only when the stream is running in low-latency mode.
 */
static int snd_usb_pcm_playback_ack(struct snd_pcm_substream *substream)
{}

static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream,
					      int cmd)
{}

static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream,
					     int cmd)
{}

static const struct snd_pcm_ops snd_usb_playback_ops =;

static const struct snd_pcm_ops snd_usb_capture_ops =;

void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream)
{}

void snd_usb_preallocate_buffer(struct snd_usb_substream *subs)
{}