Commit a304681f authored by Mark Brown's avatar Mark Brown

Merge branches 'topic/dapm', 'topic/sign', 'topic/adau1373', 'topic/max98090',...

Merge branches 'topic/dapm', 'topic/sign', 'topic/adau1373', 'topic/max98090', 'topic/mc13783', 'fix/wm8994' and 'topic/wm8995' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-enum
...@@ -222,27 +222,19 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info) ...@@ -222,27 +222,19 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
struct snd_soc_dapm_context *dapm = arizona->dapm; struct snd_soc_dapm_context *dapm = arizona->dapm;
int ret; int ret;
mutex_lock(&dapm->card->dapm_mutex);
ret = snd_soc_dapm_force_enable_pin(dapm, widget); ret = snd_soc_dapm_force_enable_pin(dapm, widget);
if (ret != 0) if (ret != 0)
dev_warn(arizona->dev, "Failed to enable %s: %d\n", dev_warn(arizona->dev, "Failed to enable %s: %d\n",
widget, ret); widget, ret);
mutex_unlock(&dapm->card->dapm_mutex);
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
if (!arizona->pdata.micd_force_micbias) { if (!arizona->pdata.micd_force_micbias) {
mutex_lock(&dapm->card->dapm_mutex);
ret = snd_soc_dapm_disable_pin(arizona->dapm, widget); ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
if (ret != 0) if (ret != 0)
dev_warn(arizona->dev, "Failed to disable %s: %d\n", dev_warn(arizona->dev, "Failed to disable %s: %d\n",
widget, ret); widget, ret);
mutex_unlock(&dapm->card->dapm_mutex);
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
} }
} }
...@@ -304,16 +296,12 @@ static void arizona_stop_mic(struct arizona_extcon_info *info) ...@@ -304,16 +296,12 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
ARIZONA_MICD_ENA, 0, ARIZONA_MICD_ENA, 0,
&change); &change);
mutex_lock(&dapm->card->dapm_mutex);
ret = snd_soc_dapm_disable_pin(dapm, widget); ret = snd_soc_dapm_disable_pin(dapm, widget);
if (ret != 0) if (ret != 0)
dev_warn(arizona->dev, dev_warn(arizona->dev,
"Failed to disable %s: %d\n", "Failed to disable %s: %d\n",
widget, ret); widget, ret);
mutex_unlock(&dapm->card->dapm_mutex);
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
if (info->micd_reva) { if (info->micd_reva) {
......
...@@ -37,7 +37,6 @@ static void arizona_haptics_work(struct work_struct *work) ...@@ -37,7 +37,6 @@ static void arizona_haptics_work(struct work_struct *work)
struct arizona_haptics, struct arizona_haptics,
work); work);
struct arizona *arizona = haptics->arizona; struct arizona *arizona = haptics->arizona;
struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
int ret; int ret;
if (!haptics->arizona->dapm) { if (!haptics->arizona->dapm) {
...@@ -67,13 +66,10 @@ static void arizona_haptics_work(struct work_struct *work) ...@@ -67,13 +66,10 @@ static void arizona_haptics_work(struct work_struct *work)
return; return;
} }
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS"); ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to start HAPTICS: %d\n", dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
ret); ret);
mutex_unlock(dapm_mutex);
return; return;
} }
...@@ -81,21 +77,14 @@ static void arizona_haptics_work(struct work_struct *work) ...@@ -81,21 +77,14 @@ static void arizona_haptics_work(struct work_struct *work)
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to sync DAPM: %d\n", dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
ret); ret);
mutex_unlock(dapm_mutex);
return; return;
} }
mutex_unlock(dapm_mutex);
} else { } else {
/* This disable sequence will be a noop if already enabled */ /* This disable sequence will be a noop if already enabled */
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS"); ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n", dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
ret); ret);
mutex_unlock(dapm_mutex);
return; return;
} }
...@@ -103,12 +92,9 @@ static void arizona_haptics_work(struct work_struct *work) ...@@ -103,12 +92,9 @@ static void arizona_haptics_work(struct work_struct *work)
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to sync DAPM: %d\n", dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
ret); ret);
mutex_unlock(dapm_mutex);
return; return;
} }
mutex_unlock(dapm_mutex);
ret = regmap_update_bits(arizona->regmap, ret = regmap_update_bits(arizona->regmap,
ARIZONA_HAPTICS_CONTROL_1, ARIZONA_HAPTICS_CONTROL_1,
ARIZONA_HAP_CTRL_MASK, ARIZONA_HAP_CTRL_MASK,
...@@ -155,16 +141,11 @@ static int arizona_haptics_play(struct input_dev *input, void *data, ...@@ -155,16 +141,11 @@ static int arizona_haptics_play(struct input_dev *input, void *data,
static void arizona_haptics_close(struct input_dev *input) static void arizona_haptics_close(struct input_dev *input)
{ {
struct arizona_haptics *haptics = input_get_drvdata(input); struct arizona_haptics *haptics = input_get_drvdata(input);
struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
cancel_work_sync(&haptics->work); cancel_work_sync(&haptics->work);
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
if (haptics->arizona->dapm) if (haptics->arizona->dapm)
snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS"); snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
mutex_unlock(dapm_mutex);
} }
static int arizona_haptics_probe(struct platform_device *pdev) static int arizona_haptics_probe(struct platform_device *pdev)
......
...@@ -449,14 +449,23 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, ...@@ -449,14 +449,23 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
/* dapm audio pin control and status */ /* dapm audio pin control and status */
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin);
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin);
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin);
int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin);
int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm);
int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm);
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin);
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec); void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
......
...@@ -45,6 +45,11 @@ ...@@ -45,6 +45,11 @@
((unsigned long)&(struct soc_mixer_control) \ ((unsigned long)&(struct soc_mixer_control) \
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
.max = xmax, .platform_max = xmax, .invert = xinvert}) .max = xmax, .platform_max = xmax, .invert = xinvert})
#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
.max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \
.invert = xinvert})
#define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \ ((unsigned long)&(struct soc_mixer_control) \
{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
...@@ -152,6 +157,15 @@ ...@@ -152,6 +157,15 @@
{.reg = xreg, .rreg = xrreg, \ {.reg = xreg, .rreg = xrreg, \
.shift = xshift, .rshift = xshift, \ .shift = xshift, .rshift = xshift, \
.max = xmax, .min = xmin} } .max = xmax, .min = xmin} }
#define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, \
.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
.private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \
xmin, xmax, xsign_bit, xinvert) }
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
...@@ -1067,6 +1081,7 @@ struct soc_mixer_control { ...@@ -1067,6 +1081,7 @@ struct soc_mixer_control {
int min, max, platform_max; int min, max, platform_max;
int reg, rreg; int reg, rreg;
unsigned int shift, rshift; unsigned int shift, rshift;
unsigned int sign_bit;
unsigned int invert:1; unsigned int invert:1;
unsigned int autodisable:1; unsigned int autodisable:1;
}; };
...@@ -1188,4 +1203,15 @@ extern struct dentry *snd_soc_debugfs_root; ...@@ -1188,4 +1203,15 @@ extern struct dentry *snd_soc_debugfs_root;
extern const struct dev_pm_ops snd_soc_pm_ops; extern const struct dev_pm_ops snd_soc_pm_ops;
/* Helper functions */
static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm)
{
mutex_lock(&dapm->card->dapm_mutex);
}
static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
{
mutex_unlock(&dapm->card->dapm_mutex);
}
#endif #endif
...@@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = { ...@@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = {
"DMIC1", "DMIC1",
}; };
static const struct soc_enum adau1373_decimator_enum = static SOC_ENUM_SINGLE_DECL(adau1373_decimator_enum,
SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); 0, 0, adau1373_decimator_text);
static const struct snd_kcontrol_new adau1373_decimator_mux = static const struct snd_kcontrol_new adau1373_decimator_mux =
SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum);
......
...@@ -541,6 +541,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, ...@@ -541,6 +541,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
unsigned int freq, int dir) unsigned int freq, int dir)
{ {
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
if (dir == SND_SOC_CLOCK_IN) { if (dir == SND_SOC_CLOCK_IN) {
switch (clk_id) { switch (clk_id) {
...@@ -573,7 +574,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, ...@@ -573,7 +574,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2,
iclk_ctrl2); iclk_ctrl2);
snd_soc_dapm_sync(&codec->dapm); snd_soc_dapm_sync(dapm);
} }
} else { } else {
unsigned int mask; unsigned int mask;
...@@ -600,17 +601,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, ...@@ -600,17 +601,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
adav80x->sysclk_pd[clk_id] = false; adav80x->sysclk_pd[clk_id] = false;
} }
snd_soc_dapm_mutex_lock(dapm);
if (adav80x->sysclk_pd[0]) if (adav80x->sysclk_pd[0])
snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1");
else else
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1");
if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2])
snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2");
else else
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2");
snd_soc_dapm_sync(&codec->dapm); snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
} }
return 0; return 0;
......
This diff is collapsed.
...@@ -408,8 +408,8 @@ static const char * const adcl_enum_text[] = { ...@@ -408,8 +408,8 @@ static const char * const adcl_enum_text[] = {
"MC1L", "RXINL", "MC1L", "RXINL",
}; };
static const struct soc_enum adcl_enum = static SOC_ENUM_SINGLE_DECL(adcl_enum,
SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcl_enum_text), adcl_enum_text); 0, 0, adcl_enum_text);
static const struct snd_kcontrol_new left_input_mux = static const struct snd_kcontrol_new left_input_mux =
SOC_DAPM_ENUM_VIRT("Route", adcl_enum); SOC_DAPM_ENUM_VIRT("Route", adcl_enum);
...@@ -418,8 +418,8 @@ static const char * const adcr_enum_text[] = { ...@@ -418,8 +418,8 @@ static const char * const adcr_enum_text[] = {
"MC1R", "MC2", "RXINR", "TXIN", "MC1R", "MC2", "RXINR", "TXIN",
}; };
static const struct soc_enum adcr_enum = static SOC_ENUM_SINGLE_DECL(adcr_enum,
SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcr_enum_text), adcr_enum_text); 0, 0, adcr_enum_text);
static const struct snd_kcontrol_new right_input_mux = static const struct snd_kcontrol_new right_input_mux =
SOC_DAPM_ENUM_VIRT("Route", adcr_enum); SOC_DAPM_ENUM_VIRT("Route", adcr_enum);
...@@ -580,9 +580,9 @@ static struct snd_soc_dapm_route mc13783_routes[] = { ...@@ -580,9 +580,9 @@ static struct snd_soc_dapm_route mc13783_routes[] = {
static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix", static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix",
"Mono", "Mono Mix"}; "Mono", "Mono Mix"};
static const struct soc_enum mc13783_enum_3d_mixer = static SOC_ENUM_SINGLE_DECL(mc13783_enum_3d_mixer,
SOC_ENUM_SINGLE(MC13783_AUDIO_RX1, 16, ARRAY_SIZE(mc13783_3d_mixer), MC13783_AUDIO_RX1, 16,
mc13783_3d_mixer); mc13783_3d_mixer);
static struct snd_kcontrol_new mc13783_control_list[] = { static struct snd_kcontrol_new mc13783_control_list[] = {
SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0), SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0),
......
...@@ -2100,6 +2100,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100) ...@@ -2100,6 +2100,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100)
int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
{ {
struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
if (jack) { if (jack) {
wm5100->jack = jack; wm5100->jack = jack;
...@@ -2117,9 +2118,14 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) ...@@ -2117,9 +2118,14 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
WM5100_ACCDET_RATE_MASK); WM5100_ACCDET_RATE_MASK);
/* We need the charge pump to power MICBIAS */ /* We need the charge pump to power MICBIAS */
snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2"); snd_soc_dapm_mutex_lock(dapm);
snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
snd_soc_dapm_sync(&codec->dapm); snd_soc_dapm_force_enable_pin_unlocked(dapm, "CP2");
snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK");
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
/* We start off just enabling microphone detection - even a /* We start off just enabling microphone detection - even a
* plain headphone will trigger detection. * plain headphone will trigger detection.
......
...@@ -3089,6 +3089,7 @@ static irqreturn_t wm8962_irq(int irq, void *data) ...@@ -3089,6 +3089,7 @@ static irqreturn_t wm8962_irq(int irq, void *data)
int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
{ {
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
int irq_mask, enable; int irq_mask, enable;
wm8962->jack = jack; wm8962->jack = jack;
...@@ -3109,14 +3110,18 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) ...@@ -3109,14 +3110,18 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
snd_soc_jack_report(wm8962->jack, 0, snd_soc_jack_report(wm8962->jack, 0,
SND_JACK_MICROPHONE | SND_JACK_BTN_0); SND_JACK_MICROPHONE | SND_JACK_BTN_0);
snd_soc_dapm_mutex_lock(dapm);
if (jack) { if (jack) {
snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK");
snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS"); snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS");
} else { } else {
snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK"); snd_soc_dapm_disable_pin_unlocked(dapm, "SYSCLK");
snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS"); snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS");
} }
snd_soc_dapm_mutex_unlock(dapm);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(wm8962_mic_detect); EXPORT_SYMBOL_GPL(wm8962_mic_detect);
......
This diff is collapsed.
...@@ -561,10 +561,8 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w, ...@@ -561,10 +561,8 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) struct snd_kcontrol *kcontrol, int event)
{ {
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
struct wm8995_priv *wm8995;
codec = w->codec; codec = w->codec;
wm8995 = snd_soc_codec_get_drvdata(codec);
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
...@@ -783,14 +781,12 @@ static const char *sidetone_text[] = { ...@@ -783,14 +781,12 @@ static const char *sidetone_text[] = {
"ADC/DMIC1", "DMIC2", "ADC/DMIC1", "DMIC2",
}; };
static const struct soc_enum sidetone1_enum = static SOC_ENUM_SINGLE_DECL(sidetone1_enum, WM8995_SIDETONE, 0, sidetone_text);
SOC_ENUM_SINGLE(WM8995_SIDETONE, 0, 2, sidetone_text);
static const struct snd_kcontrol_new sidetone1_mux = static const struct snd_kcontrol_new sidetone1_mux =
SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum);
static const struct soc_enum sidetone2_enum = static SOC_ENUM_SINGLE_DECL(sidetone2_enum, WM8995_SIDETONE, 1, sidetone_text);
SOC_ENUM_SINGLE(WM8995_SIDETONE, 1, 2, sidetone_text);
static const struct snd_kcontrol_new sidetone2_mux = static const struct snd_kcontrol_new sidetone2_mux =
SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum);
...@@ -886,8 +882,7 @@ static const char *adc_mux_text[] = { ...@@ -886,8 +882,7 @@ static const char *adc_mux_text[] = {
"DMIC", "DMIC",
}; };
static const struct soc_enum adc_enum = static const SOC_ENUM_SINGLE_DECL(adc_enum, 0, 0, adc_mux_text);
SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text);
static const struct snd_kcontrol_new adcl_mux = static const struct snd_kcontrol_new adcl_mux =
SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum);
......
...@@ -2251,6 +2251,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, ...@@ -2251,6 +2251,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8996_polarity_fn polarity_cb) wm8996_polarity_fn polarity_cb)
{ {
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
wm8996->jack = jack; wm8996->jack = jack;
wm8996->detecting = true; wm8996->detecting = true;
...@@ -2267,8 +2268,12 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, ...@@ -2267,8 +2268,12 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
WM8996_MICB2_DISCH, 0); WM8996_MICB2_DISCH, 0);
/* LDO2 powers the microphones, SYSCLK clocks detection */ /* LDO2 powers the microphones, SYSCLK clocks detection */
snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); snd_soc_dapm_mutex_lock(dapm);
snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO2");
snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK");
snd_soc_dapm_mutex_unlock(dapm);
/* We start off just enabling microphone detection - even a /* We start off just enabling microphone detection - even a
* plain headphone will trigger detection. * plain headphone will trigger detection.
......
...@@ -101,20 +101,27 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol, ...@@ -101,20 +101,27 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_context *dapm = &codec->dapm;
if (ucontrol->value.integer.value[0] == hs_switch) if (ucontrol->value.integer.value[0] == hs_switch)
return 0; return 0;
snd_soc_dapm_mutex_lock(dapm);
if (ucontrol->value.integer.value[0]) { if (ucontrol->value.integer.value[0]) {
pr_debug("hs_set HS path\n"); pr_debug("hs_set HS path\n");
snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT");
} else { } else {
pr_debug("hs_set EP path\n"); pr_debug("hs_set EP path\n");
snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT");
} }
snd_soc_dapm_sync(&codec->dapm);
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
hs_switch = ucontrol->value.integer.value[0]; hs_switch = ucontrol->value.integer.value[0];
return 0; return 0;
...@@ -122,18 +129,20 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol, ...@@ -122,18 +129,20 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol,
static void lo_enable_out_pins(struct snd_soc_codec *codec) static void lo_enable_out_pins(struct snd_soc_codec *codec)
{ {
snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL"); struct snd_soc_dapm_context *dapm = &codec->dapm;
snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR");
snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL"); snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTL");
snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR"); snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTR");
snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT"); snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTL");
snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT"); snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTR");
snd_soc_dapm_enable_pin_unlocked(dapm, "VIB1OUT");
snd_soc_dapm_enable_pin_unlocked(dapm, "VIB2OUT");
if (hs_switch) { if (hs_switch) {
snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT");
} else { } else {
snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT");
} }
} }
...@@ -148,44 +157,52 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol, ...@@ -148,44 +157,52 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_context *dapm = &codec->dapm;
if (ucontrol->value.integer.value[0] == lo_dac) if (ucontrol->value.integer.value[0] == lo_dac)
return 0; return 0;
snd_soc_dapm_mutex_lock(dapm);
/* we dont want to work with last state of lineout so just enable all /* we dont want to work with last state of lineout so just enable all
* pins and then disable pins not required * pins and then disable pins not required
*/ */
lo_enable_out_pins(codec); lo_enable_out_pins(codec);
switch (ucontrol->value.integer.value[0]) { switch (ucontrol->value.integer.value[0]) {
case 0: case 0:
pr_debug("set vibra path\n"); pr_debug("set vibra path\n");
snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT"); snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT");
snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT"); snd_soc_dapm_disable_pin_unlocked(dapm, "VIB2OUT");
snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0);
break; break;
case 1: case 1:
pr_debug("set hs path\n"); pr_debug("set hs path\n");
snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones");
snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT");
snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22);
break; break;
case 2: case 2:
pr_debug("set spkr path\n"); pr_debug("set spkr path\n");
snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL"); snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTL");
snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR"); snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTR");
snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44);
break; break;
case 3: case 3:
pr_debug("set null path\n"); pr_debug("set null path\n");
snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL"); snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTL");
snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR"); snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTR");
snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66);
break; break;
} }
snd_soc_dapm_sync(&codec->dapm);
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
lo_dac = ucontrol->value.integer.value[0]; lo_dac = ucontrol->value.integer.value[0];
return 0; return 0;
} }
......
...@@ -106,57 +106,59 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, ...@@ -106,57 +106,59 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
if (ucontrol->value.enumerated.item[0] >= control->items) if (ucontrol->value.enumerated.item[0] >= control->items)
return -EINVAL; return -EINVAL;
mutex_lock(&codec->mutex); snd_soc_dapm_mutex_lock(dapm);
/* Translate selection to bitmap */ /* Translate selection to bitmap */
pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]];
/* Setup pins after corresponding bits if changed */ /* Setup pins after corresponding bits if changed */
pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE));
if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) { if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) {
changed = 1; changed = 1;
if (pin) if (pin)
snd_soc_dapm_enable_pin(dapm, "Mouthpiece"); snd_soc_dapm_enable_pin_unlocked(dapm, "Mouthpiece");
else else
snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece");
} }
pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); pin = !!(pins & (1 << AMS_DELTA_EARPIECE));
if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) { if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) {
changed = 1; changed = 1;
if (pin) if (pin)
snd_soc_dapm_enable_pin(dapm, "Earpiece"); snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece");
else else
snd_soc_dapm_disable_pin(dapm, "Earpiece"); snd_soc_dapm_disable_pin_unlocked(dapm, "Earpiece");
} }
pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); pin = !!(pins & (1 << AMS_DELTA_MICROPHONE));
if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) { if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) {
changed = 1; changed = 1;
if (pin) if (pin)
snd_soc_dapm_enable_pin(dapm, "Microphone"); snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone");
else else
snd_soc_dapm_disable_pin(dapm, "Microphone"); snd_soc_dapm_disable_pin_unlocked(dapm, "Microphone");
} }
pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); pin = !!(pins & (1 << AMS_DELTA_SPEAKER));
if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) { if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) {
changed = 1; changed = 1;
if (pin) if (pin)
snd_soc_dapm_enable_pin(dapm, "Speaker"); snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker");
else else
snd_soc_dapm_disable_pin(dapm, "Speaker"); snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker");
} }
pin = !!(pins & (1 << AMS_DELTA_AGC)); pin = !!(pins & (1 << AMS_DELTA_AGC));
if (pin != ams_delta_audio_agc) { if (pin != ams_delta_audio_agc) {
ams_delta_audio_agc = pin; ams_delta_audio_agc = pin;
changed = 1; changed = 1;
if (pin) if (pin)
snd_soc_dapm_enable_pin(dapm, "AGCIN"); snd_soc_dapm_enable_pin_unlocked(dapm, "AGCIN");
else else
snd_soc_dapm_disable_pin(dapm, "AGCIN"); snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN");
} }
if (changed) if (changed)
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync_unlocked(dapm);
mutex_unlock(&codec->mutex); snd_soc_dapm_mutex_unlock(dapm);
return changed; return changed;
} }
...@@ -315,12 +317,17 @@ static void cx81801_close(struct tty_struct *tty) ...@@ -315,12 +317,17 @@ static void cx81801_close(struct tty_struct *tty)
v253_ops.close(tty); v253_ops.close(tty);
/* Revert back to default audio input/output constellation */ /* Revert back to default audio input/output constellation */
snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); snd_soc_dapm_mutex_lock(dapm);
snd_soc_dapm_enable_pin(dapm, "Earpiece");
snd_soc_dapm_enable_pin(dapm, "Microphone"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece");
snd_soc_dapm_disable_pin(dapm, "Speaker"); snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece");
snd_soc_dapm_disable_pin(dapm, "AGCIN"); snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone");
snd_soc_dapm_sync(dapm); snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker");
snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN");
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(codec);
} }
/* Line discipline .hangup() */ /* Line discipline .hangup() */
......
...@@ -68,26 +68,30 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) ...@@ -68,26 +68,30 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm)
break; break;
} }
snd_soc_dapm_mutex_lock(dapm);
if (n810_spk_func) if (n810_spk_func)
snd_soc_dapm_enable_pin(dapm, "Ext Spk"); snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk");
else else
snd_soc_dapm_disable_pin(dapm, "Ext Spk"); snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk");
if (hp) if (hp)
snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
else else
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
if (line1l) if (line1l)
snd_soc_dapm_enable_pin(dapm, "LINE1L"); snd_soc_dapm_enable_pin_unlocked(dapm, "LINE1L");
else else
snd_soc_dapm_disable_pin(dapm, "LINE1L"); snd_soc_dapm_disable_pin_unlocked(dapm, "LINE1L");
if (n810_dmic_func) if (n810_dmic_func)
snd_soc_dapm_enable_pin(dapm, "DMic"); snd_soc_dapm_enable_pin_unlocked(dapm, "DMic");
else else
snd_soc_dapm_disable_pin(dapm, "DMic"); snd_soc_dapm_disable_pin_unlocked(dapm, "DMic");
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_sync(dapm); snd_soc_dapm_mutex_unlock(dapm);
} }
static int n810_startup(struct snd_pcm_substream *substream) static int n810_startup(struct snd_pcm_substream *substream)
......
...@@ -74,26 +74,30 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) ...@@ -74,26 +74,30 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
break; break;
} }
snd_soc_dapm_mutex_lock(dapm);
if (rx51_spk_func) if (rx51_spk_func)
snd_soc_dapm_enable_pin(dapm, "Ext Spk"); snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk");
else else
snd_soc_dapm_disable_pin(dapm, "Ext Spk"); snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk");
if (rx51_dmic_func) if (rx51_dmic_func)
snd_soc_dapm_enable_pin(dapm, "DMic"); snd_soc_dapm_enable_pin_unlocked(dapm, "DMic");
else else
snd_soc_dapm_disable_pin(dapm, "DMic"); snd_soc_dapm_disable_pin_unlocked(dapm, "DMic");
if (hp) if (hp)
snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
else else
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
if (hs) if (hs)
snd_soc_dapm_enable_pin(dapm, "HS Mic"); snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic");
else else
snd_soc_dapm_disable_pin(dapm, "HS Mic"); snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic");
gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout); gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout);
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
} }
static int rx51_startup(struct snd_pcm_substream *substream) static int rx51_startup(struct snd_pcm_substream *substream)
......
...@@ -47,51 +47,55 @@ static int corgi_spk_func; ...@@ -47,51 +47,55 @@ static int corgi_spk_func;
static void corgi_ext_control(struct snd_soc_dapm_context *dapm) static void corgi_ext_control(struct snd_soc_dapm_context *dapm)
{ {
snd_soc_dapm_mutex_lock(dapm);
/* set up jack connection */ /* set up jack connection */
switch (corgi_jack_func) { switch (corgi_jack_func) {
case CORGI_HP: case CORGI_HP:
/* set = unmute headphone */ /* set = unmute headphone */
gpio_set_value(CORGI_GPIO_MUTE_L, 1); gpio_set_value(CORGI_GPIO_MUTE_L, 1);
gpio_set_value(CORGI_GPIO_MUTE_R, 1); gpio_set_value(CORGI_GPIO_MUTE_R, 1);
snd_soc_dapm_disable_pin(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack");
snd_soc_dapm_disable_pin(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
break; break;
case CORGI_MIC: case CORGI_MIC:
/* reset = mute headphone */ /* reset = mute headphone */
gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_L, 0);
gpio_set_value(CORGI_GPIO_MUTE_R, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 0);
snd_soc_dapm_enable_pin(dapm, "Mic Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack");
snd_soc_dapm_disable_pin(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
break; break;
case CORGI_LINE: case CORGI_LINE:
gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_L, 0);
gpio_set_value(CORGI_GPIO_MUTE_R, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 0);
snd_soc_dapm_disable_pin(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack");
snd_soc_dapm_enable_pin(dapm, "Line Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack");
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
break; break;
case CORGI_HEADSET: case CORGI_HEADSET:
gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_L, 0);
gpio_set_value(CORGI_GPIO_MUTE_R, 1); gpio_set_value(CORGI_GPIO_MUTE_R, 1);
snd_soc_dapm_enable_pin(dapm, "Mic Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack");
snd_soc_dapm_disable_pin(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Headset Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack");
break; break;
} }
if (corgi_spk_func == CORGI_SPK_ON) if (corgi_spk_func == CORGI_SPK_ON)
snd_soc_dapm_enable_pin(dapm, "Ext Spk"); snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk");
else else
snd_soc_dapm_disable_pin(dapm, "Ext Spk"); snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk");
/* signal a DAPM event */ /* signal a DAPM event */
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
} }
static int corgi_startup(struct snd_pcm_substream *substream) static int corgi_startup(struct snd_pcm_substream *substream)
......
...@@ -45,27 +45,31 @@ static void magician_ext_control(struct snd_soc_codec *codec) ...@@ -45,27 +45,31 @@ static void magician_ext_control(struct snd_soc_codec *codec)
{ {
struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &codec->dapm;
snd_soc_dapm_mutex_lock(dapm);
if (magician_spk_switch) if (magician_spk_switch)
snd_soc_dapm_enable_pin(dapm, "Speaker"); snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker");
else else
snd_soc_dapm_disable_pin(dapm, "Speaker"); snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker");
if (magician_hp_switch) if (magician_hp_switch)
snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
else else
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
switch (magician_in_sel) { switch (magician_in_sel) {
case MAGICIAN_MIC: case MAGICIAN_MIC:
snd_soc_dapm_disable_pin(dapm, "Headset Mic"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Mic");
snd_soc_dapm_enable_pin(dapm, "Call Mic"); snd_soc_dapm_enable_pin_unlocked(dapm, "Call Mic");
break; break;
case MAGICIAN_MIC_EXT: case MAGICIAN_MIC_EXT:
snd_soc_dapm_disable_pin(dapm, "Call Mic"); snd_soc_dapm_disable_pin_unlocked(dapm, "Call Mic");
snd_soc_dapm_enable_pin(dapm, "Headset Mic"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Mic");
break; break;
} }
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
} }
static int magician_startup(struct snd_pcm_substream *substream) static int magician_startup(struct snd_pcm_substream *substream)
......
...@@ -46,61 +46,66 @@ static int spitz_mic_gpio; ...@@ -46,61 +46,66 @@ static int spitz_mic_gpio;
static void spitz_ext_control(struct snd_soc_dapm_context *dapm) static void spitz_ext_control(struct snd_soc_dapm_context *dapm)
{ {
snd_soc_dapm_mutex_lock(dapm);
if (spitz_spk_func == SPITZ_SPK_ON) if (spitz_spk_func == SPITZ_SPK_ON)
snd_soc_dapm_enable_pin(dapm, "Ext Spk"); snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk");
else else
snd_soc_dapm_disable_pin(dapm, "Ext Spk"); snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk");
/* set up jack connection */ /* set up jack connection */
switch (spitz_jack_func) { switch (spitz_jack_func) {
case SPITZ_HP: case SPITZ_HP:
/* enable and unmute hp jack, disable mic bias */ /* enable and unmute hp jack, disable mic bias */
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
snd_soc_dapm_disable_pin(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack");
snd_soc_dapm_disable_pin(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
gpio_set_value(SPITZ_GPIO_MUTE_L, 1); gpio_set_value(SPITZ_GPIO_MUTE_L, 1);
gpio_set_value(SPITZ_GPIO_MUTE_R, 1); gpio_set_value(SPITZ_GPIO_MUTE_R, 1);
break; break;
case SPITZ_MIC: case SPITZ_MIC:
/* enable mic jack and bias, mute hp */ /* enable mic jack and bias, mute hp */
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
snd_soc_dapm_disable_pin(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
snd_soc_dapm_enable_pin(dapm, "Mic Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack");
gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
gpio_set_value(SPITZ_GPIO_MUTE_R, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
break; break;
case SPITZ_LINE: case SPITZ_LINE:
/* enable line jack, disable mic bias and mute hp */ /* enable line jack, disable mic bias and mute hp */
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
snd_soc_dapm_disable_pin(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack");
snd_soc_dapm_enable_pin(dapm, "Line Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack");
gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
gpio_set_value(SPITZ_GPIO_MUTE_R, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
break; break;
case SPITZ_HEADSET: case SPITZ_HEADSET:
/* enable and unmute headset jack enable mic bias, mute L hp */ /* enable and unmute headset jack enable mic bias, mute L hp */
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Mic Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack");
snd_soc_dapm_disable_pin(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
snd_soc_dapm_enable_pin(dapm, "Headset Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack");
gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
gpio_set_value(SPITZ_GPIO_MUTE_R, 1); gpio_set_value(SPITZ_GPIO_MUTE_R, 1);
break; break;
case SPITZ_HP_OFF: case SPITZ_HP_OFF:
/* jack removed, everything off */ /* jack removed, everything off */
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
snd_soc_dapm_disable_pin(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack");
snd_soc_dapm_disable_pin(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
gpio_set_value(SPITZ_GPIO_MUTE_R, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
break; break;
} }
snd_soc_dapm_sync(dapm);
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
} }
static int spitz_startup(struct snd_pcm_substream *substream) static int spitz_startup(struct snd_pcm_substream *substream)
......
...@@ -48,31 +48,35 @@ static void tosa_ext_control(struct snd_soc_codec *codec) ...@@ -48,31 +48,35 @@ static void tosa_ext_control(struct snd_soc_codec *codec)
{ {
struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &codec->dapm;
snd_soc_dapm_mutex_lock(dapm);
/* set up jack connection */ /* set up jack connection */
switch (tosa_jack_func) { switch (tosa_jack_func) {
case TOSA_HP: case TOSA_HP:
snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)");
snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
break; break;
case TOSA_MIC_INT: case TOSA_MIC_INT:
snd_soc_dapm_enable_pin(dapm, "Mic (Internal)"); snd_soc_dapm_enable_pin_unlocked(dapm, "Mic (Internal)");
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_disable_pin(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
break; break;
case TOSA_HEADSET: case TOSA_HEADSET:
snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)");
snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Headset Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack");
break; break;
} }
if (tosa_spk_func == TOSA_SPK_ON) if (tosa_spk_func == TOSA_SPK_ON)
snd_soc_dapm_enable_pin(dapm, "Speaker"); snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker");
else else
snd_soc_dapm_disable_pin(dapm, "Speaker"); snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker");
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_sync(dapm); snd_soc_dapm_mutex_unlock(dapm);
} }
static int tosa_startup(struct snd_pcm_substream *substream) static int tosa_startup(struct snd_pcm_substream *substream)
......
...@@ -2715,6 +2715,48 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, ...@@ -2715,6 +2715,48 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
} }
EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
/**
* snd_soc_read_signed - Read a codec register and interprete as signed value
* @codec: codec
* @reg: Register to read
* @mask: Mask to use after shifting the register value
* @shift: Right shift of register value
* @sign_bit: Bit that describes if a number is negative or not.
*
* This functions reads a codec register. The register value is shifted right
* by 'shift' bits and masked with the given 'mask'. Afterwards it translates
* the given registervalue into a signed integer if sign_bit is non-zero.
*
* Returns the register value as signed int.
*/
static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg,
unsigned int mask, unsigned int shift, unsigned int sign_bit)
{
int ret;
unsigned int val;
val = (snd_soc_read(codec, reg) >> shift) & mask;
if (!sign_bit)
return val;
/* non-negative number */
if (!(val & BIT(sign_bit)))
return val;
ret = val;
/*
* The register most probably does not contain a full-sized int.
* Instead we have an arbitrary number of bits in a signed
* representation which has to be translated into a full-sized int.
* This is done by filling up all bits above the sign-bit.
*/
ret |= ~((int)(BIT(sign_bit) - 1));
return ret;
}
/** /**
* snd_soc_info_volsw - single mixer info callback * snd_soc_info_volsw - single mixer info callback
* @kcontrol: mixer control * @kcontrol: mixer control
...@@ -2743,7 +2785,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, ...@@ -2743,7 +2785,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
uinfo->value.integer.min = 0; uinfo->value.integer.min = 0;
uinfo->value.integer.max = platform_max; uinfo->value.integer.max = platform_max - mc->min;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_info_volsw); EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
...@@ -2769,11 +2811,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, ...@@ -2769,11 +2811,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
unsigned int shift = mc->shift; unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift; unsigned int rshift = mc->rshift;
int max = mc->max; int max = mc->max;
int min = mc->min;
int sign_bit = mc->sign_bit;
unsigned int mask = (1 << fls(max)) - 1; unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert; unsigned int invert = mc->invert;
ucontrol->value.integer.value[0] = if (sign_bit)
(snd_soc_read(codec, reg) >> shift) & mask; mask = BIT(sign_bit + 1) - 1;
ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask,
shift, sign_bit) - min;
if (invert) if (invert)
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
max - ucontrol->value.integer.value[0]; max - ucontrol->value.integer.value[0];
...@@ -2781,10 +2828,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, ...@@ -2781,10 +2828,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
if (snd_soc_volsw_is_stereo(mc)) { if (snd_soc_volsw_is_stereo(mc)) {
if (reg == reg2) if (reg == reg2)
ucontrol->value.integer.value[1] = ucontrol->value.integer.value[1] =
(snd_soc_read(codec, reg) >> rshift) & mask; snd_soc_read_signed(codec, reg, mask, rshift,
sign_bit) - min;
else else
ucontrol->value.integer.value[1] = ucontrol->value.integer.value[1] =
(snd_soc_read(codec, reg2) >> shift) & mask; snd_soc_read_signed(codec, reg2, mask, shift,
sign_bit) - min;
if (invert) if (invert)
ucontrol->value.integer.value[1] = ucontrol->value.integer.value[1] =
max - ucontrol->value.integer.value[1]; max - ucontrol->value.integer.value[1];
...@@ -2815,6 +2864,8 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, ...@@ -2815,6 +2864,8 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
unsigned int shift = mc->shift; unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift; unsigned int rshift = mc->rshift;
int max = mc->max; int max = mc->max;
int min = mc->min;
unsigned int sign_bit = mc->sign_bit;
unsigned int mask = (1 << fls(max)) - 1; unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert; unsigned int invert = mc->invert;
int err; int err;
...@@ -2822,13 +2873,16 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, ...@@ -2822,13 +2873,16 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
unsigned int val2 = 0; unsigned int val2 = 0;
unsigned int val, val_mask; unsigned int val, val_mask;
val = (ucontrol->value.integer.value[0] & mask); if (sign_bit)
mask = BIT(sign_bit + 1) - 1;
val = ((ucontrol->value.integer.value[0] + min) & mask);
if (invert) if (invert)
val = max - val; val = max - val;
val_mask = mask << shift; val_mask = mask << shift;
val = val << shift; val = val << shift;
if (snd_soc_volsw_is_stereo(mc)) { if (snd_soc_volsw_is_stereo(mc)) {
val2 = (ucontrol->value.integer.value[1] & mask); val2 = ((ucontrol->value.integer.value[1] + min) & mask);
if (invert) if (invert)
val2 = max - val2; val2 = max - val2;
if (reg == reg2) { if (reg == reg2) {
......
...@@ -386,7 +386,8 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, ...@@ -386,7 +386,8 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
return -1; return -1;
} }
static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val) static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg,
unsigned int val)
{ {
if (w->codec) if (w->codec)
return snd_soc_write(w->codec, reg, val); return snd_soc_write(w->codec, reg, val);
...@@ -506,7 +507,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, ...@@ -506,7 +507,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_switch: case snd_soc_dapm_switch:
case snd_soc_dapm_mixer: case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl: { case snd_soc_dapm_mixer_named_ctl: {
int val; unsigned int val;
struct soc_mixer_control *mc = (struct soc_mixer_control *) struct soc_mixer_control *mc = (struct soc_mixer_control *)
w->kcontrol_news[i].private_value; w->kcontrol_news[i].private_value;
int reg = mc->reg; int reg = mc->reg;
...@@ -530,7 +531,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, ...@@ -530,7 +531,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_mux: { case snd_soc_dapm_mux: {
struct soc_enum *e = (struct soc_enum *) struct soc_enum *e = (struct soc_enum *)
w->kcontrol_news[i].private_value; w->kcontrol_news[i].private_value;
int val, item; unsigned int val, item;
soc_widget_read(w, e->reg, &val); soc_widget_read(w, e->reg, &val);
item = (val >> e->shift_l) & e->mask; item = (val >> e->shift_l) & e->mask;
...@@ -559,7 +560,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, ...@@ -559,7 +560,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_value_mux: { case snd_soc_dapm_value_mux: {
struct soc_enum *e = (struct soc_enum *) struct soc_enum *e = (struct soc_enum *)
w->kcontrol_news[i].private_value; w->kcontrol_news[i].private_value;
int val, item; unsigned int val, item;
soc_widget_read(w, e->reg, &val); soc_widget_read(w, e->reg, &val);
val = (val >> e->shift_l) & e->mask; val = (val >> e->shift_l) & e->mask;
...@@ -1218,7 +1219,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, ...@@ -1218,7 +1219,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
ret = regulator_allow_bypass(w->regulator, false); ret = regulator_allow_bypass(w->regulator, false);
if (ret != 0) if (ret != 0)
dev_warn(w->dapm->dev, dev_warn(w->dapm->dev,
"ASoC: Failed to bypass %s: %d\n", "ASoC: Failed to unbypass %s: %d\n",
w->name, ret); w->name, ret);
} }
...@@ -1228,7 +1229,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, ...@@ -1228,7 +1229,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
ret = regulator_allow_bypass(w->regulator, true); ret = regulator_allow_bypass(w->regulator, true);
if (ret != 0) if (ret != 0)
dev_warn(w->dapm->dev, dev_warn(w->dapm->dev,
"ASoC: Failed to unbypass %s: %d\n", "ASoC: Failed to bypass %s: %d\n",
w->name, ret); w->name, ret);
} }
...@@ -2341,18 +2342,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, ...@@ -2341,18 +2342,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
} }
/** /**
* snd_soc_dapm_sync - scan and power dapm paths * snd_soc_dapm_sync_unlocked - scan and power dapm paths
* @dapm: DAPM context * @dapm: DAPM context
* *
* Walks all dapm audio paths and powers widgets according to their * Walks all dapm audio paths and powers widgets according to their
* stream or path usage. * stream or path usage.
* *
* Requires external locking.
*
* Returns 0 for success. * Returns 0 for success.
*/ */
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm)
{ {
int ret;
/* /*
* Suppress early reports (eg, jacks syncing their state) to avoid * Suppress early reports (eg, jacks syncing their state) to avoid
* silly DAPM runs during card startup. * silly DAPM runs during card startup.
...@@ -2360,8 +2361,25 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) ...@@ -2360,8 +2361,25 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
if (!dapm->card || !dapm->card->instantiated) if (!dapm->card || !dapm->card->instantiated)
return 0; return 0;
return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked);
/**
* snd_soc_dapm_sync - scan and power dapm paths
* @dapm: DAPM context
*
* Walks all dapm audio paths and powers widgets according to their
* stream or path usage.
*
* Returns 0 for success.
*/
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
{
int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); ret = snd_soc_dapm_sync_unlocked(dapm);
mutex_unlock(&dapm->card->dapm_mutex); mutex_unlock(&dapm->card->dapm_mutex);
return ret; return ret;
} }
...@@ -3210,15 +3228,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, ...@@ -3210,15 +3228,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value; const char *pin = (const char *)kcontrol->private_value;
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
if (ucontrol->value.integer.value[0]) if (ucontrol->value.integer.value[0])
snd_soc_dapm_enable_pin(&card->dapm, pin); snd_soc_dapm_enable_pin(&card->dapm, pin);
else else
snd_soc_dapm_disable_pin(&card->dapm, pin); snd_soc_dapm_disable_pin(&card->dapm, pin);
mutex_unlock(&card->dapm_mutex);
snd_soc_dapm_sync(&card->dapm); snd_soc_dapm_sync(&card->dapm);
return 0; return 0;
} }
...@@ -3248,7 +3262,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, ...@@ -3248,7 +3262,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
ret = regulator_allow_bypass(w->regulator, true); ret = regulator_allow_bypass(w->regulator, true);
if (ret != 0) if (ret != 0)
dev_warn(w->dapm->dev, dev_warn(w->dapm->dev,
"ASoC: Failed to unbypass %s: %d\n", "ASoC: Failed to bypass %s: %d\n",
w->name, ret); w->name, ret);
} }
break; break;
...@@ -3766,6 +3780,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, ...@@ -3766,6 +3780,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
mutex_unlock(&card->dapm_mutex); mutex_unlock(&card->dapm_mutex);
} }
/**
* snd_soc_dapm_enable_pin_unlocked - enable pin.
* @dapm: DAPM context
* @pin: pin name
*
* Enables input/output pin and its parents or children widgets iff there is
* a valid audio route and active audio stream.
*
* Requires external locking.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching.
*/
int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin)
{
return snd_soc_dapm_set_pin(dapm, pin, 1);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);
/** /**
* snd_soc_dapm_enable_pin - enable pin. * snd_soc_dapm_enable_pin - enable pin.
* @dapm: DAPM context * @dapm: DAPM context
...@@ -3773,17 +3807,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, ...@@ -3773,17 +3807,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
* *
* Enables input/output pin and its parents or children widgets iff there is * Enables input/output pin and its parents or children widgets iff there is
* a valid audio route and active audio stream. * a valid audio route and active audio stream.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching. * do any widget power switching.
*/ */
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
{ {
return snd_soc_dapm_set_pin(dapm, pin, 1); int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_set_pin(dapm, pin, 1);
mutex_unlock(&dapm->card->dapm_mutex);
return ret;
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
/** /**
* snd_soc_dapm_force_enable_pin - force a pin to be enabled * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
* @dapm: DAPM context * @dapm: DAPM context
* @pin: pin name * @pin: pin name
* *
...@@ -3791,11 +3834,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); ...@@ -3791,11 +3834,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
* intended for use with microphone bias supplies used in microphone * intended for use with microphone bias supplies used in microphone
* jack detection. * jack detection.
* *
* Requires external locking.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching. * do any widget power switching.
*/ */
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin) const char *pin)
{ {
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
...@@ -3811,24 +3856,102 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, ...@@ -3811,24 +3856,102 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);
/**
* snd_soc_dapm_force_enable_pin - force a pin to be enabled
* @dapm: DAPM context
* @pin: pin name
*
* Enables input/output pin regardless of any other state. This is
* intended for use with microphone bias supplies used in microphone
* jack detection.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching.
*/
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
const char *pin)
{
int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
mutex_unlock(&dapm->card->dapm_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
/**
* snd_soc_dapm_disable_pin_unlocked - disable pin.
* @dapm: DAPM context
* @pin: pin name
*
* Disables input/output pin and its parents or children widgets.
*
* Requires external locking.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching.
*/
int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin)
{
return snd_soc_dapm_set_pin(dapm, pin, 0);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);
/** /**
* snd_soc_dapm_disable_pin - disable pin. * snd_soc_dapm_disable_pin - disable pin.
* @dapm: DAPM context * @dapm: DAPM context
* @pin: pin name * @pin: pin name
* *
* Disables input/output pin and its parents or children widgets. * Disables input/output pin and its parents or children widgets.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching. * do any widget power switching.
*/ */
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
const char *pin) const char *pin)
{ {
return snd_soc_dapm_set_pin(dapm, pin, 0); int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_set_pin(dapm, pin, 0);
mutex_unlock(&dapm->card->dapm_mutex);
return ret;
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
/**
* snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
* @dapm: DAPM context
* @pin: pin name
*
* Marks the specified pin as being not connected, disabling it along
* any parent or child widgets. At present this is identical to
* snd_soc_dapm_disable_pin() but in future it will be extended to do
* additional things such as disabling controls which only affect
* paths through the pin.
*
* Requires external locking.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching.
*/
int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin)
{
return snd_soc_dapm_set_pin(dapm, pin, 0);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);
/** /**
* snd_soc_dapm_nc_pin - permanently disable pin. * snd_soc_dapm_nc_pin - permanently disable pin.
* @dapm: DAPM context * @dapm: DAPM context
...@@ -3845,7 +3968,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); ...@@ -3845,7 +3968,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
*/ */
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
{ {
return snd_soc_dapm_set_pin(dapm, pin, 0); int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_set_pin(dapm, pin, 0);
mutex_unlock(&dapm->card->dapm_mutex);
return ret;
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment