From a00cebf51d5ceed8ba9f6fac5fb189b38cd5a7c2 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 31 May 2017 14:32:33 +0200 Subject: ASoC: atmel: tse850: fix off-by-one in the "ANA" enumeration count At some point I added the "Low" entry at the beginning of the array without bumping the enumeration count from 9 to 10. Fix this. While at it, fix the anti-pattern for the other enumeration (used by MUX{1,2}). Fixes: aa43112445f0 ("ASoC: atmel: tse850: add ASoC driver for the Axentia TSE-850") Signed-off-by: Peter Rosin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/atmel/tse850-pcm5142.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index a72c7d642026..3a1393283156 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -227,7 +227,7 @@ int tse850_put_ana(struct snd_kcontrol *kctrl, static const char * const mux_text[] = { "Mixer", "Loop" }; static const struct soc_enum mux_enum = - SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, mux_text); + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(mux_text), mux_text); static const struct snd_kcontrol_new mux1 = SOC_DAPM_ENUM_EXT("MUX1", mux_enum, tse850_get_mux1, tse850_put_mux1); @@ -252,7 +252,7 @@ static const char * const ana_text[] = { }; static const struct soc_enum ana_enum = - SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 9, ana_text); + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(ana_text), ana_text); static const struct snd_kcontrol_new out = SOC_DAPM_ENUM_EXT("ANA", ana_enum, tse850_get_ana, tse850_put_ana); -- cgit v1.2.3 From dc43f46a9b6988a40d4e11d05b8107d4546c61b9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 31 May 2017 16:51:13 +0100 Subject: ASoC: cs35l35: Add additional delay for reset Very fast systems may violate the minimum constraints for time the reset line needs to remain low, or communicate with the device too soon after releasing the reset. Fix this by adding some delays in to allow the chip to properly reset, also factor out the reset into a function as it is likely it will be re-used in later additions to the driver. Signed-off-by: Charles Keepax Acked-by: Paul Handrigan Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l35.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index f8aef5869b03..5ff12e4116e5 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -162,6 +162,14 @@ static bool cs35l35_precious_register(struct device *dev, unsigned int reg) } } +static void cs35l35_reset(struct cs35l35_private *cs35l35) +{ + gpiod_set_value_cansleep(cs35l35->reset_gpio, 0); + usleep_range(2000, 2100); + gpiod_set_value_cansleep(cs35l35->reset_gpio, 1); + usleep_range(1000, 1100); +} + static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35) { int ret; @@ -1454,7 +1462,7 @@ static int cs35l35_i2c_probe(struct i2c_client *i2c_client, } } - gpiod_set_value_cansleep(cs35l35->reset_gpio, 1); + cs35l35_reset(cs35l35); init_completion(&cs35l35->pdn_done); -- cgit v1.2.3 From b5f2a487f524e6eeeec38651e7b58760ebfd843e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 9 Jun 2017 15:01:21 +0800 Subject: ASoC: ak4613: Fix out of bounds array access for ak4613_iface Signed-off-by: Axel Lin Acked-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/ak4613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index b2dfddead227..987918628d5b 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -345,7 +345,7 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width)) iface = priv->iface; } else { - for (i = ARRAY_SIZE(ak4613_iface); i >= 0; i--) { + for (i = ARRAY_SIZE(ak4613_iface) - 1; i >= 0; i--) { if (!ak4613_dai_fmt_matching(ak4613_iface + i, is_play, fmt, width)) -- cgit v1.2.3 From 2a0c2189d8170d52da64543cbf955f0908c15e70 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Mon, 19 Jun 2017 10:56:33 +0100 Subject: ASoC: da7219: Fix HP detection procedure for all MCLK frequencies Currently when HP detection procedure runs for certain MCLK frequencies, when PLL is bypassed, the procedure will incorrectly report Lineout instead of Headphones due to timing incosistencies. To avoid this problem, the PLL is temporarily enabled (if currently bypassed and MCLK present) to provide consistent timings for the procedure, regardless of MCLK frequency. Signed-off-by: Adam Thomson Acked-by: Sathyanarayana Nujella Signed-off-by: Mark Brown --- sound/soc/codecs/da7219-aad.c | 31 +++++++++++++++++++------ sound/soc/codecs/da7219.c | 53 +++++++++++++++++++++++++++++-------------- sound/soc/codecs/da7219.h | 5 +++- 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 6274d79c1353..1d1d10dd92ae 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -115,19 +115,21 @@ static void da7219_aad_hptest_work(struct work_struct *work) struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); u16 tonegen_freq_hptest; - u8 pll_srm_sts, gain_ramp_ctrl, accdet_cfg8; + u8 pll_srm_sts, pll_ctrl, gain_ramp_ctrl, accdet_cfg8; int report = 0, ret = 0; - /* Lock DAPM and any Kcontrols that are affected by this test */ + /* Lock DAPM, Kcontrols affected by this test and the PLL */ snd_soc_dapm_mutex_lock(dapm); - mutex_lock(&da7219->lock); + mutex_lock(&da7219->ctrl_lock); + mutex_lock(&da7219->pll_lock); /* Ensure MCLK is available for HP test procedure */ if (da7219->mclk) { ret = clk_prepare_enable(da7219->mclk); if (ret) { dev_err(codec->dev, "Failed to enable mclk - %d\n", ret); - mutex_unlock(&da7219->lock); + mutex_unlock(&da7219->pll_lock); + mutex_unlock(&da7219->ctrl_lock); snd_soc_dapm_mutex_unlock(dapm); return; } @@ -136,12 +138,21 @@ static void da7219_aad_hptest_work(struct work_struct *work) /* * If MCLK not present, then we're using the internal oscillator and * require different frequency settings to achieve the same result. + * + * If MCLK is present, but PLL is not enabled then we enable it here to + * ensure a consistent detection procedure. */ pll_srm_sts = snd_soc_read(codec, DA7219_PLL_SRM_STS); - if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) + if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) { tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); - else + + pll_ctrl = snd_soc_read(codec, DA7219_PLL_CTRL); + if ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS) + da7219_set_pll(codec, DA7219_SYSCLK_PLL, + DA7219_PLL_FREQ_OUT_98304); + } else { tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC); + } /* Ensure gain ramping at fastest rate */ gain_ramp_ctrl = snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL); @@ -302,11 +313,17 @@ static void da7219_aad_hptest_work(struct work_struct *work) snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, DA7219_HP_R_AMP_OE_MASK); + /* Restore PLL to previous configuration, if re-configured */ + if ((pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) && + ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS)) + da7219_set_pll(codec, DA7219_SYSCLK_MCLK, 0); + /* Remove MCLK, if previously enabled */ if (da7219->mclk) clk_disable_unprepare(da7219->mclk); - mutex_unlock(&da7219->lock); + mutex_unlock(&da7219->pll_lock); + mutex_unlock(&da7219->ctrl_lock); snd_soc_dapm_mutex_unlock(dapm); /* diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 99601627f83c..f71d72c22bfc 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -260,9 +260,9 @@ static int da7219_volsw_locked_get(struct snd_kcontrol *kcontrol, struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); int ret; - mutex_lock(&da7219->lock); + mutex_lock(&da7219->ctrl_lock); ret = snd_soc_get_volsw(kcontrol, ucontrol); - mutex_unlock(&da7219->lock); + mutex_unlock(&da7219->ctrl_lock); return ret; } @@ -274,9 +274,9 @@ static int da7219_volsw_locked_put(struct snd_kcontrol *kcontrol, struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); int ret; - mutex_lock(&da7219->lock); + mutex_lock(&da7219->ctrl_lock); ret = snd_soc_put_volsw(kcontrol, ucontrol); - mutex_unlock(&da7219->lock); + mutex_unlock(&da7219->ctrl_lock); return ret; } @@ -288,9 +288,9 @@ static int da7219_enum_locked_get(struct snd_kcontrol *kcontrol, struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); int ret; - mutex_lock(&da7219->lock); + mutex_lock(&da7219->ctrl_lock); ret = snd_soc_get_enum_double(kcontrol, ucontrol); - mutex_unlock(&da7219->lock); + mutex_unlock(&da7219->ctrl_lock); return ret; } @@ -302,9 +302,9 @@ static int da7219_enum_locked_put(struct snd_kcontrol *kcontrol, struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); int ret; - mutex_lock(&da7219->lock); + mutex_lock(&da7219->ctrl_lock); ret = snd_soc_put_enum_double(kcontrol, ucontrol); - mutex_unlock(&da7219->lock); + mutex_unlock(&da7219->ctrl_lock); return ret; } @@ -424,9 +424,9 @@ static int da7219_tonegen_freq_get(struct snd_kcontrol *kcontrol, u16 val; int ret; - mutex_lock(&da7219->lock); + mutex_lock(&da7219->ctrl_lock); ret = regmap_raw_read(da7219->regmap, reg, &val, sizeof(val)); - mutex_unlock(&da7219->lock); + mutex_unlock(&da7219->ctrl_lock); if (ret) return ret; @@ -458,9 +458,9 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol, */ val = cpu_to_le16(ucontrol->value.integer.value[0]); - mutex_lock(&da7219->lock); + mutex_lock(&da7219->ctrl_lock); ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val)); - mutex_unlock(&da7219->lock); + mutex_unlock(&da7219->ctrl_lock); return ret; } @@ -801,7 +801,7 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, ++i; msleep(50); } - } while ((i < DA7219_SRM_CHECK_RETRIES) && (!srm_lock)); + } while ((i < DA7219_SRM_CHECK_RETRIES) & (!srm_lock)); if (!srm_lock) dev_warn(codec->dev, "SRM failed to lock\n"); @@ -1129,6 +1129,8 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, return -EINVAL; } + mutex_lock(&da7219->pll_lock); + switch (clk_id) { case DA7219_CLKSRC_MCLK_SQR: snd_soc_update_bits(codec, DA7219_PLL_CTRL, @@ -1141,6 +1143,7 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, break; default: dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); + mutex_unlock(&da7219->pll_lock); return -EINVAL; } @@ -1152,19 +1155,20 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, if (ret) { dev_err(codec_dai->dev, "Failed to set clock rate %d\n", freq); + mutex_unlock(&da7219->pll_lock); return ret; } } da7219->mclk_rate = freq; + mutex_unlock(&da7219->pll_lock); + return 0; } -static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int fref, unsigned int fout) +int da7219_set_pll(struct snd_soc_codec *codec, int source, unsigned int fout) { - struct snd_soc_codec *codec = codec_dai->codec; struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); u8 pll_ctrl, indiv_bits, indiv; @@ -1237,6 +1241,20 @@ static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, return 0; } +static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, + int source, unsigned int fref, unsigned int fout) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + int ret; + + mutex_lock(&da7219->pll_lock); + ret = da7219_set_pll(codec, source, fout); + mutex_unlock(&da7219->pll_lock); + + return ret; +} + static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; @@ -1741,7 +1759,8 @@ static int da7219_probe(struct snd_soc_codec *codec) unsigned int rev; int ret; - mutex_init(&da7219->lock); + mutex_init(&da7219->ctrl_lock); + mutex_init(&da7219->pll_lock); /* Regulator configuration */ ret = da7219_handle_supplies(codec); diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index 6baba7455fa1..8d6c3c8c8026 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -810,7 +810,8 @@ struct da7219_priv { bool wakeup_source; struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; struct regmap *regmap; - struct mutex lock; + struct mutex ctrl_lock; + struct mutex pll_lock; struct clk *mclk; unsigned int mclk_rate; @@ -821,4 +822,6 @@ struct da7219_priv { u8 gain_ramp_ctrl; }; +int da7219_set_pll(struct snd_soc_codec *codec, int source, unsigned int fout); + #endif /* __DA7219_H */ -- cgit v1.2.3 From 01b8cedfd0422326caae308641dcadaa85e0ca72 Mon Sep 17 00:00:00 2001 From: Satish Babu Patakokila Date: Fri, 16 Jun 2017 17:33:40 -0700 Subject: ASoC: compress: Derive substream from stream based on direction Currently compress driver hardcodes direction as playback to get substream from the stream. This results in getting the incorrect substream for compressed capture usecase. To fix this, remove the hardcoding and derive substream based on the stream direction. Signed-off-by: Satish Babu Patakokila Signed-off-by: Banajit Goswami Acked-By: Vinod Koul Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/soc-compress.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index bfd71b873ca2..206f36bf43e8 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -81,7 +81,8 @@ out: static int soc_compr_open_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; + struct snd_pcm_substream *fe_substream = + fe->pcm->streams[cstream->direction].substream; struct snd_soc_platform *platform = fe->platform; struct snd_soc_dai *cpu_dai = fe->cpu_dai; struct snd_soc_dpcm *dpcm; @@ -467,7 +468,8 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, struct snd_compr_params *params) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; + struct snd_pcm_substream *fe_substream = + fe->pcm->streams[cstream->direction].substream; struct snd_soc_platform *platform = fe->platform; struct snd_soc_dai *cpu_dai = fe->cpu_dai; int ret = 0, stream; -- cgit v1.2.3