lkml.org 
[lkml]   [2012]   [Mar]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 046/108] ASoC: pxa-ssp: atomically set stream active masks
    3.0-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Daniel Mack <zonque@gmail.com>

    commit 273b72c8ce6b28df6b49423d775c3e59072c73c5 upstream.

    PXA's SSP engine fails to take its current channel phase into account
    when enabling a stream while the engine is already running. This
    results in randomly swapped left/right channels on either the record
    or the playback side, depending on which one was enabled first.

    The following patch fixes this by factoring out the bit field
    modifications in question to a separate function that pauses the
    engine temporarily, modifies the bits and kicks it off again
    afterwards. Appearantly, a transition of SSCR0_SSE syncs both
    directions properly.

    The patch has been rolled out to quite a number of devices over the
    last weeks and seems to fix the issue reliably.

    Signed-off-by: Daniel Mack <zonque@gmail.com>
    Reported-and-tested-by: Sven Neumann <s.neumann@raumfeld.com>
    Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    sound/soc/pxa/pxa-ssp.c | 61 ++++++++++++++++++++++++++++--------------------
    1 file changed, 36 insertions(+), 25 deletions(-)

    --- a/sound/soc/pxa/pxa-ssp.c
    +++ b/sound/soc/pxa/pxa-ssp.c
    @@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_
    return 0;
    }

    +static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream,
    + struct ssp_device *ssp, int value)
    +{
    + uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
    + uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1);
    + uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP);
    + uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR);
    +
    + if (value && (sscr0 & SSCR0_SSE))
    + pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE);
    +
    + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    + if (value)
    + sscr1 |= SSCR1_TSRE;
    + else
    + sscr1 &= ~SSCR1_TSRE;
    + } else {
    + if (value)
    + sscr1 |= SSCR1_RSRE;
    + else
    + sscr1 &= ~SSCR1_RSRE;
    + }
    +
    + pxa_ssp_write_reg(ssp, SSCR1, sscr1);
    +
    + if (value) {
    + pxa_ssp_write_reg(ssp, SSSR, sssr);
    + pxa_ssp_write_reg(ssp, SSPSP, sspsp);
    + pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE);
    + }
    +}
    +
    static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
    struct snd_soc_dai *cpu_dai)
    {
    @@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pc
    pxa_ssp_enable(ssp);
    break;
    case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    - val = pxa_ssp_read_reg(ssp, SSCR1);
    - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    - val |= SSCR1_TSRE;
    - else
    - val |= SSCR1_RSRE;
    - pxa_ssp_write_reg(ssp, SSCR1, val);
    + pxa_ssp_set_running_bit(substream, ssp, 1);
    val = pxa_ssp_read_reg(ssp, SSSR);
    pxa_ssp_write_reg(ssp, SSSR, val);
    break;
    case SNDRV_PCM_TRIGGER_START:
    - val = pxa_ssp_read_reg(ssp, SSCR1);
    - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    - val |= SSCR1_TSRE;
    - else
    - val |= SSCR1_RSRE;
    - pxa_ssp_write_reg(ssp, SSCR1, val);
    - pxa_ssp_enable(ssp);
    + pxa_ssp_set_running_bit(substream, ssp, 1);
    break;
    case SNDRV_PCM_TRIGGER_STOP:
    - val = pxa_ssp_read_reg(ssp, SSCR1);
    - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    - val &= ~SSCR1_TSRE;
    - else
    - val &= ~SSCR1_RSRE;
    - pxa_ssp_write_reg(ssp, SSCR1, val);
    + pxa_ssp_set_running_bit(substream, ssp, 0);
    break;
    case SNDRV_PCM_TRIGGER_SUSPEND:
    pxa_ssp_disable(ssp);
    break;
    case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    - val = pxa_ssp_read_reg(ssp, SSCR1);
    - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    - val &= ~SSCR1_TSRE;
    - else
    - val &= ~SSCR1_RSRE;
    - pxa_ssp_write_reg(ssp, SSCR1, val);
    + pxa_ssp_set_running_bit(substream, ssp, 0);
    break;

    default:



    \
     
     \ /
      Last update: 2012-03-30 23:09    [W:0.023 / U:1.220 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site