All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] ASoC: adau17x1: Implemented safeload support
@ 2018-08-21 11:07 Robert Rosengren
  2018-08-21 11:21 ` Lars-Peter Clausen
  0 siblings, 1 reply; 2+ messages in thread
From: Robert Rosengren @ 2018-08-21 11:07 UTC (permalink / raw)
  To: Lars-Peter Clausen, Liam Girdwood, Mark Brown
  Cc: alsa-devel, Robert Rosengren, Danny Smith

From: Danny Smith <dannys@axis.com>

Safeload support has been implemented which is used
when updating for instance filter parameters using
alsa controls. Without safeload support audio can
become distorted during update.

Signed-off-by: Danny Smith <dannys@axis.com>
Signed-off-by: Robert Rosengren <robertr@axis.com>
---
 sound/soc/codecs/adau17x1.c | 77 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 75 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index 2f2afb4c0c88..3959e6ad113d 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -21,11 +21,18 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/regmap.h>
+#include <asm/unaligned.h>
 
 #include "sigmadsp.h"
 #include "adau17x1.h"
 #include "adau-utils.h"
 
+#define ADAU17X1_SAFELOAD_TARGET_ADDRESS 0x0006
+#define ADAU17X1_SAFELOAD_TRIGGER 0x0007
+#define ADAU17X1_SAFELOAD_DATA 0x0001
+#define ADAU17X1_SAFELOAD_DATA_SIZE 20
+#define ADAU17X1_WORD_SIZE 4
+
 static const char * const adau17x1_capture_mixer_boost_text[] = {
 	"Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3",
 };
@@ -328,6 +335,17 @@ static bool adau17x1_has_dsp(struct adau *adau)
 	}
 }
 
+static bool adau17x1_has_safeload(struct adau *adau)
+{
+	switch (adau->type) {
+	case ADAU1761:
+	case ADAU1781:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
 	int source, unsigned int freq_in, unsigned int freq_out)
 {
@@ -958,6 +976,56 @@ int adau17x1_resume(struct snd_soc_component *component)
 }
 EXPORT_SYMBOL_GPL(adau17x1_resume);
 
+static int adau17x1_safeload(struct sigmadsp *sigmadsp, unsigned int addr,
+	const uint8_t bytes[], size_t len)
+{
+	uint8_t buf[ADAU17X1_WORD_SIZE];
+	uint8_t data[ADAU17X1_SAFELOAD_DATA_SIZE];
+	unsigned int addr_offset;
+	unsigned int nbr_words;
+	int ret;
+
+	/* write data to safeload addresses. Check if len is not a multiple of
+	 * 4 bytes, if so we need to zero pad.
+	 */
+	nbr_words = len / ADAU17X1_WORD_SIZE;
+	if ((len - nbr_words * ADAU17X1_WORD_SIZE) == 0) {
+		ret = regmap_raw_write(sigmadsp->control_data,
+			ADAU17X1_SAFELOAD_DATA, bytes, len);
+	} else {
+		nbr_words++;
+		memset(data, 0, ADAU17X1_SAFELOAD_DATA_SIZE);
+		memcpy(data, bytes, len);
+		ret = regmap_raw_write(sigmadsp->control_data,
+			ADAU17X1_SAFELOAD_DATA, data,
+			nbr_words * ADAU17X1_WORD_SIZE);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	/* Write target address, target address is offset by 1 */
+	addr_offset = addr - 1;
+	put_unaligned_be32(addr_offset, buf);
+	ret = regmap_raw_write(sigmadsp->control_data,
+		ADAU17X1_SAFELOAD_TARGET_ADDRESS, buf, ADAU17X1_WORD_SIZE);
+	if (ret < 0)
+		return ret;
+
+	/* write nbr of words to trigger address */
+	put_unaligned_be32(nbr_words, buf);
+	ret = regmap_raw_write(sigmadsp->control_data,
+		ADAU17X1_SAFELOAD_TRIGGER, buf, ADAU17X1_WORD_SIZE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct sigmadsp_ops adau17x1_sigmadsp_ops = {
+	.safeload = adau17x1_safeload,
+};
+
 int adau17x1_probe(struct device *dev, struct regmap *regmap,
 	enum adau17x1_type type, void (*switch_mode)(struct device *dev),
 	const char *firmware_name)
@@ -1003,8 +1071,13 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
 	dev_set_drvdata(dev, adau);
 
 	if (firmware_name) {
-		adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, NULL,
-			firmware_name);
+		if (adau17x1_has_safeload(adau)) {
+			adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap,
+				&adau17x1_sigmadsp_ops, firmware_name);
+		} else {
+			adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap,
+				NULL, firmware_name);
+		}
 		if (IS_ERR(adau->sigmadsp)) {
 			dev_warn(dev, "Could not find firmware file: %ld\n",
 				PTR_ERR(adau->sigmadsp));
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v3] ASoC: adau17x1: Implemented safeload support
  2018-08-21 11:07 [PATCH v3] ASoC: adau17x1: Implemented safeload support Robert Rosengren
@ 2018-08-21 11:21 ` Lars-Peter Clausen
  0 siblings, 0 replies; 2+ messages in thread
From: Lars-Peter Clausen @ 2018-08-21 11:21 UTC (permalink / raw)
  To: Robert Rosengren, Liam Girdwood, Mark Brown
  Cc: alsa-devel, Robert Rosengren, Danny Smith

On 08/21/2018 01:07 PM, Robert Rosengren wrote:
> From: Danny Smith <dannys@axis.com>
> 
> Safeload support has been implemented which is used
> when updating for instance filter parameters using
> alsa controls. Without safeload support audio can
> become distorted during update.
> 
> Signed-off-by: Danny Smith <dannys@axis.com>
> Signed-off-by: Robert Rosengren <robertr@axis.com>

Thanks, looks very good.

Acked-by: Lars-Peter Clausen <lars@metafoo.de>


> ---
>  sound/soc/codecs/adau17x1.c | 77 +++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 75 insertions(+), 2 deletions(-)
> 
> diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
> index 2f2afb4c0c88..3959e6ad113d 100644
> --- a/sound/soc/codecs/adau17x1.c
> +++ b/sound/soc/codecs/adau17x1.c
> @@ -21,11 +21,18 @@
>  #include <linux/i2c.h>
>  #include <linux/spi/spi.h>
>  #include <linux/regmap.h>
> +#include <asm/unaligned.h>
>  
>  #include "sigmadsp.h"
>  #include "adau17x1.h"
>  #include "adau-utils.h"
>  
> +#define ADAU17X1_SAFELOAD_TARGET_ADDRESS 0x0006
> +#define ADAU17X1_SAFELOAD_TRIGGER 0x0007
> +#define ADAU17X1_SAFELOAD_DATA 0x0001
> +#define ADAU17X1_SAFELOAD_DATA_SIZE 20
> +#define ADAU17X1_WORD_SIZE 4
> +
>  static const char * const adau17x1_capture_mixer_boost_text[] = {
>  	"Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3",
>  };
> @@ -328,6 +335,17 @@ static bool adau17x1_has_dsp(struct adau *adau)
>  	}
>  }
>  
> +static bool adau17x1_has_safeload(struct adau *adau)
> +{
> +	switch (adau->type) {
> +	case ADAU1761:
> +	case ADAU1781:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
>  static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
>  	int source, unsigned int freq_in, unsigned int freq_out)
>  {
> @@ -958,6 +976,56 @@ int adau17x1_resume(struct snd_soc_component *component)
>  }
>  EXPORT_SYMBOL_GPL(adau17x1_resume);
>  
> +static int adau17x1_safeload(struct sigmadsp *sigmadsp, unsigned int addr,
> +	const uint8_t bytes[], size_t len)
> +{
> +	uint8_t buf[ADAU17X1_WORD_SIZE];
> +	uint8_t data[ADAU17X1_SAFELOAD_DATA_SIZE];
> +	unsigned int addr_offset;
> +	unsigned int nbr_words;
> +	int ret;
> +
> +	/* write data to safeload addresses. Check if len is not a multiple of
> +	 * 4 bytes, if so we need to zero pad.
> +	 */
> +	nbr_words = len / ADAU17X1_WORD_SIZE;
> +	if ((len - nbr_words * ADAU17X1_WORD_SIZE) == 0) {
> +		ret = regmap_raw_write(sigmadsp->control_data,
> +			ADAU17X1_SAFELOAD_DATA, bytes, len);
> +	} else {
> +		nbr_words++;
> +		memset(data, 0, ADAU17X1_SAFELOAD_DATA_SIZE);
> +		memcpy(data, bytes, len);
> +		ret = regmap_raw_write(sigmadsp->control_data,
> +			ADAU17X1_SAFELOAD_DATA, data,
> +			nbr_words * ADAU17X1_WORD_SIZE);
> +	}
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Write target address, target address is offset by 1 */
> +	addr_offset = addr - 1;
> +	put_unaligned_be32(addr_offset, buf);
> +	ret = regmap_raw_write(sigmadsp->control_data,
> +		ADAU17X1_SAFELOAD_TARGET_ADDRESS, buf, ADAU17X1_WORD_SIZE);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* write nbr of words to trigger address */
> +	put_unaligned_be32(nbr_words, buf);
> +	ret = regmap_raw_write(sigmadsp->control_data,
> +		ADAU17X1_SAFELOAD_TRIGGER, buf, ADAU17X1_WORD_SIZE);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static const struct sigmadsp_ops adau17x1_sigmadsp_ops = {
> +	.safeload = adau17x1_safeload,
> +};
> +
>  int adau17x1_probe(struct device *dev, struct regmap *regmap,
>  	enum adau17x1_type type, void (*switch_mode)(struct device *dev),
>  	const char *firmware_name)
> @@ -1003,8 +1071,13 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
>  	dev_set_drvdata(dev, adau);
>  
>  	if (firmware_name) {
> -		adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, NULL,
> -			firmware_name);
> +		if (adau17x1_has_safeload(adau)) {
> +			adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap,
> +				&adau17x1_sigmadsp_ops, firmware_name);
> +		} else {
> +			adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap,
> +				NULL, firmware_name);
> +		}
>  		if (IS_ERR(adau->sigmadsp)) {
>  			dev_warn(dev, "Could not find firmware file: %ld\n",
>  				PTR_ERR(adau->sigmadsp));
> 

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-08-21 11:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-08-21 11:07 [PATCH v3] ASoC: adau17x1: Implemented safeload support Robert Rosengren
2018-08-21 11:21 ` Lars-Peter Clausen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.