lkml.org 
[lkml]   [2021]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 739/800] ASoC: atmel-i2s: Fix usage of capture and playback at the same time
    Date
    From: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>

    [ Upstream commit 3b7961a326f8a7e03f54a19f02fedae8d488b80f ]

    For both capture and playback streams to work at the same time, only the
    needed values from a register need to be updated. Also, clocks should be
    enabled only when the first stream is started and stopped when there is no
    running stream.

    Fixes: b543e467d1a9 ("ASoC: atmel-i2s: add driver for the new Atmel I2S controller")
    Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
    Link: https://lore.kernel.org/r/20210618150741.401739-2-codrin.ciubotariu@microchip.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    sound/soc/atmel/atmel-i2s.c | 34 ++++++++++++++++++++++++++--------
    1 file changed, 26 insertions(+), 8 deletions(-)

    diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
    index 48c158535ff6..e5c4625b7771 100644
    --- a/sound/soc/atmel/atmel-i2s.c
    +++ b/sound/soc/atmel/atmel-i2s.c
    @@ -200,6 +200,7 @@ struct atmel_i2s_dev {
    unsigned int fmt;
    const struct atmel_i2s_gck_param *gck_param;
    const struct atmel_i2s_caps *caps;
    + int clk_use_no;
    };

    static irqreturn_t atmel_i2s_interrupt(int irq, void *dev_id)
    @@ -321,9 +322,16 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
    {
    struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
    bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
    - unsigned int mr = 0;
    + unsigned int mr = 0, mr_mask;
    int ret;

    + mr_mask = ATMEL_I2SC_MR_FORMAT_MASK | ATMEL_I2SC_MR_MODE_MASK |
    + ATMEL_I2SC_MR_DATALENGTH_MASK;
    + if (is_playback)
    + mr_mask |= ATMEL_I2SC_MR_TXMONO;
    + else
    + mr_mask |= ATMEL_I2SC_MR_RXMONO;
    +
    switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    case SND_SOC_DAIFMT_I2S:
    mr |= ATMEL_I2SC_MR_FORMAT_I2S;
    @@ -402,7 +410,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
    return -EINVAL;
    }

    - return regmap_write(dev->regmap, ATMEL_I2SC_MR, mr);
    + return regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr);
    }

    static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
    @@ -495,18 +503,28 @@ static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
    is_master = (mr & ATMEL_I2SC_MR_MODE_MASK) == ATMEL_I2SC_MR_MODE_MASTER;

    /* If master starts, enable the audio clock. */
    - if (is_master && mck_enabled)
    - err = atmel_i2s_switch_mck_generator(dev, true);
    - if (err)
    - return err;
    + if (is_master && mck_enabled) {
    + if (!dev->clk_use_no) {
    + err = atmel_i2s_switch_mck_generator(dev, true);
    + if (err)
    + return err;
    + }
    + dev->clk_use_no++;
    + }

    err = regmap_write(dev->regmap, ATMEL_I2SC_CR, cr);
    if (err)
    return err;

    /* If master stops, disable the audio clock. */
    - if (is_master && !mck_enabled)
    - err = atmel_i2s_switch_mck_generator(dev, false);
    + if (is_master && !mck_enabled) {
    + if (dev->clk_use_no == 1) {
    + err = atmel_i2s_switch_mck_generator(dev, false);
    + if (err)
    + return err;
    + }
    + dev->clk_use_no--;
    + }

    return err;
    }
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-12 11:04    [W:4.031 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site