diff options
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.patch | 141 |
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 + |