Linux Audio

Check our new training course

Loading...
v4.17
  1/*
 
  2 * linux/sound/soc-dpcm.h -- ALSA SoC Dynamic PCM Support
  3 *
  4 * Author:		Liam Girdwood <lrg@ti.com>
  5 *
  6 * This program is free software; you can redistribute it and/or modify
  7 * it under the terms of the GNU General Public License version 2 as
  8 * published by the Free Software Foundation.
  9 */
 10
 11#ifndef __LINUX_SND_SOC_DPCM_H
 12#define __LINUX_SND_SOC_DPCM_H
 13
 14#include <linux/slab.h>
 15#include <linux/list.h>
 16#include <sound/pcm.h>
 17
 18struct snd_soc_pcm_runtime;
 19
 20/*
 21 * Types of runtime_update to perform. e.g. originated from FE PCM ops
 22 * or audio route changes triggered by muxes/mixers.
 23 */
 24enum snd_soc_dpcm_update {
 25	SND_SOC_DPCM_UPDATE_NO	= 0,
 26	SND_SOC_DPCM_UPDATE_BE,
 27	SND_SOC_DPCM_UPDATE_FE,
 28};
 29
 30/*
 31 * Dynamic PCM Frontend -> Backend link management states.
 32 */
 33enum snd_soc_dpcm_link_state {
 34	SND_SOC_DPCM_LINK_STATE_NEW	= 0,	/* newly created link */
 35	SND_SOC_DPCM_LINK_STATE_FREE,		/* link to be dismantled */
 36};
 37
 38/*
 39 * Dynamic PCM Frontend -> Backend link PCM states.
 40 */
 41enum snd_soc_dpcm_state {
 42	SND_SOC_DPCM_STATE_NEW	= 0,
 43	SND_SOC_DPCM_STATE_OPEN,
 44	SND_SOC_DPCM_STATE_HW_PARAMS,
 45	SND_SOC_DPCM_STATE_PREPARE,
 46	SND_SOC_DPCM_STATE_START,
 47	SND_SOC_DPCM_STATE_STOP,
 48	SND_SOC_DPCM_STATE_PAUSED,
 49	SND_SOC_DPCM_STATE_SUSPEND,
 50	SND_SOC_DPCM_STATE_HW_FREE,
 51	SND_SOC_DPCM_STATE_CLOSE,
 52};
 53
 54/*
 55 * Dynamic PCM trigger ordering. Triggering flexibility is required as some
 56 * DSPs require triggering before/after their CPU platform and DAIs.
 57 *
 58 * i.e. some clients may want to manually order this call in their PCM
 59 * trigger() whilst others will just use the regular core ordering.
 60 */
 61enum snd_soc_dpcm_trigger {
 62	SND_SOC_DPCM_TRIGGER_PRE		= 0,
 63	SND_SOC_DPCM_TRIGGER_POST,
 64	SND_SOC_DPCM_TRIGGER_BESPOKE,
 65};
 66
 67/*
 68 * Dynamic PCM link
 69 * This links together a FE and BE DAI at runtime and stores the link
 70 * state information and the hw_params configuration.
 71 */
 72struct snd_soc_dpcm {
 73	/* FE and BE DAIs*/
 74	struct snd_soc_pcm_runtime *be;
 75	struct snd_soc_pcm_runtime *fe;
 76
 77	/* link state */
 78	enum snd_soc_dpcm_link_state state;
 79
 80	/* list of BE and FE for this DPCM link */
 81	struct list_head list_be;
 82	struct list_head list_fe;
 83
 84	/* hw params for this link - may be different for each link */
 85	struct snd_pcm_hw_params hw_params;
 86#ifdef CONFIG_DEBUG_FS
 87	struct dentry *debugfs_state;
 88#endif
 89};
 90
 91/*
 92 * Dynamic PCM runtime data.
 93 */
 94struct snd_soc_dpcm_runtime {
 95	struct list_head be_clients;
 96	struct list_head fe_clients;
 97
 98	int users;
 99	struct snd_pcm_runtime *runtime;
100	struct snd_pcm_hw_params hw_params;
101
102	/* state and update */
103	enum snd_soc_dpcm_update runtime_update;
104	enum snd_soc_dpcm_state state;
105
106	int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */
 
 
 
 
107};
108
 
 
 
 
 
 
 
 
 
 
109/* can this BE stop and free */
110int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
111		struct snd_soc_pcm_runtime *be, int stream);
112
113/* can this BE perform a hw_params() */
114int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
115		struct snd_soc_pcm_runtime *be, int stream);
116
 
 
 
 
117/* is the current PCM operation for this FE ? */
118int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
119
120/* is the current PCM operation for this BE ? */
121int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
122		struct snd_soc_pcm_runtime *be, int stream);
123
124/* get the substream for this BE */
125struct snd_pcm_substream *
126	snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
127
128/* get the BE runtime state */
129enum snd_soc_dpcm_state
130	snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream);
131
132/* set the BE runtime state */
133void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
134	enum snd_soc_dpcm_state state);
135
136/* internal use only */
137int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
138void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
139int soc_dpcm_runtime_update(struct snd_soc_card *);
 
 
 
 
140
141int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
142	int stream, struct snd_soc_dapm_widget_list **list_);
 
143int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
144	int stream, struct snd_soc_dapm_widget_list **list, int new);
145int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
146int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream);
 
147void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream);
148void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream);
149int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
150int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream);
151int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd);
152int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
153int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
154	int event);
155
156static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
157{
158	kfree(*list);
159}
160
 
 
161
162#endif
v6.8
  1/* SPDX-License-Identifier: GPL-2.0
  2 *
  3 * linux/sound/soc-dpcm.h -- ALSA SoC Dynamic PCM Support
  4 *
  5 * Author:		Liam Girdwood <lrg@ti.com>
 
 
 
 
  6 */
  7
  8#ifndef __LINUX_SND_SOC_DPCM_H
  9#define __LINUX_SND_SOC_DPCM_H
 10
 11#include <linux/slab.h>
 12#include <linux/list.h>
 13#include <sound/pcm.h>
 14
 15struct snd_soc_pcm_runtime;
 16
 17/*
 18 * Types of runtime_update to perform. e.g. originated from FE PCM ops
 19 * or audio route changes triggered by muxes/mixers.
 20 */
 21enum snd_soc_dpcm_update {
 22	SND_SOC_DPCM_UPDATE_NO	= 0,
 23	SND_SOC_DPCM_UPDATE_BE,
 24	SND_SOC_DPCM_UPDATE_FE,
 25};
 26
 27/*
 28 * Dynamic PCM Frontend -> Backend link management states.
 29 */
 30enum snd_soc_dpcm_link_state {
 31	SND_SOC_DPCM_LINK_STATE_NEW	= 0,	/* newly created link */
 32	SND_SOC_DPCM_LINK_STATE_FREE,		/* link to be dismantled */
 33};
 34
 35/*
 36 * Dynamic PCM Frontend -> Backend link PCM states.
 37 */
 38enum snd_soc_dpcm_state {
 39	SND_SOC_DPCM_STATE_NEW	= 0,
 40	SND_SOC_DPCM_STATE_OPEN,
 41	SND_SOC_DPCM_STATE_HW_PARAMS,
 42	SND_SOC_DPCM_STATE_PREPARE,
 43	SND_SOC_DPCM_STATE_START,
 44	SND_SOC_DPCM_STATE_STOP,
 45	SND_SOC_DPCM_STATE_PAUSED,
 46	SND_SOC_DPCM_STATE_SUSPEND,
 47	SND_SOC_DPCM_STATE_HW_FREE,
 48	SND_SOC_DPCM_STATE_CLOSE,
 49};
 50
 51/*
 52 * Dynamic PCM trigger ordering. Triggering flexibility is required as some
 53 * DSPs require triggering before/after their CPU platform and DAIs.
 54 *
 55 * i.e. some clients may want to manually order this call in their PCM
 56 * trigger() whilst others will just use the regular core ordering.
 57 */
 58enum snd_soc_dpcm_trigger {
 59	SND_SOC_DPCM_TRIGGER_PRE		= 0,
 60	SND_SOC_DPCM_TRIGGER_POST,
 61	SND_SOC_DPCM_TRIGGER_BESPOKE,
 62};
 63
 64/*
 65 * Dynamic PCM link
 66 * This links together a FE and BE DAI at runtime and stores the link
 67 * state information and the hw_params configuration.
 68 */
 69struct snd_soc_dpcm {
 70	/* FE and BE DAIs*/
 71	struct snd_soc_pcm_runtime *be;
 72	struct snd_soc_pcm_runtime *fe;
 73
 74	/* link state */
 75	enum snd_soc_dpcm_link_state state;
 76
 77	/* list of BE and FE for this DPCM link */
 78	struct list_head list_be;
 79	struct list_head list_fe;
 80
 
 
 81#ifdef CONFIG_DEBUG_FS
 82	struct dentry *debugfs_state;
 83#endif
 84};
 85
 86/*
 87 * Dynamic PCM runtime data.
 88 */
 89struct snd_soc_dpcm_runtime {
 90	struct list_head be_clients;
 91	struct list_head fe_clients;
 92
 93	int users;
 
 94	struct snd_pcm_hw_params hw_params;
 95
 96	/* state and update */
 97	enum snd_soc_dpcm_update runtime_update;
 98	enum snd_soc_dpcm_state state;
 99
100	int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */
101
102	int be_start; /* refcount protected by BE stream pcm lock */
103	int be_pause; /* refcount protected by BE stream pcm lock */
104	bool fe_pause; /* used to track STOP after PAUSE */
105};
106
107#define for_each_dpcm_fe(be, stream, _dpcm)				\
108	list_for_each_entry(_dpcm, &(be)->dpcm[stream].fe_clients, list_fe)
109
110#define for_each_dpcm_be(fe, stream, _dpcm)				\
111	list_for_each_entry(_dpcm, &(fe)->dpcm[stream].be_clients, list_be)
112#define for_each_dpcm_be_safe(fe, stream, _dpcm, __dpcm)			\
113	list_for_each_entry_safe(_dpcm, __dpcm, &(fe)->dpcm[stream].be_clients, list_be)
114#define for_each_dpcm_be_rollback(fe, stream, _dpcm)			\
115	list_for_each_entry_continue_reverse(_dpcm, &(fe)->dpcm[stream].be_clients, list_be)
116
117/* can this BE stop and free */
118int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
119		struct snd_soc_pcm_runtime *be, int stream);
120
121/* can this BE perform a hw_params() */
122int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
123		struct snd_soc_pcm_runtime *be, int stream);
124
125/* can this BE perform prepare */
126int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
127				 struct snd_soc_pcm_runtime *be, int stream);
128
129/* is the current PCM operation for this FE ? */
130int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
131
132/* is the current PCM operation for this BE ? */
133int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
134		struct snd_soc_pcm_runtime *be, int stream);
135
136/* get the substream for this BE */
137struct snd_pcm_substream *
138	snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
139
140/* update audio routing between PCMs and any DAI links */
141int snd_soc_dpcm_runtime_update(struct snd_soc_card *card);
 
 
 
 
 
142
143#ifdef CONFIG_DEBUG_FS
 
144void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
145#else
146static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
147{
148}
149#endif
150
151int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
152	int stream, struct snd_soc_dapm_widget_list **list_);
153void dpcm_path_put(struct snd_soc_dapm_widget_list **list);
154int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
155	int stream, struct snd_soc_dapm_widget_list **list, int new);
156int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
157void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
158		      int do_hw_free, struct snd_soc_dpcm *last);
159void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream);
160void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream);
161void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
162int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream);
163int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd);
164int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream);
165int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
166	int event);
167bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir);
168int widget_in_list(struct snd_soc_dapm_widget_list *list,
169		   struct snd_soc_dapm_widget *widget);
170
171#define dpcm_be_dai_startup_rollback(fe, stream, last)	\
172						dpcm_be_dai_stop(fe, stream, 0, last)
173#define dpcm_be_dai_startup_unwind(fe, stream)	dpcm_be_dai_stop(fe, stream, 0, NULL)
174#define dpcm_be_dai_shutdown(fe, stream)	dpcm_be_dai_stop(fe, stream, 1, NULL)
175
176#endif