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.c85
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 */
696static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 703static 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}
1004EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); 1010EXPORT_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,
1280EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); 1294EXPORT_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 */
1306int 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}
1317EXPORT_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)