From 4adeb0ccf86a5af1825bbfe290dee9e60a5ab870 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 19 Jun 2014 09:32:05 +0300 Subject: [PATCH 01/11] ASoC: max98090: Fix missing free_irq max98090.c doesn't free the threaded interrupt it requests. This causes an oops when doing "cat /proc/interrupts" after snd-soc-max98090.ko is unloaded. Fix this by requesting the interrupt by using devm_request_threaded_irq(). Signed-off-by: Jarkko Nikula Cc: Stable # 3.10+ Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index f5fccc7a8e89..d97f1ce7ff7d 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2284,7 +2284,7 @@ static int max98090_probe(struct snd_soc_codec *codec) /* Register for interrupts */ dev_dbg(codec->dev, "irq = %d\n", max98090->irq); - ret = request_threaded_irq(max98090->irq, NULL, + ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL, max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "max98090_interrupt", codec); if (ret < 0) { From a5b37bf36f541dd06d876f9a3743abc224a25fd3 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Jun 2014 16:29:37 +0300 Subject: [PATCH 02/11] ASoC: Intel: byt-max98090: Move MICBIAS widget to supply of Headset Mic Move "MICBIAS" as a supply widget to "Headset Mic" instead of keeping it between input pin "IN34" and "Headset Mic". Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/byt-max98090.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index 5fc98c64a3f4..a3c5f02a60fc 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c @@ -39,8 +39,7 @@ static const struct snd_soc_dapm_widget byt_max98090_widgets[] = { static const struct snd_soc_dapm_route byt_max98090_audio_map[] = { {"IN34", NULL, "Headset Mic"}, - {"IN34", NULL, "MICBIAS"}, - {"MICBIAS", NULL, "Headset Mic"}, + {"Headset Mic", NULL, "MICBIAS"}, {"DMICL", NULL, "Int Mic"}, {"Headphone", NULL, "HPL"}, {"Headphone", NULL, "HPR"}, From 725a6dfd014d02b4ad1d00df364a6d4a15ff2ebb Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Jun 2014 16:29:38 +0300 Subject: [PATCH 03/11] ASoC: Intel: byt-max98090: Fix mic detect GPIO polarity Mic detect GPIO is active low when headset microphone is detected. Found both by debugging and checking the schematics. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/byt-max98090.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index a3c5f02a60fc..3d06440278ec 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c @@ -83,6 +83,7 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { { .name = "mic-gpio", .idx = 1, + .invert = 1, .report = SND_JACK_MICROPHONE | SND_JACK_LINEIN, .debounce_time = 200, }, From 6a0cdccad87a7032440f204c04a599e4bcc8656b Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Jun 2014 16:29:39 +0300 Subject: [PATCH 04/11] ASoC: Intel: byt-max98090: Do not report SND_JACK_LINEIN Headset jack has only mono microphone input. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/byt-max98090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index 3d06440278ec..165ab6d6c4a3 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c @@ -84,7 +84,7 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { .name = "mic-gpio", .idx = 1, .invert = 1, - .report = SND_JACK_MICROPHONE | SND_JACK_LINEIN, + .report = SND_JACK_MICROPHONE, .debounce_time = 200, }, }; From 24988992932612ba1c069ad597125dbce3e19621 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Jun 2014 16:29:40 +0300 Subject: [PATCH 05/11] ASoC: Intel: byt-max98090: Fix jack type in order to report correctly Pass actual jack type bitmask to snd_soc_jack_new() in order to report also microphone detections and not only headphone. While at it change also jack name and pass also SND_JACK_LINEOUT type. Reported-by: Jin Yao Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/byt-max98090.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index 165ab6d6c4a3..3e2e7152ae66 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c @@ -108,7 +108,8 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) } /* Enable jack detection */ - ret = snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, jack); + ret = snd_soc_jack_new(codec, "Headset", + SND_JACK_LINEOUT | SND_JACK_HEADSET, jack); if (ret) return ret; From ab6f7d0d932313cedfb1696e0536bdbe661cd9c9 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Jun 2014 16:29:42 +0300 Subject: [PATCH 06/11] ASoC: Intel: byt-max98090: Do not enable MAX98090 microphone detection It turned out there is no need to enable microphone detection in MAX98090 codec. Headset microphone is anyway detected by a GPIO signal from another chip and headset button presses cannot be detected either because a signal needed for it is not connected. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/byt-max98090.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c index 3e2e7152ae66..5cfb41ec3fab 100644 --- a/sound/soc/intel/byt-max98090.c +++ b/sound/soc/intel/byt-max98090.c @@ -118,13 +118,9 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; - ret = snd_soc_jack_add_gpiods(card->dev->parent, jack, - ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); - if (ret) - return ret; - - return max98090_mic_detect(codec, jack); + return snd_soc_jack_add_gpiods(card->dev->parent, jack, + ARRAY_SIZE(hs_jack_gpios), + hs_jack_gpios); } static struct snd_soc_dai_link byt_max98090_dais[] = { From 001eaa25ca8cf4bfdb76fa8f2287b8d34287b9b6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 30 Jun 2014 10:01:37 +0200 Subject: [PATCH 07/11] ASoC: s6000-i2s: Fix s6000_i2s_remove() return type The platform_driver remove callback return type is int not void. Fixes the following warning: sound/soc/s6000/s6000-i2s.c:604:19: warning: incorrect type in initializer (different base types) sound/soc/s6000/s6000-i2s.c:604:19: expected int ( *remove )( ... ) sound/soc/s6000/s6000-i2s.c:604:19: got void ( static [toplevel] *)( ... ) Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/s6000/s6000-i2s.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c index 7eba7979b9af..1c8d01166e5b 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c @@ -570,7 +570,7 @@ err_release_none: return ret; } -static void s6000_i2s_remove(struct platform_device *pdev) +static int s6000_i2s_remove(struct platform_device *pdev) { struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev); struct resource *region; @@ -597,6 +597,8 @@ static void s6000_i2s_remove(struct platform_device *pdev) iounmap(mmio); region = platform_get_resource(pdev, IORESOURCE_IO, 0); release_mem_region(region->start, resource_size(region)); + + return 0; } static struct platform_driver s6000_i2s_driver = { From 8e89761876611f06ef4be865b4780b4361caf4af Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Mon, 14 Jul 2014 17:37:36 +0800 Subject: [PATCH 08/11] ASoC: Intel: Cleanup HSW pcm format support This change removes unsupported formats from System, Capture and Loopback FE DAIs. Also it fixes S24_LE support on all DAIs. While at this fix 24 bit flag for BYT as well. Signed-off-by: Jie Yang Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/intel/sst-baytrail-pcm.c | 2 +- sound/soc/intel/sst-haswell-pcm.c | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c index 8eab97368ea7..599401c0c655 100644 --- a/sound/soc/intel/sst-baytrail-pcm.c +++ b/sound/soc/intel/sst-baytrail-pcm.c @@ -32,7 +32,7 @@ static const struct snd_pcm_hardware sst_byt_pcm_hardware = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FORMAT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE, .period_bytes_min = 384, .period_bytes_max = 48000, .periods_min = 2, diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 058efb17c568..61bf6da4bb02 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -80,7 +80,7 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE | + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, .period_bytes_min = PAGE_SIZE, .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, @@ -400,7 +400,15 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); break; case SNDRV_PCM_FORMAT_S24_LE: - bits = SST_HSW_DEPTH_24BIT; + bits = SST_HSW_DEPTH_32BIT; + sst_hsw_stream_set_valid(hsw, pcm_data->stream, 24); + break; + case SNDRV_PCM_FORMAT_S8: + bits = SST_HSW_DEPTH_8BIT; + sst_hsw_stream_set_valid(hsw, pcm_data->stream, 8); + break; + case SNDRV_PCM_FORMAT_S32_LE: + bits = SST_HSW_DEPTH_32BIT; sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); break; default: @@ -685,8 +693,9 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) } #define HSW_FORMATS \ - (SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S32_LE) + (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S8) static struct snd_soc_dai_driver hsw_dais[] = { { @@ -696,7 +705,7 @@ static struct snd_soc_dai_driver hsw_dais[] = { .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, }, }, { @@ -727,8 +736,8 @@ static struct snd_soc_dai_driver hsw_dais[] = { .stream_name = "Loopback Capture", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = HSW_FORMATS, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, }, }, { @@ -737,8 +746,8 @@ static struct snd_soc_dai_driver hsw_dais[] = { .stream_name = "Analog Capture", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = HSW_FORMATS, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, }, }, }; From c761b58306b26ea78fa91488cbb04c61b35d583d Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Mon, 14 Jul 2014 17:11:11 +0800 Subject: [PATCH 09/11] ASoC: Intel: Add dummy read for SRAM block enable Add dummy read after each block enable, to workaround SRAM write missing bytes issue. Signed-off-by: Jie Yang Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-dsp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index 535f517629fd..a33b931181dc 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c @@ -359,6 +359,17 @@ static u32 hsw_block_get_bit(struct sst_mem_block *block) return bit; } +/*dummy read a SRAM block.*/ +static void sst_mem_block_dummy_read(struct sst_mem_block *block) +{ + u32 size; + u8 tmp_buf[4]; + struct sst_dsp *sst = block->dsp; + + size = block->size > 4 ? 4 : block->size; + memcpy_fromio(tmp_buf, sst->addr.lpe + block->offset, size); +} + /* enable 32kB memory block - locks held by caller */ static int hsw_block_enable(struct sst_mem_block *block) { @@ -378,6 +389,8 @@ static int hsw_block_enable(struct sst_mem_block *block) /* wait 18 DSP clock ticks */ udelay(10); + /*add a dummy read before the SRAM block is written, otherwise the writing may miss bytes sometimes.*/ + sst_mem_block_dummy_read(block); return 0; } From eff952b733d4c1ff3a6b35accce940b223372978 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 17 Jul 2014 21:21:37 +0800 Subject: [PATCH 10/11] ASoC: fsl_sai: Reset FIFOs after disabling TE/RE SAI will not clear their FIFOs after disabling TE/RE. Therfore, the driver should take care the task so as not to let useless data remain in the FIFO. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index c5a0e8af8226..b10dbd835d5c 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -371,10 +371,13 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, /* Check if the opposite FRDE is also disabled */ if (!(tx ? rcsr & FSL_SAI_CSR_FRDE : tcsr & FSL_SAI_CSR_FRDE)) { + /* Disable both directions and reset their FIFOs */ regmap_update_bits(sai->regmap, FSL_SAI_TCSR, - FSL_SAI_CSR_TERE, 0); + FSL_SAI_CSR_TERE | FSL_SAI_CSR_FR, + FSL_SAI_CSR_FR); regmap_update_bits(sai->regmap, FSL_SAI_RCSR, - FSL_SAI_CSR_TERE, 0); + FSL_SAI_CSR_TERE | FSL_SAI_CSR_FR, + FSL_SAI_CSR_FR); } break; default: From 4800f88b615f194ae3c1577038a7ccd871c907c9 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 17 Jul 2014 21:21:38 +0800 Subject: [PATCH 11/11] ASoC: fsl_sai: Fix incorrect register writing in fsl_sai_isr() In the rx irq handling part, we should clear the flags in RCSR not TCSR. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index b10dbd835d5c..1b6ee2ce849f 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -106,7 +106,7 @@ irq_rx: xcsr &= ~FSL_SAI_CSR_xF_MASK; if (flags) - regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr); + regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr); out: if (irq_none)