Date:2013-03-20 10:47:13 (11 years 9 days ago)
Author:Peter Ujfalusi
Commit:f57f34369b976ec22b1840e02ad6b64ee16e7c82
Message: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>
Files: sound/soc/omap/omap-mcpdm.c (5 diffs)

Change Details

sound/soc/omap/omap-mcpdm.c
6363
6464    /* McPDM dn offsets for rx1, and 2 channels */
6565    u32 dn_rx_offset;
66
67    /* McPDM needs to be restarted due to runtime reconfiguration */
68    bool restart;
6669};
6770
6871/*
...... 
149152static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
150153{
151154    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;
153156
154157    ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
155158    omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
...... 
287290        if (omap_mcpdm_active(mcpdm)) {
288291            omap_mcpdm_stop(mcpdm);
289292            omap_mcpdm_close_streams(mcpdm);
293            mcpdm->config[0].link_mask = 0;
294            mcpdm->config[1].link_mask = 0;
290295        }
291296    }
292297
...... 
334339    /* Configure McPDM channels, and DMA packet size */
335340    if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
336341        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
337347        dma_data->packet_size =
338348                (MCPDM_DN_THRES_MAX - threshold) * channels;
339349    } 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
340354        dma_data->packet_size = threshold * channels;
341355    }
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
342362    mcpdm->config[stream].link_mask = link_mask;
343363
344364    return 0;
...... 
352372    if (!omap_mcpdm_active(mcpdm)) {
353373        omap_mcpdm_start(mcpdm);
354374        omap_mcpdm_reg_dump(mcpdm);
375    } else if (mcpdm->restart) {
376        omap_mcpdm_stop(mcpdm);
377        omap_mcpdm_start(mcpdm);
378        mcpdm->restart = false;
379        omap_mcpdm_reg_dump(mcpdm);
355380    }
356381
357382    return 0;

Archive Download the corresponding diff file



interactive