mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			74 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From e4de6853a08fdb76e880084ab311a06cd2c2d5e8 Mon Sep 17 00:00:00 2001
 | |
| From: Matthias Reichl <github@hias.horus.com>
 | |
| Date: Thu, 18 Jan 2018 12:36:44 +0100
 | |
| Subject: [PATCH 180/277] ASoC: bcm2835: fix hw_params error when device is in
 | |
|  prepared state (#2345)
 | |
| 
 | |
| commit 8d5737a5f53902a916ee1e1cb248c9b8b883b2ea  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 <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
 | |
| -- 
 | |
| 2.16.1
 | |
| 
 |