diff options
author | Troy Kisky <troy.kisky@boundarydevices.com> | 2008-10-13 20:42:14 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2008-10-30 10:34:02 -0400 |
commit | 12ef193d5817504621e503e78d641265f6a86ac4 (patch) | |
tree | a86c1cc9d7297561b0912f0b2c0332bf2ab993ca | |
parent | 15ad9a531a64d46af54839ab13542a81ad4c82a5 (diff) |
ASoC: Allow setting codec register with debugfs filesystem
i.e. echo 6 59 >/sys/kernel/debug/soc-audio.0/codec_reg
will set register 0x06 to a value of 0x59.
Also, pop_time debugfs interface setup is moved so that it
is setup in the same function as codec_reg
Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | include/sound/soc.h | 4 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 116 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 33 |
3 files changed, 125 insertions, 28 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index a1e0357a84d7..d33825d624a5 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -425,6 +425,7 @@ struct snd_soc_codec { | |||
425 | short reg_cache_step; | 425 | short reg_cache_step; |
426 | 426 | ||
427 | /* dapm */ | 427 | /* dapm */ |
428 | u32 pop_time; | ||
428 | struct list_head dapm_widgets; | 429 | struct list_head dapm_widgets; |
429 | struct list_head dapm_paths; | 430 | struct list_head dapm_paths; |
430 | enum snd_soc_bias_level bias_level; | 431 | enum snd_soc_bias_level bias_level; |
@@ -516,6 +517,9 @@ struct snd_soc_device { | |||
516 | struct delayed_work delayed_work; | 517 | struct delayed_work delayed_work; |
517 | struct work_struct deferred_resume_work; | 518 | struct work_struct deferred_resume_work; |
518 | void *codec_data; | 519 | void *codec_data; |
520 | #ifdef CONFIG_DEBUG_FS | ||
521 | struct dentry *debugfs_root; | ||
522 | #endif | ||
519 | }; | 523 | }; |
520 | 524 | ||
521 | /* runtime channel data */ | 525 | /* runtime channel data */ |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 462e635dfc74..4707042b3dad 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include <linux/debugfs.h> | ||
29 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -961,10 +962,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
961 | } | 962 | } |
962 | 963 | ||
963 | /* codec register dump */ | 964 | /* codec register dump */ |
964 | static ssize_t codec_reg_show(struct device *dev, | 965 | static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf) |
965 | struct device_attribute *attr, char *buf) | ||
966 | { | 966 | { |
967 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | ||
968 | struct snd_soc_codec *codec = devdata->codec; | 967 | struct snd_soc_codec *codec = devdata->codec; |
969 | int i, step = 1, count = 0; | 968 | int i, step = 1, count = 0; |
970 | 969 | ||
@@ -1001,8 +1000,117 @@ static ssize_t codec_reg_show(struct device *dev, | |||
1001 | 1000 | ||
1002 | return count; | 1001 | return count; |
1003 | } | 1002 | } |
1003 | static ssize_t codec_reg_show(struct device *dev, | ||
1004 | struct device_attribute *attr, char *buf) | ||
1005 | { | ||
1006 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | ||
1007 | return soc_codec_reg_show(devdata, buf); | ||
1008 | } | ||
1009 | |||
1004 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | 1010 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); |
1005 | 1011 | ||
1012 | #ifdef CONFIG_DEBUG_FS | ||
1013 | static int codec_reg_open_file(struct inode *inode, struct file *file) | ||
1014 | { | ||
1015 | file->private_data = inode->i_private; | ||
1016 | return 0; | ||
1017 | } | ||
1018 | |||
1019 | static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, | ||
1020 | size_t count, loff_t *ppos) | ||
1021 | { | ||
1022 | ssize_t ret; | ||
1023 | struct snd_soc_device *devdata = file->private_data; | ||
1024 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
1025 | if (!buf) | ||
1026 | return -ENOMEM; | ||
1027 | ret = soc_codec_reg_show(devdata, buf); | ||
1028 | if (ret >= 0) | ||
1029 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | ||
1030 | kfree(buf); | ||
1031 | return ret; | ||
1032 | } | ||
1033 | |||
1034 | static ssize_t codec_reg_write_file(struct file *file, | ||
1035 | const char __user *user_buf, size_t count, loff_t *ppos) | ||
1036 | { | ||
1037 | char buf[32]; | ||
1038 | int buf_size; | ||
1039 | char *start = buf; | ||
1040 | unsigned long reg, value; | ||
1041 | int step = 1; | ||
1042 | struct snd_soc_device *devdata = file->private_data; | ||
1043 | struct snd_soc_codec *codec = devdata->codec; | ||
1044 | |||
1045 | buf_size = min(count, (sizeof(buf)-1)); | ||
1046 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1047 | return -EFAULT; | ||
1048 | buf[buf_size] = 0; | ||
1049 | |||
1050 | if (codec->reg_cache_step) | ||
1051 | step = codec->reg_cache_step; | ||
1052 | |||
1053 | while (*start == ' ') | ||
1054 | start++; | ||
1055 | reg = simple_strtoul(start, &start, 16); | ||
1056 | if ((reg >= codec->reg_cache_size) || (reg % step)) | ||
1057 | return -EINVAL; | ||
1058 | while (*start == ' ') | ||
1059 | start++; | ||
1060 | if (strict_strtoul(start, 16, &value)) | ||
1061 | return -EINVAL; | ||
1062 | codec->write(codec, reg, value); | ||
1063 | return buf_size; | ||
1064 | } | ||
1065 | |||
1066 | static const struct file_operations codec_reg_fops = { | ||
1067 | .open = codec_reg_open_file, | ||
1068 | .read = codec_reg_read_file, | ||
1069 | .write = codec_reg_write_file, | ||
1070 | }; | ||
1071 | |||
1072 | static void soc_init_debugfs(struct snd_soc_device *socdev) | ||
1073 | { | ||
1074 | struct dentry *root, *file; | ||
1075 | struct snd_soc_codec *codec = socdev->codec; | ||
1076 | root = debugfs_create_dir(dev_name(socdev->dev), NULL); | ||
1077 | if (IS_ERR(root) || !root) | ||
1078 | goto exit1; | ||
1079 | |||
1080 | file = debugfs_create_file("codec_reg", 0644, | ||
1081 | root, socdev, &codec_reg_fops); | ||
1082 | if (!file) | ||
1083 | goto exit2; | ||
1084 | |||
1085 | file = debugfs_create_u32("dapm_pop_time", 0744, | ||
1086 | root, &codec->pop_time); | ||
1087 | if (!file) | ||
1088 | goto exit2; | ||
1089 | socdev->debugfs_root = root; | ||
1090 | return; | ||
1091 | exit2: | ||
1092 | debugfs_remove_recursive(root); | ||
1093 | exit1: | ||
1094 | dev_err(socdev->dev, "debugfs is not available\n"); | ||
1095 | } | ||
1096 | |||
1097 | static void soc_cleanup_debugfs(struct snd_soc_device *socdev) | ||
1098 | { | ||
1099 | debugfs_remove_recursive(socdev->debugfs_root); | ||
1100 | socdev->debugfs_root = NULL; | ||
1101 | } | ||
1102 | |||
1103 | #else | ||
1104 | |||
1105 | static inline void soc_init_debugfs(struct snd_soc_device *socdev) | ||
1106 | { | ||
1107 | } | ||
1108 | |||
1109 | static inline void soc_cleanup_debugfs(struct snd_soc_device *socdev) | ||
1110 | { | ||
1111 | } | ||
1112 | #endif | ||
1113 | |||
1006 | /** | 1114 | /** |
1007 | * snd_soc_new_ac97_codec - initailise AC97 device | 1115 | * snd_soc_new_ac97_codec - initailise AC97 device |
1008 | * @codec: audio codec | 1116 | * @codec: audio codec |
@@ -1216,6 +1324,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev) | |||
1216 | if (err < 0) | 1324 | if (err < 0) |
1217 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | 1325 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); |
1218 | 1326 | ||
1327 | soc_init_debugfs(socdev); | ||
1219 | mutex_unlock(&codec->mutex); | 1328 | mutex_unlock(&codec->mutex); |
1220 | 1329 | ||
1221 | out: | 1330 | out: |
@@ -1239,6 +1348,7 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev) | |||
1239 | #endif | 1348 | #endif |
1240 | 1349 | ||
1241 | mutex_lock(&codec->mutex); | 1350 | mutex_lock(&codec->mutex); |
1351 | soc_cleanup_debugfs(socdev); | ||
1242 | #ifdef CONFIG_SND_SOC_AC97_BUS | 1352 | #ifdef CONFIG_SND_SOC_AC97_BUS |
1243 | for (i = 0; i < codec->num_dai; i++) { | 1353 | for (i = 0; i < codec->num_dai; i++) { |
1244 | codec_dai = &codec->dai[i]; | 1354 | codec_dai = &codec->dai[i]; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7e9f423f5b09..b51d82285be4 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/bitops.h> | 37 | #include <linux/bitops.h> |
38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
39 | #include <linux/jiffies.h> | 39 | #include <linux/jiffies.h> |
40 | #include <linux/debugfs.h> | ||
41 | #include <sound/core.h> | 40 | #include <sound/core.h> |
42 | #include <sound/pcm.h> | 41 | #include <sound/pcm.h> |
43 | #include <sound/pcm_params.h> | 42 | #include <sound/pcm_params.h> |
@@ -67,17 +66,13 @@ static int dapm_status = 1; | |||
67 | module_param(dapm_status, int, 0); | 66 | module_param(dapm_status, int, 0); |
68 | MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); | 67 | MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); |
69 | 68 | ||
70 | static struct dentry *asoc_debugfs; | 69 | static void pop_wait(u32 pop_time) |
71 | |||
72 | static u32 pop_time; | ||
73 | |||
74 | static void pop_wait(void) | ||
75 | { | 70 | { |
76 | if (pop_time) | 71 | if (pop_time) |
77 | schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); | 72 | schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); |
78 | } | 73 | } |
79 | 74 | ||
80 | static void pop_dbg(const char *fmt, ...) | 75 | static void pop_dbg(u32 pop_time, const char *fmt, ...) |
81 | { | 76 | { |
82 | va_list args; | 77 | va_list args; |
83 | 78 | ||
@@ -85,7 +80,7 @@ static void pop_dbg(const char *fmt, ...) | |||
85 | 80 | ||
86 | if (pop_time) { | 81 | if (pop_time) { |
87 | vprintk(fmt, args); | 82 | vprintk(fmt, args); |
88 | pop_wait(); | 83 | pop_wait(pop_time); |
89 | } | 84 | } |
90 | 85 | ||
91 | va_end(args); | 86 | va_end(args); |
@@ -230,10 +225,11 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget) | |||
230 | 225 | ||
231 | change = old != new; | 226 | change = old != new; |
232 | if (change) { | 227 | if (change) { |
233 | pop_dbg("pop test %s : %s in %d ms\n", widget->name, | 228 | pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", |
234 | widget->power ? "on" : "off", pop_time); | 229 | widget->name, widget->power ? "on" : "off", |
230 | codec->pop_time); | ||
235 | snd_soc_write(codec, widget->reg, new); | 231 | snd_soc_write(codec, widget->reg, new); |
236 | pop_wait(); | 232 | pop_wait(codec->pop_time); |
237 | } | 233 | } |
238 | pr_debug("reg %x old %x new %x change %d\n", widget->reg, | 234 | pr_debug("reg %x old %x new %x change %d\n", widget->reg, |
239 | old, new, change); | 235 | old, new, change); |
@@ -821,23 +817,13 @@ static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); | |||
821 | 817 | ||
822 | int snd_soc_dapm_sys_add(struct device *dev) | 818 | int snd_soc_dapm_sys_add(struct device *dev) |
823 | { | 819 | { |
824 | int ret = 0; | ||
825 | |||
826 | if (!dapm_status) | 820 | if (!dapm_status) |
827 | return 0; | 821 | return 0; |
828 | 822 | ||
829 | ret = device_create_file(dev, &dev_attr_dapm_widget); | 823 | ret = device_create_file(dev, &dev_attr_dapm_widget); |
830 | if (ret != 0) | 824 | if (ret != 0) |
831 | return ret; | 825 | return ret; |
832 | 826 | return device_create_file(dev, &dev_attr_dapm_widget); | |
833 | asoc_debugfs = debugfs_create_dir("asoc", NULL); | ||
834 | if (!IS_ERR(asoc_debugfs) && asoc_debugfs) | ||
835 | debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs, | ||
836 | &pop_time); | ||
837 | else | ||
838 | asoc_debugfs = NULL; | ||
839 | |||
840 | return 0; | ||
841 | } | 827 | } |
842 | 828 | ||
843 | static void snd_soc_dapm_sys_remove(struct device *dev) | 829 | static void snd_soc_dapm_sys_remove(struct device *dev) |
@@ -845,9 +831,6 @@ static void snd_soc_dapm_sys_remove(struct device *dev) | |||
845 | if (dapm_status) { | 831 | if (dapm_status) { |
846 | device_remove_file(dev, &dev_attr_dapm_widget); | 832 | device_remove_file(dev, &dev_attr_dapm_widget); |
847 | } | 833 | } |
848 | |||
849 | if (asoc_debugfs) | ||
850 | debugfs_remove_recursive(asoc_debugfs); | ||
851 | } | 834 | } |
852 | 835 | ||
853 | /* free all dapm widgets and resources */ | 836 | /* free all dapm widgets and resources */ |