X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=sound%2Fsoc%2Fsoc-dapm.c;h=af3326c635041da0c852ecc0ca11ea91212484f1;hb=32f4876e62d5caba712ca76d96b0018dcc0f9601;hp=7caf8c7b0ac5063c14a20784011de0951047e5c9;hpb=7baca6ad0ef09c8a78d798c93a3ce25336e8f50f;p=mv-sheeva.git diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7caf8c7b0ac..af3326c6350 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -24,7 +24,7 @@ * o Automatic Mic Bias support * o Jack insertion power event initiation - e.g. hp insertion will enable * sinks, dacs, etc - * o Delayed powerdown of audio susbsytem to reduce pops between a quick + * o Delayed powerdown of audio susbsystem to reduce pops between a quick * device reopen. * * Todo: @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -63,7 +62,7 @@ #define POP_DEBUG 0 #if POP_DEBUG #define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */ -#define pop_wait(time) schedule_timeout_interruptible(msecs_to_jiffies(time)) +#define pop_wait(time) schedule_timeout_uninterruptible(msecs_to_jiffies(time)) #define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME) #else #define pop_dbg(format, arg...) @@ -227,7 +226,7 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget) snd_soc_write(codec, widget->reg, new); pop_wait(POP_TIME); } - dbg("reg old %x new %x change %d\n", old, new, change); + dbg("reg %x old %x new %x change %d\n", widget->reg, old, new, change); return change; } @@ -524,11 +523,13 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) continue; if (event == SND_SOC_DAPM_STREAM_START) { - ret = w->event(w, SND_SOC_DAPM_PRE_PMU); + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMU); if (ret < 0) return ret; } else if (event == SND_SOC_DAPM_STREAM_STOP) { - ret = w->event(w, SND_SOC_DAPM_PRE_PMD); + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMD); if (ret < 0) return ret; } @@ -539,11 +540,13 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) continue; if (event == SND_SOC_DAPM_STREAM_START) { - ret = w->event(w, SND_SOC_DAPM_POST_PMU); + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMU); if (ret < 0) return ret; } else if (event == SND_SOC_DAPM_STREAM_STOP) { - ret = w->event(w, SND_SOC_DAPM_POST_PMD); + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMD); if (ret < 0) return ret; } @@ -567,26 +570,30 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) if (power) { /* power up event */ if (w->event_flags & SND_SOC_DAPM_PRE_PMU) { - ret = w->event(w, SND_SOC_DAPM_PRE_PMU); + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMU); if (ret < 0) return ret; } dapm_update_bits(w); if (w->event_flags & SND_SOC_DAPM_POST_PMU){ - ret = w->event(w, SND_SOC_DAPM_POST_PMU); + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMU); if (ret < 0) return ret; } } else { /* power down event */ if (w->event_flags & SND_SOC_DAPM_PRE_PMD) { - ret = w->event(w, SND_SOC_DAPM_PRE_PMD); + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMD); if (ret < 0) return ret; } dapm_update_bits(w); if (w->event_flags & SND_SOC_DAPM_POST_PMD) { - ret = w->event(w, SND_SOC_DAPM_POST_PMD); + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMD); if (ret < 0) return ret; } @@ -692,7 +699,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, return 0; } -/* test and update the power status of a mixer widget */ +/* test and update the power status of a mixer or switch widget */ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, struct snd_kcontrol *kcontrol, int reg, int val_mask, int val, int invert) @@ -700,7 +707,8 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, struct snd_soc_dapm_path *path; int found = 0; - if (widget->id != snd_soc_dapm_mixer) + if (widget->id != snd_soc_dapm_mixer && + widget->id != snd_soc_dapm_switch) return -ENODEV; if (!snd_soc_test_bits(widget->codec, reg, val_mask, val)) @@ -882,13 +890,15 @@ int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink, if (wsink->id == snd_soc_dapm_input) { if (wsource->id == snd_soc_dapm_micbias || wsource->id == snd_soc_dapm_mic || - wsink->id == snd_soc_dapm_line) + wsink->id == snd_soc_dapm_line || + wsink->id == snd_soc_dapm_output) wsink->ext = 1; } if (wsource->id == snd_soc_dapm_output) { if (wsink->id == snd_soc_dapm_spk || wsink->id == snd_soc_dapm_hp || - wsink->id == snd_soc_dapm_line) + wsink->id == snd_soc_dapm_line || + wsink->id == snd_soc_dapm_input) wsource->ext = 1; } @@ -961,7 +971,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) { struct snd_soc_dapm_widget *w; - mutex_lock(&codec->mutex); list_for_each_entry(w, &codec->dapm_widgets, list) { if (w->new) @@ -996,7 +1005,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) } dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); - mutex_unlock(&codec->mutex); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); @@ -1017,8 +1025,9 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; + int max = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0x01; + int mask = (1 << fls(max)) - 1; /* return the saved value if we are powered down */ if (widget->id == snd_soc_dapm_pga && !widget->power) { @@ -1033,10 +1042,10 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, (snd_soc_read(widget->codec, reg) >> rshift) & mask; if (invert) { ucontrol->value.integer.value[0] = - mask - ucontrol->value.integer.value[0]; + max - ucontrol->value.integer.value[0]; if (shift != rshift) ucontrol->value.integer.value[1] = - mask - ucontrol->value.integer.value[1]; + max - ucontrol->value.integer.value[1]; } return 0; @@ -1059,7 +1068,8 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; + int max = (kcontrol->private_value >> 16) & 0xff; + int mask = (1 << fls(max)) - 1; int invert = (kcontrol->private_value >> 24) & 0x01; unsigned short val, val2, val_mask; int ret; @@ -1067,13 +1077,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, val = (ucontrol->value.integer.value[0] & mask); if (invert) - val = mask - val; + val = max - val; val_mask = mask << shift; val = val << shift; if (shift != rshift) { val2 = (ucontrol->value.integer.value[1] & mask); if (invert) - val2 = mask - val2; + val2 = max - val2; val_mask |= mask << rshift; val |= val2 << rshift; } @@ -1091,13 +1101,17 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert); if (widget->event) { if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { - ret = widget->event(widget, SND_SOC_DAPM_PRE_REG); - if (ret < 0) + ret = widget->event(widget, kcontrol, + SND_SOC_DAPM_PRE_REG); + if (ret < 0) { + ret = 1; goto out; + } } ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); if (widget->event_flags & SND_SOC_DAPM_POST_REG) - ret = widget->event(widget, SND_SOC_DAPM_POST_REG); + ret = widget->event(widget, kcontrol, + SND_SOC_DAPM_POST_REG); } else ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); @@ -1172,13 +1186,15 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, dapm_mux_update_power(widget, kcontrol, mask, mux, e); if (widget->event) { if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { - ret = widget->event(widget, SND_SOC_DAPM_PRE_REG); + ret = widget->event(widget, + kcontrol, SND_SOC_DAPM_PRE_REG); if (ret < 0) goto out; } ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); if (widget->event_flags & SND_SOC_DAPM_POST_REG) - ret = widget->event(widget, SND_SOC_DAPM_POST_REG); + ret = widget->event(widget, + kcontrol, SND_SOC_DAPM_POST_REG); } else ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); @@ -1272,11 +1288,34 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, mutex_unlock(&codec->mutex); dapm_power_widgets(codec, event); - dump_dapm(codec, __FUNCTION__); + dump_dapm(codec, __func__); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); +/** + * snd_soc_dapm_device_event - send a device event to the dapm core + * @socdev: audio device + * @event: device event + * + * Sends a device event to the dapm core. The core then makes any + * necessary machine or codec power changes.. + * + * Returns 0 for success else error. + */ +int snd_soc_dapm_device_event(struct snd_soc_device *socdev, int event) +{ + struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_machine *machine = socdev->machine; + + if (machine->dapm_event) + machine->dapm_event(machine, event); + if (codec->dapm_event) + codec->dapm_event(codec, event); + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_device_event); + /** * snd_soc_dapm_set_endpoint - set audio endpoint status * @codec: audio codec @@ -1295,10 +1334,11 @@ int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec, list_for_each_entry(w, &codec->dapm_widgets, list) { if (!strcmp(w->name, endpoint)) { w->connected = status; + return 0; } } - return 0; + return -ENODEV; } EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);