Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Mark Brown <broonie@kernel.org>

authored by

Maruthi Srinivas Bayyavarapu and committed by
Mark Brown
0032e9db e164835a

+43 -27
+43 -27
sound/soc/dwc/designware_i2s.c
··· 98 98 unsigned int i2s_reg_comp1; 99 99 unsigned int i2s_reg_comp2; 100 100 struct device *dev; 101 + u32 ccr; 102 + u32 xfer_resolution; 101 103 102 104 /* data related to DMA transfers b/w i2s and DMAC */ 103 105 union dw_i2s_snd_dma_data play_dma_data; ··· 219 217 return 0; 220 218 } 221 219 220 + static void dw_i2s_config(struct dw_i2s_dev *dev, int stream) 221 + { 222 + u32 ch_reg, irq; 223 + struct i2s_clk_config_data *config = &dev->config; 224 + 225 + 226 + i2s_disable_channels(dev, stream); 227 + 228 + for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { 229 + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 230 + i2s_write_reg(dev->i2s_base, TCR(ch_reg), 231 + dev->xfer_resolution); 232 + i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); 233 + irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); 234 + i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); 235 + i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); 236 + } else { 237 + i2s_write_reg(dev->i2s_base, RCR(ch_reg), 238 + dev->xfer_resolution); 239 + i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); 240 + irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); 241 + i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); 242 + i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); 243 + } 244 + 245 + } 246 + } 247 + 222 248 static int dw_i2s_hw_params(struct snd_pcm_substream *substream, 223 249 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 224 250 { 225 251 struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); 226 252 struct i2s_clk_config_data *config = &dev->config; 227 - u32 ccr, xfer_resolution, ch_reg, irq; 228 253 int ret; 229 254 230 255 switch (params_format(params)) { 231 256 case SNDRV_PCM_FORMAT_S16_LE: 232 257 config->data_width = 16; 233 - ccr = 0x00; 234 - xfer_resolution = 0x02; 258 + dev->ccr = 0x00; 259 + dev->xfer_resolution = 0x02; 235 260 break; 236 261 237 262 case SNDRV_PCM_FORMAT_S24_LE: 238 263 config->data_width = 24; 239 - ccr = 0x08; 240 - xfer_resolution = 0x04; 264 + dev->ccr = 0x08; 265 + dev->xfer_resolution = 0x04; 241 266 break; 242 267 243 268 case SNDRV_PCM_FORMAT_S32_LE: 244 269 config->data_width = 32; 245 - ccr = 0x10; 246 - xfer_resolution = 0x05; 270 + dev->ccr = 0x10; 271 + dev->xfer_resolution = 0x05; 247 272 break; 248 273 249 274 default: ··· 291 262 return -EINVAL; 292 263 } 293 264 294 - i2s_disable_channels(dev, substream->stream); 265 + dw_i2s_config(dev, substream->stream); 295 266 296 - for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { 297 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 298 - i2s_write_reg(dev->i2s_base, TCR(ch_reg), 299 - xfer_resolution); 300 - i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); 301 - irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); 302 - i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); 303 - i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); 304 - } else { 305 - i2s_write_reg(dev->i2s_base, RCR(ch_reg), 306 - xfer_resolution); 307 - i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); 308 - irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); 309 - i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); 310 - i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); 311 - } 312 - } 313 - 314 - i2s_write_reg(dev->i2s_base, CCR, ccr); 267 + i2s_write_reg(dev->i2s_base, CCR, dev->ccr); 315 268 316 269 config->sample_rate = params_rate(params); 317 270 ··· 442 431 443 432 if (dev->capability & DW_I2S_MASTER) 444 433 clk_enable(dev->clk); 434 + 435 + if (dai->playback_active) 436 + dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK); 437 + if (dai->capture_active) 438 + dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE); 445 439 return 0; 446 440 } 447 441