diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-01-23 05:38:54 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-01-30 23:18:57 -0500 |
commit | 8e9bb423a2f70eb5f15ba5cc4423b0b6f75133e2 (patch) | |
tree | 50119b19e7ef50f213cfe8126ef551df5f3d2e1e /sound/soc | |
parent | 949db153b6466c6f7cad5a427ecea94985927311 (diff) |
ASoC: wm2000: Lock state machine updates
Need to ensure we don't get confused by simultaneous updates.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/codecs/wm2000.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 12bcae63a7f0..eb96b8768098 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -76,6 +76,8 @@ struct wm2000_priv { | |||
76 | 76 | ||
77 | int anc_download_size; | 77 | int anc_download_size; |
78 | char *anc_download; | 78 | char *anc_download; |
79 | |||
80 | struct mutex lock; | ||
79 | }; | 81 | }; |
80 | 82 | ||
81 | static int wm2000_write(struct i2c_client *i2c, unsigned int reg, | 83 | static int wm2000_write(struct i2c_client *i2c, unsigned int reg, |
@@ -599,13 +601,20 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol, | |||
599 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 601 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
600 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); | 602 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); |
601 | int anc_active = ucontrol->value.enumerated.item[0]; | 603 | int anc_active = ucontrol->value.enumerated.item[0]; |
604 | int ret; | ||
602 | 605 | ||
603 | if (anc_active > 1) | 606 | if (anc_active > 1) |
604 | return -EINVAL; | 607 | return -EINVAL; |
605 | 608 | ||
609 | mutex_lock(&wm2000->lock); | ||
610 | |||
606 | wm2000->anc_active = anc_active; | 611 | wm2000->anc_active = anc_active; |
607 | 612 | ||
608 | return wm2000_anc_set_mode(wm2000); | 613 | ret = wm2000_anc_set_mode(wm2000); |
614 | |||
615 | mutex_unlock(&wm2000->lock); | ||
616 | |||
617 | return ret; | ||
609 | } | 618 | } |
610 | 619 | ||
611 | static int wm2000_speaker_get(struct snd_kcontrol *kcontrol, | 620 | static int wm2000_speaker_get(struct snd_kcontrol *kcontrol, |
@@ -625,13 +634,20 @@ static int wm2000_speaker_put(struct snd_kcontrol *kcontrol, | |||
625 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 634 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
626 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); | 635 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); |
627 | int val = ucontrol->value.enumerated.item[0]; | 636 | int val = ucontrol->value.enumerated.item[0]; |
637 | int ret; | ||
628 | 638 | ||
629 | if (val > 1) | 639 | if (val > 1) |
630 | return -EINVAL; | 640 | return -EINVAL; |
631 | 641 | ||
642 | mutex_lock(&wm2000->lock); | ||
643 | |||
632 | wm2000->spk_ena = val; | 644 | wm2000->spk_ena = val; |
633 | 645 | ||
634 | return wm2000_anc_set_mode(wm2000); | 646 | ret = wm2000_anc_set_mode(wm2000); |
647 | |||
648 | mutex_unlock(&wm2000->lock); | ||
649 | |||
650 | return ret; | ||
635 | } | 651 | } |
636 | 652 | ||
637 | static const struct snd_kcontrol_new wm2000_controls[] = { | 653 | static const struct snd_kcontrol_new wm2000_controls[] = { |
@@ -648,6 +664,9 @@ static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w, | |||
648 | { | 664 | { |
649 | struct snd_soc_codec *codec = w->codec; | 665 | struct snd_soc_codec *codec = w->codec; |
650 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); | 666 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); |
667 | int ret; | ||
668 | |||
669 | mutex_lock(&wm2000->lock); | ||
651 | 670 | ||
652 | if (SND_SOC_DAPM_EVENT_ON(event)) | 671 | if (SND_SOC_DAPM_EVENT_ON(event)) |
653 | wm2000->anc_eng_ena = 1; | 672 | wm2000->anc_eng_ena = 1; |
@@ -655,7 +674,11 @@ static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w, | |||
655 | if (SND_SOC_DAPM_EVENT_OFF(event)) | 674 | if (SND_SOC_DAPM_EVENT_OFF(event)) |
656 | wm2000->anc_eng_ena = 0; | 675 | wm2000->anc_eng_ena = 0; |
657 | 676 | ||
658 | return wm2000_anc_set_mode(wm2000); | 677 | ret = wm2000_anc_set_mode(wm2000); |
678 | |||
679 | mutex_unlock(&wm2000->lock); | ||
680 | |||
681 | return ret; | ||
659 | } | 682 | } |
660 | 683 | ||
661 | static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = { | 684 | static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = { |
@@ -782,6 +805,8 @@ static int wm2000_i2c_probe(struct i2c_client *i2c, | |||
782 | return -ENOMEM; | 805 | return -ENOMEM; |
783 | } | 806 | } |
784 | 807 | ||
808 | mutex_init(&wm2000->lock); | ||
809 | |||
785 | dev_set_drvdata(&i2c->dev, wm2000); | 810 | dev_set_drvdata(&i2c->dev, wm2000); |
786 | 811 | ||
787 | wm2000->regmap = devm_regmap_init_i2c(i2c, &wm2000_regmap); | 812 | wm2000->regmap = devm_regmap_init_i2c(i2c, &wm2000_regmap); |