linux/sound/soc/soc-pcm.c

// SPDX-License-Identifier: GPL-2.0+
//
// soc-pcm.c  --  ALSA SoC PCM
//
// Copyright 2005 Wolfson Microelectronics PLC.
// Copyright 2005 Openedhand Ltd.
// Copyright (C) 2010 Slimlogic Ltd.
// Copyright (C) 2010 Texas Instruments Inc.
//
// Authors: Liam Girdwood <[email protected]>
//          Mark Brown <[email protected]>

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pinctrl/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/export.h>
#include <linux/debugfs.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dpcm.h>
#include <sound/soc-link.h>
#include <sound/initval.h>

#define soc_pcm_ret(rtd, ret)
static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd,
			       const char *func, int ret)
{}

static inline void snd_soc_dpcm_stream_lock_irq(struct snd_soc_pcm_runtime *rtd,
						int stream)
{}

#define snd_soc_dpcm_stream_lock_irqsave_nested(rtd, stream, flags)

static inline void snd_soc_dpcm_stream_unlock_irq(struct snd_soc_pcm_runtime *rtd,
						  int stream)
{}

#define snd_soc_dpcm_stream_unlock_irqrestore(rtd, stream, flags)

#define DPCM_MAX_BE_USERS

static inline const char *soc_cpu_dai_name(struct snd_soc_pcm_runtime *rtd)
{}
static inline const char *soc_codec_dai_name(struct snd_soc_pcm_runtime *rtd)
{}

#ifdef CONFIG_DEBUG_FS
static const char *dpcm_state_string(enum snd_soc_dpcm_state state)
{}

static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
			       int stream, char *buf, size_t size)
{}

static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
				    size_t count, loff_t *ppos)
{}

static const struct file_operations dpcm_state_fops =;

void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
{}

static void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm, int stream)
{}

static void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
{}

#else
static inline void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm,
					     int stream)
{
}

static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
{
}
#endif

/* Set FE's runtime_update state; the state is protected via PCM stream lock
 * for avoiding the race with trigger callback.
 * If the state is unset and a trigger is pending while the previous operation,
 * process the pending trigger action here.
 */
static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);
static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
				     int stream, enum snd_soc_dpcm_update state)
{}

static void dpcm_set_be_update_state(struct snd_soc_pcm_runtime *be,
				     int stream, enum snd_soc_dpcm_update state)
{}

/**
 * snd_soc_runtime_action() - Increment/Decrement active count for
 * PCM runtime components
 * @rtd: ASoC PCM runtime that is activated
 * @stream: Direction of the PCM stream
 * @action: Activate stream if 1. Deactivate if -1.
 *
 * Increments/Decrements the active count for all the DAIs and components
 * attached to a PCM runtime.
 * Should typically be called when a stream is opened.
 *
 * Must be called with the rtd->card->pcm_mutex being held
 */
void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
			    int stream, int action)
{}
EXPORT_SYMBOL_GPL();

/**
 * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay
 * @rtd: The ASoC PCM runtime that should be checked.
 *
 * This function checks whether the power down delay should be ignored for a
 * specific PCM runtime. Returns true if the delay is 0, if the DAI link has
 * been configured to ignore the delay, or if none of the components benefits
 * from having the delay.
 */
bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
{}

/**
 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
 * @substream: the pcm substream
 * @hw: the hardware parameters
 *
 * Sets the substream runtime hardware parameters.
 */
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
	const struct snd_pcm_hardware *hw)
{}
EXPORT_SYMBOL_GPL();

/* DPCM stream event, send event to FE and all active BEs. */
int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
	int event)
{}

static void soc_pcm_set_dai_params(struct snd_soc_dai *dai,
				   struct snd_pcm_hw_params *params)
{}

static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
					struct snd_soc_dai *soc_dai)
{}

static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params)
{}

static void soc_pcm_update_symmetry(struct snd_pcm_substream *substream)
{}

static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits)
{}

static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
{}

static void soc_pcm_hw_init(struct snd_pcm_hardware *hw)
{}

static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw,
				   const struct snd_soc_pcm_stream *p)
{}

static void soc_pcm_hw_update_chan(struct snd_pcm_hardware *hw,
				   const struct snd_soc_pcm_stream *p)
{}

static void soc_pcm_hw_update_format(struct snd_pcm_hardware *hw,
				     const struct snd_soc_pcm_stream *p)
{}

static void soc_pcm_hw_update_subformat(struct snd_pcm_hardware *hw,
					const struct snd_soc_pcm_stream *p)
{}

/**
 * snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream
 * @rtd: ASoC PCM runtime
 * @hw: PCM hardware parameters (output)
 * @stream: Direction of the PCM stream
 *
 * Calculates the subset of stream parameters supported by all DAIs
 * associated with the PCM stream.
 */
int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
			    struct snd_pcm_hardware *hw, int stream)
{}
EXPORT_SYMBOL_GPL();

static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
{}

static int soc_pcm_components_open(struct snd_pcm_substream *substream)
{}

static int soc_pcm_components_close(struct snd_pcm_substream *substream,
				    int rollback)
{}

static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd,
			 struct snd_pcm_substream *substream, int rollback)
{}

/*
 * Called by ALSA when a PCM substream is closed. Private data can be
 * freed here. The cpu DAI, codec DAI, machine and components are also
 * shutdown.
 */
static int __soc_pcm_close(struct snd_soc_pcm_runtime *rtd,
			   struct snd_pcm_substream *substream)
{}

/* PCM close ops for non-DPCM streams */
static int soc_pcm_close(struct snd_pcm_substream *substream)
{}

static int soc_hw_sanity_check(struct snd_pcm_substream *substream)
{}

/*
 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
 * then initialized and any private data can be allocated. This also calls
 * startup for the cpu DAI, component, machine and codec DAI.
 */
static int __soc_pcm_open(struct snd_soc_pcm_runtime *rtd,
			  struct snd_pcm_substream *substream)
{}

/* PCM open ops for non-DPCM streams */
static int soc_pcm_open(struct snd_pcm_substream *substream)
{}

/*
 * Called by ALSA when the PCM substream is prepared, can set format, sample
 * rate, etc.  This function is non atomic and can be called multiple times,
 * it can refer to the runtime info.
 */
static int __soc_pcm_prepare(struct snd_soc_pcm_runtime *rtd,
			     struct snd_pcm_substream *substream)
{}

/* PCM prepare ops for non-DPCM streams */
static int soc_pcm_prepare(struct snd_pcm_substream *substream)
{}

static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params,
				       unsigned int mask)
{}

static int soc_pcm_hw_clean(struct snd_soc_pcm_runtime *rtd,
			    struct snd_pcm_substream *substream, int rollback)
{}

/*
 * Frees resources allocated by hw_params, can be called multiple times
 */
static int __soc_pcm_hw_free(struct snd_soc_pcm_runtime *rtd,
			     struct snd_pcm_substream *substream)
{}

/* hw_free PCM ops for non-DPCM streams */
static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
{}

/*
 * Called by ALSA when the hardware params are set by application. This
 * function can also be called multiple times and can allocate buffers
 * (using snd_pcm_lib_* ). It's non-atomic.
 */
static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
			       struct snd_pcm_substream *substream,
			       struct snd_pcm_hw_params *params)
{}

/* hw_params PCM ops for non-DPCM streams */
static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params)
{}

#define TRIGGER_MAX
static int (* const trigger[][TRIGGER_MAX])(struct snd_pcm_substream *substream, int cmd, int rollback) =;

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

/*
 * soc level wrapper for pointer callback
 * If cpu_dai, codec_dai, component driver has the delay callback, then
 * the runtime->delay will be updated via snd_soc_pcm_component/dai_delay().
 */
static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
{}

/* connect a FE and BE */
static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
		struct snd_soc_pcm_runtime *be, int stream)
{}

/* reparent a BE onto another FE */
static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
			struct snd_soc_pcm_runtime *be, int stream)
{}

/* disconnect a BE and FE */
void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
{}

/* get BE for DAI widget and stream */
static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
		struct snd_soc_dapm_widget *widget, int stream)
{}

int widget_in_list(struct snd_soc_dapm_widget_list *list,
		struct snd_soc_dapm_widget *widget)
{}
EXPORT_SYMBOL_GPL();

bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir)
{}
EXPORT_SYMBOL_GPL();

int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
	int stream, struct snd_soc_dapm_widget_list **list)
{}

void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
{}

static bool dpcm_be_is_active(struct snd_soc_dpcm *dpcm, int stream,
			      struct snd_soc_dapm_widget_list *list)
{}

static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
			    struct snd_soc_dapm_widget_list **list_)
{}

static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
	struct snd_soc_dapm_widget_list **list_)
{}

/*
 * Find the corresponding BE DAIs that source or sink audio to this
 * FE substream.
 */
int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
	int stream, struct snd_soc_dapm_widget_list **list, int new)
{}

void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
{}

void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
		      int do_hw_free, struct snd_soc_dpcm *last)
{}

int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
{}

static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream)
{}

static void dpcm_runtime_setup_be_format(struct snd_pcm_substream *substream)
{}

static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream)
{}

static void dpcm_runtime_setup_be_rate(struct snd_pcm_substream *substream)
{}

static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
			       int stream)
{}

static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
{}

static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
{}

void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
{}

static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
{}

int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
{}

static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params)
{}

int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
			       int cmd)
{}
EXPORT_SYMBOL_GPL();

static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream,
				  int cmd, bool fe_first)
{}

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

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

int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
{}

static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
{}

static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
{}

static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
{}

static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new)
{}

/* Called by DAPM mixer/mux changes to update audio routing between PCMs and
 * any DAI links.
 */
int snd_soc_dpcm_runtime_update(struct snd_soc_card *card)
{}
EXPORT_SYMBOL_GPL();

static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream)
{}

static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
{}

static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
{}

static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
				    int *playback, int *capture)
{}

static int soc_create_pcm(struct snd_pcm **pcm,
			  struct snd_soc_pcm_runtime *rtd,
			  int playback, int capture, int num)
{}

/* create a new pcm */
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
{}

/* is the current PCM operation for this FE ? */
int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream)
{}
EXPORT_SYMBOL_GPL();

/* is the current PCM operation for this BE ? */
int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
		struct snd_soc_pcm_runtime *be, int stream)
{}
EXPORT_SYMBOL_GPL();

/* get the substream for this BE */
struct snd_pcm_substream *
	snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream)
{}
EXPORT_SYMBOL_GPL();

static int snd_soc_dpcm_check_state(struct snd_soc_pcm_runtime *fe,
				    struct snd_soc_pcm_runtime *be,
				    int stream,
				    const enum snd_soc_dpcm_state *states,
				    int num_states)
{}

/*
 * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE
 * are not running, paused or suspended for the specified stream direction.
 */
int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
		struct snd_soc_pcm_runtime *be, int stream)
{}
EXPORT_SYMBOL_GPL();

/*
 * We can only change hw params a BE DAI if any of it's FE are not prepared,
 * running, paused or suspended for the specified stream direction.
 */
int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
		struct snd_soc_pcm_runtime *be, int stream)
{}
EXPORT_SYMBOL_GPL();

/*
 * We can only prepare a BE DAI if any of it's FE are not prepared,
 * running or paused for the specified stream direction.
 */
int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
				 struct snd_soc_pcm_runtime *be, int stream)
{}
EXPORT_SYMBOL_GPL();