提交 0032e9db 编写于 作者: M Maruthi Srinivas Bayyavarapu 提交者: 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: NMaruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Reviewed-by: NAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: NAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: NMark Brown <broonie@kernel.org>
上级 e164835a
......@@ -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);
......@@ -431,6 +442,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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册