aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r--sound/soc/soc-pcm.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 458f116aa570..a1d4426a99d9 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -23,6 +23,7 @@
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <linux/export.h> 25#include <linux/export.h>
26#include <linux/debugfs.h>
26#include <sound/core.h> 27#include <sound/core.h>
27#include <sound/pcm.h> 28#include <sound/pcm.h>
28#include <sound/pcm_params.h> 29#include <sound/pcm_params.h>
@@ -690,6 +691,10 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
690 stream ? "capture" : "playback", fe->dai_link->name, 691 stream ? "capture" : "playback", fe->dai_link->name,
691 stream ? "<-" : "->", be->dai_link->name); 692 stream ? "<-" : "->", be->dai_link->name);
692 693
694#ifdef CONFIG_DEBUG_FS
695 dpcm->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644,
696 fe->debugfs_dpcm_root, &dpcm->state);
697#endif
693 return 1; 698 return 1;
694} 699}
695 700
@@ -741,6 +746,9 @@ static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
741 /* BEs still alive need new FE */ 746 /* BEs still alive need new FE */
742 dpcm_be_reparent(fe, dpcm->be, stream); 747 dpcm_be_reparent(fe, dpcm->be, stream);
743 748
749#ifdef CONFIG_DEBUG_FS
750 debugfs_remove(dpcm->debugfs_state);
751#endif
744 list_del(&dpcm->list_be); 752 list_del(&dpcm->list_be);
745 list_del(&dpcm->list_fe); 753 list_del(&dpcm->list_fe);
746 kfree(dpcm); 754 kfree(dpcm);
@@ -1890,3 +1898,147 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
1890 return 1; 1898 return 1;
1891} 1899}
1892EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); 1900EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
1901
1902#ifdef CONFIG_DEBUG_FS
1903static char *dpcm_state_string(enum snd_soc_dpcm_state state)
1904{
1905 switch (state) {
1906 case SND_SOC_DPCM_STATE_NEW:
1907 return "new";
1908 case SND_SOC_DPCM_STATE_OPEN:
1909 return "open";
1910 case SND_SOC_DPCM_STATE_HW_PARAMS:
1911 return "hw_params";
1912 case SND_SOC_DPCM_STATE_PREPARE:
1913 return "prepare";
1914 case SND_SOC_DPCM_STATE_START:
1915 return "start";
1916 case SND_SOC_DPCM_STATE_STOP:
1917 return "stop";
1918 case SND_SOC_DPCM_STATE_SUSPEND:
1919 return "suspend";
1920 case SND_SOC_DPCM_STATE_PAUSED:
1921 return "paused";
1922 case SND_SOC_DPCM_STATE_HW_FREE:
1923 return "hw_free";
1924 case SND_SOC_DPCM_STATE_CLOSE:
1925 return "close";
1926 }
1927
1928 return "unknown";
1929}
1930
1931static int dpcm_state_open_file(struct inode *inode, struct file *file)
1932{
1933 file->private_data = inode->i_private;
1934 return 0;
1935}
1936
1937static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
1938 int stream, char *buf, size_t size)
1939{
1940 struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
1941 struct snd_soc_dpcm *dpcm;
1942 ssize_t offset = 0;
1943
1944 /* FE state */
1945 offset += snprintf(buf + offset, size - offset,
1946 "[%s - %s]\n", fe->dai_link->name,
1947 stream ? "Capture" : "Playback");
1948
1949 offset += snprintf(buf + offset, size - offset, "State: %s\n",
1950 dpcm_state_string(fe->dpcm[stream].state));
1951
1952 if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
1953 (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
1954 offset += snprintf(buf + offset, size - offset,
1955 "Hardware Params: "
1956 "Format = %s, Channels = %d, Rate = %d\n",
1957 snd_pcm_format_name(params_format(params)),
1958 params_channels(params),
1959 params_rate(params));
1960
1961 /* BEs state */
1962 offset += snprintf(buf + offset, size - offset, "Backends:\n");
1963
1964 if (list_empty(&fe->dpcm[stream].be_clients)) {
1965 offset += snprintf(buf + offset, size - offset,
1966 " No active DSP links\n");
1967 goto out;
1968 }
1969
1970 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1971 struct snd_soc_pcm_runtime *be = dpcm->be;
1972 params = &dpcm->hw_params;
1973
1974 offset += snprintf(buf + offset, size - offset,
1975 "- %s\n", be->dai_link->name);
1976
1977 offset += snprintf(buf + offset, size - offset,
1978 " State: %s\n",
1979 dpcm_state_string(be->dpcm[stream].state));
1980
1981 if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
1982 (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
1983 offset += snprintf(buf + offset, size - offset,
1984 " Hardware Params: "
1985 "Format = %s, Channels = %d, Rate = %d\n",
1986 snd_pcm_format_name(params_format(params)),
1987 params_channels(params),
1988 params_rate(params));
1989 }
1990
1991out:
1992 return offset;
1993}
1994
1995static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
1996 size_t count, loff_t *ppos)
1997{
1998 struct snd_soc_pcm_runtime *fe = file->private_data;
1999 ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
2000 char *buf;
2001
2002 buf = kmalloc(out_count, GFP_KERNEL);
2003 if (!buf)
2004 return -ENOMEM;
2005
2006 if (fe->cpu_dai->driver->playback.channels_min)
2007 offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK,
2008 buf + offset, out_count - offset);
2009
2010 if (fe->cpu_dai->driver->capture.channels_min)
2011 offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE,
2012 buf + offset, out_count - offset);
2013
2014 ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
2015
2016 kfree(buf);
2017
2018 return ret;
2019}
2020
2021static const struct file_operations dpcm_state_fops = {
2022 .open = dpcm_state_open_file,
2023 .read = dpcm_state_read_file,
2024 .llseek = default_llseek,
2025};
2026
2027int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
2028{
2029 rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
2030 rtd->card->debugfs_card_root);
2031 if (!rtd->debugfs_dpcm_root) {
2032 dev_dbg(rtd->dev,
2033 "ASoC: Failed to create dpcm debugfs directory %s\n",
2034 rtd->dai_link->name);
2035 return -EINVAL;
2036 }
2037
2038 rtd->debugfs_dpcm_state = debugfs_create_file("state", 0644,
2039 rtd->debugfs_dpcm_root,
2040 rtd, &dpcm_state_fops);
2041
2042 return 0;
2043}
2044#endif