diff options
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 85 |
1 files changed, 61 insertions, 24 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 29a546fecacf..620d7ea3c15f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/bitops.h> | 43 | #include <linux/bitops.h> |
44 | #include <linux/platform_device.h> | 44 | #include <linux/platform_device.h> |
45 | #include <linux/jiffies.h> | 45 | #include <linux/jiffies.h> |
46 | #include <sound/driver.h> | ||
47 | #include <sound/core.h> | 46 | #include <sound/core.h> |
48 | #include <sound/pcm.h> | 47 | #include <sound/pcm.h> |
49 | #include <sound/pcm_params.h> | 48 | #include <sound/pcm_params.h> |
@@ -524,11 +523,13 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
524 | continue; | 523 | continue; |
525 | 524 | ||
526 | if (event == SND_SOC_DAPM_STREAM_START) { | 525 | if (event == SND_SOC_DAPM_STREAM_START) { |
527 | ret = w->event(w, SND_SOC_DAPM_PRE_PMU); | 526 | ret = w->event(w, |
527 | NULL, SND_SOC_DAPM_PRE_PMU); | ||
528 | if (ret < 0) | 528 | if (ret < 0) |
529 | return ret; | 529 | return ret; |
530 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | 530 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { |
531 | ret = w->event(w, SND_SOC_DAPM_PRE_PMD); | 531 | ret = w->event(w, |
532 | NULL, SND_SOC_DAPM_PRE_PMD); | ||
532 | if (ret < 0) | 533 | if (ret < 0) |
533 | return ret; | 534 | return ret; |
534 | } | 535 | } |
@@ -539,11 +540,13 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
539 | continue; | 540 | continue; |
540 | 541 | ||
541 | if (event == SND_SOC_DAPM_STREAM_START) { | 542 | if (event == SND_SOC_DAPM_STREAM_START) { |
542 | ret = w->event(w, SND_SOC_DAPM_POST_PMU); | 543 | ret = w->event(w, |
544 | NULL, SND_SOC_DAPM_POST_PMU); | ||
543 | if (ret < 0) | 545 | if (ret < 0) |
544 | return ret; | 546 | return ret; |
545 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | 547 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { |
546 | ret = w->event(w, SND_SOC_DAPM_POST_PMD); | 548 | ret = w->event(w, |
549 | NULL, SND_SOC_DAPM_POST_PMD); | ||
547 | if (ret < 0) | 550 | if (ret < 0) |
548 | return ret; | 551 | return ret; |
549 | } | 552 | } |
@@ -567,26 +570,30 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
567 | if (power) { | 570 | if (power) { |
568 | /* power up event */ | 571 | /* power up event */ |
569 | if (w->event_flags & SND_SOC_DAPM_PRE_PMU) { | 572 | if (w->event_flags & SND_SOC_DAPM_PRE_PMU) { |
570 | ret = w->event(w, SND_SOC_DAPM_PRE_PMU); | 573 | ret = w->event(w, |
574 | NULL, SND_SOC_DAPM_PRE_PMU); | ||
571 | if (ret < 0) | 575 | if (ret < 0) |
572 | return ret; | 576 | return ret; |
573 | } | 577 | } |
574 | dapm_update_bits(w); | 578 | dapm_update_bits(w); |
575 | if (w->event_flags & SND_SOC_DAPM_POST_PMU){ | 579 | if (w->event_flags & SND_SOC_DAPM_POST_PMU){ |
576 | ret = w->event(w, SND_SOC_DAPM_POST_PMU); | 580 | ret = w->event(w, |
581 | NULL, SND_SOC_DAPM_POST_PMU); | ||
577 | if (ret < 0) | 582 | if (ret < 0) |
578 | return ret; | 583 | return ret; |
579 | } | 584 | } |
580 | } else { | 585 | } else { |
581 | /* power down event */ | 586 | /* power down event */ |
582 | if (w->event_flags & SND_SOC_DAPM_PRE_PMD) { | 587 | if (w->event_flags & SND_SOC_DAPM_PRE_PMD) { |
583 | ret = w->event(w, SND_SOC_DAPM_PRE_PMD); | 588 | ret = w->event(w, |
589 | NULL, SND_SOC_DAPM_PRE_PMD); | ||
584 | if (ret < 0) | 590 | if (ret < 0) |
585 | return ret; | 591 | return ret; |
586 | } | 592 | } |
587 | dapm_update_bits(w); | 593 | dapm_update_bits(w); |
588 | if (w->event_flags & SND_SOC_DAPM_POST_PMD) { | 594 | if (w->event_flags & SND_SOC_DAPM_POST_PMD) { |
589 | ret = w->event(w, SND_SOC_DAPM_POST_PMD); | 595 | ret = w->event(w, |
596 | NULL, SND_SOC_DAPM_POST_PMD); | ||
590 | if (ret < 0) | 597 | if (ret < 0) |
591 | return ret; | 598 | return ret; |
592 | } | 599 | } |
@@ -692,7 +699,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | |||
692 | return 0; | 699 | return 0; |
693 | } | 700 | } |
694 | 701 | ||
695 | /* test and update the power status of a mixer widget */ | 702 | /* test and update the power status of a mixer or switch widget */ |
696 | static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | 703 | static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, |
697 | struct snd_kcontrol *kcontrol, int reg, | 704 | struct snd_kcontrol *kcontrol, int reg, |
698 | int val_mask, int val, int invert) | 705 | int val_mask, int val, int invert) |
@@ -700,7 +707,8 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | |||
700 | struct snd_soc_dapm_path *path; | 707 | struct snd_soc_dapm_path *path; |
701 | int found = 0; | 708 | int found = 0; |
702 | 709 | ||
703 | if (widget->id != snd_soc_dapm_mixer) | 710 | if (widget->id != snd_soc_dapm_mixer && |
711 | widget->id != snd_soc_dapm_switch) | ||
704 | return -ENODEV; | 712 | return -ENODEV; |
705 | 713 | ||
706 | if (!snd_soc_test_bits(widget->codec, reg, val_mask, val)) | 714 | if (!snd_soc_test_bits(widget->codec, reg, val_mask, val)) |
@@ -963,7 +971,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | |||
963 | { | 971 | { |
964 | struct snd_soc_dapm_widget *w; | 972 | struct snd_soc_dapm_widget *w; |
965 | 973 | ||
966 | mutex_lock(&codec->mutex); | ||
967 | list_for_each_entry(w, &codec->dapm_widgets, list) | 974 | list_for_each_entry(w, &codec->dapm_widgets, list) |
968 | { | 975 | { |
969 | if (w->new) | 976 | if (w->new) |
@@ -998,7 +1005,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | |||
998 | } | 1005 | } |
999 | 1006 | ||
1000 | dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); | 1007 | dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); |
1001 | mutex_unlock(&codec->mutex); | ||
1002 | return 0; | 1008 | return 0; |
1003 | } | 1009 | } |
1004 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | 1010 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); |
@@ -1019,8 +1025,9 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
1019 | int reg = kcontrol->private_value & 0xff; | 1025 | int reg = kcontrol->private_value & 0xff; |
1020 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1026 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1021 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1027 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
1022 | int mask = (kcontrol->private_value >> 16) & 0xff; | 1028 | int max = (kcontrol->private_value >> 16) & 0xff; |
1023 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1029 | int invert = (kcontrol->private_value >> 24) & 0x01; |
1030 | int mask = (1 << fls(max)) - 1; | ||
1024 | 1031 | ||
1025 | /* return the saved value if we are powered down */ | 1032 | /* return the saved value if we are powered down */ |
1026 | if (widget->id == snd_soc_dapm_pga && !widget->power) { | 1033 | if (widget->id == snd_soc_dapm_pga && !widget->power) { |
@@ -1035,10 +1042,10 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
1035 | (snd_soc_read(widget->codec, reg) >> rshift) & mask; | 1042 | (snd_soc_read(widget->codec, reg) >> rshift) & mask; |
1036 | if (invert) { | 1043 | if (invert) { |
1037 | ucontrol->value.integer.value[0] = | 1044 | ucontrol->value.integer.value[0] = |
1038 | mask - ucontrol->value.integer.value[0]; | 1045 | max - ucontrol->value.integer.value[0]; |
1039 | if (shift != rshift) | 1046 | if (shift != rshift) |
1040 | ucontrol->value.integer.value[1] = | 1047 | ucontrol->value.integer.value[1] = |
1041 | mask - ucontrol->value.integer.value[1]; | 1048 | max - ucontrol->value.integer.value[1]; |
1042 | } | 1049 | } |
1043 | 1050 | ||
1044 | return 0; | 1051 | return 0; |
@@ -1061,7 +1068,8 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1061 | int reg = kcontrol->private_value & 0xff; | 1068 | int reg = kcontrol->private_value & 0xff; |
1062 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1069 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1063 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1070 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
1064 | int mask = (kcontrol->private_value >> 16) & 0xff; | 1071 | int max = (kcontrol->private_value >> 16) & 0xff; |
1072 | int mask = (1 << fls(max)) - 1; | ||
1065 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1073 | int invert = (kcontrol->private_value >> 24) & 0x01; |
1066 | unsigned short val, val2, val_mask; | 1074 | unsigned short val, val2, val_mask; |
1067 | int ret; | 1075 | int ret; |
@@ -1069,13 +1077,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1069 | val = (ucontrol->value.integer.value[0] & mask); | 1077 | val = (ucontrol->value.integer.value[0] & mask); |
1070 | 1078 | ||
1071 | if (invert) | 1079 | if (invert) |
1072 | val = mask - val; | 1080 | val = max - val; |
1073 | val_mask = mask << shift; | 1081 | val_mask = mask << shift; |
1074 | val = val << shift; | 1082 | val = val << shift; |
1075 | if (shift != rshift) { | 1083 | if (shift != rshift) { |
1076 | val2 = (ucontrol->value.integer.value[1] & mask); | 1084 | val2 = (ucontrol->value.integer.value[1] & mask); |
1077 | if (invert) | 1085 | if (invert) |
1078 | val2 = mask - val2; | 1086 | val2 = max - val2; |
1079 | val_mask |= mask << rshift; | 1087 | val_mask |= mask << rshift; |
1080 | val |= val2 << rshift; | 1088 | val |= val2 << rshift; |
1081 | } | 1089 | } |
@@ -1093,13 +1101,17 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1093 | dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert); | 1101 | dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert); |
1094 | if (widget->event) { | 1102 | if (widget->event) { |
1095 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 1103 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { |
1096 | ret = widget->event(widget, SND_SOC_DAPM_PRE_REG); | 1104 | ret = widget->event(widget, kcontrol, |
1097 | if (ret < 0) | 1105 | SND_SOC_DAPM_PRE_REG); |
1106 | if (ret < 0) { | ||
1107 | ret = 1; | ||
1098 | goto out; | 1108 | goto out; |
1109 | } | ||
1099 | } | 1110 | } |
1100 | ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); | 1111 | ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); |
1101 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) | 1112 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) |
1102 | ret = widget->event(widget, SND_SOC_DAPM_POST_REG); | 1113 | ret = widget->event(widget, kcontrol, |
1114 | SND_SOC_DAPM_POST_REG); | ||
1103 | } else | 1115 | } else |
1104 | ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); | 1116 | ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); |
1105 | 1117 | ||
@@ -1174,13 +1186,15 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1174 | dapm_mux_update_power(widget, kcontrol, mask, mux, e); | 1186 | dapm_mux_update_power(widget, kcontrol, mask, mux, e); |
1175 | if (widget->event) { | 1187 | if (widget->event) { |
1176 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 1188 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { |
1177 | ret = widget->event(widget, SND_SOC_DAPM_PRE_REG); | 1189 | ret = widget->event(widget, |
1190 | kcontrol, SND_SOC_DAPM_PRE_REG); | ||
1178 | if (ret < 0) | 1191 | if (ret < 0) |
1179 | goto out; | 1192 | goto out; |
1180 | } | 1193 | } |
1181 | ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); | 1194 | ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); |
1182 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) | 1195 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) |
1183 | ret = widget->event(widget, SND_SOC_DAPM_POST_REG); | 1196 | ret = widget->event(widget, |
1197 | kcontrol, SND_SOC_DAPM_POST_REG); | ||
1184 | } else | 1198 | } else |
1185 | ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); | 1199 | ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); |
1186 | 1200 | ||
@@ -1280,6 +1294,29 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, | |||
1280 | EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); | 1294 | EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); |
1281 | 1295 | ||
1282 | /** | 1296 | /** |
1297 | * snd_soc_dapm_device_event - send a device event to the dapm core | ||
1298 | * @socdev: audio device | ||
1299 | * @event: device event | ||
1300 | * | ||
1301 | * Sends a device event to the dapm core. The core then makes any | ||
1302 | * necessary machine or codec power changes.. | ||
1303 | * | ||
1304 | * Returns 0 for success else error. | ||
1305 | */ | ||
1306 | int snd_soc_dapm_device_event(struct snd_soc_device *socdev, int event) | ||
1307 | { | ||
1308 | struct snd_soc_codec *codec = socdev->codec; | ||
1309 | struct snd_soc_machine *machine = socdev->machine; | ||
1310 | |||
1311 | if (machine->dapm_event) | ||
1312 | machine->dapm_event(machine, event); | ||
1313 | if (codec->dapm_event) | ||
1314 | codec->dapm_event(codec, event); | ||
1315 | return 0; | ||
1316 | } | ||
1317 | EXPORT_SYMBOL_GPL(snd_soc_dapm_device_event); | ||
1318 | |||
1319 | /** | ||
1283 | * snd_soc_dapm_set_endpoint - set audio endpoint status | 1320 | * snd_soc_dapm_set_endpoint - set audio endpoint status |
1284 | * @codec: audio codec | 1321 | * @codec: audio codec |
1285 | * @endpoint: audio signal endpoint (or start point) | 1322 | * @endpoint: audio signal endpoint (or start point) |