Skip to content

Commit d372016

Browse files
HiassofTpopcornmix
authored andcommitted
ASoC: bcm2835: fix hw_params error when device is in prepared state (#2345)
commit 8d5737a upstream. 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 <[email protected]>
1 parent 884c644 commit d372016

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

sound/soc/bcm/bcm2835-i2s.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct bcm2835_i2s_dev {
130130
struct regmap *i2s_regmap;
131131
struct clk *clk;
132132
bool clk_prepared;
133+
int clk_rate;
133134
};
134135

135136
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,
419420
}
420421

421422
/* Clock should only be set up here if CPU is clock master */
422-
if (bit_clock_master) {
423-
ret = clk_set_rate(dev->clk, bclk_rate);
424-
if (ret)
425-
return ret;
423+
if (bit_clock_master &&
424+
(!dev->clk_prepared || dev->clk_rate != bclk_rate)) {
425+
if (dev->clk_prepared)
426+
bcm2835_i2s_stop_clock(dev);
427+
428+
if (dev->clk_rate != bclk_rate) {
429+
ret = clk_set_rate(dev->clk, bclk_rate);
430+
if (ret)
431+
return ret;
432+
dev->clk_rate = bclk_rate;
433+
}
434+
435+
bcm2835_i2s_start_clock(dev);
426436
}
427437

428438
/* Setup the frame format */
@@ -618,8 +628,6 @@ static int bcm2835_i2s_prepare(struct snd_pcm_substream *substream,
618628
struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
619629
uint32_t cs_reg;
620630

621-
bcm2835_i2s_start_clock(dev);
622-
623631
/*
624632
* Clear both FIFOs if the one that should be started
625633
* is not empty at the moment. This should only happen

0 commit comments

Comments
 (0)