Commit 81054b226b76145628670a962674ab312690ab86

Authored by Peter Ujfalusi
Committed by Mark Brown
1 parent 623766318a

ASoC: omap-mcpdm: Fix for full duplex audio use case

Due to HW limitation within OMAP McPDM IP uplink and downlink need to be
started at the same time. This causes issues when we have two streams
running, for example:
arecord | aplay

In this case the playback stream would have no channels enabled since at the
capture start we are not aware that a playback is going to start.

The workaround is to configure the other direction to stereo when the first
stream is started. When the second stream is coming we check the new stream's
number of channels against the pre-configured channels. If it does not match
we stop and restart McPDM to update the configuration. This might result a
small pop. If the coming stream is a match we do nothing in the McPDM driver.

This workaround can handle most use cases without the need to restart McPDM.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 1 changed file with 26 additions and 1 deletions Side-by-side Diff

sound/soc/omap/omap-mcpdm.c
... ... @@ -63,6 +63,9 @@
63 63  
64 64 /* McPDM dn offsets for rx1, and 2 channels */
65 65 u32 dn_rx_offset;
  66 +
  67 + /* McPDM needs to be restarted due to runtime reconfiguration */
  68 + bool restart;
66 69 };
67 70  
68 71 /*
... ... @@ -149,7 +152,7 @@
149 152 static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
150 153 {
151 154 u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
152   - u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask;
  155 + u32 link_mask = MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK;
153 156  
154 157 ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
155 158 omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
... ... @@ -287,6 +290,8 @@
287 290 if (omap_mcpdm_active(mcpdm)) {
288 291 omap_mcpdm_stop(mcpdm);
289 292 omap_mcpdm_close_streams(mcpdm);
  293 + mcpdm->config[0].link_mask = 0;
  294 + mcpdm->config[1].link_mask = 0;
290 295 }
291 296 }
292 297  
293 298  
294 299  
... ... @@ -334,11 +339,26 @@
334 339 /* Configure McPDM channels, and DMA packet size */
335 340 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
336 341 link_mask <<= 3;
  342 +
  343 + /* If capture is not running assume a stereo stream to come */
  344 + if (!mcpdm->config[!stream].link_mask)
  345 + mcpdm->config[!stream].link_mask = 0x3;
  346 +
337 347 dma_data->packet_size =
338 348 (MCPDM_DN_THRES_MAX - threshold) * channels;
339 349 } else {
  350 + /* If playback is not running assume a stereo stream to come */
  351 + if (!mcpdm->config[!stream].link_mask)
  352 + mcpdm->config[!stream].link_mask = (0x3 << 3);
  353 +
340 354 dma_data->packet_size = threshold * channels;
341 355 }
  356 +
  357 + /* Check if we need to restart McPDM with this stream */
  358 + if (mcpdm->config[stream].link_mask &&
  359 + mcpdm->config[stream].link_mask != link_mask)
  360 + mcpdm->restart = true;
  361 +
342 362 mcpdm->config[stream].link_mask = link_mask;
343 363  
344 364 return 0;
... ... @@ -351,6 +371,11 @@
351 371  
352 372 if (!omap_mcpdm_active(mcpdm)) {
353 373 omap_mcpdm_start(mcpdm);
  374 + omap_mcpdm_reg_dump(mcpdm);
  375 + } else if (mcpdm->restart) {
  376 + omap_mcpdm_stop(mcpdm);
  377 + omap_mcpdm_start(mcpdm);
  378 + mcpdm->restart = false;
354 379 omap_mcpdm_reg_dump(mcpdm);
355 380 }
356 381