Commit 0032e9db authored by Maruthi Srinivas Bayyavarapu's avatar Maruthi Srinivas Bayyavarapu Committed by Mark Brown

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: default avatarMaruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent e164835a
...@@ -98,6 +98,8 @@ struct dw_i2s_dev { ...@@ -98,6 +98,8 @@ struct dw_i2s_dev {
unsigned int i2s_reg_comp1; unsigned int i2s_reg_comp1;
unsigned int i2s_reg_comp2; unsigned int i2s_reg_comp2;
struct device *dev; struct device *dev;
u32 ccr;
u32 xfer_resolution;
/* data related to DMA transfers b/w i2s and DMAC */ /* data related to DMA transfers b/w i2s and DMAC */
union dw_i2s_snd_dma_data play_dma_data; union dw_i2s_snd_dma_data play_dma_data;
...@@ -217,31 +219,58 @@ static int dw_i2s_startup(struct snd_pcm_substream *substream, ...@@ -217,31 +219,58 @@ static int dw_i2s_startup(struct snd_pcm_substream *substream,
return 0; 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, static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{ {
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
struct i2s_clk_config_data *config = &dev->config; struct i2s_clk_config_data *config = &dev->config;
u32 ccr, xfer_resolution, ch_reg, irq;
int ret; int ret;
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE: case SNDRV_PCM_FORMAT_S16_LE:
config->data_width = 16; config->data_width = 16;
ccr = 0x00; dev->ccr = 0x00;
xfer_resolution = 0x02; dev->xfer_resolution = 0x02;
break; break;
case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_LE:
config->data_width = 24; config->data_width = 24;
ccr = 0x08; dev->ccr = 0x08;
xfer_resolution = 0x04; dev->xfer_resolution = 0x04;
break; break;
case SNDRV_PCM_FORMAT_S32_LE: case SNDRV_PCM_FORMAT_S32_LE:
config->data_width = 32; config->data_width = 32;
ccr = 0x10; dev->ccr = 0x10;
xfer_resolution = 0x05; dev->xfer_resolution = 0x05;
break; break;
default: default:
...@@ -262,27 +291,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -262,27 +291,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; 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++) { i2s_write_reg(dev->i2s_base, CCR, dev->ccr);
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);
config->sample_rate = params_rate(params); config->sample_rate = params_rate(params);
...@@ -431,6 +442,11 @@ static int dw_i2s_resume(struct snd_soc_dai *dai) ...@@ -431,6 +442,11 @@ static int dw_i2s_resume(struct snd_soc_dai *dai)
if (dev->capability & DW_I2S_MASTER) if (dev->capability & DW_I2S_MASTER)
clk_enable(dev->clk); 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment