lkml.org 
[lkml]   [2018]   [Feb]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 55/88] ASoC: rockchip: i2s: fix playback after runtime resume
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

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

    From: John Keeping <john@metanate.com>

    commit c66234cfedfc3e6e3b62563a5f2c1562be09a35d upstream.

    When restoring registers during runtime resume, we must not write to
    I2S_TXDR which is the transmit FIFO as this queues up a sample to be
    output and pushes all of the output channels down by one.

    This can be demonstrated with the speaker-test utility:

    for i in a b c; do speaker-test -c 2 -s 1; done

    which should play a test through the left speaker three times but if the
    I2S hardware starts runtime suspended the first sample will be played
    through the right speaker.

    Fix this by marking I2S_TXDR as volatile (which also requires marking it
    as readble, even though it technically isn't). This seems to be the
    most robust fix, the alternative of giving I2S_TXDR a default value is
    more fragile since it does not prevent regcache writing to the register
    in all circumstances.

    While here, also fix the configuration of I2S_RXDR and I2S_FIFOLR; these
    are not writable so they do not suffer from the same problem as I2S_TXDR
    but reading from I2S_RXDR does suffer from a similar problem.

    Fixes: f0447f6cbb20 ("ASoC: rockchip: i2s: restore register during runtime_suspend/resume cycle", 2016-09-07)
    Signed-off-by: John Keeping <john@metanate.com>
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    sound/soc/rockchip/rockchip_i2s.c | 6 ++++++
    1 file changed, 6 insertions(+)

    --- a/sound/soc/rockchip/rockchip_i2s.c
    +++ b/sound/soc/rockchip/rockchip_i2s.c
    @@ -476,6 +476,7 @@ static bool rockchip_i2s_rd_reg(struct d
    case I2S_INTCR:
    case I2S_XFER:
    case I2S_CLR:
    + case I2S_TXDR:
    case I2S_RXDR:
    case I2S_FIFOLR:
    case I2S_INTSR:
    @@ -490,6 +491,9 @@ static bool rockchip_i2s_volatile_reg(st
    switch (reg) {
    case I2S_INTSR:
    case I2S_CLR:
    + case I2S_FIFOLR:
    + case I2S_TXDR:
    + case I2S_RXDR:
    return true;
    default:
    return false;
    @@ -499,6 +503,8 @@ static bool rockchip_i2s_volatile_reg(st
    static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)
    {
    switch (reg) {
    + case I2S_RXDR:
    + return true;
    default:
    return false;
    }

    \
     
     \ /
      Last update: 2018-02-15 19:15    [W:4.088 / U:0.180 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site