aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amdfalconx86/recipes-kernel/linux/files/1134-ASoC-dwc-reconfigure-dwc-in-resume-from-suspend.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/files/1134-ASoC-dwc-reconfigure-dwc-in-resume-from-suspend.patch')
-rw-r--r--meta-amdfalconx86/recipes-kernel/linux/files/1134-ASoC-dwc-reconfigure-dwc-in-resume-from-suspend.patch141
1 files changed, 141 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/files/1134-ASoC-dwc-reconfigure-dwc-in-resume-from-suspend.patch b/meta-amdfalconx86/recipes-kernel/linux/files/1134-ASoC-dwc-reconfigure-dwc-in-resume-from-suspend.patch
new file mode 100644
index 00000000..4ed5331c
--- /dev/null
+++ b/meta-amdfalconx86/recipes-kernel/linux/files/1134-ASoC-dwc-reconfigure-dwc-in-resume-from-suspend.patch
@@ -0,0 +1,141 @@
+From ae2005698a4268461512386e741b489254e46915 Mon Sep 17 00:00:00 2001
+From: Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com>
+Date: Mon, 23 Nov 2015 20:08:21 +0530
+Subject: [PATCH 09/17] ASoC: dwc: reconfigure dwc in 'resume' from 'suspend'
+
+DWC IP can be powered off during system suspend in some platforms.
+After system is resumed, dwc needs to be programmed again to continue
+audio use case.
+
+Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Kalyan Alle <kalyan.alle@amd.com>
+---
+ sound/soc/dwc/designware_i2s.c | 70 ++++++++++++++++++++++++++----------------
+ 1 file changed, 43 insertions(+), 27 deletions(-)
+
+diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
+index 4f8f074..4e40a44 100644
+--- a/sound/soc/dwc/designware_i2s.c
++++ b/sound/soc/dwc/designware_i2s.c
+@@ -98,6 +98,8 @@ struct dw_i2s_dev {
+ unsigned int i2s_reg_comp1;
+ unsigned int i2s_reg_comp2;
+ struct device *dev;
++ u32 ccr;
++ u32 xfer_resolution;
+
+ /* data related to DMA transfers b/w i2s and DMAC */
+ union dw_i2s_snd_dma_data play_dma_data;
+@@ -217,31 +219,58 @@ static int dw_i2s_startup(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
++static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
++{
++ u32 ch_reg, irq;
++ struct i2s_clk_config_data *config = &dev->config;
++
++
++ i2s_disable_channels(dev, stream);
++
++ for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
++ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ i2s_write_reg(dev->i2s_base, TCR(ch_reg),
++ dev->xfer_resolution);
++ i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
++ irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
++ i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
++ i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
++ } else {
++ i2s_write_reg(dev->i2s_base, RCR(ch_reg),
++ dev->xfer_resolution);
++ i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
++ irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
++ i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
++ i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
++ }
++
++ }
++}
++
+ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+ {
+ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+ struct i2s_clk_config_data *config = &dev->config;
+- u32 ccr, xfer_resolution, ch_reg, irq;
+ int ret;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ config->data_width = 16;
+- ccr = 0x00;
+- xfer_resolution = 0x02;
++ dev->ccr = 0x00;
++ dev->xfer_resolution = 0x02;
+ break;
+
+ case SNDRV_PCM_FORMAT_S24_LE:
+ config->data_width = 24;
+- ccr = 0x08;
+- xfer_resolution = 0x04;
++ dev->ccr = 0x08;
++ dev->xfer_resolution = 0x04;
+ break;
+
+ case SNDRV_PCM_FORMAT_S32_LE:
+ config->data_width = 32;
+- ccr = 0x10;
+- xfer_resolution = 0x05;
++ dev->ccr = 0x10;
++ dev->xfer_resolution = 0x05;
+ break;
+
+ default:
+@@ -262,27 +291,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
+ return -EINVAL;
+ }
+
+- i2s_disable_channels(dev, substream->stream);
++ dw_i2s_config(dev, substream->stream);
+
+- for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+- i2s_write_reg(dev->i2s_base, TCR(ch_reg),
+- xfer_resolution);
+- i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
+- irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
+- i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
+- i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
+- } else {
+- i2s_write_reg(dev->i2s_base, RCR(ch_reg),
+- xfer_resolution);
+- i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
+- irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
+- i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
+- i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
+- }
+- }
+-
+- i2s_write_reg(dev->i2s_base, CCR, ccr);
++ i2s_write_reg(dev->i2s_base, CCR, dev->ccr);
+
+ config->sample_rate = params_rate(params);
+
+@@ -414,6 +425,11 @@ static int dw_i2s_resume(struct snd_soc_dai *dai)
+
+ if (dev->capability & DW_I2S_MASTER)
+ clk_enable(dev->clk);
++
++ if (dai->playback_active)
++ dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK);
++ if (dai->capture_active)
++ dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE);
+ return 0;
+ }
+
+--
+2.7.4
+