If bcm2835 is configured as bitclock master calling hw_params() after prepare() fails with EBUSY. This also makes it impossible to use bcm2835 in full duplex mode.
The error is caused by the split clock setup: clk_set_rate is called in hw_params, clk_prepare_enable in prepare. As hw_params doesn't check if the clock was already enabled clk_set_rate fails with EBUSY.
Fix this by moving clock startup from prepare to hw_params and let hw_params properly deal with an already set up or enabled clock.
Signed-off-by: Matthias Reichl hias@horus.com --- sound/soc/bcm/bcm2835-i2s.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index 2e449d7173fc..d5f73a8ab893 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -130,6 +130,7 @@ struct bcm2835_i2s_dev { struct regmap *i2s_regmap; struct clk *clk; bool clk_prepared; + int clk_rate; };
static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) @@ -419,10 +420,19 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, }
/* Clock should only be set up here if CPU is clock master */ - if (bit_clock_master) { - ret = clk_set_rate(dev->clk, bclk_rate); - if (ret) - return ret; + if (bit_clock_master && + (!dev->clk_prepared || dev->clk_rate != bclk_rate)) { + if (dev->clk_prepared) + bcm2835_i2s_stop_clock(dev); + + if (dev->clk_rate != bclk_rate) { + ret = clk_set_rate(dev->clk, bclk_rate); + if (ret) + return ret; + dev->clk_rate = bclk_rate; + } + + bcm2835_i2s_start_clock(dev); }
/* Setup the frame format */ @@ -618,8 +628,6 @@ static int bcm2835_i2s_prepare(struct snd_pcm_substream *substream, struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); uint32_t cs_reg;
- bcm2835_i2s_start_clock(dev); - /* * Clear both FIFOs if the one that should be started * is not empty at the moment. This should only happen