diff options
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r-- | sound/soc/soc-pcm.c | 152 |
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 | } |
1892 | EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); | 1900 | EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); |
1901 | |||
1902 | #ifdef CONFIG_DEBUG_FS | ||
1903 | static 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 | |||
1931 | static int dpcm_state_open_file(struct inode *inode, struct file *file) | ||
1932 | { | ||
1933 | file->private_data = inode->i_private; | ||
1934 | return 0; | ||
1935 | } | ||
1936 | |||
1937 | static 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 | |||
1991 | out: | ||
1992 | return offset; | ||
1993 | } | ||
1994 | |||
1995 | static 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 | |||
2021 | static 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 | |||
2027 | int 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 | ||