diff options
| author | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
|---|---|---|
| committer | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
| commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
| tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /sound/soc/intel/common/sst-dsp.c | |
| parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
| parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) | |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'sound/soc/intel/common/sst-dsp.c')
| -rw-r--r-- | sound/soc/intel/common/sst-dsp.c | 71 | 
1 files changed, 71 insertions, 0 deletions
diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c index 64e94212d2d2..a627236dd1f5 100644 --- a/sound/soc/intel/common/sst-dsp.c +++ b/sound/soc/intel/common/sst-dsp.c @@ -20,6 +20,7 @@  #include <linux/module.h>  #include <linux/platform_device.h>  #include <linux/io.h> +#include <linux/delay.h>  #include "sst-dsp.h"  #include "sst-dsp-priv.h" @@ -196,6 +197,22 @@ int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset,  }  EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked); +/* This is for registers bits with attribute RWC */ +void sst_dsp_shim_update_bits_forced_unlocked(struct sst_dsp *sst, u32 offset, +				u32 mask, u32 value) +{ +	unsigned int old, new; +	u32 ret; + +	ret = sst_dsp_shim_read_unlocked(sst, offset); + +	old = ret; +	new = (old & (~mask)) | (value & mask); + +	sst_dsp_shim_write_unlocked(sst, offset, new); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced_unlocked); +  int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset,  				u32 mask, u32 value)  { @@ -222,6 +239,60 @@ int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset,  }  EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); +/* This is for registers bits with attribute RWC */ +void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset, +				u32 mask, u32 value) +{ +	unsigned long flags; + +	spin_lock_irqsave(&sst->spinlock, flags); +	sst_dsp_shim_update_bits_forced_unlocked(sst, offset, mask, value); +	spin_unlock_irqrestore(&sst->spinlock, flags); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced); + +int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask, +			 u32 target, u32 timeout, char *operation) +{ +	int time, ret; +	u32 reg; +	bool done = false; + +	/* +	 * we will poll for couple of ms using mdelay, if not successful +	 * then go to longer sleep using usleep_range +	 */ + +	/* check if set state successful */ +	for (time = 0; time < 5; time++) { +		if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) { +			done = true; +			break; +		} +		mdelay(1); +	} + +	if (done ==  false) { +		/* sleeping in 10ms steps so adjust timeout value */ +		timeout /= 10; + +		for (time = 0; time < timeout; time++) { +			if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) +				break; + +			usleep_range(5000, 10000); +		} +	} + +	reg = sst_dsp_shim_read_unlocked(ctx, offset); +	dev_info(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation, +			(time < timeout) ? "successful" : "timedout"); +	ret = time < timeout ? 0 : -ETIME; + +	return ret; +} +EXPORT_SYMBOL_GPL(sst_dsp_register_poll); +  void sst_dsp_dump(struct sst_dsp *sst)  {  	if (sst->ops->dump)  |