aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c127
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;
67module_param(dapm_status, int, 0); 68module_param(dapm_status, int, 0);
68MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); 69MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
69 70
70static unsigned int pop_time; 71static struct dentry *asoc_debugfs;
72
73static u32 pop_time;
71 74
72static void pop_wait(void) 75static 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 */
685static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 694static 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
812static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); 821static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
813 822
814/* pop/click delay times */
815static 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
821static 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
836static DEVICE_ATTR(dapm_pop_time, 0744, dapm_pop_time_show,
837 dapm_pop_time_store);
838
839int snd_soc_dapm_sys_add(struct device *dev) 823int 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
853static void snd_soc_dapm_sys_remove(struct device *dev) 844static 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,