From 7e9614ebcf4d74edba864cc91e1e8a3ec6b32fc2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 19:55:45 +0000 Subject: ASoC: wm8962: Hold a runtime PM reference while handling interrupts If the device is runtime suspended then we can't interact with it as it may have been powered off and the register map will be in cache only mode. Signed-off-by: Mark Brown Acked-by: Charles Keepax --- sound/soc/codecs/wm8962.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs/wm8962.c') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 97db3b45b411..1996567346c6 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3003,9 +3003,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) unsigned int active; int reg, ret; + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "Failed to resume: %d\n", ret); + return IRQ_NONE; + } + ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK, &mask); if (ret != 0) { + pm_runtime_put(dev); dev_err(dev, "Failed to read interrupt mask: %d\n", ret); return IRQ_NONE; @@ -3013,14 +3020,17 @@ static irqreturn_t wm8962_irq(int irq, void *data) ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active); if (ret != 0) { + pm_runtime_put(dev); dev_err(dev, "Failed to read interrupt: %d\n", ret); return IRQ_NONE; } active &= ~mask; - if (!active) + if (!active) { + pm_runtime_put(dev); return IRQ_NONE; + } /* Acknowledge the interrupts */ ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active); @@ -3070,6 +3080,8 @@ static irqreturn_t wm8962_irq(int irq, void *data) msecs_to_jiffies(250)); } + pm_runtime_put(dev); + return IRQ_HANDLED; } -- cgit v1.2.1 From df6ab65f2fef3d7b769f3ba87c7bb265ace80b4e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 19:59:31 +0000 Subject: ASoC: wm8962: Check if we runtime resume the device when starting FLL Signed-off-by: Mark Brown Acked-by: Charles Keepax --- sound/soc/codecs/wm8962.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs/wm8962.c') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 1996567346c6..d7d43c9371f4 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2886,7 +2886,11 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, try_wait_for_completion(&wm8962->fll_lock); - pm_runtime_get_sync(codec->dev); + ret = pm_runtime_get_sync(codec->dev); + if (ret < 0) { + dev_err(codec->dev, "Failed to resume device: %d\n", ret); + return ret; + } snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | -- cgit v1.2.1 From d6f95e5407674d2f7d61feef81fef96b364d9188 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 20:04:34 +0000 Subject: ASoC: wm8962: Clean up error handling for failed FLL start Don't record the FLL as having started and leave the hardware disabled ensuring we are in a better state if this does happen to be a transient error and making debugging easier. Signed-off-by: Mark Brown Acked-by: Charles Keepax --- sound/soc/codecs/wm8962.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sound/soc/codecs/wm8962.c') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d7d43c9371f4..cd96d463a505 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2898,8 +2898,6 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); - ret = 0; - /* This should be a massive overestimate but go even * higher if we'll error out */ @@ -2913,14 +2911,17 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, if (timeout == 0 && wm8962->irq) { dev_err(codec->dev, "FLL lock timed out"); - ret = -ETIMEDOUT; + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_ENA, 0); + pm_runtime_put(codec->dev); + return -ETIMEDOUT; } wm8962->fll_fref = Fref; wm8962->fll_fout = Fout; wm8962->fll_src = source; - return ret; + return 0; } static int wm8962_mute(struct snd_soc_dai *dai, int mute) -- cgit v1.2.1 From 9d7433b064a6349aae8a266e8243ef75637bec45 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 20:32:06 +0000 Subject: ASoC: wm8962: Reinitialise the IRQ completion rather than just trying it This is better practice. Signed-off-by: Mark Brown Acked-by: Charles Keepax --- sound/soc/codecs/wm8962.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs/wm8962.c') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index cd96d463a505..c06bb5088e60 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2884,7 +2884,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); - try_wait_for_completion(&wm8962->fll_lock); + reinit_completion(&wm8962->fll_lock); ret = pm_runtime_get_sync(codec->dev); if (ret < 0) { -- cgit v1.2.1 From da6ebf83bb8f3ad5e12b2543f15962e27939ff7f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:07 +0100 Subject: ASoC: wm8962: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'sound/soc/codecs/wm8962.c') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index c06bb5088e60..3924ee243745 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1658,16 +1658,16 @@ static const char *cap_hpf_mode_text[] = { "Hi-fi", "Application" }; -static const struct soc_enum cap_hpf_mode = - SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(cap_hpf_mode, + WM8962_ADC_DAC_CONTROL_2, 10, cap_hpf_mode_text); static const char *cap_lhpf_mode_text[] = { "LPF", "HPF" }; -static const struct soc_enum cap_lhpf_mode = - SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(cap_lhpf_mode, + WM8962_LHPF1, 1, cap_lhpf_mode_text); static const struct snd_kcontrol_new wm8962_snd_controls[] = { SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), @@ -2014,40 +2014,40 @@ static int dsp2_event(struct snd_soc_dapm_widget *w, static const char *st_text[] = { "None", "Left", "Right" }; -static const struct soc_enum str_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text); +static SOC_ENUM_SINGLE_DECL(str_enum, + WM8962_DAC_DSP_MIXING_1, 2, st_text); static const struct snd_kcontrol_new str_mux = SOC_DAPM_ENUM("Right Sidetone", str_enum); -static const struct soc_enum stl_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text); +static SOC_ENUM_SINGLE_DECL(stl_enum, + WM8962_DAC_DSP_MIXING_2, 2, st_text); static const struct snd_kcontrol_new stl_mux = SOC_DAPM_ENUM("Left Sidetone", stl_enum); static const char *outmux_text[] = { "DAC", "Mixer" }; -static const struct soc_enum spkoutr_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(spkoutr_enum, + WM8962_SPEAKER_MIXER_2, 7, outmux_text); static const struct snd_kcontrol_new spkoutr_mux = SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum); -static const struct soc_enum spkoutl_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(spkoutl_enum, + WM8962_SPEAKER_MIXER_1, 7, outmux_text); static const struct snd_kcontrol_new spkoutl_mux = SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum); -static const struct soc_enum hpoutr_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(hpoutr_enum, + WM8962_HEADPHONE_MIXER_2, 7, outmux_text); static const struct snd_kcontrol_new hpoutr_mux = SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum); -static const struct soc_enum hpoutl_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(hpoutl_enum, + WM8962_HEADPHONE_MIXER_1, 7, outmux_text); static const struct snd_kcontrol_new hpoutl_mux = SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum); -- cgit v1.2.1 From d7f31d3c898e3e621a34d5d64966f7b830df66f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:32:05 +0100 Subject: ASoC: wm8962: Replace codec->control_data with wm8962->regmap With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the wm8962 driver for this by using wm8962->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound/soc/codecs/wm8962.c') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 3924ee243745..6ff1ff83b4dd 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1479,7 +1479,9 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) { - return regcache_sync_region(codec->control_data, + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + return regcache_sync_region(wm8962->regmap, WM8962_HDBASS_AI_1, WM8962_MAX_REGISTER); } -- cgit v1.2.1