diff options
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 127 |
1 files changed, 62 insertions, 65 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f9d100bc8479..9ca9c08610fa 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/bitops.h> | 38 | #include <linux/bitops.h> |
39 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
40 | #include <linux/jiffies.h> | 40 | #include <linux/jiffies.h> |
41 | #include <linux/debugfs.h> | ||
41 | #include <sound/core.h> | 42 | #include <sound/core.h> |
42 | #include <sound/pcm.h> | 43 | #include <sound/pcm.h> |
43 | #include <sound/pcm_params.h> | 44 | #include <sound/pcm_params.h> |
@@ -67,7 +68,9 @@ static int dapm_status = 1; | |||
67 | module_param(dapm_status, int, 0); | 68 | module_param(dapm_status, int, 0); |
68 | MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); | 69 | MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); |
69 | 70 | ||
70 | static unsigned int pop_time; | 71 | static struct dentry *asoc_debugfs; |
72 | |||
73 | static u32 pop_time; | ||
71 | 74 | ||
72 | static void pop_wait(void) | 75 | static void pop_wait(void) |
73 | { | 76 | { |
@@ -104,10 +107,13 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
104 | case snd_soc_dapm_switch: | 107 | case snd_soc_dapm_switch: |
105 | case snd_soc_dapm_mixer: { | 108 | case snd_soc_dapm_mixer: { |
106 | int val; | 109 | int val; |
107 | int reg = w->kcontrols[i].private_value & 0xff; | 110 | struct soc_mixer_control *mc = (struct soc_mixer_control *) |
108 | int shift = (w->kcontrols[i].private_value >> 8) & 0x0f; | 111 | w->kcontrols[i].private_value; |
109 | int mask = (w->kcontrols[i].private_value >> 16) & 0xff; | 112 | unsigned int reg = mc->reg; |
110 | int invert = (w->kcontrols[i].private_value >> 24) & 0x01; | 113 | unsigned int shift = mc->shift; |
114 | int max = mc->max; | ||
115 | unsigned int mask = (1 << fls(max)) - 1; | ||
116 | unsigned int invert = mc->invert; | ||
111 | 117 | ||
112 | val = snd_soc_read(w->codec, reg); | 118 | val = snd_soc_read(w->codec, reg); |
113 | val = (val >> shift) & mask; | 119 | val = (val >> shift) & mask; |
@@ -122,13 +128,13 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
122 | struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value; | 128 | struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value; |
123 | int val, item, bitmask; | 129 | int val, item, bitmask; |
124 | 130 | ||
125 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | 131 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
126 | ; | 132 | ; |
127 | val = snd_soc_read(w->codec, e->reg); | 133 | val = snd_soc_read(w->codec, e->reg); |
128 | item = (val >> e->shift_l) & (bitmask - 1); | 134 | item = (val >> e->shift_l) & (bitmask - 1); |
129 | 135 | ||
130 | p->connect = 0; | 136 | p->connect = 0; |
131 | for (i = 0; i < e->mask; i++) { | 137 | for (i = 0; i < e->max; i++) { |
132 | if (!(strcmp(p->name, e->texts[i])) && item == i) | 138 | if (!(strcmp(p->name, e->texts[i])) && item == i) |
133 | p->connect = 1; | 139 | p->connect = 1; |
134 | } | 140 | } |
@@ -165,7 +171,7 @@ static int dapm_connect_mux(struct snd_soc_codec *codec, | |||
165 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 171 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
166 | int i; | 172 | int i; |
167 | 173 | ||
168 | for (i = 0; i < e->mask; i++) { | 174 | for (i = 0; i < e->max; i++) { |
169 | if (!(strcmp(control_name, e->texts[i]))) { | 175 | if (!(strcmp(control_name, e->texts[i]))) { |
170 | list_add(&path->list, &codec->dapm_paths); | 176 | list_add(&path->list, &codec->dapm_paths); |
171 | list_add(&path->list_sink, &dest->sources); | 177 | list_add(&path->list_sink, &dest->sources); |
@@ -247,16 +253,19 @@ static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power) | |||
247 | return 0; | 253 | return 0; |
248 | 254 | ||
249 | if (widget->num_kcontrols && k) { | 255 | if (widget->num_kcontrols && k) { |
250 | int reg = k->private_value & 0xff; | 256 | struct soc_mixer_control *mc = |
251 | int shift = (k->private_value >> 8) & 0x0f; | 257 | (struct soc_mixer_control *)k->private_value; |
252 | int mask = (k->private_value >> 16) & 0xff; | 258 | unsigned int reg = mc->reg; |
253 | int invert = (k->private_value >> 24) & 0x01; | 259 | unsigned int shift = mc->shift; |
260 | int max = mc->max; | ||
261 | unsigned int mask = (1 << fls(max)) - 1; | ||
262 | unsigned int invert = mc->invert; | ||
254 | 263 | ||
255 | if (power) { | 264 | if (power) { |
256 | int i; | 265 | int i; |
257 | /* power up has happended, increase volume to last level */ | 266 | /* power up has happended, increase volume to last level */ |
258 | if (invert) { | 267 | if (invert) { |
259 | for (i = mask; i > widget->saved_value; i--) | 268 | for (i = max; i > widget->saved_value; i--) |
260 | snd_soc_update_bits(widget->codec, reg, mask, i); | 269 | snd_soc_update_bits(widget->codec, reg, mask, i); |
261 | } else { | 270 | } else { |
262 | for (i = 0; i < widget->saved_value; i++) | 271 | for (i = 0; i < widget->saved_value; i++) |
@@ -684,7 +693,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) | |||
684 | /* test and update the power status of a mux widget */ | 693 | /* test and update the power status of a mux widget */ |
685 | static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | 694 | static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, |
686 | struct snd_kcontrol *kcontrol, int mask, | 695 | struct snd_kcontrol *kcontrol, int mask, |
687 | int val, struct soc_enum* e) | 696 | int mux, int val, struct soc_enum *e) |
688 | { | 697 | { |
689 | struct snd_soc_dapm_path *path; | 698 | struct snd_soc_dapm_path *path; |
690 | int found = 0; | 699 | int found = 0; |
@@ -700,12 +709,12 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | |||
700 | if (path->kcontrol != kcontrol) | 709 | if (path->kcontrol != kcontrol) |
701 | continue; | 710 | continue; |
702 | 711 | ||
703 | if (!path->name || ! e->texts[val]) | 712 | if (!path->name || !e->texts[mux]) |
704 | continue; | 713 | continue; |
705 | 714 | ||
706 | found = 1; | 715 | found = 1; |
707 | /* we now need to match the string in the enum to the path */ | 716 | /* we now need to match the string in the enum to the path */ |
708 | if (!(strcmp(path->name, e->texts[val]))) | 717 | if (!(strcmp(path->name, e->texts[mux]))) |
709 | path->connect = 1; /* new connection */ | 718 | path->connect = 1; /* new connection */ |
710 | else | 719 | else |
711 | path->connect = 0; /* old connection must be powered down */ | 720 | path->connect = 0; /* old connection must be powered down */ |
@@ -811,51 +820,35 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
811 | 820 | ||
812 | static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); | 821 | static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); |
813 | 822 | ||
814 | /* pop/click delay times */ | ||
815 | static ssize_t dapm_pop_time_show(struct device *dev, | ||
816 | struct device_attribute *attr, char *buf) | ||
817 | { | ||
818 | return sprintf(buf, "%d\n", pop_time); | ||
819 | } | ||
820 | |||
821 | static ssize_t dapm_pop_time_store(struct device *dev, | ||
822 | struct device_attribute *attr, | ||
823 | const char *buf, size_t count) | ||
824 | |||
825 | { | ||
826 | unsigned long val; | ||
827 | |||
828 | if (strict_strtoul(buf, 10, &val) >= 0) | ||
829 | pop_time = val; | ||
830 | else | ||
831 | printk(KERN_ERR "Unable to parse pop_time setting\n"); | ||
832 | |||
833 | return count; | ||
834 | } | ||
835 | |||
836 | static DEVICE_ATTR(dapm_pop_time, 0744, dapm_pop_time_show, | ||
837 | dapm_pop_time_store); | ||
838 | |||
839 | int snd_soc_dapm_sys_add(struct device *dev) | 823 | int snd_soc_dapm_sys_add(struct device *dev) |
840 | { | 824 | { |
841 | int ret = 0; | 825 | int ret = 0; |
842 | 826 | ||
843 | if (dapm_status) { | 827 | if (!dapm_status) |
844 | ret = device_create_file(dev, &dev_attr_dapm_widget); | 828 | return 0; |
845 | 829 | ||
846 | if (ret == 0) | 830 | ret = device_create_file(dev, &dev_attr_dapm_widget); |
847 | ret = device_create_file(dev, &dev_attr_dapm_pop_time); | 831 | if (ret != 0) |
848 | } | 832 | return ret; |
849 | 833 | ||
850 | return ret; | 834 | asoc_debugfs = debugfs_create_dir("asoc", NULL); |
835 | if (!IS_ERR(asoc_debugfs)) | ||
836 | debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs, | ||
837 | &pop_time); | ||
838 | else | ||
839 | asoc_debugfs = NULL; | ||
840 | |||
841 | return 0; | ||
851 | } | 842 | } |
852 | 843 | ||
853 | static void snd_soc_dapm_sys_remove(struct device *dev) | 844 | static void snd_soc_dapm_sys_remove(struct device *dev) |
854 | { | 845 | { |
855 | if (dapm_status) { | 846 | if (dapm_status) { |
856 | device_remove_file(dev, &dev_attr_dapm_pop_time); | ||
857 | device_remove_file(dev, &dev_attr_dapm_widget); | 847 | device_remove_file(dev, &dev_attr_dapm_widget); |
858 | } | 848 | } |
849 | |||
850 | if (asoc_debugfs) | ||
851 | debugfs_remove_recursive(asoc_debugfs); | ||
859 | } | 852 | } |
860 | 853 | ||
861 | /* free all dapm widgets and resources */ | 854 | /* free all dapm widgets and resources */ |
@@ -1133,12 +1126,14 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
1133 | struct snd_ctl_elem_value *ucontrol) | 1126 | struct snd_ctl_elem_value *ucontrol) |
1134 | { | 1127 | { |
1135 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1128 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); |
1136 | int reg = kcontrol->private_value & 0xff; | 1129 | struct soc_mixer_control *mc = |
1137 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1130 | (struct soc_mixer_control *)kcontrol->private_value; |
1138 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1131 | unsigned int reg = mc->reg; |
1139 | int max = (kcontrol->private_value >> 16) & 0xff; | 1132 | unsigned int shift = mc->shift; |
1140 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1133 | unsigned int rshift = mc->rshift; |
1141 | int mask = (1 << fls(max)) - 1; | 1134 | int max = mc->max; |
1135 | unsigned int invert = mc->invert; | ||
1136 | unsigned int mask = (1 << fls(max)) - 1; | ||
1142 | 1137 | ||
1143 | /* return the saved value if we are powered down */ | 1138 | /* return the saved value if we are powered down */ |
1144 | if (widget->id == snd_soc_dapm_pga && !widget->power) { | 1139 | if (widget->id == snd_soc_dapm_pga && !widget->power) { |
@@ -1176,12 +1171,14 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1176 | struct snd_ctl_elem_value *ucontrol) | 1171 | struct snd_ctl_elem_value *ucontrol) |
1177 | { | 1172 | { |
1178 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1173 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); |
1179 | int reg = kcontrol->private_value & 0xff; | 1174 | struct soc_mixer_control *mc = |
1180 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1175 | (struct soc_mixer_control *)kcontrol->private_value; |
1181 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1176 | unsigned int reg = mc->reg; |
1182 | int max = (kcontrol->private_value >> 16) & 0xff; | 1177 | unsigned int shift = mc->shift; |
1183 | int mask = (1 << fls(max)) - 1; | 1178 | unsigned int rshift = mc->rshift; |
1184 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1179 | int max = mc->max; |
1180 | unsigned int mask = (1 << fls(max)) - 1; | ||
1181 | unsigned int invert = mc->invert; | ||
1185 | unsigned short val, val2, val_mask; | 1182 | unsigned short val, val2, val_mask; |
1186 | int ret; | 1183 | int ret; |
1187 | 1184 | ||
@@ -1248,7 +1245,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
1248 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1245 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1249 | unsigned short val, bitmask; | 1246 | unsigned short val, bitmask; |
1250 | 1247 | ||
1251 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | 1248 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
1252 | ; | 1249 | ; |
1253 | val = snd_soc_read(widget->codec, e->reg); | 1250 | val = snd_soc_read(widget->codec, e->reg); |
1254 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); | 1251 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); |
@@ -1278,15 +1275,15 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1278 | unsigned short mask, bitmask; | 1275 | unsigned short mask, bitmask; |
1279 | int ret = 0; | 1276 | int ret = 0; |
1280 | 1277 | ||
1281 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | 1278 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
1282 | ; | 1279 | ; |
1283 | if (ucontrol->value.enumerated.item[0] > e->mask - 1) | 1280 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
1284 | return -EINVAL; | 1281 | return -EINVAL; |
1285 | mux = ucontrol->value.enumerated.item[0]; | 1282 | mux = ucontrol->value.enumerated.item[0]; |
1286 | val = mux << e->shift_l; | 1283 | val = mux << e->shift_l; |
1287 | mask = (bitmask - 1) << e->shift_l; | 1284 | mask = (bitmask - 1) << e->shift_l; |
1288 | if (e->shift_l != e->shift_r) { | 1285 | if (e->shift_l != e->shift_r) { |
1289 | if (ucontrol->value.enumerated.item[1] > e->mask - 1) | 1286 | if (ucontrol->value.enumerated.item[1] > e->max - 1) |
1290 | return -EINVAL; | 1287 | return -EINVAL; |
1291 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 1288 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
1292 | mask |= (bitmask - 1) << e->shift_r; | 1289 | mask |= (bitmask - 1) << e->shift_r; |
@@ -1294,7 +1291,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1294 | 1291 | ||
1295 | mutex_lock(&widget->codec->mutex); | 1292 | mutex_lock(&widget->codec->mutex); |
1296 | widget->value = val; | 1293 | widget->value = val; |
1297 | dapm_mux_update_power(widget, kcontrol, mask, mux, e); | 1294 | dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); |
1298 | if (widget->event) { | 1295 | if (widget->event) { |
1299 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 1296 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { |
1300 | ret = widget->event(widget, | 1297 | ret = widget->event(widget, |