summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-pcm.c
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2020-02-24 21:48:25 +0000
committerMark Brown <broonie@kernel.org>2020-02-24 21:48:25 +0000
commit6bff73c6115d088fee4d09aff65e145b990382eb (patch)
tree1ed2b6350e794c49f389f0fec2c7e1234941ed3b /sound/soc/soc-pcm.c
parentd2aaa8d8bfba93237ac944ee058fb98e2c2ef983 (diff)
parent154dae87e73faa6d56265f22cae16dcdcea3dbb0 (diff)
ASoC: soc-pcm cleanup step4
Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>: Hi Mark These are soc-pcm cleanup step4. [01/13] - [06/13] are posted but not yet accepted patches. To avoid conflict, I merged these into step4. These patches are already received Reviewed-by from Pierre-Louis. Subject: [PATCH 0/6] ASoC: use for_each_rtd_codec_dai() macro Date: Thu, 13 Feb 2020 13:08:07 +0900 Kuninori Morimoto (13): 1) ASoC: soundwaire: qcom: use for_each_rtd_codec_dai() macro 2) ASoC: qcom: sdm845: use for_each_rtd_codec_dai() macro 3) ASoC: qcom: apq8016_sbc: use for_each_rtd_codec_dai() macro 4) ASoC: intel: cml_rt1011_rt5682: use for_each_rtd_codec_dai() macro 5) ASoC: intel: kbl_da7219_max98927: use for_each_rtd_codec_dai() macro 6) ASoC: mediatek: mt8183-da7219-max98357: use for_each_rtd_codec_dai() macro 7) ASoC: soc-pcm: add snd_soc_dai_get_pcm_stream() 8) ASoC: soc-pcm: cleanup soc_pcm_apply_msb() 9) ASoC: soc-pcm: add snd_soc_dai_get_widget() 10) ASoC: soc-pcm: merge dpcm_run_new/old_update() into dpcm_fe_runtime_update() 11) ASoC: soc-pcm: move dpcm_path_put() to soc-pcm.c 12) ASoC: soc-pcm: move CONFIG_DEBUG_FS functions to top side 13) ASoC: soc-pcm: add dpcm_create/remove_debugfs_state() drivers/soundwire/qcom.c | 7 +- include/sound/soc-dai.h | 15 + include/sound/soc-dapm.h | 1 + include/sound/soc-dpcm.h | 7 +- sound/soc/intel/boards/cml_rt1011_rt5682.c | 3 +- sound/soc/intel/boards/kbl_da7219_max98927.c | 8 +- sound/soc/intel/skylake/skl-pcm.c | 10 +- .../mediatek/mt8183/mt8183-da7219-max98357.c | 8 +- sound/soc/qcom/apq8016_sbc.c | 7 +- sound/soc/qcom/sdm845.c | 20 +- sound/soc/soc-dai.c | 7 +- sound/soc/soc-dapm.c | 20 +- sound/soc/soc-pcm.c | 462 ++++++++---------- 13 files changed, 266 insertions(+), 309 deletions(-) -- 2.17.1 Thank you for your help !! Best regards --- Kuninori Morimoto
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r--sound/soc/soc-pcm.c462
1 files changed, 209 insertions, 253 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 235baeb2d56a..00b65a5a9a98 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -28,6 +28,174 @@
#define DPCM_MAX_BE_USERS 8
+#ifdef CONFIG_DEBUG_FS
+static const char *dpcm_state_string(enum snd_soc_dpcm_state state)
+{
+ switch (state) {
+ case SND_SOC_DPCM_STATE_NEW:
+ return "new";
+ case SND_SOC_DPCM_STATE_OPEN:
+ return "open";
+ case SND_SOC_DPCM_STATE_HW_PARAMS:
+ return "hw_params";
+ case SND_SOC_DPCM_STATE_PREPARE:
+ return "prepare";
+ case SND_SOC_DPCM_STATE_START:
+ return "start";
+ case SND_SOC_DPCM_STATE_STOP:
+ return "stop";
+ case SND_SOC_DPCM_STATE_SUSPEND:
+ return "suspend";
+ case SND_SOC_DPCM_STATE_PAUSED:
+ return "paused";
+ case SND_SOC_DPCM_STATE_HW_FREE:
+ return "hw_free";
+ case SND_SOC_DPCM_STATE_CLOSE:
+ return "close";
+ }
+
+ return "unknown";
+}
+
+static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
+ int stream, char *buf, size_t size)
+{
+ struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
+ struct snd_soc_dpcm *dpcm;
+ ssize_t offset = 0;
+ unsigned long flags;
+
+ /* FE state */
+ offset += snprintf(buf + offset, size - offset,
+ "[%s - %s]\n", fe->dai_link->name,
+ stream ? "Capture" : "Playback");
+
+ offset += snprintf(buf + offset, size - offset, "State: %s\n",
+ dpcm_state_string(fe->dpcm[stream].state));
+
+ if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
+ offset += snprintf(buf + offset, size - offset,
+ "Hardware Params: "
+ "Format = %s, Channels = %d, Rate = %d\n",
+ snd_pcm_format_name(params_format(params)),
+ params_channels(params),
+ params_rate(params));
+
+ /* BEs state */
+ offset += snprintf(buf + offset, size - offset, "Backends:\n");
+
+ if (list_empty(&fe->dpcm[stream].be_clients)) {
+ offset += snprintf(buf + offset, size - offset,
+ " No active DSP links\n");
+ goto out;
+ }
+
+ spin_lock_irqsave(&fe->card->dpcm_lock, flags);
+ for_each_dpcm_be(fe, stream, dpcm) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ params = &dpcm->hw_params;
+
+ offset += snprintf(buf + offset, size - offset,
+ "- %s\n", be->dai_link->name);
+
+ offset += snprintf(buf + offset, size - offset,
+ " State: %s\n",
+ dpcm_state_string(be->dpcm[stream].state));
+
+ if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
+ offset += snprintf(buf + offset, size - offset,
+ " Hardware Params: "
+ "Format = %s, Channels = %d, Rate = %d\n",
+ snd_pcm_format_name(params_format(params)),
+ params_channels(params),
+ params_rate(params));
+ }
+ spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
+out:
+ return offset;
+}
+
+static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct snd_soc_pcm_runtime *fe = file->private_data;
+ ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
+ int stream;
+ char *buf;
+
+ buf = kmalloc(out_count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ for_each_pcm_streams(stream)
+ if (snd_soc_dai_stream_valid(fe->cpu_dai, stream))
+ offset += dpcm_show_state(fe, stream,
+ buf + offset,
+ out_count - offset);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
+
+ kfree(buf);
+ return ret;
+}
+
+static const struct file_operations dpcm_state_fops = {
+ .open = simple_open,
+ .read = dpcm_state_read_file,
+ .llseek = default_llseek,
+};
+
+void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
+{
+ if (!rtd->dai_link)
+ return;
+
+ if (!rtd->dai_link->dynamic)
+ return;
+
+ if (!rtd->card->debugfs_card_root)
+ return;
+
+ rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
+ rtd->card->debugfs_card_root);
+
+ debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root,
+ rtd, &dpcm_state_fops);
+}
+
+static void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm, int stream)
+{
+ char *name;
+
+ name = kasprintf(GFP_KERNEL, "%s:%s", dpcm->be->dai_link->name,
+ stream ? "capture" : "playback");
+ if (name) {
+ dpcm->debugfs_state = debugfs_create_dir(
+ name, dpcm->fe->debugfs_dpcm_root);
+ debugfs_create_u32("state", 0644, dpcm->debugfs_state,
+ &dpcm->state);
+ kfree(name);
+ }
+}
+
+static void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
+{
+ debugfs_remove_recursive(dpcm->debugfs_state);
+}
+
+#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
+
static int soc_rtd_startup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_substream *substream)
{
@@ -82,15 +250,6 @@ static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd,
return 0;
}
-static inline
-struct snd_soc_dapm_widget *dai_get_widget(struct snd_soc_dai *dai, int stream)
-{
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- return dai->playback_widget;
- else
- return dai->capture_widget;
-}
-
static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
int stream, int action)
{
@@ -363,29 +522,24 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai;
+ struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu;
+ int stream = substream->stream;
int i;
unsigned int bits = 0, cpu_bits;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- for_each_rtd_codec_dai(rtd, i, codec_dai) {
- if (codec_dai->driver->playback.sig_bits == 0) {
- bits = 0;
- break;
- }
- bits = max(codec_dai->driver->playback.sig_bits, bits);
- }
- cpu_bits = cpu_dai->driver->playback.sig_bits;
- } else {
- for_each_rtd_codec_dai(rtd, i, codec_dai) {
- if (codec_dai->driver->capture.sig_bits == 0) {
- bits = 0;
- break;
- }
- bits = max(codec_dai->driver->capture.sig_bits, bits);
+ for_each_rtd_codec_dai(rtd, i, codec_dai) {
+ pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream);
+
+ if (pcm_codec->sig_bits == 0) {
+ bits = 0;
+ break;
}
- cpu_bits = cpu_dai->driver->capture.sig_bits;
+ bits = max(pcm_codec->sig_bits, bits);
}
+ pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
+ cpu_bits = pcm_cpu->sig_bits;
+
soc_pcm_set_msb(substream, bits);
soc_pcm_set_msb(substream, cpu_bits);
}
@@ -396,20 +550,16 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
struct snd_pcm_hardware *hw = &runtime->hw;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai;
- struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver;
- struct snd_soc_dai_driver *codec_dai_drv;
struct snd_soc_pcm_stream *codec_stream;
struct snd_soc_pcm_stream *cpu_stream;
unsigned int chan_min = 0, chan_max = UINT_MAX;
unsigned int rate_min = 0, rate_max = UINT_MAX;
unsigned int rates = UINT_MAX;
u64 formats = ULLONG_MAX;
+ int stream = substream->stream;
int i;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cpu_stream = &cpu_dai_drv->playback;
- else
- cpu_stream = &cpu_dai_drv->capture;
+ cpu_stream = snd_soc_dai_get_pcm_stream(rtd->cpu_dai, stream);
/* first calculate min/max only for CODECs in the DAI link */
for_each_rtd_codec_dai(rtd, i, codec_dai) {
@@ -427,11 +577,8 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
substream->stream))
continue;
- codec_dai_drv = codec_dai->driver;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- codec_stream = &codec_dai_drv->playback;
- else
- codec_stream = &codec_dai_drv->capture;
+ codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream);
+
chan_min = max(chan_min, codec_stream->channels_min);
chan_max = min(chan_max, codec_stream->channels_max);
rate_min = max(rate_min, codec_stream->rate_min);
@@ -1152,9 +1299,6 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
{
struct snd_soc_dpcm *dpcm;
unsigned long flags;
-#ifdef CONFIG_DEBUG_FS
- char *name;
-#endif
/* only add new dpcms */
for_each_dpcm_be(fe, stream, dpcm) {
@@ -1179,17 +1323,8 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
stream ? "capture" : "playback", fe->dai_link->name,
stream ? "<-" : "->", be->dai_link->name);
-#ifdef CONFIG_DEBUG_FS
- name = kasprintf(GFP_KERNEL, "%s:%s", be->dai_link->name,
- stream ? "capture" : "playback");
- if (name) {
- dpcm->debugfs_state = debugfs_create_dir(name,
- fe->debugfs_dpcm_root);
- debugfs_create_u32("state", 0644, dpcm->debugfs_state,
- &dpcm->state);
- kfree(name);
- }
-#endif
+ dpcm_create_debugfs_state(dpcm, stream);
+
return 1;
}
@@ -1242,9 +1377,8 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
/* BEs still alive need new FE */
dpcm_be_reparent(fe, dpcm->be, stream);
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove_recursive(dpcm->debugfs_state);
-#endif
+ dpcm_remove_debugfs_state(dpcm);
+
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
list_del(&dpcm->list_be);
list_del(&dpcm->list_fe);
@@ -1269,7 +1403,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
if (!be->dai_link->no_pcm)
continue;
- w = dai_get_widget(be->cpu_dai, stream);
+ w = snd_soc_dai_get_widget(be->cpu_dai, stream);
dev_dbg(card->dev, "ASoC: try BE : %s\n",
w ? w->name : "(not set)");
@@ -1278,7 +1412,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
return be;
for_each_rtd_codec_dai(be, i, dai) {
- w = dai_get_widget(dai, stream);
+ w = snd_soc_dai_get_widget(dai, stream);
if (w == widget)
return be;
@@ -1338,6 +1472,11 @@ int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
return paths;
}
+void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
+{
+ snd_soc_dapm_dai_free_widgets(list);
+}
+
static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
struct snd_soc_dapm_widget_list **list_)
{
@@ -1353,7 +1492,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
unsigned int i;
/* is there a valid CPU DAI widget for this BE */
- widget = dai_get_widget(dpcm->be->cpu_dai, stream);
+ widget = snd_soc_dai_get_widget(dpcm->be->cpu_dai, stream);
/* prune the BE if it's no longer in our active list */
if (widget && widget_in_list(list, widget))
@@ -1362,7 +1501,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
/* is there a valid CODEC DAI widget for this BE */
do_prune = 1;
for_each_rtd_codec_dai(dpcm->be, i, dai) {
- widget = dai_get_widget(dai, stream);
+ widget = snd_soc_dai_get_widget(dai, stream);
/* prune the BE if it's no longer in our active list */
if (widget && widget_in_list(list, widget))
@@ -1615,7 +1754,6 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream,
for_each_dpcm_be(fe, stream, dpcm) {
struct snd_soc_pcm_runtime *be = dpcm->be;
- struct snd_soc_dai_driver *codec_dai_drv;
struct snd_soc_pcm_stream *codec_stream;
int i;
@@ -1627,11 +1765,7 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream,
if (!snd_soc_dai_stream_valid(dai, stream))
continue;
- codec_dai_drv = dai->driver;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- codec_stream = &codec_dai_drv->playback;
- else
- codec_stream = &codec_dai_drv->capture;
+ codec_stream = snd_soc_dai_get_pcm_stream(dai, stream);
*formats &= codec_stream->formats;
}
@@ -1656,15 +1790,10 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
for_each_dpcm_be(fe, stream, dpcm) {
struct snd_soc_pcm_runtime *be = dpcm->be;
- struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver;
- struct snd_soc_dai_driver *codec_dai_drv;
struct snd_soc_pcm_stream *codec_stream;
struct snd_soc_pcm_stream *cpu_stream;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- cpu_stream = &cpu_dai_drv->playback;
- else
- cpu_stream = &cpu_dai_drv->capture;
+ cpu_stream = snd_soc_dai_get_pcm_stream(be->cpu_dai, stream);
*channels_min = max(*channels_min, cpu_stream->channels_min);
*channels_max = min(*channels_max, cpu_stream->channels_max);
@@ -1674,12 +1803,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
* DAIs connected to a single CPU DAI, use CPU DAI's directly
*/
if (be->num_codecs == 1) {
- codec_dai_drv = be->codec_dais[0]->driver;
-
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- codec_stream = &codec_dai_drv->playback;
- else
- codec_stream = &codec_dai_drv->capture;
+ codec_stream = snd_soc_dai_get_pcm_stream(be->codec_dais[0], stream);
*channels_min = max(*channels_min,
codec_stream->channels_min);
@@ -1708,17 +1832,12 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
for_each_dpcm_be(fe, stream, dpcm) {
struct snd_soc_pcm_runtime *be = dpcm->be;
- struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver;
- struct snd_soc_dai_driver *codec_dai_drv;
struct snd_soc_pcm_stream *codec_stream;
struct snd_soc_pcm_stream *cpu_stream;
struct snd_soc_dai *dai;
int i;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- cpu_stream = &cpu_dai_drv->playback;
- else
- cpu_stream = &cpu_dai_drv->capture;
+ cpu_stream = snd_soc_dai_get_pcm_stream(be->cpu_dai, stream);
*rate_min = max(*rate_min, cpu_stream->rate_min);
*rate_max = min_not_zero(*rate_max, cpu_stream->rate_max);
@@ -1732,11 +1851,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
if (!snd_soc_dai_stream_valid(dai, stream))
continue;
- codec_dai_drv = dai->driver;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- codec_stream = &codec_dai_drv->playback;
- else
- codec_stream = &codec_dai_drv->capture;
+ codec_stream = snd_soc_dai_get_pcm_stream(dai, stream);
*rate_min = max(*rate_min, codec_stream->rate_min);
*rate_max = min_not_zero(*rate_max,
@@ -2596,37 +2711,12 @@ disconnect:
return ret;
}
-static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
-{
- int ret;
-
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
- ret = dpcm_run_update_startup(fe, stream);
- if (ret < 0)
- dev_err(fe->dev, "ASoC: failed to startup some BEs\n");
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
-
- return ret;
-}
-
-static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
-{
- int ret;
-
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
- ret = dpcm_run_update_shutdown(fe, stream);
- if (ret < 0)
- dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n");
- dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
-
- return ret;
-}
-
static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new)
{
struct snd_soc_dapm_widget_list *list;
int stream;
int count, paths;
+ int ret;
if (!fe->dai_link->dynamic)
return 0;
@@ -2663,10 +2753,14 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new)
/* update any playback/capture paths */
count = dpcm_process_paths(fe, stream, &list, new);
if (count) {
+ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
if (new)
- dpcm_run_new_update(fe, stream);
+ ret = dpcm_run_update_startup(fe, stream);
else
- dpcm_run_old_update(fe, stream);
+ ret = dpcm_run_update_shutdown(fe, stream);
+ if (ret < 0)
+ dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n");
+ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
dpcm_clear_pending_state(fe, stream);
dpcm_be_disconnect(fe, stream);
@@ -3006,141 +3100,3 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
}
EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
-
-#ifdef CONFIG_DEBUG_FS
-static const char *dpcm_state_string(enum snd_soc_dpcm_state state)
-{
- switch (state) {
- case SND_SOC_DPCM_STATE_NEW:
- return "new";
- case SND_SOC_DPCM_STATE_OPEN:
- return "open";
- case SND_SOC_DPCM_STATE_HW_PARAMS:
- return "hw_params";
- case SND_SOC_DPCM_STATE_PREPARE:
- return "prepare";
- case SND_SOC_DPCM_STATE_START:
- return "start";
- case SND_SOC_DPCM_STATE_STOP:
- return "stop";
- case SND_SOC_DPCM_STATE_SUSPEND:
- return "suspend";
- case SND_SOC_DPCM_STATE_PAUSED:
- return "paused";
- case SND_SOC_DPCM_STATE_HW_FREE:
- return "hw_free";
- case SND_SOC_DPCM_STATE_CLOSE:
- return "close";
- }
-
- return "unknown";
-}
-
-static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
- int stream, char *buf, size_t size)
-{
- struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
- struct snd_soc_dpcm *dpcm;
- ssize_t offset = 0;
- unsigned long flags;
-
- /* FE state */
- offset += snprintf(buf + offset, size - offset,
- "[%s - %s]\n", fe->dai_link->name,
- stream ? "Capture" : "Playback");
-
- offset += snprintf(buf + offset, size - offset, "State: %s\n",
- dpcm_state_string(fe->dpcm[stream].state));
-
- if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
- (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
- offset += snprintf(buf + offset, size - offset,
- "Hardware Params: "
- "Format = %s, Channels = %d, Rate = %d\n",
- snd_pcm_format_name(params_format(params)),
- params_channels(params),
- params_rate(params));
-
- /* BEs state */
- offset += snprintf(buf + offset, size - offset, "Backends:\n");
-
- if (list_empty(&fe->dpcm[stream].be_clients)) {
- offset += snprintf(buf + offset, size - offset,
- " No active DSP links\n");
- goto out;
- }
-
- spin_lock_irqsave(&fe->card->dpcm_lock, flags);
- for_each_dpcm_be(fe, stream, dpcm) {
- struct snd_soc_pcm_runtime *be = dpcm->be;
- params = &dpcm->hw_params;
-
- offset += snprintf(buf + offset, size - offset,
- "- %s\n", be->dai_link->name);
-
- offset += snprintf(buf + offset, size - offset,
- " State: %s\n",
- dpcm_state_string(be->dpcm[stream].state));
-
- if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
- (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
- offset += snprintf(buf + offset, size - offset,
- " Hardware Params: "
- "Format = %s, Channels = %d, Rate = %d\n",
- snd_pcm_format_name(params_format(params)),
- params_channels(params),
- params_rate(params));
- }
- spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
-out:
- return offset;
-}
-
-static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct snd_soc_pcm_runtime *fe = file->private_data;
- ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
- int stream;
- char *buf;
-
- buf = kmalloc(out_count, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- for_each_pcm_streams(stream)
- if (snd_soc_dai_stream_valid(fe->cpu_dai, stream))
- offset += dpcm_show_state(fe, stream,
- buf + offset,
- out_count - offset);
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
-
- kfree(buf);
- return ret;
-}
-
-static const struct file_operations dpcm_state_fops = {
- .open = simple_open,
- .read = dpcm_state_read_file,
- .llseek = default_llseek,
-};
-
-void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
-{
- if (!rtd->dai_link)
- return;
-
- if (!rtd->dai_link->dynamic)
- return;
-
- if (!rtd->card->debugfs_card_root)
- return;
-
- rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
- rtd->card->debugfs_card_root);
-
- debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root,
- rtd, &dpcm_state_fops);
-}
-#endif