From 6a9a440681f2170b9a07b1cf28c6aa7532c307c8 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 27 May 2017 15:50:44 +0800 Subject: [PATCH 1/7] ASoC: zx-i2s: fix harsh noise with 16-bit audio The audio parameter setup in zx_i2s_hw_params() works fine with 32-bit samples, but for 16-bit ones, all we can hear is harsh noises. As suggested by vendor driver code, DMA burst size and TS width should always be 32 bits, no matter audio sample is 16-bit or 32-bit. Follow the suggestion above to fix the harsh noise issue seen with 16-bit audio samples. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/zte/zx-i2s.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c index a865f37c2a56..a7f7a56e0a2d 100644 --- a/sound/soc/zte/zx-i2s.c +++ b/sound/soc/zte/zx-i2s.c @@ -226,11 +226,12 @@ static int zx_i2s_hw_params(struct snd_pcm_substream *substream, struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai); struct snd_dmaengine_dai_dma_data *dma_data; unsigned int lane, ch_num, len, ret = 0; + unsigned int ts_width = 32; unsigned long val; unsigned long chn_cfg; dma_data = snd_soc_dai_get_dma_data(socdai, substream); - dma_data->addr_width = params_width(params) >> 3; + dma_data->addr_width = ts_width >> 3; val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL); val &= ~(ZX_I2S_TIMING_TS_WIDTH_MASK | ZX_I2S_TIMING_DATA_SIZE_MASK | @@ -251,7 +252,7 @@ static int zx_i2s_hw_params(struct snd_pcm_substream *substream, dev_err(socdai->dev, "Unknown data format\n"); return -EINVAL; } - val |= ZX_I2S_TIMING_TS_WIDTH(len) | ZX_I2S_TIMING_DATA_SIZE(len); + val |= ZX_I2S_TIMING_TS_WIDTH(ts_width) | ZX_I2S_TIMING_DATA_SIZE(len); ch_num = params_channels(params); switch (ch_num) { From af2728e4deb9f08721374f3adc06b1d3e7d133ec Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Tue, 6 Jun 2017 14:59:54 +0800 Subject: [PATCH 2/7] ASoC: rt5663: Fix the IRQ issue The patch fixed the IRQ issue. Signed-off-by: Oder Chiou Signed-off-by: Mark Brown --- sound/soc/codecs/rt5663.c | 2 +- sound/soc/codecs/rt5663.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index a32508d7dcfd..8569e8c7d894 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -3141,7 +3141,7 @@ static int rt5663_i2c_probe(struct i2c_client *i2c, regmap_update_bits(rt5663->regmap, RT5663_DIG_MISC, RT5663_DIG_GATE_CTRL_MASK, RT5663_DIG_GATE_CTRL_EN); regmap_update_bits(rt5663->regmap, RT5663_AUTO_1MRC_CLK, - RT5663_IRQ_POW_SAV_MASK, RT5663_IRQ_POW_SAV_EN); + RT5663_IRQ_MANUAL_MASK, RT5663_IRQ_MANUAL_EN); regmap_update_bits(rt5663->regmap, RT5663_IRQ_1, RT5663_EN_IRQ_JD1_MASK, RT5663_EN_IRQ_JD1_EN); regmap_update_bits(rt5663->regmap, RT5663_GPIO_1, diff --git a/sound/soc/codecs/rt5663.h b/sound/soc/codecs/rt5663.h index d77fae619f2f..4621812c94d8 100644 --- a/sound/soc/codecs/rt5663.h +++ b/sound/soc/codecs/rt5663.h @@ -590,6 +590,10 @@ #define RT5663_IRQ_POW_SAV_JD1_SHIFT 14 #define RT5663_IRQ_POW_SAV_JD1_DIS (0x0 << 14) #define RT5663_IRQ_POW_SAV_JD1_EN (0x1 << 14) +#define RT5663_IRQ_MANUAL_MASK (0x1 << 8) +#define RT5663_IRQ_MANUAL_SHIFT 8 +#define RT5663_IRQ_MANUAL_DIS (0x0 << 8) +#define RT5663_IRQ_MANUAL_EN (0x1 << 8) /* IRQ Control 1 (0x00b6) */ #define RT5663_EN_CB_JD_MASK (0x1 << 3) From 17616ce62c84c94e9519574e9d2df6f20e80a285 Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Mon, 12 Jun 2017 11:02:17 +0800 Subject: [PATCH 3/7] ASoC: rt5663: Check the JD status in the resume function In the suspend, the IRQ function will not work in some machines. So the JD status should be checked in the resume function. Signed-off-by: Oder Chiou Signed-off-by: Mark Brown --- sound/soc/codecs/rt5663.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 8569e8c7d894..a33202affeb1 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -2847,6 +2847,8 @@ static int rt5663_resume(struct snd_soc_codec *codec) regcache_cache_only(rt5663->regmap, false); regcache_sync(rt5663->regmap); + rt5663_irq(0, rt5663); + return 0; } #else From 5894b91d1e700f38b4157df143be1502cf08daa8 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Fri, 9 Jun 2017 16:52:46 +0800 Subject: [PATCH 4/7] ASoC: rockchip: i2s: add a delay before i2s clear in order to guarantee i2s lrck signal integrity, when i2s stop, need at least one lrck cycle to ensure signal integrity. the max delay time is when lrck is 8khz, the delay time is 125us(1/8khz), using udelay(150) with a 25us margin. Signed-off-by: Sugar Zhang Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 974915cb4c4f..f54843342ee2 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -116,6 +116,7 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP); + udelay(150); regmap_update_bits(i2s->regmap, I2S_CLR, I2S_CLR_TXC | I2S_CLR_RXC, I2S_CLR_TXC | I2S_CLR_RXC); @@ -162,6 +163,7 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP); + udelay(150); regmap_update_bits(i2s->regmap, I2S_CLR, I2S_CLR_TXC | I2S_CLR_RXC, I2S_CLR_TXC | I2S_CLR_RXC); From a205c159f9e2db586a5ea475f4d22fa22e78fed8 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 17 Jun 2017 22:25:28 +0800 Subject: [PATCH 5/7] ASoC: zx-i2s: flip I2S master/slave mode The SND_SOC_DAIFMT_MASTER bits are defined to specify the master/slave mode for Codec, not I2S. So the I2S master/slave mode should be flipped according to SND_SOC_DAIFMT_MASTER bits. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/zte/zx-i2s.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c index a7f7a56e0a2d..8bbad1d72bc5 100644 --- a/sound/soc/zte/zx-i2s.c +++ b/sound/soc/zte/zx-i2s.c @@ -203,13 +203,15 @@ static int zx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - i2s->master = 1; - val |= ZX_I2S_TIMING_MAST; - break; - case SND_SOC_DAIFMT_CBS_CFS: + /* Codec is master, and I2S is slave. */ i2s->master = 0; val |= ZX_I2S_TIMING_SLAVE; break; + case SND_SOC_DAIFMT_CBS_CFS: + /* Codec is slave, and I2S is master. */ + i2s->master = 1; + val |= ZX_I2S_TIMING_MAST; + break; default: dev_err(cpu_dai->dev, "Unknown master/slave format\n"); return -EINVAL; From a6ff8ddcf3f38ec84337e5e7eb3e0e9a73754cf5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 28 Jun 2017 15:01:24 +0200 Subject: [PATCH 6/7] ASoC: rt5645: del btn_check_timer on remove The timer may still be running when rt5645_i2c_remove() gets called, call del_timer_sync() to make sure it is stopped. Signed-off-by: Hans de Goede Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 87844a45886a..206b41688d96 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3897,6 +3897,7 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) cancel_delayed_work_sync(&rt5645->jack_detect_work); cancel_delayed_work_sync(&rt5645->rcclock_work); + del_timer_sync(&rt5645->btn_check_timer); snd_soc_unregister_codec(&i2c->dev); regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); From 8e2d163b736e719ef850493ac7740a61d30b8f23 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 28 Jun 2017 15:38:00 +0800 Subject: [PATCH 7/7] ASoC: rt5670: fix wrong audio route When we select "IF1_ADC4" for IF1 ADC Muxes, it is actually connected to "TxDP_ADC" widget. This patch fixes the audio route and remove the unexisting "IF1_ADC4" widget. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index e27c5a4a0a15..d95d2e693dc6 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -1717,7 +1717,6 @@ static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = { SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), /* DSP */ SND_SOC_DAPM_PGA("TxDP_ADC", SND_SOC_NOPM, 0, 0, NULL, 0), @@ -2086,13 +2085,13 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { { "IF1 ADC1 IN1 Mux", "IF1_ADC3", "IF1_ADC3" }, { "IF1 ADC1 IN2 Mux", "IF1_ADC1_IN1", "IF1 ADC1 IN1 Mux" }, - { "IF1 ADC1 IN2 Mux", "IF1_ADC4", "IF1_ADC4" }, + { "IF1 ADC1 IN2 Mux", "IF1_ADC4", "TxDP_ADC" }, { "IF1 ADC2 IN Mux", "IF_ADC2", "IF_ADC2" }, { "IF1 ADC2 IN Mux", "VAD_ADC", "VAD_ADC" }, { "IF1 ADC2 IN1 Mux", "IF1_ADC2_IN", "IF1 ADC2 IN Mux" }, - { "IF1 ADC2 IN1 Mux", "IF1_ADC4", "IF1_ADC4" }, + { "IF1 ADC2 IN1 Mux", "IF1_ADC4", "TxDP_ADC" }, { "IF1_ADC1" , NULL, "IF1 ADC1 IN2 Mux" }, { "IF1_ADC2" , NULL, "IF1 ADC2 IN1 Mux" },